From a1d7e81859f554f3a53680cc35f0f49bf1f77098 Mon Sep 17 00:00:00 2001
From: wwf <1971391498@qq.com>
Date: 星期四, 14 五月 2026 14:37:02 +0800
Subject: [PATCH] 导入项目
---
src/views/bpm/oa/leave/create.vue | 257 +++++++++++++++++++++++++++++++++++++++++++++++++++
1 files changed, 257 insertions(+), 0 deletions(-)
diff --git a/src/views/bpm/oa/leave/create.vue b/src/views/bpm/oa/leave/create.vue
new file mode 100644
index 0000000..b64f4ca
--- /dev/null
+++ b/src/views/bpm/oa/leave/create.vue
@@ -0,0 +1,257 @@
+<template>
+ <el-row :gutter="20">
+ <el-col :span="16">
+ <ContentWrap title="鐢宠淇℃伅">
+ <el-form
+ ref="formRef"
+ v-loading="formLoading"
+ :model="formData"
+ :rules="formRules"
+ label-width="80px"
+ >
+ <el-form-item label="璇峰亣绫诲瀷" prop="type">
+ <el-select v-model="formData.type" clearable placeholder="璇烽�夋嫨璇峰亣绫诲瀷">
+ <el-option
+ v-for="dict in getIntDictOptions(DICT_TYPE.BPM_OA_LEAVE_TYPE)"
+ :key="dict.value"
+ :label="dict.label"
+ :value="dict.value"
+ />
+ </el-select>
+ </el-form-item>
+ <el-form-item label="寮�濮嬫椂闂�" prop="startTime">
+ <el-date-picker
+ v-model="formData.startTime"
+ clearable
+ placeholder="璇烽�夋嫨寮�濮嬫椂闂�"
+ type="datetime"
+ value-format="x"
+ />
+ </el-form-item>
+ <el-form-item label="缁撴潫鏃堕棿" prop="endTime">
+ <el-date-picker
+ v-model="formData.endTime"
+ clearable
+ placeholder="璇烽�夋嫨缁撴潫鏃堕棿"
+ type="datetime"
+ value-format="x"
+ />
+ </el-form-item>
+ <el-form-item label="鍘熷洜" prop="reason">
+ <el-input v-model="formData.reason" placeholder="璇疯緭鍏ヨ鍋囧師鍥�" type="textarea" />
+ </el-form-item>
+ <el-form-item>
+ <el-button :disabled="formLoading" type="primary" @click="submitForm">
+ 纭� 瀹�
+ </el-button>
+ </el-form-item>
+ </el-form>
+ </ContentWrap>
+ </el-col>
+
+ <!-- 瀹℃壒鐩稿叧锛氭祦绋嬩俊鎭� -->
+ <el-col :span="8">
+ <ContentWrap title="瀹℃壒娴佺▼" :bodyStyle="{ padding: '0 20px 0' }">
+ <ProcessInstanceTimeline
+ ref="timelineRef"
+ :activity-nodes="activityNodes"
+ :show-status-icon="false"
+ @select-user-confirm="selectUserConfirm"
+ />
+ </ContentWrap>
+ </el-col>
+ </el-row>
+</template>
+<script lang="ts" setup>
+import { DICT_TYPE, getIntDictOptions } from '@/utils/dict'
+import * as LeaveApi from '@/api/bpm/leave'
+import { useTagsViewStore } from '@/store/modules/tagsView'
+
+// 瀹℃壒鐩稿叧锛歩mport
+import * as DefinitionApi from '@/api/bpm/definition'
+import ProcessInstanceTimeline from '@/views/bpm/processInstance/detail/ProcessInstanceTimeline.vue'
+import * as ProcessInstanceApi from '@/api/bpm/processInstance'
+import { CandidateStrategy, NodeId } from '@/components/SimpleProcessDesignerV2/src/consts'
+import { ApprovalNodeInfo } from '@/api/bpm/processInstance'
+
+defineOptions({ name: 'BpmOALeaveCreate' })
+
+const message = useMessage() // 娑堟伅寮圭獥
+const { delView } = useTagsViewStore() // 瑙嗗浘鎿嶄綔
+const { push, currentRoute } = useRouter() // 璺敱
+const { query } = useRoute() // 鏌ヨ鍙傛暟
+
+const formLoading = ref(false) // 琛ㄥ崟鐨勫姞杞戒腑锛�1锛変慨鏀规椂鐨勬暟鎹姞杞斤紱2锛夋彁浜ょ殑鎸夐挳绂佺敤
+const formData = ref({
+ type: undefined,
+ reason: undefined,
+ startTime: undefined,
+ endTime: undefined
+})
+const formRules = reactive({
+ type: [{ required: true, message: '璇峰亣绫诲瀷涓嶈兘涓虹┖', trigger: 'blur' }],
+ reason: [{ required: true, message: '璇峰亣鍘熷洜涓嶈兘涓虹┖', trigger: 'change' }],
+ startTime: [{ required: true, message: '璇峰亣寮�濮嬫椂闂翠笉鑳戒负绌�', trigger: 'change' }],
+ endTime: [{ required: true, message: '璇峰亣缁撴潫鏃堕棿涓嶈兘涓虹┖', trigger: 'change' }]
+})
+const formRef = ref() // 琛ㄥ崟 Ref
+
+// 瀹℃壒鐩稿叧锛氬彉閲�
+const processDefineKey = 'oa_leave' // 娴佺▼瀹氫箟 Key
+const startUserSelectTasks = ref([]) // 鍙戣捣浜洪渶瑕侀�夋嫨瀹℃壒浜虹殑鐢ㄦ埛浠诲姟鍒楄〃
+const startUserSelectAssignees = ref({}) // 鍙戣捣浜洪�夋嫨瀹℃壒浜虹殑鏁版嵁
+const tempStartUserSelectAssignees = ref({}) // 鍘嗗彶鍙戣捣浜洪�夋嫨瀹℃壒浜虹殑鏁版嵁锛岀敤浜庢瘡娆¤〃鍗曞彉鏇存椂锛屼复鏃朵繚瀛�
+const activityNodes = ref<ProcessInstanceApi.ApprovalNodeInfo[]>([]) // 瀹℃壒鑺傜偣淇℃伅
+const processDefinitionId = ref('')
+
+/** 鎻愪氦琛ㄥ崟 */
+const submitForm = async () => {
+ // 1.1 鏍¢獙琛ㄥ崟
+ if (!formRef) return
+ const valid = await formRef.value.validate()
+ if (!valid) return
+ // 1.2 瀹℃壒鐩稿叧锛氭牎楠屾寚瀹氬鎵逛汉
+ if (startUserSelectTasks.value?.length > 0) {
+ for (const userTask of startUserSelectTasks.value) {
+ if (
+ Array.isArray(startUserSelectAssignees.value[userTask.id]) &&
+ startUserSelectAssignees.value[userTask.id].length === 0
+ ) {
+ return message.warning(`璇烽�夋嫨${userTask.name}鐨勫鎵逛汉`)
+ }
+ }
+ }
+
+ // 2. 鎻愪氦璇锋眰
+ formLoading.value = true
+ try {
+ const data = { ...formData.value } as unknown as LeaveApi.LeaveVO
+ // 瀹℃壒鐩稿叧锛氳缃寚瀹氬鎵逛汉
+ if (startUserSelectTasks.value?.length > 0) {
+ data.startUserSelectAssignees = startUserSelectAssignees.value
+ }
+ await LeaveApi.createLeave(data)
+ message.success('鍙戣捣鎴愬姛')
+ // 鍏抽棴褰撳墠 Tab
+ delView(unref(currentRoute))
+ await push({ name: 'BpmOALeave' })
+ } finally {
+ formLoading.value = false
+ }
+}
+
+/** 瀹℃壒鐩稿叧锛氳幏鍙栧鎵硅鎯� */
+const getApprovalDetail = async () => {
+ try {
+ const data = await ProcessInstanceApi.getApprovalDetail({
+ processDefinitionId: processDefinitionId.value,
+ // TODO 灏忓寳锛氬彲浠ユ敮鎸� processDefinitionKey 鏌ヨ
+ activityId: NodeId.START_USER_NODE_ID,
+ processVariablesStr: JSON.stringify({ day: daysDifference() }) // 瑙e喅 GET 鏃犳硶浼犻�掑璞$殑闂锛屽悗绔� String 鍐嶈浆 JSON
+ })
+
+ if (!data) {
+ message.error('鏌ヨ涓嶅埌瀹℃壒璇︽儏淇℃伅锛�')
+ return
+ }
+ // 鑾峰彇瀹℃壒鑺傜偣锛屾樉绀� Timeline 鐨勬暟鎹�
+ activityNodes.value = data.activityNodes
+
+ // 鑾峰彇鍙戣捣浜鸿嚜閫夌殑浠诲姟
+ startUserSelectTasks.value = data.activityNodes?.filter(
+ (node: ApprovalNodeInfo) => CandidateStrategy.START_USER_SELECT === node.candidateStrategy
+ )
+ // 鎭㈠涔嬪墠鐨勯�夋嫨瀹℃壒浜�
+ if (startUserSelectTasks.value?.length > 0) {
+ for (const node of startUserSelectTasks.value) {
+ if (
+ tempStartUserSelectAssignees.value[node.id] &&
+ tempStartUserSelectAssignees.value[node.id].length > 0
+ ) {
+ startUserSelectAssignees.value[node.id] = tempStartUserSelectAssignees.value[node.id]
+ } else {
+ startUserSelectAssignees.value[node.id] = []
+ }
+ }
+ }
+ } finally {
+ }
+}
+
+/** 瀹℃壒鐩稿叧锛氶�夋嫨鍙戣捣浜� */
+const selectUserConfirm = (id: string, userList: any[]) => {
+ startUserSelectAssignees.value[id] = userList?.map((item: any) => item.id)
+}
+
+// 璁$畻澶╂暟宸�
+// TODO @灏忓寳锛氬彲浠ユ悶鍒� formatTime 閲岄潰鍘伙紝鐒跺悗鐪嬬湅 dayjs 閲岄潰鏈夋病鏈夌幇鎴愮殑鏂规硶锛屾垨鑰呰緟鍔╄绠楃殑鏂规硶銆�
+const daysDifference = () => {
+ const oneDay = 24 * 60 * 60 * 1000 // 涓�澶╃殑姣鏁�
+ const diffTime = Math.abs(Number(formData.value.endTime) - Number(formData.value.startTime))
+ return Math.floor(diffTime / oneDay)
+}
+
+/** 鑾峰彇璇峰亣鏁版嵁锛岀敤浜庨噸鏂板彂璧锋椂鑷姩濉厖 */
+const getDetail = async (id: number) => {
+ try {
+ formLoading.value = true
+ const data = await LeaveApi.getLeave(id)
+ if (!data) {
+ message.error('閲嶆柊鍙戣捣璇峰亣澶辫触锛屽師鍥狅細璇峰亣鏁版嵁涓嶅瓨鍦�')
+ return
+ }
+ formData.value = {
+ type: data.type,
+ reason: data.reason,
+ startTime: data.startTime,
+ endTime: data.endTime
+ }
+ } finally {
+ formLoading.value = false
+ }
+}
+
+/** 鍒濆鍖� */
+onMounted(async () => {
+ // TODO @灏忓寳锛氳繖閲屽彲浠ョ畝鍖栵紝缁熶竴閫氳繃 getApprovalDetail 澶勭悊涔堬紵
+ const processDefinitionDetail = await DefinitionApi.getProcessDefinition(
+ undefined,
+ processDefineKey
+ )
+
+ if (!processDefinitionDetail) {
+ message.error('OA 璇峰亣鐨勬祦绋嬫ā鍨嬫湭閰嶇疆锛岃妫�鏌ワ紒')
+ return
+ }
+ processDefinitionId.value = processDefinitionDetail.id
+ startUserSelectTasks.value = processDefinitionDetail.startUserSelectTasks
+
+ // 濡傛灉鏈変笟鍔$紪鍙凤紝璇存槑鏄噸鏂板彂璧凤紝闇�瑕佸姞杞藉師鏈夋暟鎹�
+ if (query.id) {
+ await getDetail(Number(query.id))
+ }
+
+ // 瀹℃壒鐩稿叧锛氬姞杞芥渶鏂扮殑瀹℃壒璇︽儏锛屼富瑕佺敤浜庤妭鐐归娴�
+ await getApprovalDetail()
+})
+
+/** 瀹℃壒鐩稿叧锛氶娴嬫祦绋嬭妭鐐逛細鍥犱负杈撳叆鐨勫弬鏁板�艰�屼骇鐢熸柊鐨勯娴嬬粨鏋滃�硷紝鎵�浠ラ渶閲嶆柊棰勬祴涓�娆�, formData.value鍙敼鎴愬疄闄呬笟鍔′腑鐨勭壒瀹氬瓧娈� */
+watch(
+ formData.value,
+ (newValue, oldValue) => {
+ if (!oldValue) {
+ return
+ }
+ if (newValue && Object.keys(newValue).length > 0) {
+ // 璁板綍涔嬪墠鐨勮妭鐐瑰鎵逛汉
+ tempStartUserSelectAssignees.value = startUserSelectAssignees.value
+ startUserSelectAssignees.value = {}
+ // 鍔犺浇鏈�鏂扮殑瀹℃壒璇︽儏,涓昏鐢ㄤ簬鑺傜偣棰勬祴
+ getApprovalDetail()
+ }
+ },
+ {
+ immediate: true
+ }
+)
+</script>
--
Gitblit v1.8.0