Merge branch 'developer' of ssh://code.cyweb.top:30033/scj/zhxy/v3/cloud-ui into developer
This commit is contained in:
@@ -1,11 +0,0 @@
|
||||
# port 端口号
|
||||
VITE_PORT=8888
|
||||
|
||||
#浏览器自动打开
|
||||
VITE_OPEN=true
|
||||
|
||||
# 本地环境
|
||||
ENV=development
|
||||
|
||||
# ADMIN 服务地址
|
||||
VITE_ADMIN_PROXY_PATH = http://scj-v3.zhxy.link/api
|
||||
3
.gitignore
vendored
3
.gitignore
vendored
@@ -31,4 +31,5 @@ pnpm-lock.yaml
|
||||
|
||||
# cursor review
|
||||
final_review_gate.py
|
||||
.cursor/
|
||||
.cursor/
|
||||
.env.development
|
||||
BIN
src/assets/file/履约验收模版/表3:履约验收表模板(工程).wps
Normal file
BIN
src/assets/file/履约验收模版/表3:履约验收表模板(工程).wps
Normal file
Binary file not shown.
BIN
src/assets/file/履约验收模版/表3:履约验收表模板(服务).wps
Normal file
BIN
src/assets/file/履约验收模版/表3:履约验收表模板(服务).wps
Normal file
Binary file not shown.
BIN
src/assets/file/履约验收模版/表3:履约验收表模板(货物).wps
Normal file
BIN
src/assets/file/履约验收模版/表3:履约验收表模板(货物).wps
Normal file
Binary file not shown.
BIN
src/assets/file/服务商城采购需求模板/服务商城项目需求模板(公开比选).doc
Normal file
BIN
src/assets/file/服务商城采购需求模板/服务商城项目需求模板(公开比选).doc
Normal file
Binary file not shown.
BIN
src/assets/file/服务商城采购需求模板/服务商城项目需求模板(直选).doc
Normal file
BIN
src/assets/file/服务商城采购需求模板/服务商城项目需求模板(直选).doc
Normal file
Binary file not shown.
BIN
src/assets/file/服务商城采购需求模板/服务商城项目需求模板(邀请比选).doc
Normal file
BIN
src/assets/file/服务商城采购需求模板/服务商城项目需求模板(邀请比选).doc
Normal file
Binary file not shown.
BIN
src/assets/file/服务商城采购需求模板/附1:服务商城服务类品目.xlsx
Normal file
BIN
src/assets/file/服务商城采购需求模板/附1:服务商城服务类品目.xlsx
Normal file
Binary file not shown.
BIN
src/assets/file/服务商城采购需求模板/附2:服务商城工程类品目.xlsx
Normal file
BIN
src/assets/file/服务商城采购需求模板/附2:服务商城工程类品目.xlsx
Normal file
Binary file not shown.
BIN
src/assets/file/表1:采购需求填报模板.doc
Normal file
BIN
src/assets/file/表1:采购需求填报模板.doc
Normal file
Binary file not shown.
BIN
src/assets/file/表2 政府采购意向公告模版.xlsx
Normal file
BIN
src/assets/file/表2 政府采购意向公告模版.xlsx
Normal file
Binary file not shown.
BIN
src/assets/file/表3:履约验收表模板.docx
Normal file
BIN
src/assets/file/表3:履约验收表模板.docx
Normal file
Binary file not shown.
BIN
src/assets/file/表4:采购申请审批表(系统生成).docx
Normal file
BIN
src/assets/file/表4:采购申请审批表(系统生成).docx
Normal file
Binary file not shown.
BIN
src/assets/file/表5:采购文件审批表(系统生成).docx
Normal file
BIN
src/assets/file/表5:采购文件审批表(系统生成).docx
Normal file
Binary file not shown.
@@ -16,7 +16,8 @@ import SignInput from "./sign/index.vue";
|
||||
|
||||
// vite 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']
|
||||
)
|
||||
|
||||
/**
|
||||
|
||||
@@ -29,6 +29,7 @@ declare module 'vue-router' {
|
||||
isIframe?: boolean;
|
||||
roles?: string[];
|
||||
icon?: string;
|
||||
activeMenu?: string; // 指定菜单高亮的路径
|
||||
}
|
||||
}
|
||||
|
||||
@@ -98,6 +99,14 @@ export const staticRoutes: Array<RouteRecordRaw> = [
|
||||
isAuth: true,
|
||||
},
|
||||
},
|
||||
{
|
||||
path: '/finance/purchasingrequisition/add',
|
||||
name: 'purchasingrequisition.add',
|
||||
component: () => import('/@/views/finance/purchasingrequisition/add.vue'),
|
||||
meta: {
|
||||
isAuth: false, // 不需要认证,纯页面展示
|
||||
},
|
||||
},
|
||||
...staticRoutesFlow
|
||||
];
|
||||
|
||||
|
||||
@@ -422,6 +422,16 @@
|
||||
</el-form-item>
|
||||
</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'">
|
||||
<el-form-item
|
||||
@@ -632,7 +642,7 @@
|
||||
</template>
|
||||
|
||||
<script setup lang="ts" name="PurchasingRequisitionAdd">
|
||||
import { reactive, ref, onMounted, computed, watch } from 'vue'
|
||||
import { reactive, ref, onMounted, computed, watch, nextTick } from 'vue'
|
||||
import { useRouter } from 'vue-router'
|
||||
import { addObj, tempStore } from '/@/api/finance/purchasingrequisition';
|
||||
import { getTree } from '/@/api/finance/purchasingcategory';
|
||||
@@ -682,6 +692,7 @@ const dataForm = reactive({
|
||||
purchaseRequirement: '',
|
||||
meetingMinutes: '',
|
||||
feasibilityReport: '',
|
||||
meetingMinutesUrgent: '',
|
||||
meetingMinutesSingle: '',
|
||||
meetingMinutesImport: '',
|
||||
singleSourceProof: '',
|
||||
@@ -735,6 +746,13 @@ const isDeptPurchase = computed(() => {
|
||||
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(() => {
|
||||
return isDeptPurchase.value ? '部门自行采购' : '学校统一采购';
|
||||
@@ -885,7 +903,7 @@ const downloadTemplate = async (type: string) => {
|
||||
'direct_select': { fileName: '服务商城项目需求模板(直选).doc', displayName: '服务商城项目需求模板(直选).doc' },
|
||||
'public_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' },
|
||||
'single_source': { fileName: '表7:单一来源论专家证附件.docx', displayName: '单一来源论专家证附件.docx' },
|
||||
'feasibility_report': { fileName: '表6:项目可行性论证报告模板.doc', displayName: '项目可行性论证报告模板.doc' },
|
||||
@@ -987,7 +1005,14 @@ const prevStep = () => {
|
||||
|
||||
// 取消
|
||||
const handleCancel = () => {
|
||||
router.back();
|
||||
// 如果是在 iframe 中,向父窗口发送关闭消息
|
||||
if (window.parent !== window) {
|
||||
window.parent.postMessage({
|
||||
type: 'purchasingrequisition:close'
|
||||
}, '*');
|
||||
} else {
|
||||
router.back();
|
||||
}
|
||||
};
|
||||
|
||||
// 获取品目树形数据
|
||||
@@ -1207,8 +1232,8 @@ const handleSubmit = async () => {
|
||||
'businessNegotiationTable', 'marketPurchaseMinutes', 'onlineMallMaterials',
|
||||
'serviceDirectSelect', 'servicePublicSelect', 'purchaseRequirementTemplate',
|
||||
'serviceInviteSelect', 'servicePublicSelectAuto', 'purchaseRequirement',
|
||||
'meetingMinutes', 'feasibilityReport', 'meetingMinutesSingle',
|
||||
'meetingMinutesImport', 'singleSourceProof', 'importApplication',
|
||||
'meetingMinutes', 'feasibilityReport', 'meetingMinutesUrgent',
|
||||
'meetingMinutesSingle', 'meetingMinutesImport', 'singleSourceProof', 'importApplication',
|
||||
'governmentPurchaseIntent', 'servicePublicSelectSchool'
|
||||
];
|
||||
|
||||
@@ -1220,7 +1245,15 @@ const handleSubmit = async () => {
|
||||
|
||||
await addObj(submitData);
|
||||
useMessage().success('提交成功');
|
||||
router.push('/finance/purchasingrequisition');
|
||||
|
||||
// 如果是在 iframe 中,向父窗口发送消息
|
||||
if (window.parent !== window) {
|
||||
window.parent.postMessage({
|
||||
type: 'purchasingrequisition:submitSuccess'
|
||||
}, '*');
|
||||
} else {
|
||||
router.push('/finance/purchasingrequisition');
|
||||
}
|
||||
} catch (err: any) {
|
||||
useMessage().error(err.msg || '提交失败');
|
||||
} finally {
|
||||
@@ -1248,8 +1281,8 @@ const handleTempStore = async () => {
|
||||
'businessNegotiationTable', 'marketPurchaseMinutes', 'onlineMallMaterials',
|
||||
'serviceDirectSelect', 'servicePublicSelect', 'purchaseRequirementTemplate',
|
||||
'serviceInviteSelect', 'servicePublicSelectAuto', 'purchaseRequirement',
|
||||
'meetingMinutes', 'feasibilityReport', 'meetingMinutesSingle',
|
||||
'meetingMinutesImport', 'singleSourceProof', 'importApplication',
|
||||
'meetingMinutes', 'feasibilityReport', 'meetingMinutesUrgent',
|
||||
'meetingMinutesSingle', 'meetingMinutesImport', 'singleSourceProof', 'importApplication',
|
||||
'governmentPurchaseIntent', 'servicePublicSelectSchool'
|
||||
];
|
||||
|
||||
@@ -1261,7 +1294,15 @@ const handleTempStore = async () => {
|
||||
|
||||
await tempStore(submitData);
|
||||
useMessage().success('暂存成功');
|
||||
router.push('/finance/purchasingrequisition');
|
||||
|
||||
// 如果是在 iframe 中,向父窗口发送消息
|
||||
if (window.parent !== window) {
|
||||
window.parent.postMessage({
|
||||
type: 'purchasingrequisition:submitSuccess'
|
||||
}, '*');
|
||||
} else {
|
||||
router.push('/finance/purchasingrequisition');
|
||||
}
|
||||
} catch (err: any) {
|
||||
useMessage().error(err.msg || '暂存失败');
|
||||
} finally {
|
||||
@@ -1292,6 +1333,31 @@ watch(() => categoryTreeData.value, () => {
|
||||
|
||||
// 初始化
|
||||
onMounted(async () => {
|
||||
// 检测是否在 iframe 中,如果是,则修改相关元素的 overflow 样式以支持滚动
|
||||
if (window.parent !== window) {
|
||||
nextTick(() => {
|
||||
// 修改 html 和 body
|
||||
document.documentElement.style.overflow = 'auto';
|
||||
document.documentElement.style.height = 'auto';
|
||||
document.body.style.overflow = 'auto';
|
||||
document.body.style.height = 'auto';
|
||||
|
||||
// 修改 html 和 body,添加类名
|
||||
document.documentElement.classList.add('iframe-mode');
|
||||
document.body.classList.add('iframe-mode');
|
||||
|
||||
// 修改 #app
|
||||
const app = document.getElementById('app');
|
||||
if (app) {
|
||||
app.style.overflow = 'auto';
|
||||
app.style.height = 'auto';
|
||||
app.style.minHeight = '100%';
|
||||
// 添加一个类名标记,方便样式控制
|
||||
app.classList.add('iframe-mode');
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
await Promise.all([
|
||||
getCategoryTreeData(),
|
||||
getFundSourceDict(),
|
||||
@@ -1341,3 +1407,26 @@ onMounted(async () => {
|
||||
}
|
||||
</style>
|
||||
|
||||
<style>
|
||||
/* 当页面在 iframe 中时,允许滚动 */
|
||||
html.iframe-mode,
|
||||
body.iframe-mode {
|
||||
overflow: auto !important;
|
||||
height: 100% !important;
|
||||
min-height: 100% !important;
|
||||
}
|
||||
|
||||
#app.iframe-mode {
|
||||
overflow: auto !important;
|
||||
height: auto !important;
|
||||
min-height: 100% !important;
|
||||
}
|
||||
|
||||
/* 在 iframe 模式下,修改页面容器样式 */
|
||||
.iframe-mode .modern-page-container {
|
||||
min-height: auto !important;
|
||||
height: auto !important;
|
||||
overflow: visible !important;
|
||||
}
|
||||
</style>
|
||||
|
||||
|
||||
@@ -213,13 +213,33 @@
|
||||
</el-card>
|
||||
</div>
|
||||
|
||||
<!-- 新增页面 iframe 对话框 -->
|
||||
<el-dialog
|
||||
v-model="showAddIframe"
|
||||
title="新增采购申请"
|
||||
width="1000px"
|
||||
:close-on-click-modal="false"
|
||||
:close-on-press-escape="true"
|
||||
destroy-on-close
|
||||
class="iframe-dialog"
|
||||
@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" />
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<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 { BasicTableProps, useTable } from "/@/hooks/table";
|
||||
import { getPage, delObj } from "/@/api/finance/purchasingrequisition";
|
||||
@@ -235,6 +255,9 @@ const tableRef = ref()
|
||||
const formDialogRef = ref()
|
||||
const searchFormRef = ref()
|
||||
const showSearch = ref(true)
|
||||
const showAddIframe = ref(false)
|
||||
const addIframeRef = ref<HTMLIFrameElement>()
|
||||
const addIframeSrc = ref('')
|
||||
|
||||
/**
|
||||
* 定义响应式表格数据
|
||||
@@ -265,12 +288,42 @@ const handleReset = () => {
|
||||
};
|
||||
|
||||
/**
|
||||
* 新增采购申请 - 跳转到新页面
|
||||
* 新增采购申请 - 在 iframe 中展示
|
||||
*/
|
||||
const handleAdd = () => {
|
||||
router.push({
|
||||
path: '/finance/purchasingrequisition/add'
|
||||
});
|
||||
// 构建 iframe 的 src,使用当前页面的 hash 路由
|
||||
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 +349,54 @@ const handleDelete = async (row: any) => {
|
||||
useMessage().error(err.msg || '删除失败');
|
||||
}
|
||||
};
|
||||
|
||||
// 组件卸载时清理事件监听器
|
||||
onUnmounted(() => {
|
||||
window.removeEventListener('message', handleIframeMessage)
|
||||
});
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss">
|
||||
@import '/@/assets/styles/modern-page.scss';
|
||||
|
||||
.iframe-dialog-content {
|
||||
width: 100%;
|
||||
height: 70vh;
|
||||
min-height: 500px;
|
||||
max-height: calc(100vh - 200px);
|
||||
position: relative;
|
||||
overflow: hidden;
|
||||
|
||||
.add-iframe {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
min-height: 500px;
|
||||
border: none;
|
||||
display: block;
|
||||
}
|
||||
}
|
||||
|
||||
:deep(.iframe-dialog) {
|
||||
.el-dialog {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
max-height: 90vh;
|
||||
margin-top: 5vh !important;
|
||||
}
|
||||
|
||||
.el-dialog__header {
|
||||
flex-shrink: 0;
|
||||
padding: 20px 20px 10px;
|
||||
}
|
||||
|
||||
.el-dialog__body {
|
||||
padding: 20px;
|
||||
overflow-y: auto;
|
||||
overflow-x: hidden;
|
||||
flex: 1;
|
||||
min-height: 0;
|
||||
max-height: calc(100vh - 200px);
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
||||
|
||||
Reference in New Issue
Block a user