设计资料
This commit is contained in:
@ -5,7 +5,7 @@ VITE_APP_TITLE = 新能源项目管理平台
|
||||
VITE_APP_ENV = 'development'
|
||||
|
||||
# 开发环境
|
||||
VITE_APP_BASE_API = 'http://192.168.110.159:8898'
|
||||
VITE_APP_BASE_API = 'http://192.168.110.180:8898'
|
||||
|
||||
# 无人机接口地址
|
||||
|
||||
|
26
src/api/design/Professional/index.ts
Normal file
26
src/api/design/Professional/index.ts
Normal file
@ -0,0 +1,26 @@
|
||||
import request from '@/utils/request';
|
||||
|
||||
// 提资计划
|
||||
// 批量新增或修改
|
||||
export const extractBatch = (data) => {
|
||||
return request({
|
||||
url: '/design/extract/batch',
|
||||
method: 'post',
|
||||
data: data
|
||||
});
|
||||
};
|
||||
// 批量新增或修改
|
||||
export const extractList = (params) => {
|
||||
return request({
|
||||
url: '/design/extract/list',
|
||||
method: 'get',
|
||||
params: params
|
||||
});
|
||||
};
|
||||
// 获取提资清单详细信息
|
||||
export const extractDetail = (id) => {
|
||||
return request({
|
||||
url: '/design/extract/' + id,
|
||||
method: 'get'
|
||||
});
|
||||
};
|
29
src/api/design/appointment/index.ts
Normal file
29
src/api/design/appointment/index.ts
Normal file
@ -0,0 +1,29 @@
|
||||
import request from '@/utils/request';
|
||||
|
||||
// 设计人员
|
||||
// 新增
|
||||
export const designUserAdd = (data) => {
|
||||
return request({
|
||||
url: '/design/user/batch',
|
||||
method: 'post',
|
||||
data: data
|
||||
});
|
||||
};
|
||||
|
||||
// 查询
|
||||
export const designUserList = (query) => {
|
||||
return request({
|
||||
url: '/design/user/list',
|
||||
method: 'get',
|
||||
params: query
|
||||
});
|
||||
};
|
||||
|
||||
// 查询
|
||||
export const systemUserList = (query) => {
|
||||
return request({
|
||||
url: '/system/user/list',
|
||||
method: 'get',
|
||||
params: query
|
||||
});
|
||||
};
|
27
src/api/design/condition/index.ts
Normal file
27
src/api/design/condition/index.ts
Normal file
@ -0,0 +1,27 @@
|
||||
import request from '@/utils/request';
|
||||
|
||||
// 收资计划
|
||||
// 查询收资清单目录列表
|
||||
export const collectCatalogueList = (data) => {
|
||||
return request({
|
||||
url: '/design/collectCatalogue/list',
|
||||
method: 'get',
|
||||
params: data
|
||||
});
|
||||
};
|
||||
|
||||
// 查询收资文件列表
|
||||
export const collectFileList = (params) => {
|
||||
return request({
|
||||
url: '/design/collectFile/list',
|
||||
method: 'get',
|
||||
params
|
||||
});
|
||||
};
|
||||
// 获取收资文件详细信息
|
||||
export const getCollectFile = (id) => {
|
||||
return request({
|
||||
url: '/design/collectFile/' + id,
|
||||
method: 'get'
|
||||
});
|
||||
};
|
19
src/api/design/received/index.ts
Normal file
19
src/api/design/received/index.ts
Normal file
@ -0,0 +1,19 @@
|
||||
import request from '@/utils/request';
|
||||
|
||||
// 收资计划
|
||||
// 批量新增或修改
|
||||
export const collectBatch = (data) => {
|
||||
return request({
|
||||
url: '/design/collect/batch',
|
||||
method: 'post',
|
||||
data: data
|
||||
});
|
||||
};
|
||||
|
||||
// 获取收资清单详细信息
|
||||
export const byProjectId = (ProjectId) => {
|
||||
return request({
|
||||
url: '/design/collect/byProjectId/' + ProjectId,
|
||||
method: 'get'
|
||||
});
|
||||
};
|
@ -38,6 +38,7 @@ export const useUserStore = defineStore('user', () => {
|
||||
const nickname = ref('');
|
||||
const userId = ref<string | number>('');
|
||||
const tenantId = ref<string>('');
|
||||
const deptId = ref<string | number>('');
|
||||
const avatar = ref('');
|
||||
const roles = ref<Array<string>>([]); // 用户角色编码集合 → 判断路由权限
|
||||
const permissions = ref<Array<string>>([]); // 用户权限编码集合 → 判断按钮权限
|
||||
@ -82,6 +83,7 @@ export const useUserStore = defineStore('user', () => {
|
||||
avatar.value = profile;
|
||||
userId.value = user.userId;
|
||||
tenantId.value = user.tenantId;
|
||||
deptId.value = user.deptId;
|
||||
|
||||
// **新增项目数据获取**
|
||||
const [projectErr, projectRes] = await to(getUserProject());
|
||||
@ -141,6 +143,7 @@ export const useUserStore = defineStore('user', () => {
|
||||
return {
|
||||
userId,
|
||||
tenantId,
|
||||
deptId,
|
||||
token,
|
||||
nickname,
|
||||
avatar,
|
||||
|
156
src/views/design/Professional/index.vue
Normal file
156
src/views/design/Professional/index.vue
Normal file
@ -0,0 +1,156 @@
|
||||
<template>
|
||||
<div class="p-6 bg-gray-50 condition">
|
||||
<transition>
|
||||
<div v-show="showSearch" class="mb-[10px]">
|
||||
<el-card shadow="never">
|
||||
<el-form ref="queryFormRef" :model="queryParams" :inline="true">
|
||||
<el-form-item label="电话" prop="phone">
|
||||
<el-input v-model="queryParams.phone" placeholder="请输入电话" clearable @keyup.enter="handleQuery" />
|
||||
</el-form-item>
|
||||
<el-form-item>
|
||||
<el-button type="primary" icon="Search" @click="handleQuery">搜索</el-button>
|
||||
<el-button icon="Refresh" @click="resetQuery">重置</el-button>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
</el-card>
|
||||
</div>
|
||||
</transition>
|
||||
<el-card shadow="never">
|
||||
<template #header>
|
||||
<el-row :gutter="10" class="mb8">
|
||||
<el-col :span="1.5">
|
||||
<el-button type="primary" plain icon="Plus" @click="handleAdd">新增</el-button>
|
||||
</el-col>
|
||||
<right-toolbar v-model:showSearch="showSearch" @queryTable="getList"></right-toolbar>
|
||||
</el-row>
|
||||
</template>
|
||||
<el-table v-loading="loading" :data="professionalList">
|
||||
<el-table-column label="序号" align="center" type="index" width="100" />
|
||||
<el-table-column label="提资人" align="center" prop="userName" />
|
||||
<el-table-column label="专业" align="center" prop="userMajor" />
|
||||
<el-table-column label="电话" align="center" prop="phone" />
|
||||
<el-table-column label="邮箱" align="center" prop="email" />
|
||||
<el-table-column label="流程状态" align="center" prop="status">
|
||||
<template #default="scope">
|
||||
<dict-tag :options="wf_business_status" :value="scope.row.status" />
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="操作">
|
||||
<template #default="scope">
|
||||
<el-row :gutter="10" class="mb8">
|
||||
<el-col :span="1.5" v-if="scope.row.status === 'draft' || scope.row.status === 'cancel' || scope.row.status === 'back'">
|
||||
<el-button size="small" type="primary" icon="Edit" @click="handleUpdate(scope.row)">审核</el-button>
|
||||
</el-col>
|
||||
<!-- <el-col :span="1.5" v-if="scope.row.status === 'draft' || scope.row.status === 'cancel' || scope.row.status === 'back'">
|
||||
<el-button size="small" type="primary" icon="Delete" @click="handleDelete(scope.row)">删除</el-button>
|
||||
</el-col> -->
|
||||
</el-row>
|
||||
<el-row :gutter="10" class="mb8">
|
||||
<el-col :span="1.5">
|
||||
<el-button type="warning" size="small" icon="View" v-if="scope.row.status != 'draft'" @click="handleViewInfo(scope.row)"
|
||||
>查看流程</el-button
|
||||
>
|
||||
</el-col>
|
||||
</el-row>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
<pagination v-show="total > 0" :total="total" v-model:page="queryParams.pageNum" v-model:limit="queryParams.pageSize" @pagination="getList" />
|
||||
</el-card>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup name="DataCollectionForm" lang="ts">
|
||||
import { ref, reactive, computed, onMounted } from 'vue';
|
||||
import { useUserStoreHook } from '@/store/modules/user';
|
||||
const { proxy } = getCurrentInstance() as ComponentInternalInstance;
|
||||
const { wf_business_status } = toRefs<any>(proxy?.useDict('wf_business_status'));
|
||||
import { extractList } from '@/api/design/Professional';
|
||||
|
||||
// 获取用户 store
|
||||
const userStore = useUserStoreHook();
|
||||
const total = ref(0);
|
||||
// 从 store 中获取当前选中的项目
|
||||
const currentProject = computed(() => userStore.selectedProject);
|
||||
const professionalList = ref([]);
|
||||
const showSearch = ref(true);
|
||||
const loading = ref(false);
|
||||
const data = reactive({
|
||||
queryParams: {
|
||||
pageNum: 1,
|
||||
pageSize: 10,
|
||||
projectId: currentProject.value?.id,
|
||||
phone: undefined,
|
||||
status: undefined,
|
||||
params: {}
|
||||
}
|
||||
});
|
||||
const queryFormRef = ref<ElFormInstance>();
|
||||
const { queryParams } = toRefs(data);
|
||||
// 查询提资清单表
|
||||
const getList = async () => {
|
||||
let res = await extractList({ projectId: currentProject.value?.id });
|
||||
if (res.code == 200) {
|
||||
professionalList.value = res.rows;
|
||||
total.value = res.total; //默认第一个
|
||||
}
|
||||
};
|
||||
/** 搜索按钮操作 */
|
||||
const handleQuery = () => {
|
||||
queryParams.value.pageNum = 1;
|
||||
getList();
|
||||
};
|
||||
|
||||
/** 重置按钮操作 */
|
||||
const resetQuery = () => {
|
||||
queryFormRef.value?.resetFields();
|
||||
handleQuery();
|
||||
};
|
||||
/** 新增按钮操作 */
|
||||
const handleAdd = (row) => {
|
||||
proxy.$tab.closePage(proxy.$route);
|
||||
proxy.$router.push({
|
||||
path: `/design-management/Professional/indexEdit`,
|
||||
query: {
|
||||
id: row.id,
|
||||
type: 'add'
|
||||
}
|
||||
});
|
||||
};
|
||||
const handleViewInfo = (row) => {
|
||||
proxy.$tab.closePage(proxy.$route);
|
||||
proxy.$router.push({
|
||||
path: `/design-management/Professional/indexEdit`,
|
||||
query: {
|
||||
id: row.id,
|
||||
type: 'view'
|
||||
}
|
||||
});
|
||||
};
|
||||
const handleUpdate = (row) => {
|
||||
proxy.$tab.closePage(proxy.$route);
|
||||
proxy.$router.push({
|
||||
path: `/design-management/Professional/indexEdit`,
|
||||
query: {
|
||||
id: row.id,
|
||||
type: 'update'
|
||||
}
|
||||
});
|
||||
};
|
||||
const handleDelete = (row) => {
|
||||
//
|
||||
};
|
||||
|
||||
// 页面挂载时初始化数据
|
||||
onMounted(() => {
|
||||
getList();
|
||||
});
|
||||
</script>
|
||||
|
||||
<style lang="scss">
|
||||
.condition {
|
||||
.el-tabs__header {
|
||||
height: 84vh !important;
|
||||
}
|
||||
}
|
||||
</style>
|
535
src/views/design/Professional/indexEdit.vue
Normal file
535
src/views/design/Professional/indexEdit.vue
Normal file
@ -0,0 +1,535 @@
|
||||
<template>
|
||||
<div class="p-4 bg-gray-50">
|
||||
<div class="max-w-4xl mx-auto">
|
||||
<!-- 顶部按钮区域 -->
|
||||
<el-card class="mb-4 rounded-lg shadow-sm bg-white border border-gray-100 transition-all hover:shadow-md">
|
||||
<approvalButton
|
||||
@submitForm="submitForm"
|
||||
@approvalVerifyOpen="approvalVerifyOpen"
|
||||
@handleApprovalRecord="handleApprovalRecord"
|
||||
:buttonLoading="buttonLoading"
|
||||
:id="form.id"
|
||||
:status="form.status"
|
||||
:pageType="routeParams.type"
|
||||
/>
|
||||
</el-card>
|
||||
<!-- 表单区域 -->
|
||||
<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>
|
||||
</div>
|
||||
<div class="p-6">
|
||||
<div class="appWidth mx-auto bg-white rounded-xl shadow-sm overflow-hidden transition-all duration-300 hover:shadow-md">
|
||||
<!-- 表单内容区域 -->
|
||||
<el-form :disabled="disableAll" ref="mainFormRef" :model="form" :rules="mainRules" label-width="120px" class="p-6">
|
||||
<!-- 基本信息区域 -->
|
||||
<div class="bg-blue-50 p-4 rounded-lg mb-6">
|
||||
<h3 class="text-lg font-semibold text-blue-700 mb-4">基本信息</h3>
|
||||
<div class="grid grid-cols-1 md:grid-cols-2 gap-4">
|
||||
<el-form-item label="收资人" prop="userId" class="mb-4">
|
||||
<el-select
|
||||
v-model="form.userId"
|
||||
placeholder="请选择提资人"
|
||||
class="w-full transition-all duration-300 border-gray-300 focus:border-blue-400 focus:ring-1 focus:ring-blue-400"
|
||||
>
|
||||
<el-option v-for="item in userList" :key="item.userId" :label="item.nickName" :value="item.userId" />
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item label="专业" prop="user_major" class="mb-4">
|
||||
<el-select
|
||||
v-model="form.user_major"
|
||||
placeholder="请选择专业"
|
||||
class="transition-all duration-300 border-gray-300"
|
||||
:rules="{ required: true, message: '请选择专业', trigger: 'change' }"
|
||||
>
|
||||
<el-option v-for="item in des_user_major" :key="item.value" :label="item.label" :value="item.value" />
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item label="电话" prop="phone" class="mb-4">
|
||||
<el-input placeholder="请输入电话" v-model="form.phone" autocomplete="off" />
|
||||
</el-form-item>
|
||||
<el-form-item label="邮箱" prop="email" class="mb-4">
|
||||
<el-input placeholder="请输入邮箱" v-model="form.email" autocomplete="off" />
|
||||
</el-form-item>
|
||||
</div>
|
||||
</div>
|
||||
<!-- 资料文件区域 -->
|
||||
<div class="mb-6">
|
||||
<div class="flex items-center justify-between mb-4">
|
||||
<h3 class="text-lg font-semibold text-blue-700">资料文件清单</h3>
|
||||
<el-button type="primary" size="small" @click="addDocumentItem" icon="Plus"> 添加资料 </el-button>
|
||||
</div>
|
||||
<el-form :disabled="disableAll" ref="documentsFormRef" :model="form" class="space-y-4">
|
||||
<div
|
||||
v-for="(item, index) in form.documents"
|
||||
:key="item.id"
|
||||
class="bg-gray-50 p-4 rounded-lg transition-all duration-200 hover:shadow-sm"
|
||||
>
|
||||
<div class="flex justify-between items-start mb-2">
|
||||
<span class="text-sm font-medium text-gray-600">资料 {{ index + 1 }}</span>
|
||||
<el-button
|
||||
type="text"
|
||||
size="small"
|
||||
text-color="#ff4d4f"
|
||||
@click="removeDocumentItem(index)"
|
||||
icon="el-icon-delete"
|
||||
v-if="form.documents.length > 1"
|
||||
>
|
||||
删除
|
||||
</el-button>
|
||||
</div>
|
||||
<div class="grid grid-cols-1 md:grid-cols-2 gap-4">
|
||||
<el-form-item
|
||||
label="资料名称"
|
||||
:prop="`documents.${index}.catalogueName`"
|
||||
:rules="[{ required: true, message: '请输入文件目录名称', trigger: 'blur' }]"
|
||||
class="mb-4"
|
||||
>
|
||||
<el-input placeholder="请输入文件目录名称" v-model="item.catalogueName" autocomplete="off" />
|
||||
</el-form-item>
|
||||
<el-form-item label="备注" :prop="`documents.${index}.remark`" class="mb-4">
|
||||
<el-input placeholder="请输入备注" v-model="item.remark" autocomplete="off" />
|
||||
</el-form-item>
|
||||
</div>
|
||||
</div>
|
||||
</el-form>
|
||||
</div>
|
||||
</el-form>
|
||||
</div>
|
||||
</div>
|
||||
</el-card>
|
||||
<!-- 提交组件 -->
|
||||
<submitVerify ref="submitVerifyRef" :task-variables="taskVariables" @submit-callback="submitCallback" />
|
||||
<approvalRecord ref="approvalRecordRef"></approvalRecord>
|
||||
<!-- 流程选择对话框 -->
|
||||
<el-dialog
|
||||
draggable
|
||||
v-model="dialogVisible.visible"
|
||||
:title="dialogVisible.title"
|
||||
:before-close="handleClose"
|
||||
width="500"
|
||||
class="rounded-lg shadow-lg"
|
||||
>
|
||||
<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-select>
|
||||
</div>
|
||||
<template #footer>
|
||||
<div class="dialog-footer p-4 border-t border-gray-100 flex justify-end space-x-3">
|
||||
<el-button @click="handleClose" class="px-4 py-2 border border-gray-300 rounded-md text-gray-700 hover:bg-gray-50 transition-colors"
|
||||
>取消</el-button
|
||||
>
|
||||
<el-button type="primary" @click="submitFlow()" class="px-4 py-2 bg-primary text-white rounded-md hover:bg-primary/90 transition-colors"
|
||||
>确认</el-button
|
||||
>
|
||||
</div>
|
||||
</template>
|
||||
</el-dialog>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup name="Leave" lang="ts">
|
||||
import { LeaveForm } from '@/api/workflow/leave/types';
|
||||
import { startWorkFlow } from '@/api/workflow/task';
|
||||
import SubmitVerify from '@/components/Process/submitVerify.vue';
|
||||
import ApprovalRecord from '@/components/Process/approvalRecord.vue';
|
||||
import ApprovalButton from '@/components/Process/approvalButton.vue';
|
||||
import { StartProcessBo } from '@/api/workflow/workflowCommon/types';
|
||||
const { proxy } = getCurrentInstance() as ComponentInternalInstance;
|
||||
import { useUserStoreHook } from '@/store/modules/user';
|
||||
import { systemUserList } from '@/api/design/appointment';
|
||||
import { extractBatch, extractDetail } from '@/api/design/Professional';
|
||||
// 获取用户 store
|
||||
const userStore = useUserStoreHook();
|
||||
// 从 store 中获取项目列表和当前选中的项目
|
||||
const currentProject = computed(() => userStore.selectedProject);
|
||||
const { des_user_major } = toRefs<any>(proxy?.useDict('des_user_major'));
|
||||
const buttonLoading = ref(false);
|
||||
const loading = ref(true);
|
||||
const disableAll = ref(false);
|
||||
//路由参数
|
||||
const routeParams = ref<Record<string, any>>({});
|
||||
const flowCodeOptions = [
|
||||
{
|
||||
value: currentProject.value?.id + '_extract',
|
||||
label: '互提资料清单'
|
||||
}
|
||||
];
|
||||
|
||||
const flowCode = ref<string>('');
|
||||
const status = ref<string>('');
|
||||
const dialogVisible = reactive<DialogOption>({
|
||||
visible: false,
|
||||
title: '流程定义'
|
||||
});
|
||||
//提交组件
|
||||
const submitVerifyRef = ref<InstanceType<typeof SubmitVerify>>();
|
||||
//审批记录组件
|
||||
const approvalRecordRef = ref<InstanceType<typeof ApprovalRecord>>();
|
||||
//按钮组件
|
||||
const approvalButtonRef = ref<InstanceType<typeof ApprovalButton>>();
|
||||
|
||||
const leaveFormRef = ref<ElFormInstance>();
|
||||
const dialog = reactive({
|
||||
visible: false,
|
||||
title: '',
|
||||
isEdit: false
|
||||
});
|
||||
const submitFormData = ref<StartProcessBo>({
|
||||
businessId: '',
|
||||
flowCode: '',
|
||||
variables: {}
|
||||
});
|
||||
const taskVariables = ref<Record<string, any>>({});
|
||||
// 用户列表
|
||||
const userList = ref([]);
|
||||
const userMap = new Map();
|
||||
// 表单引用
|
||||
const mainFormRef = ref();
|
||||
const handleClose = () => {
|
||||
dialogVisible.visible = false;
|
||||
flowCode.value = '';
|
||||
buttonLoading.value = false;
|
||||
};
|
||||
// 表单数据
|
||||
const form = reactive({
|
||||
projectId: currentProject.value?.id,
|
||||
userId: '', // 收资人
|
||||
user_major: '', // 专业
|
||||
phone: '', // 电话
|
||||
email: '', // 邮箱
|
||||
id: '',
|
||||
status: '',
|
||||
documents: [
|
||||
{
|
||||
id: Date.now(),
|
||||
catalogueName: '', // 文件目录名称
|
||||
remark: '' // 备注
|
||||
}
|
||||
] as Array<{
|
||||
id: number;
|
||||
catalogueName: string;
|
||||
remark: string;
|
||||
}>
|
||||
});
|
||||
// 主表单验证规则
|
||||
const mainRules = reactive({
|
||||
userId: [{ required: true, message: '请输入收资人', trigger: 'blur' }],
|
||||
user_major: [{ required: true, message: '请选择专业', trigger: 'change' }],
|
||||
phone: [
|
||||
{ required: true, message: '请输入电话', trigger: 'blur' },
|
||||
{ pattern: /^1[3-9]\d{9}$/, message: '请输入正确的手机号码', trigger: 'blur' }
|
||||
],
|
||||
email: [
|
||||
{ required: true, message: '请输入邮箱', trigger: 'blur' },
|
||||
{ type: 'email', message: '请输入正确的邮箱格式', trigger: 'blur' }
|
||||
]
|
||||
});
|
||||
/** 表单重置 */
|
||||
const reset = () => {
|
||||
if (mainFormRef.value) {
|
||||
mainFormRef.value.resetFields();
|
||||
}
|
||||
// 重置资料列表,保留一个空项
|
||||
form.documents = [
|
||||
{
|
||||
id: Date.now(),
|
||||
catalogueName: '',
|
||||
remark: ''
|
||||
}
|
||||
];
|
||||
leaveFormRef.value?.resetFields();
|
||||
};
|
||||
// 添加资料项
|
||||
const addDocumentItem = () => {
|
||||
form.documents.push({
|
||||
id: Date.now(),
|
||||
catalogueName: '',
|
||||
remark: ''
|
||||
});
|
||||
};
|
||||
|
||||
// 删除资料项
|
||||
const removeDocumentItem = (index: number) => {
|
||||
form.documents.splice(index, 1);
|
||||
};
|
||||
/** 提交按钮 */
|
||||
const submitForm = (status1: string) => {
|
||||
status.value = status1;
|
||||
buttonLoading.value = true;
|
||||
dialog.visible = false;
|
||||
// 验证表单数据
|
||||
// 验证表单数据(主要验证基本信息中的必填项)
|
||||
mainFormRef.value.validate(async (valid) => {
|
||||
if (valid) {
|
||||
console.log('验证成功');
|
||||
form.documents.map((item, i) => {
|
||||
item.num = i + 1;
|
||||
});
|
||||
let body = {
|
||||
desExtractBo: {
|
||||
projectId: currentProject.value?.id,
|
||||
userId: form.userId, // 收资人
|
||||
userMajor: form.user_major, // 专业
|
||||
id: form.id,
|
||||
phone: form.phone, // 电话
|
||||
email: form.email, // 邮箱
|
||||
userName: userMap.get(form.userId)
|
||||
},
|
||||
catalogueList: form.documents
|
||||
};
|
||||
let res = await extractBatch(body);
|
||||
if (res.code == 200) {
|
||||
buttonLoading.value = false;
|
||||
dialog.visible = false;
|
||||
} else {
|
||||
ElMessage.error(res.msg);
|
||||
}
|
||||
// 表单验证通过,执行提交逻辑
|
||||
form.id = res.data;
|
||||
submit(status.value, form);
|
||||
} else {
|
||||
// 表单验证失败,提示用户并关闭加载状态
|
||||
proxy?.$modal.msgError('请完善必填信息后再提交');
|
||||
buttonLoading.value = false;
|
||||
return false;
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
const submitFlow = async () => {
|
||||
handleStartWorkFlow(form);
|
||||
dialogVisible.visible = false;
|
||||
};
|
||||
//提交申请
|
||||
const handleStartWorkFlow = async (data: LeaveForm) => {
|
||||
try {
|
||||
submitFormData.value.flowCode = flowCode.value;
|
||||
submitFormData.value.businessId = data.id;
|
||||
//流程变量
|
||||
taskVariables.value = {
|
||||
// leave4/5 使用的流程变量
|
||||
userList: ['1', '3', '4']
|
||||
};
|
||||
submitFormData.value.variables = taskVariables.value;
|
||||
const resp = await startWorkFlow(submitFormData.value);
|
||||
if (submitVerifyRef.value) {
|
||||
buttonLoading.value = false;
|
||||
submitVerifyRef.value.openDialog(resp.data.taskId);
|
||||
}
|
||||
} finally {
|
||||
buttonLoading.value = false;
|
||||
}
|
||||
};
|
||||
//审批记录
|
||||
const handleApprovalRecord = () => {
|
||||
approvalRecordRef.value.init(form.id);
|
||||
};
|
||||
//提交回调
|
||||
const submitCallback = async () => {
|
||||
await proxy.$tab.closePage(proxy.$route);
|
||||
proxy.$router.go(-1);
|
||||
};
|
||||
//审批
|
||||
const approvalVerifyOpen = async () => {
|
||||
submitVerifyRef.value.openDialog(routeParams.value.taskId);
|
||||
};
|
||||
const submit = async (status, data) => {
|
||||
if (status === 'draft') {
|
||||
buttonLoading.value = false;
|
||||
proxy?.$modal.msgSuccess('暂存成功');
|
||||
proxy.$tab.closePage(proxy.$route);
|
||||
proxy.$router.go(-1);
|
||||
} else {
|
||||
if ((form.status === 'draft' && (flowCode.value === '' || flowCode.value === null)) || routeParams.value.type === 'add') {
|
||||
flowCode.value = flowCodeOptions[0].value;
|
||||
dialogVisible.visible = true;
|
||||
return;
|
||||
}
|
||||
//说明启动过先随意穿个参数
|
||||
if (flowCode.value === '' || flowCode.value === null) {
|
||||
flowCode.value = 'xx';
|
||||
}
|
||||
await handleStartWorkFlow(data);
|
||||
}
|
||||
};
|
||||
/** 查询当前部门的所有用户 */
|
||||
const getDeptAllUser = async (deptId: any) => {
|
||||
try {
|
||||
const res = await systemUserList({ deptId });
|
||||
// 实际项目中使用接口返回的数据
|
||||
userList.value = res.rows;
|
||||
userList.value.forEach((user) => {
|
||||
userMap.set(user.userId, user.nickName);
|
||||
});
|
||||
} catch (error) {
|
||||
ElMessage.error('获取用户列表失败');
|
||||
}
|
||||
};
|
||||
// 查询数据 再次回显
|
||||
const byProjectIdAll = async () => {
|
||||
loading.value = true;
|
||||
buttonLoading.value = false;
|
||||
// 调用接口获取数据
|
||||
const res = await extractDetail(routeParams.value.id);
|
||||
if (res.code === 200 && res.data) {
|
||||
const data = res.data;
|
||||
// 回显基本信息
|
||||
form.userId = data.userId || '';
|
||||
form.user_major = data.userMajor || '';
|
||||
form.phone = data.phone || '';
|
||||
form.email = data.email || '';
|
||||
form.id = data.id || '';
|
||||
form.status = data.status || '';
|
||||
if (data.status != 'draft') {
|
||||
disableAll.value = true;
|
||||
}
|
||||
|
||||
// 回显资料文件列表
|
||||
if (data.catalogueList && data.catalogueList.length > 0) {
|
||||
// 清空现有列表
|
||||
form.documents = [];
|
||||
// 填充新数据
|
||||
data.catalogueList.forEach((item: any, index: number) => {
|
||||
form.documents.push({
|
||||
id: item.id || Date.now() + index, // 确保id唯一
|
||||
catalogueName: item.catalogueName || '',
|
||||
remark: item.remark || ''
|
||||
});
|
||||
});
|
||||
} else {
|
||||
// 如果没有资料,保持一个空项
|
||||
form.documents = [
|
||||
{
|
||||
id: Date.now(),
|
||||
catalogueName: '',
|
||||
remark: ''
|
||||
}
|
||||
];
|
||||
}
|
||||
}
|
||||
loading.value = false;
|
||||
buttonLoading.value = false;
|
||||
};
|
||||
onMounted(() => {
|
||||
nextTick(async () => {
|
||||
routeParams.value = proxy.$route.query;
|
||||
reset();
|
||||
loading.value = false;
|
||||
if (routeParams.value.type === 'update' || routeParams.value.type === 'view' || routeParams.value.type === 'approval') {
|
||||
getDeptAllUser(userStore.deptId).then(() => {
|
||||
byProjectIdAll();
|
||||
});
|
||||
} else {
|
||||
getDeptAllUser(userStore.deptId);
|
||||
}
|
||||
});
|
||||
});
|
||||
</script>
|
||||
<style scoped lang="scss">
|
||||
/* 全局样式 */
|
||||
:root {
|
||||
--primary: #409eff;
|
||||
--primary-light: #66b1ff;
|
||||
--primary-dark: #3a8ee6;
|
||||
--success: #67c23a;
|
||||
--warning: #e6a23c;
|
||||
--danger: #f56c6c;
|
||||
--info: #909399;
|
||||
}
|
||||
|
||||
/* 表单样式优化 */
|
||||
.el-form-item {
|
||||
.el-form-item__label {
|
||||
color: #606266;
|
||||
font-weight: 500;
|
||||
}
|
||||
|
||||
.el-input__inner,
|
||||
.el-select .el-input__inner {
|
||||
border-radius: 4px;
|
||||
transition:
|
||||
border-color 0.2s,
|
||||
box-shadow 0.2s;
|
||||
|
||||
&:focus {
|
||||
border-color: var(--primary-light);
|
||||
box-shadow: 0 0 0 2px rgba(64, 158, 255, 0.1);
|
||||
}
|
||||
}
|
||||
|
||||
.el-textarea__inner {
|
||||
border-radius: 4px;
|
||||
transition:
|
||||
border-color 0.2s,
|
||||
box-shadow 0.2s;
|
||||
|
||||
&:focus {
|
||||
border-color: var(--primary-light);
|
||||
box-shadow: 0 0 0 2px rgba(64, 158, 255, 0.1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* 按钮样式优化 */
|
||||
.el-button {
|
||||
border-radius: 4px;
|
||||
transition: all 0.2s;
|
||||
|
||||
&.is-primary {
|
||||
background-color: var(--primary);
|
||||
border-color: var(--primary);
|
||||
|
||||
&:hover {
|
||||
background-color: var(--primary-light);
|
||||
border-color: var(--primary-light);
|
||||
}
|
||||
|
||||
&:active {
|
||||
background-color: var(--primary-dark);
|
||||
border-color: var(--primary-dark);
|
||||
}
|
||||
}
|
||||
|
||||
&.is-text {
|
||||
color: var(--primary);
|
||||
|
||||
&:hover {
|
||||
color: var(--primary-light);
|
||||
background-color: rgba(64, 158, 255, 0.05);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* 卡片样式优化 */
|
||||
.el-card {
|
||||
transition: all 0.3s ease;
|
||||
|
||||
&:hover {
|
||||
/* transform: translateY(-2px); */
|
||||
}
|
||||
}
|
||||
|
||||
/* 对话框样式优化 */
|
||||
.el-dialog {
|
||||
.el-dialog__header {
|
||||
background-color: #f5f7fa;
|
||||
border-bottom: 1px solid #ebeef5;
|
||||
padding: 15px 20px;
|
||||
}
|
||||
|
||||
.el-dialog__title {
|
||||
font-size: 16px;
|
||||
font-weight: 600;
|
||||
color: #303133;
|
||||
}
|
||||
|
||||
.el-dialog__footer {
|
||||
padding: 15px 20px;
|
||||
border-top: 1px solid #ebeef5;
|
||||
}
|
||||
}
|
||||
</style>
|
516
src/views/design/appointment/index.vue
Normal file
516
src/views/design/appointment/index.vue
Normal file
@ -0,0 +1,516 @@
|
||||
<template>
|
||||
<div class="p-6 bg-gray-50">
|
||||
<div class="appWidth mx-auto bg-white rounded-xl shadow-sm overflow-hidden transition-all duration-300 hover:shadow-md">
|
||||
<!-- 表单标题区域 -->
|
||||
<div class="bg-gradient-to-r from-blue-500 to-blue-600 text-white p-6">
|
||||
<h2 class="text-2xl font-bold flex items-center"><i class="el-icon-user-circle mr-3"></i>人员配置</h2>
|
||||
<p class="text-blue-100 mt-2 opacity-90">请配置项目相关负责人员信息</p>
|
||||
<!-- ,带 <span class="text-red-300">*</span> 为必填项 -->
|
||||
</div>
|
||||
|
||||
<!-- 表单内容区域 -->
|
||||
<el-form ref="leaveFormRef" :model="form" :rules="rules" label-width="120px" class="p-6 space-y-6">
|
||||
<!-- 设计负责人 -->
|
||||
<div class="fonts">
|
||||
<el-form-item label="设计负责人" prop="designLeader" class="mb-4">
|
||||
<el-select
|
||||
v-model="form.designLeader"
|
||||
placeholder="请选择设计负责人"
|
||||
class="w-full transition-all duration-300 border-gray-300 focus:border-blue-400 focus:ring-1 focus:ring-blue-400"
|
||||
>
|
||||
<el-option v-for="item in userList" :key="item.userId" :label="item.nickName" :value="item.userId" />
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
</div>
|
||||
|
||||
<!-- 设计人员 -->
|
||||
<div class="border border-gray-200 rounded-lg p-5 transition-all duration-300 hover:shadow-md bg-gray-50">
|
||||
<div class="flex justify-between items-center mb-5">
|
||||
<h3 class="text-lg font-semibold text-gray-700 flex items-center"><i class="el-icon-user mr-2 text-blue-500"></i>设计人员</h3>
|
||||
<el-button
|
||||
type="primary"
|
||||
size="small"
|
||||
@click="addPerson('designers')"
|
||||
class="transition-all duration-300 transform hover:scale-105 bg-blue-500 hover:bg-blue-600"
|
||||
>
|
||||
<i class="el-icon-plus mr-1"></i>新增设计人员
|
||||
</el-button>
|
||||
</div>
|
||||
|
||||
<div v-for="(designer, index) in form.designers" :key="index" class="flex items-center mb-4 animate-fadeIn">
|
||||
<el-form-item
|
||||
:prop="`designers.${index}.userId`"
|
||||
:rules="{ required: true, message: '请选择设计人员', trigger: 'change' }"
|
||||
class="flex-1 mr-3"
|
||||
>
|
||||
<div class="grid grid-cols-1 md:grid-cols-2 gap-4">
|
||||
<el-select
|
||||
v-model="designer.userMajor"
|
||||
placeholder="请选择专业"
|
||||
class="transition-all duration-300 border-gray-300"
|
||||
:rules="{ required: true, message: '请选择专业', trigger: 'change' }"
|
||||
>
|
||||
<el-option v-for="item in des_user_major" :key="item.value" :label="item.label" :value="item.value" />
|
||||
</el-select>
|
||||
<el-select v-model="designer.userId" placeholder="请选择设计人员" class="transition-all duration-300 border-gray-300">
|
||||
<el-option v-for="item in userList" :key="item.userId" :label="item.nickName" :value="item.userId" />
|
||||
</el-select>
|
||||
</div>
|
||||
</el-form-item>
|
||||
<el-button
|
||||
type="danger"
|
||||
size="small"
|
||||
@click="removePerson('designers', index)"
|
||||
class="transition-all duration-300 hover:bg-red-600"
|
||||
:disabled="form.designers.length <= 1"
|
||||
>
|
||||
<el-icon :size="16">
|
||||
<Delete />
|
||||
</el-icon>
|
||||
</el-button>
|
||||
</div>
|
||||
<div v-if="form.designers.length === 0" class="text-gray-500 text-center py-4 bg-gray-100 rounded-lg border border-dashed border-gray-200">
|
||||
暂无设计人员,请点击"新增设计人员"添加
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- 校审人员 -->
|
||||
<div class="border border-gray-200 rounded-lg p-5 transition-all duration-300 hover:shadow-md bg-gray-50">
|
||||
<div class="flex justify-between items-center mb-5">
|
||||
<h3 class="text-lg font-semibold text-gray-700 flex items-center"><i class="el-icon-check-circle mr-2 text-green-500"></i>校审人员</h3>
|
||||
<el-button
|
||||
type="primary"
|
||||
size="small"
|
||||
@click="addPerson('reviewers')"
|
||||
class="transition-all duration-300 transform hover:scale-105 bg-blue-500 hover:bg-blue-600"
|
||||
>
|
||||
<i class="el-icon-plus mr-1"></i>新增校审人员
|
||||
</el-button>
|
||||
</div>
|
||||
|
||||
<div v-for="(reviewer, index) in form.reviewers" :key="index" class="flex items-center mb-4 animate-fadeIn">
|
||||
<el-form-item
|
||||
:prop="`reviewers.${index}.userId`"
|
||||
:rules="{ required: true, message: '请选择校审人员', trigger: 'change' }"
|
||||
class="flex-1 mr-3"
|
||||
>
|
||||
<div class="grid grid-cols-1 md:grid-cols-2 gap-4">
|
||||
<el-select
|
||||
v-model="reviewer.userMajor"
|
||||
placeholder="请选择专业"
|
||||
class="transition-all duration-300 border-gray-300"
|
||||
:rules="{ required: true, message: '请选择专业', trigger: 'change' }"
|
||||
>
|
||||
<el-option v-for="item in des_user_major" :key="item.value" :label="item.label" :value="item.value" />
|
||||
</el-select>
|
||||
<el-select v-model="reviewer.userId" placeholder="请选择校审人员" class="transition-all duration-300 border-gray-300">
|
||||
<el-option v-for="item in userList" :key="item.userId" :label="item.nickName" :value="item.userId" />
|
||||
</el-select>
|
||||
</div>
|
||||
</el-form-item>
|
||||
<el-button
|
||||
type="danger"
|
||||
size="small"
|
||||
@click="removePerson('reviewers', index)"
|
||||
class="transition-all duration-300 hover:bg-red-600"
|
||||
:disabled="form.reviewers.length <= 1"
|
||||
>
|
||||
<el-icon :size="16">
|
||||
<Delete />
|
||||
</el-icon>
|
||||
</el-button>
|
||||
</div>
|
||||
|
||||
<div v-if="form.reviewers.length === 0" class="text-gray-500 text-center py-4 bg-gray-100 rounded-lg border border-dashed border-gray-200">
|
||||
暂无校审人员,请点击"新增校审人员"添加
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- 提交按钮区域 -->
|
||||
<div class="flex justify-center space-x-6 mt-8 pt-6 border-t border-gray-100">
|
||||
<el-button
|
||||
type="primary"
|
||||
size="large"
|
||||
@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>
|
||||
</div>
|
||||
</el-form>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup name="PersonnelForm" lang="ts">
|
||||
import { ref, reactive, computed, onMounted, toRefs } from 'vue';
|
||||
import { getCurrentInstance } from 'vue';
|
||||
import type { ComponentInternalInstance } from 'vue';
|
||||
import { useUserStoreHook } from '@/store/modules/user';
|
||||
import { listUserByDeptId } from '@/api/system/user';
|
||||
import { ElMessage, ElLoading } from 'element-plus';
|
||||
import { Delete } from '@element-plus/icons-vue';
|
||||
import { designUserAdd, designUserList, systemUserList } from '@/api/design/appointment';
|
||||
|
||||
// 获取当前实例
|
||||
const { proxy } = getCurrentInstance() as ComponentInternalInstance;
|
||||
// 获取用户 store
|
||||
const userStore = useUserStoreHook();
|
||||
// 从 store 中获取当前选中的项目
|
||||
const currentProject = computed(() => userStore.selectedProject);
|
||||
// 专业字典数据
|
||||
const { des_user_major } = toRefs<any>(proxy?.useDict('des_user_major'));
|
||||
|
||||
// 表单数据
|
||||
const form = reactive({
|
||||
projectId: currentProject.value?.id,
|
||||
designLeader: null, // 设计负责人
|
||||
// 设计人员列表(包含用户ID和专业)
|
||||
designers: [] as Array<{ userId: number | null; userMajor: string | null }>,
|
||||
// 校审人员列表(包含用户ID和专业)
|
||||
reviewers: [] as Array<{ userId: number | null; userMajor: string | null }>
|
||||
});
|
||||
|
||||
// 表单验证规则
|
||||
const rules = reactive({
|
||||
designLeader: [{ required: true, message: '请选择设计负责人', trigger: 'change' }]
|
||||
});
|
||||
|
||||
// 用户列表
|
||||
const userList = ref([]);
|
||||
|
||||
// 表单引用
|
||||
const leaveFormRef = ref();
|
||||
|
||||
/** 查询当前部门的所有用户 */
|
||||
const getDeptAllUser = async (deptId: any) => {
|
||||
try {
|
||||
const res = await systemUserList({ deptId });
|
||||
// 实际项目中使用接口返回的数据
|
||||
userList.value = res.rows;
|
||||
} catch (error) {
|
||||
ElMessage.error('获取用户列表失败');
|
||||
} finally {
|
||||
}
|
||||
};
|
||||
|
||||
/** 查询当前表单数据并回显 */
|
||||
const designUser = async () => {
|
||||
if (!currentProject.value?.id) return;
|
||||
|
||||
const loading = ElLoading.service({
|
||||
lock: true,
|
||||
text: '加载配置数据中...',
|
||||
background: 'rgba(255, 255, 255, 0.7)'
|
||||
});
|
||||
try {
|
||||
const res = await designUserList({ projectId: currentProject.value?.id });
|
||||
if (res.code == 200 && res.rows) {
|
||||
// 清空现有数据
|
||||
form.designLeader = null;
|
||||
form.designers = [];
|
||||
form.reviewers = [];
|
||||
// 处理返回的数据,进行回显
|
||||
res.rows.forEach((item: any) => {
|
||||
if (item.userType == 1) {
|
||||
item.userType = 'designLeader';
|
||||
} else if (item.userType == 2) {
|
||||
item.userType = 'designer';
|
||||
} else if (item.userType == 3) {
|
||||
item.userType = 'reviewer';
|
||||
}
|
||||
// 根据userType区分不同类型的人员
|
||||
switch (item.userType) {
|
||||
case 'designLeader':
|
||||
case 1:
|
||||
form.designLeader = item.userId;
|
||||
break;
|
||||
|
||||
case 'designer':
|
||||
case 2:
|
||||
form.designers.push({
|
||||
userId: item.userId,
|
||||
userMajor: item.userMajor || null
|
||||
});
|
||||
break;
|
||||
|
||||
case 'reviewer':
|
||||
case 3:
|
||||
form.reviewers.push({
|
||||
userId: item.userId,
|
||||
userMajor: item.userMajor || null
|
||||
});
|
||||
break;
|
||||
}
|
||||
});
|
||||
// 如果没有设计人员或校审人员,添加一个空项
|
||||
if (form.designers.length === 0) {
|
||||
form.designers.push({ userId: null, userMajor: null });
|
||||
}
|
||||
if (form.reviewers.length === 0) {
|
||||
form.reviewers.push({ userId: null, userMajor: null });
|
||||
}
|
||||
} else {
|
||||
// 添加默认空项
|
||||
form.designers.push({ userId: null, userMajor: null });
|
||||
form.reviewers.push({ userId: null, userMajor: null });
|
||||
}
|
||||
} catch (error) {
|
||||
ElMessage.error('获取配置数据失败');
|
||||
// 添加默认空项
|
||||
form.designers.push({ userId: null, userMajor: null });
|
||||
form.reviewers.push({ userId: null, userMajor: null });
|
||||
} finally {
|
||||
loading.close();
|
||||
}
|
||||
};
|
||||
|
||||
/** 添加人员 */
|
||||
const addPerson = (type: 'designers' | 'reviewers') => {
|
||||
form[type].push({ userId: null, userMajor: null });
|
||||
// 滚动到最后一个新增的元素
|
||||
setTimeout(() => {
|
||||
const elements = document.querySelectorAll(`[data-v-${proxy?.$options.__scopeId}] .el-select`);
|
||||
if (elements.length > 0) {
|
||||
elements[elements.length - 1].scrollIntoView({ behavior: 'smooth', block: 'nearest' });
|
||||
}
|
||||
}, 100);
|
||||
};
|
||||
|
||||
/** 移除人员 */
|
||||
const removePerson = (type: 'designers' | 'reviewers', index: number) => {
|
||||
if (form[type].length <= 1) {
|
||||
ElMessage.warning('至少保留一个人员');
|
||||
return;
|
||||
}
|
||||
form[type].splice(index, 1);
|
||||
};
|
||||
|
||||
/** 提交表单 */
|
||||
const submitForm = async () => {
|
||||
if (!leaveFormRef.value) return;
|
||||
|
||||
try {
|
||||
// 表单验证
|
||||
await leaveFormRef.value.validate();
|
||||
// 构建提交数据 - 所有人员信息放在一个数组中
|
||||
const submitData = {
|
||||
projectId: form.projectId,
|
||||
personnel: [
|
||||
// 设计负责人
|
||||
{
|
||||
userId: form.designLeader,
|
||||
userType: 'designLeader', // 设计负责人类型标识
|
||||
userMajor: null // 负责人不需要专业
|
||||
},
|
||||
// 设计人员
|
||||
...form.designers.map((designer) => ({
|
||||
userId: designer.userId,
|
||||
userType: 'designer', // 设计人员类型标识
|
||||
userMajor: designer.userMajor // 包含专业信息
|
||||
})),
|
||||
// 校审人员
|
||||
...form.reviewers.map((reviewer) => ({
|
||||
userId: reviewer.userId,
|
||||
userType: 'reviewer', // 校审人员类型标识
|
||||
userMajor: reviewer.userMajor // 包含专业信息
|
||||
}))
|
||||
]
|
||||
};
|
||||
|
||||
// 数据处理
|
||||
const arr = [];
|
||||
userList.value.forEach((item) => {
|
||||
submitData.personnel.forEach((item1) => {
|
||||
if (item1.userId === item.userId) {
|
||||
let userType = 1; // 默认为设计负责人
|
||||
if (item1.userType === 'designer') {
|
||||
userType = 2; // 设计人员
|
||||
} else if (item1.userType === 'reviewer') {
|
||||
userType = 3; // 校审人员
|
||||
}
|
||||
arr.push({
|
||||
userName: item.nickName,
|
||||
projectId: submitData.projectId,
|
||||
userId: item1.userId,
|
||||
userType: userType,
|
||||
userMajor: item1.userMajor
|
||||
});
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
// 提交到后端
|
||||
const res = await designUserAdd({
|
||||
list: arr,
|
||||
projectId: currentProject.value?.id
|
||||
});
|
||||
if (res.code === 200) {
|
||||
ElMessage.success('提交成功');
|
||||
} else {
|
||||
ElMessage.error(res.msg || '提交失败');
|
||||
}
|
||||
} catch (error) {
|
||||
ElMessage.error('请完善表单信息后再提交');
|
||||
} finally {
|
||||
// 关闭加载状态
|
||||
ElLoading.service().close();
|
||||
}
|
||||
};
|
||||
|
||||
/** 重置表单 */
|
||||
const resetForm = () => {
|
||||
if (leaveFormRef.value) {
|
||||
leaveFormRef.value.resetFields();
|
||||
form.designers = [{ userId: null, userMajor: null }];
|
||||
form.reviewers = [{ userId: null, userMajor: null }];
|
||||
ElMessage.info('表单已重置');
|
||||
}
|
||||
};
|
||||
|
||||
// 页面挂载时初始化数据
|
||||
onMounted(() => {
|
||||
console.log(userStore.deptId);
|
||||
// 先获取用户列表,再加载表单数据
|
||||
getDeptAllUser(userStore.deptId).then(() => {
|
||||
designUser();
|
||||
});
|
||||
});
|
||||
</script>
|
||||
|
||||
<style lang="scss">
|
||||
.appWidth {
|
||||
width: 50vw;
|
||||
max-width: 1200px;
|
||||
.el-select__wrapper {
|
||||
width: 16vw !important;
|
||||
}
|
||||
.el-button--small {
|
||||
margin-bottom: 10px;
|
||||
}
|
||||
.fonts {
|
||||
.el-form-item--default .el-form-item__label {
|
||||
font-size: 18px !important;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 自定义动画
|
||||
@keyframes fadeIn {
|
||||
from {
|
||||
opacity: 0;
|
||||
transform: translateY(10px);
|
||||
}
|
||||
to {
|
||||
opacity: 1;
|
||||
transform: translateY(0);
|
||||
}
|
||||
}
|
||||
|
||||
.animate-fadeIn {
|
||||
animation: fadeIn 0.3s ease-out forwards;
|
||||
}
|
||||
|
||||
// 表单样式优化
|
||||
::v-deep .el-form {
|
||||
--el-form-item-margin-bottom: 0;
|
||||
}
|
||||
|
||||
::v-deep .el-form-item {
|
||||
margin-bottom: 0;
|
||||
|
||||
&__label {
|
||||
font-weight: 500;
|
||||
color: #4e5969;
|
||||
padding: 0 0 8px 0;
|
||||
}
|
||||
|
||||
&__content {
|
||||
padding: 0;
|
||||
}
|
||||
}
|
||||
|
||||
::v-deep .el-select {
|
||||
width: 100%;
|
||||
|
||||
.el-input__inner {
|
||||
border-radius: 6px;
|
||||
transition: all 0.3s ease;
|
||||
}
|
||||
|
||||
&:hover .el-input__inner {
|
||||
border-color: #66b1ff;
|
||||
}
|
||||
|
||||
&.el-select-focus .el-input__inner {
|
||||
border-color: #409eff;
|
||||
box-shadow: 0 0 0 2px rgba(64, 158, 255, 0.2);
|
||||
}
|
||||
}
|
||||
|
||||
::v-deep .el-button {
|
||||
border-radius: 6px;
|
||||
padding: 8px 16px;
|
||||
|
||||
&--primary {
|
||||
background-color: #409eff;
|
||||
border-color: #409eff;
|
||||
|
||||
&:hover {
|
||||
background-color: #66b1ff;
|
||||
border-color: #66b1ff;
|
||||
}
|
||||
}
|
||||
|
||||
&--danger {
|
||||
background-color: #f56c6c;
|
||||
border-color: #f56c6c;
|
||||
|
||||
&:hover {
|
||||
background-color: #f78989;
|
||||
border-color: #f78989;
|
||||
}
|
||||
|
||||
&:disabled {
|
||||
background-color: #ffcccc;
|
||||
border-color: #ffbbbb;
|
||||
cursor: not-allowed;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 响应式网格布局
|
||||
.grid {
|
||||
display: grid;
|
||||
}
|
||||
|
||||
.grid-cols-1 {
|
||||
grid-template-columns: repeat(1, minmax(0, 1fr));
|
||||
}
|
||||
|
||||
.md\:grid-cols-2 {
|
||||
grid-template-columns: repeat(2, minmax(0, 1fr));
|
||||
}
|
||||
|
||||
.gap-4 {
|
||||
gap: 1rem;
|
||||
}
|
||||
|
||||
// 适配小屏幕
|
||||
@media (max-width: 768px) {
|
||||
.appWidth {
|
||||
width: 95vw;
|
||||
}
|
||||
|
||||
::v-deep .el-form {
|
||||
padding: 4px;
|
||||
}
|
||||
|
||||
::v-deep .el-form-item__label {
|
||||
width: 100px;
|
||||
}
|
||||
}
|
||||
</style>
|
159
src/views/design/condition/comm/filePage.vue
Normal file
159
src/views/design/condition/comm/filePage.vue
Normal file
@ -0,0 +1,159 @@
|
||||
<template>
|
||||
<div>
|
||||
<el-card shadow="never">
|
||||
<template #header>
|
||||
<el-row :gutter="10" class="mb8">
|
||||
<el-col :span="1.5">
|
||||
<div class="box_btn">
|
||||
<file-upload :limit="1" :uploadUrl="uploadUrl" :params="uploadParams" :on-upload-success="uploadFile" :fileType="[]">
|
||||
<el-button type="primary" style="float: left">
|
||||
<el-icon size="small"><Upload /></el-icon>上传文件
|
||||
</el-button>
|
||||
</file-upload>
|
||||
</div>
|
||||
</el-col>
|
||||
<right-toolbar @queryTable="getList"></right-toolbar>
|
||||
</el-row>
|
||||
</template>
|
||||
<el-table :data="FileList" style="width: 100%" height="64vh">
|
||||
<el-table-column type="index" align="center" label="序号" width="180" />
|
||||
<el-table-column prop="fileName" align="center" label="文件名称" />
|
||||
<el-table-column label="流程状态" align="center" prop="status">
|
||||
<template #default="scope">
|
||||
<dict-tag :options="wf_business_status" :value="scope.row.status" />
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="操作">
|
||||
<template #default="scope">
|
||||
<el-button type="primary" icon="Download" @click="onExport(scope.row.fileUrl)">下载</el-button>
|
||||
<el-button type="success" icon="Plus" v-show="scope.row.status == 'draft' || scope.row.status == 'waiting'" @click="onUpdate(scope.row)"
|
||||
>审核</el-button
|
||||
>
|
||||
<el-button type="warning" v-show="scope.row.status != 'draft'" icon="View" @click="onView(scope.row)">查看流程</el-button>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
<pagination v-show="total > 0" :total="total" v-model:page="queryParams.pageNum" v-model:limit="queryParams.pageSize" @pagination="getList" />
|
||||
</el-card>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup name="DataCollectionForm" lang="ts">
|
||||
import { ref, reactive, computed, onMounted } from 'vue';
|
||||
import { useUserStoreHook } from '@/store/modules/user';
|
||||
import { collectFileList } from '@/api/design/condition';
|
||||
const { proxy } = getCurrentInstance() as any;
|
||||
const { wf_business_status } = toRefs<any>(proxy?.useDict('wf_business_status'));
|
||||
// 获取用户 store
|
||||
const userStore = useUserStoreHook();
|
||||
// 从 store 中获取当前选中的项目
|
||||
const currentProject = computed(() => userStore.selectedProject);
|
||||
const uploadUrl = computed(() => {
|
||||
return `/design/collectFile/upload`;
|
||||
});
|
||||
// 父组件传递的参数接受
|
||||
const props = defineProps({
|
||||
catalogueId: {
|
||||
type: Number
|
||||
}
|
||||
});
|
||||
const uploadParams = computed(() => {
|
||||
return {
|
||||
catalogueId: props.catalogueId,
|
||||
projectId: currentProject.value.id
|
||||
};
|
||||
});
|
||||
|
||||
const total = ref(0);
|
||||
const data = reactive({
|
||||
queryParams: {
|
||||
pageNum: 1,
|
||||
pageSize: 10,
|
||||
projectId: currentProject.value?.id,
|
||||
formNo: undefined,
|
||||
projectName: undefined,
|
||||
submitUnit: undefined,
|
||||
specialty: undefined,
|
||||
submitDate: undefined,
|
||||
volumeName: undefined,
|
||||
volumeNo: undefined,
|
||||
changeReason: undefined,
|
||||
status: undefined,
|
||||
params: {},
|
||||
catalogueId: props.catalogueId
|
||||
}
|
||||
});
|
||||
const { queryParams } = toRefs(data);
|
||||
const FileList = ref([]);
|
||||
// 查询收资清单目录列表
|
||||
const getList = async () => {
|
||||
let res = await collectFileList(queryParams.value);
|
||||
if (res.code == 200) {
|
||||
FileList.value = res.rows;
|
||||
total.value = res.total;
|
||||
}
|
||||
};
|
||||
// 上传文件
|
||||
const uploadFile = (files) => {
|
||||
proxy.$modal.success('上传成功');
|
||||
console.log(files);
|
||||
getList();
|
||||
};
|
||||
const onUpdate = (row) => {
|
||||
// 审核
|
||||
proxy.$tab.closePage(proxy.$route);
|
||||
proxy.$router.push({
|
||||
path: `/design-management/condition/indexEdit`,
|
||||
query: {
|
||||
id: row.id,
|
||||
type: 'update'
|
||||
}
|
||||
});
|
||||
};
|
||||
const onView = (row) => {
|
||||
// 查看流程
|
||||
proxy.$tab.closePage(proxy.$route);
|
||||
proxy.$router.push({
|
||||
path: `/design-management/condition/indexEdit`,
|
||||
query: {
|
||||
id: row.id,
|
||||
type: 'view'
|
||||
}
|
||||
});
|
||||
};
|
||||
const onExport = (fileUrl) => {
|
||||
if (!fileUrl) {
|
||||
proxy.$modal.error('文件地址不存在,无法下载');
|
||||
return;
|
||||
}
|
||||
try {
|
||||
// 创建一个隐藏的a标签
|
||||
const link = document.createElement('a');
|
||||
// 设置下载地址
|
||||
link.href = fileUrl;
|
||||
// 从URL中提取文件名作为下载文件名
|
||||
const fileName = fileUrl.split('/').pop();
|
||||
link.download = fileName || 'download file';
|
||||
// 触发点击事件
|
||||
link.click();
|
||||
// 下载后移除a标签
|
||||
document.body.removeChild(link);
|
||||
// 显示下载成功提示
|
||||
proxy.$modal.success('文件开始下载');
|
||||
} catch (error) {
|
||||
// proxy.$modal.error('下载失败,请稍后重试');
|
||||
}
|
||||
};
|
||||
// 页面挂载时初始化数据
|
||||
onMounted(() => {
|
||||
getList();
|
||||
});
|
||||
</script>
|
||||
|
||||
<style lang="scss">
|
||||
.condition {
|
||||
.el-tabs__header {
|
||||
height: 84vh !important;
|
||||
}
|
||||
}
|
||||
</style>
|
50
src/views/design/condition/index.vue
Normal file
50
src/views/design/condition/index.vue
Normal file
@ -0,0 +1,50 @@
|
||||
<template>
|
||||
<div class="p-6 bg-gray-50 condition">
|
||||
<el-tabs v-model="activeName" type="border-card" :tab-position="tabPosition" class="demo-tabs" @tab-click="handleClick">
|
||||
<el-tab-pane :label="item.catalogueName" :name="item.id" v-for="(item, i) of FolderList" :key="i">
|
||||
<div style="height: 80vh; background: #f0f8ff9e">
|
||||
<filePage :catalogueId="item.id"></filePage>
|
||||
</div>
|
||||
</el-tab-pane>
|
||||
</el-tabs>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup name="DataCollectionForm" lang="ts">
|
||||
import { ref, reactive, computed, onMounted } from 'vue';
|
||||
import { useUserStoreHook } from '@/store/modules/user';
|
||||
import type { TabsPaneContext, TabsInstance } from 'element-plus';
|
||||
import { collectCatalogueList } from '@/api/design/condition';
|
||||
import filePage from './comm/filePage.vue';
|
||||
const tabPosition = ref<TabsInstance['tabPosition']>('left');
|
||||
const activeName = ref('');
|
||||
// 获取用户 store
|
||||
const userStore = useUserStoreHook();
|
||||
// 从 store 中获取当前选中的项目
|
||||
const currentProject = computed(() => userStore.selectedProject);
|
||||
const FolderList = ref([]);
|
||||
const handleClick = (tab: TabsPaneContext, event: Event) => {
|
||||
console.log(tab, event);
|
||||
};
|
||||
// 查询收资清单目录列表
|
||||
const getList = async () => {
|
||||
let res = await collectCatalogueList({ projectId: currentProject.value?.id });
|
||||
if (res.code == 200) {
|
||||
FolderList.value = res.rows;
|
||||
activeName.value = res.rows[0].id; //默认第一个
|
||||
}
|
||||
};
|
||||
|
||||
// 页面挂载时初始化数据
|
||||
onMounted(() => {
|
||||
getList();
|
||||
});
|
||||
</script>
|
||||
|
||||
<style lang="scss">
|
||||
.condition {
|
||||
.el-tabs__header {
|
||||
height: 84vh !important;
|
||||
}
|
||||
}
|
||||
</style>
|
353
src/views/design/condition/indexEdit.vue
Normal file
353
src/views/design/condition/indexEdit.vue
Normal file
@ -0,0 +1,353 @@
|
||||
<template>
|
||||
<div class="p-4 bg-gray-50">
|
||||
<div class="max-w-4xl mx-auto">
|
||||
<!-- 顶部按钮区域 -->
|
||||
<el-card class="mb-4 rounded-lg shadow-sm bg-white border border-gray-100 transition-all hover:shadow-md">
|
||||
<approvalButton
|
||||
@submitForm="submitForm"
|
||||
@approvalVerifyOpen="approvalVerifyOpen"
|
||||
@handleApprovalRecord="handleApprovalRecord"
|
||||
:buttonLoading="buttonLoading"
|
||||
:id="form.id"
|
||||
:status="form.status"
|
||||
:pageType="routeParams.type"
|
||||
/>
|
||||
</el-card>
|
||||
<!-- 表单区域 -->
|
||||
<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>
|
||||
</div>
|
||||
<div class="p-6">
|
||||
<el-form
|
||||
ref="leaveFormRef"
|
||||
v-loading="loading"
|
||||
:disabled="routeParams.type === 'view'"
|
||||
:model="form"
|
||||
:rules="rules"
|
||||
label-width="100px"
|
||||
class="space-y-4"
|
||||
>
|
||||
<div class="grid grid-cols-1 gap-4">
|
||||
<el-row>
|
||||
<el-col :span="12">
|
||||
<el-form-item label="文件名称" prop="formNo">
|
||||
<el-input disabled v-model="form.fileName" placeholder="请输入文件名称" />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="24">
|
||||
<el-form-item label="文件" prop="formNo">
|
||||
<div style="display: flex">
|
||||
<span style="color: rgb(50, 142, 248)" @click="onOpen">点击打开</span>
|
||||
</div>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
</el-row>
|
||||
</div>
|
||||
</el-form>
|
||||
</div>
|
||||
</el-card>
|
||||
<!-- 提交组件 -->
|
||||
<submitVerify ref="submitVerifyRef" :task-variables="taskVariables" @submit-callback="submitCallback" />
|
||||
<approvalRecord ref="approvalRecordRef"></approvalRecord>
|
||||
<!-- 流程选择对话框 -->
|
||||
<el-dialog
|
||||
draggable
|
||||
v-model="dialogVisible.visible"
|
||||
:title="dialogVisible.title"
|
||||
:before-close="handleClose"
|
||||
width="500"
|
||||
class="rounded-lg shadow-lg"
|
||||
>
|
||||
<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-select>
|
||||
</div>
|
||||
<template #footer>
|
||||
<div class="dialog-footer p-4 border-t border-gray-100 flex justify-end space-x-3">
|
||||
<el-button @click="handleClose" class="px-4 py-2 border border-gray-300 rounded-md text-gray-700 hover:bg-gray-50 transition-colors"
|
||||
>取消</el-button
|
||||
>
|
||||
<el-button type="primary" @click="submitFlow()" class="px-4 py-2 bg-primary text-white rounded-md hover:bg-primary/90 transition-colors"
|
||||
>确认</el-button
|
||||
>
|
||||
</div>
|
||||
</template>
|
||||
</el-dialog>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup name="Leave" lang="ts">
|
||||
import { LeaveForm, LeaveQuery, LeaveVO } from '@/api/workflow/leave/types';
|
||||
import { startWorkFlow } from '@/api/workflow/task';
|
||||
import SubmitVerify from '@/components/Process/submitVerify.vue';
|
||||
import ApprovalRecord from '@/components/Process/approvalRecord.vue';
|
||||
import ApprovalButton from '@/components/Process/approvalButton.vue';
|
||||
import { StartProcessBo } from '@/api/workflow/workflowCommon/types';
|
||||
const { proxy } = getCurrentInstance() as ComponentInternalInstance;
|
||||
import { useUserStoreHook } from '@/store/modules/user';
|
||||
const { design_change_reason_type } = toRefs<any>(proxy?.useDict('design_change_reason_type'));
|
||||
import { getKnowledgeDocument } from '@/api/design/technicalStandard';
|
||||
import { getCollectFile } from '@/api/design/condition';
|
||||
// 获取用户 store
|
||||
const userStore = useUserStoreHook();
|
||||
// 从 store 中获取项目列表和当前选中的项目
|
||||
const currentProject = computed(() => userStore.selectedProject);
|
||||
const buttonLoading = ref(false);
|
||||
const loading = ref(true);
|
||||
//路由参数
|
||||
const routeParams = ref<Record<string, any>>({});
|
||||
const flowCode = ref<string>('');
|
||||
const status = ref<string>('');
|
||||
const dialogVisible = reactive<DialogOption>({
|
||||
visible: false,
|
||||
title: '流程定义'
|
||||
});
|
||||
//提交组件
|
||||
const submitVerifyRef = ref<InstanceType<typeof SubmitVerify>>();
|
||||
//审批记录组件
|
||||
const approvalRecordRef = ref<InstanceType<typeof ApprovalRecord>>();
|
||||
//按钮组件
|
||||
const flowCodeOptions = [
|
||||
{
|
||||
value: currentProject.value?.id + '_collectFile',
|
||||
label: '设计输入文件'
|
||||
}
|
||||
];
|
||||
|
||||
const leaveFormRef = ref<ElFormInstance>();
|
||||
const dialog = reactive({
|
||||
visible: false,
|
||||
title: '',
|
||||
isEdit: false
|
||||
});
|
||||
const submitFormData = ref<StartProcessBo>({
|
||||
businessId: '',
|
||||
flowCode: '',
|
||||
variables: {}
|
||||
});
|
||||
const taskVariables = ref<Record<string, any>>({});
|
||||
|
||||
const initFormData = {
|
||||
id: undefined,
|
||||
fileName: undefined,
|
||||
fileUrl: undefined,
|
||||
status: undefined,
|
||||
originalName: undefined
|
||||
};
|
||||
const data = reactive({
|
||||
form: { ...initFormData },
|
||||
rules: {}
|
||||
});
|
||||
const onOpen = () => {
|
||||
window.open(form.value.fileUrl, '_blank');
|
||||
};
|
||||
const handleClose = () => {
|
||||
dialogVisible.visible = false;
|
||||
flowCode.value = '';
|
||||
buttonLoading.value = false;
|
||||
};
|
||||
const { form, rules } = toRefs(data);
|
||||
|
||||
/** 表单重置 */
|
||||
const reset = () => {
|
||||
form.value = { ...initFormData };
|
||||
leaveFormRef.value?.resetFields();
|
||||
};
|
||||
|
||||
/** 获取详情 */
|
||||
const getInfo = () => {
|
||||
loading.value = true;
|
||||
buttonLoading.value = false;
|
||||
nextTick(async () => {
|
||||
const res = await getCollectFile(routeParams.value.id);
|
||||
Object.assign(form.value, res.data);
|
||||
loading.value = false;
|
||||
buttonLoading.value = false;
|
||||
});
|
||||
};
|
||||
|
||||
/** 提交按钮 */
|
||||
const submitForm = (status1: string) => {
|
||||
status.value = status1;
|
||||
submit(status.value, form.value);
|
||||
};
|
||||
|
||||
const submitFlow = async () => {
|
||||
handleStartWorkFlow(form.value);
|
||||
dialogVisible.visible = false;
|
||||
};
|
||||
//提交申请
|
||||
const handleStartWorkFlow = async (data: LeaveForm) => {
|
||||
try {
|
||||
submitFormData.value.flowCode = flowCode.value;
|
||||
submitFormData.value.businessId = data.id;
|
||||
//流程变量
|
||||
taskVariables.value = {
|
||||
// leave4/5 使用的流程变量
|
||||
userList: ['1', '3', '4']
|
||||
};
|
||||
submitFormData.value.variables = taskVariables.value;
|
||||
const resp = await startWorkFlow(submitFormData.value);
|
||||
if (submitVerifyRef.value) {
|
||||
buttonLoading.value = false;
|
||||
submitVerifyRef.value.openDialog(resp.data.taskId);
|
||||
}
|
||||
} finally {
|
||||
buttonLoading.value = false;
|
||||
}
|
||||
};
|
||||
//审批记录
|
||||
const handleApprovalRecord = () => {
|
||||
approvalRecordRef.value.init(form.value.id);
|
||||
};
|
||||
//提交回调
|
||||
const submitCallback = async () => {
|
||||
await proxy.$tab.closePage(proxy.$route);
|
||||
proxy.$router.go(-1);
|
||||
};
|
||||
//审批
|
||||
const approvalVerifyOpen = async () => {
|
||||
submitVerifyRef.value.openDialog(routeParams.value.taskId);
|
||||
};
|
||||
// 图纸上传成功之后 开始提交
|
||||
const submit = async (status, data) => {
|
||||
form.value = data;
|
||||
if (status === 'draft') {
|
||||
buttonLoading.value = false;
|
||||
proxy?.$modal.msgSuccess('暂存成功');
|
||||
proxy.$tab.closePage(proxy.$route);
|
||||
proxy.$router.go(-1);
|
||||
} else {
|
||||
if ((form.value.status === 'draft' && (flowCode.value === '' || flowCode.value === null)) || routeParams.value.type === 'add') {
|
||||
flowCode.value = flowCodeOptions[0].value;
|
||||
dialogVisible.visible = true;
|
||||
return;
|
||||
}
|
||||
//说明启动过先随意穿个参数
|
||||
if (flowCode.value === '' || flowCode.value === null) {
|
||||
flowCode.value = 'xx';
|
||||
}
|
||||
await handleStartWorkFlow(data);
|
||||
}
|
||||
};
|
||||
|
||||
onMounted(() => {
|
||||
nextTick(async () => {
|
||||
routeParams.value = proxy.$route.query;
|
||||
reset();
|
||||
loading.value = false;
|
||||
console.log(routeParams.value.type);
|
||||
if (routeParams.value.type === 'update' || routeParams.value.type === 'view' || routeParams.value.type === 'approval') {
|
||||
getInfo();
|
||||
}
|
||||
});
|
||||
});
|
||||
</script>
|
||||
<style scoped lang="scss">
|
||||
/* 全局样式 */
|
||||
:root {
|
||||
--primary: #409eff;
|
||||
--primary-light: #66b1ff;
|
||||
--primary-dark: #3a8ee6;
|
||||
--success: #67c23a;
|
||||
--warning: #e6a23c;
|
||||
--danger: #f56c6c;
|
||||
--info: #909399;
|
||||
}
|
||||
|
||||
/* 表单样式优化 */
|
||||
.el-form-item {
|
||||
.el-form-item__label {
|
||||
color: #606266;
|
||||
font-weight: 500;
|
||||
}
|
||||
|
||||
.el-input__inner,
|
||||
.el-select .el-input__inner {
|
||||
border-radius: 4px;
|
||||
transition:
|
||||
border-color 0.2s,
|
||||
box-shadow 0.2s;
|
||||
|
||||
&:focus {
|
||||
border-color: var(--primary-light);
|
||||
box-shadow: 0 0 0 2px rgba(64, 158, 255, 0.1);
|
||||
}
|
||||
}
|
||||
|
||||
.el-textarea__inner {
|
||||
border-radius: 4px;
|
||||
transition:
|
||||
border-color 0.2s,
|
||||
box-shadow 0.2s;
|
||||
|
||||
&:focus {
|
||||
border-color: var(--primary-light);
|
||||
box-shadow: 0 0 0 2px rgba(64, 158, 255, 0.1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* 按钮样式优化 */
|
||||
.el-button {
|
||||
border-radius: 4px;
|
||||
transition: all 0.2s;
|
||||
|
||||
&.is-primary {
|
||||
background-color: var(--primary);
|
||||
border-color: var(--primary);
|
||||
|
||||
&:hover {
|
||||
background-color: var(--primary-light);
|
||||
border-color: var(--primary-light);
|
||||
}
|
||||
|
||||
&:active {
|
||||
background-color: var(--primary-dark);
|
||||
border-color: var(--primary-dark);
|
||||
}
|
||||
}
|
||||
|
||||
&.is-text {
|
||||
color: var(--primary);
|
||||
|
||||
&:hover {
|
||||
color: var(--primary-light);
|
||||
background-color: rgba(64, 158, 255, 0.05);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* 卡片样式优化 */
|
||||
.el-card {
|
||||
transition: all 0.3s ease;
|
||||
|
||||
&:hover {
|
||||
/* transform: translateY(-2px); */
|
||||
}
|
||||
}
|
||||
|
||||
/* 对话框样式优化 */
|
||||
.el-dialog {
|
||||
.el-dialog__header {
|
||||
background-color: #f5f7fa;
|
||||
border-bottom: 1px solid #ebeef5;
|
||||
padding: 15px 20px;
|
||||
}
|
||||
|
||||
.el-dialog__title {
|
||||
font-size: 16px;
|
||||
font-weight: 600;
|
||||
color: #303133;
|
||||
}
|
||||
|
||||
.el-dialog__footer {
|
||||
padding: 15px 20px;
|
||||
border-top: 1px solid #ebeef5;
|
||||
}
|
||||
}
|
||||
</style>
|
@ -149,7 +149,7 @@ const flowCodeOptions = [
|
||||
{
|
||||
value: currentProject.value?.id + '_designchanged',
|
||||
label: '设计变更审批'
|
||||
},
|
||||
}
|
||||
];
|
||||
|
||||
const flowCode = ref<string>('');
|
||||
@ -234,7 +234,7 @@ const getInfo = () => {
|
||||
nextTick(async () => {
|
||||
const res = await getDesignChange(routeParams.value.id);
|
||||
Object.assign(form.value, res.data);
|
||||
if(form.value.changeReason.length >0){
|
||||
if (form.value.changeReason.length > 0) {
|
||||
form.value.changeReason = form.value.changeReason.split(',');
|
||||
}
|
||||
loading.value = false;
|
||||
@ -245,8 +245,8 @@ const getInfo = () => {
|
||||
/** 提交按钮 */
|
||||
const submitForm = (status1: string) => {
|
||||
status.value = status1;
|
||||
var changeReason=''
|
||||
if(form.value.changeReason.length >0){
|
||||
var changeReason = '';
|
||||
if (form.value.changeReason.length > 0) {
|
||||
changeReason = form.value.changeReason.join(',');
|
||||
}
|
||||
leaveFormRef.value?.validate(async (valid: boolean) => {
|
||||
@ -254,9 +254,9 @@ const submitForm = (status1: string) => {
|
||||
buttonLoading.value = true;
|
||||
var res;
|
||||
if (form.value.id) {
|
||||
res = await updateDesignChange({...form.value,changeReason}).finally(() => (buttonLoading.value = false));
|
||||
res = await updateDesignChange({ ...form.value, changeReason }).finally(() => (buttonLoading.value = false));
|
||||
} else {
|
||||
res = await addDesignChange({...form.value,changeReason}).finally(() => (buttonLoading.value = false));
|
||||
res = await addDesignChange({ ...form.value, changeReason }).finally(() => (buttonLoading.value = false));
|
||||
}
|
||||
if (res.code == 200) {
|
||||
dialog.visible = false;
|
||||
|
@ -32,9 +32,7 @@
|
||||
<template #default="scope">
|
||||
<el-row :gutter="10" class="mb8">
|
||||
<el-col :span="1.5" v-if="scope.row.status === 'draft' || scope.row.status === 'cancel' || scope.row.status === 'back'">
|
||||
<el-button v-hasPermi="['design:drawing:edit']" size="small" type="primary" icon="Edit" @click="handleUpdate(scope.row)"
|
||||
>修改</el-button
|
||||
>
|
||||
<el-button v-hasPermi="['design:drawing:edit']" size="small" type="primary" icon="Edit" @click="handleUpdate(scope.row)">修改</el-button>
|
||||
</el-col>
|
||||
<el-col :span="1.5" v-if="scope.row.status === 'draft' || scope.row.status === 'cancel' || scope.row.status === 'back'">
|
||||
<el-button v-hasPermi="['design:drawing:remove']" size="small" type="primary" icon="Delete" @click="handleDelete(scope.row)"
|
||||
@ -44,9 +42,7 @@
|
||||
</el-row>
|
||||
<el-row :gutter="10" class="mb8">
|
||||
<el-col :span="1.5">
|
||||
<el-button type="primary" size="small" icon="View" v-if="scope.row.status != 'draft'" @click="handleViewInfo(scope.row)"
|
||||
>查看</el-button
|
||||
>
|
||||
<el-button type="primary" size="small" icon="View" v-if="scope.row.status != 'draft'" @click="handleViewInfo(scope.row)">查看</el-button>
|
||||
</el-col>
|
||||
<el-col :span="1.5" v-if="scope.row.status === 'waiting'">
|
||||
<el-button size="small" type="primary" icon="Notification" @click="handleCancelProcessApply(scope.row.id)">撤销</el-button>
|
||||
@ -55,12 +51,12 @@
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
</template>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { ref, defineProps, defineEmits } from 'vue';
|
||||
<script setup lang="ts">
|
||||
import { ref, defineProps, defineEmits } from 'vue';
|
||||
|
||||
const props = defineProps({
|
||||
const props = defineProps({
|
||||
drawingList: {
|
||||
type: Array,
|
||||
required: true
|
||||
@ -77,38 +73,31 @@
|
||||
type: Array,
|
||||
required: true
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
const emits = defineEmits([
|
||||
'selection-change',
|
||||
'view',
|
||||
'update',
|
||||
'delete',
|
||||
'view-info',
|
||||
'cancel-process-apply'
|
||||
]);
|
||||
const emits = defineEmits(['selection-change', 'view', 'update', 'delete', 'view-info', 'cancel-process-apply']);
|
||||
|
||||
const handleSelectionChange = (selection) => {
|
||||
const handleSelectionChange = (selection) => {
|
||||
emits('selection-change', selection);
|
||||
};
|
||||
};
|
||||
|
||||
const handleView = (row) => {
|
||||
const handleView = (row) => {
|
||||
emits('view', row);
|
||||
};
|
||||
};
|
||||
|
||||
const handleUpdate = (row) => {
|
||||
const handleUpdate = (row) => {
|
||||
emits('update', row);
|
||||
};
|
||||
};
|
||||
|
||||
const handleDelete = (row) => {
|
||||
const handleDelete = (row) => {
|
||||
emits('delete', row);
|
||||
};
|
||||
};
|
||||
|
||||
const handleViewInfo = (row) => {
|
||||
const handleViewInfo = (row) => {
|
||||
emits('view-info', row);
|
||||
};
|
||||
};
|
||||
|
||||
const handleCancelProcessApply = (id) => {
|
||||
const handleCancelProcessApply = (id) => {
|
||||
emits('cancel-process-apply', id);
|
||||
};
|
||||
</script>
|
||||
};
|
||||
</script>
|
||||
|
355
src/views/design/received/index.vue
Normal file
355
src/views/design/received/index.vue
Normal file
@ -0,0 +1,355 @@
|
||||
<template>
|
||||
<div class="p-6 bg-gray-50">
|
||||
<div class="appWidth mx-auto bg-white rounded-xl shadow-sm overflow-hidden transition-all duration-300 hover:shadow-md">
|
||||
<!-- 表单标题区域 -->
|
||||
<div class="bg-gradient-to-r from-blue-500 to-blue-600 text-white p-6">
|
||||
<h2 class="text-2xl font-bold flex items-center"><i class="el-icon-user-circle mr-3"></i>收集资料清单</h2>
|
||||
<p class="text-blue-100 mt-2 opacity-90">请填写相关资料信息</p>
|
||||
</div>
|
||||
|
||||
<!-- 表单内容区域 -->
|
||||
<el-form ref="mainFormRef" :model="form" :rules="mainRules" label-width="120px" class="p-6">
|
||||
<!-- 基本信息区域 -->
|
||||
<div class="bg-blue-50 p-4 rounded-lg mb-6">
|
||||
<h3 class="text-lg font-semibold text-blue-700 mb-4">基本信息</h3>
|
||||
|
||||
<div class="grid grid-cols-1 md:grid-cols-2 gap-4">
|
||||
<el-form-item label="收资人" prop="userId" class="mb-4">
|
||||
<el-select
|
||||
:disabled="disabledAll"
|
||||
v-model="form.userId"
|
||||
placeholder="请选择收资人"
|
||||
class="w-full transition-all duration-300 border-gray-300 focus:border-blue-400 focus:ring-1 focus:ring-blue-400"
|
||||
>
|
||||
<el-option v-for="item in userList" :key="item.userId" :label="item.nickName" :value="item.userId" />
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item label="专业" prop="user_major" class="mb-4">
|
||||
<el-select
|
||||
:disabled="disabledAll"
|
||||
v-model="form.user_major"
|
||||
placeholder="请选择专业"
|
||||
class="transition-all duration-300 border-gray-300"
|
||||
:rules="{ required: true, message: '请选择专业', trigger: 'change' }"
|
||||
>
|
||||
<el-option v-for="item in des_user_major" :key="item.value" :label="item.label" :value="item.value" />
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
|
||||
<el-form-item label="电话" prop="phone" class="mb-4">
|
||||
<el-input :disabled="disabledAll" placeholder="请输入电话" v-model="form.phone" autocomplete="off" />
|
||||
</el-form-item>
|
||||
|
||||
<el-form-item label="邮箱" prop="email" class="mb-4">
|
||||
<el-input :disabled="disabledAll" placeholder="请输入邮箱" v-model="form.email" autocomplete="off" />
|
||||
</el-form-item>
|
||||
</div>
|
||||
</div>
|
||||
<!-- 资料文件区域 -->
|
||||
<div class="mb-6">
|
||||
<div class="flex items-center justify-between mb-4">
|
||||
<h3 class="text-lg font-semibold text-blue-700">资料文件清单</h3>
|
||||
<el-button type="primary" size="small" @click="addDocumentItem" v-if="!disabledAll" icon="Plus"> 添加资料 </el-button>
|
||||
</div>
|
||||
<el-form ref="documentsFormRef" :model="form" class="space-y-4">
|
||||
<div v-for="(item, index) in form.documents" :key="item.id" class="bg-gray-50 p-4 rounded-lg transition-all duration-200 hover:shadow-sm">
|
||||
<div class="flex justify-between items-start mb-2">
|
||||
<span class="text-sm font-medium text-gray-600">资料 {{ index + 1 }}</span>
|
||||
<el-button
|
||||
type="text"
|
||||
size="small"
|
||||
text-color="#ff4d4f"
|
||||
@click="removeDocumentItem(index)"
|
||||
icon="el-icon-delete"
|
||||
v-if="form.documents.length > 1 && !disabledAll"
|
||||
>
|
||||
删除
|
||||
</el-button>
|
||||
</div>
|
||||
|
||||
<div class="grid grid-cols-1 md:grid-cols-2 gap-4">
|
||||
<el-form-item
|
||||
label="文件目录名称"
|
||||
:prop="`documents.${index}.catalogueName`"
|
||||
:rules="[{ required: true, message: '请输入文件目录名称', trigger: 'blur' }]"
|
||||
class="mb-4"
|
||||
>
|
||||
<el-input :disabled="disabledAll" placeholder="请输入文件目录名称" v-model="item.catalogueName" autocomplete="off" />
|
||||
</el-form-item>
|
||||
<el-form-item label="备注" :prop="`documents.${index}.remark`" class="mb-4">
|
||||
<el-input :disabled="disabledAll" placeholder="请输入备注" v-model="item.remark" autocomplete="off" />
|
||||
</el-form-item>
|
||||
</div>
|
||||
</div>
|
||||
</el-form>
|
||||
</div>
|
||||
<!-- 操作按钮区域 -->
|
||||
<div class="flex justify-center gap-4 mt-8">
|
||||
<el-button type="primary" @click="submitForm" v-if="!form.id || form.status == 'draft'" size="large">确认提交</el-button>
|
||||
<!-- <el-button @click="resetForm" size="large">重置</el-button> -->
|
||||
<el-button type="primary" @click="update" v-show="form.id && form.status == 'draft'" size="large">审核</el-button>
|
||||
<el-button type="primary" @click="update" v-show="form.status == 'back'" size="large">重新发起审核</el-button>
|
||||
<el-button type="primary" @click="onView" v-show="form.id && form.status != 'draft'" size="large">查看流程</el-button>
|
||||
</div>
|
||||
</el-form>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup name="DataCollectionForm" lang="ts">
|
||||
import { ref, reactive, computed, onMounted } from 'vue';
|
||||
import { useUserStoreHook } from '@/store/modules/user';
|
||||
import { ElMessage, ElLoading } from 'element-plus';
|
||||
import { systemUserList } from '@/api/design/appointment';
|
||||
import { collectBatch, byProjectId } from '@/api/design/received';
|
||||
// 获取用户 store
|
||||
const { proxy } = getCurrentInstance() as ComponentInternalInstance;
|
||||
const userStore = useUserStoreHook();
|
||||
// 从 store 中获取当前选中的项目
|
||||
const currentProject = computed(() => userStore.selectedProject);
|
||||
const { des_user_major } = toRefs<any>(proxy?.useDict('des_user_major'));
|
||||
|
||||
// 表单引用
|
||||
const mainFormRef = ref();
|
||||
// 用户列表
|
||||
const userList = ref([]);
|
||||
const userMap = new Map();
|
||||
const disabledAll = ref(false);
|
||||
// 表单数据
|
||||
const form = reactive({
|
||||
projectId: currentProject.value?.id,
|
||||
userId: '', // 收资人
|
||||
user_major: '', // 专业
|
||||
phone: '', // 电话
|
||||
email: '', // 邮箱
|
||||
id: '',
|
||||
status: '',
|
||||
documents: [
|
||||
{
|
||||
id: Date.now(),
|
||||
catalogueName: '', // 文件目录名称
|
||||
remark: '' // 备注
|
||||
}
|
||||
] as Array<{
|
||||
id: number;
|
||||
catalogueName: string;
|
||||
remark: string;
|
||||
}>
|
||||
});
|
||||
|
||||
// 主表单验证规则
|
||||
const mainRules = reactive({
|
||||
userId: [{ required: true, message: '请输入收资人', trigger: 'blur' }],
|
||||
user_major: [{ required: true, message: '请选择专业', trigger: 'change' }],
|
||||
phone: [
|
||||
{ required: true, message: '请输入电话', trigger: 'blur' },
|
||||
{ pattern: /^1[3-9]\d{9}$/, message: '请输入正确的手机号码', trigger: 'blur' }
|
||||
],
|
||||
email: [
|
||||
{ required: true, message: '请输入邮箱', trigger: 'blur' },
|
||||
{ type: 'email', message: '请输入正确的邮箱格式', trigger: 'blur' }
|
||||
]
|
||||
});
|
||||
|
||||
// 添加资料项
|
||||
const addDocumentItem = () => {
|
||||
form.documents.push({
|
||||
id: Date.now(),
|
||||
catalogueName: '',
|
||||
remark: ''
|
||||
});
|
||||
};
|
||||
|
||||
// 删除资料项
|
||||
const removeDocumentItem = (index: number) => {
|
||||
form.documents.splice(index, 1);
|
||||
};
|
||||
// 查询数据 再次回显
|
||||
const byProjectIdAll = async () => {
|
||||
// 调用接口获取数据
|
||||
const res = await byProjectId(currentProject.value?.id);
|
||||
if (res.code === 200 && res.data) {
|
||||
const data = res.data;
|
||||
// 回显基本信息
|
||||
form.userId = data.userId || '';
|
||||
form.user_major = data.userMajor || '';
|
||||
form.phone = data.phone || '';
|
||||
form.email = data.email || '';
|
||||
form.id = data.id || '';
|
||||
form.status = data.status || '';
|
||||
if (form.status == 'finish') {
|
||||
// 表单全部禁用
|
||||
disabledAll.value = true;
|
||||
}
|
||||
// 回显资料文件列表
|
||||
if (data.catalogueList && data.catalogueList.length > 0) {
|
||||
// 清空现有列表
|
||||
form.documents = [];
|
||||
// 填充新数据
|
||||
data.catalogueList.forEach((item: any, index: number) => {
|
||||
form.documents.push({
|
||||
id: item.id || Date.now() + index, // 确保id唯一
|
||||
catalogueName: item.catalogueName || '',
|
||||
remark: item.remark || ''
|
||||
});
|
||||
});
|
||||
} else {
|
||||
// 如果没有资料,保持一个空项
|
||||
form.documents = [
|
||||
{
|
||||
id: Date.now(),
|
||||
catalogueName: '',
|
||||
remark: ''
|
||||
}
|
||||
];
|
||||
}
|
||||
}
|
||||
};
|
||||
// 提交表单
|
||||
const submitForm = async () => {
|
||||
if (!mainFormRef.value) return;
|
||||
try {
|
||||
const valid = await mainFormRef.value.validate();
|
||||
if (valid) {
|
||||
// 这里可以添加提交逻辑
|
||||
form.documents.map((item, i) => {
|
||||
item.num = i + 1;
|
||||
});
|
||||
let body = {
|
||||
desCollectBo: {
|
||||
projectId: currentProject.value?.id,
|
||||
userId: form.userId, // 收资人
|
||||
userMajor: form.user_major, // 专业
|
||||
id: form.id,
|
||||
phone: form.phone, // 电话
|
||||
email: form.email, // 邮箱
|
||||
userName: userMap.get(form.userId)
|
||||
},
|
||||
catalogueList: form.documents
|
||||
};
|
||||
let res = await collectBatch(body);
|
||||
if (res.code == 200) {
|
||||
byProjectIdAll();
|
||||
ElMessage.success('表单提交成功');
|
||||
} else {
|
||||
ElMessage.success(res.msg);
|
||||
}
|
||||
}
|
||||
} catch (error) {
|
||||
ElMessage.error('请完善表单信息后再提交');
|
||||
}
|
||||
};
|
||||
// 重置表单
|
||||
const resetForm = () => {
|
||||
if (mainFormRef.value) {
|
||||
mainFormRef.value.resetFields();
|
||||
}
|
||||
// 重置资料列表,保留一个空项
|
||||
form.documents = [
|
||||
{
|
||||
id: Date.now(),
|
||||
catalogueName: '',
|
||||
remark: ''
|
||||
}
|
||||
];
|
||||
};
|
||||
/** 查询当前部门的所有用户 */
|
||||
const getDeptAllUser = async (deptId: any) => {
|
||||
try {
|
||||
const res = await systemUserList({ deptId });
|
||||
// 实际项目中使用接口返回的数据
|
||||
userList.value = res.rows;
|
||||
userList.value.forEach((user) => {
|
||||
userMap.set(user.userId, user.nickName);
|
||||
});
|
||||
} catch (error) {
|
||||
ElMessage.error('获取用户列表失败');
|
||||
}
|
||||
};
|
||||
const update = () => {
|
||||
proxy.$tab.closePage(proxy.$route);
|
||||
proxy.$router.push({
|
||||
path: `/design-management/received/indexEdit`,
|
||||
query: {
|
||||
id: form.id,
|
||||
type: 'update'
|
||||
}
|
||||
});
|
||||
};
|
||||
const onView = () => {
|
||||
proxy.$tab.closePage(proxy.$route);
|
||||
proxy.$router.push({
|
||||
path: `/design-management/received/indexEdit`,
|
||||
query: {
|
||||
id: form.id,
|
||||
type: 'view'
|
||||
}
|
||||
});
|
||||
};
|
||||
// 页面挂载时初始化数据
|
||||
onMounted(() => {
|
||||
// 可以在这里添加初始化逻辑
|
||||
getDeptAllUser(userStore.deptId).then(() => {
|
||||
byProjectIdAll();
|
||||
});
|
||||
});
|
||||
//监听项目id刷新数据
|
||||
const listeningProject = watch(
|
||||
() => currentProject.value.id,
|
||||
(nid, oid) => {
|
||||
getDeptAllUser(userStore.deptId).then(() => {
|
||||
byProjectIdAll();
|
||||
});
|
||||
}
|
||||
);
|
||||
|
||||
onUnmounted(() => {
|
||||
listeningProject();
|
||||
});
|
||||
</script>
|
||||
|
||||
<style lang="scss">
|
||||
.appWidth {
|
||||
width: 90%;
|
||||
max-width: 1000px;
|
||||
}
|
||||
|
||||
// 全局样式调整,使界面更柔和
|
||||
::v-deep .el-input__inner,
|
||||
::v-deep .el-select__input {
|
||||
border-radius: 6px;
|
||||
border-color: #dcdfe6;
|
||||
transition: all 0.2s ease;
|
||||
}
|
||||
|
||||
::v-deep .el-input__inner:focus,
|
||||
::v-deep .el-select__input:focus {
|
||||
border-color: #409eff;
|
||||
box-shadow: 0 0 0 2px rgba(64, 158, 255, 0.2);
|
||||
}
|
||||
|
||||
::v-deep .el-button {
|
||||
border-radius: 6px;
|
||||
transition: all 0.2s ease;
|
||||
}
|
||||
|
||||
::v-deep .el-form-item__label {
|
||||
font-weight: 500;
|
||||
color: #606266;
|
||||
}
|
||||
|
||||
// 响应式调整
|
||||
@media (max-width: 768px) {
|
||||
.appWidth {
|
||||
width: 95%;
|
||||
}
|
||||
|
||||
::v-deep .el-form-item {
|
||||
margin-bottom: 16px;
|
||||
}
|
||||
|
||||
::v-deep .el-form-item__label {
|
||||
width: 100px;
|
||||
}
|
||||
}
|
||||
</style>
|
454
src/views/design/received/indexEdit.vue
Normal file
454
src/views/design/received/indexEdit.vue
Normal file
@ -0,0 +1,454 @@
|
||||
<template>
|
||||
<div class="p-4 bg-gray-50">
|
||||
<div class="max-w-4xl mx-auto">
|
||||
<!-- 顶部按钮区域 -->
|
||||
<el-card class="mb-4 rounded-lg shadow-sm bg-white border border-gray-100 transition-all hover:shadow-md">
|
||||
<approvalButton
|
||||
@submitForm="submitForm"
|
||||
@approvalVerifyOpen="approvalVerifyOpen"
|
||||
@handleApprovalRecord="handleApprovalRecord"
|
||||
:buttonLoading="buttonLoading"
|
||||
:id="form.id"
|
||||
:status="form.status"
|
||||
:pageType="routeParams.type"
|
||||
/>
|
||||
</el-card>
|
||||
<!-- 表单区域 -->
|
||||
<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>
|
||||
</div>
|
||||
<div class="p-6">
|
||||
<div class="appWidth mx-auto bg-white rounded-xl shadow-sm overflow-hidden transition-all duration-300 hover:shadow-md">
|
||||
<!-- 表单内容区域 -->
|
||||
<el-form ref="mainFormRef" :model="form" label-width="120px" class="p-6">
|
||||
<!-- 基本信息区域 -->
|
||||
<div class="bg-blue-50 p-4 rounded-lg mb-6">
|
||||
<h3 class="text-lg font-semibold text-blue-700 mb-4">基本信息</h3>
|
||||
<div class="grid grid-cols-1 md:grid-cols-2 gap-4">
|
||||
<el-form-item label="收资人" prop="userId" class="mb-4">
|
||||
<el-select
|
||||
disabled
|
||||
v-model="form.userId"
|
||||
placeholder="请选择收资人"
|
||||
class="w-full transition-all duration-300 border-gray-300 focus:border-blue-400 focus:ring-1 focus:ring-blue-400"
|
||||
>
|
||||
<el-option v-for="item in userList" :key="item.userId" :label="item.nickName" :value="item.userId" />
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item label="专业" prop="user_major" class="mb-4">
|
||||
<el-select
|
||||
disabled
|
||||
v-model="form.user_major"
|
||||
placeholder="请选择专业"
|
||||
class="transition-all duration-300 border-gray-300"
|
||||
:rules="{ required: true, message: '请选择专业', trigger: 'change' }"
|
||||
>
|
||||
<el-option v-for="item in des_user_major" :key="item.value" :label="item.label" :value="item.value" />
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
|
||||
<el-form-item label="电话" prop="phone" class="mb-4">
|
||||
<el-input disabled placeholder="请输入电话" v-model="form.phone" autocomplete="off" />
|
||||
</el-form-item>
|
||||
|
||||
<el-form-item label="邮箱" prop="email" class="mb-4">
|
||||
<el-input disabled placeholder="请输入邮箱" v-model="form.email" autocomplete="off" />
|
||||
</el-form-item>
|
||||
</div>
|
||||
</div>
|
||||
<!-- 资料文件区域 -->
|
||||
<div class="mb-6">
|
||||
<el-form ref="documentsFormRef" :model="form" class="space-y-4">
|
||||
<div
|
||||
v-for="(item, index) in form.documents"
|
||||
:key="item.id"
|
||||
class="bg-gray-50 p-4 rounded-lg transition-all duration-200 hover:shadow-sm"
|
||||
>
|
||||
<div class="grid grid-cols-1 md:grid-cols-2 gap-4">
|
||||
<el-form-item
|
||||
label="文件目录名称"
|
||||
:prop="`documents.${index}.catalogueName`"
|
||||
:rules="[{ required: true, message: '请输入文件目录名称', trigger: 'blur' }]"
|
||||
class="mb-4"
|
||||
>
|
||||
<el-input disabled placeholder="请输入文件目录名称" v-model="item.catalogueName" autocomplete="off" />
|
||||
</el-form-item>
|
||||
<el-form-item label="备注" :prop="`documents.${index}.remark`" class="mb-4">
|
||||
<el-input disabled placeholder="请输入备注" v-model="item.remark" autocomplete="off" />
|
||||
</el-form-item>
|
||||
</div>
|
||||
</div>
|
||||
</el-form>
|
||||
</div>
|
||||
</el-form>
|
||||
</div>
|
||||
</div>
|
||||
</el-card>
|
||||
<!-- 提交组件 -->
|
||||
<submitVerify ref="submitVerifyRef" :task-variables="taskVariables" @submit-callback="submitCallback" />
|
||||
<approvalRecord ref="approvalRecordRef"></approvalRecord>
|
||||
<!-- 流程选择对话框 -->
|
||||
<el-dialog
|
||||
draggable
|
||||
v-model="dialogVisible.visible"
|
||||
:title="dialogVisible.title"
|
||||
:before-close="handleClose"
|
||||
width="500"
|
||||
class="rounded-lg shadow-lg"
|
||||
>
|
||||
<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-select>
|
||||
</div>
|
||||
<template #footer>
|
||||
<div class="dialog-footer p-4 border-t border-gray-100 flex justify-end space-x-3">
|
||||
<el-button @click="handleClose" class="px-4 py-2 border border-gray-300 rounded-md text-gray-700 hover:bg-gray-50 transition-colors"
|
||||
>取消</el-button
|
||||
>
|
||||
<el-button type="primary" @click="submitFlow()" class="px-4 py-2 bg-primary text-white rounded-md hover:bg-primary/90 transition-colors"
|
||||
>确认</el-button
|
||||
>
|
||||
</div>
|
||||
</template>
|
||||
</el-dialog>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup name="Leave" lang="ts">
|
||||
import { LeaveForm } from '@/api/workflow/leave/types';
|
||||
import { startWorkFlow } from '@/api/workflow/task';
|
||||
import SubmitVerify from '@/components/Process/submitVerify.vue';
|
||||
import ApprovalRecord from '@/components/Process/approvalRecord.vue';
|
||||
import ApprovalButton from '@/components/Process/approvalButton.vue';
|
||||
import { StartProcessBo } from '@/api/workflow/workflowCommon/types';
|
||||
const { proxy } = getCurrentInstance() as ComponentInternalInstance;
|
||||
import { useUserStoreHook } from '@/store/modules/user';
|
||||
import { systemUserList } from '@/api/design/appointment';
|
||||
import { collectBatch, byProjectId } from '@/api/design/received';
|
||||
// 获取用户 store
|
||||
const userStore = useUserStoreHook();
|
||||
// 从 store 中获取项目列表和当前选中的项目
|
||||
const currentProject = computed(() => userStore.selectedProject);
|
||||
const { des_user_major } = toRefs<any>(proxy?.useDict('des_user_major'));
|
||||
const buttonLoading = ref(false);
|
||||
const loading = ref(true);
|
||||
//路由参数
|
||||
const routeParams = ref<Record<string, any>>({});
|
||||
const flowCodeOptions = [
|
||||
{
|
||||
value: currentProject.value?.id + '_collect',
|
||||
label: '收资清单'
|
||||
}
|
||||
];
|
||||
|
||||
const flowCode = ref<string>('');
|
||||
const status = ref<string>('');
|
||||
const dialogVisible = reactive<DialogOption>({
|
||||
visible: false,
|
||||
title: '流程定义'
|
||||
});
|
||||
//提交组件
|
||||
const submitVerifyRef = ref<InstanceType<typeof SubmitVerify>>();
|
||||
//审批记录组件
|
||||
const approvalRecordRef = ref<InstanceType<typeof ApprovalRecord>>();
|
||||
//按钮组件
|
||||
const approvalButtonRef = ref<InstanceType<typeof ApprovalButton>>();
|
||||
|
||||
const leaveFormRef = ref<ElFormInstance>();
|
||||
const dialog = reactive({
|
||||
visible: false,
|
||||
title: '',
|
||||
isEdit: false
|
||||
});
|
||||
const submitFormData = ref<StartProcessBo>({
|
||||
businessId: '',
|
||||
flowCode: '',
|
||||
variables: {}
|
||||
});
|
||||
const taskVariables = ref<Record<string, any>>({});
|
||||
// 用户列表
|
||||
const userList = ref([]);
|
||||
const userMap = new Map();
|
||||
// 表单引用
|
||||
const mainFormRef = ref();
|
||||
const handleClose = () => {
|
||||
dialogVisible.visible = false;
|
||||
flowCode.value = '';
|
||||
buttonLoading.value = false;
|
||||
};
|
||||
// 表单数据
|
||||
const form = reactive({
|
||||
projectId: currentProject.value?.id,
|
||||
userId: '', // 收资人
|
||||
user_major: '', // 专业
|
||||
phone: '', // 电话
|
||||
email: '', // 邮箱
|
||||
id: '',
|
||||
status: '',
|
||||
documents: [
|
||||
{
|
||||
id: Date.now(),
|
||||
catalogueName: '', // 文件目录名称
|
||||
remark: '' // 备注
|
||||
}
|
||||
] as Array<{
|
||||
id: number;
|
||||
catalogueName: string;
|
||||
remark: string;
|
||||
}>
|
||||
});
|
||||
/** 表单重置 */
|
||||
const reset = () => {
|
||||
if (mainFormRef.value) {
|
||||
mainFormRef.value.resetFields();
|
||||
}
|
||||
// 重置资料列表,保留一个空项
|
||||
form.documents = [
|
||||
{
|
||||
id: Date.now(),
|
||||
catalogueName: '',
|
||||
remark: ''
|
||||
}
|
||||
];
|
||||
leaveFormRef.value?.resetFields();
|
||||
};
|
||||
|
||||
/** 提交按钮 */
|
||||
const submitForm = (status1: string) => {
|
||||
status.value = status1;
|
||||
buttonLoading.value = true;
|
||||
dialog.visible = false;
|
||||
submit(status.value, form);
|
||||
};
|
||||
|
||||
const submitFlow = async () => {
|
||||
handleStartWorkFlow(form);
|
||||
dialogVisible.visible = false;
|
||||
};
|
||||
//提交申请
|
||||
const handleStartWorkFlow = async (data: LeaveForm) => {
|
||||
try {
|
||||
submitFormData.value.flowCode = flowCode.value;
|
||||
submitFormData.value.businessId = data.id;
|
||||
//流程变量
|
||||
taskVariables.value = {
|
||||
// leave4/5 使用的流程变量
|
||||
userList: ['1', '3', '4']
|
||||
};
|
||||
submitFormData.value.variables = taskVariables.value;
|
||||
const resp = await startWorkFlow(submitFormData.value);
|
||||
if (submitVerifyRef.value) {
|
||||
buttonLoading.value = false;
|
||||
submitVerifyRef.value.openDialog(resp.data.taskId);
|
||||
}
|
||||
} finally {
|
||||
buttonLoading.value = false;
|
||||
}
|
||||
};
|
||||
//审批记录
|
||||
const handleApprovalRecord = () => {
|
||||
approvalRecordRef.value.init(form.id);
|
||||
};
|
||||
//提交回调
|
||||
const submitCallback = async () => {
|
||||
await proxy.$tab.closePage(proxy.$route);
|
||||
proxy.$router.go(-1);
|
||||
};
|
||||
//审批
|
||||
const approvalVerifyOpen = async () => {
|
||||
submitVerifyRef.value.openDialog(routeParams.value.taskId);
|
||||
};
|
||||
const submit = async (status, data) => {
|
||||
if (status === 'draft') {
|
||||
buttonLoading.value = false;
|
||||
proxy?.$modal.msgSuccess('暂存成功');
|
||||
proxy.$tab.closePage(proxy.$route);
|
||||
proxy.$router.go(-1);
|
||||
} else {
|
||||
if ((form.status === 'draft' && (flowCode.value === '' || flowCode.value === null)) || routeParams.value.type === 'add') {
|
||||
flowCode.value = flowCodeOptions[0].value;
|
||||
dialogVisible.visible = true;
|
||||
return;
|
||||
}
|
||||
//说明启动过先随意穿个参数
|
||||
if (flowCode.value === '' || flowCode.value === null) {
|
||||
flowCode.value = 'xx';
|
||||
}
|
||||
await handleStartWorkFlow(data);
|
||||
}
|
||||
};
|
||||
/** 查询当前部门的所有用户 */
|
||||
const getDeptAllUser = async (deptId: any) => {
|
||||
try {
|
||||
const res = await systemUserList({ deptId });
|
||||
// 实际项目中使用接口返回的数据
|
||||
userList.value = res.rows;
|
||||
userList.value.forEach((user) => {
|
||||
userMap.set(user.userId, user.nickName);
|
||||
});
|
||||
} catch (error) {
|
||||
ElMessage.error('获取用户列表失败');
|
||||
}
|
||||
};
|
||||
// 查询数据 再次回显
|
||||
const byProjectIdAll = async () => {
|
||||
loading.value = true;
|
||||
buttonLoading.value = false;
|
||||
// 调用接口获取数据
|
||||
const res = await byProjectId(currentProject.value?.id);
|
||||
if (res.code === 200 && res.data) {
|
||||
const data = res.data;
|
||||
// 回显基本信息
|
||||
form.userId = data.userId || '';
|
||||
form.user_major = data.userMajor || '';
|
||||
form.phone = data.phone || '';
|
||||
form.email = data.email || '';
|
||||
form.id = data.id || '';
|
||||
form.status = data.status || '';
|
||||
// 回显资料文件列表
|
||||
if (data.catalogueList && data.catalogueList.length > 0) {
|
||||
// 清空现有列表
|
||||
form.documents = [];
|
||||
// 填充新数据
|
||||
data.catalogueList.forEach((item: any, index: number) => {
|
||||
form.documents.push({
|
||||
id: item.id || Date.now() + index, // 确保id唯一
|
||||
catalogueName: item.catalogueName || '',
|
||||
remark: item.remark || ''
|
||||
});
|
||||
});
|
||||
} else {
|
||||
// 如果没有资料,保持一个空项
|
||||
form.documents = [
|
||||
{
|
||||
id: Date.now(),
|
||||
catalogueName: '',
|
||||
remark: ''
|
||||
}
|
||||
];
|
||||
}
|
||||
}
|
||||
loading.value = false;
|
||||
buttonLoading.value = false;
|
||||
};
|
||||
onMounted(() => {
|
||||
nextTick(async () => {
|
||||
routeParams.value = proxy.$route.query;
|
||||
reset();
|
||||
loading.value = false;
|
||||
if (routeParams.value.type === 'update' || routeParams.value.type === 'view' || routeParams.value.type === 'approval') {
|
||||
getDeptAllUser(userStore.deptId).then(() => {
|
||||
byProjectIdAll();
|
||||
});
|
||||
}
|
||||
});
|
||||
});
|
||||
</script>
|
||||
<style scoped lang="scss">
|
||||
/* 全局样式 */
|
||||
:root {
|
||||
--primary: #409eff;
|
||||
--primary-light: #66b1ff;
|
||||
--primary-dark: #3a8ee6;
|
||||
--success: #67c23a;
|
||||
--warning: #e6a23c;
|
||||
--danger: #f56c6c;
|
||||
--info: #909399;
|
||||
}
|
||||
|
||||
/* 表单样式优化 */
|
||||
.el-form-item {
|
||||
.el-form-item__label {
|
||||
color: #606266;
|
||||
font-weight: 500;
|
||||
}
|
||||
|
||||
.el-input__inner,
|
||||
.el-select .el-input__inner {
|
||||
border-radius: 4px;
|
||||
transition:
|
||||
border-color 0.2s,
|
||||
box-shadow 0.2s;
|
||||
|
||||
&:focus {
|
||||
border-color: var(--primary-light);
|
||||
box-shadow: 0 0 0 2px rgba(64, 158, 255, 0.1);
|
||||
}
|
||||
}
|
||||
|
||||
.el-textarea__inner {
|
||||
border-radius: 4px;
|
||||
transition:
|
||||
border-color 0.2s,
|
||||
box-shadow 0.2s;
|
||||
|
||||
&:focus {
|
||||
border-color: var(--primary-light);
|
||||
box-shadow: 0 0 0 2px rgba(64, 158, 255, 0.1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* 按钮样式优化 */
|
||||
.el-button {
|
||||
border-radius: 4px;
|
||||
transition: all 0.2s;
|
||||
|
||||
&.is-primary {
|
||||
background-color: var(--primary);
|
||||
border-color: var(--primary);
|
||||
|
||||
&:hover {
|
||||
background-color: var(--primary-light);
|
||||
border-color: var(--primary-light);
|
||||
}
|
||||
|
||||
&:active {
|
||||
background-color: var(--primary-dark);
|
||||
border-color: var(--primary-dark);
|
||||
}
|
||||
}
|
||||
|
||||
&.is-text {
|
||||
color: var(--primary);
|
||||
|
||||
&:hover {
|
||||
color: var(--primary-light);
|
||||
background-color: rgba(64, 158, 255, 0.05);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* 卡片样式优化 */
|
||||
.el-card {
|
||||
transition: all 0.3s ease;
|
||||
|
||||
&:hover {
|
||||
/* transform: translateY(-2px); */
|
||||
}
|
||||
}
|
||||
|
||||
/* 对话框样式优化 */
|
||||
.el-dialog {
|
||||
.el-dialog__header {
|
||||
background-color: #f5f7fa;
|
||||
border-bottom: 1px solid #ebeef5;
|
||||
padding: 15px 20px;
|
||||
}
|
||||
|
||||
.el-dialog__title {
|
||||
font-size: 16px;
|
||||
font-weight: 600;
|
||||
color: #303133;
|
||||
}
|
||||
|
||||
.el-dialog__footer {
|
||||
padding: 15px 20px;
|
||||
border-top: 1px solid #ebeef5;
|
||||
}
|
||||
}
|
||||
</style>
|
@ -37,8 +37,8 @@
|
||||
</el-col>
|
||||
<el-col :span="24">
|
||||
<el-form-item label="文件" prop="formNo">
|
||||
<div style="display: flex;">
|
||||
<span style="color: rgb(50, 142, 248);" >{{ form.originalName }}</span>
|
||||
<div style="display: flex">
|
||||
<span style="color: rgb(50, 142, 248)">{{ form.originalName }}</span>
|
||||
<!-- <el-button type="primary" link @click="handleView(scope.row)"
|
||||
><el-icon><View /></el-icon>查看</el-button
|
||||
> -->
|
||||
@ -139,10 +139,10 @@ const taskVariables = ref<Record<string, any>>({});
|
||||
|
||||
const initFormData = {
|
||||
id: undefined,
|
||||
fileName:undefined,
|
||||
fileUrl:undefined,
|
||||
status:undefined,
|
||||
originalName:undefined
|
||||
fileName: undefined,
|
||||
fileUrl: undefined,
|
||||
status: undefined,
|
||||
originalName: undefined
|
||||
};
|
||||
const data = reactive({
|
||||
form: { ...initFormData },
|
||||
@ -177,7 +177,7 @@ const getInfo = () => {
|
||||
/** 提交按钮 */
|
||||
const submitForm = (status1: string) => {
|
||||
status.value = status1;
|
||||
submit(status.value,form.value);
|
||||
submit(status.value, form.value);
|
||||
};
|
||||
|
||||
const submitFlow = async () => {
|
||||
|
@ -77,56 +77,79 @@
|
||||
</el-card>
|
||||
</el-col>
|
||||
</el-row>
|
||||
|
||||
<!-- 添加或修改物资-材料设备对话框 -->
|
||||
<el-dialog :title="dialog.title" v-model="dialog.visible" width="500px" append-to-body>
|
||||
<el-dialog draggable :title="dialog.title" v-model="dialog.visible" width="500px" append-to-body>
|
||||
<el-form ref="cailiaoshebeiFormRef" :model="form" :rules="rules" label-width="130px">
|
||||
<el-form-item label="物资执行状态" prop="materialStatus">
|
||||
<el-form-item label="物资执行状态" prop="bo.materialStatus">
|
||||
<el-select v-model="form.bo.materialStatus" placeholder="请选择物资执行状态" clearable filterable @change="handleChange">
|
||||
<el-option v-for="item in material_status" :key="item.value" :label="item.label" :value="item.value" />
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item label="物资逾期类型" prop="overdueType" v-if="form.bo.materialStatus == 3">
|
||||
<el-form-item label="物资逾期类型" prop="bo.overdueType" v-if="form.bo.materialStatus == 3">
|
||||
<el-select v-model="form.bo.overdueType" placeholder="请选择物资逾期类型" clearable filterable>
|
||||
<el-option v-for="item in overdue_type" :key="item.value" :label="item.label" :value="item.value" />
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item label="逾期原因" prop="cause" v-if="form.bo.materialStatus == 3">
|
||||
<el-input v-model="form.bo.cause" placeholder="请输入逾期原因" />
|
||||
<el-form-item label="逾期原因" prop="bo.cause" v-if="form.bo.materialStatus == 3">
|
||||
<el-input v-model="form.bo.cause" type="textarea" placeholder="请输入逾期原因" />
|
||||
</el-form-item>
|
||||
<el-form-item label="实际到货时间" prop="actualArrival" v-if="form.bo.materialStatus < 4">
|
||||
<el-form-item label="实际到货时间" prop="bo.actualArrival" v-if="form.bo.materialStatus < 4">
|
||||
<el-date-picker clearable v-model="form.bo.actualArrival" type="date" value-format="YYYY-MM-DD" placeholder="请选择实际到货时间" />
|
||||
</el-form-item>
|
||||
<el-form-item label="验收时间" prop="receptionTime" v-if="form.bo.materialStatus < 4">
|
||||
<el-form-item label="验收时间" prop="bo.receptionTime" v-if="form.bo.materialStatus < 4">
|
||||
<el-date-picker clearable v-model="form.bo.receptionTime" type="date" value-format="YYYY-MM-DD" placeholder="请选择验收时间" />
|
||||
</el-form-item>
|
||||
<el-form-item label="验收数量" prop="acceptanceQuantity" v-if="form.bo.materialStatus < 4">
|
||||
<el-form-item label="验收数量" prop="bo.acceptanceQuantity" v-if="form.bo.materialStatus < 4">
|
||||
<el-input v-model="form.bo.acceptanceQuantity" type="number" placeholder="请输入验收数量" />
|
||||
</el-form-item>
|
||||
<el-form-item label="需求提交时间" prop="requiredTime">
|
||||
<el-date-picker clearable v-model="form.bo.requiredTime" type="date" value-format="YYYY-MM-DD" placeholder="请选择需求提交时间" />
|
||||
<el-form-item label="需求提交时间" prop="bo.requiredTime">
|
||||
<el-date-picker
|
||||
clearable
|
||||
v-model="form.bo.requiredTime"
|
||||
:disabled="form.bo.requiredTime != null && form.bo.requiredTime != ''"
|
||||
type="date"
|
||||
value-format="YYYY-MM-DD"
|
||||
placeholder="请选择需求提交时间"
|
||||
/>
|
||||
</el-form-item>
|
||||
|
||||
<el-form-item label="订货时间" prop="orderTime">
|
||||
<el-date-picker clearable v-model="form.bo.orderTime" type="date" value-format="YYYY-MM-DD" placeholder="请选择订货时间" />
|
||||
<el-form-item label="订货时间" prop="bo.orderTime">
|
||||
<el-date-picker
|
||||
clearable
|
||||
:disabled="form.bo.orderTime != null && form.bo.orderTime != ''"
|
||||
v-model="form.bo.orderTime"
|
||||
type="date"
|
||||
value-format="YYYY-MM-DD"
|
||||
placeholder="请选择订货时间"
|
||||
/>
|
||||
</el-form-item>
|
||||
|
||||
<el-form-item label="操作状态" prop="operationStatus" v-if="form.bo.materialStatus <= 4 || form.bo.materialStatus == 10">
|
||||
<el-select v-model="form.bo.operationStatus" placeholder="请选择物资执行状态" clearable filterable @change="handleChange">
|
||||
<el-form-item label="操作状态" prop="bo.operationStatus" v-if="form.bo.materialStatus <= 4 || form.bo.materialStatus == 10">
|
||||
<el-select disabled v-model="form.bo.operationStatus" placeholder="请选择物资执行状态" clearable filterable>
|
||||
<el-option v-for="item in operation_s" :key="item.value" :label="item.label" :value="item.value" />
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
|
||||
<el-form-item label="单据类型" prop="billType" v-if="form.bo.materialStatus < 4 || form.bo.materialStatus == 10">
|
||||
<el-select v-model="form.bo.billType" placeholder="请选择单据类型" clearable filterable>
|
||||
<el-form-item label="单据类型" prop="bo.billType" v-if="form.bo.materialStatus < 4 || form.bo.materialStatus == 10">
|
||||
<el-select disabled v-model="form.bo.billType" placeholder="请选择单据类型" clearable filterable>
|
||||
<el-option label="签收单" value="1" />
|
||||
<el-option label="退货单" value="2" />
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item label="上传文件" prop="file" v-if="form.bo.materialStatus < 4 || form.bo.materialStatus == 10">
|
||||
<el-form-item
|
||||
label="上传单据"
|
||||
prop="file"
|
||||
v-if="form.bo.materialStatus < 4 || form.bo.materialStatus == 10"
|
||||
:rules="[
|
||||
{
|
||||
required: isFileRequired,
|
||||
message: '请上传单据',
|
||||
trigger: 'blur'
|
||||
}
|
||||
]"
|
||||
>
|
||||
<file-upload
|
||||
v-model="form.file"
|
||||
:fileType="['doc', 'docx']"
|
||||
:fileType="['pdf', 'png', 'jpg', 'jpeg']"
|
||||
:autoUpload="false"
|
||||
ref="fileUploadRef"
|
||||
:data="form.bo"
|
||||
@ -157,22 +180,13 @@
|
||||
</template>
|
||||
|
||||
<script setup name="Cailiaoshebei" lang="ts">
|
||||
import {
|
||||
listCailiaoshebei,
|
||||
getCailiaoshebei,
|
||||
delCailiaoshebei,
|
||||
addCailiaoshebei,
|
||||
updateCailiaoshebei,
|
||||
listBatch,
|
||||
getBatch,
|
||||
delBatch
|
||||
} from '@/api/materials/orderMaterials';
|
||||
import { listCailiaoshebei, delCailiaoshebei, addCailiaoshebei, listBatch, getBatch, delBatch } from '@/api/materials/orderMaterials';
|
||||
import { CailiaoshebeiVO, CailiaoshebeiQuery, CailiaoshebeiForm } from '@/api/materials/cailiaoshebei/types';
|
||||
import { listContractor } from '@/api/project/contractor';
|
||||
import { useUserStoreHook } from '@/store/modules/user';
|
||||
|
||||
const { proxy } = getCurrentInstance() as ComponentInternalInstance;
|
||||
const { supply, overdue_type, material_status, operation_status } = toRefs<any>(
|
||||
const { overdue_type, material_status, operation_status } = toRefs<any>(
|
||||
proxy?.useDict('supply', 'material_status', 'overdue_type', 'operation_status')
|
||||
);
|
||||
// 获取用户 store
|
||||
@ -190,6 +204,7 @@ const multiple = ref(true);
|
||||
const total = ref(0);
|
||||
const batchOptions = ref<any[]>([]);
|
||||
const fileUploadRef = ref();
|
||||
const operation_s = ref([]); // 移出函数,避免重复定义
|
||||
|
||||
const queryFormRef = ref<ElFormInstance>();
|
||||
const cailiaoshebeiFormRef = ref<ElFormInstance>();
|
||||
@ -213,7 +228,7 @@ const initFormData: CailiaoshebeiForm = {
|
||||
finishTime: undefined,
|
||||
unit: undefined,
|
||||
plan: undefined,
|
||||
file: '',
|
||||
file: null, // 确保初始化为null
|
||||
realQuantity: undefined,
|
||||
projectId: currentProject.value.id,
|
||||
bo: {
|
||||
@ -250,13 +265,25 @@ const data = reactive<PageData<CailiaoshebeiForm, CailiaoshebeiQuery>>({
|
||||
params: {}
|
||||
},
|
||||
rules: {
|
||||
id: [{ required: true, message: '主键ID不能为空', trigger: 'blur' }]
|
||||
'bo.materialStatus': [{ required: true, message: '请选择物资执行状态', trigger: 'change' }],
|
||||
'bo.overdueType': [{ required: true, message: '请选择物资逾期类型', trigger: 'change' }],
|
||||
'bo.cause': [{ required: true, message: '请输入逾期原因', trigger: 'blur' }],
|
||||
'bo.actualArrival': [{ required: true, message: '请选择实际到货时间', trigger: 'change' }],
|
||||
'bo.receptionTime': [{ required: true, message: '请选择验收时间', trigger: 'change' }],
|
||||
'bo.acceptanceQuantity': [{ required: true, message: '请输入验收数量', trigger: 'blur' }],
|
||||
'bo.requiredTime': [{ required: true, message: '请选择需求提交时间', trigger: 'change' }],
|
||||
'bo.orderTime': [{ required: true, message: '请选择订货时间', trigger: 'change' }]
|
||||
}
|
||||
});
|
||||
|
||||
const { queryParams, form, rules } = toRefs(data);
|
||||
const batchNumber = ref('');
|
||||
|
||||
// 计算属性:判断文件是否必填
|
||||
const isFileRequired = computed(() => {
|
||||
return form.value.bo.materialStatus < 4 || form.value.bo.materialStatus == 10;
|
||||
});
|
||||
|
||||
/** 查询物资-材料设备列表 */
|
||||
const getList = async () => {
|
||||
if (!queryParams.value.batchNumber) return;
|
||||
@ -264,20 +291,21 @@ const getList = async () => {
|
||||
loading.value = true;
|
||||
const res = await listCailiaoshebei(queryParams.value);
|
||||
cailiaoshebeiList.value = res.rows;
|
||||
|
||||
loading.value = false;
|
||||
};
|
||||
|
||||
//查询批次列表
|
||||
// 查询批次列表
|
||||
const getBatchList = async () => {
|
||||
const res = await listBatch(queryParams.value);
|
||||
console.log('🚀 ~ getBatchList ~ res:', res);
|
||||
batchOptions.value = res.rows;
|
||||
total.value = res.total;
|
||||
|
||||
try {
|
||||
if (res.rows.length > 0) {
|
||||
batchTreeRef.value.setCurrentKey(res.rows[0].batchNumber);
|
||||
form.value.batchNumber = res.rows[0].batchNumber;
|
||||
queryParams.value.batchNumber = res.rows[0].batchNumber;
|
||||
}
|
||||
} catch (error) {
|
||||
form.value.batchNumber = '';
|
||||
}
|
||||
@ -289,10 +317,6 @@ const getBatchList = async () => {
|
||||
const handleNodeClick = (data: any) => {
|
||||
queryParams.value.batchNumber = data.batchNumber;
|
||||
form.value.batchNumber = data.batchNumber;
|
||||
console.log('🚀 ~ handleNodeClick ~ form.value:', form.value);
|
||||
if (data.batchNumber === '0') {
|
||||
queryParams.value.batchNumber = '';
|
||||
}
|
||||
getList();
|
||||
};
|
||||
|
||||
@ -310,13 +334,11 @@ const cancel = () => {
|
||||
/** 表单重置 */
|
||||
const reset = () => {
|
||||
const preservedBatchId = form.value.batchNumber;
|
||||
|
||||
form.value = {
|
||||
...initFormData,
|
||||
bo: { ...initFormData.bo }, // 新建一个 bo 对象
|
||||
bo: { ...initFormData.bo },
|
||||
batchNumber: preservedBatchId
|
||||
};
|
||||
|
||||
cailiaoshebeiFormRef.value?.resetFields();
|
||||
};
|
||||
|
||||
@ -335,44 +357,36 @@ const resetQuery = () => {
|
||||
/** 多选框选中数据 */
|
||||
const handleSelectionChange = (selection: CailiaoshebeiVO[]) => {
|
||||
ids.value = selection.map((item) => item.id);
|
||||
single.value = selection.length != 1;
|
||||
single.value = selection.length !== 1;
|
||||
multiple.value = !selection.length;
|
||||
};
|
||||
|
||||
/** 新增按钮操作 */
|
||||
const handleAdd = () => {
|
||||
reset();
|
||||
dialog.visible = true;
|
||||
dialog.title = '添加物资-材料设备';
|
||||
};
|
||||
|
||||
/** 修改按钮操作 */
|
||||
const operation_s = ref([]);
|
||||
const handleUpdate = async (row?: CailiaoshebeiVO) => {
|
||||
reset();
|
||||
operation_s.value = operation_status.value.slice(0, 2);
|
||||
Object.assign(form.value.bo, row);
|
||||
console.log('🚀 ~ handleUpdate ~ form.value:', form.value);
|
||||
handleChange(form.value.bo.materialStatus);
|
||||
dialog.visible = true;
|
||||
dialog.title = '修改物资-材料设备';
|
||||
};
|
||||
|
||||
/** 提交按钮 */
|
||||
const submitForm = () => {
|
||||
cailiaoshebeiFormRef.value?.validate(async (valid: boolean) => {
|
||||
if (valid) {
|
||||
buttonLoading.value = true;
|
||||
|
||||
// 清理空值
|
||||
Object.keys(form.value.bo).forEach((key) => {
|
||||
if (form.value.bo[key] == 'null' || form.value.bo[key] == null) {
|
||||
delete form.value.bo[key];
|
||||
}
|
||||
});
|
||||
console.log('🚀 ~ submitForm ~ form.value:', form.value.bo);
|
||||
|
||||
cailiaoshebeiFormRef.value?.validate(async (valid: boolean) => {
|
||||
if (valid) {
|
||||
buttonLoading.value = true;
|
||||
if (fileUploadRef.value) {
|
||||
fileUploadRef.value!.submitUpload();
|
||||
} else {
|
||||
form.value.bo.file = null;
|
||||
await addCailiaoshebei(form.value.bo).finally(() => (buttonLoading.value = false));
|
||||
dialog.visible = false;
|
||||
getList();
|
||||
@ -381,26 +395,6 @@ const submitForm = () => {
|
||||
});
|
||||
};
|
||||
|
||||
/** 新增批次 */
|
||||
const addBatch = async () => {
|
||||
await proxy?.$modal.confirm('是否确认新增批次?').finally(() => (loading.value = false));
|
||||
const res = await getBatch({ projectId: currentProject.value.id });
|
||||
console.log('🚀 ~ addBatch ~ res:', res);
|
||||
await getBatchList();
|
||||
|
||||
proxy?.$modal.msgSuccess('新增成功');
|
||||
};
|
||||
|
||||
/** 删除批次 */
|
||||
const handleDeleteBatch = async () => {
|
||||
const _ids = batchTreeRef.value.getCurrentNode()?.id;
|
||||
await proxy?.$modal.confirm('是否确认删除批次编号为"' + _ids + '"的数据项?').finally(() => (loading.value = false));
|
||||
await delBatch(_ids);
|
||||
proxy?.$modal.msgSuccess('删除成功');
|
||||
queryParams.value.batchNumber = '';
|
||||
await getBatchList();
|
||||
};
|
||||
|
||||
/** 删除按钮操作 */
|
||||
const handleDelete = async (row?: CailiaoshebeiVO) => {
|
||||
const _ids = row?.id || ids.value;
|
||||
@ -418,13 +412,24 @@ const handleUploadSuccess = () => {
|
||||
};
|
||||
|
||||
const handleChange = (value: number) => {
|
||||
// 清空文件字段当状态改变时
|
||||
form.value.file = null;
|
||||
if (value == 1 || value == 2 || value == 3) {
|
||||
form.value.bo.operationStatus = '1';
|
||||
form.value.bo.billType = '1';
|
||||
}
|
||||
if (value == 10) {
|
||||
form.value.bo.operationStatus = '2';
|
||||
form.value.bo.billType = '2';
|
||||
}
|
||||
if (!(value < 4 || value == 10)) {
|
||||
form.value.bo.billType = '';
|
||||
form.value.file = '';
|
||||
} else if (value == 3) {
|
||||
form.value.bo.overdueType = '';
|
||||
form.value.bo.cause = '';
|
||||
}
|
||||
// 触发文件字段验证更新
|
||||
cailiaoshebeiFormRef.value?.validateField('file');
|
||||
};
|
||||
|
||||
/** 查询供货商列表 */
|
||||
@ -443,10 +448,10 @@ onMounted(() => {
|
||||
getSupplierList();
|
||||
});
|
||||
|
||||
//监听项目id刷新数据
|
||||
// 监听项目id刷新数据
|
||||
const listeningProject = watch(
|
||||
() => currentProject.value.id,
|
||||
(nid, oid) => {
|
||||
(nid) => {
|
||||
queryParams.value.projectId = nid;
|
||||
form.value.projectId = nid;
|
||||
getBatchList();
|
||||
|
Reference in New Issue
Block a user