Compare commits
	
		
			2439 Commits
		
	
	
		
			dev
			...
			8b72cc93a0
		
	
	| Author | SHA1 | Date | |
|---|---|---|---|
|  | 8b72cc93a0 | ||
|  | 6819b17126 | ||
|  | d9a35f0081 | ||
|  | 4b26e6f5d0 | ||
|  | ebb28ed676 | ||
|  | a059d2bd57 | ||
|  | fde372007f | ||
|  | 9aed740388 | ||
|  | 8a20db021a | ||
|  | 8daf15cf3f | ||
|  | ba8dc41c83 | ||
|  | 6744b18240 | ||
|  | a3ea6d9c51 | ||
|  | 5fa30a0e0e | ||
|  | 6b030791bb | ||
|  | d0922c5309 | ||
|  | d46bb82086 | ||
|  | 1ead1b2e9a | ||
|  | c5f4f9b356 | ||
|  | 3fbde7f193 | ||
|  | e5abd1514b | ||
|  | 33ed4fe5d5 | ||
|  | 4051b31101 | ||
|  | 94b1788e8c | ||
|  | 7944a1a8e3 | ||
|  | 17b28025d8 | ||
|  | 0a6b77943f | ||
|  | a599566b20 | ||
|  | 1a7031342f | ||
|  | 516a8edb5e | ||
|  | f4e2100882 | ||
|  | 9f6998e042 | ||
|  | f730850d93 | ||
|  | 0ef83a945f | ||
|  | cbfd68f50c | ||
|  | 7762eb6d24 | ||
|  | db1a323921 | ||
|  | 1a61475f57 | ||
|  | 356e6438e0 | ||
|  | 5fe82a68ef | ||
|  | 9b6e02810a | ||
|  | f0a32ad868 | ||
|  | ce64bfd54d | ||
|  | a53d25fae2 | ||
|  | 08d5e0e4fd | ||
|  | b23f8325f4 | ||
|  | 0adb2b1486 | ||
|  | 38082397a9 | ||
|  | 4d527dc8ec | ||
|  | d90aca62e4 | ||
|  | 44f11be05c | ||
|  | 7a21ab3804 | ||
|  | 6bb4802f15 | ||
|  | cfc8f3c8e0 | ||
|  | 3f26b8b6df | ||
|  | 350ca644cf | ||
|  | 99b507657f | ||
|  | 2e93f1465f | ||
|  | 07a4d0637f | ||
|  | 66a721c1eb | ||
|  | 5efd2a1d3f | ||
|  | d0c447bb41 | ||
|  | ebc143a052 | ||
|  | 70b77669ab | ||
|  | 7393bcbc6e | ||
|  | 2abdab1b20 | ||
|  | d1a8800a9b | ||
|  | ced505b585 | ||
|  | 25010984f9 | ||
|  | 75d5971e42 | ||
|  | f5085b1cb3 | ||
|  | baa5c3124a | ||
|  | d1ae5ff2c7 | ||
|  | 962d2a4068 | ||
|  | 3adbb68466 | ||
|  | 7f086f8b83 | ||
|  | 95689baff9 | ||
|  | d39650eca5 | ||
|  | 4f44f50db5 | ||
|  | 27a2052241 | ||
|  | 072390dc13 | ||
|  | 385447d3b4 | ||
|  | 532ceeb5e7 | ||
|  | 2275590461 | ||
|  | d25b082eff | ||
|  | 6feaeb22bf | ||
|  | dad169496c | ||
|  | 3eef1eeb3c | ||
|  | f108a61293 | ||
|  | e1231d408c | ||
|  | c073c8d0bd | ||
|  | 437ae1425c | ||
|  | b6dcddac6f | ||
|  | e283d6a650 | ||
|  | 230f8c3b80 | ||
|  | 382be3d32f | ||
|  | a7c3b22f87 | ||
|  | 3585cceca8 | ||
|  | 908e65f136 | ||
|  | 7828af24fd | ||
|  | 185630ad2c | ||
|  | 67c4c8032e | ||
|  | 39ce5404c1 | ||
|  | 9f02c2d011 | ||
|  | 9d369e9a0f | ||
|  | 19a9486f48 | ||
|  | ab9ec446c7 | ||
|  | 0d3d8f23bb | ||
|  | 971742b392 | ||
|  | 63a425cf77 | ||
|  | e11d504f18 | ||
|  | 0e35945d4a | ||
|  | 0762067bec | ||
|  | 290ecb6823 | ||
|  | ee15427e88 | ||
|  | 06fa7b636e | ||
|  | 225c0088e1 | ||
|  | ae83152271 | ||
|  | b1c0beb8f6 | ||
|  | 4d96417661 | ||
|  | 711db33df3 | ||
|  | b7c0350134 | ||
|  | 9ff89c19f3 | ||
|  | 4684952973 | ||
|  | 4ead05b251 | ||
|  | cf62d2f508 | ||
|  | a894db0144 | ||
|  | a748a8b337 | ||
|  | 37a6cb3457 | ||
|  | 045449331f | ||
|  | 4c72bd2ac9 | ||
|  | b3942f5822 | ||
|  | 0b6bc910c4 | ||
|  | a4233d5f2c | ||
|  | 31c874e1ba | ||
|  | d40830188d | ||
|  | e789570a1b | ||
|  | 0de94d76ee | ||
|  | 536f579523 | ||
|  | c8d75ab72a | ||
|  | ad9676c040 | ||
|  | 29bd119ff4 | ||
|  | b07cca9bcf | ||
|  | 1c2364574d | ||
|  | 528082fc6b | ||
|  | 823c327894 | ||
|  | 39f6275e31 | ||
|  | 44d971998a | ||
|  | 6d7769e61a | ||
|  | afe1df98f3 | ||
|  | 97bd799b6d | ||
|  | 3316b73450 | ||
|  | eee06c837d | ||
|  | c4ae782195 | ||
|  | 2b22db2bf3 | ||
|  | 30cf69df04 | ||
|  | 54352ece58 | ||
|  | daffd10bce | ||
|  | a22b574614 | ||
|  | e3c79f232d | ||
|  | 1ae371cb30 | ||
|  | 96d24a8b22 | ||
|  | 34eb7320fa | ||
|  | 9fa56ad890 | ||
|  | 263dd9ea37 | ||
|  | 85de031db2 | ||
|  | a6f11e56a7 | ||
|  | 15f6dc6499 | ||
|  | b64b102682 | ||
|  | 576553e962 | ||
|  | ff5e2d4fe2 | ||
|  | 3f41df22a9 | ||
|  | 043aaf8399 | ||
|  | a5e0f3a6c5 | ||
|  | f9123942ca | ||
|  | b67e30ce25 | ||
|  | 5a2762a7c6 | ||
|  | c43a8992fd | ||
|  | 705a252618 | ||
|  | e2e957880b | ||
|  | 104f5d1049 | ||
|  | b3f11698f2 | ||
|  | 285e242e9e | ||
|  | 00b2dbb4a4 | ||
|  | 0b41291bf1 | ||
|  | f35c272a19 | ||
|  | 3a5af5777c | ||
|  | 2cbddaeb4a | ||
|  | e88658b1be | ||
|  | 8e73c39c47 | ||
|  | 119cd5bad9 | ||
|  | ddfdbf161a | ||
|  | 0940462d70 | ||
|  | 80978d3794 | ||
|  | 134b78189d | ||
|  | 0c9b5d522e | ||
|  | c663bd52fc | ||
|  | 573349f864 | ||
|  | 6a1d86b88a | ||
|  | c1bca77b3f | ||
|  | f962d9db1d | ||
|  | 78a3842e01 | ||
|  | e69b66d2aa | ||
|  | 85c6d365b1 | ||
|  | 1131f98b27 | ||
|  | 0188289e05 | ||
|  | 1ae490f744 | ||
|  | c842794d0d | ||
|  | f888c81508 | ||
|  | 6118304302 | ||
|  | 6b2906fb53 | ||
|  | 4e33b3ae02 | ||
|  | 688834a86e | ||
|  | df49e1f9dc | ||
|  | 4f36215dad | ||
|  | 5bc9f859f4 | ||
|  | 05d4acf5da | ||
|  | 755719e228 | ||
|  | 41d74a9d57 | ||
|  | 9ca1b4f161 | ||
|  | 0a5592594b | ||
|  | 2c39458e98 | ||
|  | aefe08d35e | ||
|  | 6de9346d01 | ||
|  | a02e0d575b | ||
|  | 358f77b13b | ||
|  | 494cc25c4d | ||
|  | cd314f3da7 | ||
|  | 065306e511 | ||
|  | 8b724e52b3 | ||
|  | 155366d92e | ||
|  | bcba8286cc | ||
|  | f007dc84e7 | ||
|  | cb4c7dd623 | ||
|  | 10b44698e1 | ||
|  | 83c782f3e6 | ||
|  | f8c75eab5b | ||
|  | d5b1190492 | ||
|  | 2bac43eeda | ||
|  | 77176e5bf5 | ||
|  | 891757c7eb | ||
|  | 47e31b127d | ||
|  | 6ad47f207a | ||
|  | 0ff3eaff97 | ||
|  | 7d4c79ce1a | ||
|  | 43e7f044f3 | ||
|  | efd05d3298 | ||
|  | e6c143881d | ||
|  | 5b2ccae4ae | ||
|  | de86b003fa | ||
|  | 70f8685b07 | ||
|  | df50f83ee2 | ||
|  | 8a2015da4c | ||
|  | 5ee3bfbc41 | ||
|  | f7c2d03428 | ||
|  | 4889f8bc09 | ||
|  | 1ea55c9e13 | ||
|  | 438cbaa978 | ||
|  | 6a295b67d8 | ||
|  | 3f389d2f43 | ||
|  | c3f46fcd50 | ||
|  | daa79e7b1b | ||
|  | 074f77fac0 | ||
|  | 1c27e3e574 | ||
|  | a4f430be3e | ||
|  | c6672bc712 | ||
|  | 5897590973 | ||
|  | 846ac803df | ||
|  | b066edd428 | ||
|  | 9015cd06c0 | ||
|  | 859a8198fe | ||
|  | 077cb2cad2 | ||
|  | bc1504cce5 | ||
|  | 4c01b277d2 | ||
|  | 01cd905669 | ||
|  | eac706bfcb | ||
|  | be9aa08cd9 | ||
|  | 1cac8ab8e0 | ||
|  | 4385ba2354 | ||
|  | 8707b6d48d | ||
|  | a10a09c979 | ||
|  | 4a563fbc78 | ||
|  | 4e790062c7 | ||
|  | 59a998ee70 | ||
|  | ed809fe9f4 | ||
|  | ec9bc40fe0 | ||
|  | fb3ded6877 | ||
|  | 870bc38f1c | ||
|  | 2a882cb3ee | ||
|  | 80b6a03999 | ||
|  | f1ba9f7409 | ||
|  | 740c6497f1 | ||
|  | 5cc073cb87 | ||
|  | 809ef180a9 | ||
|  | 3ebed172ac | ||
|  | 0220dc7f67 | ||
|  | 08cb8b1be8 | ||
|  | 9b7b1283a8 | ||
|  | a6af330500 | ||
|  | a9224b896b | ||
|  | 308c7f8ab0 | ||
|  | 916fae5c36 | ||
|  | 42aca4d540 | ||
|  | af5c7fb279 | ||
|  | 01c9853f9e | ||
|  | a52278552c | ||
|  | 1c9a736274 | ||
|  | dbb986688c | ||
|  | 0fd8a0e1fa | ||
|  | 60a4d6a1c8 | ||
|  | bad99f9383 | ||
|  | dc1eacdc7f | ||
|  | 9ecde574bc | ||
|  | a6362ee638 | ||
|  | c1e1ac4b8b | ||
|  | f8a7ffaca9 | ||
|  | a362764dad | ||
|  | fc468044c6 | ||
|  | 1e9fd39349 | ||
|  | dd3e60ee2f | ||
|  | ece1ef06c3 | ||
|  | 6683b51c2f | ||
|  | ff2d0a8315 | ||
|  | 541d090fa7 | ||
|  | 1f5b213ddd | ||
|  | 165ae97634 | ||
|  | f72c34e802 | ||
|  | 57db3819bb | ||
|  | d3d8e4f397 | ||
|  | 29e4d1ec4b | ||
|  | 388274ace5 | ||
|  | 6fc848d164 | ||
|  | 01b4f3abb8 | ||
|  | 7c34462adc | ||
|  | 77664107fa | ||
|  | 9c5f594a58 | ||
|  | 8a704eae3e | ||
|  | 09f9795cd8 | ||
|  | 0f1df0b87d | ||
|  | b5a07c699a | ||
|  | 61852f86ec | ||
|  | e2d5d29d0c | ||
|  | 23bfdb7ac5 | ||
|  | 172213cdc2 | ||
|  | 1e65208a4b | ||
|  | 7aa17bd31c | ||
|  | 205f17b706 | ||
|  | 2164d0f348 | ||
|  | 72d69e5c8f | ||
|  | 91fd641845 | ||
|  | ece292c45a | ||
|  | 6b59beba0d | ||
|  | aba3e33e70 | ||
|  | 5fd3ed4542 | ||
|  | c707186f48 | ||
|  | ebc5e3aeef | ||
|  | 52cbc12d20 | ||
|  | 00105f6a7d | ||
|  | 53bf64712e | ||
|  | 5ddb198c0e | ||
|  | 15e9f9d760 | ||
|  | 236404c5ba | ||
|  | 9b8f05e764 | ||
|  | 2dc62004e1 | ||
|  | a4c5517b09 | ||
|  | e1b9633ba4 | ||
|  | e73dd17908 | ||
|  | 54880a9562 | ||
|  | 2ff20d4fc5 | ||
|  | f719b71628 | ||
|  | 3e3f3349b4 | ||
|  | be8698382a | ||
|  | 463e545c19 | ||
|  | 210e410a26 | ||
|  | 4e051d9bee | ||
|  | 2796506449 | ||
|  | f0f7f75bf3 | ||
|  | 587b988ade | ||
|  | 8279b89ff5 | ||
|  | 2143da5dce | ||
|  | f095e344f5 | ||
|  | d59aef8a15 | ||
|  | ebf726afd5 | ||
|  | c0667636a5 | ||
|  | 892979ef1a | ||
|  | eca9fc8196 | ||
|  | 8566f8cd70 | ||
|  | f7976b6022 | ||
|  | d17ae463e8 | ||
|  | 927a091075 | ||
|  | b4234e30d8 | ||
|  | f2a513bd0e | ||
|  | 90e89cd60d | ||
|  | cd4a5621bb | ||
|  | 5c29d7ca5d | ||
|  | 18dd1937ce | ||
|  | c65f06acc0 | ||
|  | e7991254fa | ||
|  | 46ea63390e | ||
|  | 17990fe640 | ||
|  | 615f83861e | ||
|  | 428eb3319f | ||
|  | 91f3956508 | ||
|  | 5fa3d83f3e | ||
|  | d1c0c4a784 | ||
|  | 316e530943 | ||
|  | 692ffab0d9 | ||
|  | a293259fb9 | ||
|  | ea0ec60401 | ||
|  | 526af7828d | ||
|  | 3c9ac1b3d8 | ||
|  | 562a875219 | ||
|  | d21a9ba075 | ||
|  | 777411294c | ||
|  | 4dd5d85607 | ||
|  | 4476215d1c | ||
|  | fccdcf735f | ||
|  | 8c9db36978 | ||
|  | aded396bd1 | ||
|  | fa6553c4f6 | ||
|  | 180cc0778d | ||
|  | 840934372e | ||
|  | ec09a998f7 | ||
|  | 426f081cbc | ||
|  | 890af51f30 | ||
|  | 18fa7ac43f | ||
|  | 6b54d60ae0 | ||
|  | 4753245f74 | ||
|  | a1c2cef0d9 | ||
|  | 5423483f1c | ||
|  | a20fcb413a | ||
|  | f3e1580fef | ||
|  | cd708b373c | ||
|  | d025673c53 | ||
|  | a85f7b201c | ||
|  | 6dbe6365e8 | ||
|  | f909eae8c0 | ||
|  | 674ddb1fd6 | ||
|  | 7dfd1c8d6c | ||
|  | 7393eeb858 | ||
|  | 8f21db5ca3 | ||
|  | 7a0538dff0 | ||
|  | fdfbaad6d8 | ||
| e72f7c5e9f | |||
| bc50d76366 | |||
| fe7c6a5cb8 | |||
|  | 372f52e655 | ||
|  | 5d2a66b861 | ||
|  | b5523f5f40 | ||
|  | a4d4e3cea5 | ||
|  | f50bd497be | ||
|  | de918d48dc | ||
|  | d599972b7f | ||
|  | dee681d246 | ||
|  | 8990e921ae | ||
|  | 67fb697136 | ||
|  | f34d6bf108 | ||
|  | 570476b2aa | ||
|  | 0821d9b238 | ||
|  | c557433324 | ||
|  | 78d2c0ee21 | ||
|  | 03cd857bf3 | ||
|  | 5273f300ea | ||
|  | 4c220621b5 | ||
|  | e2c0e919d3 | ||
|  | bffb6d14e0 | ||
|  | 10b43594ca | ||
|  | c7b37d645d | ||
|  | bc17e11c47 | ||
|  | 0731de6926 | ||
|  | 9710e0aa00 | ||
|  | 59b4151e15 | ||
|  | d0a695e874 | ||
|  | ec55f48a63 | ||
|  | f69a6a75c8 | ||
|  | 6f688a058c | ||
|  | 9ea22ba66b | ||
|  | dbf63a0952 | ||
|  | 2de8bc681b | ||
|  | 1ba2d12376 | ||
|  | cb24b1560d | ||
|  | 5656d35d71 | ||
|  | 80734a0893 | ||
|  | 2335d43070 | ||
|  | 1a1ed43bd3 | ||
|  | 32500deaee | ||
|  | 5b56f03269 | ||
|  | f5dcdd3755 | ||
|  | 68d4f8ac1b | ||
|  | 4442b2c578 | ||
|  | 66d0f0c8ab | ||
|  | a65bb62369 | ||
|  | da02013346 | ||
|  | c30099b635 | ||
|  | 75f3efa38a | ||
|  | f9e74f8362 | ||
|  | 13b779ff3e | ||
|  | 8a1fa07e9b | ||
|  | 44a486fba6 | ||
|  | 99030da813 | ||
|  | 592981cdf8 | ||
|  | ca9e65f0cf | ||
|  | e21be6d018 | ||
|  | 28439149b3 | ||
|  | e259a3c411 | ||
|  | 124cb852aa | ||
|  | d3fc263f4e | ||
|  | f404055955 | ||
|  | 421d15e27e | ||
|  | 1994faf5b8 | ||
|  | 6cca359c2a | ||
|  | 304a64f65c | ||
|  | 717328223a | ||
|  | f1ed3b9b54 | ||
|  | 7b5cbdf010 | ||
|  | f1dd17b8f9 | ||
|  | 4e145e8435 | ||
|  | 066feca056 | ||
|  | 9414658842 | ||
|  | c494281257 | ||
|  | 0c940de38d | ||
|  | eaf7819d22 | ||
|  | 212413ae5f | ||
|  | 0e94cec311 | ||
|  | 9946553938 | ||
|  | 06eb7a30bf | ||
|  | f9684bb0c4 | ||
|  | bafa145712 | ||
|  | 1f884ac990 | ||
|  | 776539a32b | ||
|  | f82d7f58e7 | ||
|  | a42aa166d1 | ||
|  | 7232b894f7 | ||
|  | 4f3a5af06d | ||
|  | ac3ea74b87 | ||
|  | d18b879873 | ||
|  | 8d477fd6b5 | ||
|  | 4f446d5a09 | ||
|  | f77d943ba6 | ||
|  | 23d845f828 | ||
|  | f0c3ae6cd4 | ||
|  | 7ec939c54d | ||
|  | 619858e595 | ||
|  | 5e37673dba | ||
|  | e45d794128 | ||
|  | 74f31b61d2 | ||
|  | 30f8f09645 | ||
|  | 40860776a0 | ||
|  | ad0a91750c | ||
|  | 1aa2e264d7 | ||
|  | 7792ec186c | ||
|  | 60e9377f2e | ||
|  | 2f711f455a | ||
|  | 4943c4cd09 | ||
|  | c399e1a522 | ||
|  | 6975bf7608 | ||
|  | f01445678d | ||
|  | 059112abba | ||
|  | eaba5f7be7 | ||
|  | ffa8e336b6 | ||
|  | 10a67de2ba | ||
|  | 9316a8749e | ||
| b6f7aac2cd | |||
|  | 194c9e59df | ||
|  | 4fefcb8766 | ||
|  | ee78546e7a | ||
|  | 35aedab466 | ||
|  | 4574738593 | ||
|  | 7a0577b1c3 | ||
|  | 94300ec85c | ||
|  | 0256669afb | ||
|  | 42673696b4 | ||
|  | fdb5226b31 | ||
|  | 8f5b0a990e | ||
|  | 2e3671c1fa | ||
|  | 1819bdf1b9 | ||
|  | 37c81cb607 | ||
|  | d0a7759428 | ||
|  | cf6a8cf71f | ||
|  | d8efdc369c | ||
|  | d38355ba37 | ||
|  | 2603294bf9 | ||
|  | b4a8363efe | ||
|  | c84e0d288e | ||
|  | 6168d5d4b2 | ||
|  | d7e8fa64fd | ||
|  | 8f6917b10f | ||
|  | 312c17d985 | ||
|  | 15f9f4f9d3 | ||
|  | 94d27be493 | ||
|  | 47c74b5d0a | ||
|  | fb0b73be04 | ||
|  | 914fb11d48 | ||
|  | 950dd57d2d | ||
|  | 293737d8ac | ||
|  | 258bf54607 | ||
|  | 62a38d7d9e | ||
|  | bcfd770fc2 | ||
|  | 07cff62073 | ||
|  | 1312af0d5c | ||
|  | 791af1c397 | ||
|  | 3be2c18960 | ||
|  | aa4cdb88a2 | ||
|  | 4d45905531 | ||
|  | 4f4319150b | ||
|  | 7913e12144 | ||
|  | a0113a6770 | ||
|  | 088d91bb95 | ||
|  | bdd2e7f5ee | ||
|  | 81f9744633 | ||
|  | 5859210eb3 | ||
|  | a784c2c9b4 | ||
|  | 688437a068 | ||
|  | 843476a24b | ||
|  | df464eae89 | ||
|  | 22023aa887 | ||
|  | 5718b5bfa2 | ||
|  | 3ac80e3bbb | ||
|  | ed6b0695f2 | ||
|  | 1370593dd0 | ||
|  | acb6393f7d | ||
|  | 0aaa71aa29 | ||
|  | 0c3dab491f | ||
|  | 63d85b5c5b | ||
|  | 3473d09885 | ||
|  | 10ae557ad0 | ||
|  | 9307452a14 | ||
|  | a2519d82a2 | ||
|  | ec8da18298 | ||
|  | 91701965e9 | ||
|  | 86171587a0 | ||
|  | 6474d8d4a1 | ||
|  | dc45b610cc | ||
|  | a0afde54ff | ||
|  | 329aeecb34 | ||
|  | 1b4f7d95bf | ||
|  | 2221b11742 | ||
|  | 4e07ff289e | ||
|  | 542466d01a | ||
|  | b64f63ef9b | ||
|  | ff9491490c | ||
|  | 9e720dd808 | ||
|  | 985efd1a83 | ||
|  | 9251ab86e3 | ||
|  | 961950bf5e | ||
|  | ed390fafc2 | ||
|  | ddc099cffb | ||
|  | c66b661779 | ||
|  | 407b3ba2ac | ||
|  | d61c61d553 | ||
|  | eaadc9ae9c | ||
|  | 667e2af2df | ||
|  | 059df5fddf | ||
|  | 2d74465cf7 | ||
|  | 8b0650641e | ||
|  | c830b57f1f | ||
|  | f4b0e31858 | ||
|  | 24b7be6b32 | ||
|  | 5620d9aeb9 | ||
|  | 3cc973c3be | ||
|  | 2546cadadd | ||
|  | 1dd3a81607 | ||
|  | 67f1d0c45c | ||
|  | ba05fbda15 | ||
|  | 6ea2e37243 | ||
|  | cd33176a79 | ||
|  | 8d19706bac | ||
|  | ebb263cf2b | ||
|  | 00e02114cf | ||
|  | 5a64f7ac7d | ||
|  | d5f959707a | ||
|  | 4ec643dd1a | ||
|  | fd90613094 | ||
|  | 1420676c7c | ||
|  | b37a7b0d04 | ||
|  | 8c07c9a6cb | ||
|  | 189e7621ad | ||
|  | e55b5b8a8d | ||
|  | b7b1431b20 | ||
|  | f9b7833e47 | ||
|  | 82bd4af605 | ||
|  | da422ec320 | ||
|  | 8df77fb17a | ||
|  | 522b197279 | ||
|  | e49b4840e3 | ||
|  | ca7ad35d97 | ||
|  | 4ba346e72a | ||
|  | eed32e32a7 | ||
|  | 3ade163fbd | ||
|  | ab92982e71 | ||
|  | 6b7ff8e58c | ||
|  | 7be1dfd235 | ||
|  | 76f8830a0e | ||
|  | de994686f7 | ||
|  | 5b09630e62 | ||
|  | c776c1d733 | ||
|  | 21ed9dc914 | ||
|  | cec6ccc78a | ||
|  | 6f6dc79702 | ||
|  | 656b4be0c3 | ||
|  | e129575479 | ||
|  | 1b2348ef73 | ||
|  | 3a9377fe4b | ||
|  | d6d1b16a81 | ||
|  | 30b25883a8 | ||
|  | 872e7afdd3 | ||
|  | 4eeb00b093 | ||
|  | dec9937830 | ||
|  | c2a1ad2cd7 | ||
|  | 8dd48bc16c | ||
|  | 8aaf56e9e9 | ||
|  | 8224ebfb8a | ||
|  | fa551fe618 | ||
|  | 03272542b9 | ||
|  | 1c69fc8366 | ||
|  | 50541832cc | ||
|  | 39a344b054 | ||
|  | 54d49f0d14 | ||
|  | b235b5a3dc | ||
|  | 54b4c6f7c3 | ||
|  | 51aa329160 | ||
|  | 6c60c3439a | ||
|  | e725476603 | ||
|  | 1604efdecc | ||
|  | 7e1bf238a2 | ||
|  | c300e4072b | ||
|  | c0199b7b27 | ||
|  | 068f041b1b | ||
|  | 2a35b7611d | ||
|  | ec7048ac6b | ||
|  | 5a9a408bac | ||
|  | 449f315602 | ||
|  | d217c3a7d9 | ||
|  | 12c3076fbf | ||
|  | b2a6f5c09d | ||
|  | aeb7a68940 | ||
|  | adbf66aa00 | ||
|  | 20cd701073 | ||
|  | 8753f74791 | ||
|  | 39ad7e3a2f | ||
|  | e619acafd0 | ||
|  | 9332c73979 | ||
|  | de826faffd | ||
|  | 587b472194 | ||
|  | 7a67f0ebac | ||
|  | 74ddc88d00 | ||
|  | 87441df05d | ||
|  | 5b32a8d9f2 | ||
|  | 7075fed306 | ||
|  | 45083c459d | ||
|  | 390315d8fc | ||
|  | e22bee323c | ||
|  | f05e036bd0 | ||
|  | 27be7e63fc | ||
|  | 075beeb66b | ||
|  | a06537df58 | ||
|  | fc504404eb | ||
|  | 833b812a5f | ||
|  | 3dc9c0b86d | ||
|  | f146d3de01 | ||
|  | 0d772dd5d8 | ||
|  | a90f9be052 | ||
|  | 9038477862 | ||
|  | 468e05d75a | ||
|  | 673de90b92 | ||
|  | 4ce40daea1 | ||
|  | 21346a6798 | ||
|  | fa6f4a6d96 | ||
|  | 71f3bce5c7 | ||
|  | 6ac9c8e569 | ||
|  | cab95c1ae7 | ||
|  | 59b65f1745 | ||
|  | d1bc5a27ce | ||
|  | 28bb272ea4 | ||
|  | 97755bf7f9 | ||
|  | 2146056299 | ||
|  | 69e586d62b | ||
|  | be339c78ba | ||
|  | c8c1e558b1 | ||
|  | e03b0a203a | ||
|  | 6c88de497b | ||
|  | b8838d2171 | ||
|  | 17249c16fa | ||
|  | 8e167df7e3 | ||
|  | 378f4eba0b | ||
|  | ed4b58e215 | ||
|  | c99a9a1332 | ||
|  | f342e7d672 | ||
|  | 4f240ce79b | ||
|  | 3ef745acc6 | ||
|  | d767bd4326 | ||
|  | 36768dd5ca | ||
|  | 0b024f86c2 | ||
|  | 144d8be0d2 | ||
|  | ef371ae830 | ||
|  | 45a6e9f468 | ||
|  | d05b98d6e1 | ||
|  | 14cbefd125 | ||
|  | 046f0bf729 | ||
|  | 6b1c753d63 | ||
|  | 356ce8a63c | ||
|  | 3a27e68a90 | ||
|  | 6f414822de | ||
|  | 783bd0c4a3 | ||
|  | f140ef743d | ||
|  | e87f7305af | ||
|  | d076ac472c | ||
|  | 5949a8080b | ||
|  | 9a30b5aee0 | ||
|  | b1959edcd3 | ||
|  | 681088cb8d | ||
|  | 18009fdcb1 | ||
|  | 12712f55c8 | ||
|  | 2394a51cc0 | ||
|  | 9582d09ab7 | ||
|  | fce4725783 | ||
|  | 7d90a45cf6 | ||
|  | e3c3058a14 | ||
|  | 8b37b1236e | ||
|  | 20361ebe31 | ||
|  | d26ab93831 | ||
|  | d031e5d8e1 | ||
|  | 87f046d128 | ||
|  | 60b14432b6 | ||
|  | 9e5c080c4d | ||
|  | 3824243527 | ||
|  | 408fcffb29 | ||
|  | e416bd4b33 | ||
|  | 376cd60edd | ||
|  | 497db329be | ||
|  | f375ede115 | ||
|  | 406be50c27 | ||
|  | 2840952a41 | ||
|  | 4d843a9917 | ||
|  | 853dfc5988 | ||
|  | 437b348d06 | ||
|  | d143c6cc94 | ||
|  | 15ca20f906 | ||
|  | 0b2b613a7d | ||
|  | 8e0265232b | ||
|  | 0bc282c796 | ||
|  | 3acc7ef3d1 | ||
|  | 8f9d0d577f | ||
|  | ccf1be34be | ||
|  | 22c77339d2 | ||
|  | 7c71eb3cb8 | ||
|  | 3501165a3a | ||
|  | b42d1a0502 | ||
|  | cc1026765f | ||
|  | 16052ff00c | ||
|  | e983bd22a1 | ||
|  | b09cfd62a5 | ||
|  | 42b77e095c | ||
|  | a7e4c4528b | ||
|  | 852fa0346f | ||
|  | 295ff657e8 | ||
|  | 56b12271b8 | ||
|  | 80438a6ef2 | ||
|  | a3f6cde2da | ||
|  | 0f1e9d4815 | ||
|  | 7cee782996 | ||
|  | 129ea08723 | ||
|  | cf6b2ae087 | ||
|  | cc6719a677 | ||
|  | 76523d1c9f | ||
|  | 545f796578 | ||
|  | f2ff079d79 | ||
|  | f51879a8af | ||
|  | c6638f891d | ||
|  | 6c517b5f2f | ||
|  | 20d2cd8426 | ||
|  | 645b6c774f | ||
|  | ac9b240a0f | ||
|  | 0164aaa924 | ||
|  | 9c0330561c | ||
|  | 2575c256c4 | ||
|  | 543636c180 | ||
|  | 23383c28de | ||
|  | c616e57b4f | ||
|  | 4e5814b1a1 | ||
|  | 47779269b4 | ||
|  | fe62caea78 | ||
|  | 0dd726ced9 | ||
|  | 5549773805 | ||
|  | 56688f75d8 | ||
|  | e3a9f8032b | ||
|  | 06eaf1e59d | ||
|  | 5dba7c558f | ||
|  | 47a1f52cde | ||
|  | 38d79cc0e2 | ||
|  | f697a86440 | ||
|  | bcbdb81ad1 | ||
|  | a1dfc6483c | ||
|  | 358ad78f13 | ||
|  | 164fe19a4a | ||
|  | 9c45f25e8d | ||
|  | 8af3b1b9fb | ||
|  | 5f92126be4 | ||
|  | 8af5ea6f45 | ||
|  | cde4ef3ddf | ||
|  | 44b4685257 | ||
|  | b89581c900 | ||
|  | c18511ac01 | ||
|  | 6e1b0a0684 | ||
|  | 5b90115b80 | ||
|  | f4c3ad72c4 | ||
|  | 4eb960b16b | ||
|  | f2a7cafc76 | ||
|  | 96647bfa90 | ||
|  | 2d943d4399 | ||
|  | fc0f92a7de | ||
|  | 00340f1d21 | ||
|  | f59179e3bc | ||
|  | 27e6fe0eb2 | ||
|  | 107515e876 | ||
|  | 6a3cadf53d | ||
|  | feea70120c | ||
|  | 549d747a8c | ||
|  | 201076e0fe | ||
|  | 75d33443f0 | ||
|  | b5afda4cce | ||
|  | 7e40790569 | ||
|  | 507565de3d | ||
|  | ad2e5bccab | ||
|  | 077fc80264 | ||
|  | 7e0bc1ef61 | ||
|  | 4392aed3f6 | ||
|  | fe9b1cd542 | ||
|  | 99d9d36549 | ||
|  | 019e8262bb | ||
|  | e89d9d8716 | ||
|  | 6a828ff68c | ||
|  | 31c18321ae | ||
|  | 1763582623 | ||
|  | d0a194e41b | ||
|  | a020f4c097 | ||
|  | 5d8ab39041 | ||
|  | e78a89a112 | ||
|  | 3e440cfad9 | ||
|  | 0266acd77a | ||
|  | 97306a8dc0 | ||
|  | 2598239ccd | ||
|  | 9623b426b0 | ||
|  | 68d122e38d | ||
|  | d93a658666 | ||
|  | 88a2955788 | ||
|  | 2cfa55841a | ||
|  | 8c77493f7a | ||
|  | 2eedf9e7fc | ||
|  | cbda18f8e8 | ||
|  | ce7db89626 | ||
|  | be91cfe3b0 | ||
|  | 99368c5f86 | ||
|  | 38d5f9d753 | ||
|  | 4a6732d816 | ||
|  | 44ce4979d7 | ||
|  | ccd8cdf9ba | ||
|  | ba7987b7ff | ||
|  | 9af8a19922 | ||
|  | f47a481076 | ||
|  | 84096c9bde | ||
|  | 73b7c5222b | ||
|  | 6d435d32d7 | ||
|  | 1fec63c027 | ||
|  | 383fcd00b0 | ||
|  | 5bd534c170 | ||
|  | c71cb51e11 | ||
|  | a8ac7b14d4 | ||
|  | 291d068c66 | ||
|  | 57c1037871 | ||
|  | ca19697d1c | ||
|  | 6d037bbe8d | ||
|  | c3f80c5fa6 | ||
|  | 8b320ece34 | ||
|  | e6f2d1e599 | ||
|  | fbf2ac5d12 | ||
|  | ccdbbc8562 | ||
|  | 5181e9ec14 | ||
|  | c90cdf7678 | ||
|  | 57120ca85f | ||
|  | df27cbefec | ||
|  | 381eefb78f | ||
|  | 969785c47a | ||
|  | 02ae6b6280 | ||
|  | 568c560e61 | ||
|  | c9d6b0dd14 | ||
|  | 4d0954fad5 | ||
|  | 6ff5e64613 | ||
|  | 4100f0744d | ||
|  | 81d4c7c174 | ||
|  | 66ee9806cf | ||
|  | 09b9b308ff | ||
|  | 1e6c7109f3 | ||
|  | 17dc4d48a4 | ||
|  | 3d927d8e8d | ||
|  | 66addd9ebe | ||
|  | f92602a7c1 | ||
|  | ef06d88bd4 | ||
|  | 399180d2cf | ||
|  | 3ec7a262d4 | ||
|  | 8acfa11f94 | ||
|  | 14bee51dbd | ||
|  | 1934cfaafc | ||
|  | a20d1d893c | ||
|  | a29f7b4aae | ||
|  | c73dba2cf0 | ||
|  | d15a9ee20e | ||
|  | 56e330588f | ||
|  | c3ad840e0c | ||
|  | 46e5ac38dc | ||
|  | d662e2dc75 | ||
|  | 3361aa300b | ||
|  | 6741eb17d4 | ||
|  | 44e2c25f5b | ||
|  | e238a9e052 | ||
|  | 3087ca7ae9 | ||
|  | 64226da7cf | ||
|  | 0a5edffcf8 | ||
|  | 3e7ac24bd5 | ||
|  | 80d487a726 | ||
|  | 77cf1c1525 | ||
|  | 2248485801 | ||
|  | ed46bece45 | ||
|  | da858fbe35 | ||
|  | f2f3d5c8a7 | ||
|  | df160cbb2b | ||
|  | 6cd0602536 | ||
|  | 41a78266fe | ||
|  | ef639ba1c1 | ||
|  | 56b3240de7 | ||
|  | e80e0c61d9 | ||
|  | 4398d76a91 | ||
|  | c5784e268e | ||
|  | b6a55f5b9d | ||
|  | 7249809b09 | ||
|  | 892a308e0b | ||
|  | 0507cd9a89 | ||
|  | 60facb4d4d | ||
|  | d7ccdb3897 | ||
|  | 49ddfe9404 | ||
|  | e84f8b4c18 | ||
|  | 973ca20fb6 | ||
|  | 5b5fcd2a88 | ||
|  | 1f20801f2c | ||
|  | fe1a7c6ced | ||
|  | 6d14c00acc | ||
|  | f7cf905f93 | ||
|  | de3e4ef259 | ||
|  | 079f85eab9 | ||
|  | c241d613fe | ||
|  | f346e8289f | ||
|  | de018e95b5 | ||
|  | f5b9baac75 | ||
|  | 8e501b0f7e | ||
|  | 597189adb1 | ||
|  | 6d28ab9d12 | ||
|  | 1090dc13f1 | ||
|  | 8ae50f3852 | ||
|  | b098a4e294 | ||
|  | 89ffcc639a | ||
|  | 35105ddc05 | ||
|  | de42648740 | ||
|  | b1f62f868b | ||
|  | d026b4aa14 | ||
|  | 9a3eeca0cf | ||
|  | 16418ba1f5 | ||
|  | b5b530d1d7 | ||
|  | 9370e764bb | ||
|  | 4f4c4b1cb1 | ||
|  | b77c5cc7ee | ||
|  | 927747e95d | ||
|  | 30b25e56b8 | ||
|  | fff9891177 | ||
|  | 7086b7af99 | ||
|  | bbdc9c3983 | ||
|  | 11ca29b3f6 | ||
|  | b126053e09 | ||
|  | 4d7b5949c1 | ||
|  | 0f752889fd | ||
|  | aca3b38dab | ||
|  | 9c37fa0414 | ||
|  | 1481bf7fa0 | ||
|  | 181a4018be | ||
|  | 3724b25e4c | ||
|  | dfc9a1cb03 | ||
|  | 090d15dda1 | ||
|  | c3fa9b8d79 | ||
|  | 4f9c4c8d27 | ||
|  | a9959a8ed2 | ||
|  | fa9f36bca9 | ||
|  | 4d8fd26ddd | ||
|  | f5a65e98be | ||
|  | 5a4c1f9a61 | ||
|  | 605f8a33f6 | ||
|  | 090fceabbe | ||
|  | 53d9e5f558 | ||
|  | fb3206a9ec | ||
|  | 3bf5efdd64 | ||
|  | 14fc3eff94 | ||
|  | a1cb11b1d8 | ||
|  | 8beb2a3699 | ||
|  | 8b818e82b4 | ||
|  | deb5ef82e1 | ||
|  | 1fc632f097 | ||
|  | ada5ef8bfe | ||
|  | 7deff7e464 | ||
|  | 466192f7fd | ||
|  | cc74131f44 | ||
|  | 4f217788ca | ||
|  | a8557de4d6 | ||
|  | 69b2bd6b6f | ||
|  | bd5698a781 | ||
|  | 7539d38294 | ||
|  | 32f819f16a | ||
|  | cf19a1ee7b | ||
|  | c0b9078a0b | ||
|  | 09a161686c | ||
|  | c7a32d0319 | ||
|  | 5d42d5ad34 | ||
|  | c0a513a1a7 | ||
|  | d1fa008407 | ||
|  | 7d203cda5e | ||
|  | 1846715f47 | ||
|  | 7ee414725c | ||
|  | d0361418cf | ||
|  | b202caec7f | ||
|  | 4bed4bca66 | ||
|  | 61b11585b2 | ||
|  | 671d62d0cc | ||
|  | 33695de84f | ||
|  | 4b99f2768f | ||
|  | 6b4051b984 | ||
|  | a2747e7182 | ||
|  | b36a3661a0 | ||
|  | 8a7dc2e798 | ||
|  | 8c5e95859a | ||
|  | 908a11d268 | ||
|  | 2daeb761b1 | ||
|  | bb67491c2d | ||
|  | c5b3f6daa2 | ||
|  | 8eb675f4a4 | ||
|  | 6a9ca31b8f | ||
|  | f76f662aac | ||
|  | 12c6feb238 | ||
|  | de50f365af | ||
|  | 14575cbb33 | ||
|  | 4530440bd6 | ||
|  | fdbe251c3e | ||
|  | f4d7cebd8a | ||
|  | 113a7a174e | ||
|  | 693b85d0b0 | ||
|  | 9dd6790b2d | ||
|  | ca810d2da1 | ||
|  | da9b3b2add | ||
|  | 5b4443f41f | ||
|  | 4e54061671 | ||
|  | e594478f16 | ||
|  | 6f7903b9ce | ||
|  | ff55cd42ba | ||
|  | 36b34a190b | ||
|  | 18c0827f5a | ||
|  | d49d93b19d | ||
|  | 7ec58be72d | ||
|  | 9bc648f5b8 | ||
|  | 6be6b2626a | ||
|  | 1320479c39 | ||
|  | 84f5c26cd3 | ||
|  | a2fa56c2ad | ||
|  | 49c967885c | ||
|  | 40a62ead01 | ||
|  | 6b7e887ae8 | ||
|  | fb01e4f84f | ||
|  | 6d200ea43b | ||
|  | 8be74f75fd | ||
|  | 785ba26120 | ||
|  | a461c9add7 | ||
|  | 9ab6ed0f11 | ||
|  | e553c9c758 | ||
|  | 42eff40f48 | ||
|  | 87ae42f7fe | ||
|  | c37a19036a | ||
|  | 7d72023ad7 | ||
|  | c72eb9c40e | ||
|  | fd089d78ac | ||
|  | 5b49e3ef7c | ||
|  | 4d97436d14 | ||
|  | 442f0deccb | ||
|  | 483a4d585f | ||
|  | 1bd2bf44bb | ||
|  | 62c927746b | ||
|  | 1cb5b85483 | ||
|  | ea60eb2938 | ||
|  | 032b077bdc | ||
|  | 27b91ad6fa | ||
|  | 1971f36547 | ||
|  | 14cdb8bd31 | ||
|  | a3a847aff6 | ||
|  | 9084c6fd1b | ||
|  | a698ef19cb | ||
|  | 2cdfa358eb | ||
|  | ef91ed6254 | ||
|  | c9b5dc63af | ||
|  | f437e49ed2 | ||
|  | 1c64d0b827 | ||
|  | b48e60ea69 | ||
|  | 7330da14eb | ||
|  | 3823968e95 | ||
|  | a69319b9e4 | ||
|  | 895ca677cf | ||
|  | 481f3f13b3 | ||
|  | c55de2e7ea | ||
|  | 9aa6d8f180 | ||
|  | 29b9e8fdd0 | ||
|  | b106b798eb | ||
|  | f361599dc5 | ||
|  | e31ced26f9 | ||
|  | 416d4a3a45 | ||
|  | 930ce7bf70 | ||
|  | d6dc17553d | ||
|  | d64fab95f4 | ||
|  | 61d0e5b401 | ||
|  | dcf5c019b9 | ||
|  | b8dcf71057 | ||
|  | 25068e9f2d | ||
|  | eab6649474 | ||
|  | 16178ecbac | ||
|  | 3a1e6a51cf | ||
|  | c39e347b28 | ||
|  | 657f31b6bc | ||
|  | 6c2d460aa9 | ||
|  | eb0f04ebd7 | ||
|  | cf5e4e466e | ||
|  | a1677cab63 | ||
|  | 021c696120 | ||
|  | d5cd5e490b | ||
|  | 18d4919386 | ||
|  | 485a294fb4 | ||
|  | acfac42957 | ||
|  | 46dbf2e570 | ||
|  | c151ca3679 | ||
|  | aebf16936c | ||
|  | e420628475 | ||
|  | df940bc035 | ||
|  | c13334c38a | ||
|  | 4248e915b3 | ||
|  | 6cafe6f9c5 | ||
|  | b7563eebc8 | ||
|  | 8288b7d26a | ||
|  | 46f49f4686 | ||
|  | ec189139b6 | ||
|  | 4385d32cf6 | ||
|  | 0d309a158e | ||
|  | 89c406d802 | ||
|  | 75b7b01706 | ||
|  | b377e98dbe | ||
|  | ecda9aac4e | ||
|  | 7e545b7b99 | ||
|  | 9dbc8bccf3 | ||
|  | 5cfc275876 | ||
|  | f0dfc59828 | ||
|  | f3cf8360c2 | ||
|  | 5e7ef3d27a | ||
|  | dd4ab4ec0d | ||
|  | fdbe0c4c37 | ||
|  | 8b3f831bbd | ||
|  | 8309afbbd8 | ||
|  | 22e22185b5 | ||
|  | ad4772ce98 | ||
|  | 5d8088ce8c | ||
|  | cbde0e30f7 | ||
|  | 6c9d7f54d8 | ||
|  | 54f23228f8 | ||
|  | 1c557e3f63 | ||
|  | 70172e2a98 | ||
|  | 310a39cd3a | ||
|  | 27fe4304b6 | ||
|  | 4d15f1eb10 | ||
|  | 6c75e81cb7 | ||
|  | f86132fbb1 | ||
|  | a0c331fbd4 | ||
|  | 7422040057 | ||
|  | 3bbdc89d6b | ||
|  | 04caf5b569 | ||
|  | 5721938ea2 | ||
|  | 04a0f81129 | ||
|  | 1e7632abe7 | ||
|  | bd167224cb | ||
|  | 068ae16f50 | ||
|  | 3d74da20e0 | ||
|  | 9533b4b1ba | ||
|  | 86e53ab31d | ||
|  | 1731e68364 | ||
|  | f53c7b82ef | ||
|  | 08225b7e1f | ||
|  | ebf1802374 | ||
|  | c848ad8063 | ||
|  | 9e3fdd0922 | ||
|  | d0ed795da2 | ||
|  | c471549e0d | ||
|  | 42fb9cd0aa | ||
|  | e29c00477b | ||
|  | b6b5254c80 | ||
|  | 4e14121dbd | ||
|  | 06c5fc7af5 | ||
|  | e653f84891 | ||
|  | f497a3a658 | ||
|  | ac0baae856 | ||
|  | 7a042222db | ||
|  | 5ed957b628 | ||
|  | 0dda0201ba | ||
|  | da27eaee98 | ||
|  | 104e966604 | ||
|  | 7a7896b3f1 | ||
|  | 3da57e5351 | ||
|  | acf90b3d7d | ||
|  | d3b220ab50 | ||
|  | 8086251ef5 | ||
|  | a703350639 | ||
|  | e030c693b4 | ||
|  | 19f308ee52 | ||
|  | 2dadcfe4e6 | ||
|  | 3aeeed7951 | ||
|  | 39dacc0b20 | ||
|  | 3a01fa9011 | ||
|  | ffaf9e8aae | ||
|  | 4c65ce4df4 | ||
|  | d4f1c04f07 | ||
|  | c02b19f3eb | ||
|  | 86bbb552c5 | ||
|  | a19b770b9f | ||
|  | e2e2e34f74 | ||
|  | d2a2f5d702 | ||
|  | 9d1ebec018 | ||
|  | ae868f6525 | ||
|  | 99480dc8d3 | ||
|  | 81dbd135e2 | ||
|  | 6633182efe | ||
|  | 2129a8ad8b | ||
|  | 24d16e65d3 | ||
|  | 8f2ac6ed81 | ||
|  | b18e9ce7ae | ||
|  | 30dad1ee7d | ||
|  | cda8a68794 | ||
|  | 33831736a9 | ||
|  | a0170b974d | ||
|  | a009c8379a | ||
|  | d66ff0ede0 | ||
|  | ce1d5ccb5d | ||
|  | 361a857ccd | ||
|  | a024aa6931 | ||
|  | 20408bb71f | ||
|  | b16d4a8af9 | ||
|  | 8f3dc49a76 | ||
|  | 024efa9bcb | ||
|  | a6122f481d | ||
|  | f1b4729b63 | ||
|  | aebe3d75d7 | ||
|  | 05959f7e24 | ||
|  | 8614b5a369 | ||
|  | 7be3016bfa | ||
|  | 72d6e63edc | ||
|  | 7dca4813ed | ||
|  | ab11967a8e | ||
|  | 189186c988 | ||
|  | d1f6348ef3 | ||
|  | 328cff225d | ||
|  | fe682e7a2b | ||
|  | 0631d8ea2e | ||
|  | e995c30eea | ||
|  | 8d4fa0c81d | ||
|  | 3808155201 | ||
|  | 529e0ddccf | ||
|  | 106535fc01 | ||
|  | f053a06231 | ||
|  | 00d90dc8b7 | ||
|  | 999f6190dc | ||
|  | b4d4c3d46b | ||
|  | a63bc61f4a | ||
|  | d66760f9c2 | ||
|  | 76dfe48114 | ||
|  | 23fae77443 | ||
|  | 0e31e19472 | ||
|  | 8e09ea8efc | ||
|  | 0bd31e965d | ||
|  | 34e50b6406 | ||
|  | fb97afe39a | ||
|  | 8ad3292630 | ||
|  | 812e085795 | ||
|  | d0cafeea6d | ||
|  | 4a88944b9c | ||
|  | f3570acc61 | ||
|  | e210352339 | ||
|  | da6bbc2a40 | ||
|  | cada8f6972 | ||
|  | 663cb21eb2 | ||
|  | 8cd4546f9d | ||
|  | 4030225304 | ||
|  | 5b266397ee | ||
|  | b5bfc24916 | ||
|  | 3e9090c6a4 | ||
|  | 2147a1dea8 | ||
|  | a8f83afbf8 | ||
|  | c16559ea1e | ||
|  | 7c6a898bf0 | ||
|  | 84689f602b | ||
|  | e8d89279d6 | ||
|  | 789a5673e3 | ||
|  | cef67555bf | ||
|  | b30ce1c9a2 | ||
|  | 8615e4cb34 | ||
|  | f2d0a09dc8 | ||
|  | 7a04aba3f9 | ||
|  | bc2e68207f | ||
|  | fd9260cc74 | ||
|  | 6f0fbde825 | ||
|  | c8f6b546cb | ||
|  | 341643a87e | ||
|  | 452952670b | ||
|  | 54bcd5979a | ||
|  | 0770065a43 | ||
|  | 0b040a2192 | ||
|  | cc748e1c99 | ||
|  | 97b1cc0f8d | ||
|  | 8aa991ae07 | ||
|  | 5a43d51436 | ||
|  | 590dfcc348 | ||
|  | e2e347bd14 | ||
|  | 4e8a30948d | ||
|  | d61ad0c909 | ||
|  | 87a038b0ed | ||
|  | ebf652932a | ||
|  | 8bd754064e | ||
|  | 8bce4caa97 | ||
|  | acd7915be4 | ||
|  | 5f6e420460 | ||
|  | d8b1251dd8 | ||
|  | 495cea8064 | ||
|  | 89390fa3ff | ||
|  | a887fb8adf | ||
|  | ecd6a00c35 | ||
|  | e75b6b8459 | ||
|  | bc296e0cb9 | ||
|  | c87cff02f7 | ||
|  | 413219ac7a | ||
|  | b6189a2eda | ||
|  | 9c4423b8bc | ||
|  | 0ac5a99433 | ||
|  | 1b95c37826 | ||
|  | cec0cf34e4 | ||
|  | 152defa377 | ||
|  | 499a57880f | ||
|  | 0dbf18c751 | ||
|  | 6a91ea51c9 | ||
|  | 421c7ee0a5 | ||
|  | e08c522066 | ||
|  | 2d71a56011 | ||
|  | 50ab3b2edd | ||
|  | 230ce1822f | ||
|  | df8ef12198 | ||
|  | edfe9b2c2b | ||
|  | 448e057ae8 | ||
|  | b042f60e41 | ||
|  | 08a91c64db | ||
|  | f17509d6d7 | ||
|  | 021f60b7d7 | ||
|  | 6039674de8 | ||
|  | a4476570bd | ||
|  | 7df0f128a3 | ||
|  | 74e78c8e59 | ||
|  | 36f401b165 | ||
|  | 892cae075f | ||
|  | 30f19c6431 | ||
|  | c67611f204 | ||
|  | 0bed36e832 | ||
|  | e45ebaa025 | ||
|  | fcef2eb44b | ||
|  | 8ce27cbc55 | ||
|  | d121bb6a73 | ||
|  | e709e1e74f | ||
|  | a10971e126 | ||
|  | 04c47c0387 | ||
|  | 6a9ce60c47 | ||
|  | 93efa0608a | ||
|  | 7c8a9a28d7 | ||
|  | 47f0099020 | ||
|  | 1fb3f7cb5e | ||
|  | bf784f05ea | ||
|  | 8539bd5d75 | ||
|  | ff8665fbc4 | ||
|  | eee3818332 | ||
|  | 6be2744b49 | ||
|  | 46b9e57ed1 | ||
|  | d62b0bafac | ||
|  | bfef93c8a8 | ||
|  | e7d30c38cd | ||
|  | 780b520878 | ||
|  | c9f8b5939c | ||
|  | 2114486851 | ||
|  | 59061827f1 | ||
|  | 180e43924a | ||
|  | c3674e7e5a | ||
|  | 1218923012 | ||
|  | 0f7842c5c2 | ||
|  | b49521cf3a | ||
|  | 8a7e27b58f | ||
|  | 9493853fe4 | ||
|  | f8e91898af | ||
|  | 7036ed9bc8 | ||
|  | 68bdd92126 | ||
|  | 5bac0e1183 | ||
|  | d23eb73948 | ||
|  | 403dfeb725 | ||
|  | be1b24568a | ||
|  | 38a6ace8d2 | ||
|  | a1c7972f9d | ||
|  | 0222a26313 | ||
|  | 8564a6881e | ||
|  | 580fbf1366 | ||
|  | 567923139d | ||
|  | 3d7d4655f5 | ||
|  | b9afe898b3 | ||
|  | 4234539e65 | ||
|  | 4214ccd49c | ||
|  | dd0c6cf1ef | ||
|  | 8e293e0d9b | ||
| 01bb09da30 | |||
|  | 1e5085f4cc | ||
|  | 467a5d789b | ||
|  | 4c080b7b19 | ||
|  | 31e79f88a3 | ||
|  | bc26d3af46 | ||
|  | 81dee66f6c | ||
|  | 0cc8626866 | ||
|  | 7652208a74 | ||
|  | 1344fa92fe | ||
|  | 11e3bc06f0 | ||
| b2fde1c419 | |||
| 0c65313b35 | |||
|  | 28856c980c | ||
|  | 249917b3d9 | ||
|  | cea33b109f | ||
|  | 6302d125e8 | ||
|  | 0a0913d922 | ||
|  | 7aaf9cd6be | ||
|  | 093d46ee4e | ||
|  | d433c503e4 | ||
|  | 841c67b51d | ||
|  | 993db9585e | ||
|  | 870d2b27bc | ||
|  | d111a4b95c | ||
|  | 708a2193b0 | ||
|  | 670ceae73c | ||
|  | a17182c918 | ||
|  | f9e2fa0222 | ||
|  | bb07c913aa | ||
|  | 7e5b68818f | ||
|  | 695b30855e | ||
|  | 29db1a13cc | ||
|  | e977b079a8 | ||
|  | ea04b618cd | ||
|  | 6c237e8f2f | ||
|  | 5f355e47f1 | ||
|  | addb18b2ef | ||
|  | 4846762d37 | ||
|  | dff66dca3e | ||
|  | 89a7eb3441 | ||
|  | 609b6edbba | ||
|  | be3eca952d | ||
|  | 8fbf846ff9 | ||
|  | ddee2e82b3 | ||
|  | 8d52238a6f | ||
|  | ea5850fb70 | ||
|  | 6a58457c36 | ||
|  | 47596137ec | ||
|  | 124b588a66 | ||
|  | 4670ffee85 | ||
|  | 6a5078dbb7 | ||
|  | 2c89032a7e | ||
|  | bf508e8cb8 | ||
|  | d000c5f394 | ||
|  | c2badb66e2 | ||
|  | 8d3a4ad6c2 | ||
|  | 081effb3b3 | ||
|  | 12331f8970 | ||
|  | 4333cfa0ab | ||
|  | 93b364f049 | ||
|  | 27f208561e | ||
|  | 37893bb106 | ||
|  | 6a79f09476 | ||
|  | 377e1b8f93 | ||
|  | 561d24bade | ||
|  | 23b1b47a7d | ||
|  | fba1d515b2 | ||
|  | 35ad7b031d | ||
|  | 5f67f637d3 | ||
|  | ff75533025 | ||
|  | 6ddadfe53c | ||
|  | 182015e843 | ||
|  | 3f97c9e17e | ||
|  | 5320115e13 | ||
|  | f1f3e6fe5a | ||
|  | 7e5c3c78e6 | ||
|  | 0da7a3e74a | ||
|  | 996c5ab75a | ||
|  | b1d8a3c1ca | ||
|  | 9c4d0868cf | ||
|  | 2f30da9156 | ||
|  | e61cc019e8 | ||
|  | 0bed825f70 | ||
|  | ffeb1b182d | ||
|  | a6141078e0 | ||
|  | c68babb4d0 | ||
|  | 77159304aa | ||
|  | bddfa88823 | ||
|  | 5b41cd85e0 | ||
|  | deb90a8574 | ||
|  | a8547275bd | ||
|  | a10ec22c99 | ||
|  | be61bf2166 | ||
|  | d5f31cbe97 | ||
|  | 470cb4d398 | ||
|  | 982612a1e7 | ||
|  | 3d84a3afe7 | ||
|  | 2c49e28a58 | ||
|  | d5d7314af5 | ||
|  | 05453ed16d | ||
|  | 51185a43ee | ||
|  | e45f6ee040 | ||
|  | e3297fead4 | ||
|  | 543df34425 | ||
|  | 76ccc36824 | ||
|  | d0965fddfe | ||
|  | d4d662a201 | ||
|  | 40e2d71db4 | ||
|  | cd2f56db4f | ||
|  | 443ec1b082 | ||
|  | 46c6bc67ec | ||
|  | 18af0281b1 | ||
|  | b947d4236d | ||
|  | 1abd4c49b0 | ||
|  | a7072daf4a | ||
|  | 22f3a52a14 | ||
|  | cfcbef14c5 | ||
|  | 2193c950d9 | ||
|  | 5eeef42174 | ||
|  | 34e23beaeb | ||
|  | e419339c10 | ||
|  | ba6e3a0c95 | ||
|  | a6401b44b2 | ||
|  | 81e3a86776 | ||
|  | feb76e4d63 | ||
|  | 28ec0d0ef9 | ||
|  | 15fa0bfd38 | ||
|  | ce36a373eb | ||
|  | 38bc07f0fd | ||
|  | 9793ac502f | ||
|  | 00ee02ccb9 | ||
|  | 4cd0fa249c | ||
|  | 66c4ed2b79 | ||
|  | eda173a5a7 | ||
|  | e7006873ca | ||
|  | 1d0f10ddca | ||
|  | c81e461cb5 | ||
|  | a1f9f71d31 | ||
|  | 79eb498a83 | ||
|  | fb89cb1a8d | ||
|  | 90fa4f53f8 | ||
|  | ba22e5f039 | ||
|  | 894f3b7952 | ||
|  | 5aff9d6bc2 | ||
|  | 565d053224 | ||
|  | ee7f70734b | ||
|  | 7d3169b077 | ||
|  | fd33eb238d | ||
|  | 22494d28d3 | ||
|  | e95986c93a | ||
|  | a63e704b1e | ||
|  | 5aa5438dd6 | ||
|  | 7cc92ee011 | ||
|  | 642276cbdc | ||
|  | 039cfb5673 | ||
|  | a176ee54fa | ||
|  | 825c7210e2 | ||
|  | 14abc276c3 | ||
|  | a6b5c47251 | ||
|  | 26ad1124bf | ||
|  | b576a61551 | ||
|  | 275461a474 | ||
|  | d9e4901336 | ||
|  | 66ad57066a | ||
|  | af3ad4ff63 | ||
|  | 7850eb9bb9 | ||
|  | feaa79e1b1 | ||
|  | 904d6f8c49 | ||
|  | b6f0b27b9b | ||
|  | 9ca7094ee4 | ||
|  | c6487873b8 | ||
|  | a6e46660cc | ||
|  | 31f41cbff5 | ||
|  | 725c68ad18 | ||
|  | 2d62200297 | ||
|  | 29495c0ee3 | ||
|  | 554db4fe72 | ||
|  | 39707d88d5 | ||
|  | c42f6006b8 | ||
|  | b69b0e878a | ||
|  | a37da5cfd0 | ||
|  | 83210f5501 | ||
|  | 81a7a77f2c | ||
|  | 17463ed691 | ||
|  | 793c384d58 | ||
|  | 5595f0295d | ||
|  | 8a478fa108 | ||
|  | f14212d1a3 | ||
|  | 44e142d935 | ||
|  | 36a795c585 | ||
|  | d2aa32ee18 | ||
|  | 890d263017 | ||
|  | 4ff8f5c9e1 | ||
|  | 377c48d4a0 | ||
|  | c29791c904 | ||
|  | 489c36ac00 | ||
|  | fef2f1d781 | ||
|  | e3d316d374 | ||
|  | f7fc731773 | ||
|  | 94a6972bda | ||
|  | 838f61b16e | ||
|  | 1a9be3bc1a | ||
|  | 36a1e17314 | ||
|  | aa29336164 | ||
|  | e19b9bcc4a | ||
|  | 8fe8b65535 | ||
|  | 3277618a05 | ||
|  | 2833cd589a | ||
|  | 02e4b80ba1 | ||
|  | 5e9f44e5c4 | ||
|  | 8a830a53d9 | ||
|  | 30a77df14e | ||
|  | d707dea56b | ||
|  | 3aa20736a5 | ||
|  | c61941e6ba | ||
|  | 8b2c78636e | ||
|  | 36a4e6a533 | ||
|  | 7f5cb892af | ||
|  | e03f33a334 | ||
|  | 8379a5be40 | ||
|  | 79539038b7 | ||
|  | 7083bf34a6 | ||
|  | 992cf9a870 | ||
|  | 4db8bb7001 | ||
|  | bab8ba857e | ||
|  | 8f89d2355f | ||
|  | 5848c05c9c | ||
|  | 07fbf08f78 | ||
|  | 4185ce15ae | ||
|  | 2235f5411c | ||
|  | f47f9ad336 | ||
|  | dc91f5b104 | ||
|  | 372d69ea85 | ||
|  | b7647d87bc | ||
|  | 4d3f12785c | ||
|  | fde725abb2 | ||
|  | 0e09eea6cf | ||
|  | a6bad0cba2 | ||
|  | a271861fb1 | ||
|  | be0e713f5b | ||
|  | 3b5d99072a | ||
|  | ae15375d55 | ||
|  | d9082683cc | ||
|  | 4b31a9bbbc | ||
|  | 741460d55b | ||
|  | 9ca1f09fc5 | ||
|  | e270cb25ee | ||
|  | c8429cac20 | ||
|  | 7e51b443c2 | ||
|  | 09f9256f06 | ||
|  | 7f33c522ea | ||
|  | da8c1bdaf2 | ||
|  | 0f122aad76 | ||
|  | 7c19380b22 | ||
|  | 599c04ab62 | ||
|  | 0bafb6ad26 | ||
|  | dd764c99ff | ||
|  | 97fd249134 | ||
|  | 4a434b4009 | ||
|  | cc3af06617 | ||
|  | 01c48a1cd6 | ||
|  | f42b272636 | ||
|  | bebb4bbf04 | ||
|  | e8ff014598 | ||
|  | 240b1537da | ||
|  | c561494d7b | ||
|  | a4ce4af297 | ||
|  | 4d3c2ec149 | ||
|  | 3279bdb348 | ||
|  | 2d6094153e | ||
|  | fed26bc925 | ||
|  | 5f715dedb2 | ||
|  | 0028854ea5 | ||
|  | 632ae0c86c | ||
|  | fc017fcc5a | ||
|  | 8138515a4c | ||
|  | c2a4261ac4 | ||
|  | c17bdd2b2f | ||
|  | 66ec58a21e | ||
|  | 5f320d5a3b | ||
|  | 553b49eb13 | ||
|  | d3c4d69781 | ||
|  | 9b4b16fc57 | ||
|  | c91826f741 | ||
|  | 69e419d9cf | ||
|  | e20a06fa4f | ||
|  | a9ad0a47ae | ||
|  | 370f0093ff | ||
|  | 35ee47189f | ||
|  | 0314be9515 | ||
|  | 883ec09a0e | ||
|  | d12c7b2c5e | ||
|  | 02a4b50fc0 | ||
|  | 5030e55f84 | ||
|  | 5e27020f77 | ||
|  | dc13def187 | ||
|  | 4e9be55405 | ||
|  | 127c018d83 | ||
|  | 3835a9a470 | ||
|  | 28f52973f3 | ||
|  | 7a936f8a9f | ||
|  | 6b55a574d8 | ||
|  | 1182f5b3af | ||
|  | 6858e8eca6 | ||
|  | fe3e06e654 | ||
|  | 78e9e20a5d | ||
|  | 394975f4d5 | ||
|  | 57107ae4ad | ||
|  | b4ae677932 | ||
|  | 4ab84b7766 | ||
|  | 7f4607c3ba | ||
|  | 823e382748 | ||
|  | b1ae10b570 | ||
|  | 82baab5401 | ||
| 8bf6c57668 | |||
|  | 5e4bd93238 | ||
|  | 5f4aa6034f | ||
|  | 101d67ad48 | ||
|  | 7d2fded062 | ||
|  | a79a165d60 | ||
|  | ddd4bfc033 | ||
|  | ae1edfe384 | ||
|  | 44ffb4f607 | ||
|  | 060900ebc7 | ||
|  | 8673ab0197 | ||
|  | bc30cc3e03 | ||
|  | 0de2f5ecf4 | ||
|  | ee933c3460 | ||
|  | 243def0a2f | ||
|  | 991310f9b8 | ||
|  | 30b9a137c2 | ||
|  | 2320fcd462 | ||
|  | 288e652f93 | ||
|  | 9b845a04bf | ||
| 2362f194cf | |||
|  | 2bf45e799f | ||
|  | d28e02d004 | ||
|  | c7e7ab69ea | ||
|  | fe1639c89d | ||
| d1219caea7 | |||
|  | 68a7c57e0b | ||
|  | c5f9f3f3b0 | ||
|  | cc96fa6d65 | ||
|  | 4ac0d0b7d8 | ||
|  | b4a5343ce6 | ||
|  | a07cd5f295 | ||
|  | e73c339a99 | ||
|  | 92b94b2289 | ||
|  | d7c406b0e9 | ||
|  | 6f8b6a01a1 | ||
|  | 9e4bcaa6a4 | ||
|  | df45607495 | ||
|  | 99fab7d22b | ||
|  | c3d404dcbf | ||
|  | 9fc84a5ebf | ||
|  | ffc48ff3fa | ||
|  | dea5786a85 | ||
|  | 851e7a1bbb | ||
|  | 6542952597 | ||
|  | c9cc263d52 | ||
|  | 2f54bd3054 | ||
|  | 34dd1da3f5 | ||
|  | 0cd43bc229 | ||
|  | ce5e2a3330 | ||
|  | 5ca7516c5e | ||
|  | d2961c2760 | ||
|  | 262897223b | ||
|  | 33034b6db2 | ||
|  | bb192c6e68 | ||
|  | 654cc3e644 | ||
|  | dc607c2c91 | ||
|  | ec06d22c00 | ||
|  | 74f7f7a340 | ||
|  | 9bf9905bf7 | ||
|  | 31d7c5b75d | ||
|  | 874851f6ee | ||
|  | eb8862ad1f | ||
|  | ecd5c5c4bd | ||
|  | 43565daed4 | ||
|  | 50631a3e36 | ||
|  | b2b85d4f2d | ||
|  | e7d1bd2af0 | ||
|  | 35498105ec | ||
|  | 13e503cc55 | ||
|  | 29dba7eab7 | ||
|  | d39f1d793b | ||
|  | 120e10d348 | ||
|  | 8e7a8488b3 | ||
|  | 8252fca39f | ||
|  | 32a02f04bd | ||
|  | b20b9bd30c | ||
|  | c48d86ee42 | ||
|  | 33107d6a6e | ||
|  | 9ce1c89d90 | ||
|  | a4311f7acd | ||
|  | 48cbeefa39 | ||
|  | 97520a33ea | ||
|  | 265ec48919 | ||
|  | c56e8127d7 | ||
|  | 8031358f60 | ||
|  | 10cea217bf | ||
|  | 4466f66584 | ||
|  | 2e9cd1c5a9 | ||
|  | 4b560896f6 | ||
|  | 6055ddb90f | ||
|  | 85ae4d8036 | ||
|  | 9383a41500 | ||
|  | f016cd338c | ||
|  | 3af39ca6a9 | ||
|  | 5089b071dd | ||
|  | 07ce838056 | ||
|  | 7e00aa30a9 | ||
|  | 8fa66aeed5 | ||
|  | 791c3a72fd | ||
|  | b09d4980c2 | ||
|  | 37d61417ad | ||
|  | 5f691befb0 | ||
|  | 33babd6b2f | ||
|  | 4e5c201cd2 | ||
|  | 309b1cdffa | ||
|  | 8bd0f97911 | ||
|  | c4caac27f7 | ||
|  | caa7c809ab | ||
|  | fc40512a8e | ||
|  | 73980d8dde | ||
|  | 5f46e2f3d0 | ||
|  | 965a3552c8 | ||
|  | d13d61a17d | ||
|  | 7f5fcdadb6 | ||
|  | 6021b64cd7 | ||
|  | dfbc0ee705 | ||
|  | b71845155e | ||
|  | ad01c3f8f7 | ||
|  | 37dfaf7a6d | ||
|  | c9ab9f853d | ||
|  | 062eb8eb5f | ||
|  | 7fb28c7fd4 | ||
|  | e79d98d623 | ||
|  | cb2d64f92a | ||
|  | 48dc4a3d33 | ||
|  | f1534ffc71 | ||
|  | 7edeb5124e | ||
|  | 7b085f916b | ||
|  | 7aef39843a | ||
|  | 4098093a1c | ||
|  | 3f87bffd17 | ||
|  | 14cd66cf13 | ||
|  | 5acb635f6b | ||
|  | 7d111f90e4 | ||
|  | cbc57959e3 | ||
|  | c56e28081a | ||
|  | 5237a6edbb | ||
|  | 4f5963697b | ||
|  | eae8459ca5 | ||
|  | 3efb7f43d2 | ||
|  | ee8dda577b | ||
|  | 87e7fa45ce | ||
|  | d6cdc715b5 | ||
|  | d04559427e | ||
|  | d11670366d | ||
|  | 3e393880b1 | ||
|  | 9c9146ca8c | ||
|  | 22174f431d | ||
|  | ea5e35d8b4 | ||
|  | e0b7c76b9a | ||
|  | 3284aaca02 | ||
|  | c9db239b23 | ||
|  | 8806c1357f | ||
|  | dbe55db84d | ||
|  | 9dbe2fde3f | ||
|  | e7301e6cb9 | ||
|  | a86f37ecfc | ||
|  | 531ab674f3 | ||
|  | 31cbb5d2bf | ||
|  | 96acf75571 | ||
|  | f09c27abb2 | ||
|  | ccea7494e6 | ||
|  | 856b27fd33 | ||
|  | 19b2ec07d9 | ||
|  | 19fde2b445 | ||
|  | 8c3c5f8876 | ||
|  | 042139091a | ||
|  | 1a318d4d2a | ||
|  | 225b2eb035 | ||
|  | a477039f7c | ||
|  | 1b63596355 | ||
|  | 69f4fe5f36 | ||
|  | 056730c338 | ||
|  | cb549dd492 | ||
|  | 0f8859cf3c | ||
|  | 1d4e69460a | ||
|  | bdf6459fd6 | ||
|  | 6e5657e446 | ||
|  | 1f41eb6acc | ||
|  | 9e80281542 | ||
|  | 26d1fbf8be | ||
|  | 75e646832b | ||
|  | a12ea7d641 | ||
|  | aeb4fcd452 | ||
|  | a62913ee6c | ||
|  | b1a8a70bdd | ||
|  | 549ef25edf | ||
|  | fd70858523 | ||
|  | 850dd34da9 | ||
|  | ee67948bc0 | ||
|  | 7561f7af27 | ||
|  | 6813e9d75b | ||
|  | ef51d99f66 | ||
|  | b482e6d691 | ||
|  | 91cbb0928b | ||
|  | 1e9ac9d65a | ||
|  | 2757dcf19c | ||
|  | f895172405 | ||
|  | a9351c58d3 | ||
|  | 0d5ae1bf0c | ||
|  | 84605fd1e7 | ||
|  | 9209ac9fae | ||
|  | e78cdbe81d | ||
|  | f178667db8 | ||
|  | fb0354221d | ||
|  | bda2b10c7f | ||
|  | 719a45a4c2 | ||
|  | 69eead6c28 | ||
|  | 40a2cb39b8 | ||
|  | 657dcea2a1 | ||
|  | 5d6d98abc2 | ||
|  | 0d3d163aec | ||
|  | a83b4746f9 | ||
|  | 458b41b5f6 | ||
|  | 3c04ca7c5a | ||
|  | 81d437399c | ||
|  | cc3fc6a8bd | ||
|  | bd41857962 | ||
|  | ff4f83959a | ||
|  | 46d5a004d4 | ||
|  | 3f49a771c5 | ||
|  | 9fddbc5e6a | ||
|  | d3036b3b89 | ||
|  | 1e59444e0e | ||
|  | 1fa3081b08 | ||
|  | ec1860cece | ||
|  | cc1dc9173d | ||
|  | 025eb8e865 | ||
|  | 3e5acf655e | ||
|  | bf31cb10da | ||
|  | ffcf343915 | ||
|  | 86e99e0c74 | ||
|  | f0e20994a2 | ||
|  | 9739073178 | ||
|  | 07f27ac44c | ||
|  | 281acb69be | ||
|  | 6bf1d00455 | ||
|  | 290bb93b49 | ||
|  | f7bf8f8f35 | ||
|  | d93ae197e3 | ||
|  | 2dee5e3b37 | ||
|  | 5d95afe99d | ||
|  | 9bb702549e | ||
|  | 5360102236 | ||
|  | e6cebd42b3 | ||
|  | 6f41acf447 | ||
|  | c7c8f1d72e | ||
|  | 8f8e8afa83 | ||
|  | 6fae11838c | ||
|  | 6577e406a4 | ||
|  | 53aeb4c43a | ||
|  | 8c85768a4d | ||
|  | f7de5fc391 | ||
|  | c0d80e528e | ||
|  | 361012c80e | ||
|  | 8832a8365c | ||
|  | fa2e1968bb | ||
|  | 91ac09a2e3 | ||
|  | f1b35354dc | ||
|  | 34694492b9 | ||
|  | b1b35b05cf | ||
|  | 1c8d53cec5 | ||
|  | 8efb289cc4 | ||
|  | b2ddce303f | ||
|  | ade9638c13 | ||
|  | c762999f67 | ||
|  | 026fd37a22 | ||
|  | 7691c392e4 | ||
|  | 32f8cbf995 | ||
|  | 2894dac5d8 | ||
|  | 99f086a75a | ||
|  | 6eac863f34 | ||
|  | e917c16c2c | ||
|  | bb3015f626 | ||
|  | a9e63cca54 | ||
|  | f753f534a4 | ||
|  | 046715d4b6 | ||
|  | cfb0177a45 | ||
|  | 12b3a48baa | ||
|  | e710fc4604 | ||
|  | edc371ed30 | ||
|  | 54f1356756 | ||
|  | e02fcd6a08 | ||
|  | 2ac19ef81f | ||
|  | 10d9d5ee65 | ||
|  | c8fd7fa5f2 | ||
|  | f9f2812344 | ||
|  | f9411b7278 | ||
|  | 2f01516cff | ||
|  | 1940a24a05 | ||
|  | 0a9ce48880 | ||
|  | 3bec4fc26d | ||
|  | d9499cae4a | ||
|  | a2207a781f | ||
|  | 4fd7e4ee2a | ||
|  | 9f9eb7d23a | ||
|  | ab3604d613 | ||
|  | 5a56b3be3f | ||
|  | 7c1aedd461 | ||
|  | 2a7dec2811 | ||
|  | 0530e553eb | ||
|  | 2b33f221d6 | ||
|  | 6c1167a98a | ||
|  | 464a12ad1e | ||
|  | f431ddb5f8 | ||
|  | 1295278175 | ||
|  | fe87373cfb | ||
|  | 30078c1755 | ||
|  | c11b74d689 | ||
|  | ac5400fb6c | ||
|  | 919612648a | ||
|  | c78b43c01c | ||
|  | bfd0b7767b | ||
|  | 0067f9ecbc | ||
|  | 3ede04c0c3 | ||
|  | 36f979a67a | ||
|  | 2f42c353e4 | ||
|  | 28d958ecc9 | ||
|  | 880a144cc1 | ||
|  | 7857bfab40 | ||
|  | 0303017f2b | ||
|  | ab4692b655 | ||
|  | b26eb2e1dc | ||
|  | 88e9c450b5 | ||
|  | 08c8fe0366 | ||
|  | 0284997d6a | ||
|  | b03ba3b988 | ||
|  | 298bae5301 | ||
|  | 39a4916939 | ||
|  | 77bd0c256f | ||
|  | 3ba14427a5 | ||
|  | ac869994a7 | ||
|  | 3f30a1cbd1 | ||
|  | 2421df4995 | ||
|  | 71261b4a82 | ||
|  | 9df5e447eb | ||
|  | 9b25a8fa0e | ||
|  | e898b55fa3 | ||
|  | f740372e71 | ||
|  | 8f73ddb063 | ||
|  | 90fed1bae2 | ||
|  | 4d5b7f3664 | ||
|  | cb7493c6c9 | ||
|  | 9c69aab95c | ||
|  | c228aaa7af | ||
|  | a8d4dede1d | ||
|  | b07607a932 | ||
|  | 962ea61fa5 | ||
|  | 57e8a411c2 | ||
|  | 2a48e816f4 | ||
|  | 97611a8dc8 | ||
|  | ce113372e8 | ||
|  | f204f3fff3 | ||
|  | aa9a3a92f1 | ||
|  | edddb02dfe | ||
|  | 407c1a8db0 | ||
|  | 7d265446c4 | ||
|  | 575606766f | ||
|  | 4a0f4535d0 | ||
|  | 06e75084bb | ||
|  | 89a22c82c9 | ||
|  | 1bbb14bf5d | ||
|  | b082164ff6 | ||
|  | 2a0b67be09 | ||
|  | e437812fd5 | ||
|  | fb0291ff99 | ||
|  | fd90a48b9c | ||
|  | ba1fdf332b | ||
|  | c1ca2fa181 | ||
|  | 8549f68fbd | ||
|  | b597eb5916 | ||
|  | 646902cc53 | ||
|  | 48535c313e | ||
|  | 368a490502 | ||
|  | 8f5cf47c75 | ||
|  | 3a4dabae4e | ||
|  | e608ab6204 | ||
|  | d97f650fb5 | ||
|  | 4c6142d0b6 | ||
|  | 5ed1532762 | ||
|  | 368ec56181 | ||
|  | 65455afb58 | ||
|  | 21d32a888d | ||
|  | 8da835bd0b | ||
|  | 843a5b83c5 | ||
|  | a8347e622d | ||
|  | ef3c99e086 | ||
|  | 0acae3b222 | ||
|  | 73442de46c | ||
|  | 8a73e9cb2c | ||
|  | b13b8a0ded | ||
|  | 9c05b0d79c | ||
|  | 5dfa42880e | ||
|  | 9af93d42f7 | ||
|  | 58def567cd | ||
|  | b944c0f25f | ||
|  | 5e2fcdea28 | ||
|  | adee39f37f | ||
|  | d00b876181 | ||
|  | 039d65c94d | ||
|  | 39849cea5a | ||
|  | 2e13f43057 | ||
|  | aff79a6d5f | ||
|  | f90c7c2c6f | ||
|  | 7c49db0a33 | ||
|  | 5992e78365 | ||
|  | 71e7bb68ab | ||
|  | ff684ffe83 | ||
|  | 854fb197bb | ||
|  | 6716deb004 | ||
|  | b631420500 | ||
|  | 43527038aa | ||
|  | 419469b52d | ||
|  | b206dfa77f | ||
|  | 7ef87ef44f | ||
|  | 45432afb6f | ||
|  | 4daab388ab | ||
|  | a50e13a8df | ||
|  | dd662e8d22 | ||
|  | ece325a45e | ||
|  | f7de989f59 | ||
|  | 3be7075a08 | ||
|  | 2ca0518c98 | ||
|  | 60a8791e92 | ||
|  | 1f9295f1a7 | ||
|  | 769d69b8be | ||
|  | 6e12c5d4ce | ||
|  | fcda3b5e8e | ||
|  | d4692f883d | ||
|  | a08f2525ee | ||
|  | 5ad966a025 | ||
|  | b2f9169f9f | ||
|  | 54d4ebcd4d | ||
|  | c661413585 | ||
|  | 87739cf75e | ||
|  | 3ef31d3631 | ||
|  | 398e0890ba | ||
|  | b70bff5807 | ||
|  | 15f5d59794 | ||
|  | 25edd8b7df | ||
|  | 34ca42cfa3 | ||
|  | efd31eaaa5 | ||
|  | de4eccb8c8 | ||
|  | 7368889731 | ||
|  | 1c38847eff | ||
|  | e68efdd6fe | ||
|  | e0a0cea985 | ||
|  | 6d5eeb2174 | ||
|  | 4700c71a44 | ||
|  | 552c91eb23 | ||
|  | cf582b359a | ||
|  | 1ec38cb03d | ||
|  | 05129aa200 | ||
|  | 57abf72ecd | ||
|  | b0051271da | ||
|  | f46198b63f | ||
|  | d5246f6863 | ||
|  | eff73b831b | ||
|  | a804b82b06 | ||
|  | e16c1d6c85 | ||
|  | 0fc014b17b | ||
|  | 05aad4b68e | ||
|  | 653e441f55 | ||
|  | cf80182740 | ||
|  | 0c2ac4808a | ||
|  | ebce8b7025 | ||
|  | fc1e0812f5 | ||
|  | 81f3a4b35d | ||
|  | 3f1084a542 | ||
|  | 6f129181f3 | ||
|  | f6ab2c9306 | ||
|  | 9ea39b1386 | ||
|  | 6e98d28b88 | ||
|  | cae010c2fc | ||
|  | 1b9c231a08 | ||
|  | 8883aaceb1 | ||
|  | afeb2ffbec | ||
|  | 1d6f9d4928 | ||
|  | 7b11e728ff | ||
|  | 2e2c38848a | ||
|  | 617ef4b9c9 | ||
|  | efc537a45b | ||
|  | 1ae777d0d5 | ||
|  | dd33829b39 | ||
|  | 8edddb8cda | ||
|  | f68fef4012 | ||
|  | 5a287a627a | ||
|  | 37c6f38354 | ||
|  | 68b8c4f43d | ||
|  | 422b809a08 | ||
|  | d34a69d143 | ||
|  | e8b49517e2 | ||
|  | b1d31708da | ||
|  | 6c44cf5a65 | ||
|  | 06f02e3435 | ||
|  | 28968f7cbb | ||
|  | bc5408bfbc | ||
|  | 072c780824 | ||
|  | c0cbb61731 | ||
|  | 73355a8f07 | ||
|  | eef6c52ac5 | ||
|  | 33a5d975ce | ||
|  | ee91eeb7c5 | ||
|  | c85c6f85fa | ||
|  | 7b6640a42e | ||
|  | 4b2aee6d04 | ||
|  | 49426284fc | ||
|  | 2c7a536d28 | ||
|  | 6b9dd3d898 | ||
|  | da7691db33 | ||
|  | e4aa26de64 | ||
|  | d6b806bd02 | ||
|  | 61afcd2d98 | ||
|  | 183885134d | ||
|  | 981c6cf3f8 | ||
|  | 6a847bd991 | ||
|  | 99ee6f83f9 | ||
|  | 9454c5a1de | ||
|  | 4130d0ceb4 | ||
|  | be394a53c2 | ||
|  | d037a7d938 | ||
|  | bbdd34f0ec | ||
|  | c09ead4515 | ||
|  | 90293be2fa | ||
|  | 3d58a98b38 | ||
|  | fc395682d8 | ||
|  | 6ee02bb486 | ||
|  | 43a4d05d60 | ||
|  | 2760adc7b9 | ||
|  | de8d58766c | ||
|  | 9a56c2ee8a | ||
|  | 945d538bad | ||
|  | 4a5e04c2be | ||
|  | 7a0d77770d | ||
|  | 623fc73640 | ||
|  | ccf21dacb5 | ||
|  | 1744f27b75 | ||
|  | e3d8559ff6 | ||
|  | 7137263693 | ||
|  | 05baf15363 | ||
|  | 2b50fdf5a4 | ||
|  | b70e270475 | ||
|  | 80704876f0 | ||
|  | ded1bbfcb9 | ||
|  | ce1fd46b7e | ||
|  | 44ca30cbf3 | ||
|  | 3e69a37fa6 | ||
|  | eaa57ebec8 | ||
|  | dc4a9761e9 | ||
|  | fc695b80f7 | ||
|  | 1938c91e05 | ||
|  | d0ccae9c1a | ||
|  | 5bc00ec520 | ||
|  | 20b04d1789 | ||
|  | 5a9f0ae9d1 | ||
|  | a75d96561c | ||
|  | e86f473fc0 | ||
|  | e5591db83a | ||
|  | af298ca17e | ||
|  | c112e7cde8 | ||
|  | 100d75fec0 | ||
|  | d8fcd77b4f | ||
|  | 95d22d59f6 | ||
|  | f4fe01797d | ||
|  | f2b9834cb1 | ||
|  | 0d7c0a9671 | ||
|  | ccc6455274 | ||
|  | 083c1ff068 | ||
|  | be15c94417 | ||
|  | 9de3f32d6c | ||
|  | 7590a5bcb2 | ||
|  | 7bbdaee6d3 | ||
|  | e445063afc | ||
|  | 59542c73b3 | ||
|  | 4bb6e3be77 | ||
|  | 88296e0f3e | ||
|  | 425cb93e8d | ||
|  | f18a7fd85c | ||
|  | e67a8c4ac2 | ||
|  | dbbd384221 | ||
|  | bca314e635 | ||
|  | 7b5841122e | ||
|  | 58ec778b3e | ||
|  | c04bcbf90e | ||
|  | 89b39916d7 | ||
|  | b388d03536 | ||
|  | 097b434712 | ||
|  | 392ffee1ea | ||
|  | 84299df63e | ||
|  | 4e1cf8a814 | ||
|  | de53dfed54 | ||
|  | cc06862696 | ||
|  | 2d76c3fee4 | ||
|  | d7d6f12142 | ||
|  | cf2de900f0 | ||
|  | 6a39364b03 | ||
|  | 38d01b37fd | ||
|  | 98946c1e28 | 
							
								
								
									
										4
									
								
								.env.oms
									
									
									
									
									
										Normal file
									
								
							
							
						
						| @@ -0,0 +1,4 @@ | ||||
| VUE_APP_SCOPE=oms | ||||
| VUE_APP_API=http://192.168.1.87:19897 | ||||
| VUE_APP_IS_SIMPLE_SERVER=1 | ||||
| VUE_APP_PORT=19897 | ||||
							
								
								
									
										5
									
								
								.env.xumu
									
									
									
									
									
										Normal file
									
								
							
							
						
						| @@ -0,0 +1,5 @@ | ||||
| VUE_APP_SCOPE=xumu | ||||
| VUE_APP_API=http://192.168.1.87:12413 | ||||
| VUE_APP_IS_SIMPLE_SERVER=1 | ||||
| VUE_APP_PORT=12413 | ||||
| VUE_APP_OMS_ID=2cd70a15-a3cf-4b4d-9a22-0f3b3a888b08   # oms定制方案的ID | ||||
							
								
								
									
										6
									
								
								.gitignore
									
									
									
									
										vendored
									
									
								
							
							
						
						| @@ -25,3 +25,9 @@ yarn-error.log* | ||||
| /oms/dist/ | ||||
| /project/*/index.js | ||||
| /project/*/dist | ||||
| /ui/package-lock.json | ||||
| /examples/modules.json | ||||
| /examples/router/apps.js | ||||
| /src/apps/ | ||||
| /src/config.json | ||||
| /src/utils/apps.js | ||||
|   | ||||
| @@ -6,6 +6,7 @@ core/ | ||||
| public/ | ||||
| project/ | ||||
| .idea/ | ||||
| ui/lib/ | ||||
|  | ||||
| # 忽略指定文件 | ||||
| vue.config.js | ||||
|   | ||||
							
								
								
									
										6
									
								
								.npmrc
									
									
									
									
									
								
							
							
						
						| @@ -1,6 +1,4 @@ | ||||
| registry=http://cli.sinoecare.net/ | ||||
| email=aixianling@sinoecare.com | ||||
| always-auth=true | ||||
| _auth="YWRtaW46YWRtaW4xMjM=" | ||||
| package-lock=false | ||||
|  | ||||
| registry=http://registry.npmmirror.com | ||||
| legacy-peer-deps=true | ||||
|   | ||||
							
								
								
									
										38
									
								
								bin/appsSync.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						| @@ -0,0 +1,38 @@ | ||||
| const axios = require("axios"); | ||||
| const {chalkTag, findApp, fs} = require("./tools"); | ||||
| const compiler = require('vue-template-compiler') | ||||
| 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(() => 0) | ||||
|   } else return Promise.reject("没有应用") | ||||
| } | ||||
| const getAppInfo = (file, apps) => { | ||||
|   if (/[\\\/](App[A-Z][^\\\/]+)\.vue$/g.test(file)) { | ||||
|     const name = file.replace(/.+[\\\/](App[^\\\/]+)\.vue$/, '$1'), | ||||
|         source = fs.readFileSync(file).toString(), | ||||
|         parsed = compiler.parseComponent(source), | ||||
|         script = parsed.script?.content || "", | ||||
|         label = script.match(/label:[^,]+/)?.[0]?.replace(/.+["']([^"']+).+/, '$1') | ||||
|     apps.push({ | ||||
|       id: file.replace(/\.vue$/, '').replace(/[\\\/]/g, '_'), | ||||
|       label: label || name, | ||||
|       libPath: `/${file.replace(/\.vue$/, '').replace(/[\\\/]/g, '/')}`, | ||||
|       name, | ||||
|       type: 'web' | ||||
|     }) | ||||
|   } | ||||
| } | ||||
| const sync = () => { | ||||
|   chalkTag.info("开始扫描库工程...") | ||||
|   const list = [] | ||||
|   Promise.all([ | ||||
|     findApp('packages', app => getAppInfo(app, list)), | ||||
|     findApp('project', app => getAppInfo(app, list)), | ||||
|   ]).then(() => { | ||||
|     chalkTag.info("正在同步...") | ||||
|     saveApps({type: "web", list}).catch(() => 0).finally(() => chalkTag.done("同步成功!")) | ||||
|   }) | ||||
| } | ||||
| sync() | ||||
							
								
								
									
										99
									
								
								bin/build.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						| @@ -0,0 +1,99 @@ | ||||
| const axios = require('axios') | ||||
| const {fsExtra, copyFiles, findApp, chalkTag, fs} = require("./tools"); | ||||
| const compiler = require('vue-template-compiler') | ||||
| const getBuildConfig = id => { | ||||
|   axios.post('http://192.168.1.87:12525/node/custom/detail', null, {params: {id}}).then(res => { | ||||
|     if (res?.data) { | ||||
|       const config = res.data.data | ||||
|       fsExtra.outputJson('src/config.json', config.extra) | ||||
|       createPages(config) | ||||
|     } | ||||
|   }) | ||||
| } | ||||
| const getAppInfo = (file, apps) => { | ||||
|   if (/[\\\/](App[A-Z][^\\\/]+)\.vue$/g.test(file)) { | ||||
|     const name = file.replace(/.+[\\\/](App[^\\\/]+)\.vue$/, '$1'), | ||||
|       source = fs.readFileSync(file).toString(), | ||||
|       parsed = compiler.parseComponent(source), | ||||
|       script = parsed.script?.content || "", | ||||
|       label = script.match(/label:[^,]+/)?.[0]?.replace(/.+["']([^"']+).+/, '$1') | ||||
|     const paths = file.split(/[\\\/]/) | ||||
|     apps.push({ | ||||
|       id: file.replace(/\.vue$/, '').replace(/[\\\/]/g, '_'), | ||||
|       label: label || name, | ||||
|       path: `/${file.replace(/\.vue$/, '').replace(/[\\\/]/g, '/')}`, | ||||
|       workspace: paths.at(0), | ||||
|       esm: file.replace(/[\\\/]/g, '/').substring(4), | ||||
|       name | ||||
|     }) | ||||
|   } | ||||
| } | ||||
|  | ||||
| /** | ||||
|  * 根据配置生成应用路由 | ||||
|  * @param {Object} config - 配置对象,用于定制化路由生成过程 | ||||
|  * @returns {Promise} - 返回一个Promise对象,表示路由生成完成 | ||||
|  */ | ||||
| const createRoutes = (config = {}) => { | ||||
|   // 初始化路由数组 | ||||
|   const routes = [] | ||||
|   // 获取签到页面的路径,如果未指定,则使用默认路径 | ||||
|   let signPage = '../views/sign' | ||||
|   let {signPage: sign, homePage: home = "console"} = config.extra || {} | ||||
|   if (config.extra?.signPage) { | ||||
|     signPage = `../apps/custom/${sign}/${sign}` | ||||
|   } | ||||
|   let homePage = `../views/console` | ||||
|   if (config.extra?.homePage) { | ||||
|     homePage = `../apps/custom/${home}/${home}` | ||||
|   } | ||||
|   // 查找并处理所有应用,将它们的信息添加到路由中 | ||||
|   return findApp("src/apps", app => getAppInfo(app, routes)).then(() => { | ||||
|     // 生成并输出apps.js文件,定义所有应用的路由 | ||||
|     fsExtra.outputFile('src/utils/apps.js', `export default [ | ||||
|     {path: "/login", name: "登录", component: () => import('${signPage}')}, | ||||
|     {path: '/dv', name: '数据大屏入口', component: () => import('../views/dvIndex')}, | ||||
|     {path: '/v', name: 'Home', component: () => import('../views/home'), children: [ | ||||
|       {path:'/',name:'mainEntry', component:()=>import('../views/mainEntry'),children:[ | ||||
|       {name: "${home}", path: "${home}", component: () => import('${homePage}')}, | ||||
|       ${routes.filter(e => ![sign, home].includes(e.name)).map(e => { | ||||
|       // 解构每个路由的属性,用于生成路由配置 | ||||
|       const {name, label, esm} = e | ||||
|       // 生成单个路由配置的字符串表示 | ||||
|       return `{name:"${name}",label:"${label}",path:"${name}",component:()=>import("../${esm}")}` | ||||
|     }).join(',\n')}, | ||||
|       {path: '*',name: '404',component: ()=>import('../views/building')}, | ||||
|       ]} | ||||
|     ]}, | ||||
|     {path: '/', name: "init"}, | ||||
|      | ||||
|     ]`) | ||||
|     // 扫描完毕,使用chalkTag标记任务完成 | ||||
|     chalkTag.done("扫描完毕") | ||||
|   }) | ||||
| } | ||||
|  | ||||
| const createPages = (config = {}) => { | ||||
|   fsExtra.emptyDir("src/apps", err => { | ||||
|     if (!err) { | ||||
|       const {customPath, appList} = config | ||||
|       const stdApps = {} | ||||
|       appList.filter(e => !/project/.test(e.id))?.forEach(e => { | ||||
|         const paths = e.libPath.split('/').filter(Boolean) || [] | ||||
|         paths.pop() | ||||
|         stdApps[paths.join("/")] = 1 | ||||
|       }) | ||||
|       Promise.all([ | ||||
|         copyFiles("src/apps/core", "packages/core"), | ||||
|         copyFiles("src/apps/custom", `project/${customPath}`), | ||||
|         ...Object.keys(stdApps).map(e => copyFiles(`src/apps/${e.replace(/^packages[\\\/]/, '')}`, e)), | ||||
|       ]).then(() => createRoutes(config)).then(() => fsExtra.ensureFile("src/apps/actions.js")) | ||||
|     } | ||||
|   }) | ||||
| } | ||||
|  | ||||
| const start = () => { | ||||
|   const buildId = process.argv[2] || process.env.VUE_APP_OMS_ID || 'f670cc46-7cf7-4a0f-86ee-3077044c0b17' | ||||
|   getBuildConfig(buildId) | ||||
| } | ||||
| start() | ||||
							
								
								
									
										37
									
								
								bin/scanApps.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						| @@ -0,0 +1,37 @@ | ||||
| const {chalkTag, findApp, fs, fsExtra} = require("./tools"); | ||||
| const compiler = require('vue-template-compiler') | ||||
| const getAppInfo = (file, apps) => { | ||||
|   if (/[\\\/](App[A-Z][^\\\/]+)\.vue$/g.test(file)) { | ||||
|     const name = file.replace(/.+[\\\/](App[^\\\/]+)\.vue$/, '$1'), | ||||
|       source = fs.readFileSync(file).toString(), | ||||
|       parsed = compiler.parseComponent(source), | ||||
|       script = parsed.script?.content || "", | ||||
|       label = script.match(/label:[^,]+/)?.[0]?.replace(/.+["']([^"']+).+/, '$1') | ||||
|     const paths = file.split(/[\\\/]/) | ||||
|     apps.push({ | ||||
|       id: file.replace(/\.vue$/, '').replace(/[\\\/]/g, '_'), | ||||
|       label: label || name, | ||||
|       path: `/${file.replace(/\.vue$/, '').replace(/[\\\/]/g, '/')}`, | ||||
|       workspace: paths.at(0), | ||||
|       esm: file.replace(/[\\\/]/g, '/'), | ||||
|       name | ||||
|     }) | ||||
|   } | ||||
| } | ||||
|  | ||||
| const start = () => { | ||||
|   chalkTag.info("开始扫描库工程...") | ||||
|   const {VUE_APP_SCOPE, VUE_APP_CORE} = process.env | ||||
|   const list = [] | ||||
|   let scanScope = ['packages', 'project'] | ||||
|   if (VUE_APP_SCOPE) scanScope = [`project/${VUE_APP_SCOPE}`] | ||||
|   if (VUE_APP_CORE) scanScope.push('packages/core') | ||||
|   Promise.all(scanScope.map(e => findApp(e, app => getAppInfo(app, list)))).then(() => { | ||||
|     fsExtra.outputFile('examples/router/apps.js', `export default [${list.map(e => { | ||||
|       const {name, label, path, esm} = e | ||||
|       return `{name:"${name}",label:"${label}",path:"${path}",component:()=>import("@${esm}")}` | ||||
|     }).join(',\n')}]`) | ||||
|     chalkTag.done("扫描完毕") | ||||
|   }) | ||||
| } | ||||
| start() | ||||
							
								
								
									
										70
									
								
								bin/tools.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						| @@ -0,0 +1,70 @@ | ||||
| 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(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} | ||||
| @@ -1,5 +0,0 @@ | ||||
| apps/ | ||||
| index.js | ||||
| *.map | ||||
| vcapps.import.js | ||||
| dist/ | ||||
| @@ -1,45 +0,0 @@ | ||||
| /** | ||||
|  * 系统业务模块 | ||||
|  * @param Vue 外部接入Vue | ||||
|  * @param params showList:打印加载的应用;apps:加载的应用文件名数组 | ||||
|  */ | ||||
|  | ||||
| const install = function (Vue, params) { | ||||
|   if (install.installed) return Promise.resolve() | ||||
|   else { | ||||
|     // 遍历工作控件内的应用 | ||||
|     let apps = [] | ||||
|     let contexts = require.context('.', true, /\.(\/.+)\/App[^\/]+\.vue$/) | ||||
|     if (contexts) { | ||||
|       contexts.keys().map(e => { | ||||
|         if (contexts(e).default) { | ||||
|           if (params?.apps) { | ||||
|             if (params?.apps.includes(contexts(e).default.name)) { | ||||
|               apps.push(contexts(e).default) | ||||
|               Vue.component(contexts(e).default.name, contexts(e).default) | ||||
|             } | ||||
|           } else { | ||||
|             apps.push(contexts(e).default) | ||||
|             Vue.component(contexts(e).default.name, contexts(e).default) | ||||
|           } | ||||
|         } | ||||
|       }) | ||||
|       // apps.map(e=>{ | ||||
|       //   console.log(e.name,e.label) | ||||
|       // }) | ||||
|       !!params?.showList && console.log(apps.map(e => e.name)) | ||||
|     } | ||||
|     return Promise.resolve(apps) | ||||
|   } | ||||
|  | ||||
| } | ||||
|  | ||||
| // 判断是否是直接引入文件 | ||||
| if (typeof window !== 'undefined' && window.Vue) { | ||||
|   install(window.Vue) | ||||
| } | ||||
|  | ||||
| export default { | ||||
|   // 导出的对象必须具有 install,才能被 Vue.use() 方法安装 | ||||
|   install | ||||
| } | ||||
| @@ -1,12 +0,0 @@ | ||||
| { | ||||
|   "name": "dvcp-core", | ||||
|   "description": "系统业务模块", | ||||
|   "version": "1.0.13", | ||||
|   "main": "dist/dvcp-core.common.js", | ||||
|   "files": [ | ||||
|     "dist" | ||||
|   ], | ||||
|   "publishConfig": { | ||||
|     "registry": "http://cli.sinoecare.net" | ||||
|   } | ||||
| } | ||||
| @@ -2,14 +2,20 @@ | ||||
|   <div id="app"> | ||||
|     <header-nav v-if="showTools" title="web端产品库"> | ||||
|       <template #right> | ||||
|         <mock/> | ||||
|         <div @click="showTools=false,dvDev=true">大屏开发</div> | ||||
|         <div @click="showTools=false">隐藏工具栏</div> | ||||
|         <div @click="handleLogin">点此登录</div> | ||||
|       </template> | ||||
|     </header-nav> | ||||
|     <el-row class="fill mar-t48" type="flex"> | ||||
|       <slider-nav v-if="showTools"/> | ||||
|       <main-content class="fill"/> | ||||
|     <ai-dv-wrapper class="fill" v-if="dvDev"> | ||||
|       <router-view v-bind="commonAttrs"/> | ||||
|     </ai-dv-wrapper> | ||||
|     <el-row v-else-if="showTools" class="fill mar-t48" type="flex"> | ||||
|       <slider-nav/> | ||||
|       <main-content class="fill" :commonAttrs="commonAttrs"/> | ||||
|     </el-row> | ||||
|     <router-view class="fill" v-else v-bind="commonAttrs"/> | ||||
|     <div v-if="dialog" class="sign-box"> | ||||
|       <ai-sign style="margin: auto" :instance="$request" :action="{login}" | ||||
|                visible @login="getToken" :showScanLogin="false"/> | ||||
| @@ -23,10 +29,12 @@ import SliderNav from "./components/sliderNav"; | ||||
| import MainContent from "./components/mainContent"; | ||||
| import HeaderNav from "./components/headerNav"; | ||||
| import {mapActions, mapMutations, mapState} from "vuex"; | ||||
| import Mock from "./components/mock"; | ||||
| import AiDvWrapper from "dui/dv/layout/AiDvWrapper/AiDvWrapper.vue"; | ||||
|  | ||||
| export default { | ||||
|   name: 'app', | ||||
|   components: {HeaderNav, MainContent, SliderNav}, | ||||
|   components: {AiDvWrapper, Mock, HeaderNav, MainContent, SliderNav}, | ||||
|   computed: { | ||||
|     ...mapState(['user']), | ||||
|     login() { | ||||
| @@ -34,16 +42,29 @@ export default { | ||||
|       /project\/sass/g.test(location.pathname) && (url += "?corpId=ww596787bb70f08288") | ||||
|       return url | ||||
|     }, | ||||
|     commonAttrs() { | ||||
|       return { | ||||
|         instance: this.$request, | ||||
|         dict: this.$dict, | ||||
|         permissions: this.$permissions | ||||
|       } | ||||
|     } | ||||
|   }, | ||||
|   data() { | ||||
|     return { | ||||
|       dialog: false, | ||||
|       showTools: true, | ||||
|       dvDev: false | ||||
|     } | ||||
|   }, | ||||
|   watch: { | ||||
|     showTools(v) { | ||||
|       v && (this.dvDev = false) | ||||
|     } | ||||
|   }, | ||||
|   methods: { | ||||
|     ...mapMutations(['setToken', 'setFinanceUser']), | ||||
|     ...mapActions(['getUserInfo']), | ||||
|     ...mapMutations(['setToken']), | ||||
|     ...mapActions(['getUserInfo', 'getFinanceUser']), | ||||
|     getToken(params) { | ||||
|       if (params.access_token) { | ||||
|         this.setToken([params.token_type, params.access_token].join(' ')) | ||||
| @@ -58,12 +79,15 @@ export default { | ||||
|         this.dialog = true | ||||
|       }) | ||||
|     }, | ||||
|     handleMock() { | ||||
|     } | ||||
|   }, | ||||
|   created() { | ||||
|     wx = jWeixin | ||||
|     if (this.user.token) this.getUserInfo().then(() => { | ||||
|     const {jWeixin} = window | ||||
|     window.wx = jWeixin | ||||
|     if (this.user.token) this.getUserInfo().finally(() => { | ||||
|       if (/^\/project\/xiushan/.test(location.pathname)) { | ||||
|         this.setFinanceUser() | ||||
|         this.getFinanceUser() | ||||
|       } | ||||
|     }) | ||||
|   } | ||||
| @@ -97,6 +121,7 @@ html, body { | ||||
|     top: 0; | ||||
|     right: 60px; | ||||
|     opacity: 0; | ||||
|     z-index: 999; | ||||
|  | ||||
|     &:hover { | ||||
|       opacity: 1; | ||||
|   | ||||
| @@ -13,7 +13,7 @@ | ||||
|         <el-avatar :src="user.info.avatar"> | ||||
|           {{ defaultAvatar }} | ||||
|         </el-avatar> | ||||
|         <span>{{ [user.info.name, user.info.roleName].join(" - ") }}</span> | ||||
|         <span v-text="defaultName"/> | ||||
|         <i :class="dropdownIcon"/> | ||||
|       </el-row> | ||||
|       <el-dropdown-menu> | ||||
| @@ -45,12 +45,9 @@ export default { | ||||
|   }, | ||||
|   computed: { | ||||
|     ...mapState(['user']), | ||||
|     dropdownIcon() { | ||||
|       return this.isClick ? 'el-icon-caret-top' : 'el-icon-caret-bottom' | ||||
|     }, | ||||
|     defaultAvatar() { | ||||
|       return this.user.info.name?.slice(-2) || "无名" | ||||
|     } | ||||
|     dropdownIcon: v => v.isClick ? 'el-icon-caret-top' : 'el-icon-caret-bottom', | ||||
|     defaultAvatar: v => v.user.info.name?.slice(-2) || "无名", | ||||
|     defaultName: v => [v.user.info.name, v.user.info.roleName].filter(Boolean)?.join(" - ") || "请先登录" | ||||
|   }, | ||||
|   methods: { | ||||
|     // 获取最新的安卓、ios下载二维码 | ||||
| @@ -124,11 +121,12 @@ export default { | ||||
|     z-index: -1; | ||||
|   } | ||||
|  | ||||
|   ::v-deep.toolbar { | ||||
|   :deep(.toolbar) { | ||||
|     gap: 12px; | ||||
|     margin-right: 32px; | ||||
|  | ||||
|     & > div { | ||||
|     & > div, .toolbarBtn { | ||||
|       color: #fff; | ||||
|       padding: 0 12px; | ||||
|  | ||||
|       &:hover { | ||||
| @@ -167,7 +165,7 @@ export default { | ||||
|   } | ||||
| } | ||||
|  | ||||
| ::v-deep .downLoad_main { | ||||
| :deep( .downLoad_main ) { | ||||
|   width: 100%; | ||||
|   height: 100%; | ||||
|   padding: 16px; | ||||
|   | ||||
| @@ -1,76 +1,22 @@ | ||||
| <template> | ||||
|   <section class="mainContent"> | ||||
|     <el-tabs class="layout" type="card" :value="currentTab" @tab-click="handleTabClick" | ||||
|              @tab-remove="handleTabRemove"> | ||||
|       <el-tab-pane label="默认页" class="layoutItem"> | ||||
|         <ai-empty>欢迎使用村微产品库</ai-empty> | ||||
|       </el-tab-pane> | ||||
|       <el-tab-pane v-for="op in tabs" :key="op.name" :closable="op.name!='工作台'" :name="op.name" :label="op.label" lazy> | ||||
|         <router-view v-if="currentTab==op.name"/> | ||||
|       </el-tab-pane> | ||||
|     </el-tabs> | ||||
|     <ai-nav-tab :routes="$apps"/> | ||||
|     <div class="fill"> | ||||
|       <router-view v-bind="$attrs.commonAttrs"/> | ||||
|       <ai-empty v-if="isHome">欢迎使用村微产品库</ai-empty> | ||||
|     </div> | ||||
|   </section> | ||||
| </template> | ||||
|  | ||||
| <script> | ||||
| import {mapState} from "vuex"; | ||||
| import AiNavTab from "dui/packages/basic/AiNavTab"; | ||||
|  | ||||
| export default { | ||||
|   name: "mainContent", | ||||
|   components: {AiNavTab}, | ||||
|   computed: { | ||||
|     ...mapState(['apps']), | ||||
|     currentTab() { | ||||
|       let {name, query, hash} = this.$route | ||||
|       return [name?.replace(query?.id, ''), query?.id, hash].join("") || "0" | ||||
|     } | ||||
|     isHome: v => v.$route.path == '/', | ||||
|   }, | ||||
|   data() { | ||||
|     return { | ||||
|       tabs: [] | ||||
|     } | ||||
|   }, | ||||
|   watch: { | ||||
|     $route: { | ||||
|       immediate: true, | ||||
|       handler() { | ||||
|         this.getTabs("route") | ||||
|       } | ||||
|     }, | ||||
|   }, | ||||
|   methods: { | ||||
|     handleTabClick({name}) { | ||||
|       let {name: route, query, hash} = this.tabs.find(e => e.name == name), | ||||
|           exps = [] | ||||
|       query.id && exps.push(query.id) | ||||
|       hash && exps.push(hash) | ||||
|       let reg = new RegExp(`(${exps.join("|")})`, 'g') | ||||
|       this.$router.push({name: route.replace(reg, ''), query, hash}) | ||||
|     }, | ||||
|     handleTabRemove(id = this.currentTab) { | ||||
|       let tabs = JSON.parse(JSON.stringify(this.tabs)), | ||||
|           index = tabs?.findIndex(e => id == e.name) | ||||
|       if (id == this.currentTab) { | ||||
|         let next = tabs?.[index + 1] || tabs?.[index - 1] | ||||
|         next ? this.handleTabClick(next) : this.$router.push({path: '/'}) | ||||
|       } | ||||
|       this.tabs.splice(index, 1) | ||||
|     }, | ||||
|     getTabs(from) { | ||||
|       let {name, query, hash} = this.$route | ||||
|       console.log(`getTabs>>>>>>>>>%s>>>>>>>%s`, from, name) | ||||
|       let tab = this.tabs.find(e => e.name == this.currentTab), | ||||
|           tabName = [name, query?.id, hash].join("") | ||||
|       if (tab) { | ||||
|       } else if (!name) { | ||||
|       } else if (tabName) { | ||||
|         let menu = this.apps.find(e => e.name == name) | ||||
|         this.tabs.push({name: tabName, query, hash, label: menu?.label}) | ||||
|       } | ||||
|     }, | ||||
|   }, | ||||
|   created() { | ||||
|     this.getTabs("created") | ||||
|   } | ||||
| } | ||||
| </script> | ||||
|  | ||||
| @@ -78,86 +24,7 @@ export default { | ||||
| .mainContent { | ||||
|   height: 100%; | ||||
|   width: 100%; | ||||
|  | ||||
|   ::v-deep.layout { | ||||
|     height: 100%; | ||||
|     background: #F5F6F9; | ||||
|     display: flex; | ||||
|     flex-direction: column; | ||||
|  | ||||
|     & > .el-tabs__header { | ||||
|       margin-bottom: 0; | ||||
|       background: linear-gradient(180deg, #FCFCFC 0%, #E0E2E4 100%); | ||||
|       height: 40px; | ||||
|       display: flex; | ||||
|       align-items: flex-end; | ||||
|       border: none; | ||||
|  | ||||
|       .el-tabs__nav { | ||||
|         border: none; | ||||
|       } | ||||
|  | ||||
|       .el-tabs__item { | ||||
|         padding: 0 8px 0 12px; | ||||
|         text-align: left; | ||||
|         min-width: 130px; | ||||
|         height: 36px; | ||||
|         line-height: 36px; | ||||
|         border: none; | ||||
|         color: #555; | ||||
|         font-size: 12px; | ||||
|  | ||||
|         & + .el-tabs__item { | ||||
|           margin-left: 2px; | ||||
|         } | ||||
|  | ||||
|         .el-icon-close { | ||||
|           float: right; | ||||
|           width: auto; | ||||
|           height: 100%; | ||||
|           line-height: 36px; | ||||
|           background: transparent; | ||||
|           font-size: 16px; | ||||
|           color: #89b; | ||||
|  | ||||
|           &:hover { | ||||
|             color: #000; | ||||
|           } | ||||
|         } | ||||
|  | ||||
|         &.is-active { | ||||
|           border: 1px solid #D8DCE3; | ||||
|           border-bottom: none; | ||||
|           border-radius: 4px 4px 0 0; | ||||
|           background: #F5F6F9; | ||||
|           color: #222; | ||||
|  | ||||
|           &:after { | ||||
|             display: none; | ||||
|           } | ||||
|         } | ||||
|  | ||||
|         &:after { | ||||
|           position: absolute; | ||||
|           right: 0; | ||||
|           content: " "; | ||||
|           width: 1px; | ||||
|           background: #D8DCE3; | ||||
|           height: 24px; | ||||
|           top: 50%; | ||||
|           transform: translateY(-50%); | ||||
|         } | ||||
|       } | ||||
|     } | ||||
|  | ||||
|     .el-tabs__content { | ||||
|       flex: 1; | ||||
|       min-height: 0; | ||||
|  | ||||
|       .el-tab-pane { | ||||
|         height: 100%; | ||||
|       } | ||||
|     } | ||||
|   } | ||||
|   display: flex; | ||||
|   flex-direction: column; | ||||
| } | ||||
| </style> | ||||
|   | ||||
							
								
								
									
										110
									
								
								examples/components/mock.vue
									
									
									
									
									
										Normal file
									
								
							
							
						
						| @@ -0,0 +1,110 @@ | ||||
| <template> | ||||
|   <section class="mock"> | ||||
|     <el-dropdown> | ||||
|       <div class="toolbarBtn" v-text="`生成随机数据`"/> | ||||
|       <el-dropdown-menu slot="dropdown"> | ||||
|         <el-dropdown-item> | ||||
|           <ai-dialog-btn dialogTitle="随机数据配置" :customFooter="false" @onConfirm="submit" appendToBody @open="getBeans" width="500px"> | ||||
|             <div class="btn" slot="btn">生成数据</div> | ||||
|             <el-form size="small" label-width="60px"> | ||||
|               <el-form-item label="接口"> | ||||
|                 <el-input v-model="action" placeholder="请输入接口" @change="handleAction"/> | ||||
|               </el-form-item> | ||||
|             </el-form> | ||||
|           </ai-dialog-btn> | ||||
|         </el-dropdown-item> | ||||
|         <el-dropdown-item> | ||||
|           <ai-dialog-btn dialogTitle="随机数据配置" :customFooter="false" @onConfirm="generateForm" appendToBody @open="getBeans" width="500px"> | ||||
|             <div class="btn" slot="btn">页面数据</div> | ||||
|             <el-form size="small" label-width="60px"> | ||||
|               <el-form-item label="接口"> | ||||
|                 <el-input v-model="action" placeholder="请输入接口" @change="handleAction"/> | ||||
|               </el-form-item> | ||||
|             </el-form> | ||||
|           </ai-dialog-btn> | ||||
|         </el-dropdown-item> | ||||
|       </el-dropdown-menu> | ||||
|     </el-dropdown> | ||||
|   </section> | ||||
| </template> | ||||
|  | ||||
| <script> | ||||
| import Mock from "mockjs" | ||||
| import instance from "../router/axios"; | ||||
|  | ||||
| export default { | ||||
|   name: "mock", | ||||
|   data() { | ||||
|     return { | ||||
|       instance, | ||||
|       action: "", | ||||
|       config: "", | ||||
|       swagger: {},//swagger接口对象集合 | ||||
|     } | ||||
|   }, | ||||
|   computed: { | ||||
|     url: v => /addOrUpdate/.test(v.action) ? v.action : `/${v.action}/addOrUpdate` | ||||
|   }, | ||||
|   methods: { | ||||
|     handleAction() { | ||||
|       let formName = this.swagger.paths[this.url]?.post.parameters.find(e => e.in == "body")?.name || "" | ||||
|       const {Random} = Mock | ||||
|       if (formName) { | ||||
|         formName = Random.capitalize(formName) | ||||
|         const props = this.swagger.definitions[formName]?.properties || {} | ||||
|         Object.keys(props).map(e => { | ||||
|           const item = props[e] | ||||
|           if (item.format == "date-time") { | ||||
|             props[e] = () => Random.datetime() | ||||
|           } else if (/[0-9a-zA-Z]/.test(item.description)) { | ||||
|             props[e] = () => Random.pick(item.description?.match(/\b[0-9a-zA-Z]+\b/g)) | ||||
|           } else if (/address/i.test(e)) { | ||||
|             props[e] = () => Random.county(true) | ||||
|           } else if (/userName/i.test(e)) { | ||||
|             props[e] = () => Random.cname() | ||||
|           } else if (/lat/.test(e)) { | ||||
|             props[e] = () => Random.float(3, 53, 6, 8) | ||||
|           } else if (/lng/.test(e)) { | ||||
|             props[e] = () => Random.float(73, 135, 6, 8) | ||||
|           } else if (item.type == "number") { | ||||
|             props[e] = () => Random.float(0, 1000, 0, 2) | ||||
|           } else if (item.type == "integer") { | ||||
|             props[e] = () => Random.integer(0, 1000) | ||||
|           } else if (item.type == "string") { | ||||
|             props[e] = () => Random.ctitle() | ||||
|           } else props[e] = null | ||||
|         }) | ||||
|         this.config = props | ||||
|       } | ||||
|     }, | ||||
|     getBeans() { | ||||
|       this.instance.get("/app/v2/api-docs", {withoutToken: true}).then(res => this.swagger = res) | ||||
|     }, | ||||
|     generateForm() { | ||||
|       const {mock} = Mock | ||||
|       this.$vm.$emit("mock", mock(this.config)) | ||||
|     }, | ||||
|     submit() { | ||||
|       const {mock} = Mock | ||||
|       const data = mock({ | ||||
|         'list|50-100': [this.config] | ||||
|       }) | ||||
|       Promise.all(data.list.map(e => this.instance.post(this.url, e))).then(() => this.$message.success("随机数据生成,执行完毕!")) | ||||
|     } | ||||
|   } | ||||
| } | ||||
| </script> | ||||
|  | ||||
| <style lang="scss" scoped> | ||||
| .mock { | ||||
|   .btn { | ||||
|     cursor: pointer; | ||||
|     user-select: none; | ||||
|     padding: 0 12px; | ||||
|  | ||||
|     &:hover { | ||||
|       color: rgba(#fff, .8); | ||||
|     } | ||||
|   } | ||||
| } | ||||
| </style> | ||||
| @@ -39,25 +39,22 @@ export default { | ||||
|     } | ||||
|   }, | ||||
|   computed: { | ||||
|     ...mapState(['user', 'apps']), | ||||
|     ...mapState(['user']), | ||||
|     navs() { | ||||
|       let reg = new RegExp(`.*${this.searchApp?.replace(/-/g,'')||''}.*`, 'gi') | ||||
|       return (this.apps || []).filter(e => !this.searchApp || reg?.test(e.name) || reg?.test(e.label)).map(e => { | ||||
|       return (this.$apps || []).filter(e => !this.searchApp || reg?.test(e.name) || reg?.test(e.label)).map(e => { | ||||
|         if (/\/project\//.test(e.path)) { | ||||
|           e.project = e.path.replace(/.*project\/([^\/]+)\/.+/, '$1') | ||||
|           e.project = process.env.VUE_APP_SCOPE || e.path.replace(/.*project\/([^\/]+)\/.+/, '$1') | ||||
|         } else if (/\/core\//.test(e.path)) { | ||||
|           e.project = "core" | ||||
|         } | ||||
|         return e | ||||
|       }) | ||||
|     }, | ||||
|     isConsoleRoute() { | ||||
|       return this.$route.name == "工作台" | ||||
|     }, | ||||
|     menuPath() { | ||||
|       let paths = [], current = this.apps?.find(e => e.name == this.$route.name) | ||||
|       let paths = [], current = this.$apps?.find(e => e.name == this.$route.name) | ||||
|       const findParent = name => { | ||||
|         let menu = this.apps?.find(e => e.name == name) | ||||
|         let menu = this.$apps?.find(e => e.name == name) | ||||
|         if (menu) { | ||||
|           paths.push(menu.name) | ||||
|           if (!!menu.parentId) findParent(menu.parentId) | ||||
| @@ -200,7 +197,7 @@ export default { | ||||
|     } | ||||
|   } | ||||
|  | ||||
|   ::v-deep .ai-menu { | ||||
|   :deep( .ai-menu ) { | ||||
|     padding-left: 0; | ||||
|     flex: 1; | ||||
|     min-height: 0; | ||||
| @@ -214,7 +211,7 @@ export default { | ||||
|     } | ||||
|   } | ||||
|  | ||||
|   ::v-deep .searchApp { | ||||
|   :deep( .searchApp ) { | ||||
|     display: flex; | ||||
|     align-items: center; | ||||
|     height: 44px; | ||||
|   | ||||
| @@ -1,20 +1,18 @@ | ||||
| import Vue from 'vue'; | ||||
| import App from './App.vue'; | ||||
| import ui from 'element-ui'; | ||||
| import router from './router/router'; | ||||
| import router from './router'; | ||||
| import axios from './router/axios'; | ||||
| import utils from './utils'; | ||||
| import vcUI from 'dvcp-ui'; | ||||
| import 'dvcp-ui/lib/styles/common.scss'; | ||||
| import 'dvcp-ui/lib/dvcp-ui.css'; | ||||
| import dui from 'dui/packages'; | ||||
| import store from './store'; | ||||
| import dataV from '@jiaminghi/data-view'; | ||||
| import dvui from '../project/dvui/entries' | ||||
| import dvui from 'dui/dv' | ||||
|  | ||||
| Vue.use(dataV); | ||||
| Vue.use(dataV) | ||||
| Vue.use(ui); | ||||
| Vue.use(vcUI); | ||||
| Vue.use(dvui) | ||||
| Vue.use(dui); | ||||
| Vue.use(dvui); | ||||
| //富文本编辑器配置 | ||||
| Vue.config.productionTip = false; | ||||
| Object.keys(utils).map((e) => (Vue.prototype[e] = utils[e])); | ||||
| @@ -24,12 +22,14 @@ const app = new Vue({ | ||||
|   store, | ||||
|   render: h => h(App) | ||||
| }); | ||||
|  | ||||
| let theme = null | ||||
| store.dispatch('getSystem').then(({colorScheme}) => { | ||||
|   theme = JSON.parse(colorScheme || null) | ||||
| store.dispatch('getSystem').then(res => { | ||||
|   theme = JSON.parse(res?.colorScheme || null) | ||||
|   Vue.prototype.$theme = theme?.web || "blue" | ||||
|   return import(`dvcp-ui/lib/styles/theme.${theme?.web}.scss`).catch(() => 0) | ||||
|   return import(`dui/lib/styles/theme.${theme?.web}.scss`).catch(() => 0) | ||||
| }).finally(() => { | ||||
|   !theme ? app.$mount('#app') : import(`dvcp-ui/lib/styles/common.scss`).finally(() => app.$mount('#app')) | ||||
|   Vue.prototype.$vm = app | ||||
|   import(`dui/lib/styles/common.scss`).finally(() => app.$mount('#app')) | ||||
| }) | ||||
|  | ||||
|   | ||||
| @@ -1,48 +0,0 @@ | ||||
| import store from "../store"; | ||||
| import {waiting} from "../utils"; | ||||
| import appEntry from "../views/apps/appEntry"; | ||||
| import router from "./router"; | ||||
| import axios from "./axios"; | ||||
|  | ||||
| export default { | ||||
|   routes: () => store.state.apps, | ||||
|   init() { | ||||
|     //约束正则式 | ||||
|     store.commit("cleanApps") | ||||
|     // 自动化本工程应用 | ||||
|     this.loadApps() | ||||
|   }, | ||||
|   loadApps() { | ||||
|     //新App的自动化格式 | ||||
|     let apps = require.context('../../packages/', true, /\.(\/.+)\/App[A-Z][^\/]+\.vue$/, 'lazy'), | ||||
|         projects = require.context('../../project/', true, /\.(\/.+)\/App[A-Z][^\/]+\.vue$/, 'lazy') | ||||
|     const promise = (mods, base) => Promise.all(mods.keys().map(path => mods(path).then(file => { | ||||
|       if (file.default) { | ||||
|         let {name, label} = file.default, | ||||
|             addApp = { | ||||
|               name: path.replace(/\.\/?(vue)?/g, '')?.split("/").join("_"), label: label || name, | ||||
|               path: `/${base}${path.replace(/\.(\/.+\/App.+)\.vue$/, '$1')}`, | ||||
|               component: appEntry, | ||||
|               module: file.default | ||||
|             } | ||||
|         waiting.setContent(`加载${name}...`) | ||||
|         router.addRoute(addApp) | ||||
|         //命名规范入口文件必须以App开头 | ||||
|         return store.commit("addApp", addApp) | ||||
|       } else return 0 | ||||
|     }))) | ||||
|     waiting.init({innerHTML: '应用加载中..'}) | ||||
|     Promise.all([ | ||||
|       promise(apps, "packages"), | ||||
|       promise(projects, "project") | ||||
|     ]).then(() => { | ||||
|       // axios.post("/node/wechatapps/addOrUpdate", { | ||||
|       //   type: "web", | ||||
|       //   list: this.routes().map(({path: libPath, label, module: {name}, name: id}) => ({ | ||||
|       //     id, type: 'web', libPath, label, name | ||||
|       //   })) | ||||
|       // }, {baseURL: "/ns"}).catch(() => 0) | ||||
|       waiting.close() | ||||
|     }) | ||||
|   } | ||||
| } | ||||
| @@ -1,5 +1,5 @@ | ||||
| import instance from 'dvcp-ui/lib/js/request' | ||||
| import {Message} from 'element-ui' | ||||
| import { Message } from 'element-ui' | ||||
| import instance from 'dui/lib/js/request' | ||||
|  | ||||
| let baseURLs = { | ||||
|   production: "/", | ||||
| @@ -8,20 +8,10 @@ let baseURLs = { | ||||
| instance.defaults.baseURL = baseURLs[process.env.NODE_ENV] | ||||
| instance.interceptors.request.use(config => { | ||||
|   if (config.url.startsWith("/node")) { | ||||
|     config.baseURL = "/ns" | ||||
|   } else if (/\/project\/beta/.test(location.pathname)) { | ||||
|     config.baseURL = "/wg" | ||||
|   } else if (/\/project\/sass/.test(location.pathname)) { | ||||
|     config.baseURL = "/saas" | ||||
|   } else if (/\/xiushan/.test(location.pathname)) { | ||||
|     config.baseURL = "/xsjr" | ||||
|   } else if (/project\/oms/.test(location.pathname)) { | ||||
|     config.baseURL = "/omsapi" | ||||
|   } else if (/#url-/.test(location.hash)) { | ||||
|     config.baseURL = location.hash.replace(/#url-/, '/') | ||||
|     config.url = "/ns" + config.url | ||||
|   } | ||||
|   if (["/xsjr", "/omsapi"].includes(config.baseURL)) { | ||||
|     config.url = config.url.replace(/(app|auth|admin)\//, "") | ||||
|   if (process.env.VUE_APP_IS_SIMPLE_SERVER == 1) { | ||||
|     config.url = config.url.replace(/^\/(app|auth|admin)\//, "/api/") | ||||
|   } | ||||
|   return config | ||||
| }, error => Message.error(error)) | ||||
|   | ||||
| @@ -1,13 +1,13 @@ | ||||
| import Vue from 'vue' | ||||
| import VueRouter from 'vue-router' | ||||
| import autoRoutes from './autoRoutes' | ||||
| import apps from "./apps"; | ||||
| 
 | ||||
| Vue.use(VueRouter) | ||||
| autoRoutes.init() | ||||
| Vue.prototype.$apps = apps | ||||
| export default new VueRouter({ | ||||
|   mode: 'history', | ||||
|   hashbang: false, | ||||
|   routes: autoRoutes.routes(), | ||||
|   routes: apps, | ||||
|   scrollBehavior(to) { | ||||
|     if (to.hash) { | ||||
|       return { | ||||
| @@ -1,28 +1,12 @@ | ||||
| import Vue from 'vue' | ||||
| import Vuex from 'vuex' | ||||
| import preState from 'vuex-persistedstate' | ||||
| import * as modules from "dvcp-ui/lib/js/modules" | ||||
| import axios from "../router/axios"; | ||||
| import * as modules from "dui/lib/js/modules" | ||||
| import xsActions from "../../project/xiushan/actions" | ||||
|  | ||||
| Vue.use(Vuex) | ||||
|  | ||||
| export default new Vuex.Store({ | ||||
|   state: { | ||||
|     apps: [] | ||||
|   }, | ||||
|   mutations: { | ||||
|     addApp(state, app) { | ||||
|       state.apps.push(app) | ||||
|     }, | ||||
|     cleanApps(state) { | ||||
|       state.apps = [] | ||||
|     }, | ||||
|     setFinanceUser(state) { | ||||
|       axios.post("appfinancialorganizationuser/checkUser").then(res => { | ||||
|         state.user.financeUser = res.data | ||||
|       }).catch(() => 0) | ||||
|     } | ||||
|   }, | ||||
|   actions: {...xsActions}, | ||||
|   modules, | ||||
|   plugins: [preState()] | ||||
| }) | ||||
|   | ||||
| @@ -1,6 +1,6 @@ | ||||
| import {MessageBox} from 'element-ui' | ||||
| import store from '../store' | ||||
| import tools from 'dvcp-ui/lib/js/utils' | ||||
| import tools from 'dui/lib/js/utils' | ||||
|  | ||||
| const addChildParty = (parent, pending) => { | ||||
|   let doBeforeCount = pending.length | ||||
| @@ -28,6 +28,7 @@ const $confirm = (content, options) => { | ||||
|   return MessageBox.confirm(content, { | ||||
|     type: "warning", | ||||
|     confirmButtonText: "确认", | ||||
|     closeOnClickModal: false, | ||||
|     center: true, | ||||
|     title: "提示", | ||||
|     dangerouslyUseHTMLString: true, | ||||
| @@ -69,7 +70,7 @@ export const waiting = { | ||||
|       div.style.lineHeight = '100vh' | ||||
|       div.style.color = '#26f' | ||||
|       div.style.fontSize = '20px' | ||||
|       div.style.background = 'rgba(255,255,255,.8)' | ||||
|       div.style.background = 'rgba(255,255,255,.6)' | ||||
|       div.style.backdropFilter = 'blur(6px)' | ||||
|       document.body.appendChild(div) | ||||
|     } else if (count < 10) { | ||||
|   | ||||
| @@ -1,37 +0,0 @@ | ||||
| <template> | ||||
|   <section class="appEntry"> | ||||
|     <component v-if="app" :is="app" :instance="$request" :dict="$dict" :permissions="$permissions"/> | ||||
|     <ai-empty v-else>无法找到应用文件</ai-empty> | ||||
|   </section> | ||||
| </template> | ||||
|  | ||||
| <script> | ||||
|  | ||||
| import {mapState} from "vuex"; | ||||
|  | ||||
| export default { | ||||
|   name: "appEntry", | ||||
|   label: "应用库-应用", | ||||
|   computed: { | ||||
|     ...mapState(['apps']), | ||||
|     app() { | ||||
|       let app = this.apps.find(e => e.name == this.$route.name) | ||||
|       return app ? app.module : "" | ||||
|     } | ||||
|   } | ||||
| } | ||||
| </script> | ||||
|  | ||||
| <style lang="scss" scoped> | ||||
| .appEntry { | ||||
|   width: 100%; | ||||
|   flex: 1; | ||||
|   min-width: 0; | ||||
|   min-height: 0; | ||||
|   height: 100%; | ||||
|  | ||||
|   & > * { | ||||
|     height: 100%; | ||||
|   } | ||||
| } | ||||
| </style> | ||||
| @@ -1,13 +0,0 @@ | ||||
| <template> | ||||
|   <router-view /> | ||||
| </template> | ||||
|  | ||||
| <script> | ||||
|   export default { | ||||
|     name: "index" | ||||
|   } | ||||
| </script> | ||||
|  | ||||
| <style scoped> | ||||
|  | ||||
| </style> | ||||
							
								
								
									
										74
									
								
								package.json
									
									
									
									
									
								
							
							
						
						| @@ -1,36 +1,44 @@ | ||||
| { | ||||
|   "name": "cw-webapps", | ||||
|   "version": "2.0.0", | ||||
|   "name": "dvcp-web-apps", | ||||
|   "version": "4.0.0", | ||||
|   "private": false, | ||||
|   "author": "kubbo", | ||||
|   "main": "lib/cw-webapps.common.js", | ||||
|   "scripts": { | ||||
|     "dev": "vue-cli-service serve", | ||||
|     "lib": "vue-cli-service build --no-clean --target lib --dest lib packages/index.js&&npm unpublish --force&&npm publish", | ||||
|     "lib:core": "vue-cli-service build --target lib --dest core/dist core/index.js --name dvcp-core&&npm unpublish dvcp-core --force&&npm publish core/", | ||||
|     "lib:project": "node project/build.js", | ||||
|     "lib:all": "node project/allProject.js&&npm unpublish --workspaces --force&&npm publish --workspaces", | ||||
|     "ui": "npm i dvcp-ui@latest" | ||||
|     "dev": "vue-cli-service serve examples/main.js", | ||||
|     "build": "vue-cli-service build", | ||||
|     "oms": "vue-cli-service serve examples/main.js --mode oms", | ||||
|     "xumu": "vue-cli-service serve examples/main.js --mode xumu", | ||||
|     "sync": "node bin/appsSync.js", | ||||
|     "preview": "node bin/build.js && vue-cli-service serve", | ||||
|     "predev": "node bin/scanApps.js", | ||||
|     "preoms": "dotenv -e .env.oms node bin/scanApps.js", | ||||
|     "prexumu": "dotenv -e .env.xumu node bin/scanApps.js", | ||||
|     "view:xumu": "vue-cli-service serve --mode xumu", | ||||
|     "preview:xumu": "dotenv -e .env.xumu node bin/build.js" | ||||
|   }, | ||||
|   "workspaces": [ | ||||
|     "project/*" | ||||
|   ], | ||||
|   "dependencies": { | ||||
|     "@amap/amap-jsapi-loader": "^1.0.1", | ||||
|     "@jiaminghi/c-render": "^0.4.3", | ||||
|     "@jiaminghi/charts": "^0.2.18", | ||||
|     "@ckeditor/ckeditor5-vue2": "^3.0.1", | ||||
|     "@jiaminghi/data-view": "^2.10.0", | ||||
|     "bin-code-editor": "^0.9.0", | ||||
|     "@logicflow/core": "^1.2.1", | ||||
|     "bin-ace-editor": "^3.2.0", | ||||
|     "crypto-js": "^4.2.0", | ||||
|     "dayjs": "^1.8.35", | ||||
|     "dvcp-ui": "^1.42.2", | ||||
|     "echarts": "^5.1.2", | ||||
|     "echarts": "^5.5.1", | ||||
|     "echarts-wordcloud": "^2.0.0", | ||||
|     "hash.js": "^1.1.7", | ||||
|     "html2canvas": "^1.4.1", | ||||
|     "jspdf": "^2.5.2", | ||||
|     "mp4box": "^0.4.1", | ||||
|     "print-js": "^1.0.63", | ||||
|     "serialize-javascript": "^6.0.0", | ||||
|     "sortablejs": "^1.12.0", | ||||
|     "vue-carousel": "^0.18.0", | ||||
|     "vue-cropper": "^0.6.5", | ||||
|     "vue-draggable-resizable": "^2.3.0", | ||||
|     "vue-json-editor": "^1.4.3", | ||||
|     "vue-qr": "^4.0.9", | ||||
|     "vue-ruler-tool": "^1.2.4", | ||||
|     "vue-style-loader": "^4.1.3", | ||||
|     "vuedraggable": "^2.24.3" | ||||
|   }, | ||||
|   "devDependencies": { | ||||
| @@ -43,40 +51,27 @@ | ||||
|     "axios": "^0.19.2", | ||||
|     "babel-eslint": "^10.1.0", | ||||
|     "core-js": "^2.6.11", | ||||
|     "dotenv-cli": "^7.4.2", | ||||
|     "element-ui": "^2.15.9", | ||||
|     "eslint": "^5.16.0", | ||||
|     "eslint-plugin-vue": "^5.0.0", | ||||
|     "image-webpack-loader": "^6.0.0", | ||||
|     "inquirer": "^6.5.2", | ||||
|     "mockjs": "^1.1.0", | ||||
|     "node-ipc": "^9.2.1", | ||||
|     "readline": "^1.3.0", | ||||
|     "sass": "~1.32.12", | ||||
|     "sass": "~1.32.6", | ||||
|     "sass-loader": "^7.3.1", | ||||
|     "uglifyjs-webpack-plugin": "^2.2.0", | ||||
|     "v-viewer": "^1.6.4", | ||||
|     "vue": "^2.6.14", | ||||
|     "vue": "^2.7.14", | ||||
|     "vue-router": "^3.3.4", | ||||
|     "vue-style-loader": "^4.1.3", | ||||
|     "vue-template-compiler": "^2.6.14", | ||||
|     "vue-template-compiler": "^2.7.14", | ||||
|     "vuex": "^3.5.1", | ||||
|     "vuex-persistedstate": "^2.7.1" | ||||
|   }, | ||||
|   "vetur": { | ||||
|     "attributes": "./attributes.json" | ||||
|   }, | ||||
|   "eslintConfig": { | ||||
|     "root": true, | ||||
|     "env": { | ||||
|       "node": true | ||||
|     }, | ||||
|     "extends": [ | ||||
|       "plugin:vue/essential", | ||||
|       "eslint:recommended" | ||||
|     ], | ||||
|     "rules": {}, | ||||
|     "parserOptions": { | ||||
|       "parser": "babel-eslint" | ||||
|     } | ||||
|   }, | ||||
|   "postcss": { | ||||
|     "plugins": { | ||||
|       "autoprefixer": {} | ||||
| @@ -86,5 +81,8 @@ | ||||
|     "> 1%", | ||||
|     "last 2 versions", | ||||
|     "not ie <= 8" | ||||
|   ] | ||||
|   ], | ||||
|   "resolutions": { | ||||
|     "sass": "1.32.6" | ||||
|   } | ||||
| } | ||||
|   | ||||
							
								
								
									
										289
									
								
								packages/bigscreen/designer/Add.vue
									
									
									
									
									
										Normal file
									
								
							
							
						
						| @@ -0,0 +1,289 @@ | ||||
| <template> | ||||
|   <ai-detail> | ||||
|     <template slot="title"> | ||||
|       <ai-title :title="isEdit ? '编辑项目' : '添加项目'" isShowBack isShowBottomBorder @onBackClick="cancel"/> | ||||
|     </template> | ||||
|     <template slot="content"> | ||||
|       <el-form ref="form" :model="form" label-width="110px" label-position="right"> | ||||
|         <ai-card title="基本信息"> | ||||
|           <template #content> | ||||
|             <div class="ai-form"> | ||||
|               <el-form-item label="名称" prop="name" | ||||
|                             :rules="[{ required: true, message: '请输入大屏项目名称', trigger: 'blur' }]"> | ||||
|                 <el-input size="small" :maxlength="30" placeholder="请输入大屏项目名称" v-model="form.name"></el-input> | ||||
|               </el-form-item> | ||||
|               <el-form-item label="描述" style="width: 100%;" prop="description"> | ||||
|                 <el-input size="small" :maxlength="200" :rows="5" type="textarea" style="width: 100%;" | ||||
|                           placeholder="请输入描述" | ||||
|                           v-model="form.description"></el-input> | ||||
|               </el-form-item> | ||||
|               <el-form-item label="是否开启" style="width: 100%;" prop="status"> | ||||
|                 <el-switch | ||||
|                     v-model="form.status" | ||||
|                     active-value="1" | ||||
|                     inactive-value="0"> | ||||
|                 </el-switch> | ||||
|               </el-form-item> | ||||
|             </div> | ||||
|           </template> | ||||
|         </ai-card> | ||||
|         <ai-card title="大屏" v-if="isEdit"> | ||||
|           <template #right> | ||||
|             <el-button @click="gotoDesign()" type="primary">添加大屏</el-button> | ||||
|             <el-button @click="dialog=true" type="primary">定制大屏</el-button> | ||||
|           </template> | ||||
|           <template #content> | ||||
|             <ai-table | ||||
|                 :tableData="tableData" | ||||
|                 :col-configs="colConfigs" | ||||
|                 :total="total" | ||||
|                 style="margin-top: 6px;" | ||||
|                 :border="true" | ||||
|                 row-key="id" | ||||
|                 :isShowPagination="false" | ||||
|                 @getList="() => {}"> | ||||
|               <el-table-column slot="options" label="状态" align="center"> | ||||
|                 <template slot-scope="{ row }"> | ||||
|                   <el-switch | ||||
|                       v-model="row.status" | ||||
|                       active-value="1" | ||||
|                       @change="() => onStatusChange(row.id)"> | ||||
|                   </el-switch> | ||||
|                 </template> | ||||
|               </el-table-column> | ||||
|               <el-table-column slot="options" width="160px" fixed="right" label="操作" align="center"> | ||||
|                 <template slot-scope="{ row, column, $index }"> | ||||
|                   <div class="table-options"> | ||||
|                     <el-button type="text" @click="toEdit(row.id, row.isCustom, row)">编辑</el-button> | ||||
|                     <el-button type="text" @click="toViewer(row.id)">预览</el-button> | ||||
|                     <el-button type="text" @click="remove($index)">删除</el-button> | ||||
|                   </div> | ||||
|                 </template> | ||||
|               </el-table-column> | ||||
|             </ai-table> | ||||
|           </template> | ||||
|         </ai-card> | ||||
|       </el-form> | ||||
|       <ai-dialog :visible.sync="dialog" title="定制大屏" @closed="custom={}" @onConfirm="handleCustomizedDV"> | ||||
|         <el-form ref="CustomDVFrom" size="small" :model="custom" :rules="rules" label-width="80px"> | ||||
|           <el-form-item label="大屏标题" prop="title"> | ||||
|             <el-input v-model="custom.title" clearable placeholder="请填写"/> | ||||
|           </el-form-item> | ||||
|           <el-form-item label="选择大屏" prop="dv"> | ||||
|             <ai-select v-model="custom.dv" :selectList="dict.getDict('customizedDVs')"/> | ||||
|           </el-form-item> | ||||
|           <el-form-item label="静态数据"> | ||||
|             <el-input type="textarea" rows="5" v-model="custom.meta"/> | ||||
|           </el-form-item> | ||||
|         </el-form> | ||||
|       </ai-dialog> | ||||
|     </template> | ||||
|     <template #footer> | ||||
|       <el-button @click="cancel">取消</el-button> | ||||
|       <el-button type="primary" @click="confirm">提交</el-button> | ||||
|     </template> | ||||
|   </ai-detail> | ||||
| </template> | ||||
|  | ||||
| <script> | ||||
| import Layout from './viewport.vue' | ||||
| import Sortable from 'sortablejs' | ||||
| import {mapActions} from "vuex" | ||||
|  | ||||
| export default { | ||||
|   name: 'Add', | ||||
|   props: { | ||||
|     instance: Function, | ||||
|     dict: Object, | ||||
|     urlPrefix: String | ||||
|   }, | ||||
|   inject: { | ||||
|     home: {default: ''} | ||||
|   }, | ||||
|   components: { | ||||
|     Layout | ||||
|   }, | ||||
|   data() { | ||||
|     return { | ||||
|       info: {}, | ||||
|       department: [], | ||||
|       form: { | ||||
|         name: '', | ||||
|         relationLsIds: '', | ||||
|         relationLsNames: '', | ||||
|         status: '1', | ||||
|         description: '' | ||||
|       }, | ||||
|       screenId: '', | ||||
|       query: {}, | ||||
|       total: 0, | ||||
|       colConfigs: [ | ||||
|         {prop: 'title', label: '标题'}, | ||||
|         {prop: 'id', label: 'ID'} | ||||
|       ], | ||||
|       tableData: [], | ||||
|       id: '', | ||||
|       dialog: false, | ||||
|       custom: {}, | ||||
|       rules: { | ||||
|         dv: [{required: true, message: "请选择 定制大屏"}], | ||||
|         title: [{required: true, message: "请输入 大屏标题"}], | ||||
|       }, | ||||
|       config: { | ||||
|         backgroundImage: [] | ||||
|       } | ||||
|     } | ||||
|   }, | ||||
|   computed: { | ||||
|     isEdit: v => !!v.$route.query.id | ||||
|   }, | ||||
|   created() { | ||||
|     this.dict.load('customizedDVs') | ||||
|     this.getInfo().then(() => this.$route.params?.id && this.onChange(this.$route.params)) | ||||
|   }, | ||||
|   methods: { | ||||
|     ...mapActions(['closePage']), | ||||
|     getInfo() { | ||||
|       let {id} = this.$route.query | ||||
|       if (!id) return Promise.reject() | ||||
|       return this.instance.post(`${this.urlPrefix}/appdiylargescreen/queryLargeScreenProjectDetailById?id=${id}`).then(res => { | ||||
|         if (res?.data) { | ||||
|           this.form = { | ||||
|             ...res.data | ||||
|           } | ||||
|           if (res.data.relationLsIds) { | ||||
|             this.tableData = res.data.lsList.map(v => { | ||||
|               let conf = JSON.parse(v.config || '') || {} | ||||
|               return { | ||||
|                 id: v.id, | ||||
|                 title: v.title, | ||||
|                 dv: conf.custom || '', | ||||
|                 meta: JSON.stringify(conf.meta), | ||||
|                 isCustom: !!conf.custom, | ||||
|                 status: v.status | ||||
|               } | ||||
|             }) | ||||
|             this.total = res.data.lsList.length | ||||
|             this.$nextTick(() => { | ||||
|               this.rowDrop() | ||||
|             }) | ||||
|           } | ||||
|         } | ||||
|       }) | ||||
|     }, | ||||
|     onStatusChange(id) { | ||||
|       this.instance.post(`${this.urlPrefix}/appdiylargescreen/enableLargeScreen?id=${id}`).then(res => { | ||||
|         if (res.code === 0) { | ||||
|           this.$message.success('操作成功') | ||||
|         } | ||||
|       }) | ||||
|     }, | ||||
|     rowDrop() { | ||||
|       const tbody = document.querySelector('.el-table__body-wrapper tbody') | ||||
|       const _this = this | ||||
|       Sortable.create(tbody, { | ||||
|         onEnd({newIndex, oldIndex}) { | ||||
|           const currRow = _this.tableData.splice(oldIndex, 1)[0] | ||||
|           _this.tableData.splice(newIndex, 0, currRow) | ||||
|         } | ||||
|       }) | ||||
|     }, | ||||
|     toViewer(id) { | ||||
|       this.$router.push({query: {id}, hash: "#preview"}) | ||||
|     }, | ||||
|     onChange(e) { | ||||
|       const ids = this.tableData.map(v => v.id) | ||||
|       if (ids.indexOf(e.id) < 0) { | ||||
|         this.tableData.push({ | ||||
|           title: e.title, | ||||
|           id: e.id, | ||||
|           status: '1' | ||||
|         }) | ||||
|       } else { | ||||
|         const index = this.tableData.findIndex(v => v.id === e.id) | ||||
|         this.$set(this.tableData[index], 'title', e.title) | ||||
|       } | ||||
|       this.$nextTick(() => { | ||||
|         if (this.$route.query.id) { | ||||
|           const ids = this.tableData.map(v => v.id).join(',') | ||||
|           const names = this.tableData.map(v => v.name).join(',') | ||||
|           this.instance.post(`${this.urlPrefix}/appdiylargescreen/addOrUpdateLargeScreenProject`, { | ||||
|             ...this.form, | ||||
|             relationLsIds: ids, | ||||
|             relationLsNames: names | ||||
|           }) | ||||
|         } | ||||
|       }) | ||||
|     }, | ||||
|     gotoDesign(did) { | ||||
|       const {id} = this.$route.query | ||||
|       this.$router.push({hash: "#design", query: {id, did, name: this.form.name}}) | ||||
|     }, | ||||
|     toEdit(id, isCustom, form) { | ||||
|       if (!isCustom) { | ||||
|         this.gotoDesign(id) | ||||
|       } else { | ||||
|         this.dialog = true | ||||
|         this.custom = form | ||||
|       } | ||||
|     }, | ||||
|  | ||||
|     remove(index) { | ||||
|       this.tableData.splice(index, 1) | ||||
|     }, | ||||
|  | ||||
|     confirm() { | ||||
|       this.$refs.form.validate((valid) => { | ||||
|         if (valid) { | ||||
|           const ids = this.tableData.map(v => v.id).join(',') | ||||
|           const names = this.tableData.map(v => v.name).join(',') | ||||
|           this.instance.post(`${this.urlPrefix}/appdiylargescreen/addOrUpdateLargeScreenProject`, { | ||||
|             ...this.form, | ||||
|             relationLsIds: ids, | ||||
|             relationLsNames: names | ||||
|           }).then(res => { | ||||
|             if (res.code == 0) { | ||||
|               this.$message.success('提交成功') | ||||
|  | ||||
|               this.home && this.home.refreshDvOptions && this.home.refreshDvOptions() | ||||
|               setTimeout(() => { | ||||
|                 this.cancel() | ||||
|               }, 600) | ||||
|             } | ||||
|           }) | ||||
|         } | ||||
|       }) | ||||
|     }, | ||||
|  | ||||
|     cancel() { | ||||
|       this.closePage() | ||||
|       this.$router.push({}) | ||||
|     }, | ||||
|  | ||||
|     handleCustomizedDV() { | ||||
|       this.$refs.CustomDVFrom.validate(v => { | ||||
|         if (v) { | ||||
|           this.instance.post(`${this.urlPrefix}/appdiylargescreen/addOrUpdateLargeScreen`, { | ||||
|             config: JSON.stringify({ | ||||
|               custom: this.custom.dv, | ||||
|               meta: JSON.parse(this.custom.meta?.replace(/\\n/g, '') || null) | ||||
|             }), | ||||
|             status: 1, | ||||
|             id: this.custom.id, | ||||
|             title: this.custom.title, | ||||
|           }).then(res => { | ||||
|             if (res?.code == 0 && res?.data) { | ||||
|               this.$message.success('保存成功') | ||||
|               this.onChange(res.data) | ||||
|               this.dialog = false | ||||
|             } | ||||
|           }) | ||||
|         } | ||||
|       }) | ||||
|     } | ||||
|   } | ||||
| } | ||||
| </script> | ||||
|  | ||||
| <style scoped lang="scss"> | ||||
| </style> | ||||
| @@ -5,15 +5,16 @@ | ||||
| </template> | ||||
|  | ||||
| <script> | ||||
| import List from './components/List.vue' | ||||
| import Add from './components/Add' | ||||
| import SourceData from './components/SourceData' | ||||
| import Preview from "./components/preview"; | ||||
| import List from './List.vue' | ||||
| import Add from './Add.vue' | ||||
| import SourceData from './SourceData.vue' | ||||
| import Preview from "./preview.vue"; | ||||
| import DesignDashboard from "./viewport.vue"; | ||||
|  | ||||
| export default { | ||||
|   name: 'AppDesigner', | ||||
|   label: '大屏设计', | ||||
|   components: {Preview, List, Add, SourceData}, | ||||
|   components: {DesignDashboard, Preview, List, Add, SourceData}, | ||||
|   props: { | ||||
|     instance: Function, | ||||
|     dict: Object, | ||||
| @@ -29,7 +30,8 @@ export default { | ||||
|       const {hash} = this.$route | ||||
|       return hash == "#sourceData" ? SourceData : | ||||
|           hash == "#add" ? Add : | ||||
|               hash == "#preview" ? Preview : List | ||||
|               hash == "#preview" ? Preview : | ||||
|                   hash == "#design" ? DesignDashboard : List | ||||
|     }, | ||||
|     tabs() { | ||||
|       return [ | ||||
|   | ||||
| @@ -33,7 +33,7 @@ | ||||
|           style="margin-top: 6px;" | ||||
|           :current.sync="search.current" | ||||
|           :size.sync="search.size" | ||||
|           @getList="getList"> | ||||
|           @getList="getList" :dict="dict"> | ||||
|         <el-table-column slot="options" width="160px" fixed="right" label="操作" align="center"> | ||||
|           <template slot-scope="{ row }"> | ||||
|             <div class="table-options"> | ||||
| @@ -88,7 +88,7 @@ export default { | ||||
|         {prop: 'name', label: '模板名称'}, | ||||
|         {prop: 'createUserName', align: 'center', label: '创建人'}, | ||||
|         {prop: 'description', align: 'center', label: '描述'}, | ||||
|         {prop: 'status', align: 'center', label: '状态', formart: v => this.dict.getLabel('cwpStatus', v)}, | ||||
|         {prop: 'status', align: 'center', label: '状态', dict:"cwpStatus"}, | ||||
|         {prop: 'createTime', align: 'center', label: '创建时间'} | ||||
|       ], | ||||
|       tableData: [], | ||||
| @@ -210,7 +210,7 @@ export default { | ||||
|         {prop: 'appName', label: '应用名'}, | ||||
|         {prop: 'appTableName', align: 'center', label: '表名'}, | ||||
|         {prop: 'description', align: 'center', label: '描述'}, | ||||
|         {prop: 'type', align: 'center', label: '类型', formart: v => v === '0' ? '村微应用' : 'sql语句'}, | ||||
|         {prop: 'type', align: 'center', label: '类型', format: v => v === '0' ? '村微应用' : 'sql语句'}, | ||||
|         {prop: 'createUserName', align: 'center', label: '创建人'}, | ||||
|         {prop: 'createTime', align: 'center', label: '创建时间'} | ||||
|       ], | ||||
| @@ -1,316 +0,0 @@ | ||||
| <template> | ||||
|   <ai-detail> | ||||
|     <template slot="title"> | ||||
|       <ai-title :title="id ? '编辑项目' : '添加项目'" isShowBack isShowBottomBorder @onBackClick="cancel"/> | ||||
|     </template> | ||||
|     <template slot="content"> | ||||
|       <el-form ref="form" :model="form" label-width="110px" label-position="right"> | ||||
|         <ai-card title="基本信息"> | ||||
|           <template #content> | ||||
|             <div class="ai-form"> | ||||
|               <el-form-item label="名称" prop="name" :rules="[{ required: true, message: '请输入大屏项目名称', trigger: 'blur' }]"> | ||||
|                 <el-input size="small" :maxlength="30" placeholder="请输入大屏项目名称" v-model="form.name"></el-input> | ||||
|               </el-form-item> | ||||
|               <el-form-item label="描述" style="width: 100%;" prop="description"> | ||||
|                 <el-input size="small" :maxlength="200" :rows="5" type="textarea" style="width: 100%;" placeholder="请输入描述" v-model="form.description"></el-input> | ||||
|               </el-form-item> | ||||
|               <el-form-item label="是否开启" style="width: 100%;" prop="status"> | ||||
|                 <el-switch | ||||
|                   v-model="form.status" | ||||
|                   active-value="1" | ||||
|                   inactive-value="0"> | ||||
|                 </el-switch> | ||||
|               </el-form-item> | ||||
|             </div> | ||||
|           </template> | ||||
|         </ai-card> | ||||
|         <ai-card title="大屏"> | ||||
|           <template #right> | ||||
|             <el-button @click="add('')" type="primary">添加大屏</el-button> | ||||
|             <el-button @click="dialog=true" type="primary">定制大屏</el-button> | ||||
|           </template> | ||||
|           <template #content> | ||||
|             <ai-table | ||||
|               :tableData="tableData" | ||||
|               :col-configs="colConfigs" | ||||
|               :total="total" | ||||
|               style="margin-top: 6px;" | ||||
|               :border="true" | ||||
|               row-key="id" | ||||
|               :isShowPagination="false" | ||||
|               @getList="() => {}"> | ||||
|               <el-table-column slot="options" label="状态" align="center"> | ||||
|                 <template slot-scope="{ row }"> | ||||
|                   <el-switch | ||||
|                     v-model="row.status" | ||||
|                     active-value="1" | ||||
|                     @change="() => onStatusChange(row.id)"> | ||||
|                   </el-switch> | ||||
|                 </template> | ||||
|               </el-table-column> | ||||
|               <el-table-column slot="options" width="160px" fixed="right" label="操作" align="center"> | ||||
|                 <template slot-scope="{ row, column, $index }"> | ||||
|                   <div class="table-options"> | ||||
|                     <el-button type="text" @click="toEdit(row.id, row.isCustom, row)">编辑</el-button> | ||||
|                     <el-button type="text" @click="toViewer(row.id)">预览</el-button> | ||||
|                     <el-button type="text" @click="remove($index)">删除</el-button> | ||||
|                   </div> | ||||
|                 </template> | ||||
|               </el-table-column> | ||||
|             </ai-table> | ||||
|           </template> | ||||
|         </ai-card> | ||||
|       </el-form> | ||||
|       <Layout | ||||
|         v-if="isShowLayout" | ||||
|         :instance="instance" | ||||
|         :dict="dict" | ||||
|         :params="query" | ||||
|         @change="onChange" | ||||
|         :urlPrefix="urlPrefix" | ||||
|         :theme="config.theme" | ||||
|         @close="isShowLayout = false"> | ||||
|       </Layout> | ||||
|       <ai-dialog :visible.sync="dialog" title="定制大屏" @closed="custom={}" @onConfirm="handleCustomizedDV"> | ||||
|         <el-form ref="CustomDVFrom" size="small" :model="custom" :rules="rules" label-width="80px"> | ||||
|           <el-form-item label="大屏标题" prop="title"> | ||||
|             <el-input v-model="custom.title" clearable placeholder="请填写"/> | ||||
|           </el-form-item> | ||||
|           <el-form-item label="选择大屏" prop="dv"> | ||||
|             <ai-select v-model="custom.dv" :selectList="dict.getDict('customizedDVs')"/> | ||||
|           </el-form-item> | ||||
|           <el-form-item label="静态数据"> | ||||
|             <el-input type="textarea" rows="5" v-model="custom.meta"/> | ||||
|           </el-form-item> | ||||
|         </el-form> | ||||
|       </ai-dialog> | ||||
|     </template> | ||||
|     <template #footer> | ||||
|       <el-button @click="cancel">取消</el-button> | ||||
|       <el-button type="primary" @click="confirm">提交</el-button> | ||||
|     </template> | ||||
|   </ai-detail> | ||||
| </template> | ||||
|  | ||||
| <script> | ||||
|   import Layout from './Layout.vue' | ||||
|   import Sortable from 'sortablejs' | ||||
|  | ||||
|   export default { | ||||
|     name: 'Add', | ||||
|     props: { | ||||
|       instance: Function, | ||||
|       dict: Object, | ||||
|       urlPrefix: String | ||||
|     }, | ||||
|     inject: { | ||||
|       home: {default: ''} | ||||
|     }, | ||||
|     components: { | ||||
|       Layout | ||||
|     }, | ||||
|  | ||||
|     data() { | ||||
|       return { | ||||
|         info: {}, | ||||
|         department: [], | ||||
|         form: { | ||||
|           name: '', | ||||
|           relationLsIds: '', | ||||
|           relationLsNames: '', | ||||
|           status: '1', | ||||
|           description: '' | ||||
|         }, | ||||
|         screenId: '', | ||||
|         query: {}, | ||||
|         total: 0, | ||||
|         colConfigs: [ | ||||
|           {prop: 'title', label: '标题'}, | ||||
|           {prop: 'id', label: 'ID'} | ||||
|         ], | ||||
|         tableData: [], | ||||
|         isShowLayout: false, | ||||
|         id: '', | ||||
|         dialog: false, | ||||
|         custom: {}, | ||||
|         rules: { | ||||
|           dv: [{required: true, message: "请选择 定制大屏"}], | ||||
|           title: [{required: true, message: "请输入 大屏标题"}], | ||||
|         }, | ||||
|         config: { | ||||
|           backgroundImage: [] | ||||
|         } | ||||
|       } | ||||
|     }, | ||||
|  | ||||
|     created() { | ||||
|       this.dict.load('customizedDVs') | ||||
|       this.getInfo() | ||||
|     }, | ||||
|  | ||||
|  | ||||
|     methods: { | ||||
|       getInfo() { | ||||
|         let {id} = this.$route.query | ||||
|         if (!id) return | ||||
|         this.instance.post(`${this.urlPrefix}/appdiylargescreen/queryLargeScreenProjectDetailById?id=${id}`).then(res => { | ||||
|           if (res?.data) { | ||||
|             this.form = { | ||||
|               ...res.data | ||||
|             } | ||||
|             if (res.data.relationLsIds) { | ||||
|               this.tableData = res.data.lsList.map(v => { | ||||
|                 let conf = JSON.parse(v.config || '') || {} | ||||
|                 return { | ||||
|                   id: v.id, | ||||
|                   title: v.title, | ||||
|                   dv: conf.custom || '', | ||||
|                   meta: JSON.stringify(conf.meta), | ||||
|                   isCustom: !!conf.custom, | ||||
|                   status: v.status | ||||
|                 } | ||||
|               }) | ||||
|               this.total = res.data.lsList.length | ||||
|  | ||||
|               this.$nextTick(() => { | ||||
|                 this.rowDrop() | ||||
|               }) | ||||
|             } | ||||
|           } | ||||
|         }) | ||||
|       }, | ||||
|  | ||||
|       onStatusChange (id) { | ||||
|         this.instance.post(`${this.urlPrefix}/appdiylargescreen/enableLargeScreen?id=${id}`).then(res => { | ||||
|           if (res.code === 0) { | ||||
|             this.$message.success('操作成功') | ||||
|           } | ||||
|         }) | ||||
|       }, | ||||
|  | ||||
|       rowDrop() { | ||||
|         const tbody = document.querySelector('.el-table__body-wrapper tbody') | ||||
|         const _this = this | ||||
|         Sortable.create(tbody, { | ||||
|           onEnd({newIndex, oldIndex}) { | ||||
|             const currRow = _this.tableData.splice(oldIndex, 1)[0] | ||||
|             _this.tableData.splice(newIndex, 0, currRow) | ||||
|           } | ||||
|         }) | ||||
|       }, | ||||
|  | ||||
|       toViewer(id) { | ||||
|         this.$router.push({query: {id}, hash: "#preview"}) | ||||
|       }, | ||||
|       onChange(e) { | ||||
|         const ids = this.tableData.map(v => v.id) | ||||
|         if (ids.indexOf(e.id) < 0) { | ||||
|           this.tableData.push({ | ||||
|             title: e.title, | ||||
|             id: e.id, | ||||
|             status: '1' | ||||
|           }) | ||||
|         } else { | ||||
|           const index = this.tableData.findIndex(v => v.id === e.id) | ||||
|           this.$set(this.tableData[index], 'title', e.title) | ||||
|         } | ||||
|  | ||||
|         this.$nextTick(() => { | ||||
|           if (this.$route.query.id) { | ||||
|             const ids = this.tableData.map(v => v.id).join(',') | ||||
|             const names = this.tableData.map(v => v.name).join(',') | ||||
|             this.instance.post(`${this.urlPrefix}/appdiylargescreen/addOrUpdateLargeScreenProject`, { | ||||
|               ...this.form, | ||||
|               relationLsIds: ids, | ||||
|               relationLsNames: names | ||||
|             }).then(res => { | ||||
|               if (res.code == 0) { | ||||
|               } | ||||
|             }) | ||||
|           } | ||||
|         }) | ||||
|       }, | ||||
|  | ||||
|       add() { | ||||
|         this.query = { | ||||
|           id: '', | ||||
|           name: this.form.name | ||||
|         } | ||||
|         this.isShowLayout = true | ||||
|       }, | ||||
|  | ||||
|       toEdit(id, isCustom, form) { | ||||
|         if (!isCustom) { | ||||
|           this.query = { | ||||
|             id, | ||||
|             name: this.form.name | ||||
|           } | ||||
|  | ||||
|           this.isShowLayout = true | ||||
|         } else { | ||||
|           this.dialog = true | ||||
|           this.custom = { | ||||
|             ...form, | ||||
|  | ||||
|           } | ||||
|         } | ||||
|       }, | ||||
|  | ||||
|       remove(index) { | ||||
|         this.tableData.splice(index, 1) | ||||
|       }, | ||||
|  | ||||
|       confirm() { | ||||
|         this.$refs.form.validate((valid) => { | ||||
|           if (valid) { | ||||
|             const ids = this.tableData.map(v => v.id).join(',') | ||||
|             const names = this.tableData.map(v => v.name).join(',') | ||||
|             this.instance.post(`${this.urlPrefix}/appdiylargescreen/addOrUpdateLargeScreenProject`, { | ||||
|               ...this.form, | ||||
|               relationLsIds: ids, | ||||
|               relationLsNames: names | ||||
|             }).then(res => { | ||||
|               if (res.code == 0) { | ||||
|                 this.$message.success('提交成功') | ||||
|  | ||||
|                 this.home && this.home.refreshDvOptions && this.home.refreshDvOptions() | ||||
|                 setTimeout(() => { | ||||
|                   this.cancel() | ||||
|                 }, 600) | ||||
|               } | ||||
|             }) | ||||
|           } | ||||
|         }) | ||||
|       }, | ||||
|  | ||||
|       cancel() { | ||||
|         this.$router.push({}) | ||||
|       }, | ||||
|  | ||||
|       handleCustomizedDV() { | ||||
|         this.$refs.CustomDVFrom.validate(v => { | ||||
|           if (v) { | ||||
|             this.instance.post(`${this.urlPrefix}/appdiylargescreen/addOrUpdateLargeScreen`, { | ||||
|               config: JSON.stringify({ | ||||
|                 custom: this.custom.dv, | ||||
|                 meta: JSON.parse(this.custom.meta?.replace(/\\n/g, '') || null) | ||||
|               }), | ||||
|               status: 1, | ||||
|               id: this.custom.id, | ||||
|               title: this.custom.title, | ||||
|             }).then(res => { | ||||
|               if (res?.code == 0 && res?.data) { | ||||
|                 this.$message.success('保存成功') | ||||
|                 this.onChange(res.data) | ||||
|                 this.dialog = false | ||||
|               } | ||||
|             }) | ||||
|           } | ||||
|         }) | ||||
|       } | ||||
|     } | ||||
|   } | ||||
| </script> | ||||
|  | ||||
| <style scoped lang="scss"> | ||||
| </style> | ||||
							
								
								
									
										459
									
								
								packages/bigscreen/designer/components/DataConfig.vue
									
									
									
									
									
										Normal file
									
								
							
							
						
						| @@ -0,0 +1,459 @@ | ||||
| <template> | ||||
|   <div class="layout-config__group--wrapper"> | ||||
|     <template v-if="options.type=='map'"> | ||||
|       <ai-fold> | ||||
|         <div slot="title" class="flex w100"> | ||||
|           <span class="layoutTitle fill">标记点设置</span> | ||||
|           <el-button type="text" icon="iconfont iconAdd" @click="handleMapMarker()">添加</el-button> | ||||
|         </div> | ||||
|         <config-item v-for="(item,i) in markers" :key="i" :label="item.label"> | ||||
|           <el-input :value="[item.lat,item.lng].join(',')" readonly size="small"/> | ||||
|           <el-button type="text" icon="el-icon-edit" @click="handleMapMarker(item,i)"/> | ||||
|           <el-button type="text" icon="el-icon-delete" @click="removeMapMarker(i)"/> | ||||
|         </config-item> | ||||
|       </ai-fold> | ||||
|       <ai-fold title="标记点连线"> | ||||
|         <ai-dialog-btn :modal="false" dialog-title="设置标记点连线" :customFooter="false" @confirm="savePolylines" | ||||
|                        @open="handleMapPolylines"> | ||||
|           <code-editor slot="btn" readonly :value="JSON.stringify(options.staticData.polylines, null, 2)" lang="json" | ||||
|                        theme="github" width="100%" height="250" placeholder="测试默认值"/> | ||||
|           <el-button class="m-center" type="text" @click="handleMapPolylineDoc" :closable="false"> | ||||
|             点击查看连线设置参考文档 | ||||
|           </el-button> | ||||
|           <code-editor v-model="json" lang="json" theme="github" width="100%" height="440"/> | ||||
|         </ai-dialog-btn> | ||||
|       </ai-fold> | ||||
|     </template> | ||||
|     <template v-else-if="isPlot"> | ||||
|       <ai-fold v-for="(chart,i) in options.charts" :key="i"> | ||||
|         <div slot="title" class="flex w100"> | ||||
|           <span class="layoutTitle fill" v-text="chart.title"/> | ||||
|           <el-button type="text" icon="el-icon-delete" @click="options.charts.splice(i,1)"/> | ||||
|         </div> | ||||
|         <config-item label="图表名"> | ||||
|           <el-input size="small" v-model="chart.title"/> | ||||
|         </config-item> | ||||
|         <config-item label="图表模板"> | ||||
|           <chart-picker v-model="chart.chart"/> | ||||
|         </config-item> | ||||
|         <datasource-picker v-model="chart.ds" :instance="instance" class="mar-b10" | ||||
|                            @input="chart={...chart,...chart.ds},$emit('change',options)"/> | ||||
|         <config-item label="数据维度" v-if="chart.dataType !== 'staticData'"> | ||||
|           <code-editor v-model="chart.djson" lang="json" theme="github" width="100%" height="100" | ||||
|                        placeholder="参照echarts配置数据维度,为一个数组,数组的第一个值为维度值" | ||||
|                        @change="v=>chart.dimensions=JSON.parse(v)"/> | ||||
|         </config-item> | ||||
|       </ai-fold> | ||||
|       <el-button type="text" icon="el-icon-plus" @click="options.charts.push({title:'新图表'})">添加图表</el-button> | ||||
|     </template> | ||||
|     <template v-else-if="options.type=='monitorCarousel'"> | ||||
|       <config-item label="监控列表"> | ||||
|         <el-button type="text" icon="el-icon-plus" @click="options.list.push({})"/> | ||||
|       </config-item> | ||||
|       <el-table size="mini" :data="options.list" border :row-style="{backgroundColor:'transparent'}"> | ||||
|         <el-table-column label="监控类型"> | ||||
|           <template v-slot="{row}"> | ||||
|             <ai-select size="mini" v-model="row.monitorType" :select-list="monitorTypes"/> | ||||
|           </template> | ||||
|         </el-table-column> | ||||
|         <el-table-column label="监控地址"> | ||||
|           <template v-slot="{row}"> | ||||
|             <el-input v-if="['hik','dahua'].includes(row.monitorType)" size="mini" v-model="row.src" clearable/> | ||||
|             <div v-else-if="['cmcc','slw'].includes(row.monitorType)"> | ||||
|               <el-input size="mini" v-model="row.api" clearable placeholder="请输入监控列表接口"/> | ||||
|               <ai-select v-model="row.did" :instance="instance" @change="handleMonitor(row)" size="mini" | ||||
|                          :prop="{label:'name'}" :condition="e=>!!e.name&&!!e.id" class="mar-t8" :action="row.api"/> | ||||
|             </div> | ||||
|           </template> | ||||
|         </el-table-column> | ||||
|         <el-table-column width="60px" label="操作"> | ||||
|           <template v-slot="{row,i}"> | ||||
|             <el-button type="text" @click="$confirm('是否删除该监控?').then(()=>options.list.splice(i,1))">删除 | ||||
|             </el-button> | ||||
|           </template> | ||||
|         </el-table-column> | ||||
|       </el-table> | ||||
|     </template> | ||||
|     <div class="layout-config__group" v-else-if="['hik','dahua'].includes(options.monitorType)"> | ||||
|       <h2>基础设置</h2> | ||||
|       <config-item label="视频地址"> | ||||
|         <el-input size="mini" v-model="options.src"/> | ||||
|       </config-item> | ||||
|     </div> | ||||
|     <div class="layout-config__group" v-else> | ||||
|       <h2>基础设置</h2> | ||||
|       <datasource-picker :options="options" :instance="instance" @input="$emit('change',options)"/> | ||||
|     </div> | ||||
|     <div class="layout-config__group" v-if="isTable"> | ||||
|       <h2>表格设置</h2> | ||||
|       <code-editor v-model="json" theme="github" width="100%" height="440" | ||||
|                    placeholder="参照dvScrollBoard设置表格" | ||||
|                    @change="v=>options.tableConfig=JSON.parse(v)"/> | ||||
|     </div> | ||||
|     <div v-if="options.dataType!='staticData'&&options.type=='monitor'&&['cmcc','slw'].includes(options.monitorType)" | ||||
|          class="layout-config__group"> | ||||
|       <h2>字段设置</h2> | ||||
|       <config-item label="监控视频"> | ||||
|         <el-select size="mini" v-model="options.moniterId" placeholder="请选择监控视频" @change="onMoniterId"> | ||||
|           <el-option | ||||
|               v-for="(item, index) in monitorList" | ||||
|               :key="index" | ||||
|               :label="item.name" | ||||
|               :value="item.id"> | ||||
|           </el-option> | ||||
|         </el-select> | ||||
|       </config-item> | ||||
|     </div> | ||||
|     <div v-if="options.dataType!='staticData'&& keys.length &&!['table','monitor','map','plot'].includes(options.type)" | ||||
|          class="layout-config__group"> | ||||
|       <h2>字段设置</h2> | ||||
|       <config-item label="X轴设置"> | ||||
|         <el-select size="mini" v-model="options.dataX" placeholder="请选择X轴" @change="onChooseChange"> | ||||
|           <el-option | ||||
|               v-for="(item, index) in keys" | ||||
|               :key="index" | ||||
|               :label="item" | ||||
|               :value="item"> | ||||
|           </el-option> | ||||
|         </el-select> | ||||
|       </config-item> | ||||
|       <config-item label="Y轴设置"> | ||||
|         <el-select size="mini" multiple :multiple-limit="options.type.indexOf('pie') > -1 ? 1 : 100" | ||||
|                    v-model="options.dataY" collapse-tags placeholder="请选择Y轴" | ||||
|                    @change="onChooseChange"> | ||||
|           <el-option | ||||
|               v-for="(item, index) in keys" | ||||
|               :key="index" | ||||
|               :label="item" | ||||
|               :value="item"> | ||||
|           </el-option> | ||||
|         </el-select> | ||||
|       </config-item> | ||||
|     </div> | ||||
|     <ai-dialog class="layout-config__edit" v-model="showMapEditor" title="设置地图标记点" append-to-body | ||||
|                @close="form={}" @confirm="saveMarker"> | ||||
|       <el-form :model="form" size="small" ref="mapMarker" label-width="120px"> | ||||
|         <el-form-item label="标记点名称" :rules="{required:true,message:'请填写标记点名称'}"> | ||||
|           <el-input placeholder="用于地图上展示对标记点的文字标签" v-model="form.label" clearable/> | ||||
|         </el-form-item> | ||||
|         <el-form-item label="标记点图标"> | ||||
|           <el-input placeholder="用于地图上展示对标记点的显示图标" v-model="form.icon" clearable/> | ||||
|         </el-form-item> | ||||
|         <div flex> | ||||
|           <el-form-item class="fill" label="经度" :rules="{required:true,message:'请填写标记点经度'}"> | ||||
|             <el-input v-model="form.lng" clearable placeholder="小数点位保留至少6位数"/> | ||||
|           </el-form-item> | ||||
|           <el-form-item class="fill" label="纬度" :rules="{required:true,message:'请填写标记点纬度'}"> | ||||
|             <el-input v-model="form.lat" clearable placeholder="小数点位保留至少6位数"/> | ||||
|           </el-form-item> | ||||
|         </div> | ||||
|         <el-form-item label="弹窗内容"> | ||||
|           <ai-editor v-model="form.infoWindowHtml" :instance="instance"/> | ||||
|         </el-form-item> | ||||
|       </el-form> | ||||
|     </ai-dialog> | ||||
|   </div> | ||||
| </template> | ||||
|  | ||||
| <script> | ||||
| import CodeEditor from 'bin-ace-editor' | ||||
| import 'brace/mode/json' | ||||
| import 'brace/snippets/json'; | ||||
| import 'brace/theme/github'; | ||||
| import 'brace/theme/monokai'; | ||||
| import AiDialogBtn from "dui/packages/layout/AiDialogBtn.vue"; | ||||
| import AiFold from "dui/packages/layout/AiFold.vue"; | ||||
| import ChartPicker from "./chartPicker.vue"; | ||||
| import {monitorTypes} from "../config"; | ||||
| import ConfigItem from "./configItem.vue"; | ||||
| import DatasourcePicker from "./datasourcePicker.vue"; | ||||
| import AiSelect from "dui/packages/basic/AiSelect.vue"; | ||||
| import {DvCompData} from "dui/dv"; | ||||
|  | ||||
| export default { | ||||
|   name: 'dataConfig', | ||||
|   model: { | ||||
|     prop: "options", | ||||
|     event: "change" | ||||
|   }, | ||||
|   props: { | ||||
|     options: Object, | ||||
|     instance: Function, | ||||
|     dict: Object, | ||||
|   }, | ||||
|   data() { | ||||
|     return { | ||||
|       dataTypes: Object.entries(DvCompData.types).map(e => ({id: e[0], label: e[1]})), | ||||
|       json: "", | ||||
|       keys: [], | ||||
|       monitorList: [], | ||||
|       list: [], | ||||
|       showMapEditor: false, | ||||
|       form: {}, | ||||
|       datasource: {}, | ||||
|       monitorTypes | ||||
|     } | ||||
|   }, | ||||
|   computed: { | ||||
|     markers: v => v.options.staticData?.markers || [], | ||||
|     isTable: v => v.options.type == 'table', | ||||
|     isPlot: v => v.options.type == 'plot' | ||||
|   }, | ||||
|   components: { | ||||
|     AiSelect, | ||||
|     DatasourcePicker, | ||||
|     ConfigItem, | ||||
|     ChartPicker, | ||||
|     AiFold, | ||||
|     AiDialogBtn, | ||||
|     CodeEditor, | ||||
|   }, | ||||
|   created() { | ||||
|     if (this.options.type == "map" && Array.isArray(this.options.staticData)) {//处理历史数据,并更新最新数据结构 | ||||
|       const values = this.$copy(this.options) | ||||
|       values.staticData = {markers: this.$copy(this.options.staticData)} | ||||
|       this.$emit("change", values) | ||||
|     } else if (this.isTable) { | ||||
|       this.json = JSON.stringify(this.options.tableConfig) | ||||
|     } else if (this.options.type == "monitorCarousel") { | ||||
|       const {list = []} = this.options | ||||
|       this.$set(this.options, 'list', list) | ||||
|     } else if (this.isPlot) { | ||||
|       this.options.charts = this.options.charts.map(e => ({...e, ds: e})) | ||||
|     } | ||||
|   }, | ||||
|   mounted() { | ||||
|     if ((this.options.dataY && this.options.dataY.length && this.options.dataX) || this.options.type === 'monitor') { | ||||
|       const api = this.options.dataType === 'apiData' ? this.options.api : `/app/appdiylargescreen/statisticsByLsid?id=${this.options.sourceDataId}` | ||||
|       this.instance.post(api).then(res => { | ||||
|         if (res.code == 0) { | ||||
|           if (res.data.length && this.options.type !== 'monitor') { | ||||
|             this.list = res.data | ||||
|             this.keys = Object.keys(res.data[0]) | ||||
|  | ||||
|             this.$nextTick(() => { | ||||
|               this.onChooseChange() | ||||
|             }) | ||||
|           } else if (this.options.type === 'monitor') { | ||||
|             this.monitorList = res.data | ||||
|  | ||||
|             if (this.options.src) { | ||||
|               const obj = res.data.filter(v => this.options.title === v.name) | ||||
|  | ||||
|               if (obj.length) { | ||||
|                 this.options.src = obj[0].url | ||||
|               } | ||||
|             } | ||||
|           } | ||||
|         } | ||||
|       }) | ||||
|     } | ||||
|   }, | ||||
|   methods: { | ||||
|     onMoniterId(e) { | ||||
|       this.instance.post(`/app/appzyvideoequipment/getWebSdkUrl?deviceId=${e}`).then(res => { | ||||
|         if (res.code == 0) { | ||||
|           this.options.src = JSON.parse(res.data).url | ||||
|         } | ||||
|       }) | ||||
|     }, | ||||
|     handleMonitor(row) { | ||||
|       this.instance.post(`/app/appzyvideoequipment/getWebSdkUrl?deviceId=${row.did}`).then(res => { | ||||
|         if (res.code == 0) { | ||||
|           this.$set(row, 'src', JSON.parse(res.data).url) | ||||
|         } | ||||
|       }) | ||||
|     }, | ||||
|     onChooseChange() { | ||||
|       let arr = [] | ||||
|       if (this.options.dataX && this.options.dataY.length) { | ||||
|         this.list.forEach(item => { | ||||
|           let obj = {} | ||||
|           this.options.dataY.forEach(v => { | ||||
|             obj[v] = item[v] | ||||
|           }) | ||||
|           arr.push({ | ||||
|             [this.options.dataX]: item[this.options.dataX], | ||||
|             ...obj | ||||
|           }) | ||||
|         }) | ||||
|         this.options[this.options.dataType] = arr | ||||
|       } | ||||
|     }, | ||||
|     handleMapMarker(v = {}, index) { | ||||
|       this.form = this.$copy({...v, index}) | ||||
|       this.showMapEditor = true | ||||
|     }, | ||||
|     saveMarker() { | ||||
|       this.$refs.mapMarker.validate().then(() => { | ||||
|         const i = this.$copy(this.form.index) | ||||
|         delete this.form.index | ||||
|         if (i > -1) { | ||||
|           this.options.staticData.markers.splice(i, 1, this.form) | ||||
|         } else this.options.staticData.markers.push(this.form) | ||||
|         this.showMapEditor = false | ||||
|       }) | ||||
|     }, | ||||
|     removeMapMarker(i) { | ||||
|       this.$confirm("是否要删除该标记点").then(() => { | ||||
|         this.options.staticData.markers.splice(i, 1) | ||||
|       }) | ||||
|     }, | ||||
|     savePolylines() { | ||||
|       this.$set(this.options.staticData, 'polylines', JSON.parse(this.json)) | ||||
|     }, | ||||
|     handleMapPolylines() { | ||||
|       this.json = JSON.stringify(this.options.staticData.polylines || [{path: [[31.547706, 107.224325], [31.552456, 107.201185]]}]) | ||||
|     }, | ||||
|     handleMapPolylineDoc() { | ||||
|       window.open('https://lbs.amap.com/api/javascript-api-v2/documentation#polyline') | ||||
|     } | ||||
|   } | ||||
| } | ||||
| </script> | ||||
|  | ||||
| <style lang="scss"> | ||||
| .el-dialog__body { | ||||
|   .jsoneditor-vue { | ||||
|     height: 480px; | ||||
|  | ||||
|     .jsoneditor-poweredBy { | ||||
|       display: none; | ||||
|     } | ||||
|   } | ||||
| } | ||||
|  | ||||
| .ai-dialog__wrapper { | ||||
|   color: #333; | ||||
| } | ||||
|  | ||||
| .layout-config__group--wrapper { | ||||
|  | ||||
|   :deep(.layout-config__group) { | ||||
|     padding: 10px 10px 20px; | ||||
|     border-bottom: 1px solid #000000; | ||||
|  | ||||
|     &:last-child { | ||||
|       border: none; | ||||
|     } | ||||
|  | ||||
|  | ||||
|     & > h2 { | ||||
|       margin-bottom: 20px; | ||||
|       color: #FFFFFF; | ||||
|       font-size: 15px; | ||||
|       font-weight: 700; | ||||
|     } | ||||
|  | ||||
|     .layoutTitle { | ||||
|       color: #FFFFFF; | ||||
|       font-size: 15px; | ||||
|       font-weight: 700; | ||||
|     } | ||||
|   } | ||||
|  | ||||
|   :deep(.layout-config__item) { | ||||
|     display: flex; | ||||
|     align-items: center; | ||||
|     justify-content: space-between; | ||||
|     margin-bottom: 10px; | ||||
|  | ||||
|     &:last-child { | ||||
|       margin-bottom: 0; | ||||
|     } | ||||
|  | ||||
|     label { | ||||
|       flex-shrink: 0; | ||||
|       width: 60px; | ||||
|       color: #FFFFFF; | ||||
|       font-size: 12px; | ||||
|       text-align: right; | ||||
|     } | ||||
|  | ||||
|     .el-select .el-tag { | ||||
|       color: #fff; | ||||
|       background: transparent; | ||||
|     } | ||||
|  | ||||
|     .el-input__icon { | ||||
|       color: #fff; | ||||
|     } | ||||
|  | ||||
|     .el-switch__label { | ||||
|       color: #fff; | ||||
|     } | ||||
|  | ||||
|     .el-select { | ||||
|       width: 100%; | ||||
|  | ||||
|       &:last-child { | ||||
|         margin-right: 0; | ||||
|       } | ||||
|  | ||||
|       input { | ||||
|         background: #262C33; | ||||
|         font-size: 12px; | ||||
|         color: #fff; | ||||
|         border: 1px solid #030411; | ||||
|       } | ||||
|  | ||||
|       .el-input__icon { | ||||
|         color: #fff; | ||||
|       } | ||||
|     } | ||||
|  | ||||
|     :deep(.el-collapse) { | ||||
|       height: 18px; | ||||
|     } | ||||
|   } | ||||
|  | ||||
|   .el-icon-delete { | ||||
|     color: #f46; | ||||
|   } | ||||
|  | ||||
|   .el-button--text + .el-button--text { | ||||
|     margin-left: 0; | ||||
|   } | ||||
|  | ||||
|   input { | ||||
|     background: #262C33; | ||||
|     font-size: 12px; | ||||
|     color: #fff; | ||||
|     border: 1px solid #030411; | ||||
|   } | ||||
|  | ||||
|   .layout-config__item--right { | ||||
|     display: flex; | ||||
|     align-items: center; | ||||
|     justify-content: flex-end; | ||||
|     text-align: right; | ||||
|     margin-left: 30px; | ||||
|   } | ||||
|  | ||||
|   .el-table { | ||||
|     background-color: transparent; | ||||
|  | ||||
|     tr { | ||||
|       background-color: transparent; | ||||
|     } | ||||
|  | ||||
|     .el-table__cell { | ||||
|       color: white; | ||||
|       background-color: #1D2127 !important; | ||||
|  | ||||
|       input:disabled { | ||||
|         background-color: transparent; | ||||
|         border-color: transparent; | ||||
|         color: white; | ||||
|         padding: 0; | ||||
|       } | ||||
|  | ||||
|       &:last-of-type { | ||||
|         border-left: 1px solid #fff; | ||||
|       } | ||||
|     } | ||||
|   } | ||||
| } | ||||
|  | ||||
|  | ||||
| </style> | ||||
							
								
								
									
										91
									
								
								packages/bigscreen/designer/components/chartPicker.vue
									
									
									
									
									
										Normal file
									
								
							
							
						
						| @@ -0,0 +1,91 @@ | ||||
| <template> | ||||
|   <section class="chartPicker"> | ||||
|     <ai-dialog-btn :modal="false" dialog-title="选择图表模板" :customFooter="false" | ||||
|                    @confirm="handleConfirm" @open="handleOpenDialog"> | ||||
|       <template #btn> | ||||
|         <img class="pointer thumb" v-if="current.thumb" :src="current.thumb"/> | ||||
|         <el-button v-else type="text">选择图表</el-button> | ||||
|       </template> | ||||
|       <div class="charts"> | ||||
|         <div class="item pointer" v-for="(tpl,i) in tpls" :key="i" :class="{selected:selected==tpl.type}" | ||||
|              @click="selected=tpl.type"> | ||||
|           <img :src="tpl.thumb"/> | ||||
|           <div v-text="tpl.label"/> | ||||
|         </div> | ||||
|       </div> | ||||
|     </ai-dialog-btn> | ||||
|   </section> | ||||
| </template> | ||||
| <script> | ||||
| import AiDialogBtn from "dui/packages/layout/AiDialogBtn"; | ||||
| import {chartTpl} from "../config"; | ||||
|  | ||||
| export default { | ||||
|   name: "chartPicker", | ||||
|   components: {AiDialogBtn}, | ||||
|   model: { | ||||
|     prop: "value", | ||||
|     event: "input" | ||||
|   }, | ||||
|   props: { | ||||
|     value: String, | ||||
|     tpls: {default: () => chartTpl.map(e => e.list).flat()} | ||||
|   }, | ||||
|   data() { | ||||
|     return { | ||||
|       selected: null | ||||
|     } | ||||
|   }, | ||||
|   computed: { | ||||
|     current: v => v.tpls.find(e => e.type == v.value) || {} | ||||
|   }, | ||||
|   watch: { | ||||
|     value(v) { | ||||
|       v && this.$emit("config", this.$echartTpls[v]) | ||||
|     } | ||||
|   }, | ||||
|   methods: { | ||||
|     handleConfirm() { | ||||
|       this.$emit("input", this.selected) | ||||
|     }, | ||||
|     handleOpenDialog() { | ||||
|       this.selected = this.$copy(this.value) | ||||
|     } | ||||
|   }, | ||||
| } | ||||
| </script> | ||||
| <style scoped lang="scss"> | ||||
| .chartPicker { | ||||
|   text-align: left; | ||||
|  | ||||
|   .pointer { | ||||
|     cursor: pointer; | ||||
|   } | ||||
|  | ||||
|   .thumb { | ||||
|     width: 200px; | ||||
|     height: 90px; | ||||
|   } | ||||
|  | ||||
|   .charts { | ||||
|     display: grid; | ||||
|     grid-template-columns: 1fr 1fr 1fr 1fr 1fr; | ||||
|     gap: 8px; | ||||
|  | ||||
|     .item { | ||||
|       text-align: center; | ||||
|       padding: 2px; | ||||
|       border: 2px solid transparent; | ||||
|  | ||||
|       & > img { | ||||
|         width: 100%; | ||||
|         height: 90px; | ||||
|       } | ||||
|  | ||||
|       &.selected, &:hover { | ||||
|         border-color: #46f; | ||||
|       } | ||||
|     } | ||||
|   } | ||||
| } | ||||
| </style> | ||||
							
								
								
									
										89
									
								
								packages/bigscreen/designer/components/componentConfig.vue
									
									
									
									
									
										Normal file
									
								
							
							
						
						| @@ -0,0 +1,89 @@ | ||||
| <template> | ||||
|   <section class="componentConfig"> | ||||
|     <div class="layout-right__content--wrapper"> | ||||
|       <div class="layout-config__group"> | ||||
|         <h2>基础设置</h2> | ||||
|         <div class="layout-config__item"> | ||||
|           <label>图表尺寸</label> | ||||
|           <div class="layout-config__item--right"> | ||||
|             <el-input-number size="mini" :min="0" v-model="config.width" controls-position="right"/> | ||||
|             <el-input-number size="mini" :min="0" v-model="config.height" controls-position="right"/> | ||||
|           </div> | ||||
|         </div> | ||||
|         <div class="layout-config__item"> | ||||
|           <label>图表位置</label> | ||||
|           <div class="layout-config__item--right"> | ||||
|             <el-input-number size="mini" :min="0" v-model="config.left" controls-position="right"/> | ||||
|             <el-input-number size="mini" :min="0" v-model="config.top" controls-position="right"/> | ||||
|           </div> | ||||
|         </div> | ||||
|         <config-item label="內边距"> | ||||
|           <el-input size="mini" v-model="config.padding" clearable placeholder="请输入符合css的padding合法值"/> | ||||
|         </config-item> | ||||
|       </div> | ||||
|     </div> | ||||
|     <div class="layout-right__content--wrapper"> | ||||
|       <div class="layout-config__group"> | ||||
|         <h2>组件设置</h2> | ||||
|         <config-extra v-model="config"/> | ||||
|       </div> | ||||
|     </div> | ||||
|     <div class="layout-right__content--wrapper"> | ||||
|       <div class="layout-config__group"> | ||||
|         <h2>弹窗设置</h2> | ||||
|         <config-item label="标题"> | ||||
|           <el-input size="mini" clearable placeholder="请输入弹窗标题" v-model="config.dialogTitle"/> | ||||
|         </config-item> | ||||
|         <config-item label="内容" v-if="!['table','AiDvTable','AiDvMap','linkageMap'].includes(config.type)"> | ||||
|           <ai-dialog-btn dialog-title="弹窗内容" text="打开编辑器" :modal="false"> | ||||
|             <ai-editor clearable placeholder="请输入弹窗内容" v-model="config.dialogContent" :instance="instance"/> | ||||
|           </ai-dialog-btn> | ||||
|         </config-item> | ||||
|       </div> | ||||
|     </div> | ||||
|   </section> | ||||
| </template> | ||||
|  | ||||
| <script> | ||||
| import ConfigItem from "./configItem"; | ||||
| import ConfigExtra from "./configExtra.vue"; | ||||
|  | ||||
| export default { | ||||
|   name: 'componentConfig', | ||||
|   components: {ConfigExtra, ConfigItem}, | ||||
|   props: { | ||||
|     config: {default: () => ({})}, | ||||
|     instance: Function, | ||||
|     dict: Object, | ||||
|   }, | ||||
| } | ||||
| </script> | ||||
|  | ||||
| <style lang="scss" scoped> | ||||
| .componentConfig { | ||||
|   .table-config { | ||||
|     & > div { | ||||
|       display: flex; | ||||
|       align-items: center; | ||||
|       justify-content: space-between; | ||||
|       width: 232px; | ||||
|  | ||||
|       :deep( .el-select ) { | ||||
|         width: 80px; | ||||
|       } | ||||
|  | ||||
|       .el-select { | ||||
|         width: 100%; | ||||
|  | ||||
|         .el-input { | ||||
|           width: 100%; | ||||
|  | ||||
|           :deep( input ) { | ||||
|             width: 80px | ||||
|           } | ||||
|         } | ||||
|       } | ||||
|     } | ||||
|   } | ||||
| } | ||||
| </style> | ||||
							
								
								
									
										239
									
								
								packages/bigscreen/designer/components/configExtra.vue
									
									
									
									
									
										Normal file
									
								
							
							
						
						| @@ -0,0 +1,239 @@ | ||||
| <script> | ||||
| import GroupItem from "./groupItem"; | ||||
| import ConfigItem from "./configItem"; | ||||
| import ChartPicker from "./chartPicker"; | ||||
| import JsonEditor from "./jsonEditor"; | ||||
| import {layers, monitorTypes} from "../config"; | ||||
| import AiDvSummary from "dui/dv/layout/AiDvSummary/AiDvSummary"; | ||||
|  | ||||
| export default { | ||||
|   name: "configExtra", | ||||
|   components: {JsonEditor, ChartPicker, ConfigItem, GroupItem}, | ||||
|   props: ['config'], | ||||
|   model: { | ||||
|     prop: 'config', | ||||
|     event: 'input' | ||||
|   }, | ||||
|   data() { | ||||
|     return { | ||||
|       borderList: ['border0', 'border1', 'border2', 'border3', 'border4', 'border5', 'border6', 'border7', 'border8', 'border9', 'border10', | ||||
|         'border11', 'border12', 'border13', 'border14', 'border15'],//边框待选项 | ||||
|       layers, monitorTypes, | ||||
|       tableStatus: [ | ||||
|         {label: '是', value: '1'}, | ||||
|         {label: '否', value: '0'} | ||||
|       ], | ||||
|       positionList: [ | ||||
|         {label: "左上", id: "lt"}, | ||||
|         {label: "右上", id: "rt"}, | ||||
|         {label: "左下", id: "lb"}, | ||||
|         {label: "右下", id: "rb"} | ||||
|       ], | ||||
|     } | ||||
|   }, | ||||
|   computed: { | ||||
|     summaryOps: () => Object.keys(AiDvSummary.components).map(e => ({label: e, id: e})), | ||||
|     values: v => v.config?.[v.config?.dataType] || v.config.data | ||||
|   }, | ||||
|   watch: { | ||||
|     values: { | ||||
|       immediate: true, deep: true, | ||||
|       handler() { | ||||
|         if (this.config.type === 'AiDvTable') { | ||||
|           this.config.config = this.values?.map((v, i) => { | ||||
|             return { | ||||
|               color: this.config.config?.[i]?.color || '', | ||||
|               width: this.config.config?.[i]?.width || '', | ||||
|               align: this.config.config?.[i]?.align || '', | ||||
|             } | ||||
|           }) | ||||
|         } | ||||
|       } | ||||
|     } | ||||
|   }, | ||||
| } | ||||
| </script> | ||||
|  | ||||
| <template> | ||||
|   <section class="configExtra"> | ||||
|     <config-item label="标题"> | ||||
|       <el-input v-model="config.summaryTitle" size="mini" v-if="config.display === 'summary2'" placeholder="请输入标题"/> | ||||
|       <el-input v-else v-model="config.title" size="mini" placeholder="请输入标题"/> | ||||
|     </config-item> | ||||
|     <config-item label="边框" v-if="config.type !== 'display'"> | ||||
|       <el-select size="mini" v-model="config.border" placeholder="请选择边框" clearable> | ||||
|         <el-option | ||||
|             v-for="(item, index) in borderList" | ||||
|             :key="index" | ||||
|             :label="item" | ||||
|             :value="item"> | ||||
|         </el-option> | ||||
|       </el-select> | ||||
|     </config-item> | ||||
|     <config-item label="图表模板"> | ||||
|       <chart-picker v-model="config.type" :tpls="layers" @input="v=>config.echartOps=$echartTpls[v]"/> | ||||
|     </config-item> | ||||
|     <template v-if="/(AiDvMap|linkageMap)/.test(config.type)"> | ||||
|       <config-item label="地图数据(geoJSON)"> | ||||
|         <el-input v-model="config.geoJson" size="mini" clearable placeholder="请输入geoJson的URL地址"/> | ||||
|       </config-item> | ||||
|     </template> | ||||
|     <template v-if="/linkageMap/.test(config.type)"> | ||||
|       <config-item v-for="(item,i) in config.summaryConfigs" :key="i" :label="`统计${i+1}`"> | ||||
|         <ai-select placeholder="请选择位置" v-model="item.pos" :select-list="positionList" size="mini"/> | ||||
|         <ai-select placeholder="请选择类型" v-model="item.display" :select-list="summaryOps" size="mini"/> | ||||
|       </config-item> | ||||
|     </template> | ||||
|     <template v-if="/tabs/.test(config.type)"> | ||||
|       <group-item v-for="(tab,i) in values" :key="i" :label="i"> | ||||
|         <group-item v-for="(comp,j) in tab" :key="j" :label="comp.name"> | ||||
|           <config-extra v-model="tab[j]"/> | ||||
|         </group-item> | ||||
|       </group-item> | ||||
|     </template> | ||||
|     <template v-if="/Chart/.test(config.type)"> | ||||
|       <config-item label="图表配置项" top-label> | ||||
|         <json-editor v-model="config.echartOps"/> | ||||
|       </config-item> | ||||
|     </template> | ||||
|     <config-item label="视频地址" v-if="config.type === 'video'"> | ||||
|       <el-input v-model="config.src" size="mini"/> | ||||
|     </config-item> | ||||
|     <config-item label="图片URL" v-if="config.type=='img'"> | ||||
|       <el-input v-model="config.src" size="mini" clearable placeholder="请输入图片URL"/> | ||||
|     </config-item> | ||||
|     <config-item label="视频类型" v-if="config.type === 'monitor'"> | ||||
|       <ai-select size="mini" v-model="config.monitorType" :select-list="monitorTypes"/> | ||||
|     </config-item> | ||||
|     <config-item label="样式" v-if="config.type === 'AiRanking'"> | ||||
|       <el-select size="mini" v-model="config.subType" placeholder="请选择样式" clearable> | ||||
|         <el-option label="样式1" value="Ranking1"></el-option> | ||||
|         <el-option label="样式2" value="Ranking2"></el-option> | ||||
|         <el-option label="样式3" value="Ranking3"></el-option> | ||||
|       </el-select> | ||||
|     </config-item> | ||||
|     <template v-if="config.type === 'table' || config.type === 'AiDvTable'"> | ||||
|       <config-item label="显示排名"> | ||||
|         <el-select size="mini" v-model="config.isShowIndex" placeholder="请选择" clearable> | ||||
|           <el-option | ||||
|               v-for="(item, index) in tableStatus" | ||||
|               :key="index" | ||||
|               :label="item.label" | ||||
|               :value="item.value"> | ||||
|           </el-option> | ||||
|         </el-select> | ||||
|       </config-item> | ||||
|       <config-item label="斑马纹" v-if="config.type === 'AiDvTable'"> | ||||
|         <el-select size="mini" v-model="config.stripe" placeholder="请选择" clearable> | ||||
|           <el-option | ||||
|               label="是" | ||||
|               value="1"> | ||||
|           </el-option> | ||||
|           <el-option | ||||
|               label="否" | ||||
|               value="0"> | ||||
|           </el-option> | ||||
|         </el-select> | ||||
|       </config-item> | ||||
|       <config-item label="简易样式" v-if="config.type === 'AiDvTable'"> | ||||
|         <el-select size="mini" v-model="config.simple" placeholder="请选择" clearable> | ||||
|           <el-option | ||||
|               label="是" | ||||
|               value="1"> | ||||
|           </el-option> | ||||
|           <el-option | ||||
|               label="否" | ||||
|               value="0"> | ||||
|           </el-option> | ||||
|         </el-select> | ||||
|       </config-item> | ||||
|       <config-item label="表格行数" v-if="config.type !== 'AiDvTable'"> | ||||
|         <el-input-number size="mini" style="width: 232px" :min="0" v-model="config.rowNum" controls-position="right"/> | ||||
|       </config-item> | ||||
|       <config-item v-if="config.type === 'AiDvTable'" v-for="(item, i) in config.config" :key="i" :label="`第${i+1}列`"> | ||||
|         <el-select size="mini" style="width: 80px;" v-model="item.align" placeholder="请选择" clearable> | ||||
|           <el-option label="居中" value="center"></el-option> | ||||
|           <el-option label="居左" value="left"></el-option> | ||||
|           <el-option label="居右" value="right"></el-option> | ||||
|         </el-select> | ||||
|         <el-color-picker v-model="item.color" class="mar-h10" size="mini"/> | ||||
|         <el-input-number v-model="item.width" label="描述文字" controls-position="right" size="mini"/> | ||||
|       </config-item> | ||||
|     </template> | ||||
|     <template v-if="config.type === 'map'"> | ||||
|       <div class="layout-config__item"> | ||||
|         <label>遮罩层</label> | ||||
|         <div class="layout-config__item--right"> | ||||
|           <el-select size="mini" v-model="config.mask" placeholder="请选择" clearable> | ||||
|             <el-option label="是" value="1"></el-option> | ||||
|             <el-option label="否" value="2"></el-option> | ||||
|           </el-select> | ||||
|         </div> | ||||
|       </div> | ||||
|       <div class="layout-config__item"> | ||||
|         <label>地图图层</label> | ||||
|         <div class="layout-config__item--right"> | ||||
|           <el-select size="mini" v-model="config.layers" placeholder="请选择" clearable> | ||||
|             <el-option label="地图" value="vector"/> | ||||
|             <el-option label="卫星" value="satellite"/> | ||||
|           </el-select> | ||||
|         </div> | ||||
|       </div> | ||||
|       <div class="layout-config__item"> | ||||
|         <label>选择地区</label> | ||||
|         <div class="layout-config__item--right"> | ||||
|           <AiAreaGet :instance="instance" :valueLevel="3" v-model="config.areaId" placeholder="地图展示的中心"/> | ||||
|         </div> | ||||
|       </div> | ||||
|       <div class="layout-config__item"> | ||||
|         <label>限制地区</label> | ||||
|         <div class="layout-config__item--right"> | ||||
|           <ai-select v-model="config.limitArea" :selectList="dict.getDict('yesOrNo')"/> | ||||
|         </div> | ||||
|       </div> | ||||
|       <div class="layout-config__item"> | ||||
|         <label>显示标签</label> | ||||
|         <div class="layout-config__item--right"> | ||||
|           <ai-select v-model="config.alwaysShow" :selectList="dict.getDict('yesOrNo')"/> | ||||
|         </div> | ||||
|       </div> | ||||
|       <div class="layout-config__item"> | ||||
|         <label>展示光轨</label> | ||||
|         <div class="layout-config__item--right"> | ||||
|           <ai-select v-model="config.pulseLines" :selectList="dict.getDict('yesOrNo')"/> | ||||
|         </div> | ||||
|       </div> | ||||
|       <div class="layout-config__item layout-config__item--input"> | ||||
|         <label>地图样式</label> | ||||
|         <div class="layout-config__item--right"> | ||||
|           <el-input size="mini" v-model="config.mapStyle" clearable placeholder="请输入地图样式ID,从UI处获取.."/> | ||||
|         </div> | ||||
|       </div> | ||||
|       <div class="layout-config__item layout-config__item--input"> | ||||
|         <label>3D地图</label> | ||||
|         <div class="layout-config__item--right"> | ||||
|           <ai-select v-model="config.is3d" :selectList="dict.getDict('yesOrNo')"/> | ||||
|         </div> | ||||
|       </div> | ||||
|       <div class="layout-config__item layout-config__item--input" v-if="config.is3d==1"> | ||||
|         <label>3D环绕</label> | ||||
|         <div class="layout-config__item--right"> | ||||
|           <ai-select v-model="config.is3dAround" :selectList="dict.getDict('yesOrNo')"/> | ||||
|         </div> | ||||
|       </div> | ||||
|       <div class="layout-config__item layout-config__item--input"> | ||||
|         <label>显示图例</label> | ||||
|         <div class="layout-config__item--right"> | ||||
|           <ai-select v-model="config.showPingchangMapLegend" :selectList="dict.getDict('yesOrNo')"/> | ||||
|         </div> | ||||
|       </div> | ||||
|     </template> | ||||
|     <config-item label="数据汇总" v-if="config.type === 'summary'"> | ||||
|       <ai-select size="mini" v-model="config.display" placeholder="请选择类型" :select-list="summaryOps"/> | ||||
|     </config-item> | ||||
|   </section> | ||||
| </template> | ||||
|  | ||||
| <style scoped lang="scss"> | ||||
|  | ||||
| </style> | ||||
							
								
								
									
										111
									
								
								packages/bigscreen/designer/components/configItem.vue
									
									
									
									
									
										Normal file
									
								
							
							
						
						| @@ -0,0 +1,111 @@ | ||||
| <template> | ||||
|   <section class="configItem" :class="{topLabel}"> | ||||
|     <label :class="{bold}" v-text="label"/> | ||||
|     <div class="content fill"> | ||||
|       <slot v-if="$slots.default"/> | ||||
|       <div v-else-if="value" v-html="value"/> | ||||
|     </div> | ||||
|   </section> | ||||
| </template> | ||||
| <script> | ||||
| export default { | ||||
|   name: "configItem", | ||||
|   props: { | ||||
|     label: String, | ||||
|     value: {default: null}, | ||||
|     topLabel: Boolean, | ||||
|     bold: Boolean | ||||
|   }, | ||||
| } | ||||
| </script> | ||||
| <style scoped lang="scss"> | ||||
| .configItem { | ||||
|   display: flex; | ||||
|   align-items: center; | ||||
|   justify-content: space-between; | ||||
|   margin-bottom: 10px; | ||||
|  | ||||
|  | ||||
|   &:last-child { | ||||
|     margin-bottom: 0; | ||||
|   } | ||||
|  | ||||
|   & > label { | ||||
|     flex-shrink: 0; | ||||
|     width: 60px; | ||||
|     color: #FFFFFF; | ||||
|     font-size: 12px; | ||||
|     text-align: right; | ||||
|  | ||||
|     &.bold { | ||||
|       font-weight: bold; | ||||
|     } | ||||
|   } | ||||
|  | ||||
|   .el-select .el-tag { | ||||
|     color: #fff; | ||||
|     background: transparent; | ||||
|   } | ||||
|  | ||||
|   .el-input__icon { | ||||
|     color: #fff; | ||||
|   } | ||||
|  | ||||
|   .el-switch__label { | ||||
|     color: #fff; | ||||
|   } | ||||
|  | ||||
|   .el-select, .ai-select { | ||||
|     width: 100%; | ||||
|  | ||||
|     &:last-child { | ||||
|       margin-right: 0; | ||||
|     } | ||||
|  | ||||
|     input { | ||||
|       background: #262C33; | ||||
|       font-size: 12px; | ||||
|       color: #fff; | ||||
|       border: 1px solid #030411; | ||||
|     } | ||||
|  | ||||
|     .el-input__icon { | ||||
|       color: #fff; | ||||
|     } | ||||
|   } | ||||
|  | ||||
|   :deep(.el-collapse) { | ||||
|     height: 18px; | ||||
|   } | ||||
|  | ||||
|   :deep(.content) { | ||||
|     display: flex; | ||||
|     align-items: center; | ||||
|     justify-content: flex-end; | ||||
|     text-align: right; | ||||
|     margin-left: 27px; | ||||
|  | ||||
|     input, textarea { | ||||
|       background: #262C33; | ||||
|       font-size: 12px; | ||||
|       color: #fff; | ||||
|       border: 1px solid #030411; | ||||
|     } | ||||
|   } | ||||
|  | ||||
|   &.topLabel { | ||||
|     flex-direction: column; | ||||
|     align-items: normal; | ||||
|  | ||||
|     & > label { | ||||
|       margin-bottom: 8px; | ||||
|     } | ||||
|  | ||||
|     .content { | ||||
|       flex-shrink: 0; | ||||
|       width: 100%; | ||||
|       margin-left: 0; | ||||
|     } | ||||
|   } | ||||
| } | ||||
| </style> | ||||
							
								
								
									
										119
									
								
								packages/bigscreen/designer/components/datasourcePicker.vue
									
									
									
									
									
										Normal file
									
								
							
							
						
						| @@ -0,0 +1,119 @@ | ||||
| <template> | ||||
|   <section class="datasourcePicker"> | ||||
|     <config-item label="数据类型"> | ||||
|       <ai-select v-model="source.dataType" placeholder="请选择数据类型" :select-list="dataTypes"/> | ||||
|     </config-item> | ||||
|     <div class="codeEditor" v-if="['htmlData'].includes(source.dataType)"> | ||||
|       <ai-dialog-btn :modal="false" dialog-title="编辑器" :customFooter="false" | ||||
|                      @confirm="changeData(JSON.parse(content))" @open="content=contentstr"> | ||||
|         <code-editor slot="btn" readonly :value="contentstr" :lang="dataLang" theme="github" width="100%" height="250"/> | ||||
|         <code-editor v-model="content" :lang="dataLang" theme="github" width="100%" height="440" wrap/> | ||||
|       </ai-dialog-btn> | ||||
|     </div> | ||||
|     <template v-else-if="source.dataType === 'staticData'"> | ||||
|       <config-item label="设置数据" topLabel> | ||||
|         <json-editor v-model="options.staticData" mainMenuBar/> | ||||
|       </config-item> | ||||
|     </template> | ||||
|     <config-item v-else-if="source.dataType === 'dynamicData'" label="数据源"> | ||||
|       <ai-select v-model="source.sourceDataId" placeholder="请选择数据源" :instance="instance" | ||||
|                  :prop="{label:'description'}" @change="changeData" | ||||
|                  action="/app/appdiylargescreen/allDatasourceByPage"/> | ||||
|     </config-item> | ||||
|     <config-item label="接口地址" v-else-if="source.dataType === 'apiData'"> | ||||
|       <el-input size="small" v-model="source.api" @change="changeData" placeholder="请输入数据接口URL"/> | ||||
|     </config-item> | ||||
|   </section> | ||||
| </template> | ||||
| <script> | ||||
| import AiDialogBtn from "dui/packages/layout/AiDialogBtn.vue"; | ||||
| import ConfigItem from "./configItem.vue"; | ||||
| import CodeEditor from 'bin-ace-editor' | ||||
| import 'brace/mode/json' | ||||
| import 'brace/snippets/json'; | ||||
| import 'brace/theme/github'; | ||||
| import 'brace/theme/monokai'; | ||||
| import JsonEditor from "./jsonEditor.vue"; | ||||
| import {DvCompData} from "dui/dv"; | ||||
|  | ||||
| export default { | ||||
|   name: "datasourcePicker", | ||||
|   components: {JsonEditor, ConfigItem, AiDialogBtn, CodeEditor}, | ||||
|   model: { | ||||
|     event: "input", | ||||
|     prop: "options" | ||||
|   }, | ||||
|   props: { | ||||
|     options: Object, | ||||
|     instance: Function | ||||
|   }, | ||||
|   data() { | ||||
|     return { | ||||
|       dataTypes: Object.entries(DvCompData.types).map(e => ({id: e[0], label: e[1]})), | ||||
|       content: "", | ||||
|       loading: false, | ||||
|     } | ||||
|   }, | ||||
|   computed: { | ||||
|     contentstr: v => JSON.stringify(v.options.staticData), | ||||
|     dataLang: v => v.options.dataType == 'htmlData' ? 'html' : 'json', | ||||
|     source: { | ||||
|       set(v) { | ||||
|         this.$emit("input", v) | ||||
|       }, | ||||
|       get() { | ||||
|         return this.options | ||||
|       } | ||||
|     }, | ||||
|     staticDataOps() { | ||||
|       const columnProp = "name", ops = {colConfigs: [], tableData: []} | ||||
|       if (Array.isArray(this.options.staticData)) { | ||||
|         const columns = [] | ||||
|         ops.colConfigs = [] | ||||
|         this.options.staticData.map((row, i) => { | ||||
|           const prop = `c${i || ""}` | ||||
|           ops.colConfigs.push({label: row[columnProp] || row.key, prop}) | ||||
|           Object.entries(row).map(([k, v]) => { | ||||
|             if (/^v/.test(k) && k != "value") { | ||||
|               const item = ops.tableData[k.substring(1) || 0] || {} | ||||
|               item[prop] = v | ||||
|               ops.tableData[k.substring(1) || 0] = item | ||||
|             } else if (![columnProp, 'key'].includes(k)) { | ||||
|               const index = columns.findIndex(e => k == e) | ||||
|               if (index > -1) { | ||||
|                 const item = ops.tableData[index] || {} | ||||
|                 item[prop] = v | ||||
|                 ops.tableData[index] = item | ||||
|               } else { | ||||
|                 columns.push(k) | ||||
|                 const newIndex = columns.length - 1 | ||||
|                 const item = ops.tableData[newIndex] || {} | ||||
|                 item[prop] = v | ||||
|                 ops.tableData[newIndex] = item | ||||
|               } | ||||
|             } | ||||
|           }) | ||||
|         }) | ||||
|         ops.tableData = ops.tableData.map(e => ({...e, $cellEdit: false})) | ||||
|       } | ||||
|       return ops | ||||
|     } | ||||
|   }, | ||||
|   methods: { | ||||
|     changeData(sdata) { | ||||
|       this.source.dataType == 'staticData' ? this.source.staticData = sdata : | ||||
|           new DvCompData(this.source, this.instance).getData().then(data => { | ||||
|             this.source[this.source.dataType] = data | ||||
|           }) | ||||
|     } | ||||
|   } | ||||
| } | ||||
| </script> | ||||
| <style scoped lang="scss"> | ||||
| .datasourcePicker { | ||||
|   .codeEditor { | ||||
|     position: relative; | ||||
|     padding-left: 10px; | ||||
|   } | ||||
| } | ||||
| </style> | ||||
| @@ -1,463 +0,0 @@ | ||||
| <template> | ||||
|   <div class="layout-config__group--wrapper"> | ||||
|     <ai-dialog | ||||
|       append-to-body | ||||
|       :visible.sync="isShowEditor" | ||||
|       width="1000px" | ||||
|       class="layout-config__edit" | ||||
|       title="编辑器" | ||||
|       @onConfirm="onConfirm"> | ||||
|       <div> | ||||
|         <code-editor v-model="json" :lint="true"  auto-format height="440px"></code-editor> | ||||
|       </div> | ||||
|     </ai-dialog> | ||||
|     <div class="layout-config__group" v-if="options.monitorType !== 'hik' && options.monitorType !== 'dahua'"> | ||||
|       <h2>基础设置</h2> | ||||
|       <div class="layout-config__item"> | ||||
|         <label>数据类型</label> | ||||
|         <div class="layout-config__item--right"> | ||||
|           <el-select size="mini" v-model="options.dataType" placeholder="请选择数据类型"> | ||||
|             <el-option | ||||
|               v-for="item in dataTypes" | ||||
|               :key="item.value" | ||||
|               :label="item.label" | ||||
|               :value="item.value"> | ||||
|             </el-option> | ||||
|           </el-select> | ||||
|         </div> | ||||
|       </div> | ||||
|       <div class="layout-config__code" v-if="options.dataType === 'staticData'"> | ||||
|         <el-button @click="showEditor" class="layout-config__code--btn" title="编辑" type="text" icon="iconfont iconjdq_led_edit"></el-button> | ||||
|         <vue-json-editor | ||||
|           :value="options.staticData" | ||||
|           :show-btns="false" | ||||
|           mode="view" | ||||
|           lang="zh"> | ||||
|         </vue-json-editor> | ||||
|       </div> | ||||
|       <template v-else-if="options.dataType === 'dynamicData'"> | ||||
|         <div class="layout-config__item"> | ||||
|           <label>数据源</label> | ||||
|           <div class="layout-config__item--right"> | ||||
|             <el-select size="mini" v-model="options.sourceDataId" placeholder="请选择数据源" @change="onDataChange"> | ||||
|               <el-option | ||||
|                 v-for="item in sourceData" | ||||
|                 :key="item.id" | ||||
|                 :label="item.description" | ||||
|                 :value="item.id"> | ||||
|               </el-option> | ||||
|             </el-select> | ||||
|           </div> | ||||
|         </div> | ||||
|       </template> | ||||
|       <template v-else> | ||||
|         <div class="layout-config__item"> | ||||
|           <label>接口地址</label> | ||||
|           <div class="layout-config__item--right"> | ||||
|             <el-input size="mini" v-model="options.api" @blur="onApiChange"></el-input> | ||||
|           </div> | ||||
|         </div> | ||||
|       </template> | ||||
|     </div> | ||||
|     <div class="layout-config__group" v-if="options.monitorType === 'hik' || options.monitorType === 'dahua'"> | ||||
|       <h2>基础设置</h2> | ||||
|       <div class="layout-config__item"> | ||||
|         <label>视频地址</label> | ||||
|         <div class="layout-config__item--right"> | ||||
|           <el-input size="mini" v-model="options.src"></el-input> | ||||
|         </div> | ||||
|       </div> | ||||
|     </div> | ||||
|     <div class="layout-config__group" v-if="options.dataType !== 'staticData' && options.type === 'monitor' && (options.monitorType === 'cmcc' || options.monitorType === 'slw')"> | ||||
|       <h2>字段设置</h2> | ||||
|       <div class="layout-config__item"> | ||||
|         <label>监控视频</label> | ||||
|         <div class="layout-config__item--right"> | ||||
|           <el-select size="mini" v-model="options.moniterId" placeholder="请选择监控视频" @change="onMoniterId"> | ||||
|             <el-option | ||||
|               v-for="(item, index) in monitorList" | ||||
|               :key="index" | ||||
|               :label="item.name" | ||||
|               :value="item.id"> | ||||
|             </el-option> | ||||
|           </el-select> | ||||
|         </div> | ||||
|       </div> | ||||
|     </div> | ||||
|     <div class="layout-config__group" v-if="options.dataType !== 'staticData' && options.type !== 'monitor' && keys.length && options.type !== 'table'"> | ||||
|       <h2>字段设置</h2> | ||||
|       <div class="layout-config__item"> | ||||
|         <label>X轴设置</label> | ||||
|         <div class="layout-config__item--right"> | ||||
|           <el-select size="mini" v-model="options.dataX" placeholder="请选择X轴" @change="onChooseChange"> | ||||
|             <el-option | ||||
|               v-for="(item, index) in keys" | ||||
|               :key="index" | ||||
|               :label="item" | ||||
|               :value="item"> | ||||
|             </el-option> | ||||
|           </el-select> | ||||
|         </div> | ||||
|       </div> | ||||
|       <div class="layout-config__item"> | ||||
|         <label>Y轴设置</label> | ||||
|         <div class="layout-config__item--right"> | ||||
|           <el-select size="mini" multiple :multiple-limit="options.type.indexOf('pie') > -1 ? 1 : 100" v-model="options.dataY" collapse-tags placeholder="请选择Y轴" @change="onChooseChange"> | ||||
|             <el-option | ||||
|               v-for="(item, index) in keys" | ||||
|               :key="index" | ||||
|               :label="item" | ||||
|               :value="item"> | ||||
|             </el-option> | ||||
|           </el-select> | ||||
|         </div> | ||||
|       </div> | ||||
|     </div> | ||||
|   </div> | ||||
| </template> | ||||
|  | ||||
| <script> | ||||
|   import vueJsonEditor from 'vue-json-editor' | ||||
|   import { CodeEditor } from 'bin-code-editor' | ||||
|   import 'bin-code-editor/lib/styles/index.css' | ||||
|  | ||||
|   export default { | ||||
|     name: 'dataCofing', | ||||
|  | ||||
|     props: { | ||||
|       options: Object, | ||||
|       instance: Function, | ||||
|       dict: Object, | ||||
|       params: Object, | ||||
|       urlPrefix: String | ||||
|     }, | ||||
|  | ||||
|     data () { | ||||
|       return { | ||||
|         dataTypes: [ | ||||
|           { | ||||
|             value: 'staticData', | ||||
|             label: '静态数据' | ||||
|           }, | ||||
|           { | ||||
|             value: 'dynamicData', | ||||
|             label: '动态数据' | ||||
|           }, | ||||
|           { | ||||
|             value: 'apiData', | ||||
|             label: '接口' | ||||
|           } | ||||
|         ], | ||||
|         isShowEditor: false, | ||||
|         json: {}, | ||||
|         sourceDataId: '', | ||||
|         sourceData: [], | ||||
|         keys: [], | ||||
|         monitorList: [], | ||||
|         list: [], | ||||
|         jsonData: `{"title":"测试json数据","children":[{"name":"子项名称", "desc":"子项说明" },{"name":"子项名称1", "desc":"子项说明1" }]}` | ||||
|       } | ||||
|     }, | ||||
|  | ||||
|     components: { | ||||
|       vueJsonEditor, | ||||
|       CodeEditor | ||||
|     }, | ||||
|  | ||||
|     mounted () { | ||||
|       this.getDataList() | ||||
|  | ||||
|       if ((this.options.dataY && this.options.dataY.length && this.options.dataX) || this.options.type === 'monitor') { | ||||
|         const api = this.options.dataType === 'apiData' ? this.options.api : `${this.urlPrefix}/appdiylargescreen/statisticsByLsid?id=${this.options.sourceDataId}` | ||||
|         this.instance.post(api).then(res => { | ||||
|           if (res.code == 0) { | ||||
|             if (res.data.length && this.options.type !== 'monitor') { | ||||
|               this.list = res.data | ||||
|               this.keys = Object.keys(res.data[0]) | ||||
|  | ||||
|               this.$nextTick(() => { | ||||
|                 this.onChooseChange() | ||||
|               }) | ||||
|             } else if (this.options.type === 'monitor') { | ||||
|               this.monitorList = res.data | ||||
|  | ||||
|               if (this.options.src) { | ||||
|                 const obj = res.data.filter(v => this.options.title === v.name) | ||||
|  | ||||
|                 if (obj.length) { | ||||
|                   this.options.src = obj[0].url | ||||
|                 } | ||||
|               } | ||||
|             } | ||||
|           } | ||||
|         }) | ||||
|       } | ||||
|     }, | ||||
|  | ||||
|     methods: { | ||||
|       showEditor () { | ||||
|         this.json = JSON.stringify(this.options.staticData) | ||||
|         this.isShowEditor = true | ||||
|       }, | ||||
|  | ||||
|       onMoniterId (e) { | ||||
|         this.instance.post(`${this.urlPrefix}/appzyvideoequipment/getWebSdkUrl?deviceId=${e}`).then(res => { | ||||
|           if (res.code == 0) { | ||||
|             this.options.src = JSON.parse(res.data).url | ||||
|           } | ||||
|         }) | ||||
|       }, | ||||
|  | ||||
|       getDataList () { | ||||
|         this.instance.post(`${this.urlPrefix}/appdiylargescreen/allDatasourceByPage`, null, { | ||||
|           params: { | ||||
|             current: 1, | ||||
|             size: 10000 | ||||
|           } | ||||
|         }).then(res => { | ||||
|           if (res.code == 0) { | ||||
|             this.sourceData = res.data.records | ||||
|           } | ||||
|         }) | ||||
|       }, | ||||
|  | ||||
|       onApiChange () { | ||||
|         this.options.dataX = '' | ||||
|         this.options.dataY = [] | ||||
|         this.instance.post(this.options.api).then(res => { | ||||
|           if (res.code == 0) { | ||||
|             if (res.data.length) { | ||||
|               if (this.options.type === 'table') { | ||||
|                 const keys = Object.keys(res.data[0]) | ||||
|                 const list = res.data | ||||
|                 this.options.apiData = keys.map(v => { | ||||
|                   let obj = {} | ||||
|                   list.forEach((item, index) => { | ||||
|                     obj[`v${index}`] = item[v] | ||||
|                   }) | ||||
|  | ||||
|                   return { | ||||
|                     row: v, | ||||
|                     ...obj | ||||
|                   } | ||||
|                 }) | ||||
|               } else if (this.options.type === 'summary') { | ||||
|                 if (this.options.display === 'summary9') { | ||||
|                   this.options.apiData = res.data | ||||
|                 } else { | ||||
|                   this.options.apiData = Object.keys(res.data[0]).map(item => { | ||||
|                     return { | ||||
|                       key: item, | ||||
|                       value: res.data[0][item] | ||||
|                     } | ||||
|                   }) | ||||
|                 } | ||||
|               } else if (this.options.type === 'monitor') { | ||||
|                 this.monitorList = res.data | ||||
|               } else { | ||||
|                 this.list = res.data | ||||
|                 this.keys = Object.keys(res.data[0]) | ||||
|               } | ||||
|             } | ||||
|           } else { | ||||
|             this.options.dynamicData = [] | ||||
|           } | ||||
|         }) | ||||
|       }, | ||||
|  | ||||
|       onChooseChange () { | ||||
|         let arr = [] | ||||
|         if (this.options.dataX && this.options.dataY.length) { | ||||
|           this.list.forEach(item => { | ||||
|             let obj = {} | ||||
|             this.options.dataY.forEach(v => { | ||||
|               obj[v] = item[v] | ||||
|             }) | ||||
|             arr.push({ | ||||
|               [this.options.dataX]: item[this.options.dataX], | ||||
|               ...obj | ||||
|             }) | ||||
|           }) | ||||
|  | ||||
|           this.options[this.options.dataType] = arr | ||||
|         } | ||||
|       }, | ||||
|  | ||||
|       onDataChange (e) { | ||||
|         this.options.dataX = '' | ||||
|         this.options.dataY = [] | ||||
|         this.instance.post(`${this.urlPrefix}/appdiylargescreen/statisticsByLsid?id=${e}`).then(res => { | ||||
|           if (res.code == 0) { | ||||
|             if (res.data.length) { | ||||
|               if (this.options.type === 'table') { | ||||
|                 const keys = Object.keys(res.data[0]) | ||||
|                 const list = res.data | ||||
|                 this.options.dynamicData = keys.map(v => { | ||||
|                   let obj = {} | ||||
|                   list.forEach((item, index) => { | ||||
|                     obj[`v${index}`] = item[v] | ||||
|                   }) | ||||
|  | ||||
|                   return { | ||||
|                     row: v, | ||||
|                     ...obj | ||||
|                   } | ||||
|                 }) | ||||
|               } else if (this.options.type === 'summary') { | ||||
|                 this.options.dynamicData = Object.keys(res.data[0]).map(item => { | ||||
|                   return { | ||||
|                     key: item, | ||||
|                     value: res.data[0][item] | ||||
|                   } | ||||
|                 }) | ||||
|               } else { | ||||
|                 this.list = res.data | ||||
|                 this.keys = Object.keys(res.data[0]) | ||||
|               } | ||||
|             } else { | ||||
|               this.options.dynamicData = [] | ||||
|             } | ||||
|           } | ||||
|         }) | ||||
|       }, | ||||
|  | ||||
|       onConfirm () { | ||||
|         this.$set(this.options, 'staticData', JSON.parse(this.json)) | ||||
|         this.isShowEditor = false | ||||
|         this.$emit('change') | ||||
|       } | ||||
|     } | ||||
|   } | ||||
| </script> | ||||
|  | ||||
| <style lang="scss"> | ||||
|    .el-dialog__body { | ||||
|       .jsoneditor-vue { | ||||
|         height: 480px; | ||||
|  | ||||
|         .jsoneditor-poweredBy { | ||||
|           display: none; | ||||
|         } | ||||
|       } | ||||
|     } | ||||
|   .layout-config__group--wrapper { | ||||
|     .layout-config__code .jsoneditor-vue { | ||||
|       .jsoneditor-menu { | ||||
|         display: none; | ||||
|       } | ||||
|  | ||||
|       .jsoneditor { | ||||
|         border: 1px solid #030411; | ||||
|         background: #0e1013; | ||||
|       } | ||||
|  | ||||
|       .jsoneditor-field { | ||||
|         color: gray; | ||||
|       } | ||||
|  | ||||
|       .jsoneditor-tree button:focus { | ||||
|         background-color: transparent; | ||||
|         outline: none; | ||||
|       } | ||||
|     } | ||||
|  | ||||
|     .layout-config__group { | ||||
|       padding: 10px 10px 20px; | ||||
|       border-bottom: 1px solid #000000; | ||||
|  | ||||
|       &:last-child { | ||||
|         border: none; | ||||
|       } | ||||
|  | ||||
|       .layout-config__code { | ||||
|         position: relative; | ||||
|         padding-left: 10px; | ||||
|  | ||||
|         .layout-config__code--btn { | ||||
|           position: absolute; | ||||
|           right: 0; | ||||
|           top: 0; | ||||
|           color: gray; | ||||
|           z-index: 1; | ||||
|  | ||||
|           &:hover { | ||||
|             opacity: 0.8  ; | ||||
|           } | ||||
|         } | ||||
|       } | ||||
|  | ||||
|       & > h2 { | ||||
|         margin-bottom: 20px; | ||||
|         color: #FFFFFF; | ||||
|         font-size: 15px; | ||||
|         font-weight: 700; | ||||
|       } | ||||
|     } | ||||
|  | ||||
|     .layout-config__item { | ||||
|       display: flex; | ||||
|       align-items: center; | ||||
|       justify-content: space-between; | ||||
|       margin-bottom: 10px; | ||||
|  | ||||
|       &:last-child { | ||||
|         margin-bottom: 0; | ||||
|       } | ||||
|  | ||||
|       label { | ||||
|         flex-shrink: 0; | ||||
|         width: 60px; | ||||
|         color: #FFFFFF; | ||||
|         font-size: 12px; | ||||
|         text-align: right; | ||||
|       } | ||||
|  | ||||
|       .layout-config__item--right { | ||||
|         display: flex; | ||||
|         align-items: center; | ||||
|         justify-content: flex-end; | ||||
|         width: 200px; | ||||
|         text-align: right; | ||||
|       } | ||||
|  | ||||
|       .el-select .el-tag { | ||||
|         color: #fff; | ||||
|         background: transparent; | ||||
|       } | ||||
|  | ||||
|       input { | ||||
|         background: #262C33; | ||||
|         font-size: 12px; | ||||
|         color: #fff; | ||||
|         border: 1px solid #030411; | ||||
|       } | ||||
|  | ||||
|       .el-input__icon { | ||||
|         color: #fff; | ||||
|       } | ||||
|  | ||||
|       .el-switch__label { | ||||
|         color: #fff; | ||||
|       } | ||||
|  | ||||
|       .el-select { | ||||
|         width: 100%; | ||||
|  | ||||
|         &:last-child { | ||||
|           margin-right: 0; | ||||
|         } | ||||
|  | ||||
|         input { | ||||
|           background: #262C33; | ||||
|           font-size: 12px; | ||||
|           color: #fff; | ||||
|           border: 1px solid #030411; | ||||
|         } | ||||
|  | ||||
|         .el-input__icon { | ||||
|           color: #fff; | ||||
|         } | ||||
|       } | ||||
|     } | ||||
|   } | ||||
| </style> | ||||
							
								
								
									
										32
									
								
								packages/bigscreen/designer/components/groupItem.vue
									
									
									
									
									
										Normal file
									
								
							
							
						
						| @@ -0,0 +1,32 @@ | ||||
| <script> | ||||
| export default { | ||||
|   name: "groupItem", | ||||
|   props: ['label'] | ||||
| } | ||||
| </script> | ||||
|  | ||||
| <template> | ||||
|   <section class="groupItem"> | ||||
|     <h2 v-if="label" v-text="label"/> | ||||
|     <slot/> | ||||
|   </section> | ||||
| </template> | ||||
|  | ||||
| <style scoped lang="scss"> | ||||
| .groupItem { | ||||
|   padding: 10px 10px 20px; | ||||
|   border-bottom: 1px solid #000000; | ||||
|  | ||||
|   &:last-child { | ||||
|     border: none; | ||||
|   } | ||||
|  | ||||
|  | ||||
|   & > h2 { | ||||
|     margin-bottom: 20px; | ||||
|     color: #FFFFFF; | ||||
|     font-size: 15px; | ||||
|     font-weight: 700; | ||||
|   } | ||||
| } | ||||
| </style> | ||||
							
								
								
									
										98
									
								
								packages/bigscreen/designer/components/jsonEditor.vue
									
									
									
									
									
										Normal file
									
								
							
							
						
						| @@ -0,0 +1,98 @@ | ||||
| <script> | ||||
| export default { | ||||
|   name: "jsonEditor", | ||||
|   model: { | ||||
|     event: "input", | ||||
|     prop: "value" | ||||
|   }, | ||||
|   props: { | ||||
|     value: {default: () => ({})} | ||||
|   }, | ||||
|   data() { | ||||
|     return { | ||||
|       editor: null, | ||||
|       fullscreen: false | ||||
|     } | ||||
|   }, | ||||
|   watch: { | ||||
|     value(v) { | ||||
|       const content = this.editor.get() | ||||
|       if (v && content && JSON.stringify(v) != JSON.stringify(content)) { | ||||
|         this.editor?.set(v) | ||||
|       } | ||||
|     } | ||||
|   }, | ||||
|   methods: { | ||||
|     init() { | ||||
|       const {JSONEditor} = window | ||||
|       if (!this.editor && JSONEditor) { | ||||
|         const {mode, search, mainMenuBar, navigationBar} = this.$attrs | ||||
|         this.editor = new JSONEditor(this.$el, { | ||||
|           modes: ['code', 'form', 'tree'], | ||||
|           language: 'zh-CN', mode, search, mainMenuBar, navigationBar, statusBar: true, | ||||
|           onChange: () => { | ||||
|             this.$emit("input", this.editor.get()) | ||||
|           }, | ||||
|         }, this.value) | ||||
|       } else setTimeout(() => this.init(), 500) | ||||
|       const fullscreenBtn = this.$el.querySelector(".fullscreenBtn") | ||||
|       if (!fullscreenBtn) { | ||||
|         const btn = document.createElement("div") | ||||
|         btn.className = "fullscreenBtn el-icon-full-screen" | ||||
|         btn.onclick = evt => { | ||||
|           evt.stopPropagation() | ||||
|           this.fullscreen = !this.fullscreen | ||||
|         } | ||||
|         this.$el.appendChild(btn) | ||||
|       } | ||||
|     } | ||||
|   }, | ||||
|   mounted() { | ||||
|     this.init() | ||||
|   }, | ||||
|   beforeDestroy() { | ||||
|     this.editor?.destroy() | ||||
|   } | ||||
| } | ||||
| </script> | ||||
|  | ||||
| <template> | ||||
|   <section class="jsoneditor" @contextmenu.stop :class="{fullscreen}"/> | ||||
| </template> | ||||
|  | ||||
| <style scoped lang="scss"> | ||||
| .jsoneditor { | ||||
|   position: relative; | ||||
|  | ||||
|   &.fullscreen { | ||||
|     position: fixed; | ||||
|     left: 50%; | ||||
|     top: 50%; | ||||
|     transform: translate(-50%, -50%); | ||||
|     width: 80vw; | ||||
|     height: 80vh; | ||||
|     z-index: 202403221146; | ||||
|   } | ||||
|  | ||||
|   :deep(.ace-jsoneditor) { | ||||
|     font-size: 14px !important; | ||||
|   } | ||||
|  | ||||
|   :deep(.fullscreenBtn) { | ||||
|     position: absolute; | ||||
|     z-index: 202403221132; | ||||
|     right: 6px; | ||||
|     top: 0; | ||||
|     height: 35px; | ||||
|     color: white; | ||||
|     display: flex; | ||||
|     align-items: center; | ||||
|     justify-content: center; | ||||
|     cursor: pointer; | ||||
|  | ||||
|     &:hover { | ||||
|       color: rgba(white, .6); | ||||
|     } | ||||
|   } | ||||
| } | ||||
| </style> | ||||
| @@ -1,22 +1,16 @@ | ||||
| <template> | ||||
|   <section class="preview"> | ||||
|     <ai-dv-wrapper :views="[{label: '返回'}]" :theme="config.theme" @change="$router.back()" v-if="screenId" :title="info.name"> | ||||
|       <ai-dv-background | ||||
|           :theme="config.theme" | ||||
|           v-if="config.length || config.theme === '1'" | ||||
|           :src="config.theme === '1' ? 'https://cdn.cunwuyun.cn/dvcp/dv/img/dj-bg.png' : config.backgroundImage[0].url"> | ||||
|       </ai-dv-background> | ||||
|       <app-gigscreen-viewer :urlPrefix="urlPrefix" :instance="instance" :dict="dict" :id="screenId"/> | ||||
|     <ai-dv-wrapper :views="[{label: '返回'}]" :theme="config.theme" @change="handleBack" v-if="screenId" :title="info.name" :background="bgImg" :titleSize="config.titleSize"> | ||||
|       <ai-dv-viewer :urlPrefix="urlPrefix" :instance="instance" :dict="dict" :id="screenId"/> | ||||
|     </ai-dv-wrapper> | ||||
|   </section> | ||||
| </template> | ||||
| 
 | ||||
| <script> | ||||
| import AppGigscreenViewer from "../../viewer/AppGigscreenViewer"; | ||||
| import {mapActions} from "vuex" | ||||
| 
 | ||||
| export default { | ||||
|   name: "preview", | ||||
|   components: {AppGigscreenViewer}, | ||||
|   props: { | ||||
|     instance: Function, | ||||
|     dict: Object, | ||||
| @@ -27,7 +21,8 @@ export default { | ||||
|     } | ||||
|   }, | ||||
|   computed: { | ||||
|     screenId: v => v.$route.query.id | ||||
|     screenId: v => v.$route.query.id, | ||||
|     bgImg: v => v.config.theme == 1 ? 'https://cdn.cunwuyun.cn/dvcp/dv/img/dj_bg.png' : (v.config.backgroundImage?.[0]?.url || "") | ||||
|   }, | ||||
|   data() { | ||||
|     return { | ||||
| @@ -36,14 +31,19 @@ export default { | ||||
|     } | ||||
|   }, | ||||
|   methods: { | ||||
|     ...mapActions(['closePage']), | ||||
|     getDvData() { | ||||
|       let {id} = this.$route.query | ||||
|       this.instance.post(`${this.urlPrefix}/appdiylargescreen/queryLargeScreenDetailById?id=${id}`).then(res => { | ||||
|       this.instance.post(`/app/appdiylargescreen/queryLargeScreenDetailById?id=${id}`).then(res => { | ||||
|         if (res?.data) { | ||||
|           this.info = res.data | ||||
|           this.config = JSON.parse(res.data.config).dashboard | ||||
|         } | ||||
|       }) | ||||
|     }, | ||||
|     handleBack() { | ||||
|       this.$router.back() | ||||
|       this.closePage() | ||||
|     } | ||||
|   }, | ||||
|   created() { | ||||
| @@ -7,23 +7,30 @@ | ||||
|         <h2>{{ dashboard.title }}</h2> | ||||
|       </div> | ||||
|       <div class="layout-header__right"> | ||||
|         <span type="text" @click="preview">预览</span> | ||||
|         <span type="text" @click="isShowImg = true">素材</span> | ||||
|         <span type="text" @click="back">退出</span> | ||||
|         <span type="text" @click="back()">退出</span> | ||||
|         <span type="text" @click="save">保存</span> | ||||
|       </div> | ||||
|     </div> | ||||
|     <div class="layout-wrapper"> | ||||
|       <div class="layout-left"> | ||||
|         <h2>全部资产</h2> | ||||
|       <div class="layout-left" :class="{hide:leftHide}"> | ||||
|         <h2 class="flex"> | ||||
|           <div class="fill">全部资产</div> | ||||
|           <el-button class="leftHideBtn" type="text" @click="leftHide=!leftHide">{{ | ||||
|               leftHide ? "展开" : "收起" | ||||
|             }} | ||||
|           </el-button> | ||||
|         </h2> | ||||
|         <div class="layout-left__wrapper"> | ||||
|           <div class="layout-left__left"> | ||||
|             <div @click="subIndex = 0, parentIndex = index" :class="parentIndex === index ? 'active' : ''" | ||||
|             <div @click="subIndex = 0, parentIndex = index" :class="{active: parentIndex === index}" | ||||
|                  v-for="(item, index) in components" :key="index"> | ||||
|               <i class="iconfont iconqiyeguanli"></i> | ||||
|               <span>{{ item.label }}</span> | ||||
|             </div> | ||||
|           </div> | ||||
|           <div class="layout-left__middle"> | ||||
|           <div class="layout-left__middle" v-if="hasCategories"> | ||||
|             <div>全部</div> | ||||
|             <div | ||||
|                 class="layout-left__middle--item" | ||||
| @@ -44,29 +51,28 @@ | ||||
|       </div> | ||||
|       <div class="layout-middle"> | ||||
|         <div class="canvas-wrapper"> | ||||
|           <vue-ruler-tool | ||||
|               v-model="dashboard.presetLine" | ||||
|               class="vueRuler" | ||||
|               :step-length="50" | ||||
|               :parent="true" | ||||
|               :position="'relative'" | ||||
|               :is-scale-revise="true" | ||||
|               :visible.sync="dashboard.presetLineVisible"> | ||||
|             <div | ||||
|                 id="workbench" | ||||
|                 class="workbench" | ||||
|                 :style="{ | ||||
|           <vue-ruler-tool v-model="dashboard.presetLine" v-if="resizeWrapper" | ||||
|                           class="vueRuler" | ||||
|                           :step-length="50" | ||||
|                           parent | ||||
|                           is-scale-revise | ||||
|                           position="relative" | ||||
|                           :visible.sync="dashboard.presetLineVisible"> | ||||
|             <div id="workbench" | ||||
|                  class="workbench" | ||||
|                  :style="{ | ||||
|                 transform: workbenchTransform, | ||||
|                 width: bigscreenWidth + 'px', | ||||
|                 height: bigscreenHeight + 'px' | ||||
|               }"> | ||||
|               <ai-dv-wrapper style="height: 100%" :title="params.name" :theme="dashboard.theme"> | ||||
|               <ai-dv-wrapper | ||||
|                   style="height: 100%" | ||||
|                   :type="dashboard.style" | ||||
|                   :title="$route.query.name" | ||||
|                   :titleSize="dashboard.titleSize" | ||||
|                   :theme="dashboard.theme" | ||||
|                   :background="dashboard.theme == 1 ? 'https://cdn.cunwuyun.cn/dvcp/dv/img/dj_bg.png' : (dashboard.backgroundImage.length ? dashboard.backgroundImage[0].url : '')"> | ||||
|                 <div style="width: 100%; height: 100%"> | ||||
|                   <AiDvBackground | ||||
|                       :theme="dashboard.theme" | ||||
|                       v-if="dashboard.backgroundImage.length || dashboard.theme === '1'" | ||||
|                       :src="dashboard.theme === '1' ? 'https://cdn.cunwuyun.cn/dvcp/dv/img/dj-bg.png' : dashboard.backgroundImage[0].url"> | ||||
|                   </AiDvBackground> | ||||
|                   <vue-draggable-resizable | ||||
|                       :w="item.width" | ||||
|                       :h="item.height" | ||||
| @@ -80,10 +86,10 @@ | ||||
|                       :class="[activeIndex === index ? 'drag-active' : '']" | ||||
|                       class="draggable" | ||||
|                       @contextmenu.native.stop="e => onContextmenu(e, index)" | ||||
|                       @dragging="(x, y) => onDrag(x, y, index)" | ||||
|                       @resizing="(x, y, w, h) => onResizing(x, y, w, h, index, item.type)" | ||||
|                       @dragstop="(x, y) => onDrag(x, y,item)" | ||||
|                       @resizestop="(x, y, w, h) => onResizing(x, y, w, h, item)" | ||||
|                       @activated="onActivated(index)" | ||||
|                       @click.native.stop="activeIndex = index" | ||||
|                       @click.native.stop | ||||
|                       v-for="(item, index) in componentList" | ||||
|                       :key="index"> | ||||
|                     <div class="coordinate" v-show="activeIndex === index"> | ||||
| @@ -91,7 +97,7 @@ | ||||
|                       <div class="coordinate-top"></div> | ||||
|                       <div class="coordinate-label">{{ item.left }}, {{ item.top }}</div> | ||||
|                     </div> | ||||
|                     <ai-dv-render :data="item" :theme="dashboard.theme" :index="index" :instance="instance" /> | ||||
|                     <ai-dv-render :data="item" :theme="dashboard.theme" :index="index" :instance="instance"/> | ||||
|                   </vue-draggable-resizable> | ||||
|                 </div> | ||||
|               </ai-dv-wrapper> | ||||
| @@ -100,181 +106,44 @@ | ||||
|         </div> | ||||
|       </div> | ||||
|       <div class="layout-right" @click.stop> | ||||
|         <div class="layout-tab" v-if="activeIndex > -1"> | ||||
|           <span @click="configIndex = 0" :class="[configIndex === 0 ? 'layout-tab__active' : '']">参数</span> | ||||
|           <span @click="configIndex = 1" :class="[configIndex === 1 ? 'layout-tab__active' : '']">数据</span> | ||||
|         </div> | ||||
|         <div class="layout-right__content" v-if="activeIndex > -1"> | ||||
|           <div class="layout-right__content--wrapper" v-show="configIndex === 0"> | ||||
|             <div class="layout-config__group"> | ||||
|               <h2>基础设置</h2> | ||||
|               <div class="layout-config__item"> | ||||
|                 <label>图表尺寸</label> | ||||
|                 <div class="layout-config__item--right"> | ||||
|                   <el-input-number size="mini" :min="0" v-model="currLayout.width" | ||||
|                                    controls-position="right"></el-input-number> | ||||
|                   <el-input-number size="mini" :min="0" v-model="currLayout.height" | ||||
|                                    controls-position="right"></el-input-number> | ||||
|                 </div> | ||||
|               </div> | ||||
|               <div class="layout-config__item"> | ||||
|                 <label>图表位置</label> | ||||
|                 <div class="layout-config__item--right"> | ||||
|                   <el-input-number size="mini" :min="0" v-model="currLayout.left" | ||||
|                                    controls-position="right"></el-input-number> | ||||
|                   <el-input-number size="mini" :min="0" v-model="currLayout.top" | ||||
|                                    controls-position="right"></el-input-number> | ||||
|                 </div> | ||||
|               </div> | ||||
|         <!-- 选中组件面板--> | ||||
|         <template v-if="activeIndex > -1"> | ||||
|           <div class="layout-tab"> | ||||
|             <span @click="configIndex = 0" :class="[configIndex === 0 ? 'layout-tab__active' : '']">参数</span> | ||||
|             <span @click="configIndex = 1" :class="[configIndex === 1 ? 'layout-tab__active' : '']">数据</span> | ||||
|           </div> | ||||
|           <div class="layout-right__content"> | ||||
|             <component-config v-show="configIndex === 0" :config="currLayout" v-bind="$props"/> | ||||
|             <div class="layout-right__content--wrapper" v-show="configIndex === 1" | ||||
|                  v-if="currLayout.type !== 'title' && currLayout.type !== 'video'"> | ||||
|               <data-config v-model="currLayout" :instance="instance" :dict="dict" @change="onChange('barChart')"/> | ||||
|             </div> | ||||
|           </div> | ||||
|           <div class="layout-right__content--wrapper" v-show="configIndex === 0"> | ||||
|             <div class="layout-config__group"> | ||||
|               <h2>组件设置</h2> | ||||
|               <div class="layout-config__item layout-config__item--input"> | ||||
|                 <label>标题</label> | ||||
|                 <div class="layout-config__item--right"> | ||||
|                   <el-input v-model="currLayout.title" size="mini"></el-input> | ||||
|                 </div> | ||||
|               </div> | ||||
|               <div class="layout-config__item layout-config__item--input" v-if="currLayout.display === 'summary2'"> | ||||
|                 <label>标题</label> | ||||
|                 <div class="layout-config__item--right"> | ||||
|                   <el-input v-model="currLayout.summaryTitle" size="mini"></el-input> | ||||
|                 </div> | ||||
|               </div> | ||||
|               <div class="layout-config__item" v-if="currLayout.type !== 'display'"> | ||||
|                 <label>边框</label> | ||||
|                 <div class="layout-config__item--right"> | ||||
|                   <el-select size="mini" v-model="currLayout.border" placeholder="请选择边框" clearable> | ||||
|                     <el-option | ||||
|                         v-for="(item, index) in borderList" | ||||
|                         :key="index" | ||||
|                         :label="item" | ||||
|                         :value="item"> | ||||
|                     </el-option> | ||||
|                   </el-select> | ||||
|                 </div> | ||||
|               </div> | ||||
|               <div class="layout-config__item layout-config__item--input" v-if="currLayout.type === 'video'"> | ||||
|                 <label>视频地址</label> | ||||
|                 <div class="layout-config__item--right"> | ||||
|                   <el-input v-model="currLayout.src" size="mini"></el-input> | ||||
|                 </div> | ||||
|               </div> | ||||
|               <div class="layout-config__item" v-if="currLayout.type === 'monitor'"> | ||||
|                 <label>视频类型</label> | ||||
|                 <div class="layout-config__item--right"> | ||||
|                   <el-select size="mini" v-model="currLayout.monitorType" placeholder="请选择" clearable> | ||||
|                     <el-option label="中国移动" value="cmcc"></el-option> | ||||
|                     <el-option label="海康威视" value="hik"></el-option> | ||||
|                     <el-option label="大华" value="dahua"></el-option> | ||||
|                     <el-option label="视联网" value="slw"></el-option> | ||||
|                   </el-select> | ||||
|                 </div> | ||||
|               </div> | ||||
|               <div class="layout-config__item" v-if="currLayout.type === 'table'"> | ||||
|                 <label>显示排名</label> | ||||
|                 <div class="layout-config__item--right"> | ||||
|                   <el-select size="mini" v-model="currLayout.isShowIndex" placeholder="请选择" clearable> | ||||
|                     <el-option | ||||
|                         v-for="(item, index) in tableStatus" | ||||
|                         :key="index" | ||||
|                         :label="item.label" | ||||
|                         :value="item.value"> | ||||
|                     </el-option> | ||||
|                   </el-select> | ||||
|                 </div> | ||||
|               </div> | ||||
|               <div class="layout-config__item" v-if="currLayout.type === 'table'"> | ||||
|                 <label>表格行数</label> | ||||
|                 <div class="layout-config__item--right"> | ||||
|                   <el-input-number size="mini" style="width: 232px" :min="0" v-model="currLayout.rowNum" controls-position="right"></el-input-number> | ||||
|                 </div> | ||||
|               </div> | ||||
|               <template v-if="currLayout.type === 'map'"> | ||||
|                 <div class="layout-config__item"> | ||||
|                   <label>遮罩层</label> | ||||
|                   <div class="layout-config__item--right"> | ||||
|                     <el-select size="mini" v-model="currLayout.mask" placeholder="请选择" clearable> | ||||
|                       <el-option label="是" value="1"></el-option> | ||||
|                       <el-option label="否" value="2"></el-option> | ||||
|                     </el-select> | ||||
|                   </div> | ||||
|                 </div> | ||||
|                 <div class="layout-config__item"> | ||||
|                   <label>选择地区</label> | ||||
|                   <div class="layout-config__item--right"> | ||||
|                     <AiAreaGet :instance="instance" :valueLevel="3" v-model="currLayout.areaId" placeholder="请选择地区"></AiAreaGet> | ||||
|                   </div> | ||||
|                 </div> | ||||
|                 <div class="layout-config__item"> | ||||
|                   <label>展示光轨</label> | ||||
|                   <div class="layout-config__item--right"> | ||||
|                     <ai-select v-model="currLayout.pulseLines" :selectList="dict.getDict('yesOrNo')"/> | ||||
|                   </div> | ||||
|                 </div> | ||||
|                 <div class="layout-config__item layout-config__item--input"> | ||||
|                   <label>地图样式</label> | ||||
|                   <div class="layout-config__item--right"> | ||||
|                     <el-input size="mini" v-model="currLayout.mapStyle" clearable placeholder="请输入地图样式ID,从UI处获取.."/> | ||||
|                   </div> | ||||
|                 </div> | ||||
|               </template> | ||||
|               <div class="layout-config__item" v-if="currLayout.type === 'summary'"> | ||||
|                 <label>数据汇总</label> | ||||
|                 <div class="layout-config__item--right"> | ||||
|                   <el-select size="mini" v-model="currLayout.display" placeholder="请选择类型" clearable> | ||||
|                     <el-option | ||||
|                         v-for="(item, index) in summaryList" | ||||
|                         :key="index" | ||||
|                         :label="item" | ||||
|                         :value="item"> | ||||
|                     </el-option> | ||||
|                   </el-select> | ||||
|                 </div> | ||||
|               </div> | ||||
|             </div> | ||||
|           </div> | ||||
|           <div class="layout-right__content--wrapper" v-show="configIndex === 1" | ||||
|                v-if="currLayout.type !== 'title' && currLayout.type !== 'video'"> | ||||
|             <data-config | ||||
|                 ref="dataConfig" | ||||
|                 :instance="instance" | ||||
|                 :dict="dict" | ||||
|                 :urlPrefix="urlPrefix" | ||||
|                 :options="currLayout" | ||||
|                 @change="onChange('barChart')"> | ||||
|             </data-config> | ||||
|           </div> | ||||
|         </div> | ||||
|         <div class="layout-page__setting layout-right__content" v-if="activeIndex === -1"> | ||||
|         </template> | ||||
|         <!--未选中组件,页面设置--> | ||||
|         <div class="layout-page__setting layout-right__content" v-else> | ||||
|           <h2>页面设置</h2> | ||||
|           <div class="layout-config__group"> | ||||
|             <div class="layout-config__item"> | ||||
|               <label>屏幕大小</label> | ||||
|               <div class="layout-config__item--right"> | ||||
|                 <el-input-number size="mini" :min="0" v-model="bigscreenWidth" disabled | ||||
|                                  controls-position="right"></el-input-number> | ||||
|                 <el-input-number size="mini" :min="0" v-model="bigscreenHeight" disabled | ||||
|                                  controls-position="right"></el-input-number> | ||||
|               </div> | ||||
|             </div> | ||||
|             <div class="layout-config__item layout-config__item--input"> | ||||
|               <label>屏幕标题</label> | ||||
|               <div class="layout-config__item--right"> | ||||
|                 <el-input v-model="dashboard.title" size="mini"></el-input> | ||||
|               </div> | ||||
|             </div> | ||||
|             <div class="layout-config__item"> | ||||
|               <label>主题设置</label> | ||||
|               <div class="layout-config__item--right"> | ||||
|                 <el-select size="mini" v-model="dashboard.theme" placeholder="请选择"> | ||||
|                   <el-option label="默认" value="0"></el-option> | ||||
|                   <el-option label="党建" value="1"></el-option> | ||||
|                 </el-select> | ||||
|               </div> | ||||
|             </div> | ||||
|             <config-item label="屏幕大小"> | ||||
|               <el-input-number size="mini" :min="0" v-model="bigscreenWidth" controls-position="right"/> | ||||
|               <el-input-number size="mini" :min="0" v-model="bigscreenHeight" controls-position="right"/> | ||||
|             </config-item> | ||||
|             <config-item label="屏幕标题"> | ||||
|               <el-input v-model="dashboard.title" size="mini"/> | ||||
|               <el-input type="number" v-model="dashboard.titleSize" size="mini" placeholder="字体大小" :max="68"/> | ||||
|             </config-item> | ||||
|             <config-item label="主题设置"> | ||||
|               <el-select size="mini" v-model="dashboard.theme" placeholder="请选择"> | ||||
|                 <el-option label="默认" value="0"></el-option> | ||||
|                 <el-option label="党建" value="1"></el-option> | ||||
|               </el-select> | ||||
|             </config-item> | ||||
|             <config-item label="样式设置"> | ||||
|               <el-select size="mini" v-model="dashboard.style" placeholder="请选择"> | ||||
|                 <el-option label="默认" value="black"/> | ||||
|                 <el-option label="经典" value="classic"/> | ||||
|               </el-select> | ||||
|             </config-item> | ||||
|             <div class="layout-config__item"> | ||||
|               <label>背景图</label> | ||||
|               <div class="layout-config__item--right layout-config__item--bg"> | ||||
| @@ -321,9 +190,9 @@ | ||||
|           :total="images.length" | ||||
|           :colConfigs="colConfigs" | ||||
|           @getList="() => {}"> | ||||
|         <el-table-column slot="img" prop="素材地址" label="素材" align="center"> | ||||
|         <el-table-column :slot="'img'" prop="素材地址" label="素材" align="center"> | ||||
|         </el-table-column> | ||||
|         <el-table-column slot="options" width="140px" fixed="right" label="操作" align="center"> | ||||
|         <el-table-column :slot="'options'" width="140px" fixed="right" label="操作" align="center"> | ||||
|           <template slot-scope="{ row, $index }"> | ||||
|             <div class="table-options"> | ||||
|               <el-button type="text" @click="removeImg($index)">删除</el-button> | ||||
| @@ -333,7 +202,8 @@ | ||||
|         </el-table-column> | ||||
|       </ai-table> | ||||
|     </ai-dialog> | ||||
|     <ai-dialog :visible.sync="isShowAddImg" width="580px" append-to-body title="添加素材" @closed="form.images = []" @onConfirm="onImageConfirm"> | ||||
|     <ai-dialog :visible.sync="isShowAddImg" width="580px" append-to-body title="添加素材" @closed="form.images = []" | ||||
|                @onConfirm="onImageConfirm"> | ||||
|       <ai-uploader | ||||
|           :instance="instance" | ||||
|           v-model="form.images" | ||||
| @@ -348,20 +218,27 @@ | ||||
| 
 | ||||
| <script> | ||||
| 
 | ||||
| import {components} from '../config' | ||||
| import {components} from './config' | ||||
| import VueRulerTool from 'vue-ruler-tool' | ||||
| import VueDraggableResizable from 'vue-draggable-resizable' | ||||
| import 'vue-draggable-resizable/dist/VueDraggableResizable.css' | ||||
| import DataConfig from './form/DataConfig.vue' | ||||
| import DataConfig from './components/DataConfig.vue' | ||||
| import ComponentConfig from "./components/componentConfig.vue"; | ||||
| import {mapActions} from "vuex" | ||||
| import Vue from "vue"; | ||||
| import ConfigItem from "./components/configItem.vue"; | ||||
| 
 | ||||
| export default { | ||||
|   name: "viewport", | ||||
|   provide() { | ||||
|     return { | ||||
|       setCurLayer: this.setCurLayer | ||||
|     } | ||||
|   }, | ||||
|   props: { | ||||
|     instance: Function, | ||||
|     dict: Object, | ||||
|     params: Object, | ||||
|     urlPrefix: String | ||||
|   }, | ||||
| 
 | ||||
|   data() { | ||||
|     return { | ||||
|       colConfigs: [ | ||||
| @@ -386,11 +263,13 @@ export default { | ||||
|       componentList: [], | ||||
|       dashboard: { | ||||
|         title: '大屏', | ||||
|         titleSize: 38, | ||||
|         width: 1920, | ||||
|         height: 1080, | ||||
|         theme: '0', | ||||
|         backgroundColor: '', | ||||
|         backgroundImage: [] | ||||
|         backgroundImage: [], | ||||
|         style: 'black' | ||||
|       }, | ||||
|       menuX: 0, | ||||
|       menuY: 0, | ||||
| @@ -400,66 +279,69 @@ export default { | ||||
|       middleHeight: 0, | ||||
|       widthScale: 0, | ||||
|       heightScale: 0, | ||||
|       bigscreenScaleInWorkbench: 0, | ||||
|       tableStatus: [{ | ||||
|         label: '是', | ||||
|         value: '1' | ||||
|       }, { | ||||
|         label: '否', | ||||
|         value: '0' | ||||
|       }], | ||||
|       images: [], | ||||
|       summaryList: ['summary0', 'summary1', 'summary2', 'summary3', 'summary4', 'summary6', 'summary5', 'summary7', 'summary8', 'summary9', 'summary10', 'summary11'], | ||||
|       borderList: ['border0', 'border1', 'border2', 'border3', 'border4', 'border5'] | ||||
|       leftHide: false, | ||||
|       resizeWrapper: true | ||||
|     } | ||||
|   }, | ||||
| 
 | ||||
|   components: { | ||||
|     ConfigItem, | ||||
|     ComponentConfig, | ||||
|     DataConfig, | ||||
|     VueRulerTool, | ||||
|     VueDraggableResizable, | ||||
|   }, | ||||
| 
 | ||||
|   computed: { | ||||
|     workbenchTransform() { | ||||
|       return `scale(${this.heightScale})` | ||||
|     }, | ||||
| 
 | ||||
|     currLayout() { | ||||
|       if (this.activeIndex === -1) return {} | ||||
|       return this.componentList[this.activeIndex] | ||||
|     }, | ||||
| 
 | ||||
|     widget() { | ||||
|       if (this.components.length && this.components[this.parentIndex].list.length) { | ||||
|         return this.components[this.parentIndex].list[this.subIndex].list | ||||
|     currLayout: { | ||||
|       set(v) { | ||||
|         this.setCurLayer(v) | ||||
|       }, | ||||
|       get() { | ||||
|         return this.activeIndex > -1 ? this.componentList[this.activeIndex] : {} | ||||
|       } | ||||
|     }, | ||||
|     widget() { | ||||
|       const categories = this.components[this.parentIndex].list | ||||
|       if (categories.length) { | ||||
|         return categories[this.subIndex]?.list || categories | ||||
|       } | ||||
| 
 | ||||
|       return [] | ||||
|     }, | ||||
|     hasCategories: v => v.components[v.parentIndex].list[v.subIndex].list?.length > 0, | ||||
|     comps: v => { | ||||
|       const obj = {} | ||||
|       const handleOps = e => { | ||||
|         e.echartOps = e.echartOps || v.$echartTpls[e.type] | ||||
|         obj[e.type] = e | ||||
|       } | ||||
|       v.components.map(e => e.list.map(c => c.list?.map(handleOps) || handleOps(c))) | ||||
|       return obj | ||||
|     } | ||||
|   }, | ||||
| 
 | ||||
|   mounted() { | ||||
|     if (this.params && this.params.id) { | ||||
|       this.getInfo(this.params.id) | ||||
|     } | ||||
|     this.dict.load("yesOrNo") | ||||
|     this.getInfo(this.$route.query.did) | ||||
|     this.$nextTick(() => { | ||||
|       this.middleWidth = document.querySelector('.layout-wrapper').offsetWidth - 670 | ||||
|       this.middleHeight = document.querySelector('.layout-wrapper').offsetHeight | ||||
|       this.initCanvas() | ||||
|     }) | ||||
|   }, | ||||
| 
 | ||||
|   methods: { | ||||
|     bindEvent() { | ||||
|       this.middleWidth = document.querySelector('.layout-wrapper').offsetWidth - 670 | ||||
|       this.middleHeight = document.querySelector('.layout-wrapper').offsetHeight | ||||
| 
 | ||||
|       this.$nextTick(() => { | ||||
|   watch: { | ||||
|     leftHide: { | ||||
|       handler(v) { | ||||
|         this.middleWidth = document.querySelector('.layout-wrapper').offsetWidth - (v ? 340 : 670) | ||||
|         this.initCanvas() | ||||
|       }) | ||||
|     }, | ||||
| 
 | ||||
|         this.resizeWrapper = false | ||||
|         this.$nextTick(() => this.resizeWrapper = true) | ||||
|       } | ||||
|     } | ||||
|   }, | ||||
|   methods: { | ||||
|     ...mapActions(['closePage']), | ||||
|     copy(link) { | ||||
|       let oInput = document.createElement('input') | ||||
|       oInput.value = link | ||||
| @@ -472,11 +354,9 @@ export default { | ||||
|       }) | ||||
|       oInput.remove() | ||||
|     }, | ||||
| 
 | ||||
|     removeImg(index) { | ||||
|       this.images.splice(index, 1) | ||||
|     }, | ||||
| 
 | ||||
|     onImageConfirm() { | ||||
|       if (!this.form.images.length) { | ||||
|         return this.$message.error('请上传图片') | ||||
| @@ -490,7 +370,7 @@ export default { | ||||
|       this.form.images = [] | ||||
|       this.isShowAddImg = false | ||||
|     }, | ||||
| 
 | ||||
|     //置顶图层 | ||||
|     setTop() { | ||||
|       const maxZindex = Math.max.apply(Math, this.componentList.map(item => { | ||||
|         return item.zIndex | ||||
| @@ -498,84 +378,87 @@ export default { | ||||
| 
 | ||||
|       this.$set(this.componentList[this.activeIndex], 'zIndex', maxZindex + 1) | ||||
|     }, | ||||
| 
 | ||||
|     //置底图层 | ||||
|     setBottom() { | ||||
|       const item = this.componentList[this.activeIndex] | ||||
|       this.componentList.splice(this.activeIndex, 1) | ||||
|       this.componentList.unshift(item) | ||||
|     }, | ||||
| 
 | ||||
|     getInfo(id) { | ||||
|       this.instance.post(`${this.urlPrefix}/appdiylargescreen/queryLargeScreenDetailById?id=${id}`).then(res => { | ||||
|         if (res.code === 0) { | ||||
|       id && this.instance.post(`/app/appdiylargescreen/queryLargeScreenDetailById?id=${id}`).then(res => { | ||||
|         if (res?.data) { | ||||
|           const data = JSON.parse(res.data.config) | ||||
|           this.componentList = data.config | ||||
|           const getComp = type => this.comps[type] || {} | ||||
|           this.componentList = data.config.filter(Boolean).map(e => ({...getComp(e.type), ...e})) | ||||
|           this.dashboard = data.dashboard | ||||
|           this.images = data.images || [] | ||||
|         } | ||||
|       }) | ||||
|     }, | ||||
| 
 | ||||
|     back() { | ||||
|       this.$emit('close') | ||||
|       const {id} = this.$route.query | ||||
|       this.$router.push({hash: "#add", query: {id}}) | ||||
|       this.closePage() | ||||
|     }, | ||||
| 
 | ||||
|     save() { | ||||
|       this.instance.post(`${this.urlPrefix}/appdiylargescreen/addOrUpdateLargeScreen`, { | ||||
|       const {did: id, id: pid} = this.$route.query, {dashboard} = this | ||||
|       this.instance.post(`/app/appdiylargescreen/addOrUpdateLargeScreen`, { | ||||
|         id, pid, | ||||
|         config: JSON.stringify({ | ||||
|           config: this.componentList, | ||||
|           dashboard: this.dashboard, | ||||
|           dashboard, | ||||
|           images: this.images | ||||
|         }), | ||||
|         status: 1, | ||||
|         title: this.dashboard.title, | ||||
|         id: this.params.id || '' | ||||
|         title: dashboard.title, | ||||
|       }).then(res => { | ||||
|         if (res.code == 0) { | ||||
|         if (res?.code == 0) { | ||||
|           this.$message.success('保存成功') | ||||
|           this.$emit('change', res.data) | ||||
|           this.back() | ||||
|           this.getInfo(this.$route.query.did) | ||||
|         } | ||||
|       }) | ||||
|     }, | ||||
| 
 | ||||
|     //从资产中新建时使用 | ||||
|     clone(e) { | ||||
|       if (/Chart/.test(e.type)) { | ||||
|         e.echartOps = this.$echartTpls[e.config] | ||||
|       } | ||||
|       this.componentList.push(this.deepClone(e)) | ||||
|     }, | ||||
| 
 | ||||
|     onChange(e) { | ||||
|       if (e.indexOf('Chart') > -1) { | ||||
|         this.$refs[`chart${this.activeIndex}`][0].refresh() | ||||
|       } | ||||
|     onChange() { | ||||
|       this.$refs[`chart${this.activeIndex}`]?.[0]?.refresh() | ||||
|     }, | ||||
| 
 | ||||
|     deepClone(data, hash = new WeakMap()) { | ||||
|       if (typeof data !== 'object' || data === null) { | ||||
|         throw new TypeError('传入参数不是对象') | ||||
|       } | ||||
|       if (hash.has(data)) { | ||||
|         return hash.get(data) | ||||
|       } | ||||
|       let newData = {} | ||||
|       const dataKeys = Object.keys(data) | ||||
|       dataKeys.forEach(value => { | ||||
|         const currentDataValue = data[value] | ||||
|         if (typeof currentDataValue !== "object" || currentDataValue === null) { | ||||
|           newData[value] = currentDataValue | ||||
|         } else if (Array.isArray(currentDataValue)) { | ||||
|           newData[value] = [...currentDataValue] | ||||
|         } else if (currentDataValue instanceof Set) { | ||||
|           newData[value] = new Set([...currentDataValue]) | ||||
|         } else if (currentDataValue instanceof Map) { | ||||
|           newData[value] = new Map([...currentDataValue]) | ||||
|     deepClone(obj) { | ||||
|       if (obj instanceof Object) { | ||||
|         let newObj = {} | ||||
|         if (Array.isArray(obj)) { | ||||
|           return this.$copy(obj) | ||||
|         } else if (typeof obj == 'function') { | ||||
|           newObj = obj.bind(newObj) | ||||
|         } else { | ||||
|           hash.set(data, data) | ||||
|           newData[value] = this.deepClone(currentDataValue, hash) | ||||
|           for (let key in obj) { | ||||
|             let value = obj[key] | ||||
|             if (typeof value == 'function') { | ||||
|               newObj[key] = value.bind(newObj) | ||||
|             } else if (typeof value == 'object') { | ||||
|               if (Array.isArray(value)) { | ||||
|                 newObj[key] = [] | ||||
|                 value.forEach(item => { | ||||
|                   newObj[key].push(this.deepClone(item)) | ||||
|                 }) | ||||
|               } else { | ||||
|                 newObj[key] = this.deepClone(value) | ||||
|               } | ||||
|             } else { | ||||
|               newObj[key] = value | ||||
|             } | ||||
|           } | ||||
|         } | ||||
|       }) | ||||
|       return newData | ||||
|         return newObj | ||||
|       } else { | ||||
|         return obj | ||||
|       } | ||||
|     }, | ||||
| 
 | ||||
|     onContextmenu(e, index) { | ||||
|       this.menuX = e.clientX + 10 | ||||
|       this.menuY = e.clientY + 10 | ||||
| @@ -584,43 +467,48 @@ export default { | ||||
| 
 | ||||
|       e.preventDefault() | ||||
|     }, | ||||
| 
 | ||||
|     //复制图层功能 | ||||
|     copyLayer() { | ||||
|       const layer = this.deepClone(this.componentList[this.activeIndex]) | ||||
|       this.componentList.push(layer) | ||||
|     }, | ||||
| 
 | ||||
|     //删除图层功能 | ||||
|     removeLayer() { | ||||
|       this.componentList.splice(this.activeIndex, 1) | ||||
|       this.activeIndex = -1 | ||||
|     }, | ||||
| 
 | ||||
|     onActivated(index) { | ||||
|       this.activeIndex = index | ||||
|     }, | ||||
| 
 | ||||
| 
 | ||||
|     onDrag(x, y, index) { | ||||
|       this.$set(this.componentList[index], 'left', x) | ||||
|       this.$set(this.componentList[index], 'top', y) | ||||
|     onDrag(x, y, item) { | ||||
|       item.left = x | ||||
|       item.top = y | ||||
|     }, | ||||
| 
 | ||||
|     onResizing(x, y, w, h, index, type) { | ||||
|       this.$set(this.componentList[index], 'left', x) | ||||
|       this.$set(this.componentList[index], 'top', y) | ||||
|       this.$set(this.componentList[index], 'width', w) | ||||
|       this.$set(this.componentList[index], 'height', h) | ||||
| 
 | ||||
|       if (type.indexOf('Chart') > -1) { | ||||
|         // this.$refs[`chart${index}`][0].watchResize() | ||||
|       } | ||||
|     onResizing(x, y, w, h, item) { | ||||
|       item.left = x | ||||
|       item.top = y | ||||
|       item.width = w | ||||
|       item.height = h | ||||
|     }, | ||||
| 
 | ||||
|     initCanvas() { | ||||
|       var widthScale = (this.middleWidth - this.widthPaddingTools) / this.bigscreenWidth | ||||
|       var heightScale = (this.middleHeight - this.widthPaddingTools) / this.bigscreenHeight | ||||
|       let widthScale = (this.middleWidth - this.widthPaddingTools) / this.bigscreenWidth | ||||
|       let heightScale = (this.middleHeight - this.widthPaddingTools) / this.bigscreenHeight | ||||
|       this.heightScale = Math.min(widthScale, heightScale) | ||||
|     }, | ||||
|     preview() { | ||||
|       const {origin, pathname} = location | ||||
|       window.open(origin + pathname + '?id=' + this.$route.query.did + "#preview") | ||||
|     }, | ||||
|     setCurLayer(v) { | ||||
|       this.componentList.splice(this.activeIndex, 1, v) | ||||
|     } | ||||
|   }, | ||||
|   created() { | ||||
|     Vue.use(window.AVUE, { | ||||
|       size: 'mini', | ||||
|       tableSize: 'mini', | ||||
|       calcHeight: 36, | ||||
|     }) | ||||
|   } | ||||
| } | ||||
| </script> | ||||
| @@ -636,7 +524,7 @@ export default { | ||||
|   color: #fff; | ||||
|   background: #1d1e1f; | ||||
| 
 | ||||
|   ::v-deep .dv-scroll-board { | ||||
|   :deep( .dv-scroll-board ) { | ||||
|     height: calc(100%) !important; | ||||
| 
 | ||||
|     .header-item { | ||||
| @@ -720,17 +608,17 @@ export default { | ||||
|         opacity: 0.8; | ||||
|       } | ||||
| 
 | ||||
|       ::v-deep .el-upload-list--picture-card, ::v-deep.el-upload-list__item-thumbnail, ::v-deep .uploader { | ||||
|       :deep( .el-upload-list--picture-card), :deep(.el-upload-list__item-thumbnail), :deep( .uploader ) { | ||||
|         width: 232px; | ||||
|         height: 120px; | ||||
|       } | ||||
| 
 | ||||
|       ::v-deep .el-upload-list--picture-card .el-upload-list__item { | ||||
|       :deep( .el-upload-list--picture-card .el-upload-list__item ) { | ||||
|         width: 232px; | ||||
|         height: 120px; | ||||
|       } | ||||
| 
 | ||||
|       ::v-deep .el-upload--picture-card { | ||||
|       :deep( .el-upload--picture-card ) { | ||||
|         background-color: transparent; | ||||
|       } | ||||
| 
 | ||||
| @@ -757,7 +645,7 @@ export default { | ||||
|     } | ||||
|   } | ||||
| 
 | ||||
|   ::v-deep #dv-full-screen-container { | ||||
|   :deep( #dv-full-screen-container ) { | ||||
|     width: 100% !important; | ||||
|     height: 100% !important; | ||||
|   } | ||||
| @@ -880,6 +768,22 @@ export default { | ||||
|     flex-shrink: 0; | ||||
|     background: #1D2127; | ||||
| 
 | ||||
|     &.hide { | ||||
|       width: 0; | ||||
|       position: relative; | ||||
| 
 | ||||
|       h2 > .fill { | ||||
|         display: none; | ||||
|       } | ||||
| 
 | ||||
|       .leftHideBtn { | ||||
|         position: absolute; | ||||
|         left: 0; | ||||
|         top: 0; | ||||
|         transform: translate(0, -100%); | ||||
|       } | ||||
|     } | ||||
| 
 | ||||
|     & > h2 { | ||||
|       height: 40px; | ||||
|       line-height: 40px; | ||||
| @@ -920,6 +824,7 @@ export default { | ||||
|       padding: 0 10px; | ||||
|       background: #0A0B0D; | ||||
|       overflow-y: auto; | ||||
|       overflow-x: hidden; | ||||
| 
 | ||||
|       .layout-left__right--item { | ||||
|         margin-top: 10px; | ||||
| @@ -931,8 +836,12 @@ export default { | ||||
|         } | ||||
| 
 | ||||
|         img { | ||||
|           width: 180px; | ||||
|           height: 80px; | ||||
|           width: auto; | ||||
|           height: auto; | ||||
|           max-height: 130px; | ||||
|           max-width: 100%; | ||||
|           margin-left: 50%; | ||||
|           transform: translateX(-50%); | ||||
|         } | ||||
| 
 | ||||
|         span { | ||||
| @@ -1008,13 +917,13 @@ export default { | ||||
| 
 | ||||
|   .layout-middle { | ||||
|     flex: 1; | ||||
|     min-width: 0; | ||||
|     background: #000; | ||||
| 
 | ||||
|     .canvas-wrapper { | ||||
|       position: relative; | ||||
|       -webkit-transform-origin: 0 0; | ||||
|       transform-origin: 0 0; | ||||
|       -webkit-box-sizing: border-box; | ||||
|       box-sizing: border-box; | ||||
|       height: 100%; | ||||
|       margin: 0; | ||||
| @@ -1024,11 +933,11 @@ export default { | ||||
|         width: 100%; | ||||
|         padding: 18px 0 0 18px; | ||||
| 
 | ||||
|         ::v-deep .vue-ruler-ref-line-v, ::v-deep .vue-ruler-ref-line-h { | ||||
|         :deep( .vue-ruler-ref-line-v), :deep( .vue-ruler-ref-line-h ) { | ||||
|           display: none; | ||||
|         } | ||||
| 
 | ||||
|         ::v-deep .vue-ruler-v { | ||||
|         :deep( .vue-ruler-v ) { | ||||
|           .n { | ||||
|             transform: rotate(180deg); | ||||
|           } | ||||
| @@ -1048,7 +957,7 @@ export default { | ||||
|       } | ||||
|     } | ||||
| 
 | ||||
|     ::v-deep .handle { | ||||
|     :deep( .handle ) { | ||||
|       border-radius: 100%; | ||||
|       border: none; | ||||
|       background-color: #09f; | ||||
| @@ -1063,6 +972,7 @@ export default { | ||||
|     .draggable { | ||||
|       position: absolute; | ||||
|       border: none; | ||||
|       transition: none; | ||||
| 
 | ||||
|       &::after { | ||||
|         position: absolute; | ||||
| @@ -1096,7 +1006,7 @@ export default { | ||||
|     border-left: 1px solid #000000; | ||||
|     background: #1D2127; | ||||
| 
 | ||||
|     ::v-deep .el-input-number { | ||||
|     :deep(.el-input-number ) { | ||||
|       width: 106px; | ||||
|       margin-right: 20px; | ||||
| 
 | ||||
| @@ -1118,9 +1028,9 @@ export default { | ||||
|       } | ||||
|     } | ||||
| 
 | ||||
|     .layout-right__content { | ||||
|       height: calc(100% - 40px); | ||||
|       overflow-y: overlay; | ||||
|     :deep(.layout-right__content ) { | ||||
|       height: calc(100% - 50px); | ||||
|       overflow-y: auto; | ||||
|       overflow-x: hidden; | ||||
| 
 | ||||
|       .layout-config__group { | ||||
| @@ -1145,12 +1055,13 @@ export default { | ||||
|           margin-bottom: 0; | ||||
|         } | ||||
| 
 | ||||
|         ::v-deep .el-select, ::v-deep .el-cascader { | ||||
|         .el-select, .el-cascader { | ||||
|           width: 232px; | ||||
|           color: #fff; | ||||
|           background: transparent; | ||||
| 
 | ||||
|           input { | ||||
|             width: 232px; | ||||
|             width: 100%; | ||||
|             background: #262C33; | ||||
|             font-size: 12px; | ||||
|             color: #fff; | ||||
| @@ -1188,7 +1099,7 @@ export default { | ||||
|           } | ||||
|         } | ||||
| 
 | ||||
|         &.layout-config__item--input ::v-deep input { | ||||
|         &.layout-config__item--input input { | ||||
|           width: 232px; | ||||
|           background: #262C33; | ||||
|           font-size: 12px; | ||||
| @@ -12,7 +12,7 @@ | ||||
| 
 | ||||
| <script> | ||||
| import {scrollBoard} from '@jiaminghi/data-view' | ||||
| import bgImage from '../assets/centralTask/bg.png' | ||||
| import bgImage from './assets/centralTask/bg.png' | ||||
| import Vue from "vue"; | ||||
| 
 | ||||
| Vue.use(scrollBoard) | ||||
| @@ -74,7 +74,7 @@ export default { | ||||
|     .leftBox { | ||||
|       width: 100%; | ||||
|       height: 100%; | ||||
|       background-image: url("../assets/centralTask/box.png"); | ||||
|       background-image: url("./assets/centralTask/box.png"); | ||||
|       background-size: 100% 100%; | ||||
|       background-repeat: no-repeat; | ||||
|       display: flex; | ||||
| @@ -88,7 +88,7 @@ export default { | ||||
|   .boxTitle { | ||||
|     height: 68px; | ||||
|     width: 534px; | ||||
|     background-image: url("../assets/centralTask/titleBox.png"); | ||||
|     background-image: url("./assets/centralTask/titleBox.png"); | ||||
|     text-align: center; | ||||
|     font-size: 22px; | ||||
|     font-weight: 400; | ||||
| @@ -97,7 +97,7 @@ export default { | ||||
|     line-height: 68px; | ||||
|   } | ||||
| 
 | ||||
|   ::v-deep .dv-scroll-board { | ||||
|   :deep( .dv-scroll-board ){ | ||||
|     width: 100%; | ||||
|     flex: 1; | ||||
|     min-height: 0; | ||||
| @@ -298,7 +298,7 @@ export default { | ||||
|   flex-direction: column; | ||||
| 
 | ||||
| 
 | ||||
|   ::v-deep .eventItem { | ||||
|   :deep( .eventItem ){ | ||||
|     width: 100%; | ||||
|     color: #82C5FF; | ||||
| 
 | ||||
| @@ -309,7 +309,7 @@ export default { | ||||
|     } | ||||
|   } | ||||
| 
 | ||||
|   ::v-deep .communityEvent { | ||||
|   :deep( .communityEvent ){ | ||||
|     list-style-type: circle; | ||||
|     white-space: nowrap; | ||||
|     overflow: hidden; | ||||
| @@ -320,7 +320,7 @@ export default { | ||||
|     color: #82C5FF; | ||||
|   } | ||||
| 
 | ||||
|   ::v-deep .tag { | ||||
|   :deep( .tag ){ | ||||
|     padding: 0 10px; | ||||
|     border-radius: 4px; | ||||
|     margin-right: 10px; | ||||
| @@ -343,7 +343,7 @@ export default { | ||||
|   } | ||||
| 
 | ||||
|   .centerTopPane { | ||||
|     background-image: url("../assets/govInteraction/globe_map.png"); | ||||
|     background-image: url("./assets/govInteraction/globe_map.png"); | ||||
|     background-repeat: no-repeat; | ||||
|     background-size: 100% 100%; | ||||
|     height: 540px; | ||||
| @@ -361,7 +361,7 @@ export default { | ||||
|       transform: translate(-50%, -50%); | ||||
|     } | ||||
| 
 | ||||
|     ::v-deep .gradientFont { | ||||
|     :deep( .gradientFont ){ | ||||
|       background-image: linear-gradient(180deg, #FFFFFF 0%, #FFFFFF 18%, #6BC7FF 100%); | ||||
|       -webkit-background-clip: text; | ||||
|       -webkit-text-fill-color: transparent; | ||||
| @@ -373,10 +373,10 @@ export default { | ||||
|       } | ||||
|     } | ||||
| 
 | ||||
|     ::v-deep .dataPane { | ||||
|     :deep( .dataPane ){ | ||||
|       width: 122px; | ||||
|       height: 114px; | ||||
|       background-image: url("../assets/govInteraction/kuaikuai.png"); | ||||
|       background-image: url("./assets/govInteraction/kuaikuai.png"); | ||||
|       background-repeat: no-repeat; | ||||
|       background-size: 100% 80px; | ||||
|       background-position: bottom center; | ||||
| @@ -426,7 +426,7 @@ export default { | ||||
| 
 | ||||
|   .titlePane { | ||||
|     width: 100%; | ||||
|     background-image: url("../assets/govInteraction/title.png"); | ||||
|     background-image: url("./assets/govInteraction/title.png"); | ||||
|     background-repeat: no-repeat; | ||||
|     background-size: 309px 100%; | ||||
|     height: 60px; | ||||
| @@ -55,7 +55,7 @@ | ||||
|           <ai-echart | ||||
|               style="height: 100%; width: 100%;" | ||||
|               :data="eventInfo" | ||||
|               :ops="pieChart"> | ||||
|               :ops="pieChart2"> | ||||
|           </ai-echart> | ||||
|         </div> | ||||
|       </div> | ||||
| @@ -63,7 +63,7 @@ | ||||
|     <el-dialog :visible.sync="isShowInfo" width="640px" :close-on-click-modal="false" :modal-append-to-body="false"> | ||||
|       <template slot="title"> | ||||
|         <h2>家庭信息</h2> | ||||
|         <img src="../assets/grid/close.png" @click="isShowInfo = false"> | ||||
|         <img src="./assets/grid/close.png" @click="isShowInfo = false"> | ||||
|       </template> | ||||
|       <div class="grid-info"> | ||||
|         <div class="grid-info__title"> | ||||
| @@ -86,15 +86,11 @@ | ||||
| </template> | ||||
| 
 | ||||
| <script> | ||||
| import pieChart from 'dvcp-dv-ui/components/AiEchart/template/pie/pieChart2' | ||||
| import barChart1 from 'dvcp-dv-ui/components/AiEchart/template/bar/barChart1' | ||||
| import AiOkrTree from "dvcp-dv-ui/components/AiOkrTree/AiOkrTree" | ||||
| import {barChart1, pieChart2} from "./components/chartOps" | ||||
| 
 | ||||
| export default { | ||||
|   name: 'AppGridDV', | ||||
| 
 | ||||
|   label: '网格数据大屏', | ||||
|   components: {AiOkrTree}, | ||||
|   props: { | ||||
|     instance: Function, | ||||
|     dict: Object, | ||||
| @@ -111,7 +107,7 @@ export default { | ||||
|       barChart1, | ||||
|       userInfo: [], | ||||
|       eventInfo: [], | ||||
|       pieChart, | ||||
|       pieChart2, | ||||
|       total: 0, | ||||
|       isShowInfo: false, | ||||
|       defaultProps: { | ||||
| @@ -131,14 +127,14 @@ export default { | ||||
|               } | ||||
|             }, row.householdName === '1' ? '户主' : (this.dict.getLabel('householdRelation', row.householdRelation) || '-')) | ||||
|           }, | ||||
|           formart: v => this.dict.getLabel('householdRelation', v) | ||||
|           format: v => this.dict.getLabel('householdRelation', v) | ||||
|         }, | ||||
|         { | ||||
|           prop: 'idNumber', | ||||
|           label: '身份证号', | ||||
|           align: 'center', | ||||
|           width: 220, | ||||
|           formart: v => v ? v.replace(/^(\d{10})\d{4}(.{4}$)/g, `$1${Array(5).join('*')}$2`) : '-' | ||||
|           format: v => v ? v.replace(/^(\d{10})\d{4}(.{4}$)/g, `$1${Array(5).join('*')}$2`) : '-' | ||||
|         }, | ||||
|         {prop: 'phone', label: '联系方式', align: 'center'} | ||||
|       ], | ||||
| @@ -512,7 +508,7 @@ export default { | ||||
|     } | ||||
|   } | ||||
| 
 | ||||
|   ::v-deep .el-dialog__body { | ||||
|   :deep( .el-dialog__body ){ | ||||
|     padding: 10px 40px 30px; | ||||
| 
 | ||||
|     .el-table { | ||||
| @@ -542,7 +538,7 @@ export default { | ||||
|     } | ||||
|   } | ||||
| 
 | ||||
|   ::v-deep .el-dialog { | ||||
|   :deep( .el-dialog ){ | ||||
|     position: absolute; | ||||
|     top: 50%; | ||||
|     left: 50%; | ||||
| @@ -580,7 +576,7 @@ export default { | ||||
|     } | ||||
|   } | ||||
| 
 | ||||
|   ::v-deep .userlist-container { | ||||
|   :deep( .userlist-container ){ | ||||
|     .userlist { | ||||
|       display: flex; | ||||
|       align-items: center; | ||||
| @@ -710,7 +706,7 @@ export default { | ||||
|     display: flex; | ||||
|     width: 320px; | ||||
|     height: 62px; | ||||
|     background-image: url(../assets/grid/title-bg.png); | ||||
|     background-image: url(assets/grid/title-bg.png); | ||||
|     background-size: 100% 100%; | ||||
| 
 | ||||
|     h2 { | ||||
| @@ -776,7 +772,7 @@ export default { | ||||
|       height: 300%; | ||||
|     } | ||||
| 
 | ||||
|     ::v-deep .org-chart-container { | ||||
|     :deep( .org-chart-container ){ | ||||
|       display: flex; | ||||
|       justify-content: center; | ||||
| 
 | ||||
| @@ -805,7 +801,7 @@ export default { | ||||
|       } | ||||
|     } | ||||
| 
 | ||||
|     ::v-deep .org-chart-node-children { | ||||
|     :deep( .org-chart-node-children ){ | ||||
|       display: flex; | ||||
|       justify-content: center; | ||||
|     } | ||||
| @@ -823,7 +819,7 @@ export default { | ||||
|       padding-bottom: 8px; | ||||
|     } | ||||
| 
 | ||||
|     ::v-deep .el-tree { | ||||
|     :deep( .el-tree ){ | ||||
|       background: transparent; | ||||
| 
 | ||||
|       .el-tree-node__expand-icon { | ||||
							
								
								
									
										812
									
								
								packages/bigscreen/dv/AppHouseMapDv.vue
									
									
									
									
									
										Normal file
									
								
							
							
						
						| @@ -0,0 +1,812 @@ | ||||
| <template> | ||||
|   <div style="height:100%;" class="AppHouseMapDv"> | ||||
|     <div class="map"> | ||||
|       <div id="map" ref="rootmap" @click="hidePopup"/> | ||||
|       <div class="community-info" v-show="isShowInfo"> | ||||
|         <div class="community-info__close" title="关闭" @click="info = {}, isShowInfo = false,chooseBuildId=''"> | ||||
|           <i class="iconClean iconfont"></i> | ||||
|         </div> | ||||
|         <div class="community-info__header"> | ||||
|           <h2 v-if="!info.name">{{ info.createAddress }}</h2> | ||||
|           <h2 v-if="info.name">{{ info.homesteadAddress }}</h2> | ||||
|           <div>{{ info.lng }},{{ info.lat }}</div> | ||||
|         </div> | ||||
|         <div class="community-info__wrapper" v-if="info.name"> | ||||
|           <h2>户主信息</h2> | ||||
|           <div class="community-info__item"> | ||||
|             <label>所属村</label> | ||||
|             <span>{{ info.areaName }}</span> | ||||
|           </div> | ||||
|           <div class="community-info__item"> | ||||
|             <label>姓名</label> | ||||
|             <span style="color:#2266FF;">{{ info.name }}</span> | ||||
|           </div> | ||||
|           <div class="community-info__item"> | ||||
|             <label>联系电话</label> | ||||
|             <span style="color:#2266FF;">{{ info.phone }}</span> | ||||
|           </div> | ||||
|           <div class="community-info__item"> | ||||
|             <label>性别</label> | ||||
|             <span>{{ info.sex == 1 ? '男' : '女' }}</span> | ||||
|           </div> | ||||
|           <div class="community-info__item"> | ||||
|             <label>年龄</label> | ||||
|             <span>{{ info.age }}</span> | ||||
|           </div> | ||||
|         </div> | ||||
|         <div class="community-info__wrapper" v-if="info.name"> | ||||
|           <h2>宅基地信息</h2> | ||||
|           <div class="community-info__item"> | ||||
|             <label>住宅建筑面积</label> | ||||
|             <span>{{ info.liveBuildingArea }}m²</span> | ||||
|           </div> | ||||
|           <div class="community-info__item"> | ||||
|             <label>建筑层数</label> | ||||
|             <span>{{ info.buildingFloorNumber }}层</span> | ||||
|           </div> | ||||
|           <div class="community-info__item"> | ||||
|             <label>建筑高度</label> | ||||
|             <span>{{ info.buildingHeight }}m</span> | ||||
|           </div> | ||||
|         </div> | ||||
|         <div class="community-info__wrapper" v-if="!info.name"> | ||||
|           <h2>房屋信息</h2> | ||||
|           <div class="community-info__item"> | ||||
|             <label>所属社区</label> | ||||
|             <span>{{ info.areaName }}</span> | ||||
|           </div> | ||||
|           <div class="community-info__item"> | ||||
|             <label>所属小区</label> | ||||
|             <span>{{ info.communityName }}</span> | ||||
|           </div> | ||||
|           <div class="community-info__item"> | ||||
|             <label>房屋类型</label> | ||||
|             <span>{{ dict.getLabel("communityBuildingType", info.buildingType) }}</span> | ||||
|           </div> | ||||
|           <div class="community-info__item"> | ||||
|             <label>楼长姓名</label> | ||||
|             <span>{{ info.managerName }}</span> | ||||
|           </div> | ||||
|           <div class="community-info__item"> | ||||
|             <label>楼长电话</label> | ||||
|             <span>{{ info.managerPhone }}</span> | ||||
|           </div> | ||||
|         </div> | ||||
|       </div> | ||||
|     </div> | ||||
|   </div> | ||||
| </template> | ||||
|  | ||||
| <script> | ||||
| import AMapLoader from '@amap/amap-jsapi-loader' | ||||
| import {mapState} from 'vuex' | ||||
|  | ||||
| export default { | ||||
|   name: 'AppHouseMapDv', | ||||
|   label: '房屋地图', | ||||
|   provide() { | ||||
|     return { | ||||
|       root: this | ||||
|     } | ||||
|   }, | ||||
|   props: { | ||||
|     instance: Function, | ||||
|     dict: Object | ||||
|   }, | ||||
|   data() { | ||||
|     return { | ||||
|       map: null, | ||||
|       mapLib: null, | ||||
|       community: '', | ||||
|       areaData: {}, | ||||
|       isShowInfo: false, | ||||
|       areaId: '', | ||||
|       areaName: '', | ||||
|       list: [], | ||||
|       info: {}, | ||||
|       resident: null, | ||||
|       satellite: null, | ||||
|       zoom: 11, | ||||
|       chooseBuildId: '', | ||||
|       buildList: [], | ||||
|       searchList: [], | ||||
|       house: null, | ||||
|       center: [], | ||||
|       type: '', | ||||
|       showStatistics: false | ||||
|     } | ||||
|   }, | ||||
|   computed: { | ||||
|     ...mapState(['user']) | ||||
|   }, | ||||
|  | ||||
|   watch: { | ||||
|     community: { | ||||
|       deep: true, | ||||
|       handler() { | ||||
|         this.debounce(this.search, 500) | ||||
|       } | ||||
|     }, | ||||
|  | ||||
|     showStatistics: { | ||||
|       deep: true, | ||||
|       handler() { | ||||
|         this.debounce(this.getCorpLocation, 500) | ||||
|       } | ||||
|     }, | ||||
|   }, | ||||
|  | ||||
|   created() { | ||||
|     this.dict.load('householdRelation', 'communityBuildingType') | ||||
|   }, | ||||
|  | ||||
|   mounted() { | ||||
|     this.areaId = this.user.info.areaId | ||||
|     this.areaName = this.user.info.areaName | ||||
|     this.getCorpLocation() | ||||
|   }, | ||||
|  | ||||
|   methods: { | ||||
|     getCorpLocation() { | ||||
|       if (this.showStatistics) { | ||||
|         return | ||||
|       } | ||||
|       this.instance.post("/app/appdvcpconfig/getCorpLocation").then(res => { | ||||
|         if (res.code == 0) { | ||||
|           this.initMap(res.data) | ||||
|         } | ||||
|       }) | ||||
|     }, | ||||
|     changeZoom(isAdd) { | ||||
|       const zoom = isAdd ? this.map.getZoom() + 1 : this.map.getZoom() - 1 | ||||
|       this.map.setZoom(zoom, false, 600) | ||||
|     }, | ||||
|  | ||||
|     getBuildInfo(id, type) { | ||||
|       var url = `/app/apphomesteadinfo/queryDetailById?id=${id}` | ||||
|       if (type == 0) { | ||||
|         url = `/app/appcommunityhouseinfo/queryDetailByIdWithBuilding?buildId=${id}` | ||||
|       } | ||||
|       this.instance.post(url).then(res => { | ||||
|         if (res.code === 0) { | ||||
|           if (type == 1) { | ||||
|             this.info = res.data | ||||
|           } else { | ||||
|             this.info = res.data.build | ||||
|             this.resident = null; | ||||
|           } | ||||
|           this.$nextTick(() => { | ||||
|             this.isShowInfo = true | ||||
|           }) | ||||
|         } | ||||
|       }) | ||||
|     }, | ||||
|  | ||||
|     chooseCommunity(item) { | ||||
|       if (item.name) { //宅基地 | ||||
|         if (!item.lng || !item.lat) { | ||||
|           return this.$message.error('未获取到该房屋坐标信息') | ||||
|         } else { | ||||
|           this.map.setZoomAndCenter(18, [item.lng, item.lat], false, 600) | ||||
|           this.info = item | ||||
|           this.$nextTick(() => { | ||||
|             this.isShowSearch = false | ||||
|             this.isShowInfo = true | ||||
|           }) | ||||
|         } | ||||
|  | ||||
|       } else { //楼栋 | ||||
|         this.instance.post(`/app/appcommunityhouseinfo/queryDetailByIdWithBuilding`, null, { | ||||
|           params: { | ||||
|             buildId: item.buildingId, | ||||
|             houseId: item.id, | ||||
|             residentId: item.residentId | ||||
|           } | ||||
|         }).then(res => { | ||||
|           if (res.code === 0) { | ||||
|             if (!res.data.build?.lng || !res.data.build?.lat) { | ||||
|               this.isShowInfo = true | ||||
|               this.isShowSearch = false | ||||
|               this.info = res.data.build; | ||||
|               return this.$message.error('未获取到该房屋坐标信息') | ||||
|             } else { | ||||
|               this.chooseBuildId = res.data.build.id | ||||
|               this.house = res.data.house | ||||
|               this.resident = res.data.resident; | ||||
|             } | ||||
|  | ||||
|             this.map.setZoomAndCenter(18, [res.data.build?.lng, res.data.build?.lat], false, 600) | ||||
|             this.info = res.data.build | ||||
|             this.$nextTick(() => { | ||||
|               this.isShowSearch = false | ||||
|               this.isShowInfo = true | ||||
|             }) | ||||
|           } | ||||
|         }) | ||||
|       } | ||||
|     }, | ||||
|  | ||||
|     toCenter() { | ||||
|       this.map.setZoomAndCenter(this.zoom, this.center, false, 600) | ||||
|     }, | ||||
|  | ||||
|     renderClusterMarker(context) { | ||||
|       let el = `<div class="polymeric"> | ||||
|         <div class="polymeric-container"> | ||||
|           <p>${context.count}</p> | ||||
|         </div> | ||||
|       </div>` | ||||
|       let {mapLib: AMap} = this | ||||
|       let offset = new AMap.Pixel(-9, -9) | ||||
|       context.marker.setContent(el) | ||||
|       context.marker.setOffset(offset) | ||||
|       context.marker.lnglat = context.clusterData[0].lnglat | ||||
|  | ||||
|       context.marker.on('click', e => { | ||||
|         this.map.setZoomAndCenter(this.map.getZoom() + 2, e.target.lnglat, false, 500) | ||||
|       }) | ||||
|     }, | ||||
|  | ||||
|     renderMarker(context) { | ||||
|       const buildId = context.data[0].id | ||||
|       let el = '' | ||||
|       var urlType = '' | ||||
|       if (context.data[0].communityName == context.data[0].buildingNumber) { //宅基地 | ||||
|         urlType = 1 | ||||
|         el = `<div id="buildId-${buildId}" class="mark ${buildId === this.chooseBuildId ? 'mark-active' : ''}"> | ||||
|          <div class="mark-contaienr"> | ||||
|             <span>${context.data[0].areaName}</span>   | ||||
|             <span>${context.data[0].communityName}</span> | ||||
|           </div> | ||||
|       </div>` | ||||
|       } else { | ||||
|         urlType = 0 | ||||
|         el = `<div id="buildId-${buildId}" class="mark ${buildId === this.chooseBuildId ? 'mark-active' : ''}"> | ||||
|          <div class="mark-contaienr"> | ||||
|             <span>${context.data[0].communityName}</span>   | ||||
|             <span>${context.data[0].buildingNumber}栋</span> | ||||
|           </div> | ||||
|       </div>` | ||||
|       } | ||||
|  | ||||
|       context.marker.setContent(el); | ||||
|       context.marker.setAnchor("center") | ||||
|       context.marker.id = `${buildId}` | ||||
|       context.marker.lnglat = context.data[0].lnglat | ||||
|       context.marker.urlType = urlType | ||||
|  | ||||
|       context.marker.on('click', e => { | ||||
|         this.chooseBuildId = e.target.id | ||||
|         this.getBuildInfo(e.target.id, e.target.urlType) | ||||
|         context.marker.setContent(el); | ||||
|         document.querySelectorAll('.mark').forEach(el => { | ||||
|           el.classList.remove('mark-active') | ||||
|         }) | ||||
|         document.querySelector(`#buildId-${e.target.id}`).classList.add('mark-active') | ||||
|       }) | ||||
|     }, | ||||
|  | ||||
|     addMakert(points) { | ||||
|       let {mapLib: AMap} = this | ||||
|       new AMap.MarkerClusterer(this.map, points, { | ||||
|         gridSize: 60, | ||||
|         maxZoom: 15, | ||||
|         clusterByZoomChange: false, | ||||
|         renderClusterMarker: this.renderClusterMarker, | ||||
|         renderMarker: this.renderMarker | ||||
|       }) | ||||
|     }, | ||||
|  | ||||
|     getCommunityList() { | ||||
|       this.instance.post('/app/appcommunitybuildinginfo/listByBuilding', null, { | ||||
|         params: { | ||||
|           current: 1, | ||||
|           size: 1000000 | ||||
|         } | ||||
|       }).then(res => { | ||||
|         if (res.code === 0) { | ||||
|           this.buildList = res.data | ||||
|           const points = res.data.map(item => { | ||||
|             return { | ||||
|               lnglat: [item.lng, item.lat], | ||||
|               id: item.id, | ||||
|               corpId: item.corpId, | ||||
|               areaName: item.areaName, | ||||
|               buildingNumber: item.name || item.buildingNumber, | ||||
|               communityName: item.name || item.communityName, | ||||
|             } | ||||
|           }) | ||||
|  | ||||
|           this.addMakert(points) | ||||
|         } | ||||
|       }) | ||||
|     }, | ||||
|  | ||||
|     hidePopup() { | ||||
|       this.isShowArea = false | ||||
|       this.isShowSearch = false | ||||
|     }, | ||||
|  | ||||
|     initMap({lng, lat}) { | ||||
|       this.center = [lng, lat]; | ||||
|       AMapLoader.load({ | ||||
|         key: '54a02a43d9828a8f9cd4f26fe281e74e', | ||||
|         version: '2.0', | ||||
|         plugins: ['AMap.ToolBar', 'AMap.Scale', 'AMap.MouseTool', 'AMap.MarkerClusterer'], | ||||
|         AMapUI: { | ||||
|           version: '1.1', | ||||
|           plugins: [] | ||||
|         } | ||||
|       }).then((AMap) => { | ||||
|         this.mapLib = AMap | ||||
|         this.map = new AMap.Map('map', { | ||||
|           resizeEnable: true, | ||||
|           zooms: [6, 20], | ||||
|           center: [lng, lat], | ||||
|           zoom: this.zoom, | ||||
|           mapStyle: 'amap://styles/40f6fba77127e061a058f670433a67ec' | ||||
|         }) | ||||
|         this.satellite = new AMap.TileLayer.Satellite() | ||||
|         this.getCommunityList() | ||||
|       }) | ||||
|     } | ||||
|   } | ||||
| } | ||||
| </script> | ||||
|  | ||||
| <style lang="scss" scoped> | ||||
| .map { | ||||
|   :deep( .amap-logo), :deep( .amap-copyright ){ | ||||
|     display: none !important; | ||||
|   } | ||||
|  | ||||
|   :deep( .amap-icon ){ | ||||
|     width: 40px !important; | ||||
|     height: 40px !important; | ||||
|  | ||||
|     img { | ||||
|       width: 100%; | ||||
|       height: 100%; | ||||
|     } | ||||
|   } | ||||
| } | ||||
|  | ||||
| .community-info__star { | ||||
|   margin-top: 4px; | ||||
|   margin-bottom: 8px; | ||||
|  | ||||
|   .community-info__star--content { | ||||
|     display: flex; | ||||
|     align-items: center; | ||||
|     height: 36px; | ||||
|     padding: 0 12px; | ||||
|     color: #666666; | ||||
|     font-size: 12px; | ||||
|  | ||||
|     span { | ||||
|       flex: 1; | ||||
|       text-align: center; | ||||
|  | ||||
|       &:first-child { | ||||
|         text-align: left; | ||||
|       } | ||||
|  | ||||
|       &:last-child { | ||||
|         text-align: right; | ||||
|       } | ||||
|     } | ||||
|  | ||||
|     &:nth-of-type(2n) { | ||||
|       background: #fff; | ||||
|     } | ||||
|   } | ||||
|  | ||||
|   .community-info__star--tab { | ||||
|     display: flex; | ||||
|     align-items: center; | ||||
|     height: 36px; | ||||
|     padding: 0 12px; | ||||
|     user-select: none; | ||||
|     background: #fff; | ||||
|  | ||||
|     span { | ||||
|       height: 100%; | ||||
|       line-height: 36px; | ||||
|       color: #999999; | ||||
|       font-size: 12px; | ||||
|       font-weight: 700; | ||||
|       cursor: pointer; | ||||
|       border-bottom: 2px solid transparent; | ||||
|  | ||||
|       &:first-child { | ||||
|         margin-right: 16px; | ||||
|       } | ||||
|  | ||||
|       &.star-active { | ||||
|         color: #2266FF; | ||||
|         border-bottom: 2px solid #2266FF; | ||||
|       } | ||||
|     } | ||||
|   } | ||||
| } | ||||
|  | ||||
| .community-info__item--imgs { | ||||
|   display: block !important; | ||||
|   height: auto !important; | ||||
|  | ||||
|   label { | ||||
|     height: 36px; | ||||
|     line-height: 36px; | ||||
|   } | ||||
|  | ||||
|   .community-info__item--img { | ||||
|     display: flex; | ||||
|     align-items: center; | ||||
|     flex-wrap: wrap; | ||||
|     padding-bottom: 10px; | ||||
|     overflow: hidden; | ||||
|  | ||||
|     img { | ||||
|       width: 69px; | ||||
|       height: 69px; | ||||
|       margin-right: 4px; | ||||
|       margin-bottom: 4px; | ||||
|       cursor: pointer; | ||||
|  | ||||
|       &:nth-of-type(4n) { | ||||
|         margin-right: 0; | ||||
|       } | ||||
|  | ||||
|       &:last-child { | ||||
|         margin-right: 0; | ||||
|       } | ||||
|     } | ||||
|   } | ||||
| } | ||||
| .map { | ||||
|   position: relative; | ||||
|   width: 100%; | ||||
|   height: 100%; | ||||
|   overflow: hidden; | ||||
|  | ||||
|   :deep( .ol-zoom ){ | ||||
|     display: none !important; | ||||
|     top: inherit !important; | ||||
|     bottom: 0.5em !important; | ||||
|   } | ||||
|  | ||||
|   div { | ||||
|     box-sizing: border-box; | ||||
|   } | ||||
|  | ||||
|   #map { | ||||
|     width: 100%; | ||||
|     height: 100%; | ||||
|   } | ||||
| } | ||||
|  | ||||
| .community { | ||||
|   display: flex; | ||||
|   align-items: center; | ||||
|   position: relative; | ||||
|   height: 28px; | ||||
|   padding: 0 10px; | ||||
|   background: #0F8F64; | ||||
|   border-radius: 26px; | ||||
|   color: #fff; | ||||
|   font-size: 12px; | ||||
|   cursor: pointer; | ||||
|  | ||||
|   &.color1 { | ||||
|     background: #2266FF; | ||||
|  | ||||
|     em:after { | ||||
|       border-top-color: #2266FF !important; | ||||
|     } | ||||
|   } | ||||
|  | ||||
|   &.color2 { | ||||
|     background: #F46159; | ||||
|  | ||||
|     em:after { | ||||
|       border-top-color: #F46159 !important; | ||||
|     } | ||||
|   } | ||||
|  | ||||
|   em { | ||||
|     position: absolute; | ||||
|     bottom: -6px; | ||||
|     left: 50%; | ||||
|     transform: translate(-50%, 0); | ||||
|  | ||||
|     &::after { | ||||
|       position: absolute; | ||||
|       bottom: -6px; | ||||
|       left: 0; | ||||
|       width: 0; | ||||
|       height: 0; | ||||
|       border: 6px solid #0F8F64; | ||||
|       border-bottom-color: transparent; | ||||
|       border-left-color: transparent; | ||||
|       border-right-color: transparent; | ||||
|       transform: translate(-50%, 0); | ||||
|       overflow: hidden; | ||||
|       content: ' '; | ||||
|     } | ||||
|   } | ||||
|  | ||||
|   i { | ||||
|     padding-right: 2px; | ||||
|     position: relative; | ||||
|     color: #ffc928; | ||||
|     font-size: 16px; | ||||
|     font-style: normal; | ||||
|   } | ||||
| } | ||||
|  | ||||
| :deep( .polymeric ){ | ||||
|   display: flex; | ||||
|   position: relative; | ||||
|   align-items: center; | ||||
|   justify-content: center; | ||||
|   width: 62px; | ||||
|   height: 62px; | ||||
|   border-radius: 50%; | ||||
|   cursor: pointer; | ||||
|   user-select: none; | ||||
|  | ||||
|   &.polymeric-active { | ||||
|     .polymeric-container { | ||||
|       background: #F46159; | ||||
|     } | ||||
|  | ||||
|     &::after { | ||||
|       background-color: #F46159; | ||||
|     } | ||||
|   } | ||||
|  | ||||
|   &::after { | ||||
|     position: absolute; | ||||
|     z-index: -1; | ||||
|     width: 62px; | ||||
|     height: 62px; | ||||
|     border-radius: 50%; | ||||
|     -webkit-animation: warn 1s ease-out 0s infinite; | ||||
|     animation: warn 1s ease-out 0s infinite; | ||||
|     background-color: rgba(15, 143, 100, 1); | ||||
|     transform: translate(-50%, -50%); | ||||
|     content: " "; | ||||
|   } | ||||
|  | ||||
|   .polymeric-container { | ||||
|     display: flex; | ||||
|     align-items: center; | ||||
|     justify-content: center; | ||||
|     flex-direction: column; | ||||
|     width: 62px; | ||||
|     height: 62px; | ||||
|     border-radius: 50%; | ||||
|     background: rgba(15, 143, 100, 1); | ||||
|  | ||||
|     p { | ||||
|       text-align: center; | ||||
|       width: 58px; | ||||
|       color: #fff; | ||||
|       font-size: 18px; | ||||
|       overflow: hidden; | ||||
|       text-overflow: ellipsis; | ||||
|       white-space: nowrap; | ||||
|     } | ||||
|  | ||||
|     p:first-child { | ||||
|       font-size: 14px; | ||||
|     } | ||||
|  | ||||
|     h2 { | ||||
|       color: #fff; | ||||
|       font-weight: normal; | ||||
|       font-size: 12px; | ||||
|     } | ||||
|   } | ||||
| } | ||||
|  | ||||
| :deep( .mark ){ | ||||
|   user-select: none; | ||||
|   cursor: pointer; | ||||
|   height: 32px; | ||||
|   border-radius: 26px; | ||||
|   position: relative; | ||||
|   display: flex; | ||||
|   align-items: center; | ||||
|   justify-content: center; | ||||
|   box-sizing: border-box; | ||||
|   padding: 0 12px; | ||||
|   background: rgba(0,39,100,0.50); | ||||
|   border: 1px solid #36A5FF; | ||||
|   border-radius: 30px; | ||||
|  | ||||
|   &.mark-active { | ||||
|     background: #004AC0; | ||||
|     border: 1px solid transparent; | ||||
|     box-shadow: inset 0 0 8px 2px #33BBFF; | ||||
|   } | ||||
|  | ||||
|   .mark-contaienr { | ||||
|     color: white; | ||||
|     font-size: 14px; | ||||
|     position: relative; | ||||
|     overflow: hidden; | ||||
|     text-overflow: ellipsis; | ||||
|     white-space: nowrap; | ||||
|     display: flex; | ||||
|     align-items: center; | ||||
|     justify-content: center; | ||||
|   } | ||||
|  | ||||
|   .arrow { | ||||
|     position: absolute; | ||||
|     left: 50%; | ||||
|     transform: translateX(-50%); | ||||
|     bottom: -21px; | ||||
|     width: 0; | ||||
|     height: 0; | ||||
|     border: 12px solid transparent; | ||||
|     border-top: 12px solid #0F8F64; | ||||
|   } | ||||
|  | ||||
| } | ||||
|  | ||||
| @-webkit-keyframes warn { | ||||
|   0% { | ||||
|     transform: scale(.5); | ||||
|     opacity: 1 | ||||
|   } | ||||
|  | ||||
|   30% { | ||||
|     opacity: .5 | ||||
|   } | ||||
|  | ||||
|   to { | ||||
|     transform: scale(1.8); | ||||
|     opacity: 0 | ||||
|   } | ||||
| } | ||||
|  | ||||
| @keyframes warn { | ||||
|   0% { | ||||
|     transform: scale(.5); | ||||
|     opacity: 1 | ||||
|   } | ||||
|  | ||||
|   30% { | ||||
|     opacity: .5 | ||||
|   } | ||||
|  | ||||
|   to { | ||||
|     transform: scale(1.4); | ||||
|     opacity: 0 | ||||
|   } | ||||
| } | ||||
|  | ||||
| .community-info { | ||||
|   position: absolute; | ||||
|   top: 58px; | ||||
|   right: 10px; | ||||
|   width: 400px; | ||||
|   height: calc(100% - 117px); | ||||
|   overflow-y: auto; | ||||
|   overflow-x: hidden; | ||||
|   z-index: 111; | ||||
|   border-radius: 2px; | ||||
|   background: rgba(0,15,38,0.30); | ||||
|   border: 1px solid #103588; | ||||
|   // filter: blur(5px); | ||||
|  | ||||
|   .community-info__close { | ||||
|     position: absolute; | ||||
|     right: 0; | ||||
|     top: 0; | ||||
|     padding: 16px 12px 0 12px; | ||||
|     font-size: 16px; | ||||
|     color: #fff; | ||||
|     cursor: pointer; | ||||
|  | ||||
|     &:hover { | ||||
|       opacity: 0.6; | ||||
|     } | ||||
|   } | ||||
|  | ||||
|   &::-webkit-scrollbar { | ||||
|     width: 6px; | ||||
|     height: 1px; | ||||
|   } | ||||
|  | ||||
|   &::-webkit-scrollbar-thumb { | ||||
|     border-radius: 6px; | ||||
|     background: rgba(144, 147, 153, .5); | ||||
|   } | ||||
|  | ||||
|   .community-info__header { | ||||
|     padding: 12px 20px; | ||||
|     background-image: linear-gradient(270deg, rgba(11, 158, 255, 0.2) 0%, rgba(2, 81, 227, 0.2) 100%); | ||||
|  | ||||
|     h2 { | ||||
|       max-width: 360px; | ||||
|       line-height: 28px; | ||||
|       margin: 0; | ||||
|       color: #fff; | ||||
|       font-size: 20px; | ||||
|       font-weight: 600; | ||||
|       margin-bottom: 10px; | ||||
|     } | ||||
|  | ||||
|     div { | ||||
|       display: flex; | ||||
|       align-items: center; | ||||
|       color: #D2E0FF; | ||||
|       font-size: 12px; | ||||
|     } | ||||
|  | ||||
|     span { | ||||
|       display: block; | ||||
|       margin-top: 4px; | ||||
|       font-style: normal; | ||||
|       color: #82C5FF; | ||||
|       font-size: 14px; | ||||
|     } | ||||
|   } | ||||
|  | ||||
|   .community-info__wrapper { | ||||
|     h2 { | ||||
|       margin: 20px 0 20px 20px; | ||||
|       padding: 0 20px; | ||||
|       font-size: 15px; | ||||
|       color: #fff; | ||||
|       font-weight: 600; | ||||
|       background: url(https://cdn.cunwuyun.cn/dvcp/ply/title-bg.png) no-repeat; | ||||
|       background-size: 169px 30px; | ||||
|       background-position-y: -5px; | ||||
|       background-position-x: -10px; | ||||
|     } | ||||
|  | ||||
|     .community-info__item { | ||||
|       display: flex; | ||||
|       align-items: center; | ||||
|       justify-content: space-between; | ||||
|       margin: 0 20px; | ||||
|       padding: 12px 12px; | ||||
|       font-size: 14px; | ||||
|       color: #fff; | ||||
|       background: rgba(63, 136, 255, 0.15); | ||||
|  | ||||
|       &:nth-of-type(2n) { | ||||
|         background: transparent; | ||||
|       } | ||||
|  | ||||
|       span { | ||||
|         max-width: 70%; | ||||
|         text-align: right; | ||||
|       } | ||||
|  | ||||
|       label { | ||||
|         flex-shrink: 1; | ||||
|         color: #82C5FF; | ||||
|       } | ||||
|     } | ||||
|  | ||||
|     &.community-info__wrapper--last { | ||||
|       .community-info__item { | ||||
|         background: #fff; | ||||
|  | ||||
|         &:nth-of-type(2n-1) { | ||||
|           background: #fff; | ||||
|         } | ||||
|       } | ||||
|     } | ||||
|  | ||||
|     .bg-fff { | ||||
|       background-color: #fff !important; | ||||
|     } | ||||
|   } | ||||
| } | ||||
| </style> | ||||
							
								
								
									
										887
									
								
								packages/bigscreen/dv/AppMonitorMapDv.vue
									
									
									
									
									
										Normal file
									
								
							
							
						
						| @@ -0,0 +1,887 @@ | ||||
| <template> | ||||
|   <div class="map"> | ||||
|     <div id="map" ref="rootmap" /> | ||||
|     <div class="community-info" v-show="isShowInfo"> | ||||
|       <div class="community-info__close" title="关闭" @click="closeInfo"> | ||||
|         <i class="iconClean iconfont"></i> | ||||
|       </div> | ||||
|       <div class="community-info__header"> | ||||
|         <div class="user" :style="userStyle"> | ||||
|           <span>{{ formatName(info.name) }}</span> | ||||
|         </div> | ||||
|         <h2>{{ info.name }}</h2> | ||||
|         <h3>{{ info.gpsDesc }}</h3> | ||||
|         <p>最后更新时间:{{ info.lastUpdateTime }}</p> | ||||
|         <div class="community-info__header--status"> | ||||
|           <div :style="{color: info.onlineStatus === '1' ? '#2EA222' : '#F46' }"> | ||||
|             <i class="iconfont iconzhuangtai"></i> | ||||
|             <span>设备{{ info.onlineStatus === '1' ? '在线' : '离线' }}</span> | ||||
|           </div> | ||||
|           <div> | ||||
|             <i class="iconfont icondianliang"></i> | ||||
|             <span>剩余{{ info.electricQuantity }}%</span> | ||||
|           </div> | ||||
|         </div> | ||||
|         <div class="community-info__header--info"> | ||||
|           <div class="community-info__header--info-item" v-for="(item, index) in testItem" :key="item.name" v-if="index !== 0"> | ||||
|             <div class="left"> | ||||
|               <div :style="{backgroundColor: item.color}"> | ||||
|                 <i :class="item.icon" class="iconfont"></i> | ||||
|               </div> | ||||
|               <span>{{ item.name }}</span> | ||||
|             </div> | ||||
|             <i :style="{color: (testData[index] && testData[index].abnormalStatus === '1') ? '#F46' : ''}">{{ testData[index] ? testData[index].itemValue : '-' }}{{ index === '1' ? '℃' : '' }}</i> | ||||
|           </div> | ||||
|         </div> | ||||
|       </div> | ||||
|       <div class="community-info__wrapper"> | ||||
|         <div class="community-info__title"> | ||||
|           <h2>人员信息</h2> | ||||
|           <span :style="userStatusColor">{{ userStatus }}</span> | ||||
|         </div> | ||||
|         <div class="community-info__item"> | ||||
|           <label>姓名</label> | ||||
|           <span>{{ info.name}}</span> | ||||
|         </div> | ||||
|         <div class="community-info__item"> | ||||
|           <label>性别</label> | ||||
|           <span>{{ info.sex === '1' ? '男' : '女' }}</span> | ||||
|         </div> | ||||
|         <div class="community-info__item"> | ||||
|           <label>年龄</label> | ||||
|           <span>{{ info.age }}</span> | ||||
|         </div> | ||||
|         <div class="community-info__item"> | ||||
|           <label>所属地区</label> | ||||
|           <span>{{ info.areaName }}</span> | ||||
|         </div> | ||||
|         <div class="community-info__item"> | ||||
|           <label>联系电话</label> | ||||
|           <span>{{ info.phone }}</span> | ||||
|         </div> | ||||
|       </div> | ||||
|     </div> | ||||
|   </div> | ||||
| </template> | ||||
|  | ||||
| <script> | ||||
| import AMapLoader from '@amap/amap-jsapi-loader' | ||||
| import {mapState} from 'vuex' | ||||
|  | ||||
| export default { | ||||
|   name: 'AppMonitorMapDv', | ||||
|   label: '监护地图', | ||||
|   provide() { | ||||
|     return { | ||||
|       root: this | ||||
|     } | ||||
|   }, | ||||
|   props: { | ||||
|     instance: Function, | ||||
|     dict: Object | ||||
|   }, | ||||
|   data() { | ||||
|     return { | ||||
|       map: null, | ||||
|       community: '', | ||||
|       isShowInfo: false, | ||||
|       info: {}, | ||||
|       satellite: null, | ||||
|       zoom: 11, | ||||
|       choosedId: '', | ||||
|       testItem: [{ | ||||
|         name: '体温', | ||||
|         icon: 'icontiwen', | ||||
|         color: '#6BA3DB' | ||||
|       }, { | ||||
|         name: '心率', | ||||
|         icon: 'iconxinlv', | ||||
|         color: '#72BB5C' | ||||
|       }, { | ||||
|         name: '血压', | ||||
|         icon: 'iconxueya', | ||||
|         color: '#7577CB' | ||||
|       }, { | ||||
|         name: '血氧', | ||||
|         icon: 'iconxueyang', | ||||
|         color: '#FF5656' | ||||
|       }], | ||||
|       testData: [], | ||||
|       center: [] | ||||
|     } | ||||
|   }, | ||||
|   computed: { | ||||
|     ...mapState(['user']), | ||||
|  | ||||
|     userStatus () { | ||||
|       if (this.info.abnormalStatus === '2') { | ||||
|         return '求助' | ||||
|       } | ||||
|  | ||||
|       if (this.info.abnormalStatus === '1') { | ||||
|         return '异常' | ||||
|       } | ||||
|  | ||||
|       if (this.info.abnormalStatus === '0') { | ||||
|         return '正常' | ||||
|       } | ||||
|  | ||||
|       return '-' | ||||
|     }, | ||||
|  | ||||
|     userStatusColor () { | ||||
|       if (this.info.abnormalStatus === '2') { | ||||
|         return { | ||||
|           color: '#FF69DD', | ||||
|           border: '1px solid #FF69DD' | ||||
|         } | ||||
|       } | ||||
|  | ||||
|       if (this.info.abnormalStatus === '1') { | ||||
|         return { | ||||
|           color: '#FF6969', | ||||
|           border: '1px solid #FF6969' | ||||
|         } | ||||
|       } | ||||
|  | ||||
|       return { | ||||
|         color: '#22FF81', | ||||
|         border: '1px solid #22FF81' | ||||
|       } | ||||
|     }, | ||||
|  | ||||
|     userStyle () { | ||||
|       if (this.info.abnormalStatus === '2') { | ||||
|         return { | ||||
|           background: 'rgba(96,8,102,0.80)', | ||||
|           border: '1px solid #FF69DD', | ||||
|           boxShadow: '0 4px 4px 0 #000000, inset 0 0 8px 4px #C312CA' | ||||
|         } | ||||
|       } | ||||
|  | ||||
|       if (this.info.abnormalStatus === '1') { | ||||
|         return { | ||||
|           background: 'rgba(79,14,7,0.80)', | ||||
|           border: '1px solid #FF6969', | ||||
|           boxShadow: '0 4px 4px 0 #000000, inset 0 0 8px 4px #C60E0E' | ||||
|         } | ||||
|       } | ||||
|  | ||||
|       return { | ||||
|         background: 'rgba(8,73,35,0.80)', | ||||
|         border: '1px solid #22FF81', | ||||
|         boxShadow: '0 4px 4px 0 #000000, inset 0 0 8px 4px #15BE55' | ||||
|       } | ||||
|     } | ||||
|   }, | ||||
|  | ||||
|   mounted() { | ||||
|     this.getCorpLocation() | ||||
|   }, | ||||
|  | ||||
|   methods: { | ||||
|     getIdInfo (UUserCard, num) { | ||||
|       if (num == 1) { | ||||
|         var birth = UUserCard.substring(6, 10) + '-' + UUserCard.substring(10, 12) + '-' + UUserCard.substring(12, 14) | ||||
|         return birth | ||||
|       } | ||||
|       if (num == 2) { | ||||
|         if (parseInt(UUserCard.substr(16, 1)) % 2 == 1) { | ||||
|           return '1' | ||||
|         } else { | ||||
|           return '0' | ||||
|         } | ||||
|       } | ||||
|  | ||||
|       if (num == 3) { | ||||
|         var myDate = new Date() | ||||
|         var month = myDate.getMonth() + 1 | ||||
|         var day = myDate.getDate() | ||||
|         var age = myDate.getFullYear() - UUserCard.substring(6, 10) - 1; | ||||
|         if (UUserCard.substring(10, 12) < month || UUserCard.substring(10, 12) == month && UUserCard.substring(12, 14) <= day) { | ||||
|           age ++ | ||||
|         } | ||||
|  | ||||
|         return age | ||||
|       } | ||||
|     }, | ||||
|  | ||||
|     getCorpLocation(){ | ||||
|       this.instance.post("/app/appdvcpconfig/getCorpLocation").then(res=>{ | ||||
|         if(res.code==0){ | ||||
|           this.initMap(res.data); | ||||
|         } | ||||
|       }) | ||||
|     }, | ||||
|  | ||||
|     getList () { | ||||
|       this.instance.post(`/app/appintelligentguardianshipdevice/list`, null, { | ||||
|         params: { | ||||
|           size: 8000, | ||||
|           current: 1 | ||||
|         } | ||||
|       }).then(res => { | ||||
|         if (res.code == 0) { | ||||
|           const points = res.data.records.map(item => { | ||||
|             return { | ||||
|               ...item, | ||||
|               lnglat: [item.lng, item.lat], | ||||
|               id: item.id, | ||||
|               corpId: item.corpId, | ||||
|               areaName:item.areaName, | ||||
|               name: item.name | ||||
|             } | ||||
|           }) | ||||
|  | ||||
|           this.addMakert(points) | ||||
|  | ||||
|           if (this.$route.query.id) { | ||||
|             this.onTreeChange({ | ||||
|               type: '1', | ||||
|               deviceId: this.$route.query.id, | ||||
|               lng: this.$route.query.lng, | ||||
|               lat: this.$route.query.lat | ||||
|             }) | ||||
|           } | ||||
|         } | ||||
|       }) | ||||
|     }, | ||||
|  | ||||
|     formatName (str) { | ||||
|       if (!str) return '' | ||||
|  | ||||
|       return str.substr(str.length - 2) | ||||
|     }, | ||||
|  | ||||
|     getInfo (id) { | ||||
|       this.instance.post(`/app/appintelligentguardianshipdevice/queryMonitorList?deviceId=${id}&type=1`).then(res => { | ||||
|         if (res.code === 0) { | ||||
|           let obj = {} | ||||
|           this.testData = res.data.records.forEach(item => { | ||||
|             obj[item.item] = item | ||||
|           }) | ||||
|  | ||||
|           this.testData = obj | ||||
|         } | ||||
|       }) | ||||
|       this.instance.post(`/app/appintelligentguardianshipdevice/queryDetailById?id=${id}`).then(res => { | ||||
|         if (res.code === 0) { | ||||
|           this.info = res.data | ||||
|           this.info.age = this.getIdInfo(res.data.idNumber, 3) | ||||
|           this.isShowInfo = true | ||||
|         } | ||||
|       }) | ||||
|     }, | ||||
|  | ||||
|     toCenter() { | ||||
|       this.map.setZoomAndCenter(this.zoom, this.center, false, 600) | ||||
|     }, | ||||
|  | ||||
|     renderClusterMarker(context) { | ||||
|       let el = `<div class="polymeric"> | ||||
|         <div class="polymeric-container"> | ||||
|           <p>${context.count}</p> | ||||
|         </div> | ||||
|       </div>` | ||||
|  | ||||
|       let offset = new AMap.Pixel(-9, -9) | ||||
|       context.marker.setContent(el) | ||||
|       context.marker.setOffset(offset) | ||||
|       context.marker.lnglat = context.clusterData[0].lnglat | ||||
|  | ||||
|       context.marker.on('click', e => { | ||||
|         this.map.setZoomAndCenter(this.map.getZoom() + 3, e.target.lnglat, false, 500) | ||||
|       }) | ||||
|     }, | ||||
|  | ||||
|     renderMarker(context) { | ||||
|       const buildId = context.data[0].id | ||||
|  | ||||
|       let el = `<div class="mark mark${context.data[0].abnormalStatus}" id="buildId-${buildId}"> | ||||
|          <div class="mark-contaienr"> | ||||
|             <span>${context.data[0].name}</span> | ||||
|           </div> | ||||
|       </div>` | ||||
|  | ||||
|       context.marker.setContent(el); | ||||
|       context.marker.setAnchor("center") | ||||
|       context.marker.id = `${buildId}` | ||||
|       context.marker.data = JSON.stringify(context.data[0]) | ||||
|       context.marker.lnglat = context.data[0].lnglat | ||||
|  | ||||
|       context.marker.on('click', e => { | ||||
|         this.choosedId = e.target.id | ||||
|         this.getInfo(e.target.id) | ||||
|         context.marker.setContent(el); | ||||
|         document.querySelectorAll('.mark').forEach(el => { | ||||
|           el.classList.remove('mark-active') | ||||
|         }) | ||||
|         document.querySelector(`#buildId-${e.target.id}`).add('mark-active') | ||||
|         this.map.setZoomAndCenter(this.map.getZoom() + 0.000000001, e.target.lnglat, false, 300) | ||||
|       }) | ||||
|     }, | ||||
|  | ||||
|     closeInfo () { | ||||
|       this.info = {} | ||||
|       this.isShowInfo = false | ||||
|       this.choosedId = '' | ||||
|       this.map.setZoom(this.map.getZoom() + 0.0001) | ||||
|     }, | ||||
|  | ||||
|     addMakert(points) { | ||||
|       new AMap.MarkerClusterer(this.map, points, { | ||||
|         gridSize: 60, | ||||
|         maxZoom: 15, | ||||
|         clusterByZoomChange: false, | ||||
|         renderClusterMarker: this.renderClusterMarker, | ||||
|         renderMarker: this.renderMarker | ||||
|       }) | ||||
|     }, | ||||
|  | ||||
|     initMap({lng,lat}) { | ||||
|       this.center = [lng,lat]; | ||||
|       AMapLoader.load({ | ||||
|         key: '54a02a43d9828a8f9cd4f26fe281e74e', | ||||
|         version: '2.0', | ||||
|         plugins: ['AMap.ToolBar', 'AMap.Scale', 'AMap.MouseTool', 'AMap.MarkerClusterer'], | ||||
|         AMapUI: { | ||||
|           version: '1.1', | ||||
|           plugins: [] | ||||
|         } | ||||
|       }).then((AMap) => { | ||||
|         this.map = new AMap.Map('map', { | ||||
|           resizeEnable: true, | ||||
|           zooms: [6, 20], | ||||
|           center: [lng, lat], | ||||
|           zoom: this.zoom, | ||||
|           mapStyle: 'amap://styles/40f6fba77127e061a058f670433a67ec' | ||||
|         }) | ||||
|         this.satellite = new AMap.TileLayer.Satellite() | ||||
|         this.getList() | ||||
|       }) | ||||
|     } | ||||
|   } | ||||
| } | ||||
| </script> | ||||
|  | ||||
| <style lang="scss" scoped> | ||||
|   .map { | ||||
|     position: relative; | ||||
|     width: 100%; | ||||
|     height: 100%; | ||||
|     overflow: hidden; | ||||
|  | ||||
|     .community-info { | ||||
|       position: absolute; | ||||
|       top: 10px; | ||||
|       right: 10px; | ||||
|       width: 400px; | ||||
|       max-height: calc(100% - 20px); | ||||
|       overflow-y: overlay; | ||||
|       overflow-x: hidden; | ||||
|       z-index: 111; | ||||
|       background: rgba(7,11,35,0.50); | ||||
|       border: 1px solid #14345F; | ||||
|  | ||||
|       .community-info__close { | ||||
|         position: absolute; | ||||
|         right: 0; | ||||
|         top: 0; | ||||
|         padding: 16px 12px 0 12px; | ||||
|         font-size: 16px; | ||||
|         color: #8899bb; | ||||
|         cursor: pointer; | ||||
|  | ||||
|         &:hover { | ||||
|           opacity: 0.6; | ||||
|         } | ||||
|       } | ||||
|  | ||||
|       &::-webkit-scrollbar { | ||||
|         width: 6px; | ||||
|         height: 1px; | ||||
|       } | ||||
|  | ||||
|       &::-webkit-scrollbar-thumb { | ||||
|         border-radius: 6px; | ||||
|         background: rgba(144, 147, 153, .5); | ||||
|       } | ||||
|  | ||||
|       .community-info__header { | ||||
|         padding-top: 40px; | ||||
|         text-align: center; | ||||
|  | ||||
|         .user { | ||||
|           display: flex; | ||||
|           align-items: center; | ||||
|           justify-content: center; | ||||
|           width: 50px; | ||||
|           height: 50px; | ||||
|           margin: 0 auto 8px; | ||||
|           border-radius: 50%; | ||||
|           background: #2266FF; | ||||
|  | ||||
|           span { | ||||
|             color: #fff; | ||||
|             font-size: 16px; | ||||
|           } | ||||
|         } | ||||
|  | ||||
|         h2 { | ||||
|           line-height: 24px; | ||||
|           margin-bottom: 12px; | ||||
|           font-weight: Bold; | ||||
|           font-size: 16px; | ||||
|           color: #FFFFFF; | ||||
|         } | ||||
|  | ||||
|         h3, p { | ||||
|           width: 300px; | ||||
|           line-height: 22px; | ||||
|           margin: 0 auto 4px; | ||||
|           font-size: 13px; | ||||
|           color: #82C5FF; | ||||
|           text-align: center; | ||||
|           font-weight: normal; | ||||
|         } | ||||
|  | ||||
|         & > h3 { | ||||
|           line-height: 1.4; | ||||
|           color: #82C5FF; | ||||
|         } | ||||
|  | ||||
|         .community-info__header--info { | ||||
|           display: flex; | ||||
|           flex-wrap: wrap; | ||||
|           padding: 0 20px; | ||||
|  | ||||
|           .community-info__header--info-item { | ||||
|             display: flex; | ||||
|             align-items: center; | ||||
|             justify-content: space-between; | ||||
|             width: 174px; | ||||
|             height: 56px; | ||||
|             margin-bottom: 10px; | ||||
|             padding: 0 12px; | ||||
|             background-image: linear-gradient(270deg, rgba(119,169,255,0.20) 0%, rgba(66,112,255,0.50) 100%); | ||||
|             border-radius: 4px; | ||||
|  | ||||
|             &:nth-of-type(2n - 1) { | ||||
|               margin-right: 10px; | ||||
|             } | ||||
|  | ||||
|             & > i { | ||||
|               position: relative; | ||||
|               top: 2px; | ||||
|               font-style: normal; | ||||
|               color: #fff; | ||||
|               font-size: 16px; | ||||
|               font-weight: 700; | ||||
|             } | ||||
|  | ||||
|             .left { | ||||
|               display: flex; | ||||
|               align-items: center; | ||||
|  | ||||
|               span { | ||||
|                 font-size: 14px; | ||||
|                 color: rgba(130, 197, 255, 1); | ||||
|               } | ||||
|  | ||||
|               div { | ||||
|                 display: flex; | ||||
|                 align-items: center; | ||||
|                 justify-content: center; | ||||
|                 margin-right: 8px; | ||||
|                 width: 24px; | ||||
|                 height: 24px; | ||||
|                 border-radius: 50%; | ||||
|                 background: #6BA3DB; | ||||
|  | ||||
|                 i { | ||||
|                   color: #fff; | ||||
|                   font-size: 16px; | ||||
|                 } | ||||
|               } | ||||
|             } | ||||
|           } | ||||
|         } | ||||
|  | ||||
|         .community-info__header--status { | ||||
|           display: flex; | ||||
|           align-items: center; | ||||
|           justify-content: center; | ||||
|           margin-bottom: 20px; | ||||
|  | ||||
|           div { | ||||
|             display: flex; | ||||
|             align-items: center; | ||||
|             color: #74FF66; | ||||
|           } | ||||
|  | ||||
|           span { | ||||
|             font-size: 14px; | ||||
|           } | ||||
|  | ||||
|           div:first-child { | ||||
|             margin-right: 20px; | ||||
|           } | ||||
|  | ||||
|           i { | ||||
|             position: relative; | ||||
|             margin-right: 2px; | ||||
|             font-size: 16px; | ||||
|           } | ||||
|  | ||||
|           div:last-child { | ||||
|             color: #fff; | ||||
|  | ||||
|             span { | ||||
|               font-size: 12px; | ||||
|             } | ||||
|           } | ||||
|         } | ||||
|       } | ||||
|  | ||||
|       .community-info__wrapper { | ||||
|         padding: 0 20px 40px; | ||||
|  | ||||
|         .community-info__title { | ||||
|           display: flex; | ||||
|           align-items: center; | ||||
|           justify-content: space-between; | ||||
|           margin-bottom: 20px; | ||||
|  | ||||
|           h2 { | ||||
|             position: relative; | ||||
|             width: 169px; | ||||
|             padding: 0 20px; | ||||
|             font-size: 15px; | ||||
|             color: #fff; | ||||
|             font-weight: 700; | ||||
|             background: url(https://cdn.cunwuyun.cn/dvcp/ply/title-bg.png) no-repeat; | ||||
|             background-size: 169px 30px; | ||||
|             background-position-y: -5px; | ||||
|             background-position-x: -10px; | ||||
|           } | ||||
|  | ||||
|           span { | ||||
|             width: 52px; | ||||
|             height: 24px; | ||||
|             line-height: 24px; | ||||
|             color: #fff; | ||||
|             font-size: 14px; | ||||
|             text-align: center; | ||||
|             border-radius: 12px; | ||||
|           } | ||||
|         } | ||||
|  | ||||
|         .community-info__item { | ||||
|           display: flex; | ||||
|           align-items: center; | ||||
|           justify-content: space-between; | ||||
|           height: 40px; | ||||
|           padding: 0 12px; | ||||
|           font-size: 12px; | ||||
|           color: #fff; | ||||
|           background: transparent; | ||||
|  | ||||
|           &:nth-of-type(2n) { | ||||
|             background-image: linear-gradient(270deg, rgba(119,169,255,0.20) 0%, rgba(66,112,255,0.50) 100%); | ||||
|           } | ||||
|  | ||||
|           span { | ||||
|             max-width: 70%; | ||||
|             text-align: right; | ||||
|           } | ||||
|  | ||||
|           label { | ||||
|             flex-shrink: 1; | ||||
|             color: rgba(130, 197, 255, 1); | ||||
|           } | ||||
|         } | ||||
|  | ||||
|         &.community-info__wrapper--last { | ||||
|           .community-info__item { | ||||
|             background: #fff; | ||||
|  | ||||
|             &:nth-of-type(2n) { | ||||
|               background: #F3F6F9; | ||||
|             } | ||||
|           } | ||||
|         } | ||||
|       } | ||||
|     } | ||||
|  | ||||
|     :deep( .ol-zoom ){ | ||||
|       display: none !important; | ||||
|       top: inherit !important; | ||||
|       bottom: 0.5em !important; | ||||
|     } | ||||
|  | ||||
|     div { | ||||
|       box-sizing: border-box; | ||||
|     } | ||||
|  | ||||
|     #map { | ||||
|       width: 100%; | ||||
|       height: 100%; | ||||
|     } | ||||
|  | ||||
|     :deep( .amap-logo), :deep( .amap-copyright ){ | ||||
|       display: none !important; | ||||
|     } | ||||
|  | ||||
|     :deep( .amap-icon ){ | ||||
|       width: 40px !important; | ||||
|       height: 40px !important; | ||||
|  | ||||
|       img { | ||||
|         width: 100%; | ||||
|         height: 100%; | ||||
|       } | ||||
|     } | ||||
|  | ||||
|     .no-more { | ||||
|       display: block; | ||||
|       height: 60px; | ||||
|       line-height: 60px; | ||||
|       margin-top: 2px; | ||||
|       text-align: center; | ||||
|       font-size: 12px; | ||||
|       color: #999; | ||||
|       width: 100%; | ||||
|     } | ||||
|   } | ||||
|  | ||||
|   .community { | ||||
|     display: flex; | ||||
|     align-items: center; | ||||
|     position: relative; | ||||
|     height: 28px; | ||||
|     padding: 0 10px; | ||||
|     background: #0F8F64; | ||||
|     border-radius: 26px; | ||||
|     color: #fff; | ||||
|     font-size: 12px; | ||||
|     cursor: pointer; | ||||
|  | ||||
|     &.color1 { | ||||
|       background: #2266FF; | ||||
|  | ||||
|       em:after { | ||||
|         border-top-color: #2266FF !important; | ||||
|       } | ||||
|     } | ||||
|  | ||||
|     &.color2 { | ||||
|       background: #F46159; | ||||
|  | ||||
|       em:after { | ||||
|         border-top-color: #F46159 !important; | ||||
|       } | ||||
|     } | ||||
|  | ||||
|     em { | ||||
|       position: absolute; | ||||
|       bottom: -6px; | ||||
|       left: 50%; | ||||
|       transform: translate(-50%, 0); | ||||
|  | ||||
|       &::after { | ||||
|         position: absolute; | ||||
|         bottom: -6px; | ||||
|         left: 0; | ||||
|         width: 0; | ||||
|         height: 0; | ||||
|         border: 6px solid #0F8F64; | ||||
|         border-bottom-color: transparent; | ||||
|         border-left-color: transparent; | ||||
|         border-right-color: transparent; | ||||
|         transform: translate(-50%, 0); | ||||
|         overflow: hidden; | ||||
|         content: ' '; | ||||
|       } | ||||
|     } | ||||
|  | ||||
|     i { | ||||
|       padding-right: 2px; | ||||
|       position: relative; | ||||
|       color: #ffc928; | ||||
|       font-size: 16px; | ||||
|       font-style: normal; | ||||
|     } | ||||
|   } | ||||
|  | ||||
|   :deep( .polymeric ){ | ||||
|     display: flex; | ||||
|     position: relative; | ||||
|     align-items: center; | ||||
|     justify-content: center; | ||||
|     width: 62px; | ||||
|     height: 62px; | ||||
|     border-radius: 50%; | ||||
|     cursor: pointer; | ||||
|     user-select: none; | ||||
|  | ||||
|     &.polymeric-active { | ||||
|       .polymeric-container { | ||||
|         background: #F46159; | ||||
|       } | ||||
|  | ||||
|       &::after { | ||||
|         background-color: #F46159; | ||||
|       } | ||||
|     } | ||||
|  | ||||
|     &::after { | ||||
|       position: absolute; | ||||
|       z-index: -1; | ||||
|       width: 62px; | ||||
|       height: 62px; | ||||
|       border-radius: 50%; | ||||
|       -webkit-animation: warn 1s ease-out 0s infinite; | ||||
|       animation: warn 1s ease-out 0s infinite; | ||||
|       background-color: rgba(15, 143, 100, 1); | ||||
|       transform: translate(-50%, -50%); | ||||
|       content: " "; | ||||
|     } | ||||
|  | ||||
|     .polymeric-container { | ||||
|       display: flex; | ||||
|       align-items: center; | ||||
|       justify-content: center; | ||||
|       flex-direction: column; | ||||
|       width: 62px; | ||||
|       height: 62px; | ||||
|       border-radius: 50%; | ||||
|       background: rgba(15, 143, 100, 1); | ||||
|  | ||||
|       p { | ||||
|         text-align: center; | ||||
|         width: 58px; | ||||
|         color: #fff; | ||||
|         font-size: 18px; | ||||
|         overflow: hidden; | ||||
|         text-overflow: ellipsis; | ||||
|         white-space: nowrap; | ||||
|       } | ||||
|  | ||||
|       p:first-child{ | ||||
|         font-size: 14px; | ||||
|       } | ||||
|  | ||||
|       h2 { | ||||
|         color: #fff; | ||||
|         font-weight: normal; | ||||
|         font-size: 12px; | ||||
|       } | ||||
|     } | ||||
|   } | ||||
|  | ||||
|   :deep( .mark){ | ||||
|     display: flex; | ||||
|     align-items: center; | ||||
|     justify-content: center; | ||||
|     position: relative; | ||||
|     user-select: none; | ||||
|     cursor: pointer; | ||||
|     width: 56px; | ||||
|     height: 56px; | ||||
|     background: rgba(108,94,14,0.80); | ||||
|     border: 1px solid #FFDF54; | ||||
|     box-shadow: 0 4px 4px 0 #000000, inset 0 0 8px 4px #D1A818; | ||||
|     border-radius: 50%; | ||||
|     box-sizing: border-box; | ||||
|     font-size: 14px; | ||||
|     color: #FFFFFF; | ||||
|     overflow: hidden; | ||||
|     text-overflow: ellipsis; | ||||
|     white-space: nowrap; | ||||
|     text-shadow: 0 2px 4px rgba(0,0,0,0.50); | ||||
|  | ||||
|     &.mark0 { | ||||
|       background: rgba(8,73,35,0.80); | ||||
|       border: 1px solid #22FF81; | ||||
|       box-shadow: 0 4px 4px 0 #000000, inset 0 0 8px 4px #15BE55; | ||||
|     } | ||||
|  | ||||
|     &.mark1 { | ||||
|       background: rgba(79,14,7,0.80); | ||||
|       border: 1px solid #FF6969; | ||||
|       box-shadow: 0 4px 4px 0 #000000, inset 0 0 8px 4px #C60E0E; | ||||
|     } | ||||
|  | ||||
|     &.mark2 { | ||||
|       background: rgba(96,8,102,0.80); | ||||
|       border: 1px solid #FF69DD; | ||||
|       box-shadow: 0 4px 4px 0 #000000, inset 0 0 8px 4px #C312CA; | ||||
|     } | ||||
|  | ||||
|     .mark-contaienr { | ||||
|       width: 56px; | ||||
|       overflow: hidden; | ||||
|       text-overflow: ellipsis; | ||||
|       white-space: nowrap; | ||||
|       text-align: center; | ||||
|     } | ||||
|  | ||||
|     // &.mark1::after { | ||||
|     //   position: absolute; | ||||
|     //   z-index: -1; | ||||
|     //   width: 100px; | ||||
|     //   height: 100px; | ||||
|     //   border-radius: 50%; | ||||
|     //   -webkit-animation: warn 1s ease-out 0s infinite; | ||||
|     //   animation: warn 1s ease-out 0s infinite; | ||||
|     //   background-color: #FF6969; | ||||
|     //   transform: translate(-50%, -50%); | ||||
|     //   content: " "; | ||||
|     // } | ||||
|  | ||||
|     // &.mark2::after { | ||||
|     //   position: absolute; | ||||
|     //   z-index: -1; | ||||
|     //   width: 100px; | ||||
|     //   height: 100px; | ||||
|     //   border-radius: 50%; | ||||
|     //   -webkit-animation: warn 1s ease-out 0s infinite; | ||||
|     //   animation: warn 1s ease-out 0s infinite; | ||||
|     //   background-color: #FF69DD; | ||||
|     //   transform: translate(-50%, -50%); | ||||
|     //   content: " "; | ||||
|     // } | ||||
|   } | ||||
|  | ||||
|   @-webkit-keyframes warn { | ||||
|     0% { | ||||
|       transform: scale(.5); | ||||
|       opacity: 1 | ||||
|     } | ||||
|  | ||||
|     30% { | ||||
|       opacity: .5 | ||||
|     } | ||||
|  | ||||
|     to { | ||||
|       transform: scale(1.8); | ||||
|       opacity: 0 | ||||
|     } | ||||
|   } | ||||
|  | ||||
|   @keyframes warn { | ||||
|     0% { | ||||
|       transform: scale(.5); | ||||
|       opacity: 1 | ||||
|     } | ||||
|  | ||||
|     30% { | ||||
|       opacity: .5 | ||||
|     } | ||||
|  | ||||
|     to { | ||||
|       transform: scale(1.4); | ||||
|       opacity: 0 | ||||
|     } | ||||
|   } | ||||
| </style> | ||||
| @@ -32,7 +32,7 @@ | ||||
|                 </div> | ||||
|               </div> | ||||
|             </div> | ||||
|             <div class="chart1" style="width: 100%; height: 200px;"></div> | ||||
|             <div class="chart1" style="width: 100%; height: 160px;"></div> | ||||
|           </div> | ||||
|           <div class="item"> | ||||
|             <div class="title">居民群统计</div> | ||||
| @@ -65,24 +65,25 @@ | ||||
|                 </div> | ||||
|               </div> | ||||
|             </div> | ||||
|             <div class="chart2" style="width: 100%; height: 200px;"></div> | ||||
|             <div class="chart2" style="width: 100%; height: 160px;"></div> | ||||
|           </div> | ||||
|           <div class="item item-tags"> | ||||
|             <div class="title">标签人群</div> | ||||
|             <div class="item-bottom"> | ||||
|               <div class="item-bottom__item"> | ||||
|                 <h2>高龄老人</h2> | ||||
|                 <span>{{ tagInfo.elderlyPeople || 0 }}</span> | ||||
|             <div class="title">宣发统计</div> | ||||
|             <div class="item-top xf"> | ||||
|               <div class="item-top__item"> | ||||
|                 <h2>宣发任务数</h2> | ||||
|                 <p>{{ xfInfo.createCount || 0 }}</p> | ||||
|               </div> | ||||
|               <div class="item-bottom__item"> | ||||
|                 <h2>精神病人</h2> | ||||
|                 <span>{{ tagInfo.mentalIllness || 0 }}</span> | ||||
|               <div class="item-top__item"> | ||||
|                 <h2>执行宣发次数</h2> | ||||
|                 <p>{{ xfInfo.executeCount || 0 }}</p> | ||||
|               </div> | ||||
|               <div class="item-bottom__item"> | ||||
|                 <h2>贫困居民</h2> | ||||
|                 <span>{{ tagInfo.poorResidents || 0 }}</span> | ||||
|               <div class="item-top__item"> | ||||
|                 <h2>触达人次</h2> | ||||
|                 <p>{{ xfInfo.receiveCount || 0 }}</p> | ||||
|               </div> | ||||
|             </div> | ||||
|             <div class="chart11" style="width: 336px; margin-top: 10px; height: 160px;"></div> | ||||
|           </div> | ||||
|         </div> | ||||
|         <div class="tab-content__item" v-show="leftIndex === 1"> | ||||
| @@ -229,7 +230,7 @@ | ||||
| <script> | ||||
|   import DonutChart from './components/DonutChart' | ||||
|   import PdGrid from './components/PdGrid' | ||||
|   import * as echarts from 'echarts' | ||||
| 
 | ||||
| 
 | ||||
|   export default { | ||||
|     name: 'AppPdDv', | ||||
| @@ -262,6 +263,7 @@ | ||||
|         groupChatNumber: {}, | ||||
|         dynamicList: [], | ||||
|         rankList: [], | ||||
|         xfInfo: {}, | ||||
|         pointList: [] | ||||
|       } | ||||
|     }, | ||||
| @@ -291,9 +293,22 @@ | ||||
|             this.pointList = res.data | ||||
|           } | ||||
|         }) | ||||
|         this.instance.post(`app/appintegraluser/suffixWeekIntegralSort`).then(res => { | ||||
|         this.instance.post(`app/appintegraluser/userTotalIntegralSort`).then(res => { | ||||
|           if (res.code === 0) { | ||||
|             this.rankList = res.data | ||||
|             this.pointList = res.data | ||||
|           } | ||||
|         }) | ||||
|         this.instance.post(`app/appmasssendingtask/statisticsEffectByPidu`).then(res => { | ||||
|           if (res.code === 0) { | ||||
|             this.xfInfo = res.data | ||||
|             this.initBarChart('.chart11', { | ||||
|               x: res.data.trend.map(v => v.ymd), | ||||
|               value: res.data.trend.map(v => v.createCount), | ||||
|               name: '宣发统计' | ||||
|             }, [ | ||||
|               {offset: 0, color: 'rgba(25, 179, 209, 1)'}, | ||||
|               {offset: 1, color: 'rgba(25, 179, 209, 0)'} | ||||
|             ]) | ||||
|           } | ||||
|         }) | ||||
|         this.instance.post(`/app/wxgroupstatistic/getCustommerNumber`).then(res => { | ||||
| @@ -655,6 +670,39 @@ | ||||
|       } | ||||
|     } | ||||
| 
 | ||||
|     .xf { | ||||
|       display: flex; | ||||
|       align-items: center; | ||||
|       justify-content: space-between; | ||||
| 
 | ||||
|       .item-top__item { | ||||
|         display: flex; | ||||
|         align-items: center; | ||||
|         justify-content: center; | ||||
|         flex-direction: column; | ||||
|         width: 107px; | ||||
|         height: 52px; | ||||
|         line-height: 1; | ||||
|         cursor: pointer; | ||||
|         user-select: none; | ||||
|         background: url(https://cdn.cunwuyun.cn/dvcp/dv/pddv/ql4.png); | ||||
|         background-size: 100% 100%; | ||||
| 
 | ||||
|         h2 { | ||||
|           margin-bottom: 8px; | ||||
|           color: #2AB7D1; | ||||
|           font-size: 12px; | ||||
|         } | ||||
| 
 | ||||
|         p { | ||||
|           font-size: 14px; | ||||
|           color: #fff; | ||||
|           font-weight: bold; | ||||
|           font-style: oblique; | ||||
|         } | ||||
|       } | ||||
|     } | ||||
| 
 | ||||
|     .ql { | ||||
|       display: flex; | ||||
|       align-items: center; | ||||
							
								
								
									
										1257
									
								
								packages/bigscreen/dv/AppPlyDv.vue
									
									
									
									
									
										Normal file
									
								
							
							
						
						
							
								
								
									
										1396
									
								
								packages/bigscreen/dv/AppQxnDv.vue
									
									
									
									
									
										Normal file
									
								
							
							
						
						
							
								
								
									
										1735
									
								
								packages/bigscreen/dv/AppQxnEventDv.vue
									
									
									
									
									
										Normal file
									
								
							
							
						
						
							
								
								
									
										505
									
								
								packages/bigscreen/dv/AppResourceMapDv.vue
									
									
									
									
									
										Normal file
									
								
							
							
						
						| @@ -0,0 +1,505 @@ | ||||
| <template> | ||||
|   <div class="map"> | ||||
|     <div id="map" ref="rootmap" /> | ||||
|     <div class="community-info" v-show="isShowInfo"> | ||||
|       <div class="community-info__close" title="关闭" @click="closeInfo"> | ||||
|         <i class="iconClean iconfont"></i> | ||||
|       </div> | ||||
|       <div class="community-info__header"> | ||||
|         <h2>{{ info.resourceName }}</h2> | ||||
|         <el-tag type="success" size="small" style="margin: 6px 0;">{{ info.categoryName }}</el-tag> | ||||
|         <div>{{ info.areaName }}{{ info.address }}</div> | ||||
|       </div> | ||||
|       <div class="community-info__wrapper"> | ||||
|         <div class="community-info__title"> | ||||
|           <h2>资源信息</h2> | ||||
|         </div> | ||||
|         <p>{{ info.information }}</p> | ||||
|       </div> | ||||
|     </div> | ||||
|   </div> | ||||
| </template> | ||||
|  | ||||
| <script> | ||||
| import AMapLoader from '@amap/amap-jsapi-loader' | ||||
| import {mapState} from 'vuex' | ||||
|  | ||||
| export default { | ||||
|   name: 'AppResourceMapDv', | ||||
|   label: '资源地图', | ||||
|   provide() { | ||||
|     return { | ||||
|       root: this | ||||
|     } | ||||
|   }, | ||||
|   props: { | ||||
|     instance: Function, | ||||
|     dict: Object | ||||
|   }, | ||||
|   data() { | ||||
|     return { | ||||
|       map: null, | ||||
|       community: '', | ||||
|       isShowInfo: false, | ||||
|       info: {}, | ||||
|       satellite: null, | ||||
|       zoom: 11, | ||||
|       choosedId: '', | ||||
|       center: [], | ||||
|       list: [] | ||||
|     } | ||||
|   }, | ||||
|   computed: { | ||||
|     ...mapState(['user']) | ||||
|   }, | ||||
|  | ||||
|   mounted() { | ||||
|     this.getCorpLocation() | ||||
|   }, | ||||
|  | ||||
|   methods: { | ||||
|     getCorpLocation(){ | ||||
|       this.instance.post("/app/appdvcpconfig/getCorpLocation").then(res=>{ | ||||
|         if(res.code==0){ | ||||
|           this.initMap(res.data) | ||||
|         } | ||||
|       }) | ||||
|     }, | ||||
|  | ||||
|     getList () { | ||||
|       this.instance.post(`/app/appresourceinfo/listAll`).then(res => { | ||||
|         if (res.code == 0) { | ||||
|           const points = res.data.map(item => { | ||||
|             return { | ||||
|               ...item, | ||||
|               lnglat: [item.lng, item.lat], | ||||
|               id: item.id, | ||||
|               corpId: item.corpId, | ||||
|               areaName:item.areaName, | ||||
|               name: item.resourceName | ||||
|             } | ||||
|           }) | ||||
|  | ||||
|           this.list = points | ||||
|  | ||||
|           this.addMakert(points) | ||||
|         } | ||||
|       }) | ||||
|     }, | ||||
|  | ||||
|     getInfo (id) { | ||||
|       this.info = this.list.filter(v => id === v.id)[0] | ||||
|       this.isShowInfo = true | ||||
|     }, | ||||
|  | ||||
|     renderClusterMarker(context) { | ||||
|       let el = `<div class="polymeric"> | ||||
|         <div class="polymeric-container"> | ||||
|           <p>${context.count}</p> | ||||
|         </div> | ||||
|       </div>` | ||||
|  | ||||
|       let offset = new AMap.Pixel(-9, -9) | ||||
|       context.marker.setContent(el) | ||||
|       context.marker.setOffset(offset) | ||||
|       context.marker.lnglat = context.clusterData[0].lnglat | ||||
|  | ||||
|       context.marker.on('click', e => { | ||||
|         this.map.setZoomAndCenter(this.map.getZoom() + 3, e.target.lnglat, false, 500) | ||||
|       }) | ||||
|     }, | ||||
|  | ||||
|     renderMarker(context) { | ||||
|       const buildId = context.data[0].id | ||||
|  | ||||
|       let el = `<div id="buildId-${buildId}" class="mark ${buildId === this.choosedId ? 'mark-active' : ''}"> | ||||
|          <img src="${context.data[0].categoryIcon || 'https://cdn.cunwuyun.cn/dvcp/ply/icon.png'}"> | ||||
|       </div>` | ||||
|  | ||||
|       context.marker.setContent(el); | ||||
|       context.marker.setAnchor("center") | ||||
|       context.marker.id = `${buildId}` | ||||
|       context.marker.data = JSON.stringify(context.data[0]) | ||||
|       context.marker.lnglat = context.data[0].lnglat | ||||
|  | ||||
|       context.marker.on('click', e => { | ||||
|         this.choosedId = e.target.id | ||||
|         this.getInfo(e.target.id) | ||||
|         context.marker.setContent(el); | ||||
|         document.querySelectorAll('.mark').forEach(el => { | ||||
|           el.classList.remove('mark-active') | ||||
|         }) | ||||
|         document.querySelector(`#buildId-${e.target.id}`).classList.add('mark-active') | ||||
|       }) | ||||
|     }, | ||||
|  | ||||
|     closeInfo () { | ||||
|       this.info = {} | ||||
|       this.isShowInfo = false | ||||
|       this.choosedId = '' | ||||
|       this.map.setZoom(this.map.getZoom() + 0.0001) | ||||
|     }, | ||||
|  | ||||
|     addMakert(points) { | ||||
|       new AMap.MarkerClusterer(this.map, points, { | ||||
|         gridSize: 60, | ||||
|         maxZoom: 15, | ||||
|         clusterByZoomChange: false, | ||||
|         renderClusterMarker: this.renderClusterMarker, | ||||
|         renderMarker: this.renderMarker | ||||
|       }) | ||||
|     }, | ||||
|  | ||||
|     initMap({lng,lat}) { | ||||
|       this.center = [lng,lat]; | ||||
|       AMapLoader.load({ | ||||
|         key: '54a02a43d9828a8f9cd4f26fe281e74e', | ||||
|         version: '2.0', | ||||
|         plugins: ['AMap.ToolBar', 'AMap.Scale', 'AMap.MouseTool', 'AMap.MarkerClusterer'], | ||||
|         AMapUI: { | ||||
|           version: '1.1', | ||||
|           plugins: [] | ||||
|         } | ||||
|       }).then((AMap) => { | ||||
|         this.map = new AMap.Map('map', { | ||||
|           resizeEnable: true, | ||||
|           zooms: [6, 20], | ||||
|           center: [lng, lat], | ||||
|           zoom: this.zoom, | ||||
|           mapStyle: 'amap://styles/40f6fba77127e061a058f670433a67ec' | ||||
|         }) | ||||
|         this.satellite = new AMap.TileLayer.Satellite() | ||||
|         this.getList() | ||||
|       }) | ||||
|     } | ||||
|   } | ||||
| } | ||||
| </script> | ||||
|  | ||||
| <style lang="scss" scoped> | ||||
|   .map { | ||||
|     position: relative; | ||||
|     width: 100%; | ||||
|     height: 100%; | ||||
|     overflow: hidden; | ||||
|  | ||||
|     .community-info__header { | ||||
|       margin-bottom: 10px; | ||||
|       padding: 12px 20px; | ||||
|       background-image: linear-gradient(270deg, rgba(11, 158, 255, 0.2) 0%, rgba(2, 81, 227, 0.2) 100%); | ||||
|  | ||||
|       h2 { | ||||
|         max-width: 360px; | ||||
|         line-height: 28px; | ||||
|         margin: 0; | ||||
|         color: #fff; | ||||
|         font-size: 20px; | ||||
|         font-weight: 500; | ||||
|       } | ||||
|  | ||||
|       div { | ||||
|         display: flex; | ||||
|         align-items: center; | ||||
|         color: #D2E0FF; | ||||
|         font-size: 12px; | ||||
|       } | ||||
|     } | ||||
|  | ||||
|     .community-info { | ||||
|       position: absolute; | ||||
|       top: 10px; | ||||
|       right: 10px; | ||||
|       width: 400px; | ||||
|       max-height: calc(100% - 20px); | ||||
|       overflow-y: overlay; | ||||
|       overflow-x: hidden; | ||||
|       z-index: 111; | ||||
|       background: rgba(7,11,35,0.50); | ||||
|       border: 1px solid #14345F; | ||||
|  | ||||
|       .community-info__close { | ||||
|         position: absolute; | ||||
|         right: 0; | ||||
|         top: 0; | ||||
|         padding: 16px 12px 0 12px; | ||||
|         font-size: 16px; | ||||
|         color: #8899bb; | ||||
|         cursor: pointer; | ||||
|  | ||||
|         &:hover { | ||||
|           opacity: 0.6; | ||||
|         } | ||||
|       } | ||||
|  | ||||
|       &::-webkit-scrollbar { | ||||
|         width: 6px; | ||||
|         height: 1px; | ||||
|       } | ||||
|  | ||||
|       &::-webkit-scrollbar-thumb { | ||||
|         border-radius: 6px; | ||||
|         background: rgba(144, 147, 153, .5); | ||||
|       } | ||||
|  | ||||
|       .community-info__wrapper { | ||||
|         padding: 0 20px 40px; | ||||
|  | ||||
|         .community-info__title { | ||||
|           display: flex; | ||||
|           align-items: center; | ||||
|           justify-content: space-between; | ||||
|           margin-bottom: 20px; | ||||
|  | ||||
|           h2 { | ||||
|             position: relative; | ||||
|             width: 169px; | ||||
|             padding: 0 20px; | ||||
|             font-size: 15px; | ||||
|             color: #fff; | ||||
|             font-weight: 700; | ||||
|             background: url(https://cdn.cunwuyun.cn/dvcp/ply/title-bg.png) no-repeat; | ||||
|             background-size: 169px 30px; | ||||
|             background-position-y: -5px; | ||||
|             background-position-x: -10px; | ||||
|           } | ||||
|  | ||||
|           span { | ||||
|             width: 52px; | ||||
|             height: 24px; | ||||
|             line-height: 24px; | ||||
|             color: #fff; | ||||
|             font-size: 14px; | ||||
|             text-align: center; | ||||
|             border-radius: 12px; | ||||
|           } | ||||
|         } | ||||
|  | ||||
|         p { | ||||
|           line-height: 1.5; | ||||
|           font-size: 14px; | ||||
|           color: #82C5FF; | ||||
|         } | ||||
|       } | ||||
|     } | ||||
|  | ||||
|     :deep( .ol-zoom ){ | ||||
|       display: none !important; | ||||
|       top: inherit !important; | ||||
|       bottom: 0.5em !important; | ||||
|     } | ||||
|  | ||||
|     div { | ||||
|       box-sizing: border-box; | ||||
|     } | ||||
|  | ||||
|     #map { | ||||
|       width: 100%; | ||||
|       height: 100%; | ||||
|     } | ||||
|  | ||||
|     :deep( .amap-logo), :deep( .amap-copyright ){ | ||||
|       display: none !important; | ||||
|     } | ||||
|  | ||||
|     :deep( .amap-icon ){ | ||||
|       width: 40px !important; | ||||
|       height: 40px !important; | ||||
|  | ||||
|       img { | ||||
|         width: 100%; | ||||
|         height: 100%; | ||||
|       } | ||||
|     } | ||||
|  | ||||
|     .no-more { | ||||
|       display: block; | ||||
|       height: 60px; | ||||
|       line-height: 60px; | ||||
|       margin-top: 2px; | ||||
|       text-align: center; | ||||
|       font-size: 12px; | ||||
|       color: #999; | ||||
|       width: 100%; | ||||
|     } | ||||
|   } | ||||
|  | ||||
|   .community { | ||||
|     display: flex; | ||||
|     align-items: center; | ||||
|     position: relative; | ||||
|     height: 28px; | ||||
|     padding: 0 10px; | ||||
|     background: #0F8F64; | ||||
|     border-radius: 26px; | ||||
|     color: #fff; | ||||
|     font-size: 12px; | ||||
|     cursor: pointer; | ||||
|  | ||||
|     &.color1 { | ||||
|       background: #2266FF; | ||||
|  | ||||
|       em:after { | ||||
|         border-top-color: #2266FF !important; | ||||
|       } | ||||
|     } | ||||
|  | ||||
|     &.color2 { | ||||
|       background: #F46159; | ||||
|  | ||||
|       em:after { | ||||
|         border-top-color: #F46159 !important; | ||||
|       } | ||||
|     } | ||||
|  | ||||
|     em { | ||||
|       position: absolute; | ||||
|       bottom: -6px; | ||||
|       left: 50%; | ||||
|       transform: translate(-50%, 0); | ||||
|  | ||||
|       &::after { | ||||
|         position: absolute; | ||||
|         bottom: -6px; | ||||
|         left: 0; | ||||
|         width: 0; | ||||
|         height: 0; | ||||
|         border: 6px solid #0F8F64; | ||||
|         border-bottom-color: transparent; | ||||
|         border-left-color: transparent; | ||||
|         border-right-color: transparent; | ||||
|         transform: translate(-50%, 0); | ||||
|         overflow: hidden; | ||||
|         content: ' '; | ||||
|       } | ||||
|     } | ||||
|  | ||||
|     i { | ||||
|       padding-right: 2px; | ||||
|       position: relative; | ||||
|       color: #ffc928; | ||||
|       font-size: 16px; | ||||
|       font-style: normal; | ||||
|     } | ||||
|   } | ||||
|  | ||||
|   :deep( .polymeric ){ | ||||
|     display: flex; | ||||
|     position: relative; | ||||
|     align-items: center; | ||||
|     justify-content: center; | ||||
|     width: 62px; | ||||
|     height: 62px; | ||||
|     border-radius: 50%; | ||||
|     cursor: pointer; | ||||
|     user-select: none; | ||||
|  | ||||
|     &.polymeric-active { | ||||
|       .polymeric-container { | ||||
|         background: #F46159; | ||||
|       } | ||||
|  | ||||
|       &::after { | ||||
|         background-color: #F46159; | ||||
|       } | ||||
|     } | ||||
|  | ||||
|     &::after { | ||||
|       position: absolute; | ||||
|       z-index: -1; | ||||
|       width: 62px; | ||||
|       height: 62px; | ||||
|       border-radius: 50%; | ||||
|       -webkit-animation: warn 1s ease-out 0s infinite; | ||||
|       animation: warn 1s ease-out 0s infinite; | ||||
|       background-color: rgba(15, 143, 100, 1); | ||||
|       transform: translate(-50%, -50%); | ||||
|       content: " "; | ||||
|     } | ||||
|  | ||||
|     .polymeric-container { | ||||
|       display: flex; | ||||
|       align-items: center; | ||||
|       justify-content: center; | ||||
|       flex-direction: column; | ||||
|       width: 62px; | ||||
|       height: 62px; | ||||
|       border-radius: 50%; | ||||
|       background: rgba(15, 143, 100, 1); | ||||
|  | ||||
|       p { | ||||
|         text-align: center; | ||||
|         width: 58px; | ||||
|         color: #fff; | ||||
|         font-size: 18px; | ||||
|         overflow: hidden; | ||||
|         text-overflow: ellipsis; | ||||
|         white-space: nowrap; | ||||
|       } | ||||
|  | ||||
|       p:first-child{ | ||||
|         font-size: 14px; | ||||
|       } | ||||
|  | ||||
|       h2 { | ||||
|         color: #fff; | ||||
|         font-weight: normal; | ||||
|         font-size: 12px; | ||||
|       } | ||||
|     } | ||||
|   } | ||||
|  | ||||
|   :deep( .mark){ | ||||
|     position: relative; | ||||
|     user-select: none; | ||||
|     width: 50px; | ||||
|     height: 50px; | ||||
|     border-radius: 50%; | ||||
|     cursor: pointer; | ||||
|  | ||||
|     img { | ||||
|       width: 50px; | ||||
|       height: 50px; | ||||
|       border-radius: 50%; | ||||
|     } | ||||
|  | ||||
|     &:hover { | ||||
|       opacity: 0.8; | ||||
|     } | ||||
|  | ||||
|     &.mark-active { | ||||
|       transform: scale(1.2); | ||||
|     } | ||||
|   } | ||||
|  | ||||
|   @-webkit-keyframes warn { | ||||
|     0% { | ||||
|       transform: scale(.5); | ||||
|       opacity: 1 | ||||
|     } | ||||
|  | ||||
|     30% { | ||||
|       opacity: .5 | ||||
|     } | ||||
|  | ||||
|     to { | ||||
|       transform: scale(1.8); | ||||
|       opacity: 0 | ||||
|     } | ||||
|   } | ||||
|  | ||||
|   @keyframes warn { | ||||
|     0% { | ||||
|       transform: scale(.5); | ||||
|       opacity: 1 | ||||
|     } | ||||
|  | ||||
|     30% { | ||||
|       opacity: .5 | ||||
|     } | ||||
|  | ||||
|     to { | ||||
|       transform: scale(1.4); | ||||
|       opacity: 0 | ||||
|     } | ||||
|   } | ||||
| </style> | ||||
| @@ -439,7 +439,6 @@ export default { | ||||
|         } | ||||
|       }).then(res => { | ||||
|         if (res.code === 0) { | ||||
|           console.log(res) | ||||
|           this.buildList = res.data.records | ||||
|           const points = res.data.records.map(item => { | ||||
|             return { | ||||
| @@ -950,7 +949,7 @@ export default { | ||||
|   } | ||||
| 
 | ||||
| 
 | ||||
|   ::v-deep .ai-list__content--right-wrapper { | ||||
|   :deep( .ai-list__content--right-wrapper ){ | ||||
|     height: 100%; | ||||
|     margin: 0 !important; | ||||
|     background-color: transparent !important; | ||||
| @@ -959,11 +958,11 @@ export default { | ||||
| 
 | ||||
| 
 | ||||
|   .map { | ||||
|     ::v-deep .amap-logo, ::v-deep .amap-copyright { | ||||
|     :deep( .amap-logo), :deep( .amap-copyright ){ | ||||
|       display: none !important; | ||||
|     } | ||||
| 
 | ||||
|     ::v-deep .amap-icon { | ||||
|     :deep( .amap-icon ){ | ||||
|       width: 40px !important; | ||||
|       height: 40px !important; | ||||
| 
 | ||||
| @@ -1080,7 +1079,7 @@ export default { | ||||
|     height: 100%; | ||||
|     overflow: hidden; | ||||
| 
 | ||||
|     ::v-deep .ol-zoom { | ||||
|     :deep( .ol-zoom ){ | ||||
|       display: none !important; | ||||
|       top: inherit !important; | ||||
|       bottom: 0.5em !important; | ||||
| @@ -1096,7 +1095,7 @@ export default { | ||||
|     } | ||||
|   } | ||||
| 
 | ||||
|   ::v-deep .polymeric { | ||||
|   :deep( .polymeric ){ | ||||
|     display: flex; | ||||
|     position: relative; | ||||
|     align-items: center; | ||||
| @@ -1162,7 +1161,7 @@ export default { | ||||
|     } | ||||
|   } | ||||
| 
 | ||||
|   ::v-deep .mark { | ||||
|   :deep( .mark ){ | ||||
|     width: 56px; | ||||
|     height: 56px; | ||||
|     text-align: center; | ||||
| @@ -1173,25 +1172,25 @@ export default { | ||||
|     color: #fff; | ||||
|   } | ||||
| 
 | ||||
|   ::v-deep .online-status0 { | ||||
|   :deep( .online-status0 ){ | ||||
|     background: rgba(8, 73, 35, 0.8); | ||||
|     box-shadow: 0 4px 4px 0 #000000, 0 0 8px 4px #15BE55; | ||||
|     border: 1px solid #22FF81; | ||||
|   } | ||||
| 
 | ||||
|   ::v-deep .online-status1 { | ||||
|   :deep( .online-status1 ){ | ||||
|     background: rgba(79, 14, 7, 0.8); | ||||
|     box-shadow: 0 4px 4px 0 #000000, 0 0 8px 4px #C60E0E; | ||||
|     border: 1px solid #FF6969; | ||||
|   } | ||||
| 
 | ||||
|   ::v-deep .online-status2 { | ||||
|   :deep( .online-status2 ){ | ||||
|     background: rgba(96, 8, 102, 0.8); | ||||
|     box-shadow: 0 4px 4px 0 #000000, 0 0 8px 4px #C312CA; | ||||
|     border: 1px solid #FF69DD; | ||||
|   } | ||||
| 
 | ||||
|   ::v-deep .online-status3 { | ||||
|   :deep( .online-status3 ){ | ||||
|     background: rgba(108, 94, 14, 0.8); | ||||
|     box-shadow: 0 4px 4px 0 #000000, 0 0 8px 4px #D1A818; | ||||
|     border: 1px solid #FFDF54; | ||||
| @@ -287,7 +287,7 @@ export default { | ||||
| 
 | ||||
|       .left-top { | ||||
|         width: 100%; | ||||
|         background-image: url("../assets/videoMonitor/box1.png"); | ||||
|         background-image: url("./assets/videoMonitor/box1.png"); | ||||
|         background-size: 100% 100%; | ||||
|         position: relative; | ||||
|         overflow: hidden; | ||||
| @@ -301,7 +301,7 @@ export default { | ||||
|       .left-bottom { | ||||
|         width: 100%; | ||||
|         height: 311px; | ||||
|         background-image: url("../assets/videoMonitor/box2.png"); | ||||
|         background-image: url("./assets/videoMonitor/box2.png"); | ||||
|         background-size: 100% 100%; | ||||
|         margin-top: 7px; | ||||
|         display: flex; | ||||
| @@ -326,7 +326,7 @@ export default { | ||||
|         display: flex; | ||||
|         align-items: center; | ||||
|         justify-content: center; | ||||
|         background-image: url("../assets/videoMonitor/card.png"); | ||||
|         background-image: url("./assets/videoMonitor/card.png"); | ||||
|         background-size: 100% 100%; | ||||
|         margin-right: 24px; | ||||
| 
 | ||||
| @@ -352,7 +352,7 @@ export default { | ||||
|       .center-bottom { | ||||
|         width: 100%; | ||||
|         height: 789px; | ||||
|         background-image: url("../assets/videoMonitor/middlebox.png"); | ||||
|         background-image: url("./assets/videoMonitor/middlebox.png"); | ||||
|         background-size: 100% 100%; | ||||
|         margin-top: 40px; | ||||
|         position: relative; | ||||
| @@ -398,7 +398,7 @@ export default { | ||||
|       .right-top { | ||||
|         width: 100%; | ||||
|         height: 333px; | ||||
|         background-image: url("../assets/videoMonitor/box3.png"); | ||||
|         background-image: url("./assets/videoMonitor/box3.png"); | ||||
|         background-size: 100% 100%; | ||||
|         position: relative; | ||||
|         overflow: hidden; | ||||
| @@ -432,7 +432,7 @@ export default { | ||||
|       .right-middle, .right-bottom { | ||||
|         width: 100%; | ||||
|         height: 276px; | ||||
|         background-image: url("../assets/videoMonitor/box4.png"); | ||||
|         background-image: url("./assets/videoMonitor/box4.png"); | ||||
|         background-size: 100% 100%; | ||||
|         margin: 19px 0; | ||||
|         position: relative; | ||||
| @@ -457,7 +457,7 @@ export default { | ||||
|           } | ||||
|         } | ||||
| 
 | ||||
|         ::v-deep .AiEchart { | ||||
|         :deep( .AiEchart ){ | ||||
|           width: 251px; | ||||
|           height: 175px; | ||||
|           margin: 11px auto 0; | ||||
| @@ -506,15 +506,15 @@ export default { | ||||
|     color: #FFFFFF; | ||||
|   } | ||||
| 
 | ||||
|   ::v-deep .index { | ||||
|   :deep( .index ){ | ||||
|     background-color: transparent !important; | ||||
|   } | ||||
| 
 | ||||
|   ::v-deep .header { | ||||
|     background: url("../assets/videoMonitor/titlebox.png"); | ||||
|   :deep( .header ){ | ||||
|     background: url("./assets/videoMonitor/titlebox.png"); | ||||
|   } | ||||
| 
 | ||||
|   ::v-deep .row-item div:nth-child(3) { | ||||
|   :deep( .row-item div:nth-child(3) ){ | ||||
|     font-size: 13px; | ||||
|     color: #00CDFF; | ||||
|   } | ||||
| @@ -45,7 +45,7 @@ | ||||
|             <div class="item-top jmq"> | ||||
|               <div class="header"> | ||||
|                 <span>居民群</span> | ||||
|                 <span>{{ isChoose ? '派出所' : '公安局' }}</span> | ||||
|                 <span>{{ isChoose ? '乡镇派出所' : '县级公安局' }}</span> | ||||
|                 <span>群成员</span> | ||||
|               </div> | ||||
|               <div class="item-top__list"> | ||||
| @@ -139,7 +139,7 @@ | ||||
|         <div class="item-wrapper"> | ||||
|           <div class="item-top__item"> | ||||
|             <h2>{{ girdInfo['村民警员'] || 0 }}</h2> | ||||
|             <p>村民警员</p> | ||||
|             <p>村区民警</p> | ||||
|           </div> | ||||
|           <div class="item-top__item"> | ||||
|             <h2>{{ girdInfo['居民群'] || 0 }}</h2> | ||||
| @@ -201,11 +201,11 @@ | ||||
| <script> | ||||
|   import DonutChart from './components/DonutChart' | ||||
|   import XyGrid from './components/XyGrid' | ||||
|   import * as echarts from 'echarts' | ||||
| 
 | ||||
| 
 | ||||
|   export default { | ||||
|     name: 'AppXyDv', | ||||
|     label: '兴义大屏', | ||||
|     label: '黔西南大屏', | ||||
| 
 | ||||
|     props: { | ||||
|       instance: Function, | ||||
| @@ -246,7 +246,7 @@ | ||||
|     }, | ||||
| 
 | ||||
|     mounted () { | ||||
|       document.title = '兴义大屏' | ||||
|       document.title = '黔西南大屏' | ||||
|       this.$nextTick(() => { | ||||
|         if (document.querySelector('.AiDvWrapper .viewPanel')) { | ||||
|           document.querySelector('.AiDvWrapper .viewPanel').style.backgroundImage = 'url(https://cdn.cunwuyun.cn/dvcp/dv/pddv/bg.png)' | ||||
| @@ -344,7 +344,7 @@ | ||||
|             this.initLineChart('.chart2', { | ||||
|               x: res.data['群成员数'].map(v => v.month), | ||||
|               value: res.data['群成员数'].map(v => v.totalNumber), | ||||
|               name: '居民群' | ||||
|               name: '群成员' | ||||
|             }) | ||||
|           } | ||||
|         }) | ||||
| @@ -427,10 +427,12 @@ | ||||
|                 this.list = list.map(v => { | ||||
|                   return { | ||||
|                     ...v, | ||||
|                     rate1: (v['居民群'] / v1 * 100).toFixed(0) + '%', | ||||
|                     rate2: (v['群成员'] / v2 * 100).toFixed(0) + '%' | ||||
|                     rate1: v1 === 0 ? '0%' : (v['居民群'] / v1 * 100).toFixed(0) + '%', | ||||
|                     rate2: v2 === 0 ? '0%' : (v['群成员'] / v2 * 100).toFixed(0) + '%' | ||||
|                   } | ||||
|                 }) | ||||
|               } else { | ||||
|                 this.list = [] | ||||
|               } | ||||
|             } | ||||
|           }) | ||||
| @@ -440,7 +442,7 @@ | ||||
|           if (res.code === 0) { | ||||
|             this.girdInfo = res.data.countInfo | ||||
|             this.gridList = res.data.groupList | ||||
|             if (res.data.typeInfo) { | ||||
|             if (res.data.typeInfo.length) { | ||||
|               this.total = res.data.typeInfo.map(v => v.c).reduce((x, y) => x + y) | ||||
|               this.typeList = res.data.typeInfo.map(v => { | ||||
|                 return { | ||||
| @@ -449,6 +451,9 @@ | ||||
|                 } | ||||
|               }) | ||||
|               this.initChart5('.chart10', this.typeList) | ||||
|             } else { | ||||
|               this.total = 0 | ||||
|               this.typeList = [] | ||||
|             } | ||||
|           } | ||||
|         }) | ||||
							
								
								
									
										1267
									
								
								packages/bigscreen/dv/AppYyxDv.vue
									
									
									
									
									
										Normal file
									
								
							
							
						
						| Before Width: | Height: | Size: 362 KiB After Width: | Height: | Size: 362 KiB | 
| Before Width: | Height: | Size: 11 KiB After Width: | Height: | Size: 11 KiB | 
| Before Width: | Height: | Size: 3.3 KiB After Width: | Height: | Size: 3.3 KiB | 
| Before Width: | Height: | Size: 693 KiB After Width: | Height: | Size: 693 KiB | 
| Before Width: | Height: | Size: 11 KiB After Width: | Height: | Size: 11 KiB | 
| Before Width: | Height: | Size: 24 KiB After Width: | Height: | Size: 24 KiB | 
| Before Width: | Height: | Size: 11 KiB After Width: | Height: | Size: 11 KiB | 
| Before Width: | Height: | Size: 445 B After Width: | Height: | Size: 445 B | 
| Before Width: | Height: | Size: 26 KiB After Width: | Height: | Size: 26 KiB | 
| Before Width: | Height: | Size: 140 KiB After Width: | Height: | Size: 140 KiB | 
| Before Width: | Height: | Size: 4.5 KiB After Width: | Height: | Size: 4.5 KiB | 
| Before Width: | Height: | Size: 3.5 KiB After Width: | Height: | Size: 3.5 KiB | 
| Before Width: | Height: | Size: 3.6 KiB After Width: | Height: | Size: 3.6 KiB | 
| Before Width: | Height: | Size: 3.4 KiB After Width: | Height: | Size: 3.4 KiB | 
| Before Width: | Height: | Size: 3.0 KiB After Width: | Height: | Size: 3.0 KiB | 
| Before Width: | Height: | Size: 8.0 KiB After Width: | Height: | Size: 8.0 KiB | 
| Before Width: | Height: | Size: 5.2 KiB After Width: | Height: | Size: 5.2 KiB | 
| @@ -5,7 +5,7 @@ | ||||
|         ref="tree" | ||||
|         id="tree" | ||||
|         :style="{left: x, top: y, transform: `scale(${scale}) translate(-50%, -50%) `, 'transform-origin': `${0} ${0}`}"> | ||||
|       <VueOkrTree | ||||
|       <ai-okr-tree | ||||
|           :props="props" | ||||
|           node-key="id" | ||||
|           show-collapsable | ||||
| @@ -15,23 +15,16 @@ | ||||
|           ref="VueOkrTree" | ||||
|           @node-click="onNodeClick" | ||||
|           :data="treeData"> | ||||
|       </VueOkrTree> | ||||
|       </ai-okr-tree> | ||||
|     </div> | ||||
|   </div> | ||||
| </template> | ||||
| 
 | ||||
| <script> | ||||
| import AiOkrTree from "dvcp-dv-ui/components/AiOkrTree/AiOkrTree" | ||||
| 
 | ||||
| export default { | ||||
|   name: 'AiGrid', | ||||
| 
 | ||||
|   props: ['instance'], | ||||
| 
 | ||||
|   components: { | ||||
|     VueOkrTree: AiOkrTree | ||||
|   }, | ||||
| 
 | ||||
|   data() { | ||||
|     return { | ||||
|       scale: 1, | ||||
| @@ -169,7 +162,7 @@ export default { | ||||
|     background: linear-gradient(180deg, #42C6CE 0%, #307598 100%); | ||||
|   } | ||||
| 
 | ||||
|   ::v-deep .org-chart-container { | ||||
|   :deep( .org-chart-container ){ | ||||
|     color: #FFFFFF; | ||||
|     font-size: 16px; | ||||
| 
 | ||||
							
								
								
									
										190
									
								
								packages/bigscreen/dv/components/DoughnutChart.vue
									
									
									
									
									
										Normal file
									
								
							
							
						
						| @@ -0,0 +1,190 @@ | ||||
| <template> | ||||
|   <div class="DoughnutChart-wrapper"> | ||||
|     <div class="DoughnutChart" :id="id"> | ||||
|       <canvas :id="canvasId"></canvas> | ||||
|       <div class="DonutChart-text"> | ||||
|         <span>{{ ratio }}%</span> | ||||
|       </div> | ||||
|     </div> | ||||
|     <div class="DoughnutChart-explain"> | ||||
|       <div class="item" v-for="(item, index) in value" :key="index"> | ||||
|         <i></i> | ||||
|         <span :style="labelStyle">{{ item.key }}</span> | ||||
|         <p>{{ item.value }}</p> | ||||
|       </div> | ||||
|     </div> | ||||
|   </div> | ||||
| </template> | ||||
|  | ||||
| <script> | ||||
|   export default { | ||||
|     props: ['ratio', 'value', 'labelStyle'], | ||||
|  | ||||
|     data () { | ||||
|       return { | ||||
|         id: `DonutChart-${Math.ceil(Math.random() * 10000)}`, | ||||
|         canvasId: `DonutChartCanvas-${Math.ceil(Math.random() * 10000)}`, | ||||
|         canvasWidth: 90, | ||||
|         canvasHeight: 90 | ||||
|       } | ||||
|     }, | ||||
|  | ||||
|     watch: { | ||||
|       ratio () { | ||||
|         this.init() | ||||
|       } | ||||
|     }, | ||||
|  | ||||
|     mounted () { | ||||
|       this.$nextTick(() => { | ||||
|         this.init() | ||||
|       }) | ||||
|     }, | ||||
|  | ||||
|     methods: { | ||||
|       drawLine(ctx, options) { | ||||
|         const { beginX, beginY, endX, endY, lineColor, lineWidth } = options | ||||
|         ctx.lineWidth = lineWidth | ||||
|         ctx.strokeStyle = lineColor | ||||
|         ctx.beginPath() | ||||
|         ctx.moveTo(beginX, beginY) | ||||
|         ctx.lineTo(endX, endY) | ||||
|         ctx.closePath() | ||||
|         ctx.stroke() | ||||
|       }, | ||||
|  | ||||
|       angle (a, i, ox, oy, or) { | ||||
|         var hudu = (2 * Math.PI / 360) * a * i | ||||
|         var x = ox + Math.sin(hudu) * or | ||||
|         var y = oy - Math.cos(hudu) * or | ||||
|         return x + '_' + y | ||||
|       }, | ||||
|  | ||||
|       mapColor (value) { | ||||
|         if (value < 25) { | ||||
|           return '#FFC139' | ||||
|         } | ||||
|  | ||||
|         if (value < 50) { | ||||
|           return '#21E03E' | ||||
|         } | ||||
|  | ||||
|         return '#05C8FF' | ||||
|       }, | ||||
|  | ||||
|       init () { | ||||
|         const ctx = document.querySelector(`#${this.canvasId}`).getContext('2d') | ||||
|         const canvasWidth = document.querySelector(`#${this.id}`).offsetWidth | ||||
|         const canvasHeight = document.querySelector(`#${this.id}`).offsetHeight | ||||
|         const angle = this.ratio / 100 * 2 | ||||
|         let radian = 0 | ||||
|  | ||||
|         ctx.width = canvasWidth | ||||
|         ctx.height = canvasHeight | ||||
|         const x = canvasWidth / 2 | ||||
|         const y = canvasHeight / 2 | ||||
|         ctx.lineWidth = 4 | ||||
|         ctx.strokeStyle = 'rgba(102, 121, 138, 0.3)' | ||||
|         ctx.beginPath(); | ||||
|         ctx.arc(x, y, x - 8, 0, 2 * Math.PI) | ||||
|         ctx.stroke() | ||||
|  | ||||
|         ctx.beginPath() | ||||
|         ctx.lineWidth = 4 | ||||
|         var g = ctx.createLinearGradient(0, 0, 0, 80) | ||||
|         g.addColorStop(0, 'rgba(44, 150, 231, 0.8)') | ||||
|         g.addColorStop(1, 'rgba(92, 255, 243, 1)') | ||||
|         ctx.strokeStyle = g | ||||
|  | ||||
|         if (this.ratio < 25) { | ||||
|           radian = 3 / 2 + angle | ||||
|           ctx.arc(x, y, x - 8, Math.PI + Math.PI / 2, Math.PI * radian, false) | ||||
|         } else if (this.ratio === 100) { | ||||
|           ctx.arc(x, y, x - 8, 0, Math.PI * 2) | ||||
|         } else { | ||||
|           radian = (this.ratio - 25) / 100 * 2 | ||||
|           ctx.arc(x, y, x - 8, Math.PI + Math.PI / 2, Math.PI * radian, false) | ||||
|         } | ||||
|         ctx.stroke() | ||||
|  | ||||
|         ctx.beginPath() | ||||
|         ctx.strokeStyle = 'rgba(102, 121, 138, 0.4)' | ||||
|         ctx.lineWidth = 1 | ||||
|         ctx.arc(x, y, x - 15, 0, 2 * Math.PI) | ||||
|         ctx.stroke() | ||||
|       } | ||||
|     } | ||||
|   } | ||||
| </script> | ||||
|  | ||||
| <style lang="scss" scoped> | ||||
|   .DoughnutChart-wrapper { | ||||
|     display: flex; | ||||
|     align-items: center; | ||||
|     justify-content: space-between; | ||||
|     height: 100%; | ||||
|     padding-top: 12px; | ||||
|  | ||||
|     .DoughnutChart-explain { | ||||
|       flex: 1; | ||||
|       margin-left: 10px; | ||||
|  | ||||
|       .item { | ||||
|         display: flex; | ||||
|         align-items: center; | ||||
|  | ||||
|         &:first-child { | ||||
|           margin-bottom: 10px; | ||||
|         } | ||||
|  | ||||
|         i { | ||||
|           width: 8px; | ||||
|           height: 8px; | ||||
|           margin-right: 6px; | ||||
|           border-radius: 50%; | ||||
|           background: #5AF9F0; | ||||
|         } | ||||
|  | ||||
|         span { | ||||
|           width: 78px; | ||||
|           font-weight: 400; | ||||
|           font-size: 14px; | ||||
|           color: #9BB7D4; | ||||
|         } | ||||
|  | ||||
|         p { | ||||
|           font-size: 14px; | ||||
|           color: #FFFFFF; | ||||
|         } | ||||
|  | ||||
|         &:last-child i { | ||||
|           background: rgba(102, 121, 138, 0.3); | ||||
|         } | ||||
|       } | ||||
|     } | ||||
|  | ||||
|  | ||||
|     .DoughnutChart { | ||||
|       position: relative; | ||||
|       width: 90px; | ||||
|       height: 90px; | ||||
|       overflow: hidden; | ||||
|  | ||||
|       .DonutChart-text { | ||||
|         display: flex; | ||||
|         position: absolute; | ||||
|         justify-content: center; | ||||
|         top: 50%; | ||||
|         left: 50%; | ||||
|         z-index: 1; | ||||
|         transform: translate(-50%, -50%); | ||||
|  | ||||
|         span { | ||||
|           font-size: 17px; | ||||
|           font-weight: bold; | ||||
|           color: #02FEFF; | ||||
|         } | ||||
|       } | ||||
|     } | ||||
|   } | ||||
| </style> | ||||
							
								
								
									
										386
									
								
								packages/bigscreen/dv/components/DvMap.vue
									
									
									
									
									
										Normal file
									
								
							
							
						
						| @@ -0,0 +1,386 @@ | ||||
| <template> | ||||
|   <div class="AiDvMap"> | ||||
|     <div class="chart-map" :class="v" style="width: 100%; height: 100%"></div> | ||||
|     <transition name="fade"> | ||||
|       <div class="info" v-if="isShowInfo"> | ||||
|         <div class="info-mask" @click="isShowInfo = false"></div> | ||||
|         <div class="info-content"> | ||||
|           <div class="info-title"> | ||||
|             <h2>{{ title }}</h2> | ||||
|           </div> | ||||
|           <img src="https://cdn.cunwuyun.cn/dvcp/dv/qxn/close.png" @click="isShowInfo = false" /> | ||||
|           <div class="info-wrapper" v-if="type === '0'"> | ||||
|             <div class="info-wrapper__item"> | ||||
|               <label>下属单位:</label> | ||||
|               <span>{{ info['派出所数量'] }}个派出所</span> | ||||
|             </div> | ||||
|             <div class="info-wrapper__item"> | ||||
|               <label>居民群:</label> | ||||
|               <span>{{ info['群数量'] }}</span> | ||||
|             </div> | ||||
|             <div class="info-wrapper__item"> | ||||
|               <label>成员人数:</label> | ||||
|               <span>{{ info['成员总数'] }}</span> | ||||
|             </div> | ||||
|             <div class="info-wrapper__item"> | ||||
|               <label>群人数:</label> | ||||
|               <span>{{ info['群成员数量'] }}</span> | ||||
|             </div> | ||||
|             <div class="info-wrapper__item"> | ||||
|               <label>激活比例:</label> | ||||
|               <span>{{ rate }}</span> | ||||
|             </div> | ||||
|             <div class="info-wrapper__item"> | ||||
|               <label>好友人数:</label> | ||||
|               <span>{{ info['外部联系人数量'] }}</span> | ||||
|             </div> | ||||
|             <div class="info-wrapper__item"> | ||||
|               <label>群主人数:</label> | ||||
|               <span>{{ info['群主人数'] }}</span> | ||||
|             </div> | ||||
|           </div> | ||||
|           <div class="info-wrapper" v-else> | ||||
|             <div class="info-wrapper__item"> | ||||
|               <label>负责人:</label> | ||||
|               <span>{{ info['负责人'] }}</span> | ||||
|             </div> | ||||
|             <div class="info-wrapper__item"> | ||||
|               <label>下属警格数:</label> | ||||
|               <span>{{ info['下属警格数量'] }}</span> | ||||
|             </div> | ||||
|             <div class="info-wrapper__item"> | ||||
|               <label>警格人数:</label> | ||||
|               <span>{{ info['外部联系人数量'] }}</span> | ||||
|             </div> | ||||
|             <div class="info-wrapper__item"> | ||||
|               <label>事件处理率:</label> | ||||
|               <span>{{ rate }}</span> | ||||
|             </div> | ||||
|             <div class="info-wrapper__item"> | ||||
|               <label>待处理:</label> | ||||
|               <span>{{ info['待受理'] }}</span> | ||||
|             </div> | ||||
|             <div class="info-wrapper__item"> | ||||
|               <label>处理中:</label> | ||||
|               <span>{{ info['办理中'] }}</span> | ||||
|             </div> | ||||
|             <div class="info-wrapper__item"> | ||||
|               <label>已办理:</label> | ||||
|               <span>{{ info['已办结'] }}</span> | ||||
|             </div> | ||||
|             <div class="info-wrapper__item"> | ||||
|               <label>事件总数:</label> | ||||
|               <span>{{ info['事件总数'] }}</span> | ||||
|             </div> | ||||
|           </div> | ||||
|         </div> | ||||
|       </div> | ||||
|     </transition> | ||||
|   </div> | ||||
| </template> | ||||
|  | ||||
| <script> | ||||
|  | ||||
|  | ||||
|   export default { | ||||
|     name: 'AiDvMap', | ||||
|  | ||||
|     props: { | ||||
|       instance: Function, | ||||
|       type: String | ||||
|     }, | ||||
|  | ||||
|     data() { | ||||
|       return { | ||||
|         info: {}, | ||||
|         timer: null, | ||||
|         title: '', | ||||
|         v: `AiDvMap-${new Date().getTime()}`, | ||||
|         chart: null, | ||||
|         isShowInfo: false, | ||||
|         geoJSON: require('./geoJSon/qxnGeoJSON.json') | ||||
|       } | ||||
|     }, | ||||
|  | ||||
|     computed: { | ||||
|       rate () { | ||||
|         if (!this.info['事件总数']) { | ||||
|           return '0%' | ||||
|         } | ||||
|  | ||||
|         return ((this.info['事件总数'] - this.info['待受理']) / this.info['事件总数']).toFixed(4) * 100 + '%' | ||||
|       } | ||||
|     }, | ||||
|  | ||||
|     mounted() { | ||||
|       this.$nextTick(() => { | ||||
|         this.initChart() | ||||
|       }) | ||||
|     }, | ||||
|  | ||||
|     methods: { | ||||
|       initChart() { | ||||
|         this.chart = echarts.init(document.querySelector(`.${this.v}`)) | ||||
|         echarts.registerMap('黔西南', this.geoJSON) | ||||
|  | ||||
|         let option = { | ||||
|           geo: [ | ||||
|             { | ||||
|               map: "黔西南", | ||||
|               aspectScale: 1, | ||||
|               zoom: 0.65, | ||||
|               layoutCenter: ["50%", "50%"], | ||||
|               layoutSize: "180%", | ||||
|               show: true, | ||||
|               roam: false, | ||||
|               emphasis: { | ||||
|                 show: true, | ||||
|                 label: { | ||||
|                   textStyle: { | ||||
|                     color: "#FFFFFF" | ||||
|                   }, | ||||
|                 }, | ||||
|                 itemStyle: { | ||||
|                   // areaColor: '#fff' | ||||
|                 } | ||||
|               }, | ||||
|               label: { | ||||
|                 normal: { | ||||
|                   show: true, | ||||
|                   color: '#fff', | ||||
|                   fontSize: '14' | ||||
|                 } | ||||
|               }, | ||||
|               itemStyle: { | ||||
|                 normal: { | ||||
|                   borderColor: "rgba(2, 254, 255, 0.7)", | ||||
|                   borderWidth: 2, | ||||
|                   shadowColor: "rgba(2, 254, 255, 0.1)", | ||||
|                   shadowOffsetY: 10, | ||||
|                   shadowBlur: 120, | ||||
|                   areaColor: "#0f7295", | ||||
|                 }, | ||||
|               } | ||||
|             }, | ||||
|             // 重影 | ||||
|             { | ||||
|               type: "map", | ||||
|               map: "黔西南", | ||||
|               zlevel: -1, | ||||
|               aspectScale: 1, | ||||
|               zoom: 0.65, | ||||
|               layoutCenter: ["50%", "51%"], | ||||
|               layoutSize: "180%", | ||||
|               roam: false, | ||||
|               silent: true, | ||||
|               itemStyle: { | ||||
|                 normal: { | ||||
|                   borderWidth: 1, | ||||
|                   // borderColor:"rgba(17, 149, 216,0.6)", | ||||
|                   borderColor: "rgba(2, 254, 255, 0.3)", | ||||
|                   shadowColor: "rgba(2, 254, 255, 0.3)", | ||||
|                   shadowOffsetY: 5, | ||||
|                   shadowBlur: 15, | ||||
|                   areaColor: "rgba(5,21,35,0.1)", | ||||
|                 }, | ||||
|               }, | ||||
|             }, | ||||
|             { | ||||
|               type: "map", | ||||
|               map: "黔西南", | ||||
|               zlevel: -2, | ||||
|               aspectScale: 1, | ||||
|               zoom: 0.65, | ||||
|               layoutCenter: ["50%", "52%"], | ||||
|               layoutSize: "180%", | ||||
|               roam: false, | ||||
|               silent: true, | ||||
|               itemStyle: { | ||||
|                 normal: { | ||||
|                   borderWidth: 1, | ||||
|                   // borderColor: "rgba(57, 132, 188,0.4)", | ||||
|                   borderColor: "rgba(2, 254, 255, 0.2)", | ||||
|                   shadowColor: "rgba(2, 254, 255, 0.24)", | ||||
|                   shadowOffsetY: 5, | ||||
|                   shadowBlur: 15, | ||||
|                   areaColor: "transpercent", | ||||
|                 }, | ||||
|               }, | ||||
|             }, | ||||
|             { | ||||
|               type: "map", | ||||
|               map: "黔西南", | ||||
|               zlevel: -3, | ||||
|               aspectScale: 1, | ||||
|               zoom: 0.65, | ||||
|               layoutCenter: ["50%", "53%"], | ||||
|               layoutSize: "180%", | ||||
|               roam: false, | ||||
|               silent: true, | ||||
|               itemStyle: { | ||||
|                 normal: { | ||||
|                   borderWidth: 1, | ||||
|                   // borderColor: "rgba(11, 43, 97,0.8)", | ||||
|                   borderColor: "rgba(2, 254, 255, 0.1)", | ||||
|                   shadowColor: "rgba(2, 254, 255, 0.1)", | ||||
|                   shadowOffsetY: 15, | ||||
|                   shadowBlur: 10, | ||||
|                   areaColor: "transpercent", | ||||
|                 }, | ||||
|               }, | ||||
|             } | ||||
|           ], | ||||
|           series: [ | ||||
|             { | ||||
|               type: 'scatter', | ||||
|               map: "黔西南", | ||||
|               coordinateSystem: 'geo', | ||||
|               z: 3, | ||||
|               zlevel: 3, | ||||
|               // symbol: 'none', | ||||
|               symbolSize: 16, | ||||
|               rippleEffect: { | ||||
|                 period: 2, | ||||
|                 scale: 4, | ||||
|                 brushType: 'fill' | ||||
|               }, | ||||
|               label: { | ||||
|                   show: false | ||||
|               }, | ||||
|               roam: false, | ||||
|               itemStyle: { | ||||
|                 normal: { | ||||
|                   areaColor: '#000', | ||||
|                   borderColor: '#a18a3a', | ||||
|                   borderWidth: 1 | ||||
|                 }, | ||||
|                 emphasis: { | ||||
|                   show: false, | ||||
|                   areaColor: null | ||||
|                 } | ||||
|               }, | ||||
|               data: [] | ||||
|             } | ||||
|           ] | ||||
|         } | ||||
|         this.chart.setOption(option) | ||||
|         this.chart.on('click', e => { | ||||
|           this.getInfo(e.name) | ||||
|         }) | ||||
|       }, | ||||
|  | ||||
|       getInfo (name) { | ||||
|         this.title = `${name}公安局` | ||||
|         this.instance.post(`/api/wxgridinfo/comprehensiveOverviewMap`, null, { | ||||
|           params: { | ||||
|             gridName: `${name}公安局`, | ||||
|             corpId: 'wwb182f88f0327b37f' | ||||
|           } | ||||
|         }).then(res => { | ||||
|           if (res.code === 0) { | ||||
|             this.info = res.data | ||||
|             this.isShowInfo = true | ||||
|           } | ||||
|         }) | ||||
|       } | ||||
|     } | ||||
|   } | ||||
| </script> | ||||
|  | ||||
| <style lang="scss" scoped> | ||||
|   .AiDvMap { | ||||
|     display: flex; | ||||
|     align-items: center; | ||||
|     justify-content: center; | ||||
|     width: 100%; | ||||
|     height: 100%; | ||||
|  | ||||
|     .info { | ||||
|       position: fixed; | ||||
|       left: 0; | ||||
|       top: 0; | ||||
|       z-index: 111; | ||||
|       width: 100%; | ||||
|       height: 100%; | ||||
|       overflow: hidden; | ||||
|  | ||||
|       .info-mask { | ||||
|         position: absolute; | ||||
|         left: 0; | ||||
|         top: 0; | ||||
|         z-index: 1; | ||||
|         width: 100%; | ||||
|         height: 100%; | ||||
|         background: rgba($color: #000000, $alpha: 0.1); | ||||
|       } | ||||
|  | ||||
|       .info-content { | ||||
|         position: absolute; | ||||
|         top: 50%; | ||||
|         left: 50%; | ||||
|         z-index: 11; | ||||
|         width: 390px; | ||||
|         height: 262px; | ||||
|         padding: 15px 18px 0; | ||||
|         background: url(https://cdn.cunwuyun.cn/dvcp/dv/qxn/info-bg.png); | ||||
|         background-size: 100% 100%; | ||||
|         transform: translate(-50%, -50%); | ||||
|  | ||||
|         .info-wrapper { | ||||
|           display: flex; | ||||
|           flex-wrap: wrap; | ||||
|           justify-content: space-between; | ||||
|           margin-top: 40px; | ||||
|  | ||||
|           .info-wrapper__item { | ||||
|             display: flex; | ||||
|             align-items: center; | ||||
|             width: 50%; | ||||
|             line-height: 1; | ||||
|             margin-bottom: 20px; | ||||
|  | ||||
|             label { | ||||
|               width: 90px; | ||||
|               margin-right: 10px; | ||||
|               color: #fff; | ||||
|               text-align: right; | ||||
|               font-size: 14px; | ||||
|               font-weight: 500; | ||||
|             } | ||||
|  | ||||
|             span { | ||||
|               flex: 1; | ||||
|               font-size: 14px; | ||||
|               color: #FF8533; | ||||
|             } | ||||
|           } | ||||
|         } | ||||
|  | ||||
|         img { | ||||
|           position: absolute; | ||||
|           top: 30px; | ||||
|           right: 18px; | ||||
|           z-index: 1; | ||||
|           width: 24px; | ||||
|           height: 24px; | ||||
|           cursor: pointer; | ||||
|           transition: all ease 300ms; | ||||
|  | ||||
|           &:hover { | ||||
|             opacity: 0.6; | ||||
|           } | ||||
|         } | ||||
|  | ||||
|         .info-title { | ||||
|           display: flex; | ||||
|           align-items: center; | ||||
|  | ||||
|           h2 { | ||||
|             font-size: 16px; | ||||
|             color: #fff; | ||||
|           } | ||||
|         } | ||||
|       } | ||||
|     } | ||||
|   } | ||||
| </style> | ||||
							
								
								
									
										334
									
								
								packages/bigscreen/dv/components/PlyGird.vue
									
									
									
									
									
										Normal file
									
								
							
							
						
						| @@ -0,0 +1,334 @@ | ||||
| <template> | ||||
|   <div class="PlyGird"> | ||||
|     <div class="pdgrid-title"> | ||||
|       <h2>{{ currGird }}</h2> | ||||
|     </div> | ||||
|     <div class="pdgrid-body"> | ||||
|       <div class="pdgrid-body__item" @click="isShowGrid2 = true"> | ||||
|         <h2>{{ girdNum2 }}</h2> | ||||
|         <div class="bottom"> | ||||
|           <i></i> | ||||
|           <p>{{ girdName2 }}</p> | ||||
|           <i class="right"></i> | ||||
|         </div> | ||||
|       </div> | ||||
|     </div> | ||||
|     <transition name="fade"> | ||||
|       <div class="grid-dialog" v-show="isShowGrid2"> | ||||
|         <div class="mask" @click="isShowGrid2 = false"></div> | ||||
|         <div class="grid-container"> | ||||
|           <h2 :title="girdName2">{{ girdName2 }}</h2> | ||||
|           <div class="grid-list"> | ||||
|             <div | ||||
|               :class="[currIndex2 === index ? 'grid-active' : '']" | ||||
|               v-for="(item, index) in girdInfoList2" | ||||
|               :key="index" | ||||
|               :title="item.girdName" | ||||
|               @click.stop="onGrid2Click(item, index)"> | ||||
|               {{ item.girdName }} | ||||
|             </div> | ||||
|           </div> | ||||
|         </div> | ||||
|       </div> | ||||
|     </transition> | ||||
|   </div> | ||||
| </template> | ||||
|  | ||||
| <script> | ||||
|   export default { | ||||
|     name: 'pdgrid', | ||||
|  | ||||
|     props: ['instance'], | ||||
|  | ||||
|     data () { | ||||
|       return { | ||||
|         isShowGrid2: false, | ||||
|         currIndex2: 0, | ||||
|         girdInfoList2: [], | ||||
|         girdName2: '', | ||||
|         girdNum2: 0, | ||||
|         currGird: '' | ||||
|       } | ||||
|     }, | ||||
|  | ||||
|     mounted () { | ||||
|       this.$nextTick(() => { | ||||
|         document.addEventListener('keydown', this.onKeyDown) | ||||
|       }) | ||||
|       this.getInfo() | ||||
|     }, | ||||
|  | ||||
|     destroyed () { | ||||
|       document.removeEventListener('keydown', this.onKeyDown) | ||||
|     }, | ||||
|  | ||||
|     methods: { | ||||
|       onKeyDown (e) { | ||||
|         if (e.keyCode == 27) { | ||||
|           this.isShowGrid2 = false | ||||
|         } | ||||
|       }, | ||||
|  | ||||
|       onGrid2Click (item, index) { | ||||
|         this.currIndex2 = index | ||||
|         this.girdName2 = item.girdName | ||||
|         this.isShowGrid2 = false | ||||
|         this.$emit('nodeClick', item.id) | ||||
|  | ||||
|         this.currGird = item.girdName | ||||
|         this.getInfo(item.id) | ||||
|       }, | ||||
|  | ||||
|       getInfo (id) { | ||||
|         this.instance.post(`/app/appgirdinfo/queryPlyDetailByGirdId?id=${id || ''}`).then(res => { | ||||
|           if (res.code === 0) { | ||||
|             res.data.girdInfoList2 && (this.girdInfoList2 = res.data.girdInfoList2) | ||||
|             res.data.girdName2 && (this.girdName2 = res.data.girdName2) | ||||
|             res.data.girdNum2 != null && (this.girdNum2 = res.data.girdNum2) | ||||
|             res.data.girdName1 && (this.currGird = res.data.girdName1) | ||||
|  | ||||
|             if (!id) { | ||||
|               this.currIndex2 = res.data.girdInfoList2.findIndex(v => res.data.girdName2 === v.girdName) | ||||
|             } | ||||
|           } | ||||
|         }) | ||||
|       } | ||||
|     } | ||||
|   } | ||||
| </script> | ||||
|  | ||||
| <style lang="scss" scoped> | ||||
|   .PlyGird { | ||||
|     position: relative; | ||||
|     width: 100%; | ||||
|     height: 100%; | ||||
|     overflow: hidden; | ||||
|     box-sizing: border-box; | ||||
|     background: url(https://cdn.cunwuyun.cn/dvcp/dv/pddv/middle-bg.png) no-repeat center; | ||||
|     background-size: contain; | ||||
|  | ||||
|     .fade-enter-active, .fade-leave-active { | ||||
|       transition: opacity .3s ease-in-out; | ||||
|     } | ||||
|     .fade-enter, .fade-leave-to { | ||||
|       opacity: 0; | ||||
|     } | ||||
|  | ||||
|     * { | ||||
|       box-sizing: border-box; | ||||
|     } | ||||
|  | ||||
|     .pdgrid-grid__title { | ||||
|       position: absolute; | ||||
|       top: 40px; | ||||
|       left: 50%; | ||||
|       width: 271px; | ||||
|       height: 53px; | ||||
|       line-height: 53px; | ||||
|       text-align: center; | ||||
|       background: url(https://cdn.cunwuyun.cn/dvcp/dv/pddv/grid-title-sbg.png) no-repeat center; | ||||
|       background-size: 100% 100%; | ||||
|       cursor: pointer; | ||||
|       transform: translateX(-50%); | ||||
|       transition: opacity ease 0.3s; | ||||
|  | ||||
|       &:hover { | ||||
|         opacity: 0.8; | ||||
|       } | ||||
|  | ||||
|       h2 { | ||||
|         width: 182px; | ||||
|         margin: 0 auto; | ||||
|         white-space: nowrap; | ||||
|         overflow: hidden; | ||||
|         text-overflow: ellipsis; | ||||
|         color: #FFFFFF; | ||||
|         font-size: 21px; | ||||
|         text-shadow: 0px 0px 13px rgb(59 182 255 / 80%); | ||||
|         background: #fff; | ||||
|         -webkit-background-clip: text; | ||||
|         -webkit-text-fill-color: transparent; | ||||
|       } | ||||
|     } | ||||
|  | ||||
|     .pdgrid-title { | ||||
|       position: absolute; | ||||
|       top: 200px; | ||||
|       left: 50%; | ||||
|       min-width: 640px; | ||||
|       height: 80px; | ||||
|       line-height: 80px; | ||||
|       text-align: center; | ||||
|       background: url(https://cdn.cunwuyun.cn/dvcp/dv/pddv/middle-titlebg.png) no-repeat center; | ||||
|       background-size: 100% 100%; | ||||
|       transform: translateX(-50%); | ||||
|  | ||||
|       h2 { | ||||
|         color: #FFFFFF; | ||||
|         font-size: 22px; | ||||
|         white-space: nowrap; | ||||
|         text-shadow: 0px 0px 13px rgb(59 182 255 / 80%); | ||||
|         background: #fff; | ||||
|         -webkit-background-clip: text; | ||||
|         -webkit-text-fill-color: transparent; | ||||
|       } | ||||
|     } | ||||
|  | ||||
|     .pdgrid-body { | ||||
|       display: flex; | ||||
|       position: absolute; | ||||
|       justify-content: center; | ||||
|       bottom: 133px; | ||||
|       left: 0; | ||||
|       width: 100%; | ||||
|       padding: 0 112px; | ||||
|  | ||||
|       .pdgrid-body__item { | ||||
|         display: flex; | ||||
|         flex-direction: column; | ||||
|         width: 200px; | ||||
|         height: 187px; | ||||
|         align-items: center; | ||||
|         padding-top: 71px; | ||||
|         cursor: pointer; | ||||
|         background: url(https://cdn.cunwuyun.cn/dvcp/dv/pddv/item-bg.png) no-repeat center; | ||||
|         background-size: 100% 100%; | ||||
|         transition: opacity ease 0.3s; | ||||
|  | ||||
|         &:hover { | ||||
|           opacity: 0.8; | ||||
|         } | ||||
|  | ||||
|         h2 { | ||||
|           font-size: 36px; | ||||
|           color: #FFFFFF; | ||||
|           text-shadow: 0px 0px 13px rgb(59 182 255 / 80%); | ||||
|           background: #fff; | ||||
|           -webkit-background-clip: text; | ||||
|           -webkit-text-fill-color: transparent; | ||||
|         } | ||||
|  | ||||
|         p { | ||||
|           max-width: 164px; | ||||
|           margin-top: 4px; | ||||
|           padding: 0 16px; | ||||
|           font-size: 16px; | ||||
|           color: #FFFFFF; | ||||
|           text-shadow: 0px 0px 13px rgb(59 182 255 / 80%); | ||||
|           background: #fff; | ||||
|           -webkit-background-clip: text; | ||||
|           font-weight: 600; | ||||
|           white-space: nowrap; | ||||
|           overflow: hidden; | ||||
|           text-overflow: ellipsis; | ||||
|           -webkit-text-fill-color: transparent; | ||||
|         } | ||||
|  | ||||
|         .bottom { | ||||
|           display: flex; | ||||
|           align-items: center; | ||||
|  | ||||
|           i { | ||||
|             width: 0px; | ||||
|             height: 0px; | ||||
|             border: 6px solid transparent; | ||||
|             border-top-color: transparent; | ||||
|             border-bottom-color: transparent; | ||||
|             border-left-color: transparent; | ||||
|             border-right-color: #FFCB42; | ||||
|  | ||||
|             &.right { | ||||
|               width: 0px; | ||||
|               height: 0px; | ||||
|               border: 6px solid transparent; | ||||
|               border-top-color: transparent; | ||||
|               border-bottom-color: transparent; | ||||
|               border-left-color: #FFCB42; | ||||
|               border-right-color: transparent; | ||||
|             } | ||||
|           } | ||||
|         } | ||||
|       } | ||||
|     } | ||||
|  | ||||
|     .grid-dialog { | ||||
|       position: fixed; | ||||
|       top: 0; | ||||
|       left: 0; | ||||
|       z-index: 111; | ||||
|       width: 100%; | ||||
|       height: 100%; | ||||
|  | ||||
|       & > .mask { | ||||
|         position: absolute; | ||||
|         left: 0; | ||||
|         top: 0; | ||||
|         z-index: 1; | ||||
|         width: 100%; | ||||
|         height: 100%; | ||||
|         background: rgba(0, 0, 0, 0.5); | ||||
|       } | ||||
|  | ||||
|       .grid-container { | ||||
|         display: flex; | ||||
|         position: absolute; | ||||
|         flex-direction: column; | ||||
|         left: 50%; | ||||
|         top: 50%; | ||||
|         z-index: 2; | ||||
|         width: 640px; | ||||
|         height: 640px; | ||||
|         background: rgba(7,13,41,0.9); | ||||
|         border: 1px solid #144662; | ||||
|         transform: translate(-50%, -50%); | ||||
|  | ||||
|         & > h2 { | ||||
|           width: 100%; | ||||
|           height: 67px; | ||||
|           line-height: 67px; | ||||
|           padding: 0 20px; | ||||
|           text-align: center; | ||||
|           color: #FFFFFF; | ||||
|           font-size: 24px; | ||||
|           white-space: nowrap; | ||||
|           overflow: hidden; | ||||
|           text-overflow: ellipsis; | ||||
|           text-shadow: 0px 0px 13px rgb(59 182 255 / 80%); | ||||
|           background: url(https://cdn.cunwuyun.cn/dvcp/dv/pddv/grid-title-bg.png) no-repeat center; | ||||
|           background-size: 100% 100%; | ||||
|         } | ||||
|  | ||||
|         .grid-list { | ||||
|           flex: 1; | ||||
|           overflow-y: auto; | ||||
|  | ||||
|           & > div { | ||||
|             height: 67px; | ||||
|             line-height: 67px; | ||||
|             padding: 0 20px; | ||||
|             text-align: center; | ||||
|             color: #FFFFFF; | ||||
|             font-size: 27px; | ||||
|             cursor: pointer; | ||||
|             white-space: nowrap; | ||||
|             overflow: hidden; | ||||
|             text-overflow: ellipsis; | ||||
|             transition: all ease 0.5s; | ||||
|  | ||||
|             &.grid-active { | ||||
|               background: linear-gradient(270deg, rgba(0,48,124,0) 0%, #00307C 16%, rgba(0,99,255,0.9100) 50%, rgba(0,48,124,0.8200) 87%, rgba(0,48,124,0) 100%); | ||||
|               box-shadow: inset 0px -1px 0px 0px rgba(16,34,54,1); | ||||
|               text-shadow: 0px 3px 5px rgba(0,0,0,0.5000); | ||||
|             } | ||||
|  | ||||
|             &:hover { | ||||
|               background: linear-gradient(270deg, rgba(0,48,124,0) 0%, #00307C 16%, rgba(0,99,255,0.9100) 50%, rgba(0,48,124,0.8200) 87%, rgba(0,48,124,0) 100%); | ||||
|               box-shadow: inset 0px -1px 0px 0px rgba(16,34,54,1); | ||||
|               text-shadow: 0px 3px 5px rgba(0,0,0,0.5000); | ||||
|             } | ||||
|           } | ||||
|         } | ||||
|       } | ||||
|     } | ||||
|   } | ||||
| </style> | ||||
| @@ -3,9 +3,9 @@ | ||||
|     <div class="pdgrid-title"> | ||||
|       <h2>{{ currGird }}</h2> | ||||
|     </div> | ||||
|     <!-- <div class="pdgrid-grid__title" @click="isShowGrid2 = true"> | ||||
|     <div class="pdgrid-grid__title" @click="isShowGrid2 = true"> | ||||
|       <h2 :title="girdName2">{{ girdName2 }}</h2> | ||||
|     </div> --> | ||||
|     </div> | ||||
|     <div class="pdgrid-body"> | ||||
|       <div class="pdgrid-body__item" @click="isShowGrid3 = true"> | ||||
|         <h2>{{ girdNum3 || 0 }}</h2> | ||||
| @@ -38,14 +38,15 @@ | ||||
|         <div class="grid-container"> | ||||
|           <h2 :title="girdName2">{{ girdName2 }}</h2> | ||||
|           <div class="grid-list"> | ||||
|             <div | ||||
|             <div @click.stop="onGrid2Click(girdId1, girdName2)">{{ girdName2 }}</div> | ||||
|             <!-- <div | ||||
|               :class="[currIndex2 === index ? 'grid-active' : '']" | ||||
|               v-for="(item, index) in girdInfoList2" | ||||
|               :key="index" | ||||
|               :title="item.girdName" | ||||
|               @click.stop="onGrid2Click(item, index)"> | ||||
|               {{ item.girdName }} | ||||
|             </div> | ||||
|             </div> --> | ||||
|           </div> | ||||
|         </div> | ||||
|       </div> | ||||
| @@ -120,6 +121,7 @@ | ||||
|         isShowGrid4: false, | ||||
|         isShowGrid5: false, | ||||
|         currIndex2: 0, | ||||
|         girdId1: '', | ||||
|         currIndex3: 0, | ||||
|         currIndex4: 0, | ||||
|         currIndex5: 0, | ||||
| @@ -134,7 +136,8 @@ | ||||
|         girdNum3: 0, | ||||
|         girdNum4: 0, | ||||
|         girdNum5: 0, | ||||
|         currGird: '' | ||||
|         currGird: '', | ||||
|         girdName1: '' | ||||
|       } | ||||
|     }, | ||||
| 
 | ||||
| @@ -159,9 +162,9 @@ | ||||
|         } | ||||
|       }, | ||||
| 
 | ||||
|       onGrid2Click (item, index) { | ||||
|         this.currIndex2 = index | ||||
|         this.girdName2 = item.girdName | ||||
|       onGrid2Click (id, name) { | ||||
|         // this.currIndex2 = index | ||||
|         // this.girdName2 = item.girdName | ||||
|         this.currIndex3 = -1 | ||||
|         this.currIndex4 = -1 | ||||
|         this.currIndex5 = -1 | ||||
| @@ -169,10 +172,10 @@ | ||||
|         this.girdInfoList3 = [] | ||||
|         this.girdInfoList4 = [] | ||||
|         this.girdInfoList5 = [] | ||||
|         this.$emit('nodeClick', item.id) | ||||
|         this.$emit('nodeClick', id) | ||||
| 
 | ||||
|         this.currGird = item.girdName | ||||
|         this.getInfo(item.id) | ||||
|         this.currGird = name | ||||
|         this.getInfo(id) | ||||
|       }, | ||||
| 
 | ||||
|       onGrid3Click (item, index) { | ||||
| @@ -234,6 +237,11 @@ | ||||
|             res.data.girdName3 && (this.girdName4 = res.data.girdName3) | ||||
|             res.data.girdName4 && (this.girdName5 = res.data.girdName4) | ||||
| 
 | ||||
|             if (this.girdId1) { | ||||
|               this.girdName2 = res.data.girdName1 | ||||
|               this.girdId1 = res.data.girdId1 | ||||
|             } | ||||
| 
 | ||||
|             res.data.girdNum2 != null && (this.girdNum3 = res.data.girdNum2) | ||||
|             res.data.girdNum3 != null && (this.girdNum4 = res.data.girdNum3) | ||||
|             res.data.girdNum4 != null && (this.girdNum5 = res.data.girdNum4) | ||||
							
								
								
									
										498
									
								
								packages/bigscreen/dv/components/YyxGrid.vue
									
									
									
									
									
										Normal file
									
								
							
							
						
						| @@ -0,0 +1,498 @@ | ||||
| <template> | ||||
|   <div class="pdgrid"> | ||||
|     <div class="pdgrid-title"> | ||||
|       <h2>{{ currGird }}</h2> | ||||
|     </div> | ||||
|     <div class="pdgrid-grid__title" @click="isShowGrid2 = true"> | ||||
|       <h2 :title="girdName2">{{ girdName2 }}</h2> | ||||
|     </div> | ||||
|     <div class="pdgrid-body"> | ||||
|       <div class="pdgrid-body__item" @click="isShowGrid3 = true"> | ||||
|         <h2>{{ girdNum3 || 0 }}</h2> | ||||
|         <div class="bottom"> | ||||
|           <i></i> | ||||
|           <p>{{ girdName3 }}</p> | ||||
|           <i class="right"></i> | ||||
|         </div> | ||||
|       </div> | ||||
|       <div class="pdgrid-body__item" @click.stop="isShowGrid4 = true"> | ||||
|         <h2>{{ girdNum4 || 0 }}</h2> | ||||
|         <div class="bottom"> | ||||
|           <i></i> | ||||
|           <p>{{ girdName4 }}</p> | ||||
|           <i class="right"></i> | ||||
|         </div> | ||||
|       </div> | ||||
|       <div class="pdgrid-body__item" @click="isShowGrid5 = true"> | ||||
|         <h2>{{ girdNum5 || 0 }}</h2> | ||||
|         <div class="bottom"> | ||||
|           <i></i> | ||||
|           <p>{{ girdName5 }}</p> | ||||
|           <i class="right"></i> | ||||
|         </div> | ||||
|       </div> | ||||
|     </div> | ||||
|     <transition name="fade"> | ||||
|       <div class="grid-dialog" v-show="isShowGrid2"> | ||||
|         <div class="mask" @click="isShowGrid2 = false"></div> | ||||
|         <div class="grid-container"> | ||||
|           <h2 :title="girdName2">{{ girdName2 }}</h2> | ||||
|           <div class="grid-list"> | ||||
|             <div @click.stop="onGrid2Click(girdId1, girdName2)">{{ girdName2 }}</div> | ||||
|             <!-- <div | ||||
|               :class="[currIndex2 === index ? 'grid-active' : '']" | ||||
|               v-for="(item, index) in girdInfoList2" | ||||
|               :key="index" | ||||
|               :title="item.girdName" | ||||
|               @click.stop="onGrid2Click(item, index)"> | ||||
|               {{ item.girdName }} | ||||
|             </div> --> | ||||
|           </div> | ||||
|         </div> | ||||
|       </div> | ||||
|     </transition> | ||||
|     <transition name="fade"> | ||||
|       <div class="grid-dialog" v-show="isShowGrid3"> | ||||
|         <div class="mask" @click="isShowGrid3 = false"></div> | ||||
|         <div class="grid-container"> | ||||
|           <h2 :title="girdName3">{{ girdName3 }}</h2> | ||||
|           <div class="grid-list"> | ||||
|             <div | ||||
|               :class="[currIndex3 === index ? 'grid-active' : '']" | ||||
|               v-for="(item, index) in girdInfoList3" | ||||
|               :key="index" | ||||
|               :title="item.girdName" | ||||
|               @click.stop="onGrid3Click(item, index)"> | ||||
|               {{ item.girdName }} | ||||
|             </div> | ||||
|           </div> | ||||
|         </div> | ||||
|       </div> | ||||
|     </transition> | ||||
|     <transition name="fade"> | ||||
|       <div class="grid-dialog" v-show="isShowGrid4"> | ||||
|         <div class="mask" @click="isShowGrid4 = false"></div> | ||||
|         <div class="grid-container"> | ||||
|           <h2 :title="girdName4">{{ girdName4 }}</h2> | ||||
|           <div class="grid-list"> | ||||
|             <div | ||||
|               :class="[currIndex4 === index ? 'grid-active' : '']" | ||||
|               v-for="(item, index) in girdInfoList4" | ||||
|               :key="index" | ||||
|               :title="item.girdName" | ||||
|               @click.stop="onGrid4Click(item, index)"> | ||||
|               {{ item.girdName }} | ||||
|             </div> | ||||
|           </div> | ||||
|         </div> | ||||
|       </div> | ||||
|     </transition> | ||||
|     <transition name="fade"> | ||||
|       <div class="grid-dialog" v-show="isShowGrid5"> | ||||
|         <div class="mask" @click="isShowGrid5 = false"></div> | ||||
|         <div class="grid-container"> | ||||
|           <h2 :title="girdName5">{{ girdName5 }}</h2> | ||||
|           <div class="grid-list"> | ||||
|             <div | ||||
|               :class="[currIndex5 === index ? 'grid-active' : '']" | ||||
|               v-for="(item, index) in girdInfoList5" | ||||
|               :key="index" | ||||
|               :title="item.girdName" | ||||
|               @click.stop="onGrid5Click(item, index)"> | ||||
|               {{ item.girdName }} | ||||
|             </div> | ||||
|           </div> | ||||
|         </div> | ||||
|       </div> | ||||
|     </transition> | ||||
|   </div> | ||||
| </template> | ||||
|  | ||||
| <script> | ||||
|   export default { | ||||
|     name: 'XyGrid', | ||||
|  | ||||
|     props: ['instance'], | ||||
|  | ||||
|     data () { | ||||
|       return { | ||||
|         isShowGrid2: false, | ||||
|         isShowGrid3: false, | ||||
|         isShowGrid4: false, | ||||
|         isShowGrid5: false, | ||||
|         currIndex2: 0, | ||||
|         girdId1: '', | ||||
|         currIndex3: 0, | ||||
|         currIndex4: 0, | ||||
|         currIndex5: 0, | ||||
|         girdInfoList2: [], | ||||
|         girdInfoList3: [], | ||||
|         girdInfoList4: [], | ||||
|         girdInfoList5: [], | ||||
|         girdName2: '', | ||||
|         girdName3: '', | ||||
|         girdName4: '', | ||||
|         girdName5: '', | ||||
|         girdNum3: 0, | ||||
|         girdNum4: 0, | ||||
|         girdNum5: 0, | ||||
|         currGird: '', | ||||
|         girdName1: '' | ||||
|       } | ||||
|     }, | ||||
|  | ||||
|     mounted () { | ||||
|       this.$nextTick(() => { | ||||
|         document.addEventListener('keydown', this.onKeyDown) | ||||
|       }) | ||||
|       this.getInfo() | ||||
|     }, | ||||
|  | ||||
|     destroyed () { | ||||
|       document.removeEventListener('keydown', this.onKeyDown) | ||||
|     }, | ||||
|  | ||||
|     methods: { | ||||
|       onKeyDown (e) { | ||||
|         if (e.keyCode == 27) { | ||||
|           this.isShowGrid2 = false | ||||
|           this.isShowGrid3 = false | ||||
|           this.isShowGrid4 = false | ||||
|           this.isShowGrid5 = false | ||||
|         } | ||||
|       }, | ||||
|  | ||||
|       onGrid2Click (id, name) { | ||||
|         // this.currIndex2 = index | ||||
|         // this.girdName2 = item.girdName | ||||
|         this.currIndex3 = -1 | ||||
|         this.currIndex4 = -1 | ||||
|         this.currIndex5 = -1 | ||||
|         this.isShowGrid2 = false | ||||
|         this.girdInfoList3 = [] | ||||
|         this.girdInfoList4 = [] | ||||
|         this.girdInfoList5 = [] | ||||
|         this.$emit('nodeClick', id) | ||||
|  | ||||
|         this.currGird = name | ||||
|         this.getInfo(id) | ||||
|       }, | ||||
|  | ||||
|       onGrid3Click (item, index) { | ||||
|         this.currIndex3 = index | ||||
|         this.girdName3 = item.girdName | ||||
|         this.currIndex4 = -1 | ||||
|         this.currIndex5 = -1 | ||||
|         this.girdNum3 = 1 | ||||
|         this.isShowGrid3 = false | ||||
|         this.$emit('nodeClick', { | ||||
|           id: item.id, | ||||
|           level: 2 | ||||
|         }) | ||||
|         this.girdInfoList4 = [] | ||||
|         this.girdInfoList5 = [] | ||||
|         this.currGird = item.girdName | ||||
|         this.getInfo(item.id) | ||||
|       }, | ||||
|  | ||||
|       onGrid4Click (item, index) { | ||||
|         this.currIndex4 = index | ||||
|         this.girdName4 = item.girdName | ||||
|         this.currIndex5 = -1 | ||||
|         this.girdNum4 = 1 | ||||
|         this.isShowGrid4 = false | ||||
|         this.$emit('nodeClick', { | ||||
|           id: item.id, | ||||
|           level: 3 | ||||
|         }) | ||||
|         this.girdInfoList5 = [] | ||||
|  | ||||
|         this.currGird = item.girdName | ||||
|         this.getInfo(item.id) | ||||
|       }, | ||||
|  | ||||
|       onGrid5Click (item, index) { | ||||
|         this.currIndex5 = index | ||||
|         this.girdName5 = item.girdName | ||||
|         this.isShowGrid5 = false | ||||
|         this.girdNum5 = 1 | ||||
|         this.$emit('nodeClick', { | ||||
|           id: item.id, | ||||
|           level: 4 | ||||
|         }) | ||||
|  | ||||
|         this.currGird = item.girdName | ||||
|         this.getInfo(item.id) | ||||
|       }, | ||||
|  | ||||
|       getInfo (id) { | ||||
|         this.instance.post(`/app/yyx_appgirdinfo/queryGirdInfo?id=${id || ''}`).then(res => { | ||||
|           if (res.code === 0) { | ||||
|             res.data.girdInfoList2 && (this.girdInfoList3 = res.data.girdInfoList2) | ||||
|             res.data.girdInfoList3 && (this.girdInfoList4 = res.data.girdInfoList3) | ||||
|             res.data.girdInfoList4 && (this.girdInfoList5 = res.data.girdInfoList4) | ||||
|  | ||||
|             res.data.girdName1 && (this.girdName2 = res.data.girdName1) | ||||
|             res.data.girdName2 && (this.girdName3 = res.data.girdName2) | ||||
|             res.data.girdName3 && (this.girdName4 = res.data.girdName3) | ||||
|             res.data.girdName4 && (this.girdName5 = res.data.girdName4) | ||||
|  | ||||
|             if (this.girdId1) { | ||||
|               this.girdName2 = res.data.girdName1 | ||||
|               this.girdId1 = res.data.girdId1 | ||||
|             } | ||||
|  | ||||
|             res.data.girdNum2 != null && (this.girdNum3 = res.data.girdNum2) | ||||
|             res.data.girdNum3 != null && (this.girdNum4 = res.data.girdNum3) | ||||
|             res.data.girdNum4 != null && (this.girdNum5 = res.data.girdNum4) | ||||
|  | ||||
|             if (!id) { | ||||
|               this.currGird = res.data.girdName1 | ||||
|             } | ||||
|           } | ||||
|         }) | ||||
|       } | ||||
|     } | ||||
|   } | ||||
| </script> | ||||
|  | ||||
| <style lang="scss"> | ||||
|   .pdgrid { | ||||
|     position: relative; | ||||
|     width: 100%; | ||||
|     height: 100%; | ||||
|     overflow: hidden; | ||||
|     box-sizing: border-box; | ||||
|     background: url(https://cdn.cunwuyun.cn/dvcp/dv/pddv/middle-bg.png) no-repeat center; | ||||
|     background-size: contain; | ||||
|  | ||||
|     .fade-enter-active, .fade-leave-active { | ||||
|       transition: opacity .3s ease-in-out; | ||||
|     } | ||||
|     .fade-enter, .fade-leave-to { | ||||
|       opacity: 0; | ||||
|     } | ||||
|  | ||||
|     * { | ||||
|       box-sizing: border-box; | ||||
|     } | ||||
|  | ||||
|     .pdgrid-grid__title { | ||||
|       position: absolute; | ||||
|       top: 40px; | ||||
|       left: 50%; | ||||
|       width: 271px; | ||||
|       height: 53px; | ||||
|       line-height: 53px; | ||||
|       text-align: center; | ||||
|       background: url(https://cdn.cunwuyun.cn/dvcp/dv/pddv/grid-title-sbg.png) no-repeat center; | ||||
|       background-size: 100% 100%; | ||||
|       cursor: pointer; | ||||
|       transform: translateX(-50%); | ||||
|       transition: opacity ease 0.3s; | ||||
|  | ||||
|       &:hover { | ||||
|         opacity: 0.8; | ||||
|       } | ||||
|  | ||||
|       h2 { | ||||
|         width: 182px; | ||||
|         margin: 0 auto; | ||||
|         white-space: nowrap; | ||||
|         overflow: hidden; | ||||
|         text-overflow: ellipsis; | ||||
|         color: #FFFFFF; | ||||
|         font-size: 21px; | ||||
|         text-shadow: 0px 0px 13px rgb(59 182 255 / 80%); | ||||
|         background: #fff; | ||||
|         -webkit-background-clip: text; | ||||
|         -webkit-text-fill-color: transparent; | ||||
|       } | ||||
|     } | ||||
|  | ||||
|     .pdgrid-title { | ||||
|       position: absolute; | ||||
|       top: 200px; | ||||
|       left: 50%; | ||||
|       min-width: 640px; | ||||
|       height: 80px; | ||||
|       line-height: 80px; | ||||
|       text-align: center; | ||||
|       background: url(https://cdn.cunwuyun.cn/dvcp/dv/pddv/middle-titlebg.png) no-repeat center; | ||||
|       background-size: 100% 100%; | ||||
|       transform: translateX(-50%); | ||||
|  | ||||
|       h2 { | ||||
|         color: #FFFFFF; | ||||
|         font-size: 22px; | ||||
|         white-space: nowrap; | ||||
|         text-shadow: 0px 0px 13px rgb(59 182 255 / 80%); | ||||
|         background: #fff; | ||||
|         -webkit-background-clip: text; | ||||
|         -webkit-text-fill-color: transparent; | ||||
|       } | ||||
|     } | ||||
|  | ||||
|     .pdgrid-body { | ||||
|       display: flex; | ||||
|       position: absolute; | ||||
|       justify-content: space-between; | ||||
|       bottom: 200px; | ||||
|       left: 0; | ||||
|       width: 100%; | ||||
|       padding: 0 112px; | ||||
|  | ||||
|       .pdgrid-body__item { | ||||
|         display: flex; | ||||
|         flex-direction: column; | ||||
|         width: 200px; | ||||
|         height: 187px; | ||||
|         align-items: center; | ||||
|         padding-top: 71px; | ||||
|         cursor: pointer; | ||||
|         background: url(https://cdn.cunwuyun.cn/dvcp/dv/pddv/item-bg.png) no-repeat center; | ||||
|         background-size: 100% 100%; | ||||
|         transition: opacity ease 0.3s; | ||||
|  | ||||
|         &:hover { | ||||
|           opacity: 0.8; | ||||
|         } | ||||
|  | ||||
|         &:nth-of-type(2) { | ||||
|           position: relative; | ||||
|           top: 67px; | ||||
|         } | ||||
|  | ||||
|         h2 { | ||||
|           font-size: 36px; | ||||
|           color: #FFFFFF; | ||||
|           text-shadow: 0px 0px 13px rgb(59 182 255 / 80%); | ||||
|           background: #fff; | ||||
|           -webkit-background-clip: text; | ||||
|           -webkit-text-fill-color: transparent; | ||||
|         } | ||||
|  | ||||
|         p { | ||||
|           max-width: 164px; | ||||
|           margin-top: 4px; | ||||
|           padding: 0 16px; | ||||
|           font-size: 16px; | ||||
|           color: #FFFFFF; | ||||
|           text-shadow: 0px 0px 13px rgb(59 182 255 / 80%); | ||||
|           background: #fff; | ||||
|           -webkit-background-clip: text; | ||||
|           font-weight: 600; | ||||
|           white-space: nowrap; | ||||
|           overflow: hidden; | ||||
|           text-overflow: ellipsis; | ||||
|           -webkit-text-fill-color: transparent; | ||||
|         } | ||||
|  | ||||
|         .bottom { | ||||
|           display: flex; | ||||
|           align-items: center; | ||||
|  | ||||
|           i { | ||||
|             width: 0px; | ||||
|             height: 0px; | ||||
|             border: 6px solid transparent; | ||||
|             border-top-color: transparent; | ||||
|             border-bottom-color: transparent; | ||||
|             border-left-color: transparent; | ||||
|             border-right-color: #FFCB42; | ||||
|  | ||||
|             &.right { | ||||
|               width: 0px; | ||||
|               height: 0px; | ||||
|               border: 6px solid transparent; | ||||
|               border-top-color: transparent; | ||||
|               border-bottom-color: transparent; | ||||
|               border-left-color: #FFCB42; | ||||
|               border-right-color: transparent; | ||||
|             } | ||||
|           } | ||||
|         } | ||||
|       } | ||||
|     } | ||||
|  | ||||
|     .grid-dialog { | ||||
|       position: fixed; | ||||
|       top: 0; | ||||
|       left: 0; | ||||
|       z-index: 111; | ||||
|       width: 100%; | ||||
|       height: 100%; | ||||
|  | ||||
|       & > .mask { | ||||
|         position: absolute; | ||||
|         left: 0; | ||||
|         top: 0; | ||||
|         z-index: 1; | ||||
|         width: 100%; | ||||
|         height: 100%; | ||||
|         background: rgba(0, 0, 0, 0.5); | ||||
|       } | ||||
|  | ||||
|       .grid-container { | ||||
|         display: flex; | ||||
|         position: absolute; | ||||
|         flex-direction: column; | ||||
|         left: 50%; | ||||
|         top: 50%; | ||||
|         z-index: 2; | ||||
|         width: 640px; | ||||
|         height: 640px; | ||||
|         background: rgba(7,13,41,0.9); | ||||
|         border: 1px solid #144662; | ||||
|         transform: translate(-50%, -50%); | ||||
|  | ||||
|         & > h2 { | ||||
|           width: 100%; | ||||
|           height: 67px; | ||||
|           line-height: 67px; | ||||
|           padding: 0 20px; | ||||
|           text-align: center; | ||||
|           color: #FFFFFF; | ||||
|           font-size: 24px; | ||||
|           white-space: nowrap; | ||||
|           overflow: hidden; | ||||
|           text-overflow: ellipsis; | ||||
|           text-shadow: 0px 0px 13px rgb(59 182 255 / 80%); | ||||
|           background: url(https://cdn.cunwuyun.cn/dvcp/dv/pddv/grid-title-bg.png) no-repeat center; | ||||
|           background-size: 100% 100%; | ||||
|         } | ||||
|  | ||||
|         .grid-list { | ||||
|           flex: 1; | ||||
|           overflow-y: auto; | ||||
|  | ||||
|           & > div { | ||||
|             height: 67px; | ||||
|             line-height: 67px; | ||||
|             padding: 0 20px; | ||||
|             text-align: center; | ||||
|             color: #FFFFFF; | ||||
|             font-size: 27px; | ||||
|             cursor: pointer; | ||||
|             white-space: nowrap; | ||||
|             overflow: hidden; | ||||
|             text-overflow: ellipsis; | ||||
|             transition: all ease 0.5s; | ||||
|  | ||||
|             &.grid-active { | ||||
|               background: linear-gradient(270deg, rgba(0,48,124,0) 0%, #00307C 16%, rgba(0,99,255,0.9100) 50%, rgba(0,48,124,0.8200) 87%, rgba(0,48,124,0) 100%); | ||||
|               box-shadow: inset 0px -1px 0px 0px rgba(16,34,54,1); | ||||
|               text-shadow: 0px 3px 5px rgba(0,0,0,0.5000); | ||||
|             } | ||||
|  | ||||
|             &:hover { | ||||
|               background: linear-gradient(270deg, rgba(0,48,124,0) 0%, #00307C 16%, rgba(0,99,255,0.9100) 50%, rgba(0,48,124,0.8200) 87%, rgba(0,48,124,0) 100%); | ||||
|               box-shadow: inset 0px -1px 0px 0px rgba(16,34,54,1); | ||||
|               text-shadow: 0px 3px 5px rgba(0,0,0,0.5000); | ||||
|             } | ||||
|           } | ||||
|         } | ||||
|       } | ||||
|     } | ||||
|   } | ||||
| </style> | ||||
| @@ -1,4 +1,4 @@ | ||||
| export default { | ||||
| export const pieChart2 = { | ||||
|   legend: { | ||||
|     bottom: 0, | ||||
|     itemGap: 14, | ||||
| @@ -94,3 +94,94 @@ export default { | ||||
|     ) | ||||
|   } | ||||
| } | ||||
| export const barChart1 = { | ||||
|   legend: { | ||||
|     right: 0, | ||||
|     itemHeight: 5, | ||||
|     itemWidth: 16, | ||||
|     textStyle: { color: '#fff' } | ||||
|   }, | ||||
|   yAxis: { | ||||
|     nameGap: 23, | ||||
|     minInterval: 1, | ||||
|     splitLine: { lineStyle: { color: 'rgba(255,255,255,.2)', type: 'dashed' } }, | ||||
|     axisLabel: { color: '#fff' }, | ||||
|     axisPointer: { show: false } | ||||
|   }, | ||||
|   axisPointer: { | ||||
|     type: 'shadow', | ||||
|     triggerTooltip: false, | ||||
|     shadowStyle: { color: 'rgba(46, 153, 255, .2)' } | ||||
|   }, | ||||
|   color: [ | ||||
|     { | ||||
|       type: 'linear', | ||||
|       x: 0, | ||||
|       x2: 0, | ||||
|       y: 0, | ||||
|       y2: 1, | ||||
|       colorStops: [ | ||||
|         { offset: 0, color: 'rgba(66, 187, 255, 1)' }, | ||||
|         { offset: 1, color: 'rgba(37, 143, 255, 0.2)' } | ||||
|       ] | ||||
|     }, | ||||
|     { | ||||
|       type: 'linear', | ||||
|       x: 0, | ||||
|       x2: 0, | ||||
|       y: 0, | ||||
|       y2: 1, | ||||
|       colorStops: [ | ||||
|         { offset: 0, color: 'rgba(66, 255, 254, 1)' }, | ||||
|         { offset: 1, color: 'rgba(37, 255, 246, 0.2)' } | ||||
|       ] | ||||
|     }, | ||||
|     { | ||||
|       type: 'linear', | ||||
|       x: 0, | ||||
|       x2: 0, | ||||
|       y: 0, | ||||
|       y2: 1, | ||||
|       colorStops: [ | ||||
|         { offset: 0, color: 'rgba(97, 253, 185, 1)' }, | ||||
|         { offset: 1, color: 'rgba(97, 253, 185, 0.2)' } | ||||
|       ] | ||||
|     }, | ||||
|     { | ||||
|       type: 'linear', | ||||
|       x: 0, | ||||
|       x2: 0, | ||||
|       y: 0, | ||||
|       y2: 1, | ||||
|       colorStops: [ | ||||
|         { offset: 0, color: 'rgba(253, 108, 57, 1)' }, | ||||
|         { offset: 1, color: 'rgba(253, 108, 57, 0.2)' } | ||||
|       ] | ||||
|     }, | ||||
|     { | ||||
|       type: 'linear', | ||||
|       x: 0, | ||||
|       x2: 0, | ||||
|       y: 0, | ||||
|       y2: 1, | ||||
|       colorStops: [ | ||||
|         { offset: 0, color: 'rgba(248, 187, 25, 1)' }, | ||||
|         { offset: 1, color: 'rgba(55, 39, 5, 1)' } | ||||
|       ] | ||||
|     } | ||||
|   ], | ||||
|   daemon: { | ||||
|     type: 'bar', | ||||
|     label: { | ||||
|       show: true, | ||||
|       position: 'top', | ||||
|       color: '#fff', | ||||
|       formatter: e => { | ||||
|         return e.data[e.seriesName] || '' | ||||
|       } | ||||
|     }, | ||||
|     barWidth: 16, | ||||
|     barCategoryGap: 40, | ||||
|     itemStyle: {} | ||||
|   } | ||||
| } | ||||
							
								
								
									
										1
									
								
								packages/bigscreen/dv/components/geoJSon/qxnGeoJSON.json
									
									
									
									
									
										Normal file
									
								
							
							
						
						| @@ -307,7 +307,7 @@ export default { | ||||
|       .addressBook-left__list--search { | ||||
|         flex: 1; | ||||
|  | ||||
|         ::v-deep input { | ||||
|         :deep( input ){ | ||||
|           width: 100%; | ||||
|         } | ||||
|       } | ||||
| @@ -324,7 +324,7 @@ export default { | ||||
|       font-size: 14px; | ||||
|     } | ||||
|  | ||||
|     ::v-deep .el-tree { | ||||
|     :deep( .el-tree ){ | ||||
|       background: transparent; | ||||
|  | ||||
|       .el-tree-node__expand-icon.is-leaf { | ||||
| @@ -369,7 +369,7 @@ export default { | ||||
|     } | ||||
|   } | ||||
|  | ||||
|   ::v-deep .ai-list__content--left { | ||||
|   :deep( .ai-list__content--left ){ | ||||
|     margin-right: 2px; | ||||
|   } | ||||
|  | ||||
| @@ -421,7 +421,7 @@ export default { | ||||
|     } | ||||
|   } | ||||
|  | ||||
|   ::v-deep .ai-list__content--right { | ||||
|   :deep( .ai-list__content--right ){ | ||||
|  | ||||
|     .ai-list__content--right-wrapper { | ||||
|       min-height: 100%; | ||||
|   | ||||
							
								
								
									
										55
									
								
								packages/conv/AppEventReporting/AppEventReporting.vue
									
									
									
									
									
										Normal file
									
								
							
							
						
						| @@ -0,0 +1,55 @@ | ||||
| <template> | ||||
|   <section class="AppEventReporting"> | ||||
|     <component ref="component" :is="currentPage" @change="onChange" :params="params" :instance="instance" :dict="dict" :menuName="menuName" /> | ||||
|   </section> | ||||
| </template> | ||||
|  | ||||
| <script> | ||||
| import List from './components/List' | ||||
| import Detail from './components/Detail' | ||||
| import Setting from './components/Setting' | ||||
|  | ||||
| export default { | ||||
|   name: 'AppEventReporting', | ||||
|   label: '巡查上报', | ||||
|  | ||||
|   props: { | ||||
|     instance: Function, | ||||
|     dict: Object, | ||||
|     menuName: {default: '巡查上报'} | ||||
|   }, | ||||
|  | ||||
|   data() { | ||||
|     return { | ||||
|       component: 'List', | ||||
|       params: {} | ||||
|     } | ||||
|   }, | ||||
|   computed: { | ||||
|     currentPage() { | ||||
|       let {hash, query: {id}} = this.$route | ||||
|       return hash == "#Setting" ? Setting : | ||||
|           !!id ? Detail : List | ||||
|     } | ||||
|   }, | ||||
|   components: { | ||||
|     List, | ||||
|     Detail, | ||||
|     Setting | ||||
|   }, | ||||
|  | ||||
|   methods: { | ||||
|     onChange(data) { | ||||
|       this.$router.push({query: data.params, hash: data.type == "Setting" ? "#Setting" : ""}) | ||||
|     } | ||||
|   } | ||||
| } | ||||
| </script> | ||||
|  | ||||
| <style lang="scss"> | ||||
| .AppEventReporting { | ||||
|   height: 100%; | ||||
|   background: #F3F6F9; | ||||
|   overflow: auto; | ||||
| } | ||||
| </style> | ||||
							
								
								
									
										592
									
								
								packages/conv/AppEventReporting/components/Detail.vue
									
									
									
									
									
										Normal file
									
								
							
							
						
						| @@ -0,0 +1,592 @@ | ||||
| <template> | ||||
|   <ai-detail class="reportAtWillDetail" v-loading="isLoading"> | ||||
|     <template #title> | ||||
|       <ai-title title="详情" isShowBack isShowBottomBorder @onBackClick="cancel(false)"> | ||||
|         <template #rightBtn> | ||||
|           <div class="title-btns"> | ||||
|             <el-button type="primary" icon="iconfont iconPerson_Transfered" @click="isShowForward = true" v-if="detail.powerTransmit">指派事件</el-button> | ||||
|             <el-button type="primary" icon="iconfont iconRegister" @click="isShowAdd = true" v-if="detail.powerHandle">处理事件</el-button> | ||||
|           </div> | ||||
|         </template> | ||||
|       </ai-title> | ||||
|     </template> | ||||
|     <template #content> | ||||
|       <div class="detail-content__wrapper"> | ||||
|         <div class="detail-content__wrapper--left"> | ||||
|           <ai-card title="基础信息"> | ||||
|             <template #content> | ||||
|               <ai-wrapper> | ||||
|                 <ai-info-item label="上报人员" :value="detail.name"></ai-info-item> | ||||
|                 <ai-info-item label="当前状态" :value="dict.getLabel('clapEventStatus', detail.eventStatus)"></ai-info-item> | ||||
|                 <ai-info-item label="联系方式">{{ detail.phone }}</ai-info-item> | ||||
|                 <ai-info-item label="上报时间">{{ detail.createTime }}</ai-info-item> | ||||
|                 <ai-info-item label="事件来源">{{ dict.getLabel('residentEventSource', detail.eventSource) }}</ai-info-item> | ||||
|                 <ai-info-item label="事件类型">{{ detail.groupName }}</ai-info-item> | ||||
|                 <ai-info-item label="事件描述" isLine>{{ detail.content }}</ai-info-item> | ||||
|                 <ai-info-item label="现场照片" isLine> | ||||
|                   <ai-uploader :instance="instance" disabled v-model="detail.files"></ai-uploader> | ||||
|                 </ai-info-item> | ||||
|                 <ai-info-item label="所属网格">{{ detail.girdName }}</ai-info-item> | ||||
|                 <ai-info-item label="事件位置" isLine> | ||||
|                   <div id="map" style="width: 500px; height: 280px;"></div> | ||||
|                 </ai-info-item> | ||||
|               </ai-wrapper> | ||||
|             </template> | ||||
|           </ai-card> | ||||
|           <ai-evaluation v-if="!!detail.id" :bid="detail.id" :info.sync="evaluation"/> | ||||
|         </div> | ||||
|         <div class="rightZone"> | ||||
|           <ai-card title="办理进度"> | ||||
|             <template #content> | ||||
|               <el-steps direction="vertical" :active="1"> | ||||
|                 <el-step | ||||
|                     v-for="(item, i) in process" | ||||
|                     :key="i" | ||||
|                     :title="item.systemExplain" | ||||
|                     :description="item.doTime"> | ||||
|                   <template #title> | ||||
|                     <h2 class="step-title" style="font-weight: 500; font-size: 14px;"> | ||||
|                       {{ item.systemExplain }} | ||||
|                     </h2> | ||||
|                   </template> | ||||
|                   <template #description> | ||||
|                     <p style="color: #888; margin: 0 4px 10px 0; font-size: 14px;">{{ item.doTime }}</p> | ||||
|                     <div style="color: #444;margin-bottom: 10px;" v-if="item.doExplain">{{ item.doExplain }}</div> | ||||
|                     <ai-uploader :instance="instance" disabled v-model="item.files"></ai-uploader> | ||||
|                   </template> | ||||
|                 </el-step> | ||||
|               </el-steps> | ||||
|             </template> | ||||
|           </ai-card> | ||||
|         </div> | ||||
|       </div> | ||||
|       <ai-dialog | ||||
|           :visible.sync="isShowAdd" | ||||
|           width="800px" | ||||
|           title="事件处理" | ||||
|           @closed="onClose" | ||||
|           @onConfirm="handleEvent"> | ||||
|         <el-form class="ai-form" label-width="120px" :model="form" ref="form"> | ||||
|           <el-form-item label="事件分类" prop="groupId" style="width: 100%;" :rules="[{ required: true, message: '请选择事件分类' }]"> | ||||
|             <ai-select | ||||
|                 v-model="form.groupId" | ||||
|                 placeholder="请选择事件分类" | ||||
|                 :selectList="dictList"> | ||||
|             </ai-select> | ||||
|           </el-form-item> | ||||
|           <el-form-item label="处理结果" prop="eventStatus" style="width: 100%;" :rules="[{ required: true, message: '请选择处理结果' }]"> | ||||
|             <el-radio-group v-model="form.eventStatus"> | ||||
|               <el-radio label="1">已办结</el-radio> | ||||
|               <el-radio label="0">已拒绝</el-radio> | ||||
|             </el-radio-group> | ||||
|           </el-form-item> | ||||
|           <el-form-item label="处理意见" prop="content" style="width: 100%;" :rules="[{ required: true, message: '请输入处理意见' }]"> | ||||
|             <el-input type="textarea" :rows="5" :maxlength="500" v-model="form.content" clearable placeholder="请输入处理意见" show-word-limit></el-input> | ||||
|           </el-form-item> | ||||
|           <el-form-item label="图片" prop="files" style="width: 100%;"> | ||||
|             <ai-uploader | ||||
|                 :instance="instance" | ||||
|                 isShowTip | ||||
|                 v-model="form.files" | ||||
|                 :limit="9"> | ||||
|             </ai-uploader> | ||||
|           </el-form-item> | ||||
|         </el-form> | ||||
|       </ai-dialog> | ||||
|       <ai-dialog | ||||
|           :visible.sync="isShowForward" | ||||
|           width="800px" | ||||
|           @close="onClose" | ||||
|           title="事件指派" | ||||
|           @onConfirm="onForwardConfirm"> | ||||
|         <el-form class="ai-form" label-width="120px" :model="forwardForm" ref="forwardForm"> | ||||
|           <el-form-item label="转交" prop="name" style="width: 100%;" :rules="[{ required: true, message: '请选择网格员或网格' }]"> | ||||
|             <el-input disabled size="small" v-model="forwardForm.name" clearable placeholder="请选择网格员或网格"> | ||||
|               <template slot="append"> | ||||
|                 <el-button @click="getGirdList().then(()=>isShowUser=true )">选择</el-button> | ||||
|               </template> | ||||
|             </el-input> | ||||
|           </el-form-item> | ||||
|           <el-form-item label="办理意见" prop="content" style="width: 100%;" :rules="[{ required: true, message: '请输入办理意见' }]"> | ||||
|             <el-input type="textarea" :rows="5" :maxlength="500" v-model="forwardForm.content" clearable placeholder="请输入办理意见" show-word-limit></el-input> | ||||
|           </el-form-item> | ||||
|           <el-form-item label="图片" prop="files" style="width: 100%;"> | ||||
|             <ai-uploader | ||||
|                 :instance="instance" | ||||
|                 v-model="forwardForm.files" | ||||
|                 isShowTip | ||||
|                 :limit="9"> | ||||
|             </ai-uploader> | ||||
|           </el-form-item> | ||||
|         </el-form> | ||||
|       </ai-dialog> | ||||
|       <ai-dialog | ||||
|           :visible.sync="isShowUser" | ||||
|           width="800px" | ||||
|           title="选择网格员" | ||||
|           @onConfirm="onConfirm"> | ||||
|         <div class="grid-wrapper"> | ||||
|           <el-input | ||||
|               style="margin-bottom: 10px;" | ||||
|               size="small" | ||||
|               placeholder="请输入网格名称/网格员姓名/网格员电话" | ||||
|               v-model="name" @change="$refs.tree.filter(name)" | ||||
|               suffix-icon="iconfont iconSearch"> | ||||
|           </el-input> | ||||
|           <el-tree | ||||
|               :filter-node-method="filterNode" | ||||
|               ref="tree" | ||||
|               :props="defaultProps" | ||||
|               node-key="id" | ||||
|               :data="tree" | ||||
|               highlight-current | ||||
|               @current-change="onTreeChange"> | ||||
|             <div class="tree-container" slot-scope="{ data }"> | ||||
|               <div class="tree-container__user"> | ||||
|                 <div class="tree-user__item"> | ||||
|                   <span v-if="!data.isUser">{{ data.girdName }}</span> | ||||
|                   <span v-else>{{data.name}}<span v-if="data.phone">-{{data.phone}}</span></span> | ||||
|                 </div> | ||||
|               </div> | ||||
|             </div> | ||||
|           </el-tree> | ||||
|         </div> | ||||
|       </ai-dialog> | ||||
|     </template> | ||||
|   </ai-detail> | ||||
| </template> | ||||
|  | ||||
| <script> | ||||
| import AMapLoader from '@amap/amap-jsapi-loader' | ||||
| import {mapState} from 'vuex' | ||||
|  | ||||
| export default { | ||||
|   name: 'Detail', | ||||
|   props: ['dict', 'instance'], | ||||
|  | ||||
|   data() { | ||||
|     return { | ||||
|       forwardForm: { | ||||
|         content: '', | ||||
|         girdId: '', | ||||
|         girdName: '', | ||||
|         girdMemberId: '', | ||||
|         girdMemberName: '', | ||||
|         name: '' | ||||
|       }, | ||||
|       isLoading: true, | ||||
|       name: '', | ||||
|       detail: {}, | ||||
|       isShowUser: false, | ||||
|       eventList: [], | ||||
|       isShowAdd: false, | ||||
|       userList: [], | ||||
|       processList: [], | ||||
|       dictList: [], | ||||
|       defaultProps: { | ||||
|         label: 'girdName' | ||||
|       }, | ||||
|       isShowForward: false, | ||||
|       tree: [], | ||||
|       gridInfo: {}, | ||||
|       form: { | ||||
|         files: [], | ||||
|         groupId: '', | ||||
|         groupName: '', | ||||
|         content: [], | ||||
|         eventStatus: '1' | ||||
|       }, | ||||
|       evaluation: {} | ||||
|     } | ||||
|   }, | ||||
|  | ||||
|   computed: { | ||||
|     ...mapState(['user']), | ||||
|     process: v => [v.evaluation.id ? { | ||||
|       systemExplain: `${v.evaluation.createUserName}完成评价 (${v.evaluation.score}星评价)`, | ||||
|       doTime: v.evaluation.createTime, | ||||
|       doExplain: v.evaluation.rateText, | ||||
|     } : null, v.processList].flat().filter(Boolean) | ||||
|   }, | ||||
|  | ||||
|   created() { | ||||
|     this.getDict() | ||||
|     this.dict.load('clapEventStatus', 'residentEventSource').then(() => { | ||||
|       this.getDetail() | ||||
|     }) | ||||
|   }, | ||||
|  | ||||
|   methods: { | ||||
|     getDetail() { | ||||
|       this.instance.post('/app/apppatrolreportinfov2/queryDetailById', null, { | ||||
|         params: {id: this.$route.query.id} | ||||
|       }).then(res => { | ||||
|         if (res?.data) { | ||||
|           this.detail = res.data | ||||
|           this.processList = res.data.processList | ||||
|           this.form.groupId = res.data.groupId | ||||
|  | ||||
|           this.$nextTick(() => { | ||||
|             this.initMap() | ||||
|           }) | ||||
|           this.isLoading = false | ||||
|         } | ||||
|       }).catch(() => { | ||||
|         this.isLoading = false | ||||
|       }) | ||||
|     }, | ||||
|  | ||||
|     getGirdList() { | ||||
|       return this.instance.post(`/app/apppatrolreportinfov2/listGirdInfoByTransfer?id=${this.$route.query.id}`).then(res => { | ||||
|         if (res?.data) { | ||||
|           // return this.tree = this.formatList([res.data]) | ||||
|           this.tree = res.data | ||||
|           this.tree.map((item) => { | ||||
|             item.children = [item.girdMemberList?.map(e => ({ | ||||
|               ...e, isUser: true, girdName: item.girdName | ||||
|             })) || []].flat() | ||||
|           }) | ||||
|         } | ||||
|       }) | ||||
|     }, | ||||
|  | ||||
|     onClose() { | ||||
|       this.form.files = [] | ||||
|       this.form.groupId = '' | ||||
|       this.form.groupName = '' | ||||
|       this.form.content = '' | ||||
|       this.form.eventStatus = '' | ||||
|       this.forwardForm.content = '' | ||||
|       this.forwardForm.girdId = '' | ||||
|       this.forwardForm.girdName = '' | ||||
|       this.forwardForm.girdMemberId = '' | ||||
|       this.forwardForm.girdMemberName = '' | ||||
|       this.forwardForm.name = '' | ||||
|       this.forwardForm.files = [] | ||||
|     }, | ||||
|  | ||||
|     formatList(list) { | ||||
|       for (let item of list) { | ||||
|         item.children = [item.girdList, item.girdMemberList?.map(e => ({ | ||||
|           ...e, isUser: true, girdName: item.girdName, | ||||
|           girdId: item.id | ||||
|         })) || []].flat() | ||||
|         if (item.girdList?.length > 0) { | ||||
|           this.formatList(item.girdList) | ||||
|         } | ||||
|       } | ||||
|       return list | ||||
|     }, | ||||
|  | ||||
|     filterNode(value, data) { | ||||
|       if (!value) return true | ||||
|  | ||||
|       return (data.girdName && data.girdName.indexOf(value) !== -1) || (data.name && data.name.indexOf(value) !== -1) || (data.name && data.phone.indexOf(value) !== -1) | ||||
|     }, | ||||
|  | ||||
|     onTreeChange(e) { | ||||
|       this.gridInfo = e | ||||
|     }, | ||||
|  | ||||
|     onForwardConfirm() { | ||||
|       this.$refs.forwardForm.validate(v => { | ||||
|         if (v) { | ||||
|           this.instance.post('/app/apppatrolreportinfov2/transfer', { | ||||
|             ...this.forwardForm, | ||||
|             id: this.$route.query.id | ||||
|           }).then(res => { | ||||
|             if (res?.code == 0) { | ||||
|               this.isShowForward = false | ||||
|               this.onClose() | ||||
|               this.getDetail() | ||||
|               this.$message.success('转交成功!') | ||||
|             } | ||||
|           }) | ||||
|         } | ||||
|       }) | ||||
|     }, | ||||
|  | ||||
|     onConfirm() { | ||||
|       // if (this.gridInfo.userId) { | ||||
|       //   this.forwardForm.girdId = this.gridInfo.girdId | ||||
|       //   this.forwardForm.girdName = this.gridInfo.girdName | ||||
|       //   this.forwardForm.girdMemberId = this.gridInfo.id | ||||
|       //   this.forwardForm.girdMemberName = this.gridInfo.name | ||||
|       // } else { | ||||
|       //   this.forwardForm.girdId = this.gridInfo.id | ||||
|       // } | ||||
|       // this.forwardForm.girdName = this.gridInfo.girdName | ||||
|       // this.forwardForm.name = `${this.gridInfo.girdName}${this.gridInfo.name ? '-' + this.gridInfo.name : ''}` | ||||
|       // this.isShowUser = false | ||||
|       if(!this.gridInfo.userId) { | ||||
|         return this.$message.error('请选择网格员!') | ||||
|       }  | ||||
|       this.forwardForm.girdId = this.gridInfo.girdId | ||||
|       this.forwardForm.girdName = this.gridInfo.girdName | ||||
|       this.forwardForm.girdMemberId = this.gridInfo.id | ||||
|       this.forwardForm.girdMemberName = this.gridInfo.name | ||||
|       this.forwardForm.name = `${this.gridInfo.girdName}${this.gridInfo.name ? '-' + this.gridInfo.name : ''}` | ||||
|       this.isShowUser = false | ||||
|     }, | ||||
|     getDict() { | ||||
|       this.instance.post(`/app/apppatrolreportgroupv2/list?current=1&size=100000`).then(res => { | ||||
|         if (res.code == 0) { | ||||
|           this.dictList = res.data.records.map(v => { | ||||
|             return { | ||||
|               dictValue: v.id, | ||||
|               dictName: v.groupName | ||||
|             } | ||||
|           }) | ||||
|         } | ||||
|       }) | ||||
|     }, | ||||
|  | ||||
|     close() { | ||||
|       this.$confirm('确定关闭该事件?').then(() => { | ||||
|         this.instance.post(`/app/apppatrolreportinfov2/delete?ids=${this.$route.query.id}`).then(res => { | ||||
|           if (res.code == 0) { | ||||
|             this.$message.success('删除成功!') | ||||
|             this.getList() | ||||
|           } | ||||
|         }) | ||||
|       }) | ||||
|     }, | ||||
|  | ||||
|     cancel(isRefresh) { | ||||
|       this.$emit('change', { | ||||
|         type: 'list', | ||||
|         isRefresh: !!isRefresh | ||||
|       }) | ||||
|     }, | ||||
|  | ||||
|     initMap() { | ||||
|       let {lng, lat} = this.detail | ||||
|       let center = [lng, lat] | ||||
|       AMapLoader.load({ | ||||
|         key: 'b553334ba34f7ac3cd09df9bc8b539dc', | ||||
|         version: '2.0' | ||||
|       }).then(AMap => { | ||||
|         let map = new AMap.Map('map', { | ||||
|           center, | ||||
|           zoom: 14 | ||||
|         }) | ||||
|         let marker = new AMap.Marker({ | ||||
|           position: new AMap.LngLat(lng, lat), | ||||
|           title: this.detail.address | ||||
|         }) | ||||
|         map.add(marker) | ||||
|       }) | ||||
|     }, | ||||
|  | ||||
|     handleEvent() { | ||||
|       this.$refs.form.validate(v => { | ||||
|         if (v) { | ||||
|           this.instance.post('/app/apppatrolreportinfov2/finish', { | ||||
|             ...this.form, | ||||
|             groupName: this.dictList.filter(v => v.dictValue === this.form.groupId)[0].dictName, | ||||
|             id: this.$route.query.id | ||||
|           }).then(res => { | ||||
|             if (res?.code == 0) { | ||||
|               this.isShowAdd = false | ||||
|               this.getDetail() | ||||
|               this.$message.success('处理成功!') | ||||
|             } | ||||
|           }) | ||||
|         } | ||||
|       }) | ||||
|     } | ||||
|   } | ||||
| } | ||||
| </script> | ||||
|  | ||||
| <style lang="scss" scoped> | ||||
| .reportAtWillDetail { | ||||
|   height: 100%; | ||||
|  | ||||
|   .grid-wrapper { | ||||
|     min-height: 360px; | ||||
|   } | ||||
|  | ||||
|   .title-btns { | ||||
|     display: flex; | ||||
|     align-items: center; | ||||
|   } | ||||
|  | ||||
|   :deep( .el-tree ) { | ||||
|     background: transparent; | ||||
|  | ||||
|     .el-tree-node__expand-icon.is-leaf { | ||||
|       color: transparent !important; | ||||
|     } | ||||
|  | ||||
|     .el-tree-node__content > .el-tree-node__expand-icon { | ||||
|       padding: 4px; | ||||
|     } | ||||
|  | ||||
|     .el-tree-node__content { | ||||
|       height: 32px; | ||||
|     } | ||||
|  | ||||
|     .el-tree__empty-text { | ||||
|       color: #222; | ||||
|       font-size: 14px; | ||||
|     } | ||||
|  | ||||
|     .el-tree-node__children .el-tree-node__content { | ||||
|       height: 32px; | ||||
|     } | ||||
|  | ||||
|     .el-tree-node__content:hover { | ||||
|       background: #E8EFFF; | ||||
|       color: #222222; | ||||
|       border-radius: 2px; | ||||
|     } | ||||
|  | ||||
|     .is-current > .el-tree-node__content { | ||||
|       &:hover { | ||||
|         background: #2266FF; | ||||
|         color: #fff; | ||||
|       } | ||||
|  | ||||
|       background: #2266FF; | ||||
|  | ||||
|       span { | ||||
|         color: #fff; | ||||
|       } | ||||
|     } | ||||
|   } | ||||
|  | ||||
|   .el-steps { | ||||
|     :deep( .el-step__icon ) { | ||||
|       font-size: 12px; | ||||
|       color: #555555; | ||||
|       border-color: #d0d4dc; | ||||
|     } | ||||
|  | ||||
|     :deep( .el-step__head.is-finish ) { | ||||
|       .el-step__icon.is-text { | ||||
|         border: none; | ||||
|         color: #fff; | ||||
|         font-size: 12px; | ||||
|         background: #2266ff; | ||||
|       } | ||||
|     } | ||||
|  | ||||
|     :deep( .el-step__line ) { | ||||
|       background-color: #d0d4dc; | ||||
|     } | ||||
|   } | ||||
|  | ||||
|   .imgs { | ||||
|     font-size: 0; | ||||
|  | ||||
|     img { | ||||
|       width: 108px; | ||||
|       height: 108px; | ||||
|       margin-right: 4px; | ||||
|       margin-bottom: 4px; | ||||
|       cursor: pointer; | ||||
|       user-select: none; | ||||
|  | ||||
|       &:hover { | ||||
|         opacity: 0.8; | ||||
|       } | ||||
|  | ||||
|       &:nth-of-type(2n) { | ||||
|         margin-right: 0; | ||||
|       } | ||||
|     } | ||||
|   } | ||||
|  | ||||
|   :deep( .report-dialog ) { | ||||
|     .el-select { | ||||
|       width: 100%; | ||||
|     } | ||||
|   } | ||||
|  | ||||
|   :deep( .el-step__head.is-process ) { | ||||
|     color: #555; | ||||
|     border-color: #555; | ||||
|   } | ||||
|  | ||||
|   :deep( .is-finish h2 ) { | ||||
|     color: #2266ff; | ||||
|   } | ||||
|  | ||||
|   .step-title { | ||||
|     color: #555; | ||||
|   } | ||||
|  | ||||
|   .detail-content__wrapper { | ||||
|     display: flex; | ||||
|     width: 100%; | ||||
|     flex-wrap: wrap; | ||||
|  | ||||
|     .detail-content__wrapper--left { | ||||
|       flex: 1; | ||||
|       margin-right: 20px; | ||||
|     } | ||||
|   } | ||||
|  | ||||
|   :deep( .ai-detail__content ) { | ||||
|     background: #f3f6f9; | ||||
|  | ||||
|     .ai-detail__content--wrapper { | ||||
|       display: flex; | ||||
|       gap: 16px; | ||||
|       width: 100%; | ||||
|       max-width: 100%; | ||||
|       padding: 16px; | ||||
|       box-sizing: border-box; | ||||
|  | ||||
|       & > .el-card { | ||||
|         flex: 1; | ||||
|         min-width: 0; | ||||
|       } | ||||
|  | ||||
|       .rightZone { | ||||
|         width: 400px; | ||||
|         flex-shrink: 0; | ||||
|         display: flex; | ||||
|         flex-direction: column; | ||||
|         gap: 16px; | ||||
|       } | ||||
|     } | ||||
|   } | ||||
|  | ||||
|   :deep( .el-card ) { | ||||
|     .el-card__header { | ||||
|       padding: 12px 16px; | ||||
|       font-weight: bold; | ||||
|     } | ||||
|  | ||||
|     .el-card__body { | ||||
|       padding: 8px; | ||||
|     } | ||||
|  | ||||
|     #amap { | ||||
|       width: 466px; | ||||
|       height: 232px; | ||||
|     } | ||||
|  | ||||
|     .el-steps { | ||||
|       margin-left: 8px; | ||||
|     } | ||||
|  | ||||
|     .imgFormItem > .el-form-item__content { | ||||
|       display: flex; | ||||
|       gap: 16px; | ||||
|       flex-wrap: wrap; | ||||
|  | ||||
|       &:before { | ||||
|         content: none; | ||||
|       } | ||||
|  | ||||
|       .el-image__inner { | ||||
|         width: 82px; | ||||
|         height: 82px; | ||||
|       } | ||||
|     } | ||||
|   } | ||||
| } | ||||
| </style> | ||||
							
								
								
									
										249
									
								
								packages/conv/AppEventReporting/components/List.vue
									
									
									
									
									
										Normal file
									
								
							
							
						
						| @@ -0,0 +1,249 @@ | ||||
| <template> | ||||
|   <ai-list> | ||||
|     <template #title> | ||||
|       <ai-title :title="menuName" isShowBottomBorder> | ||||
|         <el-button type="primary" slot="rightBtn" @click="toSetting">事件类型设置</el-button> | ||||
|       </ai-title> | ||||
|     </template> | ||||
|     <template #content> | ||||
|       <ai-search-bar> | ||||
|         <template #left> | ||||
|           <ai-select | ||||
|             v-model="search.eventStatus" | ||||
|             clearable | ||||
|             placeholder="处理状态" | ||||
|             :selectList="dict.getDict('clapEventStatus')" | ||||
|             @change="search.current = 1, getList()"> | ||||
|           </ai-select> | ||||
|           <ai-select | ||||
|             v-model="search.eventSource" | ||||
|             clearable | ||||
|             placeholder="事件来源" | ||||
|             :selectList="dict.getDict('residentEventSource')" | ||||
|             @change="search.current = 1, getList()"> | ||||
|           </ai-select> | ||||
|           <ai-select | ||||
|             v-model="search.groupId" | ||||
|             clearable | ||||
|             placeholder="事件类型" | ||||
|             :selectList="typeList" | ||||
|             @change="search.current = 1, getList()"> | ||||
|           </ai-select> | ||||
|           <el-cascader ref="cascader1" v-model="girdArr" :options="girdOptions" placeholder="所属网格" size="small" | ||||
|             :props="defaultProps" :show-all-levels="false" @change="gridChange" clearable></el-cascader> | ||||
|           <el-date-picker size="small" v-model="searchDotime" type="daterange" range-separator="至" @change="timeChange" | ||||
|             start-placeholder="开始日期" end-placeholder="结束日期" value-format="yyyy-MM-dd" format="yyyy-MM-dd"></el-date-picker> | ||||
|         </template> | ||||
|         <template #right> | ||||
|           <ai-download :instance="instance" url="/app/apppatrolreportinfov2/export" :params="search" fileName="巡查上报" | ||||
|                        :disabled="tableData.length == 0"> | ||||
|             <el-button icon="iconfont iconExported" :disabled="tableData.length == 0">导出</el-button> | ||||
|           </ai-download> | ||||
|           <el-input | ||||
|               v-model="search.content" | ||||
|               class="search-input" | ||||
|               size="small" | ||||
|               v-throttle="() => {search.current = 1, getList()}" | ||||
|               placeholder="请输入内容描述/上报人员/联系方式" | ||||
|               clearable | ||||
|               @change="getList" | ||||
|               @clear="search.current = 1, search.content = '', getList()" | ||||
|               suffix-icon="iconfont iconSearch"> | ||||
|           </el-input> | ||||
|         </template> | ||||
|       </ai-search-bar> | ||||
|       <ai-table :tableData="tableData" :colConfigs="colConfigs" :total="total" :current.sync="search.current" :size.sync="search.size" @getList="getList"> | ||||
|         <el-table-column slot="options" label="操作" fixed="right" width="120" align="center"> | ||||
|           <div class="table-options" slot-scope="{row}"> | ||||
|             <el-button type="text" title="详情" @click="toDetail(row.id)">详情</el-button> | ||||
|             <el-button type="text" title="删除" @click="handleDelete(row.id)">删除</el-button> | ||||
|           </div> | ||||
|         </el-table-column> | ||||
|       </ai-table> | ||||
|     </template> | ||||
|   </ai-list> | ||||
| </template> | ||||
|  | ||||
| <script> | ||||
| import {mapState} from 'vuex' | ||||
|  | ||||
| export default { | ||||
|   name: 'List', | ||||
|   label: "巡查上报", | ||||
|  | ||||
|   props: { | ||||
|     instance: Function, | ||||
|     dict: Object, | ||||
|     menuName: String | ||||
|   }, | ||||
|  | ||||
|   data() { | ||||
|     return { | ||||
|       userList: [], | ||||
|       search: { | ||||
|         current: 1, | ||||
|         size: 10, | ||||
|         eventStatus: '', | ||||
|         content: '', | ||||
|         eventSource: '', | ||||
|         groupId: '', | ||||
|         createTimeStart: '', | ||||
|         createTimeEnd: '', | ||||
|         girdId: '' | ||||
|       }, | ||||
|       total: 0, | ||||
|       tableData: [], | ||||
|       content: '', | ||||
|       id: '', | ||||
|       girdId: '', | ||||
|       girdArr: [], | ||||
|       girdOptions: [], | ||||
|       defaultProps: { | ||||
|         label: 'girdName', | ||||
|         value: 'id', | ||||
|         children: 'children', | ||||
|         checkStrictly: true, | ||||
|       }, | ||||
|       searchDotime: [], | ||||
|       typeList: [] | ||||
|     } | ||||
|   }, | ||||
|  | ||||
|   computed: { | ||||
|     ...mapState(['user']), | ||||
|  | ||||
|     colConfigs() { | ||||
|       return [ | ||||
|         {prop: 'content', label: '内容描述', width: '300px'}, | ||||
|         {prop: 'eventSource', label: '事件来源', align: 'center', dict: 'residentEventSource'}, | ||||
|         {prop: 'groupName', label: '事件类型', align: 'center'}, | ||||
|         {prop: 'girdName', label: '所属网格', align: 'center'}, | ||||
|         {prop: 'createTime', label: '上报时间', align: 'center'}, | ||||
|         {prop: 'name', label: '上报人员', align: 'center'}, | ||||
|         {prop: 'phone', label: '联系方式', align: 'center'}, | ||||
|         {prop: 'eventStatus', label: '处理状态', align: 'center', format: v => this.dict.getLabel('clapEventStatus', v)}, | ||||
|         {prop: 'processTime', label: '处理时长', align: 'center'}, | ||||
|         {slot: 'options'} | ||||
|       ] | ||||
|     }, | ||||
|  | ||||
|     handleStatusOps() { | ||||
|       return this.dict.getDict("reportAtWillHandleStatus").map(e => ({label: e.dictName, value: e.dictValue})) | ||||
|     } | ||||
|   }, | ||||
|  | ||||
|   created() { | ||||
|     this.dict.load('clapEventStatus', 'residentEventSource').then(() => { | ||||
|       this.getList() | ||||
|       this.getGridList() | ||||
|       this.getTypeList() | ||||
|     }) | ||||
|   }, | ||||
|  | ||||
|   methods: { | ||||
|     timeChange() { | ||||
|       if (this.searchDotime) { | ||||
|         this.search.createTimeStart = this.searchDotime[0] | ||||
|         this.search.createTimeEnd = this.searchDotime[1] | ||||
|       } else { | ||||
|         this.search.createTimeStart = null | ||||
|         this.search.createTimeEnd = null | ||||
|       } | ||||
|       this.search.current = 1 | ||||
|       this.getList() | ||||
|     }, | ||||
|     // 所有网格 | ||||
|     getGridList() { | ||||
|       this.instance.post(`/app/appgirdinfo/listAll3`).then((res) => { | ||||
|         if (res?.code == 0) { | ||||
|           this.girdOptions = this.toTree(res.data) | ||||
|         } | ||||
|       }) | ||||
|     }, | ||||
|     // 转树形结构 | ||||
|     toTree(data) { | ||||
|       let result = []; | ||||
|       if (!Array.isArray(data)) { | ||||
|         return result | ||||
|       } | ||||
|       let map = {}; | ||||
|       data.forEach(item => { | ||||
|         map[item.id] = item; | ||||
|       }); | ||||
|       data.forEach(item => { | ||||
|         let parent = map[item.parentGirdId]; | ||||
|         if (parent) { | ||||
|           (parent.children || (parent.children = [])).push(item); | ||||
|         } else { | ||||
|           result.push(item); | ||||
|         } | ||||
|       }); | ||||
|       return result; | ||||
|     }, | ||||
|     gridChange(val) { | ||||
|       this.girdArr = val | ||||
|       this.search.girdId = val?.[val.length - 1] | ||||
|       this.$refs.cascader1.dropDownVisible = false; | ||||
|       this.search.current = 1 | ||||
|       this.getList() | ||||
|     }, | ||||
|     getList() { | ||||
|       this.instance.post(`/app/apppatrolreportinfov2/list`, null, { | ||||
|         params: { | ||||
|           ...this.search | ||||
|         } | ||||
|       }).then(res => { | ||||
|         if (res.code == 0) { | ||||
|           this.tableData = res.data.records | ||||
|           this.total = res.data.total | ||||
|         } | ||||
|       }) | ||||
|     }, | ||||
|  | ||||
|     toDetail(id) { | ||||
|       this.$emit('change', { | ||||
|         type: 'Detail', | ||||
|         params: { | ||||
|           id: id || '' | ||||
|         } | ||||
|       }) | ||||
|     }, | ||||
|  | ||||
|     toSetting() { | ||||
|       this.$emit('change', { | ||||
|         type: 'Setting', | ||||
|         params: { | ||||
|           id: '' | ||||
|         } | ||||
|       }) | ||||
|     }, | ||||
|     handleDelete(ids) { | ||||
|       this.$confirm("是否要进行删除?").then(() => { | ||||
|         this.instance.post("/app/apppatrolreportinfov2/delete", null, { | ||||
|           params: {ids} | ||||
|         }).then(res => { | ||||
|           if (res?.code == 0) { | ||||
|             this.$message.success("删除成功!") | ||||
|             this.getList() | ||||
|           } | ||||
|         }) | ||||
|       }).catch(() => 0) | ||||
|     }, | ||||
|     getTypeList() { | ||||
|       this.instance.post(`/app/apppatrolreportgroupv2/list?size=10000`).then(res => { | ||||
|         if (res.code == 0) { | ||||
|           res.data.records.map((item) => { | ||||
|             item.dictName = item.groupName | ||||
|             item.dictValue = item.id | ||||
|           }) | ||||
|           this.typeList = res.data.records | ||||
|         } | ||||
|       }) | ||||
|     } | ||||
|   }, | ||||
|    | ||||
| } | ||||
| </script> | ||||
|  | ||||
| <style lang="scss" scoped> | ||||
| </style> | ||||
							
								
								
									
										178
									
								
								packages/conv/AppEventReporting/components/Setting.vue
									
									
									
									
									
										Normal file
									
								
							
							
						
						| @@ -0,0 +1,178 @@ | ||||
| <template> | ||||
|   <ai-list class="notice"> | ||||
|     <template slot="title"> | ||||
|       <ai-title  isShowBack isShowBottomBorder title="事件类型" @onBackClick="cancel(false)"></ai-title> | ||||
|     </template> | ||||
|     <template slot="content"> | ||||
|       <ai-search-bar class="search-bar"> | ||||
|         <template #left> | ||||
|           <el-button size="small" type="primary" icon="iconfont iconAdd" @click="isShowAdd = true">添加事件类型</el-button> | ||||
|         </template> | ||||
|         <template slot="right"> | ||||
|           <el-input | ||||
|             v-model="search.groupName" | ||||
|             class="search-input" | ||||
|             size="small" | ||||
|             v-throttle="() => {search.current = 1, getList()}" | ||||
|             placeholder="请输入事件类型名称" | ||||
|             clearable | ||||
|             @change="getList" | ||||
|             @clear="search.current = 1, search.groupName = '', getList()" | ||||
|             suffix-icon="iconfont iconSearch"> | ||||
|           </el-input> | ||||
|         </template> | ||||
|       </ai-search-bar> | ||||
|       <ai-table | ||||
|         :tableData="tableData" | ||||
|         :col-configs="colConfigs" | ||||
|         :total="total" | ||||
|         style="margin-top: 6px;" | ||||
|         :current.sync="search.current" | ||||
|         :size.sync="search.size" | ||||
|         @getList="getList"> | ||||
|         <el-table-column slot="tags" label="标签"> | ||||
|           <template slot-scope="{ row }"> | ||||
|             <div class="table-tags"> | ||||
|               <el-tag type="info" v-for="(item, index) in row.tags" size="small" :key="index">{{ item }}</el-tag> | ||||
|             </div> | ||||
|           </template> | ||||
|         </el-table-column> | ||||
|         <el-table-column slot="options" width="120px" fixed="right" label="操作" align="center"> | ||||
|           <div class="table-options" slot-scope="{ row }"> | ||||
|             <el-button type="text" @click="edit(row)">编辑</el-button> | ||||
|             <el-button type="text" @click="remove(row.id)">删除</el-button> | ||||
|           </div> | ||||
|         </el-table-column> | ||||
|       </ai-table> | ||||
|       <ai-dialog | ||||
|         :visible.sync="isShowAdd" | ||||
|         width="780px" | ||||
|         height="580px" | ||||
|         :title="id ? '编辑事件类型' : '添加事件类型'" | ||||
|         @close="onClose" | ||||
|         @onConfirm="onConfirm"> | ||||
|         <el-form ref="form" class="ai-form" :model="form" label-width="110px" label-position="right"> | ||||
|           <el-form-item label="事件类型" prop="groupName" style="width: 100%;" :rules="[{ required: true, message: '请输入事件类型名称', trigger: 'blur' }]"> | ||||
|             <el-input size="small" :maxlength="10" show-word-limit placeholder="请输入事件类型名称" v-model="form.groupName"></el-input> | ||||
|           </el-form-item> | ||||
|           <el-form-item label="排序" prop="showIndex" style="width: 100%;" :rules="[{ required: true, message: '请输入排序', trigger: 'blur' }]"> | ||||
|             <el-input-number size="small" v-model="form.showIndex" :min="1" :max="100" label="请输入排序"></el-input-number> | ||||
|           </el-form-item> | ||||
|         </el-form> | ||||
|       </ai-dialog> | ||||
|     </template> | ||||
|   </ai-list> | ||||
| </template> | ||||
|  | ||||
| <script> | ||||
|   import { mapState } from 'vuex' | ||||
|   export default { | ||||
|     name: 'List', | ||||
|  | ||||
|     props: { | ||||
|       instance: Function, | ||||
|       dict: Object | ||||
|     }, | ||||
|  | ||||
|     data() { | ||||
|       return { | ||||
|         search: { | ||||
|           current: 1, | ||||
|           size: 10, | ||||
|           groupName: '' | ||||
|         }, | ||||
|         form: { | ||||
|           groupName: '', | ||||
|           showIndex: '' | ||||
|         }, | ||||
|         id: '', | ||||
|         isShowAdd: false, | ||||
|         total: 0, | ||||
|         colConfigs: [ | ||||
|           {prop: 'groupName', label: '事件类型', align: 'left'}, | ||||
|           {prop: 'showIndex', label: '排序', align: 'center'}, | ||||
|           {slot: 'options', label: '操作'} | ||||
|         ], | ||||
|         tableData: [] | ||||
|       } | ||||
|     }, | ||||
|  | ||||
|     computed: { | ||||
|       ...mapState(['user']) | ||||
|     }, | ||||
|  | ||||
|     mounted() { | ||||
|       this.getList() | ||||
|     }, | ||||
|  | ||||
|     methods: { | ||||
|       getList() { | ||||
|         this.instance.post(`/app/apppatrolreportgroupv2/list`, null, { | ||||
|           params: { | ||||
|             ...this.search | ||||
|           } | ||||
|         }).then(res => { | ||||
|           if (res.code == 0) { | ||||
|             this.tableData = res.data.records | ||||
|             this.total = res.data.total | ||||
|           } | ||||
|         }) | ||||
|       }, | ||||
|  | ||||
|       edit (e) { | ||||
|         this.id = e.id | ||||
|         this.form.groupName = e.groupName | ||||
|         this.form.showIndex = '' | ||||
|  | ||||
|         this.$nextTick(() => { | ||||
|           this.isShowAdd = true | ||||
|         }) | ||||
|       }, | ||||
|  | ||||
|       onClose () { | ||||
|         this.id = '' | ||||
|         this.form.showIndex = '' | ||||
|         this.form.groupName = '' | ||||
|       }, | ||||
|  | ||||
|       onConfirm () { | ||||
|         this.$refs.form.validate((valid) => { | ||||
|           if (valid) { | ||||
|             this.instance.post(`/app/apppatrolreportgroupv2/addOrUpdate`, { | ||||
|               ...this.form, | ||||
|               id: this.id || null | ||||
|             }).then(res => { | ||||
|               if (res.code === 0) { | ||||
|                 this.$message.success('添加成功') | ||||
|                 this.isShowAdd = false | ||||
|  | ||||
|                 this.getList() | ||||
|               } | ||||
|             }) | ||||
|           } | ||||
|         }) | ||||
|       }, | ||||
|  | ||||
|       cancel (isRefresh) { | ||||
|         this.$emit('change', { | ||||
|           type: 'list', | ||||
|           isRefresh: !!isRefresh | ||||
|         }) | ||||
|       }, | ||||
|  | ||||
|       remove(id) { | ||||
|         this.$confirm('确定删除该数据?').then(() => { | ||||
|           this.instance.post(`/app/apppatrolreportgroupv2/delete?ids=${id}`).then(res => { | ||||
|             if (res.code == 0) { | ||||
|               this.$message.success('删除成功!') | ||||
|               this.getList() | ||||
|             } | ||||
|           }) | ||||
|         }) | ||||
|       } | ||||
|     } | ||||
|   } | ||||
| </script> | ||||
|  | ||||
| <style lang="scss" scoped> | ||||
| </style> | ||||
| @@ -185,7 +185,7 @@ | ||||
|         recordList: [], | ||||
|         colConfigs: [ | ||||
|           {prop: 'createTime', label: '上报日期', align: 'center', dateFormat: 'YYYY-MM-DD'}, | ||||
|           {prop: 'status', label: '健康状态', align: 'center', formart: v => v === '0' ? '异常' : '正常' } | ||||
|           {prop: 'status', label: '健康状态', align: 'center', format: v => v === '0' ? '异常' : '正常' } | ||||
|         ], | ||||
|         tabList: ['基本信息', '每日上报', '异常处理'] | ||||
|       } | ||||
|   | ||||
| @@ -119,7 +119,7 @@ | ||||
|           { prop: 'name', label: '姓名' }, | ||||
|           { prop: 'phone', align: 'center', label: '手机号码' }, | ||||
|           { prop: 'areaName', align: 'center', label: '所属地区', width: '200px' }, | ||||
|           { prop: 'reportTime', align: 'center', label: '上报时间', width: '200px' },  | ||||
|           { prop: 'reportTime', align: 'center', label: '上报时间', width: '200px' }, | ||||
|           { | ||||
|             prop: 'vaccine', | ||||
|             align: 'center', | ||||
| @@ -130,10 +130,10 @@ | ||||
|                 } | ||||
|               }, row.today === '0' ? '-' : (row.vaccine || 0 + '次')) | ||||
|             } | ||||
|           },  | ||||
|           { prop: 'healthCode', align: 'center', label: '健康码', formart: v => v ? this.dict.getLabel('epidemicHealthCode', v) : '-' },  | ||||
|           { prop: 'checkTime', align: 'center', label: '核酸日期', formart: v => v ? v.split(' ')[0] : '-' },  | ||||
|           { prop: 'checkResult', align: 'center', label: '检测结果', formart: v => v ? this.dict.getLabel('epidemicRecentTestResult', v) : '-' },  | ||||
|           }, | ||||
|           { prop: 'healthCode', align: 'center', label: '健康码', format: v => v ? this.dict.getLabel('epidemicHealthCode', v) : '-' }, | ||||
|           { prop: 'checkTime', align: 'center', label: '核酸日期', format: v => v ? v.split(' ')[0] : '-' }, | ||||
|           { prop: 'checkResult', align: 'center', label: '检测结果', format: v => v ? this.dict.getLabel('epidemicRecentTestResult', v) : '-' }, | ||||
|           { | ||||
|             prop: 'status', | ||||
|             align: 'center', | ||||
| @@ -146,7 +146,7 @@ | ||||
|               }, row.today === '0' ? '-' : (row.status === '0' ? '异常' : '正常')) | ||||
|             } | ||||
|           }, | ||||
|           { prop: 'today', align: 'center', label: '今日上报', formart: v => v === '0' ? '未上报' : '已上报' }, | ||||
|           { prop: 'today', align: 'center', label: '今日上报', format: v => v === '0' ? '未上报' : '已上报' }, | ||||
|         ], | ||||
|         tableData: [], | ||||
|         total: 0, | ||||
| @@ -191,7 +191,7 @@ | ||||
|         }).catch(() => { | ||||
|           this.loading = false | ||||
|         }) | ||||
|          | ||||
|  | ||||
|         this.getTotalInfo() | ||||
|       }, | ||||
|  | ||||
| @@ -242,7 +242,7 @@ | ||||
|  | ||||
| <style scoped lang="scss"> | ||||
|   .list { | ||||
|     ::v-deep .ai-list__content { | ||||
|     :deep( .ai-list__content ){ | ||||
|       padding: 0!important; | ||||
|  | ||||
|       .ai-list__content--right-wrapper { | ||||
|   | ||||
							
								
								
									
										397
									
								
								packages/conv/AppPatrolReportSet/AppPatrolReportSet.vue
									
									
									
									
									
										Normal file
									
								
							
							
						
						| @@ -0,0 +1,397 @@ | ||||
| <template> | ||||
|   <ai-detail class="AppPatrolReportSet"> | ||||
|     <ai-title slot="title" title="巡查上报设置"  isShowBottomBorder> | ||||
|       <el-button size="small" type="primary" icon="iconfont iconAdd" slot="rightBtn" @click="add">添加节点</el-button> | ||||
|     </ai-title> | ||||
|     <template slot="content"> | ||||
|       <div class="list" v-if="list.length"> | ||||
|         <div class="item" v-for="(item, index) in list" :key="index"> | ||||
|           <div class="btn"> | ||||
|             <el-button type="text" @click="edit(index)">编辑</el-button> | ||||
|             <el-button type="text" @click="del(index)">删除</el-button> | ||||
|           </div> | ||||
|           <div class="index">{{index < 9 ? `0${index+1}` : `${index+1}`}}</div> | ||||
|           <div class="info"> | ||||
|             <div class="label">节点类型</div> | ||||
|             <div class="value">{{item.nodeType == 0 ? '首节点' : $dict.getLabel('prfcNodeType', item.nodeType)}}</div> | ||||
|           </div> | ||||
|           <div class="info"> | ||||
|             <div class="label">上级节点网络</div> | ||||
|             <div class="value">{{item.girdName}}<span class="span" v-if="item.nodeType == 2 && item.onlyCoordination == '1'">仅协同部门</span></div> | ||||
|           </div> | ||||
|           <div class="flex"> | ||||
|             <div class="info"> | ||||
|               <div class="label">生效功能</div> | ||||
|               <div class="value"> | ||||
|                 <span v-if="item.functionAdd == 1">添加</span> | ||||
|                 <span v-if="item.functionHandle == 1">办理</span> | ||||
|                 <span v-if="item.functionTransmit == 1">转交</span> | ||||
|               </div> | ||||
|             </div> | ||||
|             <div class="info"> | ||||
|               <div class="label">生效身份</div> | ||||
|               <div class="value"> | ||||
|                 <span v-if="item.roleMember == 1">网格员</span> | ||||
|                 <span v-if="item.roleAdmin == 1">网格长</span> | ||||
|               </div> | ||||
|             </div> | ||||
|           </div> | ||||
|  | ||||
|           <div v-if="item.nodeType == 3"> | ||||
|             <div class="info"> | ||||
|               <div class="label">同级节点网络</div> | ||||
|               <div class="value">{{item.girdName2}}<span class="span" v-if="item.nodeType == 3 && item.onlyCoordination == '1'">仅协同部门</span></div> | ||||
|             </div> | ||||
|             <div class="flex"> | ||||
|               <div class="info"> | ||||
|                 <div class="label">生效功能</div> | ||||
|                 <div class="value"> | ||||
|                   <span v-if="item.functionAdd2 == 1">添加</span> | ||||
|                   <span v-if="item.functionHandle2 == 1">办理</span> | ||||
|                   <span v-if="item.functionTransmit2 == 1">转交</span> | ||||
|                 </div> | ||||
|               </div> | ||||
|               <div class="info"> | ||||
|                 <div class="label">生效身份</div> | ||||
|                 <div class="value"> | ||||
|                   <span v-if="item.roleMember2 == 1">网格员</span> | ||||
|                   <span v-if="item.roleAdmin2 == 1">网格长</span> | ||||
|                 </div> | ||||
|               </div> | ||||
|               <!-- <div class="info"> | ||||
|                 <div class="label">条件约束</div> | ||||
|                 <div class="value">名称约束</div> | ||||
|               </div> --> | ||||
|             </div> | ||||
|           </div> | ||||
|         </div> | ||||
|       </div> | ||||
|       <ai-empty v-else>暂无数据</ai-empty> | ||||
|        | ||||
|       <ai-dialog :visible.sync="dialog" :title="dialogTitle" @closed="$refs.form.resetFields()" @onConfirm="onConfirm" width="70%"> | ||||
|         <el-form ref="form" :rules="rules" size="small" :model="form" label-width="110px"> | ||||
|           <el-form-item label="节点类型" prop="nodeType" v-if="form.nodeType === '0'"> | ||||
|             <ai-select disabled | ||||
|               v-model="form.nodeType" | ||||
|               clearable | ||||
|               placeholder="请选择..." | ||||
|               :selectList="nodeTypeDictList"> | ||||
|             </ai-select> | ||||
|           </el-form-item> | ||||
|           <el-form-item label="节点类型" prop="nodeType" v-else> | ||||
|             <ai-select :disabled="getGirdList.length == 1 && form.nodeType == '1'" | ||||
|               v-model="form.nodeType" | ||||
|               clearable | ||||
|               placeholder="请选择..." | ||||
|               :selectList="dict.getDict('prfcNodeType')" @change="changeNodeType"> | ||||
|             </ai-select> | ||||
|           </el-form-item> | ||||
|           <el-form-item label="选择节点网格" prop="girdId" > | ||||
|             <ai-picker v-if="form.nodeType === '0'" | ||||
|               :ops="{label: 'girdName'}" | ||||
|               dialogTitle="选择节点网格" | ||||
|               action="/app/appgirdinfo/girdList" | ||||
|               :instance="instance" | ||||
|               @pick="onGirdChange" | ||||
|               v-model="form.girdIdList"> | ||||
|               <div class="userSelcet"> | ||||
|                 <span style="color: #606266;" v-if="form.girdIdList.length">{{ form.girdName }}</span> | ||||
|                 <span v-else>选择节点网格</span> | ||||
|                 <i class="el-icon-arrow-down"></i> | ||||
|               </div> | ||||
|             </ai-picker> | ||||
|             <el-input placeholder="节点网格" v-model="form.girdName" disabled v-else></el-input> | ||||
|             <el-checkbox v-model="sameLevelUsed" disabled>当前选中网格层级生效</el-checkbox> | ||||
|             <el-checkbox v-model="form.onlyCoordination" v-if="form.nodeType == '2'" true-label="1" false-label="0">仅协同部门</el-checkbox> | ||||
|           </el-form-item> | ||||
|           <el-form-item label="生效功能"> | ||||
|             <el-checkbox v-model="form.functionAdd" true-label="1" false-label="0">添加</el-checkbox> | ||||
|             <el-checkbox v-model="form.functionHandle" true-label="1" false-label="0">办理</el-checkbox> | ||||
|             <el-checkbox v-model="form.functionTransmit" true-label="1" false-label="0">转交</el-checkbox> | ||||
|           </el-form-item> | ||||
|           <el-form-item label="生效身份"> | ||||
|             <el-checkbox v-model="form.roleMember" true-label="1" false-label="0">网格员</el-checkbox> | ||||
|             <el-checkbox v-model="form.roleAdmin" true-label="1" false-label="0">网格长</el-checkbox> | ||||
|           </el-form-item> | ||||
|           <div v-if="form.nodeType == 3"> | ||||
|             <el-form-item label="同级节点网格" prop="girdId2"> | ||||
|               <el-input placeholder="节点网格" v-model="form.girdName2" disabled></el-input> | ||||
|               <el-checkbox v-model="sameLevelUsed" disabled>当前选中网格层级生效</el-checkbox> | ||||
|               <el-checkbox v-model="form.onlyCoordination" v-if="form.nodeType == '3'" true-label="1" false-label="0">仅协同部门</el-checkbox> | ||||
|             </el-form-item> | ||||
|             <el-form-item label="生效功能"> | ||||
|               <el-checkbox v-model="form.functionAdd2" true-label="1" false-label="0">添加</el-checkbox> | ||||
|               <el-checkbox v-model="form.functionHandle2" true-label="1" false-label="0">办理</el-checkbox> | ||||
|               <el-checkbox v-model="form.functionTransmit2" true-label="1" false-label="0">转交</el-checkbox> | ||||
|             </el-form-item> | ||||
|             <el-form-item label="生效身份"> | ||||
|               <el-checkbox v-model="form.roleMember2" true-label="1" false-label="0">网格员</el-checkbox> | ||||
|               <el-checkbox v-model="form.roleAdmin2" true-label="1" false-label="0">网格长</el-checkbox> | ||||
|             </el-form-item> | ||||
|           </div> | ||||
|         </el-form> | ||||
|       </ai-dialog> | ||||
|     </template> | ||||
|     <template slot="footer"> | ||||
|       <el-button @click="getList">返回</el-button> | ||||
|       <el-button type="primary" @click="confirm">提交</el-button> | ||||
|     </template> | ||||
|   </ai-detail> | ||||
| </template> | ||||
|  | ||||
| <script> | ||||
|   export default { | ||||
|     name: 'AppPatrolReportSet', | ||||
|     label: '巡查上报设置', | ||||
|  | ||||
|     props: { | ||||
|       instance: Function, | ||||
|       dict: Object, | ||||
|       permissions: Function | ||||
|     }, | ||||
|  | ||||
|     data () { | ||||
|       return { | ||||
|         dialog: false, | ||||
|         dialogTitle: '', | ||||
|         form: { | ||||
|           nodeType: '', //0:首节点、1:上级、2:同级、3:混合 | ||||
|           girdIdList: [], | ||||
|           girdId: '', | ||||
|           girdCode: '', | ||||
|           girdLevel: '', | ||||
|           girdName: '', | ||||
|           functionAdd: '1', | ||||
|           functionHandle: '1', | ||||
|           functionTransmit: '1', | ||||
|           roleAdmin: '1', | ||||
|           roleMember: '1', | ||||
|           girdId2: '', | ||||
|           girdCode2: '', | ||||
|           girdLevel2: '', | ||||
|           girdName2: '', | ||||
|           functionAdd2: '1', | ||||
|           functionHandle2: '1', | ||||
|           functionTransmit2: '1', | ||||
|           roleAdmin2: '1', | ||||
|           roleMember2: '1', | ||||
|           onlyCoordination: '1' | ||||
|         }, | ||||
|         list: [], | ||||
|         nodeTypeDictList: [{dictName: '首节点', dictValue: '0'}], | ||||
|         sameLevelUsed: true, | ||||
|         getGirdList: [], | ||||
|         editIndex: '' | ||||
|       } | ||||
|     }, | ||||
|     computed: { | ||||
|       rules() { | ||||
|         return { | ||||
|           nodeType: [{ required: true, message: '请选择节点类型', trigger: 'change'}], | ||||
|           girdId: [{ required: true, message: '请选择节点网络', trigger: 'change'}], | ||||
|           girdId2: [{ required: true, message: '请选择同级节点网格', trigger: 'change'}], | ||||
|         } | ||||
|       }, | ||||
|     }, | ||||
|     created() { | ||||
|       this.dict.load('prfcNodeType').then(() => { | ||||
|         this.getList() | ||||
|       }) | ||||
|     }, | ||||
|     methods: { | ||||
|       add() { | ||||
|         this.form = { | ||||
|           nodeType: '', //0:首节点、1:上级、2:同级、3:混合 | ||||
|           girdIdList: [], | ||||
|           girdId: '', | ||||
|           girdCode: '', | ||||
|           girdLevel: '', | ||||
|           girdName: '', | ||||
|           functionAdd: '1', | ||||
|           functionHandle: '1', | ||||
|           functionTransmit: '1', | ||||
|           roleAdmin: '1', | ||||
|           roleMember: '1', | ||||
|           girdId2: '', | ||||
|           girdCode2: '', | ||||
|           girdLevel2: '', | ||||
|           girdName2: '', | ||||
|           functionAdd2: '1', | ||||
|           functionHandle2: '1', | ||||
|           functionTransmit2: '1', | ||||
|           roleAdmin2: '1', | ||||
|           roleMember2: '1', | ||||
|           onlyCoordination: '1' | ||||
|         } | ||||
|         if(this.list.length > 0) { | ||||
|           this.getGird(this.list.length-1) | ||||
|         }else { //首节点 | ||||
|           this.form.nodeType = '0' | ||||
|         } | ||||
|         this.dialogTitle = '添加节点' | ||||
|         this.dialog = true | ||||
|         this.$refs.form.resetFields() | ||||
|       }, | ||||
|       del(index) { | ||||
|         this.$confirm('确定删除该节点?').then(() => { | ||||
|           this.list.splice(index, 1) | ||||
|         }) | ||||
|       }, | ||||
|       edit(index) { | ||||
|         this.editIndex = index | ||||
|         this.form = {...this.list[index]} | ||||
|         if(this.form.nodeType != '0') { | ||||
|           this.getGird(index-1) | ||||
|         }  | ||||
|         this.dialogTitle = '编辑节点' | ||||
|         this.dialog = true | ||||
|       }, | ||||
|       onConfirm() { | ||||
|         this.$refs.form.validate((valid) => { | ||||
|           if (valid) { | ||||
|             if(this.dialogTitle == '添加节点') { | ||||
|               this.list.push(this.form) | ||||
|             }else { | ||||
|               this.list.splice(this.editIndex, 1, this.form) | ||||
|             } | ||||
|             this.dialog = false | ||||
|           } | ||||
|         }) | ||||
|       }, | ||||
|       getList() { | ||||
|         this.instance.post(`/app/apppatrolreportflowconfigv2/queryNew`).then(res => { | ||||
|           if (res.code == 0) { | ||||
|             this.list = res.data | ||||
|           } | ||||
|         }) | ||||
|       }, | ||||
|       onGirdChange(e) { | ||||
|         this.form.girdId = e[0].id | ||||
|         this.form.girdCode = e[0].girdCode | ||||
|         this.form.girdLevel = e[0].girdLevel | ||||
|         this.form.girdName = e[0].girdName | ||||
|       }, | ||||
|       changeNodeType(e) { //1 上下级节点取数组0;2同级节点选择数组1; 3混合节点主取数组0,同级选择数组1 | ||||
|         console.log(e) | ||||
|         var arr = [] | ||||
|         if(e == 1) { | ||||
|           arr.push(this.getGirdList[0]) | ||||
|         } | ||||
|         if(e == 2) { | ||||
|           arr.push(this.getGirdList[1]) | ||||
|         } | ||||
|         if(e == 3) { | ||||
|           arr.push(this.getGirdList[0]) | ||||
|           this.form.girdId2 = this.getGirdList[1].id | ||||
|           this.form.girdCode2 = this.getGirdList[1].girdCode | ||||
|           this.form.girdLevel2 = this.getGirdList[1].girdLevel | ||||
|           this.form.girdName2 = this.getGirdList[1].girdName | ||||
|         } | ||||
|         this.onGirdChange(arr) | ||||
|       }, | ||||
|       getGird(index) { | ||||
|         var girdCode = this.list[index].girdCode | ||||
|         this.instance.post(`app/apppatrolreportflowconfigv2/choiseGird?previousGirdCode=${girdCode}`).then(res => { | ||||
|           if (res.code == 0) { | ||||
|             this.getGirdList = res.data | ||||
|             if(res.data.length == 1 && this.dialogTitle == '添加节点') { //返回数据一条表示nodeType 1 上下级节点;混合节点主去数组0,同级选择数组1;同级节点选择数组1 | ||||
|               this.form.nodeType = '1' | ||||
|               this.onGirdChange(res.data) | ||||
|             } | ||||
|           } | ||||
|         }) | ||||
|       }, | ||||
|       confirm() { | ||||
|         this.instance.post(`/app/apppatrolreportflowconfigv2/addOrUpdate`, this.list).then(res => { | ||||
|           if (res.code == 0) { | ||||
|             this.$message.success('提交成功') | ||||
|             this.getList() | ||||
|           } | ||||
|         }) | ||||
|       } | ||||
|     } | ||||
|   } | ||||
| </script> | ||||
|  | ||||
| <style lang="scss" scoped> | ||||
|   .AppPatrolReportSet { | ||||
|     height: 100%; | ||||
|     .list { | ||||
|       padding: 0 16px 16px; | ||||
|       background-color: #fff; | ||||
|     } | ||||
|     .item { | ||||
|       padding: 16px 0 4px 26px; | ||||
|       position: relative; | ||||
|       border-bottom: 1px solid #F2F2F2; | ||||
|       .info { | ||||
|         height: 22px; | ||||
|         font-family: MicrosoftYaHei; | ||||
|         font-size: 14px; | ||||
|         color: #888; | ||||
|         line-height: 22px; | ||||
|         margin-bottom: 16px; | ||||
|         .label { | ||||
|           display: inline-block; | ||||
|           width: 112px; | ||||
|           color: #888; | ||||
|         } | ||||
|         .value { | ||||
|           display: inline-block; | ||||
|           width: calc(100% - 112px); | ||||
|           color: #222; | ||||
|           span { | ||||
|             display: inline-block; | ||||
|             margin-right: 24px; | ||||
|           } | ||||
|           .span { | ||||
|             margin-left: 16px; | ||||
|           } | ||||
|         } | ||||
|       } | ||||
|       .index { | ||||
|         position: absolute; | ||||
|         top: 16px; | ||||
|         left: 0; | ||||
|         height: 21px; | ||||
|         font-family: DINAlternate-Bold; | ||||
|         font-weight: 700; | ||||
|         font-size: 18px; | ||||
|         color: #666; | ||||
|       } | ||||
|       .btn { | ||||
|         position: absolute; | ||||
|         right: 0; | ||||
|         top: 16px; | ||||
|       } | ||||
|       .flex { | ||||
|         display: flex; | ||||
|         .info { | ||||
|           width: 33.3%; | ||||
|         } | ||||
|       } | ||||
|     } | ||||
|     :deep(.ai-select), | ||||
|     :deep(.el-input) { | ||||
|       display: inline-block; | ||||
|       width: 50%; | ||||
|       margin-right: 16px; | ||||
|     } | ||||
|     :deep(.AiPicker) { | ||||
|       display: inline-block; | ||||
|       width: 50%; | ||||
|       margin-right: 16px; | ||||
|       border: 1px solid #d0d4dc; | ||||
|       padding-left: 16px; | ||||
|       box-sizing: border-box; | ||||
|       border-radius: 4px; | ||||
|       position: relative; | ||||
|       .el-icon-arrow-down { | ||||
|         position: absolute; | ||||
|         top: 8px; | ||||
|         right: 8px; | ||||
|       } | ||||
|     } | ||||
|      | ||||
|   } | ||||
| </style> | ||||
| @@ -1,6 +1,6 @@ | ||||
| <template> | ||||
|   <section class="AppReportAtWill"> | ||||
|     <component ref="component" :is="currentPage" @change="onChange" :params="params" :instance="instance" :dict="dict"/> | ||||
|     <component ref="component" :is="currentPage" @change="onChange" :params="params" :instance="instance" :dict="dict" :menuName="menuName" /> | ||||
|   </section> | ||||
| </template> | ||||
|  | ||||
| @@ -15,7 +15,8 @@ export default { | ||||
|  | ||||
|   props: { | ||||
|     instance: Function, | ||||
|     dict: Object | ||||
|     dict: Object, | ||||
|     menuName: {default: '随手拍'} | ||||
|   }, | ||||
|  | ||||
|   data() { | ||||
|   | ||||
| @@ -1,7 +1,7 @@ | ||||
| <template> | ||||
|   <ai-detail class="reportAtWillDetail" v-loading="isLoading"> | ||||
|     <template #title> | ||||
|       <ai-title title="随手拍详情" isShowBack isShowBottomBorder @onBackClick="cancel(false)"> | ||||
|       <ai-title title="详情" isShowBack isShowBottomBorder @onBackClick="cancel(false)"> | ||||
|         <template #rightBtn> | ||||
|           <div class="title-btns"> | ||||
|             <el-button type="primary" icon="iconfont iconPerson_Transfered" @click="isShowForward = true" v-if="detail.eventStatus < 2">指派事件</el-button> | ||||
| @@ -12,31 +12,34 @@ | ||||
|     </template> | ||||
|     <template #content> | ||||
|       <div class="detail-content__wrapper"> | ||||
|         <ai-card class="detail-content__wrapper--left" title="基础信息"> | ||||
|           <template #content> | ||||
|             <ai-wrapper> | ||||
|               <ai-info-item label="上报人员" :value="detail.name"></ai-info-item> | ||||
|               <ai-info-item label="当前状态" :value="dict.getLabel('clapEventStatus', detail.eventStatus)"></ai-info-item> | ||||
|               <ai-info-item label="联系方式">{{ detail.phone }}</ai-info-item> | ||||
|               <ai-info-item label="上报时间">{{ detail.createTime }}</ai-info-item> | ||||
|               <ai-info-item label="事件类型">{{ detail.groupName }}</ai-info-item> | ||||
|               <ai-info-item label="事件描述" isLine>{{ detail.content }}</ai-info-item> | ||||
|               <ai-info-item label="现场照片" isLine> | ||||
|                 <ai-uploader :instance="instance" disabled v-model="detail.files"></ai-uploader> | ||||
|               </ai-info-item> | ||||
|               <ai-info-item label="所属网格">{{ detail.girdName }}</ai-info-item> | ||||
|               <ai-info-item label="事件位置" isLine> | ||||
|                 <div id="map" style="width: 500px; height: 280px;"></div> | ||||
|               </ai-info-item> | ||||
|             </ai-wrapper> | ||||
|           </template> | ||||
|         </ai-card> | ||||
|         <div class="detail-content__wrapper--left"> | ||||
|           <ai-card title="基础信息"> | ||||
|             <template #content> | ||||
|               <ai-wrapper> | ||||
|                 <ai-info-item label="上报人员" :value="detail.name"></ai-info-item> | ||||
|                 <ai-info-item label="当前状态" :value="dict.getLabel('clapEventStatus', detail.eventStatus)"></ai-info-item> | ||||
|                 <ai-info-item label="联系方式">{{ detail.phone }}</ai-info-item> | ||||
|                 <ai-info-item label="上报时间">{{ detail.createTime }}</ai-info-item> | ||||
|                 <ai-info-item label="事件类型">{{ detail.groupName }}</ai-info-item> | ||||
|                 <ai-info-item label="事件描述" isLine>{{ detail.content }}</ai-info-item> | ||||
|                 <ai-info-item label="现场照片" isLine> | ||||
|                   <ai-uploader :instance="instance" disabled v-model="detail.files"></ai-uploader> | ||||
|                 </ai-info-item> | ||||
|                 <ai-info-item label="所属网格">{{ detail.girdName }}</ai-info-item> | ||||
|                 <ai-info-item label="事件位置" isLine> | ||||
|                   <div id="map" style="width: 500px; height: 280px;"></div> | ||||
|                 </ai-info-item> | ||||
|               </ai-wrapper> | ||||
|             </template> | ||||
|           </ai-card> | ||||
|           <ai-evaluation v-if="!!detail.id" :bid="detail.id" :info.sync="evaluation"/> | ||||
|         </div> | ||||
|         <div class="rightZone"> | ||||
|           <ai-card title="办理进度"> | ||||
|             <template #content> | ||||
|               <el-steps direction="vertical" :active="1"> | ||||
|                 <el-step | ||||
|                     v-for="(item, i) in processList" | ||||
|                     v-for="(item, i) in process" | ||||
|                     :key="i" | ||||
|                     :title="item.systemExplain" | ||||
|                     :description="item.doTime"> | ||||
| @@ -190,12 +193,18 @@ export default { | ||||
|         groupName: '', | ||||
|         content: [], | ||||
|         eventStatus: '2' | ||||
|       } | ||||
|       }, | ||||
|       evaluation: {} | ||||
|     } | ||||
|   }, | ||||
|  | ||||
|   computed: { | ||||
|     ...mapState(['user']) | ||||
|     ...mapState(['user']), | ||||
|     process: v => [v.evaluation.id ? { | ||||
|       systemExplain: `${v.evaluation.createUserName}完成评价 (${v.evaluation.score}星评价)`, | ||||
|       doTime: v.evaluation.createTime, | ||||
|       doExplain: v.evaluation.rateText | ||||
|     } : null, v.processList].flat().filter(Boolean) | ||||
|   }, | ||||
|  | ||||
|   created() { | ||||
| @@ -260,10 +269,9 @@ export default { | ||||
|       return list | ||||
|     }, | ||||
|  | ||||
|     filterNode(value, data) { | ||||
|     filterNode(value, data = {}) { | ||||
|       if (!value) return true | ||||
|  | ||||
|       return (data.girdName && data.girdName.indexOf(value) !== -1) || (data.name && data.name.indexOf(value) !== -1) || (data.name && data.phone.indexOf(value) !== -1) | ||||
|       return ["girdName", "name", "phone"].some(e => data[e]?.includes(value)) | ||||
|     }, | ||||
|  | ||||
|     onTreeChange(e) { | ||||
| @@ -393,7 +401,7 @@ export default { | ||||
|     align-items: center; | ||||
|   } | ||||
|  | ||||
|   ::v-deep .el-tree { | ||||
|   :deep( .el-tree ) { | ||||
|     background: transparent; | ||||
|  | ||||
|     .el-tree-node__expand-icon.is-leaf { | ||||
| @@ -438,13 +446,13 @@ export default { | ||||
|   } | ||||
|  | ||||
|   .el-steps { | ||||
|     ::v-deep .el-step__icon { | ||||
|     :deep( .el-step__icon ) { | ||||
|       font-size: 12px; | ||||
|       color: #555555; | ||||
|       border-color: #d0d4dc; | ||||
|     } | ||||
|  | ||||
|     ::v-deep .el-step__head.is-finish { | ||||
|     :deep( .el-step__head.is-finish ) { | ||||
|       .el-step__icon.is-text { | ||||
|         border: none; | ||||
|         color: #fff; | ||||
| @@ -453,7 +461,7 @@ export default { | ||||
|       } | ||||
|     } | ||||
|  | ||||
|     ::v-deep .el-step__line { | ||||
|     :deep( .el-step__line ) { | ||||
|       background-color: #d0d4dc; | ||||
|     } | ||||
|   } | ||||
| @@ -479,18 +487,18 @@ export default { | ||||
|     } | ||||
|   } | ||||
|  | ||||
|   ::v-deep .report-dialog { | ||||
|   :deep( .report-dialog ) { | ||||
|     .el-select { | ||||
|       width: 100%; | ||||
|     } | ||||
|   } | ||||
|  | ||||
|   ::v-deep .el-step__head.is-process { | ||||
|   :deep( .el-step__head.is-process ) { | ||||
|     color: #555; | ||||
|     border-color: #555; | ||||
|   } | ||||
|  | ||||
|   ::v-deep .is-finish h2 { | ||||
|   :deep( .is-finish h2 ) { | ||||
|     color: #2266ff; | ||||
|   } | ||||
|  | ||||
| @@ -501,6 +509,7 @@ export default { | ||||
|   .detail-content__wrapper { | ||||
|     display: flex; | ||||
|     width: 100%; | ||||
|     flex-wrap: wrap; | ||||
|  | ||||
|     .detail-content__wrapper--left { | ||||
|       flex: 1; | ||||
| @@ -508,7 +517,7 @@ export default { | ||||
|     } | ||||
|   } | ||||
|  | ||||
|   ::v-deep .ai-detail__content { | ||||
|   :deep( .ai-detail__content ) { | ||||
|     background: #f3f6f9; | ||||
|  | ||||
|     .ai-detail__content--wrapper { | ||||
| @@ -534,7 +543,7 @@ export default { | ||||
|     } | ||||
|   } | ||||
|  | ||||
|   ::v-deep .el-card { | ||||
|   :deep( .el-card ) { | ||||
|     .el-card__header { | ||||
|       padding: 12px 16px; | ||||
|       font-weight: bold; | ||||
|   | ||||
| @@ -1,7 +1,7 @@ | ||||
| <template> | ||||
|   <ai-list> | ||||
|     <template #title> | ||||
|       <ai-title title="随手拍" isShowBottomBorder> | ||||
|       <ai-title :title="menuName" isShowBottomBorder> | ||||
|         <el-button type="primary" slot="rightBtn" @click="toSetting">设置</el-button> | ||||
|       </ai-title> | ||||
|     </template> | ||||
| @@ -51,7 +51,8 @@ export default { | ||||
|  | ||||
|   props: { | ||||
|     instance: Function, | ||||
|     dict: Object | ||||
|     dict: Object, | ||||
|     menuName: String | ||||
|   }, | ||||
|  | ||||
|   data() { | ||||
| @@ -81,7 +82,7 @@ export default { | ||||
|         {prop: 'createTime', label: '上报时间', align: 'center'}, | ||||
|         {prop: 'name', label: '上报居民', align: 'center'}, | ||||
|         {prop: 'phone', label: '联系方式', align: 'center'}, | ||||
|         {prop: 'eventStatus', label: '处理状态', align: 'center', formart: v => this.dict.getLabel('clapEventStatus', v)}, | ||||
|         {prop: 'eventStatus', label: '处理状态', align: 'center', format: v => this.dict.getLabel('clapEventStatus', v)}, | ||||
|         {prop: 'processTime', label: '处理时长', align: 'center'}, | ||||
|         {slot: 'options'} | ||||
|       ] | ||||
|   | ||||
| @@ -78,19 +78,19 @@ | ||||
|         colConfigs: [ | ||||
|           { prop: 'name', label: '姓名' }, | ||||
|           { prop: 'phone', align: 'center', label: '手机号码' }, | ||||
|           { prop: 'startTime', align: 'center', label: '出发时间', formart: v => v.substr(0, v.length - 3) }, | ||||
|           { prop: 'startTime', align: 'center', label: '出发时间', format: v => v.substr(0, v.length - 3) }, | ||||
|           { | ||||
|             prop: 'startAreaName', | ||||
|             align: 'center', | ||||
|             label: '出发地区' | ||||
|           }, | ||||
|           { prop: 'arriveTime', align: 'center', label: '到达时间', formart: v => v.substr(0, v.length - 3) },  | ||||
|           { prop: 'arriveTime', align: 'center', label: '到达时间', format: v => v.substr(0, v.length - 3) }, | ||||
|           { | ||||
|             prop: 'arriveAreaName', | ||||
|             align: 'center', | ||||
|             label: '到达地区' | ||||
|           }, | ||||
|           { prop: 'checkTime', align: 'center', label: '核酸日期', formart: v => v.split(' ')[0] }, | ||||
|           { prop: 'checkTime', align: 'center', label: '核酸日期', format: v => v.split(' ')[0] }, | ||||
|           { | ||||
|             prop: 'status', | ||||
|             align: 'center', | ||||
| @@ -146,7 +146,7 @@ | ||||
|         }).catch(() => { | ||||
|           this.loading = false | ||||
|         }) | ||||
|          | ||||
|  | ||||
|         this.getTotalInfo() | ||||
|       }, | ||||
|  | ||||
|   | ||||
| @@ -102,19 +102,19 @@ | ||||
|         colConfigs: [ | ||||
|           { prop: 'name', label: '姓名' }, | ||||
|           { prop: 'phone', align: 'center', label: '手机号码' }, | ||||
|           { prop: 'startTime', align: 'center', label: '出发时间', formart: v => v.substr(0, v.length - 3) }, | ||||
|           { prop: 'startTime', align: 'center', label: '出发时间', format: v => v.substr(0, v.length - 3) }, | ||||
|           { | ||||
|             prop: 'startAreaName', | ||||
|             align: 'center', | ||||
|             label: '出发地区' | ||||
|           }, | ||||
|           { prop: 'arriveTime', align: 'center', label: '到达时间', formart: v => v.substr(0, v.length - 3) },  | ||||
|           { prop: 'arriveTime', align: 'center', label: '到达时间', format: v => v.substr(0, v.length - 3) }, | ||||
|           { | ||||
|             prop: 'arriveAreaName', | ||||
|             align: 'center', | ||||
|             label: '到达地区' | ||||
|           }, | ||||
|           { prop: 'checkTime', align: 'center', label: '核酸日期', formart: v => v.split(' ')[0] }, | ||||
|           { prop: 'checkTime', align: 'center', label: '核酸日期', format: v => v.split(' ')[0] }, | ||||
|           { | ||||
|             prop: 'status', | ||||
|             align: 'center', | ||||
| @@ -170,7 +170,7 @@ | ||||
|         }).catch(() => { | ||||
|           this.loading = false | ||||
|         }) | ||||
|          | ||||
|  | ||||
|         this.getTotalInfo() | ||||
|       }, | ||||
|  | ||||
| @@ -222,7 +222,7 @@ | ||||
|  | ||||
| <style scoped lang="scss"> | ||||
|   .list { | ||||
|     ::v-deep .ai-list__content { | ||||
|     :deep( .ai-list__content ){ | ||||
|       padding: 0!important; | ||||
|  | ||||
|       .ai-list__content--right-wrapper { | ||||
|   | ||||
| @@ -77,7 +77,7 @@ | ||||
|           { prop: 'district', label: '区级', align: 'center' }, | ||||
|           { prop: 'town', label: '镇级', align: 'center' }, | ||||
|           { prop: 'village', label: '村级', align: 'center' }, | ||||
|           { prop: 'level', label: '等级', align: 'center', formart: v => this.dict.getLabel('epidemicDangerousAreaLevel', v) }, | ||||
|           { prop: 'level', label: '等级', align: 'center', format: v => this.dict.getLabel('epidemicDangerousAreaLevel', v) }, | ||||
|           { prop: 'createTime', label: '设置时间', align: 'center' }, | ||||
|           { prop: 'createUserName', label: '添加人', align: 'center' }, | ||||
|           { slot: 'options', label: '操作', align: 'center' } | ||||
|   | ||||
| @@ -62,6 +62,7 @@ | ||||
| <script> | ||||
| import {mapState} from "vuex"; | ||||
| import AddVaccination from "./addVaccination"; | ||||
| import {ID} from "dui/lib/js/utils"; | ||||
|  | ||||
| export default { | ||||
|   name: "AppVaccination", | ||||
| @@ -108,7 +109,7 @@ export default { | ||||
|         {label: "出生日期", prop: "birthday", align: 'center'}, | ||||
|         { | ||||
|           label: "身份证号", width: "160px", align: 'center', | ||||
|           render: (h, {row}) => h('span', null, this.idCardNoUtil.hideId(row.idNumber)) | ||||
|           render: (h, {row}) => h('span', null, ID.hideId(row.idNumber)) | ||||
|         }, | ||||
|         {label: "所属地区", prop: "areaName", align: 'center'}, | ||||
|         {label: "住址", prop: "address", width: "200px", align: 'center'}, | ||||
| @@ -170,7 +171,7 @@ export default { | ||||
| .AppVaccination { | ||||
|   height: 100%; | ||||
|  | ||||
|   ::v-deep .dataPane { | ||||
|   :deep( .dataPane ){ | ||||
|     flex: 1; | ||||
|     min-width: 0; | ||||
|     background: #FFFFFF; | ||||
| @@ -188,7 +189,7 @@ export default { | ||||
|     } | ||||
|   } | ||||
|  | ||||
|   ::v-deep .mainPane { | ||||
|   :deep( .mainPane ){ | ||||
|     background: #fff; | ||||
|     padding: 12px 16px; | ||||
|     box-shadow: 0 4px 6px -2px rgba(15, 15, 21, 0.15); | ||||
|   | ||||
| @@ -82,6 +82,7 @@ | ||||
|  | ||||
| <script> | ||||
| import {mapState} from "vuex"; | ||||
| import {ID} from "dui/lib/js/utils"; | ||||
|  | ||||
| export default { | ||||
|   name: "addVaccination", | ||||
| @@ -183,9 +184,9 @@ export default { | ||||
|       this.form = {...this.form, name, idNumber, phone, areaId, address} | ||||
|     }, | ||||
|     getInfoByIdNumber(code) { | ||||
|       if (this.idCardNoUtil.checkIdCardNo(code)) { | ||||
|         let info = this.idCardNoUtil.getIdCardInfo(code) | ||||
|         this.form.sex = this.dict.getValue('sex', info.gender) | ||||
|       if (ID.check(code)) { | ||||
|         let info = new ID(code) | ||||
|         this.form.sex = info.sex | ||||
|         this.form.birthday = info.birthday | ||||
|         this.$forceUpdate() | ||||
|       } | ||||
| @@ -205,7 +206,7 @@ export default { | ||||
| .addVaccination { | ||||
|   height: 100%; | ||||
|  | ||||
|   ::v-deep .ai-card__body, .el-form { | ||||
|   :deep( .ai-card__body), .el-form { | ||||
|     display: flex; | ||||
|     flex-wrap: wrap; | ||||
|   } | ||||
| @@ -226,7 +227,7 @@ export default { | ||||
|     } | ||||
|   } | ||||
|  | ||||
|   ::v-deep .el-button { | ||||
|   :deep( .el-button ){ | ||||
|     .iconfont { | ||||
|       color: inherit | ||||
|     } | ||||
|   | ||||