资源调整
This commit is contained in:
parent
9a5d8cf606
commit
33643f78ae
@ -194,24 +194,24 @@ export const xsJzListByXsIdApi = async (params: any) => {
|
||||
return await get("/api/jz/getListByXsId", params);
|
||||
};
|
||||
|
||||
// 教学资源树形
|
||||
export const typesFindTreeApi = async () => {
|
||||
return await get("/api/types/qryTreeReturn");
|
||||
// 资源目录树形
|
||||
export const zymlFindTreeApi = async () => {
|
||||
return await get("/api/zyml/qryTreeReturn");
|
||||
};
|
||||
|
||||
// 根据资源类型获取教学资源树形
|
||||
export const typesFindTreeByZylxApi = async (params: any) => {
|
||||
return await get("/api/types/qryTreeByZylx", params);
|
||||
// 根据资源类型获取资源目录树形
|
||||
export const zymlFindTreeByZylxApi = async (params: any) => {
|
||||
return await get("/api/zyml/qryTreeByZylx", params);
|
||||
};
|
||||
|
||||
// 获取资源分页
|
||||
export const resourcesFindPageApi = async (params: any) => {
|
||||
return await get("/api/resources/findPage", params);
|
||||
// 获取资源明细分页
|
||||
export const zymxFindPageApi = async (params: any) => {
|
||||
return await get("/api/zymx/findPage", params);
|
||||
};
|
||||
|
||||
// 根据资源类型获取资源分页
|
||||
export const resourcesFindPageByZylxApi = async (params: any) => {
|
||||
return await get("/api/resources/findPageByZylx", params);
|
||||
// 根据资源类型获取资源明细分页
|
||||
export const zymxFindPageByZylxApi = async (params: any) => {
|
||||
return await get("/api/zymx/findPageByZylx", params);
|
||||
};
|
||||
|
||||
// 教师积分查询
|
||||
@ -224,12 +224,12 @@ export const inspectItemFindAllApi = async (params: any) => {
|
||||
return await get("/api/inspectItem/findAlls", params);
|
||||
};
|
||||
|
||||
export const resourcesSaveApi = async (params: any) => {
|
||||
return await post("/api/resources/save", params);
|
||||
export const zymxSaveApi = async (params: any) => {
|
||||
return await post("/api/zymx/save", params);
|
||||
};
|
||||
|
||||
export const resourcesAddNumByTypeApi = async (params: any) => {
|
||||
return await post("/api/resources/addNumByType", params);
|
||||
export const zymxAddNumByTypeApi = async (params: any) => {
|
||||
return await post("/api/zymx/addNumByType", params);
|
||||
};
|
||||
|
||||
// 获取校平均工作量
|
||||
@ -346,3 +346,10 @@ export const clearUserOpenIdApi = async (params: { userId: string }) => {
|
||||
export const jsdXkkcPhotoSaveApi = async (params: any) => {
|
||||
return await post("/mobile/js/xk/photo/save", params);
|
||||
};
|
||||
|
||||
/**
|
||||
* 根据父节点查询字典数据
|
||||
*/
|
||||
export const dicFindByPidApi = async (params: { pid: string }) => {
|
||||
return await get("/api/dic/findByPid", params);
|
||||
};
|
||||
@ -30,9 +30,7 @@
|
||||
</picker-view-column>
|
||||
</picker-view>
|
||||
</view>
|
||||
<view class="button" style="width: 90%; margin: 5px auto" @click="ok"
|
||||
>确定</view
|
||||
>
|
||||
<view class="confirm-button" @click="ok">确定</view>
|
||||
</view>
|
||||
</uni-popup>
|
||||
</template>
|
||||
@ -165,4 +163,22 @@ picker-view-column {
|
||||
display: block !important;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.confirm-button {
|
||||
width: 90%;
|
||||
margin: 10px auto;
|
||||
padding: 12px 0;
|
||||
background-color: #007bff;
|
||||
color: #fff;
|
||||
text-align: center;
|
||||
border-radius: 8px;
|
||||
font-size: 16px;
|
||||
font-weight: 500;
|
||||
cursor: pointer;
|
||||
transition: background-color 0.3s;
|
||||
|
||||
&:active {
|
||||
background-color: #0056b3;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
||||
@ -16,7 +16,7 @@
|
||||
</picker-view-column>
|
||||
</picker-view>
|
||||
</view>
|
||||
<view class="button" style="width: 90%;margin: 5px auto;" @click="confirm">确定</view>
|
||||
<view class="confirm-button" @click="confirm">确定</view>
|
||||
</view>
|
||||
</uni-popup>
|
||||
</template>
|
||||
@ -487,10 +487,27 @@ export default {
|
||||
|
||||
.center {
|
||||
padding-bottom: var(--window-bottom);
|
||||
|
||||
}
|
||||
|
||||
.picker-view {
|
||||
height: 400rpx;
|
||||
}
|
||||
|
||||
.confirm-button {
|
||||
width: 90%;
|
||||
margin: 10px auto;
|
||||
padding: 12px 0;
|
||||
background-color: #007bff;
|
||||
color: #fff;
|
||||
text-align: center;
|
||||
border-radius: 8px;
|
||||
font-size: 16px;
|
||||
font-weight: 500;
|
||||
cursor: pointer;
|
||||
transition: background-color 0.3s;
|
||||
|
||||
&:active {
|
||||
background-color: #0056b3;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
||||
@ -872,21 +872,28 @@
|
||||
}
|
||||
},
|
||||
{
|
||||
"path": "pages/view/routine/kefuxuncha/zbList",
|
||||
"path": "pages/view/routine/zbxc/xcPbList",
|
||||
"style": {
|
||||
"navigationBarTitleText": "值周巡查",
|
||||
"enablePullDownRefresh": false
|
||||
}
|
||||
},
|
||||
{
|
||||
"path": "pages/view/routine/kefuxuncha/zbDetail",
|
||||
"path": "pages/view/routine/zbxc/zbList",
|
||||
"style": {
|
||||
"navigationBarTitleText": "值周巡查列表",
|
||||
"enablePullDownRefresh": false
|
||||
}
|
||||
},
|
||||
{
|
||||
"path": "pages/view/routine/zbxc/zbDetail",
|
||||
"style": {
|
||||
"navigationBarTitleText": "值周巡查详情",
|
||||
"enablePullDownRefresh": false
|
||||
}
|
||||
},
|
||||
{
|
||||
"path": "pages/view/routine/kefuxuncha/zbRecord",
|
||||
"path": "pages/view/routine/zbxc/zbRecord",
|
||||
"style": {
|
||||
"navigationBarTitleText": "值周巡查记录",
|
||||
"enablePullDownRefresh": false
|
||||
|
||||
@ -455,7 +455,14 @@ const sections = reactive<Section[]>([
|
||||
permissionKey: "routine-yrcg", // 一日常规权限编码
|
||||
path: "/pages/view/quantitativeAssessment/index/index",
|
||||
},
|
||||
|
||||
{
|
||||
id: "r19",
|
||||
icon: "zbxc",
|
||||
text: "值周巡查",
|
||||
show: true,
|
||||
permissionKey: "routine-zbxc", // 课服巡查权限编码
|
||||
path: "/pages/view/routine/zbxc/xcPbList",
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
|
||||
@ -20,6 +20,14 @@
|
||||
|
||||
<!-- 请假信息 -->
|
||||
<view class="info-list">
|
||||
<view class="info-item">
|
||||
<text class="label">学生姓名:</text>
|
||||
<text class="value">{{ qjData.xsxm }}</text>
|
||||
</view>
|
||||
<view class="info-item">
|
||||
<text class="label">所在班级:</text>
|
||||
<text class="value">{{ qjData.bc }}</text>
|
||||
</view>
|
||||
<view class="info-item">
|
||||
<text class="label">请假类型:</text>
|
||||
<text class="value">{{ qjData.qjlx }}</text>
|
||||
|
||||
@ -1,26 +1,26 @@
|
||||
<template>
|
||||
<view class="wh-full">
|
||||
<BasicLoading
|
||||
:isShow="isShow"
|
||||
bgColor="#fff"
|
||||
isShowTitle
|
||||
textColor="#000"
|
||||
title="启动中..."
|
||||
:type="1"
|
||||
:isShow="isShow"
|
||||
bgColor="#fff"
|
||||
isShowTitle
|
||||
textColor="#000"
|
||||
title="启动中..."
|
||||
:type="1"
|
||||
/>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import { onLoad } from "@dcloudio/uni-app";
|
||||
import { useDataStore } from "@/store/modules/data";
|
||||
import { useUserStore } from "@/store/modules/user";
|
||||
import { checkOpenId, findJsByPhoneApi } from "@/api/system/login";
|
||||
import { PermissionCacheManager } from "@/utils/permission";
|
||||
import {onLoad} from "@dcloudio/uni-app";
|
||||
import {useDataStore} from "@/store/modules/data";
|
||||
import {useUserStore} from "@/store/modules/user";
|
||||
import {checkOpenId, findJsByPhoneApi} from "@/api/system/login";
|
||||
import {PermissionCacheManager} from "@/utils/permission";
|
||||
|
||||
const { setGlobal, getGlobal } = useDataStore();
|
||||
const { afterLoginAction } = useUserStore();
|
||||
const { setFile, getFile } = useDataStore();
|
||||
const {setGlobal, getGlobal} = useDataStore();
|
||||
const {afterLoginAction} = useUserStore();
|
||||
const {setFile, getFile} = useDataStore();
|
||||
const isShow = ref(true);
|
||||
|
||||
/**
|
||||
@ -28,25 +28,25 @@ const isShow = ref(true);
|
||||
*/
|
||||
async function forceRefreshPermission(changeTime?: string): Promise<void> {
|
||||
try {
|
||||
|
||||
|
||||
// 重新获取用户权限
|
||||
const userStore = useUserStore();
|
||||
const currentUser = userStore.getUser;
|
||||
|
||||
|
||||
if (currentUser && currentUser.id) {
|
||||
// 重新调用权限获取接口
|
||||
const { authenticationApi } = await import('@/api/system/login');
|
||||
const result = await authenticationApi({ userId: currentUser.id });
|
||||
|
||||
const {authenticationApi} = await import('@/api/system/login');
|
||||
const result = await authenticationApi({userId: currentUser.id});
|
||||
|
||||
if (result && result.result) {
|
||||
|
||||
|
||||
// 直接设置权限并刷新缓存,不调用setAuth避免重复操作
|
||||
userStore.auth = result.result;
|
||||
|
||||
|
||||
// 手动刷新缓存,传递权限变更时间
|
||||
const { refreshPermissionCache } = await import('@/utils/permission');
|
||||
const {refreshPermissionCache} = await import('@/utils/permission');
|
||||
refreshPermissionCache(result.result, changeTime);
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
} catch (error) {
|
||||
@ -106,33 +106,32 @@ onLoad(async (data: any) => {
|
||||
rqgqtime: data.rqgqtime,
|
||||
timestampqd: data.timestampqd
|
||||
});
|
||||
console.log('已保存参数到 global:', { openId: data.openId, type: data.type });
|
||||
|
||||
console.log('已保存参数到 global:', {openId: data.openId, type: data.type});
|
||||
|
||||
try {
|
||||
const res = await checkOpenId({
|
||||
openId: data.openId,
|
||||
appCode: "JS",
|
||||
});
|
||||
if (data && data.qdId) {
|
||||
goByqd(data);
|
||||
}else if (res.resultCode == 1 && res.result) {
|
||||
if (res.resultCode == 1 && res.result) {
|
||||
// 执行登录操作
|
||||
afterLoginAction(res.result);
|
||||
|
||||
|
||||
// 如果有changeTime参数,更新权限缓存
|
||||
if (data.changeTime) {
|
||||
const { refreshPermissionCache } = await import('@/utils/permission');
|
||||
const {refreshPermissionCache} = await import('@/utils/permission');
|
||||
const userStore = useUserStore();
|
||||
const currentPermissions = userStore.getAuth;
|
||||
|
||||
|
||||
if (currentPermissions && currentPermissions.length > 0) {
|
||||
refreshPermissionCache(currentPermissions, data.changeTime);
|
||||
}
|
||||
}
|
||||
|
||||
// 跳转页面
|
||||
console.log('launchPage onLoad - 准备调用goByJs');
|
||||
goByJs(res.result.js);
|
||||
if (data && data.qdId) {
|
||||
goByqd(data);
|
||||
} else {
|
||||
goByJs(res.result.js);
|
||||
}
|
||||
} else {
|
||||
uni.reLaunch({
|
||||
url: "/pages/system/login/login",
|
||||
|
||||
@ -1,7 +1,46 @@
|
||||
<template>
|
||||
<BasicLayout :fixed="false">
|
||||
<view class="p-15">
|
||||
<BasicForm @register="register">
|
||||
<!-- 请假类型 -->
|
||||
<BasicForm @register="register" />
|
||||
|
||||
<!-- 间隔空白 -->
|
||||
<view class="section-gap"></view>
|
||||
|
||||
<!-- 时间选择区域 -->
|
||||
<view class="time-section">
|
||||
<view class="time-item" @click="startTimePicker?.open()">
|
||||
<text class="time-label">
|
||||
<text class="required-star">*</text>
|
||||
开始时间
|
||||
</text>
|
||||
<view class="time-value">
|
||||
<text :class="{ placeholder: !formData.qjkstime }">{{ formData.qjkstime || "请选择开始时间" }}</text>
|
||||
<uni-icons type="right" size="16" color="#999"></uni-icons>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<view class="time-item" @click="endTimePicker?.open()">
|
||||
<text class="time-label">
|
||||
<text class="required-star">*</text>
|
||||
结束时间
|
||||
</text>
|
||||
<view class="time-value">
|
||||
<text :class="{ placeholder: !formData.qjjstime }">{{ formData.qjjstime || "请选择结束时间" }}</text>
|
||||
<uni-icons type="right" size="16" color="#999"></uni-icons>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<view class="time-item time-item-readonly">
|
||||
<text class="time-label">请假时长</text>
|
||||
<view class="time-value">
|
||||
<text :class="{ placeholder: !formData.qjsc }">{{ formData.qjsc || "请输入选择开始时间和结束时间" }}</text>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<!-- 请假事由等其他字段 -->
|
||||
<BasicForm @register="register2">
|
||||
<template #dkmx>
|
||||
<view class="mt-15" v-show="formData.dkfs === 0">
|
||||
<JsQjDkEdit :data="formData" ref="dkRef" />
|
||||
@ -24,12 +63,29 @@
|
||||
</view>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<!-- 自定义时间选择器 -->
|
||||
<DatetimePicker
|
||||
ref="startTimePicker"
|
||||
:value="formData.qjkstime || new Date().getTime()"
|
||||
mode="datetime"
|
||||
title="选择开始时间"
|
||||
@confirm="handleStartTimeConfirm"
|
||||
/>
|
||||
<DatetimePicker
|
||||
ref="endTimePicker"
|
||||
:value="formData.qjjstime || new Date().getTime()"
|
||||
mode="datetime"
|
||||
title="选择结束时间"
|
||||
@confirm="handleEndTimeConfirm"
|
||||
/>
|
||||
</BasicLayout>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import JsQjDkEdit from "./jsQjDkEdit.vue"
|
||||
import BasicSpCsMgr from "@/components/BasicSpCsMgr/index.vue"
|
||||
import DatetimePicker from "@/components/BasicPicker/TimePicker/DatetimePicker.vue"
|
||||
import { useForm } from "@/components/BasicForm/hooks/useForm";
|
||||
import { jsQjSqApi, jsQjCxtjApi } from "@/api/base/jsQjApi";
|
||||
import { showToast } from "@/utils/uniapp";
|
||||
@ -41,6 +97,10 @@ import { QjPageUtils } from "@/utils/qjPageUtils";
|
||||
const { getJs, getUser } = useUserStore();
|
||||
const { findByPid } = useDicStore();
|
||||
|
||||
// 自定义时间选择器控制
|
||||
const startTimePicker = ref<any>(null);
|
||||
const endTimePicker = ref<any>(null);
|
||||
|
||||
// 接收外部传入属性
|
||||
const props = withDefaults(defineProps<{
|
||||
data?: any
|
||||
@ -69,6 +129,7 @@ const dkRef = ref<any>(null);
|
||||
const fileName = ref<string>('');
|
||||
const fileFormat = ref<string>('');
|
||||
|
||||
// 第一个表单:请假类型
|
||||
const [register, { setValue, getValue }] = useForm({
|
||||
schema: [
|
||||
{
|
||||
@ -83,35 +144,12 @@ const [register, { setValue, getValue }] = useForm({
|
||||
savaKey: "dictionaryCode",
|
||||
},
|
||||
},
|
||||
{
|
||||
field: "qjkstime",
|
||||
label: "开始时间",
|
||||
component: "BasicDateTimes",
|
||||
required: true,
|
||||
componentProps: {
|
||||
type: 'datetime',
|
||||
change: (e: string) => changeKsTime(e)
|
||||
},
|
||||
},
|
||||
{
|
||||
field: "qjjstime",
|
||||
label: "结束时间",
|
||||
component: "BasicDateTimes",
|
||||
required: true,
|
||||
componentProps: {
|
||||
type: 'datetime',
|
||||
change: (e: string) => changeJsTime(e)
|
||||
},
|
||||
},
|
||||
{
|
||||
field: "qjsc",
|
||||
label: "请假时长",
|
||||
component: "BasicInput",
|
||||
componentProps: {
|
||||
disabled: true,
|
||||
placeholder: "请输入选择开始时间和结束时间"
|
||||
},
|
||||
},
|
||||
],
|
||||
});
|
||||
|
||||
// 第二个表单:请假事由、附件、代课方式等
|
||||
const [register2, { setValue: setValue2, getValue: getValue2 }] = useForm({
|
||||
schema: [
|
||||
{
|
||||
field: "qjsy",
|
||||
label: "请假事由",
|
||||
@ -179,25 +217,62 @@ const [register, { setValue, getValue }] = useForm({
|
||||
],
|
||||
});
|
||||
|
||||
const changeKsTime = (selectedTime?: string) => {
|
||||
if (!selectedTime) {
|
||||
return;
|
||||
}
|
||||
formData.value.qjkstime = selectedTime;
|
||||
validateTime();
|
||||
// 日期格式化函数
|
||||
const formatDate = (dateString: string | null): string | null => {
|
||||
if (!dateString) return null;
|
||||
const date = new Date(dateString);
|
||||
const year = date.getFullYear();
|
||||
const month = String(date.getMonth() + 1).padStart(2, '0');
|
||||
const day = String(date.getDate()).padStart(2, '0');
|
||||
const hours = String(date.getHours()).padStart(2, '0');
|
||||
const minutes = String(date.getMinutes()).padStart(2, '0');
|
||||
const seconds = String(date.getSeconds()).padStart(2, '0');
|
||||
return `${year}-${month}-${day} ${hours}:${minutes}:${seconds}`;
|
||||
};
|
||||
|
||||
const changeJsTime = (selectedTime?: string) => {
|
||||
if (!selectedTime) {
|
||||
return;
|
||||
}
|
||||
formData.value.qjjstime = selectedTime;
|
||||
validateTime();
|
||||
// 自定义时间选择器确认事件处理
|
||||
const handleStartTimeConfirm = (e: any) => {
|
||||
formData.value.qjkstime = formatDate(e.value);
|
||||
calculateDuration();
|
||||
};
|
||||
|
||||
const handleEndTimeConfirm = (e: any) => {
|
||||
formData.value.qjjstime = formatDate(e.value);
|
||||
calculateDuration();
|
||||
};
|
||||
|
||||
// 计算请假时长(不显示错误提示)
|
||||
const calculateDuration = () => {
|
||||
const data = formData.value;
|
||||
// 如果两个时间都不存在,直接返回
|
||||
if (!data.qjkstime || !data.qjjstime) {
|
||||
data.qjsc = "";
|
||||
return;
|
||||
}
|
||||
// 使用dayjs库进行时间比较
|
||||
const ksTime = dayjs(data.qjkstime).valueOf();
|
||||
const jsTime = dayjs(data.qjjstime).valueOf();
|
||||
if (ksTime > jsTime) {
|
||||
uni.showToast({
|
||||
title: "请假开始时间不能大于请假结束时间!",
|
||||
icon: "none",
|
||||
});
|
||||
data.qjsc = "";
|
||||
return;
|
||||
}
|
||||
// 计算请假时长(小时)
|
||||
data.qjsc = Math.round((jsTime - ksTime) / (1000 * 60 * 60)) + "小时";
|
||||
updateDk();
|
||||
};
|
||||
|
||||
// 验证时间(用于提交时的完整验证)
|
||||
const validateTime = () => {
|
||||
const data = formData.value;
|
||||
if (!data.qjkstime || !data.qjjstime) {
|
||||
uni.showToast({
|
||||
title: "请选择开始时间和结束时间",
|
||||
icon: "none",
|
||||
});
|
||||
return false;
|
||||
}
|
||||
// 使用dayjs库进行时间比较
|
||||
@ -212,8 +287,6 @@ const validateTime = () => {
|
||||
}
|
||||
// 计算请假时长(小时)
|
||||
data.qjsc = Math.round((jsTime - ksTime) / (1000 * 60 * 60)) + "小时";
|
||||
setValue({ qjsc: data.qjsc });
|
||||
updateDk();
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -235,10 +308,17 @@ const initDk = () => {
|
||||
|
||||
const submit = async () => {
|
||||
const fd = await getValue();
|
||||
const fd2 = await getValue2();
|
||||
if (!validateTime()) {
|
||||
return;
|
||||
}
|
||||
const params = { ...fd };
|
||||
const params = {
|
||||
...fd,
|
||||
...fd2,
|
||||
qjkstime: formData.value.qjkstime,
|
||||
qjjstime: formData.value.qjjstime,
|
||||
qjsc: formData.value.qjsc,
|
||||
};
|
||||
// 注入审批人/抄送人
|
||||
params.sprList = formData.value.sprList || [];
|
||||
params.csrList = formData.value.csrList || [];
|
||||
@ -337,7 +417,10 @@ onMounted(() => {
|
||||
jsId: formData.value.jsId || getJs.id,
|
||||
sprList: formData.value.sprList || [],
|
||||
csrList: formData.value.csrList || [],
|
||||
dkfs: formData.value.dkfs || 0
|
||||
dkfs: formData.value.dkfs || 0,
|
||||
qjkstime: props.data.qjkstime || "",
|
||||
qjjstime: props.data.qjjstime || "",
|
||||
qjsc: props.data.qjsc || ""
|
||||
};
|
||||
formData.value = {
|
||||
...props.data,
|
||||
@ -347,9 +430,11 @@ onMounted(() => {
|
||||
if (props.data && props.data.id) {
|
||||
// 初始化
|
||||
setValue(formData.value);
|
||||
setValue2(formData.value);
|
||||
initDk();
|
||||
} else {
|
||||
setValue(formData.value);
|
||||
setValue2(formData.value);
|
||||
}
|
||||
console.log("onMounted:", formData.value);
|
||||
});
|
||||
@ -361,4 +446,75 @@ onMounted(() => {
|
||||
/* 保持BasicForm区块背景统一 */
|
||||
:deep(.white-bg-color) { background-color: #fff; }
|
||||
|
||||
.section-gap {
|
||||
height: 12px;
|
||||
}
|
||||
|
||||
.required-star {
|
||||
color: #f56c6c;
|
||||
margin-right: 4px;
|
||||
font-size: 15px;
|
||||
}
|
||||
|
||||
.time-section {
|
||||
background-color: #ffffff;
|
||||
border-radius: 8px;
|
||||
margin-bottom: 12px;
|
||||
box-shadow: 0 1px 4px rgba(0, 0, 0, 0.05);
|
||||
|
||||
.time-item {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
padding: 14px 15px;
|
||||
border-bottom: 1px solid #f0f0f0;
|
||||
cursor: pointer;
|
||||
transition: background-color 0.2s;
|
||||
|
||||
&:last-child {
|
||||
border-bottom: none;
|
||||
}
|
||||
|
||||
&:active {
|
||||
background-color: #fafafa;
|
||||
}
|
||||
|
||||
&.time-item-readonly {
|
||||
cursor: default;
|
||||
|
||||
&:active {
|
||||
background-color: transparent;
|
||||
}
|
||||
}
|
||||
|
||||
.time-label {
|
||||
font-size: 15px;
|
||||
color: #303133;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.time-value {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
font-size: 15px;
|
||||
color: #909399;
|
||||
flex: 1;
|
||||
justify-content: flex-end;
|
||||
|
||||
text {
|
||||
margin-right: 5px;
|
||||
color: #606266;
|
||||
|
||||
&.placeholder {
|
||||
color: #c0c4cc;
|
||||
}
|
||||
}
|
||||
|
||||
.uni-icons {
|
||||
color: #c0c4cc !important;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
@ -140,8 +140,8 @@
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import { resourcesSaveApi } from "@/api/base/server";
|
||||
import { typesFindTreeApi } from "@/api/base/server";
|
||||
import { zymxSaveApi } from "@/api/base/server";
|
||||
import { zymlFindTreeApi } from "@/api/base/server";
|
||||
import { attachmentUpload } from "@/api/system/upload";
|
||||
import { imagUrl } from "@/utils";
|
||||
import { useDicStore } from "@/store/modules/dic";
|
||||
@ -438,7 +438,7 @@ const handleSubmitForm = async () => {
|
||||
|
||||
|
||||
|
||||
const result = await resourcesSaveApi(params);
|
||||
const result = await zymxSaveApi(params);
|
||||
|
||||
if (result.resultCode === 1) {
|
||||
uni.showToast({ title: '操作成功', icon: 'success' });
|
||||
@ -477,7 +477,7 @@ const resetFormData = () => {
|
||||
// 加载树形数据
|
||||
const loadTreeData = async () => {
|
||||
try {
|
||||
const res = await typesFindTreeApi();
|
||||
const res = await zymlFindTreeApi();
|
||||
// 处理返回的数据结构,确保与BasicTree组件兼容
|
||||
if (res && Array.isArray(res)) {
|
||||
treeData.value = res.map(item => ({
|
||||
|
||||
@ -56,22 +56,15 @@
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import { typesFindTreeApi } from "@/api/base/server";
|
||||
import { zymlFindTreeApi, dicFindByPidApi } from "@/api/base/server";
|
||||
import { useDataStore } from "@/store/modules/data";
|
||||
const { setData } = useDataStore();
|
||||
|
||||
const typeTree = ref<any>([]);
|
||||
|
||||
const categoryList = ref([
|
||||
{ key: '', label: '不限' },
|
||||
{ key: '1', label: '课件' },
|
||||
{ key: '2', label: '教案' },
|
||||
{ key: '3', label: '学案' },
|
||||
{ key: '4', label: '作业' },
|
||||
{ key: '5', label: '试卷' },
|
||||
{ key: '6', label: '教材' },
|
||||
{ key: '7', label: '示范课' },
|
||||
{ key: '8', label: '音视频合集' }
|
||||
// 资源类型列表(从字典表动态获取)
|
||||
const categoryList = ref<any[]>([
|
||||
{ key: '', label: '不限' }
|
||||
]);
|
||||
|
||||
const curType = ref<any>();
|
||||
@ -81,13 +74,28 @@ const curCategory = ref<any>(categoryList.value[0]);
|
||||
|
||||
const selectType = (type: any) => {
|
||||
curType.value = type;
|
||||
curNj.value = curType.value.children[0];
|
||||
curCe.value = curNj.value.children[0];
|
||||
if (curType.value.children && curType.value.children.length > 0) {
|
||||
curNj.value = curType.value.children[0];
|
||||
if (curNj.value.children && curNj.value.children.length > 0) {
|
||||
curCe.value = curNj.value.children[0];
|
||||
} else {
|
||||
curCe.value = null;
|
||||
}
|
||||
} else {
|
||||
curNj.value = null;
|
||||
curCe.value = null;
|
||||
}
|
||||
}
|
||||
|
||||
const selectNj = (type: any) => {
|
||||
curNj.value = type;
|
||||
curCe.value = curNj.value.children[0];
|
||||
if (curNj.value.children && curNj.value.children.length > 0) {
|
||||
curCe.value = curNj.value.children[0];
|
||||
} else {
|
||||
curCe.value = null;
|
||||
}
|
||||
}
|
||||
|
||||
const selectCe = (type: any) => {
|
||||
curCe.value = type;
|
||||
}
|
||||
@ -96,9 +104,36 @@ const selectCategory = (type: any) => {
|
||||
curCategory.value = type;
|
||||
}
|
||||
|
||||
// 获取当前选中的叶子节点(支持2级和3级结构)
|
||||
const getLeafNode = () => {
|
||||
// 如果有第3级(上下册),返回第3级
|
||||
if (curCe.value) {
|
||||
return curCe.value;
|
||||
}
|
||||
// 如果只有第2级(年级),返回第2级
|
||||
if (curNj.value) {
|
||||
return curNj.value;
|
||||
}
|
||||
// 如果只有第1级(科目),返回第1级
|
||||
if (curType.value) {
|
||||
return curType.value;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
const goTo = function () {
|
||||
const leafNode = getLeafNode();
|
||||
|
||||
if (!leafNode) {
|
||||
uni.showToast({
|
||||
title: '请先选择资源类型',
|
||||
icon: 'none'
|
||||
});
|
||||
return;
|
||||
}
|
||||
|
||||
const params = {
|
||||
resourType: curCe.value.key, // 修改参数名为resourType,与后端一致
|
||||
resourType: leafNode.key, // ✅ 动态获取叶子节点的key
|
||||
category: curCategory.value.key,
|
||||
};
|
||||
|
||||
@ -106,6 +141,8 @@ const goTo = function () {
|
||||
科目: curType.value?.title,
|
||||
年级: curNj.value?.title,
|
||||
上下册: curCe.value?.title,
|
||||
叶子节点: leafNode.title,
|
||||
叶子节点层级: curCe.value ? '3级' : (curNj.value ? '2级' : '1级'),
|
||||
资源类型: curCategory.value?.label,
|
||||
传递参数: params
|
||||
});
|
||||
@ -116,9 +153,41 @@ const goTo = function () {
|
||||
});
|
||||
}
|
||||
|
||||
// 加载资源类别字典数据
|
||||
const loadCategoryList = async () => {
|
||||
try {
|
||||
const pid = '1391443399'; // 资源类别字典父ID
|
||||
const res = await dicFindByPidApi({ pid });
|
||||
console.log('资源类别字典数据:', res);
|
||||
|
||||
if (res && res.result && Array.isArray(res.result) && res.result.length > 0) {
|
||||
// 保留"不限"选项,添加从字典表获取的选项
|
||||
const dictOptions = res.result.map((item: any) => ({
|
||||
key: item.dictionaryCode || item.dictionaryValue || item.id, // 使用 dictionaryCode 作为 key
|
||||
label: item.dictionaryName || item.dictionaryValue || item.name
|
||||
}));
|
||||
|
||||
categoryList.value = [
|
||||
{ key: '', label: '不限' },
|
||||
...dictOptions
|
||||
];
|
||||
|
||||
console.log('资源类别选项(使用 dictionaryCode):', categoryList.value);
|
||||
} else {
|
||||
console.warn('字典数据为空或格式不正确,使用默认资源类别选项');
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('加载资源类别字典失败:', error);
|
||||
// 保持默认的"不限"选项
|
||||
}
|
||||
};
|
||||
|
||||
// 页面加载完成后的初始化操作
|
||||
onMounted(async () => {
|
||||
const res = await typesFindTreeApi();
|
||||
// 加载资源类别字典
|
||||
await loadCategoryList();
|
||||
|
||||
const res = await zymlFindTreeApi();
|
||||
typeTree.value = res.result || [];
|
||||
console.log('教学资源页面加载完成', res);
|
||||
|
||||
|
||||
@ -103,7 +103,7 @@
|
||||
<script lang="ts" setup>
|
||||
import { imagUrl } from "@/utils";
|
||||
import { useLayout } from "@/components/BasicListLayout/hooks/useLayout";
|
||||
import { resourcesFindPageApi, resourcesAddNumByTypeApi } from "@/api/base/server";
|
||||
import { zymxFindPageApi, zymxAddNumByTypeApi } from "@/api/base/server";
|
||||
import { useDataStore } from "@/store/modules/data";
|
||||
import {
|
||||
isVideo,
|
||||
@ -131,7 +131,7 @@ const searchKeyword = ref<string>('');
|
||||
|
||||
// --- Layout Hook (Removed 'immediate' from componentProps) ---
|
||||
const [register, { reload, setParam }] = useLayout({
|
||||
api: resourcesFindPageApi,
|
||||
api: zymxFindPageApi,
|
||||
componentProps: {
|
||||
defaultPageSize: 5, // 每页显示5条数据
|
||||
loadingMoreEnabled: true, // 启用加载更多
|
||||
@ -203,7 +203,7 @@ const handlePreviewImage = (item) => {
|
||||
|
||||
// --- 记录查看行为 ---
|
||||
const recordViewAction = (item) => {
|
||||
resourcesAddNumByTypeApi({
|
||||
zymxAddNumByTypeApi({
|
||||
id: item.id,
|
||||
type: 'view'
|
||||
});
|
||||
@ -227,7 +227,7 @@ const downloadResouce = (item: any) => {
|
||||
// 使用工具函数进行下载
|
||||
downloadFile(finalUrl, fileName)
|
||||
.then(() => {
|
||||
resourcesAddNumByTypeApi({
|
||||
zymxAddNumByTypeApi({
|
||||
id: item.id,
|
||||
type: 'down'
|
||||
});
|
||||
|
||||
@ -118,12 +118,13 @@ const loadPbList = async (isRefresh = false) => {
|
||||
}
|
||||
|
||||
try {
|
||||
// 查询所有排班数据,然后在前端过滤
|
||||
// 说明:课程巡查(A)和课业辅导巡查(B)在此页面展示,值周巡查(C)在zbxc/xcPbList.vue展示
|
||||
const params = {
|
||||
page: pagination.page,
|
||||
rows: pagination.pageSize,
|
||||
// 可以根据需要添加筛选条件
|
||||
// xcbt: '', // 排班标题
|
||||
// xclx: '', // 排班类型
|
||||
// xkId: '', // 选课ID
|
||||
// xqId: '', // 学期ID
|
||||
};
|
||||
@ -135,10 +136,16 @@ const loadPbList = async (isRefresh = false) => {
|
||||
// 根据实际API响应结构调整数据获取逻辑
|
||||
const list = res.rows || res.result?.rows || res.result?.list || [];
|
||||
|
||||
// ✅ 过滤数据:只保留课程巡查(A)和课业辅导巡查(B),排除值周巡查(C)
|
||||
const filteredList = list.filter((item: any) => item.xclx === 'A' || item.xclx === 'B');
|
||||
|
||||
console.log('原始数据数量:', list.length, '过滤后数据数量:', filteredList.length);
|
||||
console.log('过滤掉的值周巡查(C)数量:', list.length - filteredList.length);
|
||||
|
||||
if (isRefresh) {
|
||||
pbList.value = list;
|
||||
pbList.value = filteredList;
|
||||
} else {
|
||||
pbList.value.push(...list);
|
||||
pbList.value.push(...filteredList);
|
||||
}
|
||||
|
||||
// 使用records字段作为总记录数,如果没有则使用total
|
||||
@ -235,6 +242,8 @@ const getXclxText = (xclx: string) => {
|
||||
return '课程巡查';
|
||||
} else if (xclx === 'B') {
|
||||
return '课业辅导巡查';
|
||||
} else if (xclx === 'C') {
|
||||
return '值周巡查';
|
||||
}
|
||||
return '暂无';
|
||||
};
|
||||
@ -254,6 +263,7 @@ const goXc = (pb: any) => {
|
||||
delete pbData.id; // 移除原始的id字段
|
||||
|
||||
setData(pbData);
|
||||
|
||||
if (pb.xclx === 'A') {
|
||||
// 课程巡查,跳转到课程巡查列表
|
||||
uni.navigateTo({
|
||||
@ -265,9 +275,9 @@ const goXc = (pb: any) => {
|
||||
url: `/pages/view/routine/kefuxuncha/kyXkList`,
|
||||
});
|
||||
} else if (pb.xclx === 'C') {
|
||||
// 值周巡查,跳转到值周巡查列表
|
||||
// 值周巡查,跳转到值周巡查列表(zbxc目录下)
|
||||
uni.navigateTo({
|
||||
url: `/pages/view/routine/kefuxuncha/zbList`,
|
||||
url: `/pages/view/routine/zbxc/zbList`,
|
||||
});
|
||||
} else {
|
||||
uni.showToast({
|
||||
|
||||
@ -141,8 +141,8 @@
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import { resourcesSaveApi } from "@/api/base/server";
|
||||
import { typesFindTreeByZylxApi } from "@/api/base/server";
|
||||
import { zymxSaveApi } from "@/api/base/server";
|
||||
import { zymlFindTreeByZylxApi } from "@/api/base/server";
|
||||
import { attachmentUpload } from "@/api/system/upload";
|
||||
import { imagUrl } from "@/utils";
|
||||
import { useDicStore } from "@/store/modules/dic";
|
||||
@ -439,7 +439,7 @@ const handleSubmitForm = async () => {
|
||||
|
||||
|
||||
|
||||
const result = await resourcesSaveApi(params);
|
||||
const result = await zymxSaveApi(params);
|
||||
|
||||
if (result.resultCode === 1) {
|
||||
uni.showToast({ title: '操作成功', icon: 'success' });
|
||||
@ -528,7 +528,7 @@ const loadTreeData = async () => {
|
||||
|
||||
console.log('add-resource 加载资源目录,zylx:', zylx.value);
|
||||
|
||||
const res = await typesFindTreeByZylxApi({ zylx: zylx.value });
|
||||
const res = await zymlFindTreeByZylxApi({ zylx: zylx.value });
|
||||
// 处理返回的数据结构,确保与BasicTree组件兼容
|
||||
if (res && Array.isArray(res)) {
|
||||
treeData.value = res.map((item: any) => ({
|
||||
|
||||
@ -37,7 +37,7 @@
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import { typesFindTreeByZylxApi } from "@/api/base/server";
|
||||
import { zymlFindTreeByZylxApi } from "@/api/base/server";
|
||||
import { useDataStore } from "@/store/modules/data";
|
||||
const { setData } = useDataStore();
|
||||
|
||||
@ -136,7 +136,7 @@ const initData = async () => {
|
||||
console.log('当前URL:', window.location.href);
|
||||
|
||||
// 根据资源类型加载对应的数据
|
||||
const res = await typesFindTreeByZylxApi({ zylx: zylx.value });
|
||||
const res = await zymlFindTreeByZylxApi({ zylx: zylx.value });
|
||||
typeTree.value = res.result || [];
|
||||
console.log(`${topLevelTitle.value}资源页面加载完成`, res);
|
||||
|
||||
|
||||
@ -103,7 +103,7 @@
|
||||
<script lang="ts" setup>
|
||||
import { imagUrl } from "@/utils";
|
||||
import { useLayout } from "@/components/BasicListLayout/hooks/useLayout";
|
||||
import { resourcesFindPageApi, resourcesAddNumByTypeApi } from "@/api/base/server";
|
||||
import { zymxFindPageApi, zymxAddNumByTypeApi } from "@/api/base/server";
|
||||
import { useDataStore } from "@/store/modules/data";
|
||||
import {
|
||||
isVideo,
|
||||
@ -131,7 +131,7 @@ const searchKeyword = ref<string>('');
|
||||
|
||||
// --- Layout Hook (Removed 'immediate' from componentProps) ---
|
||||
const [register, { reload, setParam }] = useLayout({
|
||||
api: resourcesFindPageApi,
|
||||
api: zymxFindPageApi,
|
||||
componentProps: {
|
||||
defaultPageSize: 5, // 每页显示5条数据
|
||||
loadingMoreEnabled: true, // 启用加载更多
|
||||
@ -203,7 +203,7 @@ const handlePreviewImage = (item) => {
|
||||
|
||||
// --- 记录查看行为 ---
|
||||
const recordViewAction = (item) => {
|
||||
resourcesAddNumByTypeApi({
|
||||
zymxAddNumByTypeApi({
|
||||
id: item.id,
|
||||
type: 'view'
|
||||
});
|
||||
@ -227,7 +227,7 @@ const downloadResouce = (item: any) => {
|
||||
// 使用工具函数进行下载
|
||||
downloadFile(finalUrl, fileName)
|
||||
.then(() => {
|
||||
resourcesAddNumByTypeApi({
|
||||
zymxAddNumByTypeApi({
|
||||
id: item.id,
|
||||
type: 'down'
|
||||
});
|
||||
|
||||
570
src/pages/view/routine/zbxc/xcPbList.vue
Normal file
570
src/pages/view/routine/zbxc/xcPbList.vue
Normal file
@ -0,0 +1,570 @@
|
||||
<template>
|
||||
<view class="interest-course">
|
||||
<!-- 选课排班信息头部 - 固定部分 -->
|
||||
<view class="selection-header">
|
||||
<view class="header-content">
|
||||
<view class="title-section">
|
||||
<view class="title">
|
||||
<text v-if="pbList && pbList.length > 0">
|
||||
{{ getCurrentSemesterName() }} - 教学巡查
|
||||
</text>
|
||||
<text v-else>暂无排班数据</text>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<!-- 可滚动的内容区域 -->
|
||||
<scroll-view
|
||||
class="scrollable-content"
|
||||
scroll-y
|
||||
@scrolltolower="onScrollToLower"
|
||||
:refresher-enabled="true"
|
||||
:refresher-triggered="refreshing"
|
||||
@refresherrefresh="onRefresh"
|
||||
refresher-background="#f8fafc"
|
||||
>
|
||||
<!-- 排班列表 -->
|
||||
<view class="course-list" v-if="pbList && pbList.length > 0">
|
||||
<view v-for="(pb, index) in pbList" :key="pb.id || index" class="course-item">
|
||||
<view class="status-badge" :class="getStatusClass(pb)">
|
||||
{{ getStatusText(pb) }}
|
||||
</view>
|
||||
<view class="course-name">{{ pb.xcbt }}</view>
|
||||
<view class="course-info-item">
|
||||
<view class="info-label">巡查类型:</view>
|
||||
<view class="info-data">{{ getXclxText(pb.xclx) }}</view>
|
||||
</view>
|
||||
<view class="course-info-item">
|
||||
<view class="info-label">当前学期:</view>
|
||||
<view class="info-data">{{ pb.xqmc || '暂无' }}</view>
|
||||
</view>
|
||||
<view class="course-info-item" v-if="pb.remark">
|
||||
<view class="info-label">备注:</view>
|
||||
<view class="info-data">{{ pb.remark }}</view>
|
||||
</view>
|
||||
<view class="separator-line"></view>
|
||||
<view class="course-btn-group">
|
||||
<view class="detail-btn" @click.stop="goXc(pb)">巡查</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 class="load-more" v-if="hasMore && pbList.length > 0">
|
||||
<u-loading-icon v-if="loading" mode="spinner" size="20"></u-loading-icon>
|
||||
<text v-else>加载更多</text>
|
||||
</view>
|
||||
|
||||
<!-- 没有更多数据提示 -->
|
||||
<view class="no-more" v-if="!hasMore && pbList.length > 0">
|
||||
<text>没有更多数据了</text>
|
||||
</view>
|
||||
</scroll-view>
|
||||
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import {
|
||||
ref,
|
||||
onBeforeUnmount,
|
||||
onMounted,
|
||||
reactive,
|
||||
} from "vue";
|
||||
import { useUserStore } from "@/store/modules/user";
|
||||
import { useDataStore } from "@/store/modules/data";
|
||||
import { getPbPageApi } from "@/api/base/pbApi";
|
||||
import dayjs from "dayjs";
|
||||
|
||||
const { getJs } = useUserStore();
|
||||
const { getData, setData } = useDataStore();
|
||||
|
||||
// 排班列表数据
|
||||
const pbList = ref<any[]>([]);
|
||||
const loading = ref(false);
|
||||
const hasMore = ref(true);
|
||||
const refreshing = ref(false);
|
||||
|
||||
// 分页参数
|
||||
const pagination = reactive({
|
||||
page: 1,
|
||||
pageSize: 10,
|
||||
total: 0,
|
||||
});
|
||||
|
||||
onMounted(() => {
|
||||
loadPbList();
|
||||
});
|
||||
|
||||
// 加载排班列表
|
||||
const loadPbList = async (isRefresh = false) => {
|
||||
if (loading.value) return;
|
||||
|
||||
loading.value = true;
|
||||
|
||||
if (isRefresh) {
|
||||
pagination.page = 1;
|
||||
pbList.value = [];
|
||||
hasMore.value = true;
|
||||
}
|
||||
|
||||
try {
|
||||
const params = {
|
||||
page: pagination.page,
|
||||
rows: pagination.pageSize,
|
||||
xclx: 'C', // 巡查类型:C-值周巡查
|
||||
// 可以根据需要添加筛选条件
|
||||
// xcbt: '', // 排班标题
|
||||
// xkId: '', // 选课ID
|
||||
// xqId: '', // 学期ID
|
||||
};
|
||||
|
||||
const res: any = await getPbPageApi(params);
|
||||
|
||||
// 根据实际API响应结构判断成功条件
|
||||
if (res && (res.resultCode == 1 || res.rows || res.result)) {
|
||||
// 根据实际API响应结构调整数据获取逻辑
|
||||
const list = res.rows || res.result?.rows || res.result?.list || [];
|
||||
|
||||
if (isRefresh) {
|
||||
pbList.value = list;
|
||||
} else {
|
||||
pbList.value.push(...list);
|
||||
}
|
||||
|
||||
// 使用records字段作为总记录数,如果没有则使用total
|
||||
pagination.total = res.records || res.total || res.result?.total || 0;
|
||||
|
||||
// 判断是否还有更多数据
|
||||
hasMore.value = pbList.value.length < pagination.total;
|
||||
|
||||
if (list.length < pagination.pageSize) {
|
||||
hasMore.value = false;
|
||||
}
|
||||
} else {
|
||||
uni.showToast({
|
||||
title: res.resultMessage || res.message || '获取排班列表失败',
|
||||
icon: 'none'
|
||||
});
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('加载排班列表失败:', error);
|
||||
uni.showToast({
|
||||
title: '加载排班列表失败',
|
||||
icon: 'none'
|
||||
});
|
||||
} finally {
|
||||
loading.value = false;
|
||||
refreshing.value = false;
|
||||
}
|
||||
};
|
||||
|
||||
// 加载更多
|
||||
const loadMore = () => {
|
||||
if (hasMore.value && !loading.value) {
|
||||
pagination.page++;
|
||||
loadPbList();
|
||||
}
|
||||
};
|
||||
|
||||
// 滚动到底部时加载更多
|
||||
const onScrollToLower = () => {
|
||||
if (hasMore.value && !loading.value) {
|
||||
pagination.page++;
|
||||
loadPbList();
|
||||
}
|
||||
};
|
||||
|
||||
// 下拉刷新
|
||||
const onRefresh = () => {
|
||||
refreshing.value = true;
|
||||
loadPbList(true);
|
||||
};
|
||||
|
||||
// 获取当前学期名称
|
||||
const getCurrentSemesterName = () => {
|
||||
if (pbList.value && pbList.value.length > 0) {
|
||||
// 从第一个排班获取学期名称
|
||||
return pbList.value[0].xqmc || '当前学期';
|
||||
}
|
||||
return '当前学期';
|
||||
};
|
||||
|
||||
// 格式化日期时间
|
||||
const formatDateTime = (dateTime: string) => {
|
||||
if (!dateTime) {
|
||||
return '暂无';
|
||||
}
|
||||
|
||||
try {
|
||||
return dayjs(dateTime).format('YYYY-MM-DD HH:mm:ss');
|
||||
} catch (error) {
|
||||
console.error('时间格式化错误:', error);
|
||||
return dateTime;
|
||||
}
|
||||
};
|
||||
|
||||
// 获取状态文本
|
||||
const getStatusText = (pb: any) => {
|
||||
if (!pb.status || pb.status === 'A') {
|
||||
return '正常';
|
||||
}
|
||||
return '已停用';
|
||||
};
|
||||
|
||||
// 获取状态样式类
|
||||
const getStatusClass = (pb: any) => {
|
||||
if (!pb.status || pb.status === 'A') {
|
||||
return 'normal';
|
||||
}
|
||||
return 'disabled';
|
||||
};
|
||||
|
||||
// 获取巡查类型文本
|
||||
const getXclxText = (xclx: string) => {
|
||||
if (xclx === 'A') {
|
||||
return '课程巡查';
|
||||
} else if (xclx === 'B') {
|
||||
return '课业辅导巡查';
|
||||
} else if (xclx === 'C') {
|
||||
return '值周巡查';
|
||||
}
|
||||
return '暂无';
|
||||
};
|
||||
|
||||
// 跳转到巡查
|
||||
const goXc = (pb: any) => {
|
||||
// 添加调试信息
|
||||
console.log('排班数据pb:', pb);
|
||||
console.log('pb.id:', pb?.id);
|
||||
console.log('pb的所有属性:', Object.keys(pb || {}));
|
||||
|
||||
// 确保数据一致性,只使用pbId字段
|
||||
const pbData = {
|
||||
...pb,
|
||||
pbId: pb.id, // 将id字段作为pbId字段
|
||||
};
|
||||
delete pbData.id; // 移除原始的id字段
|
||||
|
||||
setData(pbData);
|
||||
|
||||
// 由于此页面只显示值周巡查(C),直接跳转到值周巡查列表
|
||||
if (pb.xclx === 'C') {
|
||||
// 值周巡查,跳转到值周巡查列表(zbxc目录下)
|
||||
uni.navigateTo({
|
||||
url: `/pages/view/routine/zbxc/zbList`,
|
||||
});
|
||||
} else {
|
||||
// 理论上不会执行到这里,因为已经过滤掉了其他类型
|
||||
console.warn('意外的巡查类型:', pb.xclx);
|
||||
uni.showToast({
|
||||
title: '巡查类型不匹配',
|
||||
icon: 'none'
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
// 页面卸载前清除定时器
|
||||
onBeforeUnmount(() => {
|
||||
// 清理工作
|
||||
});
|
||||
|
||||
// 暴露方法给父组件
|
||||
defineExpose({
|
||||
loadPbList,
|
||||
onRefresh,
|
||||
});
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.interest-course {
|
||||
min-height: 100%;
|
||||
background: linear-gradient(180deg, #f8fafc 0%, #f1f5f9 100%);
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
height: 100%;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.selection-header {
|
||||
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
|
||||
padding: 25px 20px;
|
||||
color: #fff;
|
||||
border-radius: 0 0 20px 20px;
|
||||
box-shadow: 0 8px 32px rgba(102, 126, 234, 0.3);
|
||||
position: sticky;
|
||||
top: 0;
|
||||
left: 0;
|
||||
right: 0;
|
||||
z-index: 10;
|
||||
position: relative;
|
||||
overflow: hidden;
|
||||
|
||||
&::before {
|
||||
content: '';
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
right: 0;
|
||||
bottom: 0;
|
||||
background: linear-gradient(45deg, rgba(255, 255, 255, 0.1) 0%, transparent 50%, rgba(255, 255, 255, 0.05) 100%);
|
||||
pointer-events: none;
|
||||
}
|
||||
|
||||
.header-content {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 15px;
|
||||
position: relative;
|
||||
z-index: 1;
|
||||
|
||||
.title-section {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
|
||||
.title {
|
||||
font-size: 20px;
|
||||
font-weight: 700;
|
||||
text-align: center;
|
||||
text-shadow: 0 2px 4px rgba(0, 0, 0, 0.1);
|
||||
letter-spacing: 0.5px;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 可滚动内容区域样式
|
||||
.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: 20px;
|
||||
background-color: #fff;
|
||||
border-radius: 12px;
|
||||
padding: 20px;
|
||||
box-sizing: border-box;
|
||||
border: 1px solid #f0f0f0;
|
||||
transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1);
|
||||
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.06);
|
||||
animation: fadeInUp 0.6s ease-out;
|
||||
|
||||
&:hover {
|
||||
transform: translateY(-2px);
|
||||
box-shadow: 0 8px 25px rgba(0, 0, 0, 0.12);
|
||||
border-color: #e8e8e8;
|
||||
}
|
||||
|
||||
.status-badge {
|
||||
position: absolute;
|
||||
top: 15px;
|
||||
right: 15px;
|
||||
background-color: #fff;
|
||||
border-radius: 20px;
|
||||
padding: 6px 12px;
|
||||
font-size: 11px;
|
||||
font-weight: 600;
|
||||
border: 1px solid #e0e0e0;
|
||||
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.08);
|
||||
letter-spacing: 0.5px;
|
||||
animation: fadeInRight 0.5s ease-out 0.2s both;
|
||||
}
|
||||
|
||||
.status-badge.normal {
|
||||
color: #67c23a;
|
||||
border-color: #e1f3d8;
|
||||
background-color: #f0f9ff;
|
||||
}
|
||||
|
||||
.status-badge.disabled {
|
||||
color: #f56c6c;
|
||||
border-color: #fde2e2;
|
||||
background-color: #fef0f0;
|
||||
}
|
||||
|
||||
.course-name {
|
||||
font-size: 17px;
|
||||
font-weight: 600;
|
||||
color: #1a1a1a;
|
||||
margin-bottom: 15px;
|
||||
padding-right: 90px;
|
||||
line-height: 1.4;
|
||||
animation: fadeInLeft 0.5s ease-out 0.1s both;
|
||||
}
|
||||
|
||||
.course-btn-group {
|
||||
display: flex;
|
||||
justify-content: flex-end;
|
||||
gap: 10px;
|
||||
|
||||
.detail-btn {
|
||||
display: inline-block;
|
||||
font-size: 14px;
|
||||
font-weight: 600;
|
||||
padding: 8px 18px;
|
||||
border-radius: 8px;
|
||||
transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1);
|
||||
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.15);
|
||||
animation: fadeInUp 0.5s ease-out 0.3s both;
|
||||
color: #2879ff;
|
||||
background: linear-gradient(135deg, rgba(40, 121, 255, 0.1), rgba(40, 121, 255, 0.05));
|
||||
border: 1px solid #2879ff;
|
||||
|
||||
&:hover {
|
||||
background: linear-gradient(135deg, rgba(40, 121, 255, 0.15), rgba(40, 121, 255, 0.1));
|
||||
transform: translateY(-1px);
|
||||
box-shadow: 0 4px 15px rgba(40, 121, 255, 0.25);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.course-info-item {
|
||||
display: flex;
|
||||
margin-bottom: 14px;
|
||||
font-size: 13px;
|
||||
align-items: center;
|
||||
animation: fadeInUp 0.5s ease-out 0.15s both;
|
||||
|
||||
.info-label {
|
||||
color: #666;
|
||||
flex: 0 0 100px;
|
||||
font-weight: 500;
|
||||
}
|
||||
|
||||
.info-data {
|
||||
flex: 1 0 1px;
|
||||
color: #333;
|
||||
font-weight: 400;
|
||||
}
|
||||
}
|
||||
|
||||
.separator-line {
|
||||
height: 1px;
|
||||
background: linear-gradient(90deg, transparent, #e8e8e8, transparent);
|
||||
margin: 18px 0;
|
||||
opacity: 0.8;
|
||||
animation: fadeIn 0.5s ease-out 0.25s both;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 加载更多样式
|
||||
.load-more {
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
padding: 20px;
|
||||
color: #666;
|
||||
font-size: 14px;
|
||||
|
||||
text {
|
||||
color: #2879ff;
|
||||
cursor: pointer;
|
||||
}
|
||||
}
|
||||
|
||||
// 没有更多数据样式
|
||||
.no-more {
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
padding: 20px;
|
||||
color: #999;
|
||||
font-size: 12px;
|
||||
|
||||
text {
|
||||
color: #999;
|
||||
}
|
||||
}
|
||||
|
||||
// 添加动画关键帧
|
||||
@keyframes fadeInUp {
|
||||
from {
|
||||
opacity: 0;
|
||||
transform: translateY(20px);
|
||||
}
|
||||
to {
|
||||
opacity: 1;
|
||||
transform: translateY(0);
|
||||
}
|
||||
}
|
||||
|
||||
@keyframes fadeInLeft {
|
||||
from {
|
||||
opacity: 0;
|
||||
transform: translateX(-20px);
|
||||
}
|
||||
to {
|
||||
opacity: 1;
|
||||
transform: translateX(0);
|
||||
}
|
||||
}
|
||||
|
||||
@keyframes fadeInRight {
|
||||
from {
|
||||
opacity: 0;
|
||||
transform: translateX(20px);
|
||||
}
|
||||
to {
|
||||
opacity: 1;
|
||||
transform: translateX(0);
|
||||
}
|
||||
}
|
||||
|
||||
@keyframes fadeIn {
|
||||
from {
|
||||
opacity: 0;
|
||||
}
|
||||
to {
|
||||
opacity: 1;
|
||||
}
|
||||
}
|
||||
|
||||
// 暂无数据样式
|
||||
.empty-course-list {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
padding: 80px 20px;
|
||||
text-align: center;
|
||||
|
||||
.empty-icon {
|
||||
margin-bottom: 25px;
|
||||
background: linear-gradient(135deg, #f1f5f9 0%, #e2e8f0 100%);
|
||||
width: 90px;
|
||||
height: 90px;
|
||||
border-radius: 50%;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
box-shadow: 0 4px 20px rgba(0, 0, 0, 0.08);
|
||||
border: 2px solid rgba(255, 255, 255, 0.8);
|
||||
}
|
||||
|
||||
.empty-text {
|
||||
font-size: 18px;
|
||||
font-weight: 600;
|
||||
color: #475569;
|
||||
margin-bottom: 8px;
|
||||
letter-spacing: 0.3px;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
@ -137,8 +137,8 @@
|
||||
<ImageVideoUpload
|
||||
v-model:image-list="imageList"
|
||||
v-model:video-list="videoList"
|
||||
:max-image-count="5"
|
||||
:max-video-count="3"
|
||||
:max-image-count="10"
|
||||
:max-video-count="5"
|
||||
:compress-config="compressConfig"
|
||||
:upload-api="attachmentUpload"
|
||||
@image-upload-success="onImageUploadSuccess"
|
||||
@ -259,10 +259,10 @@ const currentInputLabel = ref('');
|
||||
const currentInputValue = ref('');
|
||||
const currentItem = ref<any>(null);
|
||||
|
||||
// 格式化时间
|
||||
// 格式化时间(只显示日期,不显示时和分)
|
||||
const formatTime = (timestamp: string) => {
|
||||
if (!timestamp) return '';
|
||||
return dayjs(timestamp).format('MM-DD HH:mm');
|
||||
return dayjs(timestamp).format('MM-DD');
|
||||
};
|
||||
|
||||
// 加载巡查项目
|
||||
@ -135,11 +135,11 @@ const getDutyDisplayName = (zb: any) => {
|
||||
return displayName || '值周教师';
|
||||
};
|
||||
|
||||
// 格式化值周时间
|
||||
// 格式化值周时间(只显示日期,不显示时和分)
|
||||
const formatDutyTime = (zb: any) => {
|
||||
if (zb.zbkstime && zb.zbjstime) {
|
||||
const startTime = dayjs(zb.zbkstime).format('MM-DD HH:mm');
|
||||
const endTime = dayjs(zb.zbjstime).format('MM-DD HH:mm');
|
||||
const startTime = dayjs(zb.zbkstime).format('MM-DD');
|
||||
const endTime = dayjs(zb.zbjstime).format('MM-DD');
|
||||
return `${startTime} ~ ${endTime}`;
|
||||
}
|
||||
return '暂无';
|
||||
@ -384,7 +384,7 @@ const goXc = async (zb: any) => {
|
||||
|
||||
dataStore.setData(combinedData);
|
||||
uni.navigateTo({
|
||||
url: `/pages/view/routine/kefuxuncha/zbDetail`,
|
||||
url: `/pages/view/routine/zbxc/zbDetail`,
|
||||
});
|
||||
};
|
||||
|
||||
@ -413,7 +413,7 @@ const goRecord = (zb: any) => {
|
||||
|
||||
dataStore.setData(combinedData);
|
||||
uni.navigateTo({
|
||||
url: `/pages/view/routine/kefuxuncha/zbRecord`,
|
||||
url: `/pages/view/routine/zbxc/zbRecord`,
|
||||
});
|
||||
};
|
||||
|
||||
BIN
src/static/base/home/zbxc.png
Normal file
BIN
src/static/base/home/zbxc.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 4.6 KiB |
Loading…
x
Reference in New Issue
Block a user