调整请假审批和代课的处理

This commit is contained in:
ywyonui 2025-09-24 11:34:23 +08:00
parent e9efeac6ff
commit 9aa15f7252
10 changed files with 530 additions and 741 deletions

View File

@ -1,5 +1,10 @@
<template>
<view class="lcgl-info">
<view class="flex-row items-center justify-between mb-15" v-if="showTitle">
<view class="dk-title">
<BasicTitle line title="审批流程" :isBorder="false" />
</view>
</view>
<!-- 申请人 -->
<view class="info-section sqr">
<view class="section-title">申请人</view>
@ -136,10 +141,12 @@ const { setLcgl } = useDataStore();
//
const props = withDefaults(defineProps<{
ywId: string,
ywType: string
ywType: string,
showTitle?: boolean
}>(), {
ywId: '',
ywType: ''
ywType: '',
showTitle: false
});
const sqrSp = ref<any>({});

View File

@ -1,222 +0,0 @@
<template>
<view class="dk-info">
<view class="info-card" v-for="(item, index) in dkList" :key="index">
<view class="card-header">
<text class="applicant-name">{{ item.dktime }}{{ item.xqLabel }}{{ item.jcmc }}</text>
<text v-if="item.jsId === jsId" class="assigned-tag">我的代课</text>
</view>
<view class="divider"></view>
<view class="card-body">
<view class="info-row">
<text class="label">排课名称:</text>
<text class="value">{{ item.pkMc }}</text>
</view>
<view class="info-row">
<text class="label">上课时间:</text>
<text class="value">{{ item.startTime }}-{{ item.endTime }}</text>
</view>
<view class="info-row">
<text class="label">代课老师:</text>
<view class="value">{{ item.jsName }}</view>
</view>
<!-- <view class="info-row">
<text class="label">确认状态:</text>
<view class="value">{{ item.statusLabel }}</view>
</view> -->
</view>
</view>
</view>
</template>
<script setup lang="ts">
import { findDkPageApi } from "@/api/base/jsQjApi";
import { useUserStore } from "@/store/modules/user";
import { ref, computed, watch, onMounted } from "vue";
const { getJs } = useUserStore();
//
const props = withDefaults(
defineProps<{
qjId?: string;
}>(),
{
qjId: ""
}
);
// emit
const emit = defineEmits(["loadDkList"]);
//
const notifyParentLoaded = () => {
emit("loadDkList", dkList.value);
};
const jsId = computed(() => getJs.id);
const wdNameList = ref<string[]>([
"周一",
"周二",
"周三",
"周四",
"周五",
"周六",
"周日",
]);
const jsTypeMc: any = {
ZAM: "早自习",
AM: "上午",
PM: "下午",
};
const qrStatus: any = {
"wait": "待确认",
"approved": "同意",
"rejected": "拒绝",
};
const dkList = ref<any>([]);
watch(
() => props.qjId,
(newVal, oldVal) => {
//
console.log("qjId changed:", newVal, oldVal);
if (newVal != oldVal && newVal) {
init();
}
}
);
const init = async () => {
const res: any = await findDkPageApi({
qjId: props.qjId,
page: 1,
rows: 1000,
});
const rows = (res && (res.rows || res.result || res.data)) || [];
dkList.value = rows.map((item: any) => {
item.dktime = item.dktime.split(" ")[0];
item.jcmc = jsTypeMc[item.jcType] + "第" + item.jc + "节";
const xq: number = item.xq - 1;
item.xqLabel = wdNameList.value[xq];
item.statusLabel = qrStatus[item.qrStatus] || "未知";
return item;
});
//
dkList.value = dkList.value.sort((a: any, b: any) => {
if (a.jsId === jsId.value) {
return -1;
} else if (b.jsId === jsId.value) {
return 1;
} else {
return 0;
}
});
notifyParentLoaded();
};
//
onMounted(async () => {
await init();
});
const getDkList = () => {
return dkList.value;
};
//
defineExpose({
getDkList,
});
</script>
<style lang="scss" scoped>
.dk-info {
background-color: #f5f7fa;
}
.info-card {
margin: 15px;
background-color: #fff;
border-radius: 8px;
box-shadow: 0 2px 6px rgba(0, 0, 0, 0.05);
.card-header {
font-size: 16px;
font-weight: bold;
color: #333;
padding: 15px;
position: relative;
.applicant-name {
font-size: 16px;
font-weight: bold;
color: #333;
}
/* 添加指派标记样式 */
.assigned-tag {
background-color: var(--primary-color, #1890ff);;
color: white;
font-size: 12px;
padding: 5px 10px;
border-bottom-left-radius: 8px;
border-top-right-radius: 8px;
font-weight: normal;
position: absolute;
right: 0;
top: 0;
}
}
.divider {
height: 1px;
background-color: #eee;
}
.card-body {
padding: 15px;
.info-row {
display: flex;
margin-bottom: 10px;
.label {
font-size: 14px;
color: #999;
width: 70px;
flex-shrink: 0;
margin-right: 8px;
}
.value {
font-size: 14px;
color: #333;
flex: 1;
}
}
.info-column {
display: flex;
flex-direction: column;
.label {
font-size: 14px;
color: #999;
flex-shrink: 0;
margin-right: 8px;
width: 100%;
margin-bottom: 5px;
}
.value {
font-size: 14px;
color: #333;
flex: 1;
}
}
}
}
</style>

View File

@ -1,19 +1,25 @@
<template>
<view class="info-card">
<view class="card-header">
<text class="applicant-name" v-if="dbFlag">{{ qjData.xxzy }}</text>
<text class="applicant-name" v-else>教师{{ qjData.jsName }}的请假申请</text>
<view class="qj-info">
<view class="flex-row items-center justify-between mx-15 mt-15">
<view class="dk-title">
<BasicTitle line title="请假信息" :isBorder="false" />
</view>
</view>
<view class="divider"></view>
<view class="card-body">
<view class="info-row"><text class="label">请假类型:</text><text class="value">{{ qjData.qjlx }}</text></view>
<view class="info-row"><text class="label">开始时间:</text><text class="value">{{ qjData.qjkstime }}</text></view>
<view class="info-row"><text class="label">结束时间:</text><text class="value">{{ qjData.qjjstime }}</text></view>
<view class="info-row"><text class="label">请假时长:</text><text class="value">{{ qjData.qjsc }}</text></view>
<view class="info-row"><text class="label">请假事由:</text><text class="value">{{ qjData.qjsy }}</text></view>
<view class="info-row" style="margin-bottom: 0; margin-top: 10px">
<text class="label">代课方式:</text>
<text class="value" :class="{ 'no-dk-style': dkfsText === '无须代课' }">{{ dkfsText }}</text>
<view class="info-card m-15">
<view class="card-header">
<text class="applicant-name" v-if="dbFlag">{{ qjData.xxzy }}</text>
<text class="applicant-name" v-else>教师{{ qjData.jsName }}的请假申请</text>
</view>
<view class="card-body">
<view class="info-row"><text class="label">请假类型:</text><text class="value">{{ qjData.qjlx }}</text></view>
<view class="info-row"><text class="label">开始时间:</text><text class="value">{{ qjData.qjkstime }}</text></view>
<view class="info-row"><text class="label">结束时间:</text><text class="value">{{ qjData.qjjstime }}</text></view>
<view class="info-row"><text class="label">请假时长:</text><text class="value">{{ qjData.qjsc }}</text></view>
<view class="info-row"><text class="label">请假事由:</text><text class="value">{{ qjData.qjsy }}</text></view>
<view class="info-row" style="margin-bottom: 0; margin-top: 10px">
<text class="label">代课方式:</text>
<text class="value" :class="{ 'no-dk-style': dkfsText === '无须代课' }">{{ dkfsText }}</text>
</view>
</view>
</view>
</view>
@ -102,16 +108,19 @@ defineExpose({
<style lang="scss" scoped>
.info-card {
margin: 15px;
background-color: #fff;
border-radius: 8px;
box-shadow: 0 2px 6px rgba(0, 0, 0, 0.05);
margin-bottom: 30rpx;
padding: 30rpx;
background: #fff;
border-radius: 16rpx;
box-shadow: 0 4rpx 16rpx rgba(0, 0, 0, 0.1);
.card-header {
font-size: 16px;
font-size: 32rpx;
font-weight: bold;
margin-bottom: 30rpx;
color: #333;
padding: 15px;
border-bottom: 4rpx solid #007aff;
padding-bottom: 10rpx;
.applicant-name {
font-size: 16px;

View File

@ -1,43 +1,34 @@
<template>
<view class="back-f8f8f8">
<view class="flex-row items-center justify-between py-15">
<div class="qj-dk">
<view class="flex-row items-center justify-between mx-15">
<view class="dk-title">
<BasicTitle line title="代课明细" :isBorder="false" />
</view>
<view @click="getPkkbList">
<view @click="getPkkbList" v-if="isEdit">
<BasicIcon type="refreshempty" size="25" />
</view>
</view>
<view class="dk-tabs mb-10" v-if="dkList && dkList.length">
<BasicTabs
class="type-tabs"
ref="tabsRef"
:list="tabList"
bar-width="60px"
scroll-count="4"
:current="curTabIndex"
@change="switchTab"
/>
<view class="dk-card" v-if="curTabIndex === 0">
<view class="card-body">
<view class="info-row">
<text class="label">代课老师:</text>
<view class="value">
<BasicJsPicker
@change="changeJsByTy"
:parent-data="tyDk"
:defaultValue="tyDk.dkJsId"
:multiple="false"
:excludeIds="excludeIds"
/>
<view class="dk-edit" v-if="isEdit">
<view class="dk-tabs mb-10" v-if="dkList && dkList.length">
<BasicTabs class="type-tabs" ref="tabsRef" :list="tabList" bar-width="60px" scroll-count="4"
:current="curTabIndex" @change="switchTab" />
<view class="dk-card" v-if="curTabIndex === 0">
<view class="card-body">
<view class="info-row">
<text class="label">代课老师:</text>
<view class="value">
<BasicJsPicker @change="changeJsByTy" :parent-data="tyDk" :defaultValue="tyDk.dkJsId" :multiple="false"
:excludeIds="excludeIds" />
</view>
</view>
</view>
</view>
</view>
<view v-if="curTabIndex === 1">
<view v-for="(item, index) in kmDkList" :key="index">
<view class="dk-card" style="margin: 0">
<view class="card-body">
<view v-if="curTabIndex === 1">
<view class="dk-card">
<view class="card-header">
<text class="applicant-name">排课信息</text>
</view>
<view class="card-body" style="margin-bottom: 20rpx" v-for="(item, index) in kmDkList" :key="index">
<view class="info-row">
<text class="label">排课名称:</text>
<text class="value">{{ item.pkMc }}</text>
@ -45,29 +36,20 @@
<view class="info-row">
<text class="label">代课老师:</text>
<view class="value">
<BasicJsPicker
@change="changeJsByKm"
:parent-data="item"
:defaultValue="item.dkJsId"
:multiple="false"
:excludeIds="excludeIds"
/>
<BasicJsPicker @change="changeJsByKm" :parent-data="item" :defaultValue="item.dkJsId"
:multiple="false" :excludeIds="excludeIds" />
</view>
</view>
</view>
</view>
</view>
</view>
</view>
<view v-if="dkList.length > 0">
<view v-for="(item, index) in dkList" :key="index">
<view class="dk-card">
<view v-if="dkList.length > 0">
<view class="dk-card" v-for="(item, index) in dkList" :key="index">
<view class="card-header">
<text class="applicant-name"
>{{ item.dktime }}{{ wdNameList[item.xq - 1] }}{{
item.jcmc
}}</text
>
<text class="applicant-name">{{ item.dktime }}{{ QjPageUtils.wdNameList[item.xq - 1] }}{{
item.jcmc
}}</text>
</view>
<view class="card-body">
<view class="info-row">
@ -81,38 +63,73 @@
<view class="info-row">
<text class="label">代课老师:</text>
<view class="value" v-if="curTabIndex === 2">
<BasicJsPicker
@change="changeJs"
:parent-data="item"
:defaultValue="item.dkJsId"
:multiple="false"
:excludeIds="excludeIds"
/>
<BasicJsPicker @change="changeJs" :parent-data="item" :defaultValue="item.dkJsId" :multiple="false"
:excludeIds="excludeIds" />
</view>
<view v-else>{{ item.dkJsName }}</view>
</view>
</view>
</view>
</view>
<view v-else class="p-15 flex-row-center color-9 font-13 white-bg-color">暂无数据</view>
</view>
<view v-else class="p-15 flex-row-center color-9 font-13 white-bg-color"
>暂无数据</view
>
</view>
<view class="dk-info" v-else>
<view v-if="dkList && dkList.length">
<view class="dk-card" v-for="(item, index) in dkList" :key="index">
<view class="card-header">
<text class="applicant-name">{{ item.dktime }}{{ item.xqLabel }}{{ item.jcmc }}</text>
<text v-if="item.jsId === jsId" class="assigned-tag">我的代课</text>
</view>
<view class="card-body">
<view class="info-row">
<text class="label">排课名称:</text>
<text class="value">{{ item.pkMc }}</text>
</view>
<view class="info-row">
<text class="label">上课时间:</text>
<text class="value">{{ item.startTime }}-{{ item.endTime }}</text>
</view>
<view class="info-row">
<text class="label">代课老师:</text>
<view class="value" v-if="item.dkJsId">{{ item.jsName }}</view>
<text class="value no-teacher" v-else>没有选择代课老师</text>
</view>
<!-- <view class="info-row">
<text class="label">确认状态:</text>
<view class="value">{{ item.statusLabel }}</view>
</view> -->
</view>
</view>
</view>
<view v-else-if="isDetail" class="empty-dk">
<view>暂无代课信息等待教科处协调</view>
</view>
<view v-else class="empty-dk">
<view>教科处协调,请点击协调代课按钮</view>
<view>如无法协调,请点击转办按钮</view>
</view>
</view>
</div>
</template>
<script setup lang="ts">
import { getPkkbByJsRangeTimeApi, findDkPageApi } from "@/api/base/jsQjApi";
import BasicJsPicker from "@/components/BasicJsPicker/Picker.vue";
import { useUserStore } from "@/store/modules/user";
import { useCommonStore } from "@/store/modules/common";
const { getJs } = useUserStore();
const { getAllJsBasicInfoVo } = useCommonStore();
import { QjPageUtils } from "@/utils/qjPageUtils";
const jsId = computed(() => getJs.id);
// emit
const emit = defineEmits(["inited"]);
//
const props = withDefaults(
defineProps<{
data?: any;
isEdit?: boolean;
isDetail?: boolean;
}>(),
{
data: () => ({
@ -121,25 +138,11 @@ const props = withDefaults(
qjkstime: "", //
qjjstime: "", //
}),
isEdit: true, //
isDetail: false, //
}
);
const wdNameList = ref<string[]>([
"周一",
"周二",
"周三",
"周四",
"周五",
"周六",
"周日",
]);
const jsTypeMc: any = {
ZAM: "早自习",
AM: "上午",
PM: "下午",
};
//
const excludeIds = ref<any>([]);
@ -168,15 +171,12 @@ const switchTab = (index: number) => {
};
const getPkkbList = async () => {
//
if (!props.data.qjjstime || !props.data.qjkstime) {
//
const newList = await QjPageUtils.getPkkbList(props.data);
if (!newList || !newList.length) {
console.log("没有排课信息");
return;
}
const res = await getPkkbByJsRangeTimeApi({
jsId: props.data.jsId,
startTime: props.data.qjkstime,
endTime: props.data.qjjstime,
});
//
const srcData: any = {};
dkList.value.map((item: any) => {
@ -188,26 +188,12 @@ const getPkkbList = async () => {
};
});
const kmMap: any = {};
dkList.value = res.result.map((item: any) => {
item.dktime = item.kbtime.split(" ")[0];
item.njbjmx = item.bc + item.bjmc;
item.jcmc = jsTypeMc[item.jcType] + "第" + item.jc + "节";
const key = item.dktime + item.jcType + item.jc;
const src = srcData[key];
if (src) {
item.dkJsId = src.dkJsId;
item.dkJsName = src.dkJsName;
item.userId = src.userId;
} else {
item.dkJsId = "";
item.dkJsName = "";
item.userId = "";
}
dkList.value = newList.map((item: any) => {
kmMap[item.pkMc] = kmMap[item.pkMc] || {
pkMc: item.pkMc,
};
return item;
});
})
// kmMapvalue
kmDkList.value = Object.values(kmMap);
};
@ -276,27 +262,9 @@ const validate = async () => {
};
const initDkList = async () => {
const resJs = await getAllJsBasicInfoVo();
const jsList = resJs.result || [];
const res: any = await findDkPageApi({
qjId: props.data.qjId,
page: 1,
rows: 1000,
});
const newList = await QjPageUtils.getDkList(props.data.id, props.data.jsId);
const kmMap: any = {};
const rows = (res && (res.rows || res.result || res.data)) || [];
dkList.value = rows.map((item: any) => {
item.dktime = item.dktime.split(" ")[0];
item.jcmc = jsTypeMc[item.jcType] + "第" + item.jc + "节";
const xq: number = item.xq - 1;
item.xqLabel = wdNameList.value[xq];
const js = jsList.find((js: any) => js.id === item.jsId);
if (js) {
item.dkJsId = js.id;
item.dkJsName = js.jsxm;
item.userId = js.userId;
}
dkList.value = newList.map((item: any) => {
kmMap[item.pkMc] = kmMap[item.pkMc] || {
pkMc: item.pkMc,
};
@ -312,8 +280,20 @@ const getDkList = () => {
return dkList.value;
};
//
const init = async () => {
//
await initDkList();
//
if (!dkList.value || !dkList.value.length && props.isEdit) {
await getPkkbList();
}
emit("inited", dkList.value);
};
//
defineExpose({
init,
getPkkbList,
validate,
getDkList,
@ -322,74 +302,170 @@ defineExpose({
</script>
<style lang="scss" scoped>
.dk-tabs {
flex: 1 0 1px;
}
.dk-card {
background-color: #ffffff;
border-radius: 8px;
margin-bottom: 15px;
box-shadow: 0 2px 6px rgba(0, 0, 0, 0.08);
overflow: hidden;
}
margin-bottom: 30rpx;
padding: 30rpx;
background: #fff;
border-radius: 16rpx;
box-shadow: 0 4rpx 16rpx rgba(0, 0, 0, 0.1);
.card-header {
padding: 12px 15px;
border-bottom: 1px solid #f0f0f0;
.applicant-name {
font-size: 16px;
.card-header {
font-size: 32rpx;
font-weight: bold;
margin-bottom: 30rpx;
color: #333;
}
}
border-bottom: 4rpx solid #007aff;
padding-bottom: 10rpx;
.card-body {
padding: 15px;
.info-row {
display: flex;
align-items: center;
margin-bottom: 10px;
&:last-child {
margin-bottom: 0;
}
.label {
font-size: 14px;
color: #666;
width: 70px;
flex-shrink: 0;
margin-right: 8px;
}
.value {
font-size: 14px;
.applicant-name {
font-size: 16px;
font-weight: bold;
color: #333;
flex: 1;
}
}
.card-body {
display: flex;
flex-direction: column;
padding: 20rpx;
border: 2rpx solid #eee;
border-radius: 8rpx;
margin-bottom: 20rpx;
.info-row {
display: flex;
.data {
align-items: center;
margin-bottom: 10px;
&:last-child {
margin-bottom: 0;
}
.label {
font-size: 14px;
color: #666;
width: 70px;
flex-shrink: 0;
margin-right: 8px;
}
.value {
font-size: 14px;
color: #333;
flex: 1;
display: flex;
.data {
flex: 1;
}
}
}
}
}
.card-footer {
padding: 12px 15px;
border-top: 1px solid #f0f0f0;
display: flex;
justify-content: space-between;
align-items: center;
font-size: 14px;
color: #888;
cursor: pointer;
.dk-edit {
.dk-tabs {
flex: 1 0 1px;
}
.arrow {
font-size: 16px;
color: #ccc;
.dk-card {
margin-bottom: 15px;
overflow: hidden;
box-shadow: none;
border: 1px solid rgba(0, 0, 0, 0.1);
.card-body {
margin-bottom: 0;
.info-row {
.label {
color: #666;
}
.value {
color: #333;
.data {
flex: 1;
}
}
}
}
&:last-child {
margin-bottom: 0;
}
}
}
.dk-info {
.dk-card {
margin: 15px;
.card-header {
position: relative;
.assigned-tag {
background-color: var(--primary-color, #1890ff);
color: white;
font-size: 12px;
padding: 5px 10px;
border-bottom-left-radius: 8px;
border-top-right-radius: 8px;
font-weight: normal;
position: absolute;
right: 0;
top: 0;
}
}
.card-body {
.info-row {
margin-bottom: 10px;
.label {
color: #999;
}
.value {
color: #333;
&.no-teacher {
color: #ff4757;
font-weight: 500;
}
}
}
.info-column {
display: flex;
flex-direction: column;
.label {
font-size: 14px;
color: #999;
flex-shrink: 0;
margin-right: 8px;
width: 100%;
margin-bottom: 5px;
}
.value {
font-size: 14px;
color: #333;
flex: 1;
}
}
}
}
.empty-dk {
margin: 15px;
background-color: #fff;
border-radius: 8px;
padding: 50px 15px;
box-shadow: 0 2px 6px rgba(0, 0, 0, 0.05);
text-align: center;
}
}
</style>

View File

@ -3,7 +3,9 @@
<view class="p-15">
<BasicForm @register="register">
<template #dkmx>
<JsQjDkEdit :data="formData" ref="dkRef" v-if="formData.dkfs === 0" />
<view class="mt-15" v-if="formData.dkfs === 0">
<JsQjDkEdit :data="formData" ref="dkRef" />
</view>
</template>
<template #spcs>
<BasicSpCsMgr
@ -34,6 +36,7 @@ import { showToast } from "@/utils/uniapp";
import dayjs from "dayjs";
import { useUserStore } from "@/store/modules/user";
import { useDicStore } from "@/store/modules/dic";
import { QjPageUtils } from "@/utils/qjPageUtils";
const { getJs, getUser } = useUserStore();
const { findByPid } = useDicStore();
@ -217,16 +220,29 @@ const submit = async () => {
return;
}
if (dkList.length) {
let emptyJsList:any = [];
params.dkList = dkList.map((item: any) => {
const newItem = {...item};
newItem.jsId = item.dkJsId || item.jsId;
newItem.jsName = item.dkJsName || item.jsName;
newItem.jsId = item.dkJsId;
newItem.jsName = item.dkJsName;
newItem.userId = item.dkUserId || item.userId;
newItem.pkkbId = item.id;
newItem.dktime = item.dktime + " 00:00:00";
newItem.id = "";
newItem.qjId = "";
if (!newItem.jsId) {
emptyJsList.push(item);
}
return newItem;
});
if (emptyJsList.length) {
const item = emptyJsList[0];
uni.showToast({
title: `请选择${item.dktime}${QjPageUtils.wdNameList[item.xq - 1]})的${item.jcmc}的代课教师`,
icon: "none",
});
return;
}
} else {
params.dkList = [];
}

View File

@ -1,5 +1,5 @@
<template>
<view class="leave-list">
<view class="qj-list">
<BasicListLayout @register="register" style="position: absolute;">
<template v-slot="{ data, index }">
<view class="leave-card" @click="goToDetail(data)">
@ -63,7 +63,7 @@ const goToDetail = (item: any | null) => {
</script>
<style lang="scss" scoped>
.leave-list {
.qj-list {
display: flex;
width: 100%;
height: 100%;

View File

@ -7,16 +7,13 @@
</view>
<!-- 代课信息 -->
<view>
<view v-if="!showDkFlag" class="empty-dk">
<view>{{ showDkEmptyLabel }}</view>
</view>
<JsQjDetailDk v-else :qjId="qjId" @loadDkList="handleDkListLoaded" />
<view v-if="qjData && qjData.dkfs === 0 || qjData.dkfs === 1">
<JsQjDkEdit :data="qjData" :is-edit="false" :is-detail="true" ref="dkRef" />
</view>
<!-- 审批流程 -->
<view class="mt-15">
<LcglSp :yw-id="qjId" yw-type="JS_QJ" />
<LcglSp :yw-id="qjId" yw-type="JS_QJ" :show-title="true" />
</view>
</view>
<template #bottom>
@ -33,7 +30,7 @@
import { useDataStore } from "@/store/modules/data";
import { ref } from "vue";
import JsQjDetailInfo from "./components/jsQjDetailInfo.vue";
import JsQjDetailDk from "./components/jsQjDetailDk.vue";
import JsQjDkEdit from "./components/jsQjDkEdit.vue";
import LcglSp from "@/components/LcglSp/index.vue";
import { onLoad } from "@dcloudio/uni-app";
import { QjPageUtils } from "@/utils/qjPageUtils";
@ -42,27 +39,21 @@ const { getQjData, setQjData, getXxts } = useDataStore();
const dbFlag = ref(false);
const qjId = ref('');
const showDkFlag = ref(false);
const showDkEmptyLabel = ref('');
const qjData = ref<any>({});
const dkRef = ref<any>(null);
const handleQjDataLoaded = (data: any) => {
data = data || {};
const dkfs = typeof (data.dkfs) === "string" ? parseInt(data.dkfs) : (data.dkfs || 2);
data.dkfs = dkfs;
setQjData(data);
qjData.value = data;
if (data.spResult && data.spResult != "A" && getXxts && getXxts.dbZt === "A") {
QjPageUtils.updateXxts();
}
const dkfs = typeof (data.dkfs) === "string" ? parseInt(data.dkfs) : (data.dkfs || 2);
const bpmStatus = typeof (data.bpmStatus) === "string" ? parseInt(data.bpmStatus) : (data.bpmStatus || 1);
showDkFlag.value = dkfs === 0 || (dkfs === 1 && bpmStatus > 4);
if (dkfs === 1) {
showDkEmptyLabel.value = "等待教科处协调";
} else if (dkfs === 2) {
showDkEmptyLabel.value = "无需代课";
}
};
const handleDkListLoaded = (list: any[]) => {
// JsQjDetail
nextTick(() => {
dkRef.value.init();
});
};
const goHome = () => {
@ -97,13 +88,4 @@ onLoad(async (data) => {
.qj-detail {
background-color: #f5f7fa;
}
.empty-dk {
margin: 15px;
background-color: #fff;
border-radius: 8px;
padding: 50px 15px;
box-shadow: 0 2px 6px rgba(0, 0, 0, 0.05);
text-align: center;
}
</style>

View File

@ -7,48 +7,17 @@
:dbFlag="dbFlag"
@loadQjData="handleQjDataLoaded"
/>
<!-- 代课信息 -->
<view class="dk-info">
<view class="section-title">
<text class="title-text">代课信息</text>
<view class="title-underline"></view>
</view>
<view v-if="!showDkFlag && !showPkkbFlag" class="empty-dk">
<view>{{ showDkEmptyLabel }}</view>
</view>
<view v-else-if="showPkkbFlag && !showDkFlag" class="pkkb-list">
<view v-for="(item, index) in pkkbList" :key="index" class="pkkb-card">
<view class="card-header">
<text class="applicant-name">{{ item.dktime }}{{ item.xqLabel }}{{ item.jcmc }}</text>
</view>
<view class="divider"></view>
<view class="card-body">
<view class="info-row">
<text class="label">排课名称:</text>
<text class="value">{{ item.pkMc }}</text>
</view>
<view class="info-row">
<text class="label">上课时间:</text>
<text class="value">{{ item.startTime }}-{{ item.endTime }}</text>
</view>
<view class="info-row">
<text class="label">代课老师:</text>
<text class="value no-teacher">没有选择代课老师</text>
</view>
</view>
</view>
</view>
<JsQjDetailDk v-else
:qjId="qjId"
@loadDkList="handleDkListLoaded"
/>
<view v-if="qjData && qjData.dkfs === 0 || qjData.dkfs === 1">
<JsQjDkEdit :data="qjData" :is-edit="false" ref="dkRef" @inited="handleDkInited" />
</view>
<!-- 审批流程 -->
<LcglSp :yw-id="qjId" yw-type="JS_QJ" />
<LcglSp :yw-id="qjId" yw-type="JS_QJ" :show-title="true" />
</view>
<template #bottom>
<YwConfirm
<YwConfirm v-if="initedFlag"
:spApi="jsQjSpApi"
:stopApi="jsQjStopApi"
:xtDkApi="jsQjXtApi"
@ -72,7 +41,7 @@ import { useUserStore } from "@/store/modules/user";
import { useDataStore } from "@/store/modules/data";
import { ref } from "vue";
import JsQjDetailInfo from "./components/jsQjDetailInfo.vue";
import JsQjDetailDk from "./components/jsQjDetailDk.vue";
import JsQjDkEdit from "./components/jsQjDkEdit.vue";
import YwConfirm from "@/pages/components/YwConfirm/index.vue";
import LcglSp from "@/components/LcglSp/index.vue";
import { QjPageUtils } from "@/utils/qjPageUtils";
@ -83,12 +52,11 @@ const { setQjData, getXxts } = useDataStore();
const dbFlag = ref(false);
const qjId = ref('');
const showDkFlag = ref(false);
const showDkEmptyLabel = ref('');
const showXtDkButton = ref(false);
const showApproveButton = ref(true);
const pkkbList = ref<any[]>([]);
const showPkkbFlag = ref(false);
const qjData = ref<any>({});
const dkRef = ref<any>(null);
const initedFlag = ref(false);
const spParams = computed(() => {
return {
@ -99,78 +67,30 @@ const spParams = computed(() => {
const handleQjDataLoaded = async (data: any) => {
data = data || {};
const dkfs = typeof (data.dkfs) === "string" ? parseInt(data.dkfs) : (data.dkfs || 2);
data.dkfs = dkfs;
qjData.value = data;
setQjData(data);
if (data.spResult && data.spResult != "A" && getXxts && getXxts.dbZt === "A") {
uni.reLaunch({ url: '/pages/base/js/qj/detail' });
QjPageUtils.updateXxts();
return;
}
const dkfs = typeof(data.dkfs) === "string" ? parseInt(data.dkfs) : (data.dkfs || 2);
showDkFlag.value = dkfs === 0;
//
await getPkkbData(data);
if (dkfs === 1) {
showDkEmptyLabel.value = "教科处协调,请点击协调代课按钮\n如无法协调,请点击转办按钮";
showXtDkButton.value = true; //
showApproveButton.value = false; //
} else if (dkfs === 2) {
showDkEmptyLabel.value = "无需代课";
showXtDkButton.value = false; //
showApproveButton.value = true; //
} else {
showXtDkButton.value = false; //
showApproveButton.value = true; //
nextTick(() => {
dkRef.value.init();
});
};
//
const handleDkInited = async (dkList: any) => {
if (dkList && dkList.length) {
showApproveButton.value = true;
showXtDkButton.value = false;
} else if (qjData.value.dkfs === 1) {
showApproveButton.value = false;
showXtDkButton.value = true;
}
};
const handleDkListLoaded = (list: any[]) => {
// JsQjDetail
};
//
const getPkkbData = async (data: any) => {
if (!data.qjkstime || !data.qjjstime) {
return;
}
try {
const res = await getPkkbByJsRangeTimeApi({
jsId: data.jsId,
startTime: data.qjkstime,
endTime: data.qjjstime,
});
if (res && res.result) {
pkkbList.value = res.result.map((item: any) => {
item.dktime = item.kbtime.split(" ")[0];
item.jcmc = getJcMc(item.jcType) + "第" + item.jc + "节";
const xq: number = item.xq - 1;
item.xqLabel = getWdName(xq);
return item;
});
showPkkbFlag.value = pkkbList.value.length > 0;
}
} catch (error) {
console.error("获取排课信息失败:", error);
}
};
//
const getJcMc = (jcType: string) => {
const jsTypeMc: any = {
ZAM: "早自习",
AM: "上午",
PM: "下午",
};
return jsTypeMc[jcType] || jcType;
};
//
const getWdName = (xq: number) => {
const wdNameList = ["周一", "周二", "周三", "周四", "周五", "周六", "周日"];
return wdNameList[xq] || "";
initedFlag.value = true;
};
onLoad(async (data?: any) => {
@ -180,6 +100,11 @@ onLoad(async (data?: any) => {
}
qjId.value = ret.qjId;
dbFlag.value = ret.dbFlag;
// 3
initedFlag.value = false;
setTimeout(() => {
initedFlag.value = true;
}, 3000);
});
</script>
@ -187,118 +112,4 @@ onLoad(async (data?: any) => {
.qj-detail {
background-color: #f5f7fa;
}
.dk-info {
margin: 15px;
background-color: #fff;
border-radius: 8px;
box-shadow: 0 2px 6px rgba(0, 0, 0, 0.05);
overflow: hidden;
.section-title {
padding: 15px 15px 0 15px;
margin-bottom: 0;
.title-text {
font-size: 16px;
font-weight: bold;
color: #333;
display: block;
margin-bottom: 8px;
}
.title-underline {
height: 2px;
background-color: #007aff;
width: 100%;
border-radius: 1px;
}
}
//
:deep(.dk-info) {
margin: 0;
background-color: transparent;
box-shadow: none;
}
:deep(.info-card) {
margin: 0;
border-radius: 0;
box-shadow: none;
border-bottom: 1px solid #f0f0f0;
&:last-child {
border-bottom: none;
}
}
}
.empty-dk {
background-color: #fff;
border-radius: 8px;
padding: 50px 15px;
box-shadow: 0 2px 6px rgba(0, 0, 0, 0.05);
text-align: center;
white-space: pre-line;
line-height: 1.6;
}
.pkkb-list {
.pkkb-card {
background-color: #fff;
border-radius: 8px;
margin-bottom: 15px;
box-shadow: 0 2px 6px rgba(0, 0, 0, 0.05);
overflow: hidden;
.card-header {
padding: 15px;
border-bottom: 1px solid #eee;
.applicant-name {
font-size: 16px;
font-weight: bold;
color: #333;
}
}
.divider {
height: 1px;
background-color: #eee;
}
.card-body {
padding: 15px;
.info-row {
display: flex;
margin-bottom: 10px;
&:last-child {
margin-bottom: 0;
}
.label {
font-size: 14px;
color: #999;
width: 70px;
flex-shrink: 0;
margin-right: 8px;
}
.value {
font-size: 14px;
color: #333;
flex: 1;
&.no-teacher {
color: #ff4757;
font-weight: 500;
}
}
}
}
}
}
</style>

View File

@ -1,83 +1,188 @@
import { xxtsFindByIdApi, xxtsSaveApi } from "@/api/base/xxtsApi";
import { useUserStore } from "@/store/modules/user";
import { useDataStore } from "@/store/modules/data";
import { useCommonStore } from "@/store/modules/common";
import { findDkPageApi, getPkkbByJsRangeTimeApi } from "@/api/base/jsQjApi";
const { loginByOpenId } = useUserStore();
const { getQjData, setXxts, setQjData, getXxts } = useDataStore();
const { getAllJsBasicInfoVo } = useCommonStore();
export const QjPageUtils = {
// 初始化校验
async init(data?: any) {
let ret = {
success: true,
dbFlag: false,
qjId: getQjData.id,
};
if (!data || !data.from || data.from != "db") {
return ret;
// 节数类型名称
const jsTypeMc:any = {
ZAM: "早自习",
AM: "上午",
PM: "下午",
};
// 周几名称
const wdNameList: any =[
"星期一",
"星期二",
"星期三",
"星期四",
"星期五",
"星期六",
"星期日",
];
// 确认状态
const qrStatus: any = {
"wait": "待确认",
"approved": "同意",
"rejected": "拒绝",
};
const init = async (data?: any) => {
let ret = {
success: true,
dbFlag: false,
qjId: getQjData.id,
};
if (!data || !data.from || data.from != "db") {
return ret;
}
// 从待办过来的,需要从后端获取数据
ret.dbFlag = true;
// 检查登录状态
const isLoggedIn = await loginByOpenId(data.openId);
if (!isLoggedIn) {
console.log("用户未登录,跳过处理");
ret.success = false;
return ret;
}
let url = "/pages/base/message/index";
try {
// 优先从后端根据url中的id去查询Xxts
const xxtsRes = await xxtsFindByIdApi({ id: data.id });
if (xxtsRes && xxtsRes.result) {
const xxts = xxtsRes.result;
setXxts(xxts);
ret.qjId = xxts.xxzbId;
// 检查待办状态
if (xxts.dbZt === "B") {
// 消息推送状态为B
setQjData({ id: xxts.xxzbId, from: "xxts-B" });
if (!data.detailFlag) {
url = "/pages/view/hr/jsQj/detail";
uni.reLaunch({ url });
ret.success = false;
} else {
ret.success = true;
}
}
} else {
uni.showToast({
title: "获取消息推送数据失败",
icon: "error",
});
uni.reLaunch({ url });
ret.success = false;
}
// 从待办过来的,需要从后端获取数据
ret.dbFlag = true;
// 检查登录状态
const isLoggedIn = await loginByOpenId(data.openId);
if (!isLoggedIn) {
console.log("用户未登录,跳过处理");
return ret;
} catch (error) {
console.error("获取待办信息失败", error);
// 如果获取Xxts失败回退到原来的逻辑
const xxtsData = getXxts;
if (xxtsData && xxtsData.dbZt === "B") {
setQjData({ id: data.id });
uni.reLaunch({ url });
ret.success = false;
return ret;
}
let url = "/pages/base/message/index";
try {
// 优先从后端根据url中的id去查询Xxts
const xxtsRes = await xxtsFindByIdApi({ id: data.id });
if (xxtsRes && xxtsRes.result) {
const xxts = xxtsRes.result;
setXxts(xxts);
ret.qjId = xxts.xxzbId;
// 检查待办状态
if (xxts.dbZt === "B") {
// 消息推送状态为B
setQjData({ id: xxts.xxzbId, from: "xxts-B" });
if (!data.detailFlag) {
url = "/pages/view/hr/jsQj/detail";
uni.reLaunch({ url });
ret.success = false;
} else {
ret.success = true;
}
}
} else {
uni.showToast({
title: "获取消息推送数据失败",
icon: "error",
});
uni.reLaunch({ url });
ret.success = false;
}
return ret;
} catch (error) {
console.error("获取待办信息失败", error);
// 如果获取Xxts失败回退到原来的逻辑
const xxtsData = getXxts;
if (xxtsData && xxtsData.dbZt === "B") {
setQjData({ id: data.id });
uni.reLaunch({ url });
ret.success = false;
return ret;
}
}
};
const updateXxts = async () => {
// 如果没有查询过消息推送,表示不是从待办进入的,不自动更新,
if (!getXxts || !getXxts.id) {
return false;
}
console.log("更新待办状态getXxts", getXxts);
// 更新待办状态
await xxtsSaveApi({
id: getXxts.id,
dbZt: "B",
});
return true;
};
const rebuildDkList = (list: any, jsId: string) => {
const newList = list.map((item: any) => {
const dktime = item.dktime || item.kbtime;
item.dktime = dktime.split(" ")[0];
item.jcmc = jsTypeMc[item.jcType] + "第" + item.jc + "节";
const xq: number = item.xq - 1;
item.xqLabel = wdNameList[xq];
item.statusLabel = qrStatus[item.qrStatus] || "未知";
return item;
});
// 排序,将当前教师作为代课教师的代课数据,排在前面,并且添加一个标记
return newList.sort((a: any, b: any) => {
if (a.jsId === jsId) {
return -1;
} else if (b.jsId === jsId) {
return 1;
} else {
return 0;
}
},
// 检查待办状态是否需要更新
async updateXxts() {
// 如果没有查询过消息推送,表示不是从待办进入的,不自动更新,
if (!getXxts || !getXxts.id) {
return false;
});
};
const getDkList = async (qjId: string, jsId: string) => {
const res: any = await findDkPageApi({
qjId: qjId,
page: 1,
rows: 1000,
});
const rows = (res && (res.rows || res.result || res.data)) || [];
if (!rows.length) {
return [];
}
const resJs = await getAllJsBasicInfoVo();
const jsList = resJs.result || [];
const newList = rebuildDkList(rows, jsId);
return newList.map((item: any) => {
const js = jsList.find((js: any) => js.id === item.jsId);
if (js) {
item.dkJsId = js.id;
item.dkJsName = js.jsxm;
item.userId = js.userId;
}
console.log("更新待办状态getXxts", getXxts);
// 更新待办状态
await xxtsSaveApi({
id: getXxts.id,
dbZt: "B",
return item;
});
};
// 获取排课信息
const getPkkbList = async (data: any) => {
if (!data.qjkstime || !data.qjjstime) {
return [];
}
try {
const res = await getPkkbByJsRangeTimeApi({
jsId: data.jsId,
startTime: data.qjkstime,
endTime: data.qjjstime,
});
return true;
},
}
const rows = (res && (res.rows || res.result)) || [];
return rebuildDkList(rows, data.jsId);
} catch (error) {
console.error("获取排课信息失败:", error);
return [];
}
};
// 导出
export const QjPageUtils = {
wdNameList,
// 初始化校验
init,
// 检查待办状态是否需要更新
updateXxts,
// 重构代课教师列表
rebuildDkList,
// 获取代课教师列表
getDkList,
// 获取排课信息
getPkkbList
};

View File

@ -62,6 +62,11 @@ export const interceptor = {
return JSON.parse(response.data);
}
if (response.data) {
if (response.data.resultCode === -9998) {
uni.reLaunch({
url: "/pages/system/login/login",
});
}
return response.data;
} else {
console.log("接口无返回值", response);