Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
1b036e84d1 | ||
|
|
900d275055 | ||
|
|
2ff21aa65e | ||
|
|
108dcccafe | ||
|
|
a805ceb534 | ||
|
|
cb02377706 | ||
|
|
bead947284 | ||
|
|
fa59b3c16a | ||
|
|
fde37b0410 | ||
|
|
e6f2a62c15 | ||
|
|
df8b1fbc0d | ||
|
|
36b5db16dd | ||
|
|
8bbe9ad424 | ||
|
|
3fec45b5b4 | ||
|
|
8caf19a193 | ||
|
|
05a6c4f288 | ||
|
|
d88707b306 | ||
|
|
8f31bd73cd | ||
|
|
9e44a6cf0f | ||
|
|
188b4033ba | ||
|
|
145226deed | ||
|
|
f5d445be1d | ||
|
|
e21114c0b5 | ||
|
|
cfb3e4a5ff | ||
|
|
162b93bc1d | ||
|
|
0763f33351 | ||
|
|
0704672ad3 | ||
|
|
8ed2afb712 | ||
|
|
5d91131eb7 | ||
|
|
46da7e2876 | ||
|
|
4a829c7525 | ||
|
|
4d3c5b7eff | ||
|
|
fcf948e781 | ||
|
|
bd643f9376 | ||
|
|
b7f06ec698 | ||
|
|
7f7c508bb2 | ||
|
|
638035249e | ||
|
|
bfddd674c1 | ||
|
|
e8a0eb08d6 | ||
|
|
4abd246d96 | ||
|
|
d072098038 | ||
|
|
1ad5de57f9 | ||
|
|
eeb76bb4c2 | ||
|
|
fe48f87f37 | ||
|
|
f0ba8ff0af | ||
|
|
14cb120519 | ||
|
|
34542cae4b | ||
|
|
ccf21dd4d4 | ||
|
|
416df14b8c | ||
|
|
21c7c17e8f | ||
|
|
a854e96343 | ||
|
|
b1752f39b6 | ||
|
|
9b647cc19e | ||
|
|
922b0c4e63 | ||
|
|
10f6a2b158 | ||
|
|
806888cce8 | ||
|
|
4d44440070 | ||
|
|
35b2708ca6 | ||
|
|
c4ee9581d0 | ||
|
|
0a48b523b9 | ||
|
|
1f22e0b88d | ||
|
|
d266b99e9e | ||
|
|
69940e2780 | ||
|
|
369860a055 | ||
|
|
ae0bca1774 | ||
|
|
d14ba2ed9e | ||
|
|
bb17651915 | ||
|
|
dd76cc581c | ||
|
|
b9178c88aa | ||
|
|
933628050b | ||
|
|
925d356e41 | ||
|
|
12c0f36bb8 | ||
|
|
b98f1220ac | ||
|
|
392603c811 | ||
|
|
e655b4d6ef | ||
|
|
c76b622722 | ||
|
|
51c6bfe42c | ||
|
|
60d4175396 | ||
|
|
20054b28c3 | ||
|
|
79b6b87721 | ||
|
|
b6cd12a300 | ||
|
|
993d070560 | ||
|
|
fa0892980d | ||
|
|
32d6ac0183 | ||
|
|
ece1533436 | ||
|
|
e53786e8bd | ||
|
|
908b3c212c | ||
|
|
ec61670b75 | ||
|
|
21ade9b9ac | ||
|
|
a68ae29f3a | ||
|
|
9e628ba59d | ||
|
|
5730707be9 | ||
|
|
6550983413 | ||
|
|
0051264142 | ||
|
|
ba8681e3c7 | ||
|
|
e881b9cefd | ||
|
|
7706e46bfa | ||
|
|
75af4f07c0 | ||
|
|
9e3f228a61 | ||
|
|
d6c016e3ea | ||
|
|
dbacc0c371 | ||
|
|
4cfc785667 | ||
|
|
5734faa5fc | ||
|
|
326fc3d03f | ||
|
|
93006504ce | ||
|
|
cb68ef5fa7 | ||
|
|
b4b9015869 | ||
|
|
2204876076 | ||
|
|
ebc995ac4c | ||
|
|
9dfb869a4b | ||
|
|
61bf6fb85b | ||
|
|
ac46a37638 | ||
|
|
749e44081e | ||
|
|
5162191340 | ||
|
|
82b53b9b03 | ||
|
|
80d87b8e99 | ||
|
|
6224602152 | ||
|
|
848bc60612 | ||
|
|
1a6afa3263 | ||
|
|
2b0789112f | ||
|
|
e9bb9403b4 | ||
|
|
96a499a815 | ||
|
|
f72e4f47f4 | ||
|
|
44f322bb35 | ||
|
|
1064bbe570 | ||
|
|
1afdbe651e | ||
|
|
18e87cf967 | ||
|
|
f3777f6334 | ||
|
|
4acd379d50 | ||
|
|
8a73fbe775 | ||
|
|
38fe69fbd4 | ||
|
|
f341ba4d3c | ||
|
|
21c9cba67b | ||
|
|
3938a78db2 | ||
|
|
2871961582 | ||
|
|
a9ca98036c | ||
|
|
6f86ea96da | ||
|
|
922b9edfcb | ||
|
|
c825216063 | ||
|
|
f70c8dcee2 | ||
|
|
8d73d741d4 | ||
|
|
d3c596dcaf | ||
|
|
334c0241a9 | ||
|
|
db3b8285d1 | ||
|
|
9ab367e4f4 | ||
|
|
5fd8177791 | ||
|
|
fda50ff291 | ||
|
|
f147f05aeb | ||
|
|
53de30c698 | ||
|
|
afcb7e76b7 | ||
|
|
557dc7d5d9 | ||
|
|
8cc40626d6 | ||
|
|
ca64760dd0 | ||
|
|
cd2f049619 | ||
|
|
c09af1cbe1 | ||
|
|
cabfc5ccc0 | ||
|
|
2b329d33e4 | ||
|
|
893cd5d8f5 | ||
|
|
edaf30a32b | ||
|
|
b6ff9ede11 | ||
|
|
e89b274e3f | ||
|
|
e45cade877 | ||
|
|
bb34c2b75c | ||
|
|
39facc2f49 | ||
|
|
807e9272a5 | ||
|
|
d974124918 | ||
|
|
8f6e6fdb54 | ||
|
|
ed786b2db6 | ||
|
|
5c560e2fbe | ||
|
|
0e755acf52 | ||
|
|
16d53bbf4b | ||
|
|
9c43594010 | ||
|
|
b0b62eb250 | ||
|
|
33cf98e306 | ||
|
|
8da1c04b55 | ||
|
|
8d759b2a0b | ||
|
|
00619ca6db | ||
|
|
91c262fb24 | ||
|
|
9c05ff35db | ||
|
|
1abfec766e | ||
|
|
3d5cb15eae | ||
|
|
7a6f5c2db8 | ||
|
|
d3b4063b94 | ||
|
|
d3614cbbac | ||
|
|
f19e8c4d0a | ||
|
|
f98f794f77 | ||
|
|
68c573d902 | ||
|
|
d800143a88 | ||
|
|
9983dc5bb9 | ||
|
|
906169f9be | ||
|
|
6f9cb4f8f2 | ||
|
|
c0e51bd7aa | ||
|
|
e3c46cab53 | ||
|
|
440ad58a77 | ||
|
|
8d33476472 | ||
|
|
75d0be9742 | ||
|
|
8daf9bb347 | ||
|
|
14c9e33b60 | ||
|
|
2da5cc34a8 | ||
|
|
9516e7184f | ||
|
|
39d3995ea0 | ||
|
|
6e7812a11b | ||
|
|
36dc3c0b5c | ||
|
|
ef9ed50533 | ||
|
|
bd4f2b8b7c | ||
|
|
d66664b3d4 | ||
|
|
7fe8b8b7a9 | ||
|
|
a0ecfed693 | ||
|
|
ca7077caf6 | ||
|
|
1bbed80e2e | ||
|
|
0895f9ffcb | ||
|
|
210c4d4024 | ||
|
|
2cd98a438f | ||
|
|
33366efe11 | ||
|
|
1a04b7b9e7 | ||
|
|
8eee46d85c | ||
|
|
918f35f824 | ||
|
|
bd80a6f34f | ||
|
|
63f0a2058d | ||
|
|
dc31aeb24e | ||
|
|
19c752e81d | ||
|
|
05ba908a7f | ||
|
|
8db7c7d92b | ||
|
|
990093c0cb | ||
|
|
27d7fe48c6 | ||
|
|
79819aed19 | ||
|
|
3f3faaca9b | ||
|
|
490c4bde02 | ||
|
|
7f034724a9 | ||
|
|
efcf64ed7d | ||
|
|
4adc5677a0 | ||
|
|
1b070e720d | ||
|
|
520244eea9 | ||
|
|
e83df37616 | ||
|
|
c96f3cea61 | ||
|
|
29e1426a79 | ||
|
|
1be7713f56 | ||
|
|
5876fdca10 | ||
|
|
8e821445c2 | ||
|
|
9bd8d8e9cb | ||
|
|
3c4327e4dd | ||
|
|
1eacbe62d6 | ||
|
|
a2474c9c43 | ||
|
|
cc9e11859d | ||
|
|
f60b308dec | ||
|
|
616fe2c3c1 | ||
|
|
d1be8991b3 | ||
|
|
82fbb5e024 | ||
|
|
15a3e80d62 | ||
|
|
6726a7c562 | ||
|
|
8a8cb159a4 | ||
|
|
87ffd38dcd | ||
|
|
8f2c6ab0db | ||
|
|
cc39be8207 | ||
|
|
b82391da0a | ||
|
|
a9082d8b6f | ||
|
|
ecc924301d | ||
|
|
11ec263a64 | ||
|
|
bbf7956f6d | ||
|
|
b0f26f64f7 | ||
|
|
bd09ecf688 | ||
|
|
a6ec43fd46 | ||
|
|
0a9882e909 | ||
|
|
c8d26db4b4 | ||
|
|
fdeedcfe7b | ||
|
|
2211618ada | ||
|
|
c87713f040 | ||
|
|
91fc46691e | ||
|
|
ad10328b73 | ||
|
|
0b8301cc1c | ||
|
|
f74e8e6689 | ||
|
|
805745f384 | ||
|
|
824fb4d5ec | ||
|
|
d74677abd0 | ||
|
|
df5c3be7fa | ||
|
|
cc60edf8d3 | ||
|
|
d1e0270bee | ||
|
|
5353531e8b | ||
|
|
9cad4d6054 | ||
|
|
d9ebb61dc1 | ||
|
|
2ae7838aeb | ||
|
|
fd4ef4b172 | ||
|
|
959ee90810 | ||
|
|
cb7c5b7458 | ||
|
|
c06dd8e273 | ||
|
|
4542337f4f | ||
|
|
376ec1a61c | ||
|
|
51e28065ee | ||
|
|
3d5879ecb8 | ||
|
|
61418a1a1b | ||
|
|
9c8d10b70c | ||
|
|
131e071b2d | ||
|
|
bfa396b127 | ||
|
|
ffa691c4ee | ||
|
|
86f3ae2301 | ||
|
|
12e87cc0f2 | ||
|
|
f156ba1877 | ||
|
|
60de1b9737 | ||
|
|
5232a2bf3f | ||
|
|
9460c264eb | ||
|
|
df6cca0731 | ||
|
|
e801ea949b | ||
|
|
3d5bef78b3 | ||
|
|
a46185e4dd | ||
|
|
cdf0a1137d | ||
|
|
46eb89695d | ||
|
|
4c259cd60f | ||
|
|
d172d3db73 | ||
|
|
ca40047f0b | ||
|
|
ac18d871ca | ||
|
|
24c459557d | ||
|
|
63693f7a83 | ||
|
|
09c03abf51 | ||
|
|
8764c6c471 | ||
|
|
8fb54dbb7c | ||
|
|
bebf1e7ae3 | ||
|
|
03c6a6ce59 | ||
|
|
f1beb488ce | ||
|
|
89deddb9e0 | ||
|
|
e7403ba2a4 | ||
|
|
aa93172c1d | ||
|
|
689d92dc66 | ||
|
|
fa4081d669 | ||
|
|
4466c5b4ec | ||
|
|
431ae7b01b | ||
|
|
561d60bccd | ||
|
|
d603f1edd0 | ||
|
|
8f2b81bb79 | ||
|
|
63638ce4a1 | ||
|
|
a96a2ec9ec | ||
|
|
a431867f41 | ||
|
|
32c6818ee8 | ||
|
|
f6698c0286 | ||
|
|
2d7bf84593 | ||
|
|
a8cf6b6f29 | ||
|
|
15b8ea5a0d | ||
|
|
c06de8095e | ||
|
|
0803e33d1d | ||
|
|
d883b860ac | ||
|
|
88c7dc52be | ||
|
|
5aa8261b7b | ||
|
|
da75b1758f | ||
|
|
7237da9764 | ||
|
|
3634fca835 | ||
|
|
24ead9f09b | ||
|
|
15e7a260bf | ||
|
|
e3bc50e4fc | ||
|
|
6a03b7637e | ||
|
|
8b0d598d8a | ||
|
|
8ca3d26cbb | ||
|
|
e896e5bb27 | ||
|
|
939e3790ee | ||
|
|
8c81a9fc19 | ||
|
|
5c15b7f503 | ||
|
|
f164225bbe | ||
|
|
61fa0f65ab | ||
|
|
ac436ae186 | ||
|
|
5871464681 | ||
|
|
138cf760b2 | ||
|
|
cb64b940a5 | ||
|
|
264cad5301 | ||
|
|
7de0b075cb | ||
|
|
e04a8eeea9 | ||
|
|
c2b439c463 | ||
|
|
de754a6a6e | ||
|
|
8bea8ce623 | ||
|
|
a33c0887b0 | ||
|
|
559cd48c4f | ||
|
|
07241b5efb | ||
|
|
2be1411179 | ||
|
|
b9460d2028 | ||
|
|
959731609f | ||
|
|
d8dcc911b5 | ||
|
|
1c8bdc7e7e | ||
|
|
7acc2fcb1b | ||
|
|
2b38e62c85 | ||
|
|
0569dd1a26 | ||
|
|
43a41290a0 | ||
|
|
a3c5d253b3 | ||
|
|
055abf62cd | ||
|
|
ca2b7202e6 | ||
|
|
b6c654f039 | ||
|
|
60fdbfb838 | ||
|
|
f6f786f1b6 | ||
|
|
1a1e53ae70 | ||
|
|
fc31528367 | ||
|
|
48b3b08f0a | ||
|
|
cfdceca9f3 | ||
|
|
0fef28e4a5 | ||
|
|
efaf9ea96c | ||
|
|
68762e73a2 | ||
|
|
d5ffc80ea5 | ||
|
|
0d44b6cb37 | ||
|
|
da65de038e | ||
|
|
80746d20fd | ||
|
|
c3884c5dfd | ||
|
|
222a841226 | ||
|
|
934d5e7ca8 | ||
|
|
dbca077f31 | ||
|
|
7ab9aa77b8 | ||
|
|
6fc5f8c685 | ||
|
|
1a681c2063 | ||
|
|
58d3d1ed9a | ||
|
|
22081cbd48 | ||
|
|
b7d5ce4bc5 | ||
|
|
e0b38f5804 | ||
|
|
482ce62370 | ||
|
|
bc8948eecf | ||
|
|
a9994970fc | ||
|
|
91593d5d40 | ||
|
|
ac9e5846c4 | ||
|
|
9c370f729a | ||
|
|
36beffe140 | ||
|
|
f21991f4fc | ||
|
|
ad02983098 | ||
|
|
25d346c201 | ||
|
|
1a56021e75 | ||
|
|
da66aead54 | ||
|
|
f14032d69d | ||
|
|
9658af7c04 | ||
|
|
490b11aa3a | ||
|
|
e7643c0343 | ||
|
|
5c02e79105 | ||
|
|
b2c15ab2cb | ||
|
|
4d3c5ef7c1 | ||
|
|
83b9332125 | ||
|
|
3d83f4928a | ||
|
|
c06bc71020 | ||
|
|
3e0da37e16 | ||
|
|
986f50c6da | ||
|
|
76903f6868 | ||
|
|
bd5262e21d | ||
|
|
ebd593bf92 | ||
|
|
67ece2ac5c | ||
|
|
051a610e56 | ||
|
|
3d15eadb5d | ||
|
|
175f9d58ad | ||
|
|
8d907a76bf | ||
|
|
cea5b8b138 | ||
|
|
27569a746e | ||
|
|
20b7403a6a | ||
|
|
6c1298f7ef | ||
|
|
df60cb617f | ||
|
|
c16bcef5a6 | ||
|
|
ffc134d26c | ||
|
|
5ec08e9758 | ||
|
|
9e99807bd0 | ||
|
|
10beee84fb | ||
|
|
7f25419caf | ||
|
|
b0de27a721 | ||
|
|
c1b9baf8b6 | ||
|
|
151076a79e | ||
|
|
b116d82376 | ||
|
|
be978f2e9f | ||
|
|
663c8b3824 | ||
|
|
05e6c2c2df | ||
|
|
057a980982 | ||
|
|
73e8516024 | ||
|
|
8ba6095b1b | ||
|
|
43dcefdcf0 | ||
|
|
93bee8c82c | ||
|
|
0385d4dbb3 | ||
|
|
aefee5211a | ||
|
|
dd2c4b6b3c | ||
|
|
f01dc0a539 | ||
|
|
7883e3161d | ||
|
|
0275cb6dd7 | ||
|
|
e1d2305ddd | ||
|
|
b19d56ad02 | ||
|
|
0887c46f14 | ||
|
|
9d322c3a94 | ||
|
|
1776217f1c | ||
|
|
79f011fe17 | ||
|
|
f5474840b3 | ||
|
|
be13eb1d0d | ||
|
|
02fe7e31d0 | ||
|
|
5525bc2257 | ||
|
|
cb82578b27 | ||
|
|
24f2c49e0b | ||
|
|
9cde488577 | ||
|
|
1ce3343578 | ||
|
|
40fe87920b | ||
|
|
1cf286b057 | ||
|
|
e8f1b411ba | ||
|
|
742456dd87 | ||
|
|
657ad506a4 | ||
|
|
6c1798097c | ||
|
|
8454d1d3e5 | ||
|
|
9e25686c7c | ||
|
|
760bab7d29 | ||
|
|
3976e49e35 | ||
|
|
7092e24098 | ||
|
|
eeae01e661 | ||
|
|
ccd56f2dda | ||
|
|
9402b29684 | ||
|
|
e8e1467f27 | ||
|
|
0fb70607d9 | ||
|
|
a60826529b | ||
|
|
99f8fa8253 | ||
|
|
0222eef6b5 | ||
|
|
c350fc466e | ||
|
|
41cbabcf88 | ||
|
|
2101731f0b | ||
|
|
bcf2f7a5dc | ||
|
|
9f704fb8ff | ||
|
|
7c158af3cc | ||
|
|
66c6463f44 | ||
|
|
449d1191ff | ||
|
|
f4705ad4e1 | ||
|
|
143eb655b1 | ||
|
|
bbf009e15d | ||
|
|
ecf9052452 | ||
|
|
869cae0675 | ||
|
|
dd36bbce42 | ||
|
|
939ceb32ce | ||
|
|
e2fe04749b | ||
|
|
20a9780654 | ||
|
|
c77526e8c5 | ||
|
|
1434d7ddad | ||
|
|
b4d85b782e | ||
|
|
f75e8d1fd4 | ||
|
|
c1c21d826d | ||
|
|
51e6887bde | ||
|
|
bde5597467 | ||
|
|
de967a0160 | ||
|
|
9527b41b62 | ||
|
|
1f1ac1f246 | ||
|
|
ff14cf90f0 | ||
|
|
21483448b9 | ||
|
|
769b63d9ca | ||
|
|
dcf66749af | ||
|
|
500b8632df | ||
|
|
730da857e1 | ||
|
|
c96902d622 | ||
|
|
0076236280 | ||
|
|
ae53ca6f4f | ||
|
|
9a36d9d663 | ||
|
|
f55c9b7273 | ||
|
|
6ff31b90c7 | ||
|
|
a0996bd0cf | ||
|
|
f405ac3293 | ||
|
|
2d999138ba | ||
|
|
1d533e49e4 | ||
|
|
dee479ce3c | ||
|
|
715f37eb0b | ||
|
|
56543b8db4 | ||
|
|
7f3950018e | ||
|
|
d26e0976db | ||
|
|
95a51ce4f3 | ||
|
|
0925253a9d | ||
|
|
98bf5a102e | ||
|
|
ff0c12c551 | ||
|
|
243da124a8 | ||
|
|
deb4585d4b | ||
|
|
afdee2cd48 | ||
|
|
f4dd1bed63 | ||
|
|
d96f951113 | ||
|
|
f5d013187b | ||
|
|
50ab864698 | ||
|
|
b1c832d27f | ||
|
|
5ba6c5ee00 | ||
|
|
ac6618a943 | ||
|
|
decdd1b25d | ||
|
|
97c8cefb7d | ||
|
|
bfb69ccccd | ||
|
|
958ec41f4e | ||
|
|
dc5bede084 | ||
|
|
755526834e | ||
|
|
221f78aa9a | ||
|
|
4e640bae88 | ||
|
|
014d1f8cd2 | ||
|
|
6acfc77d08 | ||
|
|
033462d25f | ||
|
|
2512253020 | ||
|
|
c331a83b74 | ||
|
|
56829ff921 | ||
|
|
6037ac4052 | ||
|
|
1f0ef78219 | ||
|
|
1c469300f5 | ||
|
|
7ba611bdb7 | ||
|
|
aba61120e4 | ||
|
|
e885bf2f2a | ||
|
|
ddfa0a5a0f | ||
|
|
855987d5fa | ||
|
|
bc95dc2959 | ||
|
|
3c49ed570a | ||
|
|
2f0fdd1d36 | ||
|
|
2d7bab8adb | ||
|
|
ab1c506226 | ||
|
|
99addf2cfa | ||
|
|
64af029c86 | ||
|
|
4793897511 | ||
|
|
786468f437 | ||
|
|
1f517c3faf | ||
|
|
4c15e6675a | ||
|
|
5358863fc6 | ||
|
|
0e15d6c9d2 | ||
|
|
f6e4753b34 | ||
|
|
e8a3745b5e | ||
|
|
091ce90359 | ||
|
|
b5fa188805 | ||
|
|
8f8edc9565 | ||
|
|
3c54f5f565 | ||
|
|
13cf1feefb | ||
|
|
6772568a58 | ||
|
|
8926dd1173 | ||
|
|
dcfad7a427 | ||
|
|
db4795744e | ||
|
|
f17dfb9a31 | ||
|
|
7b84ddd358 | ||
|
|
283a9d0507 | ||
|
|
c01571d11d | ||
|
|
757281ce34 | ||
|
|
b57a2c50a9 | ||
|
|
36385a74ba | ||
|
|
c048dcf02a | ||
|
|
9ede8ffe4d | ||
|
|
d16bed4ad7 | ||
|
|
68dae2d1fe | ||
|
|
d05c67ffaa | ||
|
|
5ca3358237 | ||
|
|
ffc81621d7 | ||
|
|
a489d21add | ||
|
|
bc004b3b27 | ||
|
|
52889e3504 | ||
|
|
6764f86980 | ||
|
|
02af138069 | ||
|
|
427c2d5d2a | ||
|
|
87d1047fa9 | ||
|
|
34b788cb88 | ||
|
|
291dc51849 | ||
|
|
1b7d604858 | ||
|
|
b51397fe19 | ||
|
|
68e1556378 | ||
|
|
23150fcfc3 | ||
|
|
1f14bf4bda | ||
|
|
b4677c4546 | ||
|
|
9f3bc1ead8 | ||
|
|
607c2b6c4a | ||
|
|
3820710c56 | ||
|
|
cce1fadc33 | ||
|
|
77971f9c96 | ||
|
|
624594bb5c | ||
|
|
eed7bb2e1a | ||
|
|
cc14963bc8 | ||
|
|
7218e71884 | ||
|
|
faf4557783 | ||
|
|
728cf15c45 | ||
|
|
48f6624737 | ||
|
|
5286ad1cd6 | ||
|
|
ee12e691be | ||
|
|
c2f98043df | ||
|
|
05b408d107 | ||
|
|
0d4b6f6344 | ||
|
|
07dc725857 | ||
|
|
d16194b794 | ||
|
|
d0f73344bf | ||
|
|
08dd4ed072 | ||
|
|
501a1c2f4d | ||
|
|
a0f157c8b6 | ||
|
|
2d424fc9a6 | ||
|
|
a40866e27f | ||
|
|
60ddc45b9b | ||
|
|
03b8bd5e22 | ||
|
|
de29528165 | ||
|
|
6b45ed7e78 | ||
|
|
59c7c49efa | ||
|
|
33d59c8b7d | ||
|
|
5f7ccd4e7c | ||
|
|
960f27f6ef | ||
|
|
aa57d89bea | ||
|
|
c5b1ad480f | ||
|
|
feadd022e7 | ||
|
|
4c0a5e8c30 | ||
|
|
b0d4c87d8e | ||
|
|
1a0f0a11b1 | ||
|
|
d21c060903 | ||
|
|
0230a4af01 | ||
|
|
2ed41ab164 | ||
|
|
c89941d435 | ||
|
|
55856be1de | ||
|
|
a6e29c5615 | ||
|
|
ecf9f26547 | ||
|
|
4dabfcba23 | ||
|
|
53c63ba68f | ||
|
|
2d4ed85e94 | ||
|
|
470c5076a3 | ||
|
|
762b51a5b4 | ||
|
|
13e925e29f | ||
|
|
e4e37d0cb4 | ||
|
|
3660cd26ae | ||
|
|
a31c995508 | ||
|
|
d0501ee0a6 | ||
|
|
3ddba81e24 | ||
|
|
c9d5ec26a2 | ||
|
|
441b91381f | ||
|
|
0db264dcac | ||
|
|
783f6283ca |
No files matched your search
@@ -18,3 +18,8 @@ VITE_APP_DOCALERT_ENABLE=true
|
||||
|
||||
# 百度统计
|
||||
VITE_APP_BAIDU_CODE = a1ff8825baa73c3a78eb96aa40325abc
|
||||
|
||||
# 默认账户密码
|
||||
VITE_APP_DEFAULT_LOGIN_TENANT = 芋道源码
|
||||
VITE_APP_DEFAULT_LOGIN_USERNAME = admin
|
||||
VITE_APP_DEFAULT_LOGIN_PASSWORD = admin123
|
||||
@@ -1,20 +1,16 @@
|
||||
# 开发环境:本地只启动前端项目,依赖开发环境(后端、APP)
|
||||
NODE_ENV=development
|
||||
NODE_ENV=production
|
||||
|
||||
VITE_DEV=true
|
||||
|
||||
# 请求路径
|
||||
VITE_BASE_URL='http://api-dashboard.yudao.iocoder.cn'
|
||||
# VITE_BASE_URL='http://dofast.demo.huizhizao.vip:20001'
|
||||
|
||||
# 文件上传类型:server - 后端上传, client - 前端直连上传,仅支持S3服务
|
||||
VITE_UPLOAD_TYPE=server
|
||||
# 上传路径
|
||||
VITE_UPLOAD_URL='http://api-dashboard.yudao.iocoder.cn/admin-api/infra/file/upload'
|
||||
|
||||
# 接口前缀
|
||||
VITE_API_BASEPATH=/dev-api
|
||||
|
||||
# 接口地址
|
||||
VITE_API_URL=/admin-api
|
||||
|
||||
@@ -37,4 +33,4 @@ VITE_OUT_DIR=dist
|
||||
VITE_MALL_H5_DOMAIN='http://mall.yudao.iocoder.cn'
|
||||
|
||||
# 验证码的开关
|
||||
VITE_APP_CAPTCHA_ENABLE=false
|
||||
VITE_APP_CAPTCHA_ENABLE=true
|
||||
@@ -11,9 +11,6 @@ VITE_UPLOAD_TYPE=server
|
||||
# 上传路径
|
||||
VITE_UPLOAD_URL='http://localhost:48080/admin-api/infra/file/upload'
|
||||
|
||||
# 接口前缀
|
||||
VITE_API_BASEPATH=/dev-api
|
||||
|
||||
# 接口地址
|
||||
VITE_API_URL=/admin-api
|
||||
|
||||
|
||||
@@ -11,9 +11,6 @@ VITE_UPLOAD_TYPE=server
|
||||
# 上传路径
|
||||
VITE_UPLOAD_URL='http://localhost:48080/admin-api/infra/file/upload'
|
||||
|
||||
# 接口前缀
|
||||
VITE_API_BASEPATH=
|
||||
|
||||
# 接口地址
|
||||
VITE_API_URL=/admin-api
|
||||
|
||||
|
||||
@@ -11,9 +11,6 @@ VITE_UPLOAD_TYPE=server
|
||||
# 上传路径
|
||||
VITE_UPLOAD_URL='http://api-dashboard.yudao.iocoder.cn/admin-api/infra/file/upload'
|
||||
|
||||
# 接口前缀
|
||||
VITE_API_BASEPATH=
|
||||
|
||||
# 接口地址
|
||||
VITE_API_URL=/admin-api
|
||||
|
||||
|
||||
@@ -11,9 +11,6 @@ VITE_UPLOAD_TYPE=server
|
||||
# 上传路径
|
||||
VITE_UPLOAD_URL='http://localhost:48080/admin-api/infra/file/upload'
|
||||
|
||||
# 接口前缀
|
||||
VITE_API_BASEPATH=
|
||||
|
||||
# 接口地址
|
||||
VITE_API_URL=/admin-api
|
||||
|
||||
|
||||
@@ -2,9 +2,7 @@ node_modules
|
||||
.DS_Store
|
||||
dist
|
||||
dist-ssr
|
||||
*.local
|
||||
/dist*
|
||||
*-lock.*
|
||||
pnpm-debug
|
||||
auto-*.d.ts
|
||||
.idea
|
||||
|
||||
|
After Width: | Height: | Size: 21 KiB |
|
After Width: | Height: | Size: 348 KiB |
|
After Width: | Height: | Size: 16 KiB |
|
After Width: | Height: | Size: 17 KiB |
|
After Width: | Height: | Size: 13 KiB |
@@ -3,7 +3,6 @@
|
||||
"christian-kohler.path-intellisense",
|
||||
"vscode-icons-team.vscode-icons",
|
||||
"davidanson.vscode-markdownlint",
|
||||
"stylelint.vscode-stylelint",
|
||||
"dbaeumer.vscode-eslint",
|
||||
"esbenp.prettier-vscode",
|
||||
"mrmlnc.vscode-less",
|
||||
|
||||
@@ -54,17 +54,16 @@
|
||||
|
||||
推荐 VS Code 开发,配合插件如下:
|
||||
|
||||
| 插件名 | 功能 |
|
||||
|-------------------------------|--------------------------|
|
||||
| TypeScript Vue Plugin (Volar) | 用于 TypeScript 的 Vue 插件 |
|
||||
| Vue Language Features (Volar) | Vue3.0 语法支持 |
|
||||
| unocss | unocss for vscode |
|
||||
| Iconify IntelliSense | Iconify 预览和搜索 |
|
||||
| i18n Ally | 国际化智能提示 |
|
||||
| Stylelint | Css 格式化 |
|
||||
| Prettier | 代码格式化 |
|
||||
| ESLint | 脚本代码检查 |
|
||||
| DotENV | env 文件高亮 |
|
||||
| 插件名 | 功能 |
|
||||
|-------------------------------|---------------------|
|
||||
| Vue - Official | Vue 与 TypeScript 支持 |
|
||||
| unocss | unocss for vscode |
|
||||
| Iconify IntelliSense | Iconify 预览和搜索 |
|
||||
| i18n Ally | 国际化智能提示 |
|
||||
| Stylelint | Css 格式化 |
|
||||
| Prettier | 代码格式化 |
|
||||
| ESLint | 脚本代码检查 |
|
||||
| DotENV | env 文件高亮 |
|
||||
|
||||
## 🔥 后端架构
|
||||
|
||||
@@ -117,6 +116,8 @@
|
||||
| 🚀 | 应用管理 | 管理 SSO 单点登录的应用,支持多种 OAuth2 授权方式 |
|
||||
| 🚀 | 地区管理 | 展示省份、城市、区镇等城市信息,支持 IP 对应城市 |
|
||||
|
||||

|
||||
|
||||
### 工作流程
|
||||
|
||||
| | 功能 | 描述 |
|
||||
@@ -129,6 +130,8 @@
|
||||
| 🚀 | 已办任务 | 查看自己【已】审批的工作任务,未来会支持回退操作 |
|
||||
| 🚀 | OA 请假 | 作为业务自定义接入工作流的使用示例,只需创建请求对应的工作流程,即可进行审批 |
|
||||
|
||||

|
||||
|
||||
### 支付系统
|
||||
|
||||
| | 功能 | 描述 |
|
||||
@@ -142,27 +145,27 @@ ps:核心功能已经实现,正在对接微信小程序中...
|
||||
|
||||
### 基础设施
|
||||
|
||||
| | 功能 | 描述 |
|
||||
|-----|----------|----------------------------------------------|
|
||||
| 🚀 | 代码生成 | 前后端代码的生成(Java、Vue、SQL、单元测试),支持 CRUD 下载 |
|
||||
| 🚀 | 系统接口 | 基于 Swagger 自动生成相关的 RESTful API 接口文档 |
|
||||
| 🚀 | 数据库文档 | 基于 Screw 自动生成数据库文档,支持导出 Word、HTML、MD 格式 |
|
||||
| | 表单构建 | 拖动表单元素生成相应的 HTML 代码,支持导出 JSON、Vue 文件 |
|
||||
| 🚀 | 配置管理 | 对系统动态配置常用参数,支持 SpringBoot 加载 |
|
||||
| ⭐️ | 定时任务 | 在线(添加、修改、删除)任务调度包含执行结果日志 |
|
||||
| 🚀 | 文件服务 | 支持将文件存储到 S3(MinIO、阿里云、腾讯云、七牛云)、本地、FTP、数据库等 |
|
||||
| 🚀 | API 日志 | 包括 RESTful API 访问日志、异常日志两部分,方便排查 API 相关的问题 |
|
||||
| | MySQL 监控 | 监视当前系统数据库连接池状态,可进行分析SQL找出系统性能瓶颈 |
|
||||
| | Redis 监控 | 监控 Redis 数据库的使用情况,使用的 Redis Key 管理 |
|
||||
| 🚀 | 消息队列 | 基于 Redis 实现消息队列,Stream 提供集群消费,Pub/Sub 提供广播消费 |
|
||||
| 🚀 | Java 监控 | 基于 Spring Boot Admin 实现 Java 应用的监控 |
|
||||
| 🚀 | 链路追踪 | 接入 SkyWalking 组件,实现链路追踪 |
|
||||
| 🚀 | 日志中心 | 接入 SkyWalking 组件,实现日志中心 |
|
||||
| 🚀 | 分布式锁 | 基于 Redis 实现分布式锁,满足并发场景 |
|
||||
| 🚀 | 幂等组件 | 基于 Redis 实现幂等组件,解决重复请求问题 |
|
||||
| 🚀 | 服务保障 | 基于 Resilience4j 实现服务的稳定性,包括限流、熔断等功能 |
|
||||
| 🚀 | 日志服务 | 轻量级日志中心,查看远程服务器的日志 |
|
||||
| 🚀 | 单元测试 | 基于 JUnit + Mockito 实现单元测试,保证功能的正确性、代码的质量等 |
|
||||
| | 功能 | 描述 |
|
||||
|----|----------|----------------------------------------------|
|
||||
| 🚀 | 代码生成 | 前后端代码的生成(Java、Vue、SQL、单元测试),支持 CRUD 下载 |
|
||||
| 🚀 | 系统接口 | 基于 Swagger 自动生成相关的 RESTful API 接口文档 |
|
||||
| 🚀 | 数据库文档 | 基于 Screw 自动生成数据库文档,支持导出 Word、HTML、MD 格式 |
|
||||
| | 表单构建 | 拖动表单元素生成相应的 HTML 代码,支持导出 JSON、Vue 文件 |
|
||||
| 🚀 | 配置管理 | 对系统动态配置常用参数,支持 SpringBoot 加载 |
|
||||
| ⭐️ | 定时任务 | 在线(添加、修改、删除)任务调度包含执行结果日志 |
|
||||
| 🚀 | 文件服务 | 支持将文件存储到 S3(MinIO、阿里云、腾讯云、七牛云)、本地、FTP、数据库等 |
|
||||
| 🚀 | API 日志 | 包括 RESTful API 访问日志、异常日志两部分,方便排查 API 相关的问题 |
|
||||
| | MySQL 监控 | 监视当前系统数据库连接池状态,可进行分析SQL找出系统性能瓶颈 |
|
||||
| | Redis 监控 | 监控 Redis 数据库的使用情况,使用的 Redis Key 管理 |
|
||||
| 🚀 | 消息队列 | 基于 Redis 实现消息队列,Stream 提供集群消费,Pub/Sub 提供广播消费 |
|
||||
| 🚀 | Java 监控 | 基于 Spring Boot Admin 实现 Java 应用的监控 |
|
||||
| 🚀 | 链路追踪 | 接入 SkyWalking 组件,实现链路追踪 |
|
||||
| 🚀 | 日志中心 | 接入 SkyWalking 组件,实现日志中心 |
|
||||
| 🚀 | 服务保障 | 基于 Redis 实现分布式锁、幂等、限流功能,满足高并发场景 |
|
||||
| 🚀 | 日志服务 | 轻量级日志中心,查看远程服务器的日志 |
|
||||
| 🚀 | 单元测试 | 基于 JUnit + Mockito 实现单元测试,保证功能的正确性、代码的质量等 |
|
||||
|
||||

|
||||
|
||||
### 数据报表
|
||||
|
||||
@@ -188,26 +191,24 @@ ps:核心功能已经实现,正在对接微信小程序中...
|
||||
|
||||
### 商城系统
|
||||
|
||||
演示地址:<https://doc.iocoder.cn/mall-preview/>
|
||||
|
||||

|
||||
|
||||

|
||||
|
||||
_前端基于 crmeb uniapp 经过授权重构,优化代码实现,接入芋道快速开发平台_
|
||||
|
||||
演示地址:<https://doc.iocoder.cn/mall-preview/>
|
||||
|
||||
### ERP 系统
|
||||
|
||||

|
||||
|
||||
演示地址:<https://doc.iocoder.cn/erp-preview/>
|
||||
|
||||

|
||||
|
||||
### CRM 系统
|
||||
|
||||

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

|
||||
|
||||
## 🐷 演示图
|
||||
|
||||
### 系统功能
|
||||
|
||||
@@ -27,6 +27,12 @@ const include = [
|
||||
'echarts-wordcloud',
|
||||
'@wangeditor/editor',
|
||||
'@wangeditor/editor-for-vue',
|
||||
'@microsoft/fetch-event-source',
|
||||
'markdown-it',
|
||||
'markmap-view',
|
||||
'markmap-lib',
|
||||
'markmap-toolbar',
|
||||
'highlight.js',
|
||||
'element-plus',
|
||||
'element-plus/es',
|
||||
'element-plus/es/locale/lang/zh-cn',
|
||||
@@ -104,7 +110,11 @@ const include = [
|
||||
'element-plus/es/components/collapse/style/css',
|
||||
'element-plus/es/components/collapse-item/style/css',
|
||||
'element-plus/es/components/button-group/style/css',
|
||||
'element-plus/es/components/text/style/css'
|
||||
'element-plus/es/components/text/style/css',
|
||||
'element-plus/es/components/segmented/style/css',
|
||||
'@element-plus/icons-vue',
|
||||
'element-plus/es/components/footer/style/css',
|
||||
'element-plus/es/components/empty/style/css'
|
||||
]
|
||||
|
||||
const exclude = ['@iconify/json']
|
||||
|
||||
@@ -1,22 +1,22 @@
|
||||
{
|
||||
"name": "yudao-ui-admin-vue3",
|
||||
"version": "2.0.1-snapshot",
|
||||
"version": "2.2.0-snapshot",
|
||||
"description": "基于vue3、vite4、element-plus、typesScript",
|
||||
"author": "xingyu",
|
||||
"private": false,
|
||||
"scripts": {
|
||||
"i": "pnpm install",
|
||||
"dev": "vite --mode local-dev",
|
||||
"dev": "vite --mode env.local",
|
||||
"dev-server": "vite --mode dev",
|
||||
"ts:check": "vue-tsc --noEmit",
|
||||
"build:local-dev": "node --max_old_space_size=8192 ./node_modules/vite/bin/vite.js build --mode local-dev",
|
||||
"build:dev": "node --max_old_space_size=8192 ./node_modules/vite/bin/vite.js build --mode local-dev",
|
||||
"build:local": "node --max_old_space_size=8192 ./node_modules/vite/bin/vite.js build",
|
||||
"build:dev": "node --max_old_space_size=8192 ./node_modules/vite/bin/vite.js build --mode dev",
|
||||
"build:test": "node --max_old_space_size=8192 ./node_modules/vite/bin/vite.js build --mode test",
|
||||
"build:stage": "node --max_old_space_size=8192 ./node_modules/vite/bin/vite.js build --mode stage",
|
||||
"build:prod": "node --max_old_space_size=8192 ./node_modules/vite/bin/vite.js build --mode prod",
|
||||
"serve:dev": "vite preview --mode dev",
|
||||
"serve:prod": "vite preview --mode prod",
|
||||
"preview": "pnpm build:local-dev && vite preview",
|
||||
"preview": "pnpm build:local && vite preview",
|
||||
"clean": "npx rimraf node_modules",
|
||||
"clean:cache": "npx rimraf node_modules/.cache",
|
||||
"lint:eslint": "eslint --fix --ext .js,.ts,.vue ./src",
|
||||
@@ -29,13 +29,14 @@
|
||||
"@form-create/designer": "^3.1.3",
|
||||
"@form-create/element-ui": "^3.1.24",
|
||||
"@iconify/iconify": "^3.1.1",
|
||||
"@microsoft/fetch-event-source": "^2.0.1",
|
||||
"@videojs-player/vue": "^1.0.0",
|
||||
"@vueuse/core": "^10.9.0",
|
||||
"@wangeditor/editor": "^5.1.23",
|
||||
"@wangeditor/editor-for-vue": "^5.1.10",
|
||||
"@zxcvbn-ts/core": "^3.0.4",
|
||||
"animate.css": "^4.1.1",
|
||||
"axios": "^1.6.7",
|
||||
"axios": "^1.6.8",
|
||||
"benz-amr-recorder": "^1.1.5",
|
||||
"bpmn-js-token-simulation": "^0.10.0",
|
||||
"camunda-bpmn-moddle": "^7.0.1",
|
||||
@@ -46,24 +47,29 @@
|
||||
"driver.js": "^1.3.1",
|
||||
"echarts": "^5.5.0",
|
||||
"echarts-wordcloud": "^2.1.0",
|
||||
"element-plus": "2.5.3",
|
||||
"element-plus": "2.7.0",
|
||||
"fast-xml-parser": "^4.3.2",
|
||||
"highlight.js": "^11.9.0",
|
||||
"jsencrypt": "^3.3.2",
|
||||
"lodash-es": "^4.17.21",
|
||||
"markdown-it": "^14.1.0",
|
||||
"markmap-common": "^0.16.0",
|
||||
"markmap-lib": "^0.16.1",
|
||||
"markmap-toolbar": "^0.17.0",
|
||||
"markmap-view": "^0.16.0",
|
||||
"min-dash": "^4.1.1",
|
||||
"mitt": "^3.0.1",
|
||||
"nprogress": "^0.2.0",
|
||||
"pinia": "^2.1.7",
|
||||
"pinia-plugin-persistedstate": "^3.2.0",
|
||||
"pinia-plugin-persistedstate": "^3.2.1",
|
||||
"qrcode": "^1.5.3",
|
||||
"qs": "^6.11.2",
|
||||
"qs": "^6.12.0",
|
||||
"steady-xml": "^0.1.0",
|
||||
"url": "^0.11.3",
|
||||
"video.js": "^7.21.5",
|
||||
"vue": "3.4.20",
|
||||
"vue": "3.4.21",
|
||||
"vue-dompurify-html": "^4.1.4",
|
||||
"vue-i18n": "9.9.1",
|
||||
"vue-i18n": "9.10.2",
|
||||
"vue-router": "^4.3.0",
|
||||
"vue-types": "^5.1.1",
|
||||
"vuedraggable": "^4.1.0",
|
||||
@@ -83,8 +89,8 @@
|
||||
"@types/qs": "^6.9.12",
|
||||
"@typescript-eslint/eslint-plugin": "^7.1.0",
|
||||
"@typescript-eslint/parser": "^7.1.0",
|
||||
"@unocss/transformer-variant-group": "^0.58.5",
|
||||
"@unocss/eslint-config": "^0.57.4",
|
||||
"@unocss/transformer-variant-group": "^0.58.5",
|
||||
"@vitejs/plugin-legacy": "^5.3.1",
|
||||
"@vitejs/plugin-vue": "^5.0.4",
|
||||
"@vitejs/plugin-vue-jsx": "^3.1.0",
|
||||
@@ -102,6 +108,7 @@
|
||||
"postcss-html": "^1.6.0",
|
||||
"postcss-scss": "^4.0.9",
|
||||
"prettier": "^3.2.5",
|
||||
"prettier-eslint": "^16.3.0",
|
||||
"rimraf": "^5.0.5",
|
||||
"rollup": "^4.12.0",
|
||||
"sass": "^1.69.5",
|
||||
@@ -136,7 +143,6 @@
|
||||
"url": "https://gitee.com/yudaocode/yudao-ui-admin-vue3/issues"
|
||||
},
|
||||
"homepage": "https://gitee.com/yudaocode/yudao-ui-admin-vue3",
|
||||
"packageManager": "pnpm@8.6.0",
|
||||
"engines": {
|
||||
"node": ">= 16.0.0",
|
||||
"pnpm": ">=8.6.0"
|
||||
|
||||
@@ -54,4 +54,8 @@ body {
|
||||
.#{$prefix-cls}-grey-mode {
|
||||
filter: grayscale(100%);
|
||||
}
|
||||
|
||||
.scrollbar__view {
|
||||
height: 99%!important;
|
||||
}
|
||||
</style>
|
||||
@@ -0,0 +1,65 @@
|
||||
import request from '@/config/axios'
|
||||
|
||||
// AI 聊天对话 VO
|
||||
export interface ChatConversationVO {
|
||||
id: number // ID 编号
|
||||
userId: number // 用户编号
|
||||
title: string // 对话标题
|
||||
pinned: boolean // 是否置顶
|
||||
roleId: number // 角色编号
|
||||
modelId: number // 模型编号
|
||||
model: string // 模型标志
|
||||
temperature: number // 温度参数
|
||||
maxTokens: number // 单条回复的最大 Token 数量
|
||||
maxContexts: number // 上下文的最大 Message 数量
|
||||
createTime?: Date // 创建时间
|
||||
// 额外字段
|
||||
systemMessage?: string // 角色设定
|
||||
modelName?: string // 模型名字
|
||||
roleAvatar?: string // 角色头像
|
||||
modelMaxTokens?: string // 模型的单条回复的最大 Token 数量
|
||||
modelMaxContexts?: string // 模型的上下文的最大 Message 数量
|
||||
}
|
||||
|
||||
// AI 聊天对话 API
|
||||
export const ChatConversationApi = {
|
||||
// 获得【我的】聊天对话
|
||||
getChatConversationMy: async (id: number) => {
|
||||
return await request.get({ url: `/ai/chat/conversation/get-my?id=${id}` })
|
||||
},
|
||||
|
||||
// 新增【我的】聊天对话
|
||||
createChatConversationMy: async (data?: ChatConversationVO) => {
|
||||
return await request.post({ url: `/ai/chat/conversation/create-my`, data })
|
||||
},
|
||||
|
||||
// 更新【我的】聊天对话
|
||||
updateChatConversationMy: async (data: ChatConversationVO) => {
|
||||
return await request.put({ url: `/ai/chat/conversation/update-my`, data })
|
||||
},
|
||||
|
||||
// 删除【我的】聊天对话
|
||||
deleteChatConversationMy: async (id: string) => {
|
||||
return await request.delete({ url: `/ai/chat/conversation/delete-my?id=${id}` })
|
||||
},
|
||||
|
||||
// 删除【我的】所有对话,置顶除外
|
||||
deleteChatConversationMyByUnpinned: async () => {
|
||||
return await request.delete({ url: `/ai/chat/conversation/delete-by-unpinned` })
|
||||
},
|
||||
|
||||
// 获得【我的】聊天对话列表
|
||||
getChatConversationMyList: async () => {
|
||||
return await request.get({ url: `/ai/chat/conversation/my-list` })
|
||||
},
|
||||
|
||||
// 获得对话分页
|
||||
getChatConversationPage: async (params: any) => {
|
||||
return await request.get({ url: `/ai/chat/conversation/page`, params })
|
||||
},
|
||||
|
||||
// 管理员删除消息
|
||||
deleteChatConversationByAdmin: async (id: number) => {
|
||||
return await request.delete({ url: `/ai/chat/conversation/delete-by-admin?id=${id}` })
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,83 @@
|
||||
import request from '@/config/axios'
|
||||
import { fetchEventSource } from '@microsoft/fetch-event-source'
|
||||
import { getAccessToken } from '@/utils/auth'
|
||||
import { config } from '@/config/axios/config'
|
||||
|
||||
// 聊天VO
|
||||
export interface ChatMessageVO {
|
||||
id: number // 编号
|
||||
conversationId: number // 对话编号
|
||||
type: string // 消息类型
|
||||
userId: string // 用户编号
|
||||
roleId: string // 角色编号
|
||||
model: number // 模型标志
|
||||
modelId: number // 模型编号
|
||||
content: string // 聊天内容
|
||||
tokens: number // 消耗 Token 数量
|
||||
createTime: Date // 创建时间
|
||||
roleAvatar: string // 角色头像
|
||||
userAvatar: string // 创建时间
|
||||
}
|
||||
|
||||
// AI chat 聊天
|
||||
export const ChatMessageApi = {
|
||||
// 消息列表
|
||||
getChatMessageListByConversationId: async (conversationId: number | null) => {
|
||||
return await request.get({
|
||||
url: `/ai/chat/message/list-by-conversation-id?conversationId=${conversationId}`
|
||||
})
|
||||
},
|
||||
|
||||
// 发送 Stream 消息
|
||||
// 为什么不用 axios 呢?因为它不支持 SSE 调用
|
||||
sendChatMessageStream: async (
|
||||
conversationId: number,
|
||||
content: string,
|
||||
ctrl,
|
||||
enableContext: boolean,
|
||||
onMessage,
|
||||
onError,
|
||||
onClose
|
||||
) => {
|
||||
const token = getAccessToken()
|
||||
return fetchEventSource(`${config.base_url}/ai/chat/message/send-stream`, {
|
||||
method: 'post',
|
||||
headers: {
|
||||
'Content-Type': 'application/json',
|
||||
Authorization: `Bearer ${token}`
|
||||
},
|
||||
openWhenHidden: true,
|
||||
body: JSON.stringify({
|
||||
conversationId,
|
||||
content,
|
||||
useContext: enableContext
|
||||
}),
|
||||
onmessage: onMessage,
|
||||
onerror: onError,
|
||||
onclose: onClose,
|
||||
signal: ctrl.signal
|
||||
})
|
||||
},
|
||||
|
||||
// 删除消息
|
||||
deleteChatMessage: async (id: string) => {
|
||||
return await request.delete({ url: `/ai/chat/message/delete?id=${id}` })
|
||||
},
|
||||
|
||||
// 删除指定对话的消息
|
||||
deleteByConversationId: async (conversationId: number) => {
|
||||
return await request.delete({
|
||||
url: `/ai/chat/message/delete-by-conversation-id?conversationId=${conversationId}`
|
||||
})
|
||||
},
|
||||
|
||||
// 获得消息分页
|
||||
getChatMessagePage: async (params: any) => {
|
||||
return await request.get({ url: '/ai/chat/message/page', params })
|
||||
},
|
||||
|
||||
// 管理员删除消息
|
||||
deleteChatMessageByAdmin: async (id: number) => {
|
||||
return await request.delete({ url: `/ai/chat/message/delete-by-admin?id=${id}` })
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,103 @@
|
||||
import request from '@/config/axios'
|
||||
|
||||
// AI 绘图 VO
|
||||
export interface ImageVO {
|
||||
id: number // 编号
|
||||
platform: string // 平台
|
||||
model: string // 模型
|
||||
prompt: string // 提示词
|
||||
width: number // 图片宽度
|
||||
height: number // 图片高度
|
||||
status: number // 状态
|
||||
publicStatus: boolean // 公开状态
|
||||
picUrl: string // 任务地址
|
||||
errorMessage: string // 错误信息
|
||||
options: any // 配置 Map<string, string>
|
||||
taskId: number // 任务编号
|
||||
buttons: ImageMidjourneyButtonsVO[] // mj 操作按钮
|
||||
createTime: Date // 创建时间
|
||||
finishTime: Date // 完成时间
|
||||
}
|
||||
|
||||
export interface ImageDrawReqVO {
|
||||
platform: string // 平台
|
||||
prompt: string // 提示词
|
||||
model: string // 模型
|
||||
style: string // 图像生成的风格
|
||||
width: string // 图片宽度
|
||||
height: string // 图片高度
|
||||
options: object // 绘制参数,Map<String, String>
|
||||
}
|
||||
|
||||
export interface ImageMidjourneyImagineReqVO {
|
||||
prompt: string // 提示词
|
||||
model: string // 模型 mj nijj
|
||||
base64Array: string[] // size不能为空
|
||||
width: string // 图片宽度
|
||||
height: string // 图片高度
|
||||
version: string // 版本
|
||||
}
|
||||
|
||||
export interface ImageMidjourneyActionVO {
|
||||
id: number // 图片编号
|
||||
customId: string // MJ::JOB::upsample::1::85a4b4c1-8835-46c5-a15c-aea34fad1862 动作标识
|
||||
}
|
||||
|
||||
export interface ImageMidjourneyButtonsVO {
|
||||
customId: string // MJ::JOB::upsample::1::85a4b4c1-8835-46c5-a15c-aea34fad1862 动作标识
|
||||
emoji: string // 图标 emoji
|
||||
label: string // Make Variations 文本
|
||||
style: number // 样式: 2(Primary)、3(Green)
|
||||
}
|
||||
|
||||
// AI 图片 API
|
||||
export const ImageApi = {
|
||||
// 获取【我的】绘图分页
|
||||
getImagePageMy: async (params: any) => {
|
||||
return await request.get({ url: `/ai/image/my-page`, params })
|
||||
},
|
||||
// 获取【我的】绘图记录
|
||||
getImageMy: async (id: number) => {
|
||||
return await request.get({ url: `/ai/image/get-my?id=${id}` })
|
||||
},
|
||||
// 获取【我的】绘图记录列表
|
||||
getImageListMyByIds: async (ids: number[]) => {
|
||||
return await request.get({ url: `/ai/image/my-list-by-ids`, params: { ids: ids.join(',') } })
|
||||
},
|
||||
// 生成图片
|
||||
drawImage: async (data: ImageDrawReqVO) => {
|
||||
return await request.post({ url: `/ai/image/draw`, data })
|
||||
},
|
||||
// 删除【我的】绘画记录
|
||||
deleteImageMy: async (id: number) => {
|
||||
return await request.delete({ url: `/ai/image/delete-my?id=${id}` })
|
||||
},
|
||||
|
||||
// ================ midjourney 专属 ================
|
||||
|
||||
// 【Midjourney】生成图片
|
||||
midjourneyImagine: async (data: ImageMidjourneyImagineReqVO) => {
|
||||
return await request.post({ url: `/ai/image/midjourney/imagine`, data })
|
||||
},
|
||||
// 【Midjourney】Action 操作(二次生成图片)
|
||||
midjourneyAction: async (data: ImageMidjourneyActionVO) => {
|
||||
return await request.post({ url: `/ai/image/midjourney/action`, data })
|
||||
},
|
||||
|
||||
// ================ 绘图管理 ================
|
||||
|
||||
// 查询绘画分页
|
||||
getImagePage: async (params: any) => {
|
||||
return await request.get({ url: `/ai/image/page`, params })
|
||||
},
|
||||
|
||||
// 更新绘画发布状态
|
||||
updateImage: async (data: any) => {
|
||||
return await request.put({ url: '/ai/image/update', data })
|
||||
},
|
||||
|
||||
// 删除绘画
|
||||
deleteImage: async (id: number) => {
|
||||
return await request.delete({ url: `/ai/image/delete?id=` + id })
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,38 @@
|
||||
import { getAccessToken } from '@/utils/auth'
|
||||
import { fetchEventSource } from '@microsoft/fetch-event-source'
|
||||
import { config } from '@/config/axios/config'
|
||||
|
||||
export interface AiMindMapGenerateReqVO {
|
||||
prompt: string
|
||||
}
|
||||
|
||||
export const AiMindMapApi = {
|
||||
generateMindMap: ({
|
||||
data,
|
||||
onClose,
|
||||
onMessage,
|
||||
onError,
|
||||
ctrl
|
||||
}: {
|
||||
data: AiMindMapGenerateReqVO
|
||||
onMessage?: (res: any) => void
|
||||
onError?: (...args: any[]) => void
|
||||
onClose?: (...args: any[]) => void
|
||||
ctrl: AbortController
|
||||
}) => {
|
||||
const token = getAccessToken()
|
||||
return fetchEventSource(`${config.base_url}/ai/mind-map/generate-stream`, {
|
||||
method: 'post',
|
||||
headers: {
|
||||
'Content-Type': 'application/json',
|
||||
Authorization: `Bearer ${token}`
|
||||
},
|
||||
openWhenHidden: true,
|
||||
body: JSON.stringify(data),
|
||||
onmessage: onMessage,
|
||||
onerror: onError,
|
||||
onclose: onClose,
|
||||
signal: ctrl.signal
|
||||
})
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,44 @@
|
||||
import request from '@/config/axios'
|
||||
|
||||
// AI API 密钥 VO
|
||||
export interface ApiKeyVO {
|
||||
id: number // 编号
|
||||
name: string // 名称
|
||||
apiKey: string // 密钥
|
||||
platform: string // 平台
|
||||
url: string // 自定义 API 地址
|
||||
status: number // 状态
|
||||
}
|
||||
|
||||
// AI API 密钥 API
|
||||
export const ApiKeyApi = {
|
||||
// 查询 API 密钥分页
|
||||
getApiKeyPage: async (params: any) => {
|
||||
return await request.get({ url: `/ai/api-key/page`, params })
|
||||
},
|
||||
|
||||
// 获得 API 密钥列表
|
||||
getApiKeySimpleList: async () => {
|
||||
return await request.get({ url: `/ai/api-key/simple-list` })
|
||||
},
|
||||
|
||||
// 查询 API 密钥详情
|
||||
getApiKey: async (id: number) => {
|
||||
return await request.get({ url: `/ai/api-key/get?id=` + id })
|
||||
},
|
||||
|
||||
// 新增 API 密钥
|
||||
createApiKey: async (data: ApiKeyVO) => {
|
||||
return await request.post({ url: `/ai/api-key/create`, data })
|
||||
},
|
||||
|
||||
// 修改 API 密钥
|
||||
updateApiKey: async (data: ApiKeyVO) => {
|
||||
return await request.put({ url: `/ai/api-key/update`, data })
|
||||
},
|
||||
|
||||
// 删除 API 密钥
|
||||
deleteApiKey: async (id: number) => {
|
||||
return await request.delete({ url: `/ai/api-key/delete?id=` + id })
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,53 @@
|
||||
import request from '@/config/axios'
|
||||
|
||||
// AI 聊天模型 VO
|
||||
export interface ChatModelVO {
|
||||
id: number // 编号
|
||||
keyId: number // API 秘钥编号
|
||||
name: string // 模型名字
|
||||
model: string // 模型标识
|
||||
platform: string // 模型平台
|
||||
sort: number // 排序
|
||||
status: number // 状态
|
||||
temperature: number // 温度参数
|
||||
maxTokens: number // 单条回复的最大 Token 数量
|
||||
maxContexts: number // 上下文的最大 Message 数量
|
||||
}
|
||||
|
||||
// AI 聊天模型 API
|
||||
export const ChatModelApi = {
|
||||
// 查询聊天模型分页
|
||||
getChatModelPage: async (params: any) => {
|
||||
return await request.get({ url: `/ai/chat-model/page`, params })
|
||||
},
|
||||
|
||||
// 获得聊天模型列表
|
||||
getChatModelSimpleList: async (status?: number) => {
|
||||
return await request.get({
|
||||
url: `/ai/chat-model/simple-list`,
|
||||
params: {
|
||||
status
|
||||
}
|
||||
})
|
||||
},
|
||||
|
||||
// 查询聊天模型详情
|
||||
getChatModel: async (id: number) => {
|
||||
return await request.get({ url: `/ai/chat-model/get?id=` + id })
|
||||
},
|
||||
|
||||
// 新增聊天模型
|
||||
createChatModel: async (data: ChatModelVO) => {
|
||||
return await request.post({ url: `/ai/chat-model/create`, data })
|
||||
},
|
||||
|
||||
// 修改聊天模型
|
||||
updateChatModel: async (data: ChatModelVO) => {
|
||||
return await request.put({ url: `/ai/chat-model/update`, data })
|
||||
},
|
||||
|
||||
// 删除聊天模型
|
||||
deleteChatModel: async (id: number) => {
|
||||
return await request.delete({ url: `/ai/chat-model/delete?id=` + id })
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,80 @@
|
||||
import request from '@/config/axios'
|
||||
|
||||
// AI 聊天角色 VO
|
||||
export interface ChatRoleVO {
|
||||
id: number // 角色编号
|
||||
modelId: number // 模型编号
|
||||
name: string // 角色名称
|
||||
avatar: string // 角色头像
|
||||
category: string // 角色类别
|
||||
sort: number // 角色排序
|
||||
description: string // 角色描述
|
||||
systemMessage: string // 角色设定
|
||||
welcomeMessage: string // 角色设定
|
||||
publicStatus: boolean // 是否公开
|
||||
status: number // 状态
|
||||
}
|
||||
|
||||
// AI 聊天角色 分页请求 vo
|
||||
export interface ChatRolePageReqVO {
|
||||
name?: string // 角色名称
|
||||
category?: string // 角色类别
|
||||
publicStatus: boolean // 是否公开
|
||||
pageNo: number // 是否公开
|
||||
pageSize: number // 是否公开
|
||||
}
|
||||
|
||||
// AI 聊天角色 API
|
||||
export const ChatRoleApi = {
|
||||
// 查询聊天角色分页
|
||||
getChatRolePage: async (params: any) => {
|
||||
return await request.get({ url: `/ai/chat-role/page`, params })
|
||||
},
|
||||
|
||||
// 查询聊天角色详情
|
||||
getChatRole: async (id: number) => {
|
||||
return await request.get({ url: `/ai/chat-role/get?id=` + id })
|
||||
},
|
||||
|
||||
// 新增聊天角色
|
||||
createChatRole: async (data: ChatRoleVO) => {
|
||||
return await request.post({ url: `/ai/chat-role/create`, data })
|
||||
},
|
||||
|
||||
// 修改聊天角色
|
||||
updateChatRole: async (data: ChatRoleVO) => {
|
||||
return await request.put({ url: `/ai/chat-role/update`, data })
|
||||
},
|
||||
|
||||
// 删除聊天角色
|
||||
deleteChatRole: async (id: number) => {
|
||||
return await request.delete({ url: `/ai/chat-role/delete?id=` + id })
|
||||
},
|
||||
|
||||
// ======= chat 聊天
|
||||
|
||||
// 获取 my role
|
||||
getMyPage: async (params: ChatRolePageReqVO) => {
|
||||
return await request.get({ url: `/ai/chat-role/my-page`, params})
|
||||
},
|
||||
|
||||
// 获取角色分类
|
||||
getCategoryList: async () => {
|
||||
return await request.get({ url: `/ai/chat-role/category-list`})
|
||||
},
|
||||
|
||||
// 创建角色
|
||||
createMy: async (data: ChatRoleVO) => {
|
||||
return await request.post({ url: `/ai/chat-role/create-my`, data})
|
||||
},
|
||||
|
||||
// 更新角色
|
||||
updateMy: async (data: ChatRoleVO) => {
|
||||
return await request.put({ url: `/ai/chat-role/update-my`, data})
|
||||
},
|
||||
|
||||
// 删除角色 my
|
||||
deleteMy: async (id: number) => {
|
||||
return await request.delete({ url: `/ai/chat-role/delete-my?id=` + id })
|
||||
},
|
||||
}
|
||||
@@ -0,0 +1,41 @@
|
||||
import request from '@/config/axios'
|
||||
|
||||
// AI 音乐 VO
|
||||
export interface MusicVO {
|
||||
id: number // 编号
|
||||
userId: number // 用户编号
|
||||
title: string // 音乐名称
|
||||
lyric: string // 歌词
|
||||
imageUrl: string // 图片地址
|
||||
audioUrl: string // 音频地址
|
||||
videoUrl: string // 视频地址
|
||||
status: number // 音乐状态
|
||||
gptDescriptionPrompt: string // 描述词
|
||||
prompt: string // 提示词
|
||||
platform: string // 模型平台
|
||||
model: string // 模型
|
||||
generateMode: number // 生成模式
|
||||
tags: string // 音乐风格标签
|
||||
duration: number // 音乐时长
|
||||
publicStatus: boolean // 是否发布
|
||||
taskId: string // 任务id
|
||||
errorMessage: string // 错误信息
|
||||
}
|
||||
|
||||
// AI 音乐 API
|
||||
export const MusicApi = {
|
||||
// 查询音乐分页
|
||||
getMusicPage: async (params: any) => {
|
||||
return await request.get({ url: `/ai/music/page`, params })
|
||||
},
|
||||
|
||||
// 更新音乐
|
||||
updateMusic: async (data: any) => {
|
||||
return await request.put({ url: '/ai/music/update', data })
|
||||
},
|
||||
|
||||
// 删除音乐
|
||||
deleteMusic: async (id: number) => {
|
||||
return await request.delete({ url: `/ai/music/delete?id=` + id })
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,85 @@
|
||||
import { fetchEventSource } from '@microsoft/fetch-event-source'
|
||||
|
||||
import { getAccessToken } from '@/utils/auth'
|
||||
import { config } from '@/config/axios/config'
|
||||
import { AiWriteTypeEnum } from '@/views/ai/utils/constants'
|
||||
import request from '@/config/axios'
|
||||
|
||||
export interface WriteVO {
|
||||
type: AiWriteTypeEnum.WRITING | AiWriteTypeEnum.REPLY // 1:撰写 2:回复
|
||||
prompt: string // 写作内容提示 1。撰写 2回复
|
||||
originalContent: string // 原文
|
||||
length: number // 长度
|
||||
format: number // 格式
|
||||
tone: number // 语气
|
||||
language: number // 语言
|
||||
userId?: number // 用户编号
|
||||
platform?: string // 平台
|
||||
model?: string // 模型
|
||||
generatedContent?: string // 生成的内容
|
||||
errorMessage?: string // 错误信息
|
||||
createTime?: Date // 创建时间
|
||||
}
|
||||
|
||||
export interface AiWritePageReqVO extends PageParam {
|
||||
userId?: number // 用户编号
|
||||
type?: AiWriteTypeEnum // 写作类型
|
||||
platform?: string // 平台
|
||||
createTime?: [string, string] // 创建时间
|
||||
}
|
||||
|
||||
export interface AiWriteRespVo {
|
||||
id: number
|
||||
userId: number
|
||||
type: number
|
||||
platform: string
|
||||
model: string
|
||||
prompt: string
|
||||
generatedContent: string
|
||||
originalContent: string
|
||||
length: number
|
||||
format: number
|
||||
tone: number
|
||||
language: number
|
||||
errorMessage: string
|
||||
createTime: string
|
||||
}
|
||||
|
||||
export const WriteApi = {
|
||||
writeStream: ({
|
||||
data,
|
||||
onClose,
|
||||
onMessage,
|
||||
onError,
|
||||
ctrl
|
||||
}: {
|
||||
data: WriteVO
|
||||
onMessage?: (res: any) => void
|
||||
onError?: (...args: any[]) => void
|
||||
onClose?: (...args: any[]) => void
|
||||
ctrl: AbortController
|
||||
}) => {
|
||||
const token = getAccessToken()
|
||||
return fetchEventSource(`${config.base_url}/ai/write/generate-stream`, {
|
||||
method: 'post',
|
||||
headers: {
|
||||
'Content-Type': 'application/json',
|
||||
Authorization: `Bearer ${token}`
|
||||
},
|
||||
openWhenHidden: true,
|
||||
body: JSON.stringify(data),
|
||||
onmessage: onMessage,
|
||||
onerror: onError,
|
||||
onclose: onClose,
|
||||
signal: ctrl.signal
|
||||
})
|
||||
},
|
||||
// 获取写作列表
|
||||
getWritePage: (params: AiWritePageReqVO) => {
|
||||
return request.get<PageResult<AiWriteRespVo[]>>({ url: `/ai/write/page`, params })
|
||||
},
|
||||
// 删除写作
|
||||
deleteWrite(id: number) {
|
||||
return request.delete({ url: `/ai/write/delete`, params: { id } })
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,43 @@
|
||||
import request from '@/config/axios'
|
||||
|
||||
// BPM 流程分类 VO
|
||||
export interface CategoryVO {
|
||||
id: number // 分类编号
|
||||
name: string // 分类名
|
||||
code: string // 分类标志
|
||||
status: number // 分类状态
|
||||
sort: number // 分类排序
|
||||
}
|
||||
|
||||
// BPM 流程分类 API
|
||||
export const CategoryApi = {
|
||||
// 查询流程分类分页
|
||||
getCategoryPage: async (params: any) => {
|
||||
return await request.get({ url: `/bpm/category/page`, params })
|
||||
},
|
||||
|
||||
// 查询流程分类列表
|
||||
getCategorySimpleList: async () => {
|
||||
return await request.get({ url: `/bpm/category/simple-list` })
|
||||
},
|
||||
|
||||
// 查询流程分类详情
|
||||
getCategory: async (id: number) => {
|
||||
return await request.get({ url: `/bpm/category/get?id=` + id })
|
||||
},
|
||||
|
||||
// 新增流程分类
|
||||
createCategory: async (data: CategoryVO) => {
|
||||
return await request.post({ url: `/bpm/category/create`, data })
|
||||
},
|
||||
|
||||
// 修改流程分类
|
||||
updateCategory: async (data: CategoryVO) => {
|
||||
return await request.put({ url: `/bpm/category/update`, data })
|
||||
},
|
||||
|
||||
// 删除流程分类
|
||||
deleteCategory: async (id: number) => {
|
||||
return await request.delete({ url: `/bpm/category/delete?id=` + id })
|
||||
}
|
||||
}
|
||||
@@ -1,8 +1,9 @@
|
||||
import request from '@/config/axios'
|
||||
|
||||
export const getProcessDefinitionBpmnXML = async (id: number) => {
|
||||
export const getProcessDefinition = async (id?: string, key?: string) => {
|
||||
return await request.get({
|
||||
url: '/bpm/process-definition/get-bpmn-xml?id=' + id
|
||||
url: '/bpm/process-definition/get',
|
||||
params: { id, key }
|
||||
})
|
||||
}
|
||||
|
||||
|
||||
@@ -49,8 +49,8 @@ export const getFormPage = async (params) => {
|
||||
}
|
||||
|
||||
// 获得动态表单的精简列表
|
||||
export const getSimpleFormList = async () => {
|
||||
export const getFormSimpleList = async () => {
|
||||
return await request.get({
|
||||
url: '/bpm/form/list-all-simple'
|
||||
url: '/bpm/form/simple-list'
|
||||
})
|
||||
}
|
||||
@@ -2,7 +2,7 @@ import request from '@/config/axios'
|
||||
|
||||
export type LeaveVO = {
|
||||
id: number
|
||||
result: number
|
||||
status: number
|
||||
type: number
|
||||
reason: string
|
||||
processInstanceId: string
|
||||
|
||||
@@ -5,6 +5,7 @@ export type ProcessDefinitionVO = {
|
||||
version: number
|
||||
deploymentTIme: string
|
||||
suspensionState: number
|
||||
formType?: number
|
||||
}
|
||||
|
||||
export type ModelVO = {
|
||||
|
||||
@@ -0,0 +1,42 @@
|
||||
import request from '@/config/axios'
|
||||
|
||||
// BPM 流程表达式 VO
|
||||
export interface ProcessExpressionVO {
|
||||
id: number // 编号
|
||||
name: string // 表达式名字
|
||||
status: number // 表达式状态
|
||||
expression: string // 表达式
|
||||
}
|
||||
|
||||
// BPM 流程表达式 API
|
||||
export const ProcessExpressionApi = {
|
||||
// 查询BPM 流程表达式分页
|
||||
getProcessExpressionPage: async (params: any) => {
|
||||
return await request.get({ url: `/bpm/process-expression/page`, params })
|
||||
},
|
||||
|
||||
// 查询BPM 流程表达式详情
|
||||
getProcessExpression: async (id: number) => {
|
||||
return await request.get({ url: `/bpm/process-expression/get?id=` + id })
|
||||
},
|
||||
|
||||
// 新增BPM 流程表达式
|
||||
createProcessExpression: async (data: ProcessExpressionVO) => {
|
||||
return await request.post({ url: `/bpm/process-expression/create`, data })
|
||||
},
|
||||
|
||||
// 修改BPM 流程表达式
|
||||
updateProcessExpression: async (data: ProcessExpressionVO) => {
|
||||
return await request.put({ url: `/bpm/process-expression/update`, data })
|
||||
},
|
||||
|
||||
// 删除BPM 流程表达式
|
||||
deleteProcessExpression: async (id: number) => {
|
||||
return await request.delete({ url: `/bpm/process-expression/delete?id=` + id })
|
||||
},
|
||||
|
||||
// 导出BPM 流程表达式 Excel
|
||||
exportProcessExpression: async (params) => {
|
||||
return await request.download({ url: `/bpm/process-expression/export-excel`, params })
|
||||
}
|
||||
}
|
||||
@@ -1,4 +1,5 @@
|
||||
import request from '@/config/axios'
|
||||
import { ProcessDefinitionVO } from '@/api/bpm/model'
|
||||
|
||||
export type Task = {
|
||||
id: string
|
||||
@@ -18,53 +19,41 @@ export type ProcessInstanceVO = {
|
||||
businessKey: string
|
||||
createTime: string
|
||||
endTime: string
|
||||
processDefinition?: ProcessDefinitionVO
|
||||
}
|
||||
|
||||
export type ProcessInstanceCCVO = {
|
||||
type: number,
|
||||
taskName: string,
|
||||
taskKey: string,
|
||||
processInstanceName: string,
|
||||
processInstanceKey: string,
|
||||
startUserId: string,
|
||||
options:string [],
|
||||
reason: string
|
||||
}
|
||||
|
||||
export const getMyProcessInstancePage = async (params) => {
|
||||
export const getProcessInstanceMyPage = async (params: any) => {
|
||||
return await request.get({ url: '/bpm/process-instance/my-page', params })
|
||||
}
|
||||
|
||||
export const getProcessInstanceManagerPage = async (params: any) => {
|
||||
return await request.get({ url: '/bpm/process-instance/manager-page', params })
|
||||
}
|
||||
|
||||
export const createProcessInstance = async (data) => {
|
||||
return await request.post({ url: '/bpm/process-instance/create', data: data })
|
||||
}
|
||||
|
||||
export const cancelProcessInstance = async (id: number, reason: string) => {
|
||||
export const cancelProcessInstanceByStartUser = async (id: number, reason: string) => {
|
||||
const data = {
|
||||
id: id,
|
||||
reason: reason
|
||||
}
|
||||
return await request.delete({ url: '/bpm/process-instance/cancel', data: data })
|
||||
return await request.delete({ url: '/bpm/process-instance/cancel-by-start-user', data: data })
|
||||
}
|
||||
|
||||
export const getProcessInstance = async (id: number) => {
|
||||
export const cancelProcessInstanceByAdmin = async (id: number, reason: string) => {
|
||||
const data = {
|
||||
id: id,
|
||||
reason: reason
|
||||
}
|
||||
return await request.delete({ url: '/bpm/process-instance/cancel-by-admin', data: data })
|
||||
}
|
||||
|
||||
export const getProcessInstance = async (id: string) => {
|
||||
return await request.get({ url: '/bpm/process-instance/get?id=' + id })
|
||||
}
|
||||
|
||||
/**
|
||||
* 抄送
|
||||
* @param data 抄送数据
|
||||
* @returns 是否抄送成功
|
||||
*/
|
||||
export const createProcessInstanceCC = async (data) => {
|
||||
return await request.post({ url: '/bpm/process-instance/cc/create', data: data })
|
||||
export const getProcessInstanceCopyPage = async (params: any) => {
|
||||
return await request.get({ url: '/bpm/process-instance/copy/page', params })
|
||||
}
|
||||
|
||||
/**
|
||||
* 抄送列表
|
||||
* @param params
|
||||
* @returns
|
||||
*/
|
||||
export const getProcessInstanceCCPage = async (params) => {
|
||||
return await request.get({ url: '/bpm/process-instance/cc/my-page', params })
|
||||
}
|
||||
@@ -0,0 +1,40 @@
|
||||
import request from '@/config/axios'
|
||||
|
||||
// BPM 流程监听器 VO
|
||||
export interface ProcessListenerVO {
|
||||
id: number // 编号
|
||||
name: string // 监听器名字
|
||||
type: string // 监听器类型
|
||||
status: number // 监听器状态
|
||||
event: string // 监听事件
|
||||
valueType: string // 监听器值类型
|
||||
value: string // 监听器值
|
||||
}
|
||||
|
||||
// BPM 流程监听器 API
|
||||
export const ProcessListenerApi = {
|
||||
// 查询流程监听器分页
|
||||
getProcessListenerPage: async (params: any) => {
|
||||
return await request.get({ url: `/bpm/process-listener/page`, params })
|
||||
},
|
||||
|
||||
// 查询流程监听器详情
|
||||
getProcessListener: async (id: number) => {
|
||||
return await request.get({ url: `/bpm/process-listener/get?id=` + id })
|
||||
},
|
||||
|
||||
// 新增流程监听器
|
||||
createProcessListener: async (data: ProcessListenerVO) => {
|
||||
return await request.post({ url: `/bpm/process-listener/create`, data })
|
||||
},
|
||||
|
||||
// 修改流程监听器
|
||||
updateProcessListener: async (data: ProcessListenerVO) => {
|
||||
return await request.put({ url: `/bpm/process-listener/update`, data })
|
||||
},
|
||||
|
||||
// 删除流程监听器
|
||||
deleteProcessListener: async (id: number) => {
|
||||
return await request.delete({ url: `/bpm/process-listener/delete?id=` + id })
|
||||
}
|
||||
}
|
||||
@@ -4,78 +4,63 @@ export type TaskVO = {
|
||||
id: number
|
||||
}
|
||||
|
||||
export const getTodoTaskPage = async (params) => {
|
||||
export const getTaskTodoPage = async (params: any) => {
|
||||
return await request.get({ url: '/bpm/task/todo-page', params })
|
||||
}
|
||||
|
||||
export const getDoneTaskPage = async (params) => {
|
||||
export const getTaskDonePage = async (params: any) => {
|
||||
return await request.get({ url: '/bpm/task/done-page', params })
|
||||
}
|
||||
|
||||
export const completeTask = async (data) => {
|
||||
return await request.put({ url: '/bpm/task/complete', data })
|
||||
export const getTaskManagerPage = async (params: any) => {
|
||||
return await request.get({ url: '/bpm/task/manager-page', params })
|
||||
}
|
||||
|
||||
export const approveTask = async (data) => {
|
||||
export const approveTask = async (data: any) => {
|
||||
return await request.put({ url: '/bpm/task/approve', data })
|
||||
}
|
||||
|
||||
export const rejectTask = async (data) => {
|
||||
export const rejectTask = async (data: any) => {
|
||||
return await request.put({ url: '/bpm/task/reject', data })
|
||||
}
|
||||
export const backTask = async (data) => {
|
||||
return await request.put({ url: '/bpm/task/back', data })
|
||||
}
|
||||
|
||||
export const updateTaskAssignee = async (data) => {
|
||||
return await request.put({ url: '/bpm/task/update-assignee', data })
|
||||
}
|
||||
|
||||
export const getTaskListByProcessInstanceId = async (processInstanceId) => {
|
||||
export const getTaskListByProcessInstanceId = async (processInstanceId: string) => {
|
||||
return await request.get({
|
||||
url: '/bpm/task/list-by-process-instance-id?processInstanceId=' + processInstanceId
|
||||
})
|
||||
}
|
||||
|
||||
// 导出任务
|
||||
export const exportTask = async (params) => {
|
||||
return await request.download({ url: '/bpm/task/export', params })
|
||||
}
|
||||
|
||||
// 获取所有可回退的节点
|
||||
export const getReturnList = async (params) => {
|
||||
return await request.get({ url: '/bpm/task/return-list', params })
|
||||
export const getTaskListByReturn = async (id: string) => {
|
||||
return await request.get({ url: '/bpm/task/list-by-return', params: { id } })
|
||||
}
|
||||
|
||||
// 回退
|
||||
export const returnTask = async (data) => {
|
||||
export const returnTask = async (data: any) => {
|
||||
return await request.put({ url: '/bpm/task/return', data })
|
||||
}
|
||||
|
||||
/**
|
||||
* 委派
|
||||
*/
|
||||
export const delegateTask = async (data) => {
|
||||
// 委派
|
||||
export const delegateTask = async (data: any) => {
|
||||
return await request.put({ url: '/bpm/task/delegate', data })
|
||||
}
|
||||
|
||||
/**
|
||||
* 加签
|
||||
*/
|
||||
export const taskAddSign = async (data) => {
|
||||
// 转派
|
||||
export const transferTask = async (data: any) => {
|
||||
return await request.put({ url: '/bpm/task/transfer', data })
|
||||
}
|
||||
|
||||
// 加签
|
||||
export const signCreateTask = async (data: any) => {
|
||||
return await request.put({ url: '/bpm/task/create-sign', data })
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取减签任务列表
|
||||
*/
|
||||
export const getChildrenTaskList = async (id: string) => {
|
||||
return await request.get({ url: '/bpm/task/children-list?taskId=' + id })
|
||||
}
|
||||
|
||||
/**
|
||||
* 减签
|
||||
*/
|
||||
export const taskSubSign = async (data) => {
|
||||
// 减签
|
||||
export const signDeleteTask = async (data: any) => {
|
||||
return await request.delete({ url: '/bpm/task/delete-sign', data })
|
||||
}
|
||||
|
||||
// 获取减签任务列表
|
||||
export const getChildrenTaskList = async (id: string) => {
|
||||
return await request.get({ url: '/bpm/task/list-by-parent-task-id?parentTaskId=' + id })
|
||||
}
|
||||
@@ -1,29 +0,0 @@
|
||||
import request from '@/config/axios'
|
||||
|
||||
export type TaskAssignVO = {
|
||||
id: number
|
||||
modelId: string
|
||||
processDefinitionId: string
|
||||
taskDefinitionKey: string
|
||||
taskDefinitionName: string
|
||||
options: string[]
|
||||
type: number
|
||||
}
|
||||
|
||||
export const getTaskAssignRuleList = async (params) => {
|
||||
return await request.get({ url: '/bpm/task-assign-rule/list', params })
|
||||
}
|
||||
|
||||
export const createTaskAssignRule = async (data: TaskAssignVO) => {
|
||||
return await request.post({
|
||||
url: '/bpm/task-assign-rule/create',
|
||||
data: data
|
||||
})
|
||||
}
|
||||
|
||||
export const updateTaskAssignRule = async (data: TaskAssignVO) => {
|
||||
return await request.put({
|
||||
url: '/bpm/task-assign-rule/update',
|
||||
data: data
|
||||
})
|
||||
}
|
||||
@@ -4,7 +4,7 @@ export type UserGroupVO = {
|
||||
id: number
|
||||
name: string
|
||||
description: string
|
||||
memberUserIds: number[]
|
||||
userIds: number[]
|
||||
status: number
|
||||
remark: string
|
||||
createTime: string
|
||||
@@ -42,6 +42,6 @@ export const getUserGroupPage = async (params) => {
|
||||
}
|
||||
|
||||
// 获取用户组精简信息列表
|
||||
export const getSimpleUserGroupList = async (): Promise<UserGroupVO[]> => {
|
||||
return await request.get({ url: '/bpm/user-group/list-all-simple' })
|
||||
export const getUserGroupSimpleList = async (): Promise<UserGroupVO[]> => {
|
||||
return await request.get({ url: '/bpm/user-group/simple-list' })
|
||||
}
|
||||
@@ -1,5 +1,5 @@
|
||||
import request from '@/config/axios'
|
||||
import { TransferReqVO } from '@/api/crm/customer'
|
||||
import { TransferReqVO } from '@/api/crm/permission'
|
||||
|
||||
export interface BusinessVO {
|
||||
id: number
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import request from '@/config/axios'
|
||||
import { TransferReqVO } from '@/api/crm/customer'
|
||||
import { TransferReqVO } from '@/api/crm/permission'
|
||||
|
||||
export interface ClueVO {
|
||||
id: number // 编号
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import request from '@/config/axios'
|
||||
import { TransferReqVO } from '@/api/crm/customer'
|
||||
import { TransferReqVO } from '@/api/crm/permission'
|
||||
|
||||
export interface ContactVO {
|
||||
id: number // 编号
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import request from '@/config/axios'
|
||||
import { TransferReqVO } from '@/api/crm/customer'
|
||||
import { TransferReqVO } from '@/api/crm/permission'
|
||||
|
||||
export interface ContractVO {
|
||||
id: number
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
import request from '@/config/axios'
|
||||
import { TransferReqVO } from '@/api/crm/permission'
|
||||
|
||||
export interface CustomerVO {
|
||||
id: number // 编号
|
||||
@@ -102,12 +103,6 @@ export const getCustomerSimpleList = async () => {
|
||||
|
||||
// ======================= 业务操作 =======================
|
||||
|
||||
export interface TransferReqVO {
|
||||
id: number | undefined // 客户编号
|
||||
newOwnerUserId: number | undefined // 新负责人的用户编号
|
||||
oldOwnerPermissionLevel: number | undefined // 老负责人加入团队后的权限级别
|
||||
}
|
||||
|
||||
// 客户转移
|
||||
export const transferCustomer = async (data: TransferReqVO) => {
|
||||
return await request.put({ url: '/crm/customer/transfer', data })
|
||||
|
||||
@@ -6,6 +6,7 @@ export interface PermissionVO {
|
||||
bizType: number // Crm 类型
|
||||
bizId: number // Crm 类型数据编号
|
||||
level: number // 权限级别
|
||||
toBizTypes?: number[] // 同时添加至
|
||||
deptName?: string // 部门名称
|
||||
nickname?: string // 用户昵称
|
||||
postNames?: string[] // 岗位名称数组
|
||||
@@ -13,6 +14,13 @@ export interface PermissionVO {
|
||||
ids?: number[]
|
||||
}
|
||||
|
||||
export interface TransferReqVO {
|
||||
id: number // 模块编号
|
||||
newOwnerUserId: number // 新负责人的用户编号
|
||||
oldOwnerPermissionLevel?: number // 老负责人加入团队后的权限级别
|
||||
toBizTypes?: number[] // 转移客户时,需要额外有【联系人】【商机】【合同】的 checkbox 选择
|
||||
}
|
||||
|
||||
/**
|
||||
* CRM 业务类型枚举
|
||||
*
|
||||
|
||||
@@ -3,18 +3,20 @@ import request from '@/config/axios'
|
||||
export interface ReceivableVO {
|
||||
id: number
|
||||
no: string
|
||||
planId: number
|
||||
customerId: number
|
||||
planId?: number
|
||||
customerId?: number
|
||||
customerName?: string
|
||||
contractId: number
|
||||
contractId?: number
|
||||
contract?: {
|
||||
id?: number
|
||||
name?: string
|
||||
no: string
|
||||
totalPrice: number
|
||||
}
|
||||
auditStatus: number
|
||||
processInstanceId: number
|
||||
returnTime: Date
|
||||
returnType: string
|
||||
returnType: number
|
||||
price: number
|
||||
ownerUserId: number
|
||||
ownerUserName?: string
|
||||
|
||||
@@ -11,7 +11,7 @@ export interface ReceivablePlanVO {
|
||||
remindTime: Date
|
||||
customerId: number
|
||||
customerName?: string
|
||||
contractId: number
|
||||
contractId?: number
|
||||
contractNo?: string
|
||||
ownerUserId: number
|
||||
ownerUserName?: string
|
||||
|
||||
@@ -0,0 +1,168 @@
|
||||
import request from '@/config/axios'
|
||||
|
||||
export interface CrmStatisticsCustomerSummaryByDateRespVO {
|
||||
time: string
|
||||
customerCreateCount: number
|
||||
customerDealCount: number
|
||||
}
|
||||
|
||||
export interface CrmStatisticsCustomerSummaryByUserRespVO {
|
||||
ownerUserName: string
|
||||
customerCreateCount: number
|
||||
customerDealCount: number
|
||||
contractPrice: number
|
||||
receivablePrice: number
|
||||
}
|
||||
|
||||
export interface CrmStatisticsFollowUpSummaryByDateRespVO {
|
||||
time: string
|
||||
followUpRecordCount: number
|
||||
followUpCustomerCount: number
|
||||
}
|
||||
|
||||
export interface CrmStatisticsFollowUpSummaryByUserRespVO {
|
||||
ownerUserName: string
|
||||
followupRecordCount: number
|
||||
followupCustomerCount: number
|
||||
}
|
||||
|
||||
export interface CrmStatisticsFollowUpSummaryByTypeRespVO {
|
||||
followUpType: string
|
||||
followUpRecordCount: number
|
||||
}
|
||||
|
||||
export interface CrmStatisticsCustomerContractSummaryRespVO {
|
||||
customerName: string
|
||||
contractName: string
|
||||
totalPrice: number
|
||||
receivablePrice: number
|
||||
customerType: string
|
||||
customerSource: string
|
||||
ownerUserName: string
|
||||
creatorUserName: string
|
||||
createTime: Date
|
||||
orderDate: Date
|
||||
}
|
||||
|
||||
export interface CrmStatisticsPoolSummaryByDateRespVO {
|
||||
time: string
|
||||
customerPutCount: number
|
||||
customerTakeCount: number
|
||||
}
|
||||
|
||||
export interface CrmStatisticsPoolSummaryByUserRespVO {
|
||||
ownerUserName: string
|
||||
customerPutCount: number
|
||||
customerTakeCount: number
|
||||
}
|
||||
|
||||
export interface CrmStatisticsCustomerDealCycleByDateRespVO {
|
||||
time: string
|
||||
customerDealCycle: number
|
||||
}
|
||||
|
||||
export interface CrmStatisticsCustomerDealCycleByUserRespVO {
|
||||
ownerUserName: string
|
||||
customerDealCycle: number
|
||||
customerDealCount: number
|
||||
}
|
||||
|
||||
export interface CrmStatisticsCustomerDealCycleByAreaRespVO {
|
||||
areaName: string
|
||||
customerDealCycle: number
|
||||
customerDealCount: number
|
||||
}
|
||||
|
||||
export interface CrmStatisticsCustomerDealCycleByProductRespVO {
|
||||
productName: string
|
||||
customerDealCycle: number
|
||||
customerDealCount: number
|
||||
}
|
||||
|
||||
// 客户分析 API
|
||||
export const StatisticsCustomerApi = {
|
||||
// 1.1 客户总量分析(按日期)
|
||||
getCustomerSummaryByDate: (params: any) => {
|
||||
return request.get({
|
||||
url: '/crm/statistics-customer/get-customer-summary-by-date',
|
||||
params
|
||||
})
|
||||
},
|
||||
// 1.2 客户总量分析(按用户)
|
||||
getCustomerSummaryByUser: (params: any) => {
|
||||
return request.get({
|
||||
url: '/crm/statistics-customer/get-customer-summary-by-user',
|
||||
params
|
||||
})
|
||||
},
|
||||
// 2.1 客户跟进次数分析(按日期)
|
||||
getFollowUpSummaryByDate: (params: any) => {
|
||||
return request.get({
|
||||
url: '/crm/statistics-customer/get-follow-up-summary-by-date',
|
||||
params
|
||||
})
|
||||
},
|
||||
// 2.2 客户跟进次数分析(按用户)
|
||||
getFollowUpSummaryByUser: (params: any) => {
|
||||
return request.get({
|
||||
url: '/crm/statistics-customer/get-follow-up-summary-by-user',
|
||||
params
|
||||
})
|
||||
},
|
||||
// 3.1 获取客户跟进方式统计数
|
||||
getFollowUpSummaryByType: (params: any) => {
|
||||
return request.get({
|
||||
url: '/crm/statistics-customer/get-follow-up-summary-by-type',
|
||||
params
|
||||
})
|
||||
},
|
||||
// 4.1 合同摘要信息(客户转化率页面)
|
||||
getContractSummary: (params: any) => {
|
||||
return request.get({
|
||||
url: '/crm/statistics-customer/get-contract-summary',
|
||||
params
|
||||
})
|
||||
},
|
||||
// 5.1 获取客户公海分析(按日期)
|
||||
getPoolSummaryByDate: (param: any) => {
|
||||
return request.get({
|
||||
url: '/crm/statistics-customer/get-pool-summary-by-date',
|
||||
params: param
|
||||
})
|
||||
},
|
||||
// 5.2 获取客户公海分析(按用户)
|
||||
getPoolSummaryByUser: (param: any) => {
|
||||
return request.get({
|
||||
url: '/crm/statistics-customer/get-pool-summary-by-user',
|
||||
params: param
|
||||
})
|
||||
},
|
||||
// 6.1 获取客户成交周期(按日期)
|
||||
getCustomerDealCycleByDate: (params: any) => {
|
||||
return request.get({
|
||||
url: '/crm/statistics-customer/get-customer-deal-cycle-by-date',
|
||||
params
|
||||
})
|
||||
},
|
||||
// 6.2 获取客户成交周期(按用户)
|
||||
getCustomerDealCycleByUser: (params: any) => {
|
||||
return request.get({
|
||||
url: '/crm/statistics-customer/get-customer-deal-cycle-by-user',
|
||||
params
|
||||
})
|
||||
},
|
||||
// 6.2 获取客户成交周期(按用户)
|
||||
getCustomerDealCycleByArea: (params: any) => {
|
||||
return request.get({
|
||||
url: '/crm/statistics-customer/get-customer-deal-cycle-by-area',
|
||||
params
|
||||
})
|
||||
},
|
||||
// 6.2 获取客户成交周期(按用户)
|
||||
getCustomerDealCycleByProduct: (params: any) => {
|
||||
return request.get({
|
||||
url: '/crm/statistics-customer/get-customer-deal-cycle-by-product',
|
||||
params
|
||||
})
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,58 @@
|
||||
import request from '@/config/axios'
|
||||
|
||||
export interface CrmStatisticFunnelRespVO {
|
||||
customerCount: number // 客户数
|
||||
businessCount: number // 商机数
|
||||
businessWinCount: number // 赢单数
|
||||
}
|
||||
|
||||
export interface CrmStatisticsBusinessSummaryByDateRespVO {
|
||||
time: string // 时间
|
||||
businessCreateCount: number // 商机数
|
||||
totalPrice: number | string // 商机金额
|
||||
}
|
||||
|
||||
export interface CrmStatisticsBusinessInversionRateSummaryByDateRespVO {
|
||||
time: string // 时间
|
||||
businessCount: number // 商机数量
|
||||
businessWinCount: number // 赢单商机数
|
||||
}
|
||||
|
||||
// 客户分析 API
|
||||
export const StatisticFunnelApi = {
|
||||
// 1. 获取销售漏斗统计数据
|
||||
getFunnelSummary: (params: any) => {
|
||||
return request.get({
|
||||
url: '/crm/statistics-funnel/get-funnel-summary',
|
||||
params
|
||||
})
|
||||
},
|
||||
// 2. 获取商机结束状态统计
|
||||
getBusinessSummaryByEndStatus: (params: any) => {
|
||||
return request.get({
|
||||
url: '/crm/statistics-funnel/get-business-summary-by-end-status',
|
||||
params
|
||||
})
|
||||
},
|
||||
// 3. 获取新增商机分析(按日期)
|
||||
getBusinessSummaryByDate: (params: any) => {
|
||||
return request.get({
|
||||
url: '/crm/statistics-funnel/get-business-summary-by-date',
|
||||
params
|
||||
})
|
||||
},
|
||||
// 4. 获取商机转化率分析(按日期)
|
||||
getBusinessInversionRateSummaryByDate: (params: any) => {
|
||||
return request.get({
|
||||
url: '/crm/statistics-funnel/get-business-inversion-rate-summary-by-date',
|
||||
params
|
||||
})
|
||||
},
|
||||
// 5. 获取商机列表(按日期)
|
||||
getBusinessPageByDate: (params: any) => {
|
||||
return request.get({
|
||||
url: '/crm/statistics-funnel/get-business-page-by-date',
|
||||
params
|
||||
})
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,33 @@
|
||||
import request from '@/config/axios'
|
||||
|
||||
export interface StatisticsPerformanceRespVO {
|
||||
time: string
|
||||
currentMonthCount: number
|
||||
lastMonthCount: number
|
||||
lastYearCount: number
|
||||
}
|
||||
|
||||
// 排行 API
|
||||
export const StatisticsPerformanceApi = {
|
||||
// 员工获得合同金额统计
|
||||
getContractPricePerformance: (params: any) => {
|
||||
return request.get({
|
||||
url: '/crm/statistics-performance/get-contract-price-performance',
|
||||
params
|
||||
})
|
||||
},
|
||||
// 员工获得回款统计
|
||||
getReceivablePricePerformance: (params: any) => {
|
||||
return request.get({
|
||||
url: '/crm/statistics-performance/get-receivable-price-performance',
|
||||
params
|
||||
})
|
||||
},
|
||||
//员工获得签约合同数量统计
|
||||
getContractCountPerformance: (params: any) => {
|
||||
return request.get({
|
||||
url: '/crm/statistics-performance/get-contract-count-performance',
|
||||
params
|
||||
})
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,60 @@
|
||||
import request from '@/config/axios'
|
||||
|
||||
export interface CrmStatisticCustomerBaseRespVO {
|
||||
customerCount: number
|
||||
dealCount: number
|
||||
dealPortion: string | number
|
||||
}
|
||||
|
||||
export interface CrmStatisticCustomerIndustryRespVO extends CrmStatisticCustomerBaseRespVO {
|
||||
industryId: number
|
||||
industryPortion: string | number
|
||||
}
|
||||
|
||||
export interface CrmStatisticCustomerSourceRespVO extends CrmStatisticCustomerBaseRespVO {
|
||||
source: number
|
||||
sourcePortion: string | number
|
||||
}
|
||||
|
||||
export interface CrmStatisticCustomerLevelRespVO extends CrmStatisticCustomerBaseRespVO {
|
||||
level: number
|
||||
levelPortion: string | number
|
||||
}
|
||||
|
||||
export interface CrmStatisticCustomerAreaRespVO extends CrmStatisticCustomerBaseRespVO {
|
||||
areaId: number
|
||||
areaName: string
|
||||
areaPortion: string | number
|
||||
}
|
||||
|
||||
// 客户分析 API
|
||||
export const StatisticsPortraitApi = {
|
||||
// 1. 获取客户行业统计数据
|
||||
getCustomerIndustry: (params: any) => {
|
||||
return request.get({
|
||||
url: '/crm/statistics-portrait/get-customer-industry-summary',
|
||||
params
|
||||
})
|
||||
},
|
||||
// 2. 获取客户来源统计数据
|
||||
getCustomerSource: (params: any) => {
|
||||
return request.get({
|
||||
url: '/crm/statistics-portrait/get-customer-source-summary',
|
||||
params
|
||||
})
|
||||
},
|
||||
// 3. 获取客户级别统计数据
|
||||
getCustomerLevel: (params: any) => {
|
||||
return request.get({
|
||||
url: '/crm/statistics-portrait/get-customer-level-summary',
|
||||
params
|
||||
})
|
||||
},
|
||||
// 4. 获取客户地区统计数据
|
||||
getCustomerArea: (params: any) => {
|
||||
return request.get({
|
||||
url: '/crm/statistics-portrait/get-customer-area-summary',
|
||||
params
|
||||
})
|
||||
}
|
||||
}
|
||||
@@ -13,8 +13,8 @@ export interface ProductCategoryVO {
|
||||
// ERP 产品分类 API
|
||||
export const ProductCategoryApi = {
|
||||
// 查询产品分类列表
|
||||
getProductCategoryList: async (params) => {
|
||||
return await request.get({ url: `/erp/product-category/list`, params })
|
||||
getProductCategoryList: async () => {
|
||||
return await request.get({ url: `/erp/product-category/list` })
|
||||
},
|
||||
|
||||
// 查询产品分类精简列表
|
||||
|
||||
@@ -8,11 +8,15 @@ export interface ApiAccessLogVO {
|
||||
applicationName: string
|
||||
requestMethod: string
|
||||
requestParams: string
|
||||
responseBody: string
|
||||
requestUrl: string
|
||||
userIp: string
|
||||
userAgent: string
|
||||
operateModule: string
|
||||
operateName: string
|
||||
operateType: number
|
||||
beginTime: Date
|
||||
endTIme: Date
|
||||
endTime: Date
|
||||
duration: number
|
||||
resultCode: number
|
||||
resultMsg: string
|
||||
|
||||
@@ -28,7 +28,6 @@ export type CodegenColumnVO = {
|
||||
columnComment: string
|
||||
nullable: number
|
||||
primaryKey: number
|
||||
autoIncrement: boolean
|
||||
ordinalPosition: number
|
||||
javaType: string
|
||||
javaField: string
|
||||
|
||||
@@ -1,16 +0,0 @@
|
||||
import request from '@/config/axios'
|
||||
|
||||
// 导出Html
|
||||
export const exportHtml = () => {
|
||||
return request.download({ url: '/infra/db-doc/export-html' })
|
||||
}
|
||||
|
||||
// 导出Word
|
||||
export const exportWord = () => {
|
||||
return request.download({ url: '/infra/db-doc/export-word' })
|
||||
}
|
||||
|
||||
// 导出Markdown
|
||||
export const exportMarkdown = () => {
|
||||
return request.download({ url: '/infra/db-doc/export-markdown' })
|
||||
}
|
||||
@@ -7,8 +7,8 @@ export interface Demo02CategoryVO {
|
||||
}
|
||||
|
||||
// 查询示例分类列表
|
||||
export const getDemo02CategoryList = async (params) => {
|
||||
return await request.get({ url: `/infra/demo02-category/list`, params })
|
||||
export const getDemo02CategoryList = async () => {
|
||||
return await request.get({ url: `/infra/demo02-category/list` })
|
||||
}
|
||||
|
||||
// 查询示例分类详情
|
||||
|
||||
@@ -12,6 +12,7 @@ export interface JobLogVO {
|
||||
duration: string
|
||||
status: number
|
||||
createTime: string
|
||||
result: string
|
||||
}
|
||||
|
||||
// 任务日志列表
|
||||
|
||||
@@ -0,0 +1,10 @@
|
||||
import request from '@/config/axios'
|
||||
|
||||
/**
|
||||
* 获得商品浏览记录分页
|
||||
*
|
||||
* @param params 请求参数
|
||||
*/
|
||||
export const getBrowseHistoryPage = (params: any) => {
|
||||
return request.get({ url: '/product/browse-history/page', params })
|
||||
}
|
||||
@@ -0,0 +1,35 @@
|
||||
import request from '@/config/axios'
|
||||
|
||||
export interface KeFuConversationRespVO {
|
||||
id: number // 编号
|
||||
userId: number // 会话所属用户
|
||||
userAvatar: string // 会话所属用户头像
|
||||
userNickname: string // 会话所属用户昵称
|
||||
lastMessageTime: Date // 最后聊天时间
|
||||
lastMessageContent: string // 最后聊天内容
|
||||
lastMessageContentType: number // 最后发送的消息类型
|
||||
adminPinned: boolean // 管理端置顶
|
||||
userDeleted: boolean // 用户是否可见
|
||||
adminDeleted: boolean // 管理员是否可见
|
||||
adminUnreadMessageCount: number // 管理员未读消息数
|
||||
createTime?: string // 创建时间
|
||||
}
|
||||
|
||||
// 客服会话 API
|
||||
export const KeFuConversationApi = {
|
||||
// 获得客服会话列表
|
||||
getConversationList: async () => {
|
||||
return await request.get({ url: '/promotion/kefu-conversation/list' })
|
||||
},
|
||||
// 客服会话置顶
|
||||
updateConversationPinned: async (data: any) => {
|
||||
return await request.put({
|
||||
url: '/promotion/kefu-conversation/update-conversation-pinned',
|
||||
data
|
||||
})
|
||||
},
|
||||
// 删除客服会话
|
||||
deleteConversation: async (id: number) => {
|
||||
return await request.get({ url: '/promotion/kefu-conversation/delete?id' + id })
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,36 @@
|
||||
import request from '@/config/axios'
|
||||
|
||||
export interface KeFuMessageRespVO {
|
||||
id: number // 编号
|
||||
conversationId: number // 会话编号
|
||||
senderId: number // 发送人编号
|
||||
senderAvatar: string // 发送人头像
|
||||
senderType: number // 发送人类型
|
||||
receiverId: number // 接收人编号
|
||||
receiverType: number // 接收人类型
|
||||
contentType: number // 消息类型
|
||||
content: string // 消息
|
||||
readStatus: boolean // 是否已读
|
||||
createTime: Date // 创建时间
|
||||
}
|
||||
|
||||
// 客服会话 API
|
||||
export const KeFuMessageApi = {
|
||||
// 发送客服消息
|
||||
sendKeFuMessage: async (data: any) => {
|
||||
return await request.post({
|
||||
url: '/promotion/kefu-message/send',
|
||||
data
|
||||
})
|
||||
},
|
||||
// 更新客服消息已读状态
|
||||
updateKeFuMessageReadStatus: async (conversationId: number) => {
|
||||
return await request.put({
|
||||
url: '/promotion/kefu-message/update-read-status?conversationId=' + conversationId
|
||||
})
|
||||
},
|
||||
// 获得消息分页数据
|
||||
getKeFuMessagePage: async (params: any) => {
|
||||
return await request.get({ url: '/promotion/kefu-message/page', params })
|
||||
}
|
||||
}
|
||||
@@ -1,49 +1,53 @@
|
||||
import request from '@/config/axios'
|
||||
|
||||
// 秒杀时段 VO
|
||||
export interface SeckillConfigVO {
|
||||
id: number
|
||||
name: string
|
||||
startTime: string
|
||||
endTime: string
|
||||
sliderPicUrls: string[]
|
||||
status: number
|
||||
id: number // 编号
|
||||
name: string // 秒杀时段名称
|
||||
startTime: string // 开始时间点
|
||||
endTime: string // 结束时间点
|
||||
sliderPicUrls: string[] // 秒杀轮播图
|
||||
status: number // 活动状态
|
||||
}
|
||||
|
||||
// 查询秒杀时段配置列表
|
||||
export const getSeckillConfigPage = async (params) => {
|
||||
return await request.get({ url: '/promotion/seckill-config/page', params })
|
||||
}
|
||||
// 秒杀时段 API
|
||||
export const SeckillConfigApi = {
|
||||
// 查询秒杀时段分页
|
||||
getSeckillConfigPage: async (params: any) => {
|
||||
return await request.get({ url: `/promotion/seckill-config/page`, params })
|
||||
},
|
||||
|
||||
// 查询秒杀时段配置详情
|
||||
export const getSeckillConfig = async (id: number) => {
|
||||
return await request.get({ url: '/promotion/seckill-config/get?id=' + id })
|
||||
}
|
||||
// 查询秒杀时段列表
|
||||
getSimpleSeckillConfigList: async () => {
|
||||
return await request.get({ url: `/promotion/seckill-config/list` })
|
||||
},
|
||||
|
||||
// 获得所有开启状态的秒杀时段精简列表
|
||||
export const getSimpleSeckillConfigList = async () => {
|
||||
return await request.get({ url: '/promotion/seckill-config/list-all-simple' })
|
||||
}
|
||||
// 查询秒杀时段详情
|
||||
getSeckillConfig: async (id: number) => {
|
||||
return await request.get({ url: `/promotion/seckill-config/get?id=` + id })
|
||||
},
|
||||
|
||||
// 新增秒杀时段配置
|
||||
export const createSeckillConfig = async (data: SeckillConfigVO) => {
|
||||
return await request.post({ url: '/promotion/seckill-config/create', data })
|
||||
}
|
||||
// 新增秒杀时段
|
||||
createSeckillConfig: async (data: SeckillConfigVO) => {
|
||||
return await request.post({ url: `/promotion/seckill-config/create`, data })
|
||||
},
|
||||
|
||||
// 修改秒杀时段配置
|
||||
export const updateSeckillConfig = async (data: SeckillConfigVO) => {
|
||||
return await request.put({ url: '/promotion/seckill-config/update', data })
|
||||
}
|
||||
// 修改秒杀时段
|
||||
updateSeckillConfig: async (data: SeckillConfigVO) => {
|
||||
return await request.put({ url: `/promotion/seckill-config/update`, data })
|
||||
},
|
||||
|
||||
// 修改时段配置状态
|
||||
export const updateSeckillConfigStatus = (id: number, status: number) => {
|
||||
const data = {
|
||||
id,
|
||||
status
|
||||
// 删除秒杀时段
|
||||
deleteSeckillConfig: async (id: number) => {
|
||||
return await request.delete({ url: `/promotion/seckill-config/delete?id=` + id })
|
||||
},
|
||||
|
||||
// 修改时段配置状态
|
||||
updateSeckillConfigStatus: async (id: number, status: number) => {
|
||||
const data = {
|
||||
id,
|
||||
status
|
||||
}
|
||||
return request.put({ url: '/promotion/seckill-config/update-status', data: data })
|
||||
}
|
||||
return request.put({ url: '/promotion/seckill-config/update-status', data: data })
|
||||
}
|
||||
|
||||
// 删除秒杀时段配置
|
||||
export const deleteSeckillConfig = async (id: number) => {
|
||||
return await request.delete({ url: '/promotion/seckill-config/delete?id=' + id })
|
||||
}
|
||||
@@ -5,7 +5,7 @@ import { formatDate } from '@/utils/formatTime'
|
||||
|
||||
/** 会员分析 Request VO */
|
||||
export interface MemberAnalyseReqVO {
|
||||
times: [dayjs.ConfigType, dayjs.ConfigType]
|
||||
times: dayjs.ConfigType[]
|
||||
}
|
||||
|
||||
/** 会员分析 Response VO */
|
||||
|
||||
@@ -141,7 +141,7 @@ export const getExpressTrackList = async (id: number | null) => {
|
||||
}
|
||||
|
||||
export interface DeliveryVO {
|
||||
id: number // 订单编号
|
||||
id?: number // 订单编号
|
||||
logisticsId: number | null // 物流公司编号
|
||||
logisticsNo: string // 物流编号
|
||||
}
|
||||
|
||||
@@ -1,39 +0,0 @@
|
||||
import request from '@/config/axios'
|
||||
|
||||
export interface UReportDataVO {
|
||||
id: number
|
||||
name: string
|
||||
status: number
|
||||
content: string
|
||||
remark: string
|
||||
}
|
||||
|
||||
// 查询Ureport2报表分页
|
||||
export const getUReportDataPage = async (params) => {
|
||||
return await request.get({ url: `/report/ureport-data/page`, params })
|
||||
}
|
||||
|
||||
// 查询Ureport2报表详情
|
||||
export const getUReportData = async (id: number) => {
|
||||
return await request.get({ url: `/report/ureport-data/get?id=` + id })
|
||||
}
|
||||
|
||||
// 新增Ureport2报表
|
||||
export const createUReportData = async (data: UReportDataVO) => {
|
||||
return await request.post({ url: `/report/ureport-data/create`, data })
|
||||
}
|
||||
|
||||
// 修改Ureport2报表
|
||||
export const updateUReportData = async (data: UReportDataVO) => {
|
||||
return await request.put({ url: `/report/ureport-data/update`, data })
|
||||
}
|
||||
|
||||
// 删除Ureport2报表
|
||||
export const deleteUReportData = async (id: number) => {
|
||||
return await request.delete({ url: `/report/ureport-data/delete?id=` + id })
|
||||
}
|
||||
|
||||
// 导出Ureport2报表 Excel
|
||||
export const exportUReportData = async (params) => {
|
||||
return await request.download({ url: `/report/ureport-data/export-excel`, params })
|
||||
}
|
||||
@@ -1,40 +0,0 @@
|
||||
import request from '@/config/axios'
|
||||
|
||||
export interface ErrorCodeVO {
|
||||
id: number | undefined
|
||||
type: number
|
||||
applicationName: string
|
||||
code: number | undefined
|
||||
message: string
|
||||
memo: string
|
||||
createTime: Date
|
||||
}
|
||||
|
||||
// 查询错误码列表
|
||||
export const getErrorCodePage = (params: PageParam) => {
|
||||
return request.get({ url: '/system/error-code/page', params })
|
||||
}
|
||||
|
||||
// 查询错误码详情
|
||||
export const getErrorCode = (id: number) => {
|
||||
return request.get({ url: '/system/error-code/get?id=' + id })
|
||||
}
|
||||
|
||||
// 新增错误码
|
||||
export const createErrorCode = (data: ErrorCodeVO) => {
|
||||
return request.post({ url: '/system/error-code/create', data })
|
||||
}
|
||||
|
||||
// 修改错误码
|
||||
export const updateErrorCode = (data: ErrorCodeVO) => {
|
||||
return request.put({ url: '/system/error-code/update', data })
|
||||
}
|
||||
|
||||
// 删除错误码
|
||||
export const deleteErrorCode = (id: number) => {
|
||||
return request.delete({ url: '/system/error-code/delete?id=' + id })
|
||||
}
|
||||
// 导出错误码
|
||||
export const excelErrorCode = (params) => {
|
||||
return request.download({ url: '/system/error-code/export-excel', params })
|
||||
}
|
||||
@@ -8,6 +8,7 @@ export interface MailAccountVO {
|
||||
host: string
|
||||
port: number
|
||||
sslEnable: boolean
|
||||
starttlsEnable: boolean
|
||||
}
|
||||
|
||||
// 查询邮箱账号列表
|
||||
|
||||
@@ -2,30 +2,6 @@ import request from '@/config/axios'
|
||||
|
||||
export type OperateLogVO = {
|
||||
id: number
|
||||
userNickname: string
|
||||
traceId: string
|
||||
userId: number
|
||||
module: string
|
||||
name: string
|
||||
type: number
|
||||
content: string
|
||||
exts: Map<String, Object>
|
||||
requestMethod: string
|
||||
requestUrl: string
|
||||
userIp: string
|
||||
userAgent: string
|
||||
javaMethod: string
|
||||
javaMethodArgs: string
|
||||
startTime: Date
|
||||
duration: number
|
||||
resultCode: number
|
||||
resultMsg: string
|
||||
resultData: string
|
||||
}
|
||||
|
||||
export type OperateLogV2VO = {
|
||||
id: number
|
||||
userNickname: string
|
||||
traceId: string
|
||||
userType: number
|
||||
userId: number
|
||||
@@ -42,11 +18,6 @@ export type OperateLogV2VO = {
|
||||
creator: string
|
||||
creatorName: string
|
||||
createTime: Date
|
||||
// 数据扩展,渲染时使用
|
||||
title: string // 操作标题(如果为空则取 name 值)
|
||||
colSize: number // 变更记录行数
|
||||
contentStrList: string[]
|
||||
tagsContentList: string[]
|
||||
}
|
||||
|
||||
// 查询操作日志列表
|
||||
@@ -54,6 +25,6 @@ export const getOperateLogPage = (params: PageParam) => {
|
||||
return request.get({ url: '/system/operate-log/page', params })
|
||||
}
|
||||
// 导出操作日志
|
||||
export const exportOperateLog = (params) => {
|
||||
export const exportOperateLog = (params: any) => {
|
||||
return request.download({ url: '/system/operate-log/export', params })
|
||||
}
|
||||
@@ -1,58 +0,0 @@
|
||||
import request from '@/config/axios'
|
||||
import qs from 'qs'
|
||||
|
||||
export interface SensitiveWordVO {
|
||||
id: number
|
||||
name: string
|
||||
status: number
|
||||
description: string
|
||||
tags: string[]
|
||||
createTime: Date
|
||||
}
|
||||
|
||||
export interface SensitiveWordTestReqVO {
|
||||
text: string
|
||||
tag: string[]
|
||||
}
|
||||
|
||||
// 查询敏感词列表
|
||||
export const getSensitiveWordPage = (params: PageParam) => {
|
||||
return request.get({ url: '/system/sensitive-word/page', params })
|
||||
}
|
||||
|
||||
// 查询敏感词详情
|
||||
export const getSensitiveWord = (id: number) => {
|
||||
return request.get({ url: '/system/sensitive-word/get?id=' + id })
|
||||
}
|
||||
|
||||
// 新增敏感词
|
||||
export const createSensitiveWord = (data: SensitiveWordVO) => {
|
||||
return request.post({ url: '/system/sensitive-word/create', data })
|
||||
}
|
||||
|
||||
// 修改敏感词
|
||||
export const updateSensitiveWord = (data: SensitiveWordVO) => {
|
||||
return request.put({ url: '/system/sensitive-word/update', data })
|
||||
}
|
||||
|
||||
// 删除敏感词
|
||||
export const deleteSensitiveWord = (id: number) => {
|
||||
return request.delete({ url: '/system/sensitive-word/delete?id=' + id })
|
||||
}
|
||||
|
||||
// 导出敏感词
|
||||
export const exportSensitiveWord = (params) => {
|
||||
return request.download({ url: '/system/sensitive-word/export-excel', params })
|
||||
}
|
||||
|
||||
// 获取所有敏感词的标签数组
|
||||
export const getSensitiveWordTagList = () => {
|
||||
return request.get({ url: '/system/sensitive-word/get-tags' })
|
||||
}
|
||||
|
||||
// 获得文本所包含的不合法的敏感词数组
|
||||
export const validateText = (query: SensitiveWordTestReqVO) => {
|
||||
return request.get({
|
||||
url: '/system/sensitive-word/validate-text?' + qs.stringify(query, { arrayFormat: 'repeat' })
|
||||
})
|
||||
}
|
||||
@@ -0,0 +1 @@
|
||||
<?xml version="1.0" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg t="1715606039621" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="4256" xmlns:xlink="http://www.w3.org/1999/xlink" width="200" height="200"><path d="M878.250667 981.333333H375.338667a104.661333 104.661333 0 0 1-104.661334-104.661333V375.338667a104.661333 104.661333 0 0 1 104.661334-104.661334h502.912a104.661333 104.661333 0 0 1 104.661333 104.661334v502.912C981.333333 934.485333 934.485333 981.333333 878.250667 981.333333zM375.338667 364.373333a10.666667 10.666667 0 0 0-10.922667 10.965334v502.912c0 6.229333 4.693333 10.922667 10.922667 10.922666h502.912a10.666667 10.666667 0 0 0 10.922666-10.922666V375.338667a10.666667 10.666667 0 0 0-10.922666-10.922667H375.338667z" fill="#ffffff" p-id="4257"></path><path d="M192.597333 753.322667H147.328A104.661333 104.661333 0 0 1 42.666667 648.661333V147.328A104.661333 104.661333 0 0 1 147.328 42.666667H650.24a104.661333 104.661333 0 0 1 104.618667 104.661333v49.962667c0 26.538667-20.309333 46.848-46.848 46.848a46.037333 46.037333 0 0 1-46.848-46.848V147.328a10.666667 10.666667 0 0 0-10.922667-10.965333H147.328a10.666667 10.666667 0 0 0-10.965333 10.965333V650.24c0 6.229333 4.693333 10.922667 10.965333 10.922667h45.269333c26.538667 0 46.848 20.309333 46.848 46.848 0 26.538667-21.845333 45.312-46.848 45.312z" fill="#ffffff" p-id="4258"></path></svg>
|
||||
|
After Width: | Height: | Size: 1.5 KiB |
@@ -0,0 +1 @@
|
||||
<?xml version="1.0" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg t="1715352878351" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="1499" xmlns:xlink="http://www.w3.org/1999/xlink" width="200" height="200"><path d="M624.5 786.3c92.9 0 168.2-75.3 168.2-168.2V309c0-92.4-75.3-168.2-168.2-168.2H303.6c-92.4 0-168.2 75.3-168.2 168.2v309.1c0 92.4 75.3 168.2 168.2 168.2h320.9zM178.2 618.1V309c0-69.4 56.1-125.5 125.5-125.5h320.9c69.4 0 125.5 56.1 125.5 125.5v309.1c0 69.4-56.1 125.5-125.5 125.5h-321c-69.4 0-125.4-56.1-125.4-125.5z" p-id="1500" fill="#8a8a8a"></path><path d="M849.8 295.1v361.5c0 102.7-83.6 186.3-186.3 186.3H279.1v42.7h384.4c126.3 0 229.1-102.8 229.1-229.1V295.1h-42.8zM307.9 361.8h312.3c11.8 0 21.4-9.6 21.4-21.4 0-11.8-9.6-21.4-21.4-21.4H307.9c-11.8 0-21.4 9.6-21.4 21.4 0 11.9 9.6 21.4 21.4 21.4zM307.9 484.6h312.3c11.8 0 21.4-9.6 21.4-21.4 0-11.8-9.6-21.4-21.4-21.4H307.9c-11.8 0-21.4 9.6-21.4 21.4 0 11.9 9.6 21.4 21.4 21.4z" p-id="1501" fill="#8a8a8a"></path><path d="M620.2 607.4c11.8 0 21.4-9.6 21.4-21.4 0-11.8-9.6-21.4-21.4-21.4H307.9c-11.8 0-21.4 9.6-21.4 21.4 0 11.8 9.6 21.4 21.4 21.4h312.3z" p-id="1502" fill="#8a8a8a"></path></svg>
|
||||
|
After Width: | Height: | Size: 1.2 KiB |
|
After Width: | Height: | Size: 108 KiB |
|
After Width: | Height: | Size: 87 KiB |
@@ -0,0 +1 @@
|
||||
<?xml version="1.0" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg t="1715354120346" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="3256" xmlns:xlink="http://www.w3.org/1999/xlink" width="200" height="200"><path d="M907.1 263.7H118.9c-9.1 0-16.4-7.3-16.4-16.4s7.3-16.4 16.4-16.4H907c9.1 0 16.4 7.3 16.4 16.4s-7.3 16.4-16.3 16.4z" fill="#8a8a8a" p-id="3257"></path><path d="M772.5 928.3H257.4c-27.7 0-50.2-22.5-50.2-50.2V247.2c0-9.1 7.3-16.4 16.4-16.4H801c12.1 0 21.9 9.8 21.9 21.9v625.2c0 27.8-22.6 50.4-50.4 50.4zM240 263.7v614.4c0 9.6 7.8 17.4 17.4 17.4h515.2c9.7 0 17.5-7.9 17.5-17.5V263.7H240zM657.4 131.1H368.6c-9.1 0-16.4-7.3-16.4-16.4s7.3-16.4 16.4-16.4h288.7c9.1 0 16.4 7.3 16.4 16.4s-7.3 16.4-16.3 16.4z" fill="#8a8a8a" p-id="3258"></path><path d="M416 754.5c-9.1 0-16.4-7.3-16.4-16.4V517.8c0-9.1 7.3-16.4 16.4-16.4s16.4 7.3 16.4 16.4V738c0.1 9.1-7.3 16.5-16.4 16.5z" fill="#8a8a8a" p-id="3259"></path><path d="M416 465.2c-9.1 0-16.4-7.3-16.4-16.4v-59.4c0-9.1 7.3-16.4 16.4-16.4s16.4 7.3 16.4 16.4v59.4c0.1 9.1-7.3 16.4-16.4 16.4zM604.9 754.5c-9.1 0-16.4-7.3-16.4-16.4v-67.2c0-9.1 7.3-16.4 16.4-16.4s16.4 7.3 16.4 16.4V738c0 9.1-7.3 16.5-16.4 16.5z" fill="#8a8a8a" opacity=".4" p-id="3260"></path><path d="M604.9 619.1c-9.1 0-16.4-7.3-16.4-16.4V389.4c0-9.1 7.3-16.4 16.4-16.4s16.4 7.3 16.4 16.4v213.3c0 9.1-7.3 16.4-16.4 16.4z" fill="#8a8a8a" p-id="3261"></path></svg>
|
||||
|
After Width: | Height: | Size: 1.5 KiB |
@@ -0,0 +1 @@
|
||||
<?xml version="1.0" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg t="1716345268026" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="5622" xmlns:xlink="http://www.w3.org/1999/xlink" width="200" height="200"><path d="M956.408445 419.226665a250.670939 250.670939 0 0 0-22.425219-209.609236A263.163526 263.163526 0 0 0 652.490412 85.715535 259.784384 259.784384 0 0 0 457.728923 0.008192a261.422756 261.422756 0 0 0-249.44216 178.582564 258.453206 258.453206 0 0 0-172.848261 123.901894c-57.03583 96.868753-44.031251 219.132275 32.153053 302.279661a250.670939 250.670939 0 0 0 22.32282 209.609237 263.163526 263.163526 0 0 0 281.595213 123.901893A259.067596 259.067596 0 0 0 566.271077 1023.990784a260.60357 260.60357 0 0 0 249.339762-178.889759 258.453206 258.453206 0 0 0 172.848261-123.901893c57.445423-96.868753 44.13365-218.82508-32.050655-302.074865zM566.578272 957.124721c-45.362429 0-89.496079-15.666934-124.516283-44.543243 1.638372-0.921584 4.198329-2.150363 6.143895-3.481541l206.537289-117.757998a32.35785 32.35785 0 0 0 16.895713-29.081105V474.82892l87.243317 49.97035c1.023983 0.307195 1.638372 1.228779 1.638372 2.252762v238.075953c0 105.8798-86.936122 191.689541-193.942303 191.996736zM148.588578 781.102113a189.846373 189.846373 0 0 1-23.346803-128.612213c1.535974 1.023983 4.09593 2.559956 6.143895 3.48154L337.922959 773.729439c10.444622 6.143896 23.346803 6.143896 34.098621 0l252.30931-143.664758v99.531108c0 1.023983-0.307195 1.945567-1.331177 2.559956l-208.892449 118.986778a196.297463 196.297463 0 0 1-265.518686-70.04041zM94.112704 335.97688c22.630015-39.013737 58.367008-68.81163 101.16948-84.171369V494.591784c0 11.7758 6.45109 22.93721 16.793315 28.978707l252.30931 143.767156L377.141493 716.796006a3.174346 3.174346 0 0 1-2.867152 0.307195l-208.892448-118.986777A190.870355 190.870355 0 0 1 94.215102 335.874482z m717.607001 164.861198L559.410394 357.070922 646.653711 307.20297a3.174346 3.174346 0 0 1 2.969549-0.307195l208.892449 118.986777a190.358364 190.358364 0 0 1 70.961994 262.139544 194.556693 194.556693 0 0 1-101.16948 84.171369V529.407192a31.538664 31.538664 0 0 0-16.588518-28.671513z m87.03852-129.329002c-1.74077-1.023983-4.300727-2.559956-6.246294-3.48154l-206.639687-117.757999a34.09862 34.09862 0 0 0-33.996222 0L399.566711 393.934295v-99.531108c0-1.023983 0.307195-1.945567 1.331178-2.559956l208.892449-119.089176a195.990268 195.990268 0 0 1 265.518686 70.450003c22.732414 38.706542 31.129071 84.171369 23.346803 128.305018zM352.258716 548.862861l-87.243317-49.560757a2.457558 2.457558 0 0 1-1.638372-2.252762V258.870991c0-105.8798 87.243317-191.996736 194.556692-191.689541a194.556693 194.556693 0 0 1 124.209089 44.543243c-1.638372 0.921584-4.198329 2.252762-6.143896 3.48154l-206.639687 117.757999a31.948257 31.948257 0 0 0-16.793315 29.081105l-0.307194 286.715126z m47.307995-100.759887L512 384.001664l112.535687 63.998912v127.997824l-112.228492 63.998912-112.535687-63.998912-0.307195-127.997824z" p-id="5623" fill="#707070"></path></svg>
|
||||
|
After Width: | Height: | Size: 3.0 KiB |
|
After Width: | Height: | Size: 86 KiB |
|
After Width: | Height: | Size: 121 KiB |
|
After Width: | Height: | Size: 3.5 KiB |
@@ -54,7 +54,7 @@ const currentLocale = computed(() => localeStore.currentLocale)
|
||||
<ElConfigProvider
|
||||
:namespace="variables.elNamespace"
|
||||
:locale="currentLocale.elLocale"
|
||||
:message="{ max: 1 }"
|
||||
:message="{ max: 5 }"
|
||||
:size="size"
|
||||
>
|
||||
<slot></slot>
|
||||
|
||||
@@ -10,12 +10,13 @@ const prefixCls = getPrefixCls('content-wrap')
|
||||
|
||||
defineProps({
|
||||
title: propTypes.string.def(''),
|
||||
message: propTypes.string.def('')
|
||||
message: propTypes.string.def(''),
|
||||
bodyStyle: propTypes.object.def({ padding: '20px' })
|
||||
})
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<ElCard :class="[prefixCls, 'mb-15px']" shadow="never">
|
||||
<ElCard :body-style="bodyStyle" :class="[prefixCls, 'mb-15px']" shadow="never">
|
||||
<template v-if="title" #header>
|
||||
<div class="flex items-center">
|
||||
<span class="text-16px font-700">{{ title }}</span>
|
||||
@@ -30,8 +31,6 @@ defineProps({
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
<div>
|
||||
<slot></slot>
|
||||
</div>
|
||||
<slot></slot>
|
||||
</ElCard>
|
||||
</template>
|
||||
@@ -503,9 +503,13 @@ const submit = () => {
|
||||
emit('update:modelValue', defaultValue.value)
|
||||
dialogVisible.value = false
|
||||
}
|
||||
|
||||
const inputChange = () => {
|
||||
emit('update:modelValue', defaultValue.value)
|
||||
}
|
||||
</script>
|
||||
<template>
|
||||
<el-input v-model="defaultValue" class="input-with-select" v-bind="$attrs">
|
||||
<el-input v-model="defaultValue" class="input-with-select" v-bind="$attrs" @input="inputChange">
|
||||
<template #append>
|
||||
<el-select v-model="select" placeholder="生成器" style="width: 115px">
|
||||
<el-option label="每分钟" value="0 * * * * ?" />
|
||||
|
||||
@@ -22,8 +22,8 @@ export default defineComponent({
|
||||
const dictOptions = getDictOptions(dictType)
|
||||
dictOptions.forEach((dict: DictDataType) => {
|
||||
if (dict.value === value) {
|
||||
if (dict.colorType + '' === 'primary' || dict.colorType + '' === 'default') {
|
||||
dict.colorType = ''
|
||||
if (dict.colorType + '' === 'default') {
|
||||
dict.colorType = 'info'
|
||||
}
|
||||
dictData.value = dict
|
||||
}
|
||||
|
||||
@@ -95,6 +95,7 @@ const handleCloneComponent = (component: DiyComponent<any>) => {
|
||||
.editor-left {
|
||||
z-index: 1;
|
||||
flex-shrink: 0;
|
||||
user-select: none;
|
||||
box-shadow: 8px 0 8px -8px rgb(0 0 0 / 12%);
|
||||
|
||||
:deep(.el-collapse) {
|
||||
|
||||
@@ -0,0 +1,90 @@
|
||||
<template>
|
||||
<div class="h-40px flex items-center justify-center">
|
||||
<MagicCubeEditor
|
||||
v-model="cellList"
|
||||
class="m-b-16px"
|
||||
:rows="1"
|
||||
:cols="cellCount"
|
||||
:cube-size="38"
|
||||
@hot-area-selected="handleHotAreaSelected"
|
||||
/>
|
||||
<img src="@/assets/imgs/diy/app-nav-bar-mp.png" alt="" class="h-30px w-76px" v-if="isMp" />
|
||||
</div>
|
||||
<template v-for="(cell, cellIndex) in cellList" :key="cellIndex">
|
||||
<template v-if="selectedHotAreaIndex === cellIndex">
|
||||
<el-form-item label="类型" :prop="`cell[${cellIndex}].type`">
|
||||
<el-radio-group v-model="cell.type">
|
||||
<el-radio label="text">文字</el-radio>
|
||||
<el-radio label="image">图片</el-radio>
|
||||
<el-radio label="search">搜索框</el-radio>
|
||||
</el-radio-group>
|
||||
</el-form-item>
|
||||
<!-- 1. 文字 -->
|
||||
<template v-if="cell.type === 'text'">
|
||||
<el-form-item label="内容" :prop="`cell[${cellIndex}].text`">
|
||||
<el-input v-model="cell!.text" maxlength="10" show-word-limit />
|
||||
</el-form-item>
|
||||
<el-form-item label="颜色" :prop="`cell[${cellIndex}].text`">
|
||||
<ColorInput v-model="cell!.textColor" />
|
||||
</el-form-item>
|
||||
</template>
|
||||
<!-- 2. 图片 -->
|
||||
<template v-else-if="cell.type === 'image'">
|
||||
<el-form-item label="图片" :prop="`cell[${cellIndex}].imgUrl`">
|
||||
<UploadImg v-model="cell.imgUrl" :limit="1" height="56px" width="56px">
|
||||
<template #tip>建议尺寸 56*56</template>
|
||||
</UploadImg>
|
||||
</el-form-item>
|
||||
<el-form-item label="链接" :prop="`cell[${cellIndex}].url`">
|
||||
<AppLinkInput v-model="cell.url" />
|
||||
</el-form-item>
|
||||
</template>
|
||||
<!-- 3. 搜索框 -->
|
||||
<template v-else>
|
||||
<el-form-item label="提示文字" :prop="`cell[${cellIndex}].placeholder`">
|
||||
<el-input v-model="cell.placeholder" maxlength="10" show-word-limit />
|
||||
</el-form-item>
|
||||
<el-form-item label="圆角" :prop="`cell[${cellIndex}].borderRadius`">
|
||||
<el-slider
|
||||
v-model="cell.borderRadius"
|
||||
:max="100"
|
||||
:min="0"
|
||||
show-input
|
||||
input-size="small"
|
||||
:show-input-controls="false"
|
||||
/>
|
||||
</el-form-item>
|
||||
</template>
|
||||
</template>
|
||||
</template>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { NavigationBarCellProperty } from '../config'
|
||||
import { usePropertyForm } from '@/components/DiyEditor/util'
|
||||
// 导航栏属性面板
|
||||
defineOptions({ name: 'NavigationBarCellProperty' })
|
||||
|
||||
const props = defineProps<{
|
||||
modelValue: NavigationBarCellProperty[]
|
||||
isMp: boolean
|
||||
}>()
|
||||
const emit = defineEmits(['update:modelValue'])
|
||||
const { formData: cellList } = usePropertyForm(props.modelValue, emit)
|
||||
if (!cellList.value) cellList.value = []
|
||||
|
||||
// 单元格数量:小程序6个(右侧胶囊按钮占了2个),其它平台8个
|
||||
const cellCount = computed(() => (props.isMp ? 6 : 8))
|
||||
|
||||
// 选中的热区
|
||||
const selectedHotAreaIndex = ref(0)
|
||||
const handleHotAreaSelected = (cellValue: NavigationBarCellProperty, index: number) => {
|
||||
selectedHotAreaIndex.value = index
|
||||
if (!cellValue.type) {
|
||||
cellValue.type = 'text'
|
||||
cellValue.textColor = '#111111'
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss"></style>
|
||||
@@ -2,22 +2,53 @@ import { DiyComponent } from '@/components/DiyEditor/util'
|
||||
|
||||
/** 顶部导航栏属性 */
|
||||
export interface NavigationBarProperty {
|
||||
// 页面标题
|
||||
title: string
|
||||
// 页面描述
|
||||
description: string
|
||||
// 顶部导航高度
|
||||
navBarHeight: number
|
||||
// 页面背景颜色
|
||||
backgroundColor: string
|
||||
// 页面背景图片
|
||||
backgroundImage: string
|
||||
// 背景类型
|
||||
bgType: 'color' | 'img'
|
||||
// 背景颜色
|
||||
bgColor: string
|
||||
// 图片链接
|
||||
bgImg: string
|
||||
// 样式类型:默认 | 沉浸式
|
||||
styleType: 'default' | 'immersion'
|
||||
styleType: 'normal' | 'inner'
|
||||
// 常驻显示
|
||||
alwaysShow: boolean
|
||||
// 是否显示返回按钮
|
||||
showGoBack: boolean
|
||||
// 小程序单元格列表
|
||||
mpCells: NavigationBarCellProperty[]
|
||||
// 其它平台单元格列表
|
||||
otherCells: NavigationBarCellProperty[]
|
||||
// 本地变量
|
||||
_local: {
|
||||
// 预览顶部导航(小程序)
|
||||
previewMp: boolean
|
||||
// 预览顶部导航(非小程序)
|
||||
previewOther: boolean
|
||||
}
|
||||
}
|
||||
|
||||
/** 顶部导航栏 - 单元格 属性 */
|
||||
export interface NavigationBarCellProperty {
|
||||
// 类型:文字 | 图片 | 搜索框
|
||||
type: 'text' | 'image' | 'search'
|
||||
// 宽度
|
||||
width: number
|
||||
// 高度
|
||||
height: number
|
||||
// 顶部位置
|
||||
top: number
|
||||
// 左侧位置
|
||||
left: number
|
||||
// 文字内容
|
||||
text: string
|
||||
// 文字颜色
|
||||
textColor: string
|
||||
// 图片地址
|
||||
imgUrl: string
|
||||
// 图片链接
|
||||
url: string
|
||||
// 搜索框:提示文字
|
||||
placeholder: string
|
||||
// 搜索框:边框圆角半径
|
||||
borderRadius: number
|
||||
}
|
||||
|
||||
// 定义组件
|
||||
@@ -26,13 +57,26 @@ export const component = {
|
||||
name: '顶部导航栏',
|
||||
icon: 'tabler:layout-navbar',
|
||||
property: {
|
||||
title: '页面标题',
|
||||
description: '',
|
||||
navBarHeight: 35,
|
||||
backgroundColor: '#fff',
|
||||
backgroundImage: '',
|
||||
styleType: 'default',
|
||||
bgType: 'color',
|
||||
bgColor: '#fff',
|
||||
bgImg: '',
|
||||
styleType: 'normal',
|
||||
alwaysShow: true,
|
||||
showGoBack: true
|
||||
mpCells: [
|
||||
{
|
||||
type: 'text',
|
||||
textColor: '#111111'
|
||||
}
|
||||
],
|
||||
otherCells: [
|
||||
{
|
||||
type: 'text',
|
||||
textColor: '#111111'
|
||||
}
|
||||
],
|
||||
_local: {
|
||||
previewMp: true,
|
||||
previewOther: false
|
||||
}
|
||||
}
|
||||
} as DiyComponent<NavigationBarProperty>
|
||||
@@ -1,45 +1,73 @@
|
||||
<template>
|
||||
<div
|
||||
class="navigation-bar"
|
||||
:style="{
|
||||
height: `${property.navBarHeight}px`,
|
||||
backgroundColor: property.backgroundColor,
|
||||
backgroundImage: `url(${property.backgroundImage})`
|
||||
}"
|
||||
>
|
||||
<!-- 左侧 -->
|
||||
<div class="left">
|
||||
<Icon icon="ep:arrow-left" v-show="property.showGoBack" />
|
||||
<div class="navigation-bar" :style="bgStyle">
|
||||
<div class="h-full w-full flex items-center">
|
||||
<div v-for="(cell, cellIndex) in cellList" :key="cellIndex" :style="getCellStyle(cell)">
|
||||
<span v-if="cell.type === 'text'">{{ cell.text }}</span>
|
||||
<img v-else-if="cell.type === 'image'" :src="cell.imgUrl" alt="" class="h-full w-full" />
|
||||
<SearchBar v-else :property="getSearchProp" />
|
||||
</div>
|
||||
</div>
|
||||
<!-- 中间 -->
|
||||
<div
|
||||
class="center"
|
||||
:style="{
|
||||
height: `${property.navBarHeight}px`,
|
||||
lineHeight: `${property.navBarHeight}px`
|
||||
}"
|
||||
>
|
||||
{{ property.title }}
|
||||
</div>
|
||||
<!-- 右侧 -->
|
||||
<div class="right"></div>
|
||||
<img
|
||||
v-if="property._local?.previewMp"
|
||||
src="@/assets/imgs/diy/app-nav-bar-mp.png"
|
||||
alt=""
|
||||
class="h-30px w-86px"
|
||||
/>
|
||||
</div>
|
||||
</template>
|
||||
<script setup lang="ts">
|
||||
import { NavigationBarProperty } from './config'
|
||||
import { NavigationBarCellProperty, NavigationBarProperty } from './config'
|
||||
import SearchBar from '@/components/DiyEditor/components/mobile/SearchBar/index.vue'
|
||||
import { StyleValue } from 'vue'
|
||||
import { SearchProperty } from '@/components/DiyEditor/components/mobile/SearchBar/config'
|
||||
|
||||
/** 页面顶部导航栏 */
|
||||
defineOptions({ name: 'NavigationBar' })
|
||||
|
||||
defineProps<{ property: NavigationBarProperty }>()
|
||||
const props = defineProps<{ property: NavigationBarProperty }>()
|
||||
|
||||
// 背景
|
||||
const bgStyle = computed(() => {
|
||||
const background =
|
||||
props.property.bgType === 'img' && props.property.bgImg
|
||||
? `url(${props.property.bgImg}) no-repeat top center / 100% 100%`
|
||||
: props.property.bgColor
|
||||
return { background }
|
||||
})
|
||||
// 单元格列表
|
||||
const cellList = computed(() =>
|
||||
props.property._local?.previewMp ? props.property.mpCells : props.property.otherCells
|
||||
)
|
||||
// 单元格宽度
|
||||
const cellWidth = computed(() => {
|
||||
return props.property._local?.previewMp ? (375 - 80 - 86) / 6 : (375 - 90) / 8
|
||||
})
|
||||
// 获得单元格样式
|
||||
const getCellStyle = (cell: NavigationBarCellProperty) => {
|
||||
return {
|
||||
width: cell.width * cellWidth.value + (cell.width - 1) * 10 + 'px',
|
||||
left: cell.left * cellWidth.value + (cell.left + 1) * 10 + 'px',
|
||||
position: 'absolute'
|
||||
} as StyleValue
|
||||
}
|
||||
// 获得搜索框属性
|
||||
const getSearchProp = (cell: NavigationBarCellProperty) => {
|
||||
return {
|
||||
height: 30,
|
||||
showScan: false,
|
||||
placeholder: cell.placeholder,
|
||||
borderRadius: cell.borderRadius
|
||||
} as SearchProperty
|
||||
}
|
||||
</script>
|
||||
<style lang="scss" scoped>
|
||||
.navigation-bar {
|
||||
display: flex;
|
||||
height: 35px;
|
||||
height: 50px;
|
||||
background: #fff;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
padding: 0 6px;
|
||||
|
||||
/* 左边 */
|
||||
.left {
|
||||
|
||||
@@ -1,53 +1,73 @@
|
||||
<template>
|
||||
<el-form label-width="80px" :model="formData" :rules="rules">
|
||||
<el-form-item label="页面标题" prop="title">
|
||||
<el-input v-model="formData!.title" placeholder="页面标题" maxlength="25" show-word-limit />
|
||||
</el-form-item>
|
||||
<el-form-item label="页面描述" prop="description">
|
||||
<el-input
|
||||
type="textarea"
|
||||
v-model="formData!.description"
|
||||
placeholder="用户通过微信分享给朋友时,会自动显示页面描述"
|
||||
/>
|
||||
</el-form-item>
|
||||
<el-form-item label="样式" prop="styleType">
|
||||
<el-radio-group v-model="formData!.styleType">
|
||||
<el-radio label="default">默认</el-radio>
|
||||
<el-radio label="immersion">沉浸式</el-radio>
|
||||
<el-radio label="normal">标准</el-radio>
|
||||
<el-tooltip
|
||||
content="沉侵式头部仅支持微信小程序、APP,建议页面第一个组件为图片展示类组件"
|
||||
placement="top"
|
||||
>
|
||||
<el-radio label="inner">沉浸式</el-radio>
|
||||
</el-tooltip>
|
||||
</el-radio-group>
|
||||
</el-form-item>
|
||||
<el-form-item label="常驻显示" prop="alwaysShow" v-if="formData.styleType === 'immersion'">
|
||||
<el-form-item label="常驻显示" prop="alwaysShow" v-if="formData.styleType === 'inner'">
|
||||
<el-radio-group v-model="formData!.alwaysShow">
|
||||
<el-radio :label="false">关闭</el-radio>
|
||||
<el-radio :label="true">开启</el-radio>
|
||||
<el-tooltip content="常驻显示关闭后,头部小组件将在页面滑动时淡入" placement="top">
|
||||
<el-radio :label="true">开启</el-radio>
|
||||
</el-tooltip>
|
||||
</el-radio-group>
|
||||
</el-form-item>
|
||||
<el-form-item label="高度" prop="navBarHeight">
|
||||
<el-slider
|
||||
v-model="formData!.navBarHeight"
|
||||
:max="100"
|
||||
:min="35"
|
||||
show-input
|
||||
input-size="small"
|
||||
/>
|
||||
<el-form-item label="背景类型" prop="bgType">
|
||||
<el-radio-group v-model="formData.bgType">
|
||||
<el-radio label="color">纯色</el-radio>
|
||||
<el-radio label="img">图片</el-radio>
|
||||
</el-radio-group>
|
||||
</el-form-item>
|
||||
<el-form-item label="返回按钮" prop="showGoBack">
|
||||
<el-switch v-model="formData!.showGoBack" />
|
||||
<el-form-item label="背景颜色" prop="bgColor" v-if="formData.bgType === 'color'">
|
||||
<ColorInput v-model="formData.bgColor" />
|
||||
</el-form-item>
|
||||
<el-form-item label="背景颜色" prop="backgroundColor">
|
||||
<ColorInput v-model="formData!.backgroundColor" />
|
||||
</el-form-item>
|
||||
<el-form-item label="背景图片" prop="backgroundImage">
|
||||
<UploadImg v-model="formData!.backgroundImage" :limit="1">
|
||||
<template #tip>建议宽度 750px</template>
|
||||
</UploadImg>
|
||||
<el-form-item label="背景图片" prop="bgImg" v-else>
|
||||
<UploadImg v-model="formData.bgImg" :limit="1" width="56px" height="56px" />
|
||||
</el-form-item>
|
||||
<el-card class="property-group" shadow="never">
|
||||
<template #header>
|
||||
<div class="flex items-center justify-between">
|
||||
<span>内容(小程序)</span>
|
||||
<el-form-item prop="_local.previewMp" class="m-b-0!">
|
||||
<el-checkbox
|
||||
v-model="formData._local.previewMp"
|
||||
@change="formData._local.previewOther = !formData._local.previewMp"
|
||||
>预览</el-checkbox
|
||||
>
|
||||
</el-form-item>
|
||||
</div>
|
||||
</template>
|
||||
<NavigationBarCellProperty v-model="formData.mpCells" is-mp />
|
||||
</el-card>
|
||||
<el-card class="property-group" shadow="never">
|
||||
<template #header>
|
||||
<div class="flex items-center justify-between">
|
||||
<span>内容(非小程序)</span>
|
||||
<el-form-item prop="_local.previewOther" class="m-b-0!">
|
||||
<el-checkbox
|
||||
v-model="formData._local.previewOther"
|
||||
@change="formData._local.previewMp = !formData._local.previewOther"
|
||||
>预览</el-checkbox
|
||||
>
|
||||
</el-form-item>
|
||||
</div>
|
||||
</template>
|
||||
<NavigationBarCellProperty v-model="formData.otherCells" :is-mp="false" />
|
||||
</el-card>
|
||||
</el-form>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { NavigationBarProperty } from './config'
|
||||
import { usePropertyForm } from '@/components/DiyEditor/util'
|
||||
import NavigationBarCellProperty from '@/components/DiyEditor/components/mobile/NavigationBar/components/CellProperty.vue'
|
||||
// 导航栏属性面板
|
||||
defineOptions({ name: 'NavigationBarProperty' })
|
||||
// 表单校验
|
||||
@@ -58,6 +78,9 @@ const rules = {
|
||||
const props = defineProps<{ modelValue: NavigationBarProperty }>()
|
||||
const emit = defineEmits(['update:modelValue'])
|
||||
const { formData } = usePropertyForm(props.modelValue, emit)
|
||||
if (!formData.value._local) {
|
||||
formData.value._local = { previewMp: true, previewOther: false }
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss"></style>
|
||||
@@ -96,11 +96,6 @@ const editorConfig = computed((): IEditorConfig => {
|
||||
// 选择文件时的类型限制,默认为 ['image/*'] 。如不想限制,则设置为 []
|
||||
allowedFileTypes: ['image/*'],
|
||||
|
||||
// 自定义上传参数,例如传递验证的 token 等。参数会被添加到 formData 中,一起上传到服务端。
|
||||
meta: { updateSupport: 0 },
|
||||
// 将 meta 拼接到 url 参数中,默认 false
|
||||
metaWithUrl: true,
|
||||
|
||||
// 自定义增加 http header
|
||||
headers: {
|
||||
Accept: '*',
|
||||
@@ -108,9 +103,6 @@ const editorConfig = computed((): IEditorConfig => {
|
||||
'tenant-id': getTenantId()
|
||||
},
|
||||
|
||||
// 跨域是否传递 cookie ,默认为 false
|
||||
withCredentials: true,
|
||||
|
||||
// 超时时间,默认为 10 秒
|
||||
timeout: 5 * 1000, // 5 秒
|
||||
|
||||
@@ -119,7 +111,7 @@ const editorConfig = computed((): IEditorConfig => {
|
||||
|
||||
// 上传之前触发
|
||||
onBeforeUpload(file: File) {
|
||||
console.log(file)
|
||||
// console.log(file)
|
||||
return file
|
||||
},
|
||||
// 上传进度的回调函数
|
||||
@@ -142,6 +134,54 @@ const editorConfig = computed((): IEditorConfig => {
|
||||
customInsert(res: any, insertFn: InsertFnType) {
|
||||
insertFn(res.data, 'image', res.data)
|
||||
}
|
||||
},
|
||||
['uploadVideo']: {
|
||||
server: import.meta.env.VITE_UPLOAD_URL,
|
||||
// 单个文件的最大体积限制,默认为 10M
|
||||
maxFileSize: 10 * 1024 * 1024,
|
||||
// 最多可上传几个文件,默认为 100
|
||||
maxNumberOfFiles: 10,
|
||||
// 选择文件时的类型限制,默认为 ['video/*'] 。如不想限制,则设置为 []
|
||||
allowedFileTypes: ['video/*'],
|
||||
|
||||
// 自定义增加 http header
|
||||
headers: {
|
||||
Accept: '*',
|
||||
Authorization: 'Bearer ' + getAccessToken(),
|
||||
'tenant-id': getTenantId()
|
||||
},
|
||||
|
||||
// 超时时间,默认为 30 秒
|
||||
timeout: 15 * 1000, // 15 秒
|
||||
|
||||
// form-data fieldName,后端接口参数名称,默认值wangeditor-uploaded-image
|
||||
fieldName: 'file',
|
||||
|
||||
// 上传之前触发
|
||||
onBeforeUpload(file: File) {
|
||||
// console.log(file)
|
||||
return file
|
||||
},
|
||||
// 上传进度的回调函数
|
||||
onProgress(progress: number) {
|
||||
// progress 是 0-100 的数字
|
||||
console.log('progress', progress)
|
||||
},
|
||||
onSuccess(file: File, res: any) {
|
||||
console.log('onSuccess', file, res)
|
||||
},
|
||||
onFailed(file: File, res: any) {
|
||||
alert(res.message)
|
||||
console.log('onFailed', file, res)
|
||||
},
|
||||
onError(file: File, err: any, res: any) {
|
||||
alert(err.message)
|
||||
console.error('onError', file, err, res)
|
||||
},
|
||||
// 自定义插入图片
|
||||
customInsert(res: any, insertFn: InsertFnType) {
|
||||
insertFn(res.data, 'mp4', res.data)
|
||||
}
|
||||
}
|
||||
},
|
||||
uploadImgShowBase64: true
|
||||
|
||||
@@ -0,0 +1,4 @@
|
||||
import { useFormCreateDesigner } from './src/useFormCreateDesigner'
|
||||
import { useApiSelect } from './src/components/useApiSelect'
|
||||
|
||||
export { useFormCreateDesigner, useApiSelect }
|
||||
@@ -0,0 +1,59 @@
|
||||
<!-- 数据字典 Select 选择器 -->
|
||||
<template>
|
||||
<el-select v-if="selectType === 'select'" class="w-1/1" v-bind="attrs">
|
||||
<el-option
|
||||
v-for="(dict, index) in getDictOptions"
|
||||
:key="index"
|
||||
:label="dict.label"
|
||||
:value="dict.value"
|
||||
/>
|
||||
</el-select>
|
||||
<el-radio-group v-if="selectType === 'radio'" class="w-1/1" v-bind="attrs">
|
||||
<el-radio v-for="(dict, index) in getDictOptions" :key="index" :value="dict.value">
|
||||
{{ dict.label }}
|
||||
</el-radio>
|
||||
</el-radio-group>
|
||||
<el-checkbox-group v-if="selectType === 'checkbox'" class="w-1/1" v-bind="attrs">
|
||||
<el-checkbox
|
||||
v-for="(dict, index) in getDictOptions"
|
||||
:key="index"
|
||||
:label="dict.label"
|
||||
:value="dict.value"
|
||||
/>
|
||||
</el-checkbox-group>
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import { getBoolDictOptions, getIntDictOptions, getStrDictOptions } from '@/utils/dict'
|
||||
|
||||
defineOptions({ name: 'DictSelect' })
|
||||
|
||||
const attrs = useAttrs()
|
||||
|
||||
// 接受父组件参数
|
||||
interface Props {
|
||||
dictType: string // 字典类型
|
||||
valueType?: 'str' | 'int' | 'bool' // 字典值类型
|
||||
selectType?: 'select' | 'radio' | 'checkbox' // 选择器类型,下拉框 select、多选框 checkbox、单选框 radio
|
||||
formCreateInject?: any
|
||||
}
|
||||
|
||||
const props = withDefaults(defineProps<Props>(), {
|
||||
valueType: 'str',
|
||||
selectType: 'select'
|
||||
})
|
||||
|
||||
// 获得字典配置
|
||||
const getDictOptions = computed(() => {
|
||||
switch (props.valueType) {
|
||||
case 'str':
|
||||
return getStrDictOptions(props.dictType)
|
||||
case 'int':
|
||||
return getIntDictOptions(props.dictType)
|
||||
case 'bool':
|
||||
return getBoolDictOptions(props.dictType)
|
||||
default:
|
||||
return []
|
||||
}
|
||||
})
|
||||
</script>
|
||||
@@ -0,0 +1,248 @@
|
||||
import request from '@/config/axios'
|
||||
import { isEmpty } from '@/utils/is'
|
||||
import { ApiSelectProps } from '@/components/FormCreate/src/type'
|
||||
import { jsonParse } from '@/utils'
|
||||
|
||||
export const useApiSelect = (option: ApiSelectProps) => {
|
||||
return defineComponent({
|
||||
name: option.name,
|
||||
props: {
|
||||
// 选项标签
|
||||
labelField: {
|
||||
type: String,
|
||||
default: () => option.labelField ?? 'label'
|
||||
},
|
||||
// 选项的值
|
||||
valueField: {
|
||||
type: String,
|
||||
default: () => option.valueField ?? 'value'
|
||||
},
|
||||
// api 接口
|
||||
url: {
|
||||
type: String,
|
||||
default: () => option.url ?? ''
|
||||
},
|
||||
// 请求类型
|
||||
method: {
|
||||
type: String,
|
||||
default: 'GET'
|
||||
},
|
||||
// 选项解析函数
|
||||
parseFunc: {
|
||||
type: String,
|
||||
default: ''
|
||||
},
|
||||
// 请求参数
|
||||
data: {
|
||||
type: String,
|
||||
default: ''
|
||||
},
|
||||
// 选择器类型,下拉框 select、多选框 checkbox、单选框 radio
|
||||
selectType: {
|
||||
type: String,
|
||||
default: 'select'
|
||||
},
|
||||
// 是否多选
|
||||
multiple: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
},
|
||||
// 是否远程搜索
|
||||
remote: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
},
|
||||
// 远程搜索时携带的参数
|
||||
remoteField: {
|
||||
type: String,
|
||||
default: 'label'
|
||||
}
|
||||
},
|
||||
setup(props) {
|
||||
const attrs = useAttrs()
|
||||
const options = ref<any[]>([]) // 下拉数据
|
||||
const loading = ref(false) // 是否正在从远程获取数据
|
||||
const queryParam = ref<any>() // 当前输入的值
|
||||
const getOptions = async () => {
|
||||
options.value = []
|
||||
// 接口选择器
|
||||
if (isEmpty(props.url)) {
|
||||
return
|
||||
}
|
||||
switch (props.method) {
|
||||
case 'GET':
|
||||
let url: string = props.url
|
||||
if (props.remote) {
|
||||
url = `${url}?${props.remoteField}=${queryParam.value}`
|
||||
}
|
||||
parseOptions(await request.get({ url: url }))
|
||||
break
|
||||
case 'POST':
|
||||
const data: any = jsonParse(props.data)
|
||||
if (props.remote) {
|
||||
data[props.remoteField] = queryParam.value
|
||||
}
|
||||
parseOptions(await request.post({ url: props.url, data: data }))
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
function parseOptions(data: any) {
|
||||
// 情况一:如果有自定义解析函数优先使用自定义解析
|
||||
if (!isEmpty(props.parseFunc)) {
|
||||
options.value = parseFunc()?.(data)
|
||||
return
|
||||
}
|
||||
// 情况二:返回的直接是一个列表
|
||||
if (Array.isArray(data)) {
|
||||
parseOptions0(data)
|
||||
return
|
||||
}
|
||||
// 情况二:返回的是分页数据,尝试读取 list
|
||||
data = data.list
|
||||
if (!!data && Array.isArray(data)) {
|
||||
parseOptions0(data)
|
||||
return
|
||||
}
|
||||
// 情况三:不是 yudao-vue-pro 标准返回
|
||||
console.warn(
|
||||
`接口[${props.url}] 返回结果不是 yudao-vue-pro 标准返回建议采用自定义解析函数处理`
|
||||
)
|
||||
}
|
||||
|
||||
function parseOptions0(data: any[]) {
|
||||
if (Array.isArray(data)) {
|
||||
options.value = data.map((item: any) => ({
|
||||
label: parseExpression(item, props.labelField),
|
||||
value: parseExpression(item, props.valueField)
|
||||
}))
|
||||
return
|
||||
}
|
||||
console.warn(`接口[${props.url}] 返回结果不是一个数组`)
|
||||
}
|
||||
|
||||
function parseFunc() {
|
||||
let parse: any = null
|
||||
if (!!props.parseFunc) {
|
||||
// 解析字符串函数
|
||||
parse = new Function(`return ${props.parseFunc}`)()
|
||||
}
|
||||
return parse
|
||||
}
|
||||
|
||||
function parseExpression(data: any, template: string) {
|
||||
// 检测是否使用了表达式
|
||||
if (template.indexOf('${') === -1) {
|
||||
return data[template]
|
||||
}
|
||||
// 正则表达式匹配模板字符串中的 ${...}
|
||||
const pattern = /\$\{([^}]*)}/g
|
||||
// 使用replace函数配合正则表达式和回调函数来进行替换
|
||||
return template.replace(pattern, (_, expr) => {
|
||||
// expr 是匹配到的 ${} 内的表达式(这里是属性名),从 data 中获取对应的值
|
||||
const result = data[expr.trim()] // 去除前后空白,以防用户输入带空格的属性名
|
||||
if (!result) {
|
||||
console.warn(
|
||||
`接口选择器选项模版[${template}][${expr.trim()}] 解析值失败结果为[${result}], 请检查属性名称是否存在于接口返回值中,存在则忽略此条!!!`
|
||||
)
|
||||
}
|
||||
return result
|
||||
})
|
||||
}
|
||||
|
||||
const remoteMethod = async (query: any) => {
|
||||
if (!query) {
|
||||
return
|
||||
}
|
||||
loading.value = true
|
||||
try {
|
||||
queryParam.value = query
|
||||
await getOptions()
|
||||
} finally {
|
||||
loading.value = false
|
||||
}
|
||||
}
|
||||
|
||||
onMounted(async () => {
|
||||
await getOptions()
|
||||
})
|
||||
|
||||
const buildSelect = () => {
|
||||
if (props.multiple) {
|
||||
// fix:多写此步是为了解决 multiple 属性问题
|
||||
return (
|
||||
<el-select
|
||||
class="w-1/1"
|
||||
multiple
|
||||
loading={loading.value}
|
||||
{...attrs}
|
||||
remote={props.remote}
|
||||
{...(props.remote && { remoteMethod: remoteMethod })}
|
||||
>
|
||||
{options.value.map((item, index) => (
|
||||
<el-option key={index} label={item.label} value={item.value} />
|
||||
))}
|
||||
</el-select>
|
||||
)
|
||||
}
|
||||
debugger
|
||||
return (
|
||||
<el-select
|
||||
class="w-1/1"
|
||||
loading={loading.value}
|
||||
{...attrs}
|
||||
remote={props.remote}
|
||||
{...(props.remote && { remoteMethod: remoteMethod })}
|
||||
>
|
||||
{options.value.map((item, index) => (
|
||||
<el-option key={index} label={item.label} value={item.value} />
|
||||
))}
|
||||
</el-select>
|
||||
)
|
||||
}
|
||||
const buildCheckbox = () => {
|
||||
if (isEmpty(options.value)) {
|
||||
options.value = [
|
||||
{ label: '选项1', value: '选项1' },
|
||||
{ label: '选项2', value: '选项2' }
|
||||
]
|
||||
}
|
||||
return (
|
||||
<el-checkbox-group class="w-1/1" {...attrs}>
|
||||
{options.value.map((item, index) => (
|
||||
<el-checkbox key={index} label={item.label} value={item.value} />
|
||||
))}
|
||||
</el-checkbox-group>
|
||||
)
|
||||
}
|
||||
const buildRadio = () => {
|
||||
if (isEmpty(options.value)) {
|
||||
options.value = [
|
||||
{ label: '选项1', value: '选项1' },
|
||||
{ label: '选项2', value: '选项2' }
|
||||
]
|
||||
}
|
||||
return (
|
||||
<el-radio-group class="w-1/1" {...attrs}>
|
||||
{options.value.map((item, index) => (
|
||||
<el-radio key={index} value={item.value}>
|
||||
{item.label}
|
||||
</el-radio>
|
||||
))}
|
||||
</el-radio-group>
|
||||
)
|
||||
}
|
||||
return () => (
|
||||
<>
|
||||
{props.selectType === 'select'
|
||||
? buildSelect()
|
||||
: props.selectType === 'radio'
|
||||
? buildRadio()
|
||||
: props.selectType === 'checkbox'
|
||||
? buildCheckbox()
|
||||
: buildSelect()}
|
||||
</>
|
||||
)
|
||||
}
|
||||
})
|
||||
}
|
||||
@@ -0,0 +1,15 @@
|
||||
import { useUploadFileRule } from './useUploadFileRule'
|
||||
import { useUploadImgRule } from './useUploadImgRule'
|
||||
import { useUploadImgsRule } from './useUploadImgsRule'
|
||||
import { useDictSelectRule } from './useDictSelectRule'
|
||||
import { useEditorRule } from './useEditorRule'
|
||||
import { useSelectRule } from './useSelectRule'
|
||||
|
||||
export {
|
||||
useUploadFileRule,
|
||||
useUploadImgRule,
|
||||
useUploadImgsRule,
|
||||
useDictSelectRule,
|
||||
useEditorRule,
|
||||
useSelectRule
|
||||
}
|
||||
@@ -0,0 +1,181 @@
|
||||
const selectRule = [
|
||||
{
|
||||
type: 'select',
|
||||
field: 'selectType',
|
||||
title: '选择器类型',
|
||||
value: 'select',
|
||||
options: [
|
||||
{ label: '下拉框', value: 'select' },
|
||||
{ label: '单选框', value: 'radio' },
|
||||
{ label: '多选框', value: 'checkbox' }
|
||||
],
|
||||
// 参考 https://www.form-create.com/v3/guide/control 组件联动,单选框和多选框不需要多选属性
|
||||
control: [
|
||||
{
|
||||
value: 'select',
|
||||
condition: '==',
|
||||
method: 'hidden',
|
||||
rule: [
|
||||
'multiple',
|
||||
'clearable',
|
||||
'collapseTags',
|
||||
'multipleLimit',
|
||||
'allowCreate',
|
||||
'filterable',
|
||||
'noMatchText',
|
||||
'remote',
|
||||
'remoteMethod',
|
||||
'reserveKeyword',
|
||||
'defaultFirstOption',
|
||||
'automaticDropdown'
|
||||
]
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
type: 'switch',
|
||||
field: 'filterable',
|
||||
title: '是否可搜索'
|
||||
},
|
||||
{ type: 'switch', field: 'multiple', title: '是否多选' },
|
||||
{
|
||||
type: 'switch',
|
||||
field: 'disabled',
|
||||
title: '是否禁用'
|
||||
},
|
||||
{ type: 'switch', field: 'clearable', title: '是否可以清空选项' },
|
||||
{
|
||||
type: 'switch',
|
||||
field: 'collapseTags',
|
||||
title: '多选时是否将选中值按文字的形式展示'
|
||||
},
|
||||
{
|
||||
type: 'inputNumber',
|
||||
field: 'multipleLimit',
|
||||
title: '多选时用户最多可以选择的项目数,为 0 则不限制',
|
||||
props: { min: 0 }
|
||||
},
|
||||
{
|
||||
type: 'input',
|
||||
field: 'autocomplete',
|
||||
title: 'autocomplete 属性'
|
||||
},
|
||||
{ type: 'input', field: 'placeholder', title: '占位符' },
|
||||
{ type: 'switch', field: 'allowCreate', title: '是否允许用户创建新条目' },
|
||||
{
|
||||
type: 'input',
|
||||
field: 'noMatchText',
|
||||
title: '搜索条件无匹配时显示的文字'
|
||||
},
|
||||
{ type: 'input', field: 'noDataText', title: '选项为空时显示的文字' },
|
||||
{
|
||||
type: 'switch',
|
||||
field: 'reserveKeyword',
|
||||
title: '多选且可搜索时,是否在选中一个选项后保留当前的搜索关键词'
|
||||
},
|
||||
{
|
||||
type: 'switch',
|
||||
field: 'defaultFirstOption',
|
||||
title: '在输入框按下回车,选择第一个匹配项'
|
||||
},
|
||||
{
|
||||
type: 'switch',
|
||||
field: 'popperAppendToBody',
|
||||
title: '是否将弹出框插入至 body 元素',
|
||||
value: true
|
||||
},
|
||||
{
|
||||
type: 'switch',
|
||||
field: 'automaticDropdown',
|
||||
title: '对于不可搜索的 Select,是否在输入框获得焦点后自动弹出选项菜单'
|
||||
}
|
||||
]
|
||||
|
||||
const apiSelectRule = [
|
||||
{
|
||||
type: 'input',
|
||||
field: 'url',
|
||||
title: 'url 地址',
|
||||
props: {
|
||||
placeholder: '/system/user/simple-list'
|
||||
}
|
||||
},
|
||||
{
|
||||
type: 'select',
|
||||
field: 'method',
|
||||
title: '请求类型',
|
||||
value: 'GET',
|
||||
options: [
|
||||
{ label: 'GET', value: 'GET' },
|
||||
{ label: 'POST', value: 'POST' }
|
||||
],
|
||||
control: [
|
||||
{
|
||||
value: 'GET',
|
||||
condition: '!=',
|
||||
method: 'hidden',
|
||||
rule: [
|
||||
{
|
||||
type: 'input',
|
||||
field: 'data',
|
||||
title: '请求参数 JSON 格式',
|
||||
props: {
|
||||
autosize: true,
|
||||
type: 'textarea',
|
||||
placeholder: '{"type": 1}'
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
type: 'input',
|
||||
field: 'labelField',
|
||||
title: 'label 属性',
|
||||
info: '可以使用 el 表达式:${属性},来实现复杂数据组合。如:${nickname}-${id}',
|
||||
props: {
|
||||
placeholder: 'nickname'
|
||||
}
|
||||
},
|
||||
{
|
||||
type: 'input',
|
||||
field: 'valueField',
|
||||
title: 'value 属性',
|
||||
info: '可以使用 el 表达式:${属性},来实现复杂数据组合。如:${nickname}-${id}',
|
||||
props: {
|
||||
placeholder: 'id'
|
||||
}
|
||||
},
|
||||
{
|
||||
type: 'input',
|
||||
field: 'parseFunc',
|
||||
title: '选项解析函数',
|
||||
info: `data 为接口返回值,需要写一个匿名函数解析返回值为选择器 options 列表
|
||||
(data: any)=>{ label: string; value: any }[]`,
|
||||
props: {
|
||||
autosize: true,
|
||||
rows: { minRows: 2, maxRows: 6 },
|
||||
type: 'textarea',
|
||||
placeholder: `
|
||||
function (data) {
|
||||
console.log(data)
|
||||
return data.list.map(item=> ({label: item.nickname,value: item.id}))
|
||||
}`
|
||||
}
|
||||
},
|
||||
{
|
||||
type: 'switch',
|
||||
field: 'remote',
|
||||
info: '是否可搜索',
|
||||
title: '其中的选项是否从服务器远程加载'
|
||||
},
|
||||
{
|
||||
type: 'input',
|
||||
field: 'remoteField',
|
||||
title: '请求参数',
|
||||
info: '远程请求时请求携带的参数名称,如:name'
|
||||
}
|
||||
]
|
||||
|
||||
export { selectRule, apiSelectRule }
|
||||
@@ -0,0 +1,64 @@
|
||||
import { generateUUID } from '@/utils'
|
||||
import * as DictDataApi from '@/api/system/dict/dict.type'
|
||||
import { localeProps, makeRequiredRule } from '@/components/FormCreate/src/utils'
|
||||
import { selectRule } from '@/components/FormCreate/src/config/selectRule'
|
||||
import { cloneDeep } from 'lodash-es'
|
||||
|
||||
/**
|
||||
* 字典选择器规则,如果规则使用到动态数据则需要单独配置不能使用 useSelectRule
|
||||
*/
|
||||
export const useDictSelectRule = () => {
|
||||
const label = '字典选择器'
|
||||
const name = 'DictSelect'
|
||||
const rules = cloneDeep(selectRule)
|
||||
const dictOptions = ref<{ label: string; value: string }[]>([]) // 字典类型下拉数据
|
||||
onMounted(async () => {
|
||||
const data = await DictDataApi.getSimpleDictTypeList()
|
||||
if (!data || data.length === 0) {
|
||||
return
|
||||
}
|
||||
dictOptions.value =
|
||||
data?.map((item: DictDataApi.DictTypeVO) => ({
|
||||
label: item.name,
|
||||
value: item.type
|
||||
})) ?? []
|
||||
})
|
||||
return {
|
||||
icon: 'icon-doc-text',
|
||||
label,
|
||||
name,
|
||||
rule() {
|
||||
return {
|
||||
type: name,
|
||||
field: generateUUID(),
|
||||
title: label,
|
||||
info: '',
|
||||
$required: false
|
||||
}
|
||||
},
|
||||
props(_, { t }) {
|
||||
return localeProps(t, name + '.props', [
|
||||
makeRequiredRule(),
|
||||
{
|
||||
type: 'select',
|
||||
field: 'dictType',
|
||||
title: '字典类型',
|
||||
value: '',
|
||||
options: dictOptions.value
|
||||
},
|
||||
{
|
||||
type: 'select',
|
||||
field: 'dictValueType',
|
||||
title: '字典值类型',
|
||||
value: 'str',
|
||||
options: [
|
||||
{ label: '数字', value: 'int' },
|
||||
{ label: '字符串', value: 'str' },
|
||||
{ label: '布尔值', value: 'bool' }
|
||||
]
|
||||
},
|
||||
...rules
|
||||
])
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,32 @@
|
||||
import { generateUUID } from '@/utils'
|
||||
import { localeProps, makeRequiredRule } from '@/components/FormCreate/src/utils'
|
||||
|
||||
export const useEditorRule = () => {
|
||||
const label = '富文本'
|
||||
const name = 'Editor'
|
||||
return {
|
||||
icon: 'icon-editor',
|
||||
label,
|
||||
name,
|
||||
rule() {
|
||||
return {
|
||||
type: name,
|
||||
field: generateUUID(),
|
||||
title: label,
|
||||
info: '',
|
||||
$required: false
|
||||
}
|
||||
},
|
||||
props(_, { t }) {
|
||||
return localeProps(t, name + '.props', [
|
||||
makeRequiredRule(),
|
||||
{
|
||||
type: 'input',
|
||||
field: 'height',
|
||||
title: '高度'
|
||||
},
|
||||
{ type: 'switch', field: 'readonly', title: '是否只读' }
|
||||
])
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,36 @@
|
||||
import { generateUUID } from '@/utils'
|
||||
import { localeProps, makeRequiredRule } from '@/components/FormCreate/src/utils'
|
||||
import { selectRule } from '@/components/FormCreate/src/config/selectRule'
|
||||
import { SelectRuleOption } from '@/components/FormCreate/src/type'
|
||||
import { cloneDeep } from 'lodash-es'
|
||||
|
||||
/**
|
||||
* 通用选择器规则 hook
|
||||
*
|
||||
* @param option 规则配置
|
||||
*/
|
||||
export const useSelectRule = (option: SelectRuleOption) => {
|
||||
const label = option.label
|
||||
const name = option.name
|
||||
const rules = cloneDeep(selectRule)
|
||||
return {
|
||||
icon: option.icon,
|
||||
label,
|
||||
name,
|
||||
rule() {
|
||||
return {
|
||||
type: name,
|
||||
field: generateUUID(),
|
||||
title: label,
|
||||
info: '',
|
||||
$required: false
|
||||
}
|
||||
},
|
||||
props(_, { t }) {
|
||||
if (!option.props) {
|
||||
option.props = []
|
||||
}
|
||||
return localeProps(t, name + '.props', [makeRequiredRule(), ...option.props, ...rules])
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,80 @@
|
||||
import { generateUUID } from '@/utils'
|
||||
import { localeProps, makeRequiredRule } from '@/components/FormCreate/src/utils'
|
||||
|
||||
export const useUploadFileRule = () => {
|
||||
const label = '文件上传'
|
||||
const name = 'UploadFile'
|
||||
return {
|
||||
icon: 'icon-upload',
|
||||
label,
|
||||
name,
|
||||
rule() {
|
||||
return {
|
||||
type: name,
|
||||
field: generateUUID(),
|
||||
title: label,
|
||||
info: '',
|
||||
$required: false
|
||||
}
|
||||
},
|
||||
props(_, { t }) {
|
||||
return localeProps(t, name + '.props', [
|
||||
makeRequiredRule(),
|
||||
{
|
||||
type: 'select',
|
||||
field: 'fileType',
|
||||
title: '文件类型',
|
||||
value: ['doc', 'xls', 'ppt', 'txt', 'pdf'],
|
||||
options: [
|
||||
{ label: 'doc', value: 'doc' },
|
||||
{ label: 'xls', value: 'xls' },
|
||||
{ label: 'ppt', value: 'ppt' },
|
||||
{ label: 'txt', value: 'txt' },
|
||||
{ label: 'pdf', value: 'pdf' }
|
||||
],
|
||||
props: {
|
||||
multiple: true
|
||||
}
|
||||
},
|
||||
{
|
||||
type: 'switch',
|
||||
field: 'autoUpload',
|
||||
title: '是否在选取文件后立即进行上传',
|
||||
value: true
|
||||
},
|
||||
{
|
||||
type: 'switch',
|
||||
field: 'drag',
|
||||
title: '拖拽上传',
|
||||
value: false
|
||||
},
|
||||
{
|
||||
type: 'switch',
|
||||
field: 'isShowTip',
|
||||
title: '是否显示提示',
|
||||
value: true
|
||||
},
|
||||
{
|
||||
type: 'inputNumber',
|
||||
field: 'fileSize',
|
||||
title: '大小限制(MB)',
|
||||
value: 5,
|
||||
props: { min: 0 }
|
||||
},
|
||||
{
|
||||
type: 'inputNumber',
|
||||
field: 'limit',
|
||||
title: '数量限制',
|
||||
value: 5,
|
||||
props: { min: 0 }
|
||||
},
|
||||
{
|
||||
type: 'switch',
|
||||
field: 'disabled',
|
||||
title: '是否禁用',
|
||||
value: false
|
||||
}
|
||||
])
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,89 @@
|
||||
import { generateUUID } from '@/utils'
|
||||
import { localeProps, makeRequiredRule } from '@/components/FormCreate/src/utils'
|
||||
|
||||
export const useUploadImgRule = () => {
|
||||
const label = '单图上传'
|
||||
const name = 'UploadImg'
|
||||
return {
|
||||
icon: 'icon-upload',
|
||||
label,
|
||||
name,
|
||||
rule() {
|
||||
return {
|
||||
type: name,
|
||||
field: generateUUID(),
|
||||
title: label,
|
||||
info: '',
|
||||
$required: false
|
||||
}
|
||||
},
|
||||
props(_, { t }) {
|
||||
return localeProps(t, name + '.props', [
|
||||
makeRequiredRule(),
|
||||
{
|
||||
type: 'switch',
|
||||
field: 'drag',
|
||||
title: '拖拽上传',
|
||||
value: false
|
||||
},
|
||||
{
|
||||
type: 'select',
|
||||
field: 'fileType',
|
||||
title: '图片类型限制',
|
||||
value: ['image/jpeg', 'image/png', 'image/gif'],
|
||||
options: [
|
||||
{ label: 'image/apng', value: 'image/apng' },
|
||||
{ label: 'image/bmp', value: 'image/bmp' },
|
||||
{ label: 'image/gif', value: 'image/gif' },
|
||||
{ label: 'image/jpeg', value: 'image/jpeg' },
|
||||
{ label: 'image/pjpeg', value: 'image/pjpeg' },
|
||||
{ label: 'image/svg+xml', value: 'image/svg+xml' },
|
||||
{ label: 'image/tiff', value: 'image/tiff' },
|
||||
{ label: 'image/webp', value: 'image/webp' },
|
||||
{ label: 'image/x-icon', value: 'image/x-icon' }
|
||||
],
|
||||
props: {
|
||||
multiple: true
|
||||
}
|
||||
},
|
||||
{
|
||||
type: 'inputNumber',
|
||||
field: 'fileSize',
|
||||
title: '大小限制(MB)',
|
||||
value: 5,
|
||||
props: { min: 0 }
|
||||
},
|
||||
{
|
||||
type: 'input',
|
||||
field: 'height',
|
||||
title: '组件高度',
|
||||
value: '150px'
|
||||
},
|
||||
{
|
||||
type: 'input',
|
||||
field: 'width',
|
||||
title: '组件宽度',
|
||||
value: '150px'
|
||||
},
|
||||
{
|
||||
type: 'input',
|
||||
field: 'borderradius',
|
||||
title: '组件边框圆角',
|
||||
value: '8px'
|
||||
},
|
||||
{
|
||||
type: 'switch',
|
||||
field: 'disabled',
|
||||
title: '是否显示删除按钮',
|
||||
value: true
|
||||
},
|
||||
{
|
||||
type: 'switch',
|
||||
field: 'showBtnText',
|
||||
title: '是否显示按钮文字',
|
||||
value: true
|
||||
}
|
||||
])
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,84 @@
|
||||
import { generateUUID } from '@/utils'
|
||||
import { localeProps, makeRequiredRule } from '@/components/FormCreate/src/utils'
|
||||
|
||||
export const useUploadImgsRule = () => {
|
||||
const label = '多图上传'
|
||||
const name = 'UploadImgs'
|
||||
return {
|
||||
icon: 'icon-upload',
|
||||
label,
|
||||
name,
|
||||
rule() {
|
||||
return {
|
||||
type: name,
|
||||
field: generateUUID(),
|
||||
title: label,
|
||||
info: '',
|
||||
$required: false
|
||||
}
|
||||
},
|
||||
props(_, { t }) {
|
||||
return localeProps(t, name + '.props', [
|
||||
makeRequiredRule(),
|
||||
{
|
||||
type: 'switch',
|
||||
field: 'drag',
|
||||
title: '拖拽上传',
|
||||
value: false
|
||||
},
|
||||
{
|
||||
type: 'select',
|
||||
field: 'fileType',
|
||||
title: '图片类型限制',
|
||||
value: ['image/jpeg', 'image/png', 'image/gif'],
|
||||
options: [
|
||||
{ label: 'image/apng', value: 'image/apng' },
|
||||
{ label: 'image/bmp', value: 'image/bmp' },
|
||||
{ label: 'image/gif', value: 'image/gif' },
|
||||
{ label: 'image/jpeg', value: 'image/jpeg' },
|
||||
{ label: 'image/pjpeg', value: 'image/pjpeg' },
|
||||
{ label: 'image/svg+xml', value: 'image/svg+xml' },
|
||||
{ label: 'image/tiff', value: 'image/tiff' },
|
||||
{ label: 'image/webp', value: 'image/webp' },
|
||||
{ label: 'image/x-icon', value: 'image/x-icon' }
|
||||
],
|
||||
props: {
|
||||
multiple: true
|
||||
}
|
||||
},
|
||||
{
|
||||
type: 'inputNumber',
|
||||
field: 'fileSize',
|
||||
title: '大小限制(MB)',
|
||||
value: 5,
|
||||
props: { min: 0 }
|
||||
},
|
||||
{
|
||||
type: 'inputNumber',
|
||||
field: 'limit',
|
||||
title: '数量限制',
|
||||
value: 5,
|
||||
props: { min: 0 }
|
||||
},
|
||||
{
|
||||
type: 'input',
|
||||
field: 'height',
|
||||
title: '组件高度',
|
||||
value: '150px'
|
||||
},
|
||||
{
|
||||
type: 'input',
|
||||
field: 'width',
|
||||
title: '组件宽度',
|
||||
value: '150px'
|
||||
},
|
||||
{
|
||||
type: 'input',
|
||||
field: 'borderradius',
|
||||
title: '组件边框圆角',
|
||||
value: '8px'
|
||||
}
|
||||
])
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,50 @@
|
||||
import { Rule } from '@form-create/element-ui' //左侧拖拽按钮
|
||||
|
||||
// 左侧拖拽按钮
|
||||
export interface MenuItem {
|
||||
label: string
|
||||
name: string
|
||||
icon: string
|
||||
}
|
||||
|
||||
// 左侧拖拽按钮分类
|
||||
export interface Menu {
|
||||
title: string
|
||||
name: string
|
||||
list: MenuItem[]
|
||||
}
|
||||
|
||||
export interface MenuList extends Array<Menu> {}
|
||||
|
||||
// 拖拽组件的规则
|
||||
export interface DragRule {
|
||||
icon: string
|
||||
name: string
|
||||
label: string
|
||||
children?: string
|
||||
inside?: true
|
||||
drag?: true | String
|
||||
dragBtn?: false
|
||||
mask?: false
|
||||
|
||||
rule(): Rule
|
||||
|
||||
props(v: any, v1: any): Rule[]
|
||||
}
|
||||
|
||||
// 通用下拉组件 Props 类型
|
||||
export interface ApiSelectProps {
|
||||
name: string // 组件名称
|
||||
labelField?: string // 选项标签
|
||||
valueField?: string // 选项的值
|
||||
url?: string // url 接口
|
||||
isDict?: boolean // 是否字典选择器
|
||||
}
|
||||
|
||||
// 选择组件规则配置类型
|
||||
export interface SelectRuleOption {
|
||||
label: string // label 名称
|
||||
name: string // 组件名称
|
||||
icon: string // 组件图标
|
||||
props?: any[] // 组件规则
|
||||
}
|
||||
@@ -0,0 +1,100 @@
|
||||
import {
|
||||
useDictSelectRule,
|
||||
useEditorRule,
|
||||
useSelectRule,
|
||||
useUploadFileRule,
|
||||
useUploadImgRule,
|
||||
useUploadImgsRule
|
||||
} from './config'
|
||||
import { Ref } from 'vue'
|
||||
import { Menu } from '@/components/FormCreate/src/type'
|
||||
import { apiSelectRule } from '@/components/FormCreate/src/config/selectRule'
|
||||
|
||||
/**
|
||||
* 表单设计器增强 hook
|
||||
* 新增
|
||||
* - 文件上传
|
||||
* - 单图上传
|
||||
* - 多图上传
|
||||
* - 字典选择器
|
||||
* - 用户选择器
|
||||
* - 部门选择器
|
||||
* - 富文本
|
||||
*/
|
||||
export const useFormCreateDesigner = async (designer: Ref) => {
|
||||
const editorRule = useEditorRule()
|
||||
const uploadFileRule = useUploadFileRule()
|
||||
const uploadImgRule = useUploadImgRule()
|
||||
const uploadImgsRule = useUploadImgsRule()
|
||||
|
||||
/**
|
||||
* 构建表单组件
|
||||
*/
|
||||
const buildFormComponents = () => {
|
||||
// 移除自带的上传组件规则,使用 uploadFileRule、uploadImgRule、uploadImgsRule 替代
|
||||
designer.value?.removeMenuItem('upload')
|
||||
// 移除自带的富文本组件规则,使用 editorRule 替代
|
||||
designer.value?.removeMenuItem('fc-editor')
|
||||
const components = [editorRule, uploadFileRule, uploadImgRule, uploadImgsRule]
|
||||
components.forEach((component) => {
|
||||
// 插入组件规则
|
||||
designer.value?.addComponent(component)
|
||||
// 插入拖拽按钮到 `main` 分类下
|
||||
designer.value?.appendMenuItem('main', {
|
||||
icon: component.icon,
|
||||
name: component.name,
|
||||
label: component.label
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
const userSelectRule = useSelectRule({
|
||||
name: 'UserSelect',
|
||||
label: '用户选择器',
|
||||
icon: 'icon-user-o'
|
||||
})
|
||||
const deptSelectRule = useSelectRule({
|
||||
name: 'DeptSelect',
|
||||
label: '部门选择器',
|
||||
icon: 'icon-address-card-o'
|
||||
})
|
||||
const dictSelectRule = useDictSelectRule()
|
||||
const apiSelectRule0 = useSelectRule({
|
||||
name: 'ApiSelect',
|
||||
label: '接口选择器',
|
||||
icon: 'icon-server',
|
||||
props: [...apiSelectRule]
|
||||
})
|
||||
|
||||
/**
|
||||
* 构建系统字段菜单
|
||||
*/
|
||||
const buildSystemMenu = () => {
|
||||
// 移除自带的下拉选择器组件,使用 currencySelectRule 替代
|
||||
// designer.value?.removeMenuItem('select')
|
||||
// designer.value?.removeMenuItem('radio')
|
||||
// designer.value?.removeMenuItem('checkbox')
|
||||
const components = [userSelectRule, deptSelectRule, dictSelectRule, apiSelectRule0]
|
||||
const menu: Menu = {
|
||||
name: 'system',
|
||||
title: '系统字段',
|
||||
list: components.map((component) => {
|
||||
// 插入组件规则
|
||||
designer.value?.addComponent(component)
|
||||
// 插入拖拽按钮到 `system` 分类下
|
||||
return {
|
||||
icon: component.icon,
|
||||
name: component.name,
|
||||
label: component.label
|
||||
}
|
||||
})
|
||||
}
|
||||
designer.value?.addMenu(menu)
|
||||
}
|
||||
|
||||
onMounted(async () => {
|
||||
await nextTick()
|
||||
buildFormComponents()
|
||||
buildSystemMenu()
|
||||
})
|
||||
}
|
||||