This commit is contained in:
Teo
2025-09-09 10:07:21 +08:00
116 changed files with 11164 additions and 3383 deletions

View File

@ -47,9 +47,9 @@
<el-row :gutter="8" class="mb-3 font-medium text-gray-700 whitespace-nowrap">
<el-col :span="4">专业</el-col>
<el-col :span="5">设计人员可多选</el-col>
<el-col :span="5">校审人员</el-col>
<el-col :span="5">校审人员</el-col> <el-col :span="4">审核人员</el-col>
<el-col :span="5">审定人员</el-col>
<el-col :span="4">审核人员</el-col>
<el-col :span="3"></el-col>
</el-row>
@ -65,7 +65,7 @@
>
<el-row :gutter="8" class="items-top">
<!-- 1. 专业选择核心统一所有角色的专业来源 -->
<el-col :span="3" class="mb-4 sm:mb-0 pl-4" style="margin-top:8px;">
<el-col :span="3" class="mb-4 sm:mb-0 pl-4" style="margin-top: 8px">
<el-form-item
:prop="`designers.${configIndex}.userMajor`"
:rules="[
@ -76,7 +76,8 @@
label-width="60px"
label="专业"
>
<el-select filterable
<el-select
filterable
v-model="form.designers[configIndex].userMajor"
placeholder="请选择专业"
class="w-full transition-all duration-300 border-gray-300"
@ -109,7 +110,8 @@
label="设计"
label-width="50px"
>
<el-select filterable
<el-select
filterable
v-model="person.userId"
placeholder="选择人员"
class="w-full transition-all duration-300 border-gray-300"
@ -165,7 +167,8 @@
label="校审"
label-width="50px"
>
<el-select filterable
<el-select
filterable
v-model="person.userId"
placeholder="选择人员"
class="w-full transition-all duration-300 border-gray-300"
@ -206,7 +209,65 @@
</el-col>
<!-- 4. 审定人员 -->
<!-- 5. 审核人员 -->
<el-col :span="5" class="mb-4 sm:mb-0">
<div class="pl-2 border-l-2 border-purple-200 py-2">
<div class="space-y-3">
<div
v-for="(person, personIndex) in majorConfig.auditorPersons"
:key="`auditor-${configIndex}-${personIndex}`"
class="flex items-center"
>
<el-form-item
:prop="`auditor.${configIndex}.persons.${personIndex}.userId`"
:rules="{ required: true, message: '请选择审核人员', trigger: 'change' }"
class="flex-1 mr-2 mb-0"
label="审核"
label-width="50px"
>
<el-select
filterable
v-model="person.userId"
placeholder="选择人员"
class="w-full transition-all duration-300 border-gray-300"
@change="() => checkDuplicate(person, 'auditor', configIndex, personIndex)"
>
<el-option v-for="item in userList" :key="`user-${item.userId}`" :label="item.nickName" :value="item.userId" />
</el-select>
</el-form-item>
<!-- <div class="flex gap-1">
<el-button
type="danger"
size="small"
@click="removePerson('auditor', configIndex, personIndex)"
class="transition-all duration-300 hover:bg-red-600"
:disabled="majorConfig.auditorPersons.length <= 1 || disabledForm"
>
<el-icon :size="14"><Delete /></el-icon>
</el-button>
<el-button
type="success"
size="small"
@click="addPerson('auditor', configIndex)"
class="transition-all duration-300 transform hover:scale-105"
:disabled="!form.designers[configIndex].userMajor || disabledForm"
>
<el-icon :size="14"><Plus /></el-icon>
</el-button>
</div> -->
</div>
</div>
<div
v-if="majorConfig.auditorPersons.length == 0"
class="text-gray-500 text-xs py-2 bg-gray-100 rounded border border-dashed border-gray-200"
>
点击"添加"
</div>
</div>
</el-col>
<el-col :span="5" class="mb-4 sm:mb-0">
<div class="pl-2 border-l-2 border-orange-200 py-2">
<div class="space-y-3">
<div
@ -221,7 +282,8 @@
label="审定"
label-width="50px"
>
<el-select filterable
<el-select
filterable
v-model="person.userId"
placeholder="选择人员"
class="w-full transition-all duration-300 border-gray-300"
@ -261,64 +323,8 @@
</div>
</el-col>
<!-- 5. 审核人员 -->
<el-col :span="5" class="mb-4 sm:mb-0">
<div class="pl-2 border-l-2 border-purple-200 py-2">
<div class="space-y-3">
<div
v-for="(person, personIndex) in majorConfig.auditorPersons"
:key="`auditor-${configIndex}-${personIndex}`"
class="flex items-center"
>
<el-form-item
:prop="`auditor.${configIndex}.persons.${personIndex}.userId`"
:rules="{ required: true, message: '请选择审核人员', trigger: 'change' }"
class="flex-1 mr-2 mb-0"
label="审核"
label-width="50px"
>
<el-select filterable
v-model="person.userId"
placeholder="选择人员"
class="w-full transition-all duration-300 border-gray-300"
@change="() => checkDuplicate(person, 'auditor', configIndex, personIndex)"
>
<el-option v-for="item in userList" :key="`user-${item.userId}`" :label="item.nickName" :value="item.userId" />
</el-select>
</el-form-item>
<!-- <div class="flex gap-1">
<el-button
type="danger"
size="small"
@click="removePerson('auditor', configIndex, personIndex)"
class="transition-all duration-300 hover:bg-red-600"
:disabled="majorConfig.auditorPersons.length <= 1 || disabledForm"
>
<el-icon :size="14"><Delete /></el-icon>
</el-button>
<el-button
type="success"
size="small"
@click="addPerson('auditor', configIndex)"
class="transition-all duration-300 transform hover:scale-105"
:disabled="!form.designers[configIndex].userMajor || disabledForm"
>
<el-icon :size="14"><Plus /></el-icon>
</el-button>
</div> -->
</div>
</div>
<div
v-if="majorConfig.auditorPersons.length == 0"
class="text-gray-500 text-xs py-2 bg-gray-100 rounded border border-dashed border-gray-200"
>
点击"添加"
</div>
</div>
</el-col>
<!-- 操作列 -->
<el-col :span="2" class="text-right pr-4">
<el-col :span="2" class="pr-4 mt-2 text-right">
<el-button
type="text"
class="text-red-500 hover:text-red-700 transition-colors"
@ -338,13 +344,17 @@
type="primary"
size="large"
v-hasPermi="['design:user:batch']"
icon="Check"
@click="submitForm"
class="px-8 py-2.5 transition-all duration-300 transform hover:scale-105 bg-blue-500 hover:bg-blue-600 text-white font-medium"
>
<i class="el-icon-check mr-2"></i>确认提交
>确认提交
</el-button>
<el-button size="large" @click="resetForm" class="px-8 py-2.5 transition-all duration-300 border-gray-300 hover:bg-gray-100 font-medium">
<i class="el-icon-refresh mr-2"></i>重置
<el-button
size="large"
icon="Refresh"
@click="resetForm"
class="px-8 py-2.5 transition-all duration-300 border-gray-300 hover:bg-gray-100 font-medium"
>重置
</el-button>
</div>
</el-form>

View File

@ -6,7 +6,7 @@
<el-card v-if="index < 3" shadow="always">
<el-form :model="state.queryForm" :inline="true">
<el-form-item label="版本号" prop="versions">
<el-select v-model="state.queryForm.versions" placeholder="选择版本号">
<el-select v-model="state.queryForm.versions" placeholder="选择版本号" @change="handleChangeVersion">
<el-option v-for="item in state.options" :key="item.versions" :label="item.versions" :value="item.versions" />
</el-select>
</el-form-item>
@ -16,7 +16,7 @@
</el-select>
</el-form-item>
<el-form-item>
<el-button type="primary" @click="openTable(index)">{{ isExpandAll ? '一键收起' : '一键展开' }}</el-button>
<el-button type="primary" @click="openTable(index)">{{ isExpandAll ? '一键收起' : '一键展开' }}</el-button>
</el-form-item>
<el-form-item>
<el-button type="success" @click="downloadTemplate(1)">下载模板</el-button>
@ -62,15 +62,10 @@
</el-upload>
</el-form-item>
<el-form-item v-if="state.versionsData.status == 'draft'">
<el-button type="primary" con="edit" @click="clickApprovalSheet()">审核</el-button>
<el-button type="primary" con="edit" @click="clickApprovalSheet()">审核</el-button>
</el-form-item>
<el-form-item v-if="state.versionsData.status == 'waiting' || state.versionsData.status == 'finish'">
<el-button
icon="view"
@click="lookApprovalFlow()"
type="warning"
>查看流程</el-button
>
<el-button icon="view" @click="lookApprovalFlow()" type="warning">查看流程</el-button>
</el-form-item>
</el-form>
</el-card>
@ -171,6 +166,7 @@ const handleTabChange = (tab) => {
onMounted(async () => {
await getVersionNums();
});
// 获取版本号
async function getVersionNums(isSheet = true) {
try {
@ -247,10 +243,10 @@ async function handleSheetName() {
// 获取列表
async function handleQueryList(isSheet = true) {
if (isSheet && !state.queryForm.sheet) {
console.warn('表名不存在,无法获取列表数据');
return;
}
// if (isSheet && !state.queryForm) {
// console.warn('表名不存在,无法获取列表数据');
// return;
// }
try {
state.loading.list = true;
@ -308,12 +304,12 @@ function handleChange(sheet) {
function handleChangeVersion(versions) {
state.queryForm.versions = versions;
state.versionsData = state.options.find((e) => e.versions == versions);
console.log('state.versionsData', state.versionsData);
// console.log('state.versionsData', state.versionsData);
state.sheets = [];
handleQueryList();
}
// 在 openTable 方法中通过索引获取对应的表格实例
function openTable( index) {
function openTable(index) {
isExpandAll.value = !isExpandAll.value;
nextTick(() => {
// 通过索引获取当前标签页的表格实例
@ -358,12 +354,12 @@ function lookApprovalFlow(row) {
const downloadTemplate = (type) => {
// 导出模版文件
try {
let linkurl = '';
let linkurl = '';
let name = '';
if (type==1) {
if (type == 1) {
linkurl = '/billOfQuantities.xlsx';
name = '工程量清单模板.xlsx';
}else{
} else {
linkurl = '/materialsEquipment.xlsx';
name = '物资设备清单模板.xlsx';
}

View File

@ -16,7 +16,7 @@
<!-- 表单区域 -->
<el-card class="rounded-lg shadow-sm bg-white border border-gray-100 transition-all hover:shadow-md overflow-hidden">
<div class="p-4 bg-gradient-to-r from-blue-50 to-indigo-50 border-b border-gray-100">
<h3 class="text-lg font-semibold text-gray-800">投标工程清单</h3>
<h3 class="text-lg font-semibold text-gray-800">投标工程清单</h3>
</div>
<div class="p-6">
<el-form

View File

@ -113,7 +113,7 @@ const approvalRecordRef = ref<InstanceType<typeof ApprovalRecord>>();
//按钮组件
const flowCodeOptions = [
{
value: currentProject.value?.id + '_materialsPlans',
value: currentProject.value?.id + '_equipmentList',
label: '物资设备清单审核'
}
];

View File

@ -93,11 +93,10 @@
>审核通知单</el-button
>
<el-button
v-if="scope.row.status != 'draft'"
v-if="scope.row.status != 'draft' || scope.row.auditStatus != 'draft'"
type="success"
link
icon="View"
v-hasPermi="['design:designChange:query']"
@click="handleViewDetail(scope.row)"
>查看通知单</el-button
>
@ -113,8 +112,7 @@
type="warning"
link
icon="View"
v-hasPermi="['design:drawingreviewReceipts:list']"
v-if="scope.row.status != 'draft'"
v-if="scope.row.status != 'draft' || scope.row.auditStatus != 'draft'"
@click="handleViewHistory(scope.row)"
>查看单据</el-button
>

View File

@ -50,7 +50,7 @@
<div class="p-4">
<p class="text-gray-600 mb-4">请选择要启动的流程</p>
<el-select v-model="flowCode" placeholder="请选择流程" style="width: 100%">
<el-option v-for="item in flowCodeOptions" :key="item.value" :label="item.label" :value="item.value" />
<el-option v-for="item in [flowCodeOptions[optionIndex]]" :key="item.value" :label="item.label" :value="item.value" />
</el-select>
</div>
<template #footer>
@ -98,6 +98,7 @@ const flowCodeOptions = ref([
label: '资金设计变更审批'
}
]);
const optionIndex = ref<number>(0);
const flowCode = ref<string>('');
const status = ref<string>('');
@ -272,12 +273,12 @@ const submit = async (status, data) => {
} else {
if ((form.value.status === 'draft' && (flowCode.value === '' || flowCode.value === null)) || routeParams.value.type === 'add') {
if (form.value.costEstimation == '0') {
flowCodeOptions.value = [flowCodeOptions.value[0]];
optionIndex.value = 0;
} else {
console.log('🚀 ~ submit ~ flowCodeOptions.value:', flowCodeOptions.value[1]);
flowCodeOptions.value = [flowCodeOptions.value[1]];
optionIndex.value = 1;
}
flowCode.value = flowCodeOptions.value[0].value;
flowCode.value = flowCodeOptions.value[optionIndex.value].value;
dialogVisible.visible = true;
return;
}

View File

@ -49,7 +49,32 @@
<!-- 资料文件区域 -->
<div class="mb-8">
<div class="flex items-center justify-between mb-5">
<h3 class="text-lg font-semibold text-blue-700">资料文件清单</h3>
<div style="display: flex; align-items: center">
<h3 class="text-lg font-semibold text-blue-700" style="margin-right: 20px">资料文件清单</h3>
<el-upload
class="upload-excel"
action="#"
v-if="!form.id || form.status == 'draft'"
ref="uploadRef"
:auto-upload="false"
:on-change="importTemplate"
:show-file-list="false"
:accept="'.xlsx,.xls'"
:limit="1"
>
<el-button type="primary" icon="Download">导入文件</el-button>
</el-upload>
<el-button
v-if="!form.id || form.status == 'draft'"
type="primary"
style="margin-left: 20px"
icon="Upload"
@click="exportTemplate"
class="transition-all hover:bg-blue-600"
>
导出模版
</el-button>
</div>
<el-button type="primary" size="small" @click="addDocumentItem" v-if="!disabledAll" icon="Plus" class="transition-all hover:bg-blue-600">
添加资料
</el-button>
@ -180,11 +205,11 @@ import { ref, reactive, computed, onMounted, onUnmounted, watch, getCurrentInsta
import { useUserStoreHook } from '@/store/modules/user';
import { ElMessage, ElLoading, FormRules } from 'element-plus';
import { systemUserList } from '@/api/design/appointment';
import { collectBatch, byProjectId, exportWord } from '@/api/design/received';
import { collectBatch, byProjectId, exportWord, exportExcel } from '@/api/design/received';
import { getUser } from '@/api/system/user';
import type { ComponentInternalInstance, ElFormInstance } from 'element-plus';
import { getInfo } from '@/api/login';
import * as XLSX from 'xlsx';
// 全局实例与状态管理
const { proxy } = getCurrentInstance() as ComponentInternalInstance;
const userStore = useUserStoreHook();
@ -200,7 +225,7 @@ const documentsFormRef = ref<ElFormInstance>();
const userList = ref<any[]>([]);
const userMap = new Map<string, string>(); // 存储用户ID与昵称映射
const disabledAll = ref(false); // 表单是否全部禁用
const uploadRef = ref<any>();
// 表单核心数据
const form = reactive({
projectId: currentProject.value?.id,
@ -445,7 +470,66 @@ const onLoad = async () => {
console.error('文件导出错误:', error);
}
};
const exportTemplate = async () => {
// 导出模版
proxy?.download(
'design/collect/exportExcel',
{
deptId: userStore.deptId
},
`收资清单表格.xlsx`
);
};
const importTemplate = async (files, fileList) => {
// 导入表格数据
const file = fileList[0].raw; // 获取原始文件对象
const reader = new FileReader();
let obj = {
id: '编码',
name: '人员',
fliename: '目录名',
remark: '备注'
};
reader.onload = (e) => {
try {
// 读取文件内容
const data = new Uint8Array(e.target.result);
// 解析Excel
const workbook = XLSX.read(data, { type: 'array' });
// 获取第一个工作表名称
const firstSheetName = workbook.SheetNames[0];
// 获取第一个工作表内容
const worksheet = workbook.Sheets[firstSheetName];
// 转换为JSON格式
const jsonData = XLSX.utils.sheet_to_json(worksheet);
if (jsonData.length === 0) {
ElMessage.info('Excel文件中没有数据');
return;
}
let arr = [];
// 判断form.documents 是否对象
jsonData.forEach((item, index) => {
if (item[obj.id]) {
arr.push({
id: Date.now() + index,
catalogueName: item[obj.fliename],
remark: item[obj.remark],
userId: item[obj.id]
});
}
});
form.documents = arr;
uploadRef.value.clearFiles();
console.log(arr);
} catch (err) {}
};
// 以ArrayBuffer方式读取文件
reader.readAsArrayBuffer(file);
};
/** 页面挂载初始化 */
onMounted(() => {
// 先获取当前用户信息,再获取部门用户列表,最后回显表单数据

View File

@ -121,10 +121,10 @@
</div> -->
<div class="info-item">
<span class="info-label">更新时间</span>
<span class="info-label">上传时间</span>
<div class="info-value mt-0.5 flex items-center">
<i class="fa fa-calendar-o text-gray-400 dark:text-gray-500 mr-1.5"></i>
{{ info.updateTime || '未更新' }}
{{ info.createTime || '暂无' }}
</div>
</div>
</div>

View File

@ -68,6 +68,7 @@
<el-button link type="primary" icon="View" @click="handleView(scope.row)" v-hasPermi="['design:volumeCatalog:listFile']"
>查看文件</el-button
>
<el-badge v-if="scope.row.fileCount" :value="scope.row.fileCount" class="item" type="danger"> </el-badge>
</template>
</el-table-column>
<el-table-column label="外部意见" align="center">
@ -153,6 +154,11 @@
<el-form-item v-if="uploadForm.type == '3'" label="蓝图" prop="fileIds">
<file-upload :fileType="['pdf']" :isShowTip="false" :fileSize="100" v-model="uploadForm.fileIds"></file-upload>
</el-form-item>
<el-form-item v-if="uploadForm.type == '3'" label="通知人">
<el-select multiple filterable clearable v-model="form.userIds" placeholder="请选择通知人">
<el-option :value="item.userId" v-for="item in userCoryList" :key="item.userId" :label="item.nickName + '-' + item.phonenumber" />
</el-select>
</el-form-item>
<el-form-item v-if="uploadForm.type == '1'" label="过程图纸" prop="cancellationIds">
<file-upload :fileType="['pdf']" :isShowTip="false" :fileSize="100" v-model="uploadForm.cancellationIds"></file-upload>
</el-form-item>
@ -166,8 +172,8 @@
<!-- 查看文件列表 -->
<el-dialog draggable title="图纸列表" v-model="viewVisible" width="1000px">
<el-tabs type="border-card" v-model="activeName" class="demo-tabs" @tab-click="handleClick">
<el-tab-pane label="蓝图" name="3"
><TableContent :data="fileList" :wf-business-status="wf_business_status">
<el-tab-pane label="蓝图" name="3">
<TableContent :data="fileList" :wf-business-status="wf_business_status">
<template #operation="{ row }">
<el-button
link
@ -190,10 +196,10 @@
>查看单据</el-button
>
</template>
</TableContent></el-tab-pane
>
<el-tab-pane label="过程图纸 " name="1"
><TableContent :data="fileList" :wf-business-status="wf_business_status">
</TableContent>
</el-tab-pane>
<el-tab-pane label="过程图纸 " name="1">
<TableContent :data="fileList" :wf-business-status="wf_business_status">
<template #operation="{ row }">
<el-button link type="primary" icon="edit" @click="handleAudit(row)" v-if="row.auditStatus == 'draft' || row.auditStatus == 'back'"
>审核</el-button
@ -211,15 +217,15 @@
>查看单据</el-button
>
</template>
</TableContent></el-tab-pane
>
<el-tab-pane label="作废 " name="4"
><TableContent :data="fileList" :wf-business-status="wf_business_status">
</TableContent>
</el-tab-pane>
<el-tab-pane label="作废 " name="4">
<TableContent :data="fileList" :wf-business-status="wf_business_status">
<template #operation="{ row }">
<el-button type="danger" link icon="Download" @click="handleDownload(row)"> 下载 </el-button>
</template>
</TableContent></el-tab-pane
>
</TableContent>
</el-tab-pane>
</el-tabs>
<template #footer>
<span>
@ -255,7 +261,8 @@ import {
uploadVolumeFile,
majorList,
getVolumeCatafileList,
volumeFileList
volumeFileList,
copyUserList
} from '@/api/design/volumeCatalog';
import { VolumeCatalogVO } from '@/api/design/volumeCatalog/types';
import { useUserStoreHook } from '@/store/modules/user';
@ -281,6 +288,7 @@ const uploadOpinionVisible = ref(false);
const design = ref('');
const total = ref(0);
const dialogHistory = ref(false);
const userCoryList = ref([]);
const opinion = ref('');
const updateRow = ref({
opinion: []
@ -416,7 +424,13 @@ const cancel = () => {
reset();
dialog.visible = false;
};
// 获取人员列表
const getDesignUserList = async () => {
const res = await copyUserList({ projectId: currentProject.value?.id, userType: 2 });
if (res.code === 200) {
userCoryList.value = res.data;
}
};
/** 表单重置 */
const reset = () => {
form.value = { ...initFormData };
@ -546,7 +560,7 @@ const onSubmit = async () => {
type: uploadForm.type
};
try {
await uploadVolumeFile(obj);
await uploadVolumeFile({ ...obj, userIds: form.value.userIds });
proxy?.$modal.msgSuccess('文件上传成功');
uploadVisible.value = false;
await getList();
@ -631,22 +645,29 @@ const getVolumeFileList = async (type) => {
}
};
const exportFile = () => {
// 导出模版文件
try {
// 创建a标签
const link = document.createElement('a');
// 设置PDF文件路径 - 相对于public目录
link.href = '/catalog.xlsx';
// 设置下载后的文件名
link.download = '设计出图计划导入模版.xlsx';
// 触发点击
document.body.appendChild(link);
link.click();
// 清理
document.body.removeChild(link);
} catch (error) {
alert('下载失败,请重试');
}
proxy?.download(
'/design/volumeCatalog/exportExcel',
{
projectId: currentProject.value?.id
},
`设计出图计划导入模版.xlsx`
);
// // 导出模版文件
// try {
// // 创建a标签
// const link = document.createElement('a');
// // 设置PDF文件路径 - 相对于public目录
// link.href = '/catalog.xlsx';
// // 设置下载后的文件名
// link.download = '设计出图计划导入模版.xlsx';
// // 触发点击
// document.body.appendChild(link);
// link.click();
// // 清理
// document.body.removeChild(link);
// } catch (error) {
// alert('下载失败,请重试');
// }
};
// 切换
const handleClick = (val) => {
@ -656,6 +677,7 @@ const handleAuditInfo = (row) => {
// 审核图纸
};
onMounted(() => {
getDesignUserList();
getSpecialtyList();
getList();
});
@ -666,6 +688,7 @@ const listeningProject = watch(
(nid, oid) => {
queryParams.value.projectId = nid;
form.value.projectId = nid;
getDesignUserList();
getSpecialtyList();
getList();
}
@ -684,6 +707,7 @@ onUnmounted(() => {
border-collapse: collapse; //合并为一个单一的边框
border-color: rgba(199, 199, 199, 1); //边框颜色按实际自定义即可
}
thead {
tr {
th {
@ -693,16 +717,19 @@ onUnmounted(() => {
letter-spacing: 5px;
padding: 15px;
}
td {
text-align: left;
height: 35px; //设置单元格最小高度
padding: 15px;
}
.th-bg {
background-color: rgba(247, 247, 247, 1);
}
}
}
tbody {
tr {
td {
@ -710,6 +737,7 @@ onUnmounted(() => {
height: 40px; //设置单元格最小高度
padding: 15px;
}
th {
height: 35px; //设置单元格最小高度
text-align: center;
@ -718,6 +746,7 @@ onUnmounted(() => {
}
}
}
.table-content {
box-shadow: 0px 0px 10px #ddd;
padding: 20px;