采购文件审批
This commit is contained in:
131
src/api/finance/purchasingdoc.ts
Normal file
131
src/api/finance/purchasingdoc.ts
Normal file
@@ -0,0 +1,131 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2018-2025, cyweb All rights reserved.
|
||||||
|
*
|
||||||
|
* Redistribution and use in source and binary forms, with or without
|
||||||
|
* modification, are permitted provided that the following conditions are met:
|
||||||
|
*
|
||||||
|
* Redistributions of source code must retain the above copyright notice,
|
||||||
|
* this list of conditions and the following disclaimer.
|
||||||
|
* Redistributions in binary form must reproduce the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer in the
|
||||||
|
* documentation and/or other materials provided with the distribution.
|
||||||
|
* Neither the name of the pig4cloud.com developer nor the names of its
|
||||||
|
* contributors may be used to endorse or promote products derived from
|
||||||
|
* this software without specific prior written permission.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
import request from '/@/utils/request';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取采购文件列表(含历史版本)
|
||||||
|
* @param applyId 采购申请ID
|
||||||
|
*/
|
||||||
|
export function getDocList(applyId: number | string) {
|
||||||
|
return request({
|
||||||
|
url: '/purchase/purchasingdoc/list/' + applyId,
|
||||||
|
method: 'get'
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 上传采购文件(招标代理)
|
||||||
|
* @param data 文件信息
|
||||||
|
*/
|
||||||
|
export function uploadDoc(data: any) {
|
||||||
|
return request({
|
||||||
|
url: '/purchase/purchasingdoc/upload',
|
||||||
|
method: 'post',
|
||||||
|
data
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 重新上传采购文件
|
||||||
|
* @param data 文件信息
|
||||||
|
*/
|
||||||
|
export function reuploadDoc(data: any) {
|
||||||
|
return request({
|
||||||
|
url: '/purchase/purchasingdoc/reupload',
|
||||||
|
method: 'post',
|
||||||
|
data
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取采购文件下载地址
|
||||||
|
* @param id 采购文件ID
|
||||||
|
*/
|
||||||
|
export function getDocDownloadUrl(id: number | string) {
|
||||||
|
return `/purchase/purchasingdoc/download/${id}`;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 确认无误
|
||||||
|
* @param data 审核信息
|
||||||
|
*/
|
||||||
|
export function confirmDoc(data: any) {
|
||||||
|
return request({
|
||||||
|
url: '/purchase/purchasingdoc/confirm',
|
||||||
|
method: 'post',
|
||||||
|
data
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 退回修改
|
||||||
|
* @param data 审核信息
|
||||||
|
*/
|
||||||
|
export function returnDoc(data: any) {
|
||||||
|
return request({
|
||||||
|
url: '/purchase/purchasingdoc/return',
|
||||||
|
method: 'post',
|
||||||
|
data
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 确认流程结束
|
||||||
|
* @param applyId 采购申请ID
|
||||||
|
*/
|
||||||
|
export function completeDoc(applyId: number | string) {
|
||||||
|
return request({
|
||||||
|
url: '/purchase/purchasingdoc/complete',
|
||||||
|
method: 'post',
|
||||||
|
params: { applyId }
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取审核记录
|
||||||
|
* @param applyId 采购申请ID
|
||||||
|
*/
|
||||||
|
export function getAuditRecords(applyId: number | string) {
|
||||||
|
return request({
|
||||||
|
url: '/purchase/purchasingdoc/audit-records/' + applyId,
|
||||||
|
method: 'get'
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取待审核列表
|
||||||
|
* @param params 分页参数
|
||||||
|
*/
|
||||||
|
export function getMyPending(params?: any) {
|
||||||
|
return request({
|
||||||
|
url: '/purchase/purchasingdoc/my-pending',
|
||||||
|
method: 'get',
|
||||||
|
params
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取可执行操作
|
||||||
|
* @param applyId 采购申请ID
|
||||||
|
*/
|
||||||
|
export function getAvailableActions(applyId: number | string) {
|
||||||
|
return request({
|
||||||
|
url: '/purchase/purchasingdoc/actions/' + applyId,
|
||||||
|
method: 'get'
|
||||||
|
});
|
||||||
|
}
|
||||||
@@ -0,0 +1,65 @@
|
|||||||
|
<template>
|
||||||
|
<el-table :data="records" stripe v-loading="loading" max-height="400">
|
||||||
|
<el-table-column prop="operateTypeDesc" label="操作类型" width="100" align="center">
|
||||||
|
<template #default="scope">
|
||||||
|
<el-tag :type="getOperateTypeStyle(scope.row.operateType)">
|
||||||
|
{{ scope.row.operateTypeDesc }}
|
||||||
|
</el-tag>
|
||||||
|
</template>
|
||||||
|
</el-table-column>
|
||||||
|
<el-table-column prop="operateRoleDesc" label="操作角色" width="100" />
|
||||||
|
<el-table-column prop="operateByName" label="操作人" width="100" />
|
||||||
|
<el-table-column prop="currentVersion" label="文件版本" width="80" align="center" />
|
||||||
|
<el-table-column prop="remark" label="批注意见" min-width="200" show-overflow-tooltip>
|
||||||
|
<template #default="scope">
|
||||||
|
{{ scope.row.remark || '-' }}
|
||||||
|
</template>
|
||||||
|
</el-table-column>
|
||||||
|
<el-table-column prop="operateTime" label="操作时间" width="160" />
|
||||||
|
</el-table>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script setup lang="ts">
|
||||||
|
import { ref, watch } from 'vue'
|
||||||
|
import { getAuditRecords } from '/@/api/finance/purchasingdoc'
|
||||||
|
|
||||||
|
const props = defineProps<{
|
||||||
|
applyId: number | string
|
||||||
|
}>()
|
||||||
|
|
||||||
|
const records = ref<any[]>([])
|
||||||
|
const loading = ref(false)
|
||||||
|
|
||||||
|
const loadRecords = async () => {
|
||||||
|
if (!props.applyId) return
|
||||||
|
loading.value = true
|
||||||
|
try {
|
||||||
|
const res = await getAuditRecords(props.applyId)
|
||||||
|
records.value = res.data || []
|
||||||
|
} catch (e) {
|
||||||
|
records.value = []
|
||||||
|
} finally {
|
||||||
|
loading.value = false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const refresh = () => {
|
||||||
|
loadRecords()
|
||||||
|
}
|
||||||
|
|
||||||
|
const getOperateTypeStyle = (type: string) => {
|
||||||
|
const styleMap: Record<string, string> = {
|
||||||
|
'UPLOAD': 'primary',
|
||||||
|
'CONFIRM': 'success',
|
||||||
|
'RETURN': 'warning',
|
||||||
|
'COMPLETE': 'success'
|
||||||
|
}
|
||||||
|
return styleMap[type] || 'info'
|
||||||
|
}
|
||||||
|
|
||||||
|
watch(() => props.applyId, () => {
|
||||||
|
loadRecords()
|
||||||
|
}, { immediate: true })
|
||||||
|
|
||||||
|
defineExpose({ refresh })
|
||||||
|
</script>
|
||||||
@@ -0,0 +1,323 @@
|
|||||||
|
<template>
|
||||||
|
<el-dialog
|
||||||
|
v-model="visible"
|
||||||
|
title="采购文件审核"
|
||||||
|
width="900px"
|
||||||
|
destroy-on-close
|
||||||
|
@close="handleClose">
|
||||||
|
<el-tabs v-model="activeTab">
|
||||||
|
<!-- 项目信息 -->
|
||||||
|
<el-tab-pane label="项目信息" name="info">
|
||||||
|
<el-descriptions :column="2" border>
|
||||||
|
<el-descriptions-item label="采购编号">{{ applyInfo.purchaseNo }}</el-descriptions-item>
|
||||||
|
<el-descriptions-item label="项目名称">{{ applyInfo.projectName }}</el-descriptions-item>
|
||||||
|
<el-descriptions-item label="需求部门">{{ applyInfo.deptName }}</el-descriptions-item>
|
||||||
|
<el-descriptions-item label="预算金额">{{ applyInfo.budget ? Number(applyInfo.budget).toLocaleString() + '元' : '-' }}</el-descriptions-item>
|
||||||
|
<el-descriptions-item label="招标代理">{{ applyInfo.agentName || '-' }}</el-descriptions-item>
|
||||||
|
<el-descriptions-item label="审核状态">
|
||||||
|
<el-tag :type="getStatusType(applyInfo.docAuditStatus)">
|
||||||
|
{{ getStatusLabel(applyInfo.docAuditStatus) }}
|
||||||
|
</el-tag>
|
||||||
|
</el-descriptions-item>
|
||||||
|
</el-descriptions>
|
||||||
|
</el-tab-pane>
|
||||||
|
|
||||||
|
<!-- 采购需求文件 -->
|
||||||
|
<el-tab-pane label="采购需求文件" name="requirement">
|
||||||
|
<el-table :data="requirementFiles" stripe v-loading="requirementLoading">
|
||||||
|
<el-table-column prop="fileTitle" label="文件名称" min-width="200" show-overflow-tooltip />
|
||||||
|
<el-table-column prop="fileType" label="文件类型" width="120">
|
||||||
|
<template #default="scope">
|
||||||
|
{{ getFileTypeLabel(scope.row.fileType) }}
|
||||||
|
</template>
|
||||||
|
</el-table-column>
|
||||||
|
<el-table-column label="操作" width="100" align="center">
|
||||||
|
<template #default="scope">
|
||||||
|
<el-button type="primary" link icon="Download" @click="handleDownloadRequirement(scope.row)">
|
||||||
|
下载
|
||||||
|
</el-button>
|
||||||
|
</template>
|
||||||
|
</el-table-column>
|
||||||
|
</el-table>
|
||||||
|
</el-tab-pane>
|
||||||
|
|
||||||
|
<!-- 采购文件 -->
|
||||||
|
<el-tab-pane label="采购文件" name="doc">
|
||||||
|
<div class="doc-header">
|
||||||
|
<el-button v-if="canUpload" type="primary" icon="Upload" @click="handleUpload">
|
||||||
|
{{ applyInfo.docAuditStatus === 'RETURNED' ? '重新上传' : '上传文件' }}
|
||||||
|
</el-button>
|
||||||
|
</div>
|
||||||
|
<el-table :data="docList" stripe v-loading="docLoading">
|
||||||
|
<el-table-column prop="fileName" label="文件名称" min-width="200" show-overflow-tooltip />
|
||||||
|
<el-table-column prop="version" label="版本" width="80" align="center" />
|
||||||
|
<el-table-column prop="uploadByName" label="上传人" width="100" />
|
||||||
|
<el-table-column prop="uploadTime" label="上传时间" width="160" />
|
||||||
|
<el-table-column label="操作" width="100" align="center">
|
||||||
|
<template #default="scope">
|
||||||
|
<el-button type="primary" link icon="Download" @click="handleDownloadDoc(scope.row)">
|
||||||
|
下载
|
||||||
|
</el-button>
|
||||||
|
</template>
|
||||||
|
</el-table-column>
|
||||||
|
</el-table>
|
||||||
|
</el-tab-pane>
|
||||||
|
|
||||||
|
<!-- 审核记录 -->
|
||||||
|
<el-tab-pane label="审核记录" name="audit">
|
||||||
|
<AuditRecordList :apply-id="applyInfo.id" ref="auditRecordListRef" />
|
||||||
|
</el-tab-pane>
|
||||||
|
</el-tabs>
|
||||||
|
|
||||||
|
<!-- 操作区域 -->
|
||||||
|
<template #footer>
|
||||||
|
<div class="dialog-footer">
|
||||||
|
<el-button v-if="canConfirm" type="success" @click="handleConfirm">确认无误</el-button>
|
||||||
|
<el-button v-if="canReturn" type="warning" @click="handleReturn">退回修改</el-button>
|
||||||
|
<el-button v-if="canComplete" type="primary" @click="handleComplete">确认流程结束</el-button>
|
||||||
|
<el-button @click="handleClose">关闭</el-button>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<!-- 退回原因弹窗 -->
|
||||||
|
<el-dialog v-model="returnDialogVisible" title="退回原因" width="400px" append-to-body>
|
||||||
|
<el-form>
|
||||||
|
<el-form-item label="退回原因">
|
||||||
|
<el-input v-model="returnRemark" type="textarea" :rows="3" placeholder="请输入退回原因" />
|
||||||
|
</el-form-item>
|
||||||
|
</el-form>
|
||||||
|
<template #footer>
|
||||||
|
<el-button @click="returnDialogVisible = false">取消</el-button>
|
||||||
|
<el-button type="primary" @click="submitReturn">确定</el-button>
|
||||||
|
</template>
|
||||||
|
</el-dialog>
|
||||||
|
</el-dialog>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script setup lang="ts">
|
||||||
|
import { ref, computed, defineAsyncComponent } from 'vue'
|
||||||
|
import { useMessage, useMessageBox } from '/@/hooks/message'
|
||||||
|
import { getObj, getApplyFiles } from '/@/api/finance/purchasingrequisition'
|
||||||
|
import { getDocList, uploadDoc, reuploadDoc, confirmDoc, returnDoc, completeDoc, getAvailableActions, getDocDownloadUrl } from '/@/api/finance/purchasingdoc'
|
||||||
|
import other from '/@/utils/other'
|
||||||
|
|
||||||
|
const AuditRecordList = defineAsyncComponent(() => import('./AuditRecordList.vue'));
|
||||||
|
|
||||||
|
const emit = defineEmits(['refresh']);
|
||||||
|
|
||||||
|
const visible = ref(false)
|
||||||
|
const activeTab = ref('info')
|
||||||
|
const applyInfo = ref<any>({})
|
||||||
|
const requirementFiles = ref<any[]>([])
|
||||||
|
const requirementLoading = ref(false)
|
||||||
|
const docList = ref<any[]>([])
|
||||||
|
const docLoading = ref(false)
|
||||||
|
const auditRecordListRef = ref()
|
||||||
|
const availableActions = ref<string[]>([])
|
||||||
|
|
||||||
|
const returnDialogVisible = ref(false)
|
||||||
|
const returnRemark = ref('')
|
||||||
|
|
||||||
|
const canUpload = computed(() => availableActions.value.includes('upload'))
|
||||||
|
const canConfirm = computed(() => availableActions.value.includes('confirm'))
|
||||||
|
const canReturn = computed(() => availableActions.value.includes('return'))
|
||||||
|
const canComplete = computed(() => availableActions.value.includes('complete'))
|
||||||
|
|
||||||
|
const open = async (row: any) => {
|
||||||
|
visible.value = true
|
||||||
|
activeTab.value = 'info'
|
||||||
|
applyInfo.value = {}
|
||||||
|
requirementFiles.value = []
|
||||||
|
docList.value = []
|
||||||
|
returnRemark.value = ''
|
||||||
|
|
||||||
|
// 加载详情
|
||||||
|
try {
|
||||||
|
const res = await getObj(row.id)
|
||||||
|
applyInfo.value = res.data || res
|
||||||
|
} catch (e: any) {
|
||||||
|
useMessage().error(e?.msg || '加载项目信息失败')
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// 加载可执行操作
|
||||||
|
try {
|
||||||
|
const actionsRes = await getAvailableActions(row.id)
|
||||||
|
availableActions.value = actionsRes.data || []
|
||||||
|
} catch (e) {
|
||||||
|
availableActions.value = []
|
||||||
|
}
|
||||||
|
|
||||||
|
// 加载采购需求文件
|
||||||
|
loadRequirementFiles()
|
||||||
|
// 加载采购文件
|
||||||
|
loadDocList()
|
||||||
|
}
|
||||||
|
|
||||||
|
const loadRequirementFiles = async () => {
|
||||||
|
if (!applyInfo.value.id) return
|
||||||
|
requirementLoading.value = true
|
||||||
|
try {
|
||||||
|
const res = await getApplyFiles(applyInfo.value.id)
|
||||||
|
const files = res.data || res || []
|
||||||
|
// 过滤采购需求文件(fileType=120)
|
||||||
|
requirementFiles.value = files.filter((f: any) => f.fileType === '120')
|
||||||
|
} catch (e) {
|
||||||
|
requirementFiles.value = []
|
||||||
|
} finally {
|
||||||
|
requirementLoading.value = false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const loadDocList = async () => {
|
||||||
|
if (!applyInfo.value.id) return
|
||||||
|
docLoading.value = true
|
||||||
|
try {
|
||||||
|
const res = await getDocList(applyInfo.value.id)
|
||||||
|
docList.value = res.data || []
|
||||||
|
} catch (e) {
|
||||||
|
docList.value = []
|
||||||
|
} finally {
|
||||||
|
docLoading.value = false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const handleUpload = () => {
|
||||||
|
// 触发文件上传
|
||||||
|
const input = document.createElement('input')
|
||||||
|
input.type = 'file'
|
||||||
|
input.accept = '*/*'
|
||||||
|
input.onchange = async (e: any) => {
|
||||||
|
const file = e.target.files[0]
|
||||||
|
if (!file) return
|
||||||
|
// TODO: 实现文件上传到OSS,然后调用上传接口
|
||||||
|
useMessage().info('文件上传功能需要配合OSS实现')
|
||||||
|
}
|
||||||
|
input.click()
|
||||||
|
}
|
||||||
|
|
||||||
|
const handleDownloadRequirement = (row: any) => {
|
||||||
|
if (row.remark) {
|
||||||
|
const url = `/purchase/purchasingfiles/download?fileName=${encodeURIComponent(row.remark)}&fileTitle=${encodeURIComponent(row.fileTitle)}`
|
||||||
|
other.downBlobFile(url, {}, row.fileTitle)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const handleDownloadDoc = (row: any) => {
|
||||||
|
const url = getDocDownloadUrl(row.id)
|
||||||
|
other.downBlobFile(url, {}, row.fileName)
|
||||||
|
}
|
||||||
|
|
||||||
|
const handleConfirm = async () => {
|
||||||
|
try {
|
||||||
|
await useMessageBox().confirm('确定要确认该采购文件无误吗?')
|
||||||
|
} catch {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
await confirmDoc({ applyId: applyInfo.value.id })
|
||||||
|
useMessage().success('确认成功')
|
||||||
|
emit('refresh')
|
||||||
|
loadDocList()
|
||||||
|
auditRecordListRef.value?.refresh()
|
||||||
|
// 重新加载可执行操作
|
||||||
|
const actionsRes = await getAvailableActions(applyInfo.value.id)
|
||||||
|
availableActions.value = actionsRes.data || []
|
||||||
|
} catch (e: any) {
|
||||||
|
useMessage().error(e?.msg || '确认失败')
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const handleReturn = () => {
|
||||||
|
returnRemark.value = ''
|
||||||
|
returnDialogVisible.value = true
|
||||||
|
}
|
||||||
|
|
||||||
|
const submitReturn = async () => {
|
||||||
|
try {
|
||||||
|
await returnDoc({ applyId: applyInfo.value.id, remark: returnRemark.value })
|
||||||
|
useMessage().success('退回成功')
|
||||||
|
returnDialogVisible.value = false
|
||||||
|
emit('refresh')
|
||||||
|
loadDocList()
|
||||||
|
auditRecordListRef.value?.refresh()
|
||||||
|
// 重新加载可执行操作
|
||||||
|
const actionsRes = await getAvailableActions(applyInfo.value.id)
|
||||||
|
availableActions.value = actionsRes.data || []
|
||||||
|
} catch (e: any) {
|
||||||
|
useMessage().error(e?.msg || '退回失败')
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const handleComplete = async () => {
|
||||||
|
try {
|
||||||
|
await useMessageBox().confirm('确定要确认流程结束吗?')
|
||||||
|
} catch {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
await completeDoc(applyInfo.value.id)
|
||||||
|
useMessage().success('流程已结束')
|
||||||
|
emit('refresh')
|
||||||
|
loadDocList()
|
||||||
|
auditRecordListRef.value?.refresh()
|
||||||
|
// 重新加载可执行操作
|
||||||
|
const actionsRes = await getAvailableActions(applyInfo.value.id)
|
||||||
|
availableActions.value = actionsRes.data || []
|
||||||
|
} catch (e: any) {
|
||||||
|
useMessage().error(e?.msg || '操作失败')
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const handleClose = () => {
|
||||||
|
visible.value = false
|
||||||
|
}
|
||||||
|
|
||||||
|
const getStatusType = (status: string) => {
|
||||||
|
const typeMap: Record<string, string> = {
|
||||||
|
'PENDING_UPLOAD': 'info',
|
||||||
|
'ASSET_REVIEWING': 'warning',
|
||||||
|
'DEPT_REVIEWING': 'warning',
|
||||||
|
'AUDIT_REVIEWING': 'warning',
|
||||||
|
'ASSET_CONFIRMING': 'primary',
|
||||||
|
'COMPLETED': 'success',
|
||||||
|
'RETURNED': 'danger'
|
||||||
|
}
|
||||||
|
return typeMap[status] || 'info'
|
||||||
|
}
|
||||||
|
|
||||||
|
const getStatusLabel = (status: string) => {
|
||||||
|
const labelMap: Record<string, string> = {
|
||||||
|
'PENDING_UPLOAD': '待上传',
|
||||||
|
'ASSET_REVIEWING': '资产管理处审核中',
|
||||||
|
'DEPT_REVIEWING': '需求部门审核中',
|
||||||
|
'AUDIT_REVIEWING': '内审部门审核中',
|
||||||
|
'ASSET_CONFIRMING': '资产管理处确认中',
|
||||||
|
'COMPLETED': '已完成',
|
||||||
|
'RETURNED': '已退回'
|
||||||
|
}
|
||||||
|
return labelMap[status] || '-'
|
||||||
|
}
|
||||||
|
|
||||||
|
const getFileTypeLabel = (type: string) => {
|
||||||
|
const labelMap: Record<string, string> = {
|
||||||
|
'120': '采购需求表',
|
||||||
|
'130': '采购文件'
|
||||||
|
}
|
||||||
|
return labelMap[type] || type
|
||||||
|
}
|
||||||
|
|
||||||
|
defineExpose({ open })
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style scoped lang="scss">
|
||||||
|
.doc-header {
|
||||||
|
margin-bottom: 16px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.dialog-footer {
|
||||||
|
display: flex;
|
||||||
|
justify-content: flex-end;
|
||||||
|
gap: 8px;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
193
src/views/finance/purchasingrequisition/docAudit/index.vue
Normal file
193
src/views/finance/purchasingrequisition/docAudit/index.vue
Normal file
@@ -0,0 +1,193 @@
|
|||||||
|
<template>
|
||||||
|
<div class="modern-page-container">
|
||||||
|
<div class="page-wrapper">
|
||||||
|
<!-- 搜索表单卡片 -->
|
||||||
|
<el-card v-show="showSearch" class="search-card" shadow="never">
|
||||||
|
<template #header>
|
||||||
|
<div class="card-header">
|
||||||
|
<span class="card-title">
|
||||||
|
<el-icon class="title-icon"><Search /></el-icon>
|
||||||
|
筛选条件
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
<el-form :model="state.queryForm" ref="searchFormRef" :inline="true" @keyup.enter="getDataList" class="search-form">
|
||||||
|
<el-form-item label="采购编号" prop="purchaseNo">
|
||||||
|
<el-input
|
||||||
|
v-model="state.queryForm.purchaseNo"
|
||||||
|
placeholder="请输入采购编号"
|
||||||
|
clearable
|
||||||
|
style="width: 200px" />
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item label="项目名称" prop="projectName">
|
||||||
|
<el-input
|
||||||
|
v-model="state.queryForm.projectName"
|
||||||
|
placeholder="请输入项目名称"
|
||||||
|
clearable
|
||||||
|
style="width: 200px" />
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item label="审核状态" prop="docAuditStatus">
|
||||||
|
<el-select
|
||||||
|
v-model="state.queryForm.docAuditStatus"
|
||||||
|
placeholder="请选择审核状态"
|
||||||
|
clearable
|
||||||
|
style="width: 200px">
|
||||||
|
<el-option label="待上传" value="PENDING_UPLOAD" />
|
||||||
|
<el-option label="资产管理处审核中" value="ASSET_REVIEWING" />
|
||||||
|
<el-option label="需求部门审核中" value="DEPT_REVIEWING" />
|
||||||
|
<el-option label="内审部门审核中" value="AUDIT_REVIEWING" />
|
||||||
|
<el-option label="资产管理处确认中" value="ASSET_CONFIRMING" />
|
||||||
|
<el-option label="已完成" value="COMPLETED" />
|
||||||
|
<el-option label="已退回" value="RETURNED" />
|
||||||
|
</el-select>
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item>
|
||||||
|
<el-button type="primary" icon="Search" @click="getDataList">查询</el-button>
|
||||||
|
<el-button icon="Refresh" @click="handleReset">重置</el-button>
|
||||||
|
</el-form-item>
|
||||||
|
</el-form>
|
||||||
|
</el-card>
|
||||||
|
|
||||||
|
<!-- 内容卡片 -->
|
||||||
|
<el-card class="content-card" shadow="never">
|
||||||
|
<template #header>
|
||||||
|
<div class="card-header">
|
||||||
|
<span class="card-title">
|
||||||
|
<el-icon class="title-icon"><DocumentChecked /></el-icon>
|
||||||
|
采购文件审核
|
||||||
|
</span>
|
||||||
|
<div class="header-actions">
|
||||||
|
<right-toolbar v-model:showSearch="showSearch" class="ml10" @queryTable="getDataList" />
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<!-- 表格 -->
|
||||||
|
<el-table
|
||||||
|
ref="tableRef"
|
||||||
|
:data="state.dataList"
|
||||||
|
v-loading="state.loading"
|
||||||
|
stripe
|
||||||
|
:cell-style="tableStyle.cellStyle"
|
||||||
|
:header-cell-style="tableStyle.headerCellStyle"
|
||||||
|
class="modern-table">
|
||||||
|
<el-table-column type="index" label="序号" width="70" align="center">
|
||||||
|
<template #header>
|
||||||
|
<el-icon><List /></el-icon>
|
||||||
|
</template>
|
||||||
|
</el-table-column>
|
||||||
|
<el-table-column prop="purchaseNo" label="采购编号" min-width="140" show-overflow-tooltip />
|
||||||
|
<el-table-column prop="projectName" label="项目名称" min-width="200" show-overflow-tooltip />
|
||||||
|
<el-table-column prop="deptName" label="需求部门" min-width="150" show-overflow-tooltip />
|
||||||
|
<el-table-column prop="budget" label="预算金额(元)" width="120" align="right">
|
||||||
|
<template #default="scope">
|
||||||
|
{{ scope.row.budget ? Number(scope.row.budget).toLocaleString() : '-' }}
|
||||||
|
</template>
|
||||||
|
</el-table-column>
|
||||||
|
<el-table-column prop="docAuditStatus" label="审核状态" width="140" align="center">
|
||||||
|
<template #default="scope">
|
||||||
|
<el-tag :type="getStatusType(scope.row.docAuditStatus)">
|
||||||
|
{{ getStatusLabel(scope.row.docAuditStatus) }}
|
||||||
|
</el-tag>
|
||||||
|
</template>
|
||||||
|
</el-table-column>
|
||||||
|
<el-table-column prop="currentDocVersion" label="当前版本" width="100" align="center">
|
||||||
|
<template #default="scope">
|
||||||
|
{{ scope.row.currentDocVersion || '-' }}
|
||||||
|
</template>
|
||||||
|
</el-table-column>
|
||||||
|
<el-table-column label="操作" align="center" fixed="right" width="120">
|
||||||
|
<template #default="scope">
|
||||||
|
<el-button type="primary" link icon="View" @click="handleAudit(scope.row)">
|
||||||
|
审核
|
||||||
|
</el-button>
|
||||||
|
</template>
|
||||||
|
</el-table-column>
|
||||||
|
</el-table>
|
||||||
|
|
||||||
|
<!-- 分页 -->
|
||||||
|
<pagination
|
||||||
|
v-if="state.pagination && state.pagination.total && state.pagination.total > 0"
|
||||||
|
:total="state.pagination.total"
|
||||||
|
:current="state.pagination.current"
|
||||||
|
:size="state.pagination.size"
|
||||||
|
@sizeChange="sizeChangeHandle"
|
||||||
|
@currentChange="currentChangeHandle"
|
||||||
|
/>
|
||||||
|
</el-card>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- 审核弹窗 -->
|
||||||
|
<DocAuditDialog ref="docAuditDialogRef" @refresh="getDataList" />
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script setup lang="ts" name="PurchasingDocAudit">
|
||||||
|
import { ref, reactive, defineAsyncComponent, onMounted } from 'vue'
|
||||||
|
import { BasicTableProps, useTable } from "/@/hooks/table";
|
||||||
|
import { useMessage } from "/@/hooks/message";
|
||||||
|
import { getPage } from "/@/api/finance/purchasingrequisition";
|
||||||
|
import { Search, DocumentChecked, List } from '@element-plus/icons-vue'
|
||||||
|
|
||||||
|
// 引入组件
|
||||||
|
const DocAuditDialog = defineAsyncComponent(() => import('./DocAuditDialog.vue'));
|
||||||
|
|
||||||
|
const docAuditDialogRef = ref()
|
||||||
|
const searchFormRef = ref()
|
||||||
|
const showSearch = ref(true)
|
||||||
|
|
||||||
|
const state: BasicTableProps = reactive<BasicTableProps>({
|
||||||
|
pageList: getPage,
|
||||||
|
queryForm: {
|
||||||
|
purchaseNo: '',
|
||||||
|
projectName: '',
|
||||||
|
docAuditStatus: '',
|
||||||
|
},
|
||||||
|
createdIsNeed: true
|
||||||
|
});
|
||||||
|
|
||||||
|
const { getDataList, tableStyle, sizeChangeHandle, currentChangeHandle } = useTable(state);
|
||||||
|
|
||||||
|
const handleReset = () => {
|
||||||
|
searchFormRef.value?.resetFields();
|
||||||
|
getDataList();
|
||||||
|
};
|
||||||
|
|
||||||
|
const getStatusType = (status: string) => {
|
||||||
|
const typeMap: Record<string, string> = {
|
||||||
|
'PENDING_UPLOAD': 'info',
|
||||||
|
'ASSET_REVIEWING': 'warning',
|
||||||
|
'DEPT_REVIEWING': 'warning',
|
||||||
|
'AUDIT_REVIEWING': 'warning',
|
||||||
|
'ASSET_CONFIRMING': 'primary',
|
||||||
|
'COMPLETED': 'success',
|
||||||
|
'RETURNED': 'danger'
|
||||||
|
};
|
||||||
|
return typeMap[status] || 'info';
|
||||||
|
};
|
||||||
|
|
||||||
|
const getStatusLabel = (status: string) => {
|
||||||
|
const labelMap: Record<string, string> = {
|
||||||
|
'PENDING_UPLOAD': '待上传',
|
||||||
|
'ASSET_REVIEWING': '资产管理处审核中',
|
||||||
|
'DEPT_REVIEWING': '需求部门审核中',
|
||||||
|
'AUDIT_REVIEWING': '内审部门审核中',
|
||||||
|
'ASSET_CONFIRMING': '资产管理处确认中',
|
||||||
|
'COMPLETED': '已完成',
|
||||||
|
'RETURNED': '已退回'
|
||||||
|
};
|
||||||
|
return labelMap[status] || '-';
|
||||||
|
};
|
||||||
|
|
||||||
|
const handleAudit = (row: any) => {
|
||||||
|
docAuditDialogRef.value?.open(row);
|
||||||
|
};
|
||||||
|
|
||||||
|
onMounted(() => {
|
||||||
|
// 页面加载时的初始化逻辑
|
||||||
|
});
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style scoped lang="scss">
|
||||||
|
@import '/@/assets/styles/modern-page.scss';
|
||||||
|
</style>
|
||||||
@@ -391,6 +391,9 @@
|
|||||||
</span>
|
</span>
|
||||||
</template>
|
</template>
|
||||||
</el-dialog>
|
</el-dialog>
|
||||||
|
|
||||||
|
<!-- 采购文件审核弹窗 -->
|
||||||
|
<DocAuditDialog ref="docAuditDialogRef" @refresh="getDataList" />
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
@@ -412,6 +415,7 @@ const ImplementForm = defineAsyncComponent(() => import('./implementForm.vue'));
|
|||||||
const ActionDropdown = defineAsyncComponent(() => import('/@/components/tools/action-dropdown.vue'));
|
const ActionDropdown = defineAsyncComponent(() => import('/@/components/tools/action-dropdown.vue'));
|
||||||
const PurchasingAcceptModal = defineAsyncComponent(() => import('./accept/PurchasingAcceptModal.vue'));
|
const PurchasingAcceptModal = defineAsyncComponent(() => import('./accept/PurchasingAcceptModal.vue'));
|
||||||
const FlowCommentTimeline = defineAsyncComponent(() => import('/@/views/jsonflow/comment/timeline.vue'));
|
const FlowCommentTimeline = defineAsyncComponent(() => import('/@/views/jsonflow/comment/timeline.vue'));
|
||||||
|
const DocAuditDialog = defineAsyncComponent(() => import('./docAudit/DocAuditDialog.vue'));
|
||||||
|
|
||||||
// 字典数据和品目树数据
|
// 字典数据和品目树数据
|
||||||
const dictData = ref({
|
const dictData = ref({
|
||||||
@@ -431,6 +435,7 @@ const formDialogRef = ref()
|
|||||||
const acceptModalRef = ref()
|
const acceptModalRef = ref()
|
||||||
const searchFormRef = ref()
|
const searchFormRef = ref()
|
||||||
const showSearch = ref(true)
|
const showSearch = ref(true)
|
||||||
|
const docAuditDialogRef = ref()
|
||||||
/** 审批过程弹窗:是否显示、当前行对应的流程 job(供 Comment 组件用)、类型(申请单/文件) */
|
/** 审批过程弹窗:是否显示、当前行对应的流程 job(供 Comment 组件用)、类型(申请单/文件) */
|
||||||
const showFlowComment = ref(false)
|
const showFlowComment = ref(false)
|
||||||
const currFlowJob = ref<{ id?: number; flowInstId?: number } | null>(null)
|
const currFlowJob = ref<{ id?: number; flowInstId?: number } | null>(null)
|
||||||
@@ -599,6 +604,11 @@ const handleImplement = (row: any) => {
|
|||||||
implementFormRef.value?.openDialog(row);
|
implementFormRef.value?.openDialog(row);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/** 打开采购文件审核 */
|
||||||
|
const handleDocAudit = (row: any) => {
|
||||||
|
docAuditDialogRef.value?.open(row);
|
||||||
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 删除当前行
|
* 删除当前行
|
||||||
* @param row - 当前行数据
|
* @param row - 当前行数据
|
||||||
@@ -692,6 +702,12 @@ const getActionMenuItems = (row: any) => {
|
|||||||
icon: Collection,
|
icon: Collection,
|
||||||
visible: () => row?.purchaseMode === '2' || (row?.purchaseMode === '0' && row?.purchaseType === '4'),
|
visible: () => row?.purchaseMode === '2' || (row?.purchaseMode === '0' && row?.purchaseType === '4'),
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
command: 'docAudit',
|
||||||
|
label: '采购文件审核',
|
||||||
|
icon: DocumentChecked,
|
||||||
|
visible: () => row?.implementType === '2' && row?.agentId,
|
||||||
|
},
|
||||||
];
|
];
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -725,6 +741,9 @@ const handleMoreCommand = (command: string, row: any) => {
|
|||||||
case 'assignAgent':
|
case 'assignAgent':
|
||||||
openAssignAgentDialog(row);
|
openAssignAgentDialog(row);
|
||||||
break;
|
break;
|
||||||
|
case 'docAudit':
|
||||||
|
handleDocAudit(row);
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -9,9 +9,11 @@
|
|||||||
<el-button type="primary" icon="FolderAdd" @click="openUploadDialog()">
|
<el-button type="primary" icon="FolderAdd" @click="openUploadDialog()">
|
||||||
新增模板
|
新增模板
|
||||||
</el-button>
|
</el-button>
|
||||||
|
<el-alert type="info" :closable="false" class="mb3 mt-3" show-icon>
|
||||||
|
此处模版中的模版编码对应用户端下载模版匹配,请勿随意修改或删除。正常情况下如有发生模版变化,重新上传即可。如有新增模版,请联系管理员进行处理。
|
||||||
|
</el-alert>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
|
|||||||
@@ -46,7 +46,7 @@
|
|||||||
icon="FolderAdd"
|
icon="FolderAdd"
|
||||||
type="primary"
|
type="primary"
|
||||||
@click="formDialogRef.openDialog()"
|
@click="formDialogRef.openDialog()"
|
||||||
v-auth="'purchase_purchasingBusinessLeader_add'">
|
v-auth="'purchasing_bus_leader_add'">
|
||||||
新增
|
新增
|
||||||
</el-button>
|
</el-button>
|
||||||
<el-button
|
<el-button
|
||||||
@@ -55,13 +55,13 @@
|
|||||||
icon="Delete"
|
icon="Delete"
|
||||||
type="primary"
|
type="primary"
|
||||||
class="ml10"
|
class="ml10"
|
||||||
v-auth="'purchase_purchasingBusinessLeader_del'"
|
v-auth="'purchasing_bus_leader_del'"
|
||||||
@click="handleDelete(selectObjs)">
|
@click="handleDelete(selectObjs)">
|
||||||
删除
|
删除
|
||||||
</el-button>
|
</el-button>
|
||||||
<right-toolbar
|
<right-toolbar
|
||||||
v-model:showSearch="showSearch"
|
v-model:showSearch="showSearch"
|
||||||
:export="'purchase_purchasingBusinessLeader_export'"
|
:export="'purchasing_bus_leader_export'"
|
||||||
@exportExcel="exportExcel"
|
@exportExcel="exportExcel"
|
||||||
class="ml10"
|
class="ml10"
|
||||||
@queryTable="getDataList" />
|
@queryTable="getDataList" />
|
||||||
@@ -116,7 +116,7 @@
|
|||||||
icon="Delete"
|
icon="Delete"
|
||||||
link
|
link
|
||||||
type="danger"
|
type="danger"
|
||||||
v-auth="'purchase_purchasingBusinessLeader_del'"
|
v-auth="'purchasing_bus_leader_del'"
|
||||||
@click="handleDelete([scope.row.id])">
|
@click="handleDelete([scope.row.id])">
|
||||||
删除
|
删除
|
||||||
</el-button>
|
</el-button>
|
||||||
|
|||||||
Reference in New Issue
Block a user