修复跳转到告知书问题
This commit is contained in:
parent
e392903194
commit
e602f4c9bc
@ -16,7 +16,7 @@ import XsPicker from "@/pages/base/components/XsPicker/index.vue"
|
||||
import { useDataStore } from "@/store/modules/data";
|
||||
import { useUserStore } from "@/store/modules/user";
|
||||
const { getGlobal } = useDataStore();
|
||||
const { checkXqk, checkJlb, setXsPickerInitialized } = useUserStore();
|
||||
const { checkXqk, checkJlb, checkJc, setXsPickerInitialized } = useUserStore();
|
||||
|
||||
const switchXs = (xs: any) => {
|
||||
// 设置学生选择器已初始化标记
|
||||
@ -26,6 +26,8 @@ const switchXs = (xs: any) => {
|
||||
checkXqk();
|
||||
} else if (getGlobal.type == 2) {
|
||||
checkJlb();
|
||||
} else if (getGlobal.type == 3) {
|
||||
checkJc();
|
||||
} else {
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,78 +1,75 @@
|
||||
# JC模块 - 就餐标准管理
|
||||
# 就餐模块业务逻辑调整说明
|
||||
|
||||
## 功能概述
|
||||
## 概述
|
||||
参照选课的处理和业务逻辑,对就餐相关的业务逻辑进行了调整,实现了统一的状态管理和页面跳转逻辑。
|
||||
|
||||
JC模块是用于管理学生就餐标准的前端模块,包含以下主要功能:
|
||||
## 主要调整
|
||||
|
||||
### 1. 就餐标准列表 (`/pages/base/jc/index.vue`)
|
||||
- 显示当前学期可用的就餐标准
|
||||
- 支持学生选择器切换不同学生
|
||||
- 展示就餐标准的基本信息(名称、价格、描述)
|
||||
### 1. useUserStore中的checkJc方法完善
|
||||
- **位置**: `src/store/modules/user.ts`
|
||||
- **功能**: 根据后端返回的type值进行页面跳转
|
||||
- **逻辑**:
|
||||
- `type = 1`: 未选择(返回可选标准列表)→ 跳转到报名页面 `/pages/base/jc/bm`
|
||||
- `type = 2`: 待支付 → 跳转到支付页面 `/pages/base/jc/pay/index`
|
||||
- `type = 3`: 已支付 → 跳转到已选择页面 `/pages/base/jc/index`
|
||||
|
||||
### 2. 就餐标准详情 (`/pages/base/jc/detail.vue`)
|
||||
- 显示就餐标准的详细信息
|
||||
- 包含标准描述、使用说明、注意事项等
|
||||
- 支持图片展示
|
||||
### 2. 页面整合
|
||||
- **删除页面**:
|
||||
- `detail.vue` - 就餐标准详情页面
|
||||
- `bm-detail.vue` - 报名详情页面
|
||||
- **整合到**: `index.vue` - 已选择就餐标准展示页面
|
||||
|
||||
### 3. 就餐标准报名 (`/pages/base/jc/bm.vue`)
|
||||
- 支持多选就餐标准
|
||||
- 实时计算总金额
|
||||
- 确认报名后跳转到支付页面
|
||||
### 3. index.vue页面重构
|
||||
- **功能**: 展示已选择的就餐标准信息
|
||||
- **包含内容**:
|
||||
- 就餐标准基本信息(名称、价格、描述、有效期)
|
||||
- 报名信息(报名时间、支付状态、订单号)
|
||||
- 使用说明
|
||||
- 注意事项
|
||||
- **状态处理**:
|
||||
- 有已选择标准:显示详细信息
|
||||
- 无已选择标准:显示空状态,提供"立即报名"按钮
|
||||
|
||||
### 4. 支付流程 (`/pages/base/jc/pay/`)
|
||||
- 支付页面 (`index.vue`):显示报名信息和支付倒计时
|
||||
- 支付等待页面 (`wait.vue`):处理支付回调
|
||||
- 支付成功页面 (`success.vue`):支付成功提示
|
||||
- 支付失败页面 (`fail.vue`):支付失败处理
|
||||
### 4. bm.vue页面调整
|
||||
- **跳转逻辑**: 已报名时跳转到 `index.vue` 而不是已删除的 `bm-detail.vue`
|
||||
|
||||
### 5. 就餐记录 (`/pages/base/jc/record.vue`)
|
||||
- 显示学生的就餐记录历史
|
||||
- 包含就餐日期、状态、地点等信息
|
||||
### 5. 后端接口对应
|
||||
- **接口**: `/mobile/jz/jc/getJcBzList`
|
||||
- **返回类型**: `AppJzXsJcVo`
|
||||
- **type字段含义**:
|
||||
- `1`: 未选择(返回可选标准列表)
|
||||
- `2`: 待支付
|
||||
- `3`: 已支付
|
||||
|
||||
## 组件结构
|
||||
## 页面跳转流程
|
||||
|
||||
### 核心组件
|
||||
- `JcBzList` (`/pages/base/components/JcBzList/index.vue`):就餐标准列表组件
|
||||
- `JcRecordList` (`/pages/base/components/JcRecordList/index.vue`):就餐记录列表组件
|
||||
### 通过launchPage的type=3进入
|
||||
1. **useUserStore.toHome(type=3)** → 调用checkJc()
|
||||
2. **checkJc()** → 调用后端接口获取就餐状态
|
||||
3. **根据返回的type值跳转**:
|
||||
- type=1 → `/pages/base/jc/bm` (报名页面)
|
||||
- type=2 → `/pages/base/jc/pay/index` (支付页面)
|
||||
- type=3 → `/pages/base/jc/index` (已选择页面)
|
||||
|
||||
### API接口
|
||||
所有JC相关的API接口都集中在 `jcApi.ts` 文件中,包括:
|
||||
- 获取就餐标准列表
|
||||
- 获取就餐标准详情
|
||||
- 学生报名就餐标准
|
||||
- 取消报名
|
||||
- 发起支付
|
||||
- 查询支付状态
|
||||
- 获取就餐记录等
|
||||
### 页面间跳转
|
||||
- **报名成功** → 跳转到支付页面
|
||||
- **支付成功** → 跳转到已选择页面
|
||||
- **查看详情** → 在已选择页面中展示完整信息
|
||||
|
||||
## 数据流
|
||||
## 技术实现
|
||||
|
||||
1. **报名流程**:
|
||||
- 学生选择就餐标准 → 确认报名 → 跳转支付页面 → 完成支付
|
||||
### 前端
|
||||
- **状态管理**: 使用Pinia store管理用户状态和就餐数据
|
||||
- **页面路由**: 使用uni.reLaunch进行页面跳转
|
||||
- **数据获取**: 通过API接口获取就餐状态和详情信息
|
||||
|
||||
2. **数据存储**:
|
||||
- 使用 Pinia store 管理状态
|
||||
- 本地存储保存选中状态
|
||||
- 支付数据通过 store 传递
|
||||
|
||||
## 技术特点
|
||||
|
||||
- 采用 Vue 3 Composition API
|
||||
- 使用 TypeScript 进行类型检查
|
||||
- 响应式设计,支持移动端
|
||||
- 模块化组件设计
|
||||
- 统一的错误处理机制
|
||||
### 后端
|
||||
- **状态检查**: 通过Redis缓存和数据库查询确定就餐状态
|
||||
- **类型定义**: 使用AppJzXsJcVo统一返回格式
|
||||
- **业务逻辑**: 参照选课模块的实现方式
|
||||
|
||||
## 注意事项
|
||||
|
||||
1. 支付倒计时功能需要后端提供倒计时接口
|
||||
2. 多选功能需要合理处理数据同步
|
||||
3. 支付状态查询需要定时轮询
|
||||
4. 图片资源需要正确的路径处理
|
||||
|
||||
## 扩展建议
|
||||
|
||||
1. 可以添加就餐标准筛选功能
|
||||
2. 支持按时间范围查询就餐记录
|
||||
3. 添加就餐统计功能
|
||||
4. 支持批量操作就餐标准
|
||||
1. 确保后端接口返回的type值与前端期望一致
|
||||
2. 页面跳转使用uni.reLaunch确保正确的页面栈管理
|
||||
3. 数据获取失败时使用备用方案(跳转到报名页面)
|
||||
4. 删除的页面文件已清理,避免引用错误
|
||||
@ -1,295 +0,0 @@
|
||||
<template>
|
||||
<view class="bm-detail-page">
|
||||
<!-- 页面头部 -->
|
||||
<view class="page-header">
|
||||
<view class="header-title">报名详情</view>
|
||||
</view>
|
||||
|
||||
<!-- 学生信息 -->
|
||||
<view class="info-card">
|
||||
<view class="card-title">学生信息</view>
|
||||
<view class="student-info">
|
||||
<view class="info-item">
|
||||
<text class="label">姓名:</text>
|
||||
<text class="value">{{ curXs.xm }}</text>
|
||||
</view>
|
||||
<view class="info-item">
|
||||
<text class="label">班级:</text>
|
||||
<text class="value">{{ curXs.bjmc }}</text>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<!-- 报名信息 -->
|
||||
<view class="info-card">
|
||||
<view class="card-title">报名信息</view>
|
||||
<view class="bm-info">
|
||||
<view class="info-item">
|
||||
<text class="label">报名时间:</text>
|
||||
<text class="value">{{ bmInfo.bmTime || '暂无' }}</text>
|
||||
</view>
|
||||
<view class="info-item">
|
||||
<text class="label">报名状态:</text>
|
||||
<text class="value status-success">已报名</text>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<!-- 就餐标准详情 -->
|
||||
<JcBzDetailCard
|
||||
v-if="bmJcBzList.length > 0"
|
||||
:jc-bz-list="bmJcBzList"
|
||||
title="已报名的就餐标准"
|
||||
:show-detail-btn="true"
|
||||
:show-summary="false"
|
||||
@detail="goToDetail"
|
||||
/>
|
||||
|
||||
<!-- 支付信息 -->
|
||||
<view class="info-card">
|
||||
<view class="card-title">支付信息</view>
|
||||
<view class="payment-info">
|
||||
<view class="info-item">
|
||||
<text class="label">缴费金额:</text>
|
||||
<text class="value total-price">¥{{ totalAmount }}</text>
|
||||
</view>
|
||||
<view class="info-item">
|
||||
<text class="label">支付状态:</text>
|
||||
<text class="value" :class="paymentStatusClass">{{ paymentStatusText }}</text>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<!-- 底部操作 -->
|
||||
<view class="bottom-actions">
|
||||
<view class="action-btn primary" @click="goToPay" v-if="paymentStatus === 'unpaid'">
|
||||
立即支付
|
||||
</view>
|
||||
<view class="action-btn secondary" @click="goBack">
|
||||
返回
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { ref, computed, onMounted } from "vue";
|
||||
import { useUserStore } from "@/store/modules/user";
|
||||
import { useDataStore } from "@/store/modules/data";
|
||||
import JcBzDetailCard from "@/pages/base/components/JcBzDetailCard/index.vue";
|
||||
import { jcGetXsBmJcBzListApi } from "@/api/base/jcApi";
|
||||
|
||||
const { getCurXs } = useUserStore();
|
||||
const { getData, setData } = useDataStore();
|
||||
|
||||
const curXs = computed(() => getCurXs);
|
||||
|
||||
// 报名信息
|
||||
const bmInfo = ref<any>({});
|
||||
// 已报名的就餐标准列表
|
||||
const bmJcBzList = ref<any[]>([]);
|
||||
// 支付状态
|
||||
const paymentStatus = ref<string>('unpaid'); // unpaid, paid, expired
|
||||
|
||||
// 计算总金额
|
||||
const totalAmount = computed(() => {
|
||||
let total = 0;
|
||||
bmJcBzList.value.forEach(jcBz => {
|
||||
total += jcBz.jfje || 0;
|
||||
});
|
||||
return total;
|
||||
});
|
||||
|
||||
// 支付状态样式
|
||||
const paymentStatusClass = computed(() => {
|
||||
switch (paymentStatus.value) {
|
||||
case 'paid':
|
||||
return 'status-success';
|
||||
case 'expired':
|
||||
return 'status-error';
|
||||
default:
|
||||
return 'status-warning';
|
||||
}
|
||||
});
|
||||
|
||||
// 支付状态文本
|
||||
const paymentStatusText = computed(() => {
|
||||
switch (paymentStatus.value) {
|
||||
case 'paid':
|
||||
return '已支付';
|
||||
case 'expired':
|
||||
return '已过期';
|
||||
default:
|
||||
return '待支付';
|
||||
}
|
||||
});
|
||||
|
||||
// 获取报名信息
|
||||
const getBmInfo = async () => {
|
||||
try {
|
||||
const res = await jcGetXsBmJcBzListApi({
|
||||
xsId: curXs.value.id
|
||||
});
|
||||
|
||||
if (res.resultCode === 1) {
|
||||
bmJcBzList.value = res.result || [];
|
||||
// 这里可以根据实际数据结构设置其他信息
|
||||
bmInfo.value = {
|
||||
bmTime: new Date().toLocaleString(),
|
||||
// 其他报名信息
|
||||
};
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('获取报名信息失败:', error);
|
||||
}
|
||||
};
|
||||
|
||||
// 跳转到详情页面
|
||||
const goToDetail = (jcBz: any) => {
|
||||
setData({
|
||||
...getData,
|
||||
jcBzData: jcBz
|
||||
});
|
||||
uni.navigateTo({
|
||||
url: '/pages/base/jc/detail'
|
||||
});
|
||||
};
|
||||
|
||||
// 跳转到支付页面
|
||||
const goToPay = () => {
|
||||
// 保存支付数据到store
|
||||
setData({
|
||||
...getData,
|
||||
xsId: curXs.value.id,
|
||||
jcBzIds: bmJcBzList.value.map(item => item.id),
|
||||
jcBzList: bmJcBzList.value,
|
||||
totalJe: totalAmount.value,
|
||||
});
|
||||
|
||||
uni.redirectTo({
|
||||
url: '/pages/base/jc/pay/index'
|
||||
});
|
||||
};
|
||||
|
||||
// 返回上一页
|
||||
const goBack = () => {
|
||||
uni.navigateBack();
|
||||
};
|
||||
|
||||
onMounted(() => {
|
||||
getBmInfo();
|
||||
});
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.bm-detail-page {
|
||||
min-height: 100vh;
|
||||
background-color: #f5f7fa;
|
||||
padding-bottom: 100px;
|
||||
}
|
||||
|
||||
.page-header {
|
||||
background: linear-gradient(135deg, #4a90e2, #2879ff);
|
||||
padding: 20px 15px;
|
||||
color: #fff;
|
||||
text-align: center;
|
||||
|
||||
.header-title {
|
||||
font-size: 18px;
|
||||
font-weight: bold;
|
||||
}
|
||||
}
|
||||
|
||||
.info-card {
|
||||
margin: 15px;
|
||||
background-color: #fff;
|
||||
border-radius: 8px;
|
||||
padding: 15px;
|
||||
box-shadow: 0 2px 6px rgba(0, 0, 0, 0.05);
|
||||
|
||||
.card-title {
|
||||
font-size: 16px;
|
||||
font-weight: bold;
|
||||
color: #333;
|
||||
margin-bottom: 15px;
|
||||
border-bottom: 1px solid #f0f0f0;
|
||||
padding-bottom: 10px;
|
||||
}
|
||||
|
||||
.student-info,
|
||||
.bm-info,
|
||||
.payment-info {
|
||||
.info-item {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
margin-bottom: 10px;
|
||||
|
||||
&:last-child {
|
||||
margin-bottom: 0;
|
||||
}
|
||||
|
||||
.label {
|
||||
font-size: 14px;
|
||||
color: #666;
|
||||
}
|
||||
|
||||
.value {
|
||||
font-size: 14px;
|
||||
color: #333;
|
||||
font-weight: 500;
|
||||
|
||||
&.total-price {
|
||||
color: #ff6b00;
|
||||
font-weight: bold;
|
||||
font-size: 16px;
|
||||
}
|
||||
|
||||
&.status-success {
|
||||
color: #52c41a;
|
||||
}
|
||||
|
||||
&.status-warning {
|
||||
color: #faad14;
|
||||
}
|
||||
|
||||
&.status-error {
|
||||
color: #ff4d4f;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.bottom-actions {
|
||||
position: fixed;
|
||||
bottom: 0;
|
||||
left: 0;
|
||||
right: 0;
|
||||
background-color: #fff;
|
||||
padding: 15px;
|
||||
box-shadow: 0 -2px 10px rgba(0, 0, 0, 0.05);
|
||||
display: flex;
|
||||
gap: 15px;
|
||||
|
||||
.action-btn {
|
||||
flex: 1;
|
||||
height: 44px;
|
||||
line-height: 44px;
|
||||
text-align: center;
|
||||
border-radius: 22px;
|
||||
font-size: 16px;
|
||||
|
||||
&.primary {
|
||||
background-color: #2879ff;
|
||||
color: #fff;
|
||||
}
|
||||
|
||||
&.secondary {
|
||||
background-color: #fff;
|
||||
color: #333;
|
||||
border: 1px solid #ddd;
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
@ -171,9 +171,9 @@ const confirmBm = async () => {
|
||||
content: '您已经报名了该就餐标准,是否查看报名详情?',
|
||||
success: (modalRes) => {
|
||||
if (modalRes.confirm) {
|
||||
// 跳转到报名详情页面
|
||||
// 跳转到已选择页面
|
||||
uni.redirectTo({
|
||||
url: '/pages/base/jc/bm-detail'
|
||||
url: '/pages/base/jc/index'
|
||||
});
|
||||
} else {
|
||||
// 返回上一页
|
||||
|
||||
@ -1,285 +0,0 @@
|
||||
<template>
|
||||
<BasicLayout>
|
||||
<view class="jc-detail">
|
||||
<!-- 就餐标准信息卡片 -->
|
||||
<view class="info-card">
|
||||
<view class="card-title">就餐标准信息</view>
|
||||
<view class="divider"></view>
|
||||
|
||||
<view class="jc-info">
|
||||
<image
|
||||
class="jc-image"
|
||||
:src="jcDetail.lxtp"
|
||||
mode="aspectFill"
|
||||
></image>
|
||||
|
||||
<view class="jc-content">
|
||||
<view class="jc-name">{{ jcDetail.bzmc }}</view>
|
||||
<view class="jc-price">
|
||||
价格:<text class="price-value">¥{{ jcDetail.jfje }}</text>
|
||||
</view>
|
||||
<view class="jc-desc">{{ jcDetail.bzms || '暂无描述' }}</view>
|
||||
<view class="jc-time">有效期:{{ jcDetail.yxq || '暂无有效期信息' }}</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<!-- 就餐标准详情 -->
|
||||
<view class="info-card">
|
||||
<view class="card-title">标准详情</view>
|
||||
<view class="divider"></view>
|
||||
|
||||
<view class="content-section">
|
||||
<text>{{ jcDetail.bzms || "暂无详细信息" }}</text>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<!-- 使用说明 -->
|
||||
<view class="info-card">
|
||||
<view class="card-title">使用说明</view>
|
||||
<view class="divider"></view>
|
||||
|
||||
<view class="content-section">
|
||||
<template v-if="usageInstructions && usageInstructions.length > 0">
|
||||
<view
|
||||
v-for="(instruction, index) in usageInstructions"
|
||||
:key="index"
|
||||
class="instruction-item"
|
||||
>
|
||||
<text>{{ instruction }}</text>
|
||||
</view>
|
||||
</template>
|
||||
<template v-else>
|
||||
<view class="empty-data">
|
||||
<u-icon name="info-circle" color="#C8C9CC" size="18"></u-icon>
|
||||
<text>暂无使用说明</text>
|
||||
</view>
|
||||
</template>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<!-- 注意事项 -->
|
||||
<view class="info-card">
|
||||
<view class="card-title">注意事项</view>
|
||||
<view class="divider"></view>
|
||||
|
||||
<view class="content-section">
|
||||
<template v-if="precautions && precautions.length > 0">
|
||||
<view
|
||||
v-for="(precaution, index) in precautions"
|
||||
:key="index"
|
||||
class="precaution-item"
|
||||
>
|
||||
<text>{{ precaution }}</text>
|
||||
</view>
|
||||
</template>
|
||||
<template v-else>
|
||||
<view class="empty-data">
|
||||
<u-icon name="info-circle" color="#C8C9CC" size="18"></u-icon>
|
||||
<text>暂无注意事项</text>
|
||||
</view>
|
||||
</template>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
<template #bottom>
|
||||
<view class="white-bg-color py-5">
|
||||
<view class="flex-row items-center pb-10 pt-5">
|
||||
<u-button
|
||||
text="返回"
|
||||
class="ml-15 mr-7"
|
||||
:plain="true"
|
||||
@click="navigateBack"
|
||||
/>
|
||||
</view>
|
||||
</view>
|
||||
</template>
|
||||
</BasicLayout>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { ref, onMounted, computed } from "vue";
|
||||
import { navigateBack } from "@/utils/uniapp";
|
||||
import { useDataStore } from "@/store/modules/data";
|
||||
import { storeToRefs } from "pinia";
|
||||
import { imagUrl } from "@/utils";
|
||||
import { jcGetJcBzDetailApi } from "@/api/base/jcApi";
|
||||
|
||||
// 定义就餐标准数据类型
|
||||
interface JcBzData {
|
||||
id?: string;
|
||||
bzmc?: string;
|
||||
jfje?: number;
|
||||
bzms?: string;
|
||||
yxq?: string;
|
||||
lxtp?: string;
|
||||
[key: string]: any; // 允许其他字段
|
||||
}
|
||||
|
||||
const useData = useDataStore();
|
||||
const { jcBzData } = storeToRefs(useData);
|
||||
|
||||
// 使用说明 - 从备注中解析
|
||||
const usageInstructions = ref<string[]>([]);
|
||||
|
||||
// 注意事项 - 从备注中解析
|
||||
const precautions = ref<string[]>([]);
|
||||
|
||||
const jcBzDetail = jcBzData.value as JcBzData;
|
||||
if (jcBzDetail && jcBzDetail.id) {
|
||||
jcGetJcBzDetailApi({
|
||||
jcBzId: jcBzDetail.id,
|
||||
}).then((res) => {
|
||||
if (res.resultCode == 1) {
|
||||
// 这里可以根据实际数据结构处理详情信息
|
||||
console.log('就餐标准详情:', res.result);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
// 就餐标准详情数据
|
||||
const jcDetail = computed(() => {
|
||||
const data = (jcBzData.value as JcBzData) || {};
|
||||
return {
|
||||
id: data.id || "",
|
||||
bzmc: data.bzmc || "暂无标准名称",
|
||||
jfje: data.jfje || 0,
|
||||
bzms: data.bzms || "暂无描述",
|
||||
yxq: data.yxq || "暂无有效期信息",
|
||||
lxtp: imagUrl(data.lxtp || ''), // 使用imagUrl处理图片路径
|
||||
};
|
||||
});
|
||||
|
||||
// 解析使用说明和注意事项
|
||||
const parseInstructions = () => {
|
||||
const data = (jcBzData.value as JcBzData) || {};
|
||||
const bzms = data.bzms || '';
|
||||
|
||||
// 这里可以根据实际的数据格式来解析使用说明和注意事项
|
||||
// 示例:假设备注中包含使用说明和注意事项,用特定分隔符分隔
|
||||
if (bzms) {
|
||||
// 这里可以根据实际的数据格式来解析
|
||||
// 示例:假设使用说明和注意事项用"注意事项:"分隔
|
||||
const parts = bzms.split('注意事项:');
|
||||
if (parts.length > 1) {
|
||||
usageInstructions.value = parts[0].split('\n').filter(item => item.trim());
|
||||
precautions.value = parts[1].split('\n').filter(item => item.trim());
|
||||
} else {
|
||||
usageInstructions.value = bzms.split('\n').filter(item => item.trim());
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
onMounted(() => {
|
||||
parseInstructions();
|
||||
});
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.jc-detail {
|
||||
background-color: #f5f7fa;
|
||||
}
|
||||
|
||||
.info-card {
|
||||
margin: 15px;
|
||||
background-color: #fff;
|
||||
border-radius: 8px;
|
||||
padding: 15px;
|
||||
box-shadow: 0 2px 6px rgba(0, 0, 0, 0.05);
|
||||
|
||||
.card-title {
|
||||
font-size: 16px;
|
||||
font-weight: bold;
|
||||
color: #333;
|
||||
margin-bottom: 10px;
|
||||
}
|
||||
|
||||
.divider {
|
||||
height: 1px;
|
||||
background-color: #eee;
|
||||
margin-bottom: 15px;
|
||||
}
|
||||
}
|
||||
|
||||
.jc-info {
|
||||
display: flex;
|
||||
|
||||
.jc-image {
|
||||
width: 120px;
|
||||
height: 138px;
|
||||
border-radius: 8px;
|
||||
margin-right: 15px;
|
||||
}
|
||||
|
||||
.jc-content {
|
||||
flex: 1;
|
||||
|
||||
.jc-name {
|
||||
font-size: 18px;
|
||||
font-weight: bold;
|
||||
color: #333;
|
||||
margin-bottom: 10px;
|
||||
}
|
||||
|
||||
.jc-price {
|
||||
font-size: 14px;
|
||||
color: #666;
|
||||
margin-bottom: 8px;
|
||||
|
||||
.price-value {
|
||||
color: #ff6b00;
|
||||
font-weight: bold;
|
||||
}
|
||||
}
|
||||
|
||||
.jc-desc {
|
||||
font-size: 14px;
|
||||
color: #666;
|
||||
margin-bottom: 8px;
|
||||
line-height: 1.4;
|
||||
}
|
||||
|
||||
.jc-time {
|
||||
font-size: 14px;
|
||||
color: #666;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.content-section {
|
||||
font-size: 14px;
|
||||
color: #666;
|
||||
line-height: 1.6;
|
||||
|
||||
.instruction-item,
|
||||
.precaution-item {
|
||||
margin-bottom: 10px;
|
||||
padding-left: 15px;
|
||||
position: relative;
|
||||
|
||||
&:before {
|
||||
content: "•";
|
||||
position: absolute;
|
||||
left: 0;
|
||||
color: #2879ff;
|
||||
}
|
||||
|
||||
&:last-child {
|
||||
margin-bottom: 0;
|
||||
}
|
||||
}
|
||||
|
||||
.empty-data {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
padding: 20px 0;
|
||||
color: #909399;
|
||||
font-size: 14px;
|
||||
|
||||
text {
|
||||
margin-left: 8px;
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
@ -1,6 +1,7 @@
|
||||
<template>
|
||||
<view class="jc-page">
|
||||
<!-- 就餐信息头部 - 固定部分 -->
|
||||
<BasicLayout>
|
||||
<view class="jc-index">
|
||||
<!-- 就餐信息头部 -->
|
||||
<view class="selection-header">
|
||||
<view class="header-content">
|
||||
<!-- 学生选择部分 -->
|
||||
@ -8,35 +9,206 @@
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<!-- 可滚动的内容区域 -->
|
||||
<view class="scrollable-content">
|
||||
<JcBzList :xs-id="curXs.id" />
|
||||
<!-- 已选择的就餐标准信息 -->
|
||||
<view class="selected-jc-info" v-if="selectedJcBz">
|
||||
<view class="info-card">
|
||||
<view class="card-title">已选择的就餐标准</view>
|
||||
<view class="divider"></view>
|
||||
|
||||
<view class="jc-info">
|
||||
<image
|
||||
class="jc-image"
|
||||
:src="selectedJcBz.lxtp"
|
||||
mode="aspectFill"
|
||||
></image>
|
||||
|
||||
<view class="jc-content">
|
||||
<view class="jc-name">{{ selectedJcBz.bzmc }}</view>
|
||||
<view class="jc-price">
|
||||
价格:<text class="price-value">¥{{ selectedJcBz.jfje }}</text>
|
||||
</view>
|
||||
<view class="jc-desc">{{ selectedJcBz.bzms || '暂无描述' }}</view>
|
||||
<view class="jc-time">有效期:{{ selectedJcBz.yxq || '暂无有效期信息' }}</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<!-- 报名信息 -->
|
||||
<view class="info-card" v-if="bmInfo">
|
||||
<view class="card-title">报名信息</view>
|
||||
<view class="divider"></view>
|
||||
|
||||
<view class="bm-info">
|
||||
<view class="bm-item">
|
||||
<text class="label">报名时间:</text>
|
||||
<text class="value">{{ bmInfo.bmTime }}</text>
|
||||
</view>
|
||||
<view class="bm-item">
|
||||
<text class="label">支付状态:</text>
|
||||
<text class="value status-paid">已支付</text>
|
||||
</view>
|
||||
<view class="bm-item">
|
||||
<text class="label">订单号:</text>
|
||||
<text class="value">{{ bmInfo.orderNumber || '暂无' }}</text>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<!-- 使用说明 -->
|
||||
<view class="info-card">
|
||||
<view class="card-title">使用说明</view>
|
||||
<view class="divider"></view>
|
||||
|
||||
<view class="content-section">
|
||||
<template v-if="usageInstructions && usageInstructions.length > 0">
|
||||
<view
|
||||
v-for="(instruction, index) in usageInstructions"
|
||||
:key="index"
|
||||
class="instruction-item"
|
||||
>
|
||||
<text>{{ instruction }}</text>
|
||||
</view>
|
||||
</template>
|
||||
<template v-else>
|
||||
<view class="empty-data">
|
||||
<u-icon name="info-circle" color="#C8C9CC" size="18"></u-icon>
|
||||
<text>暂无使用说明</text>
|
||||
</view>
|
||||
</template>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<!-- 注意事项 -->
|
||||
<view class="info-card">
|
||||
<view class="card-title">注意事项</view>
|
||||
<view class="divider"></view>
|
||||
|
||||
<view class="content-section">
|
||||
<template v-if="precautions && precautions.length > 0">
|
||||
<view
|
||||
v-for="(precaution, index) in precautions"
|
||||
:key="index"
|
||||
class="precaution-item"
|
||||
>
|
||||
<text>{{ precaution }}</text>
|
||||
</view>
|
||||
</template>
|
||||
<template v-else>
|
||||
<view class="empty-data">
|
||||
<u-icon name="info-circle" color="#C8C9CC" size="18"></u-icon>
|
||||
<text>暂无注意事项</text>
|
||||
</view>
|
||||
</template>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<!-- 未选择就餐标准时的提示 -->
|
||||
<view class="no-selection" v-else>
|
||||
<view class="empty-state">
|
||||
<u-icon name="info-circle" color="#C8C9CC" size="48"></u-icon>
|
||||
<text class="empty-text">暂未选择就餐标准</text>
|
||||
<u-button
|
||||
text="立即报名"
|
||||
type="primary"
|
||||
@click="goToBm"
|
||||
class="bm-button"
|
||||
/>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</BasicLayout>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import XsPicker from "@/pages/base/components/XsPicker/index.vue"
|
||||
import JcBzList from "@/pages/base/components/JcBzList/index.vue"
|
||||
import { ref, onMounted, computed } from "vue";
|
||||
import { useUserStore } from "@/store/modules/user";
|
||||
import { useDataStore } from "@/store/modules/data";
|
||||
import { storeToRefs } from "pinia";
|
||||
import { imagUrl } from "@/utils";
|
||||
import XsPicker from "@/pages/base/components/XsPicker/index.vue"
|
||||
import { jcGetXsBmJcBzListApi } from "@/api/base/jcApi";
|
||||
|
||||
const { getCurXs } = useUserStore();
|
||||
const { getData, setData } = useDataStore();
|
||||
|
||||
const curXs = computed(() => getCurXs);
|
||||
|
||||
// 页面卸载前清除定时器
|
||||
onBeforeUnmount(() => {
|
||||
// 已选择的就餐标准
|
||||
const selectedJcBz = ref<any>(null);
|
||||
// 报名信息
|
||||
const bmInfo = ref<any>(null);
|
||||
// 使用说明
|
||||
const usageInstructions = ref<string[]>([]);
|
||||
// 注意事项
|
||||
const precautions = ref<string[]>([]);
|
||||
|
||||
// 获取已选择的就餐标准信息
|
||||
const getSelectedJcInfo = async () => {
|
||||
try {
|
||||
const res = await jcGetXsBmJcBzListApi({
|
||||
xsId: curXs.value.id
|
||||
});
|
||||
|
||||
if (res.resultCode === 1 && res.result && res.result.length > 0) {
|
||||
// 获取第一个已报名的就餐标准
|
||||
const jcQd = res.result[0];
|
||||
selectedJcBz.value = {
|
||||
id: jcQd.bzId,
|
||||
bzmc: jcQd.bzmc || '就餐标准',
|
||||
jfje: jcQd.jfje || 0,
|
||||
bzms: jcQd.bzms || '暂无描述',
|
||||
yxq: jcQd.yxq || '暂无有效期信息',
|
||||
lxtp: imagUrl(jcQd.lxtp || ''),
|
||||
};
|
||||
|
||||
// 设置报名信息
|
||||
bmInfo.value = {
|
||||
bmTime: jcQd.createdTime ? new Date(jcQd.createdTime).toLocaleString() : new Date().toLocaleString(),
|
||||
orderNumber: jcQd.zfptId || '暂无',
|
||||
status: jcQd.jfzt === 'B' ? '已支付' : '待支付'
|
||||
};
|
||||
|
||||
// 解析使用说明和注意事项
|
||||
parseInstructions();
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('获取已选择就餐标准失败:', error);
|
||||
}
|
||||
};
|
||||
|
||||
// 解析使用说明和注意事项
|
||||
const parseInstructions = () => {
|
||||
const bzms = selectedJcBz.value?.bzms || '';
|
||||
|
||||
if (bzms) {
|
||||
// 这里可以根据实际的数据格式来解析
|
||||
const parts = bzms.split('注意事项:');
|
||||
if (parts.length > 1) {
|
||||
usageInstructions.value = parts[0].split('\n').filter((item: string) => item.trim());
|
||||
precautions.value = parts[1].split('\n').filter((item: string) => item.trim());
|
||||
} else {
|
||||
usageInstructions.value = bzms.split('\n').filter((item: string) => item.trim());
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
// 跳转到报名页面
|
||||
const goToBm = () => {
|
||||
uni.reLaunch({
|
||||
url: '/pages/base/jc/bm'
|
||||
});
|
||||
};
|
||||
|
||||
onMounted(() => {
|
||||
getSelectedJcInfo();
|
||||
});
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.jc-page {
|
||||
min-height: 100%;
|
||||
.jc-index {
|
||||
min-height: 100vh;
|
||||
background-color: #f5f7fa;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
height: 100%;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.selection-header {
|
||||
@ -58,10 +230,160 @@ onBeforeUnmount(() => {
|
||||
}
|
||||
}
|
||||
|
||||
// 可滚动内容区域样式
|
||||
.scrollable-content {
|
||||
.selected-jc-info {
|
||||
padding: 15px;
|
||||
}
|
||||
|
||||
.info-card {
|
||||
margin-bottom: 15px;
|
||||
background-color: #fff;
|
||||
border-radius: 8px;
|
||||
padding: 15px;
|
||||
box-shadow: 0 2px 6px rgba(0, 0, 0, 0.05);
|
||||
|
||||
.card-title {
|
||||
font-size: 16px;
|
||||
font-weight: bold;
|
||||
color: #333;
|
||||
margin-bottom: 10px;
|
||||
}
|
||||
|
||||
.divider {
|
||||
height: 1px;
|
||||
background-color: #eee;
|
||||
margin-bottom: 15px;
|
||||
}
|
||||
}
|
||||
|
||||
.jc-info {
|
||||
display: flex;
|
||||
|
||||
.jc-image {
|
||||
width: 120px;
|
||||
height: 138px;
|
||||
border-radius: 8px;
|
||||
margin-right: 15px;
|
||||
}
|
||||
|
||||
.jc-content {
|
||||
flex: 1;
|
||||
overflow-y: auto;
|
||||
-webkit-overflow-scrolling: touch; // 增强iOS滚动体验
|
||||
|
||||
.jc-name {
|
||||
font-size: 18px;
|
||||
font-weight: bold;
|
||||
color: #333;
|
||||
margin-bottom: 10px;
|
||||
}
|
||||
|
||||
.jc-price {
|
||||
font-size: 14px;
|
||||
color: #666;
|
||||
margin-bottom: 8px;
|
||||
|
||||
.price-value {
|
||||
color: #ff6b00;
|
||||
font-weight: bold;
|
||||
}
|
||||
}
|
||||
|
||||
.jc-desc {
|
||||
font-size: 14px;
|
||||
color: #666;
|
||||
margin-bottom: 8px;
|
||||
line-height: 1.4;
|
||||
}
|
||||
|
||||
.jc-time {
|
||||
font-size: 14px;
|
||||
color: #666;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.bm-info {
|
||||
.bm-item {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
margin-bottom: 10px;
|
||||
|
||||
&:last-child {
|
||||
margin-bottom: 0;
|
||||
}
|
||||
|
||||
.label {
|
||||
font-size: 14px;
|
||||
color: #666;
|
||||
}
|
||||
|
||||
.value {
|
||||
font-size: 14px;
|
||||
color: #333;
|
||||
|
||||
&.status-paid {
|
||||
color: #52c41a;
|
||||
font-weight: bold;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.content-section {
|
||||
font-size: 14px;
|
||||
color: #666;
|
||||
line-height: 1.6;
|
||||
|
||||
.instruction-item,
|
||||
.precaution-item {
|
||||
margin-bottom: 10px;
|
||||
padding-left: 15px;
|
||||
position: relative;
|
||||
|
||||
&:before {
|
||||
content: "•";
|
||||
position: absolute;
|
||||
left: 0;
|
||||
color: #2879ff;
|
||||
}
|
||||
|
||||
&:last-child {
|
||||
margin-bottom: 0;
|
||||
}
|
||||
}
|
||||
|
||||
.empty-data {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
padding: 20px 0;
|
||||
color: #909399;
|
||||
font-size: 14px;
|
||||
|
||||
text {
|
||||
margin-left: 8px;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.no-selection {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
min-height: 60vh;
|
||||
|
||||
.empty-state {
|
||||
text-align: center;
|
||||
|
||||
.empty-text {
|
||||
display: block;
|
||||
margin: 20px 0;
|
||||
color: #909399;
|
||||
font-size: 16px;
|
||||
}
|
||||
|
||||
.bm-button {
|
||||
margin-top: 20px;
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
||||
@ -22,6 +22,12 @@ const { setGlobal } = useDataStore();
|
||||
const userStore = useUserStore();
|
||||
const isShow = ref(true);
|
||||
|
||||
const toLogin = () => {
|
||||
uni.reLaunch({
|
||||
url: "/pages/system/login/login",
|
||||
});
|
||||
};
|
||||
|
||||
onLoad(async (data: any) => {
|
||||
setGlobal(data);
|
||||
if (data && data.openId) {
|
||||
@ -42,20 +48,12 @@ onLoad(async (data: any) => {
|
||||
}
|
||||
// 直接跳转到首页,关注检查在首页进行
|
||||
userStore.toHome(data.type);
|
||||
} else {
|
||||
uni.reLaunch({
|
||||
url: "/pages/system/login/login",
|
||||
});
|
||||
return;
|
||||
}
|
||||
} catch (err) {
|
||||
uni.reLaunch({
|
||||
url: "/pages/system/login/login",
|
||||
});
|
||||
toLogin();
|
||||
}
|
||||
} else {
|
||||
uni.reLaunch({
|
||||
url: "/pages/system/login/login",
|
||||
});
|
||||
}
|
||||
toLogin();
|
||||
});
|
||||
</script>
|
||||
|
||||
@ -1,6 +1,7 @@
|
||||
import { defineStore } from "pinia";
|
||||
import { authenticationApi, loginCode, loginPass, weChatLogin, checkOpenId } from "@/api/system/login";
|
||||
import { checkXsXkByTypeApi, xsKxApi } from "@/api/base/xkApi";
|
||||
import { jcGetJcBzListApi } from "@/api/base/jcApi";
|
||||
import { AUTH_KEY } from "@/config";
|
||||
import { imagUrl } from "@/utils";
|
||||
import { useWebSocket } from '@/utils/webSocket/webSocket'
|
||||
@ -228,6 +229,15 @@ export const useUserStore = defineStore({
|
||||
url: "/pages/base/home/xsXz",
|
||||
});
|
||||
}
|
||||
} else if (type == 3) {
|
||||
// 俱乐部逻辑: 判断当前学生列表
|
||||
if (this.userdata.xsList && this.userdata.xsList.length == 1) {
|
||||
this.checkJc();
|
||||
} else if (this.userdata.xsList && this.userdata.xsList.length > 1) {
|
||||
uni.reLaunch({
|
||||
url: "/pages/base/home/xsXz",
|
||||
});
|
||||
}
|
||||
} else {
|
||||
uni.reLaunch({
|
||||
url: "/pages/base/home/index",
|
||||
@ -267,12 +277,11 @@ export const useUserStore = defineStore({
|
||||
default:
|
||||
// 默认跳转到告知书页面
|
||||
uni.reLaunch({
|
||||
url: "/pages/base/gzs/xqk",
|
||||
url: "/pages/base/gzs/xkXqk",
|
||||
});
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// 接口调用失败,使用备用方案
|
||||
this.checkXqkFallback();
|
||||
} catch (error) {
|
||||
@ -303,12 +312,12 @@ export const useUserStore = defineStore({
|
||||
}
|
||||
}
|
||||
uni.reLaunch({
|
||||
url: "/pages/base/gzs/xqk",
|
||||
url: "/pages/base/gzs/xkXqk",
|
||||
});
|
||||
} catch (error) {
|
||||
console.error("备用方案也失败:", error);
|
||||
uni.reLaunch({
|
||||
url: "/pages/base/gzs/xqk",
|
||||
url: "/pages/base/gzs/xkXqk",
|
||||
});
|
||||
}
|
||||
},
|
||||
@ -345,7 +354,7 @@ export const useUserStore = defineStore({
|
||||
default:
|
||||
// 默认跳转到告知书页面
|
||||
uni.reLaunch({
|
||||
url: "/pages/base/gzs/jlb",
|
||||
url: "/pages/base/gzs/xkJlb",
|
||||
});
|
||||
return;
|
||||
}
|
||||
@ -382,12 +391,71 @@ export const useUserStore = defineStore({
|
||||
}
|
||||
}
|
||||
uni.reLaunch({
|
||||
url: "/pages/base/gzs/jlb",
|
||||
url: "/pages/base/gzs/xkJlb",
|
||||
});
|
||||
} catch (error) {
|
||||
console.error("备用方案也失败:", error);
|
||||
uni.reLaunch({
|
||||
url: "/pages/base/gzs/jlb",
|
||||
url: "/pages/base/gzs/xkJlb",
|
||||
});
|
||||
}
|
||||
},
|
||||
// 就餐查询 - 优化版本
|
||||
async checkJc() {
|
||||
try {
|
||||
// 使用getJcBzList接口获取详细就餐信息
|
||||
const res = await jcGetJcBzListApi({
|
||||
xsId: this.curXs.id
|
||||
});
|
||||
|
||||
if (res.resultCode === 1) {
|
||||
const data = res.result;
|
||||
const type = data.type;
|
||||
|
||||
switch (type) {
|
||||
case 1: // 未选择(返回可选标准列表)- 跳转到报名页面
|
||||
uni.reLaunch({
|
||||
url: "/pages/base/jc/bm",
|
||||
});
|
||||
return;
|
||||
case 2: // 待支付 - 跳转到支付页面
|
||||
uni.reLaunch({
|
||||
url: "/pages/base/jc/pay/index",
|
||||
});
|
||||
return;
|
||||
case 3: // 已支付 - 跳转到已选择页面
|
||||
uni.reLaunch({
|
||||
url: "/pages/base/jc/index",
|
||||
});
|
||||
return;
|
||||
default:
|
||||
// 默认跳转到报名页面
|
||||
uni.reLaunch({
|
||||
url: "/pages/base/gzs/jc",
|
||||
});
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// 接口调用失败,使用备用方案
|
||||
this.checkJcFallback();
|
||||
} catch (error) {
|
||||
console.error("查询就餐状态失败:", error);
|
||||
// 异常情况,使用备用方案
|
||||
this.checkJcFallback();
|
||||
}
|
||||
},
|
||||
// 就餐备用检查方案
|
||||
async checkJcFallback() {
|
||||
try {
|
||||
// 备用方案:直接跳转到报名页面
|
||||
uni.reLaunch({
|
||||
url: "/pages/base/gzs/jc",
|
||||
});
|
||||
} catch (error) {
|
||||
console.error("备用方案也失败:", error);
|
||||
uni.reLaunch({
|
||||
url: "/pages/base/gzs/jc",
|
||||
});
|
||||
}
|
||||
},
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user