提交代码

This commit is contained in:
2026-02-02 15:03:09 +08:00
parent 21562e57a6
commit 291ff5434b
17 changed files with 139 additions and 14 deletions

Binary file not shown.

Binary file not shown.

View File

@@ -16,7 +16,8 @@ import SignInput from "./sign/index.vue";
// vite glob导入 // vite glob导入
const modules: Record<string, () => Promise<unknown>> = import.meta.glob( const modules: Record<string, () => Promise<unknown>> = import.meta.glob(
['../../views/jsonflow/*/*.vue', '../../views/order/*/*.vue', '../../views/purchase/*/*.vue'] ['../../views/jsonflow/*/*.vue', '../../views/order/*/*.vue',
'../../views/purchase/*/*.vue','../../views/finance/purchasingrequisition/add.vue']
) )
/** /**

View File

@@ -29,6 +29,7 @@ declare module 'vue-router' {
isIframe?: boolean; isIframe?: boolean;
roles?: string[]; roles?: string[];
icon?: string; icon?: string;
activeMenu?: string; // 指定菜单高亮的路径
} }
} }
@@ -98,6 +99,14 @@ export const staticRoutes: Array<RouteRecordRaw> = [
isAuth: true, isAuth: true,
}, },
}, },
{
path: '/finance/purchasingrequisition/add',
name: 'purchasingrequisition.add',
component: () => import('/@/views/finance/purchasingrequisition/add.vue'),
meta: {
isAuth: false, // 不需要认证,纯页面展示
},
},
...staticRoutesFlow ...staticRoutesFlow
]; ];

View File

@@ -422,6 +422,16 @@
</el-form-item> </el-form-item>
</template> </template>
<!-- 特殊情况紧急 -->
<template v-if="isUrgentSpecial">
<el-form-item label="会议纪要" prop="meetingMinutesUrgent" class="mb20">
<upload-file
v-model="dataForm.meetingMinutesUrgent"
:limit="5"
upload-file-url="/purchase/purchasingfiles/upload" />
</el-form-item>
</template>
<!-- 特殊情况单一来源 --> <!-- 特殊情况单一来源 -->
<template v-if="dataForm.isSpecial === '2'"> <template v-if="dataForm.isSpecial === '2'">
<el-form-item <el-form-item
@@ -682,6 +692,7 @@ const dataForm = reactive({
purchaseRequirement: '', purchaseRequirement: '',
meetingMinutes: '', meetingMinutes: '',
feasibilityReport: '', feasibilityReport: '',
meetingMinutesUrgent: '',
meetingMinutesSingle: '', meetingMinutesSingle: '',
meetingMinutesImport: '', meetingMinutesImport: '',
singleSourceProof: '', singleSourceProof: '',
@@ -735,6 +746,13 @@ const isDeptPurchase = computed(() => {
return false; return false;
}); });
// 判断是否为紧急情况ID: 6509b59e24c1c6568f4277e544f3e55e
const isUrgentSpecial = computed(() => {
const urgentItem = isSpecialList.value.find(item => item.id === '6509b59e24c1c6568f4277e544f3e55e');
if (!urgentItem) return false;
return dataForm.isSpecial === urgentItem.value;
});
// 第二步标题 // 第二步标题
const stepTwoTitle = computed(() => { const stepTwoTitle = computed(() => {
return isDeptPurchase.value ? '部门自行采购' : '学校统一采购'; return isDeptPurchase.value ? '部门自行采购' : '学校统一采购';
@@ -885,7 +903,7 @@ const downloadTemplate = async (type: string) => {
'direct_select': { fileName: '服务商城项目需求模板(直选).doc', displayName: '服务商城项目需求模板(直选).doc' }, 'direct_select': { fileName: '服务商城项目需求模板(直选).doc', displayName: '服务商城项目需求模板(直选).doc' },
'public_select': { fileName: '服务商城项目需求模板(公开比选).doc', displayName: '服务商城项目需求模板(公开比选).doc' }, 'public_select': { fileName: '服务商城项目需求模板(公开比选).doc', displayName: '服务商城项目需求模板(公开比选).doc' },
'invite_select': { fileName: '服务商城项目需求模板(邀请比选).doc', displayName: '服务商城项目需求模板(邀请比选).doc' }, 'invite_select': { fileName: '服务商城项目需求模板(邀请比选).doc', displayName: '服务商城项目需求模板(邀请比选).doc' },
'purchase_requirement': { fileName: '表1采购需求填报模板.xlsx', displayName: '采购需求填报模板.xlsx' }, 'purchase_requirement': { fileName: '表1采购需求填报模板.doc', displayName: '采购需求填报模板.doc' },
'import_application': { fileName: '附件1进口产品申请及专家论证意见表.doc', displayName: '进口产品申请及专家论证意见表.doc' }, 'import_application': { fileName: '附件1进口产品申请及专家论证意见表.doc', displayName: '进口产品申请及专家论证意见表.doc' },
'single_source': { fileName: '表7单一来源论专家证附件.docx', displayName: '单一来源论专家证附件.docx' }, 'single_source': { fileName: '表7单一来源论专家证附件.docx', displayName: '单一来源论专家证附件.docx' },
'feasibility_report': { fileName: '表6项目可行性论证报告模板.doc', displayName: '项目可行性论证报告模板.doc' }, 'feasibility_report': { fileName: '表6项目可行性论证报告模板.doc', displayName: '项目可行性论证报告模板.doc' },
@@ -987,7 +1005,14 @@ const prevStep = () => {
// 取消 // 取消
const handleCancel = () => { const handleCancel = () => {
// 如果是在 iframe 中,向父窗口发送关闭消息
if (window.parent !== window) {
window.parent.postMessage({
type: 'purchasingrequisition:close'
}, '*');
} else {
router.back(); router.back();
}
}; };
// 获取品目树形数据 // 获取品目树形数据
@@ -1207,8 +1232,8 @@ const handleSubmit = async () => {
'businessNegotiationTable', 'marketPurchaseMinutes', 'onlineMallMaterials', 'businessNegotiationTable', 'marketPurchaseMinutes', 'onlineMallMaterials',
'serviceDirectSelect', 'servicePublicSelect', 'purchaseRequirementTemplate', 'serviceDirectSelect', 'servicePublicSelect', 'purchaseRequirementTemplate',
'serviceInviteSelect', 'servicePublicSelectAuto', 'purchaseRequirement', 'serviceInviteSelect', 'servicePublicSelectAuto', 'purchaseRequirement',
'meetingMinutes', 'feasibilityReport', 'meetingMinutesSingle', 'meetingMinutes', 'feasibilityReport', 'meetingMinutesUrgent',
'meetingMinutesImport', 'singleSourceProof', 'importApplication', 'meetingMinutesSingle', 'meetingMinutesImport', 'singleSourceProof', 'importApplication',
'governmentPurchaseIntent', 'servicePublicSelectSchool' 'governmentPurchaseIntent', 'servicePublicSelectSchool'
]; ];
@@ -1220,7 +1245,15 @@ const handleSubmit = async () => {
await addObj(submitData); await addObj(submitData);
useMessage().success('提交成功'); useMessage().success('提交成功');
// 如果是在 iframe 中,向父窗口发送消息
if (window.parent !== window) {
window.parent.postMessage({
type: 'purchasingrequisition:submitSuccess'
}, '*');
} else {
router.push('/finance/purchasingrequisition'); router.push('/finance/purchasingrequisition');
}
} catch (err: any) { } catch (err: any) {
useMessage().error(err.msg || '提交失败'); useMessage().error(err.msg || '提交失败');
} finally { } finally {
@@ -1248,8 +1281,8 @@ const handleTempStore = async () => {
'businessNegotiationTable', 'marketPurchaseMinutes', 'onlineMallMaterials', 'businessNegotiationTable', 'marketPurchaseMinutes', 'onlineMallMaterials',
'serviceDirectSelect', 'servicePublicSelect', 'purchaseRequirementTemplate', 'serviceDirectSelect', 'servicePublicSelect', 'purchaseRequirementTemplate',
'serviceInviteSelect', 'servicePublicSelectAuto', 'purchaseRequirement', 'serviceInviteSelect', 'servicePublicSelectAuto', 'purchaseRequirement',
'meetingMinutes', 'feasibilityReport', 'meetingMinutesSingle', 'meetingMinutes', 'feasibilityReport', 'meetingMinutesUrgent',
'meetingMinutesImport', 'singleSourceProof', 'importApplication', 'meetingMinutesSingle', 'meetingMinutesImport', 'singleSourceProof', 'importApplication',
'governmentPurchaseIntent', 'servicePublicSelectSchool' 'governmentPurchaseIntent', 'servicePublicSelectSchool'
]; ];
@@ -1261,7 +1294,15 @@ const handleTempStore = async () => {
await tempStore(submitData); await tempStore(submitData);
useMessage().success('暂存成功'); useMessage().success('暂存成功');
// 如果是在 iframe 中,向父窗口发送消息
if (window.parent !== window) {
window.parent.postMessage({
type: 'purchasingrequisition:submitSuccess'
}, '*');
} else {
router.push('/finance/purchasingrequisition'); router.push('/finance/purchasingrequisition');
}
} catch (err: any) { } catch (err: any) {
useMessage().error(err.msg || '暂存失败'); useMessage().error(err.msg || '暂存失败');
} finally { } finally {

View File

@@ -213,13 +213,32 @@
</el-card> </el-card>
</div> </div>
<!-- 新增页面 iframe 对话框 -->
<el-dialog
v-model="showAddIframe"
title="新增采购申请"
width="1000px"
:close-on-click-modal="false"
:close-on-press-escape="true"
destroy-on-close
@close="closeAddIframe">
<div class="iframe-dialog-content">
<iframe
ref="addIframeRef"
:src="addIframeSrc"
frameborder="0"
class="add-iframe"
@load="onIframeLoad" />
</div>
</el-dialog>
<!-- 编辑新增表单对话框 --> <!-- 编辑新增表单对话框 -->
<FormDialog ref="formDialogRef" @refresh="getDataList" /> <FormDialog ref="formDialogRef" @refresh="getDataList" />
</div> </div>
</template> </template>
<script setup lang="ts" name="PurchasingRequisition"> <script setup lang="ts" name="PurchasingRequisition">
import { ref, reactive, defineAsyncComponent } from 'vue' import { ref, reactive, defineAsyncComponent, onUnmounted } from 'vue'
import { useRouter } from 'vue-router' import { useRouter } from 'vue-router'
import { BasicTableProps, useTable } from "/@/hooks/table"; import { BasicTableProps, useTable } from "/@/hooks/table";
import { getPage, delObj } from "/@/api/finance/purchasingrequisition"; import { getPage, delObj } from "/@/api/finance/purchasingrequisition";
@@ -235,6 +254,9 @@ const tableRef = ref()
const formDialogRef = ref() const formDialogRef = ref()
const searchFormRef = ref() const searchFormRef = ref()
const showSearch = ref(true) const showSearch = ref(true)
const showAddIframe = ref(false)
const addIframeRef = ref<HTMLIFrameElement>()
const addIframeSrc = ref('')
/** /**
* 定义响应式表格数据 * 定义响应式表格数据
@@ -265,12 +287,42 @@ const handleReset = () => {
}; };
/** /**
* 新增采购申请 - 跳转到新页面 * 新增采购申请 - 在 iframe 中展示
*/ */
const handleAdd = () => { const handleAdd = () => {
router.push({ // 构建 iframe 的 src使用当前页面的 hash 路由
path: '/finance/purchasingrequisition/add' const baseUrl = window.location.origin + window.location.pathname
}); addIframeSrc.value = `${baseUrl}#/finance/purchasingrequisition/add`
showAddIframe.value = true
// 监听来自 iframe 的消息
window.addEventListener('message', handleIframeMessage)
};
/**
* 关闭新增 iframe
*/
const closeAddIframe = () => {
showAddIframe.value = false
// 移除消息监听器
window.removeEventListener('message', handleIframeMessage)
};
/**
* 处理 iframe 发送的消息
*/
const handleIframeMessage = (event: MessageEvent) => {
// 验证消息来源(可选,根据实际需求)
// if (event.origin !== window.location.origin) return
if (event.data && event.data.type === 'purchasingrequisition:submitSuccess') {
// 提交成功,关闭 iframe 并刷新列表
closeAddIframe()
getDataList()
useMessage().success('提交成功')
} else if (event.data && event.data.type === 'purchasingrequisition:close') {
// 关闭 iframe
closeAddIframe()
}
}; };
/** /**
@@ -296,9 +348,31 @@ const handleDelete = async (row: any) => {
useMessage().error(err.msg || '删除失败'); useMessage().error(err.msg || '删除失败');
} }
}; };
// 组件卸载时清理事件监听器
onUnmounted(() => {
window.removeEventListener('message', handleIframeMessage)
});
</script> </script>
<style scoped lang="scss"> <style scoped lang="scss">
@import '/@/assets/styles/modern-page.scss'; @import '/@/assets/styles/modern-page.scss';
.iframe-dialog-content {
width: 100%;
height: 70vh;
min-height: 500px;
position: relative;
.add-iframe {
width: 100%;
height: 100%;
border: none;
}
}
:deep(.el-dialog__body) {
padding: 20px;
}
</style> </style>