From b59518d5c068ae8e6e32cce90ccf281bf81dc54a Mon Sep 17 00:00:00 2001
From: 云 <2163098428@qq.com>
Date: 星期三, 19 八月 2026 14:34:39 +0800
Subject: [PATCH] feat(collaborativeApproval): 添加用印审批功能支持
---
src/views/collaborativeApproval/sealManagement/index.vue | 290 ++++++++++++++++++++++++++++++++++------------------------
1 files changed, 170 insertions(+), 120 deletions(-)
diff --git a/src/views/collaborativeApproval/sealManagement/index.vue b/src/views/collaborativeApproval/sealManagement/index.vue
index 7a02751..e4a08ef 100644
--- a/src/views/collaborativeApproval/sealManagement/index.vue
+++ b/src/views/collaborativeApproval/sealManagement/index.vue
@@ -7,7 +7,6 @@
</div>
</template>
-
<!-- 鐢ㄥ嵃鐢宠绠$悊 -->
<div class="tab-content">
<el-row :gutter="20" class="mb-20 ">
@@ -75,22 +74,39 @@
<el-form-item label="鐢宠鍘熷洜" prop="reason">
<el-input v-model="sealForm.reason" type="textarea" :rows="4" placeholder="璇疯缁嗚鏄庣敤鍗板師鍥�" />
</el-form-item>
- <el-form-item label="瀹℃壒浜�" prop="approveUserId">
- <el-select v-model="sealForm.approveUserId" placeholder="璇烽�夋嫨瀹℃壒浜�" style="width: 100%" filterable>
- <el-option
- v-for="user in userList"
- :key="user.userId"
- :label="user.nickName"
- :value="user.userId"
- />
- </el-select>
- </el-form-item>
<el-form-item label="绱ф�ョ▼搴�" prop="urgency">
<el-radio-group v-model="sealForm.urgency">
- <el-radio label="normal">鏅��</el-radio>
- <el-radio label="urgent">绱ф��</el-radio>
- <el-radio label="very-urgent">鐗规��</el-radio>
+ <el-radio value="normal">鏅��</el-radio>
+ <el-radio value="urgent">绱ф��</el-radio>
+ <el-radio value="very-urgent">鐗规��</el-radio>
</el-radio-group>
+ </el-form-item>
+ <el-form-item label="闄勪欢涓婁紶">
+ <el-upload
+ multiple
+ :show-file-list="false"
+ :action="sealUploadUrl"
+ name="files"
+ :headers="uploadHeaders"
+ :limit="10"
+ :before-upload="handleBeforeUpload"
+ :on-success="handleUploadSuccess"
+ :on-error="handleUploadError"
+ :on-exceed="handleUploadExceed"
+ >
+ <el-button type="primary">鐐瑰嚮涓婁紶闄勪欢</el-button>
+ </el-upload>
+ <el-table v-if="sealForm.attachmentList.length" :data="sealForm.attachmentList" border class="attachment-table">
+ <el-table-column label="闄勪欢鍚嶇О" show-overflow-tooltip>
+ <template #default="scope">{{ scope.row.name }}</template>
+ </el-table-column>
+ <el-table-column label="鎿嶄綔" width="140" align="center">
+ <template #default="scope">
+ <el-button link type="primary" size="small" @click="previewFile(scope.row)">棰勮</el-button>
+ <el-button link type="danger" size="small" @click="removeAttachment(scope.$index)">鍒犻櫎</el-button>
+ </template>
+ </el-table-column>
+ </el-table>
</el-form-item>
</el-form>
</FormDialog>
@@ -119,21 +135,41 @@
</el-descriptions-item>
<el-descriptions-item label="鐢宠鍘熷洜" :span="2">{{ currentSealDetail.reason }}</el-descriptions-item>
</el-descriptions>
+ <!-- 闄勪欢鍒楄〃 -->
+ <div v-if="currentSealDetail.commonFileList?.length" class="attachment-section">
+ <div class="attachment-title">闄勪欢鍒楄〃锛�</div>
+ <el-table :data="currentSealDetail.commonFileList" border class="attachment-table">
+ <el-table-column label="闄勪欢鍚嶇О" show-overflow-tooltip>
+ <template #default="scope">
+ {{ scope.row.originalFilename || scope.row.name || scope.row.fileName || '鏈懡鍚嶆枃浠�' }}
+ </template>
+ </el-table-column>
+ <el-table-column fixed="right" label="鎿嶄綔" width="150" align="center">
+ <template #default="scope">
+ <el-button link type="primary" size="small" @click="previewFile(scope.row)">棰勮</el-button>
+ <el-button link type="primary" size="small" @click="downloadFile(scope.row)">涓嬭浇</el-button>
+ </template>
+ </el-table-column>
+ </el-table>
+ </div>
</div>
</FormDialog>
+ <!-- 鏂囦欢棰勮缁勪欢 -->
+ <FilePreview ref="filePreviewRef" />
</div>
</template>
<script setup>
-import { ref, reactive, onMounted, getCurrentInstance, watch } from 'vue'
+import { ref, reactive, onMounted, getCurrentInstance } from 'vue'
import { useRoute } from 'vue-router'
-import { ElMessage, ElMessageBox } from 'element-plus'
-import { listSealApplication, addSealApplication, updateSealApplication } from '@/api/collaborativeApproval/sealManagement.js'
-import { userListNoPageByTenantId } from '@/api/system/user.js'
+import { ElMessage } from 'element-plus'
+import { listSealApplication, addSealApplication } from '@/api/collaborativeApproval/sealManagement.js'
import useUserStore from '@/store/modules/user'
+import { getToken } from '@/utils/auth'
import FormDialog from '@/components/Dialog/FormDialog.vue'
import PIMTable from '@/components/PIMTable/PIMTable.vue'
+import FilePreview from '@/components/filePreview/index.vue'
// 鍝嶅簲寮忔暟鎹�
// 鐢ㄥ嵃鐢宠鐩稿叧
@@ -143,24 +179,27 @@
const tableLoading = ref(false)
const showSealDetailDialog = ref(false)
const currentSealDetail = ref(null)
+const filePreviewRef = ref(null)
const sealFormRef = ref()
-const userList = ref([])
+// 闄勪欢涓婁紶锛堟湰鍦颁笂浼狅紝闈� minio锛岃繑鍥� [{ name, url }]锛�
+const sealUploadUrl = import.meta.env.VITE_APP_BASE_API + '/common/uploadsList'
+const uploadHeaders = ref({ Authorization: 'Bearer ' + getToken() })
const sealForm = reactive({
+ id: null,
applicationNum: '',
title: '',
sealType: '',
reason: '',
- approveUserId: '',
urgency: 'normal',
- status: 'pending'
+ status: 'pending',
+ attachmentList: []
})
const sealRules = {
applicationNum: [{ required: true, message: '璇疯緭鍏ョ敵璇风紪鍙�', trigger: 'blur' }],
title: [{ required: true, message: '璇疯緭鍏ョ敵璇锋爣棰�', trigger: 'blur' }],
sealType: [{ required: true, message: '璇烽�夋嫨鐢ㄥ嵃绫诲瀷', trigger: 'change' }],
- reason: [{ required: true, message: '璇疯緭鍏ョ敵璇峰師鍥�', trigger: 'blur' }],
- approveUserId: [{ required: true, message: '璇烽�夋嫨瀹℃壒浜�', trigger: 'change' }]
+ reason: [{ required: true, message: '璇疯緭鍏ョ敵璇峰師鍥�', trigger: 'blur' }]
}
const sealSearchForm = reactive({
@@ -209,9 +248,9 @@
// 鐢ㄥ嵃鐢宠琛ㄦ牸鍒楅厤缃紙闇�鍦� getStatusText/getSealTypeText 绛変箣鍚庡畾涔夛級
const sealTableColumn = ref([
- { label: '鐢宠缂栧彿', prop: 'applicationNum',},
+ { label: '鐢宠缂栧彿', prop: 'applicationNum' },
{ label: '鐢宠鏍囬', prop: 'title', showOverflowTooltip: true },
- { label: '鐢宠浜�', prop: 'createUserName', },
+ { label: '鐢宠浜�', prop: 'createUserName' },
{ label: '鎵�灞為儴闂�', prop: 'department', width: 150 },
{
label: '鐢ㄥ嵃绫诲瀷',
@@ -229,40 +268,27 @@
formatData: (v) => getStatusText(v),
formatType: (v) => getStatusType(v)
},
- { label: '瀹℃壒浜�', prop: 'approveUserName', width: 120 },
{
dataType: 'action',
label: '鎿嶄綔',
- width: 250,
+ width: 150,
fixed: 'right',
align: 'center',
operation: [
- { name: '鏌ョ湅', clickFun: (row) => viewSealDetail(row) },
- {
- name: '瀹℃壒',
- clickFun: (row) => approveSeal(row),
- showHide: (row) => row.status === 'pending' && row.approveUserId === userStore.id
- },
- {
- name: '鎷掔粷',
- clickFun: (row) => rejectSeal(row),
- showHide: (row) => row.status === 'pending' && row.approveUserId === userStore.id
- },
{
name: '閲嶆柊鐢宠',
clickFun: (row) => reapplySeal(row),
- showHide: (row) => row.status === 'rejected' && row.createUser === userStore.id
- }
+ showHide: (row) => row.status === 'rejected' && Number(userStore.id) === row.createUser
+ },
+ { name: '璇︽儏', clickFun: (row) => viewSealDetail(row) }
]
}
])
// 鎼滅储鍗扮珷鐢宠
const searchSealApplications = () => {
- page.current=1
+ page.current = 1
getSealApplicationList()
-
- // ElMessage.success('鎼滅储瀹屾垚')
}
// 閲嶇疆鍗扮珷鐢宠鎼滅储
const resetSealSearch = () => {
@@ -271,43 +297,52 @@
sealSearchForm.applicationNum = ''
searchSealApplications()
}
-// 鎻愪氦鐢ㄥ嵃鐢宠
+
+// 閲嶆柊鐢宠鐢ㄥ嵃
+const reapplySeal = (row) => {
+ // 棰勫~琛ㄥ崟鏁版嵁
+ Object.assign(sealForm, {
+ id: row.id,
+ applicationNum: row.applicationNum,
+ title: row.title,
+ sealType: row.sealType,
+ reason: row.reason,
+ urgency: row.urgency || 'normal',
+ status: 'pending',
+ attachmentList: row.commonFileList || []
+ })
+ showSealApplyDialog.value = true
+}
+
+// 鎻愪氦鐢ㄥ嵃鐢宠锛堟柊澧炰笌閲嶆柊鐢宠鍧囪蛋 add 鎺ュ彛锛氶噸鏂扮敵璇蜂細閲嶆柊鍙戣捣鍗忓悓瀹℃壒娴佺▼锛�
const submitSealApplication = async () => {
try {
await sealFormRef.value.validate()
addSealApplication(sealForm).then(res => {
- if(res.code == 200){
- ElMessage.success('鐢宠鎻愪氦鎴愬姛')
+ if (res.code == 200) {
+ ElMessage.success(sealForm.id ? '閲嶆柊鐢宠鎴愬姛' : '鐢宠鎻愪氦鎴愬姛')
closeSealApplyDialog()
getSealApplicationList()
- Object.assign(sealForm, {
- applicationNum: '',
- title: '',
- sealType: '',
- reason: '',
- approveUserId: '',
- urgency: 'normal',
- status: 'pending'
- })
}
}).catch(err => {
console.log(err.msg)
})
-
} catch (error) {
}
}
+
// 鍏抽棴鐢ㄥ嵃鐢宠瀵硅瘽妗�
const closeSealApplyDialog = () => {
// 娓呯┖琛ㄥ崟鏁版嵁
Object.assign(sealForm, {
+ id: null,
applicationNum: '',
title: '',
sealType: '',
reason: '',
- approveUserId: '',
urgency: 'normal',
- status: 'pending'
+ status: 'pending',
+ attachmentList: []
})
// 娓呴櫎琛ㄥ崟楠岃瘉鐘舵��
if (sealFormRef.value) {
@@ -325,55 +360,64 @@
currentSealDetail.value = row
showSealDetailDialog.value = true
}
-// 瀹℃壒鐢ㄥ嵃鐢宠
-const approveSeal = (row) => {
- ElMessageBox.confirm('纭閫氳繃璇ョ敤鍗扮敵璇凤紵', '鎻愮ず', {
- confirmButtonText: '纭畾',
- cancelButtonText: '鍙栨秷',
- type: 'warning'
- }).then(() => {
- row.status = 'approved'
- updateSealApplication(row).then(res => {
- if(res.code == 200){
- ElMessage.success('瀹℃壒閫氳繃')
- getSealApplicationList()
- }
- })
- })
+
+// 闄勪欢涓婁紶鍓嶆牎楠岋紙鍗曚釜鏂囦欢涓嶈秴杩� 50MB锛�
+const handleBeforeUpload = (file) => {
+ if (file.size / 1024 / 1024 > 50) {
+ ElMessage.error('鏂囦欢澶у皬涓嶈兘瓒呰繃 50MB')
+ return false
+ }
+ return true
}
-// 鎷掔粷鐢ㄥ嵃鐢宠
-const rejectSeal = (row) => {
- ElMessageBox.prompt('璇疯緭鍏ユ嫆缁濆師鍥�', '鎻愮ず', {
- confirmButtonText: '纭畾',
- cancelButtonText: '鍙栨秷',
- inputPattern: /\S+/,
- inputErrorMessage: '鎷掔粷鍘熷洜涓嶈兘涓虹┖'
- }).then(({ value }) => {
- row.status = 'rejected'
- updateSealApplication(row).then(res => {
- if(res.code == 200){
- ElMessage.success('宸叉嫆缁濈敵璇�')
- getSealApplicationList()
- }
- })
- })
+// 闄勪欢涓婁紶鎴愬姛鍥炶皟
+const handleUploadSuccess = (res) => {
+ if (res.code === 200) {
+ const list = res.data || []
+ list.forEach(item => sealForm.attachmentList.push({ name: item.name, url: item.url }))
+ ElMessage.success('涓婁紶鎴愬姛')
+ } else {
+ ElMessage.error(res.msg || '涓婁紶澶辫触')
+ }
+}
+// 闄勪欢涓婁紶澶辫触鍥炶皟
+const handleUploadError = () => {
+ ElMessage.error('闄勪欢涓婁紶澶辫触')
+}
+// 闄勪欢鏁伴噺瓒呭嚭
+const handleUploadExceed = () => {
+ ElMessage.warning('鏈�澶氫笂浼� 10 涓檮浠�')
+}
+// 鍒犻櫎寰呮彁浜ら檮浠�
+const removeAttachment = (index) => {
+ sealForm.attachmentList.splice(index, 1)
+}
+// 棰勮鏂囦欢锛堝畬鏁村彲璁块棶 URL锛岀洿鎺ユ墦寮�锛屼笉鎷� host锛�
+const previewFile = (row) => {
+ const url = row.previewURL || row.previewUrl || row.url
+ if (url && filePreviewRef.value) {
+ filePreviewRef.value.openUrl(url)
+ } else {
+ ElMessage.warning('鏂囦欢鍦板潃鏃犳晥锛屾棤娉曢瑙�')
+ }
}
-// 閲嶆柊鐢宠鐢ㄥ嵃
-const reapplySeal = (row) => {
- // 棰勫~琛ㄥ崟鏁版嵁
- Object.assign(sealForm, {
- applicationNum: row.applicationNum,
- title: row.title,
- sealType: row.sealType,
- reason: row.reason,
- approveUserId: row.approveUserId,
- urgency: row.urgency || 'normal',
- status: 'pending'
- })
- showSealApplyDialog.value = true
+// 涓嬭浇鏂囦欢
+const downloadFile = (row) => {
+ const url = row.downloadURL || row.downloadUrl || row.url
+ if (url) {
+ const filename = row.originalFilename || row.name || row.fileName || 'download'
+ const a = document.createElement('a')
+ a.href = url
+ a.download = filename
+ a.target = '_blank'
+ a.rel = 'noopener noreferrer'
+ document.body.appendChild(a)
+ a.click()
+ document.body.removeChild(a)
+ } else {
+ ElMessage.warning('鏂囦欢鍦板潃鏃犳晥锛屾棤娉曚笅杞�')
+ }
}
-
// 瀵煎嚭鐢ㄥ嵃鐢宠
const { proxy } = getCurrentInstance()
const handleExport = () => {
@@ -384,13 +428,13 @@
const getSealApplicationList = async () => {
tableLoading.value = true
listSealApplication(page, sealSearchForm)
- .then(res => {
- sealApplications.value = res.data.records
- page.total = res.data.total
- tableLoading.value = false
- }).catch(err => {
- tableLoading.value = false
- })
+ .then(res => {
+ sealApplications.value = res.data.records
+ page.total = res.data.total
+ tableLoading.value = false
+ }).catch(err => {
+ tableLoading.value = false
+ })
}
// 鍒嗛〉鍙樺寲澶勭悊
const paginationChange = (obj) => {
@@ -398,15 +442,6 @@
page.size = obj.limit;
getSealApplicationList();
};
-
-// 鐩戝惉瀵硅瘽妗嗘墦寮�锛岃幏鍙栫敤鎴峰垪琛�
-watch(showSealApplyDialog, (newVal) => {
- if (newVal) {
- userListNoPageByTenantId().then((res) => {
- userList.value = res.data;
- });
- }
-});
onMounted(() => {
// 璺敱鎼哄甫 applicationNum 鏃讹紝棰勫~骞舵煡璇�
@@ -442,4 +477,19 @@
.ml-10 {
margin-left: 10px;
}
-</style>
+
+.attachment-section {
+ margin-top: 20px;
+}
+
+.attachment-title {
+ font-size: 14px;
+ color: #606266;
+ margin-bottom: 10px;
+ font-weight: 500;
+}
+
+.attachment-table {
+ border-radius: 4px;
+}
+</style>
\ No newline at end of file
--
Gitblit v1.9.3