调整完善请假相关页面

This commit is contained in:
ywyonui 2025-07-27 23:37:02 +08:00
parent 2bf0fc57d8
commit d59489c4a5
8 changed files with 864 additions and 202 deletions

View File

@ -45,6 +45,13 @@ export const jsQjDkQrApi = async (params: any) => {
return await post("/api/jsQj/dk/qr", params); return await post("/api/jsQj/dk/qr", params);
}; };
/**
*
*/
export const jsQjZbApi = async (params: any) => {
return await post("/api/jsQj/zb", params);
};
/** /**
* *
*/ */
@ -86,4 +93,4 @@ export const findQjListApi = async (params: any) => {
*/ */
export const getQjActivitiHistoryApi = async (params: any) => { export const getQjActivitiHistoryApi = async (params: any) => {
return await get("/activiti/history/historicFlow", params); return await get("/activiti/history/historicFlow", params);
}; };

View File

@ -8,7 +8,9 @@
<view class="info-card"> <view class="info-card">
<view class="card-header"> <view class="card-header">
<text class="applicant-name" v-if="dbFlag">{{ qjData.dbZy }}</text> <text class="applicant-name" v-if="dbFlag">{{ qjData.dbZy }}</text>
<text class="applicant-name" v-else>教师{{ qjData.jsName }}的请假申请</text> <text class="applicant-name" v-else
>教师{{ qjData.jsName }}的请假申请</text
>
</view> </view>
<view class="divider"></view> <view class="divider"></view>
<view class="card-body"> <view class="card-body">
@ -32,9 +34,11 @@
<text class="label">请假事由:</text> <text class="label">请假事由:</text>
<text class="value">{{ qjData.qjsy }}</text> <text class="value">{{ qjData.qjsy }}</text>
</view> </view>
<view class="info-row" style="margin-bottom: 0;margin-top: 10px;"> <view class="info-row" style="margin-bottom: 0; margin-top: 10px">
<text class="label">代课方式:</text> <text class="label">代课方式:</text>
<text class="value">{{ dkfsList[qjData.dkfs] ? dkfsList[qjData.dkfs].text : "" }}</text> <text class="value">{{
dkfsList[qjData.dkfs] ? dkfsList[qjData.dkfs].text : ""
}}</text>
</view> </view>
</view> </view>
</view> </view>
@ -43,17 +47,18 @@
<view class="dk-title pl-15 pr-15"> <view class="dk-title pl-15 pr-15">
<BasicTitle line title="代课明细" :isBorder="false" /> <BasicTitle line title="代课明细" :isBorder="false" />
</view> </view>
<view > <view>
<view class="dk-card"> <view class="dk-card">
<view class="card-body"> <view class="card-body"> </view>
</view>
</view> </view>
</view> </view>
<!-- 请假信息卡片 --> <!-- 请假信息卡片 -->
<view class="info-card" v-for="(item, index) in dkList" :key="index"> <view class="info-card" v-for="(item, index) in dkList" :key="index">
<view class="card-header"> <view class="card-header">
<text class="applicant-name">{{ item.dktime }}{{ wdNameList[item.xq - 1] }}{{ item.jcmc }}</text> <text class="applicant-name"
>{{ item.dktime }}{{ item.xqLabel }}{{ item.jcmc }}</text
>
</view> </view>
<view class="divider"></view> <view class="divider"></view>
<view class="card-body"> <view class="card-body">
@ -78,28 +83,47 @@
</view> </view>
<ProgressList :procInstId="qjData.procInstId" /> <ProgressList :procInstId="qjData.procInstId" />
</view> </view>
</view> </view>
</template> </template>
<script setup lang="ts"> <script setup lang="ts">
import ProgressList from "./progressList.vue" import { findDkPageApi, findQjById } from "@/api/base/jsQjApi";
import { findQjById, findDkPageApi } from "@/api/base/jsQjApi";
import { useDataStore } from "@/store/modules/data"; import { useDataStore } from "@/store/modules/data";
import ProgressList from "./progressList.vue";
const { getDb } = useDataStore(); const { getDb } = useDataStore();
// //
const props = withDefaults(defineProps<{ const props = withDefaults(
qjId?: string, defineProps<{
dbFlag?: boolean qjId?: string;
}>(), { dbFlag?: boolean;
qjId: "", }>(),
dbFlag: false {
}); qjId: "",
dbFlag: false,
}
);
// emit
const emit = defineEmits(["loadQjData", "loadDkList"]);
//
const notifyParentLoaded = () => {
emit("loadQjData", qjData.value);
emit("loadDkList", dkList.value);
};
const qjData = ref<any>({}); const qjData = ref<any>({});
const wdNameList = ref<string[]>(["周一", "周二", "周三", "周四", "周五", "周六", "周日"]); const wdNameList = ref<string[]>([
"周一",
"周二",
"周三",
"周四",
"周五",
"周六",
"周日",
]);
const dkfsList = ref<any>([ const dkfsList = ref<any>([
{ value: 0, text: "自行协调" }, { value: 0, text: "自行协调" },
@ -108,22 +132,25 @@ const dkfsList = ref<any>([
]); ]);
const jsTypeMc: any = { const jsTypeMc: any = {
"ZAM": '早自习', ZAM: "早自习",
"AM": '上午', AM: "上午",
"PM": '下午', PM: "下午",
}; };
const dkList = ref<any>([]); const dkList = ref<any>([]);
watch(() => props.qjId, (newVal, oldVal) => { watch(
// () => props.qjId,
console.log('qjId changed:', newVal, oldVal); (newVal, oldVal) => {
if (newVal != oldVal && newVal) { //
init(); console.log("qjId changed:", newVal, oldVal);
if (newVal != oldVal && newVal) {
init();
}
} }
}); );
const init = async () => { const init = async () => {
{ {
const res = await findQjById({ id: props.qjId }); const res = await findQjById({ id: props.qjId });
qjData.value = res.result; qjData.value = res.result;
@ -133,22 +160,43 @@ const init = async () => {
return; return;
} }
{ {
const res:any = await findDkPageApi({ qjId: props.qjId, page: 1, rows: 1000 }); const res: any = await findDkPageApi({
qjId: props.qjId,
page: 1,
rows: 1000,
});
dkList.value = res.rows.map((item: any) => { dkList.value = res.rows.map((item: any) => {
item.dktime = item.dktime.split(" ")[0]; item.dktime = item.dktime.split(" ")[0];
item.jcmc = jsTypeMc[item.jcType] + "第" + item.jc + "节"; item.jcmc = jsTypeMc[item.jcType] + "第" + item.jc + "节";
const xq: number = item.xq - 1;
item.xqLabel = wdNameList.value[xq];
return item; return item;
}); });
} }
if (props.dbFlag) { if (props.dbFlag) {
qjData.value.dbZy = getDb.dbZy; qjData.value.dbZy = getDb.dbZy;
} }
notifyParentLoaded();
}; };
// //
onMounted(async () => { onMounted(async () => {
await init(); await init();
}); });
const getQjData = () => {
return qjData.value;
};
const getDkList = () => {
return dkList.value;
};
//
defineExpose({
getQjData,
getDkList,
});
</script> </script>
<style lang="scss" scoped> <style lang="scss" scoped>
@ -213,7 +261,7 @@ onMounted(async () => {
width: 100%; width: 100%;
margin-bottom: 5px; margin-bottom: 5px;
} }
.value { .value {
font-size: 14px; font-size: 14px;
color: #333; color: #333;
@ -221,7 +269,5 @@ onMounted(async () => {
} }
} }
} }
} }
</style> </style>

View File

@ -9,23 +9,34 @@
</view> </view>
</view> </view>
<view class="dk-tabs mb-10" v-if="dkList && dkList.length"> <view class="dk-tabs mb-10" v-if="dkList && dkList.length">
<BasicTabs class="type-tabs" <BasicTabs
ref="tabsRef" :list="tabList" bar-width="60px" scroll-count="4" class="type-tabs"
:current="curTabIndex" @change="switchTab" ref="tabsRef"
/> :list="tabList"
bar-width="60px"
scroll-count="4"
:current="curTabIndex"
@change="switchTab"
/>
<view class="dk-card" v-if="curTabIndex === 0"> <view class="dk-card" v-if="curTabIndex === 0">
<view class="card-body"> <view class="card-body">
<view class="info-row"> <view class="info-row">
<text class="label">代课老师:</text> <text class="label">代课老师:</text>
<view class="value"> <view class="value">
<JsPicker @change="changeJsByTy" :parent-data="tyDk" :defualtValue="tyDk.dkJsId" :multiple="false" :excludeIds="excludeIds" /> <JsPicker
@change="changeJsByTy"
:parent-data="tyDk"
:defualtValue="tyDk.dkJsId"
:multiple="false"
:excludeIds="excludeIds"
/>
</view> </view>
</view> </view>
</view> </view>
</view> </view>
<view v-if="curTabIndex === 1"> <view v-if="curTabIndex === 1">
<view v-for="(item, index) in kmDkList" :key="index"> <view v-for="(item, index) in kmDkList" :key="index">
<view class="dk-card" style="margin: 0;"> <view class="dk-card" style="margin: 0">
<view class="card-body"> <view class="card-body">
<view class="info-row"> <view class="info-row">
<text class="label">排课名称:</text> <text class="label">排课名称:</text>
@ -34,7 +45,13 @@
<view class="info-row"> <view class="info-row">
<text class="label">代课老师:</text> <text class="label">代课老师:</text>
<view class="value"> <view class="value">
<JsPicker @change="changeJsByKm" :parent-data="item" :defualtValue="item.dkJsId" :multiple="false" :excludeIds="excludeIds" /> <JsPicker
@change="changeJsByKm"
:parent-data="item"
:defualtValue="item.dkJsId"
:multiple="false"
:excludeIds="excludeIds"
/>
</view> </view>
</view> </view>
</view> </view>
@ -46,7 +63,11 @@
<view v-for="(item, index) in dkList" :key="index"> <view v-for="(item, index) in dkList" :key="index">
<view class="dk-card"> <view class="dk-card">
<view class="card-header"> <view class="card-header">
<text class="applicant-name">{{ item.dktime }}{{ wdNameList[item.xq - 1] }}{{ item.jcmc }}</text> <text class="applicant-name"
>{{ item.dktime }}{{ wdNameList[item.xq - 1] }}{{
item.jcmc
}}</text
>
</view> </view>
<view class="card-body"> <view class="card-body">
<view class="info-row"> <view class="info-row">
@ -60,7 +81,13 @@
<view class="info-row"> <view class="info-row">
<text class="label">代课老师:</text> <text class="label">代课老师:</text>
<view class="value" v-if="curTabIndex === 2"> <view class="value" v-if="curTabIndex === 2">
<JsPicker @change="changeJs" :parent-data="item" :defualtValue="item.dkJsId" :multiple="false" :excludeIds="excludeIds" /> <JsPicker
@change="changeJs"
:parent-data="item"
:defualtValue="item.dkJsId"
:multiple="false"
:excludeIds="excludeIds"
/>
</view> </view>
<view v-else>{{ item.dkJsName }}</view> <view v-else>{{ item.dkJsName }}</view>
</view> </view>
@ -68,31 +95,56 @@
</view> </view>
</view> </view>
</view> </view>
<view v-else class="p-15 flex-row-center color-9 font-13 white-bg-color">暂无数据</view> <view v-else class="p-15 flex-row-center color-9 font-13 white-bg-color"
>暂无数据</view
>
</view> </view>
</template> </template>
<script setup lang="ts"> <script setup lang="ts">
import JsPicker from "@/pages/components/JsPicker/index.vue";
import { getPkkbByJsRangeTimeApi } from "@/api/base/jsQjApi"; import { getPkkbByJsRangeTimeApi } from "@/api/base/jsQjApi";
import JsPicker from "@/pages/components/JsPicker/index.vue";
import { useUserStore } from "@/store/modules/user"; import { useUserStore } from "@/store/modules/user";
const { getJs } = useUserStore(); const { getJs } = useUserStore();
// //
const props = withDefaults(defineProps<{ const props = withDefaults(
data: any defineProps<{
}>(), { data: any;
data: () => ({ }>(),
jsId: "", {
qjkstime: "", // data: () => ({
qjjstime: "", // jsId: "",
}) qjkstime: "", //
}); qjjstime: "", //
}),
}
);
const wdNameList = ref<string[]>(["周一", "周二", "周三", "周四", "周五", "周六", "周日"]); const wdNameList = ref<string[]>([
"周一",
"周二",
"周三",
"周四",
"周五",
"周六",
"周日",
]);
const jsTypeMc: any = {
ZAM: "早自习",
AM: "上午",
PM: "下午",
};
// //
const excludeIds = ref<any>([getJs.id]); const excludeIds = ref<any>([]);
if (props.data && props.data.jsId && props.data.jsId.length) {
excludeIds.value.push(props.data.jsId);
} else {
excludeIds.value.push(getJs.id);
}
const tyDk = ref<any>({}); const tyDk = ref<any>({});
@ -108,14 +160,8 @@ const tabList = ref([
const curTabIndex = ref(0); const curTabIndex = ref(0);
const switchTab = (index : number) => { const switchTab = (index: number) => {
curTabIndex.value = index; curTabIndex.value = index;
}
const jsTypeMc: any = {
"ZAM": '早自习',
"AM": '上午',
"PM": '下午',
}; };
const getPkkbList = async () => { const getPkkbList = async () => {
@ -126,14 +172,14 @@ const getPkkbList = async () => {
}); });
// //
const srcData: any = {}; const srcData: any = {};
dkList.value.map((item: any) => { dkList.value.map((item: any) => {
const key = item.dktime + item.jcType + item.jc; const key = item.dktime + item.jcType + item.jc;
srcData[key] = { srcData[key] = {
dkJsId: item.dkJsId, dkJsId: item.dkJsId,
dkJsName: item.dkJsName dkJsName: item.dkJsName,
}; };
}); });
const kmMap:any = {}; const kmMap: any = {};
dkList.value = res.result.map((item: any) => { dkList.value = res.result.map((item: any) => {
item.dktime = item.kbtime.split(" ")[0]; item.dktime = item.kbtime.split(" ")[0];
item.njbjmx = item.bc + item.bjmc; item.njbjmx = item.bc + item.bjmc;
@ -155,7 +201,7 @@ const getPkkbList = async () => {
}); });
// kmMapvalue // kmMapvalue
kmDkList.value = Object.values(kmMap); kmDkList.value = Object.values(kmMap);
} };
const changeJsByTy = (selected: any, item: any) => { const changeJsByTy = (selected: any, item: any) => {
item.dkJsId = selected.value; item.dkJsId = selected.value;
@ -164,7 +210,7 @@ const changeJsByTy = (selected: any, item: any) => {
return { return {
...dk, ...dk,
dkJsId: item.dkJsId, dkJsId: item.dkJsId,
dkJsName: item.dkJsName dkJsName: item.dkJsName,
}; };
}); });
dkList.value = newList; dkList.value = newList;
@ -172,11 +218,11 @@ const changeJsByTy = (selected: any, item: any) => {
return { return {
...km, ...km,
dkJsId: item.dkJsId, dkJsId: item.dkJsId,
dkJsName: item.dkJsName dkJsName: item.dkJsName,
}; };
}); });
kmDkList.value = newKmList; kmDkList.value = newKmList;
} };
const changeJsByKm = (selected: any, item: any) => { const changeJsByKm = (selected: any, item: any) => {
item.dkJsId = selected.value; item.dkJsId = selected.value;
@ -189,14 +235,14 @@ const changeJsByKm = (selected: any, item: any) => {
return dk; return dk;
}); });
dkList.value = newList; dkList.value = newList;
} };
const changeJs = (selected: any, item: any) => { const changeJs = (selected: any, item: any) => {
item.dkJsId = selected.value; item.dkJsId = selected.value;
item.dkJsName = selected.label; item.dkJsName = selected.label;
} };
const validate = async () => { const validate = async () => {
// //
if (!dkList.value || !dkList.value.length) { if (!dkList.value || !dkList.value.length) {
await getPkkbList(); await getPkkbList();
@ -214,18 +260,18 @@ const validate = async () => {
} }
} }
return true; return true;
} };
// ref // ref
const getDkList = () => { const getDkList = () => {
return dkList.value; return dkList.value;
} };
// //
defineExpose({ defineExpose({
getPkkbList, getPkkbList,
validate, validate,
getDkList getDkList,
}); });
</script> </script>

View File

@ -5,11 +5,11 @@
</template> </template>
<script setup lang="ts"> <script setup lang="ts">
import JsQjEdit from "./components/jsQjEdit.vue" import { findQjById } from "@/api/base/jsQjApi";
import { findQjById } from '@/api/base/jsQjApi';
import { onLoad } from '@dcloudio/uni-app';
import { useDataStore } from "@/store/modules/data"; import { useDataStore } from "@/store/modules/data";
const { setData, getData } = useDataStore(); import { onLoad } from "@dcloudio/uni-app";
import JsQjEdit from "./components/jsQjEdit.vue";
const { setData, getData, getDb } = useDataStore();
const dbFlag = ref(false); const dbFlag = ref(false);
@ -19,6 +19,12 @@ onLoad(async (data: any) => {
// //
if (data && data.from && data.from == "db") { if (data && data.from && data.from == "db") {
dbFlag.value = true; dbFlag.value = true;
if (getDb.dbZt === "B") {
setData({ id: data.id });
let url = "/pages/view/hr/jsQj/detail"; // 使
uni.navigateTo({ url });
return;
}
const res = await findQjById({ id: data.id }); const res = await findQjById({ id: data.id });
nextTick(() => { nextTick(() => {
setData(res.result); setData(res.result);
@ -33,4 +39,4 @@ onLoad(async (data: any) => {
.leave-page { .leave-page {
height: 100vh; height: 100vh;
} }
</style> </style>

View File

@ -1,33 +1,289 @@
<template> <template>
<view class="leave-page"> <BasicLayout>
代课教师确认 <!-- 选项卡 -->
</view> <BasicTabs
class="leave-tabs"
ref="tabsRef"
:list="tabList"
bar-width="60px"
scroll-count="4"
:current="curTabIndex"
@change="switchTab"
/>
<view v-if="curTabIndex === 0">
<!-- 请假信息卡片 -->
<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
>
</view>
<view class="divider"></view>
<view class="card-body">
<view class="info-row">
<text class="label">排课名称:</text>
<text class="value">{{ item.pkName }}</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">{{ qjData.jsName }}</view>
</view>
</view>
</view>
</view>
<JsQjDetail
v-show="curTabIndex === 1"
:qjId="qjId"
:dbFlag="dbFlag"
v-if="qjId && qjId.length"
@loadQjData="loadQjData"
@loadDkList="loadDkList"
/>
<!-- 驳回弹窗 -->
<u-popup
:show="dlgFlag"
mode="center"
:closeOnClickOverlay="false"
@close="closeDlg"
>
<view class="popup-content">
<view class="popup-title">驳回原因</view>
<u-input
v-model="rejectReason"
type="textarea"
placeholder="请填写驳回原因"
:autoHeight="true"
maxlength="200"
/>
<view class="popup-actions flex-row justify-end mt-4">
<u-button class="mr-2" @click="closeDlg">取消</u-button>
<u-button type="primary" @click="handleReject">确定</u-button>
</view>
</view>
</u-popup>
<template #bottom>
<view class="white-bg-color py-5">
<view class="divider"></view>
<view class="flex-row items-center pb-10 pt-5">
<u-button
text="驳回"
class="ml-15 mr-7"
:plain="true"
@click="showDlg"
/>
<u-button
text="同意"
class="mr-15 mr-7"
type="primary"
@click="submit"
/>
</view>
</view>
</template>
</BasicLayout>
</template> </template>
<script setup lang="ts"> <script setup lang="ts">
import { findQjById } from '@/api/base/jsQjApi'; import { jsQjDkQrApi } from "@/api/base/jsQjApi";
import { onLoad } from '@dcloudio/uni-app';
import { useDataStore } from "@/store/modules/data"; import { useDataStore } from "@/store/modules/data";
const { setData } = useDataStore(); import { useUserStore } from "@/store/modules/user";
import { navigateBack } from "@/utils/uniapp";
import { onLoad } from "@dcloudio/uni-app";
import { ref } from "vue";
import JsQjDetail from "./components/jsQjDetail.vue";
const { getJs } = useUserStore();
const { setData, getData, getDb } = useDataStore();
const dkList = ref<any>([]);
const qjData = ref<any>({});
const dbFlag = ref(false); const dbFlag = ref(false);
const qjId = ref<string>();
const dkId = ref<string>();
const dlgFlag = ref(false);
const rejectReason = ref("");
const tabList = ref([
{ name: "当前代课", id: "dk-info" },
{ name: "请假信息", id: "qj-info" },
]);
const curTabIndex = ref(1);
const switchTab = (index: number) => {
curTabIndex.value = index;
};
const loadQjData = (data: any) => {
qjData.value = data;
};
const loadDkList = (data: any) => {
// dbGlId
if (!getDb.dbGlId) {
getDb.dbGlId = "";
}
const idArr = getDb.dbGlId.split(",");
dkList.value = [];
data.map((dk: any) => {
if (idArr.includes(String(dk.id))) {
dkList.value.push(dk);
}
});
switchTab(0);
};
const submit = async () => {
const params = {
qjId: qjId.value,
jsId: getJs.id,
qrStatus: 2,
qrYj: "同意",
};
uni.showLoading({ title: "确认代课中..." });
await jsQjDkQrApi(params);
uni.hideLoading();
navigateBack();
};
const showDlg = () => {
dlgFlag.value = true;
};
const closeDlg = () => {
dlgFlag.value = false;
};
//
const handleReject = async () => {
if (!rejectReason.value.trim()) {
uni.showToast({ title: "请填写驳回意见", icon: "none" });
return;
}
const params: any = {
qjId: qjId.value,
jsId: getJs.id,
qrStatus: 1, // 1
qrYj: rejectReason.value,
};
uni.showLoading({ title: "正在驳回..." });
try {
await jsQjDkQrApi(params);
uni.hideLoading();
uni.showToast({ title: "已驳回", icon: "success" });
closeDlg();
setTimeout(() => {
navigateBack();
}, 500);
} catch (e) {
uni.hideLoading();
}
};
onLoad(async (data: any) => { onLoad(async (data: any) => {
// //
if (data && data.from && data.from == "db") { if (data && data.from && data.from == "db") {
qjId.value = data.id;
dkId.value = data.dkId;
dbFlag.value = true; dbFlag.value = true;
const res = await findQjById({ id: data.id }); if (getDb.dbZt === "B") {
nextTick(() => { setData({ id: data.id });
setData(res.result); let url = "/pages/view/hr/jsQj/detail"; // 使
}); uni.navigateTo({ url });
return;
}
} else { } else {
qjId.value = getData.id;
dbFlag.value = false; dbFlag.value = false;
} }
}); });
</script> </script>
<style lang="scss" scoped> <style scoped>
.leave-page { .popup-content {
height: 100vh; width: 80vw;
background: #fff;
border-radius: 12px;
padding: 24px 16px 16px 16px;
} }
</style> .popup-title {
font-size: 16px;
font-weight: bold;
margin-bottom: 12px;
}
.popup-actions {
margin-top: 16px;
}
.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;
.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;
.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,21 +1,60 @@
<template> <template>
<BasicLayout> <BasicLayout>
<JsQjDetail :qjId="qjId" :dbFlag="dbFlag" v-if="qjId && qjId.length" /> <JsQjDetail :qjId="qjId" :dbFlag="dbFlag" v-if="qjId && qjId.length" />
<!-- 驳回弹窗 -->
<u-popup
:show="bhDlgFlag"
mode="center"
:closeOnClickOverlay="false"
@close="closeBhDlg"
>
<view class="popup-content">
<view class="popup-title">驳回原因</view>
<u-input
v-model="rejectReason"
type="textarea"
placeholder="请填写驳回原因"
:autoHeight="true"
maxlength="200"
/>
<view class="popup-actions flex-row justify-end mt-4">
<u-button class="mr-2" @click="closeBhDlg">取消</u-button>
<u-button type="primary" @click="handleReject">确定</u-button>
</view>
</view>
</u-popup>
<!-- 转办弹窗 -->
<u-popup
:show="zbDlgFlag"
mode="center"
:closeOnClickOverlay="false"
@close="closeZbDlg"
>
<view class="popup-content">
<view class="popup-title">转到教师</view>
<JsPicker
@change="changeZbJs"
:multiple="false"
:excludeIds="excludeIds"
/>
<!-- 这里可以扩展选择转办对象等内容 -->
<view class="popup-actions flex-row justify-end mt-4">
<u-button class="mr-2" @click="closeZbDlg">取消</u-button>
<u-button type="primary" @click="handleTransfer">确定</u-button>
</view>
</view>
</u-popup>
<template #bottom> <template #bottom>
<view class="white-bg-color py-5"> <view class="white-bg-color py-5">
<view class="divider"></view>
<view class="flex-row items-center pb-10 pt-5"> <view class="flex-row items-center pb-10 pt-5">
<u-button <u-button
text="驳回" text="驳回"
class="ml-15 mr-7" class="ml-15 mr-7"
:plain="true" :plain="true"
@click="navigateBack" @click="showBhDlg"
/>
<u-button
text="转办"
class="ml-7 mr-7"
:plain="true"
@click="navigateBack"
/> />
<u-button text="转办" class="mr-7" :plain="true" @click="showZbDlg" />
<u-button <u-button
text="同意" text="同意"
class="mr-15 mr-7" class="mr-15 mr-7"
@ -29,69 +68,148 @@
</template> </template>
<script setup lang="ts"> <script setup lang="ts">
import JsQjDetail from "./components/jsQjDetail.vue"; import { jsQjJwcQrApi, jsQjZbApi } from "@/api/base/jsQjApi";
import { onLoad } from "@dcloudio/uni-app"; import JsPicker from "@/pages/components/JsPicker/index.vue";
import { navigateBack } from "@/utils/uniapp";
import { useForm } from "@/components/BasicForm/hooks/useForm";
import { jsQjSpApi } from '@/api/base/jsQjApi';
import { useUserStore } from "@/store/modules/user";
import { useDataStore } from "@/store/modules/data"; import { useDataStore } from "@/store/modules/data";
import { useUserStore } from "@/store/modules/user";
import { navigateBack } from "@/utils/uniapp";
import { onLoad } from "@dcloudio/uni-app";
import { ref } from "vue";
import JsQjDetail from "./components/jsQjDetail.vue";
const { getJs } = useUserStore(); const { getJs } = useUserStore();
const { getData } = useDataStore(); const { setData, getData, getDb } = useDataStore();
const dbFlag = ref(false); const dbFlag = ref(false);
const qjId = ref<string>(); const qjId = ref<string>();
const [register, { getValue }] = useForm({ //
schema: [ const bhDlgFlag = ref(false);
{ const rejectReason = ref("");
field: "spStatus",
label: "审批意见",
component: "BasicCheckbox",
required: true,
componentProps: {
data: [
{ value: 2, text: "同意" },
{ value: 1, text: "拒绝" },
],
},
},
{
field: "spYj",
label: "审批说明",
component: "BasicInput",
required: true,
itemProps: {
labelPosition: "top",
},
componentProps: {
type: "textarea",
},
},
],
});
//
const zbDlgFlag = ref(false);
const excludeIds = ref<string[]>([getJs.id]);
const zbJs = ref<any>({});
//
const submit = async () => { const submit = async () => {
const data = await getValue(); const params = {
const params = { ...data }; qjId: qjId.value,
params.qjId = qjId.value; jsId: getJs.id,
params.jsId = getJs.id; qrStatus: 2,
qrYj: "同意",
};
uni.showLoading({ title: "审批中..." }); uni.showLoading({ title: "审批中..." });
await jsQjSpApi(params); await jsQjJwcQrApi(params);
uni.hideLoading(); uni.hideLoading();
navigateBack(); navigateBack();
}; };
// /
const showBhDlg = () => {
bhDlgFlag.value = true;
};
const closeBhDlg = () => {
bhDlgFlag.value = false;
};
// /
const showZbDlg = () => {
zbDlgFlag.value = true;
};
const closeZbDlg = () => {
zbDlgFlag.value = false;
};
const changeZbJs = (selected: any) => {
zbJs.value = selected;
};
//
const handleReject = async () => {
if (!rejectReason.value.trim()) {
uni.showToast({ title: "请填写驳回意见", icon: "none" });
return;
}
const params: any = {
qjId: qjId.value,
jsId: getJs.id,
spStatus: 1, // 1
spYj: rejectReason.value,
};
uni.showLoading({ title: "正在驳回..." });
try {
await jsQjJwcQrApi(params);
uni.hideLoading();
uni.showToast({ title: "已驳回", icon: "success" });
closeBhDlg();
setTimeout(() => {
navigateBack();
}, 500);
} catch (e) {
uni.hideLoading();
}
};
//
const handleTransfer = async () => {
if (!zbJs.value || !zbJs.value.value) {
uni.showToast({ title: "请填写转办教师", icon: "none" });
return;
}
const params: any = {
qjId: qjId.value,
jsId: getJs.id,
dbId: getDb.id,
zbJsId: zbJs.value.value,
zbJsxm: zbJs.value.label,
};
uni.showLoading({ title: "正在转办..." });
try {
await jsQjZbApi(params);
uni.hideLoading();
uni.showToast({ title: "已转办", icon: "success" });
closeBhDlg();
setTimeout(() => {
navigateBack();
}, 500);
} catch (e) {
uni.hideLoading();
}
};
onLoad(async (data: any) => { onLoad(async (data: any) => {
// //
if (data && data.from && data.from == "db") { if (data && data.from && data.from == "db") {
qjId.value = data.id; qjId.value = data.id;
dbFlag.value = true; dbFlag.value = true;
if (getDb.dbZt === "B") {
setData({ id: data.id });
let url = "/pages/view/hr/jsQj/detail"; // 使
uni.navigateTo({ url });
return;
}
} else { } else {
qjId.value = getData.id; qjId.value = getData.id;
dbFlag.value = false; dbFlag.value = false;
} }
}); });
</script> </script>
<style scoped>
.popup-content {
width: 80vw;
background: #fff;
border-radius: 12px;
padding: 24px 16px 16px 16px;
}
.popup-title {
font-size: 16px;
font-weight: bold;
margin-bottom: 12px;
}
.popup-actions {
margin-top: 16px;
}
</style>

View File

@ -1,33 +1,162 @@
<template> <template>
<view class="leave-page"> <BasicLayout>
教务处协调 <!-- 选项卡 -->
</view> <BasicTabs
class="leave-tabs"
ref="tabsRef"
:list="tabList"
bar-width="60px"
scroll-count="4"
:current="curTabIndex"
@change="switchTab"
/>
<view class="pl-15 pr-15" v-show="curTabIndex === 0">
<JsQjDkEdit
:data="formData"
ref="dkRef"
v-if="formData && formData.dkfs === '1'"
/>
</view>
<JsQjDetail
v-show="curTabIndex === 1"
:qjId="qjId"
:dbFlag="dbFlag"
v-if="qjId && qjId.length"
@loadQjData="loadQjData"
/>
<template #bottom>
<view class="white-bg-color py-5">
<view class="divider"></view>
<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> </template>
<script setup lang="ts"> <script setup lang="ts">
import { findQjById } from '@/api/base/jsQjApi'; import { jsQjJwcXtApi } from "@/api/base/jsQjApi";
import { onLoad } from '@dcloudio/uni-app';
import { useDataStore } from "@/store/modules/data"; import { useDataStore } from "@/store/modules/data";
const { setData } = useDataStore(); import { useUserStore } from "@/store/modules/user";
import { navigateBack, showToast } from "@/utils/uniapp";
import { onLoad } from "@dcloudio/uni-app";
import { ref } from "vue";
import JsQjDetail from "./components/jsQjDetail.vue";
import JsQjDkEdit from "./components/jsQjDkEdit.vue";
const { getJs } = useUserStore();
const { setData, getData, getDb } = useDataStore();
const dkRef = ref<any>(null);
const formData = ref<any>({});
const dbFlag = ref(false); const dbFlag = ref(false);
const qjId = ref<string>();
const tabList = ref([
{ name: "代课协调", id: "dk-edit" },
{ name: "请假信息", id: "qj-info" },
]);
const curTabIndex = ref(1);
let initDkTabFlag = false;
const switchTab = (index: number) => {
curTabIndex.value = index;
if (index === 0 && !initDkTabFlag) {
nextTick(() => {
dkRef.value.getPkkbList();
initDkTabFlag = true;
});
}
};
const loadQjData = (data: any) => {
formData.value = data;
switchTab(0);
};
const submit = async () => {
const params = {
qjId: qjId.value,
jsId: getJs.id,
dkList: [],
};
const flag = await dkRef.value.validate();
if (!flag) {
uni.showToast({
title: "请选择代课教师",
icon: "none",
});
return;
}
let dkList = dkRef.value.getDkList() || [];
if (dkList.length) {
params.dkList = dkList.map((item: any) => {
const newItem = { ...item };
newItem.jsId = item.dkJsId;
newItem.jsName = item.dkJsName;
newItem.pkkbId = item.id;
newItem.dktime = item.dktime + " 00:00:00";
newItem.id = "";
newItem.qjId = "";
return newItem;
});
}
uni.showLoading({ title: "提交中..." });
await jsQjJwcXtApi(params).then(() => {
showToast({ title: "提交成功", icon: "success" });
uni.reLaunch({
url: "/pages/base/service/index",
});
});
uni.hideLoading();
};
onLoad(async (data: any) => { onLoad(async (data: any) => {
// //
if (data && data.from && data.from == "db") { if (data && data.from && data.from == "db") {
qjId.value = data.id;
dbFlag.value = true; dbFlag.value = true;
const res = await findQjById({ id: data.id }); if (getDb.dbZt === "B") {
nextTick(() => { setData({ id: data.id });
setData(res.result); let url = "/pages/view/hr/jsQj/detail"; // 使
}); uni.navigateTo({ url });
return;
}
} else { } else {
qjId.value = getData.id;
dbFlag.value = false; dbFlag.value = false;
} }
}); });
</script> </script>
<style lang="scss" scoped> <style scoped>
.leave-page { .popup-content {
height: 100vh; width: 80vw;
background: #fff;
border-radius: 12px;
padding: 24px 16px 16px 16px;
} }
</style> .popup-title {
font-size: 16px;
font-weight: bold;
margin-bottom: 12px;
}
.popup-actions {
margin-top: 16px;
}
</style>

View File

@ -1,18 +1,40 @@
<template> <template>
<BasicLayout> <BasicLayout>
<JsQjDetail :qjId="qjId" :dbFlag="dbFlag" v-if="qjId && qjId.length" /> <JsQjDetail :qjId="qjId" :dbFlag="dbFlag" v-if="qjId && qjId.length" />
<!-- 驳回弹窗 -->
<u-popup
:show="dlgFlag"
mode="center"
:closeOnClickOverlay="false"
@close="closeDlg"
>
<view class="popup-content">
<view class="popup-title">驳回原因</view>
<u-input
v-model="rejectReason"
type="textarea"
placeholder="请填写驳回原因"
:autoHeight="true"
maxlength="200"
/>
<view class="popup-actions flex-row justify-end mt-4">
<u-button class="mr-2" @click="closeDlg">取消</u-button>
<u-button type="primary" @click="handleReject">确定</u-button>
</view>
</view>
</u-popup>
<template #bottom> <template #bottom>
<view class="white-bg-color py-5"> <view class="white-bg-color py-5">
<view class="divider"></view> <view class="divider"></view>
<view class="flex-row items-center pb-10 pt-5"> <view class="flex-row items-center pb-10 pt-5">
<u-button <u-button
text="取消" text="驳回"
class="ml-15 mr-7" class="ml-15 mr-7"
:plain="true" :plain="true"
@click="navigateBack" @click="showDlg"
/> />
<u-button <u-button
text="提交" text="同意"
class="mr-15 mr-7" class="mr-15 mr-7"
type="primary" type="primary"
@click="submit" @click="submit"
@ -24,69 +46,101 @@
</template> </template>
<script setup lang="ts"> <script setup lang="ts">
import JsQjDetail from "./components/jsQjDetail.vue"; import { jsQjSpApi } from "@/api/base/jsQjApi";
import { onLoad } from "@dcloudio/uni-app";
import { navigateBack } from "@/utils/uniapp";
import { useForm } from "@/components/BasicForm/hooks/useForm";
import { jsQjSpApi } from '@/api/base/jsQjApi';
import { useUserStore } from "@/store/modules/user";
import { useDataStore } from "@/store/modules/data"; import { useDataStore } from "@/store/modules/data";
import { useUserStore } from "@/store/modules/user";
import { navigateBack } from "@/utils/uniapp";
import { onLoad } from "@dcloudio/uni-app";
import { ref } from "vue";
import JsQjDetail from "./components/jsQjDetail.vue";
const { getJs } = useUserStore(); const { getJs } = useUserStore();
const { getData } = useDataStore(); const { setData, getData, getDb } = useDataStore();
const dbFlag = ref(false); const dbFlag = ref(false);
const qjId = ref<string>(); const qjId = ref<string>();
const [register, { getValue }] = useForm({ const dlgFlag = ref(false);
schema: [ const rejectReason = ref("");
{
field: "spStatus",
label: "审批意见",
component: "BasicCheckbox",
required: true,
componentProps: {
data: [
{ value: 2, text: "同意" },
{ value: 1, text: "拒绝" },
],
},
},
{
field: "spYj",
label: "审批说明",
component: "BasicInput",
required: true,
itemProps: {
labelPosition: "top",
},
componentProps: {
type: "textarea",
},
},
],
});
const submit = async () => { const submit = async () => {
const data = await getValue(); const params = {
const params = { ...data }; qjId: qjId.value,
params.qjId = qjId.value; jsId: getJs.id,
params.jsId = getJs.id; spStatus: 2,
spYj: "同意",
};
uni.showLoading({ title: "审批中..." }); uni.showLoading({ title: "审批中..." });
await jsQjSpApi(params); await jsQjSpApi(params);
uni.hideLoading(); uni.hideLoading();
navigateBack(); navigateBack();
}; };
const showDlg = () => {
dlgFlag.value = true;
};
const closeDlg = () => {
dlgFlag.value = false;
};
//
const handleReject = async () => {
if (!rejectReason.value.trim()) {
uni.showToast({ title: "请填写驳回意见", icon: "none" });
return;
}
const params: any = {
qjId: qjId.value,
jsId: getJs.id,
spStatus: 1, // 1
spYj: rejectReason.value,
};
uni.showLoading({ title: "正在驳回..." });
try {
await jsQjSpApi(params);
uni.hideLoading();
uni.showToast({ title: "已驳回", icon: "success" });
closeDlg();
setTimeout(() => {
navigateBack();
}, 500);
} catch (e) {
uni.hideLoading();
}
};
onLoad(async (data: any) => { onLoad(async (data: any) => {
// //
if (data && data.from && data.from == "db") { if (data && data.from && data.from == "db") {
qjId.value = data.id; qjId.value = data.id;
dbFlag.value = true; dbFlag.value = true;
if (getDb.dbZt === "B") {
setData({ id: data.id });
let url = "/pages/view/hr/jsQj/detail"; // 使
uni.navigateTo({ url });
return;
}
} else { } else {
qjId.value = getData.id; qjId.value = getData.id;
dbFlag.value = false; dbFlag.value = false;
} }
}); });
</script> </script>
<style scoped>
.popup-content {
width: 80vw;
background: #fff;
border-radius: 12px;
padding: 24px 16px 16px 16px;
}
.popup-title {
font-size: 16px;
font-weight: bold;
margin-bottom: 12px;
}
.popup-actions {
margin-top: 16px;
}
</style>