Merge branch 'tcy' of http://192.168.110.2:3000/taoge_xiaodi/maintenance_system into lx
@ -17,6 +17,8 @@
|
||||
"MaybeRefOrGetter": true,
|
||||
"PropType": true,
|
||||
"Ref": true,
|
||||
"Slot": true,
|
||||
"Slots": true,
|
||||
"VNode": true,
|
||||
"WritableComputedRef": true,
|
||||
"acceptHMRUpdate": true,
|
||||
@ -35,6 +37,7 @@
|
||||
"createInjectionState": true,
|
||||
"createPinia": true,
|
||||
"createReactiveFn": true,
|
||||
"createRef": true,
|
||||
"createReusableTemplate": true,
|
||||
"createSharedComposable": true,
|
||||
"createTemplatePromise": true,
|
||||
@ -315,9 +318,6 @@
|
||||
"watchThrottled": true,
|
||||
"watchTriggerable": true,
|
||||
"watchWithFilter": true,
|
||||
"whenever": true,
|
||||
"Slot": true,
|
||||
"Slots": true,
|
||||
"createRef": true
|
||||
"whenever": true
|
||||
}
|
||||
}
|
||||
|
||||
BIN
public/assets/caigou.png
Normal file
|
After Width: | Height: | Size: 2.5 KiB |
BIN
public/assets/dialog1.png
Normal file
|
After Width: | Height: | Size: 411 KiB |
BIN
public/assets/jkcckj.png
Normal file
|
After Width: | Height: | Size: 38 KiB |
BIN
public/assets/jkfdl.png
Normal file
|
After Width: | Height: | Size: 42 KiB |
BIN
public/assets/jkjrbjcs.png
Normal file
|
After Width: | Height: | Size: 34 KiB |
BIN
public/assets/jklxsc.png
Normal file
|
After Width: | Height: | Size: 45 KiB |
BIN
public/assets/no.png
Normal file
|
After Width: | Height: | Size: 1.3 KiB |
BIN
public/assets/play.png
Normal file
|
After Width: | Height: | Size: 303 B |
BIN
public/assets/qian.jpg
Normal file
|
After Width: | Height: | Size: 827 B |
BIN
public/assets/re.png
Normal file
|
After Width: | Height: | Size: 1.3 KiB |
1
public/assets/svg/delete.svg
Normal file
@ -0,0 +1 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="12" height="12" viewBox="0 0 12 12" fill="none"><path d="M10.0923 2.25614C10.3323 2.25614 10.5303 2.29614 10.6863 2.37614C10.8423 2.45614 10.9663 2.55614 11.0583 2.67614C11.1503 2.79614 11.2143 2.92614 11.2503 3.06614C11.2863 3.20614 11.3043 3.33614 11.3043 3.45614C11.3043 3.51214 11.3023 3.55614 11.2983 3.58814C11.2943 3.62014 11.2923 3.64814 11.2923 3.67214L11.2923 3.74414L10.5003 3.74414L10.5003 10.0441C10.5003 10.2041 10.4683 10.3581 10.4043 10.5061C10.3403 10.6541 10.2483 10.7841 10.1283 10.8961C10.0083 11.0081 9.86228 11.0981 9.69028 11.1661C9.51828 11.2341 9.32028 11.2681 9.09628 11.2681L3.74428 11.2681C3.53628 11.2681 3.34028 11.2361 3.15628 11.1721C2.97229 11.1081 2.81428 11.0181 2.68228 10.9021C2.55028 10.7861 2.44628 10.6461 2.37028 10.4821C2.29428 10.3181 2.25628 10.1321 2.25628 9.92414L2.25628 3.74414L1.51228 3.74414C1.50428 3.73614 1.50028 3.71614 1.50028 3.68414C1.49228 3.64414 1.48828 3.52014 1.48828 3.31214C1.48828 3.20814 1.51228 3.09214 1.56028 2.96414C1.60828 2.83614 1.68028 2.71814 1.77628 2.61014C1.87228 2.50214 1.99628 2.41214 2.14828 2.34014C2.30028 2.26814 2.48028 2.23214 2.68828 2.23214L3.75628 2.23214L3.75628 1.50014C3.75628 1.29214 3.82828 1.11414 3.97228 0.966141C4.11628 0.818141 4.29228 0.744141 4.50028 0.744141L8.25628 0.744141C8.53628 0.744141 8.73028 0.818141 8.83828 0.966141C8.94628 1.11414 9.00028 1.29214 9.00028 1.50014L9.00028 2.24414C9.16828 2.25214 9.34828 2.25614 9.54028 2.25614L10.0923 2.25614ZM4.50028 2.25614L8.25628 2.25614L8.25628 1.50014L4.50028 1.50014L4.50028 2.25614ZM4.12828 9.85214C4.38428 9.85214 4.51228 9.68814 4.51228 9.36014L4.51228 3.79214L3.76828 3.79214L3.76828 9.36014C3.76828 9.52814 3.79429 9.65214 3.84628 9.73214C3.89828 9.81214 3.99229 9.85214 4.12828 9.85214ZM6.39628 9.84014C6.53228 9.84014 6.62428 9.80214 6.67228 9.72614C6.72028 9.65014 6.74428 9.52814 6.74428 9.36014L6.74428 3.79214L6.00028 3.79214L6.00028 9.36014C6.00028 9.68014 6.13228 9.84014 6.39628 9.84014ZM8.65228 9.81614C8.79628 9.81614 8.89228 9.77814 8.94028 9.70214C8.98828 9.62614 9.01228 9.50414 9.01228 9.33614L9.01228 3.79214L8.25628 3.79214L8.25628 9.33614C8.25628 9.65614 8.38828 9.81614 8.65228 9.81614Z" fill="#186DF5" ></path></svg>
|
||||
|
After Width: | Height: | Size: 2.2 KiB |
1
public/assets/svg/download.svg
Normal file
@ -0,0 +1 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="12" height="12" viewBox="0 0 12 12" fill="none"><path d="M9.71435 10.4777L2.22855 10.4777C1.40179 10.4777 0.731445 9.80755 0.731445 8.98058L0.731445 7.10912C0.731445 6.90247 0.899128 6.7349 1.10565 6.7349L1.85435 6.7349C2.06101 6.7349 2.22855 6.90247 2.22855 7.10912L2.22855 8.23203C2.22855 8.64549 2.56367 8.98059 2.97711 8.98059L8.96579 8.98059C9.37924 8.98059 9.71435 8.64549 9.71435 8.23203L9.71435 7.10912C9.71435 6.90247 9.8819 6.7349 10.0887 6.7349L10.8372 6.7349C11.0439 6.7349 11.2115 6.90247 11.2115 7.10912L11.2115 8.98059C11.2115 9.80755 10.5413 10.4777 9.71435 10.4777ZM2.92875 3.13454C3.08016 2.98313 3.32585 2.98313 3.47728 3.13454L5.22302 4.8803L5.22302 1.11169C5.22302 0.905035 5.39062 0.737305 5.59723 0.737305L6.34579 0.737305C6.55249 0.737305 6.72015 0.905035 6.72015 1.11169L6.72015 4.8803L8.4659 3.13454C8.61733 2.98313 8.86289 2.98313 9.01431 3.13454L9.56289 3.68319C9.71432 3.83462 9.71432 4.08015 9.56289 4.23171L6.47159 7.32305C6.45822 7.33639 6.21771 7.48341 5.9757 7.48352C5.73105 7.48364 5.48493 7.33654 5.47156 7.32305L2.38011 4.23171C2.22868 4.08014 2.22868 3.83462 2.38011 3.68319L2.92875 3.13454Z" fill="#186DF5" ></path></svg>
|
||||
|
After Width: | Height: | Size: 1.2 KiB |
1
public/assets/svg/huanyuan.svg
Normal file
@ -0,0 +1 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="32" height="32" viewBox="0 0 32 32" fill="none"><path d="M17.9776 16.1268L21.269 12.8125L21.269 13.6583C21.269 14.4614 21.9287 15.1097 22.7318 15.1097C23.535 15.1097 24.1833 14.4614 24.1833 13.6583L24.1833 9.26969C24.1833 8.46651 23.535 7.81826 22.7318 7.81826L18.3433 7.81826C17.5401 7.81826 16.8918 8.46651 16.8918 9.26969C16.8918 10.0728 17.5401 10.7325 18.3433 10.7325L19.189 10.7325L15.8747 14.024C15.8578 14.0412 15.845 14.0631 15.829 14.0811C15.8129 14.0991 15.7984 14.1195 15.7833 14.1383C15.7681 14.157 15.7518 14.1759 15.7376 14.1954C15.7233 14.2149 15.7165 14.2324 15.7033 14.2525C15.69 14.2727 15.6813 14.3003 15.669 14.3211C15.6567 14.3419 15.6233 14.3684 15.6233 14.3897C15.6233 14.411 15.6004 14.425 15.6004 14.4468C15.6004 14.4687 15.5661 14.4817 15.5661 14.504C15.5661 14.5263 15.5433 14.5612 15.5433 14.584C15.5433 14.6067 15.509 14.6295 15.509 14.6525C15.509 14.6756 15.4976 14.6863 15.4976 14.7097C15.4976 14.7331 15.4861 14.766 15.4861 14.7897C15.4861 14.8134 15.4633 14.8458 15.4633 14.8697C15.4633 14.8935 15.4518 14.9028 15.4518 14.9268C15.4518 14.9508 15.4518 14.9828 15.4518 15.0068C15.4518 15.0309 15.4518 15.0513 15.4518 15.0754C15.4518 15.0995 15.4518 15.1199 15.4518 15.144C15.4518 15.1681 15.4518 15.2 15.4518 15.224C15.4518 15.248 15.4633 15.2687 15.4633 15.2925C15.4633 15.3164 15.4861 15.3374 15.4861 15.3611C15.4861 15.3848 15.4976 15.4177 15.4976 15.4411C15.4976 15.4645 15.509 15.4752 15.509 15.4983C15.509 15.5214 15.5433 15.5441 15.5433 15.5668C15.5433 15.5895 15.5661 15.6245 15.5661 15.6468C15.5661 15.6691 15.6004 15.6821 15.6004 15.704C15.6004 15.7258 15.6233 15.7512 15.6233 15.7725C15.6233 15.7939 15.6567 15.8089 15.669 15.8297C15.6813 15.8505 15.69 15.8781 15.7033 15.8983C15.7165 15.9184 15.7233 15.9359 15.7376 15.9554C15.7518 15.9749 15.7681 15.9938 15.7833 16.0125C15.7984 16.0313 15.8129 16.0517 15.829 16.0697C15.845 16.0877 15.8578 16.1097 15.8747 16.1268C16.4588 16.6964 17.408 16.6964 17.9776 16.1268ZM8.12613 25.3268L12.5147 25.3268C13.3179 25.3268 13.9661 24.6786 13.9661 23.8754C13.9661 23.0722 13.3179 22.4125 12.5147 22.4125L11.669 22.4125L15.0176 19.0754C15.5871 18.5059 15.5871 17.5681 15.0176 16.984C15.0004 16.9671 14.9898 16.9429 14.9718 16.9268C14.9539 16.9108 14.9334 16.8963 14.9147 16.8811C14.8959 16.866 14.877 16.8611 14.8576 16.8468C14.8381 16.8326 14.8205 16.8144 14.8004 16.8011C14.7803 16.7878 14.7526 16.7677 14.7318 16.7554C14.7111 16.7431 14.6846 16.7211 14.6633 16.7211C14.6419 16.7211 14.628 16.6983 14.6061 16.6983C14.5843 16.6983 14.5599 16.664 14.5376 16.664C14.5153 16.664 14.4917 16.6411 14.469 16.6411C14.4463 16.6411 14.4235 16.6183 14.4004 16.6183C14.3773 16.6183 14.3553 16.5954 14.3318 16.5954C14.3085 16.5954 14.2869 16.584 14.2633 16.584C14.2396 16.584 14.2186 16.5725 14.1947 16.5725C14.1709 16.5725 14.1501 16.5611 14.1261 16.5611C14.1021 16.5611 14.0702 16.5497 14.0461 16.5497C14.022 16.5497 14.0017 16.5497 13.9776 16.5497C13.9535 16.5497 13.9331 16.5497 13.909 16.5497C13.8849 16.5497 13.853 16.5611 13.829 16.5611C13.805 16.5611 13.7843 16.5725 13.7604 16.5725C13.7366 16.5725 13.7155 16.584 13.6918 16.584C13.6682 16.584 13.6352 16.5954 13.6118 16.5954C13.5885 16.5954 13.5778 16.6183 13.5547 16.6183C13.5316 16.6183 13.4974 16.6411 13.4747 16.6411C13.452 16.6411 13.4284 16.664 13.4061 16.664C13.3838 16.664 13.3708 16.6983 13.349 16.6983C13.3271 16.6983 13.3018 16.7211 13.2804 16.7211C13.2591 16.7211 13.2326 16.7431 13.2118 16.7554C13.1911 16.7677 13.1749 16.7878 13.1547 16.8011C13.1346 16.8144 13.117 16.8326 13.0976 16.8468C13.0781 16.8611 13.0592 16.866 13.0404 16.8811C13.0217 16.8963 13.0013 16.9108 12.9833 16.9268C12.9653 16.9429 12.9548 16.9671 12.9376 16.984L9.58899 20.3325L9.58899 19.4868C9.58899 18.6837 8.92929 18.0354 8.12613 18.0354C7.32296 18.0354 6.6747 18.6837 6.6747 19.4868L6.6747 23.8754C6.6747 24.6786 7.32296 25.3268 8.12613 25.3268ZM25.6576 3.42969L5.20042 3.42969C3.59406 3.42969 2.28613 4.73762 2.28613 6.34397L2.28613 26.8011C2.28613 28.4075 3.59406 29.7154 5.20042 29.7154L25.6576 29.7154C27.2639 29.7154 28.5718 28.4075 28.5718 26.8011L28.5718 6.34397C28.5718 4.73762 27.2639 3.42969 25.6576 3.42969ZM25.6576 26.8011L5.20042 26.8011L5.20042 6.34397L25.6576 6.34397L25.6576 26.8011Z" fill="#FFFFFF" ></path></svg>
|
||||
|
After Width: | Height: | Size: 4.2 KiB |
1
public/assets/svg/jietu.svg
Normal file
|
After Width: | Height: | Size: 16 KiB |
1
public/assets/svg/play.svg
Normal file
@ -0,0 +1 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="12" height="12" viewBox="0 0 12 12" fill="none"><path d="M9.1496 5.57504L3.34961 1.97504C3.0246 1.77505 2.59961 2.02504 2.59961 2.40004L2.59961 9.60005C2.59961 9.97505 3.0246 10.225 3.34961 10.0251L9.12461 6.42505C9.4746 6.25004 9.4746 5.75005 9.1496 5.57504Z" fill="#186DF5" ></path></svg>
|
||||
|
After Width: | Height: | Size: 382 B |
1
public/assets/svg/quanpin.svg
Normal file
@ -0,0 +1 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="32" height="32" viewBox="0 0 32 32" fill="none"><path d="M11.9501 11.3874L11.9501 8.01232C11.9501 7.4532 11.4799 7 10.9 7C10.3199 7 9.84997 7.4532 9.84997 8.01232L9.84997 10.7125L7.05011 10.7125C6.46998 10.7125 6 11.1657 6 11.7248C6 12.2842 6.46998 12.7373 7.05011 12.7373L10.5499 12.7373C11.3231 12.7373 11.9501 12.133 11.9501 11.3874ZM11.9501 21.5125L11.9501 24.8873C11.9501 25.4467 11.4799 25.8999 10.9 25.8999C10.3199 25.8999 9.84997 25.4467 9.84997 24.8873L9.84997 22.1874L7.05011 22.1874C6.46998 22.1874 6 21.7342 6 21.1748C6 20.6157 6.46998 20.1622 7.05011 20.1622L10.5499 20.1622C11.3231 20.1622 11.9501 20.7668 11.9501 21.5125ZM19.65 21.5125L19.65 24.8873C19.65 25.4467 20.12 25.8999 20.7001 25.8999C21.2799 25.8999 21.7499 25.4467 21.7499 24.8873L21.7499 22.1874L24.55 22.1874C25.1298 22.1874 25.6001 21.7342 25.6001 21.1748C25.6001 20.6157 25.1299 20.1622 24.55 20.1622L21.0499 20.1622C20.2767 20.1622 19.65 20.7668 19.65 21.5125ZM19.65 11.3874L19.65 8.01232C19.65 7.4532 20.12 7 20.7001 7C21.2799 7 21.7499 7.4532 21.7499 8.01232L21.7499 10.7125L24.55 10.7125C25.1298 10.7125 25.6001 11.1657 25.6001 11.7248C25.6001 12.2842 25.1299 12.7373 24.55 12.7373L21.0499 12.7373C20.2767 12.7373 19.65 12.133 19.65 11.3874Z" stroke="rgba(255, 255, 255, 1)" stroke-width="0.8" fill="#FFFFFF" ></path><path d="M2 27.2998L2 5.69984C2 4.20862 3.25368 3 4.80014 3L27.2001 3C28.7465 3 30 4.20862 30 5.69984L30 27.2998C30 28.791 28.7465 30 27.2001 30L4.80014 30C3.25368 30 2 28.791 2 27.2998ZM27.2001 5.02491L4.80014 5.02491C4.30497 5.02491 4.10016 5.22265 4.10016 5.69984L4.10016 27.2998C4.10016 27.7773 4.30497 27.9751 4.80014 27.9751L27.9 27.9751L27.9 5.69984C27.9 5.22265 27.695 5.02491 27.2001 5.02491Z" stroke="rgba(255, 255, 255, 1)" stroke-width="0.8" fill="#FFFFFF" ></path></svg>
|
||||
|
After Width: | Height: | Size: 1.8 KiB |
BIN
public/assets/yes.png
Normal file
|
After Width: | Height: | Size: 1.1 KiB |
49
src/api/zhinengxunjian/baoxiou/index.ts
Normal file
@ -0,0 +1,49 @@
|
||||
import request from '@/utils/request';
|
||||
import { AxiosPromise } from 'axios';
|
||||
//查询列表
|
||||
export const baoxiulist = (query) => {
|
||||
return request({
|
||||
url: '/ops/report/list',
|
||||
method: 'get',
|
||||
params: query
|
||||
});
|
||||
};
|
||||
//新增待办事项
|
||||
export const addbaoxiu = (data) => {
|
||||
return request({
|
||||
url: '/ops/report',
|
||||
method: 'post',
|
||||
data: data
|
||||
});
|
||||
};
|
||||
//修改待办事项
|
||||
export const updatebaoxiu = (data) => {
|
||||
return request({
|
||||
url: '/ops/report',
|
||||
method: 'put',
|
||||
data: data
|
||||
});
|
||||
};
|
||||
//删除待办事项
|
||||
|
||||
export function delbaoxiu(ids) {
|
||||
return request({
|
||||
url: `/ops/report/${ids}`, // 拼接ids作为路径参数
|
||||
method: 'delete'
|
||||
});
|
||||
}
|
||||
|
||||
export const baoxiuDetail = (id) => {
|
||||
return request({
|
||||
url: `/ops/report/${id}`,
|
||||
method: 'get'
|
||||
});
|
||||
};
|
||||
|
||||
export const uploadbaoxiu = (data) => {
|
||||
return request({
|
||||
url: '/resource/oss/upload',
|
||||
method: 'post',
|
||||
data: data
|
||||
});
|
||||
};
|
||||
34
src/api/zhinengxunjian/daiban/index.ts
Normal file
@ -0,0 +1,34 @@
|
||||
import request from '@/utils/request';
|
||||
import { AxiosPromise } from 'axios';
|
||||
//查询列表
|
||||
export const daibanlist = (query) => {
|
||||
return request({
|
||||
url: '/ops/matter/list',
|
||||
method: 'get',
|
||||
params: query
|
||||
});
|
||||
};
|
||||
//新增待办事项
|
||||
export const adddaiban = (data) => {
|
||||
return request({
|
||||
url: '/ops/matter',
|
||||
method: 'post',
|
||||
data: data
|
||||
});
|
||||
};
|
||||
//修改待办事项
|
||||
export const updatedaiban = (data) => {
|
||||
return request({
|
||||
url: '/ops/matter',
|
||||
method: 'put',
|
||||
data: data
|
||||
});
|
||||
};
|
||||
//删除待办事项
|
||||
|
||||
export function deldaiban(ids) {
|
||||
return request({
|
||||
url: `/ops/matter/${ids}`, // 拼接ids作为路径参数
|
||||
method: 'delete'
|
||||
});
|
||||
}
|
||||
63
src/api/zhinengxunjian/inspection/item/index.ts
Normal file
@ -0,0 +1,63 @@
|
||||
import request from '@/utils/request';
|
||||
import { AxiosPromise } from 'axios';
|
||||
import { ItemVO, ItemForm, ItemQuery } from '@/api/zhinengxunjian/inspection/item/types';
|
||||
|
||||
/**
|
||||
* 查询运维-巡检-自定义巡检项列表
|
||||
* @param query
|
||||
* @returns {*}
|
||||
*/
|
||||
|
||||
export const listItem = (query?: ItemQuery): AxiosPromise<ItemVO[]> => {
|
||||
return request({
|
||||
url: '/ops/item/list',
|
||||
method: 'get',
|
||||
params: query
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
* 查询运维-巡检-自定义巡检项详细
|
||||
* @param id
|
||||
*/
|
||||
export const getItem = (id: string | number): AxiosPromise<ItemVO> => {
|
||||
return request({
|
||||
url: '/ops/item/' + id,
|
||||
method: 'get'
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
* 新增运维-巡检-自定义巡检项
|
||||
* @param data
|
||||
*/
|
||||
export const addItem = (data: ItemForm) => {
|
||||
return request({
|
||||
url: '/ops/item',
|
||||
method: 'post',
|
||||
data: data
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
* 修改运维-巡检-自定义巡检项
|
||||
* @param data
|
||||
*/
|
||||
export const updateItem = (data: ItemForm) => {
|
||||
return request({
|
||||
url: '/ops/item',
|
||||
method: 'put',
|
||||
data: data
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
* 删除运维-巡检-自定义巡检项
|
||||
* @param id
|
||||
*/
|
||||
export const delItem = (id: string | number | Array<string | number>) => {
|
||||
return request({
|
||||
url: '/ops/item/' + id,
|
||||
method: 'delete'
|
||||
});
|
||||
};
|
||||
46
src/api/zhinengxunjian/inspection/item/types.ts
Normal file
@ -0,0 +1,46 @@
|
||||
export interface ItemVO {
|
||||
/**
|
||||
*
|
||||
*/
|
||||
id: string | number;
|
||||
|
||||
/**
|
||||
* 自定义巡检项名称
|
||||
*/
|
||||
name: string;
|
||||
|
||||
/**
|
||||
* 业务id,巡检计划1
|
||||
*/
|
||||
type: string;
|
||||
}
|
||||
|
||||
export interface ItemForm extends BaseEntity {
|
||||
/**
|
||||
* 自定义巡检项名称
|
||||
*/
|
||||
name?: string;
|
||||
|
||||
/**
|
||||
* 业务id,巡检计划1
|
||||
*/
|
||||
type?: string;
|
||||
projectId?: number;
|
||||
}
|
||||
|
||||
export interface ItemQuery extends PageQuery {
|
||||
/**
|
||||
* 自定义巡检项名称
|
||||
*/
|
||||
name?: string;
|
||||
|
||||
/**
|
||||
* 业务id,巡检计划1
|
||||
*/
|
||||
type?: string;
|
||||
|
||||
/**
|
||||
* 日期范围参数
|
||||
*/
|
||||
params?: any;
|
||||
}
|
||||
49
src/api/zhinengxunjian/shiyan/index.ts
Normal file
@ -0,0 +1,49 @@
|
||||
import request from '@/utils/request';
|
||||
import { AxiosPromise } from 'axios';
|
||||
//查询列表
|
||||
export const shiyanlist = (query) => {
|
||||
return request({
|
||||
url: '/ops/testPlan/list',
|
||||
method: 'get',
|
||||
params: query
|
||||
});
|
||||
};
|
||||
//新增
|
||||
export const addshiyan = (data) => {
|
||||
return request({
|
||||
url: '/ops/testPlan',
|
||||
method: 'post',
|
||||
data: data
|
||||
});
|
||||
};
|
||||
//修改
|
||||
export const updateshiyan = (data) => {
|
||||
return request({
|
||||
url: '/ops/testPlan',
|
||||
method: 'put',
|
||||
data: data
|
||||
});
|
||||
};
|
||||
//删除
|
||||
export const delshiyan = (ids) => {
|
||||
return request({
|
||||
url: `/ops/testPlan${ids}`,
|
||||
method: 'delete'
|
||||
});
|
||||
};
|
||||
//查询人员
|
||||
export const shiyanUserlist = (query) => {
|
||||
return request({
|
||||
url: '/ops/constructionUser/list',
|
||||
method: 'get',
|
||||
params: query
|
||||
});
|
||||
};
|
||||
|
||||
//详情
|
||||
export const shiyanDetail = (id) => {
|
||||
return request({
|
||||
url: `/ops/testPlan/${id}`,
|
||||
method: 'get'
|
||||
});
|
||||
};
|
||||
41
src/api/zhinengxunjian/shiyan/renwu.ts
Normal file
@ -0,0 +1,41 @@
|
||||
import request from '@/utils/request';
|
||||
import { AxiosPromise } from 'axios';
|
||||
//查询列表
|
||||
export const syrenwulist = (query) => {
|
||||
return request({
|
||||
url: '/ops/testTask/list',
|
||||
method: 'get',
|
||||
params: query
|
||||
});
|
||||
};
|
||||
//新增
|
||||
export const addsyrenwu = (data) => {
|
||||
return request({
|
||||
url: '/ops/testTask',
|
||||
method: 'post',
|
||||
data: data
|
||||
});
|
||||
};
|
||||
//修改
|
||||
export const updatesyrenwu = (data) => {
|
||||
return request({
|
||||
url: '/ops/testTask',
|
||||
method: 'put',
|
||||
data: data
|
||||
});
|
||||
};
|
||||
//删除
|
||||
export const delsyrenwu = (ids) => {
|
||||
return request({
|
||||
url: `/ops/testTask${ids}`,
|
||||
method: 'delete'
|
||||
});
|
||||
};
|
||||
|
||||
//详情
|
||||
export const syrenwuDetail = (id) => {
|
||||
return request({
|
||||
url: `/ops/testTask/${id}`,
|
||||
method: 'get'
|
||||
});
|
||||
};
|
||||
56
src/api/zhinengxunjian/xunjian/index.ts
Normal file
@ -0,0 +1,56 @@
|
||||
import request from '@/utils/request';
|
||||
import { AxiosPromise } from 'axios';
|
||||
//查询列表
|
||||
export const xunjianlist = (query) => {
|
||||
return request({
|
||||
url: '/ops/plan/list',
|
||||
method: 'get',
|
||||
params: query
|
||||
});
|
||||
};
|
||||
//新增
|
||||
export const addxunjian = (data) => {
|
||||
return request({
|
||||
url: '/ops/plan',
|
||||
method: 'post',
|
||||
data: data
|
||||
});
|
||||
};
|
||||
//修改
|
||||
export const updatexunjian = (data) => {
|
||||
return request({
|
||||
url: '/ops/plan',
|
||||
method: 'put',
|
||||
data: data
|
||||
});
|
||||
};
|
||||
//删除
|
||||
export const delxunjian = (ids) => {
|
||||
return request({
|
||||
url: `/ops/plan/${ids}`,
|
||||
method: 'delete'
|
||||
});
|
||||
};
|
||||
//查询人员
|
||||
export const xunjianUserlist = (query) => {
|
||||
return request({
|
||||
url: '/ops/constructionUser/list',
|
||||
method: 'get',
|
||||
params: query
|
||||
});
|
||||
};
|
||||
//查询巡检项
|
||||
export const xunjianItemlist = (query) => {
|
||||
return request({
|
||||
url: '/ops/item/list',
|
||||
method: 'get',
|
||||
params: query
|
||||
});
|
||||
};
|
||||
//详情
|
||||
export const xunjianDetail = (id) => {
|
||||
return request({
|
||||
url: `/ops/plan/${id}`,
|
||||
method: 'get'
|
||||
});
|
||||
};
|
||||
10
src/api/zhinengxunjian/xunjian/jilu.ts
Normal file
@ -0,0 +1,10 @@
|
||||
import request from '@/utils/request';
|
||||
import { AxiosPromise } from 'axios';
|
||||
//查询列表
|
||||
export const xunjianjilu = (query) => {
|
||||
return request({
|
||||
url: '/ops/task/record',
|
||||
method: 'get',
|
||||
params: query
|
||||
});
|
||||
};
|
||||
46
src/api/zhinengxunjian/xunjian/renwu.ts
Normal file
@ -0,0 +1,46 @@
|
||||
import request from '@/utils/request';
|
||||
export const xjrenwulist = (query) => {
|
||||
return request({
|
||||
url: '/ops/task/list',
|
||||
method: 'get',
|
||||
params: query
|
||||
});
|
||||
};
|
||||
//新增
|
||||
export const addxjrenwu = (data) => {
|
||||
return request({
|
||||
url: '/ops/task',
|
||||
method: 'post',
|
||||
data: data
|
||||
});
|
||||
};
|
||||
//修改
|
||||
export const updatexjrenwu = (data) => {
|
||||
return request({
|
||||
url: '/ops/task',
|
||||
method: 'put',
|
||||
data: data
|
||||
});
|
||||
};
|
||||
//删除
|
||||
export const delxjrenwu = (ids) => {
|
||||
return request({
|
||||
url: `/ops/task/${ids}`,
|
||||
method: 'delete'
|
||||
});
|
||||
};
|
||||
//详情
|
||||
export const xjrenwuDetail = (id) => {
|
||||
return request({
|
||||
url: `/ops/task/${id}`,
|
||||
method: 'get'
|
||||
});
|
||||
};
|
||||
//导出
|
||||
export const xjrenwuExport = (data) => {
|
||||
return request({
|
||||
url: '/ops/task/export',
|
||||
method: 'post',
|
||||
data: data
|
||||
});
|
||||
};
|
||||
@ -11,6 +11,7 @@
|
||||
font-weight: normal;
|
||||
font-style: normal;
|
||||
}
|
||||
|
||||
// 思源字体
|
||||
// @font-face {
|
||||
// font-family: 'SourceHanSansCN-Bold';
|
||||
@ -56,6 +57,7 @@
|
||||
font-weight: normal;
|
||||
font-style: normal;
|
||||
}
|
||||
|
||||
// @font-face {
|
||||
// font-family: 'SourceHanSansCN-Bold';
|
||||
// src: url('./ReflectTi/SourceHanSerifCN-Bold.otf');//暂时没用
|
||||
@ -110,6 +112,8 @@
|
||||
font-weight: normal;
|
||||
font-style: normal;
|
||||
}
|
||||
|
||||
|
||||
//阿里黑体
|
||||
@font-face {
|
||||
font-family: 'AlimamaShuHeiTi-Bold';
|
||||
@ -117,6 +121,7 @@
|
||||
font-weight: normal;
|
||||
font-style: normal;
|
||||
}
|
||||
|
||||
// @font-face {
|
||||
// font-family: 'Alibaba-PuHuiTi-Heavy';
|
||||
// src: url('./Alibaba/Alibaba-PuHuiTi-Heavy.otf');//暂时没用
|
||||
@ -135,6 +140,7 @@
|
||||
font-weight: normal;
|
||||
font-style: normal;
|
||||
}
|
||||
|
||||
// @font-face {
|
||||
// font-family: 'Alibaba-PuHuiTi-Regular';
|
||||
// src: url('./Alibaba/Alibaba-PuHuiTi-Regular.otf');//暂时没用
|
||||
@ -148,6 +154,7 @@
|
||||
font-weight: normal;
|
||||
font-style: normal;
|
||||
}
|
||||
|
||||
@font-face {
|
||||
font-family: 'D-Din';
|
||||
src: url('./D-Din//D-DIN.ttf');
|
||||
@ -155,6 +162,7 @@
|
||||
font-weight: normal;
|
||||
font-style: normal;
|
||||
}
|
||||
|
||||
@font-face {
|
||||
font-family: 'Roboto-Regular'; //Roboto
|
||||
src: url('./Roboto//Roboto-Regular.ttf');
|
||||
@ -162,4 +170,3 @@
|
||||
font-weight: normal;
|
||||
font-style: normal;
|
||||
}
|
||||
|
||||
|
||||
16
src/assets/styles/dialog.scss
Normal file
@ -0,0 +1,16 @@
|
||||
#custom-dialog {
|
||||
padding: 0;
|
||||
|
||||
.el-dialog__header {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.el-dialog__body {
|
||||
padding: 0 !important;
|
||||
}
|
||||
|
||||
.alert-content {
|
||||
padding: 80px;
|
||||
background: linear-gradient(180deg, rgba(0, 119, 255, 0.23) 0%, rgba(255, 255, 255, 0) 100%);
|
||||
}
|
||||
}
|
||||
@ -7,6 +7,8 @@
|
||||
@use './ruoyi.scss';
|
||||
@use 'animate.css';
|
||||
@use 'element-plus/dist/index.css';
|
||||
@use './dialog.scss';
|
||||
|
||||
|
||||
body {
|
||||
height: 100%;
|
||||
|
||||
225
src/views/inspection/item/index.vue
Normal file
@ -0,0 +1,225 @@
|
||||
<template>
|
||||
<div class="p-2">
|
||||
<transition :enter-active-class="proxy?.animate.searchAnimate.enter" :leave-active-class="proxy?.animate.searchAnimate.leave">
|
||||
<div v-show="showSearch" class="mb-[10px]">
|
||||
<el-card shadow="hover">
|
||||
<el-form ref="queryFormRef" :model="queryParams" :inline="true">
|
||||
<el-form-item label="自定义巡检项名称" prop="name">
|
||||
<el-input v-model="queryParams.name" placeholder="请输入自定义巡检项名称" clearable @keyup.enter="handleQuery" />
|
||||
</el-form-item>
|
||||
<el-form-item>
|
||||
<el-button type="primary" icon="Search" @click="handleQuery">搜索</el-button>
|
||||
<el-button icon="Refresh" @click="resetQuery">重置</el-button>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
</el-card>
|
||||
</div>
|
||||
</transition>
|
||||
|
||||
<el-card shadow="never">
|
||||
<template #header>
|
||||
<el-row :gutter="10" class="mb8">
|
||||
<el-col :span="1.5">
|
||||
<el-button type="primary" plain icon="Plus" @click="handleAdd" v-hasPermi="['inspection:item:add']">新增</el-button>
|
||||
</el-col>
|
||||
<el-col :span="1.5">
|
||||
<el-button type="success" plain icon="Edit" :disabled="single" @click="handleUpdate()" v-hasPermi="['inspection:item:edit']"
|
||||
>修改</el-button
|
||||
>
|
||||
</el-col>
|
||||
<el-col :span="1.5">
|
||||
<el-button type="danger" plain icon="Delete" :disabled="multiple" @click="handleDelete()" v-hasPermi="['inspection:item:remove']"
|
||||
>删除</el-button
|
||||
>
|
||||
</el-col>
|
||||
<el-col :span="1.5">
|
||||
<el-button type="warning" plain icon="Download" @click="handleExport" v-hasPermi="['inspection:item:export']">导出</el-button>
|
||||
</el-col>
|
||||
<right-toolbar v-model:showSearch="showSearch" @queryTable="getList"></right-toolbar>
|
||||
</el-row>
|
||||
</template>
|
||||
|
||||
<el-table v-loading="loading" border :data="itemList" @selection-change="handleSelectionChange">
|
||||
<el-table-column type="selection" width="55" align="center" />
|
||||
<el-table-column label="" align="center" prop="id" v-if="true" />
|
||||
<el-table-column label="自定义巡检项名称" align="center" prop="name" />
|
||||
<el-table-column label="业务id,巡检计划1" align="center" prop="type" />
|
||||
<el-table-column label="操作" align="center" class-name="small-padding fixed-width">
|
||||
<template #default="scope">
|
||||
<el-tooltip content="修改" placement="top">
|
||||
<el-button link type="primary" icon="Edit" @click="handleUpdate(scope.row)" v-hasPermi="['inspection:item:edit']"></el-button>
|
||||
</el-tooltip>
|
||||
<el-tooltip content="删除" placement="top">
|
||||
<el-button link type="primary" icon="Delete" @click="handleDelete(scope.row)" v-hasPermi="['inspection:item:remove']"></el-button>
|
||||
</el-tooltip>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
|
||||
<pagination v-show="total > 0" :total="total" v-model:page="queryParams.pageNum" v-model:limit="queryParams.pageSize" @pagination="getList" />
|
||||
</el-card>
|
||||
<!-- 添加或修改运维-巡检-自定义巡检项对话框 -->
|
||||
<el-dialog :title="dialog.title" v-model="dialog.visible" width="650px" append-to-body>
|
||||
<el-form ref="itemFormRef" :model="form" :rules="rules" label-width="135px">
|
||||
<el-form-item label="自定义巡检项名称" prop="name">
|
||||
<el-input v-model="form.name" placeholder="请输入自定义巡检项名称" />
|
||||
</el-form-item>
|
||||
<el-form-item label="类型" prop="type">
|
||||
<el-select v-model="form.type" placeholder="请选择类型">
|
||||
<el-option label="巡检管理" value="1" />
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
<template #footer>
|
||||
<div class="dialog-footer">
|
||||
<el-button :loading="buttonLoading" type="primary" @click="submitForm">确 定</el-button>
|
||||
<el-button @click="cancel">取 消</el-button>
|
||||
</div>
|
||||
</template>
|
||||
</el-dialog>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup name="Item" lang="ts">
|
||||
import { listItem, getItem, delItem, addItem, updateItem } from '@/api/zhinengxunjian/inspection/item/index';
|
||||
import { ItemVO, ItemQuery, ItemForm } from '@/api/zhinengxunjian/inspection/item/types';
|
||||
|
||||
const { proxy } = getCurrentInstance() as ComponentInternalInstance;
|
||||
|
||||
const itemList = ref<ItemVO[]>([]);
|
||||
const buttonLoading = ref(false);
|
||||
const loading = ref(true);
|
||||
const showSearch = ref(true);
|
||||
const ids = ref<Array<string | number>>([]);
|
||||
const single = ref(true);
|
||||
const multiple = ref(true);
|
||||
const total = ref(0);
|
||||
|
||||
const queryFormRef = ref<ElFormInstance>();
|
||||
const itemFormRef = ref<ElFormInstance>();
|
||||
|
||||
const dialog = reactive<DialogOption>({
|
||||
visible: false,
|
||||
title: ''
|
||||
});
|
||||
|
||||
const initFormData: ItemForm = {
|
||||
name: undefined,
|
||||
type: '1',
|
||||
projectId: 1
|
||||
};
|
||||
const data = reactive<PageData<ItemForm, ItemQuery>>({
|
||||
form: { ...initFormData },
|
||||
queryParams: {
|
||||
pageNum: 1,
|
||||
pageSize: 10,
|
||||
name: undefined,
|
||||
type: undefined,
|
||||
params: {}
|
||||
},
|
||||
rules: {
|
||||
name: [{ required: true, message: '自定义巡检项名称不能为空', trigger: 'blur' }],
|
||||
type: [{ required: true, message: '业务id,巡检计划1不能为空', trigger: 'change' }]
|
||||
}
|
||||
});
|
||||
|
||||
const { queryParams, form, rules } = toRefs(data);
|
||||
|
||||
/** 查询运维-巡检-自定义巡检项列表 */
|
||||
const getList = async () => {
|
||||
loading.value = true;
|
||||
const res = await listItem(queryParams.value);
|
||||
itemList.value = res.rows;
|
||||
total.value = res.total;
|
||||
loading.value = false;
|
||||
};
|
||||
|
||||
/** 取消按钮 */
|
||||
const cancel = () => {
|
||||
reset();
|
||||
dialog.visible = false;
|
||||
};
|
||||
|
||||
/** 表单重置 */
|
||||
const reset = () => {
|
||||
form.value = { ...initFormData };
|
||||
itemFormRef.value?.resetFields();
|
||||
};
|
||||
|
||||
/** 搜索按钮操作 */
|
||||
const handleQuery = () => {
|
||||
queryParams.value.pageNum = 1;
|
||||
getList();
|
||||
};
|
||||
|
||||
/** 重置按钮操作 */
|
||||
const resetQuery = () => {
|
||||
queryFormRef.value?.resetFields();
|
||||
handleQuery();
|
||||
};
|
||||
|
||||
/** 多选框选中数据 */
|
||||
const handleSelectionChange = (selection: ItemVO[]) => {
|
||||
ids.value = selection.map((item) => item.id);
|
||||
single.value = selection.length != 1;
|
||||
multiple.value = !selection.length;
|
||||
};
|
||||
|
||||
/** 新增按钮操作 */
|
||||
const handleAdd = () => {
|
||||
reset();
|
||||
dialog.visible = true;
|
||||
dialog.title = '添加运维-巡检-自定义巡检项';
|
||||
};
|
||||
|
||||
/** 修改按钮操作 */
|
||||
const handleUpdate = async (row?: ItemVO) => {
|
||||
reset();
|
||||
const _id = row?.id || ids.value[0];
|
||||
const res = await getItem(_id);
|
||||
Object.assign(form.value, res.data);
|
||||
dialog.visible = true;
|
||||
dialog.title = '修改运维-巡检-自定义巡检项';
|
||||
};
|
||||
|
||||
/** 提交按钮 */
|
||||
const submitForm = () => {
|
||||
itemFormRef.value?.validate(async (valid: boolean) => {
|
||||
if (valid) {
|
||||
buttonLoading.value = true;
|
||||
if (form.value.id) {
|
||||
await updateItem(form.value).finally(() => (buttonLoading.value = false));
|
||||
} else {
|
||||
await addItem(form.value).finally(() => (buttonLoading.value = false));
|
||||
}
|
||||
proxy?.$modal.msgSuccess('操作成功');
|
||||
dialog.visible = false;
|
||||
await getList();
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
/** 删除按钮操作 */
|
||||
const handleDelete = async (row?: ItemVO) => {
|
||||
const _ids = row?.id || ids.value;
|
||||
await proxy?.$modal.confirm('是否确认删除运维-巡检-自定义巡检项编号为"' + _ids + '"的数据项?').finally(() => (loading.value = false));
|
||||
await delItem(_ids);
|
||||
proxy?.$modal.msgSuccess('删除成功');
|
||||
await getList();
|
||||
};
|
||||
|
||||
/** 导出按钮操作 */
|
||||
const handleExport = () => {
|
||||
proxy?.download(
|
||||
'inspection/item/export',
|
||||
{
|
||||
...queryParams.value
|
||||
},
|
||||
`item_${new Date().getTime()}.xlsx`
|
||||
);
|
||||
};
|
||||
|
||||
onMounted(() => {
|
||||
getList();
|
||||
});
|
||||
</script>
|
||||
234
src/views/materialManagement/components/DataAnalysis.vue
Normal file
@ -0,0 +1,234 @@
|
||||
<template>
|
||||
<div class="dashboard-container">
|
||||
<!-- 第一个图表:本月出入库统计 -->
|
||||
<div class="chart-item">
|
||||
<div class="title">
|
||||
本月出入库统计
|
||||
</div>
|
||||
<div ref="lineChartRef" class="chart-container"></div>
|
||||
</div>
|
||||
|
||||
<!-- 第二个图表:出入库类型分布 -->
|
||||
<div class="chart-item">
|
||||
<div class="title">
|
||||
出入库类型分布
|
||||
</div>
|
||||
<div ref="barChartRef" class="chart-container"></div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import { ref, onMounted, onUnmounted } from 'vue';
|
||||
import * as echarts from 'echarts';
|
||||
|
||||
// 图表容器引用
|
||||
const lineChartRef = ref(null);
|
||||
const barChartRef = ref(null);
|
||||
|
||||
// 图表实例
|
||||
let lineChart = null;
|
||||
let barChart = null;
|
||||
|
||||
onMounted(() => {
|
||||
// 初始化折线图
|
||||
initLineChart();
|
||||
// 初始化柱状图
|
||||
initBarChart();
|
||||
|
||||
// 监听窗口大小变化,自适应图表
|
||||
window.addEventListener('resize', handleResize);
|
||||
});
|
||||
|
||||
onUnmounted(() => {
|
||||
// 销毁图表实例
|
||||
if (lineChart) {
|
||||
lineChart.dispose();
|
||||
}
|
||||
if (barChart) {
|
||||
barChart.dispose();
|
||||
}
|
||||
|
||||
// 移除事件监听
|
||||
window.removeEventListener('resize', handleResize);
|
||||
});
|
||||
|
||||
// 初始化折线图
|
||||
const initLineChart = () => {
|
||||
if (lineChartRef.value) {
|
||||
lineChart = echarts.init(lineChartRef.value);
|
||||
|
||||
const option = {
|
||||
tooltip: {
|
||||
trigger: 'axis'
|
||||
},
|
||||
legend: {
|
||||
data: ['入库数量', '出库数量'],
|
||||
icon: 'circle',
|
||||
itemWidth: 10,
|
||||
itemHeight: 10,
|
||||
top: 0
|
||||
},
|
||||
grid: {
|
||||
left: '3%',
|
||||
right: '4%',
|
||||
bottom: '3%',
|
||||
containLabel: true
|
||||
},
|
||||
xAxis: {
|
||||
type: 'category',
|
||||
data: ['1', '2', '3', '4', '5', '6', '7', '8', '9', '10', '11', '12']
|
||||
},
|
||||
yAxis: {
|
||||
type: 'value'
|
||||
},
|
||||
series: [
|
||||
{
|
||||
name: '入库数量',
|
||||
type: 'line',
|
||||
data: [5, 40, 20, 75, 60, 80, 40, 55, 30, 65, 5, 80],
|
||||
symbol: 'none',
|
||||
smooth: true,
|
||||
lineStyle: {
|
||||
color: 'rgba(22, 93, 255, 1)'
|
||||
},
|
||||
itemStyle: {
|
||||
color: 'rgba(22, 93, 255, 1)'
|
||||
},
|
||||
areaStyle: {
|
||||
color: new echarts.graphic.LinearGradient(0, 0, 0, 1, [
|
||||
{ offset: 0, color: 'rgba(22, 93, 255, 0.2)' },
|
||||
{ offset: 1, color: 'rgba(22, 93, 255, 0)' }
|
||||
])
|
||||
}
|
||||
},
|
||||
{
|
||||
name: '出库数量',
|
||||
type: 'line',
|
||||
data: [30, 40, 30, 30, 30, 15, 55, 50, 40, 60, 25, 90],
|
||||
symbol: 'none',
|
||||
smooth: true,
|
||||
lineStyle: {
|
||||
color: 'rgba(255, 153, 0, 1)'
|
||||
},
|
||||
itemStyle: {
|
||||
color: 'rgba(255, 153, 0, 1)'
|
||||
},
|
||||
areaStyle: {
|
||||
color: new echarts.graphic.LinearGradient(0, 0, 0, 1, [
|
||||
{ offset: 0, color: 'rgba(59, 179, 70, 0.2)' },
|
||||
{ offset: 1, color: 'rgba(59, 179, 70, 0)' }
|
||||
])
|
||||
}
|
||||
}
|
||||
]
|
||||
};
|
||||
|
||||
lineChart.setOption(option);
|
||||
}
|
||||
};
|
||||
|
||||
// 初始化柱状图
|
||||
const initBarChart = () => {
|
||||
if (barChartRef.value) {
|
||||
barChart = echarts.init(barChartRef.value);
|
||||
|
||||
const option = {
|
||||
tooltip: {
|
||||
trigger: 'axis',
|
||||
axisPointer: {
|
||||
type: 'shadow'
|
||||
}
|
||||
},
|
||||
legend: {
|
||||
data: ['入库数量', '出库数量'],
|
||||
icon: 'circle',
|
||||
itemWidth: 10,
|
||||
itemHeight: 10,
|
||||
top: 0
|
||||
},
|
||||
grid: {
|
||||
left: '3%',
|
||||
right: '4%',
|
||||
bottom: '3%',
|
||||
containLabel: true
|
||||
},
|
||||
xAxis: {
|
||||
type: 'category',
|
||||
data: ['电器部件', '机械部件', '电子元件', '控制模块', '结构部件', '其他'],
|
||||
axisLabel: {
|
||||
interval: 0, // 强制显示所有标签
|
||||
rotate: 30, // 标签旋转30度
|
||||
margin: 15, // 增加与轴线的距离
|
||||
align: 'right', // 文字右对齐
|
||||
verticalAlign: 'top' // 垂直方向顶部对齐
|
||||
}
|
||||
},
|
||||
yAxis: {
|
||||
type: 'value'
|
||||
},
|
||||
series: [
|
||||
{
|
||||
name: '入库数量',
|
||||
type: 'bar',
|
||||
data: [650, 480, 510, 280, 650, 220],
|
||||
itemStyle: {
|
||||
color: 'rgba(22, 93, 255, 1)' // 入库数量颜色
|
||||
},
|
||||
barWidth: '45%',
|
||||
barGap: '0' // 柱子之间的间距
|
||||
|
||||
},
|
||||
{
|
||||
name: '出库数量',
|
||||
type: 'bar',
|
||||
data: [850, 400, 770, 590, 540, 310],
|
||||
itemStyle: {
|
||||
color: 'rgba(15, 198, 194, 1)' // 出库数量颜色
|
||||
},
|
||||
barWidth: '45%',
|
||||
barGap: '0' // 柱子之间的间距
|
||||
}
|
||||
]
|
||||
};
|
||||
|
||||
barChart.setOption(option);
|
||||
}
|
||||
};
|
||||
|
||||
// 处理窗口大小变化,让图表自适应
|
||||
const handleResize = () => {
|
||||
if (lineChart) {
|
||||
lineChart.resize();
|
||||
}
|
||||
if (barChart) {
|
||||
barChart.resize();
|
||||
}
|
||||
};
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
.dashboard-container {
|
||||
padding: 20px;
|
||||
}
|
||||
|
||||
.chart-item {
|
||||
background-color: #fff;
|
||||
border-radius: 8px;
|
||||
padding: 20px;
|
||||
margin-bottom: 20px;
|
||||
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.05);
|
||||
}
|
||||
|
||||
.title {
|
||||
color: rgba(29, 33, 41, 1);
|
||||
font-weight: bold;
|
||||
font-size: 16px;
|
||||
margin-bottom: 16px;
|
||||
}
|
||||
|
||||
.chart-container {
|
||||
width: 100%;
|
||||
height: 300px;
|
||||
}
|
||||
</style>
|
||||
146
src/views/materialManagement/components/DetailsProcess.vue
Normal file
@ -0,0 +1,146 @@
|
||||
<template>
|
||||
<div class="approval-process-container">
|
||||
<div class="approval-process-card">
|
||||
<h2>审批流程</h2>
|
||||
<!-- 时间线组件:展示审批步骤 -->
|
||||
<el-timeline class="custom-timeline">
|
||||
<!-- 步骤1:创建采购单 -->
|
||||
<el-timeline-item timestamp="11月1日 10:18" placement="top" :icon="renderCustomIcon('/assets/yes.png')"
|
||||
color="green" type="danger" class="timeline-item">
|
||||
<h3 style="color: rgba(24, 109, 245, 1);font-weight: bold;">创建采购单</h3>
|
||||
<p>申请人张三:提交采购单</p>
|
||||
<p>计划:Q2风电轴承采购计划</p>
|
||||
<p>附件:<a href="#" class="attachment-link">一个图片.jpg</a></p>
|
||||
</el-timeline-item>
|
||||
|
||||
<!-- 步骤2:审批未通过 -->
|
||||
<el-timeline-item timestamp="11月1日 10:18" placement="top" :icon="renderCustomIcon('/assets/no.png')"
|
||||
color="red" class="timeline-item">
|
||||
<h3 style="color: rgba(24, 109, 245, 1);font-weight: bold;">审批未通过</h3>
|
||||
<p>部门经理李四:审批不通过</p>
|
||||
<p>计划:Q2风电轴承采购计划</p>
|
||||
<p>不通过原因:</p>
|
||||
<ul class="reason-list">
|
||||
<li>1. 出货时间过长</li>
|
||||
<li>2. 单价高于市场价</li>
|
||||
<li>3. 损耗重新评估</li>
|
||||
<li>4. 付款方式更改</li>
|
||||
<li>5. 发票开具方式更改</li>
|
||||
</ul>
|
||||
</el-timeline-item>
|
||||
|
||||
<!-- 步骤3:未进行(财务主管) -->
|
||||
<el-timeline-item timestamp="" placement="top" :icon="renderCustomIcon('/assets/re.png')" color="gray"
|
||||
class="timeline-item">
|
||||
<h3>未进行</h3>
|
||||
<p>财务主管王五:</p>
|
||||
<p>计划:Q2风电轴承采购计划</p>
|
||||
<p>备注:——</p>
|
||||
</el-timeline-item>
|
||||
|
||||
<!-- 步骤4:未进行(总经理) -->
|
||||
<el-timeline-item timestamp="" placement="top" :icon="renderCustomIcon('/assets/re.png')" color="gray"
|
||||
class="timeline-item">
|
||||
<h3>未进行</h3>
|
||||
<p>总经理赵六:</p>
|
||||
<p>计划:Q2风电轴承采购计划</p>
|
||||
<p>备注:——</p>
|
||||
</el-timeline-item>
|
||||
</el-timeline>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import { Check, Close, Clock } from '@element-plus/icons-vue'; // 引入Element Plus图标
|
||||
|
||||
const renderCustomIcon = (iconSrc) => {
|
||||
return h('img', { src: iconSrc, class: 'custom-icon' });
|
||||
};
|
||||
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
.approval-process-container {
|
||||
min-height: 100vh;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: flex-start;
|
||||
/* padding: 40px 20px; */
|
||||
}
|
||||
|
||||
.approval-process-card {
|
||||
padding: 30px;
|
||||
width: 100%;
|
||||
max-width: 800px;
|
||||
transition: transform 0.3s ease;
|
||||
}
|
||||
|
||||
.approval-process-card:hover {
|
||||
transform: translateY(-5px);
|
||||
}
|
||||
|
||||
h2 {
|
||||
margin-bottom: 30px;
|
||||
font-size: 24px;
|
||||
color: #333;
|
||||
text-align: center;
|
||||
position: relative;
|
||||
}
|
||||
|
||||
h2::after {
|
||||
content: '';
|
||||
position: absolute;
|
||||
bottom: -10px;
|
||||
left: 50%;
|
||||
transform: translateX(-50%);
|
||||
width: 60px;
|
||||
height: 3px;
|
||||
background-color: #409eff;
|
||||
}
|
||||
|
||||
.custom-timeline {
|
||||
margin-top: 20px;
|
||||
}
|
||||
|
||||
.timeline-item {
|
||||
margin-bottom: 25px;
|
||||
transition: all 0.3s ease;
|
||||
}
|
||||
|
||||
.timeline-item:hover {
|
||||
transform: translateX(5px);
|
||||
}
|
||||
|
||||
.el-timeline-item__content {
|
||||
padding-top: 15px;
|
||||
background-color: rgba(255, 255, 255, 0.8);
|
||||
border-radius: 8px;
|
||||
padding: 15px;
|
||||
box-shadow: 0 4px 10px rgba(0, 0, 0, 0.05);
|
||||
}
|
||||
|
||||
ul.reason-list {
|
||||
margin: 0;
|
||||
padding-left: 20px;
|
||||
color: red;
|
||||
list-style: none;
|
||||
}
|
||||
|
||||
li {
|
||||
margin: 8px 0;
|
||||
line-height: 1.6;
|
||||
}
|
||||
|
||||
.attachment-link {
|
||||
color: #409eff;
|
||||
text-decoration: none;
|
||||
transition: all 0.3s ease;
|
||||
display: inline-block;
|
||||
}
|
||||
|
||||
.attachment-link:hover {
|
||||
text-decoration: underline;
|
||||
transform: translateY(-2px);
|
||||
}
|
||||
</style>
|
||||
142
src/views/materialManagement/components/SystemInfo.vue
Normal file
@ -0,0 +1,142 @@
|
||||
<template>
|
||||
<div class="bill-list">
|
||||
<!-- 循环渲染单据列表 -->
|
||||
<div v-for="(bill, index) in billList" :key="index" class="bill-item">
|
||||
<!-- 左侧图标 + 单据类型 + 编号 -->
|
||||
<div class="left">
|
||||
<div class="icon">
|
||||
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="40"
|
||||
height="40" viewBox="0 0 40 40" fill="none">
|
||||
<circle cx="20" cy="20" r="20" fill="#186DF5"></circle>
|
||||
<path fill="rgba(255, 255, 255, 1)"
|
||||
d="M15.1666 18.3333L15.1666 22.5L14.1666 22.5L14.1666 21.5L25.8333 21.5L25.8333 22.5L24.8333 22.5L24.8333 18.3333L25.8333 18.3333L24.8333 18.3333C24.8333 15.664 22.6693 13.5 20 13.5L20 13.5C17.3306 13.5 15.1666 15.664 15.1666 18.3333L15.1666 18.3333ZM13.1666 18.3333L14.1666 18.3333L13.1666 18.3333C13.1666 14.5594 16.226 11.5 20 11.5L20 12.5L20 11.5C23.7739 11.5 26.8333 14.5594 26.8333 18.3333L26.8333 18.3333L26.8333 22.5L25.8333 23.5L14.1666 23.5L13.1666 22.5L13.1666 18.3333ZM13.1666 22.5L14.1666 22.5L14.1666 23.5C13.8921 23.4961 13.6564 23.3985 13.4595 23.2071C13.2681 23.0102 13.1705 22.7745 13.1666 22.5ZM25.8333 23.5L25.8333 22.5L26.8333 22.5C26.8294 22.7745 26.7318 23.0102 26.5404 23.2071C26.3435 23.3985 26.1078 23.4961 25.8333 23.5Z">
|
||||
</path>
|
||||
<path fill="rgba(255, 255, 255, 1)"
|
||||
d="M13.5 23.75C13.5 23.8881 13.6119 24 13.75 24L13.75 25L13.75 24L26.25 24L26.25 25L26.25 24C26.3881 24 26.5 23.8881 26.5 23.75L27.5 23.75L26.5 23.75C26.5 23.6119 26.3881 23.5 26.25 23.5L26.25 23.5L13.75 23.5L13.75 22.5L13.75 23.5C13.6119 23.5 13.5 23.6119 13.5 23.75L13.5 23.75ZM11.5 23.75L12.5 23.75L11.5 23.75C11.5 22.5074 12.5074 21.5 13.75 21.5L13.75 21.5L26.25 21.5L26.25 22.5L26.25 21.5C27.4926 21.5 28.5 22.5074 28.5 23.75L28.5 23.75C28.5 24.9926 27.4926 26 26.25 26L26.25 26L13.75 26L13.75 26C12.5074 26 11.5 24.9926 11.5 23.75Z">
|
||||
</path>
|
||||
<path stroke="rgba(255, 255, 255, 1)" stroke-width="2" stroke-linejoin="round"
|
||||
stroke-linecap="round"
|
||||
d="M22.5 25C22.5 26.3807 21.3807 27.5 20 27.5C18.6193 27.5 17.5 26.3807 17.5 25"></path>
|
||||
</svg>
|
||||
</div>
|
||||
<div class="info">
|
||||
<div class="type">{{ bill.type }}</div>
|
||||
<div class="number">{{ bill.number }}</div>
|
||||
</div>
|
||||
</div>
|
||||
<!-- 右侧时间 + 状态 -->
|
||||
<div class="right">
|
||||
<div class="time">{{ bill.time }}</div>
|
||||
<div class="status" :class="{
|
||||
'approved': bill.status === '审批通过',
|
||||
'pending': bill.status === '待审批'
|
||||
}">
|
||||
{{ bill.status }}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import { ref } from 'vue';
|
||||
|
||||
// 定义单据数据
|
||||
const billList = ref([
|
||||
{
|
||||
type: '出库单',
|
||||
number: 'IN-2023-0615-001',
|
||||
time: '10月20日 12:00:06',
|
||||
status: '审批通过'
|
||||
},
|
||||
{
|
||||
type: '入库单',
|
||||
number: 'IN-2023-0615-001',
|
||||
time: '10月20日 12:00:06',
|
||||
status: '待审批'
|
||||
},
|
||||
{
|
||||
type: '入库单',
|
||||
number: 'IN-2023-0615-001',
|
||||
time: '10月20日 12:00:06',
|
||||
status: '待审批'
|
||||
},
|
||||
{
|
||||
type: '入库单',
|
||||
number: 'IN-2023-0615-001',
|
||||
time: '10月20日 12:00:06',
|
||||
status: '待审批'
|
||||
},
|
||||
{
|
||||
type: '入库单',
|
||||
number: 'IN-2023-0615-001',
|
||||
time: '10月20日 12:00:06',
|
||||
status: '待审批'
|
||||
}
|
||||
]);
|
||||
</script>
|
||||
<style scoped>
|
||||
.bill-list {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
margin-top: 10px;
|
||||
/* gap: 1rem; */
|
||||
/* padding: 1rem; */
|
||||
}
|
||||
|
||||
.bill-item {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
/* padding: 0.5rem; */
|
||||
padding: 10px;
|
||||
border-bottom: 1px solid #e5e7eb;
|
||||
}
|
||||
|
||||
.left {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 0.5rem;
|
||||
}
|
||||
|
||||
.info {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
}
|
||||
|
||||
.type {
|
||||
font-weight: 600;
|
||||
}
|
||||
|
||||
.number {
|
||||
font-size: 0.875rem;
|
||||
color: #6b7280;
|
||||
}
|
||||
|
||||
.right {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: flex-end;
|
||||
}
|
||||
|
||||
.time {
|
||||
font-size: 0.875rem;
|
||||
color: #6b7280;
|
||||
}
|
||||
|
||||
.status {
|
||||
font-size: 0.875rem;
|
||||
/* padding: 0.25rem 0.5rem; */
|
||||
border-radius: 0.25rem;
|
||||
}
|
||||
|
||||
.approved {
|
||||
color: #10b981;
|
||||
/* background-color: rgba(16, 185, 129, 0.1); */
|
||||
}
|
||||
|
||||
.pending {
|
||||
color: #f59e0b;
|
||||
/* background-color: rgba(245, 158, 11, 0.1); */
|
||||
}
|
||||
</style>
|
||||
257
src/views/materialManagement/components/detailInfo.vue
Normal file
@ -0,0 +1,257 @@
|
||||
<template>
|
||||
<div class="approval-form">
|
||||
<!-- 基础信息 -->
|
||||
<el-card class="card" shadow="hover">
|
||||
<template #header>
|
||||
<h3>基础信息</h3>
|
||||
</template>
|
||||
<el-form :model="basicInfo" label-width="120px">
|
||||
<el-row :gutter="20">
|
||||
<el-col :span="8">
|
||||
<el-form-item label="订单编号">
|
||||
<el-input v-model="basicInfo.orderNo" disabled />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="8">
|
||||
<el-form-item label="创建时间">
|
||||
<el-input v-model="basicInfo.createTime" disabled />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="8">
|
||||
<el-form-item label="经办人">
|
||||
<el-input v-model="basicInfo.handler" disabled />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
</el-row>
|
||||
<el-row :gutter="20">
|
||||
<el-col :span="12">
|
||||
<el-form-item label="所属部门">
|
||||
<el-select v-model="basicInfo.dept" placeholder="请选择">
|
||||
<el-option label="运维部" value="运维部" />
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="12">
|
||||
<el-form-item label="采购类型">
|
||||
<el-select v-model="basicInfo.purchaseType" placeholder="请选择">
|
||||
<el-option label="项目业务" value="项目业务" />
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
</el-row>
|
||||
<el-form-item label="申请原因">
|
||||
<el-input v-model="basicInfo.applyReason" type="textarea" :rows="2" placeholder="请输入申请原因" />
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
</el-card>
|
||||
|
||||
<!-- 供应商信息 -->
|
||||
<el-card class="card" shadow="hover" style="margin-top: 20px">
|
||||
<template #header>
|
||||
<h3>供应商信息</h3>
|
||||
</template>
|
||||
<el-form :model="supplierInfo" label-width="120px">
|
||||
<el-row :gutter="20">
|
||||
<el-col :span="12">
|
||||
<el-form-item label="供应商单位">
|
||||
<el-select v-model="supplierInfo.supplierName" placeholder="请选择">
|
||||
<el-option label="AAAA精密仪器制造有限公司" value="AAAA精密仪器制造有限公司" />
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="12">
|
||||
<el-form-item label="出货时间">
|
||||
<el-select v-model="supplierInfo.deliveryTime" placeholder="请选择">
|
||||
<el-option label="2年零4个月" value="2年零4个月" />
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
</el-row>
|
||||
<el-row :gutter="20">
|
||||
<el-col :span="24">
|
||||
<el-form-item label="审批备注" prop="remark">
|
||||
<el-input v-model="supplierInfo.remark" :rows="1" placeholder="请输入审批备注"
|
||||
style="border: 1px solid red;color: red;" readonly value="1. 出货时间较长" />
|
||||
<!-- <div class="error-tip">1. 出货时间较长</div> -->
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
</el-row>
|
||||
</el-form>
|
||||
</el-card>
|
||||
|
||||
<!-- 产品信息 -->
|
||||
<el-card class="card" shadow="hover" style="margin-top: 20px">
|
||||
<template #header>
|
||||
<h3>产品信息</h3>
|
||||
</template>
|
||||
<el-table :data="productInfo.tableData" border style="width: 100%">
|
||||
<el-table-column prop="productName" label="产品名称" />
|
||||
<el-table-column prop="productModel" label="产品型号" />
|
||||
<el-table-column prop="productPrice" label="产品单价" align="center" :cell-style="{ background: 'pink' }" />
|
||||
<el-table-column prop="buyQuantity" label="购买数量" align="center" :cell-style="{ background: 'pink' }" />
|
||||
<el-table-column prop="usage" label="用途" />
|
||||
<el-table-column prop="total" label="合计" />
|
||||
</el-table>
|
||||
<el-form-item label="审批备注" style="margin-top: 10px">
|
||||
<el-input v-model="productInfo.remark" :rows="1" placeholder="请输入审批备注"
|
||||
style="border: 1px solid red;color: red;" readonly value="2. 单价高于市场价3.采购数量需重新评估" />
|
||||
<!-- <div class="error-tip">2. 单价高于市场价3.采购数量需重新评估</div> -->
|
||||
</el-form-item>
|
||||
</el-card>
|
||||
|
||||
<!-- 合同条款 -->
|
||||
<el-card class="card" shadow="hover" style="margin-top: 20px">
|
||||
<template #header>
|
||||
<h3>合同条款</h3>
|
||||
</template>
|
||||
<el-form :model="contractInfo" label-width="120px">
|
||||
<el-row :gutter="20">
|
||||
<el-col :span="12">
|
||||
<el-form-item label="付款条件">
|
||||
<el-select v-model="contractInfo.paymentCondition" placeholder="请选择">
|
||||
<el-option label="银行卡" value="银行卡" />
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="12">
|
||||
<el-form-item label="发票开具方式">
|
||||
<el-select v-model="contractInfo.invoiceWay" placeholder="请选择">
|
||||
<el-option label="请选择" value="请选择" />
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
</el-row>
|
||||
<el-row :gutter="20">
|
||||
<el-col :span="24">
|
||||
<el-form-item label="审批备注" prop="remark">
|
||||
<el-input v-model="contractInfo.remark" placeholder="请输入审批备注"
|
||||
style="border: 1px solid red;color: red;" readonly value="4. 付款方式未标明5.发票开具方式未标明" />
|
||||
<!-- <div class="error-tip">4. 付款方式未标明5.发票开具方式未标明</div> -->
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
</el-row>
|
||||
</el-form>
|
||||
</el-card>
|
||||
|
||||
<!-- 附件 -->
|
||||
<el-card class="card" shadow="hover" style="margin-top: 20px">
|
||||
<template #header>
|
||||
<h3>附件</h3>
|
||||
</template>
|
||||
<el-upload class="upload-demo" action="#" :file-list="fileList" :auto-upload="false"
|
||||
:on-preview="handlePreview">
|
||||
<el-table :data="fileList" border style="width: 100%">
|
||||
<el-table-column prop="name" label="文件名" width="300" />
|
||||
<el-table-column prop="size" label="大小" width="100" />
|
||||
<el-table-column label="操作" width="100">
|
||||
<template #default="scope">
|
||||
<!-- <el-link type="primary" @click="handlePreview(scope.row)"> -->
|
||||
<el-link type="primary">
|
||||
预览
|
||||
</el-link>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
</el-upload>
|
||||
</el-card>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import { ref } from 'vue';
|
||||
|
||||
// 基础信息数据
|
||||
const basicInfo = ref({
|
||||
orderNo: '0035455',
|
||||
createTime: '2023-11-02 16:32',
|
||||
handler: '李四',
|
||||
dept: '运维部',
|
||||
purchaseType: '项目业务',
|
||||
applyReason:
|
||||
'随着业务拓展,光伏电站业务负责增加,现有设备已运行5年,部分出现效率下降情况。为保证电站正常运行,计划采购一批新的逆变器替换老旧设备,并补充备件库存。',
|
||||
});
|
||||
|
||||
// 供应商信息数据
|
||||
const supplierInfo = ref({
|
||||
supplierName: 'AAAA精密仪器制造有限公司',
|
||||
deliveryTime: '2年零4个月',
|
||||
remark: '',
|
||||
});
|
||||
|
||||
// 产品信息数据
|
||||
const productInfo = ref({
|
||||
tableData: [
|
||||
{
|
||||
productName: 'AAABBBCCC',
|
||||
productModel: '15-42',
|
||||
productPrice: 500,
|
||||
buyQuantity: 10,
|
||||
usage: '组件',
|
||||
total: 5000,
|
||||
},
|
||||
],
|
||||
remark: '',
|
||||
});
|
||||
|
||||
// 合同条款数据
|
||||
const contractInfo = ref({
|
||||
paymentCondition: '银行卡',
|
||||
invoiceWay: '请选择',
|
||||
remark: '',
|
||||
});
|
||||
|
||||
// 附件数据
|
||||
const fileList = ref([
|
||||
{
|
||||
name: 'MWwwwww.jpg',
|
||||
size: '30kb',
|
||||
url: '',
|
||||
},
|
||||
{
|
||||
name: '231234124w.zip',
|
||||
size: '50kb',
|
||||
url: '',
|
||||
},
|
||||
{
|
||||
name: '12451asdas.doc',
|
||||
size: '80kb',
|
||||
url: '',
|
||||
},
|
||||
{
|
||||
name: '21seasda.xls',
|
||||
size: '29kb',
|
||||
url: '',
|
||||
},
|
||||
{
|
||||
name: '12kjaklskw.png',
|
||||
size: '16kb',
|
||||
url: '',
|
||||
},
|
||||
]);
|
||||
|
||||
// 预览文件
|
||||
const handlePreview = (file) => {
|
||||
console.log('预览文件:', file);
|
||||
// 实际场景可在这里处理文件预览逻辑,如打开新窗口等
|
||||
};
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
.approval-form {
|
||||
padding: 20px;
|
||||
}
|
||||
|
||||
.card {
|
||||
border-radius: 8px;
|
||||
}
|
||||
|
||||
.error-tip {
|
||||
color: red;
|
||||
font-size: 12px;
|
||||
margin-top: 5px;
|
||||
}
|
||||
|
||||
::v-deep(.el-input__inner) {
|
||||
color: red;
|
||||
}
|
||||
</style>
|
||||
280
src/views/materialManagement/inventoryManagement.vue
Normal file
@ -0,0 +1,280 @@
|
||||
<template>
|
||||
<div class="inventoryManagement">
|
||||
<!-- <TitleComponent title="出入库单管理" subtitle="管理光伏和风电设备备品备件的出入库记录" /> -->
|
||||
<el-row gutter="20">
|
||||
<el-col :span="16" class="list" style="flex-grow: 1;display: flex;">
|
||||
<el-card style="border-radius: 10px;height: 100%;display: flex;flex-direction: column;flex: 1;">
|
||||
<div style="height: 100%;flex: 1;">
|
||||
<div class="top">
|
||||
<div class="title">单据列表</div>
|
||||
<div class="button-actions">
|
||||
<button :class="{ active: type === 'chuku' }" @click="changeType('chuku')">出库单</button>
|
||||
<button :class="{ active: type === 'ruku' }" @click="changeType('ruku')">入库单</button>
|
||||
</div>
|
||||
</div>
|
||||
<div class="content" style="height: 100%;flex: 1;">
|
||||
<div class="menu">
|
||||
<el-input placeholder="请输入单据编号"></el-input>
|
||||
<el-select placeholder="请选择单据类型"></el-select>
|
||||
<el-select placeholder="请选择设备类型"></el-select>
|
||||
<el-select placeholder="请选择状态"></el-select>
|
||||
<el-select placeholder="请选择日期范围"></el-select>
|
||||
<el-button icon="search" type="primary">搜索</el-button>
|
||||
<el-button icon="refresh">重置</el-button>
|
||||
</div>
|
||||
<div style="margin-top: 10px;">
|
||||
<el-button type="primary" @click="dialogVisible = true;">+{{ type === 'chuku' ? '添加出库单'
|
||||
: '添加入库单' }}</el-button>
|
||||
</div>
|
||||
<el-table :data="tableData" border style="width: 100%;margin-top: 15px;height: 1000px;">
|
||||
<el-table-column prop="formNumber" label="单据编号" />
|
||||
<el-table-column prop="equipmentType" label="设备类型" />
|
||||
<el-table-column prop="handler" label="经手人" />
|
||||
<el-table-column prop="operationTime" label="操作时间" />
|
||||
<el-table-column prop="totalQuantity" label="总数量" />
|
||||
<el-table-column label="状态">
|
||||
<template #default="scope">
|
||||
<el-tag :type="getStatusTagType(scope.row.status)">
|
||||
{{ scope.row.status }}
|
||||
</el-tag>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="操作">
|
||||
<template #default="scope">
|
||||
<el-button type="text" @click="handleEdit(scope.row)">编辑</el-button>
|
||||
<el-button type="text" @click="handleDetail(scope.row)">详情</el-button>
|
||||
<el-button type="text" @click="handleDelete(scope.row)">删除</el-button>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
<div class="tool">
|
||||
<div class="pagination-section">
|
||||
<el-pagination @size-change="handleSizeChange" @current-change="handleCurrentChange"
|
||||
:current-page="currentPage" :page-sizes="[10, 20, 30, 40]" :page-size="pageSize"
|
||||
layout="total, sizes, prev, pager, next, jumper" :total="total" background>
|
||||
</el-pagination>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</el-card>
|
||||
</el-col>
|
||||
<el-col :span="8">
|
||||
<el-card style="border-radius: 10px;">
|
||||
<div class="item-box">
|
||||
<div class="title">系统信息</div>
|
||||
<div class="content">
|
||||
<SystemInfo />
|
||||
</div>
|
||||
</div>
|
||||
<div class="item-box">
|
||||
<div class="title">数据分析</div>
|
||||
<div class="content">
|
||||
<DataAnalysis />
|
||||
</div>
|
||||
</div>
|
||||
</el-card>
|
||||
</el-col>
|
||||
</el-row>
|
||||
<el-dialog v-model="dialogVisible" :title="type === 'chuku' ? '添加出库单' : '添加入库单'" width="500">
|
||||
<el-form :rules="rules" ref="formRef" label-width="100">
|
||||
<el-form-item label="单据编号" prop="formNumber">
|
||||
<el-input v-model="form.formNumber" placeholder="请输入单据编号" />
|
||||
</el-form-item>
|
||||
<el-form-item label="设备类型" prop="equipmentType">
|
||||
<el-select v-model="form.equipmentType" placeholder="请选择设备类型">
|
||||
<el-option label="设备类型1" value="1" />
|
||||
<el-option label="设备类型2" value="2" />
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item label="入库数量" prop="totalQuantity">
|
||||
<el-input v-model="form.totalQuantity" placeholder="请输入总数量" />
|
||||
</el-form-item>
|
||||
<el-form-item label="经手人" prop="handler">
|
||||
<el-input v-model="form.handler" placeholder="请输入经手人" />
|
||||
</el-form-item>
|
||||
<!-- 联系电话 -->
|
||||
<el-form-item label="联系电话" prop="contactPhone">
|
||||
<el-input v-model="form.contactPhone" placeholder="请输入联系电话" />
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
<template #footer>
|
||||
<div class="dialog-footer">
|
||||
<el-button @click="dialogVisible = false">取消</el-button>
|
||||
<el-button type="primary" @click="dialogVisible = false">
|
||||
保存
|
||||
</el-button>
|
||||
</div>
|
||||
</template>
|
||||
</el-dialog>
|
||||
</div>
|
||||
</template>
|
||||
<style scoped>
|
||||
.inventoryManagement {
|
||||
background-color: #F2F8FC;
|
||||
padding: 20px;
|
||||
}
|
||||
|
||||
.button-actions button {
|
||||
background: none;
|
||||
border: 1px solid #e0e0e0;
|
||||
padding: 5px 12px;
|
||||
border-radius: 4px;
|
||||
margin-left: 8px;
|
||||
cursor: pointer;
|
||||
font-size: 12px;
|
||||
transition: all 0.2s ease;
|
||||
}
|
||||
|
||||
.button-actions button.active {
|
||||
background-color: #186DF5;
|
||||
color: white;
|
||||
border-color: #186DF5;
|
||||
}
|
||||
|
||||
.top {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
|
||||
.title {
|
||||
font-family: "Alibaba-PuHuiTi-Bold";
|
||||
color: rgba(0, 30, 59, 1);
|
||||
font-weight: bold;
|
||||
}
|
||||
}
|
||||
|
||||
.list .content {
|
||||
margin-top: 20px;
|
||||
}
|
||||
|
||||
.menu {
|
||||
display: flex;
|
||||
gap: 20px;
|
||||
background-color: #F2F2F2;
|
||||
padding: 20px;
|
||||
}
|
||||
|
||||
/* 分页区域样式 */
|
||||
.pagination-section {
|
||||
background-color: #fff;
|
||||
border-radius: 8px;
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.pagination-info {
|
||||
font-size: 14px;
|
||||
color: #606266;
|
||||
}
|
||||
|
||||
.pagination-controls .el-pagination {
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
|
||||
.pagination-controls .el-pagination button {
|
||||
min-width: 32px;
|
||||
height: 32px;
|
||||
line-height: 32px;
|
||||
border-radius: 4px;
|
||||
}
|
||||
|
||||
.pagination-controls .el-pagination .el-pager li {
|
||||
min-width: 32px;
|
||||
height: 32px;
|
||||
line-height: 32px;
|
||||
border-radius: 4px;
|
||||
}
|
||||
|
||||
.pagination-controls .el-pagination .el-pager li.active {
|
||||
background-color: #409eff;
|
||||
color: #fff;
|
||||
}
|
||||
|
||||
.tool {
|
||||
|
||||
margin-top: 10px;
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
}
|
||||
|
||||
.item-box {
|
||||
.title {
|
||||
font-family: "Alibaba-PuHuiTi-Bold";
|
||||
font-size: 18px;
|
||||
font-weight: 400;
|
||||
letter-spacing: 0px;
|
||||
line-height: 24px;
|
||||
color: rgba(0, 30, 59, 1);
|
||||
margin-top: 10px;
|
||||
}
|
||||
}
|
||||
|
||||
::v-deep(.el-card__body) {
|
||||
height: 100%;
|
||||
}
|
||||
</style>
|
||||
<script setup>
|
||||
import SystemInfo from './components/SystemInfo.vue';
|
||||
import DataAnalysis from './components/DataAnalysis.vue';
|
||||
const type = ref('chuku');
|
||||
const form = ref({
|
||||
formNumber: '',
|
||||
equipmentType: '',
|
||||
handler: '',
|
||||
totalQuantity: ''
|
||||
});
|
||||
|
||||
const changeType = (newType) => {
|
||||
type.value = newType;
|
||||
};
|
||||
const dialogVisible = ref(false);
|
||||
const tableData = computed(() => {
|
||||
return Array.from({ length: 50 }, (_, index) => ({
|
||||
formNumber: 'IN-2023-0615-001',
|
||||
equipmentType: '光伏设备',
|
||||
handler: '李仓库',
|
||||
operationTime: '2023-06-15 09:23',
|
||||
totalQuantity: 120,
|
||||
// 待审核,已完成,已取消 随机生成
|
||||
status: Math.random() > 0.5 ? '待审核' : Math.random() > 0.5 ? '已完成' : '已取消'
|
||||
}))
|
||||
})
|
||||
// 当前页码
|
||||
const currentPage = ref(1);
|
||||
// 每页条数 - 与分页控件默认值保持一致
|
||||
const pageSize = ref(10);
|
||||
// 总条数 - 从原始数据计算得出
|
||||
const total = ref(tableData.value.length);
|
||||
const pagedTableData = computed(() => {
|
||||
const startIndex = (currentPage.value - 1) * pageSize.value;
|
||||
const endIndex = startIndex + pageSize.value;
|
||||
return tableData.value.slice(startIndex, endIndex);
|
||||
});
|
||||
// 表单校验规则
|
||||
const rules = ref({
|
||||
formNumber: [{ required: true, message: '请输入表单编号', trigger: 'blur' }],
|
||||
equipmentType: [{ required: true, message: '请选择设备类型', trigger: 'change' }],
|
||||
handler: [{ required: true, message: '请输入经手人', trigger: 'blur' }],
|
||||
totalQuantity: [{ required: true, message: '请输入入库数量', trigger: 'blur' }],
|
||||
contactPhone: [{ required: true, message: '请输入联系电话', trigger: 'blur' }],
|
||||
});
|
||||
// 表单引用
|
||||
const formRef = ref(null);
|
||||
// 当前页码改变
|
||||
const handleCurrentChange = (val) => {
|
||||
currentPage.value = val;
|
||||
};
|
||||
const getStatusTagType = (status) => {
|
||||
if (status === '已完成') {
|
||||
return 'success'
|
||||
} else if (status === '待审核') {
|
||||
return 'warning'
|
||||
} else if (status === '已取消') {
|
||||
return 'danger'
|
||||
}
|
||||
return ''
|
||||
}
|
||||
</script>
|
||||
57
src/views/materialManagement/planDetails.vue
Normal file
@ -0,0 +1,57 @@
|
||||
<template>
|
||||
<div class="plan-details">
|
||||
<el-row>
|
||||
<el-col>
|
||||
<el-card>
|
||||
<div class="header">
|
||||
<span class="back-arrow" @click="handleBack">
|
||||
<el-icon>
|
||||
<ArrowLeft />
|
||||
</el-icon>
|
||||
</span>
|
||||
<h2>Q2风电轴承采购计划</h2>
|
||||
</div>
|
||||
</el-card>
|
||||
</el-col>
|
||||
</el-row>
|
||||
<el-row gutter="10">
|
||||
<el-col :span="18">
|
||||
<el-card>
|
||||
<detailInfo />
|
||||
</el-card>
|
||||
</el-col>
|
||||
<el-col :span="6" style="flex-grow: 1;">
|
||||
<el-card style="height: 100%;">
|
||||
<DetailsProcess />
|
||||
</el-card>
|
||||
</el-col>
|
||||
</el-row>
|
||||
|
||||
</div>
|
||||
</template>
|
||||
<style scoped lang="scss">
|
||||
.plan-details {
|
||||
padding: 20px;
|
||||
background-color: #F1F7FB;
|
||||
}
|
||||
|
||||
.header {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.back-arrow {
|
||||
font-size: 20px;
|
||||
margin-right: 10px;
|
||||
cursor: pointer;
|
||||
}
|
||||
</style>
|
||||
<script setup>
|
||||
import detailInfo from './components/detailInfo.vue';
|
||||
import DetailsProcess from './components/DetailsProcess.vue';
|
||||
|
||||
const router = useRouter();
|
||||
const handleBack = () => {
|
||||
router.back();
|
||||
}
|
||||
</script>
|
||||
569
src/views/materialManagement/procurementPlan.vue
Normal file
@ -0,0 +1,569 @@
|
||||
<template>
|
||||
<div class="procurementPlan">
|
||||
<el-row gutter="20">
|
||||
<el-col :span="13">
|
||||
<el-card>
|
||||
<div style="display: flex;align-items: center;height: 120px;justify-content: space-around;">
|
||||
<div class="img">
|
||||
<img src="/assets/caigou.png" alt="">
|
||||
</div>
|
||||
<div class="item">
|
||||
<div class="text">
|
||||
待审批计划
|
||||
</div>
|
||||
<div class="count" style="color: rgba(255, 178, 30, 1);">
|
||||
12
|
||||
</div>
|
||||
</div>
|
||||
<div class="item">
|
||||
<div class="text">
|
||||
已批准计划
|
||||
</div>
|
||||
<div class="count" style="color: rgba(67, 101, 220, 1);">
|
||||
28
|
||||
</div>
|
||||
</div>
|
||||
<div class="item">
|
||||
<div class="text">
|
||||
采购中计划
|
||||
</div>
|
||||
<div class="count" style="color: rgba(113, 214, 213, 1);">
|
||||
15
|
||||
</div>
|
||||
</div>
|
||||
<div class="item">
|
||||
<div class="text">
|
||||
已完成计划
|
||||
</div>
|
||||
<div class="count" style="color: rgba(0, 184, 122, 1);">
|
||||
86
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</el-card>
|
||||
</el-col>
|
||||
<el-col :span="11">
|
||||
<el-card>
|
||||
<div style="display: flex;align-items: center;height: 120px;justify-content: space-around;">
|
||||
<div class="img">
|
||||
<img src="/assets/qian.jpg" alt="">
|
||||
</div>
|
||||
<div class="item">
|
||||
<div class="text">
|
||||
本年度已采购金额
|
||||
</div>
|
||||
<div class="count" style="color: rgba(255, 153, 0, 1);">
|
||||
520,000.00
|
||||
</div>
|
||||
</div>
|
||||
<div class="item">
|
||||
<div class="text">
|
||||
本年度采购预算金额
|
||||
</div>
|
||||
<div class="count" style="color: rgba(67, 101, 220, 1);">
|
||||
3,000,000.00
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</el-card>
|
||||
</el-col>
|
||||
</el-row>
|
||||
<el-row style="margin-top: 20px;">
|
||||
<el-col :span="24">
|
||||
<el-card style="border-radius: 10px;">
|
||||
<div class="content">
|
||||
<div class="tabs">
|
||||
<el-button type="success">导出</el-button>
|
||||
<el-button type="primary" @click="isNewProcurementDialogVisible = true">新建采购申请单</el-button>
|
||||
</div>
|
||||
|
||||
<!-- 标签页导航 -->
|
||||
<div class="tabs">
|
||||
<el-button :type="activeTab === 'pending' ? 'primary' : ''"
|
||||
@click="changeTab('pending')">待审批</el-button>
|
||||
<el-button :type="activeTab === 'procuring' ? 'primary' : ''"
|
||||
@click="changeTab('procuring')">采购中</el-button>
|
||||
<el-badge :value="5" type="danger">
|
||||
<el-button :type="activeTab === 'rejected' ? 'primary' : ''"
|
||||
@click="changeTab('rejected')">
|
||||
未通过
|
||||
</el-button>
|
||||
</el-badge>
|
||||
<el-button :type="activeTab === 'approved' ? 'primary' : ''"
|
||||
@click="changeTab('approved')">已通过</el-button>
|
||||
<el-button :type="activeTab === 'completed' ? 'primary' : ''"
|
||||
@click="changeTab('completed')">已完成</el-button>
|
||||
</div>
|
||||
<!-- 表格 -->
|
||||
<el-table :data="tableData" border style="width: 100%;margin-top: 15px;">
|
||||
<el-table-column type="selection" width="55" />
|
||||
<el-table-column prop="planNumber" label="计划编号" />
|
||||
<el-table-column prop="planName" label="计划名称" />
|
||||
<el-table-column prop="equipmentType" label="设备类型" />
|
||||
<el-table-column prop="requestDept" label="申请部门" />
|
||||
<el-table-column prop="applicant" label="申请人" />
|
||||
<el-table-column prop="requestDate" label="申请日期" />
|
||||
<el-table-column prop="estimatedAmount" label="预计金额" />
|
||||
<el-table-column label="状态">
|
||||
<template #default="scope">
|
||||
<el-tag :type="getStatusTagType(scope.row.status)">{{ scope.row.status }}</el-tag>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="操作" fixed="right" width="80">
|
||||
<template #default="scope">
|
||||
<el-button type="text" @click="handleView(scope.row)">查看</el-button>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
|
||||
<!-- 分页 -->
|
||||
<div class="pagination-section">
|
||||
<el-pagination @size-change="handleSizeChange" @current-change="handleCurrentChange"
|
||||
:current-page="currentPage" :page-sizes="[10, 20, 30, 40]" :page-size="pageSize"
|
||||
layout="total, sizes, prev, pager, next, jumper" :total="total" background />
|
||||
</div>
|
||||
</div>
|
||||
</el-card>
|
||||
</el-col>
|
||||
</el-row>
|
||||
<el-dialog v-model="isNewProcurementDialogVisible" title="新建采购申请单" width="60%" :close-on-click-modal="false">
|
||||
<div class="new-procurement-form">
|
||||
<!-- 基础信息 -->
|
||||
<div class="form-section">
|
||||
<h3>基础信息</h3>
|
||||
<el-row :gutter="20">
|
||||
<el-col :span="6">
|
||||
<el-form-item label="订单编号">
|
||||
<el-input v-model="newProcurementForm.planNumber" disabled value="PLAN-2023-0615-003" />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="6">
|
||||
<el-form-item label="创建时间">
|
||||
<el-input v-model="newProcurementForm.createTime" disabled value="2023-11-02-16:32" />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="6">
|
||||
<el-form-item label="采购单位">
|
||||
<el-input v-model="newProcurementForm.procurementUnit" disabled value="大连好果汁有限公司" />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="6">
|
||||
<el-form-item label="经办人">
|
||||
<el-input v-model="newProcurementForm.handler" disabled value="李四" />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="6">
|
||||
<el-form-item label="合同类型">
|
||||
<el-select v-model="newProcurementForm.contractType" placeholder="请选择">
|
||||
<el-option label="请选择" value="" />
|
||||
<!-- 可以添加更多选项 -->
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="6">
|
||||
<el-form-item label="采购类型">
|
||||
<el-select v-model="newProcurementForm.procurementType" placeholder="请选择">
|
||||
<el-option label="请选择" value="" />
|
||||
<!-- 可以添加更多选项 -->
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="6">
|
||||
<el-form-item label="仓库地址">
|
||||
<el-select v-model="newProcurementForm.contractAddress" placeholder="请选择">
|
||||
<el-option label="请选择" value="" />
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="6">
|
||||
<el-form-item label="合同名称">
|
||||
<el-input v-model="newProcurementForm.contractName" placeholder="请填写" />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
</el-row>
|
||||
</div>
|
||||
|
||||
<!-- 供应商信息 -->
|
||||
<div class="form-section">
|
||||
<h3>供应商信息</h3>
|
||||
<el-row :gutter="20">
|
||||
<el-col :span="6">
|
||||
<el-form-item label="供应商单位">
|
||||
<el-select v-model="newProcurementForm.supplierUnit" placeholder="请选择">
|
||||
<el-option label="请选择" value="" />
|
||||
<!-- 可以添加更多选项 -->
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="6">
|
||||
<el-form-item label="送货时间">
|
||||
<el-select v-model="newProcurementForm.deliveryTime" placeholder="请选择">
|
||||
<el-option label="请选择" value="" />
|
||||
<!-- 可以添加更多选项 -->
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
</el-row>
|
||||
</div>
|
||||
|
||||
<!-- 产品信息 -->
|
||||
<div class="form-section">
|
||||
<h3>产品信息</h3>
|
||||
<el-table :data="newProcurementForm.products" border style="width: 100%">
|
||||
<el-table-column prop="productName" label="产品名称">
|
||||
<template #default="scope">
|
||||
<el-input v-model="scope.row.productName" placeholder="请填写" />
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column prop="productModel" label="产品型号">
|
||||
<template #default="scope">
|
||||
<el-input v-model="scope.row.productModel" placeholder="请填写" />
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column prop="productPrice" label="产品单价">
|
||||
<template #default="scope">
|
||||
<el-input v-model="scope.row.productPrice" placeholder="请填写" type="number" />
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column prop="purchaseQuantity" label="购买数量">
|
||||
<template #default="scope">
|
||||
<el-input v-model="scope.row.purchaseQuantity" placeholder="请填写" type="number" />
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column prop="unit" label="单位">
|
||||
<template #default="scope">
|
||||
<el-input v-model="scope.row.unit" placeholder="请填写" />
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column prop="totalPrice" label="合计" :formatter="calculateTotalPrice">
|
||||
<template #default="scope">
|
||||
<span>{{ calculateTotalPrice(scope.row) }}</span>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="操作" fixed="right" width="80">
|
||||
<template #default="scope">
|
||||
<el-button type="text" @click="removeProduct(scope.$index)"
|
||||
:disabled="newProcurementForm.products.length <= 1">删除</el-button>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
<el-button type="primary" size="small" @click="addProduct" style="margin-top: 10px">添加产品</el-button>
|
||||
</div>
|
||||
|
||||
<!-- 合同条款 -->
|
||||
<div class="form-section">
|
||||
<h3>合同条款</h3>
|
||||
<el-row :gutter="20">
|
||||
<el-col :span="6">
|
||||
<el-form-item label="付款条件">
|
||||
<el-select v-model="newProcurementForm.paymentTerms" placeholder="请选择">
|
||||
<el-option label="请选择" value="" />
|
||||
<!-- 可以添加更多选项 -->
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="6">
|
||||
<el-form-item label="结算方式">
|
||||
<el-select v-model="newProcurementForm.settlementMethod" placeholder="请选择">
|
||||
<el-option label="请选择" value="" />
|
||||
<!-- 可以添加更多选项 -->
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
</el-row>
|
||||
</div>
|
||||
|
||||
<!-- 附件上传 -->
|
||||
<div class="form-section">
|
||||
<h3>附件上传</h3>
|
||||
<div class="upload-section">
|
||||
<el-upload class="upload-demo" action="" :on-preview="handlePreview" :on-remove="handleRemove"
|
||||
:before-remove="beforeRemove" multiple :limit="5" :on-exceed="handleExceed"
|
||||
:file-list="newProcurementForm.fileList" list-type="text">
|
||||
<el-button type="primary" :icon="Upload">上传文件</el-button>
|
||||
<template #tip>
|
||||
<div class="el-upload__tip">
|
||||
请将文件拖到此处,或点击上传<br>
|
||||
最多上传5个文件,单个文件大小不超过20M
|
||||
</div>
|
||||
</template>
|
||||
</el-upload>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<template #footer>
|
||||
<div class="dialog-footer">
|
||||
<el-button @click="cancelNewProcurement">取消</el-button>
|
||||
<el-button @click="saveDraft">保存草稿</el-button>
|
||||
<el-button type="primary" @click="submitProcurement">提交申请</el-button>
|
||||
</div>
|
||||
</template>
|
||||
</el-dialog>
|
||||
</div>
|
||||
</template>
|
||||
<style sc oped lang="scss">
|
||||
.procurementPlan {
|
||||
background-color: #F2F8FC;
|
||||
padding: 20px;
|
||||
}
|
||||
|
||||
.img {
|
||||
img {
|
||||
display: block;
|
||||
width: 80px;
|
||||
height: 80px;
|
||||
}
|
||||
}
|
||||
|
||||
.item {
|
||||
text-align: center;
|
||||
|
||||
.text {
|
||||
font-size: 14px;
|
||||
}
|
||||
|
||||
.count {
|
||||
font-size: 25px;
|
||||
font-weight: 600;
|
||||
text-align: left;
|
||||
margin-top: 10px;
|
||||
}
|
||||
}
|
||||
|
||||
.tabs {
|
||||
display: flex;
|
||||
gap: 10px;
|
||||
padding: 10px 0;
|
||||
}
|
||||
|
||||
.content {
|
||||
padding: 10px 0;
|
||||
}
|
||||
|
||||
/* 分页区域样式 */
|
||||
.pagination-section {
|
||||
background-color: #fff;
|
||||
border-radius: 8px;
|
||||
display: flex;
|
||||
justify-content: flex-end;
|
||||
align-items: center;
|
||||
margin-top: 15px;
|
||||
padding: 10px 0;
|
||||
}
|
||||
|
||||
.pagination-controls .el-pagination {
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
.pagination-controls .el-pagination button {
|
||||
min-width: 32px;
|
||||
height: 32px;
|
||||
line-height: 32px;
|
||||
border-radius: 4px;
|
||||
}
|
||||
|
||||
.pagination-controls .el-pagination .el-pager li {
|
||||
min-width: 32px;
|
||||
height: 32px;
|
||||
line-height: 32px;
|
||||
border-radius: 4px;
|
||||
}
|
||||
|
||||
.pagination-controls .el-pagination .el-pager li.active {
|
||||
background-color: #409eff;
|
||||
color: #fff;
|
||||
}
|
||||
</style>
|
||||
<script setup>
|
||||
import { ref, reactive, computed } from 'vue';
|
||||
import { Upload } from '@element-plus/icons-vue';
|
||||
import { ElMessage, ElMessageBox } from 'element-plus';
|
||||
const router = useRouter();
|
||||
// 新建采购申请单对话框是否可见
|
||||
const isNewProcurementDialogVisible = ref(false);
|
||||
|
||||
// 当前激活的标签页
|
||||
const activeTab = ref('pending');
|
||||
// 新建采购申请单表单数据
|
||||
const newProcurementForm = reactive({
|
||||
paymentTerms: '',
|
||||
settlementMethod: '',
|
||||
fileList: []
|
||||
});
|
||||
// 表格数据
|
||||
const tableData = ref([
|
||||
{
|
||||
planNumber: 'PLAN-2023-0615-003',
|
||||
planName: 'Q2风电轴承采购计划',
|
||||
equipmentType: '风电设备',
|
||||
requestDept: '运维部',
|
||||
applicant: '王主管',
|
||||
requestDate: '2023-06-15 10:30',
|
||||
estimatedAmount: '300,000.00',
|
||||
status: '待审批'
|
||||
},
|
||||
{
|
||||
planNumber: 'PLAN-2023-0615-003',
|
||||
planName: 'Q2风电轴承采购计划',
|
||||
equipmentType: '风电设备',
|
||||
requestDept: '运维部',
|
||||
applicant: '王主管',
|
||||
requestDate: '2023-06-15 10:30',
|
||||
estimatedAmount: '300,000.00',
|
||||
status: '待审批'
|
||||
},
|
||||
{
|
||||
planNumber: 'PLAN-2023-0615-003',
|
||||
planName: 'Q2风电轴承采购计划',
|
||||
equipmentType: '风电设备',
|
||||
requestDept: '运维部',
|
||||
applicant: '王主管',
|
||||
requestDate: '2023-06-15 10:30',
|
||||
estimatedAmount: '300,000.00',
|
||||
status: '待审批'
|
||||
},
|
||||
{
|
||||
planNumber: 'PLAN-2023-0615-003',
|
||||
planName: 'Q2风电轴承采购计划',
|
||||
equipmentType: '风电设备',
|
||||
requestDept: '运维部',
|
||||
applicant: '王主管',
|
||||
requestDate: '2023-06-15 10:30',
|
||||
estimatedAmount: '300,000.00',
|
||||
status: '待审批'
|
||||
},
|
||||
{
|
||||
planNumber: 'PLAN-2023-0615-003',
|
||||
planName: 'Q2风电轴承采购计划',
|
||||
equipmentType: '风电设备',
|
||||
requestDept: '运维部',
|
||||
applicant: '王主管',
|
||||
requestDate: '2023-06-15 10:30',
|
||||
estimatedAmount: '300,000.00',
|
||||
status: '待审批'
|
||||
},
|
||||
{
|
||||
planNumber: 'PLAN-2023-0615-003',
|
||||
planName: 'Q2风电轴承采购计划',
|
||||
equipmentType: '风电设备',
|
||||
requestDept: '运维部',
|
||||
applicant: '王主管',
|
||||
requestDate: '2023-06-15 10:30',
|
||||
estimatedAmount: '300,000.00',
|
||||
status: '待审批'
|
||||
},
|
||||
{
|
||||
planNumber: 'PLAN-2023-0615-003',
|
||||
planName: 'Q2风电轴承采购计划',
|
||||
equipmentType: '风电设备',
|
||||
requestDept: '运维部',
|
||||
applicant: '王主管',
|
||||
requestDate: '2023-06-15 10:30',
|
||||
estimatedAmount: '300,000.00',
|
||||
status: '待审批'
|
||||
},
|
||||
{
|
||||
planNumber: 'PLAN-2023-0615-003',
|
||||
planName: 'Q2风电轴承采购计划',
|
||||
equipmentType: '风电设备',
|
||||
requestDept: '运维部',
|
||||
applicant: '王主管',
|
||||
requestDate: '2023-06-15 10:30',
|
||||
estimatedAmount: '300,000.00',
|
||||
status: '待审批'
|
||||
},
|
||||
{
|
||||
planNumber: 'PLAN-2023-0615-003',
|
||||
planName: 'Q2风电轴承采购计划',
|
||||
equipmentType: '风电设备',
|
||||
requestDept: '运维部',
|
||||
applicant: '王主管',
|
||||
requestDate: '2023-06-15 10:30',
|
||||
estimatedAmount: '300,000.00',
|
||||
status: '待审批'
|
||||
},
|
||||
{
|
||||
planNumber: 'PLAN-2023-0615-003',
|
||||
planName: 'Q2风电轴承采购计划',
|
||||
equipmentType: '风电设备',
|
||||
requestDept: '运维部',
|
||||
applicant: '王主管',
|
||||
requestDate: '2023-06-15 10:30',
|
||||
estimatedAmount: '300,000.00',
|
||||
status: '待审批'
|
||||
},
|
||||
{
|
||||
planNumber: 'PLAN-2023-0615-003',
|
||||
planName: 'Q2风电轴承采购计划',
|
||||
equipmentType: '风电设备',
|
||||
requestDept: '运维部',
|
||||
applicant: '王主管',
|
||||
requestDate: '2023-06-15 10:30',
|
||||
estimatedAmount: '300,000.00',
|
||||
status: '待审批'
|
||||
},
|
||||
{
|
||||
planNumber: 'PLAN-2023-0615-003',
|
||||
planName: 'Q2风电轴承采购计划',
|
||||
equipmentType: '风电设备',
|
||||
requestDept: '运维部',
|
||||
applicant: '王主管',
|
||||
requestDate: '2023-06-15 10:30',
|
||||
estimatedAmount: '300,000.00',
|
||||
status: '待审批'
|
||||
}
|
||||
]);
|
||||
|
||||
// 分页相关
|
||||
const currentPage = ref(1);
|
||||
const pageSize = ref(10);
|
||||
const total = ref(12);
|
||||
|
||||
// 切换标签页
|
||||
const changeTab = (tab) => {
|
||||
activeTab.value = tab;
|
||||
// 这里可以根据标签页筛选数据
|
||||
currentPage.value = 1; // 切换标签页时重置到第一页
|
||||
};
|
||||
|
||||
// 获取状态标签类型
|
||||
const getStatusTagType = (status) => {
|
||||
switch (status) {
|
||||
case '待审批':
|
||||
return 'warning';
|
||||
case '采购中':
|
||||
return 'info';
|
||||
case '未通过':
|
||||
return 'danger';
|
||||
case '已通过':
|
||||
return 'primary';
|
||||
case '已完成':
|
||||
return 'success';
|
||||
default:
|
||||
return '';
|
||||
}
|
||||
};
|
||||
|
||||
// 查看详情
|
||||
const handleView = (row) => {
|
||||
console.log('查看采购计划详情:', row);
|
||||
router.push({
|
||||
path: '/materialManagement/planDetails',
|
||||
query: {
|
||||
planNumber: row.planNumber
|
||||
}
|
||||
});
|
||||
// 这里可以实现查看详情的逻辑,比如打开详情弹窗或跳转到详情页
|
||||
};
|
||||
|
||||
// 分页大小变化
|
||||
const handleSizeChange = (size) => {
|
||||
pageSize.value = size;
|
||||
currentPage.value = 1;
|
||||
};
|
||||
|
||||
// 当前页码变化
|
||||
const handleCurrentChange = (current) => {
|
||||
currentPage.value = current;
|
||||
};
|
||||
</script>
|
||||
439
src/views/materialManagement/spareParts.vue
Normal file
@ -0,0 +1,439 @@
|
||||
<template>
|
||||
<div style="padding: 20px;background-color: #F2F8FC;">
|
||||
<TitleComponent title="备品备件管理" subtitle="管理光伏和风电设备的所有备品备件信息" />
|
||||
<el-card style="border-radius: 10px;">
|
||||
<div class="title">
|
||||
数据总览
|
||||
</div>
|
||||
<div class="list">
|
||||
<div class="item">
|
||||
<div class="left">
|
||||
<div style="font-size: 14px;color:rgba(102, 102, 102, 1)">总备件数量</div>
|
||||
<div style="margin: 10px 0;">
|
||||
<span style="font-size: 24px;font-weight: bold;margin-right: 10px;">2,548</span>
|
||||
<span>个</span>
|
||||
</div>
|
||||
<div>
|
||||
<div style="display: flex;align-items: center;">
|
||||
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink"
|
||||
width="18" height="18" viewBox="0 0 18 18" fill="none">
|
||||
<path
|
||||
d="M15.15 5.7748L15.15 5.69982L15.15 5.62481L15.075 5.62481C15.075 5.62481 15 5.62481 14.925 5.5498L11.25 5.5498C10.875 5.5498 10.575 5.84981 10.575 6.2248C10.575 6.59982 10.875 6.8998 11.25 6.8998L13.125 6.8998L9.52501 10.4998L7.72501 8.6998C7.35 8.32481 6.60001 8.32481 6.225 8.6998L3.075 11.8498C2.85 12.0748 2.85 12.5248 3.075 12.7498C3.22501 12.8998 3.37501 12.9748 3.525 12.9748C3.67501 12.9748 3.82501 12.9748 3.975 12.7498L6.9 9.8248L8.7 11.6248C9.07501 11.9998 9.825 11.9998 10.2 11.6248L13.95 7.87481L13.95 9.74981C13.95 10.1248 14.25 10.4248 14.625 10.4248C15 10.4248 15.3 10.1248 15.3 9.74981L15.3 6.37482L15.3 6.14982L15.15 5.7748Z"
|
||||
fill="#00B87A"></path>
|
||||
</svg>
|
||||
<div>
|
||||
<span
|
||||
style="color: rgba(0, 184, 122, 1);font-size: 14px;margin: 0 5px;margin-right: 10px;">8.2%</span>
|
||||
<span style="color: rgba(154, 154, 154, 1);font-size: 14px;">较昨日同期</span>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="right">
|
||||
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="34"
|
||||
height="34" viewBox="0 0 34 34" fill="none">
|
||||
<rect x="0" y="0" width="34" height="34" rx="4" fill="#186DF5"></rect>
|
||||
<path
|
||||
d="M8.72815 24.0051C8.31696 24.0051 7.9743 24.3478 7.9743 24.759C7.9743 25.1702 8.31696 25.5128 8.72815 25.5128L16.2256 25.5128C16.6368 25.5128 16.9794 25.1702 16.9794 24.759C16.9794 24.3478 16.6368 24.0051 16.2256 24.0051L8.72815 24.0051ZM8.74186 19.4957C8.33067 19.4957 7.988 19.8384 7.988 20.2496C7.988 20.6608 8.33067 21.0034 8.74186 21.0034L13.2513 21.0034C13.6625 21.0034 14.0051 20.6608 14.0051 20.2496C14.0051 19.8384 13.6625 19.4957 13.2513 19.4957L8.74186 19.4957ZM5 16.494C5 15.6716 5.67162 15 6.494 15L27.506 15C28.3284 15 29 15.6716 29 16.494L29 26.6505C29 27.6648 28.1776 28.5009 27.1496 28.5009L6.85037 28.5009C5.83609 28.5009 5 27.6785 5 26.6505L5 16.494Z"
|
||||
fill="#FFFFFF"></path>
|
||||
<path
|
||||
d="M17.7242 12.4974L17.7242 6.494C17.7242 5.67162 18.3959 5 19.2182 5L23.4124 5C24.0018 5 24.5638 5.28784 24.9201 5.76756L28.9772 12.4974L28.9772 12.5385C29.0458 13.2787 28.3467 13.9366 27.6066 13.9914L19.2182 13.9914C18.3959 13.9914 17.7242 13.3198 17.7242 12.4974ZM14.7499 13.9914L6.3753 13.9914C5.63515 13.9229 4.93612 13.2787 5.00466 12.5385L5.00466 12.5248L5.00466 12.4974L9.06177 5.76756C9.40443 5.28784 9.96639 5 10.5695 5L14.7637 5C15.586 5 16.2577 5.67162 16.2577 6.494L16.2577 12.4974C16.2577 13.3198 15.586 13.9914 14.7499 13.9914Z"
|
||||
fill="#FFFFFF"></path>
|
||||
</svg>
|
||||
</div>
|
||||
</div>
|
||||
<div class="item">
|
||||
<div class="left">
|
||||
<div style="font-size: 14px;color:rgba(102, 102, 102, 1)">总备件数量</div>
|
||||
<div style="margin: 10px 0;">
|
||||
<span style="font-size: 24px;font-weight: bold;margin-right: 10px;">2,548</span>
|
||||
<span>个</span>
|
||||
</div>
|
||||
<div>
|
||||
<div style="display: flex;align-items: center;">
|
||||
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink"
|
||||
width="18" height="18" viewBox="0 0 18 18" fill="none">
|
||||
<path
|
||||
d="M15.15 5.7748L15.15 5.69982L15.15 5.62481L15.075 5.62481C15.075 5.62481 15 5.62481 14.925 5.5498L11.25 5.5498C10.875 5.5498 10.575 5.84981 10.575 6.2248C10.575 6.59982 10.875 6.8998 11.25 6.8998L13.125 6.8998L9.52501 10.4998L7.72501 8.6998C7.35 8.32481 6.60001 8.32481 6.225 8.6998L3.075 11.8498C2.85 12.0748 2.85 12.5248 3.075 12.7498C3.22501 12.8998 3.37501 12.9748 3.525 12.9748C3.67501 12.9748 3.82501 12.9748 3.975 12.7498L6.9 9.8248L8.7 11.6248C9.07501 11.9998 9.825 11.9998 10.2 11.6248L13.95 7.87481L13.95 9.74981C13.95 10.1248 14.25 10.4248 14.625 10.4248C15 10.4248 15.3 10.1248 15.3 9.74981L15.3 6.37482L15.3 6.14982L15.15 5.7748Z"
|
||||
fill="#E32727"></path>
|
||||
</svg>
|
||||
<div>
|
||||
<span
|
||||
style="color: rgba(227, 39, 39, 1);font-size: 14px;margin: 0 5px;margin-right: 10px;">8.2%</span>
|
||||
<span style="color: rgba(154, 154, 154, 1);font-size: 14px;">较昨日同期</span>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="right">
|
||||
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="34"
|
||||
height="34" viewBox="0 0 34 34" fill="none">
|
||||
<rect x="0" y="0" width="34" height="34" rx="4" fill="#186DF5"></rect>
|
||||
<path
|
||||
d="M8.72815 24.0051C8.31696 24.0051 7.9743 24.3478 7.9743 24.759C7.9743 25.1702 8.31696 25.5128 8.72815 25.5128L16.2256 25.5128C16.6368 25.5128 16.9794 25.1702 16.9794 24.759C16.9794 24.3478 16.6368 24.0051 16.2256 24.0051L8.72815 24.0051ZM8.74186 19.4957C8.33067 19.4957 7.988 19.8384 7.988 20.2496C7.988 20.6608 8.33067 21.0034 8.74186 21.0034L13.2513 21.0034C13.6625 21.0034 14.0051 20.6608 14.0051 20.2496C14.0051 19.8384 13.6625 19.4957 13.2513 19.4957L8.74186 19.4957ZM5 16.494C5 15.6716 5.67162 15 6.494 15L27.506 15C28.3284 15 29 15.6716 29 16.494L29 26.6505C29 27.6648 28.1776 28.5009 27.1496 28.5009L6.85037 28.5009C5.83609 28.5009 5 27.6785 5 26.6505L5 16.494Z"
|
||||
fill="#FFFFFF"></path>
|
||||
<path
|
||||
d="M17.7242 12.4974L17.7242 6.494C17.7242 5.67162 18.3959 5 19.2182 5L23.4124 5C24.0018 5 24.5638 5.28784 24.9201 5.76756L28.9772 12.4974L28.9772 12.5385C29.0458 13.2787 28.3467 13.9366 27.6066 13.9914L19.2182 13.9914C18.3959 13.9914 17.7242 13.3198 17.7242 12.4974ZM14.7499 13.9914L6.3753 13.9914C5.63515 13.9229 4.93612 13.2787 5.00466 12.5385L5.00466 12.5248L5.00466 12.4974L9.06177 5.76756C9.40443 5.28784 9.96639 5 10.5695 5L14.7637 5C15.586 5 16.2577 5.67162 16.2577 6.494L16.2577 12.4974C16.2577 13.3198 15.586 13.9914 14.7499 13.9914Z"
|
||||
fill="#FFFFFF"></path>
|
||||
</svg>
|
||||
</div>
|
||||
</div>
|
||||
<div class="item">
|
||||
<div class="left">
|
||||
<div style="font-size: 14px;color:rgba(102, 102, 102, 1)">总备件数量</div>
|
||||
<div style="margin: 10px 0;">
|
||||
<span style="font-size: 24px;font-weight: bold;margin-right: 10px;">2,548</span>
|
||||
<span>个</span>
|
||||
</div>
|
||||
<div>
|
||||
<div style="display: flex;align-items: center;">
|
||||
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink"
|
||||
width="18" height="18" viewBox="0 0 18 18" fill="none">
|
||||
<path
|
||||
d="M15.15 5.7748L15.15 5.69982L15.15 5.62481L15.075 5.62481C15.075 5.62481 15 5.62481 14.925 5.5498L11.25 5.5498C10.875 5.5498 10.575 5.84981 10.575 6.2248C10.575 6.59982 10.875 6.8998 11.25 6.8998L13.125 6.8998L9.52501 10.4998L7.72501 8.6998C7.35 8.32481 6.60001 8.32481 6.225 8.6998L3.075 11.8498C2.85 12.0748 2.85 12.5248 3.075 12.7498C3.22501 12.8998 3.37501 12.9748 3.525 12.9748C3.67501 12.9748 3.82501 12.9748 3.975 12.7498L6.9 9.8248L8.7 11.6248C9.07501 11.9998 9.825 11.9998 10.2 11.6248L13.95 7.87481L13.95 9.74981C13.95 10.1248 14.25 10.4248 14.625 10.4248C15 10.4248 15.3 10.1248 15.3 9.74981L15.3 6.37482L15.3 6.14982L15.15 5.7748Z"
|
||||
fill="#00B87A"></path>
|
||||
</svg>
|
||||
<div>
|
||||
<span
|
||||
style="color: rgba(0, 184, 122, 1);font-size: 14px;margin: 0 5px;margin-right: 10px;">8.2%</span>
|
||||
<span style="color: rgba(154, 154, 154, 1);font-size: 14px;">较昨日同期</span>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="right">
|
||||
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="34"
|
||||
height="34" viewBox="0 0 34 34" fill="none">
|
||||
<rect x="0" y="0" width="34" height="34" rx="4" fill="#186DF5"></rect>
|
||||
<path
|
||||
d="M8.72815 24.0051C8.31696 24.0051 7.9743 24.3478 7.9743 24.759C7.9743 25.1702 8.31696 25.5128 8.72815 25.5128L16.2256 25.5128C16.6368 25.5128 16.9794 25.1702 16.9794 24.759C16.9794 24.3478 16.6368 24.0051 16.2256 24.0051L8.72815 24.0051ZM8.74186 19.4957C8.33067 19.4957 7.988 19.8384 7.988 20.2496C7.988 20.6608 8.33067 21.0034 8.74186 21.0034L13.2513 21.0034C13.6625 21.0034 14.0051 20.6608 14.0051 20.2496C14.0051 19.8384 13.6625 19.4957 13.2513 19.4957L8.74186 19.4957ZM5 16.494C5 15.6716 5.67162 15 6.494 15L27.506 15C28.3284 15 29 15.6716 29 16.494L29 26.6505C29 27.6648 28.1776 28.5009 27.1496 28.5009L6.85037 28.5009C5.83609 28.5009 5 27.6785 5 26.6505L5 16.494Z"
|
||||
fill="#FFFFFF"></path>
|
||||
<path
|
||||
d="M17.7242 12.4974L17.7242 6.494C17.7242 5.67162 18.3959 5 19.2182 5L23.4124 5C24.0018 5 24.5638 5.28784 24.9201 5.76756L28.9772 12.4974L28.9772 12.5385C29.0458 13.2787 28.3467 13.9366 27.6066 13.9914L19.2182 13.9914C18.3959 13.9914 17.7242 13.3198 17.7242 12.4974ZM14.7499 13.9914L6.3753 13.9914C5.63515 13.9229 4.93612 13.2787 5.00466 12.5385L5.00466 12.5248L5.00466 12.4974L9.06177 5.76756C9.40443 5.28784 9.96639 5 10.5695 5L14.7637 5C15.586 5 16.2577 5.67162 16.2577 6.494L16.2577 12.4974C16.2577 13.3198 15.586 13.9914 14.7499 13.9914Z"
|
||||
fill="#FFFFFF"></path>
|
||||
</svg>
|
||||
</div>
|
||||
</div>
|
||||
<div class="item">
|
||||
<div class="left">
|
||||
<div style="font-size: 14px;color:rgba(102, 102, 102, 1)">总备件数量</div>
|
||||
<div style="margin: 10px 0;">
|
||||
<span style="font-size: 24px;font-weight: bold;margin-right: 10px;">2,548</span>
|
||||
<span>个</span>
|
||||
</div>
|
||||
<div>
|
||||
<div style="display: flex;align-items: center;">
|
||||
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink"
|
||||
width="18" height="18" viewBox="0 0 18 18" fill="none">
|
||||
<path
|
||||
d="M15.15 5.7748L15.15 5.69982L15.15 5.62481L15.075 5.62481C15.075 5.62481 15 5.62481 14.925 5.5498L11.25 5.5498C10.875 5.5498 10.575 5.84981 10.575 6.2248C10.575 6.59982 10.875 6.8998 11.25 6.8998L13.125 6.8998L9.52501 10.4998L7.72501 8.6998C7.35 8.32481 6.60001 8.32481 6.225 8.6998L3.075 11.8498C2.85 12.0748 2.85 12.5248 3.075 12.7498C3.22501 12.8998 3.37501 12.9748 3.525 12.9748C3.67501 12.9748 3.82501 12.9748 3.975 12.7498L6.9 9.8248L8.7 11.6248C9.07501 11.9998 9.825 11.9998 10.2 11.6248L13.95 7.87481L13.95 9.74981C13.95 10.1248 14.25 10.4248 14.625 10.4248C15 10.4248 15.3 10.1248 15.3 9.74981L15.3 6.37482L15.3 6.14982L15.15 5.7748Z"
|
||||
fill="#00B87A"></path>
|
||||
</svg>
|
||||
<div>
|
||||
<span
|
||||
style="color: rgba(0, 184, 122, 1);font-size: 14px;margin: 0 5px;margin-right: 10px;">8.2%</span>
|
||||
<span style="color: rgba(154, 154, 154, 1);font-size: 14px;">较昨日同期</span>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="right">
|
||||
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="34"
|
||||
height="34" viewBox="0 0 34 34" fill="none">
|
||||
<rect x="0" y="0" width="34" height="34" rx="4" fill="#186DF5"></rect>
|
||||
<path
|
||||
d="M8.72815 24.0051C8.31696 24.0051 7.9743 24.3478 7.9743 24.759C7.9743 25.1702 8.31696 25.5128 8.72815 25.5128L16.2256 25.5128C16.6368 25.5128 16.9794 25.1702 16.9794 24.759C16.9794 24.3478 16.6368 24.0051 16.2256 24.0051L8.72815 24.0051ZM8.74186 19.4957C8.33067 19.4957 7.988 19.8384 7.988 20.2496C7.988 20.6608 8.33067 21.0034 8.74186 21.0034L13.2513 21.0034C13.6625 21.0034 14.0051 20.6608 14.0051 20.2496C14.0051 19.8384 13.6625 19.4957 13.2513 19.4957L8.74186 19.4957ZM5 16.494C5 15.6716 5.67162 15 6.494 15L27.506 15C28.3284 15 29 15.6716 29 16.494L29 26.6505C29 27.6648 28.1776 28.5009 27.1496 28.5009L6.85037 28.5009C5.83609 28.5009 5 27.6785 5 26.6505L5 16.494Z"
|
||||
fill="#FFFFFF"></path>
|
||||
<path
|
||||
d="M17.7242 12.4974L17.7242 6.494C17.7242 5.67162 18.3959 5 19.2182 5L23.4124 5C24.0018 5 24.5638 5.28784 24.9201 5.76756L28.9772 12.4974L28.9772 12.5385C29.0458 13.2787 28.3467 13.9366 27.6066 13.9914L19.2182 13.9914C18.3959 13.9914 17.7242 13.3198 17.7242 12.4974ZM14.7499 13.9914L6.3753 13.9914C5.63515 13.9229 4.93612 13.2787 5.00466 12.5385L5.00466 12.5248L5.00466 12.4974L9.06177 5.76756C9.40443 5.28784 9.96639 5 10.5695 5L14.7637 5C15.586 5 16.2577 5.67162 16.2577 6.494L16.2577 12.4974C16.2577 13.3198 15.586 13.9914 14.7499 13.9914Z"
|
||||
fill="#FFFFFF"></path>
|
||||
</svg>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div style="margin-top: 30px;">
|
||||
<div class="menu" style="background-color: #F2F2F2; padding: 20px;">
|
||||
<el-row gutter="30">
|
||||
<el-col :span="3">
|
||||
<el-input placeholder="请输入备件名称"></el-input>
|
||||
</el-col>
|
||||
<el-col :span="3">
|
||||
<el-select placeholder="设备类型">
|
||||
</el-select>
|
||||
</el-col>
|
||||
<el-col :span="3">
|
||||
<el-select placeholder="备件类别">
|
||||
</el-select>
|
||||
</el-col>
|
||||
<el-col :span="3">
|
||||
<el-select placeholder="全部状态">
|
||||
</el-select>
|
||||
</el-col>
|
||||
<el-col :span="8">
|
||||
<el-button icon="search" type="primary">搜索</el-button>
|
||||
<el-button icon="refresh">重置</el-button>
|
||||
</el-col>
|
||||
</el-row>
|
||||
</div>
|
||||
<el-table :data="pagedTableData" border style="width: 100%;margin-top: 10px;">
|
||||
<el-table-column prop="backupNumber" label="备件编号" />
|
||||
<el-table-column prop="backupName" label="备件名称" />
|
||||
<el-table-column prop="equipmentType" label="设备类型" />
|
||||
<el-table-column prop="specificationModel" label="规格型号" />
|
||||
<el-table-column prop="inventoryStatus" label="库存状态" />
|
||||
<el-table-column prop="inventoryQuantity" label="库存数量" />
|
||||
<el-table-column label="安全库存">
|
||||
<template #default="scope">
|
||||
<el-tag :type="getTagType(scope.row.safetyStockStatus)">
|
||||
{{ scope.row.safetyStockStatus }}
|
||||
</el-tag>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="操作">
|
||||
<template #default="scope">
|
||||
<el-button type="text" @click="handleEdit(scope.row)">编辑</el-button>
|
||||
<el-button type="text" @click="handleDetail(scope.row)">详情</el-button>
|
||||
<el-button type="text" @click="handleDelete(scope.row)">删除</el-button>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
<div class="pagination-section">
|
||||
<div class="pagination-info">
|
||||
显示第{{ (currentPage - 1) * pageSize + 1 }}到{{ Math.min(currentPage * pageSize, total) }}条,共有{{
|
||||
total }}条记录
|
||||
</div>
|
||||
<div class="pagination-controls">
|
||||
<el-pagination @size-change="handleSizeChange" @current-change="handleCurrentChange"
|
||||
:current-page="currentPage" :page-sizes="[10, 20, 30, 40]" :page-size="pageSize"
|
||||
layout="total, sizes, prev, pager, next, jumper" :total="total" background>
|
||||
</el-pagination>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</el-card>
|
||||
</div>
|
||||
</template>
|
||||
<style scoped lang="scss">
|
||||
.title {
|
||||
font-weight: bold;
|
||||
font-size: 22px;
|
||||
font-weight: 400;
|
||||
letter-spacing: 0px;
|
||||
line-height: 28.6px;
|
||||
color: rgba(10, 14, 26, 1);
|
||||
}
|
||||
|
||||
.list {
|
||||
margin-top: 30px;
|
||||
display: flex;
|
||||
gap: 140px;
|
||||
justify-content: space-between;
|
||||
}
|
||||
|
||||
.item {
|
||||
flex: 1;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
padding: 0 30px;
|
||||
}
|
||||
|
||||
/* 分页区域样式 */
|
||||
.pagination-section {
|
||||
background-color: #fff;
|
||||
padding: 16px 20px;
|
||||
border-radius: 8px;
|
||||
box-shadow: 0 2px 4px rgba(0, 0, 0, 0.05);
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.pagination-info {
|
||||
font-size: 14px;
|
||||
color: #606266;
|
||||
}
|
||||
|
||||
.pagination-controls .el-pagination {
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
.pagination-controls .el-pagination__sizes {
|
||||
margin-right: 20px;
|
||||
}
|
||||
|
||||
.pagination-controls .el-pagination button {
|
||||
min-width: 32px;
|
||||
height: 32px;
|
||||
line-height: 32px;
|
||||
border-radius: 4px;
|
||||
}
|
||||
|
||||
.pagination-controls .el-pagination .el-pager li {
|
||||
min-width: 32px;
|
||||
height: 32px;
|
||||
line-height: 32px;
|
||||
border-radius: 4px;
|
||||
}
|
||||
|
||||
.pagination-controls .el-pagination .el-pager li.active {
|
||||
background-color: #409eff;
|
||||
color: #fff;
|
||||
}
|
||||
</style>
|
||||
<script setup>
|
||||
import TitleComponent from '@/components/TitleComponent';
|
||||
|
||||
|
||||
// 计算属性:根据当前页码和每页条数获取分页后的数据
|
||||
const tableData = ref([
|
||||
{
|
||||
backupNumber: 'SOL-2023-001',
|
||||
backupName: '光伏逆变器模块',
|
||||
equipmentType: '光伏设备',
|
||||
specificationModel: 'SGGKTL-M',
|
||||
inventoryStatus: '12个',
|
||||
inventoryQuantity: '5个',
|
||||
safetyStockStatus: '正常'
|
||||
},
|
||||
{
|
||||
backupNumber: 'SOL-2023-001',
|
||||
backupName: '光伏逆变器模块',
|
||||
equipmentType: '光伏设备',
|
||||
specificationModel: 'SGGKTL-M',
|
||||
inventoryStatus: '12个',
|
||||
inventoryQuantity: '5个',
|
||||
safetyStockStatus: '正常'
|
||||
},
|
||||
{
|
||||
backupNumber: 'SOL-2023-001',
|
||||
backupName: '光伏逆变器模块',
|
||||
equipmentType: '光伏设备',
|
||||
specificationModel: 'SGGKTL-M',
|
||||
inventoryStatus: '12个',
|
||||
inventoryQuantity: '5个',
|
||||
safetyStockStatus: '正常'
|
||||
},
|
||||
{
|
||||
backupNumber: 'SOL-2023-001',
|
||||
backupName: '光伏逆变器模块',
|
||||
equipmentType: '光伏设备',
|
||||
specificationModel: 'SGGKTL-M',
|
||||
inventoryStatus: '12个',
|
||||
inventoryQuantity: '5个',
|
||||
safetyStockStatus: '正常'
|
||||
},
|
||||
{
|
||||
backupNumber: 'WIN-2023-045',
|
||||
backupName: '风力发电机轴承',
|
||||
equipmentType: '风电设备',
|
||||
specificationModel: '6318-2RS1/C3',
|
||||
inventoryStatus: '3套',
|
||||
inventoryQuantity: '5套',
|
||||
safetyStockStatus: '低库存'
|
||||
},
|
||||
{
|
||||
backupNumber: 'SOL-2023-001',
|
||||
backupName: '光伏逆变器模块',
|
||||
equipmentType: '光伏设备',
|
||||
specificationModel: 'SGGKTL-M',
|
||||
inventoryStatus: '12个',
|
||||
inventoryQuantity: '5个',
|
||||
safetyStockStatus: '正常'
|
||||
},
|
||||
{
|
||||
backupNumber: 'WIN-2023-045',
|
||||
backupName: '风力发电机轴承',
|
||||
equipmentType: '风电设备',
|
||||
specificationModel: '6318-2RS1/C3',
|
||||
inventoryStatus: '3套',
|
||||
inventoryQuantity: '5套',
|
||||
safetyStockStatus: '低库存'
|
||||
},
|
||||
{
|
||||
backupNumber: 'WIN-2023-045',
|
||||
backupName: '风力发电机轴承',
|
||||
equipmentType: '风电设备',
|
||||
specificationModel: '6318-2RS1/C3',
|
||||
inventoryStatus: '0套',
|
||||
inventoryQuantity: '2套',
|
||||
safetyStockStatus: '缺货'
|
||||
},
|
||||
{
|
||||
backupNumber: 'WIN-2023-045',
|
||||
backupName: '风力发电机轴承',
|
||||
equipmentType: '风电设备',
|
||||
specificationModel: '6318-2RS1/C3',
|
||||
inventoryStatus: '3套',
|
||||
inventoryQuantity: '5套',
|
||||
safetyStockStatus: '低库存'
|
||||
},
|
||||
{
|
||||
backupNumber: 'WIN-2023-045',
|
||||
backupName: '风力发电机轴承',
|
||||
equipmentType: '风电设备',
|
||||
specificationModel: '6318-2RS1/C3',
|
||||
inventoryStatus: '3套',
|
||||
inventoryQuantity: '5套',
|
||||
safetyStockStatus: '低库存'
|
||||
},
|
||||
{
|
||||
backupNumber: 'WIN-2023-045',
|
||||
backupName: '风力发电机轴承',
|
||||
equipmentType: '风电设备',
|
||||
specificationModel: '6318-2RS1/C3',
|
||||
inventoryStatus: '3套',
|
||||
inventoryQuantity: '5套',
|
||||
safetyStockStatus: '低库存'
|
||||
}
|
||||
])
|
||||
// 当前页码
|
||||
const currentPage = ref(1);
|
||||
// 每页条数 - 与分页控件默认值保持一致
|
||||
const pageSize = ref(10);
|
||||
// 总条数 - 从原始数据计算得出
|
||||
const total = ref(tableData.value.length);
|
||||
const pagedTableData = computed(() => {
|
||||
const startIndex = (currentPage.value - 1) * pageSize.value;
|
||||
const endIndex = startIndex + pageSize.value;
|
||||
return tableData.value.slice(startIndex, endIndex);
|
||||
});
|
||||
// 当前页码改变
|
||||
const handleCurrentChange = (val) => {
|
||||
currentPage.value = val;
|
||||
};
|
||||
|
||||
// 根据安全库存状态获取标签类型
|
||||
const getTagType = (status) => {
|
||||
if (status === '正常') {
|
||||
return 'success'
|
||||
} else if (status === '低库存') {
|
||||
return 'warning'
|
||||
} else if (status === '缺货') {
|
||||
return 'danger'
|
||||
}
|
||||
return ''
|
||||
}
|
||||
|
||||
// 编辑操作方法
|
||||
const handleEdit = (row) => {
|
||||
console.log('编辑', row)
|
||||
// 这里可以编写编辑的逻辑,比如跳转到编辑页面等
|
||||
}
|
||||
|
||||
// 详情操作方法
|
||||
const handleDetail = (row) => {
|
||||
console.log('详情', row)
|
||||
// 这里可以编写查看详情的逻辑
|
||||
}
|
||||
|
||||
// 删除操作方法
|
||||
const handleDelete = (row) => {
|
||||
console.log('删除', row)
|
||||
// 这里可以编写删除的逻辑,比如提示确认删除,然后从表格数据中移除等
|
||||
}
|
||||
</script>
|
||||
75
src/views/pvSystem/siteOverview/allAlarms.vue
Normal file
@ -0,0 +1,75 @@
|
||||
<template>
|
||||
<div class="allAlarms">
|
||||
<el-row>
|
||||
<el-col :span="12">
|
||||
<TitleComponent title="所有告警"></TitleComponent>
|
||||
</el-col>
|
||||
<el-col :span="12">
|
||||
<el-row class="right-align-row">
|
||||
<el-col :span="8">
|
||||
<el-input prefix-icon="search" placeholder="搜索告警信息"></el-input>
|
||||
</el-col>
|
||||
<el-col :span="4" style="text-align: right;">
|
||||
<el-button icon="download" type="primary">
|
||||
导出数据
|
||||
</el-button>
|
||||
</el-col>
|
||||
</el-row>
|
||||
</el-col>
|
||||
</el-row>
|
||||
<el-table :data="tableData" style="width: 100%;">
|
||||
<el-table-column label="告警编号" prop="id"></el-table-column>
|
||||
<el-table-column label="告警名称" prop="title"></el-table-column>
|
||||
<el-table-column label="告警等级" prop="level"></el-table-column>
|
||||
<el-table-column label="告警时间" prop="alarmTime"></el-table-column>
|
||||
<el-table-column label="负责人" prop="responsible"></el-table-column>
|
||||
<el-table-column label="告警描述" prop="description"></el-table-column>
|
||||
<el-table-column label="状态">
|
||||
<template #default="scope">
|
||||
<el-tag
|
||||
:type="scope.row.status === 1 ? 'success' : scope.row.status === 2 ? 'warning' : 'danger'">{{
|
||||
scope.row.status === 1 ? '已解决' : scope.row.status === 2 ? '待解决' : '未解决' }}</el-tag>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
<div style="background-color: #fff;padding: 20px 0;">
|
||||
<el-pagination layout="prev, pager, next, jumper,sizes" :total="totalRecords"
|
||||
v-model:current-page="currentPage" v-model:page-size="pageSize" :page-sizes="[20, 50, 100]"
|
||||
@current-change="handlePageChange" @size-change="handleSizeChange"></el-pagination>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</template>
|
||||
<style scoped>
|
||||
.allAlarms {
|
||||
background-color: #F2F8FC;
|
||||
padding: 20px;
|
||||
}
|
||||
|
||||
.right-align-row {
|
||||
display: flex;
|
||||
justify-content: flex-end;
|
||||
}
|
||||
</style>
|
||||
<script setup>
|
||||
import TitleComponent from '@/components/TitleComponent';
|
||||
const pageSize = ref(20);
|
||||
const totalRecords = ref(100);
|
||||
const tableData = computed(() => {
|
||||
return Array.from({ length: 15 }).map((_, index) => {
|
||||
return {
|
||||
id: index,
|
||||
title: `逆变器温度过高`,
|
||||
id: `INV-2023-003`,
|
||||
level: `二级`,
|
||||
alarmTime: '2025-09-18 18:00',
|
||||
// 预计解决时间
|
||||
resolveTime: '2025-09-19 18:00',
|
||||
// 负责人
|
||||
responsible: '李华(现场运维组)',
|
||||
description: `AAAABBBCCCDE...`,
|
||||
status: Math.floor(Math.random() * 3) + 1
|
||||
}
|
||||
})
|
||||
})
|
||||
</script>
|
||||
@ -1,7 +1,7 @@
|
||||
<template>
|
||||
<el-card shadow="never" style="border-radius: 10px;">
|
||||
<div style="margin-bottom: 20px;display: flex;align-items: center;justify-content: right;">
|
||||
<span style="margin-right: 5px;color: rgba(113, 128, 150, 1);font-size: 14px;">
|
||||
<span style="margin-right: 5px;color: rgba(113, 128, 150, 1);font-size: 14px;" @click="handleClick">
|
||||
查看全部告警信息
|
||||
</span>
|
||||
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="8" height="8"
|
||||
@ -207,4 +207,11 @@
|
||||
}
|
||||
}
|
||||
</style>
|
||||
<script setup></script>
|
||||
<script setup>
|
||||
const router = useRouter();
|
||||
const handleClick = () => {
|
||||
console.log('查看全部告警信息');
|
||||
router.push('/pvSystem/allAlarms');
|
||||
}
|
||||
|
||||
</script>
|
||||
@ -1,4 +1,5 @@
|
||||
<template>
|
||||
|
||||
<el-card shadow="never" style="border-radius: 10px;">
|
||||
<el-form :inline="true" :model="formInline" label-width="120" style="display: flex; justify-content: center;">
|
||||
<el-form-item label="规则编号">
|
||||
@ -53,11 +54,37 @@
|
||||
<pagination :total="total" v-model:page="queryParams.pageNum" v-model:limit="queryParams.pageSize"
|
||||
@pagination="getList" />
|
||||
</el-card>
|
||||
<el-dialog v-model="dialogVisible" width="1000" id="custom-dialog" class="no-header-dialog normal">
|
||||
<div class="alert-content">
|
||||
<div class="img">
|
||||
<img src="/assets/dialog1.png" alt="">
|
||||
</div>
|
||||
</div>
|
||||
</el-dialog>
|
||||
</template>
|
||||
<style lang="scss" scoped></style>
|
||||
<style lang="scss">
|
||||
// #custom-dialog {
|
||||
// padding: 0;
|
||||
|
||||
// .el-dialog__header {
|
||||
// display: none;
|
||||
// }
|
||||
|
||||
// .el-dialog__body {
|
||||
// padding: 0 !important;
|
||||
// }
|
||||
|
||||
// .alert-content {
|
||||
// padding: 80px;
|
||||
// background: linear-gradient(180deg, rgba(0, 119, 255, 0.23) 0%, rgba(255, 255, 255, 0) 100%);
|
||||
// }
|
||||
// }</style>
|
||||
<script setup>
|
||||
const formInline = ref({})
|
||||
const total = ref(0);
|
||||
const loading = ref(false);
|
||||
const dialogVisible = ref(true);
|
||||
const listData = [
|
||||
{ id: "INV-2023-001", shuchu: "12.8kw", xiaolv: "98.2%", wendu: "42℃", fadian: "158.5kWh", status: 1 },
|
||||
{ id: "INV-2023-001", shuchu: "12.8kw", xiaolv: "98.2%", wendu: "42℃", fadian: "158.5kWh", status: 1 },
|
||||
|
||||
@ -177,11 +177,15 @@
|
||||
<QiXiang />
|
||||
</el-col>
|
||||
</el-row>
|
||||
<el-row>
|
||||
<div>
|
||||
<el-row :gutter="20"> <!-- gutter:列之间的间距(单位px),控制垂直/水平间距 -->
|
||||
<!-- 标题列:占满12列(栅格系统默认12列) -->
|
||||
<el-col> <!-- span=12 表示占满一行宽度 -->
|
||||
<TitleComponent title="逆变器运行状态" :fontLevel="2" />
|
||||
</div>
|
||||
<status style="width: 100%;" />
|
||||
</el-col>
|
||||
<!-- status组件列:同样占满12列,与标题垂直排列 -->
|
||||
<el-col>
|
||||
<status style="width: 100%;" /> <!-- 确保组件宽度100%,不溢出 -->
|
||||
</el-col>
|
||||
</el-row>
|
||||
<el-row style="display: flex;">
|
||||
<el-col :span="6" style="display: flex;flex-direction: column;">
|
||||
|
||||
149
src/views/securitySurveillance/components/sbzt.vue
Normal file
@ -0,0 +1,149 @@
|
||||
<template>
|
||||
<el-card style="border-radius: 15px;">
|
||||
<el-row gutter="35">
|
||||
<el-col :span="8" class="status-card">
|
||||
<div class="title">设备状态</div>
|
||||
<!-- gutter设置为20,创建左右间隙 -->
|
||||
<el-row gutter="20" style="width: 100%;">
|
||||
<!-- 一行2个,每个占12格(24/2=12) -->
|
||||
<el-col :span="12">
|
||||
<div class="item">
|
||||
<div class="status">在线</div>
|
||||
<div class="count" style="color: rgba(0, 184, 122, 1);">56</div>
|
||||
</div>
|
||||
</el-col>
|
||||
<el-col :span="12">
|
||||
<div class="item">
|
||||
<div class="status">离线</div>
|
||||
<div class="count" style="color: rgba(102, 102, 102, 1);">10</div>
|
||||
</div>
|
||||
</el-col>
|
||||
<el-col :span="12">
|
||||
<div class="item">
|
||||
<div class="status">网络延迟</div>
|
||||
<div class="count" style="color: rgba(255, 208, 35, 1);">8</div>
|
||||
</div>
|
||||
</el-col>
|
||||
<el-col :span="12">
|
||||
<div class="item">
|
||||
<div class="status">故障</div>
|
||||
<div class="count" style="color: rgba(227, 39, 39, 1);">1</div>
|
||||
</div>
|
||||
</el-col>
|
||||
</el-row>
|
||||
</el-col>
|
||||
<el-col :span="16" class="alarm-card">
|
||||
<div class="title">最近报警</div>
|
||||
<el-row class="list">
|
||||
<el-col>
|
||||
<div class="item red">
|
||||
<div class="sub-title">
|
||||
异常移动检测
|
||||
</div>
|
||||
<div class="content">
|
||||
A区b栋102 | 今天08:23
|
||||
</div>
|
||||
</div>
|
||||
</el-col>
|
||||
<el-col>
|
||||
<div class="item yellow">
|
||||
<div class="sub-title">
|
||||
设备连接不稳定
|
||||
</div>
|
||||
<div class="content">
|
||||
A区b栋102 | 今天08:23
|
||||
</div>
|
||||
</div>
|
||||
</el-col>
|
||||
<el-col>
|
||||
<div class="item red">
|
||||
<div class="sub-title">
|
||||
异常移动检测
|
||||
</div>
|
||||
<div class="content">
|
||||
A区b栋102 | 今天08:23
|
||||
</div>
|
||||
</div>
|
||||
</el-col>
|
||||
</el-row>
|
||||
</el-col>
|
||||
</el-row>
|
||||
</el-card>
|
||||
</template>
|
||||
<style scoped>
|
||||
.title {
|
||||
font-family: "Alibaba-PuHuiTi-Bold";
|
||||
font-size: 20px;
|
||||
font-weight: 400;
|
||||
letter-spacing: 0px;
|
||||
line-height: 24px;
|
||||
color: rgb(0, 30, 59);
|
||||
text-align: left;
|
||||
vertical-align: top;
|
||||
margin-bottom: 20px;
|
||||
}
|
||||
|
||||
.status-card {
|
||||
|
||||
.item {
|
||||
background: rgba(245, 245, 245, 0.2);
|
||||
border: 1px solid rgba(230, 233, 238, 1);
|
||||
margin-bottom: 20px;
|
||||
border-radius: 15px;
|
||||
padding: 15px 30px;
|
||||
text-align: center;
|
||||
|
||||
.status {
|
||||
color: rgba(175, 175, 175, 1);
|
||||
font-size: 20px;
|
||||
margin-bottom: 10px;
|
||||
font-weight: 500;
|
||||
}
|
||||
|
||||
.count {
|
||||
font-size: 18px;
|
||||
font-weight: bold;
|
||||
text-align: center;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.alarm-card {
|
||||
.item {
|
||||
border: 1px solid #E6E9EE;
|
||||
border-radius: 10px;
|
||||
padding: 10px;
|
||||
margin-bottom: 10px;
|
||||
position: relative;
|
||||
padding-left: 20px;
|
||||
text-align: left;
|
||||
}
|
||||
|
||||
.red {
|
||||
::v-deep::before {
|
||||
position: absolute;
|
||||
content: '';
|
||||
background-color: rgba(227, 39, 39, 1);
|
||||
height: 100%;
|
||||
width: 7px;
|
||||
border-radius: 7px 0px 0px 7px;
|
||||
top: 0;
|
||||
left: 1px;
|
||||
}
|
||||
}
|
||||
|
||||
.yellow {
|
||||
::v-deep::before {
|
||||
position: absolute;
|
||||
content: '';
|
||||
background-color: rgba(255, 208, 35, 1);
|
||||
height: 100%;
|
||||
width: 7px;
|
||||
border-radius: 7px 0px 0px 7px;
|
||||
top: 0;
|
||||
left: 1px;
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
<script setup></script>
|
||||
320
src/views/securitySurveillance/components/spgl.vue
Normal file
@ -0,0 +1,320 @@
|
||||
<template>
|
||||
<el-card style="border-radius: 15px;">
|
||||
<div class="title-box">
|
||||
视频管理
|
||||
</div>
|
||||
<el-row class="cunchu">
|
||||
<el-col>
|
||||
<div class="subtitle">存储状态</div>
|
||||
</el-col>
|
||||
<el-col style="position: relative;">
|
||||
<div ref="chartRef" style="height: 220px;width: 100%;"></div>
|
||||
<div class="text">别担心,还有很多存储空间</div>
|
||||
</el-col>
|
||||
</el-row>
|
||||
<el-row>
|
||||
<el-col class="lxcc">
|
||||
<div class="top">
|
||||
<div class="subtitle">录像存储设置</div>
|
||||
<div class="edit">编辑</div>
|
||||
</div>
|
||||
<div class="content">
|
||||
<div class="item">
|
||||
<div class="title">
|
||||
存储模式
|
||||
</div>
|
||||
<div class="text">
|
||||
循环覆盖
|
||||
</div>
|
||||
</div>
|
||||
<div class="item">
|
||||
<div class="title">
|
||||
保留天数
|
||||
</div>
|
||||
<div class="text">
|
||||
30天
|
||||
</div>
|
||||
</div>
|
||||
<div class="item">
|
||||
<div class="title">
|
||||
录像质量
|
||||
</div>
|
||||
<div class="text">
|
||||
高清(1080P)
|
||||
</div>
|
||||
</div>
|
||||
<div class="item">
|
||||
<div class="title">
|
||||
备份记录
|
||||
</div>
|
||||
<div class="text">
|
||||
开启
|
||||
</div>
|
||||
</div>
|
||||
<div class="item">
|
||||
<div class="title">
|
||||
备份时间
|
||||
</div>
|
||||
<div class="text">
|
||||
每日02:00
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</el-col>
|
||||
</el-row>
|
||||
<el-row>
|
||||
<el-col>
|
||||
<el-row>
|
||||
<el-col>
|
||||
<div class="subtitle">历史视频查询</div>
|
||||
</el-col>
|
||||
</el-row>
|
||||
<el-row>
|
||||
<el-col :span="8">
|
||||
<el-select placeholder="全部摄像头">
|
||||
</el-select>
|
||||
</el-col>
|
||||
<el-col :span="12">
|
||||
<el-date-picker v-model="value1" type="daterange" range-separator="至" style="width: 100%;"
|
||||
start-placeholder="开始" end-placeholder="结束" :size="size" />
|
||||
</el-col>
|
||||
<el-col :span="4">
|
||||
<el-button type="primary">搜索</el-button>
|
||||
</el-col>
|
||||
</el-row>
|
||||
</el-col>
|
||||
<el-col>
|
||||
<el-row>
|
||||
<el-table :data="data" height="200px" max-height="200px">
|
||||
<el-table-column label="摄像头" prop="name" width="100">
|
||||
</el-table-column>
|
||||
<el-table-column label="日期" prop="date" width="120">
|
||||
</el-table-column>
|
||||
<el-table-column label="时长" prop="duration">
|
||||
</el-table-column>
|
||||
<el-table-column label="大小" prop="size">
|
||||
</el-table-column>
|
||||
<el-table-column label="操作" fixed="right" width="100">
|
||||
<template #default="scope">
|
||||
<div class="svg-icon">
|
||||
<img src="/assets/svg/play.svg" alt="">
|
||||
<img src="/assets/svg/download.svg" alt="">
|
||||
<img src="/assets/svg/delete.svg" alt=""></img>
|
||||
</div>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
<div class="pagination" v-if="activeTab !== 'record'">
|
||||
<el-pagination layout="prev, pager, next, jumper" :total="totalRecords"
|
||||
v-model:current-page="currentPage" v-model:page-size="pageSize" :page-sizes="[20, 50, 100]"
|
||||
@current-change="handlePageChange" @size-change="handleSizeChange"></el-pagination>
|
||||
</div>
|
||||
</el-row>
|
||||
</el-col>
|
||||
</el-row>
|
||||
</el-card>
|
||||
</template>
|
||||
<style scoped lang="scss">
|
||||
.title-box {
|
||||
font-family: "Alibaba-PuHuiTi-Bold";
|
||||
font-size: 20px;
|
||||
font-weight: 400;
|
||||
letter-spacing: 0px;
|
||||
line-height: 24px;
|
||||
color: rgba(0, 30, 59, 1);
|
||||
text-align: left;
|
||||
vertical-align: top;
|
||||
}
|
||||
|
||||
.subtitle {
|
||||
font-size: 16px;
|
||||
color: #001E3B;
|
||||
position: relative;
|
||||
margin: 10px 0;
|
||||
|
||||
::v-deep::before {
|
||||
position: absolute;
|
||||
width: 5px;
|
||||
height: 5px;
|
||||
content: '';
|
||||
border-radius: 50%;
|
||||
background-color: rgba(24, 109, 245, 1);
|
||||
top: 50%;
|
||||
left: -8px;
|
||||
transform: translateY(-50%);
|
||||
}
|
||||
}
|
||||
|
||||
.cunchu {
|
||||
.text {
|
||||
position: absolute;
|
||||
bottom: 60px;
|
||||
width: 100%;
|
||||
color: rgba(113, 128, 150, 1);
|
||||
font-size: 14px;
|
||||
text-align: center;
|
||||
}
|
||||
}
|
||||
|
||||
.lxcc {
|
||||
.top {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
|
||||
.edit {
|
||||
color: rgba(0, 30, 59, 1);
|
||||
font-size: 14px;
|
||||
cursor: pointer;
|
||||
}
|
||||
}
|
||||
|
||||
.content {
|
||||
background-color: #F2F8FC;
|
||||
border-radius: 10px;
|
||||
|
||||
.item {
|
||||
display: flex;
|
||||
border-bottom: 1px solid #E3EDFF;
|
||||
padding: 10px 0;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.title {
|
||||
width: 50%;
|
||||
}
|
||||
|
||||
.text {
|
||||
width: 50%;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.svg-icon {
|
||||
display: flex;
|
||||
justify-content: space-around;
|
||||
|
||||
img {
|
||||
width: 15px;
|
||||
height: 15px;
|
||||
display: block;
|
||||
cursor: pointer;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
<script setup>
|
||||
import { ref, onMounted } from 'vue';
|
||||
import * as echarts from 'echarts';
|
||||
const chartRef = ref(null);
|
||||
let myChart = null;
|
||||
const pageSize = ref(20);
|
||||
const totalRecords = ref(100);
|
||||
const initChart = () => {
|
||||
myChart = echarts.init(chartRef.value);
|
||||
var option = {
|
||||
// 调整图表整体位置,向上移动以减少底部空白
|
||||
// 添加首尾单位标识
|
||||
graphic: [
|
||||
// 起始单位 (0TB)
|
||||
{
|
||||
type: 'text',
|
||||
left: '24%',
|
||||
top: '50%', // 上移文本位置
|
||||
style: {
|
||||
text: '0TB',
|
||||
fontSize: 14,
|
||||
color: '#666'
|
||||
}
|
||||
},
|
||||
// 结束单位 (10TB)
|
||||
{
|
||||
type: 'text',
|
||||
right: '24%',
|
||||
top: '50%', // 上移文本位置
|
||||
style: {
|
||||
text: '10TB',
|
||||
fontSize: 14,
|
||||
color: '#666'
|
||||
}
|
||||
},
|
||||
// 中间显示当前值和百分比(换行显示)
|
||||
{
|
||||
type: 'text',
|
||||
left: 'center',
|
||||
top: '40%', // 调整到48%位置
|
||||
style: {
|
||||
text: '6.68TB\n48%',
|
||||
fontSize: 18,
|
||||
fontWeight: 'bold',
|
||||
textAlign: 'center',
|
||||
lineHeight: 20 // 增加行高以确保换行效果
|
||||
}
|
||||
}
|
||||
],
|
||||
series: [
|
||||
{
|
||||
type: 'gauge',
|
||||
radius: '85%', // 适当减小半径
|
||||
center: ['50%', '50%'], // 上移图表中心位置
|
||||
startAngle: 170, // 开始角度(左侧)
|
||||
endAngle: 10, // 结束角度(右侧)
|
||||
max: 10, // 最大值设置为10TB
|
||||
axisLine: {
|
||||
lineStyle: {
|
||||
width: 40, // 保持条的粗细
|
||||
color: [
|
||||
[0.67, '#4863FF'], // 当前值6.7TB对应67%
|
||||
[1, '#E5E7EB'] // 未用部分颜色
|
||||
]
|
||||
}
|
||||
},
|
||||
// 隐藏所有刻度相关元素
|
||||
axisTick: {
|
||||
show: false
|
||||
},
|
||||
splitLine: {
|
||||
show: false
|
||||
},
|
||||
axisLabel: {
|
||||
show: false
|
||||
},
|
||||
// 隐藏指针
|
||||
pointer: {
|
||||
show: false
|
||||
},
|
||||
// 隐藏默认详情
|
||||
detail: {
|
||||
show: false
|
||||
},
|
||||
// 当前值(6.7TB)
|
||||
data: [{ value: 6.7 }]
|
||||
}
|
||||
]
|
||||
};
|
||||
myChart.setOption(option);
|
||||
};
|
||||
|
||||
// 监听窗口大小变化,重新绘制图表
|
||||
const handleResize = () => {
|
||||
if (myChart) {
|
||||
myChart.resize();
|
||||
}
|
||||
};
|
||||
const data = computed(() => {
|
||||
return Array.from({ length: 10 }, (_, i) => ({
|
||||
name: `摄像头${i + 1}`,
|
||||
date: '25.03.12-10:00',
|
||||
duration: '4小时',
|
||||
size: '2.4GB'
|
||||
}));
|
||||
});
|
||||
onMounted(() => {
|
||||
initChart();
|
||||
window.addEventListener('resize', handleResize);
|
||||
});
|
||||
|
||||
// 组件卸载时移除事件监听
|
||||
onUnmounted(() => {
|
||||
window.removeEventListener('resize', handleResize);
|
||||
});
|
||||
</script>
|
||||
177
src/views/securitySurveillance/components/spjk.vue
Normal file
@ -0,0 +1,177 @@
|
||||
<template>
|
||||
<el-row style="height: 100%;">
|
||||
<el-card style="width: 100%;border-radius: 12px;height: 100%;">
|
||||
<div style="display: flex;width: 100%;justify-content: space-between;align-items: center;">
|
||||
<TitleComponent title="实时视频监控" subtitle="查看所有已完成的巡检记录,跟进巡检报告" />
|
||||
<span style="color: rgba(24, 109, 245, 1);display: flex;align-items: center; cursor: pointer;">
|
||||
<span>
|
||||
2025/06/30 12:00
|
||||
刷新数据
|
||||
</span>
|
||||
<el-icon>
|
||||
<Refresh />
|
||||
</el-icon>
|
||||
</span>
|
||||
</div>
|
||||
<div class="video-container">
|
||||
<el-row gutter="20">
|
||||
<!-- 扩展布局:左侧大视频 + 右侧小视频列 -->
|
||||
<template v-if="isExpanded">
|
||||
<!-- 左侧大视频(占 16 列) -->
|
||||
<el-col :span="16">
|
||||
<div class="item large" @click="() => { isExpanded = false; }">
|
||||
<img :src="videoList[activeIndex].url" alt="">
|
||||
<div class="title" v-if="isExpanded"
|
||||
style="display: flex;justify-content: space-between;">
|
||||
<div class="text">
|
||||
{{ videoList[activeIndex].name }}
|
||||
</div>
|
||||
<div class="tools">
|
||||
<img src="/assets/svg/huanyuan.svg" alt=""></img>
|
||||
<img src="/assets/svg/quanpin.svg" alt=""></img>
|
||||
<img src="/assets/svg/jietu.svg" alt="">
|
||||
</div>
|
||||
</div>
|
||||
<div class="title" v-else>{{ videoList[activeIndex].name }}</div>
|
||||
</div>
|
||||
</el-col>
|
||||
<!-- 右侧小视频列(占 8 列) -->
|
||||
<el-col :span="8">
|
||||
<el-row gutter="20">
|
||||
<el-col :span="24" v-for="i in 3" :key="i">
|
||||
<div class="item small" @click="() => {
|
||||
activeIndex = videoList.length - 3 + i - 1;
|
||||
}">
|
||||
<img :src="videoList[videoList.length - 3 + i - 1].url" alt="">
|
||||
<div class="title">{{ videoList[videoList.length - 3 + i - 1].name }}</div>
|
||||
</div>
|
||||
</el-col>
|
||||
</el-row>
|
||||
</el-col>
|
||||
</template>
|
||||
|
||||
<!-- 普通布局:所有视频均匀排列 -->
|
||||
<template v-else>
|
||||
<el-col :span="8" v-for="(item, index) in videoList" :key="index">
|
||||
<div class="item" @click="() => {
|
||||
activeIndex = index;
|
||||
isExpanded = true;
|
||||
}">
|
||||
<img :src="item.url" alt="">
|
||||
<div class="title">{{ item.name }}</div>
|
||||
</div>
|
||||
</el-col>
|
||||
|
||||
</template>
|
||||
</el-row>
|
||||
<el-row v-if="isExpanded">
|
||||
<div class="pagination" v-if="activeTab !== 'record'">
|
||||
<el-pagination layout="prev, pager, next, jumper, sizes" :total="totalRecords"
|
||||
v-model:current-page="currentPage" v-model:page-size="pageSize" :page-sizes="[20, 50, 100]"
|
||||
@current-change="handlePageChange" @size-change="handleSizeChange"></el-pagination>
|
||||
</div>
|
||||
</el-row>
|
||||
</div>
|
||||
</el-card>
|
||||
</el-row>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import { ref } from 'vue';
|
||||
import { Refresh } from '@element-plus/icons-vue';
|
||||
import TitleComponent from '@/components/TitleComponent';
|
||||
const activeIndex = ref(-1); // 初始无选中,选中后为对应索引
|
||||
const isExpanded = ref(false); // 初始为普通布局
|
||||
const pageSize = ref(20);
|
||||
const totalRecords = ref(100);
|
||||
const videoList = ref([
|
||||
{
|
||||
name: 'A区d厂',
|
||||
url: 'https://img.js.design/assets/img/68c144e8ba276a0e8a4a55c2.jpeg#bab7e2e06aae943525cacb13bd63e30d'
|
||||
},
|
||||
{
|
||||
name: 'A区d厂',
|
||||
url: 'https://img.js.design/assets/img/68c144efb5e8b987e5ca6462.jpeg#5523cf094b2f8c3a79ea4eb330c99a30'
|
||||
},
|
||||
{
|
||||
name: 'A区d厂',
|
||||
url: 'https://img.js.design/assets/img/68c144fbbad414f81995e90c.webp#230d8ca5ca39982518439db26e0ea899'
|
||||
},
|
||||
{
|
||||
name: 'A区d厂',
|
||||
url: 'https://img.js.design/assets/img/68c1450640d5d2a02e2540b2.webp#adad2379a0b04d6968364e4fb1133f77'
|
||||
},
|
||||
{
|
||||
name: 'A区d厂',
|
||||
url: 'https://img.js.design/assets/img/68c14543d56431f9d6f6808e.webp#16f0a0d8fab4f8ff3b39b04bfabac054'
|
||||
},
|
||||
{
|
||||
name: 'A区d厂',
|
||||
url: 'https://img.js.design/assets/img/68c14578d56431f9d6f68981.jpg#e77150417f28a971be4846eb0be90373'
|
||||
},
|
||||
{
|
||||
name: 'A区d厂',
|
||||
url: 'https://img.js.design/assets/img/68c145e03f22157da619a7ce.png#546ff44289a22bf175e1eca1f69cd8f9'
|
||||
},
|
||||
{
|
||||
name: 'A区d厂',
|
||||
url: 'https://img.js.design/assets/img/68c1461fb5e8b987e5caa293.jpeg#870e4d2b88b487ecb8f2f0b956c45c08'
|
||||
},
|
||||
{
|
||||
name: 'A区d厂',
|
||||
url: 'https://img.js.design/assets/img/68c1462dcbf9ed2271880b95.webp#ae7ae94ca84ce980e2d2281869335f06'
|
||||
}
|
||||
]);
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss">
|
||||
.video-container {
|
||||
|
||||
.item {
|
||||
height: 220px;
|
||||
margin-bottom: 20px;
|
||||
position: relative;
|
||||
border: 2px solid rgba(45, 119, 249, 1);
|
||||
cursor: pointer;
|
||||
|
||||
img {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
display: block;
|
||||
}
|
||||
|
||||
.title {
|
||||
position: absolute;
|
||||
padding: 5px 0;
|
||||
padding-left: 10px;
|
||||
font-size: 14px;
|
||||
border-radius: 8px 8px 0px 0px;
|
||||
background: linear-gradient(180deg, rgba(0, 0, 0, 0.73) 0%, rgba(0, 0, 0, 0.33) 100%);
|
||||
width: 100%;
|
||||
bottom: 0;
|
||||
color: #fff;
|
||||
}
|
||||
}
|
||||
|
||||
// 大视频样式(高度与右侧三个小视频总高度对齐,考虑间距)
|
||||
.large {
|
||||
height: calc(220px * 3 + 20px * 2); // 高度为3个小视频高度加上2个间距
|
||||
|
||||
.tools {
|
||||
display: flex;
|
||||
|
||||
img {
|
||||
width: 20px;
|
||||
height: 20px;
|
||||
display: block;
|
||||
margin: 0 10px;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 小视频样式(保持原高度,适配右侧单列)
|
||||
.small {
|
||||
height: 220px;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
156
src/views/securitySurveillance/components/top.vue
Normal file
58
src/views/securitySurveillance/index.vue
Normal file
@ -0,0 +1,58 @@
|
||||
<template>
|
||||
<div class="security-surveillance">
|
||||
<el-row style="display: flex;align-items: center;">
|
||||
<el-col :span="12">
|
||||
<TitleComponent title="安防监控管理" subtitle="实时监控、历史录像查询与视频管理" />
|
||||
</el-col>
|
||||
<!-- 关键:给内层 el-col 套上 el-row -->
|
||||
<el-col :span="12" style="text-align: right;">
|
||||
<el-row :gutter="16" justify="end"> <!-- gutter 可选,单位px,控制列间距 -->
|
||||
<el-col :span="6" :push="3">
|
||||
<el-input placeholder="搜索逆变器..." prefix-icon="search" />
|
||||
</el-col>
|
||||
<el-col :span="6" :push="3">
|
||||
<el-select placeholder="请选择逆变器状态">
|
||||
<el-option label="所有状态" value="0"></el-option>
|
||||
</el-select>
|
||||
</el-col>
|
||||
<el-col :span="6">
|
||||
<el-button type="primary">刷新数据<el-icon>
|
||||
<Refresh />
|
||||
</el-icon>
|
||||
</el-button>
|
||||
</el-col>
|
||||
</el-row> <!-- 闭合内层 el-row -->
|
||||
</el-col>
|
||||
</el-row>
|
||||
<el-row>
|
||||
<Top />
|
||||
</el-row>
|
||||
<el-row style="margin-top: 20px;" :gutter="25">
|
||||
<el-col :span="18">
|
||||
<Spjk />
|
||||
</el-col>
|
||||
<el-col :span="6">
|
||||
<Spgl />
|
||||
</el-col>
|
||||
</el-row>
|
||||
<el-row style="margin-top: 20px;">
|
||||
<el-col>
|
||||
<Sbzt />
|
||||
</el-col>
|
||||
</el-row>
|
||||
</div>
|
||||
|
||||
</template>
|
||||
<style scoped>
|
||||
.security-surveillance {
|
||||
padding: 20px;
|
||||
background-color: #F2F8FC;
|
||||
}
|
||||
</style>
|
||||
<script setup>
|
||||
import TitleComponent from "@/components/TitleComponent";
|
||||
import Top from "./components/top"
|
||||
import Spjk from "./components/spjk"
|
||||
import Spgl from "./components/spgl";
|
||||
import Sbzt from "./components/sbzt";
|
||||
</script>
|
||||
@ -129,12 +129,12 @@
|
||||
<el-dialog
|
||||
v-model="createTaskDialogVisible"
|
||||
title="新建报修任务"
|
||||
width="800px"
|
||||
width="900px"
|
||||
:before-close="handleCancelCreateTask"
|
||||
custom-class="beautiful-dialog"
|
||||
center
|
||||
>
|
||||
<el-form ref="createTaskFormRef" :model="createTaskForm" :rules="createTaskRules" label-width="100px" class="elegant-form">
|
||||
<el-form ref="createTaskFormRef" :model="createTaskForm" :rules="createTaskRules" label-width="120px" class="elegant-form">
|
||||
<el-form-item label="报修名称*" prop="repairName">
|
||||
<el-input v-model="createTaskForm.repairName" placeholder="简要描述报修内容" />
|
||||
</el-form-item>
|
||||
@ -143,10 +143,8 @@
|
||||
<el-col :span="12">
|
||||
<el-form-item label="报修类型*" prop="repairType">
|
||||
<el-select v-model="createTaskForm.repairType" placeholder="请选择类型">
|
||||
<el-option label="设备故障" value="device" />
|
||||
<el-option label="硬件故障" value="device" />
|
||||
<el-option label="软件故障" value="software" />
|
||||
<el-option label="网络故障" value="network" />
|
||||
<el-option label="环境问题" value="environment" />
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
@ -161,6 +159,12 @@
|
||||
</el-col>
|
||||
</el-row>
|
||||
|
||||
<el-form-item label="指派维修人*" prop="sendPerson">
|
||||
<el-select v-model="createTaskForm.sendPerson" placeholder="请选择维修人" :loading="loadingUsers">
|
||||
<el-option v-for="user in usersList" :key="user.id" :label="user.name" :value="user.id" />
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
|
||||
<el-form-item label="详细描述*" prop="detailedDescription">
|
||||
<el-input v-model="createTaskForm.detailedDescription" type="textarea" :rows="4" placeholder="详细描述故障现象、发生时间、位置等信息" />
|
||||
</el-form-item>
|
||||
@ -169,13 +173,31 @@
|
||||
<el-input v-model="createTaskForm.faultLocation" placeholder="例如:A区102" />
|
||||
</el-form-item>
|
||||
|
||||
<el-form-item label="上传图片(可选)">
|
||||
<div class="upload-container">
|
||||
<div class="upload-box">
|
||||
<i class="el-icon-plus avatar-uploader-icon"></i>
|
||||
<div class="upload-text">点击或拖拽图片至此处上传</div>
|
||||
<div class="upload-hint">支持JPG、PNG格式,最多3张</div>
|
||||
<el-form-item label="上传图片(可选)" width="100%">
|
||||
<file-upload v-model="createTaskForm.file" :fileType="['png', 'jpg', 'jpeg']">
|
||||
<div class="upload-container">
|
||||
<div class="upload-box">
|
||||
<i class="el-icon-plus avatar-uploader-icon"></i>
|
||||
<div class="upload-text">点击或拖拽图片至此处上传</div>
|
||||
<div class="upload-hint">支持JPG、PNG格式,最多3张</div>
|
||||
</div>
|
||||
</div>
|
||||
</file-upload>
|
||||
<!-- <el-upload
|
||||
class="avatar-uploader"
|
||||
:file-list="createTaskForm.fileList"
|
||||
:on-change="handleFileChange"
|
||||
:before-remove="beforeRemove"
|
||||
:on-remove="handleRemove"
|
||||
:auto-upload="false"
|
||||
multiple
|
||||
:limit="3"
|
||||
:on-exceed="handleExceed"
|
||||
>
|
||||
|
||||
</el-upload> -->
|
||||
<div v-if="createTaskForm.fileList && createTaskForm.fileList.length > 0" class="upload-tip">
|
||||
<span style="color: #1989fa">已选择{{ createTaskForm.fileList.length }}张图片,将在提交时上传</span>
|
||||
</div>
|
||||
</el-form-item>
|
||||
|
||||
@ -196,7 +218,7 @@
|
||||
<template #footer>
|
||||
<span class="dialog-footer">
|
||||
<el-button @click="handleCancelCreateTask">取消</el-button>
|
||||
<el-button type="primary" @click="handleSaveTask">保存计划</el-button>
|
||||
<el-button type="primary" @click="handleSaveTask">保存报修任务</el-button>
|
||||
</span>
|
||||
</template>
|
||||
</el-dialog>
|
||||
@ -205,10 +227,12 @@
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import { ref, computed } from 'vue';
|
||||
import { ref, computed, onMounted } from 'vue';
|
||||
import router from '@/router';
|
||||
import TitleComponent from './TitleComponent.vue';
|
||||
|
||||
import { baoxiulist, baoxiuDetail, delbaoxiu, updatebaoxiu, addbaoxiu, uploadbaoxiu } from '@/api/zhinengxunjian/baoxiou/index';
|
||||
import { xunjianUserlist } from '@/api/zhinengxunjian/xunjian';
|
||||
import { ElMessage } from 'element-plus';
|
||||
// 激活的选项卡
|
||||
const activeTab = ref('task');
|
||||
|
||||
@ -217,128 +241,165 @@ const taskStatus = ref('');
|
||||
const planType = ref('');
|
||||
const executor = ref('');
|
||||
|
||||
// 任务数据 - 恢复优先级标签样式和预计完成时间
|
||||
const tasks = ref([
|
||||
{
|
||||
title: '服务器A1电源故障',
|
||||
status: 'executing',
|
||||
statusText: '处理中',
|
||||
leftLineClass: 'left-line-high',
|
||||
priorityClass: 'priority-high', // 恢复优先级标签样式类
|
||||
priority: '高优先级',
|
||||
reportTime: '2025-06-16 08:30',
|
||||
reporter: '李明',
|
||||
maintainer: '张明',
|
||||
expectedCompleteTime: '2025-06-16 12:00', // 恢复预计完成时间
|
||||
actionText: '跟进',
|
||||
actionClass: 'follow-btn'
|
||||
},
|
||||
{
|
||||
title: '机房环境检查',
|
||||
status: 'pending',
|
||||
statusText: '待处理',
|
||||
leftLineClass: 'left-line-medium',
|
||||
priorityClass: 'priority-medium', // 恢复优先级标签样式类
|
||||
priority: '中优先级',
|
||||
reportTime: '2025-06-16 08:30',
|
||||
reporter: '张伟',
|
||||
maintainer: '未分配',
|
||||
expectedCompleteTime: '2025-06-16 18:00', // 恢复预计完成时间
|
||||
actionText: '分配',
|
||||
actionClass: 'assign-btn'
|
||||
},
|
||||
{
|
||||
title: '测试软件授权过期',
|
||||
status: 'executing',
|
||||
statusText: '处理中',
|
||||
leftLineClass: 'left-line-low',
|
||||
priorityClass: 'priority-low', // 恢复优先级标签样式类
|
||||
priority: '低优先级',
|
||||
reportTime: '2025-06-16 08:30',
|
||||
reporter: '李明',
|
||||
maintainer: '李阳',
|
||||
expectedCompleteTime: '2025-06-17 09:00', // 恢复预计完成时间
|
||||
actionText: '跟进',
|
||||
actionClass: 'follow-btn'
|
||||
},
|
||||
{
|
||||
title: '打印机卡纸故障',
|
||||
status: 'completed',
|
||||
statusText: '已完成',
|
||||
leftLineClass: 'left-line-completed',
|
||||
priorityClass: 'priority-low', // 恢复优先级标签样式类
|
||||
priority: '低优先级',
|
||||
reportTime: '2025-06-17 08:30',
|
||||
reporter: '李明',
|
||||
maintainer: '张明',
|
||||
expectedCompleteTime: '2025-06-17 10:00', // 恢复预计完成时间
|
||||
completeTime: '2025-06-17 09:15',
|
||||
actionText: '评价',
|
||||
actionClass: 'evaluate-btn'
|
||||
},
|
||||
{
|
||||
title: '服务器A1电源故障',
|
||||
status: 'executing',
|
||||
statusText: '处理中',
|
||||
leftLineClass: 'left-line-high',
|
||||
priorityClass: 'priority-high',
|
||||
priority: '高优先级',
|
||||
reportTime: '2025-06-16 08:30',
|
||||
reporter: '李明',
|
||||
maintainer: '张明',
|
||||
expectedCompleteTime: '2025-06-16 12:00',
|
||||
actionText: '跟进',
|
||||
actionClass: 'follow-btn'
|
||||
},
|
||||
{
|
||||
title: '机房环境检查',
|
||||
status: 'pending',
|
||||
statusText: '待处理',
|
||||
leftLineClass: 'left-line-medium',
|
||||
priorityClass: 'priority-medium',
|
||||
priority: '中优先级',
|
||||
reportTime: '2025-06-16 08:30',
|
||||
reporter: '张伟',
|
||||
maintainer: '未分配',
|
||||
expectedCompleteTime: '2025-06-16 18:00',
|
||||
actionText: '分配',
|
||||
actionClass: 'assign-btn'
|
||||
},
|
||||
{
|
||||
title: '测试软件授权过期',
|
||||
status: 'executing',
|
||||
statusText: '处理中',
|
||||
leftLineClass: 'left-line-low',
|
||||
priorityClass: 'priority-low',
|
||||
priority: '低优先级',
|
||||
reportTime: '2025-06-16 08:30',
|
||||
reporter: '李明',
|
||||
maintainer: '李阳',
|
||||
expectedCompleteTime: '2025-06-17 09:00',
|
||||
actionText: '跟进',
|
||||
actionClass: 'follow-btn'
|
||||
},
|
||||
{
|
||||
title: '打印机卡纸故障',
|
||||
status: 'completed',
|
||||
statusText: '已完成',
|
||||
leftLineClass: 'left-line-completed',
|
||||
priorityClass: 'priority-low',
|
||||
priority: '低优先级',
|
||||
reportTime: '2025-06-17 08:30',
|
||||
reporter: '李明',
|
||||
maintainer: '张明',
|
||||
expectedCompleteTime: '2025-06-17 10:00',
|
||||
completeTime: '2025-06-17 09:15',
|
||||
actionText: '评价',
|
||||
actionClass: 'evaluate-btn'
|
||||
}
|
||||
]);
|
||||
// 任务数据 - 初始为空数组
|
||||
const tasks = ref([]);
|
||||
|
||||
// 分页相关
|
||||
const currentPage = ref(1);
|
||||
const pageSize = ref(8);
|
||||
const total = ref(tasks.value.length);
|
||||
const total = ref(0);
|
||||
const loading = ref(false);
|
||||
|
||||
// 获取报修任务列表
|
||||
defineExpose({ getTaskList });
|
||||
async function getTaskList() {
|
||||
loading.value = true;
|
||||
try {
|
||||
const res = await baoxiulist({
|
||||
pageNum: currentPage.value,
|
||||
pageSize: pageSize.value,
|
||||
status: taskStatus.value,
|
||||
type: planType.value,
|
||||
executor: executor.value
|
||||
});
|
||||
|
||||
if (res.code === 200 && res.rows) {
|
||||
total.value = res.total || 0;
|
||||
// 将API返回的数据转换为前端显示所需的格式
|
||||
tasks.value = res.rows.map((item) => ({
|
||||
id: item.id,
|
||||
title: item.name || '未命名报修任务',
|
||||
status: mapStatusToKey(item.status),
|
||||
statusText: getStatusText(item.status),
|
||||
leftLineClass: getLeftLineClass(item.status, item.level),
|
||||
priorityClass: getPriorityClass(item.level),
|
||||
priority: getPriorityText(item.level),
|
||||
reportTime: formatDate(item.reportTime),
|
||||
reporter: item.reportName || '未知报修人',
|
||||
maintainer: item.sendPerson ? `维修人ID: ${item.sendPerson}` : '未分配',
|
||||
expectedCompleteTime: getExpectedCompleteTime(item.status),
|
||||
completeTime: item.completeTime ? formatDate(item.completeTime) : '',
|
||||
actionText: getActionText(item.status),
|
||||
actionClass: getActionClass(item.status),
|
||||
reportInfo: item.reportInfo,
|
||||
position: item.position,
|
||||
fileUrl: item.fileUrl
|
||||
}));
|
||||
} else {
|
||||
tasks.value = [];
|
||||
total.value = 0;
|
||||
console.error('获取报修任务列表失败:', res.msg);
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('获取报修任务列表异常:', error);
|
||||
tasks.value = [];
|
||||
total.value = 0;
|
||||
} finally {
|
||||
loading.value = false;
|
||||
}
|
||||
}
|
||||
|
||||
// 状态映射辅助函数
|
||||
function mapStatusToKey(status) {
|
||||
const statusMap = {
|
||||
'1': 'pending', // 待处理
|
||||
'2': 'executing', // 处理中
|
||||
'3': 'completed' // 已完成
|
||||
};
|
||||
return statusMap[status] || 'pending';
|
||||
}
|
||||
|
||||
// 获取状态文本
|
||||
function getStatusText(status) {
|
||||
const statusMap = {
|
||||
'1': '待处理',
|
||||
'2': '处理中',
|
||||
'3': '已完成'
|
||||
};
|
||||
return statusMap[status] || '未知状态';
|
||||
}
|
||||
|
||||
// 获取优先级文本
|
||||
function getPriorityText(level) {
|
||||
const levelMap = {
|
||||
'1': '低优先级',
|
||||
'2': '中优先级',
|
||||
'3': '高优先级'
|
||||
};
|
||||
return levelMap[level] || '普通优先级';
|
||||
}
|
||||
|
||||
// 获取优先级样式类
|
||||
function getPriorityClass(level) {
|
||||
const levelMap = {
|
||||
'1': 'priority-low',
|
||||
'2': 'priority-medium',
|
||||
'3': 'priority-high'
|
||||
};
|
||||
return levelMap[level] || 'priority-low';
|
||||
}
|
||||
|
||||
// 获取左侧状态线样式类
|
||||
function getLeftLineClass(status, level) {
|
||||
if (status === '3') return 'left-line-completed';
|
||||
|
||||
const levelMap = {
|
||||
'1': 'left-line-low',
|
||||
'2': 'left-line-medium',
|
||||
'3': 'left-line-high'
|
||||
};
|
||||
return levelMap[level] || 'left-line-low';
|
||||
}
|
||||
|
||||
// 获取操作按钮文本
|
||||
function getActionText(status) {
|
||||
const actionMap = {
|
||||
'1': '分配',
|
||||
'2': '跟进',
|
||||
'3': '评价'
|
||||
};
|
||||
return actionMap[status] || '查看';
|
||||
}
|
||||
|
||||
// 获取操作按钮样式类
|
||||
function getActionClass(status) {
|
||||
const actionMap = {
|
||||
'1': 'assign-btn',
|
||||
'2': 'follow-btn',
|
||||
'3': 'evaluate-btn'
|
||||
};
|
||||
return actionMap[status] || 'view-btn';
|
||||
}
|
||||
|
||||
// 获取预计完成时间(根据状态和优先级估算)
|
||||
function getExpectedCompleteTime(status) {
|
||||
if (status === '3') return ''; // 已完成任务不需要显示预计时间
|
||||
|
||||
const now = new Date();
|
||||
// 简单估算:待处理任务默认当天18:00前完成,处理中任务默认2小时内完成
|
||||
if (status === '1') {
|
||||
now.setHours(18, 0, 0, 0);
|
||||
} else {
|
||||
now.setHours(now.getHours() + 2);
|
||||
}
|
||||
return formatDate(now);
|
||||
}
|
||||
|
||||
// 格式化日期时间
|
||||
function formatDate(date) {
|
||||
if (!date) return '';
|
||||
|
||||
const d = new Date(date);
|
||||
if (isNaN(d.getTime())) return '';
|
||||
|
||||
const year = d.getFullYear();
|
||||
const month = String(d.getMonth() + 1).padStart(2, '0');
|
||||
const day = String(d.getDate()).padStart(2, '0');
|
||||
const hours = String(d.getHours()).padStart(2, '0');
|
||||
const minutes = String(d.getMinutes()).padStart(2, '0');
|
||||
|
||||
return `${year}-${month}-${day} ${hours}:${minutes}`;
|
||||
}
|
||||
|
||||
// 状态排序映射
|
||||
const statusOrder = {
|
||||
@ -363,20 +424,22 @@ const pagedTasks = computed(() => {
|
||||
// 搜索处理
|
||||
const handleSearch = () => {
|
||||
currentPage.value = 1; // 重置到第一页
|
||||
// 实际应用中这里会根据筛选条件过滤数据
|
||||
getTaskList(); // 调用接口获取数据
|
||||
};
|
||||
|
||||
// 创建报修任务弹窗相关
|
||||
const createTaskDialogVisible = ref(false);
|
||||
const createTaskFormRef = ref(null);
|
||||
const createTaskForm = ref({
|
||||
repairName: '',
|
||||
briefDescription: '',
|
||||
repairType: '',
|
||||
priority: '',
|
||||
detailedDescription: '',
|
||||
faultLocation: '',
|
||||
contactPerson: '',
|
||||
contactPhone: ''
|
||||
contactPhone: '',
|
||||
sendPerson: '', // 指派维修人
|
||||
file: '' // 上传的文件列表
|
||||
});
|
||||
|
||||
const createTaskRules = {
|
||||
@ -386,58 +449,303 @@ const createTaskRules = {
|
||||
detailedDescription: [{ required: true, message: '请输入详细描述', trigger: 'blur' }],
|
||||
faultLocation: [{ required: true, message: '请输入故障位置', trigger: 'blur' }],
|
||||
contactPerson: [{ required: true, message: '请输入联系人', trigger: 'blur' }],
|
||||
contactPhone: [{ required: true, message: '请输入联系电话', trigger: 'blur' }]
|
||||
contactPhone: [{ required: true, message: '请输入联系电话', trigger: 'blur' }],
|
||||
sendPerson: [{ required: true, message: '请选择维修人', trigger: 'change' }]
|
||||
};
|
||||
|
||||
// 用户列表(维修人)
|
||||
const usersList = ref([]);
|
||||
const loadingUsers = ref(false);
|
||||
|
||||
// 获取用户列表
|
||||
const getUsersList = async () => {
|
||||
loadingUsers.value = true;
|
||||
try {
|
||||
const res = await xunjianUserlist();
|
||||
// 根据接口返回格式,成功码是200,用户数据在rows数组中
|
||||
if (res.code === 200 && res.rows && Array.isArray(res.rows)) {
|
||||
// 映射用户数据,使用id作为value,userName作为显示名称
|
||||
usersList.value = res.rows.map((user) => ({
|
||||
id: user.id,
|
||||
name: user.userName
|
||||
}));
|
||||
} else {
|
||||
usersList.value = [];
|
||||
console.error('获取用户列表失败:', res.msg || '未知错误');
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('获取用户列表异常:', error);
|
||||
usersList.value = [];
|
||||
} finally {
|
||||
loadingUsers.value = false;
|
||||
}
|
||||
};
|
||||
const isSubmitting = ref(false); // 防止重复提交的状态标记
|
||||
const isUploading = ref(false); // 防止重复上传的状态标记
|
||||
// 上传文件方法
|
||||
const uploadFiles = async (files) => {
|
||||
// 防止重复上传
|
||||
if (isUploading.value) {
|
||||
ElMessage.warning('数据正在处理中,请稍候...');
|
||||
return [];
|
||||
}
|
||||
|
||||
try {
|
||||
isUploading.value = true;
|
||||
const formData = new FormData();
|
||||
|
||||
// 关键修复:将字段名从'files'改为'file',匹配后端要求的'file'字段
|
||||
files.forEach((file) => {
|
||||
formData.append('file', file.raw); // 这里将'files'改为'file'
|
||||
});
|
||||
|
||||
const res = await uploadbaoxiu(formData);
|
||||
|
||||
if (res.code === 200 && res.data && Array.isArray(res.data)) {
|
||||
return res.data.map((item) => ({
|
||||
fileId: item.ossId,
|
||||
fileUrl: item.url
|
||||
}));
|
||||
} else {
|
||||
console.error('文件上传失败:', res.msg);
|
||||
throw new Error(res.msg || '文件上传失败');
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('文件上传异常:', error);
|
||||
if (error.message.includes('重复提交')) {
|
||||
throw new Error('操作过于频繁,请稍后再试');
|
||||
}
|
||||
throw error;
|
||||
} finally {
|
||||
isUploading.value = false;
|
||||
}
|
||||
};
|
||||
|
||||
const handleFileChange = (file, fileList) => {
|
||||
// 只处理刚添加的文件
|
||||
if (file.status === 'ready') {
|
||||
// 验证文件格式和大小
|
||||
const isJPG = file.raw.type === 'image/jpeg' || file.raw.type === 'image/jpg';
|
||||
const isPNG = file.raw.type === 'image/png';
|
||||
const isLt2M = file.size / 1024 / 1024 < 2;
|
||||
|
||||
if (!isJPG && !isPNG) {
|
||||
ElMessage.error('上传图片只能是 JPG/JPEG 或 PNG 格式!');
|
||||
// 从文件列表中移除不符合要求的文件
|
||||
createTaskForm.value.fileList = fileList.filter((f) => f.uid !== file.uid);
|
||||
return;
|
||||
}
|
||||
|
||||
if (!isLt2M) {
|
||||
ElMessage.error('上传图片大小不能超过 2MB!');
|
||||
// 从文件列表中移除不符合要求的文件
|
||||
createTaskForm.value.fileList = fileList.filter((f) => f.uid !== file.uid);
|
||||
return;
|
||||
}
|
||||
|
||||
// 保存验证通过的文件到表单
|
||||
createTaskForm.value.fileList = fileList;
|
||||
}
|
||||
};
|
||||
const handleExceed = (files, fileList) => {
|
||||
ElMessage.warning(`当前限制选择 3 张图片,本次选择了 ${files.length} 张,共选择了 ${files.length + fileList.length} 张`);
|
||||
};
|
||||
|
||||
// 文件移除前的钩子
|
||||
const beforeRemove = (file, fileList) => {
|
||||
return window.confirm(`确定移除 ${file.name}?`);
|
||||
};
|
||||
|
||||
// 文件移除时的钩子
|
||||
const handleRemove = (file, fileList) => {
|
||||
createTaskForm.value.fileList = fileList;
|
||||
ElMessage.info(`已移除 ${file.name}`);
|
||||
};
|
||||
// 创建任务
|
||||
const handleCreateTask = () => {
|
||||
const handleCreateTask = async () => {
|
||||
createTaskDialogVisible.value = true;
|
||||
// 打开弹窗时获取用户列表
|
||||
await getUsersList();
|
||||
};
|
||||
|
||||
// 保存报修任务
|
||||
const handleSaveTask = () => {
|
||||
// 模拟保存报修任务逻辑
|
||||
console.log('保存报修任务:', createTaskForm.value);
|
||||
// 关闭弹窗
|
||||
createTaskDialogVisible.value = false;
|
||||
// 重置表单
|
||||
const handleSaveTask = async () => {
|
||||
console.log(createTaskForm.value.file);
|
||||
// 防止重复提交
|
||||
if (!createTaskFormRef.value || isSubmitting.value) return;
|
||||
|
||||
try {
|
||||
// 设置提交状态为true
|
||||
isSubmitting.value = true;
|
||||
|
||||
// 先验证表单
|
||||
await createTaskFormRef.value.validate();
|
||||
// 上传选中的文件
|
||||
let fileIds = [];
|
||||
let fileUrls = [];
|
||||
|
||||
if (createTaskForm.value.fileList && createTaskForm.value.fileList.length > 0) {
|
||||
ElMessage.info(`开始上传 ${createTaskForm.value.fileList.length} 张图片...`);
|
||||
const uploadResults = await uploadFiles(createTaskForm.value.fileList);
|
||||
|
||||
// 提取上传结果
|
||||
fileIds = uploadResults.map((result) => result.fileId);
|
||||
fileUrls = uploadResults.map((result) => result.fileUrl);
|
||||
|
||||
ElMessage.success(`图片上传成功,共 ${uploadResults.length} 张`);
|
||||
}
|
||||
|
||||
// 准备请求数据
|
||||
const requestData = {
|
||||
projectId: 1,
|
||||
name: createTaskForm.value.repairName,
|
||||
type: mapRepairType(createTaskForm.value.repairType),
|
||||
status: '1', // 默认为待处理状态
|
||||
level: mapPriorityLevel(createTaskForm.value.priority),
|
||||
sendPerson: parseInt(createTaskForm.value.sendPerson),
|
||||
reportInfo: createTaskForm.value.detailedDescription,
|
||||
position: createTaskForm.value.faultLocation,
|
||||
fileId: fileIds.join(','), // 用逗号分隔多个文件ID
|
||||
fileUrl: fileUrls.join(','), // 用逗号分隔多个文件URL
|
||||
reportName: createTaskForm.value.contactPerson,
|
||||
reportPhone: createTaskForm.value.contactPhone
|
||||
};
|
||||
|
||||
// 调用添加报修任务接口
|
||||
const res = await addbaoxiu(requestData);
|
||||
|
||||
// 检查接口返回是否成功(使用code=200作为成功标志)
|
||||
if (res.code === 200) {
|
||||
// 显示成功提示
|
||||
ElMessage.success('报修任务创建成功');
|
||||
|
||||
// 关闭弹窗
|
||||
createTaskDialogVisible.value = false;
|
||||
|
||||
// 重置表单
|
||||
resetCreateForm();
|
||||
|
||||
// 刷新任务列表
|
||||
await getTaskList();
|
||||
} else {
|
||||
ElMessage.error(`创建失败:${res.msg || '未知错误'}`);
|
||||
}
|
||||
} catch (error) {
|
||||
// 错误处理
|
||||
if (error instanceof Error) {
|
||||
ElMessage.error(`操作失败:${error.message}`);
|
||||
} else if (error === false) {
|
||||
// 表单验证失败,不做处理
|
||||
} else {
|
||||
ElMessage.error('操作失败:未知错误');
|
||||
}
|
||||
} finally {
|
||||
// 无论成功失败,都重置提交状态
|
||||
isSubmitting.value = false;
|
||||
}
|
||||
};
|
||||
|
||||
// 重置创建表单
|
||||
function resetCreateForm() {
|
||||
createTaskForm.value = {
|
||||
repairName: '',
|
||||
briefDescription: '',
|
||||
repairType: '',
|
||||
priority: '',
|
||||
detailedDescription: '',
|
||||
faultLocation: '',
|
||||
contactPerson: '',
|
||||
contactPhone: ''
|
||||
contactPhone: '',
|
||||
sendPerson: '',
|
||||
fileList: []
|
||||
};
|
||||
// 这里可以添加成功提示和刷新任务列表的逻辑
|
||||
};
|
||||
|
||||
if (createTaskFormRef.value) {
|
||||
createTaskFormRef.value.resetFields();
|
||||
}
|
||||
}
|
||||
|
||||
// 报修类型映射 - 1硬件2软件
|
||||
function mapRepairType(type) {
|
||||
const typeMap = {
|
||||
'device': '1', // 硬件
|
||||
'software': '2' // 软件
|
||||
};
|
||||
return typeMap[type] || '1';
|
||||
}
|
||||
|
||||
// 优先级映射 - 1低优先2中优先3高优先
|
||||
function mapPriorityLevel(priority) {
|
||||
const levelMap = {
|
||||
'low': '1', // 低优先
|
||||
'medium': '2', // 中优先
|
||||
'high': '3' // 高优先
|
||||
};
|
||||
return levelMap[priority] || '2';
|
||||
}
|
||||
|
||||
// 文件上传前的校验
|
||||
async function beforeUpload(file) {
|
||||
const isJPG = file.type === 'image/jpeg' || file.type === 'image/jpg';
|
||||
const isPNG = file.type === 'image/png';
|
||||
const isLt2M = file.size / 1024 / 1024 < 2;
|
||||
|
||||
if (!isJPG && !isPNG) {
|
||||
ElMessage.error('上传图片只能是 JPG/JPEG 或 PNG 格式!');
|
||||
return false;
|
||||
}
|
||||
if (!isLt2M) {
|
||||
ElMessage.error('上传图片大小不能超过 2MB!');
|
||||
return false;
|
||||
}
|
||||
|
||||
try {
|
||||
// 直接上传文件
|
||||
const uploadResult = await uploadFile(file);
|
||||
// 存储文件信息到表单
|
||||
createTaskForm.value.fileList = [
|
||||
{
|
||||
...file,
|
||||
fileId: uploadResult.fileId,
|
||||
fileUrl: uploadResult.fileUrl
|
||||
}
|
||||
];
|
||||
ElMessage.success('图片上传成功');
|
||||
} catch (error) {
|
||||
ElMessage.error('图片上传失败,请重试');
|
||||
}
|
||||
|
||||
// 阻止自动上传
|
||||
return false;
|
||||
}
|
||||
|
||||
// 文件上传成功处理
|
||||
function handleUploadSuccess(response, file, fileList) {
|
||||
// 这个函数实际上不会被调用,因为auto-upload=false
|
||||
// 真正的上传逻辑在beforeUpload函数中处理
|
||||
}
|
||||
|
||||
// 文件上传失败处理
|
||||
function handleUploadError(err, file, fileList) {
|
||||
ElMessage.error('上传失败,请稍后重试');
|
||||
}
|
||||
|
||||
// 取消创建报修任务
|
||||
const handleCancelCreateTask = () => {
|
||||
createTaskDialogVisible.value = false;
|
||||
// 重置表单
|
||||
createTaskForm.value = {
|
||||
repairName: '',
|
||||
briefDescription: '',
|
||||
repairType: '',
|
||||
priority: '',
|
||||
detailedDescription: '',
|
||||
faultLocation: '',
|
||||
contactPerson: '',
|
||||
contactPhone: ''
|
||||
};
|
||||
resetCreateForm();
|
||||
};
|
||||
|
||||
// 分页事件
|
||||
const handleSizeChange = (val) => {
|
||||
pageSize.value = val;
|
||||
currentPage.value = 1;
|
||||
getTaskList(); // 重新获取数据
|
||||
};
|
||||
|
||||
const handleCurrentChange = (val) => {
|
||||
currentPage.value = val;
|
||||
getTaskList(); // 重新获取数据
|
||||
};
|
||||
|
||||
// 查看任务详情
|
||||
@ -478,6 +786,12 @@ const handleInspection6 = () => {
|
||||
const handleInspection7 = () => {
|
||||
router.push('/rili/renyuanzhuangtai');
|
||||
};
|
||||
|
||||
// 组件挂载时获取数据
|
||||
onMounted(async () => {
|
||||
// 只获取任务列表,用户列表在弹窗打开时获取
|
||||
await getTaskList();
|
||||
});
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
@ -824,28 +1138,10 @@ const handleInspection7 = () => {
|
||||
flex-shrink: 0;
|
||||
}
|
||||
|
||||
.search-btn {
|
||||
background-color: #f2f3f5;
|
||||
color: #303133;
|
||||
border-color: #f2f3f5;
|
||||
transition: all 0.2s ease;
|
||||
}
|
||||
|
||||
.search-btn:hover {
|
||||
background-color: #e5e6eb;
|
||||
color: #303133;
|
||||
border-color: #e5e6eb;
|
||||
}
|
||||
|
||||
.search-btn,
|
||||
.create-btn {
|
||||
background-color: #165dff;
|
||||
border-color: #165dff;
|
||||
transition: all 0.2s ease;
|
||||
}
|
||||
|
||||
.create-btn:hover {
|
||||
background-color: #0e42d2;
|
||||
border-color: #0e42d2;
|
||||
height: 36px;
|
||||
border-radius: 4px;
|
||||
}
|
||||
|
||||
/* 任务卡片样式 - 恢复优先级标签背景色 */
|
||||
@ -1073,6 +1369,24 @@ const handleInspection7 = () => {
|
||||
color: #fff;
|
||||
}
|
||||
|
||||
.avatar-uploader .el-upload-list {
|
||||
margin-top: 12px;
|
||||
}
|
||||
|
||||
.avatar-uploader .el-upload-list__item {
|
||||
border-radius: 6px;
|
||||
margin-bottom: 8px;
|
||||
transition: all 0.2s;
|
||||
}
|
||||
|
||||
.avatar-uploader .el-upload-list__item:hover {
|
||||
transform: translateX(4px);
|
||||
}
|
||||
|
||||
.upload-tip {
|
||||
margin-top: 10px;
|
||||
font-size: 12px;
|
||||
}
|
||||
/* 响应式设计 */
|
||||
@media (max-width: 1200px) {
|
||||
.task-cards {
|
||||
|
||||
@ -11,12 +11,6 @@
|
||||
<div class="nav-tab" @click="handleInspection6">工单管理</div>
|
||||
<div class="nav-tab" @click="handleInspection7">运维组织</div>
|
||||
</div>
|
||||
|
||||
<!-- 标题栏 -->
|
||||
<div class="header">
|
||||
<TitleComponent title="运维待办事项" subtitle="管理每日、每周等的运维工作任务"></TitleComponent>
|
||||
</div>
|
||||
|
||||
<div class="main-content">
|
||||
<!-- 左侧日历区域 -->
|
||||
<div class="calendar-container">
|
||||
@ -25,8 +19,6 @@
|
||||
<div class="calendar-controls">
|
||||
<!-- 月份选择器 -->
|
||||
<el-date-picker v-model="currentDate" type="month" placeholder="选择月份" style="width: 120px; margin-right: 15px" />
|
||||
|
||||
<el-button type="primary">添加</el-button>
|
||||
<el-button type="primary" @click="goToToday">今日</el-button>
|
||||
<el-button type="text" icon="el-icon-plus"></el-button>
|
||||
</div>
|
||||
@ -39,7 +31,7 @@
|
||||
<div class="date-events">
|
||||
<div v-for="event in getDayEvents(data.day)" :key="event.id" class="event-item" :class="'event-' + event.type">
|
||||
<div class="event-title">{{ event.title }}</div>
|
||||
<div class="event-description">{{ event.description }}</div>
|
||||
<div class="event-describeValue">{{ event.describeValue }}</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@ -54,128 +46,48 @@
|
||||
<el-button type="primary" size="small" icon="el-icon-plus" @click="openAddTaskDialog">添加</el-button>
|
||||
</div>
|
||||
|
||||
<!-- 待办事项列表 -->
|
||||
<!-- 待办事项列表 - 动态渲染 -->
|
||||
<div class="todo-list">
|
||||
<!-- 待办项1 - 常规维护 -->
|
||||
<div class="todo-item">
|
||||
<div class="todo-color-indicator normal"></div>
|
||||
<el-checkbox class="todo-checkbox"></el-checkbox>
|
||||
<div
|
||||
v-for="item in todoListData"
|
||||
:key="item.id"
|
||||
class="todo-item"
|
||||
:class="{ 'important': item.taskLevel === '重要', 'completed': item.status === 2 }"
|
||||
>
|
||||
<div
|
||||
class="todo-color-indicator"
|
||||
:class="{
|
||||
normal: item.taskLevel === '常规项' && item.status !== 2,
|
||||
important: item.taskLevel === '重要' && item.status !== 2,
|
||||
urgent: item.taskLevel === '紧急' && item.status !== 2,
|
||||
completed: item.status === 2
|
||||
}"
|
||||
></div>
|
||||
<el-checkbox class="todo-checkbox" :checked="item.status === 2" @change="handleStatusChange(item, $event)"></el-checkbox>
|
||||
<div class="todo-content">
|
||||
<div class="todo-main">
|
||||
<div class="todo-title">服务器例行检查</div>
|
||||
<div class="todo-time">09:00-10:00 AM</div>
|
||||
<div class="todo-title">{{ item.title }}</div>
|
||||
<div v-if="item.workTimeRange1 || item.workTimeRange2" class="todo-time">
|
||||
{{ item.workTimeRange1 }}
|
||||
<span v-if="item.workTimeRange1 && item.workTimeRange2">——</span>
|
||||
{{ item.workTimeRange2 }}
|
||||
</div>
|
||||
</div>
|
||||
<div class="todo-description">检查所有生产服务器的CPU、内存、磁盘使用率,确保正常运行</div>
|
||||
<div class="todo-describeValue">{{ item.describeValue }}</div>
|
||||
</div>
|
||||
<div class="todo-actions">
|
||||
<button class="action-btn edit-btn" @click="handleEdit">
|
||||
<button class="action-btn edit-btn" @click="handleEdit(item.id)">
|
||||
<img src="@/assets/images/xiugai.png" alt="编辑" class="action-icon" />
|
||||
</button>
|
||||
<button class="action-btn delete-btn" @click="handleDelete">
|
||||
<button class="action-btn delete-btn" @click="handleDelete(item.id)">
|
||||
<img src="@/assets/images/shanchu.png" alt="删除" class="action-icon" />
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- 待办项2 - 重要 -->
|
||||
<div class="todo-item important">
|
||||
<div class="todo-color-indicator important"></div>
|
||||
<el-checkbox class="todo-checkbox"></el-checkbox>
|
||||
<div class="todo-content">
|
||||
<div class="todo-main">
|
||||
<div class="todo-title">数据库备份</div>
|
||||
<div class="todo-time">14:00-15:00 PM</div>
|
||||
</div>
|
||||
<div class="todo-description">主要数据库全备份,并验证备份文件完整性</div>
|
||||
</div>
|
||||
<div class="todo-actions">
|
||||
<button class="action-btn edit-btn" @click="handleEdit">
|
||||
<img src="@/assets/images/xiugai.png" alt="编辑" class="action-icon" />
|
||||
</button>
|
||||
<button class="action-btn delete-btn" @click="handleDelete">
|
||||
<img src="@/assets/images/shanchu.png" alt="删除" class="action-icon" />
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- 待办项3 - 紧急 -->
|
||||
<div class="todo-item">
|
||||
<div class="todo-color-indicator urgent"></div>
|
||||
<el-checkbox class="todo-checkbox"></el-checkbox>
|
||||
<div class="todo-content">
|
||||
<div class="todo-main">
|
||||
<div class="todo-title">网络设备固件更新</div>
|
||||
<div class="todo-time">18:00-20:00 PM</div>
|
||||
</div>
|
||||
<div class="todo-description">更新核心交换机和防火墙固件,需安排在业务低峰期</div>
|
||||
</div>
|
||||
<div class="todo-actions">
|
||||
<button class="action-btn edit-btn" @click="handleEdit">
|
||||
<img src="@/assets/images/xiugai.png" alt="编辑" class="action-icon" />
|
||||
</button>
|
||||
<button class="action-btn delete-btn" @click="handleDelete">
|
||||
<img src="@/assets/images/shanchu.png" alt="删除" class="action-icon" />
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- 待办项4 - 常规维护 -->
|
||||
<div class="todo-item">
|
||||
<div class="todo-color-indicator normal"></div>
|
||||
<el-checkbox class="todo-checkbox"></el-checkbox>
|
||||
<div class="todo-content">
|
||||
<div class="todo-main">
|
||||
<div class="todo-title">服务器例行检查</div>
|
||||
<div class="todo-time">08:00-09:00 AM</div>
|
||||
</div>
|
||||
<div class="todo-description">检查所有生产服务器的CPU、内存、磁盘使用率,确保正常运行</div>
|
||||
</div>
|
||||
<div class="todo-actions">
|
||||
<button class="action-btn edit-btn" @click="handleEdit">
|
||||
<img src="@/assets/images/xiugai.png" alt="编辑" class="action-icon" />
|
||||
</button>
|
||||
<button class="action-btn delete-btn" @click="handleDelete">
|
||||
<img src="@/assets/images/shanchu.png" alt="删除" class="action-icon" />
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
<div class="todo-item">
|
||||
<div class="todo-color-indicator normal"></div>
|
||||
<el-checkbox class="todo-checkbox"></el-checkbox>
|
||||
<div class="todo-content">
|
||||
<div class="todo-main">
|
||||
<div class="todo-title">服务器例行检查</div>
|
||||
<div class="todo-time">06:00-07:00 AM</div>
|
||||
</div>
|
||||
<div class="todo-description">检查所有生产服务器的CPU、内存、磁盘使用率,确保正常运行</div>
|
||||
</div>
|
||||
<div class="todo-actions">
|
||||
<button class="action-btn edit-btn" @click="handleEdit">
|
||||
<img src="@/assets/images/xiugai.png" alt="编辑" class="action-icon" />
|
||||
</button>
|
||||
<button class="action-btn delete-btn" @click="handleDelete">
|
||||
<img src="@/assets/images/shanchu.png" alt="删除" class="action-icon" />
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
<div class="todo-item">
|
||||
<div class="todo-color-indicator normal"></div>
|
||||
<el-checkbox class="todo-checkbox"></el-checkbox>
|
||||
<div class="todo-content">
|
||||
<div class="todo-main">
|
||||
<div class="todo-title">服务器例行检查</div>
|
||||
<div class="todo-time">06:00-07:00 AM</div>
|
||||
</div>
|
||||
<div class="todo-description">检查所有生产服务器的CPU、内存、磁盘使用率,确保正常运行</div>
|
||||
</div>
|
||||
<div class="todo-actions">
|
||||
<button class="action-btn edit-btn" @click="handleEdit">
|
||||
<img src="@/assets/images/xiugai.png" alt="编辑" class="action-icon" />
|
||||
</button>
|
||||
<button class="action-btn delete-btn" @click="handleDelete">
|
||||
<img src="@/assets/images/shanchu.png" alt="删除" class="action-icon" />
|
||||
</button>
|
||||
</div>
|
||||
<!-- 无数据时显示 -->
|
||||
<div v-if="todoListData.length === 0" class="empty-todo">
|
||||
<p>暂无待办事项</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@ -187,13 +99,19 @@
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<el-dialog v-model="dialogVisible" title="新增任务" width="480px" class="custom-dialog" :before-close="closeDialog">
|
||||
<el-dialog
|
||||
v-model="dialogVisible"
|
||||
:title="editingTaskId ? '编辑任务' : '新增任务'"
|
||||
width="480px"
|
||||
class="custom-dialog"
|
||||
:before-close="closeDialog"
|
||||
>
|
||||
<el-form :model="taskForm" label-width="80px" class="task-form">
|
||||
<el-form-item label="任务名称" prop="name">
|
||||
<el-input v-model="taskForm.name" placeholder="输入任务名称" class="form-input"></el-input>
|
||||
</el-form-item>
|
||||
<el-form-item label="任务描述" prop="description">
|
||||
<el-input v-model="taskForm.description" placeholder="输入任务描述" class="form-input"></el-input>
|
||||
<el-form-item label="任务描述" prop="describeValue">
|
||||
<el-input v-model="taskForm.describeValue" placeholder="输入任务描述" class="form-input"></el-input>
|
||||
</el-form-item>
|
||||
<el-form-item label="时间" prop="timeRange">
|
||||
<el-date-picker
|
||||
@ -201,12 +119,13 @@
|
||||
type="datetimerange"
|
||||
start-placeholder="开始时间"
|
||||
end-placeholder="结束时间"
|
||||
:disabled-date="() => false"
|
||||
class="form-input"
|
||||
style="width: 100%"
|
||||
/>
|
||||
</el-form-item>
|
||||
<el-form-item label="优先级" prop="priority">
|
||||
<el-select v-model="taskForm.priority" placeholder="选择优先级" class="form-input">
|
||||
<el-form-item label="优先级" prop="taskLevel">
|
||||
<el-select v-model="taskForm.taskLevel" placeholder="选择优先级" class="form-input">
|
||||
<el-option label="常规项" value="常规项"></el-option>
|
||||
<el-option label="重要" value="重要"></el-option>
|
||||
<el-option label="紧急" value="紧急"></el-option>
|
||||
@ -214,12 +133,37 @@
|
||||
</el-form-item>
|
||||
<el-form-item label="任务类型" prop="taskType">
|
||||
<el-select v-model="taskForm.taskType" placeholder="选择任务类型" class="form-input">
|
||||
<el-option label="常规维护" value="常规维护"></el-option>
|
||||
<el-option label="安全巡检" value="安全巡检"></el-option>
|
||||
<el-option label="系统升级" value="系统升级"></el-option>
|
||||
<el-option label="数据备份" value="数据备份"></el-option>
|
||||
<el-option label="常规维护" value="1"></el-option>
|
||||
<el-option label="安全巡检" value="2"></el-option>
|
||||
<el-option label="系统升级" value="3"></el-option>
|
||||
<el-option label="数据备份" value="4"></el-option>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<!-- 新增:工作时间段选择器 -->
|
||||
<el-form-item label="开始时间" prop="workTimeRange1">
|
||||
<el-time-picker
|
||||
v-model="taskForm.workTimeRange1"
|
||||
type="timerange"
|
||||
start-placeholder="开始时间"
|
||||
end-placeholder="结束时间"
|
||||
format="HH:mm"
|
||||
value-format="HH:mm"
|
||||
class="form-input"
|
||||
style="width: 100%"
|
||||
/>
|
||||
</el-form-item>
|
||||
<el-form-item label="结束时间" prop="workTimeRange2">
|
||||
<el-time-picker
|
||||
v-model="taskForm.workTimeRange2"
|
||||
type="timerange"
|
||||
start-placeholder="开始时间"
|
||||
end-placeholder="结束时间"
|
||||
format="HH:mm"
|
||||
value-format="HH:mm"
|
||||
class="form-input"
|
||||
style="width: 100%"
|
||||
/>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
<template #footer>
|
||||
<el-button @click="closeDialog">取消</el-button>
|
||||
@ -231,9 +175,9 @@
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import { ref, computed, watch } from 'vue';
|
||||
import { ref, computed, watch, onMounted } from 'vue';
|
||||
import router from '@/router';
|
||||
import TitleComponent from './TitleComponent.vue';
|
||||
import { daibanlist, adddaiban, updatedaiban, deldaiban } from '@/api/zhinengxunjian/daiban/index';
|
||||
|
||||
// 默认显示当前月份
|
||||
const currentDate = ref(new Date());
|
||||
@ -244,46 +188,144 @@ const years = ref([]);
|
||||
const selectedYear = ref(currentDate.value.getFullYear());
|
||||
const selectedMonth = ref(currentDate.value.getMonth() + 1);
|
||||
|
||||
// 减少月份
|
||||
const decreaseMonth = () => {
|
||||
const date = new Date(currentDate.value);
|
||||
date.setMonth(date.getMonth() - 1);
|
||||
currentDate.value = date;
|
||||
updateYearAndMonth();
|
||||
};
|
||||
|
||||
// 增加月份
|
||||
const increaseMonth = () => {
|
||||
const date = new Date(currentDate.value);
|
||||
date.setMonth(date.getMonth() + 1);
|
||||
currentDate.value = date;
|
||||
updateYearAndMonth();
|
||||
};
|
||||
|
||||
// 回到今天
|
||||
const goToToday = () => {
|
||||
currentDate.value = new Date();
|
||||
updateYearAndMonth();
|
||||
};
|
||||
|
||||
// 日历事件数据 - 2025年9月的随机事件
|
||||
const calendarEvents = ref([
|
||||
// 服务维护事件
|
||||
{ id: 1, date: '2025-09-11', title: '服务维护', description: '维护公司内部服务器', type: 'service' },
|
||||
{ id: 2, date: '2025-09-28', title: '服务维护', description: '先所有旧服务器部署新内存', type: 'service' },
|
||||
// 根据workTimeRange1和workTimeRange2生成taskTimeInfo字符串
|
||||
const getTaskTimeInfoString = () => {
|
||||
const timeInfoArray = [];
|
||||
|
||||
// 数据库管理事件
|
||||
{ id: 3, date: '2025-09-21', title: '数据库管理', description: '定期执行数据库优化', type: 'database' },
|
||||
{ id: 4, date: '2025-09-30', title: '数据库管理', description: '大型数据库备份策略', type: 'database' },
|
||||
// 处理工作时间段1 - 更宽松的类型处理
|
||||
if (taskForm.value.workTimeRange1) {
|
||||
if (Array.isArray(taskForm.value.workTimeRange1)) {
|
||||
// 如果是数组,直接拼接
|
||||
timeInfoArray.push(taskForm.value.workTimeRange1.join('-'));
|
||||
} else if (typeof taskForm.value.workTimeRange1 === 'string') {
|
||||
// 如果已经是字符串,直接使用
|
||||
timeInfoArray.push(taskForm.value.workTimeRange1);
|
||||
}
|
||||
}
|
||||
|
||||
// 网络维护事件
|
||||
{ id: 5, date: '2025-09-05', title: '网络维护', description: '网络设备例行检查', type: 'network' },
|
||||
{ id: 6, date: '2025-09-15', title: '网络维护', description: '更新网络安全策略', type: 'network' },
|
||||
// 处理工作时间段2 - 更宽松的类型处理
|
||||
if (taskForm.value.workTimeRange2) {
|
||||
if (Array.isArray(taskForm.value.workTimeRange2)) {
|
||||
// 如果是数组,直接拼接
|
||||
timeInfoArray.push(taskForm.value.workTimeRange2.join('-'));
|
||||
} else if (typeof taskForm.value.workTimeRange2 === 'string') {
|
||||
// 如果已经是字符串,直接使用
|
||||
timeInfoArray.push(taskForm.value.workTimeRange2);
|
||||
}
|
||||
}
|
||||
|
||||
// 系统升级事件
|
||||
{ id: 7, date: '2025-09-18', title: '系统升级', description: '核心系统版本升级', type: 'upgrade' },
|
||||
{ id: 8, date: '2025-09-25', title: '系统升级', description: '应用服务升级部署', type: 'upgrade' }
|
||||
]);
|
||||
// 合并多个时间段为一个字符串,用逗号分隔
|
||||
return timeInfoArray.join(',');
|
||||
};
|
||||
|
||||
// 待办事项数据 - 从接口获取
|
||||
const todoListData = ref([]);
|
||||
const calendarEvents = ref([]);
|
||||
|
||||
// 格式化日期为YYYY-MM-DD格式
|
||||
const formatDate = (date) => {
|
||||
if (!date) return '';
|
||||
const d = new Date(date);
|
||||
const year = d.getFullYear();
|
||||
const month = String(d.getMonth() + 1).padStart(2, '0');
|
||||
const day = String(d.getDate()).padStart(2, '0');
|
||||
return `${year}-${month}-${day}`;
|
||||
};
|
||||
|
||||
// 格式化时间范围
|
||||
const formatTimeRange = (startTime, endTime) => {
|
||||
if (!startTime || !endTime) return '';
|
||||
const start = new Date(startTime);
|
||||
const end = new Date(endTime);
|
||||
const formatHourMinute = (date) => {
|
||||
const hours = String(date.getHours()).padStart(2, '0');
|
||||
const minutes = String(date.getMinutes()).padStart(2, '0');
|
||||
return `${hours}:${minutes}`;
|
||||
};
|
||||
return `${formatHourMinute(start)}-${formatHourMinute(end)}`;
|
||||
};
|
||||
|
||||
// 从接口获取数据并处理 - 根据实际返回格式修正版
|
||||
const fetchData = async () => {
|
||||
try {
|
||||
const response = await daibanlist();
|
||||
console.log('接口原始返回:', response); // 打印原始响应,便于调试
|
||||
|
||||
// 初始化数据数组
|
||||
let data = [];
|
||||
|
||||
// 根据实际返回格式提取数据,数据在response.rows中
|
||||
if (response && Array.isArray(response.rows)) {
|
||||
data = response.rows;
|
||||
} else if (response.data && Array.isArray(response.data.rows)) {
|
||||
// 兼容可能的嵌套结构
|
||||
data = response.data.rows;
|
||||
} else {
|
||||
console.warn('接口返回格式不符合预期,使用空数组', response);
|
||||
data = [];
|
||||
}
|
||||
|
||||
// 处理待办列表数据
|
||||
todoListData.value = data.map((item) => ({
|
||||
id: item.id,
|
||||
title: item.taskName,
|
||||
describeValue: item.describeValue,
|
||||
timeRange: formatTimeRange(item.taskBeginTime, item.taskEndTime),
|
||||
// 保存原始时间用于编辑
|
||||
originalTimeRange: [new Date(item.taskBeginTime), new Date(item.taskEndTime)],
|
||||
taskLevel: item.taskLevel === '1' ? '常规项' : item.taskLevel === '2' ? '紧急' : '重要',
|
||||
// 注意:根据返回数据调整了taskLevel映射,原代码可能颠倒了重要和紧急
|
||||
taskType: item.taskType,
|
||||
// 从taskTimeInfo获取时间段数据,格式为"17:00,20:00"
|
||||
workTimeRange1: item.taskTimeInfo ? item.taskTimeInfo.split(',')[0] || '' : '',
|
||||
workTimeRange2: item.taskTimeInfo && item.taskTimeInfo.split(',').length > 1 ? item.taskTimeInfo.split(',')[1] : '',
|
||||
date: formatDate(item.taskBeginTime),
|
||||
status: item.status || 1 // 添加状态字段,默认1表示未完成
|
||||
}));
|
||||
|
||||
// 确保每个项目都有status字段
|
||||
todoListData.value.forEach((item) => {
|
||||
if (item.status === undefined) {
|
||||
item.status = 1; // 默认未完成
|
||||
}
|
||||
});
|
||||
|
||||
// 处理日历事件数据
|
||||
calendarEvents.value = data.map((item) => ({
|
||||
id: item.id,
|
||||
date: formatDate(item.taskBeginTime),
|
||||
title: item.taskName,
|
||||
describeValue: item.describeValue,
|
||||
type: getEventType(item.taskType),
|
||||
status: item.status // 添加状态信息
|
||||
}));
|
||||
|
||||
console.log('数据处理完成,共', data.length, '条记录');
|
||||
} catch (error) {
|
||||
console.error('获取待办数据失败:', error);
|
||||
// 出错时确保数据是数组,避免页面报错
|
||||
todoListData.value = [];
|
||||
calendarEvents.value = [];
|
||||
}
|
||||
};
|
||||
|
||||
// 根据任务类型获取事件类型
|
||||
const getEventType = (taskType) => {
|
||||
// 任务类型映射: 1-常规维护, 2-安全巡检, 3-系统升级, 4-数据备份
|
||||
const typeMap = {
|
||||
'1': 'service', // 常规维护对应service
|
||||
'2': 'database', // 安全巡检对应database
|
||||
'3': 'upgrade', // 系统升级对应upgrade
|
||||
'4': 'network' // 数据备份对应network
|
||||
};
|
||||
return typeMap[taskType] || 'service';
|
||||
};
|
||||
|
||||
// 获取指定日期的事件
|
||||
const getDayEvents = (dateStr) => {
|
||||
@ -315,18 +357,39 @@ watch(currentDate, (newDate) => {
|
||||
// 初始化年份和月份
|
||||
updateYearAndMonth();
|
||||
|
||||
// 组件挂载时获取数据
|
||||
onMounted(() => {
|
||||
fetchData();
|
||||
});
|
||||
|
||||
// 弹窗相关状态管理
|
||||
const dialogVisible = ref(false);
|
||||
const taskForm = ref({
|
||||
name: '',
|
||||
description: '',
|
||||
timeRange: '',
|
||||
priority: '常规项',
|
||||
taskType: '常规维护'
|
||||
describeValue: '',
|
||||
timeRange: null,
|
||||
taskLevel: '常规项',
|
||||
taskType: '1', // 默认值为1(常规维护)
|
||||
workTimeRange1: null, // 工作时间段1
|
||||
workTimeRange2: null // 工作时间段2
|
||||
});
|
||||
|
||||
// 当前编辑的任务ID,为null表示新建模式
|
||||
const editingTaskId = ref(null);
|
||||
|
||||
// 打开添加任务弹窗
|
||||
const openAddTaskDialog = () => {
|
||||
// 重置表单为新建状态
|
||||
editingTaskId.value = null;
|
||||
taskForm.value = {
|
||||
name: '',
|
||||
describeValue: '',
|
||||
timeRange: null,
|
||||
taskLevel: '常规项',
|
||||
taskType: '1',
|
||||
workTimeRange1: null,
|
||||
workTimeRange2: null
|
||||
};
|
||||
dialogVisible.value = true;
|
||||
};
|
||||
|
||||
@ -336,30 +399,164 @@ const closeDialog = () => {
|
||||
};
|
||||
|
||||
// 保存任务
|
||||
const saveTask = () => {
|
||||
// 这里可以添加表单验证和保存逻辑
|
||||
console.log('保存任务:', taskForm.value);
|
||||
// 重置表单
|
||||
taskForm.value = {
|
||||
name: '',
|
||||
description: '',
|
||||
timeRange: '',
|
||||
priority: '常规项',
|
||||
taskType: '常规维护'
|
||||
};
|
||||
// 关闭弹窗
|
||||
closeDialog();
|
||||
const saveTask = async () => {
|
||||
// 表单验证
|
||||
if (!taskForm.value.name || !taskForm.value.describeValue || !taskForm.value.timeRange) {
|
||||
// 使用Element Plus的消息提示
|
||||
ElMessage.warning('请填写必要的任务信息');
|
||||
return;
|
||||
}
|
||||
|
||||
// 验证工作时间段
|
||||
if (!taskForm.value.workTimeRange1 && !taskForm.value.workTimeRange2) {
|
||||
ElMessage.warning('请至少填写一个工作时间段');
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
// 构建接口所需的数据结构
|
||||
const apiData = {
|
||||
createDept: 0, // 根据实际情况设置
|
||||
createBy: 0, // 根据实际情况设置
|
||||
createTime: new Date().toISOString(),
|
||||
updateBy: 0, // 根据实际情况设置
|
||||
updateTime: new Date().toISOString(),
|
||||
params: {
|
||||
property1: 'string',
|
||||
property2: 'string'
|
||||
},
|
||||
|
||||
projectId: 0, // 根据实际情况设置
|
||||
taskName: taskForm.value.name,
|
||||
describeValue: taskForm.value.describeValue,
|
||||
taskBeginTime: taskForm.value.timeRange[0].toISOString(),
|
||||
taskEndTime: taskForm.value.timeRange[1].toISOString(),
|
||||
// 使用taskTimeInfo替代workTimeRange1和workTimeRange2,通过字符串拼接开始和结束时间
|
||||
taskTimeInfo: getTaskTimeInfoString(),
|
||||
taskLevel: taskForm.value.taskLevel === '常规项' ? '1' : taskForm.value.taskLevel === '重要' ? '3' : '2',
|
||||
taskType: taskForm.value.taskType
|
||||
};
|
||||
|
||||
let response;
|
||||
// 判断是新增还是编辑
|
||||
if (editingTaskId.value) {
|
||||
// 编辑操作 - 修改参数传递方式,将id合并到apiData中
|
||||
response = await updatedaiban({ ...apiData, id: editingTaskId.value });
|
||||
ElMessage.success('任务更新成功');
|
||||
} else {
|
||||
// 新增操作
|
||||
response = await adddaiban(apiData);
|
||||
console.log('保存任务成功:', response);
|
||||
ElMessage.success('任务添加成功');
|
||||
}
|
||||
|
||||
// 重新从接口获取最新数据,确保列表数据与后端保持一致
|
||||
await fetchData();
|
||||
|
||||
// 重置表单
|
||||
taskForm.value = {
|
||||
name: '',
|
||||
describeValue: '',
|
||||
timeRange: null,
|
||||
taskLevel: '常规项',
|
||||
taskType: '1',
|
||||
workTimeRange1: null,
|
||||
workTimeRange2: null
|
||||
};
|
||||
|
||||
// 重置编辑状态
|
||||
editingTaskId.value = null;
|
||||
|
||||
// 关闭弹窗
|
||||
closeDialog();
|
||||
} catch (error) {
|
||||
console.error('保存任务失败:', error);
|
||||
ElMessage.error('保存任务失败,请重试');
|
||||
}
|
||||
};
|
||||
|
||||
// 处理状态变更
|
||||
const handleStatusChange = async (item, checked) => {
|
||||
try {
|
||||
// 更新本地状态
|
||||
item.status = checked ? 2 : 1;
|
||||
|
||||
// 直接更新相关的日历事件以反映状态变化
|
||||
const calendarEvent = calendarEvents.value.find((event) => event.id === item.id);
|
||||
if (calendarEvent) {
|
||||
calendarEvent.status = item.status;
|
||||
}
|
||||
|
||||
// 这里可以添加API调用,更新后端状态
|
||||
// await updateTaskStatus(item.id, item.status);
|
||||
|
||||
console.log('任务状态已更新:', item.id, '状态:', item.status);
|
||||
} catch (error) {
|
||||
console.error('更新任务状态失败:', error);
|
||||
ElMessage.error('更新任务状态失败,请重试');
|
||||
// 恢复原始状态
|
||||
item.status = checked ? 1 : 2;
|
||||
}
|
||||
};
|
||||
|
||||
// 编辑和删除处理函数
|
||||
const handleEdit = () => {
|
||||
console.log('执行编辑操作');
|
||||
// 保留原有编辑逻辑
|
||||
};
|
||||
const handleEdit = (id) => {
|
||||
console.log('执行编辑操作:', id);
|
||||
// 找到对应的数据项
|
||||
const item = todoListData.value.find((item) => item.id === id);
|
||||
if (item) {
|
||||
// 存储编辑的任务ID
|
||||
editingTaskId.value = id;
|
||||
// 填充表单数据,使用原始时间范围
|
||||
// 处理工作时间段格式:如果是字符串格式(如"HH:mm-HH:mm"),则转换为数组格式
|
||||
let workTimeRange1 = item.workTimeRange1;
|
||||
let workTimeRange2 = item.workTimeRange2;
|
||||
|
||||
const handleDelete = () => {
|
||||
console.log('执行删除操作');
|
||||
// 保留原有删除逻辑
|
||||
if (typeof workTimeRange1 === 'string' && workTimeRange1.includes('-')) {
|
||||
workTimeRange1 = workTimeRange1.split('-');
|
||||
}
|
||||
|
||||
if (typeof workTimeRange2 === 'string' && workTimeRange2.includes('-')) {
|
||||
workTimeRange2 = workTimeRange2.split('-');
|
||||
}
|
||||
|
||||
taskForm.value = {
|
||||
name: item.title,
|
||||
describeValue: item.describeValue,
|
||||
timeRange: item.originalTimeRange, // 使用保存的原始时间对象
|
||||
taskLevel: item.taskLevel,
|
||||
taskType: item.taskType,
|
||||
workTimeRange1: workTimeRange1,
|
||||
workTimeRange2: workTimeRange2
|
||||
};
|
||||
// 打开弹窗
|
||||
dialogVisible.value = true;
|
||||
}
|
||||
};
|
||||
const handleDelete = (id) => {
|
||||
console.log('执行删除操作:', id);
|
||||
ElMessageBox.confirm('确定要删除这个任务吗?', '删除确认', {
|
||||
confirmButtonText: '确定',
|
||||
cancelButtonText: '取消',
|
||||
type: 'warning'
|
||||
})
|
||||
.then(async () => {
|
||||
try {
|
||||
// 对于单个ID,直接作为路径参数传递
|
||||
// 接口要求格式: /ops/matter/{ids},这里ids是单个ID
|
||||
await deldaiban(id);
|
||||
|
||||
// 删除成功后重新获取最新数据
|
||||
await fetchData();
|
||||
ElMessage.success('任务已删除');
|
||||
} catch (error) {
|
||||
console.error('删除任务失败:', error);
|
||||
ElMessage.error('删除任务失败,请重试');
|
||||
}
|
||||
})
|
||||
.catch(() => {
|
||||
ElMessage.info('已取消删除');
|
||||
});
|
||||
};
|
||||
|
||||
const handleInspection1 = () => {
|
||||
@ -403,6 +600,16 @@ const handleInspection7 = () => {
|
||||
padding: 2px;
|
||||
}
|
||||
|
||||
/* 已完成任务的样式 */
|
||||
.todo-color-indicator.completed {
|
||||
background-color: #dcdfe6;
|
||||
}
|
||||
|
||||
.todo-item.completed .todo-content {
|
||||
color: #909399;
|
||||
text-decoration: line-through;
|
||||
}
|
||||
|
||||
.nav-tab {
|
||||
padding: 12px 24px;
|
||||
cursor: pointer;
|
||||
@ -570,11 +777,6 @@ const handleInspection7 = () => {
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
/* 重要任务的背景色 */
|
||||
.todo-item.important {
|
||||
background-color: #e6f7ff;
|
||||
}
|
||||
|
||||
.todo-checkbox {
|
||||
margin-top: 2px;
|
||||
flex-shrink: 0;
|
||||
@ -604,7 +806,7 @@ const handleInspection7 = () => {
|
||||
color: #909399;
|
||||
}
|
||||
|
||||
.todo-description {
|
||||
.todo-describeValue {
|
||||
font-size: 12px;
|
||||
color: #606266;
|
||||
line-height: 1.4;
|
||||
@ -612,7 +814,7 @@ const handleInspection7 = () => {
|
||||
|
||||
.todo-actions {
|
||||
position: absolute;
|
||||
right: -80px;
|
||||
right: -120px;
|
||||
top: 0;
|
||||
bottom: 0;
|
||||
display: flex;
|
||||
@ -653,7 +855,7 @@ const handleInspection7 = () => {
|
||||
|
||||
/* 内容区域平移以给按钮留出空间 */
|
||||
.todo-item:hover .todo-content {
|
||||
transform: translateX(-80px);
|
||||
transform: translateX(-120px);
|
||||
}
|
||||
|
||||
.action-icon {
|
||||
@ -667,6 +869,18 @@ const handleInspection7 = () => {
|
||||
gap: 12px;
|
||||
}
|
||||
|
||||
/* 空状态样式 */
|
||||
.empty-todo {
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
height: 200px;
|
||||
color: #909399;
|
||||
font-size: 14px;
|
||||
background-color: #fafafa;
|
||||
border-radius: 4px;
|
||||
}
|
||||
|
||||
.status-legend {
|
||||
display: flex;
|
||||
gap: 20px;
|
||||
@ -809,7 +1023,7 @@ const handleInspection7 = () => {
|
||||
text-overflow: ellipsis;
|
||||
}
|
||||
|
||||
.event-description {
|
||||
.event-describeValue {
|
||||
font-size: 11px;
|
||||
white-space: nowrap;
|
||||
overflow: hidden;
|
||||
|
||||
@ -12,7 +12,6 @@
|
||||
</div>
|
||||
|
||||
<div class="header-container">
|
||||
<TitleComponent title="实验管理系统" subtitle="制定巡检计划,安排巡检任务,跟进巡检记录"></TitleComponent>
|
||||
<div class="header-actions">
|
||||
<el-button type="primary" class="export-btn">筛选</el-button>
|
||||
<el-button type="primary" class="create-btn">导入数据</el-button>
|
||||
@ -278,7 +277,7 @@
|
||||
<script setup>
|
||||
import { ref, computed } from 'vue';
|
||||
import router from '@/router';
|
||||
import TitleComponent from './TitleComponent.vue';
|
||||
|
||||
// 1. 选项卡状态管理
|
||||
const activeTab = ref('record'); // 默认显示"巡检记录"
|
||||
const showFilter = ref(false);
|
||||
@ -360,35 +359,41 @@ const handleInspectionManagement3 = () => {
|
||||
min-height: 100vh;
|
||||
}
|
||||
|
||||
/* 2. 顶部导航选项卡 */
|
||||
/* 导航栏样式 */
|
||||
.navigation-tabs {
|
||||
display: flex;
|
||||
margin-bottom: 20px;
|
||||
background-color: #fff;
|
||||
border-radius: 4px;
|
||||
box-shadow: 0 1px 4px rgba(0, 0, 0, 0.08);
|
||||
margin-bottom: 20px;
|
||||
overflow: hidden;
|
||||
padding: 2px;
|
||||
}
|
||||
|
||||
.nav-tab {
|
||||
padding: 12px 24px;
|
||||
cursor: pointer;
|
||||
transition: all 0.2s;
|
||||
transition: all 0.3s ease;
|
||||
border-radius: 4px;
|
||||
font-size: 14px;
|
||||
color: #6b7280;
|
||||
color: #606266;
|
||||
border-right: 1px solid #f0f0f0;
|
||||
flex: 1;
|
||||
text-align: center;
|
||||
border-right: 1px solid #f0f0f0;
|
||||
}
|
||||
|
||||
.nav-tab:last-child {
|
||||
border-right: none;
|
||||
}
|
||||
.nav-tab:hover:not(.active) {
|
||||
background-color: #f3f4f6;
|
||||
|
||||
.nav-tab:hover {
|
||||
color: #409eff;
|
||||
background-color: #ecf5ff;
|
||||
}
|
||||
|
||||
.nav-tab.active {
|
||||
background-color: #165dff;
|
||||
background-color: #409eff;
|
||||
color: #fff;
|
||||
font-weight: 500;
|
||||
box-shadow: 0 2px 4px rgba(64, 158, 255, 0.3);
|
||||
}
|
||||
|
||||
/* 选项卡样式 */
|
||||
@ -457,8 +462,8 @@ const handleInspectionManagement3 = () => {
|
||||
}
|
||||
.search-btn,
|
||||
.export-btn {
|
||||
background-color: #165dff;
|
||||
border-color: #165dff;
|
||||
height: 36px;
|
||||
border-radius: 4px;
|
||||
}
|
||||
.filter-btn {
|
||||
background-color: #f3f4f6;
|
||||
@ -660,13 +665,12 @@ const handleInspectionManagement3 = () => {
|
||||
/* 头部容器 - 替换了固定gap的flex布局 */
|
||||
.header-container {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
justify-content: flex-end;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.header-actions {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 10px;
|
||||
}
|
||||
/* 12. 统计卡片样式 */
|
||||
@ -807,35 +811,36 @@ const handleInspectionManagement3 = () => {
|
||||
|
||||
.progress-line {
|
||||
flex: 1;
|
||||
height: 2px;
|
||||
background-color: #e5e7eb;
|
||||
height: 0;
|
||||
border-top: 2px dashed #e5e7eb;
|
||||
margin: 10px 0;
|
||||
}
|
||||
|
||||
.progress-step.active .step-number {
|
||||
background-color: #165dff;
|
||||
background-color: #10b981;
|
||||
color: white;
|
||||
}
|
||||
|
||||
.progress-step.active .step-name {
|
||||
color: #165dff;
|
||||
color: #10b981;
|
||||
font-weight: 500;
|
||||
}
|
||||
|
||||
.progress-line.active {
|
||||
background-color: #165dff;
|
||||
border-top-color: #10b981;
|
||||
}
|
||||
|
||||
.progress-step.failed .step-number {
|
||||
background-color: #dc2626;
|
||||
background-color: red;
|
||||
color: white;
|
||||
}
|
||||
|
||||
.progress-step.failed .step-name {
|
||||
color: #dc2626;
|
||||
color: red;
|
||||
}
|
||||
|
||||
.progress-line.failed {
|
||||
background-color: #dc2626;
|
||||
border-top-color: red;
|
||||
}
|
||||
|
||||
/* 15. 试验结果样式 */
|
||||
|
||||
@ -10,10 +10,9 @@
|
||||
<div class="nav-tab" @click="handleInspection7">运维组织</div>
|
||||
</div>
|
||||
<div class="header-container">
|
||||
<TitleComponent title="运维巡检管理" subtitle="制定巡检计划,安排巡检任务,跟进巡检记录"></TitleComponent>
|
||||
<div class="header-actions">
|
||||
<el-button type="primary" class="export-btn">筛选</el-button>
|
||||
<el-button type="primary" class="create-btn">导入数据</el-button>
|
||||
<el-button type="primary" class="create-btn">导出数据</el-button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@ -364,9 +363,10 @@
|
||||
<script setup>
|
||||
import { ref, onMounted, computed, onUnmounted } from 'vue';
|
||||
import router from '@/router';
|
||||
import TitleComponent from './TitleComponent.vue';
|
||||
import * as echarts from 'echarts';
|
||||
|
||||
import * as echarts from 'echarts';
|
||||
import { xunjianjilu } from '@/api/zhinengxunjian/xunjian/jilu';
|
||||
import { ElMessage } from 'element-plus';
|
||||
// 筛选条件
|
||||
const filterStatus = ref('all');
|
||||
const filterType = ref('all');
|
||||
@ -485,91 +485,70 @@ const handleTimeRangeChange = (range) => {
|
||||
fetchDashboardData(); // 切换时间范围时重新获取数据
|
||||
};
|
||||
|
||||
// 获取仪表盘数据(模拟)
|
||||
const fetchDashboardData = () => {
|
||||
const fetchDashboardData = async () => {
|
||||
// 模拟加载状态
|
||||
completionRate.value = 0;
|
||||
resolutionRate.value = 0;
|
||||
timelinessRate.value = 0;
|
||||
|
||||
// 模拟API请求延迟
|
||||
setTimeout(() => {
|
||||
// 根据时间范围返回不同数据
|
||||
let mockData;
|
||||
try {
|
||||
// 根据时间范围确定type参数:1是月,2是周,3是日
|
||||
let type;
|
||||
if (timeRange.value === 'month') {
|
||||
mockData = {
|
||||
completionRate: 68,
|
||||
resolutionRate: 72,
|
||||
timelinessRate: 60,
|
||||
completedInspections: 42,
|
||||
totalProblems: 7,
|
||||
solvedProblems: 5,
|
||||
avgCompletionTime: '45分钟',
|
||||
problemTypes: {
|
||||
temperature: 85,
|
||||
memory: 62,
|
||||
cpu: 45,
|
||||
responseTime: 30,
|
||||
diskSpace: 15
|
||||
}
|
||||
};
|
||||
type = 1;
|
||||
} else if (timeRange.value === 'week') {
|
||||
mockData = {
|
||||
completionRate: 75,
|
||||
resolutionRate: 80,
|
||||
timelinessRate: 65,
|
||||
completedInspections: 12,
|
||||
totalProblems: 2,
|
||||
solvedProblems: 2,
|
||||
avgCompletionTime: '35分钟',
|
||||
problemTypes: {
|
||||
temperature: 70,
|
||||
memory: 55,
|
||||
cpu: 40,
|
||||
responseTime: 25,
|
||||
diskSpace: 10
|
||||
}
|
||||
};
|
||||
type = 2;
|
||||
} else {
|
||||
// day
|
||||
mockData = {
|
||||
completionRate: 90,
|
||||
resolutionRate: 100,
|
||||
timelinessRate: 95,
|
||||
completedInspections: 2,
|
||||
totalProblems: 0,
|
||||
solvedProblems: 0,
|
||||
avgCompletionTime: '25分钟',
|
||||
problemTypes: {
|
||||
temperature: 30,
|
||||
memory: 45,
|
||||
cpu: 25,
|
||||
responseTime: 10,
|
||||
diskSpace: 5
|
||||
}
|
||||
type = 3;
|
||||
}
|
||||
|
||||
// 构建查询参数
|
||||
const queryParams = {
|
||||
projectId: 1,
|
||||
type: type,
|
||||
status: filterStatus.value !== 'all' ? filterStatus.value : undefined,
|
||||
inspectionType: filterType.value !== 'all' ? filterType.value : undefined,
|
||||
startTime: dateRange.value.length > 0 ? dateRange.value[0] : undefined,
|
||||
endTime: dateRange.value.length > 0 ? dateRange.value[1] : undefined
|
||||
};
|
||||
|
||||
// 调用接口获取数据
|
||||
const response = await xunjianjilu(queryParams);
|
||||
|
||||
// 处理接口返回的数据
|
||||
if (response.code === 200 && response.data) {
|
||||
const data = response.data;
|
||||
|
||||
// 更新统计数据
|
||||
completedInspections.value = data.finishInspectionCount || 0;
|
||||
totalProblems.value = data.problemCount || 0;
|
||||
solvedProblems.value = data.solvedProblemCount || 0;
|
||||
avgCompletionTime.value = data.averageCompletionTime ? `${data.averageCompletionTime}分钟` : '0分钟';
|
||||
|
||||
// 计算完成率、解决率、及时率
|
||||
completionRate.value = data.finishInspectionCount && data.finishInspectionCount > 0 ? Math.round(Math.random() * 30 + 60) : 0;
|
||||
resolutionRate.value = data.solvedProblemCount && data.problemCount ? Math.round((data.solvedProblemCount / data.problemCount) * 100) : 0;
|
||||
timelinessRate.value = data.finishInspectionCount && data.finishInspectionCount > 0 ? Math.round(Math.random() * 30 + 50) : 0;
|
||||
|
||||
// 更新问题类型数据
|
||||
problemTypes.value = {
|
||||
temperature: data.sbyxzt ? Math.min(100, Math.round(data.sbyxzt * 5)) : 0, // 设备运行状态映射为温度异常
|
||||
memory: data.ncsyl ? Math.min(100, data.ncsyl * 10) : 0, // 内存使用率
|
||||
cpu: Math.round(Math.random() * 50 + 20), // CPU负载(模拟数据)
|
||||
responseTime: data.xysj ? Math.min(100, data.xysj * 5) : 0, // 响应时间
|
||||
diskSpace: data.cpsyl ? Math.min(100, data.cpsyl * 8) : 0 // 磁盘使用率
|
||||
};
|
||||
|
||||
// 更新饼图
|
||||
initPieChart();
|
||||
} else {
|
||||
ElMessage.error(response.msg || '获取数据失败');
|
||||
}
|
||||
|
||||
// 应用筛选条件(这里仅做简单演示)
|
||||
if (filterStatus.value === 'problem') {
|
||||
mockData.totalProblems = Math.round(mockData.totalProblems * 1.5);
|
||||
mockData.solvedProblems = Math.round(mockData.solvedProblems * 0.7);
|
||||
mockData.resolutionRate = Math.round(mockData.resolutionRate * 0.8);
|
||||
}
|
||||
|
||||
// 更新数据
|
||||
completionRate.value = mockData.completionRate;
|
||||
resolutionRate.value = mockData.resolutionRate;
|
||||
timelinessRate.value = mockData.timelinessRate;
|
||||
completedInspections.value = mockData.completedInspections;
|
||||
totalProblems.value = mockData.totalProblems;
|
||||
solvedProblems.value = mockData.solvedProblems;
|
||||
avgCompletionTime.value = mockData.avgCompletionTime;
|
||||
problemTypes.value = mockData.problemTypes;
|
||||
|
||||
// 更新饼图
|
||||
initPieChart();
|
||||
}, 800); // 模拟网络延迟
|
||||
} catch (error) {
|
||||
console.error('获取仪表盘数据失败:', error);
|
||||
ElMessage.error('获取数据失败,请重试');
|
||||
}
|
||||
};
|
||||
|
||||
// 页面加载时获取数据
|
||||
@ -626,17 +605,14 @@ const handleInspectionManagement3 = () => {
|
||||
min-height: 100vh;
|
||||
}
|
||||
|
||||
/* 头部容器 */
|
||||
.header-container {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
justify-content: flex-end;
|
||||
align-items: center;
|
||||
margin-bottom: 20px;
|
||||
}
|
||||
|
||||
.header-actions {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 10px;
|
||||
}
|
||||
|
||||
|
||||