Compare commits
	
		
			1758 Commits
		
	
	
		
			master
			...
			1de1e3b6d6
		
	
	| Author | SHA1 | Date | |
|---|---|---|---|
|  | 1de1e3b6d6 | ||
|  | 549dc9f18e | ||
|  | 7274566ef7 | ||
|  | ba3b2ba0e1 | ||
|  | 025f42bf76 | ||
|  | 9528bf2553 | ||
|  | 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 | # 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> | ||||||