Compare commits
3 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 021ac7f7bd | |||
| b75e1f9bd9 | |||
| c41176af8d |
@@ -110,21 +110,22 @@ func GetLeaveApplyApprovers(c *fiber.Ctx) error {
|
||||
|
||||
// ExecuteLeaveApplyRequest 请假申请执行参数
|
||||
type ExecuteLeaveApplyRequest struct {
|
||||
LeaveType int `json:"leaveType"` // 类型编码
|
||||
StartTime string `json:"startTime"` // yyyy-MM-dd HH:mm:ss
|
||||
EndTime string `json:"endTime"` // yyyy-MM-dd HH:mm:ss
|
||||
LeaveReason string `json:"leaveReason"` // 请假原因
|
||||
OutStatus bool `json:"outStatus"` // 是否离校
|
||||
UrgencyMobile string `json:"urgencyMobile"` // 紧急联系人(离校必填)
|
||||
Address string `json:"address"` // 目的地(离校必填)
|
||||
DetailAddress string `json:"detailAddress"` // 详细地址(离校必填)
|
||||
Longitude string `json:"longitude"` // 定位经度
|
||||
Latitude string `json:"latitude"` // 定位纬度
|
||||
LocationAddr string `json:"locationAddr"` // 定位地址
|
||||
ImageURL string `json:"imageUrl"` // 附件(可选)
|
||||
ApproverWid string `json:"approverWid"` // 审批人 userWid
|
||||
ApproverId string `json:"approverId"` // 审批人 userId
|
||||
ApproverName string `json:"approverName"` // 审批人姓名
|
||||
LeaveType int `json:"leaveType"` // 类型编码
|
||||
StartTime string `json:"startTime"` // yyyy-MM-dd HH:mm:ss
|
||||
EndTime string `json:"endTime"` // yyyy-MM-dd HH:mm:ss
|
||||
LeaveReason string `json:"leaveReason"` // 请假原因
|
||||
OutStatus bool `json:"outStatus"` // 是否离校
|
||||
UrgencyMobile string `json:"urgencyMobile"` // 紧急联系人(离校必填)
|
||||
Address string `json:"address"` // 目的地(离校必填)
|
||||
DetailAddress string `json:"detailAddress"` // 详细地址(离校必填)
|
||||
Longitude string `json:"longitude"` // 定位经度
|
||||
Latitude string `json:"latitude"` // 定位纬度
|
||||
LocationAddr string `json:"locationAddr"` // 定位地址
|
||||
ImageURL string `json:"imageUrl"` // 附件(可选)
|
||||
ApproverWid string `json:"approverWid"` // 审批人 userWid(候选为空时可不传)
|
||||
ApproverId string `json:"approverId"` // 审批人 userId
|
||||
ApproverName string `json:"approverName"` // 审批人姓名
|
||||
CcUsers []cpd.LeaveApprover `json:"ccUsers"` // 抄送人(非必填,候选取自审批人列表)
|
||||
}
|
||||
|
||||
// ExecuteLeaveApply 执行请假申请(SSE 同步执行:checkOnceLeave → 提交)。
|
||||
@@ -265,11 +266,24 @@ func ExecuteLeaveApply(c *fiber.Ctx) error {
|
||||
sendEvent("task_error", map[string]interface{}{"status": "error", "message": errMsg})
|
||||
return
|
||||
}
|
||||
// 审批人:needApproval=1 且学校配置了候选审批人时必选;
|
||||
// 候选列表为空(学校未配置审批节点人员,如 ysdwl「大四学生请假」)时允许不选,跳过即可
|
||||
if cfg.NeedApproval == 1 && req.ApproverWid == "" {
|
||||
errMsg := "该请假类型需要选择审批人"
|
||||
saveLog(false, errMsg)
|
||||
sendEvent("task_error", map[string]interface{}{"status": "error", "message": errMsg, "needApprover": true})
|
||||
return
|
||||
candidates, err := cpd.FetchReportApprovers(cookieMap, host, req.LeaveType, req.StartTime, req.EndTime)
|
||||
if err != nil {
|
||||
errMsg := "获取请假审批人失败: " + err.Error()
|
||||
slog.Warn("校验审批人候选失败", "userId", userID, "error", err)
|
||||
saveLog(false, errMsg)
|
||||
sendEvent("task_error", map[string]interface{}{"status": "error", "message": errMsg})
|
||||
return
|
||||
}
|
||||
if len(candidates) > 0 {
|
||||
errMsg := "该请假类型需要选择审批人"
|
||||
saveLog(false, errMsg)
|
||||
sendEvent("task_error", map[string]interface{}{"status": "error", "message": errMsg, "needApprover": true})
|
||||
return
|
||||
}
|
||||
slog.Info("该类型无候选审批人,允许不选提交", "userId", userID, "leaveType", req.LeaveType)
|
||||
}
|
||||
|
||||
// 2. 可请假检查
|
||||
@@ -299,6 +313,7 @@ func ExecuteLeaveApply(c *fiber.Ctx) error {
|
||||
ApproverWid: req.ApproverWid,
|
||||
ApproverId: req.ApproverId,
|
||||
ApproverName: req.ApproverName,
|
||||
CcUsers: req.CcUsers,
|
||||
}
|
||||
form := cpd.BuildLeaveApplyForm(p, user.MobileCode, "15", "9.9.6")
|
||||
err = cpd.SubmitLeaveApply(cookieMap, host, form, req.Longitude, req.Latitude, user.MobileCode, user.StudentID)
|
||||
|
||||
@@ -172,21 +172,66 @@ func FetchLeaveTypeCfg(cookieMap map[string]string, host string, code int) (*Lea
|
||||
|
||||
// LeaveApplyParams 请假申请提交参数
|
||||
type LeaveApplyParams struct {
|
||||
LeaveType int // 类型编码
|
||||
StartTime string // yyyy-MM-dd HH:mm:ss
|
||||
EndTime string // yyyy-MM-dd HH:mm:ss
|
||||
LeaveReason string // 请假原因
|
||||
OutStatus bool // 是否离校
|
||||
UrgencyMobile string // 紧急联系人手机号(离校必填)
|
||||
Address string // 目的地(离校必填,如 xx省/xx市/xx区)
|
||||
DetailAddress string // 详细地址(离校必填)
|
||||
Longitude string // 定位经度
|
||||
Latitude string // 定位纬度
|
||||
LocationAddr string // 定位地址
|
||||
ImageURL string // 附件图片 URL(可选)
|
||||
ApproverWid string // 审批人 userWid(needApproval=1 时必填)
|
||||
ApproverId string // 审批人 userId
|
||||
ApproverName string // 审批人姓名
|
||||
LeaveType int // 类型编码
|
||||
StartTime string // yyyy-MM-dd HH:mm:ss
|
||||
EndTime string // yyyy-MM-dd HH:mm:ss
|
||||
LeaveReason string // 请假原因
|
||||
OutStatus bool // 是否离校
|
||||
UrgencyMobile string // 紧急联系人手机号(离校必填)
|
||||
Address string // 目的地(离校必填,如 xx省/xx市/xx区)
|
||||
DetailAddress string // 详细地址(离校必填)
|
||||
Longitude string // 定位经度
|
||||
Latitude string // 定位纬度
|
||||
LocationAddr string // 定位地址
|
||||
ImageURL string // 附件图片 URL(可选)
|
||||
ApproverWid string // 审批人 userWid(needApproval=1 且学校配置了候选审批人时必填;候选为空可不选)
|
||||
ApproverId string // 审批人 userId
|
||||
ApproverName string // 审批人姓名
|
||||
CcUsers []LeaveApprover // 抄送人(非必填;候选取自审批人列表)
|
||||
}
|
||||
|
||||
// BuildLeaveCcInfo 构造抄送人信息(ccInfo)。
|
||||
// 官方结构:{totalSize, teachers:[], students:[]},人员含 personType(0=老师 1=学生)。
|
||||
// 审批人接口不返回 personType,按 userId 是否纯数字推断(学号纯数字,教师工号常含字母)。
|
||||
func BuildLeaveCcInfo(users []LeaveApprover) map[string]interface{} {
|
||||
teachers := make([]interface{}, 0, len(users))
|
||||
students := make([]interface{}, 0, len(users))
|
||||
for _, u := range users {
|
||||
if u.UserWid == "" {
|
||||
continue
|
||||
}
|
||||
personType := 1 // 默认学生
|
||||
if u.UserId == "" {
|
||||
personType = 0
|
||||
} else {
|
||||
for _, ch := range u.UserId {
|
||||
if ch < '0' || ch > '9' {
|
||||
personType = 0 // 含非数字字符 → 教师
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
person := map[string]interface{}{
|
||||
"userWid": u.UserWid,
|
||||
"userId": u.UserId,
|
||||
"userName": u.UserName,
|
||||
"name2Id": u.UserName + "/" + u.UserId,
|
||||
"personType": personType,
|
||||
"dept": nil,
|
||||
"sex": nil,
|
||||
"teacherName": u.UserName,
|
||||
}
|
||||
if personType == 0 {
|
||||
teachers = append(teachers, person)
|
||||
} else {
|
||||
students = append(students, person)
|
||||
}
|
||||
}
|
||||
return map[string]interface{}{
|
||||
"totalSize": len(teachers) + len(students),
|
||||
"teachers": teachers,
|
||||
"students": students,
|
||||
}
|
||||
}
|
||||
|
||||
// BuildLeaveApplyForm 构造请假申请表单(/leave/apply 的明文 JSON body,
|
||||
@@ -224,12 +269,9 @@ func BuildLeaveApplyForm(p LeaveApplyParams, deviceId, systemVersion, appVersion
|
||||
"holidayAutoDefineVos": []interface{}{},
|
||||
"appVersion": appVersion,
|
||||
"deviceId": deviceId,
|
||||
"ccInfo": map[string]interface{}{
|
||||
"teachers": []interface{}{},
|
||||
"students": []interface{}{},
|
||||
},
|
||||
"cheatType": nil,
|
||||
"source": 1,
|
||||
"ccInfo": BuildLeaveCcInfo(p.CcUsers),
|
||||
"cheatType": nil,
|
||||
"source": 1,
|
||||
"location": map[string]interface{}{
|
||||
"deviceId": deviceId,
|
||||
"systemName": "Android",
|
||||
|
||||
@@ -166,6 +166,56 @@ func TestBuildLeaveApplyForm(t *testing.T) {
|
||||
if attach, ok := form2["applyAttach"].([]interface{}); !ok || len(attach) != 0 {
|
||||
t.Errorf("无附件时 applyAttach 应为空数组: %v", form2["applyAttach"])
|
||||
}
|
||||
// 无抄送人:ccInfo 仍必须存在且为空结构
|
||||
cc, ok := form2["ccInfo"].(map[string]interface{})
|
||||
if !ok || cc["totalSize"] != 0 {
|
||||
t.Errorf("无抄送人时 ccInfo 应为空结构: %v", form2["ccInfo"])
|
||||
}
|
||||
}
|
||||
|
||||
func TestBuildLeaveCcInfo(t *testing.T) {
|
||||
// 学生(纯数字 userId)+ 教师(含字母 userId)分组
|
||||
users := []LeaveApprover{
|
||||
{UserWid: "92274797", UserId: "02727", UserName: "王欣然"}, // 纯数字 → students
|
||||
{UserWid: "915560902", UserId: "kjxy0003", UserName: "杨瑚"}, // 含字母 → teachers
|
||||
}
|
||||
cc := BuildLeaveCcInfo(users)
|
||||
if cc["totalSize"] != 2 {
|
||||
t.Errorf("totalSize 应为 2,实际 %v", cc["totalSize"])
|
||||
}
|
||||
students, _ := cc["students"].([]interface{})
|
||||
teachers, _ := cc["teachers"].([]interface{})
|
||||
if len(students) != 1 || len(teachers) != 1 {
|
||||
t.Fatalf("分组错误: students=%d teachers=%d", len(students), len(teachers))
|
||||
}
|
||||
st, _ := students[0].(map[string]interface{})
|
||||
if st["userWid"] != "92274797" || st["name2Id"] != "王欣然/02727" || st["personType"] != 1 {
|
||||
t.Errorf("学生抄送人字段错误: %v", st)
|
||||
}
|
||||
tc, _ := teachers[0].(map[string]interface{})
|
||||
if tc["userWid"] != "915560902" || tc["personType"] != 0 {
|
||||
t.Errorf("教师抄送人字段错误: %v", tc)
|
||||
}
|
||||
|
||||
// 空列表:结构完整但 totalSize=0
|
||||
empty := BuildLeaveCcInfo(nil)
|
||||
if empty["totalSize"] != 0 {
|
||||
t.Errorf("空抄送人 totalSize 应为 0: %v", empty["totalSize"])
|
||||
}
|
||||
if arr, ok := empty["teachers"].([]interface{}); !ok || len(arr) != 0 {
|
||||
t.Errorf("空抄送人 teachers 应为空数组: %v", empty["teachers"])
|
||||
}
|
||||
|
||||
// 提交表单携带抄送人
|
||||
form := BuildLeaveApplyForm(LeaveApplyParams{
|
||||
LeaveType: 1, StartTime: "2026-09-15 08:00:00", EndTime: "2026-09-15 18:00:00",
|
||||
LeaveReason: "身体不适需休息", Longitude: "118.1", Latitude: "24.6", LocationAddr: "校内",
|
||||
CcUsers: users,
|
||||
}, "device-1", "15", "9.9.6")
|
||||
fcc, _ := form["ccInfo"].(map[string]interface{})
|
||||
if fcc == nil || fcc["totalSize"] != 2 {
|
||||
t.Errorf("表单 ccInfo 应包含 2 名抄送人: %v", form["ccInfo"])
|
||||
}
|
||||
}
|
||||
|
||||
func TestSubmitLeaveApply(t *testing.T) {
|
||||
|
||||
@@ -100,6 +100,8 @@ export interface ExecuteLeaveApplyParams {
|
||||
approverWid?: string
|
||||
approverId?: string
|
||||
approverName?: string
|
||||
/** 抄送人(非必填;候选取自审批人列表) */
|
||||
ccUsers?: LeaveApprover[]
|
||||
}
|
||||
|
||||
// ======== API ========
|
||||
|
||||
@@ -7,7 +7,7 @@
|
||||
<div class="flex items-center justify-between mb-3">
|
||||
<div>
|
||||
<p class="text-sm font-semibold text-gray-900">请假与销假</p>
|
||||
<p class="text-xs text-gray-400 mt-0.5">提交请假申请,或返校后一键销假</p>
|
||||
<p class="text-xs text-gray-400 mt-0.5">异地一键请假销假,自行设置位置</p>
|
||||
</div>
|
||||
<div class="w-10 h-10 rounded-full bg-rose-50 flex items-center justify-center">
|
||||
<CalendarCheck class="w-5 h-5 text-rose-500" />
|
||||
@@ -497,9 +497,13 @@
|
||||
</button>
|
||||
</div>
|
||||
|
||||
<!-- 审批人(needApproval=1 时) -->
|
||||
<!-- 审批人(needApproval=1 时;候选为空则不强制选择,允许直接提交) -->
|
||||
<div v-if="currentType?.needApproval === 1">
|
||||
<label class="text-xs text-gray-500 mb-1 block">审批人 <span class="text-rose-500">*</span></label>
|
||||
<label class="text-xs text-gray-500 mb-1 block">
|
||||
审批人
|
||||
<span v-if="applyApprovers.length > 0" class="text-rose-500">*</span>
|
||||
<span v-else class="text-[10px] text-gray-400">(该校未配置审批人,可不选)</span>
|
||||
</label>
|
||||
<div v-if="loadingApplyApprovers" class="flex items-center justify-center py-3">
|
||||
<LoaderCircle class="w-4 h-4 text-rose-400 animate-spin" />
|
||||
</div>
|
||||
@@ -524,7 +528,10 @@
|
||||
</div>
|
||||
</div>
|
||||
<div v-else class="rounded-lg bg-amber-50 border border-amber-100 p-2.5">
|
||||
<p class="text-[10px] text-amber-600">请先选择请假类型并填写开始/结束时间,再获取审批人</p>
|
||||
<p v-if="canFetchApplyApprovers" class="text-[10px] text-amber-600">
|
||||
该校该请假类型未配置审批人,无需选择,可直接提交
|
||||
</p>
|
||||
<p v-else class="text-[10px] text-amber-600">请先选择请假类型并填写开始/结束时间,再获取审批人</p>
|
||||
<button
|
||||
@click="loadApplyApprovers"
|
||||
:disabled="loadingApplyApprovers || !canFetchApplyApprovers"
|
||||
@@ -533,6 +540,36 @@
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- 抄送人(非必填;候选复用审批人列表,可多选) -->
|
||||
<div v-if="canFetchApplyApprovers && applyApprovers.length > 0">
|
||||
<label class="text-xs text-gray-500 mb-1 block">
|
||||
抄送人
|
||||
<span class="text-[10px] text-gray-400">(非必填,可多选)</span>
|
||||
</label>
|
||||
<div class="space-y-1.5">
|
||||
<div
|
||||
v-for="a in applyApprovers"
|
||||
:key="'cc-' + a.userWid"
|
||||
@click="toggleCcUser(a)"
|
||||
class="p-2.5 rounded-lg border cursor-pointer transition-colors flex items-center gap-2"
|
||||
:class="isCcSelected(a)
|
||||
? 'border-blue-400 bg-blue-50'
|
||||
: 'border-gray-100 hover:border-blue-200'"
|
||||
>
|
||||
<div
|
||||
class="w-3.5 h-3.5 rounded border shrink-0 flex items-center justify-center"
|
||||
:class="isCcSelected(a) ? 'border-blue-500 bg-blue-500' : 'border-gray-300'"
|
||||
>
|
||||
<svg v-if="isCcSelected(a)" class="w-2.5 h-2.5 text-white" viewBox="0 0 12 12" fill="none">
|
||||
<path d="M2 6l3 3 5-6" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" />
|
||||
</svg>
|
||||
</div>
|
||||
<span class="text-xs text-gray-900">{{ a.userName }}</span>
|
||||
<span class="text-[10px] text-gray-400">{{ a.userId }}</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- 执行状态 -->
|
||||
<p v-if="applyMessage" class="text-[11px] leading-relaxed" :class="applyStatus === 'error' ? 'text-red-500' : applyStatus === 'success' ? 'text-green-600' : 'text-blue-500'">
|
||||
{{ applyMessage }}
|
||||
@@ -559,17 +596,32 @@
|
||||
</div>
|
||||
</div>
|
||||
</Teleport>
|
||||
<!-- ======== 无法请/销假:右侧贴边窄竖条(样式同打卡页「收藏本站」),点击跳转工单页 ======== -->
|
||||
<button
|
||||
class="fixed right-0 bottom-32 z-40 flex flex-col items-center gap-1.5 rounded-l-md bg-rose-500/95 py-3 px-1.5 text-white text-xs font-medium shadow-lg shadow-rose-500/30 hover:bg-rose-600 active:scale-95 transition-all"
|
||||
@click="goTicket"
|
||||
>
|
||||
<MessageSquare class="w-3.5 h-3.5 flex-shrink-0" />
|
||||
<span class="bookmark-vtext">无法请/销假?提交工单</span>
|
||||
</button>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { ref, watch, onMounted, onUnmounted } from 'vue'
|
||||
import { CalendarCheck, CalendarPlus, LoaderCircle, Trash2, X, MapPin, Upload } from 'lucide-vue-next'
|
||||
import { useRouter } from 'vue-router'
|
||||
import { CalendarCheck, CalendarPlus, LoaderCircle, Trash2, X, MapPin, Upload, MessageSquare } from 'lucide-vue-next'
|
||||
import * as leaveApi from '@/api/leave'
|
||||
import type { LeaveItem, LeaveReportPlace, LeaveType } from '@/api/leave'
|
||||
import { useMessage } from '@/composables/useMessage'
|
||||
|
||||
const { message } = useMessage()
|
||||
const router = useRouter()
|
||||
|
||||
/** 跳转工单页面(无法请/销假时提交工单反馈) */
|
||||
function goTicket() {
|
||||
router.push('/ticket')
|
||||
}
|
||||
|
||||
// ======== 销假日志 ========
|
||||
const loadingLogs = ref(false)
|
||||
@@ -954,6 +1006,7 @@ function openApplyModal() {
|
||||
approverWid: '',
|
||||
}
|
||||
applyApprovers.value = []
|
||||
applyCcUsers.value = []
|
||||
currentType.value = null
|
||||
canFetchApplyApprovers.value = false
|
||||
loadLeaveTypes()
|
||||
@@ -985,6 +1038,7 @@ function onApplyTypeChange() {
|
||||
const t = currentTypeOf()
|
||||
currentType.value = t
|
||||
applyApprovers.value = []
|
||||
applyCcUsers.value = []
|
||||
applyForm.value.approverWid = ''
|
||||
// mustOut=1 强制离校;其余默认不离校
|
||||
applyForm.value.outStatus = t?.mustOut === 1
|
||||
@@ -993,9 +1047,7 @@ function onApplyTypeChange() {
|
||||
applyForm.value.address = ''
|
||||
applyForm.value.detailAddress = ''
|
||||
}
|
||||
if (t?.needApproval === 1) {
|
||||
tryAutoFetchApplyApprovers()
|
||||
}
|
||||
// 类型/时间变化由 watch 统一触发候选加载(审批人+抄送人同源)
|
||||
}
|
||||
|
||||
function toggleOutStatus() {
|
||||
@@ -1015,11 +1067,18 @@ function toApiTime(v: string): string {
|
||||
return normalized.length === 16 ? normalized + ':00' : normalized
|
||||
}
|
||||
|
||||
function tryAutoFetchApplyApprovers() {
|
||||
const { leaveType, startTime, endTime } = applyForm.value
|
||||
canFetchApplyApprovers.value = !!(leaveType && startTime && endTime)
|
||||
if (canFetchApplyApprovers.value && currentType.value?.needApproval === 1) {
|
||||
loadApplyApprovers()
|
||||
// ======== 抄送人(非必填,候选复用审批人列表) ========
|
||||
const applyCcUsers = ref<leaveApi.LeaveApprover[]>([])
|
||||
|
||||
function isCcSelected(a: leaveApi.LeaveApprover) {
|
||||
return applyCcUsers.value.some(cc => cc.userWid === a.userWid)
|
||||
}
|
||||
|
||||
function toggleCcUser(a: leaveApi.LeaveApprover) {
|
||||
if (isCcSelected(a)) {
|
||||
applyCcUsers.value = applyCcUsers.value.filter(cc => cc.userWid !== a.userWid)
|
||||
} else {
|
||||
applyCcUsers.value = [...applyCcUsers.value, a]
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1033,12 +1092,18 @@ async function loadApplyApprovers() {
|
||||
endTime: toApiTime(applyForm.value.endTime),
|
||||
})
|
||||
applyApprovers.value = res.data.data || []
|
||||
// 换类型/时间后原审批人可能已不在候选中,清掉失效选择
|
||||
if (applyForm.value.approverWid && !applyApprovers.value.some(a => a.userWid === applyForm.value.approverWid)) {
|
||||
applyForm.value.approverWid = ''
|
||||
}
|
||||
if (applyApprovers.value.length === 1) {
|
||||
applyForm.value.approverWid = applyApprovers.value[0].userWid
|
||||
}
|
||||
// 抄送人清理:去除不在新候选中的
|
||||
applyCcUsers.value = applyCcUsers.value.filter(cc => applyApprovers.value.some(a => a.userWid === cc.userWid))
|
||||
} catch (e: any) {
|
||||
// 静默降级:候选加载失败不打断填表(如需审批,提交时后端会再次校验并给出明确提示)
|
||||
applyApprovers.value = []
|
||||
message.error(e?.response?.data?.message || '获取审批人失败')
|
||||
} finally {
|
||||
loadingApplyApprovers.value = false
|
||||
}
|
||||
@@ -1133,13 +1198,13 @@ async function getApplyGPS() {
|
||||
}
|
||||
}
|
||||
|
||||
// 类型/起止时间变化时:needApproval 类型自动重取审批人(审批流按时间段变化)
|
||||
// 类型/起止时间变化时:自动重取候选(审批流按类型与时间段变化;候选同时用于审批人与抄送人)
|
||||
watch(
|
||||
() => [applyForm.value.leaveType, applyForm.value.startTime, applyForm.value.endTime] as const,
|
||||
() => {
|
||||
if (!showApplyModal.value) return
|
||||
canFetchApplyApprovers.value = !!(applyForm.value.leaveType && applyForm.value.startTime && applyForm.value.endTime)
|
||||
if (canFetchApplyApprovers.value && currentType.value?.needApproval === 1) {
|
||||
if (canFetchApplyApprovers.value) {
|
||||
loadApplyApprovers()
|
||||
}
|
||||
},
|
||||
@@ -1192,7 +1257,8 @@ async function submitApply() {
|
||||
message.warning('请填写定位地址')
|
||||
return
|
||||
}
|
||||
if (t?.needApproval === 1 && !f.approverWid) {
|
||||
// 审批人:仅当学校配置了候选审批人时必选;候选为空(未配置人员)允许不选
|
||||
if (t?.needApproval === 1 && applyApprovers.value.length > 0 && !f.approverWid) {
|
||||
message.warning('该请假类型需要选择审批人')
|
||||
return
|
||||
}
|
||||
@@ -1220,6 +1286,7 @@ async function submitApply() {
|
||||
approverWid: approver?.userWid,
|
||||
approverId: approver?.userId,
|
||||
approverName: approver?.userName,
|
||||
ccUsers: applyCcUsers.value.length > 0 ? applyCcUsers.value : undefined,
|
||||
},
|
||||
{
|
||||
onConnecting: () => {
|
||||
@@ -1259,3 +1326,12 @@ async function submitApply() {
|
||||
)
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
/* 贴边按钮竖排文字:样式与打卡页「收藏本站」一致
|
||||
(仅文字本身竖排,容器保持常规纵排:图标在上、文字在下) */
|
||||
.bookmark-vtext {
|
||||
writing-mode: vertical-rl;
|
||||
letter-spacing: 2px;
|
||||
}
|
||||
</style>
|
||||
|
||||
Reference in New Issue
Block a user