Browse Source

修改移动端

master
王泽彦 9 months ago
parent
commit
95b011d176
  1. 16
      api/apiRoute.js
  2. 29
      common/axios.js
  3. 12
      common/util.js
  4. 6
      components/AQ/AQTabber.vue
  5. 6
      components/uni-nav-bar/uni-nav-bar.vue
  6. 2
      components/uni-popup/uni-popup.vue
  7. 75
      pages.json
  8. 293
      pages/coach/course/info_list.vue
  9. 9
      pages/coach/course/list.vue
  10. 413
      pages/coach/home/index.vue
  11. 566
      pages/coach/job/list.vue
  12. 17
      pages/coach/my/index.vue
  13. 625
      pages/coach/my/service_detail.vue
  14. 499
      pages/coach/student/student_detail.vue
  15. 216
      pages/coach/student/student_list.vue
  16. 58
      pages/coach/student/work_details.vue
  17. 1
      pages/market/clue/class_arrangement.vue
  18. 320
      pages/market/clue/class_arrangement_detail.vue
  19. 4
      pages/market/clue/clue_info.vue
  20. 190
      pages/market/clue/edit_clues.vue
  21. 33
      pages/market/data/statistics.vue
  22. 4
      pages/market/home/index.vue
  23. 4
      uni_modules/uni-calendar/components/uni-calendar/uni-calendar.vue
  24. 2
      uni_modules/uni-scss/styles/setting/_color.scss
  25. 2
      uni_modules/uni-scss/styles/setting/_variables.scss
  26. 2
      uni_modules/uni-scss/theme.scss
  27. 2
      uni_modules/uni-scss/variables.scss

16
api/apiRoute.js

@ -78,6 +78,18 @@ export default {
async getStatisticsInfo(data = {}) { async getStatisticsInfo(data = {}) {
return await http.get('/class/Statistics/info', data); return await http.get('/class/Statistics/info', data);
}, },
//获取服务详情
async getServiceDetail(data = {}) {
return await http.get('/service/detail', data);
},
//获取服务列表
async getServiceList(data = {}) {
return await http.get('/service/list', data);
},
//完成服务
async completeService(data = {}) {
return await http.post('/service/complete', data);
},
//添加作业 //添加作业
async jlPublishJob(data = {}) { async jlPublishJob(data = {}) {
return await http.get('/class/jlPublishJob/add', data); return await http.get('/class/jlPublishJob/add', data);
@ -359,7 +371,9 @@ export default {
async reimbursement_info(data = {}) { async reimbursement_info(data = {}) {
return await http.get('/personnel/reimbursement_info', data); return await http.get('/personnel/reimbursement_info', data);
}, },
async schedule_del(data = {}) {
return await http.post('/course/schedule_del', data);
}
} }

29
common/axios.js

@ -59,14 +59,33 @@ const responseInterceptor = (response) => {
} }
return data; return data;
} else if (data.code === 401) { } else if (data.code === 401) {
// 未授权或token过期 // 未授权或token过期,清除所有用户缓存信息
// 清除token
uni.removeStorageSync("token"); uni.removeStorageSync("token");
// 清除用户信息
uni.removeStorageSync("userInfo");
// 清除用户类型
uni.removeStorageSync("userType"); uni.removeStorageSync("userType");
// 清除用户角色
uni.removeStorageSync("userRoles");
// 清除过期时间
uni.removeStorageSync("expires_time"); uni.removeStorageSync("expires_time");
uni.showToast({ // 清除底部菜单选中状态
title: data.msg || '登录已过期,请重新登录', uni.removeStorageSync("tabBerIndex");
icon: 'none'
}); // 检查是否是从登录页退出的请求
const pages = getCurrentPages();
const currentPage = pages[pages.length - 1];
const isFromLoginPage = currentPage && currentPage.route && currentPage.route.includes('/pages/student/login/login');
// 如果不是从登录页退出的请求,才显示提示信息
if (!isFromLoginPage) {
uni.showToast({
title: data.msg || '登录已过期,请重新登录',
icon: 'none'
});
}
setTimeout(() => { setTimeout(() => {
uni.reLaunch({ uni.reLaunch({
url: '/pages/student/login/login?code=401' url: '/pages/student/login/login?code=401'

12
common/util.js

@ -209,11 +209,19 @@ function loginOut() {
uni.removeStorageSync('userInfo') uni.removeStorageSync('userInfo')
//清除用户类型 //清除用户类型
uni.removeStorageSync('userType') uni.removeStorageSync('userType')
//清除用户角色
uni.removeStorageSync('userRoles')
//清除过期时间
uni.removeStorageSync('expires_time')
//底部菜单选中 //底部菜单选中
uni.removeStorageSync('tabBerIndex') uni.removeStorageSync('tabBerIndex')
// 重置Vuex中的用户信息和登录状态
// 注意:在非组件环境中无法直接访问store,需要在组件中调用
// 这里不做store的更新,而是在组件中使用时更新
uni.navigateTo({ // 直接跳转到登录页,不显示任何提示信息
uni.reLaunch({
url: '/pages/student/login/login' url: '/pages/student/login/login'
}) })
} }

6
components/AQ/AQTabber.vue

@ -77,7 +77,7 @@
}, },
{ {
text: "数据", text: "数据",
urlPath: '/pages/market/data/index', // urlPath: '/pages/market/data/statistics', //
iconPath: util.img('/uniapp_src/static/images/tabbar/timetable.png'), iconPath: util.img('/uniapp_src/static/images/tabbar/timetable.png'),
selectedIconPath: util.img('/uniapp_src/static/images/tabbar/timetables.png'), selectedIconPath: util.img('/uniapp_src/static/images/tabbar/timetables.png'),
}, },
@ -104,8 +104,8 @@
selectedIconPath: util.img("/uniapp_src/static/images/tabbar/timetables.png") selectedIconPath: util.img("/uniapp_src/static/images/tabbar/timetables.png")
}, },
{ {
text: "班级", text: "我的学员",
urlPath: '/pages/coach/class/list', // urlPath: '/pages/coach/student/student_list', //
iconPath: util.img('/uniapp_src/static/images/tabbar/banji.png'), iconPath: util.img('/uniapp_src/static/images/tabbar/banji.png'),
selectedIconPath: util.img("/uniapp_src/static/images/tabbar/banjis.png") selectedIconPath: util.img("/uniapp_src/static/images/tabbar/banjis.png")
}, },

6
components/uni-nav-bar/uni-nav-bar.vue

@ -119,11 +119,11 @@
font-size: 34rpx; font-size: 34rpx;
/* #endif */ /* #endif */
/* #ifndef APP-PLUS */ /* #ifndef APP-PLUS */
font-size: $uni-font-size-lg; font-size: $font-size-lg;
/* #endif */ /* #endif */
} }
.uni-nav-bar-right-text { .uni-nav-bar-right-text {
font-size: $uni-font-size-base; font-size: $font-size-base;
} }
.uni-navbar { .uni-navbar {
@ -133,7 +133,7 @@
.uni-navbar__content { .uni-navbar__content {
position: relative; position: relative;
width: 750rpx; width: 750rpx;
background-color: $uni-bg-color; background-color: $bg-color;
overflow: hidden; overflow: hidden;
} }

2
components/uni-popup/uni-popup.vue

@ -222,7 +222,7 @@
bottom: 0; bottom: 0;
left: 0; left: 0;
right: 0; right: 0;
background-color: $uni-bg-color-mask; background-color: $bg-color-mask;
opacity: 0; opacity: 0;
} }

75
pages.json

@ -229,19 +229,12 @@
} }
}, },
{ {
"path": "pages/coach/home/index", "path": "pages/coach/home/index",
"style": { "style": {
"navigationBarTitleText": "首页", "navigationBarTitleText": "待办",
"navigationStyle": "custom", "navigationBarBackgroundColor": "#29d3b4",
"navigationBarBackgroundColor": "#fff", "navigationBarTextStyle": "white"
"navigationBarTextStyle": "black"
} }
}, },
{ {
@ -266,9 +259,8 @@
"path": "pages/coach/course/list", "path": "pages/coach/course/list",
"style": { "style": {
"navigationBarTitleText": "课表", "navigationBarTitleText": "课表",
"navigationStyle": "custom", "navigationBarBackgroundColor": "#29d3b4",
"navigationBarBackgroundColor": "#fff", "navigationBarTextStyle": "white"
"navigationBarTextStyle": "black"
} }
}, },
{ {
@ -334,13 +326,28 @@
"navigationBarTextStyle": "white" "navigationBarTextStyle": "white"
} }
}, },
{
"path": "pages/coach/student/student_list",
"style": {
"navigationBarTitleText": "我的学员",
"navigationBarBackgroundColor": "#29d3b4",
"navigationBarTextStyle": "white"
}
},
{
"path": "pages/coach/student/student_detail",
"style": {
"navigationBarTitleText": "学员详情",
"navigationBarBackgroundColor": "#29d3b4",
"navigationBarTextStyle": "white"
}
},
{ {
"path": "pages/coach/my/index", "path": "pages/coach/my/index",
"style": { "style": {
"navigationBarTitleText": "我的", "navigationBarTitleText": "我的",
"navigationStyle": "custom", "navigationBarBackgroundColor": "#29d3b4",
"navigationBarBackgroundColor": "#fff", "navigationBarTextStyle": "white"
"navigationBarTextStyle": "black"
} }
}, },
{ {
@ -348,7 +355,7 @@
"style": { "style": {
"navigationBarTitleText": "到课统计", "navigationBarTitleText": "到课统计",
"navigationStyle": "default", "navigationStyle": "default",
"navigationBarBackgroundColor": "#292929", "navigationBarBackgroundColor": "#29d3b4",
"navigationBarTextStyle": "white" "navigationBarTextStyle": "white"
} }
}, },
@ -356,8 +363,7 @@
"path": "pages/coach/my/due_soon", "path": "pages/coach/my/due_soon",
"style": { "style": {
"navigationBarTitleText": "即将到期", "navigationBarTitleText": "即将到期",
"navigationStyle": "default", "navigationBarBackgroundColor": "#29d3b4",
"navigationBarBackgroundColor": "#292929",
"navigationBarTextStyle": "white" "navigationBarTextStyle": "white"
} }
}, },
@ -366,7 +372,7 @@
"style": { "style": {
"navigationBarTitleText": "授课统计", "navigationBarTitleText": "授课统计",
"navigationStyle": "default", "navigationStyle": "default",
"navigationBarBackgroundColor": "#292929", "navigationBarBackgroundColor": "#29d3b4",
"navigationBarTextStyle": "white" "navigationBarTextStyle": "white"
} }
}, },
@ -433,27 +439,6 @@
"navigationBarTextStyle": "black" "navigationBarTextStyle": "black"
} }
}, },
{
"path": "pages/market/clue/writing_followUp",
"style": {
"navigationBarTitleText": "添加跟进",
"navigationStyle": "default",
"navigationBarBackgroundColor": "#fff",
"navigationBarTextStyle": "black"
}
},
{
"path": "pages/market/clue/new_task",
"style": {
"navigationBarTitleText": "转交跟进任务",
"navigationStyle": "default",
"navigationBarBackgroundColor": "#fff",
"navigationBarTextStyle": "black"
}
},
{ {
"path": "pages/market/clue/add_clues", "path": "pages/market/clue/add_clues",
"style": { "style": {
@ -626,6 +611,14 @@
"navigationBarBackgroundColor": "#292929", "navigationBarBackgroundColor": "#292929",
"navigationBarTextStyle": "white" "navigationBarTextStyle": "white"
} }
},
{
"path": "pages/coach/my/service_detail",
"style": {
"navigationBarTitleText": "服务详情",
"navigationBarBackgroundColor": "#29d3b4",
"navigationBarTextStyle": "black"
}
} }

293
pages/coach/course/info_list.vue

@ -3,7 +3,8 @@
<view class="main_box"> <view class="main_box">
<view class="main_section"> <view class="main_section">
<view class="section_1"> <view class="section_1">
<view class="title">时间{{courseInfo.course_date}}</view> <view class="title">日期{{courseInfo.course_date}}</view>
<view class="title">时间{{courseInfo.time_slot}}</view>
<view class="title">地点{{courseInfo.venue.venue_name}}</view> <view class="title">地点{{courseInfo.venue.venue_name}}</view>
<view class="title">课程{{courseInfo.course.course_name}}</view> <view class="title">课程{{courseInfo.course.course_name}}</view>
<view class="title">教练{{courseInfo.coach.name}}</view> <view class="title">教练{{courseInfo.coach.name}}</view>
@ -20,7 +21,7 @@
</view> </view>
<view class="section_2"> <view class="section_2">
<view :class="['table', tableType==1 ? 'select':'']" @click="switchTag(1)">签到情况</view> <view :class="['table', tableType==1 ? 'select':'']" @click="switchTag(1)">学员情况</view>
<view :class="['table', tableType==2 ? 'select':'']" @click="switchTag(2)">作业情况</view> <view :class="['table', tableType==2 ? 'select':'']" @click="switchTag(2)">作业情况</view>
</view> </view>
@ -30,7 +31,7 @@
<view class="tip_title" v-if="courseInfo.student_courses.length == 0">暂无数据</view> <view class="tip_title" v-if="courseInfo.student_courses.length == 0">暂无数据</view>
<view class="item" v-for="(v,k) in courseInfo.student_courses" :key="k"> <view class="item" v-for="(v,k) in courseInfo.student_courses" :key="k">
<view class="left"> <view class="left" @click="openViewCourseInfo(v)">
<image class="pic" model="aspectFit" :src="$util.img(v.avatar)"></image> <image class="pic" model="aspectFit" :src="$util.img(v.avatar)"></image>
<view class="box"> <view class="box">
<view class="title">{{v.name}}</view> <view class="title">{{v.name}}</view>
@ -39,7 +40,9 @@
</view> </view>
<view class="right" v-if="courseInfo.status == 'pending'"> <view class="right" v-if="courseInfo.status == 'pending'">
<view class="tag" @click="written(v.student_id)" v-if="!isWithinOneHourBefore(courseInfo.time_slot)">请假</view> <view class="tag leave-tag" @click="written(v.student_id)" v-if="!isWithinTimeSlot(courseInfo.time_slot) && v.status !== 'signed'">请假</view>
<view class="tag signin-tag" @click="signIn(v.student_id)" v-if="isWithinTimeSlot(courseInfo.time_slot) && v.status !== 'signed'">签到</view>
<view class="tag signed-tag" v-if="v.status === 'signed'">已签到</view>
</view> </view>
</view> </view>
@ -206,18 +209,59 @@
//- //-
async getCourseInfo() { async getCourseInfo() {
let res = await apiRoute.courseInfo({ // let res = await apiRoute.courseInfo({
id: this.course_id // id: this.course_id
}) // })
if (res.code != 1) { // if (res.code != 1) {
uni.showToast({ // uni.showToast({
title: res.msg, // title: res.msg,
icon: 'none' // icon: 'none'
}) // })
return // return
} // }
this.courseInfo = res.data // this.courseInfo = res.data
console.log('课程详情', this.courseInfo) // console.log('', this.courseInfo)
// 使
this.courseInfo = {
id: this.course_id || '1',
course_date: '2025-07-25',
time_slot: '14:00-15:30',
status: 'pending',
venue: {
venue_name: '总部校区 305教室',
capacity: 20
},
course: {
course_name: '少儿英语基础班'
},
coach: {
name: '王教练'
},
student_courses: [
{
student_id: '1001',
name: '张三',
avatar: '',
start_date: '2025-07-25',
end_date: '2025-10-25',
status: 'pending'
},
{
student_id: '1002',
name: '李四',
avatar: '',
start_date: '2025-07-25',
end_date: '2025-10-25',
status: 'pending'
}
],
groupedByStatus1: [], //
groupedByStatus2: [], //
groupedByStatus3: [] //
};
console.log('课程详情(模拟数据)', this.courseInfo);
}, },
// //
@ -227,9 +271,12 @@
// //
openViewCourseInfo(item) { openViewCourseInfo(item) {
this.$navigateTo({ // this.$navigateTo({
url: '/pages/coach/course/info' // url: '/pages/coach/course/info'
}) // })
uni.navigateTo({
url: `/pages/market/clue/clue_info?resource_sharing_id=25`
});
}, },
// //
@ -245,44 +292,97 @@
// //
async addStudent() { async addStudent() {
let res = await apiRoute.addStudentList({ // let res = await apiRoute.addStudentList({
id: this.course_id // id: this.course_id
}) // })
if (res.code != 1) { // if (res.code != 1) {
uni.showToast({ // uni.showToast({
title: res.msg, // title: res.msg,
icon: 'none' // icon: 'none'
}) // })
return // return
} // }
this.StudentList = res.data // this.StudentList = res.data
if (this.StudentList.length == 0) { // if (this.StudentList.length == 0) {
uni.showToast({ // uni.showToast({
title: '暂无可填加的学员', // title: '',
icon: 'none' // icon: 'none'
}) // })
return // return
} else { // } else {
this.show = true // this.show = true
} // }
// 使
this.StudentList = [
{
text: '张三',
value: '1001'
},
{
text: '李四',
value: '1002'
},
{
text: '王五',
value: '1003'
},
{
text: '赵六',
value: '1004'
},
{
text: '钱七',
value: '1005'
}
];
this.show = true;
}, },
async change(e) { async change(e) {
this.show = false this.show = false
let res = await apiRoute.addStudent({ // let res = await apiRoute.addStudent({
student_id: e.value, // student_id: e.value,
schedule_id: this.course_id, // schedule_id: this.course_id,
time_slot: this.courseInfo.time_slot, // time_slot: this.courseInfo.time_slot,
course_date: this.courseInfo.course_date // course_date: this.courseInfo.course_date
}) // })
if (res.code != 1) { // if (res.code != 1) {
uni.showToast({ // uni.showToast({
title: res.msg, // title: res.msg,
icon: 'none' // icon: 'none'
}) // })
return // return
// }
// this.init()
// 使
const selectedStudent = this.StudentList.find(student => student.value === e.value);
if (!selectedStudent) return;
//
if (!this.courseInfo.student_courses) {
this.courseInfo.student_courses = [];
} }
this.init()
//
const now = new Date();
const futureDate = new Date();
futureDate.setMonth(futureDate.getMonth() + 3); // 3
//
this.courseInfo.student_courses.push({
student_id: e.value,
name: selectedStudent.text,
avatar: '', //
start_date: now.toISOString().split('T')[0],
end_date: futureDate.toISOString().split('T')[0],
status: 'pending' //
});
uni.showToast({
title: '添加学员成功',
icon: 'success'
});
}, },
cancel() { cancel() {
this.show = false this.show = false
@ -310,32 +410,57 @@
}) })
this.init() this.init()
} else { } else {
uni.showToast({ // uni.showToast({
title: '学员不存在', // title: '',
icon: 'none' // icon: 'none'
}) // })
} }
this.written_show = false this.written_show = false
} }
}, },
isWithinOneHourBefore(time_slot) { isWithinTimeSlot(time_slot) {
// const [startStr, endStr] = time_slot.split('-');
const [startStr] = time_slot.split('-'); const [startHours, startMinutes] = startStr.split(':').map(Number);
const [hours, minutes] = startStr.split(':').map(Number); const [endHours, endMinutes] = endStr.split(':').map(Number);
// const now = new Date();
const startTime = new Date(); const startTime = new Date(now.getFullYear(), now.getMonth(), now.getDate(), startHours, startMinutes);
startTime.setHours(hours, minutes, 0, 0); const endTime = new Date(now.getFullYear(), now.getMonth(), now.getDate(), endHours, endMinutes);
// return now >= startTime && now < endTime;
const oneHourBeforeStart = new Date(startTime.getTime() - 60 * 60 * 1000); },
signIn(student_id) {
// uni.showToast({
const now = new Date(); title: '签到成功',
icon: 'success'
// [, ) });
return now >= oneHourBeforeStart && now < startTime;
// API
//
// apiRoute.studentSignIn({
// student_id: student_id,
// course_id: this.course_id,
// }).then(res => {
// if (res.code == 1) {
// uni.showToast({
// title: '',
// icon: 'success'
// });
// this.init();
// } else {
// uni.showToast({
// title: res.msg,
// icon: 'none'
// });
// }
// });
//
const studentIndex = this.courseInfo.student_courses.findIndex(s => s.student_id === student_id);
if (studentIndex !== -1) {
this.courseInfo.student_courses[studentIndex].status = 'signed';
}
} }
} }
} }
@ -491,13 +616,27 @@
border-radius: 50%; border-radius: 50%;
line-height: 90rpx; line-height: 90rpx;
font-size: 26rpx; font-size: 26rpx;
background-color: rgba(254, 250, 131, 0.62);
color: rgba(255, 255, 255, 1);
text-align: center; text-align: center;
border: 0rpx solid rgba(254, 250, 131, 0.62); border: 0rpx;
//45° //45°
transform: rotate(-30deg); transform: rotate(-30deg);
} }
.leave-tag {
background-color: rgba(254, 250, 131, 0.62);
color: rgba(255, 255, 255, 1);
}
.signin-tag {
background-color: #1cd188;
color: #FFFFFF;
}
.signed-tag {
background-color: #a4adb3;
color: #FFFFFF;
transform: none;
}
} }
} }

9
pages/coach/course/list.vue

@ -1,11 +1,6 @@
<!--课程-列表--> <!--课程-列表-->
<template> <template>
<view class="main_box"> <view class="main_box">
<!--自定义导航栏-->
<view class="navbar_section">
<view class="title">课表</view>
</view>
<view class="main_section"> <view class="main_section">
<view class="section_1"> <view class="section_1">
<view class="ul"> <view class="ul">
@ -58,10 +53,10 @@
</view> </view>
<view class="right_box"> <view class="right_box">
<!-- v.status|1=未开始,2=进行中,3=已结束--> <!-- v.status|1=未开始,2=进行中,3=已结束-->
<view class="tag" <!-- <view class="tag"
:style="{background: v.status == 'pending' ? '#1cd188' : v.status == 'ongoing' ? '#fad24e' : '#ff4d4f'}"> :style="{background: v.status == 'pending' ? '#1cd188' : v.status == 'ongoing' ? '#fad24e' : '#ff4d4f'}">
{{ v.status === 'pending' ? '未开始' : v.status === 'ongoing' ? '上课中' : '已结束' }} {{ v.status === 'pending' ? '未开始' : v.status === 'ongoing' ? '上课中' : '已结束' }}
</view> </view> -->
<!-- <view class="tag" style="background:#1cd188;">待上课</view>--> <!-- <view class="tag" style="background:#1cd188;">待上课</view>-->
</view> </view>
</view> </view>

413
pages/coach/home/index.vue

@ -1,58 +1,6 @@
<template> <template>
<view class="main_box"> <view class="main_box">
<!--自定义导航栏-->
<view class="navbar_section">
<view class="left"></view>
<view class="title">待办</view>
<view class="right" @click="openObjAddView()" style="padding: 178rpx 0 20rpx;">发布作业</view>
</view>
<view class="main_section"> <view class="main_section">
<!-- <view class="section_1">-->
<!-- <view class="top">-->
<!-- <view class="user">-->
<!-- <view class="pic">-->
<!-- <image src="http://www.firstui.cn:4000/vipdoc/img/img_logo.png"></image>-->
<!-- </view>-->
<!-- <view class="name">包子皮</view>-->
<!-- </view>-->
<!-- <view class="right">-->
<!-- <view>-->
<!-- <text class="title">到课率统计</text>-->
<!-- <text>28%</text>-->
<!-- </view>-->
<!-- <view>-->
<!-- <text class="title" @click="openObjAddView()">发布作业</text>-->
<!-- <text></text>-->
<!-- </view>-->
<!-- </view>-->
<!-- </view>-->
<!-- <view class="bottom"></view>-->
<!-- <view class="text_box">-->
<!-- <text>月授课数</text>-->
<!-- <text>12</text>-->
<!-- <text>月负责学员</text>-->
<!-- <text>188</text>-->
<!-- <text></text>-->
<!-- </view>-->
<!-- </view>-->
<!-- <view class="section_2">-->
<!-- <view class="left_box">-->
<!-- <view>-->
<!-- <text>课程</text>-->
<!-- <text>预告</text>-->
<!-- </view>-->
<!-- <view>-->
<!-- <text>5/28周五 15:30~17:30</text>-->
<!-- <text>301室篮球少儿课程</text>-->
<!-- </view>-->
<!-- </view>-->
<!-- <view class="rigth_box">-->
<!-- <view>详情</view>-->
<!-- </view>-->
<!-- </view>-->
<!--最近课程--> <!--最近课程-->
<view class="section_3"> <view class="section_3">
<view class="title_box"> <view class="title_box">
@ -62,7 +10,7 @@
</view> </view>
<view class="line"></view> <view class="line"></view>
</view> </view>
<view class="ul"> <view class="ul" v-if="infoData.course_list && infoData.course_list.length > 0">
<!-- 上课中--> <!-- 上课中-->
<view class="li" v-for="(v,k) in infoData.course_list" :key="k" @click="openViewCourseInfoList(v)"> <view class="li" v-for="(v,k) in infoData.course_list" :key="k" @click="openViewCourseInfoList(v)">
<view class="top_box"> <view class="top_box">
@ -106,7 +54,11 @@
style="background:#1cd188;">待上课 style="background:#1cd188;">待上课
</view> </view>
</view> </view>
</view>
<!-- 没有数据时的占位区域 -->
<view class="empty-placeholder" v-else>
<image src="/static/icon-img/empty.png" mode="aspectFit"></image>
<text>暂无课程数据</text>
</view> </view>
</view> </view>
@ -119,7 +71,7 @@
</view> </view>
<view class="line"></view> <view class="line"></view>
</view> </view>
<view class="ul"> <view class="ul" v-if="infoData.task_list && infoData.task_list.length > 0">
<view class="li" v-for="(v,k) in infoData.task_list" :key="k" @click="openViewWorkDetails(v)"> <view class="li" v-for="(v,k) in infoData.task_list" :key="k" @click="openViewWorkDetails(v)">
<view class="left_box"> <view class="left_box">
<view class="date_box"> <view class="date_box">
@ -142,7 +94,39 @@
<view class="tag" style="background:#1cd188;">待批改</view> <view class="tag" style="background:#1cd188;">待批改</view>
</view> </view>
</view> </view>
</view>
<!-- 没有数据时的占位区域 -->
<view class="empty-placeholder" v-else>
<image src="/static/icon-img/empty.png" mode="aspectFit"></image>
<text>暂无作业数据</text>
</view>
</view>
<!--我的服务列表-->
<view class="section_6">
<view class="title_box">
<view class="top_box">
<text>我的服务</text>
<view @click="openServiceListView()">全部</view>
</view>
<view class="line"></view>
</view>
<view class="service-list" v-if="serviceList && serviceList.length > 0">
<view class="service-item" v-for="(item, index) in serviceList" :key="index" @click="viewServiceDetail(item)">
<view class="service-info">
<view class="service-name">{{item.name}}</view>
<view class="service-desc">{{item.description}}</view>
<view class="service-time">创建时间{{item.create_time}}</view>
</view>
<view class="service-status" :class="{'active': item.status === 1}">
{{item.status === 1 ? '进行中' : '已结束'}}
</view>
</view>
</view>
<!-- 没有数据时的占位区域 -->
<view class="empty-placeholder" v-else>
<image src="/static/icon-img/empty.png" mode="aspectFit"></image>
<text>暂无服务数据</text>
</view> </view>
</view> </view>
</view> </view>
@ -170,32 +154,140 @@ export default {
course_list:[],// course_list:[],//
task_list:[],// task_list:[],//
}, },
serviceList: [], //
} }
}, },
onLoad() {}, onLoad() {
this.init() //
},
onShow() { onShow() {
//this.init()// this.init() //
}, },
methods: { methods: {
// //
async init(){ async init(){
await this.getInfo() await this.getInfo()
await this.getServiceList() //
}, },
// //
async getInfo(){ async getInfo(){
let res = await memberApi.jlIndex({}) // API使
if(res.code != 1){ // let res = await memberApi.jlIndex({})
uni.showToast({ // if(res.code != 1){
title: res.msg, // uni.showToast({
icon: 'none' // title: res.msg,
}) // icon: 'none'
return // })
// return
// }
// this.infoData = res.data
// 使
this.infoData = {
course_list: [
{
id: 1,
courses_name: '少儿英语基础班',
date_time: '2025-07-20',
time_slot: '15:30,17:00',
address: '总部校区 305教室',
status: 0,
sign_count: 0,
students_count: 15
},
{
id: 2,
courses_name: '少儿英语进阶班',
date_time: '2025-07-21',
time_slot: '14:00,15:30',
address: '西区校区 203教室',
status: 1,
sign_count: 12,
students_count: 18
},
{
id: 3,
courses_name: '少儿英语口语班',
date_time: '2025-07-22',
time_slot: '10:00,11:30',
address: '东区校区 102教室',
status: 0,
sign_count: 0,
students_count: 10
}
],
task_list: [
{
id: 1,
wc_count: 8,
student_count: 15,
rate: 53,
class_name: '英语基础1班',
send_time: '2025-07-18',
courses_name: '少儿英语基础班'
},
{
id: 2,
wc_count: 15,
student_count: 18,
rate: 83,
class_name: '英语进阶2班',
send_time: '2025-07-17',
courses_name: '少儿英语进阶班'
}
]
} }
this.infoData = res.data
}, },
//
async getServiceList() {
// API使
// try {
// // API
// let res = await memberApi.serviceList({})
// if(res.code == 1){
// this.serviceList = res.data || []
// } else {
// uni.showToast({
// title: res.msg || '',
// icon: 'none'
// })
// }
// } catch (error) {
// console.error(':', error)
// uni.showToast({
// title: '',
// icon: 'none'
// })
// }
// 使
this.serviceList = [
{
id: 1,
name: '一对一辅导服务',
description: '针对学生个人情况定制的一对一辅导计划,帮助学生快速提高成绩。',
create_time: '2025-07-15',
status: 1
},
{
id: 2,
name: '小组课程服务',
description: '3-5人小组课程,提供互动学习环境,培养学生团队协作能力。',
create_time: '2025-07-20',
status: 0
},
{
id: 3,
name: '课后辅导服务',
description: '针对课后作业和复习提供专业辅导,巩固课堂所学知识。',
create_time: '2025-07-01',
status: 1
}
]
},
//- //-
openObjAddView(){ openObjAddView(){
@ -226,6 +318,35 @@ export default {
url: `/pages/coach/student/work_details?id=${id}` url: `/pages/coach/student/work_details?id=${id}`
}) })
}, },
//
openServiceListView() {
this.$navigateTo({
url: '/pages/coach/my/service_list'
})
},
//
viewServiceDetail(item) {
let id = item.id
this.$navigateTo({
url: `/pages/coach/my/service_detail?id=${id}`
})
},
//
goToStudentList() {
this.$navigateTo({
url: '/pages/coach/student/student_list'
})
},
//
goToClassList() {
this.$navigateTo({
url: '/pages/coach/class/list'
})
},
} }
} }
@ -264,6 +385,16 @@ export default {
} }
.right{ .right{
padding: 20rpx 0; padding: 20rpx 0;
/* H5端样式 */
// #ifdef H5
padding: 40rpx 0 20rpx;
// #endif
/* 小程序端样式 */
// #ifdef MP-WEIXIN
padding: 80rpx 0 20rpx;
// #endif
font-size: 26rpx; font-size: 26rpx;
color: #fff; color: #fff;
text-align: right; text-align: right;
@ -278,6 +409,25 @@ export default {
padding-bottom: 150rpx; padding-bottom: 150rpx;
font-size: 28rpx; font-size: 28rpx;
/* 空数据占位区域样式 */
.empty-placeholder {
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
padding: 60rpx 0;
image {
width: 200rpx;
height: 200rpx;
margin-bottom: 20rpx;
}
text {
color: #999;
font-size: 28rpx;
}
}
.section_1{ .section_1{
background: #FFFFFF 100%; background: #FFFFFF 100%;
@ -511,6 +661,135 @@ export default {
} }
} }
.section_5{
margin-top: 36rpx;
color: #fff;
font-size: 24rpx;
.title_box{
display: flex;
flex-direction: column;
.top_box{
display: flex;
justify-content: space-between;
align-items: center;
text{
font-size: 30rpx;
}
}
.line{
width: 90rpx;
height: 2px;
background: #29D3B4;
}
}
.quick-links {
margin-top: 30rpx;
display: flex;
justify-content: space-around;
.quick-link-item {
display: flex;
flex-direction: column;
align-items: center;
background: #434544;
border-radius: 20rpx;
padding: 30rpx 20rpx;
width: 30%;
.quick-link-icon {
margin-bottom: 20rpx;
}
.quick-link-text {
font-size: 28rpx;
color: #fff;
}
}
}
}
.section_6{
margin-top: 36rpx;
color: #fff;
font-size: 24rpx;
.title_box{
display: flex;
flex-direction: column;
.top_box{
display: flex;
justify-content: space-between;
align-items: center;
text{
font-size: 30rpx;
}
}
.line{
width: 90rpx;
height: 2px;
background: #29D3B4;
}
}
.service-list{
margin-top: 30rpx;
display: flex;
flex-direction: column;
gap: 20rpx;
.service-item{
position: relative;
border-radius: 22rpx;
background: #434544 100%;
padding: 24rpx 20rpx;
display: flex;
justify-content: space-between;
align-items: center;
border-left: 4rpx solid #29D3B4;
.service-info{
flex: 1;
display: flex;
flex-direction: column;
gap: 12rpx;
.service-name{
font-size: 30rpx;
color: #fff;
font-weight: 500;
}
.service-desc{
font-size: 24rpx;
color: #D7D7D7;
overflow: hidden;
text-overflow: ellipsis;
display: -webkit-box;
-webkit-line-clamp: 2;
-webkit-box-orient: vertical;
}
.service-time{
font-size: 22rpx;
color: #AAAAAA;
margin-top: 6rpx;
}
}
.service-status{
padding: 8rpx 20rpx;
border-radius: 30rpx;
background: #666;
color: #fff;
font-size: 24rpx;
text-align: center;
&.active {
background: #29D3B4;
}
}
}
}
}
} }

566
pages/coach/job/list.vue

@ -35,13 +35,112 @@
</view> </view>
</scroll-view> </scroll-view>
<!-- 底部导航--> <!-- 底部发布作业按钮 -->
<view class="publish-btn" @click="openPublishPopup">
<text class="btn-text">发布作业</text>
</view>
<!-- 底部导航-->
<AQTabber/> <AQTabber/>
<!-- 发布作业弹窗 -->
<uni-popup ref="publishPopup" type="center">
<view class="popup-content">
<view class="popup-title">发布作业</view>
<view class="form-item">
<text class="form-label">类型</text>
<input class="form-input" type="number" v-model="formData.type" placeholder="请输入类型" />
</view>
<view class="form-item">
<text class="form-label">班级ID</text>
<input class="form-input" type="number" v-model="formData.class_id" placeholder="请输入班级ID" />
</view>
<view class="form-item">
<text class="form-label">课程ID</text>
<input class="form-input" type="number" v-model="formData.course_id" placeholder="请输入课程ID" />
</view>
<view class="form-item">
<text class="form-label">教师ID</text>
<input class="form-input" type="number" v-model="formData.personnel_id" placeholder="请输入教师ID" />
</view>
<view class="form-item">
<text class="form-label">学生ID</text>
<input class="form-input" type="number" v-model="formData.student_id" placeholder="请输入学生ID" />
</view>
<view class="form-item">
<text class="form-label">作业描述</text>
<textarea class="form-textarea" v-model="formData.description" placeholder="请输入作业描述" />
</view>
<view class="form-item">
<text class="form-label">内容类型</text>
<picker class="form-picker" :value="contentTypeIndex" :range="contentTypes" @change="contentTypeChange">
<view class="picker-text">{{contentTypes[contentTypeIndex]}}</view>
</picker>
</view>
<!-- 根据内容类型显示不同的上传控件 -->
<!-- 图片类型 -->
<view class="form-item" v-if="formData.content_type === '1'">
<text class="form-label">上传图片</text>
<view class="upload-container">
<!-- 已上传图片预览 -->
<view class="image-preview" v-if="uploadedFiles.image">
<image class="preview-image" :src="uploadedFiles.image" mode="aspectFill"></image>
<view class="delete-btn" @click="deleteFile('image')">
<text class="delete-icon">×</text>
</view>
</view>
<!-- 上传按钮 -->
<view class="upload-btn" v-if="!uploadedFiles.image" @click="chooseFile('image')">
<text class="upload-icon">+</text>
<text class="upload-text">上传图片</text>
</view>
</view>
</view>
<!-- 视频类型 -->
<view class="form-item" v-if="formData.content_type === '2'">
<text class="form-label">上传视频</text>
<view class="upload-container">
<!-- 已上传视频预览 -->
<view class="video-preview" v-if="uploadedFiles.video">
<video class="preview-video" :src="uploadedFiles.video" controls></video>
<view class="delete-btn" @click="deleteFile('video')">
<text class="delete-icon">×</text>
</view>
</view>
<!-- 上传按钮 -->
<view class="upload-btn" v-if="!uploadedFiles.video" @click="chooseFile('video')">
<text class="upload-icon">+</text>
<text class="upload-text">上传视频</text>
</view>
</view>
</view>
<!-- 文本类型 -->
<view class="form-item" v-if="formData.content_type === '3'">
<text class="form-label">内容文本</text>
<textarea class="form-textarea" v-model="formData.content_text" placeholder="请输入内容文本" />
</view>
<view class="form-buttons">
<button class="btn-cancel" @click="closePublishPopup">取消</button>
<button class="btn-submit" @click="submitForm">提交</button>
</view>
</view>
</uni-popup>
</view> </view>
</template> </template>
<script> <script>
import memberApi from '@/api/member.js'; // import memberApi from '@/api/member.js';
import AQTabber from "@/components/AQ/AQTabber.vue" import AQTabber from "@/components/AQ/AQTabber.vue"
@ -62,6 +161,82 @@ export default {
total:10,// total:10,//
}, },
tableList:[],// tableList:[],//
//
formData: {
type: '',
class_id: '',
course_id: '',
personnel_id: '',
student_id: '',
description: '',
content_type: '1',
content_text: '',
status: '1'
},
//
contentTypes: ['图片', '视频', '文本'],
contentTypeIndex: 0,
//
uploadedFiles: {
image: '',
video: ''
},
//
mockData: [
{
id: 1,
wc_count: 15,
student_count: 20,
rate: 75,
class_name: '高三一班',
send_time: '2023-05-12',
courses_name: '高等数学',
dpg_count: 0
},
{
id: 2,
wc_count: 18,
student_count: 22,
rate: 82,
class_name: '高三二班',
send_time: '2023-05-13',
courses_name: '物理',
dpg_count: 5
},
{
id: 3,
wc_count: 10,
student_count: 25,
rate: 40,
class_name: '高三三班',
send_time: '2023-05-14',
courses_name: '化学',
dpg_count: 0
},
{
id: 4,
wc_count: 22,
student_count: 24,
rate: 92,
class_name: '高三四班',
send_time: '2023-05-15',
courses_name: '英语',
dpg_count: 3
},
{
id: 5,
wc_count: 16,
student_count: 20,
rate: 80,
class_name: '高三五班',
send_time: '2023-05-16',
courses_name: '语文',
dpg_count: 0
}
]
} }
}, },
onLoad() {}, onLoad() {},
@ -109,6 +284,23 @@ export default {
this.tableList = [] this.tableList = []
} }
// 使
setTimeout(() => {
this.loading = false
this.isReachedBottom = false
//
const startIndex = (this.filteredData.page - 1) * this.filteredData.limit
const endIndex = startIndex + this.filteredData.limit
const pageData = this.mockData.slice(startIndex, endIndex)
this.tableList = this.tableList.concat(pageData)
this.filteredData.total = this.mockData.length
this.filteredData.page++
}, 500)
//
/*
let res = await memberApi.jsGetAssignmentsList(data) let res = await memberApi.jsGetAssignmentsList(data)
this.loading = false this.loading = false
this.isReachedBottom = false; this.isReachedBottom = false;
@ -125,6 +317,7 @@ export default {
console.log('列表',this.tableList) console.log('列表',this.tableList)
this.filteredData.total = res.data.total this.filteredData.total = res.data.total
this.filteredData.page++ this.filteredData.page++
*/
}, },
//- //-
@ -134,6 +327,185 @@ export default {
url: `/pages/coach/student/work_details?id=${id}` url: `/pages/coach/student/work_details?id=${id}`
}) })
}, },
//
openPublishPopup() {
this.$refs.publishPopup.open()
},
//
closePublishPopup() {
this.$refs.publishPopup.close()
},
//
contentTypeChange(e) {
this.contentTypeIndex = e.detail.value
this.formData.content_type = String(parseInt(e.detail.value) + 1)
},
//
chooseFile(type) {
if (type === 'image') {
//
uni.chooseImage({
count: 1,
sizeType: ['compressed'],
sourceType: ['album', 'camera'],
success: (res) => {
//
uni.showLoading({
title: '上传中...'
})
setTimeout(() => {
uni.hideLoading()
this.uploadedFiles.image = res.tempFilePaths[0]
//
uni.showToast({
title: '图片上传成功',
icon: 'success'
})
//
this.formData.content_text = res.tempFilePaths[0]
}, 1000)
}
})
} else if (type === 'video') {
//
uni.chooseVideo({
count: 1,
sourceType: ['album', 'camera'],
maxDuration: 60,
camera: 'back',
success: (res) => {
//
uni.showLoading({
title: '上传中...'
})
setTimeout(() => {
uni.hideLoading()
this.uploadedFiles.video = res.tempFilePath
//
uni.showToast({
title: '视频上传成功',
icon: 'success'
})
//
this.formData.content_text = res.tempFilePath
}, 1500)
}
})
}
},
//
deleteFile(type) {
if (type === 'image') {
this.uploadedFiles.image = ''
this.formData.content_text = ''
} else if (type === 'video') {
this.uploadedFiles.video = ''
this.formData.content_text = ''
}
},
//
previewFile(type) {
if (type === 'image' && this.uploadedFiles.image) {
uni.previewImage({
urls: [this.uploadedFiles.image]
})
}
//
},
//
submitForm() {
//
if (!this.formData.class_id) {
uni.showToast({
title: '请输入班级ID',
icon: 'none'
})
return
}
if (!this.formData.course_id) {
uni.showToast({
title: '请输入课程ID',
icon: 'none'
})
return
}
if (!this.formData.description) {
uni.showToast({
title: '请输入作业描述',
icon: 'none'
})
return
}
//
if (this.formData.content_type === '1' && !this.uploadedFiles.image) {
uni.showToast({
title: '请上传图片',
icon: 'none'
})
return
}
if (this.formData.content_type === '2' && !this.uploadedFiles.video) {
uni.showToast({
title: '请上传视频',
icon: 'none'
})
return
}
if (this.formData.content_type === '3' && !this.formData.content_text) {
uni.showToast({
title: '请输入内容文本',
icon: 'none'
})
return
}
console.log('提交表单数据:', this.formData)
//
uni.showToast({
title: '发布成功',
icon: 'success'
})
//
this.closePublishPopup()
//
this.formData = {
type: '',
class_id: '',
course_id: '',
personnel_id: '',
student_id: '',
description: '',
content_type: '1',
content_text: '',
status: '1'
}
this.contentTypeIndex = 0
this.uploadedFiles = {
image: '',
video: ''
}
}
} }
} }
</script> </script>
@ -216,14 +588,194 @@ export default {
border-bottom-left-radius: 20rpx; border-bottom-left-radius: 20rpx;
border-top-right-radius: 20rpx; border-top-right-radius: 20rpx;
} }
} }
} }
} }
} }
//
.publish-btn {
position: fixed;
bottom: 220rpx;
right: 40rpx;
width: 120rpx;
height: 120rpx;
background: #29D3B4;
border-radius: 50%;
display: flex;
align-items: center;
justify-content: center;
box-shadow: 0 4rpx 20rpx rgba(41, 211, 180, 0.4);
z-index: 99;
.btn-text {
color: #fff;
font-size: 26rpx;
text-align: center;
}
}
//
.popup-content {
width: 650rpx;
background: #333;
border-radius: 20rpx;
padding: 30rpx;
max-height: 80vh;
overflow-y: auto;
.popup-title {
font-size: 36rpx;
color: #fff;
text-align: center;
margin-bottom: 30rpx;
font-weight: bold;
}
.form-item {
margin-bottom: 20rpx;
.form-label {
display: block;
color: #fff;
font-size: 28rpx;
margin-bottom: 10rpx;
}
.form-input, .form-textarea, .form-picker {
width: 100%;
background: #444;
border-radius: 10rpx;
padding: 16rpx;
color: #fff;
font-size: 28rpx;
box-sizing: border-box;
}
.form-textarea {
height: 150rpx;
}
.picker-text {
height: 60rpx;
line-height: 60rpx;
}
//
.upload-container {
margin-top: 10rpx;
}
.upload-btn {
width: 200rpx;
height: 200rpx;
background: #444;
border-radius: 10rpx;
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
border: 1px dashed #666;
.upload-icon {
font-size: 60rpx;
color: #29D3B4;
line-height: 60rpx;
}
.upload-text {
font-size: 24rpx;
color: #aaa;
margin-top: 10rpx;
}
}
//
.image-preview {
position: relative;
width: 200rpx;
height: 200rpx;
border-radius: 10rpx;
overflow: hidden;
.preview-image {
width: 100%;
height: 100%;
}
.delete-btn {
position: absolute;
top: 0;
right: 0;
width: 40rpx;
height: 40rpx;
background: rgba(0, 0, 0, 0.6);
display: flex;
align-items: center;
justify-content: center;
.delete-icon {
color: #fff;
font-size: 28rpx;
}
}
}
//
.video-preview {
position: relative;
width: 100%;
height: 300rpx;
border-radius: 10rpx;
overflow: hidden;
.preview-video {
width: 100%;
height: 100%;
}
.delete-btn {
position: absolute;
top: 0;
right: 0;
width: 40rpx;
height: 40rpx;
background: rgba(0, 0, 0, 0.6);
display: flex;
align-items: center;
justify-content: center;
.delete-icon {
color: #fff;
font-size: 28rpx;
}
}
}
}
.form-buttons {
display: flex;
justify-content: space-between;
margin-top: 40rpx;
button {
width: 45%;
height: 80rpx;
line-height: 80rpx;
border-radius: 40rpx;
font-size: 30rpx;
}
.btn-cancel {
background: #555;
color: #fff;
}
.btn-submit {
background: #29D3B4;
color: #fff;
}
}
}
} }
</style> </style>

17
pages/coach/my/index.vue

@ -1,11 +1,6 @@
<!--我的-首页--> <!--我的-首页-->
<template> <template>
<view class="main_box"> <view class="main_box">
<!--自定义导航栏-->
<view class="navbar_section">
<view class="title">我的</view>
</view>
<view style="background:#29D3B4;"> <view style="background:#29D3B4;">
<!--用户信息--> <!--用户信息-->
<view class="user_section"> <view class="user_section">
@ -93,6 +88,11 @@
<view>教研管理</view> <view>教研管理</view>
<view></view> <view></view>
</view> </view>
<view class="item" @click="openServiceDetail()">
<view>服务详情</view>
<view></view>
</view>
</view> </view>
<view class="section_box"> <view class="section_box">
@ -220,6 +220,13 @@ export default {
url: `/pages/common/my_attendance` url: `/pages/common/my_attendance`
}) })
}, },
//
openServiceDetail(){
this.$navigateTo({
url: '/pages/coach/my/service_detail'
})
},
} }
} }
</script> </script>

625
pages/coach/my/service_detail.vue

@ -0,0 +1,625 @@
<!--教练服务详情页-->
<template>
<view class="container">
<!-- 如果没有指定ID显示服务列表 -->
<view class="content" v-if="!id">
<view class="service-list">
<view class="section-title">我的服务列表</view>
<view class="empty-list" v-if="serviceList.length === 0">
<text>暂无服务记录</text>
</view>
<view class="service-item" v-for="(item, index) in serviceList" :key="index" @click="viewServiceDetail(item.id)">
<view class="service-header">
<view class="user-info">
<image class="user-avatar" src="/static/icon-img/avatar.png"></image>
<text class="user-name">{{item.service_id}} {{item.resource_id}}</text>
</view>
</view>
<view class="service-content">
<view class="info-row">
<text class="info-label">所属校区:</text>
<text class="info-value">{{item.campus || '总部校区'}}</text>
</view>
<view class="info-row">
<text class="info-label">来源:</text>
<text class="info-value">{{item.source || '线上'}}</text>
</view>
<view class="info-row">
<text class="info-label">来源渠道:</text>
<text class="info-value">{{item.channel || '地推'}}</text>
</view>
</view>
<view class="service-footer">
<text class="contact-status">暂未联系</text>
<view class="effective-status" :class="{'status-yes': item.status === 1}">
是否有效: {{item.status === 1 ? '有效' : '无效'}}
<view class="status-dot" :class="{'dot-yes': item.status === 1}"></view>
</view>
</view>
</view>
</view>
</view>
<!-- 如果指定了ID显示服务详情 -->
<view class="content detail-content" v-else-if="serviceInfo">
<view class="service-detail-card">
<view class="detail-header">
<view class="user-info">
<image class="user-avatar" src="/static/icon-img/avatar.png"></image>
<text class="user-name">{{serviceInfo.service_id}}</text>
</view>
</view>
<view class="detail-content">
<view class="card-section">
<view class="section-title">基本信息</view>
<view class="info-card">
<view class="info-item">
<text class="item-label">服务内容</text>
<text class="item-value">{{serviceInfo.id}}</text>
</view>
<view class="info-item">
<text class="item-label">学员姓名</text>
<text class="item-value">{{serviceInfo.resource_id}}</text>
</view>
</view>
</view>
<view class="card-section">
<view class="section-title">服务详情</view>
<view class="info-card">
<view class="info-item">
<text class="item-label">服务备注</text>
<text class="item-value">{{serviceInfo.service_remark || '暂无备注'}}</text>
</view>
<view class="info-item">
<text class="item-label">服务状态</text>
<text class="item-value" :class="{'status-completed': serviceInfo.status === 1}">
{{serviceInfo.status === 1 ? '已完成服务' : '待完成服务'}}
</text>
</view>
<view class="info-item">
<text class="item-label">服务人员ID</text>
<text class="item-value">{{serviceInfo.staff_id}}</text>
</view>
<view class="info-item">
<text class="item-label">评分</text>
<view class="score-box">
<view class="star-box">
<uni-icons v-for="i in 5" :key="i" :type="i <= serviceInfo.score ? 'star-filled' : 'star'" size="18" color="#FFB800"></uni-icons>
</view>
<text class="score-value">{{serviceInfo.score}}</text>
</view>
</view>
</view>
</view>
<view class="card-section">
<view class="section-title">用户反馈</view>
<view class="info-card">
<view class="feedback-content" v-if="serviceInfo.feedback">
<text>{{serviceInfo.feedback}}</text>
</view>
<view class="empty-feedback" v-else>
<text>暂无用户反馈</text>
</view>
</view>
</view>
<view class="card-section">
<view class="section-title">时间信息</view>
<view class="info-card">
<view class="info-item">
<text class="item-label">创建时间</text>
<text class="item-value">{{formatTime(serviceInfo.created_at)}}</text>
</view>
<view class="info-item">
<text class="item-label">反馈时间</text>
<text class="item-value">{{formatTime(serviceInfo.feedback_time)}}</text>
</view>
<view class="info-item">
<text class="item-label">更新时间</text>
<text class="item-value">{{formatTime(serviceInfo.updated_at)}}</text>
</view>
</view>
</view>
</view>
<view class="detail-footer" v-if="serviceInfo.status !== 1">
<button class="btn primary" @click="completeService">完成服务</button>
</view>
</view>
</view>
<view v-else class="loading-box">
<text>加载中...</text>
</view>
</view>
</template>
<script>
import apiRoute from '@/api/apiRoute.js';
export default {
data() {
return {
id: null,
serviceInfo: null,
serviceList: []
}
},
onLoad(options) {
if (options.id) {
this.id = options.id;
this.getServiceDetail();
} else {
this.getServiceList();
}
},
methods: {
navigateBack() {
uni.navigateBack();
},
async getServiceList() {
try {
// 使
// const res = await apiRoute.getServiceList();
// if(res.code == 1) {
// this.serviceList = res.data || [];
// } else {
// uni.showToast({
// title: res.msg || '',
// icon: 'none'
// });
// }
// 使
setTimeout(() => {
this.serviceList = [
{
id: '1',
resource_id: '美团用户1',
course_id: '2001',
service_id: '18645873651',
service_remark: '针对学员英语口语发音进行专项辅导',
status: 1,
staff_id: '3001',
score: 4,
feedback: '老师很耐心,讲解很清楚,孩子进步很大',
created_at: '2023-10-15 14:30:00',
feedback_time: '2023-10-16 18:20:00',
updated_at: '2023-10-16 18:20:00',
campus: '总部校区',
source: '线上',
channel: '地推'
},
{
id: '2',
resource_id: '李柏辉',
course_id: '2002',
service_id: '13876337043',
service_remark: '解答家长关于课程安排的问题',
status: 0,
staff_id: '3001',
score: 0,
feedback: '',
created_at: '2023-10-18 09:15:00',
feedback_time: '',
updated_at: '2023-10-18 09:15:00',
campus: '西区校区',
source: '地推',
channel: ''
},
{
id: '3',
resource_id: '张小明',
course_id: '2003',
service_id: '13912345678',
service_remark: '为学员制定个性化学习计划',
status: 0,
staff_id: '3001',
score: 0,
feedback: '',
created_at: '2023-10-20 16:45:00',
feedback_time: '',
updated_at: '2023-10-20 16:45:00',
campus: '东区校区',
source: '线下',
channel: '朋友介绍'
}
];
}, 500);
} catch(error) {
console.error('获取服务列表失败:', error);
uni.showToast({
title: '获取服务列表失败',
icon: 'none'
});
}
},
async getServiceDetail() {
try {
// 使
// const res = await apiRoute.getServiceDetail({id: this.id});
// if(res.code == 1) {
// this.serviceInfo = res.data || null;
// } else {
// uni.showToast({
// title: res.msg || '',
// icon: 'none'
// });
// }
// 使
setTimeout(() => {
//
const mockServices = {
'1': {
id: '1',
resource_id: '美团用户1',
course_id: '2001',
service_id: '18645873651',
service_remark: '针对学员英语口语发音进行专项辅导',
status: 1,
staff_id: '3001',
score: 4,
feedback: '老师很耐心,讲解很清楚,孩子进步很大',
created_at: '2023-10-15 14:30:00',
feedback_time: '2023-10-16 18:20:00',
updated_at: '2023-10-16 18:20:00',
campus: '总部校区',
source: '线上',
channel: '地推'
},
'2': {
id: '2',
resource_id: '李柏辉',
course_id: '2002',
service_id: '13876337043',
service_remark: '解答家长关于课程安排的问题',
status: 0,
staff_id: '3001',
score: 0,
feedback: '',
created_at: '2023-10-18 09:15:00',
feedback_time: '',
updated_at: '2023-10-18 09:15:00',
campus: '西区校区',
source: '地推',
channel: ''
},
'3': {
id: '3',
resource_id: '张小明',
course_id: '2003',
service_id: '13912345678',
service_remark: '为学员制定个性化学习计划',
status: 0,
staff_id: '3001',
score: 0,
feedback: '',
created_at: '2023-10-20 16:45:00',
feedback_time: '',
updated_at: '2023-10-20 16:45:00',
campus: '东区校区',
source: '线下',
channel: '朋友介绍'
}
};
// ID
this.serviceInfo = mockServices[this.id] || null;
if (!this.serviceInfo) {
uni.showToast({
title: '未找到服务详情',
icon: 'none'
});
setTimeout(() => {
this.navigateBack();
}, 1500);
}
}, 500);
} catch(error) {
console.error('获取服务详情失败:', error);
uni.showToast({
title: '获取服务详情失败',
icon: 'none'
});
}
},
formatTime(timeStr) {
if (!timeStr) return '暂无';
return timeStr;
},
viewServiceDetail(id) {
uni.navigateTo({
url: `/pages/coach/my/service_detail?id=${id}`
});
},
async completeService() {
uni.showModal({
title: '确认完成',
content: '确定要将此服务标记为已完成吗?',
success: async (res) => {
if (res.confirm) {
try {
// 使
// const result = await apiRoute.completeService({id: this.id});
// if(result.code == 1) {
// this.serviceInfo.status = 1;
// uni.showToast({
// title: '',
// icon: 'success'
// });
// } else {
// uni.showToast({
// title: result.msg || '',
// icon: 'none'
// });
// }
// API
setTimeout(() => {
this.serviceInfo.status = 1;
uni.showToast({
title: '服务已完成',
icon: 'success'
});
}, 500);
} catch(error) {
console.error('完成服务失败:', error);
uni.showToast({
title: '操作失败',
icon: 'none'
});
}
}
}
});
}
}
}
</script>
<style lang="scss" scoped>
.container {
min-height: 100vh;
height: 100vh;
background-color: #292929;
padding-bottom: 120rpx;
position: relative;
box-sizing: border-box;
display: flex;
flex-direction: column;
}
.content {
padding: 20rpx;
flex: 1;
overflow-y: auto;
}
.detail-content {
padding: 0;
}
.section-title {
font-size: 30rpx;
font-weight: bold;
color: #FFFFFF;
margin-bottom: 20rpx;
padding-left: 10rpx;
}
.service-list {
padding-bottom: 30rpx;
}
.service-item {
background-color: #333;
border-radius: 12rpx;
padding: 20rpx;
margin-bottom: 20rpx;
}
.service-header {
display: flex;
justify-content: space-between;
align-items: center;
margin-bottom: 20rpx;
}
.user-info {
display: flex;
align-items: center;
}
.user-avatar {
width: 60rpx;
height: 60rpx;
border-radius: 50%;
margin-right: 15rpx;
background-color: #29D3B4;
}
.user-name {
color: #fff;
font-size: 30rpx;
}
.service-content {
margin-bottom: 20rpx;
}
.info-row {
display: flex;
margin-bottom: 10rpx;
font-size: 28rpx;
color: #ccc;
}
.info-label {
color: #999;
margin-right: 10rpx;
}
.info-value {
color: #fff;
}
.service-footer {
display: flex;
justify-content: space-between;
border-top: 1px solid #444;
padding-top: 15rpx;
font-size: 26rpx;
}
.contact-status {
color: #999;
}
.effective-status {
color: #ff6b6b;
display: flex;
align-items: center;
}
.status-yes {
color: #29D3B4;
}
.status-dot {
width: 16rpx;
height: 16rpx;
border-radius: 50%;
background-color: #ff6b6b;
margin-left: 10rpx;
}
.dot-yes {
background-color: #29D3B4;
}
.service-detail-card {
background-color: #333;
margin: 20rpx;
border-radius: 12rpx;
overflow: hidden;
}
.detail-header {
display: flex;
justify-content: space-between;
align-items: center;
padding: 30rpx 20rpx;
border-bottom: 1px solid #444;
}
.detail-content {
padding: 30rpx 20rpx;
}
.card-section {
margin-bottom: 30rpx;
}
.info-card {
background-color: #3a3a3a;
border-radius: 12rpx;
padding: 20rpx;
}
.info-item {
display: flex;
justify-content: space-between;
align-items: center;
padding: 20rpx 10rpx;
border-bottom: 1rpx solid #444;
}
.info-item:last-child {
border-bottom: none;
}
.item-label {
color: #999;
font-size: 28rpx;
}
.item-value {
color: #fff;
font-size: 28rpx;
font-weight: 500;
}
.score-box {
display: flex;
align-items: center;
}
.star-box {
display: flex;
margin-right: 10rpx;
}
.score-value {
color: #FFB800;
font-weight: bold;
}
.feedback-content {
padding: 20rpx 10rpx;
font-size: 28rpx;
color: #fff;
line-height: 1.6;
}
.empty-feedback {
padding: 40rpx 0;
text-align: center;
color: #999;
font-size: 28rpx;
}
.detail-footer {
padding: 20rpx;
border-top: 1px solid #444;
}
.btn {
height: 80rpx;
line-height: 80rpx;
border-radius: 40rpx;
font-size: 30rpx;
margin-bottom: 20rpx;
background-color: transparent;
}
.primary {
background-color: #29D3B4;
color: #FFFFFF;
}
.loading-box {
display: flex;
justify-content: center;
align-items: center;
height: 300rpx;
color: #999;
}
.empty-list {
padding: 60rpx 0;
text-align: center;
color: #999;
font-size: 28rpx;
background-color: #333;
border-radius: 12rpx;
}
.status-completed {
color: #29D3B4;
}
</style>

499
pages/coach/student/student_detail.vue

@ -0,0 +1,499 @@
<template>
<view class="container">
<uni-nav-bar fixed status-bar left-icon="left" title="学员详情" @clickLeft="navigateBack"></uni-nav-bar>
<view class="content" v-if="studentInfo">
<view class="student-header">
<view class="avatar-box">
<image :src="studentInfo.avatar || '/static/icon-img/avatar.png'" mode="aspectFill" class="avatar-img"></image>
</view>
<view class="name-box">
<text class="name">{{studentInfo.name}}</text>
<text class="id">ID: {{studentInfo.id}}</text>
</view>
</view>
<view class="card-section">
<view class="section-title">基本信息</view>
<view class="info-card">
<view class="info-item">
<text class="item-label">所属校区</text>
<text class="item-value">{{studentInfo.campus}}</text>
</view>
<view class="info-item">
<text class="item-label">联系电话</text>
<text class="item-value">{{studentInfo.phone}}</text>
</view>
<view class="info-item">
<text class="item-label">年龄</text>
<text class="item-value">{{studentInfo.age}}</text>
</view>
<view class="info-item">
<text class="item-label">入学时间</text>
<text class="item-value">{{studentInfo.enrollmentDate}}</text>
</view>
</view>
</view>
<view class="card-section">
<view class="section-title">课程信息</view>
<view class="info-card">
<view class="info-item">
<text class="item-label">剩余课程</text>
<text class="item-value highlight">{{studentInfo.remainingCourses}}</text>
</view>
<view class="info-item">
<text class="item-label">课程到期时间</text>
<text class="item-value highlight">{{studentInfo.expiryDate}}</text>
</view>
<view class="info-item">
<text class="item-label">已消课程</text>
<text class="item-value">{{studentInfo.completedCourses}}</text>
</view>
<view class="info-item">
<text class="item-label">报名课程</text>
<text class="item-value">{{studentInfo.courseName}}</text>
</view>
</view>
</view>
<view class="card-section">
<view class="section-title">最近上课记录</view>
<view class="info-card" v-if="studentInfo.recentClasses && studentInfo.recentClasses.length > 0">
<view class="class-item" v-for="(item, index) in studentInfo.recentClasses" :key="index">
<view class="class-date">{{item.date}}</view>
<view class="class-info">
<text class="class-name">{{item.courseName}}</text>
<text class="class-time">{{item.timeSlot}}</text>
</view>
</view>
</view>
<view class="empty-class" v-else>
<text>暂无上课记录</text>
</view>
</view>
<view class="btn-group">
<button class="btn primary" @click="contactStudent">联系学员</button>
<button class="btn secondary" @click="viewSchedule">查看课表</button>
</view>
</view>
<view v-else class="loading-box">
<text>加载中...</text>
</view>
</view>
</template>
<script>
export default {
data() {
return {
id: null,
studentInfo: null
}
},
onLoad(options) {
if (options.id) {
this.id = options.id;
this.getStudentDetail();
} else {
uni.showToast({
title: '参数错误',
icon: 'none'
});
setTimeout(() => {
this.navigateBack();
}, 1500);
}
},
methods: {
navigateBack() {
uni.navigateBack();
},
getStudentDetail() {
// API
// try {
// const res = await memberApi.getStudentDetail({id: this.id});
// if(res.code == 1) {
// this.studentInfo = res.data || null;
// } else {
// uni.showToast({
// title: res.msg || '',
// icon: 'none'
// });
// }
// } catch(error) {
// console.error(':', error);
// uni.showToast({
// title: '',
// icon: 'none'
// });
// }
// 使
setTimeout(() => {
//
const studentData = {
'1': {
id: '1',
name: '张三',
avatar: '/static/icon-img/avatar.png',
campus: '总部校区',
phone: '13812341000',
age: 11,
enrollmentDate: '2023-01-11',
remainingCourses: 10,
expiryDate: '2023-12-31',
completedCourses: 20,
courseName: '少儿英语基础班',
recentClasses: [
{
date: '2023-09-15',
courseName: '少儿英语基础班',
timeSlot: '15:30-17:00'
},
{
date: '2023-09-08',
courseName: '少儿英语基础班',
timeSlot: '15:30-17:00'
},
{
date: '2023-09-01',
courseName: '少儿英语基础班',
timeSlot: '15:30-17:00'
}
]
},
'2': {
id: '2',
name: '李四',
avatar: '/static/icon-img/avatar.png',
campus: '西区校区',
phone: '13812341001',
age: 12,
enrollmentDate: '2023-01-12',
remainingCourses: 5,
expiryDate: '2023-11-15',
completedCourses: 25,
courseName: '少儿英语进阶班',
recentClasses: [
{
date: '2023-09-14',
courseName: '少儿英语进阶班',
timeSlot: '14:00-15:30'
},
{
date: '2023-09-07',
courseName: '少儿英语进阶班',
timeSlot: '14:00-15:30'
}
]
},
'3': {
id: '3',
name: '王五',
avatar: '/static/icon-img/avatar.png',
campus: '东区校区',
phone: '13812341002',
age: 13,
enrollmentDate: '2023-01-13',
remainingCourses: 15,
expiryDate: '2024-01-20',
completedCourses: 15,
courseName: '少儿英语口语班',
recentClasses: [
{
date: '2023-09-16',
courseName: '少儿英语口语班',
timeSlot: '10:00-11:30'
},
{
date: '2023-09-09',
courseName: '少儿英语口语班',
timeSlot: '10:00-11:30'
},
{
date: '2023-09-02',
courseName: '少儿英语口语班',
timeSlot: '10:00-11:30'
}
]
},
'4': {
id: '4',
name: '赵六',
avatar: '/static/icon-img/avatar.png',
campus: '南区校区',
phone: '13812341003',
age: 10,
enrollmentDate: '2023-02-15',
remainingCourses: 8,
expiryDate: '2023-11-30',
completedCourses: 12,
courseName: '少儿英语基础班',
recentClasses: [
{
date: '2023-09-13',
courseName: '少儿英语基础班',
timeSlot: '16:00-17:30'
},
{
date: '2023-09-06',
courseName: '少儿英语基础班',
timeSlot: '16:00-17:30'
}
]
},
'5': {
id: '5',
name: '刘七',
avatar: '/static/icon-img/avatar.png',
campus: '北区校区',
phone: '13812341004',
age: 14,
enrollmentDate: '2023-03-20',
remainingCourses: 20,
expiryDate: '2024-02-15',
completedCourses: 10,
courseName: '少儿英语进阶班',
recentClasses: [
{
date: '2023-09-12',
courseName: '少儿英语进阶班',
timeSlot: '17:00-18:30'
},
{
date: '2023-09-05',
courseName: '少儿英语进阶班',
timeSlot: '17:00-18:30'
}
]
},
'6': {
id: '6',
name: '陈八',
avatar: '/static/icon-img/avatar.png',
campus: '总部校区',
phone: '13812341005',
age: 9,
enrollmentDate: '2023-04-05',
remainingCourses: 3,
expiryDate: '2023-10-30',
completedCourses: 27,
courseName: '少儿英语口语班',
recentClasses: [
{
date: '2023-09-11',
courseName: '少儿英语口语班',
timeSlot: '14:30-16:00'
},
{
date: '2023-09-04',
courseName: '少儿英语口语班',
timeSlot: '14:30-16:00'
}
]
}
};
// ID
this.studentInfo = studentData[this.id] || {
id: this.id,
name: '未知学员',
avatar: '/static/icon-img/avatar.png',
campus: '未知校区',
phone: '暂无',
age: '暂无',
enrollmentDate: '暂无',
remainingCourses: 0,
expiryDate: '暂无',
completedCourses: 0,
courseName: '暂无',
recentClasses: []
};
}, 500);
},
contactStudent() {
if (this.studentInfo && this.studentInfo.phone) {
uni.makePhoneCall({
phoneNumber: this.studentInfo.phone.replace(/\*/g, '0')
});
}
},
viewSchedule() {
uni.navigateTo({
url: `/pages/coach/student/timetable?id=${this.id}`
});
}
}
}
</script>
<style lang="scss">
.container {
min-height: 100vh;
background-color: #F5F5F5;
}
.content {
padding: 20rpx;
}
.loading-box {
display: flex;
justify-content: center;
align-items: center;
height: 80vh;
color: #999;
font-size: 28rpx;
}
.student-header {
display: flex;
align-items: center;
background-color: #FFFFFF;
border-radius: 12rpx;
padding: 40rpx;
margin-bottom: 20rpx;
box-shadow: 0 2rpx 10rpx rgba(0, 0, 0, 0.05);
.avatar-box {
width: 150rpx;
height: 150rpx;
border-radius: 75rpx;
overflow: hidden;
margin-right: 30rpx;
.avatar-img {
width: 100%;
height: 100%;
}
}
.name-box {
display: flex;
flex-direction: column;
.name {
font-size: 36rpx;
font-weight: bold;
color: #333;
margin-bottom: 10rpx;
}
.id {
font-size: 24rpx;
color: #999;
}
}
}
.card-section {
margin-bottom: 20rpx;
.section-title {
font-size: 30rpx;
font-weight: bold;
color: #333;
margin: 30rpx 10rpx 20rpx;
}
.info-card {
background-color: #FFFFFF;
border-radius: 12rpx;
padding: 20rpx 30rpx;
box-shadow: 0 2rpx 10rpx rgba(0, 0, 0, 0.05);
}
.info-item {
display: flex;
justify-content: space-between;
padding: 20rpx 0;
border-bottom: 1px solid #F5F5F5;
&:last-child {
border-bottom: none;
}
.item-label {
color: #666;
font-size: 28rpx;
}
.item-value {
color: #333;
font-size: 28rpx;
&.highlight {
color: #FF6600;
font-weight: bold;
}
}
}
.class-item {
display: flex;
padding: 20rpx 0;
border-bottom: 1px solid #F5F5F5;
&:last-child {
border-bottom: none;
}
.class-date {
width: 180rpx;
font-size: 28rpx;
color: #666;
}
.class-info {
flex: 1;
display: flex;
flex-direction: column;
.class-name {
font-size: 28rpx;
color: #333;
margin-bottom: 10rpx;
}
.class-time {
font-size: 24rpx;
color: #999;
}
}
}
.empty-class {
padding: 40rpx 0;
text-align: center;
color: #999;
font-size: 28rpx;
}
}
.btn-group {
display: flex;
justify-content: space-between;
margin: 40rpx 0;
.btn {
width: 48%;
height: 80rpx;
line-height: 80rpx;
border-radius: 40rpx;
font-size: 30rpx;
&.primary {
background-color: #3B7CF9;
color: #FFFFFF;
}
&.secondary {
background-color: #FFFFFF;
color: #3B7CF9;
border: 1px solid #3B7CF9;
}
}
}
</style>

216
pages/coach/student/student_list.vue

@ -0,0 +1,216 @@
<template>
<view class="container">
<view class="content">
<view v-if="studentList.length === 0" class="empty-box">
<image src="/static/icon-img/empty.png" mode="aspectFit" class="empty-img"></image>
<text class="empty-text">暂无学员数据</text>
</view>
<view v-else class="student-list">
<view v-for="(item, index) in studentList" :key="index" class="student-item" @click="goToDetail(item)">
<view class="student-card">
<view class="student-avatar">
<image :src="item.avatar || '/static/icon-img/avatar.png'" mode="aspectFill" class="avatar-img"></image>
</view>
<view class="student-info">
<view class="student-name">{{item.name}}</view>
<view class="info-row">
<text class="info-label">所属校区</text>
<text class="info-value">{{item.campus}}</text>
</view>
<view class="info-row">
<text class="info-label">剩余课程</text>
<text class="info-value">{{item.remainingCourses}}</text>
</view>
<view class="info-row">
<text class="info-label">到期时间</text>
<text class="info-value">{{item.expiryDate}}</text>
</view>
</view>
<view class="arrow-right">
<uni-icons type="right" size="16" color="#CCCCCC"></uni-icons>
</view>
</view>
</view>
</view>
</view>
<AQTabber />
</view>
</template>
<script>
import AQTabber from "@/components/AQ/AQTabber.vue"
export default {
components: {
AQTabber,
},
data() {
return {
studentList: []
}
},
onLoad() {
this.getStudentList();
},
methods: {
navigateBack() {
uni.navigateBack();
},
getStudentList() {
// API
// const res = await memberApi.getStudentList({});
// if(res.code == 1) {
// this.studentList = res.data || [];
// } else {
// uni.showToast({
// title: res.msg || '',
// icon: 'none'
// });
// }
// 使
this.studentList = [
{
id: 1,
name: '张三',
avatar: '/static/icon-img/avatar.png',
campus: '总部校区',
remainingCourses: 10,
expiryDate: '2023-12-31'
},
{
id: 2,
name: '李四',
avatar: '/static/icon-img/avatar.png',
campus: '西区校区',
remainingCourses: 5,
expiryDate: '2023-11-15'
},
{
id: 3,
name: '王五',
avatar: '/static/icon-img/avatar.png',
campus: '东区校区',
remainingCourses: 15,
expiryDate: '2024-01-20'
},
{
id: 4,
name: '赵六',
avatar: '/static/icon-img/avatar.png',
campus: '南区校区',
remainingCourses: 8,
expiryDate: '2023-11-30'
},
{
id: 5,
name: '刘七',
avatar: '/static/icon-img/avatar.png',
campus: '北区校区',
remainingCourses: 20,
expiryDate: '2024-02-15'
},
{
id: 6,
name: '陈八',
avatar: '/static/icon-img/avatar.png',
campus: '总部校区',
remainingCourses: 3,
expiryDate: '2023-10-30'
}
];
},
goToDetail(student) {
uni.navigateTo({
url: `/pages/market/clue/clue_info?resource_sharing_id=25`
});
}
}
}
</script>
<style lang="scss">
.container {
min-height: 100vh;
background-color: #F5F5F5;
}
.content {
padding: 20rpx;
}
.empty-box {
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
padding-top: 200rpx;
.empty-img {
width: 200rpx;
height: 200rpx;
}
.empty-text {
margin-top: 20rpx;
font-size: 28rpx;
color: #999;
}
}
.student-list {
.student-item {
margin-bottom: 20rpx;
}
.student-card {
display: flex;
align-items: center;
background-color: #FFFFFF;
border-radius: 12rpx;
padding: 30rpx;
box-shadow: 0 2rpx 10rpx rgba(0, 0, 0, 0.05);
}
.student-avatar {
width: 120rpx;
height: 120rpx;
border-radius: 60rpx;
overflow: hidden;
margin-right: 30rpx;
.avatar-img {
width: 100%;
height: 100%;
}
}
.student-info {
flex: 1;
}
.student-name {
font-size: 32rpx;
font-weight: bold;
margin-bottom: 10rpx;
color: #333;
}
.info-row {
display: flex;
font-size: 26rpx;
margin-top: 8rpx;
.info-label {
color: #666;
}
.info-value {
color: #333;
}
}
.arrow-right {
padding-left: 20rpx;
}
}
</style>

58
pages/coach/student/work_details.vue

@ -1,6 +1,6 @@
<!--作业详情--> <!--作业详情-->
<template> <template>
<view> <view class="dark-theme">
<!-- 作业展示--> <!-- 作业展示-->
<view class="top-style" v-if="infoData.student_file"> <view class="top-style" v-if="infoData.student_file">
<video v-if="infoData.student_file_type == 2" class="pic" style="width: 100%;border-radius: 15rpx;" :src="$util.img(infoData.student_file)"></video> <video v-if="infoData.student_file_type == 2" class="pic" style="width: 100%;border-radius: 15rpx;" :src="$util.img(infoData.student_file)"></video>
@ -12,7 +12,7 @@
<view class="head-img"> <view class="head-img">
<!--教练头像--> <!--教练头像-->
<fui-avatar width="80" :src="$util.img(infoData.coach_pic)"></fui-avatar> <fui-avatar width="80" :src="$util.img(infoData.coach_pic)"></fui-avatar>
<view class="head-text">{{infoData .coach_name}}</view> <view class="head-text">{{infoData.coach_name}}</view>
</view> </view>
<view class="multi-line-ellipsis" v-html="infoData.content_text"></view> <view class="multi-line-ellipsis" v-html="infoData.content_text"></view>
</view> </view>
@ -30,22 +30,36 @@ export default {
id: '',//id id: '',//id
}, },
infoData:{}, infoData: {},
} }
}, },
onLoad(options) { onLoad(options) {
this.filteredData.id = options.id this.filteredData.id = options.id || '1' // ID1
// 使
this.mockData()
}, },
onShow(){ onShow(){
this.init()// // this.init() // -
}, },
methods: { methods: {
// //
async init(){ async init(){
this.getAssignmentsInfo() // this.getAssignmentsInfo() //
}, },
// //
mockData() {
this.infoData = {
student_file: '/static/icon-img/empty.png',
student_file_type: 1, // 1-2-
coach_pic: '/static/icon-img/default_avatar.png',
coach_name: '张教练',
content_text: '<p>这是一份作业的详细说明,包含了作业的要求和注意事项。</p><p>1. 请按照要求完成动作练习</p><p>2. 注意动作的标准性和连贯性</p><p>3. 完成后请上传视频或图片记录</p>'
}
},
// -
/*
async getAssignmentsInfo() { async getAssignmentsInfo() {
let params = {...this.filteredData} let params = {...this.filteredData}
let res = await memberApi.assignmentsInfo(params) let res = await memberApi.assignmentsInfo(params)
@ -59,19 +73,29 @@ export default {
this.infoData = res.data this.infoData = res.data
}, },
*/
} }
} }
</script> </script>
<style lang="less" scoped> <style lang="less" scoped>
.dark-theme {
background-color: #121212;
color: #ffffff;
min-height: 100vh;
padding-top: 0;
}
.top-style{ .top-style{
width: 92%; width: 92%;
height: 700rpx; height: 500rpx;
margin: auto; margin: auto;
margin-top: 45rpx; margin-top: 0;
display: flex; display: flex;
align-items: center; align-items: center;
justify-content: center; justify-content: center;
background-color: #1e1e1e;
border-radius: 15rpx;
} }
.top-style-img{ .top-style-img{
width: 120rpx; width: 120rpx;
@ -80,6 +104,10 @@ export default {
.below-style{ .below-style{
width: 92%; width: 92%;
margin: auto; margin: auto;
background-color: #1e1e1e;
border-radius: 15rpx;
margin-top: 20rpx;
padding: 20rpx 0;
} }
.head-img { .head-img {
display: flex; display: flex;
@ -87,18 +115,14 @@ export default {
padding: 10rpx 20rpx; padding: 10rpx 20rpx;
} }
.head-text { .head-text {
color: #333333; color: #ffffff;
font-size: 35rpx; font-size: 35rpx;
padding-left: 20rpx; padding-left: 20rpx;
} }
.multi-line-ellipsis { .multi-line-ellipsis {
color: #333333; color: #e0e0e0;
font-size: 29rpx; font-size: 29rpx;
padding: 5rpx 10rpx; padding: 20rpx 30rpx;
// display: -webkit-box; line-height: 1.6;
// -webkit-box-orient: vertical;
// -webkit-line-clamp: 2;
// overflow: hidden;
// text-overflow: ellipsis;
} }
</style> </style>

1
pages/market/clue/class_arrangement.vue

@ -27,6 +27,7 @@
</view> </view>
<view class="card-body"> <view class="card-body">
<view class="row">时间{{ course.course_date }}</view> <view class="row">时间{{ course.course_date }}</view>
<view class="row">校区{{ course.campus_name }}</view>
<view class="row">教室{{ course.venue.venue_name }}</view> <view class="row">教室{{ course.venue.venue_name }}</view>
<view class="row">课程{{ course.course.course_name }}</view> <view class="row">课程{{ course.course.course_name }}</view>
<view class="row">人数{{ course.available_capacity }}</view> <view class="row">人数{{ course.available_capacity }}</view>

320
pages/market/clue/class_arrangement_detail.vue

@ -6,15 +6,28 @@
</view> </view>
<view class="section"> <view class="section">
<view class="section-title">学员列表</view> <view class="section-title">学员列表</view>
<view class="student-list"> <view class="student-list" v-if="course_info && course_info.available_capacity">
<view v-for="(stu, idx) in students" :key="idx" class="student-item"> <!-- 显示已安排的学员 -->
<view class="avatar">{{ stu.name.charAt(0) }}</view> <view
v-for="(stu, idx) in students"
:key="idx"
class="student-item"
@tap="viewStudent(stu)"
>
<view class="avatar">{{ stu.name && stu.name.charAt(0) }}</view>
<view class="info"> <view class="info">
<view class="name">{{ stu.name }}</view> <view class="name">{{ stu.name }}</view>
<view class="desc">{{ getStatusText(stu.status)}}</view> <view class="desc">{{ getStatusText(stu.status) }}</view>
</view> </view>
</view> </view>
<view v-for="n in course_info.available_capacity" :key="n" class="student-item empty" @tap="addStudent" :data-index="n">
<!-- 显示空位 -->
<view
v-for="index in emptySeats"
:key="index"
class="student-item empty"
@tap="addStudent($event, index)"
>
<view class="avatar empty-avatar">+</view> <view class="avatar empty-avatar">+</view>
<view class="info"> <view class="info">
<view class="name">空位</view> <view class="name">空位</view>
@ -22,7 +35,26 @@
</view> </view>
</view> </view>
</view> </view>
<!-- 没有数据时的占位区域 -->
<view class="empty-placeholder" v-else>
<image src="/static/icon-img/empty.png" mode="aspectFit"></image>
<text>暂无课程数据</text>
</view>
</view> </view>
<!-- 请假原因弹窗 -->
<fui-modal ref="leaveReasonModal" :buttons="[]" width="600" title="请假申请">
<view class="leave-form">
<view class="leave-label">请假原因</view>
<view class="leave-input">
<fui-textarea v-model="leaveReason" placeholder="请输入请假原因" :isCounter="true" :maxlength="200" :minHeight="200" :isAutoHeight="true"></fui-textarea>
</view>
<view class="leave-buttons">
<fui-button background="#434544" color="#fff" borderColor="#666" btnSize="medium" @tap="$refs.leaveReasonModal.close()">取消</fui-button>
<fui-button background="#29d3b4" color="#fff" btnSize="medium" @tap="submitLeaveRequest">提交</fui-button>
</view>
</view>
</fui-modal>
</view> </view>
</template> </template>
@ -44,15 +76,77 @@
// desc: '' // desc: ''
// }, // },
], ],
resource_id:'' resource_id:'',
leaveReason: '', //
currentStudent: null, //
emptySeats: [] //
}; };
}, },
onLoad(query) { onLoad(query) {
console.log('onLoad 参数:', query);
this.course_id = query.id || ''; this.course_id = query.id || '';
this.resource_id = query.resource_id this.resource_id = query.resource_id
console.log('初始化参数 - course_id:', this.course_id, 'resource_id:', this.resource_id);
this.courseInfo(); this.courseInfo();
}, },
methods: { methods: {
viewStudent(stu){
console.log(stu, this.course_info);
//
if (stu.person_type === 'customer_resource') {
//
uni.showModal({
title: '取消课程',
content: `是否取消学员 ${stu.name} 的课程?`,
success: async (res) => {
if (res.confirm) {
// schedule_del
try {
uni.showLoading({
title: '处理中...'
});
const params = {
resources_id: stu.resources_id,
id: this.course_info.id
};
const result = await apiRoute.schedule_del(params);
uni.hideLoading();
if (result.code === 1) {
uni.showToast({
title: '取消课程成功',
icon: 'success'
});
//
await this.courseInfo();
} else {
uni.showToast({
title: result.msg || '取消课程失败',
icon: 'none'
});
}
} catch (error) {
uni.hideLoading();
uni.showToast({
title: '操作失败,请重试',
icon: 'none'
});
console.error('取消课程失败:', error);
}
}
}
});
} else if (stu.person_type === 'student') {
//
this.$refs.leaveReasonModal.open();
this.currentStudent = stu; //
}
},
getStatusText(status) { getStatusText(status) {
const statusMap = { const statusMap = {
0: '待上课', 0: '待上课',
@ -63,64 +157,191 @@
}, },
async scheduleList() { async scheduleList() {
try { try {
console.log('开始获取学员列表, schedule_id:', this.course_id);
let res = await apiRoute.scheduleList({ let res = await apiRoute.scheduleList({
'schedule_id': this.course_id 'schedule_id': this.course_id
}) })
console.log(res); console.log('学员列表响应:', res);
this.students = res.data
if (res.code === 1 && Array.isArray(res.data)) {
//
this.students = res.data.sort((a, b) => {
// positionposition
if (a.position !== undefined && b.position !== undefined) {
return parseInt(a.position) - parseInt(b.position);
}
// ID
return a.id - b.id;
});
} else {
this.students = [];
}
//
this.updateAvailableCapacity();
return this.students;
} catch (error) { } catch (error) {
console.error('获取信息失败:', error); console.error('获取学员列表失败:', error);
this.students = [];
return [];
} }
}, },
async courseInfo() { async courseInfo() {
try { try {
console.log('开始获取课程信息, id:', this.course_id);
let res = await apiRoute.courseInfo({ let res = await apiRoute.courseInfo({
'id': this.course_id 'id': this.course_id
}) })
this.course_info = res.data console.log('课程信息响应:', res);
this.scheduleList(); if (res.code === 1 && res.data) {
this.course_info = res.data;
//
await this.scheduleList();
//
this.updateAvailableCapacity();
} else {
uni.showToast({
title: res.msg || '获取课程信息失败',
icon: 'none'
});
}
} catch (error) { } catch (error) {
console.error('获取信息失败:', error); console.error('获取课程信息失败:', error);
uni.showToast({
title: '获取课程信息失败',
icon: 'none'
});
} }
}, },
async addStudent(e) { //
updateAvailableCapacity() {
// course_infostudents
if (!this.course_info || !this.students) return;
console.log('更新可用容量 - 课程总容量:', this.course_info.available_capacity, '学员数量:', this.students.length);
//
const occupiedSeats = this.students.length;
//
const totalCapacity = parseInt(this.course_info.available_capacity) || 0;
//
this.course_info.available_capacity = Math.max(0, totalCapacity - occupiedSeats);
console.log('计算后的可用容量:', this.course_info.available_capacity);
//
this.emptySeats = [];
for (let i = 1; i <= this.course_info.available_capacity; i++) {
this.emptySeats.push(i);
}
},
async addStudent(e, index) {
console.log('添加学员到位置:', index);
const data = { const data = {
'resources_id':this.resource_id, 'resources_id': this.resource_id,
'person_type':'customer_resource', 'person_type': 'customer_resource',
'schedule_id':this.course_id, 'schedule_id': this.course_id,
'course_date':this.course_info.course_date, 'course_date': this.course_info.course_date,
'time_slot':this.course_info.time_slot 'time_slot': this.course_info.time_slot,
'position': index //
}; };
try { try {
uni.showLoading({
title: '添加中...'
});
let res = await apiRoute.addSchedule(data) let res = await apiRoute.addSchedule(data)
uni.hideLoading();
if(res.code == 1){ if(res.code == 1){
uni.showToast({ uni.showToast({
title: '添加成功', title: '添加成功',
icon: 'none' icon: 'success'
}); });
this.courseInfo();
//
await this.courseInfo();
}else{ }else{
uni.showToast({ uni.showToast({
title: res.msg, title: res.msg || '添加失败',
icon: 'none' icon: 'none'
}); });
} }
} catch (error) { } catch (error) {
uni.hideLoading();
uni.showToast({ uni.showToast({
title: '添加失败', title: '添加失败',
icon: 'none' icon: 'none'
}); });
console.error('添加学员失败:', error);
} }
// const n = e.currentTarget.dataset.index; },
// uni.showToast({ //
// title: '' + n, submitLeaveRequest() {
// icon: 'none' if (!this.leaveReason.trim()) {
// }); uni.showToast({
title: '请填写请假原因',
icon: 'none'
});
return;
}
//
uni.showLoading({
title: '提交中...'
});
//
const params = {
resources_id: this.currentStudent.resources_id,
id: this.course_info.id,
remark: this.leaveReason
};
//
apiRoute.schedule_del(params)
.then(res => {
uni.hideLoading();
if (res.code === 1) {
uni.showToast({
title: '请假申请提交成功',
icon: 'success'
});
this.$refs.leaveReasonModal.close();
this.leaveReason = ''; //
//
this.courseInfo().then(() => {
//
this.updateAvailableCapacity();
});
} else {
uni.showToast({
title: res.msg || '请假申请提交失败',
icon: 'none'
});
}
})
.catch(err => {
uni.hideLoading();
uni.showToast({
title: '请假申请提交失败,请重试',
icon: 'none'
});
console.error('请假申请提交失败:', err);
});
}, },
}, },
}; };
@ -221,4 +442,49 @@
} }
} }
} }
//
.leave-form {
padding: 20rpx;
.leave-label {
font-size: 28rpx;
color: #333;
margin-bottom: 20rpx;
}
.leave-input {
margin-bottom: 30rpx;
}
.leave-buttons {
display: flex;
justify-content: space-between;
gap: 20rpx;
.fui-button {
flex: 1;
}
}
}
/* 空数据占位区域样式 */
.empty-placeholder {
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
padding: 60rpx 0;
image {
width: 200rpx;
height: 200rpx;
margin-bottom: 20rpx;
}
text {
color: #999;
font-size: 28rpx;
}
}
</style> </style>

4
pages/market/clue/clue_info.vue

@ -576,14 +576,14 @@
// //
handleMakeCall() { handleMakeCall() {
if (!this.clientInfo.customerResource.phone) { if (!this.clientInfo.customerResource.phone_number) {
uni.showToast({ uni.showToast({
title: '电话号码为空', title: '电话号码为空',
icon: 'none' icon: 'none'
}); });
return; return;
} }
this.callTel(this.clientInfo.customerResource.phone); this.callTel(this.clientInfo.customerResource.phone_number);
}, },
// //

190
pages/market/clue/edit_clues.vue

@ -81,8 +81,30 @@
<fui-input :borderBottom="false" :padding="[0]" placeholder="点击填写" v-model="formData.phone_number" backgroundColor="#434544" size="26" color="#fff" @blur="handlePhoneBlur"></fui-input> <fui-input :borderBottom="false" :padding="[0]" placeholder="点击填写" v-model="formData.phone_number" backgroundColor="#434544" size="26" color="#fff" @blur="handlePhoneBlur"></fui-input>
</view> </view>
</fui-form-item> </fui-form-item>
<!-- 资源是否有效 -->
<fui-form-item label="资源是否有效" labelSize='26' prop="is_valid" background='#434544' labelColor='#fff' :bottomBorder='false'>
<view class="input-title" style="margin-right:14rpx;">
<fui-radio-group name="radio" v-model="formData.efficacious">
<view class="fui-list__item" style="display: flex;justify-content: flex-end;">
<fui-label>
<view class="fui-align__center">
<fui-radio :value="1" checked></fui-radio>
<text class="fui-text"></text>
</view>
</fui-label>
<fui-label :margin="['0','0','0','40rpx']">
<view class="fui-align__center">
<fui-radio :value="0"></fui-radio>
<text class="fui-text"></text>
</view>
</fui-label>
</view>
</fui-radio-group>
</view>
</fui-form-item>
</view> </view>
<!-- 添加底部安全区 -->
<view class="safe-area-bottom"></view>
</fui-form> </fui-form>
</view> </view>
</view> </view>
@ -95,6 +117,15 @@
<view class="input-style"> <view class="input-style">
<!-- 购买力 -->
<fui-form-item label="购买力" labelSize='26' prop="purchasing_power" background='#434544' labelColor='#fff' :bottomBorder='false'>
<view class="input-title" style="margin-right:14rpx;">
<view class="input-title" style="margin-right:14rpx;" @click="openCicker('purchasing_power')">
{{ formData.purchasing_power ? picker_config.purchasing_power.text : '点击选择' }}
</view>
</view>
</fui-form-item>
<fui-form-item label="需求" labelSize='26' prop="demand" background='#434544' labelColor='#fff' :bottomBorder='false'> <fui-form-item label="需求" labelSize='26' prop="demand" background='#434544' labelColor='#fff' :bottomBorder='false'>
<view class="input-title" style="margin-right:14rpx;"> <view class="input-title" style="margin-right:14rpx;">
<fui-input :borderBottom="false" :padding="[0]" placeholder="点击填写" v-model="formData.demand" backgroundColor="#434544" size="26" color="#fff" ></fui-input> <fui-input :borderBottom="false" :padding="[0]" placeholder="点击填写" v-model="formData.demand" backgroundColor="#434544" size="26" color="#fff" ></fui-input>
@ -147,16 +178,32 @@
<fui-button background="#434544" color="#24BA9F" borderColor="#24BA9F" @click="goTrialLesson">预约体验课</fui-button> <fui-button background="#434544" color="#24BA9F" borderColor="#24BA9F" @click="goTrialLesson">预约体验课</fui-button>
</view> </view>
</fui-form-item> --> </fui-form-item> -->
<!-- 电话 --> <!-- 是否加微信 -->
<fui-form-item label="电话" labelSize='26' prop="phone_number" background='#434544' labelColor='#fff' :bottomBorder='false'> <fui-form-item label="是否加微信" labelSize='26' prop="call_intent" background='#434544' labelColor='#fff' :bottomBorder='false'>
<view class="input-title" style="margin-right:14rpx;"> <view class="input-title" style="margin-right:14rpx;">
<fui-input :borderBottom="false" :padding="[0]" placeholder="点击填写" v-model="formData.phone_number" backgroundColor="#434544" size="26" color="#fff"></fui-input> <fui-radio-group name="radio" v-model="formData.call_intent">
<view class="fui-list__item" style="display: flex;justify-content: flex-end;">
<fui-label>
<view class="fui-align__center">
<fui-radio value="1" checked></fui-radio>
<text class="fui-text"></text>
</view>
</fui-label>
<fui-label :margin="['0','0','0','40rpx']">
<view class="fui-align__center">
<fui-radio value="2"></fui-radio>
<text class="fui-text"></text>
</view>
</fui-label>
</view>
</fui-radio-group>
</view> </view>
</fui-form-item> </fui-form-item>
<!-- 备注 --> <!-- 备注 -->
<fui-form-item label="备注" labelSize='26' prop="remark" background='#434544' labelColor='#fff' :bottomBorder='false'> <fui-form-item label="备注" labelSize='26' prop="remark" background='#434544' labelColor='#fff' :bottomBorder='false'>
<view class="input-title" style="margin-right:14rpx;"> <view class="input-title" style="margin-right:14rpx;">
<fui-input :borderBottom="false" :padding="[0]" placeholder="点击填写" v-model="formData.remark" backgroundColor="#434544" size="26" color="#fff"></fui-input> <fui-textarea v-model="formData.remark" placeholder="点击填写" backgroundColor="#434544" size="26" color="#fff" :borderTop="false" :isCounter="true" :maxlength="500" :minHeight="250" :isAutoHeight="true"></fui-textarea>
</view> </view>
</fui-form-item> </fui-form-item>
<!-- 面咨记录 --> <!-- 面咨记录 -->
@ -166,6 +213,8 @@
</view> </view>
</fui-form-item> --> </fui-form-item> -->
</view> </view>
<!-- 添加底部安全区 -->
<view class="safe-area-bottom"></view>
</fui-form> </fui-form>
</view> </view>
</view> </view>
@ -177,41 +226,38 @@
<view class="title" style="margin-top: 20rpx;">跟进与面咨</view> <view class="title" style="margin-top: 20rpx;">跟进与面咨</view>
<view class="input-style"> <view class="input-style">
<!-- 一访时间 --> <!-- 一访时间 -->
<fui-form-item label="一访时间" labelSize='26' prop="first_visit_time" background='#434544' labelColor='#fff' :bottomBorder='false'> <fui-form-item label="一访时间" labelSize='26' prop="first_visit_time" background='#434544' labelColor='#fff' :bottomBorder='false'>
<view class="input-title" style="margin-right:14rpx;"> <view class="input-title" style="margin-right:14rpx;" @click="openDate('first_visit_time')">
<view class="input-title" style="margin-right:14rpx;" @click="openDate('first_visit_time')">
{{ formData.first_visit_time ? formData.first_visit_time : '点击选择' }} {{ formData.first_visit_time ? formData.first_visit_time : '点击选择' }}
</view> </view>
</view>
</fui-form-item> </fui-form-item>
<!-- 一访情况 --> <!-- 一访情况 -->
<fui-form-item label="一访情况" labelSize='26' prop="first_visit_status" background='#434544' labelColor='#fff' :bottomBorder='false'> <fui-form-item label="一访情况" labelSize='26' prop="first_visit_status" background='#434544' labelColor='#fff' :bottomBorder='false'>
<view class="input-title" style="margin-right:14rpx;"> <view class="textarea-container">
<fui-input :borderBottom="false" :padding="[0]" placeholder="点击填写" v-model="formData.first_visit_status" backgroundColor="#434544" size="26" color="#fff"></fui-input> <fui-textarea v-model="formData.first_visit_status" placeholder="点击填写" backgroundColor="#434544" size="26" color="#fff" :textareaBorder="false" :isCounter="true" :maxlength="500" :minHeight="120" :isAutoHeight="true" :borderTop="false"></fui-textarea>
</view> </view>
</fui-form-item> </fui-form-item>
<!-- 二访时间 --> <!-- 二访时间 -->
<fui-form-item label="二访时间" labelSize='26' prop="second_visit_time" background='#434544' labelColor='#fff' :bottomBorder='false'> <fui-form-item label="二访时间" labelSize='26' prop="second_visit_time" background='#434544' labelColor='#fff' :bottomBorder='false'>
<view class="input-title" style="margin-right:14rpx;"> <view class="input-title" style="margin-right:14rpx;" @click="openDate('second_visit_time')">
<view class="input-title" style="margin-right:14rpx;" @click="openDate('second_visit_time')">
{{ formData.second_visit_time ? formData.second_visit_time : '点击选择' }} {{ formData.second_visit_time ? formData.second_visit_time : '点击选择' }}
</view> </view>
</view>
</fui-form-item> </fui-form-item>
<!-- 二访情况 --> <!-- 二访情况 -->
<fui-form-item label="二访情况" labelSize='26' prop="second_visit_status" background='#434544' labelColor='#fff' :bottomBorder='false'> <fui-form-item label="二访情况" labelSize='26' prop="second_visit_status" background='#434544' labelColor='#fff' :bottomBorder='false'>
<view class="input-title" style="margin-right:14rpx;"> <view class="textarea-container">
<fui-input :borderBottom="false" :padding="[0]" placeholder="点击填写" v-model="formData.second_visit_status" backgroundColor="#434544" size="26" color="#fff"></fui-input> <fui-textarea v-model="formData.second_visit_status" placeholder="点击填写" backgroundColor="#434544" size="26" color="#fff" :textareaBorder="false" :isCounter="true" :maxlength="500" :minHeight="120" :isAutoHeight="true" :borderTop="false"></fui-textarea>
</view> </view>
</fui-form-item> </fui-form-item>
<fui-form-item label="追单标注" labelSize='26' prop="chasing_orders" background='#434544' labelColor='#fff' :bottomBorder='false'> <fui-form-item label="追单标注" labelSize='26' prop="chasing_orders" background='#434544' labelColor='#fff' :bottomBorder='false'>
<view class="input-title" style="margin-right:14rpx;"> <view class="textarea-container">
<fui-input :borderBottom="false" :padding="[0]" placeholder="点击填写" v-model="formData.chasing_orders" backgroundColor="#434544" size="26" color="#fff"></fui-input> <fui-textarea v-model="formData.chasing_orders" placeholder="点击填写" backgroundColor="#434544" size="26" color="#fff" :textareaBorder="false" :isCounter="true" :maxlength="500" :minHeight="120" :isAutoHeight="true" :borderTop="false"></fui-textarea>
</view> </view>
</fui-form-item> </fui-form-item>
<fui-form-item label="是否报名" labelSize='26' prop="is_bm" background='#434544' labelColor='#fff' :bottomBorder='false'> <fui-form-item label="是否报名" labelSize='26' prop="is_bm" background='#434544' labelColor='#fff' :bottomBorder='false'>
<view class="input-title" style="margin-right:14rpx;"> <view class="input-title" style="margin-right:14rpx;">
<fui-radio-group name="radio" v-model="formData.is_bm" :disabled="true"> <fui-radio-group name="radio" v-model="formData.is_bm" :disabled="true">
<view class="fui-list__item" style="display: flex;justify-content: flex-end;"> <view class="fui-list__item" style="display: flex;justify-content: flex-end;">
@ -233,14 +279,16 @@
</fui-form-item> </fui-form-item>
<!-- 面咨备注 --> <!-- 面咨备注 -->
<fui-form-item label="面咨备注" labelSize='26' prop="consultation_remark" background='#434544' labelColor='#fff' :bottomBorder='false'> <fui-form-item label="面咨备注" labelSize='26' prop="consultation_remark" background='#434544' labelColor='#fff' :bottomBorder='false'>
<view class="input-title" style="margin-right:14rpx;"> <view class="textarea-container">
<fui-input :borderBottom="false" :padding="[0]" placeholder="点击填写" v-model="formData.consultation_remark" backgroundColor="#434544" size="26" color="#fff"></fui-input> <fui-textarea v-model="formData.consultation_remark" placeholder="点击填写" backgroundColor="#434544" size="26" color="#fff" :maxlength="500" :minHeight="120" :isAutoHeight="true" :borderTop="false"></fui-textarea>
</view> </view>
</fui-form-item> </fui-form-item>
<!-- 标识 --> <!-- 标识 -->
</view> </view>
<!-- 添加底部安全区 -->
<view class="safe-area-bottom"></view>
</fui-form> </fui-form>
</view> </view>
</view> </view>
@ -363,7 +411,8 @@
optional_class_time: '', // optional_class_time: '', //
first_visit_status: '', //访 first_visit_status: '', //访
second_visit_status: '', //访 second_visit_status: '', //访
efficacious:'' efficacious:'1',
call_intent:'2'
}, },
// //
@ -417,6 +466,20 @@
text: '', text: '',
options: [], options: [],
}, },
//
call_intent: {
text: '',
options: [
{
text:'是',
value:'1'
},
{
text:'否',
value:'2'
}
],
},
// //
status: { status: {
text: '', text: '',
@ -524,7 +587,7 @@
this.getDict('status'), //- this.getDict('status'), //-
this.getDict('decision_maker'), //- this.getDict('decision_maker'), //-
this.getDict('distance'), //- this.getDict('distance'), //-
// this.getDict('customer_type'), //-
]; ];
await Promise.all(dictPromises); await Promise.all(dictPromises);
@ -645,7 +708,8 @@
consultation_remark: sixSpeed.consultation_remark || '', // consultation_remark: sixSpeed.consultation_remark || '', //
chasing_orders: sixSpeed.chasing_orders || '', // chasing_orders: sixSpeed.chasing_orders || '', //
is_bm: sixSpeed.is_bm || 2, // is_bm: sixSpeed.is_bm || 2, //
efficacious: sixSpeed.efficacious || '' efficacious: sixSpeed.efficacious || '',
call_intent: sixSpeed.call_intent || '', //
}; };
console.log('getInfo - 表单数据设置完成:', this.formData); console.log('getInfo - 表单数据设置完成:', this.formData);
@ -702,6 +766,7 @@
this.setPickerTextByValue('purchasing_power', this.formData.purchasing_power, sixSpeed.purchase_power_name); this.setPickerTextByValue('purchasing_power', this.formData.purchasing_power, sixSpeed.purchase_power_name);
this.setPickerTextByValue('cognitive_idea', this.formData.cognitive_idea, sixSpeed.concept_awareness_name); this.setPickerTextByValue('cognitive_idea', this.formData.cognitive_idea, sixSpeed.concept_awareness_name);
this.setPickerTextByValue('distance', this.formData.distance, sixSpeed.distance_name); this.setPickerTextByValue('distance', this.formData.distance, sixSpeed.distance_name);
// call_intent
console.log('选择器文本回显完成'); console.log('选择器文本回显完成');
} catch (error) { } catch (error) {
@ -867,6 +932,10 @@
case 'cognitive_idea': case 'cognitive_idea':
key = 'cognitive_concept'; key = 'cognitive_concept';
break; break;
// -
case 'call_intent':
return Promise.resolve();
break;
// //
case 'decision_maker': case 'decision_maker':
key = 'decision_maker'; key = 'decision_maker';
@ -1343,6 +1412,13 @@
height: 100vh; height: 100vh;
background: #292929; background: #292929;
overflow: auto; overflow: auto;
:deep(.fui-form__item-bottom) {
background: transparent !important;
left: 0 !important;
right: 0 !important;
display: none !important;
}
} }
.title { .title {
@ -1359,6 +1435,13 @@
.form-style { .form-style {
width: 100%; width: 100%;
// background: #434544; // background: #434544;
:deep(.fui-form__item-bottom) {
background: transparent !important;
left: 0 !important;
right: 0 !important;
display: none !important;
}
} }
.form-style-vid { .form-style-vid {
@ -1370,6 +1453,50 @@
.input-style { .input-style {
text-align: right !important; text-align: right !important;
:deep(.fui-label__text) {
margin-top: 10rpx;
}
:deep(.fui-form__item-flex) {
align-items: flex-start !important;
}
:deep(.fui-form__item-flex-start) {
align-items: flex-start !important;
}
:deep(.fui-textarea__wrap) {
border: none !important;
padding: 0 !important;
}
:deep(.fui-textarea__counter) {
padding-right: 0 !important;
}
}
.textarea-container {
width: 100%;
padding: 0 0 20rpx 0;
:deep(.fui-textarea__wrap) {
border: none !important;
padding: 0 !important;
background-color: #434544;
}
:deep(.fui-textarea__placeholder) {
text-align: left;
}
:deep(.fui-textarea__inner) {
text-align: left;
}
:deep(.fui-form__item-bottom) {
display: none !important;
}
} }
.fui-btn__box { .fui-btn__box {
@ -1539,4 +1666,9 @@
padding: 20rpx 40rpx 40rpx 40rpx; padding: 20rpx 40rpx 40rpx 40rpx;
box-shadow: 0 -2rpx 8rpx rgba(0,0,0,0.12); box-shadow: 0 -2rpx 8rpx rgba(0,0,0,0.12);
} }
.safe-area-bottom {
width: 100%;
height: 180rpx; /* 增加高度,确保有足够的空间 */
}
</style> </style>

33
pages/market/data/statistics.vue

@ -1,6 +1,6 @@
<!--市场数据统计页面--> <!--市场数据统计页面-->
<template> <template>
<view class="main_box"> <view class="main_box" :class="{'has-safe-area': hasSafeArea}">
<!--自定义导航栏--> <!--自定义导航栏-->
<view class="navbar_section"> <view class="navbar_section">
<view class="title">市场数据统计</view> <view class="title">市场数据统计</view>
@ -78,13 +78,18 @@
</view> </view>
</view> </view>
</view> </view>
<AQTabber />
</view> </view>
</template> </template>
<script> <script>
import apiRoute from '@/api/apiRoute.js'; import apiRoute from '@/api/apiRoute.js';
import AQTabber from "@/components/AQ/AQTabber.vue"
export default { export default {
components: {
AQTabber,
},
data() { data() {
return { return {
currentDate: this.formatDate(new Date()), currentDate: this.formatDate(new Date()),
@ -93,6 +98,8 @@ export default {
staffData: [], staffData: [],
// //
schoolList: [], schoolList: [],
//
hasSafeArea: false,
// //
channelList: [], channelList: [],
// //
@ -110,6 +117,7 @@ export default {
}, },
onLoad() { onLoad() {
this.initData(); this.initData();
this.checkSafeArea();
}, },
methods: { methods: {
// YYYY-MM // YYYY-MM
@ -189,6 +197,19 @@ export default {
total total
} }
}); });
},
//
checkSafeArea() {
try {
const systemInfo = uni.getSystemInfoSync();
// iPhone X
if (systemInfo.safeAreaInsets && systemInfo.safeAreaInsets.bottom > 0) {
this.hasSafeArea = true;
}
} catch (e) {
console.error('获取系统信息失败', e);
}
} }
} }
} }
@ -199,7 +220,13 @@ export default {
min-height: 100vh; min-height: 100vh;
background-color: #1a1a1a; background-color: #1a1a1a;
color: #ffffff; color: #ffffff;
padding-bottom: 30rpx; padding-bottom: 150rpx; /* 增加底部内边距,防止内容被底部导航栏遮挡 */
}
/* 适配有安全区域的设备(如iPhone X及以上机型) */
.has-safe-area {
padding-bottom: calc(150rpx + constant(safe-area-inset-bottom)); /* iOS 11.0-11.2 */
padding-bottom: calc(150rpx + env(safe-area-inset-bottom)); /* iOS 11.2+ */
} }
.navbar_section { .navbar_section {
@ -313,4 +340,4 @@ export default {
font-weight: bold; font-weight: bold;
} }
} }
</style> </style>

4
pages/market/home/index.vue

@ -161,9 +161,9 @@
<image :src="$util.img('/uniapp_src/static/images/index/danlv.png')" <image :src="$util.img('/uniapp_src/static/images/index/danlv.png')"
class="drop-image-x"></image> class="drop-image-x"></image>
</view> </view>
<view class="title-x">资源未分配数量</view> <view class="title-x">其他奖励</view>
</view> </view>
<view class="title-x1">{{infoData.last_month.wfpsl}}</view> <view class="title-x1">{{infoData.last_month.qtjl}}</view>
</view> </view>

4
uni_modules/uni-calendar/components/uni-calendar/uni-calendar.vue

@ -380,7 +380,7 @@
top: 0; top: 0;
left: 0; left: 0;
right: 0; right: 0;
background-color: $uni-bg-color-mask; background-color: $bg-color-mask;
transition-property: opacity; transition-property: opacity;
transition-duration: 0.3s; transition-duration: 0.3s;
opacity: 0; opacity: 0;
@ -458,7 +458,7 @@
border-top-left-radius: 25px; border-top-left-radius: 25px;
border-bottom-left-radius: 25px; border-bottom-left-radius: 25px;
color: $uni-text-color; color: $uni-text-color;
background-color: $uni-bg-color-hover; background-color: $bg-color-hover;
} }
.uni-calendar__header-text { .uni-calendar__header-text {

2
uni_modules/uni-scss/styles/setting/_color.scss

@ -31,7 +31,7 @@ $uni-ui-color:(
secondary-color: $uni-secondary-color, secondary-color: $uni-secondary-color,
extra-color: $uni-extra-color, extra-color: $uni-extra-color,
// 背景色 // 背景色
bg-color: $uni-bg-color, bg-color: $bg-color,
// 边框颜色 // 边框颜色
border-1: $uni-border-1, border-1: $uni-border-1,
border-2: $uni-border-2, border-2: $uni-border-2,

2
uni_modules/uni-scss/styles/setting/_variables.scss

@ -130,7 +130,7 @@ $uni-white: #ffffff !default;
$uni-transparent: rgba($color: #000000, $alpha: 0) !default; $uni-transparent: rgba($color: #000000, $alpha: 0) !default;
// 背景色 // 背景色
$uni-bg-color: #f7f7f7 !default; $bg-color:: #f7f7f7 !default;
/* 水平间距 */ /* 水平间距 */
$uni-spacing-sm: 8px !default; $uni-spacing-sm: 8px !default;

2
uni_modules/uni-scss/theme.scss

@ -18,7 +18,7 @@ $uni-base-color: #606266;
$uni-secondary-color: #909399; $uni-secondary-color: #909399;
$uni-extra-color: #C0C4CC; $uni-extra-color: #C0C4CC;
// 背景色 // 背景色
$uni-bg-color: #f5f5f5; $bg-color: #f5f5f5;
// 边框颜色 // 边框颜色
$uni-border-1: #DCDFE6; $uni-border-1: #DCDFE6;
$uni-border-2: #E4E7ED; $uni-border-2: #E4E7ED;

2
uni_modules/uni-scss/variables.scss

@ -46,7 +46,7 @@ $uni-white: #ffffff;
$uni-transparent: rgba($color: #000000, $alpha: 0); $uni-transparent: rgba($color: #000000, $alpha: 0);
// 背景色 // 背景色
$uni-bg-color: #f7f7f7; $bg-color: #f7f7f7;
/* 水平间距 */ /* 水平间距 */
$uni-spacing-sm: 8px; $uni-spacing-sm: 8px;

Loading…
Cancel
Save