From 0067a6a3c15d99b655c320d843c9292f2e5475c7 Mon Sep 17 00:00:00 2001
From: "@xiao-xiao0105" <1097449274@qq.com>
Date: Fri, 6 Nov 2026 13:36:54 +0800
Subject: [PATCH] =?UTF-8?q?=E4=BF=AE=E6=94=B9=E9=A2=84=E7=BA=A6=E7=9B=B8?=
=?UTF-8?q?=E5=85=B3=E5=8A=9F=E8=83=BD?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
pages/book/book.vue | 193 ++++++-----
pages/book/bookinfo.vue | 19 +-
pages/book/booklist.vue | 21 +-
pages/book/bookteacher.vue | 3 +
pages/chatbox/im-user-info.vue | 50 +--
pages/components/member-card-scroll.vue | 36 +-
pages/components/member-card.vue | 16 +-
pages/user/cardDetail.vue | 2 +-
pages/user/courselist.vue | 7 +-
pages/user/mycourseinfo.vue | 420 +++++++++++++++++++++---
pages/user/user.vue | 116 ++-----
11 files changed, 588 insertions(+), 295 deletions(-)
diff --git a/pages/book/book.vue b/pages/book/book.vue
index a9d4771..8f14758 100644
--- a/pages/book/book.vue
+++ b/pages/book/book.vue
@@ -10,7 +10,7 @@
-
+
@@ -51,8 +51,8 @@
-
-
+
+
@@ -73,46 +73,53 @@
-
-
- {{ currentCourse.courseName }}
-
- 需扣 {{ currentCourse.deductType === 'count'
- ? currentCourse.deductCount + '次'
- : '¥' + currentCourse.deductAmount }}
-
+
+
+ 无对应会员卡可使用
+
+
+
+
+ {{ item.courseName}}
+
+ 需扣 {{ selectedCard.memberChargeType === 'total_fee'
+ ? '¥' + selectedCard.chargeFee
+ : selectedCard.chargeCnt + '次'}}
+
+
+
+
+ 本次使用卡片:
+
+ {{ effectiveCardName }}
+
+ 默认
+
-
-
- 本次使用卡片:
-
- {{ effectiveCardName }}
-
- 默认
+
+
+
+
+
-
-
-
-
+
+
@@ -135,31 +142,27 @@ export default {
userid: "",
id: "",
item: {
- courseTimeId: 1935590320322428931,
- claName: "普拉提A班",
- courseName: "普拉提",
- storeName: "慢瑜伽-三台子店",
+ courseTimeId: null,
+ claName: "",
+ courseName: "",
+ storeName: "",
pic: null,
- claDate: "2025-10-01",
- weekDay: "星期二",
- startTime: "08:00",
- endTime: "09:30",
- staffName: "冉洪涛老师",
- studentCount: 1,
+ claDate: "",
+ weekDay: "",
+ startTime: "",
+ endTime: "",
+ staffName: "",
+ studentCount: null,
roomName: null,
- claColor: "#409EFF",
- claTimeStatus: "1",
- bookAttendCnt: "1",
- atClassCnt: "5",
- lessCnt: "3"
+ claColor: "",
+ claTimeStatus: "",
+ bookAttendCnt: "",
+ atClassCnt: "",
+ lessCnt: ""
},
remark: null,
memberCards: [],
currentCourse: {
- courseName: '普拉提A班',
- deductType: 'COUNT',
- deductCount: 1,
- deductAmount: 0
},
defaultCardId: null,
// ✅ 用户手动选中的卡(父组件持有)
@@ -210,9 +213,9 @@ export default {
isCardUsable(card) {
if (!card) return false;
if (card.status && card.status !== 'ACTIVE') return false;
- if (card.expireDate) {
+ if (card.expiryDate) {
const now = new Date();
- const expire = new Date(card.expireDate.replace(/-/g, '/'));
+ const expire = new Date(card.expiryDate.replace(/-/g, '/'));
if (now > expire) return false;
}
const type = this.currentCourse.deductType;
@@ -235,15 +238,19 @@ export default {
// ✅ 打开弹窗:重置手动选择,用默认卡
async openCardSelect(item) {
var user = myCache('userInfo');
+ item.visitStore=user.visitStore;
+ console.log('item',item)
const { data: memberCards } =
await uni.$http.post("/api/memberCard/getMemberCardListByCourseTimeId",
- {visitStore:user.visitStore,
- courseId:item.courseId
- });
- console.log("memberCards",memberCards)
+ item);
//如果为空 则没有适合的卡片
this.memberCards = memberCards.data
- this.selectedCard = null;
+ console.log('this.memberCards',this.memberCards)
+ if(this.memberCards&&this.memberCards.length > 0){
+ this.selectedCard = this.memberCards[0];
+ }else{
+ this.selectedCard = null;
+ }
this.$refs.cardPopup.open();
},
@@ -252,37 +259,53 @@ export default {
},
async confirmSelect() {
- // ✅ 直接从父组件 computed 拿有效卡
const card = this.effectiveCard;
if (!card) {
uni.showToast({ title: '无可用会员卡', icon: 'none' });
return;
}
- const { data: res } = await uni.$http.post('/api/course/bookCourse', {
- courseTimeId: this.item.courseTimeId,
- cardId: card.id
+ // 开启loading
+ uni.showLoading({
+ title: '预约中...',
+ mask: true // 遮罩,防止重复点击
});
- if (res && res.success) {
- myCache('courserefresh', 1);
- uni.showModal({
- title: '提示',
- content: '课程已预约!',
- cancelText: '返回',
- confirmText: '确定',
- success: ress => {
- uni.navigateBack({ delta: 1 });
- }
+ try {
+ const { data: res } = await uni.$http.post('/api/course/bookCourse', {
+ courseTimeId: this.item.courseTimeId,
+ memberCardId: card.memberCardId,
+ memberChargeType: this.selectedCard.memberChargeType,
+ chargeCnt: this.selectedCard.chargeCnt,
+ chargeFee: this.selectedCard.chargeFee
});
- } else {
- uni.showModal({
- title: '提示',
- content: res.message ? res.message : '课程预约失败!',
- cancelText: '取消',
- confirmText: '确定'
+ if (res && res.success) {
+ myCache('courserefresh', 1);
+ this.closeCardSelect();
+ this.$refs.uToast.show({
+ title: '课程预约成功,请到 我的预约-预约中 查看',
+ type: 'success',
+ duration: 2000
+ });
+ } else {
+ this.$refs.uToast.show({
+ title: res.message ? res.message : '课程预约失败!',
+ type: 'error',
+ duration: 2000
+ });
+ }
+ } catch (err) {
+ // 网络异常捕获
+ this.$refs.uToast.show({
+ title: '预约请求异常,请稍后重试',
+ type: 'error',
+ duration: 2000
});
+ } finally {
+ // 不管成功失败、报错,都关闭loading
+ uni.hideLoading();
}
},
+
formatTime(timeStr) {
return timeStr.slice(0, 5);
},
@@ -819,5 +842,11 @@ export default {
border: none;
&::after { border: none; }
}
+ .empty-tip {
+ padding: 60rpx 20rpx;
+ text-align: center;
+ font-size: 28rpx;
+ color: #999;
+ }
diff --git a/pages/book/bookinfo.vue b/pages/book/bookinfo.vue
index 76511c6..b865925 100644
--- a/pages/book/bookinfo.vue
+++ b/pages/book/bookinfo.vue
@@ -23,19 +23,24 @@
预约状态:
- 教练确认
+ 预约中
预约中
- 待上课
+ 预约成功,待上课
已完成
已取消
+
+ 签到状态:
+ 已签到
+ 未签到
+
授课教练:
{{info.teacherName }}
上课教室:
- {{info.roomName }}
+ {{info.roomName?info.roomName:'待定'}}
上课时间:
@@ -168,7 +173,7 @@
this.id=options.id;
this.getinfo();
}
-
+
// 设置app角标
this.setBadge();
},
@@ -187,13 +192,13 @@
// 设置app角标
setBadge() {
var count = myCache("massageCount")?myCache("massageCount"):-1;
- if (count > 0) {
+ if (count > 0) {
// app清除角标的数量
//#ifdef APP-PLUS
plus.runtime.setBadgeNumber(count);
//#endif
-
- } else {
+
+ } else {
// app清除角标的数量
clearBadgeNumber();
}
diff --git a/pages/book/booklist.vue b/pages/book/booklist.vue
index 59090d4..9747bac 100644
--- a/pages/book/booklist.vue
+++ b/pages/book/booklist.vue
@@ -19,11 +19,13 @@
- 教练确认
+
+ 预约中
预约中
- 待上课
+ 预约成功,待上课
已完成
已取消
+ 预约失败
@@ -35,7 +37,8 @@
{{item.courseName}} {{item.claName}}
教练:{{item.teacherName || '-'}}
上课时间:{{ item.claDate+' '+item.startTime+'-'+item.endTime}}
- 教室:{{item.roomName}}
+ 教室:{{item.roomName?item.roomName:'待定'}}
+ 使用会员卡号:{{item.cardNo}}
@@ -49,7 +52,7 @@
-
+
@@ -677,7 +680,7 @@ import { mapState, mapGetters, mapActions } from 'vuex';
// 取消预约
cancelyydo(e){
console.log(e);
- var id= e.currentTarget.dataset.id;
+ // var id= e.currentTarget.dataset.id;
var that = this;
//取消预约
uni.showModal({
@@ -687,16 +690,14 @@ import { mapState, mapGetters, mapActions } from 'vuex';
confirmText: '确定',
success: ress => {
if (ress.confirm) {
- that.delyydo(id);
+ that.delyydo(e);
}
}
});
},
// 取消预约
- async delyydo(id){
- var param={
- "courseTimeId":id
- };
+ async delyydo(e){
+ var param=e;
uni.showToast({
title: '取消中...',
icon: 'success',
diff --git a/pages/book/bookteacher.vue b/pages/book/bookteacher.vue
index 13aa2f3..73d1244 100644
--- a/pages/book/bookteacher.vue
+++ b/pages/book/bookteacher.vue
@@ -12,10 +12,12 @@
性别:{{item.sex==2?'男':(item.sex==1?'女':'未知')}}
电话:{{item.phone?item.phone:'-'}}
+ 会员卡号:{{item.cardNo?item.cardNo:'-'}}
+
教练确认
预约中
待上课
@@ -139,6 +141,7 @@
// 全部
this.loadStatus="noMore";
this.list=res.data;
+ console.log('this.list',this.list)
this.$forceUpdate();
}
else{
diff --git a/pages/chatbox/im-user-info.vue b/pages/chatbox/im-user-info.vue
index 91f9ebb..a3ed2e1 100644
--- a/pages/chatbox/im-user-info.vue
+++ b/pages/chatbox/im-user-info.vue
@@ -8,16 +8,6 @@
ID:{{ userInfo.id || userInfo.userId || '-' }}
-
-
-
-
-
-
-
-
-
-
加入黑名单
@@ -84,45 +74,7 @@ export default {
console.error('查询黑名单状态失败', e)
}
},
- /**
- * switch点击,不直接改状态,弹出确认弹窗
- */
- onBlackSwitchChange(e) {
- // e.detail.value 是用户想要切换到的目标状态
- const targetStatus = e.detail.value
- const title = targetStatus ? '加入黑名单' : '取消黑名单'
- const content = targetStatus
- ? '加入黑名单后,对方将无法给你发送消息,确定?'
- : '确定将该用户移出黑名单?'
-
- uni.showModal({
- title,
- content,
- success: async (res) => {
- if (!res.confirm) {
- // 用户点取消,不做任何操作,switch会自动回弹回旧状态,无需手动赋值
- return
- }
- try {
- const url = targetStatus ? '/api/blacklist/add?targetUid=' : '/api/blacklist/cancel?targetUid='
- await uni.$http.post(`${url}${this.userId}`)
- // 接口成功才更新本地状态
- this.isBlacked = targetStatus
- uni.showToast({
- title: this.isBlacked ? '已加入黑名单' : '已取消黑名单',
- icon: 'none'
- })
- } catch (err) {
- uni.showToast({ title: '操作失败', icon: 'none' })
- }
- }
- })
- },
onSendMessage() {
- // if (this.isBlacked) {
- // uni.showToast({ title: '你已将对方加入黑名单', icon: 'none' })
- // return
- // }
let chat = {
type: 'PRIVATE',
targetId: this.userId,
@@ -190,7 +142,7 @@ export default {
onBackPress(e) {
// 来源是左上角返回 / 安卓返回键
if(e.from === 'backbutton'){
- if(this.isBlacked){
+ if(this.isBlacked && this.chatIndex){
// 拉黑成功,自定义跳转chat
this.goBackChat()
return true // return true 阻止原生默认返回
diff --git a/pages/components/member-card-scroll.vue b/pages/components/member-card-scroll.vue
index 9a09413..61a5d35 100644
--- a/pages/components/member-card-scroll.vue
+++ b/pages/components/member-card-scroll.vue
@@ -1,7 +1,7 @@
- 正常
+ 正常
{{ getUnusableReason(card) }}
@@ -99,15 +99,20 @@ export default {
},
// 动态计算首尾 padding
innerStyle() {
- if (!this.center) {
+ // ✅ 只要卡片总数=1,不管外部center参数传啥,自动触发居中计算
+ const isSingleCard = this.cards && this.cards.length === 1;
+ if (!this.center && !isSingleCard) {
+ // 多卡正常:保留原来的20rpx边距
return { paddingLeft: '20rpx', paddingRight: '20rpx' };
}
+ // 居中计算:左右padding = (屏幕宽度750rpx - 卡片宽度) / 2,刚好把卡片推到正中间
const padding = Math.max(0, (this.screenWidthRpx - this.cardWidthRpx) / 2);
return {
- paddingLeft: padding + 'rpx',
+ paddingLeft: padding-30 + 'rpx',
paddingRight: padding + 'rpx'
};
}
+
},
watch: {
cards: {
@@ -183,9 +188,9 @@ export default {
if (!card) return false;
// ✅ 只有 ACTIVE 才可用
if (card.status && card.status !== 'ACTIVE') return false;
- if (card.expireDate) {
+ if (card.expiryDate) {
const now = new Date();
- const expire = new Date(card.expireDate.replace(/-/g, '/'));
+ const expire = new Date(card.expiryDate.replace(/-/g, '/'));
if (now > expire) return false;
}
if (card.type === 'count') {
@@ -214,9 +219,9 @@ export default {
if (card.status && card.status == 'DEPLETED') {
return '卡片额度已用完';
}
- if (card.expireDate) {
+ if (card.expiryDate) {
const now = new Date();
- const expire = new Date(card.expireDate.replace(/-/g, '/'));
+ const expire = new Date(card.expiryDate.replace(/-/g, '/'));
if (now > expire) return '卡片已过期';
}
if (card.type === 'count') {
@@ -231,7 +236,7 @@ export default {
return '不可用';
},
- // 对外方法:获取有效卡(用于提交预约)
+ // 对外方法:获取有效卡(用于提交预约)
getEffectiveCard() {
return this.effectiveCard;
},
@@ -299,4 +304,17 @@ export default {
background: #00a89b;
}
}
+.card-scroll-wrap {
+ width: 100%;
+ overflow-x: auto;
+ padding: 20rpx 0;
+ /* 多卡时默认左对齐横向滚动 */
+ display: flex;
+ gap: 20rpx;
+}
+
+
+
+
+
diff --git a/pages/components/member-card.vue b/pages/components/member-card.vue
index 027fa19..182eadb 100644
--- a/pages/components/member-card.vue
+++ b/pages/components/member-card.vue
@@ -21,22 +21,28 @@
- {{ card.chargeType === 'count' ? '剩余次数' : card.chargeType ==='days'?'剩余天数':'卡内余额' }}
+ {{ card.chargeType === 'count' ? '剩余次数' : card.chargeType ==='days'?'剩余天数':'可用余额' }}
¥
- {{ card.chargeType === 'count' ? (card.remainingCount || 0) : card.chargeType ==='days'?card.remainingDays: formatAmount(card.remainingTotalFee) }}
+ {{
+ card.chargeType === 'count'
+ ? Math.max((card.remainingCount || 0) - (card.freezeCount || 0), 0)
+ : card.chargeType === 'days'
+ ? (card.remainingDays || 0)
+ : formatAmount( Math.max( (Number(card.remainingTotalFee)||0) - (Number(card.freezeAmount)||0), 0 ) )
+ }}
次
天
-
+
预约占用
- {{ card.type === 'count' ? card.frozenCount + '次' : '¥' + formatAmount(card.frozenAmount) }}
+ {{ card.type === 'count' ? card.freezeCount + '次' : '¥' + formatAmount(card.freezeAmount) }}
@@ -45,7 +51,7 @@
NO. {{ card.cardNo || '--' }}
- {{ card.expireDate ? '有效期至 ' + card.expireDate : '长期有效' }}
+ {{ card.expiryDate ? '有效期至 ' + card.expiryDate : '长期有效' }}
diff --git a/pages/user/cardDetail.vue b/pages/user/cardDetail.vue
index e9111f4..7eef243 100644
--- a/pages/user/cardDetail.vue
+++ b/pages/user/cardDetail.vue
@@ -74,7 +74,7 @@
有效期至
- {{ card.expireDate || '长期有效' }}
+ {{ card.expiryDate || '长期有效' }}
状态
diff --git a/pages/user/courselist.vue b/pages/user/courselist.vue
index 333e8f5..8509509 100644
--- a/pages/user/courselist.vue
+++ b/pages/user/courselist.vue
@@ -56,11 +56,12 @@
-
+
- {{item.courseName}}
+ {{item.courseName}}
+
@@ -74,7 +75,7 @@
- {{item.roomName}}
+ {{item.roomName?item.roomName:'教室待定'}}
diff --git a/pages/user/mycourseinfo.vue b/pages/user/mycourseinfo.vue
index c2b5c7f..c085f4c 100644
--- a/pages/user/mycourseinfo.vue
+++ b/pages/user/mycourseinfo.vue
@@ -1,29 +1,31 @@
-
+
-
+
-
+
- {{item.courseName}}
+ {{item.courseName}}
+
- {{item.startTime+'-'+item.endTime}}
+ {{formatTime(item.startTime)+'-'+formatTime(item.endTime)}}
-
+
+ {{item.courseTypeName}}
{{item.courseTypeName}}
{{item.courseTypeName}}
-
+
@@ -49,24 +51,34 @@
- 预约人数{{item.lessCnt}}人
+ 满{{item.lessCnt}}人开课
+
+
+ 未上课
+ 已确认上课
+
-
-
-
+
+
+
-
+
学员名单
+
+ 可签到 {{ checkableList.length }} 人
+
+
学员姓名
性别
电话
预约状态
+ 是否签到
@@ -74,7 +86,7 @@
{{item.studentName}}
- {{item.sex=1?'女':(item.sex=2?'男':'未知')}}
+ {{item.sex==2?'男':(item.sex==1?'女':'未知')}}
{{item.phone}}
@@ -82,16 +94,69 @@
{{ retstr(item.bookStatus)}}
+
+ {{ item.checkIn=='1'?'已签到':'未签到'}}
+
-
+
-
+
+
+
+
+ 批量签到
+ 已选 {{ selectedIds.length }} / {{ checkableList.length }} 人
+
+
+
+
+ ✓
+
+
+ 全选
+
+
+
+
+
+
+
+ ✓
+
+
+ {{ stu.studentName }}
+ {{ stu.phone }} · {{ retstr(stu.bookStatus) }}
+
+
+
+ 暂无可签到学员
+
+
+
+
+
+
+
+
+
+
-
-
+
+
@@ -150,9 +215,24 @@
name3:"年卡",
name4:"3390",
},
- ]
+ ],
+ batchVisible: false, // 弹窗开关
+ selectedIds: [], // 已勾选的 bookId
+ submitting: false // 防重复提交
};
},
+ computed: {
+ // 可签到数据:bookStatus ∈ [0,1,2] 且 checkIn === 0
+ checkableList() {
+ return (this.studentlist || []).filter(stu => this.isCheckable(stu));
+ },
+ // 是否全选
+ isAllSelected() {
+ return this.checkableList.length > 0 &&
+ this.selectedIds.length === this.checkableList.length;
+ }
+ },
+
onLoad(options) {
// 课程详情
if(options.id){
@@ -173,11 +253,19 @@
}
},
methods: {
+ formatTime(timeStr) {
+ // 假设 timeStr 格式为 "HH:MM:SS"
+ return timeStr.slice(0, 5); // 取前5位 "HH:MM"
+ },
retstr(val){
// 描述:0->预约中;1->教练确认;2->店长确认/预约成功/待上课 3->已取消;4->已完成/待评价;
if(val=='0'){
return '预约中';
}
+ else if (val == '1')
+ {
+ return '教练确认';
+ }
else if(val=='2'){
return '待上课 ';
}
@@ -242,15 +330,18 @@
uni.showLoading({
title: '数据加载中...'
});
- const {data: res} = await uni.$http.post('/api/my/courseTimeDetail', {courseTimeId:this.id});
- if(res&&res.data){
- var data=res.data;
- // 信息
- this.item=data.courseDetail;
- this.studentlist=data.studentList;
- this.loadStatus='noMore';
- this.$forceUpdate();
- }
+ try {
+ const { data: res } = await uni.$http.post('/api/my/courseTimeDetail', { courseTimeId: this.id });
+ if (res && res.data) {
+ var data = res.data;
+ this.item = data.courseDetail;
+ this.studentlist = data.studentList;
+ this.loadStatus = 'noMore';
+ this.$forceUpdate();
+ }
+ } finally {
+ uni.hideLoading(); // ← 关键
+ }
},
gotoorder(){
var that = this;
@@ -271,7 +362,7 @@
async orderdodo(){
var param={
"courseTimeId": this.item.courseTimeId,
- "startTime": this.item.startTime,
+ "startTime": this.item.startTime,
"endTime": this.item.endTime
};
uni.showToast({
@@ -280,7 +371,8 @@
duration: 2000
});
const {data: res} = await uni.$http.post('/api/my/confirmClass', param);
- if(res.msg=="successed"){
+ console.log(res)
+ if(res.success=="true"){
uni.showToast({
title: '已确定上课!',
icon: 'success',
@@ -295,14 +387,115 @@
}
else{
uni.showToast({
- title: res.msg? res.msg:'确定上课失败!',
- icon: 'error',
+ title: res.message? res.message:'确定上课失败!',
+ icon: 'none',
duration: 2000
});
}
},
-
- }
+
+ // 取预约记录主键(兼容 bookId / id 两种字段名)
+ getBookId(stu) {
+ return stu.bookId || stu.id;
+ },
+
+// 是否可签到
+ isCheckable(stu) {
+ if (!stu) return false;
+ const rawStatus = stu.bookStatus;
+ if (rawStatus === null || rawStatus === undefined || rawStatus === '') return false;
+ const status = Number(rawStatus);
+ const checkIn = Number(stu.checkIn === null || stu.checkIn === undefined || stu.checkIn === '' ? 0 : stu.checkIn);
+ return [0, 1, 2].includes(status) && checkIn === 0;
+ },
+
+// 是否已勾选
+ isChecked(stu) {
+ return this.selectedIds.includes(this.getBookId(stu));
+ },
+
+// 打开弹窗(默认全选)
+ openBatch() {
+ if (this.checkableList.length === 0) {
+ uni.showToast({ title: '暂无可签到学员', icon: 'none' });
+ return;
+ }
+ this.selectedIds = this.checkableList.map(stu => this.getBookId(stu));
+ this.batchVisible = true;
+ },
+
+// 关闭弹窗
+ closeBatch() {
+ if (this.submitting) return;
+ this.batchVisible = false;
+ },
+
+// 全选/取消全选
+ toggleAll() {
+ if (this.isAllSelected) {
+ this.selectedIds = [];
+ } else {
+ this.selectedIds = this.checkableList.map(stu => this.getBookId(stu));
+ }
+ },
+
+// 单选切换
+ toggleOne(stu) {
+ const id = this.getBookId(stu);
+ const idx = this.selectedIds.indexOf(id);
+ if (idx > -1) {
+ this.selectedIds.splice(idx, 1);
+ } else {
+ this.selectedIds.push(id);
+ }
+ },
+
+// 提交批量签到
+ async doBatchCheckIn() {
+ if (this.submitting) return;
+ if (this.selectedIds.length === 0) {
+ uni.showToast({ title: '请至少勾选一名学员', icon: 'none' });
+ return;
+ }
+
+ const submitCount = this.selectedIds.length;
+ const bookIds = this.selectedIds.slice();
+
+ this.submitting = true;
+ uni.showLoading({ title: '提交中...', mask: true });
+
+ try {
+ const { data: res } = await uni.$http.post('/api/my/batchCheckIn', {
+ bookIds: bookIds
+ });
+
+ if (res && (res.success === true || res.success === 'true')) {
+ this.batchVisible = false;
+ this.selectedIds = [];
+ myCache('courserefresh', 1);
+ uni.showToast({
+ title: `已签到 ${submitCount} 人`.trim() || '签到成功',
+ icon: 'success',
+ duration: 2000
+ });
+ // 刷新名单
+ await this.getinfo();
+ } else {
+ uni.showToast({
+ title: (res && res.msg) ? res.msg : '批量签到失败!',
+ icon: 'none',
+ duration: 2500
+ });
+ }
+ } catch (e) {
+ uni.showToast({ title: '签到请求异常,请稍后重试', icon: 'none', duration: 2500 });
+ } finally {
+ uni.hideLoading();
+ this.submitting = false;
+ }
+ }
+
+ }
}
@@ -385,7 +578,7 @@
}
}
}
-
+
.oscon{
background-color: #f3fafa;
border-radius: 16rpx;
@@ -426,7 +619,7 @@
}
}
}
-
+
.oinfo{
padding:20rpx;
position: relative;
@@ -439,7 +632,7 @@
padding: 20rpx 20rpx;
}
}
-
+
.tcon{
display: flex;
flex-direction: column;
@@ -466,14 +659,14 @@
}
}
}
-
+
.red{
color:#ff3d0e;
}
.green{
color:#00cd00;
}
-
+
::v-deep.uni-radio-input-checked{
background-color: #00A99A !important;
border-color: #00A99A !important;
@@ -483,7 +676,7 @@
::v-deep.uni-radio-input-checked::before{
display: none!important;
}
-
+
.scell{
display: flex;
flex-wrap: wrap;
@@ -586,7 +779,7 @@
font-size: 26rpx;
color: #333;
margin-right: 10rpx;
- }
+ }
.txtbg3{
padding: 2rpx 15rpx;
border-radius: 30rpx;
@@ -670,6 +863,149 @@
}
}
}
-
-
+ /* ===== 批量签到入口 ===== */
+ .batch-bar {
+ display: flex;
+ align-items: center;
+ justify-content: space-between;
+ padding: 0 10rpx 16rpx;
+ }
+ .batch-tip {
+ font-size: 24rpx;
+ color: #999;
+ }
+ .batch-btn {
+ margin: 0;
+ height: 64rpx;
+ line-height: 64rpx;
+ padding: 0 30rpx;
+ font-size: 26rpx;
+ color: #fff;
+ background-color: #00A99A !important;
+ border-radius: 32rpx;
+ border: none;
+ }
+ .batch-btn::after {
+ border: none !important;
+ }
+
+ /* ===== 批量签到弹窗 ===== */
+ .batch-mask {
+ position: fixed;
+ left: 0;
+ top: 0;
+ right: 0;
+ bottom: 0;
+ background: rgba(0, 0, 0, 0.5);
+ z-index: 999;
+ display: flex;
+ align-items: center;
+ justify-content: center;
+ }
+ .batch-dialog {
+ width: 640rpx;
+ max-height: 72vh;
+ background: #fff;
+ border-radius: 20rpx;
+ display: flex;
+ flex-direction: column;
+ overflow: hidden;
+ }
+ .bd-title {
+ text-align: center;
+ font-size: 32rpx;
+ font-weight: 600;
+ color: #000;
+ padding: 30rpx 0 8rpx;
+ }
+ .bd-sub {
+ text-align: center;
+ font-size: 24rpx;
+ color: #999;
+ padding-bottom: 16rpx;
+ }
+ .bd-all,
+ .bd-item {
+ display: flex;
+ align-items: center;
+ padding: 22rpx 30rpx;
+ border-top: 1rpx solid #f2f2f2;
+ }
+ .cb {
+ width: 40rpx;
+ height: 40rpx;
+ border-radius: 50%;
+ border: 2rpx solid #c8c8c8;
+ display: flex;
+ align-items: center;
+ justify-content: center;
+ margin-right: 20rpx;
+ flex-shrink: 0;
+ box-sizing: border-box;
+ }
+ .cb.checked {
+ background: #00A99A;
+ border-color: #00A99A;
+ }
+ .cb-icon {
+ color: #fff;
+ font-size: 22rpx;
+ line-height: 1;
+ }
+ .bd-list {
+ max-height: 460rpx;
+ }
+ .bd-info {
+ flex: 1;
+ }
+ .bd-name {
+ font-size: 28rpx;
+ color: #333;
+ }
+ .bd-meta {
+ font-size: 24rpx;
+ color: #999;
+ margin-top: 6rpx;
+ }
+ .bd-empty {
+ text-align: center;
+ font-size: 26rpx;
+ color: #999;
+ padding: 80rpx 0;
+ }
+ .bd-btns {
+ display: flex;
+ padding: 20rpx 30rpx 30rpx;
+ }
+ .bd-cancel {
+ flex: 1;
+ margin: 0 20rpx 0 0;
+ height: 80rpx;
+ line-height: 80rpx;
+ font-size: 28rpx;
+ color: #666;
+ background: #f5f5f5 !important;
+ border-radius: 40rpx;
+ border: none;
+ }
+ .bd-confirm {
+ flex: 1;
+ margin: 0;
+ height: 80rpx;
+ line-height: 80rpx;
+ font-size: 28rpx;
+ color: #fff;
+ background: #00A99A !important;
+ border-radius: 40rpx;
+ border: none;
+ }
+ .bd-cancel::after,
+ .bd-confirm::after {
+ border: none !important;
+ }
+ .bd-confirm[disabled] {
+ opacity: 0.5;
+ }
+
+
diff --git a/pages/user/user.vue b/pages/user/user.vue
index 2716f30..481a2b5 100644
--- a/pages/user/user.vue
+++ b/pages/user/user.vue
@@ -13,20 +13,27 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+ 暂无会员卡
+
+
+
+
+
+
+
-
+
@@ -219,77 +226,7 @@
avatar:"../../static/image/logo.png",
roleId:[],
memberCards: [
- // 1. 次卡:正常,余额充足
- {
- id: 1001,
- cardNo: '88880001',
-
- chargeType: 'count',//收费模式 count:课时 days:时间 total_fee:储值
- cardName: '次卡',
- remainingCount: 8,
- frozenCount: 1,
- remainingTotalFee: 0,
- frozenAmount: 0,
- expireDate: '2027-12-31',
- status: 'ACTIVE'
- },
- // 2. 次卡:剩余次数不足(只剩1次)
- {
- id: 1002,
- type: 'COUNT',
- cardName: '次卡',
- name: '体验次卡',
- cardNo: '88880002',
- remainingCount: 1,
- frozenCount: 0,
- remainAmount: 0,
- frozenAmount: 0,
- expireDate: '2026-12-31',
- status: 'NORMAL'
- },
- // 3. 储值卡:余额充足
- {
- id: 1003,
- type: 'AMOUNT',
- cardName: '储值卡',
- name: '瑜伽储值卡',
- cardNo: '88880003',
- remainingCount: 0,
- frozenCount: 0,
- remainAmount: 1280.50,
- frozenAmount: 200.00,
- expireDate: '2028-06-30',
- status: 'NORMAL'
- },
- // 4. 储值卡:余额不足(只剩50元)
- {
- id: 1004,
- type: 'AMOUNT',
- cardName: '储值卡',
- name: '小额储值卡',
- cardNo: '88880004',
- remainingCount: 0,
- frozenCount: 0,
- remainAmount: 50.00,
- frozenAmount: 0,
- expireDate: '2027-01-01',
- status: 'NORMAL'
- },
- // 5. 已过期的次卡
- {
- id: 1005,
- type: 'COUNT',
- cardName: '次卡',
- name: '过期次卡',
- cardNo: '88880005',
- remainingCount: 5,
- frozenCount: 0,
- remainAmount: 0,
- frozenAmount: 0,
- expireDate: '2025-01-01', // 已过期
- status: 'NORMAL'
- }
],
favoritesnum:0,//我的收藏数量
menus: [
@@ -425,7 +362,7 @@
this.signature = user.signature?user.signature:this.signature;
this.roleId=user.roleId?user.roleId:[];
this.getmember();
-
+ this.getMemberCards();
// if(myCache("ifuserEdit"))
// {
// myCache("ifuserEdit",false)
@@ -1238,5 +1175,10 @@
align-items: center;
}
}
-
+ .empty-tip {
+ padding: 60rpx 20rpx;
+ text-align: center;
+ font-size: 28rpx;
+ color: #999;
+ }