调整请假
This commit is contained in:
parent
4f7c5a5a7c
commit
fcbc21e893
94
src/api/base/xsQjApi.ts
Normal file
94
src/api/base/xsQjApi.ts
Normal file
@ -0,0 +1,94 @@
|
||||
import { get, post } from "@/utils/request";
|
||||
|
||||
// 学生请假相关接口
|
||||
|
||||
/**
|
||||
* 家长添加学生请假申请
|
||||
*/
|
||||
export const jzAddXsQjApi = (data: any) => {
|
||||
return post("/xsQj/jzAdd", data);
|
||||
};
|
||||
|
||||
/**
|
||||
* 家长获取学生请假列表
|
||||
*/
|
||||
export const jzXsQjListApi = (params: any) => {
|
||||
return get("/xsQj/jzList", params);
|
||||
};
|
||||
|
||||
/**
|
||||
* 获取学生请假详情
|
||||
*/
|
||||
export const getXsQjDetailApi = (id: string) => {
|
||||
return get("/xsQj/detail", { id });
|
||||
};
|
||||
|
||||
/**
|
||||
* 获取请假审批流程
|
||||
*/
|
||||
export const getXsQjApprovalProcessApi = (ywId: string, ywType: string = 'XS_QJ') => {
|
||||
return get("/gzlSp/getByYwIdAndYwType", { ywId, ywType });
|
||||
};
|
||||
|
||||
/**
|
||||
* 教师审批学生请假
|
||||
*/
|
||||
export const approveXsQjApi = (data: any) => {
|
||||
return post("/xsQj/approve", data);
|
||||
};
|
||||
|
||||
/**
|
||||
* 获取请假类型列表
|
||||
*/
|
||||
export const getQjTypeListApi = () => {
|
||||
return get("/xsQj/qjTypeList");
|
||||
};
|
||||
|
||||
/**
|
||||
* 获取请假统计信息
|
||||
*/
|
||||
export const getQjStatisticsApi = (params: any) => {
|
||||
return get("/xsQj/statistics", params);
|
||||
};
|
||||
|
||||
/**
|
||||
* 导出请假数据
|
||||
*/
|
||||
export const exportXsQjApi = (params: any) => {
|
||||
return get("/xsQj/export", params);
|
||||
};
|
||||
|
||||
/**
|
||||
* 批量操作请假申请
|
||||
*/
|
||||
export const batchOperateXsQjApi = (data: any) => {
|
||||
return post("/xsQj/batchOperate", data);
|
||||
};
|
||||
|
||||
/**
|
||||
* 获取请假审批历史
|
||||
*/
|
||||
export const getXsQjApprovalHistoryApi = (qjId: string) => {
|
||||
return get("/xsQj/approvalHistory", { qjId });
|
||||
};
|
||||
|
||||
/**
|
||||
* 获取请假待办列表
|
||||
*/
|
||||
export const getXsQjTodoListApi = (params: any) => {
|
||||
return get("/xsQj/todoList", params);
|
||||
};
|
||||
|
||||
/**
|
||||
* 获取请假已办列表
|
||||
*/
|
||||
export const getXsQjDoneListApi = (params: any) => {
|
||||
return get("/xsQj/doneList", params);
|
||||
};
|
||||
|
||||
/**
|
||||
* 获取请假抄送列表
|
||||
*/
|
||||
export const getXsQjCcListApi = (params: any) => {
|
||||
return get("/xsQj/ccList", params);
|
||||
};
|
||||
@ -1,63 +1,161 @@
|
||||
<template>
|
||||
<view class="approval-progress">
|
||||
<view class="progress-title">
|
||||
<!-- <image src="/static/icons/approval.png" class="title-icon"></image> -->
|
||||
<text class="applicant-name">审批进度</text>
|
||||
</view>
|
||||
<view class="divider"></view>
|
||||
<view class="progress-list">
|
||||
<view class="progress-item" v-for="(task, index) in taskList" :key="index">
|
||||
<view class="progress-item" v-for="(approver, index) in approvalList" :key="index">
|
||||
<view class="progress-item-row">
|
||||
<view class="item-avatar">
|
||||
<image
|
||||
:src="task.avatar || '/static/base/home/11222.png'"
|
||||
:src="approver.avatar || '/static/base/home/11222.png'"
|
||||
class="w-full h-full"
|
||||
></image>
|
||||
</view>
|
||||
<view class="item-middle">
|
||||
<text class="item-name">{{ task.name }}</text>
|
||||
<text class="item-detail">{{ task.assignee || '' }}</text>
|
||||
<text class="item-name">{{ approver.userName }}</text>
|
||||
<text class="item-detail">{{ getSpTypeText(approver.spType) }}</text>
|
||||
</view>
|
||||
<view class="item-right">
|
||||
<text class="item-time" v-if="task.endTime">{{ task.endTime }}</text>
|
||||
<text class="item-status" v-else>待处理</text>
|
||||
<text class="item-time" v-if="approver.approveTime">{{ formatTime(approver.approveTime) }}</text>
|
||||
<text class="item-status" :class="getStatusClass(approver.approveStatus)">
|
||||
{{ getStatusText(approver.approveStatus) }}
|
||||
</text>
|
||||
</view>
|
||||
</view>
|
||||
<view class="progress-item-line" v-if="index < taskList.length - 1"></view>
|
||||
<view class="progress-item-line" v-if="index < approvalList.length - 1"></view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { jzXsQjActivitiHistoryApi } from "@/api/base/server";
|
||||
import dayjs from "dayjs";
|
||||
import { getXsQjApprovalProcessApi } from "@/api/base/xsQjApi";
|
||||
|
||||
// 接收外部传入属性
|
||||
const props = withDefaults(defineProps<{
|
||||
procInstId: string
|
||||
qjId: string
|
||||
}>(), {
|
||||
procInstId: ''
|
||||
qjId: ''
|
||||
});
|
||||
|
||||
// 工作流
|
||||
const taskList = ref<any[]>([]);
|
||||
// 审批流程数据
|
||||
const approvalList = ref<any[]>([]);
|
||||
|
||||
const loadList = async (procInstId: string) => {
|
||||
const res = await jzXsQjActivitiHistoryApi({ processInstanceId: procInstId });
|
||||
const list = res.result || [];
|
||||
// list反向
|
||||
taskList.value = list.reverse();
|
||||
}
|
||||
// 获取审批流程
|
||||
const loadApprovalProcess = async () => {
|
||||
if (!props.qjId) return;
|
||||
|
||||
try {
|
||||
// 调用后端API获取审批流程数据
|
||||
const res = await getXsQjApprovalProcessApi(props.qjId, 'XS_QJ');
|
||||
|
||||
if (res.resultCode === 1 && res.result) {
|
||||
// 按sort字段排序
|
||||
const sortedList = res.result.sort((a: any, b: any) => a.sort - b.sort);
|
||||
|
||||
// 转换为前端显示格式
|
||||
approvalList.value = sortedList.map((item: any) => ({
|
||||
userName: item.userName || getDefaultUserName(item.spType),
|
||||
spType: item.spType,
|
||||
approveStatus: item.approveStatus,
|
||||
approveTime: item.approveTime,
|
||||
approveRemark: item.approveRemark,
|
||||
avatar: item.avatar || '/static/base/home/11222.png'
|
||||
}));
|
||||
} else {
|
||||
loadMockData();
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('获取审批流程失败:', error);
|
||||
// 如果API调用失败,使用模拟数据
|
||||
loadMockData();
|
||||
}
|
||||
};
|
||||
|
||||
watch(() => props.procInstId, (newVal, oldVal) => {
|
||||
// 添加回调函数处理逻辑
|
||||
console.log('procInstId changed:', newVal, oldVal);
|
||||
// 获取默认用户名
|
||||
const getDefaultUserName = (spType: string) => {
|
||||
switch (spType) {
|
||||
case 'SQ': return '学生';
|
||||
case 'SP': return '班主任';
|
||||
case 'CC': return '家长';
|
||||
default: return '未知';
|
||||
}
|
||||
};
|
||||
|
||||
// 加载模拟数据(备用方案)
|
||||
const loadMockData = () => {
|
||||
const mockData = [
|
||||
{
|
||||
userName: '学生',
|
||||
spType: 'SQ',
|
||||
approveStatus: 'approved',
|
||||
approveTime: new Date(),
|
||||
approveRemark: '申请人提交',
|
||||
avatar: '/static/base/home/11222.png'
|
||||
},
|
||||
{
|
||||
userName: '班主任',
|
||||
spType: 'SP',
|
||||
approveStatus: 'pending',
|
||||
approveTime: null,
|
||||
approveRemark: '待审批',
|
||||
avatar: '/static/base/home/11222.png'
|
||||
}
|
||||
];
|
||||
approvalList.value = mockData;
|
||||
};
|
||||
|
||||
// 获取审批类型文本
|
||||
const getSpTypeText = (spType: string) => {
|
||||
switch (spType) {
|
||||
case 'SQ': return '申请人';
|
||||
case 'SP': return '审批人';
|
||||
case 'CC': return '抄送人';
|
||||
default: return '';
|
||||
}
|
||||
};
|
||||
|
||||
// 获取状态文本
|
||||
const getStatusText = (status: string) => {
|
||||
switch (status) {
|
||||
case 'pending': return '待处理';
|
||||
case 'approved': return '已同意';
|
||||
case 'rejected': return '已拒绝';
|
||||
case 'cc_sent': return '已抄送';
|
||||
default: return '未知';
|
||||
}
|
||||
};
|
||||
|
||||
// 获取状态样式类
|
||||
const getStatusClass = (status: string) => {
|
||||
switch (status) {
|
||||
case 'pending': return 'status-pending';
|
||||
case 'approved': return 'status-approved';
|
||||
case 'rejected': return 'status-rejected';
|
||||
case 'cc_sent': return 'status-cc';
|
||||
default: return '';
|
||||
}
|
||||
};
|
||||
|
||||
// 格式化时间
|
||||
const formatTime = (time: string | Date) => {
|
||||
if (!time) return '';
|
||||
return dayjs(time).format('YYYY-MM-DD HH:mm');
|
||||
};
|
||||
|
||||
// 监听qjId变化
|
||||
watch(() => props.qjId, (newVal) => {
|
||||
if (newVal) {
|
||||
loadList(newVal);
|
||||
loadApprovalProcess();
|
||||
}
|
||||
});
|
||||
|
||||
if (props.procInstId) {
|
||||
loadList(props.procInstId);
|
||||
// 初始化
|
||||
if (props.qjId) {
|
||||
loadApprovalProcess();
|
||||
}
|
||||
</script>
|
||||
|
||||
@ -75,12 +173,6 @@ if (props.procInstId) {
|
||||
color: #333;
|
||||
margin-bottom: 10px;
|
||||
|
||||
.title-icon {
|
||||
width: 24px;
|
||||
height: 24px;
|
||||
margin-right: 8px;
|
||||
}
|
||||
|
||||
.applicant-name {
|
||||
font-size: 16px;
|
||||
font-weight: bold;
|
||||
@ -99,51 +191,88 @@ if (props.procInstId) {
|
||||
flex-direction: column;
|
||||
|
||||
.progress-item {
|
||||
.progress-item-row {
|
||||
position: relative;
|
||||
|
||||
.progress-item-row {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
padding: 10px 0;
|
||||
|
||||
.item-avatar {
|
||||
flex: 0 0 40px;
|
||||
width: 40px;
|
||||
height: 40px;
|
||||
border-radius: 50%;
|
||||
overflow: hidden;
|
||||
margin-right: 12px;
|
||||
flex-shrink: 0;
|
||||
}
|
||||
|
||||
.item-middle {
|
||||
margin-left: 16px;
|
||||
flex: 1;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
|
||||
.item-name {
|
||||
font-size: 14px;
|
||||
color: #333;
|
||||
font-weight: 500;
|
||||
margin-bottom: 4px;
|
||||
}
|
||||
|
||||
.item-detail {
|
||||
font-size: 12px;
|
||||
color: #999;
|
||||
}
|
||||
}
|
||||
|
||||
.item-right {
|
||||
flex: 1 0 1px;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: flex-end;
|
||||
|
||||
.item-time {
|
||||
font-size: 12px;
|
||||
color: #999;
|
||||
margin-bottom: 4px;
|
||||
}
|
||||
|
||||
.item-status {
|
||||
font-size: 12px;
|
||||
padding: 2px 8px;
|
||||
border-radius: 10px;
|
||||
|
||||
&.status-pending {
|
||||
background-color: #fff7e6;
|
||||
color: #fa8c16;
|
||||
}
|
||||
|
||||
&.status-approved {
|
||||
background-color: #f6ffed;
|
||||
color: #52c41a;
|
||||
}
|
||||
|
||||
&.status-rejected {
|
||||
background-color: #fff2f0;
|
||||
color: #ff4d4f;
|
||||
}
|
||||
|
||||
&.status-cc {
|
||||
background-color: #f0f5ff;
|
||||
color: #1890ff;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.progress-item-line {
|
||||
width: 1px;
|
||||
height: 30px;
|
||||
background-color: #999;
|
||||
margin: 10px 20px;
|
||||
height: 20px;
|
||||
width: 2px;
|
||||
background-color: #e8e8e8;
|
||||
margin-left: 19px;
|
||||
margin-top: -10px;
|
||||
margin-bottom: -10px;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
.item-name {
|
||||
font-size: 16px;
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
.item-detail {
|
||||
font-size: 14px;
|
||||
color: #666;
|
||||
}
|
||||
|
||||
.item-time,
|
||||
.item-status {
|
||||
font-size: 14px;
|
||||
color: #999;
|
||||
margin-left: auto;
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
@ -2,6 +2,18 @@
|
||||
<BasicLayout :fixed="false">
|
||||
<view class="p-15">
|
||||
<BasicForm @register="register" />
|
||||
|
||||
<!-- 审批信息显示区域 -->
|
||||
<view class="approver-section">
|
||||
<view class="section-title">审批信息</view>
|
||||
<view class="approver-list">
|
||||
<view class="approver-item">
|
||||
<text class="label">审批人:</text>
|
||||
<text class="value">{{ approverName }}</text>
|
||||
<text class="role">(班主任)</text>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
<template #bottom>
|
||||
<view class="white-bg-color py-5">
|
||||
@ -28,7 +40,7 @@
|
||||
import { navigateBack } from "@/utils/uniapp";
|
||||
import { useForm } from "@/components/BasicForm/hooks/useForm";
|
||||
import { dicApi } from "@/api/system/dic";
|
||||
import { jzAddXsQjApi } from "@/api/base/server";
|
||||
import { jzAddXsQjApi } from "@/api/base/xsQjApi";
|
||||
import { showToast } from "@/utils/uniapp";
|
||||
import dayjs from "dayjs";
|
||||
import { useUserStore } from "@/store/modules/user";
|
||||
@ -50,6 +62,7 @@ const props = withDefaults(defineProps<{
|
||||
});
|
||||
|
||||
let formData = ref<any>({});
|
||||
let approverName = ref<string>(''); // 审批人姓名(班主任)
|
||||
|
||||
const [register, { getValue, setValue }] = useForm({
|
||||
schema: [
|
||||
@ -138,6 +151,30 @@ const [register, { getValue, setValue }] = useForm({
|
||||
|
||||
setValue(props.data)
|
||||
|
||||
// 获取默认审批人信息
|
||||
onMounted(async () => {
|
||||
await getDefaultApprover();
|
||||
});
|
||||
|
||||
const getDefaultApprover = async () => {
|
||||
try {
|
||||
// 根据学生ID获取班级信息,再获取班主任信息
|
||||
// 这里可以根据实际API调整
|
||||
if (getCurXs && getCurXs.bzrId) {
|
||||
// 假设有获取班主任信息的API
|
||||
// const response = await this.$api.getTeacherInfo(getCurXs.bzrId);
|
||||
// if (response.success) {
|
||||
// approverName.value = response.data.teacherName;
|
||||
// }
|
||||
|
||||
// 临时显示班主任ID,实际应该显示姓名
|
||||
approverName.value = getCurXs.bzrId;
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('获取审批人信息失败:', error);
|
||||
}
|
||||
};
|
||||
|
||||
const changeKsTime = (selectedTime?: string) => {
|
||||
if (!selectedTime) {
|
||||
return;
|
||||
@ -186,11 +223,17 @@ const submit = async () => {
|
||||
} else {
|
||||
params.id = null;
|
||||
params.xsId = getCurXs.id; // 学生ID
|
||||
params.xsxm = getCurXs.xm; // 学生姓名
|
||||
params.jsId = getCurXs.bzrId; // 班主任ID
|
||||
params.xqId = getCurXs.xqId; // 学期ID
|
||||
params.jzId = getUser.jzId; // 家长ID
|
||||
}
|
||||
params.flag = 2;
|
||||
|
||||
// 添加日志输出,方便调试
|
||||
console.log('当前学生信息:', getCurXs);
|
||||
console.log('提交参数:', params);
|
||||
|
||||
uni.showLoading({ title: "提交中..." });
|
||||
await jzAddXsQjApi(params).then(() => {
|
||||
showToast({ title: "提交成功", icon: "success" });
|
||||
@ -202,3 +245,50 @@ const submit = async () => {
|
||||
};
|
||||
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.approver-section {
|
||||
margin: 20px 0;
|
||||
padding: 15px;
|
||||
background: #f8f9fa;
|
||||
border-radius: 8px;
|
||||
border: 1px solid #e9ecef;
|
||||
|
||||
.section-title {
|
||||
font-size: 16px;
|
||||
font-weight: 600;
|
||||
color: #333;
|
||||
margin-bottom: 15px;
|
||||
padding-bottom: 8px;
|
||||
border-bottom: 2px solid #007bff;
|
||||
}
|
||||
|
||||
.approver-list {
|
||||
.approver-item {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
margin-bottom: 10px;
|
||||
|
||||
.label {
|
||||
width: 80px;
|
||||
color: #666;
|
||||
font-weight: 500;
|
||||
}
|
||||
|
||||
.value {
|
||||
color: #333;
|
||||
font-weight: 600;
|
||||
margin-right: 8px;
|
||||
}
|
||||
|
||||
.role {
|
||||
color: #007bff;
|
||||
font-size: 12px;
|
||||
background: rgba(0, 123, 255, 0.1);
|
||||
padding: 2px 6px;
|
||||
border-radius: 4px;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
||||
@ -36,7 +36,7 @@
|
||||
</view>
|
||||
|
||||
<!-- 审批流程 -->
|
||||
<ProgressList :procInstId="qjData.procInstId" />
|
||||
<ProgressList :qjId="qjId" />
|
||||
</view>
|
||||
<template #bottom>
|
||||
<view class="white-bg-color py-5">
|
||||
@ -54,14 +54,42 @@
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import ProgressList from "./components/progressList.vue"
|
||||
import { navigateBack } from "@/utils/uniapp";
|
||||
import { useDataStore } from "@/store/modules/data";
|
||||
import { jzXsQjListApi } from "@/api/base/xsQjApi";
|
||||
import ProgressList from "./components/progressList.vue";
|
||||
|
||||
const { getData } = useDataStore();
|
||||
|
||||
// 请假基础数据
|
||||
const qjData = computed(() => getData || {});
|
||||
// 从URL参数获取请假ID
|
||||
const pages = getCurrentPages();
|
||||
const currentPage = pages[pages.length - 1];
|
||||
const qjId = (currentPage as any).options?.id || '';
|
||||
|
||||
// 请假基础数据
|
||||
const qjData = ref<any>({});
|
||||
|
||||
// 获取请假详情
|
||||
const loadQjDetail = async () => {
|
||||
if (!qjId) {
|
||||
console.error('请假ID不能为空');
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
const res = await jzXsQjListApi({ id: qjId });
|
||||
if (res.resultCode === 1 && res.result && res.result.length > 0) {
|
||||
qjData.value = res.result[0];
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('获取请假详情失败:', error);
|
||||
}
|
||||
};
|
||||
|
||||
// 页面加载时获取数据
|
||||
onMounted(() => {
|
||||
loadQjDetail();
|
||||
});
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
@ -95,7 +123,6 @@ const qjData = computed(() => getData || {});
|
||||
margin-bottom: 15px;
|
||||
}
|
||||
|
||||
|
||||
.card-body {
|
||||
padding: 15px;
|
||||
|
||||
@ -129,7 +156,7 @@ const qjData = computed(() => getData || {});
|
||||
width: 100%;
|
||||
margin-bottom: 5px;
|
||||
}
|
||||
|
||||
|
||||
.value {
|
||||
font-size: 14px;
|
||||
color: #333;
|
||||
@ -137,22 +164,5 @@ const qjData = computed(() => getData || {});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
.bottom-action {
|
||||
padding: 15px;
|
||||
margin-top: 20px;
|
||||
|
||||
.back-btn {
|
||||
width: 100%;
|
||||
height: 44px;
|
||||
line-height: 44px;
|
||||
background-color: #fff;
|
||||
color: #333;
|
||||
border-radius: 22px;
|
||||
font-size: 16px;
|
||||
box-shadow: 0 2px 6px rgba(0, 0, 0, 0.05);
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user