Compare commits
742 Commits
| Author | SHA1 | Date |
|---|---|---|
|
|
fb2595ef90 | |
|
|
eaaf55eafa | |
|
|
d910450426 | |
|
|
f813245827 | |
|
|
cfbd13289f | |
|
|
e98f0b7558 | |
|
|
cd86de54e1 | |
|
|
152964395d | |
|
|
60eb1335f8 | |
|
|
f2b3b12553 | |
|
|
c066889c37 | |
|
|
f8c869f1ff | |
|
|
00779aacb3 | |
|
|
6b81d1b0d5 | |
|
|
126b33687a | |
|
|
9d665bd6b9 | |
|
|
5b67c2e740 | |
|
|
2d7c3c3072 | |
|
|
5cc68c9dd0 | |
|
|
df8e23542b | |
|
|
e7361a60ec | |
|
|
66843f2392 | |
|
|
83bf576daf | |
|
|
2a97bed546 | |
|
|
c8ce1a8911 | |
|
|
d1a2601b6c | |
|
|
d2587c17b0 | |
|
|
33cdfcac3c | |
|
|
58f2e23654 | |
|
|
d207e3b82c | |
|
|
1afa70bb53 | |
|
|
751ba2c782 | |
|
|
057ca0bfde | |
|
|
df720b2c1a | |
|
|
4b6e2de778 | |
|
|
e6e15ca4ef | |
|
|
0d175cbe9c | |
|
|
f02a5975b8 | |
|
|
b35ce18c6e | |
|
|
63a38dce49 | |
|
|
629f747795 | |
|
|
c11db17376 | |
|
|
b3462c3286 | |
|
|
9cc52f128c | |
|
|
67997bd44d | |
|
|
5790211897 | |
|
|
6b1425d541 | |
|
|
13c3028ecc | |
|
|
cb175e331f | |
|
|
3f09fc1498 | |
|
|
8585008f79 | |
|
|
00990d9453 | |
|
|
2a84b590b5 | |
|
|
769c970e08 | |
|
|
4d3c481a93 | |
|
|
fda4b39c01 | |
|
|
74d8942f39 | |
|
|
9ec98f0846 | |
|
|
f71094e878 | |
|
|
e816288b82 | |
|
|
f1f8f4e64a | |
|
|
9badda3d11 | |
|
|
250d3eb39f | |
|
|
5607f23322 | |
|
|
538d04a380 | |
|
|
b9d333f7ec | |
|
|
dab9509ba0 | |
|
|
b1bd32a89b | |
|
|
ec796b8336 | |
|
|
e7a61ce150 | |
|
|
1bdc0d992f | |
|
|
8bcfa20577 | |
|
|
ab15c884bf | |
|
|
9c57ae07a6 | |
|
|
03fcecadcc | |
|
|
3a88adb8a6 | |
|
|
c759cb2593 | |
|
|
f77166b3a2 | |
|
|
f7928b34b2 | |
|
|
454a5b54bd | |
|
|
09c19526bb | |
|
|
b9a7eddb72 | |
|
|
0bc1981675 | |
|
|
a4dd9d30ce | |
|
|
9d54f60b10 | |
|
|
76cfcda2e9 | |
|
|
7ec4df4995 | |
|
|
d71c81e8ff | |
|
|
a70fcc9616 | |
|
|
4821d49017 | |
|
|
a1b66588ec | |
|
|
a098c201e1 | |
|
|
8da5c12dfc | |
|
|
3d0917f1a9 | |
|
|
0280df114f | |
|
|
6b61004b6a | |
|
|
8d69e4d9f0 | |
|
|
cd42a653c5 | |
|
|
56de1f1412 | |
|
|
80f071d57f | |
|
|
68800c96d7 | |
|
|
2dfa863d68 | |
|
|
4cded0a674 | |
|
|
aac626da32 | |
|
|
584370358e | |
|
|
76bed17ed9 | |
|
|
e9e534018f | |
|
|
5db93a345a | |
|
|
7c943cc06b | |
|
|
5c8dd1a6da | |
|
|
6592135cc5 | |
|
|
2f16ee7cf5 | |
|
|
0c1b737325 | |
|
|
5bbdcffb97 | |
|
|
1867015e97 | |
|
|
b6aeadd9a2 | |
|
|
1e44b87359 | |
|
|
a1081bf7a6 | |
|
|
9bb2026b4d | |
|
|
4554cd016a | |
|
|
350d5ee60e | |
|
|
1ec058cbe3 | |
|
|
709951e6db | |
|
|
fbc03a9713 | |
|
|
1bbb7eb1d5 | |
|
|
88515705dc | |
|
|
81b4690998 | |
|
|
cfb1f8401e | |
|
|
5182cdbffa | |
|
|
d649a617ac | |
|
|
71a23487f7 | |
|
|
89f75428d6 | |
|
|
179881bd3d | |
|
|
58f8b7fb22 | |
|
|
6740401f6c | |
|
|
b42e9b36e5 | |
|
|
f8c2d4b1ff | |
|
|
41d5aa93d6 | |
|
|
3135b28211 | |
|
|
08511191f7 | |
|
|
0246fa1ebc | |
|
|
0e4012c623 | |
|
|
4933180560 | |
|
|
aa577d84e9 | |
|
|
8710da9383 | |
|
|
5a1f4901da | |
|
|
3da4a3f417 | |
|
|
84b91c6795 | |
|
|
735ff018be | |
|
|
0163794e3f | |
|
|
bb63ca9541 | |
|
|
6b28518165 | |
|
|
0d7d7aea73 | |
|
|
4adce844d3 | |
|
|
19b5f38e23 | |
|
|
80fa8b74e8 | |
|
|
5710761dbe | |
|
|
877ba2727f | |
|
|
70a639967c | |
|
|
6cbbe88902 | |
|
|
eb9cdbab9b | |
|
|
4907f281af | |
|
|
aadf9b6e39 | |
|
|
84e77f64ea | |
|
|
3e89077d46 | |
|
|
c8c425538f | |
|
|
b04c10aab6 | |
|
|
b5f79db321 | |
|
|
42d82875ce | |
|
|
4d8d2de6ad | |
|
|
294700a247 | |
|
|
f55b18ffd7 | |
|
|
ca5931e8c4 | |
|
|
ccfc122eae | |
|
|
59183029b6 | |
|
|
e81ca2c13f | |
|
|
dcccef1c02 | |
|
|
9a5bee4dce | |
|
|
29665f02bf | |
|
|
06f776d1ef | |
|
|
40f0ba71f5 | |
|
|
0fced45a9c | |
|
|
2ea7da06c5 | |
|
|
aac4e88353 | |
|
|
30356a24e6 | |
|
|
ba60bc3c14 | |
|
|
f5feddc6c7 | |
|
|
0868deb82b | |
|
|
1299acd8f9 | |
|
|
43717807a4 | |
|
|
1b4e126128 | |
|
|
d23b246aee | |
|
|
71f2e5f504 | |
|
|
4bbd34fab9 | |
|
|
08e4bb40b4 | |
|
|
9c49f4bb1e | |
|
|
28905b0bec | |
|
|
bbcad709ca | |
|
|
a5f0537cb0 | |
|
|
c78d89f549 | |
|
|
f2a17cbe78 | |
|
|
9667232684 | |
|
|
1f584ff0c9 | |
|
|
75ed17a1f9 | |
|
|
cc6ccaab38 | |
|
|
0be4b51eaa | |
|
|
b40822e3ed | |
|
|
df5cb426d1 | |
|
|
2d36d6b510 | |
|
|
88d5661e0c | |
|
|
8ce773f264 | |
|
|
329fa68207 | |
|
|
e1f6449073 | |
|
|
51e8b27d4c | |
|
|
e555ee065e | |
|
|
c164904a14 | |
|
|
a0ceb45df9 | |
|
|
c641542c71 | |
|
|
b5dacd992f | |
|
|
a3d8e4bfc1 | |
|
|
e385823d46 | |
|
|
897220e19a | |
|
|
b293e112c6 | |
|
|
627e31f1b0 | |
|
|
8020b4b743 | |
|
|
228c5463da | |
|
|
50ee691191 | |
|
|
eda6ffaf1e | |
|
|
d55f17670a | |
|
|
9f20d52b4e | |
|
|
86445a38e4 | |
|
|
9a73e961fc | |
|
|
c0b2ef980e | |
|
|
e8dc464e79 | |
|
|
99c38c93c8 | |
|
|
244c0a5884 | |
|
|
c6fd599784 | |
|
|
4ca2f1c6e8 | |
|
|
36d7dc23fa | |
|
|
42317ddf41 | |
|
|
c7fd6ffb0e | |
|
|
3a83fb0c3e | |
|
|
5907c04e00 | |
|
|
6885927441 | |
|
|
c8c589ae7e | |
|
|
d0889b5cc4 | |
|
|
2f1a866cb4 | |
|
|
fee32c1d12 | |
|
|
f2652833a1 | |
|
|
c3aa63982f | |
|
|
4a968d9379 | |
|
|
ec9b323195 | |
|
|
d69455e8ef | |
|
|
33e2582f60 | |
|
|
991408b451 | |
|
|
a096073a8e | |
|
|
f30157fa59 | |
|
|
12a81a7a7d | |
|
|
e808fe74c1 | |
|
|
4665a787a0 | |
|
|
b7774fc9d9 | |
|
|
6f18718c87 | |
|
|
2a32715c99 | |
|
|
46f323431c | |
|
|
2b1fcb038b | |
|
|
d779a39862 | |
|
|
0c8db0f6be | |
|
|
37393e1820 | |
|
|
93e23c6b05 | |
|
|
e023a0852a | |
|
|
306739cabb | |
|
|
093479bb33 | |
|
|
bd369df3bc | |
|
|
4f7b396ebb | |
|
|
d700b04841 | |
|
|
243456d928 | |
|
|
7e8b9c2368 | |
|
|
92298bac2b | |
|
|
436a865bef | |
|
|
185011ee21 | |
|
|
feca01484b | |
|
|
35e1166b9f | |
|
|
d0c17090ef | |
|
|
cc32ebeb12 | |
|
|
02372f12ba | |
|
|
e9bdbb610a | |
|
|
2013ba4de4 | |
|
|
e417a2c209 | |
|
|
f1273571c7 | |
|
|
064a6a20f0 | |
|
|
cb5e7e00f1 | |
|
|
5ed39c03a4 | |
|
|
794b103aa9 | |
|
|
c7b1bb3492 | |
|
|
89349f8d91 | |
|
|
8e0b65a0e1 | |
|
|
b096e83f93 | |
|
|
4a69c9e665 | |
|
|
7a60a081a2 | |
|
|
c693c854a7 | |
|
|
5eca357a5c | |
|
|
2930dcd78e | |
|
|
e421d9d99b | |
|
|
f542db27f9 | |
|
|
b2cf1646a4 | |
|
|
adecddae67 | |
|
|
a653e428f3 | |
|
|
eb62e63a04 | |
|
|
6c029bfa32 | |
|
|
fe77bc8bc9 | |
|
|
ccabbf0e97 | |
|
|
5b84ac5b13 | |
|
|
f610bd690b | |
|
|
76f9d3d9fc | |
|
|
1e6c39a4c6 | |
|
|
7a1f8da68f | |
|
|
51cae9b00c | |
|
|
7cbeaa8390 | |
|
|
6be3a0e204 | |
|
|
a9b76ba2ed | |
|
|
53ccec1d80 | |
|
|
4af5d6152b | |
|
|
307781f437 | |
|
|
1326994d8e | |
|
|
fd70a3f3e0 | |
|
|
298930b0d7 | |
|
|
54d95b8761 | |
|
|
4a16040d3e | |
|
|
ee95548340 | |
|
|
320e687bad | |
|
|
ad43c6817e | |
|
|
c8747c079d | |
|
|
224bfe7fcb | |
|
|
f443bfbc7b | |
|
|
195b2ea0d2 | |
|
|
4150479549 | |
|
|
5ebf513498 | |
|
|
4e4ffc439c | |
|
|
ad7ed50b52 | |
|
|
92f8916225 | |
|
|
7e4edd270d | |
|
|
332ff44219 | |
|
|
834ce3efc0 | |
|
|
5211f5065d | |
|
|
96d6f89732 | |
|
|
6ab06584eb | |
|
|
a6433c2b50 | |
|
|
128a131797 | |
|
|
c775d7ed80 | |
|
|
b8b4308e1c | |
|
|
80d6e2255f | |
|
|
4e0968d4b7 | |
|
|
44a5809a46 | |
|
|
2428fb1407 | |
|
|
bb78882f72 | |
|
|
df88a23102 | |
|
|
ca5f360231 | |
|
|
147b50ec45 | |
|
|
34439dce4e | |
|
|
9a22027b35 | |
|
|
282a102826 | |
|
|
417e6c2ade | |
|
|
9d69d7f46c | |
|
|
87d1593a1f | |
|
|
7fbdf3d914 | |
|
|
65287cf4b7 | |
|
|
6da3017dcf | |
|
|
5c02057198 | |
|
|
a7ca7cdb9f | |
|
|
79408d406d | |
|
|
e555f71bf8 | |
|
|
4c320346c3 | |
|
|
e5ec88169a | |
|
|
914711ae04 | |
|
|
4c1e3b9548 | |
|
|
9cd3987475 | |
|
|
47a853330d | |
|
|
2aced2f659 | |
|
|
cd955df02f | |
|
|
0a819df2bf | |
|
|
67afcadcf0 | |
|
|
1128ef5acd | |
|
|
ca39b8d0c9 | |
|
|
fece74f744 | |
|
|
6b3506f128 | |
|
|
5613dcef99 | |
|
|
3528517fe0 | |
|
|
2a5b520ec9 | |
|
|
e2fb3602f1 | |
|
|
da3580cbd7 | |
|
|
0c300d040c | |
|
|
d43a3729c3 | |
|
|
bed97a84d8 | |
|
|
b908076846 | |
|
|
885a0a9a00 | |
|
|
340baf4f0b | |
|
|
82cda0edaa | |
|
|
9fe875355a | |
|
|
5f21bd2036 | |
|
|
5b5ea6d2d8 | |
|
|
3dcfd23036 | |
|
|
186914bcac | |
|
|
4b3205fee8 | |
|
|
e4453841db | |
|
|
32db4cbd11 | |
|
|
5558249cd3 | |
|
|
86b636ae54 | |
|
|
c9f7154524 | |
|
|
d72f872369 | |
|
|
b300011d07 | |
|
|
3946253d6e | |
|
|
11fc367845 | |
|
|
bdc65cc250 | |
|
|
70dad0f600 | |
|
|
26e9aa244b | |
|
|
913f77fd2f | |
|
|
dba774e1c7 | |
|
|
af09d652a3 | |
|
|
0babdfbc44 | |
|
|
f154d53be9 | |
|
|
ed3cd2fe3b | |
|
|
59912a00bc | |
|
|
675d8b0179 | |
|
|
a1ca296fc0 | |
|
|
c1b1fe90fd | |
|
|
30b5610a73 | |
|
|
db9b9df8f7 | |
|
|
ae6a75e913 | |
|
|
37d72c1628 | |
|
|
ab3e6bb37c | |
|
|
9ddb899a1a | |
|
|
1f0cda8aee | |
|
|
90ae85317c | |
|
|
a8ae891aff | |
|
|
1f2df3e944 | |
|
|
e39a432210 | |
|
|
6b3bcee582 | |
|
|
6c274b75b8 | |
|
|
278032c94b | |
|
|
23a8982f5c | |
|
|
5df6c32d04 | |
|
|
7cae330c3c | |
|
|
100aaa4cee | |
|
|
ead0b73e7b | |
|
|
2ace846e38 | |
|
|
1d98393f0c | |
|
|
c48ee2a364 | |
|
|
95d1e8432f | |
|
|
4d59ac78bd | |
|
|
f1143e134e | |
|
|
e3e869faee | |
|
|
8350e72393 | |
|
|
15f74b9d97 | |
|
|
55b54e24fe | |
|
|
46b4ce81e4 | |
|
|
7a723d03d0 | |
|
|
9d6fbfd0d6 | |
|
|
8fd6bf47b1 | |
|
|
f25f3a34d0 | |
|
|
2823848fae | |
|
|
b9467b2bc3 | |
|
|
fa190e0975 | |
|
|
90dc8cf997 | |
|
|
53c5ccc00a | |
|
|
06c9e8d7c1 | |
|
|
f32818c6aa | |
|
|
fb03afb6b7 | |
|
|
577efa56a9 | |
|
|
cb98b3a47e | |
|
|
8daf9a3ce5 | |
|
|
a83d8248d7 | |
|
|
4cdc92f759 | |
|
|
54c668c3f0 | |
|
|
ac3fc6b7d3 | |
|
|
a6a6efdf59 | |
|
|
8043faf6c7 | |
|
|
ebed9e64ed | |
|
|
913636ae44 | |
|
|
7b064e9f33 | |
|
|
16da0eaca3 | |
|
|
6acfee2737 | |
|
|
92abf7edaa | |
|
|
395babc1f5 | |
|
|
68cde54bad | |
|
|
c7d7529c00 | |
|
|
748f60c7bb | |
|
|
ffee62e940 | |
|
|
a0ea221131 | |
|
|
2846bcb84e | |
|
|
542ed6c08f | |
|
|
6dabb848a5 | |
|
|
de0181e0d9 | |
|
|
a850d426ef | |
|
|
771277d5d9 | |
|
|
20b4f5c99f | |
|
|
e7fa87b301 | |
|
|
40c66958bc | |
|
|
600fc71aed | |
|
|
443e4b04cd | |
|
|
556a3c0fab | |
|
|
1eca52f962 | |
|
|
e21adb395b | |
|
|
0e4bf80bf4 | |
|
|
107750971b | |
|
|
24e1be47ca | |
|
|
7e0978c764 | |
|
|
83a0c9662d | |
|
|
a4736a49f8 | |
|
|
1cbdf442ee | |
|
|
f91a2702c9 | |
|
|
c885c0c71a | |
|
|
a8f67ab717 | |
|
|
aa7d8630b5 | |
|
|
36313f378e | |
|
|
45054d3238 | |
|
|
173e6b08c9 | |
|
|
75e4d07395 | |
|
|
2a86404ba5 | |
|
|
b8a0199cde | |
|
|
a46ed55a86 | |
|
|
1a9fbddef4 | |
|
|
1209aaafb4 | |
|
|
8e71261d49 | |
|
|
586978f1b0 | |
|
|
49e45eab54 | |
|
|
bd22793ceb | |
|
|
b2013436c5 | |
|
|
cc808cb8c5 | |
|
|
afffc4b3f0 | |
|
|
99710ef9dc | |
|
|
3d4ae04d9b | |
|
|
707b391449 | |
|
|
45b843f344 | |
|
|
191fd90f06 | |
|
|
05920cd66d | |
|
|
01508d5e42 | |
|
|
57cf6cbc9e | |
|
|
dd69d7c1a5 | |
|
|
63743b6929 | |
|
|
38597dd19d | |
|
|
03ebbea46a | |
|
|
8e7a5d1ec3 | |
|
|
e7365a4a00 | |
|
|
aa74a2535b | |
|
|
32379ba4b7 | |
|
|
bf4fed78f2 | |
|
|
722afc85df | |
|
|
3036596d16 | |
|
|
aee539f37e | |
|
|
05b41692ba | |
|
|
7fe8d7b4be | |
|
|
aace726a91 | |
|
|
e6f6e5464a | |
|
|
7d04b600fb | |
|
|
8a622889ff | |
|
|
463bfde2ac | |
|
|
893f74dc3e | |
|
|
e136679934 | |
|
|
8a215fbcc7 | |
|
|
ac5e4c4722 | |
|
|
04d01b0bab | |
|
|
cb1d7565a3 | |
|
|
1d9b6407a4 | |
|
|
22ed522711 | |
|
|
a3598ef859 | |
|
|
6fe09ec2dd | |
|
|
57911d9e09 | |
|
|
3aee283495 | |
|
|
54b24c2677 | |
|
|
8cadad0a1e | |
|
|
633c5f3cda | |
|
|
a8431e2040 | |
|
|
7a2b916387 | |
|
|
f3deefae56 | |
|
|
d0a7065991 | |
|
|
5b7e7c4d56 | |
|
|
f4dfb68b7b | |
|
|
8f4f27d860 | |
|
|
e9eab29953 | |
|
|
4f1eeb7da5 | |
|
|
6fd426d719 | |
|
|
331da3c8c7 | |
|
|
c48943bc67 | |
|
|
f6c5bc4b7c | |
|
|
448f073143 | |
|
|
fc31aa3c8f | |
|
|
7680b33b99 | |
|
|
548da70f9f | |
|
|
0441afc24f | |
|
|
1196dab9e4 | |
|
|
00bf48704d | |
|
|
7a1218e6f0 | |
|
|
dbb1a19c5d | |
|
|
f433b207c6 | |
|
|
82b91dfed3 | |
|
|
1295aee180 | |
|
|
00105e1302 | |
|
|
e82433e3e7 | |
|
|
ccaef2b591 | |
|
|
bb5d75bc7e | |
|
|
528395e2c3 | |
|
|
6a9012e5e4 | |
|
|
6e8315ab40 | |
|
|
36aa195378 | |
|
|
de2662ca8f | |
|
|
35acb9558b | |
|
|
c4a262d1e2 | |
|
|
a1e021074e | |
|
|
0a7ead980a | |
|
|
cdcbd58f0e | |
|
|
c57f3d8820 | |
|
|
02c977f969 | |
|
|
a0019cef04 | |
|
|
e447a8a569 | |
|
|
071468b716 | |
|
|
24b8bba754 | |
|
|
6d60071515 | |
|
|
baed599fcc | |
|
|
7cb2699f19 | |
|
|
1ce562601f | |
|
|
4b5da81ba6 | |
|
|
6aca9a9c99 | |
|
|
c55465a6c0 | |
|
|
2ae684bdad | |
|
|
ce2bfa5cd2 | |
|
|
63265c1a6b | |
|
|
fa195fde8e | |
|
|
1057f2932b | |
|
|
b9224fc379 | |
|
|
57dd818170 | |
|
|
49256ec1b7 | |
|
|
f6f92e5403 | |
|
|
613c311076 | |
|
|
9ee7a7d9ff | |
|
|
44f8aed06d | |
|
|
d5d4a5c591 | |
|
|
74381aa8c1 | |
|
|
203ee9b623 | |
|
|
13b1ef71a9 | |
|
|
ba08820be8 | |
|
|
d9e933e3a6 | |
|
|
50216e5047 | |
|
|
6c8c49966a | |
|
|
4aeb7a489a | |
|
|
3862942e9f | |
|
|
8571fc43b0 | |
|
|
59aabd956d | |
|
|
9b09ba4483 | |
|
|
42f2fecb1e | |
|
|
af0057940a | |
|
|
9e3d75ae65 | |
|
|
e5f5523bc6 | |
|
|
4cc900f542 | |
|
|
ce34e6e1a0 | |
|
|
db1dfae481 | |
|
|
012412ec22 | |
|
|
db97d414ec | |
|
|
8bf286fda0 | |
|
|
91119eac8e | |
|
|
686c3f9208 | |
|
|
8a7e2bd8e4 | |
|
|
174c4ae749 | |
|
|
67da9417a8 | |
|
|
d5b49e6a3b | |
|
|
c894617e10 | |
|
|
10f4641fee | |
|
|
c478bef269 | |
|
|
0302b70c48 | |
|
|
2426f891e7 | |
|
|
e2433fc531 | |
|
|
bbc74ae663 | |
|
|
ea79b7d6a1 | |
|
|
f4a4ced88d | |
|
|
19b2d7af41 | |
|
|
343d8a1c1e | |
|
|
9480f8272a | |
|
|
0d9e260a6a | |
|
|
51bca25345 | |
|
|
694396dcfb | |
|
|
1cb53e943e | |
|
|
13c8318adc | |
|
|
48ed797055 | |
|
|
3c2285141c | |
|
|
49b884c0b1 | |
|
|
24d20ca9ee | |
|
|
6f02181024 | |
|
|
17d5d1b889 | |
|
|
a5c76ef89d | |
|
|
e622c052a9 | |
|
|
ed3353a271 | |
|
|
de28c5c4c2 | |
|
|
965f5f96b7 | |
|
|
61d9df7f58 | |
|
|
231a5169ec | |
|
|
ce7b7b910a | |
|
|
f7f01c9280 | |
|
|
81a61558cb | |
|
|
a9f21c1acb | |
|
|
19c7f0d5dd | |
|
|
cd43149429 | |
|
|
19919f6685 | |
|
|
036ef294db | |
|
|
7d2bc2e885 | |
|
|
89b237f6b4 | |
|
|
d8f685708d | |
|
|
f8ce09a203 | |
|
|
59d83d29cb | |
|
|
02193755be | |
|
|
6d524906a3 | |
|
|
cbd1f0bcbb | |
|
|
2ba2c8e986 | |
|
|
06f1ae1a66 | |
|
|
029b2ffaab | |
|
|
64ac25de00 | |
|
|
6606dfd40a | |
|
|
6da4a39ff9 | |
|
|
aa95d0e87c | |
|
|
6353f0a8e9 | |
|
|
e6327ae9da | |
|
|
4395353c22 | |
|
|
c023ebbdb9 | |
|
|
af3fe53ec8 | |
|
|
e981fb159f | |
|
|
79b9d55854 | |
|
|
b2055a4457 | |
|
|
7bf7e09002 | |
|
|
de8d39ffed | |
|
|
543a7e3962 | |
|
|
9dfe3f5af8 | |
|
|
f11b08d8cb | |
|
|
45b6f08984 | |
|
|
92a4676f8d | |
|
|
7bf7c0bb06 | |
|
|
8f8cf5b704 | |
|
|
6be238430d | |
|
|
f77216d8f4 | |
|
|
d42a9b2409 | |
|
|
6753834054 | |
|
|
77a4a64eb4 | |
|
|
49db40d557 | |
|
|
0032c608f1 | |
|
|
fa603b32b1 |
|
After Width: | Height: | Size: 58 KiB |
|
After Width: | Height: | Size: 163 KiB |
|
After Width: | Height: | Size: 79 KiB |
|
After Width: | Height: | Size: 74 KiB |
|
Before Width: | Height: | Size: 32 KiB After Width: | Height: | Size: 41 KiB |
|
After Width: | Height: | Size: 216 KiB |
|
After Width: | Height: | Size: 54 KiB |
|
|
@ -6,10 +6,10 @@ runs:
|
|||
using: 'composite'
|
||||
steps:
|
||||
- name: Install pnpm
|
||||
uses: pnpm/action-setup@v4
|
||||
uses: pnpm/action-setup@v6
|
||||
|
||||
- name: Install Node.js
|
||||
uses: actions/setup-node@v4
|
||||
uses: actions/setup-node@v6
|
||||
with:
|
||||
node-version-file: .node-version
|
||||
cache: 'pnpm'
|
||||
|
|
|
|||
|
|
@ -30,7 +30,7 @@ jobs:
|
|||
- windows-latest
|
||||
steps:
|
||||
- name: Checkout code
|
||||
uses: actions/checkout@v4
|
||||
uses: actions/checkout@v6
|
||||
with:
|
||||
fetch-depth: 0
|
||||
|
||||
|
|
|
|||
|
|
@ -25,7 +25,7 @@ jobs:
|
|||
|
||||
steps:
|
||||
- name: Checkout code
|
||||
uses: actions/checkout@v4
|
||||
uses: actions/checkout@v6
|
||||
with:
|
||||
fetch-depth: 0
|
||||
|
||||
|
|
|
|||
|
|
@ -28,12 +28,12 @@ jobs:
|
|||
timeout-minutes: 20
|
||||
steps:
|
||||
- name: Checkout code
|
||||
uses: actions/checkout@v4
|
||||
uses: actions/checkout@v6
|
||||
with:
|
||||
fetch-depth: 0
|
||||
|
||||
- name: Install pnpm
|
||||
uses: pnpm/action-setup@v4
|
||||
uses: pnpm/action-setup@v6
|
||||
with:
|
||||
run_install: false
|
||||
|
||||
|
|
@ -67,7 +67,7 @@ jobs:
|
|||
|
||||
steps:
|
||||
- name: Checkout code
|
||||
uses: actions/checkout@v4
|
||||
uses: actions/checkout@v6
|
||||
with:
|
||||
fetch-depth: 0
|
||||
|
||||
|
|
@ -90,7 +90,7 @@ jobs:
|
|||
- windows-latest
|
||||
steps:
|
||||
- name: Checkout code
|
||||
uses: actions/checkout@v4
|
||||
uses: actions/checkout@v6
|
||||
with:
|
||||
fetch-depth: 0
|
||||
|
||||
|
|
|
|||
|
|
@ -57,7 +57,7 @@ jobs:
|
|||
# your codebase is analyzed, see https://docs.github.com/en/code-security/code-scanning/creating-an-advanced-setup-for-code-scanning/codeql-code-scanning-for-compiled-languages
|
||||
steps:
|
||||
- name: Checkout repository
|
||||
uses: actions/checkout@v4
|
||||
uses: actions/checkout@v6
|
||||
|
||||
# Initializes the CodeQL tools for scanning.
|
||||
- name: Initialize CodeQL
|
||||
|
|
|
|||
|
|
@ -12,7 +12,7 @@ jobs:
|
|||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Checkout code
|
||||
uses: actions/checkout@v4
|
||||
uses: actions/checkout@v6
|
||||
with:
|
||||
fetch-depth: 0
|
||||
|
||||
|
|
@ -30,7 +30,7 @@ jobs:
|
|||
run: pnpm build:play
|
||||
|
||||
- name: Sync Playground files
|
||||
uses: SamKirkland/FTP-Deploy-Action@v4.3.6
|
||||
uses: SamKirkland/FTP-Deploy-Action@v4.4.0
|
||||
with:
|
||||
server: ${{ secrets.PRO_FTP_HOST }}
|
||||
username: ${{ secrets.WEB_PLAYGROUND_FTP_ACCOUNT }}
|
||||
|
|
@ -43,7 +43,7 @@ jobs:
|
|||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Checkout code
|
||||
uses: actions/checkout@v4
|
||||
uses: actions/checkout@v6
|
||||
with:
|
||||
fetch-depth: 0
|
||||
|
||||
|
|
@ -54,7 +54,7 @@ jobs:
|
|||
run: pnpm build:docs
|
||||
|
||||
- name: Sync Docs files
|
||||
uses: SamKirkland/FTP-Deploy-Action@v4.3.6
|
||||
uses: SamKirkland/FTP-Deploy-Action@v4.4.0
|
||||
with:
|
||||
server: ${{ secrets.PRO_FTP_HOST }}
|
||||
username: ${{ secrets.WEBSITE_FTP_ACCOUNT }}
|
||||
|
|
@ -67,7 +67,7 @@ jobs:
|
|||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Checkout code
|
||||
uses: actions/checkout@v4
|
||||
uses: actions/checkout@v6
|
||||
with:
|
||||
fetch-depth: 0
|
||||
|
||||
|
|
@ -85,7 +85,7 @@ jobs:
|
|||
run: pnpm run build:antd
|
||||
|
||||
- name: Sync files
|
||||
uses: SamKirkland/FTP-Deploy-Action@v4.3.6
|
||||
uses: SamKirkland/FTP-Deploy-Action@v4.4.0
|
||||
with:
|
||||
server: ${{ secrets.PRO_FTP_HOST }}
|
||||
username: ${{ secrets.WEB_ANTD_FTP_ACCOUNT }}
|
||||
|
|
@ -98,7 +98,7 @@ jobs:
|
|||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Checkout code
|
||||
uses: actions/checkout@v4
|
||||
uses: actions/checkout@v6
|
||||
with:
|
||||
fetch-depth: 0
|
||||
|
||||
|
|
@ -116,7 +116,7 @@ jobs:
|
|||
run: pnpm run build:ele
|
||||
|
||||
- name: Sync files
|
||||
uses: SamKirkland/FTP-Deploy-Action@v4.3.6
|
||||
uses: SamKirkland/FTP-Deploy-Action@v4.4.0
|
||||
with:
|
||||
server: ${{ secrets.PRO_FTP_HOST }}
|
||||
username: ${{ secrets.WEB_ELE_FTP_ACCOUNT }}
|
||||
|
|
@ -129,7 +129,7 @@ jobs:
|
|||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Checkout code
|
||||
uses: actions/checkout@v4
|
||||
uses: actions/checkout@v6
|
||||
with:
|
||||
fetch-depth: 0
|
||||
|
||||
|
|
@ -147,7 +147,7 @@ jobs:
|
|||
run: pnpm run build:naive
|
||||
|
||||
- name: Sync files
|
||||
uses: SamKirkland/FTP-Deploy-Action@v4.3.6
|
||||
uses: SamKirkland/FTP-Deploy-Action@v4.4.0
|
||||
with:
|
||||
server: ${{ secrets.PRO_FTP_HOST }}
|
||||
username: ${{ secrets.WEB_NAIVE_FTP_ACCOUNT }}
|
||||
|
|
|
|||
|
|
@ -20,6 +20,6 @@ jobs:
|
|||
if: github.repository == 'vbenjs/vue-vben-admin'
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: release-drafter/release-drafter@v6
|
||||
- uses: release-drafter/release-drafter@v7
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
|
|
|
|||
|
|
@ -18,7 +18,7 @@ jobs:
|
|||
steps:
|
||||
- name: remove enhancement pending
|
||||
if: github.event.label.name == 'enhancement'
|
||||
uses: actions-cool/issues-helper@v3
|
||||
uses: actions-cool/issues-helper-backup@d65454423c6fbbd20026b9b499d403f79422ac69
|
||||
with:
|
||||
actions: 'remove-labels'
|
||||
token: ${{ secrets.GITHUB_TOKEN }}
|
||||
|
|
@ -27,7 +27,7 @@ jobs:
|
|||
|
||||
- name: remove bug pending
|
||||
if: github.event.label.name == 'bug'
|
||||
uses: actions-cool/issues-helper@v3
|
||||
uses: actions-cool/issues-helper-backup@d65454423c6fbbd20026b9b499d403f79422ac69
|
||||
with:
|
||||
actions: 'remove-labels'
|
||||
token: ${{ secrets.GITHUB_TOKEN }}
|
||||
|
|
@ -36,7 +36,7 @@ jobs:
|
|||
|
||||
- name: needs reproduction
|
||||
if: github.event.label.name == 'needs reproduction'
|
||||
uses: actions-cool/issues-helper@v3
|
||||
uses: actions-cool/issues-helper-backup@d65454423c6fbbd20026b9b499d403f79422ac69
|
||||
with:
|
||||
actions: 'create-comment, remove-labels'
|
||||
token: ${{ secrets.GITHUB_TOKEN }}
|
||||
|
|
|
|||
|
|
@ -3,78 +3,48 @@ name: Create Release Tag
|
|||
on:
|
||||
push:
|
||||
tags:
|
||||
- 'v*.*.*' # Push events to matching v*, i.e. v1.0, v20.15.10
|
||||
|
||||
env:
|
||||
HUSKY: '0'
|
||||
- 'v*.*.*'
|
||||
workflow_dispatch:
|
||||
inputs:
|
||||
tag:
|
||||
description: 'Tag to create (e.g. v1.2.3)'
|
||||
required: true
|
||||
type: string
|
||||
|
||||
permissions:
|
||||
pull-requests: write
|
||||
contents: write
|
||||
|
||||
jobs:
|
||||
build:
|
||||
release:
|
||||
name: Create Release
|
||||
if: github.repository == 'vbenjs/vue-vben-admin'
|
||||
runs-on: ubuntu-latest
|
||||
strategy:
|
||||
matrix:
|
||||
node-version: [20]
|
||||
steps:
|
||||
- name: Checkout code
|
||||
uses: actions/checkout@v4
|
||||
uses: actions/checkout@v6
|
||||
with:
|
||||
fetch-depth: 0
|
||||
|
||||
# - name: Checkout code
|
||||
# uses: actions/checkout@v4
|
||||
# with:
|
||||
# fetch-depth: 0
|
||||
|
||||
# - name: Install pnpm
|
||||
# uses: pnpm/action-setup@v4
|
||||
|
||||
# - name: Use Node.js ${{ matrix.node-version }}
|
||||
# uses: actions/setup-node@v4
|
||||
# with:
|
||||
# node-version: ${{ matrix.node-version }}
|
||||
# cache: "pnpm"
|
||||
|
||||
# - name: Install dependencies
|
||||
# run: pnpm install --frozen-lockfile
|
||||
|
||||
# - name: Test and Build
|
||||
# run: |
|
||||
# pnpm run test
|
||||
# pnpm run build
|
||||
|
||||
- name: version
|
||||
- name: Extract version
|
||||
id: version
|
||||
run: |
|
||||
tag=${GITHUB_REF/refs\/tags\//}
|
||||
version=${tag#v}
|
||||
major=${version%%.*}
|
||||
echo "tag=${tag}" >> $GITHUB_OUTPUT
|
||||
echo "version=${version}" >> $GITHUB_OUTPUT
|
||||
echo "major=${major}" >> $GITHUB_OUTPUT
|
||||
if [[ "${{ github.event_name }}" == "workflow_dispatch" ]]; then
|
||||
raw_tag="${{ inputs.tag }}"
|
||||
else
|
||||
raw_tag="${GITHUB_REF_NAME}"
|
||||
fi
|
||||
# Normalize: ensure v prefix
|
||||
tag="${raw_tag}"
|
||||
[[ "${tag:0:1}" != "v" ]] && tag="v${tag}"
|
||||
version="${tag#v}"
|
||||
major="${version%%.*}"
|
||||
echo "tag=${tag}" >> "${GITHUB_OUTPUT}"
|
||||
echo "version=${version}" >> "${GITHUB_OUTPUT}"
|
||||
echo "major=${major}" >> "${GITHUB_OUTPUT}"
|
||||
|
||||
- uses: release-drafter/release-drafter@v6
|
||||
- uses: release-drafter/release-drafter@v7
|
||||
with:
|
||||
version: ${{ steps.version.outputs.version }}
|
||||
publish: true
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
|
||||
# - name: force update major tag
|
||||
# run: |
|
||||
# git tag v${{ steps.version.outputs.major }} ${{ steps.version.outputs.tag }} -f
|
||||
# git push origin refs/tags/v${{ steps.version.outputs.major }} -f
|
||||
|
||||
# - name: Create Release for Tag
|
||||
# id: release_tag
|
||||
# uses: ncipollo/release-action@v1
|
||||
# with:
|
||||
# token: ${{ secrets.GITHUB_TOKEN }}
|
||||
# generateReleaseNotes: "true"
|
||||
# body: |
|
||||
# > Please refer to [CHANGELOG.md](https://github.com/vbenjs/vue-vben-admin/blob/main/CHANGELOG.md) for details.
|
||||
|
|
|
|||
|
|
@ -22,7 +22,8 @@ yarn.lock
|
|||
package-lock.json
|
||||
.VSCodeCounter
|
||||
**/backend-mock/data
|
||||
|
||||
.omx
|
||||
.pnpm-store
|
||||
# local env files
|
||||
.env.local
|
||||
.env.*.local
|
||||
|
|
@ -50,3 +51,12 @@ vite.config.ts.*
|
|||
*.sw?
|
||||
.history
|
||||
.cursor
|
||||
|
||||
# AI
|
||||
.agent
|
||||
.agents
|
||||
.claude
|
||||
.codex
|
||||
skills-lock.json
|
||||
.atomcode
|
||||
datalog
|
||||
|
|
|
|||
|
|
@ -1 +1 @@
|
|||
22.1.0
|
||||
22.22.0
|
||||
|
|
|
|||
12
.npmrc
|
|
@ -1,13 +1 @@
|
|||
registry=https://registry.npmmirror.com
|
||||
public-hoist-pattern[]=lefthook
|
||||
public-hoist-pattern[]=eslint
|
||||
public-hoist-pattern[]=prettier
|
||||
public-hoist-pattern[]=prettier-plugin-tailwindcss
|
||||
public-hoist-pattern[]=stylelint
|
||||
public-hoist-pattern[]=*postcss*
|
||||
public-hoist-pattern[]=@commitlint/*
|
||||
public-hoist-pattern[]=czg
|
||||
|
||||
strict-peer-dependencies=false
|
||||
auto-install-peers=true
|
||||
dedupe-peer-dependents=true
|
||||
|
|
|
|||
|
|
@ -1,18 +0,0 @@
|
|||
dist
|
||||
dev-dist
|
||||
.local
|
||||
.output.js
|
||||
node_modules
|
||||
.nvmrc
|
||||
coverage
|
||||
CODEOWNERS
|
||||
.nitro
|
||||
.output
|
||||
|
||||
|
||||
**/*.svg
|
||||
**/*.sh
|
||||
|
||||
public
|
||||
.npmrc
|
||||
*-lock.yaml
|
||||
|
|
@ -1 +0,0 @@
|
|||
export { default } from '@vben/prettier-config';
|
||||
|
|
@ -2,3 +2,7 @@ dist
|
|||
public
|
||||
__tests__
|
||||
coverage
|
||||
.codex
|
||||
.claude
|
||||
.agent
|
||||
.agents
|
||||
|
|
|
|||
|
|
@ -2,14 +2,18 @@
|
|||
"recommendations": [
|
||||
// Vue 3 的语言支持
|
||||
"Vue.volar",
|
||||
// 将 ESLint JavaScript 集成到 VS Code 中。
|
||||
// 将 eslint 集成到 VS Code 中。
|
||||
"dbaeumer.vscode-eslint",
|
||||
// 将 oxlint 集成到 VS Code 中。
|
||||
"oxc.oxc-vscode",
|
||||
// Visual Studio Code 的官方 Stylelint 扩展
|
||||
"stylelint.vscode-stylelint",
|
||||
// 使用 Prettier 的代码格式化程序
|
||||
"esbenp.prettier-vscode",
|
||||
// 使用 oxfmt 的代码格式化程序
|
||||
"oxc.oxc-vscode",
|
||||
// 支持 dotenv 文件语法
|
||||
"mikestead.dotenv",
|
||||
// YAML 语言支持,供 ESLint 校验 pnpm-workspace.yaml 等文件
|
||||
"redhat.vscode-yaml",
|
||||
// 源代码的拼写检查器
|
||||
"streetsidesoftware.code-spell-checker",
|
||||
// Tailwind CSS 的官方 VS Code 插件
|
||||
|
|
|
|||
|
|
@ -2,6 +2,15 @@
|
|||
"$schema": "https://json.schemastore.org/launchsettings.json",
|
||||
"version": "0.2.0",
|
||||
"configurations": [
|
||||
{
|
||||
"type": "chrome",
|
||||
"name": "vben admin antd dev",
|
||||
"request": "launch",
|
||||
"url": "http://localhost:5999",
|
||||
"env": { "NODE_ENV": "development" },
|
||||
"sourceMaps": true,
|
||||
"webRoot": "${workspaceFolder}/apps/web-antdv-next"
|
||||
},
|
||||
{
|
||||
"type": "chrome",
|
||||
"name": "vben admin antd dev",
|
||||
|
|
|
|||
|
|
@ -1,5 +1,6 @@
|
|||
{
|
||||
"tailwindCSS.experimental.configFile": "internal/tailwind-config/src/index.ts",
|
||||
"tailwindCSS.experimental.configFile": "internal/tailwind-config/src/theme.css",
|
||||
"tailwindCSS.lint.suggestCanonicalClasses": "ignore",
|
||||
// workbench
|
||||
"workbench.list.smoothScrolling": true,
|
||||
"workbench.startupEditor": "newUntitledFile",
|
||||
|
|
@ -31,39 +32,51 @@
|
|||
"editor.autoClosingOvertype": "always",
|
||||
"editor.autoClosingQuotes": "beforeWhitespace",
|
||||
"editor.wordSeparators": "`~!@#%^&*()=+[{]}\\|;:'\",.<>/?",
|
||||
"editor.quickSuggestions": {
|
||||
"strings": "on"
|
||||
},
|
||||
|
||||
// lint && format
|
||||
"oxc.enable": true,
|
||||
"oxc.typeAware": false,
|
||||
"oxc.configPath": "oxlint.config.ts",
|
||||
"oxc.fmt.configPath": "oxfmt.config.ts",
|
||||
"eslint.useFlatConfig": true,
|
||||
"editor.codeActionsOnSave": {
|
||||
"source.fixAll.eslint": "explicit",
|
||||
"source.fixAll.oxc": "explicit",
|
||||
"source.fixAll.stylelint": "explicit",
|
||||
"source.organizeImports": "never"
|
||||
},
|
||||
"editor.defaultFormatter": "esbenp.prettier-vscode",
|
||||
"editor.defaultFormatter": "oxc.oxc-vscode",
|
||||
"[html]": {
|
||||
"editor.defaultFormatter": "esbenp.prettier-vscode"
|
||||
"editor.defaultFormatter": "oxc.oxc-vscode"
|
||||
},
|
||||
"[css]": {
|
||||
"editor.defaultFormatter": "esbenp.prettier-vscode"
|
||||
"editor.defaultFormatter": "oxc.oxc-vscode"
|
||||
},
|
||||
"[scss]": {
|
||||
"editor.defaultFormatter": "esbenp.prettier-vscode"
|
||||
"editor.defaultFormatter": "oxc.oxc-vscode"
|
||||
},
|
||||
"[javascript]": {
|
||||
"editor.defaultFormatter": "esbenp.prettier-vscode"
|
||||
"editor.defaultFormatter": "oxc.oxc-vscode"
|
||||
},
|
||||
"[typescript]": {
|
||||
"editor.defaultFormatter": "esbenp.prettier-vscode"
|
||||
"editor.defaultFormatter": "oxc.oxc-vscode"
|
||||
},
|
||||
"[json]": {
|
||||
"editor.defaultFormatter": "esbenp.prettier-vscode"
|
||||
"editor.defaultFormatter": "oxc.oxc-vscode"
|
||||
},
|
||||
"[markdown]": {
|
||||
"editor.defaultFormatter": "esbenp.prettier-vscode"
|
||||
"editor.defaultFormatter": "oxc.oxc-vscode"
|
||||
},
|
||||
"[jsonc]": {
|
||||
"editor.defaultFormatter": "esbenp.prettier-vscode"
|
||||
"editor.defaultFormatter": "oxc.oxc-vscode"
|
||||
},
|
||||
"[vue]": {
|
||||
"editor.defaultFormatter": "esbenp.prettier-vscode"
|
||||
"editor.defaultFormatter": "oxc.oxc-vscode"
|
||||
},
|
||||
|
||||
// extensions
|
||||
"extensions.ignoreRecommendations": true,
|
||||
|
||||
|
|
@ -79,6 +92,7 @@
|
|||
"files.insertFinalNewline": true,
|
||||
"files.simpleDialog.enable": true,
|
||||
"files.associations": {
|
||||
"*.css": "tailwindcss",
|
||||
"*.ejs": "html",
|
||||
"*.art": "html",
|
||||
"**/tsconfig.json": "jsonc",
|
||||
|
|
@ -118,7 +132,7 @@
|
|||
// search
|
||||
"search.searchEditor.singleClickBehaviour": "peekDefinition",
|
||||
"search.followSymlinks": false,
|
||||
// 在使用搜索功能时,将这些文件夹/文件排除在外
|
||||
// 使用搜索功能时,将这些文件和文件夹排除在外
|
||||
"search.exclude": {
|
||||
"**/node_modules": true,
|
||||
"**/*.log": true,
|
||||
|
|
@ -159,7 +173,7 @@
|
|||
"emmet.triggerExpansionOnTab": false,
|
||||
|
||||
"errorLens.enabledDiagnosticLevels": ["warning", "error"],
|
||||
"errorLens.excludeBySource": ["cSpell", "Grammarly", "eslint"],
|
||||
"errorLens.excludeBySource": ["cSpell", "Grammarly"],
|
||||
|
||||
"stylelint.enable": true,
|
||||
"stylelint.packageManager": "pnpm",
|
||||
|
|
@ -167,9 +181,10 @@
|
|||
"stylelint.customSyntax": "postcss-html",
|
||||
"stylelint.snippet": ["css", "less", "postcss", "scss", "vue"],
|
||||
|
||||
"typescript.inlayHints.enumMemberValues.enabled": true,
|
||||
"typescript.preferences.preferTypeOnlyAutoImports": true,
|
||||
"typescript.preferences.includePackageJsonAutoImports": "on",
|
||||
"js/ts.tsdk.path": "node_modules/typescript/lib",
|
||||
"js/ts.inlayHints.enumMemberValues.enabled": true,
|
||||
"js/ts.preferences.preferTypeOnlyAutoImports": true,
|
||||
"js/ts.preferences.includePackageJsonAutoImports": "on",
|
||||
|
||||
"eslint.validate": [
|
||||
"javascript",
|
||||
|
|
@ -181,7 +196,8 @@
|
|||
"markdown",
|
||||
"json",
|
||||
"jsonc",
|
||||
"json5"
|
||||
"json5",
|
||||
"yaml"
|
||||
],
|
||||
|
||||
"tailwindCSS.experimental.classRegex": [
|
||||
|
|
@ -192,7 +208,7 @@
|
|||
"*": false
|
||||
},
|
||||
|
||||
"cssVariables.lookupFiles": ["packages/core/base/design/src/**/*.css"],
|
||||
"cssVariables.lookupFiles": ["packages/@core/base/design/src/**/*.css"],
|
||||
|
||||
"i18n-ally.localesPaths": [
|
||||
"packages/locales/src/langs",
|
||||
|
|
@ -217,12 +233,9 @@
|
|||
"*.env": "$(capture).env.*",
|
||||
"README.md": "README*,CHANGELOG*,LICENSE,CNAME",
|
||||
"package.json": "pnpm-lock.yaml,pnpm-workspace.yaml,.gitattributes,.gitignore,.gitpod.yml,.npmrc,.browserslistrc,.node-version,.git*,.tazerc.json",
|
||||
"eslint.config.mjs": ".eslintignore,.prettierignore,.stylelintignore,.commitlintrc.*,.prettierrc.*,stylelint.config.*,.lintstagedrc.mjs,cspell.json,lefthook.yml",
|
||||
"tailwind.config.mjs": "postcss.*"
|
||||
"oxlint.config.ts": ".eslintignore,.stylelintignore,.commitlintrc.*,stylelint.config.*,.lintstagedrc.mjs,cspell.json,lefthook.yml,oxfmt.config.*,eslint.config.*"
|
||||
},
|
||||
"commentTranslate.hover.enabled": false,
|
||||
"commentTranslate.multiLineMerge": true,
|
||||
"vue.server.hybridMode": true,
|
||||
"typescript.tsdk": "node_modules/typescript/lib",
|
||||
"oxc.enable": false
|
||||
"vue.server.hybridMode": true
|
||||
}
|
||||
|
|
|
|||
234
README.md
|
|
@ -9,7 +9,7 @@
|
|||
|
||||
## 🐶 新手必读
|
||||
|
||||
- nodejs > 20.12.0 && pnpm > 10.22.0 (强制使用pnpm)
|
||||
- nodejs >= v20.19.0(推荐 v22 / v24) && pnpm >= 10.32.1(强制使用 pnpm)
|
||||
- 演示地址【Vue3 + element-plus】:<http://dashboard-vue3.yudao.iocoder.cn>
|
||||
- 演示地址【Vue3 + vben5(ant-design-vue)】:<http://dashboard-vben.yudao.iocoder.cn>
|
||||
- 演示地址【Vue2 + element-ui】:<http://dashboard.yudao.iocoder.cn>
|
||||
|
|
@ -20,12 +20,12 @@
|
|||
|
||||
**芋道**,以开发者为中心,打造中国第一流的快速开发平台,全部开源,个人与企业可 100% 免费使用。
|
||||
|
||||
- 采用最新 [vue-vben-admin](https://github.com/vbenjs/vue-vben-admin) v5 实现
|
||||
- 采用最新 [vue-vben-admin](https://github.com/vbenjs/vue-vben-admin) v5.7.0 实现
|
||||
- 支持 [Ant Design Vue](https://www.antdv.com/) | [Element Plus](https://element-plus.org/zh-CN/) | [Naive UI](https://www.naiveui.com/) | [TDesign](https://tdesign.tencent.com/) 多种免费开源的中后台模版,具备如下特性:
|
||||
|
||||

|
||||
|
||||
- **最新技术栈**:使用 Vue3、Vite6 等前端前沿技术开发
|
||||
- **最新技术栈**:使用 Vue3、Vite8 等前端前沿技术开发
|
||||
- **TypeScript**: 应用程序级 JavaScript 的语言
|
||||
- **主题**: 提供多套主题色彩,可配置自定义主题
|
||||
- **国际化**:内置完善的国际化方案
|
||||
|
|
@ -33,7 +33,7 @@
|
|||
- **组件**:二次封装了多个常用的组件
|
||||
- **示例**:内置丰富的示例
|
||||
|
||||
## [外包项目请联系【非项目需求请勿扫码,非客服,不解答项目问题】](https://www.shuduokeji.com)
|
||||
## [外包项目请联系【非项目需求请勿扫码,非客服,不解答项目问题】](https://www.shuduokeji.com?yudao)
|
||||
|
||||

|
||||
|
||||
|
|
@ -41,26 +41,26 @@
|
|||
|
||||
| 框架 | 说明 | 版本 |
|
||||
| --- | --- | --- |
|
||||
| [Vue](https://staging-cn.vuejs.org/) | vue框架 | 3.5.24 |
|
||||
| [Vite](https://cn.vitejs.dev//) | 开发与构建工具 | 7.2.2 |
|
||||
| [Vue](https://staging-cn.vuejs.org/) | vue框架 | 3.5.30 |
|
||||
| [Vite](https://cn.vitejs.dev//) | 开发与构建工具 | 8.0.0 |
|
||||
| [Ant Design Vue](https://www.antdv.com/) | Ant Design Vue | 4.2.6 |
|
||||
| [Element Plus](https://element-plus.org/zh-CN/) | Element Plus | 2.10.2 |
|
||||
| [Naive UI](https://www.naiveui.com/) | Naive UI | 2.42.0 |
|
||||
| [TDesign](https://tdesign.tencent.com/) | TDesign | 1.17.1 |
|
||||
| [Element Plus](https://element-plus.org/zh-CN/) | Element Plus | 2.13.5 |
|
||||
| [Naive UI](https://www.naiveui.com/) | Naive UI | 2.44.1 |
|
||||
| [TDesign](https://tdesign.tencent.com/) | TDesign | 1.18.5 |
|
||||
| [TypeScript](https://www.typescriptlang.org/docs/) | JavaScript 超集 | 5.9.3 |
|
||||
| [pinia](https://pinia.vuejs.org/) | Vue 存储库替代 vuex5 | 3.0.3 |
|
||||
| [vueuse](https://vueuse.org/) | 常用工具集 | 13.4.0 |
|
||||
| [vue-i18n](https://kazupon.github.io/vue-i18n/zh/introduction.html/) | 国际化 | 11.1.7 |
|
||||
| [vue-router](https://router.vuejs.org/) | Vue 路由 | 4.5.1 |
|
||||
| [Tailwind CSS](https://tailwindcss.com/) | 原子 CSS | 3.4.18 |
|
||||
| [pinia](https://pinia.vuejs.org/) | Vue 存储库替代 vuex5 | 3.0.4 |
|
||||
| [vueuse](https://vueuse.org/) | 常用工具集 | 14.2.1 |
|
||||
| [vue-i18n](https://kazupon.github.io/vue-i18n/zh/introduction.html/) | 国际化 | 11.3.0 |
|
||||
| [vue-router](https://router.vuejs.org/) | Vue 路由 | 5.0.3 |
|
||||
| [Tailwind CSS](https://tailwindcss.com/) | 原子 CSS | 4.2.1 |
|
||||
| [Iconify](https://iconify.design/) | 图标组件 | 5.0.0 |
|
||||
| [Iconify](https://icon-sets.iconify.design/) | 在线图标库 | 2.2.406 |
|
||||
| [TinyMCE](https://www.tiny.cloud/) | 富文本编辑器 | 6.1.0 |
|
||||
| [Iconify](https://icon-sets.iconify.design/) | 在线图标库 | 2.2.449 |
|
||||
| [TinyMCE](https://www.tiny.cloud/) | 富文本编辑器 | 7.3.0 |
|
||||
| [Echarts](https://echarts.apache.org/) | 图表库 | 6.0.0 |
|
||||
| [axios](https://axios-http.com/) | http客户端 | 1.10.0 |
|
||||
| [dayjs](https://day.js.org/) | 日期处理库 | 1.11.13 |
|
||||
| [axios](https://axios-http.com/) | http客户端 | 1.13.6 |
|
||||
| [dayjs](https://day.js.org/) | 日期处理库 | 1.11.20 |
|
||||
| [vee-validate](https://vee-validate.logaretm.com/) | 表单验证 | 4.15.1 |
|
||||
| [zod](https://zod.dev/) | 数据验证 | 3.25.67 |
|
||||
| [zod](https://zod.dev/) | 数据验证 | 3.25.76 |
|
||||
|
||||
## 🔥 后端架构
|
||||
|
||||
|
|
@ -84,31 +84,31 @@
|
|||
|
||||
- 通用模块(必选):系统功能、基础设施
|
||||
- 通用模块(可选):工作流程、支付系统、数据报表、会员中心
|
||||
- 业务系统(按需):ERP 系统、CRM 系统、商城系统、微信公众号、AI 大模型
|
||||
- 业务系统(按需):Mall 电子商城、OA 办公自动化、ERP 企业资源计划系统、WMS 仓库管理系统、CRM 客户关系管理、CMS 内容管理系统、MES 执行制造系统、AI 大模型平台、IoT 物联网系统、IM 即时通讯系统、Mobile 手机移动端、Report 数据大屏
|
||||
|
||||
### 系统功能
|
||||
|
||||
| | 功能 | 描述 |
|
||||
|----|-------|---------------------------------|
|
||||
| | 用户管理 | 用户是系统操作者,该功能主要完成系统用户配置 |
|
||||
| ⭐️ | 在线用户 | 当前系统中活跃用户状态监控,支持手动踢下线 |
|
||||
| | 角色管理 | 角色菜单权限分配、设置角色按机构进行数据范围权限划分 |
|
||||
| | 菜单管理 | 配置系统菜单、操作权限、按钮权限标识等,本地缓存提供性能 |
|
||||
| | 部门管理 | 配置系统组织机构(公司、部门、小组),树结构展现支持数据权限 |
|
||||
| | 岗位管理 | 配置系统用户所属担任职务 |
|
||||
| 🚀 | 租户管理 | 配置系统租户,支持 SaaS 场景下的多租户功能 |
|
||||
| 🚀 | 租户套餐 | 配置租户套餐,自定每个租户的菜单、操作、按钮的权限 |
|
||||
| | 字典管理 | 对系统中经常使用的一些较为固定的数据进行维护 |
|
||||
| 🚀 | 短信管理 | 短信渠道、短息模板、短信日志,对接阿里云、腾讯云等主流短信平台 |
|
||||
| 🚀 | 邮件管理 | 邮箱账号、邮件模版、邮件发送日志,支持所有邮件平台 |
|
||||
| 🚀 | 站内信 | 系统内的消息通知,提供站内信模版、站内信消息 |
|
||||
| 🚀 | 操作日志 | 系统正常操作日志记录和查询,集成 Swagger 生成日志内容 |
|
||||
| ⭐️ | 登录日志 | 系统登录日志记录查询,包含登录异常 |
|
||||
| 🚀 | 错误码管理 | 系统所有错误码的管理,可在线修改错误提示,无需重启服务 |
|
||||
| | 通知公告 | 系统通知公告信息发布维护 |
|
||||
| 🚀 | 敏感词 | 配置系统敏感词,支持标签分组 |
|
||||
| 🚀 | 应用管理 | 管理 SSO 单点登录的应用,支持多种 OAuth2 授权方式 |
|
||||
| 🚀 | 地区管理 | 展示省份、城市、区镇等城市信息,支持 IP 对应城市 |
|
||||
| | 功能 | 描述 |
|
||||
| --- | --- | --- |
|
||||
| | 用户管理 | 用户是系统操作者,该功能主要完成系统用户配置 |
|
||||
| ⭐️ | 在线用户 | 当前系统中活跃用户状态监控,支持手动踢下线 |
|
||||
| | 角色管理 | 角色菜单权限分配、设置角色按机构进行数据范围权限划分 |
|
||||
| | 菜单管理 | 配置系统菜单、操作权限、按钮权限标识等,本地缓存提供性能 |
|
||||
| | 部门管理 | 配置系统组织机构(公司、部门、小组),树结构展现支持数据权限 |
|
||||
| | 岗位管理 | 配置系统用户所属担任职务 |
|
||||
| 🚀 | 租户管理 | 配置系统租户,支持 SaaS 场景下的多租户功能 |
|
||||
| 🚀 | 租户套餐 | 配置租户套餐,自定每个租户的菜单、操作、按钮的权限 |
|
||||
| | 字典管理 | 对系统中经常使用的一些较为固定的数据进行维护 |
|
||||
| 🚀 | 短信管理 | 短信渠道、短息模板、短信日志,对接阿里云、腾讯云等主流短信平台 |
|
||||
| 🚀 | 邮件管理 | 邮箱账号、邮件模版、邮件发送日志,支持所有邮件平台 |
|
||||
| 🚀 | 站内信 | 系统内的消息通知,提供站内信模版、站内信消息 |
|
||||
| 🚀 | 操作日志 | 系统正常操作日志记录和查询,集成 Swagger 生成日志内容 |
|
||||
| ⭐️ | 登录日志 | 系统登录日志记录查询,包含登录异常 |
|
||||
| 🚀 | 错误码管理 | 系统所有错误码的管理,可在线修改错误提示,无需重启服务 |
|
||||
| | 通知公告 | 系统通知公告信息发布维护 |
|
||||
| 🚀 | 敏感词 | 配置系统敏感词,支持标签分组 |
|
||||
| 🚀 | 应用管理 | 管理 SSO 单点登录的应用,支持多种 OAuth2 授权方式 |
|
||||
| 🚀 | 地区管理 | 展示省份、城市、区镇等城市信息,支持 IP 对应城市 |
|
||||
|
||||

|
||||
|
||||
|
|
@ -126,32 +126,32 @@
|
|||
>
|
||||
> 前者支持轻量配置简单流程,后者实现复杂场景深度编排
|
||||
|
||||
| 功能列表 | 功能描述 | 是否完成 |
|
||||
|------------|-------------------------------------------------------------------------------------|------|
|
||||
| SIMPLE 设计器 | 仿钉钉/飞书设计器,支持拖拽搭建表单流程,10 分钟快速完成审批流程配置 | ✅ |
|
||||
| BPMN 设计器 | 基于 BPMN 标准开发,适配复杂业务场景,满足多层级审批及流程自动化需求 | ✅ |
|
||||
| 会签 | 同一个审批节点设置多个人(如 A、B、C 三人,三人会同时收到待办任务),需全部同意之后,审批才可到下一审批节点 | ✅ |
|
||||
| 或签 | 同一个审批节点设置多个人,任意一个人处理后,就能进入下一个节点 | ✅ |
|
||||
| 依次审批 | (顺序会签)同一个审批节点设置多个人(如 A、B、C 三人),三人按顺序依次收到待办,即 A 先审批,A 提交后 B 才能审批,需全部同意之后,审批才可到下一审批节点 | ✅ |
|
||||
| 抄送 | 将审批结果通知给抄送人,同一个审批默认排重,不重复抄送给同一人 | ✅ |
|
||||
| 驳回 | (退回)将审批重置发送给某节点,重新审批。可驳回至发起人、上一节点、任意节点 | ✅ |
|
||||
| 转办 | A 转给其 B 审批,B 审批后,进入下一节点 | ✅ |
|
||||
| 委派 | A 转给其 B 审批,B 审批后,转给 A,A 继续审批后进入下一节点 | ✅ |
|
||||
| 加签 | 允许当前审批人根据需要,自行增加当前节点的审批人,支持向前、向后加签 | ✅ |
|
||||
| 减签 | (取消加签)在当前审批人操作之前,减少审批人 | ✅ |
|
||||
| 撤销 | (取消流程)流程发起人,可以对流程进行撤销处理 | ✅ |
|
||||
| 终止 | 系统管理员,在任意节点终止流程实例 | ✅ |
|
||||
| 表单权限 | 支持拖拉拽配置表单,每个审批节点可配置只读、编辑、隐藏权限 | ✅ |
|
||||
| 超时审批 | 配置超时审批时间,超时后自动触发审批通过、不通过、驳回等操作 | ✅ |
|
||||
| 自动提醒 | 配置提醒时间,到达时间后自动触发短信、邮箱、站内信等通知提醒,支持自定义重复提醒频次 | ✅ |
|
||||
| 父子流程 | 主流程设置子流程节点,子流程节点会自动触发子流程。子流程结束后,主流程才会执行(继续往下下执行),支持同步子流程、异步子流程 | ✅ |
|
||||
| 条件分支 | (排它分支)用于在流程中实现决策,即根据条件选择一个分支执行 | ✅ |
|
||||
| 并行分支 | 允许将流程分成多条分支,不进行条件判断,所有分支都会执行 | ✅ |
|
||||
| 包容分支 | (条件分支 + 并行分支的结合体)允许基于条件选择多条分支执行,但如果没有任何一个分支满足条件,则可以选择默认分支 | ✅ |
|
||||
| 路由分支 | 根据条件选择一个分支执行(重定向到指定配置节点),也可以选择默认分支执行(继续往下执行) | ✅ |
|
||||
| 触发节点 | 执行到该节点,触发 HTTP 请求、HTTP 回调、更新数据、删除数据等 | ✅ |
|
||||
| 延迟节点 | 执行到该节点,审批等待一段时间再执行,支持固定时长、固定日期等 | ✅ |
|
||||
| 拓展设置 | 流程前置/后置通知,节点(任务)前置、后置通知,流程报表,自动审批去重,自定流程编号、标题、摘要,流程报表等 | ✅ |
|
||||
| 功能列表 | 功能描述 | 是否完成 |
|
||||
| --- | --- | --- |
|
||||
| SIMPLE 设计器 | 仿钉钉/飞书设计器,支持拖拽搭建表单流程,10 分钟快速完成审批流程配置 | ✅ |
|
||||
| BPMN 设计器 | 基于 BPMN 标准开发,适配复杂业务场景,满足多层级审批及流程自动化需求 | ✅ |
|
||||
| 会签 | 同一个审批节点设置多个人(如 A、B、C 三人,三人会同时收到待办任务),需全部同意之后,审批才可到下一审批节点 | ✅ |
|
||||
| 或签 | 同一个审批节点设置多个人,任意一个人处理后,就能进入下一个节点 | ✅ |
|
||||
| 依次审批 | (顺序会签)同一个审批节点设置多个人(如 A、B、C 三人),三人按顺序依次收到待办,即 A 先审批,A 提交后 B 才能审批,需全部同意之后,审批才可到下一审批节点 | ✅ |
|
||||
| 抄送 | 将审批结果通知给抄送人,同一个审批默认排重,不重复抄送给同一人 | ✅ |
|
||||
| 驳回 | (退回)将审批重置发送给某节点,重新审批。可驳回至发起人、上一节点、任意节点 | ✅ |
|
||||
| 转办 | A 转给其 B 审批,B 审批后,进入下一节点 | ✅ |
|
||||
| 委派 | A 转给其 B 审批,B 审批后,转给 A,A 继续审批后进入下一节点 | ✅ |
|
||||
| 加签 | 允许当前审批人根据需要,自行增加当前节点的审批人,支持向前、向后加签 | ✅ |
|
||||
| 减签 | (取消加签)在当前审批人操作之前,减少审批人 | ✅ |
|
||||
| 撤销 | (取消流程)流程发起人,可以对流程进行撤销处理 | ✅ |
|
||||
| 终止 | 系统管理员,在任意节点终止流程实例 | ✅ |
|
||||
| 表单权限 | 支持拖拉拽配置表单,每个审批节点可配置只读、编辑、隐藏权限 | ✅ |
|
||||
| 超时审批 | 配置超时审批时间,超时后自动触发审批通过、不通过、驳回等操作 | ✅ |
|
||||
| 自动提醒 | 配置提醒时间,到达时间后自动触发短信、邮箱、站内信等通知提醒,支持自定义重复提醒频次 | ✅ |
|
||||
| 父子流程 | 主流程设置子流程节点,子流程节点会自动触发子流程。子流程结束后,主流程才会执行(继续往下下执行),支持同步子流程、异步子流程 | ✅ |
|
||||
| 条件分支 | (排它分支)用于在流程中实现决策,即根据条件选择一个分支执行 | ✅ |
|
||||
| 并行分支 | 允许将流程分成多条分支,不进行条件判断,所有分支都会执行 | ✅ |
|
||||
| 包容分支 | (条件分支 + 并行分支的结合体)允许基于条件选择多条分支执行,但如果没有任何一个分支满足条件,则可以选择默认分支 | ✅ |
|
||||
| 路由分支 | 根据条件选择一个分支执行(重定向到指定配置节点),也可以选择默认分支执行(继续往下执行) | ✅ |
|
||||
| 触发节点 | 执行到该节点,触发 HTTP 请求、HTTP 回调、更新数据、删除数据等 | ✅ |
|
||||
| 延迟节点 | 执行到该节点,审批等待一段时间再执行,支持固定时长、固定日期等 | ✅ |
|
||||
| 拓展设置 | 流程前置/后置通知,节点(任务)前置、后置通知,流程报表,自动审批去重,自定流程编号、标题、摘要,流程报表等 | ✅ |
|
||||
|
||||
### 支付系统
|
||||
|
||||
|
|
@ -165,26 +165,26 @@
|
|||
|
||||
### 基础设施
|
||||
|
||||
| | 功能 | 描述 |
|
||||
|----|-----------|----------------------------------------------|
|
||||
| 🚀 | 代码生成 | 前后端代码的生成(Java、Vue、SQL、单元测试),支持 CRUD 下载 |
|
||||
| 🚀 | 系统接口 | 基于 Swagger 自动生成相关的 RESTful API 接口文档 |
|
||||
| 🚀 | 数据库文档 | 基于 Screw 自动生成数据库文档,支持导出 Word、HTML、MD 格式 |
|
||||
| | 表单构建 | 拖动表单元素生成相应的 HTML 代码,支持导出 JSON、Vue 文件 |
|
||||
| 🚀 | 配置管理 | 对系统动态配置常用参数,支持 SpringBoot 加载 |
|
||||
| ⭐️ | 定时任务 | 在线(添加、修改、删除)任务调度包含执行结果日志 |
|
||||
| 🚀 | 文件服务 | 支持将文件存储到 S3(MinIO、阿里云、腾讯云、七牛云)、本地、FTP、数据库等 |
|
||||
| 🚀 | WebSocket | 提供 WebSocket 接入示例,支持一对一、一对多发送方式 |
|
||||
| 🚀 | API 日志 | 包括 RESTful API 访问日志、异常日志两部分,方便排查 API 相关的问题 |
|
||||
| | MySQL 监控 | 监视当前系统数据库连接池状态,可进行分析SQL找出系统性能瓶颈 |
|
||||
| | Redis 监控 | 监控 Redis 数据库的使用情况,使用的 Redis Key 管理 |
|
||||
| 🚀 | 消息队列 | 基于 Redis 实现消息队列,Stream 提供集群消费,Pub/Sub 提供广播消费 |
|
||||
| 🚀 | Java 监控 | 基于 Spring Boot Admin 实现 Java 应用的监控 |
|
||||
| 🚀 | 链路追踪 | 接入 SkyWalking 组件,实现链路追踪 |
|
||||
| 🚀 | 日志中心 | 接入 SkyWalking 组件,实现日志中心 |
|
||||
| 🚀 | 服务保障 | 基于 Redis 实现分布式锁、幂等、限流功能,满足高并发场景 |
|
||||
| 🚀 | 日志服务 | 轻量级日志中心,查看远程服务器的日志 |
|
||||
| 🚀 | 单元测试 | 基于 JUnit + Mockito 实现单元测试,保证功能的正确性、代码的质量等 |
|
||||
| | 功能 | 描述 |
|
||||
| --- | --- | --- |
|
||||
| 🚀 | 代码生成 | 前后端代码的生成(Java、Vue、SQL、单元测试),支持 CRUD 下载 |
|
||||
| 🚀 | 系统接口 | 基于 Swagger 自动生成相关的 RESTful API 接口文档 |
|
||||
| 🚀 | 数据库文档 | 基于 Screw 自动生成数据库文档,支持导出 Word、HTML、MD 格式 |
|
||||
| | 表单构建 | 拖动表单元素生成相应的 HTML 代码,支持导出 JSON、Vue 文件 |
|
||||
| 🚀 | 配置管理 | 对系统动态配置常用参数,支持 SpringBoot 加载 |
|
||||
| ⭐️ | 定时任务 | 在线(添加、修改、删除)任务调度包含执行结果日志 |
|
||||
| 🚀 | 文件服务 | 支持将文件存储到 S3(MinIO、阿里云、腾讯云、七牛云)、本地、FTP、数据库等 |
|
||||
| 🚀 | WebSocket | 提供 WebSocket 接入示例,支持一对一、一对多发送方式 |
|
||||
| 🚀 | API 日志 | 包括 RESTful API 访问日志、异常日志两部分,方便排查 API 相关的问题 |
|
||||
| | MySQL 监控 | 监视当前系统数据库连接池状态,可进行分析SQL找出系统性能瓶颈 |
|
||||
| | Redis 监控 | 监控 Redis 数据库的使用情况,使用的 Redis Key 管理 |
|
||||
| 🚀 | 消息队列 | 基于 Redis 实现消息队列,Stream 提供集群消费,Pub/Sub 提供广播消费 |
|
||||
| 🚀 | Java 监控 | 基于 Spring Boot Admin 实现 Java 应用的监控 |
|
||||
| 🚀 | 链路追踪 | 接入 SkyWalking 组件,实现链路追踪 |
|
||||
| 🚀 | 日志中心 | 接入 SkyWalking 组件,实现日志中心 |
|
||||
| 🚀 | 服务保障 | 基于 Redis 实现分布式锁、幂等、限流功能,满足高并发场景 |
|
||||
| 🚀 | 日志服务 | 轻量级日志中心,查看远程服务器的日志 |
|
||||
| 🚀 | 单元测试 | 基于 JUnit + Mockito 实现单元测试,保证功能的正确性、代码的质量等 |
|
||||
|
||||

|
||||
|
||||
|
|
@ -197,19 +197,19 @@
|
|||
|
||||
### 微信公众号
|
||||
|
||||
| | 功能 | 描述 |
|
||||
|----|--------|-------------------------------|
|
||||
| 🚀 | 账号管理 | 配置接入的微信公众号,可支持多个公众号 |
|
||||
| 🚀 | 数据统计 | 统计公众号的用户增减、累计用户、消息概况、接口分析等数据 |
|
||||
| 🚀 | 粉丝管理 | 查看已关注、取关的粉丝列表,可对粉丝进行同步、打标签等操作 |
|
||||
| 🚀 | 消息管理 | 查看粉丝发送的消息列表,可主动回复粉丝消息 |
|
||||
| 🚀 | 模版消息 | 配置和发送模版消息,用于向粉丝推送通知类消息 |
|
||||
| 🚀 | 自动回复 | 自动回复粉丝发送的消息,支持关注回复、消息回复、关键字回复 |
|
||||
| 🚀 | 标签管理 | 对公众号的标签进行创建、查询、修改、删除等操作 |
|
||||
| 🚀 | 菜单管理 | 自定义公众号的菜单,也可以从公众号同步菜单 |
|
||||
| 🚀 | 素材管理 | 管理公众号的图片、语音、视频等素材,支持在线播放语音、视频 |
|
||||
| 🚀 | 图文草稿箱 | 新增常用的图文素材到草稿箱,可发布到公众号 |
|
||||
| 🚀 | 图文发表记录 | 查看已发布成功的图文素材,支持删除操作 |
|
||||
| | 功能 | 描述 |
|
||||
| --- | --- | --- |
|
||||
| 🚀 | 账号管理 | 配置接入的微信公众号,可支持多个公众号 |
|
||||
| 🚀 | 数据统计 | 统计公众号的用户增减、累计用户、消息概况、接口分析等数据 |
|
||||
| 🚀 | 粉丝管理 | 查看已关注、取关的粉丝列表,可对粉丝进行同步、打标签等操作 |
|
||||
| 🚀 | 消息管理 | 查看粉丝发送的消息列表,可主动回复粉丝消息 |
|
||||
| 🚀 | 模版消息 | 配置和发送模版消息,用于向粉丝推送通知类消息 |
|
||||
| 🚀 | 自动回复 | 自动回复粉丝发送的消息,支持关注回复、消息回复、关键字回复 |
|
||||
| 🚀 | 标签管理 | 对公众号的标签进行创建、查询、修改、删除等操作 |
|
||||
| 🚀 | 菜单管理 | 自定义公众号的菜单,也可以从公众号同步菜单 |
|
||||
| 🚀 | 素材管理 | 管理公众号的图片、语音、视频等素材,支持在线播放语音、视频 |
|
||||
| 🚀 | 图文草稿箱 | 新增常用的图文素材到草稿箱,可发布到公众号 |
|
||||
| 🚀 | 图文发表记录 | 查看已发布成功的图文素材,支持删除操作 |
|
||||
|
||||
### 商城系统
|
||||
|
||||
|
|
@ -219,18 +219,44 @@
|
|||
|
||||

|
||||
|
||||
### 会员中心
|
||||
|
||||
| | 功能 | 描述 |
|
||||
| --- | --- | --- |
|
||||
| 🚀 | 会员管理 | 会员是 C 端的消费者,该功能用于会员的搜索与管理 |
|
||||
| 🚀 | 会员标签 | 对会员的标签进行创建、查询、修改、删除等操作 |
|
||||
| 🚀 | 会员等级 | 对会员的等级、成长值进行管理,可用于订单折扣等会员权益 |
|
||||
| 🚀 | 会员分组 | 对会员进行分组,用于用户画像、内容推送等运营手段 |
|
||||
| 🚀 | 积分签到 | 回馈给签到、消费等行为的积分,会员可订单抵现、积分兑换等途径消耗 |
|
||||
|
||||
### ERP 系统
|
||||
|
||||
演示地址:<https://doc.iocoder.cn/erp-preview/>
|
||||
|
||||

|
||||
|
||||
### WMS 系统
|
||||
|
||||
演示地址:<https://doc.iocoder.cn/wms-preview/>
|
||||
|
||||

|
||||
|
||||

|
||||
|
||||
### CRM 系统
|
||||
|
||||
演示地址:<https://doc.iocoder.cn/crm-preview/>
|
||||
|
||||

|
||||
|
||||
### MES 系统
|
||||
|
||||
演示地址:<https://doc.iocoder.cn/mes-preview/>
|
||||
|
||||

|
||||
|
||||

|
||||
|
||||
### AI 大模型
|
||||
|
||||
演示地址:<https://doc.iocoder.cn/ai-preview/>
|
||||
|
|
@ -238,3 +264,11 @@
|
|||

|
||||
|
||||

|
||||
|
||||
### IoT 物联网
|
||||
|
||||
演示地址:<https://doc.iocoder.cn/iot/build>
|
||||
|
||||

|
||||
|
||||

|
||||
|
|
|
|||
|
|
@ -33,3 +33,6 @@ VITE_APP_API_ENCRYPT_REQUEST_KEY = 52549111389893486934626385991395
|
|||
VITE_APP_API_ENCRYPT_RESPONSE_KEY = 96103715984234343991809655248883
|
||||
# VITE_APP_API_ENCRYPT_REQUEST_KEY = MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCls2rIpnGdYnLFgz1XU13GbNQ5DloyPpvW00FPGjqn5Z6JpK+kDtVlnkhwR87iRrE5Vf2WNqRX6vzbLSgveIQY8e8oqGCb829myjf1MuI+ZzN4ghf/7tEYhZJGPI9AbfxFqBUzm+kR3/HByAI22GLT96WM26QiMK8n3tIP/yiLswIDAQAB
|
||||
# VITE_APP_API_ENCRYPT_RESPONSE_KEY = MIICdgIBADANBgkqhkiG9w0BAQEFAASCAmAwggJcAgEAAoGBAOH8IfIFxL/MR9XIg1UDv5z1fGXQI93E8wrU4iPFovL/sEt9uSgSkjyidC2O7N+m7EKtoN6b1u7cEwXSkwf3kfK0jdWLSQaNpX5YshqXCBzbDfugDaxuyYrNA4/tIMs7mzZAk0APuRXB35Dmupou7Yw7TFW/7QhQmGfzeEKULQvnAgMBAAECgYAw8LqlQGyQoPv5p3gRxEMOCfgL0JzD3XBJKztiRd35RDh40Nx1ejgjW4dPioFwGiVWd2W8cAGHLzALdcQT2KDJh+T/tsd4SPmI6uSBBK6Ff2DkO+kFFcuYvfclQQKqxma5CaZOSqhgenacmgTMFeg2eKlY3symV6JlFNu/IKU42QJBAOhxAK/Eq3e61aYQV2JSguhMR3b8NXJJRroRs/QHEanksJtl+M+2qhkC9nQVXBmBkndnkU/l2tYcHfSBlAyFySMCQQD445tgm/J2b6qMQmuUGQAYDN8FIkHjeKmha+l/fv0igWm8NDlBAem91lNDIPBUzHL1X1+pcts5bjmq99YdOnhtAkAg2J8dN3B3idpZDiQbC8fd5bGPmdI/pSUudAP27uzLEjr2qrE/QPPGdwm2m7IZFJtK7kK1hKio6u48t/bg0iL7AkEAuUUs94h+v702Fnym+jJ2CHEkXvz2US8UDs52nWrZYiM1o1y4tfSHm8H8bv8JCAa9GHyriEawfBraILOmllFdLQJAQSRZy4wmlaG48MhVXodB85X+VZ9krGXZ2TLhz7kz9iuToy53l9jTkESt6L5BfBDCVdIwcXLYgK+8KFdHN5W7HQ==
|
||||
|
||||
# 百度地图
|
||||
VITE_BAIDU_MAP_KEY=Y2aJXiswwPxy6mwFs1z9c7U5gwX9WfUN
|
||||
|
|
@ -21,3 +21,6 @@ VITE_INJECT_APP_LOADING=true
|
|||
|
||||
# 打包后是否生成dist.zip
|
||||
VITE_ARCHIVER=true
|
||||
|
||||
# 验证码的开关
|
||||
VITE_APP_CAPTCHA_ENABLE=true
|
||||
|
|
@ -12,16 +12,15 @@
|
|||
content="width=device-width,initial-scale=1.0,minimum-scale=1.0,maximum-scale=1.0,user-scalable=0"
|
||||
/>
|
||||
<!-- 由 vite 注入 VITE_APP_TITLE 变量,在 .env 文件内配置 -->
|
||||
<title><%= VITE_APP_TITLE %></title>
|
||||
<title>%VITE_APP_TITLE%</title>
|
||||
<link rel="icon" href="/favicon.ico" />
|
||||
<script>
|
||||
var HM_ID = '<%= VITE_APP_BAIDU_CODE %>'
|
||||
var HM_ID = '<%= VITE_APP_BAIDU_CODE %>';
|
||||
if (HM_ID) {
|
||||
var _hmt = _hmt || [];
|
||||
(function () {
|
||||
var hm = document.createElement('script');
|
||||
hm.src =
|
||||
'https://hm.baidu.com/hm.js?' + HM_ID;
|
||||
hm.src = 'https://hm.baidu.com/hm.js?' + HM_ID;
|
||||
var s = document.getElementsByTagName('script')[0];
|
||||
s.parentNode.insertBefore(hm, s);
|
||||
})();
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
{
|
||||
"name": "@vben/web-antd",
|
||||
"version": "5.5.9",
|
||||
"version": "5.7.0",
|
||||
"homepage": "https://vben.pro",
|
||||
"bugs": "https://github.com/vbenjs/vue-vben-admin/issues",
|
||||
"repository": {
|
||||
|
|
|
|||
|
|
@ -1 +0,0 @@
|
|||
export { default } from '@vben/tailwind-config/postcss';
|
||||
|
|
@ -2537,12 +2537,12 @@ interface EditorSelection {
|
|||
normalize: () => Range;
|
||||
selectorChanged: (selector: string, callback: (active: boolean, args: {
|
||||
node: Node;
|
||||
selector: String;
|
||||
selector: string;
|
||||
parents: Node[];
|
||||
}) => void) => EditorSelection;
|
||||
selectorChangedWithUnbind: (selector: string, callback: (active: boolean, args: {
|
||||
node: Node;
|
||||
selector: String;
|
||||
selector: string;
|
||||
parents: Node[];
|
||||
}) => void) => {
|
||||
unbind: () => void;
|
||||
|
|
@ -3217,9 +3217,9 @@ interface Tools {
|
|||
<T, R>(arr: ArrayLike<T> | null | undefined, cb: ArrayCallback<T, R>): R[];
|
||||
<T, R>(obj: Record<string, T> | null | undefined, cb: ObjCallback<T, R>): R[];
|
||||
};
|
||||
extend: (obj: Object, ext: Object, ...objs: Object[]) => any;
|
||||
extend: (obj: object, ext: object, ...objs: object[]) => any;
|
||||
walk: <T extends Record<string, any>>(obj: T, f: WalkCallback<T>, n?: keyof T, scope?: any) => void;
|
||||
resolve: (path: string, o?: Object) => any;
|
||||
resolve: (path: string, o?: object) => any;
|
||||
explode: (s: string | string[], d?: string | RegExp) => string[];
|
||||
_addCacheSuffix: (url: string) => string;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -3,36 +3,82 @@
|
|||
* 可用于 vben-form、vben-modal、vben-drawer 等组件使用,
|
||||
*/
|
||||
|
||||
/* eslint-disable vue/one-component-per-file */
|
||||
|
||||
import type {
|
||||
AutoCompleteProps,
|
||||
ButtonProps,
|
||||
CascaderProps,
|
||||
CheckboxGroupProps,
|
||||
CheckboxProps,
|
||||
DatePickerProps,
|
||||
DividerProps,
|
||||
InputNumberProps,
|
||||
InputProps,
|
||||
MentionsProps,
|
||||
RadioGroupProps,
|
||||
RadioProps,
|
||||
RateProps,
|
||||
SelectProps,
|
||||
SpaceProps,
|
||||
SwitchProps,
|
||||
TextAreaProps,
|
||||
TimePickerProps,
|
||||
TreeSelectProps,
|
||||
UploadChangeParam,
|
||||
UploadFile,
|
||||
UploadProps,
|
||||
} from 'ant-design-vue';
|
||||
import type { RangePickerProps } from 'ant-design-vue/es/date-picker';
|
||||
|
||||
import type { Component, Ref } from 'vue';
|
||||
|
||||
import type { BaseFormComponentType } from '@vben/common-ui';
|
||||
import type {
|
||||
ApiComponentSharedProps,
|
||||
BaseFormComponentType,
|
||||
IconPickerProps,
|
||||
} from '@vben/common-ui';
|
||||
import type { Sortable } from '@vben/hooks';
|
||||
import type { Recordable } from '@vben/types';
|
||||
|
||||
import {
|
||||
computed,
|
||||
defineAsyncComponent,
|
||||
defineComponent,
|
||||
h,
|
||||
nextTick,
|
||||
onMounted,
|
||||
onUnmounted,
|
||||
ref,
|
||||
render,
|
||||
unref,
|
||||
watch,
|
||||
} from 'vue';
|
||||
|
||||
import { ApiComponent, globalShareState, IconPicker } from '@vben/common-ui';
|
||||
import {
|
||||
ApiComponent,
|
||||
globalShareState,
|
||||
IconPicker,
|
||||
VCropper,
|
||||
} from '@vben/common-ui';
|
||||
import { useSortable } from '@vben/hooks';
|
||||
import { IconifyIcon } from '@vben/icons';
|
||||
import { $t } from '@vben/locales';
|
||||
import { isEmpty } from '@vben/utils';
|
||||
|
||||
import { notification } from 'ant-design-vue';
|
||||
import { message, Modal, notification } from 'ant-design-vue';
|
||||
|
||||
import { Tinymce as RichTextarea } from '#/components/tinymce';
|
||||
import { FileUpload, ImageUpload } from '#/components/upload';
|
||||
type AdapterUploadProps = UploadProps & {
|
||||
aspectRatio?: string;
|
||||
crop?: boolean;
|
||||
draggable?: boolean;
|
||||
handleChange?: (event: UploadChangeParam) => void;
|
||||
maxSize?: number;
|
||||
onDragSort?: (oldIndex: number, newIndex: number) => void;
|
||||
onHandleChange?: (event: UploadChangeParam) => void;
|
||||
};
|
||||
|
||||
const AutoComplete = defineAsyncComponent(
|
||||
() => import('ant-design-vue/es/auto-complete'),
|
||||
|
|
@ -90,8 +136,8 @@ const PreviewGroup = defineAsyncComponent(() =>
|
|||
import('ant-design-vue/es/image').then((res) => res.ImagePreviewGroup),
|
||||
);
|
||||
|
||||
const withDefaultPlaceholder = <T extends Component>(
|
||||
component: T,
|
||||
const withDefaultPlaceholder = (
|
||||
component: Component,
|
||||
type: 'input' | 'select',
|
||||
componentProps: Recordable<any> = {},
|
||||
) => {
|
||||
|
|
@ -124,173 +170,110 @@ const withDefaultPlaceholder = <T extends Component>(
|
|||
});
|
||||
};
|
||||
|
||||
const withPreviewUpload = () => {
|
||||
return defineComponent({
|
||||
name: Upload.name,
|
||||
emits: ['change', 'update:modelValue'],
|
||||
setup: (
|
||||
props: any,
|
||||
{ attrs, slots, emit }: { attrs: any; emit: any; slots: any },
|
||||
) => {
|
||||
const previewVisible = ref<boolean>(false);
|
||||
const IMAGE_EXTENSIONS = new Set([
|
||||
'bmp',
|
||||
'gif',
|
||||
'jpeg',
|
||||
'jpg',
|
||||
'png',
|
||||
'svg',
|
||||
'webp',
|
||||
]);
|
||||
|
||||
const placeholder = attrs?.placeholder || $t(`ui.placeholder.upload`);
|
||||
|
||||
const listType = attrs?.listType || attrs?.['list-type'] || 'text';
|
||||
|
||||
const fileList = ref<UploadProps['fileList']>(
|
||||
attrs?.fileList || attrs?.['file-list'] || [],
|
||||
);
|
||||
|
||||
const handleChange = async (event: UploadChangeParam) => {
|
||||
fileList.value = event.fileList;
|
||||
emit('change', event);
|
||||
emit(
|
||||
'update:modelValue',
|
||||
event.fileList?.length ? fileList.value : undefined,
|
||||
);
|
||||
};
|
||||
|
||||
const handlePreview = async (file: UploadFile) => {
|
||||
previewVisible.value = true;
|
||||
await previewImage(file, previewVisible, fileList);
|
||||
};
|
||||
|
||||
const renderUploadButton = (): any => {
|
||||
const isDisabled = attrs.disabled;
|
||||
|
||||
// 如果禁用,不渲染上传按钮
|
||||
if (isDisabled) {
|
||||
return null;
|
||||
}
|
||||
|
||||
// 否则渲染默认上传按钮
|
||||
return isEmpty(slots)
|
||||
? createDefaultSlotsWithUpload(listType, placeholder)
|
||||
: slots;
|
||||
};
|
||||
|
||||
// 可以监听到表单API设置的值
|
||||
watch(
|
||||
() => attrs.modelValue,
|
||||
(res) => {
|
||||
fileList.value = res;
|
||||
},
|
||||
);
|
||||
|
||||
return () =>
|
||||
h(
|
||||
Upload,
|
||||
{
|
||||
...props,
|
||||
...attrs,
|
||||
fileList: fileList.value,
|
||||
onChange: handleChange,
|
||||
onPreview: handlePreview,
|
||||
},
|
||||
renderUploadButton(),
|
||||
);
|
||||
},
|
||||
});
|
||||
};
|
||||
|
||||
const createDefaultSlotsWithUpload = (
|
||||
listType: string,
|
||||
placeholder: string,
|
||||
) => {
|
||||
switch (listType) {
|
||||
case 'picture-card': {
|
||||
return {
|
||||
default: () => placeholder,
|
||||
};
|
||||
}
|
||||
default: {
|
||||
return {
|
||||
default: () =>
|
||||
h(
|
||||
Button,
|
||||
{
|
||||
icon: h(IconifyIcon, {
|
||||
icon: 'ant-design:upload-outlined',
|
||||
class: 'mb-1 size-4',
|
||||
}),
|
||||
},
|
||||
() => placeholder,
|
||||
),
|
||||
};
|
||||
/**
|
||||
* 检查是否为图片文件
|
||||
*/
|
||||
function isImageFile(file: UploadFile): boolean {
|
||||
if (file.url) {
|
||||
try {
|
||||
const pathname = new URL(file.url, 'http://localhost').pathname;
|
||||
const ext = pathname.split('.').pop()?.toLowerCase();
|
||||
return ext ? IMAGE_EXTENSIONS.has(ext) : false;
|
||||
} catch {
|
||||
const ext = file.url?.split('.').pop()?.toLowerCase();
|
||||
return ext ? IMAGE_EXTENSIONS.has(ext) : false;
|
||||
}
|
||||
}
|
||||
};
|
||||
if (!file.type) {
|
||||
const ext = file.name?.split('.').pop()?.toLowerCase();
|
||||
return ext ? IMAGE_EXTENSIONS.has(ext) : false;
|
||||
}
|
||||
return file.type.startsWith('image/');
|
||||
}
|
||||
|
||||
const previewImage = async (
|
||||
/**
|
||||
* 创建默认的上传按钮插槽
|
||||
*/
|
||||
function createDefaultUploadSlots(listType: string, placeholder: string) {
|
||||
if (listType === 'picture-card') {
|
||||
return { default: () => placeholder };
|
||||
}
|
||||
return {
|
||||
default: () =>
|
||||
h(
|
||||
Button,
|
||||
{
|
||||
icon: h(IconifyIcon, {
|
||||
icon: 'ant-design:upload-outlined',
|
||||
class: 'mb-1 size-4',
|
||||
}),
|
||||
},
|
||||
() => placeholder,
|
||||
),
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取文件的 Base64
|
||||
*/
|
||||
function getBase64(file: File): Promise<string> {
|
||||
return new Promise((resolve, reject) => {
|
||||
const reader = new FileReader();
|
||||
reader.readAsDataURL(file);
|
||||
reader.addEventListener('load', () => resolve(reader.result as string));
|
||||
reader.addEventListener('error', reject);
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 预览图片
|
||||
*/
|
||||
async function previewImage(
|
||||
file: UploadFile,
|
||||
visible: Ref<boolean>,
|
||||
fileList: Ref<UploadProps['fileList']>,
|
||||
) => {
|
||||
// 检查是否为图片文件的辅助函数
|
||||
const isImageFile = (file: UploadFile): boolean => {
|
||||
const imageExtensions = new Set([
|
||||
'bmp',
|
||||
'gif',
|
||||
'jpeg',
|
||||
'jpg',
|
||||
'png',
|
||||
'webp',
|
||||
]);
|
||||
if (file.url) {
|
||||
const ext = file.url?.split('.').pop()?.toLowerCase();
|
||||
return ext ? imageExtensions.has(ext) : false;
|
||||
}
|
||||
if (!file.type) {
|
||||
const ext = file.name?.split('.').pop()?.toLowerCase();
|
||||
return ext ? imageExtensions.has(ext) : false;
|
||||
}
|
||||
return file.type.startsWith('image/');
|
||||
};
|
||||
|
||||
// 如果当前文件不是图片,直接打开
|
||||
) {
|
||||
// 非图片文件直接打开链接
|
||||
if (!isImageFile(file)) {
|
||||
if (file.url) {
|
||||
window.open(file.url, '_blank');
|
||||
} else if (file.preview) {
|
||||
window.open(file.preview, '_blank');
|
||||
const url = file.url || file.preview;
|
||||
if (url) {
|
||||
window.open(url, '_blank');
|
||||
} else {
|
||||
console.warn('无法打开文件,没有可用的URL或预览地址');
|
||||
message.error($t('ui.formRules.previewWarning'));
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
// 对于图片文件,继续使用预览组
|
||||
const [ImageComponent, PreviewGroupComponent] = await Promise.all([
|
||||
Image,
|
||||
PreviewGroup,
|
||||
]);
|
||||
|
||||
const getBase64 = (file: File) => {
|
||||
return new Promise((resolve, reject) => {
|
||||
const reader = new FileReader();
|
||||
reader.readAsDataURL(file);
|
||||
reader.addEventListener('load', () => resolve(reader.result));
|
||||
reader.addEventListener('error', (error) => reject(error));
|
||||
});
|
||||
};
|
||||
// 从fileList中过滤出所有图片文件
|
||||
const imageFiles = (unref(fileList) || []).filter((element) =>
|
||||
isImageFile(element),
|
||||
);
|
||||
// 过滤图片文件并生成预览
|
||||
const imageFiles = (unref(fileList) || []).filter((f) => isImageFile(f));
|
||||
|
||||
// 为所有没有预览地址的图片生成预览
|
||||
for (const imgFile of imageFiles) {
|
||||
if (!imgFile.url && !imgFile.preview && imgFile.originFileObj) {
|
||||
imgFile.preview = (await getBase64(imgFile.originFileObj)) as string;
|
||||
imgFile.preview = await getBase64(imgFile.originFileObj);
|
||||
}
|
||||
}
|
||||
const container: HTMLElement | null = document.createElement('div');
|
||||
document.body.append(container);
|
||||
|
||||
// 用于追踪组件是否已卸载
|
||||
const container = document.createElement('div');
|
||||
document.body.append(container);
|
||||
let isUnmounted = false;
|
||||
|
||||
const currentIndex = imageFiles.findIndex((f) => f.uid === file.uid);
|
||||
|
||||
const PreviewWrapper = {
|
||||
setup() {
|
||||
return () => {
|
||||
|
|
@ -301,12 +284,10 @@ const previewImage = async (
|
|||
class: 'hidden',
|
||||
preview: {
|
||||
visible: visible.value,
|
||||
// 设置初始显示的图片索引
|
||||
current: imageFiles.findIndex((f) => f.uid === file.uid),
|
||||
current: currentIndex,
|
||||
onVisibleChange: (value: boolean) => {
|
||||
visible.value = value;
|
||||
if (!value) {
|
||||
// 延迟清理,确保动画完成
|
||||
setTimeout(() => {
|
||||
if (!isUnmounted && container) {
|
||||
isUnmounted = true;
|
||||
|
|
@ -319,7 +300,6 @@ const previewImage = async (
|
|||
},
|
||||
},
|
||||
() =>
|
||||
// 渲染所有图片文件
|
||||
imageFiles.map((imgFile) =>
|
||||
h(ImageComponent, {
|
||||
key: imgFile.uid,
|
||||
|
|
@ -332,6 +312,292 @@ const previewImage = async (
|
|||
};
|
||||
|
||||
render(h(PreviewWrapper), container);
|
||||
}
|
||||
|
||||
/**
|
||||
* 图片裁剪操作
|
||||
*/
|
||||
function cropImage(file: File, aspectRatio: string | undefined) {
|
||||
return new Promise<Blob | string | undefined>((resolve, reject) => {
|
||||
const container = document.createElement('div');
|
||||
document.body.append(container);
|
||||
|
||||
let isUnmounted = false;
|
||||
let objectUrl: null | string = null;
|
||||
|
||||
const open = ref<boolean>(true);
|
||||
const cropperRef = ref<InstanceType<typeof VCropper> | null>(null);
|
||||
|
||||
const closeModal = () => {
|
||||
open.value = false;
|
||||
setTimeout(() => {
|
||||
if (!isUnmounted && container) {
|
||||
if (objectUrl) {
|
||||
URL.revokeObjectURL(objectUrl);
|
||||
}
|
||||
isUnmounted = true;
|
||||
render(null, container);
|
||||
container.remove();
|
||||
}
|
||||
}, 300);
|
||||
};
|
||||
|
||||
const CropperWrapper = {
|
||||
setup() {
|
||||
return () => {
|
||||
if (isUnmounted) return null;
|
||||
if (!objectUrl) {
|
||||
objectUrl = URL.createObjectURL(file);
|
||||
}
|
||||
return h(
|
||||
Modal,
|
||||
{
|
||||
open: open.value,
|
||||
title: h('div', {}, [
|
||||
$t('ui.crop.title'),
|
||||
h(
|
||||
'span',
|
||||
{
|
||||
class: `${aspectRatio ? '' : 'hidden'} ml-2 text-sm text-gray-400 font-normal`,
|
||||
},
|
||||
$t('ui.crop.titleTip', [aspectRatio]),
|
||||
),
|
||||
]),
|
||||
centered: true,
|
||||
width: 548,
|
||||
keyboard: false,
|
||||
maskClosable: false,
|
||||
closable: false,
|
||||
cancelText: $t('common.cancel'),
|
||||
okText: $t('ui.crop.confirm'),
|
||||
destroyOnClose: true,
|
||||
onOk: async () => {
|
||||
const cropper = cropperRef.value;
|
||||
if (!cropper) {
|
||||
reject(new Error('Cropper not found'));
|
||||
closeModal();
|
||||
return;
|
||||
}
|
||||
try {
|
||||
const dataUrl = await cropper.getCropImage();
|
||||
if (dataUrl) {
|
||||
resolve(dataUrl);
|
||||
} else {
|
||||
reject(new Error($t('ui.crop.errorTip')));
|
||||
}
|
||||
} catch {
|
||||
reject(new Error($t('ui.crop.errorTip')));
|
||||
} finally {
|
||||
closeModal();
|
||||
}
|
||||
},
|
||||
onCancel() {
|
||||
resolve('');
|
||||
closeModal();
|
||||
},
|
||||
},
|
||||
() =>
|
||||
h(VCropper, {
|
||||
ref: (ref: any) => (cropperRef.value = ref),
|
||||
img: objectUrl as string,
|
||||
aspectRatio,
|
||||
}),
|
||||
);
|
||||
};
|
||||
},
|
||||
};
|
||||
|
||||
render(h(CropperWrapper), container);
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 带预览功能的上传组件
|
||||
*/
|
||||
const withPreviewUpload = () => {
|
||||
return defineComponent({
|
||||
name: Upload.name,
|
||||
emits: ['update:modelValue'],
|
||||
setup(
|
||||
props: any,
|
||||
{ attrs, slots, emit }: { attrs: any; emit: any; slots: any },
|
||||
) {
|
||||
const previewVisible = ref<boolean>(false);
|
||||
const placeholder = attrs?.placeholder || $t('ui.placeholder.upload');
|
||||
const listType = attrs?.listType || attrs?.['list-type'] || 'text';
|
||||
const fileList = ref<UploadProps['fileList']>(
|
||||
attrs?.fileList || attrs?.['file-list'] || [],
|
||||
);
|
||||
|
||||
const maxSize = computed(() => attrs?.maxSize ?? attrs?.['max-size']);
|
||||
const aspectRatio = computed(
|
||||
() => attrs?.aspectRatio ?? attrs?.['aspect-ratio'],
|
||||
);
|
||||
|
||||
const handleBeforeUpload = async (
|
||||
file: UploadFile,
|
||||
originFileList: Array<File>,
|
||||
) => {
|
||||
// 文件大小限制
|
||||
if (maxSize.value && (file.size || 0) / 1024 / 1024 > maxSize.value) {
|
||||
message.error($t('ui.formRules.sizeLimit', [maxSize.value]));
|
||||
file.status = 'removed';
|
||||
return false;
|
||||
}
|
||||
|
||||
// 图片裁剪处理
|
||||
if (
|
||||
attrs.crop &&
|
||||
!attrs.multiple &&
|
||||
originFileList[0] &&
|
||||
isImageFile(file)
|
||||
) {
|
||||
file.status = 'removed';
|
||||
const blob = await cropImage(originFileList[0], aspectRatio.value);
|
||||
if (!blob) {
|
||||
throw new Error($t('ui.crop.errorTip'));
|
||||
}
|
||||
return blob;
|
||||
}
|
||||
|
||||
return attrs.beforeUpload?.(file) ?? true;
|
||||
};
|
||||
|
||||
const handleChange = (event: UploadChangeParam) => {
|
||||
try {
|
||||
attrs.handleChange?.(event);
|
||||
attrs.onHandleChange?.(event);
|
||||
} catch (error) {
|
||||
console.error(error);
|
||||
}
|
||||
fileList.value = event.fileList.filter(
|
||||
(file) => file.status !== 'removed',
|
||||
);
|
||||
emit(
|
||||
'update:modelValue',
|
||||
event.fileList?.length ? fileList.value : undefined,
|
||||
);
|
||||
};
|
||||
|
||||
const handlePreview = async (file: UploadFile) => {
|
||||
previewVisible.value = true;
|
||||
await previewImage(file, previewVisible, fileList);
|
||||
};
|
||||
|
||||
const renderUploadButton = () => {
|
||||
if (attrs.disabled) return null;
|
||||
return isEmpty(slots)
|
||||
? createDefaultUploadSlots(listType, placeholder)
|
||||
: slots;
|
||||
};
|
||||
|
||||
// 拖拽排序
|
||||
const draggable = computed(
|
||||
() => (attrs.draggable ?? false) && !attrs.disabled,
|
||||
);
|
||||
const uploadId = `upload-${Date.now()}-${Math.random().toString(36).slice(2, 9)}`;
|
||||
const sortableInstance = ref<null | Sortable>(null);
|
||||
|
||||
const styleId = `upload-drag-style-${uploadId}`;
|
||||
|
||||
function injectDragStyle() {
|
||||
if (!document.querySelector(`[id="${styleId}"]`)) {
|
||||
const style = document.createElement('style');
|
||||
style.id = styleId;
|
||||
style.textContent = `
|
||||
[data-upload-id="${uploadId}"] .ant-upload-list-item { cursor: move; }
|
||||
[data-upload-id="${uploadId}"] .ant-upload-list-item:hover { box-shadow: 0 2px 8px rgba(0,0,0,0.15); }
|
||||
`;
|
||||
document.head.append(style);
|
||||
}
|
||||
}
|
||||
|
||||
function removeDragStyle() {
|
||||
document.querySelector(`[id="${styleId}"]`)?.remove();
|
||||
}
|
||||
|
||||
async function initSortable(retryCount = 0) {
|
||||
if (!draggable.value) return;
|
||||
|
||||
injectDragStyle();
|
||||
await nextTick();
|
||||
await new Promise((resolve) => setTimeout(resolve, 100));
|
||||
|
||||
const container = document.querySelector(
|
||||
`[data-upload-id="${uploadId}"] .ant-upload-list`,
|
||||
) as HTMLElement;
|
||||
|
||||
if (!container) {
|
||||
if (retryCount < 5) {
|
||||
setTimeout(() => initSortable(retryCount + 1), 200);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
const { initializeSortable } = useSortable(container, {
|
||||
animation: 300,
|
||||
delay: 400,
|
||||
delayOnTouchOnly: true,
|
||||
filter:
|
||||
'.ant-upload-select, .ant-upload-list-item-error, .ant-upload-list-item-uploading',
|
||||
onEnd: (evt) => {
|
||||
const { oldIndex, newIndex } = evt;
|
||||
if (
|
||||
oldIndex === undefined ||
|
||||
newIndex === undefined ||
|
||||
oldIndex === newIndex
|
||||
) {
|
||||
return;
|
||||
}
|
||||
|
||||
const list = [...(fileList.value || [])];
|
||||
const [movedItem] = list.splice(oldIndex, 1);
|
||||
if (movedItem) {
|
||||
list.splice(newIndex, 0, movedItem);
|
||||
fileList.value = list;
|
||||
}
|
||||
|
||||
attrs.onDragSort?.(oldIndex, newIndex);
|
||||
emit('update:modelValue', fileList.value);
|
||||
},
|
||||
});
|
||||
|
||||
sortableInstance.value = await initializeSortable();
|
||||
}
|
||||
|
||||
// 监听表单值变化
|
||||
watch(
|
||||
() => attrs.modelValue,
|
||||
(res) => {
|
||||
fileList.value = res;
|
||||
},
|
||||
);
|
||||
|
||||
onMounted(initSortable);
|
||||
onUnmounted(() => {
|
||||
sortableInstance.value?.destroy();
|
||||
removeDragStyle();
|
||||
});
|
||||
|
||||
return () =>
|
||||
h(
|
||||
'div',
|
||||
{ 'data-upload-id': uploadId, class: 'w-full' },
|
||||
h(
|
||||
Upload,
|
||||
{
|
||||
...props,
|
||||
...attrs,
|
||||
fileList: fileList.value,
|
||||
beforeUpload: handleBeforeUpload,
|
||||
onChange: handleChange,
|
||||
onPreview: handlePreview,
|
||||
},
|
||||
renderUploadButton() as any,
|
||||
),
|
||||
);
|
||||
},
|
||||
});
|
||||
};
|
||||
|
||||
// 这里需要自行根据业务组件库进行适配,需要用到的组件都需要在这里类型说明
|
||||
|
|
@ -369,11 +635,45 @@ export type ComponentType =
|
|||
| 'Upload'
|
||||
| BaseFormComponentType;
|
||||
|
||||
/**
|
||||
* 与 {@link ComponentType} 中注册的组件名一一对应,便于 Schema 上 `component` + `componentProps` 联动提示
|
||||
*/
|
||||
export interface ComponentPropsMap {
|
||||
ApiCascader: ApiComponentSharedProps & CascaderProps;
|
||||
ApiSelect: ApiComponentSharedProps & SelectProps;
|
||||
ApiTreeSelect: ApiComponentSharedProps & TreeSelectProps;
|
||||
AutoComplete: AutoCompleteProps;
|
||||
Cascader: CascaderProps;
|
||||
Checkbox: CheckboxProps;
|
||||
CheckboxGroup: CheckboxGroupProps;
|
||||
DatePicker: DatePickerProps;
|
||||
DefaultButton: ButtonProps;
|
||||
Divider: DividerProps;
|
||||
IconPicker: IconPickerProps;
|
||||
Input: InputProps;
|
||||
InputNumber: InputNumberProps;
|
||||
InputPassword: InputProps;
|
||||
Mentions: MentionsProps;
|
||||
PrimaryButton: ButtonProps;
|
||||
Radio: RadioProps;
|
||||
RadioGroup: RadioGroupProps;
|
||||
RangePicker: RangePickerProps;
|
||||
Rate: RateProps;
|
||||
Select: SelectProps;
|
||||
Space: SpaceProps;
|
||||
Switch: SwitchProps;
|
||||
Textarea: TextAreaProps;
|
||||
TimePicker: TimePickerProps;
|
||||
TreeSelect: TreeSelectProps;
|
||||
Upload: AdapterUploadProps;
|
||||
}
|
||||
|
||||
async function initComponentAdapter() {
|
||||
const components: Partial<Record<ComponentType, Component>> = {
|
||||
// 如果你的组件体积比较大,可以使用异步加载
|
||||
// Button: () =>
|
||||
// import('xxx').then((res) => res.Button),
|
||||
|
||||
ApiCascader: withDefaultPlaceholder(ApiComponent, 'select', {
|
||||
component: Cascader,
|
||||
fieldNames: { label: 'label', value: 'value', children: 'children' },
|
||||
|
|
@ -381,34 +681,20 @@ async function initComponentAdapter() {
|
|||
modelPropName: 'value',
|
||||
visibleEvent: 'onVisibleChange',
|
||||
}),
|
||||
ApiSelect: withDefaultPlaceholder(
|
||||
{
|
||||
...ApiComponent,
|
||||
name: 'ApiSelect',
|
||||
},
|
||||
'select',
|
||||
{
|
||||
component: Select,
|
||||
loadingSlot: 'suffixIcon',
|
||||
visibleEvent: 'onDropdownVisibleChange',
|
||||
modelPropName: 'value',
|
||||
},
|
||||
),
|
||||
ApiTreeSelect: withDefaultPlaceholder(
|
||||
{
|
||||
...ApiComponent,
|
||||
name: 'ApiTreeSelect',
|
||||
},
|
||||
'select',
|
||||
{
|
||||
component: TreeSelect,
|
||||
fieldNames: { label: 'label', value: 'value', children: 'children' },
|
||||
loadingSlot: 'suffixIcon',
|
||||
modelPropName: 'value',
|
||||
optionsPropName: 'treeData',
|
||||
visibleEvent: 'onVisibleChange',
|
||||
},
|
||||
),
|
||||
ApiSelect: withDefaultPlaceholder(ApiComponent, 'select', {
|
||||
component: Select,
|
||||
loadingSlot: 'suffixIcon',
|
||||
modelPropName: 'value',
|
||||
visibleEvent: 'onVisibleChange',
|
||||
}),
|
||||
ApiTreeSelect: withDefaultPlaceholder(ApiComponent, 'select', {
|
||||
component: TreeSelect,
|
||||
fieldNames: { label: 'label', value: 'value', children: 'children' },
|
||||
loadingSlot: 'suffixIcon',
|
||||
modelPropName: 'value',
|
||||
optionsPropName: 'treeData',
|
||||
visibleEvent: 'onVisibleChange',
|
||||
}),
|
||||
AutoComplete,
|
||||
Cascader,
|
||||
Checkbox,
|
||||
|
|
@ -425,7 +711,9 @@ async function initComponentAdapter() {
|
|||
modelValueProp: 'value',
|
||||
}),
|
||||
Input: withDefaultPlaceholder(Input, 'input'),
|
||||
InputNumber: withDefaultPlaceholder(InputNumber, 'input'),
|
||||
InputNumber: withDefaultPlaceholder(InputNumber, 'input', {
|
||||
style: { width: '100%' },
|
||||
}),
|
||||
InputPassword: withDefaultPlaceholder(InputPassword, 'input'),
|
||||
Mentions: withDefaultPlaceholder(Mentions, 'input'),
|
||||
// 自定义主要按钮
|
||||
|
|
|
|||
|
|
@ -1,9 +1,9 @@
|
|||
import type {
|
||||
VbenFormProps as FormProps,
|
||||
VbenFormSchema as FormSchema,
|
||||
VbenFormProps,
|
||||
} from '@vben/common-ui';
|
||||
|
||||
import type { ComponentType } from './component';
|
||||
import type { ComponentPropsMap, ComponentType } from './component';
|
||||
|
||||
import { setupVbenForm, useVbenForm as useForm, z } from '@vben/common-ui';
|
||||
import { $t } from '@vben/locales';
|
||||
|
|
@ -61,9 +61,10 @@ async function initSetupVbenForm() {
|
|||
});
|
||||
}
|
||||
|
||||
const useVbenForm = useForm<ComponentType>;
|
||||
const useVbenForm = useForm<ComponentType, ComponentPropsMap>;
|
||||
|
||||
export { initSetupVbenForm, useVbenForm, z };
|
||||
|
||||
export type VbenFormSchema = FormSchema<ComponentType>;
|
||||
export type { VbenFormProps };
|
||||
export type VbenFormApi = ReturnType<typeof useVbenForm>[1]; // add by 芋艿:用于 data.ts 表单 schema 内调用 setFieldValue
|
||||
export type VbenFormSchema = FormSchema<ComponentType, ComponentPropsMap>;
|
||||
export type VbenFormProps = FormProps<ComponentType, ComponentPropsMap>;
|
||||
|
|
|
|||
|
|
@ -1,6 +1,8 @@
|
|||
import type { VxeTableGridOptions } from '@vben/plugins/vxe-table';
|
||||
import type { Recordable } from '@vben/types';
|
||||
|
||||
import type { ComponentPropsMap, ComponentType } from './component';
|
||||
|
||||
import { h } from 'vue';
|
||||
|
||||
import { IconifyIcon } from '@vben/icons';
|
||||
|
|
@ -10,7 +12,7 @@ import {
|
|||
AsyncVxeTable,
|
||||
createRequiredValidation,
|
||||
setupVbenVxeTable,
|
||||
useVbenVxeGrid,
|
||||
useVbenVxeGrid as useGrid,
|
||||
} from '@vben/plugins/vxe-table';
|
||||
import {
|
||||
erpCountInputFormatter,
|
||||
|
|
@ -199,7 +201,7 @@ setupVbenVxeTable({
|
|||
vxeUI.renderer.add('CellOperation', {
|
||||
renderTableDefault({ attrs, options, props }, { column, row }) {
|
||||
const defaultProps = { size: 'small', type: 'link', ...props };
|
||||
let align = 'end';
|
||||
let align: string;
|
||||
switch (column.align) {
|
||||
case 'center': {
|
||||
align = 'center';
|
||||
|
|
@ -363,10 +365,13 @@ setupVbenVxeTable({
|
|||
useVbenForm,
|
||||
});
|
||||
|
||||
export { createRequiredValidation, useVbenVxeGrid };
|
||||
export { createRequiredValidation };
|
||||
|
||||
export const [VxeTable, VxeColumn] = [AsyncVxeTable, AsyncVxeColumn];
|
||||
|
||||
export * from '#/components/table-action';
|
||||
export const useVbenVxeGrid = <T extends Record<string, any>>(
|
||||
...rest: Parameters<typeof useGrid<T, ComponentType, ComponentPropsMap>>
|
||||
) => useGrid<T, ComponentType, ComponentPropsMap>(...rest);
|
||||
|
||||
export type * from '@vben/plugins/vxe-table';
|
||||
|
|
|
|||
|
|
@ -16,10 +16,10 @@ export namespace CrmCustomerLimitConfigApi {
|
|||
|
||||
/** 客户限制配置类型 */
|
||||
export enum LimitConfType {
|
||||
/** 锁定客户数限制 */
|
||||
CUSTOMER_LOCK_LIMIT = 2,
|
||||
/** 拥有客户数限制 */
|
||||
CUSTOMER_QUANTITY_LIMIT = 1,
|
||||
/** 锁定客户数限制 */
|
||||
CUSTOMER_LOCK_LIMIT = 2,
|
||||
}
|
||||
|
||||
/** 查询客户限制配置列表 */
|
||||
|
|
|
|||
|
|
@ -35,11 +35,11 @@ export namespace CrmPermissionApi {
|
|||
* CRM 业务类型枚举
|
||||
*/
|
||||
export enum BizTypeEnum {
|
||||
CRM_BUSINESS = 4, // 商机
|
||||
CRM_CLUE = 1, // 线索
|
||||
CRM_CONTACT = 3, // 联系人
|
||||
CRM_CONTRACT = 5, // 合同
|
||||
CRM_CUSTOMER = 2, // 客户
|
||||
CRM_CONTACT = 3, // 联系人
|
||||
CRM_BUSINESS = 4, // 商机
|
||||
CRM_CONTRACT = 5, // 合同
|
||||
CRM_PRODUCT = 6, // 产品
|
||||
CRM_RECEIVABLE = 7, // 回款
|
||||
CRM_RECEIVABLE_PLAN = 8, // 回款计划
|
||||
|
|
|
|||
|
|
@ -3,37 +3,21 @@ import type { PageParam, PageResult } from '@vben/request';
|
|||
import { requestClient } from '#/api/request';
|
||||
|
||||
export namespace AlertConfigApi {
|
||||
/** IoT 告警配置 VO */
|
||||
/** IoT 告警配置 */
|
||||
export interface AlertConfig {
|
||||
id?: number;
|
||||
name: string;
|
||||
name?: string;
|
||||
description?: string;
|
||||
level?: number;
|
||||
status?: number;
|
||||
sceneRuleIds?: number[];
|
||||
receiveUserIds?: number[];
|
||||
receiveUserNames?: string;
|
||||
receiveUserNames?: string[];
|
||||
receiveTypes?: number[];
|
||||
createTime?: Date;
|
||||
updateTime?: Date;
|
||||
}
|
||||
}
|
||||
|
||||
/** IoT 告警配置 */
|
||||
export interface AlertConfig {
|
||||
id?: number;
|
||||
name?: string;
|
||||
description?: string;
|
||||
level?: number;
|
||||
status?: number;
|
||||
sceneRuleIds?: number[];
|
||||
receiveUserIds?: number[];
|
||||
receiveUserNames?: string;
|
||||
receiveTypes?: number[];
|
||||
createTime?: Date;
|
||||
updateTime?: Date;
|
||||
}
|
||||
|
||||
/** 查询告警配置分页 */
|
||||
export function getAlertConfigPage(params: PageParam) {
|
||||
return requestClient.get<PageResult<AlertConfigApi.AlertConfig>>(
|
||||
|
|
@ -49,20 +33,20 @@ export function getAlertConfig(id: number) {
|
|||
);
|
||||
}
|
||||
|
||||
/** 查询所有告警配置列表 */
|
||||
export function getAlertConfigList() {
|
||||
/** 获取告警配置简单列表 */
|
||||
export function getSimpleAlertConfigList() {
|
||||
return requestClient.get<AlertConfigApi.AlertConfig[]>(
|
||||
'/iot/alert-config/list',
|
||||
'/iot/alert-config/simple-list',
|
||||
);
|
||||
}
|
||||
|
||||
/** 新增告警配置 */
|
||||
export function createAlertConfig(data: AlertConfig) {
|
||||
export function createAlertConfig(data: AlertConfigApi.AlertConfig) {
|
||||
return requestClient.post('/iot/alert-config/create', data);
|
||||
}
|
||||
|
||||
/** 修改告警配置 */
|
||||
export function updateAlertConfig(data: AlertConfig) {
|
||||
export function updateAlertConfig(data: AlertConfigApi.AlertConfig) {
|
||||
return requestClient.put('/iot/alert-config/update', data);
|
||||
}
|
||||
|
||||
|
|
@ -70,25 +54,3 @@ export function updateAlertConfig(data: AlertConfig) {
|
|||
export function deleteAlertConfig(id: number) {
|
||||
return requestClient.delete(`/iot/alert-config/delete?id=${id}`);
|
||||
}
|
||||
|
||||
/** 批量删除告警配置 */
|
||||
export function deleteAlertConfigList(ids: number[]) {
|
||||
return requestClient.delete('/iot/alert-config/delete-list', {
|
||||
params: { ids: ids.join(',') },
|
||||
});
|
||||
}
|
||||
|
||||
/** 启用/禁用告警配置 */
|
||||
export function toggleAlertConfig(id: number, enabled: boolean) {
|
||||
return requestClient.put(`/iot/alert-config/toggle`, {
|
||||
id,
|
||||
enabled,
|
||||
});
|
||||
}
|
||||
|
||||
/** 获取告警配置简单列表 */
|
||||
export function getSimpleAlertConfigList() {
|
||||
return requestClient.get<AlertConfigApi.AlertConfig[]>(
|
||||
'/iot/alert-config/simple-list',
|
||||
);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -3,41 +3,21 @@ import type { PageParam, PageResult } from '@vben/request';
|
|||
import { requestClient } from '#/api/request';
|
||||
|
||||
export namespace AlertRecordApi {
|
||||
/** IoT 告警记录 VO */
|
||||
/** IoT 告警记录 */
|
||||
export interface AlertRecord {
|
||||
id?: number;
|
||||
configId?: number;
|
||||
configName?: string;
|
||||
configLevel?: number;
|
||||
deviceId?: number;
|
||||
deviceName?: string;
|
||||
productId?: number;
|
||||
productName?: string;
|
||||
deviceMessage?: string;
|
||||
deviceMessage?: any;
|
||||
processStatus?: boolean;
|
||||
processRemark?: string;
|
||||
processTime?: Date;
|
||||
createTime?: Date;
|
||||
}
|
||||
}
|
||||
|
||||
/** IoT 告警记录 */
|
||||
export interface AlertRecord {
|
||||
id?: number;
|
||||
configId?: number;
|
||||
configName?: string;
|
||||
configLevel?: number;
|
||||
deviceId?: number;
|
||||
deviceName?: string;
|
||||
productId?: number;
|
||||
productName?: string;
|
||||
deviceMessage?: string;
|
||||
processStatus?: boolean;
|
||||
processRemark?: string;
|
||||
processTime?: Date;
|
||||
createTime?: Date;
|
||||
}
|
||||
|
||||
/** 查询告警记录分页 */
|
||||
export function getAlertRecordPage(params: PageParam) {
|
||||
return requestClient.get<PageResult<AlertRecordApi.AlertRecord>>(
|
||||
|
|
@ -54,29 +34,9 @@ export function getAlertRecord(id: number) {
|
|||
}
|
||||
|
||||
/** 处理告警记录 */
|
||||
export function processAlertRecord(id: number, remark?: string) {
|
||||
export function processAlertRecord(id: number, processRemark?: string) {
|
||||
return requestClient.put('/iot/alert-record/process', {
|
||||
id,
|
||||
remark,
|
||||
});
|
||||
}
|
||||
|
||||
/** 批量处理告警记录 */
|
||||
export function batchProcessAlertRecord(ids: number[], remark?: string) {
|
||||
return requestClient.put('/iot/alert-record/batch-process', {
|
||||
ids,
|
||||
remark,
|
||||
});
|
||||
}
|
||||
|
||||
/** 删除告警记录 */
|
||||
export function deleteAlertRecord(id: number) {
|
||||
return requestClient.delete(`/iot/alert-record/delete?id=${id}`);
|
||||
}
|
||||
|
||||
/** 批量删除告警记录 */
|
||||
export function deleteAlertRecordList(ids: number[]) {
|
||||
return requestClient.delete('/iot/alert-record/delete-list', {
|
||||
params: { ids: ids.join(',') },
|
||||
processRemark,
|
||||
});
|
||||
}
|
||||
|
|
|
|||
|
|
@ -3,39 +3,48 @@ import type { PageParam, PageResult } from '@vben/request';
|
|||
import { requestClient } from '#/api/request';
|
||||
|
||||
export namespace IotDeviceApi {
|
||||
// TODO @haohao:需要跟后端对齐,必要的 ReqVO、RespVO
|
||||
/** 设备 */
|
||||
export interface Device {
|
||||
id?: number; // 设备 ID,主键,自增
|
||||
id?: number; // 设备编号
|
||||
deviceName: string; // 设备名称
|
||||
nickname?: string; // 备注名称
|
||||
serialNumber?: string; // 设备序列号
|
||||
picUrl?: string; // 设备图片
|
||||
groupIds?: number[]; // 设备分组编号数组
|
||||
productId: number; // 产品编号
|
||||
productKey?: string; // 产品标识
|
||||
productName?: string; // 产品名称(只有部分接口返回,例如 getDeviceLocationList)
|
||||
deviceType?: number; // 设备类型
|
||||
nickname?: string; // 设备备注名称
|
||||
gatewayId?: number; // 网关设备 ID
|
||||
state?: number; // 设备状态
|
||||
status?: number; // 设备状态(兼容字段)
|
||||
onlineTime?: Date; // 最后上线时间
|
||||
offlineTime?: Date; // 最后离线时间
|
||||
activeTime?: Date; // 设备激活时间
|
||||
createTime?: Date; // 创建时间
|
||||
ip?: string; // 设备的 IP 地址
|
||||
firmwareVersion?: string; // 设备的固件版本
|
||||
deviceSecret?: string; // 设备密钥,用于设备认证,需安全存储
|
||||
mqttClientId?: string; // MQTT 客户端 ID
|
||||
mqttUsername?: string; // MQTT 用户名
|
||||
mqttPassword?: string; // MQTT 密码
|
||||
authType?: string; // 认证类型
|
||||
locationType?: number; // 定位类型
|
||||
deviceSecret?: string; // 设备密钥,用于设备认证
|
||||
config?: string; // 设备配置
|
||||
latitude?: number; // 设备位置的纬度
|
||||
longitude?: number; // 设备位置的经度
|
||||
areaId?: number; // 地区编码
|
||||
address?: string; // 设备详细地址
|
||||
serialNumber?: string; // 设备序列号
|
||||
config?: string; // 设备配置
|
||||
groupIds?: number[]; // 添加分组 ID
|
||||
picUrl?: string; // 设备图片
|
||||
location?: string; // 位置信息(格式:经度,纬度)
|
||||
createTime?: Date; // 创建时间
|
||||
}
|
||||
|
||||
/** 设备更新分组 Request VO */
|
||||
export interface DeviceUpdateGroupReqVO {
|
||||
ids: number[]; // 设备编号列表(必填)
|
||||
groupIds: number[]; // 分组编号列表(必填)
|
||||
}
|
||||
|
||||
/** 设备认证信息 Response VO */
|
||||
export interface DeviceAuthInfoRespVO {
|
||||
clientId: string; // 客户端 ID
|
||||
username: string; // 用户名
|
||||
password: string; // 密码
|
||||
}
|
||||
|
||||
/** 设备导入 Response VO */
|
||||
export interface DeviceImportRespVO {
|
||||
createDeviceNames?: string[]; // 创建成功的设备名称列表
|
||||
updateDeviceNames?: string[]; // 更新成功的设备名称列表
|
||||
failureDeviceNames?: Record<string, string>; // 失败的设备名称及原因
|
||||
}
|
||||
|
||||
/** IoT 设备属性详细 VO */
|
||||
|
|
@ -56,25 +65,12 @@ export namespace IotDeviceApi {
|
|||
updateTime: Date; // 更新时间
|
||||
}
|
||||
|
||||
/** 设备认证参数 VO */
|
||||
export interface DeviceAuthInfo {
|
||||
clientId: string; // 客户端 ID
|
||||
username: string; // 用户名
|
||||
password: string; // 密码
|
||||
}
|
||||
|
||||
/** 设备发送消息 Request VO */
|
||||
export interface DeviceMessageSendReq {
|
||||
deviceId: number; // 设备编号
|
||||
method: string; // 请求方法
|
||||
params?: any; // 请求参数
|
||||
}
|
||||
|
||||
/** 设备分组更新请求 */
|
||||
export interface DeviceGroupUpdateReq {
|
||||
ids: number[]; // 设备 ID 列表
|
||||
groupIds: number[]; // 分组 ID 列表
|
||||
}
|
||||
}
|
||||
|
||||
/** 查询设备分页 */
|
||||
|
|
@ -92,33 +88,33 @@ export function getDevice(id: number) {
|
|||
|
||||
/** 新增设备 */
|
||||
export function createDevice(data: IotDeviceApi.Device) {
|
||||
return requestClient.post('/iot/device/create', data);
|
||||
return requestClient.post<number>('/iot/device/create', data);
|
||||
}
|
||||
|
||||
/** 修改设备 */
|
||||
export function updateDevice(data: IotDeviceApi.Device) {
|
||||
return requestClient.put('/iot/device/update', data);
|
||||
return requestClient.put<boolean>('/iot/device/update', data);
|
||||
}
|
||||
|
||||
/** 修改设备分组 */
|
||||
export function updateDeviceGroup(data: IotDeviceApi.DeviceGroupUpdateReq) {
|
||||
return requestClient.put('/iot/device/update-group', data);
|
||||
export function updateDeviceGroup(data: IotDeviceApi.DeviceUpdateGroupReqVO) {
|
||||
return requestClient.put<boolean>('/iot/device/update-group', data);
|
||||
}
|
||||
|
||||
/** 删除单个设备 */
|
||||
export function deleteDevice(id: number) {
|
||||
return requestClient.delete(`/iot/device/delete?id=${id}`);
|
||||
return requestClient.delete<boolean>(`/iot/device/delete?id=${id}`);
|
||||
}
|
||||
|
||||
/** 删除多个设备 */
|
||||
export function deleteDeviceList(ids: number[]) {
|
||||
return requestClient.delete('/iot/device/delete-list', {
|
||||
return requestClient.delete<boolean>('/iot/device/delete-list', {
|
||||
params: { ids: ids.join(',') },
|
||||
});
|
||||
}
|
||||
|
||||
/** 导出设备 */
|
||||
export function exportDeviceExcel(params: any) {
|
||||
export function exportDeviceExcel(params: PageParam) {
|
||||
return requestClient.download('/iot/device/export-excel', { params });
|
||||
}
|
||||
|
||||
|
|
@ -141,6 +137,11 @@ export function getDeviceListByProductId(productId: number) {
|
|||
});
|
||||
}
|
||||
|
||||
/** 获取设备位置列表(用于地图展示) */
|
||||
export function getDeviceLocationList() {
|
||||
return requestClient.get<IotDeviceApi.Device[]>('/iot/device/location-list');
|
||||
}
|
||||
|
||||
/** 获取导入模板 */
|
||||
export function importDeviceTemplate() {
|
||||
return requestClient.download('/iot/device/get-import-template');
|
||||
|
|
@ -148,10 +149,10 @@ export function importDeviceTemplate() {
|
|||
|
||||
/** 导入设备 */
|
||||
export function importDevice(file: File, updateSupport: boolean) {
|
||||
return requestClient.upload('/iot/device/import', {
|
||||
file,
|
||||
updateSupport,
|
||||
});
|
||||
return requestClient.upload<IotDeviceApi.DeviceImportRespVO>(
|
||||
`/iot/device/import?updateSupport=${updateSupport}`,
|
||||
{ file },
|
||||
);
|
||||
}
|
||||
|
||||
/** 获取设备属性最新数据 */
|
||||
|
|
@ -164,7 +165,7 @@ export function getLatestDeviceProperties(params: any) {
|
|||
|
||||
/** 获取设备属性历史数据 */
|
||||
export function getHistoryDevicePropertyList(params: any) {
|
||||
return requestClient.get<PageResult<IotDeviceApi.DeviceProperty>>(
|
||||
return requestClient.get<IotDeviceApi.DeviceProperty[]>(
|
||||
'/iot/device/property/history-list',
|
||||
{ params },
|
||||
);
|
||||
|
|
@ -172,7 +173,7 @@ export function getHistoryDevicePropertyList(params: any) {
|
|||
|
||||
/** 获取设备认证信息 */
|
||||
export function getDeviceAuthInfo(id: number) {
|
||||
return requestClient.get<IotDeviceApi.DeviceAuthInfo>(
|
||||
return requestClient.get<IotDeviceApi.DeviceAuthInfoRespVO>(
|
||||
'/iot/device/get-auth-info',
|
||||
{ params: { id } },
|
||||
);
|
||||
|
|
@ -196,3 +197,35 @@ export function getDeviceMessagePairPage(params: PageParam) {
|
|||
export function sendDeviceMessage(params: IotDeviceApi.DeviceMessageSendReq) {
|
||||
return requestClient.post('/iot/device/message/send', params);
|
||||
}
|
||||
|
||||
/** 绑定子设备到网关设备 */
|
||||
export function bindDeviceGateway(gatewayId: number, subIds: number[]) {
|
||||
return requestClient.put<boolean>('/iot/device/bind-gateway', {
|
||||
gatewayId,
|
||||
subIds,
|
||||
});
|
||||
}
|
||||
|
||||
/** 解绑子设备与网关设备 */
|
||||
export function unbindDeviceGateway(gatewayId: number, subIds: number[]) {
|
||||
return requestClient.put<boolean>('/iot/device/unbind-gateway', {
|
||||
gatewayId,
|
||||
subIds,
|
||||
});
|
||||
}
|
||||
|
||||
/** 获取网关设备的子设备列表 */
|
||||
export function getSubDeviceList(gatewayId: number) {
|
||||
return requestClient.get<IotDeviceApi.Device[]>(
|
||||
'/iot/device/sub-device-list',
|
||||
{ params: { gatewayId } },
|
||||
);
|
||||
}
|
||||
|
||||
/** 获取未绑定的子设备分页 */
|
||||
export function getUnboundSubDevicePage(params: PageParam) {
|
||||
return requestClient.get<PageResult<IotDeviceApi.Device>>(
|
||||
'/iot/device/unbound-sub-device-page',
|
||||
{ params },
|
||||
);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,30 @@
|
|||
import { requestClient } from '#/api/request';
|
||||
|
||||
export namespace IotDeviceModbusConfigApi {
|
||||
/** Modbus 连接配置 VO */
|
||||
export interface ModbusConfig {
|
||||
id?: number; // 主键
|
||||
deviceId: number; // 设备编号
|
||||
ip: string; // Modbus 服务器 IP 地址
|
||||
port: number; // Modbus 服务器端口
|
||||
slaveId: number; // 从站地址
|
||||
timeout: number; // 连接超时时间,单位:毫秒
|
||||
retryInterval: number; // 重试间隔,单位:毫秒
|
||||
mode: number; // 模式
|
||||
frameFormat: number; // 帧格式
|
||||
status: number; // 状态
|
||||
}
|
||||
}
|
||||
|
||||
/** 获取设备的 Modbus 连接配置 */
|
||||
export function getModbusConfig(deviceId: number) {
|
||||
return requestClient.get<IotDeviceModbusConfigApi.ModbusConfig>(
|
||||
'/iot/device-modbus-config/get',
|
||||
{ params: { deviceId } },
|
||||
);
|
||||
}
|
||||
|
||||
/** 保存 Modbus 连接配置 */
|
||||
export function saveModbusConfig(data: IotDeviceModbusConfigApi.ModbusConfig) {
|
||||
return requestClient.post('/iot/device-modbus-config/save', data);
|
||||
}
|
||||
|
|
@ -0,0 +1,52 @@
|
|||
import type { PageParam, PageResult } from '@vben/request';
|
||||
|
||||
import { requestClient } from '#/api/request';
|
||||
|
||||
export namespace IotDeviceModbusPointApi {
|
||||
/** Modbus 点位配置 VO */
|
||||
export interface ModbusPoint {
|
||||
id?: number; // 主键
|
||||
deviceId: number; // 设备编号
|
||||
thingModelId?: number; // 物模型属性编号
|
||||
identifier: string; // 属性标识符
|
||||
name: string; // 属性名称
|
||||
functionCode?: number; // Modbus 功能码
|
||||
registerAddress?: number; // 寄存器起始地址
|
||||
registerCount?: number; // 寄存器数量
|
||||
byteOrder?: string; // 字节序
|
||||
rawDataType?: string; // 原始数据类型
|
||||
scale: number; // 缩放因子
|
||||
pollInterval: number; // 轮询间隔,单位:毫秒
|
||||
status: number; // 状态
|
||||
}
|
||||
}
|
||||
|
||||
/** 获取设备的 Modbus 点位分页 */
|
||||
export function getModbusPointPage(params: PageParam) {
|
||||
return requestClient.get<PageResult<IotDeviceModbusPointApi.ModbusPoint>>(
|
||||
'/iot/device-modbus-point/page',
|
||||
{ params },
|
||||
);
|
||||
}
|
||||
|
||||
/** 获取 Modbus 点位详情 */
|
||||
export function getModbusPoint(id: number) {
|
||||
return requestClient.get<IotDeviceModbusPointApi.ModbusPoint>(
|
||||
`/iot/device-modbus-point/get?id=${id}`,
|
||||
);
|
||||
}
|
||||
|
||||
/** 创建 Modbus 点位配置 */
|
||||
export function createModbusPoint(data: IotDeviceModbusPointApi.ModbusPoint) {
|
||||
return requestClient.post('/iot/device-modbus-point/create', data);
|
||||
}
|
||||
|
||||
/** 更新 Modbus 点位配置 */
|
||||
export function updateModbusPoint(data: IotDeviceModbusPointApi.ModbusPoint) {
|
||||
return requestClient.put('/iot/device-modbus-point/update', data);
|
||||
}
|
||||
|
||||
/** 删除 Modbus 点位配置 */
|
||||
export function deleteModbusPoint(id: number) {
|
||||
return requestClient.delete(`/iot/device-modbus-point/delete?id=${id}`);
|
||||
}
|
||||
|
|
@ -3,39 +3,22 @@ import type { PageParam, PageResult } from '@vben/request';
|
|||
import { requestClient } from '#/api/request';
|
||||
|
||||
export namespace IoTOtaFirmwareApi {
|
||||
/** IoT OTA 固件 VO */
|
||||
/** IoT OTA 固件信息 */
|
||||
export interface Firmware {
|
||||
id?: number;
|
||||
name: string;
|
||||
version: string;
|
||||
productId: number;
|
||||
productName?: string;
|
||||
name?: string;
|
||||
description?: string;
|
||||
version?: string;
|
||||
productId?: number;
|
||||
productName?: string;
|
||||
fileUrl?: string;
|
||||
fileMd5?: string;
|
||||
fileSize?: number;
|
||||
status?: number;
|
||||
fileDigestAlgorithm?: string;
|
||||
fileDigestValue?: string;
|
||||
createTime?: Date;
|
||||
updateTime?: Date;
|
||||
}
|
||||
}
|
||||
|
||||
/** IoT OTA 固件 */
|
||||
export interface IoTOtaFirmware {
|
||||
id?: number;
|
||||
name?: string;
|
||||
version?: string;
|
||||
productId?: number;
|
||||
productName?: string;
|
||||
description?: string;
|
||||
fileUrl?: string;
|
||||
fileMd5?: string;
|
||||
fileSize?: number;
|
||||
status?: number;
|
||||
createTime?: Date;
|
||||
updateTime?: Date;
|
||||
}
|
||||
|
||||
/** 查询 OTA 固件分页 */
|
||||
export function getOtaFirmwarePage(params: PageParam) {
|
||||
return requestClient.get<PageResult<IoTOtaFirmwareApi.Firmware>>(
|
||||
|
|
@ -52,12 +35,12 @@ export function getOtaFirmware(id: number) {
|
|||
}
|
||||
|
||||
/** 新增 OTA 固件 */
|
||||
export function createOtaFirmware(data: IoTOtaFirmware) {
|
||||
export function createOtaFirmware(data: IoTOtaFirmwareApi.Firmware) {
|
||||
return requestClient.post('/iot/ota/firmware/create', data);
|
||||
}
|
||||
|
||||
/** 修改 OTA 固件 */
|
||||
export function updateOtaFirmware(data: IoTOtaFirmware) {
|
||||
export function updateOtaFirmware(data: IoTOtaFirmwareApi.Firmware) {
|
||||
return requestClient.put('/iot/ota/firmware/update', data);
|
||||
}
|
||||
|
||||
|
|
@ -65,26 +48,3 @@ export function updateOtaFirmware(data: IoTOtaFirmware) {
|
|||
export function deleteOtaFirmware(id: number) {
|
||||
return requestClient.delete(`/iot/ota/firmware/delete?id=${id}`);
|
||||
}
|
||||
|
||||
/** 批量删除 OTA 固件 */
|
||||
export function deleteOtaFirmwareList(ids: number[]) {
|
||||
return requestClient.delete('/iot/ota/firmware/delete-list', {
|
||||
params: { ids: ids.join(',') },
|
||||
});
|
||||
}
|
||||
|
||||
/** 更新 OTA 固件状态 */
|
||||
export function updateOtaFirmwareStatus(id: number, status: number) {
|
||||
return requestClient.put(`/iot/ota/firmware/update-status`, {
|
||||
id,
|
||||
status,
|
||||
});
|
||||
}
|
||||
|
||||
/** 根据产品 ID 查询固件列表 */
|
||||
export function getOtaFirmwareListByProductId(productId: number) {
|
||||
return requestClient.get<IoTOtaFirmwareApi.Firmware[]>(
|
||||
'/iot/ota/firmware/list-by-product-id',
|
||||
{ params: { productId } },
|
||||
);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -3,45 +3,21 @@ import type { PageParam, PageResult } from '@vben/request';
|
|||
import { requestClient } from '#/api/request';
|
||||
|
||||
export namespace IoTOtaTaskApi {
|
||||
/** IoT OTA 升级任务 VO */
|
||||
/** IoT OTA 升级任务 */
|
||||
export interface Task {
|
||||
id?: number;
|
||||
name: string;
|
||||
name?: string;
|
||||
description?: string;
|
||||
firmwareId: number;
|
||||
firmwareName?: string;
|
||||
productId?: number;
|
||||
productName?: string;
|
||||
firmwareId?: number;
|
||||
status?: number;
|
||||
deviceScope?: number;
|
||||
deviceIds?: number[];
|
||||
status?: number;
|
||||
successCount?: number;
|
||||
failureCount?: number;
|
||||
pendingCount?: number;
|
||||
deviceTotalCount?: number;
|
||||
deviceSuccessCount?: number;
|
||||
createTime?: Date;
|
||||
updateTime?: Date;
|
||||
}
|
||||
}
|
||||
|
||||
/** IoT OTA 升级任务 */
|
||||
export interface OtaTask {
|
||||
id?: number;
|
||||
name?: string;
|
||||
description?: string;
|
||||
firmwareId?: number;
|
||||
firmwareName?: string;
|
||||
productId?: number;
|
||||
productName?: string;
|
||||
deviceScope?: number;
|
||||
deviceIds?: number[];
|
||||
status?: number;
|
||||
successCount?: number;
|
||||
failureCount?: number;
|
||||
pendingCount?: number;
|
||||
createTime?: Date;
|
||||
updateTime?: Date;
|
||||
}
|
||||
|
||||
/** 查询 OTA 升级任务分页 */
|
||||
export function getOtaTaskPage(params: PageParam) {
|
||||
return requestClient.get<PageResult<IoTOtaTaskApi.Task>>(
|
||||
|
|
@ -56,43 +32,11 @@ export function getOtaTask(id: number) {
|
|||
}
|
||||
|
||||
/** 新增 OTA 升级任务 */
|
||||
export function createOtaTask(data: OtaTask) {
|
||||
export function createOtaTask(data: IoTOtaTaskApi.Task) {
|
||||
return requestClient.post('/iot/ota/task/create', data);
|
||||
}
|
||||
|
||||
/** 修改 OTA 升级任务 */
|
||||
export function updateOtaTask(data: OtaTask) {
|
||||
return requestClient.put('/iot/ota/task/update', data);
|
||||
}
|
||||
|
||||
/** 删除 OTA 升级任务 */
|
||||
export function deleteOtaTask(id: number) {
|
||||
return requestClient.delete(`/iot/ota/task/delete?id=${id}`);
|
||||
}
|
||||
|
||||
/** 批量删除 OTA 升级任务 */
|
||||
export function deleteOtaTaskList(ids: number[]) {
|
||||
return requestClient.delete('/iot/ota/task/delete-list', {
|
||||
params: { ids: ids.join(',') },
|
||||
});
|
||||
}
|
||||
|
||||
/** 取消 OTA 升级任务 */
|
||||
export function cancelOtaTask(id: number) {
|
||||
return requestClient.put(`/iot/ota/task/cancel?id=${id}`);
|
||||
}
|
||||
|
||||
/** 启动 OTA 升级任务 */
|
||||
export function startOtaTask(id: number) {
|
||||
return requestClient.put(`/iot/ota/task/start?id=${id}`);
|
||||
}
|
||||
|
||||
/** 暂停 OTA 升级任务 */
|
||||
export function pauseOtaTask(id: number) {
|
||||
return requestClient.put(`/iot/ota/task/pause?id=${id}`);
|
||||
}
|
||||
|
||||
/** 恢复 OTA 升级任务 */
|
||||
export function resumeOtaTask(id: number) {
|
||||
return requestClient.put(`/iot/ota/task/resume?id=${id}`);
|
||||
return requestClient.post(`/iot/ota/task/cancel?id=${id}`);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -3,44 +3,24 @@ import type { PageParam, PageResult } from '@vben/request';
|
|||
import { requestClient } from '#/api/request';
|
||||
|
||||
export namespace IoTOtaTaskRecordApi {
|
||||
/** IoT OTA 升级任务记录 VO */
|
||||
/** IoT OTA 升级任务记录 */
|
||||
export interface TaskRecord {
|
||||
id?: number;
|
||||
taskId: number;
|
||||
taskName?: string;
|
||||
deviceId: number;
|
||||
deviceName?: string;
|
||||
firmwareId?: number;
|
||||
firmwareName?: string;
|
||||
firmwareVersion?: string;
|
||||
taskId?: number;
|
||||
deviceId?: string;
|
||||
deviceName?: string;
|
||||
currentVersion?: string;
|
||||
fromFirmwareId?: number;
|
||||
fromFirmwareVersion?: string;
|
||||
status?: number;
|
||||
progress?: number;
|
||||
errorMessage?: string;
|
||||
startTime?: Date;
|
||||
endTime?: Date;
|
||||
createTime?: Date;
|
||||
description?: string;
|
||||
updateTime?: Date;
|
||||
}
|
||||
}
|
||||
|
||||
// TODO @AI:这里应该拿到 IoTOtaTaskRecordApi 里
|
||||
/** IoT OTA 升级任务记录 */
|
||||
export interface OtaTaskRecord {
|
||||
id?: number;
|
||||
taskId?: number;
|
||||
taskName?: string;
|
||||
deviceId?: number;
|
||||
deviceName?: string;
|
||||
firmwareId?: number;
|
||||
firmwareName?: string;
|
||||
firmwareVersion?: string;
|
||||
status?: number;
|
||||
progress?: number;
|
||||
errorMessage?: string;
|
||||
startTime?: Date;
|
||||
endTime?: Date;
|
||||
createTime?: Date;
|
||||
}
|
||||
|
||||
/** 查询 OTA 升级任务记录分页 */
|
||||
export function getOtaTaskRecordPage(params: PageParam) {
|
||||
return requestClient.get<PageResult<IoTOtaTaskRecordApi.TaskRecord>>(
|
||||
|
|
@ -49,48 +29,12 @@ export function getOtaTaskRecordPage(params: PageParam) {
|
|||
);
|
||||
}
|
||||
|
||||
/** 查询 OTA 升级任务记录详情 */
|
||||
export function getOtaTaskRecord(id: number) {
|
||||
return requestClient.get<IoTOtaTaskRecordApi.TaskRecord>(
|
||||
`/iot/ota/task/record/get?id=${id}`,
|
||||
);
|
||||
}
|
||||
|
||||
/** 根据任务 ID 查询记录列表 */
|
||||
export function getOtaTaskRecordListByTaskId(taskId: number) {
|
||||
return requestClient.get<IoTOtaTaskRecordApi.TaskRecord[]>(
|
||||
'/iot/ota/task/record/list-by-task-id',
|
||||
{ params: { taskId } },
|
||||
);
|
||||
}
|
||||
|
||||
/** 根据设备 ID 查询记录列表 */
|
||||
export function getOtaTaskRecordListByDeviceId(deviceId: number) {
|
||||
return requestClient.get<IoTOtaTaskRecordApi.TaskRecord[]>(
|
||||
'/iot/ota/task/record/list-by-device-id',
|
||||
{ params: { deviceId } },
|
||||
);
|
||||
}
|
||||
|
||||
/** 根据固件 ID 查询记录列表 */
|
||||
export function getOtaTaskRecordListByFirmwareId(firmwareId: number) {
|
||||
return requestClient.get<IoTOtaTaskRecordApi.TaskRecord[]>(
|
||||
'/iot/ota/task/record/list-by-firmware-id',
|
||||
{ params: { firmwareId } },
|
||||
);
|
||||
}
|
||||
|
||||
/** 重试升级任务记录 */
|
||||
export function retryOtaTaskRecord(id: number) {
|
||||
return requestClient.put(`/iot/ota/task/record/retry?id=${id}`);
|
||||
}
|
||||
|
||||
/** 取消升级任务记录 */
|
||||
/** 取消 OTA 升级任务记录 */
|
||||
export function cancelOtaTaskRecord(id: number) {
|
||||
return requestClient.put(`/iot/ota/task/record/cancel?id=${id}`);
|
||||
}
|
||||
|
||||
/** 获取升级任务记录状态统计 */
|
||||
/** 获取 OTA 升级任务记录状态统计 */
|
||||
export function getOtaTaskRecordStatusStatistics(
|
||||
firmwareId?: number,
|
||||
taskId?: number,
|
||||
|
|
|
|||
|
|
@ -7,11 +7,10 @@ export namespace IotProductCategoryApi {
|
|||
export interface ProductCategory {
|
||||
id?: number; // 分类 ID
|
||||
name: string; // 分类名称
|
||||
parentId?: number; // 父级分类 ID
|
||||
sort?: number; // 分类排序
|
||||
status?: number; // 分类状态
|
||||
description?: string; // 分类描述
|
||||
createTime?: string; // 创建时间
|
||||
createTime?: Date; // 创建时间
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -8,8 +8,9 @@ export namespace IotProductApi {
|
|||
id?: number; // 产品编号
|
||||
name: string; // 产品名称
|
||||
productKey?: string; // 产品标识
|
||||
productSecret?: string; // 产品密钥
|
||||
protocolId?: number; // 协议编号
|
||||
protocolType?: number; // 接入协议类型
|
||||
protocolType?: string; // 协议类型
|
||||
categoryId?: number; // 产品所属品类标识符
|
||||
categoryName?: string; // 产品所属品类名称
|
||||
icon?: string; // 产品图标
|
||||
|
|
@ -17,16 +18,33 @@ export namespace IotProductApi {
|
|||
description?: string; // 产品描述
|
||||
status?: number; // 产品状态
|
||||
deviceType?: number; // 设备类型
|
||||
locationType?: number; // 定位类型
|
||||
netType?: number; // 联网方式
|
||||
codecType?: string; // 数据格式(编解码器类型)
|
||||
dataFormat?: number; // 数据格式
|
||||
validateType?: number; // 认证方式
|
||||
serializeType?: string; // 序列化类型
|
||||
registerEnabled?: boolean; // 是否开启动态注册
|
||||
deviceCount?: number; // 设备数量
|
||||
createTime?: Date; // 创建时间
|
||||
}
|
||||
}
|
||||
|
||||
// IoT 协议类型枚举
|
||||
export enum ProtocolTypeEnum {
|
||||
COAP = 'coap',
|
||||
EMQX = 'emqx',
|
||||
HTTP = 'http',
|
||||
MODBUS_TCP_CLIENT = 'modbus_tcp_client',
|
||||
MODBUS_TCP_SERVER = 'modbus_tcp_server',
|
||||
MQTT = 'mqtt',
|
||||
TCP = 'tcp',
|
||||
UDP = 'udp',
|
||||
WEBSOCKET = 'websocket',
|
||||
}
|
||||
|
||||
// IoT 序列化类型枚举
|
||||
export enum SerializeTypeEnum {
|
||||
BINARY = 'binary',
|
||||
JSON = 'json',
|
||||
}
|
||||
|
||||
/** 查询产品分页 */
|
||||
export function getProductPage(params: PageParam) {
|
||||
return requestClient.get<PageResult<IotProductApi.Product>>(
|
||||
|
|
@ -68,8 +86,13 @@ export function updateProductStatus(id: number, status: number) {
|
|||
}
|
||||
|
||||
/** 查询产品(精简)列表 */
|
||||
export function getSimpleProductList() {
|
||||
return requestClient.get<IotProductApi.Product[]>('/iot/product/simple-list');
|
||||
export function getSimpleProductList(deviceType?: number) {
|
||||
return requestClient.get<IotProductApi.Product[]>(
|
||||
'/iot/product/simple-list',
|
||||
{
|
||||
params: { deviceType },
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
/** 根据 ProductKey 获取产品信息 */
|
||||
|
|
@ -78,3 +101,10 @@ export function getProductByKey(productKey: string) {
|
|||
params: { productKey },
|
||||
});
|
||||
}
|
||||
|
||||
/** 同步产品物模型 TDengine 超级表结构 */
|
||||
export function syncProductPropertyTable(productId: number) {
|
||||
return requestClient.post(
|
||||
`/iot/product/sync-property-table?productId=${productId}`,
|
||||
);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -3,45 +3,21 @@ import type { PageParam, PageResult } from '@vben/request';
|
|||
import { requestClient } from '#/api/request';
|
||||
|
||||
export namespace DataRuleApi {
|
||||
/** IoT 数据流转规则 VO */
|
||||
export interface Rule {
|
||||
/** IoT 数据流转规则 */
|
||||
export interface DataRule {
|
||||
id?: number;
|
||||
name: string;
|
||||
name?: string;
|
||||
description?: string;
|
||||
status?: number;
|
||||
productId?: number;
|
||||
productKey?: string;
|
||||
sourceConfigs?: SourceConfig[];
|
||||
sourceConfigs?: any[];
|
||||
sinkIds?: number[];
|
||||
createTime?: Date;
|
||||
}
|
||||
|
||||
/** IoT 数据源配置 */
|
||||
export interface SourceConfig {
|
||||
productId?: number;
|
||||
productKey?: string;
|
||||
deviceId?: number;
|
||||
type?: string;
|
||||
topic?: string;
|
||||
}
|
||||
}
|
||||
|
||||
/** IoT 数据流转规则 */
|
||||
export interface DataRule {
|
||||
id?: number;
|
||||
name?: string;
|
||||
description?: string;
|
||||
status?: number;
|
||||
productId?: number;
|
||||
productKey?: string;
|
||||
sourceConfigs?: any[];
|
||||
sinkIds?: number[];
|
||||
createTime?: Date;
|
||||
}
|
||||
|
||||
/** 查询数据流转规则分页 */
|
||||
export function getDataRulePage(params: PageParam) {
|
||||
return requestClient.get<PageResult<DataRuleApi.Rule>>(
|
||||
return requestClient.get<PageResult<DataRuleApi.DataRule>>(
|
||||
'/iot/data-rule/page',
|
||||
{ params },
|
||||
);
|
||||
|
|
@ -49,16 +25,16 @@ export function getDataRulePage(params: PageParam) {
|
|||
|
||||
/** 查询数据流转规则详情 */
|
||||
export function getDataRule(id: number) {
|
||||
return requestClient.get<DataRuleApi.Rule>(`/iot/data-rule/get?id=${id}`);
|
||||
return requestClient.get<DataRuleApi.DataRule>(`/iot/data-rule/get?id=${id}`);
|
||||
}
|
||||
|
||||
/** 新增数据流转规则 */
|
||||
export function createDataRule(data: DataRule) {
|
||||
export function createDataRule(data: DataRuleApi.DataRule) {
|
||||
return requestClient.post('/iot/data-rule/create', data);
|
||||
}
|
||||
|
||||
/** 修改数据流转规则 */
|
||||
export function updateDataRule(data: DataRule) {
|
||||
export function updateDataRule(data: DataRuleApi.DataRule) {
|
||||
return requestClient.put('/iot/data-rule/update', data);
|
||||
}
|
||||
|
||||
|
|
@ -66,18 +42,3 @@ export function updateDataRule(data: DataRule) {
|
|||
export function deleteDataRule(id: number) {
|
||||
return requestClient.delete(`/iot/data-rule/delete?id=${id}`);
|
||||
}
|
||||
|
||||
/** 批量删除数据流转规则 */
|
||||
export function deleteDataRuleList(ids: number[]) {
|
||||
return requestClient.delete('/iot/data-rule/delete-list', {
|
||||
params: { ids: ids.join(',') },
|
||||
});
|
||||
}
|
||||
|
||||
/** 更新数据流转规则状态 */
|
||||
export function updateDataRuleStatus(id: number, status: number) {
|
||||
return requestClient.put(`/iot/data-rule/update-status`, {
|
||||
id,
|
||||
status,
|
||||
});
|
||||
}
|
||||
|
|
|
|||
|
|
@ -2,101 +2,147 @@ import type { PageParam, PageResult } from '@vben/request';
|
|||
|
||||
import { requestClient } from '#/api/request';
|
||||
|
||||
interface BaseConfig {
|
||||
type: string;
|
||||
}
|
||||
|
||||
export namespace DataSinkApi {
|
||||
/** IoT 数据流转目的 VO */
|
||||
export interface Sink {
|
||||
export interface DataSink {
|
||||
id?: number;
|
||||
name: string;
|
||||
name?: string;
|
||||
description?: string;
|
||||
status?: number;
|
||||
type: string;
|
||||
config?: any;
|
||||
direction?: number;
|
||||
type?: number;
|
||||
config?:
|
||||
| DatabaseConfig
|
||||
| HttpConfig
|
||||
| KafkaMQConfig
|
||||
| MqttConfig
|
||||
| RabbitMQConfig
|
||||
| RedisStreamMQConfig
|
||||
| RocketMQConfig
|
||||
| TcpConfig
|
||||
| WebSocketConfig;
|
||||
createTime?: Date;
|
||||
}
|
||||
|
||||
/** HTTP 配置 */
|
||||
export interface HttpConfig extends BaseConfig {
|
||||
url: string;
|
||||
method: string;
|
||||
headers: Record<string, string>;
|
||||
query: Record<string, string>;
|
||||
body: string;
|
||||
}
|
||||
|
||||
/** TCP 配置 */
|
||||
export interface TcpConfig extends BaseConfig {
|
||||
host: string;
|
||||
port: number;
|
||||
connectTimeoutMs: number;
|
||||
readTimeoutMs: number;
|
||||
ssl: boolean;
|
||||
sslCertPath: string;
|
||||
dataFormat: string;
|
||||
heartbeatIntervalMs: number;
|
||||
reconnectIntervalMs: number;
|
||||
maxReconnectAttempts: number;
|
||||
}
|
||||
|
||||
/** WebSocket 配置 */
|
||||
export interface WebSocketConfig extends BaseConfig {
|
||||
serverUrl: string;
|
||||
connectTimeoutMs: number;
|
||||
sendTimeoutMs: number;
|
||||
heartbeatIntervalMs: number;
|
||||
heartbeatMessage: string;
|
||||
subprotocols: string;
|
||||
customHeaders: string;
|
||||
verifySslCert: boolean;
|
||||
dataFormat: string;
|
||||
reconnectIntervalMs: number;
|
||||
maxReconnectAttempts: number;
|
||||
enableCompression: boolean;
|
||||
sendRetryCount: number;
|
||||
sendRetryIntervalMs: number;
|
||||
}
|
||||
|
||||
/** MQTT 配置 */
|
||||
export interface MqttConfig extends BaseConfig {
|
||||
url: string;
|
||||
username: string;
|
||||
password: string;
|
||||
clientId: string;
|
||||
topic: string;
|
||||
}
|
||||
|
||||
/** Database 配置 */
|
||||
export interface DatabaseConfig extends BaseConfig {
|
||||
jdbcUrl: string;
|
||||
username: string;
|
||||
password: string;
|
||||
tableName: string;
|
||||
}
|
||||
|
||||
/** RocketMQ 配置 */
|
||||
export interface RocketMQConfig extends BaseConfig {
|
||||
nameServer: string;
|
||||
accessKey: string;
|
||||
secretKey: string;
|
||||
group: string;
|
||||
topic: string;
|
||||
tags: string;
|
||||
}
|
||||
|
||||
/** Kafka 配置 */
|
||||
export interface KafkaMQConfig extends BaseConfig {
|
||||
bootstrapServers: string;
|
||||
username: string;
|
||||
password: string;
|
||||
ssl: boolean;
|
||||
topic: string;
|
||||
}
|
||||
|
||||
/** RabbitMQ 配置 */
|
||||
export interface RabbitMQConfig extends BaseConfig {
|
||||
host: string;
|
||||
port: number;
|
||||
virtualHost: string;
|
||||
username: string;
|
||||
password: string;
|
||||
exchange: string;
|
||||
routingKey: string;
|
||||
queue: string;
|
||||
}
|
||||
|
||||
/** Redis Stream MQ 配置 */
|
||||
export interface RedisStreamMQConfig extends BaseConfig {
|
||||
host: string;
|
||||
port: number;
|
||||
password: string;
|
||||
database: number;
|
||||
topic: string;
|
||||
}
|
||||
}
|
||||
|
||||
/** IoT 数据流转目的 */
|
||||
export interface DataSinkVO {
|
||||
id?: number;
|
||||
name?: string;
|
||||
description?: string;
|
||||
status?: number;
|
||||
type?: string;
|
||||
config?: any;
|
||||
createTime?: Date;
|
||||
}
|
||||
|
||||
/** IoT 数据目的类型枚举 */
|
||||
export enum IotDataSinkTypeEnum {
|
||||
HTTP = 'HTTP',
|
||||
KAFKA = 'KAFKA',
|
||||
MQTT = 'MQTT',
|
||||
RABBITMQ = 'RABBITMQ',
|
||||
REDIS_STREAM = 'REDIS_STREAM',
|
||||
ROCKETMQ = 'ROCKETMQ',
|
||||
}
|
||||
|
||||
/** HTTP 配置 */
|
||||
export interface HttpConfig {
|
||||
url?: string;
|
||||
method?: string;
|
||||
headers?: Record<string, string>;
|
||||
timeout?: number;
|
||||
}
|
||||
|
||||
/** MQTT 配置 */
|
||||
export interface MqttConfig {
|
||||
broker?: string;
|
||||
port?: number;
|
||||
topic?: string;
|
||||
username?: string;
|
||||
password?: string;
|
||||
clientId?: string;
|
||||
qos?: number;
|
||||
}
|
||||
|
||||
/** Kafka 配置 */
|
||||
export interface KafkaMQConfig {
|
||||
bootstrapServers?: string;
|
||||
topic?: string;
|
||||
acks?: string;
|
||||
retries?: number;
|
||||
batchSize?: number;
|
||||
}
|
||||
|
||||
/** RabbitMQ 配置 */
|
||||
export interface RabbitMQConfig {
|
||||
host?: string;
|
||||
port?: number;
|
||||
virtualHost?: string;
|
||||
username?: string;
|
||||
password?: string;
|
||||
exchange?: string;
|
||||
routingKey?: string;
|
||||
queue?: string;
|
||||
}
|
||||
|
||||
/** RocketMQ 配置 */
|
||||
export interface RocketMQConfig {
|
||||
nameServer?: string;
|
||||
topic?: string;
|
||||
tag?: string;
|
||||
producerGroup?: string;
|
||||
}
|
||||
|
||||
/** Redis Stream 配置 */
|
||||
export interface RedisStreamMQConfig {
|
||||
host?: string;
|
||||
port?: number;
|
||||
password?: string;
|
||||
database?: number;
|
||||
streamKey?: string;
|
||||
maxLen?: number;
|
||||
}
|
||||
/** 数据流转目的类型 */
|
||||
export const IotDataSinkTypeEnum = {
|
||||
HTTP: 1,
|
||||
TCP: 2,
|
||||
WEBSOCKET: 3,
|
||||
MQTT: 10,
|
||||
DATABASE: 20,
|
||||
REDIS_STREAM: 21,
|
||||
ROCKETMQ: 30,
|
||||
RABBITMQ: 31,
|
||||
KAFKA: 32,
|
||||
} as const;
|
||||
|
||||
/** 查询数据流转目的分页 */
|
||||
export function getDataSinkPage(params: PageParam) {
|
||||
return requestClient.get<PageResult<DataSinkApi.Sink>>(
|
||||
return requestClient.get<PageResult<DataSinkApi.DataSink>>(
|
||||
'/iot/data-sink/page',
|
||||
{ params },
|
||||
);
|
||||
|
|
@ -104,26 +150,23 @@ export function getDataSinkPage(params: PageParam) {
|
|||
|
||||
/** 查询数据流转目的详情 */
|
||||
export function getDataSink(id: number) {
|
||||
return requestClient.get<DataSinkApi.Sink>(`/iot/data-sink/get?id=${id}`);
|
||||
return requestClient.get<DataSinkApi.DataSink>(`/iot/data-sink/get?id=${id}`);
|
||||
}
|
||||
|
||||
/** 查询所有数据流转目的列表 */
|
||||
export function getDataSinkList() {
|
||||
return requestClient.get<DataSinkApi.Sink[]>('/iot/data-sink/list');
|
||||
}
|
||||
|
||||
/** 查询数据流转目的简单列表 */
|
||||
/** 查询数据流转目的(精简)列表 */
|
||||
export function getDataSinkSimpleList() {
|
||||
return requestClient.get<DataSinkApi.Sink[]>('/iot/data-sink/simple-list');
|
||||
return requestClient.get<DataSinkApi.DataSink[]>(
|
||||
'/iot/data-sink/simple-list',
|
||||
);
|
||||
}
|
||||
|
||||
/** 新增数据流转目的 */
|
||||
export function createDataSink(data: DataSinkVO) {
|
||||
export function createDataSink(data: DataSinkApi.DataSink) {
|
||||
return requestClient.post('/iot/data-sink/create', data);
|
||||
}
|
||||
|
||||
/** 修改数据流转目的 */
|
||||
export function updateDataSink(data: DataSinkVO) {
|
||||
export function updateDataSink(data: DataSinkApi.DataSink) {
|
||||
return requestClient.put('/iot/data-sink/update', data);
|
||||
}
|
||||
|
||||
|
|
@ -131,18 +174,3 @@ export function updateDataSink(data: DataSinkVO) {
|
|||
export function deleteDataSink(id: number) {
|
||||
return requestClient.delete(`/iot/data-sink/delete?id=${id}`);
|
||||
}
|
||||
|
||||
/** 批量删除数据流转目的 */
|
||||
export function deleteDataSinkList(ids: number[]) {
|
||||
return requestClient.delete('/iot/data-sink/delete-list', {
|
||||
params: { ids: ids.join(',') },
|
||||
});
|
||||
}
|
||||
|
||||
/** 更新数据流转目的状态 */
|
||||
export function updateDataSinkStatus(id: number, status: number) {
|
||||
return requestClient.put(`/iot/data-sink/update-status`, {
|
||||
id,
|
||||
status,
|
||||
});
|
||||
}
|
||||
|
|
|
|||
|
|
@ -11,25 +11,20 @@ export namespace RuleSceneApi {
|
|||
status?: number;
|
||||
triggers?: Trigger[];
|
||||
actions?: Action[];
|
||||
lastTriggeredTime?: Date;
|
||||
createTime?: Date;
|
||||
}
|
||||
|
||||
/** 场景联动规则的触发器 */
|
||||
export interface Trigger {
|
||||
type?: string;
|
||||
type?: number;
|
||||
productId?: number;
|
||||
deviceId?: number;
|
||||
identifier?: string;
|
||||
operator?: string;
|
||||
value?: any;
|
||||
cronExpression?: string;
|
||||
conditionGroups?: TriggerConditionGroup[];
|
||||
}
|
||||
|
||||
/** 场景联动规则的触发条件组 */
|
||||
export interface TriggerConditionGroup {
|
||||
conditions?: TriggerCondition[];
|
||||
operator?: string;
|
||||
conditionGroups?: TriggerCondition[][];
|
||||
}
|
||||
|
||||
/** 场景联动规则的触发条件 */
|
||||
|
|
@ -39,72 +34,22 @@ export namespace RuleSceneApi {
|
|||
identifier?: string;
|
||||
operator?: string;
|
||||
value?: any;
|
||||
type?: string;
|
||||
type?: number;
|
||||
param?: string;
|
||||
}
|
||||
|
||||
/** 场景联动规则的动作 */
|
||||
export interface Action {
|
||||
type?: string;
|
||||
type?: number;
|
||||
productId?: number;
|
||||
deviceId?: number;
|
||||
identifier?: string;
|
||||
value?: any;
|
||||
alertConfigId?: number;
|
||||
params?: string;
|
||||
}
|
||||
}
|
||||
|
||||
// TODO @haohao:貌似下面的,和 RuleSceneApi 重复了。
|
||||
/** IoT 场景联动规则 */
|
||||
export interface IotSceneRule {
|
||||
id?: number;
|
||||
name?: string;
|
||||
description?: string;
|
||||
status?: number;
|
||||
triggers?: Trigger[];
|
||||
actions?: Action[];
|
||||
createTime?: Date;
|
||||
}
|
||||
|
||||
/** IoT 场景联动规则触发器 */
|
||||
export interface Trigger {
|
||||
type?: string;
|
||||
productId?: number;
|
||||
deviceId?: number;
|
||||
identifier?: string;
|
||||
operator?: string;
|
||||
value?: any;
|
||||
cronExpression?: string;
|
||||
conditionGroups?: TriggerConditionGroup[];
|
||||
}
|
||||
|
||||
/** IoT 场景联动规则触发条件组 */
|
||||
export interface TriggerConditionGroup {
|
||||
conditions?: TriggerCondition[];
|
||||
operator?: string;
|
||||
}
|
||||
|
||||
/** IoT 场景联动规则触发条件 */
|
||||
export interface TriggerCondition {
|
||||
productId?: number;
|
||||
deviceId?: number;
|
||||
identifier?: string;
|
||||
operator?: string;
|
||||
value?: any;
|
||||
type?: string;
|
||||
param?: string;
|
||||
}
|
||||
|
||||
/** IoT 场景联动规则动作 */
|
||||
export interface Action {
|
||||
type?: string;
|
||||
productId?: number;
|
||||
deviceId?: number;
|
||||
identifier?: string;
|
||||
value?: any;
|
||||
alertConfigId?: number;
|
||||
params?: string;
|
||||
}
|
||||
|
||||
/** 查询场景联动规则分页 */
|
||||
export function getSceneRulePage(params: PageParam) {
|
||||
return requestClient.get<PageResult<RuleSceneApi.SceneRule>>(
|
||||
|
|
@ -121,12 +66,12 @@ export function getSceneRule(id: number) {
|
|||
}
|
||||
|
||||
/** 新增场景联动规则 */
|
||||
export function createSceneRule(data: IotSceneRule) {
|
||||
export function createSceneRule(data: RuleSceneApi.SceneRule) {
|
||||
return requestClient.post('/iot/scene-rule/create', data);
|
||||
}
|
||||
|
||||
/** 修改场景联动规则 */
|
||||
export function updateSceneRule(data: IotSceneRule) {
|
||||
export function updateSceneRule(data: RuleSceneApi.SceneRule) {
|
||||
return requestClient.put('/iot/scene-rule/update', data);
|
||||
}
|
||||
|
||||
|
|
@ -136,7 +81,6 @@ export function deleteSceneRule(id: number) {
|
|||
}
|
||||
|
||||
/** 批量删除场景联动规则 */
|
||||
// TODO @haohao:貌似用上。
|
||||
export function deleteSceneRuleList(ids: number[]) {
|
||||
return requestClient.delete('/iot/scene-rule/delete-list', {
|
||||
params: { ids: ids.join(',') },
|
||||
|
|
|
|||
|
|
@ -17,18 +17,6 @@ export namespace IotStatisticsApi {
|
|||
productCategoryDeviceCounts: Record<string, number>; // 按品类统计的设备数量
|
||||
}
|
||||
|
||||
/** 时间戳-数值的键值对类型 */
|
||||
export interface TimeValueItem {
|
||||
[key: string]: number;
|
||||
}
|
||||
|
||||
/** 消息统计数据类型 */
|
||||
export interface DeviceMessageSummary {
|
||||
statType: number;
|
||||
upstreamCounts: TimeValueItem[];
|
||||
downstreamCounts: TimeValueItem[];
|
||||
}
|
||||
|
||||
/** 设备消息数量统计(按日期) */
|
||||
export interface DeviceMessageSummaryByDateRespVO {
|
||||
time: string; // 时间轴
|
||||
|
|
|
|||
|
|
@ -1,126 +1,209 @@
|
|||
import type { Rule } from 'ant-design-vue/es/form';
|
||||
|
||||
import type { PageParam, PageResult } from '@vben/request';
|
||||
|
||||
import { isEmpty } from '@vben/utils';
|
||||
|
||||
import { requestClient } from '#/api/request';
|
||||
|
||||
export namespace ThingModelApi {
|
||||
/** IoT 物模型数据 VO */
|
||||
/** IoT 物模型数据 */
|
||||
export interface ThingModel {
|
||||
id?: number;
|
||||
productId?: number;
|
||||
productKey?: string;
|
||||
identifier: string;
|
||||
name: string;
|
||||
desc?: string;
|
||||
type: string;
|
||||
property?: ThingModelProperty;
|
||||
event?: ThingModelEvent;
|
||||
service?: ThingModelService;
|
||||
identifier?: string;
|
||||
name?: string;
|
||||
description?: string;
|
||||
dataType?: string;
|
||||
type?: number; // 参见 IoTThingModelTypeEnum 枚举类
|
||||
property?: Property;
|
||||
event?: Event;
|
||||
service?: Service;
|
||||
}
|
||||
|
||||
/** IoT 物模型属性 */
|
||||
export interface Property {
|
||||
identifier: string;
|
||||
name: string;
|
||||
accessMode: string;
|
||||
dataType: string;
|
||||
identifier?: string;
|
||||
name?: string;
|
||||
accessMode?: string;
|
||||
required?: boolean;
|
||||
dataType?: string;
|
||||
description?: string;
|
||||
dataSpecs?: any;
|
||||
dataSpecsList?: any[];
|
||||
desc?: string;
|
||||
}
|
||||
|
||||
/** IoT 物模型服务 */
|
||||
export interface Service {
|
||||
identifier: string;
|
||||
name: string;
|
||||
callType: string;
|
||||
inputData?: any[];
|
||||
outputData?: any[];
|
||||
desc?: string;
|
||||
identifier?: string;
|
||||
name?: string;
|
||||
required?: boolean;
|
||||
callType?: string;
|
||||
description?: string;
|
||||
inputParams?: Param[];
|
||||
outputParams?: Param[];
|
||||
method?: string;
|
||||
}
|
||||
|
||||
/** IoT 物模型事件 */
|
||||
export interface Event {
|
||||
identifier: string;
|
||||
identifier?: string;
|
||||
name?: string;
|
||||
required?: boolean;
|
||||
type?: string;
|
||||
description?: string;
|
||||
outputParams?: Param[];
|
||||
method?: string;
|
||||
}
|
||||
|
||||
/** IoT 物模型参数 */
|
||||
export interface Param {
|
||||
identifier?: string;
|
||||
name?: string;
|
||||
direction?: string;
|
||||
paraOrder?: number;
|
||||
dataType?: string;
|
||||
dataSpecs?: any;
|
||||
dataSpecsList?: any[];
|
||||
}
|
||||
|
||||
/** IoT 物模型 TSL(树形)响应 */
|
||||
export interface ThingModelTSL {
|
||||
productId?: number;
|
||||
productKey?: string;
|
||||
properties?: Property[];
|
||||
events?: Event[];
|
||||
services?: Service[];
|
||||
}
|
||||
|
||||
/** IoT 数据定义(数值型) */
|
||||
export interface DataSpecsNumberData {
|
||||
min?: number | string;
|
||||
max?: number | string;
|
||||
step?: number | string;
|
||||
unit?: string;
|
||||
unitName?: string;
|
||||
}
|
||||
|
||||
/** IoT 数据定义(枚举/布尔型) */
|
||||
export interface DataSpecsEnumOrBoolData {
|
||||
value: number | string;
|
||||
name: string;
|
||||
type: string;
|
||||
outputData?: any[];
|
||||
desc?: string;
|
||||
}
|
||||
}
|
||||
|
||||
/** IoT 物模型数据 */
|
||||
export interface ThingModelData {
|
||||
id?: number;
|
||||
productId?: number;
|
||||
productKey?: string;
|
||||
identifier?: string;
|
||||
name?: string;
|
||||
desc?: string;
|
||||
type?: string;
|
||||
dataType?: string;
|
||||
property?: ThingModelProperty;
|
||||
event?: ThingModelEvent;
|
||||
service?: ThingModelService;
|
||||
/** 生成「必填 + 数字」类校验器:拼到 size / length / 枚举值上 */
|
||||
function buildRequiredNumberValidator(label: string) {
|
||||
return (_rule: any, value: any, callback: any) => {
|
||||
if (isEmpty(value)) {
|
||||
callback(new Error(`${label}不能为空`));
|
||||
return;
|
||||
}
|
||||
if (Number.isNaN(Number(value))) {
|
||||
callback(new Error(`${label}必须是数字`));
|
||||
return;
|
||||
}
|
||||
callback();
|
||||
};
|
||||
}
|
||||
|
||||
/** IoT 物模型属性 */
|
||||
export interface ThingModelProperty {
|
||||
identifier?: string;
|
||||
name?: string;
|
||||
accessMode?: string;
|
||||
dataType?: string;
|
||||
dataSpecs?: any;
|
||||
dataSpecsList?: any[];
|
||||
desc?: string;
|
||||
}
|
||||
|
||||
/** IoT 物模型服务 */
|
||||
export interface ThingModelService {
|
||||
identifier?: string;
|
||||
name?: string;
|
||||
callType?: string;
|
||||
inputData?: any[];
|
||||
outputData?: any[];
|
||||
desc?: string;
|
||||
}
|
||||
|
||||
/** IoT 物模型事件 */
|
||||
export interface ThingModelEvent {
|
||||
identifier?: string;
|
||||
name?: string;
|
||||
type?: string;
|
||||
outputData?: any[];
|
||||
desc?: string;
|
||||
}
|
||||
|
||||
/** IoT 数据定义(数值型) */
|
||||
export interface DataSpecsNumberData {
|
||||
min?: number | string;
|
||||
max?: number | string;
|
||||
step?: number | string;
|
||||
unit?: string;
|
||||
unitName?: string;
|
||||
}
|
||||
|
||||
/** IoT 数据定义(枚举/布尔型) */
|
||||
export interface DataSpecsEnumOrBoolData {
|
||||
value: number | string;
|
||||
name: string;
|
||||
/** 生成「标识符样式」名称校验器:开头需为中文 / 英文 / 数字,整体仅允许中文、英文、数字、下划线、短划线,长度 ≤ 20 */
|
||||
export function buildIdentifierLikeNameValidator(label: string) {
|
||||
return (_rule: any, value: string, callback: any) => {
|
||||
if (isEmpty(value)) {
|
||||
callback(new Error(`${label}不能为空`));
|
||||
return;
|
||||
}
|
||||
if (!/^[一-龥A-Za-z0-9]/.test(value)) {
|
||||
callback(new Error(`${label}必须以中文、英文字母或数字开头`));
|
||||
return;
|
||||
}
|
||||
if (!/^[一-龥A-Za-z0-9][\w一-龥-]*$/.test(value)) {
|
||||
callback(
|
||||
new Error(`${label}只能包含中文、英文字母、数字、下划线和短划线`),
|
||||
);
|
||||
return;
|
||||
}
|
||||
if (value.length > 20) {
|
||||
callback(new Error(`${label}长度不能超过 20 个字符`));
|
||||
return;
|
||||
}
|
||||
callback();
|
||||
};
|
||||
}
|
||||
|
||||
/** IoT 物模型表单校验规则 */
|
||||
export interface ThingModelFormRules {
|
||||
[key: string]: any;
|
||||
}
|
||||
export const ThingModelFormRules: Record<string, Rule[]> = {
|
||||
name: [
|
||||
{ required: true, message: '功能名称不能为空', trigger: 'blur' },
|
||||
{
|
||||
pattern: /^[一-龥A-Za-z0-9][一-龥A-Za-z0-9\-_/.]{0,29}$/,
|
||||
message:
|
||||
'支持中文、大小写字母、日文、数字、短划线、下划线、斜杠和小数点,必须以中文、英文或数字开头,不超过 30 个字符',
|
||||
trigger: 'blur',
|
||||
},
|
||||
],
|
||||
type: [{ required: true, message: '功能类型不能为空', trigger: 'blur' }],
|
||||
identifier: [
|
||||
{ required: true, message: '标识符不能为空', trigger: 'blur' },
|
||||
{
|
||||
pattern: /^\w{1,50}$/,
|
||||
message: '支持大小写字母、数字和下划线,不超过 50 个字符',
|
||||
trigger: 'blur',
|
||||
},
|
||||
{
|
||||
validator: (_rule: any, value: string, callback: any) => {
|
||||
const reservedKeywords = [
|
||||
'set',
|
||||
'get',
|
||||
'post',
|
||||
'property',
|
||||
'event',
|
||||
'time',
|
||||
'value',
|
||||
];
|
||||
if (reservedKeywords.includes(value)) {
|
||||
callback(
|
||||
new Error(
|
||||
'set, get, post, property, event, time, value 是系统保留字段,不能用于标识符定义',
|
||||
),
|
||||
);
|
||||
return;
|
||||
}
|
||||
if (/^\d+$/.test(value)) {
|
||||
callback(new Error('标识符不能是纯数字'));
|
||||
return;
|
||||
}
|
||||
callback();
|
||||
},
|
||||
trigger: 'blur',
|
||||
},
|
||||
],
|
||||
childDataType: [{ required: true, message: '元素类型不能为空' }],
|
||||
size: [
|
||||
{
|
||||
required: true,
|
||||
validator: buildRequiredNumberValidator('元素个数'),
|
||||
trigger: 'blur',
|
||||
},
|
||||
],
|
||||
length: [
|
||||
{
|
||||
required: true,
|
||||
validator: buildRequiredNumberValidator('文本长度'),
|
||||
trigger: 'blur',
|
||||
},
|
||||
],
|
||||
accessMode: [
|
||||
{ required: true, message: '请选择读写类型', trigger: 'change' },
|
||||
],
|
||||
callType: [{ required: true, message: '请选择调用方式', trigger: 'change' }],
|
||||
eventType: [{ required: true, message: '请选择事件类型', trigger: 'change' }],
|
||||
};
|
||||
|
||||
/** 验证布尔型名称 */
|
||||
export function validateBoolName(_rule: any, value: any, callback: any) {
|
||||
if (value) {
|
||||
callback();
|
||||
} else {
|
||||
callback(new Error('枚举描述不能为空'));
|
||||
}
|
||||
}
|
||||
/** 校验布尔值名称 */
|
||||
export const validateBoolName = buildIdentifierLikeNameValidator('布尔值名称');
|
||||
|
||||
/** 查询产品物模型分页 */
|
||||
export function getThingModelPage(params: PageParam) {
|
||||
|
|
@ -141,17 +224,19 @@ export function getThingModel(id: number) {
|
|||
export function getThingModelListByProductId(productId: number) {
|
||||
return requestClient.get<ThingModelApi.ThingModel[]>(
|
||||
'/iot/thing-model/list',
|
||||
{ params: { productId } },
|
||||
{
|
||||
params: { productId },
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
/** 新增物模型 */
|
||||
export function createThingModel(data: ThingModelData) {
|
||||
export function createThingModel(data: ThingModelApi.ThingModel) {
|
||||
return requestClient.post('/iot/thing-model/create', data);
|
||||
}
|
||||
|
||||
/** 修改物模型 */
|
||||
export function updateThingModel(data: ThingModelData) {
|
||||
export function updateThingModel(data: ThingModelApi.ThingModel) {
|
||||
return requestClient.put('/iot/thing-model/update', data);
|
||||
}
|
||||
|
||||
|
|
@ -161,26 +246,11 @@ export function deleteThingModel(id: number) {
|
|||
}
|
||||
|
||||
/** 获取物模型 TSL */
|
||||
export function getThingModelTSL(productId: number) {
|
||||
return requestClient.get<ThingModelApi.ThingModel[]>(
|
||||
export function getThingModelTSLByProductId(productId: number) {
|
||||
return requestClient.get<ThingModelApi.ThingModelTSL>(
|
||||
'/iot/thing-model/get-tsl',
|
||||
{ params: { productId } },
|
||||
{
|
||||
params: { productId },
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
/** 导入物模型 TSL
|
||||
export function importThingModelTSL(productId: number, tslData: any) {
|
||||
return requestClient.post('/iot/thing-model/import-tsl', {
|
||||
productId,
|
||||
tslData,
|
||||
});
|
||||
}
|
||||
*/
|
||||
|
||||
/** 导出物模型 TSL
|
||||
export function exportThingModelTSL(productId: number) {
|
||||
return requestClient.get<any>('/iot/thing-model/export-tsl', {
|
||||
params: { productId },
|
||||
});
|
||||
}
|
||||
*/
|
||||
|
|
|
|||
|
|
@ -0,0 +1,27 @@
|
|||
import { requestClient } from '#/api/request';
|
||||
|
||||
export namespace MesCalCalendarApi {
|
||||
/** 排班日历班组排班项 */
|
||||
export interface CalendarTeamShiftItem {
|
||||
teamId?: number; // 班组编号
|
||||
teamName?: string; // 班组名称
|
||||
shiftId?: number; // 班次编号
|
||||
shiftName?: string; // 班次名称
|
||||
sort?: number; // 排序
|
||||
}
|
||||
|
||||
/** 排班日历天 */
|
||||
export interface CalendarDay {
|
||||
day?: string; // 日期
|
||||
shiftType?: number; // 轮班方式
|
||||
teamShifts?: CalendarTeamShiftItem[]; // 班组班次
|
||||
}
|
||||
}
|
||||
|
||||
/** 查询排班日历列表 */
|
||||
export function getCalendarList(params: any) {
|
||||
return requestClient.get<MesCalCalendarApi.CalendarDay[]>(
|
||||
'/mes/cal/calendar/list',
|
||||
{ params },
|
||||
);
|
||||
}
|
||||
|
|
@ -0,0 +1,39 @@
|
|||
import { requestClient } from '#/api/request';
|
||||
|
||||
export namespace MesCalHolidayApi {
|
||||
/** MES 假期设置 */
|
||||
export interface Holiday {
|
||||
id?: number; // 编号
|
||||
day?: number | string; // 日期
|
||||
type?: number; // 日期类型
|
||||
remark?: string; // 备注
|
||||
createTime?: Date; // 创建时间
|
||||
}
|
||||
|
||||
/** 假期查询参数 */
|
||||
export interface HolidayQuery {
|
||||
startDay?: string;
|
||||
endDay?: string;
|
||||
}
|
||||
}
|
||||
|
||||
/** 查询假期设置列表 */
|
||||
export function getHolidayList(params?: MesCalHolidayApi.HolidayQuery) {
|
||||
return requestClient.get<MesCalHolidayApi.Holiday[]>(
|
||||
'/mes/cal/holiday/list',
|
||||
{ params },
|
||||
);
|
||||
}
|
||||
|
||||
/** 根据日期查询假期设置 */
|
||||
export function getHolidayByDay(day: string) {
|
||||
return requestClient.get<MesCalHolidayApi.Holiday>(
|
||||
'/mes/cal/holiday/get-by-day',
|
||||
{ params: { day } },
|
||||
);
|
||||
}
|
||||
|
||||
/** 保存假期设置 */
|
||||
export function saveHoliday(data: MesCalHolidayApi.Holiday) {
|
||||
return requestClient.post('/mes/cal/holiday/save', data);
|
||||
}
|
||||
|
|
@ -0,0 +1,59 @@
|
|||
import type { PageParam, PageResult } from '@vben/request';
|
||||
|
||||
import { requestClient } from '#/api/request';
|
||||
|
||||
export namespace MesCalPlanApi {
|
||||
/** MES 排班计划 */
|
||||
export interface Plan {
|
||||
id?: number; // 计划编号
|
||||
code?: string; // 计划编码
|
||||
name?: string; // 计划名称
|
||||
calendarType?: number; // 班组类型
|
||||
startDate?: number; // 开始日期
|
||||
endDate?: number; // 结束日期
|
||||
shiftType?: number; // 轮班方式
|
||||
shiftMethod?: number; // 倒班方式
|
||||
shiftCount?: number; // 倒班天数
|
||||
status?: number; // 状态
|
||||
remark?: string; // 备注
|
||||
createTime?: Date; // 创建时间
|
||||
}
|
||||
}
|
||||
|
||||
/** 查询排班计划分页 */
|
||||
export function getPlanPage(params: PageParam) {
|
||||
return requestClient.get<PageResult<MesCalPlanApi.Plan>>(
|
||||
'/mes/cal/plan/page',
|
||||
{ params },
|
||||
);
|
||||
}
|
||||
|
||||
/** 查询排班计划详情 */
|
||||
export function getPlan(id: number) {
|
||||
return requestClient.get<MesCalPlanApi.Plan>(`/mes/cal/plan/get?id=${id}`);
|
||||
}
|
||||
|
||||
/** 新增排班计划 */
|
||||
export function createPlan(data: MesCalPlanApi.Plan) {
|
||||
return requestClient.post<number>('/mes/cal/plan/create', data);
|
||||
}
|
||||
|
||||
/** 修改排班计划 */
|
||||
export function updatePlan(data: MesCalPlanApi.Plan) {
|
||||
return requestClient.put('/mes/cal/plan/update', data);
|
||||
}
|
||||
|
||||
/** 确认排班计划 */
|
||||
export function confirmPlan(id: number) {
|
||||
return requestClient.put(`/mes/cal/plan/confirm?id=${id}`);
|
||||
}
|
||||
|
||||
/** 删除排班计划 */
|
||||
export function deletePlan(id: number) {
|
||||
return requestClient.delete(`/mes/cal/plan/delete?id=${id}`);
|
||||
}
|
||||
|
||||
/** 导出排班计划 */
|
||||
export function exportPlan(params: any) {
|
||||
return requestClient.download('/mes/cal/plan/export-excel', { params });
|
||||
}
|
||||
|
|
@ -0,0 +1,36 @@
|
|||
import { requestClient } from '#/api/request';
|
||||
|
||||
export namespace MesCalPlanShiftApi {
|
||||
/** MES 计划班次 */
|
||||
export interface PlanShift {
|
||||
id?: number; // 班次编号
|
||||
planId?: number; // 排班计划编号
|
||||
sort?: number; // 显示顺序
|
||||
name?: string; // 班次名称
|
||||
startTime?: string; // 开始时间
|
||||
endTime?: string; // 结束时间
|
||||
remark?: string; // 备注
|
||||
}
|
||||
}
|
||||
|
||||
/** 查询指定排班计划的班次列表 */
|
||||
export function getPlanShiftListByPlan(planId: number) {
|
||||
return requestClient.get<MesCalPlanShiftApi.PlanShift[]>(
|
||||
`/mes/cal/plan-shift/list-by-plan?planId=${planId}`,
|
||||
);
|
||||
}
|
||||
|
||||
/** 新增计划班次 */
|
||||
export function createPlanShift(data: MesCalPlanShiftApi.PlanShift) {
|
||||
return requestClient.post('/mes/cal/plan-shift/create', data);
|
||||
}
|
||||
|
||||
/** 修改计划班次 */
|
||||
export function updatePlanShift(data: MesCalPlanShiftApi.PlanShift) {
|
||||
return requestClient.put('/mes/cal/plan-shift/update', data);
|
||||
}
|
||||
|
||||
/** 删除计划班次 */
|
||||
export function deletePlanShift(id: number) {
|
||||
return requestClient.delete(`/mes/cal/plan-shift/delete?id=${id}`);
|
||||
}
|
||||
|
|
@ -0,0 +1,30 @@
|
|||
import { requestClient } from '#/api/request';
|
||||
|
||||
export namespace MesCalPlanTeamApi {
|
||||
/** MES 计划班组关联 */
|
||||
export interface PlanTeam {
|
||||
id?: number; // 关联编号
|
||||
planId?: number; // 排班计划编号
|
||||
teamId?: number; // 班组编号
|
||||
teamCode?: string; // 班组编码
|
||||
teamName?: string; // 班组名称
|
||||
remark?: string; // 备注
|
||||
}
|
||||
}
|
||||
|
||||
/** 查询指定排班计划的班组列表 */
|
||||
export function getPlanTeamListByPlan(planId: number) {
|
||||
return requestClient.get<MesCalPlanTeamApi.PlanTeam[]>(
|
||||
`/mes/cal/plan-team/list-by-plan?planId=${planId}`,
|
||||
);
|
||||
}
|
||||
|
||||
/** 新增计划班组关联 */
|
||||
export function createPlanTeam(data: MesCalPlanTeamApi.PlanTeam) {
|
||||
return requestClient.post('/mes/cal/plan-team/create', data);
|
||||
}
|
||||
|
||||
/** 删除计划班组关联 */
|
||||
export function deletePlanTeam(id: number) {
|
||||
return requestClient.delete(`/mes/cal/plan-team/delete?id=${id}`);
|
||||
}
|
||||
|
|
@ -0,0 +1,53 @@
|
|||
import type { PageParam, PageResult } from '@vben/request';
|
||||
|
||||
import { requestClient } from '#/api/request';
|
||||
|
||||
export namespace MesCalTeamApi {
|
||||
/** MES 班组 */
|
||||
export interface Team {
|
||||
id?: number; // 班组编号
|
||||
code?: string; // 班组编码
|
||||
name?: string; // 班组名称
|
||||
calendarType?: number; // 班组类型
|
||||
remark?: string; // 备注
|
||||
createTime?: Date; // 创建时间
|
||||
}
|
||||
}
|
||||
|
||||
/** 查询班组分页 */
|
||||
export function getTeamPage(params: PageParam) {
|
||||
return requestClient.get<PageResult<MesCalTeamApi.Team>>(
|
||||
'/mes/cal/team/page',
|
||||
{ params },
|
||||
);
|
||||
}
|
||||
|
||||
/** 查询班组列表 */
|
||||
export function getTeamList() {
|
||||
return requestClient.get<MesCalTeamApi.Team[]>('/mes/cal/team/list');
|
||||
}
|
||||
|
||||
/** 查询班组详情 */
|
||||
export function getTeam(id: number) {
|
||||
return requestClient.get<MesCalTeamApi.Team>(`/mes/cal/team/get?id=${id}`);
|
||||
}
|
||||
|
||||
/** 新增班组 */
|
||||
export function createTeam(data: MesCalTeamApi.Team) {
|
||||
return requestClient.post('/mes/cal/team/create', data);
|
||||
}
|
||||
|
||||
/** 修改班组 */
|
||||
export function updateTeam(data: MesCalTeamApi.Team) {
|
||||
return requestClient.put('/mes/cal/team/update', data);
|
||||
}
|
||||
|
||||
/** 删除班组 */
|
||||
export function deleteTeam(id: number) {
|
||||
return requestClient.delete(`/mes/cal/team/delete?id=${id}`);
|
||||
}
|
||||
|
||||
/** 导出班组 */
|
||||
export function exportTeam(params: any) {
|
||||
return requestClient.download('/mes/cal/team/export-excel', { params });
|
||||
}
|
||||
|
|
@ -0,0 +1,51 @@
|
|||
import type { PageParam, PageResult } from '@vben/request';
|
||||
|
||||
import { requestClient } from '#/api/request';
|
||||
|
||||
export namespace MesCalTeamMemberApi {
|
||||
/** MES 班组成员 */
|
||||
export interface TeamMember {
|
||||
id?: number; // 成员编号
|
||||
teamId?: number; // 班组编号
|
||||
userId?: number; // 用户编号
|
||||
nickname?: string; // 用户昵称
|
||||
telephone?: string; // 用户手机号
|
||||
remark?: string; // 备注
|
||||
}
|
||||
}
|
||||
|
||||
/** 创建班组成员 */
|
||||
export function createTeamMember(data: MesCalTeamMemberApi.TeamMember) {
|
||||
return requestClient.post('/mes/cal/team-member/create', data);
|
||||
}
|
||||
|
||||
/** 删除班组成员 */
|
||||
export function deleteTeamMember(id: number) {
|
||||
return requestClient.delete(`/mes/cal/team-member/delete?id=${id}`);
|
||||
}
|
||||
|
||||
/** 查询班组成员分页 */
|
||||
export function getTeamMemberPage(params: PageParam) {
|
||||
return requestClient.get<PageResult<MesCalTeamMemberApi.TeamMember>>(
|
||||
'/mes/cal/team-member/page',
|
||||
{ params },
|
||||
);
|
||||
}
|
||||
|
||||
/** 查询指定班组的成员列表 */
|
||||
export function getTeamMemberListByTeam(teamId: number) {
|
||||
return requestClient.get<MesCalTeamMemberApi.TeamMember[]>(
|
||||
'/mes/cal/team-member/list-by-team',
|
||||
{ params: { teamId } },
|
||||
);
|
||||
}
|
||||
|
||||
/** 查询多个班组的成员列表 */
|
||||
export function getTeamMemberListByTeamIds(teamIds: number[]) {
|
||||
return requestClient.get<MesCalTeamMemberApi.TeamMember[]>(
|
||||
'/mes/cal/team-member/list-by-team',
|
||||
{
|
||||
params: { teamIds: teamIds.join(',') },
|
||||
},
|
||||
);
|
||||
}
|
||||
|
|
@ -0,0 +1,65 @@
|
|||
import type { PageParam, PageResult } from '@vben/request';
|
||||
|
||||
import { requestClient } from '#/api/request';
|
||||
|
||||
export namespace MesDvCheckPlanApi {
|
||||
/** MES 点检保养方案 */
|
||||
export interface CheckPlan {
|
||||
id?: number; // 方案编号
|
||||
code?: string; // 方案编码
|
||||
name?: string; // 方案名称
|
||||
type?: number; // 方案类型
|
||||
startDate?: Date | number; // 开始日期
|
||||
endDate?: Date | number; // 结束日期
|
||||
cycleType?: number; // 周期类型
|
||||
cycleCount?: number; // 周期数量
|
||||
status?: number; // 状态
|
||||
remark?: string; // 备注
|
||||
createTime?: Date; // 创建时间
|
||||
}
|
||||
}
|
||||
|
||||
/** 查询点检保养方案分页 */
|
||||
export function getCheckPlanPage(params: PageParam) {
|
||||
return requestClient.get<PageResult<MesDvCheckPlanApi.CheckPlan>>(
|
||||
'/mes/dv/check-plan/page',
|
||||
{ params },
|
||||
);
|
||||
}
|
||||
|
||||
/** 查询点检保养方案详情 */
|
||||
export function getCheckPlan(id: number) {
|
||||
return requestClient.get<MesDvCheckPlanApi.CheckPlan>(
|
||||
`/mes/dv/check-plan/get?id=${id}`,
|
||||
);
|
||||
}
|
||||
|
||||
/** 新增点检保养方案 */
|
||||
export function createCheckPlan(data: MesDvCheckPlanApi.CheckPlan) {
|
||||
return requestClient.post<number>('/mes/dv/check-plan/create', data);
|
||||
}
|
||||
|
||||
/** 修改点检保养方案 */
|
||||
export function updateCheckPlan(data: MesDvCheckPlanApi.CheckPlan) {
|
||||
return requestClient.put('/mes/dv/check-plan/update', data);
|
||||
}
|
||||
|
||||
/** 启用点检保养方案 */
|
||||
export function enableCheckPlan(id: number) {
|
||||
return requestClient.put(`/mes/dv/check-plan/enable?id=${id}`);
|
||||
}
|
||||
|
||||
/** 停用点检保养方案 */
|
||||
export function disableCheckPlan(id: number) {
|
||||
return requestClient.put(`/mes/dv/check-plan/disable?id=${id}`);
|
||||
}
|
||||
|
||||
/** 删除点检保养方案 */
|
||||
export function deleteCheckPlan(id: number) {
|
||||
return requestClient.delete(`/mes/dv/check-plan/delete?id=${id}`);
|
||||
}
|
||||
|
||||
/** 导出点检保养方案 */
|
||||
export function exportCheckPlan(params: any) {
|
||||
return requestClient.download('/mes/dv/check-plan/export-excel', { params });
|
||||
}
|
||||
|
|
@ -0,0 +1,34 @@
|
|||
import { requestClient } from '#/api/request';
|
||||
|
||||
export namespace MesDvCheckPlanMachineryApi {
|
||||
/** MES 点检保养方案设备 */
|
||||
export interface CheckPlanMachinery {
|
||||
id?: number; // 关联编号
|
||||
planId?: number; // 方案编号
|
||||
machineryId?: number; // 设备编号
|
||||
machineryCode?: string; // 设备编码
|
||||
machineryName?: string; // 设备名称
|
||||
machineryBrand?: string; // 品牌
|
||||
machinerySpecification?: string; // 规格型号
|
||||
remark?: string; // 备注
|
||||
}
|
||||
}
|
||||
|
||||
/** 查询指定方案的设备列表 */
|
||||
export function getCheckPlanMachineryListByPlan(planId: number) {
|
||||
return requestClient.get<MesDvCheckPlanMachineryApi.CheckPlanMachinery[]>(
|
||||
`/mes/dv/check-plan-machinery/list-by-plan?planId=${planId}`,
|
||||
);
|
||||
}
|
||||
|
||||
/** 新增方案设备关联 */
|
||||
export function createCheckPlanMachinery(
|
||||
data: MesDvCheckPlanMachineryApi.CheckPlanMachinery,
|
||||
) {
|
||||
return requestClient.post('/mes/dv/check-plan-machinery/create', data);
|
||||
}
|
||||
|
||||
/** 删除方案设备关联 */
|
||||
export function deleteCheckPlanMachinery(id: number) {
|
||||
return requestClient.delete(`/mes/dv/check-plan-machinery/delete?id=${id}`);
|
||||
}
|
||||
|
|
@ -0,0 +1,35 @@
|
|||
import { requestClient } from '#/api/request';
|
||||
|
||||
export namespace MesDvCheckPlanSubjectApi {
|
||||
/** MES 点检保养方案项目 */
|
||||
export interface CheckPlanSubject {
|
||||
id?: number; // 关联编号
|
||||
planId?: number; // 方案编号
|
||||
subjectId?: number; // 项目编号
|
||||
subjectCode?: string; // 项目编码
|
||||
subjectName?: string; // 项目名称
|
||||
subjectType?: number; // 项目类型
|
||||
subjectContent?: string; // 项目内容
|
||||
subjectStandard?: string; // 标准
|
||||
remark?: string; // 备注
|
||||
}
|
||||
}
|
||||
|
||||
/** 查询指定方案的项目列表 */
|
||||
export function getCheckPlanSubjectListByPlan(planId: number) {
|
||||
return requestClient.get<MesDvCheckPlanSubjectApi.CheckPlanSubject[]>(
|
||||
`/mes/dv/check-plan-subject/list-by-plan?planId=${planId}`,
|
||||
);
|
||||
}
|
||||
|
||||
/** 新增方案项目关联 */
|
||||
export function createCheckPlanSubject(
|
||||
data: MesDvCheckPlanSubjectApi.CheckPlanSubject,
|
||||
) {
|
||||
return requestClient.post('/mes/dv/check-plan-subject/create', data);
|
||||
}
|
||||
|
||||
/** 删除方案项目关联 */
|
||||
export function deleteCheckPlanSubject(id: number) {
|
||||
return requestClient.delete(`/mes/dv/check-plan-subject/delete?id=${id}`);
|
||||
}
|
||||
|
|
@ -0,0 +1,65 @@
|
|||
import type { PageParam, PageResult } from '@vben/request';
|
||||
|
||||
import { requestClient } from '#/api/request';
|
||||
|
||||
export namespace MesDvCheckRecordApi {
|
||||
/** MES 设备点检记录 */
|
||||
export interface CheckRecord {
|
||||
id?: number; // 记录编号
|
||||
planId?: number; // 点检计划编号
|
||||
planName?: string; // 计划名称
|
||||
machineryId?: number; // 设备编号
|
||||
machineryCode?: string; // 设备编码
|
||||
machineryName?: string; // 设备名称
|
||||
machineryBrand?: string; // 品牌
|
||||
machinerySpecification?: string; // 规格型号
|
||||
checkTime?: Date | number; // 点检时间
|
||||
userId?: number; // 点检人编号
|
||||
nickname?: string; // 点检人名称
|
||||
status?: number; // 状态
|
||||
remark?: string; // 备注
|
||||
createTime?: Date; // 创建时间
|
||||
}
|
||||
}
|
||||
|
||||
/** 查询设备点检记录分页 */
|
||||
export function getCheckRecordPage(params: PageParam) {
|
||||
return requestClient.get<PageResult<MesDvCheckRecordApi.CheckRecord>>(
|
||||
'/mes/dv/check-record/page',
|
||||
{ params },
|
||||
);
|
||||
}
|
||||
|
||||
/** 查询设备点检记录详情 */
|
||||
export function getCheckRecord(id: number) {
|
||||
return requestClient.get<MesDvCheckRecordApi.CheckRecord>(
|
||||
`/mes/dv/check-record/get?id=${id}`,
|
||||
);
|
||||
}
|
||||
|
||||
/** 新增设备点检记录 */
|
||||
export function createCheckRecord(data: MesDvCheckRecordApi.CheckRecord) {
|
||||
return requestClient.post<number>('/mes/dv/check-record/create', data);
|
||||
}
|
||||
|
||||
/** 修改设备点检记录 */
|
||||
export function updateCheckRecord(data: MesDvCheckRecordApi.CheckRecord) {
|
||||
return requestClient.put('/mes/dv/check-record/update', data);
|
||||
}
|
||||
|
||||
/** 提交设备点检记录 */
|
||||
export function submitCheckRecord(id: number) {
|
||||
return requestClient.put(`/mes/dv/check-record/submit?id=${id}`);
|
||||
}
|
||||
|
||||
/** 删除设备点检记录 */
|
||||
export function deleteCheckRecord(id: number) {
|
||||
return requestClient.delete(`/mes/dv/check-record/delete?id=${id}`);
|
||||
}
|
||||
|
||||
/** 导出设备点检记录 */
|
||||
export function exportCheckRecord(params: any) {
|
||||
return requestClient.download('/mes/dv/check-record/export-excel', {
|
||||
params,
|
||||
});
|
||||
}
|
||||
|
|
@ -0,0 +1,53 @@
|
|||
import type { PageParam, PageResult } from '@vben/request';
|
||||
|
||||
import { requestClient } from '#/api/request';
|
||||
|
||||
export namespace MesDvCheckRecordLineApi {
|
||||
/** MES 设备点检记录明细 */
|
||||
export interface CheckRecordLine {
|
||||
id?: number; // 明细编号
|
||||
recordId?: number; // 点检记录编号
|
||||
subjectId?: number; // 点检项目编号
|
||||
subjectCode?: string; // 项目编码
|
||||
subjectName?: string; // 项目名称
|
||||
subjectContent?: string; // 检查内容
|
||||
subjectStandard?: string; // 检查标准
|
||||
checkStatus?: number; // 点检结果
|
||||
checkResult?: string; // 异常描述
|
||||
remark?: string; // 备注
|
||||
}
|
||||
}
|
||||
|
||||
/** 查询设备点检记录明细分页 */
|
||||
export function getCheckRecordLinePage(params: PageParam) {
|
||||
return requestClient.get<PageResult<MesDvCheckRecordLineApi.CheckRecordLine>>(
|
||||
'/mes/dv/check-record-line/page',
|
||||
{ params },
|
||||
);
|
||||
}
|
||||
|
||||
/** 查询设备点检记录明细详情 */
|
||||
export function getCheckRecordLine(id: number) {
|
||||
return requestClient.get<MesDvCheckRecordLineApi.CheckRecordLine>(
|
||||
`/mes/dv/check-record-line/get?id=${id}`,
|
||||
);
|
||||
}
|
||||
|
||||
/** 新增设备点检记录明细 */
|
||||
export function createCheckRecordLine(
|
||||
data: MesDvCheckRecordLineApi.CheckRecordLine,
|
||||
) {
|
||||
return requestClient.post('/mes/dv/check-record-line/create', data);
|
||||
}
|
||||
|
||||
/** 修改设备点检记录明细 */
|
||||
export function updateCheckRecordLine(
|
||||
data: MesDvCheckRecordLineApi.CheckRecordLine,
|
||||
) {
|
||||
return requestClient.put('/mes/dv/check-record-line/update', data);
|
||||
}
|
||||
|
||||
/** 删除设备点检记录明细 */
|
||||
export function deleteCheckRecordLine(id: number) {
|
||||
return requestClient.delete(`/mes/dv/check-record-line/delete?id=${id}`);
|
||||
}
|
||||
|
|
@ -0,0 +1,85 @@
|
|||
import type { PageParam, PageResult } from '@vben/request';
|
||||
|
||||
import { requestClient } from '#/api/request';
|
||||
|
||||
export namespace MesDvMachineryApi {
|
||||
/** MES 设备台账 */
|
||||
export interface Machinery {
|
||||
id?: number; // 设备编号
|
||||
code?: string; // 设备编码
|
||||
name?: string; // 设备名称
|
||||
brand?: string; // 品牌
|
||||
specification?: string; // 规格型号
|
||||
machineryTypeId?: number; // 设备类型编号
|
||||
machineryTypeName?: string; // 设备类型名称
|
||||
workshopId?: number; // 所属车间编号
|
||||
workshopName?: string; // 所属车间名称
|
||||
status?: number; // 设备状态
|
||||
lastMaintenTime?: Date; // 最近保养时间
|
||||
lastCheckTime?: Date; // 最近点检时间
|
||||
remark?: string; // 备注
|
||||
createTime?: Date; // 创建时间
|
||||
}
|
||||
|
||||
/** 设备导入结果 */
|
||||
export interface MachineryImportRespVO {
|
||||
createCodes?: string[]; // 新增成功的设备编码
|
||||
updateCodes?: string[]; // 更新成功的设备编码
|
||||
failureCodes?: Record<string, string>; // 导入失败的设备编码及原因
|
||||
}
|
||||
}
|
||||
|
||||
/** 查询设备分页 */
|
||||
export function getMachineryPage(params: PageParam) {
|
||||
return requestClient.get<PageResult<MesDvMachineryApi.Machinery>>(
|
||||
'/mes/dv/machinery/page',
|
||||
{ params },
|
||||
);
|
||||
}
|
||||
|
||||
/** 查询设备精简列表 */
|
||||
export function getMachinerySimpleList() {
|
||||
return requestClient.get<MesDvMachineryApi.Machinery[]>(
|
||||
'/mes/dv/machinery/simple-list',
|
||||
);
|
||||
}
|
||||
|
||||
/** 查询设备详情 */
|
||||
export function getMachinery(id: number) {
|
||||
return requestClient.get<MesDvMachineryApi.Machinery>(
|
||||
`/mes/dv/machinery/get?id=${id}`,
|
||||
);
|
||||
}
|
||||
|
||||
/** 新增设备 */
|
||||
export function createMachinery(data: MesDvMachineryApi.Machinery) {
|
||||
return requestClient.post('/mes/dv/machinery/create', data);
|
||||
}
|
||||
|
||||
/** 修改设备 */
|
||||
export function updateMachinery(data: MesDvMachineryApi.Machinery) {
|
||||
return requestClient.put('/mes/dv/machinery/update', data);
|
||||
}
|
||||
|
||||
/** 删除设备 */
|
||||
export function deleteMachinery(id: number) {
|
||||
return requestClient.delete(`/mes/dv/machinery/delete?id=${id}`);
|
||||
}
|
||||
|
||||
/** 导出设备 */
|
||||
export function exportMachinery(params: any) {
|
||||
return requestClient.download('/mes/dv/machinery/export-excel', { params });
|
||||
}
|
||||
|
||||
/** 下载设备导入模板 */
|
||||
export function importMachineryTemplate() {
|
||||
return requestClient.download('/mes/dv/machinery/get-import-template');
|
||||
}
|
||||
|
||||
/** 导入设备 */
|
||||
export function importMachinery(file: File, updateSupport: boolean) {
|
||||
return requestClient.upload<MesDvMachineryApi.MachineryImportRespVO>(
|
||||
`/mes/dv/machinery/import?updateSupport=${updateSupport}`,
|
||||
{ file },
|
||||
);
|
||||
}
|
||||
|
|
@ -0,0 +1,53 @@
|
|||
import { requestClient } from '#/api/request';
|
||||
|
||||
export namespace MesDvMachineryTypeApi {
|
||||
/** MES 设备类型 */
|
||||
export interface MachineryType {
|
||||
id?: number; // 设备类型编号
|
||||
parentId?: number; // 父类型编号
|
||||
code?: string; // 类型编码
|
||||
name?: string; // 类型名称
|
||||
sort?: number; // 显示排序
|
||||
status?: number; // 状态
|
||||
remark?: string; // 备注
|
||||
createTime?: Date; // 创建时间
|
||||
children?: MachineryType[]; // 子类型
|
||||
}
|
||||
}
|
||||
|
||||
/** 查询设备类型列表 */
|
||||
export function getMachineryTypeList(params?: any) {
|
||||
return requestClient.get<MesDvMachineryTypeApi.MachineryType[]>(
|
||||
'/mes/dv/machinery-type/list',
|
||||
{ params },
|
||||
);
|
||||
}
|
||||
|
||||
/** 查询设备类型精简列表 */
|
||||
export function getMachineryTypeSimpleList() {
|
||||
return requestClient.get<MesDvMachineryTypeApi.MachineryType[]>(
|
||||
'/mes/dv/machinery-type/simple-list',
|
||||
);
|
||||
}
|
||||
|
||||
/** 查询设备类型详情 */
|
||||
export function getMachineryType(id: number) {
|
||||
return requestClient.get<MesDvMachineryTypeApi.MachineryType>(
|
||||
`/mes/dv/machinery-type/get?id=${id}`,
|
||||
);
|
||||
}
|
||||
|
||||
/** 新增设备类型 */
|
||||
export function createMachineryType(data: MesDvMachineryTypeApi.MachineryType) {
|
||||
return requestClient.post('/mes/dv/machinery-type/create', data);
|
||||
}
|
||||
|
||||
/** 修改设备类型 */
|
||||
export function updateMachineryType(data: MesDvMachineryTypeApi.MachineryType) {
|
||||
return requestClient.put('/mes/dv/machinery-type/update', data);
|
||||
}
|
||||
|
||||
/** 删除设备类型 */
|
||||
export function deleteMachineryType(id: number) {
|
||||
return requestClient.delete(`/mes/dv/machinery-type/delete?id=${id}`);
|
||||
}
|
||||
|
|
@ -0,0 +1,65 @@
|
|||
import type { PageParam, PageResult } from '@vben/request';
|
||||
|
||||
import { requestClient } from '#/api/request';
|
||||
|
||||
export namespace MesDvMaintenRecordApi {
|
||||
/** MES 设备保养记录 */
|
||||
export interface MaintenRecord {
|
||||
id?: number; // 记录编号
|
||||
planId?: number; // 计划编号
|
||||
planName?: string; // 计划名称
|
||||
machineryId?: number; // 设备编号
|
||||
machineryCode?: string; // 设备编码
|
||||
machineryName?: string; // 设备名称
|
||||
machineryBrand?: string; // 品牌
|
||||
machinerySpecification?: string; // 规格型号
|
||||
maintenTime?: Date | number; // 保养时间
|
||||
userId?: number; // 用户编号
|
||||
nickname?: string; // 保养人名称
|
||||
status?: number; // 状态
|
||||
remark?: string; // 备注
|
||||
createTime?: Date; // 创建时间
|
||||
}
|
||||
}
|
||||
|
||||
/** 查询设备保养记录分页 */
|
||||
export function getMaintenRecordPage(params: PageParam) {
|
||||
return requestClient.get<PageResult<MesDvMaintenRecordApi.MaintenRecord>>(
|
||||
'/mes/dv/mainten-record/page',
|
||||
{ params },
|
||||
);
|
||||
}
|
||||
|
||||
/** 查询设备保养记录详情 */
|
||||
export function getMaintenRecord(id: number) {
|
||||
return requestClient.get<MesDvMaintenRecordApi.MaintenRecord>(
|
||||
`/mes/dv/mainten-record/get?id=${id}`,
|
||||
);
|
||||
}
|
||||
|
||||
/** 新增设备保养记录 */
|
||||
export function createMaintenRecord(data: MesDvMaintenRecordApi.MaintenRecord) {
|
||||
return requestClient.post<number>('/mes/dv/mainten-record/create', data);
|
||||
}
|
||||
|
||||
/** 修改设备保养记录 */
|
||||
export function updateMaintenRecord(data: MesDvMaintenRecordApi.MaintenRecord) {
|
||||
return requestClient.put('/mes/dv/mainten-record/update', data);
|
||||
}
|
||||
|
||||
/** 提交设备保养记录 */
|
||||
export function submitMaintenRecord(id: number) {
|
||||
return requestClient.put(`/mes/dv/mainten-record/submit?id=${id}`);
|
||||
}
|
||||
|
||||
/** 删除设备保养记录 */
|
||||
export function deleteMaintenRecord(id: number) {
|
||||
return requestClient.delete(`/mes/dv/mainten-record/delete?id=${id}`);
|
||||
}
|
||||
|
||||
/** 导出设备保养记录 */
|
||||
export function exportMaintenRecord(params: any) {
|
||||
return requestClient.download('/mes/dv/mainten-record/export-excel', {
|
||||
params,
|
||||
});
|
||||
}
|
||||
|
|
@ -0,0 +1,51 @@
|
|||
import type { PageParam, PageResult } from '@vben/request';
|
||||
|
||||
import { requestClient } from '#/api/request';
|
||||
|
||||
export namespace MesDvMaintenRecordLineApi {
|
||||
/** MES 设备保养记录明细 */
|
||||
export interface MaintenRecordLine {
|
||||
id?: number; // 明细编号
|
||||
recordId?: number; // 保养记录编号
|
||||
subjectId?: number; // 项目编号
|
||||
subjectName?: string; // 项目名称
|
||||
subjectContent?: string; // 项目内容
|
||||
subjectStandard?: string; // 项目标准
|
||||
status?: number; // 保养结果
|
||||
result?: string; // 异常描述
|
||||
remark?: string; // 备注
|
||||
}
|
||||
}
|
||||
|
||||
/** 查询设备保养记录明细分页 */
|
||||
export function getMaintenRecordLinePage(params: PageParam) {
|
||||
return requestClient.get<
|
||||
PageResult<MesDvMaintenRecordLineApi.MaintenRecordLine>
|
||||
>('/mes/dv/mainten-record-line/page', { params });
|
||||
}
|
||||
|
||||
/** 查询设备保养记录明细详情 */
|
||||
export function getMaintenRecordLine(id: number) {
|
||||
return requestClient.get<MesDvMaintenRecordLineApi.MaintenRecordLine>(
|
||||
`/mes/dv/mainten-record-line/get?id=${id}`,
|
||||
);
|
||||
}
|
||||
|
||||
/** 新增设备保养记录明细 */
|
||||
export function createMaintenRecordLine(
|
||||
data: MesDvMaintenRecordLineApi.MaintenRecordLine,
|
||||
) {
|
||||
return requestClient.post('/mes/dv/mainten-record-line/create', data);
|
||||
}
|
||||
|
||||
/** 修改设备保养记录明细 */
|
||||
export function updateMaintenRecordLine(
|
||||
data: MesDvMaintenRecordLineApi.MaintenRecordLine,
|
||||
) {
|
||||
return requestClient.put('/mes/dv/mainten-record-line/update', data);
|
||||
}
|
||||
|
||||
/** 删除设备保养记录明细 */
|
||||
export function deleteMaintenRecordLine(id: number) {
|
||||
return requestClient.delete(`/mes/dv/mainten-record-line/delete?id=${id}`);
|
||||
}
|
||||
|
|
@ -0,0 +1,81 @@
|
|||
import type { PageParam, PageResult } from '@vben/request';
|
||||
|
||||
import { requestClient } from '#/api/request';
|
||||
|
||||
export namespace MesDvRepairApi {
|
||||
/** MES 维修工单 */
|
||||
export interface Repair {
|
||||
id?: number; // 工单编号
|
||||
code?: string; // 维修工单编码
|
||||
name?: string; // 维修工单名称
|
||||
machineryId?: number; // 设备编号
|
||||
machineryCode?: string; // 设备编码
|
||||
machineryName?: string; // 设备名称
|
||||
machineryBrand?: string; // 品牌
|
||||
machinerySpecification?: string; // 规格型号
|
||||
requireDate?: Date | number; // 报修日期
|
||||
finishDate?: Date | number; // 维修完成日期
|
||||
confirmDate?: Date | number; // 验收日期
|
||||
result?: number; // 维修结果
|
||||
acceptedUserId?: number; // 维修人编号
|
||||
acceptedUserNickname?: string; // 维修人名称
|
||||
confirmUserId?: number; // 验收人编号
|
||||
confirmUserNickname?: string; // 验收人名称
|
||||
sourceDocType?: number; // 来源单据类型
|
||||
sourceDocId?: number; // 来源单据编号
|
||||
sourceDocCode?: string; // 来源单据编码
|
||||
status?: number; // 状态
|
||||
remark?: string; // 备注
|
||||
createTime?: Date; // 创建时间
|
||||
}
|
||||
}
|
||||
|
||||
/** 查询维修工单分页 */
|
||||
export function getRepairPage(params: PageParam) {
|
||||
return requestClient.get<PageResult<MesDvRepairApi.Repair>>(
|
||||
'/mes/dv/repair/page',
|
||||
{ params },
|
||||
);
|
||||
}
|
||||
|
||||
/** 查询维修工单详情 */
|
||||
export function getRepair(id: number) {
|
||||
return requestClient.get<MesDvRepairApi.Repair>(
|
||||
`/mes/dv/repair/get?id=${id}`,
|
||||
);
|
||||
}
|
||||
|
||||
/** 新增维修工单 */
|
||||
export function createRepair(data: MesDvRepairApi.Repair) {
|
||||
return requestClient.post<number>('/mes/dv/repair/create', data);
|
||||
}
|
||||
|
||||
/** 修改维修工单 */
|
||||
export function updateRepair(data: MesDvRepairApi.Repair) {
|
||||
return requestClient.put('/mes/dv/repair/update', data);
|
||||
}
|
||||
|
||||
/** 删除维修工单 */
|
||||
export function deleteRepair(id: number) {
|
||||
return requestClient.delete(`/mes/dv/repair/delete?id=${id}`);
|
||||
}
|
||||
|
||||
/** 导出维修工单 */
|
||||
export function exportRepair(params: any) {
|
||||
return requestClient.download('/mes/dv/repair/export-excel', { params });
|
||||
}
|
||||
|
||||
/** 提交维修工单 */
|
||||
export function submitRepair(id: number) {
|
||||
return requestClient.put(`/mes/dv/repair/submit?id=${id}`);
|
||||
}
|
||||
|
||||
/** 确认维修完成 */
|
||||
export function confirmRepair(data: MesDvRepairApi.Repair) {
|
||||
return requestClient.put('/mes/dv/repair/confirm', data);
|
||||
}
|
||||
|
||||
/** 完成验收 */
|
||||
export function finishRepair(id: number, result: number) {
|
||||
return requestClient.put(`/mes/dv/repair/finish?id=${id}&result=${result}`);
|
||||
}
|
||||
|
|
@ -0,0 +1,49 @@
|
|||
import type { PageParam, PageResult } from '@vben/request';
|
||||
|
||||
import { requestClient } from '#/api/request';
|
||||
|
||||
export namespace MesDvRepairLineApi {
|
||||
/** MES 维修工单行 */
|
||||
export interface RepairLine {
|
||||
id?: number; // 明细编号
|
||||
repairId?: number; // 维修工单编号
|
||||
subjectId?: number; // 项目编号
|
||||
subjectName?: string; // 项目名称
|
||||
subjectContent?: string; // 项目内容
|
||||
subjectStandard?: string; // 项目标准
|
||||
malfunction?: string; // 故障描述
|
||||
malfunctionUrl?: string; // 故障图片 URL
|
||||
description?: string; // 维修描述
|
||||
remark?: string; // 备注
|
||||
}
|
||||
}
|
||||
|
||||
/** 查询维修工单行分页 */
|
||||
export function getRepairLinePage(params: PageParam) {
|
||||
return requestClient.get<PageResult<MesDvRepairLineApi.RepairLine>>(
|
||||
'/mes/dv/repair-line/page',
|
||||
{ params },
|
||||
);
|
||||
}
|
||||
|
||||
/** 查询维修工单行详情 */
|
||||
export function getRepairLine(id: number) {
|
||||
return requestClient.get<MesDvRepairLineApi.RepairLine>(
|
||||
`/mes/dv/repair-line/get?id=${id}`,
|
||||
);
|
||||
}
|
||||
|
||||
/** 新增维修工单行 */
|
||||
export function createRepairLine(data: MesDvRepairLineApi.RepairLine) {
|
||||
return requestClient.post('/mes/dv/repair-line/create', data);
|
||||
}
|
||||
|
||||
/** 修改维修工单行 */
|
||||
export function updateRepairLine(data: MesDvRepairLineApi.RepairLine) {
|
||||
return requestClient.put('/mes/dv/repair-line/update', data);
|
||||
}
|
||||
|
||||
/** 删除维修工单行 */
|
||||
export function deleteRepairLine(id: number) {
|
||||
return requestClient.delete(`/mes/dv/repair-line/delete?id=${id}`);
|
||||
}
|
||||
|
|
@ -0,0 +1,60 @@
|
|||
import type { PageParam, PageResult } from '@vben/request';
|
||||
|
||||
import { requestClient } from '#/api/request';
|
||||
|
||||
export namespace MesDvSubjectApi {
|
||||
/** MES 点检保养项目 */
|
||||
export interface Subject {
|
||||
id?: number; // 项目编号
|
||||
code?: string; // 项目编码
|
||||
name?: string; // 项目名称
|
||||
type?: number; // 项目类型
|
||||
content?: string; // 项目内容
|
||||
standard?: string; // 标准
|
||||
status?: number; // 状态
|
||||
remark?: string; // 备注
|
||||
createTime?: Date; // 创建时间
|
||||
}
|
||||
}
|
||||
|
||||
/** 查询点检保养项目分页 */
|
||||
export function getSubjectPage(params: PageParam) {
|
||||
return requestClient.get<PageResult<MesDvSubjectApi.Subject>>(
|
||||
'/mes/dv/subject/page',
|
||||
{ params },
|
||||
);
|
||||
}
|
||||
|
||||
/** 查询点检保养项目精简列表 */
|
||||
export function getSubjectSimpleList() {
|
||||
return requestClient.get<MesDvSubjectApi.Subject[]>(
|
||||
'/mes/dv/subject/simple-list',
|
||||
);
|
||||
}
|
||||
|
||||
/** 查询点检保养项目详情 */
|
||||
export function getSubject(id: number) {
|
||||
return requestClient.get<MesDvSubjectApi.Subject>(
|
||||
`/mes/dv/subject/get?id=${id}`,
|
||||
);
|
||||
}
|
||||
|
||||
/** 新增点检保养项目 */
|
||||
export function createSubject(data: MesDvSubjectApi.Subject) {
|
||||
return requestClient.post('/mes/dv/subject/create', data);
|
||||
}
|
||||
|
||||
/** 修改点检保养项目 */
|
||||
export function updateSubject(data: MesDvSubjectApi.Subject) {
|
||||
return requestClient.put('/mes/dv/subject/update', data);
|
||||
}
|
||||
|
||||
/** 删除点检保养项目 */
|
||||
export function deleteSubject(id: number) {
|
||||
return requestClient.delete(`/mes/dv/subject/delete?id=${id}`);
|
||||
}
|
||||
|
||||
/** 导出点检保养项目 */
|
||||
export function exportSubject(params: any) {
|
||||
return requestClient.download('/mes/dv/subject/export-excel', { params });
|
||||
}
|
||||
|
|
@ -0,0 +1,49 @@
|
|||
import { requestClient } from '#/api/request';
|
||||
|
||||
export namespace MesMdAutoCodePartApi {
|
||||
/** MES 编码规则分段 */
|
||||
export interface AutoCodePart {
|
||||
id?: number; // 分段编号
|
||||
ruleId?: number; // 规则编号
|
||||
sort?: number; // 排序
|
||||
type?: number; // 分段类型
|
||||
length?: number; // 长度
|
||||
dateFormat?: string; // 日期格式
|
||||
fixCharacter?: string; // 固定字符
|
||||
serialStartNo?: number; // 流水号起始值
|
||||
serialStep?: number; // 流水号步长
|
||||
cycleFlag?: boolean; // 是否循环
|
||||
cycleMethod?: number; // 循环方式
|
||||
remark?: string; // 备注
|
||||
}
|
||||
}
|
||||
|
||||
/** 查询编码规则分段详情 */
|
||||
export function getAutoCodePart(id: number) {
|
||||
return requestClient.get<MesMdAutoCodePartApi.AutoCodePart>(
|
||||
`/mes/md/auto-code-part/get?id=${id}`,
|
||||
);
|
||||
}
|
||||
|
||||
/** 查询编码规则分段列表 */
|
||||
export function getAutoCodePartListByRuleId(ruleId: number) {
|
||||
return requestClient.get<MesMdAutoCodePartApi.AutoCodePart[]>(
|
||||
'/mes/md/auto-code-part/list-by-rule-id',
|
||||
{ params: { ruleId } },
|
||||
);
|
||||
}
|
||||
|
||||
/** 新增编码规则分段 */
|
||||
export function createAutoCodePart(data: MesMdAutoCodePartApi.AutoCodePart) {
|
||||
return requestClient.post('/mes/md/auto-code-part/create', data);
|
||||
}
|
||||
|
||||
/** 修改编码规则分段 */
|
||||
export function updateAutoCodePart(data: MesMdAutoCodePartApi.AutoCodePart) {
|
||||
return requestClient.put('/mes/md/auto-code-part/update', data);
|
||||
}
|
||||
|
||||
/** 删除编码规则分段 */
|
||||
export function deleteAutoCodePart(id: number) {
|
||||
return requestClient.delete(`/mes/md/auto-code-part/delete?id=${id}`);
|
||||
}
|
||||
|
|
@ -0,0 +1,9 @@
|
|||
import { requestClient } from '#/api/request';
|
||||
|
||||
/** 生成 MES 编码 */
|
||||
export function generateAutoCode(ruleCode: string, inputChar?: string) {
|
||||
return requestClient.post<string>('/mes/md/auto-code-record/generate', {
|
||||
inputChar,
|
||||
ruleCode,
|
||||
});
|
||||
}
|
||||
|
|
@ -0,0 +1,57 @@
|
|||
import type { PageParam, PageResult } from '@vben/request';
|
||||
|
||||
import { requestClient } from '#/api/request';
|
||||
|
||||
export namespace MesMdAutoCodeRuleApi {
|
||||
/** MES 编码规则 */
|
||||
export interface AutoCodeRule {
|
||||
id?: number; // 规则编号
|
||||
code?: string; // 规则编码
|
||||
name?: string; // 规则名称
|
||||
description?: string; // 规则描述
|
||||
maxLength?: number; // 最大长度
|
||||
padded?: boolean; // 是否补齐
|
||||
paddedChar?: string; // 补齐字符
|
||||
paddedMethod?: number; // 补齐方式
|
||||
status?: number; // 状态
|
||||
remark?: string; // 备注
|
||||
createTime?: Date; // 创建时间
|
||||
}
|
||||
}
|
||||
|
||||
/** 查询编码规则分页 */
|
||||
export function getAutoCodeRulePage(params: PageParam) {
|
||||
return requestClient.get<PageResult<MesMdAutoCodeRuleApi.AutoCodeRule>>(
|
||||
'/mes/md/auto-code-rule/page',
|
||||
{ params },
|
||||
);
|
||||
}
|
||||
|
||||
/** 查询编码规则详情 */
|
||||
export function getAutoCodeRule(id: number) {
|
||||
return requestClient.get<MesMdAutoCodeRuleApi.AutoCodeRule>(
|
||||
`/mes/md/auto-code-rule/get?id=${id}`,
|
||||
);
|
||||
}
|
||||
|
||||
/** 新增编码规则 */
|
||||
export function createAutoCodeRule(data: MesMdAutoCodeRuleApi.AutoCodeRule) {
|
||||
return requestClient.post('/mes/md/auto-code-rule/create', data);
|
||||
}
|
||||
|
||||
/** 修改编码规则 */
|
||||
export function updateAutoCodeRule(data: MesMdAutoCodeRuleApi.AutoCodeRule) {
|
||||
return requestClient.put('/mes/md/auto-code-rule/update', data);
|
||||
}
|
||||
|
||||
/** 删除编码规则 */
|
||||
export function deleteAutoCodeRule(id: number) {
|
||||
return requestClient.delete(`/mes/md/auto-code-rule/delete?id=${id}`);
|
||||
}
|
||||
|
||||
/** 导出编码规则 */
|
||||
export function exportAutoCodeRule(params: PageParam) {
|
||||
return requestClient.download('/mes/md/auto-code-rule/export-excel', {
|
||||
params,
|
||||
});
|
||||
}
|
||||
|
|
@ -0,0 +1,86 @@
|
|||
import type { PageParam, PageResult } from '@vben/request';
|
||||
|
||||
import { requestClient } from '#/api/request';
|
||||
|
||||
export namespace MesMdClientApi {
|
||||
/** MES 客户 */
|
||||
export interface Client {
|
||||
id?: number; // 客户编号
|
||||
code?: string; // 客户编码
|
||||
name?: string; // 客户名称
|
||||
nickname?: string; // 客户简称
|
||||
englishName?: string; // 客户英文名称
|
||||
description?: string; // 客户简介
|
||||
logo?: string; // 客户 LOGO 地址
|
||||
type?: number; // 客户类型
|
||||
address?: string; // 客户地址
|
||||
website?: string; // 客户官网地址
|
||||
email?: string; // 客户邮箱地址
|
||||
telephone?: string; // 客户电话
|
||||
contact1Name?: string; // 联系人1
|
||||
contact1Telephone?: string; // 联系人1电话
|
||||
contact1Email?: string; // 联系人1邮箱
|
||||
contact2Name?: string; // 联系人2
|
||||
contact2Telephone?: string; // 联系人2电话
|
||||
contact2Email?: string; // 联系人2邮箱
|
||||
creditCode?: string; // 统一社会信用代码
|
||||
status?: number; // 状态
|
||||
remark?: string; // 备注
|
||||
createTime?: Date; // 创建时间
|
||||
}
|
||||
|
||||
/** 客户导入结果 */
|
||||
export interface ClientImportRespVO {
|
||||
createCodes?: string[]; // 新增成功的客户编码
|
||||
updateCodes?: string[]; // 更新成功的客户编码
|
||||
failureCodes?: Record<string, string>; // 导入失败的客户编码及原因
|
||||
}
|
||||
}
|
||||
|
||||
/** 查询客户分页 */
|
||||
export function getClientPage(params: PageParam) {
|
||||
return requestClient.get<PageResult<MesMdClientApi.Client>>(
|
||||
'/mes/md-client/page',
|
||||
{ params },
|
||||
);
|
||||
}
|
||||
|
||||
/** 查询客户详情 */
|
||||
export function getClient(id: number) {
|
||||
return requestClient.get<MesMdClientApi.Client>(
|
||||
`/mes/md-client/get?id=${id}`,
|
||||
);
|
||||
}
|
||||
|
||||
/** 新增客户 */
|
||||
export function createClient(data: MesMdClientApi.Client) {
|
||||
return requestClient.post('/mes/md-client/create', data);
|
||||
}
|
||||
|
||||
/** 修改客户 */
|
||||
export function updateClient(data: MesMdClientApi.Client) {
|
||||
return requestClient.put('/mes/md-client/update', data);
|
||||
}
|
||||
|
||||
/** 删除客户 */
|
||||
export function deleteClient(id: number) {
|
||||
return requestClient.delete(`/mes/md-client/delete?id=${id}`);
|
||||
}
|
||||
|
||||
/** 导出客户 */
|
||||
export function exportClient(params: any) {
|
||||
return requestClient.download('/mes/md-client/export-excel', { params });
|
||||
}
|
||||
|
||||
/** 下载客户导入模板 */
|
||||
export function importClientTemplate() {
|
||||
return requestClient.download('/mes/md-client/get-import-template');
|
||||
}
|
||||
|
||||
/** 导入客户 */
|
||||
export function importClient(file: File, updateSupport: boolean) {
|
||||
return requestClient.upload<MesMdClientApi.ClientImportRespVO>(
|
||||
`/mes/md-client/import?updateSupport=${updateSupport}`,
|
||||
{ file },
|
||||
);
|
||||
}
|
||||
|
|
@ -0,0 +1,35 @@
|
|||
import { requestClient } from '#/api/request';
|
||||
|
||||
export namespace MesMdItemBatchConfigApi {
|
||||
/** MES 物料批次属性配置 */
|
||||
export interface BatchConfig {
|
||||
id?: number; // 编号
|
||||
itemId?: number; // 物料编号
|
||||
produceDateFlag?: boolean; // 批次属性-生产日期
|
||||
expireDateFlag?: boolean; // 批次属性-有效期
|
||||
receiptDateFlag?: boolean; // 批次属性-入库日期
|
||||
vendorFlag?: boolean; // 批次属性-供应商
|
||||
clientFlag?: boolean; // 批次属性-客户
|
||||
salesOrderCodeFlag?: boolean; // 批次属性-销售订单编号
|
||||
purchaseOrderCodeFlag?: boolean; // 批次属性-采购订单编号
|
||||
workorderFlag?: boolean; // 批次属性-生产工单
|
||||
taskFlag?: boolean; // 批次属性-生产任务
|
||||
workstationFlag?: boolean; // 批次属性-工作站
|
||||
toolFlag?: boolean; // 批次属性-工具
|
||||
moldFlag?: boolean; // 批次属性-模具
|
||||
lotNumberFlag?: boolean; // 批次属性-生产批号
|
||||
qualityStatusFlag?: boolean; // 批次属性-质量状态
|
||||
}
|
||||
}
|
||||
|
||||
/** 根据物料编号获取批次属性配置 */
|
||||
export function getBatchConfigByItemId(itemId: number) {
|
||||
return requestClient.get<MesMdItemBatchConfigApi.BatchConfig>(
|
||||
`/mes/md/item-batch-config/get-by-item-id?itemId=${itemId}`,
|
||||
);
|
||||
}
|
||||
|
||||
/** 保存批次属性配置 */
|
||||
export function saveBatchConfig(data: MesMdItemBatchConfigApi.BatchConfig) {
|
||||
return requestClient.post('/mes/md/item-batch-config/save', data);
|
||||
}
|
||||
|
|
@ -0,0 +1,85 @@
|
|||
import type { PageParam, PageResult } from '@vben/request';
|
||||
|
||||
import { requestClient } from '#/api/request';
|
||||
|
||||
export namespace MesMdItemApi {
|
||||
/** MES 物料产品 */
|
||||
export interface Item {
|
||||
id?: number; // 物料编号
|
||||
code?: string; // 物料编码
|
||||
name?: string; // 物料名称
|
||||
specification?: string; // 规格型号
|
||||
unitMeasureId?: number; // 计量单位编号
|
||||
unitMeasureName?: string; // 计量单位名称
|
||||
itemTypeId?: number; // 物料分类编号
|
||||
itemTypeName?: string; // 物料分类名称
|
||||
itemOrProduct?: string; // 物料/产品标识
|
||||
status?: number; // 状态
|
||||
safeStockFlag?: boolean; // 是否启用安全库存
|
||||
minStock?: number; // 最低库存量
|
||||
maxStock?: number; // 最高库存量
|
||||
highValue?: boolean; // 是否高值物料
|
||||
batchFlag?: boolean; // 是否启用批次管理
|
||||
remark?: string; // 备注
|
||||
createTime?: Date; // 创建时间
|
||||
}
|
||||
|
||||
/** 物料导入结果 */
|
||||
export interface ItemImportRespVO {
|
||||
createCodes?: string[]; // 新增成功的物料编码
|
||||
updateCodes?: string[]; // 更新成功的物料编码
|
||||
failureCodes?: Record<string, string>; // 导入失败的物料编码及原因
|
||||
}
|
||||
}
|
||||
|
||||
/** 查询物料产品分页 */
|
||||
export function getItemPage(params: PageParam) {
|
||||
return requestClient.get<PageResult<MesMdItemApi.Item>>('/mes/md/item/page', {
|
||||
params,
|
||||
});
|
||||
}
|
||||
|
||||
/** 查询物料产品详情 */
|
||||
export function getItem(id: number) {
|
||||
return requestClient.get<MesMdItemApi.Item>(`/mes/md/item/get?id=${id}`);
|
||||
}
|
||||
|
||||
/** 新增物料产品 */
|
||||
export function createItem(data: MesMdItemApi.Item) {
|
||||
return requestClient.post<number>('/mes/md/item/create', data);
|
||||
}
|
||||
|
||||
/** 修改物料产品 */
|
||||
export function updateItem(data: MesMdItemApi.Item) {
|
||||
return requestClient.put('/mes/md/item/update', data);
|
||||
}
|
||||
|
||||
/** 修改物料产品状态 */
|
||||
export function updateItemStatus(id: number, status: number) {
|
||||
return requestClient.put('/mes/md/item/update-status', undefined, {
|
||||
params: { id, status },
|
||||
});
|
||||
}
|
||||
|
||||
/** 删除物料产品 */
|
||||
export function deleteItem(id: number) {
|
||||
return requestClient.delete(`/mes/md/item/delete?id=${id}`);
|
||||
}
|
||||
|
||||
/** 导出物料产品 */
|
||||
export function exportItem(params: any) {
|
||||
return requestClient.download('/mes/md/item/export-excel', { params });
|
||||
}
|
||||
|
||||
/** 下载物料导入模板 */
|
||||
export function importItemTemplate() {
|
||||
return requestClient.download('/mes/md/item/get-import-template');
|
||||
}
|
||||
|
||||
/** 导入物料产品 */
|
||||
export function importItem(file: File, updateSupport: boolean) {
|
||||
return requestClient.upload<MesMdItemApi.ItemImportRespVO>(
|
||||
`/mes/md/item/import?updateSupport=${updateSupport}`,
|
||||
{ file },
|
||||
);
|
||||
}
|
||||
|
|
@ -0,0 +1,58 @@
|
|||
import type { PageParam, PageResult } from '@vben/request';
|
||||
|
||||
import { requestClient } from '#/api/request';
|
||||
|
||||
export namespace MesMdProductBomApi {
|
||||
/** MES 产品 BOM */
|
||||
export interface ProductBom {
|
||||
id?: number; // BOM 编号
|
||||
itemId?: number; // 物料产品编号
|
||||
bomItemId?: number; // BOM 物料编号
|
||||
quantity?: number; // 物料使用比例
|
||||
status?: number; // 是否启用
|
||||
remark?: string; // 备注
|
||||
createTime?: Date; // 创建时间
|
||||
bomItemCode?: string; // BOM 物料编码
|
||||
bomItemName?: string; // BOM 物料名称
|
||||
bomItemSpecification?: string; // BOM 物料规格
|
||||
unitMeasureName?: string; // 计量单位名称
|
||||
itemOrProduct?: string; // 物料/产品标识
|
||||
}
|
||||
}
|
||||
|
||||
/** 新增产品 BOM */
|
||||
export function createProductBom(data: MesMdProductBomApi.ProductBom) {
|
||||
return requestClient.post('/mes/md/product-bom/create', data);
|
||||
}
|
||||
|
||||
/** 修改产品 BOM */
|
||||
export function updateProductBom(data: MesMdProductBomApi.ProductBom) {
|
||||
return requestClient.put('/mes/md/product-bom/update', data);
|
||||
}
|
||||
|
||||
/** 删除产品 BOM */
|
||||
export function deleteProductBom(id: number) {
|
||||
return requestClient.delete(`/mes/md/product-bom/delete?id=${id}`);
|
||||
}
|
||||
|
||||
/** 查询产品 BOM 详情 */
|
||||
export function getProductBom(id: number) {
|
||||
return requestClient.get<MesMdProductBomApi.ProductBom>(
|
||||
`/mes/md/product-bom/get?id=${id}`,
|
||||
);
|
||||
}
|
||||
|
||||
/** 查询产品 BOM 分页 */
|
||||
export function getProductBomPage(params: PageParam) {
|
||||
return requestClient.get<PageResult<MesMdProductBomApi.ProductBom>>(
|
||||
'/mes/md/product-bom/page',
|
||||
{ params },
|
||||
);
|
||||
}
|
||||
|
||||
/** 根据物料产品编号查询产品 BOM 列表 */
|
||||
export function getProductBomListByItemId(itemId: number) {
|
||||
return requestClient.get<MesMdProductBomApi.ProductBom[]>(
|
||||
`/mes/md/product-bom/list-by-item-id?itemId=${itemId}`,
|
||||
);
|
||||
}
|
||||
|
|
@ -0,0 +1,57 @@
|
|||
import type { PageParam, PageResult } from '@vben/request';
|
||||
|
||||
import { requestClient } from '#/api/request';
|
||||
|
||||
export namespace MesMdProductSipApi {
|
||||
/** MES 产品 SIP */
|
||||
export interface ProductSip {
|
||||
id?: number; // SIP 编号
|
||||
itemId?: number; // 物料产品编号
|
||||
sort?: number; // 排列顺序
|
||||
processId?: number; // 工序编号
|
||||
title?: string; // 标题
|
||||
description?: string; // 详细描述
|
||||
url?: string; // 图片地址
|
||||
remark?: string; // 备注
|
||||
createTime?: Date; // 创建时间
|
||||
processCode?: string; // 工序编码
|
||||
processName?: string; // 工序名称
|
||||
}
|
||||
}
|
||||
|
||||
/** 新增产品 SIP */
|
||||
export function createProductSip(data: MesMdProductSipApi.ProductSip) {
|
||||
return requestClient.post('/mes/md/product-sip/create', data);
|
||||
}
|
||||
|
||||
/** 修改产品 SIP */
|
||||
export function updateProductSip(data: MesMdProductSipApi.ProductSip) {
|
||||
return requestClient.put('/mes/md/product-sip/update', data);
|
||||
}
|
||||
|
||||
/** 删除产品 SIP */
|
||||
export function deleteProductSip(id: number) {
|
||||
return requestClient.delete(`/mes/md/product-sip/delete?id=${id}`);
|
||||
}
|
||||
|
||||
/** 查询产品 SIP 详情 */
|
||||
export function getProductSip(id: number) {
|
||||
return requestClient.get<MesMdProductSipApi.ProductSip>(
|
||||
`/mes/md/product-sip/get?id=${id}`,
|
||||
);
|
||||
}
|
||||
|
||||
/** 查询产品 SIP 分页 */
|
||||
export function getProductSipPage(params: PageParam) {
|
||||
return requestClient.get<PageResult<MesMdProductSipApi.ProductSip>>(
|
||||
'/mes/md/product-sip/page',
|
||||
{ params },
|
||||
);
|
||||
}
|
||||
|
||||
/** 根据物料产品编号查询产品 SIP 列表 */
|
||||
export function getProductSipListByItemId(itemId: number) {
|
||||
return requestClient.get<MesMdProductSipApi.ProductSip[]>(
|
||||
`/mes/md/product-sip/list-by-item-id?itemId=${itemId}`,
|
||||
);
|
||||
}
|
||||
|
|
@ -0,0 +1,57 @@
|
|||
import type { PageParam, PageResult } from '@vben/request';
|
||||
|
||||
import { requestClient } from '#/api/request';
|
||||
|
||||
export namespace MesMdProductSopApi {
|
||||
/** MES 产品 SOP */
|
||||
export interface ProductSop {
|
||||
id?: number; // SOP 编号
|
||||
itemId?: number; // 物料产品编号
|
||||
sort?: number; // 排列顺序
|
||||
processId?: number; // 工序编号
|
||||
title?: string; // 标题
|
||||
description?: string; // 详细描述
|
||||
url?: string; // 图片地址
|
||||
remark?: string; // 备注
|
||||
createTime?: Date; // 创建时间
|
||||
processCode?: string; // 工序编码
|
||||
processName?: string; // 工序名称
|
||||
}
|
||||
}
|
||||
|
||||
/** 新增产品 SOP */
|
||||
export function createProductSop(data: MesMdProductSopApi.ProductSop) {
|
||||
return requestClient.post('/mes/md/product-sop/create', data);
|
||||
}
|
||||
|
||||
/** 修改产品 SOP */
|
||||
export function updateProductSop(data: MesMdProductSopApi.ProductSop) {
|
||||
return requestClient.put('/mes/md/product-sop/update', data);
|
||||
}
|
||||
|
||||
/** 删除产品 SOP */
|
||||
export function deleteProductSop(id: number) {
|
||||
return requestClient.delete(`/mes/md/product-sop/delete?id=${id}`);
|
||||
}
|
||||
|
||||
/** 查询产品 SOP 详情 */
|
||||
export function getProductSop(id: number) {
|
||||
return requestClient.get<MesMdProductSopApi.ProductSop>(
|
||||
`/mes/md/product-sop/get?id=${id}`,
|
||||
);
|
||||
}
|
||||
|
||||
/** 查询产品 SOP 分页 */
|
||||
export function getProductSopPage(params: PageParam) {
|
||||
return requestClient.get<PageResult<MesMdProductSopApi.ProductSop>>(
|
||||
'/mes/md/product-sop/page',
|
||||
{ params },
|
||||
);
|
||||
}
|
||||
|
||||
/** 根据物料产品编号查询产品 SOP 列表 */
|
||||
export function getProductSopListByItemId(itemId: number) {
|
||||
return requestClient.get<MesMdProductSopApi.ProductSop[]>(
|
||||
`/mes/md/product-sop/list-by-item-id?itemId=${itemId}`,
|
||||
);
|
||||
}
|
||||
|
|
@ -0,0 +1,54 @@
|
|||
import { requestClient } from '#/api/request';
|
||||
|
||||
export namespace MesMdItemTypeApi {
|
||||
/** MES 物料产品分类 */
|
||||
export interface ItemType {
|
||||
id?: number; // 分类编号
|
||||
parentId?: number; // 父分类编号
|
||||
code?: string; // 分类编码
|
||||
name?: string; // 分类名称
|
||||
itemOrProduct?: string; // 物料/产品标识
|
||||
sort?: number; // 显示排序
|
||||
status?: number; // 状态
|
||||
remark?: string; // 备注
|
||||
createTime?: Date; // 创建时间
|
||||
children?: ItemType[]; // 子分类
|
||||
}
|
||||
}
|
||||
|
||||
/** 查询物料产品分类列表 */
|
||||
export function getItemTypeList(params?: any) {
|
||||
return requestClient.get<MesMdItemTypeApi.ItemType[]>(
|
||||
'/mes/md/item-type/list',
|
||||
{ params },
|
||||
);
|
||||
}
|
||||
|
||||
/** 查询物料产品分类精简列表 */
|
||||
export function getItemTypeSimpleList() {
|
||||
return requestClient.get<MesMdItemTypeApi.ItemType[]>(
|
||||
'/mes/md/item-type/simple-list',
|
||||
);
|
||||
}
|
||||
|
||||
/** 查询物料产品分类详情 */
|
||||
export function getItemType(id: number) {
|
||||
return requestClient.get<MesMdItemTypeApi.ItemType>(
|
||||
`/mes/md/item-type/get?id=${id}`,
|
||||
);
|
||||
}
|
||||
|
||||
/** 新增物料产品分类 */
|
||||
export function createItemType(data: MesMdItemTypeApi.ItemType) {
|
||||
return requestClient.post('/mes/md/item-type/create', data);
|
||||
}
|
||||
|
||||
/** 修改物料产品分类 */
|
||||
export function updateItemType(data: MesMdItemTypeApi.ItemType) {
|
||||
return requestClient.put('/mes/md/item-type/update', data);
|
||||
}
|
||||
|
||||
/** 删除物料产品分类 */
|
||||
export function deleteItemType(id: number) {
|
||||
return requestClient.delete(`/mes/md/item-type/delete?id=${id}`);
|
||||
}
|
||||
|
|
@ -0,0 +1,62 @@
|
|||
import type { PageParam, PageResult } from '@vben/request';
|
||||
|
||||
import { requestClient } from '#/api/request';
|
||||
|
||||
export namespace MesMdUnitMeasureApi {
|
||||
/** MES 计量单位 */
|
||||
export interface UnitMeasure {
|
||||
id?: number; // 单位编号
|
||||
code?: string; // 单位编码
|
||||
name?: string; // 单位名称
|
||||
primaryFlag?: boolean; // 是否主单位
|
||||
primaryId?: number; // 主单位编号
|
||||
changeRate?: number; // 与主单位换算比例
|
||||
status?: number; // 状态
|
||||
remark?: string; // 备注
|
||||
createTime?: Date; // 创建时间
|
||||
}
|
||||
}
|
||||
|
||||
/** 查询计量单位分页 */
|
||||
export function getUnitMeasurePage(params: PageParam) {
|
||||
return requestClient.get<PageResult<MesMdUnitMeasureApi.UnitMeasure>>(
|
||||
'/mes/md/unit-measure/page',
|
||||
{ params },
|
||||
);
|
||||
}
|
||||
|
||||
/** 查询计量单位精简列表 */
|
||||
export function getUnitMeasureSimpleList() {
|
||||
return requestClient.get<MesMdUnitMeasureApi.UnitMeasure[]>(
|
||||
'/mes/md/unit-measure/simple-list',
|
||||
);
|
||||
}
|
||||
|
||||
/** 查询计量单位详情 */
|
||||
export function getUnitMeasure(id: number) {
|
||||
return requestClient.get<MesMdUnitMeasureApi.UnitMeasure>(
|
||||
`/mes/md/unit-measure/get?id=${id}`,
|
||||
);
|
||||
}
|
||||
|
||||
/** 新增计量单位 */
|
||||
export function createUnitMeasure(data: MesMdUnitMeasureApi.UnitMeasure) {
|
||||
return requestClient.post('/mes/md/unit-measure/create', data);
|
||||
}
|
||||
|
||||
/** 修改计量单位 */
|
||||
export function updateUnitMeasure(data: MesMdUnitMeasureApi.UnitMeasure) {
|
||||
return requestClient.put('/mes/md/unit-measure/update', data);
|
||||
}
|
||||
|
||||
/** 删除计量单位 */
|
||||
export function deleteUnitMeasure(id: number) {
|
||||
return requestClient.delete(`/mes/md/unit-measure/delete?id=${id}`);
|
||||
}
|
||||
|
||||
/** 导出计量单位 */
|
||||
export function exportUnitMeasure(params: PageParam) {
|
||||
return requestClient.download('/mes/md/unit-measure/export-excel', {
|
||||
params,
|
||||
});
|
||||
}
|
||||
|
|
@ -0,0 +1,87 @@
|
|||
import type { PageParam, PageResult } from '@vben/request';
|
||||
|
||||
import { requestClient } from '#/api/request';
|
||||
|
||||
export namespace MesMdVendorApi {
|
||||
/** MES 供应商 */
|
||||
export interface Vendor {
|
||||
id?: number; // 供应商编号
|
||||
code?: string; // 供应商编码
|
||||
name?: string; // 供应商名称
|
||||
nickname?: string; // 供应商简称
|
||||
englishName?: string; // 供应商英文名称
|
||||
description?: string; // 供应商简介
|
||||
logo?: string; // 供应商 LOGO 地址
|
||||
level?: string; // 供应商等级
|
||||
score?: number; // 供应商评分
|
||||
address?: string; // 供应商地址
|
||||
website?: string; // 供应商官网地址
|
||||
email?: string; // 供应商邮箱地址
|
||||
telephone?: string; // 供应商电话
|
||||
contact1Name?: string; // 联系人1
|
||||
contact1Telephone?: string; // 联系人1电话
|
||||
contact1Email?: string; // 联系人1邮箱
|
||||
contact2Name?: string; // 联系人2
|
||||
contact2Telephone?: string; // 联系人2电话
|
||||
contact2Email?: string; // 联系人2邮箱
|
||||
creditCode?: string; // 统一社会信用代码
|
||||
status?: number; // 状态
|
||||
remark?: string; // 备注
|
||||
createTime?: Date; // 创建时间
|
||||
}
|
||||
|
||||
/** 供应商导入结果 */
|
||||
export interface VendorImportRespVO {
|
||||
createCodes?: string[]; // 新增成功的供应商编码
|
||||
updateCodes?: string[]; // 更新成功的供应商编码
|
||||
failureCodes?: Record<string, string>; // 导入失败的供应商编码及原因
|
||||
}
|
||||
}
|
||||
|
||||
/** 查询供应商分页 */
|
||||
export function getVendorPage(params: PageParam) {
|
||||
return requestClient.get<PageResult<MesMdVendorApi.Vendor>>(
|
||||
'/mes/md-vendor/page',
|
||||
{ params },
|
||||
);
|
||||
}
|
||||
|
||||
/** 查询供应商详情 */
|
||||
export function getVendor(id: number) {
|
||||
return requestClient.get<MesMdVendorApi.Vendor>(
|
||||
`/mes/md-vendor/get?id=${id}`,
|
||||
);
|
||||
}
|
||||
|
||||
/** 新增供应商 */
|
||||
export function createVendor(data: MesMdVendorApi.Vendor) {
|
||||
return requestClient.post('/mes/md-vendor/create', data);
|
||||
}
|
||||
|
||||
/** 修改供应商 */
|
||||
export function updateVendor(data: MesMdVendorApi.Vendor) {
|
||||
return requestClient.put('/mes/md-vendor/update', data);
|
||||
}
|
||||
|
||||
/** 删除供应商 */
|
||||
export function deleteVendor(id: number) {
|
||||
return requestClient.delete(`/mes/md-vendor/delete?id=${id}`);
|
||||
}
|
||||
|
||||
/** 导出供应商 */
|
||||
export function exportVendor(params: any) {
|
||||
return requestClient.download('/mes/md-vendor/export-excel', { params });
|
||||
}
|
||||
|
||||
/** 下载供应商导入模板 */
|
||||
export function importVendorTemplate() {
|
||||
return requestClient.download('/mes/md-vendor/get-import-template');
|
||||
}
|
||||
|
||||
/** 导入供应商 */
|
||||
export function importVendor(file: File, updateSupport: boolean) {
|
||||
return requestClient.upload<MesMdVendorApi.VendorImportRespVO>(
|
||||
`/mes/md-vendor/import?updateSupport=${updateSupport}`,
|
||||
{ file },
|
||||
);
|
||||
}
|
||||
|
|
@ -0,0 +1,58 @@
|
|||
import type { PageParam, PageResult } from '@vben/request';
|
||||
|
||||
import { requestClient } from '#/api/request';
|
||||
|
||||
export namespace MesMdWorkstationApi {
|
||||
/** MES 工作站 */
|
||||
export interface Workstation {
|
||||
id?: number; // 工作站编号
|
||||
code?: string; // 工作站编码
|
||||
name?: string; // 工作站名称
|
||||
address?: string; // 工作站地点
|
||||
workshopId?: number; // 所在车间编号
|
||||
workshopName?: string; // 所在车间名称
|
||||
processId?: number; // 工序编号
|
||||
processName?: string; // 工序名称
|
||||
warehouseId?: number; // 线边库编号
|
||||
locationId?: number; // 库区编号
|
||||
areaId?: number; // 库位编号
|
||||
status?: number; // 状态
|
||||
remark?: string; // 备注
|
||||
createTime?: Date; // 创建时间
|
||||
}
|
||||
}
|
||||
|
||||
/** 查询工作站分页 */
|
||||
export function getWorkstationPage(params: PageParam) {
|
||||
return requestClient.get<PageResult<MesMdWorkstationApi.Workstation>>(
|
||||
'/mes/md-workstation/page',
|
||||
{ params },
|
||||
);
|
||||
}
|
||||
|
||||
/** 查询工作站详情 */
|
||||
export function getWorkstation(id: number) {
|
||||
return requestClient.get<MesMdWorkstationApi.Workstation>(
|
||||
`/mes/md-workstation/get?id=${id}`,
|
||||
);
|
||||
}
|
||||
|
||||
/** 新增工作站 */
|
||||
export function createWorkstation(data: MesMdWorkstationApi.Workstation) {
|
||||
return requestClient.post<number>('/mes/md-workstation/create', data);
|
||||
}
|
||||
|
||||
/** 修改工作站 */
|
||||
export function updateWorkstation(data: MesMdWorkstationApi.Workstation) {
|
||||
return requestClient.put('/mes/md-workstation/update', data);
|
||||
}
|
||||
|
||||
/** 删除工作站 */
|
||||
export function deleteWorkstation(id: number) {
|
||||
return requestClient.delete(`/mes/md-workstation/delete?id=${id}`);
|
||||
}
|
||||
|
||||
/** 导出工作站 */
|
||||
export function exportWorkstation(params: any) {
|
||||
return requestClient.download('/mes/md-workstation/export-excel', { params });
|
||||
}
|
||||
|
|
@ -0,0 +1,35 @@
|
|||
import { requestClient } from '#/api/request';
|
||||
|
||||
export namespace MesMdWorkstationMachineApi {
|
||||
/** MES 工作站设备资源 */
|
||||
export interface WorkstationMachine {
|
||||
id?: number; // 资源编号
|
||||
workstationId?: number; // 工作站编号
|
||||
machineryId?: number; // 设备编号
|
||||
machineryCode?: string; // 设备编码
|
||||
machineryName?: string; // 设备名称
|
||||
quantity?: number; // 数量
|
||||
remark?: string; // 备注
|
||||
createTime?: Date; // 创建时间
|
||||
}
|
||||
}
|
||||
|
||||
/** 查询工作站设备资源列表 */
|
||||
export function getWorkstationMachineList(workstationId: number) {
|
||||
return requestClient.get<MesMdWorkstationMachineApi.WorkstationMachine[]>(
|
||||
'/mes/md-workstation-machine/list-by-workstation',
|
||||
{ params: { workstationId } },
|
||||
);
|
||||
}
|
||||
|
||||
/** 新增工作站设备资源 */
|
||||
export function createWorkstationMachine(
|
||||
data: MesMdWorkstationMachineApi.WorkstationMachine,
|
||||
) {
|
||||
return requestClient.post('/mes/md-workstation-machine/create', data);
|
||||
}
|
||||
|
||||
/** 删除工作站设备资源 */
|
||||
export function deleteWorkstationMachine(id: number) {
|
||||
return requestClient.delete(`/mes/md-workstation-machine/delete?id=${id}`);
|
||||
}
|
||||
|
|
@ -0,0 +1,41 @@
|
|||
import { requestClient } from '#/api/request';
|
||||
|
||||
export namespace MesMdWorkstationToolApi {
|
||||
/** MES 工作站工装夹具资源 */
|
||||
export interface WorkstationTool {
|
||||
id?: number; // 资源编号
|
||||
workstationId?: number; // 工作站编号
|
||||
toolTypeId?: number; // 工具类型编号
|
||||
toolTypeName?: string; // 工具类型名称
|
||||
quantity?: number; // 数量
|
||||
remark?: string; // 备注
|
||||
createTime?: Date; // 创建时间
|
||||
}
|
||||
}
|
||||
|
||||
/** 查询工作站工装夹具资源列表 */
|
||||
export function getWorkstationToolList(workstationId: number) {
|
||||
return requestClient.get<MesMdWorkstationToolApi.WorkstationTool[]>(
|
||||
'/mes/md-workstation-tool/list-by-workstation',
|
||||
{ params: { workstationId } },
|
||||
);
|
||||
}
|
||||
|
||||
/** 新增工作站工装夹具资源 */
|
||||
export function createWorkstationTool(
|
||||
data: MesMdWorkstationToolApi.WorkstationTool,
|
||||
) {
|
||||
return requestClient.post('/mes/md-workstation-tool/create', data);
|
||||
}
|
||||
|
||||
/** 修改工作站工装夹具资源 */
|
||||
export function updateWorkstationTool(
|
||||
data: MesMdWorkstationToolApi.WorkstationTool,
|
||||
) {
|
||||
return requestClient.put('/mes/md-workstation-tool/update', data);
|
||||
}
|
||||
|
||||
/** 删除工作站工装夹具资源 */
|
||||
export function deleteWorkstationTool(id: number) {
|
||||
return requestClient.delete(`/mes/md-workstation-tool/delete?id=${id}`);
|
||||
}
|
||||
|
|
@ -0,0 +1,41 @@
|
|||
import { requestClient } from '#/api/request';
|
||||
|
||||
export namespace MesMdWorkstationWorkerApi {
|
||||
/** MES 工作站人力资源 */
|
||||
export interface WorkstationWorker {
|
||||
id?: number; // 资源编号
|
||||
workstationId?: number; // 工作站编号
|
||||
postId?: number; // 岗位编号
|
||||
postName?: string; // 岗位名称
|
||||
quantity?: number; // 数量
|
||||
remark?: string; // 备注
|
||||
createTime?: Date; // 创建时间
|
||||
}
|
||||
}
|
||||
|
||||
/** 查询工作站人力资源列表 */
|
||||
export function getWorkstationWorkerList(workstationId: number) {
|
||||
return requestClient.get<MesMdWorkstationWorkerApi.WorkstationWorker[]>(
|
||||
'/mes/md-workstation-worker/list-by-workstation',
|
||||
{ params: { workstationId } },
|
||||
);
|
||||
}
|
||||
|
||||
/** 新增工作站人力资源 */
|
||||
export function createWorkstationWorker(
|
||||
data: MesMdWorkstationWorkerApi.WorkstationWorker,
|
||||
) {
|
||||
return requestClient.post('/mes/md-workstation-worker/create', data);
|
||||
}
|
||||
|
||||
/** 修改工作站人力资源 */
|
||||
export function updateWorkstationWorker(
|
||||
data: MesMdWorkstationWorkerApi.WorkstationWorker,
|
||||
) {
|
||||
return requestClient.put('/mes/md-workstation-worker/update', data);
|
||||
}
|
||||
|
||||
/** 删除工作站人力资源 */
|
||||
export function deleteWorkstationWorker(id: number) {
|
||||
return requestClient.delete(`/mes/md-workstation-worker/delete?id=${id}`);
|
||||
}
|
||||
|
|
@ -0,0 +1,60 @@
|
|||
import type { PageParam, PageResult } from '@vben/request';
|
||||
|
||||
import { requestClient } from '#/api/request';
|
||||
|
||||
export namespace MesMdWorkshopApi {
|
||||
/** MES 车间 */
|
||||
export interface Workshop {
|
||||
id?: number; // 车间编号
|
||||
code?: string; // 车间编码
|
||||
name?: string; // 车间名称
|
||||
area?: number; // 面积
|
||||
chargeUserId?: number; // 负责人用户编号
|
||||
chargeUserName?: string; // 负责人名称
|
||||
status?: number; // 状态
|
||||
remark?: string; // 备注
|
||||
createTime?: Date; // 创建时间
|
||||
}
|
||||
}
|
||||
|
||||
/** 查询车间分页 */
|
||||
export function getWorkshopPage(params: PageParam) {
|
||||
return requestClient.get<PageResult<MesMdWorkshopApi.Workshop>>(
|
||||
'/mes/md-workshop/page',
|
||||
{ params },
|
||||
);
|
||||
}
|
||||
|
||||
/** 查询车间精简列表 */
|
||||
export function getWorkshopSimpleList() {
|
||||
return requestClient.get<MesMdWorkshopApi.Workshop[]>(
|
||||
'/mes/md-workshop/simple-list',
|
||||
);
|
||||
}
|
||||
|
||||
/** 查询车间详情 */
|
||||
export function getWorkshop(id: number) {
|
||||
return requestClient.get<MesMdWorkshopApi.Workshop>(
|
||||
`/mes/md-workshop/get?id=${id}`,
|
||||
);
|
||||
}
|
||||
|
||||
/** 新增车间 */
|
||||
export function createWorkshop(data: MesMdWorkshopApi.Workshop) {
|
||||
return requestClient.post('/mes/md-workshop/create', data);
|
||||
}
|
||||
|
||||
/** 修改车间 */
|
||||
export function updateWorkshop(data: MesMdWorkshopApi.Workshop) {
|
||||
return requestClient.put('/mes/md-workshop/update', data);
|
||||
}
|
||||
|
||||
/** 删除车间 */
|
||||
export function deleteWorkshop(id: number) {
|
||||
return requestClient.delete(`/mes/md-workshop/delete?id=${id}`);
|
||||
}
|
||||
|
||||
/** 导出车间 */
|
||||
export function exportWorkshop(params: any) {
|
||||
return requestClient.download('/mes/md-workshop/export-excel', { params });
|
||||
}
|
||||
|
|
@ -0,0 +1,38 @@
|
|||
import type { PageParam, PageResult } from '@vben/request';
|
||||
|
||||
import { requestClient } from '#/api/request';
|
||||
|
||||
export namespace MesProProcessApi {
|
||||
/** MES 生产工序 */
|
||||
export interface Process {
|
||||
id: number;
|
||||
code?: string;
|
||||
name?: string;
|
||||
attention?: string;
|
||||
status?: number;
|
||||
remark?: string;
|
||||
createTime?: Date;
|
||||
}
|
||||
}
|
||||
|
||||
/** 查询生产工序分页 */
|
||||
export function getProcessPage(params: PageParam) {
|
||||
return requestClient.get<PageResult<MesProProcessApi.Process>>(
|
||||
'/mes/pro/process/page',
|
||||
{ params },
|
||||
);
|
||||
}
|
||||
|
||||
/** 查询生产工序精简列表 */
|
||||
export function getProcessSimpleList() {
|
||||
return requestClient.get<MesProProcessApi.Process[]>(
|
||||
'/mes/pro/process/simple-list',
|
||||
);
|
||||
}
|
||||
|
||||
/** 查询生产工序详情 */
|
||||
export function getProcess(id: number) {
|
||||
return requestClient.get<MesProProcessApi.Process>(
|
||||
`/mes/pro/process/get?id=${id}`,
|
||||
);
|
||||
}
|
||||
|
|
@ -0,0 +1,61 @@
|
|||
import type { PageParam, PageResult } from '@vben/request';
|
||||
|
||||
import { requestClient } from '#/api/request';
|
||||
|
||||
export namespace MesTmToolApi {
|
||||
/** MES 工具台账 */
|
||||
export interface Tool {
|
||||
id?: number; // 工具编号
|
||||
code?: string; // 工具编码
|
||||
name?: string; // 工具名称
|
||||
brand?: string; // 品牌
|
||||
specification?: string; // 型号规格
|
||||
toolTypeId?: number; // 工具类型编号
|
||||
toolTypeName?: string; // 工具类型名称
|
||||
quantity?: number; // 数量
|
||||
availableQuantity?: number; // 可用数量
|
||||
maintenType?: number; // 保养维护类型
|
||||
nextMaintenPeriod?: number; // 下次保养周期
|
||||
nextMaintenDate?: Date | number; // 下次保养日期
|
||||
status?: number; // 状态
|
||||
remark?: string; // 备注
|
||||
createTime?: Date; // 创建时间
|
||||
}
|
||||
}
|
||||
|
||||
/** 查询工具台账分页 */
|
||||
export function getToolPage(params: PageParam) {
|
||||
return requestClient.get<PageResult<MesTmToolApi.Tool>>('/mes/tm/tool/page', {
|
||||
params,
|
||||
});
|
||||
}
|
||||
|
||||
/** 查询工具精简列表 */
|
||||
export function getToolSimpleList() {
|
||||
return requestClient.get<MesTmToolApi.Tool[]>('/mes/tm/tool/simple-list');
|
||||
}
|
||||
|
||||
/** 查询工具台账详情 */
|
||||
export function getTool(id: number) {
|
||||
return requestClient.get<MesTmToolApi.Tool>(`/mes/tm/tool/get?id=${id}`);
|
||||
}
|
||||
|
||||
/** 新增工具台账 */
|
||||
export function createTool(data: MesTmToolApi.Tool) {
|
||||
return requestClient.post('/mes/tm/tool/create', data);
|
||||
}
|
||||
|
||||
/** 修改工具台账 */
|
||||
export function updateTool(data: MesTmToolApi.Tool) {
|
||||
return requestClient.put('/mes/tm/tool/update', data);
|
||||
}
|
||||
|
||||
/** 删除工具台账 */
|
||||
export function deleteTool(id: number) {
|
||||
return requestClient.delete(`/mes/tm/tool/delete?id=${id}`);
|
||||
}
|
||||
|
||||
/** 导出工具台账 */
|
||||
export function exportTool(params: any) {
|
||||
return requestClient.download('/mes/tm/tool/export-excel', { params });
|
||||
}
|
||||
|
|
@ -0,0 +1,59 @@
|
|||
import type { PageParam, PageResult } from '@vben/request';
|
||||
|
||||
import { requestClient } from '#/api/request';
|
||||
|
||||
export namespace MesTmToolTypeApi {
|
||||
/** MES 工具类型 */
|
||||
export interface ToolType {
|
||||
id?: number; // 工具类型编号
|
||||
code?: string; // 类型编码
|
||||
name?: string; // 类型名称
|
||||
codeFlag?: boolean; // 是否编码管理
|
||||
maintenType?: number; // 保养维护类型
|
||||
maintenPeriod?: number; // 保养周期
|
||||
remark?: string; // 备注
|
||||
createTime?: Date; // 创建时间
|
||||
}
|
||||
}
|
||||
|
||||
/** 查询工具类型分页 */
|
||||
export function getToolTypePage(params: PageParam) {
|
||||
return requestClient.get<PageResult<MesTmToolTypeApi.ToolType>>(
|
||||
'/mes/tm/tool-type/page',
|
||||
{ params },
|
||||
);
|
||||
}
|
||||
|
||||
/** 查询工具类型精简列表 */
|
||||
export function getToolTypeSimpleList() {
|
||||
return requestClient.get<MesTmToolTypeApi.ToolType[]>(
|
||||
'/mes/tm/tool-type/simple-list',
|
||||
);
|
||||
}
|
||||
|
||||
/** 查询工具类型详情 */
|
||||
export function getToolType(id: number) {
|
||||
return requestClient.get<MesTmToolTypeApi.ToolType>(
|
||||
`/mes/tm/tool-type/get?id=${id}`,
|
||||
);
|
||||
}
|
||||
|
||||
/** 新增工具类型 */
|
||||
export function createToolType(data: MesTmToolTypeApi.ToolType) {
|
||||
return requestClient.post('/mes/tm/tool-type/create', data);
|
||||
}
|
||||
|
||||
/** 修改工具类型 */
|
||||
export function updateToolType(data: MesTmToolTypeApi.ToolType) {
|
||||
return requestClient.put('/mes/tm/tool-type/update', data);
|
||||
}
|
||||
|
||||
/** 删除工具类型 */
|
||||
export function deleteToolType(id: number) {
|
||||
return requestClient.delete(`/mes/tm/tool-type/delete?id=${id}`);
|
||||
}
|
||||
|
||||
/** 导出工具类型 */
|
||||
export function exportToolType(params: any) {
|
||||
return requestClient.download('/mes/tm/tool-type/export-excel', { params });
|
||||
}
|
||||
|
|
@ -0,0 +1,65 @@
|
|||
import type { PageParam, PageResult } from '@vben/request';
|
||||
|
||||
import { requestClient } from '#/api/request';
|
||||
|
||||
export namespace MesWmBarcodeApi {
|
||||
/** MES 条码清单 */
|
||||
export interface Barcode {
|
||||
id?: number;
|
||||
configId?: number;
|
||||
format?: number;
|
||||
bizType?: number;
|
||||
content?: string;
|
||||
bizId?: number;
|
||||
bizCode?: string;
|
||||
bizName?: string;
|
||||
status?: number;
|
||||
remark?: string;
|
||||
createTime?: Date;
|
||||
}
|
||||
}
|
||||
|
||||
/** 查询条码分页 */
|
||||
export function getBarcodePage(params: PageParam) {
|
||||
return requestClient.get<PageResult<MesWmBarcodeApi.Barcode>>(
|
||||
'/mes/wm/barcode/page',
|
||||
{ params },
|
||||
);
|
||||
}
|
||||
|
||||
/** 查询条码详情 */
|
||||
export function getBarcode(id: number) {
|
||||
return requestClient.get<MesWmBarcodeApi.Barcode>(
|
||||
`/mes/wm/barcode/get?id=${id}`,
|
||||
);
|
||||
}
|
||||
|
||||
/** 根据业务对象获取条码 */
|
||||
export function getBarcodeByBusiness(bizType: number, bizId: number) {
|
||||
return requestClient.get<MesWmBarcodeApi.Barcode>(
|
||||
'/mes/wm/barcode/get-by-business',
|
||||
{ params: { bizType, bizId } },
|
||||
);
|
||||
}
|
||||
|
||||
/** 新增条码 */
|
||||
export function createBarcode(data: MesWmBarcodeApi.Barcode) {
|
||||
return requestClient.post('/mes/wm/barcode/create', data);
|
||||
}
|
||||
|
||||
/** 修改条码 */
|
||||
export function updateBarcode(data: MesWmBarcodeApi.Barcode) {
|
||||
return requestClient.put('/mes/wm/barcode/update', data);
|
||||
}
|
||||
|
||||
/** 删除条码 */
|
||||
export function deleteBarcode(id: number) {
|
||||
return requestClient.delete(`/mes/wm/barcode/delete?id=${id}`);
|
||||
}
|
||||
|
||||
/** 生成条码内容 */
|
||||
export function generateBarcodeContent(bizType: number, bizCode: string) {
|
||||
return requestClient.get<string>('/mes/wm/barcode/generate-content', {
|
||||
params: { bizType, bizCode },
|
||||
});
|
||||
}
|
||||
|
|
@ -0,0 +1,34 @@
|
|||
import { requestClient } from '#/api/request';
|
||||
|
||||
export namespace MesWmItemReceiptApi {
|
||||
/** MES 采购入库单 */
|
||||
export interface ItemReceipt {
|
||||
id?: number; // 入库单编号
|
||||
code?: string; // 入库单编码
|
||||
name?: string; // 入库单名称
|
||||
iqcId?: number; // 来料检验单编号
|
||||
iqcCode?: string; // 来料检验单编码
|
||||
noticeId?: number; // 到货通知单编号
|
||||
noticeCode?: string; // 到货通知单编码
|
||||
purchaseOrderCode?: string; // 采购订单号
|
||||
vendorId?: number; // 供应商编号
|
||||
vendorName?: string; // 供应商名称
|
||||
warehouseId?: number; // 仓库编号
|
||||
warehouseName?: string; // 仓库名称
|
||||
locationId?: number; // 库区编号
|
||||
locationName?: string; // 库区名称
|
||||
areaId?: number; // 库位编号
|
||||
areaName?: string; // 库位名称
|
||||
receiptDate?: Date | number | string; // 入库日期
|
||||
status?: number; // 状态
|
||||
remark?: string; // 备注
|
||||
createTime?: Date; // 创建时间
|
||||
}
|
||||
}
|
||||
|
||||
/** 查询采购入库单详情 */
|
||||
export function getItemReceipt(id: number) {
|
||||
return requestClient.get<MesWmItemReceiptApi.ItemReceipt>(
|
||||
`/mes/wm/item-receipt/get?id=${id}`,
|
||||
);
|
||||
}
|
||||
|
|
@ -0,0 +1,28 @@
|
|||
import type { PageParam, PageResult } from '@vben/request';
|
||||
|
||||
import { requestClient } from '#/api/request';
|
||||
|
||||
export namespace MesWmItemReceiptLineApi {
|
||||
/** MES 物料接收单行 */
|
||||
export interface ItemReceiptLine {
|
||||
id?: number; // 行编号
|
||||
receiptId?: number; // 入库单编号
|
||||
receiptCode?: string; // 入库单编码
|
||||
purchaseOrderCode?: string; // 采购订单号
|
||||
itemId?: number; // 物料编号
|
||||
itemCode?: string; // 物料编码
|
||||
itemName?: string; // 物料名称
|
||||
specification?: string; // 规格型号
|
||||
unitMeasureName?: string; // 单位
|
||||
receivedQuantity?: number; // 入库数量
|
||||
batchCode?: string; // 批次号
|
||||
}
|
||||
}
|
||||
|
||||
/** 查询物料接收单行分页 */
|
||||
export function getItemReceiptLinePage(params: PageParam) {
|
||||
return requestClient.get<PageResult<MesWmItemReceiptLineApi.ItemReceiptLine>>(
|
||||
'/mes/wm/item-receipt-line/page',
|
||||
{ params },
|
||||
);
|
||||
}
|
||||
|
|
@ -0,0 +1,23 @@
|
|||
import type { PageParam, PageResult } from '@vben/request';
|
||||
|
||||
import { requestClient } from '#/api/request';
|
||||
|
||||
export namespace MesWmProductSalesApi {
|
||||
/** MES 销售出库单 */
|
||||
export interface ProductSales {
|
||||
id?: number; // 销售出库单编号
|
||||
code?: string; // 出库单编号
|
||||
name?: string; // 出库单名称
|
||||
salesOrderCode?: string; // 销售订单编号
|
||||
salesDate?: Date; // 出库日期
|
||||
status?: number; // 单据状态
|
||||
}
|
||||
}
|
||||
|
||||
/** 查询销售出库单分页 */
|
||||
export function getProductSalesPage(params: PageParam) {
|
||||
return requestClient.get<PageResult<MesWmProductSalesApi.ProductSales>>(
|
||||
'/mes/wm/product-sales/page',
|
||||
{ params },
|
||||
);
|
||||
}
|
||||
|
|
@ -0,0 +1,24 @@
|
|||
import type { PageParam, PageResult } from '@vben/request';
|
||||
|
||||
import { requestClient } from '#/api/request';
|
||||
|
||||
export namespace MesWmProductSalesLineApi {
|
||||
/** MES 销售出库单行 */
|
||||
export interface ProductSalesLine {
|
||||
id?: number; // 行编号
|
||||
itemId?: number; // 物料编号
|
||||
itemCode?: string; // 物料编码
|
||||
itemName?: string; // 物料名称
|
||||
specification?: string; // 规格型号
|
||||
unitMeasureName?: string; // 单位
|
||||
quantity?: number; // 出库数量
|
||||
batchCode?: string; // 批次号
|
||||
}
|
||||
}
|
||||
|
||||
/** 查询销售出库单行分页 */
|
||||
export function getProductSalesLinePage(params: PageParam) {
|
||||
return requestClient.get<
|
||||
PageResult<MesWmProductSalesLineApi.ProductSalesLine>
|
||||
>('/mes/wm/product-sales-line/page', { params });
|
||||
}
|
||||
|
|
@ -0,0 +1,50 @@
|
|||
import type { PageParam, PageResult } from '@vben/request';
|
||||
|
||||
import { requestClient } from '#/api/request';
|
||||
|
||||
export namespace MesWmWarehouseAreaApi {
|
||||
/** MES 库位 */
|
||||
export interface WarehouseArea {
|
||||
id?: number; // 库位编号
|
||||
code?: string; // 库位编码
|
||||
name?: string; // 库位名称
|
||||
warehouseId?: number; // 仓库编号
|
||||
warehouseName?: string; // 仓库名称
|
||||
locationId?: number; // 库区编号
|
||||
locationName?: string; // 库区名称
|
||||
area?: number; // 面积
|
||||
maxLoad?: number; // 最大载荷
|
||||
positionX?: number; // X 坐标
|
||||
positionY?: number; // Y 坐标
|
||||
positionZ?: number; // Z 坐标
|
||||
status?: number; // 状态
|
||||
frozen?: boolean; // 是否冻结
|
||||
allowItemMixing?: boolean; // 是否允许物料混放
|
||||
allowBatchMixing?: boolean; // 是否允许批次混放
|
||||
remark?: string; // 备注
|
||||
createTime?: Date; // 创建时间
|
||||
}
|
||||
}
|
||||
|
||||
/** 查询库位分页 */
|
||||
export function getWarehouseAreaPage(params: PageParam) {
|
||||
return requestClient.get<PageResult<MesWmWarehouseAreaApi.WarehouseArea>>(
|
||||
'/mes/wm/warehouse-area/page',
|
||||
{ params },
|
||||
);
|
||||
}
|
||||
|
||||
/** 查询库位精简列表 */
|
||||
export function getWarehouseAreaSimpleList(locationId?: number) {
|
||||
return requestClient.get<MesWmWarehouseAreaApi.WarehouseArea[]>(
|
||||
'/mes/wm/warehouse-area/simple-list',
|
||||
{ params: { locationId } },
|
||||
);
|
||||
}
|
||||
|
||||
/** 查询库位详情 */
|
||||
export function getWarehouseArea(id: number) {
|
||||
return requestClient.get<MesWmWarehouseAreaApi.WarehouseArea>(
|
||||
`/mes/wm/warehouse-area/get?id=${id}`,
|
||||
);
|
||||
}
|
||||
|
|
@ -0,0 +1,40 @@
|
|||
import type { PageParam, PageResult } from '@vben/request';
|
||||
|
||||
import { requestClient } from '#/api/request';
|
||||
|
||||
export namespace MesWmWarehouseApi {
|
||||
/** MES 仓库 */
|
||||
export interface Warehouse {
|
||||
id?: number; // 仓库编号
|
||||
code?: string; // 仓库编码
|
||||
name?: string; // 仓库名称
|
||||
address?: string; // 地址
|
||||
area?: number; // 面积
|
||||
chargeUserId?: number; // 负责人
|
||||
frozen?: boolean; // 是否冻结
|
||||
remark?: string; // 备注
|
||||
createTime?: Date; // 创建时间
|
||||
}
|
||||
}
|
||||
|
||||
/** 查询仓库分页 */
|
||||
export function getWarehousePage(params: PageParam) {
|
||||
return requestClient.get<PageResult<MesWmWarehouseApi.Warehouse>>(
|
||||
'/mes/wm/warehouse/page',
|
||||
{ params },
|
||||
);
|
||||
}
|
||||
|
||||
/** 查询仓库精简列表 */
|
||||
export function getWarehouseSimpleList() {
|
||||
return requestClient.get<MesWmWarehouseApi.Warehouse[]>(
|
||||
'/mes/wm/warehouse/simple-list',
|
||||
);
|
||||
}
|
||||
|
||||
/** 查询仓库详情 */
|
||||
export function getWarehouse(id: number) {
|
||||
return requestClient.get<MesWmWarehouseApi.Warehouse>(
|
||||
`/mes/wm/warehouse/get?id=${id}`,
|
||||
);
|
||||
}
|
||||
|
|
@ -0,0 +1,40 @@
|
|||
import type { PageParam, PageResult } from '@vben/request';
|
||||
|
||||
import { requestClient } from '#/api/request';
|
||||
|
||||
export namespace MesWmWarehouseLocationApi {
|
||||
/** MES 库区 */
|
||||
export interface WarehouseLocation {
|
||||
id?: number; // 库区编号
|
||||
code?: string; // 库区编码
|
||||
name?: string; // 库区名称
|
||||
warehouseId?: number; // 仓库编号
|
||||
warehouseName?: string; // 仓库名称
|
||||
area?: number; // 面积
|
||||
frozen?: boolean; // 是否冻结
|
||||
remark?: string; // 备注
|
||||
createTime?: Date; // 创建时间
|
||||
}
|
||||
}
|
||||
|
||||
/** 查询库区分页 */
|
||||
export function getWarehouseLocationPage(params: PageParam) {
|
||||
return requestClient.get<
|
||||
PageResult<MesWmWarehouseLocationApi.WarehouseLocation>
|
||||
>('/mes/wm/warehouse-location/page', { params });
|
||||
}
|
||||
|
||||
/** 查询库区精简列表 */
|
||||
export function getWarehouseLocationSimpleList(warehouseId?: number) {
|
||||
return requestClient.get<MesWmWarehouseLocationApi.WarehouseLocation[]>(
|
||||
'/mes/wm/warehouse-location/simple-list',
|
||||
{ params: { warehouseId } },
|
||||
);
|
||||
}
|
||||
|
||||
/** 查询库区详情 */
|
||||
export function getWarehouseLocation(id: number) {
|
||||
return requestClient.get<MesWmWarehouseLocationApi.WarehouseLocation>(
|
||||
`/mes/wm/warehouse-location/get?id=${id}`,
|
||||
);
|
||||
}
|
||||
|
|
@ -119,13 +119,58 @@ function createRequestClient(baseURL: string, options?: RequestClientOptions) {
|
|||
response.data = apiEncrypt.decryptResponse(response.data);
|
||||
} catch (error) {
|
||||
console.error('响应数据解密失败:', error);
|
||||
throw new Error(`响应数据解密失败: ${(error as Error).message}`);
|
||||
throw new Error(`响应数据解密失败: ${(error as Error).message}`, {
|
||||
cause: error,
|
||||
});
|
||||
}
|
||||
}
|
||||
return response;
|
||||
},
|
||||
});
|
||||
|
||||
// add by 芋艿:对应 https://t.zsxq.com/SHqWw 反馈
|
||||
// 处理 Blob 响应中的业务错误(如 401):后端把「账号未登录」包成 HTTP 200 + body {code: 401, msg: ...},
|
||||
// download 强制 responseType: 'blob' 后被 axios 包成 application/json 的 Blob,defaultResponseInterceptor 走
|
||||
// responseReturn === 'body' 分支直接返回,绕过了 authenticateResponseInterceptor 的 401 token 刷新;
|
||||
// 这里把这种 Blob 解析回 JSON,再以 axios 风格抛出,让后续拦截器接管
|
||||
client.addResponseInterceptor({
|
||||
fulfilled: async (response) => {
|
||||
const blob = response.data;
|
||||
if (!(blob instanceof Blob)) {
|
||||
return response;
|
||||
}
|
||||
// Blob.type 在部分环境可能为空或大小写不一,叠加 response header 一起判断更稳
|
||||
const blobType = (blob.type || '').toLowerCase();
|
||||
const headerType = String(
|
||||
response.headers?.['content-type'] ??
|
||||
response.headers?.['Content-Type'] ??
|
||||
'',
|
||||
).toLowerCase();
|
||||
if (
|
||||
!blobType.includes('application/json') &&
|
||||
!headerType.includes('application/json')
|
||||
) {
|
||||
return response;
|
||||
}
|
||||
let parsed: any;
|
||||
try {
|
||||
parsed = JSON.parse(await blob.text());
|
||||
} catch {
|
||||
return response;
|
||||
}
|
||||
if (parsed && parsed.code !== undefined && parsed.code !== 0) {
|
||||
response.data = parsed;
|
||||
throw Object.assign(new Error(parsed.msg ?? 'Request failed'), {
|
||||
config: response.config,
|
||||
response,
|
||||
data: parsed,
|
||||
isAxiosError: true,
|
||||
});
|
||||
}
|
||||
return response;
|
||||
},
|
||||
});
|
||||
|
||||
// 处理返回的响应数据格式
|
||||
client.addResponseInterceptor(
|
||||
defaultResponseInterceptor({
|
||||
|
|
|
|||