Compare commits

...

133 Commits

Author SHA1 Message Date
38dcbe7f7a 优化 2025-09-10 11:42:24 +08:00
71ba51772d 优化 2025-09-10 09:58:41 +08:00
Teo
11a3db5b61 修改 2025-09-10 09:23:51 +08:00
Teo
b662da584a 合并 2025-09-10 01:20:22 +08:00
Teo
311623e208 合并 2025-09-10 01:11:46 +08:00
fadbb6a911 大屏合并 2025-09-09 22:14:04 +08:00
ljx
0afefe44ca 大屏提交 2025-09-09 22:07:43 +08:00
71ec027000 优化 2025-09-09 22:00:19 +08:00
c913be2690 合并 2025-09-09 21:57:51 +08:00
217cf85ea4 优化 2025-09-09 21:55:42 +08:00
d5cf2a600e 项目级页面添加漫游、摄像头、定位设备、无人机、摄像头视频播放 2025-09-09 21:52:59 +08:00
tcy
e6f235036e refactor(components): 优化多个组件的样式和布局
- 调整了多个组件的输入框、按钮等元素的样式
- 优化了部分对话框的布局结构
- 统一了表单项的样式
- 调整了部分字体大小和颜色
2025-09-09 21:12:04 +08:00
35a7825759 项目级大屏地球 2025-09-09 19:52:26 +08:00
4bd192dc87 Merge branch 'main' of http://192.168.110.2:3000/taoge/mk_system into fs 2025-09-09 19:18:09 +08:00
dhr
78de3276d3 Merge branch 'ljx' of http://xny.yj-3d.com:3000/taoge/mk_system into dhr 2025-09-09 18:35:52 +08:00
dhr
cabf64088b 0909 2025-09-09 18:35:03 +08:00
a50fbc26d7 优化 2025-09-09 18:18:17 +08:00
d92a540786 金额格式设置 2025-09-09 17:03:01 +08:00
dhr
db6d39e02e 0909 2025-09-09 15:38:38 +08:00
ljx
d01a56d9dc 修改 2025-09-09 15:37:59 +08:00
ljx
16eb852d9d 数字化大屏 2025-09-09 15:26:15 +08:00
Teo
f006ca5a2b 1 2025-09-09 14:45:43 +08:00
ljx
460472b29a Merge branch 'main' of http://xny.yj-3d.com:3000/taoge/new_project into ljx 2025-09-09 11:47:40 +08:00
ljx
3579ff100f 修改 2025-09-09 11:46:44 +08:00
731c423483 优化 2025-09-09 10:50:32 +08:00
c3a2e68980 合并 2025-09-09 10:48:54 +08:00
dhr
84246a3a61 0909 2025-09-09 10:37:05 +08:00
ljx
23ceb718e9 tijiao 2025-09-09 10:18:28 +08:00
ljx
9cb43687c4 Merge branch 'main' of http://xny.yj-3d.com:3000/taoge/new_project into ljx 2025-09-09 10:18:14 +08:00
fe9c299d64 Merge branch 'main' of http://192.168.110.2:3000/taoge/mk_system into fs 2025-09-09 10:17:02 +08:00
16fda90d96 合并 2025-09-09 10:15:34 +08:00
Teo
e3ff6020ac 1 2025-09-09 10:11:50 +08:00
Teo
32dc012598 合并 2025-09-09 10:07:21 +08:00
f6afa97b2d 合并 2025-09-09 10:03:11 +08:00
ljx
7be3859988 Merge branch 'main' of http://xny.yj-3d.com:3000/taoge/new_project into ljx 2025-09-09 10:00:56 +08:00
ljx
f1339ad082 识别身份证 2025-09-09 09:59:03 +08:00
dhr
ac812246ea Merge branch 'main' of http://xny.yj-3d.com:3000/taoge/mk_system into dhr 2025-09-09 09:42:56 +08:00
dhr
177da7a28a 0909 2025-09-09 09:42:28 +08:00
Teo
4cd7efcfe4 上传 2025-09-09 09:40:08 +08:00
e520f3b581 Merge branch 'main' of http://192.168.110.2:3000/taoge/mk_system into fs 2025-09-09 09:36:29 +08:00
ee849ba62a 合并 2025-09-09 09:12:18 +08:00
Teo
0c3ea8fe73 提交 2025-09-09 09:08:34 +08:00
cd9e00fc33 优化 2025-09-09 09:05:28 +08:00
7738212dd7 优化 2025-09-08 20:08:32 +08:00
ljx
942375b06b 修改提交 2025-09-08 20:07:09 +08:00
cf2b805770 优化 2025-09-08 20:00:59 +08:00
dhr
7e7d21f9ce Merge branch 'main' of http://xny.yj-3d.com:3000/taoge/mk_system into dhr 2025-09-08 15:45:11 +08:00
dhr
dc35cb8354 0908 2025-09-08 15:44:35 +08:00
Teo
4a9a0c4214 设计管理人员任命修复ui 2025-09-08 10:23:39 +08:00
Teo
e377368c41 合并 2025-09-08 10:22:41 +08:00
Teo
f341f08248 1 2025-09-08 10:21:17 +08:00
8eac9bce6c 合并 2025-09-08 09:49:11 +08:00
ljx
2ec6dcd74f 提交 2025-09-08 09:46:27 +08:00
6e33ae2972 优化 2025-09-08 09:41:59 +08:00
8631a697f4 合并 2025-09-06 19:20:55 +08:00
22a1379ca8 合并 2025-09-06 19:20:17 +08:00
38cf536f1b 合并 2025-09-06 19:18:50 +08:00
4f21a81706 优化 2025-09-06 19:18:00 +08:00
178f44a5a3 优化 2025-09-06 19:15:47 +08:00
dhr
4fa4c754f9 0906 2025-09-06 18:51:05 +08:00
tcy
5101dc7657 fix(ctr): 修复收入合同类型切换后未重置合同类型的问题
- 在切换收入合同类型时,确保合同类型被正确重置
- 优化了模板中的代码格式,提高了可读性
2025-09-06 18:26:17 +08:00
ljx
b412e847d4 提交 2025-09-06 18:24:12 +08:00
ljx
e39823db40 Merge branch 'main' of http://xny.yj-3d.com:3000/taoge/new_project into ljx 2025-09-06 18:24:00 +08:00
ljx
e71ec5b9c1 提交 2025-09-06 18:23:14 +08:00
ljx
52342e6623 修改9.06bug 2025-09-06 18:18:31 +08:00
ljx
dd594676ac 台账修改 2025-09-06 17:38:25 +08:00
6380ee505f 优化 2025-09-06 15:58:47 +08:00
Teo
c5dac4fbcc 合并 2025-09-06 15:27:22 +08:00
tcy
d50dbe719d refactor(formalities): 优化手续办理清单模板页面布局
- 调整了多个组件的样式和布局,包括表格、表单、按钮等
- 优化了部分代码结构,提高了代码可读性和维护性
- 添加了文件数量徽章,增强了用户界面的交互性
2025-09-06 15:19:02 +08:00
Teo
3fa3b5b508 1 2025-09-06 15:16:15 +08:00
tcy
dd12f54dc9 Merge branch 'main' of http://xny.yj-3d.com:3000/taoge/mk_system into tcy 2025-09-06 15:10:10 +08:00
tcy
d37243af6b refactor(volumeCatalog): 优化卷册目录页面布局和功能
- 调整表格列布局,增加文件数量徽章
- 优化导入按钮位置和样式
- 改进查看文件列表对话框,统一操作按钮样式
- 调整上传图纸和意见的组件样式
- 优化表格样式,增加对齐方式
2025-09-06 15:09:47 +08:00
3e4b85fc48 合并 2025-09-06 14:43:13 +08:00
b4dadc415d 优化 2025-09-06 14:41:47 +08:00
dhr
fff6fb5584 0905 2025-09-06 14:37:46 +08:00
dhr
3d50132338 0906 2025-09-06 13:21:10 +08:00
10538985ce 合并 2025-09-06 12:50:05 +08:00
2696d5cad5 合并 2025-09-06 12:46:03 +08:00
f0af5e47fa 优化 2025-09-06 12:45:15 +08:00
a517e694aa Merge branch 'main' of http://192.168.110.2:3000/taoge/mk_system into fs 2025-09-06 12:40:09 +08:00
ljx
03ec2223aa 提交 2025-09-05 22:17:25 +08:00
c9496f4400 gps 2025-09-05 21:36:48 +08:00
shi
db20b45f78 style:修改用户弹窗样式 2025-09-05 17:28:00 +08:00
shi
78dd437746 Merge branch 'main' of http://192.168.110.2:3000/taoge/mk_system into szq 2025-09-05 16:03:39 +08:00
922af12760 优化 2025-09-05 16:01:49 +08:00
b910c6fee2 Merge branch 'dhr' of http://192.168.110.2:3000/taoge/mk_system into fs 2025-09-05 15:13:10 +08:00
dhr
eb895793dd 0905 2025-09-05 15:11:21 +08:00
19b48371ef 优化 2025-09-05 14:18:26 +08:00
26b2ff2370 优化 2025-09-05 10:53:30 +08:00
b96217b9bb 优化 2025-09-05 10:46:16 +08:00
ljx
f68e5f96f6 修改 2025-09-05 10:44:38 +08:00
dhr
c35a75d030 0904 2025-09-04 22:56:00 +08:00
974b2e7038 优化 2025-09-04 22:02:54 +08:00
f9a6ad7fda 优化 2025-09-04 18:55:48 +08:00
eaaf940960 合并 2025-09-04 18:55:11 +08:00
6f7d7e56c2 合并 2025-09-04 18:53:10 +08:00
0f439c9220 优化 2025-09-04 18:42:45 +08:00
Teo
2b989e1d46 采购设计报表新增tab切换 2025-09-04 18:40:25 +08:00
Teo
26bef3f724 修复bug 2025-09-04 17:56:01 +08:00
shi
e075ce1bfc style 2025-09-04 17:36:13 +08:00
a257068054 打卡范围 2025-09-04 17:11:18 +08:00
Teo
80bb267e7d 合并 2025-09-04 11:11:22 +08:00
Teo
57460d0af1 增加搜索 2025-09-04 11:10:55 +08:00
4dd1f2d6d5 1 2025-09-04 10:56:28 +08:00
17ee714729 11 2025-09-04 10:37:24 +08:00
08556fbf7f 111 2025-09-04 10:36:43 +08:00
23b6551829 合并 2025-09-04 09:04:27 +08:00
9b06c042ef 优化 2025-09-04 09:03:42 +08:00
ljx
ab7d51d3a2 Merge branch 'main' of http://xny.yj-3d.com:3000/taoge/new_project into ljx 2025-09-03 17:31:25 +08:00
ljx
5f6547aeb1 提交 2025-09-03 17:31:16 +08:00
d26db2d321 优化 2025-09-03 17:28:50 +08:00
9d9224d6ad 合并 2025-09-03 15:44:29 +08:00
055811702b 优化 2025-09-03 15:42:10 +08:00
ljx
eb98e8c8c3 修改禅道bug 2025-09-03 15:10:20 +08:00
ljx
288ee14d5e Merge branch 'main' of http://xny.yj-3d.com:3000/taoge/new_project into ljx 2025-09-03 11:56:52 +08:00
ljx
26e4c899db 修改bug 2025-09-02 20:37:07 +08:00
a95d18906f 优化 2025-09-02 19:34:26 +08:00
2737e579c8 合并 2025-09-02 19:20:07 +08:00
069841ea99 合并 2025-09-02 19:16:42 +08:00
ljx
85e5572e53 修改bug 2025-09-02 19:15:36 +08:00
46f9c0568c 合并 2025-09-02 19:14:34 +08:00
1a476b8ee8 优化 2025-09-02 19:13:43 +08:00
ljx
d06d6a9504 修改禅道bug 2025-09-02 19:09:43 +08:00
ljx
0c81842fd6 Merge branch 'main' of http://xny.yj-3d.com:3000/taoge/new_project into ljx 2025-09-02 19:03:49 +08:00
ljx
2ba08c79ed 修改禅道bug 2025-09-02 19:00:50 +08:00
ddccc64586 工程量清单 2025-09-02 15:08:39 +08:00
0c0e55a383 Merge branch 'main' of http://192.168.110.2:3000/taoge/mk_system into fs 2025-09-02 14:59:06 +08:00
253e395ace 优化 2025-09-02 09:52:36 +08:00
192ffb5091 合并 2025-09-01 09:22:33 +08:00
9cecbeaa20 合并 2025-09-01 09:22:12 +08:00
shi
290fc16c32 略改样式 2025-08-25 19:59:36 +08:00
shi
e4523299d4 完善项目及大屏 2025-08-22 22:17:57 +08:00
shi
a712dce2cd 添加屏幕扩展动画 2025-08-22 17:47:58 +08:00
262 changed files with 22742 additions and 5798 deletions

View File

@ -8,7 +8,8 @@ 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://192.168.110.188:8919'
VITE_APP_BASE_API_GO = 'http://xny.yj-3d.com:7464'
# VITE_APP_BASE_API_GO = 'http://192.168.110.188:8919'
# 无人机接口地址

View File

@ -15,7 +15,7 @@ VITE_APP_SNAILJOB_ADMIN = '/snail-job'
# 生产环境
# GO生产环境
VITE_APP_BASE_API_GO = 'http://58.17.134.85:7363'
VITE_APP_BASE_API_GO = 'http://58.17.134.85:7464'
VITE_APP_BASE_API = 'http://xny.yj-3d.com:8899'
# 是否在打包时开启压缩,支持 gzip 和 brotli

View File

@ -0,0 +1 @@

View File

@ -67,10 +67,12 @@
"vue-json-pretty": "2.4.0",
"vue-print-nb": "^1.7.5",
"vue-router": "4.4.5",
"vue-simple-uploader": "^1.0.3",
"vue-types": "5.1.3",
"vue3-print-nb": "^0.1.4",
"vue3-scroll-seamless": "^1.0.6",
"vxe-table": "4.5.22"
"vxe-table": "4.5.22",
"xlsx": "^0.18.5"
},
"devDependencies": {
"@eslint/js": "9.15.0",

Binary file not shown.

1
public/vite.svg Normal file
View File

@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" aria-hidden="true" role="img" class="iconify iconify--logos" width="31.88" height="32" preserveAspectRatio="xMidYMid meet" viewBox="0 0 256 257"><defs><linearGradient id="IconifyId1813088fe1fbc01fb466" x1="-.828%" x2="57.636%" y1="7.652%" y2="78.411%"><stop offset="0%" stop-color="#41D1FF"></stop><stop offset="100%" stop-color="#BD34FE"></stop></linearGradient><linearGradient id="IconifyId1813088fe1fbc01fb467" x1="43.376%" x2="50.316%" y1="2.242%" y2="89.03%"><stop offset="0%" stop-color="#FFEA83"></stop><stop offset="8.333%" stop-color="#FFDD35"></stop><stop offset="100%" stop-color="#FFA800"></stop></linearGradient></defs><path fill="url(#IconifyId1813088fe1fbc01fb466)" d="M255.153 37.938L134.897 252.976c-2.483 4.44-8.862 4.466-11.382.048L.875 37.958c-2.746-4.814 1.371-10.646 6.827-9.67l120.385 21.517a6.537 6.537 0 0 0 2.322-.004l117.867-21.483c5.438-.991 9.574 4.796 6.877 9.62Z"></path><path fill="url(#IconifyId1813088fe1fbc01fb467)" d="M185.432.063L96.44 17.501a3.268 3.268 0 0 0-2.634 3.014l-5.474 92.456a3.268 3.268 0 0 0 3.997 3.378l24.777-5.718c2.318-.535 4.413 1.507 3.936 3.838l-7.361 36.047c-.495 2.426 1.782 4.5 4.151 3.78l15.304-4.649c2.372-.72 4.652 1.36 4.15 3.788l-11.698 56.621c-.732 3.542 3.979 5.473 5.943 2.437l1.313-2.028l72.516-144.72c1.215-2.423-.88-5.186-3.54-4.672l-25.505 4.922c-2.396.462-4.435-1.77-3.759-4.114l16.646-57.705c.677-2.35-1.37-4.583-3.769-4.113Z"></path></svg>

After

Width:  |  Height:  |  Size: 1.5 KiB

BIN
public/xx.xlsx Normal file

Binary file not shown.

View File

@ -16,6 +16,17 @@ export const listContactnotice = (query?: ContactnoticeQuery): AxiosPromise<Cont
});
};
/**
* 根据项目id查询项目班组班组长信息列表
* @param projectId
*/
export const listProjectTeamForeman = (projectId: string | number): AxiosPromise<any[]> => {
return request({
url: '/project/projectTeam/listForeman/' + projectId,
method: 'get'
});
};
/**
* 查询联系单详细
* @param id

View File

@ -24,3 +24,11 @@ export const exportWord = (params) => {
method: 'post'
});
};
// 导出模版
export const exportExcel = (params) => {
return request({
url: '/design/collect/exportExcel',
method: 'post',
params: params
});
};

View File

@ -127,6 +127,17 @@ export const majorList = (params) => {
params: params
});
};
/**
* 获取人员列表
* @param query
*/
export const copyUserList = (params) => {
return request({
url: '/design/volumeCatalog/copyUserList',
method: 'get',
params: params
});
};
/**
* 获取二维码信息
* @param query

View File

@ -0,0 +1,13 @@
import request from '@/utils/request';
import { AxiosPromise } from 'axios';
/**
* 查询企业关键指标
*/
export const keyIndex = () => {
return request({
url: '/enterprise/big/screen/keyIndex',
method: 'get'
});
};

111
src/api/equipment/index.ts Normal file
View File

@ -0,0 +1,111 @@
import request from '@/utils/request';
import { AxiosPromise } from 'axios';
import { EquipmentVO, EquipmentForm, EquipmentQuery } from '@/api/equipment/types';
/**
* 查询GPS设备详细列表
* @param query
* @returns {*}
*/
export const listEquipment = (query?: EquipmentQuery): AxiosPromise<EquipmentVO[]> => {
return request({
url: '/gps/equipment/list',
method: 'get',
params: query
});
};
/**
* 查询GPS设备详细详细
* @param id
*/
export const getEquipment = (id: string | number): AxiosPromise<EquipmentVO> => {
return request({
url: '/gps/equipment/' + id,
method: 'get'
});
};
/**
* 新增GPS设备详细
* @param data
*/
export const addEquipment = (data: EquipmentForm) => {
return request({
url: '/gps/equipment',
method: 'post',
data: data
});
};
/**
* 修改GPS设备详细
* @param data
*/
export const updateEquipment = (data: EquipmentForm) => {
return request({
url: '/gps/equipment',
method: 'put',
data: data
});
};
/**
* 删除GPS设备详细
* @param id
*/
export const delEquipment = (id: string | number | Array<string | number>) => {
return request({
url: '/gps/equipment/' + id,
method: 'delete'
});
};
export const bindUser = (data) => {
return request({
url: '/gps/equipment/bindManmachine',
method: 'post',
data: data
});
};
export const getUserId = (projectId) => {
return request({
url: '/gps/equipment/userList',
method: 'get',
params: { projectId }
});
};
export const gethistroyUser = (data) => {
return request({
url: '/gps/equipment/getUserList',
method: 'get',
params: data
});
};
// 解除绑定接口定义确保使用POST方法并正确传递data
export function getRemoveBind(data: { id: number; clientId: string }) {
return request({
url: '/gps/equipment/unbindManmachine',
method: 'post',
data: data
});
}
export function getProjectId() {
return request({
url: 'gps/equipment/getProjectList',
method: 'get'
});
}
export const getFootNote = (data) => {
return request({
url: 'gps/equipmentSon/getList',
method: 'get',
data: data
});
};

169
src/api/equipment/types.ts Normal file
View File

@ -0,0 +1,169 @@
export interface EquipmentVO {
/**
*
*/
id: string | number;
/**
* 项目ID
*/
projectId: string | number;
/**
* 用户id
*/
userId: string | number;
/**
* 设备标识
*/
clientId: string | number;
/**
* 设备名称
*/
deviceName: string;
/**
* 是否使用UDP协议0=否1=是
*/
udp: number;
/**
* 远程连接地址IP:端口)
*/
remoteAddressStr: string;
/**
* 连接创建时间
*/
creationTime: number;
/**
* 最后活动时间
*/
lastAccessedTime: number;
/**
* 是否已注册0=未注册1=已注册
*/
registered: number;
/**
* 备注
*/
remark: string;
}
export interface EquipmentForm extends BaseEntity {
/**
*
*/
id?: string | number;
/**
* 项目ID
*/
projectId?: string | number;
/**
* 用户id
*/
userId?: string | number;
/**
* 设备标识
*/
clientId?: string | number;
/**
* 设备名称
*/
deviceName?: string;
/**
* 是否使用UDP协议0=否1=是
*/
udp?: number;
/**
* 远程连接地址IP:端口)
*/
remoteAddressStr?: string;
/**
* 连接创建时间
*/
creationTime?: number;
/**
* 最后活动时间
*/
lastAccessedTime?: number;
/**
* 是否已注册0=未注册1=已注册
*/
registered?: number;
/**
* 备注
*/
remark?: string;
}
export interface EquipmentQuery extends PageQuery {
/**
* 项目ID
*/
projectId?: string | number;
/**
* 是否绑定
*/
type?: string | number;
/**
* 用户id
*/
userId?: string | number;
/**
* 设备标识
*/
clientId?: string | number;
/**
* 设备名称
*/
deviceName?: string;
/**
* 是否使用UDP协议0=否1=是
*/
udp?: number;
/**
* 远程连接地址IP:端口)
*/
remoteAddressStr?: string;
/**
* 连接创建时间
*/
creationTime?: number;
/**
* 最后活动时间
*/
lastAccessedTime?: number;
/**
* 是否已注册0=未注册1=已注册
*/
registered?: number;
/**
* 日期范围参数
*/
params?: any;
}

View File

@ -1,4 +1,5 @@
import request from '@/utils/request-go';
import request1 from '@/utils/request';
import { AxiosPromise } from 'axios';
import {
QualityVO,
@ -172,7 +173,7 @@ export const getweatherList = (): AxiosPromise<weatherVO[]> => {
*/
export const getSafetyDay = (id?: string): AxiosPromise<safetyDayVO> => {
return request({
return request1({
url: '/project/project/safetyDay/' + id,
method: 'get'
});

View File

@ -98,3 +98,18 @@ export const cashTotal = () => {
method: 'get'
});
};
//安全天数
export const getSafetyDay = (projectId) => {
return request({
url: '/money/big/screen/safetyDay/' + projectId,
method: 'get'
});
};
//安全天数
export const getWeather = (projectId) => {
return request({
url: '/money/big/screen/weather/' + projectId,
method: 'get'
});
};

View File

@ -129,10 +129,10 @@ export function getGoToken(): AxiosPromise<any> {
data: {
status: 'yjdsj',
verifyCode: '1111',
// username: 'admin',
// password: 'zmkg@2023A'
username: 'admin',
password: 'zmkg@2023A'
// username: 'admin1',
// password: 'zmkg@2023C'
password: 'zmkg@2023C'
}
});
}

View File

@ -1,63 +1,45 @@
import request from '@/utils/request';
import { AxiosPromise } from 'axios';
import { MachineryForm, MachineryQuery, MachineryVO } from '@/api/machinery/machinery/types';
/**
* 查询机械列表
* @param query
* @returns {*}
*/
export const listMachinery = (query?: MachineryQuery): AxiosPromise<MachineryVO[]> => {
import request from '@/utils/request-go';
// 查询机械列表
export function listBusMachinery(query: object) {
return request({
url: '/machinery/machinery/list',
url: '/zm/api/v1/system/busMachinery/list',
method: 'get',
params: query
});
};
/**
* 查询机械详细
* @param id
*/
export const getMachinery = (id: string | number): AxiosPromise<MachineryVO> => {
}
// 查询机械详细
export function getBusMachinery(id: number) {
return request({
url: '/machinery/machinery/' + id,
method: 'get'
url: '/zm/api/v1/system/busMachinery/get',
method: 'get',
params: {
id: id.toString()
}
});
};
/**
* 新增机械
* @param data
*/
export const addMachinery = (data: MachineryForm): AxiosPromise<string | number> => {
}
// 新增机械
export function addBusMachinery(data: object) {
return request({
url: '/machinery/machinery',
url: '/zm/api/v1/system/busMachinery/add',
method: 'post',
data: data
});
};
/**
* 修改机械
* @param data
*/
export const updateMachinery = (data: MachineryForm) => {
}
// 修改机械
export function updateBusMachinery(data: object) {
return request({
url: '/machinery/machinery',
url: '/zm/api/v1/system/busMachinery/edit',
method: 'put',
data: data
});
};
/**
* 删除机械
* @param id
*/
export const delMachinery = (id: string | number | Array<string | number>) => {
}
// 删除机械
export function delBusMachinery(ids: number[]) {
return request({
url: '/machinery/machinery/' + id,
method: 'delete'
url: '/zm/api/v1/system/busMachinery/delete',
method: 'delete',
data: {
ids: ids
}
});
};
}

View File

@ -1,63 +1,45 @@
import request from '@/utils/request';
import { AxiosPromise } from 'axios';
import { MachineryDetailForm, MachineryDetailQuery, MachineryDetailVO } from '@/api/machinery/machineryDetail/types';
/**
* 查询机械详情列表
* @param query
* @returns {*}
*/
export const listMachineryDetail = (query?: MachineryDetailQuery): AxiosPromise<MachineryDetailVO[]> => {
import request from '@/utils/request-go';
// 查询机械详情列表
export function listBusMachineryDetail(query: object) {
return request({
url: '/machinery/machineryDetail/list',
url: '/zm/api/v1/system/busMachineryDetail/list',
method: 'get',
params: query
});
};
/**
* 查询机械详情详细
* @param id
*/
export const getMachineryDetail = (id: string | number): AxiosPromise<MachineryDetailVO> => {
}
// 查询机械详情详细
export function getBusMachineryDetail(id: number) {
return request({
url: '/machinery/machineryDetail/' + id,
method: 'get'
url: '/zm/api/v1/system/busMachineryDetail/get',
method: 'get',
params: {
id: id.toString()
}
});
};
/**
* 新增机械详情
* @param data
*/
export const addMachineryDetail = (data: MachineryDetailForm): AxiosPromise<string | number> => {
}
// 新增机械详情
export function addBusMachineryDetail(data: object) {
return request({
url: '/machinery/machineryDetail',
url: '/zm/api/v1/system/busMachineryDetail/add',
method: 'post',
data: data
});
};
/**
* 修改机械详情
* @param data
*/
export const updateMachineryDetail = (data: MachineryDetailForm) => {
}
// 修改机械详情
export function updateBusMachineryDetail(data: object) {
return request({
url: '/machinery/machineryDetail',
url: '/zm/api/v1/system/busMachineryDetail/edit',
method: 'put',
data: data
});
};
/**
* 删除机械详情
* @param id
*/
export const delMachineryDetail = (id: string | number | Array<string | number>) => {
}
// 删除机械详情
export function delBusMachineryDetail(ids: number[]) {
return request({
url: '/machinery/machineryDetail/' + id,
method: 'delete'
url: '/zm/api/v1/system/busMachineryDetail/delete',
method: 'delete',
data: {
ids: ids
}
});
};
}

View File

@ -1,4 +1,5 @@
import request from '@/utils/request-go';
import requestGo from '@/utils/request-go';
import request from '@/utils/request';
import { AxiosPromise } from 'axios';
import { CompanyForm, CompanyQuery, CompanyVO } from '@/api/materials/company/types';
@ -9,11 +10,23 @@ import { CompanyForm, CompanyQuery, CompanyVO } from '@/api/materials/company/ty
*/
export const listCompany = (query?: CompanyQuery): AxiosPromise<CompanyVO[]> => {
return request({
return requestGo({
url: '/zm/api/v1/system/busCompany/list',
method: 'get',
params: query
});
}; /**
* 查询材料提供商
* @param query
* @returns {*}
*/
export const supplierInputGet = (query?) => {
return request({
url: '/supplierInput/supplierInput/getList',
method: 'get',
params: query
});
};
/**

View File

@ -75,3 +75,11 @@ export const inventoryList = (id: any) => {
method: 'get'
});
};
//获取材料表信息
export const getMaterialInfo = (id: any) => {
return request({
url: '/materials/materials/listByFormCode/' + id,
method: 'get'
});
};

View File

@ -0,0 +1,27 @@
import request from '@/utils/request';
//获取出库材料得列表
export const outboundMaterials = (query?: any) => {
return request({
url: '/materials/materials/listRelevancy',
method: 'get',
params: query
});
};
//新增出库
export const addOutbound = (data?: any) => {
return request({
url: '/materials/materialsInventory',
method: 'post',
data
});
};
//获取材料列表
export const getMaterialsList = (query?: any) => {
return request({
url: '/materials/materials/list',
method: 'get',
params: query
});
};

View File

@ -1,4 +1,5 @@
import request from '@/utils/request-go';
import requestGo from '@/utils/request-go';
import request from '@/utils/request';
import { AxiosPromise } from 'axios';
import { MaterialsForm, MaterialsQuery, MaterialsVO } from '@/api/materials/materials/types';
@ -8,7 +9,7 @@ import { MaterialsForm, MaterialsQuery, MaterialsVO } from '@/api/materials/mate
* @returns {*}
*/
export const listMaterials = (query?: MaterialsQuery): AxiosPromise<MaterialsVO[]> => {
return request({
return requestGo({
url: '/zm/api/v1/system/busEquipmentMaterials/list',
method: 'get',
params: query
@ -20,7 +21,7 @@ export const listMaterials = (query?: MaterialsQuery): AxiosPromise<MaterialsVO[
* @param id
*/
export const getMaterials = (id: string | number): AxiosPromise<MaterialsVO> => {
return request({
return requestGo({
url: '/zm/api/v1/system/busEquipmentMaterials/get',
method: 'get',
params: {

View File

@ -1,4 +1,5 @@
import request from '@/utils/request-go';
import requestGo from '@/utils/request-go';
import request from '@/utils/request';
import { AxiosPromise } from 'axios';
import { MaterialsInventoryForm, MaterialsInventoryQuery, MaterialsInventoryVO } from '@/api/materials/materialsInventory/types';
@ -9,7 +10,7 @@ import { MaterialsInventoryForm, MaterialsInventoryQuery, MaterialsInventoryVO }
*/
export const listMaterialsInventory = (query?: MaterialsInventoryQuery): AxiosPromise<MaterialsInventoryVO[]> => {
return request({
return requestGo({
url: '/zm/api/v1/system/busEquipmentMaterialsInventory/excellist',
method: 'get',
params: query
@ -61,3 +62,13 @@ export const delMaterialsInventory = (id: string | number | Array<string | numbe
method: 'delete'
});
};
//获取新的列表数据
export const getLedgerList = (query?: any) => {
return request({
url: '/materials/materials/listUseDetail',
method: 'get',
params: query
});
};
//导出

View File

@ -33,7 +33,6 @@ export interface MaterialsUseRecordVO {
* 备注
*/
remark: string;
}
export interface MaterialsUseRecordForm extends BaseEntity {
@ -71,11 +70,9 @@ export interface MaterialsUseRecordForm extends BaseEntity {
* 备注
*/
remark?: string;
}
export interface MaterialsUseRecordQuery extends PageQuery {
/**
* 项目ID
*/
@ -101,11 +98,9 @@ export interface MaterialsUseRecordQuery extends PageQuery {
*/
residueNumber?: string | number;
/**
* 日期范围参数
*/
params?: any;
/**
* 日期范围参数
*/
params?: any;
materialsId?: string | number;
}

View File

@ -4,6 +4,8 @@ import { RouteRecordRaw } from 'vue-router';
// 获取路由
export function getRouters(id: string): AxiosPromise<RouteRecordRaw[]> {
console.log('🚀 ~ getRouters ~ id:', id);
return request({
url: '/system/menu/getRouters/' + id,
method: 'get'

View File

@ -8,7 +8,7 @@ import { MonthPlanVO, MonthPlanForm, MonthPlanQuery } from '@/api/out/monthPlan/
* @returns {*}
*/
export const listMonthPlan = (query?: MonthPlanQuery): AxiosPromise<MonthPlanVO[]> => {
export const listMonthPlan = (query?: any) => {
return request({
url: '/out/monthPlan/list',
method: 'get',
@ -93,7 +93,7 @@ export const isSubmit = (id): AxiosPromise => {
*/
export const getMonthInfo = (query): AxiosPromise<MonthPlanVO> => {
return request({
url: '/out/monthPlan/monthInfo',
url: '/out/monthPlan/monthInfo/' + query.id,
method: 'get',
params: query
});
@ -120,4 +120,4 @@ export const purchaseValueA = (query) => {
method: 'get',
params: query
});
};
};

View File

@ -0,0 +1,43 @@
import request from '@/utils/request';
import { AxiosPromise } from 'axios';
/**
* 查询项目数据
* @param query
* @returns {*}
*/
export const projectProgress = (query?: any): any => {
return request({
url: '/enterprise/big/screen/projectProgress',
method: 'get',
params: query
});
};
/**
* 产值
* @param query
* @returns {*}
*/
export const outpuProgress = (query?: any): any => {
return request({
url: '/enterprise/big/screen/projectOutputValueComparison',
method: 'get',
params: query
});
};
/**
* 预警
* @param query
* @returns {*}
*/
export const earlyWarning = (query?: any): any => {
return request({
url: '/enterprise/big/screen/riskEarlyWarning',
method: 'get',
params: query
});
};

View File

@ -8,10 +8,11 @@ import { ProgressCategoryVO, ProgressCategoryForm, ProgressCategoryQuery } from
* @returns {*}
*/
export const listProgressCategory = (id?: string | number): AxiosPromise<any[]> => {
export const listProgressCategory = (parentId?: string | number,name?:string): AxiosPromise<any[]> => {
return request({
url: '/progress/progressCategory/listByParent/' + id,
method: 'get'
url: '/progress/progressCategory/listByParent',
method: 'get',
params:{parentId,name}
});
};

View File

@ -78,9 +78,10 @@ export const getTabList = (id: string) => {
* @param parentId
* @returns {*}
*/
export const listProgressCategoryTemplateByParent = (parentId: string | number): AxiosPromise<ProgressCategoryTemplateVO[]> => {
export const listProgressCategoryTemplateByParent = (parentId: string | number,name:string): AxiosPromise<ProgressCategoryTemplateVO[]> => {
return request({
url: '/progress/progressCategoryTemplate/listByParent/' + parentId,
method: 'get'
url: '/progress/progressCategoryTemplate/listByParent' ,
method: 'get',
params:{parentId,name}
});
};

View File

@ -0,0 +1,61 @@
import request from '@/utils/request-go';
// 查询员工工资考核记录列表
export function listBusSalaryDetails(query: object) {
return request({
url: '/zm/api/v1/system/busSalaryDetails/list',
method: 'get',
params: query
});
}
// 查询员工工资考核记录详细
export function getBusSalaryDetails(id: number) {
return request({
url: '/zm/api/v1/system/busSalaryDetails/get',
method: 'get',
params: {
id: id.toString()
}
});
}
// 新增员工工资考核记录
export function addBusSalaryDetails(data: object) {
return request({
url: '/zm/api/v1/system/busSalaryDetails/add',
method: 'post',
data: data
});
}
// 修改员工工资考核记录
export function updateBusSalaryDetails(data: object) {
return request({
url: '/zm/api/v1/system/busSalaryDetails/edit',
method: 'put',
data: data
});
}
// 删除员工工资考核记录
export function delBusSalaryDetails(ids: number[]) {
return request({
url: '/zm/api/v1/system/busSalaryDetails/delete',
method: 'delete',
data: {
ids: ids
}
});
}
// 根据身份证获取当前考勤记录明细
export function getByIdDetail(params) {
return request({
url: '/zm/api/v1/system/busSalaryDetails/getByIdDetail',
method: 'get',
params
});
}
// 工资条获取(可根据项目or班组or施工人员)
export function salarySheet(params) {
return request({
url: '/zm/api/v1/system/busSalaryDetails/salarySheet',
method: 'get',
params
});
}

View File

@ -1,4 +1,4 @@
import request from '@/utils/request-go';
import request from '@/utils/request';
import { AxiosPromise } from 'axios';
import {
ConstructionUserForm,
@ -23,7 +23,7 @@ import requestGo from '@/utils/request-go';
*/
export const listConstructionMonth = (query?: ConstructionMonthQuery): AxiosPromise<AttendanceMonthVO[]> => {
return request({
return requestGo({
url: '/zm/api/wxApplet/wxApplet/busAttendance/byOpenId',
method: 'get',
params: query
@ -62,7 +62,7 @@ export const listConstructionUserInTeam = (query?: ConstructionUserQuery): Axios
* @param id
*/
export const getConstructionUser = (id: string | number): AxiosPromise<ConstructionUserVO> => {
return request({
return requestGo({
url: '/zm/api/wxApplet/wxApplet/busConstructionUser/getDetails?id=' + id,
method: 'get'
});
@ -73,7 +73,7 @@ export const getConstructionUser = (id: string | number): AxiosPromise<Construct
* @param data
*/
export const transferConstructionUser = (data: skipType) => {
return request({
return requestGo({
url: '/zm/api/wxApplet/wxApplet/busConstructionUser/changePay',
method: 'put',
data: data
@ -84,7 +84,7 @@ export const transferConstructionUser = (data: skipType) => {
* 查询项目以及项目下的分包公司列表
*/
export const getProjectContractorList = () => {
return request({
return requestGo({
url: '/zm/api/v1/system/sysProject/list?pageNum=1&pageSize=1000',
method: 'get'
});
@ -95,7 +95,7 @@ export const getProjectContractorList = () => {
* @param data
*/
export const addConstructionUser = (data: ConstructionUserForm): AxiosPromise<string | number> => {
return request({
return requestGo({
url: '/zm/api/wxApplet/wxApplet/busConstructionUser/add',
method: 'post',
data: data
@ -107,7 +107,7 @@ export const addConstructionUser = (data: ConstructionUserForm): AxiosPromise<st
* @param data
*/
export const updateConstructionUser = (data: ConstructionUserForm) => {
return request({
return requestGo({
url: '/zm/api/v1/system/busConstructionUser/pcEdit',
method: 'put',
data: data
@ -119,7 +119,7 @@ export const updateConstructionUser = (data: ConstructionUserForm) => {
* @param id
*/
export const delConstructionUser = (data) => {
return request({
return requestGo({
url: '/zm/api/wxApplet/wxApplet/busConstructionUser/delete',
method: 'delete',
data
@ -131,7 +131,7 @@ export const delConstructionUser = (data) => {
* @param data
*/
export const updateConstructionUserStatus = (data: ConstructionUserStatusForm) => {
return request({
return requestGo({
url: '/zm/api/wxApplet/wxApplet/busConstructionUser/changeState',
method: 'delete',
data: data
@ -143,7 +143,7 @@ export const updateConstructionUserStatus = (data: ConstructionUserStatusForm) =
* @param data
*/
export const updateConstructionUserPlayCardStatus = (data: ConstructionUserPlayCardForm) => {
return request({
return requestGo({
url: '/zm/api/v1/system/busConstructionUser/oneClickOpen',
method: 'put',
data: data
@ -155,7 +155,7 @@ export const updateConstructionUserPlayCardStatus = (data: ConstructionUserPlayC
* @param data
*/
export const updateConstructionUserPlayCardOneStatus = (data: ConstructionUserPlayCardForm) => {
return request({
return requestGo({
url: '/zm/api/v1/system/busConstructionUser/clockingCondition',
method: 'put',
data: data
@ -167,7 +167,7 @@ export const updateConstructionUserPlayCardOneStatus = (data: ConstructionUserPl
* @param data
*/
export const updateConstructionUserSalary = (data: ConstructionUserSalaryForm) => {
return request({
return requestGo({
url: '/zm/api/wxApplet/wxApplet/busConstructionUser/payEdit',
method: 'put',
data: data
@ -179,7 +179,7 @@ export const updateConstructionUserSalary = (data: ConstructionUserSalaryForm) =
* @param query
*/
export const getConstructionUserExit = (query: ConstructionUserExitForm) => {
return request({
return requestGo({
url: '/zm/api/v1/system/busConstructionUser/departureRecord',
method: 'post',
data: query
@ -191,7 +191,7 @@ export const getConstructionUserExit = (query: ConstructionUserExitForm) => {
* @param query
*/
export const dowloadConstructionUserTemplate = (query: ConstructionUserTemplateForm) => {
return request({
return requestGo({
url: '/zm/api/v1/system/busConstructionUser/templateExport',
method: 'get',
params: query
@ -208,7 +208,7 @@ export const dowloadConstructionUserTemplate = (query: ConstructionUserTemplateF
* @param data
*/
export const delConstructionUserMember = (data: ConstructionUserMembeForm) => {
return request({
return requestGo({
url: '/zm/api/v1/system/busConstructionUser/departure',
method: 'post',
data
@ -226,3 +226,30 @@ export const importConstructionUserInfo = (file: string) => {
data: { file }
});
};
// 获取项目列表
export const ProjectList = (query) => {
return request({
url: '/contractor/constructionUser/projectList',
method: 'get',
params: query
});
};
// 获取班组列表
export const TeamList = (query) => {
return request({
url: '/contractor/constructionUser/teamList',
method: 'get',
params: query
});
};
// 班组分配
export const TeamDistribution = (data) => {
return request({
url: '/contractor/constructionUser/addTeam',
method: 'post',
data: data
});
};

View File

@ -182,6 +182,8 @@ export interface ConstructionUserVO {
* 创建时间
*/
createTime: string;
sysUserId: string | number;
}
export interface skipType {
/**

View File

@ -23,7 +23,7 @@ export const listConstructionUserFile = (query?: ConstructionUserFileQuery): Axi
*/
export const setConstructionUserFile = (data: ConstructionUserFileForm): AxiosPromise<string | number> => {
return request({
url: '/project/constructionUserFile/save',
url: '/contractor/constructionUserFile/save',
method: 'post',
data
});
@ -35,7 +35,7 @@ export const setConstructionUserFile = (data: ConstructionUserFileForm): AxiosPr
*/
export const delConstructionUserFile = (id: string | number | Array<string | number>) => {
return request({
url: '/project/constructionUserFile/' + id,
url: '/contractor/constructionUserFile/' + id,
method: 'delete'
});
};

View File

@ -196,3 +196,71 @@ export const changeProject = (id: string | number) => {
method: 'get'
});
};
/**
* 打卡规则
* @param id
*/
export const attendanceRuleEdit = (data) => {
return request({
url: '/project/attendanceRule',
method: 'put',
data
});
};
/**
* 打卡规则
* @param id
*/
export const attendanceRuleAdd = (data) => {
return request({
url: '/project/attendanceRule',
method: 'post',
data
});
};
/**
* 获取规则
* @param id
*/
export const byProjectIdDetail = (id) => {
return request({
url: '/project/attendanceRule/byProjectId/' + id,
method: 'get'
});
};
// 新增项目打卡范围
export const addAttendanceRange = (data) => {
return request({
url: '/project/projectPunchrange',
method: 'post',
data
});
};
// 删除项目打卡范围
export const delAttendanceRange = (id) => {
return request({
url: '/project/projectPunchrange/' + id,
method: 'delete'
});
};
// 修改项目打卡范围
export const updateAttendanceRange = (data) => {
return request({
url: '/project/projectPunchrange',
method: 'put',
data
});
};
// 查询项目打卡范围列表
export const getAttendanceRangeList = (data) => {
return request({
url: '/project/projectPunchrange/list',
method: 'get',
params: data
});
};

View File

@ -75,3 +75,12 @@ export const delProjectTeam = (ids: string | number | Array<string | number>) =>
params: { ids }
});
};
// 根据项目或班组导出出勤记录(班组)
export function exportSalary(data: any) {
return request({
url: '/zm/api/v1/system/busConstructionUser/exportSalary',
method: 'post',
data
});
}

View File

@ -55,6 +55,11 @@ export interface ProjectTeamForm extends BaseEntity {
* 备注
*/
remark?: string;
/**
* 创建时间
*/
punchRangeList?: [];
}
export interface ProjectTeamQuery extends PageQuery {

View File

@ -0,0 +1,90 @@
import request from '@/utils/request';
import { AxiosPromise } from 'axios';
// 查询生项目天气
export const getScreenWeather = (projectId: number | string) => {
return request({
url: '/project/big/screen/weather/' + projectId,
method: 'get',
});
};
// 查询项目安全天数
export const getScreenSafetyDay = (projectId: number | string) => {
return request({
url: '/project/big/screen/safetyDay/' + projectId,
method: 'get',
});
};
// 查询项目公告
export const getScreenNews = (projectId: number | string) => {
return request({
url: '/project/big/screen/news/' + projectId,
method: 'get',
});
};
// 查询项目土地统计
export const getScreenLand = (projectId: number | string) => {
return request({
url: '/project/big/screen/' + projectId,
method: 'get',
});
};
// 查询项目形象进度
export const getScreenImgProcess = (projectId: number | string) => {
return request({
url: '/project/big/screen/imageProgress/' + projectId,
method: 'get',
});
};
// 查询项目人员情况
export const getScreenPeople = (projectId: number | string) => {
return request({
url: '/project/big/screen/people/' + projectId,
method: 'get',
});
};
// 查询项目AI安全巡检
export const getScreenSafetyInspection = (projectId: number | string) => {
return request({
url: '/project/big/screen/safetyInspection/' + projectId,
method: 'get',
});
};
// 查询项目概况
export const getScreenGeneralize = (projectId: number | string) => {
return request({
url: '/project/big/screen/generalize/' + projectId,
method: 'get',
});
};
// 获取gps数据
export const getGps = (projectId) => {
return request({
url: '/project/big/screen/getClientList/' + projectId,
method: 'get'
});
};
// 选中列表
export const getSelectList = (params) => {
return request({
url: '/project/big/screen/getList',
method: 'get',
params
});
};
// 设置选中
export const setSelect = (data) => {
return request({
url: '/project/big/screen/setList',
method: 'post',
data
});
};

View File

@ -0,0 +1,5 @@
export interface TableQuery extends PageQuery {
tableName: string;
tableComment: string;
dataName: string;
}

View File

@ -1,4 +1,5 @@
import request from '@/utils/request-go';
import requestGo from '@/utils/request-go';
import request from '@/utils/request';
import { AxiosPromise } from 'axios';
import { QualityConstructionLogVO, QualityConstructionLogForm, QualityConstructionLogQuery } from '@/api/quality/qualityConstructionLog/types';
@ -9,7 +10,7 @@ import { QualityConstructionLogVO, QualityConstructionLogForm, QualityConstructi
*/
export const listQualityConstructionLog = (query?: QualityConstructionLogQuery): AxiosPromise<QualityConstructionLogVO[]> => {
return request({
return requestGo({
url: '/zm/api/v1/system/busConstructionLog/list',
method: 'get',
params: query
@ -21,8 +22,8 @@ export const listQualityConstructionLog = (query?: QualityConstructionLogQuery):
* @param id
*/
export const getQualityConstructionLog = (id: string | number): AxiosPromise<QualityConstructionLogVO> => {
return request({
url: 'zm/api/v1/system/busConstructionLog/get',
return requestGo({
url: '/zm/api/v1/system/busConstructionLog/get',
method: 'get',
params: { id }
});
@ -57,7 +58,7 @@ export const updateQualityConstructionLog = (data: QualityConstructionLogForm) =
* @param id
*/
export const delQualityConstructionLog = (id: string | number | Array<string | number>) => {
return request({
return requestGo({
url: '/zm/api/v1/system/busConstructionLog/delete',
method: 'delete',
data: { ids: id }

View File

@ -1,6 +1,6 @@
import request from '@/utils/request';
import { AxiosPromise } from 'axios';
import { QuestionBankVO, QuestionBankForm, QuestionBankQuery } from '@/api/safety/questionBank/types';
import { QuestionBankVO, QuestionBankForm, QuestionBankQuery } from '@/api/safety/wgzQuestionBank/types';
/**
* 查询题库列表
@ -10,7 +10,7 @@ import { QuestionBankVO, QuestionBankForm, QuestionBankQuery } from '@/api/safet
export const listQuestionBank = (query?: QuestionBankQuery): AxiosPromise<QuestionBankVO[]> => {
return request({
url: '/safety/questionBank/list',
url: '/safety/wgzQuestionBank/list',
method: 'get',
params: query
});
@ -22,7 +22,7 @@ export const listQuestionBank = (query?: QuestionBankQuery): AxiosPromise<Questi
*/
export const getQuestionBank = (id: string | number): AxiosPromise<QuestionBankVO> => {
return request({
url: '/safety/questionBank/' + id,
url: '/safety/wgzQuestionBank/' + id,
method: 'get'
});
};
@ -33,7 +33,7 @@ export const getQuestionBank = (id: string | number): AxiosPromise<QuestionBankV
*/
export const addQuestionBank = (data: QuestionBankForm) => {
return request({
url: '/safety/questionBank',
url: '/safety/wgzQuestionBank',
method: 'post',
data: data
});
@ -45,7 +45,7 @@ export const addQuestionBank = (data: QuestionBankForm) => {
*/
export const updateQuestionBank = (data: QuestionBankForm) => {
return request({
url: '/safety/questionBank',
url: '/safety/wgzQuestionBank',
method: 'put',
data: data
});
@ -57,7 +57,7 @@ export const updateQuestionBank = (data: QuestionBankForm) => {
*/
export const delQuestionBank = (id: string | number | Array<string | number>) => {
return request({
url: '/safety/questionBank/' + id,
url: '/safety/wgzQuestionBank/' + id,
method: 'delete'
});
};

View File

@ -1,6 +1,6 @@
import request from '@/utils/request';
import { AxiosPromise } from 'axios';
import { QuestionUserAnswerVO, QuestionUserAnswerForm, QuestionUserAnswerQuery } from '@/api/safety/questionUserAnswer/types';
import { QuestionUserAnswerVO, QuestionUserAnswerForm, QuestionUserAnswerQuery } from '@/api/safety/wgzQuestionSave/types';
/**
* 查询用户试卷存储列表
@ -10,7 +10,7 @@ import { QuestionUserAnswerVO, QuestionUserAnswerForm, QuestionUserAnswerQuery }
export const listQuestionUserAnswer = (query?: QuestionUserAnswerQuery): AxiosPromise<QuestionUserAnswerVO[]> => {
return request({
url: '/safety/questionUserAnswer/list',
url: '/safety/wgzQuestionSave/list',
method: 'get',
params: query
});
@ -22,7 +22,7 @@ export const listQuestionUserAnswer = (query?: QuestionUserAnswerQuery): AxiosPr
*/
export const getQuestionUserAnswer = (id: string | number): AxiosPromise<QuestionUserAnswerVO> => {
return request({
url: '/safety/questionUserAnswer/' + id,
url: '/safety/wgzQuestionSave/' + id,
method: 'get'
});
};
@ -33,7 +33,7 @@ export const getQuestionUserAnswer = (id: string | number): AxiosPromise<Questio
*/
export const addQuestionUserAnswer = (data: QuestionUserAnswerForm) => {
return request({
url: '/safety/questionUserAnswer',
url: '/safety/wgzQuestionSave',
method: 'post',
data: data
});
@ -45,7 +45,7 @@ export const addQuestionUserAnswer = (data: QuestionUserAnswerForm) => {
*/
export const updateQuestionUserAnswer = (data: QuestionUserAnswerForm) => {
return request({
url: '/safety/questionUserAnswer',
url: '/safety/wgzQuestionSave',
method: 'put',
data: data
});
@ -57,7 +57,7 @@ export const updateQuestionUserAnswer = (data: QuestionUserAnswerForm) => {
*/
export const delQuestionUserAnswer = (id: string | number | Array<string | number>) => {
return request({
url: '/safety/questionUserAnswer/' + id,
url: '/safety/wgzQuestionSave/' + id,
method: 'delete'
});
};
@ -68,7 +68,7 @@ export const delQuestionUserAnswer = (id: string | number | Array<string | numbe
*/
export const uploadQuestionUserAnswer = (data: any) => {
return request({
url: '/safety/questionUserAnswer/upload/zip',
url: '/safety/wgzQuestionSave/upload/zip',
method: 'post',
data: data
});

View File

@ -10,7 +10,7 @@ import { QuestionsCategoryVO, QuestionsCategoryForm, QuestionsCategoryQuery } fr
export const listQuestionsCategory = (query?: QuestionsCategoryQuery): AxiosPromise<QuestionsCategoryVO[]> => {
return request({
url: '/safety/questionsCategory/list',
url: '/safety/wzgQuestionCategory/list',
method: 'get',
params: query
});
@ -22,7 +22,7 @@ export const listQuestionsCategory = (query?: QuestionsCategoryQuery): AxiosProm
*/
export const getQuestionsCategory = (id: string | number): AxiosPromise<QuestionsCategoryVO> => {
return request({
url: '/safety/questionsCategory/' + id,
url: '/safety/wzgQuestionCategory' + id,
method: 'get'
});
};
@ -33,7 +33,7 @@ export const getQuestionsCategory = (id: string | number): AxiosPromise<Question
*/
export const addQuestionsCategory = (data: QuestionsCategoryForm) => {
return request({
url: '/safety/questionsCategory',
url: '/safety/wzgQuestionCategory',
method: 'post',
data: data
});
@ -45,7 +45,7 @@ export const addQuestionsCategory = (data: QuestionsCategoryForm) => {
*/
export const updateQuestionsCategory = (data: QuestionsCategoryForm) => {
return request({
url: '/safety/questionsCategory',
url: '/safety/wzgQuestionCategory',
method: 'put',
data: data
});
@ -57,7 +57,7 @@ export const updateQuestionsCategory = (data: QuestionsCategoryForm) => {
*/
export const delQuestionsCategory = (id: string | number | Array<string | number>) => {
return request({
url: '/safety/questionsCategory/' + id,
url: '/safety/wzgQuestionCategory' + id,
method: 'delete'
});
};

View File

@ -22,7 +22,7 @@ export const listQuestionsConfig = (query?: QuestionsConfigQuery): AxiosPromise<
*/
export const getQuestionsConfig = (id: string | number): AxiosPromise<QuestionsConfigVO> => {
return request({
url: '/safety/questionsConfig/' + id,
url: '/safety/wzgQuestionsConfiguration/' + id,
method: 'get'
});
};
@ -45,7 +45,7 @@ export const addQuestionsConfig = (data: QuestionsConfigForm) => {
*/
export const updateQuestionsConfig = (data: QuestionsConfigForm) => {
return request({
url: '/safety/questionsConfig',
url: '/safety/wzgQuestionsConfiguration',
method: 'put',
data: data
});

View File

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

View File

@ -57,7 +57,7 @@ export const updateViolationLevel = (data: ViolationLevelForm) => {
* @param id
*/
export const delViolationLevel = (id: string | number | Array<string | number>) => {
return request({
return request1({
url: '/zm/api/v1/system/busViolationLevel/delete',
method: 'delete',
data: { ids: id }

View File

@ -61,3 +61,22 @@ export const delSupplierInput = (id: string | number | Array<string | number>) =
method: 'delete'
});
};
//导入供商入库
export const leadingIn = (formData: FormData, projectId) => {
return request({
url: '/supplierInput/supplierInput/import?projectId=' + projectId,
method: 'post',
data: formData,
headers: {
'Content-Type': 'multipart/form-data'
}
});
};
//导入供商出库
export const leadingOut = () => {
return request({
url: '/supplierInput/supplierInput/export',
method: 'post'
});
};

View File

@ -79,3 +79,26 @@ export const landTransferLedgerCount = (id: string | number | Array<string | num
method: 'get'
});
};
export const addSonLandTransferLedger = (data) => {
return request({
url: '/land/landTransferLedger/children/add',
method: 'post',
data: data
});
};
export const listSonLandTransferLedger = (query) => {
return request({
url: '/land/landTransferLedger/children/list',
method: 'get',
params: query
});
};
// api/yourApiModule.js
export const listallCountValue = (projectId) => {
return request({
url: '/land/landTransferLedger/allCountValue/' + projectId,
method: 'get'
});
};

View File

@ -4,6 +4,11 @@ export interface LandTransferLedgerVO {
*/
id: string | number;
/**
* 父级ID
*/
parentId: string | number;
/**
* 项目ID
*/
@ -83,7 +88,6 @@ export interface LandTransferLedgerVO {
* 下一步策略
*/
nextStrategy: string;
}
export interface LandTransferLedgerForm extends BaseEntity {
@ -92,6 +96,11 @@ export interface LandTransferLedgerForm extends BaseEntity {
*/
id?: string | number;
/**
* 父级ID
*/
parentId: string | number;
/**
* 项目ID
*/
@ -171,11 +180,9 @@ export interface LandTransferLedgerForm extends BaseEntity {
* 下一步策略
*/
nextStrategy?: string;
}
export interface LandTransferLedgerQuery extends PageQuery {
/**
* 项目ID
*/
@ -256,11 +263,8 @@ export interface LandTransferLedgerQuery extends PageQuery {
*/
nextStrategy?: string;
/**
* 日期范围参数
*/
params?: any;
/**
* 日期范围参数
*/
params?: any;
}

View File

@ -20,18 +20,20 @@ export const getMenu = (menuId: string | number): AxiosPromise<MenuVO> => {
};
// 查询菜单下拉树结构
export const treeselect = (): AxiosPromise<MenuTreeOption[]> => {
export const treeselect = (params?: any): AxiosPromise<MenuTreeOption[]> => {
return request({
url: '/system/menu/treeselect',
method: 'get'
method: 'get',
params
});
};
// 根据角色ID查询菜单下拉树结构
export const roleMenuTreeselect = (roleId: string | number): AxiosPromise<RoleMenuTree> => {
export const roleMenuTreeselect = (roleId: string | number, params?: any): AxiosPromise<RoleMenuTree> => {
return request({
url: '/system/menu/roleMenuTreeselect/' + roleId,
method: 'get'
method: 'get',
params
});
};

View File

@ -31,3 +31,20 @@ export function delOss(ossId: string | number | Array<string | number>) {
export function downLoadOss(ossId: { id?: string | number; idList?: string | number | Array<string | number> }, url: string, fileName: string) {
return download(url, ossId, fileName);
}
//识别身份证
export function recognizeidCard(data: any, type: any) {
return request({
url: '/contractor/constructionUser/idCard?idCardSide=' + type,
method: 'post',
data: data
});
}
//识别银行卡
export function recognizeBankCard(data: any) {
return request({
url: '/contractor/constructionUser/bankCard',
method: 'post',
data: data
});
}

View File

@ -147,10 +147,11 @@ export const authUserSelectAll = (data: any) => {
});
};
// 根据角色ID查询部门树结构
export const deptTreeSelect = (roleId: string | number): AxiosPromise<RoleDeptTree> => {
export const deptTreeSelect = (roleId: string | number, params?) => {
return request({
url: '/system/role/deptTree/' + roleId,
method: 'get'
method: 'get',
params
});
};

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.5 KiB

BIN
src/assets/images/break.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 40 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 37 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 35 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.4 KiB

BIN
src/assets/large/actual.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 23 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 24 KiB

BIN
src/assets/large/delay.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 26 KiB

BIN
src/assets/large/plan.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 26 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 248 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 652 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 665 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 104 KiB

View File

@ -53,7 +53,7 @@
style="margin-top: 10px"
v-for="(file, index) in fileList"
:key="file.uid"
class="el-upload-list__item upload-list__item-content"
class="el-upload-list__item ele-upload-list__item-content"
v-if="autoUpload"
>
<el-link :href="`${file.url}`" :underline="false" target="_blank">
@ -208,6 +208,7 @@ watch(
});
} else {
fileList.value = [];
return [];
}
},
@ -225,7 +226,12 @@ watch(
);
// 上传前校检格式和大小
const handleBeforeUpload = (file: any) => {
if (!validateFile(file)) return false;
if (!validateFile(file)) {
if (props.isGo) {
fileList.value = [];
}
return false;
}
proxy?.$modal.loading('正在上传文件,请稍候...');
number.value++;
return true;
@ -265,7 +271,6 @@ interface UploadFileWithOssId extends UploadFile {
}
const handleUploadSuccess = (res: any, file: UploadFileWithOssId) => {
console.log('🚀 ~ handleUploadSuccess ~ res:', res.code);
if (res.code === 200 || res.code === 0) {
console.log('上传成功');
// 上传成功,不管 data 是否为空
@ -276,6 +281,9 @@ const handleUploadSuccess = (res: any, file: UploadFileWithOssId) => {
});
} else {
console.log('失败', res);
if (props.isGo) {
fileList.value = [];
}
number.value--;
proxy?.$modal.closeLoading();
@ -299,7 +307,7 @@ const handleChange = (file: any, filelist: any) => {
}
}
// 记录 status = 'ready' 的文件
if (file.status === 'ready') {
if (file.status === 'ready' && !props.isConstruction) {
pendingFiles.value.push(file);
fileList.value = pendingFiles.value;
}
@ -310,8 +318,6 @@ const handleChange = (file: any, filelist: any) => {
// 删除文件
const handleRemove = (file: any, fileList: any) => {
console.log(11);
emit('handleRemove', file, fileList);
};
@ -329,12 +335,15 @@ const handleDelete = async (index: string | number, type?: string) => {
delOss(index);
fileList.value = fileList.value.filter((f) => f.ossId !== index);
} else {
let ossId = fileList.value[index].ossId;
delOss(ossId);
if (!props.isGo) {
let ossId = fileList.value[index].ossId;
delOss(ossId);
}
index = parseInt(index as string);
fileList.value.splice(index, 1);
}
} finally {
// fileList.value = [];
emit('handleRemove');
emit('update:modelValue', listToString(fileList.value));
}

View File

@ -41,7 +41,7 @@
</template>
<script setup lang="ts">
import { listByIds, delOss } from '@/api/system/oss';
import { listByIds, delOss, recognizeidCard, recognizeBankCard } from '@/api/system/oss';
import { OssVO } from '@/api/system/oss/types';
import { propTypes } from '@/utils/propTypes';
import { globalHeaders } from '@/utils/request';
@ -63,24 +63,37 @@ const props = defineProps({
type: Boolean,
default: true
},
isGo: {
type: Boolean,
default: false
},
// 图片上传路径
action: {
type: String,
default: ''
},
// 是否支持压缩,默认否
compressSupport: {
type: Boolean,
default: false
},
// 压缩目标大小单位KB。默认300KB以上文件才压缩并压缩至300KB以内
compressTargetSize: propTypes.number.def(300)
compressTargetSize: propTypes.number.def(300),
idCardType: {
type: String,
default: false
}
});
const { proxy } = getCurrentInstance() as ComponentInternalInstance;
const emit = defineEmits(['update:modelValue']);
const emit = defineEmits(['update:modelValue', 'success']);
const number = ref(0);
const uploadList = ref<any[]>([]);
const dialogImageUrl = ref('');
const dialogVisible = ref(false);
const baseUrl = import.meta.env.VITE_APP_BASE_API;
const uploadImgUrl = ref(baseUrl + '/resource/oss/upload'); // 上传的图片服务器地址
const baseUrl = props.isGo ? import.meta.env.VITE_APP_BASE_API_GO : import.meta.env.VITE_APP_BASE_API;
const uploadImgUrl = ref(baseUrl + props.action ? props.action : '/resource/oss/upload'); // 上传的图片服务器地址
const headers = ref(globalHeaders());
const fileList = ref<any[]>([]);
@ -121,7 +134,7 @@ watch(
);
/** 上传前loading加载 */
const handleBeforeUpload = (file: any) => {
const handleBeforeUpload = async (file: any) => {
let isImg = false;
if (props.fileType.length) {
let fileExtension = '';
@ -169,10 +182,32 @@ const handleExceed = () => {
};
// 上传成功回调
const handleUploadSuccess = (res: any, file: UploadFile) => {
const handleUploadSuccess = async (res: any, file: UploadFile) => {
if (res.code === 200) {
uploadList.value.push({ name: res.data.fileName, url: res.data.url, ossId: res.data.ossId });
uploadedSuccessfully();
if (props.idCardType) {
const formData = new FormData();
formData.append('file', file.raw); // 假设后端接收的字段名为file
if (props.idCardType === 'front' || props.idCardType === 'back') {
const res = await recognizeidCard(formData, props.idCardType);
if (res.code === 200) {
proxy?.$modal.msgSuccess('身份证识别成功');
emit('success', res.data);
} else {
proxy?.$modal.msgError('身份证识别失败');
}
}
if (props.idCardType === 'bank') {
const res = await recognizeBankCard(formData);
if (res.code === 200) {
proxy?.$modal.msgSuccess('银行卡识别成功');
emit('success', res.data);
} else {
proxy?.$modal.msgError('银行卡识别失败');
}
}
}
} else {
number.value--;
proxy?.$modal.closeLoading();
@ -201,6 +236,7 @@ const uploadedSuccessfully = () => {
fileList.value = fileList.value.filter((f) => f.url !== undefined).concat(uploadList.value);
uploadList.value = [];
number.value = 0;
console.log(listToString(fileList.value));
emit('update:modelValue', listToString(fileList.value));
proxy?.$modal.closeLoading();
}

View File

@ -170,8 +170,6 @@ onMounted(() => {
//分页
const getWaitingList = () => {
pageByTaskWait({ pageNum: 1, pageSize: 10 }).then((resp) => {
console.log(resp);
total.value = resp.total;
});
};

View File

@ -0,0 +1,427 @@
<template>
<div class="uploader-container" v-show="panelShow">
<div class="header">
<span>文件列表</span>
<span class="shrink" @click="closeHandle">
<el-icon style="vertical-align: middle"><DArrowRight /></el-icon>
</span>
</div>
<div class="box">
<uploader
ref="uploaderRef"
:options="options"
:file-status-text="handleFileStatusText"
:autoStart="true"
@file-added="onFileAdded"
@file-success="onFileSuccess"
@file-progress="onFileProgress"
@file-error="onFileError"
class="uploader-example"
>
<uploader-unsupport></uploader-unsupport>
<div v-show="false">
<uploader-btn ref="uploadBtn" :attrs="all">选择文件</uploader-btn>
<!-- <uploader-btn :attrs="image">选择图片</uploader-btn>
<uploader-btn :directory="true">选择文件夹</uploader-btn> -->
</div>
<uploader-list>
<template v-slot="props">
<ul class="file-list">
<li v-for="file in props.fileList" :key="file.id">
<uploader-file :ref="'file_' + file.id" :class="'file_' + file.id" :file="file" :list="true"></uploader-file>
</li>
<div class="no-file" v-if="!props.fileList.length">暂无待上传文件</div>
</ul>
</template>
</uploader-list>
</uploader>
</div>
</div>
</template>
<script>
import SparkMD5 from 'spark-md5';
import axios from 'axios';
import { bigUpload } from '@/store/modules/bigUpload';
const stores = bigUpload();
import { ElMessage, ElLoading } from 'element-plus';
const instance = axios.create({
baseURL: '',
timeout: 1000 * 60 * 60 * 24
});
import sign from '@/utils/sign.js';
import { getGoToken } from '@/utils/auth';
const BASE_URL = 'http://58.17.134.85:8920';
const acceptConfig = ['.zip', '.rar']; //文件
// const acceptConfig = {
// // image: ['gif', 'jpg', 'jpeg', 'png', 'bmp', 'webp'],
// // video: ['mp4', 'm3u8', 'rmvb', 'avi', 'swf', '3gp', 'mkv', 'flv'],
// // audio: ['mp3', 'wav', 'wma', 'ogg', 'aac', 'flac'],
// // document: ['doc', 'txt', 'docx', 'pages', 'epub', 'pdf', 'numbers', 'csv', 'xls', 'xlsx', 'keynote', 'ppt', 'pptx', 'zip'],
// // document: ['.zip', '.rar'],
// // all() {
// // return [...this.document];
// // },
// };
export default {
name: 'bigUploader',
data() {
return {
options: {
target: BASE_URL + '/zm/api/v1/system/bigUpload/upload', // 目标上传 URL(线上不加baseURL)
chunkSize: '2048000', // 分片大小
fileParameterName: 'upfile', //上传文件时文件的参数名,默认 file
maxChunkRetries: 3, //最大自动失败重试上传次数
testChunks: true, //是否开启服务器分片校验
// 服务器分片校验函数,秒传及断点续传基础
// 可选的函数用于根据 XHR 响应内容检测每个块是否上传成功了传入的参数是Uploader.Chunk 实例以及请求响应信息。
// 这样就没必要上传(测试)所有的块了
checkChunkUploadedByResponse: function (chunk, message) {
// try {
// let objMessage = JSON.parse(message);
// const { code, data } = objMessage;
// console.log(code);
// if (code === 0) {
// if (data.skipUpload) {
// return true;
// }
// console.log((data.uploaded || []).indexOf(chunk.offset + 1));
// return (data.uploaded || []).indexOf(chunk.offset + 1) >= 0;
// }
// } catch (e) {
// console.error(e);
// }
return false;
},
headers: {
Authorization: null
},
query: (file, chunk) => {
return {
...file.params
};
}
},
image: {
accept: 'image/*'
},
all: {
accept: []
},
statusText: {
success: '成功了',
error: '出错了',
uploading: '上传中',
paused: '暂停中',
waiting: '等待中'
},
uploadType: '', //
uploadTypesList: [
// 上传区分 安全考试
{ id: 1000, label: '安全考试上传' },
{ id: 1001, label: '工资资料上传' },
{ id: 1002, label: '工资资料模板上传' },
{ id: 1003, label: '竣工图上传' },
{ id: 1003, label: '竣工图上传' },
{ id: 1004, label: '倾斜模板上传' },
{ id: 1005, label: '员工资料上传' },
{ id: 1006, label: '可研及专题报告' },
{ id: 1007, label: '施工图' },
{ id: 10000, label: '大文件上传' },
{ id: 1008, label: '质量会议上传' },
{ id: 1010, label: '安全会议上传' }
],
acceptList: [], //需要上传的类型
uploadTypes: ''
};
},
mounted() {
this.$nextTick(() => {
console.log('挂载', getGoToken());
this.mittBus.on('bigUploader.uploadFile', this.uploadFile);
});
},
computed: {
panelShow() {
return stores.panelShow;
},
uploadBtn() {
return this.$refs.uploadBtn && this.$refs.uploadBtn.btn;
}
},
methods: {
openHandle() {
stores.setPanelShow(true);
},
closeHandle() {
this.$refs.uploaderRef.uploader.files = [];
this.$refs.uploaderRef.uploader.fileList = [];
stores.setPanelShow(false);
},
uploadFile(obj) {
this.uploadType = obj.type;
this.uploadTypes = obj.types;
if (!this.options.headers.Authorization) {
this.options.headers.Authorization = 'Bearer ' + getGoToken();
}
// 修改accept值
if (this.uploadBtn) {
this.uploadBtn.querySelector('input').accept = obj.accept;
}
if (this.uploadBtn) {
this.$nextTick(() => {
this.uploadBtn.click();
});
}
},
handleFileStatusText(status, response) {
if (status === 'success') {
const { code, data } = response;
if (code === 0 && data.needMerge === true) {
return '文件合并中...';
} else {
return this.statusText[status];
}
} else {
return this.statusText[status];
}
},
//上传过程中出错了
onFileError(rootFile, file, response, chunk) {
console.error(rootFile, file, response, chunk);
},
// 设置自定义状态
setStatus(id, text) {
this.$nextTick(() => {
if (this.$refs['file_' + id]) {
const el = this.$refs['file_' + id][0].$el.getElementsByClassName('uploader-file-status')[0].getElementsByTagName('span')[0];
const parent = el.parentNode;
const para = document.createElement('span');
para.appendChild(document.createTextNode(text));
para.className = 'para';
el.style.display = 'none';
parent.appendChild(para);
}
});
},
// 删除自定义状态
removeStatus(id) {
try {
const els = this.$refs['file_' + id][0].$el.getElementsByClassName('uploader-file-status')[0].getElementsByClassName('para');
if (els && els.length > 0) {
const parent = els[0].parentNode;
for (let i = 0; i < els.length; i++) {
parent.removeChild(els[i]);
}
}
const firstSpan = this.$refs['file_' + id][0].$el.getElementsByClassName('uploader-file-status')[0].getElementsByTagName('span')[0];
firstSpan.style.display = '';
} catch (e) {
console.error(e);
}
},
/**
文件上传成功事件
第一个参数 rootFile 就是成功上传的文件所属的根 Uploader.File 对象,它应该包含或者等于成功上传文件;
第二个参数 file 就是当前成功的 Uploader.File 对象本身;
第三个参数 message 就是服务端响应内容,永远都是字符串;
第四个参数 chunk 就是 Uploader.Chunk 实例, 它就是该文件的最后一个块实例如果你想得到请求响应码的话chunk.xhr.status 就是。
*/
onFileSuccess(rootFile, file, response, chunk) {
try {
let res = JSON.parse(response);
const { code, data } = res;
if (code === 0) {
// 如果服务端返回需要合并
if (data.needMerge) {
// 文件合并操作
let obj = {
identifier: data.identifier,
totalChunks: data.totalChunks,
totalSize: data.totalSize,
filename: data.filename,
token: getGoToken()
};
if (this.uploadType) {
//后台需要的参数
obj.num = '1'.toString();
}
if (this.uploadType == 3 || this.uploadType == 100 || this.uploadType == 101 || this.uploadType == 102) {
//后台需要的参数
obj.num = '2'.toString();
}
let header = {
Authorization: 'Bearer ' + getGoToken(),
...sign(obj)
};
// 请求合并
instance
.post('/zm/api/v1/system/bigUpload/uploadMerge', obj, {
headers: header
})
.then((res) => {
const { status, data } = res;
return data;
})
.then((res) => {
let { code, data } = res;
if (code === 0) {
this.setStatus(file.id, this.statusText['success']);
this.setMittBus(data, file);
}
});
} else {
// 不需要合并
// 秒传或普通上传
this.setMittBus(data, file);
}
}
} catch (e) {
console.error(e);
}
},
// 返回响应请求
setMittBus(data, file) {
let index = '';
this.uploadTypesList.forEach((item) => {
if (item.id == this.uploadTypes) {
index = this.uploadTypes;
}
});
console.log(data);
console.log(file);
this.mittBus.emit('bigUploader.uploadFileSuccess' + index, { ...data, fileType: file.fileType });
},
// 一个文件在上传中
onFileProgress(rootFile, file, chunk) {
// 上传过程中
// console.log(`上传中 ${file.name}chunk${chunk.startByte / 1024 / 1024} ~ ${chunk.endByte / 1024 / 1024}`);
},
// 这个事件一般用作文件校验,如果说返回了 false那么这个文件就会被忽略不会添加到文件上传列表中。
onFileAdded(file) {
this.computeMD5(file);
// 将额外的参数赋值到每个文件上解决了不同文件使用不同params的需求
if (this.uploadType) {
//后台需要的参数
let num = '1'.toString();
if (this.uploadType == 3) {
//后台需要的参数
num = '2'.toString();
} else if (this.uploadType == 100 || this.uploadType == 101 || this.uploadType == 102) {
//竣工图文件上传
num = '2'.toString();
}
file.params = { ...this.params, num };
} else {
file.params = { ...this.params };
}
this.openHandle();
},
computeMD5(file) {
let fileReader = new FileReader();
let time = new Date().getTime();
let blobSlice = File.prototype.slice || File.prototype.mozSlice || File.prototype.webkitSlice;
// 分片序号
let currentChunk = 0;
// 分片大小
const chunkSize = 10 * 1024 * 1000;
// 分片总数量
let chunks = Math.ceil(file.size / chunkSize);
let spark = new SparkMD5.ArrayBuffer();
this.setStatus(file.id, 'md5计算中');
file.pause();
loadNext();
fileReader.onload = (e) => {
spark.append(e.target.result);
if (currentChunk < chunks) {
currentChunk++;
loadNext();
// 实时展示MD5的计算进度
this.$nextTick(() => {
const loading = ElLoading.service({
lock: true,
text: '正在文件检验中……',
background: 'rgba(0, 0, 0, 0.7)'
});
if (((currentChunk / chunks) * 100).toFixed(0) == 100) {
loading.close();
}
// console.log('校验MD5 ' + ((currentChunk / chunks) * 100).toFixed(0) + '%');
});
} else {
let md5 = spark.end();
this.computeMD5Success(md5, file);
this.removeStatus(file.id);
// console.log(`MD5计算完毕${file.name} \nMD5${md5} \n分片${chunks} 大小:${file.size} 用时:${new Date().getTime() - time} ms`);
}
};
fileReader.onerror = function () {
// console.error();
ElMessage.error(`文件${file.name}读取出错,请检查该文件`);
file.cancel();
};
function loadNext() {
let start = currentChunk * chunkSize;
let end = start + chunkSize >= file.size ? file.size : start + chunkSize;
fileReader.readAsArrayBuffer(blobSlice.call(file.file, start, end));
}
},
// md5 计算完毕
computeMD5Success(md5, file) {
file.uniqueIdentifier = md5;
file.resume();
}
}
};
</script>
<style scoped lang="scss">
.uploader-min {
background-color: #fff;
z-index: 9999;
position: absolute;
right: 0;
bottom: 10px;
box-shadow: 0 0 10px rgba(0, 0, 0, 0.4);
padding: 15px;
cursor: pointer;
}
.uploader-container {
background-color: #fff;
z-index: 9999;
position: absolute;
right: 0;
bottom: 10px;
box-shadow: 0 0 10px rgba(0, 0, 0, 0.4);
}
.header {
background-color: #fff;
height: 35px;
line-height: 35px;
display: flex;
padding: 0 10px;
justify-content: space-between;
.shrink {
cursor: pointer;
}
}
.box {
max-height: 200px;
overflow-y: scroll;
}
.uploader-example {
width: 550px;
padding: 15px;
font-size: 12px;
}
.uploader-example .uploader-btn {
margin-right: 4px;
}
.uploader-example .uploader-list {
overflow-x: hidden;
overflow-y: hidden;
}
</style>

View File

@ -0,0 +1,244 @@
<template>
<div class="up-img" v-if="limit > 1">
<el-upload
v-model:file-list="dataFileList"
:limit="limit"
:action="action"
:multiple="multiple"
:list-type="listType"
:on-success="handleAvatarSuccess"
:on-preview="handlePictureCardPreview"
:on-remove="handleRemove"
:on-exceed="handleExceed"
:before-upload="beforeAvatarUpload"
:data="dataParam"
:name="fileName"
:headers="headers"
ref="elUploadRef"
>
<el-icon><Plus /></el-icon>
</el-upload>
<el-dialog v-model="dialogVisible">
<img w-full :src="dialogImageUrl" alt="Preview Image" />
</el-dialog>
</div>
<div v-else>
<div class="up-img">
<el-upload
ref="elUploadRef"
v-model:file-list="dataFileList"
:limit="limit"
class="avatar-uploader"
:action="action"
:show-file-list="false"
:on-success="handleAvatarSuccess"
:before-upload="beforeAvatarUpload"
:on-preview="handlePictureCardPreview"
:on-remove="handleRemove"
:on-exceed="handleExceed"
:data="dataParam"
:name="fileName"
:headers="headers"
>
<img v-if="imageUrl" :src="imageUrl" class="avatar" />
<el-icon v-else class="avatar-uploader-icon"><Plus /></el-icon>
</el-upload>
</div>
</div>
</template>
<script lang="ts">
import { defineComponent, ref, computed, getCurrentInstance, reactive, toRefs } from 'vue';
import type { UploadProps, UploadUserFile, UploadInstance } from 'element-plus';
import { ElMessage, genFileId } from 'element-plus';
import _ from 'lodash';
import sign from '@/utils/sign.js';
export default defineComponent({
name: 'uploadImg',
props: {
action: { type: String, default: '' }, //上传地址
name: { type: String, default: 'file' }, //上传文件类型
limit: { type: Number, default: 1 }, //上传最大数量
method: { type: String, default: 'post' }, //设置上传请求方法
multiple: { type: Boolean, default: true }, //是否支持多选文件
showFileList: { type: Boolean, default: true }, //是否显示已上传文件列表
drag: { type: Boolean, default: false }, //是否启用拖拽上传
accept: { type: String, default: '' }, //接受上传的文件类型格式
disabled: { type: Boolean, default: false }, //是否是否禁止上传
listType: { type: String, default: 'picture-card' }, //是否启用拖拽上传
uploadSize: { type: Number, default: 100 }, //上传文件大小
modelValue: {
type: Array,
default: function () {
return [];
}
},
uploadData: { type: Object, default: {} },
fileName: {
type: String,
default: 'file'
}
},
setup(props, { emit }) {
const baseURL: string | undefined | boolean = import.meta.env.VITE_APP_BASE_API_GO;
const { proxy } = getCurrentInstance() as any;
const token = proxy?.$cache.local.get('goToken');
const dialogImageUrl = ref('');
const elUploadRef = ref<UploadInstance>();
const dialogVisible = ref(false);
const imageUrl = ref('');
const state = reactive({
fileName: props.fileName
});
const headers = reactive({
Authorization: 'Bearer ' + token,
...sign({ token: token, ...props.uploadData })
});
const dataParam = reactive({
token: token,
...props.uploadData
});
let uploadedFile: Array<any> = [];
const dataFileList = computed({
get: () => {
let value: Array<UploadUserFile> = (props.modelValue as UploadUserFile[]) || [];
if (value.length) {
value.map((item: UploadUserFile) => {
if (item.url) {
// item.url = proxy.getUpFileUrl(item.url);
}
return item;
});
}
uploadedFile = _.cloneDeep(value);
return value;
},
set: (val) => {
emit('uploadData', val);
}
});
const beforeAvatarUpload: UploadProps['beforeUpload'] = (rawFile) => {
if (rawFile.type.substring(0, 5) !== 'image') {
ElMessage.error('请上传图片文件');
return false;
} else if (rawFile.size / 1024 / 1024 > props.uploadSize) {
ElMessage.error('上传文件超过' + props.uploadSize + 'M');
return false;
}
return true;
};
const handleRemove: UploadProps['onRemove'] = (file) => {
uploadedFile.splice(
uploadedFile.findIndex((item: any) => item.uid === file.uid),
1
);
setDataFileList();
};
const handleExceed = (files) => {
elUploadRef.value!.clearFiles();
const file = files[0];
file.uid = genFileId();
elUploadRef.value!.handleStart(file);
elUploadRef.value!.submit();
// ElMessage.error('最多可上传' + props.limit + '个文件,已超出最大限制数。');
};
const handlePictureCardPreview: UploadProps['onPreview'] = (uploadFile) => {
dialogImageUrl.value = uploadFile.url!;
dialogVisible.value = true;
};
const handleAvatarSuccess: UploadProps['onSuccess'] = (response, uploadFile) => {
emit('uploadImageAuth', response); //返回认证的数据
if (props.limit == 1) {
uploadedFile = [];
imageUrl.value = URL.createObjectURL(uploadFile.raw!);
}
uploadedFile = uploadedFile.filter((item: UploadUserFile) => {
return item.raw?.uid != uploadFile.raw?.uid;
});
if (response.code === 0) {
// if (response.data.name) {
// uploadedFile.push({
// // 单图
// name: response.data.name,
// url: response.data.path,
// fileType: response.data.type,
// size: response.data.size,
// });
// } else {
// console.log(response.data);
// if (response.data.list) {
// uploadedFile.push({
// // 多图
// name: response.data.list[0].name,
// url: response.data.list[0].path,
// fileType: response.data.list[0].type,
// size: response.data.list[0].size,
// });
// return;
// }
uploadedFile.push({
// 多图
name: response.data[0].name,
url: response.data[0].path,
fileType: response.data[0].type,
size: response.data[0].size
});
// }
setDataFileList();
} else {
ElMessage.error(response.message);
imageUrl.value = '';
}
emit('uploadImageAuth1', uploadedFile); //返回认证的数据
};
const setDataFileList = () => {
dataFileList.value = uploadedFile;
};
return {
dataFileList,
imageUrl,
baseURL,
dialogVisible,
dialogImageUrl,
handleExceed,
beforeAvatarUpload,
handleRemove,
handlePictureCardPreview,
handleAvatarSuccess,
dataParam,
headers,
elUploadRef,
...toRefs(state)
};
}
});
</script>
<style scoped>
.up-img :deep(.avatar-uploader .avatar) {
width: 178px;
height: 178px;
display: block;
}
.up-img :deep(.avatar-uploader .el-upload) {
border: 1px dashed var(--el-border-color);
border-radius: 6px;
cursor: pointer;
position: relative;
overflow: hidden;
transition: var(--el-transition-duration-fast);
}
.up-img :deep(.avatar-uploader .el-upload:hover) {
border-color: var(--el-color-primary);
}
.up-img :deep(.el-icon.avatar-uploader-icon) {
font-size: 28px;
color: #8c939d;
width: 178px;
height: 178px;
text-align: center;
}
</style>

View File

@ -7,6 +7,7 @@
<template #title>
<span class="menu-title" :title="hasTitle(onlyOneChild.meta.title)">{{ onlyOneChild.meta.title }}</span>
<span class="bage" v-if="onlyOneChild.meta?.title == '我的待办' && total > 0">{{ total }}</span>
<span class="bage" v-if="onlyOneChild.meta?.title == '我的抄送' && totalChao > 0">{{ totalChao }}</span>
</template>
</el-menu-item>
</app-link>
@ -16,7 +17,7 @@
<template v-if="item.meta" #title>
<svg-icon :icon-class="item.meta ? item.meta.icon : ''" />
<span class="menu-title" :title="hasTitle(item.meta?.title)">{{ item.meta?.title }}</span>
<!-- <span class="bage" v-if="item.meta?.title == '我的任务' && total >= 0">{{ total }}</span> -->
<span class="bage" v-if="item.meta?.title == '我的任务' && total + totalChao > 0">{{ total + totalChao }}</span>
</template>
<sidebar-item
@ -36,7 +37,7 @@ import { isExternal } from '@/utils/validate';
import AppLink from './Link.vue';
import { getNormalPath } from '@/utils/ruoyi';
import { RouteRecordRaw } from 'vue-router';
import { pageByTaskWait } from '@/api/workflow/task';
import { pageByTaskWait, pageByTaskCopy } from '@/api/workflow/task';
import useUserStore from '@/store/modules/user';
import useNoticeStore from '@/store/modules/notice';
const userStore = useUserStore();
@ -56,21 +57,28 @@ const props = defineProps({
}
});
const total = ref(0);
const totalChao = ref(0);
onMounted(() => {
if (onlyOneChild.value.meta?.title == '我的待办' || props.item.meta?.title == '我的任务') {
console.log(44444444);
getWaitingList();
getChaoList();
}
if (onlyOneChild.value.meta?.title == '我的抄送') {
getChaoList();
}
});
// 获取我的待办
//分页
const getWaitingList = () => {
pageByTaskWait({ pageNum: 1, pageSize: 10 }).then((resp) => {
console.log(resp);
total.value = resp.total;
});
};
// 获取我的抄送
const getChaoList = () => {
pageByTaskCopy({ pageNum: 1, pageSize: 10 }).then((resp) => {
totalChao.value = resp.total;
});
};
const onlyOneChild = ref<any>({});
const hasOneShowingChild = (parent: RouteRecordRaw, children?: RouteRecordRaw[]) => {
@ -123,9 +131,7 @@ const hasTitle = (title: string | undefined): string => {
watch(
() => noticeStore.state.value.notices,
(newVal) => {
if (onlyOneChild.value.meta?.title == '我的待办') {
console.log(121212121);
if (onlyOneChild.value.meta?.title == '我的待办' || props.item.meta?.title == '我的任务') {
let time = setTimeout(() => {
getWaitingList();
clearTimeout(time);

View File

@ -61,6 +61,7 @@ setLocal('dockSocketUrl', 'ws://58.17.134.85:9512/websocket');
ElDialog.props.closeOnClickModal.default = false;*/
// **main.js**
import { vue3ScrollSeamless } from 'vue3-scroll-seamless';
import uploader from 'vue-simple-uploader';
import bus from './utils/bus';
import $message from '@/plugins/modal';
@ -74,6 +75,8 @@ app.use(print);
app.use(i18n);
app.use(VXETable);
app.use(plugins);
app.use(uploader);
app.use(bus);
app.component('vue3ScrollSeamless', vue3ScrollSeamless);
// 自定义指令

View File

@ -9,7 +9,7 @@ import animate from '@/animate';
import { download as dl } from '@/utils/request';
import { useDict } from '@/utils/dict';
import { getConfigKey, updateConfigByKey } from '@/api/system/config';
import { parseTime, addDateRange, handleTree, selectDictLabel, selectDictLabels } from '@/utils/ruoyi';
import { parseTime, addDateRange, handleTree, selectDictLabel, selectDictLabels,formatPrice } from '@/utils/ruoyi';
import { downloadFile } from '@/utils/useFileDownload';
import { App } from 'vue';
@ -42,4 +42,5 @@ export default function installPlugin(app: App) {
app.config.globalProperties.selectDictLabels = selectDictLabels;
app.config.globalProperties.animate = animate;
app.config.globalProperties.downloadFile = downloadFile;
app.config.globalProperties.formatPrice = formatPrice;
}

View File

@ -72,9 +72,15 @@ export const constantRoutes: RouteRecordRaw[] = [
component: () => import('@/views/error/401.vue'),
hidden: true
},
{
path: '/ProjectScreen',
component: () => import('@/views/ProjectScreen/index.vue'),
component: () => import('@/views/projectLarge/ProjectScreen/index.vue'),
hidden: true
},
{
path: '/digitalizationScreen',
component: () => import('@/views/enterpriseLarge/digitalizationScreen/index.vue'),
hidden: true
},
{

View File

@ -45,7 +45,9 @@ export const usePermissionStore = defineStore('permission', () => {
sidebarRouters.value = routes;
};
const generateRoutes = async (): Promise<RouteRecordRaw[]> => {
const res = await getRouters(useUserStoreHook().selectedProject?.id || '0');
const id = useUserStoreHook().selectedProject ? useUserStoreHook().selectedProject.id : '0';
console.log('🚀 ~ generateRoutes ~ useUserStoreHook().selectedProject?.id:', id);
const res = await getRouters(id);
const { data } = res;
const sdata = JSON.parse(JSON.stringify(data));
const rdata = JSON.parse(JSON.stringify(data));

View File

@ -10,6 +10,10 @@ export const setToken = (access_token: string) => (tokenStorage.value = access_t
export const removeToken = () => (tokenStorage.value = null);
export const getGoToken = () => {
return getLocal('goToken');
};
export const getDockSocketUrl = () => {
return getLocal('dockSocketUrl');
};

212
src/utils/exportExcel.ts Normal file
View File

@ -0,0 +1,212 @@
import { exportSalary } from '@/api/project/projectTeam';
import { exportDataToExcel } from '@/utils/exportDataToExcel.js';
export function useExcelExport() {
// 数据整合函数
const exportConfig = (obj, proxy, times) => {
// 如果导出前要处理数据,需要深克隆一份表格数据,然后进行处理
let time = proxy.parseTime(new Date(times), '{y}年{m}月'); // 当前年月
let header1 = ['建筑施工企业现场人员考勤表(' + time + ''];
let projectName = '项目部名称:' + obj.projectName;
let teamName = '班组类别:' + obj.teamName;
let header2 = [];
let header3 = [projectName + ' ' + teamName];
const header = ['序号', '姓名/日期', '身份证号'];
let columnsWidth = [6, 10, 26]; // 表格宽度
let obj1 = { index: '', name: '', identity_card: '' };
let fields = ['index', 'row', 'identity_card'];
// 计算当前月天数
let years = times.split('-')[0];
let month = times.split('-')[1];
let listLength = new Date(years, month, 0).getDate();
for (let index = 0; index < listLength; index++) {
obj1['day' + index] = '';
fields.push('day' + index);
header.push(index + 1);
columnsWidth.push(4);
}
header.push('合计');
fields.push('sum');
header.push('是否离场');
fields.push('type');
header.push('签字');
fields.push('sign');
// 上方共用
let data = [];
if (!(obj.team && obj.team.length)) return;
obj.team.forEach((item, index) => {
let obj = { row: '', index: '', identity_card: '' };
for (let key in item.attendance) {
let j = parseInt(key.split('-')[2]) - 1;
obj['day' + j] = item.attendance[key];
}
obj.row = item.row;
obj.index = index + 1;
obj.identity_card = item.identity_card;
let start = ''; // 从表格那一列哪一行开始
let end = ''; // 从表格那一列哪一行结束
let cols = 5 + index; // 行数
start = 'D' + cols;
// 判断当月天数 获取表格中最后一天的列标识
if (listLength == 28) {
end = 'AE' + cols;
} else if (listLength == 29) {
end = 'AF' + cols;
} else if (listLength == 30) {
end = 'AG' + cols;
} else {
end = 'AH' + cols;
}
obj.sum = { formula: 'SUM(' + start + ':' + end + ')', result: 0 };
obj.sign = '';
obj.type = item.type ? '离场' : '未离场';
data.push(obj);
});
const merges = [
// 单元格合并
{ row: 0, col: 0, rowspan: 1, colspan: listLength + 5 },
{ row: 2, col: 0, rowspan: 1, colspan: listLength + 5 },
{ row: obj.team.length + 5, col: 0, rowspan: 1, colspan: 3 },
{ row: obj.team.length + 5, col: 3, rowspan: 1, colspan: 10 },
{ row: obj.team.length + 5, col: 13, rowspan: 1, colspan: 10 },
{ row: obj.team.length + 5, col: 23, rowspan: 1, colspan: 10 }
];
data.push({});
// 表格尾部标题
data.push({
index: '制表人:',
day0: '班组负责人',
day10: '项目负责人',
day20: '制表日期'
});
data.push({
index: '注:',
row: '1、本考勤表必须按照每日实际工时进行填写'
});
data.push({
row: '2、本考勤表作为工资计发的重要依据。'
});
const config = {
data,
fields,
headers: [header1, header2, header3, header],
merges,
attrs: [],
view: [],
columnsWidth,
sheetName: obj.teamName
};
// 设置全表单元格边框,居中布局
config.attrs.push({
rowStart: 3,
rowEnd: config.data.length - 1,
colStart: 0,
colEnd: config.fields.length - 1,
attr: {
alignment: { vertical: 'middle', horizontal: 'center' },
border: {
top: { style: 'thin' },
left: { style: 'thin' },
bottom: { style: 'thin' },
right: { style: 'thin' }
}
}
});
// 设置表头字体加粗
config.attrs.push({
rowStart: 0,
rowEnd: 0,
colStart: 0,
colEnd: config.fields.length - 1,
attr: {
alignment: { vertical: 'middle', horizontal: 'center' },
font: {
bold: true,
size: '16'
}
}
});
config.attrs.push({
rowStart: 2,
rowEnd: 2,
colStart: 0,
colEnd: config.fields.length - 1,
attr: {
alignment: { vertical: 'middle', horizontal: 'center' }
}
});
return config;
};
// 导出函数
const exportExcel = async (obj, proxy, name = undefined) => {
try {
const res = await exportSalary(obj);
if (res.code === 0 && res.data.AttendanceAllOne) {
let config = [];
let AttendanceAllOne = res.data.AttendanceAllOne;
// 处理每个表格
AttendanceAllOne.forEach((item) => {
let datas = exportConfig(item, proxy, obj.years);
if (datas) {
config.push(datas);
}
});
// 获取项目名
let projectName = '';
if (name) {
projectName = res.data.AttendanceAllOne[0].projectName + '-' + name;
} else {
projectName = res.data.AttendanceAllOne[0].projectName;
}
let year = obj.years.split('-')[0];
let month = obj.years.split('-')[1];
// 导出Excel
exportDataToExcel(config, `${projectName}-${year}${month}月考勤表.xlsx`);
} else if (res.code === 0) {
ElMessage({
message: '暂无考勤数据',
type: 'warning'
});
} else {
ElMessage({
message: res.message || '导出失败',
type: 'error'
});
}
} catch (error) {
ElMessage({
message: '导出过程出错',
type: 'error'
});
console.error('Excel导出错误:', error);
}
};
return {
exportConfig,
exportExcel
};
}

View File

@ -5,8 +5,6 @@ import { ProjectTeamVO } from '@/api/project/projectTeam/types';
import useUserStore from '@/store/modules/user';
export const getProjectTeam = async () => {
const isPermission = useUserStore().permissions.some((item) => item == 'project:team:list');
console.log(useUserStore().permissions);
if (!isPermission && useUserStore().permissions[0] != '*:*:*') return;
const { goId } = $cache.local.getJSON('selectedProject');

View File

@ -1,51 +1,272 @@
import $cache from '@/plugins/cache';
import useUserStore from '@/store/modules/user';
import request from '@/utils/request';
import axios from 'axios';
import sign from '@/utils/sign.js';
import CryptoJS from 'crypto-js';
/**
* 包装 request 请求,统一使用 Go 服务地址作为 baseURL
* @param config 原始请求配置
*/
const BASE_GO_URL = import.meta.env.VITE_APP_BASE_API_GO;
const token = $cache.local.get('goToken');
interface RequestGo extends Function {
(config: any): Promise<any>;
download?: (url: string, params: any, filename: string) => void;
}
const requestGo: RequestGo = (config: any) => {
return request({
baseURL: BASE_GO_URL,
...config,
headers: {
'Authorization': `Bearer ${$cache.local.get('goToken') || ''}`
// 加密密钥
const corySecretKey = 'happyCoryOrTieHanHan202410151415';
// 配置新建一个 axios 实例
const service = axios.create({
baseURL: BASE_GO_URL as any,
timeout: 120000,
headers: { 'Content-Type': 'application/json' }
});
// 不需要修改项目id的接口数组
const whiteUrl = [
'/api/wxApplet/wxApplet/sysProjectTeam/list',
'/api/wxApplet/wxApplet/sysProjectTeam/add',
'/api/wxApplet/wxApplet/sysProjectTeam/edit',
'/api/v1/test/testFollowInfo/add',
'/api/wxApplet/wxApplet/busConstructionUser/changePay',
// 获取项目资料文件夹
'/api/v1/system/documentData/treeStructureData',
'/api/v1/system/busConstructionUser/exportSalary',
'/api/v1/system/busSalaryDetails/list',
'/api/v1/system/ys7Devices/add',
'/api/v1/system/ys7Devices/edit',
'/api/v1/system/subProject/add',
'/api/v1/system/subProject/edit',
'/api/v1/system/subProject/list',
'/api/v1/system/workStatus/getTree',
'/api/v1/system/sysProjectIntroduce/list',
'/api/v1/system/sysProjectIntroduce/add',
'/api/v1/system/sysProjectIntroduce/edit',
'/video/hat/manage/api/v1/video/device/list',
'/video/hat/manage/api/v1/video/project/bind',
'/api/v1/system/notifications/publish',
'/api/v1/system/notifications/list',
'/api/v1/system/notifications/edit',
'/webodm/api/v1/taskCreate',
'/webodm/api/v1/taskProcess',
'/webodm/api/v1/download',
'/api/v1/system/manageTaskRecord/upDataResource',
'/api/v1/system/ys7Devices/list',
'/api/v1/system/busFolderFile/add',
'/api/v1/system/manageTaskRecordResource/voluntarilyReq',
'/api/v1/system/busAttendanceMachine/edit',
'/api/v1/system/qianqiFangzhen/add',
'/api/v1/system/qianqiNibianqi/add'
];
const exceptionStr = '/api/v1/test/'; // /api/v1/test/*接口拦截
// 添加请求拦截器
service.interceptors.request.use(
(config: any) => {
// 在发送请求之前做些什么 token
if (token) {
config.headers = config.headers || {};
(config.headers as any)['Authorization'] = `Bearer ${token}`;
console.log('🚀 ~ config.headers:', config.headers);
}
});
};
const stores = useUserStore();
if (!whiteUrl.includes(config.url) && !config.url.includes(exceptionStr)) {
if (config.params && Reflect.has(config.params, 'projectId')) {
config.params.projectId = stores.selectedProject.goId;
}
// 处理FormData中的projectId
if (config.data instanceof FormData && config.data.has('projectId')) {
config.data.set('projectId', stores.selectedProject.goId);
}
}
let dataInfoReq = {};
if (config.method === 'get' || config.method === 'delete') {
config.params = config.params || {};
dataInfoReq = JSON.parse(JSON.stringify(config.params));
const encryptedParam = encryptAES256(JSON.stringify(dataInfoReq), corySecretKey);
if ($cache.local.get('i18n') != null) {
config.params = { coryKey: encryptedParam, corySimplifiedToTraditional: $cache.local.get('i18n') };
} else {
config.params = { coryKey: encryptedParam };
}
} else {
// 处理FormData类型
if (config.data instanceof FormData) {
// 将FormData转换为普通对象
dataInfoReq = Object.fromEntries(config.data.entries());
// 重新创建一个新的FormData实例
const newFormData = new FormData();
const encryptedData = encryptAES256(JSON.stringify(dataInfoReq), corySecretKey);
requestGo.download = function (url: string, params: any, filename: string, method: 'post' | 'get' = 'post') {
return request({
url,
method: method,
baseURL: BASE_GO_URL,
data: method === 'post' ? params : undefined,
params: method === 'get' ? params : undefined,
headers: {
'Authorization': `Bearer ${$cache.local.get('goToken') || ''}`
},
responseType: 'blob'
}).then((response) => {
// ✅ 只取 response.data
const blob = new Blob([response.data]);
const link = document.createElement('a');
link.style.display = 'none';
link.href = URL.createObjectURL(blob);
link.setAttribute('download', filename);
document.body.appendChild(link);
link.click();
document.body.removeChild(link);
URL.revokeObjectURL(link.href);
});
};
newFormData.append('coryKey', encryptedData);
if ($cache.local.get('i18n') != null) {
newFormData.append('corySimplifiedToTraditional', $cache.local.get('i18n'));
}
export default requestGo;
// 如果有文件,需要重新添加
for (let [key, value] of config.data.entries()) {
if (value instanceof File) {
newFormData.append(key, value);
}
}
config.data = newFormData;
// 设置Content-Type为undefined让浏览器自动设置boundary
config.headers['Content-Type'] = undefined;
} else {
dataInfoReq = config.data;
const encryptedData = encryptAES256(JSON.stringify(dataInfoReq), corySecretKey);
if ($cache.local.get('i18n') != null) {
config.data = { coryKey: encryptedData, corySimplifiedToTraditional: $cache.local.get('i18n') };
} else {
config.data = { coryKey: encryptedData };
}
}
}
const { timestamp, nonce, sign: signature } = sign(dataInfoReq);
config.headers.timestamp = timestamp;
config.headers.nonce = nonce;
config.headers.sign = signature;
return config;
},
(error) => {
// 对请求错误做些什么
return Promise.reject(error);
}
);
// 添加响应拦截器
service.interceptors.response.use(
(response) => {
// 对响应数据进行解密操作
try {
// 处理特殊情况data为空值或不需要解密的情况
if (response.data.data === null || response.data.data === '' || response.data.data === undefined) {
return response.data;
}
// 检查响应数据格式
if (typeof response.data.data !== 'string') {
// 尝试将非字符串数据转换为字符串
try {
response.data.data = JSON.stringify(response.data.data);
} catch (convertError) {
throw new Error('响应数据格式不正确,无法转换为字符串');
}
}
// 执行解密
const decryptedData = decryptAES256(response.data.data, corySecretKey);
// 正确处理解密后的数据
if (decryptedData && typeof decryptedData === 'object') {
// 保持response.data的结构不变只替换data字段的内容
response.data = {
...response.data,
data: decryptedData
};
} else {
// 如果解密后的数据不是对象,可能需要特殊处理
response.data.data = decryptedData;
}
if (response.data.code !== 0) {
ElMessage.error(response.data.message);
}
return response.data;
} catch (decryptError) {
// 提供更友好的错误信息
if (decryptError.message.includes('无效的Base64格式')) {
ElMessage.error('数据格式错误:接收到无效的加密数据');
} else {
ElMessage.error('数据解密失败,请联系管理员');
}
return Promise.reject(decryptError);
}
},
(error) => {
// 对响应错误做点什么
if (error.message.indexOf('timeout') !== -1) {
ElMessage.error('网络超时');
} else if (error.message === 'Network Error') {
ElMessage.error('网络连接错误');
} else {
console.log(error, '网络错误');
if (error.response.data) ElMessage.error(error.response.statusText);
else {
ElMessage.error('接口路径找不到');
console.log(error, '接口路径找不到');
}
}
return Promise.reject(error);
}
);
// 加密函数
function encryptAES256(plainText: string, key: string): string | null {
try {
const parsedKey = CryptoJS.enc.Utf8.parse(key);
const iv = CryptoJS.lib.WordArray.random(16);
const plainTextWordArray = CryptoJS.enc.Utf8.parse(plainText);
const encrypted = CryptoJS.AES.encrypt(plainTextWordArray, parsedKey, {
iv: iv,
mode: CryptoJS.mode.CBC,
padding: CryptoJS.pad.Pkcs7
});
const encryptedData = iv.concat(encrypted.ciphertext);
return encryptedData.toString(CryptoJS.enc.Base64);
} catch (err) {
console.error('Encryption error:', err.message);
return null;
}
}
// 增强的解密函数,处理各种输入情况
function decryptAES256(encryptedData: string, key: string): any {
// eslint-disable-next-line no-useless-catch
try {
// 检查输入是否为有效的Base64字符串
if (!/^[A-Za-z0-9+/=]+$/.test(encryptedData)) {
// 尝试对非标准Base64字符串进行处理
// 移除可能的前缀
const cleanData = encryptedData.replace(/^data:.*?;base64,/, '').replace(/\s/g, ''); // 移除空格
if (!/^[A-Za-z0-9+/=]+$/.test(cleanData)) {
throw new Error('无效的Base64格式');
}
return decryptAES256(cleanData, key);
}
const decodedData = CryptoJS.enc.Base64.parse(encryptedData);
const iv = CryptoJS.lib.WordArray.create(decodedData.words.slice(0, 4));
const encryptedText = CryptoJS.lib.WordArray.create(decodedData.words.slice(4));
const parsedKey = CryptoJS.enc.Utf8.parse(key);
const decrypted = CryptoJS.AES.decrypt({ ciphertext: encryptedText }, parsedKey, {
iv: iv,
mode: CryptoJS.mode.CBC,
padding: CryptoJS.pad.Pkcs7
});
const decryptedStr = decrypted.toString(CryptoJS.enc.Utf8);
// 尝试解析为JSON
try {
return JSON.parse(decryptedStr);
} catch (jsonError) {
return decryptedStr;
}
} catch (err) {
throw err;
}
}
// 导出 axios 实例
export default service;

View File

@ -62,7 +62,23 @@ export const addDateRange = (params: any, dateRange: any[], propName?: string) =
}
return search;
};
// 价格格式化函数
export const formatPrice = (price, show = true) => {
if ((!show && price == 0) || price == '' || price == undefined || price == null) return '';
if (!price && price !== 0) return '0.0000';
// 转换为数字并保留四位小数
const num = Number(price);
if (isNaN(num)) return '0.0000';
const fixedNum = num.toFixed(4);
const [integer, decimal] = fixedNum.split('.');
// 千分位处理
const formattedInteger = integer.replace(/\B(?=(\d{3})+(?!\d))/g, ',');
return `${formattedInteger}.${decimal}`;
};
// 回显数据字典
export const selectDictLabel = (datas: any, value: number | string) => {
if (value === undefined) {

View File

@ -1,174 +0,0 @@
<template>
<div class="centerPage">
<div class="topPage">
<!-- 暂无 -->
</div>
<div class="endPage">
<Title title="AI安全巡检" :prefix="true" />
<div class="swiper">
<div class="arrow" :class="{ 'canUse': canLeft }" @click="swiperClick('left')">
<el-icon size="16" color="skyblue">
<ArrowLeft />
</el-icon>
</div>
<div class="swiper_content" ref="swiperContent">
<div class="swiper_item" v-for="(item, index) in swiperList" :key="index">
<img src="@/assets/projectLarge/swiper.png" alt="" class="swiper_img">
<div class="swiper_date">{{ item.date }}</div>
<div class="swiper_tip">{{ item.tip }}</div>
</div>
</div>
<div class="arrow" :class="{ 'canUse': canRight }" @click="swiperClick('right')">
<el-icon size="16">
<ArrowRight />
</el-icon>
</div>
</div>
</div>
</div>
</template>
<script setup lang="ts">
import { ref } from "vue"
import Title from './title.vue'
const swiperList = ref([
{ date: '03-18 15:00', tip: '未佩戴安全帽1' },
{ date: '03-18 15:00', tip: '未佩戴安全帽2' },
{ date: '03-18 15:00', tip: '未佩戴安全帽3' },
{ date: '03-18 15:00', tip: '未佩戴安全帽4' },
{ date: '03-18 15:00', tip: '未佩戴安全帽5' },
{ date: '03-18 15:00', tip: '未佩戴安全帽6' },
{ date: '03-18 15:00', tip: '未佩戴安全帽7' },
{ date: '03-18 15:00', tip: '未佩戴安全帽8' },
{ date: '03-18 15:00', tip: '未佩戴安全帽9' },
{ date: '03-18 15:00', tip: '未佩戴安全帽10' },
{ date: '03-18 15:00', tip: '未佩戴安全帽11' },
{ date: '03-18 15:00', tip: '未佩戴安全帽12' },
])
const swiperContent = ref<HTMLDivElement>()
const swiperItemWidth = ref(100)
const canLeft = ref(false)
const canRight = ref(true)
const swiperClick = (direction: 'left' | 'right') => {
if (direction === 'right') {
if (swiperContent.value.scrollLeft >= swiperContent.value.scrollWidth - swiperContent.value.clientWidth) {
canRight.value = false
canLeft.value = true
return
}
swiperContent.value.scrollLeft += swiperItemWidth.value
} else {
if (swiperContent.value.scrollLeft <= 0) {
canLeft.value = false
canRight.value = true
return
}
swiperContent.value.scrollLeft -= swiperItemWidth.value
}
}
onMounted(() => {
swiperItemWidth.value = swiperContent.value.children[0].clientWidth + 20
})
</script>
<style scoped lang="scss">
.centerPage {
display: flex;
flex-direction: column;
width: 50vw;
height: 100%;
.topPage,
.endPage {
display: flex;
flex-direction: column;
align-items: center;
width: 100%;
padding: 15px 0;
border: 1px solid rgba(29, 214, 255, 0.1);
box-sizing: border-box;
}
.topPage {
flex: 1;
margin-bottom: 23px;
}
}
.swiper {
width: 100%;
display: flex;
align-items: center;
gap: 20px;
padding: 20px 20px 10px 20px;
.swiper_content {
width: 100%;
display: flex;
gap: 20px;
transition: all 0.3s ease-in-out;
overflow-x: auto;
&::-webkit-scrollbar {
display: none;
}
}
.swiper_item {
position: relative;
display: flex;
flex-direction: column;
align-items: center;
width: 133px;
height: 84px;
.swiper_img {
width: 133px;
height: 84px;
object-fit: cover;
}
.swiper_date {
position: absolute;
top: 4px;
right: 4px;
font-size: 14px;
font-weight: 400;
color: rgba(230, 247, 255, 1);
}
.swiper_tip {
position: absolute;
bottom: 0;
width: 100%;
padding: 5px 0;
text-align: center;
font-size: 12px;
font-weight: 400;
color: rgba(230, 247, 255, 1);
background-color: rgba(0, 0, 0, 0.5);
}
}
}
.arrow {
display: grid;
place-items: center;
width: 20px;
height: 20px;
border-radius: 50%;
border: 1px solid skyblue;
color: skyblue;
&:canUse {
color: #000 !important;
}
}
</style>

View File

@ -1,198 +0,0 @@
<template>
<div class="header">
<div class="header_left">
<div class="header_left_img">
<img src="@/assets/large/secure.png" style="width: 100%; height: 100%" />
</div>
<div style="font-size: 12px; padding-left: 10px">安全生产天数</div>
<div class="header_left_text">
1,235
<span style="font-size: 12px"></span>
</div>
</div>
<div class="title">
<div>XXX智慧工地管理平台</div>
<div>XXX Smart Construction Stic Management Dashboard</div>
</div>
<div class="right">
<div class="top-bar">
<!-- 左侧天气图标 + 日期文字 -->
<div class="left-section">
<img src="@/assets/large/weather.png" alt="天气图标" />
<span>
<span>多云 9°/18°</span>
<span style="padding-left: 20px"> {{ week[date.week] }} ({{ date.ymd }})</span>
</span>
</div>
<!-- 分割线 -->
<div class="divider">
<div class="top-block"></div>
<div class="bottom-block"></div>
</div>
<!-- 右侧管理系统图标 + 文字 -->
<div class="right-section">
<img src="@/assets/large/setting.png" alt="设置图标" />
<span>管理系统</span>
</div>
</div>
</div>
</div>
</template>
<script setup lang="ts">
const week = ['星期日', '星期一', '星期二', '星期三', '星期四', '星期五', '星期六'];
const date = ref({
ymd: '',
hms: '',
week: 0
});
const setTime = () => {
let date1 = new Date();
let year: any = date1.getFullYear();
let month: any = date1.getMonth() + 1;
let day: any = date1.getDate();
let hours: any = date1.getHours();
if (hours < 10) {
hours = '0' + hours;
}
let minutes: any = date1.getMinutes();
if (minutes < 10) {
minutes = '0' + minutes;
}
let seconds: any = date1.getSeconds();
if (seconds < 10) {
seconds = '0' + seconds;
}
date.value.ymd = year + '-' + month + '-' + day;
date.value.hms = hours + ':' + minutes + ':' + seconds;
date.value.week = date1.getDay();
};
// 添加定时器,每秒更新一次时间
const timer = setInterval(setTime, 1000);
// 组件卸载时清除定时器
onUnmounted(() => {
clearInterval(timer);
});
</script>
<style scoped lang="scss">
.header {
width: 100%;
height: 80px;
box-sizing: border-box;
padding: 10px;
display: grid;
grid-template-columns: 1fr 1fr 1fr;
color: #fff;
}
.header_left {
display: flex;
align-items: center;
.header_left_img {
width: 48px;
height: 48px;
box-sizing: border-box;
// padding-right: 10px;
}
.header_left_text {
font-weight: 500;
text-shadow: 0px 1.24px 6.21px rgba(25, 179, 250, 1);
}
}
.title {
color: #fff;
font-family: 'AlimamaShuHeiTi', sans-serif;
text-align: center;
}
.title>div:first-child {
/* 第一个子元素的样式 */
font-size: 38px;
letter-spacing: 0.1em;
}
.title>div:last-child {
/* 最后一个子元素的样式 */
font-size: 14px;
}
.right {
width: 100%;
height: 100%;
display: flex;
}
/* 顶部栏容器Flex 水平布局 + 垂直居中 */
.top-bar {
width: 100%;
height: 100%;
display: flex;
align-items: center;
justify-content: flex-end;
// background-color: #1e2128;
color: #fff;
padding: 8px 16px;
font-size: 14px;
}
/* 左侧区域(天气 + 日期):自身也用 Flex 水平排列,确保元素在一行 */
.left-section {
display: flex;
align-items: center;
// margin-right: auto; /* 让右侧元素(管理系统)居右 */
}
.left-section img {
width: 32px;
height: 32px;
margin-right: 8px;
/* 图标与文字间距 */
}
/* 分割线(视觉分隔,可根据需求调整样式) */
.divider {
display: grid;
grid-template-rows: 1fr 1fr;
height: 100%;
/* 根据需要调整高度 */
padding: 14px 10px;
}
.divider .top-block {
width: 2px;
height: 7px;
background: #19b5fb;
align-self: start;
}
.divider .bottom-block {
width: 2px;
height: 7px;
background: #19b5fb;
align-self: end;
}
/* 右侧区域(管理系统):图标 + 文字水平排列 */
.right-section {
display: flex;
align-items: center;
font-family: 'AlimamaShuHeiTi', sans-serif;
font-size: 20px;
cursor: pointer;
}
.right-section img {
width: 20px;
height: 20px;
margin-right: 6px;
/* 图标与文字间距 */
}
</style>

View File

@ -1,204 +0,0 @@
<template>
<div class="leftPage">
<div class="topPage">
<Title title="项目公告" />
<div class="content">
<div class="content_item" v-for="item in 6" :key="item">
<div class="round">
<div class="sub_round"></div>
</div>
<div class="ellipsis">2025年6月23日 重庆市两江新区广场前期准备与审批完毕区广场前期准备与审批完毕前期准备与审批完毕区广场前期准备与审批完毕</div>
</div>
</div>
</div>
<div class="endPage">
<Title title="人员情况" />
<div class="map">
<img src="@/assets/projectLarge/map.svg" alt="">
</div>
<div class="attendance_tag">
<div class="tag_item" v-for="(item, index) in tagList" :key="index">
<img src="@/assets/projectLarge/people.svg" alt="">
<div class="tag_title">{{ item.title }}</div>
<div class="tag_info">
{{ item.number }}
<span style="font-size: 14px;">{{ index === 2 ? '%' : '人' }}</span>
</div>
</div>
</div>
<div class="attendance_list">
<div class="attendance_item subfont">
<div class="attendance_item_title"></div>
<div class="attendance_item_title">在岗人数</div>
<div class="attendance_item_title">出勤率</div>
<div class="attendance_item_title">出勤时间</div>
</div>
<div v-for="item in list" :key="item.title" class="attendance_item">
<div class="attendance_item_title">{{ item.title }}</div>
<div class="attendance_item_number">{{ item.number }} <span class="subfont">/{{ item.number }}</span></div>
<div class="attendance_item_rate">{{ item.attendanceRate }} %</div>
<div class="attendance_item_date subfont">{{ item.date }}</div>
</div>
</div>
</div>
</div>
</template>
<script setup lang="ts">
import { ref } from "vue"
import Title from './title.vue'
const list = ref([
{ title: '智慧系统运维', number: 30, attendanceRate: 100, date: '2025-08-05 08:10' },
{ title: '智慧系统运维', number: 30, attendanceRate: 100, date: '2025-08-05 08:10' },
{ title: '智慧系统运维', number: 30, attendanceRate: 100, date: '2025-08-05 08:10' },
{ title: '智慧系统运维', number: 30, attendanceRate: 100, date: '2025-08-05 08:10' },
{ title: '智慧系统运维', number: 30, attendanceRate: 100, date: '2025-08-05 08:10' },
{ title: '智慧系统运维', number: 30, attendanceRate: 100, date: '2025-08-05 08:10' },
])
const tagList = ref([
{ title: '出勤人数', number: 259 },
{ title: '在岗人数', number: 100 },
{ title: '出勤率', number: 100 },
])
</script>
<style scoped lang="scss">
.leftPage {
display: flex;
flex-direction: column;
width: calc(25vw - 30px);
margin: 0 15px;
height: 100%;
.topPage,
.endPage {
display: flex;
flex-direction: column;
align-items: center;
width: 100%;
padding: 15px 0;
border: 1px solid rgba(29, 214, 255, 0.1);
box-sizing: border-box;
}
.endPage {
flex: 1;
margin-top: 23px;
}
}
.content {
max-height: 100px;
margin: 0 15px;
padding: 0 10px;
margin-top: 15px;
box-sizing: border-box;
overflow-y: auto;
&::-webkit-scrollbar-track {
background: rgba(204, 204, 204, 0.1);
border-radius: 10px;
}
&::-webkit-scrollbar-thumb {
background: rgba(29, 214, 255, 0.78);
border-radius: 10px;
}
.content_item {
display: flex;
align-items: flex-start;
gap: 10px;
// position: relative;
margin-bottom: 20px;
font-size: 14px;
font-weight: 400;
color: rgba(230, 247, 255, 1);
.ellipsis {
display: -webkit-box;
-webkit-box-orient: vertical;
-webkit-line-clamp: 2;
overflow: hidden;
text-overflow: ellipsis;
line-height: 1.5;
}
&:last-child {
margin-bottom: 0;
}
.round {
display: grid;
place-items: center;
margin-top: 3px;
width: 12px;
height: 12px;
border-radius: 50%;
background: rgba(29, 214, 255, 0.3);
.sub_round {
width: 6px;
height: 6px;
border-radius: 50%;
background: #1DD6FF;
}
}
}
}
.map {
margin-top: 15px;
}
.attendance_tag {
width: 100%;
display: flex;
justify-content: space-between;
padding: 0 30px;
margin-top: 15px;
.tag_item {
display: flex;
flex-direction: column;
align-items: center;
gap: 10px;
border: 1px dashed rgba(29, 214, 255, 0.3);
padding: 10px 25px;
.tag_info {
font-size: 20px;
font-weight: 700;
color: rgba(230, 247, 255, 1);
text-shadow: 0px 1.24px 6.21px rgba(0, 190, 247, 1);
}
.tag_title {
font-size: 14px;
font-weight: 400;
color: rgba(230, 247, 255, 1);
}
}
}
.attendance_list {
padding: 0px 30px;
font-size: 14px;
.attendance_item {
display: grid;
grid-template-columns: 3fr 2fr 2fr 3fr;
margin-top: 20px;
}
}
.subfont {
color: rgba(138, 149, 165, 1);
}
</style>

View File

@ -1,274 +0,0 @@
<template>
<div class="leftPage">
<div class="topPage">
<Title title="项目概况" />
<div class="content">
<div class="content_item">项目名称智慧生态工地社区开发项目</div>
<div class="content_item">项目位置贵州省贵阳市乌当区具体地块编号01-123-11</div>
<div class="content_item">占地面积约10000亩</div>
<div class="content_item"> 土地性质城镇住宅用地兼容商业用地容积率2.5</div>
</div>
</div>
<div class="endPage">
<!-- 饼图容器 -->
<Title title="形象进度" />
<div ref="pieChartRef" class="echart" />
<!-- 折线图容器 -->
<div ref="lineChartRef" class="echart" />
</div>
</div>
</template>
<script setup lang="ts">
import { ref, onMounted, onUnmounted, nextTick } from "vue"
import Title from './title.vue'
import * as echarts from 'echarts';
// 饼图相关
const pieChartRef = ref<HTMLDivElement | null>(null);
let pieChart: any = null;
// 折线图相关
const lineChartRef = ref<HTMLDivElement | null>(null);
let lineChart: any = null;
// 饼图数据
const pieData = [
{ name: '桩点浇筑', value: 13 },
{ name: '水泥灌注', value: 7 },
{ name: '箱变安装', value: 40 },
{ name: '支架安装', value: 20 },
{ name: '组件安装', value: 20 },
]
// 折线图数据
const barData = {
xAxis: ['地块1', '地块2', '地块3', '地块4', '地块5', '地块6'],
series: [
{
name: '计划流转面积',
data: [70, 25, 45, 115, 70, 85]
},
{
name: '已流转面积',
data: [105, 30, 150, 65, 80, 200]
}
]
}
// 饼图配置
const pieOption = {
series: {
type: 'pie',
data: pieData,
radius: [50, 80],
itemStyle: {
borderColor: '#fff',
borderWidth: 1
},
label: {
alignTo: 'edge',
formatter: '{name|{b}}\n{percent|{c} %}',
minMargin: 10,
edgeDistance: 20,
lineHeight: 15,
rich: {
name: {
fontSize: 12,
color: '#fff'
},
percent: {
fontSize: 12,
color: '#fff'
}
}
},
legend: {
top: 'bottom'
},
}
};
// 柱状图配置
const barOption = {
legend: {
data: ['计划流转面积', '已流转面积'],
top: 0
},
grid: {
left: '3%',
right: '4%',
bottom: '3%',
containLabel: true
},
xAxis: {
type: 'category',
data: barData.xAxis
},
yAxis: {
name: '单位m²',
type: 'value',
axisLabel: {
formatter: '{value}'
}
},
series: [
{
type: 'bar',
data: [], // 空数据仅用于承载markArea
markArea: {
silent: true, // 背景不响应交互
data: (() => {
const groupCount = 3; // 共3组6个月 ÷ 2
const groupWidth = 1.8; // 每组背景宽度覆盖2根柱子
const bgData = [];
for (let i = 0; i < groupCount; i++) {
const startX = i * 2 - 0.9; // 每组起始位置
const endX = startX + groupWidth; // 每组结束位置
bgData.push([
{ xAxis: startX, yAxis: 0 },
{ xAxis: endX, yAxis: 100 }
]);
}
return bgData;
})(),
itemStyle: {
color: 'rgba(255, 255, 255, 0.05)',
borderRadius: 4
}
}
},
{
name: '计划流转面积',
type: 'bar',
data: barData.series[0].data,
barWidth: 15, // 柱形宽度
itemStyle: {
color: 'rgb(29, 253, 253)'
},
},
{
name: '已流转面积',
type: 'bar',
data: barData.series[1].data,
barWidth: 15,
itemStyle: {
color: '#rgb(25, 181, 251)'
},
}
]
};
// 初始化饼图
const initPieChart = () => {
if (!pieChartRef.value) {
console.error('未找到饼图容器元素');
return;
}
pieChart = echarts.init(pieChartRef.value, null, {
renderer: 'canvas',
useDirtyRect: false
});
pieChart.setOption(pieOption);
}
// 初始化折线图
const initLineChart = () => {
if (!lineChartRef.value) {
console.error('未找到折线图容器元素');
return;
}
lineChart = echarts.init(lineChartRef.value, null, {
renderer: 'canvas',
useDirtyRect: false
});
lineChart.setOption(barOption);
}
// 响应窗口大小变化
const handleResize = () => {
if (pieChart) pieChart.resize();
if (lineChart) lineChart.resize();
};
// 组件挂载时初始化图表
onMounted(() => {
nextTick(() => {
initPieChart();
initLineChart();
window.addEventListener('resize', handleResize);
});
});
// 组件卸载时清理
onUnmounted(() => {
window.removeEventListener('resize', handleResize);
if (pieChart) {
pieChart.dispose();
pieChart = null;
}
if (lineChart) {
lineChart.dispose();
lineChart = null;
}
});
</script>
<style scoped lang="scss">
.leftPage {
display: flex;
flex-direction: column;
width: calc(25vw - 30px);
margin: 0 15px;
height: 100%;
.topPage,
.endPage {
display: flex;
flex-direction: column;
align-items: center;
width: 100%;
padding: 15px 0;
border: 1px solid rgba(29, 214, 255, 0.1);
box-sizing: border-box;
}
.endPage {
flex: 1;
margin-top: 23px;
.echart {
width: 100%;
height: 100%;
}
}
}
.content {
margin: 10px 35px;
.content_item {
font-size: 14px;
font-weight: 400;
color: rgba(230, 247, 255, 1);
margin-bottom: 10px;
&:last-child {
margin-bottom: 0;
}
}
}
.ellipse {
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
}
.subfont {
color: rgba(138, 149, 165, 1);
}
</style>

View File

@ -1,45 +0,0 @@
<template>
<div class="large-screen">
<Header />
<div class="nav">
<leftPage />
<centerPage />
<rightPage />
</div>
</div>
</template>
<script setup lang="ts">
import Header from './components/header.vue';
import leftPage from './components/leftPage.vue';
import centerPage from './components/centerPage.vue';
import rightPage from './components/rightPage.vue';
</script>
<style lang="scss" scoped>
.large-screen {
width: 100vw;
height: 100vh;
background: url('@/assets/large/bg.png') no-repeat;
background-size: 100% 100%;
background-color: rgba(4, 7, 17, 1);
}
.nav {
display: flex;
gap: 15rpx;
width: 100%;
height: calc(100vh - 100px);
box-sizing: border-box;
color: #fff;
}
.nav_left,
.nav_right {
margin: 0 15px 15px 15px;
}
.nav_center {
margin-bottom: 15px;
}
</style>

View File

@ -5,7 +5,7 @@
<el-form :model="queryForm" :inline="true">
<el-form-item label="版本号" prop="versions">
<el-select v-model="queryForm.versions" placeholder="选择版本号" @change="changeVersions">
<el-option v-for="item in options" :key="item.id" :label="item.versions" :value="item.id" />
<el-option v-for="item in options" :key="item.id" :label="item.versions" :value="item.versions" />
</el-select>
</el-form-item>
<el-form-item label="表名" prop="sheet">
@ -59,16 +59,17 @@
<el-table ref="tableRef" v-loading="loading" :data="tableData" row-key="id" border lazy default-expand-all>
<el-table-column prop="num" label="编号" />
<el-table-column prop="name" label="工程或费用名称" />
<el-table-column prop="unit" label="单位" />
<el-table-column prop="quantity" label="数量" />
<el-table-column prop="remark" label="单价" align="center">
<el-table-column prop="unit" label="单位" align="center" />
<el-table-column prop="quantity" label="数量" align="center" />
<el-table-column prop="specification" label="规格" align="center" />
<el-table-column label="单价" align="center">
<template #default="scope">
<span>{{ scope.row.unitPrice }}</span>
{{ proxy.formatPrice(scope.row.unitPrice) }}
</template>
</el-table-column>
<el-table-column prop="price" label="总价" align="center">
<template #default="scope">
{{ scope.row.price }}
{{ proxy.formatPrice(scope.row.price) }}
</template>
</el-table-column>
<!-- <el-table-column prop="price" label="操作" align="center">
@ -91,7 +92,7 @@
<script setup lang="ts">
import { useUserStoreHook } from '@/store/modules/user';
import { BiddingImportExcelFile, getTreeLimit, biddingLimitListUpdate, sheetList, obtainAllVersionNumbers } from '@/api/bidding/biddingLimit';
const { proxy } = getCurrentInstance() as ComponentInternalInstance;
const { proxy } = getCurrentInstance() as any;
const userStore = useUserStoreHook();
const currentProject = computed(() => userStore.selectedProject);
@ -166,7 +167,8 @@ const getTableData = async () => {
const params = {
projectId: currentProject.value?.id,
sheet: queryForm.value.sheet,
versions: queryForm.value.versions
versions: queryForm.value.versions,
type: '1'
};
const res = await getTreeLimit(params);
loading.value = false;
@ -209,8 +211,6 @@ const tableRef = ref<any>();
const toggleExpandAll = () => {
isExpandAll.value = !isExpandAll.value;
console.log(isExpandAll.value);
tableData.value.forEach((row) => {
tableRef.value.toggleRowExpansion(row, isExpandAll.value);
});
@ -248,7 +248,7 @@ const handleExport = () => {
projectId: currentProject.value?.id,
sheet: queryForm.value.sheet
},
`限价一览表${queryForm.value.sheet}.xlsx`
`投标成本核算清单${queryForm.value.sheet}.xlsx`
);
};
// 审核

View File

@ -210,7 +210,8 @@ const getListTable = async () => {
const res = await getTreeLimit({
projectId: currentProject.value?.id,
versions: form.value.versions,
sheet: form.value.sheet
sheet: form.value.sheet,
type: '0'
});
if (res.code == 200) {
tableData.value = res.data;

View File

@ -0,0 +1,232 @@
<template>
<div class="system-busMachineryDetail-add">
<el-dialog v-model="isShowDialog" width="769px" :close-on-click-modal="false" :destroy-on-close="true">
<template #header>
<div v-drag="['.system-busMachineryDetail-add .el-dialog', '.system-busMachineryDetail-add .el-dialog__header']">添加机械入场记录</div>
</template>
<el-form ref="formRef" :model="formData" :rules="rules" label-width="130px">
<el-row>
<el-col :span="12"
><el-form-item label="合格证编号" prop="checkoutNumber">
<el-input v-model="formData.checkoutNumber" placeholder="请输入合格证编号" /> </el-form-item
></el-col>
<el-col :span="12"
><el-form-item label="生产厂家" prop="checkoutUnit">
<el-input v-model="formData.checkoutUnit" placeholder="请输入生产厂家" /> </el-form-item
></el-col>
<el-col :span="12"
><el-form-item label="生产日期/有效期" prop="checkoutDate">
<el-date-picker
clearable
style="width: 250px"
v-model="formData.checkoutDate"
type="datetime"
placeholder="选择检定日期/有效期"
value-format="YYYY-MM-DD HH:mm:ss"
:disabled-date="disabledDate"
>
</el-date-picker> </el-form-item
></el-col>
<!-- <el-radio v-for="dict in typeOptions" :key="dict.value" :label="dict.value">{{ dict.label }}</el-radio> -->
<!-- <el-col :span="12"
><el-form-item label="出入场" prop="type">
<el-radio-group v-model="formData.type">
<el-radio label="2">入场</el-radio>
</el-radio-group>
</el-form-item></el-col
> -->
<el-col :span="12"
><el-form-item label="施工类型状态" prop="status">
<el-radio-group v-model="formData.status">
<el-radio v-for="dict in statusOptions" :key="dict.value" :label="dict.value">{{ dict.label }}</el-radio>
</el-radio-group>
</el-form-item></el-col
>
<el-col :span="12"
><el-form-item label="入场时间" prop="entryTime">
<el-date-picker
clearable
style="width: 250px"
v-model="formData.entryTime"
type="datetime"
placeholder="选择入场时间"
format="YYYY年MM月DD日 hh时mm分ss秒"
value-format="YYYY-MM-DD hh:mm:ss"
>
</el-date-picker> </el-form-item
></el-col>
<el-col :span="24"
><el-form-item label="备注" prop="remark"> <el-input v-model="formData.remark" placeholder="请输入备注" /> </el-form-item
></el-col>
<el-col :span="24">
<el-form-item label="图片" prop="picture">
<upload-img :action="baseURL + '/zm/api/v1/system/upload/multipleImg'" @uploadImageAuth1="setUpImgListPicture($event)" :limit="4">
</upload-img> </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 { ElMessage } from 'element-plus';
import { addBusMachineryDetail } from '@/api/machinery/machineryDetail';
import uploadImg from '@/components/uploadImg/index.vue';
import { BusMachineryDetailEditState } from './model';
import { stat } from 'fs';
export default defineComponent({
name: 'index',
components: {
uploadImg
},
props: {
statusOptions: {
type: Array,
default: () => []
}
},
setup(props, { emit }) {
const baseURL: string | undefined | boolean = import.meta.env.VITE_APP_BASE_API_GO;
const { proxy } = <any>getCurrentInstance();
const formRef = ref<HTMLElement | null>(null);
const menuRef = ref();
const state = reactive<BusMachineryDetailEditState>({
loading: false,
isShowDialog: false,
typeOptions: [
{ value: '2', label: '入场' },
{ value: '1', label: '出场' }
],
formData: {
id: undefined,
checkoutNumber: undefined,
checkoutUnit: undefined,
checkoutDate: undefined,
status: false,
entryTime: undefined,
createBy: undefined,
updateBy: undefined,
createdAt: undefined,
updatedAt: undefined,
deletedAt: undefined,
remark: undefined,
picture: [],
type: '2'
},
// 表单校验
rules: {
checkoutNumber: [{ required: true, message: '检验证编号不能为空', trigger: 'blur' }],
checkoutUnit: [{ required: true, message: '检验单位不能为空', trigger: 'blur' }],
checkoutDate: [{ required: true, message: '检定日期/有效期不能为空', trigger: 'blur' }],
type: [{ required: true, message: '出入场不能为空', trigger: 'blur' }]
},
imageList: [],
propsRow: {}
});
// 打开弹窗
const openDialog = (row: any) => {
resetForm();
if (row) {
state.formData.machinery_id = row.id;
state.propsRow = row;
}
state.isShowDialog = true;
};
// 关闭弹窗
const closeDialog = () => {
state.isShowDialog = false;
};
// 取消
const onCancel = () => {
closeDialog();
};
// 提交
const onSubmit = () => {
// 去重
// state.formData.picture = state.formData.picture.join(',');
const formWrap = unref(formRef) as any;
if (!formWrap) return;
formWrap.validate((valid: boolean) => {
if (valid) {
state.loading = true;
//添加
state.formData.type = '2';
addBusMachineryDetail(state.formData)
.then(() => {
ElMessage.success('添加成功');
closeDialog(); // 关闭弹窗
emit('busMachineryDetailList', state.propsRow.children, state.propsRow.id);
})
.finally(() => {
state.loading = false;
});
}
});
};
const resetForm = () => {
state.formData = {
id: undefined,
checkoutNumber: undefined,
checkoutUnit: undefined,
checkoutDate: undefined,
status: false,
entryTime: undefined,
createBy: undefined,
updateBy: undefined,
createdAt: undefined,
updatedAt: undefined,
deletedAt: undefined,
remark: undefined,
picture: []
};
};
const setUpImgListPicture = (val: any) => {
// console.log(val);
// if (val.length > 0 && val[0].url && !val[0].raw) {
// let path = '';
// val.forEach((item) => {
// // 判断是否存在http
// if (item.url.indexOf('http') != -1) {
// path = path + ',' + item.url.slice(item.url.indexOf('/upload_file') + 1);
// } else {
// path = path + ',' + item.url;
// }
// });
// path = path.slice(1);
state.formData.picture = [];
val.forEach((item) => {
state.formData.picture.push(item.url);
});
// }
};
const disabledDate = (time) => {
return time.getTime() >= Date.now(); // 8.64e7 毫秒数代表一天
};
return {
proxy,
openDialog,
closeDialog,
onCancel,
onSubmit,
menuRef,
formRef,
setUpImgListPicture,
baseURL,
disabledDate,
...toRefs(state)
};
}
});
</script>
<style scoped>
.el-col {
margin: 10px 0 !important;
}
</style>

View File

@ -0,0 +1,219 @@
<template>
<!-- 机械详情详情抽屉 -->
<div class="system-busMachineryDetail-detail">
<el-drawer v-model="isShowDialog" class="busMachineryDetail_detail" size="40%" direction="ltr">
<template #header>
<h4>机械出入场记录详情</h4>
</template>
<el-form ref="formRef" :model="formData" label-width="130px">
<el-row>
<el-col :span="12">
<el-form-item label="合格证编号">{{ formData.checkoutNumber }}</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="生产厂家">{{ formData.checkoutUnit }}</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="生产日期/有效期">{{ formData.checkoutDate }}</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="出入场">{{ formData.type == 1 ? '出场' : formData.type == 2 ? '入场' : '' }}</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="施工类型状态">{{ getOptionValue(formData.status, statusOptions, 'value', 'label') }}</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="入场时间">{{ formData.entryTime }}</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="创建时间">{{ formData.createdAt }}</el-form-item>
</el-col>
<el-col :span="24">
<el-form-item label="备注">{{ formData.remark }}</el-form-item>
</el-col>
<el-col :span="24">
<el-form-item label="图片">
<div class="pic-block" v-if="formData.picture.length" v-for="(img, key) in formData.picture" :key="'picture-' + key">
<el-image
style="width: 140px; height: 150px; margin: 0 5px"
v-if="img"
:src="'http://58.17.134.85:8920' + img"
fit="contain"
:preview-src-list="['http://58.17.134.85:8920' + img]"
:zoom-rate="1.2"
preview-teleported="true"
></el-image>
</div>
</el-form-item>
</el-col>
</el-row>
<el-row>
<el-table v-loading="loading" :data="formData.recordList">
<el-table-column label="出入场" align="center" prop="type">
<template #default="scope">
<span v-if="scope.row.type == 1">出场</span>
<span v-if="scope.row.type == 2">入场</span>
</template>
</el-table-column>
<el-table-column label="施工类型状态" align="center" prop="status">
<template #default="scope">
<span v-if="scope.row.status == 0">正常</span>
<span v-if="scope.row.status == 1">停用</span>
</template>
</el-table-column>
<!-- <el-table-column label="填报人" align="center" prop="createdBy" min-width="100px" /> -->
<el-table-column label="记录时间" align="center" prop="recordTime">
<template #default="scope">
<span>{{ proxy.parseTime(scope.row.recordTime, '{y}-{m}-{d} {h}:{i}:{s}') }}</span>
</template>
</el-table-column>
</el-table>
</el-row>
</el-form>
</el-drawer>
</div>
</template>
<script lang="ts">
import { reactive, toRefs, defineComponent, ref, getCurrentInstance } from 'vue';
import { getBusMachineryDetail } from '@/api/machinery/machineryDetail';
import { ElLoading } from 'element-plus';
import uploadImg from '@/components/uploadImg/index.vue';
import { BusMachineryDetailInfoData, BusMachineryDetailEditState } from './model';
export default defineComponent({
name: 'index',
components: {
uploadImg
},
props: {
statusOptions: {
type: Array,
default: () => []
}
},
setup(props, { emit }) {
const baseURL: string | undefined | boolean = import.meta.env.VITE_API_URL;
const { proxy } = <any>getCurrentInstance();
const formRef = ref<HTMLElement | null>(null);
const menuRef = ref();
const state = reactive<BusMachineryDetailEditState>({
loading: false,
isShowDialog: false,
formData: {
id: undefined,
checkoutNumber: undefined,
checkoutUnit: undefined,
checkoutDate: undefined,
status: false,
entryTime: undefined,
createBy: undefined,
updateBy: undefined,
createdAt: undefined,
updatedAt: undefined,
deletedAt: undefined,
remark: undefined,
picture: []
},
// 表单校验
rules: {
id: [{ required: true, message: '序号不能为空', trigger: 'blur' }],
status: [{ required: true, message: '施工类型状态不能为空', trigger: 'blur' }]
}
});
// 打开弹窗
const openDialog = (row?: BusMachineryDetailInfoData) => {
resetForm();
if (row) {
const loading = ElLoading.service({
lock: true,
text: '正在加载中……',
background: 'rgba(0, 0, 0, 0.7)',
target: '.busMachineryDetail_detail'
});
getBusMachineryDetail(row.id!).then((res: any) => {
loading.close();
const data = res.data;
state.formData = data;
if (state.formData.picture && state.formData.picture.includes('[')) {
state.formData.picture = state.formData.picture ? JSON.parse(state.formData.picture) : [];
} else {
state.formData.picture = state.formData.picture ? state.formData.picture.split(',') : [];
}
});
}
state.isShowDialog = true;
};
// 关闭弹窗
const closeDialog = () => {
state.isShowDialog = false;
};
// 取消
const onCancel = () => {
closeDialog();
};
const resetForm = () => {
state.formData = {
id: undefined,
checkoutNumber: undefined,
checkoutUnit: undefined,
checkoutDate: undefined,
status: false,
entryTime: undefined,
createBy: undefined,
updateBy: undefined,
createdAt: undefined,
updatedAt: undefined,
deletedAt: undefined,
remark: undefined,
picture: []
};
};
function getOptionValue(key: any, options: Array<any>, keyName: string, valName: string) {
keyName = keyName ?? 'key';
valName = valName ?? 'value';
const option = options.find((value) => {
return key + '' === value[keyName];
});
if (option !== undefined) {
return option[valName];
}
}
const setUpImgListPicture = (data: any) => {
state.formData.picture = data;
};
return {
proxy,
openDialog,
closeDialog,
onCancel,
menuRef,
getOptionValue,
formRef,
setUpImgListPicture,
baseURL,
...toRefs(state)
};
}
});
</script>
<style scoped>
.system-busMachineryDetail-detail :deep(.el-form-item--large .el-form-item__label) {
font-weight: bolder;
}
.pic-block {
margin-right: 8px;
}
.file-block {
width: 100%;
border: 1px solid var(--el-border-color);
border-radius: 6px;
cursor: pointer;
position: relative;
overflow: hidden;
transition: var(--el-transition-duration-fast);
margin-bottom: 5px;
padding: 3px 6px;
}
.ml-2 {
margin-right: 5px;
}
</style>

View File

@ -0,0 +1,253 @@
<template>
<div class="system-busMachineryDetail-edit">
<el-dialog v-model="isShowDialog" width="769px" :close-on-click-modal="false" :destroy-on-close="true" custom-class="busMachineryDetail_edit">
<template #header>
<div v-drag="['.system-busMachineryDetail-edit .el-dialog', '.system-busMachineryDetail-edit .el-dialog__header']">
{{ formData.id ? '修改' : '添加' }}机械出入场记录
</div>
</template>
<el-form ref="formRef" :model="formData" :rules="rules" label-width="130px">
<el-row>
<el-col :span="12">
<el-form-item label="合格证编号" prop="checkoutNumber">
<el-input v-model="formData.checkoutNumber" placeholder="请输入合格证编号" />
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="生产厂家" prop="checkoutUnit">
<el-input v-model="formData.checkoutUnit" placeholder="请输入生产厂家" />
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="生产日期/有效期" prop="checkoutDate">
<el-date-picker
clearable
style="width: 250px"
v-model="formData.checkoutDate"
type="datetime"
placeholder="选择检定日期/有效期"
value-format="YYYY-MM-DD HH:mm:ss"
:disabled-date="disabledDate"
/>
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="出入场" prop="type">
<el-radio-group v-model="formData.type">
<el-radio v-for="dict in typeOptions" :key="dict.value" :label="dict.value">{{ dict.label }}</el-radio>
</el-radio-group>
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="施工类型状态" prop="status">
<el-radio-group v-model="formData.status">
<el-radio v-for="dict in statusOptions" :key="dict.value" :label="dict.value">{{ dict.label }}</el-radio>
</el-radio-group>
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="出入场时间" prop="entryTime">
<el-date-picker
clearable
style="width: 250px"
v-model="formData.entryTime"
type="datetime"
placeholder="选择入场时间"
format="YYYY年MM月DD日 hh时mm分ss秒"
value-format="YYYY-MM-DD HH:mm:ss"
/>
</el-form-item>
</el-col>
<el-col :span="24">
<el-form-item label="备注" prop="remark">
<el-input v-model="formData.remark" placeholder="请输入备注" />
</el-form-item>
</el-col>
<el-col :span="24">
<el-form-item label="图片" prop="picture">
<UploadImg
:action="baseURL + '/zm/api/v1/system/upload/multipleImg'"
v-model="formData.picture"
@uploadData="setUpImgListPicture"
:limit="4"
ref="uploadRef"
/>
</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, ref, toRefs, defineComponent, unref } from 'vue';
import { ElMessage, ElLoading } from 'element-plus';
import { getBusMachineryDetail, addBusMachineryDetail, updateBusMachineryDetail } from '@/api/machinery/machineryDetail';
import UploadImg from '@/components/uploadImg/index.vue';
import { BusMachineryDetailInfoData, BusMachineryDetailEditState } from './model';
export default defineComponent({
name: 'editMachineChild',
components: { UploadImg },
props: {
statusOptions: { type: Array, default: () => [] }
},
setup(props, { emit }) {
const baseURL = import.meta.env.VITE_APP_BASE_API_GO;
const formRef = ref(null);
const uploadRef = ref(null);
const state = reactive<BusMachineryDetailEditState>({
loading: false,
isShowDialog: false,
typeOptions: [
{ value: '2', label: '入场' },
{ value: '1', label: '出场' }
],
formData: {
id: undefined,
checkoutNumber: '',
checkoutUnit: '',
checkoutDate: undefined,
type: '',
status: '',
entryTime: undefined,
remark: '',
picture: []
},
propsRow: {},
rules: {
checkoutNumber: [{ required: true, message: '检验证编号不能为空', trigger: 'blur' }],
checkoutUnit: [{ required: true, message: '检验单位不能为空', trigger: 'blur' }],
checkoutDate: [{ required: true, message: '检定日期/有效期不能为空', trigger: 'blur' }],
status: [{ required: true, message: '施工类型状态不能为空', trigger: 'blur' }]
}
});
const resetForm = () => {
Object.assign(state.formData, {
id: undefined,
checkoutNumber: '',
checkoutUnit: '',
checkoutDate: undefined,
type: '',
status: '',
entryTime: undefined,
remark: '',
picture: []
});
if (uploadRef.value) {
uploadRef.value.clearFiles && uploadRef.value.clearFiles(); // 清空上传组件历史
}
};
const openDialog = (props: any, row?: BusMachineryDetailInfoData) => {
resetForm();
if (props) state.propsRow = props;
if (row) {
const loadingInstance = ElLoading.service({
lock: true,
text: '正在加载中……',
background: 'rgba(0, 0, 0, 0.7)',
target: '.busMachineryDetail_edit'
});
getBusMachineryDetail(row.id!).then((res: any) => {
loadingInstance.close();
const data = res.data;
let pictureArr: any[] = [];
if (data.picture) {
if (data.picture.includes('[')) {
data.picture = JSON.parse(data.picture);
} else {
data.picture = data.picture.split(',');
}
pictureArr = data.picture.map((item, index) => ({
url: 'http://58.17.134.85:8920' + item,
name: `img_${index}`
}));
}
Object.assign(state.formData, {
...data,
type: data.type ?? '',
status: data.status ?? '',
picture: pictureArr
});
});
}
state.isShowDialog = true;
};
const closeDialog = () => {
state.isShowDialog = false;
};
const onCancel = () => closeDialog();
const setUpImgListPicture = (val: any) => {
state.formData.picture.splice(0, state.formData.picture.length, ...val);
};
const pictureConvert = () => {
if (Array.isArray(state.formData.picture)) {
state.formData.picture = state.formData.picture.map((item) => item.url.substring(item.url.indexOf('/file')));
}
};
const onSubmit = () => {
pictureConvert();
const formWrap = unref(formRef) as any;
if (!formWrap) return;
formWrap.validate((valid: boolean) => {
if (!valid) return;
state.loading = true;
const apiCall = state.formData.id ? updateBusMachineryDetail : addBusMachineryDetail;
apiCall(state.formData)
.then(() => {
ElMessage.success(state.formData.id ? '修改成功' : '添加成功');
closeDialog();
emit('busMachineryDetailList', state.propsRow.children, state.propsRow.id);
})
.finally(() => {
state.loading = false;
});
});
};
const disabledDate = (time: Date) => time.getTime() >= Date.now();
return {
...toRefs(state),
formRef,
uploadRef,
baseURL,
openDialog,
closeDialog,
onCancel,
onSubmit,
setUpImgListPicture,
disabledDate
};
}
});
</script>
<style scoped>
.el-col {
margin: 10px 0 !important;
}
</style>

View File

@ -0,0 +1,55 @@
export interface BusMachineryDetailTableColumns {
id:number; // 序号
checkoutNumber:string; // 检验证编号
checkoutUnit:string; // 检验单位
checkoutDate:string; // 检定日期/有效期
status:string; // 施工类型状态
entryTime:string; // 入场时间
createdAt:string; // 创建时间
remark:string; // 备注
picture:any[]; // 4张图片逗号分隔
}
export interface BusMachineryDetailInfoData {
id:number|undefined; // 序号
checkoutNumber:string|undefined; // 检验证编号
checkoutUnit:string|undefined; // 检验单位
checkoutDate:string|undefined; // 检定日期/有效期
status:string|undefined; // 施工类型状态
entryTime:string|undefined; // 入场时间
createBy:string|undefined; // 创建者
updateBy:string|undefined; // 更新者
createdAt:string|undefined; // 创建时间
updatedAt:string|undefined; // 更新时间
deletedAt:string|undefined; // 删除时间
remark:string|undefined; // 备注
picture:any[]; // 4张图片逗号分隔
type: undefined, // 出入场
}
export interface BusMachineryDetailTableDataState {
ids:any[];
tableData: {
data: Array<BusMachineryDetailTableColumns>;
total: number;
loading: boolean;
param: {
pageNum: number;
pageSize: number;
checkoutNumber: string|undefined;
status: string|undefined;
entryTime: string|undefined;
dateRange: string[];
};
};
}
export interface BusMachineryDetailEditState{
loading:boolean;
isShowDialog: boolean;
formData:BusMachineryDetailInfoData;
rules: object;
}

View File

@ -0,0 +1,339 @@
<template>
<div class="system-busMachineryDetail-container">
<el-card shadow="hover">
<div class="system-busMachineryDetail-search mb15">
<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="checkoutNumber">
<el-input
v-model="tableData.param.checkoutNumber"
placeholder="请输入合格证编号"
clearable
@keyup.enter.native="busMachineryDetailList"
/>
</el-form-item>
</el-col>
<el-col :span="8" class="colBlock">
<el-form-item label="施工类型状态" prop="status">
<el-select v-model="tableData.param.status" placeholder="请选择施工类型状态" clearable>
<el-option v-for="dict in account_status" :key="dict.value" :label="dict.label" :value="dict.value" />
</el-select>
</el-form-item>
</el-col>
<el-col :span="8" :class="!showAll ? 'colBlock' : 'colNone'">
<el-form-item>
<el-button type="primary" @click="busMachineryDetailList"
><el-icon><Search /></el-icon>搜索</el-button
>
<el-button @click="resetQuery(queryRef)"
><el-icon><Refresh /></el-icon>重置</el-button
>
<el-button type="primary" link @click="toggleSearch">
{{ word }}
<el-icon v-show="showAll"><ArrowUp /></el-icon>
<el-icon v-show="!showAll"><ArrowDown /></el-icon>
</el-button>
</el-form-item>
</el-col>
<el-col :span="8" :class="showAll ? 'colBlock' : 'colNone'">
<el-form-item label="入场时间" prop="entryTime">
<el-date-picker
clearable
style="width: 200px"
v-model="tableData.param.entryTime"
format="YYYY-MM-DD HH:mm:ss"
value-format="YYYY-MM-DD HH:mm:ss"
type="datetime"
placeholder="选择入场时间"
></el-date-picker>
</el-form-item>
</el-col>
<el-col :span="8" :class="showAll ? 'colBlock' : 'colNone'">
<el-form-item>
<el-button type="primary" @click="busMachineryDetailList"
><el-icon><Search /></el-icon>搜索</el-button
>
<el-button @click="resetQuery(queryRef)"
><el-icon><Refresh /></el-icon>重置</el-button
>
<el-button type="primary" link @click="toggleSearch">
{{ word }}
<el-icon v-show="showAll"><ArrowUp /></el-icon>
<el-icon v-show="!showAll"><ArrowDown /></el-icon>
</el-button>
</el-form-item>
</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/busMachineryDetail/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/busMachineryDetail/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/busMachineryDetail/delete'"
><el-icon><Delete /></el-icon>删除</el-button
>
</el-col>
</el-row>
</div>
<el-table v-loading="loading" :data="tableData.data" @selection-change="handleSelectionChange">
<el-table-column type="selection" width="55" align="center" />
<el-table-column label="序号" align="center" type="index" :index="indexMethod" width="60" />
<el-table-column label="合格证编号" align="center" prop="checkoutNumber" min-width="100px" />
<el-table-column label="生产厂家" align="center" prop="checkoutUnit" min-width="100px" />
<el-table-column label="检定日期/有效期" align="center" prop="checkoutDate" min-width="100px">
<template #default="scope">
<span>{{ scope.row.checkoutDate }}</span>
</template>
</el-table-column>
<el-table-column label="施工类型状态" align="center" prop="status" :formatter="statusFormat" min-width="100px" />
<el-table-column label="入场时间" align="center" prop="entryTime" min-width="100px">
<template #default="scope">
<span>{{ scope.row.entryTime }}</span>
</template>
</el-table-column>
<el-table-column label="创建时间" align="center" prop="createdAt" min-width="100px">
<template #default="scope">
<span>{{ scope.row.createdAt }}</span>
</template>
</el-table-column>
<el-table-column label="备注" align="center" prop="remark" min-width="100px" />
<el-table-column label="图片" align="center" prop="picture" min-width="100px">
<template #default="scope">
<div>
<el-image
style="width: 100px; height: 50px"
:initial-index="1"
v-if="scope.row.image"
:src="'http://58.17.134.85:8920' + scope.row.image"
fit="contain"
:preview-src-list="['http://58.17.134.85:8920' + scope.row.picture]"
:z-index="999999999"
></el-image>
</div>
</template>
</el-table-column>
<el-table-column label="操作" align="center" class-name="small-padding" min-width="160px">
<template #default="scope">
<el-button type="primary" link @click="handleUpdate(scope.row)"
><el-icon><EditPen /></el-icon>修改</el-button
>
<el-button type="primary" link @click="handleDelete(scope.row)"
><el-icon><DeleteFilled /></el-icon>删除</el-button
>
</template>
</el-table-column>
</el-table>
<pagination
v-show="tableData.total > 0"
:total="tableData.total"
v-model:page="tableData.param.pageNum"
v-model:limit="tableData.param.pageSize"
@pagination="busMachineryDetailList"
/>
</el-card>
<apiV1SystemBusMachineryDetailAdd
ref="addRef"
:statusOptions="account_status"
@busMachineryDetailList="busMachineryDetailList"
></apiV1SystemBusMachineryDetailAdd>
<apiV1SystemBusMachineryDetailEdit
ref="editRef"
:statusOptions="account_status"
@busMachineryDetailList="busMachineryDetailList"
></apiV1SystemBusMachineryDetailEdit>
<apiV1SystemBusMachineryDetailDetail
ref="detailRef"
:statusOptions="account_status"
@busMachineryDetailList="busMachineryDetailList"
></apiV1SystemBusMachineryDetailDetail>
</div>
</template>
<script lang="ts">
import { toRefs, reactive, onMounted, ref, defineComponent, computed, getCurrentInstance, toRaw } from 'vue';
import { ElMessageBox, ElMessage, FormInstance } from 'element-plus';
import { listBusMachineryDetail, delBusMachineryDetail } from '@/api/machinery/machineryDetail';
import { BusMachineryDetailTableColumns, BusMachineryDetailInfoData, BusMachineryDetailTableDataState } from './component/model';
import apiV1SystemBusMachineryDetailAdd from './component/add.vue';
import apiV1SystemBusMachineryDetailEdit from './component/edit.vue';
import apiV1SystemBusMachineryDetailDetail from './component/detail.vue';
export default defineComponent({
name: 'index',
components: {
apiV1SystemBusMachineryDetailAdd,
apiV1SystemBusMachineryDetailEdit,
apiV1SystemBusMachineryDetailDetail
},
setup() {
const { proxy } = <any>getCurrentInstance();
const loading = ref(false);
const queryRef = ref();
const addRef = ref();
const editRef = ref();
const detailRef = ref();
// 是否显示所有搜索选项
const showAll = ref(false);
// 非单个禁用
const single = ref(true);
// 非多个禁用
const multiple = ref(true);
const word = computed(() => {
if (showAll.value === false) {
//对文字进行处理
return '展开搜索';
} else {
return '收起搜索';
}
});
// 字典选项数据
const { account_status } = proxy.useDict('account_status');
const state = reactive<BusMachineryDetailTableDataState>({
ids: [],
tableData: {
data: [],
total: 0,
loading: false,
param: {
pageNum: 1,
pageSize: 10,
checkoutNumber: undefined,
status: undefined,
entryTime: undefined,
dateRange: []
}
}
});
// 页面加载时
onMounted(() => {
initTableData();
});
// 初始化表格数据
const initTableData = () => {
busMachineryDetailList();
};
/** 重置按钮操作 */
const resetQuery = (formEl: FormInstance | undefined) => {
if (!formEl) return;
formEl.resetFields();
busMachineryDetailList();
};
// 获取列表数据
const busMachineryDetailList = () => {
loading.value = true;
listBusMachineryDetail(state.tableData.param).then((res: any) => {
let list = res.data.list ?? [];
state.tableData.data = list;
state.tableData.data.forEach((item) => {
if (item.picture) {
item.image = item.picture.split(',')[0];
item.imageList = item.picture.split(',');
}
});
state.tableData.total = res.data.total;
loading.value = false;
});
};
const toggleSearch = () => {
showAll.value = !showAll.value;
};
// 施工类型状态字典翻译
const statusFormat = (row: BusMachineryDetailTableColumns) => {
return proxy.selectDictLabel(account_status.value, row.status);
};
// 多选框选中数据
const handleSelectionChange = (selection: Array<BusMachineryDetailInfoData>) => {
state.ids = selection.map((item) => item.id);
single.value = selection.length != 1;
multiple.value = !selection.length;
};
const handleAdd = () => {
addRef.value.openDialog();
};
const handleUpdate = (row: BusMachineryDetailTableColumns) => {
if (!row) {
row = state.tableData.data.find((item: BusMachineryDetailTableColumns) => {
return item.id === state.ids[0];
}) as BusMachineryDetailTableColumns;
}
editRef.value.openDialog(toRaw(row));
};
const handleDelete = (row: BusMachineryDetailTableColumns) => {
let msg = '你确定要删除所选数据?';
let id: number[] = [];
if (row) {
msg = `此操作将永久删除数据,是否继续?`;
id = [row.id];
} else {
id = state.ids;
}
if (id.length === 0) {
ElMessage.error('请选择要删除的数据。');
return;
}
ElMessageBox.confirm(msg, '提示', {
confirmButtonText: '确认',
cancelButtonText: '取消',
type: 'warning'
})
.then(() => {
delBusMachineryDetail(id).then(() => {
ElMessage.success('删除成功');
busMachineryDetailList();
});
})
.catch(() => {});
};
const handleView = (row: BusMachineryDetailTableColumns) => {
detailRef.value.openDialog(toRaw(row));
};
/** 自定义编号 */
const indexMethod = (index) => {
let pageNum = state.tableData.param.pageNum - 1;
if (pageNum !== -1 && pageNum !== 0) {
return index + 1 + pageNum * state.tableData.param.pageSize;
} else {
return index + 1;
}
};
return {
proxy,
addRef,
editRef,
detailRef,
showAll,
loading,
single,
multiple,
word,
queryRef,
resetQuery,
busMachineryDetailList,
toggleSearch,
statusFormat,
account_status,
handleSelectionChange,
handleAdd,
handleUpdate,
handleDelete,
indexMethod,
...toRefs(state)
};
}
});
</script>
<style lang="scss" scoped>
.colBlock {
display: block;
}
.colNone {
display: none;
}
</style>

View File

@ -5,7 +5,7 @@
<el-form :model="queryForm" :inline="true">
<el-form-item label="版本号" prop="versions">
<el-select v-model="queryForm.versions" placeholder="选择版本号" @change="changeVersions">
<el-option v-for="item in options" :key="item.id" :label="item.versions" :value="item.id" />
<el-option v-for="item in options" :key="item.id" :label="item.versions" :value="item.versions" />
</el-select>
</el-form-item>
<el-form-item label="表名" prop="sheet">
@ -57,10 +57,11 @@
</transition>
<el-card shadow="never" class="mb8">
<el-table ref="tableRef" v-loading="loading" :data="tableData" row-key="id" border lazy default-expand-all>
<el-table-column prop="num" label="编号" />
<el-table-column prop="name" label="工程或费用名称" />
<el-table-column prop="unit" label="单位" />
<el-table-column prop="quantity" label="数量">
<el-table-column prop="num" label="编号" align="center" />
<el-table-column prop="name" label="工程或费用名称" align="center" />
<el-table-column prop="unit" label="单位" align="center" />
<el-table-column prop="specification" label="规格" align="center" />
<el-table-column prop="quantity" label="数量" align="center">
<template #default="scope">
{{ scope.row.children.length > 0 ? '' : scope.row.quantity }}
</template>
@ -76,8 +77,8 @@
changePrice(scope.row);
}
"
:precision="2"
:step="0.1"
:min="0"
:precision="4"
:controls="false"
v-if="scope.row.quantity && scope.row.quantity != 0"
/>
@ -85,7 +86,7 @@
</el-table-column>
<el-table-column prop="price" label="总价" align="center">
<template #default="scope">
{{ scope.row.price != 0 ? Number(scope.row.price).toFixed(2) : null }}
{{ proxy.formatPrice(scope.row.price) }}
</template>
</el-table-column>
<el-table-column prop="operate" label="操作" align="center">
@ -184,7 +185,8 @@ const getTableData = async () => {
const params = {
projectId: currentProject.value?.id,
sheet: queryForm.value.sheet,
versions: queryForm.value.versions
versions: queryForm.value.versions,
type: '0'
};
const res = await getTreeLimit(params);
loading.value = false;
@ -260,7 +262,7 @@ const importExcel = (options: any): any => {
let formData = new FormData();
formData.append('file', options.file);
loading.value = true;
BiddingImportExcelFile({ projectId: currentProject.value?.id }, formData)
BiddingImportExcelFile({ projectId: currentProject.value?.id, versions: queryForm.value.versions }, formData)
.then((res) => {
const { code } = res;
if (code == 200) {
@ -288,7 +290,7 @@ const handleExport = () => {
projectId: currentProject.value?.id,
sheet: queryForm.value.sheet
},
`限价一览表${queryForm.value.sheet}.xlsx`
`投标成本核算${queryForm.value.sheet}.xlsx`
);
};
// 审核

View File

@ -23,13 +23,23 @@
{{ (queryParams.pageNum - 1) * queryParams.pageSize + scope.$index + 1 }}
</template>
</el-table-column>
<el-table-column prop="name" label="名称" />
<el-table-column prop="content" label="内容" />
<el-table-column prop="price" label="限价" />
<el-table-column prop="name" label="名称" align="center" />
<el-table-column prop="content" label="内容" align="center" />
<el-table-column prop="price" label="限价" align="center">
<template #default="scope">
{{ proxy.formatPrice(scope.row.price) }}
</template>
</el-table-column>
<el-table-column prop="plannedBiddingTime" align="center">
<template #header> <span style="color: red">*</span>计划招标时间 </template>
<template #default="scope">
<el-date-picker v-model="scope.row.plannedBiddingTime" type="date" value-format="YYYY-MM-DD" placeholder="选择时间" />
<el-date-picker
v-model="scope.row.plannedBiddingTime"
type="date"
value-format="YYYY-MM-DD"
placeholder="选择时间"
:disabled="scope.row.status == 0"
/>
</template>
</el-table-column>
<el-table-column prop="price" label="操作" align="center">
@ -138,25 +148,42 @@
<el-table-column prop="useQuantity" label="剩余量" align="center">
<template #default="scope">
{{
(scope.row.quantity ? Number(scope.row.quantity) : 0) - (scope.row.useQuantity ? Number(scope.row.useQuantity) : 0) == 0
(scope.row.quantity ? Number(scope.row.quantity) : 0) -
(scope.row.useQuantity ? Number(scope.row.useQuantity) : 0) -
(scope.row.selectNum ? Number(scope.row.selectNum) : 0) ==
0
? ''
: (scope.row.quantity ? Number(scope.row.quantity) : 0) - (scope.row.useQuantity ? Number(scope.row.useQuantity) : 0)
: (
(scope.row.quantity ? Number(scope.row.quantity) : 0) -
(scope.row.selectNum ? Number(scope.row.selectNum) : 0) -
(scope.row.useQuantity ? Number(scope.row.useQuantity) : 0)
).toFixed(2)
}}
</template>
</el-table-column>
<el-table-column prop="unitPrice" label="单价" align="center" />
<el-table-column prop="unitPrice" label="单价" align="center">
<template #default="scope">
{{ proxy.formatPrice(scope.row.unitPrice) }}
</template>
</el-table-column>
<el-table-column prop="price" label="总价" align="center">
<template #default="scope">
{{
((scope.row.quantity ? Number(scope.row.quantity) : 0) - (scope.row.useQuantity ? Number(scope.row.useQuantity) : 0)) *
Number(scope.row.unitPrice) ==
0
? ''
: (
((scope.row.quantity ? Number(scope.row.quantity) : 0) - (scope.row.useQuantity ? Number(scope.row.useQuantity) : 0)) *
Number(scope.row.unitPrice)
).toFixed(2)
proxy.formatPrice(
((scope.row.quantity ? Number(scope.row.quantity) : 0) -
(scope.row.useQuantity ? Number(scope.row.useQuantity) : 0) -
(scope.row.selectNum ? Number(scope.row.selectNum) : 0)) *
Number(scope.row.unitPrice) ==
0
? ''
: ((scope.row.quantity ? Number(scope.row.quantity) : 0) -
(scope.row.useQuantity ? Number(scope.row.useQuantity) : 0) -
(scope.row.selectNum ? Number(scope.row.selectNum) : 0)) *
Number(scope.row.unitPrice),
false
)
}}
</template>
</el-table-column>
@ -190,6 +217,7 @@ import { useUserStoreHook } from '@/store/modules/user';
import { getDicts } from '@/api/system/dict/data';
import { Plus } from '@element-plus/icons-vue';
import { FormInstance } from 'element-plus';
const { proxy } = getCurrentInstance();
import {
treeList,
sheetList,
@ -328,18 +356,10 @@ const getVersionNums = async () => {
getSheetName();
} else {
treeForm.value.versions = '';
ElMessage({
message: '获取版本号失败',
type: 'warning'
});
}
}
} catch (error) {
console.log(error);
ElMessage({
message: '获取版本号失败',
type: 'warning'
});
}
};
//获取表名
@ -356,19 +376,11 @@ const getSheetName = async () => {
treeForm.value.sheet = res.data[0];
} else {
treeForm.value.sheet = '';
ElMessage({
message: '获取表名失败',
type: 'warning'
});
}
getTreeList();
}
} catch (error) {
console.log(error);
ElMessage({
message: '获取表名失败',
type: 'warning'
});
}
};
const handleSelection = (selection: any) => {

View File

@ -60,8 +60,10 @@
<el-table ref="tableRef" v-loading="loading" :data="tableData" row-key="id" border lazy default-expand-all>
<el-table-column prop="num" label="编号" />
<el-table-column prop="name" label="工程或费用名称" />
<el-table-column prop="unit" label="单位" />
<el-table-column prop="quantity" label="数量">
<el-table-column prop="unit" label="单位" align="center" />
<el-table-column prop="taxRate" label="税率" align="center" />
<el-table-column prop="specification" label="规格" align="center" />
<el-table-column prop="quantity" label="数量" align="center">
<template #default="scope">
{{ scope.row.children.length > 0 ? '' : scope.row.quantity }}
</template>
@ -77,8 +79,8 @@
changePrice(scope.row);
}
"
:precision="2"
:step="0.1"
:min="0"
:precision="4"
:controls="false"
v-if="scope.row.quantity && scope.row.quantity != 0"
/>
@ -86,9 +88,7 @@
</el-table-column>
<el-table-column prop="price" label="总价" align="center">
<template #default="scope">
<!-- {{ scope.row.children.length > 0 ? scope.row.children.reduce((sum, child) => sum + child.price, 0) : scope.row.price }} -->
{{ scope.row.price != 0 ? Number(scope.row.price).toFixed(2) : null }}
<!-- {{ scope.row.price }} -->
{{ proxy.formatPrice(scope.row.price) }}
</template>
</el-table-column>
<el-table-column prop="operate" label="操作" align="center">
@ -124,7 +124,7 @@ const loading = ref(false);
const options = ref<any[]>([]);
const sheets = ref<any[]>([]);
const tableData = ref<any[]>([]);
const isExpandAll = ref(false);
const isExpandAll = ref(true);
const reviewStatus = ref('');
const versionObj: any = ref({});
const versionMap = new Map();
@ -150,18 +150,10 @@ const getVersionNums = async () => {
getSheetName();
} else {
queryForm.value.versions = '';
ElMessage({
message: '获取版本号失败',
type: 'warning'
});
}
}
} catch (error) {
console.log(error);
ElMessage({
message: '获取版本号失败',
type: 'warning'
});
}
};
//选择版本号
@ -193,19 +185,11 @@ const getSheetName = async () => {
queryForm.value.sheet = res.data[0];
} else {
queryForm.value.sheet = '';
ElMessage({
message: '获取表名失败',
type: 'warning'
});
}
getTableData();
}
} catch (error) {
console.log(error);
ElMessage({
message: '获取表名失败',
type: 'warning'
});
}
};
//获取表格
@ -323,7 +307,7 @@ const handleExport = () => {
versions: queryForm.value.versions,
type: '1'
},
`限价一览${queryForm.value.sheet}.xlsx`
`限价一览${queryForm.value.sheet}.xlsx`
);
};
// 审批

View File

@ -41,10 +41,14 @@
<el-table-column prop="specification" label="规格" />
<el-table-column prop="unit" label="单位" />
<el-table-column prop="quantity" label="数量" />
<el-table-column prop="unitPrice" label="单价" align="center" />
<el-table-column prop="price" label="总价" align="center">
<el-table-column prop="unitPrice" label="单价" align="center">
<template #default="scope">
{{ scope.row.price != 0 ? Number(scope.row.price).toFixed(2) : null }}
{{ proxy.formatPrice(scope.row.unitPrice, false) }}
</template>
</el-table-column>
<el-table-column prop="price" label="总价" align="center" width="150">
<template #default="scope">
{{ proxy.formatPrice(scope.row.price) }}
</template>
</el-table-column>
</el-table>
@ -70,8 +74,12 @@
</div>
<template #footer>
<div class="dialog-footer p-4 border-t border-gray-100 flex justify-end space-x-3">
<el-button @click="handleClose" class="px-4 py-2 border border-gray-300 rounded-md text-gray-700 hover:bg-gray-50 transition-colors">取消</el-button>
<el-button type="primary" @click="submitFlow()" class="px-4 py-2 bg-primary text-white rounded-md hover:bg-primary/90 transition-colors">确认</el-button>
<el-button @click="handleClose" class="px-4 py-2 border border-gray-300 rounded-md text-gray-700 hover:bg-gray-50 transition-colors"
>取消</el-button
>
<el-button type="primary" @click="submitFlow()" class="px-4 py-2 bg-primary text-white rounded-md hover:bg-primary/90 transition-colors"
>确认</el-button
>
</div>
</template>
</el-dialog>

View File

@ -1,54 +1,19 @@
<template>
<div class="p-2">
<el-tabs type="border-card" v-model="activeName" @tab-click="handleClick">
<el-tab-pane label="变更单" name="1"
><el-card shadow="never">
<template #header>
<el-row :gutter="10" class="mb8">
<el-col :span="1.5">
<el-button type="primary" plain icon="Plus" :disabled="addSingle" @click="handleAddApp" v-hasPermi="['quality:qualityInspection:add']"
>上传变更单模版</el-button
>
</el-col>
<right-toolbar v-model:showSearch="showSearch" @queryTable="getList"></right-toolbar>
</el-row>
</template>
<EngineeringChangeApplicationForm
@selection-change="handleSelectionChange"
:data="tableData"
:thumbnail="projectTypeOptions[1].thumbnail"
@delete="handleDelete"
></EngineeringChangeApplicationForm>
<pagination
v-show="total > 0"
:total="total"
v-model:page="queryParams.pageNum"
v-model:limit="queryParams.pageSize"
@pagination="getList"
/> </el-card
></el-tab-pane>
<el-tab-pane label="外部联系单" name="0"
><el-card shadow="never">
<template #header>
<el-row :gutter="10" class="mb8">
<el-col :span="1.5">
<el-button type="primary" plain icon="Plus" :disabled="addSingle" @click="handleAdd" v-hasPermi="['quality:qualityInspection:add']"
>上传外部联系单模版</el-button
>
</el-col>
<right-toolbar v-model:showSearch="showSearch" @queryTable="getList"></right-toolbar>
</el-row>
</template>
<Contactform @selection-change="handleSelectionChange" :data="tableData" @delete="handleDelete"></Contactform>
<pagination
v-show="total > 0"
:total="total"
v-model:page="queryParams.pageNum"
v-model:limit="queryParams.pageSize"
@pagination="getList"
/> </el-card
></el-tab-pane>
</el-tabs>
<el-card shadow="never">
<template #header>
<el-row :gutter="10" class="mb8">
<el-col :span="1.5">
<el-button type="primary" plain icon="Plus" :disabled="addSingle" @click="handleAdd" v-hasPermi="['quality:qualityInspection:add']"
>上传外部联系单模版</el-button
>
</el-col>
<right-toolbar v-model:showSearch="showSearch" @queryTable="getList"></right-toolbar>
</el-row>
</template>
<Contactform @selection-change="handleSelectionChange" :data="tableData" @delete="handleDelete"></Contactform>
<pagination v-show="total > 0" :total="total" v-model:page="queryParams.pageNum" v-model:limit="queryParams.pageSize" @pagination="getList" />
</el-card>
<el-dialog title="新增模板" v-model="dialogVisible" width="800">
<el-form :model="form" :rules="rules" ref="formRef" label-width="110px">
<div class="flex">
@ -109,14 +74,11 @@
<script setup lang="ts">
import { useUserStoreHook } from '@/store/modules/user';
import type { FormInstance, FormRules } from 'element-plus';
import type { FormInstance } from 'element-plus';
import Contactform from './components/contactform.vue';
import EngineeringChangeApplicationForm from './components/engineeringChangeApplicationForm.vue';
import { listContactTypeformtemplate } from '@/api/cory/contactformtemplate';
import { addContactnotice, delContactnotice, listContactnotice } from '@/api/cory/contactnotice';
const { proxy } = getCurrentInstance() as ComponentInternalInstance;
const { wf_business_status } = toRefs(proxy?.useDict('wf_business_status'));
// 获取用户 store
const userStore = useUserStoreHook();
// 从 store 中获取项目列表和当前选中的项目

Some files were not shown because too many files have changed in this diff Show More