调整就餐

This commit is contained in:
ywyonui 2025-08-08 20:38:11 +08:00
parent 247c1b313d
commit 04c6e5a1c9
8 changed files with 402 additions and 391 deletions

View File

@ -11,26 +11,43 @@
class="jc-bz-item"
>
<view class="jc-bz-info">
<image
<!-- 隐藏图片显示因为就餐标准没有对应图片 -->
<!-- <image
class="jc-bz-image"
:src="getImageUrl(jcBz.lxtp)"
mode="aspectFill"
></image>
></image> -->
<view class="jc-bz-content">
<view class="jc-bz-name">{{ jcBz.bzmc || '暂无标准名称' }}</view>
<view class="jc-bz-name">{{ jcBz.bzMc || '暂无标准名称' }}</view>
<view class="jc-bz-price">
价格<text class="price-value">¥{{ jcBz.jfje || 0 }}</text>
价格<text class="price-value">¥{{ jcBz.bzJe || 0 }}</text>
</view>
<view class="jc-bz-desc">{{ jcBz.bzSm || '暂无描述' }}</view>
<view class="jc-bz-capacity">
容量<text class="capacity-value">{{ jcBz.hasNum || 0 }}/{{ jcBz.maxNum || 0 }}</text>
</view>
<!-- 显示更多详细信息 -->
<view class="jc-bz-details">
<view class="detail-item" v-if="jcBz.jfKsSj">
<text class="detail-label">缴费开始</text>
<text class="detail-value">{{ jcBz.jfKsSj }}</text>
</view>
<view class="detail-item" v-if="jcBz.jfJsSj">
<text class="detail-label">缴费结束</text>
<text class="detail-value">{{ jcBz.jfJsSj }}</text>
</view>
<view class="detail-item">
<text class="detail-label">缴费状态</text>
<text class="detail-value">{{ jcBz.sfJf === '1' ? '需要缴费' : '免费' }}</text>
</view>
<view class="detail-item">
<text class="detail-label">发布状态</text>
<text class="detail-value">{{ jcBz.sfFb === '1' ? '已发布' : '待发布' }}</text>
</view>
</view>
<view class="jc-bz-desc">{{ jcBz.bzms || '暂无描述' }}</view>
<view class="jc-bz-time">有效期{{ jcBz.yxq || '暂无有效期信息' }}</view>
</view>
</view>
<!-- 可选的详情展开按钮 -->
<view v-if="showDetailBtn" class="detail-btn" @click="goToDetail(jcBz)">
<text>查看详情</text>
</view>
</view>
</view>
@ -55,11 +72,16 @@ import { imagUrl } from "@/utils";
//
interface JcBzData {
id?: string;
bzmc?: string;
jfje?: number;
bzms?: string;
yxq?: string;
lxtp?: string;
bzMc?: string; //
bzJe?: number; //
bzSm?: string; //
maxNum?: number; //
hasNum?: number; //
sfJf?: string; // 10
sfFb?: string; // 10
jfKsSj?: string; //
jfJsSj?: string; //
lxtp?: string; //
[key: string]: any;
}
@ -77,26 +99,19 @@ const props = withDefaults(defineProps<Props>(), {
showSummary: true
});
const emit = defineEmits(['detail']);
//
const totalPrice = computed(() => {
let total = 0;
props.jcBzList.forEach(jcBz => {
total += jcBz.jfje || 0;
total += jcBz.bzJe || 0;
});
return total;
});
// URL
const getImageUrl = (imagePath: string) => {
const getImageUrl = (imagePath: string | undefined) => {
return imagUrl(imagePath || '');
};
//
const goToDetail = (jcBz: JcBzData) => {
emit('detail', jcBz);
};
</script>
<style lang="scss" scoped>
@ -132,17 +147,20 @@ const goToDetail = (jcBz: JcBzData) => {
.jc-bz-info {
flex: 1;
display: flex;
/* 移除flex布局因为不再需要图片和内容的并排显示 */
/* display: flex; */
.jc-bz-image {
/* 隐藏图片样式,因为就餐标准没有对应图片 */
/* .jc-bz-image {
width: 80px;
height: 80px;
border-radius: 6px;
margin-right: 12px;
}
} */
.jc-bz-content {
flex: 1;
/* 移除flex: 1因为不再需要flex布局 */
/* flex: 1; */
.jc-bz-name {
font-size: 16px;
@ -174,22 +192,45 @@ const goToDetail = (jcBz: JcBzData) => {
overflow: hidden;
}
.jc-bz-time {
.jc-bz-capacity {
font-size: 12px;
color: #999;
.capacity-value {
color: #2879ff;
font-weight: 500;
}
}
.jc-bz-details {
margin-top: 10px;
padding-top: 10px;
border-top: 1px dashed #eee;
.detail-item {
display: flex;
margin-bottom: 5px;
font-size: 12px;
&:last-child {
margin-bottom: 0;
}
.detail-label {
color: #666;
margin-right: 5px;
min-width: 60px;
}
.detail-value {
color: #333;
font-weight: 500;
flex: 1;
}
}
}
}
}
.detail-btn {
margin-left: 10px;
padding: 6px 12px;
background-color: #2879ff;
color: #fff;
border-radius: 4px;
font-size: 12px;
white-space: nowrap;
}
}
}

View File

@ -10,7 +10,7 @@
@click="toggleSelection(jcBz)"
>
<view class="jc-bz-header">
<view class="jc-bz-name">{{ jcBz.bzmc }}</view>
<view class="jc-bz-name">{{ jcBz.bzMc }}</view>
<view class="detail-btn" @click.stop="goToDetail(jcBz)">
<image src="/static/base/home/details.svg" class="detail-icon" />
</view>
@ -18,9 +18,13 @@
<view class="jc-bz-info">
<view class="jc-bz-price">
<text>价格</text>
<text class="price-value">¥{{ jcBz.jfje }}</text>
<text class="price-value">¥{{ jcBz.bzJe }}</text>
</view>
<view class="jc-bz-desc">{{ jcBz.bzSm || '暂无描述' }}</view>
<view class="jc-bz-capacity">
<text>容量</text>
<text class="capacity-value">{{ jcBz.hasNum || 0 }}/{{ jcBz.maxNum || 0 }}</text>
</view>
<view class="jc-bz-desc">{{ jcBz.bzms || '暂无描述' }}</view>
</view>
<view v-if="jcBz.isSelected" class="selected-mark">
<uni-icons
@ -146,7 +150,7 @@ const toggleSelection = (jcBz: any) => {
const goToDetail = (jcBz: any) => {
setJcBzData(jcBz);
uni.navigateTo({
url: `/pages/base/jc/detail`,
url: `/pages/base/jc/index`,
});
};
@ -237,6 +241,17 @@ onMounted(() => {
font-size: 12px;
color: #999;
line-height: 1.4;
margin-bottom: 6px;
}
.jc-bz-capacity {
font-size: 12px;
color: #999;
.capacity-value {
color: #2879ff;
font-weight: 500;
}
}
}

View File

@ -1,6 +1,15 @@
<template>
<view class="jc-bz-picker">
<view class="picker-header" @click="showPicker">
<!-- 当只有一个标准时直接显示标准信息 -->
<view v-if="jcBzList.length === 1" class="single-jc-bz">
<view class="single-jc-bz-info">
<view class="jc-bz-name">{{ jcBzList[0].bzMc }}</view>
<view class="jc-bz-price">¥{{ jcBzList[0].bzJe }}</view>
</view>
</view>
<!-- 当有多个标准时显示拣选器 -->
<view v-else-if="jcBzList.length > 1" class="picker-header" @click="showPicker">
<view class="picker-label">
<text class="label-text">{{ label }}</text>
<text class="required" v-if="required">*</text>
@ -13,6 +22,11 @@
</view>
</view>
<!-- 当没有标准时显示提示 -->
<view v-else class="no-jc-bz">
<text class="no-data-text">暂无可用就餐标准</text>
</view>
<!-- 选择器弹窗 -->
<uni-popup ref="popup" type="bottom" :mask-click="false">
<view class="popup-content">
@ -34,8 +48,16 @@
@click="toggleSelection(jcBz)"
>
<view class="jc-bz-info">
<view class="jc-bz-name">{{ jcBz.bzmc }}</view>
<view class="jc-bz-price">¥{{ jcBz.jfje }}</view>
<view class="jc-bz-name">{{ jcBz.bzMc }}</view>
<view class="jc-bz-details">
<view class="jc-bz-price">¥{{ jcBz.bzJe }}</view>
<view class="jc-bz-desc" v-if="jcBz.bzSm">{{ jcBz.bzSm }}</view>
</view>
<view class="jc-bz-status">
<view class="capacity-info">
<text class="capacity-text">已报名: {{ jcBz.hasNum || 0 }}/{{ jcBz.maxNum || 0 }}</text>
</view>
</view>
</view>
<view v-if="isSelected(jcBz)" class="selected-icon">
<uni-icons type="checkmarkempty" color="#2879ff" size="20"></uni-icons>
@ -54,11 +76,15 @@ import { jcGetJcBzListApi } from "@/api/base/jcApi";
interface JcBzData {
id: string;
bzmc: string;
jfje: number;
bzms?: string;
yxq?: string;
lxtp?: string;
bzMc: string; //
bzJe: number; //
bzSm?: string; //
maxNum?: number; //
hasNum?: number; //
sfJf?: string; // 10
sfFb?: string; // 10
jfKsSj?: string; //
jfJsSj?: string; //
[key: string]: any;
}
@ -96,12 +122,12 @@ const selectedText = computed(() => {
const selectedItems = jcBzList.value.filter(item =>
selectedIds.value.includes(item.id)
);
return selectedItems.map(item => item.bzmc).join('、');
return selectedItems.map(item => item.bzMc).join('、');
} else {
const selectedItem = jcBzList.value.find(item =>
selectedIds.value.includes(item.id)
);
return selectedItem?.bzmc || '';
return selectedItem?.bzMc || '';
}
});
@ -121,6 +147,13 @@ const getJcBzList = async () => {
const result = res.result;
if (result && result.jcBzList) {
jcBzList.value = result.jcBzList || [];
//
if (jcBzList.value.length === 1) {
const singleJcBz = jcBzList.value[0];
selectedIds.value = [singleJcBz.id];
emit('change', singleJcBz.id);
emit('update:value', singleJcBz.id);
}
} else {
jcBzList.value = [];
}
@ -191,6 +224,31 @@ onMounted(() => {
<style lang="scss" scoped>
.jc-bz-picker {
.single-jc-bz {
padding: 15px;
background-color: #fff;
border-radius: 8px;
border: 1px solid #e5e5e5;
.single-jc-bz-info {
display: flex;
justify-content: space-between;
align-items: center;
.jc-bz-name {
font-size: 16px;
color: #333;
font-weight: 500;
}
.jc-bz-price {
font-size: 16px;
color: #ff6b00;
font-weight: bold;
}
}
}
.picker-header {
display: flex;
align-items: center;
@ -229,6 +287,19 @@ onMounted(() => {
margin-left: 10px;
}
}
.no-jc-bz {
padding: 15px;
background-color: #fff;
border-radius: 8px;
border: 1px solid #e5e5e5;
text-align: center;
.no-data-text {
font-size: 14px;
color: #999;
}
}
}
.popup-content {
@ -298,13 +369,37 @@ onMounted(() => {
.jc-bz-name {
font-size: 16px;
color: #333;
margin-bottom: 5px;
margin-bottom: 8px;
font-weight: 500;
}
.jc-bz-price {
font-size: 14px;
color: #ff6b00;
font-weight: bold;
.jc-bz-details {
margin-bottom: 8px;
.jc-bz-price {
font-size: 16px;
color: #ff6b00;
font-weight: bold;
margin-bottom: 4px;
}
.jc-bz-desc {
font-size: 12px;
color: #666;
line-height: 1.4;
}
}
.jc-bz-status {
.capacity-info {
.capacity-text {
font-size: 12px;
color: #999;
background-color: #f5f5f5;
padding: 2px 6px;
border-radius: 4px;
}
}
}
}

View File

@ -1,75 +0,0 @@
# 就餐模块业务逻辑调整说明
## 概述
参照选课的处理和业务逻辑,对就餐相关的业务逻辑进行了调整,实现了统一的状态管理和页面跳转逻辑。
## 主要调整
### 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. 页面整合
- **删除页面**:
- `detail.vue` - 就餐标准详情页面
- `bm-detail.vue` - 报名详情页面
- **整合到**: `index.vue` - 已选择就餐标准展示页面
### 3. index.vue页面重构
- **功能**: 展示已选择的就餐标准信息
- **包含内容**:
- 就餐标准基本信息(名称、价格、描述、有效期)
- 报名信息(报名时间、支付状态、订单号)
- 使用说明
- 注意事项
- **状态处理**:
- 有已选择标准:显示详细信息
- 无已选择标准:显示空状态,提供"立即报名"按钮
### 4. bm.vue页面调整
- **跳转逻辑**: 已报名时跳转到 `index.vue` 而不是已删除的 `bm-detail.vue`
### 5. 后端接口对应
- **接口**: `/mobile/jz/jc/getJcBzList`
- **返回类型**: `AppJzXsJcVo`
- **type字段含义**:
- `1`: 未选择(返回可选标准列表)
- `2`: 待支付
- `3`: 已支付
## 页面跳转流程
### 通过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` (已选择页面)
### 页面间跳转
- **报名成功** → 跳转到支付页面
- **支付成功** → 跳转到已选择页面
- **查看详情** → 在已选择页面中展示完整信息
## 技术实现
### 前端
- **状态管理**: 使用Pinia store管理用户状态和就餐数据
- **页面路由**: 使用uni.reLaunch进行页面跳转
- **数据获取**: 通过API接口获取就餐状态和详情信息
### 后端
- **状态检查**: 通过Redis缓存和数据库查询确定就餐状态
- **类型定义**: 使用AppJzXsJcVo统一返回格式
- **业务逻辑**: 参照选课模块的实现方式
## 注意事项
1. 确保后端接口返回的type值与前端期望一致
2. 页面跳转使用uni.reLaunch确保正确的页面栈管理
3. 数据获取失败时使用备用方案(跳转到报名页面)
4. 删除的页面文件已清理,避免引用错误

View File

@ -11,7 +11,7 @@
<!-- 可滚动的内容区域 -->
<view class="scrollable-content">
<!-- 就餐标准选择器 -->
<view class="form-section">
<view class="form-section" v-if="jcBzList.length > 0">
<JcBzPicker
:xs-id="curXs.id"
label="就餐标准"
@ -28,9 +28,8 @@
v-if="selectedJcBz"
:jc-bz-list="[selectedJcBz]"
title="已选择的就餐标准"
:show-detail-btn="true"
:show-detail-btn="false"
:show-summary="false"
@detail="goToDetail"
/>
</view>
@ -64,12 +63,37 @@ const curXs = computed(() => getCurXs);
const selectedJcBzId = ref<string>('');
//
const selectedJcBz = ref<any>(null);
//
const jcBzList = ref<any[]>([]);
//
const totalPrice = computed(() => {
return selectedJcBz.value?.jfje || 0;
return selectedJcBz.value?.bzJe || 0;
});
//
const getJcBzList = async () => {
try {
const res = await jcGetJcBzListApi({
xsId: curXs.value.id
});
if (res.resultCode === 1) {
const result = res.result;
jcBzList.value = result && result.jcBzList ? result.jcBzList : [];
//
if (jcBzList.value.length === 1) {
const singleJcBz = jcBzList.value[0];
selectedJcBzId.value = singleJcBz.id;
selectedJcBz.value = singleJcBz;
}
}
} catch (error) {
console.error('获取就餐标准列表失败:', error);
}
};
//
const onJcBzChange = (id: string) => {
selectedJcBzId.value = id;
@ -84,37 +108,10 @@ const updateSelectedJcBz = async (id: string) => {
return;
}
try {
//
const res = await jcGetJcBzListApi({
xsId: curXs.value.id
});
if (res.resultCode === 1) {
//
const result = res.result;
const allJcBzList = result && result.jcBzList ? result.jcBzList : [];
//
selectedJcBz.value = allJcBzList.find((jcBz: any) =>
jcBz.id === id
) || null;
}
} catch (error) {
console.error('获取就餐标准详情失败:', error);
}
};
//
const goToDetail = (jcBz: any) => {
// store
setData({
...getData,
jcBzData: jcBz
});
//
uni.navigateTo({
url: '/pages/base/jc/detail'
});
//
selectedJcBz.value = jcBzList.value.find((jcBz: any) =>
jcBz.id === id
) || null;
};
//
@ -133,7 +130,7 @@ const confirmBm = async () => {
}
try {
const res = await jcBmJcBzApi({
const params = {
xsId: curXs.value.id,
bzId: selectedJcBzId.value,
jzId: getUser.jzId,
@ -142,7 +139,8 @@ const confirmBm = async () => {
njmc: curXs.value.njmc,
bc: curXs.value.bc,
xm: curXs.value.xsxm,
});
}
const res = await jcBmJcBzApi(params);
if (res.resultCode === 1) {
uni.showToast({
@ -152,10 +150,10 @@ const confirmBm = async () => {
// store
setData({
...getData,
...params,
xsId: curXs.value.id,
jcBzIds: [selectedJcBzId.value],
jcBzList: [selectedJcBz.value],
bzId: selectedJcBzId.value,
jcBz: selectedJcBz.value,
totalJe: totalPrice.value,
});
@ -200,6 +198,11 @@ const confirmBm = async () => {
//
onBeforeUnmount(() => {
});
//
onMounted(() => {
getJcBzList();
});
</script>
<style lang="scss" scoped>

View File

@ -12,95 +12,56 @@
<!-- 已选择的就餐标准信息 -->
<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.xm }}</text>
</view>
<!-- <view class="bm-item">
<text class="label">学号</text>
<text class="value">{{ bmInfo.xh }}</text>
</view> -->
<view class="bm-item">
<text class="label">年级</text>
<text class="value">{{ bmInfo.njMc }} {{ bmInfo.njBc }}</text>
</view>
<!-- <view class="bm-item">
<text class="label">班级</text>
<text class="value">{{ bmInfo.bjMc }}</text>
</view> -->
<view class="bm-item">
<text class="label">就餐标准</text>
<text class="value">{{ selectedJcBz.bzMc }}</text>
</view>
<view class="bm-item">
<text class="label">标准价格</text>
<text class="value amount">¥{{ selectedJcBz.bzJe }}</text>
</view>
<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 amount">¥{{ bmInfo.jfJe }}</text>
</view>
<view class="bm-item">
<text class="label">缴费方式</text>
<text class="value">{{ bmInfo.jfFs }}</text>
</view>
<view class="bm-item">
<text class="label">支付状态</text>
<text class="value status-paid">已支付</text>
<text class="value" :class="getStatusClass(bmInfo.status)">{{ bmInfo.status }}</text>
</view>
<view class="bm-item">
<text class="label">订单号</text>
<text class="value">{{ bmInfo.orderNumber || '暂无' }}</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>
<!-- 未选择就餐标准时的提示 -->
@ -138,10 +99,6 @@ const curXs = computed(() => getCurXs);
const selectedJcBz = ref<any>(null);
//
const bmInfo = ref<any>(null);
// 使
const usageInstructions = ref<string[]>([]);
//
const precautions = ref<string[]>([]);
//
const getSelectedJcInfo = async () => {
@ -155,44 +112,34 @@ const getSelectedJcInfo = async () => {
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 || ''),
bzMc: jcQd.bzMc || '就餐标准',
bzJe: jcQd.jfJe || 0, // 使jfJe
bzSm: jcQd.bzSm || '暂无描述',
maxNum: jcQd.maxNum || 0,
hasNum: jcQd.hasNum || 0,
lxtp: imagUrl(jcQd.xstx || ''), // 使xstx
};
//
// JcQd
bmInfo.value = {
bmTime: jcQd.createdTime ? new Date(jcQd.createdTime).toLocaleString() : new Date().toLocaleString(),
orderNumber: jcQd.zfptId || '暂无',
status: jcQd.jfzt === 'B' ? '已支付' : '待支付'
orderNumber: jcQd.zfPtId || '暂无', // 使zfPtId
status: jcQd.jfZt === 'B' ? '已支付' : jcQd.jfZt === 'A' ? '待支付' : jcQd.jfZt === 'C' ? '已退费' : '未知状态',
jfFs: jcQd.jfFs || '暂无', //
jfJe: jcQd.jfJe || 0, //
njMc: jcQd.njMc || '', //
njBc: jcQd.njBc || '', //
bjMc: jcQd.bjMc || '', //
xm: jcQd.xm || '', //
xh: jcQd.xh || '', //
xstx: jcQd.xstx || '', //
};
// 使
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({
@ -200,6 +147,20 @@ const goToBm = () => {
});
};
// CSS
const getStatusClass = (status: string) => {
switch (status) {
case '已支付':
return 'status-paid';
case '待支付':
return 'status-pending';
case '已退费':
return 'status-refunded';
default:
return 'status-unknown';
}
};
onMounted(() => {
getSelectedJcInfo();
});
@ -255,51 +216,6 @@ onMounted(() => {
}
}
.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;
}
}
}
.bm-info {
.bm-item {
display: flex;
@ -324,43 +240,26 @@ onMounted(() => {
color: #52c41a;
font-weight: bold;
}
}
}
}
&.status-pending {
color: #faad14;
font-weight: bold;
}
&.status-refunded {
color: #ff4d4f;
font-weight: bold;
}
&.status-unknown {
color: #999;
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;
&.amount {
color: #ff6b00;
font-weight: bold;
}
}
}
}

View File

@ -26,14 +26,10 @@
<!-- 就餐标准信息 -->
<view class="jc-bz-info-card">
<view class="card-title">报名就餐标准</view>
<view class="jc-bz-list">
<view
v-for="(jcBz, index) in jcBzList"
:key="index"
class="jc-bz-item"
>
<view class="jc-bz-name">{{ jcBz.bzmc }}</view>
<view class="jc-bz-price">¥{{ jcBz.jfje }}</view>
<view class="jc-bz-list" v-if="jcBz">
<view class="jc-bz-item">
<view class="jc-bz-name">{{ jcBz.bzMc }}</view>
<view class="jc-bz-price">¥{{ jcBz.bzJe }}</view>
</view>
</view>
</view>
@ -58,25 +54,23 @@
<script setup lang="ts">
import { useUserStore } from "@/store/modules/user";
import { useDataStore } from "@/store/modules/data";
import { jcCancelBmJcBzApi, jcFqJcBzJfjApi, jcGetJcBzPayExpiredTimeApi } from "@/api/base/jcApi";
import { jcCancelBmJcBzApi, jcFqJcBzJfjApi, jcGetBmExpiredTimeApi, jcGetJcBzListApi } from "@/api/base/jcApi";
const { getCurXs, getUser } = useUserStore();
const { getData, setData } = useDataStore();
//
const curXs = computed(() => getCurXs);
//
const jcBzList = computed(() => getData.jcBzList);
// -
const jcBz = computed(() => getData.jcBz);
//
const totalJe = computed(() => {
// jcBzList.value
if (!jcBzList.value || !jcBzList.value.length) {
return 0;
// 使store
if (getData.totalJe) {
return getData.totalJe;
}
let total = 0;
for (let i = 0; i < jcBzList.value.length; i++) {
total += jcBzList.value[i].jfje;
}
return total;
// jcBz
return jcBz.value?.bzJe || 0;
});
//
@ -124,7 +118,7 @@ const cancelRegistration = () => {
try {
await jcCancelBmJcBzApi({
xsId: getData.xsId,
jcBzIds: getData.jcBzIds
bzId: getData.bzId,
});
uni.showToast({
title: "已取消报名",
@ -148,7 +142,7 @@ const payNow = async () => {
try {
const res = await jcFqJcBzJfjApi({
xsId: getData.xsId,
jcBzIds: getData.jcBzIds,
bzId: getData.bzId,
jffs: "四川农信", // TODO:
jzId: getUser.jzId,
userId: getUser.userId,
@ -173,8 +167,40 @@ const payNow = async () => {
};
onMounted(async() => {
// store
if (!getData.jcBz || !getData.bzId) {
try {
const res = await jcGetJcBzListApi({
xsId: getCurXs.id
});
if (res.resultCode === 1 && res.result) {
const data = res.result;
if (data.type === 2 && data.jcqdList && data.jcqdList.length > 0) {
// store
const jcqd = data.jcqdList[0];
const jcBz = {
id: jcqd.bzId,
bzMc: jcqd.bzMc,
bzJe: jcqd.bzJe,
bzSm: jcqd.bzSm,
};
setData({
xsId: getCurXs.id,
bzId: jcqd.bzId,
jcBz: jcBz,
totalJe: jcqd.bzJe,
});
}
}
} catch (error) {
console.error('获取就餐数据失败:', error);
}
}
try {
const res = await jcGetJcBzPayExpiredTimeApi({ xsId: getCurXs.id });
const res = await jcGetBmExpiredTimeApi({ xsId: getCurXs.id });
console.log('获取支付倒计时', res);
if (res.resultCode === 1) {
seconds = res.result;

View File

@ -46,7 +46,7 @@
<script lang="ts" setup>
import { onLoad } from "@dcloudio/uni-app";
// import { jzGetQkExpiredTime, jzXkCancelApi, jzXkJfCxjApi } from "@/api/base/server";
import { jcGetBmExpiredTimeApi } from "@/api/base/jcApi";
import { useUserStore } from "@/store/modules/user";
import { useDataStore } from "@/store/modules/data";
const { getCurXs, initWs, setWsCallback } = useUserStore();
@ -120,8 +120,6 @@ const handleWebViewError = (e: any) => {
});
};
setWsCallback((type: string, res: any) => {
console.log('收到WebSocket消息:', type, res.data);
// data
@ -135,7 +133,7 @@ setWsCallback((type: string, res: any) => {
//
setTimeout(() => {
uni.reLaunch({
url: "/pages/base/xk/pay/success",
url: "/pages/base/jc/pay/success",
});
}, 1000)
}
@ -154,7 +152,7 @@ const startCountdown = () => {
clearInterval(timer);
uni.showModal({
title: "支付超时",
content: "支付已超时,请重新选",
content: "支付已超时,请重新选择就餐标准",
showCancel: false,
success: () => {
cancelRegistration();
@ -202,12 +200,21 @@ onLoad(async (options: any) => {
if (options.payUrl) {
payUrl.value = decodeURIComponent(options.payUrl);
console.log('支付URL:', payUrl.value);
console.log('支付URL:', payUrl.value);
// const res = await jzGetQkExpiredTime({ xsId: getCurXs.id} );
// seconds = res.result;
// initWs();
// startCountdown();
//
try {
const res = await jcGetBmExpiredTimeApi({ xsId: getCurXs.id });
console.log('获取就餐倒计时', res);
if (res.resultCode === 1) {
seconds = res.result;
}
} catch (error) {
console.error('获取就餐倒计时失败:', error);
}
initWs();
startCountdown();
} else {
uni.showToast({ title: '缺少支付地址', icon: 'none' })
setTimeout(() => {