This commit is contained in:
Teo
2025-09-04 11:06:45 +08:00
parent 9d1f96309f
commit 910b24019e
83 changed files with 8390 additions and 834 deletions

View File

@ -8,7 +8,7 @@ VITE_APP_ENV = 'development'
VITE_APP_BASE_API = 'http://192.168.110.209:8899'
# VITE_APP_BASE_API = 'http://58.17.134.85:8899'
# GO开发环境
VITE_APP_BASE_API_GO = 'http://58.17.134.85:8919'
VITE_APP_BASE_API_GO = 'http://192.168.110.188:8919'
# 无人机接口地址

View File

@ -38,6 +38,7 @@
"echarts-gl": "^2.0.9",
"element-plus": "2.8.8",
"esbuild": "^0.25.0",
"exceljs": "^4.4.0",
"ezuikit-js": "^8.1.10",
"file-saver": "^2.0.5",
"fuse.js": "7.0.0",

View File

@ -131,6 +131,8 @@ export function getGoToken(): AxiosPromise<any> {
verifyCode: '1111',
username: 'admin',
password: 'zmkg@2023A'
// username: 'admin1',
// password: 'zmkg@2023C'
}
});
}

View File

@ -57,8 +57,9 @@ export const updateYs7DeviceImg = (data: Ys7DeviceImgForm) => {
* @param id
*/
export const delYs7DeviceImg = (id: string | number | Array<string | number>) => {
return request({
url: '/other/ys7DeviceImg/' + id,
method: 'delete'
return request1({
url: '/zm/api/v1/system/ys7DevicesImg/delete',
method: 'delete',
data: { ids: id }
});
};

View File

@ -9,6 +9,7 @@ import {
AttendanceMonthVO,
AttendanceMonthQuery
} from '@/api/project/attendance/types';
import requestGo from '@/utils/request-go';
/**
* 查询考勤列表
@ -45,8 +46,8 @@ export const listAttendanceTwoWeek = (query?: AttendanceTwoWeekQuery): AxiosProm
*/
export const listAttendanceMonth = (query?: AttendanceMonthQuery): AxiosPromise<AttendanceMonthVO[]> => {
return request({
url: '/project/attendance/list/month/byUserId',
return requestGo({
url: '/zm/api/v1/system/busConstructionUser/pcQueryBasedOnOpenid',
method: 'get',
params: query
});

View File

@ -1,6 +1,7 @@
import request from '@/utils/request';
import { AxiosPromise } from 'axios';
import { ConstructionBlacklistVO, ConstructionBlacklistForm, ConstructionBlacklistQuery } from '@/api/project/constructionBlacklist/types';
import requestGo from '@/utils/request-go';
/**
* 查询黑名单列表
@ -32,8 +33,8 @@ export const getConstructionBlacklist = (id: string | number): AxiosPromise<Cons
* @param data
*/
export const addConstructionBlacklist = (data: ConstructionBlacklistForm) => {
return request({
url: '/project/constructionBlacklist',
return requestGo({
url: '/zm/api/v1/system/busConstructionBlacklist/add',
method: 'post',
data: data
});
@ -56,8 +57,11 @@ export const updateConstructionBlacklist = (data: ConstructionBlacklistForm) =>
* @param id
*/
export const delConstructionBlacklist = (id: string | number | Array<string | number>) => {
return request({
url: '/project/constructionBlacklist/' + id,
method: 'delete'
return requestGo({
url: '/zm/api/v1/system/busConstructionBlacklist/delete',
method: 'delete',
data: {
openids: id
}
});
};

View File

@ -14,6 +14,7 @@ import {
ConstructionMonthQuery
} from '@/api/project/constructionUser/types';
import { AttendanceMonthVO } from '../attendance/types';
import requestGo from '@/utils/request-go';
/**
* 查询施工人员月份考勤列表
@ -23,7 +24,7 @@ import { AttendanceMonthVO } from '../attendance/types';
export const listConstructionMonth = (query?: ConstructionMonthQuery): AxiosPromise<AttendanceMonthVO[]> => {
return request({
url: '/contractor/constructionUser/list/attendance/month',
url: '/zm/api/wxApplet/wxApplet/busAttendance/byOpenId',
method: 'get',
params: query
});
@ -35,8 +36,22 @@ export const listConstructionMonth = (query?: ConstructionMonthQuery): AxiosProm
*/
export const listConstructionUser = (query?: ConstructionUserQuery): AxiosPromise<ConstructionUserVO[]> => {
return request({
url: '/contractor/constructionUser/list',
return requestGo({
url: '/zm/api/wxApplet/wxApplet/busConstructionUser/personnelInquiry',
method: 'get',
params: query
});
};
/**
* 查询施工人员列表
* @param query
* @returns {*}
*/
export const listConstructionUserInTeam = (query?: ConstructionUserQuery): AxiosPromise<ConstructionUserVO[]> => {
return requestGo({
url: '/zm/api/wxApplet/wxApplet/busConstructionUser/list',
method: 'get',
params: query
});
@ -48,7 +63,7 @@ export const listConstructionUser = (query?: ConstructionUserQuery): AxiosPromis
*/
export const getConstructionUser = (id: string | number): AxiosPromise<ConstructionUserVO> => {
return request({
url: '/contractor/constructionUser/' + id,
url: '/zm/api/wxApplet/wxApplet/busConstructionUser/getDetails?id=' + id,
method: 'get'
});
};
@ -59,7 +74,7 @@ export const getConstructionUser = (id: string | number): AxiosPromise<Construct
*/
export const transferConstructionUser = (data: skipType) => {
return request({
url: '/contractor/constructionUser/change/project',
url: '/zm/api/wxApplet/wxApplet/busConstructionUser/changePay',
method: 'put',
data: data
});
@ -70,7 +85,7 @@ export const transferConstructionUser = (data: skipType) => {
*/
export const getProjectContractorList = () => {
return request({
url: '/project/project/list/project/contractorList',
url: '/zm/api/v1/system/sysProject/list?pageNum=1&pageSize=1000',
method: 'get'
});
};
@ -81,7 +96,7 @@ export const getProjectContractorList = () => {
*/
export const addConstructionUser = (data: ConstructionUserForm): AxiosPromise<string | number> => {
return request({
url: '/contractor/constructionUser',
url: '/zm/api/wxApplet/wxApplet/busConstructionUser/add',
method: 'post',
data: data
});
@ -93,7 +108,7 @@ export const addConstructionUser = (data: ConstructionUserForm): AxiosPromise<st
*/
export const updateConstructionUser = (data: ConstructionUserForm) => {
return request({
url: '/contractor/constructionUser',
url: '/zm/api/v1/system/busConstructionUser/pcEdit',
method: 'put',
data: data
});
@ -103,10 +118,11 @@ export const updateConstructionUser = (data: ConstructionUserForm) => {
* 删除施工人员
* @param id
*/
export const delConstructionUser = (id: string | number | Array<string | number>) => {
export const delConstructionUser = (data) => {
return request({
url: '/contractor/constructionUser/' + id,
method: 'delete'
url: '/zm/api/wxApplet/wxApplet/busConstructionUser/delete',
method: 'delete',
data
});
};
@ -116,8 +132,8 @@ export const delConstructionUser = (id: string | number | Array<string | number>
*/
export const updateConstructionUserStatus = (data: ConstructionUserStatusForm) => {
return request({
url: '/contractor/constructionUser/batch/status',
method: 'put',
url: '/zm/api/wxApplet/wxApplet/busConstructionUser/changeState',
method: 'delete',
data: data
});
};
@ -128,7 +144,7 @@ export const updateConstructionUserStatus = (data: ConstructionUserStatusForm) =
*/
export const updateConstructionUserPlayCardStatus = (data: ConstructionUserPlayCardForm) => {
return request({
url: '/contractor/constructionUser/batch/clock',
url: '/zm/api/v1/system/busConstructionUser/oneClickOpen',
method: 'put',
data: data
});
@ -140,7 +156,7 @@ export const updateConstructionUserPlayCardStatus = (data: ConstructionUserPlayC
*/
export const updateConstructionUserPlayCardOneStatus = (data: ConstructionUserPlayCardForm) => {
return request({
url: '/contractor/constructionUser/clock',
url: '/zm/api/v1/system/busConstructionUser/clockingCondition',
method: 'put',
data: data
});
@ -152,7 +168,7 @@ export const updateConstructionUserPlayCardOneStatus = (data: ConstructionUserPl
*/
export const updateConstructionUserSalary = (data: ConstructionUserSalaryForm) => {
return request({
url: '/contractor/constructionUser/salary',
url: '/zm/api/wxApplet/wxApplet/busConstructionUser/payEdit',
method: 'put',
data: data
});
@ -164,9 +180,9 @@ export const updateConstructionUserSalary = (data: ConstructionUserSalaryForm) =
*/
export const getConstructionUserExit = (query: ConstructionUserExitForm) => {
return request({
url: '/contractor/constructionUserExit/list',
method: 'get',
params: query
url: '/zm/api/v1/system/busConstructionUser/departureRecord',
method: 'post',
data: query
});
};
@ -175,10 +191,17 @@ export const getConstructionUserExit = (query: ConstructionUserExitForm) => {
* @param query
*/
export const dowloadConstructionUserTemplate = (query: ConstructionUserTemplateForm) => {
let { projectId } = query;
const fileName = projectId + '_project.zip';
return request.download('/contractor/constructionUserFile/exportFileTemplate', query, fileName);
return request({
url: '/zm/api/v1/system/busConstructionUser/templateExport',
method: 'get',
params: query
});
};
// export const dowloadConstructionUserTemplate = (query: ConstructionUserTemplateForm) => {
// let { projectId } = query;
// const fileName = projectId + '_project.zip';
// return request.download('/zm/api/v1/system/busConstructionUser/templateExport', query, fileName, 'get');
// };
/**
* 施工人员退场

View File

@ -1,6 +1,7 @@
import request from '@/utils/request';
import { AxiosPromise } from 'axios';
import { ConstructionUserFileVO, ConstructionUserFileForm, ConstructionUserFileQuery } from '@/api/project/constructionUserFile/types';
import requestGo from '@/utils/request-go';
/**
* 查询施工人员文件存储列表
@ -9,8 +10,8 @@ import { ConstructionUserFileVO, ConstructionUserFileForm, ConstructionUserFileQ
*/
export const listConstructionUserFile = (query?: ConstructionUserFileQuery): AxiosPromise<ConstructionUserFileVO[]> => {
return request({
url: '/contractor/constructionUserFile/list',
return requestGo({
url: '/zm/api/wxApplet/wxApplet/busConstructionUser/get',
method: 'get',
params: query
});

View File

@ -1,6 +1,7 @@
import request from '@/utils/request';
import { AxiosPromise } from 'axios';
import { ContractorForm, ContractorQuery, ContractorVO } from '@/api/project/contractor/types';
import requestGo from '@/utils/request-go';
/**
* 查询分包单位列表
@ -9,8 +10,8 @@ import { ContractorForm, ContractorQuery, ContractorVO } from '@/api/project/con
*/
export const listContractor = (query?: ContractorQuery): AxiosPromise<ContractorVO[]> => {
return request({
url: '/contractor/contractor/list',
return requestGo({
url: '/zm/api/wxApplet/wxApplet/busLabourservice/list',
method: 'get',
params: query
});
@ -21,8 +22,8 @@ export const listContractor = (query?: ContractorQuery): AxiosPromise<Contractor
* @param id
*/
export const getContractor = (id: string | number): AxiosPromise<ContractorVO> => {
return request({
url: '/contractor/contractor/' + id,
return requestGo({
url: '/zm/api/wxApplet/wxApplet/busLabourservice/get?id=' + id,
method: 'get'
});
};
@ -32,8 +33,8 @@ export const getContractor = (id: string | number): AxiosPromise<ContractorVO> =
* @param data
*/
export const addContractor = (data: ContractorForm): AxiosPromise<string | number> => {
return request({
url: '/contractor/contractor',
return requestGo({
url: '/zm/api/wxApplet/wxApplet/busLabourservice/add',
method: 'post',
data: data
});
@ -44,8 +45,8 @@ export const addContractor = (data: ContractorForm): AxiosPromise<string | numbe
* @param data
*/
export const updateContractor = (data: ContractorForm) => {
return request({
url: '/contractor/contractor',
return requestGo({
url: '/zm/api/wxApplet/wxApplet/busLabourservice/edit',
method: 'put',
data: data
});
@ -56,8 +57,11 @@ export const updateContractor = (data: ContractorForm) => {
* @param id
*/
export const delContractor = (id: string | number | Array<string | number>) => {
return request({
url: '/contractor/contractor/' + id,
method: 'delete'
return requestGo({
url: '/zm/api/wxApplet/wxApplet/busLabourservice/delete',
method: 'delete',
data: {
ids: id
}
});
};

View File

@ -60,6 +60,6 @@ export const delProjectTeamMember = (id: string | number | Array<string | number
return request({
url: '/zm/api/wxApplet/wxApplet/sysProjectTeamMember/delete',
method: 'delete',
params: { ids: id }
data: { ids: id }
});
};

View File

@ -0,0 +1,50 @@
import request from '@/utils/request-go';
// 读取所有导入列表数据(汇总)
export function readAllImportedListData() {
return request({
url: '/zm/api/v1/system/busPayrollList/readAllImportedListData',
method: 'get'
});
}
// 工资excel导入形成的列表
export function busPayrollList(query: any) {
return request({
url: '/zm/api/v1/system/busPayrollList/list',
method: 'get',
params: query
});
}
// 根据工资表的id获取到源excel只允许查看
export function getTheSourceExcelAccordingToTheIdOfThePayroll(query: any) {
return request({
url: '/zm/api/v1/system/busPayrollList/getTheSourceExcelAccordingToTheIdOfThePayroll',
method: 'get',
params: query
});
}
// 根据工资表的id获取到源excel只允许查看
export function importExcelPaySheet(query: any) {
return request({
url: '/zm/api/v1/system/busPayrollList/importExcelPaySheet',
method: 'post',
data: query
});
}
// 根据工资表的id获取到源excel只允许查看
export function deletePayroll(query: any) {
return request({
url: '/zm/api/v1/system/busPayrollList/deletePayroll',
method: 'DELETE',
params: query
});
}
// 查询施工单位列表
export function listBusLabourservice(query: object) {
return request({
url: '/zm/api/wxApplet/wxApplet/busLabourservice/list',
method: 'get',
params: query
});
}

View File

@ -1,4 +1,4 @@
import request from '@/utils/request';
import request from '@/utils/request-go';
import { AxiosPromise } from 'axios';
import { WorkWageVO, WorkWageForm, WorkWageQuery } from '@/api/project/workWage/types';
@ -10,7 +10,7 @@ import { WorkWageVO, WorkWageForm, WorkWageQuery } from '@/api/project/workWage/
export const listWorkWage = (query?: WorkWageQuery): AxiosPromise<WorkWageVO[]> => {
return request({
url: '/project/workWage/list',
url: '/zm/api/v1/system/busTypeOfWage/list',
method: 'get',
params: query
});
@ -22,7 +22,7 @@ export const listWorkWage = (query?: WorkWageQuery): AxiosPromise<WorkWageVO[]>
*/
export const getWorkWage = (id: string | number): AxiosPromise<WorkWageVO> => {
return request({
url: '/project/workWage/' + id,
url: '/zm/api/v1/system/busTypeOfWage/get?id=' + id,
method: 'get'
});
};
@ -33,7 +33,7 @@ export const getWorkWage = (id: string | number): AxiosPromise<WorkWageVO> => {
*/
export const addWorkWage = (data: WorkWageForm) => {
return request({
url: '/project/workWage',
url: '/zm/api/v1/system/busTypeOfWage/add',
method: 'post',
data: data
});
@ -45,7 +45,7 @@ export const addWorkWage = (data: WorkWageForm) => {
*/
export const updateWorkWage = (data: WorkWageForm) => {
return request({
url: '/project/workWage',
url: '/zm/api/v1/system/busTypeOfWage/edit',
method: 'put',
data: data
});
@ -57,7 +57,20 @@ export const updateWorkWage = (data: WorkWageForm) => {
*/
export const delWorkWage = (id: string | number | Array<string | number>) => {
return request({
url: '/project/workWage/' + id,
method: 'delete'
url: '/zm/api/v1/system/busTypeOfWage/delete',
method: 'delete',
data: {
ids: id
}
});
};
/**
* 查询工种类型
*/
export const getTypeOfWork = () => {
return request({
url: '/zm/api/v1/system/dict/data/getDictData?dictType=type_of_work',
method: 'get'
});
};

View File

@ -0,0 +1,89 @@
import request from '@/utils/request-go';
// 查询质量会议树形结构
export function documentQualityMeetingTreeStructure(query: object) {
return request({
url: '/zm/api/v1/system/documentQualityMeeting/qualityTreeStructure',
method: 'get',
params: query
});
}
// 查询质量会议文件列表
export function documentQualityMeetingList(query: object) {
return request({
url: '/zm/api/v1/system/documentQualityMeeting/list',
method: 'get',
params: query
});
}
// 质量会议添加
export function documentQualityMeetingAdd(data: object) {
return request({
url: '/zm/api/v1/system/documentQualityMeeting/add',
method: 'post',
data
});
}
// 质量会议修改文件名
export function documentQualityMeetingEdit(query: object) {
return request({
url: '/zm/api/v1/system/documentQualityMeeting/edit',
method: 'put',
params: query
});
}
// 质量会议删除文件
export function documentQualityMeetingDelete(query: object) {
return request({
url: '/zm/api/v1/system/documentQualityMeeting/delete',
method: 'delete',
params: query
});
}
// 质量会议获取指定id信息
export function documentProductionDrawingGet(query: object) {
return request({
url: '/zm/api/v1/system/documentProductionDrawing/get',
method: 'get',
params: query
});
}
// 新建文件夹
export function documentQualityMeetingNewFolder(data: object) {
return request({
url: '/zm/api/v1/system/documentQualityMeeting/qualityNewFolderData',
method: 'post',
data
});
}
// 单文件下载
export function documentQualityMeetingDownload(query: object) {
return request({
url: '/zm/api/v1/system/documentQualityMeeting/qualityDataUniFileDownload',
method: 'get',
params: query
});
}
// 获取pid
export function getSelectByPid(query: object) {
return request({
url: '/zm/api/v1/system/documentQualityMeeting/qualitySelectByPid',
method: 'get',
params: query
});
}
// 回收站恢复
export function qualityDataRecyclingStation(data: object) {
return request({
url: '/zm/api/v1/system/documentQualityMeeting/qualityDataRecyclingStation',
method: 'put',
data
});
}
// 回收站列表数据
export function qualityRecycleBinList(query: object) {
return request({
url: '/zm/api/v1/system/documentQualityMeeting/qualityRecycleBinList',
method: 'get',
params: query
});
}

View File

@ -0,0 +1,92 @@
import request from '@/utils/request-go';
// 在线word编辑接口
// 获取目录 树形数据
export function treeStructureList(query: object) {
return request({
url: '/zm/api/v1/system/document/treeStructure',
method: 'get',
params: query
});
}
// 根据目录信息获取文档
export function documentList(query: object) {
return request({
url: '/zm/api/v1/system/document/list',
method: 'get',
params: query
});
}
// 修改母板名称
export function documentEdit(data: object) {
return request({
url: '/zm/api/v1/system/document/edit',
method: 'put',
data
});
}
// 获取模板list
export function documentAllList(query) {
return request({
url: '/zm/api/v1/system/document/allList',
method: 'get',
params: query
});
}
// 删除母板
export function documentDelete(ids: any) {
return request({
url: '/zm/api/v1/system/document/delete',
method: 'delete',
params: {
ids
}
});
}
// 新增母板
export function documentAdd(data: object) {
return request({
url: '/zm/api/v1/system/document/add',
method: 'post',
data: data
});
}
// 新建文件夹
export function documentNewFolder(data: object) {
return request({
url: '/zm/api/v1/system/document/newFolder',
method: 'post',
data: data
});
}
// 下载文件夹 - 模板
export function compressedDownload(relativePath) {
return request({
url: '/zm/api/v1/system/document/compressedDownload',
method: 'get',
params: {
relativePath
}
});
}
// 下载文件夹 - 资料
export function uniFolderDownload(relativePath) {
return request({
url: '/zm/api/v1/system/documentData/dataCompressedDownload',
method: 'get',
params: {
relativePath
}
});
}
// 下载文件 - 资料
export function uniFileDownload(relativePath) {
return request({
url: '/zm/api/v1/system/documentData/uniFileDownload',
method: 'get',
responseType: 'blob',
params: {
relativePath
}
});
}

View File

@ -0,0 +1,100 @@
import request from '@/utils/request-go';
// 工程资料模块
//添加工程资料
export function templateDataAdd(data: object) {
return request({
url: '/zm/api/v1/system/templateData/add',
method: 'post',
data
});
}
// 获取工程列表
export function templateDataList(query: object) {
return request({
url: '/zm/api/v1/system/templateData/list',
method: 'get',
params: query
});
}
// 删除工程资料
export function templateDataDel(query: object) {
return request({
url: '/zm/api/v1/system/templateData/delete',
method: 'delete',
params: query
});
}
// 修改工程资料
export function templateDataEdit(data: object) {
return request({
url: '/zm/api/v1/system/templateData/edit',
method: 'put',
data
});
}
// 工程资料下级模板接口
// 添加
export function templateDataJuniorAdd(data: object) {
return request({
url: '/zm/api/v1/system/templateDataJunior/add',
method: 'post',
data
});
}
// 删除
export function templateDataJuniorDel(query: object) {
return request({
url: '/zm/api/v1/system/templateDataJunior/delete',
method: 'delete',
params: query
});
}
// 修改
export function templateDataJuniorEdit(data: object) {
return request({
url: '/zm/api/v1/system/templateDataJunior/edit',
method: 'put',
data
});
}
// 列表
export function templateDataJuniorList(query: object) {
return request({
url: '/zm/api/v1/system/templateDataJunior/list',
method: 'get',
params: query
});
}
// 获取源数据
export function templateDataSourceDataList(query: object) {
return request({
url: '/zm/api/v1/system/templateDataSourceData/list',
method: 'get',
params: query
});
}
// 添加数据源
export function templateDataSourceDataAdd(query: object) {
return request({
url: '/zm/api/v1/system/templateDataSourceData/add',
method: 'get',
params: query
});
}
// 修改数据源
export function templateDataSourceDataEdit(query: object) {
return request({
url: '/zm/api/v1/system/templateDataSourceData/edit',
method: 'get',
params: query
});
}
// 删除数据源
export function templateDataSourceDataDel(query: object) {
return request({
url: '/zm/api/v1/system/templateDataSourceData/delete',
method: 'get',
params: query
});
}

View File

@ -0,0 +1,129 @@
import request from '@/utils/request-go';
// 工程资料模块
//工程列表
export function documentDataList(query: object) {
return request({
url: '/zm/api/v1/system/documentData/list',
method: 'get',
params: query
});
}
//工程列表(无分页)
export function documentDataListUnPage(query: object) {
return request({
url: '/zm/api/v1/system/documentData/sonFile',
method: 'get',
params: query
});
}
// 添加工程资料
export function documentDataAdd(data: object) {
return request({
url: '/zm/api/v1/system/documentData/add',
method: 'post',
data
});
}
// 新建文件夹
export function documentDataNewFolder(data: object) {
return request({
url: '/zm/api/v1/system/documentData/newFolder',
method: 'post',
data
});
}
// 删除工程资料
export function documentDataDelete(query: object) {
return request({
url: '/zm/api/v1/system/documentData/delete',
method: 'delete',
params: {
ids: query
}
});
}
// 修改工程资料
export function documentDataEdit(data: object) {
return request({
url: '/zm/api/v1/system/documentData/edit',
method: 'put',
data
});
}
// 获取资料树形结构
export function treeStructureData(query: object) {
return request({
url: '/zm/api/v1/system/documentData/treeStructureData',
method: 'get',
params: query
});
}
// 复制模板
export function onlineImport(data: object) {
return request({
url: '/zm/api/v1/system/documentData/onlineImport',
method: 'put',
data
});
}
// 工程资料列表数据
export function documentDataAllList(query) {
return request({
url: '/zm/api/v1/system/documentData/allList',
method: 'get',
params: query
});
}
// 文件拖动
export function onlineMobile(data) {
return request({
url: '/zm/api/v1/system/documentData/onlineMobile',
method: 'put',
data
});
}
// 回收站文件删除或恢复 资料部分
export function dataRecyclingStation(data) {
return request({
url: '/zm/api/v1/system/documentData/dataRecyclingStation',
method: 'put',
data
});
}
// 回收站文件删除或恢复 模板部分
export function templateRecycleBin(data) {
return request({
url: '/zm/api/v1/system/documentData/templateRecycleBin',
method: 'put',
data
});
}
//资料文件模糊查询查询资料里面的所有文件限制文件为ppt、excel、word
export function dataFileQuery(query) {
return request({
url: '/zm/api/v1/system/documentData/dataFileQuery',
method: 'get',
params: query
});
}
// 资料-查看-获取详细信息
export function getProfileDetail(id) {
return request({
url: '/zm/api/v1/system/documentData/get',
method: 'get',
params: {
id
}
});
}
// 查询项目列表 所有项目 无用户限制
export function listSysProjectAll(query: object) {
return request({
url: '/zm/api/v1/system/sysProject/listAll',
method: 'get',
params: query
});
}

View File

@ -58,7 +58,8 @@ export const updateQualityConstructionLog = (data: QualityConstructionLogForm) =
*/
export const delQualityConstructionLog = (id: string | number | Array<string | number>) => {
return request({
url: '/quality/qualityConstructionLog/' + id,
method: 'delete'
url: '/zm/api/v1/system/busConstructionLog/delete',
method: 'delete',
data: { ids: id }
});
};

View File

@ -46,7 +46,7 @@ export const addQualityInspection = (data: QualityInspectionForm) => {
*/
export const updateQualityInspection = (data: QualityInspectionForm) => {
return request({
url: '/quality/qualityInspection',
url: '/zm/api/v1/system/busInspectionTicket/editVerification',
method: 'put',
data: data
});
@ -58,8 +58,11 @@ export const updateQualityInspection = (data: QualityInspectionForm) => {
*/
export const delQualityInspection = (id: string | number | Array<string | number>) => {
return request({
url: '/quality/qualityInspection/' + id,
method: 'delete'
url: '/zm/api/v1/system/busInspectionTicket/delete',
method: 'delete',
data: {
ids: id
}
});
};
@ -67,3 +70,20 @@ export const delQualityInspection = (id: string | number | Array<string | number
export function downLoadOss(ossId: { id?: string | number; idList?: string | number | Array<string | number> }, url: string, fileName: string) {
return request.download(url, ossId, fileName);
}
// 查询项目下的所有人员
export function acquisitionOfCorrectivePersonnel(projectId: string | number) {
return request({
url: '/zm/api/v1/system/busInspectionTicket/acquisitionOfCorrectivePersonnel?projectId=' + projectId,
method: 'get'
});
}
// 编辑校验
export function editVerification(data: any) {
return request({
url: '/zm/api/v1/system/busInspectionTicket/editVerification',
method: 'post',
data: data
});
}

View File

@ -1,33 +1,24 @@
import request from '@/utils/request';
import {
documentSafetyMeetingListFile,
documentSafetyMeetingListFolder,
documentSafetyMeetingListQuery,
documentSafetyMeetingListVo,
documentRecycleBinListQuery,
documentRecycleBinListVO
} from './type';
import { AxiosPromise } from 'axios';
import request from '@/utils/request-go';
// 查询安全会议结构
export function documentCompletionTreeStructure(query: object) {
return request({
url: '/safety/documentSafetyMeeting/list',
url: '/zm/api/v1/system/documentSafetyMeeting/safetyTreeStructure',
method: 'get',
params: query
});
}
// 查询安全会议文件列表
export function documentCompletionList(query: documentSafetyMeetingListQuery): AxiosPromise<documentSafetyMeetingListVo> {
export function documentCompletionList(query: object) {
return request({
url: '/safety/documentSafetyMeeting/list',
url: '/zm/api/v1/system/documentSafetyMeeting/list',
method: 'get',
params: query
});
}
// 安全会议添加
export function documentCompletionAdd(data: documentSafetyMeetingListFile) {
export function documentCompletionAdd(data: object) {
return request({
url: '/safety/documentSafetyMeeting/file',
url: '/zm/api/v1/system/documentSafetyMeeting/add',
method: 'post',
data
});
@ -35,29 +26,31 @@ export function documentCompletionAdd(data: documentSafetyMeetingListFile) {
// 安全会议修改文件名
export function documentCompletionEdit(query: object) {
return request({
url: '/api/v1/system/documentSafetyMeeting/edit',
url: '/zm/api/v1/system/documentSafetyMeeting/edit',
method: 'put',
params: query
});
}
// 安全会议删除文件
export function documentCompletionDelete(id: string) {
export function documentCompletionDelete(query: object) {
return request({
url: '/safety/documentSafetyMeeting/' + id,
method: 'delete'
url: '/zm/api/v1/system/documentSafetyMeeting/delete',
method: 'delete',
params: query
});
}
// 安全会议获取指定id信息
export function documentCompletionGet(id: string) {
export function documentCompletionGet(query: object) {
return request({
url: '/safety/documentSafetyMeeting/' + id,
method: 'get'
url: '/zm/api/v1/system/documentSafetyMeeting/get',
method: 'get',
params: query
});
}
// 新建文件夹
export function newFolder(data: documentSafetyMeetingListFolder): AxiosPromise<any> {
export function newFolder(data: object) {
return request({
url: '/safety/documentSafetyMeeting/folder',
url: '/zm/api/v1/system/documentSafetyMeeting/safetyNewFolderData',
method: 'post',
data
});
@ -65,23 +58,24 @@ export function newFolder(data: documentSafetyMeetingListFolder): AxiosPromise<a
// 单文件下载
export function uniFileDownload(query: object) {
return request({
url: '/api/v1/system/documentSafetyMeeting/safetyDataUniFileDownload',
url: '/zm/api/v1/system/documentSafetyMeeting/safetyDataUniFileDownload',
method: 'get',
params: query
});
}
// 回收站恢复
export function completionDataRecyclingStation(id: string[]) {
export function completionDataRecyclingStation(data: object) {
return request({
url: '/safety/documentSafetyMeeting/recovery/' + id,
method: 'put'
url: '/zm/api/v1/system/documentSafetyMeeting/safetyDataRecyclingStation',
method: 'put',
data
});
}
// 回收站列表数据
export function documentRecycleBinList(query: documentRecycleBinListQuery): AxiosPromise<documentRecycleBinListVO> {
export function documentRecycleBinList(query: object) {
return request({
url: '/safety/documentSafetyMeeting/recycleBin/list',
url: '/zm/api/v1/system/documentSafetyMeeting/safetyRecycleBinList',
method: 'get',
params: { ...query, fileType: '2' }
params: query
});
}

View File

@ -57,8 +57,9 @@ export const updateRecognizeRecord = (data: RecognizeRecordForm) => {
* @param id
*/
export const delRecognizeRecord = (id: string | number | Array<string | number>) => {
return request({
url: '/safety/recognizeRecord/' + id,
method: 'delete'
return request1({
url: '/zm/api/v1/system/busTour/delete',
method: 'delete',
data: { ids: id }
});
};

View File

@ -58,8 +58,9 @@ export const updateSafetyInspection = (data: SafetyInspectionForm) => {
* @param id
*/
export const delSafetyInspection = (id: string | number | Array<string | number>) => {
return request({
url: '/safety/safetyInspection/' + id,
method: 'delete'
return request1({
url: '/zm/api/v1/system/busHseManagement/delete',
method: 'delete',
data: { ids: id }
});
};

View File

@ -1,6 +1,7 @@
import request from '@/utils/request';
import { AxiosPromise } from 'axios';
import { SafetyLogForm, SafetyLogQuery, SafetyLogVO } from '@/api/safety/safetyLog/types';
import requestGo from '@/utils/request-go';
/**
* 查询安全日志列表
@ -21,8 +22,8 @@ export const listSafetyLog = (query?: SafetyLogQuery): AxiosPromise<SafetyLogVO[
* @param id
*/
export const getSafetyLog = (id: string | number): AxiosPromise<SafetyLogVO> => {
return request({
url: '/safety/safetyLog/' + id,
return requestGo({
url: '/zm/api/v1/system/busHseSecurityLog/get?id=' + id,
method: 'get'
});
};
@ -32,8 +33,8 @@ export const getSafetyLog = (id: string | number): AxiosPromise<SafetyLogVO> =>
* @param data
*/
export const addSafetyLog = (data: SafetyLogForm) => {
return request({
url: '/safety/safetyLog',
return requestGo({
url: '/zm/api/v1/system/busHseSecurityLog/addText',
method: 'post',
data: data
});
@ -56,8 +57,9 @@ export const updateSafetyLog = (data: SafetyLogForm) => {
* @param id
*/
export const delSafetyLog = (id: string | number | Array<string | number>) => {
return request({
url: '/safety/safetyLog/' + id,
method: 'delete'
return requestGo({
url: '/zm/api/v1/system/busHseSecurityLog/delete',
method: 'delete',
data: { ids: id }
});
};

View File

@ -1,4 +1,4 @@
import request from '@/utils/request';
import request from '@/utils/request-go';
import { AxiosPromise } from 'axios';
import { SafetyWeeklyReportForm, SafetyWeeklyReportQuery, SafetyWeeklyReportVO } from '@/api/safety/safetyWeeklyReport/types';
@ -10,7 +10,7 @@ import { SafetyWeeklyReportForm, SafetyWeeklyReportQuery, SafetyWeeklyReportVO }
export const listSafetyWeeklyReport = (query?: SafetyWeeklyReportQuery): AxiosPromise<SafetyWeeklyReportVO[]> => {
return request({
url: '/safety/safetyWeeklyReport/list',
url: '/zm/api/v1/system/busWeeklySecurityReport/list',
method: 'get',
params: query
});
@ -33,7 +33,7 @@ export const getSafetyWeeklyReport = (id: string | number): AxiosPromise<SafetyW
*/
export const addSafetyWeeklyReport = (data: SafetyWeeklyReportForm) => {
return request({
url: '/safety/safetyWeeklyReport',
url: '/zm/api/v1/system/busWeeklySecurityReport/add',
method: 'post',
data: data
});
@ -57,7 +57,8 @@ export const updateSafetyWeeklyReport = (data: SafetyWeeklyReportForm) => {
*/
export const delSafetyWeeklyReport = (id: string | number | Array<string | number>) => {
return request({
url: '/safety/safetyWeeklyReport/' + id,
method: 'delete'
url: '/zm/api/v1/system/busWeeklySecurityReport/delete',
method: 'delete',
data: { ids: id }
});
};

View File

@ -58,8 +58,11 @@ export const updateTeamMeeting = (data: TeamMeetingForm) => {
* @param id
*/
export const delTeamMeeting = (id: string | number | Array<string | number>) => {
return request({
url: '/safety/teamMeeting/' + id,
method: 'delete'
return request1({
url: '/zm/api/wxApplet/wxApplet/sysProjectTeamSquad/delete',
method: 'delete',
data: {
ids: id
}
});
};

View File

@ -22,8 +22,8 @@ export const listViolationLevel = (query?: ViolationLevelQuery): AxiosPromise<Vi
* @param id
*/
export const getViolationLevel = (id: string | number): AxiosPromise<ViolationLevelVO> => {
return request({
url: '/safety/violationLevel/' + id,
return request1({
url: '/zm/api/v1/system/busViolationLevel/get?id=' + id,
method: 'get'
});
};
@ -33,8 +33,8 @@ export const getViolationLevel = (id: string | number): AxiosPromise<ViolationLe
* @param data
*/
export const addViolationLevel = (data: ViolationLevelForm) => {
return request({
url: '/safety/violationLevel',
return request1({
url: '/zm/api/v1/system/busViolationLevel/add',
method: 'post',
data: data
});
@ -45,8 +45,8 @@ export const addViolationLevel = (data: ViolationLevelForm) => {
* @param data
*/
export const updateViolationLevel = (data: ViolationLevelForm) => {
return request({
url: '/safety/violationLevel',
return request1({
url: '/zm/api/v1/system/busViolationLevel/edit',
method: 'put',
data: data
});
@ -58,7 +58,8 @@ export const updateViolationLevel = (data: ViolationLevelForm) => {
*/
export const delViolationLevel = (id: string | number | Array<string | number>) => {
return request({
url: '/safety/violationLevel/' + id,
method: 'delete'
url: '/zm/api/v1/system/busViolationLevel/delete',
method: 'delete',
data: { ids: id }
});
};

View File

@ -21,11 +21,10 @@ export const listViolationRecord = (query?: ViolationRecordQuery): AxiosPromise<
* 查询违规记录详细
* @param id
*/
export const getViolationRecord = (query): AxiosPromise<ViolationRecordVO> => {
export const getViolationRecord = (id: string): AxiosPromise<ViolationRecordVO> => {
return request1({
url: '/zm/api/v1/system/busViolationRecord/get',
method: 'get',
params: query
url: '/zm/api/v1/system/busViolationRecord/get?id=' + id,
method: 'get'
});
};
@ -34,8 +33,8 @@ export const getViolationRecord = (query): AxiosPromise<ViolationRecordVO> => {
* @param data
*/
export const addViolationRecord = (data: any) => {
return request({
url: '/safety/violationRecord/handler',
return request1({
url: '/zm/api/v1/system/busViolationRecord/selectTheViolator',
method: 'post',
data: data
});
@ -58,8 +57,17 @@ export const updateViolationRecord = (data: ViolationRecordForm) => {
* @param id
*/
export const delViolationRecord = (id: string | number | Array<string | number>) => {
return request({
url: '/safety/violationRecord/' + id,
method: 'delete'
return request1({
url: '/zm/api/v1/system/busViolationRecord/delete',
method: 'delete',
data: { ids: id }
});
};
export function listBusConstructionUser(query: object) {
return request1({
url: '/zm/api/v1/system/busConstructionUser/list',
method: 'get',
params: query
});
}

View File

@ -1,6 +1,7 @@
import request from '@/utils/request';
import { PostForm, PostQuery, PostVO } from './types';
import { AxiosPromise } from 'axios';
import requestGo from '@/utils/request-go';
// 查询岗位列表
export function listPost(query: { pageNum: number; pageSize: number }): AxiosPromise<PostVO[]> {
@ -13,8 +14,8 @@ export function listPost(query: { pageNum: number; pageSize: number }): AxiosPro
// 查询岗位列表
export function listTreeByProject(): AxiosPromise<PostVO[]> {
return request({
url: '/system/dept/list/tree',
return requestGo({
url: '/zm/api/v1/system/post/list?pageNum=1&pageSize=100',
method: 'get'
});
}

BIN
src/assets/icons/file.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.6 KiB

BIN
src/assets/icons/file1.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 KiB

View File

@ -53,13 +53,13 @@
style="margin-top: 10px"
v-for="(file, index) in fileList"
:key="file.uid"
class="el-upload-list__item ele-upload-list__item-content"
class="el-upload-list__item upload-list__item-content"
v-if="autoUpload"
>
<el-link :href="`${file.url}`" :underline="false" target="_blank">
<span class="el-icon-document"> {{ getFileName(file.name) }} </span>
</el-link>
<div class="ele-upload-list__item-content-action">
<div class="upload-list__item-content-action">
<el-button type="danger" link @click="handleDelete(index)">删除</el-button>
</div>
</li>
@ -70,7 +70,7 @@
<el-icon v-if="isConstruction">
<Plus />
</el-icon>
<template #file="{ file }">
<!-- <template #file="{ file }">
<div class="pdf" v-if="isConstruction">
<img src="@/assets/icons/svg/pdf.png" alt="" />
<el-text class="w-148px text-center" truncated>
@ -89,7 +89,7 @@
</a>
</div>
</div>
</template>
</template> -->
</el-upload>
</div>
</template>
@ -125,6 +125,8 @@ const props = defineProps({
autoUpload: propTypes.bool.def(true),
// 是否显示文件列表
showFileList: propTypes.bool.def(false),
// 上传类型
isGo: propTypes.bool.def(false),
// 默认显示的文件列表
defaultFileList: {
type: Array as any,
@ -156,9 +158,12 @@ const emit = defineEmits(['update:modelValue', 'handleChange', 'handleRemove']);
const number = ref(0);
const uploadList = ref<any[]>([]);
const baseUrl = import.meta.env.VITE_APP_BASE_API;
const baseUrl = props.isGo ? import.meta.env.VITE_APP_BASE_API_GO : import.meta.env.VITE_APP_BASE_API;
const uploadFileUrl = ref(baseUrl + props.uploadUrl); // 上传文件服务器地址
const headers = ref(globalHeaders());
const headers = ref({
...globalHeaders(),
'Authorization': props.isGo ? `Bearer ${proxy.$cache.local.get('goToken') || ''}` : `Bearer ${proxy.$cache.local.get('Admin-Token') || ''}`
});
const pendingFiles = ref<UploadFile[]>([]);
const realUploadUrl = computed(() => {
@ -260,7 +265,8 @@ interface UploadFileWithOssId extends UploadFile {
}
const handleUploadSuccess = (res: any, file: UploadFileWithOssId) => {
if (res.code === 200) {
console.log('🚀 ~ handleUploadSuccess ~ res:', res.code);
if (res.code === 200 || res.code === 0) {
console.log('上传成功');
// 上传成功,不管 data 是否为空
uploadList.value.push({
@ -485,7 +491,7 @@ defineExpose({ submitUpload });
}
}
.upload-file-list .ele-upload-list__item-content {
.upload-file-list .upload-list__item-content {
display: flex;
justify-content: space-between;
align-items: center;
@ -510,7 +516,7 @@ defineExpose({ submitUpload });
z-index: 1;
}
.ele-upload-list__item-content-action .el-link {
.upload-list__item-content-action .el-link {
margin-right: 10px;
}

View File

@ -50,6 +50,7 @@ const handleSelect = async (projectId: string) => {
const userStore = useUserStore();
const permissionStore = usePermissionStore();
const selectedProject = projects.value.find((p) => p.id === projectId);
console.log('🚀 ~ handleSelect ~ selectedProject:', selectedProject);
if (!selectedProject) return;
const loadingInstance = ElLoading.service({
lock: true,

View File

@ -26,11 +26,11 @@
<el-tooltip effect="dark" placement="bottom">
<ProjectSelector />
</el-tooltip>
<!-- <el-tooltip content="搜索" effect="dark" placement="bottom">
<el-tooltip content="搜索" effect="dark" placement="bottom">
<div class="right-menu-item hover-effect" @click="openSearchMenu">
<svg-icon class-name="search-icon" icon-class="search" />
</div>
</el-tooltip> -->
</el-tooltip>
<!-- 消息 -->
<el-tooltip :content="proxy.$t('navbar.message')" effect="dark" placement="bottom">
<div>

View File

@ -72,7 +72,8 @@ export const useUserStore = defineStore('user', () => {
if (projectRes?.data) {
const projectList = projectRes.data.map((p) => ({
id: p.projectId,
name: p.projectName || '未知项目'
name: p.projectName || '未知项目',
goId: p.goId
}));
setProjects(projectList);
// 如果有缓存的选中项目,且该项目在当前项目列表中存在,则使用缓存的项目
@ -159,6 +160,7 @@ export const useUserStore = defineStore('user', () => {
};
const setSelectedProject = (project: { id: string; name: string; goId: string }) => {
console.log('🚀 ~ setSelectedProject ~ project:', project);
selectedProject.value = project;
saveSelectedProjectToStorage(project);
};

View File

@ -0,0 +1,146 @@
// 封装exceljs
import ExcelJS from 'exceljs';
import FileSaver from 'file-saver';
/**
* 导出数据到Excel方法
* @param {Array[Object]} config.data 表格数据
* @param {Array[String]} config.fields 字段列表
* @param {Array[String]} config.headers excel表头列表[[]],可以是多级表头[['A1''B1'],['A2''B2']]
* @param {Array[Object]} config.merges 需要合并的单元格,需要考虑表头的行数[{row:1, col:1, rowspan: 1, colspan: 2}]
* @param {Array[Object]} config.attrs 单元格样式配置
* @param {Array[Object]} config.views 工作表视图配置
* @param {Array[Number]} config.columnsWidth 每个字段列对应的宽度
* @param {Object} config.protect 工作表保护【此配置会保护全表,一般推荐只针对单元格进行保护配置】
* @param {String} config.sheetName 工作表名称默认从sheet1开始
* @param {String} fileName excel文件名称
*/
export function exportDataToExcel(config, fileName) {
if (!config) return;
const options = {
fileName: fileName || `导出excel文件【${Date.now()}】.xlsx`,
worksheets: [],
};
if (!Array.isArray(config)) {
config = [config];
}
config.forEach((item) => {
// 深拷贝data【JSON.stringify有缺陷可自行换成_.cloneDeep】
const data = JSON.parse(JSON.stringify(item.data));
const results = data.map((obj) => {
return item.fields.map((key) => {
return obj[key];
});
});
// 生成完整excel数据
let excelData = [];
excelData = excelData.concat(item.headers).concat(results);
// 单元格合并处理【excel数据的第一行/列是从1开始】
let excelMerges = [];
excelMerges = item.merges.map((m) => {
return [m.row + 1, m.col + 1, m.row + m.rowspan, m.col + m.colspan];
});
// 单元格配置处理【excel数据的第一行/列是从1开始】
let excelAttrs = [];
excelAttrs = item.attrs.map((attr) => {
attr.rowStart += 1;
attr.rowEnd += 1;
attr.colStart += 1;
attr.colEnd += 1;
return attr;
});
options.worksheets.push({
data: excelData,
merges: excelMerges,
attrs: excelAttrs,
views: item.views,
columnsWidth: item.columnsWidth,
protect: item.protect,
sheetName: item.sheetName,
});
});
createExcel(options);
}
// 创建Excel文件方法
async function createExcel(options) {
if (!options.worksheets.length) return;
// 创建工作簿
const workbook = new ExcelJS.Workbook();
for (let i = 0; i < options.worksheets.length; i++) {
const sheetOption = options.worksheets[i];
// 创建工作表
const sheet = workbook.addWorksheet(sheetOption.sheetName || 'sheet' + (i + 1));
// 添加数据行
sheet.addRows(sheetOption.data);
// 配置视图
sheet.views = sheetOption.views;
// 单元格合并处理【开始行,开始列,结束行,结束列】
if (sheetOption.merges) {
sheetOption.merges.forEach((item) => {
sheet.mergeCells(item);
});
}
// 工作表保护
if (sheetOption.protect) {
const res = await sheet.protect(sheetOption.protect.password, sheetOption.protect.options);
}
// 单元格样式处理
if (sheetOption.attrs.length) {
sheetOption.attrs.forEach((item) => {
const attr = item.attr || {};
// 获取开始行-结束行; 开始列-结束列
const rowStart = item.rowStart;
const rowEnd = item.rowEnd;
const colStart = item.colStart;
const colEnd = item.colEnd;
if (rowStart) {
// 设置行
for (let r = rowStart; r <= rowEnd; r++) {
// 获取当前行
const row = sheet.getRow(r);
if (colStart) {
// 列设置
for (let c = colStart; c <= colEnd; c++) {
// 获取当前单元格
const cell = row.getCell(c);
Object.keys(attr).forEach((key) => {
// 给当前单元格设置定义的样式
cell[key] = attr[key];
});
}
} else {
// 未设置列,整行设置【大纲级别】
Object.keys(attr).forEach((key) => {
row[key] = attr[key];
});
}
}
} else if (colStart) {
// 未设置行,只设置了列
for (let c = colStart; c <= colEnd; c++) {
// 获取当前列,整列设置【大纲级别】
const column = sheet.getColumn(c);
Object.keys(attr).forEach((key) => {
column[key] = attr[key];
});
}
} else {
// 没有设置具体的行列,则为整表设置
Object.keys(attr).forEach((key) => {
sheet[key] = attr[key];
});
}
});
}
// 列宽设置
if (sheetOption.columnsWidth) {
for (let i = 0; i < sheet.columns.length; i++) {
sheet.columns[i].width = sheetOption.columnsWidth[i];
}
}
}
// 生成excel文件
workbook.xlsx.writeBuffer().then((buffer) => {
// application/octet-stream 二进制数据
FileSaver.saveAs(new Blob([buffer], { type: 'application/octet-stream' }), options.fileName);
});
}

View File

@ -9,13 +9,13 @@ export const getProjectTeam = async () => {
if (!isPermission && useUserStore().permissions[0] != '*:*:*') return;
const { id } = $cache.local.getJSON('selectedProject');
const { goId } = $cache.local.getJSON('selectedProject');
const res = await listProjectTeam({
pageNum: 1,
pageSize: 20,
orderByColumn: 'createTime',
isAsc: 'desc',
projectId: id
projectId: goId
});
const list = res.data.list.map((projectTeam: ProjectTeamVO) => ({

View File

@ -23,12 +23,13 @@ const requestGo: RequestGo = (config: any) => {
});
};
requestGo.download = function (url: string, params: any, filename: string) {
requestGo.download = function (url: string, params: any, filename: string, method: 'post' | 'get' = 'post') {
return request({
url,
method: 'post',
method: method,
baseURL: BASE_GO_URL,
data: params,
data: method === 'post' ? params : undefined,
params: method === 'get' ? params : undefined,
headers: {
'Authorization': `Bearer ${$cache.local.get('goToken') || ''}`
},

50
src/utils/sign.js Normal file
View File

@ -0,0 +1,50 @@
import crypto from 'crypto-js';
let coyr = 'coyrOrtiehanhan1223202409111457';
// 生成 nonce随机生成一个16位的字符串
function generateNonce() {
const chars = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789';
let nonce = '';
for (let i = 0; i < 16; i++) {
nonce += chars.charAt(Math.floor(Math.random() * chars.length));
}
return nonce;
}
// 生成当前时间戳(格式为 yyyyMMddHHmmss
function generateTimestamp() {
return new Date().getTime();
}
// 生成 MD5 哈希(需要引入第三方库,如 crypto-js
function md5Hash(str) {
return crypto.MD5(str).toString();
}
// 生成 SHA-256 哈希(需要引入第三方库,如 crypto-js
function sha256Hash(str) {
return crypto.SHA256(str).toString();
}
// 生成签名
function generateSignature(params, timestamp, nonce) {
// 加密
let coyr1 = md5Hash(coyr);
// 拼接时间戳、nonce 和 secretKey
let signStr = coyr1 + timestamp + nonce;
// MD5 加密
const md5Str = md5Hash(signStr);
// SHA-256 加密
let aaaa = sha256Hash(md5Str);
return aaaa;
}
function sign(data) {
// 生成签名
const timestamp = generateTimestamp();
const nonce = generateNonce();
const sign = generateSignature(data, timestamp, nonce);
return {
timestamp,
nonce,
sign,
};
}
// 封装
export default sign;

59
src/utils/storage.ts Normal file
View File

@ -0,0 +1,59 @@
import Cookies from 'js-cookie';
/**
* window.localStorage 浏览器永久缓存
* @method set 设置永久缓存
* @method get 获取永久缓存
* @method remove 移除永久缓存
* @method clear 移除全部永久缓存
*/
export const Local = {
// 设置永久缓存
set(key: string, val: any) {
window.localStorage.setItem(key, JSON.stringify(val));
},
// 获取永久缓存
get(key: string) {
let json: any = window.localStorage.getItem(key);
return JSON.parse(json);
},
// 移除永久缓存
remove(key: string) {
window.localStorage.removeItem(key);
},
// 移除全部永久缓存
clear() {
window.localStorage.clear();
},
};
/**
* window.sessionStorage 浏览器临时缓存
* @method set 设置临时缓存
* @method get 获取临时缓存
* @method remove 移除临时缓存
* @method clear 移除全部临时缓存
*/
export const Session = {
// 设置临时缓存
set(key: string, val: any) {
if (key === 'token') return Cookies.set(key, val);
window.sessionStorage.setItem(key, JSON.stringify(val));
},
// 获取临时缓存
get(key: string) {
if (key === 'token') return Cookies.get(key);
let json: any = window.sessionStorage.getItem(key);
return JSON.parse(json);
},
// 移除临时缓存
remove(key: string) {
if (key === 'token') return Cookies.remove(key);
window.sessionStorage.removeItem(key);
},
// 移除全部临时缓存
clear() {
Cookies.remove('token');
window.sessionStorage.clear();
},
};

View File

@ -21,6 +21,8 @@
<el-card shadow="never">
<template #header>
<el-row :gutter="10" class="mb8">
<el-button type="danger" @click="handleDelete()" plain icon="Delete" :disabled="multiple">删除</el-button>
<right-toolbar v-model:showSearch="showSearch" @queryTable="getList"></right-toolbar>
</el-row>
</template>
@ -40,6 +42,11 @@
</template>
</el-table-column>
<el-table-column label="拍摄时间" align="center" prop="createdAt" />
<el-table-column label="操作" align="center" width="120">
<template #default="scope">
<el-button type="danger" link icon="Delete" @click="handleDelete(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>

View File

@ -18,12 +18,12 @@
<el-option v-for="dict in type_of_work" :key="dict.value" :label="dict.label" :value="dict.value" />
</el-select>
</el-form-item>
<el-form-item label="打卡日期" prop="clockDate">
<el-form-item label="打卡日期" prop="dateStr">
<el-date-picker
clearable
v-model="queryParams.clockDate"
type="date"
value-format="YYYY-MM-DD"
v-model="queryParams.dateStr"
type="month"
value-format="YYYY-MM"
placeholder="请选择打卡日期"
@change="selectDate"
/>
@ -36,7 +36,7 @@
</el-card>
</div>
</transition>
<el-row :gutter="20">
<!-- <el-row :gutter="20">
<el-col :span="24" :offset="0">
<el-card shadow="hover">
<div class="el-table el-table--enable-row-hover el-table--medium">
@ -44,7 +44,7 @@
</div>
</el-card>
</el-col>
</el-row>
</el-row> -->
<el-card shadow="never">
<el-table v-loading="loading" :data="attendanceList">
@ -60,11 +60,11 @@
<el-table-column label="迟到(次)" align="center" prop="LackOfCard" />
<el-table-column label="早退(次)" align="center" prop="LeaveEarly" />
<el-table-column label="缺卡(次)" align="center" prop="BeLate" />
<!-- <el-table-column label="操作" align="center" class-name="small-padding fixed-width">
<el-table-column label="操作" align="center" class-name="small-padding fixed-width">
<template #default="scope">
<el-button link type="primary" icon="View" @click="handleDetails(scope.row)" v-hasPermi="['project:attendance:edit']">详情</el-button>
</template>
</el-table-column> -->
</el-table-column>
</el-table>
<pagination v-show="total > 0" :total="total" v-model:page="queryParams.pageNum" v-model:limit="queryParams.pageSize" @pagination="getList" />
@ -144,7 +144,7 @@ const initFormData: AttendanceForm = {
facePic: undefined,
onClockTime: undefined,
offClockTime: undefined,
clockDate: undefined,
dateStr: undefined,
clockStatus: undefined,
pinchUserId: undefined,
clockRecord: undefined,
@ -163,7 +163,7 @@ const data = reactive<PageData<AttendanceForm, AttendanceQuery>>({
pageNum: 1,
pageSize: 10,
userName: undefined,
clockDate: undefined,
dateStr: undefined,
clockStatus: undefined,
commuter: undefined,
projectId: currentProject.value.goId,
@ -176,7 +176,7 @@ const data = reactive<PageData<AttendanceForm, AttendanceQuery>>({
userId: [{ required: true, message: '人员id不能为空', trigger: 'blur' }],
facePic: [{ required: true, message: '人脸照不能为空', trigger: 'blur' }],
projectId: [{ required: true, message: '项目id不能为空', trigger: 'blur' }],
clockDate: [{ required: true, message: '打卡日期不能为空', trigger: 'blur' }],
dateStr: [{ required: true, message: '打卡日期不能为空', trigger: 'blur' }],
clockStatus: [{ required: true, message: '1正常,2迟到,3早退,4缺勤,5补卡不能为空', trigger: 'change' }]
}
});
@ -187,11 +187,11 @@ const day = computed(() => (date) => {
});
//是否打卡
const isplayCard = computed(() => (date) => {
return calendarList.value.some((item) => item.clockDate == date.day);
return calendarList.value.some((item) => item.dateStr == date.day);
});
//打卡时间下标
const playCardIdx = computed(() => (date) => {
return calendarList.value.findIndex((item) => item.clockDate == date.day);
return calendarList.value.findIndex((item) => item.dateStr == date.day);
});
//上班时间
const workTime = computed(() => (date) => {
@ -228,7 +228,7 @@ const handleCalendarMonth = async (e?) => {
}
const res = await listAttendanceMonth({ userId: dialog.id, clockMonth });
calendarList.value = res.data;
calendarList.value = res.data.list || [];
};
/** 查看打卡记录详情 */
@ -277,7 +277,7 @@ const reset = () => {
const handleQuery = () => {
queryParams.value.pageNum = 1;
getList();
getListTwoWeek();
// getListTwoWeek();
};
/** 重置按钮操作 */
@ -307,8 +307,9 @@ const incrementMonth = (dateStr: string, monthsToAdd: number) => {
/** 详情按钮操作 */
const handleDetails = async (row?: AttendanceVO) => {
const res = await listAttendanceMonth({ userId: row?.id });
calendarList.value = res.data;
const res = await listAttendanceMonth({ openid: row?.openid, dateStr: queryParams.value.dateStr });
calendarList.value = res.data.list || [];
console.log('🚀 ~ handleDetails ~ calendarList.value:', calendarList.value);
dialog.details = true;
dialog.id = row?.id;
dialog.title = row?.userName || '';
@ -336,7 +337,7 @@ const init = () => {
commandstatsIntance.value = echarts.init(commandstats.value, 'macarons');
commandstatsIntance.value.on('click', function (params) {
queryParams.value.clockDate = params.name;
queryParams.value.dateStr = params.name;
handleQuery();
});
};
@ -360,8 +361,8 @@ onUnmounted(() => {
onMounted(() => {
getTeamList();
getList();
getListTwoWeek();
init();
// getListTwoWeek();
// init();
});
</script>

View File

@ -6,7 +6,7 @@
<el-row :gutter="20" justify="space-around">
<el-col :span="12">
<el-form-item label="人脸照">
<el-image :src="userDetail?.facePicUrl" style="width: 150px; height: 150px" />
<el-image :src="userDetail?.pacePhoto" style="width: 150px; height: 150px" />
</el-form-item>
</el-col>
<el-col :span="12">
@ -31,7 +31,7 @@
</el-col>
<el-col :span="12">
<el-form-item label="民族">
{{ userDetail?.nation }}
{{ userDetail?.sfzNation }}
</el-form-item>
</el-col>
<el-col :span="12">
@ -95,7 +95,7 @@
<el-row :gutter="20">
<el-col :span="12">
<el-form-item label="施工单位">
{{ userDetail?.contractorVo?.name }}
{{ userDetail?.lwName }}
</el-form-item>
</el-col>
<el-col :span="12">
@ -112,7 +112,7 @@
<el-row :gutter="20">
<el-col :span="12">
<el-form-item label="班组">
{{ userDetail?.teamVo?.teamName }}
{{ userDetail?.bzName }}
</el-form-item>
</el-col>
<el-col :span="12">
@ -154,7 +154,7 @@ const userDetail = ref<ConstructionUserVO>();
const getUserDetail = async () => {
loading.value = true;
const res = await getConstructionUser(props.userId);
if (res.data && res.code === 200) {
if (res.data && res.code === 0) {
userDetail.value = res.data;
}
loading.value = false;

View File

@ -7,11 +7,6 @@
<el-form-item label="公司名称" prop="name">
<el-input v-model="queryParams.name" placeholder="请输入公司名称" clearable @keyup.enter="handleQuery" />
</el-form-item>
<el-form-item label="分包类型" prop="contractorType">
<el-select v-model="queryParams.contractorType" filterable placeholder="请选择类型">
<el-option v-for="(item, i) of dictList" :key="i" :label="item.dictLabel" :value="item.dictValue"> </el-option>
</el-select>
</el-form-item>
<el-form-item>
<el-button type="primary" icon="Search" @click="handleQuery">搜索</el-button>
<el-button icon="Refresh" @click="resetQuery">重置</el-button>
@ -48,17 +43,12 @@
<el-table-column type="selection" width="55" align="center" />
<el-table-column label="序号" type="index" width="60" align="center" />
<el-table-column label="公司名称" align="center" prop="name" />
<el-table-column label="分包类型" align="center">
<template #default="scope">
<span>{{ filterType(scope.row.contractorType) }}</span>
</template>
</el-table-column>
<el-table-column label="负责人" align="center" prop="principal" />
<el-table-column label="负责人联系电话" align="center" prop="principalPhone" />
<el-table-column label="负责人联系电话" align="center" prop="phone" />
<el-table-column label="管理人" align="center" prop="custodian" />
<el-table-column label="管理人联系电话" align="center" prop="custodianPhone" />
<el-table-column label="备注" align="center" prop="remark" />
<el-table-column label="创建时间" align="center" prop="createTime" width="180" />
<el-table-column label="创建时间" align="center" prop="createdAt" width="180" />
<el-table-column label="操作" align="center" class-name="small-padding fixed-width">
<template #default="scope">
<el-space wrap>
@ -81,16 +71,11 @@
<el-form-item label="公司名称" prop="name">
<el-input v-model="form.name" placeholder="请输入公司名称" />
</el-form-item>
<el-form-item label="供应商" prop="supplier">
<el-select v-model="form.supplierId" value-key="id" placeholder="请选择供应商" clearable filterable @change="">
<el-option v-for="item in supplierOptions" :key="item.id" :label="item.supplierName" :value="item.id"> </el-option>
</el-select>
</el-form-item>
<el-form-item label="负责人" prop="principal">
<el-input v-model="form.principal" placeholder="请输入负责人" />
</el-form-item>
<el-form-item label="负责人联系电话" prop="principalPhone">
<el-input v-model="form.principalPhone" placeholder="请输入负责人联系电话" />
<el-form-item label="负责人联系电话" prop="phone">
<el-input v-model="form.phone" placeholder="请输入负责人联系电话" />
</el-form-item>
<el-form-item label="管理人" prop="custodian">
<el-input v-model="form.custodian" placeholder="请输入管理人" />
@ -98,11 +83,6 @@
<el-form-item label="管理人联系电话" prop="custodianPhone">
<el-input v-model="form.custodianPhone" placeholder="请输入管理人联系电话" />
</el-form-item>
<el-form-item label="分包类型" prop="contractorType">
<el-select v-model="form.contractorType" filterable placeholder="请选择类型">
<el-option v-for="(item, i) of dictList" :key="i" :label="item.dictLabel" :value="item.dictValue"> </el-option>
</el-select>
</el-form-item>
<el-form-item label="备注" prop="remark">
<el-input v-model="form.remark" type="textarea" placeholder="请输入内容" />
</el-form-item>
@ -125,8 +105,7 @@ import { addContractor, delContractor, getContractor, listContractor, updateCont
import { ContractorForm, ContractorQuery, ContractorVO } from '@/api/project/contractor/types';
import ContractorFileDialog from '@/views/project/contractor/component/ContractorFileDialog.vue';
import { useUserStoreHook } from '@/store/modules/user';
import { getDicts, listData } from '@/api/system/dict/data';
import { listSupplierInput } from '@/api/supplierInput/supplierInput';
import { getDicts } from '@/api/system/dict/data';
const { proxy } = getCurrentInstance() as ComponentInternalInstance;
@ -155,7 +134,7 @@ const initFormData: ContractorForm = {
id: undefined,
name: undefined,
principal: undefined,
principalPhone: undefined,
phone: undefined,
custodian: undefined,
custodianPhone: undefined,
supplierId: undefined,
@ -163,7 +142,7 @@ const initFormData: ContractorForm = {
contractorType: undefined,
fileMap: undefined,
remark: undefined,
projectId: currentProject.value?.id
projectId: currentProject.value?.goId
};
const data = reactive<PageData<ContractorForm, ContractorQuery>>({
form: { ...initFormData },
@ -178,7 +157,7 @@ const data = reactive<PageData<ContractorForm, ContractorQuery>>({
custodian: undefined,
custodianPhone: undefined,
contractorType: undefined,
projectId: currentProject.value?.id,
projectId: currentProject.value?.goId,
params: {}
},
rules: {
@ -206,8 +185,8 @@ const filterType = (val) => {
const getList = async () => {
loading.value = true;
const res = await listContractor(queryParams.value);
contractorList.value = res.rows;
total.value = res.total;
contractorList.value = res.data.list;
total.value = res.data.total;
loading.value = false;
};
@ -263,10 +242,8 @@ const handleUpdate = async (row?: ContractorVO) => {
const submitForm = () => {
contractorFormRef.value?.validate(async (valid: boolean) => {
if (valid) {
form.value.projectId = currentProject.value?.id;
form.value.projectId = currentProject.value?.goId;
buttonLoading.value = true;
form.value.supplier = supplierOptions.value.find((item) => item.id == form.value.supplierId)?.supplierName;
if (form.value.id) {
await updateContractor(form.value).finally(() => (buttonLoading.value = false));
} else {
@ -288,18 +265,6 @@ const handleDelete = async (row?: ContractorVO) => {
await getList();
};
/** 获取供应商 */
const supplierOptions = ref([]);
const getSupplierList = async () => {
const res = await listSupplierInput({
projectId: currentProject.value?.id,
pageNum: 1,
state: 'finish',
pageSize: 10000
});
supplierOptions.value = res.rows;
};
/** 文件操作 **/
const visible = ref();
const currentContractorId = ref<number | string>(0);
@ -310,12 +275,11 @@ const handleContractorFile = (row?: ContractorVO) => {
};
//监听项目id刷新数据
const listeningProject = watch(
() => currentProject.value?.id,
() => currentProject.value?.goId,
(nid, oid) => {
queryParams.value.projectId = nid;
form.value.projectId = nid;
console.log('监听项目id', queryParams.value.projectId, form.value.projectId);
getSupplierList();
getList();
}
);
@ -326,6 +290,5 @@ onUnmounted(() => {
onMounted(() => {
getDictList();
getList();
getSupplierList();
});
</script>

View File

@ -14,7 +14,7 @@
<el-button icon="Refresh" @click="resetQuery">重置</el-button>
</el-form-item>
</el-form>
<!-- <el-row :gutter="10" class="mb8">
<el-row :gutter="10" class="mb8">
<el-col :span="1.5">
<el-button size="small" type="primary" plain icon="Plus" @click="handleAdd" v-hasPermi="['project:projectTeamMember:add']"> 新增 </el-button>
</el-col>
@ -45,11 +45,19 @@
</el-button>
</el-col>
<el-col :span="1.5">
<el-button size="small" type="warning" plain icon="Download" @click="handleExport" v-hasPermi="['project:projectTeamMember:export']">
<el-button
size="small"
type="warning"
plain
icon="Download"
@click="openExport"
v-hasPermi="['project:projectTeamMember:export']"
:disabled="multiple"
>
导出
</el-button>
</el-col>
</el-row> -->
</el-row>
<el-table size="small" v-loading="loading" :data="projectTeamMemberList" @selection-change="handleSelectionChange">
<el-table-column type="selection" width="55" align="center" />
<el-table-column label="序号" type="index" width="60" align="center" />
@ -59,6 +67,18 @@
<dict-tag :options="user_post_type" :value="scope.row.postId" />
</template>
</el-table-column>
<el-table-column label="操作" align="center" class-name="small-padding fixed-width">
<template #default="scope">
<el-space wrap>
<el-button link type="success" icon="Edit" @click="handleUpdate(scope.row)" v-hasPermi="['project:projectTeamMember:edit']">
修改
</el-button>
<el-button link type="danger" icon="Position" @click="handleExit(scope.row)" v-hasPermi="['project:projectTeamMember:remove']">
退场
</el-button>
</el-space>
</template>
</el-table-column>
</el-table>
<pagination
size="small"
@ -106,7 +126,19 @@
<el-input v-model="memberForm.userName" disabled></el-input>
</el-form-item>
<el-form-item label="退场文件">
<file-upload v-model="memberForm.filePath" :limit="10" :is-show-tip="false" :file-size="50" />
<file-upload
ref="uploadRef"
v-model="memberForm.filePath"
uploadUrl="/zm/api/v1/system/busConstructionUser/departure"
:accept="['png', 'jpg', 'jpeg', 'pdf']"
:data="memberForm"
:auto-upload="false"
isGo
:limit="10"
:is-show-tip="false"
show-file-list
:file-size="50"
/>
</el-form-item>
<el-form-item label="备注">
<el-input v-model="memberForm.remark" placeholder="请输入备注" type="textarea"></el-input>
@ -120,6 +152,18 @@
</span>
</template>
</el-dialog>
<el-dialog title="选择时间" v-model="visible" width="30%">
<el-form-item label="时间">
<el-date-picker v-model="exportDate" type="month" value-format="YYYY-MM" placeholder="选择日期" />
</el-form-item>
<template #footer>
<span>
<el-button @click="visible = false">取消</el-button>
<el-button type="primary" @click="handleExport">确定</el-button>
</span>
</template>
</el-dialog>
</div>
</template>
@ -137,7 +181,8 @@ import { computed, reactive, ref } from 'vue';
import { useUserStoreHook } from '@/store/modules/user';
import { listConstructionUser, delConstructionUserMember } from '@/api/project/constructionUser';
import { ConstructionUserQuery, ConstructionUserVO, ConstructionUserMembeForm } from '@/api/project/constructionUser/types';
import request from '@/utils/request-go';
const uploadRef = ref(null);
// 获取用户 store
const userStore = useUserStoreHook();
// 从 store 中获取项目列表和当前选中的项目
@ -152,14 +197,17 @@ const memberForm = reactive<ConstructionUserMembeForm>({
id: undefined,
filePath: undefined,
remark: undefined,
userName: undefined
userName: undefined,
wxOrPc: 1
});
const props = defineProps<Props>();
// 是否可见
const visible = ref(false);
const initFormData: ProjectTeamMemberForm = {
projectId: currentProject.value.goId
const exportDate = ref('');
const initFormData: any = {
projectId: currentProject.value.goId,
openid: undefined
};
const data = reactive<PageData<ProjectTeamMemberForm, ProjectTeamMemberQuery>>({
form: { ...initFormData },
@ -256,12 +304,15 @@ const userQueryParams = ref<ConstructionUserQuery>({
// 获取不在当前班组的成员
const getUserListNotInTeam = async () => {
loading.value = true;
console.log(currentProject.value.goId);
const res = await listConstructionUser({ ...userQueryParams.value, notTeamId: props.projectTeamVo.id });
userNotInTeamOpt.value = res.rows.map((user: ConstructionUserVO) => ({
userNotInTeamOpt.value = res.data.list.map((user: ConstructionUserVO) => ({
value: user.id,
label: user.userName
label: user.userName,
openid: user.openid
}));
userNotInTeamTotal.value = res.total;
userNotInTeamTotal.value = res.data.total;
loading.value = false;
};
@ -283,9 +334,12 @@ const submitForm = () => {
if (form.value.id) {
await updateProjectTeamMember(form.value).finally(() => (buttonLoading.value = false));
} else {
const openid = userNotInTeamOpt.value.find((item: any) => item.value == form.value.memberId).openid;
await addProjectTeamMember({
...form.value,
teamId: props.projectTeamVo.id
teamId: props.projectTeamVo.id,
openid
}).finally(() => (buttonLoading.value = false));
}
proxy?.$modal.msgSuccess('操作成功');
@ -300,15 +354,23 @@ const submitMemberForm = async () => {
memberFormRef.value?.validate(async (valid: boolean) => {
if (valid) {
buttonLoading.value = true;
await delConstructionUserMember(memberForm).finally(() => (buttonLoading.value = false));
uploadRef.value
.submitUpload()
.then(async (res) => {
if (res == 'nofile') {
proxy?.$modal.msgError('请上传退场文件');
} else {
proxy?.$modal.msgSuccess('操作成功');
dialog.visible = false;
await getList();
memberForm.filePath = undefined;
memberForm.remark = undefined;
memberStatus.value = false;
}
})
.finally(() => (buttonLoading.value = false));
}
});
memberStatus.value = false;
};
/** 退场按钮操作 */
@ -331,15 +393,26 @@ const handleDelete = async (row?: ProjectTeamMemberVO) => {
/** 导出按钮操作 */
const handleExport = () => {
proxy?.download(
'project/projectTeamMember/export',
request.download(
'zm/api/v1/system/busConstructionUser/exportSalary',
{
...queryParams.value
projectId: currentProject.value.goId,
dateStr: exportDate.value,
fuzzyQuery: '',
teamId: '',
typeOfWork: '',
years: exportDate.value
},
`projectTeamMember_${new Date().getTime()}.xlsx`
);
};
const openExport = () => {
exportDate.value = '';
visible.value = true;
return;
};
watch(
() => props.projectTeamVo,
(newId, oldId) => {

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,233 @@
<template>
<div class="Salary_detail">
<el-dialog v-model="isShowDialog" width="100vw" :close-on-click-modal="false" :destroy-on-close="true">
<template #header>
<div v-drag="['.Salary_detail', '.Salary_detail ']">详情</div>
</template>
<div class="content" style="margin-bottom: 20px; display: flex; font-size: 22px; color: rgb(255 99 5); justify-content: space-between">
<div style="width: 80vw">
<el-form ref="queryRef" :model="param" label-width="80px">
<el-row>
<el-col :span="6">
<el-form-item label="劳务" prop="labourService">
<el-select filterable v-model="param.labourService" placeholder="请选择劳务" clearable>
<el-option v-for="dict in laowuList" :key="dict.id" :label="dict.name" :value="dict.id" />
</el-select>
</el-form-item>
</el-col>
<el-col :span="6">
<el-form-item label="班组" prop="groupID">
<el-select filterable v-model="param.groupID" placeholder="请选择班组" clearable>
<el-option v-for="dict in teamList" :key="dict.id" :label="dict.name" :value="dict.id" />
</el-select>
</el-form-item>
</el-col>
<el-col :span="6" class="colBlock">
<el-form-item>
<el-button type="primary" @click="getbusPayrollList"
><el-icon><Search /></el-icon>搜索</el-button
>
<el-button @click="resetQuery(queryRef)"
><el-icon><Refresh /></el-icon>重置</el-button
>
</el-form-item>
</el-col>
</el-row>
</el-form>
</div>
<div>
<el-popover placement="top-start" title="" :width="200" trigger="hover" :content="DetailMoney + '元'">
<template #reference>
<el-tag class="m-2" size="large" style="cursor: pointer">金额:{{ money }}</el-tag>
</template>
</el-popover>
</div>
</div>
<div>
<el-table height="83vh" v-loading="loading" :data="tableList">
<el-table-column label="序号" align="center" type="index" min-width="50px" />
<el-table-column label="姓名" align="center" prop="name" min-width="120px" />
<el-table-column label="身份证号码" align="center" prop="identityCard" min-width="100px" />
<el-table-column label="联系方式" align="center" prop="contactWay" min-width="100px" />
<el-table-column label="班组" align="center" prop="teamOrGroup" min-width="100px" />
<el-table-column label="工种" align="center" prop="typeOfWork" min-width="100px" />
<el-table-column label="考勤时间" align="center" prop="attendanceTime" min-width="100px" />
<el-table-column label="实际工作量" align="center" prop="actualWorkload" min-width="100px" />
<el-table-column label="工资待遇" align="center">
<el-table-column label="元/量" align="center" prop="quantity" min-width="100px" />
<el-table-column label="元/天" align="center" prop="xDay" min-width="100px" />
<el-table-column label="元/月" align="center" prop="xMonth" min-width="100px" />
</el-table-column>
<el-table-column label="工资金额(元)" align="center">
<el-table-column label="加班工资" align="center" prop="overtimeWage" min-width="100px" />
<el-table-column label="应发" align="center" prop="salary" min-width="100px" />
<el-table-column label="代扣金额" align="center" prop="amountWithheld" min-width="100px" />
<el-table-column label="代缴金额" align="center" prop="amountPaid" min-width="100px" />
<el-table-column label="扣除金额" align="center" prop="deductOther" min-width="100px" />
<el-table-column label="实发金额" align="center" prop="amountPaidOut" min-width="100px" />
<el-table-column label="发放方式" align="center" prop="releaseMode" min-width="100px" />
</el-table-column>
<el-table-column label="银行卡信息" align="center">
<el-table-column label="银行卡号" align="center" prop="creditCardNumbers" min-width="100px" />
<el-table-column label="开户行" align="center" prop="openingBank" min-width="100px" />
</el-table-column>
</el-table>
<!-- <pagination
v-show="total > 0"
:total="total"
v-model:page="param.pageNum"
v-model:limit="param.pageSize"
@pagination="getbusPayrollList"
/> -->
</div>
<!-- <template #footer>
<div class="dialog-footer">
<el-button @click="onCancel"> </el-button>
</div>
</template> -->
</el-dialog>
</div>
</template>
<script lang="ts">
import { reactive, toRefs, defineComponent, ref, unref, getCurrentInstance } from 'vue';
import { busPayrollList, listBusLabourservice } from '@/api/project/salaryExcel'; //项目列表接口数据
import useUserStore from '@/store/modules/user';
import { listProjectTeam } from '@/api/project/projectTeam';
export default defineComponent({
name: 'index',
setup(props, { emit }) {
const { proxy } = <any>getCurrentInstance();
const stores = useUserStore();
const queryRef = ref();
const state = reactive({
loading: false,
isShowDialog: false,
teamList: [], //班组列表
tableList: [],
laowuList: [], //劳务
total: 0,
money: 0,
DetailMoney: 0,
param: {
pageNum: 1,
pageSize: 20,
labourService: 0,
groupID: ''
},
updateRow: null
});
// 打开弹窗
const openDialog = (row?: any) => {
state.isShowDialog = true;
state.updateRow = row;
state.param.pageNum = 1;
state.param.labourService = 0;
state.param.groupID = '';
sysProjectTeamList();
busLabourserviceList();
};
const getbusPayrollList = () => {
busPayrollList({ id: state.updateRow.id, ...state.param }).then((res: any) => {
if (res.code == 0) {
state.tableList = res.data.list;
state.total = res.data.total;
state.DetailMoney = res.data.money;
if (res.data.money >= 10000) {
state.money = (parseInt(res.data.money) / 10000).toFixed(3) + '万';
} else {
state.money = res.data.money;
}
// 判断那些班组或劳务有数据
if (res.data.bz) {
let arr = [];
state.teamList.forEach((item) => {
if (res.data.bz.includes(item.id)) {
arr.push(item);
}
});
state.teamList = arr;
}
if (res.data.lw) {
let arr1 = [];
state.laowuList.forEach((item) => {
if (res.data.lw.includes(item.id)) {
arr1.push(item);
}
});
state.laowuList = arr1;
}
}
});
};
/** 重置按钮操作 */
const resetQuery = (formEl) => {
if (!formEl) return;
formEl.resetFields();
state.param.groupID = state.teamList[0].id;
getbusPayrollList();
};
// 获取班组列表数据
const sysProjectTeamList = () => {
listProjectTeam({ pageNum: 1, pageSize: 1000, projectId: stores.selectedProject.goId }).then((res: any) => {
let list = res.data.list ?? [];
state.teamList = res.data.list;
if (state.teamList.length > 0) {
state.param.groupID = state.teamList[0].id;
}
getbusPayrollList();
});
};
// 获取列表数据
const busLabourserviceList = () => {
listBusLabourservice({ pageNum: 1, pageSize: 1000 }).then((res: any) => {
let list = res.data.list ?? [];
res.data.list.unshift({ name: '全部', id: 0 });
state.laowuList = list;
});
};
const getQuestRecordList = () => {};
// 关闭弹窗
const closeDialog = () => {
state.isShowDialog = false;
};
// 取消
const onCancel = () => {
closeDialog();
};
return {
proxy,
openDialog,
getQuestRecordList,
closeDialog,
onCancel,
resetQuery,
queryRef,
getbusPayrollList,
...toRefs(state)
};
}
});
</script>
<style lang="scss">
.Salary_detail {
.el-tag__content {
font-size: 20px;
font-weight: 600;
}
.pagination-container {
padding: 10px !important;
}
.el-dialog {
// height: 100vh;
}
.el-dialog__body {
height: 93vh !important;
max-height: 100vh !important;
}
.el-dialog__headerbtn .el-dialog__close {
color: #2a2b2d;
font-size: 30px !important;
}
}
</style>

View File

@ -0,0 +1,190 @@
<template>
<div class="document_detail" id="document_detail">
<div class="move_pop" id="detial_pop">
<!-- <span>{{ title }}</span> -->
<div class="box">
<img v-if="type == 2" src="../icon/suo.png" @click="onFull(1)" />
<img v-else src="../icon/full.png" @click="onFull(2)" />
<span class="close" @click="onClose"></span>
</div>
</div>
<div class="box_app" id="box_app"></div>
</div>
</template>
<script lang="ts">
import { toRefs, reactive, onMounted, defineComponent, getCurrentInstance } from 'vue';
import { setMove } from '@/utils/moveDiv';
export default defineComponent({
name: 'index',
setup(props, { emit }) {
const { proxy } = <any>getCurrentInstance();
const state = reactive({
title: '',
type: 2
});
onMounted(() => {
setMove('detial_pop', 'document_detail');
});
// 打开弹窗
const openDialog = (obj) => {
state.title = obj.name;
init(obj);
};
const onError = function (event) {
//举例,强制保存后,判断文档内容是否保存成功
if (event.data) {
if (event.data.errorCode == 'forcesave') {
var desc = event.data.errorDescription;
desc = JSON.parse(desc);
if (desc.error == 0) {
//保存成功
} else {
//保存失败或异常
}
} else if (event.data.errorCode == 'setallcellvalue') {
var desc = event.data.errorDescription;
desc = JSON.parse(desc);
if (desc.error == 0) {
//填充成功
} else if (desc.error == -1) {
//当前文档正处于协同编辑中
} else {
//填充异常
}
} else if (event.data.errorCode == 'clearsheet') {
var desc = event.data.errorDescription;
desc = JSON.parse(desc);
if (desc.error == 0) {
//清除成功
} else if (desc.error == -1) {
//当前文档正处于协同编辑中
} else {
//清除异常
}
}
}
};
const onDocumentReady = function () {
// console.log('文档加载完成');
};
const init = (obj) => {
let documentKey = obj.id.toString() + new Date().getTime();
let baseURL = window['$HOSTSRC'].replace('ws:', 'http:').replace('/ws', '');
let url = baseURL + obj.filenPathCoding.replaceAll('+', ' ');
let type = obj.suffix;
if (obj.suffix.includes('.')) {
type = obj.suffix.substring(1);
}
let documentType = 'word'; // docx doc
if (type == 'xlsx' || type == 'xls') {
documentType = 'cell'; //电子表格
} else if (type == 'ppt' || type == 'pptx') {
documentType = 'slide'; //演示文档文件
}
new CXO_API.CXEditor('box_app', {
document: {
fileType: type,
key: documentKey,
title: obj.name,
url
},
documentType,
editorConfig: {
mode: 'view',
callbackUrl: ''
},
height: '100%',
events: {
onDocumentReady: onDocumentReady,
onError: onError
},
zoom: -1
});
};
const onClose = () => {
emit('onClose', false);
};
const onFull = (type) => {
// 全屏
let document_detail = document.getElementById('document_detail');
state.type = type;
if (type == 2) {
document_detail.style.width = '100%';
document_detail.style.height = '100%';
} else {
document_detail.style.width = '1200px';
document_detail.style.height = '80vh';
}
};
return {
proxy,
openDialog,
onClose,
onFull,
...toRefs(state)
};
}
});
</script>
<style lang="scss">
.document_detail {
position: fixed;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
z-index: 999999;
width: 100%;
height: 100%;
border: 1px solid #9f9f9f;
.box_app {
// width: 1300px !important;
// height: 80vh !important;
background-color: #f1f1f1;
}
.move_pop {
width: 100%;
// position: absolute;
// top: 0;
// right: 0%;
height: 24px;
// background: linear-gradient(#2a5095, #213f7b, #111e48);
background-color: #f4f5f6;
display: grid;
place-items: center;
> span {
color: #000000;
font-weight: bold;
font-size: 20px;
letter-spacing: 2px;
}
.box {
display: flex;
width: 60px;
position: absolute;
top: 0;
right: 10px;
// height: 100%;
align-items: center;
img {
width: 22px;
margin-top: 6px;
cursor: pointer;
}
.close {
position: absolute;
right: 2px;
/* top: -8px; */
color: #8d8d8d;
width: 24px;
height: 24px;
font-size: 20px;
//border: 2px solid #0ff;
border-radius: 50%;
display: grid;
place-items: center;
cursor: pointer;
}
}
}
}
</style>

View File

@ -0,0 +1,167 @@
<template>
<div class="system-busSalaryDetails-add">
<el-dialog v-model="isShowDialog" width="600px" :close-on-click-modal="false" :destroy-on-close="true">
<template #header>
<div v-drag="['.system-busSalaryDetails-add .el-dialog', '.system-busSalaryDetails-add .el-dialog__header']">上传工资表</div>
</template>
<el-form ref="formRef" :model="formData" :rules="rules" label-width="110px">
<el-row>
<el-col :span="12">
<el-form-item label="日期" prop="yearToDate">
<el-date-picker v-model="formData.yearToDate" type="month" value-format="YYYY-MM" placeholder="请选择月份" />
</el-form-item>
</el-col>
<!-- <el-col :span="12">
<el-form-item prop="yearToDate">
<el-input v-model="" placeholder=""></el-input>
</el-form-item>
</el-col> -->
<el-col :span="16">
{{ BASE_URL }}
111
<el-form-item label="上传excel文件" prop="excelPath">
<el-upload
ref="upload"
class="upload-demo"
:action="`${BASE_URL}/zm/api/v1/system/upload/singleFile`"
:limit="1"
:on-exceed="handleExceed"
:auto-upload="true"
accept="application/vnd.ms-excel,application/vnd.openxmlformats-officedocument.spreadsheetml.sheet"
:headers="headers"
:on-success="onSuccess"
>
<template #trigger>
<el-button type="primary">选择表格</el-button>
</template>
<template #tip>
<div class="el-upload__tip text-red">限制1个文件新文件将覆盖旧文件</div>
</template>
</el-upload>
</el-form-item>
</el-col>
</el-row>
</el-form>
<template #footer>
<div class="dialog-footer">
<el-button type="primary" @click="onSubmit"> </el-button>
<el-button @click="onCancel"> </el-button>
</div>
</template>
</el-dialog>
</div>
</template>
<script lang="ts">
import { reactive, toRefs, defineComponent, ref, unref, getCurrentInstance } from 'vue';
import { UploadInstance, UploadProps, UploadRawFile, genFileId, ElMessage } from 'element-plus';
import { Session } from '@/utils/storage';
import { importExcelPaySheet } from '@/api/project/salaryExcel'; //项目列表接口数据
import sign from '@/utils/sign.js';
import { getToken } from '@/utils/auth';
export default defineComponent({
name: 'index',
setup(props, { emit }) {
const { proxy } = getCurrentInstance() as ComponentInternalInstance;
const formRef = ref<HTMLElement | null>(null);
const upload = ref<UploadInstance>();
const state = reactive({
fileList: [],
loading: false,
isShowDialog: false,
BASE_URL: import.meta.env.VITE_APP_BASE_API_GO,
formData: {
excelPath: '', //文件路径
yearToDate: '', //日期
name: '', //文件名
suffix: '' //后缀
},
// 表单校验
rules: {
yearToDate: [{ required: true, message: '请选择日期', trigger: 'blur' }],
excelPath: [{ required: true, message: '请选择表格', trigger: 'blur' }]
},
token: `Bearer ${proxy.$cache.local.get('goToken')}`
});
const headers = reactive({
Authorization: state.token,
...sign({})
});
// 打开弹窗
const openDialog = () => {
resetForm();
console.log(state.BASE_URL);
state.isShowDialog = true;
};
// 关闭弹窗
const closeDialog = () => {
state.isShowDialog = false;
};
const handleExceed: UploadProps['onExceed'] = (files) => {
upload.value!.clearFiles();
const file = files[0] as UploadRawFile;
file.uid = genFileId();
upload.value!.handleStart(file);
};
// 取消
const onCancel = () => {
closeDialog();
};
const onSuccess = (res) => {
if (res.code == 0) {
state.formData.excelPath = res.data.path;
state.formData.name = res.data.name;
let lastIndex = res.data.name.lastIndexOf('.');
state.formData.suffix = res.data.name.substring(lastIndex + 1);
} else {
proxy.$message.error(res.message);
}
};
// 提交
const onSubmit = () => {
const formWrap = unref(formRef) as any;
if (!formWrap) return;
formWrap.validate((valid: boolean) => {
if (valid) {
importExcelPaySheet({ ...state.formData, yearToDate: state.formData.yearToDate + '-民工工资表' }).then((res: any) => {
if (res.code == 0) {
ElMessage.success('上传成功');
closeDialog();
emit('busSalaryDetailsList');
} else {
ElMessage.error(res.message);
}
});
}
});
};
const resetForm = () => {
state.formData = {
excelPath: '', //文件路径
yearToDate: '' //日期
};
};
return {
proxy,
handleExceed,
openDialog,
upload,
closeDialog,
onCancel,
onSuccess,
onSubmit,
formRef,
BASE_URL: state.BASE_URL,
headers,
...toRefs(state)
};
}
});
</script>
<style scoped lang="scss">
//
.system-busSalaryDetails-add {
.el-col {
margin: 10px 0 !important;
}
}
</style>

View File

@ -41,23 +41,23 @@
</el-table-column>
</el-table>
</el-card>
<!-- <uploadSalary ref="uploadSalaryRef" @busSalaryDetailsList="busSalaryDetailsList"></uploadSalary>
<uploadSalaryVue ref="uploadSalaryRef" @busSalaryDetailsList="busSalaryDetailsList"></uploadSalaryVue>
<detail ref="detailRef" @busSalaryDetailsList="busSalaryDetailsList"></detail>
<documentDetail ref="documentDetailRef" v-if="showDocumentDetail" @onClose="showDocumentDetail = false"></documentDetail> -->
<documentDetail ref="documentDetailRef" v-if="showDocumentDetail" @onClose="showDocumentDetail = false"></documentDetail>
</div>
</template>
<script setup lang="ts">
import { ref, reactive, onMounted, getCurrentInstance, nextTick, toRaw } from 'vue';
// import uploadSalary from '/@/views/system/salaryExcel/component/uploadSalary.vue';
// import detail from '/@/views/system/salaryExcel/component/detail.vue';
// import { readAllImportedListData, getTheSourceExcelAccordingToTheIdOfThePayroll, deletePayroll } from '/@/api/system/salaryExcel';
// import documentDetail from '/@/views/OnlineEngineering/comm/documentsDetail/index.vue';
import uploadSalaryVue from './component/uploadSalary.vue';
import detail from './component/detail.vue';
import { readAllImportedListData, getTheSourceExcelAccordingToTheIdOfThePayroll, deletePayroll } from '@/api/project/salaryExcel';
import documentDetail from './component/documentsDetail/index.vue';
import { ElMessageBox, ElMessage } from 'element-plus';
import { useUserStoreHook } from '@/store/modules/user';
const stores = useUserStoreHook();
const { proxy } = <any>getCurrentInstance();
const BASE_URL = import.meta.env.VITE_APP_BASE_API_GO;
const loading = ref(false);
const uploadSalaryRef = ref();
const editRef = ref();
@ -130,7 +130,7 @@ const DownloadSalary = (row: any) => {
};
const DownloadSalaryMOdel = () => {
window.open('http://zmkg.cqet.top:8899/file/masterMask/coryStorageTemplate/工资表模板.xlsx', '_blank');
window.open(BASE_URL + '/file/masterMask/coryStorageTemplate/工资表模板.xlsx', '_blank');
};
const delSalary = () => {
@ -153,7 +153,7 @@ const handleSelectionChange = (selection: any[]) => {
};
onMounted(() => {
// initTableData();
initTableData();
});
</script>

View File

@ -4,16 +4,16 @@
<div v-show="showSearch" class="mb-[10px]">
<el-card shadow="hover">
<el-form ref="queryFormRef" :model="queryParams" :inline="true">
<el-form-item label="工种" prop="workType">
<el-select v-model="queryParams.workType" placeholder="全部" clearable>
<el-form-item label="工种" prop="typeOfWork">
<el-select v-model="queryParams.typeOfWork" placeholder="全部" clearable>
<el-option v-for="dict in type_of_work" :key="dict.value" :label="dict.label" :value="dict.value" />
</el-select>
</el-form-item>
<el-form-item label="工资计算方式" prop="wageCalculationType" label-width="100px">
<!-- <el-form-item label="工资计算方式" prop="wageCalculationType" label-width="100px">
<el-select v-model="queryParams.wageCalculationType" placeholder="全部" clearable>
<el-option v-for="dict in wageCalculationTypeList" :key="dict.value" :label="dict.label" :value="dict.value" />
</el-select>
</el-form-item>
</el-form-item> -->
<!-- <el-form-item label="工资计量单位" prop="wageMeasureUnit" label-width="100px">
<el-select v-model="queryParams.wageMeasureUnit" placeholder="请选择工资计量单位" clearable>
<el-option v-for="dict in wage_measure_unit_type" :key="dict.value" :label="dict.label" :value="dict.value" />
@ -44,9 +44,6 @@
>删除
</el-button>
</el-col>
<el-col :span="1.5">
<el-button type="warning" plain icon="Download" @click="handleExport" v-hasPermi="['project:workWage:export']">导出 </el-button>
</el-col>
<right-toolbar v-model:showSearch="showSearch" @queryTable="getList"></right-toolbar>
</el-row>
</template>
@ -56,29 +53,13 @@
<el-table-column label="序号" align="center" type="index" width="60px" />
<!-- <el-table-column label="主键id" align="center" prop="id" v-if="true" /> -->
<!-- <el-table-column label="项目id" align="center" prop="projectId" /> -->
<el-table-column label="工种" align="center" prop="workType">
<el-table-column label="工种" align="center" prop="typeOfWork">
<template #default="scope">
<dict-tag :options="type_of_work" :value="scope.row.workType" />
<dict-tag :options="type_of_work" :value="scope.row.typeOfWork" />
</template>
</el-table-column>
<el-table-column label="是否是特种兵" align="center" prop="isSpecialType">
<template #default="scope">
{{ scope.row.isSpecialType == 1 ? '是' : '否' }}
</template>
</el-table-column>
<el-table-column label="工资计算方式" align="center" prop="wageCalculationType">
<template #default="scope">
{{ scope.row.wageCalculationType == 1 ? '计时' : '计件' }}
</template>
</el-table-column>
<el-table-column label="工资标准" align="center" prop="wage" />
<el-table-column label="工资计量单位" align="center" prop="wageMeasureUnit">
<template #default="scope">
<dict-tag :options="wage_measure_unit_type" :value="scope.row.wageMeasureUnit" />
</template>
</el-table-column>
<el-table-column label="创建时间" align="center" prop="createTime" />
<el-table-column label="备注" align="center" prop="remark" />
<el-table-column label="工资标准" align="center" prop="standard" />
<el-table-column label="创建时间" align="center" prop="createdAt" />
<el-table-column label="操作" align="center" class-name="small-padding fixed-width">
<template #default="scope">
<el-tooltip content="修改" placement="top">
@ -99,32 +80,19 @@
<!-- <el-form-item label="项目id" prop="projectId">
<el-input v-model="form.projectId" placeholder="请输入项目id" />
</el-form-item> -->
<el-form-item label="工种" prop="workType">
<el-select v-model="form.workType" placeholder="请选择工种" :disabled="!form.id ? false : true">
<el-form-item label="工种" prop="typeOfWork">
<el-select v-model="form.typeOfWork" placeholder="请选择工种" :disabled="!form.id ? false : true">
<el-option v-for="dict in type_of_work" :key="dict.value" :label="dict.label" :value="dict.value"></el-option>
</el-select>
</el-form-item>
<el-form-item label="是否是特种兵 " prop="isSpecialType">
<el-select v-model="form.isSpecialType" placeholder="请选择是否是特种兵">
<el-option v-for="dict in isSpecialTypeList" :key="dict.value" :label="dict.label" :value="dict.value"></el-option>
</el-select>
</el-form-item>
<el-form-item label="工资计算方式" prop="wageCalculationType">
<el-select v-model="form.wageCalculationType" placeholder="请选择工资计算方式" :disabled="!form.id ? false : true">
<el-option v-for="dict in wageCalculationTypeList" :key="dict.value" :label="dict.label" :value="dict.value"></el-option>
</el-select>
</el-form-item>
<el-form-item label="工资标准" prop="wage">
<el-input v-model="form.wage" placeholder="请输入工资标准" />
<el-form-item label="工资标准" prop="standard">
<el-input v-model="form.standard" placeholder="请输入工资标准" />
</el-form-item>
<!-- <el-form-item label="工资计量单位" prop="wageMeasureUnit">
<el-select v-model="form.wageMeasureUnit" placeholder="请选择工资计量单位">
<el-option v-for="dict in wage_measure_unit_type" :key="dict.value" :label="dict.label" :value="dict.value"></el-option>
</el-select>
</el-form-item> -->
<el-form-item label="备注" prop="remark">
<el-input v-model="form.remark" type="textarea" placeholder="请输入内容" />
</el-form-item>
</el-form>
<template #footer>
<div class="dialog-footer">
@ -137,13 +105,11 @@
</template>
<script setup name="WorkWage" lang="ts">
import { listWorkWage, getWorkWage, delWorkWage, addWorkWage, updateWorkWage } from '@/api/project/workWage';
import { listWorkWage, getWorkWage, delWorkWage, addWorkWage, updateWorkWage, getTypeOfWork } from '@/api/project/workWage';
import { WorkWageVO, WorkWageQuery, WorkWageForm, SpecialType } from '@/api/project/workWage/types';
import { useUserStoreHook } from '@/store/modules/user';
const { proxy } = getCurrentInstance() as ComponentInternalInstance;
const { type_of_work, wage_measure_unit_type } = toRefs<any>(proxy?.useDict('type_of_work', 'wage_measure_unit_type'));
console.log(type_of_work);
// 获取用户 store
const userStore = useUserStoreHook();
@ -176,11 +142,11 @@ const dialog = reactive<DialogOption>({
const initFormData: WorkWageForm = {
id: undefined,
projectId: currentProject.value?.id,
projectId: currentProject.value?.goId,
workType: undefined,
isSpecialType: undefined,
wageCalculationType: undefined,
wage: undefined,
standard: undefined,
wageMeasureUnit: undefined,
remark: undefined
};
@ -189,7 +155,7 @@ const data = reactive<PageData<WorkWageForm, WorkWageQuery>>({
queryParams: {
pageNum: 1,
pageSize: 10,
projectId: currentProject.value?.id,
projectId: currentProject.value?.goId,
workType: undefined,
isSpecialType: undefined,
wageCalculationType: undefined,
@ -208,8 +174,8 @@ const { queryParams, form, rules } = toRefs(data);
const getList = async () => {
loading.value = true;
const res = await listWorkWage(queryParams.value);
workWageList.value = res.rows;
total.value = res.total;
workWageList.value = res.data.list;
total.value = res.data.total;
loading.value = false;
};
@ -266,7 +232,7 @@ const submitForm = () => {
workWageFormRef.value?.validate(async (valid: boolean) => {
if (valid) {
buttonLoading.value = true;
form.value.projectId = currentProject.value?.id;
form.value.projectId = currentProject.value?.goId;
if (form.value.id) {
await updateWorkWage(form.value).finally(() => (buttonLoading.value = false));
} else {
@ -287,21 +253,25 @@ const handleDelete = async (row?: WorkWageVO) => {
proxy?.$modal.msgSuccess('删除成功');
await getList();
};
/** 导出按钮操作 */
const handleExport = () => {
proxy?.download(
'project/workWage/export',
{
...queryParams.value
},
`workWage_${new Date().getTime()}.xlsx`
);
const type_of_work = ref([]);
const { wage_measure_unit_type } = toRefs<any>(proxy?.useDict('wage_measure_unit_type'));
console.log(wage_measure_unit_type);
const getWorkType = async () => {
const res = await getTypeOfWork();
type_of_work.value = res.data.values.map((item) => {
return {
label: item.value,
value: item.key,
elTagClass: '',
elTagType: 'default'
};
});
console.log('🚀 ~ getWorkType ~ type_of_work.value:', type_of_work.value);
};
//监听项目id刷新数据
const listeningProject = watch(
() => currentProject.value?.id,
() => currentProject.value?.goId,
(nid, oid) => {
queryParams.value.projectId = nid;
form.value.projectId = nid;
@ -315,5 +285,6 @@ onUnmounted(() => {
onMounted(() => {
getList();
getWorkType();
});
</script>

View File

@ -0,0 +1,141 @@
<template>
<div class="system-document-container">
<el-card shadow="hover">
<div class="system-document-search mb15">
<el-form :model="param" ref="queryRef" :inline="true" label-width="100px">
<el-row>
<el-col>
<el-button
type="success"
v-auth="'api/v1/system/documentQualityMeeting/qualityDataRecyclingStation'"
:disabled="multiple"
@click="onRecyclingStation(null, true)"
><el-icon><RefreshRight /></el-icon>批量恢复</el-button
>
</el-col>
</el-row>
</el-form>
</div>
<el-table v-loading="loading" :data="tableData" @selection-change="handleSelectionChange">
<el-table-column type="selection" width="55" align="center" />
<el-table-column label="序号" align="center" type="index" min-width="30px" />
<el-table-column label="文件名称" align="center" prop="name" min-width="100px" />
<el-table-column label="文件类型" align="center" prop="type" min-width="100px">
<template #default="scope">
<span>{{ scope.row.type == 1 ? '文件' : '文件夹' }}</span>
</template> </el-table-column
><el-table-column label="文件路径" align="center" min-width="100px">
<template #default="scope">
<span>{{ scope.row.filenPath }}</span>
</template>
</el-table-column>
<el-table-column label="删除时间" align="center" prop="deletedAt" min-width="100px"> </el-table-column>
<el-table-column label="操作" align="center" class-name="small-padding" min-width="100px" fixed="right">
<template #default="scope">
<el-button
type="success"
v-auth="'api/v1/system/documentQualityMeeting/qualityDataRecyclingStation'"
link
@click="onRecyclingStation(scope.row)"
><el-icon><RefreshRight /></el-icon>恢复</el-button
>
</template>
</el-table-column>
</el-table>
<pagination v-show="total > 0" :total="total" v-model:page="param.pageNum" v-model:limit="param.pageSize" @pagination="documentList" />
</el-card>
</div>
</template>
<script lang="ts">
import { toRefs, reactive, ref, defineComponent, getCurrentInstance } from 'vue';
import { ElMessageBox, ElMessage, ElLoading } from 'element-plus';
import { qualityRecycleBinList, qualityDataRecyclingStation } from '@/api/quality/documentQualityMeeting';
import { useUserStoreHook } from '@/store/modules/user';
export default defineComponent({
name: 'index',
setup() {
const stores = useUserStoreHook();
const { proxy } = <any>getCurrentInstance();
const loading = ref(false);
const queryRef = ref();
// 非多个禁用
const multiple = ref(true);
const state = reactive({
tableData: [],
param: {
type: 2,
projectId: stores.selectedProject.goId
},
total: 0,
ids: [] //所选择的文件
});
// 获取资料删除的列表数据
const getDocumentDataList = () => {
loading.value = true;
qualityRecycleBinList(state.param).then((res: any) => {
let list = res.data.list ?? [];
state.tableData = list;
state.total = res.data.total;
loading.value = false;
});
};
// 多选框选中数据
const handleSelectionChange = (selection) => {
state.ids = selection.map((item) => item.id);
multiple.value = !selection.length;
};
const onRecyclingStation = (row) => {
let ids = [];
if (row) {
ids = [row.id];
} else {
// 批量
ids = state.ids;
}
ElMessageBox.confirm('你确定要恢复所选文件或文件夹?', '提示', {
confirmButtonText: '确认',
cancelButtonText: '取消',
type: 'warning'
})
.then(() => {
const loading = ElLoading.service({
lock: true,
text: '正在恢复中……',
background: 'rgba(0, 0, 0, 0.7)'
});
qualityDataRecyclingStation({
ids,
type: 1
}).then((res) => {
loading.close();
if (res.code == 0) {
getDocumentDataList();
ElMessage.success('操作成功');
} else {
ElMessage.error(res.message);
}
});
})
.catch(() => {});
};
return {
proxy,
multiple,
loading,
onRecyclingStation,
handleSelectionChange,
getDocumentDataList,
...toRefs(state)
};
}
});
</script>
<style lang="scss" scoped>
.colBlock {
display: block;
}
.colNone {
display: none;
}
</style>

View File

@ -0,0 +1,551 @@
<template>
<div class="documentCompletion-data">
<el-tabs v-model="activeName" class="demo-tabs" @tab-click="handleClick">
<el-tab-pane label="文件夹" name="first">
<el-card>
<el-row>
<el-col :span="2" class="colBlock">
<el-button
type="success"
v-auth="'api/v1/system/documentQualityMeeting/qualityNewFolderData'"
:disabled="toolStart"
@click="handleFile(3)"
><el-icon><Plus /></el-icon>新建文件夹</el-button
>
</el-col>
<el-col :span="2" class="colBlock">
<el-button type="primary" v-auth="'api/v1/system/documentQualityMeeting/add'" :disabled="toolStart" @click="handleFile(2)"
><el-icon><Upload /></el-icon>上传文件</el-button
>
</el-col>
</el-row>
</el-card>
<el-card style="margin-top: 10px">
<div class="breadcrumb-img">
<el-breadcrumb>
<el-breadcrumb-item @click="onBreadcrumb(item)" v-for="(item, i) of breadcrumbList" :key="i">
<span title="点击打开文件夹" style="cursor: pointer">{{ item.name }}</span>
</el-breadcrumb-item>
</el-breadcrumb>
<div class="tool-All">
<div v-if="!toolStart">
<el-button type="primary" v-auth="'api/v1/system/documentQualityMeeting/delete'" @click="onBatchAll">
<el-icon><Menu /></el-icon>批量操作</el-button
>
</div>
<div v-if="toolStart">
<el-button type="warning" @click="onBatchAll">
<el-icon><Tools /></el-icon>取消操作</el-button
>
<el-button type="danger" @click="onDeleteAll">
<el-icon><Delete /></el-icon>删除</el-button
>
</div>
</div>
</div>
</el-card>
<el-card style="margin-top: 10px">
<div class="file_detail" id="file_detail1">
<el-row class="row-bg" v-if="fileList.length">
<el-col :span="2" v-for="(item, i) of fileList" :key="i">
<div :class="{ file_style: true }">
<div @click="onNav(item)" title="点击打开文件" @contextmenu="onContextmenu($event, item, i)">
<img src="@/assets/icons/file1.png" v-if="item.suffix == 'folder'" alt="" />
<img src="@/assets/icons/file.png" v-else-if="item.suffix == 'file'" alt="" />
<el-image
v-else-if="item.suffix == 'image'"
style="width: 100%; height: 100%"
:src="item.filenPathCoding"
:zoom-rate="1.2"
:max-scale="7"
:min-scale="0.2"
:initial-index="4"
:preview-src-list="[item.filenPathCoding]"
fit="cover"
/>
<img :src="'/image/' + item.suffix + '.png'" v-else />
</div>
<span @click="onFileName(item)" title="点击重命名">{{ item.name }}</span>
<div :class="{ fileActive: toolStart }" v-if="toolStart" @click="onToolAll(item)"></div>
<div class="checkbox-box" v-if="toolStart">
<el-checkbox v-model="item.checkbox" size="large" />
</div>
</div>
</el-col>
</el-row>
<el-empty :image-size="200" description="暂无文件" v-else />
<div class="right_box" id="right_box">
<div v-for="(item, i) of list" :key="i" v-auth="item.auth" @click="item.callback($event)">
{{ item.name }}
</div>
</div>
</div>
</el-card>
</el-tab-pane>
<el-tab-pane label="回收站" name="second">
<RecyclingStation ref="RecyclingStationRef"></RecyclingStation>
</el-tab-pane>
</el-tabs>
</div>
</template>
<script lang="ts">
import { toRefs, reactive, onMounted, ref, defineComponent, computed, getCurrentInstance, toRaw, nextTick, onBeforeUnmount } from 'vue';
import { ElMessageBox, ElMessage, ElLoading } from 'element-plus';
import {
documentQualityMeetingTreeStructure,
documentQualityMeetingDelete,
documentQualityMeetingAdd,
documentQualityMeetingEdit,
documentQualityMeetingNewFolder,
documentQualityMeetingDownload
} from '@/api/quality/documentQualityMeeting/index';
// 回收站
import RecyclingStation from '@/views/quality/documentQualityMeeting/RecyclingStation/index.vue';
import { useUserStoreHook } from '@/store/modules/user';
const stores = useUserStoreHook();
export default defineComponent({
name: 'index',
components: {
RecyclingStation
},
setup() {
const { proxy } = <any>getCurrentInstance();
const RecyclingStationRef = ref();
// 字典选项数据
const {} = proxy.useDict();
// 文件下载
const onExport = (event) => {
event.stopPropagation();
// 文件下载 state.typeFile: 1、文件夹 2、文件
if (state.typeFile == 1) {
window.open(state.relativePath, '_black');
} else {
documentQualityMeetingDownload({ relativePath: state.relativePath, type: state.typeFile }).then((res) => {
if (res.code == 0) {
window.open(res.data.Path, '_black');
}
});
}
};
// 文件删除
const onDeleteFile = (event, item) => {
event.stopPropagation();
setDel([state.delId]);
};
const state = reactive({
fileList: [],
activeName: 'first',
breadcrumbList: [{ id: 0, name: '目录' }], //菜单列表
projectId: stores.selectedProject.goId,
parentPid: '0', //父级的id 默认为0
fileType: 0, //文件 或压缩文件
list: [
{ id: 3, name: '文件详情', callback: onExport, auth: 'zm/api/v1/system/documentProductionDrawing/get' },
{ id: 1, name: '文件下载', callback: onExport, auth: 'zm/api/v1/system/documentQualityMeeting/qualityDataUniFileDownload' },
{ id: 2, name: '文件删除', callback: onDeleteFile, auth: 'zm/api/v1/system/documentCompletion/delete' }
],
relativePath: '', //文件下载需要相对路径
delId: '', //删除需要的id
toolStart: false,
imageType: ['jpg', 'png', 'jpeg'],
wordType: ['docx', 'doc', 'pdf', 'xls', 'xlsx', 'pptx', 'ppt']
});
onMounted(() => {
// 全局设置阻止右键点击
document.addEventListener('contextmenu', function (event) {
event.preventDefault();
});
let file_detail_box = document.getElementById('file_detail1');
// 监听当前元素点击事件 并关闭弹框
file_detail_box.addEventListener('click', () => {
let box = document.getElementById('right_box');
box.style.display = 'none';
});
// 默认第一级 父级pid为0
getdocumentQualityMeetingTreeStructure();
// 压缩文件上传
console.log(proxy.mittBus, proxy);
proxy.mittBus.on('bigUploader.uploadFileSuccess' + 1008, (res: any) => {
const { filename, totalSize, url, identifier, fileType } = res;
let arr = filename.split('.');
let fileType1 = arr[arr.length - 1];
if (fileType1 == 'zip' || fileType1 == 'rar') {
state.fileType = 1;
} else {
//除了压缩 其他文件
state.fileType = 2;
}
let obj = {
filePath: {
url,
name: filename,
size: totalSize,
fileType: '.' + fileType1 //后缀名
},
fileType: state.fileType,
pid: state.parentPid == 0 ? '' : state.parentPid,
projectId: state.projectId
};
documentQualityMeetingAdd(obj).then((res: any) => {
if (res.code == 0) {
ElMessage({
type: 'success',
message: '上传成功'
});
getdocumentQualityMeetingTreeStructure(); //获取当前当前文件夹的文件数据
} else {
ElMessage({
type: 'error',
message: res.message
});
}
});
});
});
onBeforeUnmount(() => {
// 取消订阅特定事件
proxy.mittBus.off('bigUploader.uploadFileSuccess' + 1008);
});
const getdocumentQualityMeetingTreeStructure = () => {
const loading = ElLoading.service({
lock: true,
text: '正在查询文件……',
background: 'rgba(0, 0, 0, 0.7)'
});
documentQualityMeetingTreeStructure({ projectId: state.projectId, pid: state.parentPid }).then((res: any) => {
loading.close();
if (res.code == 0) {
state.fileList = res.data.list || [];
if (state.fileList.length) {
// suffix
state.fileList.map((item) => {
item.checkbox = false;
item.name = item.name + item.suffix;
item.suffix = item.suffix.slice(1).toUpperCase();
// 截取后缀
if (item.filenPathCoding.indexOf('.') != -1) {
let str = item.filenPathCoding.slice(item.filenPathCoding.indexOf('.') + 1);
if (state.imageType.includes(str)) {
// 图片文件格式
item.suffix = 'image';
} else {
if (!window['$ICONLIST'].includes(item.suffix)) {
item.suffix = 'file';
}
}
} else {
// 当没得后缀的时候 默认未文件夹
item.suffix = 'folder';
}
return item;
});
}
}
});
};
const handleFile = (type) => {
state.fileType = type;
if (type == 3) {
// 新建文件夹
ElMessageBox.prompt('填写文件夹名', '新建文件夹', {
confirmButtonText: '确定',
cancelButtonText: '取消'
})
.then(({ value }) => {
// pid 父级
documentQualityMeetingNewFolder({ fileName: value, pid: state.parentPid == 0 ? '' : state.parentPid, projectId: state.projectId }).then(
(res: any) => {
if (res.code == 0) {
getdocumentQualityMeetingTreeStructure();
ElMessage({
type: 'success',
message: '添加成功'
});
} else {
ElMessage({
type: 'error',
message: res.message
});
}
}
);
})
.catch(() => {});
} else {
// 竣工图
proxy.mittBus.emit('bigUploader.uploadFile', { type: 100, types: 1008, accept: [] });
}
return;
};
// 页面跳转
const onNav = (item) => {
// 通过后缀判断该文件是什么类型
// 图片格式 jpg、png、jpeg、
// word文档格式:docx、doc、pdf、xls、xlsx、pptx、ppt
// 其他全文件夹
if (item.suffix == 'image') {
// 可以预览图片
return;
} else if (item.suffix == 'folder') {
// 打开文件夹
state.parentPid = item.idStr;
state.breadcrumbList.push(item); //路径设置
state.fileList = [];
// 获取对应文件夹的数据
getdocumentQualityMeetingTreeStructure();
} else {
window.open(item.filenPathCoding, '_black');
return;
}
};
const onFileName = (item) => {
// 修改文件名称
ElMessageBox.prompt('文件名称修改', '重命名', {
confirmButtonText: '确定',
cancelButtonText: '取消',
inputValue: item.name
})
.then(({ value }) => {
// 确定
documentQualityMeetingEdit({ id: item.id, name: value, type: item.type }).then((res: any) => {
if (res.code == 0) {
item.name = value;
getdocumentQualityMeetingTreeStructure();
ElMessage({
type: 'success',
message: '修改成功'
});
} else {
ElMessage({
type: 'error',
message: res.message
});
}
});
})
.catch(() => {});
};
const handleClick = (val) => {
if (state.activeName == 'second') {
getdocumentQualityMeetingTreeStructure();
} else {
RecyclingStationRef.value.getDocumentDataList();
}
};
const onBreadcrumb = (item) => {
if (item.name == '目录') {
state.parentPid = '0';
state.breadcrumbList = [{ id: 0, name: '目录' }]; //菜单列表
// 最初目录
getdocumentQualityMeetingTreeStructure();
} else {
let arr = [];
let array = state.breadcrumbList;
for (let index = 0; index < array.length; index++) {
arr.push(array[index]);
if (array[index].name == item.name) {
break;
}
}
state.breadcrumbList = arr;
// 通过 当前点击的文件进行获取数据
// 重复点击不用再次获取
if (item.idStr == state.parentPid) return;
state.parentPid = item.idStr;
getdocumentQualityMeetingTreeStructure();
}
};
// 批量操作数据
const onBatchAll = () => {
state.toolStart = !state.toolStart;
};
const setDel = (ids) => {
let msg = '你确定要删除所选数据?';
if (ids.length === 0) {
ElMessage.error('请选择要删除的数据。');
return;
}
ElMessageBox.confirm(msg, '温馨提示', {
confirmButtonText: '确认',
cancelButtonText: '取消',
type: 'warning'
})
.then(() => {
documentQualityMeetingDelete({ ids }).then((res) => {
if (res.code == 0) {
let box = document.getElementById('right_box');
box.style.display = 'none'; //显示div盒子
ElMessage.success('删除成功');
getdocumentQualityMeetingTreeStructure();
} else {
ElMessage.error(res.message);
}
});
})
.catch(() => {});
};
// 批量删除
const onDeleteAll = () => {
//获取所有已经选中的数据
let selectList = [];
if (state.fileList.length) {
state.fileList.map((item) => {
if (item.checkbox) {
selectList.push(item.id);
}
});
if (!selectList.length) {
ElMessage.warning('请选择需要删除的文件');
return;
}
setDel(selectList);
}
};
// 批量选择
const onToolAll = (row) => {
row.checkbox = !row.checkbox;
};
const onContextmenu = (event, item, i) => {
state.typeFile = item.type;
state.relativePath = item.filenPath;
state.delId = item.id;
let len = (100 / 12) * (i % 12) + 4 + '%';
let box = document.getElementById('right_box');
console.log(event);
box.style.top = event.clientY - 250 + 'px'; //鼠标点击时给div定位Y轴
box.style.left = len; //鼠标点击时给div定位X轴
box.style.display = 'block'; //显示div盒子
};
return {
proxy,
handleFile,
onFileName,
onNav,
handleClick,
RecyclingStationRef,
onBreadcrumb,
onBatchAll,
onDeleteAll,
onExport,
onDeleteFile,
onToolAll,
onContextmenu,
...toRefs(state)
};
}
});
</script>
<style lang="scss">
.documentCompletion-data {
.el-card__body {
padding: 10px !important;
}
.breadcrumb-img {
display: flex;
justify-content: space-between;
align-items: center;
width: 100%;
padding-right: 10px;
.tool-All {
display: flex;
align-items: center;
> div {
display: flex;
align-items: center;
}
}
.batch {
width: 24px;
}
}
.file_detail {
position: relative;
width: 100%;
height: 66vh;
overflow: auto;
.right_box {
position: absolute;
z-index: 999;
background-color: rgb(0 0 0 / 56%);
// width: 100px;
// height: 100px;
top: 0;
left: 0;
display: none;
border-radius: 6px;
padding: 14px 0;
> div {
font-size: 16px;
font-weight: bold;
color: #fff;
padding: 8px 20px;
cursor: pointer;
font-family: revert;
}
> div:hover {
background-color: rgb(0 0 0 / 80%);
}
}
.file_style {
// height: 100px;
width: 90px;
display: flex;
flex-direction: column;
align-items: center;
padding: 10px;
box-sizing: border-box;
animation: 0.5s ease;
position: relative;
margin-bottom: 10px;
> div {
width: 100%;
// height: 70%;
height: 80px;
> img {
width: 100%;
height: 100%;
}
}
.checkbox-box {
position: absolute;
top: -8px;
left: 60px;
z-index: 1000;
}
> span {
font-size: 12px;
width: 100%;
display: block;
text-align: center;
// display: flex;
// align-items: center;
// justify-content: center;
word-wrap: break-word;
}
}
.file_style:hover {
background-color: rgba(189, 189, 189, 0.322);
border-radius: 5px;
}
.fileActive {
display: block;
top: 0;
position: absolute;
z-index: 999;
left: 0;
width: 100%;
height: 100% !important;
border-radius: 5px;
background-color: rgba(189, 189, 189, 0.322);
}
}
}
.colBlock {
display: block;
}
.colNone {
display: none;
}
</style>

View File

@ -0,0 +1,414 @@
<template>
<div class="book_file">
<!-- 添加或修改公司对话框 -->
<el-dialog v-model="isShowDialog" width="80vw" custom-class="book_file_loading" :close-on-click-modal="false" :destroy-on-close="true">
<template #header>
<div v-drag="['.book_file .el-dialog', '.book_file .el-dialog__header']">查看资料文件</div>
</template>
<el-form :model="tableData.param" ref="queryRef" :inline="true" label-width="100px">
<el-row>
<el-col :span="8" class="colBlock">
<el-form-item label="项目名称" prop="project">
<el-select v-model="formData.project" :filter-method="filterMethod" filterable placeholder="请选择项目" clearable>
<el-option v-for="item of projectList" :key="item.id" :label="item.projectName" :value="item.id" />
</el-select>
</el-form-item>
</el-col>
<el-col :span="8" class="colBlock">
<el-form-item label="文件名称" prop="fileName">
<el-input v-model="formData.fileName" placeholder="请输入文件名称搜索" clearable @keyup.enter.native="getDataFileQuery" />
</el-form-item>
</el-col>
<el-col :span="8">
<el-form-item>
<el-button type="primary" @click="getDataFileQuery"
><el-icon><Search /></el-icon>搜索</el-button
>
<el-button @click="resetQuery" type="danger"
><el-icon><Refresh /></el-icon>清空</el-button
>
</el-form-item>
</el-col>
</el-row>
</el-form>
<div class="content">
<div class="left_box" :style="treeList.length ? 'width: 70%' : 'width: 100%'">
<el-table v-loading="loading" :data="tableData" border height="63vh" :empty-text="emptyText">
<el-table-column label="序号" align="center" type="index" max-width="30px" />
<el-table-column label="所属项目" align="center" prop="projectName" min-width="100px" />
<el-table-column label="文件名称" align="center" prop="name" min-width="100px" />
<el-table-column label="文件路径" align="center" min-width="100px">
<template #default="scope">
<span>{{ filterfilenPath(scope.row.filenPath) }}</span>
</template>
</el-table-column>
<el-table-column label="操作" align="center" class-name="small-padding" width="220px" fixed="right">
<template #default="scope">
<el-button type="success" link @click="onExport(scope.row)"
><el-icon><Download /></el-icon>下载</el-button
>
<el-button type="primary" link @click="onBook(scope.row)"
><el-icon><View /></el-icon>查看</el-button
>
<el-button type="primary" link @click="getAllTreeData(scope.row)"
><el-icon><View /></el-icon>项目资料</el-button
>
</template>
</el-table-column>
</el-table>
<pagination
v-show="tableData.length > 0"
:total="tableData.length"
v-model:page="pageNum"
v-model:limit="pageSize"
@pagination="getDataFileQuery"
/>
</div>
<div class="right_box" :style="treeList.length ? 'width: 30%' : 'width: 0'">
<el-tree
v-if="treeList.length"
ref="allTreeRef"
highlight-current
:filter-node-method="filterFolder"
:data="treeList"
:props="Props"
node-key="id"
accordion
:expand-on-click-node="false"
@node-click="onAllTreeNode"
>
<template #default="{ node, data }">
<span class="custom-tree-node">
<el-icon color="#f1a81a" v-if="data.type == '2'"><FolderOpened /></el-icon>
<el-icon color="#409eff" v-if="data.type == '1'"><Files /></el-icon>
<el-tooltip class="box-item" effect="dark" :content="node.label" placement="bottom" v-if="node.label.length > 20">
<span>{{ node.label.substring(0, 20) }}</span>
</el-tooltip>
<span v-else>{{ node.label }}</span>
<span style="margin-left: 15px" class="set-tool">
<el-button type="primary" v-auth="'/zm/api/v1/system/documentData/onlineImport'" link @click.stop="onExportFile(node, data)"
>下载</el-button
>
<el-button
type="success"
v-auth="'/zm/api/v1/system/documentData/get'"
link
@click.stop="onViewFile(node, data)"
v-if="data.type == '1'"
>查看</el-button
>
</span>
</span>
</template>
</el-tree>
</div>
</div>
</el-dialog>
<documentDetail ref="documentDetailRef" v-if="showDocumentDetail" @onClose="showDocumentDetail = false"></documentDetail>
</div>
</template>
<script lang="ts">
import { reactive, toRefs, defineComponent, ref, unref, getCurrentInstance, nextTick } from 'vue';
import { ElMessage, ElLoading } from 'element-plus';
// 接口引入
import {
dataFileQuery,
treeStructureData,
documentDataListUnPage,
getProfileDetail,
listSysProjectAll
} from '@/api/quality/onlineListquality/profileData';
import { uniFolderDownload, uniFileDownload } from '@/api/quality/onlineListquality/Online';
import documentDetail from '../documentsDetail/index.vue';
import axios from 'axios';
import sign from '@/utils/sign.js';
import { Session } from '@/utils/storage';
import { useUserStoreHook } from '@/store/modules/user';
export default defineComponent({
name: 'index',
components: { documentDetail },
setup(props, { emit }) {
const stores = useUserStoreHook();
const { proxy } = <any>getCurrentInstance();
const documentDetailRef = ref(); //详情在线dom
const allTreeRef = ref();
const baseURL: string | undefined | boolean = import.meta.env.VITE_API_URL;
const state = reactive({
loading: false,
tableData: [],
isShowDialog: false,
formData: {
fileName: '',
project: null
},
projectList: [],
projectQuery: {
name: ''
},
pageNum: 1,
pageSize: 10,
total: 0,
userName: stores.nickname + '' + stores.selectedProject.goId, // 当前用户名
showDocumentDetail: false, //详情弹框
emptyText: '暂无数据',
treeList: [] as any, //树形结构数据
arrayList: [] as any, //树形结构处理成一维数组
infoMap: new Map(), //用idstr 存储pid
infoList: [] as any, //文档列表数据
Props: {
children: 'treeStructureDataRes',
label: 'name'
},
paramsQuery: { idStr: '', project: '' } //请求参数
});
// 打开弹窗
const openDialog = () => {
state.isShowDialog = true;
getAllProject();
// 获取数据
state.emptyText = '请输入文件名称进行搜索!';
resetForm();
};
const resetForm = () => {
state.tableData = [];
state.formData.fileName = '';
state.treeList = [];
state.emptyText = '暂无数据';
};
// 获取项目列表
const getAllProject = () => {
listSysProjectAll(state.projectQuery).then((res: any) => {
if (res.code == 0) {
let list = res.data.list ?? [];
state.projectList = list;
if (res.data.list.length && !state.projectQuery.name) {
state.projectList.unshift({ id: 0, projectName: '全部' });
// 第一次
state.formData.project = 0;
getDataFileQuery();
}
}
});
};
const filterMethod = (val) => {
state.projectQuery.name = val;
listSysProjectAll(state.projectQuery).then((res: any) => {
if (res.code == 0) {
let list = res.data.list ?? [];
state.projectList = list;
if (!state.projectQuery.name) {
state.projectList.unshift({ id: 0, projectName: '全部' });
}
}
});
};
const getDataFileQuery = () => {
state.loading = true;
state.emptyText = '数据加载中……';
dataFileQuery(state.formData).then((res: any) => {
if (res.code == 0) {
state.loading = false;
state.tableData = [];
if (res.data.list && res.data.list.length) {
state.tableData = res.data.list;
state.total = res.data.list.length;
} else {
state.emptyText = '没有查询到数据,请重新输入搜索';
// ElMessage.warning('没有查询到数据,请重新输入搜索');
}
}
});
};
// 关闭弹窗
const closeDialog = () => {
state.isShowDialog = false;
};
// 取消
const onCancel = () => {
closeDialog();
};
// 查看资料文档
const onBook = (row) => {
getProfileDetail(row.id).then((res: any) => {
if (res.code == 0) {
// 查看文档
state.showDocumentDetail = true;
nextTick(() => {
documentDetailRef.value.openDialog(res.data);
});
}
});
};
// 下载
const onExport = (row) => {
axios({
method: 'get',
url: baseURL + '/zm' + '/api/v1/system/documentData/uniFileDownload',
responseType: 'blob',
params: {
relativePath: row.filenPath
},
headers: {
Authorization: 'Bearer ' + `${Session.get('token')}`,
...sign({
relativePath: row.filenPath
})
}
}).then((res) => {
let blob = new Blob([res.data], { type: res.headers['content-type'] });
const blobURL = window.URL.createObjectURL(blob);
const link = document.createElement('a');
link.style.display = 'none';
link.href = blobURL;
link.setAttribute('download', row.name + row.suffix);
if (typeof link.download === 'undefined') {
link.setAttribute('target', '_blank');
}
document.body.appendChild(link);
link.click();
document.body.removeChild(link);
window.URL.revokeObjectURL(blobURL);
});
};
const resetQuery = () => {
// 清空
state.tableData = [];
state.formData.fileName = '';
state.formData.project = null;
state.loading = false;
state.emptyText = '暂无数据';
};
const filterfilenPath = (val) => {
return val.substring(val.lastIndexOf(state.userName) + state.userName.length);
};
// 获取树形结构文件夹目录
const getAllTreeData = (row: any) => {
treeStructureData({ projectId: row.projectId }).then((res: any) => {
if (res.code == 0 && res.data && res.data.list) {
state.treeList = res.data.list;
state.paramsQuery.project = row.projectId;
setInfo(res.data.list);
}
});
};
// 处理数据
const setInfo = (arr) => {
arr.forEach((element) => {
state.arrayList.push(element);
state.infoMap.set(element.idStr, element.id);
if (element.treeStructureDataRes && element.treeStructureDataRes.length) {
setInfo(element.treeStructureDataRes);
}
});
};
// 选择目录文件
const onAllTreeNode = (row) => {
state.paramsQuery.idStr = row.idStr;
if (!state.paramsQuery.idStr) {
return;
}
state.loading = true;
// 获取文档列表数据
documentDataListUnPage(state.paramsQuery).then((res: any) => {
state.loading = false;
state.tableData = [];
state.emptyText = '暂无数据';
if (res.code == 0 && res.data.list && res.data.list.length) {
// if (row.treeStructureDataRes && row.treeStructureDataRes.length) {
// // 未存在的数据
// let different = res.data.list.filter((item: any) => !row.treeStructureDataRes.some((v: any) => v.id === item.id));
// if (different.length) {
// different.forEach((item) => {
// allTreeRef.value?.append(item, row.id);
// });
// }
// } else {
// res.data.list.forEach((item) => {
// allTreeRef.value?.append(item, row.id);
// });
// }
state.tableData = res.data.list;
}
});
};
// 下载文件
const onExportFile = (node, data) => {
// 文件夹
if (data.type == '2') {
uniFolderDownload(data.filenPath).then((res: any) => {
if (res.code == 0) {
let fileUrl = res.data.RelativePath;
window.open(fileUrl, '_self');
}
});
}
// 文件
if (data.type == '1') {
axios({
method: 'get',
url: baseURL + '/zm' + '/api/v1/system/documentData/uniFileDownload',
responseType: 'blob',
params: {
relativePath: data.filenPath
},
headers: { Authorization: 'Bearer ' + `${Session.get('token')}` }
}).then((res) => {
let blob = new Blob([res.data], { type: res.headers['content-type'] });
const blobURL = window.URL.createObjectURL(blob);
const link = document.createElement('a');
link.style.display = 'none';
link.href = blobURL;
link.setAttribute('download', data.name + data.suffix);
if (typeof link.download === 'undefined') {
link.setAttribute('target', '_blank');
}
document.body.appendChild(link);
link.click();
document.body.removeChild(link);
window.URL.revokeObjectURL(blobURL);
});
}
};
// 树形中的查看
const onViewFile = (node, data) => {
onBook(data);
};
return {
proxy,
openDialog,
closeDialog,
onCancel,
onExport,
onBook,
resetQuery,
getDataFileQuery,
filterfilenPath,
documentDetailRef,
resetForm,
getAllTreeData,
setInfo,
onAllTreeNode,
allTreeRef,
onExportFile,
onViewFile,
getAllProject,
filterMethod,
...toRefs(state)
};
}
});
</script>
<style scoped lang="scss">
.book_file {
.content {
width: 100%;
height: 100%;
display: flex;
flex-direction: row;
justify-content: space-between;
}
}
</style>

View File

@ -0,0 +1,190 @@
<template>
<div class="document_detail" id="document_detail">
<div class="move_pop" id="detial_pop">
<!-- <span>{{ title }}</span> -->
<div class="box">
<img v-if="type == 2" src="../icon/suo.png" @click="onFull(1)" />
<img v-else src="../icon/full.png" @click="onFull(2)" />
<span class="close" @click="onClose"></span>
</div>
</div>
<div class="box_app" id="box_app"></div>
</div>
</template>
<script lang="ts">
import { toRefs, reactive, onMounted, defineComponent, getCurrentInstance } from 'vue';
import { setMove } from '@/utils/moveDiv';
export default defineComponent({
name: 'index',
setup(props, { emit }) {
const { proxy } = <any>getCurrentInstance();
const state = reactive({
title: '',
type: 2
});
onMounted(() => {
setMove('detial_pop', 'document_detail');
});
// 打开弹窗
const openDialog = (obj) => {
state.title = obj.name;
init(obj);
};
const onError = function (event) {
//举例,强制保存后,判断文档内容是否保存成功
if (event.data) {
if (event.data.errorCode == 'forcesave') {
var desc = event.data.errorDescription;
desc = JSON.parse(desc);
if (desc.error == 0) {
//保存成功
} else {
//保存失败或异常
}
} else if (event.data.errorCode == 'setallcellvalue') {
var desc = event.data.errorDescription;
desc = JSON.parse(desc);
if (desc.error == 0) {
//填充成功
} else if (desc.error == -1) {
//当前文档正处于协同编辑中
} else {
//填充异常
}
} else if (event.data.errorCode == 'clearsheet') {
var desc = event.data.errorDescription;
desc = JSON.parse(desc);
if (desc.error == 0) {
//清除成功
} else if (desc.error == -1) {
//当前文档正处于协同编辑中
} else {
//清除异常
}
}
}
};
const onDocumentReady = function () {
// console.log('文档加载完成');
};
const init = (obj) => {
let documentKey = obj.id.toString() + new Date().getTime();
let baseURL = window['$HOSTSRC'].replace('ws:', 'http:').replace('/ws', '');
let url = baseURL + obj.filenPathCoding.replaceAll('+', ' ');
let type = obj.suffix;
if (obj.suffix.includes('.')) {
type = obj.suffix.substring(1);
}
let documentType = 'word'; // docx doc
if (type == 'xlsx' || type == 'xls') {
documentType = 'cell'; //电子表格
} else if (type == 'ppt' || type == 'pptx') {
documentType = 'slide'; //演示文档文件
}
new CXO_API.CXEditor('box_app', {
document: {
fileType: type,
key: documentKey,
title: obj.name,
url
},
documentType,
editorConfig: {
mode: 'view',
callbackUrl: ''
},
height: '100%',
events: {
onDocumentReady: onDocumentReady,
onError: onError
},
zoom: -1
});
};
const onClose = () => {
emit('onClose', false);
};
const onFull = (type) => {
// 全屏
let document_detail = document.getElementById('document_detail');
state.type = type;
if (type == 2) {
document_detail.style.width = '100%';
document_detail.style.height = '100%';
} else {
document_detail.style.width = '1200px';
document_detail.style.height = '80vh';
}
};
return {
proxy,
openDialog,
onClose,
onFull,
...toRefs(state)
};
}
});
</script>
<style lang="scss">
.document_detail {
position: fixed;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
z-index: 999999;
width: 100%;
height: 100%;
border: 1px solid #9f9f9f;
.box_app {
// width: 1300px !important;
// height: 80vh !important;
background-color: #f1f1f1;
}
.move_pop {
width: 100%;
// position: absolute;
// top: 0;
// right: 0%;
height: 24px;
// background: linear-gradient(#2a5095, #213f7b, #111e48);
background-color: #f4f5f6;
display: grid;
place-items: center;
> span {
color: #000000;
font-weight: bold;
font-size: 20px;
letter-spacing: 2px;
}
.box {
display: flex;
width: 60px;
position: absolute;
top: 0;
right: 10px;
// height: 100%;
align-items: center;
img {
width: 22px;
margin-top: 6px;
cursor: pointer;
}
.close {
position: absolute;
right: 2px;
/* top: -8px; */
color: #8d8d8d;
width: 24px;
height: 24px;
font-size: 20px;
//border: 2px solid #0ff;
border-radius: 50%;
display: grid;
place-items: center;
cursor: pointer;
}
}
}
}
</style>

View File

@ -0,0 +1,198 @@
<template>
<div class="document_detail_eidt" id="document_detail_eidt">
<div class="move_pop" id="detial_edit">
<!-- <span>{{ title }}</span> -->
<div class="box">
<img v-if="type == 2" src="../icon/full.png" @click="onFull(1)" />
<img v-else src="../icon/suo.png" @click="onFull(2)" />
<span class="close" @click="onClose"></span>
</div>
</div>
<div class="box_app" id="box_app_edit"></div>
</div>
</template>
<script lang="ts">
import { toRefs, reactive, onMounted, ref, defineComponent, watch, getCurrentInstance } from 'vue';
import { setMove } from '@/utils/moveDiv';
import { useUserStoreHook } from '@/store/modules/user';
export default defineComponent({
name: 'index',
setup(props, { emit }) {
const stores = useUserStoreHook();
const { proxy } = <any>getCurrentInstance();
const state = reactive({
title: '',
projectId: stores.selectedProject.goId,
type: 2,
postUrl: ''
});
onMounted(() => {
setMove('detial_edit', 'document_detail_eidt');
});
// 打开弹窗
const openDialog = (obj, url) => {
state.postUrl = url;
state.title = obj.name;
init(obj);
};
const onError = function (event) {
console.log('编辑器错误: code ' + event.data.errorCode + ', 描述' + event.data.errorDescription);
//举例,强制保存后,判断文档内容是否保存成功
if (event.data) {
if (event.data.errorCode == 'forcesave') {
var desc = event.data.errorDescription;
desc = JSON.parse(desc);
if (desc.error == 0) {
//保存成功
} else {
//保存失败或异常
}
} else if (event.data.errorCode == 'setallcellvalue') {
var desc = event.data.errorDescription;
desc = JSON.parse(desc);
if (desc.error == 0) {
//填充成功
} else if (desc.error == -1) {
//当前文档正处于协同编辑中
} else {
//填充异常
}
} else if (event.data.errorCode == 'clearsheet') {
var desc = event.data.errorDescription;
desc = JSON.parse(desc);
if (desc.error == 0) {
//清除成功
} else if (desc.error == -1) {
//当前文档正处于协同编辑中
} else {
//清除异常
}
}
}
};
const onDocumentReady = function () {
// console.log('文档加载完成');
};
const init = (obj) => {
let documentKey = obj.id.toString() + new Date().getTime();
let baseURL = window['$HOSTSRC'].replace('ws:', 'http:').replace('/ws', '');
let url = baseURL + obj.filenPathCoding.replaceAll('+', ' ');
let type = obj.suffix;
if (obj.suffix.includes('.')) {
type = obj.suffix.substring(1);
}
let documentType = 'word'; // docx doc
if (type == 'xlsx' || type == 'xls') {
documentType = 'cell'; //电子表格
} else if (type == 'ppt' || type == 'pptx') {
documentType = 'slide'; //演示文档文件
}
new CXO_API.CXEditor('box_app_edit', {
document: {
fileType: obj.suffix.substring(1),
key: documentKey,
title: obj.name,
url
},
documentType,
editorConfig: {
callbackUrl: baseURL + state.postUrl + '?path=' + obj.filenPathCoding
},
events: {
onDocumentReady: onDocumentReady,
onError: onError
}
});
};
const onClose = () => {
emit('onClose', false);
};
const onFull = (type) => {
// 全屏
let document_detail = document.getElementById('document_detail_eidt');
state.type = type;
if (type == 2) {
// 弹框放大
document_detail.style.width = '100%';
document_detail.style.height = '100%';
} else {
// 弹框缩小
document_detail.style.width = '1200px';
document_detail.style.height = '80vh';
}
};
return {
proxy,
onFull,
openDialog,
onClose,
...toRefs(state)
};
}
});
</script>
<style lang="scss">
.document_detail_eidt {
position: fixed;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
z-index: 999999;
width: 100%;
height: 100%;
border: 1px solid #9f9f9f;
.box_app {
width: 1200px !important;
height: 80vh !important;
background-color: #f1f1f1;
margin-top: 100px;
}
.move_pop {
width: 100%;
// position: absolute;
// top: 0;
// right: 0%;
height: 24px;
// background: linear-gradient(#2a5095, #213f7b, #111e48);
background-color: #f4f5f6;
display: grid;
place-items: center;
> span {
color: #000000;
font-weight: bold;
font-size: 20px;
letter-spacing: 2px;
}
.box {
display: flex;
width: 60px;
position: absolute;
top: 0;
right: 10px;
// height: 100%;
align-items: center;
img {
width: 22px;
margin-top: 6px;
cursor: pointer;
}
.close {
position: absolute;
right: 2px;
/* top: -8px; */
color: #8d8d8d;
width: 24px;
height: 24px;
font-size: 20px;
//border: 2px solid #0ff;
border-radius: 50%;
display: grid;
place-items: center;
cursor: pointer;
}
}
}
}
</style>

View File

@ -0,0 +1,102 @@
<template>
<div class="add_profile">
<el-dialog v-model="isShowDialog" width="400px" :close-on-click-modal="false" :destroy-on-close="true">
<template #header>
<div v-drag="['.add_profile .el-dialog', '.add_profile .el-dialog__header']">添加工程资料</div>
</template>
<el-form ref="formRef" :model="formData" :rules="rules" label-width="110px">
<el-form-item label="工程资料名称" prop="dataName">
<el-input v-model="formData.dataName" placeholder="请输入工程资料名称" />
</el-form-item>
<el-form-item label="类型" prop="dataType">
<el-radio-group v-model="formData.dataType">
<el-radio label="1">编写</el-radio>
<el-radio label="2">存储</el-radio>
</el-radio-group>
</el-form-item>
</el-form>
<template #footer>
<div class="dialog-footer">
<el-button type="primary" @click="onSubmit"> </el-button>
<el-button @click="onCancel"> </el-button>
</div>
</template>
</el-dialog>
</div>
</template>
<script lang="ts">
import { reactive, toRefs, defineComponent, ref, unref, getCurrentInstance } from 'vue';
import { ElMessage } from 'element-plus';
import { useUserStoreHook } from '@/store/modules/user';
// 接口文档
import { templateDataAdd } from '@/api/quality/onlineListquality/profile';
export default defineComponent({
name: 'index',
setup(props, { emit }) {
const { proxy } = <any>getCurrentInstance();
const formRef = ref<HTMLElement | null>(null);
const stores = useUserStoreHook();
const state = reactive({
loading: false,
isShowDialog: false,
formData: {
dataName: '',
dataType: '1'
},
// 表单校验
rules: {
dataName: [{ required: true, message: '工程资料名称不能为空', trigger: 'blur' }]
}
});
// 打开弹窗
const openDialog = () => {
resetForm();
state.isShowDialog = true;
};
// 关闭弹窗
const closeDialog = () => {
state.isShowDialog = false;
};
// 取消
const onCancel = () => {
closeDialog();
};
// 提交
const onSubmit = () => {
state.formData.projectId = stores.selectedProject.goId;
const formWrap = unref(formRef) as any;
if (!formWrap) return;
formWrap.validate((valid: boolean) => {
if (valid) {
state.loading = true;
templateDataAdd(state.formData)
.then(() => {
ElMessage.success('添加成功');
emit('profileDataList');
closeDialog(); // 关闭弹窗
})
.finally(() => {
state.loading = false;
});
}
});
};
const resetForm = () => {
state.formData = {
dataName: '',
dataType: '1'
};
};
return {
proxy,
openDialog,
closeDialog,
onCancel,
onSubmit,
formRef,
...toRefs(state)
};
}
});
</script>
<style scoped></style>

View File

@ -0,0 +1,96 @@
<template>
<div class="edit_profile">
<el-dialog v-model="isShowDialog" width="400px" :close-on-click-modal="false" :destroy-on-close="true">
<template #header>
<div v-drag="['.edit_profile .el-dialog', '.edit_profile .el-dialog__header']">修改工程资料</div>
</template>
<el-form ref="formRef" :model="formData" :rules="rules" label-width="110px">
<el-form-item label="工程资料名称" prop="dataName">
<el-input v-model="formData.dataName" placeholder="请输入工程资料名称" />
</el-form-item>
<el-form-item label="类型" prop="dataType">
<el-radio-group v-model="formData.dataType">
<el-radio label="1">编写</el-radio>
<el-radio label="2">存储</el-radio>
</el-radio-group>
</el-form-item>
</el-form>
<template #footer>
<div class="dialog-footer">
<el-button type="primary" @click="onSubmit"> </el-button>
<el-button @click="onCancel"> </el-button>
</div>
</template>
</el-dialog>
</div>
</template>
<script lang="ts">
import { reactive, toRefs, defineComponent, ref, unref, getCurrentInstance } from 'vue';
import { ElMessage } from 'element-plus';
import { useUserStoreHook } from '@/store/modules/user';
// 接口文档
import { templateDataEdit } from '@/api/quality/onlineListquality/profile';
export default defineComponent({
name: 'index',
setup(props, { emit }) {
const { proxy } = <any>getCurrentInstance();
const formRef = ref<HTMLElement | null>(null);
const stores = useUserStoreHook();
const state = reactive({
loading: false,
isShowDialog: false,
formData: {
dataName: '',
dataType: '1'
},
// 表单校验
rules: {
dataName: [{ required: true, message: '工程资料名称不能为空', trigger: 'blur' }]
}
});
// 打开弹窗
const openDialog = (row: any) => {
state.formData = row;
state.isShowDialog = true;
};
// 关闭弹窗
const closeDialog = () => {
state.isShowDialog = false;
};
// 取消
const onCancel = () => {
closeDialog();
};
// 提交
const onSubmit = () => {
state.formData.projectId = stores.selectedProject.goId;
const formWrap = unref(formRef) as any;
if (!formWrap) return;
formWrap.validate((valid: boolean) => {
if (valid) {
state.loading = true;
templateDataEdit(state.formData)
.then(() => {
ElMessage.success('修改成功');
closeDialog();
emit('profileDataList');
})
.finally(() => {
state.loading = false;
});
}
});
};
return {
proxy,
openDialog,
closeDialog,
onCancel,
onSubmit,
formRef,
...toRefs(state)
};
}
});
</script>
<style scoped></style>

View File

@ -0,0 +1,132 @@
<template>
<div class="add_profile">
<el-dialog v-model="isShowDialog" width="400px" :close-on-click-modal="false" :destroy-on-close="true">
<template #header>
<div v-drag="['.add_profile .el-dialog', '.add_profile .el-dialog__header']">添加工程资料</div>
</template>
<el-form ref="formRef" :model="formData" :rules="rules" label-width="80px">
<el-form-item label="模板名称" prop="name">
<el-input v-model="formData.name" placeholder="请输入模板名称" />
</el-form-item>
<el-form-item label="文件上传">
<el-upload
ref="uploadRef"
class="upload-demo"
action="/zm/api/v1/system/templateDataJunior/add"
:limit="1"
:on-exceed="handleExceed"
:auto-upload="false"
:data="formData"
:headers="headers"
style="width: 300px"
:on-success="onSuccess"
name="File"
>
<template #trigger>
<el-button type="primary">点击选择文件</el-button>
</template>
<template #tip>
<div class="el-upload__tip text-red">请上传文件</div>
</template>
</el-upload>
</el-form-item>
</el-form>
<template #footer>
<div class="dialog-footer">
<el-button type="primary" @click="onSubmit"> </el-button>
<el-button @click="onCancel"> </el-button>
</div>
</template>
</el-dialog>
</div>
</template>
<script lang="ts">
import { reactive, toRefs, defineComponent, ref, unref, getCurrentInstance } from 'vue';
import { ElMessage, genFileId } from 'element-plus';
import { Session } from '@/utils/storage';
import sign from '@/utils/sign.js';
import { useUserStoreHook } from '@/store/modules/user';
export default defineComponent({
name: 'index',
setup(props, { emit }) {
const { proxy } = getCurrentInstance() as ComponentInternalInstance;
const formRef = ref<HTMLElement | null>(null);
const stores = useUserStoreHook();
const token = proxy.$cache.local.get('goToken');
const uploadRef = ref(); //文件dom
const state = reactive({
isShowDialog: false,
formData: {
name: '',
projectId: stores.selectedProject.goId
},
// 表单校验
rules: {
name: [{ required: true, message: '模板名称不能为空', trigger: 'blur' }]
},
token: `Bearer ${Session.get('token')}`
});
const headers = reactive({
Authorization: 'Bearer ' + token,
...sign({ ...state.formData })
});
// 打开弹窗
const openDialog = () => {
resetForm();
state.isShowDialog = true;
};
// 关闭弹窗
const closeDialog = () => {
state.isShowDialog = false;
};
// 取消
const onCancel = () => {
closeDialog();
};
const handleExceed = (files) => {
uploadRef.value!.clearFiles();
const file = files[0];
file.uid = genFileId();
uploadRef.value!.handleStart(file);
};
// 提交
const onSubmit = () => {
const formWrap = unref(formRef) as any;
if (!formWrap) return;
formWrap.validate((valid: boolean) => {
if (valid) {
uploadRef.value!.submit();
}
});
};
const onSuccess = (res) => {
if (res.code == 0) {
ElMessage.success('上传成功');
} else {
ElMessage.error(res.message);
}
};
const resetForm = () => {
state.formData.name = '';
};
return {
proxy,
uploadRef,
openDialog,
closeDialog,
onCancel,
token,
onSubmit,
handleExceed,
formRef,
headers,
onSuccess,
...toRefs(state)
};
}
});
</script>
<style scoped></style>

View File

@ -0,0 +1,133 @@
<template>
<div class="add_profile">
<el-dialog v-model="isShowDialog" width="400px" :close-on-click-modal="false" :destroy-on-close="true">
<template #header>
<div v-drag="['.add_profile .el-dialog', '.add_profile .el-dialog__header']">添加工程资料</div>
</template>
<el-form ref="formRef" :model="formData" :rules="rules" label-width="80px">
<el-form-item label="模板名称" prop="name">
<el-input v-model="formData.name" placeholder="请输入模板名称" />
</el-form-item>
<el-form-item label="文件上传">
<el-upload
ref="uploadEditRef"
class="upload-demo"
action="/zm/api/v1/system/templateDataJunior/edit"
:limit="1"
:on-exceed="handleExceed"
:auto-upload="false"
:data="formData"
:headers="headers"
style="width: 300px"
:on-success="onSuccess"
name="File"
:file-list="fileList"
>
<template #trigger>
<el-button type="primary">点击选择文件</el-button>
</template>
<template #tip>
<div class="el-upload__tip text-red">请上传文件</div>
</template>
</el-upload>
</el-form-item>
</el-form>
<template #footer>
<div class="dialog-footer">
<el-button type="primary" @click="onSubmit"> </el-button>
<el-button @click="onCancel"> </el-button>
</div>
</template>
</el-dialog>
</div>
</template>
<script lang="ts">
import { reactive, toRefs, defineComponent, ref, unref, getCurrentInstance } from 'vue';
import { ElMessage, genFileId } from 'element-plus';
import sign from '@/utils/sign.js';
import { useUserStoreHook } from '@/store/modules/user';
export default defineComponent({
name: 'index',
setup(props, { emit }) {
const { proxy } = <any>getCurrentInstance();
const token = proxy.$cache.local.get('goToken');
const formRef = ref<HTMLElement | null>(null);
const stores = useUserStoreHook();
const uploadEditRef = ref(); //文件dom
const state = reactive({
isShowDialog: false,
formData: {
name: '',
projectId: stores.selectedProject.goId
},
// 表单校验
rules: {
name: [{ required: true, message: '模板名称不能为空', trigger: 'blur' }]
},
token: `Bearer ${token}`,
fileList: [] as any //已经上传的文件列表
});
var headers = reactive({
Authorization: 'Bearer ' + token,
...sign({ ...state.formData })
});
// 打开弹窗
const openDialog = (row) => {
state.fileList = [
{
src: row.filenPath,
name: row.name
}
];
state.formData.name = row.name;
state.isShowDialog = true;
};
// 关闭弹窗
const closeDialog = () => {
state.isShowDialog = false;
};
// 取消
const onCancel = () => {
closeDialog();
};
const handleExceed = (files) => {
uploadEditRef.value!.clearFiles();
const file = files[0];
file.uid = genFileId();
uploadEditRef.value!.handleStart(file);
};
// 提交
const onSubmit = () => {
const formWrap = unref(formRef) as any;
if (!formWrap) return;
formWrap.validate((valid: boolean) => {
if (valid) {
uploadEditRef.value!.submit();
}
});
};
const onSuccess = (res) => {
if (res.code == 0) {
ElMessage.success('上传成功');
} else {
ElMessage.error(res.message);
}
};
return {
proxy,
uploadEditRef,
openDialog,
closeDialog,
onCancel,
onSubmit,
handleExceed,
headers,
formRef,
onSuccess,
...toRefs(state)
};
}
});
</script>
<style scoped></style>

View File

@ -0,0 +1,274 @@
<template>
<div class="pro_file_list">
<div class="back" @click="onClose">关闭页面</div>
<div>
<el-form :model="paramsQuery" ref="queryRef" :inline="true" label-width="80px">
<el-row>
<el-col :span="2">
<el-button type="primary" @click="handleAdd"
><el-icon><Plus /></el-icon>新增</el-button
>
</el-col>
<el-col :span="2">
<el-button type="danger" :disabled="multiple" @click="handleDelete(null)"
><el-icon><Delete /></el-icon>批量删除</el-button
>
</el-col>
<el-col :span="6" class="colBlock">
<el-form-item label="模板名称" prop="name">
<el-input v-model="paramsQuery.name" placeholder="请输入模板名称" clearable @keyup.enter.native="getDocumentList" />
</el-form-item>
</el-col>
<el-col :span="6">
<el-form-item>
<el-button type="primary" @click="searchInfo"
><el-icon><Search /></el-icon>搜索</el-button
>
<el-button @click="resetQuery(queryRef)"
><el-icon><Refresh /></el-icon>重置</el-button
>
</el-form-item>
</el-col>
</el-row>
</el-form>
<el-table v-loading="loading" :data="profileList" border @selection-change="handleSelectionChange">
<el-table-column type="selection" width="55" align="center" />
<el-table-column label="序号" align="center" type="index" min-width="50px" />
<el-table-column label="模板名称" align="center" prop="name" min-width="100px" />
<el-table-column label="创建时间" align="center" prop="createdAt" min-width="100px"> </el-table-column>
<el-table-column label="操作" align="center" class-name="small-padding" min-width="200px" fixed="right">
<template #default="scope">
<el-button type="primary" link @click="handleViewSource(scope.row)"
><el-icon><View /></el-icon>查看数据源</el-button
>
<el-button type="primary" link @click="handleView(scope.row)"
><el-icon><View /></el-icon>预览模板</el-button
>
<el-button type="primary" link @click="handleDownload(scope.row)"
><el-icon><Download /></el-icon>下载</el-button
>
<el-button type="success" link @click="handleUpdate(scope.row)"
><el-icon><EditPen /></el-icon>修改</el-button
>
<el-button type="danger" link @click="handleDelete(scope.row)"
><el-icon><DeleteFilled /></el-icon>删除</el-button
>
</template>
</el-table-column>
</el-table>
<pagination
v-show="total > 0"
:total="total"
v-model:page="paramsQuery.pageNum"
v-model:limit="paramsQuery.pageSize"
@pagination="getTemplateDataJuniorList"
/>
</div>
<add ref="addRef" @getTemplateDataJuniorList="getTemplateDataJuniorList"></add>
<edit ref="editRef" @getTemplateDataJuniorList="getTemplateDataJuniorList"></edit>
<documentDetail ref="documentDetailRef" v-if="showDocumentDetail" @onClose="onCloseDetail"></documentDetail>
<sourceData ref="sourceDataRef" v-if="showSourceData" @closelist="showSourceData = false"></sourceData>
</div>
</template>
<script lang="ts">
import { toRefs, reactive, onMounted, ref, defineComponent, getCurrentInstance, nextTick } from 'vue';
import { ElMessageBox, ElMessage } from 'element-plus';
import { useUserStoreHook } from '@/store/modules/user';
// 接口文档
import { templateDataJuniorDel, templateDataJuniorList } from '@/api/quality/onlineListquality/profile';
// 添加和编辑弹框
import add from './detailComm/add.vue';
import edit from './detailComm/edit.vue';
// 预览
import documentDetail from '../../../../comm/documentsDetail/index.vue';
// 查看数据源页面
import sourceData from './sourceData/index.vue';
import axios from 'axios';
import sign from '@/utils/sign.js';
const baseURL = import.meta.env.VITE_API_URL;
export default defineComponent({
name: 'index',
components: { add, documentDetail, edit, sourceData },
setup(props, { emit }) {
const stores = useUserStoreHook();
const { proxy } = <any>getCurrentInstance();
const addRef = ref(); //添加模板资料dom
const editRef = ref(); //编辑工程资料dom
const documentDetailRef = ref(); //预览模板资料dom
const queryRef = ref(); //搜索表单dom
const sourceDataRef = ref(); //数据源列表dom
// 非多个禁用
const multiple = ref(true);
const state = reactive({
paramsQuery: {
//搜索参数
projectId: stores.selectedProject.goId,
name: '',
createdAt: '', //
suffix: '',
pageNum: 1,
pageSize: 20
},
profileList: [], //工程资料列表数据
loading: false,
ids: [], //选中的列表数据
total: 0, //列表数量
showDocumentDetail: false, //查看详情
showSourceData: false //数据源列表数据弹框
});
onMounted(() => {
getTemplateDataJuniorList();
});
// 添加模板资料
const handleAdd = () => {
addRef.value.openDialog();
};
// 删除工程资料
const handleDelete = (row) => {
let msg = '你确定要删除所选数据?';
ElMessageBox.confirm(msg, '提示', {
confirmButtonText: '确认',
cancelButtonText: '取消',
type: 'warning'
})
.then(() => {
let ids = [];
if (row) {
ids = [row.id];
} else {
ids = state.ids;
}
templateDataJuniorDel({ ids }).then(() => {
ElMessage.success('删除成功');
getTemplateDataJuniorList();
});
})
.catch(() => {});
};
// 修改工程资料数据
const handleUpdate = (row: any) => {
editRef.value.openDialog(row);
};
// 搜索
const searchInfo = () => {
getTemplateDataJuniorList();
};
// 重置
const resetQuery = (formEl) => {
if (!formEl) return;
formEl.resetFields();
getTemplateDataJuniorList();
};
// 获取工程资料列表数据
const getTemplateDataJuniorList = () => {
state.loading = true;
templateDataJuniorList(state.paramsQuery).then((res) => {
state.loading = false;
if (res.code == 0) {
state.profileList = res.data.list;
state.total = res.data.total;
}
});
};
// 选中列表数据
const handleSelectionChange = (selection: any) => {
state.ids = selection.map((item) => item.id);
multiple.value = !selection.length;
};
const onClose = () => {
// 关闭页面
emit('closePage', false);
};
// 查看数据源
const handleViewSource = (row: any) => {
state.showSourceData = true;
nextTick(() => {
sourceDataRef.value.openDialog(row);
});
};
// 预览
const handleView = (row) => {
// 查看文档
state.showDocumentDetail = true;
nextTick(() => {
documentDetailRef.value.openDialog(row);
});
};
// 关闭预览
const onCloseDetail = () => {
state.showDocumentDetail = false;
};
//下载
const handleDownload = (row) => {
if (row.filenPath) {
const fileUrl = row.filenPath; // 文件的URL地址
let name = row.name + '.' + row.suffix;
axios.get(fileUrl, { responseType: 'blob', headers: { ...sign({}) } }).then((res: any) => {
load(res.data, name);
});
}
};
const load = (res, name) => {
let blob = new Blob([res]);
const blobURL = window.URL.createObjectURL(blob);
const link = document.createElement('a');
link.style.display = 'none';
link.href = blobURL;
link.setAttribute('download', name);
if (typeof link.download === 'undefined') {
link.setAttribute('target', '_blank');
}
document.body.appendChild(link);
link.click();
document.body.removeChild(link);
window.URL.revokeObjectURL(blobURL);
};
return {
proxy,
addRef,
editRef,
documentDetailRef,
queryRef,
sourceDataRef,
multiple,
onClose,
getTemplateDataJuniorList,
onCloseDetail,
handleView,
handleViewSource,
handleDownload,
handleUpdate,
resetQuery,
searchInfo,
handleDelete,
handleAdd,
handleSelectionChange,
...toRefs(state)
};
}
});
</script>
<style lang="scss" scoped>
.pro_file_list {
width: 100vw;
height: 100vh;
position: fixed;
z-index: 999;
background-color: #fff;
padding: 10px;
box-sizing: border-box;
top: 0;
left: 0;
.back {
position: absolute;
right: 10px;
top: 10px;
font-size: 18px;
color: #fb1d1d;
z-index: 999;
cursor: pointer;
font-weight: bold;
}
}
</style>

View File

@ -0,0 +1,253 @@
<template>
<div class="source_data">
<div class="back" @click="onClose">关闭页面</div>
<div>
<el-form :model="paramsQuery" ref="queryRef" :inline="true" label-width="80px">
<el-row>
<el-col :span="2">
<el-button type="primary" @click="handleAdd"
><el-icon><Plus /></el-icon>新增</el-button
>
</el-col>
<el-col :span="2">
<el-button type="danger" :disabled="multiple" @click="handleDelete(null)"
><el-icon><Delete /></el-icon>批量删除</el-button
>
</el-col>
<el-col :span="6" class="colBlock">
<el-form-item label="数据源名称" prop="sourceName">
<el-input v-model="paramsQuery.sourceName" placeholder="请输入数据源名称" clearable @keyup.enter.native="getTemplateDataJuniorList" />
</el-form-item>
</el-col>
<el-col :span="6">
<el-form-item>
<el-button type="primary" @click="searchInfo"
><el-icon><Search /></el-icon>搜索</el-button
>
<el-button @click="resetQuery(queryRef)"
><el-icon><Refresh /></el-icon>重置</el-button
>
</el-form-item>
</el-col>
</el-row>
</el-form>
<el-table v-loading="loading" :data="profileList" border @selection-change="handleSelectionChange">
<el-table-column type="selection" width="55" align="center" />
<el-table-column label="序号" align="center" type="index" min-width="50px" />
<el-table-column label="数据源名称" align="center" prop="sourceName" min-width="100px" />
<el-table-column label="类型" align="center" prop="typeId" min-width="100px" />
<el-table-column label="创建时间" align="center" prop="createdAt" min-width="100px"> </el-table-column>
<el-table-column label="操作" align="center" class-name="small-padding" min-width="200px" fixed="right">
<template #default="scope">
<el-button type="primary" link @click="handleView(scope.row)"
><el-icon><View /></el-icon>预览模板</el-button
>
<el-button type="primary" link @click="handleDownload(scope.row)"
><el-icon><Download /></el-icon>下载</el-button
>
<el-button type="success" link @click="handleUpdate(scope.row)"
><el-icon><EditPen /></el-icon>修改</el-button
>
<el-button type="danger" link @click="handleDelete(scope.row)"
><el-icon><DeleteFilled /></el-icon>删除</el-button
>
</template>
</el-table-column>
</el-table>
<pagination
v-show="total > 0"
:total="total"
v-model:page="paramsQuery.pageNum"
v-model:limit="paramsQuery.pageSize"
@pagination="getTemplateDataJuniorList"
/>
</div>
<documentDetail ref="documentDetailRef" v-if="showDocumentDetail" @onClose="onCloseDetail"></documentDetail>
</div>
</template>
<script lang="ts">
import { toRefs, reactive, onMounted, ref, defineComponent, getCurrentInstance, nextTick } from 'vue';
import { ElMessageBox, ElMessage } from 'element-plus';
// 接口文档
import { templateDataSourceDataDel, templateDataSourceDataList } from '@/api/quality/onlineListquality/profile';
// 预览
import documentDetail from '../../../../documentsDetail/index.vue';
import axios from 'axios';
import sign from '@/utils/sign.js';
import { useUserStoreHook } from '@/store/modules/user';
const baseURL = import.meta.env.VITE_API_URL;
export default defineComponent({
name: 'index',
components: { documentDetail },
setup(props, { emit }) {
const stores = useUserStoreHook();
const { proxy } = <any>getCurrentInstance();
const addRef = ref(); //添加模板资料dom
const editRef = ref(); //编辑工程资料dom
const documentDetailRef = ref(); //预览模板资料dom
const queryRef = ref(); //搜索表单dom
// 非多个禁用
const multiple = ref(true);
const state = reactive({
paramsQuery: {
//搜索参数
projectId: stores.selectedProject.goId,
sourceName: '',
pageNum: 1,
pageSize: 20
},
profileList: [], //工程资料列表数据
loading: false,
ids: [], //选中的列表数据
total: 0, //列表数量
showDocumentDetail: false
});
const openDialog = (row: any) => {
console.log(row);
getTemplateDataJuniorList();
};
// 添加模板资料
const handleAdd = () => {
addRef.value.openDialog();
};
// 删除工程资料
const handleDelete = (row) => {
let msg = '你确定要删除所选数据?';
ElMessageBox.confirm(msg, '提示', {
confirmButtonText: '确认',
cancelButtonText: '取消',
type: 'warning'
})
.then(() => {
let ids = [];
if (row) {
ids = [row.id];
} else {
ids = state.ids;
}
templateDataSourceDataDel({ ids }).then(() => {
ElMessage.success('删除成功');
getTemplateDataJuniorList();
});
})
.catch(() => {});
};
// 修改工程资料数据
const handleUpdate = (row: any) => {
editRef.value.openDialog(row);
};
// 搜索
const searchInfo = () => {
getTemplateDataJuniorList();
};
// 重置
const resetQuery = (formEl) => {
if (!formEl) return;
formEl.resetFields();
getTemplateDataJuniorList();
};
// 获取工程资料列表数据
const getTemplateDataJuniorList = () => {
state.loading = true;
templateDataSourceDataList(state.paramsQuery).then((res: any) => {
state.loading = false;
if (res.code == 0) {
state.profileList = res.data.list;
state.total = res.data.total;
}
});
};
// 选中列表数据
const handleSelectionChange = (selection: any) => {
state.ids = selection.map((item) => item.id);
multiple.value = !selection.length;
};
const onClose = () => {
// 关闭页面
emit('closelist', false);
};
// 预览
const handleView = (row) => {
// 查看文档
state.showDocumentDetail = true;
nextTick(() => {
documentDetailRef.value.openDialog(row);
});
};
// 关闭预览
const onCloseDetail = () => {
state.showDocumentDetail = false;
};
//下载
const handleDownload = (row) => {
if (row.filenPath) {
const fileUrl = row.filenPath; // 文件的URL地址
let name = row.name + '.' + row.suffix;
axios.get(fileUrl, { responseType: 'blob', ...sign({}) }).then((res: any) => {
load(res.data, name);
});
}
};
const load = (res, name) => {
let blob = new Blob([res]);
const blobURL = window.URL.createObjectURL(blob);
const link = document.createElement('a');
link.style.display = 'none';
link.href = blobURL;
link.setAttribute('download', name);
if (typeof link.download === 'undefined') {
link.setAttribute('target', '_blank');
}
document.body.appendChild(link);
link.click();
document.body.removeChild(link);
window.URL.revokeObjectURL(blobURL);
};
return {
proxy,
addRef,
editRef,
documentDetailRef,
queryRef,
multiple,
onClose,
getTemplateDataJuniorList,
onCloseDetail,
handleView,
handleDownload,
handleUpdate,
resetQuery,
searchInfo,
handleDelete,
handleAdd,
handleSelectionChange,
openDialog,
...toRefs(state)
};
}
});
</script>
<style lang="scss">
.source_data {
width: 100vw;
height: 100vh;
position: fixed;
z-index: 989999;
background-color: #fff;
padding: 10px;
box-sizing: border-box;
top: 0;
left: 0;
.back {
position: absolute !important;
right: 10px !important;
top: 10px !important;
font-size: 18px !important;
color: #1d76fb !important;
z-index: 999 !important;
cursor: pointer !important;
font-weight: bold !important;
}
}
</style>

View File

@ -0,0 +1,205 @@
<template>
<div class="profile_data">
<div>
<el-form :model="paramsQuery" ref="queryRef" :inline="true" label-width="80px">
<el-row>
<el-col :span="2">
<el-button type="primary" @click="handleAdd"
><el-icon><Plus /></el-icon>新增</el-button
>
</el-col>
<el-col :span="2">
<el-button type="danger" :disabled="multiple" @click="handleDelete(null)"
><el-icon><Delete /></el-icon>删除</el-button
>
</el-col>
<el-col :span="6" class="colBlock">
<el-form-item label="文件名称" prop="name">
<el-input v-model="paramsQuery.name" placeholder="请输入文件名称" clearable @keyup.enter.native="getDocumentList" />
</el-form-item>
</el-col>
<el-col :span="6">
<el-form-item>
<el-button type="primary" @click="searchInfo"
><el-icon><Search /></el-icon>搜索</el-button
>
<el-button @click="resetQuery(queryRef)"
><el-icon><Refresh /></el-icon>重置</el-button
>
</el-form-item>
</el-col>
</el-row>
</el-form>
<el-table v-loading="loading" :data="profileList" @selection-change="handleSelectionChange">
<el-table-column type="selection" width="55" align="center" />
<el-table-column label="序号" align="center" type="index" min-width="50px" />
<el-table-column label="资料名称" align="center" prop="dataName" min-width="100px" />
<el-table-column label="类型" align="center" min-width="100px">
<template #default="scope">
<span>{{ scope.row.dataType == 1 ? '编写' : '存储' }}</span>
</template>
</el-table-column>
<el-table-column label="创建时间" align="center" prop="createdAt" min-width="100px"> </el-table-column>
<el-table-column label="操作" align="center" class-name="small-padding" min-width="200px" fixed="right">
<template #default="scope">
<el-button type="primary" link @click="handleFile(scope.row)"
><el-icon><Notebook /></el-icon>文件列表</el-button
>
<el-button type="success" link @click="handleUpdate(scope.row)"
><el-icon><EditPen /></el-icon>修改</el-button
>
<el-button type="danger" link @click="handleDelete(scope.row)"
><el-icon><DeleteFilled /></el-icon>删除</el-button
>
</template>
</el-table-column>
</el-table>
<pagination
v-show="total > 0"
:total="total"
v-model:page="paramsQuery.pageNum"
v-model:limit="paramsQuery.pageSize"
@pagination="getProfileDataList"
/>
</div>
<addProfile ref="addProfileRef" @profileDataList="getProfileDataList"></addProfile>
<editProfile ref="editProfileRef" @profileDataList="getProfileDataList"></editProfile>
<proFileList ref="proFileListRef" v-if="showproFileList" @closePage="closePage" @profileDataList="getProfileDataList"></proFileList>
</div>
</template>
<script lang="ts">
import { toRefs, reactive, onMounted, ref, defineComponent, watch, getCurrentInstance, nextTick } from 'vue';
import { ElLoading, ElMessageBox, ElMessage } from 'element-plus';
import { treeStructureList, documentList, documentEdit, documentDelete } from '@/api/quality/onlineListquality/Online';
// 引入添加工程资料弹框
import addProfile from './commp/addProfile/index.vue';
// 修改工程資料弹框
import editProfile from './commp/eidtProfile/index.vue';
// 文件列表数据
import proFileList from './commp/proFileList/index.vue';
// 接口文档
import { templateDataList, templateDataDel } from '@/api/quality/onlineListquality/profile';
import { useUserStoreHook } from '@/store/modules/user';
export default defineComponent({
name: 'index',
components: { addProfile, editProfile, proFileList },
setup() {
const stores = useUserStoreHook();
const { proxy } = <any>getCurrentInstance();
const addProfileRef = ref(); //添加工程资料dom
const editProfileRef = ref(); //编辑工程资料dom
const proFileListRef = ref(); //文件列表dom
const queryRef = ref(); //搜索表单dom
// 非多个禁用
const multiple = ref(true);
const state = reactive({
paramsQuery: {
//搜索参数
projectId: stores.selectedProject.goId,
dataName: '',
dataType: '', //
pageNum: 1,
pageSize: 20
},
profileList: [], //工程资料列表数据
loading: false,
ids: [], //选中的列表数据
total: 0, //列表数量
showproFileList: false //文件列表展示
});
onMounted(() => {
getProfileDataList();
});
// 添加工程资料
const handleAdd = () => {
addProfileRef.value.openDialog();
};
// 删除工程资料
const handleDelete = (row) => {
let msg = '你确定要删除所选数据?';
ElMessageBox.confirm(msg, '提示', {
confirmButtonText: '确认',
cancelButtonText: '取消',
type: 'warning'
})
.then(() => {
let ids = [];
if (row) {
ids = [row.id];
} else {
ids = state.ids;
}
templateDataDel({ ids }).then(() => {
ElMessage.success('删除成功');
getProfileDataList();
});
})
.catch(() => {});
};
// 修改工程资料数据
const handleUpdate = (row: any) => {
editProfileRef.value.openDialog(row);
};
// 搜索
const searchInfo = () => {
getProfileDataList();
};
// 重置
const resetQuery = (formEl) => {
if (!formEl) return;
formEl.resetFields();
getProfileDataList();
};
// 获取工程资料列表数据
const getProfileDataList = () => {
state.loading = true;
templateDataList(state.paramsQuery).then((res) => {
state.loading = false;
if (res.code == 0) {
state.profileList = res.data.list;
state.total = res.data.total;
}
});
};
// 选中列表数据
const handleSelectionChange = (selection: any) => {
state.ids = selection.map((item) => item.id);
multiple.value = !selection.length;
};
// 文件列表
const handleFile = (row) => {
// 打开弹框
state.showproFileList = true;
// proFileListRef.vaue.openDialog(row);
};
const closePage = () => {
state.showproFileList = false;
};
return {
proxy,
addProfileRef,
editProfileRef,
proFileListRef,
multiple,
queryRef,
getProfileDataList,
handleUpdate,
handleFile,
closePage,
resetQuery,
searchInfo,
handleDelete,
handleAdd,
handleSelectionChange,
...toRefs(state)
};
}
});
</script>
<style lang="scss">
.profile_data {
width: 100%;
height: 100%;
}
</style>

View File

@ -0,0 +1,226 @@
<template>
<div class="file_online">
<!-- 添加或修改题库_题库类别对话框 -->
<el-dialog v-model="isShowDialog" custom-class="file_online_box" width="800px" :close-on-click-modal="false" :destroy-on-close="true">
<template #header>
<div v-drag="['.file_online .el-dialog', '.file_online .el-dialog__header']">在线模板复制</div>
</template>
<div class="file_upload check_select">
<el-row>
<el-col :span="10">
<el-input class="input_left" v-model="filterText" size="small" placeholder="请输入文件名称" />
</el-col>
<el-col :span="10" style="margin-left: 20px">
<span>类型</span>
<el-select v-model="value" class="m-2" placeholder="请选择类型" @change="onChange">
<el-option label="文件夹" value="2" />
<el-option label="文件" value="1" />
</el-select>
</el-col>
</el-row>
</div>
<el-form ref="formRef" :model="formData" style="margin-top: 10px" label-width="90px">
<el-tree
ref="treeRef"
:default-expand-all="checked"
:filter-node-method="filterFolder"
:data="treeList"
:props="Props"
check-strictly
show-checkbox
node-key="id"
accordion
:expand-on-click-node="false"
@check-change="handleCheckChange"
>
<template #default="{ node, data }">
<span class="custom-tree-node">
<el-icon v-if="data.type == 2" color="#f1a81a"><FolderOpened /></el-icon>
<el-icon v-else color="#1af18a"><Document /></el-icon>
<span>{{ node.label }}</span>
</span>
</template>
</el-tree>
</el-form>
<template #footer>
<div class="dialog-footer">
<el-button type="primary" @click="onSubmit"> </el-button>
<el-button @click="onCancel"> </el-button>
</div>
</template>
</el-dialog>
</div>
</template>
<script lang="ts">
import { reactive, toRefs, defineComponent, ref, unref, getCurrentInstance, watch, nextTick } from 'vue';
import { ElMessage, ElLoading } from 'element-plus';
// 接口引入
import { documentAllList } from '@/api/quality/onlineListquality/Online';
import { onlineImport } from '@/api/quality/onlineListquality/profileData';
import { useUserStoreHook } from '@/store/modules/user';
export default defineComponent({
name: 'index',
setup(props, { emit }) {
const stores = useUserStoreHook();
const { proxy } = <any>getCurrentInstance();
const formRef = ref<HTMLElement | null>(null);
const treeRef = ref(null);
const filterText = ref(''); //搜索树形结构参数
const state = reactive({
loading: false,
isShowDialog: false,
formData: {
type: '',
TemplateId: [], //模板id
DataId: '', //资料id
projectId: stores.selectedProject.goId
},
// 表单校验
checked: true,
treeList: [],
Props: {
children: 'treeStructureRes',
label: 'name'
},
value: '2',
folderList: [], //文件夹数据
fileList: [] //文件数据
});
// 搜索数据
watch(filterText, (val: any) => {
treeRef.value!.filter(val);
});
// 查询tree树形结构数据
const filterFolder = (value: string, data: any) => {
if (!value) return true;
return data.name.includes(value);
};
// 打开弹窗
const openDialog = (DataId) => {
state.value = '2';
state.formData.TemplateId = [];
state.formData.type = '';
state.formData.DataId = DataId;
state.isShowDialog = true;
nextTick(() => {
getInfo();
});
};
// 关闭弹窗
const closeDialog = () => {
state.isShowDialog = false;
};
// 取消
const onCancel = () => {
closeDialog();
};
// 获取所有数据
const getInfo = () => {
const loading = ElLoading.service({
lock: true,
text: '正在加载中……',
background: 'rgba(0, 0, 0, 0.7)',
target: '.file_online_box'
});
documentAllList({}).then((res: any) => {
let arr = [];
let arr2 = [];
if (res.code == 0 && res.data.list && res.data.list.length) {
res.data.list.forEach((item) => {
// 把文件夹设置未不可选中
// 文件夹
if (item.type == 2) {
arr.push(item);
}
// 文件
let disabled = false;
if (item.type == 2) {
disabled = true;
}
arr2.push({ ...item, disabled });
});
state.folderList = listToTree(arr); //文件夹列表
state.treeList = state.folderList;
state.fileList = listToTree(arr2);
loading.close();
} else {
loading.close();
}
});
};
//数据处理
const listToTree = (list) => {
let array = [];
list.forEach((item) => {
// 遍历对象数组
item.name = item.name + item.suffix;
item.treeStructureRes = list.filter((info) => info.pid === item.idStr); // 找到每个对象的子节点
if (item.pid == 0) {
array.push(item); // 将一层节点放入新数组中
}
});
return array;
};
// 提交
const onSubmit = () => {
if (treeRef.value.getCheckedKeys().length) {
state.formData.TemplateId = treeRef.value.getCheckedKeys();
} else {
return;
}
const loading = ElLoading.service({
lock: true,
text: '正在上传……',
background: 'rgba(0, 0, 0, 0.7)'
});
const formWrap = unref(formRef) as any;
if (!formWrap) return;
formWrap.validate((valid: boolean) => {
if (valid) {
onlineImport(state.formData).then((res: any) => {
loading.close();
if (res.code == 0) {
ElMessage.success('导入成功');
emit('getfileOnlineType', state.formData.type);
onCancel();
} else {
ElMessage.error(res.message);
}
});
}
});
};
const handleCheckChange = (data) => {
state.formData.type = data.type;
};
const onChange = (val) => {
state.formData.TemplateId = [];
// 选中得设置为空
if (val == 2) {
// 切换文件夹
state.treeList = state.folderList;
} else {
// 切换文件
state.treeList = state.fileList;
}
};
return {
proxy,
openDialog,
closeDialog,
onCancel,
onSubmit,
getInfo,
formRef,
filterText,
handleCheckChange,
filterFolder,
treeRef,
onChange,
...toRefs(state)
};
}
});
</script>
<style scoped></style>

View File

@ -0,0 +1,835 @@
<template>
<div class="profile_engin">
<div class="box_info">
<div class="tree_left1" id="tree_left1">
<div class="check_select">
<el-button type="primary" v-auth="'/zm/api/v1/system/documentData/newFolder'" @click="addFile"
><el-icon><Plus /></el-icon>新建文件夹</el-button
>
<div class="box_btn" v-auth="'/zm/api/v1/system/documentData/add'">
<span>导入</span>
<div class="btn">
<el-button type="primary" style="float: left" @click="bigUploadFile1"
><el-icon><Plus /></el-icon>导入压缩文件</el-button
>
<el-button type="primary" style="float: left" :disabled="!parentPid" @click="uploadFile(2)"
><el-icon><Plus /></el-icon>导入文件</el-button
>
</div>
</div>
</div>
<div class="file_upload check_select">
<el-checkbox v-model="checked" @change="handleCheckedTreeExpand($event)" label="展开/折叠" size="large" />
<div style="margin: 0 10px">
<el-select v-model="paramsQuery.switch" placeholder="当前文件夹" size="small">
<el-option v-for="item in options" :key="item.id" :label="item.label" :value="item.id" />
</el-select>
</div>
<el-button type="primary" v-auth="'/zm/api/v1/system/documentProject/dataCompressedDownload'" :disabled="!parentPid" @click="onExport"
><el-icon><Download /></el-icon>下载</el-button
>
<el-button type="primary" @click="onBook" v-auth="'/zm/api/v1/system/documentData/dataFileQuery'"
><el-icon><View /></el-icon>查看全项目文件</el-button
>
</div>
<div class="file_upload check_select">
<el-input class="input_left" v-model="filterText" size="small" placeholder="请输入文件名称" />
</div>
<el-tree
ref="treeRef"
highlight-current
:default-expand-all="checked"
:filter-node-method="filterFolder"
:data="treeList"
:props="Props"
node-key="id"
accordion
:draggable="draggableCheck"
:expand-on-click-node="false"
@node-click="handleNodeClick"
:current-node-key="selectedNodeId"
@node-drop="handleDragEnd"
:allow-drop="allowDrop"
>
<template #default="{ node, data }">
<span class="custom-tree-node">
<el-icon color="#f1a81a"><FolderOpened /></el-icon>
<span>{{ node.label }}</span>
<span style="margin-left: 20px" class="set-tool">
<el-button type="primary" v-auth="'/zm/api/v1/system/documentData/onlineImport'" link @click.stop="uploadOnlineFile(node, data)"
>在线模板复制</el-button
>
<el-button type="success" v-auth="'/zm/api/v1/system/documentData/edit'" link @click.stop="onUpdateName(node, data)"
>重命名</el-button
>
<el-button type="danger" v-auth="'/zm/api/v1/system/documentData/delete'" link @click.stop="onRemove(node, data)">删除</el-button>
</span>
</span>
</template>
</el-tree>
<div class="resize-handle resize-handle-right right"></div>
</div>
<div class="list_right" id="list_right1">
<div>
<el-form :model="paramsQuery" ref="queryRef" :inline="true" label-width="100px">
<el-row>
<el-col :span="6" class="colBlock">
<el-form-item label="文件名称" prop="name">
<el-input v-model="paramsQuery.name" placeholder="请输入文件名称" clearable @keyup.enter.native="getdocumentDataList" />
</el-form-item>
</el-col>
<el-col :span="6">
<el-form-item>
<el-button type="primary" @click="searchInfo"
><el-icon><Search /></el-icon>搜索</el-button
>
<el-button @click="resetQuery"
><el-icon><Refresh /></el-icon>重置</el-button
>
</el-form-item>
</el-col>
<!-- <el-col :span="4">
<el-button type="primary" v-auth="'/zm/api/v1/system/documentData/add'" :disabled="!parentPid" @click="uploadFile(2)"
><el-icon><Plus /></el-icon>导入本地文件</el-button
>
</el-col> -->
<!-- <el-col :span="4">
<el-button type="primary" @click="onMoveFile"
><el-icon><Plus /></el-icon>移动</el-button
>
</el-col> -->
</el-row>
</el-form>
</div>
<el-table v-loading="loading" :data="infoList" height="67vh" border>
<el-table-column label="序号" align="center" type="index" min-width="50px" />
<el-table-column label="文件名称" align="center" prop="name">
<template #default="scope">
<span>{{ scope.row.name + scope.row.suffix }}</span>
</template>
</el-table-column>
<el-table-column label="上传时间" align="center" prop="createdAt"> </el-table-column>
<el-table-column label="操作" align="center">
<template #default="scope">
<el-button
type="primary"
v-auth="'/zm/api/v1/system/documentData/get'"
v-if="acceptType.includes(scope.row.suffix)"
link
@click="handleView(scope.row)"
><el-icon><View /></el-icon>查看</el-button
>
<el-button
type="primary"
v-auth="'/zm/api/v1/system/documentData/complaintBoxAdd'"
v-if="acceptType.includes(scope.row.suffix)"
link
@click="updataView(scope.row)"
><el-icon><EditPen /></el-icon>修改文件</el-button
>
<el-button type="primary" v-auth="'/zm/api/v1/system/documentData/uniFolderDownload'" link @click="onExportView(scope.row)"
><el-icon><Download /></el-icon>下载</el-button
>
<el-button type="success" v-auth="'/zm/api/v1/system/documentData/edit'" link @click="updateName(scope.row)"
><el-icon><EditPen /></el-icon>修改名称</el-button
>
<el-button type="danger" v-auth="'/zm/api/v1/system/documentData/delete'" link @click="handleDelete(scope.row)"
><el-icon><DeleteFilled /></el-icon>删除</el-button
>
</template>
</el-table-column>
</el-table>
<pagination :total="total" v-model:page="paramsQuery.pageNum" v-model:limit="paramsQuery.pageSize" @pagination="getdocumentDataList" />
</div>
</div>
<documentDetail ref="documentDetailRef" v-if="showDocumentDetail" @onClose="onClose"></documentDetail>
<documentsEdit ref="documentDataEditRef" v-if="showdocumentDataEdit" @onClose="onCloseEdit"></documentsEdit>
<uploadFileder
ref="uploadFilederRef"
v-if="showUploadFileder"
@onCloseFile="showUploadFileder = false"
@getDocumentListFileType="getdocumentDataListFileType"
></uploadFileder>
<fileOnline ref="fileOnlineRef" @getfileOnlineType="getfileOnlineType"></fileOnline>
<moveFile ref="moveFileRef"></moveFile>
<bookFile ref="bookFileRef"></bookFile>
</div>
</template>
<script lang="ts">
import { toRefs, reactive, onMounted, ref, defineComponent, watch, getCurrentInstance, nextTick, onBeforeUnmount } from 'vue';
import { ElLoading, ElMessageBox, ElMessage } from 'element-plus';
import { uniFolderDownload, uniFileDownload } from '@/api/quality/onlineListquality/Online';
import {
treeStructureData,
documentDataEdit,
documentDataDelete,
documentDataNewFolder,
documentDataList,
onlineMobile,
getProfileDetail
} from '@/api/quality/onlineListquality/profileData';
// 文档查看
import documentDetail from '../documentsDetail/index.vue';
// 文档修改编辑
import documentsEdit from '../documentsEdit/index.vue';
// 资料信息列表
import profileData from '../profileData/index.vue';
// 文件导入弹框
import uploadFileder from '../uploadFileder/index.vue';
// 在线模板文件导入
import fileOnline from './fileOnline/index.vue';
// 移动文件
import moveFile from './moveFile/index.vue';
// 所有资料文件
import bookFile from '../bookFile/index.vue';
import axios from 'axios';
import sign from '@/utils/sign.js';
import { Session } from '@/utils/storage';
import { documentDataAdd } from '@/api/quality/onlineListquality/profileData';
import { useUserStoreHook } from '@/store/modules/user';
export default defineComponent({
name: 'index',
components: { documentDetail, documentsEdit, profileData, uploadFileder, fileOnline, moveFile, bookFile },
setup(props, { emit }) {
const stores = useUserStoreHook();
const { proxy } = <any>getCurrentInstance(); //获取
const filterText = ref(''); //搜索树形结构参数
const treeRef = ref(); //树形结构dom
const documentDetailRef = ref(); //详情在线dom
const documentDataEditRef = ref(); //编辑在线dom
const uploadFilederRef = ref(); //上传文件在线dom
const fileOnlineRef = ref(); //上传在线模板dom
const moveFileRef = ref(); //移动模板dom
const bookFileRef = ref(); //资料文件弹框
const baseURL: string | undefined | boolean = import.meta.env.VITE_API_URL;
const state = reactive({
treeList: [] as any, //树形结构数据
arrayList: [] as any, //树形结构处理成一维数组
infoMap: new Map(), //用idstr 存储pid
infoList: [] as any, //文档列表数据
Props: {
children: 'treeStructureDataRes',
label: 'name'
},
total: 0, //文档数量
paramsQuery: { idStr: '', name: '', switch: 1, pageNum: 1, pageSize: 20, projectId: stores.selectedProject.goId }, //请求参数
loading: false, //列表加载
checked: true, //展开 折叠
options: [
{ id: 1, label: '当前文件夹及以下' },
{ id: 2, label: '当前文件夹' }
],
showDocumentDetail: false, //详情弹框
showdocumentDataEdit: false, //编辑弹框
showUploadFileder: false,
parentRow: null, //父级对象
parentPid: null, //父级pid
parentName: '', //父级名称
selectedNodeId: null, //选中
projectId: stores.selectedProject.goId,
acceptType: ['.pdf', '.doc', '.docx', '.xls', '.xlsx', '.ppt', '.pptx'],
draggableCheck: false, //判断是否可以移动
activeName: ''
});
// 搜索数据
watch(filterText, (val: any) => {
treeRef.value!.filter(val);
});
onMounted(() => {
// 判断是否可以移动
if (stores.permissions.includes('/zm/api/v1/system/documentData/onlineMobile') || stores.permissions.includes('*/*/*')) {
state.draggableCheck = true; //设置可移动
}
resizeHandleRight(); //鼠标移动
proxy.mittBus.on('bigUploader.uploadFileSuccess' + 1002, (res: any) => {
const { filename, totalSize, url, identifier, fileType } = res;
let arr = filename.split('.');
let fileType1 = arr[arr.length - 1];
let obj = {
filePath: {
url,
name: filename,
size: totalSize,
fileType: '.' + fileType1 //后缀名
},
fileType: 1,
pid: state.parentPid,
projectId: state.projectId
};
documentDataAdd(obj).then((res: any) => {
if (res.code == 0) {
getdocumentDataListFileType(1);
ElMessage({
type: 'success',
message: '添加成功'
});
} else {
ElMessage({
type: 'error',
message: res.message
});
}
});
});
});
onBeforeUnmount(() => {
// 取消订阅特定事件
proxy.mittBus.off('bigUploader.uploadFileSuccess' + 1002);
});
// 导入大文件
const bigUploadFile1 = () => {
// 文件上传
proxy.mittBus.emit('bigUploader.uploadFile', { type: 2, types: 1002, accept: ['.zip', '.rar'] });
};
// 新建文件夹
const addFile = () => {
let tip = '在根目录下新建文件夹';
if (state.parentPid) {
tip = '在“' + state.parentName + '文件夹”下新建文件夹';
}
ElMessageBox.prompt('请输入文件夹名称', tip, {
confirmButtonText: '确定',
cancelButtonText: '取消',
inputErrorMessage: '请输入文件夹名称',
inputValue: ''
})
.then(({ value }) => {
documentDataNewFolder({ fileName: value, pid: state.parentPid, fileType: 3, projectId: state.projectId }).then((res: any) => {
if (res.code == 0) {
ElMessage({
type: 'success',
message: '添加成功'
});
gettreeStructureData();
} else {
ElMessage({
type: 'error',
message: res.message
});
}
});
})
.catch(() => {});
};
// 导入文件
const uploadFile = (fileType) => {
if (fileType == 2 && !state.parentPid) {
ElMessage.warning('请选择文件目录!');
return;
}
// 判断上传类型 文件与压缩包区分
let acceptType = '.zip'; //压缩文件类型
if (fileType == 2) {
//文件上传
acceptType = '';
}
state.showUploadFileder = true;
nextTick(() => {
// 打开弹框
uploadFilederRef.value.openDialog(state.parentPid, fileType, acceptType, true);
});
};
const searchInfo = () => {
// 搜索
getdocumentDataList();
};
const resetQuery = () => {
// 重置
state.paramsQuery.name = '';
getdocumentDataList();
};
// 获取树形结构文件夹目录
const gettreeStructureData = () => {
state.parentPid = null;
state.activeName = 'second';
const loading = ElLoading.service({
lock: true,
text: '正在加载中……',
background: 'rgba(0, 0, 0, 0.7)',
target: '.tree_left1'
});
treeStructureData({ projectId: state.projectId }).then((res: any) => {
loading.close();
if (res.code == 0 && res.data && res.data.list) {
state.selectedNodeId = '';
state.treeList = res.data.list;
state.paramsQuery.idStr = res.data.list[0].idStr;
getdocumentDataList();
setInfo(res.data.list);
}
});
};
// 处理数据
const setInfo = (arr) => {
arr.forEach((element) => {
state.arrayList.push(element);
state.infoMap.set(element.idStr, element.id);
if (element.treeStructureDataRes && element.treeStructureDataRes.length) {
setInfo(element.treeStructureDataRes);
}
});
};
// 选择目录文件
const handleNodeClick = (row) => {
state.parentRow = row;
state.parentPid = row.idStr;
state.parentName = row.name;
state.paramsQuery.idStr = row.idStr;
state.paramsQuery.name = '';
getdocumentDataList();
if (row.id === state.selectedNodeId) {
// 如果当前节点已经选中,则取消选中
state.selectedNodeId = null;
state.parentPid = null; //关闭父级选择的id
state.parentRow = null; //获取父级对象
state.parentName = ''; //获取父级对应的名称
state.paramsQuery.idStr = ''; //
} else {
// 否则选中当前节点 重新赋值
state.selectedNodeId = row.id;
}
};
// 获取文档列表数据
const getdocumentDataList = () => {
if (!state.paramsQuery.idStr) {
return;
}
state.loading = true;
documentDataList(state.paramsQuery).then((res: any) => {
state.loading = false;
if (res.code == 0) {
res.data.list.sort((a, b) => {
return a.name.localeCompare(b.name);
});
state.infoList = res.data.list;
state.total = res.data.total;
}
});
};
// 查询tree树形结构数据
const filterFolder = (value: string, data: any) => {
if (!value) return true;
return data.name.includes(value);
};
const handleClick = () => {
// 切换页面
};
const handleDelete = (row) => {
// 删除文档
let msg = '你确定要删除所选文件?';
delFile(msg, row, () => {
getdocumentDataList();
});
};
const onExportView = (row) => {
// baseURL + '/zm' +
axios({
method: 'get',
url: '/zm/api/v1/system/documentData/uniFileDownload',
responseType: 'blob',
params: {
relativePath: row.filenPath
},
headers: {
Authorization: 'Bearer ' + `${Session.get('token')}`,
...sign({
relativePath: row.filenPath
})
}
}).then((res) => {
let blob = new Blob([res.data], { type: res.headers['content-type'] });
const blobURL = window.URL.createObjectURL(blob);
const link = document.createElement('a');
link.style.display = 'none';
link.href = blobURL;
link.setAttribute('download', row.name + row.suffix);
if (typeof link.download === 'undefined') {
link.setAttribute('target', '_blank');
}
document.body.appendChild(link);
link.click();
document.body.removeChild(link);
window.URL.revokeObjectURL(blobURL);
});
};
const updateName = (row) => {
// 修改名称
editName(row, '请输入文件名称', 1);
};
const handleView = (row) => {
getProfileDetail(row.id).then((res: any) => {
if (res.code == 0) {
// 查看文档
state.showDocumentDetail = true;
nextTick(() => {
documentDetailRef.value.openDialog(res.data);
});
}
});
};
// 关闭在线编辑弹框
const onClose = () => {
state.showDocumentDetail = false;
};
// 展开或折叠节点
const handleCheckedTreeExpand = (value: any) => {
for (let i = 0; i < state.arrayList.length; i++) {
treeRef.value.store.nodesMap[state.arrayList[i].id].expanded = value;
}
};
// 关闭修改的在线文档弹框
const onCloseEdit = () => {
state.showdocumentDataEdit = false;
};
const updataView = (row) => {
// 修改文档
state.showdocumentDataEdit = true;
nextTick(() => {
documentDataEditRef.value.openDialog(row, '/zm/api/v1/system/busConstructionUser/complaintBoxAddTwo');
});
};
const resizeHandleRight = () => {
// 右侧鼠标移动大小
const resizeHandles = document.getElementsByClassName('resize-handle');
Array.from(resizeHandles).forEach((handle) => {
handle.addEventListener('mousedown', startResize);
});
};
const startResize = (event) => {
event.preventDefault();
let dragElement = document.getElementById('tree_left1') as any;
let dragElementRight = document.getElementById('list_right1');
const currentHandle = event.target;
const direction = currentHandle.className.split(' ')[1];
const startX = event.clientX;
const startY = event.clientY;
// 左侧移动的盒子大小
const startWidth = dragElement.offsetWidth;
const startHeight = dragElement.offsetHeight;
const startLeft = dragElement.offsetLeft;
const startTop = dragElement.offsetTop;
// 右侧移动盒子宽度
const rightWidth = dragElementRight.offsetWidth;
document.addEventListener('mousemove', resize);
document.addEventListener('mouseup', stopResize);
function resize(event) {
const dx = event.clientX - startX;
const dy = event.clientY - startY;
let width = startWidth;
let height = startHeight;
let left = startLeft;
let top = startTop;
let rightWidth1 = rightWidth as any;
if (direction.includes('right')) {
width = startWidth + dx + 'px';
let w = startWidth + dx + 10 + 'px';
rightWidth1 = `calc(100% - ${w})`; //计算右侧盒子的宽度
}
if (parseInt(width) <= 0 || parseInt(height) <= 0) return;
dragElementRight.style.width = rightWidth1;
dragElement.style.width = width;
dragElement.style.height = height;
dragElement.style.left = left;
dragElement.style.top = top;
}
function stopResize() {
document.removeEventListener('mousemove', resize);
document.removeEventListener('mouseup', stopResize);
}
};
// 删除文件及文件夹
const delFile = (msg, data, cb) => {
ElMessageBox.confirm(msg, '提示', {
confirmButtonText: '确认',
cancelButtonText: '取消',
type: 'warning'
})
.then(() => {
documentDataDelete([data.id]).then((res: any) => {
if (res.code == 0) {
ElMessage.success('删除成功');
cb();
}
});
})
.catch(() => {});
};
const onRemove = (node, data) => {
const parent = node.parent;
const children = parent.data.treeStructureDataRes || parent.data;
const index = children.findIndex((d) => d.id === data.id);
let msg = '你确定要删除所选文件夹?';
delFile(msg, data, () => {
children.splice(index, 1);
if (data.idStr == state.paramsQuery.idStr) {
state.infoList = []; //清空文件列表
}
state.treeList = [...state.treeList]; //刷新当前列表数据
});
};
const editName = (data, title, type) => {
ElMessageBox.prompt(title, '温馨提示', {
confirmButtonText: '确定',
cancelButtonText: '取消',
inputErrorMessage: title,
inputValue: data.name
})
.then(({ value }) => {
documentDataEdit({ id: data.id, name: value, type, projectId: state.projectId }).then((res: any) => {
if (res.code == 0) {
ElMessage({
type: 'success',
message: '修改成功'
});
// 数据重新刷新
if (type == 2) {
gettreeStructureData();
} else {
getdocumentDataList();
}
} else {
ElMessage({
type: 'error',
message: res.message
});
}
});
})
.catch(() => {});
};
const onUpdateName = (node, data) => {
editName(data, '请输入文件夹名称', 2);
};
const getdocumentDataListFileType = (fileType) => {
if (fileType == 2) {
getdocumentDataList();
} else {
gettreeStructureData();
}
};
const getfileOnlineType = (fileType) => {
if (fileType == 1) {
getdocumentDataList();
} else {
gettreeStructureData();
}
};
const onExport = () => {
uniFolderDownload(state.parentRow.filenPath).then((res: any) => {
if (res.code == 0) {
let fileUrl = res.data.RelativePath;
window.open(fileUrl, '_self');
}
});
};
// 在线模板文件导入
const uploadOnlineFile = (node, data) => {
state.paramsQuery.idStr = data.idStr;
fileOnlineRef.value.openDialog(data.id);
};
const onMoveFile = () => {
// 移动文件
// moveFileRef.value.openDialog();
};
// 拖拽移动
const handleDragEnd = (draggingNode, dropNode, dropType, ev) => {
// TemplateId 被移动 DataId位置
let obj = { type: draggingNode.data.type, TemplateId: draggingNode.data.id, projectId: state.projectId, DataId: '' };
let DataId = '';
if (dropType == 'after' || dropType == 'before') {
// 获取父级id
// 通过pid找父级id
let pid = dropNode.data.pid; //子级pid
if (state.infoMap.has(pid)) {
//
DataId = state.infoMap.get(pid);
}
obj.DataId = DataId;
} else {
obj.DataId = dropNode.data.id;
}
if (!obj.DataId) {
return false;
}
const loading = ElLoading.service({
lock: true,
text: '正在加载中……',
background: 'rgba(0, 0, 0, 0.7)',
target: '.tree_left1'
});
onlineMobile(obj).then((res: any) => {
loading.close();
if (res.code == 0) {
ElMessage.success('移动成功');
// 重新获取文件接口
gettreeStructureData();
} else {
ElMessage.error(res.message);
}
});
};
const allowDrop = (draggingNode, dropNode, type) => {
// 不可移动
if (dropNode.data.pid == 0 && type != 'inner') {
//不可移动到最外层
return false;
} else {
return true;
}
};
// 查看所有资料
const onBook = () => {
bookFileRef.value.openDialog();
};
return {
proxy,
filterText,
bookFileRef,
treeRef,
documentDetailRef,
uploadFilederRef,
fileOnlineRef,
moveFileRef,
documentDataEditRef,
onClose,
onCloseEdit,
handleClick,
handleNodeClick,
filterFolder,
searchInfo,
addFile,
uploadFile,
resetQuery,
onBook,
getdocumentDataList,
getdocumentDataListFileType,
getfileOnlineType,
handleDelete,
onExportView,
updateName,
gettreeStructureData,
updataView,
handleView,
onRemove,
onUpdateName,
handleCheckedTreeExpand,
onExport,
bigUploadFile1,
onMoveFile,
uploadOnlineFile,
handleDragEnd,
allowDrop,
...toRefs(state)
};
}
});
</script>
<style lang="scss">
.profile_engin {
height: 80vh;
.set-tool {
display: none;
}
.el-tree-node__content:hover,
.el-tree-node__content:active {
.set-tool {
display: inline-block;
}
}
.el-tree--highlight-current .el-tree-node.is-current > .el-tree-node__content {
background-color: #354e67 !important;
color: #fff;
}
.box_info {
display: flex;
justify-content: space-between;
}
.pagination-container {
padding: 10px 0 !important;
}
> div {
height: 100%;
width: 100%;
}
.tree_left1 {
width: 30%;
background-color: #fff;
border: 1px solid #dddddd;
border-radius: 6px;
padding: 6px 0px;
position: relative;
min-width: 26%;
border-right: 6px solid;
border-right-color: rgba(204, 230, 255, 0);
.resize-handle-right {
top: 0;
width: 6px;
height: 100%;
right: -10px;
cursor: ew-resize;
position: absolute;
z-index: 999;
}
.check_select {
display: flex;
align-items: center;
width: 100%;
// justify-content: space-between;
padding: 4px;
border-bottom: 1px solid #f1f1f1;
.box_btn {
width: 360px;
margin: 0 10px 0 20px;
position: relative;
> span {
padding: 4px 10px;
background: #67c23a;
color: #fff;
border-radius: 2px;
}
.btn {
position: absolute;
left: 20%;
display: none;
top: -2px;
width: 220px;
.el-button {
float: left;
}
}
}
.box_btn:hover,
.box_btn:active {
cursor: pointer;
.btn {
display: block;
}
}
}
.file_upload {
margin: 2px 0;
}
.input_left {
padding: 6px;
box-sizing: border-box;
// border-bottom: 1px solid #cbcbcb;
}
}
.list_right {
width: 69.5%;
background: white;
border: 1px solid #ededed;
padding: 10px;
box-sizing: border-box;
}
.el-tree {
height: calc(80vh - 160px);
width: 100%;
overflow: auto !important;
}
// .el-tree-node__children {
// overflow: visible !important;
// }
}
</style>

View File

@ -0,0 +1,242 @@
<template>
<div class="move_file">
<!-- 添加或修改题库_题库类别对话框 -->
<el-dialog v-model="isShowDialog" width="1200px" :close-on-click-modal="false" :destroy-on-close="true">
<template #header>
<div v-drag="['.move_file .el-dialog', '.move_file .el-dialog__header']">文件移动</div>
</template>
<div class="move_list">
<div class="all_list">
<div class="file_upload check_select">
<el-input class="input_left" v-model="filterText" size="small" placeholder="请输入文件名称" />
</div>
<el-tree
ref="treeRef"
highlight-current
:default-expand-all="checked"
:filter-node-method="filterFolder"
:data="treeList"
:props="Props"
check-strictly
show-checkbox
node-key="id"
accordion
:expand-on-click-node="false"
@check-change="handleCheckChange"
>
<template #default="{ node, data }">
<span class="custom-tree-node">
<el-icon v-if="data.type == 2" color="#f1a81a"><FolderOpened /></el-icon>
<el-icon v-else color="#f1a81a"><Document /></el-icon>
<span>{{ node.label }}</span>
</span>
</template>
</el-tree>
</div>
<div class="box_line">
<el-button type="primary" @click="onSubmit" style="margin: 10px 0">
<el-icon><Right /></el-icon>
移入</el-button
>
<!-- <el-button type="success" @click="onSubmit" style="margin: 10px 0">
<el-icon><Back /></el-icon>
移出</el-button
> -->
</div>
<div class="all_list">
<div class="file_upload check_select">
<el-input class="input_left" v-model="filterText1" size="small" placeholder="请输入文件名称" />
</div>
<el-tree
ref="lineTreeRef"
highlight-current
:default-expand-all="lineChecked"
:filter-node-method="filterFolder"
:data="onlineList"
:props="Props"
node-key="id"
accordion
:expand-on-click-node="false"
@check-change="handleCheckChange1"
>
<template #default="{ node, data }">
<span class="custom-tree-node">
<el-icon v-if="data.type == 2" color="#f1a81a"><FolderOpened /></el-icon>
<el-icon v-else color="#f1a81a"><Document /></el-icon>
<span>{{ node.label }}</span>
</span>
</template>
</el-tree>
</div>
</div>
<template #footer>
<div class="dialog-footer">
<el-button type="primary" @click="onSubmit"> </el-button>
<el-button @click="onCancel"> </el-button>
</div>
</template>
</el-dialog>
</div>
</template>
<script lang="ts">
import { reactive, toRefs, defineComponent, ref, getCurrentInstance, watch } from 'vue';
import { ElMessage } from 'element-plus';
// 接口引入
import { documentAllList } from '@/api/quality/onlineListquality/Online';
import { onlineImport, documentDataAllList } from '@/api/quality/onlineListquality/profileData';
import { useUserStoreHook } from '@/store/modules/user';
export default defineComponent({
name: 'index',
props: {},
setup(props, { emit }) {
const stores = useUserStoreHook();
const { proxy } = <any>getCurrentInstance();
const treeRef = ref(null);
const lineTreeRef = ref(null);
const filterText = ref(''); //搜索树形结构参数
const filterText1 = ref(''); //搜索树形结构参数
const state = reactive({
loading: false,
isShowDialog: false,
formData: {
type: '',
TemplateId: '', //模板id
DataId: '' //资料id
},
// 表单校验
rules: {
categoryName: [{ required: true, message: '题库类别不能为空', trigger: 'blur' }]
},
checked: true, //模板
treeList: [], //模板列表数据
Props: {
children: 'treeStructureRes',
label: 'name'
},
checkedId: '', //选中模板id
projectId: stores.selectedProject.goId,
onlineList: [], //资料列表数据
lineChecked: false,
lineCheckedId: '' //选中资料id
});
// 搜索模板列表数据
watch(filterText, (val: any) => {
treeRef.value!.filter(val);
});
// 搜索资料列表数据
watch(filterText1, (val: any) => {
lineTreeRef.value!.filter(val);
});
// 查询tree树形结构数据
const filterFolder = (value: string, data: any) => {
if (!value) return true;
return data.name.includes(value);
};
// 打开弹窗
const openDialog = (DataId) => {
state.isShowDialog = true;
getInfo();
};
// 关闭弹窗
const closeDialog = () => {
state.isShowDialog = false;
};
// 取消
const onCancel = () => {
closeDialog();
};
// 获取所有数据
const getInfo = () => {
documentAllList().then((res) => {
if (res.code == 0 && res.data.list && res.data.list.length) {
state.treeList = listToTree(res.data.list);
}
});
documentDataAllList({ projectId: state.projectId }).then((res) => {
if (res.code == 0 && res.data.list && res.data.list.length) {
state.onlineList = listToTree(res.data.list);
}
});
};
//数据处理
const listToTree = (list) => {
let array = [];
list.forEach((item) => {
// 遍历对象数组
item.treeStructureRes = list.filter((info) => info.pid === item.idStr); // 找到每个对象的子节点
if (item.pid == 0) {
array.push(item); // 将一层节点放入新数组中
}
});
return array;
};
// 提交
const onSubmit = () => {
onlineImport(state.formData).then((res) => {
if (res.code == 0) {
ElMessage.success('导入成功');
} else {
ElMessage.error(res.message);
onCancel();
}
});
};
const handleCheckChange = (data, checked) => {
if (checked) {
state.checkedId = data.id;
treeRef.value.setCheckedKeys([data.id]);
} else {
if (state.checkedId === data.id) {
treeRef.value.setCheckedKeys([data.id]);
}
}
};
const handleCheckChange1 = (data, checked) => {
if (checked) {
state.lineCheckedId = data.id;
lineTreeRef.value.setCheckedKeys([data.id]);
} else {
if (state.lineCheckedId === data.id) {
lineTreeRef.value.setCheckedKeys([data.id]);
}
}
};
return {
proxy,
openDialog,
closeDialog,
onCancel,
onSubmit,
getInfo,
filterText,
filterText1,
handleCheckChange,
handleCheckChange1,
filterFolder,
treeRef,
lineTreeRef,
...toRefs(state)
};
}
});
</script>
<style scoped lang="scss">
.move_file {
.move_list {
display: flex;
.all_list {
width: 48%;
border: 1px solid #e8e8e8;
padding: 4px;
}
.box_line {
width: 100px;
display: flex;
align-items: center;
flex-direction: column;
justify-content: center;
}
}
}
</style>

View File

@ -0,0 +1,265 @@
<template>
<div class="system-document-container">
<el-card shadow="hover">
<div class="system-document-search mb">
<el-form :model="param" ref="queryRef" :inline="true" label-width="100px">
<el-row>
<el-col :span="5">
<el-form-item label="" prop="createdAt">
<!-- <el-radio-group v-model="value" @change="onChange" class="ml-4">
<el-radio border label="2">资料文件</el-radio>
<el-radio border label="1">模板文件</el-radio>
</el-radio-group> -->
<span>类型</span>
<el-select v-model="value" class="m-2" placeholder="请选择类型" @change="onChange">
<el-option label="资料文件" value="2" />
<el-option label="模板文件" value="1" />
</el-select>
</el-form-item>
</el-col>
<el-col :span="2" v-if="value == '1'">
<el-button
type="success"
v-auth="'/zm/api/v1/system/document/templateRecycleBin'"
:disabled="multiple"
@click="onRecyclingStation(null, true)"
><el-icon><RefreshRight /></el-icon>批量恢复</el-button
>
</el-col>
<el-col :span="2" v-if="value == '1'">
<el-button
type="danger"
v-auth="'/zm/api/v1/system/document/templateRecycleBin'"
:disabled="multiple"
@click="onRecyclingStation(null, false)"
><el-icon><DeleteFilled /></el-icon>批量删除</el-button
>
</el-col>
<el-col :span="2" v-if="value == '2'">
<el-button
type="success"
v-auth="'/zm/api/v1/system/document/dataRecyclingStation'"
:disabled="multiple"
@click="onRecyclingStation(null, true)"
><el-icon><RefreshRight /></el-icon>批量恢复</el-button
>
</el-col>
<el-col :span="2" v-if="value == '2'">
<el-button
type="danger"
v-auth="'/zm/api/v1/system/document/dataRecyclingStation'"
:disabled="multiple"
@click="onRecyclingStation(null, false)"
><el-icon><DeleteFilled /></el-icon>批量删除</el-button
>
</el-col>
</el-row>
</el-form>
</div>
<el-table v-loading="loading" :data="tableData" @selection-change="handleSelectionChange">
<el-table-column type="selection" width="55" align="center" />
<el-table-column label="序号" align="center" type="index" min-width="30px" />
<el-table-column label="文件名称" align="center" prop="name" min-width="100px" />
<el-table-column label="文件类型" align="center" prop="type" min-width="100px">
<template #default="scope">
<span>{{ scope.row.type == 1 ? '文件' : '文件夹' }}</span>
</template> </el-table-column
><el-table-column label="文件路径" align="center" min-width="100px">
<template #default="scope">
<span>{{ filterfilenPath(scope.row.filenPath) }}</span>
</template>
</el-table-column>
<el-table-column label="删除时间" align="center" prop="deletedAt" min-width="100px"> </el-table-column>
<el-table-column label="操作" align="center" class-name="small-padding" min-width="50px" fixed="right">
<template #default="scope">
<div v-if="value == '1'">
<el-button type="success" v-auth="'/zm/api/v1/system/document/templateRecycleBin'" link @click="onRecyclingStation(scope.row, true)"
><el-icon><RefreshRight /></el-icon>恢复</el-button
>
<!-- <el-button type="danger" v-auth="'/zm/api/v1/system/document/templateRecycleBin'" link @click="onRecyclingStation(scope.row, false)"
><el-icon><DeleteFilled /></el-icon>删除</el-button
> -->
</div>
<div v-else>
<el-button
type="success"
v-auth="'/zm/api/v1/system/documentData/dataRecyclingStation'"
link
@click="onRecyclingStation(scope.row, true)"
><el-icon><RefreshRight /></el-icon>恢复</el-button
>
<!-- <el-button
type="danger"
v-auth="'/zm/api/v1/system/documentData/dataRecyclingStation'"
link
@click="onRecyclingStation(scope.row, false)"
><el-icon><DeleteFilled /></el-icon>删除</el-button
> -->
</div>
</template>
</el-table-column>
</el-table>
<pagination v-show="total > 0" :total="total" v-model:page="param.pageNum" v-model:limit="param.pageSize" @pagination="documentList" />
</el-card>
</div>
</template>
<script lang="ts">
import { toRefs, reactive, ref, defineComponent, getCurrentInstance } from 'vue';
import { ElMessageBox, ElMessage, ElLoading } from 'element-plus';
import { documentDataAllList, dataRecyclingStation, templateRecycleBin } from '@/api/quality/onlineListquality/profileData'; //获取资料删除的列表数据
import { documentAllList } from '@/api/quality/onlineListquality/Online'; //获取模板删除列表数据
import { useUserStoreHook } from '@/store/modules/user';
export default defineComponent({
name: 'index',
setup() {
const stores = useUserStoreHook();
const { proxy } = <any>getCurrentInstance();
const loading = ref(false);
const queryRef = ref();
// 非多个禁用
const multiple = ref(true);
// 字典选项数据
const {} = proxy.useDict();
const state = reactive({
ids: [],
tableData: [],
param: {
type: 2,
projectId: stores.selectedProject.goId
},
total: 0,
value: '2',
ids: [], //所选择的文件
userName: stores.nickname // 当前用户名
});
// 获取资料删除的列表数据
const getDocumentDataList = () => {
loading.value = true;
state.tableData = [];
state.value = '2';
documentDataAllList(state.param).then((res: any) => {
let list = res.data.list ?? [];
state.tableData = list;
state.total = res.data.total;
loading.value = false;
});
};
// 获取模板删除的列表数据
const getDocumentList = () => {
loading.value = true;
state.tableData = [];
documentAllList(state.param).then((res: any) => {
let list = res.data.list ?? [];
state.tableData = list;
state.total = res.data.total;
loading.value = false;
});
};
// 多选框选中数据
const handleSelectionChange = (selection) => {
state.ids = selection.map((item) => item.id);
multiple.value = !selection.length;
};
const onRecyclingStation = (row, flag) => {
let type = 2;
let ids = [];
let title = '删除';
if (row) {
ids = [row.id];
} else {
// 批量
ids = state.ids;
}
let msg = '你确定要删除所选文件或文件夹?';
if (flag) {
type = 1;
title = '恢复';
msg = '你确定要恢复所选文件或文件夹?';
}
ElMessageBox.confirm(msg, '提示', {
confirmButtonText: '确认',
cancelButtonText: '取消',
type: 'warning'
})
.then(() => {
const loading = ElLoading.service({
lock: true,
text: '正在' + title + '中……',
background: 'rgba(0, 0, 0, 0.7)'
});
if (state.value == 2) {
dataRecyclingStation({
ids,
type
}).then((res) => {
loading.close();
if (res.code == 0) {
getDocumentDataList();
ElMessage.success('操作成功');
} else {
ElMessage.error(res.message);
}
});
} else {
templateRecycleBin({
ids,
type
}).then((res) => {
loading.close();
if (res.code == 0) {
getDocumentList();
ElMessage.success('操作成功');
} else {
ElMessage.error(res.message);
}
});
}
})
.catch(() => {});
};
const onChange = (val) => {
// 切换文件类型
if (val == 2) {
getDocumentDataList();
} else {
getDocumentList();
}
};
const filterfilenPath = (val) => {
// 文件路径
if (state.value == 2) {
// 资料
if (state.userName) {
//用户名不存在的情况下
val.substring(val.lastIndexOf(state.userName) + state.userName.length);
}
return val.substring(val.lastIndexOf(state.userName));
} else {
// 模板 文件在masterMask目录下 默认显示目录下路径
return val.substring(val.lastIndexOf('masterMask') + 'masterMask'.length);
}
};
return {
proxy,
onChange,
multiple,
loading,
onRecyclingStation,
handleSelectionChange,
getDocumentDataList,
filterfilenPath,
...toRefs(state)
};
}
});
</script>
<style lang="scss" scoped>
.colBlock {
display: block;
}
.colNone {
display: none;
}
</style>

View File

@ -0,0 +1,170 @@
<template>
<div class="upload_fileder">
<el-dialog v-model="isShowDialog" width="400px" :close-on-click-modal="false" :destroy-on-close="true">
<template #header>
<div v-drag="['.upload_fileder .el-dialog', '.upload_fileder .el-dialog__header']">上传文件</div>
</template>
<el-form ref="formRef" :model="formData" :rules="rules" label-width="80px">
<el-form-item label="文件上传">
<upload-file
:accept="acceptType"
uploadUrl="/zm/api/v1/system/upload/singleFile"
type="btn"
:data="{ token: fileToken }"
isGo
:onUploadSuccess="getOnSuccess"
:limit="1"
></upload-file>
</el-form-item>
</el-form>
<template #footer>
<div class="dialog-footer">
<el-button type="primary" @click="onSubmit"> </el-button>
<el-button @click="onCancel"> </el-button>
</div>
</template>
</el-dialog>
</div>
</template>
<script lang="ts">
import { reactive, toRefs, defineComponent, ref, unref, getCurrentInstance, onMounted } from 'vue';
import { ElMessage, genFileId } from 'element-plus';
import { Session } from '@/utils/storage';
import uploadFile from '@/components/FileUpload/index.vue';
import { documentAdd } from '@/api/quality/onlineListquality/Online';
import { documentDataAdd } from '@/api/quality/onlineListquality/profileData';
import { useUserStoreHook } from '@/store/modules/user';
export default defineComponent({
name: 'index',
components: { uploadFile },
setup(props, { emit }) {
const { proxy } = (<any>getCurrentInstance()) as any;
const fileToken = proxy.$cache.local.get('goToken');
const formRef = ref<HTMLElement | null>(null);
const stores = useUserStoreHook();
const uploadRef = ref(); //文件dom
const state = reactive({
isShowDialog: false,
formData: {
pid: null,
fileType: 1,
filePath: {},
projectId: stores.selectedProject.goId
},
// 表单校验
rules: {},
token: `Bearer ${fileToken}`,
acceptType: '',
flag: false
});
const getOnSuccess = (list, filePath) => {
console.log('🚀 ~ getOnSuccess ~ filePath:', filePath);
let { path, name, size } = filePath.data;
state.formData.filePath = {
url: path,
name,
size,
fileType: name.substring(name.lastIndexOf('.'), name.length) //后缀名
};
};
// 打开弹窗
const openDialog = (parentPid, fileType, acceptType, flag = false) => {
state.isShowDialog = true;
state.formData.pid = parentPid;
state.formData.fileType = fileType;
state.acceptType = acceptType;
state.flag = flag;
};
// 关闭弹窗
const closeDialog = () => {
state.isShowDialog = false;
};
// 取消
const onCancel = () => {
closeDialog();
emit('onCloseFile', true);
};
const handleExceed = (files) => {
uploadRef.value!.clearFiles();
const file = files[0];
file.uid = genFileId();
uploadRef.value!.handleStart(file);
};
// 提交
const onSubmit = () => {
if (JSON.stringify(state.formData.filePath) === '{}') {
ElMessage({
type: 'warning',
message: '请上传文件'
});
return;
}
const formWrap = unref(formRef) as any;
if (!formWrap) return;
formWrap.validate((valid: boolean) => {
if (valid) {
if (state.flag) {
// 资料文件上传
documentDataAdd(state.formData).then((res: any) => {
if (res.code == 0) {
emit('getDocumentListFileType', state.formData.fileType);
ElMessage({
type: 'success',
message: '添加成功'
});
onCancel();
} else {
ElMessage({
type: 'error',
message: res.message
});
}
});
} else {
// 模板文件上传
documentAdd(state.formData).then((res) => {
if (res.code == 0) {
emit('getDocumentListFileType', state.formData.fileType);
ElMessage({
type: 'success',
message: '添加成功'
});
onCancel();
} else {
ElMessage({
type: 'error',
message: res.message
});
}
});
}
}
});
};
const onSuccess = (res) => {
if (res.code == 0) {
ElMessage.success('上传成功');
} else {
ElMessage.error(res.message);
}
};
return {
proxy,
uploadRef,
openDialog,
closeDialog,
onCancel,
onSubmit,
handleExceed,
fileToken,
formRef,
onSuccess,
getOnSuccess,
...toRefs(state)
};
}
});
</script>
<style scoped></style>

View File

@ -0,0 +1,750 @@
<template>
<div class="p-2">
<div class="onLine_list">
<el-tabs v-model="activeName" class="demo-tabs" @tab-change="handleClick">
<el-tab-pane label="模板" name="first">
<div class="box_info">
<div class="tree_left" id="tree_left">
<div class="check_select">
<el-button type="primary" v-auth="'/zm/api/v1/system/document/newFolder'" @click="addFile"
><el-icon><Plus /></el-icon>新建文件夹</el-button
>
<div class="box_btn" v-auth="'/zm/api/v1/system/document/add'">
<span>导入</span>
<div class="btn">
<el-button type="primary" style="float: left" @click="bigUploadFile" size="small"
><el-icon><Plus /></el-icon>导入压缩文件</el-button
>
<el-button type="primary" style="float: left" :disabled="!parentPid" size="small" @click="uploadFile(2)"
><el-icon><Plus /></el-icon>导入文件</el-button
>
</div>
</div>
</div>
<div class="file_upload check_select">
<el-checkbox v-model="checked" @change="handleCheckedTreeExpand($event)" label="展开/折叠" size="large" />
<div style="margin: 0 10px">
<el-select v-model="paramsQuery.switch" placeholder="当前文件夹" size="small">
<el-option v-for="item in options" :key="item.id" :label="item.label" :value="item.id" />
</el-select>
</div>
<el-button type="primary" v-auth="'/zm/api/v1/system/document/compressedDownload'" :disabled="!parentPid" @click="onExport"
><el-icon><Download /></el-icon>下载</el-button
>
</div>
<div class="file_upload check_select">
<el-input class="input_left" v-model="filterText" size="small" placeholder="请输入文件名称" />
</div>
<el-tree
ref="treeRef"
highlight-current
:default-expand-all="checked"
:filter-node-method="filterFolder"
:data="treeList"
:props="Props"
node-key="id"
accordion
:expand-on-click-node="false"
@node-click="handleNodeClick"
:current-node-key="selectedNodeId"
>
<template #default="{ node, data }">
<span class="custom-tree-node">
<el-icon color="#f1a81a"><FolderOpened /></el-icon>
<span>{{ node.label }}</span>
<span style="margin-left: 20px" class="set-tool">
<!-- <el-button type="primary" link @click="onAppend(node)">添加文件夹</el-button> -->
<el-button type="success" link v-auth="'/zm/api/v1/system/document/edit'" @click.stop="onUpdateName(node, data)"
>重命名</el-button
>
<el-button type="danger" v-auth="'/zm/api/v1/system/document/delete'" link @click.stop="onRemove(node, data)">删除</el-button>
</span>
</span>
</template>
</el-tree>
<div class="resize-handle resize-handle-right right"></div>
</div>
<div class="list_right" id="list_right">
<div>
<el-form :model="paramsQuery" ref="queryRef" :inline="true" label-width="100px">
<el-row>
<el-col :span="8" class="colBlock">
<el-form-item label="文件名称" prop="name">
<el-input v-model="paramsQuery.name" placeholder="请输入文件名称" clearable @keyup.enter.native="getDocumentList" />
</el-form-item>
</el-col>
<el-col :span="6">
<el-form-item>
<el-button type="primary" @click="searchInfo"
><el-icon><Search /></el-icon>搜索</el-button
>
<el-button @click="resetQuery"
><el-icon><Refresh /></el-icon>重置</el-button
>
</el-form-item>
</el-col>
</el-row>
</el-form>
</div>
<el-table v-loading="loading" :data="infoList" height="67vh" border>
<el-table-column label="序号" align="center" type="index" min-width="50px" />
<el-table-column label="模板名称" align="center" prop="name">
<template #default="scope">
<span>{{ scope.row.name + scope.row.suffix }}</span>
</template>
</el-table-column>
<el-table-column label="创建时间" align="center" prop="createdAt"> </el-table-column>
<el-table-column label="操作" align="center">
<template #default="scope">
<el-button type="primary" link v-auth="'/zm/api/v1/system/document/get'" @click="handleView(scope.row)"
><el-icon><View /></el-icon>预览模板</el-button
>
<el-button type="success" link v-auth="'/zm/api/v1/system/document/complaintBoxAdd'" @click="updataView(scope.row)"
><el-icon><EditPen /></el-icon>修改模板</el-button
>
<el-button type="primary" v-auth="'/zm/api/v1/system/document/compressedDownload'" link @click="onExportView(scope.row)"
><el-icon><Download /></el-icon>下载</el-button
>
<el-button type="success" v-auth="'/zm/api/v1/system/document/edit'" link @click="updateName(scope.row)"
><el-icon><EditPen /></el-icon>修改名称</el-button
>
<el-button type="danger" link v-auth="'/zm/api/v1/system/document/delete'" @click="handleDelete(scope.row)"
><el-icon><DeleteFilled /></el-icon>删除</el-button
>
</template>
</el-table-column>
</el-table>
<pagination :total="total" v-model:page="paramsQuery.pageNum" v-model:limit="paramsQuery.pageSize" @pagination="getDocumentList" />
</div>
</div>
</el-tab-pane>
<el-tab-pane label="资料" name="second">
<div style="width: 100%; height: 100%">
<profileEngineering ref="profileEngineeringRef" :activeName="activeName"></profileEngineering>
</div>
</el-tab-pane>
<el-tab-pane label="回收站" name="three">
<div style="width: 100%; height: 100%">
<recycleBin ref="recycleBinRef"></recycleBin>
</div>
</el-tab-pane>
</el-tabs>
<documentDetail ref="documentDetailRef" v-if="showDocumentDetail" @onClose="onClose"></documentDetail>
<documentsEdit ref="documentEditRef" v-if="showDocumentEdit" @onClose="onCloseEdit"></documentsEdit>
<uploadFileder
ref="uploadFilederRef"
v-if="showUploadFileder"
@onCloseFile="showUploadFileder = false"
@getDocumentListFileType="getDocumentListFileType"
></uploadFileder>
<bookFile ref="bookFileRef"></bookFile>
</div>
</div>
</template>
<script lang="ts">
import { toRefs, reactive, onMounted, ref, defineComponent, watch, getCurrentInstance, nextTick, onBeforeUnmount } from 'vue';
import { ElLoading, ElMessageBox, ElMessage } from 'element-plus';
import {
treeStructureList,
documentList,
documentEdit,
documentDelete,
documentNewFolder,
compressedDownload
} from '@/api/quality/onlineListquality/Online';
// 文档查看
import documentDetail from './comm/documentsDetail/index.vue';
// 文档修改编辑
import documentsEdit from './comm/documentsEdit/index.vue';
// 资料信息列表
// import profileData from '/@/views/OnlineEngineering/profileData/index.vue';
// 工程资料模块
import profileEngineering from './comm/profileEngineering/index.vue';
// 回收站功能
import recycleBin from './comm/recycleBIn/index.vue';
// 文件导入弹框
import uploadFileder from './comm/uploadFileder/index.vue';
//
import { documentAdd } from '@/api/quality/onlineListquality/Online';
import { useRouter } from 'vue-router';
export default defineComponent({
name: 'index',
components: { documentDetail, documentsEdit, uploadFileder, profileEngineering, recycleBin },
setup() {
const { proxy } = <any>getCurrentInstance();
const router = useRouter();
const filterText = ref(''); //搜索树形结构参数
const treeRef = ref(); //树形结构dom
const documentDetailRef = ref(); //详情在线dom
const documentEditRef = ref(); //编辑在线dom
const uploadFilederRef = ref(); //上传文件在线dom
const profileEngineeringRef = ref(); //资料信息
const recycleBinRef = ref(); //回收站
const state = reactive({
treeList: [] as any, //树形结构数据
arrayList: [] as any, //数据
infoList: [] as any, //文档列表数据
activeName: 'first',
Props: {
children: 'treeStructureRes',
label: 'name'
},
total: 0, //文档数量
paramsQuery: { idStr: '', name: '', switch: 1, pageNum: 1, pageSize: 20 }, //请求参数
loading: false, //列表加载
checked: true, //展开 折叠
options: [
{ id: 1, label: '当前文件夹及以下' },
{ id: 2, label: '当前文件夹' }
],
showDocumentDetail: false, //详情弹框
showDocumentEdit: false, //编辑弹框
showUploadFileder: false, //文件及文件夹导入
parentRow: null, //父级对象
parentPid: null, //父级pid
parentName: '', //父级名称
selectedNodeId: null //选中
});
// 搜索数据
watch(filterText, (val: any) => {
treeRef.value!.filter(val);
});
onMounted(() => {
// let rouerPath = router.currentRoute.value.fullPath;
// // 质量管理跳转至工程资料,优先展示资料模块
// if (rouerPath.includes('quality')) {
// state.activeName = 'second';
// } else {
// state.activeName = 'first';
// }
getTreeStructureList();
resizeHandleRight();
// 判断是否调用该页面文件成功后添加到后台
proxy.mittBus.on('bigUploader.uploadFileSuccess' + 1001, (res: any) => {
const { filename, totalSize, url, identifier, fileType } = res;
let arr = filename.split('.');
let fileType1 = arr[arr.length - 1];
let obj = {
filePath: {
url,
name: filename,
size: totalSize,
fileType: '.' + fileType1 //后缀名
},
fileType: 1,
pid: state.parentPid
};
documentAdd(obj).then((res: any) => {
if (res.code == 0) {
getDocumentListFileType(1);
ElMessage({
type: 'success',
message: '添加成功'
});
} else {
ElMessage({
type: 'error',
message: res.message
});
}
});
});
});
onBeforeUnmount(() => {
// 取消订阅特定事件
proxy.mittBus.off('bigUploader.uploadFileSuccess' + 1001);
});
// 导入大文件
const bigUploadFile = () => {
// 文件上传
proxy.mittBus.emit('bigUploader.uploadFile', { type: 1, types: 1001, accept: ['.zip', '.rar'] });
};
// 新建文件夹
const addFile = () => {
let tip = '在根目录下新建文件夹';
if (state.parentPid) {
tip = '在“' + state.parentName + '文件夹”下新建文件夹';
}
ElMessageBox.prompt('请输入文件夹名称', tip, {
confirmButtonText: '确定',
cancelButtonText: '取消',
inputErrorMessage: '请输入文件夹名称',
inputValue: ''
})
.then(({ value }) => {
documentNewFolder({ fileName: value, pid: state.parentPid, fileType: 3 }).then((res) => {
if (res.code == 0) {
ElMessage({
type: 'success',
message: '添加成功'
});
getTreeStructureList();
} else {
ElMessage({
type: 'error',
message: res.message
});
}
});
})
.catch(() => {});
};
// 添加文件夹到树形结构上
const onAppend = (data) => {
if (state.parentRow) {
if (!state.parentRow.treeStructureRes) {
state.parentRow.treeStructureRes = [];
}
state.parentRow.treeStructureRes.push(data);
state.treeList = [...state.treeList];
} else {
state.treeList.push(data); //跟目录添加
}
};
//
// 导入文件
const uploadFile = (fileType) => {
if (fileType == 2 && !state.parentPid) {
ElMessage.warning('请选择文件目录!');
return;
}
// 判断上传类型 文件与压缩包区分
let acceptType = '.zip'; //压缩文件类型
if (fileType == 2) {
//文件上传
acceptType = '.pdf,.doc,.docx,.xls,.xlsx,.ppt,.pptx,';
}
state.showUploadFileder = true;
nextTick(() => {
// 打开弹框
uploadFilederRef.value.openDialog(state.parentPid, fileType, acceptType);
});
};
const searchInfo = () => {
// 搜索
getDocumentList();
};
const resetQuery = () => {
// 重置
state.paramsQuery.name = '';
getDocumentList();
};
// 获取树形结构文件夹目录
const getTreeStructureList = () => {
const loading = ElLoading.service({
lock: true,
text: '正在加载中……',
background: 'rgba(0, 0, 0, 0.7)',
target: '.tree_left'
});
treeStructureList().then((res) => {
loading.close();
if (res.code == 0 && res.data && res.data.list) {
state.selectedNodeId = '';
state.treeList = res.data.list;
state.paramsQuery.idStr = res.data.list[0].idStr;
getDocumentList();
setInfo(res.data.list);
}
});
};
// 处理数据
const setInfo = (arr) => {
arr.forEach((element) => {
state.arrayList.push(element);
if (element.treeStructureRes && element.treeStructureRes.length) {
setInfo(element.treeStructureRes);
}
});
};
// 选择目录文件
const handleNodeClick = (row) => {
state.parentRow = row;
state.parentPid = row.idStr;
state.parentName = row.name;
state.paramsQuery.idStr = row.idStr;
state.paramsQuery.name = '';
if (row.id === state.selectedNodeId) {
// 如果当前节点已经选中,则取消选中
state.selectedNodeId = null;
state.parentPid = null; //关闭父级选择的id
state.parentRow = null; //获取父级对象
state.parentName = ''; //获取父级对应的名称
// state.paramsQuery.idStr = ''; //
} else {
getDocumentList();
// 否则选中当前节点 重新赋值
state.selectedNodeId = row.id;
}
};
// 获取文档列表数据
const getDocumentList = () => {
if (!state.paramsQuery.idStr) {
return;
}
state.loading = true;
documentList(state.paramsQuery).then((res: any) => {
state.loading = false;
if (res.code == 0) {
res.data.list.sort((a, b) => {
return a.name.localeCompare(b.name);
});
state.infoList = res.data.list;
state.total = res.data.total;
}
});
};
// 查询tree树形结构数据
const filterFolder = (value: string, data: any) => {
if (!value) return true;
return data.name.includes(value);
};
const handleClick = (type) => {
// 切换页面 结构重新调用
if (type == 'first') {
// 模板
state.parentPid = null;
getTreeStructureList();
} else if (type == 'second') {
// 资料
profileEngineeringRef.value.gettreeStructureData();
} else {
// 回收站列表数据获取
recycleBinRef.value.getDocumentDataList();
}
};
const handleDelete = (row) => {
// 删除文档
let msg = '你确定要删除所选文件?';
delFile(msg, row, () => {
getDocumentList();
});
};
const onExportView = (row) => {
// 下载模板
let fileUrl = row.filenPathCoding.replaceAll('+', ' ');
window.open(fileUrl, '_Black');
};
const updateName = (row) => {
// 修改名称
editName(row, '请输入文件名称', 1);
};
const handleView = (row) => {
// 查看文档
state.showDocumentDetail = true;
nextTick(() => {
documentDetailRef.value.openDialog(row);
});
};
// 关闭在线编辑弹框
const onClose = () => {
state.showDocumentDetail = false;
};
// 展开或折叠节点
const handleCheckedTreeExpand = (value: any) => {
for (let i = 0; i < state.arrayList.length; i++) {
treeRef.value.store.nodesMap[state.arrayList[i].id].expanded = value;
}
};
// 关闭修改的在线文档弹框
const onCloseEdit = () => {
state.showDocumentEdit = false;
};
const updataView = (row) => {
// 修改文档
state.showDocumentEdit = true;
nextTick(() => {
documentEditRef.value.openDialog(row, '/zm/api/v1/system/busConstructionUser/complaintBoxAdd');
});
};
const resizeHandleRight = () => {
// 右侧鼠标移动大小
const resizeHandles = document.getElementsByClassName('resize-handle');
Array.from(resizeHandles).forEach((handle) => {
handle.addEventListener('mousedown', startResize);
});
};
const startResize = (event) => {
event.preventDefault();
let dragElement = document.getElementById('tree_left') as any;
let dragElementRight = document.getElementById('list_right');
const currentHandle = event.target;
const direction = currentHandle.className.split(' ')[1];
const startX = event.clientX;
const startY = event.clientY;
// 左侧移动的盒子大小
const startWidth = dragElement.offsetWidth;
const startHeight = dragElement.offsetHeight;
const startLeft = dragElement.offsetLeft;
const startTop = dragElement.offsetTop;
// 右侧移动盒子宽度
const rightWidth = dragElementRight.offsetWidth;
document.addEventListener('mousemove', resize);
document.addEventListener('mouseup', stopResize);
function resize(event) {
const dx = event.clientX - startX;
const dy = event.clientY - startY;
let width = startWidth;
let height = startHeight;
let left = startLeft;
let top = startTop;
let rightWidth1 = rightWidth as any;
if (direction.includes('right')) {
width = startWidth + dx + 'px';
let w = startWidth + dx + 10 + 'px';
rightWidth1 = `calc(100% - ${w})`;
}
if (parseInt(width) <= 0 || parseInt(height) <= 0) return;
dragElementRight.style.width = rightWidth1;
dragElement.style.width = width;
dragElement.style.height = height;
dragElement.style.left = left;
dragElement.style.top = top;
}
function stopResize() {
document.removeEventListener('mousemove', resize);
document.removeEventListener('mouseup', stopResize);
}
};
// 删除文件及文件夹
const delFile = (msg, data, cb) => {
ElMessageBox.confirm(msg, '提示', {
confirmButtonText: '确认',
cancelButtonText: '取消',
type: 'warning'
})
.then(() => {
documentDelete([data.id]).then((res: any) => {
if (res.code == 0) {
ElMessage.success('删除成功');
cb();
}
});
})
.catch(() => {});
};
const onRemove = (node, data) => {
const parent = node.parent;
const children = parent.data.treeStructureRes || parent.data;
const index = children.findIndex((d) => d.id === data.id);
let msg = '你确定要删除所选文件夹?';
ElMessageBox.confirm(msg, '提示', {
confirmButtonText: '确认',
cancelButtonText: '取消',
type: 'warning'
})
.then(() => {
const loading = ElLoading.service({
lock: true,
text: '正在处理中……',
background: 'rgba(0, 0, 0, 0.7)',
target: '.tree_left'
});
documentDelete([data.id]).then((res: any) => {
if (res.code == 0) {
loading.close();
ElMessage.success('删除成功');
children.splice(index, 1);
state.treeList = [...state.treeList];
if (data.idStr == state.paramsQuery.idStr) {
// 说明此时删除的是右侧列表所在的文件夹
state.infoList = [];
}
}
});
})
.catch(() => {});
};
const editName = (data, title, type) => {
ElMessageBox.prompt(title, '温馨提示', {
confirmButtonText: '确定',
cancelButtonText: '取消',
inputErrorMessage: title,
inputValue: data.name
})
.then(({ value }) => {
documentEdit({ id: data.id, name: value, type }).then((res) => {
if (res.code == 0) {
ElMessage({
type: 'success',
message: '修改成功'
});
if (type == 2) {
getTreeStructureList();
} else {
getDocumentList();
}
} else {
ElMessage({
type: 'error',
message: res.message
});
}
});
})
.catch(() => {});
};
const onUpdateName = (node, data) => {
editName(data, '请输入文件夹名称', 2);
};
const getDocumentListFileType = (fileType) => {
if (fileType == 2) {
getDocumentList();
} else {
getTreeStructureList();
}
};
const onExport = () => {
compressedDownload(state.parentRow.filenPath).then((res: any) => {
if (res.code == 0) {
let fileUrl = res.data.RelativePath;
window.open(fileUrl, '_self');
}
});
};
return {
proxy,
filterText,
treeRef,
documentDetailRef,
uploadFilederRef,
profileEngineeringRef,
recycleBinRef,
documentEditRef,
onClose,
onCloseEdit,
handleClick,
handleNodeClick,
filterFolder,
searchInfo,
addFile,
uploadFile,
bigUploadFile,
resetQuery,
getDocumentList,
getDocumentListFileType,
handleDelete,
onExportView,
updateName,
getTreeStructureList,
updataView,
handleView,
onRemove,
onAppend,
onUpdateName,
handleCheckedTreeExpand,
onExport,
...toRefs(state)
};
}
});
</script>
<style lang="scss" scoped>
.onLine_list {
height: 86vh;
.set-tool {
display: none;
}
.el-tree-node__content:hover,
.el-tree-node__content:active {
.set-tool {
display: inline-block;
}
}
.el-tree--highlight-current .el-tree-node.is-current > .el-tree-node__content {
background-color: #354e67 !important;
color: #fff;
}
.box_info {
display: flex;
justify-content: space-between;
}
.pagination-container {
padding: 10px 0 !important;
}
> div {
height: 100%;
width: 100%;
}
.tree_left {
width: 30%;
background-color: #fff;
border: 1px solid #dddddd;
border-radius: 6px;
padding: 6px 0px;
position: relative;
min-width: 26%;
border-right: 6px solid;
border-right-color: rgba(204, 230, 255, 0);
.resize-handle-right {
top: 0;
width: 6px;
height: 100%;
right: -10px;
cursor: ew-resize;
position: absolute;
z-index: 999;
}
.check_select {
display: flex;
align-items: center;
width: 100%;
padding: 4px;
border-bottom: 1px solid #f1f1f1;
.box_btn {
width: 300px;
margin: 0 10px 0 20px;
position: relative;
> span {
padding: 4px 10px;
background: #67c23a;
color: #fff;
border-radius: 2px;
}
.btn {
position: absolute;
left: 22%;
display: none;
top: -2px;
width: 220px;
.el-button {
float: left;
}
}
}
.box_btn:hover,
.box_btn:active {
cursor: pointer;
.btn {
display: block;
}
}
}
.file_upload {
margin: 2px 0;
}
.input_left {
padding: 6px;
box-sizing: border-box;
// border-bottom: 1px solid #cbcbcb;
}
}
.list_right {
width: 69.5%;
background: white;
border: 1px solid #ededed;
padding: 10px;
box-sizing: border-box;
}
.el-tree {
height: calc(80vh - 160px);
width: 100%;
overflow: auto !important;
}
// .el-tree-node__children {
// overflow: visible !important;
// }
}
</style>

View File

@ -59,6 +59,7 @@
<el-table-column label="操作" align="center" class-name="small-padding fixed-width">
<template #default="scope">
<el-button link type="primary" icon="View" @click="handleUpdate(scope.row)">详情</el-button>
<el-button link type="primary" icon="Delete" @click="handleDelete(scope.row)">删除</el-button>
</template>
</el-table-column>
</el-table>

View File

@ -52,7 +52,7 @@
</el-space>
</el-descriptions-item>
<el-descriptions-item label-align="center" label="检查状态" :span="2" label-class-name="white">
<el-steps style="max-width: 200px" :active="Number(safetyInspectionDetail?.inspectionStatus)" finish-status="finish">
<el-steps style="max-width: 200px" :active="Number(safetyInspectionDetail?.status)" finish-status="finish">
<el-step v-for="item in quality_inspection_status_type" :key="item.value" :title="item.label" />
</el-steps>
</el-descriptions-item>

View File

@ -26,7 +26,7 @@
<el-card shadow="never">
<template #header>
<el-row :gutter="10" class="mb8">
<!-- <el-col :span="1.5">
<el-col :span="1.5">
<el-button type="primary" plain icon="Plus" @click="handleAdd" v-hasPermi="['quality:qualityInspection:add']">新增</el-button>
</el-col>
<el-col :span="1.5">
@ -42,7 +42,7 @@
</el-col>
<el-col :span="1.5">
<el-button type="warning" plain icon="Download" @click="handleExport" v-hasPermi="['quality:qualityInspection:export']">导出</el-button>
</el-col> -->
</el-col>
<right-toolbar v-model:showSearch="showSearch" @queryTable="getList"></right-toolbar>
</el-row>
</template>
@ -75,23 +75,23 @@
</template>
</el-table-column>
<el-table-column label="整改人" align="center" prop="two" />
<!-- <el-table-column label="工单状态" align="center" prop="status">
<el-table-column label="工单状态" align="center" prop="status">
<template #default="scope">
<dict-tag :options="quality_inspection_status_type" :value="scope.row.status" />
</template>
</el-table-column> -->
</el-table-column>
<!-- <el-table-column label="创建者" align="center" prop="createBy" /> -->
<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"
v-if="scope.row.status == 2"
icon="EditPen"
@click="handleUpdate(scope.row)"
v-hasPermi="['quality:qualityInspection:edit']"
></el-button>
</el-tooltip> -->
>验证</el-button
>
<el-button link type="primary" icon="View" @click="handleDetail(scope.row)" v-hasPermi="['quality:qualityInspection:edit']">
详情
</el-button>
@ -101,6 +101,50 @@
<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="700px" append-to-body>
<el-form ref="qualityInspectionFormRef" :model="form" :rules="rules" label-width="80px" v-if="!form.id">
<el-form-item label="巡检标题" prop="inspectionHeadline">
<el-input v-model="form.inspectionHeadline" placeholder="请输入巡检标题" />
</el-form-item>
<el-form-item label="巡检结果" prop="inspectionResult">
<el-input v-model="form.inspectionResult" placeholder="请输入巡检结果" />
</el-form-item>
<el-form-item label="巡检类型" prop="inspectionType">
<el-select v-model="form.inspectionType" placeholder="请选择巡检类型">
<el-option v-for="dict in quality_inspection_check_type" :key="dict.value" :label="dict.label" :value="dict.value"></el-option>
</el-select>
</el-form-item>
<el-form-item label="整改人" prop="corrector">
<el-select v-model="form.corrector" placeholder="请输入整改人">
<el-option v-for="dict in foremanOpt" :key="dict.openid" :label="dict.userName" :value="dict.openid"></el-option>
</el-select>
</el-form-item>
<el-form-item label="附件" prop="inspectionFile">
<file-upload
ref="uploadRef"
v-model="form.inspectionFile"
isGo
upload-url="/zm/api/v1/system/busInspectionTicket/add"
:data="form"
:accept="['doc', 'docx', 'pdf', 'png', 'jpg', 'jpeg']"
/>
</el-form-item>
</el-form>
<el-form ref="qualityInspectionFormRef" :model="form" :rules="rules" label-width="80px" v-else>
<el-form-item label="验证意见" prop="verificationType">
<el-radio-group v-model="form.verificationType">
<el-radio label="1">通过</el-radio>
<el-radio label="2">不通过</el-radio>
</el-radio-group>
</el-form-item>
</el-form>
<template #footer>
<div class="dialog-footer">
<el-button :loading="buttonLoading" type="primary" @click="submitForm"> </el-button>
<el-button @click="cancel"> </el-button>
</div>
</template>
</el-dialog>
<el-dialog title="质量工单详情" v-model="dialog.details" width="60vw">
<quality-inspection-detail :quality-inspection-detail-id="currentId" />
</el-dialog>
@ -116,7 +160,8 @@ import {
getQualityInspection,
delQualityInspection,
addQualityInspection,
updateQualityInspection
updateQualityInspection,
acquisitionOfCorrectivePersonnel
} from '@/api/quality/qualityInspection';
import { QualityInspectionVO, QualityInspectionQuery, QualityInspectionForm } from '@/api/quality/qualityInspection/types';
import { useUserStoreHook } from '@/store/modules/user';
@ -137,7 +182,7 @@ const ids = ref<Array<string | number>>([]);
const single = ref(true);
const multiple = ref(true);
const total = ref(0);
const uploadRef = ref(null);
const queryFormRef = ref<ElFormInstance>();
const qualityInspectionFormRef = ref<ElFormInstance>();
@ -232,20 +277,27 @@ const handleSelectionChange = (selection: QualityInspectionVO[]) => {
};
/** 新增按钮操作 */
const handleAdd = () => {
const handleAdd = async () => {
reset();
await getPeople();
dialog.visible = true;
dialog.title = '添加质量-检查工单';
};
const foremanOpt = ref([]);
const getPeople = async () => {
await acquisitionOfCorrectivePersonnel(currentProject.value?.goId).then((res) => {
foremanOpt.value = res.data.list;
});
};
/** 验证按钮操作 */
const handleUpdate = async (row?: QualityInspectionVO) => {
reset();
const _id = row?.id || ids.value[0];
const res = await getQualityInspection(_id);
Object.assign(form.value, res.data);
form.value.id = row?.id;
console.log('🚀 ~ handleUpdate ~ form.value.id:', form.value.id);
dialog.visible = true;
dialog.title = '修改质量-检查工单';
dialog.title = '验证';
};
const currentId = ref<string | number>('');
@ -261,13 +313,21 @@ const submitForm = () => {
if (valid) {
buttonLoading.value = true;
if (form.value.id) {
await updateQualityInspection(form.value).finally(() => (buttonLoading.value = false));
} else {
await addQualityInspection(form.value).finally(() => (buttonLoading.value = false));
}
await updateQualityInspection({ id: form.value.id, verificationType: form.value.verificationType }).finally(
() => (buttonLoading.value = false)
);
proxy?.$modal.msgSuccess('操作成功');
dialog.visible = false;
await getList();
getList();
} else {
uploadRef.value.submitUpload().then((res) => {
if (res != 'noFile') {
proxy?.$modal.msgSuccess('操作成功');
dialog.visible = false;
getList();
}
});
}
}
});
};

View File

@ -5,7 +5,11 @@
<el-form :model="param" ref="queryRef" :inline="true" label-width="100px">
<el-row>
<el-col>
<el-button type="success" v-hasPermi="['project:project:remove']" :disabled="multiple" @click="onRecyclingStation(null)"
<el-button
type="success"
v-auth="'api/v1/system/documentCompletion/completionDataRecyclingStation'"
:disabled="multiple"
@click="onRecyclingStation(null, true)"
><el-icon><RefreshRight /></el-icon>批量恢复</el-button
>
</el-col>
@ -15,42 +19,43 @@
<el-table v-loading="loading" :data="tableData" @selection-change="handleSelectionChange">
<el-table-column type="selection" width="55" align="center" />
<el-table-column label="序号" align="center" type="index" min-width="30px" />
<el-table-column label="文件名称" align="center" prop="fileName" min-width="100px" />
<el-table-column label="文件类型" align="center" prop="fileType" min-width="100px">
<el-table-column label="文件名称" align="center" prop="name" min-width="100px" />
<el-table-column label="文件类型" align="center" prop="type" min-width="100px">
<template #default="scope">
<span>{{ scope.row.fileType == '1' ? '文件' : '文件夹' }}</span>
<span>{{ scope.row.type == 1 ? '文件' : '文件夹' }}</span>
</template> </el-table-column
><el-table-column label="文件路径" align="center" min-width="100px">
<template #default="scope">
<span>{{ scope.row.filePath }}</span>
<span>{{ scope.row.filenPath }}</span>
</template>
</el-table-column>
<el-table-column label="删除时间" align="center" prop="deletedAt" min-width="100px"> </el-table-column>
<el-table-column label="操作" align="center" class-name="small-padding" min-width="100px" fixed="right">
<template #default="scope">
<el-button type="success" v-hasPermi="['project:project:remove']" link @click="onRecyclingStation(scope.row)"
<el-button
type="success"
v-auth="'api/v1/system/documentCompletion/completionDataRecyclingStation'"
link
@click="onRecyclingStation(scope.row)"
><el-icon><RefreshRight /></el-icon>恢复</el-button
>
</template>
</el-table-column>
</el-table>
<!-- <pagination v-show="total > 0" :total="total" v-model:page="param.pageNum" v-model:limit="param.pageSize" @pagination="getDocumentDataList" /> -->
<pagination v-show="total > 0" :total="total" v-model:page="param.pageNum" v-model:limit="param.pageSize" @pagination="documentList" />
</el-card>
</div>
</template>
<script lang="ts">
import { toRefs, reactive, ref, defineComponent, getCurrentInstance } from 'vue';
import { ElMessageBox, ElMessage, ElLoading } from 'element-plus';
import { useUserStoreHook } from '@/store/modules/user';
// 获取用户 store
const userStore = useUserStoreHook();
// 从 store 中获取项目列表和当前选中的项目
const currentProject = computed(() => userStore.selectedProject);
import { documentRecycleBinList, completionDataRecyclingStation } from '@/api/safety/documentSafetyMeeting';
import { useUserStoreHook } from '@/store/modules/user';
export default defineComponent({
name: 'index',
setup() {
const stores = useUserStoreHook();
const { proxy } = <any>getCurrentInstance();
const loading = ref(false);
const queryRef = ref();
@ -60,7 +65,7 @@ export default defineComponent({
tableData: [],
param: {
type: 2,
projectId: currentProject.value?.id
projectId: stores.selectedProject.goId
},
total: 0,
ids: [] //所选择的文件
@ -69,11 +74,9 @@ export default defineComponent({
const getDocumentDataList = () => {
loading.value = true;
documentRecycleBinList(state.param).then((res: any) => {
let list = res.rows ?? [];
let list = res.data.list ?? [];
state.tableData = list;
console.log('🚀 ~ documentRecycleBinList ~ state.tableData:', state.tableData);
state.total = res.total;
state.total = res.data.total;
loading.value = false;
});
};
@ -101,13 +104,16 @@ export default defineComponent({
text: '正在恢复中……',
background: 'rgba(0, 0, 0, 0.7)'
});
completionDataRecyclingStation(ids).then((res) => {
completionDataRecyclingStation({
ids,
type: 1
}).then((res) => {
loading.close();
if (res.code == 200) {
if (res.code == 0) {
getDocumentDataList();
ElMessage.success('操作成功');
} else {
ElMessage.error(res.msg);
ElMessage.error(res.message);
}
});
})

View File

@ -1,23 +1,35 @@
<template>
<div class="documentCompletion-data">
<el-tabs v-model="activeName" class="p-4" @tab-click="handleClick">
<div class="documentCompletion-data p-2">
<el-tabs v-model="activeName" class="demo-tabs" @tab-click="handleClick">
<el-tab-pane label="文件夹" name="first">
<el-button type="success" :disabled="toolStart" @click="handleFile(3)"
<el-card>
<el-row>
<el-col :span="2" class="colBlock">
<el-button
type="success"
v-auth="'api/v1/system/documentSafetyMeeting/safetyNewFolderData'"
:disabled="toolStart"
@click="handleFile(3)"
><el-icon><Plus /></el-icon>新建文件夹</el-button
>
<el-button type="primary" :disabled="toolStart" @click="handleFile(2)"
</el-col>
<el-col :span="2" class="colBlock">
<el-button type="primary" v-auth="'api/v1/system/documentSafetyMeeting/add'" :disabled="toolStart" @click="handleFile(2)"
><el-icon><Upload /></el-icon>上传文件</el-button
>
</el-col>
</el-row>
</el-card>
<el-card style="margin-top: 10px">
<div class="breadcrumb-img">
<el-breadcrumb>
<el-breadcrumb-item @click="onBreadcrumb(item)" v-for="(item, i) of breadcrumbList" :key="i">
<span title="点击打开文件夹" style="cursor: pointer">{{ item.fileName }}</span>
<span title="点击打开文件夹" style="cursor: pointer">{{ item.name }}</span>
</el-breadcrumb-item>
</el-breadcrumb>
<div class="tool-All">
<div v-if="!toolStart">
<el-button type="primary" v-hasPermi="['project:project:remove']" @click="onBatchAll">
<el-button type="primary" v-auth="'api/v1/system/documentSafetyMeeting/delete'" @click="onBatchAll">
<el-icon><Menu /></el-icon>批量操作</el-button
>
</div>
@ -38,12 +50,12 @@
<el-col :span="2" v-for="(item, i) of fileList" :key="i">
<div :class="{ file_style: true }">
<div @click="onNav(item)" title="点击打开文件" @contextmenu="onContextmenu($event, item, i)">
<img src="../../../assets/icons/svg/file1.png" v-if="item.fileType == '2'" alt="" />
<img src="../../../assets/icons/svg/file.png" v-else-if="item.fileType == '1'" alt="" />
<img src="@/assets/icons/file1.png" v-if="item.suffix == 'folder'" alt="" />
<img src="@/assets/icons/file.png" v-else-if="item.suffix == 'file'" alt="" />
<el-image
v-else-if="item.fileType == '3'"
v-else-if="item.suffix == 'image'"
style="width: 100%; height: 100%"
:src="item.filePath"
:src="item.filenPathCoding"
:zoom-rate="1.2"
:max-scale="7"
:min-scale="0.2"
@ -51,9 +63,9 @@
:preview-src-list="[item.filenPathCoding]"
fit="cover"
/>
<img :src="'/icon/' + item.fileType + '.png'" v-else />
<img :src="'/image/' + item.suffix.replace('.', '').toUpperCase() + '.png'" v-else />
</div>
<span @click="onFileName(item)" title="点击重命名">{{ item.fileName }}</span>
<span @click="onFileName(item)" title="点击重命名">{{ item.name }}</span>
<div :class="{ fileActive: toolStart }" v-if="toolStart" @click="onToolAll(item)"></div>
<div class="checkbox-box" v-if="toolStart">
<el-checkbox v-model="item.checkbox" size="large" />
@ -63,7 +75,7 @@
</el-row>
<el-empty :image-size="200" description="暂无文件" v-else />
<div class="right_box" id="right_box">
<div v-for="(item, i) of list" :key="i" @click="item.callback($event)">
<div v-for="(item, i) of list" :key="i" v-auth="item.auth" @click="item.callback($event)">
{{ item.name }}
</div>
</div>
@ -86,15 +98,12 @@ import {
documentCompletionEdit,
newFolder,
uniFileDownload
} from '@/api/safety/documentSafetyMeeting/index';
import { useUserStoreHook } from '@/store/modules/user';
} from '@/api/safety/documentSafetyMeeting';
// 获取用户 store
const userStore = useUserStoreHook();
// 从 store 中获取项目列表和当前选中的项目
const currentProject = computed(() => userStore.selectedProject);
// 回收站
import RecyclingStation from '@/views/safety/documentSafetyMeeting/RecyclingStation/index.vue';
import RecyclingStation from './RecyclingStation/index.vue';
import { useUserStoreHook } from '@/store/modules/user';
const stores = useUserStoreHook();
export default defineComponent({
name: 'index',
components: {
@ -106,29 +115,29 @@ export default defineComponent({
// 字典选项数据
const {} = proxy.useDict();
// 文件下载
const onExport = (event) => {
const onExport = (event, item) => {
event.stopPropagation();
// 文件下载 state.typeFile: 2、文件夹 1、文件
if (state.typeFile == '2') {
// 文件下载 state.typeFile: 1、文件夹 2、文件
if (state.typeFile == 1) {
window.open(state.relativePath, '_black');
} else {
uniFileDownload({ relativePath: state.relativePath, type: state.typeFile }).then((res) => {
if (res.code == 200) {
if (res.code == 0) {
window.open(res.data.Path, '_black');
}
});
}
};
// 文件删除
const onDeleteFile = (event) => {
const onDeleteFile = (event, item) => {
event.stopPropagation();
setDel([state.delId]);
};
const state = reactive({
fileList: [],
activeName: 'first',
breadcrumbList: [{ id: 0, fileName: '目录' }], //菜单列表
projectId: currentProject.value?.id,
breadcrumbList: [{ id: 0, name: '目录' }], //菜单列表
projectId: stores.selectedProject.goId,
parentPid: '0', //父级的id 默认为0
fileType: 0, //文件 或压缩文件
list: [
@ -156,7 +165,6 @@ export default defineComponent({
// 默认第一级 父级pid为0
getdocumentCompletionTreeStructure();
// 压缩文件上传
proxy.mittBus.on('bigUploader.uploadFileSuccess' + 1010, (res: any) => {
const { filename, totalSize, url, identifier, fileType } = res;
let arr = filename.split('.');
@ -174,10 +182,12 @@ export default defineComponent({
size: totalSize,
fileType: '.' + fileType1 //后缀名
},
file: ''
fileType: state.fileType,
pid: state.parentPid == 0 ? '' : state.parentPid,
projectId: state.projectId
};
documentCompletionAdd(obj).then((res: any) => {
if (res.code == 200) {
if (res.code == 0) {
ElMessage({
type: 'success',
message: '上传成功'
@ -202,16 +212,32 @@ export default defineComponent({
text: '正在查询文件……',
background: 'rgba(0, 0, 0, 0.7)'
});
documentCompletionTreeStructure({ projectId: currentProject.value?.id, pid: state.parentPid }).then((res: any) => {
documentCompletionTreeStructure({ projectId: state.projectId, pid: state.parentPid }).then((res: any) => {
loading.close();
if (res.code == 200) {
state.fileList = res.data || [];
if (res.code == 0) {
state.fileList = res.data.list || [];
if (state.fileList.length) {
state.fileList.map((item) => {
return {
...item,
checkbox: false
};
item.checkbox = false;
item.name = item.name + item.suffix;
item.suffix = item.suffix.slice(1).toUpperCase();
// 截取后缀
if (item.filenPathCoding.indexOf('.') != -1) {
let str = item.filenPathCoding.slice(item.filenPathCoding.indexOf('.') + 1);
if (state.imageType.includes(str)) {
// 图片文件格式
item.suffix = 'image';
} else {
if (!window['$ICONLIST'].includes(item.suffix)) {
item.suffix = 'file';
}
}
} else {
// 当没得后缀的时候 默认未文件夹
item.suffix = 'folder';
}
return item;
});
}
}
@ -227,8 +253,8 @@ export default defineComponent({
})
.then(({ value }) => {
// pid 父级
newFolder({ fileName: value, pid: state.parentPid == '0' ? '' : state.parentPid, projectId: state.projectId }).then((res: any) => {
if (res.code == 200) {
newFolder({ fileName: value, pid: state.parentPid == 0 ? '' : state.parentPid, projectId: state.projectId }).then((res: any) => {
if (res.code == 0) {
getdocumentCompletionTreeStructure();
ElMessage({
type: 'success',
@ -237,7 +263,7 @@ export default defineComponent({
} else {
ElMessage({
type: 'error',
message: res.data
message: res.message
});
}
});
@ -255,12 +281,12 @@ export default defineComponent({
// 图片格式 jpg、png、jpeg、
// word文档格式:docx、doc、pdf、xls、xlsx、pptx、ppt
// 其他全文件夹
if (item.fileType == '3') {
if (item.suffix == 'image') {
// 可以预览图片
return;
} else if (item.fileType == '2') {
} else if (item.suffix == 'folder') {
// 打开文件夹
state.parentPid = item.id;
state.parentPid = item.idStr;
state.breadcrumbList.push(item); //路径设置
state.fileList = [];
// 获取对应文件夹的数据
@ -280,7 +306,7 @@ export default defineComponent({
.then(({ value }) => {
// 确定
documentCompletionEdit({ id: item.id, name: value, type: item.type }).then((res: any) => {
if (res.code == 200) {
if (res.code == 0) {
item.name = value;
getdocumentCompletionTreeStructure();
ElMessage({
@ -305,9 +331,9 @@ export default defineComponent({
}
};
const onBreadcrumb = (item) => {
if (item.fileName == '目录') {
if (item.name == '目录') {
state.parentPid = '0';
state.breadcrumbList = [{ id: 0, fileName: '目录' }]; //菜单列表
state.breadcrumbList = [{ id: 0, name: '目录' }]; //菜单列表
// 最初目录
getdocumentCompletionTreeStructure();
} else {
@ -315,15 +341,15 @@ export default defineComponent({
let array = state.breadcrumbList;
for (let index = 0; index < array.length; index++) {
arr.push(array[index]);
if (array[index].fileName == item.fileName) {
if (array[index].name == item.name) {
break;
}
}
state.breadcrumbList = arr;
// 通过 当前点击的文件进行获取数据
// 重复点击不用再次获取
if (item.id == state.parentPid) return;
state.parentPid = item.id;
if (item.idStr == state.parentPid) return;
state.parentPid = item.idStr;
getdocumentCompletionTreeStructure();
}
};
@ -343,16 +369,14 @@ export default defineComponent({
type: 'warning'
})
.then(() => {
console.log(ids);
documentCompletionDelete(ids).then((res) => {
if (res.code == 200) {
documentCompletionDelete({ ids }).then((res) => {
if (res.code == 0) {
let box = document.getElementById('right_box');
box.style.display = 'none'; //显示div盒子
ElMessage.success('删除成功');
getdocumentCompletionTreeStructure();
} else {
ElMessage.error(res.msg);
ElMessage.error(res.message);
}
});
})
@ -380,7 +404,7 @@ export default defineComponent({
row.checkbox = !row.checkbox;
};
const onContextmenu = (event, item, i) => {
state.typeFile = item.fileType;
state.typeFile = item.type;
state.relativePath = item.filenPath;
state.delId = item.id;
let len = (100 / 12) * (i % 12) + 4 + '%';

View File

@ -27,6 +27,11 @@
</transition>
<el-card shadow="never">
<el-row :gutter="10" class="mb8">
<el-button type="danger" @click="handleDelete()" plain icon="Delete" :disabled="multiple">删除</el-button>
<right-toolbar v-model:showSearch="showSearch" @queryTable="getList"></right-toolbar>
</el-row>
<el-table v-loading="loading" :data="recognizeRecordList" @selection-change="handleSelectionChange">
<el-table-column type="selection" width="55" align="center" />
<el-table-column label="设备名称" align="center" prop="sxtName" />
@ -47,6 +52,11 @@
</el-table-column>
<el-table-column label="故障描述" align="center" prop="describe" />
<el-table-column label="创建时间" align="center" prop="createdAt" width="180"> </el-table-column>
<el-table-column label="操作" align="center" width="100">
<template #default="scope">
<el-button type="danger" link icon="Delete" @click="handleDelete(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>

View File

@ -24,6 +24,24 @@
</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" v-hasPermi="['safety:safetyInspection:add']"> 新增 </el-button>
</el-col>
<el-col :span="1.5">
<el-button type="danger" plain icon="Delete" :disabled="multiple" @click="handleDelete()" v-hasPermi="['safety:safetyInspection:remove']">
删除
</el-button>
</el-col>
<!-- <el-col :span="1.5">
<el-button type="warning" plain icon="Download" @click="handleExport" :disabled="multiple" v-hasPermi="['safety:safetyInspection:export']"
>导出
</el-button>
</el-col> -->
<right-toolbar v-model:showSearch="showSearch" @queryTable="getList"></right-toolbar>
</el-row>
</template>
<el-table v-loading="loading" :data="safetyInspectionList" @selection-change="handleSelectionChange">
<el-table-column type="selection" width="55" align="center" />
<el-table-column label="序号" type="index" width="60" align="center" />
@ -76,6 +94,9 @@
<el-button link type="primary" icon="View" @click="handleShowDialog(scope.row)" v-hasPermi="['safety:safetyInspection:query']">
详情
</el-button>
<el-button link type="danger" icon="Delete" @click="handleDelete(scope.row)" v-hasPermi="['safety:safetyInspection:remove']">
删除
</el-button>
</el-space>
</template>
</el-table-column>
@ -85,51 +106,35 @@
<!-- 添加或修改安全巡检工单对话框 -->
<el-dialog :title="dialog.title" v-model="dialog.visible" append-to-body>
<el-form ref="safetyInspectionFormRef" :model="form" :rules="rules" label-width="120px">
<el-form-item label="检查类型" prop="checkType">
<el-select v-model="form.checkType" placeholder="请选择检查类型">
<el-option v-for="dict in safety_inspection_check_type" :key="dict.value" :label="dict.label" :value="dict.value"></el-option>
<el-form-item label="检查类型" prop="studyType">
<el-select v-model="form.studyType" placeholder="请选择检查类型">
<el-option v-for="dict in safety_inspection_check_type" :key="dict.key" :label="dict.value" :value="dict.key"></el-option>
</el-select>
</el-form-item>
<el-form-item label="违章类型" prop="violationType">
<el-select v-model="form.violationType" placeholder="请选择违章类型">
<el-option v-for="dict in safety_inspection_violation_type" :key="dict.value" :label="dict.label" :value="dict.value"></el-option>
<el-form-item label="违章类型" prop="tourType">
<el-select v-model="form.tourType" placeholder="请选择违章类型">
<el-option v-for="dict in safety_inspection_violation_type" :key="dict.key" :label="dict.value" :value="dict.key"></el-option>
</el-select>
</el-form-item>
<el-form-item label="巡检结果" prop="inspectionResult">
<el-input v-model="form.inspectionResult" placeholder="请输入巡检结果" />
</el-form-item>
<el-form-item label="工单整改单位" prop="rectificationUnit">
<el-select v-model="form.rectificationUnit" placeholder="请选择整改单位类型">
<el-option v-for="dict in rectification_unit_type" :key="dict.value" :label="dict.label" :value="dict.value"></el-option>
<el-form-item label="整改人" prop="corrector">
<el-select v-model="form.corrector" placeholder="请选择整改人">
<el-option v-for="dict in foremanOpt" :key="dict.openid" :label="dict.userName" :value="dict.openid"></el-option>
</el-select>
</el-form-item>
<el-form-item label="整改班组" prop="teamId">
<el-select v-model="form.teamId" placeholder="选择整改班组">
<el-option v-for="item in teamOpt" :key="item.value" :label="item.label" :value="item.value" @click="changeForeman(item.value)" />
</el-select>
</el-form-item>
<el-form-item label="整改人" prop="correctorId">
<el-select v-model="form.correctorId" placeholder="请选择整改人" :disabled="!form.teamId">
<el-option v-for="item in foremanOpt" :key="item.value" :label="item.label" :value="item.value" />
</el-select>
</el-form-item>
<el-form-item label="问题隐患" prop="hiddenDanger">
<el-input v-model="form.hiddenDanger" type="textarea" placeholder="请输入内容" />
</el-form-item>
<el-form-item label="整改措施" prop="measure">
<el-input v-model="form.measure" type="textarea" placeholder="请输入内容" />
</el-form-item>
<el-form-item label="要求整改期限" prop="checkTime">
<el-date-picker clearable v-model="form.rectificationDeadline" type="date" value-format="YYYY-MM-DD" placeholder="选择要求整改期限" />
</el-form-item>
<el-form-item label="检查附件" prop="checkFile">
<file-upload v-model="form.checkFile" :file-size="20" :file-type="['doc', 'docx', 'pdf', 'png', 'jpg', 'jpeg']" />
<el-form-item label="要求整改期限" prop="replyDate">
<el-date-picker clearable v-model="form.replyDate" type="date" value-format="YYYY-MM-DD" placeholder="选择要求整改期限" />
</el-form-item>
<el-form-item label="整改附件" prop="rectificationFile">
<file-upload v-model="form.rectificationFile" :file-size="20" :file-type="['doc', 'docx', 'pdf', 'png', 'jpg', 'jpeg']" />
</el-form-item>
<el-form-item label="备注" prop="remark">
<el-input v-model="form.remark" type="textarea" placeholder="请输入内容" />
<file-upload
ref="uploadRef"
v-model="form.inspectionFile"
isGo
upload-url="/zm/api/v1/system/busHseManagement/add"
:auto-upload="false"
show-file-list
:data="form"
:accept="['doc', 'docx', 'pdf', 'png', 'jpg', 'jpeg']"
/>
</el-form-item>
</el-form>
<template #footer>
@ -159,6 +164,7 @@ import SafetyInspectionDetailDialog from '@/views/safety/safetyInspection/compon
import { listProjectTeamForeman } from '@/api/project/projectTeam';
import { foremanQuery, ProjectTeamForemanResp } from '@/api/project/projectTeam/types';
import { getDictData } from '@/api/project/goUser/index';
import { acquisitionOfCorrectivePersonnel } from '@/api/quality/qualityInspection';
const { proxy } = getCurrentInstance() as ComponentInternalInstance;
const { review_type } = toRefs<any>(proxy?.useDict('review_type', 'safety_inspection_type'));
@ -184,31 +190,13 @@ const dialog = reactive<DialogOption>({
title: ''
});
const initFormData: SafetyInspectionForm = {
id: undefined,
pid: undefined,
const initFormData: any = {
projectId: currentProject.value.goId,
checkType: undefined,
violationType: undefined,
inspectionResult: undefined,
teamId: undefined,
correctorId: undefined,
rectificationDeadline: undefined,
isReply: undefined,
replyDate: undefined,
status: undefined,
hiddenDanger: undefined,
measure: undefined,
review: undefined,
reviewType: undefined,
checkTime: undefined,
rectificationTime: undefined,
rectificationUnit: undefined,
reviewTime: undefined,
checkFile: undefined,
rectificationFile: undefined,
remark: undefined
studyType: undefined,
tourType: undefined,
corrector: undefined,
teamName: 'undefined'
};
const data = reactive<PageData<SafetyInspectionForm, SafetyInspectionQuery>>({
form: { ...initFormData },
@ -303,20 +291,42 @@ const handleSelectionChange = (selection: SafetyInspectionVO[]) => {
single.value = selection.length != 1;
multiple.value = !selection.length;
};
//删除
const handleDelete = async (row?: SafetyInspectionVO) => {
const _ids = row?.id || ids.value;
await proxy?.$modal.confirm('是否确认删除安全巡检工单编号为"' + _ids + '"的数据项?').finally(() => (loading.value = false));
await delSafetyInspection(_ids);
proxy?.$modal.msgSuccess('删除成功');
await getList();
};
/** 新增按钮操作 */
const handleAdd = async () => {
reset();
await getPeople();
dialog.visible = true;
dialog.title = '添加安全巡检工单';
};
const getPeople = async () => {
await acquisitionOfCorrectivePersonnel(currentProject.value?.goId).then((res) => {
foremanOpt.value = res.data.list;
});
};
/** 提交按钮 */
const uploadRef = ref(null);
const submitForm = () => {
safetyInspectionFormRef.value?.validate(async (valid: boolean) => {
if (valid) {
buttonLoading.value = true;
form.value.projectId = currentProject.value?.id;
if (form.value.id) {
await updateSafetyInspection(form.value).finally(() => (buttonLoading.value = false));
} else {
await addSafetyInspection(form.value).finally(() => (buttonLoading.value = false));
}
uploadRef.value.submitUpload().then((res) => {
if (res != 'noFile') {
proxy?.$modal.msgSuccess('操作成功');
dialog.visible = false;
await getList();
getList();
buttonLoading.value = false;
}
});
}
});
};

View File

@ -2,52 +2,63 @@
<el-card v-loading="loading">
<h2 style="text-align: center; margin-top: 5px; font-weight: bold">安全日志</h2>
<el-row>
<el-col :span="12" style="text-align: left">记录人{{ safetyLogDetail?.creator?.name }}</el-col>
<el-col :span="12" style="text-align: right">记录时间{{ safetyLogDetail?.createTime }}</el-col>
<el-col :span="12" style="text-align: left">记录人{{ safetyLogDetail?.fill }}</el-col>
<el-col :span="12" style="text-align: right">记录时间{{ safetyLogDetail?.createdAt }}</el-col>
</el-row>
<el-descriptions :column="3" border style="margin-top: 8px">
<el-descriptions-item label-align="center" width="160px" label="项目名称" :span="3">{{ currentProject?.name }} </el-descriptions-item>
<el-descriptions-item label-align="center" label="发生日期">{{ safetyLogDetail?.dateOfOccurrence }} </el-descriptions-item>
<el-descriptions-item label-align="center" label="气温">
<el-descriptions-item label-align="center" width="160px" label="项目名称" :span="3">{{ safetyLogDetail?.projectName }} </el-descriptions-item>
<el-descriptions-item label-align="center" label="发生日期" :span="safetyLogDetail?.fileList ? 3 : 1"
>{{ safetyLogDetail?.dateOfOccurrence }}
</el-descriptions-item>
<el-descriptions-item label-align="center" label="气温" v-if="!safetyLogDetail?.fileList">
<span>最高{{ safetyLogDetail?.airTemperatureMax }}</span>
<span>最低{{ safetyLogDetail?.airTemperatureMin }}</span>
</el-descriptions-item>
<el-descriptions-item label-align="center" label="气候">
<dict-tag :value="safetyLogDetail?.weather" :options="weather_type" />
<el-descriptions-item label-align="center" label="气候" v-if="!safetyLogDetail?.fileList">
{{ safetyLogDetail?.climateName }}
</el-descriptions-item>
<el-descriptions-item label-align="center" label="工程施工部位及施工进展情况" :span="3">
<el-descriptions-item label-align="center" label="工程施工部位及施工进展情况" :span="3" v-if="!safetyLogDetail?.fileList">
{{ safetyLogDetail?.progress }}
</el-descriptions-item>
<el-descriptions-item label-align="center" label="当日主要危险性项目作业内容" :span="3">
<el-descriptions-item label-align="center" label="当日主要危险性项目作业内容" :span="3" v-if="!safetyLogDetail?.fileList">
{{ safetyLogDetail?.jobContent }}
</el-descriptions-item>
<el-descriptions-item label-align="center" label="施工项目安全教育与安全交底情况" :span="3">
{{ safetyLogDetail?.discloseCondition }}
<el-descriptions-item label-align="center" label="施工项目安全教育与安全交底情况" :span="3" v-if="!safetyLogDetail?.fileList">
{{ safetyLogDetail?.discloseTheFacts }}
</el-descriptions-item>
<el-descriptions-item label-align="center" label="施工作业队伍班前施工安全活动情况" :span="3">
{{ safetyLogDetail?.activityCondition }}
<el-descriptions-item label-align="center" label="施工作业队伍班前施工安全活动情况" :span="3" v-if="!safetyLogDetail?.fileList">
{{ safetyLogDetail?.progressOfActivity }}
</el-descriptions-item>
<el-descriptions-item label-align="center" label="现场施工安全巡视与检查情况" :span="3">
{{ safetyLogDetail?.examineCondition }}
<el-descriptions-item label-align="center" label="现场施工安全巡视与检查情况" :span="3" v-if="!safetyLogDetail?.fileList">
{{ safetyLogDetail?.examine }}
</el-descriptions-item>
<el-descriptions-item label-align="center" label="季节施工防寒、防暑等措施实施情况" :span="3">
{{ safetyLogDetail?.implementCondition }}
<el-descriptions-item label-align="center" label="季节施工防寒、防暑等措施实施情况" :span="3" v-if="!safetyLogDetail?.fileList">
{{ safetyLogDetail?.implementation }}
</el-descriptions-item>
<el-descriptions-item label-align="center" label="监理通知有关部门安全检查情况" :span="3">
{{ safetyLogDetail?.safetyInspectionCondition }}
<el-descriptions-item label-align="center" label="监理通知有关部门安全检查情况" :span="3" v-if="!safetyLogDetail?.fileList">
{{ safetyLogDetail?.safetyInspectionSituation }}
</el-descriptions-item>
<el-descriptions-item label-align="center" label="停工、加班情况" :span="3">{{ safetyLogDetail?.stoppageOrOvertime }} </el-descriptions-item>
<el-descriptions-item label-align="center" label="其他应记录的安全与文明施工事项" :span="3">
{{ safetyLogDetail?.otherCondition }}
<el-descriptions-item label-align="center" label="停工、加班情况" :span="3" v-if="!safetyLogDetail?.fileList"
>{{ safetyLogDetail?.stoppageOrOvertime }}
</el-descriptions-item>
<el-descriptions-item label-align="center" label="附件" :span="3">
<el-descriptions-item label-align="center" label="其他应记录的安全与文明施工事项" :span="3" v-if="!safetyLogDetail?.fileList">
{{ safetyLogDetail?.otherRecords }}
</el-descriptions-item>
<el-descriptions-item label-align="center" label="附件" :span="3" v-if="safetyLogDetail?.fileList">
<el-space direction="vertical">
<el-link v-for="item in fileList" :key="item.ossId" :href="`${item.url}`" type="primary" :underline="false" target="_blank">
<span> {{ item.originalName }} </span>
<el-link
v-for="item in safetyLogDetail?.fileList"
:key="item.id"
:href="`${BASE_URL}${item.path}`"
type="primary"
:underline="false"
target="_blank"
>
<span> {{ item.name }} </span>
</el-link>
</el-space>
</el-descriptions-item>
<el-descriptions-item label-align="center" label="备注" :span="3">{{ safetyLogDetail?.remark }} </el-descriptions-item>
<!-- <el-descriptions-item label-align="center" label="备注" :span="3">{{ safetyLogDetail?.remark }} </el-descriptions-item> -->
</el-descriptions>
</el-card>
</template>
@ -62,6 +73,8 @@ import { OssVO } from '@/api/system/oss/types';
interface Props {
safetyLogId?: string | number;
}
const BASE_URL = import.meta.env.VITE_APP_BASE_API_GO;
console.log('🚀 ~ BASE_URL:', BASE_URL);
const { proxy } = getCurrentInstance() as ComponentInternalInstance;
const { weather_type } = toRefs<any>(proxy?.useDict('weather_type'));
@ -77,7 +90,7 @@ const fileList = ref<Array<OssVO>>([]);
const get = async () => {
loading.value = true;
const res = await getSafetyLog(props.safetyLogId);
if (res.data && res.code === 200) {
if (res.data && res.code === 0) {
safetyLogDetail.value = res.data;
if (res.data.fileId) {
const fileRes = await listByIds(res.data.fileId.split(','));

View File

@ -19,6 +19,12 @@
<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" v-hasPermi="['safety:safetyLog:add']">新增 </el-button>
</el-col>
<el-col :span="1.5">
<el-button type="primary" plain icon="Upload" @click="handleAdd('file')" v-hasPermi="['safety:safetyLog:add']">上传附件 </el-button>
</el-col>
<right-toolbar v-model:showSearch="showSearch" @queryTable="getList"></right-toolbar>
</el-row>
</template>
@ -35,9 +41,8 @@
<span>{{ parseTime(scope.row.dateOfOccurrence, '{y}-{m}-{d}') }}</span>
</template>
</el-table-column>
<el-table-column label="录入时间" align="center" prop="createTime" />
<el-table-column label="录入人" align="center" prop="creatorName" />
<el-table-column label="备注" align="center" prop="remark" />
<el-table-column label="录入时间" align="center" prop="updatedAt" />
<el-table-column label="录入人" align="center" prop="fill" />
<el-table-column label="操作" align="center" class-name="small-padding fixed-width">
<template #default="scope">
<el-space>
@ -55,54 +60,115 @@
</el-card>
<!-- 添加或修改安全日志对话框 -->
<el-dialog :title="dialog.title" v-model="dialog.visible" width="950px" append-to-body>
<el-form ref="safetyLogFormRef" :model="form" :rules="rules" label-width="250px">
<el-form ref="safetyLogFormRef" :model="form" :rules="rules" label-width="210px">
<el-form-item label="发生日期" prop="dateOfOccurrence">
<el-date-picker clearable v-model="form.dateOfOccurrence" type="date" value-format="YYYY-MM-DD" placeholder="请选择发生日期">
</el-date-picker>
<el-date-picker
clearable
style="width: 200px"
v-model="form.dateOfOccurrence"
format="YYYY-MM-DD"
value-format="YYYY-MM-DD"
type="date"
placeholder="选择发生日期"
></el-date-picker>
</el-form-item>
<el-form-item label="最高气温" prop="airTemperatureMax">
<el-input v-model="form.airTemperatureMax" placeholder="请输入最高气温" />
<el-form-item label="最高气温" prop="airTemperatureMax" v-if="!fileStatus">
<el-input v-model="form.airTemperatureMax" placeholder="请输入最高气温" type="number">
<template #append></template>
</el-input>
</el-form-item>
<el-form-item label="最低气温" prop="airTemperatureMin">
<el-input v-model="form.airTemperatureMin" placeholder="请输入最低气温" />
<el-form-item label="最低气温" prop="airTemperatureMin" v-if="!fileStatus">
<el-input v-model="form.airTemperatureMin" :min="-275" :max="form.airTemperatureMax" placeholder="请输入最低气温" type="number">
<template #append></template>
</el-input>
</el-form-item>
<el-form-item label="气候" prop="weather">
<el-select v-model="form.weather" placeholder="请选择气候">
<el-form-item label="气候" prop="climate" v-if="!fileStatus">
<el-select v-model="form.climate" placeholder="请选择气候">
<el-option v-for="dict in weather_type" :key="dict.value" :label="dict.label" :value="dict.value"></el-option>
</el-select>
</el-form-item>
<el-form-item label="工程施工部位及施工进展情况" prop="progress">
<el-input v-model="form.progress" type="textarea" placeholder="请输入内容" />
<el-form-item label="工程施工部位及施工进展情况" prop="progress" v-if="!fileStatus">
<el-input v-model="form.progress" placeholder="请输入工程施工部位及施工进展情况" autosize maxlength="300" show-word-limit type="textarea" />
</el-form-item>
<el-form-item label="当日主要危险性项目作业内容">
<editor v-model="form.jobContent" :min-height="192" />
<el-form-item label="当日主要危险性项目作业内容" prop="jobContent" v-if="!fileStatus">
<el-input
v-model="form.jobContent"
placeholder="请输入当日主要危险性项目作业内容"
autosize
maxlength="300"
show-word-limit
type="textarea"
/>
</el-form-item>
<el-form-item label="施工项目安全教育与安全交底情况">
<editor v-model="form.discloseCondition" :min-height="192" />
<el-form-item label="施工项目安全教育与安全交底情况" prop="discloseTheFacts" v-if="!fileStatus">
<el-input
v-model="form.discloseTheFacts"
placeholder="请输入施工项目安全教育与安全交底情况"
autosize
maxlength="300"
show-word-limit
type="textarea"
/>
</el-form-item>
<el-form-item label="施工作业队伍班前施工安全活动情况">
<editor v-model="form.activityCondition" :min-height="192" />
<el-form-item label="施工作业队伍班前施工安全活动情况" prop="progressOfActivity" v-if="!fileStatus">
<el-input
v-model="form.progressOfActivity"
placeholder="请输入施工作业队伍班前施工安全活动情况"
autosize
maxlength="300"
show-word-limit
type="textarea"
/>
</el-form-item>
<el-form-item label="现场施工安全巡视与检查情况">
<editor v-model="form.examineCondition" :min-height="192" />
<el-form-item label="现场施工安全巡视与检查情况" prop="examine" v-if="!fileStatus">
<el-input v-model="form.examine" placeholder="请输入现场施工安全巡视与检查情况" autosize maxlength="300" show-word-limit type="textarea" />
</el-form-item>
<el-form-item label="季节施工防寒、防等措施实施情况">
<editor v-model="form.implementCondition" :min-height="192" />
<el-form-item label="季节施工防寒、防等措施实施情况" prop="implementation" v-if="!fileStatus">
<el-input
v-model="form.implementation"
placeholder="请输入季节施工防寒、防署等措施实施情况"
autosize
maxlength="300"
show-word-limit
type="textarea"
/>
</el-form-item>
<el-form-item label="监理通知有关部门安全检查情况">
<editor v-model="form.safetyInspectionCondition" :min-height="192" />
<el-form-item label="监理通知有关部门安全检查情况" prop="safetyInspectionSituation" v-if="!fileStatus">
<el-input
v-model="form.safetyInspectionSituation"
placeholder="请输入监理通知或有关部门安全检查情况"
autosize
maxlength="300"
show-word-limit
type="textarea"
/>
</el-form-item>
<el-form-item label="停工、加班情况">
<editor v-model="form.stoppageOrOvertime" :min-height="192" />
<el-form-item label="停工、加班情况" prop="stoppageOrOvertime" v-if="!fileStatus">
<el-input v-model="form.stoppageOrOvertime" placeholder="请输入停工、加班情况" autosize maxlength="300" show-word-limit type="textarea" />
</el-form-item>
<el-form-item label="其他应记录的安全与文明施工事项">
<editor v-model="form.otherCondition" :min-height="192" />
<el-form-item label="其他应记录的安全与文明施工事项" prop="otherRecords" v-if="!fileStatus">
<el-input
v-model="form.otherRecords"
placeholder="请输入其他应记录的安全与文明施工事项"
autosize
maxlength="300"
show-word-limit
type="textarea"
/>
</el-form-item>
<el-form-item label="附件" prop="fileId">
<file-upload v-model="form.fileId" />
<el-form-item label="文件上传" v-if="fileStatus">
<file-upload
v-model="form.file"
:auto-upload="false"
ref="uploadRef"
upload-url="/zm/api/v1/system/busHseSecurityLog/addFile"
isGo
:data="form"
show-file-list
/>
</el-form-item>
<el-form-item label="备注" prop="remark">
<el-input v-model="form.remark" type="textarea" placeholder="请输入内容" />
<el-input type="textarea" v-model="form.remark" maxlength="300" placeholder="请输入备注" />
</el-form-item>
</el-form>
<template #footer>
@ -112,6 +178,7 @@
</div>
</template>
</el-dialog>
<el-dialog title="安全日志详情" v-model="showDetailDialog">
<safety-log-detail-dialog :safety-log-id="currentSafetyLogId" />
</el-dialog>
@ -129,6 +196,7 @@ import SafetyLogDetailDialog from '@/views/safety/safetyLog/component/SafetyLogD
const { proxy } = getCurrentInstance() as ComponentInternalInstance;
const { weather_type } = toRefs<any>(proxy?.useDict('weather_type'));
// 获取用户 store
const userStore = useUserStoreHook();
// 从 store 中获取项目列表和当前选中的项目
@ -149,9 +217,10 @@ const dialog = reactive<DialogOption>({
title: ''
});
const initFormData: SafetyLogForm = {
const initFormData: any = {
id: undefined,
projectId: currentProject.value.goId,
file: undefined,
dateOfOccurrence: undefined,
airTemperatureMax: undefined,
airTemperatureMin: undefined,
@ -248,13 +317,16 @@ const handleShowDialog = (row?: SafetyLogVO) => {
showDetailDialog.value = true;
};
/** 提交按钮 */
const uploadRef = ref();
const submitForm = () => {
safetyLogFormRef.value?.validate(async (valid: boolean) => {
if (valid) {
buttonLoading.value = true;
form.value.projectId = currentProject.value?.id;
if (form.value.id) {
await updateSafetyLog(form.value).finally(() => (buttonLoading.value = false));
form.value.projectId = currentProject.value?.goId;
if (fileStatus.value) {
await uploadRef.value.submitUpload().finally((res) => {
buttonLoading.value = false;
});
} else {
await addSafetyLog(form.value).finally(() => (buttonLoading.value = false));
}
@ -274,6 +346,25 @@ const handleDelete = async (row?: SafetyLogVO) => {
await getList();
};
/** 新增按钮操作 */
const fileStatus = ref<boolean>(false);
const handleAdd = (type?: string) => {
reset();
if (weather_type.value.length == 5) {
weather_type.value = weather_type.value.filter((item) => item.value != '3');
weather_type.value[2].value = '3';
}
console.log('🚀 ~ handleAdd ~ type:', type);
if (type == 'file') {
fileStatus.value = true;
} else {
fileStatus.value = false;
}
dialog.visible = true;
dialog.title = '添加安全日志';
};
//监听项目id刷新数据
const listeningProject = watch(
() => currentProject.value.goId,

View File

@ -43,9 +43,6 @@
批量删除
</el-button>
</el-col>
<el-col :span="1.5">
<el-button type="warning" plain icon="Download" @click="handleExport" v-hasPermi="['safety:safetyWeeklyReport:export']">导出 </el-button>
</el-col>
<right-toolbar v-model:showSearch="showSearch" @queryTable="getList"></right-toolbar>
</el-row>
</template>
@ -59,8 +56,8 @@
<span>{{ parseTime(scope.row.scope, '{y}-{m}-{d}') }} {{ parseTime(scope.row.scopeEnd, '{y}-{m}-{d}') }}</span>
</template>
</el-table-column>
<el-table-column label="创建时间" align="center" prop="createTime" />
<el-table-column label="备注" align="center" prop="remark" />
<el-table-column label="创建时间" align="center" prop="createdAt" />
<!-- <el-table-column label="备注" align="center" prop="remark" /> -->
<el-table-column label="操作" align="center" class-name="small-padding fixed-width">
<template #default="scope">
<el-space>
@ -80,20 +77,15 @@
<!-- 添加或修改安全周报对话框 -->
<el-dialog :title="dialog.title" v-model="dialog.visible" width="500px" append-to-body>
<el-form ref="safetyWeeklyReportFormRef" :model="form" :rules="rules" label-width="120px">
<el-form-item label="周期" prop="week">
<el-input v-model="form.week" placeholder="请输入周期" />
</el-form-item>
<el-form-item label="周期开始范围" prop="scope">
<el-date-picker clearable v-model="form.scope" type="date" value-format="YYYY-MM-DD" placeholder="请选择周期范围" />
</el-form-item>
<el-form-item label="周期范围结束" prop="scopeEnd">
<el-date-picker clearable v-model="form.scopeEnd" type="date" value-format="YYYY-MM-DD" placeholder="请选择周期范围结束" />
</el-form-item>
<el-form-item label="文件位置" prop="path">
<div><file-upload v-model="form.path" :file-size="20" :limit="1" :file-type="['doc', 'docx']" /></div>
</el-form-item>
<el-form-item label="备注" prop="remark">
<el-input v-model="form.remark" type="textarea" placeholder="请输入内容" />
<el-form-item label="周期范围" prop="timeRange">
<el-date-picker
v-model="form.timeRange"
type="daterange"
range-separator=""
format="YYYY-MM-DD"
start-placeholder="开始时间"
end-placeholder="结束时间"
/>
</el-form-item>
</el-form>
<template #footer>
@ -116,6 +108,7 @@ import {
} from '@/api/safety/safetyWeeklyReport';
import { SafetyWeeklyReportForm, SafetyWeeklyReportQuery, SafetyWeeklyReportVO } from '@/api/safety/safetyWeeklyReport/types';
import { useUserStoreHook } from '@/store/modules/user';
import { dayjs } from 'element-plus';
const { proxy } = getCurrentInstance() as ComponentInternalInstance;
@ -142,7 +135,7 @@ const dialog = reactive<DialogOption>({
const initFormData: SafetyWeeklyReportForm = {
id: undefined,
projectId: currentProject.value?.id,
projectId: currentProject.value?.goId,
week: undefined,
scope: undefined,
scopeEnd: undefined,
@ -155,7 +148,7 @@ const data = reactive<PageData<SafetyWeeklyReportForm, SafetyWeeklyReportQuery>>
pageNum: 1,
pageSize: 10,
id: undefined,
projectId: currentProject.value?.id,
projectId: currentProject.value?.goId,
week: undefined,
scopeDate: undefined,
remark: undefined,
@ -163,7 +156,8 @@ const data = reactive<PageData<SafetyWeeklyReportForm, SafetyWeeklyReportQuery>>
},
rules: {
id: [{ required: true, message: '主键id不能为空', trigger: 'blur' }],
projectId: [{ required: true, message: '项目id不能为空', trigger: 'blur' }]
projectId: [{ required: true, message: '项目id不能为空', trigger: 'blur' }],
timeRange: [{ required: true, message: '周期范围不能为空', trigger: 'blur' }]
}
});
@ -173,8 +167,8 @@ const { queryParams, form, rules } = toRefs(data);
const getList = async () => {
loading.value = true;
const res = await listSafetyWeeklyReport(queryParams.value);
safetyWeeklyReportList.value = res.rows;
total.value = res.total;
safetyWeeklyReportList.value = res.data.list;
total.value = res.data.total;
loading.value = false;
};
@ -218,10 +212,11 @@ const handleAdd = () => {
/** 修改按钮操作 */
const handleUpdate = async (row?: SafetyWeeklyReportVO) => {
return;
reset();
const _id = row?.id || ids.value[0];
const res = await getSafetyWeeklyReport(_id);
Object.assign(form.value, res.data);
// const res = await getSafetyWeeklyReport(_id);
// Object.assign(form.value, res.data);
dialog.visible = true;
dialog.title = '修改安全周报';
};
@ -231,10 +226,11 @@ const submitForm = () => {
safetyWeeklyReportFormRef.value?.validate(async (valid: boolean) => {
if (valid) {
buttonLoading.value = true;
form.value.projectId = currentProject.value?.id;
form.value.projectId = currentProject.value?.goId;
if (form.value.id) {
await updateSafetyWeeklyReport(form.value).finally(() => (buttonLoading.value = false));
} else {
form.value.timeRange = form.value.timeRange.map((d) => dayjs(d).format('YYYY-MM-DD')).join(',');
await addSafetyWeeklyReport(form.value).finally(() => (buttonLoading.value = false));
}
proxy?.$modal.msgSuccess('操作成功');
@ -266,7 +262,7 @@ const handleExport = () => {
//监听项目id刷新数据
const listeningProject = watch(
() => currentProject.value?.id,
() => currentProject.value?.goId,
(nid, oid) => {
queryParams.value.projectId = nid;
form.value.projectId = nid;

View File

@ -46,6 +46,9 @@
<el-button link type="primary" icon="View" @click="handleShowDrawer(scope.row)" v-hasPermi="['safety:teamMeeting:query']">
详情
</el-button>
<el-button link type="danger" icon="Delete" @click="handleDelete(scope.row)" v-hasPermi="['safety:teamMeeting:remove']">
删除
</el-button>
</el-space>
</template>
</el-table-column>
@ -192,6 +195,14 @@ const handleAdd = () => {
dialog.visible = true;
dialog.title = '添加站班会';
};
/** 删除按钮操作 */
const handleDelete = async (row: TeamMeetingVO) => {
proxy?.$modal.confirm('确定删除选中数据吗?').then(async () => {
await delTeamMeeting(row.id);
proxy?.$modal.msgSuccess('删除成功');
await getList();
});
};
/** 展开站班会详情抽屉操作 */
const showDetailDrawer = ref<boolean>(false);

View File

@ -7,8 +7,8 @@
<el-form ref="formRef" size="large" :model="formData" :rules="rules" label-width="90px">
<el-row>
<el-col :span="12">
<el-form-item label="违章等级" prop="violationLevel">
<el-input v-model="formData.violationLevel" placeholder="请输入违章等级" />
<el-form-item label="违章等级" prop="grade">
<el-input v-model="formData.grade" placeholder="请输入违章等级" />
</el-form-item>
</el-col>
<el-col :span="12">
@ -17,43 +17,23 @@
</el-form-item>
</el-col>
<el-col :span="24">
<el-form-item label="风险等级" prop="riskType">
<el-select v-model="formData.riskType" placeholder="请选择风险等级">
<el-option v-for="dict in risxList" :key="dict.value" :label="dict.label" :value="dict.value" />
</el-select>
</el-form-item>
</el-col>
<el-col :span="24" :offset="0" prop="dept">
<el-form-item label="部门">
<el-cascader
:options="postListAll"
v-model="formData.dept"
clearable
filterable
:show-all-levels="false"
placeholder="请选择部门"
:props="{ expandTrigger: 'hover', checkStrictly: true, value: 'id', emitPath: false, multiple: true }"
@change="changeDept"
>
</el-cascader>
</el-form-item>
</el-col>
<el-col :span="24">
<el-form-item label="岗位" prop="postIdList">
<el-select v-model="formData.postIdList" placeholder="请选择岗位" multiple :disabled="!formData.dept">
<el-option
v-for="dict in formData.postWorkList"
:key="dict.postId"
:label="dict.deptName + '/' + dict.postName"
:value="dict.postId"
/>
<el-form-item label="风险等级" prop="risx">
<el-select v-model="formData.risx" placeholder="请选择风险等级">
<el-option v-for="dict in risxList" :key="dict.key" :label="dict.value" :value="dict.key" />
</el-select>
</el-form-item>
</el-col>
<el-col :span="24">
<el-form-item label="违章类型" prop="violationType">
<el-select v-model="formData.violationType" placeholder="请选择违章类型" multiple>
<el-option v-for="dict in tourTypeOptions" :key="dict.value" :label="dict.label" :value="dict.value" />
<el-form-item label="岗位" prop="posts">
<el-select v-model="formData.posts" placeholder="请选择岗位" multiple>
<el-option v-for="dict in postListAll" :key="dict.postId" :label="dict.postName" :value="dict.postId" />
</el-select>
</el-form-item>
</el-col>
<el-col :span="24">
<el-form-item label="违章类型" prop="tourType">
<el-select v-model="formData.tourType" placeholder="请选择违章类型" multiple>
<el-option v-for="dict in tourTypeOptions" :key="dict.key" :label="dict.value" :value="dict.key" />
</el-select>
</el-form-item>
</el-col>
@ -166,16 +146,14 @@ const resetForm = () => {
// 提交操作
const onSubmit = () => {
if (!formRef.value) return;
formRef.value.validate((valid: boolean) => {
if (valid) {
loading.value = true;
const param = JSON.parse(JSON.stringify(formData));
if (param.violationType?.length) {
param.violationType = param.violationType.join(',');
if (param.tourType?.length) {
param.tourType = param.tourType.join(',');
}
addViolationLevel(param)
.then(() => {
ElMessage.success('添加成功');
@ -189,32 +167,6 @@ const onSubmit = () => {
});
};
const changeDept = (val: any) => {
formData.postWorkList = getPostVoListByIds(props.postListAll, val);
formData.postIdList = [];
console.log(formData.postWorkList, val);
};
function getPostVoListByIds(tree: any[], idList: (string | number)[]): any[] {
const idSet = new Set(idList.map(String)); // 用于快速匹配 ID统一为字符串比较
const result: any[] = [];
function dfs(nodes: any[]) {
for (const node of nodes) {
if (idSet.has(String(node.id))) {
result.push(...(node.postVoList || []));
}
if (node.children && node.children.length > 0) {
dfs(node.children);
}
}
}
dfs(tree);
return result;
}
defineExpose({
openDialog,
closeDialog

View File

@ -1,16 +1,14 @@
<template>
<div class="system-busViolationLevel-edit">
<el-dialog v-model="isShowDialog" width="550px" :close-on-click-modal="false" :destroy-on-close="true" custom-class="busViolationLevel_edit">
<el-dialog v-model="isShowDialog" width="550px" :close-on-click-modal="false" :destroy-on-close="true">
<template #header>
<div v-drag="['.system-busViolationLevel-edit .el-dialog', '.system-busViolationLevel-edit .el-dialog__header']">
{{ (!formData.id || formData.id == 0 ? '添加' : '修改') + '违章等级' }}
</div>
<div v-drag="['.system-busViolationLevel-add .el-dialog', '.system-busViolationLevel-add .el-dialog__header']">修改违章等级</div>
</template>
<el-form ref="formRef" size="large" :model="formData" :rules="rules" label-width="90px">
<el-row>
<el-col :span="12">
<el-form-item label="违章等级" prop="violationLevel">
<el-input v-model="formData.violationLevel" placeholder="请输入违章等级" />
<el-form-item label="违章等级" prop="grade">
<el-input v-model="formData.grade" placeholder="请输入违章等级" />
</el-form-item>
</el-col>
<el-col :span="12">
@ -19,43 +17,23 @@
</el-form-item>
</el-col>
<el-col :span="24">
<el-form-item label="风险等级" prop="riskType">
<el-select v-model="formData.riskType" placeholder="请选择风险等级">
<el-option v-for="dict in risxList" :key="dict.value" :label="dict.label" :value="dict.value" />
</el-select>
</el-form-item>
</el-col>
<el-col :span="24" :offset="0" prop="dept">
<el-form-item label="部门">
<el-cascader
:options="postListAll"
v-model="formData.dept"
clearable
filterable
:show-all-levels="false"
placeholder="请选择部门"
:props="{ expandTrigger: 'hover', checkStrictly: true, value: 'id', emitPath: false, multiple: true }"
@change="changeDept"
>
</el-cascader>
</el-form-item>
</el-col>
<el-col :span="24">
<el-form-item label="岗位" prop="postIdList">
<el-select v-model="formData.postIdList" placeholder="请选择岗位" multiple :disabled="!formData.dept">
<el-option
v-for="dict in formData.postWorkList"
:key="dict.postId"
:label="dict.deptName + '/' + dict.postName"
:value="dict.postId"
/>
<el-form-item label="风险等级" prop="risx">
<el-select v-model="formData.risx" placeholder="请选择风险等级">
<el-option v-for="dict in risxList" :key="dict.key" :label="dict.value" :value="dict.key" />
</el-select>
</el-form-item>
</el-col>
<el-col :span="24">
<el-form-item label="违章类型" prop="violationType">
<el-select v-model="formData.violationType" placeholder="请选择违章类型" multiple>
<el-option v-for="dict in tourTypeOptions" :key="dict.value" :label="dict.label" :value="dict.value" />
<el-form-item label="岗位" prop="posts">
<el-select v-model="formData.posts" placeholder="请选择岗位" multiple>
<el-option v-for="dict in postListAll" :key="dict.postId" :label="dict.postName" :value="dict.postId" />
</el-select>
</el-form-item>
</el-col>
<el-col :span="24">
<el-form-item label="违章类型" prop="tourType">
<el-select v-model="formData.tourType" placeholder="请选择违章类型" multiple>
<el-option v-for="dict in tourTypeOptions" :key="dict.key" :label="dict.value" :value="dict.key" />
</el-select>
</el-form-item>
</el-col>
@ -138,11 +116,10 @@ const openDialog = (row?: ViolationLevelVO) => {
getViolationLevel(row.id as string).then((res) => {
loadingInstance.close();
const data = res.data;
data.postIdList = (data.postList || []).map((item: any) => item.postId);
data.violationType = data.violationType ? (data.violationType as string).split(',') : [];
formData.dept = (data.postList || []).map((item: any) => item.deptId);
formData.postWorkList = getPostVoListByIds(props.postListAll, formData.dept);
data.posts = (data.postEntity || []).map((item: any) => item.postId);
data.tourType = data.tourType ? (data.tourType as string).split(',') : [];
Object.assign(formData, data);
console.log(formData);
});
});
}
@ -167,11 +144,8 @@ const onSubmit = () => {
loading.value = true;
const param = JSON.parse(JSON.stringify(formData));
if (Array.isArray(param.violationType)) {
param.violationType = param.violationType.join(',');
}
if (Array.isArray(param.riskType)) {
param.riskType = param.riskType.join(',');
if (Array.isArray(param.tourType)) {
param.tourType = param.tourType.join(',');
}
const action = !param.id || param.id === 0 ? addViolationLevel : updateViolationLevel;

View File

@ -23,6 +23,23 @@
</el-col>
</el-row>
</el-form>
<el-row :gutter="10" class="mb8">
<el-col :span="1.5">
<el-button type="primary" @click="handleAdd" v-auth="'api/v1/system/busViolationLevel/add'">
<el-icon><Plus /></el-icon>新增
</el-button>
</el-col>
<el-col :span="1.5">
<el-button type="success" :disabled="single" @click="handleUpdate(null)" v-auth="'api/v1/system/busViolationLevel/edit'">
<el-icon><Edit /></el-icon>修改
</el-button>
</el-col>
<el-col :span="1.5">
<el-button type="danger" :disabled="multiple" @click="handleDelete(null)" v-auth="'api/v1/system/busViolationLevel/delete'">
<el-icon><Delete /></el-icon>删除
</el-button>
</el-col>
</el-row>
</div>
<el-table v-loading="loading" :data="state.tableData.data" @selection-change="handleSelectionChange">
<el-table-column type="selection" width="55" align="center" />
@ -44,6 +61,16 @@
</template>
</el-table-column>
<el-table-column label="创建时间" align="center" prop="createdAt"> </el-table-column>
<el-table-column label="操作" align="center" class-name="small-padding" width="160px" fixed="right">
<template #default="scope">
<el-button type="success" link @click="handleUpdate(scope.row)" v-auth="'api/v1/system/busViolationLevel/edit'">
<el-icon><EditPen /></el-icon>修改
</el-button>
<el-button type="danger" link @click="handleDelete(scope.row)" v-auth="'api/v1/system/busViolationLevel/delete'">
<el-icon><DeleteFilled /></el-icon>删除
</el-button>
</template>
</el-table-column>
</el-table>
<pagination
v-show="state.tableData.total > 0"
@ -56,15 +83,15 @@
<apiV1SystemBusViolationLevelAdd
ref="addRef"
:tourTypeOptions="violation_level_type"
:risxList="risk_level_type"
:tourTypeOptions="safety_inspection_violation_type"
:risxList="risx"
@busViolationLevelList="busViolationLevelList"
:postListAll="state.postListAll"
/>
<apiV1SystemBusViolationLevelEdit
ref="editRef"
:tourTypeOptions="violation_level_type"
:risxList="risk_level_type"
:tourTypeOptions="safety_inspection_violation_type"
:risxList="risx"
:postListAll="state.postListAll"
@busViolationLevelList="busViolationLevelList"
/>
@ -123,7 +150,7 @@ const state = reactive<any>({
const postList = () => {
listTreeByProject().then((res) => {
console.log('🚀 ~ listTreeByProject ~ res:', res);
state.postListAll = res.data ?? [];
state.postListAll = res.data.postList ?? [];
});
};

View File

@ -23,6 +23,7 @@
<el-card shadow="never">
<template #header>
<el-row :gutter="10" class="mb8">
<el-button type="danger" @click="handleDelete()" plain icon="Delete" :disabled="multiple">删除</el-button>
<right-toolbar v-model:showSearch="showSearch" @queryTable="getList"></right-toolbar>
</el-row>
</template>
@ -66,60 +67,94 @@
</template>
</el-table-column>
<el-table-column label="备注" align="center" prop="remark" />
<el-table-column label="操作" align="center" class-name="small-padding fixed-width">
<el-table-column label="操作" align="center" class-name="small-padding fixed-width" width="200">
<template #default="scope">
<el-tooltip content="详情" placement="top">
<el-button link type="primary" icon="View" @click="handleShowDialog(scope.row)" v-hasPermi="['safety:violationRecord:view']"
>详情</el-button
>
<el-button
link
type="primary"
icon="View"
@click="handleShowDialog(scope.row)"
icon="User"
v-if="!scope.row.openid"
@click="handleEdit(scope.row)"
v-hasPermi="['safety:violationRecord:view']"
></el-button>
</el-tooltip>
>违章处理人</el-button
>
<el-button link type="danger" icon="Delete" @click="handleDelete(scope.row)" v-hasPermi="['safety:violationRecord:view']">删除</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>
<!-- 添加或修改违规记录对话框 -->
<el-dialog :title="dialog.title" v-model="dialog.visible" width="500px" append-to-body>
<el-form ref="violationRecordFormRef" :model="form" :rules="rules" label-width="90px">
<el-form-item label="违章处理人" prop="handlerId">
<el-input v-model="form.handlerId" placeholder="请输入违章处理人" />
</el-form-item>
<el-form-item label="处理期限" prop="disposeDeadline">
<el-date-picker clearable v-model="form.disposeDeadline" type="datetime" value-format="YYYY-MM-DD HH:mm:ss" placeholder="请选择处理期限">
</el-date-picker>
</el-form-item>
<el-form-item label="备注" prop="remark">
<el-input v-model="form.remark" placeholder="请输入备注" />
</el-form-item>
</el-form>
<template #footer>
<div class="dialog-footer">
<el-button :loading="buttonLoading" type="primary" @click="submitForm"> </el-button>
<el-button @click="cancel"> </el-button>
</div>
</template>
</el-dialog>
<el-dialog title="违规记录详情" v-model="showDetailDialog" width="60vw">
<ViolationRecordDetailDialog
:violation-record-id="currentViolationRecordId"
:safety_inspection_violation_type="safety_inspection_violation_type"
/>
</el-dialog>
<el-dialog v-model="isShowDialog" width="450px" :close-on-click-modal="false" :destroy-on-close="true">
<template #header>
<div v-drag="['.system-busViolationRecord-add .el-dialog', '.system-busViolationRecord-add .el-dialog__header']">选择违章处理人</div>
</template>
<el-form ref="formRef" :model="form" :rules="rules" label-width="120px">
<el-row>
<el-col :span="24">
<el-form-item label="处理人" prop="openid">
<el-select v-model="form.openid" :filter-method="filterMethod" filterable placeholder="请选择处理人">
<el-option
v-for="(item, i) of userQuery.userList"
:key="item.openid"
:label="item.userName ? item.userName : item.nickName"
:value="item.openid"
/>
<pagination
v-show="userQuery.total > 0"
:total="userQuery.total"
v-model:page="userQuery.param.pageNum"
v-model:limit="userQuery.param.pageSize"
@pagination="busConstructionUserList"
:layout="'total, prev, pager, next'"
:isSmall="true"
style="padding: 5px 10px"
/>
</el-select>
</el-form-item>
<el-form-item label="要求处理期限" prop="processingPeriod">
<el-date-picker format="YYYY-MM-DD" value-format="YYYY-MM-DD" v-model="form.processingPeriod" type="date" placeholder="要求处理期限" />
</el-form-item>
<el-form-item label="备注" prop="remark">
<el-input v-model="form.remark" placeholder="请输入备注" />
</el-form-item>
</el-col>
</el-row>
</el-form>
<template #footer>
<div class="dialog-footer">
<el-button type="primary" @click="onSubmit" :loading="loading"> </el-button>
<el-button @click="isShowDialog = false"> </el-button>
</div>
</template>
</el-dialog>
</div>
</template>
<script setup name="ViolationRecord" lang="ts">
import { listViolationRecord, getViolationRecord, delViolationRecord, addViolationRecord, updateViolationRecord } from '@/api/safety/violationRecord';
import {
listViolationRecord,
getViolationRecord,
delViolationRecord,
addViolationRecord,
updateViolationRecord,
listBusConstructionUser
} from '@/api/safety/violationRecord';
import { ViolationRecordVO, ViolationRecordQuery, ViolationRecordForm } from '@/api/safety/violationRecord/types';
import ViolationRecordDetailDialog from './component/violationRecordDetailDialog.vue';
import { useUserStoreHook } from '@/store/modules/user';
const { proxy } = getCurrentInstance() as ComponentInternalInstance;
import { getDictData } from '@/api/project/goUser/index';
import { disable } from 'ol/rotationconstraint';
const { violation_level_type, risk_level_type, safety_inspection_type } = toRefs<any>(
proxy?.useDict('violation_level_type', 'risk_level_type', 'safety_inspection_type')
);
@ -127,6 +162,17 @@ const { violation_level_type, risk_level_type, safety_inspection_type } = toRefs
const userStore = useUserStoreHook();
// 从 store 中获取项目列表和当前选中的项目
const currentProject = computed(() => userStore.selectedProject);
const userQuery = reactive({
userList: [],
total: 0,
param: {
pageNum: 1,
pageSize: 10,
userName: undefined,
phone: undefined,
projectId: currentProject.value.goId
}
});
const violationRecordList = ref<ViolationRecordVO[]>([]);
const buttonLoading = ref(false);
@ -138,6 +184,7 @@ const multiple = ref(true);
const total = ref(0);
const currentViolationRecordId = ref<string | number>(undefined);
const showDetailDialog = ref(false);
const isShowDialog = ref(false);
const queryFormRef = ref<ElFormInstance>();
const violationRecordFormRef = ref<ElFormInstance>();
@ -194,12 +241,29 @@ const data = reactive<PageData<ViolationRecordForm, ViolationRecordQuery>>({
levelId: [{ required: true, message: '违章等级id不能为空', trigger: 'blur' }],
recognizeId: [{ required: true, message: '识别记录id不能为空', trigger: 'blur' }],
processType: [{ required: true, message: '处理流程类型(0仅通知 1通知整改复查)不能为空', trigger: 'change' }],
status: [{ required: true, message: '工单状态不能为空', trigger: 'change' }]
status: [{ required: true, message: '工单状态不能为空', trigger: 'change' }],
openid: [{ required: true, message: '处理人不能为空', trigger: 'change' }],
processingPeriod: [{ required: true, message: '要求处理期限不能为空', trigger: 'change' }]
}
});
const { queryParams, form, rules } = toRefs(data);
const filterMethod = (val) => {
userQuery.param.userName = val;
busConstructionUserList();
};
const busConstructionUserList = () => {
listBusConstructionUser(userQuery.param).then((res: any) => {
if (res.code === 0) {
userQuery.userList = [];
userQuery.userList = res.data.list;
userQuery.total = res.data.total;
}
});
};
/** 查询违规记录列表 */
const getList = async () => {
loading.value = true;
@ -247,6 +311,14 @@ const handleAdd = () => {
dialog.title = '添加违规记录';
};
const handleEdit = async (row: any) => {
reset();
busConstructionUserList();
const res = await getViolationRecord(row.id);
form.value.id = res.data.id;
isShowDialog.value = true;
};
/** 修改按钮操作 */
const handleUpdate = async (row?: ViolationRecordVO) => {
reset();
@ -261,11 +333,11 @@ const handleShowDialog = (row?: ViolationRecordVO) => {
};
/** 提交按钮 */
const submitForm = () => {
const onSubmit = () => {
violationRecordFormRef.value?.validate(async (valid: boolean) => {
if (valid) {
buttonLoading.value = true;
await addViolationRecord(form.value).finally(() => (buttonLoading.value = false));
loading.value = true;
await addViolationRecord(form.value).finally(() => (loading.value = false));
proxy?.$modal.msgSuccess('操作成功');
dialog.visible = false;
await getList();

View File

@ -688,7 +688,7 @@ onUnmounted(() => {
}
}
.upload-file-list .ele-upload-list__item-content {
.upload-file-list .upload-list__item-content {
display: flex;
justify-content: space-between;
align-items: center;