fix
This commit is contained in:
140
auto-imports.d.ts
vendored
140
auto-imports.d.ts
vendored
@@ -1,73 +1,73 @@
|
||||
// Generated by 'unplugin-auto-import'
|
||||
export {};
|
||||
export {}
|
||||
declare global {
|
||||
const EffectScope: typeof import('vue')['EffectScope'];
|
||||
const acceptHMRUpdate: typeof import('pinia')['acceptHMRUpdate'];
|
||||
const computed: typeof import('vue')['computed'];
|
||||
const createApp: typeof import('vue')['createApp'];
|
||||
const createPinia: typeof import('pinia')['createPinia'];
|
||||
const customRef: typeof import('vue')['customRef'];
|
||||
const defineAsyncComponent: typeof import('vue')['defineAsyncComponent'];
|
||||
const defineComponent: typeof import('vue')['defineComponent'];
|
||||
const defineStore: typeof import('pinia')['defineStore'];
|
||||
const effectScope: typeof import('vue')['effectScope'];
|
||||
const getActivePinia: typeof import('pinia')['getActivePinia'];
|
||||
const getCurrentInstance: typeof import('vue')['getCurrentInstance'];
|
||||
const getCurrentScope: typeof import('vue')['getCurrentScope'];
|
||||
const h: typeof import('vue')['h'];
|
||||
const inject: typeof import('vue')['inject'];
|
||||
const isProxy: typeof import('vue')['isProxy'];
|
||||
const isReactive: typeof import('vue')['isReactive'];
|
||||
const isReadonly: typeof import('vue')['isReadonly'];
|
||||
const isRef: typeof import('vue')['isRef'];
|
||||
const mapActions: typeof import('pinia')['mapActions'];
|
||||
const mapGetters: typeof import('pinia')['mapGetters'];
|
||||
const mapState: typeof import('pinia')['mapState'];
|
||||
const mapStores: typeof import('pinia')['mapStores'];
|
||||
const mapWritableState: typeof import('pinia')['mapWritableState'];
|
||||
const markRaw: typeof import('vue')['markRaw'];
|
||||
const nextTick: typeof import('vue')['nextTick'];
|
||||
const onActivated: typeof import('vue')['onActivated'];
|
||||
const onBeforeMount: typeof import('vue')['onBeforeMount'];
|
||||
const onBeforeRouteLeave: typeof import('vue-router')['onBeforeRouteLeave'];
|
||||
const onBeforeRouteUpdate: typeof import('vue-router')['onBeforeRouteUpdate'];
|
||||
const onBeforeUnmount: typeof import('vue')['onBeforeUnmount'];
|
||||
const onBeforeUpdate: typeof import('vue')['onBeforeUpdate'];
|
||||
const onDeactivated: typeof import('vue')['onDeactivated'];
|
||||
const onErrorCaptured: typeof import('vue')['onErrorCaptured'];
|
||||
const onMounted: typeof import('vue')['onMounted'];
|
||||
const onRenderTracked: typeof import('vue')['onRenderTracked'];
|
||||
const onRenderTriggered: typeof import('vue')['onRenderTriggered'];
|
||||
const onScopeDispose: typeof import('vue')['onScopeDispose'];
|
||||
const onServerPrefetch: typeof import('vue')['onServerPrefetch'];
|
||||
const onUnmounted: typeof import('vue')['onUnmounted'];
|
||||
const onUpdated: typeof import('vue')['onUpdated'];
|
||||
const provide: typeof import('vue')['provide'];
|
||||
const reactive: typeof import('vue')['reactive'];
|
||||
const readonly: typeof import('vue')['readonly'];
|
||||
const ref: typeof import('vue')['ref'];
|
||||
const resolveComponent: typeof import('vue')['resolveComponent'];
|
||||
const resolveDirective: typeof import('vue')['resolveDirective'];
|
||||
const setActivePinia: typeof import('pinia')['setActivePinia'];
|
||||
const setMapStoreSuffix: typeof import('pinia')['setMapStoreSuffix'];
|
||||
const shallowReactive: typeof import('vue')['shallowReactive'];
|
||||
const shallowReadonly: typeof import('vue')['shallowReadonly'];
|
||||
const shallowRef: typeof import('vue')['shallowRef'];
|
||||
const storeToRefs: typeof import('pinia')['storeToRefs'];
|
||||
const toRaw: typeof import('vue')['toRaw'];
|
||||
const toRef: typeof import('vue')['toRef'];
|
||||
const toRefs: typeof import('vue')['toRefs'];
|
||||
const triggerRef: typeof import('vue')['triggerRef'];
|
||||
const unref: typeof import('vue')['unref'];
|
||||
const useAttrs: typeof import('vue')['useAttrs'];
|
||||
const useCssModule: typeof import('vue')['useCssModule'];
|
||||
const useCssVars: typeof import('vue')['useCssVars'];
|
||||
const useLink: typeof import('vue-router')['useLink'];
|
||||
const useRoute: typeof import('vue-router')['useRoute'];
|
||||
const useRouter: typeof import('vue-router')['useRouter'];
|
||||
const useSlots: typeof import('vue')['useSlots'];
|
||||
const watch: typeof import('vue')['watch'];
|
||||
const watchEffect: typeof import('vue')['watchEffect'];
|
||||
const watchPostEffect: typeof import('vue')['watchPostEffect'];
|
||||
const watchSyncEffect: typeof import('vue')['watchSyncEffect'];
|
||||
const EffectScope: typeof import('vue')['EffectScope']
|
||||
const acceptHMRUpdate: typeof import('pinia')['acceptHMRUpdate']
|
||||
const computed: typeof import('vue')['computed']
|
||||
const createApp: typeof import('vue')['createApp']
|
||||
const createPinia: typeof import('pinia')['createPinia']
|
||||
const customRef: typeof import('vue')['customRef']
|
||||
const defineAsyncComponent: typeof import('vue')['defineAsyncComponent']
|
||||
const defineComponent: typeof import('vue')['defineComponent']
|
||||
const defineStore: typeof import('pinia')['defineStore']
|
||||
const effectScope: typeof import('vue')['effectScope']
|
||||
const getActivePinia: typeof import('pinia')['getActivePinia']
|
||||
const getCurrentInstance: typeof import('vue')['getCurrentInstance']
|
||||
const getCurrentScope: typeof import('vue')['getCurrentScope']
|
||||
const h: typeof import('vue')['h']
|
||||
const inject: typeof import('vue')['inject']
|
||||
const isProxy: typeof import('vue')['isProxy']
|
||||
const isReactive: typeof import('vue')['isReactive']
|
||||
const isReadonly: typeof import('vue')['isReadonly']
|
||||
const isRef: typeof import('vue')['isRef']
|
||||
const mapActions: typeof import('pinia')['mapActions']
|
||||
const mapGetters: typeof import('pinia')['mapGetters']
|
||||
const mapState: typeof import('pinia')['mapState']
|
||||
const mapStores: typeof import('pinia')['mapStores']
|
||||
const mapWritableState: typeof import('pinia')['mapWritableState']
|
||||
const markRaw: typeof import('vue')['markRaw']
|
||||
const nextTick: typeof import('vue')['nextTick']
|
||||
const onActivated: typeof import('vue')['onActivated']
|
||||
const onBeforeMount: typeof import('vue')['onBeforeMount']
|
||||
const onBeforeRouteLeave: typeof import('vue-router')['onBeforeRouteLeave']
|
||||
const onBeforeRouteUpdate: typeof import('vue-router')['onBeforeRouteUpdate']
|
||||
const onBeforeUnmount: typeof import('vue')['onBeforeUnmount']
|
||||
const onBeforeUpdate: typeof import('vue')['onBeforeUpdate']
|
||||
const onDeactivated: typeof import('vue')['onDeactivated']
|
||||
const onErrorCaptured: typeof import('vue')['onErrorCaptured']
|
||||
const onMounted: typeof import('vue')['onMounted']
|
||||
const onRenderTracked: typeof import('vue')['onRenderTracked']
|
||||
const onRenderTriggered: typeof import('vue')['onRenderTriggered']
|
||||
const onScopeDispose: typeof import('vue')['onScopeDispose']
|
||||
const onServerPrefetch: typeof import('vue')['onServerPrefetch']
|
||||
const onUnmounted: typeof import('vue')['onUnmounted']
|
||||
const onUpdated: typeof import('vue')['onUpdated']
|
||||
const provide: typeof import('vue')['provide']
|
||||
const reactive: typeof import('vue')['reactive']
|
||||
const readonly: typeof import('vue')['readonly']
|
||||
const ref: typeof import('vue')['ref']
|
||||
const resolveComponent: typeof import('vue')['resolveComponent']
|
||||
const resolveDirective: typeof import('vue')['resolveDirective']
|
||||
const setActivePinia: typeof import('pinia')['setActivePinia']
|
||||
const setMapStoreSuffix: typeof import('pinia')['setMapStoreSuffix']
|
||||
const shallowReactive: typeof import('vue')['shallowReactive']
|
||||
const shallowReadonly: typeof import('vue')['shallowReadonly']
|
||||
const shallowRef: typeof import('vue')['shallowRef']
|
||||
const storeToRefs: typeof import('pinia')['storeToRefs']
|
||||
const toRaw: typeof import('vue')['toRaw']
|
||||
const toRef: typeof import('vue')['toRef']
|
||||
const toRefs: typeof import('vue')['toRefs']
|
||||
const triggerRef: typeof import('vue')['triggerRef']
|
||||
const unref: typeof import('vue')['unref']
|
||||
const useAttrs: typeof import('vue')['useAttrs']
|
||||
const useCssModule: typeof import('vue')['useCssModule']
|
||||
const useCssVars: typeof import('vue')['useCssVars']
|
||||
const useLink: typeof import('vue-router')['useLink']
|
||||
const useRoute: typeof import('vue-router')['useRoute']
|
||||
const useRouter: typeof import('vue-router')['useRouter']
|
||||
const useSlots: typeof import('vue')['useSlots']
|
||||
const watch: typeof import('vue')['watch']
|
||||
const watchEffect: typeof import('vue')['watchEffect']
|
||||
const watchPostEffect: typeof import('vue')['watchPostEffect']
|
||||
const watchSyncEffect: typeof import('vue')['watchSyncEffect']
|
||||
}
|
||||
|
||||
@@ -416,3 +416,11 @@ export function getSupplementFileType(purchaseType: string) {
|
||||
params: { purchaseType },
|
||||
});
|
||||
}
|
||||
|
||||
export function getSupplementFilesByApplyId(applyId: string) {
|
||||
return request({
|
||||
url: '/purchase/purchasingfiles/listByType',
|
||||
method: 'get',
|
||||
params: { purchaseId: applyId },
|
||||
});
|
||||
}
|
||||
|
||||
@@ -0,0 +1,316 @@
|
||||
<template>
|
||||
<el-dialog v-model="visible" title="补充材料详情" width="90%" top="5vh" destroy-on-close append-to-body>
|
||||
<template #header>
|
||||
<div class="dialog-header">
|
||||
<span class="dialog-title">
|
||||
<el-icon><FolderOpened /></el-icon>
|
||||
补充材料详情 - {{ applyData.purchaseNo || applyId }}
|
||||
</span>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<el-row :gutter="16">
|
||||
<el-col :span="8">
|
||||
<el-card shadow="never" class="info-card">
|
||||
<template #header>
|
||||
<div class="card-header">
|
||||
<span class="card-title">采购申请信息</span>
|
||||
</div>
|
||||
</template>
|
||||
<el-descriptions :column="1" border size="small">
|
||||
<el-descriptions-item label="采购编号">{{ applyData.purchaseNo || '-' }}</el-descriptions-item>
|
||||
<el-descriptions-item label="项目名称">{{ applyData.projectName || '-' }}</el-descriptions-item>
|
||||
<el-descriptions-item label="采购金额">{{ applyData.budget ? Number(applyData.budget).toLocaleString() + ' 元' : '-' }}</el-descriptions-item>
|
||||
<el-descriptions-item label="采购方式">{{ purchaseTypeLabel || '-' }}</el-descriptions-item>
|
||||
<el-descriptions-item label="补充状态">
|
||||
<el-tag v-if="applyData.supplementFlowStatus === '1'" type="success">已完成</el-tag>
|
||||
<el-tag v-else-if="applyData.supplementFlowStatus === '0'" type="warning">审批中</el-tag>
|
||||
<el-tag v-else-if="applyData.supplementFlowStatus === '-1'" type="info">已暂存</el-tag>
|
||||
<el-tag v-else type="danger">未补充</el-tag>
|
||||
</el-descriptions-item>
|
||||
</el-descriptions>
|
||||
</el-card>
|
||||
|
||||
<el-card shadow="never" class="file-card">
|
||||
<template #header>
|
||||
<div class="card-header">
|
||||
<span class="card-title">补充材料文件</span>
|
||||
</div>
|
||||
</template>
|
||||
<el-alert v-if="requiredFileTypeName" type="info" :closable="false" style="margin-bottom: 12px">
|
||||
<template #title>
|
||||
<span>{{ requiredFileTypeName }}</span>
|
||||
</template>
|
||||
</el-alert>
|
||||
<el-table :data="fileList" border stripe size="small" v-if="fileList.length > 0" max-height="300">
|
||||
<el-table-column type="index" label="序号" width="50" />
|
||||
<el-table-column prop="name" label="文件名称" show-overflow-tooltip />
|
||||
<el-table-column label="操作" width="120" align="center">
|
||||
<template #default="scope">
|
||||
<el-button type="primary" link size="small" icon="View" @click="handlePreview(scope.row)">预览</el-button>
|
||||
<el-button type="success" link size="small" icon="Download" @click="handleDownload(scope.row)">下载</el-button>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
<el-empty v-else description="暂无补充材料文件" :image-size="60" />
|
||||
</el-card>
|
||||
</el-col>
|
||||
|
||||
<el-col :span="16">
|
||||
<el-card shadow="never" class="flow-card">
|
||||
<template #header>
|
||||
<div class="card-header">
|
||||
<span class="card-title">审批流程</span>
|
||||
</div>
|
||||
</template>
|
||||
<template v-if="applyData.supplementFlowInstId">
|
||||
<FlowCommentTimeline :key="String(applyData.supplementFlowInstId) + 'supplement'" :curr-job="supplementFlowJob" />
|
||||
</template>
|
||||
<el-empty v-else description="暂未发起审批流程" :image-size="80" />
|
||||
</el-card>
|
||||
</el-col>
|
||||
</el-row>
|
||||
|
||||
<template #footer>
|
||||
<el-button @click="visible = false">关闭</el-button>
|
||||
</template>
|
||||
|
||||
<el-dialog v-model="previewVisible" :title="previewTitle" width="80%" top="5vh" destroy-on-close append-to-body>
|
||||
<div class="preview-container">
|
||||
<iframe v-if="previewUrl" :src="previewUrl" class="preview-iframe" />
|
||||
</div>
|
||||
</el-dialog>
|
||||
</el-dialog>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { ref, computed } from 'vue';
|
||||
import { FolderOpened } from '@element-plus/icons-vue';
|
||||
import { useMessage } from '/@/hooks/message';
|
||||
import { getObj, getSupplementFileType, getApplyFiles, previewFileById, downloadFileById } from '/@/api/purchase/purchasingrequisition';
|
||||
import { getDicts } from '/@/api/admin/dict';
|
||||
|
||||
const FlowCommentTimeline = defineAsyncComponent(() => import('/@/views/jsonflow/comment/timeline.vue'));
|
||||
|
||||
interface FileItem {
|
||||
id: string;
|
||||
name: string;
|
||||
url: string;
|
||||
}
|
||||
|
||||
const visible = ref(false);
|
||||
const applyId = ref('');
|
||||
const applyData = ref<any>({});
|
||||
const fileList = ref<FileItem[]>([]);
|
||||
const purchaseTypeLabel = ref('');
|
||||
const requiredFileTypeName = ref('');
|
||||
const purchaseTypeDeptList = ref<any[]>([]);
|
||||
const previewVisible = ref(false);
|
||||
const previewTitle = ref('');
|
||||
const previewUrl = ref('');
|
||||
|
||||
const PURCHASE_TYPE_DEPT_MAP: Record<string, string> = {
|
||||
'1': '网上商城',
|
||||
'2': '市场采购',
|
||||
'3': '商务洽谈',
|
||||
'5': '询价',
|
||||
};
|
||||
|
||||
const FILE_TYPE_MAP: Record<string, string> = {
|
||||
'10': '商务洽谈纪要',
|
||||
'20': '市场采购纪要',
|
||||
'30': '网上商城采购材料',
|
||||
'150': '部门采购询价表',
|
||||
};
|
||||
|
||||
const supplementFlowJob = computed(() => {
|
||||
if (!applyData.value.supplementFlowInstId) return null;
|
||||
return {
|
||||
id: applyData.value.id,
|
||||
flowInstId: applyData.value.supplementFlowInstId,
|
||||
};
|
||||
});
|
||||
|
||||
const loadDictData = async () => {
|
||||
try {
|
||||
const res = await getDicts('PURCHASE_TYPE_DEPT');
|
||||
if (res.data && Array.isArray(res.data)) {
|
||||
purchaseTypeDeptList.value = res.data.map((item: any) => ({
|
||||
label: item.label || item.dictLabel || item.name,
|
||||
value: item.value || item.dictValue || item.code,
|
||||
}));
|
||||
if (applyData.value.purchaseType) {
|
||||
const found = purchaseTypeDeptList.value.find((item: any) => item.value === applyData.value.purchaseType);
|
||||
if (found) {
|
||||
purchaseTypeLabel.value = found.label;
|
||||
}
|
||||
}
|
||||
}
|
||||
} catch (e) {
|
||||
console.error('加载字典数据失败', e);
|
||||
}
|
||||
};
|
||||
|
||||
const getPurchaseTypeLabel = () => {
|
||||
if (applyData.value.purchaseType) {
|
||||
purchaseTypeLabel.value = PURCHASE_TYPE_DEPT_MAP[applyData.value.purchaseType] || applyData.value.purchaseType;
|
||||
}
|
||||
};
|
||||
|
||||
const getRequiredFileTypeName = () => {
|
||||
const purchaseType = applyData.value.purchaseType;
|
||||
let fileTypeCode = '';
|
||||
if (purchaseType === '3') {
|
||||
fileTypeCode = '10';
|
||||
} else if (purchaseType === '2') {
|
||||
fileTypeCode = '20';
|
||||
} else if (purchaseType === '1') {
|
||||
fileTypeCode = '30';
|
||||
} else if (purchaseType === '5') {
|
||||
fileTypeCode = '150';
|
||||
}
|
||||
if (fileTypeCode) {
|
||||
requiredFileTypeName.value = FILE_TYPE_MAP[fileTypeCode] || '补充材料';
|
||||
}
|
||||
return fileTypeCode;
|
||||
};
|
||||
|
||||
const open = async (id: string, row?: any) => {
|
||||
applyId.value = id || '';
|
||||
visible.value = true;
|
||||
fileList.value = [];
|
||||
applyData.value = row || {};
|
||||
purchaseTypeLabel.value = '';
|
||||
requiredFileTypeName.value = '';
|
||||
|
||||
if (!row || !row.purchaseType) {
|
||||
try {
|
||||
const res = await getObj(id);
|
||||
applyData.value = res?.data || {};
|
||||
} catch (e) {
|
||||
console.error('获取采购申请详情失败', e);
|
||||
useMessage().error('获取采购申请详情失败');
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
await loadDictData();
|
||||
getPurchaseTypeLabel();
|
||||
const fileTypeCode = getRequiredFileTypeName();
|
||||
|
||||
if (applyData.value.id && fileTypeCode) {
|
||||
try {
|
||||
const filesRes = await getApplyFiles(applyData.value.id);
|
||||
const files = filesRes?.data || [];
|
||||
const matchingFiles = files.filter((f: any) => String(f.fileType) === fileTypeCode);
|
||||
if (matchingFiles.length > 0) {
|
||||
fileList.value = matchingFiles.map((f: any) => ({
|
||||
id: f.id,
|
||||
name: f.fileTitle || f.fileName || '附件',
|
||||
url: f.fileUrl,
|
||||
}));
|
||||
}
|
||||
} catch (e) {
|
||||
console.error('获取文件列表失败', e);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
const handlePreview = async (row: FileItem) => {
|
||||
if (!row.id) {
|
||||
useMessage().warning('文件ID不存在');
|
||||
return;
|
||||
}
|
||||
try {
|
||||
const blob = await previewFileById(row.id);
|
||||
previewUrl.value = window.URL.createObjectURL(blob);
|
||||
previewTitle.value = row.name || '文件预览';
|
||||
previewVisible.value = true;
|
||||
} catch (e) {
|
||||
console.error('预览失败', e);
|
||||
useMessage().error('预览失败');
|
||||
}
|
||||
};
|
||||
|
||||
const handleDownload = async (row: FileItem) => {
|
||||
if (!row.id) {
|
||||
useMessage().warning('文件ID不存在');
|
||||
return;
|
||||
}
|
||||
try {
|
||||
const blob = await downloadFileById(row.id);
|
||||
const url = window.URL.createObjectURL(blob);
|
||||
const link = document.createElement('a');
|
||||
link.href = url;
|
||||
link.download = row.name || '附件.pdf';
|
||||
document.body.appendChild(link);
|
||||
link.click();
|
||||
document.body.removeChild(link);
|
||||
window.URL.revokeObjectURL(url);
|
||||
} catch (e) {
|
||||
console.error('下载失败', e);
|
||||
useMessage().error('下载失败');
|
||||
}
|
||||
};
|
||||
|
||||
const emit = defineEmits<{
|
||||
(e: 'refresh'): void;
|
||||
}>();
|
||||
|
||||
defineExpose({
|
||||
open,
|
||||
});
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss">
|
||||
.dialog-header {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.dialog-title {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 8px;
|
||||
font-size: 16px;
|
||||
font-weight: 500;
|
||||
}
|
||||
|
||||
.info-card,
|
||||
.file-card,
|
||||
.flow-card {
|
||||
margin-bottom: 16px;
|
||||
}
|
||||
|
||||
.card-header {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
}
|
||||
|
||||
.card-title {
|
||||
font-size: 14px;
|
||||
font-weight: 500;
|
||||
}
|
||||
|
||||
.preview-container {
|
||||
width: 100%;
|
||||
height: 75vh;
|
||||
}
|
||||
|
||||
.preview-iframe {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
border: none;
|
||||
}
|
||||
|
||||
:deep(.el-card__header) {
|
||||
padding: 12px 16px;
|
||||
}
|
||||
|
||||
:deep(.el-card__body) {
|
||||
padding: 12px 16px;
|
||||
}
|
||||
</style>
|
||||
@@ -55,8 +55,8 @@
|
||||
采购申请管理
|
||||
</span>
|
||||
<div class="header-actions">
|
||||
<el-button icon="Files" link type="primary"> 采购申请汇总 </el-button>
|
||||
<el-button icon="FolderAdd" type="primary" @click="handleAdd"> 新增 </el-button>
|
||||
<el-button icon="Files" link type="primary"> 采购申请汇总</el-button>
|
||||
<el-button icon="FolderAdd" type="primary" @click="handleAdd"> 新增</el-button>
|
||||
<right-toolbar v-model:showSearch="showSearch" class="ml10" @queryTable="getDataList" />
|
||||
</div>
|
||||
</div>
|
||||
@@ -74,12 +74,16 @@
|
||||
>
|
||||
<el-table-column type="index" label="序号" width="70" align="center">
|
||||
<template #header>
|
||||
<el-icon><List /></el-icon>
|
||||
<el-icon>
|
||||
<List />
|
||||
</el-icon>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column prop="purchaseNo" label="申请单编号" min-width="180">
|
||||
<template #header>
|
||||
<el-icon><DocumentCopy /></el-icon>
|
||||
<el-icon>
|
||||
<DocumentCopy />
|
||||
</el-icon>
|
||||
<span style="margin-left: 4px">申请单编号</span>
|
||||
</template>
|
||||
<template #default="scope">
|
||||
@@ -95,32 +99,42 @@
|
||||
class="copy-btn"
|
||||
@click.stop="copyToClipboard(scope.row.purchaseNo)"
|
||||
>
|
||||
<el-icon><CopyDocument /></el-icon>
|
||||
<el-icon>
|
||||
<CopyDocument />
|
||||
</el-icon>
|
||||
</el-button>
|
||||
</div>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column prop="projectName" label="采购项目名称" min-width="200" show-overflow-tooltip>
|
||||
<template #header>
|
||||
<el-icon><Document /></el-icon>
|
||||
<el-icon>
|
||||
<Document />
|
||||
</el-icon>
|
||||
<span style="margin-left: 4px">采购项目名称</span>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column prop="applyDate" label="填报日期" width="120" align="center" show-overflow-tooltip>
|
||||
<template #header>
|
||||
<el-icon><Calendar /></el-icon>
|
||||
<el-icon>
|
||||
<Calendar />
|
||||
</el-icon>
|
||||
<span style="margin-left: 4px">填报日期</span>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column prop="deptName" label="需求部门" min-width="150" show-overflow-tooltip>
|
||||
<template #header>
|
||||
<el-icon><OfficeBuilding /></el-icon>
|
||||
<el-icon>
|
||||
<OfficeBuilding />
|
||||
</el-icon>
|
||||
<span style="margin-left: 4px">需求部门</span>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column prop="projectType" label="项目类别" min-width="200" align="left" show-overflow-tooltip>
|
||||
<template #header>
|
||||
<el-icon><Collection /></el-icon>
|
||||
<el-icon>
|
||||
<Collection />
|
||||
</el-icon>
|
||||
<span style="margin-left: 4px">项目类别</span>
|
||||
</template>
|
||||
<template #default="scope">
|
||||
@@ -139,7 +153,9 @@
|
||||
</el-table-column>
|
||||
<el-table-column prop="budget" label="项目预算(元)" width="130" align="right">
|
||||
<template #header>
|
||||
<el-icon><Money /></el-icon>
|
||||
<el-icon>
|
||||
<Money />
|
||||
</el-icon>
|
||||
<span style="margin-left: 4px">项目预算</span>
|
||||
</template>
|
||||
<template #default="scope">
|
||||
@@ -148,7 +164,9 @@
|
||||
</el-table-column>
|
||||
<el-table-column prop="isSpecial" label="是否特殊" width="100" align="center">
|
||||
<template #header>
|
||||
<el-icon><Warning /></el-icon>
|
||||
<el-icon>
|
||||
<Warning />
|
||||
</el-icon>
|
||||
<span style="margin-left: 4px">是否特殊</span>
|
||||
</template>
|
||||
<template #default="scope">
|
||||
@@ -161,7 +179,9 @@
|
||||
</el-table-column>
|
||||
<el-table-column prop="isCentralized" label="是否集采" width="100" align="center">
|
||||
<template #header>
|
||||
<el-icon><CircleCheck /></el-icon>
|
||||
<el-icon>
|
||||
<CircleCheck />
|
||||
</el-icon>
|
||||
<span style="margin-left: 4px">是否集采</span>
|
||||
</template>
|
||||
<template #default="scope">
|
||||
@@ -170,9 +190,11 @@
|
||||
<span v-else>-</span>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column prop="purchaseMode" label="采购形式" width="140" align="center">
|
||||
<el-table-column prop="purchaseMode" label="采购形式" width="160" align="center">
|
||||
<template #header>
|
||||
<el-icon><Shop /></el-icon>
|
||||
<el-icon>
|
||||
<Shop />
|
||||
</el-icon>
|
||||
<span style="margin-left: 4px">采购形式</span>
|
||||
</template>
|
||||
<template #default="scope">
|
||||
@@ -181,14 +203,25 @@
|
||||
<el-tag v-else-if="scope.row.purchaseMode === '2'" type="primary">学校统一采购</el-tag>
|
||||
<span v-else>-</span>
|
||||
<el-tag v-if="scope.row.purchaseMode === '1' && scope.row.purchaseChannel === '2'" type="warning" size="small" class="entrust-tag"
|
||||
>委</el-tag
|
||||
>委
|
||||
</el-tag>
|
||||
<el-tooltip
|
||||
v-if="scope.row.purchaseMode === '1' && scope.row.purchaseChannel === '1'"
|
||||
:content="getSupplementTooltip(scope.row)"
|
||||
placement="top"
|
||||
>
|
||||
<el-icon :class="['supplement-icon', getSupplementIconClass(scope.row)]" @click.stop="handleShowSupplement(scope.row)">
|
||||
<component :is="getSupplementIcon(scope.row)" />
|
||||
</el-icon>
|
||||
</el-tooltip>
|
||||
</div>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column prop="purchaseType" label="采购方式" width="120" align="center">
|
||||
<template #header>
|
||||
<el-icon><Shop /></el-icon>
|
||||
<el-icon>
|
||||
<Shop />
|
||||
</el-icon>
|
||||
<span style="margin-left: 4px">采购方式</span>
|
||||
</template>
|
||||
<template #default="scope">
|
||||
@@ -198,29 +231,31 @@
|
||||
</el-table-column>
|
||||
<el-table-column prop="status" label="审核状态" width="100" align="center">
|
||||
<template #header>
|
||||
<el-icon><InfoFilled /></el-icon>
|
||||
<el-icon>
|
||||
<InfoFilled />
|
||||
</el-icon>
|
||||
<span style="margin-left: 4px">审核状态</span>
|
||||
</template>
|
||||
<template #default="scope">
|
||||
<el-tooltip v-if="scope.row.flowInstId" content="点击查看审批过程" placement="top">
|
||||
<el-tag v-if="scope.row.status === '-2'" type="info" class="status-tag-clickable" @click="handleShowFlowComment(scope.row)"
|
||||
>撤回</el-tag
|
||||
>
|
||||
>撤回
|
||||
</el-tag>
|
||||
<el-tag v-else-if="scope.row.status === '-1'" type="warning" class="status-tag-clickable" @click="handleShowFlowComment(scope.row)"
|
||||
>暂存</el-tag
|
||||
>
|
||||
>暂存
|
||||
</el-tag>
|
||||
<el-tag v-else-if="scope.row.status === '0'" type="primary" class="status-tag-clickable" @click="handleShowFlowComment(scope.row)"
|
||||
>运行中</el-tag
|
||||
>
|
||||
>运行中
|
||||
</el-tag>
|
||||
<el-tag v-else-if="scope.row.status === '1'" type="success" class="status-tag-clickable" @click="handleShowFlowComment(scope.row)"
|
||||
>完成</el-tag
|
||||
>
|
||||
>完成
|
||||
</el-tag>
|
||||
<el-tag v-else-if="scope.row.status === '2'" type="danger" class="status-tag-clickable" @click="handleShowFlowComment(scope.row)"
|
||||
>作废</el-tag
|
||||
>
|
||||
>作废
|
||||
</el-tag>
|
||||
<el-tag v-else-if="scope.row.status === '3'" type="info" class="status-tag-clickable" @click="handleShowFlowComment(scope.row)"
|
||||
>终止</el-tag
|
||||
>
|
||||
>终止
|
||||
</el-tag>
|
||||
<span v-else>-</span>
|
||||
</el-tooltip>
|
||||
<template v-else>
|
||||
@@ -238,7 +273,7 @@
|
||||
<el-table-column label="操作" align="center" fixed="right" width="150">
|
||||
<template #default="scope">
|
||||
<div class="op-cell">
|
||||
<el-button type="primary" link icon="View" @click="handleView(scope.row)"> 查看 </el-button>
|
||||
<el-button type="primary" link icon="View" @click="handleView(scope.row)"> 查看</el-button>
|
||||
<ActionDropdown :items="getActionMenuItems(scope.row)" @command="(command) => handleMoreCommand(command, scope.row)" />
|
||||
</div>
|
||||
</template>
|
||||
@@ -295,6 +330,9 @@
|
||||
<!-- 补充材料弹窗 -->
|
||||
<SupplementFilesDialog ref="supplementFilesDialogRef" @refresh="getDataList" />
|
||||
|
||||
<!-- 补充材料查看弹窗 -->
|
||||
<SupplementViewDialog ref="supplementViewDialogRef" @refresh="getDataList" />
|
||||
|
||||
<!-- 招标文件审核弹窗 -->
|
||||
<!-- <DocAuditDialog ref="docAuditDialogRef" @refresh="getDataList" />-->
|
||||
|
||||
@@ -389,6 +427,8 @@ import {
|
||||
RefreshRight,
|
||||
Shop,
|
||||
CopyDocument,
|
||||
Select,
|
||||
CloseBold,
|
||||
} from '@element-plus/icons-vue';
|
||||
import other from '/@/utils/other';
|
||||
import { Session } from '/@/utils/storage';
|
||||
@@ -409,6 +449,7 @@ const FileArchiveDialog = defineAsyncComponent(() => import('./FileArchiveDialog
|
||||
const UpdateFilesDialog = defineAsyncComponent(() => import('./UpdateFilesDialog.vue'));
|
||||
const ContractDialog = defineAsyncComponent(() => import('./contract/ContractDialog.vue'));
|
||||
const SupplementFilesDialog = defineAsyncComponent(() => import('./SupplementFilesDialog.vue'));
|
||||
const SupplementViewDialog = defineAsyncComponent(() => import('./SupplementViewDialog.vue'));
|
||||
// const DocAuditDialog = defineAsyncComponent(() => import('./docAudit/DocAuditDialog.vue'));
|
||||
|
||||
// 字典数据和品目树数据
|
||||
@@ -441,6 +482,7 @@ const fileArchiveDialogRef = ref();
|
||||
const updateFilesDialogRef = ref();
|
||||
const contractDialogRef = ref();
|
||||
const supplementFilesDialogRef = ref();
|
||||
const supplementViewDialogRef = ref();
|
||||
|
||||
/** 采购代表弹窗 */
|
||||
const representorDialogVisible = ref(false);
|
||||
@@ -534,7 +576,7 @@ const handleAdd = () => {
|
||||
};
|
||||
|
||||
/**
|
||||
/**
|
||||
/**
|
||||
* 点击审核状态:若有流程实例则打开「查看审批过程」弹窗(参考 hi-job.vue)
|
||||
* @param row - 当前行数据(需含 flowInstId)
|
||||
*/
|
||||
@@ -561,6 +603,42 @@ const handleShowFileFlowComment = (row: any) => {
|
||||
showFlowComment.value = true;
|
||||
};
|
||||
|
||||
const SUPPLEMENT_STATUS_MAP: Record<string, { icon: any; class: string; tooltip: string }> = {
|
||||
'1': { icon: Select, class: 'supplement-done', tooltip: '补充材料已完成,点击查看' },
|
||||
'0': { icon: CloseBold, class: 'supplement-running', tooltip: '补充材料审批中,点击查看' },
|
||||
'-1': { icon: CloseBold, class: 'supplement-pending', tooltip: '补充材料已暂存,点击查看' },
|
||||
};
|
||||
|
||||
const getSupplementIcon = (row: any) => {
|
||||
const status = row?.supplementFlowStatus;
|
||||
if (status === '1') return Select;
|
||||
return CloseBold;
|
||||
};
|
||||
|
||||
const getSupplementIconClass = (row: any) => {
|
||||
const status = row?.supplementFlowStatus;
|
||||
if (status === '1') return 'supplement-done';
|
||||
if (status === '0') return 'supplement-running';
|
||||
return 'supplement-pending';
|
||||
};
|
||||
|
||||
const getSupplementTooltip = (row: any) => {
|
||||
const status = row?.supplementFlowStatus;
|
||||
if (status === '1') return '补充材料已完成,点击查看';
|
||||
if (status === '0') return '补充材料审批中,点击查看';
|
||||
if (status === '-1') return '补充材料已暂存,点击查看';
|
||||
return '未补充材料,点击查看';
|
||||
};
|
||||
|
||||
const handleShowSupplement = (row: any) => {
|
||||
const id = row?.id ?? row?.purchaseId;
|
||||
if (!id) {
|
||||
useMessage().warning('无法获取采购申请ID');
|
||||
return;
|
||||
}
|
||||
supplementViewDialogRef.value?.open(String(id), row);
|
||||
};
|
||||
|
||||
/**
|
||||
* 打开查看对话框
|
||||
* @param row - 当前行数据
|
||||
@@ -699,41 +777,36 @@ const getActionMenuItems = (row: any) => {
|
||||
icon: Download,
|
||||
visible: () => isCompleted,
|
||||
},
|
||||
// {
|
||||
// command: 'representor',
|
||||
// label: '采购代表',
|
||||
// icon: User,
|
||||
// visible: () => isCompleted && isDeptAuditRole.value,
|
||||
// },
|
||||
// {
|
||||
// command: 'updateFiles',
|
||||
// label: '更新材料',
|
||||
// icon: RefreshRight,
|
||||
// visible: () => (isCompleted || isRunning) && hasAuth('purchase_purchasingapply_edit'),
|
||||
// },
|
||||
// {
|
||||
// command: 'contract',
|
||||
// label: '采购合同',
|
||||
// icon: DocumentChecked,
|
||||
// visible: () => isCompleted,
|
||||
// },
|
||||
{
|
||||
command: 'representor',
|
||||
label: '采购代表',
|
||||
icon: User,
|
||||
visible: () => isCompleted && isDeptAuditRole.value,
|
||||
},
|
||||
{
|
||||
command: 'updateFiles',
|
||||
label: '更新材料',
|
||||
icon: RefreshRight,
|
||||
visible: () => (isCompleted || isRunning) && hasAuth('purchase_purchasingapply_edit'),
|
||||
},
|
||||
{
|
||||
command: 'contract',
|
||||
label: '采购合同',
|
||||
icon: DocumentChecked,
|
||||
visible: () => isCompleted,
|
||||
},
|
||||
{
|
||||
command: 'supplementFiles',
|
||||
label: '补充材料',
|
||||
icon: Upload,
|
||||
visible: () => isCompleted && row?.purchaseMode === '1' && row?.purchaseChannel === '1' && hasAuth('purchase_supplement'),
|
||||
},
|
||||
{
|
||||
command: 'submitSupplementFiles',
|
||||
label: '提交补充材料',
|
||||
icon: Upload,
|
||||
visible: () => isCompleted && row?.purchaseMode === '1' && row?.purchaseChannel === '1' && row?.supplementFlowStatus === '-1' && hasAuth('purchase_supplement'),
|
||||
visible: () =>
|
||||
isCompleted && row?.purchaseMode === '1' && row?.purchaseChannel === '1' && !row?.supplementFlowStatus && hasAuth('purchase_supplement'),
|
||||
},
|
||||
// {
|
||||
// command: 'downloadFileApply',
|
||||
// label: '下载文件审批表',
|
||||
// icon: Download,
|
||||
// visible: () => true,
|
||||
// visible: () => isCompleted,
|
||||
// },
|
||||
// {
|
||||
// command: 'docAudit',
|
||||
@@ -1093,5 +1166,28 @@ onMounted(() => {
|
||||
height: 18px;
|
||||
line-height: 16px;
|
||||
}
|
||||
|
||||
.supplement-icon {
|
||||
cursor: pointer;
|
||||
font-size: 16px;
|
||||
margin-left: 4px;
|
||||
transition: transform 0.2s;
|
||||
|
||||
&:hover {
|
||||
transform: scale(1.2);
|
||||
}
|
||||
}
|
||||
|
||||
.supplement-done {
|
||||
color: #67c23a;
|
||||
}
|
||||
|
||||
.supplement-running {
|
||||
color: #e6a23c;
|
||||
}
|
||||
|
||||
.supplement-pending {
|
||||
color: #f56c6c;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
||||
Reference in New Issue
Block a user