1、调整审批流程组件

2、调整完善学生请假对应的审批流程
This commit is contained in:
ywyonui 2025-09-20 23:05:04 +08:00
parent 281cdef9a3
commit bf2b736d54
18 changed files with 1559 additions and 317 deletions

View File

@ -18,12 +18,22 @@ export const jsQjCxtjApi = async (params: any) => {
};
/**
*
*
*/
export const jsQjSpApi = async (params: any) => {
return await post("/api/jsQj/sp", params);
};
// 教师请假审批终止
export const jsQjStopApi = async (params: any) => {
return await post("/api/jsQj/stop", params);
};
// 教师请假审批转办
export const jsQjTransferApi = async (params: any) => {
return await post("/api/jsQj/transfer", params);
};
/**
*
*/

View File

@ -62,3 +62,14 @@ export function lcglSpSaveApi(params: {
export function lcglSpLogicDeleteApi(params: { id: string }) {
return post('/api/lcglSp/logicDelete', params);
}
/**
*
* @param params
*/
export function getLcglApi(params: {
ywId?: string;
ywType?: string;
}) {
return get('/api/lcglSp/getLcgl', params);
}

View File

@ -168,6 +168,16 @@ export const xsQjSpApi = async (params: any) => {
return await post("/api/xsQj/sp", params);
};
// 学生请假审批终止
export const xsQjStopApi = async (params: any) => {
return await post("/api/xsQj/stop", params);
};
// 学生请假审批转办
export const xsQjTransferApi = async (params: any) => {
return await post("/api/xsQj/transfer", params);
};
// 获取学生请假审批流程
export const getXsQjApprovalProcessApi = async (ywId: string, ywType: string = 'XS_QJ') => {
return await get("/api/lcglSp/getByYwIdAndYwType", { ywId, ywType });

View File

@ -19,15 +19,18 @@ export const getXkTfDetailByIdApi = async (id: string) => {
};
/**
* 退
* 退
*/
export const xkTfSpApi = async (params: any) => {
return await post("/api/xkTf/sp", params);
};
/**
*
*/
export const xkTfSpTransferApi = async (params: any) => {
return await post("/api/xkTf/spTransfer", params);
// 选课退费审批审批终止
export const xkTfStopApi = async (params: any) => {
return await post("/api/xkTf/stop", params);
};
// 选课退费审批审批转办
export const xkTfTransferApi = async (params: any) => {
return await post("/api/xkTf/transfer", params);
};

View File

@ -31,7 +31,34 @@
<text class="item-name">{{ spr.jsxm }}</text>
</view>
<view class="item-actions">
<text class="delete-btn" @click="removeApprover(index)">删除</text>
<!-- 上移箭头 -->
<uni-icons
v-if="index > 0"
type="top"
size="18"
color="#666"
@click="moveApproverUp(index)"
class="action-icon"
></uni-icons>
<!-- 下移箭头 -->
<uni-icons
v-if="index < approvers.length - 1"
type="bottom"
size="18"
color="#666"
@click="moveApproverDown(index)"
class="action-icon"
></uni-icons>
<!-- 删除图标改为垃圾桶图标 -->
<uni-icons
type="trash"
size="18"
color="#666"
@click="removeApprover(index)"
class="action-icon"
></uni-icons>
</view>
</view>
@ -283,6 +310,28 @@ const notifyChange = () => {
});
};
//
const moveApproverUp = (index: number) => {
if (index > 0) {
const temp = approvers.value[index];
approvers.value[index] = approvers.value[index - 1];
approvers.value[index - 1] = temp;
notifyChange();
console.log('Moved up:', index);
}
};
//
const moveApproverDown = (index: number) => {
if (index < approvers.value.length - 1) {
const temp = approvers.value[index];
approvers.value[index] = approvers.value[index + 1];
approvers.value[index + 1] = temp;
notifyChange();
console.log('Moved down:', index);
}
};
//
const handleApproverChange = (selectedTeachers: any[]) => {
if (Array.isArray(selectedTeachers)) {

View File

@ -0,0 +1,542 @@
<template>
<view class="lcgl-info">
<!-- 申请人 -->
<view class="info-section sqr">
<view class="section-title">申请人</view>
<view class="sp-list">
<view class="sp-item">
<view class="sp-info">
<text class="name">{{ sqrSp.userName }}</text>
<text class="dept">{{ sqrSp.deptName }}</text>
<text class="status" :class="getSqrStatusClass(sqrSp.approveStatus)">
{{ getSqrStatusText(sqrSp.approveStatus) }}
</text>
</view>
<!-- 显示审批意见和审批时间 -->
<view class="sp-detail" v-if="sqrSp.approveRemark || sqrSp.approveTime">
<view class="approval-info" v-if="sqrSp.approveRemark">
<text class="info-label">申请意见</text>
<text class="info-value">{{ sqrSp.approveRemark }}</text>
</view>
<view class="approval-info" v-if="sqrSp.approveTime">
<text class="info-label">申请时间</text>
<text class="info-value">{{ formatTime(sqrSp.approveTime) }}</text>
</view>
</view>
</view>
</view>
</view>
<!-- 审批人 -->
<view class="info-section spr" v-if="sprSpList.length > 0">
<view class="section-title">审批人</view>
<view class="sp-list">
<view v-for="spr in sprSpList" :key="spr.id" class="sp-item">
<view class="sp-info">
<text class="name">{{ spr.userName }}</text>
<text class="dept">{{ spr.deptName }}</text>
<text class="status" :class="getSprStatusClass(spr.approveStatus)">
{{ getSprStatusText(spr.approveStatus) }}
</text>
</view>
<!-- 显示审批意见和审批时间 -->
<view class="sp-detail" v-if="spr.approveStatus !== 'pending'">
<view class="approval-info" v-if="spr.approveRemark">
<text class="info-label">审批意见</text>
<text class="info-value">{{ spr.approveRemark }}</text>
</view>
<view class="approval-info" v-if="spr.approveTime">
<text class="info-label">审批时间</text>
<text class="info-value">{{ formatTime(spr.approveTime) }}</text>
</view>
</view>
</view>
</view>
</view>
<!-- 抄送人 -->
<view class="info-section csr" v-if="csrSpList.length > 0">
<view class="section-title">抄送人</view>
<view class="sp-list">
<view v-for="csr in displayedcsrList" :key="csr.id" class="sp-item">
<view class="sp-info">
<text class="name">{{ csr.userName }}</text>
<text class="dept">{{ csr.deptName }}</text>
<text class="status" :class="getSprStatusClass(csr.approveStatus)">
{{ getSprStatusText(csr.approveStatus) }}
</text>
</view>
</view>
</view>
<!-- 更多按钮 -->
<view v-if="csrSpList.length > 2" class="more-button" @click="toggleCsrExpanded">
<text class="more-text">
{{ csrExpanded ? '收起' : `更多(${csrSpList.length - 2})` }}
</text>
<text class="more-icon" :class="{ expanded: csrExpanded }"></text>
</view>
</view>
<!-- 操作记录 -->
<view class="info-section log" v-if="logList.length > 0">
<view class="section-title">操作记录</view>
<view class="sp-list">
<view v-for="log in displayedLogList" :key="log.id" class="sp-item">
<view class="log-header">
<text class="operator">{{ log.operatorName }}</text>
<text class="time">{{ formatTime(log.operationTime) }}</text>
</view>
<view class="log-content">
<text class="content">{{ log.operationContent }}</text>
</view>
<view class="log-detail" v-if="log.beforeChange || log.afterChange">
<u-button text="详情" size="mini" @click="showLogDetail(log)" />
</view>
</view>
</view>
<!-- 更多按钮 -->
<view v-if="logList.length > 2" class="more-button" @click="toggleLogExpanded">
<text class="more-text">
{{ logExpanded ? '收起' : `更多(${logList.length - 2})` }}
</text>
<text class="more-icon" :class="{ expanded: logExpanded }"></text>
</view>
</view>
<!-- 操作记录详情弹窗 -->
<u-popup :show="showLogDetailModal" @close="showLogDetailModal = false" mode="center">
<view class="detail-modal">
<view class="detail-header">
<text class="detail-title">操作详情</text>
<u-button text="关闭" @click="showLogDetailModal = false" />
</view>
<view class="detail-content">
<view class="detail-item" v-if="currentLog.beforeChange">
<text class="detail-label">变更前</text>
<text class="detail-value">{{ currentLog.beforeChange }}</text>
</view>
<view class="detail-item" v-if="currentLog.afterChange">
<text class="detail-label">变更后</text>
<text class="detail-value">{{ currentLog.afterChange }}</text>
</view>
<view class="detail-item" v-if="currentLog.remark">
<text class="detail-label">备注</text>
<text class="detail-value">{{ currentLog.remark }}</text>
</view>
</view>
</view>
</u-popup>
</view>
</template>
<script setup lang="ts">
import dayjs from "dayjs";
import { getLcglApi } from "@/api/base/lcglSpApi";
import { useDataStore } from "@/store/modules/data";
const { setLcgl } = useDataStore();
//
const props = withDefaults(defineProps<{
ywId: string,
ywType: string
}>(), {
ywId: '',
ywType: ''
});
const sqrSp = ref<any>({});
const sprSpList = ref<any>([]);
const csrSpList = ref<any>([]);
const logList = ref<any>([]);
//
const csrExpanded = ref(false);
//
const logExpanded = ref(false);
//
const displayedcsrList = computed(() => {
if (csrExpanded.value || csrSpList.value.length <= 2) {
return csrSpList.value;
}
return csrSpList.value.slice(0, 2);
});
//
const displayedLogList = computed(() => {
if (logExpanded.value || logList.value.length <= 2) {
return logList.value;
}
return logList.value.slice(0, 2);
});
const showLogDetailModal = ref(false);
const currentLog = ref<any>({});
//
const showLogDetail = (log: any) => {
currentLog.value = log;
showLogDetailModal.value = true;
};
//
const toggleCsrExpanded = () => {
csrExpanded.value = !csrExpanded.value;
};
//
const toggleLogExpanded = () => {
logExpanded.value = !logExpanded.value;
};
//
const getSqrStatusText = (status: any) => {
const statusMap: Record<string, string> = {
apply: "已申请",
};
return statusMap[status] || "未知";
};
//
const getSqrStatusClass = (status: any) => {
const statusMap: Record<string, string> = {
apply: "status-read",
};
return statusMap[status] || "status-default";
};
//
const getSprStatusClass = (status: any) => {
const statusMap: Record<string, string> = {
pending: "status-pending",
approved: "status-approved",
rejected: "status-rejected",
skipped: "status-skipped",
stop: "status-stop",
transfer: "status-transfer",
};
return statusMap[status] || "status-default";
};
//
const getSprStatusText = (status: any) => {
const statusMap: Record<string, string> = {
pending: "待审批",
approved: "已同意",
rejected: "已驳回",
skipped: "已跳过",
stop: "已终止",
transfer: "已转办",
};
return statusMap[status] || "未知";
};
//
const getCsrStatusClass = (status: any) => {
const statusMap: Record<string, string> = {
unread: "status-unread",
read: "status-read",
};
return statusMap[status] || "status-default";
};
//
const getCsrStatusText = (status: any) => {
const statusMap: Record<string, string> = {
unread: "未读",
read: "已读",
};
return statusMap[status] || "未知";
};
//
const loadLcgl = async () => {
if (!props.ywId || !props.ywType) return;
try {
const params = {
ywId: props.ywId,
ywType: props.ywType,
}
// API
const res = await getLcglApi(params);
sqrSp.value = {};
sqrSp.value = [];
csrSpList.value = [];
logList.value = [];
setLcgl(res.result || {});
if (res.resultCode === 1 && res.result) {
sqrSp.value = res.result.sqrSp || {};
sprSpList.value = res.result.sprSpList || [];
csrSpList.value = res.result.csrSpList || [];
logList.value = res.result.logList || [];
}
} catch (error) {
}
};
//
const formatTime = (time: string | Date) => {
if (!time) return '';
return dayjs(time).format('YYYY-MM-DD HH:mm');
};
// ywId
watch(() => props.ywId, (newVal) => {
if (newVal) {
loadLcgl();
}
});
//
if (props.ywId) {
loadLcgl();
}
</script>
<style lang="scss" scoped>
.lcgl-info {
padding: 0 30rpx;
.info-section {
margin-bottom: 30rpx;
padding: 30rpx;
background: #fff;
border-radius: 16rpx;
box-shadow: 0 4rpx 16rpx rgba(0, 0, 0, 0.1);
&.sqr {
/* 申请人区域特殊样式可以在这里添加 */
background-color: white;
}
&.spr {
/* 审批人区域特殊样式可以在这里添加 */
background-color: white;
}
&.csr {
/* 抄送人区域特殊样式可以在这里添加 */
background-color: white;
}
&.log {
margin-bottom: 80rpx; //
}
}
.section-title {
font-size: 32rpx;
font-weight: bold;
margin-bottom: 30rpx;
color: #333;
border-bottom: 4rpx solid #007aff;
padding-bottom: 10rpx;
}
.sp-list {
/* 列表容器样式 */
background-color: white;
}
.sp-item {
display: flex;
flex-direction: column;
padding: 20rpx;
border: 2rpx solid #eee;
border-radius: 8rpx;
margin-bottom: 20rpx;
.sp-info {
display: flex;
align-items: center;
.name {
font-weight: 500;
margin-right: 16rpx;
}
.dept {
color: #666;
font-size: 24rpx;
margin-right: 16rpx;
}
.status {
padding: 4rpx 12rpx;
border-radius: 8rpx;
font-size: 24rpx;
margin-left: auto;
&.status-pending {
background-color: #fff7e6;
color: #fa8c16;
}
&.status-approved {
background-color: #f6ffed;
color: #52c41a;
}
&.status-rejected {
background-color: #fff1f0;
color: #f5222d;
}
&.status-withdrawn {
background-color: #f9f9f9;
color: #8c8c8c;
}
&.status-skipped {
background-color: #f0f5ff;
color: #2f54eb;
}
&.status-stop {
background-color: #fff1f0;
color: #ff4d4f;
}
&.status-transfer {
background-color: #f9f0ff;
color: #722ed1;
}
&.status-default {
background-color: #fafafa;
color: #595959;
}
}
}
}
.sp-detail {
margin-top: 20rpx;
padding: 20rpx;
background: #f8f9fa;
border-radius: 8rpx;
border-left: 6rpx solid #007aff;
.approval-info {
display: flex;
margin-bottom: 16rpx;
&:last-child {
margin-bottom: 0;
}
.info-label {
width: 160rpx;
color: #666;
font-size: 24rpx;
flex-shrink: 0;
}
.info-value {
flex: 1;
color: #333;
font-size: 24rpx;
word-break: break-all;
}
}
}
.log-header {
display: flex;
justify-content: space-between;
margin-bottom: 16rpx;
.operator {
font-weight: 500;
color: #007aff;
}
.time {
font-size: 24rpx;
color: #666;
}
}
.log-content {
margin-bottom: 16rpx;
.content {
color: #333;
}
}
.log-detail {
margin-top: 10rpx;
}
.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);
}
}
}
.detail-modal {
width: 80vw;
max-width: 800rpx;
padding: 40rpx;
.detail-header {
display: flex;
justify-content: space-between;
align-items: center;
margin-bottom: 40rpx;
.detail-title {
font-size: 32rpx;
font-weight: bold;
}
}
.detail-content {
.detail-item {
margin-bottom: 30rpx;
.detail-label {
font-weight: 500;
color: #666;
margin-right: 20rpx;
}
.detail-value {
color: #333;
word-break: break-all;
}
}
}
}
}
</style>

View File

@ -0,0 +1,562 @@
<template>
<view class="spr-list-container">
<!-- 原始审批人 -->
<view class="section">
<view class="section-header">
<text class="section-title">原审批人</text>
</view>
<view class="list-content">
<view v-for="(spr, index) in srcSprList" :key="index" class="list-item readonly">
<view class="item-info">
<text class="item-name">{{ spr.jsxm }}</text>
</view>
<view class="item-status">
<text class="status-text" :class="getSprStatusClass(spr.approveStatus)">
{{ getSprStatusText(spr.approveStatus) }}
</text>
</view>
</view>
<view v-if="srcSprList.length === 0" class="empty-tip">
<text>暂无原审批人</text>
</view>
</view>
</view>
<!-- 原始抄送人 -->
<view class="section">
<view class="section-header">
<text class="section-title">原抄送人</text>
</view>
<view class="list-content">
<view v-for="(csr, index) in srcCsrList" :key="index" class="list-item readonly">
<view class="item-info">
<text class="item-name">{{ csr.jsxm }}</text>
</view>
</view>
<view v-if="srcCsrList.length === 0" class="empty-tip">
<text>暂无原抄送人</text>
</view>
</view>
</view>
<!-- 审批人列表 -->
<view class="section">
<view class="section-header">
<text class="section-title">审批转办人</text>
<!-- 审批人选择器 -->
<BasicJsPicker
ref="approverPickerRef"
:customTrigger="true"
:multiple="true"
:excludeIds="getExcludeApproverIds()"
:defaultValue="approvers"
title="选择审批转办人"
placeholder="请选择审批转办人"
searchPlaceholder="搜索审批转办人"
@change="handleApproverChange"
>
<template #trigger>
<view class="add-btn">
<text class="add-icon">+</text>
<text class="add-text">添加审批转办人</text>
</view>
</template>
</BasicJsPicker>
</view>
<view class="list-content">
<view v-for="(spr, index) in approvers" :key="spr.id" class="list-item">
<view class="item-info">
<text class="item-name">{{ spr.jsxm }}</text>
</view>
<view class="item-actions">
<!-- 上移箭头 -->
<uni-icons
v-if="index > 0"
type="top"
size="18"
color="#666"
@click="moveApproverUp(index)"
class="action-icon"
></uni-icons>
<!-- 下移箭头 -->
<uni-icons
v-if="index < approvers.length - 1"
type="bottom"
size="18"
color="#666"
@click="moveApproverDown(index)"
class="action-icon"
></uni-icons>
<!-- 删除图标改为垃圾桶图标 -->
<uni-icons
type="trash"
size="18"
color="#666"
@click="removeApprover(index)"
class="action-icon"
></uni-icons>
</view>
</view>
<view v-if="approvers.length === 0" class="empty-tip">
<text>暂无审批人请添加</text>
</view>
</view>
</view>
<!-- 抄送人列表 -->
<view class="section">
<view class="section-header">
<text class="section-title">新增抄送人</text>
<!-- 抄送人选择器 -->
<BasicJsPicker
ref="ccPickerRef"
:customTrigger="true"
:multiple="true"
:excludeIds="getExcludeCcIds()"
:defaultValue="ccList"
title="选择抄送人"
placeholder="请选择抄送人"
searchPlaceholder="搜索抄送人"
@change="handleCcChange"
>
<template #trigger>
<view class="add-btn">
<text class="add-icon">+</text>
<text class="add-text">添加抄送人</text>
</view>
</template>
</BasicJsPicker>
</view>
<view class="list-content">
<view v-for="(csr, index) in ccList" :key="csr.id" class="list-item">
<view class="item-info">
<text class="item-name">{{ csr.jsxm }}</text>
</view>
<view class="item-actions">
<text class="delete-btn" @click="removeCc(index)">删除</text>
</view>
</view>
<view v-if="ccList.length === 0" class="empty-tip">
<text>暂无抄送人请添加</text>
</view>
</view>
</view>
</view>
</template>
<script lang="ts" setup>
import { ref, onMounted } from "vue";
import { useCommonStore } from "@/store/modules/common";
import { useDataStore } from "@/store/modules/data";
import BasicJsPicker from "@/components/BasicJsPicker/Picker.vue";
const { getLcgl } = useDataStore();
// JsVo
interface JsInfo {
id: string;
jsxm: string;
lxdh?: string;
sfzh?: string;
headPic?: string;
userId?: number;
deptId?: string;
approveStatus?: string;
approveRemark?: string;
setId?: string;
sort?: number;
}
//
const normalizeTeacherData = (js: any, sp: any) => {
return {
id: js.id || js.value,
jsxm: js.jsxm || js.label,
lxdh: js.lxdh,
sfzh: js.sfzh,
headPic: js.headPic,
userId: js.userId,
deptId: js.deptId,
approveStatus: sp?.approveStatus,
approveRemark: sp?.approveRemark,
setId: sp?.setId,
sort: sp?.sort,
};
};
// emit
const emit = defineEmits(["change"]);
// - 使defaultValue
const approvers = ref<JsInfo[]>([]);
const ccList = ref<JsInfo[]>([]);
const srcSprList = ref<any[]>([]);
const srcCsrList = ref<any[]>([]);
//
const approverPickerRef = ref();
const ccPickerRef = ref();
// common store
const commonStore = useCommonStore();
//
const getSprStatusClass = (status: any) => {
const statusMap: Record<string, string> = {
pending: "status-pending",
approved: "status-approved",
rejected: "status-rejected",
skipped: "status-skipped",
stop: "status-stop",
transfer: "status-transfer",
};
return statusMap[status] || "status-default";
};
//
const getSprStatusText = (status: any) => {
const statusMap: Record<string, string> = {
pending: "待审批",
approved: "已同意",
rejected: "已驳回",
skipped: "已跳过",
stop: "已终止",
transfer: "已转办",
};
return statusMap[status] || "未知";
};
//
const initData = (jsList: any) => {
const srcSprSpList = getLcgl.sprSpList || [];
const srcCsrSpList = getLcgl.csrSpList || [];
//
srcSprList.value = srcSprSpList.map((sp: any) => {
const js = jsList.find((js: any) => js.userId === sp.userId);
return js ? normalizeTeacherData(js, sp) : {};
});
//
srcCsrList.value = srcCsrSpList.map((sp: any) => {
const js = jsList.find((js: any) => js.userId === sp.userId);
return js ? normalizeTeacherData(js, sp) : {};
});
// spListuserId, jsListuserId
approvers.value = [];
ccList.value = [];
};
//
const notifyChange = () => {
emit("change", {
sprList: approvers.value,
csrList: ccList.value,
});
};
//
const handleApproverChange = (selectedTeachers: any[]) => {
if (Array.isArray(selectedTeachers)) {
approvers.value = selectedTeachers;
notifyChange();
uni.showToast({
title: "审批人设置成功",
icon: "success",
});
}
};
//
const handleCcChange = (selectedTeachers: any[]) => {
if (Array.isArray(selectedTeachers)) {
ccList.value = selectedTeachers;
notifyChange();
uni.showToast({
title: "抄送人设置成功",
icon: "success",
});
}
};
//
const removeApprover = (index: number) => {
uni.showModal({
title: "确认删除",
content: `确定要删除审批人"${approvers.value[index].jsxm}"吗?`,
success: (res: any) => {
if (res.confirm) {
approvers.value.splice(index, 1);
notifyChange();
uni.showToast({
title: "删除成功",
icon: "success",
});
}
},
});
};
//
const removeCc = (index: number) => {
uni.showModal({
title: "确认删除",
content: `确定要删除抄送人"${ccList.value[index].jsxm}"吗?`,
success: (res: any) => {
if (res.confirm) {
ccList.value.splice(index, 1);
notifyChange();
uni.showToast({
title: "删除成功",
icon: "success",
});
}
},
});
};
//
const moveApproverUp = (index: number) => {
if (index > 0) {
const temp = approvers.value[index];
approvers.value[index] = approvers.value[index - 1];
approvers.value[index - 1] = temp;
notifyChange();
console.log('Moved up:', index);
}
};
//
const moveApproverDown = (index: number) => {
if (index < approvers.value.length - 1) {
const temp = approvers.value[index];
approvers.value[index] = approvers.value[index + 1];
approvers.value[index + 1] = temp;
notifyChange();
console.log('Moved down:', index);
}
};
// ID
const getExcludeApproverIds = () => {
return srcSprList.value.map((item) => item.id).filter((id) => id);
// const approverIds = approvers.value.map((item) => item.id).filter((id) => id);
// const ccIds = ccList.value.map((item) => item.id).filter((id) => id);
//
// return [...new Set([...approverIds, ...ccIds])];
};
// ID
const getExcludeCcIds = () => {
return srcCsrList.value.map((item) => item.id).filter((id) => id);
// const ccIds = ccList.value.map((item) => item.id).filter((id) => id);
// const approverIds = approvers.value.map((item) => item.id).filter((id) => id);
// //
// return [...new Set([...ccIds, ...approverIds])];
};
//
onMounted(async () => {
try {
//
const res = await commonStore.getAllJsBasicInfoVo();
initData(res.result);
} catch (error) {
console.error("SprList组件初始化失败:", error);
}
});
const getNewSprList = () => {
return approvers.value;
};
const getNewCsrList = () => {
return ccList.value;
};
defineExpose({
getNewSprList,
getNewCsrList,
});
</script>
<style lang="scss" scoped>
.spr-list-container {
.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;
}
.add-btn {
display: flex;
align-items: center;
justify-content: flex-end;
padding: 12rpx 24rpx;
background: #ffffff;
border-radius: 8rpx;
transition: all 0.3s ease;
border: 1rpx solid #ebedf0;
&:active {
background: #f5f5f5;
}
.add-icon {
color: #1890ff;
font-size: 28rpx;
margin-right: 8rpx;
font-weight: bold;
}
.add-text {
color: #1890ff;
font-size: 28rpx;
font-weight: 500;
}
}
}
.list-content {
.list-item {
display: flex;
justify-content: space-between;
align-items: center;
padding: 24rpx;
background: linear-gradient(135deg, #fafafa 0%, #f5f5f5 100%);
border-radius: 12rpx;
margin-bottom: 16rpx;
border: 1rpx solid #ebedf0;
transition: all 0.3s ease;
&:hover {
transform: translateY(-2rpx);
box-shadow: 0 8rpx 24rpx rgba(0, 0, 0, 0.1);
}
//
&.readonly {
background: linear-gradient(135deg, #ffffff 0%, #fafafa 100%);
}
.item-info {
flex: 1;
.item-name {
font-size: 30rpx;
color: #262626;
font-weight: 500;
display: block;
}
}
.item-status {
.status-text {
font-size: 24rpx;
padding: 6rpx 12rpx;
border-radius: 6rpx;
font-weight: 500;
&.status-pending {
background-color: #fff7e6;
color: #fa8c16;
}
&.status-approved {
background-color: #f6ffed;
color: #52c41a;
}
&.status-rejected {
background-color: #fff1f0;
color: #f5222d;
}
&.status-withdrawn {
background-color: #f9f9f9;
color: #8c8c8c;
}
&.status-skipped {
background-color: #f0f5ff;
color: #2f54eb;
}
&.status-stop {
background-color: #fff1f0;
color: #ff4d4f;
}
&.status-transfer {
background-color: #f9f0ff;
color: #722ed1;
}
&.status-default {
background-color: #fafafa;
color: #595959;
}
}
}
.item-actions {
display: flex;
align-items: center;
gap: 16rpx;
.action-icon {
padding: 6rpx;
border-radius: 4rpx;
&:active {
background-color: #eee;
}
}
.delete-btn {
color: #ff4d4f;
font-size: 28rpx;
padding: 8rpx 16rpx;
background: rgba(255, 77, 79, 0.1);
border-radius: 6rpx;
transition: all 0.3s ease;
&:active {
background: rgba(255, 77, 79, 0.2);
}
}
}
}
.empty-tip {
text-align: center;
padding: 60rpx 0;
color: #8c8c8c;
font-size: 28rpx;
background: #fafafa;
border-radius: 12rpx;
border: 2rpx dashed #ebedf0;
}
}
}
}
</style>

View File

@ -89,9 +89,7 @@ const currentTab = ref('A'); // 0: 待办, 1: 已办
const fetchListData = async (tabIndex: string) => {
setParam({
dbZt: tabIndex,
jsrId: getJs.id,
sidx: "xxtstime",
sord: "desc",
jsrId: getJs.id
});
reload();
};

View File

@ -36,7 +36,7 @@
<text class="label">是否离校:</text>
<text class="value">{{ qjData.sflx === 1 ? '是' : '否' }}</text>
</view>
<view class="info-column">
<view class="info-column pb-5">
<text class="label">请假事由:</text>
<text class="value">{{ qjData.qjsy }}</text>
</view>
@ -48,7 +48,7 @@
</view>
<!-- 审批流程 -->
<LcglSpList :yw-id="qjId" yw-type="XS_QJ" />
<LcglSp :yw-id="qjId" yw-type="XS_QJ" />
</view>
<template #bottom>
<view class="white-bg-color py-5">
@ -69,7 +69,7 @@
import { ref, onMounted } from 'vue';
import { useDataStore } from "@/store/modules/data";
import { getXsQjDetailApi } from "@/api/base/server";
import LcglSpList from "@/components/LcglSpList/index.vue";
import LcglSp from "@/components/LcglSp/index.vue";
const { getData } = useDataStore();
@ -97,12 +97,7 @@ const loadQjDetail = async () => {
};
const goHome = () => {
uni.reLaunch({ url: '/pages/index/index' });
};
//
const navigateBack = () => {
uni.navigateBack();
uni.reLaunch({ url: '/pages/base/message/index' });
};
//

View File

@ -29,55 +29,36 @@
<text class="label">是否离校:</text>
<text class="value">{{ qjData.sflx === 1 ? '是' : '否' }}</text>
</view>
<view class="info-column">
<view class="info-column pb-5">
<text class="label">请假事由:</text>
<text class="value">{{ qjData.qjsy }}</text>
</view>
<view class="info-row">
<text class="label">申请时间:</text>
<text class="value">{{ qjData.createdTime }}</text>
</view>
</view>
<!-- 审批意见卡片 -->
<view class="info-card">
<view class="card-header">
<text class="applicant-name">审批意见</text>
</view>
<view class="divider"></view>
<view class="card-body">
<BasicForm @register="register" />
</view>
</view>
<!-- 审批流程 -->
<LcglSp :yw-id="qjId" yw-type="XS_QJ" />
</view>
<template #bottom>
<view class="white-bg-color py-5">
<view class="flex-row items-center pb-10 pt-5">
<u-button
text="取消"
class="ml-15 mr-7"
:plain="true"
@click="navigateBack"
/>
<u-button
text="提交"
class="mr-15 mr-7"
type="primary"
@click="submit"
/>
</view>
</view>
<YwConfirm :spApi="xsQjSpApi" :stopApi="xsQjStopApi"
:transferApi="xsQjTransferApi" :params="spParams" />
</template>
</BasicLayout>
</template>
<script setup lang="ts">
import { onLoad } from "@dcloudio/uni-app";
import { useForm } from "@/components/BasicForm/hooks/useForm";
import { navigateBack } from "@/utils/uniapp";
import { xsQjFindByIdApi, xsQjSpApi } from "@/api/base/server";
import { xsQjFindByIdApi, xsQjSpApi, xsQjStopApi, xsQjTransferApi } from "@/api/base/server";
import { useUserStore } from "@/store/modules/user";
import { useDataStore } from "@/store/modules/data";
import { ref, nextTick } from "vue";
import { xxtsFindByIdApi } from "@/api/base/xxtsApi";
import LcglSp from "@/components/LcglSp/index.vue";
import YwConfirm from "@/pages/components/YwConfirm/index.vue";
import { XkTfPageUtils } from "@/utils/xkTfPageUtils";
const { getJs, loginByOpenId } = useUserStore();
const { getData, setXxts, setData, getXxts } = useDataStore();
@ -85,89 +66,21 @@ const { getData, setXxts, setData, getXxts } = useDataStore();
const dbFlag = ref(false);
// URLID
const qjId = getData.id || '';
const qjId = computed(() => {
return getData.id || '';
})
const [register, { getValue }] = useForm({
schema: [
{
field: "spStatus",
label: "审批意见",
component: "BasicCheckbox",
required: true,
itemProps: {
labelPosition: "top",
},
componentProps: {
data: [
{ value: 'approved', text: "同意" },
{ value: 'rejected', text: "拒绝" },
],
},
},
{
field: "spYj",
label: "审批说明",
component: "BasicInput",
required: true,
itemProps: {
labelPosition: "top",
},
componentProps: {
type: "textarea",
placeholder: "请输入审批说明",
},
},
],
const spParams = computed(() => {
return {
xxtsId: getXxts.id,
ywId: qjId.value
};
});
//
const qjData = computed(() => getData || {});
const xxtsData = ref<any>({})
const submit = async () => {
try {
const formData = await getValue();
if (!formData.spStatus || !formData.spYj) {
uni.showToast({
title: '请填写完整的审批信息',
icon: 'none'
});
return;
}
const params = {
qjId: qjData.value.id,
jsId: getJs.id,
spStatus: formData.spStatus,
spYj: formData.spYj,
};
uni.showLoading({
title: "提交中...",
});
const res = await xsQjSpApi(params);
uni.hideLoading();
uni.showToast({
title: '审批提交成功',
icon: 'success'
});
setTimeout(() => {
navigateBack();
}, 1500);
} catch (error) {
uni.hideLoading();
uni.showToast({
title: '提交失败,请重试',
icon: 'none'
});
console.error('审批提交失败:', error);
}
};
onLoad(async (data: any) => {
//
if (data && data.from && data.from == "db") {
@ -198,12 +111,15 @@ onLoad(async (data: any) => {
// ID
const res = await xsQjFindByIdApi({ id: xxts.xxzbId });
const xsQj = res.result || {};
// TODO:
if (xsQj.spResult != "A" && getXxts && getXxts.dbZt === "A") {
uni.reLaunch({ url: '/pages/base/xs/qj/detail' });
// const flag = await XkTfPageUtils.updateXxts();
} else {
nextTick(() => {
setData(res.result);
setData(xsQj);
});
}
}
} catch (error) {
console.error("获取待办信息失败", error);
// Xxts退

View File

@ -1,93 +1,165 @@
<template>
<view class="white-bg-color py-5">
<view class="flex-row items-center pb-10 pt-5">
<u-button text="终止" class="ml-15 mr-7" :plain="true" @click="showDlg" />
<u-button text="转办" class="mr-15 mr-7" :plain="true" @click="submit" />
<u-button text="驳回" class="ml-15 mr-7" :plain="true" @click="showDlg" />
<view class="white-bg-color py-5 yw-confirm">
<view class="flex-row items-center pt-5 pb-10">
<u-button text="驳回" class="ml-15 mr-7" :plain="true" @click="showDlg('reject')" />
<u-button text="同意" class="mr-15 mr-7" type="primary" @click="submit" />
</view>
<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="mr-15 mr-7" :plain="true" @click="showTransfer" />
</view>
<!-- 驳回弹窗 -->
<u-popup :show="dlgFlag" mode="center" :closeOnClickOverlay="false" @close="closeDlg">
<view class="popup-content">
<view class="popup-header">
<view class="popup-title">驳回原因</view>
<view class="popup-title">{{ dlgTips }}</view>
</view>
<view class="popup-body">
<u-input v-model="rejectReason" type="textarea" placeholder="请填写驳回原因" :autoHeight="true" maxlength="200" class="reject-reason-input" />
<u-input v-model="spRemark" type="textarea" :placeholder="'请填写' + dlgTips" :autoHeight="true" maxlength="200" class="reject-reason-input" />
</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="handleReject">确定</u-button>
<u-button type="primary" @click="handleDlgSubmit">确定</u-button>
</view>
</view>
</u-popup>
<YwTransfer ref="transferRef" @submit="handleTransfer" />
</view>
</template>
<script lang="ts" setup>
import YwTransfer from "../YwTransfer/index.vue";
//
const props = withDefaults(defineProps<{
api: any, // API
spApi: any, // Api
transferApi: any, // Api
stopApi: any, // Api
params: any, //
stausName?: string, //
remarkName?: string, //
approvedValue?: string, //
rejectValue?: string, //
approvedRemark?: string //
approvedRemark?: string //
autoToMessage?: boolean //
}>(), {
api: async (params: any) => {},
spApi: async (params: any) => {},
transferApi: async (params: any) => {},
stopApi: async (params: any) => {},
params: {},
stausName: 'spStatus',
remarkName: 'spRemark',
approvedValue: 'approved',
rejectValue: 'rejected',
approvedRemark: '同意'
approvedRemark: '同意',
autoToMessage: true
});
// emit
const emit = defineEmits(['submit', 'reject'])
const emit = defineEmits(['submit', 'reject', 'stop', 'transfer'])
const transferRef = ref<any>(null);
const dlgFlag = ref(false);
const rejectReason = ref("");
const showDlg = () => {
const dlgType = ref("");
const dlgTips = ref("");
const spRemark = ref("");
const goToMessage = () => {
setTimeout(() => {
uni.reLaunch({ url: '/pages/base/message/index' });
}, 100);
}
const showDlg = (type: string) => {
dlgFlag.value = true;
dlgType.value = type;
if (type === 'reject') {
dlgTips.value = '驳回原因';
} else if (type === 'stop') {
dlgTips.value = '终止原因';
}
};
const closeDlg = () => {
dlgFlag.value = false;
};
const showTransfer = () => {
transferRef.value.showDlg();
};
const submit = async () => {
const params = {
...props.params
};
params[props.stausName] = props.approvedValue;
params[props.remarkName] = "";
params[props.remarkName] = props.approvedRemark;
uni.showLoading({ title: "确认中..." });
await props.api(params);
await props.spApi(params);
uni.hideLoading();
closeDlg();
if (props.autoToMessage) {
goToMessage();
}
emit('submit');
};
//
const handleReject = async () => {
if (!rejectReason.value.trim()) {
uni.showToast({ title: "请填写驳回意见", icon: "none" });
const handleReject = async (params: any) => {
uni.showLoading({ title: "正在驳回..." });
await props.spApi(params);
uni.hideLoading();
emit('reject');
};
//
const handleStop = async (params: any) => {
uni.showLoading({ title: "正在终止..." });
await props.stopApi(params);
uni.hideLoading();
emit('stop');
}
//
const handleTransfer = 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');
};
const handleDlgSubmit = async () => {
if (!spRemark.value || !spRemark.value.trim()) {
uni.showToast({ title: "请填写" + dlgTips.value, icon: "none" });
return;
}
const params = {
...props.params
};
params[props.stausName] = props.rejectValue;
params[props.remarkName] = rejectReason.value;
uni.showLoading({ title: "正在驳回..." });
await props.api(params);
uni.hideLoading();
params[props.remarkName] = spRemark.value;
if (dlgType.value === 'reject') {
await handleReject(params);
} else if (dlgType.value === 'stop') {
await handleStop(params);
} else if (dlgType.value === 'transfer') {
await handleTransfer(params);
}
closeDlg();
emit('reject');
if (props.autoToMessage) {
goToMessage();
}
};
defineExpose({
@ -97,6 +169,11 @@ defineExpose({
</script>
<style lang="scss" scoped>
.yw-confirm {
box-shadow: 0 -0.1rem 0.5rem rgba(0, 0, 0, 0.1);
margin-top: 8rpx;
}
.popup-content {
.popup-header {
padding: 20rpx 30rpx;

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

@ -36,8 +36,7 @@
</view>
</view>
<template #bottom>
<YwConfirm :api="jsQjDkQrApi" :params="spParams"
@summit="submit" @reject="handleReject" />
<YwConfirm :api="jsQjDkQrApi" :params="spParams" />
</template>
</BasicLayout>
</template>
@ -55,7 +54,7 @@ import YwConfirm from "@/pages/components/YwConfirm/index.vue";
import { QjPageUtils } from "@/utils/qjPageUtils";
const { getJs } = useUserStore();
const { setData } = useDataStore();
const { setData, getXxts } = useDataStore();
const tabList = ref<any>([{ name: "请假信息", id: "tab-qj" }]);
const curTabIndex = ref(0);
@ -66,8 +65,8 @@ const showDkTab = ref(false);
const spParams = computed(() => {
return {
qjId: qjId.value,
jsId: getJs.id,
xxtsId: getXxts.id,
ywId: qjId.value
};
});
@ -98,19 +97,6 @@ const handleDkListLoaded = (list: any[]) => {
// JsQjDetail
};
const submit = async () => {
setTimeout(() => {
uni.reLaunch({ url: '/pages/base/message/index' });
}, 1000);
};
//
const handleReject = async () => {
setTimeout(() => {
uni.reLaunch({ url: '/pages/base/message/index' });
}, 1000);
};
onLoad(async (data?: any) => {
const ret = await QjPageUtils.init(data);
if (!ret || !ret.success) {

View File

@ -36,8 +36,7 @@
</view>
</view>
<template #bottom>
<YwConfirm :api="jsQjJwcQrApi" :params="spParams"
@summit="submit" @reject="handleReject" />
<YwConfirm :api="jsQjJwcQrApi" :params="spParams" />
</template>
</BasicLayout>
</template>
@ -56,7 +55,7 @@ import YwConfirm from "@/pages/components/YwConfirm/index.vue";
import { QjPageUtils } from "@/utils/qjPageUtils";
const { getJs } = useUserStore();
const { setData } = useDataStore();
const { setData, getXxts } = useDataStore();
const tabList = ref<any>([{ name: "请假信息", id: "tab-qj" }]);
const curTabIndex = ref(0);
@ -67,8 +66,8 @@ const showDkTab = ref(false);
const spParams = computed(() => {
return {
qjId: qjId.value,
jsId: getJs.id,
xxtsId: getXxts.id,
ywId: qjId.value
};
});

View File

@ -1,29 +1,14 @@
<template>
<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 v-show="curTabIndex === 0">
<JsQjDetailInfo
:qjId="qjId"
:dbFlag="dbFlag"
@loadQjData="handleQjDataLoaded"
/>
</view>
<!-- 代课信息 -->
<view v-show="curTabIndex === 1">
<view class="dk-info">
<view v-if="!showDkFlag" class="empty-dk">
<view>{{ showDkEmptyLabel }}</view>
</view>
@ -34,39 +19,29 @@
</view>
<!-- 审批流程 -->
<view v-show="curTabIndex === 2">
<LcglSpList :yw-id="qjId" yw-type="JS_QJ" />
</view>
<LcglSp :yw-id="qjId" yw-type="JS_QJ" />
</view>
<template #bottom>
<view class="white-bg-color py-5">
<view class="px-15">
<BasicForm @register="register" />
</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>
<YwConfirm :spApi="jsQjSpApi" :stopApi="jsQjStopApi"
:transferApi="jsQjTransferApi" :params="spParams" />
</template>
</BasicLayout>
</template>
<script setup lang="ts">
import { onLoad } from "@dcloudio/uni-app";
import { useForm } from "@/components/BasicForm/hooks/useForm";
import { navigateBack } from "@/utils/uniapp";
import { jsQjSpApi } from "@/api/base/jsQjApi";
import { jsQjSpApi, jsQjStopApi, jsQjTransferApi } from "@/api/base/jsQjApi";
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 LcglSpList from "@/components/LcglSpList/index.vue";
import YwConfirm from "@/pages/components/YwConfirm/index.vue";
import LcglSp from "@/components/LcglSp/index.vue";
import { QjPageUtils } from "@/utils/qjPageUtils";
const { getJs } = useUserStore();
const { setData } = useDataStore();
const { setData, getXxts } = useDataStore();
const tabList = ref<any>([
{ name: "请假信息", id: "tab-qj" },
@ -80,37 +55,11 @@ const qjId = ref('');
const showDkFlag = ref(false);
const showDkEmptyLabel = ref('');
const [register, { getValue }] = useForm({
schema: [
{
field: "spStatus",
label: "审批意见",
component: "BasicCheckbox",
required: true,
itemProps: {
labelPosition: "top",
},
componentProps: {
data: [
{ value: 'approved', text: "同意" },
{ value: 'rejected', text: "拒绝" },
],
},
},
{
field: "spRemark",
label: "审批说明",
component: "BasicInput",
required: true,
itemProps: {
labelPosition: "top",
},
componentProps: {
type: "textarea",
placeholder: "请输入审批说明",
},
},
],
const spParams = computed(() => {
return {
xxtsId: getXxts.id,
ywId: qjId.value
};
});
// Tab
@ -134,48 +83,6 @@ const handleDkListLoaded = (list: any[]) => {
// JsQjDetail
};
const submit = async () => {
try {
const formData = await getValue();
if (!formData.spStatus || !formData.spRemark) {
uni.showToast({
title: '请填写完整的审批信息',
icon: 'none'
});
return;
}
const params = {
qjId: qjId.value,
jsId: getJs.id,
spStatus: formData.spStatus,
spRemark: formData.spRemark,
};
uni.showLoading({
title: "提交中...",
});
const res = await jsQjSpApi(params);
uni.hideLoading();
uni.showToast({
title: '审批提交成功',
icon: 'success'
});
setTimeout(() => {
uni.reLaunch({ url: '/pages/base/message/index' });
}, 1000);
} catch (error) {
uni.hideLoading();
uni.showToast({
title: '提交失败,请重试',
icon: 'none'
});
console.error('审批提交失败:', error);
}
};
onLoad(async (data?: any) => {
const ret = await QjPageUtils.init(data);
if (!ret || !ret.success) {

View File

@ -26,8 +26,8 @@
<LcglSpList :yw-id="xkTf.id" yw-type="XK_TF" />
</view>
<template #bottom>
<YwConfirm :api="xkTfSpApi" :params="spParams"
@summit="submit" @reject="handleReject" v-if="xkTf.id" />
<YwConfirm :spApi="xkTfSpApi" :stopApi="xkTfStopApi"
:transferApi="xkTfTransferApi" :params="spParams" v-if="xkTf.id" />
</template>
</BasicLayout>
</template>
@ -42,7 +42,7 @@ import XkPaySuccessXkkc from "../components/XkPaySuccessXkkc/index.vue"
import LcglSpList from "@/components/LcglSpList/index.vue";
import PreviewImage from "@/components/PreviewImage/index.vue";
import YwConfirm from "@/pages/components/YwConfirm/index.vue";
import { getXkTfDetailByIdApi, xkTfSpApi } from "@/api/base/xkTfApi";
import { getXkTfDetailByIdApi, xkTfSpApi, xkTfStopApi, xkTfTransferApi } from "@/api/base/xkTfApi";
import { XkTfPageUtils } from "@/utils/xkTfPageUtils";
const { getJs } = useUserStore();
const { setTf, getXxts } = useDataStore();
@ -57,8 +57,8 @@ const xkTfId = ref('');
const spParams = computed(() => {
return {
xkTfId: xkTfId.value,
jsId: getJs.id,
xxtsId: getXxts.id,
ywId: xkTfId.value
};
});
@ -101,15 +101,6 @@ const loadData = async (id: string) => {
}
};
const submit = async () => {
goHome();
};
//
const handleReject = async () => {
goHome();
};
onLoad(async (data?: any) => {
const ret = await XkTfPageUtils.init(data);
if (!ret || !ret.success) {

View File

@ -53,9 +53,12 @@ export const useCommonStore = defineStore({
},
// 所有教师基础信息Vo版本
async getAllJsBasicInfoVo(): Promise<any> {
// if (!this.data.allJsBasicInfoVo) {
this.data.allJsBasicInfoVo = await jsFindAllBasicInfoVo();
// }
if (!this.data.allJsBasicInfoVo) {
const res = await jsFindAllBasicInfoVo();
if (res.resultCode == 1 && res.result && res.result.length > 0) {
this.data.allJsBasicInfoVo = res;
}
}
return Promise.resolve(this.data.allJsBasicInfoVo);
},
// 获取教师列表Vo版本用于审批人/抄送人选择)

View File

@ -10,7 +10,8 @@ export const useDataStore = defineStore({
file: {},
xs: {}, // 学生专用
jcBz: {}, // 就餐标准
tf: {}
tf: {}, // 退费时使用
lcgl: {}, // 流程管理使用
}),
getters: {
getData(): any {
@ -37,6 +38,9 @@ export const useDataStore = defineStore({
getTf(): any {
return this.tf;
},
getLcgl(): any {
return this.lcgl;
},
},
actions: {
setData(data: any) {
@ -62,6 +66,9 @@ export const useDataStore = defineStore({
},
setTf(data: any) {
this.tf = data;
},
setLcgl(data: any) {
this.lcgl = data;
}
},
persist: {