学生请假调整
This commit is contained in:
parent
091411cda0
commit
409f9f5108
@ -52,7 +52,7 @@
|
|||||||
</view>
|
</view>
|
||||||
</view>
|
</view>
|
||||||
</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">抄送人({{ csrSpList.length || 0 }})</view>
|
<view class="section-title">抄送人({{ csrSpList.length || 0 }})</view>
|
||||||
<view class="sp-list">
|
<view class="sp-list">
|
||||||
@ -66,14 +66,14 @@
|
|||||||
</view>
|
</view>
|
||||||
</view>
|
</view>
|
||||||
</view>
|
</view>
|
||||||
<!-- 更多按钮 -->
|
<!– 更多按钮 –>
|
||||||
<view v-if="csrSpList.length > 2" class="more-button" @click="toggleCsrExpanded">
|
<view v-if="csrSpList.length > 2" class="more-button" @click="toggleCsrExpanded">
|
||||||
<text class="more-text">
|
<text class="more-text">
|
||||||
{{ csrExpanded ? '收起' : `更多(${csrSpList.length - 2})` }}
|
{{ csrExpanded ? '收起' : `更多(${csrSpList.length - 2})` }}
|
||||||
</text>
|
</text>
|
||||||
<text class="more-icon" :class="{ expanded: csrExpanded }">▼</text>
|
<text class="more-icon" :class="{ expanded: csrExpanded }">▼</text>
|
||||||
</view>
|
</view>
|
||||||
</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">操作记录({{ logList.length || 0 }})</view>
|
<view class="section-title">操作记录({{ logList.length || 0 }})</view>
|
||||||
|
|||||||
@ -1,8 +1,47 @@
|
|||||||
<template>
|
<template>
|
||||||
<BasicLayout :fixed="false">
|
<BasicLayout :fixed="false">
|
||||||
<view class="p-15">
|
<view class="p-15">
|
||||||
|
<!-- 请假类型 -->
|
||||||
<BasicForm @register="register" />
|
<BasicForm @register="register" />
|
||||||
|
|
||||||
|
<!-- 间隔空白 -->
|
||||||
|
<view class="section-gap"></view>
|
||||||
|
|
||||||
|
<!-- 时间选择区域 -->
|
||||||
|
<view class="time-section">
|
||||||
|
<view class="time-item" @click="startTimePicker?.open()">
|
||||||
|
<text class="time-label">
|
||||||
|
<text class="required-star">*</text>
|
||||||
|
开始时间
|
||||||
|
</text>
|
||||||
|
<view class="time-value">
|
||||||
|
<text :class="{ placeholder: !formData.qjkstime }">{{ formData.qjkstime || "请选择开始时间" }}</text>
|
||||||
|
<uni-icons type="right" size="16" color="#999"></uni-icons>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
|
||||||
|
<view class="time-item" @click="endTimePicker?.open()">
|
||||||
|
<text class="time-label">
|
||||||
|
<text class="required-star">*</text>
|
||||||
|
结束时间
|
||||||
|
</text>
|
||||||
|
<view class="time-value">
|
||||||
|
<text :class="{ placeholder: !formData.qjjstime }">{{ formData.qjjstime || "请选择结束时间" }}</text>
|
||||||
|
<uni-icons type="right" size="16" color="#999"></uni-icons>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
|
||||||
|
<view class="time-item time-item-readonly">
|
||||||
|
<text class="time-label">请假时长</text>
|
||||||
|
<view class="time-value">
|
||||||
|
<text :class="{ placeholder: !formData.qjsc }">{{ formData.qjsc || "请输入选择开始时间和结束时间" }}</text>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
|
||||||
|
<!-- 请假事由和是否离校 -->
|
||||||
|
<BasicForm @register="register2" />
|
||||||
|
|
||||||
<!-- 审批信息显示区域 -->
|
<!-- 审批信息显示区域 -->
|
||||||
<view class="approver-section">
|
<view class="approver-section">
|
||||||
<view class="section-title">审批信息</view>
|
<view class="section-title">审批信息</view>
|
||||||
@ -14,6 +53,9 @@
|
|||||||
</view>
|
</view>
|
||||||
</view>
|
</view>
|
||||||
</view>
|
</view>
|
||||||
|
|
||||||
|
<!-- 签名组件 -->
|
||||||
|
<BasicSign ref="signCompRef" title="家长签名"></BasicSign>
|
||||||
</view>
|
</view>
|
||||||
<template #bottom>
|
<template #bottom>
|
||||||
<view class="white-bg-color py-5">
|
<view class="white-bg-color py-5">
|
||||||
@ -33,6 +75,22 @@
|
|||||||
</view>
|
</view>
|
||||||
</view>
|
</view>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
|
<!-- 自定义时间选择器 -->
|
||||||
|
<DatetimePicker
|
||||||
|
ref="startTimePicker"
|
||||||
|
:value="formData.qjkstime || new Date().getTime()"
|
||||||
|
mode="datetime"
|
||||||
|
title="选择开始时间"
|
||||||
|
@confirm="handleStartTimeConfirm"
|
||||||
|
/>
|
||||||
|
<DatetimePicker
|
||||||
|
ref="endTimePicker"
|
||||||
|
:value="formData.qjjstime || new Date().getTime()"
|
||||||
|
mode="datetime"
|
||||||
|
title="选择结束时间"
|
||||||
|
@confirm="handleEndTimeConfirm"
|
||||||
|
/>
|
||||||
</BasicLayout>
|
</BasicLayout>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
@ -45,6 +103,12 @@ import dayjs from "dayjs";
|
|||||||
import { useUserStore } from "@/store/modules/user";
|
import { useUserStore } from "@/store/modules/user";
|
||||||
import { useCommonStore } from "@/store/modules/common";
|
import { useCommonStore } from "@/store/modules/common";
|
||||||
import { useDebounce } from "@/utils/debounce";
|
import { useDebounce } from "@/utils/debounce";
|
||||||
|
import DatetimePicker from "@/components/BasicPicker/TimePicker/DatetimePicker.vue";
|
||||||
|
|
||||||
|
// 定义事件
|
||||||
|
const emit = defineEmits<{
|
||||||
|
(e: 'submit-success'): void
|
||||||
|
}>();
|
||||||
|
|
||||||
const { getCurXs, getUser } = useUserStore();
|
const { getCurXs, getUser } = useUserStore();
|
||||||
const { findByPid } = useDicStore();
|
const { findByPid } = useDicStore();
|
||||||
@ -52,6 +116,14 @@ const commonStore = useCommonStore();
|
|||||||
// 替换 isSubmitting 状态为 useDebounce
|
// 替换 isSubmitting 状态为 useDebounce
|
||||||
const { isProcessing: isSubmitting, debounce } = useDebounce(2000);
|
const { isProcessing: isSubmitting, debounce } = useDebounce(2000);
|
||||||
|
|
||||||
|
// 自定义时间选择器控制
|
||||||
|
const startTimePicker = ref<any>(null);
|
||||||
|
const endTimePicker = ref<any>(null);
|
||||||
|
|
||||||
|
// 签名组件引用
|
||||||
|
const signCompRef = ref<any>(null);
|
||||||
|
const signFile = ref<any>(null);
|
||||||
|
|
||||||
// 接收外部传入属性
|
// 接收外部传入属性
|
||||||
const props = withDefaults(defineProps<{
|
const props = withDefaults(defineProps<{
|
||||||
data?: any
|
data?: any
|
||||||
@ -67,7 +139,11 @@ const props = withDefaults(defineProps<{
|
|||||||
})
|
})
|
||||||
});
|
});
|
||||||
|
|
||||||
let formData = ref<any>({});
|
let formData = ref<any>({
|
||||||
|
qjkstime: "",
|
||||||
|
qjjstime: "",
|
||||||
|
qjsc: ""
|
||||||
|
});
|
||||||
let approverName = ref<string>(''); // 审批人姓名(班主任)
|
let approverName = ref<string>(''); // 审批人姓名(班主任)
|
||||||
|
|
||||||
const [register, { getValue, setValue }] = useForm({
|
const [register, { getValue, setValue }] = useForm({
|
||||||
@ -84,37 +160,11 @@ const [register, { getValue, setValue }] = useForm({
|
|||||||
savaKey: "dictionaryCode",
|
savaKey: "dictionaryCode",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
{ interval: true },
|
],
|
||||||
{
|
});
|
||||||
field: "qjkstime",
|
|
||||||
label: "开始时间",
|
const [register2, { getValue: getValue2, setValue: setValue2 }] = useForm({
|
||||||
component: "BasicDateTimes",
|
schema: [
|
||||||
required: true,
|
|
||||||
componentProps: {
|
|
||||||
type: 'datetime',
|
|
||||||
change: (e: string) => changeKsTime(e)
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
field: "qjjstime",
|
|
||||||
label: "结束时间",
|
|
||||||
component: "BasicDateTimes",
|
|
||||||
required: true,
|
|
||||||
componentProps: {
|
|
||||||
type: 'datetime',
|
|
||||||
change: (e: string) => changeJsTime(e)
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
field: "qjsc",
|
|
||||||
label: "请假时长",
|
|
||||||
component: "BasicInput",
|
|
||||||
componentProps: {
|
|
||||||
disabled: true,
|
|
||||||
placeholder: "请输入选择开始时间和结束时间"
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{ interval: true },
|
|
||||||
{
|
{
|
||||||
field: "qjsy",
|
field: "qjsy",
|
||||||
label: "请假事由",
|
label: "请假事由",
|
||||||
@ -142,20 +192,11 @@ const [register, { getValue, setValue }] = useForm({
|
|||||||
],
|
],
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
// {
|
|
||||||
// field: "qjtp",
|
|
||||||
// label: "请假图片",
|
|
||||||
// component: "BasicUpload",
|
|
||||||
// required: true,
|
|
||||||
// itemProps: {
|
|
||||||
// labelPosition: "top",
|
|
||||||
// },
|
|
||||||
// componentProps: {},
|
|
||||||
// },
|
|
||||||
],
|
],
|
||||||
});
|
});
|
||||||
|
|
||||||
setValue(props.data)
|
setValue(props.data)
|
||||||
|
setValue2(props.data)
|
||||||
|
|
||||||
const goHome = () => {
|
const goHome = () => {
|
||||||
uni.reLaunch({
|
uni.reLaunch({
|
||||||
@ -163,6 +204,30 @@ const goHome = () => {
|
|||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// 日期格式化函数
|
||||||
|
const formatDate = (dateString: string | null): string | null => {
|
||||||
|
if (!dateString) return null;
|
||||||
|
const date = new Date(dateString);
|
||||||
|
const year = date.getFullYear();
|
||||||
|
const month = String(date.getMonth() + 1).padStart(2, '0');
|
||||||
|
const day = String(date.getDate()).padStart(2, '0');
|
||||||
|
const hours = String(date.getHours()).padStart(2, '0');
|
||||||
|
const minutes = String(date.getMinutes()).padStart(2, '0');
|
||||||
|
const seconds = String(date.getSeconds()).padStart(2, '0');
|
||||||
|
return `${year}-${month}-${day} ${hours}:${minutes}:${seconds}`;
|
||||||
|
};
|
||||||
|
|
||||||
|
// 自定义时间选择器确认事件处理
|
||||||
|
const handleStartTimeConfirm = (e: any) => {
|
||||||
|
formData.value.qjkstime = formatDate(e.value);
|
||||||
|
calculateDuration();
|
||||||
|
};
|
||||||
|
|
||||||
|
const handleEndTimeConfirm = (e: any) => {
|
||||||
|
formData.value.qjjstime = formatDate(e.value);
|
||||||
|
calculateDuration();
|
||||||
|
};
|
||||||
|
|
||||||
// 获取默认审批人信息
|
// 获取默认审批人信息
|
||||||
onMounted(async () => {
|
onMounted(async () => {
|
||||||
await getDefaultApprover();
|
await getDefaultApprover();
|
||||||
@ -180,25 +245,37 @@ const getDefaultApprover = async () => {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
const changeKsTime = (selectedTime?: string) => {
|
// 计算请假时长(不显示错误提示)
|
||||||
if (!selectedTime) {
|
const calculateDuration = () => {
|
||||||
|
const data = formData.value;
|
||||||
|
// 如果两个时间都不存在,直接返回
|
||||||
|
if (!data.qjkstime || !data.qjjstime) {
|
||||||
|
data.qjsc = "";
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
formData.value.qjkstime = selectedTime;
|
// 使用dayjs库进行时间比较
|
||||||
validateTime();
|
const ksTime = dayjs(data.qjkstime).valueOf();
|
||||||
};
|
const jsTime = dayjs(data.qjjstime).valueOf();
|
||||||
|
if (ksTime > jsTime) {
|
||||||
const changeJsTime = (selectedTime?: string) => {
|
uni.showToast({
|
||||||
if (!selectedTime) {
|
title: "请假开始时间不能大于请假结束时间!",
|
||||||
|
icon: "none",
|
||||||
|
});
|
||||||
|
data.qjsc = "";
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
formData.value.qjjstime = selectedTime;
|
// 计算请假时长(小时)
|
||||||
validateTime();
|
data.qjsc = Math.round((jsTime - ksTime) / (1000 * 60 * 60)) + "小时";
|
||||||
};
|
}
|
||||||
|
|
||||||
|
// 验证时间(用于提交时的完整验证)
|
||||||
const validateTime = () => {
|
const validateTime = () => {
|
||||||
const data = formData.value;
|
const data = formData.value;
|
||||||
if (!data.qjkstime || !data.qjjstime) {
|
if (!data.qjkstime || !data.qjjstime) {
|
||||||
|
uni.showToast({
|
||||||
|
title: "请选择开始时间和结束时间",
|
||||||
|
icon: "none",
|
||||||
|
});
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
// 使用dayjs库进行时间比较
|
// 使用dayjs库进行时间比较
|
||||||
@ -213,16 +290,40 @@ const validateTime = () => {
|
|||||||
}
|
}
|
||||||
// 计算请假时长(小时)
|
// 计算请假时长(小时)
|
||||||
data.qjsc = Math.round((jsTime - ksTime) / (1000 * 60 * 60)) + "小时";
|
data.qjsc = Math.round((jsTime - ksTime) / (1000 * 60 * 60)) + "小时";
|
||||||
setValue({ qjsc: data.qjsc });
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
const submit = debounce(async () => {
|
const submit = debounce(async () => {
|
||||||
const fd = await getValue();
|
|
||||||
if (!validateTime()) {
|
if (!validateTime()) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
const params = { ...fd };
|
|
||||||
|
// 获取签名
|
||||||
|
const signData = await signCompRef.value.getSyncSignature();
|
||||||
|
if (!signData) {
|
||||||
|
uni.showToast({
|
||||||
|
title: "请签名",
|
||||||
|
icon: "none",
|
||||||
|
});
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
signFile.value = signData.base64;
|
||||||
|
|
||||||
|
const fd = await getValue();
|
||||||
|
const fd2 = await getValue2();
|
||||||
|
|
||||||
|
// 组合班级别称:njbc + "(" + bjmc + ")"
|
||||||
|
const bc = getCurXs.njbc ? `${getCurXs.njbc}(${getCurXs.bjmc || ''})` : (getCurXs.bjmc || '');
|
||||||
|
|
||||||
|
const params = {
|
||||||
|
...fd,
|
||||||
|
...fd2,
|
||||||
|
qjkstime: formData.value.qjkstime,
|
||||||
|
qjjstime: formData.value.qjjstime,
|
||||||
|
qjsc: formData.value.qjsc,
|
||||||
|
signFile: signFile.value, // 添加签名数据
|
||||||
|
bc: bc // 添加班级别称
|
||||||
|
};
|
||||||
if (props.data && props.data.id) {
|
if (props.data && props.data.id) {
|
||||||
params.id = props.data.id;
|
params.id = props.data.id;
|
||||||
} else {
|
} else {
|
||||||
@ -241,7 +342,8 @@ const submit = debounce(async () => {
|
|||||||
setTimeout(() => {
|
setTimeout(() => {
|
||||||
if (res.resultCode === 1) {
|
if (res.resultCode === 1) {
|
||||||
showToast({ title: "提交成功", icon: "success" });
|
showToast({ title: "提交成功", icon: "success" });
|
||||||
goHome();
|
// 触发提交成功事件,切换到请假记录页
|
||||||
|
emit('submit-success');
|
||||||
} else {
|
} else {
|
||||||
showToast({ title: res.message, icon: "error" });
|
showToast({ title: res.message, icon: "error" });
|
||||||
}
|
}
|
||||||
@ -251,6 +353,78 @@ const submit = debounce(async () => {
|
|||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style lang="scss" scoped>
|
<style lang="scss" scoped>
|
||||||
|
.section-gap {
|
||||||
|
height: 12px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.required-star {
|
||||||
|
color: #f56c6c;
|
||||||
|
margin-right: 4px;
|
||||||
|
font-size: 15px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.time-section {
|
||||||
|
background-color: #ffffff;
|
||||||
|
border-radius: 8px;
|
||||||
|
margin-bottom: 12px;
|
||||||
|
box-shadow: 0 1px 4px rgba(0, 0, 0, 0.05);
|
||||||
|
|
||||||
|
.time-item {
|
||||||
|
display: flex;
|
||||||
|
justify-content: space-between;
|
||||||
|
align-items: center;
|
||||||
|
padding: 14px 15px;
|
||||||
|
border-bottom: 1px solid #f0f0f0;
|
||||||
|
cursor: pointer;
|
||||||
|
transition: background-color 0.2s;
|
||||||
|
|
||||||
|
&:last-child {
|
||||||
|
border-bottom: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
&:active {
|
||||||
|
background-color: #fafafa;
|
||||||
|
}
|
||||||
|
|
||||||
|
&.time-item-readonly {
|
||||||
|
cursor: default;
|
||||||
|
|
||||||
|
&:active {
|
||||||
|
background-color: transparent;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.time-label {
|
||||||
|
font-size: 15px;
|
||||||
|
color: #303133;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.time-value {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
font-size: 15px;
|
||||||
|
color: #909399;
|
||||||
|
flex: 1;
|
||||||
|
justify-content: flex-end;
|
||||||
|
|
||||||
|
text {
|
||||||
|
margin-right: 5px;
|
||||||
|
color: #606266;
|
||||||
|
|
||||||
|
&.placeholder {
|
||||||
|
color: #c0c4cc;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.uni-icons {
|
||||||
|
color: #c0c4cc !important;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
.approver-section {
|
.approver-section {
|
||||||
margin: 20px 0;
|
margin: 20px 0;
|
||||||
padding: 15px;
|
padding: 15px;
|
||||||
|
|||||||
@ -6,7 +6,7 @@
|
|||||||
:current="curTabIndex" @change="switchTab"
|
:current="curTabIndex" @change="switchTab"
|
||||||
/>
|
/>
|
||||||
<view class="leave-edit" v-if="curTabIndex === 0">
|
<view class="leave-edit" v-if="curTabIndex === 0">
|
||||||
<XsQjEdit />
|
<XsQjEdit @submit-success="handleSubmitSuccess" />
|
||||||
</view>
|
</view>
|
||||||
<view class="leave-list" v-else>
|
<view class="leave-list" v-else>
|
||||||
<XsQjList />
|
<XsQjList />
|
||||||
@ -29,6 +29,11 @@ const curTabIndex = ref(0);
|
|||||||
const switchTab = (index : number) => {
|
const switchTab = (index : number) => {
|
||||||
curTabIndex.value = index;
|
curTabIndex.value = index;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const handleSubmitSuccess = () => {
|
||||||
|
// 切换到请假记录tab页
|
||||||
|
curTabIndex.value = 1;
|
||||||
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style lang="scss" scoped>
|
<style lang="scss" scoped>
|
||||||
|
|||||||
@ -169,9 +169,13 @@ const courseDetail = computed(() => {
|
|||||||
// 教师信息
|
// 教师信息
|
||||||
const teacherInfo = computed(() => {
|
const teacherInfo = computed(() => {
|
||||||
const data = (kcData.value as CourseData) || {};
|
const data = (kcData.value as CourseData) || {};
|
||||||
|
|
||||||
|
// 处理多个教师头像的情况
|
||||||
|
const teacherAvatars = data.jstx ? data.jstx.split(',').map((avatar: string) => avatar.trim()) : [];
|
||||||
|
|
||||||
return {
|
return {
|
||||||
name: data.jsName || "暂无教师信息",
|
name: data.jsName || "暂无教师信息",
|
||||||
avatar: imagUrl(data.jstx), // 默认头像
|
avatar: teacherAvatars.length > 0 ? imagUrl(teacherAvatars[0]) : '', // 只取第一个头像
|
||||||
introduction: data.kcjsms || "暂无教师介绍",
|
introduction: data.kcjsms || "暂无教师介绍",
|
||||||
};
|
};
|
||||||
});
|
});
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user