Merge branch 'dev_qiaofei'
This commit is contained in:
commit
b004356582
6
.vscode/settings.json
vendored
Normal file
6
.vscode/settings.json
vendored
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
{
|
||||||
|
"i18n-ally.localesPaths": [
|
||||||
|
"src/static/system/pdfReader/locale",
|
||||||
|
"src/components/BasicListLayout/zPaging/z-paging/i18n"
|
||||||
|
]
|
||||||
|
}
|
||||||
9196
pnpm-lock.yaml
generated
9196
pnpm-lock.yaml
generated
File diff suppressed because it is too large
Load Diff
@ -40,3 +40,28 @@ export const fractionRuleApi1 = async () => {
|
|||||||
"/api/fractionRule/findAllByItemId?itemId=B96A0FA22C414F71A3E1CDCA7E206B10"
|
"/api/fractionRule/findAllByItemId?itemId=B96A0FA22C414F71A3E1CDCA7E206B10"
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// 查询教师信息
|
||||||
|
export const jsdfindJsByPhoneApi = async (params: any) => {
|
||||||
|
return await get("/api/js/findJsByPhone", params);
|
||||||
|
};
|
||||||
|
|
||||||
|
// 选课列表
|
||||||
|
export const jsdXkListApi = async (params: any) => {
|
||||||
|
return await get("/mobile/js/xk/list", params);
|
||||||
|
};
|
||||||
|
|
||||||
|
// 选课列表
|
||||||
|
export const jsdXkkcSaveApi = async (params: any) => {
|
||||||
|
return await post("/api/xkkc/save", params);
|
||||||
|
};
|
||||||
|
|
||||||
|
// 选课学生列表
|
||||||
|
export const jsdXkXsListApi = async (params: any) => {
|
||||||
|
return await get("/mobile/js/xkxs/list", params);
|
||||||
|
};
|
||||||
|
|
||||||
|
// 提交点名信息
|
||||||
|
export const jsdXkdmListApi = async (params: any) => {
|
||||||
|
return await post("/mobile/js/xkdm/add", params);
|
||||||
|
};
|
||||||
6
src/api/system/config/index.ts
Normal file
6
src/api/system/config/index.ts
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
import { get, post } from "@/utils/request";
|
||||||
|
|
||||||
|
//字典接口
|
||||||
|
export const dmBeforeMinuteApi = async () => {
|
||||||
|
return await get("/api/comConfig/getDmBeforeMinute");
|
||||||
|
};
|
||||||
@ -1,5 +1,5 @@
|
|||||||
// const ip: string = "192.168.8.35:8897";
|
const ip: string = "192.168.239.1:8897";
|
||||||
const ip: string = "yufangzc.com";
|
// const ip: string = "yufangzc.com";
|
||||||
const fwqip: string = "yufangzc.com";
|
const fwqip: string = "yufangzc.com";
|
||||||
//打包服务器接口代理标识
|
//打包服务器接口代理标识
|
||||||
const SERVERAGENT: string = "/jsd-api";
|
const SERVERAGENT: string = "/jsd-api";
|
||||||
@ -7,7 +7,7 @@ const SERVERAGENT: string = "/jsd-api";
|
|||||||
export const HOMEAGENT: string = "";
|
export const HOMEAGENT: string = "";
|
||||||
// 接口地址
|
// 接口地址
|
||||||
export const BASE_URL: string =
|
export const BASE_URL: string =
|
||||||
process.env.NODE_ENV == "development" ? `https://${ip}/zhxy` : SERVERAGENT;
|
process.env.NODE_ENV == "development" ? `http://${ip}/zhxy` : SERVERAGENT;
|
||||||
// WebSocket地址
|
// WebSocket地址
|
||||||
export const BASE_WS_URL: string = `wss://${ip}`;
|
export const BASE_WS_URL: string = `wss://${ip}`;
|
||||||
//图片地址
|
//图片地址
|
||||||
|
|||||||
@ -385,16 +385,16 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"path": "pages/base/groupTeaching/zhujiao",
|
"path": "pages/base/groupTeaching/xkList",
|
||||||
"style": {
|
"style": {
|
||||||
"navigationBarTitleText": "zhujiao",
|
"navigationBarTitleText": "选课列表",
|
||||||
"enablePullDownRefresh": false
|
"enablePullDownRefresh": false
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"path": "pages/base/groupTeaching/zhujiaoDetails",
|
"path": "pages/base/groupTeaching/xkkcDetail",
|
||||||
"style": {
|
"style": {
|
||||||
"navigationBarTitleText": "zhujiaoDetails"
|
"navigationBarTitleText": "选课课程详情"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@ -412,7 +412,13 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"path": "pages/base/groupTeaching/studentRollCall",
|
"path": "pages/base/groupTeaching/dmXkList",
|
||||||
|
"style": {
|
||||||
|
"navigationBarTitleText": "选课列表"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"path": "pages/base/groupTeaching/dmXkkcDetail",
|
||||||
"style": {
|
"style": {
|
||||||
"navigationBarTitleText": "学生点名",
|
"navigationBarTitleText": "学生点名",
|
||||||
"enablePullDownRefresh": false
|
"enablePullDownRefresh": false
|
||||||
|
|||||||
525
src/pages/base/groupTeaching/dmXkList.vue
Normal file
525
src/pages/base/groupTeaching/dmXkList.vue
Normal file
@ -0,0 +1,525 @@
|
|||||||
|
<template>
|
||||||
|
<view class="interest-course">
|
||||||
|
<!-- 选课信息头部 - 固定部分 -->
|
||||||
|
<view class="selection-header">
|
||||||
|
<view class="header-content">
|
||||||
|
<view class="title-section" @click="clickShowXkSelector">
|
||||||
|
<view class="title">
|
||||||
|
<text v-if="xkData && xkData.xkmc">{{ xkData.xkmc }}</text>
|
||||||
|
<text v-else>选课信息</text>
|
||||||
|
</view>
|
||||||
|
<view class="switch-btn" v-if="xkList.length > 1">切换</view>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
|
||||||
|
<!-- 可滚动的内容区域 -->
|
||||||
|
<view class="scrollable-content">
|
||||||
|
<!-- 课程网格列表 -->
|
||||||
|
<view class="course-list" v-if="xkkcList && xkkcList.length > 0">
|
||||||
|
<view v-for="(xkkc, index) in xkkcList" :key="xkkc.id || index" class="course-item">
|
||||||
|
<view class="course-name">{{ xkkc.kcmc }}</view>
|
||||||
|
<view class="course-info-item">
|
||||||
|
<view class="info-label">上课周期类型:</view>
|
||||||
|
<view class="info-data">{{ xkkc.skzqlx }}</view>
|
||||||
|
</view>
|
||||||
|
<view class="course-info-item">
|
||||||
|
<view class="info-label">上课周期:</view>
|
||||||
|
<view class="info-data">{{ xkkc.skzqmc }}</view>
|
||||||
|
</view>
|
||||||
|
<view class="course-info-item">
|
||||||
|
<view class="info-label">上课开始时间:</view>
|
||||||
|
<view class="info-data">{{ xkkc.skkstime }}</view>
|
||||||
|
</view>
|
||||||
|
<view class="course-info-item">
|
||||||
|
<view class="info-label">上课结束时间:</view>
|
||||||
|
<view class="info-data">{{ xkkc.skjstime }}</view>
|
||||||
|
</view>
|
||||||
|
<view class="course-info-item">
|
||||||
|
<view class="info-label">开课地点:</view>
|
||||||
|
<view class="info-data">{{ xkkc.kcdd }}</view>
|
||||||
|
</view>
|
||||||
|
<view class="course-info-item">
|
||||||
|
<view class="info-label">上课人数:</view>
|
||||||
|
<view class="info-data">{{ xkkc.hasNum || 0 }} | {{ xkkc.maxNum || 0 }}</view>
|
||||||
|
</view>
|
||||||
|
<view class="course-btn-group">
|
||||||
|
<view class="dm-btn" @click.stop="goDm(xkkc)">点名</view>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
|
||||||
|
<!-- 暂无数据提示 -->
|
||||||
|
<view v-else class="empty-course-list">
|
||||||
|
<view class="empty-icon">
|
||||||
|
<u-icon name="list" size="50" color="#C8C9CC"></u-icon>
|
||||||
|
</view>
|
||||||
|
<view class="empty-text">暂无课程数据</view>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
|
||||||
|
<view>
|
||||||
|
<!-- 俱乐部选择弹窗 -->
|
||||||
|
<u-popup :show="showXkFlag" @close="showXkFlag = false" mode="bottom" round="10">
|
||||||
|
<view class="xk-selector">
|
||||||
|
<view class="selector-header">
|
||||||
|
<text class="selector-title">选择俱乐部</text>
|
||||||
|
<u-icon name="close" size="20" @click="showXkFlag = false"></u-icon>
|
||||||
|
</view>
|
||||||
|
<view class="xk-list">
|
||||||
|
<view v-for="(xk, index) in xkList" :key="index" class="xk-item" :class="{
|
||||||
|
'xk-item-active': xkData.id === xk.id
|
||||||
|
}" @click="switchXk(xk)">
|
||||||
|
<view class="xk-info">
|
||||||
|
<text class="xk-name">{{ xk.xkmc }}</text>
|
||||||
|
<text class="xk-type">{{ xk.xkmc }}</text>
|
||||||
|
</view>
|
||||||
|
<u-icon v-if="xkData.id === xk.id" name="checkmark" color="#409EFF" size="20"></u-icon>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
</u-popup>
|
||||||
|
</view>
|
||||||
|
|
||||||
|
</view>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script setup lang="ts">
|
||||||
|
import {
|
||||||
|
ref,
|
||||||
|
onBeforeUnmount,
|
||||||
|
onMounted,
|
||||||
|
} from "vue";
|
||||||
|
import { useUserStore } from "@/store/modules/user";
|
||||||
|
import { useDataStore } from "@/store/modules/data";
|
||||||
|
import { jsdXkListApi } from "@/api/base/server";
|
||||||
|
import { dmBeforeMinuteApi } from "@/api/system/config/index";
|
||||||
|
import dayjs from "dayjs";
|
||||||
|
|
||||||
|
const { getJs } = useUserStore();
|
||||||
|
const { getData, setData } = useDataStore();
|
||||||
|
|
||||||
|
const wdNameList = ["周一", "周二", "周三", "周四", "周五", "周六", "周日"];
|
||||||
|
|
||||||
|
// 控制选择器显示状态
|
||||||
|
const showXkFlag = ref(false);
|
||||||
|
|
||||||
|
const xkList = ref<any>([]);
|
||||||
|
|
||||||
|
const xkData = ref();
|
||||||
|
|
||||||
|
const courseInfo = ref<any>({});
|
||||||
|
|
||||||
|
// 课程列表数据
|
||||||
|
const xkkcList = ref<any[]>([]);
|
||||||
|
|
||||||
|
const dmBeforeMinute = ref<number>(0);
|
||||||
|
|
||||||
|
onMounted(async () => {
|
||||||
|
uni.showLoading({
|
||||||
|
title: "加载中...",
|
||||||
|
});
|
||||||
|
await loadCourseList();
|
||||||
|
await loadDmBeforeMinute();
|
||||||
|
uni.hideLoading();
|
||||||
|
});
|
||||||
|
|
||||||
|
// 加载课程列表
|
||||||
|
const loadCourseList = async () => {
|
||||||
|
const res = await jsdXkListApi({
|
||||||
|
jsId: getJs.id
|
||||||
|
});
|
||||||
|
if (res.resultCode == 1) {
|
||||||
|
if (res.result && res.result.length) {
|
||||||
|
xkList.value = res.result;
|
||||||
|
switchXk(res.result[0]);
|
||||||
|
} else {
|
||||||
|
xkList.value = [];
|
||||||
|
xkData.value = {};
|
||||||
|
xkkcList.value = [];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
// 获取点名时间提前分钟数
|
||||||
|
const loadDmBeforeMinute = async () => {
|
||||||
|
const res = await dmBeforeMinuteApi();
|
||||||
|
if (res.resultCode == 1) {
|
||||||
|
// 将res.result从字符串转换成int的number赋给dmBeforeMinute
|
||||||
|
dmBeforeMinute.value = parseInt(res.result);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 显示选课选择器
|
||||||
|
function clickShowXkSelector() {
|
||||||
|
if (xkList.value.length > 1) {
|
||||||
|
showXkFlag.value = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 切换选课
|
||||||
|
function switchXk(xk: any) {
|
||||||
|
xkData.value = xk;
|
||||||
|
xkkcList.value = xk.xkkcs;
|
||||||
|
showXkFlag.value = false;
|
||||||
|
for (let i = 0; i < xk.xkkcs.length; i++) {
|
||||||
|
let xkkc = xk.xkkcs[i];
|
||||||
|
// 判断周期
|
||||||
|
switch (xkkc.skzqlx) {
|
||||||
|
case '每天':
|
||||||
|
xkkc.skzqmc = "每天";
|
||||||
|
break;
|
||||||
|
case '每周':
|
||||||
|
const daysOfWeek = xkkc.skzq.split(',').map(Number);
|
||||||
|
// 从wdNameList读取daysOfWeek对应的周几
|
||||||
|
xkkc.skzqmc = daysOfWeek.map((day: number) => wdNameList[day - 1]).join(',');
|
||||||
|
break;
|
||||||
|
case '每月':
|
||||||
|
const daysOfMonth = xkkc.skzq.split(',').map(Number);
|
||||||
|
// 从根据编号加
|
||||||
|
xkkc.skzqmc = daysOfMonth.map((day: number) => day + "号").join(',');
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// 显示切换成功提示
|
||||||
|
uni.showToast({
|
||||||
|
title: `已切换到${xk.xkmc}`,
|
||||||
|
icon: "none",
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
// 跳转到点名
|
||||||
|
const goDm = (xkkc: any) => {
|
||||||
|
const now = dayjs();
|
||||||
|
let wDay = now.day();
|
||||||
|
if (wDay === 0) {
|
||||||
|
wDay = 7;
|
||||||
|
}
|
||||||
|
let mDay = now.date();
|
||||||
|
const strDate = now.format('YYYY-MM-DD') + ' ';
|
||||||
|
let dmFlag = false;
|
||||||
|
let msg = "";
|
||||||
|
// 判断周期
|
||||||
|
switch (xkkc.skzqlx) {
|
||||||
|
case '每天':
|
||||||
|
dmFlag = true;
|
||||||
|
break;
|
||||||
|
case '每周':
|
||||||
|
const daysOfWeek = xkkc.skzq.split(',').map(Number);
|
||||||
|
dmFlag = daysOfWeek.includes(wDay);
|
||||||
|
// 从wdNameList读取daysOfWeek对应的周几
|
||||||
|
xkkc.skzqmc = daysOfWeek.map((day: number) => wdNameList[day - 1]).join(',');
|
||||||
|
break;
|
||||||
|
case '每月':
|
||||||
|
const daysOfMonth = xkkc.skzq.split(',').map(Number);
|
||||||
|
dmFlag = daysOfMonth.includes(mDay);
|
||||||
|
// 从根据编号加
|
||||||
|
xkkc.skzqmc = daysOfMonth.map((day: number) => day + "号").join(',');
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
// 判断日期是否合格
|
||||||
|
if (dmFlag) {
|
||||||
|
// xkkc.skkstime开始时间向前dmBeforeMinute分钟
|
||||||
|
const startTime = dayjs(strDate + xkkc.skkstime).subtract(dmBeforeMinute.value, 'minute').format('YYYY-MM-DD HH:mm:ss');
|
||||||
|
const endTime = dayjs(strDate + xkkc.skjstime, 'YYYY-MM-DD HH:mm:ss');
|
||||||
|
dmFlag = now.isBefore(endTime) && now.isAfter(startTime)
|
||||||
|
} else {
|
||||||
|
msg = "没到点名日期";
|
||||||
|
}
|
||||||
|
if (dmFlag) {
|
||||||
|
setData(xkkc);
|
||||||
|
uni.navigateTo({
|
||||||
|
url: `/pages/base/groupTeaching/dmXkkcDetail`,
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
if (msg === "") {
|
||||||
|
msg = "没到点名时间";
|
||||||
|
}
|
||||||
|
uni.showToast({
|
||||||
|
title: msg,
|
||||||
|
icon: 'none',
|
||||||
|
duration: 2000
|
||||||
|
});
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
// 页面卸载前清除定时器
|
||||||
|
onBeforeUnmount(() => {
|
||||||
|
});
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style lang="scss" scoped>
|
||||||
|
.interest-course {
|
||||||
|
min-height: 100%;
|
||||||
|
background-color: #f5f7fa;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
height: 100%;
|
||||||
|
overflow: hidden;
|
||||||
|
}
|
||||||
|
|
||||||
|
.nav-bar {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: space-between;
|
||||||
|
padding: 15px;
|
||||||
|
height: 44px;
|
||||||
|
background-color: #fff;
|
||||||
|
|
||||||
|
.nav-left {
|
||||||
|
width: 40px;
|
||||||
|
height: 40px;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.nav-title {
|
||||||
|
font-size: 18px;
|
||||||
|
font-weight: 500;
|
||||||
|
color: #333;
|
||||||
|
}
|
||||||
|
|
||||||
|
.nav-right {
|
||||||
|
width: 40px;
|
||||||
|
display: flex;
|
||||||
|
justify-content: flex-end;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.selection-header {
|
||||||
|
background: linear-gradient(135deg, #4a90e2, #2879ff);
|
||||||
|
padding: 20px 15px;
|
||||||
|
color: #fff;
|
||||||
|
border-radius: 0 0 15px 15px;
|
||||||
|
box-shadow: 0 4px 12px rgba(40, 121, 255, 0.2);
|
||||||
|
position: sticky;
|
||||||
|
top: 0;
|
||||||
|
left: 0;
|
||||||
|
right: 0;
|
||||||
|
z-index: 10;
|
||||||
|
|
||||||
|
.header-content {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
gap: 15px;
|
||||||
|
|
||||||
|
.title-section {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
|
||||||
|
.title {
|
||||||
|
flex: 1 0 1px;
|
||||||
|
font-size: 24px;
|
||||||
|
font-weight: bold;
|
||||||
|
}
|
||||||
|
|
||||||
|
.subtitle {
|
||||||
|
font-size: 14px;
|
||||||
|
opacity: 0.8;
|
||||||
|
}
|
||||||
|
|
||||||
|
.switch-btn {
|
||||||
|
padding: 5px 15px;
|
||||||
|
background-color: rgba(255, 255, 255, 0.2);
|
||||||
|
color: #fff;
|
||||||
|
border-radius: 15px;
|
||||||
|
font-size: 15px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 可滚动内容区域样式
|
||||||
|
.scrollable-content {
|
||||||
|
flex: 1;
|
||||||
|
overflow-y: auto;
|
||||||
|
-webkit-overflow-scrolling: touch; // 增强iOS滚动体验
|
||||||
|
}
|
||||||
|
|
||||||
|
.course-list {
|
||||||
|
padding: 15px 15px 0 15px;
|
||||||
|
|
||||||
|
.course-item {
|
||||||
|
position: relative;
|
||||||
|
width: 100%;
|
||||||
|
margin-bottom: 15px;
|
||||||
|
background-color: #fff;
|
||||||
|
border-radius: 8px;
|
||||||
|
padding: 15px;
|
||||||
|
box-sizing: border-box;
|
||||||
|
border: 1px solid transparent;
|
||||||
|
transition: all 0.3s ease;
|
||||||
|
|
||||||
|
// &:nth-child(odd) {
|
||||||
|
// margin-right: 10px;
|
||||||
|
// }
|
||||||
|
|
||||||
|
// &:nth-child(even) {
|
||||||
|
// margin-left: 10px;
|
||||||
|
// }
|
||||||
|
|
||||||
|
&.selected {
|
||||||
|
border: 1px solid #3fbf72;
|
||||||
|
background-color: rgba(63, 191, 114, 0.05);
|
||||||
|
box-shadow: 0 2px 8px rgba(63, 191, 114, 0.15);
|
||||||
|
}
|
||||||
|
|
||||||
|
.course-name {
|
||||||
|
font-size: 16px;
|
||||||
|
font-weight: 500;
|
||||||
|
color: #333;
|
||||||
|
margin-bottom: 10px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.course-btn-group {
|
||||||
|
display: flex;
|
||||||
|
|
||||||
|
.dm-btn {
|
||||||
|
flex: 1 0 1px;
|
||||||
|
display: inline-block;
|
||||||
|
color: #2879ff;
|
||||||
|
font-size: 14px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.course-info-item {
|
||||||
|
display: flex;
|
||||||
|
margin-bottom: 12px;
|
||||||
|
font-size: 12px;
|
||||||
|
|
||||||
|
.info-label {
|
||||||
|
color: #949AA4;
|
||||||
|
flex: 0 0 100px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.info-data {
|
||||||
|
flex: 1 0 1px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* 学生选择器弹窗样式 */
|
||||||
|
.xk-selector {
|
||||||
|
background-color: #ffffff;
|
||||||
|
border-top-left-radius: 12px;
|
||||||
|
border-top-right-radius: 12px;
|
||||||
|
padding-bottom: 20px;
|
||||||
|
|
||||||
|
.selector-header {
|
||||||
|
display: flex;
|
||||||
|
justify-content: space-between;
|
||||||
|
align-items: center;
|
||||||
|
padding: 15px;
|
||||||
|
border-bottom: 1px solid #f2f2f2;
|
||||||
|
|
||||||
|
.selector-title {
|
||||||
|
font-size: 16px;
|
||||||
|
font-weight: 500;
|
||||||
|
color: #303133;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.xk-list {
|
||||||
|
padding: 0 15px;
|
||||||
|
|
||||||
|
.xk-item {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
padding: 15px 0;
|
||||||
|
border-bottom: 1px solid #f2f2f2;
|
||||||
|
|
||||||
|
&:last-child {
|
||||||
|
border-bottom: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
&-active {
|
||||||
|
background-color: rgba(64, 158, 255, 0.05);
|
||||||
|
}
|
||||||
|
|
||||||
|
.xk-info {
|
||||||
|
flex: 1;
|
||||||
|
margin-left: 12px;
|
||||||
|
|
||||||
|
.xk-name {
|
||||||
|
font-size: 15px;
|
||||||
|
font-weight: 500;
|
||||||
|
color: #303133;
|
||||||
|
margin-bottom: 4px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.xk-type {
|
||||||
|
font-size: 13px;
|
||||||
|
color: #303133;
|
||||||
|
margin-bottom: 4px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.xk-class {
|
||||||
|
font-size: 13px;
|
||||||
|
color: #606266;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 全局图片样式 */
|
||||||
|
.w-full {
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.h-full {
|
||||||
|
height: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 暂无数据样式
|
||||||
|
.empty-course-list {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
padding: 60px 20px;
|
||||||
|
text-align: center;
|
||||||
|
|
||||||
|
.empty-icon {
|
||||||
|
margin-bottom: 20px;
|
||||||
|
background-color: #f5f6f7;
|
||||||
|
width: 80px;
|
||||||
|
height: 80px;
|
||||||
|
border-radius: 50%;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.empty-text {
|
||||||
|
font-size: 18px;
|
||||||
|
font-weight: 500;
|
||||||
|
color: #303133;
|
||||||
|
margin-bottom: 8px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.empty-desc {
|
||||||
|
font-size: 14px;
|
||||||
|
color: #909399;
|
||||||
|
max-width: 80%;
|
||||||
|
line-height: 1.5;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 选课已结束样式 */
|
||||||
|
.enrollment-ended {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
background-color: rgba(255, 255, 255, 0.2);
|
||||||
|
border-radius: 8px;
|
||||||
|
padding: 12px 15px;
|
||||||
|
font-size: 16px;
|
||||||
|
font-weight: 500;
|
||||||
|
color: #fff;
|
||||||
|
gap: 8px;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
409
src/pages/base/groupTeaching/dmXkkcDetail.vue
Normal file
409
src/pages/base/groupTeaching/dmXkkcDetail.vue
Normal file
@ -0,0 +1,409 @@
|
|||||||
|
<template>
|
||||||
|
<BasicLayout>
|
||||||
|
<!-- 课程信息卡片 -->
|
||||||
|
<view class="course-card mx-15 my-15 bg-white white-bg-color r-md p-15">
|
||||||
|
<view class="flex-row items-center mb-15">
|
||||||
|
<view class="course-icon flex-center mr-10">
|
||||||
|
<u-icon name="calendar" color="#4080ff" size="20"></u-icon>
|
||||||
|
</view>
|
||||||
|
<text class="font-16 font-bold">{{ xkkc.kcmc }}</text>
|
||||||
|
<text class="font-14 cor-999 ml-10">{{ todayInfo.date }} ({{ todayInfo.weekName }})</text>
|
||||||
|
</view>
|
||||||
|
|
||||||
|
<!-- 考勤统计 -->
|
||||||
|
<view class="attendance-stats flex-row">
|
||||||
|
<view class="stat-item flex-col items-center">
|
||||||
|
<text class="font-18 font-bold">{{ numInfo.yd }}</text>
|
||||||
|
<text class="font-12 cor-666 mt-3">应到</text>
|
||||||
|
</view>
|
||||||
|
<view class="stat-item flex-col items-center">
|
||||||
|
<text class="font-18 font-bold cor-primary">{{ numInfo.sd }}</text>
|
||||||
|
<text class="font-12 cor-666 mt-3">实到</text>
|
||||||
|
</view>
|
||||||
|
<view class="stat-item flex-col items-center">
|
||||||
|
<text class="font-18 font-bold cor-warning">{{ numInfo.qj }}</text>
|
||||||
|
<text class="font-12 cor-666 mt-3">请假</text>
|
||||||
|
</view>
|
||||||
|
<view class="stat-item flex-col items-center">
|
||||||
|
<text class="font-18 font-bold cor-danger">{{ numInfo.qq }}</text>
|
||||||
|
<text class="font-12 cor-666 mt-3">缺勤</text>
|
||||||
|
</view>
|
||||||
|
<view class="stat-circle flex-col flex-center ml-auto">
|
||||||
|
<text class="font-20 font-bold">{{ numInfo.zg }}</text>
|
||||||
|
<text class="font-10 cor-666">总人数</text>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
|
||||||
|
<!-- 学生列表 -->
|
||||||
|
<view class="student-list mb-30 white-bg-color">
|
||||||
|
<view class="student-grid">
|
||||||
|
<view
|
||||||
|
v-for="(xs, index) in xsList"
|
||||||
|
:key="index"
|
||||||
|
class="student-item bg-white r-md p-12"
|
||||||
|
>
|
||||||
|
<view class="flex-row items-center">
|
||||||
|
<view class="avatar-container mr-8">
|
||||||
|
<image
|
||||||
|
class="student-avatar"
|
||||||
|
:src="xs.xmtx || '/static/images/default-avatar.png'"
|
||||||
|
mode="aspectFill"
|
||||||
|
></image>
|
||||||
|
</view>
|
||||||
|
<view class="flex-1 overflow-hidden">
|
||||||
|
<view class="flex-row items-center mb-3">
|
||||||
|
<text class="font-14 font-bold mr-5 text-ellipsis">{{ xs.xsxm }}</text>
|
||||||
|
<view
|
||||||
|
class="status-tag"
|
||||||
|
:class="getStatusClass(xs.xszt)"
|
||||||
|
@click="openStatusPicker(xs)"
|
||||||
|
>
|
||||||
|
{{ xs.xszt }}
|
||||||
|
<u-icon name="arrow-down" size="10"></u-icon>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
<text class="font-12 cor-666">{{ xs.bjmc }}</text>
|
||||||
|
<view class="contact-parent mt-8 flex-center">
|
||||||
|
<text class="font-12 cor-primary">联系家长</text>
|
||||||
|
<u-icon
|
||||||
|
name="phone"
|
||||||
|
color="#4080ff"
|
||||||
|
size="14"
|
||||||
|
class="ml-2"
|
||||||
|
></u-icon>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
|
||||||
|
<!-- 状态选择弹窗 -->
|
||||||
|
<u-picker
|
||||||
|
:show="statusPickerVisible"
|
||||||
|
:columns="[statusOptions]"
|
||||||
|
@confirm="confirmStatus"
|
||||||
|
@cancel="statusPickerVisible = false"
|
||||||
|
></u-picker>
|
||||||
|
|
||||||
|
<template #bottom>
|
||||||
|
<view class="submit-btn-wrap py-10 px-20 bg-white">
|
||||||
|
<button class="submit-btn" @click="submit">提交</button>
|
||||||
|
</view>
|
||||||
|
</template>
|
||||||
|
</BasicLayout>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script setup lang="ts">
|
||||||
|
import {onMounted, ref} from "vue";
|
||||||
|
import BasicLayout from "@/components/BasicLayout/Layout.vue";
|
||||||
|
import {dicApi} from "@/api/system/dic";
|
||||||
|
import { useUserStore } from "@/store/modules/user";
|
||||||
|
import { useDataStore } from "@/store/modules/data";
|
||||||
|
import { jsdXkXsListApi, jsdXkdmListApi } from "@/api/base/server";
|
||||||
|
|
||||||
|
import dayjs from "dayjs";
|
||||||
|
|
||||||
|
const { getJs } = useUserStore();
|
||||||
|
const { getData } = useDataStore();
|
||||||
|
|
||||||
|
const js = computed(() => getJs)
|
||||||
|
const xkkc = computed(() => getData)
|
||||||
|
|
||||||
|
const now = dayjs();
|
||||||
|
let wDay = now.day();
|
||||||
|
if (wDay === 0) {
|
||||||
|
wDay = 7;
|
||||||
|
}
|
||||||
|
const wdNameList = ["周一", "周二", "周三", "周四", "周五", "周六", "周日"];
|
||||||
|
const todayInfo = ref({
|
||||||
|
date: now.format("YYYY-MM-DD"),
|
||||||
|
weekName: wdNameList[wDay - 1]
|
||||||
|
})
|
||||||
|
// 人数信息
|
||||||
|
const numInfo = ref({
|
||||||
|
yd: 18,
|
||||||
|
sd: 18,
|
||||||
|
qj: 0,
|
||||||
|
qq: 0,
|
||||||
|
zg: 18
|
||||||
|
});
|
||||||
|
|
||||||
|
// 学生列表
|
||||||
|
const xsList = ref<any>([
|
||||||
|
]);
|
||||||
|
|
||||||
|
// 状态选择相关
|
||||||
|
const statusPickerVisible = ref(false);
|
||||||
|
const statusOptions = ref<Array<{ text: string, value: string }>>([]);
|
||||||
|
const curXs = ref<any>(null);
|
||||||
|
|
||||||
|
// 获取状态对应的样式类
|
||||||
|
const getStatusClass = (status: string) => {
|
||||||
|
switch (status) {
|
||||||
|
case "正常":
|
||||||
|
return "status-normal";
|
||||||
|
case "请假":
|
||||||
|
return "status-leave";
|
||||||
|
case "缺勤":
|
||||||
|
return "status-absent";
|
||||||
|
default:
|
||||||
|
return "status-normal";
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
// 获取学生状态选项
|
||||||
|
const loadStatusOptions = async () => {
|
||||||
|
try {
|
||||||
|
// 假设字典表中考勤状态的pid为763939514,根据实际情况修改
|
||||||
|
const res = await dicApi({pid: 763939514});
|
||||||
|
if (res && res.result) {
|
||||||
|
statusOptions.value = res.result.map((item: any) => {
|
||||||
|
return {
|
||||||
|
text: item.dictionaryValue,
|
||||||
|
value: item.dictionaryCode
|
||||||
|
};
|
||||||
|
});
|
||||||
|
}
|
||||||
|
} catch (error) {
|
||||||
|
console.error("获取状态选项失败", error);
|
||||||
|
// 使用默认状态
|
||||||
|
statusOptions.value = [
|
||||||
|
{text: "正常", value: "正常"},
|
||||||
|
{text: "请假", value: "请假"},
|
||||||
|
{text: "缺勤", value: "缺勤"}
|
||||||
|
];
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const loadXsList = async () => {
|
||||||
|
const res = await jsdXkXsListApi({
|
||||||
|
xkkcId: xkkc.value.id
|
||||||
|
});
|
||||||
|
if (res && res.resultCode === 1) {
|
||||||
|
xsList.value = res.result || [];
|
||||||
|
let sd = 0;
|
||||||
|
let qj = 0;
|
||||||
|
let qq = 0;
|
||||||
|
// 循环统计状态对应的人数
|
||||||
|
for (let i = 0; i < xsList.value.length; i++) {
|
||||||
|
const xs = xsList.value[i];
|
||||||
|
switch (xs.xszt) {
|
||||||
|
case "正常":
|
||||||
|
sd++;
|
||||||
|
break;
|
||||||
|
case "请假":
|
||||||
|
qj++;
|
||||||
|
break;
|
||||||
|
case "缺勤":
|
||||||
|
qq++;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
numInfo.value = {
|
||||||
|
zg: xsList.value.length,
|
||||||
|
yd: xsList.value.length - qj,
|
||||||
|
sd: sd,
|
||||||
|
qj: qj,
|
||||||
|
qq: qj
|
||||||
|
};
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
// 打开状态选择器
|
||||||
|
const openStatusPicker = (xs: any) => {
|
||||||
|
curXs.value = xs;
|
||||||
|
statusPickerVisible.value = true;
|
||||||
|
};
|
||||||
|
|
||||||
|
// 确认选择状态
|
||||||
|
const confirmStatus = (e: any) => {
|
||||||
|
if (curXs.value && e.value && e.value[0]) {
|
||||||
|
const selectedStatus = statusOptions.value.find(
|
||||||
|
(option: any) => option.value === e.value[0].value
|
||||||
|
);
|
||||||
|
|
||||||
|
if (selectedStatus) {
|
||||||
|
// 更新当前学生状态
|
||||||
|
curXs.value.xszt = selectedStatus.text;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
statusPickerVisible.value = false;
|
||||||
|
};
|
||||||
|
|
||||||
|
// 导航相关方法
|
||||||
|
const navigateBack = () => {
|
||||||
|
uni.navigateBack();
|
||||||
|
};
|
||||||
|
|
||||||
|
const toRollCallRecord = () => {
|
||||||
|
uni.navigateTo({
|
||||||
|
url: "/pages/base/groupTeaching/rollCallRecord",
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
// 联系家长
|
||||||
|
const contactParent = (student: any) => {
|
||||||
|
console.log("联系家长", student.name);
|
||||||
|
};
|
||||||
|
|
||||||
|
// 提交数据
|
||||||
|
const submit = async () => {
|
||||||
|
const res = await jsdXkdmListApi({
|
||||||
|
jsId: js.value.id,
|
||||||
|
xkkcId: xkkc.value.id,
|
||||||
|
dmtime: now,
|
||||||
|
xkdmList: xsList.value
|
||||||
|
});
|
||||||
|
uni.showToast({
|
||||||
|
title: "提交成功",
|
||||||
|
icon: "success",
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
// 页面加载时获取状态选项
|
||||||
|
onMounted(async () => {
|
||||||
|
await loadXsList();
|
||||||
|
await loadStatusOptions();
|
||||||
|
});
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style scoped lang="scss">
|
||||||
|
.container {
|
||||||
|
min-height: 100vh;
|
||||||
|
background-color: #f5f5f5;
|
||||||
|
}
|
||||||
|
|
||||||
|
.header {
|
||||||
|
height: 44px;
|
||||||
|
background-color: #fff;
|
||||||
|
}
|
||||||
|
|
||||||
|
.course-card {
|
||||||
|
border-radius: 8px;
|
||||||
|
box-shadow: 0 2px 6px rgba(0, 0, 0, 0.05);
|
||||||
|
}
|
||||||
|
|
||||||
|
.course-icon {
|
||||||
|
width: 30px;
|
||||||
|
height: 30px;
|
||||||
|
border-radius: 4px;
|
||||||
|
background-color: rgba(64, 128, 255, 0.1);
|
||||||
|
}
|
||||||
|
|
||||||
|
.attendance-stats {
|
||||||
|
padding: 10px 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.stat-item {
|
||||||
|
flex: 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
.stat-circle {
|
||||||
|
width: 60px;
|
||||||
|
height: 60px;
|
||||||
|
border-radius: 50%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.student-list {
|
||||||
|
padding: 0 15px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.student-grid {
|
||||||
|
display: grid;
|
||||||
|
grid-template-columns: repeat(2, 1fr);
|
||||||
|
gap: 20rpx;
|
||||||
|
}
|
||||||
|
|
||||||
|
.student-item {
|
||||||
|
position: relative;
|
||||||
|
}
|
||||||
|
|
||||||
|
.avatar-container {
|
||||||
|
width: 46px;
|
||||||
|
height: 46px;
|
||||||
|
border-radius: 50%;
|
||||||
|
padding: 3px;
|
||||||
|
background-color: #fff;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
box-shadow: 0 2px 6px rgba(0, 0, 0, 0.05);
|
||||||
|
}
|
||||||
|
|
||||||
|
.student-avatar {
|
||||||
|
width: 40px;
|
||||||
|
height: 40px;
|
||||||
|
border-radius: 50%;
|
||||||
|
background-color: #f5f5f5;
|
||||||
|
}
|
||||||
|
|
||||||
|
.status-tag {
|
||||||
|
font-size: 10px;
|
||||||
|
padding: 1px 5px;
|
||||||
|
border-radius: 4px;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
|
||||||
|
.status-normal {
|
||||||
|
color: #4080ff;
|
||||||
|
}
|
||||||
|
|
||||||
|
.status-leave {
|
||||||
|
color: #ff9900;
|
||||||
|
}
|
||||||
|
|
||||||
|
.status-absent {
|
||||||
|
color: #ff4d4f;
|
||||||
|
}
|
||||||
|
|
||||||
|
.text-ellipsis {
|
||||||
|
white-space: nowrap;
|
||||||
|
overflow: hidden;
|
||||||
|
text-overflow: ellipsis;
|
||||||
|
max-width: 60px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.contact-parent {
|
||||||
|
padding: 3px 8px;
|
||||||
|
border-radius: 4px;
|
||||||
|
border: 1px solid #4080ff;
|
||||||
|
display: inline-flex;
|
||||||
|
}
|
||||||
|
|
||||||
|
.submit-btn {
|
||||||
|
background-color: #4080ff;
|
||||||
|
color: #fff;
|
||||||
|
height: 44px;
|
||||||
|
border-radius: 22px;
|
||||||
|
font-size: 16px;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.cor-primary {
|
||||||
|
color: #4080ff;
|
||||||
|
}
|
||||||
|
|
||||||
|
.cor-warning {
|
||||||
|
color: #ff9900;
|
||||||
|
}
|
||||||
|
|
||||||
|
.cor-danger {
|
||||||
|
color: #ff4d4f;
|
||||||
|
}
|
||||||
|
|
||||||
|
.cor-666 {
|
||||||
|
color: #666;
|
||||||
|
}
|
||||||
|
|
||||||
|
.cor-999 {
|
||||||
|
color: #999;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
465
src/pages/base/groupTeaching/xkList.vue
Normal file
465
src/pages/base/groupTeaching/xkList.vue
Normal file
@ -0,0 +1,465 @@
|
|||||||
|
<template>
|
||||||
|
<view class="interest-course">
|
||||||
|
<!-- 选课信息头部 - 固定部分 -->
|
||||||
|
<view class="selection-header">
|
||||||
|
<view class="header-content">
|
||||||
|
<view class="title-section" @click="clickShowXkSelector">
|
||||||
|
<view class="title">
|
||||||
|
<text v-if="xkData && xkData.xkmc">{{ xkData.xkmc }}</text>
|
||||||
|
<text v-else>选课信息</text>
|
||||||
|
</view>
|
||||||
|
<view class="switch-btn" v-if="xkList.length > 1">切换</view>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
|
||||||
|
<!-- 可滚动的内容区域 -->
|
||||||
|
<view class="scrollable-content">
|
||||||
|
<!-- 课程网格列表 -->
|
||||||
|
<view class="course-list" v-if="xkkcList && xkkcList.length > 0">
|
||||||
|
<view v-for="(xkkc, index) in xkkcList" :key="xkkc.id || index" class="course-item">
|
||||||
|
<view class="course-name">{{ xkkc.kcmc }}</view>
|
||||||
|
<view class="course-info-item">
|
||||||
|
<view class="info-label">上课周期类型:</view>
|
||||||
|
<view class="info-data">{{ xkkc.skzqlx }}</view>
|
||||||
|
</view>
|
||||||
|
<view class="course-info-item">
|
||||||
|
<view class="info-label">上课周期:</view>
|
||||||
|
<view class="info-data">{{ xkkc.skzqmc }}</view>
|
||||||
|
</view>
|
||||||
|
<view class="course-info-item">
|
||||||
|
<view class="info-label">上课开始时间:</view>
|
||||||
|
<view class="info-data">{{ xkkc.skkstime }}</view>
|
||||||
|
</view>
|
||||||
|
<view class="course-info-item">
|
||||||
|
<view class="info-label">上课结束时间:</view>
|
||||||
|
<view class="info-data">{{ xkkc.skjstime }}</view>
|
||||||
|
</view>
|
||||||
|
<view class="course-info-item">
|
||||||
|
<view class="info-label">开课地点:</view>
|
||||||
|
<view class="info-data">{{ xkkc.kcdd }}</view>
|
||||||
|
</view>
|
||||||
|
<view class="course-info-item">
|
||||||
|
<view class="info-label">上课人数:</view>
|
||||||
|
<view class="info-data">{{ xkkc.hasNum || 0 }} | {{ xkkc.maxNum || 0 }}</view>
|
||||||
|
</view>
|
||||||
|
<view class="course-btn-group">
|
||||||
|
<view class="detail-btn" @click.stop="goDetail(xkkc)">详情</view>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
|
||||||
|
<!-- 暂无数据提示 -->
|
||||||
|
<view v-else class="empty-course-list">
|
||||||
|
<view class="empty-icon">
|
||||||
|
<u-icon name="list" size="50" color="#C8C9CC"></u-icon>
|
||||||
|
</view>
|
||||||
|
<view class="empty-text">暂无课程数据</view>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
|
||||||
|
<view>
|
||||||
|
<!-- 俱乐部选择弹窗 -->
|
||||||
|
<u-popup :show="showXkFlag" @close="showXkFlag = false" mode="bottom" round="10">
|
||||||
|
<view class="xk-selector">
|
||||||
|
<view class="selector-header">
|
||||||
|
<text class="selector-title">选择俱乐部</text>
|
||||||
|
<u-icon name="close" size="20" @click="showXkFlag = false"></u-icon>
|
||||||
|
</view>
|
||||||
|
<view class="xk-list">
|
||||||
|
<view v-for="(xk, index) in xkList" :key="index" class="xk-item" :class="{
|
||||||
|
'xk-item-active': xkData.id === xk.id
|
||||||
|
}" @click="switchXk(xk)">
|
||||||
|
<view class="xk-info">
|
||||||
|
<text class="xk-name">{{ xk.xkmc }}</text>
|
||||||
|
<text class="xk-type">{{ xk.xkmc }}</text>
|
||||||
|
</view>
|
||||||
|
<u-icon v-if="xkData.id === xk.id" name="checkmark" color="#409EFF" size="20"></u-icon>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
</u-popup>
|
||||||
|
</view>
|
||||||
|
|
||||||
|
</view>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script setup lang="ts">
|
||||||
|
import {
|
||||||
|
ref,
|
||||||
|
onBeforeUnmount,
|
||||||
|
onMounted,
|
||||||
|
} from "vue";
|
||||||
|
import { useUserStore } from "@/store/modules/user";
|
||||||
|
import { useDataStore } from "@/store/modules/data";
|
||||||
|
import { jsdXkListApi } from "@/api/base/server";
|
||||||
|
import dayjs from "dayjs";
|
||||||
|
|
||||||
|
const { getJs } = useUserStore();
|
||||||
|
const { getData, setData } = useDataStore();
|
||||||
|
|
||||||
|
const wdNameList = ["周一", "周二", "周三", "周四", "周五", "周六", "周日"];
|
||||||
|
|
||||||
|
// 控制选择器显示状态
|
||||||
|
const showXkFlag = ref(false);
|
||||||
|
|
||||||
|
const xkList = ref<any>([]);
|
||||||
|
|
||||||
|
const xkData = ref();
|
||||||
|
|
||||||
|
const courseInfo = ref<any>({});
|
||||||
|
|
||||||
|
// 课程列表数据
|
||||||
|
const xkkcList = ref<any[]>([]);
|
||||||
|
|
||||||
|
onMounted(() => {
|
||||||
|
loadCourseList();
|
||||||
|
});
|
||||||
|
|
||||||
|
// 加载课程列表
|
||||||
|
const loadCourseList = async () => {
|
||||||
|
uni.showLoading({
|
||||||
|
title: "加载中...",
|
||||||
|
});
|
||||||
|
const res = await jsdXkListApi({
|
||||||
|
jsId: getJs.id
|
||||||
|
});
|
||||||
|
if (res.resultCode == 1) {
|
||||||
|
if (res.result && res.result.length) {
|
||||||
|
xkList.value = res.result;
|
||||||
|
switchXk(res.result[0]);
|
||||||
|
} else {
|
||||||
|
xkList.value = [];
|
||||||
|
xkData.value = {};
|
||||||
|
xkkcList.value = [];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
uni.hideLoading();
|
||||||
|
};
|
||||||
|
|
||||||
|
// 显示选课选择器
|
||||||
|
function clickShowXkSelector() {
|
||||||
|
if (xkList.value.length > 1) {
|
||||||
|
showXkFlag.value = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 切换选课
|
||||||
|
function switchXk(xk: any) {
|
||||||
|
xkData.value = xk;
|
||||||
|
xkkcList.value = xk.xkkcs;
|
||||||
|
showXkFlag.value = false;
|
||||||
|
for (let i = 0; i < xk.xkkcs.length; i++) {
|
||||||
|
let xkkc = xk.xkkcs[i];
|
||||||
|
// 判断周期
|
||||||
|
switch (xkkc.skzqlx) {
|
||||||
|
case '每天':
|
||||||
|
xkkc.skzqmc = "每天";
|
||||||
|
break;
|
||||||
|
case '每周':
|
||||||
|
const daysOfWeek = xkkc.skzq.split(',').map(Number);
|
||||||
|
// 从wdNameList读取daysOfWeek对应的周几
|
||||||
|
xkkc.skzqmc = daysOfWeek.map((day: number) => wdNameList[day - 1]).join(',');
|
||||||
|
break;
|
||||||
|
case '每月':
|
||||||
|
const daysOfMonth = xkkc.skzq.split(',').map(Number);
|
||||||
|
// 从根据编号加
|
||||||
|
xkkc.skzqmc = daysOfMonth.map((day: number) => day + "号").join(',');
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// 显示切换成功提示
|
||||||
|
uni.showToast({
|
||||||
|
title: `已切换到${xk.xkmc}`,
|
||||||
|
icon: "none",
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
// 查看课程详情
|
||||||
|
const goDetail = (xkkc: any) => {
|
||||||
|
setData(xkkc);
|
||||||
|
uni.navigateTo({
|
||||||
|
url: `/pages/base/groupTeaching/xkkcDetail`,
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
// 页面卸载前清除定时器
|
||||||
|
onBeforeUnmount(() => {
|
||||||
|
});
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style lang="scss" scoped>
|
||||||
|
.interest-course {
|
||||||
|
min-height: 100%;
|
||||||
|
background-color: #f5f7fa;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
height: 100%;
|
||||||
|
overflow: hidden;
|
||||||
|
}
|
||||||
|
|
||||||
|
.nav-bar {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: space-between;
|
||||||
|
padding: 15px;
|
||||||
|
height: 44px;
|
||||||
|
background-color: #fff;
|
||||||
|
|
||||||
|
.nav-left {
|
||||||
|
width: 40px;
|
||||||
|
height: 40px;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.nav-title {
|
||||||
|
font-size: 18px;
|
||||||
|
font-weight: 500;
|
||||||
|
color: #333;
|
||||||
|
}
|
||||||
|
|
||||||
|
.nav-right {
|
||||||
|
width: 40px;
|
||||||
|
display: flex;
|
||||||
|
justify-content: flex-end;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.selection-header {
|
||||||
|
background: linear-gradient(135deg, #4a90e2, #2879ff);
|
||||||
|
padding: 20px 15px;
|
||||||
|
color: #fff;
|
||||||
|
border-radius: 0 0 15px 15px;
|
||||||
|
box-shadow: 0 4px 12px rgba(40, 121, 255, 0.2);
|
||||||
|
position: sticky;
|
||||||
|
top: 0;
|
||||||
|
left: 0;
|
||||||
|
right: 0;
|
||||||
|
z-index: 10;
|
||||||
|
|
||||||
|
.header-content {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
gap: 15px;
|
||||||
|
|
||||||
|
.title-section {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
|
||||||
|
.title {
|
||||||
|
flex: 1 0 1px;
|
||||||
|
font-size: 24px;
|
||||||
|
font-weight: bold;
|
||||||
|
}
|
||||||
|
|
||||||
|
.subtitle {
|
||||||
|
font-size: 14px;
|
||||||
|
opacity: 0.8;
|
||||||
|
}
|
||||||
|
|
||||||
|
.switch-btn {
|
||||||
|
padding: 5px 15px;
|
||||||
|
background-color: rgba(255, 255, 255, 0.2);
|
||||||
|
color: #fff;
|
||||||
|
border-radius: 15px;
|
||||||
|
font-size: 15px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 可滚动内容区域样式
|
||||||
|
.scrollable-content {
|
||||||
|
flex: 1;
|
||||||
|
overflow-y: auto;
|
||||||
|
-webkit-overflow-scrolling: touch; // 增强iOS滚动体验
|
||||||
|
}
|
||||||
|
|
||||||
|
.course-list {
|
||||||
|
padding: 15px 15px 0 15px;
|
||||||
|
|
||||||
|
.course-item {
|
||||||
|
position: relative;
|
||||||
|
width: 100%;
|
||||||
|
margin-bottom: 15px;
|
||||||
|
background-color: #fff;
|
||||||
|
border-radius: 8px;
|
||||||
|
padding: 15px;
|
||||||
|
box-sizing: border-box;
|
||||||
|
border: 1px solid transparent;
|
||||||
|
transition: all 0.3s ease;
|
||||||
|
|
||||||
|
// &:nth-child(odd) {
|
||||||
|
// margin-right: 10px;
|
||||||
|
// }
|
||||||
|
|
||||||
|
// &:nth-child(even) {
|
||||||
|
// margin-left: 10px;
|
||||||
|
// }
|
||||||
|
|
||||||
|
&.selected {
|
||||||
|
border: 1px solid #3fbf72;
|
||||||
|
background-color: rgba(63, 191, 114, 0.05);
|
||||||
|
box-shadow: 0 2px 8px rgba(63, 191, 114, 0.15);
|
||||||
|
}
|
||||||
|
|
||||||
|
.course-name {
|
||||||
|
font-size: 16px;
|
||||||
|
font-weight: 500;
|
||||||
|
color: #333;
|
||||||
|
margin-bottom: 10px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.course-btn-group {
|
||||||
|
display: flex;
|
||||||
|
|
||||||
|
.detail-btn {
|
||||||
|
flex: 1 0 1px;
|
||||||
|
display: inline-block;
|
||||||
|
color: #2879ff;
|
||||||
|
font-size: 14px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.course-info-item {
|
||||||
|
display: flex;
|
||||||
|
margin-bottom: 12px;
|
||||||
|
font-size: 12px;
|
||||||
|
|
||||||
|
.info-label {
|
||||||
|
color: #949AA4;
|
||||||
|
flex: 0 0 100px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.info-data {
|
||||||
|
flex: 1 0 1px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* 学生选择器弹窗样式 */
|
||||||
|
.xk-selector {
|
||||||
|
background-color: #ffffff;
|
||||||
|
border-top-left-radius: 12px;
|
||||||
|
border-top-right-radius: 12px;
|
||||||
|
padding-bottom: 20px;
|
||||||
|
|
||||||
|
.selector-header {
|
||||||
|
display: flex;
|
||||||
|
justify-content: space-between;
|
||||||
|
align-items: center;
|
||||||
|
padding: 15px;
|
||||||
|
border-bottom: 1px solid #f2f2f2;
|
||||||
|
|
||||||
|
.selector-title {
|
||||||
|
font-size: 16px;
|
||||||
|
font-weight: 500;
|
||||||
|
color: #303133;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.xk-list {
|
||||||
|
padding: 0 15px;
|
||||||
|
|
||||||
|
.xk-item {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
padding: 15px 0;
|
||||||
|
border-bottom: 1px solid #f2f2f2;
|
||||||
|
|
||||||
|
&:last-child {
|
||||||
|
border-bottom: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
&-active {
|
||||||
|
background-color: rgba(64, 158, 255, 0.05);
|
||||||
|
}
|
||||||
|
|
||||||
|
.xk-info {
|
||||||
|
flex: 1;
|
||||||
|
margin-left: 12px;
|
||||||
|
|
||||||
|
.xk-name {
|
||||||
|
font-size: 15px;
|
||||||
|
font-weight: 500;
|
||||||
|
color: #303133;
|
||||||
|
margin-bottom: 4px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.xk-type {
|
||||||
|
font-size: 13px;
|
||||||
|
color: #303133;
|
||||||
|
margin-bottom: 4px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.xk-class {
|
||||||
|
font-size: 13px;
|
||||||
|
color: #606266;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 全局图片样式 */
|
||||||
|
.w-full {
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.h-full {
|
||||||
|
height: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 暂无数据样式
|
||||||
|
.empty-course-list {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
padding: 60px 20px;
|
||||||
|
text-align: center;
|
||||||
|
|
||||||
|
.empty-icon {
|
||||||
|
margin-bottom: 20px;
|
||||||
|
background-color: #f5f6f7;
|
||||||
|
width: 80px;
|
||||||
|
height: 80px;
|
||||||
|
border-radius: 50%;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.empty-text {
|
||||||
|
font-size: 18px;
|
||||||
|
font-weight: 500;
|
||||||
|
color: #303133;
|
||||||
|
margin-bottom: 8px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.empty-desc {
|
||||||
|
font-size: 14px;
|
||||||
|
color: #909399;
|
||||||
|
max-width: 80%;
|
||||||
|
line-height: 1.5;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 选课已结束样式 */
|
||||||
|
.enrollment-ended {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
background-color: rgba(255, 255, 255, 0.2);
|
||||||
|
border-radius: 8px;
|
||||||
|
padding: 12px 15px;
|
||||||
|
font-size: 16px;
|
||||||
|
font-weight: 500;
|
||||||
|
color: #fff;
|
||||||
|
gap: 8px;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
236
src/pages/base/groupTeaching/xkkcDetail.vue
Normal file
236
src/pages/base/groupTeaching/xkkcDetail.vue
Normal file
@ -0,0 +1,236 @@
|
|||||||
|
<template>
|
||||||
|
<BasicLayout>
|
||||||
|
<!-- <template #top>
|
||||||
|
</template> -->
|
||||||
|
<view class="mb-5">
|
||||||
|
<view class="flex-row items-center white-bg-color p-15 r-md">
|
||||||
|
<view class="flex-col ml-10 flex-1 course-info">
|
||||||
|
<view class="course-name">{{ xkkc.kcmc }}</view>
|
||||||
|
<view class="course-info-item">
|
||||||
|
<view class="info-label">上课周期类型:</view>
|
||||||
|
<view class="info-data">{{ xkkc.skzqlx }}</view>
|
||||||
|
</view>
|
||||||
|
<view class="course-info-item">
|
||||||
|
<view class="info-label">上课周期:</view>
|
||||||
|
<view class="info-data">{{ xkkc.skzqmc }}</view>
|
||||||
|
</view>
|
||||||
|
<view class="course-info-item">
|
||||||
|
<view class="info-label">上课开始时间:</view>
|
||||||
|
<view class="info-data">{{ xkkc.skkstime }}</view>
|
||||||
|
</view>
|
||||||
|
<view class="course-info-item">
|
||||||
|
<view class="info-label">上课结束时间:</view>
|
||||||
|
<view class="info-data">{{ xkkc.skjstime }}</view>
|
||||||
|
</view>
|
||||||
|
<view class="course-info-item">
|
||||||
|
<view class="info-label">开课老师:</view>
|
||||||
|
<view class="info-data">{{ js.jsxm }}</view>
|
||||||
|
</view>
|
||||||
|
<view class="course-info-item">
|
||||||
|
<view class="info-label">开课地点:</view>
|
||||||
|
<view class="info-data">{{ xkkc.kcdd }}</view>
|
||||||
|
</view>
|
||||||
|
<view class="course-info-item">
|
||||||
|
<view class="info-label">上课人数:</view>
|
||||||
|
<view class="info-data">{{ xkkc.hasNum || 0 }} | {{ xkkc.maxNum || 0 }}</view>
|
||||||
|
</view>
|
||||||
|
<view class="course-info-item">
|
||||||
|
<view class="info-label">金额:</view>
|
||||||
|
<view class="info-data cor-FF8D02">¥{{ xkkc.kcje }}</view>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
<view class="p-15">
|
||||||
|
<BasicForm @register="register">
|
||||||
|
<template #jxjh>
|
||||||
|
<view class="back-f8f8f8">
|
||||||
|
<view class="flex-row items-center justify-between py-15 global-bg-color">
|
||||||
|
<view>
|
||||||
|
<BasicTitle line title="教学计划" :isBorder="false" />
|
||||||
|
</view>
|
||||||
|
<view @click="addEducation">
|
||||||
|
<BasicIcon type="icon-tianjia" size="25" />
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
<view v-if="education.xl.length > 0">
|
||||||
|
<template v-for="(item, index) in education.xl" :key="index">
|
||||||
|
<view class="po-re mb-15">
|
||||||
|
<BasicForm v-model="item.value" :schema="schema" :formsProps="{ labelWidth: 100 }" />
|
||||||
|
<view @click="deleteMemberFamily(index as number, item.value)" class="delete-icon mt-5">
|
||||||
|
<BasicIcon type="clear" size="30" />
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
</template>
|
||||||
|
</view>
|
||||||
|
<view v-else class="p-15 flex-row-center color-9 font-13 white-bg-color">教学计划暂无数据</view>
|
||||||
|
</view>
|
||||||
|
</template>
|
||||||
|
</BasicForm>
|
||||||
|
</view>
|
||||||
|
<template #bottom>
|
||||||
|
<view class="white-bg-color py-5">
|
||||||
|
<view class="flex-row items-center pb-10 pt-5">
|
||||||
|
<u-button text="返回" class="ml-15 mr-7" :plain="true" @click="navigateBack" />
|
||||||
|
<u-button text="提交" class="mr-15 mr-7" type="primary" @click="submit" />
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
</template>
|
||||||
|
</BasicLayout>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script lang="ts" setup>
|
||||||
|
import { navigateBack } from "@/utils/uniapp";
|
||||||
|
|
||||||
|
import { useForm } from "@/components/BasicForm/hooks/useForm";
|
||||||
|
import { cloneDeep, get } from "lodash";
|
||||||
|
import { useUserStore } from "@/store/modules/user";
|
||||||
|
import { useDataStore } from "@/store/modules/data";
|
||||||
|
import { jsdXkkcSaveApi } from "@/api/base/server";
|
||||||
|
const { getJs } = useUserStore();
|
||||||
|
const { getData } = useDataStore();
|
||||||
|
|
||||||
|
const js = computed(() => getJs)
|
||||||
|
const xkkc = ref<any>({})
|
||||||
|
|
||||||
|
const [register, { getValue, setValue }] = useForm({
|
||||||
|
schema: [
|
||||||
|
{
|
||||||
|
field: "kcjsms",
|
||||||
|
label: "老师信息",
|
||||||
|
component: "BasicInput",
|
||||||
|
itemProps: {
|
||||||
|
labelPosition: "top",
|
||||||
|
},
|
||||||
|
componentProps: {
|
||||||
|
type: "textarea",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
field: "jxll",
|
||||||
|
label: "教学理念",
|
||||||
|
component: "BasicInput",
|
||||||
|
itemProps: {
|
||||||
|
labelPosition: "top",
|
||||||
|
},
|
||||||
|
componentProps: {
|
||||||
|
type: "textarea",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{ colSlot: 'jxjh' },
|
||||||
|
],
|
||||||
|
});
|
||||||
|
|
||||||
|
const schema = reactive<FormsSchema[]>([
|
||||||
|
{
|
||||||
|
field: "jhjd",
|
||||||
|
label: "阶段",
|
||||||
|
component: "BasicInput",
|
||||||
|
componentProps: {},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
field: "jhsj",
|
||||||
|
label: "计划时间",
|
||||||
|
component: "BasicDateTimes",
|
||||||
|
componentProps: {},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
field: "jhdd",
|
||||||
|
label: "地址",
|
||||||
|
component: "BasicInput",
|
||||||
|
componentProps: {},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
field: "jhnr",
|
||||||
|
label: "计划内容",
|
||||||
|
component: "BasicInput",
|
||||||
|
itemProps: {
|
||||||
|
labelPosition: "top",
|
||||||
|
},
|
||||||
|
componentProps: {
|
||||||
|
type: "textarea",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
])
|
||||||
|
|
||||||
|
|
||||||
|
const education = reactive<any>(
|
||||||
|
{
|
||||||
|
xl: []
|
||||||
|
}
|
||||||
|
)
|
||||||
|
function addEducation() {
|
||||||
|
education.xl.push({ value: {
|
||||||
|
jhjd: '',
|
||||||
|
jhsj: '',
|
||||||
|
jhdd: '',
|
||||||
|
jhnr: ''
|
||||||
|
} })
|
||||||
|
}
|
||||||
|
|
||||||
|
function deleteMemberFamily(index: number, item: any) {
|
||||||
|
const list = cloneDeep(education.xl)
|
||||||
|
list.splice(index, 1)
|
||||||
|
education.xl = list
|
||||||
|
}
|
||||||
|
|
||||||
|
const submit = async () => {
|
||||||
|
const data = await getValue()
|
||||||
|
xkkc.value.kcjsms = data.kcjsms;
|
||||||
|
xkkc.value.jxll = data.jxll;
|
||||||
|
xkkc.value.jxjh = JSON.stringify(education.xl)
|
||||||
|
await jsdXkkcSaveApi(xkkc.value).then(res => {
|
||||||
|
uni.showToast({
|
||||||
|
title: '提交成功',
|
||||||
|
icon: 'success',
|
||||||
|
duration: 2000
|
||||||
|
})
|
||||||
|
}).catch(err => {
|
||||||
|
uni.showToast({
|
||||||
|
title: '提交失败',
|
||||||
|
icon: 'error',
|
||||||
|
duration: 2000
|
||||||
|
})
|
||||||
|
});
|
||||||
|
}
|
||||||
|
// 初始化
|
||||||
|
onMounted(() => {
|
||||||
|
xkkc.value = getData;
|
||||||
|
setValue(getData);
|
||||||
|
// 将xkkc中的jxjh从json字符串转换为数组
|
||||||
|
if (xkkc.value.jxjh && xkkc.value.jxjh.length > 0) {
|
||||||
|
education.xl = JSON.parse(xkkc.value.jxjh)
|
||||||
|
} else {
|
||||||
|
education.xl = [];
|
||||||
|
}
|
||||||
|
})
|
||||||
|
</script>
|
||||||
|
<style>
|
||||||
|
.delete-icon {
|
||||||
|
position: absolute;
|
||||||
|
right: 0;
|
||||||
|
top: 0;
|
||||||
|
z-index: 1;
|
||||||
|
}
|
||||||
|
.course-info {
|
||||||
|
|
||||||
|
.course-name {
|
||||||
|
font-size: 16px;
|
||||||
|
font-weight: 500;
|
||||||
|
color: #333;
|
||||||
|
margin-bottom: 10px;
|
||||||
|
}
|
||||||
|
.course-info-item {
|
||||||
|
display: flex;
|
||||||
|
margin-bottom: 12px;
|
||||||
|
font-size: 12px;
|
||||||
|
.info-label {
|
||||||
|
color: #949AA4;
|
||||||
|
flex: 0 0 100px;
|
||||||
|
}
|
||||||
|
.info-data {
|
||||||
|
flex: 1 0 1px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
||||||
@ -14,15 +14,15 @@
|
|||||||
<view class="teacher-avatar">
|
<view class="teacher-avatar">
|
||||||
<image
|
<image
|
||||||
class="avatar-image"
|
class="avatar-image"
|
||||||
:src="teacherData.avatar || '/static/base/default-avatar.png'"
|
:src="js.headPic || '/static/base/default-avatar.png'"
|
||||||
mode="aspectFill"
|
mode="aspectFill"
|
||||||
></image>
|
></image>
|
||||||
</view>
|
</view>
|
||||||
|
|
||||||
<view class="teacher-details">
|
<view class="teacher-details">
|
||||||
<view class="teacher-name">{{ teacherData.name }}</view>
|
<view class="teacher-name">{{ js.jsxm }}</view>
|
||||||
<view class="teacher-position">{{ teacherData.position }}</view>
|
<view class="teacher-position">{{ js.dzzw }} {{ js.qtzw }}</view>
|
||||||
<view class="teacher-class">{{ teacherData.className }}</view>
|
<view class="teacher-class">{{ js.njz }}</view>
|
||||||
</view>
|
</view>
|
||||||
</view>
|
</view>
|
||||||
|
|
||||||
@ -30,18 +30,18 @@
|
|||||||
<view class="stats-info">
|
<view class="stats-info">
|
||||||
<view class="stat-item">
|
<view class="stat-item">
|
||||||
<text class="stat-label">积分:</text>
|
<text class="stat-label">积分:</text>
|
||||||
<text class="stat-value">{{ teacherData.score }}分</text>
|
<text class="stat-value">{{ jsWork.jf }}分</text>
|
||||||
</view>
|
</view>
|
||||||
<view class="stat-divider">|</view>
|
<view class="stat-divider">|</view>
|
||||||
<view class="stat-item">
|
<view class="stat-item">
|
||||||
<text class="stat-label">工作量:</text>
|
<text class="stat-label">工作量:</text>
|
||||||
<text class="stat-value">{{ teacherData.workload }}课时</text>
|
<text class="stat-value">{{ jsWork.ks }}课时</text>
|
||||||
</view>
|
</view>
|
||||||
</view>
|
</view>
|
||||||
|
|
||||||
<!-- 介绍文字 -->
|
<!-- 介绍文字 -->
|
||||||
<view class="teacher-intro">
|
<view class="teacher-intro">
|
||||||
{{ teacherData.introduction }}
|
{{ js.introduction || "北冥有鱼,其名为鲲。鲲之大,不知其几千里也。" }}
|
||||||
</view>
|
</view>
|
||||||
</view>
|
</view>
|
||||||
|
|
||||||
@ -88,13 +88,22 @@
|
|||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script lang="ts" setup>
|
<script lang="ts" setup>
|
||||||
import { findJsAllByPhoneApi } from "@/api/system/login";
|
import { jsdfindJsByPhoneApi } from "@/api/base/server";
|
||||||
import { useDataStore } from "@/store/modules/data";
|
import { useDataStore } from "@/store/modules/data";
|
||||||
import { useUserStore } from "@/store/modules/user";
|
import { useUserStore } from "@/store/modules/user";
|
||||||
import { imagUrl } from "@/utils";
|
import { imagUrl } from "@/utils";
|
||||||
import { hideLoading, showLoading } from "@/utils/uniapp";
|
import { hideLoading, showLoading } from "@/utils/uniapp";
|
||||||
import { set } from "lodash";
|
import { set } from "lodash";
|
||||||
import { reactive, ref } from "vue";
|
import { reactive, ref } from "vue";
|
||||||
|
const { logout, getUser, getJs, setJs } = useUserStore();
|
||||||
|
|
||||||
|
const js = computed(() => getJs);
|
||||||
|
// 教师工作信息
|
||||||
|
const jsWork = ref<any>({
|
||||||
|
jf: 88,
|
||||||
|
ks: 40
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
interface GridItem {
|
interface GridItem {
|
||||||
id: number | string;
|
id: number | string;
|
||||||
@ -111,28 +120,6 @@ interface Section {
|
|||||||
items: GridItem[];
|
items: GridItem[];
|
||||||
}
|
}
|
||||||
|
|
||||||
// 定义老师数据接口
|
|
||||||
interface TeacherData {
|
|
||||||
name: string;
|
|
||||||
position: string;
|
|
||||||
className: string;
|
|
||||||
score: number;
|
|
||||||
workload: number;
|
|
||||||
introduction: string;
|
|
||||||
avatar?: string;
|
|
||||||
}
|
|
||||||
const { logout, getUser } = useUserStore();
|
|
||||||
// 老师数据
|
|
||||||
const teacherData = reactive<TeacherData>({
|
|
||||||
name: getUser.loginName,
|
|
||||||
position: "教研组长",
|
|
||||||
className: "2014级1班班主任",
|
|
||||||
score: 48,
|
|
||||||
workload: 20,
|
|
||||||
introduction: "北冥有鱼,其名为鲲。鲲之大,不知其几千里也。",
|
|
||||||
avatar: imagUrl(getUser.profilePhoto),
|
|
||||||
});
|
|
||||||
|
|
||||||
// 退出登录
|
// 退出登录
|
||||||
const handleLogout = () => {
|
const handleLogout = () => {
|
||||||
uni.showModal({
|
uni.showModal({
|
||||||
@ -214,6 +201,21 @@ const sections = reactive<Section[]>([
|
|||||||
show: true,
|
show: true,
|
||||||
path: "/pages/view/routine/kefuxuncha/KeFuXunCha",
|
path: "/pages/view/routine/kefuxuncha/KeFuXunCha",
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
id: "r7",
|
||||||
|
icon: "file-text-fill-2",
|
||||||
|
text: "选课详情",
|
||||||
|
show: true,
|
||||||
|
path: "/pages/base/groupTeaching/xkList",
|
||||||
|
},
|
||||||
|
|
||||||
|
{
|
||||||
|
id: "r8",
|
||||||
|
icon: "draftfill",
|
||||||
|
text: "选课点名",
|
||||||
|
show: true,
|
||||||
|
path: "/pages/base/groupTeaching/dmXkList",
|
||||||
|
},
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@ -301,17 +303,19 @@ const getIconBgColor = (index: number) => {
|
|||||||
];
|
];
|
||||||
return colors[index % colors.length];
|
return colors[index % colors.length];
|
||||||
};
|
};
|
||||||
const { setFile, getFile } = useDataStore();
|
|
||||||
// 处理网格项点击事件
|
// 处理网格项点击事件
|
||||||
const handleGridItemClick = async (item: GridItem) => {
|
const handleGridItemClick = async (item: GridItem) => {
|
||||||
console.log("Clicked item:", item);
|
console.log("Clicked item:", item);
|
||||||
if (item.text == "教师档案") {
|
if (item.text == "教师档案") {
|
||||||
showLoading("加载中...");
|
showLoading("加载中...");
|
||||||
const res = await findJsAllByPhoneApi({
|
const res = await jsdfindJsByPhoneApi({
|
||||||
phone: getUser.telephone,
|
phone: getJs.lxdh,
|
||||||
});
|
});
|
||||||
|
if (res.result.headPic && res.result.headPic.length) {
|
||||||
|
res.result.headPic = imagUrl(res.result.headPic);
|
||||||
|
}
|
||||||
|
setJs(res.result);
|
||||||
hideLoading();
|
hideLoading();
|
||||||
setFile(res.result);
|
|
||||||
}
|
}
|
||||||
setTimeout(() => {
|
setTimeout(() => {
|
||||||
if (item.path) {
|
if (item.path) {
|
||||||
|
|||||||
@ -22,65 +22,43 @@ const { afterLoginAction } = useUserStore();
|
|||||||
const { setFile, getFile } = useDataStore();
|
const { setFile, getFile } = useDataStore();
|
||||||
const isShow = ref(true);
|
const isShow = ref(true);
|
||||||
|
|
||||||
function toHome(data: any) {
|
function goByJs(js: any) {
|
||||||
if (data.type == 1) {
|
console.log(js);
|
||||||
uni.reLaunch({
|
// if (js.jsType == "助教") {
|
||||||
url: "/pages/base/groupTeaching/zhujiao",
|
// uni.reLaunch({
|
||||||
});
|
// url: "/pages/base/groupTeaching/zhujiao",
|
||||||
} else {
|
// });
|
||||||
|
// } else {
|
||||||
|
if (js.confirmStatus == "A") {
|
||||||
uni.switchTab({
|
uni.switchTab({
|
||||||
url: "/pages/base/message/index",
|
url: "/pages/base/message/index",
|
||||||
});
|
});
|
||||||
|
} else {
|
||||||
|
setFile({
|
||||||
|
...js,
|
||||||
|
...getFile,
|
||||||
|
});
|
||||||
|
setTimeout(() => {
|
||||||
|
uni.reLaunch({
|
||||||
|
url: "/pages/view/hr/teacherProfile/index",
|
||||||
|
});
|
||||||
|
}, 1500);
|
||||||
}
|
}
|
||||||
|
// }
|
||||||
}
|
}
|
||||||
onLoad(async (data: any) => {
|
onLoad(async (data: any) => {
|
||||||
if (data && data.openId) {
|
if (data && data.openId) {
|
||||||
setGlobal(data);
|
setGlobal(data);
|
||||||
checkOpenId({
|
checkOpenId({
|
||||||
openId: data.openId,
|
openId: data.openId,
|
||||||
appCode: data.type == 1 ? "ZB" : "JS",
|
appCode: "JS",
|
||||||
})
|
})
|
||||||
.then(async (res) => {
|
.then(async (res: any) => {
|
||||||
if (res.resultCode == 1) {
|
if (res.resultCode == 1) {
|
||||||
if (res.result) {
|
if (res.result) {
|
||||||
afterLoginAction(res.result);
|
afterLoginAction(res.result);
|
||||||
if (data.type == 1) {
|
// 跳转页面
|
||||||
toHome(data);
|
goByJs(res.result.js)
|
||||||
} else {
|
|
||||||
const findJsByPhoneResult = await findJsByPhoneApi({
|
|
||||||
phone: res.result.telephone,
|
|
||||||
});
|
|
||||||
if (findJsByPhoneResult.resultCode == 1) {
|
|
||||||
if (findJsByPhoneResult.result) {
|
|
||||||
if (findJsByPhoneResult.result["confirmStatus"] == "A") {
|
|
||||||
setFile({
|
|
||||||
...findJsByPhoneResult.result,
|
|
||||||
...getFile,
|
|
||||||
});
|
|
||||||
setTimeout(() => {
|
|
||||||
toHome(data);
|
|
||||||
}, 1500);
|
|
||||||
} else {
|
|
||||||
setFile({
|
|
||||||
...findJsByPhoneResult.result,
|
|
||||||
...getFile,
|
|
||||||
});
|
|
||||||
setTimeout(() => {
|
|
||||||
uni.reLaunch({
|
|
||||||
url: "/pages/view/hr/teacherProfile/index",
|
|
||||||
});
|
|
||||||
}, 1500);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
setFile({});
|
|
||||||
setTimeout(() => {
|
|
||||||
uni.reLaunch({
|
|
||||||
url: "/pages/view/hr/teacherProfile/index",
|
|
||||||
});
|
|
||||||
}, 1500);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
uni.reLaunch({
|
uni.reLaunch({
|
||||||
url: "/pages/system/login/login",
|
url: "/pages/system/login/login",
|
||||||
@ -89,6 +67,10 @@ onLoad(async (data: any) => {
|
|||||||
}
|
}
|
||||||
})
|
})
|
||||||
.catch((err) => {});
|
.catch((err) => {});
|
||||||
|
} else {
|
||||||
|
uni.reLaunch({
|
||||||
|
url: "/pages/system/login/login"
|
||||||
|
})
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
</script>
|
</script>
|
||||||
|
|||||||
@ -4,6 +4,7 @@ import {AUTH_KEY} from "@/config";
|
|||||||
|
|
||||||
interface UserState {
|
interface UserState {
|
||||||
userdata: any;
|
userdata: any;
|
||||||
|
jsData: any;
|
||||||
token: string;
|
token: string;
|
||||||
auth: string[]
|
auth: string[]
|
||||||
}
|
}
|
||||||
@ -12,7 +13,9 @@ export const useUserStore = defineStore({
|
|||||||
id: "app-user",
|
id: "app-user",
|
||||||
state: (): UserState => ({
|
state: (): UserState => ({
|
||||||
//用户数据
|
//用户数据
|
||||||
userdata: '',
|
userdata: {},
|
||||||
|
//用户数据
|
||||||
|
jsData: {},
|
||||||
// token
|
// token
|
||||||
token: '',
|
token: '',
|
||||||
//用户注册信息
|
//用户注册信息
|
||||||
@ -25,6 +28,9 @@ export const useUserStore = defineStore({
|
|||||||
getUser(): any {
|
getUser(): any {
|
||||||
return this.userdata;
|
return this.userdata;
|
||||||
},
|
},
|
||||||
|
getJs(): any {
|
||||||
|
return this.jsData;
|
||||||
|
},
|
||||||
getAuth(): string[] {
|
getAuth(): string[] {
|
||||||
return this.auth;
|
return this.auth;
|
||||||
}
|
}
|
||||||
@ -36,6 +42,9 @@ export const useUserStore = defineStore({
|
|||||||
setUser(data: any) {
|
setUser(data: any) {
|
||||||
this.userdata = data;
|
this.userdata = data;
|
||||||
},
|
},
|
||||||
|
setJs(data: any) {
|
||||||
|
this.jsData = data;
|
||||||
|
},
|
||||||
setAuth(data: string[]) {
|
setAuth(data: string[]) {
|
||||||
this.auth = data;
|
this.auth = data;
|
||||||
},
|
},
|
||||||
@ -77,6 +86,7 @@ export const useUserStore = defineStore({
|
|||||||
*/
|
*/
|
||||||
afterLoginAction(value: any) {
|
afterLoginAction(value: any) {
|
||||||
this.setUser(value)
|
this.setUser(value)
|
||||||
|
this.setJs(value.js);
|
||||||
if (value[AUTH_KEY]) {
|
if (value[AUTH_KEY]) {
|
||||||
this.setToken(value[AUTH_KEY])
|
this.setToken(value[AUTH_KEY])
|
||||||
}
|
}
|
||||||
@ -91,7 +101,8 @@ export const useUserStore = defineStore({
|
|||||||
*/
|
*/
|
||||||
logout() {
|
logout() {
|
||||||
this.setToken('')
|
this.setToken('')
|
||||||
this.setUser('')
|
this.setUser({})
|
||||||
|
this.setJs({})
|
||||||
this.setAuth([])
|
this.setAuth([])
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user