Compare commits
1752 Commits
master
...
0d20009d04
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
0d20009d04 | ||
|
|
f83091b0e6 | ||
|
|
65459954ad | ||
|
|
924fefcc0e | ||
|
|
9162649d9d | ||
|
|
ad36c17f3c | ||
|
|
28fdd13012 | ||
|
|
fd73698c48 | ||
|
|
137891332a | ||
|
|
59e072ed47 | ||
|
|
b77882a574 | ||
|
|
10cbef1f57 | ||
|
|
991114848a | ||
|
|
1efe6010a2 | ||
|
|
b1a4952d61 | ||
|
|
5b36d282c4 | ||
|
|
3b6a1cad2b | ||
|
|
35b1e13ef6 | ||
|
|
06b56c1222 | ||
|
|
dbf9cbf6ba | ||
|
|
6c02405a9a | ||
|
|
326a4ad428 | ||
|
|
e9cb4064e6 | ||
|
|
e346ef8f91 | ||
|
|
3bf4ef345b | ||
|
|
cf91fcf886 | ||
|
|
74a4a8f563 | ||
|
|
fe0024e748 | ||
|
|
22ea9dd3df | ||
|
|
70f5dc8f9f | ||
|
|
ed0ef469f2 | ||
|
|
9071d7e36b | ||
|
|
5db2205403 | ||
|
|
c937d24154 | ||
|
|
5b5f87afc3 | ||
|
|
59d9cbeb10 | ||
|
|
21ee09cc44 | ||
|
|
7cef941dea | ||
|
|
16be1d099b | ||
|
|
36fad97ad8 | ||
|
|
4efa046f0c | ||
|
|
9994004c0c | ||
|
|
79c0c5b3b3 | ||
|
|
b04a8eaf01 | ||
|
|
5e8feea477 | ||
|
|
22f6e8ca28 | ||
|
|
fd06b222a6 | ||
|
|
fb32135755 | ||
|
|
bd702517fd | ||
|
|
d46c73777e | ||
|
|
43dab0bf8e | ||
|
|
f6dc75f553 | ||
|
|
cc3c6b4de4 | ||
|
|
74be1fcd11 | ||
|
|
56ae839500 | ||
|
|
5f6131d132 | ||
|
|
6daf7e03bf | ||
|
|
c53f60c9d3 | ||
|
|
cc34079add | ||
|
|
c87d720c7f | ||
|
|
6c318233e4 | ||
|
|
9ffcd953c4 | ||
|
|
57ea58d8b7 | ||
|
|
e7649cb79d | ||
|
|
a70fd383ff | ||
|
|
0943831ccb | ||
|
|
6563cc883f | ||
|
|
ea30d6fbde | ||
|
|
329dcf52c2 | ||
|
|
fa74319438 | ||
|
|
b6ff60be56 | ||
|
|
abdf94fc5e | ||
|
|
55dfca0a74 | ||
|
|
13e6985469 | ||
|
|
44d950048d | ||
|
|
989e1dbd92 | ||
|
|
2daa6a6e15 | ||
|
|
e284353fb3 | ||
|
|
9bba55fde2 | ||
|
|
b7dadf70fd | ||
|
|
8892201095 | ||
|
|
325de69bf3 | ||
|
|
a50ddb8807 | ||
|
|
6d9a27a06d | ||
|
|
cdefdbf526 | ||
|
|
06ee2ca8a9 | ||
|
|
b60b2786c2 | ||
|
|
e907e21409 | ||
|
|
4f8c6b82cd | ||
|
|
0789bda44f | ||
|
|
f637e8c943 | ||
|
|
0b77d16f3c | ||
|
|
b1b44cf4fc | ||
|
|
ee0cf5f8fe | ||
|
|
9ab2944681 | ||
|
|
57efaad1d7 | ||
|
|
525e0d6c93 | ||
|
|
4f02c6ec90 | ||
|
|
6f00159b55 | ||
|
|
b3d720e94f | ||
|
|
feb0782b5c | ||
|
|
7dec8870b9 | ||
|
|
45da9df43c | ||
|
|
f1d1859d99 | ||
|
|
9138a1b1e9 | ||
|
|
7952757394 | ||
|
|
41a4560aba | ||
|
|
52075116cb | ||
|
|
77b798764b | ||
|
|
379c4d59a9 | ||
|
|
172e375cc8 | ||
|
|
17afe15196 | ||
|
|
f2b336d306 | ||
|
|
9167b4f1f1 | ||
|
|
8e389a2afc | ||
|
|
1a67e725af | ||
|
|
77216cbc13 | ||
|
|
38f2404ef3 | ||
|
|
fc8720fc40 | ||
|
|
41b36c7784 | ||
|
|
b1002fca35 | ||
|
|
1b14f88546 | ||
|
|
e29c5e5695 | ||
|
|
e08fcafa6b | ||
|
|
2a88b48ce5 | ||
|
|
fba1619d04 | ||
|
|
11a2b54373 | ||
|
|
db5233f3ff | ||
|
|
38265dc4ff | ||
|
|
250b854388 | ||
|
|
b777d3ee4d | ||
|
|
4e07b5c13e | ||
|
|
217a687c95 | ||
|
|
ad7e1c3bad | ||
|
|
d637a86dab | ||
|
|
72248fee11 | ||
|
|
0c13c8a477 | ||
|
|
46875570e1 | ||
|
|
24c95403e6 | ||
|
|
02fc32def7 | ||
|
|
669a358195 | ||
|
|
c37e2ad191 | ||
|
|
a1b7d92a74 | ||
|
|
ca75c39a58 | ||
|
|
cfda1e98c2 | ||
|
|
446dc2c135 | ||
|
|
45fc07c4fe | ||
|
|
a8206c8d90 | ||
|
|
73996e1394 | ||
|
|
c68b06be58 | ||
|
|
f43b985c4b | ||
|
|
573f5b3cfd | ||
|
|
56d292c0d2 | ||
|
|
1a8f516821 | ||
|
|
a5933a18f9 | ||
|
|
4590a99466 | ||
|
|
a7821904da | ||
|
|
264d2e0063 | ||
|
|
423f584474 | ||
|
|
1be5ca3cce | ||
|
|
a997a3089c | ||
|
|
4cfbe99918 | ||
|
|
ff3c38e9aa | ||
|
|
42f26c92c1 | ||
|
|
a759c7aacf | ||
|
|
988ee9bd91 | ||
|
|
b395a44e70 | ||
|
|
2c975543be | ||
|
|
1b1a55028f | ||
|
|
04eac7ef28 | ||
|
|
50668bb5a2 | ||
|
|
cfc7bf3307 | ||
|
|
225498b24d | ||
|
|
366e575d79 | ||
|
|
53068a8aa4 | ||
|
|
52d35acf05 | ||
|
|
0aa45ef8fa | ||
|
|
fc817fd6aa | ||
|
|
e631366934 | ||
|
|
2a12b0d5fc | ||
|
|
0c93015806 | ||
|
|
28d6b3c9a9 | ||
|
|
54661dec73 | ||
|
|
50a70380bd | ||
|
|
7596a1f709 | ||
|
|
7cdb62180b | ||
|
|
97cd5bd4e9 | ||
|
|
e7fb22d06d | ||
|
|
e2e3f35e17 | ||
|
|
d0727f8991 | ||
|
|
1a773d10fc | ||
|
|
263f42d51c | ||
|
|
84b265d219 | ||
|
|
316763e63b | ||
|
|
8cb39d4fdf | ||
|
|
8f6434c393 | ||
|
|
e750f68fc0 | ||
|
|
69c99d94c5 | ||
|
|
080206c1c5 | ||
|
|
9bc3e453c0 | ||
|
|
d719644038 | ||
|
|
a7f282691f | ||
|
|
2105225998 | ||
|
|
0ade3a59f1 | ||
|
|
301863e05c | ||
|
|
a00aa55617 | ||
|
|
ba4904a9cb | ||
|
|
efb18515f5 | ||
|
|
8a6b586503 | ||
|
|
21ccd9ff81 | ||
|
|
07212f3ac7 | ||
|
|
1975b8748c | ||
|
|
d24b4beed4 | ||
|
|
0fc3742e9e | ||
|
|
fed5beabd1 | ||
|
|
3a8c561a52 | ||
|
|
45d7f9b699 | ||
|
|
1c9f135ec3 | ||
|
|
7b9574a35a | ||
|
|
a0cec7c024 | ||
|
|
c49339487d | ||
|
|
78b7eec935 | ||
|
|
d29d8f8bff | ||
|
|
a9bdc76bcc | ||
|
|
17e6db28d1 | ||
|
|
3ec42eb891 | ||
|
|
61941cf978 | ||
|
|
816cb42c28 | ||
|
|
1230f98b7b | ||
|
|
143e11cdf4 | ||
|
|
3a2938e1a7 | ||
|
|
5a8aea6776 | ||
|
|
e43006a636 | ||
|
|
aa7caf498b | ||
|
|
537d27db17 | ||
|
|
db7faeac8a | ||
|
|
690d5374cc | ||
|
|
1d4a80ebd6 | ||
|
|
e982b33d50 | ||
|
|
fe8384f1d7 | ||
|
|
ae0952da7d | ||
|
|
05aa12f68d | ||
|
|
5752b4d07f | ||
|
|
1709494bff | ||
|
|
47d149fc1d | ||
|
|
44afde131d | ||
|
|
e5c5e4584b | ||
|
|
7822e34287 | ||
|
|
fab3ee32d0 | ||
|
|
63cd10ccbf | ||
|
|
dbb6706b21 | ||
|
|
c8a547eaad | ||
|
|
618e076f4d | ||
|
|
307f6c347d | ||
|
|
648ce504d6 | ||
|
|
ccb14e0716 | ||
|
|
7e10885ecd | ||
|
|
631ac14395 | ||
|
|
d15c4f89a1 | ||
|
|
eea08ecd44 | ||
|
|
466d6583aa | ||
|
|
c43dde986e | ||
|
|
4d201bd197 | ||
|
|
26c2d675d7 | ||
|
|
98367e1551 | ||
|
|
0d06f67599 | ||
|
|
5a655f74f8 | ||
|
|
802a10993f | ||
|
|
f7a003fdc5 | ||
|
|
4a50280483 | ||
|
|
ed69018562 | ||
|
|
96e9cfe264 | ||
|
|
5dbee7114c | ||
|
|
9e4cd4a6f4 | ||
|
|
b9c70b6e2e | ||
|
|
2b07fd4f3e | ||
|
|
760f84798a | ||
|
|
816e6947e5 | ||
|
|
84e5dc0354 | ||
|
|
32b82f80db | ||
|
|
8f5e79bf0b | ||
|
|
9b92f788ad | ||
|
|
9bc6083780 | ||
|
|
16ef081acc | ||
|
|
bd7cf65ca1 | ||
|
|
03932a6d31 | ||
|
|
e61437d5eb | ||
|
|
2bc9fd2121 | ||
|
|
34f318d3f8 | ||
|
|
efc13f3ef7 | ||
|
|
b92d1c8ab0 | ||
|
|
8861aede74 | ||
|
|
cdc53044d0 | ||
|
|
fed4c57a18 | ||
|
|
bfe7e13d47 | ||
|
|
16c9d7c021 | ||
|
|
ab4e0e512c | ||
|
|
dfed065f71 | ||
|
|
c0e4e2d0f7 | ||
|
|
02631bc1ac | ||
|
|
ad049fa113 | ||
|
|
6d78632498 | ||
|
|
8d5dc33873 | ||
|
|
c9bc7ddb92 | ||
|
|
f301c9c0cd | ||
|
|
9e1ae78371 | ||
|
|
3234e8acce | ||
|
|
44e4545b16 | ||
|
|
f09d09262b | ||
|
|
df15c4429c | ||
|
|
fe19a491b8 | ||
|
|
0caf427c5e | ||
|
|
4fe2e26490 | ||
|
|
f2223b1973 | ||
|
|
31060f34f4 | ||
|
|
56a9b9871c | ||
|
|
2e69a79bce | ||
|
|
e74fa78bcb | ||
|
|
ae6a3030fd | ||
|
|
05199221b8 | ||
|
|
4df8dba8d6 | ||
|
|
4aa5f362a9 | ||
|
|
36e599f972 | ||
|
|
4635459e99 | ||
|
|
014f131577 | ||
|
|
cdf5d072f3 | ||
|
|
87521f1e6e | ||
|
|
a146bbbd5a | ||
|
|
da25a3750e | ||
|
|
1f6e518300 | ||
|
|
e5a1b35146 | ||
|
|
db24ea6af7 | ||
|
|
7e88eb8ee8 | ||
|
|
e9521466f3 | ||
|
|
bea687d5f9 | ||
|
|
bc15d74c34 | ||
|
|
c04284d8c6 | ||
|
|
3b43f28a44 | ||
|
|
3f88c7a958 | ||
|
|
e2cda5b27d | ||
|
|
c07f8884aa | ||
|
|
50372f014d | ||
|
|
c3e0f4878a | ||
|
|
8c62d50bcb | ||
|
|
75e6c5004f | ||
|
|
35451cb5b6 | ||
|
|
69529ec0b1 | ||
|
|
c3f87b9d32 | ||
|
|
4c3f246e23 | ||
|
|
5bd15e121d | ||
|
|
893662e893 | ||
|
|
0d3aa3effb | ||
|
|
edea95a1e6 | ||
|
|
0464729d35 | ||
|
|
6ee800c0d4 | ||
|
|
fd23cb1ea3 | ||
|
|
6fcd895447 | ||
|
|
10ecea0829 | ||
|
|
1836b271aa | ||
|
|
f82ce583fe | ||
|
|
c0f1a6e2ab | ||
|
|
02538d4506 | ||
|
|
910a3d1039 | ||
|
|
d24cd8728a | ||
|
|
1ec01e97ec | ||
|
|
7002c8014e | ||
| c4330f00ac | |||
| d61ee360ec | |||
|
|
af15635c9a | ||
|
|
f1a25179a4 | ||
|
|
2202896efd | ||
|
|
032b2ec9ea | ||
|
|
5739b832f7 | ||
|
|
9cae289354 | ||
|
|
64cbe9e04d | ||
|
|
01dbb6695b | ||
|
|
e15bf73657 | ||
|
|
8c99ddafed | ||
|
|
915214df2b | ||
|
|
e42eee9def | ||
|
|
ada042974b | ||
|
|
3fff4143d4 | ||
|
|
e6fdb98bce | ||
|
|
6968050c6a | ||
|
|
4194829fc0 | ||
|
|
d201cebd7d | ||
|
|
ee02cc8f73 | ||
|
|
eaab46eb76 | ||
|
|
98d266845a | ||
|
|
7cd67ad3ba | ||
|
|
05276b4082 | ||
|
|
3db4ac231b | ||
|
|
1203c9610a | ||
|
|
fc20375848 | ||
|
|
da1918084c | ||
|
|
e46e2f38db | ||
|
|
6402952351 | ||
|
|
9a18db7f99 | ||
|
|
7bea38ba79 | ||
|
|
ded46304b5 | ||
|
|
b2ee7fafac | ||
|
|
61e513f45b | ||
|
|
9958eef8b8 | ||
|
|
edd2cdf632 | ||
|
|
44d5b8eac1 | ||
|
|
800df96c01 | ||
|
|
11c52de53d | ||
|
|
971ed77531 | ||
|
|
ebba4508cf | ||
|
|
cab1ccc026 | ||
|
|
d159fcd9da | ||
|
|
e2520ca60f | ||
|
|
3e3cc5693d | ||
|
|
61e524a689 | ||
|
|
740b87821a | ||
|
|
0c92fdfa86 | ||
|
|
7bd8c1f2d4 | ||
|
|
2f37357bf1 | ||
|
|
e6c36b2a80 | ||
|
|
e1c46b7630 | ||
|
|
77bca8d43c | ||
|
|
6e3aee6a2e | ||
|
|
56956f178d | ||
|
|
051627f53b | ||
|
|
009128e068 | ||
|
|
7df86b8163 | ||
|
|
d83143a783 | ||
|
|
82169094e4 | ||
|
|
19cfe66262 | ||
|
|
d90217a137 | ||
|
|
26e83e82d3 | ||
|
|
657a9e26c7 | ||
|
|
72d6d7905e | ||
|
|
a35ca752af | ||
|
|
be4696a85b | ||
|
|
101663ddda | ||
|
|
714f64676a | ||
|
|
5eb32723bb | ||
|
|
edc50dccb8 | ||
|
|
037c6347e3 | ||
|
|
047d4d1314 | ||
|
|
a456758156 | ||
|
|
98e236f1a0 | ||
|
|
d773a26630 | ||
|
|
439ed3807e | ||
|
|
b4fa9f84c3 | ||
|
|
b3e13b82b4 | ||
|
|
9927d7f880 | ||
|
|
56e4f29746 | ||
|
|
ba9279e304 | ||
|
|
cc4a891975 | ||
|
|
ba47b50ab3 | ||
|
|
56973ca021 | ||
|
|
e26e962ba3 | ||
|
|
6ce684dc82 | ||
|
|
9bdad39418 | ||
|
|
caf9f2da13 | ||
|
|
020439f8e8 | ||
|
|
2d6407c02f | ||
|
|
7d67d5863e | ||
|
|
2538a7ecf7 | ||
|
|
766b4182fd | ||
|
|
913917b54d | ||
|
|
6e027df792 | ||
|
|
4bdb61249b | ||
|
|
b92caedf40 | ||
|
|
73f9f00b53 | ||
|
|
7655976861 | ||
|
|
5b93ef80c6 | ||
|
|
3072dc10d1 | ||
|
|
7ec0f7c45f | ||
|
|
cd109e8e6d | ||
|
|
82682b6810 | ||
|
|
bf8e77b80e | ||
|
|
ba9210e1d0 | ||
|
|
7d8b7f22c6 | ||
|
|
7d1d375240 | ||
|
|
c55c9dd009 | ||
|
|
8cbc367985 | ||
|
|
c33fb7b223 | ||
|
|
c749753673 | ||
|
|
c683d3770c | ||
|
|
5c7fc681ec | ||
|
|
94d54f85fd | ||
|
|
fe9ff22748 | ||
|
|
c08d40d471 | ||
|
|
4ba8594b28 | ||
|
|
39067e6285 | ||
|
|
5e08712676 | ||
|
|
faf187f1c6 | ||
|
|
02cadf6395 | ||
|
|
ed1c2a6df2 | ||
|
|
9df0e30f96 | ||
|
|
7e0acdafbf | ||
|
|
731816ca11 | ||
|
|
d51ae093cb | ||
|
|
cc02dcb810 | ||
|
|
772d1f0a82 | ||
|
|
80f062ffc9 | ||
|
|
7709422b02 | ||
|
|
f3686f378a | ||
|
|
d7c9e7dd60 | ||
|
|
0ab3423283 | ||
|
|
dc1aa5d8b3 | ||
|
|
6fa5beef6f | ||
|
|
9e3ba31ef1 | ||
|
|
997fe953a8 | ||
|
|
214f92bf05 | ||
|
|
d9bbbb86d3 | ||
|
|
38731f3d63 | ||
|
|
ac119bc734 | ||
|
|
72b2edc0d4 | ||
|
|
0b9928e1e0 | ||
|
|
913ffd6b9c | ||
|
|
416d32d901 | ||
|
|
1fbc5e2448 | ||
|
|
8a896f2289 | ||
|
|
f44191578c | ||
|
|
1e24554662 | ||
|
|
7907123692 | ||
|
|
f26491ed65 | ||
|
|
c812fec5a5 | ||
|
|
65d8f71ea0 | ||
|
|
14533338aa | ||
|
|
0533937e25 | ||
|
|
878999c441 | ||
|
|
ba95e159f3 | ||
|
|
805adb7639 | ||
|
|
0e92e929a9 | ||
|
|
3fd7aca320 | ||
|
|
c5861c685a | ||
|
|
de6e2c5841 | ||
|
|
01beff42b0 | ||
|
|
8dc45d7f0f | ||
|
|
bc2dae4a9b | ||
|
|
1812afed13 | ||
|
|
526830773a | ||
|
|
0eaa844afd | ||
|
|
2a77cc8234 | ||
|
|
63dd7e08f1 | ||
|
|
528867ac54 | ||
|
|
daefc25b4b | ||
|
|
8c89b3b418 | ||
|
|
67cc563c32 | ||
|
|
4bee766850 | ||
|
|
63b1851029 | ||
|
|
3c898889ce | ||
|
|
fc48cb8ac5 | ||
|
|
38a020f9a7 | ||
|
|
5d8ade3a3a | ||
|
|
66a9c4aa3d | ||
|
|
defbf3ab35 | ||
|
|
a5f5c2905b | ||
|
|
30edb83bb2 | ||
|
|
333da16a4a | ||
|
|
28e4c2ed74 | ||
|
|
72bbb32bc2 | ||
|
|
4b3175165a | ||
|
|
0a95af96f5 | ||
|
|
a732e4aecb | ||
|
|
d77a4d202e | ||
|
|
3e0f6f7e6f | ||
|
|
f8bfd88de1 | ||
|
|
e56b9fbd86 | ||
|
|
b69af7117c | ||
|
|
06d6255d97 | ||
|
|
5481602d07 | ||
|
|
21b71bb0c1 | ||
|
|
2ec0060bbc | ||
|
|
4de065d59e | ||
|
|
872df25f34 | ||
|
|
315e8ffec7 | ||
|
|
1c91aead97 | ||
|
|
8bf723cc55 | ||
|
|
4288d70f0a | ||
|
|
16a4337d88 | ||
|
|
10b0acdc5f | ||
|
|
8a687ede4a | ||
|
|
214faad467 | ||
|
|
f2d13e2345 | ||
|
|
351fadae18 | ||
|
|
ea391f6f68 | ||
|
|
f599a222f2 | ||
|
|
f7b6afeb95 | ||
|
|
4794ccedad | ||
|
|
79b964055a | ||
|
|
891d8bfaf5 | ||
|
|
a43d375d3e | ||
|
|
b4e5b3f71b | ||
|
|
9629d39d9d | ||
|
|
75eb5e7434 | ||
|
|
9ef17f5680 | ||
|
|
7da51f065a | ||
|
|
595712b66e | ||
|
|
53b9e36fe8 | ||
|
|
f78b48057e | ||
|
|
410d0e70e0 | ||
|
|
2eb5df3759 | ||
|
|
77a88dba26 | ||
|
|
6027a46ee9 | ||
|
|
73d84875c3 | ||
|
|
2f98f6bc09 | ||
|
|
b3a06a51fa | ||
|
|
88f5f4279f | ||
|
|
60dd3f3d8c | ||
|
|
79a49298e2 | ||
|
|
bcdb4946e4 | ||
|
|
9f85ccc4f2 | ||
|
|
5206203caa | ||
|
|
0fe811958d | ||
|
|
6d4f30f737 | ||
|
|
6e49980aee | ||
|
|
e3abdef57b | ||
|
|
e28dc75ddb | ||
|
|
0f11adea01 | ||
|
|
606215280b | ||
|
|
1789b78c19 | ||
|
|
3a633c2f96 | ||
|
|
fe8bf9a588 | ||
|
|
49dae77888 | ||
|
|
d8979960db | ||
|
|
c6c7acc220 | ||
|
|
774ec8cc7b | ||
|
|
946af98c4a | ||
|
|
801db611c6 | ||
|
|
617eb16ba2 | ||
|
|
b345e1bd13 | ||
|
|
8ca8de8aef | ||
|
|
56c227ee78 | ||
|
|
f454b9a1e0 | ||
|
|
7ab4fba5eb | ||
|
|
7df6e54fe8 | ||
|
|
aa8db2b2ea | ||
|
|
f0553e0f14 | ||
|
|
56d8c0582b | ||
|
|
807faa4229 | ||
|
|
6118aa6b54 | ||
|
|
61477d2fb8 | ||
|
|
65802d4de8 | ||
|
|
f68f9be4c8 | ||
|
|
69ddc602ef | ||
|
|
272a3942b1 | ||
|
|
cc74aa11af | ||
|
|
f8a4b96048 | ||
|
|
4e8d540655 | ||
|
|
88cc2e9e9f | ||
|
|
e098bbbf9d | ||
|
|
ebb738e41b | ||
|
|
d29d2110dc | ||
|
|
901fc767fb | ||
|
|
3fcc993913 | ||
|
|
b6b589fcd7 | ||
|
|
bacb186def | ||
|
|
877c29965c | ||
|
|
967c73f98a | ||
|
|
9f6f44812e | ||
|
|
2c69fc946b | ||
|
|
b7d30b366a | ||
|
|
142496beb3 | ||
|
|
97d9f8dab2 | ||
|
|
99e5cfea09 | ||
|
|
5b81a23bb8 | ||
|
|
42a332b76c | ||
|
|
062b2f6039 | ||
|
|
05f593e87c | ||
|
|
1a52a6acee | ||
|
|
954290d26d | ||
|
|
089e993308 | ||
|
|
6c7b5d45da | ||
|
|
49d43d14e6 | ||
|
|
7647f30a4c | ||
|
|
e0955038d2 | ||
|
|
6e5e935cfe | ||
|
|
df8ef261a9 | ||
|
|
80a3286a05 | ||
|
|
15e63d4232 | ||
|
|
03b60d3bbe | ||
|
|
549196de75 | ||
|
|
ac2933a781 | ||
|
|
e10373abc4 | ||
|
|
eb5fb2970e | ||
|
|
a828fc8ee6 | ||
|
|
d693017b39 | ||
|
|
e9cba488e5 | ||
|
|
4d3691c17e | ||
|
|
df5d4f0380 | ||
|
|
b84814c461 | ||
|
|
cb885fa456 | ||
|
|
32871fdc1b | ||
|
|
0a47f48e81 | ||
|
|
0f568046c5 | ||
|
|
42e406ff82 | ||
|
|
599c10cd7d | ||
|
|
513bf04185 | ||
|
|
8aaba442af | ||
|
|
ae7fe3f5b5 | ||
|
|
6bcd9c870a | ||
|
|
27c23f77e5 | ||
|
|
d3df5cb76e | ||
|
|
7dd5b13695 | ||
|
|
4503abe419 | ||
|
|
d2941ceb96 | ||
|
|
d5cdacddff | ||
|
|
5ea84f0c5f | ||
|
|
11395c003f | ||
|
|
c00768252b | ||
|
|
7ccd4fccdf | ||
|
|
ec8bb6daf0 | ||
|
|
1c16eb3f62 | ||
|
|
b718727544 | ||
|
|
02abd08424 | ||
|
|
5698bfb695 | ||
|
|
b3bb77dfc0 | ||
|
|
782f632892 | ||
|
|
d53e5f3b4b | ||
|
|
cf996ed83d | ||
|
|
c276a3f908 | ||
|
|
5e7bae967e | ||
|
|
235f4127be | ||
|
|
d358301e5d | ||
|
|
cad15c95ff | ||
|
|
608c8e917f | ||
|
|
29a03f52a3 | ||
|
|
85c65143ff | ||
|
|
1e8eb71954 | ||
|
|
ccbaf345df | ||
|
|
0ab6121473 | ||
|
|
caa650d8a7 | ||
|
|
f489726c47 | ||
|
|
afa4582961 | ||
|
|
ad5e9cee56 | ||
|
|
cb8c39f89e | ||
|
|
4f49a8ce3a | ||
|
|
393358c432 | ||
|
|
e7c2ab3ff8 | ||
|
|
2ee5920d9e | ||
|
|
4c052eee8c | ||
|
|
c7ed3c81ea | ||
|
|
2df5e5fc35 | ||
|
|
58f44dc9b5 | ||
|
|
8331e08401 | ||
|
|
14466882a8 | ||
|
|
4a0391157d | ||
|
|
b4b63e86b0 | ||
|
|
3d3a9608aa | ||
|
|
9918f1eec9 | ||
|
|
c1ca841f28 | ||
|
|
43cee8bd0f | ||
|
|
43b7aa757b | ||
|
|
17543b1fca | ||
|
|
2168403b2f | ||
|
|
78d6862d9f | ||
|
|
4abfb9f7bf | ||
|
|
bd03d5b95e | ||
|
|
a3e1694d4f | ||
|
|
a6593379af | ||
|
|
447b718db4 | ||
|
|
4c980ce920 | ||
|
|
62c0878bf1 | ||
|
|
571b877853 | ||
|
|
2fee1d638f | ||
|
|
21d86f4f91 | ||
|
|
ac42fe7953 | ||
|
|
ca0563e470 | ||
|
|
79abba1c1b | ||
|
|
cbb91f554e | ||
|
|
6429df786a | ||
|
|
8a5d5fd2a2 | ||
|
|
33a36a881c | ||
|
|
def27eb80d | ||
|
|
d66df7a089 | ||
|
|
aa9b19fe1a | ||
|
|
541fe7645c | ||
|
|
4a1c602495 | ||
|
|
8c52ababf9 | ||
|
|
714ffbb869 | ||
|
|
0cec708363 | ||
|
|
4fc404df50 | ||
|
|
30c8744a0d | ||
|
|
0d119f91fc | ||
|
|
a3e0d9e3a8 | ||
|
|
c363287d0d | ||
|
|
f5cb84d57a | ||
|
|
d07437523e | ||
|
|
7876c45df5 | ||
|
|
126ab7a0e5 | ||
|
|
56dacf0dad | ||
|
|
91e69675dc | ||
|
|
65940485a9 | ||
|
|
c6c303f281 | ||
|
|
ed44e1d430 | ||
|
|
02a90196ef | ||
|
|
7fd68e9935 | ||
|
|
759640bca4 | ||
|
|
e879ea68d8 | ||
|
|
653d90b266 | ||
|
|
f0d4c65315 | ||
|
|
0644a6a800 | ||
|
|
79aa21a14a | ||
|
|
936d1d9cb8 | ||
|
|
7ae6d4dcc2 | ||
|
|
7317e67369 | ||
|
|
81c828ad22 | ||
|
|
2409a6110b | ||
|
|
731d76a8c5 | ||
|
|
60114bf14d | ||
|
|
ad8ebab5d4 | ||
|
|
902c1009bd | ||
|
|
4a1fb16a3e | ||
|
|
1b92c5437e | ||
|
|
489c855972 | ||
|
|
c22400eab4 | ||
|
|
0016b8da5d | ||
|
|
6237891af9 | ||
|
|
8ef0f6292e | ||
|
|
a36f3741bf | ||
|
|
c739dae4f9 | ||
|
|
ae600dc2c3 | ||
|
|
14ffbe81f7 | ||
|
|
bce5db8e41 | ||
|
|
fb117a21c5 | ||
|
|
c27f9b673c | ||
|
|
a69e27ca79 | ||
|
|
f67a710539 | ||
|
|
2a5fa63b4b | ||
|
|
284c8bd02b | ||
|
|
99982a9b21 | ||
|
|
17b87fce22 | ||
|
|
5d782ea172 | ||
|
|
7b27d4c1f5 | ||
|
|
f5dc0ef5d5 | ||
|
|
0faf89c232 | ||
|
|
336d1cc48f | ||
|
|
392f27f94f | ||
|
|
bf819648d2 | ||
|
|
4ef3723d03 | ||
|
|
2b3258c63a | ||
|
|
23fa2e3140 | ||
|
|
d237e7a72b | ||
|
|
2e09cd71a0 | ||
|
|
07141014a9 | ||
|
|
4ed2ba92c5 | ||
|
|
77f78ac6ee | ||
|
|
39cc46e910 | ||
|
|
1ab10e6f96 | ||
|
|
021cc97145 | ||
|
|
0a241dd286 | ||
|
|
96c50e6832 | ||
|
|
24a7e8c19a | ||
|
|
eb63f3c9c2 | ||
|
|
797ff30800 | ||
|
|
de4f337f93 | ||
|
|
77c65c4e80 | ||
|
|
c4959fabdf | ||
|
|
38d7beff8f | ||
|
|
015935b7f4 | ||
|
|
920180d95b | ||
|
|
eaa92c2dfe | ||
|
|
3d1614e99a | ||
|
|
b5c9963de2 | ||
|
|
9106ec7547 | ||
|
|
03de4e4f7e | ||
|
|
48003ffaa3 | ||
|
|
875c056075 | ||
|
|
9a8227e43c | ||
|
|
bb744c49b9 | ||
|
|
8cb77ebeee | ||
|
|
a319b5decc | ||
|
|
d4acc37880 | ||
| d63c013d1f | |||
|
|
e175e62ccd | ||
|
|
608dfb53ba | ||
|
|
7251b599db | ||
|
|
05dda2bad2 | ||
|
|
b7433bdd55 | ||
|
|
825ae8e41b | ||
|
|
06ac9ae4fd | ||
|
|
88d29e99f2 | ||
|
|
6005ae2b48 | ||
|
|
02501453a8 | ||
|
|
fcbf8c05f4 | ||
|
|
80d6ab63f4 | ||
|
|
f18b450eca | ||
|
|
3c84a52d7d | ||
|
|
6b7fd4f9b0 | ||
|
|
2e22f1a494 | ||
|
|
15304b84c3 | ||
|
|
4c6f3322cc | ||
|
|
08dd7fe4c7 | ||
|
|
1249c4b0bb | ||
|
|
cee13c878e | ||
|
|
b9b77193e3 | ||
|
|
73cf15b05f | ||
|
|
080b20e9de | ||
|
|
7ceadac5ea | ||
|
|
5cfb9dac19 | ||
|
|
b40ee95b48 | ||
|
|
a8d35407ae | ||
|
|
3a56a8c6cc | ||
|
|
b0f5da59f1 | ||
|
|
4617698596 | ||
|
|
445c615477 | ||
|
|
20d4a5de01 | ||
|
|
cf21392f70 | ||
|
|
95aa779de1 | ||
|
|
f70e222118 | ||
|
|
1ece40a1ff | ||
|
|
d6d5e06f49 | ||
|
|
96ded5c44e | ||
|
|
774d67c060 | ||
|
|
53f74ed7ab | ||
|
|
5316234edf | ||
|
|
f7a0502ab1 | ||
|
|
0b745a0745 | ||
|
|
1cb5da5e52 | ||
|
|
09c1251070 | ||
|
|
72a63e1fdc | ||
|
|
7f61b1927e | ||
|
|
73d1822777 | ||
|
|
2b26005104 | ||
|
|
e4f09cc777 | ||
|
|
7dca509968 | ||
|
|
8005d5186a | ||
|
|
3ae8441ccd | ||
|
|
630fb6a04c | ||
|
|
23b00586cc | ||
|
|
2689583c1e | ||
|
|
d9f9910b0f | ||
|
|
fd70bd5491 | ||
|
|
36d9e72cdc | ||
|
|
65597e4826 | ||
|
|
20c8d9c8ec | ||
|
|
8f0131dfc7 | ||
|
|
b11adc40c8 | ||
|
|
6545570ecd | ||
|
|
a6841cb380 | ||
|
|
2974eb27d9 | ||
|
|
43ca3a10c8 | ||
|
|
0c2fae8b95 | ||
|
|
449261a490 | ||
|
|
ccdd76c5d2 | ||
|
|
b213baf57a | ||
|
|
75af293c60 | ||
|
|
78ae2fedcc | ||
|
|
683f8d5071 | ||
|
|
3f0aa73fad | ||
| d8054b3138 | |||
| c5a8cc406e | |||
| 9a14338548 | |||
|
|
e4ce1885f8 | ||
|
|
e5d42a0d5f | ||
|
|
36c9c1d466 | ||
|
|
26e9ed8011 | ||
| fd58336719 | |||
| 78b75e153a | |||
| f7eccff38d | |||
| 2caaedd7c5 | |||
| 7b501528fb | |||
| e421f3bd30 | |||
|
|
3c59ee2c87 | ||
|
|
a5b3b0a115 | ||
|
|
803f3d52a5 | ||
|
|
face324b7c | ||
|
|
ce180ca6e1 | ||
|
|
7d4a0422cb | ||
|
|
c3e7ca5fa0 | ||
|
|
e6f016e9cd | ||
|
|
2bcba1bdd4 | ||
|
|
2d2dc39df0 | ||
|
|
1c020414da | ||
|
|
c13e90a7f6 | ||
|
|
dc1248dd3a | ||
|
|
9389719c00 | ||
|
|
873a2a0291 | ||
|
|
3ecd8a4b90 | ||
|
|
97cf6e7e48 | ||
|
|
27e1f2047f | ||
|
|
1b75874a85 | ||
|
|
96136659cb | ||
|
|
074bc889f2 | ||
|
|
79037b2b77 | ||
|
|
14758461c0 | ||
|
|
3e9a951b5e | ||
|
|
cf4c09beb2 | ||
|
|
7f242a00a3 | ||
|
|
10890ad64e | ||
|
|
a11f507248 | ||
|
|
6787bc8875 | ||
|
|
915a5b6d7e | ||
|
|
3daebc279e | ||
|
|
90a06e91b6 | ||
|
|
4f4c080ad9 | ||
|
|
cfcf2c12ea | ||
|
|
46e1ac2264 | ||
|
|
710c17567f | ||
|
|
668c51494b | ||
|
|
0df80b87fb | ||
|
|
045ef0fe5b | ||
|
|
f02a10b7a9 | ||
|
|
91c4b50066 | ||
|
|
cbd1484160 | ||
|
|
991362dfd5 | ||
|
|
5eb023311f | ||
|
|
cf613a0c4a | ||
|
|
a26ae16bcc | ||
|
|
942a10db23 | ||
|
|
396a7a2f5a | ||
|
|
c01098ccad | ||
|
|
4b07e48aac | ||
|
|
51a1b0070c | ||
|
|
f593db72f0 | ||
|
|
cd154b48cf | ||
|
|
8b1197fe54 | ||
|
|
5053ee1654 | ||
|
|
3392f5d160 | ||
|
|
0c8ab8c1bb | ||
|
|
658b8b1e95 | ||
|
|
e08d795e53 | ||
|
|
411db791fe | ||
|
|
e30090b6cb | ||
|
|
0a5e3c9b66 | ||
|
|
75d27332dd | ||
|
|
9f9e55fb4e | ||
|
|
e8948dc28d | ||
|
|
bd94a1372a | ||
|
|
2c0c80c7d3 | ||
|
|
6dd89c48f9 | ||
|
|
336461a14d | ||
|
|
0bf5bbf217 | ||
|
|
e29568c97d | ||
|
|
9b92d7ac4c | ||
|
|
e1be3f75fb | ||
|
|
3d7494ee3f | ||
|
|
67f534babc | ||
|
|
7ba0db84be | ||
|
|
50a21c9e45 | ||
|
|
77755d0298 | ||
|
|
ecd44a3c78 | ||
|
|
b9f3cda9b8 | ||
|
|
fa36ed8082 | ||
|
|
e6b1e2ec10 | ||
|
|
8be0b37093 | ||
|
|
bc6f8e9596 | ||
|
|
2ef327622a | ||
|
|
27203bef6b | ||
|
|
6917ee1fce | ||
|
|
1447e03100 | ||
|
|
92bdae2c35 | ||
|
|
9bf7e55528 | ||
|
|
ab6db00a54 | ||
|
|
2dd25ad02c | ||
|
|
60fdec8005 | ||
|
|
4cf8f9a4f6 | ||
|
|
7ac0dcbb80 | ||
|
|
0a0dab0ac2 | ||
|
|
cbb0edc14a | ||
|
|
e259bbc969 | ||
|
|
213cd46a1c | ||
|
|
d537294216 | ||
|
|
77111556bd | ||
|
|
d8569137e9 | ||
|
|
22ccf1081b | ||
|
|
350e85143a | ||
|
|
1a65407ef7 | ||
|
|
33b9400e4a | ||
|
|
5061c0d950 | ||
|
|
17bbe976b6 | ||
|
|
bb923cca81 | ||
|
|
83e06be215 | ||
|
|
a1ddb7ab60 | ||
|
|
98277aa8b9 | ||
|
|
b2c2f89263 | ||
|
|
b2ec1d98fb | ||
|
|
66c0a4d02f | ||
|
|
1ba7c55040 | ||
|
|
1c23fe25c2 | ||
|
|
52e50f6dd8 | ||
|
|
74d26168f9 | ||
|
|
e6cf36a1e1 | ||
|
|
03ed448813 | ||
|
|
21d60e230a | ||
|
|
9f6203e762 | ||
|
|
e05ce4d719 | ||
|
|
650a6ced04 | ||
|
|
a9a54483db | ||
|
|
a8f9a582bb | ||
|
|
c3723c8cfb | ||
|
|
d1e2853b6e | ||
|
|
7f1ab4e039 | ||
|
|
2ddf94eb75 | ||
|
|
eeea69196f | ||
|
|
9cc8d610c6 | ||
|
|
46276a83ff | ||
|
|
a8436087e6 | ||
|
|
70722ae3bc | ||
|
|
21d1714f7e | ||
|
|
5775c244cb | ||
|
|
f8989e4b3c | ||
|
|
808e365dde | ||
|
|
d5eadff265 | ||
|
|
280e180ec0 | ||
|
|
88ec60127f | ||
|
|
ed2166a8e4 | ||
|
|
6a42912106 | ||
|
|
02ad912923 | ||
|
|
1f0d57c808 | ||
|
|
758899d5d2 | ||
|
|
99145dfe29 | ||
|
|
93fb661712 | ||
|
|
18525d7f45 | ||
|
|
4984f4bbce | ||
|
|
9038f17227 | ||
|
|
87fbb25738 | ||
|
|
f6f989b6be | ||
|
|
2faf80cc22 | ||
|
|
eef85d2dcb | ||
|
|
a703ed79c3 | ||
|
|
0d19d797f2 | ||
|
|
cc59548dc7 | ||
|
|
1dcb4f496d | ||
|
|
4c1ae89e11 | ||
|
|
7a2a4d11c4 | ||
|
|
a19bbe29d6 | ||
|
|
99a81996a1 | ||
|
|
6b9a3db12a | ||
|
|
7c025411e9 | ||
|
|
f302a577fa | ||
|
|
2b233c209c | ||
|
|
27309d242b | ||
|
|
1d7c140180 | ||
|
|
e4f37c927f | ||
|
|
add921a438 | ||
|
|
a56d6e77ba | ||
|
|
be95bdfebb | ||
|
|
841034a7ad | ||
|
|
d97edae1a5 | ||
|
|
5d9ede9fb0 | ||
|
|
84b74c6f19 | ||
|
|
7167b61241 | ||
|
|
26f3de888d | ||
|
|
110695c03d | ||
|
|
62f201e5e5 | ||
|
|
5c59c6fb1c | ||
|
|
ef58ec52d2 | ||
|
|
4e905d03d2 | ||
|
|
15f7b56361 | ||
|
|
39d242d86a | ||
|
|
f948203f58 | ||
|
|
cdb0945124 | ||
|
|
dcebdbe334 | ||
|
|
5213d622a4 | ||
|
|
74507e4663 | ||
|
|
e76206dd9b | ||
|
|
147b0a84f3 | ||
|
|
cc6d0a987d | ||
|
|
c69d040592 | ||
|
|
63a116bc65 | ||
|
|
f5c4734430 | ||
|
|
d55355267b | ||
|
|
e1a1f46ca7 | ||
|
|
d9636e8463 | ||
|
|
215dabe5cf | ||
|
|
b691377a6c | ||
|
|
f0c6bd9964 | ||
|
|
7806ad4981 | ||
|
|
b1603f3b29 | ||
|
|
a4bd186464 | ||
|
|
3c205667d4 | ||
|
|
7622fd8ca2 | ||
|
|
f9d1809e26 | ||
|
|
80f57d2e4d | ||
|
|
48f58d5380 | ||
|
|
e4a910e832 | ||
|
|
c842a60f45 | ||
|
|
6bc0e587b4 | ||
|
|
761f404ac1 | ||
|
|
c1ea828f77 | ||
|
|
3b5aec0bca | ||
|
|
3dde4fa4ce | ||
|
|
24dad80b52 | ||
|
|
f3feb75e18 | ||
|
|
fa543d0807 | ||
|
|
2583312007 | ||
|
|
ecb0d25950 | ||
|
|
02bdd4ab18 | ||
|
|
a4d187cdf1 | ||
|
|
8667835d2b | ||
|
|
2b006da12d | ||
|
|
aaf2b8b475 | ||
|
|
9894cecb74 | ||
|
|
efc9714abb | ||
|
|
ab824d2002 | ||
|
|
6fe4959fcc | ||
|
|
c917ac5acf | ||
|
|
23302fc5c3 | ||
|
|
a049b8d896 | ||
|
|
b1988fb42b | ||
|
|
2cc5ddd0de | ||
|
|
083646bb11 | ||
|
|
337bb19746 | ||
|
|
addfa5a097 | ||
|
|
15f61074f9 | ||
|
|
d09812588d | ||
|
|
068cbb2916 | ||
|
|
70c6d61e23 | ||
|
|
ae247c2a9d | ||
|
|
fdf5680bde | ||
|
|
9bd1b05763 | ||
|
|
f61bbe9c83 | ||
|
|
4696642a66 | ||
|
|
d3a253bb64 | ||
|
|
d9e5f2bf43 | ||
|
|
729a3eb8ee | ||
|
|
ff40f6de8f | ||
|
|
b8d9a7fd6e | ||
|
|
e17fefbc9d | ||
|
|
6ddbb022f6 | ||
|
|
1d5ed72119 | ||
|
|
9b09468c0f | ||
|
|
2b6f4c3ea4 | ||
|
|
dfb0dbc66d | ||
|
|
2ef6de0eb5 | ||
|
|
9368de483b | ||
|
|
860163bb6c | ||
|
|
05c8b55eda | ||
|
|
d271a18092 | ||
|
|
1a1f1c59b0 | ||
|
|
eb903e592f | ||
|
|
5368c9df66 | ||
|
|
49764c3e3d | ||
|
|
4dccdf87c3 | ||
|
|
6e3baca4d3 | ||
|
|
de864a3d91 | ||
|
|
8835447757 | ||
|
|
31a87039ce | ||
|
|
ebf6ef2aa6 | ||
|
|
607b897e65 | ||
|
|
8306e1d5fe | ||
|
|
29a2b7adbd | ||
|
|
229b5c66f6 | ||
|
|
018a4329f2 | ||
|
|
cdd330a0f2 | ||
|
|
76b673a803 | ||
|
|
e141634634 | ||
|
|
3f8e71437d | ||
|
|
f9418701b1 | ||
|
|
e7bd8103b1 | ||
|
|
280a918d8a | ||
|
|
12124b339d | ||
|
|
56d6d7e4a3 | ||
|
|
48860fd584 | ||
|
|
0d9c250acb | ||
|
|
ff63f6f079 | ||
|
|
7fa917b279 | ||
|
|
8d3d16a5f4 | ||
|
|
b7915238c3 | ||
|
|
3ae57be0cc | ||
|
|
2bbc303c00 | ||
|
|
3c762e0f69 | ||
|
|
13567fcb3d | ||
|
|
e10c69cd2e | ||
|
|
0c889c9076 | ||
|
|
2655a44573 | ||
|
|
4f1592540e | ||
|
|
2ef633a0c8 | ||
|
|
0b83cec78b | ||
|
|
511a98026e | ||
|
|
29dac41f38 | ||
|
|
607496f22e | ||
|
|
0ff81339d7 | ||
|
|
9b62472851 | ||
|
|
56c425d1b3 | ||
|
|
9c90e17192 | ||
|
|
d71028399a | ||
|
|
2198e6e6f2 | ||
|
|
4b760830c2 | ||
|
|
99574bc82b | ||
|
|
bfb54de844 | ||
|
|
ddb9afa4a9 | ||
|
|
c575f1c5bd | ||
|
|
341a77efb4 | ||
|
|
f114f81888 | ||
|
|
b38da8876b | ||
|
|
e666bd0772 | ||
|
|
0a76f894f6 | ||
|
|
a642a2ef86 | ||
|
|
0a6508a714 | ||
|
|
39fe336980 | ||
|
|
c2fcba70f9 | ||
|
|
0a4f500c52 | ||
|
|
a139f1a921 | ||
|
|
cbd270a47e | ||
|
|
39e54666e1 | ||
|
|
56911c18e6 | ||
|
|
249fdcf4ff | ||
|
|
4870798cda | ||
|
|
bed245526f | ||
|
|
942ec62ef3 | ||
|
|
490964507a | ||
|
|
52f80012c2 | ||
|
|
102cab0ad3 | ||
|
|
97d3df74f9 | ||
|
|
6466e22491 | ||
|
|
f6f667a0f6 | ||
|
|
94ae33a36a | ||
|
|
41e4a3f3a0 | ||
|
|
8f40ac4dd4 | ||
|
|
dd8bba63c0 | ||
|
|
d18312c6d1 | ||
|
|
135a662576 | ||
|
|
731444ae9a | ||
|
|
44f9a8a5e8 | ||
|
|
f36e184fb7 | ||
|
|
b3338b8a27 | ||
|
|
7048bb57bd | ||
|
|
43e2b68093 | ||
|
|
e725724e0f | ||
|
|
76252b234e | ||
|
|
1b887350ee | ||
|
|
527a236377 | ||
|
|
36387f09cc | ||
|
|
e33464e201 | ||
|
|
980d38f86a | ||
|
|
6c9c660846 | ||
|
|
89777782c6 | ||
|
|
b3082e19ca | ||
|
|
c00a272e05 | ||
|
|
0338a914cc | ||
|
|
86eacaffca | ||
|
|
1ce02319f9 | ||
|
|
e9412b31ed | ||
|
|
fd99207ac8 | ||
|
|
cd34e7589a | ||
|
|
d58102f837 | ||
|
|
c67b8ddac5 | ||
|
|
ddc6741756 | ||
|
|
83612a66e3 | ||
|
|
d57fa9cda4 | ||
|
|
2cc8864afe | ||
|
|
a6d6376a81 | ||
|
|
ec6c9e5cb9 | ||
|
|
080abff1d6 | ||
|
|
1fd822c3e2 | ||
|
|
0cf5b490ad | ||
|
|
93453ff402 | ||
|
|
0680e835a3 | ||
|
|
423be6e32c | ||
|
|
5757cc76f5 | ||
|
|
2c771a6efb | ||
|
|
3f1d54858c | ||
|
|
e8a6fa3ac8 | ||
|
|
b8c59a8c50 | ||
|
|
29f68bedf4 | ||
|
|
29897467cb | ||
|
|
7293626b43 | ||
|
|
77c745da22 | ||
|
|
6a26cd0cd7 | ||
|
|
6370d792bb | ||
|
|
f19f23ead3 | ||
|
|
75c71cb200 | ||
|
|
b916295a8e | ||
|
|
2c73f6616e | ||
|
|
12089dced6 | ||
|
|
12bbe691e8 | ||
|
|
48e694662d | ||
|
|
973b3b71a8 | ||
|
|
f0d260d37a | ||
|
|
52ab0ee654 | ||
|
|
7f4bad3131 | ||
|
|
beb63fec25 | ||
|
|
60b5f4401c | ||
|
|
551dca7540 | ||
|
|
0faa07e325 | ||
|
|
d4423817bb | ||
|
|
6cc4bcf6ed | ||
|
|
09d5995915 | ||
|
|
5d0801ac21 | ||
|
|
6ed5ef69ad | ||
|
|
f0babad995 | ||
|
|
5a4c6103e6 | ||
|
|
115ba62141 | ||
|
|
7b967a8540 | ||
|
|
fd72e6a23f | ||
|
|
526d7b9209 | ||
|
|
85b606c208 | ||
|
|
ebc94282cc | ||
|
|
f360453843 | ||
|
|
893044f2e1 | ||
|
|
da5e1a9221 | ||
|
|
bf207e19ee | ||
|
|
3b794c3229 | ||
| b5983b00ae | |||
| 7af278b0f6 | |||
| e18188becc | |||
| f2aeeed36c | |||
| 4c426bb2ce | |||
|
|
a9c7a55ace | ||
|
|
ba43a5f135 | ||
|
|
b699f6ff4f | ||
|
|
6d2b4888d6 | ||
|
|
432c0fdb90 | ||
|
|
cb904385c3 | ||
|
|
b45ad4a3c9 | ||
|
|
9b9a5cb1c7 | ||
|
|
8674a0c406 | ||
|
|
7c834349d9 | ||
|
|
c2b186c328 | ||
|
|
11f7f6af35 | ||
|
|
9e26794b24 | ||
|
|
81068c24dd | ||
|
|
c387fb1ea3 | ||
|
|
724421754a | ||
|
|
e863829c5b | ||
|
|
d7f6ac5270 | ||
|
|
025455eebd | ||
|
|
f151ebbac7 | ||
|
|
f42239c1c5 | ||
|
|
2c8a8a2136 | ||
|
|
5f23c94af8 | ||
|
|
c04c89507c | ||
|
|
c239698292 | ||
|
|
c7edfa42e2 | ||
|
|
38361ee0a1 | ||
|
|
8c6a1d2349 | ||
|
|
f3ce80b49e | ||
|
|
f60dd5e01f | ||
|
|
94f6d25ee9 | ||
|
|
29cb1e4448 | ||
|
|
6fa86ccb8e | ||
|
|
845b19d8a8 | ||
|
|
522991f3d3 | ||
|
|
615ac2faa5 | ||
|
|
8c5ef4cdda | ||
|
|
3b8d858759 | ||
|
|
2e8be19e77 | ||
|
|
a9e67623a0 | ||
|
|
be25e7cebb | ||
|
|
07a5c3e774 | ||
|
|
8a50b67294 | ||
|
|
1b65ac7286 | ||
|
|
c88fa5c6cc | ||
|
|
ab510f09d0 | ||
|
|
1f3a5241e8 | ||
|
|
66a93b312d | ||
|
|
484991ceeb | ||
|
|
fb8f81951a | ||
|
|
0357fa0940 | ||
|
|
1853839c81 | ||
|
|
d87172a6c7 | ||
|
|
3f7875d945 | ||
|
|
11f9119607 | ||
|
|
bc7161c806 | ||
|
|
a93b30a565 | ||
|
|
a9e84c9cf6 | ||
|
|
db4fefd098 | ||
|
|
8455e6e24a | ||
|
|
5ef64873ad | ||
|
|
3eda5b324e | ||
|
|
d30b483b56 | ||
|
|
adadbe6480 | ||
|
|
d32f60fd69 | ||
|
|
4af311d1de | ||
|
|
115a321f22 | ||
|
|
8daaf7e55b | ||
|
|
061d7e9b30 | ||
|
|
10d4c88886 | ||
|
|
812f158732 | ||
|
|
60cf307fd2 | ||
|
|
e866b41f42 | ||
|
|
27920b8638 | ||
|
|
7a5882c618 | ||
|
|
152bf55233 | ||
|
|
fbbd7aadd6 | ||
|
|
d2bb350d1f | ||
|
|
803f8a4772 | ||
|
|
91cc8f6797 | ||
|
|
9fcc27a8fc | ||
|
|
89509848cc | ||
|
|
a473aa91e0 | ||
|
|
268aa87ae7 | ||
|
|
1f242413f2 | ||
|
|
4d27ebdad0 | ||
|
|
eb9b367d57 | ||
|
|
4c9455a85c | ||
|
|
8a539ab7e8 | ||
|
|
73a780c05e | ||
|
|
4fb1600b7a | ||
|
|
38b9f8f3c8 | ||
|
|
36ff4ab3e1 | ||
|
|
f602984add | ||
|
|
dd51424b45 | ||
|
|
173ab5bca7 | ||
|
|
782d060673 | ||
|
|
119663606c | ||
|
|
9ea36cba79 | ||
|
|
b144189e8f | ||
|
|
1749a5bde5 | ||
|
|
0ab14fb757 | ||
|
|
3feb255563 | ||
|
|
223bf47bbf | ||
|
|
b239b1ad4a | ||
|
|
6c3aaa7582 | ||
|
|
3bd796f26d | ||
|
|
88368d7000 | ||
|
|
43f81f1f0f | ||
|
|
d99ccf44f5 | ||
|
|
91c91d963e | ||
|
|
5857fef0a4 | ||
|
|
901663a004 | ||
|
|
6f788e7ea0 | ||
|
|
3b4888544d | ||
|
|
05bd052689 | ||
|
|
6d7442ec37 | ||
|
|
74dfc82cfd | ||
|
|
e8f1fe4da8 | ||
|
|
0b54056026 | ||
|
|
b0dcff0ebe | ||
|
|
55bae8d0e4 | ||
|
|
bcefa95305 | ||
|
|
27f5becebf | ||
|
|
57bde9ed14 | ||
|
|
d01920d015 | ||
|
|
47407454ab | ||
|
|
94049fe776 | ||
|
|
6350b1abb9 | ||
|
|
36d37125dc | ||
|
|
3197b34dcc | ||
|
|
b316ea7661 | ||
|
|
65aca68012 | ||
|
|
dba4841906 | ||
|
|
b76ba3b588 | ||
|
|
f01d0f39b2 | ||
|
|
ba03829018 | ||
|
|
7f0b19f3f0 | ||
|
|
018fd5c094 | ||
|
|
64750bf632 | ||
|
|
43d01c7e94 | ||
|
|
ded932c002 | ||
|
|
cf43abb95b | ||
|
|
60cc273b6f | ||
|
|
95bdb2671d | ||
|
|
4e6aa5a17f | ||
|
|
2a2a80f5c9 | ||
|
|
404b26e934 | ||
|
|
e13a398e6e | ||
|
|
f042951e79 | ||
|
|
09a0135703 | ||
|
|
b5fb93adc5 | ||
|
|
a0ebce751e | ||
|
|
8e1fedb603 | ||
|
|
fc31c74666 | ||
|
|
b7646379c4 | ||
|
|
3e61cfb498 | ||
|
|
3259431133 | ||
|
|
d59b695ae0 | ||
|
|
ba4fa56eda | ||
|
|
e983fb9a67 | ||
|
|
12fa343316 | ||
|
|
f1e01fd34a | ||
|
|
e23d048a5c | ||
|
|
a1dc77e206 | ||
|
|
2ed075302c | ||
|
|
1265207f9f | ||
|
|
a48e350d2e | ||
|
|
70eeab4bc2 | ||
|
|
265035eb91 | ||
|
|
2a1e2d2a5c | ||
|
|
45ce327bcb | ||
|
|
798b93b3cb | ||
|
|
724118734d | ||
|
|
798b1fad73 | ||
|
|
5de8b3d568 | ||
|
|
d6a3d7daf6 | ||
|
|
74fa627d75 | ||
|
|
aa2612514e | ||
|
|
ada192fa67 | ||
|
|
9acf0777c7 | ||
|
|
15d15ae659 | ||
|
|
ad2a47bb56 | ||
|
|
e666ee8547 | ||
|
|
fdca180787 | ||
|
|
2caf1f7c9a | ||
|
|
99945b2c6d | ||
|
|
af7b4c52f9 | ||
|
|
adeab55230 | ||
|
|
cafe80e2da | ||
|
|
9e091b2fee | ||
|
|
d546d47f3d | ||
|
|
c521c38af3 | ||
|
|
23db081c99 | ||
|
|
730d625e9c | ||
|
|
a13ea7f804 | ||
|
|
2d81ed1b15 | ||
|
|
178879c329 | ||
|
|
8f5a5d1c38 | ||
|
|
06554e4cd6 | ||
|
|
7e48145889 | ||
|
|
bbc8e5d95f | ||
|
|
ac30d09e12 | ||
|
|
99dd363534 | ||
|
|
73d0c44356 | ||
|
|
15dc8ccc73 | ||
|
|
dafa7e7d62 | ||
|
|
41c05f2eb0 | ||
|
|
8b79eb32d6 | ||
|
|
612908bacc | ||
|
|
11c0243521 | ||
|
|
757a4a7182 | ||
|
|
c247da0854 | ||
|
|
ed04004b30 | ||
|
|
3166fe09a0 | ||
|
|
6e9d3c89dd | ||
|
|
51d4ba7907 | ||
|
|
10d2feb600 | ||
|
|
024bb77f37 | ||
|
|
9d20cd57e2 | ||
|
|
6f8d1de072 | ||
|
|
b9152917ce | ||
|
|
7392b320e6 | ||
|
|
2515d1ff07 | ||
|
|
520473c497 | ||
|
|
6f43e40510 | ||
|
|
7f7dbcdc11 | ||
|
|
0d20291973 | ||
|
|
a6fc4490c4 | ||
|
|
ef54d5e611 | ||
|
|
8465d3689c | ||
|
|
c1a3d23d4e | ||
|
|
f2391dc9c0 | ||
|
|
c857850550 | ||
|
|
1f5c1bb5a5 | ||
|
|
b6bb4477c8 | ||
|
|
06ba284f76 | ||
|
|
2e7215e9cc | ||
|
|
d9eb5ced2c | ||
|
|
273ff4f90d | ||
|
|
86e378053e | ||
|
|
d9788c214d | ||
|
|
7a10b684ee | ||
|
|
1d70b75f14 | ||
|
|
5a63dadc88 | ||
|
|
f3f4374159 | ||
|
|
021348293f | ||
|
|
734f8ab79c | ||
|
|
f216078eea | ||
|
|
d8b13da38a | ||
|
|
4734c76dff | ||
|
|
ec37f652c6 | ||
|
|
2d4bcdb918 | ||
|
|
00727a66f2 | ||
|
|
3fb3086be4 | ||
|
|
ff5ae8884c | ||
|
|
31367c4f2b | ||
|
|
d11123d0ae | ||
|
|
2bff4ceefc | ||
|
|
7a5edf572d | ||
|
|
796179f440 | ||
|
|
f5ac457f56 | ||
|
|
f8efc03341 | ||
|
|
fee55eb9c6 | ||
|
|
6c7c9f5da6 | ||
|
|
78e6ad0292 | ||
|
|
21be21c53a | ||
|
|
e3ef0a2cb7 | ||
|
|
11247a161a | ||
|
|
282b41a11f | ||
|
|
b5d0a0a02c | ||
|
|
a3dfe91a05 | ||
|
|
3d78a4f15c | ||
|
|
7e27d4b467 | ||
|
|
9eea7ba23a | ||
|
|
899430f4cd | ||
|
|
8b0751dd8f | ||
|
|
df6ad8016e | ||
|
|
131ac90bdf | ||
|
|
0922aae4f1 | ||
|
|
8e663dc94e | ||
|
|
c14d2c7e0f | ||
|
|
715b0e7396 | ||
|
|
226bc12071 | ||
|
|
93fa7005f7 | ||
|
|
f85b24310b | ||
|
|
8ab0d46eaf | ||
|
|
fc65a3a481 | ||
|
|
6a3f3b10f8 | ||
|
|
92ffbc1231 | ||
|
|
57093b06e4 | ||
|
|
c420805ada | ||
|
|
f914566c02 | ||
|
|
7ae663db75 | ||
|
|
909d24021a | ||
|
|
29113550bf | ||
|
|
71a711dae7 | ||
|
|
371da2cbc6 | ||
|
|
352adae52d | ||
|
|
69183cc38b | ||
|
|
8a1d74d57b | ||
|
|
9dfcf99125 | ||
|
|
853f5c7a05 | ||
|
|
f841f2e462 | ||
|
|
1bc309e60b | ||
|
|
2101c42874 | ||
|
|
a59667914b | ||
|
|
b8aa27d5ef | ||
|
|
351b0582b2 | ||
|
|
eda588e2e3 | ||
|
|
cfb00174e3 | ||
|
|
21f5273b84 | ||
|
|
97b79400b6 | ||
|
|
b42fa7e9ed | ||
|
|
b0c57fbc6e | ||
|
|
e0ddc13369 | ||
|
|
9221b97d91 | ||
|
|
f189e13195 | ||
|
|
c7454c23b4 | ||
|
|
f448a9a12a | ||
|
|
047b4d6972 | ||
|
|
edfed81029 | ||
|
|
73393e8bff | ||
|
|
c7aadf184c | ||
|
|
7f8c3ff490 | ||
|
|
6470a2b52f | ||
|
|
6db67c6fcc | ||
|
|
c7ccba8384 | ||
|
|
96db78522c | ||
|
|
9a3043c170 | ||
|
|
fdd877f5e5 | ||
|
|
7040288003 | ||
|
|
9c71f94030 | ||
|
|
ba01c46f41 | ||
|
|
7af36a0d8b | ||
|
|
93d1761e5d | ||
|
|
5cdd6b74a8 | ||
|
|
66844a46d8 | ||
|
|
6620540f62 | ||
|
|
4e7009f386 | ||
|
|
326262eb57 | ||
|
|
56634faaf9 | ||
|
|
6add4540a5 | ||
|
|
99d9e65dde | ||
|
|
9ec4c3568a | ||
|
|
24dfdac7b9 | ||
|
|
a5431c1d77 | ||
|
|
93443d3812 | ||
|
|
e329ae9b51 | ||
|
|
ef5c05d1d5 | ||
|
|
da1d271b72 | ||
|
|
f9f75c4e34 | ||
|
|
2457845536 | ||
|
|
bc8aae4e28 | ||
|
|
2f371a08bc | ||
|
|
8d2905428e |
28
.gitignore
vendored
Normal file
@@ -0,0 +1,28 @@
|
||||
.DS_Store
|
||||
node_modules/
|
||||
unpackage/
|
||||
dist/
|
||||
lib/
|
||||
# local env files
|
||||
.env.local
|
||||
.env.*.local
|
||||
|
||||
# Log files
|
||||
npm-debug.log*
|
||||
yarn-debug.log*
|
||||
yarn-error.log*
|
||||
|
||||
# Editor directories and files
|
||||
.project
|
||||
.idea
|
||||
.vscode
|
||||
*.suo
|
||||
*.ntvs*
|
||||
*.njsproj
|
||||
*.sln
|
||||
*.sw*
|
||||
/package-lock.json
|
||||
/.hbuilderx/launch.json
|
||||
/src/pages.json
|
||||
|
||||
/src/config.json
|
||||
6
.npmrc
Normal file
@@ -0,0 +1,6 @@
|
||||
registry=http://192.168.1.87:4873/
|
||||
//registry=https://registry.npmjs.org
|
||||
email=aixianling@sinoecare.com
|
||||
always-auth=true
|
||||
//package-lock=false
|
||||
//192.168.1.87:4873/:_auth="YWRtaW46YWRtaW4xMjM="
|
||||
@@ -1,3 +1,5 @@
|
||||
# dvcp_v2_wechat_app
|
||||
|
||||
村微2.0 小程序应用库
|
||||
村微2.0 小程序应用库
|
||||
|
||||
``如果出现cache-loader异常,可以考虑升级@vue/cli-service @vue/cli-plugin-babel到5.0``
|
||||
63
babel.config.js
Normal file
@@ -0,0 +1,63 @@
|
||||
const plugins = []
|
||||
|
||||
if (process.env.UNI_OPT_TREESHAKINGNG) {
|
||||
plugins.push(require('@dcloudio/vue-cli-plugin-uni-optimize/packages/babel-plugin-uni-api/index.js'))
|
||||
}
|
||||
|
||||
if (
|
||||
(
|
||||
process.env.UNI_PLATFORM === 'app-plus' &&
|
||||
process.env.UNI_USING_V8
|
||||
) ||
|
||||
(
|
||||
process.env.UNI_PLATFORM === 'h5' &&
|
||||
process.env.UNI_H5_BROWSER === 'builtin'
|
||||
)
|
||||
) {
|
||||
const path = require('path')
|
||||
|
||||
const isWin = /^win/.test(process.platform)
|
||||
|
||||
const normalizePath = path => (isWin ? path.replace(/\\/g, '/') : path)
|
||||
|
||||
const input = normalizePath(process.env.UNI_INPUT_DIR)
|
||||
try {
|
||||
plugins.push([
|
||||
require('@dcloudio/vue-cli-plugin-hbuilderx/packages/babel-plugin-console'),
|
||||
{
|
||||
file (file) {
|
||||
file = normalizePath(file)
|
||||
if (file.indexOf(input) === 0) {
|
||||
return path.relative(input, file)
|
||||
}
|
||||
return false
|
||||
}
|
||||
}
|
||||
])
|
||||
} catch (e) {}
|
||||
}
|
||||
|
||||
process.UNI_LIBRARIES = process.UNI_LIBRARIES || ['@dcloudio/uni-ui']
|
||||
process.UNI_LIBRARIES.forEach(libraryName => {
|
||||
plugins.push([
|
||||
'import',
|
||||
{
|
||||
'libraryName': libraryName,
|
||||
'customName': (name) => {
|
||||
return `${libraryName}/lib/${name}/${name}`
|
||||
}
|
||||
}
|
||||
])
|
||||
})
|
||||
module.exports = {
|
||||
presets: [
|
||||
[
|
||||
'@vue/app',
|
||||
{
|
||||
modules: 'commonjs',
|
||||
useBuiltIns: process.env.UNI_PLATFORM === 'h5' ? 'usage' : 'entry'
|
||||
}
|
||||
]
|
||||
],
|
||||
plugins
|
||||
}
|
||||
22
bin/clean.js
Normal file
@@ -0,0 +1,22 @@
|
||||
const fs = require("fs");
|
||||
const fse = require("fs-extra")
|
||||
const path = require("path");
|
||||
const getDirs = (dir, list = [], cb) => {
|
||||
const dirs = fs.readdirSync(dir, {withFileTypes: true})
|
||||
dirs.map(d => {
|
||||
if (d.isDirectory()) {
|
||||
let p = path.join(dir, d.name)
|
||||
list.push(p)
|
||||
if (cb(d, p)) getDirs(p, list, cb)
|
||||
}
|
||||
})
|
||||
return list
|
||||
}
|
||||
getDirs(path.join(__dirname, '..', 'src'), [], (dir, path) => {
|
||||
if (["apps"].includes(dir.name)) {
|
||||
fse.remove(path)
|
||||
console.log("已清除%s", path)
|
||||
}
|
||||
return !["apps"].includes(dir.name)
|
||||
})
|
||||
fse.remove(path.join(__dirname, '..', 'lib'))
|
||||
16
bin/lib.js
Normal file
@@ -0,0 +1,16 @@
|
||||
const {findApp, chalkTag, copyFiles} = require("./tools");
|
||||
const start = () => {
|
||||
chalkTag.info("扫描主库目录,并搬运打包应用至lib文件夹下")
|
||||
let apps = []
|
||||
findApp('src/mods', file => apps.push(file))
|
||||
.then(() => Promise.all([...new Set(apps)].map(e => {
|
||||
let name = e.replace(/.+[\\\/]([^\\\/]+)$/, '$1')
|
||||
if (/^App/.test(name)) {
|
||||
return copyFiles(`lib/${name}`, e)
|
||||
}
|
||||
})))
|
||||
.then(() => {
|
||||
chalkTag.done("打包完成")
|
||||
})
|
||||
}
|
||||
start()
|
||||
75
bin/pages.js
Normal file
@@ -0,0 +1,75 @@
|
||||
const {chalkTag, findPages, fsExtra, fs} = require("./tools");
|
||||
const PageBase = require("dvcp-wui/utils/PageBase");
|
||||
let apps = {list: [], desc: "用于产品库主页面获取应用使用", type: "mp"}
|
||||
const getFileInfo = (app, file) => {
|
||||
if (/^App/.test(app.name)) {
|
||||
let {name, label} = app,
|
||||
path = app.path.replace(/.+[\\\/]([^\\\/]+)[\\\/]([^\\\/]+)$/g, `/mods/$1/$2`)
|
||||
apps.list.push({
|
||||
id: file.replace(/\.\/?(vue)?/g, '')?.replace(/[\\\/]/g, '_'),
|
||||
name,
|
||||
label,
|
||||
path,
|
||||
libPath: file?.replace(/\\/g, '/')?.replace(/^src(\/.+)\.vue/, '$1'),
|
||||
type: 'mp'
|
||||
})
|
||||
}
|
||||
}
|
||||
const start = () => {
|
||||
chalkTag.info('开始生成pages.json...')
|
||||
let json = {
|
||||
easycom: {
|
||||
"^u-(.*)": "uview-ui/components/u-$1/u-$1.vue",
|
||||
"^(Ai|V)(.*)": "@/components/$1$2/$1$2.vue",
|
||||
},
|
||||
pages: [
|
||||
{path: 'pages/home', style: {navigationBarTitleText: "小程序应用库"}}
|
||||
],
|
||||
subPackages: [
|
||||
{root: "mods/", pages: []},
|
||||
{root: "components/pages/", pages: []},
|
||||
{root: "project/", pages: []},
|
||||
],
|
||||
globalStyle: {
|
||||
pageOrientation: "auto",
|
||||
navigationBarTextStyle: "white",
|
||||
navigationBarBackgroundColor: "#4181FF",
|
||||
"mp-weixin": {
|
||||
"usingComponents": {
|
||||
"cell": "plugin://materialPlugin/cell",
|
||||
"qplayer": "plugin://player/video"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
Promise.all([
|
||||
findPages('src/components/pages', file => {
|
||||
if (/.+\\pages\\[^\\]+\.vue/g.test(file)) {
|
||||
const app = new PageBase(file.replace(/^src\\components\\pages\\(.*).vue/g, '$1').replace(/\\/g, '/'), fs.readFileSync(file).toString())
|
||||
getFileInfo(app, file)
|
||||
return json.subPackages[1].pages.push(app)
|
||||
}
|
||||
}),
|
||||
findPages('src/mods', file => {
|
||||
if (/.+\\App[^\\]+\\[^\\]+\.vue/g.test(file)) {
|
||||
const app = new PageBase(file.replace(/^src\\mods\\(.*).vue/g, '$1').replace(/\\/g, '/'), fs.readFileSync(file).toString())
|
||||
getFileInfo(app, file)
|
||||
return json.subPackages[0].pages.push(app)
|
||||
}
|
||||
}),
|
||||
findPages('src/project', file => {
|
||||
if (/.+\\App[^\\]+\\[^\\]+\.vue/g.test(file)) {
|
||||
const app = new PageBase(file.replace(/^src\\project\\(.*).vue/g, '$1').replace(/\\/g, '/'), fs.readFileSync(file).toString())
|
||||
getFileInfo(app, file)
|
||||
return json.subPackages[2].pages.push(app)
|
||||
}
|
||||
})
|
||||
]).then(() => {
|
||||
fsExtra.outputJson('src/config.json', {apps: apps.list})
|
||||
fsExtra.outputJson('src/pages.json', json, () => {
|
||||
chalkTag.done('生成pages.json')
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
start();
|
||||
52
bin/sync.js
Normal file
@@ -0,0 +1,52 @@
|
||||
const {chalkTag, fs, findPages} = require("./tools");
|
||||
const axios = require("axios");
|
||||
const PageBase = require("dvcp-wui/utils/PageBase");
|
||||
|
||||
let apps = {list: [], desc: "用于产品库主页面获取应用使用", type: 'mp'}
|
||||
const saveApps = app => {
|
||||
if (app.list.length > 0) {
|
||||
return axios.post("http://192.168.1.87:12525/node/wechatapps/addOrUpdate", app, {timeout: 1000}).then(res => {
|
||||
if (res.data.code == 0) chalkTag.done("产品库目录已同步至后台数据库...")
|
||||
}).catch(err => {
|
||||
console.log(err)
|
||||
})
|
||||
}
|
||||
}
|
||||
const getFileInfo = (app, file) => {
|
||||
if (/^App/.test(app.name) && app.label) {
|
||||
let {name, label} = app,
|
||||
path = app.path.replace(/.+[\\\/]([^\\\/]+)[\\\/]([^\\\/]+)$/g, `/mods/$1/$2`)
|
||||
apps.list.push({
|
||||
id: file.replace(/\.\/?(vue)?/g, '').replace(/[\\\/]/g, '_'),
|
||||
name,
|
||||
label,
|
||||
path,
|
||||
libPath: file.replace(/[\\\/]/g, '/').replace(/^src(\/.+)\.vue/, '$1'),
|
||||
type: 'mp'
|
||||
})
|
||||
}
|
||||
}
|
||||
const start = () => {
|
||||
chalkTag.info('开始同步数据到数据库')
|
||||
Promise.all([
|
||||
findPages('src/components/pages', file => {
|
||||
if (/.+[\\\/]pages[\\\/][^\\\/]+\.vue/g.test(file)) {
|
||||
const app = new PageBase(file.replace(/^src[\\\/]components[\\\/]pages[\\\/](.*).vue/g, '$1').replace(/[\\\/]/g, '/'), fs.readFileSync(file).toString())
|
||||
return getFileInfo(app, file)
|
||||
}
|
||||
}),
|
||||
findPages('src/mods', file => {
|
||||
if (/.+[\\\/]App[^\\\/]+[\\\/][^\\\/]+\.vue/g.test(file)) {
|
||||
const app = new PageBase(file.replace(/^src[\\\/]mods[\\\/](.*).vue/g, '$1').replace(/[\\\/]/g, '/'), fs.readFileSync(file).toString())
|
||||
return getFileInfo(app, file)
|
||||
}
|
||||
}),
|
||||
findPages('src/project', file => {
|
||||
if (/.+[\\\/]App[^\\\/]+[\\\/][^\\\/]+\.vue/g.test(file)) {
|
||||
const app = new PageBase(file.replace(/^src[\\\/]project[\\\/](.*).vue/g, '$1').replace(/[\\\/]/g, '/'), fs.readFileSync(file).toString())
|
||||
return getFileInfo(app, file)
|
||||
}
|
||||
})
|
||||
]).then(() => saveApps(apps)).finally(() => chalkTag.done('同步完成'))
|
||||
}
|
||||
start()
|
||||
85
bin/tools.js
Normal file
@@ -0,0 +1,85 @@
|
||||
const fsExtra = require('fs-extra')
|
||||
const path = require('path')
|
||||
const chalk = require('chalk')
|
||||
const fs = require('fs')
|
||||
/**
|
||||
* 将函数封装成promise
|
||||
*/
|
||||
const promisify = fn => {
|
||||
return function () {
|
||||
let args = arguments;
|
||||
return new Promise(function (resolve, reject) {
|
||||
[].push.call(args, function (err, result) {
|
||||
if (err) {
|
||||
console.log(err)
|
||||
reject(err);
|
||||
} else {
|
||||
resolve(result);
|
||||
}
|
||||
});
|
||||
fn.apply(null, args);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
const readdir = promisify(fs.readdir)
|
||||
const stat = promisify(fs.stat)
|
||||
|
||||
/**
|
||||
* 封装打印工具
|
||||
*/
|
||||
const {log} = console
|
||||
const chalkTag = {
|
||||
info: msg => log([chalk.bgBlue.black(' INFO '), msg].join(' ')),
|
||||
done: msg => log([chalk.bgGreen.black(' DONE '), msg].join(' ')),
|
||||
warn: msg => log([chalk.bgYellow.black(' WARN '), msg].join(' ')),
|
||||
error: msg => log([chalk.bgRed.black(' ERROR '), msg].join(' ')),
|
||||
}
|
||||
|
||||
/**
|
||||
* 遍历应用的方法
|
||||
*/
|
||||
const findApp = (dir, cb) => {
|
||||
fsExtra.ensureDirSync(dir)
|
||||
return readdir(dir).then(apps => {
|
||||
return Promise.all(apps.map(e => {
|
||||
let cPath = path.join(dir, e)
|
||||
return stat(cPath).then(state => {
|
||||
if (state.isDirectory()) {
|
||||
return findApp(cPath, cb)
|
||||
} else if (state.isFile()) {
|
||||
cb && cb(dir)
|
||||
}
|
||||
})
|
||||
}) || [])
|
||||
})
|
||||
}
|
||||
const findPages = (dir, cb) => {
|
||||
fsExtra.ensureDirSync(dir)
|
||||
return readdir(dir).then(apps => {
|
||||
return Promise.all(apps.map(e => {
|
||||
let cPath = path.join(dir, e)
|
||||
return stat(cPath).then(state => {
|
||||
if (state.isDirectory()) {
|
||||
return findPages(cPath, cb)
|
||||
} else if (state.isFile()) {
|
||||
cb && cb(cPath)
|
||||
}
|
||||
})
|
||||
}) || [])
|
||||
})
|
||||
}
|
||||
const copyFiles = (dir, source = 'src/mods') => {
|
||||
chalkTag.info(`开始扫描${source}...`)
|
||||
return new Promise(resolve => {
|
||||
fsExtra.emptyDir(dir, err => {
|
||||
if (!err) {
|
||||
fsExtra.copy(source, dir).then(() => {
|
||||
chalkTag.done(source + ' 扫描完毕')
|
||||
resolve()
|
||||
})
|
||||
}
|
||||
})
|
||||
})
|
||||
}
|
||||
module.exports = {findApp, chalkTag, fsExtra, copyFiles, fs, path, findPages}
|
||||
14
jest.config.js
Normal file
@@ -0,0 +1,14 @@
|
||||
module.exports = {
|
||||
globalTeardown: '@dcloudio/uni-automator/dist/teardown.js',
|
||||
testEnvironment: '@dcloudio/uni-automator/dist/environment.js',
|
||||
testEnvironmentOptions: {},
|
||||
testTimeout: 15000,
|
||||
reporters: [
|
||||
'default'
|
||||
],
|
||||
watchPathIgnorePatterns: ['/node_modules/', '/dist/', '/.git/'],
|
||||
moduleFileExtensions: ['js', 'json'],
|
||||
rootDir: __dirname,
|
||||
testMatch: ['<rootDir>/src/__tests__/**/*spec.[jt]s?(x)'],
|
||||
testPathIgnorePatterns: ['/node_modules/']
|
||||
}
|
||||
88
package.json
Normal file
@@ -0,0 +1,88 @@
|
||||
{
|
||||
"name": "dvcp-wechat-apps",
|
||||
"version": "1.0.0",
|
||||
"private": false,
|
||||
"author": "Kubbo",
|
||||
"scripts": {
|
||||
"dev": "node bin/pages.js&&cross-env NODE_ENV=development VUE_APP_CW_MODE=dev UNI_PLATFORM=mp-weixin vue-cli-service uni-build --watch",
|
||||
"pages": "node bin/pages.js",
|
||||
"lib": "npm publish -ws||(npm unpublish -ws -f&&npm publish -ws)",
|
||||
"clean": "node bin/clean.js",
|
||||
"sync": "node bin/sync.js",
|
||||
"info": "node node_modules/@dcloudio/vue-cli-plugin-uni/commands/info.js"
|
||||
},
|
||||
"files": [
|
||||
"lib"
|
||||
],
|
||||
"workspaces": [
|
||||
"src/components",
|
||||
"src"
|
||||
],
|
||||
"dependencies": {
|
||||
"@dcloudio/uni-app": "^2.0.2-4010520240507001",
|
||||
"@dcloudio/uni-app-plus": "^2.0.2-4010520240507001",
|
||||
"@dcloudio/uni-h5": "^2.0.2-4010520240507001",
|
||||
"@dcloudio/uni-i18n": "^2.0.2-4010520240507001",
|
||||
"@dcloudio/uni-mp-360": "^2.0.2-4010520240507001",
|
||||
"@dcloudio/uni-mp-alipay": "^2.0.2-4010520240507001",
|
||||
"@dcloudio/uni-mp-baidu": "^2.0.2-4010520240507001",
|
||||
"@dcloudio/uni-mp-jd": "^2.0.2-4010520240507001",
|
||||
"@dcloudio/uni-mp-kuaishou": "^2.0.2-4010520240507001",
|
||||
"@dcloudio/uni-mp-lark": "^2.0.2-4010520240507001",
|
||||
"@dcloudio/uni-mp-qq": "^2.0.2-4010520240507001",
|
||||
"@dcloudio/uni-mp-toutiao": "^2.0.2-4010520240507001",
|
||||
"@dcloudio/uni-mp-vue": "^2.0.2-4010520240507001",
|
||||
"@dcloudio/uni-mp-weixin": "^2.0.2-4010520240507001",
|
||||
"@dcloudio/uni-mp-xhs": "^2.0.2-4010520240507001",
|
||||
"@dcloudio/uni-quickapp-native": "^2.0.2-4010520240507001",
|
||||
"@dcloudio/uni-quickapp-webview": "^2.0.2-4010520240507001",
|
||||
"@dcloudio/uni-stacktracey": "^2.0.2-4010520240507001",
|
||||
"@dcloudio/uni-stat": "^2.0.2-4010520240507001",
|
||||
"@vue/shared": "^3.0.0",
|
||||
"axios": "^0.19.2",
|
||||
"axios-miniprogram-adapter": "^0.3.2",
|
||||
"core-js": "^3.8.3",
|
||||
"dayjs": "^1.9.5",
|
||||
"dvcp-wui": "^1.0.1",
|
||||
"flyio": "^0.6.2",
|
||||
"query-string": "^7.1.1",
|
||||
"regenerator-runtime": "^0.12.1",
|
||||
"swiper": "^11.1.4",
|
||||
"uview-ui": "^1.8.8",
|
||||
"vue": ">= 2.6.14 < 2.7",
|
||||
"vuex": "^3.2.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@dcloudio/types": "^3.3.2",
|
||||
"@dcloudio/uni-automator": "^2.0.2-4010520240507001",
|
||||
"@dcloudio/uni-cli-i18n": "^2.0.2-4010520240507001",
|
||||
"@dcloudio/uni-cli-shared": "^2.0.2-4010520240507001",
|
||||
"@dcloudio/uni-helper-json": "*",
|
||||
"@dcloudio/uni-migration": "^2.0.2-4010520240507001",
|
||||
"@dcloudio/uni-template-compiler": "^2.0.2-4010520240507001",
|
||||
"@dcloudio/vue-cli-plugin-hbuilderx": "^2.0.2-4010520240507001",
|
||||
"@dcloudio/vue-cli-plugin-uni": "^2.0.2-4010520240507001",
|
||||
"@dcloudio/vue-cli-plugin-uni-optimize": "^2.0.2-4010520240507001",
|
||||
"@dcloudio/webpack-uni-mp-loader": "^2.0.2-4010520240507001",
|
||||
"@dcloudio/webpack-uni-pages-loader": "^2.0.2-4010520240507001",
|
||||
"@vue/cli-plugin-babel": "~5.0.0",
|
||||
"@vue/cli-service": "~5.0.0",
|
||||
"babel-plugin-import": "^1.11.0",
|
||||
"cross-env": "^7.0.2",
|
||||
"fs-extra": "^11.1.0",
|
||||
"jest": "^25.4.0",
|
||||
"mini-types": "^0.1.4",
|
||||
"miniprogram-api-typings": "^3.1.6",
|
||||
"postcss-comment": "^2.0.0",
|
||||
"sass": "^1.45.1",
|
||||
"vue-template-compiler": ">= 2.6.14 < 2.7",
|
||||
"vuex-persistedstate": "^3.1.0"
|
||||
},
|
||||
"browserslist": [
|
||||
"Android >= 4.4",
|
||||
"ios >= 9"
|
||||
],
|
||||
"uni-app": {
|
||||
"scripts": {}
|
||||
}
|
||||
}
|
||||
22
postcss.config.js
Normal file
@@ -0,0 +1,22 @@
|
||||
const path = require('path')
|
||||
module.exports = {
|
||||
parser: require('postcss-comment'),
|
||||
plugins: [
|
||||
require('postcss-import')({
|
||||
resolve (id, basedir, importOptions) {
|
||||
if (id.startsWith('~@/')) {
|
||||
return path.resolve(process.env.UNI_INPUT_DIR, id.substr(3))
|
||||
} else if (id.startsWith('@/')) {
|
||||
return path.resolve(process.env.UNI_INPUT_DIR, id.substr(2))
|
||||
} else if (id.startsWith('/') && !id.startsWith('//')) {
|
||||
return path.resolve(process.env.UNI_INPUT_DIR, id.substr(1))
|
||||
}
|
||||
return id
|
||||
}
|
||||
}),
|
||||
require('autoprefixer')({
|
||||
remove: process.env.UNI_PLATFORM !== 'h5'
|
||||
}),
|
||||
require('@dcloudio/vue-cli-plugin-uni/packages/postcss')
|
||||
]
|
||||
}
|
||||
27
public/index.html
Normal file
@@ -0,0 +1,27 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="zh-CN">
|
||||
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<meta http-equiv="X-UA-Compatible" content="IE=edge">
|
||||
<title>
|
||||
<%= htmlWebpackPlugin.options.title %>
|
||||
</title>
|
||||
<script>
|
||||
document.addEventListener('DOMContentLoaded', function() {
|
||||
document.documentElement.style.fontSize = document.documentElement.clientWidth / 20 + 'px'
|
||||
})
|
||||
var coverSupport = 'CSS' in window && typeof CSS.supports === 'function' && (CSS.supports('top: env(a)') || CSS.supports('top: constant(a)'))
|
||||
document.write('<meta name="viewport" content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0' + (coverSupport ? ', viewport-fit=cover' : '') + '" />')
|
||||
</script>
|
||||
<link rel="stylesheet" href="<%= BASE_URL %>static/index.<%= VUE_APP_INDEX_CSS_HASH %>.css" />
|
||||
</head>
|
||||
<body>
|
||||
<noscript>
|
||||
<strong>Please enable JavaScript to continue.</strong>
|
||||
</noscript>
|
||||
<div id="app"></div>
|
||||
<!-- built files will be auto injected -->
|
||||
</body>
|
||||
|
||||
</html>
|
||||
154
src/App.vue
Normal file
@@ -0,0 +1,154 @@
|
||||
<script>
|
||||
|
||||
export default {
|
||||
onLaunch() {
|
||||
if (uni.getUpdateManager) {
|
||||
const updateManager = uni.getUpdateManager()
|
||||
if (updateManager) {
|
||||
updateManager.onUpdateReady(() => {
|
||||
this.$dialog.alert({
|
||||
title: '更新提示',
|
||||
content: '新版本已经准备好,点击确认按钮重启应用!'
|
||||
}).then(() => {
|
||||
updateManager.applyUpdate()
|
||||
}).catch(() => {
|
||||
})
|
||||
})
|
||||
}
|
||||
}
|
||||
},
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss">
|
||||
@import "~dvcp-wui/common";
|
||||
/* #ifdef MP-BAIDU */
|
||||
page {
|
||||
width: 100%;
|
||||
display: block;
|
||||
}
|
||||
|
||||
swan-template {
|
||||
width: 100%;
|
||||
min-height: 100%;
|
||||
display: flex;
|
||||
}
|
||||
|
||||
/* 原生组件模式下需要注意组件外部样式 */
|
||||
custom-component {
|
||||
width: 100%;
|
||||
min-height: 100%;
|
||||
display: flex;
|
||||
}
|
||||
|
||||
/* #endif */
|
||||
|
||||
/* #ifdef MP-ALIPAY */
|
||||
page {
|
||||
min-height: 100vh;
|
||||
}
|
||||
|
||||
/* #endif */
|
||||
|
||||
/* 原生组件模式下需要注意组件外部样式 */
|
||||
m-input {
|
||||
width: 100%;
|
||||
/* min-height: 100%; */
|
||||
display: flex;
|
||||
flex: 1;
|
||||
}
|
||||
|
||||
.content {
|
||||
display: flex;
|
||||
flex: 1;
|
||||
flex-direction: column;
|
||||
background-color: #efeff4;
|
||||
padding: 10px;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
.input-group {
|
||||
background-color: #ffffff;
|
||||
margin-top: 20px;
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.input-group::before {
|
||||
position: absolute;
|
||||
right: 0;
|
||||
top: 0;
|
||||
left: 0;
|
||||
height: 1px;
|
||||
content: "";
|
||||
-webkit-transform: scaleY(0.5);
|
||||
transform: scaleY(0.5);
|
||||
background-color: #c8c7cc;
|
||||
}
|
||||
|
||||
.input-group::after {
|
||||
position: absolute;
|
||||
right: 0;
|
||||
bottom: 0;
|
||||
left: 0;
|
||||
height: 1px;
|
||||
content: "";
|
||||
-webkit-transform: scaleY(0.5);
|
||||
transform: scaleY(0.5);
|
||||
background-color: #c8c7cc;
|
||||
}
|
||||
|
||||
.input-row {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
position: relative;
|
||||
font-size: 18px;
|
||||
line-height: 40px;
|
||||
}
|
||||
|
||||
.input-row .title {
|
||||
width: 72px;
|
||||
padding-left: 15px;
|
||||
}
|
||||
|
||||
.input-row.border::after {
|
||||
position: absolute;
|
||||
right: 0;
|
||||
bottom: 0;
|
||||
left: 8px;
|
||||
height: 1px;
|
||||
content: "";
|
||||
-webkit-transform: scaleY(0.5);
|
||||
transform: scaleY(0.5);
|
||||
background-color: #c8c7cc;
|
||||
}
|
||||
|
||||
uni-tabbar .uni-tabbar-border {
|
||||
position: absolute;
|
||||
left: 0;
|
||||
top: 0;
|
||||
width: 100%;
|
||||
height: 0;
|
||||
-webkit-transform: scaleY(0.5);
|
||||
transform: scaleY(0.5);
|
||||
}
|
||||
|
||||
.btn-row {
|
||||
margin-top: 25px;
|
||||
padding: 10px;
|
||||
}
|
||||
|
||||
button.primary {
|
||||
background-color: #0faeff;
|
||||
}
|
||||
|
||||
.flexRow {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.u-input__right-icon {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
margin-right: 8px;
|
||||
}
|
||||
</style>
|
||||
69
src/components/AiAdd/AiAdd.vue
Normal file
@@ -0,0 +1,69 @@
|
||||
<template>
|
||||
<movable-area class="movableArea">
|
||||
<movable-view direction="all" x="300" y="500">
|
||||
<div class="AiAdd" @click.stop="add"></div>
|
||||
</movable-view>
|
||||
</movable-area>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
name: "AiAdd",
|
||||
props: {},
|
||||
data() {
|
||||
return {}
|
||||
},
|
||||
methods: {
|
||||
add() {
|
||||
console.log(789)
|
||||
this.$emit("add")
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.movableArea {
|
||||
position: fixed;
|
||||
left: 0;
|
||||
top: 0;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
pointer-events: none;
|
||||
z-index: 999;
|
||||
|
||||
uni-movable-view {
|
||||
pointer-events: auto;
|
||||
}
|
||||
}
|
||||
|
||||
.AiAdd {
|
||||
width: 96px;
|
||||
height: 96px;
|
||||
background: #1365DD;
|
||||
box-shadow: 0px 8px 16px 0px rgba(0, 0, 0, 0.2);
|
||||
border-radius: 50%;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
flex-direction: column;
|
||||
justify-content: center;
|
||||
|
||||
&:before, &:after {
|
||||
content: "";
|
||||
background: #FFFFFF;
|
||||
display: block;
|
||||
position: absolute;
|
||||
border-radius: 4px;
|
||||
}
|
||||
|
||||
&:before {
|
||||
height: 48px;
|
||||
width: 4px;
|
||||
}
|
||||
|
||||
&:after {
|
||||
height: 4px;
|
||||
width: 48px;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
146
src/components/AiAreaPicker/AiAreaPicker.vue
Normal file
@@ -0,0 +1,146 @@
|
||||
<template>
|
||||
<section class="AiAreaPicker">
|
||||
<div @tap="handleJump">
|
||||
<slot v-if="$slots.default"/>
|
||||
<div v-else-if="isForm">
|
||||
<ai-more v-model="areaName"/>
|
||||
</div>
|
||||
<div v-else class="areaBtn">
|
||||
<image :src="locationIcon" class="location"/>
|
||||
<div v-text="areaName"/>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import {mapState} from 'vuex'
|
||||
import AiMore from "../AiMore/AiMore";
|
||||
import qs from "query-string"
|
||||
|
||||
export default {
|
||||
name: 'AiAreaPicker',
|
||||
components: {AiMore},
|
||||
model: {
|
||||
prop: "value",
|
||||
event: "input"
|
||||
},
|
||||
props: {
|
||||
areaId: {default: ''},
|
||||
name: {default: ''},
|
||||
value: {default: ''},
|
||||
all: Boolean,
|
||||
icon: {default: "location.svg"},
|
||||
isForm: Boolean,
|
||||
valueLevel: {default: 5},
|
||||
fullName: {default: ''},
|
||||
disabled: Boolean,
|
||||
selectRoot: {default: true}
|
||||
},
|
||||
computed: {
|
||||
...mapState(['user']),
|
||||
dataRange() {
|
||||
let rules = [10, 8, 6, 3, 0],
|
||||
level = 0
|
||||
if (this.all || this.disabled) return (level = 0)
|
||||
rules.some((e, i) => {
|
||||
let reg = new RegExp(`0{${e}}`, 'g')
|
||||
if (reg.test(this.root)) {
|
||||
return (level = i)
|
||||
}
|
||||
})
|
||||
return level
|
||||
},
|
||||
root() {
|
||||
return this.areaId || this.$areaId
|
||||
},
|
||||
locationIcon() {
|
||||
return this.$cdn + this.icon
|
||||
},
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
fullArea: [],
|
||||
areaName: ""
|
||||
}
|
||||
},
|
||||
watch: {
|
||||
root(v) {
|
||||
v && (this.getFullArea(v))
|
||||
},
|
||||
value(v) {
|
||||
v && !this.areaName && this.getAreaName(this.value)
|
||||
},
|
||||
fullArea(v) {
|
||||
v && this.$emit('update:fullName', v?.map(e => e.name)?.join("") || "")
|
||||
},
|
||||
areaName(v) {
|
||||
v && this.$emit('update:name', v)
|
||||
}
|
||||
},
|
||||
created() {
|
||||
this.value && this.getAreaName(this.value)
|
||||
},
|
||||
methods: {
|
||||
getInfo(areaId) {
|
||||
return areaId && this.$instance.post('/admin/area/getAllParentAreaId', null, {
|
||||
withoutToken: true,
|
||||
params: {areaId},
|
||||
}).then(res => {
|
||||
if (res?.data) {
|
||||
return res.data.reverse()
|
||||
}
|
||||
})
|
||||
},
|
||||
getFullArea(areaId) {
|
||||
return this.fullArea?.length > 0 ? Promise.resolve(this.fullArea) : this.getInfo(areaId).then(meta => {
|
||||
if (meta.length > 1) {
|
||||
this.fullArea = meta.slice(this.dataRange)
|
||||
} else {
|
||||
this.fullArea = meta
|
||||
}
|
||||
return this.fullArea
|
||||
})
|
||||
},
|
||||
handleJump() {
|
||||
if (!this.disabled) {
|
||||
uni.$once('selectArea', data => {
|
||||
if (data?.id) {
|
||||
this.$emit("input", data.id)
|
||||
this.areaName = data.name
|
||||
this.fullArea = data.fullArea
|
||||
this.$forceUpdate()
|
||||
}
|
||||
})
|
||||
let {value, all, valueLevel, selectRoot, areaId} = this
|
||||
let url = qs.stringifyUrl({
|
||||
url: "/components/pages/selectArea", query: {...this.$attrs, value, all, valueLevel, selectRoot, areaId}
|
||||
})
|
||||
uni.navigateTo({url})
|
||||
}
|
||||
},
|
||||
getAreaName(area, name) {
|
||||
name ? this.areaName = name : this.getFullArea(area).then(list => {
|
||||
let arr = JSON.parse(JSON.stringify(list))
|
||||
this.areaName = arr?.reverse()?.[0]?.name
|
||||
})
|
||||
},
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.AiAreaPicker {
|
||||
|
||||
.areaBtn {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.location {
|
||||
width: 28px;
|
||||
height: 80px;
|
||||
margin-right: 12px;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
87
src/components/AiBack/AiBack.vue
Normal file
@@ -0,0 +1,87 @@
|
||||
<template>
|
||||
<div v-if="btn" class="AiBack" @click.stop="back">
|
||||
<img :src="$cdn + 'home/back.png'" alt="">
|
||||
<text>返回</text>
|
||||
</div>
|
||||
<ai-fixed-btn v-else-if="!isTopPage||custom">
|
||||
<div class="AiBack" @click.stop="back">
|
||||
<img :src="$cdn + 'home/back.png'" alt="">
|
||||
<text>返回</text>
|
||||
</div>
|
||||
</ai-fixed-btn>
|
||||
</template>
|
||||
<script>
|
||||
import AiFixedBtn from "./AiFixedBtn";
|
||||
|
||||
export default {
|
||||
name: "AiBack",
|
||||
components: {AiFixedBtn},
|
||||
inject: {root: {}},
|
||||
props: {
|
||||
delta: {
|
||||
type: Number,
|
||||
default: 1
|
||||
},
|
||||
eventName: {
|
||||
type: String,
|
||||
default: ''
|
||||
},
|
||||
data: {
|
||||
type: Object | Boolean,
|
||||
default: () => {
|
||||
}
|
||||
},
|
||||
custom: Boolean,
|
||||
visible: Boolean,
|
||||
btn: Boolean
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
isTopPage: false
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
back() {
|
||||
if (this.visible) {
|
||||
return this.$parent.$emit(this.eventName, this.data)
|
||||
} else if (this.custom) {
|
||||
this.$emit("back")
|
||||
} else if (this.custom) {
|
||||
} else uni.navigateBack({
|
||||
success: () => {
|
||||
uni.$emit(this.eventName, this.data)
|
||||
}
|
||||
})
|
||||
}
|
||||
},
|
||||
mounted() {
|
||||
this.isTopPage = window.history.length <= 1
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.AiBack {
|
||||
width: 108px;
|
||||
height: 108px;
|
||||
background: #6BA1F9;
|
||||
box-shadow: 0 0 12px 0 rgba(0, 0, 0, 0.12);
|
||||
border-radius: 50%;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
flex-direction: column;
|
||||
justify-content: center;
|
||||
|
||||
img {
|
||||
width: 40px;
|
||||
height: 40px;
|
||||
}
|
||||
|
||||
text {
|
||||
font-size: 26px;
|
||||
font-weight: 800;
|
||||
color: #FFFFFF;
|
||||
line-height: 40px;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
118
src/components/AiCard/AiCard.vue
Normal file
@@ -0,0 +1,118 @@
|
||||
<template>
|
||||
<section class="AiCard">
|
||||
<div flex v-if="$slots.custom" class="start">
|
||||
<div class="fill">
|
||||
<slot name="custom"/>
|
||||
</div>
|
||||
<div v-if="$slots.menu" class="iconfont iconfont-iconMore" @tap.stop="handleMore"/>
|
||||
</div>
|
||||
<template v-else>
|
||||
<u-row>
|
||||
<div class="content">
|
||||
<slot/>
|
||||
</div>
|
||||
<div btn @tap="$emit('send')">发送</div>
|
||||
</u-row>
|
||||
<u-row justify="space-between">
|
||||
<slot v-if="$slots.title" name="title"/>
|
||||
<div v-else>{{ cardTitle }}</div>
|
||||
<div v-if="$slots.menu" class="iconfont iconfont-iconMore" @tap.stop="handleMore"/>
|
||||
</u-row>
|
||||
</template>
|
||||
<div v-if="menu" class="mask" @click.stop="handleClose">
|
||||
<div class="moreMenu" :style="menuPos">
|
||||
<slot name="menu"/>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
name: "AiCard",
|
||||
props: {
|
||||
cardTitle: String
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
menuPos: {},
|
||||
menu: false
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
handleMore({detail}) {
|
||||
this.menuPos = {
|
||||
left: detail.x - 10 + 'px',
|
||||
top: detail.y + 'px'
|
||||
}
|
||||
this.menu = !this.menu
|
||||
},
|
||||
handleClose() {
|
||||
this.menu = false
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.AiCard {
|
||||
width: 100%;
|
||||
background: #FFFFFF;
|
||||
box-shadow: 0 8px 16px 0 rgba(0, 0, 0, 0.02);
|
||||
border-radius: 8px;
|
||||
padding: 20px;
|
||||
box-sizing: border-box;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
color: #999;
|
||||
font-size: 26px;
|
||||
flex-shrink: 0;
|
||||
|
||||
.content {
|
||||
background: #F9F9F9;
|
||||
border-radius: 4px;
|
||||
min-height: 120px;
|
||||
flex: 1;
|
||||
min-width: 0;
|
||||
margin-bottom: 26px;
|
||||
padding: 20px;
|
||||
box-sizing: border-box;
|
||||
color: #333;
|
||||
}
|
||||
|
||||
.u-row {
|
||||
flex-wrap: nowrap;
|
||||
}
|
||||
|
||||
div[btn] {
|
||||
color: #1365DD;
|
||||
padding: 0 0 0 18px;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.iconfont-iconMore {
|
||||
font-size: 38px;
|
||||
transform: rotate(90deg);
|
||||
}
|
||||
|
||||
.moreMenu {
|
||||
position: fixed;
|
||||
background: #FFFFFF;
|
||||
box-shadow: 0 8px 16px 0 rgba(0, 0, 0, 0.1);
|
||||
border-radius: 4px;
|
||||
transform: translate(-100%, -100%);
|
||||
min-width: 100px;
|
||||
min-height: 100px;
|
||||
z-index: 9;
|
||||
}
|
||||
|
||||
.mask {
|
||||
position: fixed;
|
||||
top: 0;
|
||||
bottom: 0;
|
||||
left: 0;
|
||||
right: 0;
|
||||
z-index: 11;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
76
src/components/AiCell/AiCell.vue
Normal file
@@ -0,0 +1,76 @@
|
||||
<template>
|
||||
<section class="AiCell" :class="{bottomBorder,alignCenter,topLabel}">
|
||||
<div class="label" :class="{title}">
|
||||
<slot v-if="$slots.label" name="label"/>
|
||||
<span v-else>{{ label }}</span>
|
||||
</div>
|
||||
<div class="content" :class="{topLabel}">
|
||||
<slot/>
|
||||
</div>
|
||||
</section>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
name: "AiCell",
|
||||
props: {
|
||||
label: {default: ""},
|
||||
bottomBorder: Boolean,
|
||||
topLabel: Boolean,
|
||||
title: Boolean,
|
||||
alignCenter: Boolean
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.AiCell {
|
||||
display: flex;
|
||||
min-height: 72px;
|
||||
font-size: 30px;
|
||||
color: #333;
|
||||
padding: 14px 0;
|
||||
box-sizing: border-box;
|
||||
justify-content: space-between;
|
||||
|
||||
&.bottomBorder {
|
||||
border-bottom: 1px solid #eee;
|
||||
}
|
||||
|
||||
&.alignCenter {
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
&.topLabel {
|
||||
flex-direction: column;
|
||||
}
|
||||
|
||||
.label {
|
||||
min-width: 60px;
|
||||
flex-shrink: 0;
|
||||
width: auto;
|
||||
color: #999;
|
||||
|
||||
|
||||
&.title {
|
||||
color: #333;
|
||||
font-weight: bold;
|
||||
font-size: 34px;
|
||||
}
|
||||
}
|
||||
|
||||
.content {
|
||||
flex: 1;
|
||||
min-width: 100px;
|
||||
min-height: 40px;
|
||||
max-width: 500px;
|
||||
text-align: right;
|
||||
|
||||
&.topLabel {
|
||||
text-align: start;
|
||||
margin-top: 16px;
|
||||
max-width: 100%;
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
97
src/components/AiCheckbox/AiCheckbox.vue
Normal file
@@ -0,0 +1,97 @@
|
||||
<template>
|
||||
<div class="AiCheckbox">
|
||||
<div
|
||||
class="AiCheckbox-item"
|
||||
v-for="(item, index) in options"
|
||||
@click="onChange(item.value)"
|
||||
:class="[choosed.indexOf(item.value) > -1 ? 'active' : '']"
|
||||
:key="index">
|
||||
{{ item.label }}
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
name: 'AiCheckbox',
|
||||
|
||||
model: {
|
||||
event: 'input',
|
||||
prop: 'value'
|
||||
},
|
||||
|
||||
props: {
|
||||
value: Array,
|
||||
placeholder: {
|
||||
default: '请选择'
|
||||
},
|
||||
list: {
|
||||
default: () => []
|
||||
},
|
||||
dict: String,
|
||||
disabled: Boolean
|
||||
},
|
||||
|
||||
data () {
|
||||
return {
|
||||
dictKey: '',
|
||||
choosed: []
|
||||
}
|
||||
},
|
||||
|
||||
computed: {
|
||||
options () {
|
||||
return this.dictKey ? this.$dict.getDict(this.dict).map(e => ({
|
||||
value: e.dictValue,
|
||||
label: e.dictName
|
||||
})) : this.list
|
||||
}
|
||||
},
|
||||
|
||||
mounted () {
|
||||
this.$dict.load(this.dict).then(() => {
|
||||
this.dictKey = this.dict
|
||||
})
|
||||
},
|
||||
|
||||
methods: {
|
||||
onChange (value) {
|
||||
if (this.choosed.indexOf(value) > -1) {
|
||||
this.choosed.splice(this.choosed.indexOf(value), 1)
|
||||
} else {
|
||||
this.choosed.push(value)
|
||||
}
|
||||
|
||||
this.$emit('input', this.choosed)
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.AiCheckbox {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
flex-wrap: wrap;
|
||||
|
||||
.AiCheckbox-item {
|
||||
width: 100%;
|
||||
line-height: 1.3;
|
||||
padding: 20px 32px;
|
||||
margin-bottom: 16px;
|
||||
text-align: center;
|
||||
background: #FFFFFF;
|
||||
box-sizing: border-box;
|
||||
border-radius: 16px;
|
||||
color: #333333;
|
||||
font-size: 28px;
|
||||
border: 1px solid #CCCCCC;
|
||||
|
||||
&.active {
|
||||
background: #4181FF;
|
||||
color: #fff;
|
||||
border-color: #4181FF;
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
178
src/components/AiComment/AiComment.vue
Normal file
@@ -0,0 +1,178 @@
|
||||
<template>
|
||||
<div class="AiComment">
|
||||
<div class="pageTitle flex">
|
||||
评论
|
||||
<div class="mar-l16" v-text="total"/>
|
||||
</div>
|
||||
<div class="flex item" v-for="row in list" :key="row.id">
|
||||
<img :src="row.avatar"/>
|
||||
<div class="fill">
|
||||
<div class="flex font-32">
|
||||
<div class="fill font600 font-28" v-text="row.name"/>
|
||||
<AiThumbsUp :bid="row.id" type="comment" :count.sync="row.hotCount"/>
|
||||
</div>
|
||||
<div class="font-32 mar-t8 mar-b24" v-text="row.content"/>
|
||||
<div class="flex mar-b24">
|
||||
<div class="color-999" v-text="[row.areaName,row.commentTime].join(' ')"/>
|
||||
<comment-editor class="mar-l16" :bid="row.id" type="2">回复TA</comment-editor>
|
||||
</div>
|
||||
<div v-if="getArrayLength(row.replyList)>0" class="replyList">
|
||||
<div v-if="row.showAllReply">
|
||||
<div class="flex color-666 mar-t8" v-for="reply in row.replyList" :key="reply.id">
|
||||
<div class="font600" v-text="reply.name+':'"/>
|
||||
<div v-text="reply.content"/>
|
||||
</div>
|
||||
<div v-if="getArrayLength(row.replyList)>2" class="color-687DA6 mar-t8" v-text="`收起`" @click="handleExpand(row)"/>
|
||||
</div>
|
||||
<div v-else>
|
||||
<div class="flex color-666 mar-t8" v-for="reply in getReplies(row.replyList)" :key="reply.id">
|
||||
<div class="font600" v-text="reply.name+':'"/>
|
||||
<div v-text="reply.content"/>
|
||||
</div>
|
||||
<div v-if="getArrayLength(row.replyList)>2" class="color-687DA6 mar-t8" v-text="`查看全部${getArrayLength(row.replyList)}条回复 >`"
|
||||
@click="handleExpand(row)"/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<comment-editor class="fixedBottom" :bid="bid" :comment-count="total"/>
|
||||
<u-gap height="128"/>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
|
||||
import CommentEditor from "./commentEditor";
|
||||
import AiThumbsUp from "../AiThumbsUp/AiThumbsUp";
|
||||
|
||||
export default {
|
||||
name: "AiComment",
|
||||
components: {AiThumbsUp, CommentEditor},
|
||||
props: {
|
||||
bid: {default: ""}
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
list: [],
|
||||
current: 1,
|
||||
total: 0
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
getComments() {
|
||||
let {current, total, bid: contentId} = this
|
||||
if (!total || this.list.length < total) {
|
||||
this.$instance.post("/app/appcontentcomment/list", null, {
|
||||
params: {current, contentId}
|
||||
}).then(res => {
|
||||
if (res?.data) {
|
||||
res.data.records.map(e => e.showAllReply = false)
|
||||
this.list = [current == 1 ? [] : this.list, res.data.records].flat()
|
||||
this.total = res.data.total
|
||||
}
|
||||
})
|
||||
}
|
||||
},
|
||||
getReplies(list, showAll) {
|
||||
return list?.slice(0, showAll ? this.getArrayLength(list) : 2) || []
|
||||
},
|
||||
getArrayLength(list) {
|
||||
return list?.length || 0
|
||||
},
|
||||
handleExpand(row) {
|
||||
console.log(row)
|
||||
row.showAllReply = !row.showAllReply
|
||||
}
|
||||
},
|
||||
created() {
|
||||
this.getComments()
|
||||
uni.$on("moreComments", flag => {
|
||||
flag == 1 ? this.current = 1 : this.current++
|
||||
this.getComments()
|
||||
})
|
||||
},
|
||||
destroyed() {
|
||||
uni.$off("moreComments")
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.AiComment {
|
||||
background: #fff;
|
||||
|
||||
.item {
|
||||
padding: 24px 32px;
|
||||
align-items: flex-start;
|
||||
color: #333;
|
||||
font-size: 26px;
|
||||
|
||||
& > img {
|
||||
height: 64px;
|
||||
width: 64px;
|
||||
border-radius: 50%;
|
||||
margin-right: 16px;
|
||||
}
|
||||
|
||||
.content {
|
||||
margin: 8px 0 24px;
|
||||
}
|
||||
}
|
||||
|
||||
.font600 {
|
||||
font-weight: 600;
|
||||
}
|
||||
|
||||
.font-32 {
|
||||
font-size: 32px;
|
||||
}
|
||||
|
||||
.font-28 {
|
||||
font-size: 28px;
|
||||
}
|
||||
|
||||
.mar-t8 {
|
||||
margin-top: 8px;
|
||||
}
|
||||
|
||||
.mar-b24 {
|
||||
margin-bottom: 24px;
|
||||
}
|
||||
|
||||
.mar-r16 {
|
||||
margin-right: 16px;
|
||||
}
|
||||
|
||||
.mar-l16 {
|
||||
margin-left: 16px;
|
||||
}
|
||||
|
||||
.color-999 {
|
||||
color: #999;
|
||||
}
|
||||
|
||||
.color-666 {
|
||||
color: #666;
|
||||
}
|
||||
|
||||
.color-687DA6 {
|
||||
color: #687DA6;
|
||||
}
|
||||
|
||||
.replyList {
|
||||
padding: 8px 16px 16px;
|
||||
background: #F4F5FA;
|
||||
border-radius: 8px;
|
||||
font-size: 28px;
|
||||
}
|
||||
|
||||
.pageTitle {
|
||||
height: 100px;
|
||||
padding: 0 32px;
|
||||
font-size: 34px;
|
||||
font-family: PingFangSC-Semibold, PingFang SC;
|
||||
font-weight: 600;
|
||||
color: #333333;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
217
src/components/AiComment/commentEditor.vue
Normal file
@@ -0,0 +1,217 @@
|
||||
<template>
|
||||
<section class="commentEditor">
|
||||
<div v-if="$slots.default" @click="showCommentBox">
|
||||
<slot/>
|
||||
</div>
|
||||
<div v-else class="comments flex-row">
|
||||
<div class="comments-box" @click="showCommentBox">{{ boxContent }}</div>
|
||||
<img src="./static/comment.svg" alt=""/>
|
||||
<text>{{ commentCount || 0 }}</text>
|
||||
</div>
|
||||
<div class="modalWrapper" v-if="commentBoxPopup" :class="{clickClose:!modelClickClose}"
|
||||
@click="commentBoxPopup=false"/>
|
||||
<div class="commentBox" v-if="commentBoxPopup" :style="{bottom:marginBottom+ 'px'}">
|
||||
<textarea v-model="content" placeholder="写下你的想法…" maxlength="300" :focus="focus" @focus="getMarginBottom"
|
||||
@blur="marginBottom=0" :adjust-position="false" fixed/>
|
||||
<view class="flex-row form-submit">
|
||||
<div>{{ `字数 ${wordCount || 0} / 300` }}</div>
|
||||
<button @click="submitComment" :disabled="wordCount == 0">发布</button>
|
||||
</view>
|
||||
</div>
|
||||
</section>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
name: "commentEditor",
|
||||
props: {
|
||||
bid: {default: ""},
|
||||
type: {default: 1},
|
||||
needLogin: Boolean,
|
||||
customLogin: Boolean,
|
||||
commentCount: Number,
|
||||
modelClickClose: {type: Boolean, default: true}
|
||||
},
|
||||
computed: {
|
||||
wordCount() {
|
||||
return this.content.length || 0
|
||||
},
|
||||
boxContent() {
|
||||
return this.content || "我也说两句..."
|
||||
},
|
||||
isLogin() {
|
||||
return Boolean(uni.getStorageSync('token'))
|
||||
},
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
content: "",
|
||||
marginBottom: 0,
|
||||
commentBoxPopup: false,
|
||||
focus: false
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
showCommentBox() {
|
||||
if (this.customLogin) {
|
||||
this.$emit("login", flag => this.commentBoxPopup = flag)
|
||||
} else if (this.needLogin) {
|
||||
if (this.isLogin) {
|
||||
this.commentBoxPopup = true
|
||||
} else {
|
||||
this.$dialog.confirm({
|
||||
content: '您还未登陆',
|
||||
confirmText: '去登录'
|
||||
}).then(() => {
|
||||
uni.switchTab({url: '/pages/AppMine/AppMine'})
|
||||
}).catch(() => {
|
||||
})
|
||||
}
|
||||
} else {
|
||||
this.commentBoxPopup = true
|
||||
}
|
||||
},
|
||||
submitComment() {
|
||||
let {content, type, bid: contentId} = this
|
||||
this.$instance.post("/app/appcontentcomment/addByApplet", {content, type, contentId}).then(res => {
|
||||
if (res?.code == 0) {
|
||||
this.$u.toast("提交成功!")
|
||||
this.commentBoxPopup = false
|
||||
this.content = ""
|
||||
uni.$emit("moreComments", 1)//刷新评论列表
|
||||
}
|
||||
})
|
||||
},
|
||||
getMarginBottom({detail}) {
|
||||
this.marginBottom = detail.height
|
||||
this.focus = true
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.commentEditor {
|
||||
font-family: PingFangSC-Regular, PingFang SC;
|
||||
|
||||
.comments {
|
||||
width: 100%;
|
||||
height: 128px;
|
||||
padding: 24px 32px;
|
||||
box-sizing: border-box;
|
||||
position: fixed;
|
||||
bottom: 0;
|
||||
background: #fff;
|
||||
border-top: 1px solid #eee;
|
||||
|
||||
.comments-box {
|
||||
width: 580px;
|
||||
height: 80px;
|
||||
line-height: 80px;
|
||||
background-color: #F4F5FA;
|
||||
color: #666;
|
||||
font-size: 32px;
|
||||
padding-left: 32px;
|
||||
white-space: nowrap;
|
||||
text-overflow: ellipsis;
|
||||
overflow: hidden;
|
||||
border-radius: 44px;
|
||||
}
|
||||
|
||||
image {
|
||||
width: 52px;
|
||||
height: 52px;
|
||||
margin-left: 16px;
|
||||
vertical-align: middle;
|
||||
}
|
||||
|
||||
text {
|
||||
color: #666666;
|
||||
font-size: 28px;
|
||||
line-height: 60px;
|
||||
}
|
||||
}
|
||||
|
||||
.modalWrapper {
|
||||
position: fixed;
|
||||
top: 0;
|
||||
left: 0;
|
||||
right: 0;
|
||||
bottom: 0;
|
||||
background: rgba(0, 0, 0, .6);
|
||||
z-index: 9;
|
||||
|
||||
&.clickClose {
|
||||
pointer-events: none;
|
||||
}
|
||||
}
|
||||
|
||||
.commentBox {
|
||||
width: 100vw;
|
||||
height: 288px;
|
||||
background-color: #fff;
|
||||
padding: 32px 32px 24px 26px;
|
||||
box-sizing: border-box;
|
||||
position: fixed;
|
||||
left: 0;
|
||||
bottom: 0;
|
||||
z-index: 99;
|
||||
|
||||
textarea {
|
||||
width: 100%;
|
||||
height: 144px;
|
||||
color: #666;
|
||||
font-size: 26px;
|
||||
background: #F7F7F7;
|
||||
border-radius: 16px;
|
||||
padding: 16px;
|
||||
box-sizing: border-box;
|
||||
|
||||
&::placeholder {
|
||||
font-size: inherit;
|
||||
}
|
||||
}
|
||||
|
||||
.form-submit {
|
||||
margin-top: 24px;
|
||||
height: 64px;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
color: #999;
|
||||
font-size: 24px;
|
||||
|
||||
button {
|
||||
width: 144px;
|
||||
height: 64px;
|
||||
background-color: #135AB8;
|
||||
color: #fff;
|
||||
font-size: 24px;
|
||||
border-radius: 32px;
|
||||
line-height: 64px;
|
||||
text-align: center;
|
||||
margin: unset;
|
||||
|
||||
&[disabled] {
|
||||
color: #999;
|
||||
background-color: #f7f7f7;
|
||||
font-size: 28px;
|
||||
border: 0;
|
||||
}
|
||||
|
||||
&:active {
|
||||
opacity: .8;
|
||||
}
|
||||
|
||||
&:after {
|
||||
border: none;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.flex-row {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
11
src/components/AiComment/static/comment.svg
Normal file
@@ -0,0 +1,11 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<svg width="26px" height="26px" viewBox="0 0 26 26" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
|
||||
<!-- Generator: Sketch 55.2 (78181) - https://sketchapp.com -->
|
||||
<title>icon/tab_bar/Comment</title>
|
||||
<desc>Created with Sketch.</desc>
|
||||
<g id="icon/tab_bar/Comment" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
|
||||
<path d="M4.75,21.7864745 L9.45344419,19.4347524 C9.6964412,19.3132539 9.96438906,19.25 10.236068,19.25 L20,19.25 C20.6903559,19.25 21.25,18.6903559 21.25,18 L21.25,8 C21.25,7.30964406 20.6903559,6.75 20,6.75 L6,6.75 C5.30964406,6.75 4.75,7.30964406 4.75,8 L4.75,21.7864745 Z" id="矩形" stroke="#333333" stroke-width="1.5"></path>
|
||||
<rect id="矩形" fill="#999999" x="8" y="10.5" width="10" height="1.5" rx="0.75"></rect>
|
||||
<rect id="矩形备份" fill="#999999" x="8" y="14" width="10" height="1.5" rx="0.75"></rect>
|
||||
</g>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 983 B |
68
src/components/AiDate/AiDate.vue
Normal file
@@ -0,0 +1,68 @@
|
||||
<template>
|
||||
<section class="AiDate">
|
||||
<u-calendar v-model="show" :maxDate="maxDate"
|
||||
@change="handleSelect" :mode="mode" @close="show=false"/>
|
||||
<div class="flex" @click="show=true">
|
||||
<div class="label" v-if="label" v-html="label"/>
|
||||
<div class="placeholder" v-else v-html="placeholder"/>
|
||||
<u-icon name="arrow-right" color="#ddd"/>
|
||||
</div>
|
||||
</section>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import dayjs from 'dayjs'
|
||||
|
||||
export default {
|
||||
name: "AiDate",
|
||||
computed: {
|
||||
label() {
|
||||
let arr = (this.selected || this.value)?.toString()?.split(",") || []
|
||||
arr = arr.map(e => dayjs(e).format("YYYY-MM-DD").replace("Invalid Date", ''))
|
||||
return arr.join('至')
|
||||
}
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
show: false,
|
||||
selected: ""
|
||||
}
|
||||
},
|
||||
props: {
|
||||
value: {default: ""},
|
||||
placeholder: {default: "请选择"},
|
||||
mode: {default: "date"},//date 单个日期|range 日期范围
|
||||
maxDate: String
|
||||
},
|
||||
methods: {
|
||||
handleSelect(v) {
|
||||
if (this.mode == 'date') {
|
||||
this.selected = v.result
|
||||
this.$emit('change', v.result)
|
||||
} else if (this.mode == 'range') {
|
||||
this.selected = [v.startDate, v.endDate]
|
||||
this.$emit('change', v)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.AiDate {
|
||||
color: #333333;
|
||||
font-size: 30px;
|
||||
|
||||
.label {
|
||||
font-size: 30px;
|
||||
}
|
||||
|
||||
::v-deep .u-icon {
|
||||
margin-left: 8px;
|
||||
}
|
||||
|
||||
.placeholder {
|
||||
color: $uni-text-color-grey;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
143
src/components/AiDetail/AiDetail.vue
Normal file
@@ -0,0 +1,143 @@
|
||||
<template>
|
||||
<section class="AiDetail">
|
||||
<div class="content">
|
||||
<div class="title">{{ detail.title }}</div>
|
||||
<div class="info">
|
||||
<span>{{ detail.createTime }}</span>
|
||||
<span class="right">
|
||||
<em>{{ detail.viewCount }}</em>人看过
|
||||
</span>
|
||||
</div>
|
||||
<slot v-if="$slots.content" name="content"/>
|
||||
<u-parse v-else :html="detail.content"/>
|
||||
</div>
|
||||
<!-- <div class="files" v-if="detail.contentType==0 && detail.files && detail.files.length">-->
|
||||
<!-- <img class="file-img" :src="file.url" @click.native="preview(index)" alt="" v-for="(file,index) in detail.files" :key="index">-->
|
||||
<!-- </div>-->
|
||||
|
||||
<div class="files" v-if="detail.contentType==1 && detail.files && detail.files.length">
|
||||
<video class="file-img" :src="file.url" v-for="(file,index) in detail.files" :key="index"/>
|
||||
</div>
|
||||
</section>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
|
||||
export default {
|
||||
name: "AiDetail",
|
||||
props: {
|
||||
title: {default: ""},
|
||||
detail: {default: () => ({})},
|
||||
},
|
||||
methods: {
|
||||
preview(index) {
|
||||
this.$previewImage(this.detail.files, index, "url");
|
||||
}
|
||||
},
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.AiDetail {
|
||||
padding-bottom: 80px;
|
||||
background: #fff;
|
||||
|
||||
.header {
|
||||
.title {
|
||||
font-weight: bold;
|
||||
font-size: 48px;
|
||||
}
|
||||
|
||||
.bottomBar {
|
||||
justify-content: space-between;
|
||||
margin-top: 16px;
|
||||
color: #999;
|
||||
|
||||
.u-icon + .u-icon {
|
||||
margin-left: 32px;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.content {
|
||||
padding: 32px;
|
||||
background: #fff;
|
||||
|
||||
&.content {
|
||||
margin-bottom: 20px;
|
||||
|
||||
.title {
|
||||
font-size: 38px;
|
||||
font-weight: 600;
|
||||
color: #333333;
|
||||
line-height: 52px;
|
||||
margin-bottom: 32px;
|
||||
}
|
||||
|
||||
.info {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
margin-bottom: 64px;
|
||||
font-size: 30px;
|
||||
font-weight: 400;
|
||||
color: #999999;
|
||||
|
||||
.right {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
|
||||
& > em {
|
||||
color: #4181FF;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.files {
|
||||
padding: 0 32px;
|
||||
background: #fff;
|
||||
|
||||
.file-img {
|
||||
width: 100%;
|
||||
height: 486px;
|
||||
margin-bottom: 32px;
|
||||
}
|
||||
}
|
||||
|
||||
.imageList {
|
||||
justify-content: space-around;
|
||||
|
||||
.AiImage {
|
||||
margin-right: 8px;
|
||||
margin-bottom: 8px;
|
||||
}
|
||||
}
|
||||
|
||||
.fileList {
|
||||
& > div {
|
||||
margin-bottom: 8px;
|
||||
}
|
||||
|
||||
.info {
|
||||
flex: 1;
|
||||
min-width: 0;
|
||||
display: flex;
|
||||
margin-left: 16px;
|
||||
word-break: break-all;
|
||||
align-items: center;
|
||||
|
||||
& > span {
|
||||
flex: 1;
|
||||
min-width: 0;
|
||||
}
|
||||
|
||||
& > i {
|
||||
flex-shrink: 0;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
</style>
|
||||
56
src/components/AiEmpty/AiEmpty.vue
Normal file
@@ -0,0 +1,56 @@
|
||||
<template>
|
||||
<div class="emptyWrap">
|
||||
<img class="emptyImg" :src="emptyImg" :class="noPermit ? 'small-img' : ''">
|
||||
<div class="emptyText" v-html="description"></div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
name: "AiEmpty",
|
||||
props: {
|
||||
img: {default: "https://cdn.cunwuyun.cn/dvcp/h5/no-admin.png"},
|
||||
noPermit: Boolean,
|
||||
description: {
|
||||
default: '暂无相关信息',
|
||||
type: String
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
emptyImg() {
|
||||
return this.noPermit ? "https://cdn.cunwuyun.cn/dvcp/h5/no-admin.png" : this.img
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.emptyWrap {
|
||||
width: 100%;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
// margin-top: 100px;
|
||||
margin-bottom: 20px;
|
||||
|
||||
.emptyImg {
|
||||
width: 300px;
|
||||
height: 310px;
|
||||
margin-top: 52px;
|
||||
}
|
||||
|
||||
.small-img {
|
||||
width: 282px;
|
||||
height: 306px;
|
||||
}
|
||||
|
||||
.emptyText {
|
||||
font-size: 29px;
|
||||
font-family: PingFangSC-Regular, PingFang SC;
|
||||
font-weight: 400;
|
||||
color: rgba(183, 183, 183, 1);
|
||||
text-align: center;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
83
src/components/AiEvaluation/AiEvaluation.vue
Normal file
@@ -0,0 +1,83 @@
|
||||
<template>
|
||||
<section class="AiEvaluation">
|
||||
<div v-if="type=='submit'">
|
||||
<AiPagePicker v-if="!hasEvaluated" type="custom" :ops="ops" nodeKey="">
|
||||
<slot v-if="$slots.default"/>
|
||||
<div v-else v-text="placeholder"/>
|
||||
</AiPagePicker>
|
||||
<slot name="finish" v-else-if="$slots.finish"/>
|
||||
</div>
|
||||
<div v-else-if="type=='show'">
|
||||
<slot v-if="$slots.default" :evaluation="detail"/>
|
||||
<AiGroup v-if="hasEvaluated" description no-border labelColor="#999" v-else>
|
||||
<AiItem label="评级分数">
|
||||
<u-rate v-model="detail.score" disabled inactive-icon="star-fill" active-color="#F8B425"/>
|
||||
{{ detail.rateText || "" }}
|
||||
</AiItem>
|
||||
<AiItem label="评价详情" top-label>
|
||||
<div v-html="detail.content"/>
|
||||
</AiItem>
|
||||
<AiItem label="附件" top-label>
|
||||
<AiUploader :def="detail.files" disabled preview/>
|
||||
</AiItem>
|
||||
</AiGroup>
|
||||
</div>
|
||||
</section>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import AiPagePicker from "../AiPagePicker/AiPagePicker";
|
||||
import AiGroup from "../AiGroup/AiGroup";
|
||||
import AiItem from "../AiItem/AiItem";
|
||||
import AiUploader from "../AiUploader/AiUploader";
|
||||
|
||||
export default {
|
||||
name: "AiEvaluation",
|
||||
model: {
|
||||
prop: "info",
|
||||
event: "input"
|
||||
},
|
||||
props: {
|
||||
info: {default: () => ({})},
|
||||
placeholder: {default: "去评价"},
|
||||
bid: {default: ""},
|
||||
type: {default: "submit"} //可选值: submit:提交评价,show:展示评价
|
||||
},
|
||||
components: {AiUploader, AiItem, AiGroup, AiPagePicker},
|
||||
computed: {
|
||||
isShow: v => v.type == 'show',
|
||||
hasEvaluated: v => !!v.detail?.id
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
detail: {},
|
||||
ops: {
|
||||
rateTexts: ['非常不满意', '不满意', '一般', '满意', '非常满意'],
|
||||
url: "/components/pages/submitEvaluation?bid=" + this.bid
|
||||
}
|
||||
}
|
||||
},
|
||||
watch: {
|
||||
bid: {
|
||||
immediate: true,
|
||||
handler() {
|
||||
this.getDetail()
|
||||
}
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
getDetail() {
|
||||
const bizId = this.bid
|
||||
bizId && this.$instance.post("/app/appbusinesscompletionevaluation/queryMyEvaluationByBizId", null, {
|
||||
params: {bizId}
|
||||
}).then(res => {
|
||||
if (res?.data) {
|
||||
const info = res.data?.[0]
|
||||
this.detail = {...info, rateText: this.rateTexts?.[info.score - 1]}
|
||||
this.$emit("input", this.detail)
|
||||
}
|
||||
})
|
||||
}
|
||||
},
|
||||
}
|
||||
</script>
|
||||
35
src/components/AiFixedBtn/AiFixedBtn.vue
Normal file
@@ -0,0 +1,35 @@
|
||||
<template>
|
||||
<section class="AiFixedBtn">
|
||||
<movable-area class="movableArea">
|
||||
<movable-view direction="all" x="300" y="500" @tap.stop>
|
||||
<slot/>
|
||||
</movable-view>
|
||||
</movable-area>
|
||||
</section>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
name: "AiFixedBtn"
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.AiFixedBtn {
|
||||
.movableArea {
|
||||
position: fixed;
|
||||
left: 0;
|
||||
top: 0;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
pointer-events: none;
|
||||
z-index: 999;
|
||||
|
||||
uni-movable-view {
|
||||
pointer-events: auto;
|
||||
width: auto;
|
||||
height: auto;
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
61
src/components/AiGroup/AiGroup.vue
Normal file
@@ -0,0 +1,61 @@
|
||||
<template>
|
||||
<section class="AiGroup" :class="{noBorder,description}" :style="{paddingLeft:left+'rpx'}">
|
||||
<div class="groupHeader" v-if="title" v-text="title"/>
|
||||
<slot/>
|
||||
</section>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
name: "AiGroup",
|
||||
provide() {
|
||||
return {
|
||||
labelColor: this.labelColor,
|
||||
description: this.description,
|
||||
activeStep: this.activeStep
|
||||
}
|
||||
},
|
||||
props: {
|
||||
title: String,
|
||||
noBorder: Boolean,
|
||||
left: {default: 32},
|
||||
labelColor: {default: "#333"},
|
||||
description: {default: false}, //用于展示则不会又红星,会把标签的内间距去掉
|
||||
activeStep: {default: 1}//用于步骤组件的当前步数
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
items: []
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.AiGroup {
|
||||
background: #FFFFFF;
|
||||
box-shadow: inset 0px -1px 0px 0px #DDDDDD;
|
||||
|
||||
&.noBorder {
|
||||
box-shadow: none;
|
||||
}
|
||||
|
||||
& + .AiGroup {
|
||||
margin-top: 16px;
|
||||
}
|
||||
|
||||
.groupHeader {
|
||||
font-weight: bold;
|
||||
font-size: 36px;
|
||||
padding-left: 20px;
|
||||
margin-bottom: 16px;
|
||||
}
|
||||
|
||||
&.description {
|
||||
.groupHeader {
|
||||
padding-left: 0;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
</style>
|
||||
26
src/components/AiIcon/AiIcon.vue
Normal file
@@ -0,0 +1,26 @@
|
||||
<template>
|
||||
<section class="AiIcon">
|
||||
<view v-if="!singleColor" class="ai-icon" :class="icon" :style="{width:size+'px',height:size+'px'}"/>
|
||||
<view v-else class="iconfont" :style="{ fontSize: size + 'rpx', color: color }">{{ icon }}</view>
|
||||
</section>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
name: "AiIcon",
|
||||
props: {
|
||||
icon: String,
|
||||
singleColor: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
},
|
||||
color: {
|
||||
type: String
|
||||
},
|
||||
size: {type: String, default: "32"}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
<style scoped>
|
||||
@import "./iconcss.css";
|
||||
</style>
|
||||
658
src/components/AiIcon/iconcss.css
Normal file
72
src/components/AiImage/AiImage.vue
Normal file
@@ -0,0 +1,72 @@
|
||||
<template>
|
||||
<section class="AiImage">
|
||||
<div v-if="$slots.default" @tap="prev">
|
||||
<slot/>
|
||||
</div>
|
||||
<u-image v-else :src="image" @tap="prev">
|
||||
<image v-if="link" class="errorImage" slot="error" :src="cdn+'link.png'"/>
|
||||
<image v-else-if="miniapp" class="errorImage" slot="error" :src="cdn+'miniwxmp.jpg'"/>
|
||||
<image v-else class="errorImage" slot="error" :src="cdn+'file.png'"/>
|
||||
</u-image>
|
||||
</section>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import {mapActions} from "vuex";
|
||||
|
||||
export default {
|
||||
name: "AiImage",
|
||||
data() {
|
||||
return {
|
||||
dialog: false,
|
||||
cdn: "https://cdn.cunwuyun.cn/"
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
image() {
|
||||
return this.src?.replace(/\\/g, '/')
|
||||
}
|
||||
},
|
||||
props: {
|
||||
src: String,
|
||||
preview: Boolean,
|
||||
link: Boolean,
|
||||
miniapp: Boolean,
|
||||
file: {default: () => ({})}
|
||||
},
|
||||
methods: {
|
||||
...mapActions(['previewFile', 'injectJWeixin']),
|
||||
prev() {
|
||||
if (this.preview) {
|
||||
if (!!this.image) {
|
||||
uni.previewImage({
|
||||
current: this.image,
|
||||
urls: [this.image],
|
||||
})
|
||||
} else {
|
||||
this.previewFile({size: 1, ...this.file})
|
||||
}
|
||||
}
|
||||
},
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.AiImage {
|
||||
::v-deep image {
|
||||
width: 160px;
|
||||
height: 160px;
|
||||
object-fit: cover;
|
||||
}
|
||||
|
||||
::v-deep .u-image__error {
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.errorImage {
|
||||
width: 80px;
|
||||
height: 80px;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
125
src/components/AiItem/AiItem.vue
Normal file
@@ -0,0 +1,125 @@
|
||||
<template>
|
||||
<section class="AiItem" :class="{border,readonly}">
|
||||
<div v-if="topLabel" class="topLabel">
|
||||
<div class="labelPane flex">
|
||||
<div class="label" :class="{required,labelBold}" :style="{color}" v-text="label"/>
|
||||
<slot name="sub" v-if="$slots.sub"/>
|
||||
</div>
|
||||
<div class="itemContent">
|
||||
<slot v-if="$slots.default"/>
|
||||
<div v-else v-text="value"/>
|
||||
</div>
|
||||
</div>
|
||||
<div v-else class="normal flex">
|
||||
<div class="fill flex">
|
||||
<div class="label" :class="{required,labelBold}" :style="{color}" v-text="label"/>
|
||||
<slot name="sub" v-if="$slots.sub"/>
|
||||
</div>
|
||||
<div class="flexContent">
|
||||
<slot v-if="$slots.default"/>
|
||||
<div v-else v-text="value"/>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
name: "AiItem",
|
||||
inject: {
|
||||
labelColor: {default: "#333"},
|
||||
description: {default: false}
|
||||
},
|
||||
props: {
|
||||
value: {default: ""},
|
||||
label: {default: ""},
|
||||
required: Boolean,
|
||||
topLabel: Boolean,
|
||||
border: {default: true},
|
||||
labelBold: Boolean,
|
||||
},
|
||||
computed: {
|
||||
color: v => v.labelColor,
|
||||
readonly: v => !!v.description
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.AiItem {
|
||||
font-family: PingFangSC-Regular, PingFang SC;
|
||||
|
||||
&.border {
|
||||
.normal {
|
||||
border-bottom: 2px solid #ddd;
|
||||
}
|
||||
|
||||
.topLabel {
|
||||
border-bottom: 2px solid #ddd;
|
||||
}
|
||||
}
|
||||
|
||||
.normal {
|
||||
width: 100%;
|
||||
padding: 32px 32px 32px 0;
|
||||
line-height: 44px;
|
||||
box-sizing: border-box;
|
||||
// height: 112px;
|
||||
|
||||
.flexContent {
|
||||
max-width: 62vw;
|
||||
}
|
||||
}
|
||||
|
||||
.label {
|
||||
padding-left: 20px;
|
||||
font-weight: 400;
|
||||
margin-right: 20px;
|
||||
position: relative;
|
||||
|
||||
&.required:before {
|
||||
position: absolute;
|
||||
display: block;
|
||||
left: 0;
|
||||
top: 50%;
|
||||
transform: translateY(-50%);
|
||||
content: "*";
|
||||
color: #f46;
|
||||
}
|
||||
|
||||
&.labelBold {
|
||||
font-weight: bold;
|
||||
font-size: 34px;
|
||||
}
|
||||
}
|
||||
|
||||
::v-deep.topLabel {
|
||||
padding: 32px 32px 32px 0;
|
||||
|
||||
.labelPane {
|
||||
margin-bottom: 32px;
|
||||
}
|
||||
|
||||
.itemContent {
|
||||
padding-left: 20px;
|
||||
|
||||
.AiMore > .u-icon {
|
||||
width: 100%;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//展示模式下的特有样式
|
||||
&.readonly {
|
||||
.label, .itemContent {
|
||||
padding-left: 0;
|
||||
}
|
||||
}
|
||||
|
||||
.AiStep:last-of-type {
|
||||
.stepLine {
|
||||
display: none
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
113
src/components/AiListPage/AiListPage.vue
Normal file
@@ -0,0 +1,113 @@
|
||||
<template>
|
||||
<section class="AppListPage">
|
||||
<div class="header" :style="{backgroundImage: `url(${headerBg})`}">
|
||||
<img :src="headerBg" alt="">
|
||||
<p>{{label}}</p>
|
||||
</div>
|
||||
<div class="content">
|
||||
<div class="title">{{label}}</div>
|
||||
<div class="app-list">
|
||||
<div class="item" v-for="(item, index) in appList" :key="index" @click="linkTo(item.url)" >
|
||||
<!-- <div class="icon" :style="{backgroundImage: url(item.icon)}"></div> -->
|
||||
<img :src="item.icon" alt="" class="icon">
|
||||
<p>{{item.name}}</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</section>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
|
||||
export default {
|
||||
name: "AppListPage",
|
||||
props: {
|
||||
label: String,
|
||||
appList: Array,
|
||||
headerBg: String
|
||||
},
|
||||
methods: {
|
||||
linkTo(url) {
|
||||
uni.navigateTo({url})
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.AppListPage {
|
||||
padding-top: 20px;
|
||||
.header{
|
||||
width: calc(100% - 36px);
|
||||
height: 240px;
|
||||
margin: 0 18px 20px 18px;
|
||||
background-size: 100% 100%;
|
||||
img {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
}
|
||||
p{
|
||||
position: absolute;
|
||||
top: 48px;
|
||||
left: 50px;
|
||||
font-size: 46px;
|
||||
font-family: PingFangSC-Semibold, PingFang SC;
|
||||
font-weight: 600;
|
||||
color: #26385C;
|
||||
line-height: 64px;
|
||||
// padding: 48px 50px 0 50px;
|
||||
word-break: break-all;
|
||||
}
|
||||
}
|
||||
.content{
|
||||
margin: 0 20px 20px;
|
||||
width: calc(100% - 40px);
|
||||
background: #FFF;
|
||||
border-radius: 16px;
|
||||
.title{
|
||||
line-height: 70px;
|
||||
border-bottom: 1px solid #eee;
|
||||
padding-left: 20px;
|
||||
font-size: 26px;
|
||||
font-family: PingFangSC-Medium, PingFang SC;
|
||||
font-weight: 500;
|
||||
color: #999;
|
||||
}
|
||||
.app-list{
|
||||
overflow: hidden;
|
||||
.item{
|
||||
text-align: center;
|
||||
padding-bottom: 38px;
|
||||
border-right: 1px solid #eee;
|
||||
border-top: 1px solid #eee;
|
||||
width: calc(33% - 1px);
|
||||
float: left;
|
||||
.icon{
|
||||
display: inline-block;
|
||||
width: 58px;
|
||||
height: 58px;
|
||||
margin: 40px 0 18px 0;
|
||||
background-size: 100% 100%;
|
||||
text-align: center;
|
||||
}
|
||||
p{
|
||||
font-size: 28px;
|
||||
font-family: PingFangSC-Regular, PingFang SC;
|
||||
font-weight: 400;
|
||||
color: #3D434A;
|
||||
line-height: 40px;
|
||||
}
|
||||
}
|
||||
.item:nth-of-type(3n) {
|
||||
border-right: 0;
|
||||
}
|
||||
.item:nth-of-type(1),
|
||||
.item:nth-of-type(2),
|
||||
.item:nth-of-type(3) {
|
||||
border-top: 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
28
src/components/AiLoading/AiLoading.vue
Normal file
@@ -0,0 +1,28 @@
|
||||
<template>
|
||||
<section class="AiLoading">
|
||||
<image :src="image"/>
|
||||
<span>{{ tips }}</span>
|
||||
</section>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
name: "AiLoading",
|
||||
props: {
|
||||
tips: {default: "应用加载中"},
|
||||
image: {default: "https://cdn.cunwuyun.cn/wxAdmin/img/message.png"}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.AiLoading {
|
||||
font-size: 32px;
|
||||
color: #666;
|
||||
text-align: center;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
}
|
||||
</style>
|
||||
66
src/components/AiLogin/AiLogin.vue
Normal file
@@ -0,0 +1,66 @@
|
||||
<template>
|
||||
<div class="ai-login">
|
||||
<u-modal v-model="userPhoneShow" showCancelButton :showTitle="true" :title="'手机号码授权'"
|
||||
:content="'本次操作需要获取您的手机号码,请同意授权'" @cancel="hide">
|
||||
<template slot="confirm-button">
|
||||
<button open-type="getPhoneNumber" @getphonenumber="getPhoneNumber" class="confirm-button">同意</button>
|
||||
</template>
|
||||
</u-modal>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import tools from '../utils/util'
|
||||
import {mapActions} from "vuex"
|
||||
|
||||
export default {
|
||||
name: 'AiLogin',
|
||||
data() {
|
||||
return {
|
||||
userPhoneShow: false,
|
||||
userData: {},
|
||||
code: ''
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
...mapActions(['autoLogin']),
|
||||
show() {
|
||||
tools.$getLoginCode().then(res => {
|
||||
this.code = res.code;
|
||||
this.userPhoneShow = true;
|
||||
})
|
||||
},
|
||||
hide() {
|
||||
this.userPhoneShow = false
|
||||
},
|
||||
getPhoneNumber(arg) {
|
||||
const {encryptedData, errMsg, iv} = arg.detail
|
||||
if (errMsg == 'getPhoneNumber:ok') {
|
||||
tools.$getLoginCode().then(() => {
|
||||
console.log(iv, this.code)
|
||||
this.$instance.post(`/app/appwechatuser/getWechatUserPhone`, {
|
||||
encryptedData, iv,
|
||||
code: this.code
|
||||
}, {withoutToken: true}).then(d => {
|
||||
if (d.data) {
|
||||
let data = {...this.userData, phone: d.data};
|
||||
this.autoLogin(data).then(res => {
|
||||
this.$emit("success", res);
|
||||
});
|
||||
}
|
||||
})
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
<style lang="scss" scoped>
|
||||
.confirm-button {
|
||||
background-color: #fff !important;
|
||||
}
|
||||
|
||||
.confirm-button::after {
|
||||
border: none !important;
|
||||
}
|
||||
</style>
|
||||
68
src/components/AiMap/AiMap.vue
Normal file
@@ -0,0 +1,68 @@
|
||||
<template>
|
||||
<section class="AiMap">
|
||||
<div ref="amap" class="map"/>
|
||||
</section>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import AMapLoader from "@amap/amap-jsapi-loader";
|
||||
|
||||
export default {
|
||||
name: "AiMap",
|
||||
props: {
|
||||
plugins: {default: () => ['AMap.DistrictSearch']},
|
||||
map: Object,
|
||||
lib: Object
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
amap: null
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
initMap() {
|
||||
let {plugins} = this
|
||||
AMapLoader.load({
|
||||
key: '54a02a43d9828a8f9cd4f26fe281e74e',
|
||||
version: '2.0',
|
||||
plugins
|
||||
}).then(AMap => {
|
||||
this.amap = new AMap.Map(this.$refs.amap, {
|
||||
resizeEnable: true,
|
||||
zoom: 14,
|
||||
})
|
||||
this.$emit('update:lib', AMap)
|
||||
this.$emit('update:map', this.amap)
|
||||
})
|
||||
},
|
||||
},
|
||||
mounted() {
|
||||
this.initMap()
|
||||
},
|
||||
destroyed() {
|
||||
this.amap?.destroy()
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.AiMap {
|
||||
.map {
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
::v-deep .amap-logo, ::v-deep .amap-copyright {
|
||||
display: none !important;
|
||||
}
|
||||
|
||||
::v-deep .amap-icon {
|
||||
width: 40px !important;
|
||||
height: 40px !important;
|
||||
|
||||
img {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
32
src/components/AiMore/AiMore.vue
Normal file
@@ -0,0 +1,32 @@
|
||||
<template>
|
||||
<section class="AiMore">
|
||||
<u-icon name="arrow-right" color="#ddd" :label="value||placeholder" label-pos="left" :label-color="labelColor" label-size="32"/>
|
||||
</section>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
name: "AiMore",
|
||||
model: {
|
||||
prop: "value",
|
||||
event: "change"
|
||||
},
|
||||
props: {
|
||||
placeholder: {default: "请选择"},
|
||||
value: String
|
||||
},
|
||||
computed: {
|
||||
isEmpty() {
|
||||
return !this.value
|
||||
},
|
||||
labelColor() {
|
||||
return this.isEmpty ? "#999" : "#333"
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.AiMore {
|
||||
}
|
||||
</style>
|
||||
201
src/components/AiNewsList/AiNewsList.vue
Normal file
@@ -0,0 +1,201 @@
|
||||
<template>
|
||||
<section class="AiNewsList">
|
||||
<slot name="header"/>
|
||||
<slot v-if="$slots.content" name="content"/>
|
||||
<div class="list-wrap" v-if="list && list.length">
|
||||
<div class="list-card" v-for="(category,index) in list" :key="index"
|
||||
@click="$linkTo(linkUrl+category.id)">
|
||||
<div class="header">{{ category.title }}</div>
|
||||
<div class="content-wrap" v-if="category.contentType==0 && category.files && category.files.length == 1">
|
||||
<img class="img" :src="item.url" v-for="(item,index) in category.files" :key="index.id" alt="">
|
||||
</div>
|
||||
<div class="content-wrap" v-if="category.contentType==0 && category.files && category.files.length > 1">
|
||||
<img class="min-img" :src="item.url" v-for="(item,index) in category.files && category.files.slice(0,3)"
|
||||
:key="index.id" alt="">
|
||||
</div>
|
||||
<div class="content-wrap" v-if="category.contentType==1">
|
||||
<img class="img" :src="category.pictureUrl" alt="">
|
||||
<img class="play-icon" src="https://cdn.cunwuyun.cn/dvcp/pay-btn.png" alt="">
|
||||
</div>
|
||||
<div class="bottom">
|
||||
<div class="left">
|
||||
<div class="tag">{{ category.categoryName }}</div>
|
||||
{{ category.createTime }}
|
||||
</div>
|
||||
<div class="right">
|
||||
<em>{{ category.viewCount }}</em>
|
||||
人看过
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<AiEmpty v-else/>
|
||||
</section>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
|
||||
export default {
|
||||
name: "AiNewsList",
|
||||
props: {
|
||||
list: {default: () => []},
|
||||
linkUrl: {default: '/mods/AppContent/contentDetail?id='},
|
||||
props: {
|
||||
default: () => ({
|
||||
title: 'title',
|
||||
type: "type",
|
||||
createTime: "createTime",
|
||||
count: "count",
|
||||
})
|
||||
},
|
||||
loadmore: {default: "loadmore"}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.AiNewsList {
|
||||
height: 100vh;
|
||||
background: #f3f6f9;
|
||||
|
||||
.listPane {
|
||||
padding: 24px 32px 36px;
|
||||
|
||||
.card {
|
||||
background: #FFFFFF;
|
||||
box-shadow: 0 0 8px 0 rgba(0, 0, 0, 0.02);
|
||||
border-radius: 16px;
|
||||
padding: 32px;
|
||||
margin-bottom: 32px;
|
||||
|
||||
.title {
|
||||
height: 50px;
|
||||
font-size: 36px;
|
||||
font-weight: 500;
|
||||
color: #333333;
|
||||
line-height: 50px;
|
||||
margin-bottom: 24px;
|
||||
}
|
||||
|
||||
.subTitle {
|
||||
color: #999;
|
||||
width: 100%;
|
||||
|
||||
.tag {
|
||||
height: 48px;
|
||||
background: #EEEEEE;
|
||||
border-radius: 24px;
|
||||
text-align: center;
|
||||
line-height: 48px;
|
||||
margin-right: 16px;
|
||||
}
|
||||
|
||||
.count {
|
||||
color: #4181FF;
|
||||
}
|
||||
|
||||
.right {
|
||||
margin-left: auto;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.list-wrap {
|
||||
box-sizing: border-box;
|
||||
padding: 32px;
|
||||
|
||||
.list-card {
|
||||
width: 100%;
|
||||
min-height: 100px;
|
||||
background: #FFFFFF;
|
||||
box-shadow: 0 0 8px 0 rgba(0, 0, 0, 0.02);
|
||||
border-radius: 16px;
|
||||
box-sizing: border-box;
|
||||
padding: 32px;
|
||||
margin-bottom: 24px;
|
||||
|
||||
.header {
|
||||
font-size: 36px;
|
||||
font-weight: 600;
|
||||
color: #333333;
|
||||
line-height: 50px;
|
||||
display: -webkit-box;
|
||||
-webkit-box-orient: vertical;
|
||||
-webkit-line-clamp: 2;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.content-wrap {
|
||||
display: flex;
|
||||
gap: 4px;
|
||||
flex-wrap: wrap;
|
||||
margin-top: 24px;
|
||||
position: relative;
|
||||
|
||||
.img {
|
||||
width: 100%;
|
||||
height: 350px;
|
||||
}
|
||||
|
||||
.min-img {
|
||||
width: 204px;
|
||||
height: 204px;
|
||||
}
|
||||
|
||||
.play-icon {
|
||||
width: 80px;
|
||||
height: 80px;
|
||||
border-radius: 50%;
|
||||
position: absolute;
|
||||
left: 50%;
|
||||
top: 50%;
|
||||
transform: translate(-50%, -50%);
|
||||
}
|
||||
}
|
||||
|
||||
.bottom {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
margin-top: 24px;
|
||||
|
||||
.left {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
font-size: 28px;
|
||||
font-weight: 400;
|
||||
color: #999999;
|
||||
|
||||
.tag {
|
||||
width: 144px;
|
||||
height: 48px;
|
||||
background: #EEEEEE;
|
||||
border-radius: 24px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
font-size: 28px;
|
||||
font-weight: 400;
|
||||
color: #999999;
|
||||
margin-right: 16px;
|
||||
}
|
||||
}
|
||||
|
||||
.right {
|
||||
font-size: 28px;
|
||||
font-weight: 400;
|
||||
color: #999999;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
|
||||
em {
|
||||
font-style: normal;
|
||||
color: #4181FF;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
81
src/components/AiPagePicker/AiPagePicker.vue
Normal file
@@ -0,0 +1,81 @@
|
||||
<template>
|
||||
<section class="AiPagePicker">
|
||||
<div @click="handleJump">
|
||||
<slot v-if="$slots.default"/>
|
||||
<div v-else v-text="selectedLabel"/>
|
||||
</div>
|
||||
</section>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import qs from 'query-string'
|
||||
|
||||
export default {
|
||||
name: "AiPagePicker",
|
||||
model: {
|
||||
prop: "value",
|
||||
event: "input"
|
||||
},
|
||||
props: {
|
||||
value: {default: ""},
|
||||
type: {default: "resident"},
|
||||
nodeKey: {default: "idNumber"},
|
||||
selected: {default: () => []},
|
||||
placeholder: {default: "选择人员"},
|
||||
ops: {default: () => ({})},
|
||||
valueObj: Boolean,
|
||||
params: {default: () => ({})},
|
||||
multiple: Boolean,
|
||||
single: Boolean,
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
configList: {
|
||||
resident: {url: "/components/pages/selectResident", label: "name"},
|
||||
residentMultiple: {url: "/components/pages/selectResidentMultiple", label: "name"},
|
||||
sysUser: {url: "/components/pages/selectSysUser", label: "name"},
|
||||
gird: {url: "/components/pages/selectGird", label: "girdName"},
|
||||
party: {url: "/components/pages/selectParty", label: "name"},
|
||||
dept: {url: "/components/pages/selectDept", label: "name"},
|
||||
deptUser: {url: "/components/pages/selectDeptUser", label: "name"},
|
||||
custom: {...this.ops}
|
||||
},
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
config() {
|
||||
return this.configList[this.type] || {}
|
||||
},
|
||||
selectedLabel() {
|
||||
let {placeholder, config: {label}} = this
|
||||
return this.selected?.map(e => e[label])?.toString() || placeholder
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
handleJump() {
|
||||
let {config, nodeKey, valueObj, multiple, single} = this,
|
||||
selected = (valueObj ? this.value[nodeKey] : this.value) || this.selected?.map(e => e[nodeKey])
|
||||
uni.$once('pagePicker:' + this.type, data => {
|
||||
console.log('发送', data)
|
||||
this.$emit("update:selected", data)
|
||||
this.$emit("select", data)
|
||||
this.$emit("input", valueObj ? data :
|
||||
data ? (multiple ? [data].flat()?.map(e => e[nodeKey]) : data[nodeKey]) : "")
|
||||
})
|
||||
let url = `${config.url}`,
|
||||
qsstr = qs.stringify({
|
||||
selected, nodeKey, multiple, single, ...this.params
|
||||
})
|
||||
if (!!qsstr) {
|
||||
url += `?${qsstr}`
|
||||
}
|
||||
uni.navigateTo({url})
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.AiPagePicker {
|
||||
}
|
||||
</style>
|
||||
120
src/components/AiRadio/AiRadio.vue
Normal file
@@ -0,0 +1,120 @@
|
||||
<template>
|
||||
<div class="AiRadio" :class="[isLine ? 'AiRadio-line' : '']">
|
||||
<div
|
||||
class="AiRadio-item"
|
||||
v-for="(item, index) in options"
|
||||
@click="onChange(index)"
|
||||
:class="[currIndex === index ? 'active' : '']"
|
||||
:key="index">
|
||||
{{ item.label }}
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
name: 'AiRadio',
|
||||
|
||||
model: {
|
||||
event: 'input',
|
||||
prop: 'value'
|
||||
},
|
||||
|
||||
props: {
|
||||
value: String,
|
||||
placeholder: {
|
||||
default: '请选择'
|
||||
},
|
||||
list: {
|
||||
default: () => []
|
||||
},
|
||||
isLine: Boolean,
|
||||
dict: String,
|
||||
disabled: Boolean
|
||||
},
|
||||
|
||||
data () {
|
||||
return {
|
||||
currIndex: -1,
|
||||
dictKey: ''
|
||||
}
|
||||
},
|
||||
|
||||
computed: {
|
||||
options () {
|
||||
return this.dictKey ? this.$dict.getDict(this.dict).map(e => ({
|
||||
value: e.dictValue,
|
||||
label: e.dictName
|
||||
})) : this.list
|
||||
}
|
||||
},
|
||||
|
||||
mounted () {
|
||||
this.$dict.load(this.dict).then(() => {
|
||||
this.dictKey = this.dict
|
||||
|
||||
if (this.value) {
|
||||
console.log(this.value)
|
||||
this.$dict.getDict(this.dict).forEach((e, i) => {
|
||||
console.log(e)
|
||||
if (e.dictValue === this.value) {
|
||||
this.currIndex = i
|
||||
}
|
||||
})
|
||||
}
|
||||
})
|
||||
},
|
||||
|
||||
methods: {
|
||||
onChange (index) {
|
||||
this.currIndex = index
|
||||
const choosed = this.options[index]
|
||||
this.$emit('name', choosed.label)
|
||||
this.$emit('input', choosed.value)
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.AiRadio {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
flex-wrap: wrap;
|
||||
|
||||
.AiRadio-item {
|
||||
width: 212px;
|
||||
line-height: 1.3;
|
||||
padding: 20px 32px;
|
||||
margin-bottom: 16px;
|
||||
margin-right: 16px;
|
||||
padding: 20px 32px;
|
||||
text-align: center;
|
||||
background: #FFFFFF;
|
||||
border-radius: 16px;
|
||||
color: #333333;
|
||||
font-size: 28px;
|
||||
border: 1px solid #CCCCCC;
|
||||
box-sizing: border-box;
|
||||
|
||||
&:nth-of-type(3n) {
|
||||
margin-right: 0;
|
||||
}
|
||||
|
||||
&.active {
|
||||
background: #4181FF;
|
||||
color: #fff;
|
||||
border-color: #4181FF;
|
||||
}
|
||||
}
|
||||
|
||||
&.AiRadio-line {
|
||||
width: 100%;
|
||||
|
||||
.AiRadio-item {
|
||||
width: 100%;
|
||||
margin-right: 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
88
src/components/AiResult/AiResult.vue
Normal file
@@ -0,0 +1,88 @@
|
||||
<template>
|
||||
<section class="AiResult">
|
||||
<slot v-if="$slots.default"/>
|
||||
<template v-else>
|
||||
<image :src="result.image"/>
|
||||
<span class="tips">{{ result.tips }}</span>
|
||||
<slot name="extra" class="extra" v-if="$slots.extra"/>
|
||||
<div v-if="result.btn" class="btn" @tap="handleTap">{{ result.btn }}</div>
|
||||
</template>
|
||||
</section>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
name: "AiResult",
|
||||
props: {
|
||||
tips: {default: "提交成功!"},
|
||||
image: {default: "https://cdn.cunwuyun.cn/dvcp/h5/result/success.png"},
|
||||
btn: {default: ""},
|
||||
status: {default: "success"},
|
||||
btnTap: Function
|
||||
},
|
||||
computed: {
|
||||
result() {
|
||||
let obj = {
|
||||
image: this.image,
|
||||
tips: this.tips,
|
||||
btn: this.btn
|
||||
}
|
||||
if (this.status == "error") {
|
||||
obj.image = this.$cdn + "result/fail.png"
|
||||
obj.tips = this.tips || "提交失败!"
|
||||
} else if (this.status == "loading") {
|
||||
obj.image = "https://cdn.cunwuyun.cn/wxAdmin/img/message.png"
|
||||
obj.tips = this.tips || "数据读取中..."
|
||||
}
|
||||
return obj
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
handleTap() {
|
||||
this.btnTap && this.btnTap()
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.AiResult {
|
||||
padding-top: 96px;
|
||||
width: 100%;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
font-size: 36px;
|
||||
font-weight: bold;
|
||||
|
||||
& > image {
|
||||
width: 192px;
|
||||
height: 192px;
|
||||
}
|
||||
|
||||
.tips {
|
||||
margin: 16px auto 0;
|
||||
color: #333;
|
||||
}
|
||||
|
||||
.extra {
|
||||
margin-top: 48px;
|
||||
}
|
||||
|
||||
.btn {
|
||||
cursor: pointer;
|
||||
margin-top: 80px;
|
||||
width: calc(100% - 192px);
|
||||
height: 88px;
|
||||
background: #197DF0;
|
||||
box-shadow: 0 8px 16px 0 rgba(0, 0, 0, 0.02);
|
||||
border-radius: 8px;
|
||||
color: #FFF;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
font-weight: 500;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
105
src/components/AiSelect/AiSelect.vue
Normal file
@@ -0,0 +1,105 @@
|
||||
<template>
|
||||
<section class="AiSelect">
|
||||
<picker :range="options" :range-key="labelName" @change="handleConfirm" :disabled="disabled" :mode="mode">
|
||||
<div class="display" v-if="$slots.default">
|
||||
<slot/>
|
||||
</div>
|
||||
<div v-else class="display">
|
||||
<u-icon v-if="selectedLabel" :label="selectedLabel" label-pos="left" name="arrow-right" color="#ddd"/>
|
||||
<u-icon v-else :label="placeholder" label-pos="left" name="arrow-right" color="#ddd" label-color="#999"/>
|
||||
</div>
|
||||
</picker>
|
||||
</section>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
name: "AiSelect",
|
||||
model: {
|
||||
event: "input",
|
||||
prop: "value"
|
||||
},
|
||||
props: {
|
||||
value: String,
|
||||
placeholder: {default: "请选择"},
|
||||
list: {default: () => []},
|
||||
mode: {default: "selector"},
|
||||
dict: {default: ""},
|
||||
disabled: Boolean,
|
||||
labelName: {default: "label"},
|
||||
valueName: {default: "value"},
|
||||
},
|
||||
computed: {
|
||||
selectedLabel() {
|
||||
let str = this.options.find(e => e?.[this.valueName] == this.value)?.[this.labelName]
|
||||
return this.selected?.[this.labelName] || str
|
||||
},
|
||||
options() {
|
||||
return this.dictKey ? this.$dict.getDict(this.dict).map(e => ({
|
||||
value: e.dictValue,
|
||||
label: e.dictName
|
||||
})) : this.list || []
|
||||
}
|
||||
},
|
||||
watch: {
|
||||
selectedLabel: {
|
||||
immediate: true,
|
||||
handler(v) {
|
||||
this.$emit('name', v)
|
||||
}
|
||||
}
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
dictKey: '',
|
||||
selected: {}
|
||||
}
|
||||
},
|
||||
created() {
|
||||
this.dict && this.$dict.load(this.dict).then(() => {
|
||||
this.dictKey = this.dict
|
||||
})
|
||||
},
|
||||
methods: {
|
||||
handleConfirm(v) {
|
||||
if (this.mode == "selector") {
|
||||
this.selected = this.options?.[v.detail?.value] || {}
|
||||
this.$emit("data", this.selected)
|
||||
this.$emit("input", this.selected?.[this.valueName])
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.AiSelect {
|
||||
max-width: 100%;
|
||||
|
||||
::v-deep .u-icon {
|
||||
margin-left: 8px;
|
||||
}
|
||||
|
||||
.display {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
|
||||
.selectedLabel {
|
||||
flex: 1;
|
||||
min-width: 0;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
font-size: 30px;
|
||||
color: #333;
|
||||
white-space: nowrap;
|
||||
}
|
||||
}
|
||||
|
||||
i {
|
||||
font-style: normal;
|
||||
font-size: 30px;
|
||||
color: $uni-text-color-grey;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
79
src/components/AiStep/AiStep.vue
Normal file
@@ -0,0 +1,79 @@
|
||||
<template>
|
||||
<section class="AiStep flex start" :class="{active}">
|
||||
<div class="leftPane mar-r32">
|
||||
<div class="num" v-text="stepIndex"/>
|
||||
<div v-if="!isLast" class="stepLine fill"/>
|
||||
</div>
|
||||
<div class="fill">
|
||||
<slot/>
|
||||
</div>
|
||||
</section>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
name: "AiStep",
|
||||
inject: ['activeStep'],
|
||||
props: {
|
||||
index: {default: null},
|
||||
},
|
||||
computed: {
|
||||
active: v => v.activeStep == v.stepIndex,
|
||||
stepIndex: v => {
|
||||
const index = v.$parent.items.findIndex(e => e == v._uid)
|
||||
return index > -1 ? index + 1 : ""
|
||||
},
|
||||
isLast: v => v.$parent.items.length == v.stepIndex
|
||||
},
|
||||
created() {
|
||||
this.$parent.items.splice(this.index, 0, this._uid)
|
||||
},
|
||||
destroyed() {
|
||||
const index = this.$parent.items.findIndex(e => e == this._uid)
|
||||
this.$parent.items.splice(index, 1)
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.AiStep {
|
||||
width: 100%;
|
||||
font-size: 28px;
|
||||
position: relative;
|
||||
|
||||
.leftPane {
|
||||
width: 32px;
|
||||
|
||||
.num {
|
||||
color: #333;
|
||||
height: 32px;
|
||||
width: 32px;
|
||||
font-size: 28px;
|
||||
line-height: 32px;
|
||||
text-align: center;
|
||||
border: 4px solid #CCCCCC;
|
||||
border-radius: 50%;
|
||||
}
|
||||
|
||||
.stepLine {
|
||||
position: absolute;
|
||||
top: 40px;
|
||||
bottom: 0;
|
||||
width: 4px;
|
||||
left: 20px;
|
||||
transform: translateX(-50%);
|
||||
background: #eee;
|
||||
}
|
||||
}
|
||||
|
||||
&.active {
|
||||
.leftPane {
|
||||
.num {
|
||||
background: #26f;
|
||||
border-color: #26f;
|
||||
color: #fff;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
203
src/components/AiTMap/AiTMap.vue
Normal file
@@ -0,0 +1,203 @@
|
||||
<template>
|
||||
<section class="AiTMap">
|
||||
<div ref="tmap" class="map"/>
|
||||
</section>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
|
||||
import {mapState} from 'vuex'
|
||||
|
||||
export default {
|
||||
name: "AiTMap",
|
||||
props: {
|
||||
/**
|
||||
* 地区id
|
||||
*/
|
||||
areaId: String,
|
||||
/**
|
||||
* 地图参数,详情见https://lbs.qq.com/webApi/javascriptGL/glDoc/docIndexMap
|
||||
*/
|
||||
ops: {default: () => ({})},
|
||||
/**
|
||||
* 加载三方库,以腾讯地图文档要求进行添加
|
||||
*/
|
||||
libraries: {default: () => ["service"]},
|
||||
/**
|
||||
* 地图实例,支持用.sync绑定获取
|
||||
*/
|
||||
map: Object,
|
||||
/**
|
||||
* 地图库,支持用.sync绑定获取
|
||||
*/
|
||||
lib: Object,
|
||||
},
|
||||
computed: {
|
||||
...mapState(['wxwork']),
|
||||
key() {
|
||||
return process.env.NODE_ENV == "production" ?
|
||||
"RWWBZ-64BEJ-MVLFJ-FTHLQ-JTR6J-SAB2S" :
|
||||
"3RZBZ-LZUCF-CT6J5-NWKZH-FCWOQ-UUFKY"
|
||||
}
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
tmap: null,
|
||||
mapLib: null
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
injectLib(url, cb) {
|
||||
const script = document.createElement('script')
|
||||
script.type = 'text/javascript';
|
||||
script.id = "aitmap";
|
||||
script.src = url;
|
||||
script.addEventListener('load', () => {
|
||||
cb && cb()
|
||||
})
|
||||
document.body.appendChild(script);
|
||||
},
|
||||
initTMap() {
|
||||
let latLng = {}
|
||||
if (this.wxwork.config.lat) { //通用版
|
||||
latLng = this.wxwork.config
|
||||
this.mapLib = TMap
|
||||
this.tmap = new TMap.Map(this.$refs.tmap, {
|
||||
zoom: 11,
|
||||
center: new TMap.LatLng(latLng.lat, latLng.lng),
|
||||
...this.ops
|
||||
})
|
||||
this.$emit('update:lib', TMap)
|
||||
this.$emit('update:map', this.tmap)
|
||||
this.$emit('loaded')
|
||||
this.areaId && this.getMapArea()
|
||||
} else { //上架版
|
||||
uni.getLocation({
|
||||
type: "gcj02",
|
||||
success: res => {
|
||||
latLng = {
|
||||
lat: res.latitude,
|
||||
lng: res.longitude
|
||||
}
|
||||
if (latLng.lat) {
|
||||
// this.mapLib = TMap
|
||||
// this.tmap = new TMap.Map(this.$refs.tmap, {
|
||||
// zoom: 11,
|
||||
// center: new TMap.LatLng(latLng.lat, latLng.lng),
|
||||
// ...this.ops
|
||||
// })
|
||||
// this.$emit('update:lib', TMap)
|
||||
// this.$emit('update:map', this.tmap)
|
||||
// this.$emit('loaded')
|
||||
// this.areaId && this.getMapArea()
|
||||
}
|
||||
}
|
||||
})
|
||||
this.mapLib = TMap
|
||||
this.tmap = new TMap.Map(this.$refs.tmap, {
|
||||
zoom: 11,
|
||||
// center: new TMap.LatLng(latLng.lat, latLng.lng),
|
||||
...this.ops
|
||||
})
|
||||
this.$emit('update:lib', TMap)
|
||||
this.$emit('update:map', this.tmap)
|
||||
this.$emit('loaded')
|
||||
this.areaId && this.getMapArea()
|
||||
}
|
||||
},
|
||||
fitBounds(latLngList, count = 0) {
|
||||
// 由多边形顶点坐标数组计算能完整呈现该多边形的最小矩形范围
|
||||
let {mapLib: TMap} = this
|
||||
if (TMap) {
|
||||
if (latLngList.length === 0) {
|
||||
return null;
|
||||
}
|
||||
let boundsN = latLngList[0].getLat();
|
||||
let boundsS = boundsN;
|
||||
let boundsW = latLngList[0].getLng();
|
||||
let boundsE = boundsW;
|
||||
latLngList.forEach((point) => {
|
||||
point.getLat() > boundsN && (boundsN = point.getLat());
|
||||
point.getLat() < boundsS && (boundsS = point.getLat());
|
||||
point.getLng() > boundsE && (boundsE = point.getLng());
|
||||
point.getLng() < boundsW && (boundsW = point.getLng());
|
||||
});
|
||||
return new TMap.LatLngBounds(
|
||||
new TMap.LatLng(boundsS, boundsW),
|
||||
new TMap.LatLng(boundsN, boundsE)
|
||||
);
|
||||
} else {
|
||||
if (count < 5) {
|
||||
this.fitBounds(latLngList, ++count)
|
||||
}
|
||||
}
|
||||
},
|
||||
getMapArea() {
|
||||
let {mapLib, areaId, tmap: map} = this, keyword = areaId.substring(0, 6)
|
||||
let polygons = new TMap.MultiPolygon({map, geometries: []});
|
||||
new mapLib.service.District({
|
||||
polygon: 2,
|
||||
maxOffset: 100
|
||||
}).search({keyword}).then(res => {
|
||||
if (res?.result) {
|
||||
let center = res.result?.[0]?.[0]?.location
|
||||
this.tmap.setCenter(center)
|
||||
res.result.forEach((level) => {
|
||||
level.forEach((place) => {
|
||||
let bounds = [];
|
||||
let newGeometries = place.polygon.map((polygon, index) => {
|
||||
bounds.push(this.fitBounds(polygon)); // 计算能完整呈现行政区边界的最小矩形范围
|
||||
return {
|
||||
id: `${place.id}_${index}`,
|
||||
paths: polygon, // 将得到的行政区划边界用多边形标注在地图上
|
||||
};
|
||||
});
|
||||
bounds = bounds.reduce((a, b) => {
|
||||
return this.fitBounds([
|
||||
a.getNorthEast(),
|
||||
a.getSouthWest(),
|
||||
b.getNorthEast(),
|
||||
b.getSouthWest(),
|
||||
]);
|
||||
}); // 若一行政区有多个多边形边界,应计算能包含所有多边形边界的范围。
|
||||
polygons.updateGeometries(newGeometries);
|
||||
this.tmap.fitBounds(bounds);
|
||||
});
|
||||
});
|
||||
}
|
||||
})
|
||||
}
|
||||
},
|
||||
mounted() {
|
||||
if (!window?.TMap) {
|
||||
window.initTMap = this.initTMap
|
||||
this.injectLib(`https://map.qq.com/api/gljs?v=1.exp&key=${this.key}&libraries=${this.libraries.toString()}&callback=initTMap`)
|
||||
} else {
|
||||
this.initTMap()
|
||||
}
|
||||
},
|
||||
destroyed() {
|
||||
this.map.destroy()
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.AiTMap {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
flex: 1;
|
||||
min-width: 0;
|
||||
min-height: 0;
|
||||
|
||||
::v-deep.map {
|
||||
height: 100%;
|
||||
|
||||
& > div > div {
|
||||
&:nth-of-type(2), &:nth-of-type(3) {
|
||||
display: none;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
48
src/components/AiTable/AiTable.vue
Normal file
@@ -0,0 +1,48 @@
|
||||
<template>
|
||||
<section class="AiTable">
|
||||
<u-table color="#333">
|
||||
<u-tr>
|
||||
<u-th v-for="(col,i) in colConfigs" :key="i" :width="col.width">{{ col.label }}</u-th>
|
||||
</u-tr>
|
||||
<u-tr v-for="(row,j) in data" :key="j">
|
||||
<u-td v-for="(col,i) in colConfigs" :key="i" :width="col.width">
|
||||
<slot v-if="col.slot" :name="col.slot" :row="row"/>
|
||||
<p v-else-if="col.dict">{{ $dict.getLabel(col.dict, row[col.prop]) }}</p>
|
||||
<p v-else>{{ row[col.prop] || "-" }}</p>
|
||||
</u-td>
|
||||
</u-tr>
|
||||
</u-table>
|
||||
</section>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
|
||||
export default {
|
||||
name: "AiTable",
|
||||
props: {
|
||||
data: {default: () => []},
|
||||
colConfigs: {default: () => []},
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.AiTable {
|
||||
border-radius: 8px;
|
||||
min-height: 100px;
|
||||
overflow: hidden;
|
||||
|
||||
.u-table, .u-th {
|
||||
border-color: #D0D4DC !important;
|
||||
}
|
||||
|
||||
.u-th {
|
||||
background-color: #DFE6F4;
|
||||
color: #646D7F;
|
||||
}
|
||||
|
||||
.u-tr {
|
||||
height: 80px;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
62
src/components/AiThumbsUp/AiThumbsUp.vue
Normal file
@@ -0,0 +1,62 @@
|
||||
<template>
|
||||
<section class="AiThumbsUp flex" :class="{checked}" @click.native="handleClick">
|
||||
<div class="count" v-text="count||0"/>
|
||||
<u-icon :name="thumbIcon"/>
|
||||
</section>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
name: "AiThumbsUp",
|
||||
props: {
|
||||
bid: {default: ""},
|
||||
count: {default: 0},
|
||||
btn: Boolean,
|
||||
type: {default: "content"},
|
||||
action: {default: ""}
|
||||
},
|
||||
computed: {
|
||||
thumbIcon() {
|
||||
return this.checked ? "thumb-up-fill" : "thumb-up"
|
||||
}
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
checked: false,
|
||||
actions: {
|
||||
content: "/app/appcontentinfo/supportById",
|
||||
comment: "/app/appcontentcomment/supportById",
|
||||
}
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
handleClick() {
|
||||
if (!this.checked) {
|
||||
let {action, type, actions, bid: id} = this
|
||||
this.$instance.post(action || actions[type], null, {
|
||||
params: {id}
|
||||
}).then(res => {
|
||||
if (res?.code == 0) {
|
||||
this.checked = true
|
||||
this.$emit("update:count", ++this.count)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.AiThumbsUp {
|
||||
color: #666;
|
||||
|
||||
&.checked {
|
||||
color: #2D7DFF;
|
||||
}
|
||||
|
||||
.count {
|
||||
margin-right: 8px;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
65
src/components/AiTopFixed/AiTopFixed.vue
Normal file
@@ -0,0 +1,65 @@
|
||||
<template>
|
||||
<section class="AiTopFixed" :style="{background}">
|
||||
<!--占位区-->
|
||||
<div class="placeholder">
|
||||
<div v-if="$slots.tabs">
|
||||
<slot name="tabs"/>
|
||||
</div>
|
||||
<div class="content" v-if="$slots.default">
|
||||
<slot/>
|
||||
</div>
|
||||
</div>
|
||||
<!--悬浮区-->
|
||||
<div class="fixed" :style="{background}">
|
||||
<div v-if="$slots.tabs">
|
||||
<slot name="tabs"/>
|
||||
</div>
|
||||
<div class="content" v-if="$slots.default">
|
||||
<slot/>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
name: "AiTopFixed",
|
||||
props: {
|
||||
background: {default: "#fff"}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.AiTopFixed {
|
||||
width: 100%;
|
||||
|
||||
& > div {
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.fixed {
|
||||
width: 100%;
|
||||
min-height: 100px;
|
||||
top: 0;
|
||||
position: fixed;
|
||||
z-index: 9;
|
||||
}
|
||||
|
||||
.placeholder {
|
||||
visibility: hidden;
|
||||
opacity: 0;
|
||||
}
|
||||
|
||||
.content {
|
||||
min-height: 100px;
|
||||
padding: 20px 32px;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
::v-deep .u-search {
|
||||
box-shadow: 0 8px 16px 0 rgba(0, 0, 0, 0.02);
|
||||
margin-bottom: 32px !important;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
146
src/components/AiTransSpeech/AiTransSpeech.vue
Normal file
@@ -0,0 +1,146 @@
|
||||
<template>
|
||||
<div class="AiTransSpeech" v-if="!noSpeech">
|
||||
<button title="语音播报" @click="getSpeech">
|
||||
<div>
|
||||
<div class="iconfont" :class="{playing:loading}"></div>
|
||||
</div>
|
||||
<div>{{ text }}</div>
|
||||
</button>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
name: "AiTransSpeech",
|
||||
props: {
|
||||
src: String,
|
||||
content: String
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
audioContext: null,
|
||||
speech: "",
|
||||
loading: false,
|
||||
text: "开始"
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
speechString() {
|
||||
return this.content ? this.content.replace(/<\/?.+?\/?>/g, "") : ""
|
||||
},
|
||||
noSpeech() {
|
||||
return !this.src && !this.content
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
getSpeech() {
|
||||
if (!this.noSpeech) {
|
||||
if (this.audioContext) {
|
||||
if (this.loading) {
|
||||
this.loading = false
|
||||
this.audioContext.pause()
|
||||
} else {
|
||||
this.loading = true
|
||||
this.audioContext.play()
|
||||
}
|
||||
} else if (this.content) {
|
||||
this.loading = true
|
||||
if (!this.speech) {
|
||||
this.$instance.post("/app/msc/transToSpeech" + `?fileName=demo&words=${this.speechString}`).then(res => {
|
||||
if (res && res.data) {
|
||||
let url = res.data.join("")
|
||||
this.speech = url.substring(0, url.indexOf(";"))
|
||||
this.playAudio()
|
||||
}
|
||||
}).catch(() => this.loading = false)
|
||||
} else {
|
||||
this.playAudio()
|
||||
}
|
||||
} else if (this.src) {
|
||||
this.loading = true
|
||||
this.speech = this.src
|
||||
this.playAudio()
|
||||
}
|
||||
}
|
||||
},
|
||||
playAudio() {
|
||||
let _ = this
|
||||
this.audioContext = uni.createInnerAudioContext();
|
||||
this.audioContext.src = this.speech;
|
||||
this.audioContext.play()
|
||||
this.audioContext.onPlay(() => {
|
||||
_.text = "暂停"
|
||||
});
|
||||
this.audioContext.onPause(() => {
|
||||
_.loading = false
|
||||
_.text = "开始"
|
||||
});
|
||||
this.audioContext.onEnded(() => {
|
||||
_.loading = false
|
||||
_.text = "开始"
|
||||
});
|
||||
this.audioContext.onError((res) => {
|
||||
console.error(res.errMsg);
|
||||
_.text = "开始"
|
||||
});
|
||||
},
|
||||
},
|
||||
destroyed() {
|
||||
if (this.audioContext) {
|
||||
this.audioContext.pause()
|
||||
this.audioContext.destroy()
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.AiTransSpeech {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
|
||||
button {
|
||||
position: fixed;
|
||||
right: 80px;
|
||||
bottom: 150px;
|
||||
width: 104px;
|
||||
height: 104px;
|
||||
background: linear-gradient(130deg, rgba(70, 192, 253, 1) 0%, rgba(37, 158, 249, 1) 57%, rgba(39, 148, 248, 1) 100%);
|
||||
border-radius: 50%;
|
||||
font-size: 24px;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
color: #fff !important;
|
||||
z-index: 10000;
|
||||
|
||||
& > div {
|
||||
width: 48px;
|
||||
white-space: nowrap;
|
||||
line-height: normal;
|
||||
|
||||
.iconfont {
|
||||
width: 48px;
|
||||
font-size: 48px;
|
||||
line-height: 48px;
|
||||
overflow: hidden;
|
||||
|
||||
&.playing {
|
||||
animation: playingSpeech .5s infinite;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@keyframes playingSpeech {
|
||||
from {
|
||||
width: 30px
|
||||
}
|
||||
to {
|
||||
width: 100%
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
59
src/components/AiTreePath/AiTreePath.vue
Normal file
@@ -0,0 +1,59 @@
|
||||
<template>
|
||||
<section class="AiTreePath">
|
||||
<b v-text="`全部`" @click="$emit('click','all')"/>
|
||||
<div flex v-for="p in parents" :key="p.id">
|
||||
<u-icon name="arrow-right" size="32" color="#ccc"/>
|
||||
<div class="mar-l8" v-text="p[options.label]" @click="$emit('click',p)"/>
|
||||
</div>
|
||||
<u-icon v-if="label" name="arrow-right" size="32" color="#ccc"/>
|
||||
<div class="active" v-text="label" @click="$emit('click',node)"/>
|
||||
</section>
|
||||
</template>
|
||||
<script>
|
||||
export default {
|
||||
name: "AiTreePath",
|
||||
props: {
|
||||
prop: {default: () => ({})},
|
||||
paths: {default: () => ({})},
|
||||
node: {default: null}
|
||||
},
|
||||
computed: {
|
||||
options: v => ({
|
||||
id: 'id',
|
||||
label: 'name',
|
||||
parent: 'parentId',
|
||||
...v.prop
|
||||
}),
|
||||
label: v => v.node?.[v.options.label] || "",
|
||||
parent: v => v.paths?.[v.node?.[v.options.parent]],
|
||||
parents() {
|
||||
const arr = []
|
||||
const {id: KEY, parent: PARENT} = this.options
|
||||
const find = n => {
|
||||
if (!!n?.[KEY]) {
|
||||
arr.unshift(n)
|
||||
find(this.paths[n?.[PARENT]])
|
||||
}
|
||||
}
|
||||
find(this.parent)
|
||||
return arr
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
<style scoped lang="scss">
|
||||
.AiTreePath {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 8px;
|
||||
font-size: 36px;
|
||||
line-height: 40px;
|
||||
font-family: PingFang-SC;
|
||||
flex-wrap: wrap;
|
||||
|
||||
.active {
|
||||
font-weight: bold;
|
||||
color: #26f
|
||||
}
|
||||
}
|
||||
</style>
|
||||
419
src/components/AiUniIcon/AiUniIcon.vue
Normal file
300
src/components/AiUploader/AiUploader.vue
Normal file
@@ -0,0 +1,300 @@
|
||||
<template>
|
||||
<div class="ai-uploader">
|
||||
<div class="imgList" v-if="type == 'image'">
|
||||
<div class="item" v-for="(item, i) in fileList" :key="i">
|
||||
<ai-image :src="item.url" :preview="preview"/>
|
||||
<u-icon v-if="!disabled" class="delBtn" color="#f46" name="close-circle-fill" size="40" @click="remove(i)"/>
|
||||
</div>
|
||||
<div v-if="!disabled&&(fileList.length == 0 || (fileList.length < limit))" class="default" @click="upload">
|
||||
<u-icon name="photo" size="64" :label="placeholder" label-pos="bottom" label-color="#89b"/>
|
||||
</div>
|
||||
</div>
|
||||
<div class="imgList" v-else-if="type == 'video'">
|
||||
<div class="item" v-for="(item, i) in fileList" :key="i">
|
||||
<video :src="item.url" :poster="item.thumb"/>
|
||||
<u-icon v-if="!disabled" class="delBtn" color="#f46" name="close-circle-fill" size="40" @click="remove(i)"/>
|
||||
</div>
|
||||
<div v-if="!disabled&&(fileList.length == 0 || (fileList.length < limit))" class="default" @click="upload">
|
||||
<u-icon name="camera" size="64" :label="placeholder" label-pos="bottom" label-color="#89b"/>
|
||||
</div>
|
||||
</div>
|
||||
<div class="fileList" v-else>
|
||||
<div class="item" v-for="(item, i) in fileList" :key="i">
|
||||
<ai-image :preview="preview" :file="item"/>
|
||||
<div class="info">
|
||||
<span>{{ item.name }} </span>
|
||||
<i>{{ item.fileSizeStr }}</i>
|
||||
</div>
|
||||
<template v-if="!disabled">
|
||||
<div class="btn" @tap="handleReUpload(i)">
|
||||
重新上传
|
||||
</div>
|
||||
<div class="btn" @tap="remove(i)">
|
||||
删除
|
||||
</div>
|
||||
</template>
|
||||
</div>
|
||||
<div v-if="!disabled&&(fileList.length == 0 || (multiple && fileList.length < limit))" class="default"
|
||||
@click="upload">
|
||||
<u-icon name="photo" size="64" :label="placeholder" label-pos="bottom" label-color="#89b"/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import {mapState} from 'vuex'
|
||||
import AiImage from '../AiImage/AiImage'
|
||||
|
||||
export default {
|
||||
name: 'AiUploader',
|
||||
components: {AiImage},
|
||||
model: {
|
||||
prop: 'def', // :def.sync才可以回显,v-model不能回显(bug)
|
||||
event: 'input'
|
||||
},
|
||||
props: {
|
||||
limit: {default: 1}, //数量
|
||||
placeholder: {default: '添加图片'}, // 文字提示
|
||||
type: {default: 'image'}, // 文件类型:image,file,video
|
||||
multiple: {
|
||||
type: Boolean,
|
||||
default: false,
|
||||
},
|
||||
fileId: String,
|
||||
mediaId: String,
|
||||
def: {default: () => []},
|
||||
action: String,
|
||||
preview: Boolean,
|
||||
size: {default: 10 * 1024 * 1024},
|
||||
disabled: Boolean,
|
||||
},
|
||||
computed: {
|
||||
...mapState(['token']),
|
||||
errorImage: v => v.$cdn + 'file.png',
|
||||
api() {
|
||||
if (this.action) return this.action
|
||||
else return {
|
||||
image: '/admin/file/add',
|
||||
file: '/admin/file/add',
|
||||
video: '/admin/file/addVideo',
|
||||
}[this.type]
|
||||
}
|
||||
},
|
||||
watch: {
|
||||
def: {
|
||||
handler(v) {
|
||||
if (!!v?.toString()) {
|
||||
if (this.multiple) {
|
||||
this.fileList = v
|
||||
} else if (v?.url) {
|
||||
this.fileList = [v]
|
||||
} else if (v?.length > 0) {
|
||||
this.fileList = v
|
||||
}
|
||||
}
|
||||
},
|
||||
immediate: true,
|
||||
deep: true
|
||||
},
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
fileList: [],
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
remove(index) {
|
||||
this.fileList.splice(index, 1)
|
||||
this.$emit('input', this.fileList)
|
||||
},
|
||||
upload(wait) {
|
||||
let count = this.limit - (this.fileList?.length || 0)
|
||||
if (count > 0) {
|
||||
const params = {
|
||||
count,
|
||||
sizeType: ['compressed'],
|
||||
sourceType: ['album', 'camera'],
|
||||
success: res => {
|
||||
let count = this.fileList?.length + (res.tempFiles?.length || res.tempFile ? 1 : 0)
|
||||
if (count > this.limit && this.limit !== 1) {
|
||||
return this.$u.toast(`不能超过${this.limit}个`)
|
||||
}
|
||||
if (res.tempFiles?.length > 0) {
|
||||
res.tempFiles.map(this.uploadFile)
|
||||
} else if (res?.tempFile) {
|
||||
this.uploadFile(res.tempFile)
|
||||
}
|
||||
},
|
||||
}
|
||||
typeof wait == 'function' && wait()
|
||||
if (this.type == 'image') {
|
||||
uni.chooseMedia({...params, mediaType: ['image']})
|
||||
} else if (this.type == 'video') {
|
||||
uni.chooseMedia({...params, mediaType: ['video']})
|
||||
} else {
|
||||
uni.chooseFile(params)
|
||||
}
|
||||
} else {
|
||||
this.$u.toast(`不能超过${this.limit}个`)
|
||||
}
|
||||
},
|
||||
uploadFile(img) {
|
||||
if (this.size > 0 && img.size > this.size) {
|
||||
return this.$u.toast(`不能超过${Math.ceil(this.size / 1024 / 1024)}MB`)
|
||||
}
|
||||
uni.showLoading({title: '上传中'})
|
||||
if (this.manual) {
|
||||
this.$emit('manual', img)
|
||||
uni.hideLoading()
|
||||
} else {
|
||||
const filePath = img.path || img.tempFilePath
|
||||
uni.uploadFile({
|
||||
url: this.$instance.defaults.baseURL + this.api,
|
||||
filePath,
|
||||
name: 'file',
|
||||
header: {
|
||||
'Content-Type': 'multipart/form-data',
|
||||
Authorization: this.token,
|
||||
},
|
||||
success: response => {
|
||||
const res = JSON.parse(response.data)
|
||||
if (res?.data) {
|
||||
this.$emit('data', res.data)
|
||||
this.$u.toast('上传成功!')
|
||||
if (!this.action) {//默认组件接口
|
||||
if (this.type == 'image') {
|
||||
const [image = "",] = res.data
|
||||
this.fileList.push({url: image.split(";")[0], id: image.split(";")?.[1]})
|
||||
} else if (this.type == 'video') {
|
||||
const [video = "", thumb = ""] = res.data
|
||||
this.fileList.push({url: video.split(";")[0], id: video.split(";")?.[1], thumb: thumb.split(";")[0]})
|
||||
}
|
||||
} else if (this.api == '/admin/file/add2') {
|
||||
let info = res.data
|
||||
this.$emit('update:fileId', info?.id)
|
||||
this.fileList.push(res.data)
|
||||
} else if (this.api == '/admin/file/add-portrait') {
|
||||
this.fileList.push({url: res.data?.split(";")?.[0], id: res.data?.split(";")?.[1]})
|
||||
}
|
||||
this.$emit("input", this.fileList)
|
||||
this.$emit("update:def", this.fileList)
|
||||
} else {
|
||||
this.$u.toast(res.msg)
|
||||
}
|
||||
},
|
||||
fail: console.error,
|
||||
complete: uni.hideLoading
|
||||
})
|
||||
}
|
||||
|
||||
},
|
||||
handleReUpload(i) {
|
||||
this.upload(() => this.remove(i))
|
||||
},
|
||||
},
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.ai-uploader {
|
||||
width: 100%;
|
||||
line-height: normal;
|
||||
margin-bottom: 16px;
|
||||
|
||||
::v-deep.imgList {
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
|
||||
.item {
|
||||
width: 27vw;
|
||||
height: 27vw;
|
||||
position: relative;
|
||||
padding: 0 2pt 2pt 0;
|
||||
box-sizing: border-box;
|
||||
|
||||
.delBtn {
|
||||
position: absolute;
|
||||
right: -8px;
|
||||
top: -8px;
|
||||
z-index: 2;
|
||||
border-radius: 50%;
|
||||
overflow: hidden;
|
||||
background-color: #fff;
|
||||
height: 40px;
|
||||
}
|
||||
|
||||
image,video {
|
||||
width: 27vw;
|
||||
height: 27vw;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.fileList {
|
||||
.item {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
margin-bottom: 10px;
|
||||
|
||||
image {
|
||||
width: 160px;
|
||||
height: 160px;
|
||||
}
|
||||
|
||||
i {
|
||||
font-style: normal;
|
||||
color: #9b9b9b;
|
||||
}
|
||||
|
||||
.info {
|
||||
flex: 1;
|
||||
min-width: 0;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: flex-start;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
|
||||
& > span {
|
||||
flex: 1;
|
||||
min-width: 0;
|
||||
}
|
||||
}
|
||||
|
||||
div.btn {
|
||||
color: $uni-color-primary;
|
||||
margin-right: 16px;
|
||||
|
||||
}
|
||||
|
||||
div:nth-child(4) {
|
||||
color: #f72c27;
|
||||
}
|
||||
|
||||
& > * + * {
|
||||
margin-left: 20px;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
.default {
|
||||
width: 27vw;
|
||||
height: 27vw;
|
||||
box-sizing: border-box;
|
||||
border-radius: 8px;
|
||||
background: #f3f4f7;
|
||||
color: #89b;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
|
||||
.iconfont-iconAdd {
|
||||
font-size: 64px;
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
522
src/components/ckeditor.scss
Normal file
@@ -0,0 +1,522 @@
|
||||
/*
|
||||
* CKEditor 5 (v34.2.0) content styles.
|
||||
* Generated on Fri, 29 Jul 2022 13:03:52 GMT.
|
||||
* For more information, check out https://ckeditor.com/docs/ckeditor5/latest/installation/advanced/content-styles.html
|
||||
*/
|
||||
|
||||
:root {
|
||||
--ck-color-base-active: hsl(208, 88%, 52%);
|
||||
--ck-color-image-caption-background: hsl(0, 0%, 97%);
|
||||
--ck-color-image-caption-text: hsl(0, 0%, 20%);
|
||||
--ck-color-mention-background: hsla(341, 100%, 30%, 0.1);
|
||||
--ck-color-mention-text: hsl(341, 100%, 30%);
|
||||
--ck-color-table-caption-background: hsl(0, 0%, 97%);
|
||||
--ck-color-table-caption-text: hsl(0, 0%, 20%);
|
||||
--ck-color-table-column-resizer-hover: var(--ck-color-base-active);
|
||||
--ck-highlight-marker-blue: hsl(201, 97%, 72%);
|
||||
--ck-highlight-marker-green: hsl(120, 93%, 68%);
|
||||
--ck-highlight-marker-pink: hsl(345, 96%, 73%);
|
||||
--ck-highlight-marker-yellow: hsl(60, 97%, 73%);
|
||||
--ck-highlight-pen-green: hsl(112, 100%, 27%);
|
||||
--ck-highlight-pen-red: hsl(0, 85%, 49%);
|
||||
--ck-image-style-spacing: 1.5em;
|
||||
--ck-inline-image-style-spacing: calc(var(--ck-image-style-spacing) / 2);
|
||||
--ck-table-column-resizer-position-offset: calc(var(--ck-table-column-resizer-width) * -0.5 - 0.5px);
|
||||
--ck-table-column-resizer-width: 7px;
|
||||
--ck-todo-list-checkmark-size: 16px;
|
||||
--ck-z-default: 1;
|
||||
}
|
||||
|
||||
/* ckeditor5-block-quote/theme/blockquote.css */
|
||||
.ck-content blockquote {
|
||||
overflow: hidden;
|
||||
padding-right: 1.5em;
|
||||
padding-left: 1.5em;
|
||||
margin-left: 0;
|
||||
margin-right: 0;
|
||||
font-style: italic;
|
||||
border-left: solid 5px hsl(0, 0%, 80%);
|
||||
}
|
||||
|
||||
/* ckeditor5-block-quote/theme/blockquote.css */
|
||||
.ck-content[dir="rtl"] blockquote {
|
||||
border-left: 0;
|
||||
border-right: solid 5px hsl(0, 0%, 80%);
|
||||
}
|
||||
|
||||
/* ckeditor5-basic-styles/theme/code.css */
|
||||
.ck-content code {
|
||||
background-color: hsla(0, 0%, 78%, 0.3);
|
||||
padding: .15em;
|
||||
border-radius: 2px;
|
||||
}
|
||||
|
||||
/* ckeditor5-font/theme/fontsize.css */
|
||||
.ck-content .text-tiny {
|
||||
font-size: .7em;
|
||||
}
|
||||
|
||||
/* ckeditor5-font/theme/fontsize.css */
|
||||
.ck-content .text-small {
|
||||
font-size: .85em;
|
||||
}
|
||||
|
||||
/* ckeditor5-font/theme/fontsize.css */
|
||||
.ck-content .text-big {
|
||||
font-size: 1.4em;
|
||||
}
|
||||
|
||||
/* ckeditor5-font/theme/fontsize.css */
|
||||
.ck-content .text-huge {
|
||||
font-size: 1.8em;
|
||||
}
|
||||
|
||||
/* ckeditor5-highlight/theme/highlight.css */
|
||||
.ck-content .marker-yellow {
|
||||
background-color: var(--ck-highlight-marker-yellow);
|
||||
}
|
||||
|
||||
/* ckeditor5-highlight/theme/highlight.css */
|
||||
.ck-content .marker-green {
|
||||
background-color: var(--ck-highlight-marker-green);
|
||||
}
|
||||
|
||||
/* ckeditor5-highlight/theme/highlight.css */
|
||||
.ck-content .marker-pink {
|
||||
background-color: var(--ck-highlight-marker-pink);
|
||||
}
|
||||
|
||||
/* ckeditor5-highlight/theme/highlight.css */
|
||||
.ck-content .marker-blue {
|
||||
background-color: var(--ck-highlight-marker-blue);
|
||||
}
|
||||
|
||||
/* ckeditor5-highlight/theme/highlight.css */
|
||||
.ck-content .pen-red {
|
||||
color: var(--ck-highlight-pen-red);
|
||||
background-color: transparent;
|
||||
}
|
||||
|
||||
/* ckeditor5-highlight/theme/highlight.css */
|
||||
.ck-content .pen-green {
|
||||
color: var(--ck-highlight-pen-green);
|
||||
background-color: transparent;
|
||||
}
|
||||
|
||||
/* ckeditor5-image/theme/image.css */
|
||||
.ck-content .image {
|
||||
display: table;
|
||||
clear: both;
|
||||
text-align: center;
|
||||
margin: 0.9em auto;
|
||||
min-width: 50px;
|
||||
}
|
||||
|
||||
/* ckeditor5-image/theme/image.css */
|
||||
.ck-content .image img {
|
||||
display: block;
|
||||
margin: 0 auto;
|
||||
max-width: 100%;
|
||||
min-width: 100%;
|
||||
}
|
||||
|
||||
/* ckeditor5-image/theme/image.css */
|
||||
.ck-content .image-inline {
|
||||
/*
|
||||
* Normally, the .image-inline would have "display: inline-block" and "img { width: 100% }" (to follow the wrapper while resizing).;
|
||||
* Unfortunately, together with "srcset", it gets automatically stretched up to the width of the editing root.
|
||||
* This strange behavior does not happen with inline-flex.
|
||||
*/
|
||||
display: inline-flex;
|
||||
max-width: 100%;
|
||||
align-items: flex-start;
|
||||
}
|
||||
|
||||
/* ckeditor5-image/theme/image.css */
|
||||
.ck-content .image-inline picture {
|
||||
display: flex;
|
||||
}
|
||||
|
||||
/* ckeditor5-image/theme/image.css */
|
||||
.ck-content .image-inline picture,
|
||||
.ck-content .image-inline img {
|
||||
flex-grow: 1;
|
||||
flex-shrink: 1;
|
||||
max-width: 100%;
|
||||
}
|
||||
|
||||
/* ckeditor5-image/theme/imagestyle.css */
|
||||
.ck-content .image-style-block-align-left,
|
||||
.ck-content .image-style-block-align-right {
|
||||
max-width: calc(100% - var(--ck-image-style-spacing));
|
||||
}
|
||||
|
||||
/* ckeditor5-image/theme/imagestyle.css */
|
||||
.ck-content .image-style-align-left,
|
||||
.ck-content .image-style-align-right {
|
||||
clear: none;
|
||||
}
|
||||
|
||||
/* ckeditor5-image/theme/imagestyle.css */
|
||||
.ck-content .image-style-side {
|
||||
float: right;
|
||||
margin-left: var(--ck-image-style-spacing);
|
||||
max-width: 50%;
|
||||
}
|
||||
|
||||
/* ckeditor5-image/theme/imagestyle.css */
|
||||
.ck-content .image-style-align-left {
|
||||
float: left;
|
||||
margin-right: var(--ck-image-style-spacing);
|
||||
}
|
||||
|
||||
/* ckeditor5-image/theme/imagestyle.css */
|
||||
.ck-content .image-style-align-center {
|
||||
margin-left: auto;
|
||||
margin-right: auto;
|
||||
}
|
||||
|
||||
/* ckeditor5-image/theme/imagestyle.css */
|
||||
.ck-content .image-style-align-right {
|
||||
float: right;
|
||||
margin-left: var(--ck-image-style-spacing);
|
||||
}
|
||||
|
||||
/* ckeditor5-image/theme/imagestyle.css */
|
||||
.ck-content .image-style-block-align-right {
|
||||
margin-right: 0;
|
||||
margin-left: auto;
|
||||
}
|
||||
|
||||
/* ckeditor5-image/theme/imagestyle.css */
|
||||
.ck-content .image-style-block-align-left {
|
||||
margin-left: 0;
|
||||
margin-right: auto;
|
||||
}
|
||||
|
||||
/* ckeditor5-image/theme/imagestyle.css */
|
||||
.ck-content p + .image-style-align-left,
|
||||
.ck-content p + .image-style-align-right,
|
||||
.ck-content p + .image-style-side {
|
||||
margin-top: 0;
|
||||
}
|
||||
|
||||
/* ckeditor5-image/theme/imagestyle.css */
|
||||
.ck-content .image-inline.image-style-align-left,
|
||||
.ck-content .image-inline.image-style-align-right {
|
||||
margin-top: var(--ck-inline-image-style-spacing);
|
||||
margin-bottom: var(--ck-inline-image-style-spacing);
|
||||
}
|
||||
|
||||
/* ckeditor5-image/theme/imagestyle.css */
|
||||
.ck-content .image-inline.image-style-align-left {
|
||||
margin-right: var(--ck-inline-image-style-spacing);
|
||||
}
|
||||
|
||||
/* ckeditor5-image/theme/imagestyle.css */
|
||||
.ck-content .image-inline.image-style-align-right {
|
||||
margin-left: var(--ck-inline-image-style-spacing);
|
||||
}
|
||||
|
||||
/* ckeditor5-image/theme/imagecaption.css */
|
||||
.ck-content .image > figcaption {
|
||||
display: table-caption;
|
||||
caption-side: bottom;
|
||||
word-break: break-word;
|
||||
color: var(--ck-color-image-caption-text);
|
||||
background-color: var(--ck-color-image-caption-background);
|
||||
padding: .6em;
|
||||
font-size: .75em;
|
||||
outline-offset: -1px;
|
||||
}
|
||||
|
||||
/* ckeditor5-image/theme/imageresize.css */
|
||||
.ck-content .image.image_resized {
|
||||
max-width: 100%;
|
||||
display: block;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
/* ckeditor5-image/theme/imageresize.css */
|
||||
.ck-content .image.image_resized img {
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
/* ckeditor5-image/theme/imageresize.css */
|
||||
.ck-content .image.image_resized > figcaption {
|
||||
display: block;
|
||||
}
|
||||
|
||||
/* ckeditor5-language/theme/language.css */
|
||||
.ck-content span[lang] {
|
||||
font-style: italic;
|
||||
}
|
||||
|
||||
/* ckeditor5-list/theme/todolist.css */
|
||||
.ck-content .todo-list {
|
||||
list-style: none;
|
||||
}
|
||||
|
||||
/* ckeditor5-list/theme/todolist.css */
|
||||
.ck-content .todo-list li {
|
||||
margin-bottom: 5px;
|
||||
}
|
||||
|
||||
/* ckeditor5-list/theme/todolist.css */
|
||||
.ck-content .todo-list li .todo-list {
|
||||
margin-top: 5px;
|
||||
}
|
||||
|
||||
/* ckeditor5-list/theme/todolist.css */
|
||||
.ck-content .todo-list .todo-list__label > input {
|
||||
-webkit-appearance: none;
|
||||
display: inline-block;
|
||||
position: relative;
|
||||
width: var(--ck-todo-list-checkmark-size);
|
||||
height: var(--ck-todo-list-checkmark-size);
|
||||
vertical-align: middle;
|
||||
border: 0;
|
||||
left: -25px;
|
||||
margin-right: -15px;
|
||||
right: 0;
|
||||
margin-left: 0;
|
||||
}
|
||||
|
||||
/* ckeditor5-list/theme/todolist.css */
|
||||
.ck-content .todo-list .todo-list__label > input::before {
|
||||
display: block;
|
||||
position: absolute;
|
||||
box-sizing: border-box;
|
||||
content: '';
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
border: 1px solid hsl(0, 0%, 20%);
|
||||
border-radius: 2px;
|
||||
transition: 250ms ease-in-out box-shadow, 250ms ease-in-out background, 250ms ease-in-out border;
|
||||
}
|
||||
|
||||
/* ckeditor5-list/theme/todolist.css */
|
||||
.ck-content .todo-list .todo-list__label > input::after {
|
||||
display: block;
|
||||
position: absolute;
|
||||
box-sizing: content-box;
|
||||
pointer-events: none;
|
||||
content: '';
|
||||
left: calc(var(--ck-todo-list-checkmark-size) / 3);
|
||||
top: calc(var(--ck-todo-list-checkmark-size) / 5.3);
|
||||
width: calc(var(--ck-todo-list-checkmark-size) / 5.3);
|
||||
height: calc(var(--ck-todo-list-checkmark-size) / 2.6);
|
||||
border-style: solid;
|
||||
border-color: transparent;
|
||||
border-width: 0 calc(var(--ck-todo-list-checkmark-size) / 8) calc(var(--ck-todo-list-checkmark-size) / 8) 0;
|
||||
transform: rotate(45deg);
|
||||
}
|
||||
|
||||
/* ckeditor5-list/theme/todolist.css */
|
||||
.ck-content .todo-list .todo-list__label > input[checked]::before {
|
||||
background: hsl(126, 64%, 41%);
|
||||
border-color: hsl(126, 64%, 41%);
|
||||
}
|
||||
|
||||
/* ckeditor5-list/theme/todolist.css */
|
||||
.ck-content .todo-list .todo-list__label > input[checked]::after {
|
||||
border-color: hsl(0, 0%, 100%);
|
||||
}
|
||||
|
||||
/* ckeditor5-list/theme/todolist.css */
|
||||
.ck-content .todo-list .todo-list__label .todo-list__label__description {
|
||||
vertical-align: middle;
|
||||
}
|
||||
|
||||
/* ckeditor5-media-embed/theme/mediaembed.css */
|
||||
.ck-content .media {
|
||||
clear: both;
|
||||
margin: 0.9em 0;
|
||||
display: block;
|
||||
min-width: 15em;
|
||||
}
|
||||
|
||||
/* ckeditor5-page-break/theme/pagebreak.css */
|
||||
.ck-content .page-break {
|
||||
position: relative;
|
||||
clear: both;
|
||||
padding: 5px 0;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
/* ckeditor5-page-break/theme/pagebreak.css */
|
||||
.ck-content .page-break::after {
|
||||
content: '';
|
||||
position: absolute;
|
||||
border-bottom: 2px dashed hsl(0, 0%, 77%);
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
/* ckeditor5-page-break/theme/pagebreak.css */
|
||||
.ck-content .page-break__label {
|
||||
position: relative;
|
||||
z-index: 1;
|
||||
padding: .3em .6em;
|
||||
display: block;
|
||||
text-transform: uppercase;
|
||||
border: 1px solid hsl(0, 0%, 77%);
|
||||
border-radius: 2px;
|
||||
font-family: Helvetica, Arial, Tahoma, Verdana, Sans-Serif;
|
||||
font-size: 0.75em;
|
||||
font-weight: bold;
|
||||
color: hsl(0, 0%, 20%);
|
||||
background: hsl(0, 0%, 100%);
|
||||
box-shadow: 2px 2px 1px hsla(0, 0%, 0%, 0.15);
|
||||
-webkit-user-select: none;
|
||||
-moz-user-select: none;
|
||||
-ms-user-select: none;
|
||||
user-select: none;
|
||||
}
|
||||
|
||||
/* ckeditor5-table/theme/tablecaption.css */
|
||||
.ck-content .table > figcaption {
|
||||
display: table-caption;
|
||||
caption-side: top;
|
||||
word-break: break-word;
|
||||
text-align: center;
|
||||
color: var(--ck-color-table-caption-text);
|
||||
background-color: var(--ck-color-table-caption-background);
|
||||
padding: .6em;
|
||||
font-size: .75em;
|
||||
outline-offset: -1px;
|
||||
}
|
||||
|
||||
/* ckeditor5-table/theme/table.css */
|
||||
.ck-content .table {
|
||||
margin: 0.9em auto;
|
||||
display: table;
|
||||
}
|
||||
|
||||
/* ckeditor5-table/theme/table.css */
|
||||
.ck-content .table table {
|
||||
border-collapse: collapse;
|
||||
border-spacing: 0;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
border: 1px double hsl(0, 0%, 70%);
|
||||
}
|
||||
|
||||
/* ckeditor5-table/theme/table.css */
|
||||
.ck-content .table table td,
|
||||
.ck-content .table table th {
|
||||
min-width: 2em;
|
||||
padding: .4em;
|
||||
border: 1px solid hsl(0, 0%, 75%);
|
||||
}
|
||||
|
||||
/* ckeditor5-table/theme/table.css */
|
||||
.ck-content .table table th {
|
||||
font-weight: bold;
|
||||
background: hsla(0, 0%, 0%, 5%);
|
||||
}
|
||||
|
||||
/* ckeditor5-table/theme/table.css */
|
||||
.ck-content[dir="rtl"] .table th {
|
||||
text-align: right;
|
||||
}
|
||||
|
||||
/* ckeditor5-table/theme/table.css */
|
||||
.ck-content[dir="ltr"] .table th {
|
||||
text-align: left;
|
||||
}
|
||||
|
||||
/* ckeditor5-table/theme/tablecolumnresize.css */
|
||||
.ck-content .table table {
|
||||
overflow: hidden;
|
||||
table-layout: fixed;
|
||||
}
|
||||
|
||||
/* ckeditor5-table/theme/tablecolumnresize.css */
|
||||
.ck-content .table td,
|
||||
.ck-content .table th {
|
||||
position: relative;
|
||||
}
|
||||
|
||||
/* ckeditor5-table/theme/tablecolumnresize.css */
|
||||
.ck-content .table .table-column-resizer {
|
||||
position: absolute;
|
||||
top: -999999px;
|
||||
bottom: -999999px;
|
||||
right: var(--ck-table-column-resizer-position-offset);
|
||||
width: var(--ck-table-column-resizer-width);
|
||||
cursor: col-resize;
|
||||
user-select: none;
|
||||
z-index: var(--ck-z-default);
|
||||
}
|
||||
|
||||
/* ckeditor5-table/theme/tablecolumnresize.css */
|
||||
.ck-content .table[draggable] .table-column-resizer {
|
||||
display: none;
|
||||
}
|
||||
|
||||
/* ckeditor5-table/theme/tablecolumnresize.css */
|
||||
.ck-content .table .table-column-resizer:hover,
|
||||
.ck-content .table .table-column-resizer__active {
|
||||
background-color: var(--ck-color-table-column-resizer-hover);
|
||||
opacity: 0.25;
|
||||
}
|
||||
|
||||
/* ckeditor5-table/theme/tablecolumnresize.css */
|
||||
.ck-content[dir=rtl] .table .table-column-resizer {
|
||||
left: var(--ck-table-column-resizer-position-offset);
|
||||
right: unset;
|
||||
}
|
||||
|
||||
/* ckeditor5-table/theme/tablecolumnresize.css */
|
||||
.ck-content.ck-read-only .table .table-column-resizer {
|
||||
display: none;
|
||||
}
|
||||
|
||||
/* ckeditor5-code-block/theme/codeblock.css */
|
||||
.ck-content pre {
|
||||
padding: 1em;
|
||||
color: hsl(0, 0%, 20.8%);
|
||||
background: hsla(0, 0%, 78%, 0.3);
|
||||
border: 1px solid hsl(0, 0%, 77%);
|
||||
border-radius: 2px;
|
||||
text-align: left;
|
||||
direction: ltr;
|
||||
tab-size: 4;
|
||||
white-space: pre-wrap;
|
||||
font-style: normal;
|
||||
min-width: 200px;
|
||||
}
|
||||
|
||||
/* ckeditor5-code-block/theme/codeblock.css */
|
||||
.ck-content pre code {
|
||||
background: unset;
|
||||
padding: 0;
|
||||
border-radius: 0;
|
||||
}
|
||||
|
||||
/* ckeditor5-horizontal-line/theme/horizontalline.css */
|
||||
.ck-content hr {
|
||||
margin: 15px 0;
|
||||
height: 4px;
|
||||
background: hsl(0, 0%, 87%);
|
||||
border: 0;
|
||||
}
|
||||
|
||||
/* ckeditor5-mention/theme/mention.css */
|
||||
.ck-content .mention {
|
||||
background: var(--ck-color-mention-background);
|
||||
color: var(--ck-color-mention-text);
|
||||
}
|
||||
|
||||
@media print {
|
||||
/* ckeditor5-page-break/theme/pagebreak.css */
|
||||
.ck-content .page-break {
|
||||
padding: 0;
|
||||
}
|
||||
/* ckeditor5-page-break/theme/pagebreak.css */
|
||||
.ck-content .page-break::after {
|
||||
display: none;
|
||||
}
|
||||
}
|
||||
632
src/components/common.scss
Normal file
@@ -0,0 +1,632 @@
|
||||
@import '~uview-ui/theme.scss';
|
||||
@import "ckeditor";
|
||||
|
||||
/**
|
||||
常用内外边距样式
|
||||
*/
|
||||
@each $v in (8, 10, 12, 14, 16, 20, 24, 32, 48, 56, 64, 80) {
|
||||
//gap
|
||||
.gap-#{$v} {
|
||||
gap: #{$v}px
|
||||
}
|
||||
.font-#{$v} {
|
||||
font-size: #{$v}px;
|
||||
}
|
||||
@each $padMar, $pm in (mar:margin, pad:padding) {
|
||||
.#{$padMar}-#{$v} {
|
||||
#{$pm}: #{$v}px
|
||||
}
|
||||
//纵向
|
||||
.#{$padMar}-v#{$v} {
|
||||
#{$pm}-top: #{$v}px;
|
||||
#{$pm}-bottom: #{$v}px;
|
||||
}
|
||||
//横向
|
||||
.#{$padMar}-h#{$v} {
|
||||
#{$pm}-left: #{$v}px;
|
||||
#{$pm}-right: #{$v}px;
|
||||
}
|
||||
@each $pos, $p in (l:left, r:right, t:top, b:bottom) {
|
||||
.#{$padMar}-#{$pos+$v} {
|
||||
#{$pm}-#{$p}: #{$v}px
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@each $where in (sticky, fixed) {
|
||||
@each $pos, $p in (l:left, r:right, t:top, b:bottom) {
|
||||
.#{$where}-#{$pos} {
|
||||
position: fixed;
|
||||
#{$p}: 0;
|
||||
z-index: 202301031019;
|
||||
width: 100%;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.bg-fff {
|
||||
background-color: #fff;
|
||||
}
|
||||
|
||||
@font-face {
|
||||
font-family: 'iconfont';
|
||||
/* project id 1862352 */
|
||||
src: url('https://at.alicdn.com/t/font_1862352_jpvud12digs.eot');
|
||||
src: url('https://at.alicdn.com/t/font_1862352_jpvud12digs.eot?#iefix') format('embedded-opentype'),
|
||||
url('https://at.alicdn.com/t/font_1862352_jpvud12digs.woff2') format('woff2'),
|
||||
url('https://at.alicdn.com/t/font_1862352_jpvud12digs.woff') format('woff'),
|
||||
url('https://at.alicdn.com/t/font_1862352_jpvud12digs.ttf') format('truetype'),
|
||||
url('https://at.alicdn.com/t/font_1862352_jpvud12digs.svg#iconfont') format('svg');
|
||||
}
|
||||
|
||||
.iconfont {
|
||||
font-family: "iconfont" !important;
|
||||
font-size: 32px;
|
||||
font-style: normal;
|
||||
-webkit-font-smoothing: antialiased;
|
||||
-moz-osx-font-smoothing: grayscale;
|
||||
}
|
||||
|
||||
page {
|
||||
width: 100vw;
|
||||
min-height: 100vh;
|
||||
overflow-x: hidden;
|
||||
background-color: #f3f6f9;
|
||||
overflow-y: auto;
|
||||
}
|
||||
|
||||
::-webkit-scrollbar {
|
||||
width: 0;
|
||||
height: 0;
|
||||
color: transparent;
|
||||
}
|
||||
|
||||
.page {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
background-color: #f3f6f9;
|
||||
}
|
||||
|
||||
.text-hover {
|
||||
background: transparent;
|
||||
opacity: 0.5;
|
||||
}
|
||||
|
||||
.bg-hover {
|
||||
background: #eee !important;
|
||||
}
|
||||
|
||||
.flex {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
|
||||
&.spb {
|
||||
justify-content: space-between;
|
||||
}
|
||||
|
||||
&.wrap {
|
||||
flex-wrap: wrap;
|
||||
}
|
||||
|
||||
&.column {
|
||||
flex-direction: column;
|
||||
}
|
||||
|
||||
&.start {
|
||||
align-items: flex-start;
|
||||
}
|
||||
}
|
||||
|
||||
.fill {
|
||||
flex: 1;
|
||||
min-width: 0;
|
||||
min-height: 0;
|
||||
}
|
||||
|
||||
.flex-align {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.flex-between {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
}
|
||||
|
||||
.flex1 {
|
||||
flex: 1;
|
||||
}
|
||||
|
||||
.solid {
|
||||
border-bottom: 2px solid #E8E8E8;
|
||||
}
|
||||
|
||||
.flex-row {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.flex-column {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
}
|
||||
|
||||
uni-button[disabled] {
|
||||
background-color: #F7F7F7 !important;
|
||||
color: #999 !important;
|
||||
border: 0;
|
||||
}
|
||||
|
||||
uni-button:after {
|
||||
border: none !important;
|
||||
}
|
||||
|
||||
.break-word {
|
||||
word-break: break-all;
|
||||
}
|
||||
|
||||
.masking-layer {
|
||||
position: absolute;
|
||||
left: 0;
|
||||
top: 0;
|
||||
height: 100%;
|
||||
width: 100%;
|
||||
background-color: rgb(0, 0, 0);
|
||||
opacity: 0.6;
|
||||
}
|
||||
|
||||
/* 入口页列表 */
|
||||
// .list {
|
||||
// justify-content: space-between;
|
||||
// align-items: center;
|
||||
// height: 112px;
|
||||
// background-color: #fff;
|
||||
// padding-left: 32px;
|
||||
// padding-right: 32px;
|
||||
// box-sizing: border-box;
|
||||
// }
|
||||
|
||||
// .list-cell {
|
||||
// width: 48px;
|
||||
// height: 48px;
|
||||
// }
|
||||
.input-placeholder, .textarea-placeholder {
|
||||
color: #999999;
|
||||
font-size: 30px;
|
||||
}
|
||||
|
||||
.title-sub {
|
||||
height: 112px;
|
||||
margin-left: 16px;
|
||||
width: 654px;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
background: rgba(255, 255, 255, 1);
|
||||
font-size: 32px;
|
||||
color: #333333;
|
||||
}
|
||||
|
||||
.more {
|
||||
width: 32px;
|
||||
height: 32px;
|
||||
}
|
||||
|
||||
.title-line {
|
||||
border-bottom: 2px solid #DDDDDD;
|
||||
}
|
||||
|
||||
.last {
|
||||
margin-top: 16px;
|
||||
}
|
||||
|
||||
.no-content-pds {
|
||||
margin-top: 360px;
|
||||
width: 100%;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.no-content-pds view {
|
||||
height: 40px;
|
||||
font-size: 28px;
|
||||
line-height: 40px;
|
||||
font-family: PingFangSC-Regular, PingFangSC;
|
||||
}
|
||||
|
||||
.no-content-pds .text {
|
||||
color: rgba(51, 51, 51, 1);
|
||||
}
|
||||
|
||||
.no-content-pds .text-p {
|
||||
color: rgba(153, 153, 153, 1);
|
||||
margin-top: 16px;
|
||||
}
|
||||
|
||||
/* margin */
|
||||
.mar-t8 {
|
||||
margin-top: 16px;
|
||||
}
|
||||
|
||||
.mar-b8 {
|
||||
margin-bottom: 16px;
|
||||
}
|
||||
|
||||
.mar-r20 {
|
||||
margin-right: 40px;
|
||||
}
|
||||
|
||||
.mar-l10 {
|
||||
margin-left: 20px;
|
||||
}
|
||||
|
||||
/* color */
|
||||
.color-333 {
|
||||
color: #333;
|
||||
}
|
||||
|
||||
.color-999 {
|
||||
color: #999;
|
||||
}
|
||||
|
||||
.color-red {
|
||||
color: #FF4466;
|
||||
}
|
||||
|
||||
.color-666 {
|
||||
color: #666;
|
||||
}
|
||||
|
||||
.color-467DFE {
|
||||
color: #467DFE;
|
||||
}
|
||||
|
||||
.color-135AB8 {
|
||||
color: #197DF0 !important;
|
||||
}
|
||||
|
||||
/* */
|
||||
.font-12 {
|
||||
font-size: 24px;
|
||||
}
|
||||
|
||||
/* */
|
||||
.report {
|
||||
position: fixed;
|
||||
bottom: 0;
|
||||
width: 100%;
|
||||
height: 112px;
|
||||
background-color: #197DF0;
|
||||
color: #fff;
|
||||
text-align: center;
|
||||
line-height: 112px;
|
||||
font-size: 32px;
|
||||
}
|
||||
|
||||
.text-right {
|
||||
text-align: right;
|
||||
}
|
||||
|
||||
input::-webkit-input-placeholder {
|
||||
color: #999;
|
||||
}
|
||||
|
||||
.textarea-placeholder {
|
||||
color: #666;
|
||||
font-size: 26px;
|
||||
}
|
||||
|
||||
/* 多级下拉选择css */
|
||||
.type-picke-more {
|
||||
position: fixed;
|
||||
width: 100%;
|
||||
height: 330px;
|
||||
bottom: 0;
|
||||
left: 0;
|
||||
background-color: #fff;
|
||||
z-index: 99;
|
||||
}
|
||||
|
||||
.type-picke-more picker-view-column {
|
||||
text-align: center;
|
||||
line-height: 110px;
|
||||
}
|
||||
|
||||
|
||||
/* 固定在顶部 */
|
||||
.fixed-top {
|
||||
position: fixed;
|
||||
top: 0;
|
||||
left: 0;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
/* 固定在底部 */
|
||||
.fixed-bottom {
|
||||
position: fixed;
|
||||
bottom: 0;
|
||||
left: 0;
|
||||
width: 100%;
|
||||
z-index: 99;
|
||||
}
|
||||
|
||||
/* 背景颜色为蓝色的按钮 */
|
||||
.confirm-btn {
|
||||
background-color: #197DF0;
|
||||
height: 112px;
|
||||
line-height: 112px;
|
||||
color: #fff;
|
||||
font-size: 32px;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
/* 顶部搜索栏 */
|
||||
.header-search {
|
||||
width: 100%;
|
||||
height: 112px;
|
||||
padding: 16px 32px 32px 32px;
|
||||
box-sizing: border-box;
|
||||
background: #197DF0;
|
||||
}
|
||||
|
||||
.header-search .search-input-content {
|
||||
width: 686px;
|
||||
height: 64px;
|
||||
background: #0D6DDC;
|
||||
border-radius: 32px;
|
||||
padding: 14px 24px 0;
|
||||
box-sizing: border-box;
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.header-search .search-icon {
|
||||
width: 34px;
|
||||
height: 34px;
|
||||
position: absolute;
|
||||
top: 18px;
|
||||
left: 24px;
|
||||
}
|
||||
|
||||
.header-search .search-input {
|
||||
display: inline-block;
|
||||
width: calc(100% - 58px);
|
||||
height: 36px;
|
||||
line-height: 36px;
|
||||
color: #fff;
|
||||
font-size: 28px;
|
||||
padding-left: 58px;
|
||||
}
|
||||
|
||||
/* 顶部搜索栏 */
|
||||
|
||||
/* 顶部搜索框 (带下拉选择) */
|
||||
.header-search-select {
|
||||
width: 100%;
|
||||
height: 112px;
|
||||
background: #197DF0;
|
||||
padding: 24px 32px;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
.header-search-select .select-content {
|
||||
display: inline-block;
|
||||
width: 206px;
|
||||
line-height: 64px;
|
||||
font-weight: 500;
|
||||
font-size: 28px;
|
||||
color: #fff;
|
||||
vertical-align: top;
|
||||
}
|
||||
|
||||
.header-search-select .select-content img {
|
||||
width: 32px;
|
||||
height: 32px;
|
||||
vertical-align: middle;
|
||||
}
|
||||
|
||||
.header-search-select .input-content {
|
||||
display: inline-block;
|
||||
width: calc(100% - 206px);
|
||||
height: 64px;
|
||||
background: #0D6DDC;
|
||||
border-radius: 32px;
|
||||
padding: 14px 24px 0 58px;
|
||||
box-sizing: border-box;
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.header-search-select .search-icon {
|
||||
width: 34px;
|
||||
height: 34px;
|
||||
position: absolute;
|
||||
top: 18px;
|
||||
left: 24px;
|
||||
}
|
||||
|
||||
.header-search-select .search-input {
|
||||
display: inline-block;
|
||||
width: calc(100% - 58px);
|
||||
height: 36px;
|
||||
line-height: 36px;
|
||||
color: #fff;
|
||||
padding-left: 20px;
|
||||
font-size: 28px;
|
||||
}
|
||||
|
||||
/* 顶部搜索框 (带下拉选择) */
|
||||
|
||||
/* 顶部筛选框 */
|
||||
.header-select {
|
||||
width: 100%;
|
||||
height: 96px;
|
||||
background-color: #fff;
|
||||
padding: 24px 0;
|
||||
box-sizing: border-box;
|
||||
display: flex;
|
||||
}
|
||||
|
||||
.header-select .select-item {
|
||||
flex: 1;
|
||||
height: 48px;
|
||||
line-height: 48px;
|
||||
text-align: center;
|
||||
color: #666;
|
||||
font-size: 26px;
|
||||
}
|
||||
|
||||
.header-select .down-icon {
|
||||
width: 32px;
|
||||
height: 32px;
|
||||
vertical-align: middle;
|
||||
margin-left: 8px;
|
||||
}
|
||||
|
||||
.header-select .select-item:nth-of-type(2) {
|
||||
border-left: 2px solid #eee;
|
||||
}
|
||||
|
||||
/* 顶部筛选框 */
|
||||
|
||||
/* 顶部tab类型切换栏 */
|
||||
.header-tab {
|
||||
height: 96px;
|
||||
background-color: #4181FF;
|
||||
padding: 20px 0;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
.header-tab .tab-item {
|
||||
flex: 1;
|
||||
text-align: center;
|
||||
position: relative;
|
||||
color: #fff;
|
||||
font-size: 28px;
|
||||
}
|
||||
|
||||
.header-tab .tab-active {
|
||||
font-weight: 500;
|
||||
}
|
||||
|
||||
.header-tab .active-line {
|
||||
position: absolute;
|
||||
width: 40px;
|
||||
height: 4px;
|
||||
background: #FFF;
|
||||
top: 48px;
|
||||
left: 50%;
|
||||
transform: translate(-50%, -50%);
|
||||
}
|
||||
|
||||
/* 顶部tab类型切换栏 */
|
||||
|
||||
/* 下划线 */
|
||||
.underline {
|
||||
text-decoration: underline;
|
||||
}
|
||||
|
||||
/* 字体加粗 500 */
|
||||
.fw500 {
|
||||
font-weight: 500;
|
||||
}
|
||||
|
||||
/* u-input字体大小重置 */
|
||||
.fs-32 .u-input__input {
|
||||
line-height: 42px !important;
|
||||
font-size: 32px !important;
|
||||
height: 180px !important;
|
||||
overflow-y: scroll;
|
||||
}
|
||||
|
||||
/* button样式重置 */
|
||||
button {
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
background-color: #fff;
|
||||
line-height: inherit;
|
||||
border-radius: 0;
|
||||
border: none;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
button::after {
|
||||
border: none;
|
||||
}
|
||||
|
||||
.button-hover {
|
||||
background-color: #fff;
|
||||
}
|
||||
|
||||
.btn-wrapper {
|
||||
position: fixed;
|
||||
left: 50%;
|
||||
bottom: 0;
|
||||
z-index: 11;
|
||||
width: 100%;
|
||||
padding: 20px 0 20px 0 !important;
|
||||
transform: translateX(-50%);
|
||||
background: #f3f6f9;
|
||||
}
|
||||
|
||||
.bottomBtn {
|
||||
color: #fff;
|
||||
font-size: 34px;
|
||||
background: #4181FF;
|
||||
border-radius: 16px;
|
||||
height: 88px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
margin: 8px 24px;
|
||||
}
|
||||
|
||||
.btn-wrapper {
|
||||
.btn {
|
||||
width: 686px;
|
||||
height: 88px;
|
||||
line-height: 88px;
|
||||
margin: 0 auto;
|
||||
padding: 0 !important;
|
||||
text-align: center;
|
||||
color: #fff;
|
||||
font-size: 34px;
|
||||
background: #4181FF;
|
||||
border-radius: 16px;
|
||||
}
|
||||
|
||||
.disabled {
|
||||
color: #B9E7D0;
|
||||
background: #50C48A;
|
||||
}
|
||||
}
|
||||
|
||||
.rich-content {
|
||||
::v-deep {
|
||||
p {
|
||||
margin: 20px 0;
|
||||
line-height: 1.4;
|
||||
font-size: 30px;
|
||||
text-align: justify;
|
||||
color: #444;
|
||||
}
|
||||
|
||||
image {
|
||||
// margin: 20px 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.tabs {
|
||||
position: fixed;
|
||||
top: 0;
|
||||
left: 0;
|
||||
z-index: 11;
|
||||
width: 100%;
|
||||
padding: 10px 0 10px 16px;
|
||||
box-sizing: border-box;
|
||||
background: #4181FF;
|
||||
}
|
||||
8
src/components/package.json
Normal file
@@ -0,0 +1,8 @@
|
||||
{
|
||||
"name": "dvcp-wui",
|
||||
"description": "小程序UI新库",
|
||||
"version": "1.0.1",
|
||||
"dependencies": {
|
||||
"axios-miniprogram-adapter": "^0.3.2"
|
||||
}
|
||||
}
|
||||
BIN
src/components/pages/img/gird--select-icon.png
Normal file
|
After Width: | Height: | Size: 1.2 KiB |
BIN
src/components/pages/img/right-icon.png
Normal file
|
After Width: | Height: | Size: 373 B |
BIN
src/components/pages/img/tx@2x.png
Normal file
|
After Width: | Height: | Size: 1.4 KiB |
BIN
src/components/pages/img/user-img.png
Normal file
|
After Width: | Height: | Size: 1.4 KiB |
BIN
src/components/pages/img/xz.png
Normal file
|
After Width: | Height: | Size: 1.5 KiB |
BIN
src/components/pages/img/xzh.png
Normal file
|
After Width: | Height: | Size: 1.7 KiB |
337
src/components/pages/selectArea.vue
Normal file
@@ -0,0 +1,337 @@
|
||||
<template>
|
||||
<section class="selectArea">
|
||||
<div class="areaSelector">
|
||||
<div class="fixedTop">
|
||||
<em>选择区域</em>
|
||||
<div class="selectedArea">
|
||||
<p v-if="hasSelected" v-text="fullArea.map(e=>e.name).join('')"/>
|
||||
<p v-else>请选择</p>
|
||||
</div>
|
||||
<div/>
|
||||
<span v-if="urlParams.all" v-text="`省`" @click="selectNode({}, -1)"/>
|
||||
<span v-for="(area,i) in typeLabels" :key="area.id"
|
||||
v-text="area.levelLabel" @click="selectNode(area, i)"/>
|
||||
</div>
|
||||
</div>
|
||||
<scroll-view class="fill pendingList" scroll-y>
|
||||
<div class="pendingItem flexRow" flex v-for="op in pending" :key="op.id" @tap.stop="getChild(op)">
|
||||
<div class="fill" :class="{ self: index == op.id }" v-html="op.name"/>
|
||||
<u-icon v-if="index == op.id" name="checkbox-mark" color="#4181FF"/>
|
||||
</div>
|
||||
<AiEmpty v-if="pending.length==0" description="无下级地区数据"/>
|
||||
</scroll-view>
|
||||
<div class="bottomBtns">
|
||||
<div @click.stop="back">取消</div>
|
||||
<div class="primary fill" @click.stop="handleSelect">确定</div>
|
||||
</div>
|
||||
</section>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
|
||||
export default {
|
||||
name: "selectArea",
|
||||
appName: "选择地区",
|
||||
computed: {
|
||||
dataRange() {
|
||||
return this.urlParams.all || this.urlParams.disabled ? 0 : this.getAreaType(this.root)
|
||||
},
|
||||
root() {
|
||||
return this.urlParams.areaId || this.$areaId
|
||||
},
|
||||
pending() {
|
||||
return this.list?.map(e => ({...e, levelLabel: this.levelLabels[e.type]})) || []
|
||||
},
|
||||
hasSelected() {
|
||||
return this.fullArea?.length > 0
|
||||
},
|
||||
hasLastLevelValue() {
|
||||
return this.fullArea.some(e => e.type >= this.urlParams.valueLevel)
|
||||
},
|
||||
typeLabels() {
|
||||
return this.fullArea.filter(e => e.type < this.urlParams.valueLevel)
|
||||
}
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
fullArea: [],
|
||||
index: '',
|
||||
list: [],
|
||||
levelLabels: ["省", "市", "县/区", "镇/街道", "村/社区"],
|
||||
selected: {},
|
||||
urlParams: {}
|
||||
}
|
||||
},
|
||||
watch: {
|
||||
root(v) {
|
||||
v && (this.getFullArea(v))
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
getInfo(areaId) {
|
||||
return areaId && this.$instance.post('/admin/area/getAllParentAreaId', null, {
|
||||
withoutToken: true,
|
||||
params: {areaId},
|
||||
}).then(res => {
|
||||
if (res?.data) {
|
||||
res.data.forEach((e) => {
|
||||
e && (e.levelLabel = this.levelLabels[e.type])
|
||||
})
|
||||
return res.data.reverse()
|
||||
}
|
||||
})
|
||||
},
|
||||
getFullArea(areaId) {
|
||||
return this.fullArea?.length > 0 ? Promise.resolve(this.fullArea) : this.getInfo(areaId).then(meta => {
|
||||
if (meta.length > 1) {
|
||||
this.fullArea = meta.slice(this.dataRange)
|
||||
} else {
|
||||
this.fullArea = meta
|
||||
}
|
||||
return this.fullArea
|
||||
})
|
||||
},
|
||||
getChildAreas(id) {
|
||||
id && this.$instance.post('/admin/area/queryAreaByParentId', null, {
|
||||
withoutToken: true,
|
||||
params: {id},
|
||||
}).then((res) => {
|
||||
if (res?.data) {
|
||||
this.list = res.data
|
||||
if (this.urlParams.selectRoot) {
|
||||
if (this.hasLastLevelValue) {
|
||||
let parent = JSON.parse(JSON.stringify(this.fullArea?.slice(-2)?.[0]))
|
||||
this.list.unshift(parent)
|
||||
} else {
|
||||
let parent = JSON.parse(JSON.stringify(this.fullArea?.slice(-1)?.[0]))
|
||||
this.list.unshift(parent)
|
||||
}
|
||||
}
|
||||
}
|
||||
})
|
||||
},
|
||||
getProvinces() {
|
||||
this.$instance.post('/admin/area/queryProvinceList', null, {withoutToken: true}).then((res) => {
|
||||
if (res?.data) {
|
||||
this.list = res.data
|
||||
}
|
||||
})
|
||||
},
|
||||
handleSelect() {
|
||||
let {selected, fullArea} = this
|
||||
uni.$emit("selectArea", {...selected, fullArea})
|
||||
this.back()
|
||||
},
|
||||
getChild(op) {
|
||||
if (op.id != this.index) {
|
||||
this.selected = op
|
||||
this.index = op.id
|
||||
let {length} = this.fullArea
|
||||
if (op.type == this.urlParams.valueLevel) {
|
||||
if (this.hasLastLevelValue) {
|
||||
this.fullArea.splice(length - 1, 1, op)
|
||||
} else this.fullArea.push(op)
|
||||
} else if (op.type < this.urlParams.valueLevel) {
|
||||
if (this.hasLastLevelValue) {
|
||||
this.fullArea.splice(length - 1, 1)
|
||||
} else {
|
||||
this.fullArea.push(op)
|
||||
this.getChildAreas(op.id)
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
selectNode(area, i) {
|
||||
let deleteCount = this.fullArea.length - i
|
||||
if (deleteCount > 0) {
|
||||
this.fullArea.splice(i + 1, deleteCount)
|
||||
}
|
||||
if (this.urlParams.all && !area.id) {
|
||||
this.index = ''
|
||||
this.getProvinces()
|
||||
} else {
|
||||
this.index = area.id
|
||||
this.getChildAreas(area.id)
|
||||
}
|
||||
},
|
||||
handleInit() {
|
||||
//初始化
|
||||
this.index = this.urlParams.value || this.root
|
||||
if (!this.urlParams.disabled) {
|
||||
if (this.urlParams.value) {
|
||||
this.getFullArea(this.urlParams.value).then(() => {
|
||||
let area = this.fullArea.find(e => e.id == this.urlParams.value) || {}
|
||||
//当前选择列表必须是可选范围内的值
|
||||
let top = area.type == this.urlParams.valueLevel ? area.parentId : area.id
|
||||
if (this.getAreaType(top) >= this.dataRange) {
|
||||
this.getChildAreas(top)
|
||||
}
|
||||
})
|
||||
} else if (this.urlParams.all) {
|
||||
this.getProvinces()
|
||||
} else {
|
||||
this.getFullArea(this.root).then(() => {
|
||||
this.getChildAreas(this.root)
|
||||
})
|
||||
}
|
||||
}
|
||||
},
|
||||
back() {
|
||||
uni.navigateBack({})
|
||||
},
|
||||
getAreaType(area) {
|
||||
let rules = [10, 8, 6, 3, 0], level = 0
|
||||
if (area) {
|
||||
rules.some((e, i) => {
|
||||
let reg = new RegExp(`0{${e}}`, 'g')
|
||||
if (reg.test(area)) {
|
||||
return (level = i)
|
||||
}
|
||||
})
|
||||
}
|
||||
return level
|
||||
}
|
||||
},
|
||||
onLoad(params) {
|
||||
Object.keys(params).map(k => {
|
||||
this.$set(this.urlParams, k,
|
||||
params[k] == "false" ? false :
|
||||
params[k] == "undefined" ? null : params[k]
|
||||
)
|
||||
})
|
||||
this.$nextTick(() => this.handleInit())
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.selectArea {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
height: 100vh;
|
||||
background: #fff;
|
||||
|
||||
::v-deep .areaSelector {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
|
||||
span {
|
||||
cursor: pointer;
|
||||
color: #333;
|
||||
font-weight: bold;
|
||||
line-height: 112px;
|
||||
margin-right: 72px;
|
||||
position: relative;
|
||||
|
||||
&:last-of-type {
|
||||
margin-right: 0;
|
||||
|
||||
&:after {
|
||||
content: " ";
|
||||
display: block;
|
||||
position: absolute;
|
||||
bottom: -26px;
|
||||
left: 50%;
|
||||
transform: translate(-50%, 100%);
|
||||
width: 40px;
|
||||
height: 8px;
|
||||
background: #4181FF;
|
||||
border-radius: 4px;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
em {
|
||||
font-style: normal;
|
||||
font-size: 24px;
|
||||
font-weight: 400;
|
||||
color: #999999;
|
||||
line-height: 34px;
|
||||
}
|
||||
|
||||
.selectedArea {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
width: fit-content;
|
||||
max-width: calc(100vw - 128px);
|
||||
padding: 0 32px;
|
||||
height: 80px;
|
||||
background: #ECF2FF;
|
||||
border-radius: 40px;
|
||||
font-size: 32px;
|
||||
font-family: PingFangSC-Medium, PingFang SC;
|
||||
font-weight: 500;
|
||||
color: #4181FF !important;
|
||||
margin: 16px 0 32px;
|
||||
white-space: nowrap;
|
||||
|
||||
& > p {
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
direction: rtl;
|
||||
}
|
||||
}
|
||||
|
||||
.fixedTop {
|
||||
width: 100vw;
|
||||
background: #fff;
|
||||
border-bottom: 4px solid #f5f5f5;
|
||||
text-align: start;
|
||||
padding: 32px 32px 0;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
}
|
||||
|
||||
::v-deep .pendingList {
|
||||
padding: 0 32px;
|
||||
box-sizing: border-box;
|
||||
|
||||
.emptyWrap {
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.pendingItem {
|
||||
color: #333;
|
||||
height: 84px;
|
||||
text-align: start;
|
||||
|
||||
.self {
|
||||
font-weight: bold;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
::v-deep.bottomBtns {
|
||||
width: 100vw;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
text-align: center;
|
||||
height: 120px;
|
||||
font-size: 34px;
|
||||
font-family: PingFangSC-Medium, PingFang SC;
|
||||
font-weight: 500;
|
||||
color: #3671EE;
|
||||
background: #fff;
|
||||
padding: 0 32px;
|
||||
box-sizing: border-box;
|
||||
|
||||
& > div {
|
||||
padding: 0 92px;
|
||||
line-height: 88px;
|
||||
height: 88px;
|
||||
border: 1px solid #A0C0FF;
|
||||
border-radius: 16px;
|
||||
|
||||
&.primary {
|
||||
color: #fff;
|
||||
background: #4181FF;
|
||||
border-color: #4181FF;
|
||||
}
|
||||
|
||||
& + div {
|
||||
margin-left: 32px;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
182
src/components/pages/selectDept.vue
Normal file
@@ -0,0 +1,182 @@
|
||||
<template>
|
||||
<div class="selectDept">
|
||||
<AiTopFixed>
|
||||
<AiTreePath :node="cursor" :paths="depts.map" :prop="{parent:'parentid'}" @click="changeList"/>
|
||||
</AiTopFixed>
|
||||
<div class="user-list">
|
||||
<template v-if="list.length>0">
|
||||
<div class="item" v-for="(item, index) in list" :key="index" flex>
|
||||
<div class="select-img" @click="checkClick(item)">
|
||||
<img :src="item.isCheck ? checkIcon : cirIcon" alt="">
|
||||
</div>
|
||||
<div class="user-info fill" flex @click="getCursor(item)">
|
||||
<div class="fill" v-text="item.name"/>
|
||||
<u-icon v-if="Array.isArray(item.children)" class="mar-r16" name="arrow-right" size="40" color="#999"/>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
<template v-else>
|
||||
<AiEmpty/>
|
||||
<div class="pad-b118"/>
|
||||
</template>
|
||||
</div>
|
||||
<div class="pad-b118"/>
|
||||
<div class="footer">
|
||||
<div class="btn" @click="confirm">确定选择</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import {mapState} from 'vuex'
|
||||
|
||||
export default {
|
||||
name: "selectDept",
|
||||
appName: "选择部门",
|
||||
data() {
|
||||
return {
|
||||
current: 1,
|
||||
total: 0,
|
||||
name: '',
|
||||
list: [],
|
||||
depts: [],
|
||||
cirIcon: require('./img/xz.png'),
|
||||
checkIcon: require('./img/xzh.png'),
|
||||
selected: [],
|
||||
cursor: {}
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
...mapState(['user']),
|
||||
isSingle: v => !!v.$route.query.single,
|
||||
nodeKey: v => v.$route.query.nodeKey || "idNumber",
|
||||
isRequire: v => v.$route.query.isRequire || 1,
|
||||
isAuth: v => !!v.$route.query.isAuth, //是否只能选择自己当前部门及以下
|
||||
},
|
||||
onLoad(query) {
|
||||
console.log(query)
|
||||
if (query.selected) {
|
||||
this.selected = query.selected?.split(",").map(e => Number(e)) || []
|
||||
}
|
||||
this.getList()
|
||||
},
|
||||
methods: {
|
||||
getList() {
|
||||
var url = this.isAuth ? `/app/wxcp/wxdepartment/listByUser?name=${this.name}` : `/app/wxcp/wxdepartment/listAll?name=${this.name}`
|
||||
this.$http.post(url).then(res => {
|
||||
if (res?.data) {
|
||||
res.data.forEach(e => e.isCheck = this.selected.includes(e[this.nodeKey]))
|
||||
this.depts = new this.$tree(res.data, {parent: 'parentid'})
|
||||
this.list = this.depts.tree
|
||||
}
|
||||
})
|
||||
},
|
||||
checkClick(item) {
|
||||
if (this.isSingle && this.isRequire == 1) {
|
||||
this.depts.every(e => {
|
||||
e.isCheck = item.id == e.id
|
||||
})
|
||||
} else item.isCheck = !item.isCheck
|
||||
|
||||
},
|
||||
confirm() {
|
||||
let checkList = []
|
||||
this.depts.every((item) => {
|
||||
if (item.isCheck) {
|
||||
checkList.push(item)
|
||||
}
|
||||
})
|
||||
if (!checkList.length && this.isRequire == 1) {
|
||||
return this.$u.toast('请先选择部门')
|
||||
} else {
|
||||
uni.navigateBack({
|
||||
success: () => {
|
||||
uni.$emit("pagePicker:dept", checkList)
|
||||
}
|
||||
})
|
||||
}
|
||||
},
|
||||
changeList(item) {
|
||||
if (item == "all") {
|
||||
this.cursor = {}
|
||||
this.list = this.depts.tree
|
||||
} else {
|
||||
this.cursor = item
|
||||
this.list = item.children
|
||||
}
|
||||
},
|
||||
getCursor(item) {
|
||||
if (item.children?.length > 0) {
|
||||
this.cursor = item
|
||||
this.list = item.children
|
||||
}
|
||||
}
|
||||
},
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.selectDept {
|
||||
::v-deep .AiTopFixed .u-search {
|
||||
margin-bottom: 0 !important;
|
||||
}
|
||||
|
||||
.pad-b118 {
|
||||
padding-bottom: 118px;
|
||||
}
|
||||
|
||||
.user-list {
|
||||
background-color: #fff;
|
||||
|
||||
.item {
|
||||
width: 100vw;
|
||||
|
||||
.select-img {
|
||||
display: inline-block;
|
||||
|
||||
img {
|
||||
width: 48px;
|
||||
height: 48px;
|
||||
margin: 12px 36px 12px 30px;
|
||||
vertical-align: middle;
|
||||
}
|
||||
}
|
||||
|
||||
.user-info {
|
||||
padding: 20px 0 20px 0;
|
||||
height: 100%;
|
||||
border-bottom: 1px solid #E4E5E6;
|
||||
font-size: 36px;
|
||||
font-family: PingFangSC-Medium, PingFang SC;
|
||||
font-weight: 500;
|
||||
color: #333;
|
||||
line-height: 74px;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.footer {
|
||||
width: 100%;
|
||||
height: 118px;
|
||||
background: #F4F8FB;
|
||||
position: fixed;
|
||||
left: 0;
|
||||
bottom: 0;
|
||||
text-align: right;
|
||||
|
||||
.btn {
|
||||
display: inline-block;
|
||||
width: 192px;
|
||||
height: 80px;
|
||||
line-height: 80px;
|
||||
background: #1365DD;
|
||||
border-radius: 4px;
|
||||
text-align: center;
|
||||
font-size: 32px;
|
||||
font-family: PingFangSC-Regular, PingFang SC;
|
||||
color: #FFF;
|
||||
margin: 20px 34px 0 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
303
src/components/pages/selectDeptUser.vue
Normal file
@@ -0,0 +1,303 @@
|
||||
<template>
|
||||
<section class="selectDeptUser">
|
||||
<div class="header-middle">
|
||||
<div class="hint">
|
||||
<span v-for="(item, index) in selectDeptPath" :key="index">
|
||||
<span v-if="index>0" class="mar-h4">/</span>
|
||||
<span class="color-3F8DF5" @click="deptNameClick(item, index)">{{ item.name }}</span>
|
||||
</span>
|
||||
</div>
|
||||
<div class="cards" v-for="item in treeList" :key="item.id" @click="itemClick(item)">
|
||||
<div class="imges">
|
||||
<div class="imgselect" v-if="type == 1" :class="{checked:item.isChecked}" />
|
||||
<img src="./img/gird--select-icon.png" alt="" class="avatras"/>
|
||||
</div>
|
||||
<div class="rightes">
|
||||
<div class="applicationNames">{{ item.name }}</div>
|
||||
<img src="./img/right-icon.png" alt="" class="imgs"/>
|
||||
</div>
|
||||
</div>
|
||||
<div v-if="type == 0">
|
||||
<div class="userCards" v-for="(e, userIndex) in userList" :key="e.id">
|
||||
<div class="imges">
|
||||
<div class="imgselect" :class="{checked:e.isChecked}" @click.stop="itemCheck(e, 'user', userIndex)"/>
|
||||
<img src="./img/tx@2x.png" alt="" class="avatras"/>
|
||||
</div>
|
||||
<div class="rights fill">
|
||||
<div class="applicationNames" v-text="e.name"></div>
|
||||
<div class="idNumbers">{{ e.phone }}</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<AiEmpty description="暂无数据" v-if="!hasData"/>
|
||||
</div>
|
||||
<div class="subBtn" @click="submit">
|
||||
<div>确定选择</div>
|
||||
</div>
|
||||
</section>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { mapState } from "vuex";
|
||||
export default {
|
||||
name: "selectDeptUser",
|
||||
appName: "选择人员",
|
||||
data() {
|
||||
return {
|
||||
selected: [],
|
||||
allData: null,
|
||||
treeList: [],
|
||||
selectDeptPath: [],
|
||||
userList: [],
|
||||
type: 0,
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
isSingle: v => !!v.$route.query.single,
|
||||
nodeKey: v => v.$route.query.nodeKey || "id",
|
||||
isRequire: v => v.$route.query.isRequire || 1,
|
||||
hasData() {
|
||||
return this.treeList?.length > 0 || this.userList?.length > 0
|
||||
},
|
||||
...mapState(['user'])
|
||||
},
|
||||
onLoad(query) {
|
||||
if (query.selected) {
|
||||
this.selected = query.selected?.split(",") || []
|
||||
}
|
||||
this.getListAll()
|
||||
},
|
||||
methods: {
|
||||
isSelected(id) {
|
||||
return !!this.selected.find(e => e == id)
|
||||
},
|
||||
getListAll() {
|
||||
this.$instance.post('/app/wxcp/wxdepartment/listAllByCorp').then((res) => {
|
||||
if (res?.data) {
|
||||
let parents = res.data.map(e => e.parentid)
|
||||
this.allData = res.data.map(e => ({...e, hasChildren: parents.includes(e.id), isChecked: this.isSelected(e.id)}))
|
||||
this.deptInit()
|
||||
}
|
||||
})
|
||||
},
|
||||
deptInit() {
|
||||
this.treeList = this.allData.filter(e => !e.parentid)
|
||||
this.selectDeptPath = [{name: "可选范围", id: ''}]
|
||||
},
|
||||
itemClick({id, name, corpId}) {
|
||||
let index = this.selectDeptPath.findIndex(e => e.id == id && e.corpId == corpId)
|
||||
if (index == -1) {
|
||||
this.selectDeptPath.push({name, id, corpId})
|
||||
this.getDeptsAndUsersByParent(id, corpId)
|
||||
}
|
||||
},
|
||||
getDeptsAndUsersByParent(departmentId, corpId) {
|
||||
this.treeList = this.allData.filter(e => e.parentid == departmentId && e.corpId == corpId)
|
||||
this.userList = []
|
||||
this.$instance.post(`/app/wxcp/wxuser/listByDeptId`, null, {
|
||||
params: {departmentId, status: 1, cid: corpId}
|
||||
}).then(res => {
|
||||
if (res?.data) {
|
||||
this.userList = res.data.map(e => ({...e, isChecked: this.isSelected(e.id, e.corpId)}))
|
||||
}
|
||||
})
|
||||
},
|
||||
deptNameClick(row, index) {
|
||||
this.userList = []
|
||||
if (!index) { //第一级别
|
||||
this.deptInit()
|
||||
} else {
|
||||
let length = this.selectDeptPath.length - index
|
||||
this.selectDeptPath.splice(index + 1, length)
|
||||
this.getDeptsAndUsersByParent(row.id, row.corpId)
|
||||
}
|
||||
},
|
||||
itemCheck(row, kind, index) {
|
||||
if(this.isSingle) {
|
||||
this.selected = []
|
||||
this.userList.map((item) => {
|
||||
item.isChecked = false
|
||||
})
|
||||
this.userList[index].isChecked = true
|
||||
this.selected.push({...row, kind})
|
||||
} else {
|
||||
row.isChecked = !row.isChecked
|
||||
if (row.isChecked) {
|
||||
this.selected.push({...row, kind})
|
||||
} else {
|
||||
let index = this.selected.findIndex(e => e.id == row.id)
|
||||
this.selected.splice(index, 1)
|
||||
}
|
||||
}
|
||||
this.$forceUpdate()
|
||||
},
|
||||
submit() {
|
||||
if(![this.selected].flat().length) {
|
||||
return this.$u.toast('请选择人员')
|
||||
}
|
||||
uni.navigateBack({
|
||||
success: () => {
|
||||
uni.$emit("pagePicker:deptUser", this.selected)
|
||||
}
|
||||
})
|
||||
},
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.selectDeptUser {
|
||||
height: 100%;
|
||||
background: #fff;
|
||||
|
||||
.header-top {
|
||||
background: #fff;
|
||||
padding: 20px 32px;
|
||||
}
|
||||
|
||||
.header-middle {
|
||||
padding-bottom: 140px;
|
||||
|
||||
.hint {
|
||||
padding: 28px 20px 28px 32px;
|
||||
line-height: 56px;
|
||||
box-shadow: 0 1px 0 0 #e4e5e6;
|
||||
font-size: 30px;
|
||||
font-weight: 500;
|
||||
word-break: break-all;
|
||||
}
|
||||
|
||||
.empty-div {
|
||||
height: 16px;
|
||||
background: #f5f5f5;
|
||||
}
|
||||
|
||||
.imges {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
|
||||
.imgselect {
|
||||
width: 48px;
|
||||
height: 48px;
|
||||
vertical-align: middle;
|
||||
background-image: url("./img/xz.png");
|
||||
background-position: center;
|
||||
background-size: 100% 100%;
|
||||
|
||||
&.checked {
|
||||
background-image: url("./img/xzh.png");
|
||||
}
|
||||
}
|
||||
|
||||
.avatras {
|
||||
width: 74px;
|
||||
height: 74px;
|
||||
border-radius: 8px;
|
||||
margin-left: 36px;
|
||||
}
|
||||
}
|
||||
|
||||
.cards {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
height: 120px;
|
||||
line-height: 120px;
|
||||
padding: 0 0 0 32px;
|
||||
|
||||
|
||||
img {
|
||||
width: 74px;
|
||||
height: 74px;
|
||||
border-radius: 8px;
|
||||
}
|
||||
|
||||
.rightes {
|
||||
width: calc(100% - 160px);
|
||||
display: flex;
|
||||
align-items: center;
|
||||
margin-left: 32px;
|
||||
border-bottom: 1px solid #e4e5e6;
|
||||
|
||||
.applicationNames {
|
||||
flex: 1;
|
||||
min-width: 0;
|
||||
font-size: 36px;
|
||||
font-weight: 500;
|
||||
color: #333333;
|
||||
overflow: hidden;
|
||||
white-space: nowrap;
|
||||
text-overflow: ellipsis;
|
||||
}
|
||||
|
||||
.imgs {
|
||||
flex-shrink: 0;
|
||||
width: 40px;
|
||||
height: 40px;
|
||||
margin-right: 20px;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.userCards {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
height: 120px;
|
||||
line-height: 120px;
|
||||
padding: 0 0 0 32px;
|
||||
|
||||
.rights {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
margin-left: 32px;
|
||||
border-bottom: 1px solid #e4e5e6;
|
||||
padding-right: 40px;
|
||||
height: inherit;
|
||||
|
||||
.applicationNames {
|
||||
font-size: 36px;
|
||||
font-weight: 500;
|
||||
color: #333333;
|
||||
overflow: hidden;
|
||||
white-space: nowrap;
|
||||
text-overflow: ellipsis;
|
||||
}
|
||||
|
||||
.idNumbers {
|
||||
color: #666;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.subBtn {
|
||||
position: fixed;
|
||||
bottom: 0;
|
||||
left: 0;
|
||||
width: 100%;
|
||||
height: 118px;
|
||||
background: #f4f8fb;
|
||||
|
||||
div {
|
||||
width: 192px;
|
||||
height: 80px;
|
||||
line-height: 80px;
|
||||
text-align: center;
|
||||
background: #1365dd;
|
||||
border-radius: 4px;
|
||||
font-size: 32px;
|
||||
color: #fff;
|
||||
margin: 20px 34px 0 0;
|
||||
float: right;
|
||||
}
|
||||
}
|
||||
|
||||
.color-3F8DF5 {
|
||||
color: #3F8DF5;
|
||||
}
|
||||
|
||||
.mar-h4 {
|
||||
margin: 0 4px;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
253
src/components/pages/selectGird.vue
Normal file
@@ -0,0 +1,253 @@
|
||||
<template>
|
||||
<div class="SelectGird">
|
||||
<div class="header-middle">
|
||||
<div class="hint">
|
||||
<span v-for="(item, index) in selectList" :key="index">
|
||||
<span v-if="index" style="margin:0 4px;" v-text="`/`"/>
|
||||
<span style="color:#3F8DF5" @click="girdNameClick(item, index)" v-text="item.girdName"/>
|
||||
</span>
|
||||
</div>
|
||||
<div class="showTypes">
|
||||
<div v-if="options.length > 0">
|
||||
<div class="cards" v-for="(item, index) in options" :key="index" @click="itemClick(item)">
|
||||
<div class="imges">
|
||||
<img src="./img/xzh.png" alt="" class="imgselect" v-if="item.isChecked"
|
||||
@click.stop="girdClick(item, index)"/>
|
||||
<img src="./img/xz.png" alt="" class="imgselect" v-else @click.stop="girdClick(item, index)"/>
|
||||
<img src="./img/gird--select-icon.png" alt="" class="avatras"/>
|
||||
</div>
|
||||
<div class="rightes fill">
|
||||
<div class="applicationNames fill">{{ item.girdName }}</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<AiEmpty :description="`暂无数据`" class="emptyWrap" v-else/>
|
||||
</div>
|
||||
</div>
|
||||
<div class="subBtn flex">
|
||||
<div v-if="clearable" class="cancel" @click="cancel">清空</div>
|
||||
<div @click="submit">确定选择</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import {mapState} from "vuex";
|
||||
|
||||
export default {
|
||||
name: 'selectGird',
|
||||
appName: "网格选择",
|
||||
data() {
|
||||
return {
|
||||
SelectGird: {},
|
||||
allData: null,
|
||||
options: [],
|
||||
selectList: [],
|
||||
parentGirdId: '',
|
||||
query: {}
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
...mapState(['user']),
|
||||
//是否展示所有网格(随手拍)
|
||||
isApply: v => v.query?.formType == 2,
|
||||
clearable: v => v.query?.clearable,
|
||||
selected: v => [v.query?.selected].flat(),
|
||||
},
|
||||
onLoad(query) {
|
||||
this.query = query
|
||||
this.getAllGrids()
|
||||
},
|
||||
methods: {
|
||||
getAllGrids() {
|
||||
this.selectList = []
|
||||
let url = this.query.axiosUrl ? this.query.axiosUrl : `/app/appgirdinfo/listByInfo`
|
||||
this.$instance.post(url).then(res => {
|
||||
if (res?.data) {
|
||||
let parents = res.data?.map(e => e.parentGirdId)
|
||||
this.allData = res.data?.map(e => ({...e, hasChildren: parents.includes(e.id)}))
|
||||
this.treeInit()
|
||||
}
|
||||
})
|
||||
},
|
||||
treeInit(isClick) {
|
||||
let last = uni.getStorageSync("lastSelectedGrid")
|
||||
if (!isClick && last && !this.isApply) {
|
||||
this.$instance.post("/app/appgirdinfo/listFatherGirdInfo", null, {
|
||||
params: {girdId: last}
|
||||
}).then(res => {
|
||||
if (res?.data) {
|
||||
this.selectList = [{girdName: '可选范围', id: ''}, res.data.filter(e => !!this.allData.find(a => a.id == e.id))].flat()
|
||||
this.getGridsByGridMemberAndParent({id: last})
|
||||
}
|
||||
})
|
||||
} else {
|
||||
this.options = this.allData.filter((e, i, arr) => !arr?.map(e => e.id).includes(e.parentGirdId))
|
||||
this.options?.map((item) => item.isChecked = this.selected.includes(item.id))
|
||||
let obj = {girdName: '可选范围', id: ''}
|
||||
this.selectList.push(obj)
|
||||
}
|
||||
},
|
||||
itemClick(row) {
|
||||
if (row.hasChildren) {
|
||||
let obj = {
|
||||
girdName: row.girdName,
|
||||
id: row.id,
|
||||
}
|
||||
this.selectList.push(obj)
|
||||
this.getGridsByGridMemberAndParent(row)
|
||||
}
|
||||
},
|
||||
getGridsByGridMemberAndParent(row) {
|
||||
let {id: parentGirdId} = row
|
||||
this.options = this.allData.filter(e => e.parentGirdId == parentGirdId)
|
||||
this.options?.map((item) => item.isChecked = this.selected.includes(item.id))
|
||||
},
|
||||
girdNameClick(row, index) {
|
||||
if (!index) { //第一级别
|
||||
this.selectList = []
|
||||
this.treeInit(true)
|
||||
} else {
|
||||
this.selectList.splice(index, 8)
|
||||
this.getGridsByGridMemberAndParent(row)
|
||||
}
|
||||
},
|
||||
girdClick(row, index) {
|
||||
if (this.options[index].isChecked) {//取消
|
||||
this.options[index].isChecked = false
|
||||
this.SelectGird = {}
|
||||
} else {
|
||||
this.options?.map((item) => {
|
||||
item.isChecked = false
|
||||
})
|
||||
this.options[index].isChecked = true
|
||||
this.SelectGird = row
|
||||
}
|
||||
this.$forceUpdate()
|
||||
},
|
||||
submit() {
|
||||
if (this.SelectGird.id != null) {
|
||||
if (!this.isApply) {
|
||||
uni.setStorageSync("lastSelectedGrid", this.SelectGird.parentGirdId)
|
||||
}
|
||||
uni.navigateBack({
|
||||
success: () => {
|
||||
uni.$emit("pagePicker:gird", this.SelectGird)
|
||||
}
|
||||
})
|
||||
} else {
|
||||
return this.$u.toast('请选择网格')
|
||||
}
|
||||
},
|
||||
cancel() {
|
||||
this.SelectGird = {}
|
||||
uni.navigateBack({
|
||||
success: () => {
|
||||
uni.$emit("pagePicker:gird", this.SelectGird)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss">
|
||||
.SelectGird {
|
||||
min-height: 100vh;
|
||||
background: #fff;
|
||||
padding-bottom: 140px;
|
||||
box-sizing: border-box;
|
||||
|
||||
.header-middle {
|
||||
.hint {
|
||||
padding: 28px 20px 28px 32px;
|
||||
line-height: 56px;
|
||||
box-shadow: 0px 1px 0px 0px #e4e5e6;
|
||||
font-size: 30px;
|
||||
font-weight: 500;
|
||||
word-break: break-all;
|
||||
}
|
||||
|
||||
.showTypes {
|
||||
.cards {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
height: 120px;
|
||||
line-height: 120px;
|
||||
// background: pink;
|
||||
padding: 0 0 0 32px;
|
||||
|
||||
.imges {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
// width: 200px;
|
||||
.imgselect {
|
||||
width: 48px;
|
||||
height: 48px;
|
||||
vertical-align: middle;
|
||||
}
|
||||
|
||||
.avatras {
|
||||
width: 74px;
|
||||
height: 74px;
|
||||
border-radius: 8px;
|
||||
margin-left: 36px;
|
||||
}
|
||||
}
|
||||
|
||||
img {
|
||||
width: 74px;
|
||||
height: 74px;
|
||||
border-radius: 8px;
|
||||
}
|
||||
|
||||
.rightes {
|
||||
display: flex;
|
||||
border-bottom: 1px solid #e4e5e6;
|
||||
padding: 0 16px;
|
||||
|
||||
.applicationNames {
|
||||
display: inline-block;
|
||||
font-size: 36px;
|
||||
font-weight: 500;
|
||||
color: #333333;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
white-space: nowrap;
|
||||
vertical-align: bottom;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.subBtn {
|
||||
position: fixed;
|
||||
bottom: 0;
|
||||
left: 0;
|
||||
width: 100%;
|
||||
height: 118px;
|
||||
background: #f4f8fb;
|
||||
justify-content: flex-end;
|
||||
|
||||
div {
|
||||
width: 192px;
|
||||
height: 80px;
|
||||
line-height: 80px;
|
||||
text-align: center;
|
||||
border: 2px solid #1365dd;
|
||||
background: #1365dd;
|
||||
border-radius: 4px;
|
||||
font-size: 32px;
|
||||
color: #fff;
|
||||
margin-right: 32px;
|
||||
|
||||
&.cancel {
|
||||
color: #333;
|
||||
background: #fff;
|
||||
border-color: #ddd;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
202
src/components/pages/selectResident.vue
Normal file
@@ -0,0 +1,202 @@
|
||||
<template>
|
||||
<div class="selectResident">
|
||||
<!-- <AiTopFixed> -->
|
||||
<div class="search-top">
|
||||
<u-search placeholder="搜索" v-model="name" :show-action="false" bg-color="#fff" search-icon-color="#E2E8F1"
|
||||
color="#666" height="72" @search="getSearchList" @clear="handerClear" @change="getList"></u-search>
|
||||
</div>
|
||||
<!-- </AiTopFixed> -->
|
||||
<div class="user-list">
|
||||
<template v-if="list.length>0">
|
||||
<div class="item" v-for="(item, index) in list" :key="index">
|
||||
<div class="select-img" @click="checkClick(index)">
|
||||
<img :src="item.isCheck ? checkIcon : cirIcon" alt="">
|
||||
</div>
|
||||
<div class="user-info">
|
||||
<img :src="item.photo" alt="" v-if="item.photo">
|
||||
<img src="./img/user-img.png" alt="" v-else>{{ item.name }}
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
<AiEmpty v-else/>
|
||||
</div>
|
||||
<div class="pad-b118"></div>
|
||||
<div class="footer">
|
||||
<div class="btn" @click="confirm">确定选择</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import {mapState} from 'vuex'
|
||||
|
||||
export default {
|
||||
name: "selectResident",
|
||||
appName: "人员选择器(居民档案)",
|
||||
data() {
|
||||
return {
|
||||
current: 1,
|
||||
name: '',
|
||||
list: [],
|
||||
cirIcon: require('./img/xz.png'),
|
||||
checkIcon: require('./img/xzh.png'),
|
||||
selected: [],
|
||||
isSingle: false, //是否单选
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
...mapState(['user']),
|
||||
},
|
||||
onLoad(query) {
|
||||
if (query.selected) {
|
||||
this.selected = query.selected?.split(",") || []
|
||||
}
|
||||
this.isSingle = query.single || false
|
||||
this.getList()
|
||||
},
|
||||
methods: {
|
||||
getList() {
|
||||
this.$instance.post(`/app/appresident/list`, null, {
|
||||
params: {
|
||||
current: this.current,
|
||||
size: 20,
|
||||
areaId: this.user.areaId,
|
||||
con: this.name
|
||||
}
|
||||
}).then(res => {
|
||||
if (res?.data) {
|
||||
res.data.records.forEach(e => {
|
||||
e.isCheck = this.selected.includes(e.idNumber)
|
||||
})
|
||||
if (this.current > 1 && this.current > res.data.pages) {
|
||||
return
|
||||
}
|
||||
this.list = this.current > 1 ? [...this.list, ...res.data.records] : res.data.records
|
||||
}
|
||||
})
|
||||
},
|
||||
checkClick(index) {
|
||||
if(this.isSingle) {
|
||||
this.list.map((item) => {
|
||||
item.isCheck = false
|
||||
})
|
||||
this.list[index].isCheck = true
|
||||
}else {
|
||||
this.list[index].isCheck = !this.list[index].isCheck
|
||||
}
|
||||
|
||||
},
|
||||
confirm() {
|
||||
let checkList = []
|
||||
this.list.map((item) => {
|
||||
if (item.isCheck) {
|
||||
checkList.push(item)
|
||||
}
|
||||
})
|
||||
if (!checkList.length) {
|
||||
return this.$u.toast('请先选择人员')
|
||||
} else {
|
||||
uni.navigateBack({
|
||||
success: () => {
|
||||
uni.$emit("pagePicker:resident", checkList)
|
||||
}
|
||||
})
|
||||
}
|
||||
},
|
||||
handerClear() {
|
||||
this.current = 1
|
||||
this.name = ''
|
||||
this.getList()
|
||||
}
|
||||
},
|
||||
onReachBottom() {
|
||||
this.current++
|
||||
this.getList()
|
||||
},
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.selectResident {
|
||||
::v-deep .AiTopFixed .u-search {
|
||||
margin-bottom: 0 !important;
|
||||
}
|
||||
|
||||
.pad-b118 {
|
||||
padding-bottom: 118px;
|
||||
}
|
||||
|
||||
.search-top {
|
||||
position: fixed;
|
||||
top: 0;
|
||||
left: 0;
|
||||
padding: 16px;
|
||||
width: 100%;
|
||||
box-sizing: border-box;
|
||||
background-color: #E4E5E6;
|
||||
z-index: 99;
|
||||
}
|
||||
|
||||
.user-list {
|
||||
background-color: #fff;
|
||||
padding-top: 100px;
|
||||
.item {
|
||||
.select-img {
|
||||
display: inline-block;
|
||||
|
||||
img {
|
||||
width: 48px;
|
||||
height: 48px;
|
||||
margin: 12px 36px 12px 30px;
|
||||
vertical-align: middle;
|
||||
}
|
||||
}
|
||||
|
||||
.user-info {
|
||||
display: inline-block;
|
||||
padding: 20px 0 20px 0;
|
||||
width: calc(100% - 114px);
|
||||
height: 100%;
|
||||
border-bottom: 1px solid #E4E5E6;
|
||||
font-size: 36px;
|
||||
font-family: PingFangSC-Medium, PingFang SC;
|
||||
font-weight: 500;
|
||||
color: #333;
|
||||
line-height: 74px;
|
||||
|
||||
img {
|
||||
width: 74px;
|
||||
height: 74px;
|
||||
border-radius: 8px;
|
||||
margin-right: 34px;
|
||||
vertical-align: bottom;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.footer {
|
||||
width: 100%;
|
||||
height: 118px;
|
||||
background: #F4F8FB;
|
||||
position: fixed;
|
||||
left: 0;
|
||||
bottom: 0;
|
||||
text-align: right;
|
||||
|
||||
.btn {
|
||||
display: inline-block;
|
||||
width: 192px;
|
||||
height: 80px;
|
||||
line-height: 80px;
|
||||
background: #1365DD;
|
||||
border-radius: 4px;
|
||||
text-align: center;
|
||||
font-size: 32px;
|
||||
font-family: PingFangSC-Regular, PingFang SC;
|
||||
color: #FFF;
|
||||
margin: 20px 34px 0 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
194
src/components/pages/selectResidentMultiple.vue
Normal file
@@ -0,0 +1,194 @@
|
||||
<template>
|
||||
<div class="selectResident">
|
||||
<!-- <AiTopFixed> -->
|
||||
<div class="search-top">
|
||||
<u-search placeholder="搜索" v-model="name" :show-action="false" bg-color="#fff" search-icon-color="#E2E8F1"
|
||||
color="#666" height="72" @search="getSearchList" @clear="handerClear" @change="getList"></u-search>
|
||||
</div>
|
||||
<!-- </AiTopFixed> -->
|
||||
<div class="user-list">
|
||||
<template v-if="list.length>0">
|
||||
<div class="item" v-for="(item, index) in list" :key="index">
|
||||
<div class="select-img" @click="checkClick(index)">
|
||||
<img :src="item.isCheck ? checkIcon : cirIcon" alt="">
|
||||
</div>
|
||||
<div class="user-info">
|
||||
<img :src="item.photo" alt="" v-if="item.photo">
|
||||
<img src="./img/user-img.png" alt="" v-else>{{ item.name }}
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
<AiEmpty v-else/>
|
||||
</div>
|
||||
<div class="pad-b118"></div>
|
||||
<div class="footer">
|
||||
<div class="btn" @click="confirm">确定选择</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import {mapState} from 'vuex'
|
||||
|
||||
export default {
|
||||
name: "selectResident",
|
||||
appName: "人员选择器(居民档案)",
|
||||
data() {
|
||||
return {
|
||||
current: 1,
|
||||
name: '',
|
||||
list: [],
|
||||
cirIcon: require('./img/xz.png'),
|
||||
checkIcon: require('./img/xzh.png'),
|
||||
selected: [],
|
||||
isSingle: false, //是否单选
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
...mapState(['user']),
|
||||
},
|
||||
onLoad(query) {
|
||||
if (query.selected) {
|
||||
this.selected = query.selected?.split(",") || []
|
||||
}
|
||||
this.isSingle = query.single || false
|
||||
this.getList()
|
||||
},
|
||||
methods: {
|
||||
getList() {
|
||||
this.$instance.post(`/app/appresident/list`, null, {
|
||||
params: {
|
||||
current: this.current,
|
||||
size: 20,
|
||||
areaId: this.user.areaId,
|
||||
con: this.name
|
||||
}
|
||||
}).then(res => {
|
||||
if (res?.data) {
|
||||
res.data.records.forEach(e => {
|
||||
e.isCheck = this.selected.includes(e.idNumber)
|
||||
})
|
||||
if (this.current > 1 && this.current > res.data.pages) {
|
||||
return
|
||||
}
|
||||
this.list = this.current > 1 ? [...this.list, ...res.data.records] : res.data.records
|
||||
}
|
||||
})
|
||||
},
|
||||
checkClick(index) {
|
||||
this.list[index].isCheck = !this.list[index].isCheck
|
||||
},
|
||||
confirm() {
|
||||
let checkList = []
|
||||
this.list.map((item) => {
|
||||
if (item.isCheck) {
|
||||
checkList.push(item)
|
||||
}
|
||||
})
|
||||
if (!checkList.length) {
|
||||
return this.$u.toast('请先选择人员')
|
||||
} else {
|
||||
uni.navigateBack({
|
||||
success: () => {
|
||||
uni.$emit("pagePicker:residentMultiple", checkList)
|
||||
}
|
||||
})
|
||||
}
|
||||
},
|
||||
handerClear() {
|
||||
this.current = 1
|
||||
this.name = ''
|
||||
this.getList()
|
||||
}
|
||||
},
|
||||
onReachBottom() {
|
||||
this.current++
|
||||
this.getList()
|
||||
},
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.selectResident {
|
||||
::v-deep .AiTopFixed .u-search {
|
||||
margin-bottom: 0 !important;
|
||||
}
|
||||
|
||||
.pad-b118 {
|
||||
padding-bottom: 118px;
|
||||
}
|
||||
|
||||
.search-top {
|
||||
position: fixed;
|
||||
top: 0;
|
||||
left: 0;
|
||||
padding: 16px;
|
||||
width: 100%;
|
||||
box-sizing: border-box;
|
||||
background-color: #E4E5E6;
|
||||
z-index: 99;
|
||||
}
|
||||
|
||||
.user-list {
|
||||
background-color: #fff;
|
||||
padding-top: 100px;
|
||||
.item {
|
||||
.select-img {
|
||||
display: inline-block;
|
||||
|
||||
img {
|
||||
width: 48px;
|
||||
height: 48px;
|
||||
margin: 12px 36px 12px 30px;
|
||||
vertical-align: middle;
|
||||
}
|
||||
}
|
||||
|
||||
.user-info {
|
||||
display: inline-block;
|
||||
padding: 20px 0 20px 0;
|
||||
width: calc(100% - 114px);
|
||||
height: 100%;
|
||||
border-bottom: 1px solid #E4E5E6;
|
||||
font-size: 36px;
|
||||
font-family: PingFangSC-Medium, PingFang SC;
|
||||
font-weight: 500;
|
||||
color: #333;
|
||||
line-height: 74px;
|
||||
|
||||
img {
|
||||
width: 74px;
|
||||
height: 74px;
|
||||
border-radius: 8px;
|
||||
margin-right: 34px;
|
||||
vertical-align: bottom;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.footer {
|
||||
width: 100%;
|
||||
height: 118px;
|
||||
background: #F4F8FB;
|
||||
position: fixed;
|
||||
left: 0;
|
||||
bottom: 0;
|
||||
text-align: right;
|
||||
|
||||
.btn {
|
||||
display: inline-block;
|
||||
width: 192px;
|
||||
height: 80px;
|
||||
line-height: 80px;
|
||||
background: #1365DD;
|
||||
border-radius: 4px;
|
||||
text-align: center;
|
||||
font-size: 32px;
|
||||
font-family: PingFangSC-Regular, PingFang SC;
|
||||
color: #FFF;
|
||||
margin: 20px 34px 0 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
208
src/components/pages/selectSysUser.vue
Normal file
@@ -0,0 +1,208 @@
|
||||
<template>
|
||||
<div class="selectResident">
|
||||
<div class="search-top">
|
||||
<u-search placeholder="搜索" v-model="name" :show-action="false" bg-color="#fff" search-icon-color="#E2E8F1"
|
||||
color="#666" height="72" @search="current=1,getList()" @clear="handerClear" @change="current=1,getList()"></u-search>
|
||||
</div>
|
||||
<div class="user-list">
|
||||
<template v-if="list.length>0">
|
||||
<div class="item" v-for="(item, index) in list" :key="index">
|
||||
<div class="select-img" @click="checkClick(index)">
|
||||
<img :src="item.isCheck ? checkIcon : cirIcon" alt="">
|
||||
</div>
|
||||
<div class="user-info">
|
||||
<img :src="item.photo" alt="" v-if="item.photo">
|
||||
<img src="./img/user-img.png" alt="" v-else>
|
||||
{{ item.name }}
|
||||
<span v-if="isShowPhone && item.mobile">({{item.mobile}})</span>
|
||||
<span v-if="isShowPhone && item.phone && !item.mobile">({{item.phone}})</span>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
<template v-else>
|
||||
<AiEmpty/>
|
||||
<div class="pad-b118"/>
|
||||
</template>
|
||||
</div>
|
||||
<div class="pad-b118"/>
|
||||
<div class="footer">
|
||||
<div class="btn" @click="confirm">确定选择</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import {mapState} from 'vuex'
|
||||
|
||||
export default {
|
||||
name: "selectResident",
|
||||
appName: "选择人员",
|
||||
data() {
|
||||
return {
|
||||
current: 1,
|
||||
total: 0,
|
||||
name: '',
|
||||
list: [],
|
||||
cirIcon: require('./img/xz.png'),
|
||||
checkIcon: require('./img/xzh.png'),
|
||||
selected: [],
|
||||
query: null,
|
||||
isSingle: false,
|
||||
nodeKey: 'idNumber',
|
||||
isRequire: 1,
|
||||
isShowPhone: false
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
...mapState(['user']),
|
||||
},
|
||||
onLoad(query) {
|
||||
this.query = query
|
||||
if (query.selected) {
|
||||
this.selected = query.selected?.split(",") || []
|
||||
}
|
||||
this.isSingle = query.single == 'false' ? false : true
|
||||
this.nodeKey = query.nodeKey || "idNumber"
|
||||
this.isRequire = query.isRequire || 1
|
||||
this.isShowPhone = query.isShowPhone || false
|
||||
this.getList()
|
||||
},
|
||||
onShow() {
|
||||
// document.title = this.nodeKey == 'openId' ? '选择居民' : '选择员工'
|
||||
},
|
||||
methods: {
|
||||
getList() {
|
||||
let {current, total, name: con} = this
|
||||
let url = this.query.axiosUrl ? this.query.axiosUrl : `/admin/user/userIntegralList`
|
||||
if ((!total && current == 1) || current <= total) {
|
||||
url = decodeURIComponent(url)
|
||||
this.$instance.post(url, null, {
|
||||
params: {current, size: 20, con}
|
||||
}).then(res => {
|
||||
if (res?.data) {
|
||||
this.total = res.data.pages || 0
|
||||
res.data.records.forEach(e => {
|
||||
e.isCheck = this.selected.includes(e[this.nodeKey])
|
||||
})
|
||||
this.list = [current == 1 ? [] : this.list, res.data.records || []].flat()
|
||||
}
|
||||
})
|
||||
}
|
||||
},
|
||||
checkClick(index) {
|
||||
if (this.isSingle) {
|
||||
this.list.map((e, i) => {
|
||||
e.isCheck = i == index;
|
||||
})
|
||||
} else this.list[index].isCheck = !this.list[index].isCheck
|
||||
|
||||
},
|
||||
confirm() {
|
||||
let checkList = []
|
||||
this.list.map((item) => {
|
||||
if (item.isCheck) {
|
||||
checkList.push(item)
|
||||
}
|
||||
})
|
||||
if (!checkList.length && this.isRequire == 1) {
|
||||
return this.$u.toast('请先选择人员')
|
||||
} else {
|
||||
uni.navigateBack({
|
||||
success: () => {
|
||||
uni.$emit("pagePicker:sysUser", checkList)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
},
|
||||
onReachBottom() {
|
||||
this.current++
|
||||
this.getList()
|
||||
},
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.selectResident {
|
||||
::v-deep .AiTopFixed .u-search {
|
||||
margin-bottom: 0 !important;
|
||||
}
|
||||
|
||||
.pad-b118 {
|
||||
padding-bottom: 118px;
|
||||
}
|
||||
|
||||
.search-top {
|
||||
position: fixed;
|
||||
top: 0;
|
||||
left: 0;
|
||||
padding: 16px;
|
||||
width: 100%;
|
||||
box-sizing: border-box;
|
||||
background-color: #E4E5E6;
|
||||
z-index: 99;
|
||||
}
|
||||
.user-list {
|
||||
padding-top: 100px;
|
||||
background-color: #fff;
|
||||
|
||||
.item {
|
||||
.select-img {
|
||||
display: inline-block;
|
||||
|
||||
img {
|
||||
width: 48px;
|
||||
height: 48px;
|
||||
margin: 12px 36px 12px 30px;
|
||||
vertical-align: middle;
|
||||
}
|
||||
}
|
||||
|
||||
.user-info {
|
||||
display: inline-block;
|
||||
padding: 20px 0 20px 0;
|
||||
width: calc(100% - 114px);
|
||||
height: 100%;
|
||||
border-bottom: 1px solid #E4E5E6;
|
||||
font-size: 36px;
|
||||
font-family: PingFangSC-Medium, PingFang SC;
|
||||
font-weight: 500;
|
||||
color: #333;
|
||||
line-height: 74px;
|
||||
|
||||
img {
|
||||
width: 74px;
|
||||
height: 74px;
|
||||
border-radius: 8px;
|
||||
margin-right: 34px;
|
||||
vertical-align: bottom;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.footer {
|
||||
width: 100%;
|
||||
height: 118px;
|
||||
background: #F4F8FB;
|
||||
position: fixed;
|
||||
left: 0;
|
||||
bottom: 0;
|
||||
text-align: right;
|
||||
|
||||
.btn {
|
||||
display: inline-block;
|
||||
width: 192px;
|
||||
height: 80px;
|
||||
line-height: 80px;
|
||||
background: #1365DD;
|
||||
border-radius: 4px;
|
||||
text-align: center;
|
||||
font-size: 32px;
|
||||
font-family: PingFangSC-Regular, PingFang SC;
|
||||
color: #FFF;
|
||||
margin: 20px 34px 0 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
62
src/components/pages/submitEvaluation.vue
Normal file
@@ -0,0 +1,62 @@
|
||||
<template>
|
||||
<section class="submitEvaluation">
|
||||
<AiGroup>
|
||||
<AiItem label="评价分数" top-label required>
|
||||
<u-rate v-model="form.score" :size="64" active-color="#F8B425" :min-count="1" inactive-icon="star-fill"/>
|
||||
</AiItem>
|
||||
</AiGroup>
|
||||
<u-gap height="24"/>
|
||||
<AiGroup>
|
||||
<AiItem label="评价详情" top-label required>
|
||||
<u-input type="textarea" v-model="form.content" placeholder="请简要描述..."/>
|
||||
</AiItem>
|
||||
</AiGroup>
|
||||
<u-gap height="24"/>
|
||||
<AiGroup>
|
||||
<AiItem label="附件" top-label>
|
||||
<AiUploader v-model="form.files" :limit="9" multiple/>
|
||||
</AiItem>
|
||||
</AiGroup>
|
||||
<div class="fixed-bottom">
|
||||
<div class="bottomBtn" @click="submit">提交</div>
|
||||
</div>
|
||||
</section>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
name: "submitEvaluation",
|
||||
appName: "提交评价",
|
||||
data() {
|
||||
return {
|
||||
form: {
|
||||
files: []
|
||||
}
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
submit() {
|
||||
if (!this.form.score) {
|
||||
return this.$u.toast("请选择评价分数!")
|
||||
}
|
||||
if (!this.form.content) {
|
||||
return this.$u.toast("请填写评价详情!")
|
||||
}
|
||||
this.$instance.post("/app/appbusinesscompletionevaluation/addOrUpdate", this.form).then(res => {
|
||||
if (res?.code == 0) {
|
||||
this.$u.toast("提交成功!")
|
||||
setTimeout(() => uni.navigateBack({}), 1500)
|
||||
}
|
||||
})
|
||||
}
|
||||
},
|
||||
onLoad(params) {
|
||||
this.form.bizId = params.bid
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.submitEvaluation {
|
||||
}
|
||||
</style>
|
||||
53
src/components/utils/PageBase.js
Normal file
@@ -0,0 +1,53 @@
|
||||
class PageBase {
|
||||
constructor(path, vue) {
|
||||
this.path = path
|
||||
this.name = path.replace(/.*[\\\/]([^\\\/]+)$/g, '$1')
|
||||
this.init(vue)
|
||||
}
|
||||
|
||||
init(vue) {
|
||||
if (/appName/.test(vue)) {
|
||||
let appName = vue.replace(/[\s\S]*(appName:.+),[\s\S]*/gm, '$1')
|
||||
this.label = appName.replace(/(appName:|["'])/g, '')?.trim()
|
||||
}
|
||||
if (/customNavigation/.test(vue)) {
|
||||
this.style = {
|
||||
navigationStyle: "custom",
|
||||
}
|
||||
if (/navigationBarTextStyle/.test(vue)) {
|
||||
this.style.navigationBarTextStyle = vue.replace(/[\s\S]*navigationBarTextStyle:([^,]+),[\s\S]*/gm, '$1').replace(/["']/g, '')?.trim()
|
||||
}
|
||||
//导航栏背景颜色(同状态栏背景色)
|
||||
if (/navigationBarBackgroundColor/.test(vue)) {
|
||||
this.style.navigationBarBackgroundColor = vue.replace(/[\s\S]*navigationBarBackgroundColor:([^,]+),[\s\S]*/gm, '$1').replace(/["']/g, '')?.trim()
|
||||
}
|
||||
if (/enablePullDownRefresh/.test(vue)) {
|
||||
this.style.enablePullDownRefresh = true
|
||||
}
|
||||
} else {
|
||||
this.style = {navigationBarTitleText: this.label}
|
||||
//是否开启下拉刷新
|
||||
if (/enablePullDownRefresh/.test(vue)) {
|
||||
this.style.enablePullDownRefresh = true
|
||||
}
|
||||
//导航栏标题颜色及状态栏前景颜色,仅支持 black/white
|
||||
if (/navigationBarTextStyle/.test(vue)) {
|
||||
this.style.navigationBarTextStyle = vue.replace(/[\s\S]*navigationBarTextStyle:([^,]+),[\s\S]*/gm, '$1').replace(/["']/g, '')?.trim()
|
||||
}
|
||||
//导航栏背景颜色(同状态栏背景色)
|
||||
if (/navigationBarBackgroundColor/.test(vue)) {
|
||||
this.style.navigationBarBackgroundColor = vue.replace(/[\s\S]*navigationBarBackgroundColor:([^,]+),[\s\S]*/gm, '$1').replace(/["']/g, '')?.trim()
|
||||
}
|
||||
// //下拉显示出来的窗口的背景色
|
||||
// if (/backgroundColor/.test(vue)) {
|
||||
// this.style.backgroundColor = vue.replace(/[\s\S]*(backgroundColor:.+),[\s\S]*/gm, '$1')
|
||||
// }
|
||||
}
|
||||
}
|
||||
|
||||
setLabel(name) {
|
||||
this.label = name
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = PageBase
|
||||
19
src/components/utils/coin.js
Normal file
@@ -0,0 +1,19 @@
|
||||
export default {
|
||||
cny(money) {
|
||||
if (money) {
|
||||
money.toLocaleString('zh-Hans-CN', {style: 'currency', currency: "CNY"})
|
||||
}
|
||||
return money
|
||||
},
|
||||
cn(money) {
|
||||
let num = parseFloat(money), cnMoney = '',
|
||||
units = '仟佰拾亿仟佰拾万仟佰拾元角分',
|
||||
cnNum = '零壹贰叁肆伍陆柒捌玖'
|
||||
num = num.toFixed(2).replace(/\./g, '')
|
||||
units = units.substring(units.length - num.length)
|
||||
Array.from(num).map((e, i) => {
|
||||
cnMoney += cnNum.charAt(e) + units.charAt(i)
|
||||
})
|
||||
return cnMoney.replace(/零角零分$/, '整').replace(/零[仟佰拾]/g, '零').replace(/零{2,}/g, '零').replace(/零([亿|万])/g, '$1').replace(/零+元/, '元').replace(/亿零{0,3}万/, '亿').replace(/^元/, "零元")
|
||||
}
|
||||
}
|
||||
56
src/components/utils/dict.js
Normal file
@@ -0,0 +1,56 @@
|
||||
export default {
|
||||
instance: null,
|
||||
init(instance) {
|
||||
this.instance = instance
|
||||
},
|
||||
dicts() {
|
||||
return uni.getStorageSync('dicts') || [];
|
||||
},
|
||||
load(...code) {
|
||||
return !!this.instance && this.instance.post('/admin/dictionary/queryValsByCodeList?codeList=' + code.join(','), null, {
|
||||
withoutToken: true
|
||||
}).then((res) => {
|
||||
if (res && res.data) {
|
||||
let cacheDicts = {},
|
||||
meta = {};
|
||||
this.dicts().map((e) => (cacheDicts[e.key] = e));
|
||||
res.data.map((e) => (meta[e.key] = e));
|
||||
let dicts = {...cacheDicts, ...meta};
|
||||
uni.setStorageSync('dicts', Object.values(dicts));
|
||||
}
|
||||
});
|
||||
},
|
||||
getDict(key) {
|
||||
if (this.dicts().length) {
|
||||
let dict = this.dicts().find((e) => e.key == key);
|
||||
return dict ? dict.values : [];
|
||||
} else return [];
|
||||
},
|
||||
getValue(key, label) {
|
||||
if (this.dicts().length) {
|
||||
let dict = this.dicts().find((e) => e.key == key);
|
||||
if (dict) {
|
||||
let item = dict.values.find((v) => v.dictName == label);
|
||||
return item ? item.dictValue : label;
|
||||
} else return label;
|
||||
} else return label;
|
||||
},
|
||||
getLabel(key, value) {
|
||||
if (this.dicts().length) {
|
||||
let dict = this.dicts().find((e) => e.key == key);
|
||||
if (dict) {
|
||||
let item = dict.values.find((v) => v.dictValue == value);
|
||||
return item ? item.dictName : value;
|
||||
} else return value ? value : '';
|
||||
} else return value ? value : '';
|
||||
},
|
||||
getColor(key, value) {
|
||||
if (this.dicts().length) {
|
||||
let dict = this.dicts().find((e) => e.key == key);
|
||||
if (dict) {
|
||||
let item = dict.values.find((v) => v.dictValue == value);
|
||||
return item ? item.dictColor : value;
|
||||
} else return value;
|
||||
} else return value;
|
||||
}
|
||||
}
|
||||
29
src/components/utils/http.js
Normal file
@@ -0,0 +1,29 @@
|
||||
import axios from 'axios'
|
||||
import adapter from 'axios-miniprogram-adapter'
|
||||
|
||||
const instance = axios.create({
|
||||
timeout: 600000,
|
||||
withCredentials: true,
|
||||
adapter
|
||||
})
|
||||
const getToken = () => {
|
||||
let vuex = uni.getStorageSync("vuex")
|
||||
return !!vuex ? JSON.parse(vuex).token : null
|
||||
}
|
||||
const source = axios.CancelToken.source();
|
||||
instance.interceptors.request.use(config => {
|
||||
if (config.withoutToken) {
|
||||
return config
|
||||
} else if (getToken()) {
|
||||
config.headers["Authorization"] = getToken()
|
||||
} else {
|
||||
config.cancelToken = source.token
|
||||
source.cancel("用户未验证,取消请求:" + config.url)
|
||||
}
|
||||
return config
|
||||
}, err => {
|
||||
console.error(err)
|
||||
return Promise.reject(err)
|
||||
})
|
||||
|
||||
export default instance
|
||||
36
src/components/utils/list.js
Normal file
@@ -0,0 +1,36 @@
|
||||
import http from "./http";
|
||||
|
||||
class List {
|
||||
constructor(action) {
|
||||
this.action = action
|
||||
this.current = 1
|
||||
this.total = 0
|
||||
this.list = []
|
||||
}
|
||||
|
||||
getData(params) {
|
||||
const {action} = this
|
||||
return http.post(action, null, {params})
|
||||
}
|
||||
|
||||
init(params) {
|
||||
this.getData({...params, current: 1}).then(res => {
|
||||
if (res?.data) {
|
||||
this.list = res.data.records
|
||||
this.total = res.data.total
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
loadMore(params) {
|
||||
if (this.list.length < this.total) {
|
||||
this.getData({...params, current: ++this.current}).then(res => {
|
||||
if (res?.data) {
|
||||
this.list = [...this.list, ...res.data.records]
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
export default List
|
||||
153
src/components/utils/modules.js
Normal file
@@ -0,0 +1,153 @@
|
||||
import http from "./http";
|
||||
import Vue from "vue";
|
||||
|
||||
/**
|
||||
* 用户登录信息
|
||||
*/
|
||||
export const user = {
|
||||
state: () => ({}),
|
||||
mutations: {
|
||||
setUser(state, user) {
|
||||
for (const key in user) {
|
||||
Vue.set(state, key, user[key])
|
||||
}
|
||||
},
|
||||
},
|
||||
actions: {
|
||||
getUserInfo({commit}, way = "std") {
|
||||
//获取企业微信后台账号信息
|
||||
//党员认证状态 partyStatusForWX:0、未认证 1、认证中 2、已认证
|
||||
const actions = {
|
||||
std: "/app/appwechatuser/check",
|
||||
qujing: "/app/appwechatuserqujing/check",
|
||||
admin: "/app/appwechatusertog/userinfo"
|
||||
}
|
||||
return http.post(actions[way], null, {
|
||||
params: {corpId: process.env.NODE_ENV == "development" ? "ww596787bb70f08288" : undefined},
|
||||
}).then(res => {
|
||||
if (res?.data) {
|
||||
commit('setUser', res.data)
|
||||
return Promise.all([])
|
||||
}
|
||||
})
|
||||
},
|
||||
getCode({dispatch}, count = 0) {
|
||||
if (count > 3) {
|
||||
return Promise.reject("无法获取code")
|
||||
} else return new Promise((resolve, reject) => {
|
||||
uni.login({
|
||||
success: res => {
|
||||
if (res?.code) {
|
||||
resolve(res.code);
|
||||
} else {
|
||||
reject(res);
|
||||
}
|
||||
},
|
||||
fail: err => {
|
||||
console.error(err)
|
||||
resolve(dispatch("getCode", ++count))
|
||||
}
|
||||
})
|
||||
})
|
||||
},
|
||||
getToken({commit}, params) {
|
||||
if (params?.code) {
|
||||
return http.post("/auth/wechat-con/token", params, {
|
||||
headers: {"Authorization": "Basic d2VjaGF0OndlY2hhdA=="},
|
||||
withoutToken: true
|
||||
}).then(res => {
|
||||
if (res?.access_token) {
|
||||
const token = [res?.token_type, res?.access_token].join(" ").trim()
|
||||
commit("setToken", token)
|
||||
return token
|
||||
} else {
|
||||
uni.showToast({title: res?.msg})
|
||||
return Promise.reject(res?.msg)
|
||||
}
|
||||
})
|
||||
} else return Promise.reject("缺少登录code")
|
||||
},
|
||||
getAdminToken({commit}, params) {
|
||||
const {corpId = process.env.NODE_ENV == "development" ? "ww596787bb70f08288" : undefined} = params
|
||||
if (params?.code) {
|
||||
return http.post("/auth/wechat-2g/token", params, {
|
||||
headers: {"Authorization": "Basic d2VjaGF0OndlY2hhdA=="},
|
||||
params: {corpId},
|
||||
withoutToken: true
|
||||
}).then(res => {
|
||||
if (res?.access_token) {
|
||||
const token = [res?.token_type, res?.access_token].join(" ").trim()
|
||||
commit("setToken", token)
|
||||
return token
|
||||
} else {
|
||||
uni.showToast({title: res?.msg})
|
||||
return Promise.reject(res?.msg)
|
||||
}
|
||||
})
|
||||
} else return Promise.reject("缺少登录code")
|
||||
},
|
||||
autoLogin({dispatch, commit, rootState}, params = {nickName: '微信用户'}) {
|
||||
const {loginWay = rootState.loginWay || "std", phoneCode} = params
|
||||
commit("setLoginWay", loginWay)
|
||||
if (loginWay == "admin") {
|
||||
return phoneCode ? dispatch("getCode", params).then(code => dispatch('getAdminToken', {...params, code})).then(() => dispatch('getUserInfo', loginWay)) : Promise.reject("缺少手机号授权")
|
||||
} else return dispatch("getCode").then(code => dispatch("getToken", {...params, code})).then(() => dispatch('getUserInfo', loginWay))
|
||||
},
|
||||
authCheck({state, dispatch, rootState}, {checkType, modulePath}) {
|
||||
//用于进入应用的权限判断
|
||||
//checkType 1、登录认证 2、居民认证 3、党员认证 4、丰都个人认证 5、网格员
|
||||
//判断是否需要校验认证信息
|
||||
let {user: userInfo, token} = rootState
|
||||
if (!checkType) {
|
||||
//如果需要校验认证信息,必定要先验证是否登录
|
||||
uni.navigateTo({url: modulePath});
|
||||
} else if (checkType == 1) {
|
||||
if (!token) {
|
||||
return dispatch('autoLogin').then(() => dispatch('authCheck', {checkType, modulePath}));
|
||||
}
|
||||
uni.navigateTo({url: modulePath});
|
||||
} else if (checkType == 2) {
|
||||
if (!token) {
|
||||
return dispatch('autoLogin').then(() => dispatch('authCheck', {checkType, modulePath}));
|
||||
}
|
||||
if (!(userInfo.residentId && userInfo.status == 2)) {
|
||||
return uni.navigateTo({url: '/mods/AppAuth/AppAuth'});
|
||||
}
|
||||
uni.navigateTo({url: modulePath});
|
||||
} else if (checkType == 3) {
|
||||
if (!token) {
|
||||
return dispatch('autoLogin').then(() => dispatch('authCheck', {checkType, modulePath}));
|
||||
}
|
||||
if (!userInfo?.partyId) {
|
||||
return uni.showToast({title: "您还不是党员,暂时无法使用该功能", icon: "none"});
|
||||
}
|
||||
uni.navigateTo({url: modulePath});
|
||||
} else if (checkType == 4) {
|
||||
if (!token) {
|
||||
return dispatch('autoLogin', {loginWay: 'qujing'}).then(() => dispatch('authCheck', {checkType, modulePath}));
|
||||
}
|
||||
if (!userInfo.areaId) {
|
||||
return uni.showModal({
|
||||
title: '温馨提示',
|
||||
content: '您只有完成信息认证后,才可进行相关操作。',
|
||||
confirmText: '去认证',
|
||||
success: (res) => {
|
||||
if (res.confirm) {
|
||||
uni.reLaunch({url: `/pages/AppMine/userInfo?isFromTabbar=1&path=/pages/AppHome/AppHome`})
|
||||
} else if (res.cancel) {
|
||||
// 停留
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
uni.navigateTo({url: modulePath});
|
||||
} else if (checkType == 5) {
|
||||
if (userInfo.girdInfos2G && userInfo.girdInfos2G.length) {
|
||||
uni.navigateTo({url: modulePath});
|
||||
}else {
|
||||
return uni.showToast({title: "您还不是网格员,暂时无法使用该功能", icon: "none"});
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
35
src/components/utils/moment.js
Normal file
@@ -0,0 +1,35 @@
|
||||
import moment from 'dayjs'
|
||||
import duration from 'dayjs/plugin/duration'
|
||||
import updateLocale from 'dayjs/plugin/updateLocale'
|
||||
import customParseFormat from 'dayjs/plugin/customParseFormat'
|
||||
import 'dayjs/locale/zh-cn'
|
||||
|
||||
moment.locale('zh-cn')
|
||||
moment.extend(updateLocale)
|
||||
moment.extend(customParseFormat)
|
||||
moment.extend(duration)
|
||||
moment.updateLocale('zh-cn', {
|
||||
weekdays: "星期日|星期一|星期二|星期三|星期四|星期五|星期六".split("|"),
|
||||
meridiem(hour) {
|
||||
let word = ""
|
||||
if (hour < 6) {
|
||||
word = "凌晨"
|
||||
} else if (hour < 9) {
|
||||
word = "早上"
|
||||
} else if (hour < 12) {
|
||||
word = "上午"
|
||||
} else if (hour < 14) {
|
||||
word = "中午"
|
||||
} else if (hour < 17) {
|
||||
word = "下午"
|
||||
} else if (hour < 19) {
|
||||
word = "傍晚"
|
||||
} else if (hour < 22) {
|
||||
word = "晚上"
|
||||
} else {
|
||||
word = "夜里"
|
||||
}
|
||||
return word;
|
||||
}
|
||||
})
|
||||
export default moment
|
||||
16
src/components/utils/regular.js
Normal file
@@ -0,0 +1,16 @@
|
||||
export default {
|
||||
phone: /^((0\d{2,3}-\d{7,8})|((13[0-9]|14[01456879]|15[0-35-9]|16[2567]|17[0-8]|18[0-9]|19[0-35-9])\d{8}))$/,
|
||||
password: /^(?=.*\d)(?=.*[a-zA-Z])(?=.*[~!@#$%^&*,.?_-])[\da-zA-Z~!@#$%^&*,.?_-]{8,16}$/,
|
||||
money: /^([1-9]\d*|0)(\.\d{1,2})?$/,
|
||||
area: {
|
||||
village: /^\d{9}[^0]0{0,2}$/,
|
||||
town: /^\d{6}[^0]0{0,2}000$/,
|
||||
country: /^\d{4}[^0]0?0{6}$/,
|
||||
city: /^\d{2}[^0]0?0{8}$/,
|
||||
province: /^[^0]0?0{10}$/,
|
||||
},
|
||||
zh: /^[\u4e00-\u9fa5]+$/,
|
||||
email: /^\w+([-+.]\w+)*@\w+([-.]\w+)*\.\w+([-.]\w+)*$/,
|
||||
ip: /((?:(?:25[0-5]|2[0-4]\\d|[01]?\\d?\\d)\\.){3}(?:25[0-5]|2[0-4]\\d|[01]?\\d?\\d))/,
|
||||
idNumber: /^[1-9]\d{5}(19\d{2}|20[0-2]\d)(0[1-9]|1[0-2])(0[1-9]|[1-2][0-9]|3[0-1])\d{3}([0-9xX])$/
|
||||
}
|
||||
353
src/components/utils/util.js
Normal file
@@ -0,0 +1,353 @@
|
||||
import $dayjs from './moment'
|
||||
import $dict from './dict'
|
||||
import $qs from 'query-string'
|
||||
import $coin from './coin'
|
||||
import $reg from "./regular"
|
||||
|
||||
const $toast = (obj) => {
|
||||
let params = {title: '', duration: 2000, icon: 'none'};
|
||||
if (typeof obj == 'string') {
|
||||
params.title = obj;
|
||||
} else {
|
||||
Object.assign(params, obj);
|
||||
}
|
||||
uni.showToast(params);
|
||||
};
|
||||
|
||||
const $loading = (title) => {
|
||||
uni.showLoading({
|
||||
title: title ? title : '加载中',
|
||||
mask: true
|
||||
});
|
||||
};
|
||||
|
||||
const $hideLoading = () => {
|
||||
uni.hideLoading();
|
||||
};
|
||||
|
||||
const $dialog = {
|
||||
alert: (params) => {
|
||||
return new Promise((resolve) => {
|
||||
uni.showModal({
|
||||
title: '温馨提示',
|
||||
showCancel: false,
|
||||
confirmColor: '#197DF0',
|
||||
confirmText: params.confirmButtonText ? params.confirmButtonText : '确定',
|
||||
...params,
|
||||
success: (res) => {
|
||||
if (res.confirm) {
|
||||
resolve();
|
||||
}
|
||||
}
|
||||
});
|
||||
});
|
||||
},
|
||||
|
||||
confirm: (params) => {
|
||||
return new Promise((resolve, reject) => {
|
||||
uni.showModal({
|
||||
title: '温馨提示',
|
||||
showCancel: true,
|
||||
confirmColor: '#197DF0',
|
||||
cancelText: params.cancelButtonText ? params.cancelButtonText : '取消',
|
||||
confirmText: params.confirmButtonText ? params.confirmButtonText : '确定',
|
||||
...params,
|
||||
success: (res) => {
|
||||
if (res.confirm) {
|
||||
resolve();
|
||||
} else if (res.cancel) {
|
||||
reject();
|
||||
}
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
const $linkTo = (url) => {
|
||||
uni.navigateTo({
|
||||
url
|
||||
});
|
||||
};
|
||||
|
||||
const $formatName = (name) => {
|
||||
if (name == undefined) {
|
||||
return;
|
||||
}
|
||||
return name.substr(name.length - 2, name.length > 2 ? name.length - 1 : name.length);
|
||||
};
|
||||
|
||||
const $previewImage = (list, index, urlName) => {
|
||||
uni.previewImage({
|
||||
current: list[index][urlName],
|
||||
urls: list.map((v) => v[urlName])
|
||||
});
|
||||
};
|
||||
|
||||
|
||||
const $getUserProfile = () => {
|
||||
return new Promise(function (resolve) {
|
||||
wx.getUserProfile({
|
||||
desc: '用于完善会员资料',
|
||||
lang: 'zh_CN',
|
||||
success: (data) => {
|
||||
resolve(data);
|
||||
},
|
||||
fail: (err) => {
|
||||
console.log(err);
|
||||
}
|
||||
});
|
||||
});
|
||||
};
|
||||
/**
|
||||
* 身份证工具包
|
||||
*/
|
||||
const idCardNoUtil = {
|
||||
/*省,直辖市代码表*/
|
||||
provinceAndCitys: {
|
||||
11: "北京",
|
||||
12: "天津",
|
||||
13: "河北",
|
||||
14: "山西",
|
||||
15: "内蒙古",
|
||||
21: "辽宁",
|
||||
22: "吉林",
|
||||
23: "黑龙江",
|
||||
31: "上海",
|
||||
32: "江苏",
|
||||
33: "浙江",
|
||||
34: "安徽",
|
||||
35: "福建",
|
||||
36: "江西",
|
||||
37: "山东",
|
||||
41: "河南",
|
||||
42: "湖北",
|
||||
43: "湖南",
|
||||
44: "广东",
|
||||
45: "广西",
|
||||
46: "海南",
|
||||
50: "重庆",
|
||||
51: "四川",
|
||||
52: "贵州",
|
||||
53: "云南",
|
||||
54: "西藏",
|
||||
61: "陕西",
|
||||
62: "甘肃",
|
||||
63: "青海",
|
||||
64: "宁夏",
|
||||
65: "新疆",
|
||||
71: "台湾",
|
||||
81: "香港",
|
||||
82: "澳门",
|
||||
91: "国外"
|
||||
},
|
||||
|
||||
/*每位加权因子*/
|
||||
powers: ["7", "9", "10", "5", "8", "4", "2", "1", "6", "3", "7", "9", "10", "5", "8", "4", "2"],
|
||||
|
||||
/*第18位校检码*/
|
||||
parityBit: ["1", "0", "X", "9", "8", "7", "6", "5", "4", "3", "2"],
|
||||
|
||||
/*性别*/
|
||||
genders: {male: "男", female: "女"},
|
||||
|
||||
/*校验地址码*/
|
||||
checkAddressCode: function (addressCode) {
|
||||
const check = /^[1-9]\d{5}$/.test(addressCode);
|
||||
if (!check) return false;
|
||||
return !!idCardNoUtil.provinceAndCitys[parseInt(addressCode.substring(0, 2))];
|
||||
},
|
||||
|
||||
/*校验日期码*/
|
||||
checkBirthDayCode: function (birDayCode) {
|
||||
const check = /^[1-9]\d{3}((0[1-9])|(1[0-2]))((0[1-9])|([1-2][0-9])|(3[0-1]))$/.test(birDayCode);
|
||||
if (!check) return false;
|
||||
const yyyy = parseInt(birDayCode.substring(0, 4), 10);
|
||||
const mm = parseInt(birDayCode.substring(4, 6), 10);
|
||||
const dd = parseInt(birDayCode.substring(6), 10);
|
||||
const xdata = new Date(yyyy, mm - 1, dd);
|
||||
if (xdata > new Date()) {
|
||||
return false; //生日不能大于当前日期
|
||||
} else return (xdata.getFullYear() == yyyy) && (xdata.getMonth() == mm - 1) && (xdata.getDate() == dd);
|
||||
},
|
||||
|
||||
/*计算校检码*/
|
||||
getParityBit: function (idCardNo) {
|
||||
const id17 = idCardNo.substring(0, 17);
|
||||
/*加权 */
|
||||
let power = 0;
|
||||
for (let i = 0; i < 17; i++) {
|
||||
power += parseInt(id17.charAt(i), 10) * parseInt(idCardNoUtil.powers[i]);
|
||||
}
|
||||
/*取模*/
|
||||
const mod = power % 11;
|
||||
return idCardNoUtil.parityBit[mod];
|
||||
},
|
||||
|
||||
/*验证校检码*/
|
||||
checkParityBit: function (idCardNo) {
|
||||
const parityBit = idCardNo.charAt(17).toUpperCase();
|
||||
return idCardNoUtil.getParityBit(idCardNo) == parityBit;
|
||||
},
|
||||
|
||||
/*校验15位或18位的身份证号码*/
|
||||
checkIdCardNo: function (idCardNo) {
|
||||
//15位和18位身份证号码的基本校验
|
||||
const check = /^\d{15}|(\d{17}(\d|x|X))$/.test(idCardNo);
|
||||
if (!check) return false;
|
||||
//判断长度为15位或18位
|
||||
if (idCardNo.length == 15) {
|
||||
return idCardNoUtil.check15IdCardNo(idCardNo);
|
||||
} else if (idCardNo.length == 18) {
|
||||
return idCardNoUtil.check18IdCardNo(idCardNo);
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
},
|
||||
|
||||
//校验15位的身份证号码
|
||||
check15IdCardNo: function (idCardNo) {
|
||||
//15位身份证号码的基本校验
|
||||
let check = /^[1-9]\d{7}((0[1-9])|(1[0-2]))((0[1-9])|([1-2][0-9])|(3[0-1]))\d{3}$/.test(idCardNo);
|
||||
if (!check) return false;
|
||||
//校验地址码
|
||||
const addressCode = idCardNo.substring(0, 6);
|
||||
check = idCardNoUtil.checkAddressCode(addressCode);
|
||||
if (!check) return false;
|
||||
const birDayCode = '19' + idCardNo.substring(6, 12);
|
||||
//校验日期码
|
||||
return idCardNoUtil.checkBirthDayCode(birDayCode);
|
||||
},
|
||||
|
||||
//校验18位的身份证号码
|
||||
check18IdCardNo: function (idCardNo) {
|
||||
//18位身份证号码的基本格式校验
|
||||
let check = /^[1-9]\d{5}[1-9]\d{3}((0[1-9])|(1[0-2]))((0[1-9])|([1-2][0-9])|(3[0-1]))\d{3}(\d|x|X)$/.test(idCardNo);
|
||||
if (!check) return false;
|
||||
//校验地址码
|
||||
const addressCode = idCardNo.substring(0, 6);
|
||||
check = idCardNoUtil.checkAddressCode(addressCode);
|
||||
if (!check) return false;
|
||||
//校验日期码
|
||||
const birDayCode = idCardNo.substring(6, 14);
|
||||
check = idCardNoUtil.checkBirthDayCode(birDayCode);
|
||||
if (!check) return false;
|
||||
//验证校检码
|
||||
return idCardNoUtil.checkParityBit(idCardNo);
|
||||
},
|
||||
|
||||
formateDateCN: function (day) {
|
||||
const yyyy = day.substring(0, 4);
|
||||
const mm = day.substring(4, 6);
|
||||
const dd = day.substring(6);
|
||||
return yyyy + '-' + mm + '-' + dd;
|
||||
},
|
||||
|
||||
//获取信息
|
||||
getIdCardInfo: function (idCardNo) {
|
||||
let aday;
|
||||
let idCardInfo = {
|
||||
gender: "", //性别
|
||||
birthday: "", // 出生日期(yyyy-mm-dd)
|
||||
sex: ""//系统性别码
|
||||
};
|
||||
if (idCardNo.length == 15) {
|
||||
aday = '19' + idCardNo.substring(6, 12);
|
||||
idCardInfo.birthday = idCardNoUtil.formateDateCN(aday);
|
||||
if (parseInt(idCardNo.charAt(14)) % 2 == 0) {
|
||||
idCardInfo.gender = idCardNoUtil.genders.female;
|
||||
} else {
|
||||
idCardInfo.gender = idCardNoUtil.genders.male;
|
||||
}
|
||||
} else if (idCardNo.length == 18) {
|
||||
aday = idCardNo.substring(6, 14);
|
||||
idCardInfo.birthday = idCardNoUtil.formateDateCN(aday);
|
||||
if (parseInt(idCardNo.charAt(16)) % 2 == 0) {
|
||||
idCardInfo.gender = idCardNoUtil.genders.female;
|
||||
} else {
|
||||
idCardInfo.gender = idCardNoUtil.genders.male;
|
||||
}
|
||||
idCardInfo.sex = "" + Number(idCardNo.substring(16, 17)) % 2
|
||||
}
|
||||
return idCardInfo;
|
||||
},
|
||||
|
||||
/*18位转15位*/
|
||||
getId15: function (idCardNo) {
|
||||
if (idCardNo.length == 15) {
|
||||
return idCardNo;
|
||||
} else if (idCardNo.length == 18) {
|
||||
return idCardNo.substring(0, 6) + idCardNo.substring(8, 17);
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
},
|
||||
|
||||
/*15位转18位*/
|
||||
getId18: function (idCardNo) {
|
||||
if (idCardNo.length == 15) {
|
||||
const id17 = idCardNo.substring(0, 6) + '19' + idCardNo.substring(6);
|
||||
const parityBit = idCardNoUtil.getParityBit(id17);
|
||||
return id17 + parityBit;
|
||||
} else if (idCardNo.length == 18) {
|
||||
return idCardNo;
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
},
|
||||
hideId(code) {
|
||||
return code && code.replace(/^(\d{10})\d{4}(.{4}$)/g, `$1${Array(5).join('*')}$2`) || "-"
|
||||
}
|
||||
}
|
||||
/**
|
||||
* 获取年龄
|
||||
* @param code
|
||||
*/
|
||||
const $calcAge = (code) => {
|
||||
let birthday
|
||||
if (typeof code == 'string' && code.length == 18) {
|
||||
birthday = $dayjs(code.substring(6, 14), 'YYYYMMDD')
|
||||
} else if (typeof code == 'object') {
|
||||
birthday = code
|
||||
}
|
||||
return Math.ceil($dayjs.duration($dayjs().unix() - $dayjs(birthday).unix(), 's').asYears())
|
||||
}
|
||||
/**
|
||||
* 获取code
|
||||
* @returns {Promise<unknown>}
|
||||
*/
|
||||
const $getLoginCode = () => {
|
||||
return new Promise(function (resolve, reject) {
|
||||
uni.login({
|
||||
success: function (res) {
|
||||
if (res.code) {
|
||||
resolve(res);
|
||||
} else {
|
||||
reject(res);
|
||||
}
|
||||
},
|
||||
fail: function () {
|
||||
reject(false);
|
||||
}
|
||||
});
|
||||
});
|
||||
};
|
||||
|
||||
export default {
|
||||
$toast,
|
||||
$loading,
|
||||
$hideLoading,
|
||||
$dialog,
|
||||
$linkTo,
|
||||
$formatName,
|
||||
$previewImage,
|
||||
$getUserProfile,
|
||||
$idCardNoUtil: idCardNoUtil,
|
||||
$calcAge,
|
||||
$dayjs,
|
||||
$dict,
|
||||
$getLoginCode,
|
||||
$qs,
|
||||
$coin,
|
||||
$reg
|
||||
};
|
||||
24
src/main.js
Normal file
@@ -0,0 +1,24 @@
|
||||
import Vue from 'vue'
|
||||
import App from './App'
|
||||
import store from './store'
|
||||
import axios from "./utils/axios"
|
||||
import utils from 'dvcp-wui/utils/util'
|
||||
import config from './utils/config'
|
||||
import vui from 'uview-ui'
|
||||
import 'uview-ui/theme.scss'
|
||||
|
||||
Vue.use(vui)
|
||||
Vue.config.productionTip = false
|
||||
Vue.prototype.$instance = axios
|
||||
Vue.prototype.$areaId = config.areaId;
|
||||
Vue.prototype.$areaName = config.areaName;
|
||||
Vue.prototype.$cdn = 'https://cdn.cunwuyun.cn/'
|
||||
App.mpType = 'app'
|
||||
Object.keys(utils).map(e => Vue.prototype[e] = utils[e])
|
||||
utils.$dict.init(axios)
|
||||
|
||||
const app = new Vue({
|
||||
store,
|
||||
...App
|
||||
})
|
||||
app.$mount()
|
||||
42
src/manifest.json
Normal file
@@ -0,0 +1,42 @@
|
||||
{
|
||||
"name": "dvcp-wechatApps",
|
||||
"description": "数字乡村小程序应用库",
|
||||
"versionName": "1.0.0",
|
||||
"versionCode": "100",
|
||||
"transformPx": true,
|
||||
"mp-weixin": {
|
||||
"appid": "wx576d5e829b9e7d49",
|
||||
"setting": {
|
||||
"urlCheck": false
|
||||
},
|
||||
"optimization": {
|
||||
"subPackages": true
|
||||
},
|
||||
"usingComponents": true,
|
||||
"permission": {
|
||||
"scope.userLocation": {
|
||||
"desc": "你的位置信息将用于当前事件发生地点"
|
||||
},
|
||||
"scope.record": {
|
||||
"desc": "你的录音功能将使用"
|
||||
},
|
||||
"scope.phoneNumber": {
|
||||
"desc": "你的手机号码将用于当前身份信息验证"
|
||||
}
|
||||
},
|
||||
"plugins": {
|
||||
"materialPlugin": {
|
||||
"version": "1.0.5",
|
||||
"provider": "wx4d2deeab3aed6e5a"
|
||||
},
|
||||
"player": {
|
||||
"version": "2.1.15",
|
||||
"provider": "wxa75efa648b60994b"
|
||||
}
|
||||
},
|
||||
"requiredPrivateInfos": [
|
||||
"getLocation",
|
||||
"chooseLocation"
|
||||
]
|
||||
}
|
||||
}
|
||||
175
src/mods/conv/AppAddressBook/AppAddressBook.vue
Normal file
@@ -0,0 +1,175 @@
|
||||
<template>
|
||||
<div class="wrapper">
|
||||
<div class="searAreName">
|
||||
<AiAreaPicker ref="area" class="ai-area" v-model="areaId" :name.sync="areaName" :areaId="$areaId" @input="areaSelect" >
|
||||
<div class="ai-area__wrapper">
|
||||
<span class="label" v-if="areaName">{{ areaName }}</span>
|
||||
<span v-else>请选择</span>
|
||||
<u-icon name="arrow-down" color="#666" size="24" style="margin-left: 4px"></u-icon>
|
||||
</div>
|
||||
</AiAreaPicker>
|
||||
<!-- <span v-else>{{ areaName }}</span> -->
|
||||
|
||||
<u-search v-model="name" ref="searchObj" placeholder="请输入名称/类型/电话" :show-action="false" clearabled bg-color="#F5F5F5" search-icon-color="#ccc" placeholder-color="#666" @search="handerSearch" @clear=";(index = []), (name = ''), getList()" style="width: 70%" />
|
||||
</div>
|
||||
|
||||
<!-- <AiTopFixed>
|
||||
<div class="searchObj">
|
||||
<u-search v-model="name" ref="searchObj" placeholder="请输入姓名或电话" :show-action="false" clearabled bg-color="#F5F7F9" search-icon-color="#6AA8F8" placeholder-color="#D0D4D4" @search="handerSearch" @clear=";(index = []), (name = ''), getList()" />
|
||||
</div>
|
||||
</AiTopFixed> -->
|
||||
|
||||
<template v-if="list.length">
|
||||
<u-index-list :scrollTop="scrollTop" :index-list="indexList">
|
||||
<div v-for="(letter, index) in indexList" :key="index">
|
||||
<u-index-anchor :index="letter" />
|
||||
<div class="item" hover-class="bg-hover" @click="phone(item)" v-for="(item, index) in list.filter((e) => e.nameInitials == letter)" :key="index">
|
||||
<label>{{ item.name }}</label>
|
||||
<div class="info">
|
||||
{{ item.type }}<span>{{ item.phone }}</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</u-index-list>
|
||||
</template>
|
||||
|
||||
<AiEmpty v-else></AiEmpty>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { mapState } from 'vuex'
|
||||
|
||||
export default {
|
||||
name: 'AppAddressBook',
|
||||
appName: '便民通讯录',
|
||||
data() {
|
||||
return {
|
||||
scrollTop: 0,
|
||||
indexList: [],
|
||||
list: [],
|
||||
userInfo: {},
|
||||
areaId: '',
|
||||
$areaId: '',
|
||||
areaName: '',
|
||||
name: '',
|
||||
}
|
||||
},
|
||||
onLoad() {
|
||||
this.userInfo = uni.getStorageSync('userInfo')
|
||||
this.areaId = this.$areaId
|
||||
this.areaName = this.$areaName
|
||||
this.getList()
|
||||
},
|
||||
|
||||
computed: {
|
||||
...mapState(['user']),
|
||||
},
|
||||
watch: {},
|
||||
methods: {
|
||||
phone({ phone: phoneNumber }) {
|
||||
uni.makePhoneCall({ phoneNumber })
|
||||
},
|
||||
getList() {
|
||||
this.$instance
|
||||
.post('/app/appconvenientaddressbook/list', null, {
|
||||
params: {
|
||||
isPublic: 1,
|
||||
resource: 'portal',
|
||||
areaId: this.areaId,
|
||||
size: 999,
|
||||
name: this.name,
|
||||
},
|
||||
})
|
||||
.then((res) => {
|
||||
if (res?.data) {
|
||||
this.indexList = [...new Set(res.data.records.map((e) => e.nameInitials))]
|
||||
this.list = res.data.records
|
||||
}
|
||||
})
|
||||
},
|
||||
areaSelect(v) {
|
||||
if(this.user.status == 2 ) {
|
||||
this.areaId = v
|
||||
this.isMore = false
|
||||
this.current = 0
|
||||
this.list = []
|
||||
} else {
|
||||
return false
|
||||
}
|
||||
this.$nextTick(() => {
|
||||
this.getList()
|
||||
})
|
||||
},
|
||||
|
||||
handerSearch(e) {
|
||||
this.name = e
|
||||
this.getList()
|
||||
},
|
||||
},
|
||||
onPageScroll(e) {
|
||||
this.scrollTop = e.scrollTop
|
||||
},
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.wrapper {
|
||||
.searAreName {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
padding: 24px 32px;
|
||||
background: #fff;
|
||||
}
|
||||
|
||||
::v-deep .AiTopFixed {
|
||||
width: 100%;
|
||||
.placeholder {
|
||||
opacity: 1;
|
||||
visibility: inherit;
|
||||
.content {
|
||||
padding: 0 !important;
|
||||
}
|
||||
}
|
||||
.fixed {
|
||||
width: 0;
|
||||
margin: 0 !important;
|
||||
.content {
|
||||
padding: 0 !important;
|
||||
}
|
||||
}
|
||||
}
|
||||
.searchObj {
|
||||
padding: 24px 32px;
|
||||
background: #fff;
|
||||
}
|
||||
}
|
||||
|
||||
.item {
|
||||
box-sizing: border-box;
|
||||
padding: 32px 48px;
|
||||
background: #ffffff;
|
||||
box-shadow: 0 0 8px 0 rgba(0, 0, 0, 0.02);
|
||||
|
||||
& > label {
|
||||
font-size: 32px;
|
||||
font-weight: 600;
|
||||
color: #333333;
|
||||
line-height: 44px;
|
||||
}
|
||||
|
||||
.info {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
font-size: 26px;
|
||||
color: #999999;
|
||||
margin-top: 8px;
|
||||
|
||||
& > span {
|
||||
color: #333333;
|
||||
margin-left: 16px;
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
664
src/mods/conv/AppEnteringVillage/AppEnteringVillage.vue
Normal file
@@ -0,0 +1,664 @@
|
||||
<template>
|
||||
<div class="wrapper">
|
||||
<div class="header" :class="[isFixed ? 'header-active' : '']">
|
||||
<div class="status-bar" :style="{height: statusBarHeight + 'px'}"></div>
|
||||
<div class="nav-bar">
|
||||
<h2>进村</h2>
|
||||
</div>
|
||||
</div>
|
||||
<header>
|
||||
<image src="https://cdn.sinoecare.com/i/2024/07/23/669f246434b23.png"/>
|
||||
<div>
|
||||
<AiAreaPicker :selectRoot="false" ref="area" :value="areaId" :name.sync="areaName" :areaId="$areaId"
|
||||
@input="areaSelect">
|
||||
<div class="ai-area__wrapper">
|
||||
<span class="label" v-if="areaName">{{ areaName }}</span>
|
||||
<span v-else>请选择</span>
|
||||
<image src="/static/img/area-bottom.png"/>
|
||||
</div>
|
||||
</AiAreaPicker>
|
||||
<div class="welcome">欢迎进入{{ areaName }}</div>
|
||||
<div class="tag" v-if="user.homeArea === areaId">我的家乡</div>
|
||||
<div class="tag1" @click="updateUserInfo" v-if="!user.homeArea && token">设为家乡</div>
|
||||
</div>
|
||||
</header>
|
||||
<div class="card">
|
||||
<div class="card-item" hover-class="text-hover" @click="$linkTo('/mods/AppVillagerInfo/AppVillagerInfo?type=0')">
|
||||
<image src="/static/img/bcjj.png"/>
|
||||
</div>
|
||||
<div class="card-item" hover-class="text-hover" @click="$linkTo('/mods/AppVillagerInfo/AppVillagerInfo?type=4')">
|
||||
<image src="/static/img/cgmy.png"/>
|
||||
</div>
|
||||
<div class="card-item" hover-class="text-hover"
|
||||
@click="linkTo('/mods/AppCreditPoints/AppIntegralRanking', 'idNumber')">
|
||||
<image src="/static/img/jfph.png"/>
|
||||
</div>
|
||||
<div class="card-item" hover-class="text-hover"
|
||||
@click="linkTo('/mods/AppVillagerDiscussion/AppVillagerDiscussion', 'idNumber')">
|
||||
<image src="/static/img/cmys.png"/>
|
||||
</div>
|
||||
</div>
|
||||
<div class="banner" @click="linkTo('/mods/AppCreditPoints/AppCpSupermarket', 'idNumber')">
|
||||
<image src="/static/img/jf-banner.png" class="banner"/>
|
||||
</div>
|
||||
<tempalte v-if="publicList.length">
|
||||
<div class="title-wrap">
|
||||
<span class="title">三务公开</span>
|
||||
<div class="right" hover-class="text-hover"
|
||||
@click="$linkTo(`/mods/AppContent/AppContent?names=三务公开&areaId=${areaId}`)">
|
||||
<span class="title-more">更多专题</span>
|
||||
<u-icon name="arrow-right" size="28" color="#999999"></u-icon>
|
||||
</div>
|
||||
</div>
|
||||
<div class="list-news">
|
||||
<div class="news-wrap" v-for="(item,index) in publicList" :key="index"
|
||||
@click="$linkTo('/mods/AppContent/contentDetail?id='+ item.id)">
|
||||
<div class="news-title">{{ item.title }}</div>
|
||||
<div class="news-bottom">
|
||||
<div class="tag">{{ item.categoryName }}</div>
|
||||
<div class="date">{{ item.createTime ? item.createTime.split(' ')[0] : '' }}</div>
|
||||
<div class="view">
|
||||
<em>{{ item.viewCount }}</em>
|
||||
人看过
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</tempalte>
|
||||
<div class="title-wrap" v-if="activityList.length">
|
||||
<span class="title">居民活动</span>
|
||||
<div class="right">
|
||||
<span class="title-more" @click="$linkTo('/mods/AppVillageActivity/AppVillageActivity')">更多活动</span>
|
||||
<u-icon name="arrow-right" size="28" color="#999999"></u-icon>
|
||||
</div>
|
||||
</div>
|
||||
<scroll-view :scroll-x="true" style="width: 100%" class="scroll-wrap" v-if="activityList.length">
|
||||
<div
|
||||
class="scroll-card"
|
||||
@click="$linkTo('/mods/AppVillageActivity/ActivityDetail?id=' + item.id)"
|
||||
hover-class="text-hover"
|
||||
v-for="(item, index) in activityList"
|
||||
:key="index">
|
||||
<image :src="item.url" mode="aspectFill"/>
|
||||
<div class="text">
|
||||
<span>{{ item.title }}</span>
|
||||
</div>
|
||||
</div>
|
||||
<AiEmpty v-if="!activityList.length"></AiEmpty>
|
||||
</scroll-view>
|
||||
<div class="title-wrap">
|
||||
<span class="title">乡村相册</span>
|
||||
</div>
|
||||
<div class="album-list">
|
||||
<div
|
||||
class="album"
|
||||
v-for="(item, index) in albumList"
|
||||
hover-class="text-hover"
|
||||
:key="index"
|
||||
@click="$linkTo('/mods/AppPhotoAlbum/AppPhotoAlbum?type=' + item.type + '&name=' + item.name + '&url=' + item.coverImg)">
|
||||
<image :src="item.coverImg"/>
|
||||
<div class="total">共{{ item.total }}张</div>
|
||||
<div class="desc">{{ item.name }}</div>
|
||||
</div>
|
||||
<AiEmpty style="width: 100%" v-if="!albumList.length"></AiEmpty>
|
||||
</div>
|
||||
<AiLogin ref="login"/>
|
||||
</div>
|
||||
</template>
|
||||
<script>
|
||||
import {mapActions, mapState} from 'vuex'
|
||||
|
||||
export default {
|
||||
name: "AppEnteringVillage",
|
||||
appName: "进村",
|
||||
customNavigation: true,
|
||||
data() {
|
||||
return {
|
||||
isFixed: false,
|
||||
statusBarHeight: 20,
|
||||
top: 0,
|
||||
areaName: '',
|
||||
areaId: '',
|
||||
$areaId: '',
|
||||
albumList: [],
|
||||
activityList: [],
|
||||
publicList: [],
|
||||
moduleId: "",
|
||||
isInit: false
|
||||
}
|
||||
},
|
||||
|
||||
onLoad() {
|
||||
this.areaId = this.$mp.query.areaId || this.$areaId
|
||||
this.areaName = this.$mp.query.areaName || this.$areaName
|
||||
this.statusBarHeight = uni.getSystemInfoSync().statusBarHeight
|
||||
this.autoLogin()
|
||||
|
||||
this.$nextTick(() => {
|
||||
this.getAlbumList()
|
||||
this.getActiveList()
|
||||
this.getName()
|
||||
})
|
||||
|
||||
uni.$on('update', () => {
|
||||
this.getAlbumList()
|
||||
})
|
||||
},
|
||||
|
||||
computed: {
|
||||
...mapState(['user', 'token'])
|
||||
},
|
||||
|
||||
onShow() {
|
||||
this.$nextTick(() => {
|
||||
this.token && this.getUserInfo()
|
||||
})
|
||||
|
||||
if (this.user.homeArea) {
|
||||
if (!this.isInit) {
|
||||
this.areaId = this.user.homeArea
|
||||
this.areaName = this.user.homeName
|
||||
uni.setStorageSync('areaId', this.user.homeArea)
|
||||
uni.setStorageSync('areaName', this.user.homeName)
|
||||
this.isInit = true
|
||||
}
|
||||
} else if (!this.isInit && !this.user.homeArea) {
|
||||
setTimeout(() => {
|
||||
this.$dialog.alert({
|
||||
content: '请选择您的家乡'
|
||||
}).then(() => {
|
||||
this.$refs.area?.handleJump()
|
||||
this.isInit = true
|
||||
})
|
||||
}, 600)
|
||||
}
|
||||
},
|
||||
|
||||
methods: {
|
||||
...mapActions(['autoLogin', 'getUserInfo']),
|
||||
getName() {
|
||||
this.$instance.post("/app/appcontentmoduleinfo/listByNames", null, {
|
||||
params: {names: "三务公开"}
|
||||
}).then(res => {
|
||||
if (res.data && res.data.length) {
|
||||
this.moduleId = res.data[0]["id"];
|
||||
this.getPublicList();
|
||||
}
|
||||
})
|
||||
},
|
||||
|
||||
updateUserInfo() {
|
||||
if (this.areaId.endsWith('000')) {
|
||||
this.$dialog.alert({
|
||||
content: '请选择村'
|
||||
}).then(() => {
|
||||
})
|
||||
|
||||
return false
|
||||
}
|
||||
|
||||
this.$instance.post("/app/appwechatuser/updateById", {
|
||||
id: this.user.id,
|
||||
homeArea: this.areaId,
|
||||
homeName: this.areaName
|
||||
}).then(res => {
|
||||
if (res.code === 0) {
|
||||
this.getUserInfo()
|
||||
}
|
||||
})
|
||||
},
|
||||
|
||||
getPublicList() {
|
||||
this.$instance.post("/app/appcontentinfo/list", null, {
|
||||
params: {moduleId: this.moduleId, size: 3, areaId: this.areaId}
|
||||
}).then(res => {
|
||||
if (res?.data) {
|
||||
this.publicList = res.data.records;
|
||||
}
|
||||
})
|
||||
},
|
||||
|
||||
linkTo(url, type) {
|
||||
if (type) {
|
||||
if (this.token) {
|
||||
if (type === 'idNumber') {
|
||||
if (!this.user.residentId) {
|
||||
this.$linkTo('/mods/AppAuth/AppAuth')
|
||||
} else {
|
||||
this.$linkTo(url)
|
||||
}
|
||||
}
|
||||
} else {
|
||||
this.$refs.login.show()
|
||||
}
|
||||
} else {
|
||||
this.$linkTo(url)
|
||||
}
|
||||
},
|
||||
|
||||
areaSelect(v) {
|
||||
this.areaId = v
|
||||
this.isMore = false
|
||||
this.current = 0
|
||||
this.newsList = []
|
||||
|
||||
this.$nextTick(() => {
|
||||
this.getActiveList()
|
||||
this.getAlbumList()
|
||||
this.getPublicList()
|
||||
uni.setStorageSync('areaId', this.areaId)
|
||||
uni.setStorageSync('areaName', this.areaName)
|
||||
})
|
||||
},
|
||||
|
||||
getAlbumList() {
|
||||
this.$instance.post(`/app/appvillagepicturealbum/queryAlbumMenu?areaId=${this.areaId}`).then(res => {
|
||||
if (res.code == 0) {
|
||||
this.albumList = res.data.map(v => {
|
||||
return {
|
||||
...v,
|
||||
coverImg: `${this.$cdn}/dvcp/album/album${v.type}.png`
|
||||
}
|
||||
})
|
||||
}
|
||||
})
|
||||
},
|
||||
|
||||
getActiveList() {
|
||||
this.$instance.post(`/app/appvillageactivityinfo/listUp`, null, {
|
||||
params: {
|
||||
current: 1,
|
||||
size: 6,
|
||||
areaId: this.areaId
|
||||
}
|
||||
}).then(res => {
|
||||
if (res.code == 0) {
|
||||
this.activityList = res.data.records.map(v => {
|
||||
return {
|
||||
...v,
|
||||
url: v.url ? JSON.parse(v.url)[0].url : ''
|
||||
}
|
||||
})
|
||||
}
|
||||
})
|
||||
}
|
||||
},
|
||||
|
||||
onShareAppMessage() {
|
||||
return {
|
||||
title: '欢迎使用数字乡村治理服务一体化平台~',
|
||||
path: `/pages/AppEnteringVillage/AppEnteringVillage`
|
||||
}
|
||||
},
|
||||
|
||||
onPageScroll(params) {
|
||||
this.isFixed = params.scrollTop > 60;
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss">
|
||||
.wrapper {
|
||||
min-height: 100%;
|
||||
background: #F3F6F9;
|
||||
|
||||
::v-deep .emptyImg {
|
||||
margin-top: 0 !important;
|
||||
}
|
||||
|
||||
.header {
|
||||
position: fixed;
|
||||
left: 0;
|
||||
top: 0;
|
||||
z-index: 0;
|
||||
width: 100%;
|
||||
opacity: 0;
|
||||
transition: all 0.2s ease;
|
||||
|
||||
&.header-active {
|
||||
z-index: 1111;
|
||||
opacity: 1;
|
||||
background: #4181FF;
|
||||
}
|
||||
|
||||
.nav-bar {
|
||||
position: relative;
|
||||
height: 88px;
|
||||
line-height: 88px;
|
||||
color: #fff;
|
||||
font-size: 32px;
|
||||
text-align: center;
|
||||
}
|
||||
}
|
||||
|
||||
& > header {
|
||||
position: relative;
|
||||
height: 656px;
|
||||
box-sizing: border-box;
|
||||
padding-left: 32px;
|
||||
|
||||
& > div {
|
||||
position: relative;
|
||||
z-index: 11;
|
||||
}
|
||||
|
||||
.ai-area__wrapper {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
padding-top: 100px;
|
||||
|
||||
span {
|
||||
margin-right: 16px;
|
||||
color: #FFFFFF;
|
||||
font-size: 44px;
|
||||
}
|
||||
|
||||
image {
|
||||
width: 16px;
|
||||
height: 8px;
|
||||
}
|
||||
}
|
||||
|
||||
& > image {
|
||||
position: absolute;
|
||||
left: 0;
|
||||
top: 0;
|
||||
z-index: 1;
|
||||
width: 100%;
|
||||
height: 656px;
|
||||
}
|
||||
|
||||
.welcome {
|
||||
font-size: 28px;
|
||||
font-weight: 400;
|
||||
color: #FFFFFF;
|
||||
line-height: 40px;
|
||||
margin-top: 20px;
|
||||
}
|
||||
|
||||
.tag {
|
||||
width: 120px;
|
||||
height: 44px;
|
||||
background: rgba(0, 0, 0, 0.3);
|
||||
border-radius: 8px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
font-size: 22px;
|
||||
font-weight: 400;
|
||||
color: #c0cae0;
|
||||
margin-top: 16px;
|
||||
}
|
||||
|
||||
.tag1 {
|
||||
width: 120px;
|
||||
height: 44px;
|
||||
border: 1px solid #c0cae0;
|
||||
background: rgba(0, 0, 0, 0.1);
|
||||
border-radius: 8px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
font-size: 22px;
|
||||
font-weight: 400;
|
||||
color: #c0cae0;
|
||||
margin-top: 16px;
|
||||
}
|
||||
}
|
||||
|
||||
.card {
|
||||
position: relative;
|
||||
z-index: 1;
|
||||
background: #FFFFFF;
|
||||
border-radius: 32px 32px 0 0;
|
||||
margin-top: -336px;
|
||||
box-sizing: border-box;
|
||||
padding: 32px 32px 0 32px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
flex-wrap: wrap;
|
||||
|
||||
.card-item {
|
||||
width: 332px;
|
||||
height: 160px;
|
||||
margin-bottom: 32px;
|
||||
border-radius: 16px;
|
||||
|
||||
image {
|
||||
width: 332px;
|
||||
height: 160px;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.banner {
|
||||
position: relative;
|
||||
z-index: 2;
|
||||
height: 200px;
|
||||
background: linear-gradient(180deg, #FFFFFF 0%, #F3F6F9 100%);
|
||||
|
||||
image {
|
||||
display: block;
|
||||
width: 692px;
|
||||
height: 200px;
|
||||
margin: 0 auto;
|
||||
}
|
||||
}
|
||||
|
||||
.title-wrap {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
box-sizing: border-box;
|
||||
padding: 48px 32px 32px;
|
||||
|
||||
.title {
|
||||
font-size: 44px;
|
||||
font-weight: 600;
|
||||
color: #333333;
|
||||
}
|
||||
|
||||
.right {
|
||||
|
||||
.title-more {
|
||||
font-size: 28px;
|
||||
font-weight: 400;
|
||||
line-height: 40px;
|
||||
color: #999999;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.list-news {
|
||||
box-sizing: border-box;
|
||||
padding: 0 32px;
|
||||
|
||||
.news-wrap {
|
||||
height: 186px;
|
||||
background: #FFFFFF;
|
||||
box-shadow: 0 0 8px 0 rgba(0, 0, 0, 0.02);
|
||||
border-radius: 16px;
|
||||
box-sizing: border-box;
|
||||
padding: 32px;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
justify-content: space-between;
|
||||
margin-bottom: 24px;
|
||||
|
||||
&:last-child {
|
||||
margin-bottom: 0;
|
||||
}
|
||||
|
||||
.news-title {
|
||||
font-size: 36px;
|
||||
font-weight: 600;
|
||||
color: #333333;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
.news-bottom {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
|
||||
.tag {
|
||||
width: 144px;
|
||||
height: 48px;
|
||||
background: #EEEEEE;
|
||||
border-radius: 24px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
font-size: 28px;
|
||||
font-weight: 400;
|
||||
color: #999999;
|
||||
}
|
||||
|
||||
.date {
|
||||
font-size: 28px;
|
||||
font-weight: 400;
|
||||
color: #999999;
|
||||
margin-left: 16px;
|
||||
}
|
||||
|
||||
.view {
|
||||
font-size: 28px;
|
||||
font-weight: 400;
|
||||
color: #999999;
|
||||
margin-left: auto;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
|
||||
& > em {
|
||||
color: #4181FF;
|
||||
font-style: normal;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.scroll-wrap {
|
||||
box-sizing: border-box;
|
||||
padding: 0 32px;
|
||||
width: 100%;
|
||||
white-space: nowrap;
|
||||
|
||||
.scroll-card {
|
||||
display: inline-block;
|
||||
width: 400px;
|
||||
height: 332px;
|
||||
background: #FFFFFF;
|
||||
box-shadow: 0 0 8px 0 rgba(0, 0, 0, 0.02);
|
||||
border-radius: 16px;
|
||||
margin-right: 32px;
|
||||
font-size: 0;
|
||||
|
||||
& > image {
|
||||
width: 400px;
|
||||
height: 240px;
|
||||
border-radius: 16px 16px 0 0;
|
||||
}
|
||||
|
||||
.text {
|
||||
height: calc(100% - 240px);
|
||||
display: flex;
|
||||
align-items: center;
|
||||
box-sizing: border-box;
|
||||
padding: 0 32px;
|
||||
|
||||
& > span {
|
||||
font-size: 32px;
|
||||
font-weight: 600;
|
||||
color: #333333;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
white-space: nowrap;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
&:last-child {
|
||||
margin-right: 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.album-list {
|
||||
box-sizing: border-box;
|
||||
padding: 0 32px 32px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
flex-wrap: wrap;
|
||||
gap: 16px;
|
||||
|
||||
.album {
|
||||
position: relative;
|
||||
width: 218px;
|
||||
height: 240px;
|
||||
background: #FFFFFF;
|
||||
box-shadow: 0 0 8px 0 rgba(0, 0, 0, 0.02);
|
||||
border-radius: 16px;
|
||||
overflow: hidden;
|
||||
|
||||
image {
|
||||
position: absolute;
|
||||
left: 0;
|
||||
top: 0;
|
||||
z-index: 1;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
.total {
|
||||
display: flex;
|
||||
position: absolute;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
right: 8px;
|
||||
top: 8px;
|
||||
z-index: 2;
|
||||
width: 74px;
|
||||
height: 40px;
|
||||
background: rgba(0, 0, 0, .6);
|
||||
border-radius: 8px;
|
||||
font-size: 22px;
|
||||
font-weight: 400;
|
||||
color: #FFFFFF;
|
||||
}
|
||||
|
||||
.desc {
|
||||
position: absolute;
|
||||
bottom: 16px;
|
||||
left: 0;
|
||||
z-index: 2;
|
||||
width: 100%;
|
||||
height: 40px;
|
||||
line-height: 40px;
|
||||
padding: 0 12px;
|
||||
font-size: 32px;
|
||||
text-align: center;
|
||||
color: #FFFFFF;
|
||||
font-weight: 600;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
::v-deep .AiArea {
|
||||
padding-top: 64px;
|
||||
height: 88px;
|
||||
|
||||
._img {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.area-name {
|
||||
font-size: 44px;
|
||||
font-weight: 600;
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
BIN
src/mods/conv/AppEnteringVillage/custom.png
Normal file
|
After Width: | Height: | Size: 970 B |
BIN
src/mods/conv/AppEnteringVillage/custom_selected.png
Normal file
|
After Width: | Height: | Size: 1.2 KiB |
431
src/mods/conv/AppHealthReport/AddReport.vue
Normal file
@@ -0,0 +1,431 @@
|
||||
<template>
|
||||
<div class="album">
|
||||
<div class="tips">请确保以下信息全部由本人填写,本人对所填写内容的真实性和完整性负责</div>
|
||||
<div class="form-item__group">
|
||||
<div class="form-item">
|
||||
<div class="form-item__wrapper">
|
||||
<div class="form-item__title">
|
||||
<i>*</i>
|
||||
<h2>返乡人员姓名</h2>
|
||||
</div>
|
||||
<div class="form-item__right">
|
||||
<input placeholder="请输入" v-model="form.name" disabled :maxlength="20"/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-item">
|
||||
<div class="form-item__wrapper">
|
||||
<div class="form-item__title">
|
||||
<i>*</i>
|
||||
<h2>身份证号</h2>
|
||||
</div>
|
||||
<div class="form-item__right">
|
||||
<input placeholder="请输入" v-model="form.idNumber" disabled :maxlength="20"/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-item__group">
|
||||
<div class="form-item">
|
||||
<div class="form-item__wrapper">
|
||||
<div class="form-item__title">
|
||||
<i>*</i>
|
||||
<h2>当前体温</h2>
|
||||
</div>
|
||||
<div class="form-item__right">
|
||||
<input placeholder="请输入" v-model="form.temperature" :maxlength="20"/>
|
||||
<i>℃</i>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-item form-item__imgs">
|
||||
<div class="form-item__wrapper">
|
||||
<div class="form-item__title">
|
||||
<i>*</i>
|
||||
<h2>14天内是否接触新冠确诊或疑似患者</h2>
|
||||
</div>
|
||||
<div class="form-item__right">
|
||||
<AiRadio style="width: 100%;" v-model="form.touchInFourteen" dict="epidemicTouchInFourteen"></AiRadio>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-item form-item__imgs">
|
||||
<div class="form-item__wrapper">
|
||||
<div class="form-item__title">
|
||||
<i>*</i>
|
||||
<h2>当前健康状况(可多选)</h2>
|
||||
</div>
|
||||
<div class="form-item__right">
|
||||
<AiCheckbox style="width: 100%;" v-model="form.health" dict="epidemicRecentHealth"></AiCheckbox>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-item__group">
|
||||
<div class="form-item">
|
||||
<div class="form-item__wrapper">
|
||||
<div class="form-item__title">
|
||||
<i>*</i>
|
||||
<h2>核酸检测日期</h2>
|
||||
</div>
|
||||
<div class="form-item__right">
|
||||
<div class="ai-area" @click="isShowDate = true">
|
||||
<div class="ai-area__wrapper">
|
||||
<span class="label" v-if="form.checkTime">{{ form.checkTime }}</span>
|
||||
<i v-else>请选择</i>
|
||||
<u-icon name="arrow-right" color="#ddd"/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-item form-item__imgs">
|
||||
<div class="form-item__wrapper">
|
||||
<div class="form-item__title">
|
||||
<i>*</i>
|
||||
<h2>核酸检测结果</h2>
|
||||
</div>
|
||||
<div class="form-item__right">
|
||||
<AiRadio style="width: 100%;" v-model="form.checkResult" dict="epidemicRecentTestResult"></AiRadio>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-item form-item__imgs">
|
||||
<div class="form-item__wrapper">
|
||||
<div class="form-item__title">
|
||||
<i>*</i>
|
||||
<h2>健康码类型</h2>
|
||||
</div>
|
||||
<div class="form-item__right">
|
||||
<AiRadio style="width: 100%;" v-model="form.healthCode" dict="epidemicHealthCode"></AiRadio>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-item form-item__imgs">
|
||||
<div class="form-item__wrapper">
|
||||
<div class="form-item__title">
|
||||
<i>*</i>
|
||||
<h2>已接种疫苗次数</h2>
|
||||
</div>
|
||||
<div class="form-item__right">
|
||||
<AiRadio style="width: 100%;" v-model="form.vaccine" dict="epidemicVaccineTime"></AiRadio>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-item form-item__imgs">
|
||||
<div class="form-item__wrapper">
|
||||
<div class="form-item__title">
|
||||
<i style="margin-right: 8px"></i>
|
||||
<h2>本人健康码截图<span style="color: #999; font-size:14px;font-weight:normal;">(最多9张)</span></h2>
|
||||
</div>
|
||||
<div class="form-item__right" style="padding-left: 5px">
|
||||
<AiUploader v-model="form.checkPhoto" :limit="9" multiple></AiUploader>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<u-picker mode="time" :params="dataParams" v-model="isShowDate" @confirm="onDateChange"></u-picker>
|
||||
<div class="btn-wrapper">
|
||||
<div class="btn" hover-class="text-hover" @click="submit">提交</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import {mapState} from 'vuex'
|
||||
|
||||
export default {
|
||||
appName:"今日上报",
|
||||
data() {
|
||||
return {
|
||||
isShowDate: false,
|
||||
dataParams: {
|
||||
year: true,
|
||||
month: true,
|
||||
day: true
|
||||
},
|
||||
form: {
|
||||
name: '',
|
||||
idNumber: '',
|
||||
checkPhoto: [],
|
||||
checkResult: '',
|
||||
health: '',
|
||||
healthCode: '',
|
||||
temperature: '',
|
||||
vaccine: '',
|
||||
checkTime: '',
|
||||
memberId: ''
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
|
||||
computed: {
|
||||
...mapState(['user'])
|
||||
},
|
||||
|
||||
onLoad(query) {
|
||||
this.form.memberId = query.id
|
||||
this.getInfo(query.id)
|
||||
},
|
||||
|
||||
methods: {
|
||||
getInfo(id) {
|
||||
this.$instance.post(`/app/appepidemicreportmember/queryDetailById?id=${id}`).then(res => {
|
||||
if (res.code === 0) {
|
||||
this.form.name = res.data.name
|
||||
this.form.idNumber = res.data.idNumber
|
||||
|
||||
this.form.checkTime = res.data.checkTime ? res.data.checkTime.split(' ')[0] : ''
|
||||
this.form.checkResult = res.data.checkResult || ''
|
||||
this.form.healthCode = res.data.healthCode || ''
|
||||
this.form.vaccine = res.data.vaccine || ''
|
||||
}
|
||||
|
||||
this.$hideLoading()
|
||||
}).catch(() => {
|
||||
this.$hideLoading()
|
||||
})
|
||||
},
|
||||
|
||||
onDateChange(e) {
|
||||
this.form.checkTime = `${e.year}-${e.month}-${e.day}`
|
||||
},
|
||||
|
||||
submit() {
|
||||
if (!this.form.temperature) {
|
||||
return this.$toast('请输入当前体温')
|
||||
}
|
||||
|
||||
if (!this.form.touchInFourteen) {
|
||||
return this.$toast('请选择14天内是否接触新冠确诊或疑似患者')
|
||||
}
|
||||
|
||||
if (!this.form.health.length) {
|
||||
return this.$toast('请选择当前健康状况')
|
||||
}
|
||||
if (!this.form.checkTime) {
|
||||
return this.$toast('请选择核酸检测日期')
|
||||
}
|
||||
|
||||
if (!this.form.checkResult) {
|
||||
return this.$toast('请选择核酸检测结果')
|
||||
}
|
||||
|
||||
if (!this.form.healthCode) {
|
||||
return this.$toast('请选择健康码类型')
|
||||
}
|
||||
|
||||
if (!this.form.vaccine) {
|
||||
return this.$toast('请选择已接种疫苗次数')
|
||||
}
|
||||
|
||||
// if (!this.form.checkPhoto.length) {
|
||||
// return this.$toast('请上传健康码截图')
|
||||
// }
|
||||
this.$loading()
|
||||
this.$instance.post(`/app/appepidemichealthreport/addOrUpdate`, {
|
||||
...this.form,
|
||||
openid: this.user.openid,
|
||||
health: this.form.health.join(','),
|
||||
checkPhoto: JSON.stringify(this.form.checkPhoto),
|
||||
checkTime: this.form.checkTime + ' 00:00:00'
|
||||
}).then(res => {
|
||||
if (res.code == 0) {
|
||||
uni.$emit('update')
|
||||
this.$toast('提交成功')
|
||||
setTimeout(() => {
|
||||
uni.navigateBack()
|
||||
}, 400)
|
||||
}
|
||||
this.$hideLoading()
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss">
|
||||
.album {
|
||||
padding-bottom: 140px;
|
||||
|
||||
.tips {
|
||||
line-height: 1.3;
|
||||
padding: 32px 32px;
|
||||
color: #FF883C;
|
||||
font-size: 30px;
|
||||
text-align: justify;
|
||||
background: #FFF8F3;
|
||||
}
|
||||
|
||||
.form-item__group {
|
||||
margin-bottom: 24px;
|
||||
background: #fff;
|
||||
}
|
||||
|
||||
.form-item {
|
||||
padding-left: 32px;
|
||||
|
||||
.form-item__checkbox {
|
||||
width: 100%;
|
||||
|
||||
div {
|
||||
width: 100%;
|
||||
height: 80px;
|
||||
line-height: 80px;
|
||||
margin-bottom: 24px;
|
||||
text-align: center;
|
||||
background: #FFFFFF;
|
||||
border-radius: 16px;
|
||||
color: #333333;
|
||||
font-size: 28px;
|
||||
border: 1px solid #CCCCCC;
|
||||
|
||||
&.active {
|
||||
background: #4181FF;
|
||||
color: #fff;
|
||||
border-color: #4181FF;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.form-item__radio {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
flex-wrap: wrap;
|
||||
|
||||
div {
|
||||
width: 212px;
|
||||
height: 80px;
|
||||
line-height: 80px;
|
||||
margin-right: 16px;
|
||||
margin-bottom: 8px;
|
||||
text-align: center;
|
||||
background: #FFFFFF;
|
||||
border-radius: 16px;
|
||||
color: #333333;
|
||||
font-size: 28px;
|
||||
border: 1px solid #CCCCCC;
|
||||
|
||||
&:nth-of-type(3n) {
|
||||
margin-right: 0;
|
||||
}
|
||||
|
||||
&.active {
|
||||
background: #4181FF;
|
||||
color: #fff;
|
||||
border-color: #4181FF;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.ai-area__wrapper {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
padding-left: 100px;
|
||||
|
||||
span {
|
||||
color: #333;
|
||||
font-size: 30px;
|
||||
}
|
||||
|
||||
i {
|
||||
color: #999;
|
||||
font-size: 30px;
|
||||
}
|
||||
|
||||
image {
|
||||
width: 16px;
|
||||
height: 8px;
|
||||
}
|
||||
}
|
||||
|
||||
.form-item__wrapper {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
height: 128px;
|
||||
padding-right: 28px;
|
||||
border-bottom: 1px solid #DDDDDD;
|
||||
|
||||
input {
|
||||
flex: 1;
|
||||
height: 100%;
|
||||
text-align: right;
|
||||
color: #333;
|
||||
padding-right: 10px;
|
||||
}
|
||||
|
||||
.form-item__right {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
font-size: 32px;
|
||||
|
||||
span {
|
||||
max-width: 400px;
|
||||
margin-right: 8px;
|
||||
color: #333333;
|
||||
overflow: hidden;
|
||||
white-space: nowrap;
|
||||
text-overflow: ellipsis;
|
||||
}
|
||||
|
||||
i {
|
||||
margin-right: 8px;
|
||||
color: #999999;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
&:last-child {
|
||||
.form-item__wrapper {
|
||||
border-bottom: none;
|
||||
}
|
||||
}
|
||||
|
||||
.form-item__title {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
|
||||
i {
|
||||
font-size: 32px;
|
||||
color: #FF4466;
|
||||
}
|
||||
|
||||
span {
|
||||
font-size: 28px;
|
||||
color: #999999;
|
||||
}
|
||||
|
||||
h2 {
|
||||
padding: 0 4px;
|
||||
font-weight: 600;
|
||||
font-size: 32px;
|
||||
color: #333333;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
&.form-item__imgs, &.form-item__textarea {
|
||||
.form-item__wrapper {
|
||||
display: block;
|
||||
height: auto;
|
||||
padding-bottom: 32px;
|
||||
}
|
||||
|
||||
textarea {
|
||||
width: 100%;
|
||||
height: 90px;
|
||||
}
|
||||
|
||||
.form-item__title {
|
||||
padding: 32px 0;
|
||||
}
|
||||
|
||||
.form-item__right {
|
||||
padding-left: 18px;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
327
src/mods/conv/AppHealthReport/AddUser.vue
Normal file
@@ -0,0 +1,327 @@
|
||||
<template>
|
||||
<div class="album">
|
||||
<div class="form-item__group">
|
||||
<div class="form-item">
|
||||
<div class="form-item__wrapper">
|
||||
<div class="form-item__title">
|
||||
<i>*</i>
|
||||
<h2>上报人姓名</h2>
|
||||
</div>
|
||||
<div class="form-item__right">
|
||||
<input placeholder="请输入" v-model="form.name" :maxlength="20"/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-item">
|
||||
<div class="form-item__wrapper">
|
||||
<div class="form-item__title">
|
||||
<i>*</i>
|
||||
<h2>身份证号</h2>
|
||||
</div>
|
||||
<div class="form-item__right">
|
||||
<input placeholder="请输入" type="idcard" v-model="form.idNumber" :maxlength="20"/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-item">
|
||||
<div class="form-item__wrapper">
|
||||
<div class="form-item__title">
|
||||
<i>*</i>
|
||||
<h2>手机号码</h2>
|
||||
</div>
|
||||
<div class="form-item__right">
|
||||
<input placeholder="请输入" type="number" v-model="form.phone" :maxlength="11"/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-item">
|
||||
<div class="form-item__wrapper">
|
||||
<div class="form-item__title">
|
||||
<i>*</i>
|
||||
<h2>上报地区</h2>
|
||||
</div>
|
||||
<div class="form-item__right">
|
||||
<AiAreaPicker class="ai-area" :areaId="$areaId" v-model="form.areaId" :fullName.sync="form.areaName">
|
||||
<div class="ai-area__wrapper">
|
||||
<span class="label" v-if="form.areaName">{{ form.areaName }}</span>
|
||||
<i v-else>请选择</i>
|
||||
<u-icon name="arrow-right" color="#ddd"/>
|
||||
</div>
|
||||
</AiAreaPicker>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-item form-item__textarea">
|
||||
<div class="form-item__wrapper">
|
||||
<div class="form-item__title">
|
||||
<i>*</i>
|
||||
<h2>详细地址</h2>
|
||||
</div>
|
||||
<div class="form-item__right">
|
||||
<textarea auto-height v-model="form.address" :maxlength="500" placeholder="请输入详细地址"
|
||||
placeholder-style="font-size: 16px;"></textarea>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="btn-wrapper">
|
||||
<div class="btn" hover-class="text-hover" @click="submit">提交</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import {mapState} from 'vuex'
|
||||
|
||||
export default {
|
||||
appName: "添加上报人员",
|
||||
data() {
|
||||
return {
|
||||
form: {
|
||||
address: '',
|
||||
areaId: '',
|
||||
areaName: '',
|
||||
idNumber: '',
|
||||
name: '',
|
||||
phone: ''
|
||||
},
|
||||
$areaId: '',
|
||||
flag: false
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
...mapState(['user'])
|
||||
},
|
||||
|
||||
methods: {
|
||||
submit() {
|
||||
if (!this.form.name) {
|
||||
return this.$toast('请输入上报人姓名')
|
||||
}
|
||||
|
||||
if (!this.form.idNumber) {
|
||||
return this.$toast('请输入上报人身份证号')
|
||||
}
|
||||
|
||||
if (!/^[1-9]\d{5}(19\d{2}|20[0-2]\d)(0[1-9]|1[0-2])(0[1-9]|[1-2][0-9]|3[0-1])\d{3}([0-9xX])$/.test(this.form.idNumber)) {
|
||||
return this.$toast('请输入正确的身份证账号')
|
||||
}
|
||||
if (!this.form.phone) {
|
||||
return this.$toast('请选择上报人手机号码')
|
||||
}
|
||||
|
||||
if (!/^1[0-9]{10,10}$/.test(this.form.phone)) {
|
||||
return this.$toast('请输入正确的手机号码')
|
||||
}
|
||||
|
||||
if (!this.form.areaId) {
|
||||
return this.$toast('请选择上报地区')
|
||||
}
|
||||
|
||||
if (this.form.areaId.substr(this.form.areaId.length - 3, 3) === '000') {
|
||||
return this.$toast('上报地区必须选到村或社区')
|
||||
}
|
||||
|
||||
if (!this.form.address) {
|
||||
return this.$toast('请输入详细地址')
|
||||
}
|
||||
if (this.flag) return
|
||||
this.flag = true
|
||||
|
||||
this.$loading()
|
||||
this.$instance.post(`/app/appepidemicreportmember/addOrUpdate`, {
|
||||
...this.form,
|
||||
openid: this.user.openid
|
||||
}).then(res => {
|
||||
this.$hideLoading()
|
||||
this.flag = false
|
||||
if (res.code == 0) {
|
||||
this.$toast('提交成功')
|
||||
uni.$emit('update')
|
||||
setTimeout(() => {
|
||||
uni.redirectTo({
|
||||
url: `./Result?id=${res.data.id}`
|
||||
})
|
||||
}, 400)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss">
|
||||
.album {
|
||||
padding-bottom: 140px;
|
||||
|
||||
.form-item__group {
|
||||
margin-bottom: 24px;
|
||||
background: #fff;
|
||||
}
|
||||
|
||||
.form-item {
|
||||
padding-left: 32px;
|
||||
|
||||
.form-item__checkbox {
|
||||
width: 100%;
|
||||
|
||||
div {
|
||||
width: 100%;
|
||||
height: 80px;
|
||||
line-height: 80px;
|
||||
margin-bottom: 24px;
|
||||
text-align: center;
|
||||
background: #FFFFFF;
|
||||
border-radius: 16px;
|
||||
color: #333333;
|
||||
font-size: 28px;
|
||||
border: 1px solid #CCCCCC;
|
||||
|
||||
&.active {
|
||||
background: #4181FF;
|
||||
color: #fff;
|
||||
border-color: #4181FF;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.form-item__radio {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
flex-wrap: wrap;
|
||||
|
||||
div {
|
||||
width: 212px;
|
||||
height: 80px;
|
||||
line-height: 80px;
|
||||
margin-right: 16px;
|
||||
margin-bottom: 8px;
|
||||
text-align: center;
|
||||
background: #FFFFFF;
|
||||
border-radius: 16px;
|
||||
color: #333333;
|
||||
font-size: 28px;
|
||||
border: 1px solid #CCCCCC;
|
||||
|
||||
&:nth-of-type(3n) {
|
||||
margin-right: 0;
|
||||
}
|
||||
|
||||
&.active {
|
||||
background: #4181FF;
|
||||
color: #fff;
|
||||
border-color: #4181FF;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.ai-area__wrapper {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
padding-left: 100px;
|
||||
|
||||
span {
|
||||
color: #333;
|
||||
font-size: 30px;
|
||||
}
|
||||
|
||||
i {
|
||||
color: #999;
|
||||
font-size: 30px;
|
||||
}
|
||||
|
||||
image {
|
||||
width: 16px;
|
||||
height: 8px;
|
||||
}
|
||||
}
|
||||
|
||||
.form-item__wrapper {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
height: 128px;
|
||||
padding-right: 28px;
|
||||
border-bottom: 1px solid #DDDDDD;
|
||||
|
||||
input {
|
||||
flex: 1;
|
||||
height: 100%;
|
||||
text-align: right;
|
||||
color: #333;
|
||||
padding-right: 10px;
|
||||
}
|
||||
|
||||
.form-item__right {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
font-size: 32px;
|
||||
|
||||
span {
|
||||
max-width: 400px;
|
||||
margin-right: 8px;
|
||||
color: #333333;
|
||||
overflow: hidden;
|
||||
white-space: nowrap;
|
||||
text-overflow: ellipsis;
|
||||
}
|
||||
|
||||
i {
|
||||
margin-right: 8px;
|
||||
color: #999999;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
&:last-child {
|
||||
.form-item__wrapper {
|
||||
border-bottom: none;
|
||||
}
|
||||
}
|
||||
|
||||
.form-item__title {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
|
||||
i {
|
||||
font-size: 32px;
|
||||
color: #FF4466;
|
||||
}
|
||||
|
||||
span {
|
||||
font-size: 28px;
|
||||
color: #999999;
|
||||
}
|
||||
|
||||
h2 {
|
||||
padding: 0 4px;
|
||||
font-weight: 600;
|
||||
font-size: 32px;
|
||||
color: #333333;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
&.form-item__imgs, &.form-item__textarea {
|
||||
.form-item__wrapper {
|
||||
display: block;
|
||||
height: auto;
|
||||
padding-bottom: 32px;
|
||||
}
|
||||
|
||||
textarea {
|
||||
width: 100%;
|
||||
height: 90px;
|
||||
}
|
||||
|
||||
.form-item__title {
|
||||
padding: 32px 0;
|
||||
}
|
||||
|
||||
.form-item__right {
|
||||
padding-left: 18px;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
223
src/mods/conv/AppHealthReport/AppHealthReport.vue
Normal file
@@ -0,0 +1,223 @@
|
||||
<template>
|
||||
<div class="returnHomeRegister" v-if="pageShow">
|
||||
<div class="title">
|
||||
<h2>上报人员</h2>
|
||||
<div class="right">
|
||||
<span>共</span>
|
||||
<i>{{ total }}</i>
|
||||
<span>名</span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="home-list">
|
||||
<div class="item" v-for="(item, index) in list" :key="index">
|
||||
<div class="item-top">
|
||||
<div class="item-top__left">
|
||||
<h2>{{ item.name }}</h2>
|
||||
<p @click.stop="$linkTo('./UserInfo?id=' + item.id)" hover-class="text-hover">查看个人信息></p>
|
||||
</div>
|
||||
<span v-if="item.status === '0'">健康数据异常</span>
|
||||
</div>
|
||||
<div class="item-bottom">
|
||||
<div class="item-bottom__left">
|
||||
<span>上报第</span>
|
||||
<i>{{ item.diffNum || 0 }}</i>
|
||||
<span>天</span>
|
||||
</div>
|
||||
<div class="item-bottom__right" hover-class="text-hover" v-if="item.today === '0'"
|
||||
@click.stop="$linkTo('./AddReport?id=' + item.id)">
|
||||
<span style="color: #FF883C">今日未上报</span>
|
||||
<u-icon name="arrow-right" color="#ddd"/>
|
||||
</div>
|
||||
<div class="item-bottom__right" hover-class="text-hover" v-else
|
||||
@click.stop="$linkTo('./RecordList?id=' + item.id)">
|
||||
<span style="color: #999999">今日已上报</span>
|
||||
<u-icon name="arrow-right" color="#ddd"/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<AiEmpty v-if="list.length==0"/>
|
||||
</div>
|
||||
<div class="btn-wrapper">
|
||||
<div class="btn" @click="toReport" hover-class="text-hover">添加上报人员</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import {mapState} from 'vuex'
|
||||
|
||||
export default {
|
||||
name: "AppHealthReport",
|
||||
appName: "健康上报",
|
||||
data() {
|
||||
return {
|
||||
list: [],
|
||||
pageShow: false,
|
||||
current: 1,
|
||||
total: 0,
|
||||
}
|
||||
},
|
||||
|
||||
computed: {
|
||||
...mapState(['user'])
|
||||
},
|
||||
|
||||
onLoad() {
|
||||
this.$loading()
|
||||
this.$dict.load(['villageActivityStatus']).then(() => {
|
||||
this.getList()
|
||||
})
|
||||
|
||||
uni.$on('update', () => {
|
||||
this.current = 1
|
||||
this.$nextTick(() => {
|
||||
this.getList()
|
||||
})
|
||||
})
|
||||
},
|
||||
|
||||
methods: {
|
||||
toReport() {
|
||||
this.$linkTo('./AddUser')
|
||||
},
|
||||
|
||||
getList() {
|
||||
|
||||
this.$instance.post(`/app/appepidemicreportmember/list?openId=${this.user.openId}`, null, {
|
||||
params: {
|
||||
current: this.current,
|
||||
size: 15
|
||||
}
|
||||
}).then(res => {
|
||||
if (res.code == 0) {
|
||||
this.total = res.data.total
|
||||
if (this.current > 1) {
|
||||
this.list = [...this.list, ...res.data.records]
|
||||
} else {
|
||||
this.list = res.data.records
|
||||
}
|
||||
uni.hideLoading()
|
||||
this.pageShow = true
|
||||
if (res.data.records.length < 15) {
|
||||
|
||||
return false
|
||||
}
|
||||
|
||||
this.current = this.current + 1
|
||||
} else {
|
||||
uni.hideLoading()
|
||||
}
|
||||
}).catch(() => {
|
||||
uni.hideLoading()
|
||||
})
|
||||
}
|
||||
},
|
||||
|
||||
onReachBottom() {
|
||||
this.getList()
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.returnHomeRegister {
|
||||
padding: 0 0 150px 0;
|
||||
|
||||
.title {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
margin-bottom: 32px;
|
||||
padding: 48px 32px 0 32px;
|
||||
|
||||
& > h2 {
|
||||
font-size: 38px;
|
||||
color: #333;
|
||||
font-weight: 600;
|
||||
}
|
||||
|
||||
.right {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
|
||||
span {
|
||||
color: #666666;
|
||||
font-size: 28px;
|
||||
}
|
||||
|
||||
i {
|
||||
color: #4181FF;
|
||||
font-style: normal;
|
||||
font-size: 28px;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.item {
|
||||
margin: 0 32px 24px;
|
||||
border-radius: 16px;
|
||||
background: #fff;
|
||||
|
||||
.item-top {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
height: 152px;
|
||||
padding: 0 32px;
|
||||
border-bottom: 1px solid #DDDDDD;
|
||||
|
||||
.item-top__left {
|
||||
h2 {
|
||||
line-height: 44px;
|
||||
margin-bottom: 8px;
|
||||
color: #333;
|
||||
font-size: 32px;
|
||||
font-weight: 600;
|
||||
}
|
||||
|
||||
p {
|
||||
color: #999999;
|
||||
font-size: 26px;
|
||||
}
|
||||
}
|
||||
|
||||
& > span {
|
||||
font-size: 26px;
|
||||
color: #FF4466;
|
||||
}
|
||||
}
|
||||
|
||||
.item-bottom {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
height: 104px;
|
||||
padding: 0 32px;
|
||||
|
||||
.item-bottom__right {
|
||||
span {
|
||||
color: #999999;
|
||||
font-size: 28px;
|
||||
}
|
||||
}
|
||||
|
||||
.item-bottom__left {
|
||||
span {
|
||||
color: #999999;
|
||||
font-size: 28px;
|
||||
}
|
||||
|
||||
i {
|
||||
color: #4181FF;
|
||||
font-size: 28px;
|
||||
}
|
||||
}
|
||||
|
||||
& > div {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
246
src/mods/conv/AppHealthReport/Detail.vue
Normal file
@@ -0,0 +1,246 @@
|
||||
<template>
|
||||
<div class="detail">
|
||||
<div class="detail-info">
|
||||
<h2>健康状况</h2>
|
||||
<div class="detail-info__item">
|
||||
<div class="left">
|
||||
<label>当前体温</label>
|
||||
</div>
|
||||
<div class="right">
|
||||
<span :style="{color: info.temperature >= 37.3 ? '#FF4466' : '#42D784'}">{{ info.temperature }}℃</span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="detail-info__item">
|
||||
<div class="left">
|
||||
<label>14天内是否接触新冠确诊或疑似患者</label>
|
||||
</div>
|
||||
<div class="right">
|
||||
<span :style="{color: info.touchInFourteen === '0' ? '#42D784' : '#FF4466'}">{{ $dict.getLabel('epidemicTouchInFourteen', info.touchInFourteen) }}</span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="detail-info__item">
|
||||
<div class="left">
|
||||
<label>当前健康状况</label>
|
||||
</div>
|
||||
<div class="right">
|
||||
<span :style="{color: !info.isHealth ? '#42D784' : '#FF4466'}">{{ info.healthName }}</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="detail-info">
|
||||
<h2>核酸检测信息</h2>
|
||||
<div class="detail-info__item">
|
||||
<div class="left">
|
||||
<label>核酸检测日期</label>
|
||||
</div>
|
||||
<div class="right">
|
||||
<span>{{ info.checkTime.split(' ')[0] }}</span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="detail-info__item">
|
||||
<div class="left">
|
||||
<label>核酸检测结果</label>
|
||||
</div>
|
||||
<div class="right">
|
||||
<span :style="{color: info.checkResult === '0' ? '#42D784' : '#FF4466'}">{{ $dict.getLabel('epidemicRecentTestResult', info.checkResult) }}</span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="detail-info__item">
|
||||
<div class="left">
|
||||
<label>健康码状态</label>
|
||||
</div>
|
||||
<div class="right">
|
||||
<span :style="{color: info.healthCode === '0' || info.healthCode === '1' ? '#42D784' : '#FF4466'}">{{ $dict.getLabel('epidemicHealthCode', info.healthCode) }}</span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="detail-info__item">
|
||||
<div class="left">
|
||||
<label>已接种疫苗次数</label>
|
||||
</div>
|
||||
<div class="right">
|
||||
<span>{{ $dict.getLabel('epidemicVaccineTime', info.vaccine) }}</span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="detail-info__item detail-info__item--img">
|
||||
<div class="left">
|
||||
<label>本人健康码截图</label>
|
||||
</div>
|
||||
<div class="right">
|
||||
<image :src="item.url" @click="preview(item.url)" v-for="(item, index) in info.checkPhoto" :key="index" />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
appName:"上报详情",
|
||||
data () {
|
||||
return {
|
||||
info: {},
|
||||
pageShow: false
|
||||
}
|
||||
},
|
||||
|
||||
onLoad (query) {
|
||||
this.$loading()
|
||||
this.$dict.load(['epidemicTouchInFourteen', 'epidemicRecentHealth', 'epidemicRecentTestResult', 'epidemicHealthCode', 'epidemicVaccineTime']).then(() => {
|
||||
this.getInfo(query.id)
|
||||
})
|
||||
},
|
||||
|
||||
methods: {
|
||||
preview (url) {
|
||||
uni.previewImage({
|
||||
urls: this.info.checkPhoto.map(v => v.url),
|
||||
current: url
|
||||
})
|
||||
},
|
||||
|
||||
getInfo (id) {
|
||||
this.$instance.post(`/app/appepidemichealthreport/queryDetailById?id=${id}`).then(res => {
|
||||
if (res.code === 0) {
|
||||
this.info = res.data
|
||||
this.info.checkPhoto = JSON.parse(res.data.checkPhoto)
|
||||
let healthName = ''
|
||||
this.info.isHealth = false
|
||||
res.data.health.split(',').forEach(v => {
|
||||
if (v > 0) {
|
||||
this.info.isHealth = true
|
||||
}
|
||||
healthName = healthName + this.$dict.getLabel('epidemicRecentHealth', v)
|
||||
})
|
||||
this.info.healthName = healthName
|
||||
|
||||
this.$nextTick(() => {
|
||||
this.pageShow = true
|
||||
})
|
||||
}
|
||||
|
||||
this.$hideLoading()
|
||||
})
|
||||
},
|
||||
|
||||
call (phone) {
|
||||
uni.makePhoneCall({
|
||||
phoneNumber: phone
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss">
|
||||
.detail {
|
||||
padding-bottom: 40px;
|
||||
|
||||
.detail-header {
|
||||
padding: 32px;
|
||||
background: #fff;
|
||||
|
||||
h2 {
|
||||
margin-bottom: 32px;
|
||||
color: #333333;
|
||||
font-size: 40px;
|
||||
font-weight: 600;
|
||||
}
|
||||
|
||||
.item-info {
|
||||
.item-info__item {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
margin-bottom: 8px;
|
||||
|
||||
&:last-child {
|
||||
margin-bottom: 0;
|
||||
}
|
||||
|
||||
image {
|
||||
width: 32px;
|
||||
height: 32px;
|
||||
margin-right: 16px;
|
||||
}
|
||||
|
||||
span {
|
||||
color: #333;
|
||||
font-size: 28px;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.detail-info {
|
||||
margin-top: 24px;
|
||||
padding: 0 32px;
|
||||
background: #fff;
|
||||
|
||||
& > h2 {
|
||||
height: 116px;
|
||||
line-height: 116px;
|
||||
font-size: 38px;
|
||||
font-weight: 600;
|
||||
color: #333;
|
||||
}
|
||||
|
||||
.detail-info__item {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
padding: 34px 0;
|
||||
border-bottom: 1px solid #DDDDDD;
|
||||
|
||||
&:last-child {
|
||||
border: none;
|
||||
}
|
||||
|
||||
.left {
|
||||
display: flex;
|
||||
line-height: 1.3;
|
||||
max-width: 360px;
|
||||
|
||||
label {
|
||||
position: relative;
|
||||
color: #999999;
|
||||
font-size: 32px;
|
||||
}
|
||||
}
|
||||
|
||||
.right {
|
||||
display: flex;
|
||||
max-width: 450px;
|
||||
|
||||
span {
|
||||
color: #333333;
|
||||
font-size: 32px;
|
||||
text-align: right;
|
||||
}
|
||||
|
||||
image {
|
||||
width: 40px;
|
||||
height: 40px;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.detail-info__item--img {
|
||||
display: block;
|
||||
|
||||
.right {
|
||||
flex-wrap: wrap;
|
||||
max-width: 100%;
|
||||
margin-top: 34px;
|
||||
|
||||
image {
|
||||
width: 226px;
|
||||
height: 226px;
|
||||
margin: 0 9px 9px 0;
|
||||
|
||||
&:nth-of-type(3n) {
|
||||
margin-right: 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
116
src/mods/conv/AppHealthReport/RecordList.vue
Normal file
@@ -0,0 +1,116 @@
|
||||
<template>
|
||||
<div class="record" v-if="pageShow">
|
||||
<div class="record-item" v-for="(item, index) in list" :key="index" @click="$linkTo('./Detail?id=' + item.id)"
|
||||
hover-class="bg-hover">
|
||||
<div class="left">{{ item.createTime.split(' ')[0] }}的健康上报</div>
|
||||
<div class="right">
|
||||
<i v-if="item.status === '0'">健康数据异常</i>
|
||||
<u-icon name="arrow-right" color="#ddd"/>
|
||||
</div>
|
||||
</div>
|
||||
<AiEmpty v-if="!list.length && isMore"/>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
appName: "上报记录",
|
||||
data() {
|
||||
return {
|
||||
list: [],
|
||||
pageShow: false,
|
||||
current: 1,
|
||||
total: 0,
|
||||
isMore: false
|
||||
}
|
||||
},
|
||||
|
||||
onLoad(query) {
|
||||
this.$loading()
|
||||
this.getList(query)
|
||||
},
|
||||
|
||||
methods: {
|
||||
getList(query) {
|
||||
if (this.isMore) return
|
||||
|
||||
this.$instance.post(`/app/appepidemichealthreport/list?memberId=${query.id}`, null, {
|
||||
params: {
|
||||
current: this.current,
|
||||
size: 15
|
||||
}
|
||||
}).then(res => {
|
||||
if (res.code == 0) {
|
||||
this.total = res.data.total
|
||||
if (this.current > 1) {
|
||||
this.list = [...this.list, ...res.data.records]
|
||||
} else {
|
||||
this.list = res.data.records
|
||||
}
|
||||
uni.hideLoading()
|
||||
this.pageShow = true
|
||||
if (res.data.records.length < 15) {
|
||||
this.isMore = true
|
||||
|
||||
return false
|
||||
}
|
||||
|
||||
this.current = this.current + 1
|
||||
} else {
|
||||
uni.hideLoading()
|
||||
}
|
||||
}).catch(() => {
|
||||
uni.hideLoading()
|
||||
})
|
||||
}
|
||||
},
|
||||
|
||||
onReachBottom() {
|
||||
this.getList()
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss">
|
||||
.record {
|
||||
padding: 32px 0;
|
||||
|
||||
.record-item {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
width: 686px;
|
||||
height: 112px;
|
||||
margin: 0 auto 24px;
|
||||
padding: 0 28px 0 32px;
|
||||
background: #FFFFFF;
|
||||
box-sizing: border-box;
|
||||
box-shadow: 0 0 8px 0 rgba(0, 0, 0, 0.02);
|
||||
border-radius: 16px;
|
||||
|
||||
.left {
|
||||
color: #333333;
|
||||
font-size: 32px;
|
||||
font-weight: 600;
|
||||
}
|
||||
|
||||
.right {
|
||||
i {
|
||||
width: 158px;
|
||||
height: 36px;
|
||||
line-height: 36px;
|
||||
margin-right: 8px;
|
||||
text-align: center;
|
||||
font-size: 26px;
|
||||
color: #FF4466;
|
||||
background: #FFF5F7;
|
||||
}
|
||||
}
|
||||
|
||||
& > div {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
83
src/mods/conv/AppHealthReport/Result.vue
Normal file
@@ -0,0 +1,83 @@
|
||||
<template>
|
||||
<div class="result">
|
||||
<image src="/static/img/result.png" />
|
||||
<h2>添加成功!</h2>
|
||||
<div class="result-btn" hover-class="text-hover" @click="toReport">上报今日状态</div>
|
||||
<div class="result-backBtn" @click="back">返回</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
data () {
|
||||
return {
|
||||
id: ''
|
||||
}
|
||||
},
|
||||
|
||||
onLoad (query) {
|
||||
this.id = query.id
|
||||
},
|
||||
|
||||
methods: {
|
||||
back () {
|
||||
uni.navigateBack({
|
||||
delta: 1
|
||||
})
|
||||
},
|
||||
|
||||
toReport () {
|
||||
uni.redirectTo({
|
||||
url: `./AddReport?id=${this.id}`
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss">
|
||||
.result {
|
||||
min-height: 100vh;
|
||||
padding-top: 160px;
|
||||
box-sizing: border-box;
|
||||
text-align: center;
|
||||
background: #fff;
|
||||
|
||||
image {
|
||||
width: 220px;
|
||||
height: 220px;
|
||||
}
|
||||
|
||||
.result-backBtn {
|
||||
width: 320px;
|
||||
height: 88px;
|
||||
line-height: 88px;
|
||||
margin: 32px auto 0;
|
||||
text-align: center;
|
||||
border: 1px solid #4181FF;
|
||||
color: #4181FF;
|
||||
font-size: 34px;
|
||||
box-sizing: border-box;
|
||||
border-radius: 16px;
|
||||
}
|
||||
|
||||
h2 {
|
||||
margin: 32px 0 80px;
|
||||
font-weight: 600;
|
||||
font-size: 40px;
|
||||
color: #333;
|
||||
}
|
||||
|
||||
.result-btn {
|
||||
width: 320px;
|
||||
height: 88px;
|
||||
line-height: 88px;
|
||||
margin: 0 auto;
|
||||
text-align: center;
|
||||
background: #4181FF;
|
||||
color: #fff;
|
||||
font-size: 34px;
|
||||
border-radius: 16px;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
134
src/mods/conv/AppHealthReport/UserInfo.vue
Normal file
@@ -0,0 +1,134 @@
|
||||
<template>
|
||||
<div class="userinfo" v-if="pageShow">
|
||||
<div class="cell-group">
|
||||
<div class="cell-item">
|
||||
<div class="cell-item__wrapper">
|
||||
<div class="left">
|
||||
<span>上报人姓名</span>
|
||||
</div>
|
||||
<div class="right">
|
||||
<span>{{ info.name }}</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="cell-item">
|
||||
<div class="cell-item__wrapper">
|
||||
<div class="left">
|
||||
<span>身份证号</span>
|
||||
</div>
|
||||
<div class="right">
|
||||
<span>{{ info.idNumber }}</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="cell-item">
|
||||
<div class="cell-item__wrapper">
|
||||
<div class="left">
|
||||
<span>手机号码</span>
|
||||
</div>
|
||||
<div class="right">
|
||||
<span>{{ info.phone }}</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="cell-item">
|
||||
<div class="cell-item__wrapper">
|
||||
<div class="left">
|
||||
<span>上报地区</span>
|
||||
</div>
|
||||
<div class="right">
|
||||
<span>{{ info.areaName }}</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="cell-item">
|
||||
<div class="cell-item__wrapper">
|
||||
<div class="left">
|
||||
<span>详细地址</span>
|
||||
</div>
|
||||
<div class="right">
|
||||
<span>{{ info.address }}</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
appName:"个人信息",
|
||||
data () {
|
||||
return {
|
||||
info: {},
|
||||
pageShow: false
|
||||
}
|
||||
},
|
||||
|
||||
onLoad (query) {
|
||||
this.$loading()
|
||||
this.getInfo(query.id)
|
||||
},
|
||||
|
||||
methods: {
|
||||
getInfo (id) {
|
||||
this.$instance.post(`/app/appepidemicreportmember/queryDetailById?id=${id}`).then(res => {
|
||||
if (res.code === 0) {
|
||||
this.info = res.data
|
||||
if (res.data.eventStatus > 1) {
|
||||
this.result = res.data.processList[0]
|
||||
}
|
||||
this.$nextTick(() => {
|
||||
this.pageShow = true
|
||||
})
|
||||
}
|
||||
|
||||
this.$hideLoading()
|
||||
}).catch(() => {
|
||||
this.$hideLoading()
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss">
|
||||
.userinfo {
|
||||
.cell-group {
|
||||
background: #fff;
|
||||
|
||||
.cell-item {
|
||||
padding-left: 32px;
|
||||
|
||||
.cell-item__wrapper {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
padding: 34px 32px 34px 0;
|
||||
border-bottom: 1px solid #DDDDDD;
|
||||
|
||||
.left {
|
||||
span {
|
||||
color: #999999;
|
||||
font-size: 32px;
|
||||
}
|
||||
}
|
||||
|
||||
.right {
|
||||
max-width: 450px;
|
||||
text-align: right;
|
||||
span {
|
||||
color: #333333;
|
||||
font-size: 32px;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
&:last-child {
|
||||
.cell-item__wrapper {
|
||||
border-bottom: none;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
216
src/mods/conv/AppMarFuneral/AppMarFuneral.vue
Normal file
@@ -0,0 +1,216 @@
|
||||
<template>
|
||||
<div class="wrapper padding" v-if="pageShow">
|
||||
<template v-if="list.length">
|
||||
<header>
|
||||
<span>婚丧嫁娶列表</span>
|
||||
<div class="total">
|
||||
共<em>{{ list.length }}</em>条
|
||||
</div>
|
||||
</header>
|
||||
<div class="card" v-for="item in list" :key="item.id">
|
||||
<div class="item">
|
||||
<span class="label">事主姓名</span>
|
||||
<span class="value">{{ item.name }}</span>
|
||||
</div>
|
||||
<div class="item">
|
||||
<span class="label">联系方式</span>
|
||||
<span class="value">{{ item.phone }}</span>
|
||||
</div>
|
||||
<div class="item">
|
||||
<span class="label">上报时间</span>
|
||||
<span class="value">{{ item.createTime }}</span>
|
||||
</div>
|
||||
<div class="item">
|
||||
<span class="label">上报地点</span>
|
||||
<span class="value">{{ item.address }}</span>
|
||||
</div>
|
||||
<div class="item" v-if="item.content.trim().length">
|
||||
<span class="label">上报内容</span>
|
||||
<span class="value">{{ item.content || '' }}</span>
|
||||
</div>
|
||||
<div class="tag" :style="{backgroundColor:$dict.getColor('marriageType',item.type)}">
|
||||
{{ $dict.getLabel('marriageType', item.type) }}
|
||||
</div>
|
||||
<u-icon name="more-dot-fill" size="28" color="#999999" :custom-style="customStyle" @click="handleDel(item)"
|
||||
v-if="item.openId == userInfo.openId"></u-icon>
|
||||
</div>
|
||||
</template>
|
||||
<AiEmpty v-else/>
|
||||
<div class="btn-wrapper">
|
||||
<div class="btn" @click="suport" hover-class="text-hover">我要上报</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
|
||||
export default {
|
||||
name: "AppMarFuneral",
|
||||
appName: "婚丧嫁娶",
|
||||
data() {
|
||||
return {
|
||||
current: 1,
|
||||
pageShow: false,
|
||||
list: [],
|
||||
userInfo: {},
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
customStyle() {
|
||||
return {
|
||||
position: "absolute",
|
||||
top: "16px",
|
||||
right: "24px",
|
||||
transform: "rotate(90deg)"
|
||||
};
|
||||
},
|
||||
},
|
||||
|
||||
onLoad() {
|
||||
this.$loading()
|
||||
this.userInfo = uni.getStorageSync("userInfo");
|
||||
|
||||
this.$dict.load("marriageType").then(() => {
|
||||
this.getList()
|
||||
})
|
||||
|
||||
uni.$on('update', () => {
|
||||
this.current = 1
|
||||
this.getList()
|
||||
})
|
||||
},
|
||||
|
||||
methods: {
|
||||
handleDel({id}) {
|
||||
uni.showModal({
|
||||
title: "提示",
|
||||
content: "是否确定要删除?",
|
||||
success: ret => {
|
||||
if (ret.confirm) {
|
||||
this.$instance.post("/app/appmarriagefuneralinfo/delete", null, {
|
||||
params: {ids: id}
|
||||
}).then(res => {
|
||||
if (res.code == 0) {
|
||||
this.$u.toast("删除成功");
|
||||
this.getList();
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
})
|
||||
},
|
||||
getList() {
|
||||
this.$instance.post("/app/appmarriagefuneralinfo/list", null, {
|
||||
params: {
|
||||
current: this.current,
|
||||
size: 10,
|
||||
}
|
||||
}).then(res => {
|
||||
if (res?.data) {
|
||||
this.list = this.current > 1 ? [...this.list, ...res.data.records] : res.data.records;
|
||||
|
||||
this.$nextTick(() => {
|
||||
this.pageShow = true
|
||||
})
|
||||
}
|
||||
|
||||
this.$hideLoading()
|
||||
}).catch(() => {
|
||||
this.$hideLoading()
|
||||
})
|
||||
},
|
||||
suport() {
|
||||
uni.navigateTo({
|
||||
url: "./marAdd"
|
||||
})
|
||||
}
|
||||
},
|
||||
|
||||
onReachBottom() {
|
||||
this.current++;
|
||||
this.getList();
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
|
||||
.padding {
|
||||
box-sizing: border-box;
|
||||
padding: 48px 32px 156px;
|
||||
|
||||
header {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
margin-bottom: 44px;
|
||||
|
||||
& > span {
|
||||
font-size: 38px;
|
||||
font-weight: 600;
|
||||
color: #333333;
|
||||
}
|
||||
|
||||
.total {
|
||||
margin-left: auto;
|
||||
font-size: 28px;
|
||||
font-weight: 400;
|
||||
color: #666666;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
|
||||
& > em {
|
||||
color: #4181FF;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.card {
|
||||
min-height: 308px;
|
||||
background: #FFFFFF;
|
||||
box-shadow: 0px 0px 8px 0px rgba(0, 0, 0, 0.02);
|
||||
border-radius: 16px;
|
||||
box-sizing: border-box;
|
||||
padding: 32px;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
justify-content: space-between;
|
||||
position: relative;
|
||||
margin-bottom: 24px;
|
||||
|
||||
.item {
|
||||
display: flex;
|
||||
margin-bottom: 8px;
|
||||
|
||||
.label {
|
||||
font-size: 26px;
|
||||
font-weight: 400;
|
||||
color: #999999;
|
||||
flex-shrink: 0;
|
||||
line-height: 36px;
|
||||
}
|
||||
|
||||
.value {
|
||||
font-size: 26px;
|
||||
font-weight: 400;
|
||||
color: #333333;
|
||||
margin-left: 32px;
|
||||
line-height: 36px;
|
||||
}
|
||||
}
|
||||
|
||||
.tag {
|
||||
width: 70px;
|
||||
height: 44px;
|
||||
background: #FF883C;
|
||||
border-radius: 8px;
|
||||
font-size: 26px;
|
||||
line-height: 40px;
|
||||
font-weight: 400;
|
||||
color: #FFFFFF;
|
||||
text-align: center;
|
||||
margin-top: 24px;
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
174
src/mods/conv/AppMarFuneral/marAdd.vue
Normal file
@@ -0,0 +1,174 @@
|
||||
<template>
|
||||
<div class="wrapper">
|
||||
<div class="card">
|
||||
<div class="form">
|
||||
<em>*</em>
|
||||
<label>类型</label>
|
||||
<div class="right" @click="show=true">
|
||||
<u-icon name="arrow-right" color="#999999" size="28"></u-icon>
|
||||
<span class="value" style="color: #999999;font-weight:normal;" v-if="!form.typeName">请选择</span>
|
||||
<span class="value" style="color: #333333;font-weight:normal;" v-else>{{ form.typeName }}</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="card">
|
||||
<div class="form border">
|
||||
<em>*</em>
|
||||
<label>事主姓名</label>
|
||||
<div class="right">
|
||||
<u-input trim placeholder="请输入" input-align="right" v-model="form.name"
|
||||
placeholder-style="color:#999;font-size: 16px;"></u-input>
|
||||
</div>
|
||||
</div>
|
||||
<div class="form border">
|
||||
<em>*</em>
|
||||
<label>联系方式</label>
|
||||
<div class="right">
|
||||
<u-input trim placeholder="请输入" input-align="right" v-model="form.phone"
|
||||
placeholder-style="color:#999;font-size: 16px;" maxlength="11"></u-input>
|
||||
</div>
|
||||
</div>
|
||||
<div class="form">
|
||||
<em>*</em>
|
||||
<label>活动地点</label>
|
||||
<div class="right">
|
||||
<u-input trim placeholder="请输入" input-align="right" v-model="form.address"
|
||||
placeholder-style="color:#999;font-size: 16px;" style="flex: 1;margin-left: 16px;"></u-input>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="card">
|
||||
<div class="form">
|
||||
<em></em>
|
||||
<label>详细描述</label>
|
||||
</div>
|
||||
<u-input type="textarea" trim v-model="form.content" placeholder="请输入详细描述信息…" maxlength="500"
|
||||
placeholder-style="color: #999999;font-size: 15px;"/>
|
||||
</div>
|
||||
<div class="card" style="padding-bottom: 20px">
|
||||
<div class="form">
|
||||
<label>图片上传
|
||||
<span>(最多9张)</span>
|
||||
</label>
|
||||
</div>
|
||||
<AiUploader :limit="9" v-model="form.files"></AiUploader>
|
||||
</div>
|
||||
<div class="btn-wrapper">
|
||||
<div class="btn" @click="submit" hover-class="text-hover">提交</div>
|
||||
</div>
|
||||
<u-select v-model="show" :list="$dict.getDict('marriageType')" value-name="dictValue"
|
||||
label-name="dictName" @confirm="confirm"></u-select>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
|
||||
export default {
|
||||
name: "marAdd",
|
||||
appName: "我要上报",
|
||||
data() {
|
||||
return {
|
||||
form: {
|
||||
type: "",
|
||||
typeName: "",
|
||||
name: "",
|
||||
phone: "",
|
||||
address: "",
|
||||
content: "",
|
||||
personType: 0,
|
||||
files: [],
|
||||
},
|
||||
show: false,
|
||||
flag: false
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
submit() {
|
||||
if (!!!this.form.typeName) return this.$u.toast("请选择类型");
|
||||
if (!!!this.form.name) return this.$u.toast("请输入事主姓名");
|
||||
if (!!!this.form.phone) return this.$u.toast("请输入联系方式");
|
||||
if (!!!this.form.address) return this.$u.toast("请输入活动地点");
|
||||
if (this.flag) return
|
||||
this.flag = true
|
||||
this.$loading()
|
||||
this.$instance.post("/app/appmarriagefuneralinfo/addOrUpdate", {
|
||||
...this.form
|
||||
}).then(res => {
|
||||
this.$hideLoading()
|
||||
this.flag = false
|
||||
if (res.code == 0) {
|
||||
uni.$emit('update')
|
||||
this.$u.toast("提交成功");
|
||||
setTimeout(_ => {
|
||||
uni.navigateBack();
|
||||
}, 500)
|
||||
}
|
||||
})
|
||||
},
|
||||
confirm(val) {
|
||||
this.form.type = val[0].value;
|
||||
this.form.typeName = val[0].label;
|
||||
},
|
||||
},
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.wrapper {
|
||||
padding-bottom: 156px;
|
||||
}
|
||||
|
||||
.card {
|
||||
box-sizing: border-box;
|
||||
padding-left: 32px;
|
||||
background-color: #fff;
|
||||
margin-bottom: 24px;
|
||||
|
||||
.form {
|
||||
height: 112px;
|
||||
background: #FFFFFF;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
|
||||
& > em {
|
||||
width: 16px;
|
||||
height: 44px;
|
||||
font-weight: 400;
|
||||
color: #FF4466;
|
||||
line-height: 54px;
|
||||
font-style: normal;
|
||||
margin-right: 8px;
|
||||
}
|
||||
|
||||
& > label {
|
||||
font-size: 32px;
|
||||
font-weight: 500;
|
||||
color: #666666;
|
||||
|
||||
& > span {
|
||||
font-size: 28px;
|
||||
font-weight: 400;
|
||||
color: #999999;
|
||||
}
|
||||
}
|
||||
|
||||
.right {
|
||||
flex: 1;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
flex-direction: row-reverse;
|
||||
margin-right: 32px;
|
||||
|
||||
.value {
|
||||
font-size: 34px;
|
||||
font-weight: 600;
|
||||
color: #333333;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.border {
|
||||
border-bottom: 1px solid #DDDDDD;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
385
src/mods/conv/AppPhotoAlbum/AppPhotoAlbum.vue
Normal file
@@ -0,0 +1,385 @@
|
||||
<template>
|
||||
<div class="photo" v-if="pageShow">
|
||||
<div class="header" :class="[isFixed ? 'header-active' : '']">
|
||||
<div class="status-bar" :style="{height: statusBarHeight + 'px'}"></div>
|
||||
<div class="nav-bar">
|
||||
<image src="/static/img/left.png" @click="back"/>
|
||||
<h2>乡村相册</h2>
|
||||
</div>
|
||||
</div>
|
||||
<div class="back-wrapper" @click="back" v-show="!isFixed" :style="{marginTop : statusBarHeight + 'px'}">
|
||||
<image src="/static/img/left.png"/>
|
||||
</div>
|
||||
<div class="photo-header">
|
||||
<image :src="coverImg" mode="aspectFill"/>
|
||||
<h2>{{ name }}</h2>
|
||||
</div>
|
||||
<div class="photo-info">
|
||||
<div class="photo-info__item">
|
||||
<h2>{{ info.total }}</h2>
|
||||
<span>照片</span>
|
||||
</div>
|
||||
<div class="photo-info__item">
|
||||
<h2>{{ info.thisMonth }}</h2>
|
||||
<span>本月</span>
|
||||
</div>
|
||||
<div class="photo-info__item">
|
||||
<h2>{{ info.lastMonth }}</h2>
|
||||
<span>上月</span>
|
||||
</div>
|
||||
<div class="photo-info__item">
|
||||
<h2>{{ info.thisYear }}</h2>
|
||||
<span>今年</span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="photo-list">
|
||||
<div class="photo-group" v-for="(group, index) in list" :key="index">
|
||||
<h2>{{ group.name }}</h2>
|
||||
<div class="photo-wrapper">
|
||||
<div class="photo-item" v-for="(item, i) in group.list" :key="i">
|
||||
<image :src="item.url" @click="preview(item.url)" mode="aspectFill"/>
|
||||
<div class="photo-item__text">
|
||||
<span>{{ item.createUserName }} 上传</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<AiEmpty v-if="!list.length" description="暂无照片"></AiEmpty>
|
||||
</div>
|
||||
<!-- <div class="btn-wrapper">
|
||||
<div class="btn" @click="upload" hover-class="text-hover">上传图片</div>
|
||||
</div> -->
|
||||
<AiLogin ref="login"/>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import {mapState} from 'vuex'
|
||||
|
||||
export default {
|
||||
name: "AppPhotoAlbum",
|
||||
appName: "乡村相册",
|
||||
customNavigation: true,
|
||||
data() {
|
||||
return {
|
||||
isFixed: false,
|
||||
statusBarHeight: 20,
|
||||
list: [],
|
||||
type: '',
|
||||
info: {},
|
||||
name: '',
|
||||
coverImg: '',
|
||||
imgList: [],
|
||||
hideStatus: false,
|
||||
pageShow: false
|
||||
}
|
||||
},
|
||||
|
||||
computed: {
|
||||
...mapState(['user', 'token'])
|
||||
},
|
||||
|
||||
onLoad(query) {
|
||||
this.type = query.type
|
||||
this.name = query.name
|
||||
this.coverImg = query.url
|
||||
this.statusBarHeight = uni.getSystemInfoSync().statusBarHeight
|
||||
|
||||
this.$loading()
|
||||
this.getList(query.type)
|
||||
this.getTotalInfo(query.type)
|
||||
},
|
||||
|
||||
onUnload() {
|
||||
// uni.$off('update')
|
||||
},
|
||||
|
||||
methods: {
|
||||
back() {
|
||||
uni.navigateBack({
|
||||
delta: 1
|
||||
})
|
||||
},
|
||||
|
||||
preview(url) {
|
||||
let imgs = []
|
||||
this.list.forEach(item => {
|
||||
imgs = [...imgs, ...item.list.map(v => v.url)]
|
||||
})
|
||||
|
||||
uni.previewImage({
|
||||
urls: imgs,
|
||||
current: url
|
||||
})
|
||||
},
|
||||
|
||||
upload() {
|
||||
if (!this.token) {
|
||||
this.$refs.login.show()
|
||||
|
||||
return false
|
||||
}
|
||||
|
||||
this.imgList = []
|
||||
this.hideStatus = false
|
||||
uni.chooseImage({
|
||||
count: this.limit,
|
||||
sizeType: ['compressed'],
|
||||
sourceType: ['album', 'camera'],
|
||||
success: (res) => {
|
||||
if (res.tempFilePaths.length > 9) {
|
||||
this.$toast(`图片不能超过9张`)
|
||||
|
||||
return false
|
||||
}
|
||||
|
||||
this.$loading('上传中')
|
||||
res.tempFilePaths.forEach((item, index) => {
|
||||
if (index === res.tempFilePaths.length - 1) {
|
||||
this.hideStatus = true
|
||||
}
|
||||
|
||||
this.$nextTick(() => {
|
||||
this.uploadFile(item, res.tempFilePaths.length)
|
||||
})
|
||||
})
|
||||
},
|
||||
})
|
||||
},
|
||||
|
||||
uploadFile(img, total) {
|
||||
uni.uploadFile({
|
||||
url: this.$instance.defaults.baseURL + '/admin/file/add',
|
||||
filePath: img,
|
||||
name: 'file',
|
||||
header: {
|
||||
'Content-Type': 'multipart/form-data',
|
||||
Authorization: uni.getStorageSync('token'),
|
||||
},
|
||||
success: (res) => {
|
||||
const data = JSON.parse(res.data)
|
||||
|
||||
if (data.code === 0) {
|
||||
this.imgList.push(data.data[0].split(';')[0])
|
||||
} else {
|
||||
this.$toast(data.msg)
|
||||
}
|
||||
},
|
||||
complete: () => {
|
||||
this.$nextTick(() => {
|
||||
if (this.imgList.length === total && this.hideStatus) {
|
||||
this.$instance.post(`/app/appvillagepicturealbum/addPictures`, {
|
||||
areaName: uni.getStorageSync('areaName'),
|
||||
areaId: uni.getStorageSync('areaId'),
|
||||
type: this.type,
|
||||
urlList: this.imgList
|
||||
}).then(res => {
|
||||
if (res.code == 0) {
|
||||
this.getList(this.type)
|
||||
this.getTotalInfo(this.type)
|
||||
uni.$emit('update')
|
||||
}
|
||||
this.$hideLoading()
|
||||
this.hideStatus = false
|
||||
})
|
||||
}
|
||||
})
|
||||
}
|
||||
})
|
||||
},
|
||||
|
||||
getTotalInfo(type) {
|
||||
this.$instance.post(`/app/appvillagepicturealbum/statistic?areaId=${uni.getStorageSync('areaId')}&type=${type}`).then(res => {
|
||||
if (res.code === 0) {
|
||||
this.info = res.data
|
||||
}
|
||||
})
|
||||
},
|
||||
|
||||
getList(type) {
|
||||
this.$instance.post(`/app/appvillagepicturealbum/queryAlbum?areaId=${uni.getStorageSync('areaId')}&type=${type}`).then(res => {
|
||||
if (res.code === 0) {
|
||||
this.list = Object.keys(res.data).map(v => {
|
||||
return {
|
||||
name: v,
|
||||
list: res.data[v]
|
||||
}
|
||||
})
|
||||
|
||||
this.$nextTick(() => {
|
||||
this.pageShow = true
|
||||
})
|
||||
}
|
||||
|
||||
this.$hideLoading()
|
||||
})
|
||||
}
|
||||
},
|
||||
|
||||
onPageScroll(params) {
|
||||
this.isFixed = params.scrollTop > 60;
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.photo {
|
||||
width: 100vw;
|
||||
overflow-x: hidden;
|
||||
padding-bottom: 130px;
|
||||
|
||||
* {
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
.back-wrapper {
|
||||
position: fixed;
|
||||
z-index: 11;
|
||||
left: 20px;
|
||||
top: 24px;
|
||||
width: 40px;
|
||||
height: 40px;
|
||||
|
||||
image {
|
||||
width: 40px;
|
||||
height: 40px;
|
||||
}
|
||||
}
|
||||
|
||||
.header {
|
||||
position: fixed;
|
||||
left: 0;
|
||||
top: 0;
|
||||
z-index: 0;
|
||||
width: 100%;
|
||||
opacity: 0;
|
||||
transition: all 0.2s ease;
|
||||
|
||||
&.header-active {
|
||||
z-index: 1111;
|
||||
opacity: 1;
|
||||
background: linear-gradient(180deg, #4670F5 0%, #4772F5 100%);
|
||||
}
|
||||
|
||||
.nav-bar {
|
||||
position: relative;
|
||||
height: 88px;
|
||||
line-height: 88px;
|
||||
color: #fff;
|
||||
font-size: 32px;
|
||||
text-align: center;
|
||||
|
||||
image {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
z-index: 1;
|
||||
width: 40px;
|
||||
height: 40px;
|
||||
padding: 24px 20px 0 20px;
|
||||
box-sizing: content-box;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.photo-header {
|
||||
position: relative;
|
||||
height: 400px;
|
||||
|
||||
image {
|
||||
width: 100%;
|
||||
height: 400px;
|
||||
filter: blur(2px);
|
||||
}
|
||||
|
||||
h2 {
|
||||
display: flex;
|
||||
position: absolute;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
top: 0;
|
||||
left: 0;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
z-index: 1;
|
||||
color: #fff;
|
||||
background: rgba(0, 0, 0, 0.1);
|
||||
font-size: 56px;
|
||||
}
|
||||
}
|
||||
|
||||
.photo-info {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
height: 168px;
|
||||
background: #FFFFFF;
|
||||
box-shadow: 0 8px 16px 0 rgba(0, 0, 0, 0.02);
|
||||
|
||||
& > div {
|
||||
flex: 1;
|
||||
text-align: center;
|
||||
|
||||
h2 {
|
||||
margin-bottom: 10px;
|
||||
font-weight: 600;
|
||||
font-size: 38px;
|
||||
color: #333333;
|
||||
}
|
||||
|
||||
span {
|
||||
color: #999999;
|
||||
font-size: 26px;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.photo-list {
|
||||
margin-top: 32px;
|
||||
padding: 0 32px;
|
||||
|
||||
h2 {
|
||||
margin-bottom: 32px;
|
||||
color: #333333;
|
||||
font-size: 38px;
|
||||
}
|
||||
|
||||
.photo-wrapper {
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
|
||||
.photo-item {
|
||||
position: relative;
|
||||
width: 328px;
|
||||
height: 328px;
|
||||
margin-right: 30px;
|
||||
margin-bottom: 32px;
|
||||
border-radius: 12px;
|
||||
overflow: hidden;
|
||||
|
||||
&:nth-of-type(2n) {
|
||||
margin-right: 0;
|
||||
}
|
||||
|
||||
.photo-item__text {
|
||||
position: absolute;
|
||||
bottom: 0;
|
||||
left: 0;
|
||||
z-index: 1;
|
||||
width: 100%;
|
||||
height: 80px;
|
||||
line-height: 80px;
|
||||
padding: 0 16px;
|
||||
color: #FFFFFF;
|
||||
font-size: 26px;
|
||||
background: linear-gradient(180deg, rgba(0, 0, 0, 0) 0%, rgba(0, 0, 0, 0.5) 100%);
|
||||
}
|
||||
|
||||
image {
|
||||
width: 328px;
|
||||
height: 328px;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
215
src/mods/conv/AppPhotoReport/AppPhotoReport.vue
Normal file
@@ -0,0 +1,215 @@
|
||||
<template>
|
||||
<div class="photo-list">
|
||||
<div class="photo-list__wrapper">
|
||||
|
||||
<div class="photo-item" v-for="(item, index) in list" :key="index">
|
||||
<u-swipe-action @content-click="$linkTo('./PhotoDetail?id=' + item.id)" :index="item.id"
|
||||
:options="itemOptions" @click="handleDelete">
|
||||
<div class="photo-item__top">
|
||||
<h2>{{ item.content }}</h2>
|
||||
<div class="photo-item__top--info">
|
||||
<div class="photo-item__top--info-item">
|
||||
<label>事件类型</label>
|
||||
<span>{{ item.groupName }}</span>
|
||||
</div>
|
||||
<div class="photo-item__top--info-item">
|
||||
<label>所属网格</label>
|
||||
<span>{{ item.girdName }}</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="photo-item__bottom flex">
|
||||
<div class="flex fill">
|
||||
<i :class="'status-' + item.eventStatus"></i>
|
||||
<span :class="'status-' + item.eventStatus">{{ item.statusName }}</span>
|
||||
</div>
|
||||
<AiEvaluation :bid="item.id" v-if="item.eventStatus>1">
|
||||
<div class="itemBtn">去评价</div>
|
||||
<div slot="finish" class="finish">已评价</div>
|
||||
</AiEvaluation>
|
||||
</div>
|
||||
</u-swipe-action>
|
||||
</div>
|
||||
<AiEmpty v-if="!list.length"/>
|
||||
</div>
|
||||
<div class="btn-wrapper">
|
||||
<div class="btn" @click="toReport" hover-class="text-hover">我要上报</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import {mapState} from 'vuex'
|
||||
|
||||
export default {
|
||||
name: "AppPhotoReport",
|
||||
appName: "随手拍",
|
||||
data() {
|
||||
return {
|
||||
list: [],
|
||||
current: 1,
|
||||
total: 0,
|
||||
itemOptions: [
|
||||
{text: '删除', style: {backgroundColor: '#f46'}}
|
||||
]
|
||||
}
|
||||
},
|
||||
|
||||
computed: {
|
||||
...mapState(['user'])
|
||||
},
|
||||
|
||||
onShow() {
|
||||
this.current = 1
|
||||
this.getList()
|
||||
},
|
||||
onLoad() {
|
||||
this.$dict.load(['clapEventStatus'])
|
||||
},
|
||||
methods: {
|
||||
toReport() {
|
||||
this.$linkTo('./PhotoForm')
|
||||
},
|
||||
getList() {
|
||||
if (this.current == 1) {
|
||||
//当current=1时,意味着重新刷新数据
|
||||
} else if (this.list.length >= this.total && this.total > 0) {
|
||||
return //当数据总量和列表总量一样时,不用再加载数据
|
||||
}
|
||||
this.$loading()
|
||||
this.$instance.post(`/app/appclapeventinfo/listByWxApplet`, null, {
|
||||
params: {
|
||||
current: this.current, size: 15
|
||||
}
|
||||
}).then(res => {
|
||||
if (res?.data) {
|
||||
const list = res.data.records.map(v => ({...v, statusName: this.$dict.getLabel('clapEventStatus', v.eventStatus)}))
|
||||
this.list = this.current == 1 ? list : [this.list, list].flat()
|
||||
this.total = res.data.total
|
||||
this.current++
|
||||
}
|
||||
}).finally(() => uni.hideLoading())
|
||||
},
|
||||
handleDelete(ids) {
|
||||
this.$dialog.confirm({content: "是否要进行删除?"}).then(() => {
|
||||
this.$instance.post("/app/appclapeventinfo/delete", null, {
|
||||
params: {ids}
|
||||
}).then(res => {
|
||||
if (res?.code == 0) {
|
||||
this.$u.toast("删除成功!")
|
||||
this.current = 1
|
||||
this.getList()
|
||||
}
|
||||
})
|
||||
}).catch(() => 0)
|
||||
}
|
||||
},
|
||||
onReachBottom() {
|
||||
this.getList()
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss">
|
||||
.photo-list {
|
||||
padding: 24px 0 150px 0;
|
||||
|
||||
.photo-item {
|
||||
width: 686px;
|
||||
margin: 0 32px 24px;
|
||||
background: #FFFFFF;
|
||||
box-shadow: 0 0 8px 0 rgba(0, 0, 0, 0.02);
|
||||
border-radius: 16px;
|
||||
overflow: hidden;
|
||||
|
||||
.photo-item__top {
|
||||
padding: 32px;
|
||||
text-align: justify;
|
||||
|
||||
h2 {
|
||||
margin-bottom: 32px;
|
||||
line-height: 1.4;
|
||||
color: #333333;
|
||||
font-size: 32px;
|
||||
font-weight: 600;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
display: -webkit-box;
|
||||
-webkit-line-clamp: 2;
|
||||
-webkit-box-orient: vertical;
|
||||
}
|
||||
|
||||
.photo-item__top--info-item {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
|
||||
&:last-child {
|
||||
margin-bottom: 8px;
|
||||
}
|
||||
|
||||
label {
|
||||
margin-right: 32px;
|
||||
color: #999999;
|
||||
font-size: 26px;
|
||||
}
|
||||
|
||||
span {
|
||||
color: #333333;
|
||||
font-size: 26px;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.photo-item__bottom {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
height: 104px;
|
||||
padding: 0 32px;
|
||||
border-top: 1px solid #DDDDDD;
|
||||
|
||||
i {
|
||||
width: 8px;
|
||||
height: 8px;
|
||||
margin-right: 8px;
|
||||
border-radius: 50%;
|
||||
background: #FF883C;
|
||||
}
|
||||
|
||||
.itemBtn {
|
||||
border: 1px solid #4181FF;
|
||||
border-radius: 8px;
|
||||
color: #4181FF;
|
||||
padding: 8px 22px;
|
||||
|
||||
|
||||
}
|
||||
|
||||
.finish {
|
||||
color: #42D784;
|
||||
font-size: 28px;
|
||||
}
|
||||
|
||||
span {
|
||||
color: #FF883C;
|
||||
font-size: 28px;
|
||||
background: transparent !important;
|
||||
}
|
||||
|
||||
.status-1 {
|
||||
color: #1AAAFF;
|
||||
background: #1AAAFF;
|
||||
}
|
||||
|
||||
.status-2 {
|
||||
color: #42D784;
|
||||
background: #42D784;
|
||||
}
|
||||
|
||||
.status-3 {
|
||||
color: #FF4466;
|
||||
background: #FF4466;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
181
src/mods/conv/AppPhotoReport/PhotoDetail.vue
Normal file
@@ -0,0 +1,181 @@
|
||||
<template>
|
||||
<div class="photo-detail">
|
||||
<AiGroup noBorder>
|
||||
<h2>{{ info.content }}</h2>
|
||||
<div class="status-name" :class="detailStatus.cls" v-text="detailStatus.label"/>
|
||||
</AiGroup>
|
||||
<AiGroup description noBorder labelColor="#999">
|
||||
<AiItem label="事件类型" :value="info.groupName"/>
|
||||
<AiItem label="所属网格" :value="info.girdName"/>
|
||||
<AiItem label="上报时间" :value="info.createTime"/>
|
||||
<AiItem label="照片" top-label>
|
||||
<div class="flex wrap">
|
||||
<image class="fill imageItem" v-for="(item, index) in info.files" @click="preview(item.url)" :key="index" :src="item.url"/>
|
||||
</div>
|
||||
<span v-if="!hasFiles">暂无照片</span>
|
||||
</AiItem>
|
||||
</AiGroup>
|
||||
<u-gap height="24"/>
|
||||
<AiGroup title="处理详情" v-if="info.eventStatus > 1" description noBorder labelColor="#999">
|
||||
<AiItem label="处理结果" top-label :value="result.doExplain"/>
|
||||
<AiItem label="照片" top-label>
|
||||
<div class="flex wrap">
|
||||
<image class="fill imageItem" v-for="(item, index) in result.files" @click="preview(item.url)" :key="index" :src="item.url"/>
|
||||
</div>
|
||||
<span v-if="!hasFiles">暂无照片</span>
|
||||
</AiItem>
|
||||
</AiGroup>
|
||||
<u-gap height="24"/>
|
||||
<u-tabs :list="evaluation && evaluation.id ? [{name:'办理进度'},{name:'我的评价'}] : [{name:'办理进度'}] " :current="currentTab" @change="v=>currentTab=v"/>
|
||||
<u-gap height="24"/>
|
||||
<AiGroup noBorder v-if="currentTab=='0'">
|
||||
<AiStep v-for="(item,i) in process" :key="item.id" :index="i">
|
||||
<div class="flex start">
|
||||
<div class="fill stepTitle" v-text="item.systemExplain"/>
|
||||
<div class="color-999 mar-r32 stepTime" v-text="item.doTime"/>
|
||||
</div>
|
||||
<div v-if="item.doExplain" class="stepContent mar-t8" v-text="item.doExplain"/>
|
||||
<u-gap height="48"/>
|
||||
</AiStep>
|
||||
</AiGroup>
|
||||
<AiEvaluation v-if="currentTab=='1'" :bid="info.id" type="show"/>
|
||||
<AiEvaluation v-if="info.eventStatus > 1" v-model="evaluation" class="fixed-bottom bg-fff" :bid="info.id">
|
||||
<div class="bottomBtn">去评价</div>
|
||||
</AiEvaluation>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
appName: "随手拍详情",
|
||||
data() {
|
||||
return {
|
||||
info: {},
|
||||
result: {},
|
||||
currentTab: 0,
|
||||
evaluation: {}
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
detailStatus: v => {
|
||||
const status = !v.evaluation.id ? v.info.eventStatus : 'evaluation'
|
||||
return {
|
||||
cls: 'status-' + status,
|
||||
label: !v.evaluation.id ? v.$dict.getLabel('clapEventStatus', v.info.eventStatus) : "已评价"
|
||||
}
|
||||
},
|
||||
process() {
|
||||
const list = this.info.processList
|
||||
if (this.evaluation.id) {
|
||||
const {id, createUserName, score, createTime: doTime, rateText: doExplain} = this.evaluation
|
||||
list.splice(0, 0, {
|
||||
id, doTime, doExplain,
|
||||
systemExplain: `${createUserName}完成评价 (${score}星评价)`
|
||||
})
|
||||
}
|
||||
return list
|
||||
},
|
||||
hasFiles:v=>v.result.files?.length>0
|
||||
},
|
||||
onShow() {
|
||||
this.getInfo()
|
||||
},
|
||||
onLoad(query) {
|
||||
this.getInfo(query.id)
|
||||
this.$dict.load(['clapEventStatus'])
|
||||
},
|
||||
methods: {
|
||||
getInfo(id = this.info.id) {
|
||||
this.$loading()
|
||||
this.$instance.post(`/app/appclapeventinfo/queryDetailById?id=${id}`).then(res => {
|
||||
if (res?.data) {
|
||||
this.info = res.data
|
||||
if (res.data.eventStatus > 1) {
|
||||
this.result = res.data.processList[0]
|
||||
}
|
||||
}
|
||||
}).finally(() => this.$hideLoading())
|
||||
},
|
||||
previewResult(url) {
|
||||
uni.previewImage({
|
||||
urls: this.result.files.map(v => v.url),
|
||||
current: url
|
||||
})
|
||||
},
|
||||
|
||||
preview(url) {
|
||||
uni.previewImage({
|
||||
urls: this.info.files.map(v => v.url),
|
||||
current: url
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss">
|
||||
.photo-detail {
|
||||
padding: 32px 0 160px;
|
||||
margin-bottom: 60px;
|
||||
background: #fff;
|
||||
|
||||
h2 {
|
||||
line-height: 1.3;
|
||||
margin-bottom: 26px;
|
||||
color: #333333;
|
||||
text-align: justify;
|
||||
font-size: 40px;
|
||||
}
|
||||
|
||||
::v-deep.stepTitle {
|
||||
min-height: 44px;
|
||||
font-family: PingFangSC-Regular;
|
||||
font-weight: 400;
|
||||
font-size: 32px;
|
||||
}
|
||||
|
||||
.stepTime {
|
||||
line-height: 44px;
|
||||
}
|
||||
|
||||
.stepContent {
|
||||
color: #343D65;
|
||||
}
|
||||
|
||||
.status-name {
|
||||
width: 96px;
|
||||
height: 44px;
|
||||
line-height: 44px;
|
||||
margin-bottom: 20px;
|
||||
text-align: center;
|
||||
background: #FF883C;
|
||||
color: #fff;
|
||||
font-size: 26px;
|
||||
border-radius: 8px;
|
||||
|
||||
&.status-1, &.status-evaluation {
|
||||
background: #1AAAFF;
|
||||
}
|
||||
|
||||
&.status-2 {
|
||||
background: #42D784;
|
||||
}
|
||||
|
||||
&.status-3 {
|
||||
background: #FF4466;
|
||||
}
|
||||
}
|
||||
|
||||
.imageItem {
|
||||
min-width: 30%;
|
||||
height: 30vw;
|
||||
flex-shrink: 0;
|
||||
margin-right: 16px;
|
||||
margin-bottom: 16px;
|
||||
|
||||
&:nth-of-type(3n) {
|
||||
margin-right: 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
347
src/mods/conv/AppPhotoReport/PhotoForm.vue
Normal file
@@ -0,0 +1,347 @@
|
||||
<template>
|
||||
<div class="album">
|
||||
<div class="form-item__group">
|
||||
<div class="form-item">
|
||||
<div class="form-item__wrapper">
|
||||
<div class="form-item__title">
|
||||
<i>*</i>
|
||||
<h2>事件类型</h2>
|
||||
</div>
|
||||
<div class="form-item__right">
|
||||
<AiSelect :list="dictList" v-model="form.groupId" placeholder="请选择"></AiSelect>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-item form-item__textarea">
|
||||
<div class="form-item__wrapper">
|
||||
<div class="form-item__title">
|
||||
<i>*</i>
|
||||
<h2>事件描述</h2>
|
||||
</div>
|
||||
<div class="form-item__right">
|
||||
<textarea v-model="form.content" :maxlength="500" placeholder="请简要描述事件…"></textarea>
|
||||
<!-- <u-input style="width: 100%;" :height="200" v-model="value" type="textarea" :maxlength="500" :border="border" placeholder="请简要描述事件…" /> -->
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-item__group">
|
||||
<div class="form-item">
|
||||
<div class="form-item__wrapper">
|
||||
<div class="form-item__title">
|
||||
<i>*</i>
|
||||
<h2>上报位置</h2>
|
||||
</div>
|
||||
<div class="form-item__right" @click="chooseAddress">
|
||||
<span v-if="form.address">{{ form.address }}</span>
|
||||
<i v-else>请选择</i>
|
||||
<u-icon name="arrow-right" color="#ddd"/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-item">
|
||||
<div class="form-item__wrapper">
|
||||
<div class="form-item__title">
|
||||
<i>*</i>
|
||||
<h2>所属网格</h2>
|
||||
</div>
|
||||
<div class="form-item__right">
|
||||
<AiPagePicker type="gird" v-model="form.girdId" :params="{formType:2}" @select="handleSelectGrid" nodeKey="id">
|
||||
<AiMore v-model="form.girdName"/>
|
||||
</AiPagePicker>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-item__group">
|
||||
<div class="form-item form-item__imgs">
|
||||
<div class="form-item__wrapper">
|
||||
<div class="form-item__title">
|
||||
<i style="opacity: 0;">*</i>
|
||||
<h2>图片上传</h2>
|
||||
<span>(最多9张)</span>
|
||||
</div>
|
||||
<AiUploader v-model="form.files" :limit="9"></AiUploader>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-item__group">
|
||||
<div class="form-item">
|
||||
<div class="form-item__wrapper">
|
||||
<div class="form-item__title">
|
||||
<i>*</i>
|
||||
<h2>姓名</h2>
|
||||
</div>
|
||||
<div class="form-item__right">
|
||||
<input placeholder="请输入" v-model="form.name" :maxlength="20"/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-item">
|
||||
<div class="form-item__wrapper">
|
||||
<div class="form-item__title">
|
||||
<i>*</i>
|
||||
<h2>联系方式</h2>
|
||||
</div>
|
||||
<div class="form-item__right">
|
||||
<input placeholder="请输入" v-model="form.phone" :maxlength="11"/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="btn-wrapper">
|
||||
<div class="btn" hover-class="text-hover" @click="submit">提交</div>
|
||||
</div>
|
||||
<AiLogin ref="login" @success="getAuth()"/>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import {mapActions, mapState} from 'vuex'
|
||||
|
||||
export default {
|
||||
appName: "上报随手拍",
|
||||
data() {
|
||||
return {
|
||||
form: {
|
||||
content: '',
|
||||
lat: '',
|
||||
lng: '',
|
||||
address: '',
|
||||
name: '',
|
||||
phone: '',
|
||||
groupId: '',
|
||||
groupName: '',
|
||||
girdName: '',
|
||||
girdId: '',
|
||||
files: []
|
||||
},
|
||||
dictList: [],
|
||||
flag: false
|
||||
}
|
||||
},
|
||||
|
||||
computed: {
|
||||
...mapState(['user', 'token'])
|
||||
},
|
||||
|
||||
onLoad() {
|
||||
this.getDict()
|
||||
this.form.phone = this.user.phone
|
||||
this.form.name = this.user.realName || ''
|
||||
if (!this.token) {
|
||||
this.$refs.login.show();
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
...mapActions(['getUserInfo']),
|
||||
chooseAddress() {
|
||||
uni.authorize({
|
||||
scope: 'scope.userLocation',
|
||||
success: () => {
|
||||
uni.chooseLocation({
|
||||
success: res => {
|
||||
console.log(res)
|
||||
this.form.address = res.name
|
||||
this.form.lat = res.latitude
|
||||
this.form.lng = res.longitude
|
||||
}
|
||||
})
|
||||
},
|
||||
fail: () => {
|
||||
this.$dialog.confirm({
|
||||
content: '您未授权定位权限,无法选择位置'
|
||||
}).then(() => {
|
||||
wx.openSetting({
|
||||
success: res => {
|
||||
if (!res.authSetting['scope.userLocation']) {
|
||||
this.$dialog.alert({
|
||||
content: '您未授权定位权限,无法选择位置'
|
||||
}).then(() => {
|
||||
})
|
||||
} else {
|
||||
console.log('设置定位权限')
|
||||
}
|
||||
}
|
||||
})
|
||||
})
|
||||
}
|
||||
})
|
||||
},
|
||||
getDict() {
|
||||
this.$instance.post(`/app/appclapeventgroup/list?current=1&size=100000`, null, {
|
||||
withoutToken: true,
|
||||
}).then(res => {
|
||||
if (res.code == 0) {
|
||||
this.dictList = res.data.records.map(v => {
|
||||
return {
|
||||
value: v.id,
|
||||
label: v.groupName
|
||||
}
|
||||
})
|
||||
}
|
||||
})
|
||||
},
|
||||
submit() {
|
||||
if (!this.token) {
|
||||
return this.$refs.login.show();
|
||||
}
|
||||
if (!this.form.groupId) {
|
||||
return this.$toast('请选择事件类型')
|
||||
}
|
||||
|
||||
if (!this.form.content) {
|
||||
return this.$toast('请输入事件描述')
|
||||
}
|
||||
if (!this.form.address) {
|
||||
return this.$toast('请选择上报位置')
|
||||
}
|
||||
|
||||
if (!this.form.name) {
|
||||
return this.$toast('请输入上报人姓名')
|
||||
}
|
||||
|
||||
if (!this.form.phone) {
|
||||
return this.$toast('请输入上报人联系方式')
|
||||
}
|
||||
if (!this.form.girdId) {
|
||||
return this.$toast('请选择所属网格')
|
||||
}
|
||||
if (this.flag) return
|
||||
this.flag = true
|
||||
|
||||
this.$loading()
|
||||
this.$instance.post(`/app/appclapeventinfo/addOrUpdate`, {
|
||||
...this.form,
|
||||
openid: this.user.openid,
|
||||
portrait: this.user.avatarUrl,
|
||||
files: this.form.files,
|
||||
groupName: this.dictList.filter(v => v.value === this.form.groupId)[0].label
|
||||
}).then(res => {
|
||||
this.$hideLoading()
|
||||
this.flag = false
|
||||
if (res.code == 0) {
|
||||
uni.$emit('update')
|
||||
setTimeout(() => {
|
||||
uni.redirectTo({
|
||||
url: './PhotoResult?id=' + res.data.id
|
||||
})
|
||||
}, 400)
|
||||
}
|
||||
this.$hideLoading()
|
||||
})
|
||||
},
|
||||
handleSelectGrid(v) {
|
||||
this.form.girdName = v.girdName
|
||||
},
|
||||
getAuth() {
|
||||
this.$nextTick(() => {
|
||||
this.token && this.getUserInfo().then(() => {
|
||||
this.getDict()
|
||||
})
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss">
|
||||
.album {
|
||||
padding-bottom: 140px;
|
||||
|
||||
.form-item__group {
|
||||
margin-bottom: 24px;
|
||||
background: #fff;
|
||||
}
|
||||
|
||||
.form-item {
|
||||
padding-left: 32px;
|
||||
|
||||
.form-item__wrapper {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
height: 128px;
|
||||
padding-right: 28px;
|
||||
border-bottom: 1px solid #DDDDDD;
|
||||
|
||||
input {
|
||||
flex: 1;
|
||||
height: 100%;
|
||||
text-align: right;
|
||||
padding-right: 10px;
|
||||
}
|
||||
|
||||
.form-item__right {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
font-size: 32px;
|
||||
|
||||
span {
|
||||
max-width: 400px;
|
||||
margin-right: 8px;
|
||||
color: #333333;
|
||||
overflow: hidden;
|
||||
white-space: nowrap;
|
||||
text-overflow: ellipsis;
|
||||
}
|
||||
|
||||
i {
|
||||
margin-right: 8px;
|
||||
color: #999999;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
&:last-child {
|
||||
.form-item__wrapper {
|
||||
border-bottom: none;
|
||||
}
|
||||
}
|
||||
|
||||
.form-item__title {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
|
||||
i {
|
||||
font-size: 32px;
|
||||
color: #FF4466;
|
||||
}
|
||||
|
||||
span {
|
||||
font-size: 28px;
|
||||
color: #999999;
|
||||
}
|
||||
|
||||
h2 {
|
||||
padding: 0 4px;
|
||||
font-weight: 600;
|
||||
font-size: 32px;
|
||||
color: #333333;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
&.form-item__imgs, &.form-item__textarea {
|
||||
.form-item__wrapper {
|
||||
display: block;
|
||||
height: auto;
|
||||
padding-bottom: 32px;
|
||||
}
|
||||
|
||||
textarea {
|
||||
width: 100%;
|
||||
height: 160px;
|
||||
}
|
||||
|
||||
.form-item__title {
|
||||
padding: 32px 0;
|
||||
}
|
||||
|
||||
.form-item__right {
|
||||
padding-left: 18px;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
64
src/mods/conv/AppPhotoReport/PhotoResult.vue
Normal file
@@ -0,0 +1,64 @@
|
||||
<template>
|
||||
<div class="result">
|
||||
<image src="/static/img/result.png" />
|
||||
<h2>上报成功!</h2>
|
||||
<div class="result-btn" hover-class="text-hover" @click="back">前往查看</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
appName:"上报随手拍",
|
||||
data () {
|
||||
return {
|
||||
id: ''
|
||||
}
|
||||
},
|
||||
|
||||
onLoad (query) {
|
||||
this.id = query.id
|
||||
},
|
||||
|
||||
methods: {
|
||||
back () {
|
||||
uni.redirectTo({
|
||||
url: './PhotoDetail?id=' + this.id
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss">
|
||||
.result {
|
||||
min-height: 100vh;
|
||||
padding-top: 160px;
|
||||
box-sizing: border-box;
|
||||
text-align: center;
|
||||
background: #fff;
|
||||
|
||||
image {
|
||||
width: 220px;
|
||||
height: 220px;
|
||||
}
|
||||
|
||||
h2 {
|
||||
margin: 32px 0 80px;
|
||||
font-weight: 600;
|
||||
font-size: 40px;
|
||||
color: #333;
|
||||
}
|
||||
|
||||
.result-btn {
|
||||
width: 320px;
|
||||
height: 88px;
|
||||
line-height: 88px;
|
||||
margin: 0 auto;
|
||||
text-align: center;
|
||||
background: #4181FF;
|
||||
color: #fff;
|
||||
font-size: 34px;
|
||||
border-radius: 16px;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
424
src/mods/conv/AppResidentAssistant/AppResidentAssistant.vue
Normal file
@@ -0,0 +1,424 @@
|
||||
<template>
|
||||
<div class="AppResidentAssistant">
|
||||
<u-navbar title="村长Copilot" title-color="#000" title-width="300" title-size="32" :title-bold="true" :background="backgroundNavbar"></u-navbar>
|
||||
<div class="service-content">
|
||||
<div class="text-content">
|
||||
<div class="text-left">
|
||||
<div>嘿,你好呀!</div>
|
||||
<p>我是您的<span>「专属助手」</span>,</p>
|
||||
<p>有什么问题都可以问我哟~</p>
|
||||
</div>
|
||||
<img src="https://cdn.cunwuyun.cn/wechat/biaopin/residentAssistant/service.png" alt="" class="service-img">
|
||||
</div>
|
||||
</div>
|
||||
<!-- <scroll-view scroll-y="true" class="scroll-Y" @scroll="scroll"> -->
|
||||
<div class="list-content">
|
||||
<div :class="item.userType == 1 ? 'item-left' : 'item-right'" v-for="(item, index) in messageList" :key="index">
|
||||
<div class="item" :class="'item'+index">
|
||||
<div class="img-div" v-if="item.sdkFileUrl">
|
||||
<u-icon name="play-circle" :color="item.userType == 0 ? '#fff' : '#A8ADAE'" size="52" v-if="!item.isPlay" @click="play(item.sdkFileUrl, index)"></u-icon>
|
||||
<u-icon name="pause-circle" :color="item.userType == 0 ? '#fff' : '#A8ADAE'" size="52" v-else @click="playStop(index)"></u-icon>
|
||||
<img src="https://cdn.cunwuyun.cn/wechat/biaopin/residentAssistant/recording-white.png" alt="" v-if="item.userType == 0">
|
||||
<img src="https://cdn.cunwuyun.cn/wechat/biaopin/residentAssistant/recording-gray.png" alt="" v-else>
|
||||
</div>
|
||||
<p>{{item.content || ''}}</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<!-- </scroll-view> -->
|
||||
<div class="fixed-bottom">
|
||||
<div class="type-text" v-if="type == 'text'">
|
||||
<u-input type="text" placeholder="输入您的问题…" height="80" input-align="left" :clearable="false" placeholder-style="color:#666;" v-model="content" @confirm="sendMsg"></u-input>
|
||||
<img src="https://cdn.cunwuyun.cn/wechat/biaopin/residentAssistant/send.png" alt="" v-if="content.length" @click="sendMsg">
|
||||
<img src="https://cdn.cunwuyun.cn/wechat/biaopin/residentAssistant/microphone-btn.png" alt="" v-else @click="microPhone">
|
||||
</div>
|
||||
<div class="type-record" v-else>
|
||||
<img src="https://cdn.cunwuyun.cn/wechat/biaopin/residentAssistant/keyboard-btn.png" alt="" class="keyboard-btn" @click="keyboardClick">
|
||||
<div v-if="!isStart" @click="startRecord">
|
||||
<p>点击开始录音</p>
|
||||
<img src="https://cdn.cunwuyun.cn/wechat/biaopin/residentAssistant/record-btn.png" alt="" class="record-btn">
|
||||
</div>
|
||||
<div v-else @click="endRecord">
|
||||
<p>正在录音中</p>
|
||||
<div class="tips-text">点击下方,停止录音</div>
|
||||
<img src="https://cdn.cunwuyun.cn/wechat/biaopin/residentAssistant/shengbo.gif" alt="" class="recording">
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
|
||||
import {mapState} from "vuex";
|
||||
const recorderManager = uni.getRecorderManager();
|
||||
const innerAudioContext = uni.createInnerAudioContext();
|
||||
innerAudioContext.autoplay = true;
|
||||
export default {
|
||||
customNavigation: true,
|
||||
enablePullDownRefresh: true,
|
||||
name: 'AppResidentAssistant',
|
||||
appName: '村长Copilot',
|
||||
data() {
|
||||
return {
|
||||
backgroundNavbar: {
|
||||
background: 'url(https://cdn.sinoecare.com/i/2024/08/06/66b1c9696650b.png) no-repeat',
|
||||
backgroundSize: 'cover',
|
||||
},
|
||||
recorderManager: null,
|
||||
type: 'text',
|
||||
isStart: false,
|
||||
content: '',
|
||||
isFlag: false,
|
||||
voiceUrl: '',
|
||||
voiceId: '',
|
||||
messageList: [
|
||||
// {
|
||||
// userType: 0,
|
||||
// sdkFileUrl: 'http://test87ftp.cunwuyun.cn/20240104/output.mp3',
|
||||
// isPlay: false
|
||||
// }
|
||||
],
|
||||
current: 1,
|
||||
pages: 2
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
...mapState(['user']),
|
||||
},
|
||||
onLoad() {
|
||||
recorderManager.onStop((res)=> {
|
||||
console.log(res)
|
||||
this.upLoad(res.tempFilePath)
|
||||
});
|
||||
this.getHistoryList()
|
||||
},
|
||||
onPullDownRefresh() {
|
||||
if(this.current > this.pages) {
|
||||
return this.$u.toast('没有更多记录')
|
||||
}
|
||||
this.current = this.current + 1
|
||||
this.getHistoryList()
|
||||
},
|
||||
methods: {
|
||||
startRecord() {
|
||||
if(this.isFlag) return
|
||||
this.isStart = true
|
||||
uni.authorize({
|
||||
scope: 'scope.record',
|
||||
success() {
|
||||
// const options = {
|
||||
// duration: 10000,
|
||||
// sampleRate: 44100,
|
||||
// numberOfChannels: 1,
|
||||
// encodeBitRate: 192000,
|
||||
// format: 'aac',
|
||||
// frameSize: 50
|
||||
// }
|
||||
const options = {
|
||||
duration: 60000,
|
||||
sampleRate: 16000,
|
||||
format: 'mp3'
|
||||
}
|
||||
recorderManager.start(options);
|
||||
|
||||
},
|
||||
fail(err) {
|
||||
this.isStart = false
|
||||
uni.showModal({
|
||||
title: "提示",
|
||||
content: "您的录音权限未开启",
|
||||
})
|
||||
}
|
||||
})
|
||||
},
|
||||
endRecord() {
|
||||
this.isStart = false
|
||||
setTimeout(() => {
|
||||
this.isFlag = false
|
||||
}, 6000)
|
||||
recorderManager.stop();
|
||||
},
|
||||
microPhone() {
|
||||
this.type = 'voice'
|
||||
this.isStart = false
|
||||
},
|
||||
keyboardClick() {
|
||||
if(this.isStart) return
|
||||
this.type = 'text'
|
||||
this.content = ''
|
||||
},
|
||||
upLoad(filePath) {
|
||||
return new Promise((resolve, reject) => {
|
||||
uni.uploadFile({
|
||||
url: `${this.$instance.defaults.baseURL}/admin/file/add`,
|
||||
filePath,
|
||||
fileType: 'audio',
|
||||
name: 'file',
|
||||
success: uploadFileRes => {
|
||||
this.voiceUrl = JSON.parse(uploadFileRes.data).data[0].split(';')[0]
|
||||
this.voiceId = JSON.parse(uploadFileRes.data).data[0].split(';')[1]
|
||||
this.sendVoice()
|
||||
resolve(uploadFileRes)
|
||||
},
|
||||
fail: err => {
|
||||
reject(err)
|
||||
}
|
||||
})
|
||||
})
|
||||
},
|
||||
sendMsg() {
|
||||
this.$loading()
|
||||
this.$instance.post("/app/appaigccopilotinfo/add", {content: this.content, appType: 0}).then(res => {
|
||||
if(res.code == 0) {
|
||||
this.content = ''
|
||||
this.messageList.push(res.data[0])
|
||||
this.messageList.push(res.data[1])
|
||||
this.$nextTick(() => {
|
||||
uni.pageScrollTo({
|
||||
duration: 300,
|
||||
selector: `.item${this.messageList.length-1}`
|
||||
});
|
||||
})
|
||||
this.$hideLoading()
|
||||
}
|
||||
})
|
||||
},
|
||||
sendVoice() {
|
||||
this.$loading()
|
||||
this.$instance.post("/app/appaigccopilotinfo/add", {sdkFileUrl: this.voiceUrl, fileId: this.voiceId, appType: 0}).then(res => {
|
||||
if(res.code == 0) {
|
||||
this.voiceUrl = ''
|
||||
this.voiceId = ''
|
||||
res.data.map((item) => {
|
||||
if(item.sdkFileUrl) {
|
||||
item.isPlay = false
|
||||
}
|
||||
})
|
||||
this.messageList.push(res.data[0])
|
||||
this.messageList.push(res.data[1])
|
||||
uni.pageScrollTo({
|
||||
duration: 300,
|
||||
selector: `.item${this.messageList.length-1}`
|
||||
});
|
||||
this.$hideLoading()
|
||||
}
|
||||
})
|
||||
},
|
||||
getHistoryList() {
|
||||
this.$loading()
|
||||
this.$instance.post(`/app/appaigccopilotinfo/list?current=${this.current}&size=10`).then(res => {
|
||||
if(res.code == 0 && res.data.records.length) {
|
||||
res.data.records.map((item) => {
|
||||
if(item.sdkFileUrl) {
|
||||
item.isPlay = false
|
||||
}
|
||||
})
|
||||
this.messageList = this.current == 1 ? res.data.records : [...res.data.records, ...this.messageList]
|
||||
var idPage = res.data.records.length-1
|
||||
this.$nextTick(() => {
|
||||
uni.pageScrollTo({
|
||||
duration: 300,
|
||||
selector: this.current == 1 ? `.item${this.messageList.length-1}` : `.item${idPage}`
|
||||
});
|
||||
})
|
||||
this.pages = res.data.pages
|
||||
this.$hideLoading()
|
||||
}
|
||||
})
|
||||
},
|
||||
play(src, index) {
|
||||
innerAudioContext.stop();
|
||||
this.messageList.map((item) => {
|
||||
if(item.sdkFileUrl) {
|
||||
item.isPlay = false
|
||||
}
|
||||
})
|
||||
this.messageList[index].isPlay = true
|
||||
innerAudioContext.src = src;
|
||||
|
||||
this.$nextTick(() => {
|
||||
innerAudioContext.play();
|
||||
})
|
||||
innerAudioContext.onEnded(() => {
|
||||
this.messageList[index].isPlay = false
|
||||
})
|
||||
},
|
||||
playStop(index) {
|
||||
innerAudioContext.stop();
|
||||
innerAudioContext.onStop(() => {
|
||||
this.messageList[index].isPlay = false
|
||||
})
|
||||
}
|
||||
},
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
@import "~dvcp-wui/common";
|
||||
page {
|
||||
height: 100%;
|
||||
}
|
||||
.AppResidentAssistant {
|
||||
height: 100vh;
|
||||
background-color: #fff;
|
||||
.service-content {
|
||||
width: 100%;
|
||||
height: 420px;
|
||||
background-image: url("https://cdn.cunwuyun.cn/wechat/biaopin/residentAssistant/content-top-bg.png");
|
||||
background-size: 100vw;
|
||||
background-repeat: no-repeat;
|
||||
padding-top: 20px;
|
||||
box-sizing: border-box;
|
||||
.text-content {
|
||||
margin: 0 0 0 32px;
|
||||
width: 686px;
|
||||
height: 260px;
|
||||
background-image: url("https://cdn.cunwuyun.cn/wechat/biaopin/residentAssistant/service-content-bg.png");
|
||||
background-size: 100vw;
|
||||
background-repeat: no-repeat;
|
||||
padding: 32px;
|
||||
box-sizing: border-box;
|
||||
border-radius: 32px;
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
.text-left {
|
||||
width: calc(100% - 192px);
|
||||
div {
|
||||
line-height: 54px;
|
||||
font-family: SourceHanSansCN-Bold;
|
||||
font-weight: 700;
|
||||
font-size: 36px;
|
||||
background: linear-gradient(to bottom, #2A6EE9, #58A5F7);
|
||||
-webkit-background-clip: text;
|
||||
-webkit-text-fill-color: transparent;
|
||||
margin-bottom: 16px;
|
||||
}
|
||||
p {
|
||||
color: #222;
|
||||
font-size: 28px;
|
||||
font-family: SourceHanSansCN;
|
||||
line-height: 44px;
|
||||
span {
|
||||
display: inline-block;
|
||||
font-weight: 700;
|
||||
}
|
||||
}
|
||||
}
|
||||
.service-img {
|
||||
display: inline-block;
|
||||
width: 192px;
|
||||
height: 170px;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
.list-content {
|
||||
padding: 0 32px 364px;
|
||||
overflow: hidden;
|
||||
margin-top: -112px;
|
||||
background-color: #fff;
|
||||
.item {
|
||||
display: inline-block;
|
||||
max-width: 600px;
|
||||
border-radius: 24px 24px 0 24px;
|
||||
padding: 24px 32px;
|
||||
box-sizing: border-box;
|
||||
margin-bottom: 32px;
|
||||
.img-div {
|
||||
margin-bottom: 4px;
|
||||
img {
|
||||
width: 136px;
|
||||
height: 28px;
|
||||
margin-left: 26px;
|
||||
}
|
||||
}
|
||||
p {
|
||||
word-break: break-all;
|
||||
line-height: 48px;
|
||||
font-family: SourceHanSansCN-Regular;
|
||||
font-size: 32px;
|
||||
}
|
||||
}
|
||||
.item-right {
|
||||
display: flex;
|
||||
justify-content: flex-end;
|
||||
.item {
|
||||
background-image: linear-gradient(-76deg, #569EF0 0%, #276FEC 100%);
|
||||
}
|
||||
p {
|
||||
color: #fff;
|
||||
}
|
||||
}
|
||||
.item-left {
|
||||
.item {
|
||||
background-color: #F1F4F8;
|
||||
}
|
||||
p {
|
||||
color: #222;
|
||||
}
|
||||
}
|
||||
}
|
||||
.fixed-bottom {
|
||||
position: fixed;
|
||||
bottom: 0;
|
||||
left: 0;
|
||||
width: 100%;
|
||||
padding-bottom: 64px;
|
||||
border-top: 1px solid #eee;
|
||||
background-color: #fff;
|
||||
.type-text {
|
||||
padding: 24px 0 24px 32px;
|
||||
display: flex;
|
||||
u-input {
|
||||
width: calc(100% - 112px);
|
||||
height: 80px;
|
||||
background: #F4F6FA;
|
||||
border-radius: 40px;
|
||||
padding-left: 32px;
|
||||
}
|
||||
img {
|
||||
width: 80px;
|
||||
height: 80px;
|
||||
padding: 0 16px;
|
||||
}
|
||||
}
|
||||
.type-record {
|
||||
position: relative;
|
||||
text-align: center;
|
||||
padding-top: 36px;
|
||||
.keyboard-btn {
|
||||
width: 48px;
|
||||
height: 36px;
|
||||
position: absolute;
|
||||
top: 32px;
|
||||
right: 32px;
|
||||
}
|
||||
p {
|
||||
line-height: 58px;
|
||||
font-family: SourceHanSansCN-Medium;
|
||||
font-weight: 500;
|
||||
font-size: 40px;
|
||||
color: #222;
|
||||
}
|
||||
.record-btn {
|
||||
width: 156px;
|
||||
height: 156px;
|
||||
margin-top: 24px;
|
||||
}
|
||||
.tips-text {
|
||||
line-height: 40px;
|
||||
font-family: SourceHanSansCN-Regular;
|
||||
font-size: 28px;
|
||||
color: #999;
|
||||
margin-top: 16px;
|
||||
}
|
||||
.recording {
|
||||
padding-top: 48px;
|
||||
width: 204px;
|
||||
height: 96px;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
635
src/mods/conv/AppReturnHomeRegister/Add.vue
Normal file
@@ -0,0 +1,635 @@
|
||||
<template>
|
||||
<div class="album">
|
||||
<div class="tips">请确保以下信息全部由本人填写,本人对所填写内容的真实性和完整性负责</div>
|
||||
<div class="form-item__group">
|
||||
<div class="form-item">
|
||||
<div class="form-item__wrapper">
|
||||
<div class="form-item__title">
|
||||
<i>*</i>
|
||||
<h2>返乡人员姓名</h2>
|
||||
</div>
|
||||
<div class="form-item__right">
|
||||
<input placeholder="请输入" v-model="form.name" :maxlength="20"/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-item">
|
||||
<div class="form-item__wrapper">
|
||||
<div class="form-item__title">
|
||||
<i>*</i>
|
||||
<h2>身份证号</h2>
|
||||
</div>
|
||||
<div class="form-item__right">
|
||||
<input placeholder="请输入" type="idcard" v-model="form.idNumber" :maxlength="20"/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-item">
|
||||
<div class="form-item__wrapper">
|
||||
<div class="form-item__title">
|
||||
<i>*</i>
|
||||
<h2>手机号码</h2>
|
||||
</div>
|
||||
<div class="form-item__right">
|
||||
<input placeholder="请输入" type="number" v-model="form.phone" :maxlength="11"/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-item">
|
||||
<div class="form-item__wrapper">
|
||||
<div class="form-item__title">
|
||||
<i>*</i>
|
||||
<h2>人员类别</h2>
|
||||
</div>
|
||||
<div class="form-item__right">
|
||||
<AiSelect v-model="form.type" dict="epidemicRecentPersonType" class="select"></AiSelect>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-item__group">
|
||||
<div class="form-item">
|
||||
<div class="form-item__wrapper">
|
||||
<div class="form-item__title">
|
||||
<i>*</i>
|
||||
<h2>出行方式</h2>
|
||||
</div>
|
||||
<div class="form-item__right">
|
||||
<AiSelect dict="epidemicRecentTravel" v-model="form.travelType" class="select"></AiSelect>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-item">
|
||||
<div class="form-item__wrapper">
|
||||
<div class="form-item__title">
|
||||
<i>*</i>
|
||||
<h2>出发时间</h2>
|
||||
</div>
|
||||
<div class="form-item__right">
|
||||
<div class="ai-area" @click="isShowStartTime = true">
|
||||
<div class="ai-area__wrapper">
|
||||
<span class="label" v-if="form.startTime">{{ form.startTime }}</span>
|
||||
<i v-else>请选择</i>
|
||||
<u-icon name="arrow-right" color="#ddd"/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-item">
|
||||
<div class="form-item__wrapper">
|
||||
<div class="form-item__title">
|
||||
<i>*</i>
|
||||
<h2>出发地区</h2>
|
||||
</div>
|
||||
<div class="form-item__right">
|
||||
<AiAreaPicker class="ai-area" v-model="form.startAreaId" :fullName.sync="form.startAreaName" all>
|
||||
<div class="ai-area__wrapper">
|
||||
<span class="label" v-if="form.startAreaName">{{ form.startAreaName }}</span>
|
||||
<i v-else>请选择</i>
|
||||
<u-icon name="arrow-right" color="#ddd"/>
|
||||
</div>
|
||||
</AiAreaPicker>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-item form-item__textarea">
|
||||
<div class="form-item__wrapper">
|
||||
<div class="form-item__title">
|
||||
<i>*</i>
|
||||
<h2>出发地址</h2>
|
||||
</div>
|
||||
<div class="form-item__right">
|
||||
<textarea auto-height v-model="form.startAddress" :maxlength="500" placeholder="请输入详细的出发地址"
|
||||
placeholder-style="font-size: 16px"></textarea>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-item">
|
||||
<div class="form-item__wrapper">
|
||||
<div class="form-item__title">
|
||||
<i>*</i>
|
||||
<h2>到达时间</h2>
|
||||
</div>
|
||||
<div class="form-item__right">
|
||||
<div class="ai-area" @click="isShowEndTime = true">
|
||||
<div class="ai-area__wrapper">
|
||||
<span class="label" v-if="form.arriveTime">{{ form.arriveTime }}</span>
|
||||
<i v-else>请选择</i>
|
||||
<u-icon name="arrow-right" color="#ddd"/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-item">
|
||||
<div class="form-item__wrapper">
|
||||
<div class="form-item__title">
|
||||
<i>*</i>
|
||||
<h2>到达地区</h2>
|
||||
</div>
|
||||
<div class="form-item__right">
|
||||
<AiAreaPicker class="ai-area" v-model="form.arriveAreaId" :fullName.sync="form.arriveAreaName" :areaId="$areaId">
|
||||
<div class="ai-area__wrapper">
|
||||
<span class="label" v-if="form.arriveAreaName">{{ form.arriveAreaName }}</span>
|
||||
<i v-else>请选择</i>
|
||||
<u-icon name="arrow-right" color="#ddd"/>
|
||||
</div>
|
||||
</AiAreaPicker>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-item form-item__textarea">
|
||||
<div class="form-item__wrapper">
|
||||
<div class="form-item__title">
|
||||
<i>*</i>
|
||||
<h2>返乡地址</h2>
|
||||
</div>
|
||||
<div class="form-item__right">
|
||||
<textarea auto-height v-model="form.arriveAddress" :maxlength="500" placeholder="请输入详细的返乡地址"
|
||||
placeholder-style="font-size: 16px"></textarea>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-item form-item__textarea">
|
||||
<div class="form-item__wrapper">
|
||||
<div class="form-item__title">
|
||||
<i>*</i>
|
||||
<h2>行程描述</h2>
|
||||
</div>
|
||||
<div class="form-item__right">
|
||||
<textarea auto-height style="height: 90px" v-model="form.description" :maxlength="500" placeholder="请输入行程描述"
|
||||
placeholder-style="font-size: 16px"></textarea>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-item__group">
|
||||
<div class="form-item">
|
||||
<div class="form-item__wrapper">
|
||||
<div class="form-item__title">
|
||||
<i>*</i>
|
||||
<h2>核酸检测日期</h2>
|
||||
</div>
|
||||
<div class="form-item__right">
|
||||
<div class="ai-area" @click="isShowDate = true">
|
||||
<div class="ai-area__wrapper">
|
||||
<span class="label" v-if="form.checkTime">{{ form.checkTime }}</span>
|
||||
<i v-else>请选择</i>
|
||||
<u-icon name="arrow-right" color="#ddd"/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-item form-item__imgs">
|
||||
<div class="form-item__wrapper">
|
||||
<div class="form-item__title">
|
||||
<i>*</i>
|
||||
<h2>本人健康码截图或核酸检测报告<span style="color:#999; fontSize:14px; font-weight: normal;">(最多9张)</span></h2>
|
||||
</div>
|
||||
<div class="form-item__right" style="padding-left: 5px;">
|
||||
<AiUploader v-model="form.checkPhoto" :limit="9" multiple></AiUploader>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-item form-item__imgs">
|
||||
<div class="form-item__wrapper">
|
||||
<div class="form-item__title">
|
||||
<i>*</i>
|
||||
<h2>核酸检测结果</h2>
|
||||
</div>
|
||||
<div class="form-item__right">
|
||||
<AiRadio style="width: 100%;" v-model="form.checkResult" dict="epidemicRecentTestResult"/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-item__group">
|
||||
<div class="form-item">
|
||||
<div class="form-item__wrapper">
|
||||
<div class="form-item__title">
|
||||
<i>*</i>
|
||||
<h2>当前体温</h2>
|
||||
</div>
|
||||
<div class="form-item__right">
|
||||
<input placeholder="请输入" v-model="form.temperature" :maxlength="20"/>
|
||||
<i>℃</i>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-item form-item__imgs">
|
||||
<div class="form-item__wrapper">
|
||||
<div class="form-item__title">
|
||||
<i>*</i>
|
||||
<h2>14天内是否接触新冠确诊或疑似患者</h2>
|
||||
</div>
|
||||
<div class="form-item__right">
|
||||
<AiRadio style="width: 100%;" v-model="form.touchInFourteen" dict="epidemicTouchInFourteen"></AiRadio>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-item form-item__imgs">
|
||||
<div class="form-item__wrapper">
|
||||
<div class="form-item__title">
|
||||
<i>*</i>
|
||||
<h2>当前健康状况(可多选)</h2>
|
||||
</div>
|
||||
<div class="form-item__right">
|
||||
<AiCheckbox style="width: 100%;" v-model="form.health" dict="epidemicRecentHealth"></AiCheckbox>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<u-picker mode="time" :params="dataParams" v-model="isShowDate" @confirm="onDateChange"></u-picker>
|
||||
<u-picker mode="time" :params="params" v-model="isShowStartTime" @confirm="onStartChange"></u-picker>
|
||||
<u-picker mode="time" :params="params" v-model="isShowEndTime" @confirm="onEndChange"></u-picker>
|
||||
<div class="btn-wrapper">
|
||||
<div class="btn" hover-class="text-hover" @click="submit">提交</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import {mapState} from 'vuex'
|
||||
|
||||
export default {
|
||||
appName: "添加返乡记录",
|
||||
data() {
|
||||
return {
|
||||
isShowType: false,
|
||||
isShowEndTime: false,
|
||||
isShowStartTime: false,
|
||||
isShowDate: false,
|
||||
params: {
|
||||
year: true,
|
||||
month: true,
|
||||
day: true,
|
||||
hour: true,
|
||||
minute: true
|
||||
},
|
||||
dataParams: {
|
||||
year: true,
|
||||
month: true,
|
||||
day: true
|
||||
},
|
||||
form: {
|
||||
arriveAddress: '',
|
||||
arriveAreaId: '',
|
||||
arriveAreaName: '',
|
||||
arriveTime: '',
|
||||
checkPhoto: [],
|
||||
checkResult: '',
|
||||
checkTime: '',
|
||||
description: '',
|
||||
health: [],
|
||||
idNumber: '',
|
||||
name: '',
|
||||
phone: '',
|
||||
startAddress: '',
|
||||
startAreaId: '',
|
||||
startAreaName: '',
|
||||
startTime: '',
|
||||
temperature: '',
|
||||
touchInFourteen: '',
|
||||
travelType: '',
|
||||
type: '',
|
||||
unusual: '',
|
||||
},
|
||||
dictList: [],
|
||||
arr: [],
|
||||
gridList: [[], [], []],
|
||||
flag: false,
|
||||
$areaId: ''
|
||||
}
|
||||
},
|
||||
|
||||
|
||||
computed: {
|
||||
...mapState(['user'])
|
||||
},
|
||||
|
||||
onLoad() {
|
||||
this.$areaId = this.user.$areaId
|
||||
},
|
||||
|
||||
methods: {
|
||||
onDateChange(e) {
|
||||
this.form.checkTime = `${e.year}-${e.month}-${e.day}`
|
||||
},
|
||||
|
||||
onStartChange(e) {
|
||||
this.form.startTime = `${e.year}-${e.month}-${e.day} ${e.hour}:${e.minute}`
|
||||
},
|
||||
|
||||
onEndChange(e) {
|
||||
this.form.arriveTime = `${e.year}-${e.month}-${e.day} ${e.hour}:${e.minute}`
|
||||
},
|
||||
|
||||
submit() {
|
||||
if (!this.form.name) {
|
||||
return this.$toast('请输入返乡人员姓名')
|
||||
}
|
||||
|
||||
if (!this.form.idNumber) {
|
||||
return this.$toast('请输入返乡人员身份证号')
|
||||
}
|
||||
|
||||
if (!/^[1-9]\d{5}(19\d{2}|20[0-2]\d)(0[1-9]|1[0-2])(0[1-9]|[1-2][0-9]|3[0-1])\d{3}([0-9xX])$/.test(this.form.idNumber)) {
|
||||
return this.$toast('请输入正确的身份证账号')
|
||||
}
|
||||
|
||||
if (!this.form.phone) {
|
||||
return this.$toast('请输入返乡人员手机号码')
|
||||
}
|
||||
|
||||
if (!/^1[0-9]{10,10}$/.test(this.form.phone)) {
|
||||
return this.$toast('请输入正确的手机号码')
|
||||
}
|
||||
|
||||
if (!this.form.type) {
|
||||
return this.$toast('请选择人员类别')
|
||||
}
|
||||
|
||||
if (!this.form.travelType) {
|
||||
return this.$toast('请选择出行方式')
|
||||
}
|
||||
|
||||
if (!this.form.startTime) {
|
||||
return this.$toast('请选择出发时间')
|
||||
}
|
||||
|
||||
// if (new Date(this.form.startTime.replace(/-/g, '/')).getTime() > new Date().getTime()) {
|
||||
// return this.$toast('出发时间不得晚于当前时间')
|
||||
// }
|
||||
|
||||
if (!this.form.startAreaName) {
|
||||
return this.$toast('请选择出发地区')
|
||||
}
|
||||
|
||||
if (this.form.startAreaId.substr(this.form.startAreaId.length - 3, 3) === '000') {
|
||||
return this.$toast('出发地区必须选到村或社区')
|
||||
}
|
||||
if (!this.form.startAddress) {
|
||||
return this.$toast('请输入出发详细地址')
|
||||
}
|
||||
|
||||
if (!this.form.arriveTime) {
|
||||
return this.$toast('请选择到达时间')
|
||||
}
|
||||
|
||||
if (new Date(this.form.startTime.replace(/-/g, '/')).getTime() >= new Date(this.form.arriveTime.replace(/-/g, '/')).getTime()) {
|
||||
return this.$toast('到达时间不得早于出发时间')
|
||||
}
|
||||
|
||||
if (!this.form.arriveAreaName) {
|
||||
return this.$toast('请选择到达地区')
|
||||
}
|
||||
if (this.form.arriveAreaId.substr(this.form.arriveAreaId.length - 3, 3) === '000') {
|
||||
return this.$toast('到达地区必须选到村或社区')
|
||||
}
|
||||
if (!this.form.arriveAddress) {
|
||||
return this.$toast('请输入返乡地址')
|
||||
}
|
||||
|
||||
if (!this.form.description) {
|
||||
return this.$toast('请输入行程描述')
|
||||
}
|
||||
if (!this.form.checkTime) {
|
||||
return this.$toast('请选择核酸检测日期')
|
||||
}
|
||||
if (!this.form.checkPhoto.length) {
|
||||
return this.$toast('请上传本人健康码截图或核酸检测报告')
|
||||
}
|
||||
|
||||
if (!this.form.checkResult) {
|
||||
return this.$toast('请选择核酸检测结果')
|
||||
}
|
||||
if (!this.form.temperature) {
|
||||
return this.$toast('请输入当前体温')
|
||||
}
|
||||
if (!this.form.touchInFourteen) {
|
||||
return this.$toast('请选择14天内是否接触新冠确诊或疑似患者')
|
||||
}
|
||||
|
||||
if (!this.form.health.length) {
|
||||
return this.$toast('请选择当前健康状况')
|
||||
}
|
||||
if (this.flag) return
|
||||
this.flag = true
|
||||
|
||||
this.$loading()
|
||||
this.$instance.post(`/app/appepidemicbackhomerecord/addOrUpdate`, {
|
||||
...this.form,
|
||||
openid: this.user.openid,
|
||||
startTime: this.form.startTime + ':00',
|
||||
arriveTime: this.form.arriveTime + ':00',
|
||||
checkTime: this.form.checkTime + ' 00:00:00',
|
||||
health: this.form.health.join(','),
|
||||
checkPhoto: JSON.stringify(this.form.checkPhoto)
|
||||
}).then(res => {
|
||||
this.$hideLoading()
|
||||
this.flag = false
|
||||
if (res.code == 0) {
|
||||
uni.$emit('update')
|
||||
this.$toast('提交成功')
|
||||
setTimeout(() => {
|
||||
uni.navigateBack()
|
||||
}, 400)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss">
|
||||
.album {
|
||||
padding-bottom: 140px;
|
||||
|
||||
.tips {
|
||||
line-height: 1.3;
|
||||
padding: 32px 32px;
|
||||
color: #FF883C;
|
||||
font-size: 30px;
|
||||
text-align: justify;
|
||||
background: #FFF8F3;
|
||||
}
|
||||
|
||||
.form-item__group {
|
||||
margin-bottom: 24px;
|
||||
background: #fff;
|
||||
}
|
||||
|
||||
.form-item {
|
||||
padding-left: 32px;
|
||||
|
||||
.form-item__checkbox {
|
||||
width: 100%;
|
||||
|
||||
div {
|
||||
width: 100%;
|
||||
height: 80px;
|
||||
line-height: 80px;
|
||||
margin-bottom: 24px;
|
||||
text-align: center;
|
||||
background: #FFFFFF;
|
||||
border-radius: 16px;
|
||||
color: #333333;
|
||||
font-size: 28px;
|
||||
border: 1px solid #CCCCCC;
|
||||
|
||||
&.active {
|
||||
background: #4181FF;
|
||||
color: #fff;
|
||||
border-color: #4181FF;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.form-item__radio {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
flex-wrap: wrap;
|
||||
|
||||
div {
|
||||
width: 212px;
|
||||
height: 80px;
|
||||
line-height: 80px;
|
||||
margin-right: 16px;
|
||||
margin-bottom: 8px;
|
||||
text-align: center;
|
||||
background: #FFFFFF;
|
||||
border-radius: 16px;
|
||||
color: #333333;
|
||||
font-size: 28px;
|
||||
border: 1px solid #CCCCCC;
|
||||
|
||||
&:nth-of-type(3n) {
|
||||
margin-right: 0;
|
||||
}
|
||||
|
||||
&.active {
|
||||
background: #4181FF;
|
||||
color: #fff;
|
||||
border-color: #4181FF;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.ai-area__wrapper {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
padding-left: 100px;
|
||||
|
||||
span {
|
||||
color: #333;
|
||||
font-size: 30px;
|
||||
}
|
||||
|
||||
i {
|
||||
color: #999;
|
||||
font-size: 30px;
|
||||
}
|
||||
|
||||
image {
|
||||
width: 16px;
|
||||
height: 8px;
|
||||
}
|
||||
}
|
||||
|
||||
.form-item__wrapper {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
height: 128px;
|
||||
padding-right: 28px;
|
||||
border-bottom: 1px solid #DDDDDD;
|
||||
|
||||
input {
|
||||
flex: 1;
|
||||
height: 100%;
|
||||
text-align: right;
|
||||
color: #333;
|
||||
padding-right: 10px;
|
||||
}
|
||||
|
||||
.form-item__right {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
font-size: 32px;
|
||||
|
||||
.select {
|
||||
._i {
|
||||
padding-left: 100px;
|
||||
}
|
||||
}
|
||||
|
||||
span {
|
||||
max-width: 400px;
|
||||
margin-right: 8px;
|
||||
color: #333333;
|
||||
overflow: hidden;
|
||||
white-space: nowrap;
|
||||
text-overflow: ellipsis;
|
||||
}
|
||||
|
||||
i {
|
||||
margin-right: 8px;
|
||||
color: #999999;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
&:last-child {
|
||||
.form-item__wrapper {
|
||||
border-bottom: none;
|
||||
}
|
||||
}
|
||||
|
||||
.form-item__title {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
|
||||
i {
|
||||
font-size: 32px;
|
||||
color: #FF4466;
|
||||
}
|
||||
|
||||
span {
|
||||
font-size: 28px;
|
||||
color: #999999;
|
||||
}
|
||||
|
||||
h2 {
|
||||
padding: 0 4px;
|
||||
font-weight: 600;
|
||||
font-size: 32px;
|
||||
color: #333333;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
&.form-item__imgs, &.form-item__textarea {
|
||||
.form-item__wrapper {
|
||||
display: block;
|
||||
height: auto;
|
||||
padding-bottom: 32px;
|
||||
}
|
||||
|
||||
textarea {
|
||||
width: 100%;
|
||||
height: 90px;
|
||||
}
|
||||
|
||||
.form-item__title {
|
||||
padding: 32px 0;
|
||||
}
|
||||
|
||||
.form-item__right {
|
||||
padding-left: 18px;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||