调整教师请假的处理逻辑

This commit is contained in:
ywyonui 2025-09-22 18:11:59 +08:00
parent 4648a0793a
commit cf832cc3d3
17 changed files with 729 additions and 371 deletions

View File

@ -91,13 +91,6 @@ export const findQjListApi = async (params: any) => {
return await get("/api/jsQj/findPage", params); return await get("/api/jsQj/findPage", params);
}; };
/**
* ID获取默认审批人和抄送人
*/
export const getApproversByRuleId = async (ruleId: string) => {
return await get("/api/jsQj/getApproversByRuleId", { ruleId });
};
/** /**
* ID获取请假详情 * ID获取请假详情
*/ */

View File

@ -2,6 +2,14 @@ import { get, post } from "@/utils/request";
// 流程审批相关API接口 // 流程审批相关API接口
/**
* ID获取默认审批人和抄送人
*/
export const getSprAndCsrByRuleId = async (ruleId: string) => {
return await get("/api/lcglSet/getSprAndCsrByRuleId", { ruleId });
};
/** /**
* ID和业务类型获取审批流程 * ID和业务类型获取审批流程
* @param ywId ID * @param ywId ID

View File

@ -3,19 +3,11 @@
<!-- 审批人列表 --> <!-- 审批人列表 -->
<view class="section"> <view class="section">
<view class="section-header"> <view class="section-header">
<text class="section-title">审批人</text> <text class="section-title">审批人{{ approvers.length || 0 }}</text>
<!-- 审批人选择器 --> <!-- 审批人选择器 -->
<BasicJsPicker <BasicJsPicker ref="approverPickerRef" :customTrigger="true" :multiple="true"
ref="approverPickerRef" :excludeIds="getExcludeApproverIds()" :defaultValue="[]" title="选择审批人" placeholder="请选择审批人"
:customTrigger="true" searchPlaceholder="搜索审批人" @change="handleApproverChange">
:multiple="true"
:excludeIds="getExcludeApproverIds()"
:defaultValue="[]"
title="选择审批人"
placeholder="请选择审批人"
searchPlaceholder="搜索审批人"
@change="handleApproverChange"
>
<template #trigger> <template #trigger>
<view class="add-btn"> <view class="add-btn">
<text class="add-icon">+</text> <text class="add-icon">+</text>
@ -30,35 +22,18 @@
<view class="item-info"> <view class="item-info">
<text class="item-name">{{ spr.jsxm }}</text> <text class="item-name">{{ spr.jsxm }}</text>
</view> </view>
<view class="item-actions"> <view class="item-actions" v-if="!spr.fixed">
<!-- 上移箭头 --> <!-- 上移箭头 -->
<uni-icons <uni-icons v-if="index > configSprList.length" type="top" size="18" color="#666" @click="moveApproverUp(index)"
v-if="index > 0" class="action-icon"></uni-icons>
type="top"
size="18"
color="#666"
@click="moveApproverUp(index)"
class="action-icon"
></uni-icons>
<!-- 下移箭头 --> <!-- 下移箭头 -->
<uni-icons <uni-icons v-if="index < approvers.length - 1" type="bottom" size="18" color="#666"
v-if="index < approvers.length - 1" @click="moveApproverDown(index)" class="action-icon"></uni-icons>
type="bottom"
size="18"
color="#666"
@click="moveApproverDown(index)"
class="action-icon"
></uni-icons>
<!-- 删除图标改为垃圾桶图标 --> <!-- 删除图标改为垃圾桶图标 -->
<uni-icons <uni-icons type="trash" size="18" color="#666" @click="removeApprover(index)"
type="trash" class="action-icon"></uni-icons>
size="18"
color="#666"
@click="removeApprover(index)"
class="action-icon"
></uni-icons>
</view> </view>
</view> </view>
@ -71,19 +46,10 @@
<!-- 抄送人列表 --> <!-- 抄送人列表 -->
<view class="section"> <view class="section">
<view class="section-header"> <view class="section-header">
<text class="section-title">抄送人</text> <text class="section-title">抄送人{{ ccList.length || 0 }}</text>
<!-- 抄送人选择器 --> <!-- 抄送人选择器 -->
<BasicJsPicker <BasicJsPicker ref="ccPickerRef" :customTrigger="true" :multiple="true" :excludeIds="getExcludeCcIds()"
ref="ccPickerRef" :defaultValue="[]" title="选择抄送人" placeholder="请选择抄送人" searchPlaceholder="搜索抄送人" @change="handleCcChange">
:customTrigger="true"
:multiple="true"
:excludeIds="getExcludeCcIds()"
:defaultValue="[]"
title="选择抄送人"
placeholder="请选择抄送人"
searchPlaceholder="搜索抄送人"
@change="handleCcChange"
>
<template #trigger> <template #trigger>
<view class="add-btn"> <view class="add-btn">
<text class="add-icon">+</text> <text class="add-icon">+</text>
@ -94,15 +60,21 @@
</view> </view>
<view class="list-content"> <view class="list-content">
<view v-for="(csr, index) in ccList" :key="csr.id" class="list-item"> <view v-for="(csr, index) in displayedCsrList" :key="csr.id" class="list-item">
<view class="item-info"> <view class="item-info">
<text class="item-name">{{ csr.jsxm }}</text> <text class="item-name">{{ csr.jsxm }}</text>
</view> </view>
<view class="item-actions"> <view class="item-actions" v-if="!csr.fixed">
<text class="delete-btn" @click="removeCc(index)">删除</text> <text class="delete-btn" @click="removeCc(index)">删除</text>
</view> </view>
</view> </view>
<!-- 更多按钮 -->
<view v-if="ccList.length > 2" class="more-button" @click="toggleCsrExpanded">
<text class="more-text">
{{ csrExpanded ? '收起' : `更多(${ccList.length - 2})` }}
</text>
<text class="more-icon" :class="{ expanded: csrExpanded }"></text>
</view>
<view v-if="ccList.length === 0" class="empty-tip"> <view v-if="ccList.length === 0" class="empty-tip">
<text>暂无抄送人请添加</text> <text>暂无抄送人请添加</text>
</view> </view>
@ -113,14 +85,10 @@
<script lang="ts" setup> <script lang="ts" setup>
import { ref, watch, onMounted } from "vue"; import { ref, watch, onMounted } from "vue";
import { getApproversByRuleId } from "@/api/base/jsQjApi"; import { getSprAndCsrByRuleId, getByYwIdAndYwTypeApi } from "@/api/base/lcglSpApi";
import { getByYwIdAndYwTypeApi } from "@/api/base/lcglSpApi";
import { useCommonStore } from "@/store/modules/common"; import { useCommonStore } from "@/store/modules/common";
import BasicJsPicker from "@/components/BasicJsPicker/Picker.vue"; import BasicJsPicker from "@/components/BasicJsPicker/Picker.vue";
// uni
declare const uni: any;
// JsVo // JsVo
interface JsInfo { interface JsInfo {
id: string; id: string;
@ -130,27 +98,43 @@ interface JsInfo {
headPic?: string; headPic?: string;
userId?: number; userId?: number;
deptId?: string; deptId?: string;
fixed?: boolean; //
} }
// //
const normalizeTeacherData = (item: any): JsInfo => { const normalizeTeacherData = (item: any, fixed: boolean): JsInfo => {
return { return {
id: item.id || item.value, id: item.userId || item.id || item.value,
jsxm: item.jsxm || item.label, jsxm: item.userName || item.jsxm || item.label,
lxdh: item.lxdh, lxdh: item.lxdh,
sfzh: item.sfzh, sfzh: item.sfzh,
headPic: item.headPic, headPic: item.headPic,
userId: item.userId, userId: item.userId,
deptId: item.deptId, deptId: item.deptId,
fixed: fixed,
}; };
}; };
// ID
const uniqueById = (array: any[]) => {
return array.filter((item, index, self) =>
index === self.findIndex(t => t.id === item.id)
);
};
// userId
const uniqueByUserId = (array: any[]) => {
return array.filter((item, index, self) =>
index === self.findIndex(t => t.userId === item.userId)
);
};
// //
const props = withDefaults( const props = withDefaults(
defineProps<{ defineProps<{
defaultValue?: any; defaultValue?: any;
ruleId?: string; ruleId?: string;
qjId?: string; // ID ywId?: string; // ID
}>(), }>(),
{ {
defaultValue: () => ({ defaultValue: () => ({
@ -158,7 +142,7 @@ const props = withDefaults(
csrList: [], csrList: [],
}), }),
ruleId: "", ruleId: "",
qjId: "", ywId: "",
} }
); );
@ -169,6 +153,26 @@ const emit = defineEmits(["change"]);
const approvers = ref<JsInfo[]>([]); const approvers = ref<JsInfo[]>([]);
const ccList = ref<JsInfo[]>([]); const ccList = ref<JsInfo[]>([]);
//
const configSprList = ref<any>([]);
const configCsrList = ref<any>([]);
//
const csrExpanded = ref(false);
//
const displayedCsrList = computed(() => {
if (csrExpanded.value || ccList.value.length <= 2) {
return ccList.value;
}
return ccList.value.slice(0, 2);
});
//
const toggleCsrExpanded = () => {
csrExpanded.value = !csrExpanded.value;
};
// //
const approverPickerRef = ref(); const approverPickerRef = ref();
const ccPickerRef = ref(); const ccPickerRef = ref();
@ -176,65 +180,17 @@ const ccPickerRef = ref();
// common store // common store
const commonStore = useCommonStore(); const commonStore = useCommonStore();
//
const initData = () => {
if (props.defaultValue) {
if (
props.defaultValue.sprList &&
Array.isArray(props.defaultValue.sprList)
) {
// 使
approvers.value = props.defaultValue.sprList.map(normalizeTeacherData);
}
if (
props.defaultValue.csrList &&
Array.isArray(props.defaultValue.csrList)
) {
// 使
ccList.value = props.defaultValue.csrList.map(normalizeTeacherData);
}
}
};
//
watch(
() => props.defaultValue,
() => {
initData();
},
{ immediate: true, deep: true }
);
//
const loadDefaultApprovers = async () => {
try {
// IDLcglSp
if (props.qjId) {
await loadExistingApprovers();
} else if (props.ruleId) {
// LcglSet
await loadDefaultFromLcglSet();
}
} catch (error) {
console.error("获取默认审批人失败:", error);
uni.showToast({
title: "获取默认审批人失败",
icon: "none",
});
}
};
// LcglSp使 // LcglSp使
const loadExistingApprovers = async () => { const loadExistingApprovers = async () => {
try { try {
const response = await getByYwIdAndYwTypeApi(props.qjId, "JS_QJ"); const response = await getByYwIdAndYwTypeApi(props.ywId, "JS_QJ");
if ( if (
response && response &&
response.resultCode === 1 && response.resultCode === 1 &&
response.result && response.result &&
Array.isArray(response.result) Array.isArray(response.result)
) { ) {
const spList = response.result; let spList = response.result;
// //
let approverList: any = []; let approverList: any = [];
@ -250,14 +206,27 @@ const loadExistingApprovers = async () => {
} }
} }
} }
// userId
approverList = uniqueByUserId(approverList);
ccListData = uniqueByUserId(ccListData);
let changeFlag = false; let changeFlag = false;
// 使 // 使
if (approvers.value.length === 0 && approverList.length > 0) { if (approvers.value.length === 0 && approverList.length > 0) {
approvers.value = approverList.map(normalizeTeacherData); approvers.value = approverList.map((item:any) => {
// config
const f = configSprList.value.filter((config:any) => config.userId === item.userId);
return normalizeTeacherData(item, f && f.length > 0);
});
changeFlag = true; changeFlag = true;
} }
if (ccList.value.length === 0 && ccListData.length > 0) { if (ccList.value.length === 0 && ccListData.length > 0) {
ccList.value = ccListData.map(normalizeTeacherData); ccList.value = ccListData.map((item:any) => {
// config
const f = configCsrList.value.filter((config:any) => config.userId === item.userId);
return normalizeTeacherData(item, f && f.length > 0);
});
changeFlag = true; changeFlag = true;
} }
if (changeFlag) { if (changeFlag) {
@ -272,30 +241,11 @@ const loadExistingApprovers = async () => {
// LcglSet // LcglSet
const loadDefaultFromLcglSet = async () => { const loadDefaultFromLcglSet = async () => {
try { try {
const response = await getApproversByRuleId(props.ruleId); const response = await getSprAndCsrByRuleId(props.ruleId);
if (response && response.resultCode === 1 && response.result) { if (response && response.resultCode === 1 && response.result) {
const data = response.result; const data = response.result;
let changeFlag = false; configSprList.value = data.sprList;
// 使 configCsrList.value = data.csrList;
if (
approvers.value.length === 0 &&
data.approvers &&
Array.isArray(data.approvers)
) {
approvers.value = data.approvers.map(normalizeTeacherData);
changeFlag = true;
}
if (
ccList.value.length === 0 &&
data.ccList &&
Array.isArray(data.ccList)
) {
ccList.value = data.ccList.map(normalizeTeacherData);
changeFlag = true;
}
if (changeFlag) {
notifyChange();
}
} }
} catch (error) { } catch (error) {
console.error("获取默认审批人失败:", error); console.error("获取默认审批人失败:", error);
@ -336,8 +286,16 @@ const moveApproverDown = (index: number) => {
const handleApproverChange = (selectedTeachers: any[]) => { const handleApproverChange = (selectedTeachers: any[]) => {
if (Array.isArray(selectedTeachers)) { if (Array.isArray(selectedTeachers)) {
// 使 // 使
const normalizedTeachers = selectedTeachers.map(normalizeTeacherData); const normalizedTeachers = selectedTeachers.map((item:any) => {
// config
const f = configSprList.value.filter((config:any) => config.userId === item.userId);
return normalizeTeacherData(item, f && f.length > 0);
});
approvers.value.push(...normalizedTeachers); approvers.value.push(...normalizedTeachers);
// ID
approvers.value = uniqueById(approvers.value);
notifyChange(); notifyChange();
uni.showToast({ uni.showToast({
title: "审批人设置成功", title: "审批人设置成功",
@ -350,8 +308,16 @@ const handleApproverChange = (selectedTeachers: any[]) => {
const handleCcChange = (selectedTeachers: any[]) => { const handleCcChange = (selectedTeachers: any[]) => {
if (Array.isArray(selectedTeachers)) { if (Array.isArray(selectedTeachers)) {
// 使 // 使
const normalizedTeachers = selectedTeachers.map(normalizeTeacherData); const normalizedTeachers = selectedTeachers.map((item:any) => {
// config
const f = configCsrList.value.filter((config:any) => config.userId === item.userId);
return normalizeTeacherData(item, f && f.length > 0);
});
ccList.value.push(...normalizedTeachers); ccList.value.push(...normalizedTeachers);
// ID
ccList.value = uniqueById(ccList.value);
notifyChange(); notifyChange();
uni.showToast({ uni.showToast({
title: "抄送人设置成功", title: "抄送人设置成功",
@ -409,11 +375,19 @@ const getExcludeCcIds = () => {
// //
onMounted(async () => { onMounted(async () => {
try { try {
initData();
await loadDefaultApprovers();
// //
await commonStore.getAllJsBasicInfoVo(); await commonStore.getAllJsBasicInfoVo();
//
await loadDefaultFromLcglSet();
//
if (!props.ywId) {
approvers.value = configSprList.value.map((item:any) => normalizeTeacherData(item, true));
ccList.value = configCsrList.value.map((item:any) => normalizeTeacherData(item, true));
} else {
loadExistingApprovers();
}
//
console.log("SprList组件初始化成功");
} catch (error) { } catch (error) {
console.error("SprList组件初始化失败:", error); console.error("SprList组件初始化失败:", error);
} }
@ -520,6 +494,42 @@ onMounted(async () => {
border-radius: 12rpx; border-radius: 12rpx;
border: 2rpx dashed #dee2e6; border: 2rpx dashed #dee2e6;
} }
.more-button {
display: flex;
align-items: center;
justify-content: center;
padding: 16rpx 32rpx;
margin-top: 20rpx;
margin-bottom: 40rpx;
background: #f8f9fa;
border: 2rpx solid #e9ecef;
border-radius: 12rpx;
cursor: pointer;
transition: all 0.3s ease;
&:active {
background: #e9ecef;
transform: translateY(1px);
}
.more-text {
font-size: 28rpx;
color: #007aff;
margin-right: 12rpx;
}
.more-icon {
font-size: 24rpx;
color: #007aff;
transition: transform 0.3s ease;
&.expanded {
transform: rotate(180deg);
}
}
}
} }
} }
} }

View File

@ -28,7 +28,7 @@
</view> </view>
<!-- 审批人 --> <!-- 审批人 -->
<view class="info-section spr" v-if="sprSpList.length > 0"> <view class="info-section spr" v-if="sprSpList.length > 0">
<view class="section-title">审批人</view> <view class="section-title">审批人{{ sprSpList.length || 0 }}</view>
<view class="sp-list"> <view class="sp-list">
<view v-for="spr in sprSpList" :key="spr.id" class="sp-item"> <view v-for="spr in sprSpList" :key="spr.id" class="sp-item">
<view class="sp-info"> <view class="sp-info">
@ -54,14 +54,14 @@
</view> </view>
<!-- 抄送人 --> <!-- 抄送人 -->
<view class="info-section csr" v-if="csrSpList.length > 0"> <view class="info-section csr" v-if="csrSpList.length > 0">
<view class="section-title">抄送人</view> <view class="section-title">抄送人{{ csrSpList.length || 0 }}</view>
<view class="sp-list"> <view class="sp-list">
<view v-for="csr in displayedcsrList" :key="csr.id" class="sp-item"> <view v-for="csr in displayedCsrList" :key="csr.id" class="sp-item">
<view class="sp-info"> <view class="sp-info">
<text class="name">{{ csr.userName }}</text> <text class="name">{{ csr.userName }}</text>
<text class="dept">{{ csr.deptName }}</text> <text class="dept">{{ csr.deptName }}</text>
<text class="status" :class="getSprStatusClass(csr.approveStatus)"> <text class="status" :class="getCsrStatusClass(csr.approveStatus)">
{{ getSprStatusText(csr.approveStatus) }} {{ getCsrStatusText(csr.approveStatus) }}
</text> </text>
</view> </view>
</view> </view>
@ -76,7 +76,7 @@
</view> </view>
<!-- 操作记录 --> <!-- 操作记录 -->
<view class="info-section log" v-if="logList.length > 0"> <view class="info-section log" v-if="logList.length > 0">
<view class="section-title">操作记录</view> <view class="section-title">操作记录{{ logList.length || 0 }}</view>
<view class="sp-list"> <view class="sp-list">
<view v-for="log in displayedLogList" :key="log.id" class="sp-item"> <view v-for="log in displayedLogList" :key="log.id" class="sp-item">
<view class="log-header"> <view class="log-header">
@ -153,7 +153,7 @@ const csrExpanded = ref(false);
const logExpanded = ref(false); const logExpanded = ref(false);
// //
const displayedcsrList = computed(() => { const displayedCsrList = computed(() => {
if (csrExpanded.value || csrSpList.value.length <= 2) { if (csrExpanded.value || csrSpList.value.length <= 2) {
return csrSpList.value; return csrSpList.value;
} }
@ -232,8 +232,11 @@ const getSprStatusText = (status: any) => {
// //
const getCsrStatusClass = (status: any) => { const getCsrStatusClass = (status: any) => {
const statusMap: Record<string, string> = { const statusMap: Record<string, string> = {
pending: "status-pending",
approved: "status-approved",
unread: "status-unread", unread: "status-unread",
read: "status-read", read: "status-read",
cc_sent: "status-approved",
}; };
return statusMap[status] || "status-default"; return statusMap[status] || "status-default";
}; };
@ -241,6 +244,9 @@ const getCsrStatusClass = (status: any) => {
// //
const getCsrStatusText = (status: any) => { const getCsrStatusText = (status: any) => {
const statusMap: Record<string, string> = { const statusMap: Record<string, string> = {
pending: "待抄送",
approved: "已抄送",
cc_sent: "已抄送",
unread: "未读", unread: "未读",
read: "已读", read: "已读",
}; };

View File

@ -3,7 +3,7 @@
<!-- 原始审批人 --> <!-- 原始审批人 -->
<view class="section"> <view class="section">
<view class="section-header"> <view class="section-header">
<text class="section-title">原审批人</text> <text class="section-title">原审批人{{ srcSprList.length || 0 }}</text>
</view> </view>
<view class="list-content"> <view class="list-content">
<view v-for="(spr, index) in srcSprList" :key="index" class="list-item readonly"> <view v-for="(spr, index) in srcSprList" :key="index" class="list-item readonly">
@ -26,10 +26,10 @@
<!-- 原始抄送人 --> <!-- 原始抄送人 -->
<view class="section"> <view class="section">
<view class="section-header"> <view class="section-header">
<text class="section-title">原抄送人</text> <text class="section-title">原抄送人{{ srcCsrList.length || 0 }}</text>
</view> </view>
<view class="list-content"> <view class="list-content">
<view v-for="(csr, index) in srcCsrList" :key="index" class="list-item readonly"> <view v-for="(csr, index) in displayedSrcCsrList" :key="index" class="list-item readonly">
<view class="item-info"> <view class="item-info">
<text class="item-name">{{ csr.jsxm }}</text> <text class="item-name">{{ csr.jsxm }}</text>
</view> </view>
@ -38,29 +38,29 @@
<view v-if="srcCsrList.length === 0" class="empty-tip"> <view v-if="srcCsrList.length === 0" class="empty-tip">
<text>暂无原抄送人</text> <text>暂无原抄送人</text>
</view> </view>
<!-- 更多按钮 -->
<view v-if="srcCsrList.length > 2" class="more-button" @click="toggleSrcCsrExpanded">
<text class="more-text">
{{ srcCsrExpanded ? '收起' : `更多(${srcCsrList.length - 2})` }}
</text>
<text class="more-icon" :class="{ expanded: srcCsrExpanded }"></text>
</view>
</view> </view>
</view> </view>
<!-- 审批人列表 --> <!-- 审批人列表 -->
<view class="section"> <view class="section">
<view class="section-header"> <view class="section-header">
<text class="section-title">审批转办人</text> <text class="section-title">{{ newSprTitle }}</text>
<!-- 审批人选择器 --> <!-- 审批人选择器 -->
<BasicJsPicker <BasicJsPicker ref="approverPickerRef" :customTrigger="true" :multiple="true"
ref="approverPickerRef" :excludeIds="getExcludeApproverIds()" :defaultValue="approvers" title="选择审批人" placeholder="请选择审批转办人"
:customTrigger="true" searchPlaceholder="搜索审批人" @change="handleApproverChange">
:multiple="true"
:excludeIds="getExcludeApproverIds()"
:defaultValue="approvers"
title="选择审批转办人"
placeholder="请选择审批转办人"
searchPlaceholder="搜索审批转办人"
@change="handleApproverChange"
>
<template #trigger> <template #trigger>
<view class="add-btn"> <view class="add-btn">
<text class="add-icon">+</text> <text class="add-icon">+</text>
<text class="add-text">添加审批转办人</text> <text class="add-text">添加{{ newSprTitle }}</text>
</view> </view>
</template> </template>
</BasicJsPicker> </BasicJsPicker>
@ -73,33 +73,16 @@
</view> </view>
<view class="item-actions"> <view class="item-actions">
<!-- 上移箭头 --> <!-- 上移箭头 -->
<uni-icons <uni-icons v-if="index > 0" type="top" size="18" color="#666" @click="moveApproverUp(index)"
v-if="index > 0" class="action-icon"></uni-icons>
type="top"
size="18"
color="#666"
@click="moveApproverUp(index)"
class="action-icon"
></uni-icons>
<!-- 下移箭头 --> <!-- 下移箭头 -->
<uni-icons <uni-icons v-if="index < approvers.length - 1" type="bottom" size="18" color="#666"
v-if="index < approvers.length - 1" @click="moveApproverDown(index)" class="action-icon"></uni-icons>
type="bottom"
size="18"
color="#666"
@click="moveApproverDown(index)"
class="action-icon"
></uni-icons>
<!-- 删除图标改为垃圾桶图标 --> <!-- 删除图标改为垃圾桶图标 -->
<uni-icons <uni-icons type="trash" size="18" color="#666" @click="removeApprover(index)"
type="trash" class="action-icon"></uni-icons>
size="18"
color="#666"
@click="removeApprover(index)"
class="action-icon"
></uni-icons>
</view> </view>
</view> </view>
@ -112,23 +95,14 @@
<!-- 抄送人列表 --> <!-- 抄送人列表 -->
<view class="section"> <view class="section">
<view class="section-header"> <view class="section-header">
<text class="section-title">新增抄送人</text> <text class="section-title">{{ newCsrTitle }}</text>
<!-- 抄送人选择器 --> <!-- 抄送人选择器 -->
<BasicJsPicker <BasicJsPicker ref="ccPickerRef" :customTrigger="true" :multiple="true" :excludeIds="getExcludeCcIds()"
ref="ccPickerRef" :defaultValue="ccList" title="选择抄送人" placeholder="请选择抄送人" searchPlaceholder="搜索抄送人" @change="handleCcChange">
:customTrigger="true"
:multiple="true"
:excludeIds="getExcludeCcIds()"
:defaultValue="ccList"
title="选择抄送人"
placeholder="请选择抄送人"
searchPlaceholder="搜索抄送人"
@change="handleCcChange"
>
<template #trigger> <template #trigger>
<view class="add-btn"> <view class="add-btn">
<text class="add-icon">+</text> <text class="add-icon">+</text>
<text class="add-text">添加抄送人</text> <text class="add-text">添加{{ newCsrTitle }}</text>
</view> </view>
</template> </template>
</BasicJsPicker> </BasicJsPicker>
@ -159,6 +133,15 @@ import { useDataStore } from "@/store/modules/data";
import BasicJsPicker from "@/components/BasicJsPicker/Picker.vue"; import BasicJsPicker from "@/components/BasicJsPicker/Picker.vue";
const { getLcgl } = useDataStore(); const { getLcgl } = useDataStore();
//
const props = withDefaults(defineProps<{
newSprTitle?: string;
newCsrTitle?: string;
}>(), {
newSprTitle: "审批转办人",
newCsrTitle: "新抄送人"
});
// JsVo // JsVo
interface JsInfo { interface JsInfo {
id: string; id: string;
@ -207,6 +190,23 @@ const ccPickerRef = ref();
// common store // common store
const commonStore = useCommonStore(); const commonStore = useCommonStore();
//
const srcCsrExpanded = ref(false);
//
const displayedSrcCsrList = computed(() => {
if (srcCsrExpanded.value || srcCsrList.value.length <= 2) {
return srcCsrList.value;
}
return srcCsrList.value.slice(0, 2);
});
//
const toggleSrcCsrExpanded = () => {
srcCsrExpanded.value = !srcCsrExpanded.value;
};
// //
const getSprStatusClass = (status: any) => { const getSprStatusClass = (status: any) => {
const statusMap: Record<string, string> = { const statusMap: Record<string, string> = {
@ -555,6 +555,42 @@ defineExpose({
border-radius: 12rpx; border-radius: 12rpx;
border: 2rpx dashed #ebedf0; border: 2rpx dashed #ebedf0;
} }
.more-button {
display: flex;
align-items: center;
justify-content: center;
padding: 16rpx 32rpx;
margin-top: 20rpx;
margin-bottom: 40rpx;
background: #f8f9fa;
border: 2rpx solid #e9ecef;
border-radius: 12rpx;
cursor: pointer;
transition: all 0.3s ease;
&:active {
background: #e9ecef;
transform: translateY(1px);
}
.more-text {
font-size: 28rpx;
color: #007aff;
margin-right: 12rpx;
}
.more-icon {
font-size: 24rpx;
color: #007aff;
transition: transform 0.3s ease;
&.expanded {
transform: rotate(180deg);
}
}
}
} }
} }
} }

View File

@ -113,7 +113,7 @@ onLoad(async (data: any) => {
const xsQj = res.result || {}; const xsQj = res.result || {};
if (xsQj.spResult != "A" && getXxts && getXxts.dbZt === "A") { if (xsQj.spResult != "A" && getXxts && getXxts.dbZt === "A") {
uni.reLaunch({ url: '/pages/base/xs/qj/detail' }); uni.reLaunch({ url: '/pages/base/xs/qj/detail' });
// const flag = await XkTfPageUtils.updateXxts(); const flag = await XkTfPageUtils.updateXxts();
} else { } else {
nextTick(() => { nextTick(() => {
setData(xsQj); setData(xsQj);

View File

@ -0,0 +1,176 @@
<template>
<u-popup :show="dlgFlag" mode="bottom" width="calc(100% - 60rpx)" :closeOnClickOverlay="false" @close="closeDlg"
class="transfer-popup">
<view class="popup-content">
<view class="popup-header">
<view class="popup-title">转办设置</view>
</view>
<view class="popup-body">
<view class="section">
<view class="section-header">
<text class="section-title">转办原因</text>
</view>
<view class="list-content">
<u-input v-model="spRemark" type="textarea" placeholder="请填写转办原因" :autoHeight="true" maxlength="200"
class="remark-input" />
</view>
</view>
<TransferSpCsMgr ref="transferSpCsMgrRef" />
</view>
<view class="popup-actions flex-row justify-end mt-4">
<u-button class="mr-2" @click="closeDlg">取消</u-button>
<u-button type="primary" @click="submit">确定</u-button>
</view>
</view>
</u-popup>
</template>
<script setup lang="ts">
import { ref } from "vue";
import TransferSpCsMgr from "@/components/TransferSpCsMgr/index.vue"
// emit
const emit = defineEmits(["submit"]);
const transferSpCsMgrRef = ref<any>(null);
const dlgFlag = ref(false);
const spRemark = ref("");
const showDlg = (type: string) => {
dlgFlag.value = true;
};
const closeDlg = () => {
dlgFlag.value = false;
};
//
const submit = () => {
if (!spRemark.value || !spRemark.value.trim()) {
uni.showToast({ title: "请填写转办原因", icon: "none" });
return;
}
const newSprList = transferSpCsMgrRef.value.getNewSprList();
const newCsrList = transferSpCsMgrRef.value.getNewCsrList();
if (!newSprList.length) {
uni.showToast({ title: "请选择审批转办人", icon: "none" });
return;
}
emit('submit', { newSprList, newCsrList, spRemark: spRemark.value });
}
defineExpose({
showDlg,
closeDlg
});
</script>
<style lang="scss" scoped>
.transfer-popup {
width: calc(100% - 60rpx);
max-height: 90vh;
}
.popup-content {
display: flex;
flex-direction: column;
max-height: 90vh;
}
.popup-header {
flex-shrink: 0;
padding: 30rpx;
border-bottom: 1rpx solid #ebedf0;
.popup-title {
font-size: 32rpx;
font-weight: bold;
text-align: center;
color: #262626;
}
}
.popup-body {
flex: 1;
overflow-y: auto;
padding: 30rpx;
max-height: calc(90vh - 200rpx);
.flex-row {
margin-bottom: 30rpx;
.label {
font-size: 28rpx;
color: #262626;
margin-bottom: 16rpx;
}
}
.remark-input {
display: flex;
align-items: flex-start; /* 垂直上对齐 */
justify-content: flex-start; /* 水平居左对齐 */
input {
height: 160rpx;
}
}
}
.popup-actions {
flex-shrink: 0;
padding: 30rpx;
border-top: 1rpx solid #ebedf0;
}
.transfer-form {
background: #fff;
border-radius: 8px;
padding: 20px;
margin-bottom: 20px;
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1);
}
.section {
margin-bottom: 40rpx;
.section-header {
display: flex;
justify-content: space-between;
align-items: center;
margin-bottom: 20rpx;
.section-title {
font-size: 32rpx;
font-weight: bold;
color: #262626;
}
}
.list-content {
}
}
.bottom-actions {
position: fixed;
bottom: 0;
left: 0;
right: 0;
background: white;
padding: 15px;
border-top: 1px solid #eee;
box-shadow: 0 -2px 8px rgba(0, 0, 0, 0.1);
display: flex;
gap: 15px;
z-index: 1000;
}
.bottom-actions .u-button {
flex: 1;
height: 44px;
border-radius: 8px;
font-size: 16px;
font-weight: 500;
}
</style>

View File

@ -7,6 +7,9 @@
<view class="flex-row items-center pb-5"> <view class="flex-row items-center pb-5">
<u-button text="终止" class="ml-15 mr-7" :plain="true" @click="showDlg('stop')" /> <u-button text="终止" class="ml-15 mr-7" :plain="true" @click="showDlg('stop')" />
<u-button text="转办" class="mr-15 mr-7" :plain="true" @click="showTransfer" /> <u-button text="转办" class="mr-15 mr-7" :plain="true" @click="showTransfer" />
</view>
<view class="flex-row items-center pb-5">
<u-button text="协调代课教师" class="mr-15 mr-7" :plain="true" @click="showXtDlg" />
</view> </view>
<!-- 驳回弹窗 --> <!-- 驳回弹窗 -->
<u-popup :show="dlgFlag" mode="center" :closeOnClickOverlay="false" @close="closeDlg"> <u-popup :show="dlgFlag" mode="center" :closeOnClickOverlay="false" @close="closeDlg">
@ -24,12 +27,13 @@
</view> </view>
</u-popup> </u-popup>
<YwTransfer ref="transferRef" @submit="handleTransfer" /> <YwTransfer ref="transferRef" @submit="handleTransfer" />
<XtDkJs ref="xtDkJsRef" @submit="handleXtDkJs" />
</view> </view>
</template> </template>
<script lang="ts" setup> <script lang="ts" setup>
import YwTransfer from "../YwTransfer/index.vue"; import YwTransfer from "../YwTransfer/index.vue";
import XtDkJs from "../XtDkJs/index.vue";
// //
const props = withDefaults(defineProps<{ const props = withDefaults(defineProps<{
@ -43,6 +47,7 @@ const props = withDefaults(defineProps<{
rejectValue?: string, // rejectValue?: string, //
approvedRemark?: string // approvedRemark?: string //
autoToMessage?: boolean // autoToMessage?: boolean //
showXt?: boolean
}>(), { }>(), {
spApi: async (params: any) => {}, spApi: async (params: any) => {},
transferApi: async (params: any) => {}, transferApi: async (params: any) => {},
@ -53,13 +58,15 @@ const props = withDefaults(defineProps<{
approvedValue: 'approved', approvedValue: 'approved',
rejectValue: 'rejected', rejectValue: 'rejected',
approvedRemark: '同意', approvedRemark: '同意',
autoToMessage: true autoToMessage: true,
showXt: false
}); });
// emit // emit
const emit = defineEmits(['submit', 'reject', 'stop', 'transfer']) const emit = defineEmits(['submit', 'reject', 'stop', 'transfer'])
const transferRef = ref<any>(null); const transferRef = ref<any>(null);
const xtDkJsRef = ref<any>(null);
const dlgFlag = ref(false); const dlgFlag = ref(false);
const dlgType = ref(""); const dlgType = ref("");
@ -90,6 +97,10 @@ const showTransfer = () => {
transferRef.value.showDlg(); transferRef.value.showDlg();
}; };
const showXtDlg = () => {
};
const submit = async () => { const submit = async () => {
const params = { const params = {
...props.params ...props.params
@ -142,6 +153,26 @@ const handleTransfer = async (data: any) => {
} }
}; };
//
const handleXtDkJs = async (data: any) => {
const params = {
...props.params
};
const newSprList = data.newSprList || [];
const newCsrList = data.newCsrList || [];
params.spRemark = data.spRemark;
params.zbrIds = newSprList.map((item: any) => item.userId).join(",");
params.csrIds = newCsrList.map((item: any) => item.userId).join(",");
uni.showLoading({ title: "正在转办..." });
await props.transferApi(params);
transferRef.value.closeDlg();
uni.hideLoading();
emit('transfer');
if (props.autoToMessage) {
goToMessage();
}
};
const handleDlgSubmit = async () => { const handleDlgSubmit = async () => {
if (!spRemark.value || !spRemark.value.trim()) { if (!spRemark.value || !spRemark.value.trim()) {
uni.showToast({ title: "请填写" + dlgTips.value, icon: "none" }); uni.showToast({ title: "请填写" + dlgTips.value, icon: "none" });

View File

@ -19,10 +19,10 @@
<text class="label">代课老师:</text> <text class="label">代课老师:</text>
<view class="value">{{ item.jsName }}</view> <view class="value">{{ item.jsName }}</view>
</view> </view>
<view class="info-row"> <!-- <view class="info-row">
<text class="label">确认状态:</text> <text class="label">确认状态:</text>
<view class="value">{{ item.statusLabel }}</view> <view class="value">{{ item.statusLabel }}</view>
</view> </view> -->
</view> </view>
</view> </view>
</view> </view>

View File

@ -72,6 +72,10 @@ watch(
); );
const init = async () => { const init = async () => {
if (!props.qjId) {
console.log("初始化的qjId为空");
return;
}
const res = await findQjById({ id: props.qjId }); const res = await findQjById({ id: props.qjId });
qjData.value = (res && res.result) ? res.result : {}; qjData.value = (res && res.result) ? res.result : {};
if (props.dbFlag) { if (props.dbFlag) {

View File

@ -102,10 +102,12 @@
</template> </template>
<script setup lang="ts"> <script setup lang="ts">
import { getPkkbByJsRangeTimeApi } from "@/api/base/jsQjApi"; import { getPkkbByJsRangeTimeApi, findDkPageApi } from "@/api/base/jsQjApi";
import BasicJsPicker from "@/components/BasicJsPicker/Picker.vue"; import BasicJsPicker from "@/components/BasicJsPicker/Picker.vue";
import { useUserStore } from "@/store/modules/user"; import { useUserStore } from "@/store/modules/user";
import { useCommonStore } from "@/store/modules/common";
const { getJs } = useUserStore(); const { getJs } = useUserStore();
const { getAllJsBasicInfoVo } = useCommonStore();
// //
const props = withDefaults( const props = withDefaults(
@ -114,6 +116,7 @@ const props = withDefaults(
}>(), }>(),
{ {
data: () => ({ data: () => ({
qjId: "",
jsId: "", jsId: "",
qjkstime: "", // qjkstime: "", //
qjjstime: "", // qjjstime: "", //
@ -165,6 +168,10 @@ const switchTab = (index: number) => {
}; };
const getPkkbList = async () => { const getPkkbList = async () => {
//
if (!props.data.qjjstime || !props.data.qjkstime) {
return;
}
const res = await getPkkbByJsRangeTimeApi({ const res = await getPkkbByJsRangeTimeApi({
jsId: props.data.jsId, jsId: props.data.jsId,
startTime: props.data.qjkstime, startTime: props.data.qjkstime,
@ -177,6 +184,7 @@ const getPkkbList = async () => {
srcData[key] = { srcData[key] = {
dkJsId: item.dkJsId, dkJsId: item.dkJsId,
dkJsName: item.dkJsName, dkJsName: item.dkJsName,
userId: item.userId
}; };
}); });
const kmMap: any = {}; const kmMap: any = {};
@ -189,13 +197,14 @@ const getPkkbList = async () => {
if (src) { if (src) {
item.dkJsId = src.dkJsId; item.dkJsId = src.dkJsId;
item.dkJsName = src.dkJsName; item.dkJsName = src.dkJsName;
item.userId = src.userId;
} else { } else {
item.dkJsId = ""; item.dkJsId = "";
item.dkJsName = ""; item.dkJsName = "";
item.userId = "";
} }
kmMap[item.pkId] = kmMap[item.pkId] || { kmMap[item.pkMc] = kmMap[item.pkMc] || {
pkMc: item.pkMc, pkMc: item.pkMc,
pkId: item.pkId,
}; };
return item; return item;
}); });
@ -206,11 +215,13 @@ const getPkkbList = async () => {
const changeJsByTy = (selected: any, item: any) => { const changeJsByTy = (selected: any, item: any) => {
item.dkJsId = selected.value; item.dkJsId = selected.value;
item.dkJsName = selected.label; item.dkJsName = selected.label;
item.userId = selected.userId;
const newList = dkList.value.map((dk: any) => { const newList = dkList.value.map((dk: any) => {
return { return {
...dk, ...dk,
dkJsId: item.dkJsId, dkJsId: item.dkJsId,
dkJsName: item.dkJsName, dkJsName: item.dkJsName,
userId: item.userId
}; };
}); });
dkList.value = newList; dkList.value = newList;
@ -227,10 +238,11 @@ const changeJsByTy = (selected: any, item: any) => {
const changeJsByKm = (selected: any, item: any) => { const changeJsByKm = (selected: any, item: any) => {
item.dkJsId = selected.value; item.dkJsId = selected.value;
item.dkJsName = selected.label; item.dkJsName = selected.label;
item.userId = selected.userId;
// //
const newList = dkList.value.map((dk: any) => { const newList = dkList.value.map((dk: any) => {
if (dk.pkId === item.pkId) { if (dk.pkMc === item.pkMc) {
return { ...dk, dkJsId: item.dkJsId, dkJsName: item.dkJsName }; return { ...dk, dkJsId: item.dkJsId, dkJsName: item.dkJsName, userId: item.userId };
} }
return dk; return dk;
}); });
@ -240,6 +252,7 @@ const changeJsByKm = (selected: any, item: any) => {
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;
item.userId = selected.userId;
}; };
const validate = async () => { const validate = async () => {
@ -262,6 +275,38 @@ const validate = async () => {
return true; return true;
}; };
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 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;
}
kmMap[item.pkMc] = kmMap[item.pkMc] || {
pkMc: item.pkMc,
};
return item;
});
// kmMapvalue
kmDkList.value = Object.values(kmMap);
};
// ref // ref
const getDkList = () => { const getDkList = () => {
return dkList.value; return dkList.value;
@ -272,6 +317,7 @@ defineExpose({
getPkkbList, getPkkbList,
validate, validate,
getDkList, getDkList,
initDkList,
}); });
</script> </script>

View File

@ -7,9 +7,8 @@
</template> </template>
<template #spcs> <template #spcs>
<BasicSpCsMgr <BasicSpCsMgr
ruleId="yfzc_js_qj" rule-id="yfzc_js_qj"
:qjId="formData.id" :yw-id="formData.id"
:defaultValue="defSpCs"
@change="onSpCsChange" @change="onSpCsChange"
/> />
</template> </template>
@ -18,7 +17,7 @@
<template #bottom> <template #bottom>
<view class="white-bg-color py-5"> <view class="white-bg-color py-5">
<view class="flex-row items-center pb-10 pt-5"> <view class="flex-row items-center pb-10 pt-5">
<u-button text="取消" class="ml-15 mr-7" :plain="true" @click="navigateBack" /> <u-button text="取消" class="ml-15 mr-7" :plain="true" @click="goBack" />
<u-button text="提交" class="mr-15 mr-7" type="primary" @click="submit" /> <u-button text="提交" class="mr-15 mr-7" type="primary" @click="submit" />
</view> </view>
</view> </view>
@ -29,7 +28,6 @@
<script setup lang="ts"> <script setup lang="ts">
import JsQjDkEdit from "./jsQjDkEdit.vue" import JsQjDkEdit from "./jsQjDkEdit.vue"
import BasicSpCsMgr from "@/components/BasicSpCsMgr/index.vue" import BasicSpCsMgr from "@/components/BasicSpCsMgr/index.vue"
import { navigateBack } from "@/utils/uniapp";
import { useForm } from "@/components/BasicForm/hooks/useForm"; import { useForm } from "@/components/BasicForm/hooks/useForm";
import { jsQjSqApi, jsQjCxtjApi } from "@/api/base/jsQjApi"; import { jsQjSqApi, jsQjCxtjApi } from "@/api/base/jsQjApi";
import { showToast } from "@/utils/uniapp"; import { showToast } from "@/utils/uniapp";
@ -62,14 +60,6 @@ let formData = ref<any>({
jsId: getJs.id, jsId: getJs.id,
}); });
const defSpCs = computed(() => {
return {
sprList: formData.value.sprList,
csrList: formData.value.csrList,
}
})
const dkRef = ref<any>(null); const dkRef = ref<any>(null);
if (typeof props.data.dkfs === "string") { if (typeof props.data.dkfs === "string") {
@ -206,9 +196,13 @@ const updateDk = () => {
}); });
}; };
// const initDk = () => {
setValue(props.data) nextTick(() => {
updateDk(); if (dkRef.value) {
dkRef.value.initDkList();
}
});
}
const submit = async () => { const submit = async () => {
const fd = await getValue(); const fd = await getValue();
@ -216,9 +210,6 @@ const submit = async () => {
return; return;
} }
const params = { ...fd }; const params = { ...fd };
// /
params.sprList = formData.value.sprList || [];
params.csrList = formData.value.csrList || [];
if (fd.dkfs === 0) { if (fd.dkfs === 0) {
const dkList = dkRef.value.getDkList(); const dkList = dkRef.value.getDkList();
if (!dkList.length) { if (!dkList.length) {
@ -243,10 +234,15 @@ const submit = async () => {
params.dkList = []; params.dkList = [];
} }
} }
// /
params.sprList = formData.value.sprList || [];
params.csrList = formData.value.csrList || [];
let submitApi = jsQjSqApi; let submitApi = jsQjSqApi;
if (props.data && props.data.id) { if (props.data && props.data.id) {
params.id = props.data.id;
submitApi = jsQjCxtjApi submitApi = jsQjCxtjApi
params.id = props.data.id;
params.jsId = getJs.id;
params.jsName = getJs.jsxm;
} else { } else {
params.id = null; params.id = null;
params.jsId = getJs.id; params.jsId = getJs.id;
@ -270,6 +266,23 @@ const onSpCsChange = (payload: any) => {
formData.value.csrList = Array.isArray(payload.csrList) ? payload.csrList : []; formData.value.csrList = Array.isArray(payload.csrList) ? payload.csrList : [];
} }
}; };
const goBack = () => {
if (props.data && props.data.id) {
uni.reLaunch({ url: "/pages/base/message/index" });
} else {
uni.reLaunch({ url: "/pages/base/service/index" });
}
};
onMounted(() => {
if (props.data && props.data.id) {
//
setValue(props.data);
initDk();
}
});
</script> </script>
<style lang="scss" scoped> <style lang="scss" scoped>

View File

@ -53,7 +53,10 @@ const [register, { reload }] = useLayout({
// //
const goToDetail = (item: any | null) => { const goToDetail = (item: any | null) => {
setData(item); setData({
...item,
from: 'list'
});
let url = '/pages/view/hr/jsQj/detail'; // 使 let url = '/pages/view/hr/jsQj/detail'; // 使
uni.navigateTo({ url }); uni.navigateTo({ url });
}; };

View File

@ -1,76 +1,117 @@
<template> <template>
<BasicLayout> <view class="leave-page">
<view class="p-15"> <!-- 选项卡 -->
<view class="info-card"> <BasicTabs
<view class="card-header"> class="leave-tabs"
<text class="card-title">重新提交请假申请</text> ref="tabsRef"
</view> :list="tabList"
<view class="card-content"> bar-width="60px"
<text class="info-text">您的请假申请已被驳回请修改后重新提交</text> scroll-count="4"
</view> :current="curTabIndex"
@change="switchTab"
/>
<view class="leave-edit" v-if="curTabIndex === 0">
<!-- 使用请假申请组件 -->
<JsQjEdit :data="qjData" v-if="qjData && qjData.id" />
</view> </view>
<!-- 使用请假申请组件 --> <view class="leave-list" v-else>
<JsQjEdit :data="qjData" /> <view class="mt-15">
<LcglSp :yw-id="qjId" yw-type="JS_QJ" />
</view>
</view>
</view> </view>
</BasicLayout>
</template> </template>
<script setup lang="ts"> <script setup lang="ts">
import { findQjById } from "@/api/base/jsQjApi";
import { onLoad } from "@dcloudio/uni-app"; import { onLoad } from "@dcloudio/uni-app";
import { useUserStore } from "@/store/modules/user";
import { useDataStore } from "@/store/modules/data";
import { ref } from "vue"; import { ref } from "vue";
import JsQjEdit from "./components/jsQjEdit.vue"; import LcglSp from "@/components/LcglSp/index.vue";
import JsQjEdit from "./components/jsQjEdit.vue"
import { QjPageUtils } from "@/utils/qjPageUtils";
import { findQjById } from "@/api/base/jsQjApi";
const qjId = ref<string>(); const { getJs } = useUserStore();
const { getData, getXxts } = useDataStore();
//
const tabList = ref([
{ name: "重新提交", id: "leave-edit" },
{ name: "审批流程", id: "leave-detail" },
])
const curTabIndex = ref(0)
//
const switchTab = (index: number) => {
curTabIndex.value = index
}
const dbFlag = ref(false);
const qjId = ref('');
const qjData = ref<any>({}); const qjData = ref<any>({});
// const spParams = computed(() => {
const loadQjData = async () => { return {
try { xxtsId: getXxts.id,
const result:any = await findQjById({ id: qjId.value }); ywId: qjId.value
if (result.code === 1) { };
qjData.value = result.data; });
}
} catch (error) { const loadData = async () => {
console.error('获取请假信息失败:', error); const res = await findQjById({ id: qjId.value });
} qjData.value = (res && res.result) ? res.result : {};
qjData.value.dkfs = parseInt(qjData.value.dkfs);
}; };
onLoad((options:any) => { onLoad(async (data?: any) => {
if (options.qjId) { const ret = await QjPageUtils.init(data);
qjId.value = options.qjId; if (!ret || !ret.success) {
loadQjData(); return;
} }
qjId.value = ret.qjId;
dbFlag.value = ret.dbFlag;
loadData();
}); });
</script> </script>
<style lang="scss" scoped> <style lang="scss" scoped>
.info-card { .leave-page {
background: white; flex: 1 0 1px;
border-radius: 8px; display: flex;
margin-bottom: 15px; flex-direction: column;
box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1); height: 100vh;
} background: linear-gradient(135deg, #f5f7fa 0%, #c3cfe2 100%);
.card-header { .leave-tabs {
padding: 15px; flex: 0 0 45px;
border-bottom: 1px solid #eee; background: #fff;
box-shadow: 0 2rpx 8rpx rgba(0, 0, 0, 0.1);
.card-title { z-index: 10;
font-size: 16px;
font-weight: bold;
color: #333;
} }
}
.card-content { .leave-edit,
padding: 15px; .leave-list {
flex: 1 0 1px;
position: relative;
overflow-y: auto;
}
.info-text { .leave-edit {
font-size: 14px; background: #fff;
color: #666; margin: 20rpx;
line-height: 1.5; border-radius: 16rpx;
box-shadow: 0 8rpx 32rpx rgba(0, 0, 0, 0.1);
}
.leave-list {
background: #fff;
margin: 20rpx;
border-radius: 16rpx;
box-shadow: 0 8rpx 32rpx rgba(0, 0, 0, 0.1);
} }
} }
</style> </style>

View File

@ -1,41 +1,22 @@
<template> <template>
<BasicLayout> <BasicLayout>
<template #top>
<view>
<BasicTabs
class="detail-tabs"
:list="tabList"
bar-width="60px"
scroll-count="4"
:current="curTabIndex"
@change="switchTab"
/>
</view>
</template>
<view class="qj-detail"> <view class="qj-detail">
<!-- 请假信息 --> <!-- 请假信息 -->
<view v-show="curTabIndex === 0"> <view>
<JsQjDetailInfo <JsQjDetailInfo :qjId="qjId" :dbFlag="dbFlag" @loadQjData="handleQjDataLoaded" />
:qjId="qjId"
:dbFlag="dbFlag"
@loadQjData="handleQjDataLoaded"
/>
</view> </view>
<!-- 代课信息 --> <!-- 代课信息 -->
<view v-show="curTabIndex === 1"> <view>
<view v-if="!showDkFlag" class="empty-dk"> <view v-if="!showDkFlag" class="empty-dk">
<view>{{ showDkEmptyLabel }}</view> <view>{{ showDkEmptyLabel }}</view>
</view> </view>
<JsQjDetailDk v-else <JsQjDetailDk v-else :qjId="qjId" @loadDkList="handleDkListLoaded" />
:qjId="qjId"
@loadDkList="handleDkListLoaded"
/>
</view> </view>
<!-- 审批流程 --> <!-- 审批流程 -->
<view v-show="curTabIndex === 2"> <view class="mt-15">
<LcglSpList :yw-id="qjId" yw-type="JS_QJ" /> <LcglSp :yw-id="qjId" yw-type="JS_QJ" />
</view> </view>
</view> </view>
<template #bottom> <template #bottom>
@ -53,33 +34,26 @@ import { useDataStore } from "@/store/modules/data";
import { ref, computed } from "vue"; import { ref, computed } from "vue";
import JsQjDetailInfo from "./components/jsQjDetailInfo.vue"; import JsQjDetailInfo from "./components/jsQjDetailInfo.vue";
import JsQjDetailDk from "./components/jsQjDetailDk.vue"; import JsQjDetailDk from "./components/jsQjDetailDk.vue";
import LcglSpList from "@/components/LcglSpList/index.vue"; import LcglSp from "@/components/LcglSp/index.vue";
import { onLoad } from "@dcloudio/uni-app";
import { QjPageUtils } from "@/utils/qjPageUtils";
import { xxtsFindByIdApi } from "@/api/base/xxtsApi";
const { getData, setData } = useDataStore(); const { getData, setData, getXxts } = useDataStore();
const tabList = ref<any>([
{ name: "请假信息", id: "tab-qj" },
{ name: "代课信息", id: "tab-dk" },
{ name: "审批流程", id: "tab-sp" }
]);
const curTabIndex = ref(0);
const dbFlag = ref(false); const dbFlag = ref(false);
const qjId = computed(() => getData.id); const qjId = ref('');
const showDkFlag = ref(false); const showDkFlag = ref(false);
const showDkEmptyLabel = ref(''); const showDkEmptyLabel = ref('');
// Tab
const switchTab = (index: number) => {
curTabIndex.value = index;
};
const handleQjDataLoaded = (data: any) => { const handleQjDataLoaded = (data: any) => {
setData(data);
data = data || {}; data = data || {};
const dkfs = typeof(data.dkfs) === "string" ? parseInt(data.dkfs) : (data.dkfs || 2); if (data.spResult != "A" && getXxts && getXxts.dbZt === "A") {
const bpmStatus = typeof(data.bpmStatus) === "string" ? parseInt(data.bpmStatus) : (data.bpmStatus || 1); QjPageUtils.updateXxts();
}
setData(data);
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); showDkFlag.value = dkfs === 0 || (dkfs === 1 && bpmStatus > 4);
if (dkfs === 1) { if (dkfs === 1) {
showDkEmptyLabel.value = "等待教科处协调"; showDkEmptyLabel.value = "等待教科处协调";
@ -93,11 +67,31 @@ const handleDkListLoaded = (list: any[]) => {
}; };
const goHome = () => { const goHome = () => {
setData({});
uni.reLaunch({ uni.reLaunch({
url: '/pages/base/service/index', url: '/pages/base/service/index',
}); });
}; };
onLoad(async (data) => {
if (getData && getData.id && (
getData.from === "xxts-B" || getData.from === "list"
)) {
qjId.value = getData.id;
//
return;
}
const ret = await QjPageUtils.init({
...data,
detailFlag: true,
});
if (!ret || !ret.success) {
return;
}
dbFlag.value = ret.dbFlag;
qjId.value = ret.qjId;
});
</script> </script>
<style lang="scss" scoped> <style lang="scss" scoped>

View File

@ -43,12 +43,6 @@ import { QjPageUtils } from "@/utils/qjPageUtils";
const { getJs } = useUserStore(); const { getJs } = useUserStore();
const { setData, getXxts } = useDataStore(); const { setData, getXxts } = useDataStore();
const tabList = ref<any>([
{ name: "请假信息", id: "tab-qj" },
{ name: "代课信息", id: "tab-dk" },
{ name: "审批流程", id: "tab-sp" }
]);
const curTabIndex = ref(0);
const dbFlag = ref(false); const dbFlag = ref(false);
const qjId = ref(''); const qjId = ref('');
@ -62,14 +56,12 @@ const spParams = computed(() => {
}; };
}); });
// Tab
const switchTab = (index: number) => {
curTabIndex.value = index;
};
const handleQjDataLoaded = (data: any) => { const handleQjDataLoaded = (data: any) => {
setData(data);
data = data || {}; data = data || {};
setData(data);
if (data.spResult != "A" && getXxts && getXxts.dbZt === "A") {
uni.reLaunch({ url: '/pages/base/xs/qj/detail' });
}
const dkfs = typeof(data.dkfs) === "string" ? parseInt(data.dkfs) : (data.dkfs || 2); const dkfs = typeof(data.dkfs) === "string" ? parseInt(data.dkfs) : (data.dkfs || 2);
showDkFlag.value = dkfs === 0; showDkFlag.value = dkfs === 0;
if (dkfs === 1) { if (dkfs === 1) {

View File

@ -31,15 +31,19 @@ export const QjPageUtils = {
const xxtsRes = await xxtsFindByIdApi({ id: data.id }); const xxtsRes = await xxtsFindByIdApi({ id: data.id });
if (xxtsRes && xxtsRes.result) { if (xxtsRes && xxtsRes.result) {
const xxts = xxtsRes.result; const xxts = xxtsRes.result;
setXxts(xxts);
ret.qjId = xxts.xxzbId;
// 检查待办状态 // 检查待办状态
if (xxts.dbZt === "B") { if (xxts.dbZt === "B") {
setData({ id: xxts.xxzbId }); // 消息推送状态为B
setData({ id: xxts.xxzbId, from: "xxts-B" });
if (!data.detailFlag) {
url = "/pages/view/hr/jsQj/detail"; url = "/pages/view/hr/jsQj/detail";
uni.reLaunch({ url }); uni.reLaunch({ url });
ret.success = false; ret.success = false;
} else { } else {
setXxts(xxts); ret.success = true;
ret.qjId = xxts.xxzbId; }
} }
} else { } else {
uni.showToast({ uni.showToast({
@ -68,6 +72,7 @@ export const QjPageUtils = {
if (!getXxts || !getXxts.id) { if (!getXxts || !getXxts.id) {
return false; return false;
} }
console.log("更新待办状态getXxts", getXxts);
// 更新待办状态 // 更新待办状态
await xxtsSaveApi({ await xxtsSaveApi({
id: getXxts.id, id: getXxts.id,