修改体检页面,新增特殊时段不让缴费

This commit is contained in:
sangchengzhi
2026-01-13 16:27:42 +08:00
parent 04324d5362
commit aaf244eed6
5 changed files with 506 additions and 52 deletions

View File

@@ -357,6 +357,18 @@ export default {
if( _this.yuyue.m > 0 && _this.radiovalue1 == ''){
Toast("请选择支付方式");
return;
}
// 检查当前时间是否在23:48-00:01之间这个时间段内禁止充值
const now = new Date();
const hours = now.getHours();
const minutes = now.getMinutes();
if ((hours === 23 && minutes >= 48) || (hours === 0 && minutes <= 1)) {
Toast({
message: '当前时间段(23:48-00:01)正在对账暂不支持支付操作请0点过后再试',
duration: 5000
});
return;
}
console.log("card",_this.card.cardNo);
if(_this.radiovalue1 == "微信医保支付" && _this.card.cardNo !="90120746" ){

View File

@@ -256,6 +256,18 @@ export default {
if (!this.radiovalue1) {
Toast('请选择支付方式');
return;
}
// 检查当前时间是否在23:48-00:01之间这个时间段内禁止充值
const now = new Date();
const hours = now.getHours();
const minutes = now.getMinutes();
if ((hours === 23 && minutes >= 48) || (hours === 0 && minutes <= 1)) {
Toast({
message: '当前时间段(23:48-00:01)正在对账暂不支持支付操作请0点过后再试',
duration: 5000
});
return;
}
// 设置支付状态为进行中
this.isPaying = true;

View File

@@ -208,6 +208,19 @@ return;
})
},
onConfirm() {
// 检查当前时间是否在23:48-00:01之间这个时间段内禁止充值
const now = new Date();
const hours = now.getHours();
const minutes = now.getMinutes();
if ((hours === 23 && minutes >= 48) || (hours === 0 && minutes <= 1)) {
Toast({
message: '当前时间段(23:48-00:01)正在对账暂不支持支付操作请0点过后再试',
duration: 5000
});
return;
}
if(this.zyinfo.YJJKC < this.chargemoney){
Toast({
message: '今日线上剩余可充值额度不足,请调整充值金额或到收费室进行充值!',

View File

@@ -2,7 +2,16 @@
<div class="home">
<nav-bar />
<div class="bj"></div>
<div class="zstj_tc_detail">
<!-- 全局加载遮罩 -->
<div v-if="globalLoading" class="global-loading">
<div class="loading-content">
<div class="loading-spinner"></div>
<div class="loading-text">数据加载中...</div>
</div>
</div>
<div v-show="!globalLoading" class="zstj_tc_detail">
<!-- 总标题与总价 -->
<div class="box">
<div class="container">
@@ -30,10 +39,13 @@
</p>
</div>
<div class="info">
<p><strong>项目价格</strong>¥{{ item.price }}</p>
<p><strong>项目说明</strong>{{ item.explain }}</p>
<p v-if="item.detailData && item.detailData.specialRequests">
<strong>注意事项</strong>{{ item.detailData.specialRequests }}
</p>
<p v-if="item.detailData"><strong>项目详情</strong>{{ item.detailData.program_items }}</p>
</div>
</div>
@@ -55,7 +67,8 @@ export default {
data() {
return {
detailList: [], // 存储多个项目及其详情
seldate: "" // 预约日期
seldate: "", // 预约日期
globalLoading: true // 全局加载状态
};
},
mounted() {
@@ -64,6 +77,7 @@ export default {
if (!itemsStr) {
Toast("未传入项目信息");
this.globalLoading = false;
return;
}
@@ -73,6 +87,7 @@ export default {
} catch (e) {
Toast("项目数据解析失败");
console.error(e);
this.globalLoading = false;
}
},
computed: {
@@ -86,6 +101,7 @@ export default {
methods: {
// 初始化项目列表并获取每个项目的详情
getData(items) {
console.log("传入的items", items);
// 初始化项目列表
this.detailList = items.map(item => ({
...item,
@@ -93,14 +109,17 @@ export default {
detailData: null
}));
// 循环调用 apiGetDetail 获取每个项目详情
this.detailList.forEach((item, index) => {
apiGetDetail({
// 创建所有API请求的Promise数组
const requestPromises = this.detailList.map((item, index) => {
console.log("当前项目", item);
return apiGetDetail({
programId: item.id,
bookindDate: this.seldate
bookindDate: this.seldate,
Type: item.type,
})
.then(res => {
const data = res.data;
console.log(data);
const detailData = {
time: data.time || "时间未定",
time_period: data.time_period,
@@ -110,9 +129,10 @@ export default {
: data.time_period === "PM"
? "下午"
: "全天",
specialRequests: data.specialRequests || "无特殊要求"
specialRequests: data.specialRequests || "无特殊要求",
program_items: data.program_items || item.description || "无具体项目说明",
price: item.price,
};
// 使用 $set 确保响应式更新
this.$set(this.detailList[index], 'detailData', detailData);
})
@@ -121,7 +141,9 @@ export default {
const failData = {
time: "获取失败",
time_period2: "",
specialRequests: "信息加载异常"
specialRequests: "信息加载异常",
program_items: item.description || "无具体项目说明",
price: item.price,
};
this.$set(this.detailList[index], 'detailData', failData);
})
@@ -129,6 +151,17 @@ export default {
this.$set(this.detailList[index], 'loading', false);
});
});
// 等待所有请求完成后关闭全局加载状态
Promise.all(requestPromises)
.then(() => {
console.log("所有项目详情加载完成");
this.globalLoading = false;
})
.catch(err => {
console.error("部分请求失败", err);
this.globalLoading = false;
});
},
// 计算年龄的函数
getAgeFromIdNo(idNo) {
@@ -194,6 +227,7 @@ yuyue() {
programId: item.id,
time: detail.time || '',
timePeriod: detail.time_period || '',
type:item.type
};
});
@@ -258,6 +292,44 @@ yuyue() {
</script>
<style scoped lang="scss">
/* 全局加载遮罩样式 */
.global-loading {
position: fixed;
top: 0;
left: 0;
width: 100%;
height: 100%;
background-color: rgba(255, 255, 255, 0.9);
display: flex;
justify-content: center;
align-items: center;
z-index: 9999;
}
.loading-content {
text-align: center;
}
.loading-spinner {
width: 60px;
height: 60px;
border: 5px solid #f3f3f3;
border-top: 5px solid #46c3b0;
border-radius: 50%;
animation: spin 1s linear infinite;
margin: 0 auto 20px;
}
@keyframes spin {
0% { transform: rotate(0deg); }
100% { transform: rotate(360deg); }
}
.loading-text {
font-size: 24px;
color: #666;
}
.bj {
background: #f5f5f5;
position: fixed;

View File

@@ -34,6 +34,22 @@
</li>
</ul>
<!-- 类型选择 -->
<div class="typeSelect">
<div
:class="{ active: typeSelection === '1' }"
@click="typeSelection = '1'; handleTypeChange()"
>
套餐
</div>
<div
:class="{ active: typeSelection === '2' }"
@click="typeSelection = '2'; handleTypeChange()"
>
单项
</div>
</div>
<!-- 项目列表 -->
<div class="container-wrapper">
<div class="container">
@@ -55,6 +71,7 @@
<h2>
{{ item.name }}
<p>{{ item.explain }}</p>
<p>{{ item.description }}</p>
</h2>
<h3>¥{{ item.price }}</h3>
</div>
@@ -65,32 +82,134 @@
</div>
</div>
<!-- 底部预约按钮 -->
<div class="bottom-actions" v-if="selectedItems.length > 0">
<div class="action-buttons">
<button class="btn-appointment" @click="makeAppointment">立即预约</button>
<!-- 底部预约列表按钮 -->
<div class="cart-button-container">
<div
class="cart-button"
@click="openCartPopup"
v-if="selectedItems.length > 0"
>
<van-icon name="records" class="cart-icon" />
<div class="cart-text">预约列表</div>
<div class="cart-count">{{ selectedItems.length }}</div>
</div>
<div
class="cart-button empty"
@click="openCartPopup"
v-else
>
<van-icon name="records" class="cart-icon" />
<div class="cart-text">预约列表</div>
</div>
</div>
<!-- 预约列表弹窗 -->
<van-popup
v-model="showCartPopup"
position="bottom"
:style="{ height: '80%', borderRadius: '20px 20px 0 0' }"
>
<div class="cart-popup">
<!-- 弹窗头部 -->
<div class="cart-popup-header">
<h3>已选择项目 ({{ selectedItems.length }})</h3>
<van-button
type="default"
size="small"
@click="closeCartPopup"
plain
>
关闭
</van-button>
</div>
<!-- 项目列表 -->
<div class="cart-popup-content">
<van-checkbox-group
v-model="checkedItems"
@change="handlePopupSelectionChange"
>
<van-cell-group>
<van-cell
v-for="item in selectedItemsDetails"
:key="item.id"
:title="item.name"
:value="`¥${item.price}`"
is-link
>
<template #extra>
<van-checkbox :name="item.id" />
</template>
<template #label>
<div class="item-explain">{{ item.explain }}</div>
</template>
</van-cell>
</van-cell-group>
</van-checkbox-group>
</div>
<!-- 弹窗底部操作 -->
<div class="cart-popup-footer">
<div class="cart-popup-actions">
<van-button
type="default"
@click="selectAll"
plain
>
全选
</van-button>
<van-button
type="danger"
@click="deleteSelected"
plain
>
删除已选项
</van-button>
</div>
<van-button
type="primary"
block
@click="makeAppointment"
class="appointment-btn"
>
立即预约
</van-button>
</div>
</div>
</van-popup>
</div>
</template>
<script>
import { apiOpTiQuery } from "@/request/api.js";
import { Toast } from 'vant';
import { Toast, Popup, Button, Checkbox, CheckboxGroup, Cell, CellGroup, Icon } from 'vant';
export default {
name: 'Home',
components: {
[Popup.name]: Popup,
[Button.name]: Button,
[Checkbox.name]: Checkbox,
[CheckboxGroup.name]: CheckboxGroup,
[Cell.name]: Cell,
[CellGroup.name]: CellGroup,
[Icon.name]: Icon,
},
data() {
return {
searchKeyword: "",
same_week: [],
same_day: "",
selectedItems: [],
selectedItemsDetails: [], // 存储选择的项目详情
list: [],
filteredList: [],
loading: false,
finished: false,
allDataCache: {}, // 缓存格式: { "2025/10/13": [item1, item2, ...] }
typeSelection: "1", // 1: 套餐, 2: 单项
showCartPopup: false, // 控制预约列表弹窗显示
checkedItems: [], // 控制弹窗中选择的项目
};
},
created() {
@@ -98,40 +217,111 @@ export default {
},
activated() {
const apiDate = this.formatDateForAPI(this.same_day);
if (this.allDataCache[apiDate]) {
this.displayData(this.allDataCache[apiDate]);
} else {
this.fetchDataForDate(this.same_day);
}
if (this.allDataCache[apiDate + '_' + this.typeSelection]) {
this.displayData(this.allDataCache[apiDate + '_' + this.typeSelection]);
} else {
this.fetchDataForDate(this.same_day);
}
},
methods: {
toggleSelection(itemId) {
const index = this.selectedItems.indexOf(itemId);
if (index > -1) {
this.selectedItems.splice(index, 1);
this.selectedItemsDetails = this.selectedItemsDetails.filter(item => item.id !== itemId);
} else {
this.selectedItems.push(itemId);
const itemDetails = this.list.find(item => item.id === itemId);
if (itemDetails) {
this.selectedItemsDetails.push(itemDetails);
}
}
// 同步到弹窗的选择状态
this.checkedItems = [...this.selectedItems];
},
makeAppointment() {
// 打开预约列表弹窗
openCartPopup() {
if (this.selectedItems.length === 0) {
Toast('请先选择项目');
return;
}
this.showCartPopup = true;
},
const selectedItemsInfo = this.list.filter(item =>
this.selectedItems.includes(item.id)
// 关闭预约列表弹窗
closeCartPopup() {
this.showCartPopup = false;
},
// 处理弹窗中的选择变化
handlePopupSelectionChange(checkedIds) {
this.checkedItems = checkedIds;
},
// 全选功能
selectAll() {
if (this.checkedItems.length === this.selectedItems.length) {
// 如果已经全选,则取消全选
this.checkedItems = [];
Toast.success('已取消全选');
} else {
// 全选所有项目
this.checkedItems = [...this.selectedItems];
Toast.success('已全选');
}
},
// 删除已选项功能
deleteSelected() {
if (this.checkedItems.length === 0) {
Toast('请先选择要删除的项目');
return;
}
// 保存要删除的项目数量
const deletedCount = this.checkedItems.length;
// 删除选中的项目
this.selectedItems = this.selectedItems.filter(id =>
!this.checkedItems.includes(id)
);
this.selectedItemsDetails = this.selectedItemsDetails.filter(item =>
!this.checkedItems.includes(item.id)
);
// 清空选择状态
this.checkedItems = [];
// 如果没有项目了,关闭弹窗
if (this.selectedItems.length === 0) {
this.closeCartPopup();
}
Toast.success(`已删除 ${deletedCount} 个项目`);
},
// 确认预约
makeAppointment() {
if (this.checkedItems.length === 0) {
Toast('请先在弹窗中选择要预约的项目');
return;
}
// 只提交弹窗中勾选的项目
const selectedForAppointment = this.selectedItemsDetails.filter(item =>
this.checkedItems.includes(item.id)
);
this.$router.push({
path: 'Zstj_detail',
query: {
items: JSON.stringify(selectedItemsInfo),
items: JSON.stringify(selectedForAppointment),
seldate: this.same_day
}
});
Toast.success(`已选择 ${this.selectedItems.length} 个项目进行预约`);
this.closeCartPopup();
Toast.success(`已选择 ${selectedForAppointment.length} 个项目进行预约`);
},
handleSearch() {
@@ -186,14 +376,15 @@ export default {
timeSlelct(item) {
this.same_day = item.date;
this.selectedItems = [];
this.searchKeyword = "";
this.list = [];
this.filteredList = [];
const apiDate = this.formatDateForAPI(this.same_day);
if (this.allDataCache[apiDate]) {
this.displayData(this.allDataCache[apiDate]);
const cacheKey = apiDate + '_' + this.typeSelection;
if (this.allDataCache[cacheKey]) {
this.displayData(this.allDataCache[cacheKey]);
} else {
this.fetchDataForDate(this.same_day);
}
@@ -210,11 +401,13 @@ export default {
const res = await apiOpTiQuery({
startDate: apiDate,
endDate: apiDate,
HospitalZone: ""
HospitalZone: "",
Type: this.typeSelection
});
const data = res.data?.data || [];
this.allDataCache[apiDate] = data; // 缓存当天数据
console.log(data);
this.allDataCache[apiDate + '_' + this.typeSelection] = data; // 缓存当天数据和类型
this.displayData(data);
} catch (err) {
console.error("请求失败:", err);
@@ -232,12 +425,29 @@ export default {
name: item.category,
price: item.price,
explain: item.program_name,
description:item.description,
type: this.typeSelection// 添加类型标识
}));
this.filteredList = [...this.list];
this.finished = true; // 一次性加载完成
},
handleTypeChange() {
// 切换类型时重新加载数据
this.list = [];
this.filteredList = [];
this.finished = false;
this.loading = false;
const apiDate = this.formatDateForAPI(this.same_day);
if (this.allDataCache[apiDate + '_' + this.typeSelection]) {
this.displayData(this.allDataCache[apiDate + '_' + this.typeSelection]);
} else {
this.fetchDataForDate(this.same_day);
}
},
formatDateForAPI(dateStr) {
const [year, month, day] = dateStr.split('-').map(Number);
return `${year}/${String(month).padStart(2, '0')}/${String(day).padStart(2, '0')}`;
@@ -281,6 +491,41 @@ ul.timeSlelct {
}
}
/* 类型选择样式 */
.typeSelect {
display: flex;
justify-content: center;
background: white;
padding: 10px;
position: fixed;
top: 4.2rem;
left: 0;
width: 100%;
z-index: 9;
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.05);
}
.typeSelect div {
flex: 1;
max-width: 200px;
text-align: center;
padding: 12px;
margin: 0 5px;
border-radius: 25px;
background: #f5f5f5;
cursor: pointer;
transition: all 0.3s;
font-weight: bold;
font-size: 24px;
}
.typeSelect div.active {
background: #46c3b0;
color: white;
transform: translateY(-1px);
box-shadow: 0 3px 10px rgba(70, 195, 176, 0.3);
}
.bj {
background: #f5f5f5;
position: fixed;
@@ -330,7 +575,7 @@ ul.timeSlelct {
}
.zstj_tc1 {
margin-top: 120px;
margin-top: 25px;
padding: 30px 0px;
padding-bottom: 100px;
}
@@ -410,10 +655,10 @@ ul.timeSlelct {
.container-wrapper {
position: fixed;
top: 2.4rem;
top: 4.6rem;
left: 0;
right: 0;
bottom: 0;
bottom: 1.5rem;
overflow: hidden;
}
@@ -423,37 +668,137 @@ ul.timeSlelct {
background: #f5f5f5;
}
.bottom-actions {
/* 预约列表按钮样式 */
.cart-button-container {
position: fixed;
bottom: 0;
left: 0;
right: 0;
background: white;
padding: 15px;
box-shadow: 0 -2px 10px rgba(0, 0, 0, 0.1);
bottom: 0.6rem;
left: 50%;
transform: translateX(-50%);
z-index: 100;
}
.action-buttons {
.cart-button {
display: flex;
align-items: center;
justify-content: center;
padding: 0 15px;
background: linear-gradient(135deg, #46c3b0 0%, #3aa897 100%);
color: white;
padding: 15px 30px;
border-radius: 50px;
box-shadow: 0 5px 20px rgba(70, 195, 176, 0.3);
cursor: pointer;
transition: all 0.3s;
font-weight: bold;
font-size: 24px;
position: relative;
}
.btn-appointment {
width: 80%;
max-width: 500px;
height: 80px;
border: none;
border-radius: 40px;
.cart-button:hover {
transform: translateY(-3px);
box-shadow: 0 8px 25px rgba(70, 195, 176, 0.4);
}
.cart-button:active {
transform: translateY(-1px);
}
.cart-button.empty {
background: #f5f5f5;
color: #666;
box-shadow: 0 3px 10px rgba(0, 0, 0, 0.1);
}
.cart-button.empty:hover {
background: #e8e8e8;
}
.cart-icon {
font-size: 32px;
margin-right: 10px;
}
.cart-count {
position: absolute;
top: -10px;
right: -10px;
background: #ff4d4f;
color: white;
border-radius: 50%;
width: 30px;
height: 30px;
display: flex;
align-items: center;
justify-content: center;
font-size: 18px;
font-weight: bold;
}
/* 预约列表弹窗样式 */
.cart-popup {
height: 100%;
display: flex;
flex-direction: column;
padding: 20px;
}
.cart-popup-header {
display: flex;
justify-content: space-between;
align-items: center;
margin-bottom: 20px;
padding-bottom: 15px;
border-bottom: 1px solid #eee;
}
.cart-popup-header h3 {
margin: 0;
font-size: 28px;
font-weight: bold;
background-color: #46c3b0;
color: white;
transition: all 0.3s;
}
.btn-appointment:active {
background-color: #3aa897;
.cart-popup-content {
flex: 1;
overflow-y: auto;
margin-bottom: 20px;
}
.item-explain {
font-size: 20px;
color: #666;
margin-top: 5px;
}
.cart-popup-footer {
padding-top: 20px;
padding-bottom: calc(20px + env(safe-area-inset-bottom) + env(safe-area-inset-bottom) / 2);
padding-bottom: calc(20px + constant(safe-area-inset-bottom) + constant(safe-area-inset-bottom) / 2);
border-top: 1px solid #eee;
}
.cart-popup-actions {
display: flex;
justify-content: space-between;
margin-bottom: 20px;
}
.appointment-btn {
height: 80px;
font-size: 28px;
font-weight: bold;
}
/* Vant组件样式覆盖 */
.van-popup {
padding-top: 0 !important;
/* 确保弹窗底部适配安全区域 */
padding-bottom: env(safe-area-inset-bottom) !important;
padding-bottom: constant(safe-area-inset-bottom) !important;
}
/* 为iOS设备添加额外的安全区域适配 */
@supports (padding-bottom: env(safe-area-inset-bottom)) {
.cart-popup {
padding-bottom: env(safe-area-inset-bottom) !important;
}
}
</style>