This commit is contained in:
2025-08-15 17:25:27 +08:00
33 changed files with 787 additions and 258 deletions

View File

@ -5,7 +5,7 @@ VITE_APP_TITLE = 新能源项目管理平台
VITE_APP_ENV = 'development'
# 开发环境
VITE_APP_BASE_API = 'http://192.168.110.180:8898'
VITE_APP_BASE_API = 'http://192.168.110.180:8899'
# 无人机接口地址

Binary file not shown.

Before

Width:  |  Height:  |  Size: 24 KiB

After

Width:  |  Height:  |  Size: 34 KiB

View File

@ -49,7 +49,7 @@ export const addFormalitiesAreConsolidated = (data: FormalitiesAreConsolidatedFo
*/
export const updateFormalitiesAreConsolidated = (data: FormalitiesAreConsolidatedForm) => {
return request({
url: '/formalities/formalitiesAreConsolidated',
url: '/formalities/formalitiesAreConsolidated/edit',
method: 'put',
data: data
});
@ -77,3 +77,27 @@ export const editStatus = (data: FormalitiesAreConsolidatedForm) => {
data: data
});
};
/**
* 查询合规性手续合账文件列表
* @param query
* @returns {*}
*/
export const listFormalitiesAnnex = (query?: any): AxiosPromise<FormalitiesAreConsolidatedVO[]> => {
return request({
url: '/formalities/formalitiesAnnex/list',
method: 'get',
params: query
});
};
/**
* 删除合规性手续合账文件
* @param id
*/
export const delFormalitiesAnnex = (id: string | number | Array<string | number>) => {
return request({
url: '/formalities/formalitiesAnnex/' + id,
method: 'delete'
});
};

View File

@ -61,3 +61,17 @@ export const delListOfFormalities = (id: string | number | Array<string | number
method: 'delete'
});
};
/**
* 查询手续办理清单模板是否存在
* @param id
*/
export const getWhetherItExists = (id: string | number): AxiosPromise<ListOfFormalitiesVO> => {
return request({
url: '/formalities/formalitiesAreConsolidated/getWhetherItExists',
method: 'get',
params: {
projectId: id
}
});
};

View File

@ -111,3 +111,13 @@ export const purchaseDocPlanList = (id) => {
method: 'get'
});
};
/**
* 通过物流单号 物流详情
* @param id
*/
export const logisticsDetial = (id) => {
return request({
url: '/cailiaoshebei/ltn/logistics/' + id,
method: 'get'
});
};

Binary file not shown.

Before

Width:  |  Height:  |  Size: 24 KiB

After

Width:  |  Height:  |  Size: 34 KiB

View File

@ -21,6 +21,7 @@
:on-change="handleChange"
:on-remove="handleRemove"
:method="method"
:http-request="customUpload"
>
<slot>
<div>
@ -89,6 +90,7 @@
import { propTypes } from '@/utils/propTypes';
import { delOss, listByIds } from '@/api/system/oss';
import { globalHeaders } from '@/utils/request';
import axios from 'axios';
const props = defineProps({
modelValue: {
type: [String, Object, Array],
@ -143,6 +145,7 @@ const uploadList = ref<any[]>([]);
const baseUrl = import.meta.env.VITE_APP_BASE_API;
const uploadFileUrl = ref(baseUrl + props.uploadUrl); // 上传文件服务器地址
const headers = ref(globalHeaders());
const pendingFiles = ref<UploadFile[]>([]);
const realUploadUrl = computed(() => {
const search = new URLSearchParams(props.params).toString();
@ -237,28 +240,33 @@ interface UploadFileWithOssId extends UploadFile {
}
const handleUploadSuccess = (res: any, file: UploadFileWithOssId) => {
console.log(props.data);
if (res.code === 200) {
if (res.data) {
console.log('上传成功');
// 上传成功,不管 data 是否为空
uploadList.value.push({
name: res.data.fileName,
url: res.data.url,
ossId: res.data.ossId
name: file.name,
url: (res.data && res.data.url) || '',
ossId: (res.data && res.data.ossId) || ''
});
} else {
uploadList.value.push({});
}
} else {
console.log('失败', res);
number.value--;
proxy?.$modal.closeLoading();
proxy?.$modal.msgError(res.msg);
proxy?.$modal.msgError(res.msg || '上传失败');
fileUploadRef.value?.handleRemove(file);
return;
}
uploadedSuccessfully(res);
};
const handleChange = (file: any, fileList: any) => {
// 记录 status = 'ready' 的文件
if (file.status === 'ready') {
pendingFiles.value.push(file);
}
emit('handleChange', file, fileList);
};
@ -290,8 +298,6 @@ const handleDelete = async (index: string | number, type?: string) => {
// 上传结束处理
const uploadedSuccessfully = (res: any) => {
console.log(11121);
if (props.isImportInfo) {
emit('update:modelValue', 'ok');
fileUploadRef.value?.clearFiles();
@ -307,8 +313,13 @@ const uploadedSuccessfully = (res: any) => {
emit('update:modelValue', listToString(fileList.value));
proxy?.$modal.closeLoading();
props.onUploadSuccess?.(fileList.value, res);
}
if (props.autoUpload) {
fileUploadRef.value?.clearFiles();
fileList.value = [];
emit('update:modelValue', ''); // 同步到外部 v-model
}
props.onUploadSuccess?.(fileList.value, res);
};
// 获取文件名称
@ -334,13 +345,67 @@ const listToString = (list: any[], separator?: string) => {
return strs != '' ? strs.substring(0, strs.length - 1) : '';
};
const submitUpload = () => {
fileUploadRef.value!.submit();
// 改造后的 customUpload
const customUpload = async (options: any) => {
if (props.autoUpload) {
// 自动上传,单文件请求
try {
const formData = new FormData();
formData.append('file', options.file);
Object.entries(props.data).forEach(([k, v]) => {
if (v !== null && v !== undefined) formData.append(k, v as any);
});
const res = await axios?.({
url: realUploadUrl.value,
method: props.method,
data: formData,
headers: { 'Content-Type': 'multipart/form-data', ...headers.value }
});
handleUploadSuccess(res.data, options.file);
} catch (err) {
handleUploadError();
}
} else {
// 手动上传,不发请求,只缓存
pendingFiles.value.push(options.file);
}
};
defineExpose({
submitUpload
// 改造后的 submitUpload
const submitUpload = async () => {
if (props.autoUpload) {
fileUploadRef.value?.submit();
return;
}
if (!pendingFiles.value.length) {
return 'noFile';
}
try {
proxy?.$modal.loading('正在上传文件,请稍候...');
const formData = new FormData();
pendingFiles.value.forEach((f) => {
if (f.raw) formData.append('file', f.raw as File);
});
Object.entries(props.data).forEach(([k, v]) => {
if (v !== null && v !== undefined) formData.append(k, v as any);
});
const res = await axios?.({
url: realUploadUrl.value,
method: props.method,
data: formData,
headers: { 'Content-Type': 'multipart/form-data', ...headers.value }
});
handleUploadSuccess(res.data, {} as any);
pendingFiles.value = [];
fileUploadRef.value?.clearFiles();
} catch (err) {
handleUploadError();
} finally {
proxy?.$modal.closeLoading();
}
};
defineExpose({ submitUpload });
</script>
<style scoped lang="scss">

View File

@ -54,8 +54,6 @@ const onNewsClick = (item: any) => {
//并且写入pinia
noticeStore.state.value.notices = newsList.value;
//如果有formPath就前往
console.log(1111111111111111);
console.log(newsList.value[item]);
if (newsList.value[item].route) {
proxy?.$tab.openPage('/' + newsList.value[item].route, '', { id: newsList.value[item].detailId, type: 'view' });
}

View File

@ -6,7 +6,7 @@ export const useAppStore = defineStore('app', () => {
const sidebar = reactive({
opened: sidebarStatus.value ? !!+sidebarStatus.value : true,
withoutAnimation: false,
hide: true
hide: false
});
const device = ref<string>('desktop');
const size = useStorage<'large' | 'default' | 'small'>('size', 'default');

View File

@ -25,7 +25,6 @@ export const initSSE = (url: any) => {
});
watch(data, () => {
console.log(data.value);
let label = '';
let route1 = '';
let detailId = '';

View File

@ -23,7 +23,7 @@
<el-form
ref="leaveFormRef"
v-loading="loading"
:disabled="routeParams.type === 'view'"
:disabled="routeParams.type === 'view' || form.status == 'waiting'"
:model="form"
:rules="rules"
label-width="100px"

View File

@ -8,7 +8,6 @@
<el-button @click="disabledForm = false" class="px-8 py-2.5 transition-all duration-300 font-medium" v-if="disabledForm">
点击编辑
</el-button>
<!-- <span class="text-red-300">*</span> 为必填项 -->
</div>
<!-- 表单内容区域 -->
<el-form ref="leaveFormRef" :model="form" :disabled="disabledForm" :rules="rules" label-width="120px" class="p-6 space-y-6">
@ -46,15 +45,23 @@
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' }"
@change="() => checkDuplicate(designer, 'designers', index)"
>
<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-select
v-model="designer.userId"
placeholder="请选择设计人员"
class="transition-all duration-300 border-gray-300"
@change="() => checkDuplicate(designer, 'designers', index)"
>
<el-option v-for="item in userList" :key="item.userId" :label="item.nickName" :value="item.userId" />
</el-select>
</div>
@ -97,15 +104,23 @@
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' }"
@change="() => checkDuplicate(reviewer, 'reviewers', index)"
>
<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-select
v-model="reviewer.userId"
placeholder="请选择校审人员"
class="transition-all duration-300 border-gray-300"
@change="() => checkDuplicate(reviewer, 'reviewers', index)"
>
<el-option v-for="item in userList" :key="item.userId" :label="item.nickName" :value="item.userId" />
</el-select>
</div>
@ -146,7 +161,7 @@
</template>
<script setup name="PersonnelForm" lang="ts">
import { ref, reactive, computed, onMounted, toRefs } from 'vue';
import { ref, reactive, computed, onMounted, toRefs, watch, WatchStopHandle } from 'vue';
import { getCurrentInstance } from 'vue';
import type { ComponentInternalInstance } from 'vue';
import { useUserStoreHook } from '@/store/modules/user';
@ -184,11 +199,11 @@ const userList = ref([]);
// 表单引用
const leaveFormRef = ref();
const disabledForm = ref(false); //控制提交按钮状态
/** 查询当前部门的所有用户 */
const getDeptAllUser = async (deptId: any) => {
try {
const res = await systemUserList({ deptId });
// 实际项目中使用接口返回的数据
userList.value = res.rows;
} catch (error) {
ElMessage.error('获取用户列表失败');
@ -217,37 +232,20 @@ const designUser = async () => {
// 处理返回的数据,进行回显
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:
} else if (item.userType == 2) {
form.designers.push({
userId: item.userId,
userMajor: item.userMajor || null
});
break;
case 'reviewer':
case 3:
} else if (item.userType == 3) {
form.reviewers.push({
userId: item.userId,
userMajor: item.userMajor || null
});
break;
}
});
// 如果没有设计人员或校审人员,添加一个空项
// 补全默认空项
if (form.designers.length === 0) {
form.designers.push({ userId: null, userMajor: null });
}
@ -261,7 +259,6 @@ const designUser = async () => {
}
} catch (error) {
ElMessage.error('获取配置数据失败');
// 添加默认空项
form.designers.push({ userId: null, userMajor: null });
form.reviewers.push({ userId: null, userMajor: null });
} finally {
@ -272,7 +269,7 @@ const designUser = async () => {
/** 添加人员 */
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) {
@ -290,48 +287,112 @@ const removePerson = (type: 'designers' | 'reviewers', index: number) => {
form[type].splice(index, 1);
};
/** 提交表单 */
// ===================== 核心修改:重复校验逻辑 =====================
/**
* 校验同一角色内(设计/校审)的「专业+人员」组合唯一性
* @param current 当前操作的人员对象
* @param role 角色类型designers/reviewers
* @param currentIndex 当前操作的索引
*/
const checkDuplicate = (current: { userId: number | null; userMajor: string | null }, role: 'designers' | 'reviewers', currentIndex: number) => {
// 未选完专业/人员时不校验
if (!current.userId || !current.userMajor) return;
// 只获取当前角色的所有人员(设计只查设计,校审只查校审)
const targetList = form[role];
// 生成当前「专业+人员」唯一标识
const currentKey = `${current.userMajor}-${current.userId}`;
// 检查当前角色内是否有重复
const duplicateItem = targetList.find((item, index) => {
// 排除当前操作项本身
if (index === currentIndex) return false;
// 对比「专业+人员」组合
return `${item.userMajor}-${item.userId}` === currentKey;
});
// 存在重复时提示并清空当前选择
if (duplicateItem) {
ElMessage.warning(`当前「${getMajorLabel(current.userMajor)}+${getUserName(current.userId)}」组合已存在,请重新选择`);
// 清空当前项的选择
current.userId = null;
current.userMajor = null;
}
};
/** 辅助函数:通过专业值获取专业名称 */
const getMajorLabel = (majorValue: string | null) => {
if (!majorValue || !des_user_major.value) return '';
const major = des_user_major.value.find((item: any) => item.value === majorValue);
return major ? major.label : majorValue;
};
/** 辅助函数通过用户ID获取用户名 */
const getUserName = (userId: number | null) => {
if (!userId || !userList.value.length) return '';
const user = userList.value.find((item: any) => item.userId === userId);
return user ? user.nickName : userId;
};
/** 提交表单(补充提交前重复校验) */
const submitForm = async () => {
if (!leaveFormRef.value) return;
try {
// 表单验证
// 1. 先做基础表单验证
await leaveFormRef.value.validate();
// 构建提交数据 - 所有人员信息放在一个数组中
// 2. 提交前二次校验:确保当前角色内无重复(防止手动修改数据绕过实时校验)
let hasDuplicate = false;
// 校验设计人员
const designKeys = form.designers.map((item) => `${item.userMajor}-${item.userId}`);
if (new Set(designKeys).size !== designKeys.length) {
hasDuplicate = true;
ElMessage.error('设计人员中存在重复的「专业+人员」组合,请检查');
}
// 校验校审人员(不校验设计与校审之间)
if (!hasDuplicate) {
const reviewKeys = form.reviewers.map((item) => `${item.userMajor}-${item.userId}`);
if (new Set(reviewKeys).size !== reviewKeys.length) {
hasDuplicate = true;
ElMessage.error('校审人员中存在重复的「专业+人员」组合,请检查');
}
}
// 有重复则终止提交
if (hasDuplicate) return;
// 3. 构建提交数据(原有逻辑不变)
const submitData = {
projectId: form.projectId,
personnel: [
// 设计负责人
{
userId: form.designLeader,
userType: 'designLeader', // 设计负责人类型标识
userMajor: null // 负责人不需要专业
userType: 'designLeader',
userMajor: null
},
// 设计人员
...form.designers.map((designer) => ({
userId: designer.userId,
userType: 'designer', // 设计人员类型标识
userMajor: designer.userMajor // 包含专业信息
userType: 'designer',
userMajor: designer.userMajor
})),
// 校审人员
...form.reviewers.map((reviewer) => ({
userId: reviewer.userId,
userType: 'reviewer', // 校审人员类型标识
userMajor: reviewer.userMajor // 包含专业信息
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; // 校审人员
}
let userType = 1;
if (item1.userType === 'designer') userType = 2;
else if (item1.userType === 'reviewer') userType = 3;
arr.push({
userName: item.nickName,
projectId: submitData.projectId,
@ -343,7 +404,8 @@ const submitForm = async () => {
});
});
// 提交到后端
// 4. 提交到后端(原有逻辑不变)
const loading = ElLoading.service({ text: '提交中...', background: 'rgba(255,255,255,0.7)' });
const res = await designUserAdd({
list: arr,
projectId: currentProject.value?.id
@ -357,7 +419,6 @@ const submitForm = async () => {
} catch (error) {
ElMessage.error('请完善表单信息后再提交');
} finally {
// 关闭加载状态
ElLoading.service().close();
}
};
@ -371,22 +432,22 @@ const resetForm = () => {
ElMessage.info('表单已重置');
}
};
//监听项目id刷新数据
const listeningProject = watch(
// 监听项目ID刷新数据
const listeningProject: WatchStopHandle = watch(
() => currentProject.value?.id,
(nid, oid) => {
() => {
getDeptAllUser(userStore.deptId).then(() => {
designUser();
});
}
);
// 页面生命周期
onUnmounted(() => {
listeningProject();
listeningProject(); // 修复原代码watchStopHandle调用问题
});
// 页面挂载时初始化数据
onMounted(() => {
// 先获取用户列表,再加载表单数据
getDeptAllUser(userStore.deptId).then(() => {
designUser();
});

View File

@ -22,7 +22,7 @@
<el-form
ref="leaveFormRef"
v-loading="loading"
:disabled="routeParams.type === 'view'"
:disabled="routeParams.type === 'view' || form.status == 'waiting'"
:model="form"
:rules="rules"
label-width="100px"

View File

@ -22,7 +22,7 @@
<el-form
ref="leaveFormRef"
v-loading="loading"
:disabled="routeParams.type === 'view'"
:disabled="routeParams.type === 'view' || form.status == 'waiting'"
:model="form"
:rules="rules"
label-width="100px"

View File

@ -12,7 +12,14 @@
<h3 class="text-lg font-semibold text-gray-800">下发变更通知信息</h3>
</div>
<div class="p-6">
<el-form ref="leaveFormRef" :disabled="routeParams.type === 'view'" :model="form" :rules="rules" label-width="100px" class="space-y-4">
<el-form
ref="leaveFormRef"
:disabled="routeParams.type === 'view' || form.status == 'waiting'"
: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">

View File

@ -19,7 +19,14 @@
<h3 class="text-lg font-semibold text-gray-800">变更图纸信息</h3>
</div>
<div class="p-6">
<el-form ref="leaveFormRef" :disabled="routeParams.type === 'view'" :model="form" :rules="rules" label-width="100px" class="space-y-4">
<el-form
ref="leaveFormRef"
:disabled="routeParams.type === 'view' || form.status == 'waiting'"
:model="form"
:rules="rules"
label-width="100px"
class="space-y-4"
>
<div class="grid grid-cols-1 md:grid-cols-2 gap-4">
<el-form-item label="图纸文件" prop="fileId" class="mb-2 md:col-span-2">
<file-upload :fileType="['pdf']" :fileSize="''" v-model="form.fileId" class="w-full"></file-upload>

View File

@ -19,23 +19,20 @@
<h3 class="text-lg font-semibold text-gray-800">图纸评审</h3>
</div>
<div class="p-6">
<div class="grid grid-cols-1 gap-4">
<el-form
ref="leaveFormRef"
v-loading="loading"
:disabled="routeParams.type === 'view'"
:disabled="routeParams.type === 'view' || form.auditStatus == 'waiting'"
:model="form"
:rules="rules"
label-width="100px"
class="space-y-4"
>
<div class="grid grid-cols-1 gap-4">
<el-form ref="leaveFormRef" :disabled="routeParams.type === 'view'" :model="form" :rules="rules" label-width="100px" class="space-y-4">
<el-form-item label="图纸文件" v-for="value in form.fileVoList" :key="value.id" prop="fileId" class="mb-2 md:col-span-2">
<el-input v-model="value.fileName" disabled placeholder="图纸名称" />
</el-form-item>
</el-form>
</div>
</el-form>
</div>
</el-card>
<!-- 提交组件 -->

View File

@ -23,7 +23,7 @@
<el-form
ref="leaveFormRef"
v-loading="loading"
:disabled="routeParams.type === 'view'"
:disabled="routeParams.type === 'view' || form.status == 'waiting' || form.status == 'waiting'"
:model="form"
:rules="rules"
label-width="120px"

View File

@ -23,7 +23,7 @@
<el-form
ref="leaveFormRef"
v-loading="loading"
:disabled="routeParams.type === 'view'"
:disabled="routeParams.type === 'view' || form.status == 'waiting'"
:model="form"
:rules="rules"
label-width="120px"

View File

@ -23,7 +23,7 @@
<el-form
ref="leaveFormRef"
v-loading="loading"
:disabled="routeParams.type === 'view'"
:disabled="routeParams.type === 'view' || form.status == 'waiting'"
:model="form"
:rules="rules"
label-width="120px"

View File

@ -22,7 +22,7 @@
<el-form
ref="leaveFormRef"
v-loading="loading"
:disabled="routeParams.type === 'view'"
:disabled="routeParams.type === 'view' || form.status == 'waiting'"
:model="form"
:rules="rules"
label-width="100px"

View File

@ -79,16 +79,25 @@
<el-table-column label="办理状态" align="center" prop="processingStatus" />
<el-table-column label="手续材料" align="center" prop="formalitiesUrl" width="180">
<template #default="scope">
<el-link type="primary" :underline="false" :href="scope.row.formalitiesUrl" target="_blank" v-if="scope.row.formalitiesUrl">查看</el-link>
<el-link type="primary" :underline="false" @click="handlePreview(scope.row)" target="_blank">查看</el-link>
</template>
</el-table-column>
<el-table-column label="备注" align="center" prop="remark" />
<el-table-column label="操作" align="center" class-name="small-padding fixed-width">
<template #default="scope">
<div v-if="scope.row.status != 1">
<el-button link type="primary" icon="Edit" @click="handleUpdate(scope.row)" v-hasPermi="['formalities:formalitiesAreConsolidated:edit']"
>修改</el-button
>
<el-button
link
type="primary"
icon="Upload"
@click="handleUpload(scope.row)"
v-hasPermi="['formalities:formalitiesAreConsolidated:edit']"
>上传</el-button
>
<el-button
link
type="primary"
@ -97,6 +106,7 @@
v-hasPermi="['formalities:formalitiesAreConsolidated:edit']"
>修改状态</el-button
>
</div>
</template>
</el-table-column>
</el-table>
@ -116,18 +126,6 @@
<el-form-item label="备注" prop="remark">
<el-input v-model="form.remark" placeholder="请输入备注" />
</el-form-item>
<el-form-item label="上传文件" prop="processingStatus">
<file-upload
v-model="file"
ref="uploadRef"
uploadUrl="/formalities/formalitiesAreConsolidated/edit"
:data="{ ...form }"
:auto-upload="false"
showFileList
method="put"
:onUploadSuccess="handleUploadSuccess"
/>
</el-form-item>
</el-form>
<template #footer>
<div class="dialog-footer">
@ -136,6 +134,55 @@
</div>
</template>
</el-dialog>
<el-dialog draggable title="文件列表" v-model="viewVisible" width="45%">
<el-table :data="fileList" style="width: 100%" border v-loading="fileLoading">
<el-table-column prop="fileName" label="文件" align="center">
<template #default="scope">
<el-link :key="scope.row.annexUrl" :href="scope.row.annexUrl" target="_blank" type="primary" :underline="false">
{{ scope.row.fileName || '查看文件' }}
</el-link>
</template>
</el-table-column>
<el-table-column label="操作" width="90" align="center" v-if="fileStatus != 1">
<template #default="scope">
<el-button type="danger" link icon="Delete" @click="handleDeleteFile(scope.row)"> 删除 </el-button>
</template>
</el-table-column>
</el-table>
<pagination
v-show="fileTotal > 0"
:total="fileTotal"
v-model:page="fileParams.pageNum"
v-model:limit="fileParams.pageSize"
@pagination="getFileList"
/>
<template #footer>
<span>
<el-button type="primary" @click="viewVisible = false">关闭</el-button>
</span>
</template>
</el-dialog>
<!-- 上传文件对话框 -->
<el-dialog draggable title="上传文件" v-model="fileVisible" width="45%">
<el-form-item label="上传文件" prop="processingStatus">
<file-upload
v-model="file"
ref="uploadRef"
uploadUrl="/formalities/formalitiesAnnex"
:data="{ formalitiesId: form.id }"
:auto-upload="false"
showFileList
method="put"
:onUploadSuccess="handleUploadSuccess"
/>
</el-form-item>
<template #footer>
<span>
<el-button :loading="buttonLoading" type="primary" @click="submitFileForm"> </el-button>
<el-button @click="fileVisible = false"> </el-button>
</span>
</template>
</el-dialog>
</div>
</template>
@ -146,6 +193,8 @@ import {
delFormalitiesAreConsolidated,
addFormalitiesAreConsolidated,
updateFormalitiesAreConsolidated,
listFormalitiesAnnex,
delFormalitiesAnnex,
editStatus
} from '@/api/formalities/formalitiesAreConsolidated';
import {
@ -154,8 +203,7 @@ import {
FormalitiesAreConsolidatedForm
} from '@/api/formalities/formalitiesAreConsolidated/types';
import { useUserStoreHook } from '@/store/modules/user';
import { json } from 'stream/consumers';
const fileVisible = ref(false);
const { proxy } = getCurrentInstance() as ComponentInternalInstance;
// 获取用户 store
const userStore = useUserStoreHook();
@ -164,6 +212,8 @@ const currentProject = computed(() => userStore.selectedProject);
const formalitiesAreConsolidatedList = ref<FormalitiesAreConsolidatedVO[]>([]);
const buttonLoading = ref(false);
const loading = ref(true);
const fileLoading = ref(false);
const showSearch = ref(true);
const ids = ref<Array<string | number>>([]);
const single = ref(true);
@ -172,12 +222,20 @@ const total = ref(0);
const uploadRef = ref();
const queryFormRef = ref<ElFormInstance>();
const formalitiesAreConsolidatedFormRef = ref<ElFormInstance>();
const fileList = ref([]);
const fileTotal = ref(0);
const viewVisible = ref(false);
const fileStatus = ref(0);
const dialog = reactive<DialogOption>({
visible: false,
title: ''
});
const file = ref(null);
const fileParams = reactive({
pageNum: 1,
pageSize: 10,
formalitiesId: undefined
});
const initFormData: FormalitiesAreConsolidatedForm = {
id: undefined,
projectId: currentProject.value?.id,
@ -246,11 +304,14 @@ const handleSelectionChange = (selection: FormalitiesAreConsolidatedVO[]) => {
multiple.value = !selection.length;
};
/** 新增按钮操作 */
const handleAdd = () => {
reset();
dialog.visible = true;
dialog.title = '添加合规性手续合账';
/** 删除文件按钮操作 */
const handleDeleteFile = async (row) => {
await proxy?.$modal.confirm('是否确认删除文件编号为"' + row.id + '"的数据项?').finally(() => (fileLoading.value = false));
fileLoading.value = true;
await delFormalitiesAnnex(row.id);
proxy?.$modal.msgSuccess('删除成功');
await getFileList();
};
/** 修改按钮操作 */
@ -263,6 +324,15 @@ const handleUpdate = async (row?: FormalitiesAreConsolidatedVO) => {
dialog.title = '修改合规性手续合账';
};
/** 上传按钮操作 */
const handleUpload = (row) => {
form.value.id = row.id;
fileList.value = [];
file.value = null;
fileVisible.value = true;
};
const handleUpdateStatus = async (row?: FormalitiesAreConsolidatedVO) => {
await proxy?.$modal.confirm('是否确认修改状态?').finally(() => (loading.value = false));
@ -276,30 +346,43 @@ const handleUpdateStatus = async (row?: FormalitiesAreConsolidatedVO) => {
const submitForm = () => {
formalitiesAreConsolidatedFormRef.value?.validate(async (valid: boolean) => {
if (valid) {
for (const key in form.value) {
if (form.value[key] === null) {
delete form.value[key];
updateFormalitiesAreConsolidated(form.value).then(() => {
proxy?.$modal.msgSuccess('修改成功');
dialog.visible = false;
getList();
});
}
}
const res = uploadRef.value.submitUpload();
console.log(res);
});
};
const submitFileForm = () => {
uploadRef.value.submitUpload().then((res) => {
if (res === 'noFile') {
proxy?.$modal.msgWarning('请先选择文件');
}
});
};
const handleUploadSuccess = async () => {
proxy?.$modal.msgSuccess('上传成功');
dialog.visible = false;
fileVisible.value = false;
await getList();
};
/** 删除按钮操作 */
const handleDelete = async (row?: FormalitiesAreConsolidatedVO) => {
const _ids = row?.id || ids.value;
await proxy?.$modal.confirm('是否确认删除合规性手续合账编号为"' + _ids + '"的数据项?').finally(() => (loading.value = false));
await delFormalitiesAreConsolidated(_ids);
proxy?.$modal.msgSuccess('删除成功');
await getList();
const handlePreview = async (row?: FormalitiesAreConsolidatedVO) => {
viewVisible.value = true;
fileLoading.value = true;
fileParams.formalitiesId = row.id;
fileStatus.value = row.status;
getFileList();
};
const getFileList = async () => {
const res = await listFormalitiesAnnex(fileParams);
fileList.value = res.rows;
fileTotal.value = res.total;
fileLoading.value = false;
};
/** 导出按钮操作 */
@ -316,12 +399,6 @@ const handleExport = () => {
onMounted(() => {
getList();
});
const formData = new FormData();
let arr = [];
formData.append('file', JSON.stringify(arr));
formData.append('bo', JSON.stringify({}));
//监听项目id刷新数据
const listeningProject = watch(
() => currentProject.value?.id,

View File

@ -1,5 +1,7 @@
<template>
<div class="p-2">
<formalitiesAreConsolidated ref="formalitiesAreConsolidatedRef" class="overlay" v-if="showFormalitiesAreConsolidated" />
<div class="p-2" v-else>
<transition :enter-active-class="proxy?.animate.searchAnimate.enter" :leave-active-class="proxy?.animate.searchAnimate.leave">
<div v-show="showSearch" class="mb-[10px]">
<el-card shadow="hover">
@ -27,27 +29,6 @@
>确认</el-button
>
</el-col>
<!-- <el-col :span="1.5">
<el-button type="success" plain icon="Edit" :disabled="single" @click="handleUpdate()" v-hasPermi="['formalities:listOfFormalities:edit']"
>修改</el-button
>
</el-col>
<el-col :span="1.5">
<el-button
type="danger"
plain
icon="Delete"
:disabled="multiple"
@click="handleDelete()"
v-hasPermi="['formalities:listOfFormalities:remove']"
>删除</el-button
>
</el-col>
<el-col :span="1.5">
<el-button type="warning" plain icon="Download" @click="handleExport" v-hasPermi="['formalities:listOfFormalities:export']"
>导出</el-button
>
</el-col> -->
<right-toolbar v-model:showSearch="showSearch" @queryTable="getList"></right-toolbar>
</el-row>
</template>
@ -55,38 +36,18 @@
<el-table v-loading="loading" :data="listOfFormalitiesList" @selection-change="handleSelectionChange" row-key="id" default-expand-all>
<el-table-column type="selection" width="55" align="center" />
<el-table-column label="名称" prop="name" />
<!-- <el-table-column label="操作" align="center" class-name="small-padding fixed-width">
<template #default="scope">
<el-tooltip content="修改" placement="top">
<el-button
link
type="primary"
icon="Edit"
@click="handleUpdate(scope.row)"
v-hasPermi="['formalities:listOfFormalities:edit']"
></el-button>
</el-tooltip>
<el-tooltip content="删除" placement="top">
<el-button
link
type="primary"
icon="Delete"
@click="handleDelete(scope.row)"
v-hasPermi="['formalities:listOfFormalities:remove']"
></el-button>
</el-tooltip>
</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>
<!-- 添加或修改手续办理清单模板对话框 -->
<el-dialog :title="dialog.title" v-model="dialog.visible" width="500px" append-to-body>
<el-form ref="listOfFormalitiesFormRef" :model="form" :rules="rules" label-width="80px">
<!-- <el-form-item label="父级id" prop="pid">
<el-input v-model="form.pid" placeholder="请输入父级id" />
</el-form-item> -->
<el-form-item label="父级" prop="pid">
<el-select v-model="form.pid" placeholder="请选择父级">
<el-option label="根目录" value="0" />
<el-option v-for="item in listOfFormalitiesList" :label="item.name" :value="item.id" />
</el-select>
</el-form-item>
<el-form-item label="名称" prop="name">
<el-input v-model="form.name" placeholder="请输入名称" />
</el-form-item>
@ -108,11 +69,12 @@ import {
getListOfFormalities,
delListOfFormalities,
addListOfFormalities,
updateListOfFormalities
updateListOfFormalities,
getWhetherItExists
} from '@/api/formalities/listOfFormalities';
import { ListOfFormalitiesVO, ListOfFormalitiesQuery, ListOfFormalitiesForm } from '@/api/formalities/listOfFormalities/types';
import { useUserStoreHook } from '@/store/modules/user';
import formalitiesAreConsolidated from '@/views/formalities/formalitiesAreConsolidated/index.vue';
const { proxy } = getCurrentInstance() as ComponentInternalInstance;
// 获取用户 store
const userStore = useUserStoreHook();
@ -135,6 +97,8 @@ const dialog = reactive<DialogOption>({
title: ''
});
const showFormalitiesAreConsolidated = ref(false);
const initFormData: ListOfFormalitiesForm = {
id: undefined,
pid: undefined,
@ -220,7 +184,7 @@ const handleOk = async () => {
const res = await addFormalitiesAreConsolidated(data);
if (res.code == 200) {
proxy?.$modal.msgSuccess('操作成功');
proxy?.$tab.openPage('/formalities/formalitiesAreConsolidated');
showFormalitiesAreConsolidated.value = true;
}
};
@ -272,6 +236,33 @@ const handleExport = () => {
};
onMounted(() => {
getWhetherItExists(currentProject.value.id).then((res) => {
if (res.data) {
showFormalitiesAreConsolidated.value = true;
return;
}
getList();
});
});
//监听项目id刷新数据
const listeningProject = watch(
() => currentProject.value?.id,
(nid, oid) => {
getWhetherItExists(currentProject.value.id).then((res) => {
if (res.data) {
showFormalitiesAreConsolidated.value = true;
return;
}
showFormalitiesAreConsolidated.value = false;
getList();
});
}
);
onUnmounted(() => {
listeningProject();
});
</script>
<style scoped lang="scss"></style>

View File

@ -1,5 +1,5 @@
<template>
<el-dialog v-model="isShowDialog" title="变更单详情" draggable width="60vw" :close-on-click-modal="false" :destroy-on-close="true">
<el-dialog v-model="isShowDialog" title="材料设备详情" draggable width="1200px" :close-on-click-modal="false" :destroy-on-close="true">
<el-card :body-style="{ padding: '20px' }" style="border: none; box-shadow: none">
<div class="dialog-footer">
<div class="btn-item" @click="onLoad">
@ -46,26 +46,26 @@
</tbody>
<thead>
<tr>
<th width="150">序号</th>
<th width="150">名称</th>
<th width="150">规格</th>
<th width="150">单位</th>
<th width="150">数量</th>
<th width="150">验收</th>
<th width="150">缺件</th>
<th width="150">备注</th>
<td width="150">序号</td>
<td width="150">名称</td>
<td width="150">规格</td>
<td width="150">单位</td>
<td width="150">数量</td>
<td width="150">验收</td>
<td width="150">缺件</td>
<td width="150">备注</td>
</tr>
</thead>
<tbody>
<tr v-for="(item, i) of formData.itemList" :key="i">
<th width="150">{{ i + 1 }}</th>
<th width="150">{{ item.name }}</th>
<th width="150">{{ item.specification }}</th>
<th width="150">{{ item.unit }}</th>
<th width="150">{{ item.quantity }}</th>
<th width="150">{{ item.acceptedQuantity }}</th>
<th width="150">{{ item.shortageQuantity }}</th>
<th width="150">{{ item.remark }}</th>
<td width="150">{{ i + 1 }}</td>
<td width="150">{{ item.name }}</td>
<td width="150">{{ item.specification }}</td>
<td width="150">{{ item.unit }}</td>
<td width="150">{{ item.quantity }}</td>
<td width="150">{{ item.acceptedQuantity }}</td>
<td width="150">{{ item.shortageQuantity }}</td>
<td width="150">{{ item.remark }}</td>
</tr>
</tbody>
<tbody>

View File

@ -27,6 +27,7 @@
<el-table-column prop="num" label="编号" />
<el-table-column prop="name" label="工程或费用名称" width="180" />
<el-table-column prop="unit" label="单位" />
<el-table-column prop="specification" label="规格型号" />
<el-table-column prop="quantity" label="数量" width="60" />
<el-table-column prop="batchNumber" label="批次号" width="200" />
<el-table-column prop="brand" label="品牌" />

View File

@ -3,18 +3,23 @@
<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" />
<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">
<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' || routeParams.type === 'update'" :model="form"
<!-- <el-form ref="leaveFormRef" v-loading="loading" :disabled="routeParams.type === 'view' || form.status == 'waiting' || routeParams.type === 'update'" :model="form"
:rules="rules" label-width="100px" class="space-y-4">
<el-row :gutter="20">
<el-col :span="12">
@ -81,8 +86,14 @@
<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">
<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%">
@ -91,10 +102,12 @@
</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>
<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>

View File

@ -0,0 +1,244 @@
<template>
<el-drawer v-model="drawer" :direction="direction" size="40%" :before-close="handleBeforeClose" title-class="drawer-title">
<template #header>
<span class="font-bold text-lg text-gray-800">物流信息</span>
</template>
<template #default>
<!-- 物流头部信息 -->
<div class="bg-white rounded-lg shadow-md p-5 mb-6">
<div class="flex flex-col md:flex-row md:items-center justify-between gap-6">
<!-- 左侧快递基本信息 -->
<div class="flex items-center gap-6">
<div class="w-14 h-14 rounded-md overflow-hidden border border-gray-100 flex items-center justify-center">
<img
:src="logisticsData?.result.logo"
alt="快递公司Logo"
class="w-full h-full object-contain"
:onerror="`this.src='https://via.placeholder.com/48x48?text=暂无Logo'`"
/>
</div>
<div class="text-sm">
<p class="text-gray-500">快递单号</p>
<p class="font-medium text-gray-900">{{ logisticsData?.result.number }}</p>
<p class="text-gray-500 mt-1">{{ logisticsData?.result.expName }} | 最新更新: {{ logisticsData?.result.updateTime }}</p>
</div>
<div class="ml-auto">
<el-tag :type="getStatusType(logisticsData?.result.deliverystatus)" size="medium" class="px-4 py-1">
{{ getStatusText(logisticsData?.result.deliverystatus) }}
</el-tag>
<p class="text-gray-500 text-sm mt-2 text-right">耗时: {{ logisticsData?.result.takeTime || '暂无数据' }}</p>
</div>
</div>
</div>
</div>
<!-- 快递员信息有数据才显示 -->
<div v-if="logisticsData?.result.courier" class="bg-blue-50 rounded-lg p-4 mb-6 border-l-4 border-blue-400">
<div class="flex items-center justify-between">
<p class="font-medium text-blue-800">配送信息</p>
<a :href="`tel:${logisticsData?.result.courierPhone}`" class="text-blue-600 hover:text-blue-800 text-sm flex items-center gap-1">
<el-icon class="el-icon-phone"></el-icon>
联系快递员
</a>
</div>
<div class="flex flex-wrap gap-x-8 gap-y-3 mt-3 text-gray-700">
<div class="flex items-center gap-2">
<el-icon class="el-icon-user text-gray-500"></el-icon>
<span>快递员: {{ logisticsData?.result.courier }}</span>
</div>
<div class="flex items-center gap-2">
<el-icon class="el-icon-phone-outline text-gray-500"></el-icon>
<span>电话: {{ logisticsData?.result.courierPhone || '暂无' }}</span>
</div>
<div class="flex items-center gap-2">
<el-icon class="el-icon-service text-gray-500"></el-icon>
<span>客服: {{ logisticsData?.result.expPhone }}</span>
</div>
</div>
</div>
<!-- 物流轨迹列表 -->
<div class="bg-white rounded-lg shadow-md p-5">
<p class="font-medium text-gray-800 mb-4">物流轨迹{{ logisticsData?.result.list.length || 0 }}</p>
<div class="relative" style="border-left: 1px solid #d9d9d9; padding-left: 15px">
<div v-for="(item, index) in logisticsData?.result.list" :key="index" class="flex mb-8 relative">
<div class="flex flex-col items-center mr-6 z-10">
<div
:class="[
'w-8 h-8 rounded-full flex items-center justify-center',
index === 0 ? 'bg-blue-500 text-white' : 'bg-white border border-gray-300 text-gray-500'
]"
>
<el-icon v-if="index === 0" class="el-icon-check text-xs"></el-icon>
<span v-else class="text-xs">{{ index + 1 }}</span>
</div>
<p class="text-xs text-gray-500 mt-2">{{ item.time }}</p>
</div>
<div class="flex-1 bg-gray-50 rounded-lg p-4 border border-gray-100 shadow-sm">
<p class="text-gray-800">{{ item.status }}</p>
</div>
</div>
</div>
</div>
</template>
<template #footer>
<div class="drawer-footer">
<el-button @click="close" :loading="cancelLoading" class="mr-3">关闭</el-button>
</div>
</template>
</el-drawer>
</template>
<script setup lang="ts">
import { ref } from 'vue';
import type { DrawerProps } from 'element-plus';
import { Phone, PhoneOutline, User, Service, Check } from '@element-plus/icons-vue';
// 抽屉方向
const direction = ref<DrawerProps['direction']>('ltr');
// 加载状态
const cancelLoading = ref(false);
const confirmLoading = ref(false);
// 抽屉显隐
const drawer = ref(false);
// 物流数据(初始化为接口返回格式)
const logisticsData = ref({
status: '0',
msg: 'ok',
result: {
number: '',
type: '',
list: [],
deliverystatus: '0',
issign: '0',
expName: '',
expSite: '',
expPhone: '',
courier: '',
courierPhone: '',
updateTime: '',
takeTime: '',
logo: ''
}
});
/**
* 根据物流状态获取标签类型
* @param status 物流状态码
*/
const getStatusType = (status?: string) => {
switch (status) {
case '0': // 揽件
return 'info';
case '1': // 在途中
return 'warning';
case '2': // 派件中
return 'primary';
case '3': // 已签收
return 'success';
case '4': // 派送失败
case '5': // 疑难件
return 'danger';
case '6': // 退件签收
return 'error';
default:
return 'default';
}
};
/**
* 根据物流状态获取文本描述
* @param status 物流状态码
*/
const getStatusText = (status?: string) => {
const statusMap: Record<string, string> = {
'0': '快递收件(揽件)',
'1': '运输途中',
'2': '正在派件',
'3': '已签收',
'4': '派送失败',
'5': '疑难件',
'6': '退件签收'
};
return statusMap[status || '0'] || '未知状态';
};
/**
* 打开抽屉并加载物流数据
*/
const open = (data) => {
const mockData = {
result: data
};
logisticsData.value = mockData;
drawer.value = true;
};
/**
* 关闭抽屉
*/
const close = () => {
drawer.value = false;
};
/**
* 抽屉关闭前钩子(可用于拦截关闭逻辑)
*/
const handleBeforeClose = (done: () => void) => {
done(); // 直接关闭,如需确认可添加弹窗逻辑
};
// 暴露加载状态控制方法
const setCancelLoading = (loading: boolean) => {
cancelLoading.value = loading;
};
const setConfirmLoading = (loading: boolean) => {
confirmLoading.value = loading;
};
// 暴露方法供父组件调用
defineExpose({
open,
setCancelLoading,
setConfirmLoading
});
</script>
<style scoped>
.drawer-title {
padding-bottom: 8px;
border-bottom: 1px solid #f2f2f2;
}
.drawer-footer {
display: flex;
justify-content: flex-end;
gap: 12px;
padding: 16px;
border-top: 1px solid #eee;
}
:deep(.el-drawer__body) {
padding: 20px;
overflow-y: auto;
max-height: calc(100vh - 160px);
}
:deep(.el-tag) {
border-radius: 4px;
}
@media (max-width: 768px) {
:deep(.el-drawer) {
width: 95% !important;
}
.drawer-footer {
flex-direction: column;
}
:deep(.drawer-footer .el-button) {
width: 100%;
}
}
</style>

View File

@ -31,8 +31,8 @@
</el-row>
</template>
<el-table v-loading="loading" :data="purchaseDocList" @selection-change="handleSelectionChange">
<el-table-column type="selection" width="55" align="center" />
<el-table-column label="采购单编号" align="center" prop="docCode" width="90" />
<el-table-column type="index" width="60" label="序号" align="center" />
<el-table-column label="采购单编号" align="center" prop="docCode" width="150" />
<el-table-column label="批次号" align="center" prop="mrpBaseId">
<template #default="scope">
{{ batchOptions.find((item) => item.id == scope.row.mrpBaseId)?.planCode }}
@ -220,11 +220,16 @@
</template>
</el-dialog>
<!-- 查看文件列表 -->
<el-dialog title="文件列表" v-model="viewVisible" width="45%">
<el-dialog title="物流单号" v-model="viewVisible" width="45%">
<el-table v-if="fileList.length > 0" :data="fileList" style="width: 100%" border>
<el-table-column label="单号" align="center" prop="ltn" />
<el-table-column label="数量" align="center" prop="num" />
<el-table-column label="物资名称" align="center" prop="name" />
<el-table-column label="规格型号" align="center" prop="specification">
<template #default="scope">
<el-button link type="primary" icon="Finished" @click="getDetailList(scope.row.ltn)"> 查看物流信息</el-button></template
>
</el-table-column>
</el-table>
<div v-else class="empty-list text-center">暂无文件</div>
<template #footer>
@ -233,17 +238,19 @@
</span>
</template>
</el-dialog>
<logisticsDetail ref="logisticsDetailRef"></logisticsDetail>
</div>
</template>
<script setup name="PurchaseDoc" lang="ts">
import { getBatch, listBatch } from '@/api/materials/batchPlan';
import { listPurchaseDoc, getPurchaseDoc, listLink, addPurchaseDoc, updatePurchaseDoc } from '@/api/materials/purchaseDoc';
import { listPurchaseDoc, getPurchaseDoc, listLink, addPurchaseDoc, updatePurchaseDoc, logisticsDetial } from '@/api/materials/purchaseDoc';
import { PurchaseDocVO, PurchaseDocQuery, PurchaseDocForm } from '@/api/materials/purchaseDoc/types';
import { listContractor } from '@/api/project/contractor';
import { useUserStoreHook } from '@/store/modules/user';
import { getToken } from '@/utils/auth';
import logisticsDetail from './comm/logisticsDetail.vue';
import type { DrawerProps } from 'element-plus';
const { proxy } = getCurrentInstance() as ComponentInternalInstance;
const route = useRoute();
const router = useRouter();
@ -262,10 +269,11 @@ const single = ref(true);
const multiple = ref(true);
const total = ref(0);
const feedbackUrl = ref('');
// 组件
const logisticsDetailRef = ref<InstanceType<typeof logisticsDetail>>();
const queryFormRef = ref<ElFormInstance>();
const purchaseDocFormRef = ref<ElFormInstance>();
const IP = 'http://192.168.110.151:7788';
const dialog = reactive<DialogOption>({
visible: false,
title: ''
@ -480,8 +488,8 @@ const handleShare = async (row?: PurchaseDocVO) => {
});
// 获取当前域名地址
console.log(location);
textarea.value = IP + '/materials/purchaseDoc/uploadCode?data=' + data;
// textarea.value = location.host + '/materials/purchaseDoc/uploadCode?data=' + data;
// textarea.value = IP + '/materials/purchaseDoc/uploadCode?data=' + data;
textarea.value = location.host + '/materials/purchaseDoc/uploadCode?data=' + data;
textarea.style.position = 'fixed';
textarea.style.opacity = '0';
document.body.appendChild(textarea);
@ -530,6 +538,12 @@ const handleViewDetail = async (row?: PurchaseDocVO) => {
type: 'view'
});
};
const getDetailList = async (id) => {
let res = await logisticsDetial(id);
if (res.code == 200) {
logisticsDetailRef.value.open(res.data);
}
};
onMounted(() => {
getList();

View File

@ -22,7 +22,7 @@
<el-form
ref="leaveFormRef"
v-loading="loading"
:disabled="routeParams.type === 'view'"
:disabled="routeParams.type === 'view' || form.auditStatus == 'waiting'"
:model="form"
:rules="rules"
label-width="120px"

View File

@ -22,7 +22,7 @@
<el-form
ref="leaveFormRef"
v-loading="loading"
:disabled="routeParams.type === 'view'"
:disabled="routeParams.type === 'view' || form.completeAuditStatus == 'waiting'"
:model="form"
:rules="rules"
label-width="120px"

View File

@ -22,7 +22,7 @@
<el-form
ref="leaveFormRef"
v-loading="loading"
:disabled="routeParams.type === 'view'"
:disabled="routeParams.type === 'view' || form.status == 'waiting'"
:model="form"
:rules="rules"
label-width="120px"

View File

@ -12,7 +12,14 @@
/>
</el-card>
<el-card shadow="never" style="height: 78vh; overflow-y: auto">
<el-form ref="leaveFormRef" v-loading="loading" :disabled="routeParams.type === 'view'" :model="form" :rules="rules" label-width="80px">
<el-form
ref="leaveFormRef"
v-loading="loading"
:disabled="routeParams.type === 'view' || form.status == 'waiting'"
:model="form"
:rules="rules"
label-width="80px"
>
<el-form-item label="请假类型" prop="leaveType">
<el-select v-model="form.leaveType" placeholder="请选择请假类型" style="width: 100%">
<el-option v-for="item in options" :key="item.value" :label="item.label" :value="item.value" />