Compare commits
1109 Commits
clay
...
zhangkaihu
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
4371ccb5e7 | ||
|
|
f9ef5c7087 | ||
|
|
f42eacd06e | ||
| 861a6489c7 | |||
| 9133f7a7e3 | |||
| e9be87990c | |||
| ec8db3c199 | |||
| d2520336cb | |||
| e97db1a70d | |||
| afd27e38b5 | |||
| 7dd5120133 | |||
| 75da0633e5 | |||
| 41b498066f | |||
| c852448089 | |||
| 9cd744d44e | |||
| a7917137c9 | |||
| 85346fa343 | |||
| e5b205870d | |||
| 5ae66763e1 | |||
| 9221d27960 | |||
| c442b9b2fd | |||
| 25c94284ca | |||
| 5da74960f2 | |||
| cdcb76d009 | |||
| c87b5c57a6 | |||
| fd0d70072b | |||
| 747f675cfc | |||
| 941b06ab8b | |||
| 3e6f86abfd | |||
| 01ccc1ddcd | |||
| b6ac47e88b | |||
| 707486c69d | |||
| 2ef726b95b | |||
| 697af99240 | |||
| ee2f7a9162 | |||
| 476f6a794d | |||
| 0c53ee8392 | |||
| 4c1e892d35 | |||
| ac6d7863da | |||
| ea33ffb60a | |||
| a1ae39cbd7 | |||
| 0ada78f180 | |||
| 60e29aca8d | |||
| 3db2901a03 | |||
| 7428fe43d4 | |||
| 18592571a4 | |||
| 4bb03409f4 | |||
| 7fec9c5735 | |||
| 3d9f22d503 | |||
| 76c9a38718 | |||
| af7d0ac580 | |||
| 4888a7e077 | |||
| 47a2f61036 | |||
| f26e40df90 | |||
| 07103258f7 | |||
| 8fa0d72cc4 | |||
| 7684444e93 | |||
| 81446971e5 | |||
| 5930a2c4b6 | |||
| 052c0090e3 | |||
| d24892141a | |||
| 83dc28630b | |||
| 086fdb36e9 | |||
| ba4c4fccdd | |||
| bc79cfc0bc | |||
| 35d4d1b7ba | |||
| 71324efd0c | |||
| 781e7393e8 | |||
| 1eea7a377c | |||
| 065eb6cfba | |||
| 35a2f755a2 | |||
| 9bd9cda872 | |||
| dd6181880a | |||
| cd2bfe8817 | |||
| 8b6406c4e0 | |||
| fa3171fecd | |||
| 177ccee058 | |||
| 28de3667f5 | |||
| 05a5385d87 | |||
| 529f482bc7 | |||
| 20fb592584 | |||
| bd35243cbd | |||
| d7ca84a4a0 | |||
| 6c7eddcf94 | |||
| 3588257f61 | |||
| 6c47337318 | |||
| bacd397294 | |||
| b3dbb24bb2 | |||
| 9e194f5f04 | |||
| f448ec47a3 | |||
| f633862434 | |||
| a4674d497b | |||
| e8aee6f01c | |||
| 43e0f98509 | |||
| 10b66cbf15 | |||
| 560bea739c | |||
| 1ed6156117 | |||
| 4321b42003 | |||
| 7f0f74c844 | |||
| c1065cb084 | |||
| 579cadd687 | |||
| 78f4135efb | |||
| 1a120418f0 | |||
| d3ae1c1205 | |||
| e49b6ef1a3 | |||
| 6fbf37ab78 | |||
| a0d9c58c77 | |||
| b3900a2a1c | |||
| 4bb0c49dc8 | |||
| 4f6c36a20a | |||
| aada3d785b | |||
| fef4c57bd5 | |||
| 35b332f640 | |||
| 31da00d7e3 | |||
| 6afac9be28 | |||
| b54289a0a5 | |||
| dc064de364 | |||
| 7f656447b2 | |||
| 78bafe0a7e | |||
| ddf5159fbc | |||
| d0960f6ad6 | |||
| e7b982ef6c | |||
| b5ada3a1ac | |||
| 418effdb04 | |||
| 215f7c6bbf | |||
| 57a1d2700f | |||
| e4025b90e9 | |||
| e44380c000 | |||
| 70d94f3c1d | |||
| 14c6ed1168 | |||
| 05275aed15 | |||
| 47d5863361 | |||
| 9758981d3f | |||
| a946247849 | |||
| 7c2d713035 | |||
| f4330b60d5 | |||
| 1a38381ab8 | |||
| f61d50dbfc | |||
| f5b9339b36 | |||
| 66dc6df0d9 | |||
| a3c7439a7f | |||
| c7329f2f6d | |||
| 59699b6118 | |||
| 673e4fa20a | |||
| eb2a5581ca | |||
| ee5fc2cba3 | |||
| 952884a7fe | |||
| b7ca97696a | |||
| 6ba9fa4bee | |||
| baea68c52a | |||
| a2ed04e144 | |||
| 8a218ad270 | |||
| 287d6a3ad0 | |||
| 9813f8c585 | |||
| 673a26368a | |||
| 9b90dbc649 | |||
| 9adea1060c | |||
| 4f471494cc | |||
| 4e5a4bb4b9 | |||
| b4d6d97e27 | |||
| a5ebab16a6 | |||
| 6ad76d1571 | |||
| 0cc1b63ae7 | |||
| d76ef8ff9c | |||
| f105485714 | |||
| df99acd638 | |||
| af275ea6c4 | |||
| 68830daab3 | |||
| c27162f918 | |||
| f1b81d86a2 | |||
| 0c24d2cf51 | |||
| 710ccbdf65 | |||
| 7001261f01 | |||
| 7fcfc992fb | |||
| b7be0a34ae | |||
| a792df80e6 | |||
| b56e5b3544 | |||
| 5dccaa1ee7 | |||
| 6aa074bfa3 | |||
| 8aefca0c82 | |||
| e518791ddd | |||
| afda146103 | |||
| 11f7fa37aa | |||
| 35c2e1d9b4 | |||
| fe3a15fcbd | |||
| 9fd97f6ea2 | |||
| cccd14ec79 | |||
| 2ed2cae599 | |||
| 958399a32a | |||
| 745971087c | |||
| 8ea916c206 | |||
| e0aefecf50 | |||
| 10e9c9de19 | |||
| 950b32270b | |||
| b032903ed4 | |||
| 696921243e | |||
| 7200592f05 | |||
| 963b7b93e3 | |||
| 86751acbd6 | |||
| c17149235f | |||
| fda0f4fcde | |||
| 560485f255 | |||
| 2847c88c61 | |||
| 5611fd9f02 | |||
| 2827c5ace6 | |||
| 750a4c8178 | |||
| 9941fc14f6 | |||
| 8b94f044db | |||
| c71208c3e4 | |||
| b2fb3fbb67 | |||
| 7e6b48b62a | |||
| 4aa0b093bb | |||
| e77820e145 | |||
| 66d2c3c7cf | |||
| a1422067d0 | |||
| 7579b77b2d | |||
| c6390a8117 | |||
| e20f8cad7f | |||
| 5cf2e4d208 | |||
| 4f3a8550eb | |||
| ad6d7af1a3 | |||
| 65a4c72fd0 | |||
| 5ea25ae8ae | |||
| 810757e828 | |||
| e82c6e2316 | |||
| af593b08da | |||
| 2b14bd19a4 | |||
| da69cb4dba | |||
| cc1d0c8cf2 | |||
| f3d9ff44a3 | |||
| 375a678fc3 | |||
| a3cbf4d24b | |||
| d3b12bd64c | |||
| c213b3b41c | |||
| d0c677cfb4 | |||
| e9469439e8 | |||
| 62035606c9 | |||
| b101d70c75 | |||
| 382bad4cb3 | |||
| 8c5d08874f | |||
| 25d5b20b65 | |||
| 2f43919132 | |||
| 8f5b9fc637 | |||
| 7b619a9bef | |||
| f33543c540 | |||
| a9a2be2c74 | |||
| 3160e86710 | |||
| a307697028 | |||
| 062f9c7bee | |||
| e8a5b4e788 | |||
| da9624663e | |||
| 7b8cedcfb0 | |||
| d3c0b36657 | |||
| eabf9cb3d6 | |||
| b84c2ce131 | |||
| 348027f355 | |||
| 579f2777cf | |||
| ed22942ab2 | |||
| 119e3d8333 | |||
| 011566cb22 | |||
| bf34d8aa0c | |||
| 7f3fedc2f2 | |||
| 69aa6aa0fb | |||
| e54db551a6 | |||
| 6c91a0740a | |||
| f0fe6c8269 | |||
| 9174c09a6b | |||
| 4dc5ca40ee | |||
| 09705e634a | |||
| 1e29e6bdc4 | |||
| e49d8cfb5e | |||
| a3bb1a9156 | |||
| e9ced267ed | |||
| ef9a536b5c | |||
| a87be0e6e2 | |||
| 98d8ea4805 | |||
| 244f2e72b4 | |||
| f9aa6191ce | |||
| ebd7fa3851 | |||
| 2941847f54 | |||
| ca9e281119 | |||
| a1ed160445 | |||
| 9db0e8e9ec | |||
| fe09ced0bc | |||
| d73eb49461 | |||
| b890372fc5 | |||
| 53bab74ea9 | |||
|
|
023256630e | ||
|
|
f65663071a | ||
|
|
9a55494da7 | ||
|
|
d5a07e772f | ||
|
|
42499bcb22 | ||
|
|
0243d6fc56 | ||
|
|
6bdbde262f | ||
|
|
78435bbcac | ||
|
|
c3358acf73 | ||
|
|
3b1b822882 | ||
| f874cd75b7 | |||
| d9a5099436 | |||
| dd75bc6513 | |||
| d3506d841e | |||
| 263df9e489 | |||
| 65b76da880 | |||
| 50973efb0a | |||
| 8256c80648 | |||
| d0dc8ba9f8 | |||
| 97e9799b1a | |||
| e81b2bc42f | |||
| 9c297d92c9 | |||
| e2de62e54a | |||
| a3b1f96ab6 | |||
| d2c77b9cc2 | |||
| 61feb031aa | |||
| b06b4b88bb | |||
| 560fd3af3b | |||
| e5b5b26e24 | |||
| 19aa70a8ca | |||
| 06af12ca88 | |||
| 41b04e6fac | |||
| 96d912ff44 | |||
| 10f1afe23c | |||
| 0f2cb87f66 | |||
| e10978cadd | |||
| 7ce2d6edb7 | |||
| 5f8a29f2d6 | |||
| ccba937158 | |||
| efe27b8580 | |||
| 7a535c41e7 | |||
| edffc54453 | |||
| 1cf05c8653 | |||
| 7f4a3a274e | |||
| f5b3791762 | |||
| 6e5c7d172d | |||
| 4123a685b7 | |||
| 7e25e76683 | |||
| 2fe09971ab | |||
| dc099c9347 | |||
| 7e7aac5139 | |||
| 54e7a8f662 | |||
| 43785b7460 | |||
| eed18d0c17 | |||
| ad969d33bb | |||
| b41e39abbf | |||
| 981d65c759 | |||
| d7e36ee464 | |||
| 54eeefd5dd | |||
| 049091719a | |||
| df6f0083ea | |||
| a5486c1948 | |||
| 5f120bff1e | |||
| f6d5a97dfb | |||
| a6ace0a27d | |||
| 70a4899337 | |||
| b2eec2e1f3 | |||
| 5506ebee7a | |||
| a6fd326774 | |||
| 348edd66bd | |||
| d58579579d | |||
| 3139c78179 | |||
| 252a077dcd | |||
| 45aaaf5360 | |||
| 87d5677352 | |||
| 39c9408f34 | |||
| 193862f58b | |||
| 36624c5621 | |||
| 08da2601d8 | |||
| 24563fd7df | |||
| 4b4aed5600 | |||
| a175a6456a | |||
| 6de9896ead | |||
| 0bbe97c582 | |||
| 960d294870 | |||
| f3fbb8d76b | |||
| 60df95cc20 | |||
| 8a0f6c6f37 | |||
| 99be2b0501 | |||
| d8a1a661df | |||
| 942603c344 | |||
| 54772cbbb1 | |||
| f720c3cddb | |||
| a4e95e21b3 | |||
| 53b581e71c | |||
| 0a6803371b | |||
| 604a0fedb8 | |||
| 8f226e6fa3 | |||
| fb48952924 | |||
| 44eb378423 | |||
| 40ba004082 | |||
| 1a5dda5302 | |||
| 2b2e54957f | |||
| db2a062400 | |||
| cde8d9f0b4 | |||
| f36d7abca8 | |||
| 4f2bfb80ae | |||
| a560460cc1 | |||
| 7ee2f084db | |||
| b5d2dceda1 | |||
| 7d234e523b | |||
| 7c7984b08f | |||
| 68f9c787e9 | |||
| bf6779a008 | |||
| baecbac6c3 | |||
| ea625f98f3 | |||
| 065a232333 | |||
| 9b2baf43ef | |||
| 49596316f2 | |||
| 4c492a8866 | |||
| 203721e9e0 | |||
| 1a72339ade | |||
| bb84f72836 | |||
| 83a740de91 | |||
| fb0a0cd719 | |||
| 45b8b91152 | |||
| 2b36fd181f | |||
| 5c2ec69fd6 | |||
| ffe7d0bb6c | |||
| 94a46d01fe | |||
| 99d8bc156b | |||
| e78ae692ee | |||
| 80bf9ae9bd | |||
| 7be10381bd | |||
| 1fbd31f137 | |||
| 9d55426a2a | |||
| e0299baf46 | |||
| 39fedea1ca | |||
| ed8104ba92 | |||
| c5d7961b4d | |||
| ec9c4c526c | |||
| 0cb840a466 | |||
| b8aa24e6a0 | |||
| e3b17f0f04 | |||
| a1b249b86c | |||
| d12d4865c7 | |||
| a01cede9c0 | |||
| 318410ff74 | |||
| a8feed2d7f | |||
| fe0a6bb3be | |||
| 872c54abd3 | |||
| c2c1cfd6e1 | |||
| 41bd6d1686 | |||
| 779d6f7094 | |||
| 5c4f25dc1a | |||
| e65bf98db2 | |||
| c17396d44a | |||
| 344a3a03b3 | |||
| dc8fc056f9 | |||
| 9ff596c167 | |||
| a82030b04f | |||
| d316661574 | |||
| 3690235ae7 | |||
| 2a788fff0a | |||
| a3b93d0e1a | |||
| 3d6bdd50ca | |||
| 20b2203930 | |||
| d23a86e9ea | |||
| 6afc855cd8 | |||
| 44a50176cc | |||
| 069816e17f | |||
| 57ec7832f2 | |||
| dfdaabeb48 | |||
| f427fa9ef2 | |||
| bfc6845071 | |||
| ea9047ee2a | |||
| 87ab014111 | |||
| 1341f3749b | |||
| 30f3f3bdcd | |||
| f9d7b765d1 | |||
| fbb277cb30 | |||
| 145bb01fdd | |||
| 7601a7872c | |||
| f36c8ffcac | |||
| de0b64909d | |||
| 39af97815c | |||
| bcffdba692 | |||
| 2e9d015623 | |||
| 4654f71f11 | |||
| 9d63e05d03 | |||
| 6ea9538b0a | |||
| 88f4a93a81 | |||
| 9671d5a36d | |||
| f476dc9203 | |||
| 235ec0c4ff | |||
| f2ba567b93 | |||
| 525385cd17 | |||
| ee8df164d1 | |||
| df2d53b9da | |||
| 9b1d51273d | |||
| 0fc92b7742 | |||
| 1996ff0b3a | |||
| 735dedfb42 | |||
| 4ab7a04c92 | |||
| 8864e13030 | |||
| b3bfff9588 | |||
| c6d8b45537 | |||
| e7e1f33985 | |||
| 4f67329f6b | |||
| 4aff4667ef | |||
| 41fd5bef4d | |||
| 11e4b4ab3f | |||
| 509b7e35c9 | |||
| a7143c8c58 | |||
| f588695f3c | |||
| 26ba628cae | |||
| 7fbc2037d3 | |||
| 5c1a1d507a | |||
| ee2ddfca14 | |||
| c456c6f642 | |||
| 2c2055a11a | |||
| 502b4cff10 | |||
| c34fb88311 | |||
| 5949cdd843 | |||
| 22548f34c1 | |||
| c643aa0e1d | |||
| 9be3a714d1 | |||
| 478f9d2639 | |||
| 19c4f7469d | |||
| 9b50bcd0ee | |||
| 06f3fcefee | |||
| 62d18089c4 | |||
| 03a34bb637 | |||
| 9d144af68a | |||
| 00c346c7b1 | |||
| fcc67e542e | |||
|
|
f18dd60383 | ||
|
|
5019a88fd5 | ||
|
|
b573fafb8e | ||
| 1440ba821a | |||
| e0b564c56c | |||
| 158fbfd124 | |||
| 1a005f3b9e | |||
| f1cc13ae71 | |||
| 35ba4523e8 | |||
| c8731e0612 | |||
| 30f74720b4 | |||
| 9e9c4beb45 | |||
| 20798e0ce6 | |||
| 810479701c | |||
| b8392f199c | |||
| 9646a0110f | |||
| 11f887c93d | |||
| b539f4a6d7 | |||
| 216bc5034b | |||
| cefee8298a | |||
| 47633749fb | |||
| 4e325196c8 | |||
| 18c5386fdd | |||
| 242fb1ddee | |||
| 2546db9b64 | |||
| b28fbaf903 | |||
| 58ffb22bf6 | |||
| d7d825b5b0 | |||
| dc9f82f30e | |||
| 7077604a27 | |||
| ea38a6ddef | |||
| bba7a8e456 | |||
| 4a620c5d78 | |||
| c37e150bb9 | |||
| fe45524d52 | |||
| 5d21271316 | |||
| 9b78d4e52e | |||
| 349f514bcb | |||
| 85a910b794 | |||
| e4069c0de2 | |||
| 7b155f649d | |||
| ecc7b0ebc3 | |||
| c6a8a6fc70 | |||
| 4f594b0bfd | |||
| f1a02e9188 | |||
| f011a1e8fd | |||
| 090e9a1ea8 | |||
| fc8575dd0b | |||
| f162befa0d | |||
| 10bb9cbc37 | |||
| 52ca3791b3 | |||
| 2fe143b6c7 | |||
| bbf63ec51f | |||
| 222b9829b6 | |||
| ffaf17d6f9 | |||
| e9835df985 | |||
| 377e041eb2 | |||
| b3fe207469 | |||
| e527deabd5 | |||
| d644b0e3ca | |||
| 6800117ed4 | |||
| ae31f68586 | |||
| 4568101f06 | |||
| c67e5cf15e | |||
| 5bfa2a0243 | |||
| 68fa803016 | |||
| 457547a34e | |||
| adbfc42015 | |||
| 0c26f2245e | |||
| e4959cecd7 | |||
| 01029195fb | |||
| 68897bbabf | |||
| ed3462be87 | |||
| ac22684d69 | |||
| fa977c5134 | |||
| 21cc38ed73 | |||
| 662042a228 | |||
| 258e340752 | |||
| 96378e161f | |||
| 7e7197b9b8 | |||
| 2e3089e6b1 | |||
| b5a1c76fad | |||
| b7ebe7e3b9 | |||
| 3fb35e085c | |||
| f2b1cad505 | |||
| e2e4f47c60 | |||
| 87d4633b18 | |||
| 2fdbc144a6 | |||
| c43ea8be87 | |||
| e52efa0a45 | |||
| 3c6a8bedc2 | |||
| a0906ed5c7 | |||
| a9cfa60b36 | |||
| 09cef9de33 | |||
| c884333fc1 | |||
| 8274f9f186 | |||
| b90d3bc466 | |||
| e4094dcd73 | |||
| e99d217d34 | |||
| fc41bd8e6d | |||
| 5640978025 | |||
| cff3198dcd | |||
| d4d7601bae | |||
| 6018cd6838 | |||
| 1ce0bf708b | |||
| 060f6e0fd8 | |||
| 7e110dd656 | |||
| 4d5f163f17 | |||
| f4a1e3e932 | |||
| 195cc714ab | |||
| 43211d6f0c | |||
| d59c9d8cca | |||
| 8d731ff7c5 | |||
| 50504f4e94 | |||
| 37ee6af0e5 | |||
| 5362a47d1e | |||
| a1a3c0ac9f | |||
| f22e14b1ba | |||
| 5d44bae1c3 | |||
| 4d78debb92 | |||
| 93d69861bf | |||
| 936f5dbf4c | |||
| d4e7503306 | |||
| 81c24023e9 | |||
| d1a20fbad1 | |||
| 6e8f2328c6 | |||
| 83e780c17d | |||
| 251fdf7989 | |||
| 30d1664a9b | |||
| 2173cd1cf1 | |||
| 298d298dc5 | |||
| 9557e8595d | |||
| bc2c77ff34 | |||
| 99c93dd582 | |||
| 741187c129 | |||
| 8f9d5eb37b | |||
| f0e25b21d3 | |||
| 1541482e76 | |||
| ce2d39e3bf | |||
| d229f957e5 | |||
| 6d0a1940fc | |||
| b6b1c8a3ff | |||
| 4a52ab51df | |||
| 9ecabb8f69 | |||
| 09c51f13fc | |||
| a6ee226073 | |||
| 968eebaa2b | |||
| 7637608226 | |||
| db720f6d1b | |||
| 26ed532684 | |||
| 2e101d1017 | |||
| abda409817 | |||
| cb2fe73481 | |||
| c1bba811b9 | |||
| 1183be2987 | |||
| 11598c507b | |||
| 38b6299dbf | |||
| fa054d2a07 | |||
| 7541b37117 | |||
| cafba1e18c | |||
| 4755849a8c | |||
| f219635348 | |||
| ad6509f043 | |||
| 6cf0a0b0da | |||
| b2774892de | |||
| f7b0461218 | |||
| 42fc5524f3 | |||
| ea51e6a300 | |||
| 10cfe6e6ad | |||
| 1dd381cc1e | |||
| 1e02e00000 | |||
| c799c16663 | |||
| 27cb965f3a | |||
| e643d9ef86 | |||
| becce5dfab | |||
| 1da833f451 | |||
| 95a2161ab3 | |||
| 873458595d | |||
| a134dfd308 | |||
| 8fade135fe | |||
| 8408697b57 | |||
| 1bdb1e6739 | |||
| b497e2117d | |||
| 04d62635f8 | |||
| ef38b0c18f | |||
| 83af021d33 | |||
| 12d3fbcda1 | |||
| 2227ceabde | |||
| 3e3d738362 | |||
| bcb74bf29f | |||
| c4ad13b09c | |||
| 48430951ef | |||
| 443f598173 | |||
| 420605436c | |||
| a1fa0dab6a | |||
| 8b5a4aba6f | |||
| 09b1c86ceb | |||
| 3dbaf21281 | |||
| 474cf72333 | |||
| 433f0bc712 | |||
| e4d0b87069 | |||
| 8d87e2a7a0 | |||
| 4b56a92444 | |||
| 3289e799be | |||
| a7367bef2f | |||
| 87d3493c34 | |||
| 0250e3008b | |||
| cab7311cfb | |||
| 89603d1094 | |||
| 5cdec2b677 | |||
| 66746458ee | |||
|
|
892e9c01f1 | ||
| 203b0c9753 | |||
| d9d2d446f6 | |||
| bd37eb66a9 | |||
| 9ed6fc1b94 | |||
| 74fd0a8610 | |||
| 2244e96484 | |||
| f99422a8e0 | |||
| d27576ede2 | |||
| c16d86354b | |||
| d8a01ad3b1 | |||
| c61b06e8b2 | |||
| 88f12c7fce | |||
| 1b1e0a8174 | |||
| 33e6ad37b9 | |||
|
|
522eb5025c | ||
|
|
6aeb846ca4 | ||
|
|
f5d8a46829 | ||
| a7a146c055 | |||
| 94155d2ca6 | |||
| ab191e940b | |||
| 5f95f461a8 | |||
| 173b928412 | |||
| f0d19e535c | |||
| 63d8feb712 | |||
| ebccaaa12f | |||
| 147d66c756 | |||
| 04fff31b3a | |||
| 96529cccc6 | |||
| 848f167bb6 | |||
| ee869f3c34 | |||
|
|
21a111ae8f | ||
|
|
5f6f1a7912 | ||
| 5912f37ebb | |||
| 66bd341692 | |||
| 39b71a581a | |||
| 28257ceefe | |||
| e2eed22d73 | |||
| 790cac67ef | |||
| b6ddafdd25 | |||
|
|
bda93c9744 | ||
|
|
2634e9b70c | ||
| 2f3d47e349 | |||
| f7fcd79251 | |||
| 25f4f33cb0 | |||
| e06e2d553e | |||
| a5e3e269a1 | |||
| 9d0d722880 | |||
| 6ac90f3841 | |||
| e0bfe67c7e | |||
| eaed989525 | |||
| f08f754002 | |||
| 77ff2143c3 | |||
| a55031ed70 | |||
| b3c3156a08 | |||
| 76d4254f5e | |||
| 31928abbd1 | |||
| df349f1480 | |||
| 15ec2d909c | |||
| fbfbe5c328 | |||
| 067ff09c73 | |||
| 36e76b15b9 | |||
| 6e612e1f7a | |||
| 9b698cfdb3 | |||
|
|
45e0bf3c6c | ||
|
|
5111897d13 | ||
| 38631df3f9 | |||
| 1e41101f9b | |||
| 36bb362fd7 | |||
| 2f42a7464a | |||
| db2f0d8daf | |||
| ff668b1887 | |||
| a4f94099af | |||
| 96bcb30868 | |||
| 40de9f0a4c | |||
| d265ef5a32 | |||
| a21f061589 | |||
| 58c3419b35 | |||
| 5a443bfab9 | |||
| d92bcfe0aa | |||
| 055310b6e7 | |||
| 55782df345 | |||
| e0e5111f32 | |||
| 4acd0cbab1 | |||
| 925b4a2eb4 | |||
| 39cb9400f6 | |||
| c6ddba8702 | |||
|
|
0fe2bb42ae | ||
|
|
e0b937fce9 | ||
| 6f505ba281 | |||
| c740929622 | |||
| 8901053fd6 | |||
| 15689dfbc1 | |||
| ea660fff65 | |||
| 303e981a0c | |||
| bab9597739 | |||
| 1430b1eae7 | |||
| 45104ecc87 | |||
| 6bb55520cf | |||
| 95b2193393 | |||
| 74d2033857 | |||
| 8e8116e869 | |||
| 7df05a46f2 | |||
| 5754709a21 | |||
| 614bd328d1 | |||
| cc322f3352 | |||
| 328c75b2e4 | |||
| d6f53a69da | |||
| 1716a3a562 | |||
| b5933a9016 | |||
| 5048c638b8 | |||
| b4e9359165 | |||
| 24f4a4a498 | |||
| 42befadca5 | |||
| da2721ca56 | |||
| 19db2667c2 | |||
| 291f91bc61 | |||
| 0c1aa248d5 | |||
| f617b815a1 | |||
| a13006d630 | |||
|
|
fc0451ca32 | ||
| 5664faccfe | |||
| d769ec9755 | |||
| b9de011871 | |||
| d2e672e761 | |||
| 6cc409d744 | |||
|
|
9506d3e0f6 | ||
|
|
b90ed53437 | ||
|
|
fe8ca80452 | ||
|
|
1194f04eb6 | ||
|
|
c7866f2e5e | ||
|
|
e5452741e9 | ||
| ac8cbdc991 | |||
| d87dd8985c | |||
| 342b64273c | |||
|
|
3685174117 | ||
|
|
7ee43a9b4d | ||
| 84e5c2dd7e | |||
| ad7ca888a9 | |||
| 838f2edf7e | |||
| 3c1fcc327c | |||
|
|
9a66c333c7 | ||
| 3580fb41f3 | |||
| dc822bba07 | |||
| 1db5d4b11f | |||
| 1ca25d8ec4 | |||
| a9c7977347 | |||
| 3c471b1124 | |||
| 2b94151780 | |||
| 9088a792d1 | |||
| ff09ed8c8a | |||
| fdb76c31a8 | |||
| 484efa5854 | |||
| 07b3457409 | |||
| 1150fdac86 | |||
| 930684ac01 | |||
| 760d452311 | |||
| 6f0800162b | |||
| 8f3432f9a0 | |||
| ae1c614ee8 | |||
| 7ceb63b02f | |||
| a0fa5d43f1 | |||
| 008b3c942a | |||
| 3cc9f40baf | |||
| ca030e42d4 | |||
| 7b6ca29a93 | |||
| 8538f7d43f | |||
| 9f8e07c18a | |||
| a2212ac8e6 | |||
| d6c7538c36 | |||
| 150ac2afcb | |||
| 609df9855a | |||
| da2f27bc72 | |||
| eeb821de24 | |||
| a754751832 | |||
| 5235f23365 | |||
|
|
7f684fa085 | ||
|
|
d674a6ea12 | ||
| b315b667e9 | |||
| 798c42beb9 | |||
| 2613884a89 | |||
| 9a9702227c | |||
| 74ad7e9eb9 | |||
| cdb984a439 | |||
| ab33f09538 | |||
| 152da3c0e4 | |||
|
|
bd165769de | ||
|
|
c266e27c51 | ||
| 1bfa0095ae | |||
| 33c4e4baa7 | |||
| eb5df00b45 | |||
| 61be47b3d4 | |||
| e5356787be | |||
| f842bf375b | |||
| 9ef88a2d17 | |||
| 9688322f69 | |||
| 19a61159e4 | |||
| beb727760b | |||
| aa2631b7de | |||
| cfe89816f4 | |||
| 80d8d3c687 | |||
| c75bd8a197 | |||
| 12eeeced0e | |||
|
|
de69dc9b47 | ||
| 2edef9fcf0 | |||
| dfcf635f05 | |||
| 9beb9ed9de | |||
| 89dd56959a | |||
| d2f7f6080a | |||
|
|
0556e5eb79 | ||
| 6fc5a3f6f3 | |||
| 706bf36aa8 | |||
| 634931a624 | |||
| afc079b670 | |||
| c1a1b30c99 | |||
| d17bca9994 | |||
| 0fbaa25cd6 | |||
| 9a1b04966d | |||
| 759f93078b | |||
| 1e97239d18 | |||
| 49a3bbd701 | |||
| 68dc2ff018 | |||
| 6f843f54a6 | |||
| 19791498d4 | |||
| 4242b22c1a | |||
| 6e3b1e8b54 | |||
| 43703f3366 | |||
| bb052b85ac | |||
| 4049becfb8 | |||
| 2a8dabd648 | |||
| a6bd56c29c | |||
| 662e11c154 | |||
| fab991400e | |||
| b1b389ce8f | |||
| c977249713 | |||
| 9a306be965 | |||
| d01f37f5b9 | |||
| 07069af7a0 | |||
|
|
4a598f52d4 | ||
| c67a66c119 | |||
|
|
c99e553515 | ||
|
|
380c476cf3 | ||
| b433efc81a | |||
| ab4b9c1bf3 | |||
| 169423d5f9 | |||
| ce981882c8 | |||
| dd13f8d175 | |||
| 47f13d4b1e | |||
| 433bb7e1a4 | |||
| 08f86517da | |||
| 794826f0c7 | |||
| 096fa6dc51 | |||
| accf65ef10 | |||
| eaa8b834bf | |||
| b32ced514b | |||
| 78cf7e6857 | |||
| 8128766e24 | |||
| 90a08f37f6 | |||
| ad03a1ed2b | |||
| 41b1bed81d | |||
|
|
bc882f375f | ||
| 5d23a903fc | |||
| 7fb30322b3 | |||
| a795fa5786 | |||
|
|
6fcb68d929 | ||
| 9cf7396fb8 | |||
| 891cebec90 | |||
| 2206e2aa21 | |||
| ba4e927ff5 | |||
| fa366d18e5 | |||
| 31ff2a4502 | |||
| 4d312a8892 | |||
| fc09c1db05 | |||
| 62983eea10 | |||
| a7f95e98aa | |||
| df4312e61d | |||
| 65af3e7bfb | |||
| fe5c28dbf0 | |||
| 5b78df27f5 | |||
| f9cf478694 | |||
| 7b67e71bd6 | |||
| 2c5c694445 | |||
| 4649ad3abd | |||
| ac00d68350 | |||
| 40c09c58d4 | |||
| a30638d693 | |||
| 0f83224f28 | |||
| 11a1f044f5 | |||
| 7df8fbd46a | |||
| d57af223cc | |||
| a1925121d7 | |||
|
|
4f4f1842a4 | ||
| 1bc27897d8 | |||
| e5d03a07a3 | |||
|
|
d6909fb449 | ||
| 73978ca602 | |||
| ac4cdb1189 | |||
|
|
b3e85e186e | ||
| f0a09b2d0a | |||
| 501790677e | |||
|
|
700c08616f | ||
| 28207004c7 | |||
| 8c33aaa8a7 | |||
| 9e5d07d7e5 | |||
| 45dc828332 | |||
|
|
26f5c2c9c5 | ||
|
|
8ac192f8ba | ||
|
|
496109cc1a | ||
| e08eccb46d | |||
| df9debe453 | |||
| 43433b3b02 | |||
| 1cec0b123c | |||
| 324862a61f | |||
| aa76f82a74 | |||
| 24fc98cf7b | |||
| e7a2753c06 | |||
|
|
a7ae9df845 | ||
|
|
f04459aba1 | ||
| 4000b0b8e9 | |||
|
|
2d23266e50 | ||
| 99d90acebc | |||
| 6b2a94453c | |||
| bd679710e2 | |||
| 86610c07a8 | |||
|
|
b336efa79c | ||
|
|
d010907d2b | ||
|
|
894b656a82 | ||
|
|
4b9ecb9360 | ||
|
|
228fef7a9b | ||
|
|
6a6a440428 | ||
|
|
ee9462769f | ||
|
|
cf2f071f6d | ||
|
|
18113da288 | ||
|
|
743f55c11d | ||
|
|
4009f05185 | ||
|
|
182572bfd1 | ||
|
|
5edd4ee722 | ||
|
|
497f1ad64e | ||
|
|
ff632ef4cf | ||
|
|
10d094a5b7 | ||
|
|
f395fa32c7 | ||
|
|
57153d3bc7 | ||
|
|
5b3a6b6bf4 | ||
| 6fbf040107 | |||
| 6b81e35db0 | |||
|
|
97578316b8 | ||
|
|
4c07528102 | ||
|
|
065ef047a7 | ||
|
|
b5c5b9ec99 | ||
|
|
76824a5c57 | ||
|
|
75b0625dc4 | ||
|
|
4585a4e49d | ||
|
|
eb5b27fdf8 | ||
|
|
e8ab5fc050 | ||
|
|
9df7674abc | ||
|
|
21517a41a3 | ||
|
|
4449fcce60 | ||
| 27c7b68595 | |||
| 306f92f4e5 | |||
| 51fe4e113b | |||
| 3bb0b9108c | |||
| b8aff8512d | |||
| 6ec24f7431 | |||
|
|
d4373bc44f | ||
|
|
d0c20d68eb | ||
|
|
ad808d6fa6 | ||
|
|
ac92da76aa | ||
| 20c913f61f | |||
| f25e74869b | |||
|
|
09028a2041 | ||
| 0a9d2fbfc1 | |||
| 901cf7fbc4 | |||
| bd9d0a43c2 | |||
| 9eb481be57 | |||
| f568676a40 |
16
.drone.yml
@@ -8,7 +8,7 @@ steps:
|
||||
|
||||
|
||||
- name: build-package
|
||||
image: node:16.20.0
|
||||
image: node:18.19.0
|
||||
volumes:
|
||||
- name: cache
|
||||
path: /drone/src/node_modules
|
||||
@@ -23,11 +23,17 @@ steps:
|
||||
- cp docker.sh /app/build/$DRONE_REPO_NAME/
|
||||
- cp nginx.conf /app/build/$DRONE_REPO_NAME/
|
||||
- npm -v
|
||||
- node -v
|
||||
- mkdir -p ./node_modules
|
||||
- export NODE_MODULES_PATH=`pwd`/node_modules
|
||||
# - npm config set registry https://registry.npmmirror.com
|
||||
# - set NODE_OPTIONS=--openssl-legacy-provider
|
||||
# - npm install
|
||||
- npm config set registry https://registry.npmmirror.com
|
||||
- set NODE_OPTIONS=--openssl-legacy-provider
|
||||
- npm install --legacy-peer-deps
|
||||
- npm install patch-package
|
||||
- npx patch-package
|
||||
# - npm info unplugin-icons
|
||||
- npm list package-manager-detector
|
||||
# - npm install unplugin-icons@latest @antfu/install-pkg@latest package-manager-detector@latest
|
||||
- npm run build
|
||||
- ls /app/build/$DRONE_REPO_NAME/
|
||||
- echo $NODE_MODULES_PATH
|
||||
@@ -35,7 +41,7 @@ steps:
|
||||
|
||||
|
||||
- name: build-docker-prod # 制作docker镜像
|
||||
image: docker # 使用官方docker镜像
|
||||
image: 10.7.127.190:38080/docker/docker # 使用官方docker镜像
|
||||
volumes: # 将容器内目录挂载到宿主机
|
||||
- name: docker
|
||||
path: /var/run/docker.sock # 挂载宿主机的docker
|
||||
|
||||
@@ -1,9 +1,11 @@
|
||||
FROM nginx
|
||||
FROM 10.7.127.190:38080/nginx:latest
|
||||
|
||||
RUN rm -rf /etc/nginx/conf.d/default.conf
|
||||
RUN rm -rf /etc/nginx/nginx.conf
|
||||
COPY default.conf /etc/nginx/conf.d
|
||||
COPY nginx.conf /etc/nginx/
|
||||
#COPY mosr.feashow.cn_chain.crt /etc/nginx/
|
||||
#COPY private.key /etc/nginx/
|
||||
|
||||
#RUN useradd -b /home/clay -m -s /bin/bash clay
|
||||
#RUN chmod a+xr -R /home/clay && chown clay:clay -R /home/clay
|
||||
|
||||
@@ -1,2 +1,2 @@
|
||||
# <EFBFBD><EFBFBD><EFBFBD>й<EFBFBD><EFBFBD><EFBFBD>ƽ̨
|
||||
# 科技创新项目管理平台
|
||||
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
<meta charset="UTF-8">
|
||||
<link rel="icon" href="/favicon.ico">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title>科研管理平台</title>
|
||||
<title>科技创新项目管理平台</title>
|
||||
</head>
|
||||
<body>
|
||||
<div id="app"></div>
|
||||
|
||||
72
mosr.feashow.cn_chain.crt
Normal file
@@ -0,0 +1,72 @@
|
||||
-----BEGIN CERTIFICATE-----
|
||||
MIIG3DCCBMSgAwIBAgIQDzIS+rldpl8FKv9qt1IuQDANBgkqhkiG9w0BAQsFADBb
|
||||
MQswCQYDVQQGEwJDTjElMCMGA1UEChMcVHJ1c3RBc2lhIFRlY2hub2xvZ2llcywg
|
||||
SW5jLjElMCMGA1UEAxMcVHJ1c3RBc2lhIERWIFRMUyBSU0EgQ0EgMjAyNTAeFw0y
|
||||
NTAzMTkwMDAwMDBaFw0yNTA2MTcyMzU5NTlaMBoxGDAWBgNVBAMTD21vc3IuZmVh
|
||||
c2hvdy5jbjCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAK92bSayd6Wo
|
||||
wFJz+ldX8QEgQiUjEPyQB0rV+Op9/eZSmpC6y+DuS/CddOPaXs+t1fV9L2kQ1yWD
|
||||
Byc7cZK2PnzGb8+Uh9BR3UtVaCxISGqxjvt2V1lIwXbBDOUjtkVVlchhGR+BrNzP
|
||||
YGyMLhgdBDxhKK4ogBNOx23AzCpTGFsU7sL996qwYo2rhIE8UuYcw3deS4RtfMUx
|
||||
zt58wn1s+9kki6Qti7dLw3Bg0eCXop+7/FC09fg5Nh3EygMlZvLyvNOFig+o/Fk3
|
||||
6ibp2N56yFLEfe+WNj4xPCad/3Cevh5BIgTsSAPBh6J5Jk4IXoL8PuCSc96d79Bg
|
||||
SVGNGhRuCgcCAwEAAaOCAtswggLXMB8GA1UdIwQYMBaAFLQSKKW0wB2fKXFpPNkR
|
||||
lkp1aVDAMB0GA1UdDgQWBBTL9/e/QUue1NxlPXspxQ/RzXhzxTAaBgNVHREEEzAR
|
||||
gg9tb3NyLmZlYXNob3cuY24wPgYDVR0gBDcwNTAzBgZngQwBAgEwKTAnBggrBgEF
|
||||
BQcCARYbaHR0cDovL3d3dy5kaWdpY2VydC5jb20vQ1BTMA4GA1UdDwEB/wQEAwIF
|
||||
oDAdBgNVHSUEFjAUBggrBgEFBQcDAQYIKwYBBQUHAwIweQYIKwYBBQUHAQEEbTBr
|
||||
MCQGCCsGAQUFBzABhhhodHRwOi8vb2NzcC5kaWdpY2VydC5jb20wQwYIKwYBBQUH
|
||||
MAKGN2h0dHA6Ly9jYWNlcnRzLmRpZ2ljZXJ0LmNvbS9UcnVzdEFzaWFEVlRMU1JT
|
||||
QUNBMjAyNS5jcnQwDAYDVR0TAQH/BAIwADCCAX8GCisGAQQB1nkCBAIEggFvBIIB
|
||||
awFpAHYATnWjJ1yaEMM4W2zU3z9S6x3w4I4bjWnAsfpksWKaOd8AAAGVrKDPywAA
|
||||
BAMARzBFAiAJkC1pvmPIhgdAkRoyPCItM4oRM5Bb8OI3zVzNvdNTkQIhAN1Fq4mU
|
||||
GJYrJkOmwvJ2Mb5upB50Ic8C7KatpMdKEFM7AHYAfVkeEuF4KnscYWd8Xv340Idc
|
||||
FKBOlZ65Ay/ZDowuebgAAAGVrKDQBwAABAMARzBFAiAT9jfX08uN94aIeK84IySz
|
||||
jUPDa1MSWjJKsA3XusY3GAIhAJ9PvGtFx9+UM9YNNT7BZUq6hhVvhYWhlf+d0qpy
|
||||
uEl9AHcAzxFW7tUufK/zh1vZaS6b6RpxZ0qwF+ysAdJbd87MOwgAAAGVrKDP+AAA
|
||||
BAMASDBGAiEA0c9dt1JwyAMzQtv7UsPaKEJ5sp6HDaSWe5BGIYWsYrcCIQDjS6L1
|
||||
9TF6SpcEWHH6bl952VQb6Xvt1JmmKUNX6iK2xTANBgkqhkiG9w0BAQsFAAOCAgEA
|
||||
0E2VWQjWgEBz968xq2cpYGv2Enfs2TWpynuoPTwY83V7h2ejNbpjgyW1gT/kQkxa
|
||||
G5k4jpkVmNMaj3CAvK4IA5jOPh6dhzBG35Qc0PwRm0eovcUdUNUd0g4EOv82p2s1
|
||||
ab1SWNYoxGdS+y+LHhfFZ7CoVcSvBz+LHBlPTVTkLA0SWLA0fhS3pl5oGIilMtSM
|
||||
znCUUuMBtMQBv7sFX2gDEYwxGaMn3lpoqBGkpx4UBc51z/U3+X9zLqu6n/GpLC72
|
||||
+qz6QtQVm0Np8gcjul0ebQqAPwDG4U+9jYEmdwVHZ0iUKgyZPECPU+TTtHx0TFS3
|
||||
B5JXy8vbGJBqpwq6hMnu/SFm+GY3iPk7N0Aj5+9QNcl2FTF8k/nCoK3MuY71ZmxR
|
||||
E1NY6Hl5KpKzBqc7JG4iqQxJ0dD9Racn4wegGDlX0Vr2U+ohHYeETNJXOX+JT4tc
|
||||
1PBdfiywbX+FCdE2ZPehWa6dt4fnPBC/9lSywrzOWLNt9z1a/Mh73N5F6ndaXq1p
|
||||
v/N3Q0qnXpW1RZa6Baqlfvk2vqhraRbT9YH5Y+f51DhtVB6fbELO/pJr1H5kh0XI
|
||||
CczHkGTGD7xZloNfTMLP2AVguIXJ0EASAAMw/MBRWvSd4He2lLHvujEqTXsTISgv
|
||||
v+/5bZP8qBk3/oEgdLjlmqWY1sesBH84tiMZcxCkPNM=
|
||||
-----END CERTIFICATE-----
|
||||
-----BEGIN CERTIFICATE-----
|
||||
MIIFnjCCBIagAwIBAgIQCSYyO0lk42hGFRLe8aXVLDANBgkqhkiG9w0BAQsFADBh
|
||||
MQswCQYDVQQGEwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3
|
||||
d3cuZGlnaWNlcnQuY29tMSAwHgYDVQQDExdEaWdpQ2VydCBHbG9iYWwgUm9vdCBH
|
||||
MjAeFw0yNTAxMDgwMDAwMDBaFw0zNTAxMDcyMzU5NTlaMFsxCzAJBgNVBAYTAkNO
|
||||
MSUwIwYDVQQKExxUcnVzdEFzaWEgVGVjaG5vbG9naWVzLCBJbmMuMSUwIwYDVQQD
|
||||
ExxUcnVzdEFzaWEgRFYgVExTIFJTQSBDQSAyMDI1MIICIjANBgkqhkiG9w0BAQEF
|
||||
AAOCAg8AMIICCgKCAgEA0fuEmuBIsN6ZZVq+gRobMorOGIilTCIfQrxNpR8FUZ9R
|
||||
/GfbiekbiIKphQXEZ7N1uBnn6tXUuZ32zl6jPkZpHzN/Bmgk1BWSIzVc0npMzrWq
|
||||
/hrbk5+KddXJdsNpeG1+Q8lc8uVMBrztnxaPb7Rh7yQCsMrcO4hgVaqLJWkVvEfW
|
||||
ULtoCHQnNaj4IroG6VxQf1oArQ8bPbwpI02lieSahRa78FQuXdoGVeQcrkhtVjZs
|
||||
ON98vq5fPWZX2LFv7e5J6P9IHbzvOl8yyQjv+2/IOwhNSkaXX3bI+//bqF9XW/p7
|
||||
+gsUmHiK5YsvLjmXcvDmoDEGrXMzgX31Zl2nJ+umpRbLjwP8rxYIUsKoEwEdFoto
|
||||
Aid59UEBJyw/GibwXQ5xTyKD/N6C8SFkr1+myOo4oe1UB+YgvRu6qSxIABo5kYdX
|
||||
FodLP4IgoVJdeUFs1Usa6bxYEO6EgMf5lCWt9hGZszvXYZwvyZGq3ogNXM7eKyi2
|
||||
20WzJXYMmi9TYFq2Fa95aZe4wki6YhDhhOO1g0sjITGVaB73G+JOCI9yJhv6+REN
|
||||
D40ZpboUHE8JNgMVWbG1isAMVCXqiADgXtuC+tmJWPEH9cR6OuJLEpwOzPfgAbnn
|
||||
2MRu7Tsdr8jPjTPbD0FxblX1ydW3RG30vwLF5lkTTRkHG9epMgpPMdYP7nY/08MC
|
||||
AwEAAaOCAVYwggFSMBIGA1UdEwEB/wQIMAYBAf8CAQAwHQYDVR0OBBYEFLQSKKW0
|
||||
wB2fKXFpPNkRlkp1aVDAMB8GA1UdIwQYMBaAFE4iVCAYlebjbuYP+vq5Eu0GF485
|
||||
MA4GA1UdDwEB/wQEAwIBhjAdBgNVHSUEFjAUBggrBgEFBQcDAQYIKwYBBQUHAwIw
|
||||
dgYIKwYBBQUHAQEEajBoMCQGCCsGAQUFBzABhhhodHRwOi8vb2NzcC5kaWdpY2Vy
|
||||
dC5jb20wQAYIKwYBBQUHMAKGNGh0dHA6Ly9jYWNlcnRzLmRpZ2ljZXJ0LmNvbS9E
|
||||
aWdpQ2VydEdsb2JhbFJvb3RHMi5jcnQwQgYDVR0fBDswOTA3oDWgM4YxaHR0cDov
|
||||
L2NybDMuZGlnaWNlcnQuY29tL0RpZ2lDZXJ0R2xvYmFsUm9vdEcyLmNybDARBgNV
|
||||
HSAECjAIMAYGBFUdIAAwDQYJKoZIhvcNAQELBQADggEBAJ4a3svh316GY2+Z7EYx
|
||||
mBIsOwjJSnyoEfzx2T699ctLLrvuzS79Mg3pPjxSLlUgyM8UzrFc5tgVU3dZ1sFQ
|
||||
I4RM+ysJdvIAX/7Yx1QbooVdKhkdi9X7QN7yVkjqwM3fY3WfQkRTzhIkM7mYIQbR
|
||||
r+y2Vkju61BLqh7OCRpPMiudjEpP1kEtRyGs2g0aQpEIqKBzxgitCXSayO1hoO6/
|
||||
71ts801OzYlqYW9OQQQ2GCJyFbD6XHDjdpn+bWUxTKWaMY0qedSCbHE3Kl2QEF0C
|
||||
ynZ7SbC03yR+gKZQDeTXrNP1kk5Qhe7jSXgw+nhbspe0q/M1ZcNCz+sPxeOwdCcC
|
||||
gJE=
|
||||
-----END CERTIFICATE-----
|
||||
@@ -25,6 +25,7 @@ http {
|
||||
|
||||
keepalive_timeout 65;
|
||||
|
||||
|
||||
server {
|
||||
listen 80;
|
||||
listen [::]:80;
|
||||
@@ -39,6 +40,7 @@ http {
|
||||
proxy_http_version 1.1;
|
||||
proxy_set_header Upgrade $http_upgrade;
|
||||
proxy_set_header Connection 'upgrade';
|
||||
client_max_body_size 30m;
|
||||
}
|
||||
|
||||
location / {
|
||||
|
||||
@@ -7,11 +7,17 @@
|
||||
"build": "vite build",
|
||||
"preview": "vite preview"
|
||||
},
|
||||
"overrides": {
|
||||
"package-manager-detector": "1.0.0",
|
||||
|
||||
"@iconify/utils": "2.2.1"
|
||||
},
|
||||
"dependencies": {
|
||||
"@antv/g6": "^3.5.7",
|
||||
"@tinymce/tinymce-vue": "^4.0.7",
|
||||
"axios": "^1.4.0",
|
||||
"d3": "^7.8.5",
|
||||
"docx-preview": "^0.3.2",
|
||||
"echarts": "^5.4.2",
|
||||
"element-plus": "^2.6.0",
|
||||
"file-saver": "^2.0.5",
|
||||
@@ -31,6 +37,8 @@
|
||||
"vue-codemirror": "^6.1.1",
|
||||
"vue-json-viewer": "^3.0.4",
|
||||
"vue-router": "^4.1.6",
|
||||
"vue3-pdf-app": "^1.0.3",
|
||||
"vue3-print-nb": "^0.1.4",
|
||||
"vuedraggable": "^4.1.0",
|
||||
"xlsx": "^0.18.5",
|
||||
"xlsx-style-vite": "^0.0.2"
|
||||
|
||||
28
private.key
Normal file
@@ -0,0 +1,28 @@
|
||||
-----BEGIN PRIVATE KEY-----
|
||||
MIIEvQIBADANBgkqhkiG9w0BAQEFAASCBKcwggSjAgEAAoIBAQCvdm0msnelqMBS
|
||||
c/pXV/EBIEIlIxD8kAdK1fjqff3mUpqQusvg7kvwnXTj2l7PrdX1fS9pENclgwcn
|
||||
O3GStj58xm/PlIfQUd1LVWgsSEhqsY77dldZSMF2wQzlI7ZFVZXIYRkfgazcz2Bs
|
||||
jC4YHQQ8YSiuKIATTsdtwMwqUxhbFO7C/feqsGKNq4SBPFLmHMN3XkuEbXzFMc7e
|
||||
fMJ9bPvZJIukLYu3S8NwYNHgl6Kfu/xQtPX4OTYdxMoDJWby8rzThYoPqPxZN+om
|
||||
6djeeshSxH3vljY+MTwmnf9wnr4eQSIE7EgDwYeieSZOCF6C/D7gknPene/QYElR
|
||||
jRoUbgoHAgMBAAECggEABmJQMV6/9LKRoM5gduoXtjtGvNQsS4wv/7yOTHXeFZG+
|
||||
1vI89cel0rDf7mRlG7hO9xohbfizY0WDrp0+kiB4YJDVw587W8yGuTV3z1in7d3c
|
||||
/nA9WF3J0DjQ78tfV+F3zC0gPWG5+OTAtOJa0PzJSSsd0Exf8JPmtKsVopqYYcPv
|
||||
RL2uP+NfcsxIEPz7rBBqiTGbOgsoKIpVZWiV6dmGOHLnI3ktWE8GXyIFv0VO6kp2
|
||||
fk/Z2uU9rfS9Qc9NijVdZ5AejdSh70iWNdiVMTSXZ69XLQCiY1h/376mraAPZTC1
|
||||
T0fYAtaOdyRrYLIW3yuznZa6hz351+t4TjJHQGjAUQKBgQDe8FS3yM85Ve3qlNaV
|
||||
pzjpjkv8cn8u43Hyk88owNACxkvzUXx15YE+AGjjycVO5rbyC1mtdE2MKX8cd5T/
|
||||
cA75RoSDxBTR7xi9eqBzJpQ7hm2rTaZSkHhu4P9KsthgQFFYQB6EkZgYczLOs/OV
|
||||
UmPMuKwL7HcwuRf00jjAOoJPdwKBgQDJe7R4PS0VBAWnh3lC9R/NEbEoFQ6LUwPh
|
||||
Qgmgj6LRB/1NgaC7ekDCSyfFlTtpnRDD+WqCrZDiB1ZZehyUObvr0Y0Cb4Y77Fjh
|
||||
lPVG0kfcKUldMpJIfeex0LPBwYHC62Y0ztNQmtgTldDjX04b4gAEgpUReHVTJtDr
|
||||
6S1wRPVd8QKBgHIL0+roqUmVcc5NMbEBCJZCGxEbqYBdDg+gGZupdz/UHUpt5xOQ
|
||||
wprrLr1InM0OLYyIzelz06/eEo6HhgteUeqnbmbRyizS+X8E2kvN8oq47CVz5Z/b
|
||||
FCD0rOSTtSkX/gT9WB9NM9deJyGi4PsEWNWDq0+2OgsMxPqTCEEeLUdlAoGAHNmB
|
||||
tdXMpr20sZBMZLIEo7Bs1XhuZLS2UYLLLhpjDds/AeIVycJvk2J/h2Me5rh+thD4
|
||||
l02S+Upjqtw5S2AY8GNI9ZhSeDIXZ/WUSVfCwluHDbk4CPk+O8/ObWfv1KEwOU+E
|
||||
In6JggRprKTw4j0yE3M/NQkyg32DXMQ+pVy6ZYECgYEAmW/+vm3X2NMj8yjr0Io2
|
||||
P3F/9EHPkrGHNC3Qj6Q2mFus6oDe6NwOQg5Su0fFC77spHFi1g/MlGUxbzoxjVxH
|
||||
1wQmwCHBJuJ97H9MOJ9K2v88/pkvfFGthkTLpbcJLqX57WVEVnVKBMNhpLrlp+0r
|
||||
T3tV8tN010INwiQkaoqCsuw=
|
||||
-----END PRIVATE KEY-----
|
||||
BIN
public/home1.png
Normal file
|
After Width: | Height: | Size: 750 KiB |
BIN
public/home2.png
Normal file
|
After Width: | Height: | Size: 736 KiB |
BIN
public/home3.png
Normal file
|
After Width: | Height: | Size: 743 KiB |
BIN
public/home4.png
Normal file
|
After Width: | Height: | Size: 733 KiB |
BIN
public/loading.gif
Normal file
|
After Width: | Height: | Size: 19 KiB |
BIN
public/people.png
Normal file
|
After Width: | Height: | Size: 11 KiB |
211
public/upfiles.html
Normal file
@@ -0,0 +1,211 @@
|
||||
<!doctype html>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8" />
|
||||
<title>axupimgs</title>
|
||||
<meta name="viewport" content="user-scalable=no, width=device-width, initial-scale=1.0, maximum-scale=1.0"/>
|
||||
<meta name="apple-mobile-web-app-capable" content="yes" />
|
||||
<meta name="apple-mobile-web-app-status-bar-style" content="black" />
|
||||
<meta name="format-detection" content="telephone=no">
|
||||
<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1" />
|
||||
<style>
|
||||
html,body{height:100%;margin:0;padding:0;background:#fff;}
|
||||
ul{margin:0;padding:0;list-style:none;}
|
||||
#wrap{padding:10px;}
|
||||
#topbar{padding:10px 0;border-bottom:1px solid #ccc;text-align:right;}
|
||||
#topbar button {margin:0;margin-left:5px;outline:none;padding: 4px 16px;box-sizing: border-box;
|
||||
display:inline-block;border:none;border-radius:3px;text-align:center;cursor:pointer;
|
||||
font-size:14px;line-height:1.5;background-color:#f0f0f0;color:#223;
|
||||
}
|
||||
#topbar button.primary{background-color:#3d97d4;color:#fff;}
|
||||
#topbar button:hover{background-color:#207ab7;color:#fff;}
|
||||
#topbar button.removeall{float:left}
|
||||
#file_list {display:grid;grid-gap:10px;grid-template-columns:repeat(auto-fill,minmax(160px,1fr));padding-top:10px;}
|
||||
#file_list:empty:after{content:'可以直接拖拽文件到这里';color:#777;font-size:0.8em;}
|
||||
#file_list li{position:relative;display:block;vertical-align:top;padding:5px 5px;border-radius:5px;}
|
||||
#file_list li.up-over {}
|
||||
#file_list li.up-now {}
|
||||
#file_list li.up-now:after{content:'';position:absolute;top:0;left:0;display:block;width:100%;height:100%;background:rgba(255,255,255,0.8) url(loading.gif) center center no-repeat;border-radius:5px;z-index:999;}
|
||||
#file_list li:hover{background-color:#ddd;}
|
||||
#file_list li .picbox {display:flex;flex:0 0 auto;justify-content:center;overflow:hidden;position:relative;width:100%;padding-top:100%;align-items:center;}
|
||||
#file_list li .picbox img {display:block;max-width:100%;max-height:100%;position:absolute;
|
||||
top:50%;left:50%;transform:translateX(-50%) translateY(-50%);}
|
||||
#file_list li.up-over .picbox:after{content:url('data:image/svg+xml;%20charset=utf8,%3Csvg%20viewBox%3D%220%200%201024%201024%22%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20width%3D%2224%22%20height%3D%2224%22%3E%3Cpath%20d%3D%22M512%200C229.376%200%200%20229.376%200%20512s229.376%20512%20512%20512%20512-229.376%20512-512S794.624%200%20512%200z%22%20fill%3D%22%234AC711%22%3E%3C%2Fpath%3E%3Cpath%20d%3D%22M855.552%20394.752l-358.4%20358.4a50.9952%2050.9952%200%200%201-72.192%200l-204.8-204.8c-18.944-19.968-18.944-51.2%200-71.168a50.5344%2050.5344%200%200%201%2072.192-1.024L460.8%20644.608l322.048-322.048c19.968-18.944%2051.2-18.944%2071.168%200%2020.48%2019.456%2020.992%2051.712%201.536%2072.192z%22%20fill%3D%22%23FFFFFF%22%3E%3C%2Fpath%3E%3C%2Fsvg%3E');position:absolute;bottom:2px;right:2px;z-index:9;}
|
||||
#file_list li .tools {display:none;position:absolute;bottom:5px;right:5px;z-index:99;}
|
||||
#file_list li:hover .tools {display:block;}
|
||||
#file_list li .tools .remove{cursor:pointer;}
|
||||
#file_list li .tools .remove:after{content:url('data:image/svg+xml;%20charset=utf8,%3Csvg%20width=%2224%22%20height=%2224%22%20viewBox=%220%200%2024%2024%22%20xmlns=%22http://www.w3.org/2000/svg%22%3E%3Cpath%20d=%22M17%206h3a1%201%200%200%201%200%202h-1v11a3%203%200%200%201-3%203H8a3%203%200%200%201-3-3V8H4a1%201%200%201%201%200-2h3V5a3%203%200%200%201%203-3h4a3%203%200%200%201%203%203v1zm-2%200V5a1%201%200%200%200-1-1h-4a1%201%200%200%200-1%201v1h6zm2%202H7v11a1%201%200%200%200%201%201h8a1%201%200%200%200%201-1V8zm-8%203a1%201%200%200%201%202%200v6a1%201%200%200%201-2%200v-6zm4%200a1%201%200%200%201%202%200v6a1%201%200%200%201-2%200v-6z%22%3E%3C/path%3E%3C/svg%3E');}
|
||||
#file_list li .namebox {font-size:14px;line-height:20px;max-height:40px;overflow:hidden;padding:5px 10px;text-align:center;display:flex;justify-content:center;align-items:flex-start;}
|
||||
#file_list li .namebox span{word-break:break-all;vertical-align:top;}
|
||||
</style>
|
||||
|
||||
</head>
|
||||
<body>
|
||||
<div id="wrap">
|
||||
<div id="topbar"><button class="addfile primary">+ 添加文件</button><button class="removeall">清空列表</button></div>
|
||||
<ul id="file_list"></ul>
|
||||
</div>
|
||||
|
||||
<script>
|
||||
var editor=parent.tinymce.activeEditor;
|
||||
var axupimgs=parent.axupimgs;
|
||||
axupimgs.res = []; //存放本地文件的数组
|
||||
var blobInfo = {file:null}
|
||||
blobInfo.blob = function(){return this.file;}
|
||||
var upload_handler = axupimgs.images_upload_handler;
|
||||
var upload_base_path = axupimgs.images_upload_base_path;
|
||||
//为列表添加排序
|
||||
function reSort(){
|
||||
document.querySelectorAll('#file_list li').forEach((el,i)=>{
|
||||
el.setAttribute('data-num',i);
|
||||
});
|
||||
}
|
||||
|
||||
function addList(files){
|
||||
var files_sum = files.length;
|
||||
var vDom = document.createDocumentFragment();
|
||||
for(let i=0;i<files_sum;i++){
|
||||
let file = files[i];
|
||||
let blobUrl = window.URL.createObjectURL(file)
|
||||
axupimgs.res.push({file:file,blobUrl:blobUrl,url:''});
|
||||
let li = document.createElement('li');
|
||||
li.setAttribute('class','up-no');
|
||||
li.setAttribute('data-time',file.lastModified);
|
||||
li.innerHTML='<div class="picbox"><img src="'+blobUrl+'"></div><div class="namebox"><span>'+file.name+'</span></div><div class="tools"><a class="remove"></a></div>';
|
||||
vDom.appendChild(li);
|
||||
|
||||
}
|
||||
|
||||
document.querySelector('#file_list').appendChild(vDom);
|
||||
if(axupimgs.res.length>0){
|
||||
document.querySelectorAll('#file_list li.up-no').forEach((el,i)=>{
|
||||
el.classList ? el.classList.add('up-now') : el.className+=' up-now';
|
||||
});
|
||||
upAllFiles(0);
|
||||
}
|
||||
|
||||
//reSort();
|
||||
}
|
||||
|
||||
|
||||
//清空列表
|
||||
document.querySelector('#topbar .removeall').addEventListener('click',()=>{
|
||||
axupimgs.res=[]
|
||||
document.querySelectorAll('#file_list li').forEach((el,i)=>{
|
||||
el.parentNode.removeChild(el)
|
||||
});
|
||||
});
|
||||
//拖拽添加
|
||||
document.addEventListener('dragover', (e)=>{
|
||||
e.stopPropagation();
|
||||
e.preventDefault();
|
||||
e.dataTransfer.dropEffect = 'copy';
|
||||
});
|
||||
document.addEventListener('drop', (e)=>{
|
||||
e.stopPropagation();
|
||||
e.preventDefault();
|
||||
if(!e.dataTransfer.files){return false;}
|
||||
var dropfiles = e.dataTransfer.files;
|
||||
if(!(dropfiles.length>0)){return false;}
|
||||
var exts=axupimgs.axupimgs_filetype.replace(/(\s)+/g,'').toLowerCase().split(',');
|
||||
var files=[];
|
||||
for( let file of dropfiles ){
|
||||
ext = file.name.split('.');
|
||||
ext = '.'+ext[ext.length-1];
|
||||
for(let s of exts){
|
||||
if(s==ext){
|
||||
files.push(file);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
if(files.length>0){ addList(files) }
|
||||
});
|
||||
|
||||
//添加文件
|
||||
document.querySelector('#topbar .addfile').addEventListener('click',()=>{
|
||||
var input = document.createElement('input');
|
||||
input.setAttribute('type', 'file');
|
||||
input.setAttribute('multiple', 'multiple');
|
||||
input.setAttribute('accept', axupimgs.axupimgs_filetype);
|
||||
input.click();
|
||||
input.onchange = function() {
|
||||
var files = this.files;
|
||||
addList(files);
|
||||
}
|
||||
});
|
||||
|
||||
var file_i = 0;
|
||||
|
||||
function upAllFiles(n){
|
||||
var len = axupimgs.res.length;
|
||||
file_i = n;
|
||||
if(len == n){
|
||||
file_i=0;
|
||||
// document.querySelector('#topbar .upall').innerText='全部上传';
|
||||
return true;
|
||||
}
|
||||
if( axupimgs.res[n].url!='' ){
|
||||
n++;
|
||||
upAllFiles(n)
|
||||
}else{
|
||||
blobInfo.file=axupimgs.res[n].file;
|
||||
upload_handler(blobInfo,function(url,name){
|
||||
if(upload_base_path){
|
||||
if(upload_base_path.slice(-1)=='/' && url.substr(0,1)=='/' ){
|
||||
url = upload_base_path + url.slice(1);
|
||||
}else if(upload_base_path.slice(-1)!='/' && url.substr(0,1)!='/' ){
|
||||
url = upload_base_path + '/' + url;
|
||||
}else{
|
||||
url = upload_base_path + url;
|
||||
}
|
||||
}
|
||||
axupimgs.res[file_i].url = url;
|
||||
// filename = url.split('/').pop();
|
||||
filename = name
|
||||
var li = document.querySelectorAll('#file_list li')[file_i];
|
||||
li.setAttribute('class','up-over');
|
||||
li.querySelector('.namebox span').innerText = filename;
|
||||
n++
|
||||
upAllFiles(n);
|
||||
},function(err){
|
||||
// document.querySelector('#topbar .upall').innerText='全部上传';
|
||||
// document.querySelectorAll('#file_list li.up-now').forEach((el,i)=>{
|
||||
// el.setAttribute('class','up-no');
|
||||
// });
|
||||
// alert(err);
|
||||
});
|
||||
}
|
||||
|
||||
}
|
||||
//
|
||||
// document.querySelector('#topbar .upall').addEventListener('click',(e)=>{
|
||||
// if(e.target.innerText!='全部上传'){return false;}
|
||||
// if(axupimgs.res.length>0){
|
||||
// document.querySelectorAll('#file_list li.up-no').forEach((el,i)=>{
|
||||
// el.classList ? el.classList.add('up-now') : el.className+=' up-now';
|
||||
// });
|
||||
// e.target.innerText='上传中...';
|
||||
// upAllFiles(0);
|
||||
// }
|
||||
// });
|
||||
|
||||
var observ_flist = new MutationObserver( (muList,observe)=>{
|
||||
if(muList[0].addedNodes.length>0){
|
||||
muList[0].addedNodes.forEach((el)=>{
|
||||
el.querySelector('.remove').addEventListener('click',(e)=>{
|
||||
var li = e.target.parentNode.parentNode;
|
||||
var n = li.getAttribute('data-num');
|
||||
var el = document.querySelectorAll('#file_list li')[n];
|
||||
el.parentNode.removeChild(el);
|
||||
axupimgs.res.splice(n,1);
|
||||
});
|
||||
});
|
||||
}
|
||||
reSort();
|
||||
});
|
||||
observ_flist.observe(document.querySelector('#file_list'),{childList:true});
|
||||
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
36
src/api/article/index.js
Normal file
@@ -0,0 +1,36 @@
|
||||
import request from '@/utils/request.js'
|
||||
|
||||
|
||||
export const getArticle = (params) => {
|
||||
return request({
|
||||
url: '/workflow/mosr/article/list',
|
||||
method: "get",
|
||||
params
|
||||
});
|
||||
};
|
||||
export const getArticleDetail = (articleId) => {
|
||||
return request({
|
||||
url: `/workflow/mosr/article/${articleId}`,
|
||||
method: "get"
|
||||
});
|
||||
};
|
||||
export const addArticle= (data) => {
|
||||
return request({
|
||||
url: '/workflow/mosr/article/add',
|
||||
method: "post",
|
||||
data
|
||||
});
|
||||
};
|
||||
export const editArticle= (data) => {
|
||||
return request({
|
||||
url: '/workflow/mosr/article/update',
|
||||
method: "post",
|
||||
data
|
||||
});
|
||||
};
|
||||
export const deleteArticle = (articleIds) => {
|
||||
return request({
|
||||
url: `/workflow/mosr/article/${articleIds}`,
|
||||
method: "delete"
|
||||
});
|
||||
};
|
||||
@@ -14,3 +14,18 @@ export const editPassword=(data)=>{
|
||||
data
|
||||
})
|
||||
}
|
||||
|
||||
export const getAgentInfo=()=>{
|
||||
return request({
|
||||
url:'/admin/mosr/user/self/approval/agent',
|
||||
method:'get'
|
||||
})
|
||||
}
|
||||
|
||||
export const editAgentInfo=(data)=>{
|
||||
return request({
|
||||
url:'/admin/mosr/user/self/approval/agent',
|
||||
method:'post',
|
||||
data
|
||||
})
|
||||
}
|
||||
|
||||
@@ -9,6 +9,13 @@ export const addAllocation = (data) => {
|
||||
data
|
||||
});
|
||||
};
|
||||
export const addShare = (data) => {
|
||||
return request({
|
||||
url:'/workflow/mosr/cost/share',
|
||||
method: "post",
|
||||
data
|
||||
});
|
||||
};
|
||||
export const getAllocationDetail = (allocationId) => {
|
||||
return request({
|
||||
url: `/workflow/mosr/cost/allocation/info/${allocationId}`,
|
||||
@@ -61,6 +68,13 @@ export const editAllocation = (data) => {
|
||||
data
|
||||
});
|
||||
};
|
||||
export const applyCcSend = (data) => {
|
||||
return request({
|
||||
url: '/workflow/mosr/cc/send',
|
||||
method: "post",
|
||||
data
|
||||
});
|
||||
};
|
||||
export const deleteAllocation = (id) => {
|
||||
return request({
|
||||
url: `/workflow/mosr/cost/allocation/${id}`,
|
||||
@@ -79,3 +93,15 @@ export const shareExportExcel = (allocationId) => {
|
||||
}
|
||||
);
|
||||
};
|
||||
|
||||
export const shareDetailExport= (data) => {
|
||||
return axios.post(
|
||||
`${import.meta.env.VITE_BASE_URL}/workflow/mosr/cost/share/export`,
|
||||
data, {
|
||||
responseType: 'blob',
|
||||
headers: {
|
||||
Authorization: getToken()
|
||||
}
|
||||
}
|
||||
);
|
||||
};
|
||||
|
||||
@@ -1,8 +1,31 @@
|
||||
import request from '@/utils/request.js'
|
||||
|
||||
export const getHomeInfo = () => {
|
||||
export const getHomeTaskInfo = () => {
|
||||
return request({
|
||||
url: '/workflow/mosr/process/task',
|
||||
method: "get"
|
||||
});
|
||||
};
|
||||
//获取已办数据
|
||||
export const getDoneTaskInfo = () => {
|
||||
return request({
|
||||
url: '/workflow/mosr/process/task/about',
|
||||
method: "get"
|
||||
});
|
||||
};
|
||||
|
||||
//获取专项资金饼图数据
|
||||
export const getSpecialFundChart = () => {
|
||||
return request({
|
||||
url: '/workflow/home/page/statistic',
|
||||
method: "get"
|
||||
});
|
||||
};
|
||||
|
||||
//获取首页四个统计数量
|
||||
export const getHomeStatistics = () => {
|
||||
return request({
|
||||
url: '/workflow/mosr/process/task/statistics',
|
||||
method: "get"
|
||||
});
|
||||
};
|
||||
|
||||
@@ -1,4 +1,7 @@
|
||||
import request from '@/utils/request.js'
|
||||
import axios from "axios";
|
||||
import {getToken} from "@/utils/auth";
|
||||
|
||||
//需求征集
|
||||
export const getDemandInfo = (param) => {
|
||||
return request({
|
||||
@@ -7,6 +10,12 @@ export const getDemandInfo = (param) => {
|
||||
params: param
|
||||
});
|
||||
};
|
||||
export const filterRequirementName = (requirementName) => {
|
||||
return request({
|
||||
url: `/workflow/mosr/requirement/match/${requirementName}`,
|
||||
method: "get"
|
||||
});
|
||||
};
|
||||
export const getWorkflowInfo = () => {
|
||||
return request({
|
||||
url: '/workflow/mosr/requirement/process',
|
||||
@@ -88,3 +97,32 @@ export const getRequirementStatePerm = () => {
|
||||
method: "get"
|
||||
});
|
||||
};
|
||||
export const downloadTemplate = (type) => {
|
||||
return request({
|
||||
url: '/workflow/mosr/attachment/download/template',
|
||||
method: "get",
|
||||
responseType:'blob',
|
||||
params:{
|
||||
type:type
|
||||
}
|
||||
});
|
||||
};
|
||||
export const downloadTemplateZip = (typeList) => {
|
||||
return axios.get(
|
||||
`${import.meta.env.VITE_BASE_URL}/workflow/mosr/attachment/download/pack?typeList=${typeList}`,
|
||||
{
|
||||
responseType: 'blob',
|
||||
headers: {
|
||||
Authorization: getToken()
|
||||
},
|
||||
}
|
||||
);
|
||||
// return request({
|
||||
// url: '/workflow/mosr/attachment/download/pack',
|
||||
// method: "get",
|
||||
// responseType:'blob',
|
||||
// params:{
|
||||
// typeList:typeList
|
||||
// }
|
||||
// });
|
||||
};
|
||||
|
||||
@@ -18,6 +18,23 @@ export const requirementReported = (data) => {
|
||||
data: data
|
||||
});
|
||||
};
|
||||
//需求汇总-征集名称关键词匹配
|
||||
export const getRequirementName = (requirementName) => {
|
||||
return request({
|
||||
url: `/workflow/mosr/requirement/collect/project/match/${requirementName}`,
|
||||
method: "get"
|
||||
});
|
||||
};
|
||||
//需求汇总-项目名称关键词匹配
|
||||
export const getProjectName = (projectName) => {
|
||||
return request({
|
||||
url: `workflow/mosr/requirement/collect`,
|
||||
method: "get",
|
||||
params:{
|
||||
projectName:projectName
|
||||
}
|
||||
});
|
||||
};
|
||||
//获取需求上报 流程信息
|
||||
export const getProcessInfo = (specialFund) => {
|
||||
return request({
|
||||
@@ -89,3 +106,18 @@ export const approvePlan= (data) => {
|
||||
});
|
||||
};
|
||||
|
||||
|
||||
export const getProjectOption = () => {
|
||||
return request({
|
||||
url: '/workflow/mosr/requirement/master',
|
||||
method: "get"
|
||||
});
|
||||
};
|
||||
|
||||
|
||||
export const getRequirementOption = () => {
|
||||
return request({
|
||||
url: '/workflow/mosr/requirement/option',
|
||||
method: "get"
|
||||
});
|
||||
};
|
||||
|
||||
@@ -8,6 +8,13 @@ export const searchFileList = (params) => {
|
||||
params: params
|
||||
});
|
||||
};
|
||||
export const searchAllFileList = (params) => {
|
||||
return request({
|
||||
url: '/workflow/mosr/attachment/all',
|
||||
method: "get",
|
||||
params: params
|
||||
});
|
||||
};
|
||||
export const uploadFileList = (data) => {
|
||||
return request({
|
||||
url: '/workflow/mosr/attachment/upload',
|
||||
|
||||
@@ -8,6 +8,12 @@ export const getApplyProcess = (projectId) => {
|
||||
method: "get"
|
||||
});
|
||||
};
|
||||
export const filterProjectName = (projectName,targetState) => {
|
||||
return request({
|
||||
url: `/workflow/mosr/project/approval/match/${projectName}/${targetState}`,
|
||||
method: "get"
|
||||
});
|
||||
};
|
||||
export const projectApply = (data) => {
|
||||
return request({
|
||||
url: '/workflow/mosr/project/approval/initiation/apply',
|
||||
@@ -79,6 +85,35 @@ export const getTags = (projectId) => {
|
||||
method: "get"
|
||||
});
|
||||
};
|
||||
export const getTagList = (projectId) => {
|
||||
return request({
|
||||
url: `/workflow/mosr/file/tag/list`,
|
||||
method: "get",
|
||||
params:{
|
||||
projectId: projectId
|
||||
}
|
||||
});
|
||||
};
|
||||
export const addTag = (data) => {
|
||||
return request({
|
||||
url: '/workflow/mosr/file/tag/add',
|
||||
method: "post",
|
||||
data:data
|
||||
});
|
||||
};
|
||||
export const updateTag = (data) => {
|
||||
return request({
|
||||
url: '/workflow/mosr/file/tag/update',
|
||||
method: "post",
|
||||
data:data
|
||||
});
|
||||
};
|
||||
export const delTag = (tageId) => {
|
||||
return request({
|
||||
url: `/workflow/mosr/file/tag/${tageId}`,
|
||||
method: "delete"
|
||||
});
|
||||
};
|
||||
export const getPhaseProcess = () => {
|
||||
return request({
|
||||
url: '/workflow/phase/change/process',
|
||||
@@ -179,3 +214,27 @@ export const exportExcel = (data) => {
|
||||
}
|
||||
);
|
||||
};
|
||||
//台账模板下载
|
||||
export const ledgerTemplateDownload = () => {
|
||||
return axios.get(
|
||||
`${import.meta.env.VITE_BASE_URL}/workflow/mosr/project/implementation/download/template`,
|
||||
{
|
||||
responseType: 'blob',
|
||||
headers: {
|
||||
Authorization: getToken()
|
||||
}
|
||||
}
|
||||
);
|
||||
};
|
||||
//费用明细模板下载
|
||||
export const costTemplateDownload = () => {
|
||||
return axios.get(
|
||||
`${import.meta.env.VITE_BASE_URL}/workflow/mosr/rd/expense/download/template`,
|
||||
{
|
||||
responseType: 'blob',
|
||||
headers: {
|
||||
Authorization: getToken()
|
||||
}
|
||||
}
|
||||
);
|
||||
};
|
||||
|
||||
36
src/api/research-fund/index.js
Normal file
@@ -0,0 +1,36 @@
|
||||
import request from '@/utils/request.js'
|
||||
|
||||
|
||||
export const getResearchFundChart = (year) => {
|
||||
return request({
|
||||
url: '/workflow/mosr/rd/home',
|
||||
method: 'get',
|
||||
params: {year:year}
|
||||
})
|
||||
}
|
||||
export const getResearchFundDetail = (rdFundId) => {
|
||||
return request({
|
||||
url: `/workflow/mosr/rd/${rdFundId}`,
|
||||
method: "get"
|
||||
});
|
||||
};
|
||||
export const addResearchFund= (data) => {
|
||||
return request({
|
||||
url: '/workflow/mosr/rd/add',
|
||||
method: "post",
|
||||
data
|
||||
});
|
||||
};
|
||||
export const editResearchFund= (data) => {
|
||||
return request({
|
||||
url: '/workflow/mosr/rd/update',
|
||||
method: "post",
|
||||
data
|
||||
});
|
||||
};
|
||||
export const deleteResearchFund = (rdFundIds) => {
|
||||
return request({
|
||||
url: `/workflow/mosr/rd/${rdFundIds}`,
|
||||
method: "delete"
|
||||
});
|
||||
};
|
||||
@@ -20,3 +20,11 @@ export const getCompanyDetail=(companyId)=>{
|
||||
method:'get'
|
||||
})
|
||||
}
|
||||
|
||||
export const setCompanyLeader=(data)=>{
|
||||
return request({
|
||||
url:'/admin/mosr/sub/company/leader',
|
||||
method:'post',
|
||||
data:data
|
||||
})
|
||||
}
|
||||
|
||||
@@ -21,6 +21,12 @@ export const getUserAccount = () => {
|
||||
method: 'get'
|
||||
})
|
||||
}
|
||||
export const judgeIsSameRole = (userId) => {
|
||||
return request({
|
||||
url: `/admin/mosr/user/company/same/${userId}`,
|
||||
method: 'get'
|
||||
})
|
||||
}
|
||||
|
||||
// 查询角色信息
|
||||
export const getRolesOpt = () => {
|
||||
@@ -38,6 +44,13 @@ export const getJobOpt = () => {
|
||||
})
|
||||
}
|
||||
|
||||
export const getMosrUserList = (params) => {
|
||||
return request({
|
||||
url: '/admin/mosr/user',
|
||||
method: 'get',
|
||||
params
|
||||
})
|
||||
}
|
||||
export const getUserList = (params) => {
|
||||
return request({
|
||||
url: '/admin/user',
|
||||
@@ -206,3 +219,33 @@ export const checkMatrix = (userId) => {
|
||||
method: 'get'
|
||||
})
|
||||
}
|
||||
export const getAgentInfo=(userId)=>{
|
||||
return request({
|
||||
url: `/admin/mosr/user/approval/agent/${userId}`,
|
||||
method:'get'
|
||||
})
|
||||
}
|
||||
|
||||
export const editAgentInfo=(data)=>{
|
||||
return request({
|
||||
url:'/admin/mosr/user/approval/agent',
|
||||
method:'post',
|
||||
data
|
||||
})
|
||||
}
|
||||
|
||||
export const addWhiteUser=(data)=>{
|
||||
return request({
|
||||
url:'/admin/approve/white',
|
||||
method:'post',
|
||||
data
|
||||
})
|
||||
}
|
||||
|
||||
export const delWhiteUser=(data)=>{
|
||||
return request({
|
||||
url:'/admin/approve/white',
|
||||
method:'delete',
|
||||
data
|
||||
})
|
||||
}
|
||||
|
||||
@@ -1,10 +1,11 @@
|
||||
import request from '@/utils/request.js'
|
||||
|
||||
//根据角色或者部门获取到对应的数据
|
||||
export function getUserTree(type, chooseId) {
|
||||
export function getUserTree(type,chooseId){
|
||||
return request({
|
||||
url: `/admin/user/choose/${type}/${chooseId}`,
|
||||
method: 'get'
|
||||
url:`/admin/user/choose/${type}/${chooseId}`,
|
||||
method:'get'
|
||||
|
||||
})
|
||||
}
|
||||
|
||||
@@ -15,7 +16,6 @@ export function getRole() {
|
||||
method: 'get'
|
||||
})
|
||||
}
|
||||
|
||||
//获取采取树形控件的部门option
|
||||
export function getDepartmentTree() {
|
||||
return request({
|
||||
@@ -23,12 +23,11 @@ export function getDepartmentTree() {
|
||||
method: 'get'
|
||||
})
|
||||
}
|
||||
|
||||
export function getMosrUser(params) {
|
||||
return request({
|
||||
url: '/admin/mosr/user/choose',
|
||||
method: 'get',
|
||||
params: params
|
||||
params:params
|
||||
})
|
||||
}
|
||||
|
||||
@@ -36,10 +35,9 @@ export function getOrganizationStructure(params) {
|
||||
return request({
|
||||
url: '/admin/organizational/structure/choose',
|
||||
method: 'get',
|
||||
params: params
|
||||
params:params
|
||||
})
|
||||
}
|
||||
|
||||
export function getOrganizationStructureTree(params) {
|
||||
return request({
|
||||
url: '/admin/organizational/structure/tree',
|
||||
|
||||
77
src/assets/axupimgs/plugin.js
Normal file
@@ -0,0 +1,77 @@
|
||||
tinymce.PluginManager.add('axupimgs', function (editor, url) {
|
||||
var pluginName = '多图片上传';
|
||||
window.axupimgs = {}; //扔外部公共变量,也可以扔一个自定义的位置
|
||||
const baseURL = import.meta.env.VITE_BASE_URL
|
||||
|
||||
// var baseURL=tinymce.baseURL;
|
||||
var iframe1 = '/upfiles.html';
|
||||
console.log('editor',editor)
|
||||
axupimgs.images_upload_handler = editor.getParam('images_upload_handler_not_loading', undefined, 'function');
|
||||
axupimgs.images_upload_base_path = editor.getParam('images_upload_base_path', '', 'string');
|
||||
axupimgs.axupimgs_filetype = editor.getParam('axupimgs_filetype', '.png,.gif,.jpg,.jpeg', 'string');
|
||||
axupimgs.res = [];
|
||||
var openDialog = function () {
|
||||
return editor.windowManager.openUrl({
|
||||
title: pluginName,
|
||||
size: 'large',
|
||||
url: iframe1,
|
||||
buttons: [
|
||||
{
|
||||
type: 'cancel',
|
||||
text: 'Close'
|
||||
},
|
||||
{
|
||||
type: 'custom',
|
||||
text: 'Save',
|
||||
name: 'save',
|
||||
primary: true
|
||||
},
|
||||
],
|
||||
onAction: function (api, details) {
|
||||
switch (details.name) {
|
||||
case 'save':
|
||||
var html = '';
|
||||
var imgs = axupimgs.res;
|
||||
var len = imgs.length;
|
||||
for (let i = 0; i < len; i++) {
|
||||
if (imgs[i].url) {
|
||||
html += '<img src="' + imgs[i].url + '" />';
|
||||
}
|
||||
}
|
||||
editor.insertContent(html);
|
||||
axupimgs.res = [];
|
||||
api.close();
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
editor.ui.registry.getAll().icons.axupimgs || editor.ui.registry.addIcon('axupimgs', '<svg viewBox="0 0 1280 1024" xmlns="http://www.w3.org/2000/svg" width="24" height="24"><path d="M1126.2,779.8V87.6c0-24-22.6-86.9-83.5-86.9H83.5C14.7,0.7,0,63.7,0,87.7v692c0,36.2,29.2,89.7,83.5,89.7l959.3-1.3c51.7,0,83.5-42.5,83.5-88.3zm-1044,4V86.3h961.6V783.7H82.2v0.1z" fill="#53565A"/><path d="M603,461.6L521.1,366.3,313,629.8,227.2,546.8,102.4,716.8H972.8v-170L768.2,235.2,603.1,461.6zM284.6,358.4a105.4,105.4,0,0,0,73.5-30c19.5-19.1,30.3-45,30.2-71.8,0-56.8-45.9-103-102.4-103-56.6,0-102.4,46.1-102.4,103C183.4,313.5,228,358.4,284.6,358.4z" fill="#9598A0"/><path d="M1197.7,153.6l-0.3,669.3s13.5,113.9-67.4,113.9H153.6c0,24.1,23.9,87.2,83.5,87.2h959.3c58.3,0,83.6-49.5,83.6-89.9V240.8c-0.1-41.8-44.9-87.2-82.3-87.2z" fill="#53565A"/></svg>');
|
||||
|
||||
editor.ui.registry.addButton('axupimgs', {
|
||||
icon: 'axupimgs',
|
||||
tooltip: pluginName,
|
||||
onAction: function () {
|
||||
openDialog();
|
||||
}
|
||||
});
|
||||
editor.ui.registry.addMenuItem('axupimgs', {
|
||||
icon: 'axupimgs',
|
||||
text: '图片批量上传...',
|
||||
onAction: function () {
|
||||
openDialog();
|
||||
}
|
||||
});
|
||||
return {
|
||||
getMetadata: function () {
|
||||
return {
|
||||
name: pluginName,
|
||||
url: "http://tinymce.ax-z.cn/more-plugins/axupimgs.php",
|
||||
};
|
||||
}
|
||||
};
|
||||
});
|
||||
75
src/assets/axupimgs/plugin.min.js
vendored
Normal file
@@ -0,0 +1,75 @@
|
||||
tinymce.PluginManager.add('axupimgs', function(editor, url) {
|
||||
var pluginName='Ax多图片上传';
|
||||
window.axupimgs={}; //扔外部公共变量,也可以扔一个自定义的位置
|
||||
|
||||
var baseURL=tinymce.baseURL;
|
||||
var iframe1 = baseURL+'/plugins/axupimgs/upfiles.html';
|
||||
axupimgs.images_upload_handler = editor.getParam('images_upload_handler', undefined, 'function');
|
||||
axupimgs.images_upload_base_path = editor.getParam('images_upload_base_path', '', 'string');
|
||||
axupimgs.axupimgs_filetype = editor.getParam('axupimgs_filetype', '.png,.gif,.jpg,.jpeg', 'string');
|
||||
axupimgs.res=[];
|
||||
var openDialog = function() {
|
||||
return editor.windowManager.openUrl({
|
||||
title: pluginName,
|
||||
size: 'large',
|
||||
url:iframe1,
|
||||
buttons: [
|
||||
{
|
||||
type: 'cancel',
|
||||
text: 'Close'
|
||||
},
|
||||
{
|
||||
type: 'custom',
|
||||
text: 'Save',
|
||||
name: 'save',
|
||||
primary: true
|
||||
},
|
||||
],
|
||||
onAction: function (api, details) {
|
||||
switch (details.name) {
|
||||
case 'save':
|
||||
var html = '';
|
||||
var imgs = axupimgs.res;
|
||||
var len = imgs.length;
|
||||
for(let i=0;i<len;i++){
|
||||
if( imgs[i].url ){
|
||||
html += '<img src="'+imgs[i].url+'" />';
|
||||
}
|
||||
}
|
||||
editor.insertContent(html);
|
||||
axupimgs.res=[];
|
||||
api.close();
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
editor.ui.registry.getAll().icons.axupimgs || editor.ui.registry.addIcon('axupimgs','<svg viewBox="0 0 1280 1024" xmlns="http://www.w3.org/2000/svg" width="24" height="24"><path d="M1126.2,779.8V87.6c0-24-22.6-86.9-83.5-86.9H83.5C14.7,0.7,0,63.7,0,87.7v692c0,36.2,29.2,89.7,83.5,89.7l959.3-1.3c51.7,0,83.5-42.5,83.5-88.3zm-1044,4V86.3h961.6V783.7H82.2v0.1z" fill="#53565A"/><path d="M603,461.6L521.1,366.3,313,629.8,227.2,546.8,102.4,716.8H972.8v-170L768.2,235.2,603.1,461.6zM284.6,358.4a105.4,105.4,0,0,0,73.5-30c19.5-19.1,30.3-45,30.2-71.8,0-56.8-45.9-103-102.4-103-56.6,0-102.4,46.1-102.4,103C183.4,313.5,228,358.4,284.6,358.4z" fill="#9598A0"/><path d="M1197.7,153.6l-0.3,669.3s13.5,113.9-67.4,113.9H153.6c0,24.1,23.9,87.2,83.5,87.2h959.3c58.3,0,83.6-49.5,83.6-89.9V240.8c-0.1-41.8-44.9-87.2-82.3-87.2z" fill="#53565A"/></svg>');
|
||||
|
||||
editor.ui.registry.addButton('axupimgs', {
|
||||
icon: 'axupimgs',
|
||||
tooltip: pluginName,
|
||||
onAction: function() {
|
||||
openDialog();
|
||||
}
|
||||
});
|
||||
editor.ui.registry.addMenuItem('axupimgs', {
|
||||
icon: 'axupimgs',
|
||||
text: '图片批量上传...',
|
||||
onAction: function() {
|
||||
openDialog();
|
||||
}
|
||||
});
|
||||
return {
|
||||
getMetadata: function() {
|
||||
return {
|
||||
name: pluginName,
|
||||
url: "http://tinymce.ax-z.cn/more-plugins/axupimgs.php",
|
||||
};
|
||||
}
|
||||
};
|
||||
});
|
||||
BIN
src/assets/home/home1.png
Normal file
|
After Width: | Height: | Size: 750 KiB |
BIN
src/assets/home/home2.png
Normal file
|
After Width: | Height: | Size: 736 KiB |
BIN
src/assets/home/home3.png
Normal file
|
After Width: | Height: | Size: 743 KiB |
BIN
src/assets/home/home4.png
Normal file
|
After Width: | Height: | Size: 733 KiB |
@@ -60,7 +60,7 @@ html, body, #app, .el-container, .el-aside, .el-main {
|
||||
top: 0;
|
||||
bottom: 0;
|
||||
left: 0;
|
||||
z-index: 1001;
|
||||
//z-index: 1001;
|
||||
}
|
||||
|
||||
.el-dialog {
|
||||
@@ -374,6 +374,9 @@ html, body, #app, .el-container, .el-aside, .el-main {
|
||||
left: 200px;
|
||||
}
|
||||
|
||||
//.el-overlay-dialog {
|
||||
// left: 200px !important;
|
||||
//}
|
||||
//放大缩小按钮上外边距
|
||||
.scale {
|
||||
margin-top: 10px;
|
||||
@@ -382,12 +385,10 @@ html, body, #app, .el-container, .el-aside, .el-main {
|
||||
//top: -20px;
|
||||
}
|
||||
|
||||
.el-overlay-dialog {
|
||||
left: 200px !important;
|
||||
}
|
||||
|
||||
.el-overlay-dialog::-webkit-scrollbar, .scrollbar-dict::-webkit-scrollbar {
|
||||
width: 6px;
|
||||
height: 6px;
|
||||
}
|
||||
|
||||
// 滚动条轨道
|
||||
@@ -473,7 +474,16 @@ html, body, #app, .el-container, .el-aside, .el-main {
|
||||
width: 1.8em;
|
||||
height: 1.7em;
|
||||
}
|
||||
|
||||
.home-time{
|
||||
width: 1.4em;
|
||||
height: 1.4em;
|
||||
margin-right: 5px;
|
||||
}
|
||||
.file-svg{
|
||||
width: 1.4em;
|
||||
height: 1.4em;
|
||||
fill: #BEA266;
|
||||
}
|
||||
.middle-icon {
|
||||
width: 1.4em;
|
||||
height: 1.4em;
|
||||
@@ -553,7 +563,7 @@ html, body, #app, .el-container, .el-aside, .el-main {
|
||||
// 操作页面底部按钮
|
||||
.oper-page-btn {
|
||||
position: fixed;
|
||||
bottom: 15px;
|
||||
top: 135px;
|
||||
right: 15px;
|
||||
z-index: 5;
|
||||
}
|
||||
|
||||
1
src/assets/svg/home-time.svg
Normal file
@@ -0,0 +1 @@
|
||||
<?xml version="1.0" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg t="1726060385019" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="8147" data-spm-anchor-id="a313x.search_index.0.i14.42e13a81ABrE1q" xmlns:xlink="http://www.w3.org/1999/xlink" width="128" height="128"><path d="M514 514m-448 0a448 448 0 1 0 896 0 448 448 0 1 0-896 0Z" fill="#bfbfbf" p-id="8148" data-spm-anchor-id="a313x.search_index.0.i9.42e13a81ABrE1q" class=""></path><path d="M542 543.4h-56v-310c0-16.6 13.4-30 30-30 14.4 0 26 11.6 26 26v314z" fill="#ffffff" p-id="8149" data-spm-anchor-id="a313x.search_index.0.i10.42e13a81ABrE1q" class="selected"></path><path d="M809.4 515.7v-4c0-14.4-11.6-26-26-26h-284v56h284c14.4 0 26-11.6 26-26z" fill="#ffffff" p-id="8150" data-spm-anchor-id="a313x.search_index.0.i8.42e13a81ABrE1q" class=""></path></svg>
|
||||
|
After Width: | Height: | Size: 934 B |
@@ -1,6 +0,0 @@
|
||||
<svg width="71" height="68" viewBox="0 0 71 68" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<g id="Group 229">
|
||||
<ellipse id="Ellipse 12" cx="35.3747" cy="33.663" rx="35.3747" ry="33.663" fill="#87C3ED"/>
|
||||
<path id="Subtract" fill-rule="evenodd" clip-rule="evenodd" d="M23.3174 21.8325C23.3174 20.7279 24.2128 19.8325 25.3174 19.8325H28.485V23.3688C28.485 23.9211 28.9327 24.3688 29.485 24.3688H32.7358C33.288 24.3688 33.7358 23.9211 33.7358 23.3688V19.8325H45.4049C46.5094 19.8325 47.4049 20.7279 47.4049 21.8325V44.741C47.4049 45.8456 46.5094 46.741 45.4049 46.741H25.3174C24.2128 46.741 23.3174 45.8456 23.3174 44.741V21.8325ZM32.7358 19.8325H29.485V23.3688L32.7358 23.3688V19.8325ZM28.876 29.1297H39.9933V28.1297H28.876V29.1297ZM41.8462 34.4079H28.876V33.4079H41.8462V34.4079ZM41.8462 39.6862H28.876V38.6862H41.8462V39.6862Z" fill="#0043C5"/>
|
||||
</g>
|
||||
</svg>
|
||||
|
Before Width: | Height: | Size: 860 B |
@@ -1,6 +0,0 @@
|
||||
<svg width="71" height="68" viewBox="0 0 71 68" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<g id="Group 230">
|
||||
<ellipse id="Ellipse 13" cx="35.3747" cy="33.663" rx="35.3747" ry="33.663" fill="#B487ED"/>
|
||||
<path id="Subtract" fill-rule="evenodd" clip-rule="evenodd" d="M41.1045 20.8325C41.1045 20.2802 40.6568 19.8325 40.1045 19.8325H26.1016C24.997 19.8325 24.1016 20.7279 24.1016 21.8325V44.741C24.1016 45.8456 24.997 46.741 26.1016 46.741H46.189C47.2936 46.741 48.189 45.8456 48.189 44.741V27.5596C48.189 27.0073 47.7413 26.5596 47.189 26.5596H42.1045C41.5522 26.5596 41.1045 26.1118 41.1045 25.5596V20.8325ZM43.9383 31.0958H31.1861V30.0958H43.9383V31.0958ZM35.4369 23.0234H39.6876V22.0234H35.4369V23.0234ZM43.9383 36.4777H31.1861V35.4777H43.9383V36.4777ZM31.1861 41.8593H43.9383V40.8593H31.1861V41.8593Z" fill="#8600C5"/>
|
||||
</g>
|
||||
</svg>
|
||||
|
Before Width: | Height: | Size: 838 B |
@@ -1,6 +0,0 @@
|
||||
<svg width="71" height="68" viewBox="0 0 71 68" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<g id="Group 231">
|
||||
<ellipse id="Ellipse 14" cx="35.3747" cy="33.663" rx="35.3747" ry="33.663" fill="#FDCB9D"/>
|
||||
<path id="Subtract" fill-rule="evenodd" clip-rule="evenodd" d="M54.4044 32.614C54.4044 40.4161 46.1575 46.741 35.9845 46.741C32.9189 46.741 30.0281 46.1666 27.4852 45.1505C27.3501 45.3211 27.1528 45.4524 26.9047 45.5078L19.6131 47.1386C18.844 47.3106 18.1654 46.6256 18.393 45.9072L20.2692 39.9868C18.5537 37.8406 17.5647 35.3159 17.5647 32.614C17.5647 24.8119 25.8115 18.4871 35.9845 18.4871C46.1575 18.4871 54.4044 24.8119 54.4044 32.614ZM28.1916 34.6321C29.3654 34.6321 30.317 33.7286 30.317 32.614C30.317 31.4994 29.3654 30.5958 28.1916 30.5958C27.0178 30.5958 26.0662 31.4994 26.0662 32.614C26.0662 33.7286 27.0178 34.6321 28.1916 34.6321ZM38.8184 32.614C38.8184 33.7286 37.8669 34.6321 36.6931 34.6321C35.5193 34.6321 34.5677 33.7286 34.5677 32.614C34.5677 31.4994 35.5193 30.5958 36.6931 30.5958C37.8669 30.5958 38.8184 31.4994 38.8184 32.614ZM45.1945 34.6321C46.3683 34.6321 47.3198 33.7286 47.3198 32.614C47.3198 31.4994 46.3683 30.5958 45.1945 30.5958C44.0207 30.5958 43.0691 31.4994 43.0691 32.614C43.0691 33.7286 44.0207 34.6321 45.1945 34.6321Z" fill="#F47D0E"/>
|
||||
</g>
|
||||
</svg>
|
||||
|
Before Width: | Height: | Size: 1.3 KiB |
@@ -1,6 +0,0 @@
|
||||
<svg width="71" height="68" viewBox="0 0 71 68" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<g id="Group 232">
|
||||
<ellipse id="Ellipse 19" cx="35.3747" cy="33.663" rx="35.3747" ry="33.663" fill="#87EDBC"/>
|
||||
<path id="Subtract" fill-rule="evenodd" clip-rule="evenodd" d="M18.7023 20.134C18.1358 20.4872 17.7588 21.1158 17.7588 21.8325V42.0502C17.7588 43.1547 18.6542 44.0502 19.7588 44.0502H48.3477C49.4523 44.0502 50.3477 43.1547 50.3477 42.0502V21.8325C50.3477 21.1082 49.9627 20.4738 49.3861 20.1229L49.9153 20.9221L35.7553 30.2976C34.9339 30.8415 33.8697 30.8523 33.0374 30.3252L18.1997 20.9276L18.7023 20.134ZM18.7605 20.0991L33.5725 29.4804C34.0718 29.7966 34.7104 29.7902 35.2032 29.4638L49.3465 20.0993C49.0526 19.9296 48.7115 19.8325 48.3477 19.8325H19.7588C19.3952 19.8325 19.0543 19.9295 18.7605 20.0991Z" fill="#01A054"/>
|
||||
</g>
|
||||
</svg>
|
||||
|
Before Width: | Height: | Size: 845 B |
1
src/assets/svg/research_fund.svg
Normal file
@@ -0,0 +1 @@
|
||||
<?xml version="1.0" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg t="1726897356959" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="4330" xmlns:xlink="http://www.w3.org/1999/xlink" width="256" height="256"><path d="M26.293 1022.219c-14.41 0-26.122-11.652-26.122-26.006 0-14.41 11.712-26.182 26.122-26.182h818.455c69.64 0 126.306-58.5 126.306-130.379l-0.174-679.348c0-14.525 11.654-26.236 26.009-26.236 14.41 0 26.178 11.711 26.178 26.236l0.115 679.348c0 100.699-80.03 182.566-178.434 182.566H26.293z" fill="#2c2c2c" p-id="4331"></path><path d="M679.977 873.811c-14.41 0-26.063-11.654-26.063-26.006V674.537c0-14.352 11.653-26.006 26.063-26.006s26.124 11.654 26.124 26.006v173.268c0 14.351-11.714 26.006-26.124 26.006zM504.759 873.811c-14.354 0-26.009-11.654-26.009-26.006v-186.76c0-14.352 11.655-26.006 26.009-26.006 14.41 0 26.065 11.654 26.065 26.006v186.76c0 14.351-11.655 26.006-26.065 26.006zM336.313 873.811c-14.41 0-26.122-11.654-26.122-26.006v-92.26c0-14.412 11.712-26.123 26.122-26.123 14.354 0 25.894 11.711 25.894 26.123v92.26c0 14.351-11.54 26.006-25.894 26.006zM174.357 873.811c-14.354 0-26.009-11.654-26.009-26.006v-85.658c0-14.352 11.655-25.949 26.009-25.949 14.41 0 26.178 11.598 26.178 25.949v85.658c0 14.351-11.767 26.006-26.178 26.006zM50.637 873.811c-14.354 0-26.01-11.654-26.01-26.006v-85.658c0-14.352 11.655-25.949 26.01-25.949 14.41 0 26.121 11.598 26.121 25.949v85.658c0 14.351-11.711 26.006-26.121 26.006zM848.652 873.754c-14.41 0-26.124-11.598-26.124-25.949V573.379c0-14.354 11.714-26.006 26.124-26.006 14.352 0 26.007 11.652 26.007 26.006v274.426c0 14.351-11.655 25.949-26.007 25.949zM26.121 675.111C11.711 675.111 0 663.514 0 649.219c0-14.41 11.711-26.121 26.121-26.121h289.696l169.65-186.988c5.053-5.453 12.172-8.555 19.406-8.555 4.132 0 8.209 1.033 12.169 3.041l142.667 77.391 168.503-212.135c4.65-6.313 12.573-10.217 20.782-10.217 12.287 1.436 20.555 7.348 24.229 16.648 3.331 8.783 1.722 18.717-4.134 25.951l-182.05 229.299c-5.111 6.201-12.458 9.76-20.381 9.76-4.42 0-8.67-1.09-12.517-3.271L510.385 486.4 346.59 666.729c-4.648 5.283-11.768 8.383-19.289 8.383H26.121zM245.316 381.566c-10.333 0-18.716-8.439-18.716-18.715v-57.697h-62.578c-10.276 0-18.716-8.439-18.716-18.717 0-10.334 8.439-18.658 18.716-18.658h62.637v-38.064h-62.637c-10.22 0-18.659-8.439-18.659-18.715 0-10.221 8.439-18.604 18.659-18.604h66.884l-63.21-58.846c-5.109-4.592-7.291-11.369-5.741-17.854 1.379-6.717 6.258-12 12.688-13.896 1.551-0.112 3.042-0.112 4.362-0.112 7.234 0 10.967 1.662 13.896 4.535l51.842 47.994 45.986-47.307c3.445-3.673 8.268-5.625 13.32-5.625 4.878 0 9.588 1.837 12.975 5.28 3.674 3.446 5.626 8.097 5.74 12.976 0.057 4.996-1.78 9.818-5.282 13.436l-57.983 59.418h60.912c10.218 0 18.657 8.383 18.657 18.604 0 10.275-8.439 18.715-18.657 18.715h-56.436v38.064h56.436c10.218 0 18.657 8.324 18.657 18.658 0 10.277-8.439 18.717-18.657 18.717h-56.436v57.697c0.001 10.277-8.382 18.716-18.659 18.716z" fill="#2c2c2c" p-id="4332"></path><path d="M241.699 476.182c-61.602 0-121.94-25.145-165.517-68.721C16.648 348.27-6.89 261.291 14.696 180.229c21.586-80.896 85.313-144.619 166.32-166.38 19.808-5.282 40.015-7.866 60.455-7.866 62.176 0 122.858 25.262 166.606 69.411 67.459 67.284 87.438 167.755 50.866 255.882-36.341 87.955-121.482 144.906-216.785 144.906h-0.459z m0.46-432.193c-108.853 0-197.379 88.528-197.379 197.382 0 108.965 88.526 197.494 197.379 197.494 108.909 0 197.438-88.529 197.438-197.494 0-108.853-88.529-197.382-197.438-197.382z" fill="#2c2c2c" p-id="4333"></path></svg>
|
||||
|
After Width: | Height: | Size: 3.5 KiB |
@@ -1,30 +1,33 @@
|
||||
<template>
|
||||
<el-form :model="formData" ref="applyForm" :rules="rules" :label-position="labelPosition">
|
||||
<el-form :model="formData" ref="applyForm" :rules="rules" :label-position="labelPosition" :style="{marginLeft: label==='项目验收附件'?'25px': label==='项目立项附件'?'25px':'5px'}">
|
||||
<el-row>
|
||||
<!-- <el-col :span="24">-->
|
||||
<!-- <el-form-item :label="label" prop="attachment" >-->
|
||||
<!-- <template v-if="preview">-->
|
||||
<!-- <file-upload @getFile="getAttachment" :multiple="false"-->
|
||||
<!-- :disabled="singleFileArray?.length>0?true:false" title="如需修改需求申请书附件,请先删除文件再上传!"/>-->
|
||||
<!-- <fvTable style="width: 100%;max-height: 80px;" height="80" v-if="singleFileArray?.length>0"-->
|
||||
<!-- :tableConfig="editSingleTableConfig"-->
|
||||
<!-- :data="singleFileArray" :isSettingCol="false" :pagination="false">-->
|
||||
<!-- </fvTable>-->
|
||||
<!-- </template>-->
|
||||
<!-- <template v-else-if="!preview">-->
|
||||
<!-- <file-upload @getFile="getAttachment" :multiple="false"-->
|
||||
<!-- :disabled="isSingleFile"/>-->
|
||||
<!-- <fvTable style="width: 100%;max-height: 80px;" v-if="showSingleTable" height="80"-->
|
||||
<!-- :tableConfig="singleTableConfig"-->
|
||||
<!-- :data="_singleFileValue" :isSettingCol="false" :pagination="false">-->
|
||||
<!-- </fvTable>-->
|
||||
<!-- </template>-->
|
||||
<!-- </el-form-item>-->
|
||||
<!-- </el-col>-->
|
||||
<el-col :span="24">
|
||||
<el-form-item :label="label" prop="attachment" label-width="125">
|
||||
<template v-if="preview&&JSON.stringify(singleFile) !== '{}'&&JSON.stringify(singleFile)!=='null'">
|
||||
<el-button type="primary" link @click="handleDownload(singleFile)" style="font-size: 16px">
|
||||
{{ singleFile ? singleFile?.originalFileName : formData.singleFile?.originalFileName }}
|
||||
</el-button>
|
||||
<el-button type="danger" link @click="deleteSingleFile(singleFile?singleFile:formData.singleFile,1)">删除
|
||||
</el-button>
|
||||
</template>
|
||||
<template
|
||||
v-else-if="!preview||JSON.stringify(singleFile) == '{}'||singleFile==null||formData.singleFile==null">
|
||||
<file-upload @getFile="getAttachment" :multiple="false"
|
||||
:disabled="isSingleFile" ref="fileUploadRef"/>
|
||||
<!-- :showFileList="showFileList" @delete="deleteAttachment"-->
|
||||
<fvTable style="width: 100%;max-height: 80px;" v-if="showSingleTable" height="80" :tableConfig="singleTableConfig"
|
||||
:data="_singleFileValue" :isSettingCol="false" :pagination="false">
|
||||
</fvTable>
|
||||
</template>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="24">
|
||||
<el-form-item label="其他文件" label-width="125">
|
||||
<el-form-item :label="label" prop="" :required="label!='项目归档附件'">
|
||||
<file-upload @getFile="getOtherFile"/>
|
||||
<fvTable style="width: 100%;max-height: 162px;" v-if="showTable" height="162" :tableConfig="tableConfig"
|
||||
<el-button color="#DED0B2" v-if="templateDownloadBtnShow" @click="handleImportTemplateDownload"
|
||||
style="margin-left: 10px">模板下载
|
||||
</el-button>
|
||||
<fvTable style="width: 100%;" :height="label=='项目立项附件'?'160':'160'" :scrollbar-always-on="true" :style="{maxHeight:label=='项目立项附件'?'160px':'160px',height:label=='项目立项附件'?'160px':'160px'}" v-if="showTable" :tableConfig="tableConfig"
|
||||
:data="allFileList" :isSettingCol="false" :pagination="false">
|
||||
<template #empty>
|
||||
<el-empty :image-size="55" description="暂无数据" style="padding: 0"/>
|
||||
@@ -34,11 +37,14 @@
|
||||
</el-col>
|
||||
</el-row>
|
||||
</el-form>
|
||||
<file-preview ref="filePreviewRef" v-if="filePreviewShow" :fileName="filePreviewParam.fileName"
|
||||
:fileUrl="filePreviewParam.fileUrl"
|
||||
:fileType="filePreviewParam.fileType"/>
|
||||
</template>
|
||||
|
||||
<script setup lang="jsx">
|
||||
import FileUpload from '@/components/FileUpload.vue'
|
||||
import {deleteFile, downloadFile} from "@/api/project-demand";
|
||||
import {deleteFile, downloadFile, downloadTemplate, downloadTemplateZip} from "@/api/project-demand";
|
||||
import {ElMessageBox, ElNotification} from "element-plus";
|
||||
|
||||
|
||||
@@ -63,6 +69,16 @@ const props = defineProps({
|
||||
type: Boolean,
|
||||
default: false
|
||||
},
|
||||
//是否显示模板下载按钮
|
||||
templateDownloadBtnShow: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
},
|
||||
//模板下载时的文件名
|
||||
templateName: {
|
||||
type: String,
|
||||
default: ''
|
||||
},
|
||||
singleList: {
|
||||
type: Array,
|
||||
default: []
|
||||
@@ -84,32 +100,44 @@ const props = defineProps({
|
||||
default: ''
|
||||
}
|
||||
})
|
||||
const emit = defineEmits(["getAttachment", "getOtherFile","update:singleList"])
|
||||
const emit = defineEmits(["getAttachment", "getOtherFile", "update:singleList"])
|
||||
|
||||
const baseTableConf = reactive(
|
||||
[
|
||||
{
|
||||
prop: 'index',
|
||||
type: 'index',
|
||||
label: '序号',
|
||||
align: 'center',
|
||||
width: '80',
|
||||
},
|
||||
{
|
||||
prop: 'originalFileName',
|
||||
label: '文件名',
|
||||
align: 'center',
|
||||
width: 400,
|
||||
currentRender: ({row, index}) => (
|
||||
<div style="color: #2a99ff;cursor: pointer;"
|
||||
onClick={() => clickToPreview(row)}>{row.originalFileName}</div>)
|
||||
},
|
||||
{
|
||||
prop: 'tag',
|
||||
label: '标签',
|
||||
align: 'center',
|
||||
// currentRender: ({row, index}) => (
|
||||
// <el-input placeholder={row.tag} onClick={() => {}}></el-input>)
|
||||
},
|
||||
{
|
||||
prop: 'size',
|
||||
label: '文件大小',
|
||||
align: 'center',
|
||||
currentRender: ({row, index}) => (parseInt(row.size / 1024) + 'KB')
|
||||
},
|
||||
]
|
||||
)
|
||||
const tableConfig = reactive({
|
||||
columns: [
|
||||
{
|
||||
prop: 'index',
|
||||
type: 'index',
|
||||
label: '序号',
|
||||
align: 'center',
|
||||
width: '80',
|
||||
},
|
||||
{
|
||||
prop: 'originalFileName',
|
||||
label: '文件名',
|
||||
align: 'center',
|
||||
},
|
||||
{
|
||||
prop: 'tag',
|
||||
label: '标签',
|
||||
align: 'center'
|
||||
},
|
||||
{
|
||||
prop: 'size',
|
||||
label: '文件大小',
|
||||
align: 'center',
|
||||
currentRender: ({row, index}) => (parseInt(row.size / 1024) + 'KB')
|
||||
},
|
||||
...baseTableConf,
|
||||
{
|
||||
prop: 'oper',
|
||||
label: '操作',
|
||||
@@ -149,29 +177,7 @@ const tableConfig = reactive({
|
||||
})
|
||||
const singleTableConfig = reactive({
|
||||
columns: [
|
||||
{
|
||||
prop: 'index',
|
||||
type: 'index',
|
||||
label: '序号',
|
||||
align: 'center',
|
||||
width: '80',
|
||||
},
|
||||
{
|
||||
prop: 'originalFileName',
|
||||
label: '文件名',
|
||||
align: 'center',
|
||||
},
|
||||
{
|
||||
prop: 'tag',
|
||||
label: '标签',
|
||||
align: 'center'
|
||||
},
|
||||
{
|
||||
prop: 'size',
|
||||
label: '文件大小',
|
||||
align: 'center',
|
||||
currentRender: ({row, index}) => (parseInt(row.size / 1024) + 'KB')
|
||||
},
|
||||
...baseTableConf,
|
||||
{
|
||||
prop: 'oper',
|
||||
label: '操作',
|
||||
@@ -209,19 +215,68 @@ const singleTableConfig = reactive({
|
||||
}
|
||||
]
|
||||
})
|
||||
const fileUploadRef = ref()
|
||||
const editSingleTableConfig = reactive({
|
||||
columns: [
|
||||
...baseTableConf,
|
||||
{
|
||||
prop: 'oper',
|
||||
label: '操作',
|
||||
align: 'center',
|
||||
showOverflowTooltip: false,
|
||||
currentRender: ({row, index}) => {
|
||||
let btn = []
|
||||
btn.push({label: '下载', func: () => handleDownload(row), type: 'primary'})
|
||||
// if (row.newFile) {
|
||||
// btn.push({label: '删除', func: () => handleDelete(row), type: 'primary'})
|
||||
// }
|
||||
return (
|
||||
<div style={{width: '100%'}}>
|
||||
{
|
||||
btn.map(item => (
|
||||
<el-button
|
||||
type={item.type}
|
||||
onClick={() => item.func()}
|
||||
link
|
||||
>
|
||||
{item.label}
|
||||
</el-button>
|
||||
))
|
||||
}
|
||||
{
|
||||
row.newFile || props.preview || !props.preview ?
|
||||
<popover-delete name={row.originalFileName} type={'文件'} btnType={'danger'}
|
||||
// perm={['']}
|
||||
onDelete={() => deleteSingleFile(row, 1)}/>
|
||||
: ''
|
||||
}
|
||||
</div>
|
||||
)
|
||||
}
|
||||
}
|
||||
]
|
||||
})
|
||||
const singleFileArray = ref([])
|
||||
const rules = reactive({
|
||||
attachment: [{required: true, message: '请上传附件', trigger: ['blur', 'change']}],
|
||||
// attachment: [{required: true, message: '请上传附件', trigger: ['blur', 'change']}],
|
||||
})
|
||||
const applyForm = ref()
|
||||
const singleFile = ref(props.formData.singleFile)
|
||||
const singleFile = ref({})
|
||||
const isSingleFile = ref(false)
|
||||
const isHaveOneFile = ref(false)
|
||||
const allFileList = ref([])
|
||||
const deleteFileVal = ref({})
|
||||
const singleFileList = ref([])
|
||||
if(localStorage.getItem('singleFile')){
|
||||
if (localStorage.getItem('singleFile')) {
|
||||
singleFileArray.value.push(JSON.parse(localStorage.getItem('singleFile')))
|
||||
singleFile.value = JSON.parse(localStorage.getItem('singleFile'))
|
||||
}
|
||||
|
||||
const filePreviewParam = ref({
|
||||
fileUrl: '',
|
||||
fileName: '',
|
||||
fileType: 'pdf'
|
||||
})
|
||||
const filePreviewRef = ref()
|
||||
const filePreviewShow = ref(false)
|
||||
|
||||
const _singleFileValue = computed({
|
||||
get() {
|
||||
return props.singleList;
|
||||
@@ -230,8 +285,6 @@ const _singleFileValue = computed({
|
||||
emit('update:singleList', value)
|
||||
}
|
||||
})
|
||||
|
||||
// console.log('_singleFileValue',_singleFileValue.value)
|
||||
const _otherFileListValue = computed({
|
||||
get() {
|
||||
return props.otherFileList;
|
||||
@@ -240,21 +293,35 @@ const _otherFileListValue = computed({
|
||||
emit('update:otherFileList', value)
|
||||
}
|
||||
})
|
||||
if(_otherFileListValue.value&&_otherFileListValue.value.length>0){
|
||||
_otherFileListValue.value.forEach(item=>{
|
||||
if (_otherFileListValue.value && _otherFileListValue.value.length > 0) {
|
||||
isHaveOneFile.value = true
|
||||
_otherFileListValue.value.forEach(item => {
|
||||
allFileList.value.push(item)
|
||||
})
|
||||
}
|
||||
watch(() => props.showSingleTable, (newVal) => {
|
||||
props.showSingleTable = newVal
|
||||
}, {deep: true})
|
||||
// watch(() => props.showSingleTable, (newVal) => {
|
||||
// props.showSingleTable = newVal
|
||||
// }, {deep: true})
|
||||
watch(() => props.formData.fileList, (newVal) => {
|
||||
if (props.preview) {
|
||||
newVal?.forEach(item => {
|
||||
isHaveOneFile.value = true
|
||||
allFileList.value.push(item)
|
||||
})
|
||||
}
|
||||
}, {immediate: true})
|
||||
|
||||
watch(() => props.formData.singleFile, (newVal) => {
|
||||
props.formData.singleFile = newVal
|
||||
if (newVal != null) {
|
||||
singleFileArray.value.push(newVal)
|
||||
} else {
|
||||
singleFileArray.value = []
|
||||
}
|
||||
singleFile.value = newVal
|
||||
}, {immediate: true})
|
||||
|
||||
|
||||
// watch(() => props.otherFileList, (newVal) => {
|
||||
// props.otherFileList=newVal
|
||||
// if (props.preview) {
|
||||
@@ -278,43 +345,104 @@ watch(() => props.showTable, (newVal) => {
|
||||
// console.log('singleFile', newVal)
|
||||
// singleFileList.value = newVal
|
||||
// }, {deep: true})
|
||||
watch(() => props.formData.singleFile, (newVal) => {
|
||||
// console.log('singleFile', newVal)
|
||||
singleFile.value = newVal
|
||||
props.formData.singleFile=newVal
|
||||
}, {deep: true})
|
||||
|
||||
watch(() => isSingleFile.value, (newVal) => {
|
||||
isSingleFile.value = newVal
|
||||
}, {deep: true})
|
||||
watch(() => singleFile.value, (newVal) => {
|
||||
singleFile.value = newVal
|
||||
watch(() => isHaveOneFile.value, (newVal) => {
|
||||
isHaveOneFile.value = newVal
|
||||
}, {deep: true})
|
||||
// watch(() => singleFile.value, (newVal) => {
|
||||
// singleFile.value = newVal
|
||||
// }, {deep: true})
|
||||
|
||||
|
||||
const handleImportTemplateDownload = async () => {
|
||||
console.info("🚀 ~method:handleImportTemplateDownload -----", props.tag)
|
||||
let templateType = ''
|
||||
let templateTypeList = ''
|
||||
let isZip = false
|
||||
if (props.tag === '需求上报') {
|
||||
templateType = '2'
|
||||
isZip = false
|
||||
} else if (props.tag === '项目立项') {
|
||||
templateTypeList = '5,6'
|
||||
isZip = true
|
||||
} else if (props.tag === '项目验收') {
|
||||
templateType = '7'
|
||||
isZip = false
|
||||
} else if (props.tag === '阶段变更') {
|
||||
templateTypeList = '8,9'
|
||||
isZip = true
|
||||
}
|
||||
let res = ''
|
||||
if (isZip) {
|
||||
res = await downloadTemplateZip(templateTypeList)
|
||||
let fileName = props.templateName +'.zip'
|
||||
const blob = new Blob([res.data])
|
||||
let a = document.createElement('a')
|
||||
a.href = URL.createObjectURL(blob)
|
||||
a.download = fileName
|
||||
a.click()
|
||||
} else {
|
||||
res = await downloadTemplate(templateType)
|
||||
const blob = new Blob([res])
|
||||
let a = document.createElement('a')
|
||||
a.href = URL.createObjectURL(blob)
|
||||
a.download = props.templateName + ".docx"
|
||||
a.click()
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
const clickToPreview = (row) => {
|
||||
filePreviewShow.value = false
|
||||
console.log('clickToPreview', row, row.fileType)
|
||||
filePreviewParam.value = {
|
||||
fileUrl: row.url,
|
||||
fileName: row.originalFileName,
|
||||
fileType: row.fileType
|
||||
}
|
||||
nextTick(() => {
|
||||
filePreviewShow.value = true
|
||||
})
|
||||
// filePreviewRef.value.show()
|
||||
}
|
||||
|
||||
|
||||
const handleDelete = (row, type) => {
|
||||
deleteFile(row.fileId).then(res => {
|
||||
ElNotification({
|
||||
title: '提示',
|
||||
message: res.msg,
|
||||
type: res.code === 1000 ? 'success' : 'error'
|
||||
})
|
||||
if (res.code === 1000) {
|
||||
// deleteFile(row.fileId).then(res => {
|
||||
// ElNotification({
|
||||
// title: '提示',
|
||||
// message: res.msg,
|
||||
// type: res.code === 1000 ? 'success' : 'error'
|
||||
// })
|
||||
// if (res.code === 1000) {
|
||||
if (type === 'single') {
|
||||
_singleFileValue.value.splice(_singleFileValue.value.findIndex((item) => item.fileId === row.fileId), 1);
|
||||
isSingleFile.value = false
|
||||
} else {
|
||||
allFileList.value.splice(allFileList.value.findIndex((item) => item.fileId === row.fileId), 1);
|
||||
isHaveOneFile.value = !(allFileList.value && allFileList.value?.length == 0);
|
||||
console.log('allFileList.value',allFileList.value)
|
||||
if (localStorage.getItem('collectData')) {
|
||||
let collectData = JSON.parse(localStorage.getItem('collectData'))
|
||||
collectData.fileList = allFileList.value
|
||||
localStorage.setItem('collectData', JSON.stringify(collectData))
|
||||
}
|
||||
if (localStorage.getItem('otherFileList')) {
|
||||
localStorage.setItem('otherFileList', JSON.stringify(allFileList.value))
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
// }
|
||||
// });
|
||||
}
|
||||
const handleSingleDelete = (row) => {
|
||||
// console.log('row',row)
|
||||
// fileUploadRef.value.handleRemove(deleteFileVal.value.id)
|
||||
handleDelete(row, 'single')
|
||||
}
|
||||
const getAttachment = (val) => {
|
||||
// console.log('getAttachment', val)
|
||||
isSingleFile.value = true
|
||||
// deleteFileVal.value=val
|
||||
emit('getAttachment', val)
|
||||
}
|
||||
const compositeParam = (item) => {
|
||||
@@ -334,6 +462,7 @@ const getOtherFile = (val) => {
|
||||
} else {
|
||||
allFileList.value = _otherFileListValue.value
|
||||
}
|
||||
isHaveOneFile.value = true
|
||||
emit('getOtherFile', val)
|
||||
}
|
||||
const deleteAttachment = (val) => {
|
||||
@@ -346,6 +475,7 @@ const deleteAttachment = (val) => {
|
||||
})
|
||||
isSingleFile.value = false
|
||||
singleFile.value = null
|
||||
singleFileArray.value = []
|
||||
}
|
||||
});
|
||||
}
|
||||
@@ -365,6 +495,7 @@ const deleteSingleFile = (row, type) => {
|
||||
isSingleFile.value = false
|
||||
if (type === 1) {
|
||||
singleFile.value = null
|
||||
singleFileArray.value = []
|
||||
} else {
|
||||
props.otherFileList.splice(props.otherFileList.findIndex((item) => item.fileId === row.fileId), 1);
|
||||
}
|
||||
@@ -396,12 +527,28 @@ defineExpose({
|
||||
},
|
||||
allFileList,
|
||||
singleFile,
|
||||
isSingleFile
|
||||
isSingleFile,
|
||||
isHaveOneFile,
|
||||
})
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
<style lang="scss" scoped>
|
||||
:deep(.el-table--fit ) {
|
||||
height: 300px !important;
|
||||
height: 160px !important;
|
||||
}
|
||||
:deep(.el-table__header) {
|
||||
.is-leaf:first-child {
|
||||
.cell {
|
||||
margin-left: -22px !important;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
:deep(.el-table__body) {
|
||||
.el-table__cell:first-child {
|
||||
.cell {
|
||||
margin-left: -11px !important;
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
||||
@@ -84,7 +84,6 @@ const getSummaries = (param) => {
|
||||
// }
|
||||
const exportExcelHandler = () => {
|
||||
shareExportExcel(route.query.id).then(res => {
|
||||
console.log(res)
|
||||
let fileName = `科技创新项目费用分摊表-${props.allocationName}.zip`
|
||||
const blob = new Blob([res.data])
|
||||
let a = document.createElement('a')
|
||||
|
||||
@@ -1,37 +1,9 @@
|
||||
<template>
|
||||
<div v-loading="loading">
|
||||
<el-row v-if="type==='execute'">
|
||||
<el-col :span="24">
|
||||
<baseTitle :title="'附件信息'"></baseTitle>
|
||||
</el-col>
|
||||
<el-form :model="attachmentParam" inline style="margin-top: 15px">
|
||||
<el-form-item label="标签" prop="tag">
|
||||
<el-select v-model="attachmentParam.tag" placeholder="请选择标签" clearable filterable style="width: 300px">
|
||||
<el-option
|
||||
v-for="item in tagsOption"
|
||||
:key="item.value"
|
||||
:label="item.label"
|
||||
:value="item.value"
|
||||
/>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item>
|
||||
<el-button @click="handleSearchImplementationFileList" color="#DED0B2">搜索</el-button>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
<fvTable style="width: 100%;min-height:162px;max-height: 162px" v-if="showAttachmentTable" height="162"
|
||||
:tableConfig="tableConfig"
|
||||
:data="otherAttachmentList" :isSettingCol="false" :pagination="false">
|
||||
<template #empty>
|
||||
<el-empty :image-size="55" description="暂无数据" style="padding: 0"/>
|
||||
</template>
|
||||
</fvTable>
|
||||
</el-row>
|
||||
|
||||
<baseTitle v-if="type!='phase'" :title="getTagName(type)+getTitleInfo(data.taskId)"></baseTitle>
|
||||
<fvForm :schema="schema" @getInstance="(e)=>form = e"></fvForm>
|
||||
<fvForm :schema="schema" @getInstance="(e)=>form = e" style="margin-left: 15px"></fvForm>
|
||||
<el-form :model="formData" label-width="auto" style="margin-top: -15px">
|
||||
<file-component :title="getTagName(type)+'附件'" :tag="getTagName(type)"
|
||||
<file-component :title="getTagName(type)+'附件'" :tag="getTagName(type)" :isOpenPrint="isOpenPrint"
|
||||
v-model:value="formData.fileList" :processViewer="processViewer"
|
||||
:file-list-show="fileListShow"/>
|
||||
</el-form>
|
||||
@@ -56,6 +28,9 @@
|
||||
style="--el-switch-on-color:#BEA266 ; --el-switch-off-color:#cecdcd"
|
||||
/>
|
||||
</div>
|
||||
<el-button color="#DED0B2" style="margin-left: 10px"
|
||||
@click="handleCarbonCopy()">立即抄送
|
||||
</el-button>
|
||||
</div>
|
||||
<div class="process">
|
||||
<operation-render v-if="processViewer && data.operationList && data.operationList.length > 0&&!changeDiagram"
|
||||
@@ -64,6 +39,13 @@
|
||||
<process-diagram-viewer v-if="processViewer&&changeDiagram" :id-name="idName?idName:type"/>
|
||||
</div>
|
||||
</div>
|
||||
<user-picker :multiple="true" ref="carbonCopyUserRef" title="请选择抄送人员"
|
||||
v-model:value="carbonCopyUserList" @ok="carbonCopyUserPickerOk"
|
||||
@cancelOrClear="carbonCopyUserPickerOk"/>
|
||||
|
||||
<file-preview ref="filePreviewRef" :fullscreen="fullscreen" v-if="filePreviewShow"
|
||||
:fileName="filePreviewParam.fileName" :fileUrl="filePreviewParam.fileUrl"
|
||||
:fileType="filePreviewParam.fileType"/>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
@@ -74,55 +56,9 @@ import {ElLoading, ElNotification} from 'element-plus';
|
||||
import {downloadFile} from "@/api/project-demand";
|
||||
import {searchImplementationFileList} from "@/api/project-manage/attachment";
|
||||
import {getTags} from "@/api/project-manage";
|
||||
import {applyCcSend} from "@/api/expense-manage";
|
||||
import UserPicker from "@/views/workflow/process/common/UserPicker.vue";
|
||||
|
||||
const attachmentParam = reactive({
|
||||
tag: ''
|
||||
})
|
||||
const tagsOption = ref([])
|
||||
const uploadState = ref(false)
|
||||
const showAttachmentTable = ref(true)
|
||||
const otherAttachmentList = ref([])
|
||||
|
||||
const tableConfig = reactive({
|
||||
columns: [
|
||||
{
|
||||
prop: 'index',
|
||||
type: 'index',
|
||||
label: '序号',
|
||||
align: 'center',
|
||||
width: '80',
|
||||
},
|
||||
{
|
||||
prop: 'originalFileName',
|
||||
label: '文件名',
|
||||
align: 'center',
|
||||
},
|
||||
{
|
||||
prop: 'tag',
|
||||
label: '标签',
|
||||
align: 'center'
|
||||
},
|
||||
{
|
||||
prop: 'size',
|
||||
label: '文件大小',
|
||||
align: 'center',
|
||||
currentRender: ({row, index}) => (parseInt(row.size / 1024) + 'KB')
|
||||
},
|
||||
{
|
||||
prop: 'oper',
|
||||
label: '操作',
|
||||
align: 'center',
|
||||
showOverflowTooltip: false,
|
||||
currentRender: ({row, index}) => {
|
||||
return (
|
||||
<div>
|
||||
<el-button type="primary" link onClick={() => handleDownload(row)}>下载</el-button>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
}
|
||||
]
|
||||
})
|
||||
const changeDiagram = ref(false)
|
||||
const props = defineProps({
|
||||
formData: {
|
||||
@@ -141,10 +77,18 @@ const props = defineProps({
|
||||
type: Array,
|
||||
default: []
|
||||
},
|
||||
basicData: {
|
||||
type: Object,
|
||||
default: {}
|
||||
},
|
||||
fileListShow: {
|
||||
type: String,
|
||||
default: 'READ'
|
||||
},
|
||||
preProcessShow: {
|
||||
type: String,
|
||||
default: 'READ'
|
||||
},
|
||||
// approval 立项, execute 实施, 归档 archivist
|
||||
type: {
|
||||
type: String,
|
||||
@@ -154,6 +98,11 @@ const props = defineProps({
|
||||
type: Boolean,
|
||||
default: false
|
||||
},
|
||||
//是否开始打印
|
||||
isOpenPrint: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
},
|
||||
value: {
|
||||
type: String,
|
||||
default: ''
|
||||
@@ -164,6 +113,91 @@ const props = defineProps({
|
||||
}
|
||||
})
|
||||
const form = ref()
|
||||
const carbonCopyUserList = ref([])
|
||||
const carbonCopyUserRef = ref()
|
||||
|
||||
const editSingleTableConfig = reactive({
|
||||
columns: [
|
||||
{
|
||||
prop: 'index',
|
||||
type: 'index',
|
||||
label: '序号',
|
||||
align: 'center',
|
||||
width: 85,
|
||||
},
|
||||
{
|
||||
prop: 'originalFileName',
|
||||
label: '文件名',
|
||||
align: 'center',
|
||||
width: 400,
|
||||
currentRender: ({row, index}) => (
|
||||
<div style="color: #2a99ff;cursor: pointer;" onClick={() => clickToPreview(row)}>{row.originalFileName}</div>)
|
||||
},
|
||||
{
|
||||
prop: 'tag',
|
||||
label: '标签',
|
||||
align: 'center'
|
||||
},
|
||||
{
|
||||
prop: 'size',
|
||||
label: '文件大小',
|
||||
align: 'center',
|
||||
width: 150,
|
||||
currentRender: ({row, index}) => (parseInt(row.size / 1024) + 'KB')
|
||||
},
|
||||
{
|
||||
prop: 'oper',
|
||||
label: '操作',
|
||||
align: 'center',
|
||||
showOverflowTooltip: false,
|
||||
currentRender: ({row, index}) => {
|
||||
let btn = []
|
||||
btn.push({label: '下载', func: () => handleDownload(row), type: 'primary'})
|
||||
// if (row.newFile) {
|
||||
// btn.push({label: '删除', func: () => handleDelete(row), type: 'primary'})
|
||||
// }
|
||||
return (
|
||||
<div style={{width: '100%'}}>
|
||||
{
|
||||
btn.map(item => (
|
||||
<el-button
|
||||
type={item.type}
|
||||
onClick={() => item.func()}
|
||||
link>
|
||||
{item.label}
|
||||
</el-button>
|
||||
))
|
||||
}
|
||||
{
|
||||
row.newFile ? <popover-delete name={row.originalFileName} type={'文件'} btnType={'danger'}
|
||||
onDelete={() => handleDelete(row)}/>
|
||||
: ''
|
||||
}
|
||||
</div>
|
||||
)
|
||||
}
|
||||
}
|
||||
]
|
||||
})
|
||||
let preProcess = {
|
||||
label: '前置流程',
|
||||
prop: 'preProcess',
|
||||
colProps: {
|
||||
span: 24
|
||||
},
|
||||
labelWidth: 'left',
|
||||
component: () => (
|
||||
<div>
|
||||
{
|
||||
props.formData.preProcess ? props.formData.preProcess.map((item, index) => {
|
||||
return <span><a target="_blank" style={{color: '#409EFF', cursor: 'pointer'}}
|
||||
href={props.formData.preProcessBaseUrl + item.requestId}>{item.requestName} {index != (props.formData.preProcess.length - 1) ?
|
||||
<span>,</span> : ''}</a></span>
|
||||
}) : <span>{'--'}</span>
|
||||
}
|
||||
</div>
|
||||
)
|
||||
}
|
||||
const schema = computed(() => {
|
||||
let arr
|
||||
if (props.type == 'approval') {
|
||||
@@ -172,8 +206,9 @@ const schema = computed(() => {
|
||||
label: '项目负责人',
|
||||
prop: 'projectChargePerson',
|
||||
colProps: {
|
||||
span: 24
|
||||
span: 6
|
||||
},
|
||||
labelWidth: 'left',
|
||||
component: () => (
|
||||
<div>
|
||||
{
|
||||
@@ -188,156 +223,360 @@ const schema = computed(() => {
|
||||
label: '项目成员',
|
||||
prop: 'projectPersonList',
|
||||
colProps: {
|
||||
span: 24
|
||||
span: 6
|
||||
},
|
||||
labelWidth: 'left',
|
||||
component: () => (
|
||||
<div>
|
||||
{
|
||||
props.formData.projectPersonList ? props.formData.projectPersonList.map(item => {
|
||||
props.formData.projectPersonList ? props.formData.projectPersonList.map((item, index) => {
|
||||
return <span>{item.name}
|
||||
<span>{index != props.formData.projectPersonList?.length - 1 ? ',' : ''}</span></span>
|
||||
}) : <span>{'--'}</span>
|
||||
}
|
||||
</div>
|
||||
)
|
||||
},
|
||||
{
|
||||
label: '部门分管领导',
|
||||
prop: 'optionalChargeLeadership',
|
||||
colProps: {
|
||||
span: 6
|
||||
},
|
||||
labelWidth: 'left',
|
||||
component: () => (
|
||||
<div>
|
||||
{
|
||||
props.formData.optionalChargeLeadership?.length > 0 ? props.formData.optionalChargeLeadership.map(item => {
|
||||
return <span>{item.name} </span>
|
||||
}) : <span>{'--'}</span>
|
||||
}
|
||||
</div>
|
||||
)
|
||||
},
|
||||
{
|
||||
]
|
||||
if (props.preProcessShow == 'EDIT') {
|
||||
preProcess = {
|
||||
label: '前置流程',
|
||||
prop: 'preProcess',
|
||||
colProps: {
|
||||
span: 24
|
||||
},
|
||||
labelWidth: 'left',
|
||||
component: () => (
|
||||
<div>
|
||||
{
|
||||
props.formData.preProcess ? props.formData.preProcess.map(item => {
|
||||
return <span><a target="_blank" style={{color: '#409EFF', cursor: 'pointer'}}
|
||||
href={props.formData.preProcessBaseUrl + item.requestId}>{item.requestName}</a> </span>
|
||||
}) : <span>{'--'}</span>
|
||||
<select-pre-process formData={props.formData} basicData={props.basicData}/>
|
||||
}
|
||||
</div>
|
||||
)
|
||||
},
|
||||
{
|
||||
label: '项目立项附件',
|
||||
prop: 'singleFile',
|
||||
colProps: {
|
||||
span: 24
|
||||
},
|
||||
component: () => (
|
||||
<div>
|
||||
{
|
||||
props.formData.singleFile?.originalFileName ?
|
||||
<span
|
||||
style={{color: '#409EFF', cursor: 'pointer'}}
|
||||
onClick={() => handleDownload(props.formData.singleFile)}
|
||||
>
|
||||
{props.formData.singleFile?.originalFileName}
|
||||
</span> :
|
||||
<span>{'--'}</span>
|
||||
}
|
||||
</div>
|
||||
|
||||
)
|
||||
},
|
||||
]
|
||||
}
|
||||
}
|
||||
arr.push(preProcess)
|
||||
// arr.push({
|
||||
// label: '项目立项附件',
|
||||
// prop: 'singleFile',
|
||||
// colProps: {
|
||||
// span: 24
|
||||
// },
|
||||
// labelWidth: 'left',
|
||||
// component: () => {
|
||||
// let singleFileArray = [props.formData.singleFile]
|
||||
// return props.formData.singleFile ? <fvTable style="width: 100%;max-height: 80px;" height="80"
|
||||
// tableConfig={editSingleTableConfig}
|
||||
// data={singleFileArray} isSettingCol={false} pagination={false}>
|
||||
// </fvTable>
|
||||
// : <span>--</span>
|
||||
// }
|
||||
// })
|
||||
} else if (props.type == 'execute') {
|
||||
arr = [
|
||||
|
||||
{
|
||||
label: '实际专利(项)',
|
||||
prop: 'actualNewPatent',
|
||||
colProps: {
|
||||
span: 6
|
||||
},
|
||||
labelWidth: 'left',
|
||||
component: () => (
|
||||
<div>
|
||||
{
|
||||
props.formData.actualNewPatent ? props.formData.actualNewPatent :props.formData.actualNewPatent==0?0: <span>{'--'}</span>
|
||||
}
|
||||
</div>
|
||||
)
|
||||
},
|
||||
{
|
||||
label: '实际软件著作权(项)',
|
||||
prop: 'actualSoftwareCopyright',
|
||||
colProps: {
|
||||
span: 6
|
||||
},
|
||||
labelWidth: 'left',
|
||||
component: () => (
|
||||
<div>
|
||||
{
|
||||
props.formData.actualSoftwareCopyright ? props.formData.actualSoftwareCopyright : props.formData.actualSoftwareCopyright==0?0: <span>{'--'}</span>
|
||||
}
|
||||
</div>
|
||||
)
|
||||
},
|
||||
{
|
||||
label: '实际技术标准(项)',
|
||||
prop: 'actualTechnicalNorms',
|
||||
colProps: {
|
||||
span: 6
|
||||
},
|
||||
labelWidth: 'left',
|
||||
component: () => (
|
||||
<div>
|
||||
{
|
||||
props.formData.actualTechnicalNorms ? props.formData.actualTechnicalNorms : props.formData.actualTechnicalNorms==0?0:<span>{'--'}</span>
|
||||
}
|
||||
</div>
|
||||
)
|
||||
},
|
||||
{
|
||||
label: '实际新产品(项)',
|
||||
prop: 'actualNewProduct',
|
||||
colProps: {
|
||||
span: 6
|
||||
},
|
||||
labelWidth: 'left',
|
||||
component: () => (
|
||||
<div>
|
||||
{
|
||||
props.formData.actualNewProduct ? props.formData.actualNewProduct : props.formData.actualNewProduct==0?0:<span>{'--'}</span>
|
||||
}
|
||||
</div>
|
||||
)
|
||||
},
|
||||
{
|
||||
label: '实际新工艺(项)',
|
||||
prop: 'actualNewProcess',
|
||||
colProps: {
|
||||
span: 6
|
||||
},
|
||||
labelWidth: 'left',
|
||||
component: () => (
|
||||
<div>
|
||||
{
|
||||
props.formData.actualNewProcess ? props.formData.actualNewProcess : props.formData.actualNewProcess==0?0: <span>{'--'}</span>
|
||||
}
|
||||
</div>
|
||||
)
|
||||
},
|
||||
{
|
||||
label: '实际新装置(项)',
|
||||
prop: 'actualNewDevice',
|
||||
colProps: {
|
||||
span: 6
|
||||
},
|
||||
labelWidth: 'left',
|
||||
component: () => (
|
||||
<div>
|
||||
{
|
||||
props.formData.actualNewDevice ? props.formData.actualNewDevice :props.formData.actualNewDevice==0?0: <span>{'--'}</span>
|
||||
}
|
||||
</div>
|
||||
)
|
||||
},
|
||||
{
|
||||
label: '实际新材料(项)',
|
||||
prop: 'actualNewMaterials',
|
||||
colProps: {
|
||||
span: 6
|
||||
},
|
||||
labelWidth: 'left',
|
||||
component: () => (
|
||||
<div>
|
||||
{
|
||||
props.formData.actualNewMaterials ? props.formData.actualNewMaterials : props.formData.actualNewMaterials==0?0: <span>{'--'}</span>
|
||||
}
|
||||
</div>
|
||||
)
|
||||
},
|
||||
{
|
||||
label: '实际计算机软件(项)',
|
||||
prop: 'actualComputerSoftware',
|
||||
colProps: {
|
||||
span: 6
|
||||
},
|
||||
labelWidth: 'left',
|
||||
component: () => (
|
||||
<div>
|
||||
{
|
||||
props.formData.actualComputerSoftware ? props.formData.actualComputerSoftware : props.formData.actualComputerSoftware==0?0:<span>{'--'}</span>
|
||||
}
|
||||
</div>
|
||||
)
|
||||
},
|
||||
{
|
||||
label: '实际论文论著(项)',
|
||||
prop: 'actualThesis',
|
||||
colProps: {
|
||||
span: 6
|
||||
},
|
||||
labelWidth: 'left',
|
||||
component: () => (
|
||||
<div>
|
||||
{
|
||||
props.formData.actualThesis ? props.formData.actualThesis : props.formData.actualThesis==0?0:<span>{'--'}</span>
|
||||
}
|
||||
</div>
|
||||
)
|
||||
},
|
||||
{
|
||||
label: '实际研究报告(项)',
|
||||
prop: 'actualResearchReport',
|
||||
colProps: {
|
||||
span: 6
|
||||
},
|
||||
labelWidth: 'left',
|
||||
component: () => (
|
||||
<div>
|
||||
{
|
||||
props.formData.actualResearchReport ? props.formData.actualResearchReport : props.formData.actualResearchReport==0?0: <span>{'--'}</span>
|
||||
}
|
||||
</div>
|
||||
)
|
||||
},
|
||||
{
|
||||
label: '实际商标(项)',
|
||||
prop: 'actualTrademark',
|
||||
colProps: {
|
||||
span: 6
|
||||
},
|
||||
labelWidth: 'left',
|
||||
component: () => (
|
||||
<div>
|
||||
{
|
||||
props.formData.actualTrademark ? props.formData.actualTrademark :props.formData.actualTrademark==0?0: <span>{'--'}</span>
|
||||
}
|
||||
</div>
|
||||
)
|
||||
},
|
||||
{
|
||||
label: '实际其他(项)',
|
||||
prop: 'actualOther',
|
||||
colProps: {
|
||||
span: 24
|
||||
},
|
||||
labelWidth: 'left',
|
||||
component: () => (
|
||||
<div style="white-space: pre-wrap;">
|
||||
{
|
||||
props.formData.actualOther ? props.formData.actualOther : props.formData.actualOther==0?0: <span>{'--'}</span>
|
||||
}
|
||||
</div>
|
||||
)
|
||||
},
|
||||
|
||||
{
|
||||
label: '部门分管领导',
|
||||
prop: 'optionalChargeLeadership',
|
||||
colProps: {
|
||||
span: 24
|
||||
},
|
||||
labelWidth: 'left',
|
||||
component: () => (
|
||||
<div>
|
||||
{
|
||||
props.formData.optionalChargeLeadership?.length > 0 ? props.formData.optionalChargeLeadership.map(item => {
|
||||
return <span>{item.name} </span>
|
||||
}) : <span>{'--'}</span>
|
||||
}
|
||||
</div>
|
||||
)
|
||||
}
|
||||
]
|
||||
|
||||
if (props.preProcessShow == 'EDIT') {
|
||||
preProcess = {
|
||||
label: '前置流程',
|
||||
prop: 'preProcess',
|
||||
colProps: {
|
||||
span: 24
|
||||
},
|
||||
labelWidth: 'left',
|
||||
component: () => (
|
||||
<div>
|
||||
{
|
||||
props.formData.preProcess ? props.formData.preProcess.map(item => {
|
||||
return <span><a target="_blank" style={{color: '#409EFF', cursor: 'pointer'}}
|
||||
href={props.formData.preProcessBaseUrl + item.requestId}>{item.requestName}</a> </span>
|
||||
}) : <span>{'--'}</span>
|
||||
<select-pre-process formData={props.formData} basicData={props.basicData}/>
|
||||
}
|
||||
</div>
|
||||
)
|
||||
},
|
||||
{
|
||||
label: '项目验收附件',
|
||||
prop: 'singleFile',
|
||||
colProps: {
|
||||
span: 24
|
||||
},
|
||||
component: () => (
|
||||
<div>
|
||||
{
|
||||
props.formData.singleFile?.originalFileName ?
|
||||
<span
|
||||
style={{color: '#409EFF', cursor: 'pointer'}}
|
||||
onClick={() => handleDownload(props.formData.singleFile)}
|
||||
>
|
||||
{props.formData.singleFile?.originalFileName}
|
||||
</span> :
|
||||
<span>{'--'}</span>
|
||||
}
|
||||
</div>
|
||||
|
||||
)
|
||||
},
|
||||
]
|
||||
}
|
||||
}
|
||||
arr.push(preProcess)
|
||||
// arr.push(
|
||||
// {
|
||||
// label: '项目验收附件',
|
||||
// prop: 'singleFile',
|
||||
// colProps: {
|
||||
// span: 24
|
||||
// },
|
||||
// labelWidth: 'left',
|
||||
// component: () => {
|
||||
// let singleFileArray = [props.formData.singleFile]
|
||||
// return props.formData.singleFile ? <fvTable style="width: 100%;max-height: 80px;" height="80"
|
||||
// tableConfig={editSingleTableConfig}
|
||||
// data={singleFileArray} isSettingCol={false} pagination={false}>
|
||||
// </fvTable>
|
||||
// : <span>--</span>
|
||||
// }
|
||||
// })
|
||||
} else if (props.type == 'archivist') {
|
||||
arr = [
|
||||
{
|
||||
label: '项目归档附件',
|
||||
prop: 'singleFile',
|
||||
colProps: {
|
||||
span: 24
|
||||
},
|
||||
component: () => (
|
||||
<div>
|
||||
{
|
||||
props.formData.singleFile?.originalFileName ?
|
||||
<span
|
||||
style={{color: '#409EFF', cursor: 'pointer'}}
|
||||
onClick={() => handleDownload(props.formData.singleFile)}
|
||||
>
|
||||
{props.formData.singleFile?.originalFileName}
|
||||
</span> :
|
||||
<span>{'--'}</span>
|
||||
}
|
||||
</div>
|
||||
|
||||
)
|
||||
},
|
||||
// {
|
||||
// label: '项目归档附件',
|
||||
// prop: 'singleFile',
|
||||
// colProps: {
|
||||
// span: 24
|
||||
// },
|
||||
// labelWidth: 'left',
|
||||
// component: () => {
|
||||
// let singleFileArray = [props.formData.singleFile]
|
||||
// return props.formData.singleFile ? <fvTable style="width: 100%;max-height: 80px;" height="80"
|
||||
// tableConfig={editSingleTableConfig}
|
||||
// data={singleFileArray} isSettingCol={false} pagination={false}>
|
||||
// </fvTable>
|
||||
// : <span>--</span>
|
||||
// }
|
||||
// },
|
||||
]
|
||||
} else if (props.type == 'phase') {
|
||||
arr = [
|
||||
{
|
||||
label: '阶段变更附件',
|
||||
prop: 'singleFile',
|
||||
colProps: {
|
||||
span: 24
|
||||
},
|
||||
component: () => (
|
||||
<div>
|
||||
{
|
||||
props.formData.singleFile?.originalFileName ?
|
||||
<span
|
||||
style={{color: '#409EFF', cursor: 'pointer'}}
|
||||
onClick={() => handleDownload(props.formData.singleFile)}
|
||||
>
|
||||
{props.formData.singleFile?.originalFileName}
|
||||
</span> :
|
||||
<span>{'--'}</span>
|
||||
}
|
||||
</div>
|
||||
|
||||
)
|
||||
},
|
||||
// {
|
||||
// label: '阶段变更附件',
|
||||
// prop: 'singleFile',
|
||||
// colProps: {
|
||||
// span: 24
|
||||
// },
|
||||
// labelWidth: 'left',
|
||||
// component: () => {
|
||||
// let singleFileArray = [props.formData.singleFile]
|
||||
// return props.formData.singleFile ? <fvTable style="width: 100%;max-height: 80px;" height="80"
|
||||
// tableConfig={editSingleTableConfig}
|
||||
// data={singleFileArray} isSettingCol={false} pagination={false}>
|
||||
// </fvTable>
|
||||
// : <span>--</span>
|
||||
// }
|
||||
// },
|
||||
]
|
||||
}
|
||||
return arr
|
||||
})
|
||||
|
||||
const filePreviewParam = ref({
|
||||
fileUrl: '',
|
||||
fileName: '',
|
||||
fileType: ''
|
||||
})
|
||||
const filePreviewShow = ref(false)
|
||||
const route = useRoute()
|
||||
const emit = defineEmits(['update:value'])
|
||||
const emit = defineEmits(['update:value', 'ccSend'])
|
||||
const _value = computed({
|
||||
get() {
|
||||
return props.value;
|
||||
@@ -346,48 +585,49 @@ const _value = computed({
|
||||
emit("update:value", val);
|
||||
}
|
||||
})
|
||||
const getTagsOption = () => {
|
||||
if (!route.query.projectId) return
|
||||
getTags(route.query.projectId).then(res => {
|
||||
if (res.code === 1000) {
|
||||
tagsOption.value = res.data
|
||||
} else {
|
||||
ElNotification({
|
||||
title: '提示',
|
||||
message: res.msg,
|
||||
type: 'error'
|
||||
})
|
||||
}
|
||||
})
|
||||
const handleCarbonCopy = () => {
|
||||
carbonCopyUserRef.value.showUserPicker()
|
||||
}
|
||||
const handleSearchImplementationFileList = () => {
|
||||
let params = {
|
||||
targetId: route.query.projectId,
|
||||
targetState: "40"
|
||||
}
|
||||
if (attachmentParam.tag) {
|
||||
tagsOption.value.forEach(item => {
|
||||
if (item.value === attachmentParam.tag) {
|
||||
attachmentParam.tag = item.label
|
||||
}
|
||||
const carbonCopyUserPickerOk = (userList) => {
|
||||
carbonCopyUserList.value = userList.map(item => item.id)
|
||||
console.log('localFormData.value', props.data)
|
||||
console.log("🚀 ~ file:'carbonCopyUserList.value ", carbonCopyUserList.value)
|
||||
|
||||
addUser()
|
||||
}
|
||||
const addUser = async () => {
|
||||
const res = await applyCcSend({
|
||||
instanceId: props.data.processInstanceId,
|
||||
// message:props.data.remark,
|
||||
projectId: route.query.projectId,
|
||||
state: route.query.step,
|
||||
userIds: carbonCopyUserList.value
|
||||
})
|
||||
console.log('res', res)
|
||||
if (res.code === 1000) {
|
||||
ElNotification({
|
||||
title: '提示',
|
||||
message: '抄送成功',
|
||||
type: 'success'
|
||||
})
|
||||
emit('ccSend')
|
||||
} else {
|
||||
ElNotification({
|
||||
title: '提示',
|
||||
message: res.msg,
|
||||
type: 'error'
|
||||
})
|
||||
params.tag = attachmentParam.tag
|
||||
}
|
||||
searchImplementationFileList(params).then(res => {
|
||||
showAttachmentTable.value = false
|
||||
if (res.code === 1000) {
|
||||
otherAttachmentList.value = res.data.fileList
|
||||
uploadState.value = res.data.upload
|
||||
nextTick(() => {
|
||||
showAttachmentTable.value = true
|
||||
})
|
||||
} else {
|
||||
ElNotification({
|
||||
title: '提示',
|
||||
message: res.msg,
|
||||
type: 'error'
|
||||
})
|
||||
}
|
||||
}
|
||||
const clickToPreview = (row) => {
|
||||
filePreviewShow.value = false
|
||||
filePreviewParam.value = {
|
||||
fileUrl: row.url,
|
||||
fileName: row.originalFileName,
|
||||
fileType: row.fileType
|
||||
}
|
||||
nextTick(() => {
|
||||
filePreviewShow.value = true
|
||||
})
|
||||
}
|
||||
|
||||
@@ -425,22 +665,46 @@ watchEffect(() => {
|
||||
Object.keys(props.formData).length && (form.value?.setValues(props.formData))
|
||||
})
|
||||
|
||||
onMounted(() => {
|
||||
// if (props.formData.mode == 'view' && props.type == 'execute') {
|
||||
// handleSearchImplementationFileList()
|
||||
// getTagsOption()
|
||||
// }
|
||||
})
|
||||
|
||||
if (props.formData.mode == 'view' && props.type == 'execute') {
|
||||
handleSearchImplementationFileList()
|
||||
getTagsOption()
|
||||
}
|
||||
watch(() => props.loading, (newVal) => {
|
||||
props.loading = newVal
|
||||
}, {deep: true})
|
||||
</script>
|
||||
<style lang="scss">
|
||||
.execute-table {
|
||||
.el-table__header {
|
||||
.el-table__cell:last-child {
|
||||
.cell {
|
||||
margin-left: -160px !important;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.el-table__body {
|
||||
.el-table__cell:last-child {
|
||||
.cell {
|
||||
margin-left: -160px !important;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
<style lang="scss" scoped>
|
||||
|
||||
:deep(.el-table__header) {
|
||||
.is-leaf:first-child {
|
||||
.cell {
|
||||
margin-left: 10px !important;
|
||||
white-space: nowrap;
|
||||
padding: 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
:deep(.el-table__body) {
|
||||
.el-table__cell:first-child {
|
||||
.cell {
|
||||
margin-left: 5px !important;
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
<template>
|
||||
<div v-loading="loading">
|
||||
<div v-loading="loading" :style="type==='singleDetail'?'padding: 0 30px':''">
|
||||
<baseTitle title="需求征集信息" v-if="type!=='singleDetail'"></baseTitle>
|
||||
<el-form :model="formData">
|
||||
<el-row>
|
||||
<el-col :span="6" v-if="type==='singleDetail'">
|
||||
<el-form :model="formData" >
|
||||
<el-row gutter="20" style="margin-left: 5px">
|
||||
<el-col :span="6">
|
||||
<el-form-item label="征集名称">
|
||||
<span>{{ formData.requirementName }}</span>
|
||||
</el-form-item>
|
||||
@@ -33,23 +33,22 @@
|
||||
</div>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
|
||||
<el-col :span="24">
|
||||
<baseTitle title="征集说明"></baseTitle>
|
||||
<el-form-item>
|
||||
<el-card style="width: 100%">
|
||||
<div v-html="formData.collectExplain">
|
||||
</div>
|
||||
</el-card>
|
||||
<el-col :span="24" style="margin-bottom: -15px">
|
||||
<el-form-item label="征集说明">
|
||||
<div v-if="formData.collectExplain" v-html="formData.collectExplain" style="white-space: pre-wrap;">
|
||||
</div>
|
||||
<div v-else>--</div>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<baseTitle v-if="fileListShow === 'READ' || fileListShow === 'EDIT'" title="附件列表"></baseTitle>
|
||||
</el-row>
|
||||
<el-row>
|
||||
<el-col :span="24">
|
||||
<baseTitle v-if="fileListShow === 'READ' || fileListShow === 'EDIT'" title="附件文件" style="margin-bottom: 0"></baseTitle>
|
||||
<file-component title="" tag="需求征集"
|
||||
v-model:value="formData.fileList" :processViewer="processViewer"
|
||||
:file-list-show="fileListShow"/>
|
||||
</el-col>
|
||||
<el-col :span="24">
|
||||
<el-col :span="24" style="margin-top: -15px">
|
||||
<div v-if="data.taskId">
|
||||
<baseTitle title="审核意见"></baseTitle>
|
||||
<el-form-item prop="_value">
|
||||
@@ -63,7 +62,7 @@
|
||||
</div>
|
||||
</el-col>
|
||||
</el-row>
|
||||
<div class="approval-record">
|
||||
<div class="approval-record" style="margin-top: -15px">
|
||||
<div class="approval-title">
|
||||
<baseTitle title="审批记录"></baseTitle>
|
||||
<div class="diagram">
|
||||
@@ -191,4 +190,19 @@ watch(() => props.processViewer, (newVal) => {
|
||||
display: -webkit-box;
|
||||
-webkit-box-orient: vertical;
|
||||
}
|
||||
:deep(.el-table__header) {
|
||||
.is-leaf:first-child {
|
||||
.cell {
|
||||
margin-left: -53px !important;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
:deep(.el-table__body) {
|
||||
.el-table__cell:first-child {
|
||||
.cell {
|
||||
margin-left: -26px !important;
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
<template>
|
||||
<el-dialog custom-class="custom-dialog" class="border" :border="false" width="1000px" style="height: 676px"
|
||||
:title="title" :show-close="false" :visible.sync="visible" v-model="visible" append-to-body :close-on-click-modal="true" @close="closeDialog">
|
||||
:title="title" :show-close="false" :visible.sync="visible" v-model="visible" append-to-body :close-on-click-modal="false" @close="closeDialog">
|
||||
<div class="picker">
|
||||
<div class="candidate" v-loading="loading">
|
||||
<el-input v-model="filterText"
|
||||
@@ -17,8 +17,8 @@
|
||||
<el-tree :data="dataList" ref="tree" :props="defaultProps" empty-text="" node-key="value"
|
||||
:show-checkbox="showCheckbox" highlight-current default-expand-all
|
||||
:default-checked-keys="defaultChecked" :disabled="disabled"
|
||||
:check-strictly="!checkStrictly" @node-click="(node,check)=>handle(node,check)"
|
||||
@check-change="handleChange" :filter-node-method="filterNode">
|
||||
:check-strictly="!checkStrictly" @node-click="(node,check)=>handleNodeClick(node,check)"
|
||||
@check-change="handleCheckClick" :filter-node-method="filterNode">
|
||||
<template #default="{ node, data }">
|
||||
<div class="tree-node">
|
||||
<div style="display: flex;align-items: center;padding: 3px 0">
|
||||
@@ -39,7 +39,7 @@
|
||||
<el-empty :image-size="100" description="请点击左侧列表选择数据" v-show="selectList.length === 0"/>
|
||||
<div v-for="(selectItem, selectIndex) in selectList" :key="selectIndex" class="org-item">
|
||||
{{ selectItem.label }}
|
||||
<el-icon @click="noSelected(selectItem)" size="20" style="margin-left: 10px;cursor: pointer;">
|
||||
<el-icon @click="removeSingleSelected(selectItem)" size="20" style="margin-left: 10px;cursor: pointer;">
|
||||
<CircleClose/>
|
||||
</el-icon>
|
||||
</div>
|
||||
@@ -47,7 +47,7 @@
|
||||
</div>
|
||||
</div>
|
||||
<div class="footer">
|
||||
<el-button size="mini" @click="visible = false">取 消</el-button>
|
||||
<el-button size="mini" @click="cancelUserPicker">取 消</el-button>
|
||||
<el-button size="mini" color="#DED0B2" @click="selectConfirm">确 定</el-button>
|
||||
</div>
|
||||
</el-dialog>
|
||||
@@ -105,6 +105,8 @@ const defaultProps = {
|
||||
children: "children",
|
||||
disabled: "disabled",
|
||||
};
|
||||
|
||||
const isRemoveSingleSelected = ref(false);
|
||||
const emit = defineEmits(['update:modelValue'])
|
||||
const _value = computed({
|
||||
get() {
|
||||
@@ -175,7 +177,7 @@ const updateTreeCheck = (list, flag) => {
|
||||
}
|
||||
})
|
||||
}
|
||||
const handleChange = (data, checked) => {
|
||||
const handleCheckClick = (data, checked) => {
|
||||
if (data.value == -1) {
|
||||
if(checked){
|
||||
updateTreeCheck(dataList.value, false)
|
||||
@@ -219,7 +221,7 @@ const handleChange = (data, checked) => {
|
||||
}
|
||||
}
|
||||
};
|
||||
const handle = (node, check) => {
|
||||
const handleNodeClick = (node, check) => {
|
||||
if (check.isLeaf !== false) {
|
||||
if (props.multiple) {
|
||||
//不添加重复的数据到右边
|
||||
@@ -238,7 +240,7 @@ const handle = (node, check) => {
|
||||
}
|
||||
// _value.value = selectList.value
|
||||
};
|
||||
const noSelected = (selectItem) => {
|
||||
const removeSingleSelected = (selectItem) => {
|
||||
//左侧无选择框时,右侧显示×
|
||||
for (let i = 0; i < selectList.value.length; i++) {
|
||||
if (selectList.value[i].value === selectItem.value) {
|
||||
@@ -253,6 +255,7 @@ const noSelected = (selectItem) => {
|
||||
tree.value.setCheckedKeys([]);
|
||||
}
|
||||
}
|
||||
// isRemoveSingleSelected.value = true
|
||||
};
|
||||
const clearSelected = () => {
|
||||
//清空
|
||||
@@ -261,18 +264,33 @@ const clearSelected = () => {
|
||||
cancelButtonText: "取消",
|
||||
type: "warning"
|
||||
}).then(() => {
|
||||
// isRemoveSingleSelected.value = true
|
||||
if (!props.showCheckbox) {
|
||||
selectList.value = [];
|
||||
} else {
|
||||
handleChange("1");
|
||||
handleCheckClick("1");
|
||||
}
|
||||
});
|
||||
};
|
||||
const cancelUserPicker = () => {
|
||||
if (localStorage.getItem('originallyCompanySelectedList')) {
|
||||
selectList.value = JSON.parse(localStorage.getItem('originallyCompanySelectedList'))
|
||||
}else{
|
||||
selectList.value=[]
|
||||
handleCheckClick("1");
|
||||
}
|
||||
emit("cancelOrClear", selectList.value);
|
||||
visible.value = false;
|
||||
// nextTick(()=>{
|
||||
// isRemoveSingleSelected.value=false
|
||||
// })
|
||||
}
|
||||
const selectConfirm = () => {
|
||||
//确定按钮
|
||||
emit("ok", selectList.value);
|
||||
dataList.value = []
|
||||
visible.value = false;
|
||||
localStorage.setItem('originallyCompanySelectedList', JSON.stringify(selectList.value))
|
||||
};
|
||||
defineExpose({
|
||||
show
|
||||
|
||||
@@ -1,8 +1,9 @@
|
||||
<template>
|
||||
<el-form :label-position="labelAlign">
|
||||
<el-form-item :label="title?'其他文件':''" v-if="fileListShow === 'READ' || fileListShow === 'EDIT'" :label-position="labelAlign" :label-width="title?95:''">
|
||||
<el-form-item :label="title" v-if="fileListShow === 'READ' || fileListShow === 'EDIT'" :label-position="labelAlign" :style="{marginTop: '10px',marginLeft: tag!=='需求上报'?'15px':'0'}">
|
||||
<file-upload @getFile="getOtherFile" v-if="fileListShow === 'EDIT'"/>
|
||||
<fvTable style="width: 100%;max-height: 162px;" v-if="processViewer" height="162" :tableConfig="tableConfig"
|
||||
<!-- :style="{width:isOpenPrint?'610px': '100%'}" table-layout="auto" id="printTable"-->
|
||||
<fvTable style="width:100%;" :height="tag=='项目立项'?'160':'160'" :style="{maxHeight:tag=='项目立项'?'160px':'160px',height:tag=='项目立项'?'160px':'160px'}" v-if="processViewer" :scrollbar-always-on="true" :tableConfig="tableConfig"
|
||||
:data="_value" :isSettingCol="false" :pagination="false">
|
||||
<template #empty>
|
||||
<el-empty :image-size="55" description="暂无数据" style="padding: 0"/>
|
||||
@@ -10,11 +11,14 @@
|
||||
</fvTable>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
<file-preview ref="filePreviewRef" :fullscreen="fullscreen" v-if="filePreviewShow" :fileName="filePreviewParam.fileName" :fileUrl="filePreviewParam.fileUrl"
|
||||
:fileType="filePreviewParam.fileType"/>
|
||||
</template>
|
||||
|
||||
<script setup lang="jsx">
|
||||
import {downloadFile, deleteFile} from "@/api/project-demand";
|
||||
import {ElNotification} from "element-plus";
|
||||
import FilePreview from "../filePreview/index.vue";
|
||||
|
||||
const props = defineProps({
|
||||
title: {
|
||||
@@ -25,6 +29,10 @@ const props = defineProps({
|
||||
type: String,
|
||||
default: ''
|
||||
},
|
||||
fileNameTableWidth: {
|
||||
type: String,
|
||||
default: '400'
|
||||
},
|
||||
fileListShow: {
|
||||
type: String,
|
||||
default: 'READ'
|
||||
@@ -40,7 +48,17 @@ const props = defineProps({
|
||||
labelAlign: {
|
||||
type: String,
|
||||
default: 'right'
|
||||
}
|
||||
},
|
||||
//弹窗是否铺满全屏
|
||||
fullscreen: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
},
|
||||
//是否开始打印
|
||||
isOpenPrint: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
},
|
||||
})
|
||||
const emit = defineEmits(['update:value'])
|
||||
const tableConfig = reactive({
|
||||
@@ -56,11 +74,16 @@ const tableConfig = reactive({
|
||||
prop: 'originalFileName',
|
||||
label: '文件名',
|
||||
align: 'center',
|
||||
width: props.fileNameTableWidth,
|
||||
showOverflowTooltip: false,
|
||||
currentRender: ({row, index}) => (<div style="color: #2a99ff;cursor: pointer;" onClick={()=>clickToPreview(row)}>{row.originalFileName}</div>)
|
||||
},
|
||||
{
|
||||
prop: 'tag',
|
||||
label: '标签',
|
||||
align: 'center'
|
||||
align: 'center',
|
||||
showOverflowTooltip: false,
|
||||
minWidth: props.fileNameTableWidth,
|
||||
},
|
||||
{
|
||||
prop: 'size',
|
||||
@@ -94,7 +117,6 @@ const tableConfig = reactive({
|
||||
}
|
||||
{
|
||||
row.newFile ? <popover-delete name={row.originalFileName} type={'文件'} btnType={'danger'}
|
||||
perm={['mosr:requirement:del']}
|
||||
onDelete={() => handleDelete(row)}/>
|
||||
: ''
|
||||
}
|
||||
@@ -104,7 +126,12 @@ const tableConfig = reactive({
|
||||
}
|
||||
]
|
||||
})
|
||||
|
||||
const filePreviewParam = ref({
|
||||
fileUrl: '',
|
||||
fileName: '',
|
||||
fileType: 'pdf'
|
||||
})
|
||||
const filePreviewShow = ref(false)
|
||||
const _value = computed({
|
||||
get() {
|
||||
return props.value;
|
||||
@@ -113,7 +140,17 @@ const _value = computed({
|
||||
emit("update:value", val);
|
||||
}
|
||||
})
|
||||
|
||||
const clickToPreview=(row)=>{
|
||||
filePreviewShow.value = false
|
||||
filePreviewParam.value = {
|
||||
fileUrl: row.url,
|
||||
fileName: row.originalFileName,
|
||||
fileType: row.fileType
|
||||
}
|
||||
nextTick(()=>{
|
||||
filePreviewShow.value = true
|
||||
})
|
||||
}
|
||||
const getOtherFile = (val) => {
|
||||
props.processViewer = false
|
||||
let fileObj = compositeParam(val)
|
||||
@@ -164,6 +201,12 @@ watch(() => props.processViewer, (newVal) => {
|
||||
|
||||
<style scoped lang="scss">
|
||||
:deep(.el-table--fit ) {
|
||||
height: 162px !important;
|
||||
height: 160px !important;
|
||||
}
|
||||
@media print {
|
||||
//#printTable{
|
||||
// width: 400px!important;
|
||||
//}
|
||||
|
||||
}
|
||||
</style>
|
||||
|
||||
@@ -1,10 +1,54 @@
|
||||
<template>
|
||||
<!-- <baseTitle title="审核意见"></baseTitle>-->
|
||||
<!-- <fvForm :schema="schema" @getInstance="(e)=>form = e"></fvForm>-->
|
||||
<div class="oper-page-btn">
|
||||
<div class="oper-page-btn" style="display: flex">
|
||||
<el-button type="danger" @click="handleReject">驳回</el-button>
|
||||
<el-button color="#DED0B2" @click="handleAgree">同意</el-button>
|
||||
</div>
|
||||
<div class="opinion-dialog">
|
||||
<el-dialog v-model="showBackNode" title="请选择退回节点" width="400">
|
||||
<el-table :data="taskUserOptionList" style="width: 100%"
|
||||
:header-cell-style="{background:'#f5f7fa'}">
|
||||
<el-table-column width="55">
|
||||
<template #default="scope">
|
||||
<el-radio
|
||||
class="radio"
|
||||
:label="scope.row"
|
||||
v-model="backNode"
|
||||
>   
|
||||
</el-radio>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column
|
||||
prop="nodeName"
|
||||
label="节点名称">
|
||||
<!-- <template #default="scope">-->
|
||||
<!-- {{scope.row.nodeId==-1?'发起节点':scope.row.nodeName}}-->
|
||||
<!-- </template>-->
|
||||
</el-table-column>
|
||||
<el-table-column
|
||||
prop="name"
|
||||
label="操作者">
|
||||
<template #default="scope">
|
||||
<el-tag v-if="scope.row.userInfo" type="success">{{ scope.row.userInfo.name }}</el-tag>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
<div class="oper" style="display: flex;justify-content: flex-end;margin-top: 10px">
|
||||
<el-button type="danger" @click="rollbackHandler">确定</el-button>
|
||||
<el-button @click="showBackNode=false">取消</el-button>
|
||||
</div>
|
||||
<!-- <el-select v-if="taskUserOptionList?.length>0" v-model="backNode" placeholder="请选择退回节点" clearable>-->
|
||||
<!-- <el-option-->
|
||||
<!-- v-for="item in taskUserOptionList"-->
|
||||
<!-- :key="item.nodeId"-->
|
||||
<!-- :label="item.nodeName + (item.userInfo ? ':' + item.userInfo.name : '')"-->
|
||||
<!-- :value="item.nodeId">-->
|
||||
<!-- </el-option>-->
|
||||
<!-- </el-select>-->
|
||||
<!-- <el-button type="danger" @click="rollbackHandler">确认</el-button>-->
|
||||
</el-dialog>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup lang="jsx">
|
||||
@@ -27,10 +71,17 @@ const props = defineProps({
|
||||
value: {
|
||||
type: String,
|
||||
default: ''
|
||||
},
|
||||
//退回节点选择框数据
|
||||
taskUserOptionList: {
|
||||
type: Array,
|
||||
default: []
|
||||
}
|
||||
})
|
||||
|
||||
const form = ref()
|
||||
const backNode = ref({})
|
||||
const showBackNode = ref(false)
|
||||
const schema = computed(() => {
|
||||
return [
|
||||
{
|
||||
@@ -81,13 +132,13 @@ const back = () => {
|
||||
}
|
||||
}
|
||||
break;
|
||||
case 'Summary/detail':
|
||||
if (route.query.source === 'home') {
|
||||
router.push('/home')
|
||||
} else {
|
||||
router.push({name: 'Summary'})
|
||||
}
|
||||
break;
|
||||
// case 'Summary/detail':
|
||||
// if (route.query.source === 'home') {
|
||||
// router.push('/home')
|
||||
// } else {
|
||||
// router.push({name: 'Summary'})
|
||||
// }
|
||||
// break;
|
||||
case 'Requirement/detail':
|
||||
if (route.query.source === 'home') {
|
||||
router.push('/home')
|
||||
@@ -120,19 +171,26 @@ const back = () => {
|
||||
}
|
||||
// 驳回
|
||||
const handleReject = async () => {
|
||||
// const values = form.value.getValues()
|
||||
if (!_value.value) {
|
||||
ElNotification({
|
||||
title: '提示',
|
||||
message: '请填写审核意见',
|
||||
type: 'warning'
|
||||
})
|
||||
return
|
||||
}
|
||||
ElNotification({
|
||||
title: '提示',
|
||||
message: '请填写审核意见',
|
||||
type: 'warning'
|
||||
})
|
||||
return
|
||||
}
|
||||
showBackNode.value = true
|
||||
backNode.value = {}
|
||||
}
|
||||
//回退节点
|
||||
const rollbackHandler = async () => {
|
||||
// const values = form.value.getValues()
|
||||
|
||||
const params = {
|
||||
taskId: props.taskId,
|
||||
// ...values
|
||||
auditOpinion: _value.value
|
||||
auditOpinion: _value.value,
|
||||
rollBackId: backNode.value.nodeId
|
||||
}
|
||||
// console.log('params', params)
|
||||
const res = await rejectTask(params)
|
||||
@@ -141,11 +199,21 @@ const handleReject = async () => {
|
||||
message: res.msg,
|
||||
type: res.code === 1000 ? 'success' : 'error'
|
||||
})
|
||||
tagsViewStore.delVisitedViews(router.currentRoute.value.path)
|
||||
back()
|
||||
if (res.code === 1000) {
|
||||
tagsViewStore.delVisitedViews(router.currentRoute.value.path)
|
||||
back()
|
||||
}
|
||||
}
|
||||
|
||||
const handleAgree = async () => {
|
||||
if (!_value.value) {
|
||||
ElNotification({
|
||||
title: '提示',
|
||||
message: '请填写审核意见',
|
||||
type: 'warning'
|
||||
})
|
||||
return
|
||||
}
|
||||
// const values = form.value.getValues()
|
||||
const params = {
|
||||
taskId: props.taskId,
|
||||
@@ -158,11 +226,17 @@ const handleAgree = async () => {
|
||||
message: res.msg,
|
||||
type: res.code === 1000 ? 'success' : 'error'
|
||||
})
|
||||
tagsViewStore.delVisitedViews(router.currentRoute.value.path)
|
||||
back()
|
||||
if (res.code === 1000) {
|
||||
tagsViewStore.delVisitedViews(router.currentRoute.value.path)
|
||||
back()
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
|
||||
<style lang="scss">
|
||||
.opinion-dialog {
|
||||
.el-dialog__body {
|
||||
padding: 0 !important;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
||||
608
src/components/DetailComponent/ProjectAttachment.vue
Normal file
@@ -0,0 +1,608 @@
|
||||
<template>
|
||||
<el-row>
|
||||
<el-col :span="24">
|
||||
<baseTitle :title="'项目附件'"></baseTitle>
|
||||
</el-col>
|
||||
<el-tabs v-model="activeName" class="demo-tabs" @tab-click="handleTabClick" @tab-remove="tabRemove"
|
||||
style="margin-left: 15px;margin-top: -10px">
|
||||
<el-tab-pane name="all" :closable="false" label="全部">
|
||||
</el-tab-pane>
|
||||
<el-tab-pane v-for="item in tagsOption" :closable="item.isClose==1&&uploadState"
|
||||
:key="item.tagId"
|
||||
:label="item.fileTag"
|
||||
:name="item.tagId">
|
||||
<div class="tag-title">
|
||||
<div></div>
|
||||
{{ item.fileTag }}
|
||||
</div>
|
||||
</el-tab-pane>
|
||||
|
||||
<el-tab-pane name="plus" v-if="uploadState" :closable="false">
|
||||
<template #label>
|
||||
<div style="margin-top: 4px;">
|
||||
<el-icon color="#BEA266">
|
||||
<Plus/>
|
||||
</el-icon>
|
||||
</div>
|
||||
</template>
|
||||
</el-tab-pane>
|
||||
</el-tabs>
|
||||
</el-row>
|
||||
<div style="margin-top:10px;margin-bottom: 8px;margin-left: 15px;display: flex">
|
||||
<!-- <el-button color="#DED0B2" @click="handleUpload">上传附件</el-button>-->
|
||||
<file-upload v-if="!isLineBtn&&uploadState&&activeName!='plus'&&activeName!='all'" @getFile="getFile"/>
|
||||
|
||||
<el-button color="#DED0B2" @click="handleEditTag"
|
||||
v-if="activeName!='all'&&activeName!='plus'&&uploadState&&!isDefault"
|
||||
style="margin-left: 10px;">编辑
|
||||
</el-button>
|
||||
</div>
|
||||
<fvTable style="width: 100%;min-height:311px;max-height: 311px" v-if="showAttachmentTable" height="311"
|
||||
:scrollbar-always-on="true"
|
||||
:tableConfig="executeTableConfig" class="execute-apply-table"
|
||||
:data="otherAttachmentList" :isSettingCol="false" :pagination="false">
|
||||
<template #empty>
|
||||
<el-empty :image-size="90" description="暂无数据" style="padding: 0"/>
|
||||
</template>
|
||||
</fvTable>
|
||||
<div class="oper-page-btn" style="margin-right: 90px" v-if="uploadState">
|
||||
<el-button color="#DED0B2" @click="handleSubmit()">提交</el-button>
|
||||
</div>
|
||||
|
||||
<file-preview ref="filePreviewRef" :fullscreen="false" v-if="filePreviewShow" :fileName="filePreviewParam.fileName"
|
||||
:fileUrl="filePreviewParam.fileUrl"
|
||||
:fileType="filePreviewParam.fileType"/>
|
||||
<el-dialog v-model="tagNameShow" center width="450" top="40vh">
|
||||
<div style="display: flex;align-items: center">标签:
|
||||
<el-input v-model="fileParam.tagName" placeholder="请输入标签名称" style="width: 335px;" clearable/>
|
||||
</div>
|
||||
|
||||
<div class="oper" style="display: flex;justify-content: flex-end;margin-top: 10px">
|
||||
<el-button color="#DED0B2" @click="changeTag()">确定</el-button>
|
||||
<el-button @click="tagNameShow=false">取消</el-button>
|
||||
</div>
|
||||
</el-dialog>
|
||||
</template>
|
||||
|
||||
<script setup lang="jsx">
|
||||
import {addTag, delTag, getTagList, updateTag} from "@/api/project-manage";
|
||||
import {ElLoading, ElMessageBox, ElNotification} from "element-plus";
|
||||
import {searchImplementationFileList, uploadFileList} from "@/api/project-manage/attachment";
|
||||
import {deleteFile, downloadFile} from "@/api/project-demand";
|
||||
import {nextTick, onActivated} from "vue";
|
||||
|
||||
const router = useRouter()
|
||||
const route = useRoute()
|
||||
const attachmentParam = reactive({
|
||||
tag: ''
|
||||
})
|
||||
const fileParam = ref({
|
||||
tagName: ''
|
||||
})
|
||||
const uploadState = ref(false)
|
||||
const tagNameShow = ref(false)
|
||||
const isDefault = ref(false)
|
||||
const tagsOption = ref([])
|
||||
const fileList = ref([])
|
||||
const allFiles = ref([])
|
||||
const showAttachmentTable = ref(true)
|
||||
const activeName = ref('all')
|
||||
|
||||
const props = defineProps({
|
||||
fileNameTableWidth: {
|
||||
type: String,
|
||||
default: '400'
|
||||
},
|
||||
isLineBtn: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
},
|
||||
})
|
||||
const executeTableConfig = reactive({
|
||||
columns: [
|
||||
{
|
||||
prop: 'index',
|
||||
type: 'index',
|
||||
label: '序号',
|
||||
align: 'center',
|
||||
width: 85,
|
||||
},
|
||||
{
|
||||
prop: 'originalFileName',
|
||||
label: '文件名',
|
||||
align: 'center',
|
||||
width: props.fileNameTableWidth,
|
||||
showOverflowTooltip: false,
|
||||
currentRender: ({row, index}) => (
|
||||
<div style="color: #2a99ff;cursor: pointer;" onClick={() => clickToPreview(row)}>{row.originalFileName}</div>)
|
||||
},
|
||||
{
|
||||
prop: 'tag',
|
||||
label: '标签',
|
||||
align: 'center',
|
||||
showOverflowTooltip: false,
|
||||
},
|
||||
{
|
||||
prop: 'size',
|
||||
label: '文件大小',
|
||||
align: 'center',
|
||||
currentRender: ({row, index}) => (parseInt(row.size / 1024) + 'KB')
|
||||
},
|
||||
{
|
||||
prop: 'oper',
|
||||
label: '操作',
|
||||
align: 'center',
|
||||
showOverflowTooltip: false,
|
||||
currentRender: ({row, index}) => {
|
||||
return (
|
||||
<div>
|
||||
<el-button type="primary" link onClick={() => handleDownload(row)}>下载</el-button>
|
||||
{
|
||||
uploadState.value ?
|
||||
<popover-delete name={row.originalFileName} type={'文件'} btnType={'danger'}
|
||||
onDelete={() => deleteSingleFile(row)}/> : ''
|
||||
}
|
||||
</div>
|
||||
)
|
||||
}
|
||||
}
|
||||
]
|
||||
})
|
||||
// row.newFile ?: ''
|
||||
const otherAttachmentList = ref([])
|
||||
|
||||
const filePreviewParam = ref({
|
||||
fileUrl: '',
|
||||
fileName: '',
|
||||
fileType: 'pdf'
|
||||
})
|
||||
const filePreviewShow = ref(false)
|
||||
const uploadLoading = ref(false)
|
||||
const isEdit = ref(false)
|
||||
const isCloseByList = (index) => {
|
||||
// otherAttachmentList.length>0?false:true
|
||||
return otherAttachmentList.value.length == 0;
|
||||
}
|
||||
const handleDownload = (row) => {
|
||||
downloadFile(row.fileId).then(res => {
|
||||
const blob = new Blob([res])
|
||||
let a = document.createElement('a')
|
||||
a.href = URL.createObjectURL(blob)
|
||||
a.download = row.originalFileName
|
||||
a.click()
|
||||
})
|
||||
}
|
||||
const deleteSingleFile = (row) => {
|
||||
console.log("🚀 ~ file: ", row)
|
||||
deleteFile(row.fileId).then(res => {
|
||||
ElNotification({
|
||||
title: '提示',
|
||||
message: res.msg,
|
||||
type: res.code === 1000 ? 'success' : 'error'
|
||||
})
|
||||
if (res.code === 1000) {
|
||||
if (row.newFile) {
|
||||
const finalList = getLocalList().filter(item => item.fileId !== row.fileId);
|
||||
localStorage.setItem(`implementAllFileList-${route.query.projectId}`, JSON.stringify(finalList))
|
||||
} else {
|
||||
otherAttachmentList.value.splice(otherAttachmentList.value.findIndex((item) => item.fileId === row.fileId), 1);
|
||||
}
|
||||
|
||||
getAttachmentList()
|
||||
activeName.value = 'all'
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
const changeTag = async () => {
|
||||
let res = null
|
||||
if (isEdit.value) {
|
||||
res = await updateTag({
|
||||
tagId: activeName.value,
|
||||
fileTag: fileParam.value.tagName,
|
||||
projectId: route.query.projectId,
|
||||
})
|
||||
changeFileList(fileParam.value.tagName, true)
|
||||
} else {
|
||||
res = await addTag({
|
||||
projectId: route.query.projectId,
|
||||
fileTag: fileParam.value.tagName
|
||||
})
|
||||
|
||||
getAttachmentList()
|
||||
fileParam.value.tagName = ''
|
||||
activeName.value = 'all'
|
||||
}
|
||||
ElNotification({
|
||||
title: '提示',
|
||||
message: res.msg,
|
||||
type: res.code === 1000 ? 'success' : 'error'
|
||||
})
|
||||
tagNameShow.value = false;
|
||||
}
|
||||
const tabRemove = async (val) => {
|
||||
if (otherAttachmentList.value && otherAttachmentList.value.length > 0) {
|
||||
ElNotification({
|
||||
title: '提示',
|
||||
message: '该标签下存在文件,不能删除标签。如需删除标签,请先删除该标签下的所有文件。',
|
||||
type: 'error'
|
||||
})
|
||||
return;
|
||||
}
|
||||
ElMessageBox.confirm(`确认删除名称为${getTagName(val)}的标签吗?`, '系统提示', {
|
||||
confirmButtonText: '确定',
|
||||
cancelButtonText: '取消',
|
||||
type: 'warning'
|
||||
}).then(async () => {
|
||||
let res = await delTag(val)
|
||||
ElNotification({
|
||||
title: '提示',
|
||||
message: res.msg,
|
||||
type: res.code === 1000 ? 'success' : 'error'
|
||||
})
|
||||
if (res.code === 1000) {
|
||||
getTagsOption()
|
||||
otherAttachmentList.value = allFiles.value
|
||||
}
|
||||
})
|
||||
}
|
||||
const handleEditTag = () => {
|
||||
fileParam.value.tagName = getTagName(activeName.value)
|
||||
if (otherAttachmentList.value && otherAttachmentList.value.length > 0) {
|
||||
ElNotification({
|
||||
title: '提示',
|
||||
message: '该标签下存在文件,不能编辑标签。如需编辑标签,请先删除该标签下的所有文件。',
|
||||
type: 'error'
|
||||
})
|
||||
return;
|
||||
}
|
||||
tagNameShow.value = true
|
||||
isEdit.value = true
|
||||
}
|
||||
const getTagName = (name) => {
|
||||
const tagArray = tagsOption.value.filter((item1) => item1.tagId == name)
|
||||
let tagName = ''
|
||||
if (tagArray && tagArray.length > 0) {
|
||||
tagName = tagArray[0].fileTag
|
||||
}
|
||||
return tagName
|
||||
}
|
||||
const handleTabClick = (item, e) => {
|
||||
const defaultArray = tagsOption.value.filter(item1 => item1.tagId == item.props.name)
|
||||
if (defaultArray && defaultArray.length > 0) {
|
||||
isDefault.value = defaultArray[0].isDefault == 1
|
||||
} else {
|
||||
isDefault.value = false
|
||||
}
|
||||
tagNameShow.value = item.props.name == 'plus';
|
||||
if (item.props.name == 'plus') {
|
||||
isEdit.value = false
|
||||
fileParam.value.tagName = ''
|
||||
}
|
||||
if (item.props.name != 'plus') {
|
||||
if (item.props.name == 'all') {
|
||||
changeFileList('all')
|
||||
} else {
|
||||
changeFileList(getTagName(item.props.name))
|
||||
}
|
||||
// if (item.props.name == 'all') {
|
||||
// otherAttachmentList.value = allFiles.value
|
||||
// } else {
|
||||
// otherAttachmentList.value = allFiles.value.filter(item1 => item1.tag == getTagName(item.props.name))
|
||||
// }
|
||||
}
|
||||
// showAttachmentTable.value = false
|
||||
// nextTick(() => {
|
||||
// showAttachmentTable.value = true
|
||||
// })
|
||||
}
|
||||
const compositeParam = (item) => {
|
||||
return {
|
||||
fileId: item.id,
|
||||
size: item.size,
|
||||
originalFileName: item.originalFilename,
|
||||
fileType: item.fileType,
|
||||
url: item.url,
|
||||
newFile: true,
|
||||
tag: getTagName(activeName.value) || '项目实施',
|
||||
}
|
||||
}
|
||||
const getFile = (val) => {
|
||||
|
||||
console.log('上传文件', val)
|
||||
fileList.value = getLocalList()
|
||||
let fileObj = compositeParam(val)
|
||||
fileList.value.push(fileObj)
|
||||
localStorage.setItem(`implementAllFileList-${route.query.projectId}`, JSON.stringify(fileList.value))
|
||||
otherAttachmentList.value.push(fileObj)
|
||||
// handleSubmit([fileObj])
|
||||
}
|
||||
|
||||
const handleSubmit = async () => {
|
||||
if (getLocalList().length == 0) {
|
||||
ElNotification({
|
||||
title: '提示',
|
||||
message: '暂无文件可提交',
|
||||
type: 'warning'
|
||||
})
|
||||
return;
|
||||
} else {
|
||||
let params = {
|
||||
fileList: getLocalList(),
|
||||
projectId: route.query.projectId,
|
||||
targetState: "30"
|
||||
}
|
||||
let res = await uploadFileList(params)
|
||||
if (res.code !== 1000) {
|
||||
ElNotification({
|
||||
title: '提示',
|
||||
message: res.msg,
|
||||
type: 'error'
|
||||
})
|
||||
} else {
|
||||
ElNotification({
|
||||
title: '提示',
|
||||
message: res.msg,
|
||||
type: 'success'
|
||||
})
|
||||
localStorage.removeItem(`implementAllFileList-${route.query.projectId}`)
|
||||
// list.forEach(item => {
|
||||
// otherAttachmentList.value.push(item)
|
||||
// })
|
||||
getAttachmentList()
|
||||
fileList.value = []
|
||||
}
|
||||
// changeFileList('all',true)
|
||||
}
|
||||
}
|
||||
const clickToPreview = (row) => {
|
||||
filePreviewShow.value = false
|
||||
filePreviewParam.value = {
|
||||
fileUrl: row.url,
|
||||
fileName: row.originalFileName,
|
||||
fileType: row.fileType
|
||||
}
|
||||
nextTick(() => {
|
||||
filePreviewShow.value = true
|
||||
})
|
||||
}
|
||||
const changeFileList = (tag, flag) => {
|
||||
let params = {}
|
||||
if (tag == 'all') {
|
||||
otherAttachmentList.value = allFiles.value
|
||||
// params = {
|
||||
// targetId: route.query.projectId,
|
||||
// targetState: "30",
|
||||
// }
|
||||
|
||||
otherAttachmentList.value = [...otherAttachmentList.value, ...getLocalList()];
|
||||
} else {
|
||||
const filw = getLocalList().filter(item1 => item1.tag === tag);
|
||||
const filteredAllFiles = allFiles.value.filter(item1 => item1.tag === tag);
|
||||
|
||||
// 使用 fileId 作为唯一标识进行去重
|
||||
const seen = new Set();
|
||||
const uniqueFiles = [...filteredAllFiles, ...filw].filter(item => {
|
||||
if (!seen.has(item.fileId)) {
|
||||
seen.add(item.fileId);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
});
|
||||
|
||||
otherAttachmentList.value = uniqueFiles;
|
||||
// params = {
|
||||
// targetId: route.query.projectId,
|
||||
// targetState: "30",
|
||||
// tag: tag
|
||||
// }
|
||||
}
|
||||
showAttachmentTable.value = false
|
||||
|
||||
// searchImplementationFileList(params).then(res => {
|
||||
// if (res.code === 1000) {
|
||||
// if(tag == 'all'&&flag){
|
||||
// // allFiles.value = res.data.fileList
|
||||
// }else{
|
||||
// otherAttachmentList.value =res.data.fileList
|
||||
// }
|
||||
if (flag) {
|
||||
getTagsOption(flag)
|
||||
}
|
||||
nextTick(() => {
|
||||
showAttachmentTable.value = true
|
||||
})
|
||||
// }
|
||||
// })
|
||||
}
|
||||
const getLocalList = () => {
|
||||
if (localStorage.getItem(`implementAllFileList-${route.query.projectId}`) && JSON.parse(localStorage.getItem(`implementAllFileList-${route.query.projectId}`))) {
|
||||
return JSON.parse(localStorage.getItem(`implementAllFileList-${route.query.projectId}`))
|
||||
} else {
|
||||
return []
|
||||
}
|
||||
}
|
||||
const getAttachmentList = () => {
|
||||
const loading = ElLoading.service({fullscreen: true})
|
||||
let params = {
|
||||
targetId: route.query.projectId,
|
||||
targetState: "30"
|
||||
}
|
||||
showAttachmentTable.value = false
|
||||
searchImplementationFileList(params).then(res => {
|
||||
if (res.code === 1000) {
|
||||
otherAttachmentList.value = [...res.data.fileList, ...getLocalList()]
|
||||
allFiles.value = [...res.data.fileList, ...getLocalList()]
|
||||
uploadState.value = res.data.upload
|
||||
getTagsOption()
|
||||
nextTick(() => {
|
||||
showAttachmentTable.value = true
|
||||
})
|
||||
activeName.value = 'all'
|
||||
loading.close()
|
||||
} else {
|
||||
ElNotification({
|
||||
title: '提示',
|
||||
message: res.msg,
|
||||
type: 'error'
|
||||
})
|
||||
loading.close()
|
||||
}
|
||||
})
|
||||
}
|
||||
const getTagsOption = (flag) => {
|
||||
if (!route.query.projectId) return
|
||||
getTagList(route.query.projectId).then(res => {
|
||||
if (res.code === 1000) {
|
||||
|
||||
tagsOption.value = res.data.rows
|
||||
let list = []
|
||||
if (flag) {
|
||||
|
||||
list = allFiles.value
|
||||
} else {
|
||||
list = otherAttachmentList.value
|
||||
}
|
||||
tagsOption.value.forEach((tag, index) => {
|
||||
// const filterArray = list.filter(item => tag.fileTag == item.tag)
|
||||
// console.log("🚀 ~ file:filterArray ", filterArray)
|
||||
tagsOption.value[index].isClose = 1
|
||||
// tagsOption.value[index].isClose = filterArray.length > 0 ? 0 : 1
|
||||
})
|
||||
console.log("🚀 otherAttachmentList.value", allFiles.value)
|
||||
console.log("🚀 ~ file:\tagsOption.value ", tagsOption.value)
|
||||
let defaultArray = [
|
||||
{
|
||||
tagId: 'd1',
|
||||
fileTag: '合同(专项任务书)',
|
||||
isDefault: 1,
|
||||
isClose: 2
|
||||
},
|
||||
{
|
||||
tagId: 'd2',
|
||||
fileTag: '周报',
|
||||
isDefault: 1,
|
||||
isClose: 2
|
||||
},
|
||||
{
|
||||
tagId: 'd3',
|
||||
fileTag: '阶段性验收',
|
||||
isDefault: 1,
|
||||
isClose: 2
|
||||
},
|
||||
{
|
||||
tagId: 'd4',
|
||||
fileTag: '科研成果',
|
||||
isDefault: 1,
|
||||
isClose: 2
|
||||
}
|
||||
]
|
||||
tagsOption.value = [...defaultArray, ...tagsOption.value]
|
||||
// if (!res.data.rows || res.data.rows.length == 0) return;
|
||||
// activeName.value=res.data.rows[0].tagId
|
||||
} else {
|
||||
ElNotification({
|
||||
title: '提示',
|
||||
message: res.msg,
|
||||
type: 'error'
|
||||
})
|
||||
}
|
||||
})
|
||||
}
|
||||
const handleUpload = () => {
|
||||
router.push({
|
||||
name: 'Implementation/upload',
|
||||
query: {
|
||||
id: route.query.id,
|
||||
projectId: route.query.projectId,
|
||||
state: route.query.state,
|
||||
step: '30'
|
||||
}
|
||||
})
|
||||
}
|
||||
getAttachmentList()
|
||||
onActivated(() => {
|
||||
getAttachmentList()
|
||||
})
|
||||
</script>
|
||||
<style lang="scss">
|
||||
.execute-apply-table {
|
||||
//.el-table__header {
|
||||
// .el-table__cell:last-child {
|
||||
// .cell {
|
||||
// margin-left: -108px !important;
|
||||
// }
|
||||
// }
|
||||
//}
|
||||
|
||||
//.el-table__body {
|
||||
// .el-table__cell:last-child {
|
||||
// .cell {
|
||||
// margin-left: -108px !important;
|
||||
// }
|
||||
// }
|
||||
//}
|
||||
.is-leaf:first-child {
|
||||
.cell {
|
||||
margin-left: -25px !important;
|
||||
}
|
||||
}
|
||||
|
||||
.el-table__body {
|
||||
.el-table__cell:first-child {
|
||||
.cell {
|
||||
margin-left: -13px !important;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
<style scoped lang="scss">
|
||||
:deep(.el-dialog__body) {
|
||||
padding: 0 !important;
|
||||
}
|
||||
|
||||
.tag-title {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
margin-top: 15px;
|
||||
|
||||
> div {
|
||||
margin-right: 5px;
|
||||
width: 4px;
|
||||
height: 20px;
|
||||
background-color: #BEA266;
|
||||
}
|
||||
}
|
||||
|
||||
:deep(.el-table--fit ) {
|
||||
height: 311px !important;
|
||||
}
|
||||
|
||||
:deep(.el-tabs__nav) {
|
||||
//width: 75vw;
|
||||
}
|
||||
|
||||
:deep(.el-tabs__item) {
|
||||
flex: none !important;
|
||||
}
|
||||
|
||||
:deep(.el-tabs__header) {
|
||||
margin-bottom: 0;
|
||||
}
|
||||
|
||||
:deep(.el-tabs__item.is-active) {
|
||||
color: #BEA266;
|
||||
}
|
||||
|
||||
:deep(.el-tabs__active-bar) {
|
||||
background-color: #BEA266;
|
||||
}
|
||||
|
||||
.file-tag {
|
||||
width: 100%;
|
||||
display: flex;
|
||||
border-bottom: 2px solid #f6f6f6;
|
||||
/*align-items: center;*/
|
||||
}
|
||||
</style>
|
||||
@@ -1,36 +1,35 @@
|
||||
<template>
|
||||
<div v-loading="loading">
|
||||
<div v-loading="loading" style="padding: 0 30px">
|
||||
<baseTitle title="专项资金详情"></baseTitle>
|
||||
<el-form :model="formData" ref="form" label-width="auto">
|
||||
<el-row>
|
||||
<el-col :span="12">
|
||||
<el-form :model="formData" ref="form" >
|
||||
<el-row style="margin-left: 15px;margin-bottom: -18px">
|
||||
<el-col :span="6">
|
||||
<el-form-item label="专项名称">
|
||||
<span>{{ formData.name }}</span>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="12">
|
||||
<el-col :span="6">
|
||||
<el-form-item label="金额(元)">
|
||||
<span>{{ toThousands(formData.fundAmount) }}</span>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="24">
|
||||
<el-col :span="6">
|
||||
<el-form-item label="剩余金额(元)">
|
||||
<span>{{ toThousands(formData.residualAmount) }}</span>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<baseTitle title="介绍"></baseTitle>
|
||||
<el-col :span="24">
|
||||
<el-form-item>
|
||||
<el-card style="width: 100%">
|
||||
<div v-html="formData.introduce">
|
||||
<el-form-item label="专项资金情况说明" >
|
||||
<div style="white-space: pre-wrap">{{formData.introduce}}
|
||||
</div>
|
||||
</el-card>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
</el-row>
|
||||
<el-row style="margin-bottom: -18px" class="projects">
|
||||
<baseTitle title="关联项目" v-if="!data.taskId"></baseTitle>
|
||||
<el-col :span="24" v-if="!data.taskId">
|
||||
<el-form-item>
|
||||
<fvTable style="width: 100%;max-height:162px" height="162" v-if="showTable" :tableConfig="projectTable"
|
||||
<el-col :span="24" v-if="!data.taskId" >
|
||||
<el-form-item >
|
||||
<fvTable style="width: 100%;max-height:160px" height="160" v-if="showTable" :tableConfig="projectTable"
|
||||
:data="formData.projects" :isSettingCol="false" :pagination="false">
|
||||
<template #empty>
|
||||
<el-empty :image-size="55" description="暂无数据" style="padding: 0"/>
|
||||
@@ -38,10 +37,10 @@
|
||||
</fvTable>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<baseTitle title="附件列表"></baseTitle>
|
||||
<baseTitle title="附件文件"></baseTitle>
|
||||
<el-col :span="24">
|
||||
<el-form-item>
|
||||
<fvTable style="width: 100%;max-height: 162px;" height="162" v-if="showTable" :tableConfig="fileTable"
|
||||
<fvTable style="width: 100%;max-height: 160px;" height="160" v-if="showTable" :tableConfig="fileTable"
|
||||
:data="formData.files" :isSettingCol="false" :pagination="false">
|
||||
<template #empty>
|
||||
<el-empty :image-size="55" description="暂无数据" style="padding: 0"/>
|
||||
@@ -49,7 +48,7 @@
|
||||
</fvTable>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="24">
|
||||
<el-col :span="24" style="margin-top: -18px">
|
||||
<div v-if="data.taskId">
|
||||
<baseTitle title="审核意见"></baseTitle>
|
||||
<el-form-item prop="auditOpinion">
|
||||
@@ -83,7 +82,10 @@
|
||||
</div>
|
||||
</el-form>
|
||||
<opinion v-if="data.taskId" :formData="data.formData" :taskId="data.taskId"
|
||||
:taskUserOptionList="data.taskUserOptionList"
|
||||
v-model:value="formData.auditOpinion"></opinion>
|
||||
<file-preview ref="filePreviewRef" v-if="filePreviewShow" :fileName="filePreviewParam.fileName" :fileUrl="filePreviewParam.fileUrl"
|
||||
:fileType="filePreviewParam.fileType"/>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
@@ -132,6 +134,7 @@ const projectTable = reactive({
|
||||
prop: 'projectName',
|
||||
label: '项目名称',
|
||||
align: 'center',
|
||||
width: 400
|
||||
},
|
||||
{
|
||||
prop: 'specialFundAmount',
|
||||
@@ -171,6 +174,9 @@ const fileTable = reactive({
|
||||
prop: 'originalFileName',
|
||||
label: '文件名',
|
||||
align: 'center',
|
||||
width: 400,
|
||||
showOverflowTooltip: false,
|
||||
currentRender: ({row, index}) => (<div style="color: #2a99ff;cursor: pointer;" onClick={()=>clickToPreview(row)}>{row.originalFileName}</div>)
|
||||
},
|
||||
{
|
||||
prop: 'tag',
|
||||
@@ -195,6 +201,23 @@ const fileTable = reactive({
|
||||
}
|
||||
]
|
||||
})
|
||||
const filePreviewParam = ref({
|
||||
fileUrl: '',
|
||||
fileName: '',
|
||||
fileType: 'pdf'
|
||||
})
|
||||
const filePreviewShow = ref(false)
|
||||
const clickToPreview=(row)=>{
|
||||
filePreviewShow.value = false
|
||||
filePreviewParam.value = {
|
||||
fileUrl: row.url,
|
||||
fileName: row.originalFileName,
|
||||
fileType: row.fileType
|
||||
}
|
||||
nextTick(()=>{
|
||||
filePreviewShow.value = true
|
||||
})
|
||||
}
|
||||
const handleView=(row)=>{
|
||||
router.push({
|
||||
name: 'Implementation/detail',
|
||||
@@ -228,7 +251,25 @@ watch(() => props.showTable, (newVal) => {
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss">
|
||||
:deep(.el-table--fit ) {
|
||||
height: 300px !important;
|
||||
.projects{
|
||||
:deep(.el-table--fit ) {
|
||||
height: 300px !important;
|
||||
}
|
||||
}
|
||||
|
||||
:deep(.el-table__header) {
|
||||
.is-leaf:first-child {
|
||||
.cell {
|
||||
margin-left: -20px !important;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
:deep(.el-table__body) {
|
||||
.el-table__cell:first-child {
|
||||
.cell {
|
||||
margin-left: -10px !important;
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
||||
@@ -1,155 +1,153 @@
|
||||
<template>
|
||||
<div class="detail-block" v-loading="loading">
|
||||
<baseTitle title="需求上报信息"></baseTitle>
|
||||
<el-form :model="localFormData" ref="summaryForm" :rules="rules">
|
||||
<el-row gutter="50">
|
||||
<el-col :span="8">
|
||||
<el-form-item label="项目名称" prop="projectName">
|
||||
<span>{{ localFormData.projectName }}</span>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="8">
|
||||
<el-form-item label="开始时间" prop="startTime">
|
||||
<span>{{ localFormData.startTime }}</span>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="8">
|
||||
<el-form-item label="结束时间" prop="endTime">
|
||||
<span>{{ localFormData.endTime }}</span>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="8">
|
||||
<el-form-item label="项目类型" prop="projectType">
|
||||
<span>{{ filterDict(cacheStore.getDict('project_type'), localFormData.projectType) }}</span>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="8">
|
||||
<el-form-item label="研发主体" prop="rdSubject">
|
||||
<span>{{ filterDict(cacheStore.getDict('rd_subject'), localFormData.rdSubject) }}</span>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="8">
|
||||
<el-form-item label="出资类型" prop="investmentType">
|
||||
<span>{{ filterDict(cacheStore.getDict('invest_type'), localFormData.investmentType) }}</span>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<!-- <el-col :span="8">-->
|
||||
<!-- <el-form-item label="项目影响" prop="projectImpact">-->
|
||||
<!-- <span>{{ filterDict(cacheStore.getDict('project_impact'), localFormData.projectImpact) }}</span>-->
|
||||
<baseTitle title="预期知识产权"></baseTitle>
|
||||
<el-row gutter="20" style="margin-bottom: -18px;margin-left: 5px">
|
||||
<!-- <el-col :span="6">-->
|
||||
<!-- <el-form-item label="预期成果形式" prop="resultForm">-->
|
||||
<!-- <span>{{ filterDict(cacheStore.getDict('result_form'), localFormData.resultForm) }}</span>-->
|
||||
<!-- </el-form-item>-->
|
||||
<!-- </el-col>-->
|
||||
<el-col :span="8">
|
||||
<el-form-item label="所属业务板块" prop="businessSegment">
|
||||
<span>{{ filterDict(cacheStore.getDict('business_segment'), localFormData.businessSegment) }}</span>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="8">
|
||||
<el-form-item label="预期技术标准制定" prop="technicalStandard">
|
||||
<span>{{ filterDict(cacheStore.getDict('technical_standard'), localFormData.technicalStandard) }}</span>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="8">
|
||||
<el-form-item label="产学研联合" prop="industryUniversityResearch">
|
||||
<span>{{
|
||||
filterDict(cacheStore.getDict('industry_university'), localFormData.industryUniversityResearch)
|
||||
}}</span>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="8">
|
||||
<el-form-item label="开展政府申报" prop="governmentDeclaration">
|
||||
<span>{{
|
||||
filterDict(cacheStore.getDict('government_declaration'), localFormData.governmentDeclaration)
|
||||
}}</span>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="8" v-if="localFormData.isSpecialFund">
|
||||
<el-form-item label="专项资金名称" prop="specialFund">
|
||||
<span>{{
|
||||
localFormData.specialFundId === 0 ? localFormData.specialFund : changeName(fundOption, localFormData.specialFundId)
|
||||
}}</span>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="8">
|
||||
<el-form-item label="知识产权状况" prop="intellectualProperty">
|
||||
<el-col :span="6">
|
||||
<el-form-item label="知识产权归属" prop="intellectualProperty">
|
||||
<span>{{
|
||||
filterDict(cacheStore.getDict('intellectual_property'), localFormData.intellectualProperty)
|
||||
}}</span>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="16">
|
||||
<el-form-item label="预期成果形式" prop="resultForm">
|
||||
<span>{{ filterDict(cacheStore.getDict('result_form'), localFormData.resultForm) }}</span>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="24">
|
||||
<baseTitle title="预期知识产权"></baseTitle>
|
||||
</el-col>
|
||||
<el-col :span="8">
|
||||
<el-form-item label="发明专利(项)" prop="inventionPatent">
|
||||
<span>{{ localFormData.inventionPatent }}</span>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="8">
|
||||
<el-form-item label="实用性新型专利(项)" prop="newPatent">
|
||||
<el-col :span="6">
|
||||
<el-form-item label="预估专利(项)" prop="newPatent">
|
||||
<span>{{ localFormData.newPatent }}</span>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="8">
|
||||
<el-form-item label="软件著作权(项)" prop="softwareCopyright">
|
||||
|
||||
<el-col :span="6">
|
||||
<el-form-item label="预估软件著作权(项)" prop="softwareCopyright">
|
||||
<span>{{ localFormData.softwareCopyright }}</span>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="8">
|
||||
<el-form-item label="著作权(项)" prop="copyright">
|
||||
<span>{{ localFormData.copyright }}</span>
|
||||
|
||||
|
||||
<el-col :span="6">
|
||||
<el-form-item label="预估技术标准(项)" prop="technicalNorms">
|
||||
<span>{{ localFormData.technicalNorms }}</span>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="8">
|
||||
<el-form-item label="其他(项)" prop="other">
|
||||
<span>{{ localFormData.other }}</span>
|
||||
|
||||
<el-col :span="6">
|
||||
<el-form-item label="预估新产品(项)" prop="newProduct">
|
||||
<span>{{ localFormData.newProduct }}</span>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="8">
|
||||
<el-form-item label="经济预算(元)" prop="economicEstimate">
|
||||
<span>{{ toThousands(localFormData.economicEstimate) }}</span>
|
||||
|
||||
<el-col :span="6">
|
||||
<el-form-item label="预估新工艺(项)" prop="newProcess">
|
||||
<span>{{ localFormData.newProcess }}</span>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="8">
|
||||
<el-form-item label="其中申请公司总部科技创新专项资金(元)" prop="specialFundAmount"
|
||||
v-if="localFormData.isSpecialFund">
|
||||
<span>{{ toThousands(localFormData.specialFundAmount) }}</span>
|
||||
|
||||
<el-col :span="6">
|
||||
<el-form-item label="预估新装置(项)" prop="newDevice">
|
||||
<span>{{ localFormData.newDevice }}</span>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
|
||||
<el-col :span="6">
|
||||
<el-form-item label="预估新材料(项)" prop="newMaterials">
|
||||
<span>{{ localFormData.newMaterials }}</span>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
|
||||
<el-col :span="6">
|
||||
<el-form-item label="预估计算机软件(项)" prop="computerSoftware">
|
||||
<span>{{ localFormData.computerSoftware }}</span>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
|
||||
<el-col :span="6">
|
||||
<el-form-item label="预估论文论著(项)" prop="thesis">
|
||||
<span>{{ localFormData.thesis }}</span>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
|
||||
<el-col :span="6">
|
||||
<el-form-item label="预估研究报告(项)" prop="researchReport">
|
||||
<span>{{ localFormData.researchReport }}</span>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
|
||||
<el-col :span="6">
|
||||
<el-form-item label="预估商标(项)" prop="trademark">
|
||||
<span>{{ localFormData.trademark }}</span>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
|
||||
<el-col :span="6">
|
||||
<el-form-item label="预估其他(项)" prop="other">
|
||||
<span style="white-space: pre-wrap">{{ localFormData.other }}</span>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
</el-row>
|
||||
|
||||
<baseTitle title="项目描述"></baseTitle>
|
||||
<el-row gutter="20" style="margin-left: 5px;margin-bottom: -18px;">
|
||||
<el-col :span="24">
|
||||
<el-form-item label="现有业务描述" prop="serviceDescription">
|
||||
<span>{{ localFormData.serviceDescription }}</span>
|
||||
<span style="white-space: pre-wrap">{{ localFormData.serviceDescription }}</span>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="24">
|
||||
<el-form-item label="研发项目关键内容描述" prop="contentDescription">
|
||||
<span>{{ localFormData.contentDescription }}</span>
|
||||
<el-form-item label="建设目标描述" prop="contentDescription">
|
||||
<span style="white-space: pre-wrap">{{ localFormData.contentDescription }}</span>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="24">
|
||||
<baseTitle title="需求上报申请书"></baseTitle>
|
||||
</el-col>
|
||||
<el-col :span="24">
|
||||
<el-form-item>
|
||||
<el-button type="primary" link @click="handleDownload(localFormData.singleFile)" style="font-size: 16px">
|
||||
{{ localFormData.singleFile?.originalFileName }}
|
||||
</el-button>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="24">
|
||||
<baseTitle title="附件列表"></baseTitle>
|
||||
</el-col>
|
||||
<el-col :span="24">
|
||||
</el-row>
|
||||
|
||||
<baseTitle title="需求上报申请书" style="margin-bottom: -3px;"></baseTitle>
|
||||
<!-- <el-row gutter="20" style="margin-bottom: -15px;">-->
|
||||
<!-- <el-col :span="24">-->
|
||||
<!-- <single-file-component tag="需求上报" v-model:value="localFormData.singleFile" :processViewer="processViewer"/>-->
|
||||
<!-- <!– <el-form-item>–>-->
|
||||
<!-- <!– {{localFormData.singleFile}}–>-->
|
||||
<!-- <!– <el-button type="primary" link @click="handleDownload(localFormData.singleFile)" style="font-size: 16px">–>-->
|
||||
<!-- <!– {{ localFormData.singleFile?.originalFileName }}–>-->
|
||||
<!-- <!– </el-button>–>-->
|
||||
<!-- <!– </el-form-item>–>-->
|
||||
<!-- </el-col>-->
|
||||
<!-- </el-row>-->
|
||||
<!--/* <baseTitle title="附件文件" style="margin-bottom: 0"></baseTitle>*/-->
|
||||
<el-row gutter="20" style="margin-bottom: -18px;">
|
||||
<el-col :span="24" class="file-table-style">
|
||||
<file-component tag="需求上报"
|
||||
v-model:value="localFormData.fileList" :processViewer="processViewer"
|
||||
:file-list-show="fileListShow"/>
|
||||
</el-col>
|
||||
<el-col :span="24">
|
||||
<div v-if="data.taskId||data.state==='4'">
|
||||
<el-col :span="24" style="margin-top: -15px">
|
||||
<div v-if="data.taskId">
|
||||
<baseTitle title="审核意见"></baseTitle>
|
||||
<el-form-item prop="_value">
|
||||
<el-input
|
||||
v-model="_value"
|
||||
:rows="3"
|
||||
type="textarea"
|
||||
placeholder="请输入审核意见"
|
||||
/>
|
||||
</el-form-item>
|
||||
</div>
|
||||
<div v-if="data.state==='5'" style="margin-bottom: 15px">
|
||||
<baseTitle title="前置流程" v-if="localFormData.preProcess"></baseTitle>
|
||||
<div style="display: flex;align-items: center;flex-wrap: wrap;">
|
||||
<div v-for="(item,index) in localFormData.preProcess" :key="item.requestId">
|
||||
<a :href="item.baseUrl" target="_blank"
|
||||
style="color: #2a99ff;cursor: pointer">{{ item.requestName }}<span
|
||||
v-if="index != localFormData.preProcess.length -1">,</span>
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div v-perm="['annual:plan:approve']" v-if="data.state==='4'">
|
||||
<!-- <baseTitle title="前置流程"></baseTitle>-->
|
||||
<!-- <select-pre-process :formData="localFormData"/>-->
|
||||
<baseTitle title="审核意见"></baseTitle>
|
||||
<el-form-item prop="_value">
|
||||
<el-input
|
||||
@@ -163,7 +161,7 @@
|
||||
</el-col>
|
||||
</el-row>
|
||||
<div class="approval-record">
|
||||
<div class="approval-title">
|
||||
<div class="approval-title" style="margin-top: -12px">
|
||||
<baseTitle title="审批记录"></baseTitle>
|
||||
<div class="diagram">
|
||||
<div class="base-title">流程图</div>
|
||||
@@ -172,6 +170,9 @@
|
||||
style="--el-switch-on-color:#BEA266 ; --el-switch-off-color:#cecdcd"
|
||||
/>
|
||||
</div>
|
||||
<el-button color="#DED0B2" style="margin-left: 10px"
|
||||
@click="handleCarbonCopy()">立即抄送
|
||||
</el-button>
|
||||
</div>
|
||||
<div class="process">
|
||||
<operation-render v-if="processViewer && data.operationList && data.operationList.length > 0&&!changeDiagram"
|
||||
@@ -182,6 +183,10 @@
|
||||
</div>
|
||||
</div>
|
||||
</el-form>
|
||||
<user-picker :multiple="true" ref="carbonCopyUserRef" title="请选择抄送人员"
|
||||
v-model:value="carbonCopyUserList" @ok="carbonCopyUserPickerOk"
|
||||
@cancelOrClear="carbonCopyUserPickerOk"/>
|
||||
|
||||
<div class="oper-page-btn" v-perm="['annual:plan:approve']" v-if="data.state==='4'">
|
||||
<el-button type="danger" @click="handleRejectPlan">驳回年度计划</el-button>
|
||||
<el-button color="#DED0B2" @click="handleAgreePlan">通过年度计划</el-button>
|
||||
@@ -201,8 +206,11 @@ import {getSubCompOpt} from "@/api/user/user";
|
||||
import FileComponent from "./FileComponent.vue";
|
||||
import {ElNotification} from "element-plus";
|
||||
import {approvePlan} from "@/api/project-demand/summary";
|
||||
import SelectPreProcess from "@/components/SelectPreProcess.vue";
|
||||
import {applyCcSend} from "@/api/expense-manage";
|
||||
import UserPicker from "@/views/workflow/process/common/UserPicker.vue";
|
||||
|
||||
const emit = defineEmits(['update:value'])
|
||||
const emit = defineEmits(['update:value','ccSend'])
|
||||
const tagsViewStore = useTagsView()
|
||||
const cacheStore = useCacheStore()
|
||||
const props = defineProps({
|
||||
@@ -240,6 +248,8 @@ const router = useRouter()
|
||||
const fundOption = ref([])
|
||||
const companyOption = ref([])
|
||||
const dictName = ref({})
|
||||
const carbonCopyUserList = ref([])
|
||||
const carbonCopyUserRef = ref()
|
||||
const rules = reactive({
|
||||
auditOpinion: [{required: true, message: '请输入审核意见', trigger: 'blur'}],
|
||||
})
|
||||
@@ -251,6 +261,39 @@ const _value = computed({
|
||||
emit("update:value", val);
|
||||
}
|
||||
})
|
||||
const handleCarbonCopy = () => {
|
||||
carbonCopyUserRef.value.showUserPicker()
|
||||
}
|
||||
const carbonCopyUserPickerOk = (userList) => {
|
||||
carbonCopyUserList.value = userList.map(item => item.id)
|
||||
console.log('localFormData.value', props.data)
|
||||
console.log("🚀 ~ file:'carbonCopyUserList.value ", carbonCopyUserList.value)
|
||||
|
||||
addUser()
|
||||
}
|
||||
const addUser = async () => {
|
||||
const res = await applyCcSend({
|
||||
instanceId: props.data.processInstanceId,
|
||||
projectId: route.query.projectId,
|
||||
state: route.query.step,
|
||||
userIds: carbonCopyUserList.value
|
||||
})
|
||||
console.log('res', res)
|
||||
if (res.code === 1000) {
|
||||
ElNotification({
|
||||
title: '提示',
|
||||
message: '抄送成功',
|
||||
type: 'success'
|
||||
})
|
||||
emit('ccSend')
|
||||
} else {
|
||||
ElNotification({
|
||||
title: '提示',
|
||||
message: res.msg,
|
||||
type: 'error'
|
||||
})
|
||||
}
|
||||
}
|
||||
const handleRejectPlan = async () => {
|
||||
// const values = form.value.getValues()
|
||||
// console.log('route',route.query.projectId)
|
||||
@@ -263,9 +306,9 @@ const handleRejectPlan = async () => {
|
||||
return
|
||||
}
|
||||
const params = {
|
||||
auditOpinion:_value.value,
|
||||
projectId:parseInt(route.query.projectId),
|
||||
state:false
|
||||
auditOpinion: _value.value,
|
||||
projectId: parseInt(route.query.projectId),
|
||||
state: false
|
||||
}
|
||||
// console.log('params', params)
|
||||
const res = await approvePlan(params)
|
||||
@@ -280,12 +323,21 @@ const handleRejectPlan = async () => {
|
||||
})
|
||||
}
|
||||
const handleAgreePlan = async () => {
|
||||
const params = {
|
||||
auditOpinion:_value.value,
|
||||
projectId:parseInt(route.query.projectId),
|
||||
state:true
|
||||
if (!_value.value) {
|
||||
ElNotification({
|
||||
title: '提示',
|
||||
message: '请填写审核意见',
|
||||
type: 'warning'
|
||||
})
|
||||
return
|
||||
}
|
||||
// console.log('params', params)
|
||||
const params = {
|
||||
auditOpinion: _value.value,
|
||||
projectId: parseInt(route.query.projectId),
|
||||
preProcess: JSON.stringify(localFormData.value.preProcess),
|
||||
state: true
|
||||
}
|
||||
|
||||
const res = await approvePlan(params)
|
||||
ElNotification({
|
||||
title: '提示',
|
||||
@@ -355,6 +407,7 @@ watch(() => props.loading, (newVal) => {
|
||||
}, {deep: true})
|
||||
|
||||
watchEffect(() => {
|
||||
props.formData.singleFile = [props.formData.singleFile]
|
||||
return Object.keys(props.formData).length && (localFormData.value = props.formData)
|
||||
})
|
||||
|
||||
@@ -365,6 +418,25 @@ getFundOptions()
|
||||
.detail-block {
|
||||
overflow-x: hidden;
|
||||
overflow-y: auto;
|
||||
padding-bottom: 0!important;
|
||||
padding-bottom: 0 !important;
|
||||
}
|
||||
|
||||
.file-table-style {
|
||||
:deep(.el-table__header) {
|
||||
.is-leaf:first-child {
|
||||
.cell {
|
||||
margin-left: -25px !important;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
:deep(.el-table__body) {
|
||||
.el-table__cell:first-child {
|
||||
.cell {
|
||||
margin-left: -13px !important;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
</style>
|
||||
|
||||
209
src/components/DetailComponent/singleFileComponent.vue
Normal file
@@ -0,0 +1,209 @@
|
||||
<template>
|
||||
<el-form :label-position="labelAlign">
|
||||
<el-form-item :label="title?'其他文件':''" :label-position="labelAlign" :label-width="title?95:''">
|
||||
<fvTable style="width: 100%;max-height: 80px;" v-if="processViewer" height="80" :tableConfig="tableConfig"
|
||||
:data="_value" :isSettingCol="false" :pagination="false">
|
||||
<template #empty>
|
||||
<el-empty :image-size="55" description="暂无数据" style="padding: 0"/>
|
||||
</template>
|
||||
</fvTable>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
<file-preview ref="filePreviewRef" :fullscreen="fullscreen" v-if="filePreviewShow" :fileName="filePreviewParam.fileName" :fileUrl="filePreviewParam.fileUrl"
|
||||
:fileType="filePreviewParam.fileType"/>
|
||||
</template>
|
||||
|
||||
<script setup lang="jsx">
|
||||
import {downloadFile, deleteFile} from "@/api/project-demand";
|
||||
import {ElNotification} from "element-plus";
|
||||
|
||||
const props = defineProps({
|
||||
title: {
|
||||
type: String,
|
||||
default: ''
|
||||
},
|
||||
tag: {
|
||||
type: String,
|
||||
default: ''
|
||||
},
|
||||
fileNameTableWidth: {
|
||||
type: String,
|
||||
default: '400'
|
||||
},
|
||||
value: {
|
||||
type: Array,
|
||||
default: []
|
||||
},
|
||||
processViewer: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
},
|
||||
labelAlign: {
|
||||
type: String,
|
||||
default: 'right'
|
||||
},
|
||||
//弹窗是否铺满全屏
|
||||
fullscreen: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
}
|
||||
})
|
||||
const emit = defineEmits(['update:value'])
|
||||
const tableConfig = reactive({
|
||||
columns: [
|
||||
{
|
||||
prop: 'index',
|
||||
type: 'index',
|
||||
label: '序号',
|
||||
align: 'center',
|
||||
width: 85,
|
||||
},
|
||||
{
|
||||
prop: 'originalFileName',
|
||||
label: '文件名',
|
||||
align: 'center',
|
||||
width: props.fileNameTableWidth,
|
||||
showOverflowTooltip: false,
|
||||
currentRender: ({row, index}) => (<div style="color: #2a99ff;cursor: pointer;" onClick={()=>clickToPreview(row)}>{row.originalFileName}</div>)
|
||||
|
||||
},
|
||||
{
|
||||
prop: 'tag',
|
||||
label: '标签',
|
||||
align: 'center'
|
||||
},
|
||||
{
|
||||
prop: 'size',
|
||||
label: '文件大小',
|
||||
align: 'center',
|
||||
width: 150,
|
||||
currentRender: ({row, index}) => (parseInt(row.size / 1024) + 'KB')
|
||||
},
|
||||
{
|
||||
prop: 'oper',
|
||||
label: '操作',
|
||||
align: 'center',
|
||||
showOverflowTooltip: false,
|
||||
currentRender: ({row, index}) => {
|
||||
let btn = []
|
||||
btn.push({label: '下载', func: () => handleDownload(row), type: 'primary'})
|
||||
// if (row.newFile) {
|
||||
// btn.push({label: '删除', func: () => handleDelete(row), type: 'primary'})
|
||||
// }
|
||||
return (
|
||||
<div style={{width: '100%'}}>
|
||||
{
|
||||
btn.map(item => (
|
||||
<el-button
|
||||
type={item.type}
|
||||
onClick={() => item.func()}
|
||||
link>
|
||||
{item.label}
|
||||
</el-button>
|
||||
))
|
||||
}
|
||||
{
|
||||
row.newFile ? <popover-delete name={row.originalFileName} type={'文件'} btnType={'danger'}
|
||||
onDelete={() => handleDelete(row)}/>
|
||||
: ''
|
||||
}
|
||||
</div>
|
||||
)
|
||||
}
|
||||
}
|
||||
]
|
||||
})
|
||||
const filePreviewParam = ref({
|
||||
fileUrl: '',
|
||||
fileName: '',
|
||||
fileType: 'pdf'
|
||||
})
|
||||
const filePreviewShow = ref(false)
|
||||
const clickToPreview=(row)=>{
|
||||
filePreviewShow.value = false
|
||||
filePreviewParam.value = {
|
||||
fileUrl: row.url,
|
||||
fileName: row.originalFileName,
|
||||
fileType: row.fileType
|
||||
}
|
||||
nextTick(()=>{
|
||||
filePreviewShow.value = true
|
||||
})
|
||||
}
|
||||
const _value = computed({
|
||||
get() {
|
||||
return props.value;
|
||||
},
|
||||
set(val) {
|
||||
emit("update:value", val);
|
||||
}
|
||||
})
|
||||
|
||||
const getOtherFile = (val) => {
|
||||
props.processViewer = false
|
||||
let fileObj = compositeParam(val)
|
||||
_value.value.push(fileObj)
|
||||
nextTick(() => {
|
||||
props.processViewer = true
|
||||
})
|
||||
}
|
||||
|
||||
|
||||
const compositeParam = (item, type) => {
|
||||
return {
|
||||
fileId: item.id,
|
||||
size: item.size,
|
||||
originalFileName: item.originalFilename,
|
||||
fileType: item.fileType,
|
||||
url: item.url,
|
||||
newFile: true,
|
||||
tag: props.tag
|
||||
}
|
||||
}
|
||||
const handleDownload = (row) => {
|
||||
downloadFile(row.fileId).then(res => {
|
||||
const blob = new Blob([res])
|
||||
let a = document.createElement('a')
|
||||
a.href = URL.createObjectURL(blob)
|
||||
a.download = row.originalFileName
|
||||
a.click()
|
||||
})
|
||||
}
|
||||
const handleDelete = (row) => {
|
||||
deleteFile(row.fileId).then(res => {
|
||||
ElNotification({
|
||||
title: '提示',
|
||||
message: res.msg,
|
||||
type: res.code === 1000 ? 'success' : 'error'
|
||||
})
|
||||
if (res.code === 1000) {
|
||||
_value.value.splice(_value.value.findIndex((item) => item.fileId === row.fileId), 1);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
watch(() => props.processViewer, (newVal) => {
|
||||
props.processViewer = newVal
|
||||
}, {deep: true})
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss">
|
||||
:deep(.el-table--fit ) {
|
||||
height: 80px !important;
|
||||
}
|
||||
:deep(.el-table__header) {
|
||||
.is-leaf:first-child {
|
||||
.cell {
|
||||
margin-left: -25px !important;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
:deep(.el-table__body) {
|
||||
.el-table__cell:first-child {
|
||||
.cell {
|
||||
margin-left: -13px !important;
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
@@ -1,13 +1,14 @@
|
||||
<template>
|
||||
<el-upload :file-list="_value"
|
||||
:action="uploadFileUrl"
|
||||
<el-upload :file-list="_value" ref="uploadRef"
|
||||
action="#"
|
||||
:headers="headers"
|
||||
:limit="maxSize"
|
||||
with-credentials
|
||||
:multiple="multiple"
|
||||
:data="uploadParams"
|
||||
:data="uploadParams" :on-change="handleChange"
|
||||
:http-request="customUpload"
|
||||
:show-file-list="showFileList"
|
||||
:auto-upload="true"
|
||||
:auto-upload="false"
|
||||
:before-upload="beforeUpload"
|
||||
:on-success="handleUploadSuccess"
|
||||
:on-error="uploadError"
|
||||
@@ -19,16 +20,20 @@
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import { ElMessageBox, ElNotification} from "element-plus";
|
||||
import {ElLoading, ElMessage, ElMessageBox, ElNotification} from "element-plus";
|
||||
import {getToken} from '@/utils/auth'
|
||||
import {nextTick} from "vue";
|
||||
import axios from "axios";
|
||||
|
||||
const baseURL = import.meta.env.VITE_BASE_URL
|
||||
const uploadFileUrl = ref(baseURL + "/workflow/process/file/upload")
|
||||
const headers = reactive({
|
||||
'Content-Type': 'multipart/form-data',
|
||||
authorization: getToken()
|
||||
})
|
||||
const loading = ref(false)
|
||||
const showTable = ref(false)
|
||||
const uploadIndex = ref(0)
|
||||
const uploadParams = ref({})
|
||||
const props = defineProps({
|
||||
value: {
|
||||
@@ -39,7 +44,7 @@ const props = defineProps({
|
||||
},
|
||||
maxSize: {
|
||||
type: Number,
|
||||
default: 30
|
||||
default: 999999
|
||||
},
|
||||
showFileList: {
|
||||
type: Boolean,
|
||||
@@ -54,8 +59,9 @@ const props = defineProps({
|
||||
default: true
|
||||
}
|
||||
})
|
||||
|
||||
const emit = defineEmits(["input", "getFile", "delete"])
|
||||
const uploadRef = ref(null); // el-upload 的 ref
|
||||
const uploadPromises = ref([]); // 跟踪每个文件的上传状态
|
||||
const emit = defineEmits(["input", "beforeUpload","getFile", "delete"])
|
||||
const fileList = ref([])
|
||||
const _value = computed({
|
||||
get() {
|
||||
@@ -73,9 +79,79 @@ const beforeRemove = (file) => {
|
||||
}).then(() => true)
|
||||
}
|
||||
|
||||
const uploadLoading = ref(false)
|
||||
const uploadFile = ref([])
|
||||
const handleRemove = (file) => {
|
||||
emit("delete", file.response.data.id)
|
||||
}
|
||||
|
||||
// 文件选择变化时触发
|
||||
const handleChange = (file, files) => {
|
||||
console.log(file, files,'files')
|
||||
uploadIndex.value++
|
||||
uploadFile.value.push(file)
|
||||
};
|
||||
watch(() => uploadIndex.value, (newVal) => {
|
||||
console.log('newVal',newVal)
|
||||
startUpload(uploadFile.value); // 自动触发上传
|
||||
},{
|
||||
deep: true
|
||||
})
|
||||
// 自定义上传逻辑
|
||||
const customUpload = async (options) => {
|
||||
const formData = new FormData();
|
||||
formData.append('file', options.raw);
|
||||
try {
|
||||
const response = await axios.post(uploadFileUrl.value, formData, {
|
||||
headers: headers,
|
||||
});
|
||||
|
||||
fileList.value.push(response.data.data)
|
||||
|
||||
emit("getFile", response.data.data)
|
||||
return response.data; // 成功时返回响应
|
||||
} catch (error) {
|
||||
throw new Error('上传失败'); // 失败时抛出错误
|
||||
}
|
||||
};
|
||||
|
||||
// 触发所有文件上传
|
||||
const startUpload = (files) => {
|
||||
uploadLoading.value= ElLoading.service({
|
||||
fullscreen: true,
|
||||
text: '文件上传中...',
|
||||
})
|
||||
if (files.length === 0) {
|
||||
return; // 没有文件时直接返回
|
||||
}
|
||||
uploadPromises.value = []; // 重置 Promise 数组
|
||||
files.forEach((file) => {
|
||||
// 触发每个文件的上传
|
||||
const promise = new Promise((resolve, reject) => {
|
||||
customUpload(file).then(resolve)
|
||||
.catch(reject);
|
||||
});
|
||||
uploadPromises.value.push(promise);
|
||||
});
|
||||
|
||||
// 使用 Promise.all 监听所有文件上传完成
|
||||
Promise.all(uploadPromises.value)
|
||||
.then(() => {
|
||||
ElNotification({
|
||||
title: '提示',
|
||||
message: '所有文件上传完成!',
|
||||
type: 'success'
|
||||
})
|
||||
files = []; // 清空文件列表
|
||||
uploadRef.value.clearFiles(); // 清空上传组件
|
||||
nextTick(() => {
|
||||
uploadLoading.value.close()
|
||||
uploadLoading.value=null
|
||||
})
|
||||
})
|
||||
|
||||
};
|
||||
|
||||
const beforeUpload = () => {
|
||||
loading.value = true
|
||||
return true
|
||||
|
||||
114
src/components/ImportCostExcel.vue
Normal file
@@ -0,0 +1,114 @@
|
||||
<template>
|
||||
<el-upload :file-list="[]"
|
||||
:limit="maxSize"
|
||||
with-credentials
|
||||
:multiple="multiple"
|
||||
:http-request="httpRequestHandle"
|
||||
:data="uploadParams"
|
||||
:auto-upload="true"
|
||||
:show-file-list="false"
|
||||
:before-upload="beforeUpload"
|
||||
:before-remove="beforeRemove"
|
||||
:on-remove="handleRemove"
|
||||
>
|
||||
<el-button color="#DED0B2" style="margin-right: 10px;" :disabled="disabled">导入</el-button>
|
||||
</el-upload>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import {ElMessageBox, ElNotification} from "element-plus";
|
||||
import {getToken} from '@/utils/auth'
|
||||
import axios from "axios";
|
||||
|
||||
const props = defineProps({
|
||||
value: {
|
||||
type: Array,
|
||||
default: () => {
|
||||
return []
|
||||
}
|
||||
},
|
||||
maxSize: {
|
||||
type: Number,
|
||||
default: 30
|
||||
},
|
||||
disabled: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
},
|
||||
multiple: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
},
|
||||
})
|
||||
|
||||
|
||||
const baseURL = import.meta.env.VITE_BASE_URL
|
||||
const uploadFileUrl = ref(baseURL + "/workflow/mosr/rd/expense/import")
|
||||
const headers = reactive({
|
||||
authorization: getToken()
|
||||
})
|
||||
// const loading = ref(false)
|
||||
const uploadParams = ref({})
|
||||
const emit = defineEmits(["input", "getFile", "delete"])
|
||||
const beforeRemove = (file) => {
|
||||
return ElMessageBox.confirm(`确认删除名称为${file.name}的文件吗?`, '系统提示', {
|
||||
confirmButtonText: '确定',
|
||||
cancelButtonText: '取消',
|
||||
type: 'warning'
|
||||
}).then(() => true)
|
||||
}
|
||||
|
||||
const handleRemove = (file) => {
|
||||
emit("delete", file.response.data.id)
|
||||
}
|
||||
const beforeUpload = () => {
|
||||
// loading.value = true
|
||||
return true
|
||||
}
|
||||
const httpRequestHandle = (param) => {
|
||||
|
||||
let file = param.file
|
||||
axios.post(uploadFileUrl.value, {
|
||||
file: file
|
||||
}, {
|
||||
headers: {
|
||||
'Content-Type': 'multipart/form-data',
|
||||
...headers
|
||||
}
|
||||
}).then(res => {
|
||||
handleUploadSuccess(res)
|
||||
}).catch(error => {
|
||||
uploadError(error)
|
||||
})
|
||||
}
|
||||
const handleUploadSuccess = (res) => {
|
||||
let data = res.data
|
||||
ElNotification({
|
||||
title: '提示',
|
||||
message: data.code === 1000 ? '上传成功' : '上传失败',
|
||||
type: data.code === 1000 ? 'success' : 'error'
|
||||
})
|
||||
emit("success")
|
||||
}
|
||||
const uploadError = (error) => {
|
||||
console.log("🚀 ~ file:'error ", error.response.data.msg)
|
||||
|
||||
// loading.value = false
|
||||
ElNotification({
|
||||
title: '提示',
|
||||
message: error.response.data.msg,
|
||||
type: 'error'
|
||||
})
|
||||
}
|
||||
defineExpose({
|
||||
handleRemove
|
||||
})
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
a {
|
||||
font-size: 14px;
|
||||
color: #2a99ff;
|
||||
}
|
||||
|
||||
</style>
|
||||
@@ -67,7 +67,6 @@ const handleRemove = (file) => {
|
||||
}
|
||||
const beforeUpload = () => {
|
||||
// loading.value = true
|
||||
console.log('水电费水电费,beforeUpload')
|
||||
return true
|
||||
}
|
||||
const httpRequestHandle = (param) => {
|
||||
|
||||
@@ -3,12 +3,16 @@
|
||||
<slot name="pre"></slot>
|
||||
<div class="user-audit">
|
||||
<div class="circle-user">
|
||||
<Tooltip :content="user.name" placement="bottom-start" width="45px"/>
|
||||
<Tooltip v-if="userName" :content="userName" placement="bottom-start" width="45px"/>
|
||||
<Tooltip v-else :content="user.name" placement="bottom-start" width="45px"/>
|
||||
<!-- :style="{-->
|
||||
<!-- backgroundColor: '#fff'-->
|
||||
<!-- }">-->
|
||||
<div v-if="user.icon"
|
||||
class="el-timeline-item__node" :style="{
|
||||
backgroundColor: user.color
|
||||
}">
|
||||
<el-icon v-if="user.icon" size="15" :class="user.class">
|
||||
class="el-timeline-item__node">
|
||||
<div v-if="user.isAgent&&!showIcon">
|
||||
</div>
|
||||
<el-icon v-else size="15" :color="user.color" :class="user.class">
|
||||
<component :is="user.icon"/>
|
||||
</el-icon>
|
||||
</div>
|
||||
@@ -18,7 +22,6 @@
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import {Loading, Close, CircleCheckFilled, MoreFilled} from '@element-plus/icons-vue'
|
||||
|
||||
const props = defineProps({
|
||||
row: {
|
||||
@@ -29,14 +32,26 @@ const props = defineProps({
|
||||
type: Boolean,
|
||||
default: false
|
||||
},
|
||||
showIcon: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
},
|
||||
user: {
|
||||
type: Object,
|
||||
default: {}
|
||||
},
|
||||
userName: {
|
||||
type: String,
|
||||
default: ''
|
||||
},
|
||||
mode: {
|
||||
type: String,
|
||||
default: 'design'
|
||||
}
|
||||
},
|
||||
type: {
|
||||
type: String,
|
||||
default: ''
|
||||
},
|
||||
})
|
||||
|
||||
const init = () => {
|
||||
@@ -49,29 +64,41 @@ const initUser = (user) => {
|
||||
let state = user.state
|
||||
//创建节点
|
||||
if (state === 'CREATE') {
|
||||
user["icon"] = CircleCheckFilled
|
||||
user["icon"] = 'CircleCheckFilled'
|
||||
user["color"] = "#0bbd87"
|
||||
}
|
||||
//审批通过
|
||||
if (state === 'AGREE' || state === 'AUTO_PASS') {
|
||||
user["icon"] = CircleCheckFilled
|
||||
user["icon"] = 'CircleCheckFilled'
|
||||
user["color"] = "#0bbd87"
|
||||
}
|
||||
if (props.type === "CC") {
|
||||
user["icon"] = "Promotion"
|
||||
user["color"] = "#3395f8"
|
||||
}
|
||||
//审批处理中
|
||||
if (state === 'RUNNING') {
|
||||
user["icon"] = Loading
|
||||
user["icon"] = 'Loading'
|
||||
user["color"] = "#f78f5f"
|
||||
user["class"] = 'is-loading'
|
||||
}
|
||||
//拒绝后评论
|
||||
if (state === 'REFUSE') {
|
||||
user["icon"] = Close
|
||||
if (state === 'REFUSE' || state === 'ROLLBACK') {
|
||||
// user["icon"] = 'Close'
|
||||
// user["color"] = "#f56c6c"
|
||||
user["icon"] = 'CircleCloseFilled'
|
||||
user["color"] = "#f56c6c"
|
||||
}
|
||||
if (state === 'PASS') {
|
||||
user["icon"] = MoreFilled
|
||||
user["icon"] = 'MoreFilled'
|
||||
user["color"] = "#c0c4cc"
|
||||
}
|
||||
// if (state === 'ROLLBACK') {
|
||||
// // user["icon"] = 'RefreshLeft'
|
||||
// // user["color"] = "#f78f5f"
|
||||
// user["icon"] = 'CircleCloseFilled'
|
||||
// user["color"] = "#f56c6c"
|
||||
// }
|
||||
return user;
|
||||
}
|
||||
|
||||
@@ -95,13 +122,12 @@ init()
|
||||
position: relative;
|
||||
background-color: #8a7243;
|
||||
color: #fff;
|
||||
|
||||
.el-timeline-item__node {
|
||||
position: absolute;
|
||||
bottom: 0;
|
||||
right: 1px;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
</style>
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
<template>
|
||||
<div style="display: flex;justify-content: center">
|
||||
<span class="stateIcon" :style="{backgroundColor: filterDictClass(cacheStore.getDict(dictType), value)}"></span>
|
||||
<span>{{tag.label}}</span>
|
||||
<span>{{tagConfig.label}}</span>
|
||||
<span> {{ filterDict(cacheStore.getDict(dictType), value) }}</span>
|
||||
</div>
|
||||
</template>
|
||||
@@ -21,37 +21,43 @@ const props = defineProps({
|
||||
default: null
|
||||
}
|
||||
});
|
||||
const tag = reactive({
|
||||
const tagConfig = reactive({
|
||||
listClass: "green",
|
||||
isType: true,
|
||||
label: ""
|
||||
});
|
||||
// const dictList = cacheStore.getDict(props.dictType);
|
||||
// const dictFormat = () => {
|
||||
// if(dictList===undefined) return;
|
||||
// for (let i = 0; i < dictList.length; i++) {
|
||||
// if(dictList[i].value=== props.value){
|
||||
// tag.label = dictList[i].label;
|
||||
// tag.listClass=changeParams(dictList[i].listClass)
|
||||
// tag.isType = dictList[i].isType;
|
||||
// }
|
||||
// }
|
||||
// };
|
||||
const filterDictClass = (data, value) => {
|
||||
if(!data) return
|
||||
|
||||
if(data instanceof Array) {
|
||||
tag.value = data.find(item => item.value == value)
|
||||
const filterDictClass = (data, value) => {
|
||||
if (!data|| value == null) return 'gray'
|
||||
if (data instanceof Array) {
|
||||
tagConfig.value = data.find(item => item.value == value)
|
||||
if (!tagConfig.value) {
|
||||
return '#409EFF'
|
||||
} else {
|
||||
if (tagConfig.value?.isType) {
|
||||
return changeParams(tagConfig.value.listClass)
|
||||
} else {
|
||||
return tagConfig.value.listClass
|
||||
}
|
||||
}
|
||||
}
|
||||
return changeParams(tag.value.listClass)
|
||||
}
|
||||
const filterDict = (data, value) => {
|
||||
if(!data) return
|
||||
|
||||
if(data instanceof Array) {
|
||||
tag.value = data.find(item => item.value == value)
|
||||
if (!data || value == null) return '未知'
|
||||
if (data instanceof Array) {
|
||||
if (value == true || value == false) {
|
||||
tagConfig.value = data.find(item => item.value == value.toString())
|
||||
} else if (typeof value === "object") {
|
||||
if (value !== null) {
|
||||
tagConfig.value = data.find(item => item.value == value[0])
|
||||
} else {
|
||||
tagConfig.value = {}
|
||||
}
|
||||
} else {
|
||||
tagConfig.value = data.find(item => item.value == value)
|
||||
}
|
||||
}
|
||||
return tag.value.label
|
||||
return tagConfig.value?.label || '未知'
|
||||
}
|
||||
/**
|
||||
* 根据接口返回的listClass切换成对应的颜色
|
||||
|
||||
@@ -9,8 +9,10 @@
|
||||
@cancel="handleCancel"
|
||||
>
|
||||
<template #reference>
|
||||
<!-- v-perm="perm"-->
|
||||
<el-button :type="btnType" size="mini" :disabled="isDisabled" :icon="btnIcon" :plain="isPlain" :link="link">
|
||||
<el-button :type="btnType" size="mini" :disabled="isDisabled" v-if="perm" v-perm="perm" :icon="btnIcon" :plain="isPlain" :link="link">
|
||||
{{ btnText }}
|
||||
</el-button>
|
||||
<el-button :type="btnType" size="mini" :disabled="isDisabled" v-else :icon="btnIcon" :plain="isPlain" :link="link">
|
||||
{{ btnText }}
|
||||
</el-button>
|
||||
</template>
|
||||
@@ -45,7 +47,7 @@ const props = defineProps({
|
||||
},
|
||||
perm: {
|
||||
type: Array,
|
||||
default: ['']
|
||||
default: null
|
||||
},
|
||||
isDisabled: {
|
||||
type: Boolean,
|
||||
|
||||
@@ -1,11 +1,21 @@
|
||||
<template>
|
||||
<div v-loading="_value">
|
||||
<el-form :model="attachment" inline>
|
||||
<el-form :model="attachment" inline style="margin-left: 15px" @submit.prevent="handleSearch">
|
||||
<el-form-item label="名称" prop="fileName">
|
||||
<el-input v-model="attachment.fileName" placeholder="请输入附件名称查询" clearable filterable style="width: 300px"/>
|
||||
<el-input v-model="attachment.fileName" placeholder="请输入文件名查询" clearable filterable style="width: 300px"/>
|
||||
</el-form-item>
|
||||
<el-form-item label="标签" prop="tag" v-if="type==='40'">
|
||||
<el-select v-model="attachment.tag" placeholder="请选择标签" clearable filterable style="width: 300px">
|
||||
<el-form-item label="项目阶段" prop="targetState" v-if="allFile">
|
||||
<el-select v-model="attachment.targetState" placeholder="请选择项目阶段" clearable filterable style="width: 300px">
|
||||
<el-option
|
||||
v-for="item in cacheStore.getDict('archive_file_type')"
|
||||
:key="item.value"
|
||||
:label="item.label"
|
||||
:value="item.value"
|
||||
/>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item label="标签" prop="tag" v-if="type==='30'">
|
||||
<el-select v-model="attachment.tag" placeholder="请选择标签" clearable filterable style="width: 300px">
|
||||
<el-option
|
||||
v-for="item in tagsOption"
|
||||
:key="item.value"
|
||||
@@ -17,17 +27,19 @@
|
||||
<el-form-item>
|
||||
<el-button @click="handleSearch" color="#DED0B2">搜索</el-button>
|
||||
<el-button @click="handleReset">重置</el-button>
|
||||
<el-button v-if="uploadState" color="#DED0B2" @click="handleUpload">上传附件</el-button>
|
||||
<el-button v-if="uploadState&&!allFile" color="#DED0B2" @click="handleUpload">上传附件</el-button>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
<el-card style="width: 100%">
|
||||
<fvTable style="width: 100%;max-height: 300px" v-if="showTable" height="300" :tableConfig="tableConfig"
|
||||
<el-card style="width: 100%;overflow-y: hidden">
|
||||
<fvTable style="width: 100%;max-height: 318px" v-if="showTable" height="318" :tableConfig="allFile?tableConfigAll:tableConfig"
|
||||
:data="fileList" :isSettingCol="false" :pagination="false">
|
||||
<template #empty>
|
||||
<el-empty :image-size="99" description="暂无数据" style="padding: 0"/>
|
||||
</template>
|
||||
</fvTable>
|
||||
</el-card>
|
||||
<file-preview ref="filePreviewRef" v-if="filePreviewShow" :fileName="filePreviewParam.fileName" :fileUrl="filePreviewParam.fileUrl"
|
||||
:fileType="filePreviewParam.fileType"/>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
@@ -35,10 +47,12 @@
|
||||
import {downloadFile} from "@/api/project-demand";
|
||||
import {ElNotification} from "element-plus";
|
||||
import {getTags} from "@/api/project-manage";
|
||||
import {computed} from "vue";
|
||||
import {computed, ref} from "vue";
|
||||
|
||||
import {useCacheStore} from '@/stores/cache.js'
|
||||
const route = useRoute()
|
||||
const router = useRouter()
|
||||
const cacheStore = useCacheStore()
|
||||
const attachment = reactive({})
|
||||
const emit = defineEmits(['search','update:modelValue'])
|
||||
const props = defineProps({
|
||||
@@ -57,19 +71,92 @@ const props = defineProps({
|
||||
loading: {
|
||||
type: Boolean,
|
||||
default: true
|
||||
},
|
||||
allFile: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
}
|
||||
})
|
||||
const tagsOption = ref([])
|
||||
const tableConfig = reactive({
|
||||
columns: [
|
||||
{
|
||||
prop: 'originalFileName',
|
||||
label: '附件名称',
|
||||
prop: 'index',
|
||||
type: 'index',
|
||||
label: '序号',
|
||||
align: 'center',
|
||||
width:85,
|
||||
},
|
||||
{
|
||||
prop: 'originalFileName',
|
||||
label: '文件名',
|
||||
align: 'center',
|
||||
currentRender: ({row, index}) => (<div style="color: #2a99ff;cursor: pointer;" onClick={()=>clickToPreview(row)}>{row.originalFileName}</div>)
|
||||
|
||||
},
|
||||
{
|
||||
prop: 'tag',
|
||||
label: '标签',
|
||||
label:'标签',
|
||||
align: 'center'
|
||||
},
|
||||
{
|
||||
prop: 'size',
|
||||
label: '文件大小',
|
||||
align: 'center',
|
||||
currentRender: ({row, index}) => (parseInt(row.size / 1024) + 'KB')
|
||||
},
|
||||
{
|
||||
prop: 'createTime',
|
||||
label: '上传时间',
|
||||
align: 'center',
|
||||
},
|
||||
{
|
||||
prop: 'oper',
|
||||
label: '操作',
|
||||
align: 'center',
|
||||
showOverflowTooltip: false,
|
||||
currentRender: ({row, index}) => {
|
||||
return (
|
||||
<div>
|
||||
<el-button type="primary" link onClick={() => handleDownload(row)}>下载</el-button>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
}
|
||||
]
|
||||
})
|
||||
const tableConfigAll = reactive({
|
||||
columns: [
|
||||
{
|
||||
prop: 'index',
|
||||
type: 'index',
|
||||
label: '序号',
|
||||
align: 'center',
|
||||
width:85,
|
||||
},
|
||||
{
|
||||
prop: 'originalFileName',
|
||||
label: '文件名',
|
||||
align: 'center',
|
||||
currentRender: ({row, index}) => (<div style="color: #2a99ff;cursor: pointer;" onClick={()=>clickToPreview(row)}>{row.originalFileName}</div>)
|
||||
|
||||
},
|
||||
{
|
||||
prop: 'targetState',
|
||||
label:'项目阶段',
|
||||
align: 'center',
|
||||
showOverflowTooltip: false,
|
||||
currentRender: ({row, index}) => {
|
||||
if (row.targetState&&row.targetState !== null&&row.targetState!==undefined) {
|
||||
return (<Tag dictType={'archive_file_type'} value={row.targetState}/>)
|
||||
} else {
|
||||
return '--'
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
prop: 'tag',
|
||||
label:'标签',
|
||||
align: 'center'
|
||||
},
|
||||
{
|
||||
@@ -107,6 +194,23 @@ const _value = computed({
|
||||
emit('update:modelValue', value)
|
||||
}
|
||||
})
|
||||
const filePreviewParam = ref({
|
||||
fileUrl: '',
|
||||
fileName: '',
|
||||
fileType: 'pdf'
|
||||
})
|
||||
const filePreviewShow = ref(false)
|
||||
const clickToPreview=(row)=>{
|
||||
filePreviewShow.value = false
|
||||
filePreviewParam.value = {
|
||||
fileUrl: row.url,
|
||||
fileName: row.originalFileName,
|
||||
fileType: row.fileType
|
||||
}
|
||||
nextTick(()=>{
|
||||
filePreviewShow.value = true
|
||||
})
|
||||
}
|
||||
const getTagsOption = () => {
|
||||
if (!route.query.id) return
|
||||
getTags(route.query.id).then(res => {
|
||||
@@ -126,6 +230,7 @@ const handleSearch = () => {
|
||||
}
|
||||
const handleReset=()=>{
|
||||
attachment.fileName=''
|
||||
attachment.targetState=''
|
||||
attachment.tag=null
|
||||
emit('search', {})
|
||||
}
|
||||
@@ -151,12 +256,12 @@ watch(() => props.fileList, (val) => {
|
||||
})
|
||||
props.fileList = val
|
||||
})
|
||||
if (props.type === '40') {
|
||||
if (props.type === '30') {
|
||||
getTagsOption()
|
||||
}
|
||||
|
||||
onActivated(()=>{
|
||||
if (props.type === '40') {
|
||||
if (props.type === '30') {
|
||||
getTagsOption()
|
||||
}
|
||||
handleSearch()
|
||||
@@ -164,5 +269,7 @@ onActivated(()=>{
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
|
||||
:deep(.el-table--fit ) {
|
||||
height: 318px !important;
|
||||
}
|
||||
</style>
|
||||
|
||||
226
src/components/SelectPreProcess.vue
Normal file
@@ -0,0 +1,226 @@
|
||||
<template>
|
||||
<div style="display: flex;align-items: center;flex-wrap: wrap;">
|
||||
<el-button color="#DED0B2" @click="handleShowPreTable" style="margin-right: 10px">
|
||||
{{
|
||||
localFormData.preProcess && localFormData.preProcess.length > 0 ? '更改' : '请选择前置流程'
|
||||
}}
|
||||
</el-button>
|
||||
<div v-for="(item,index) in localFormData.preProcess" :key="item.requestId">
|
||||
<a :href="item.baseUrl" target="_blank"
|
||||
style="color: #2a99ff;cursor: pointer">{{ item.requestName }}<span
|
||||
v-if="index != localFormData.preProcess.length -1">,</span>
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
<el-dialog v-if="showPreTable" title="前置流程" v-model="showPreTable" width="80%">
|
||||
<el-form :model="preProcessForm" inline @submit.prevent="getPreProcessList">
|
||||
<el-form-item label="请求名称">
|
||||
<el-input v-model="preProcessForm.requestName" placeholder="请输入请求名称" clearable>
|
||||
</el-input>
|
||||
</el-form-item>
|
||||
<el-form-item>
|
||||
<el-button color="#DED0B2" @click="getPreProcessList">搜索</el-button>
|
||||
<el-button @click="handleReset">重置</el-button>
|
||||
</el-form-item>
|
||||
<el-form-item>
|
||||
<el-tag type="danger" style="font-size: 16px;color: red;" >特别提示:{{ getPreProcessTag(localFormData.projectImpact,basicData.projectImpact) }}</el-tag>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
<el-table :data="preProcessList" v-loading="loading"
|
||||
@select="handleSelect" @select-all="handleSelect" row-key="requestId" ref="preProcessTable">
|
||||
<el-table-column type="selection" width="55" :reserve-selection="true"
|
||||
:selectable="checkSelectable"/>
|
||||
<el-table-column prop="requestId" label="请求id"></el-table-column>
|
||||
<el-table-column prop="requestName" label="请求名称"></el-table-column>
|
||||
<el-table-column prop="lastOperatorName" label="最后操作人名称"></el-table-column>
|
||||
<el-table-column prop="lastOperateTime" label="最后操作时间"></el-table-column>
|
||||
<el-table-column prop="currentNodeName" label="当前节点"></el-table-column>
|
||||
<el-table-column prop="creatorName" label="创建人"></el-table-column>
|
||||
<el-table-column prop="createTime" label="创建时间"></el-table-column>
|
||||
<el-table-column label="操作" align="center">
|
||||
<template #default="scope">
|
||||
<a :href="scope.row.baseUrl" target="_blank" style="color: #2a99ff;margin-left: 10px">查看流程</a>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
<paging :current-page="pageInfo.pageNum" :page-size="pageInfo.pageSize" :page-sizes="[10, 20, 30, 40,50]"
|
||||
:total="total" @changeSize="handleSizeChange" @goPage="handleCurrentChange"/>
|
||||
<div class="oper">
|
||||
<el-button color="#DED0B2" @click="choosePreProcess">确定</el-button>
|
||||
<el-button @click="handleCancel">取消</el-button>
|
||||
</div>
|
||||
</el-dialog>
|
||||
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import {
|
||||
getPreProcess
|
||||
} from "@/api/project-manage";
|
||||
import Paging from "@/components/pagination/index.vue";
|
||||
|
||||
const props = defineProps({
|
||||
formData: {
|
||||
type: Object,
|
||||
default: {}
|
||||
},
|
||||
basicData: {
|
||||
type: Object,
|
||||
default: {}
|
||||
},
|
||||
})
|
||||
const loading = ref(false)
|
||||
//暂存数据
|
||||
const originalProcess = ref([])
|
||||
const currentList = ref([])
|
||||
const showPreTable = ref(false)
|
||||
const selectRows = ref([])
|
||||
const preProcessList = ref([])
|
||||
const total = ref(0)
|
||||
const preProcessTable = ref()
|
||||
const localFormData = ref({
|
||||
projectPersonIds: [],
|
||||
projectChargePerson: null,
|
||||
preProcess: [
|
||||
// {
|
||||
// requestId: null,
|
||||
// requestName: '',
|
||||
// baseUrl: ''
|
||||
// }
|
||||
]
|
||||
})
|
||||
const preProcessForm = reactive({
|
||||
requestName: ''
|
||||
})
|
||||
const pageInfo = reactive({
|
||||
pageNum: 1,
|
||||
pageSize: 10,
|
||||
})
|
||||
const getPreProcessTag = (impact,basicImpact) => {
|
||||
let data=''
|
||||
if(impact){
|
||||
data= impact
|
||||
}else if(basicImpact){
|
||||
data= basicImpact
|
||||
}
|
||||
if (data == 1) {
|
||||
//一般项目
|
||||
return '研发费用20万元(含)以下科技创新项目报总经理审批'
|
||||
} else if (data == 2) {
|
||||
//重大项目
|
||||
return '重大项目20万元到500万元之间要总办会审批'
|
||||
} else if (data == 3) {
|
||||
//特别重大项目
|
||||
return '特别重大项目500万元以上要董事会审批'
|
||||
}
|
||||
}
|
||||
const handleReset = () => {
|
||||
preProcessForm.requestName = ''
|
||||
getPreProcessList()
|
||||
}
|
||||
const handleSelect = async (selection) => {
|
||||
selectRows.value = selection
|
||||
}
|
||||
const checkSelectable=(row)=>{
|
||||
const detailProcessStr = localStorage.getItem('detailProcess');
|
||||
let preProcessArray = []
|
||||
if (detailProcessStr) {
|
||||
try {
|
||||
preProcessArray = JSON.parse(detailProcessStr)
|
||||
} catch (e) {
|
||||
preProcessArray=[]
|
||||
}
|
||||
if (preProcessArray&&preProcessArray.length > 0) {
|
||||
for (let i = 0; i < preProcessArray.length; i++) {
|
||||
return preProcessArray[i].requestId !== row.requestId;
|
||||
}
|
||||
}else{
|
||||
return true
|
||||
}
|
||||
}
|
||||
}
|
||||
const handleShowPreTable = () => {
|
||||
showPreTable.value = true
|
||||
nextTick(() => {
|
||||
localFormData.value.preProcess?.forEach((item) => {
|
||||
if (preProcessTable.value) {
|
||||
preProcessTable.value.toggleRowSelection(item, true)
|
||||
}
|
||||
})
|
||||
})
|
||||
getPreProcessList()
|
||||
}
|
||||
const handleCancel = () => {
|
||||
showPreTable.value = false
|
||||
}
|
||||
|
||||
const choosePreProcess = () => {
|
||||
let preProcessObj = {}
|
||||
let preProcessArray = []
|
||||
const detailProcessStr = localStorage.getItem('detailProcess');
|
||||
try {
|
||||
originalProcess.value = JSON.parse(detailProcessStr)
|
||||
} catch (e) {
|
||||
originalProcess.value=[]
|
||||
}
|
||||
selectRows.value.forEach((item) => {
|
||||
const exists = originalProcess.value?.some(dp => dp.requestId === item.requestId)
|
||||
if (!exists) {
|
||||
preProcessObj = {
|
||||
requestId: item.requestId,
|
||||
requestName: item.requestName,
|
||||
baseUrl: item.baseUrl
|
||||
}
|
||||
preProcessArray.push(preProcessObj)
|
||||
}
|
||||
})
|
||||
if(props.formData.mode === 'view'||props.formData.mode === 'resubmit'){
|
||||
localFormData.value.preProcess = [...originalProcess.value,...preProcessArray]
|
||||
}else{
|
||||
localFormData.value.preProcess = preProcessArray
|
||||
}
|
||||
localStorage.setItem('preProcess', JSON.stringify(preProcessArray))
|
||||
showPreTable.value = false
|
||||
}
|
||||
|
||||
const getPreProcessList = () => {
|
||||
loading.value = true
|
||||
getPreProcess().then(res => {
|
||||
loading.value = false
|
||||
let searchArray = []
|
||||
let regexPattern = ("%" + preProcessForm.requestName + "%").replace(/%/g, '.*').replace(/_/g, '.');
|
||||
let regex = new RegExp('^' + regexPattern + '$');
|
||||
res.data.filter((item) => {
|
||||
if (regex.test(item.requestName)) {
|
||||
searchArray.push(item)
|
||||
}
|
||||
})
|
||||
total.value = searchArray.length
|
||||
currentList.value = searchArray
|
||||
preProcessList.value = currentList.value.slice(0, 10)
|
||||
})
|
||||
}
|
||||
//切换每页显示条数
|
||||
const handleSizeChange = (val) => {
|
||||
pageInfo.pageSize = val;
|
||||
preProcessList.value = currentList.value.slice((pageInfo.pageNum - 1) * val, pageInfo.pageNum * val)
|
||||
};
|
||||
|
||||
//点击页码进行分页功能
|
||||
const handleCurrentChange = (val) => {
|
||||
pageInfo.pageNum = val;
|
||||
preProcessList.value = currentList.value.slice((val - 1) * pageInfo.pageSize, val * pageInfo.pageSize)
|
||||
};
|
||||
|
||||
watchEffect(() => {
|
||||
return Object.keys(props.formData).length && (localFormData.value = props.formData)
|
||||
})
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
.oper {
|
||||
margin-top: 20px;
|
||||
display: flex;
|
||||
justify-content: flex-end;
|
||||
}
|
||||
</style>
|
||||
@@ -3,7 +3,7 @@
|
||||
<el-form :model="formData" ref="tagForm" label-width="auto" :rules="rules">
|
||||
<el-form-item label="标签名称" prop="tagName">
|
||||
<el-input v-model="formData.tagName" placeholder="请输入标签名称" style="width: 300px" v-if="showInput"/>
|
||||
<el-select v-model="formData.tagName" placeholder="请选择标签" clearable filterable style="width: 300px" v-else>
|
||||
<el-select v-model="formData.tagName" placeholder="请选择标签" remote clearable filterable style="width: 300px" v-else>
|
||||
<el-option
|
||||
v-for="item in tagsOption"
|
||||
:key="item.label"
|
||||
@@ -16,7 +16,7 @@
|
||||
<baseTitle title="其他文件"></baseTitle>
|
||||
<el-card style="width: 100%;margin: 15px 0">
|
||||
<file-upload @getFile="getFiles"/>
|
||||
<fvTable style="width: 100%;max-height: 162px;height: 162px" height="162" v-if="showTable" :tableConfig="tableConfig"
|
||||
<fvTable style="width: 100%;max-height: 160px;height: 160px" height="160" v-if="showTable" :tableConfig="tableConfig"
|
||||
:data="fileList" :isSettingCol="false" :pagination="false">
|
||||
<template #empty>
|
||||
<el-empty :image-size="55" description="暂无数据" style="padding: 0"/>
|
||||
@@ -59,7 +59,7 @@ const tableConfig = reactive({
|
||||
},
|
||||
{
|
||||
prop: 'originalFileName',
|
||||
label: '附件名称',
|
||||
label: '文件名',
|
||||
align: 'center',
|
||||
},
|
||||
{
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
<template>
|
||||
<div class="tinymce-boxz">
|
||||
<div class="tinymce-boxz" style="width: 100%">
|
||||
<Editor v-model="content" :init="init"/>
|
||||
</div>
|
||||
</template>
|
||||
@@ -8,7 +8,7 @@
|
||||
import tinymce from 'tinymce'
|
||||
import Editor from "@tinymce/tinymce-vue";
|
||||
import {defineProps} from "vue";
|
||||
import {ElMessage} from "element-plus";
|
||||
import {ElLoading, ElMessage, ElNotification} from "element-plus";
|
||||
import {getToken} from '@/utils/auth'
|
||||
import axios from "axios";
|
||||
|
||||
@@ -36,8 +36,9 @@ import 'tinymce/plugins/insertdatetime'
|
||||
import 'tinymce/plugins/lists'
|
||||
import 'tinymce/plugins/wordcount'
|
||||
import 'tinymce/plugins/autosave'
|
||||
import '@/assets/axupimgs/plugin.js'//多图上传插件
|
||||
|
||||
const emit = defineEmits(['update:value'])
|
||||
const emit = defineEmits(['update:value','getFiles'])
|
||||
const props = defineProps({
|
||||
//默认值
|
||||
value: {
|
||||
@@ -55,7 +56,7 @@ const props = defineProps({
|
||||
plugins: {
|
||||
type: [String, Array],
|
||||
default:
|
||||
"preview searchreplace autolink directionality visualblocks visualchars fullscreen image link media template code codesample table pagebreak nonbreaking anchor insertdatetime advlist lists wordcount autosave",
|
||||
"preview searchreplace autolink directionality visualblocks visualchars fullscreen image axupimgs link media template code codesample table pagebreak nonbreaking anchor insertdatetime advlist lists wordcount autosave",
|
||||
},
|
||||
toolbar: {
|
||||
type: [String, Array],
|
||||
@@ -68,15 +69,16 @@ const props = defineProps({
|
||||
type: [String, Array],
|
||||
default: "微软雅黑=Microsoft YaHei,Helvetica Neue,PingFang SC,sans-serif;苹果苹方=PingFang SC,Microsoft YaHei,sans-serif;宋体=simsun,serif;仿宋体=FangSong,serif;黑体=SimHei,sans-serif;Arial=arial,helvetica,sans-serif;Arial Black=arial black,avant garde;Book Antiqua=book antiqua,palatino;"
|
||||
},
|
||||
width:{
|
||||
width: {
|
||||
type: String,
|
||||
default: 'auto'
|
||||
},
|
||||
height:{
|
||||
height: {
|
||||
type: Number,
|
||||
default: 500
|
||||
}
|
||||
})
|
||||
const fileLists=ref([])
|
||||
const content = ref(props.value);
|
||||
const imgUrl = ref();
|
||||
// const apiKey = reactive("v4zo4n22oanvco29ws5drh0pecuf3gh53clx53cccj3grjwg");
|
||||
@@ -88,21 +90,21 @@ const init = reactive({
|
||||
placeholder: "在这里输入文字", //textarea中的提示信息
|
||||
min_width: 300,
|
||||
min_height: 200,
|
||||
width:props.width,
|
||||
width: props.width,
|
||||
height: props.height, //注:引入autoresize插件时,此属性失效
|
||||
resize: "both", //编辑器宽高是否可变,false-否,true-高可变,'both'-宽高均可,注意引号
|
||||
promotion: false,
|
||||
branding: false, //tiny技术支持信息是否显示
|
||||
// statusbar: false, //最下方的元素路径和字数统计那一栏是否显示
|
||||
// elementpath: false, //元素路径是否显示
|
||||
statusbar: false, //最下方的元素路径和字数统计那一栏是否显示
|
||||
elementpath: false, //元素路径是否显示
|
||||
font_formats: props.fontFormats, //字体样式
|
||||
plugins: props.plugins, //插件配置 axupimgs indent2em
|
||||
toolbar: props.toolbar, //工具栏配置,设为false则隐藏
|
||||
// menubar: "file edit my1", //菜单栏配置,设为false则隐藏,不配置则默认显示全部菜单,也可自定义配置--查看 http://tinymce.ax-z.cn/configure/editor-appearance.php --搜索“自定义菜单”
|
||||
// images_upload_url: '/apib/api-upload/uploadimg', //后端处理程序的url,建议直接自定义上传函数image_upload_handler,这个就可以不用了
|
||||
menubar: "file edit view format table tools", //菜单栏配置,设为false则隐藏,不配置则默认显示全部菜单,也可自定义配置--查看 http://tinymce.ax-z.cn/configure/editor-appearance.php --搜索“自定义菜单”
|
||||
images_upload_url: '/workflow/process/file/upload', //后端处理程序的url,建议直接自定义上传函数image_upload_handler,这个就可以不用了
|
||||
// images_upload_base_path: '/demo', //相对基本路径--关于图片上传建议查看--http://tinymce.ax-z.cn/general/upload-images.php
|
||||
paste_data_images: true, //图片是否可粘贴
|
||||
file_picker_types: "file image media", //file image media分别对应三个类型文件的上传:link插件,image和axupimgs插件,media插件。想屏蔽某个插件的上传就去掉对应的参数
|
||||
file_picker_types: "file image", //file image media分别对应三个类型文件的上传:link插件,image和axupimgs插件,media插件。想屏蔽某个插件的上传就去掉对应的参数
|
||||
// 文件上传处理函数
|
||||
setup: function (editor) {
|
||||
editor.on('change', function (e) {
|
||||
@@ -115,11 +117,16 @@ const init = reactive({
|
||||
let formData = new FormData()
|
||||
formData.append('file', blobInfo.blob())
|
||||
//上传图片接口 上传成功后返回图片地址,用于显示在富文本中
|
||||
uploadFile(formData, props.imageUrl, success)
|
||||
uploadFile(formData, props.imageUrl, success, true)
|
||||
// }),
|
||||
},
|
||||
images_upload_handler_not_loading: (blobInfo, success) => {
|
||||
let formData = new FormData()
|
||||
formData.append('file', blobInfo.blob())
|
||||
//上传图片接口
|
||||
uploadFile(formData, props.imageUrl, success, false)
|
||||
},
|
||||
file_picker_callback: (callback, value, meta) => {
|
||||
// console.log('callback, value, meta',callback, value, meta)
|
||||
// 使用案例http://tinymce.ax-z.cn/general/upload-images.php
|
||||
// meta.filetype //根据这个判断点击的是什么file image media
|
||||
let filetype; //限制文件的上传类型,需要什么就添加什么的后缀
|
||||
@@ -137,16 +144,62 @@ const init = reactive({
|
||||
inputElem.click();
|
||||
inputElem.onchange = () => {
|
||||
let file = inputElem.files[0]; //获取文件信息
|
||||
let reader = new FileReader();
|
||||
reader.readAsDataURL(file);
|
||||
reader.onload = function () {
|
||||
let id = "blobid" + new Date().getTime();
|
||||
let blobCache = tinymce.activeEditor.editorUpload.blobCache;
|
||||
let base64 = reader.result.split(",")[1];
|
||||
let blobInfo = blobCache.create(id, file, base64);
|
||||
blobCache.add(blobInfo);
|
||||
callback(blobInfo.blobUri(), {alt: file.name});
|
||||
let xhr, formData;
|
||||
xhr = new XMLHttpRequest();
|
||||
xhr.withCredentials = false;
|
||||
xhr.open('POST', import.meta.env.VITE_BASE_URL + props.imageUrl);
|
||||
xhr.setRequestHeader(
|
||||
'Authorization', getToken()
|
||||
)
|
||||
let loading = ElLoading.service({
|
||||
lock: true,
|
||||
text: '文件上传中...',
|
||||
background: 'rgba(0, 0, 0, 0.7)',
|
||||
})
|
||||
xhr.onload = function () {
|
||||
let res;
|
||||
// if (xhr.status != 200) {
|
||||
// failure('HTTP Error: ' + xhr.status);
|
||||
// return;
|
||||
// }
|
||||
res = JSON.parse(xhr.responseText);
|
||||
ElNotification({
|
||||
title: '提示',
|
||||
message: res.code === 1000 ? '上传成功' : '上传失败',
|
||||
type: res.code === 1000 ? 'success' : 'error'
|
||||
})
|
||||
loading.close()
|
||||
console.log("🚀 ~ file:res.data ", res.data)
|
||||
res.data.originalFileName=res.data.originalFilename
|
||||
console.log("🚀 ~ file:'meta.filetype ",meta.filetype )
|
||||
|
||||
if (res && res.data && res.data.fileType &&
|
||||
!["png", "jpg", "jpeg","gif", "svg","ico"].includes(res.data.fileType.toLowerCase())){
|
||||
fileLists.value.push(res.data)
|
||||
emit('getFiles',fileLists.value)
|
||||
}
|
||||
const fileUrl = res.data.url;
|
||||
// '?fileId='+res.data.id+
|
||||
callback(fileUrl + '?fileName=' + res.data.originalFilename, {text: file.name, title: file.name});
|
||||
};
|
||||
formData = new FormData();
|
||||
formData.append('file', file, file.name);
|
||||
xhr.send(formData);
|
||||
//
|
||||
// let reader = new FileReader();
|
||||
// reader.readAsDataURL(file);
|
||||
// reader.onload = function () {
|
||||
// let formData;
|
||||
// let id = "blobid" + new Date().getTime();
|
||||
// let blobCache = tinymce.activeEditor.editorUpload.blobCache;
|
||||
// let base64 = reader.result.split(",")[1];
|
||||
// let blobInfo = blobCache.create(id, file, base64);
|
||||
// blobCache.add(blobInfo);
|
||||
// // callback(blobInfo.blobUri(), {alt: file.name});
|
||||
// formData = new FormData();
|
||||
// formData.append('file', file, file.name );
|
||||
// uploadFile(formData, props.imageUrl,callback)
|
||||
// };
|
||||
};
|
||||
},
|
||||
});
|
||||
@@ -154,7 +207,16 @@ const init = reactive({
|
||||
watch(() => {
|
||||
emit("update:value", content.value);
|
||||
});
|
||||
const uploadFile = (formData, url,success) => {
|
||||
const uploadFile = (formData, url, success, isLoading) => {
|
||||
let loading = null
|
||||
if (isLoading) {
|
||||
loading = ElLoading.service({
|
||||
lock: true,
|
||||
text: '图片上传中...',
|
||||
background: 'rgba(0, 0, 0, 0.7)',
|
||||
})
|
||||
}
|
||||
|
||||
axios.post(
|
||||
import.meta.env.VITE_BASE_URL + url,
|
||||
formData,
|
||||
@@ -171,18 +233,48 @@ const uploadFile = (formData, url,success) => {
|
||||
let data = res.data
|
||||
if (data.code !== 1000) {
|
||||
ElMessage.error(data.msg)
|
||||
}else {
|
||||
success(data.data.url)
|
||||
if (loading) {
|
||||
loading.close()
|
||||
}
|
||||
} else {
|
||||
if (isLoading) {
|
||||
success(data.data.url)
|
||||
} else {
|
||||
success(data.data.url, data.data.originalFilename)
|
||||
}
|
||||
if (loading) {
|
||||
loading.close()
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
</script>
|
||||
<style scoped>
|
||||
<style scoped lang="scss">
|
||||
.tox-sidebar-wrap {
|
||||
&::-webkit-scrollbar {
|
||||
width: 6px;
|
||||
}
|
||||
|
||||
// 滚动条轨道
|
||||
&::-webkit-scrollbar-track {
|
||||
background: rgb(239, 239, 239);
|
||||
border-radius: 2px;
|
||||
}
|
||||
|
||||
// 小滑块
|
||||
&::-webkit-scrollbar-thumb {
|
||||
background: rgba(80, 81, 82, 0.29);
|
||||
border-radius: 10px;
|
||||
}
|
||||
}
|
||||
|
||||
.tinymce-boxz > textarea {
|
||||
display: none;
|
||||
|
||||
}
|
||||
|
||||
</style>
|
||||
<style>
|
||||
<style lang="scss">
|
||||
/* 隐藏apikey没有绑定当前域名的提示 */
|
||||
.tox-notifications-container .tox-notification--warning {
|
||||
display: none !important;
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
placement="bottom-start"
|
||||
:disabled="isShow"
|
||||
>
|
||||
<div :class="lines?'content-lines':'content'" :style="{width: props.width}" @mouseover="isShowTooltip">
|
||||
<div :class="lines?'content-lines':textAlign=='left'?'left-content':'content'" :style="{width: props.width+'px'}" @mouseover="isShowTooltip">
|
||||
<span ref="contentRef">
|
||||
<slot name="content">{{ props.content }}</slot>
|
||||
</span>
|
||||
@@ -25,15 +25,26 @@ const props = defineProps({
|
||||
lines: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
}
|
||||
},
|
||||
textAlign: {
|
||||
type: String,
|
||||
default: ''
|
||||
},
|
||||
})
|
||||
const contentRef = ref()
|
||||
const isShow = ref(false)
|
||||
const isShowTooltip = () => {
|
||||
isShow.value = props.width > contentRef.value.offsetWidth;
|
||||
isShow.value = parseInt(props.width) > contentRef.value.offsetWidth;
|
||||
}
|
||||
</script>
|
||||
<style>
|
||||
<style scoped>
|
||||
.left-content{
|
||||
width: 45px;
|
||||
text-align: left;
|
||||
text-overflow: ellipsis;
|
||||
white-space: nowrap;
|
||||
overflow: hidden;
|
||||
}
|
||||
.content {
|
||||
width: 45px;
|
||||
text-align: center;
|
||||
|
||||
112
src/components/filePreview/DocxPreview.vue
Normal file
@@ -0,0 +1,112 @@
|
||||
<template>
|
||||
<div class="docx-preview">
|
||||
<div
|
||||
ref="docxDiv"
|
||||
class="docxDiv"
|
||||
v-loading="loading"
|
||||
></div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup lang="jsx">
|
||||
import {renderAsync} from "docx-preview";
|
||||
import axios from "axios";
|
||||
|
||||
let docx = import.meta.glob("docx-preview"); // vite不支持require
|
||||
|
||||
const props = defineProps({
|
||||
fileUrl: {
|
||||
type: String,
|
||||
default: ''
|
||||
}
|
||||
})
|
||||
|
||||
const loading = ref(false);
|
||||
|
||||
const previewFile = () => {
|
||||
loading.value = true;
|
||||
axios.request({
|
||||
url: props.fileUrl,
|
||||
method: 'get',
|
||||
responseType: 'blob'
|
||||
}).then((response) => {
|
||||
let docData = response.data;
|
||||
let docxDiv = document.getElementsByClassName("docxDiv");
|
||||
renderAsync(docData, docxDiv[0], null, {
|
||||
inWrapper: true, // 启用围绕文档内容渲染包装器
|
||||
ignoreWidth: false, // 禁止页面渲染宽度
|
||||
ignoreHeight: false, // 禁止页面渲染高度
|
||||
ignoreFonts: false, // 禁止字体渲染
|
||||
breakPages: true, // 在分页符上启用分页
|
||||
ignoreLastRenderedPageBreak: true, //禁用lastRenderedPageBreak元素的分页
|
||||
experimental: false, //启用实验性功能(制表符停止计算)
|
||||
trimXmlDeclaration: true, //如果为真,xml声明将在解析之前从xml文档中删除
|
||||
debug: false,
|
||||
}).then((res) => {
|
||||
loading.value = false;
|
||||
});
|
||||
}).catch((error) => {
|
||||
});
|
||||
};
|
||||
|
||||
previewFile()
|
||||
|
||||
</script>
|
||||
<style lang="scss">
|
||||
.docx-preview {
|
||||
overflow: auto;
|
||||
height: 650px !important;
|
||||
&::-webkit-scrollbar {
|
||||
width: 6px;
|
||||
height: 6px;
|
||||
}
|
||||
|
||||
// 滚动条轨道
|
||||
&::-webkit-scrollbar-track {
|
||||
background: rgb(239, 239, 239);
|
||||
border-radius: 2px;
|
||||
}
|
||||
|
||||
// 小滑块
|
||||
&::-webkit-scrollbar-thumb {
|
||||
background: rgba(80, 81, 82, 0.29);
|
||||
border-radius: 10px;
|
||||
}
|
||||
.docx-wrapper > section.docx {
|
||||
margin-bottom: 0 !important;
|
||||
}
|
||||
|
||||
.docx-wrapper {
|
||||
padding: 10px !important;
|
||||
|
||||
.docx {
|
||||
width: 100% !important;
|
||||
min-height: 100vh !important;
|
||||
overflow: auto !important;
|
||||
//padding: 70pt 20pt 0 20pt !important;
|
||||
|
||||
table {
|
||||
width: 100% !important;
|
||||
}
|
||||
|
||||
&::-webkit-scrollbar {
|
||||
width: 6px;
|
||||
height: 6px;
|
||||
}
|
||||
|
||||
// 滚动条轨道
|
||||
&::-webkit-scrollbar-track {
|
||||
background: rgb(239, 239, 239);
|
||||
border-radius: 2px;
|
||||
}
|
||||
|
||||
// 小滑块
|
||||
&::-webkit-scrollbar-thumb {
|
||||
background: rgba(80, 81, 82, 0.29);
|
||||
border-radius: 10px;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
||||
74
src/components/filePreview/ImagePreview.vue
Normal file
@@ -0,0 +1,74 @@
|
||||
<template>
|
||||
<div class="img-preview" >
|
||||
<img id="previewImg" :src="fileUrl" :style="{width: fullscreen?windowWidth+'px':'100%',height: fullscreen?'auto':'650px;'}" alt="Preview"/>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
const emit = defineEmits(["update:fileUrl"])
|
||||
const props = defineProps({
|
||||
fileUrl: {
|
||||
type: String,
|
||||
default: ''
|
||||
},
|
||||
fullscreen: {
|
||||
type: Boolean,
|
||||
default:false
|
||||
}
|
||||
})
|
||||
const showImagePreview = ref(true)
|
||||
const dialogWidth = ref('')
|
||||
const dialogHeight = ref('')
|
||||
// 屏幕宽度
|
||||
const windowWidth = ref(0)
|
||||
// 屏幕高度
|
||||
const windowHeight = ref(0)
|
||||
// onMounted(() => {
|
||||
// })
|
||||
// 获取屏幕尺寸
|
||||
const getWindowResize = function () {
|
||||
windowWidth.value = window.innerWidth-32
|
||||
windowHeight.value = window.innerHeight
|
||||
}
|
||||
getWindowResize()
|
||||
window.addEventListener('resize', getWindowResize)
|
||||
nextTick(() => {
|
||||
const previewImg = document.getElementById('previewImg');
|
||||
// console.log(previewImg)
|
||||
let offsetHeight = previewImg?.offsetHeight
|
||||
// console.log(offsetHeight)
|
||||
if (offsetHeight > 750){
|
||||
// previewImg?.offsetHeight = 750
|
||||
}
|
||||
})
|
||||
|
||||
// dialogWidth.value=document.getElementById('previewImg')?.offsetWidth||1500
|
||||
// dialogWidth.value=document.getElementById('previewImg')?.offsetHeight||750
|
||||
|
||||
</script>
|
||||
|
||||
<style lang="scss">
|
||||
.img-preview {
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
overflow-y: auto;
|
||||
overflow-x: auto;
|
||||
&::-webkit-scrollbar {
|
||||
width: 6px;
|
||||
height: 6px;
|
||||
}
|
||||
|
||||
// 滚动条轨道
|
||||
&::-webkit-scrollbar-track {
|
||||
background: rgb(239, 239, 239);
|
||||
border-radius: 2px;
|
||||
}
|
||||
|
||||
// 小滑块
|
||||
&::-webkit-scrollbar-thumb {
|
||||
background: rgba(80, 81, 82, 0.29);
|
||||
border-radius: 10px;
|
||||
}
|
||||
}
|
||||
|
||||
</style>
|
||||
49
src/components/filePreview/PdfPreview.vue
Normal file
@@ -0,0 +1,49 @@
|
||||
<template>
|
||||
<!-- <iframe height="650px" width="100%" :src="fileUrl" frameborder="0"></iframe>-->
|
||||
<vue-pdf-app style="height: 100vh; width: 100vw" :pdf="fileUrl" :config="pdfPreviewConfig"></vue-pdf-app>
|
||||
</template>
|
||||
|
||||
<script setup lang="jsx">
|
||||
import VuePdfApp from "vue3-pdf-app";
|
||||
import "vue3-pdf-app/dist/icons/main.css";
|
||||
|
||||
const pdfPreviewConfig = ref({
|
||||
sidebar: false,//左侧目录展示
|
||||
secondaryToolbar: false,//二级工具栏
|
||||
toolbar: false,//工具栏显示
|
||||
errorWrapper: false,
|
||||
})
|
||||
const props = defineProps({
|
||||
fileUrl: {
|
||||
type: String,
|
||||
default: ''
|
||||
}
|
||||
})
|
||||
</script>
|
||||
|
||||
<style lang="scss">
|
||||
#vuePdfApp {
|
||||
width: auto !important;
|
||||
height: 650px !important;
|
||||
}
|
||||
|
||||
#viewerContainer {
|
||||
&::-webkit-scrollbar {
|
||||
width: 6px;
|
||||
height: 6px;
|
||||
}
|
||||
|
||||
// 滚动条轨道
|
||||
&::-webkit-scrollbar-track {
|
||||
background: rgb(239, 239, 239);
|
||||
border-radius: 2px;
|
||||
}
|
||||
|
||||
// 小滑块
|
||||
&::-webkit-scrollbar-thumb {
|
||||
background: rgba(80, 81, 82, 0.29);
|
||||
border-radius: 10px;
|
||||
}
|
||||
|
||||
}
|
||||
</style>
|
||||
28
src/components/filePreview/PptPreview.vue
Normal file
@@ -0,0 +1,28 @@
|
||||
<template>
|
||||
<div id="pptx" ></div>
|
||||
</template>
|
||||
|
||||
<script setup >
|
||||
const props = defineProps({
|
||||
fileUrl: {
|
||||
type: String,
|
||||
default: ''
|
||||
},
|
||||
fullscreen: {
|
||||
type: Boolean,
|
||||
default:false
|
||||
}
|
||||
})
|
||||
// js部分 jquery已在index.html中引入 无需另外安装
|
||||
const handlePPtx = () => {
|
||||
$("#pptx").pptxToHtml({
|
||||
pptxFileUrl: props.fileUrl, //pptx文件地址
|
||||
slidesScale: "100%",
|
||||
});
|
||||
}
|
||||
handlePPtx()
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
|
||||
</style>
|
||||
78
src/components/filePreview/index.vue
Normal file
@@ -0,0 +1,78 @@
|
||||
<template>
|
||||
<div class="file-preview">
|
||||
<el-dialog id="dialog" :border="false" width="1200" :style="{height: fullscreen?'':'650px;'}" top="10vh"
|
||||
:fullscreen="fullscreen"
|
||||
:title="fileName" :show-close="true" :visible.sync="showPreview" v-model="showPreview"
|
||||
:append-to-body="false"
|
||||
:close-on-click-modal="true"
|
||||
>
|
||||
<!-- <ppt-preview :file-url="fileUrl" :fullscreen="fullscreen" v-if="fileType === 'ppt'||fileType === 'pptx'"/>-->
|
||||
<pdf-preview :file-url="fileUrl" :fullscreen="fullscreen" v-if="fileType === 'pdf'"/>
|
||||
<docx-preview :file-url="fileUrl" :fullscreen="fullscreen" v-if="fileType === 'docx'"/>
|
||||
<image-preview :fileUrl="fileUrl" :fullscreen="fullscreen" :fileName="fileName" v-if="checkImgType(fileType)"/>
|
||||
</el-dialog>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import {ElNotification} from "element-plus";
|
||||
|
||||
const emit = defineEmits(["update:fileUrl"])
|
||||
const props = defineProps({
|
||||
fileUrl: {
|
||||
type: String,
|
||||
default: ''
|
||||
},
|
||||
fileType: {
|
||||
type: String,
|
||||
default: ''
|
||||
},
|
||||
fileName: {
|
||||
type: String,
|
||||
default: ''
|
||||
},
|
||||
//弹窗是否铺满全屏
|
||||
fullscreen: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
}
|
||||
})
|
||||
const showPreview = ref(true)
|
||||
// console.info("🚀 ~method:fileType -----", props.fileType)
|
||||
|
||||
const checkImgType=(fileType)=>{
|
||||
return fileType == 'png' || fileType == 'jpg' || fileType == 'jpeg' || fileType == 'ico' || fileType == 'PNG' || fileType == 'JPG';
|
||||
}
|
||||
// console.info("🚀 ~method:‘checkImgType(props.fileType) -----", checkImgType(props.fileType))
|
||||
if(props.fileType!=='pdf'&&props.fileType!=='docx'&&!checkImgType(props.fileType)){
|
||||
showPreview.value=false
|
||||
ElNotification({
|
||||
title: '提示',
|
||||
message: props.fileName+' 文件不支持预览!',
|
||||
type: 'error'
|
||||
})
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.file-preview {
|
||||
.el-overlay-dialog {
|
||||
left: 0 !important;
|
||||
|
||||
}
|
||||
|
||||
.el-dialog__headerbtn {
|
||||
.el-dialog__close {
|
||||
font-size: 30px;
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
.el-dialog__body {
|
||||
overflow: hidden;
|
||||
|
||||
padding: 0 !important;
|
||||
}
|
||||
}
|
||||
|
||||
</style>
|
||||
@@ -1,10 +1,14 @@
|
||||
<template>
|
||||
<baseTitle title="公司详情"></baseTitle>
|
||||
<fv-Form :schema="schema" @getInstance="(e)=>form = e"></fv-Form>
|
||||
<UserPicker :multiple="false" ref="presidentNamePicker" @ok="editPresident"></UserPicker>
|
||||
<UserPicker :multiple="false" ref="generalManagerNamePicker" @ok="editGeneralManager"></UserPicker>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import {getCompanyDetail} from "@/api/subsidiary";
|
||||
<script setup lang="jsx">
|
||||
import UserPicker from '@/views/workflow/process/common/UserPicker.vue';
|
||||
import Ttsup from '@/views/system/department/components/ToolToShowUserPicker.vue'
|
||||
import {getCompanyDetail,setCompanyLeader} from "@/api/subsidiary";
|
||||
const props=defineProps({
|
||||
value:{
|
||||
type:String,
|
||||
@@ -12,6 +16,12 @@ const props=defineProps({
|
||||
}
|
||||
})
|
||||
const form = ref()
|
||||
const presidentName = ref()
|
||||
const presidentIds = ref()
|
||||
const generalManagerName = ref()
|
||||
const presidentNamePicker = ref()
|
||||
const generalManagerNamePicker = ref()
|
||||
const generalManagerIds = ref()
|
||||
const schema = reactive([
|
||||
{
|
||||
label: '公司名称:',
|
||||
@@ -21,6 +31,17 @@ const schema = reactive([
|
||||
label: '公司编码:',
|
||||
prop: 'companyCode'
|
||||
},
|
||||
{
|
||||
label: '董事长:',
|
||||
prop: 'presidentIds',
|
||||
component: ()=><Ttsup modelValue={presidentName.value} onClick={()=>{presidentNamePicker.value.showUserPicker()} } />
|
||||
|
||||
},
|
||||
{
|
||||
label: '总经理:',
|
||||
prop: 'generalManagerIds',
|
||||
component: ()=><Ttsup modelValue={generalManagerName.value} onClick={()=>{generalManagerNamePicker.value.showUserPicker()} } />
|
||||
},
|
||||
{
|
||||
label: '创建时间:',
|
||||
prop: 'createTime'
|
||||
@@ -35,10 +56,62 @@ const _value = computed({
|
||||
emit('update:value', value)
|
||||
}
|
||||
})
|
||||
const editPresident = (list) => {
|
||||
const arr = list.map(item=>item.name)
|
||||
presidentIds.value = list.map(item=>item.id)
|
||||
presidentName.value = arr.join(',')
|
||||
setDeptmentInfo({
|
||||
companyId: _value.value,
|
||||
presidentIds: presidentIds.value,
|
||||
generalManagerIds: generalManagerIds.value
|
||||
})
|
||||
}
|
||||
|
||||
const editGeneralManager = (list) => {
|
||||
const arr = list.map(item=>item.name)
|
||||
generalManagerIds.value = list.map(item=>item.id)
|
||||
generalManagerName.value = arr.join(',')
|
||||
setDeptmentInfo({
|
||||
companyId: _value.value,
|
||||
presidentIds: presidentIds.value,
|
||||
generalManagerIds: generalManagerIds.value
|
||||
})
|
||||
}
|
||||
|
||||
const setDeptmentInfo = async ({companyId = [], presidentIds = [], generalManagerIds = [] }) => {
|
||||
const params = {
|
||||
presidentIds,
|
||||
generalManagerIds,
|
||||
companyId,
|
||||
}
|
||||
const res = await setCompanyLeader(params)
|
||||
// console.log(res.data);
|
||||
}
|
||||
const getInfo = async () => {
|
||||
const { data } = await getCompanyDetail(_value.value)
|
||||
form.value.setValues(data)
|
||||
const params = {
|
||||
companyName: data.companyName,
|
||||
companyCode: data.companyCode,
|
||||
createTime: data.createTime
|
||||
}
|
||||
presidentIds.value = data.presidentIds
|
||||
generalManagerIds.value = data.generalManagerIds
|
||||
params.presidentIds = formatIdsToNames(data.presidentIds, data.presidentInfo, 'userId', 'nickName')
|
||||
presidentName.value = params.presidentIds
|
||||
params.generalManagerIds = formatIdsToNames(data.generalManagerIds, data.generalManagerInfo, 'userId', 'nickName')
|
||||
generalManagerName.value = params.generalManagerIds
|
||||
form.value.setValues(params)
|
||||
}
|
||||
|
||||
const formatIdsToNames = (ids, infoList, key, viewKey) => {
|
||||
const resArr = []
|
||||
if(!ids?.length) return
|
||||
ids.forEach(item=>{
|
||||
infoList.forEach(v=>{
|
||||
item == v[key] && resArr.push(v[viewKey])
|
||||
})
|
||||
})
|
||||
return resArr.join(',')
|
||||
}
|
||||
|
||||
getInfo()
|
||||
|
||||
@@ -3,9 +3,9 @@
|
||||
<fv-Form :schema="companySchema" @getInstance="(e)=>companyForm = e"></fv-Form>
|
||||
<baseTitle title="部门详情"></baseTitle>
|
||||
<fv-Form :schema="schema" @getInstance="(e)=>form = e"></fv-Form>
|
||||
<UserPicker ref="usrPickershipIds" @ok="editshipIds"></UserPicker>
|
||||
<UserPicker ref="usrPickerHeadIds" @ok="editheadIds"></UserPicker>
|
||||
<UserPicker ref="departmentalDeputyIds" @ok="editdeputyIds"></UserPicker>
|
||||
<UserPicker :multiple="false" ref="usrPickershipIds" @ok="editshipIds"></UserPicker>
|
||||
<UserPicker :multiple="false" ref="usrPickerHeadIds" @ok="editheadIds"></UserPicker>
|
||||
<UserPicker :multiple="false" ref="usrPickerDeputyIds" @ok="editdeputyIds"></UserPicker>
|
||||
</template>
|
||||
|
||||
<script setup lang="jsx">
|
||||
@@ -65,7 +65,7 @@ const schema = reactive([
|
||||
{
|
||||
label: '部门副职用户:',
|
||||
prop: 'departmentalDeputyIds',
|
||||
component: ()=><Ttsup modelValue={departmentalDeputyNames.value} onClick={()=>{departmentalDeputyIds.value.showUserPicker()} } />
|
||||
component: ()=><Ttsup modelValue={departmentalDeputyNames.value} onClick={()=>{usrPickerDeputyIds.value.showUserPicker()} } />
|
||||
},
|
||||
{
|
||||
label: '创建时间:',
|
||||
|
||||
@@ -1,43 +1,81 @@
|
||||
<template>
|
||||
<baseTitle title="基础信息"></baseTitle>
|
||||
<fvForm :schema="schema" @getInstance="(e)=>baseForm = e"></fvForm>
|
||||
<div class="steps-box">
|
||||
<el-steps v-if="stepsShow" :active="localActive" finish-status="success">
|
||||
<el-step
|
||||
v-for="(item, index) in localSteps"
|
||||
:key="item.key"
|
||||
:title="item.title"
|
||||
:class="stepClass(index)"
|
||||
@click="handleStep(item.key, index)"
|
||||
|
||||
>
|
||||
<template #icon>
|
||||
<el-icon style="font-size: 20px;" :class="index == localActive ? 'is-active' : 'is-end'"
|
||||
v-if="localStepSuccess.includes(index)">
|
||||
<SuccessFilled/>
|
||||
</el-icon>
|
||||
<el-icon style="font-size: 20px; color: gray;" v-else>
|
||||
<WarningFilled/>
|
||||
</el-icon>
|
||||
</template>
|
||||
</el-step>
|
||||
</el-steps>
|
||||
</div>
|
||||
<!-- 步骤内容 -->
|
||||
<div>
|
||||
<slot name="content" :localActive="localActive"></slot>
|
||||
<!-- <template v-for="(item, index) in stepList" :key="item.key">
|
||||
<component v-if="localActive == index" v-bind="item.props || {}" :is="item.component" />
|
||||
</template> -->
|
||||
<div style="padding: 0 30px" id="printBox">
|
||||
<div style="display: flex;justify-content: space-between">
|
||||
<baseTitle title="项目基本信息"></baseTitle>
|
||||
<div class="oper-page-btn" :style="{marginRight:taskId? '145px':editShow?mode=='submit'?'145px':'170px':'0'}">
|
||||
<el-button v-print="print" color="#ded0b2" icon="Printer" @click="handlePrint(print)"> 打印</el-button>
|
||||
</div>
|
||||
</div>
|
||||
<fvForm :schema="schema" @getInstance="(e)=>baseForm = e" label-position="left" label-width="left"
|
||||
style="margin-left: 15px"></fvForm>
|
||||
<div class="steps-box">
|
||||
<el-steps v-if="stepsShow" :active="localActive" finish-status="success">
|
||||
<el-step
|
||||
v-for="(item, index) in localSteps"
|
||||
:key="item.key"
|
||||
:title="item.title"
|
||||
:class="stepClass(index)"
|
||||
@click="handleStep(item.key, index)"
|
||||
>
|
||||
<template #icon>
|
||||
<el-icon style="font-size: 20px;" :class="index == localActive ? 'is-active' : 'is-end'"
|
||||
v-if="localStepSuccess.includes(index)">
|
||||
<SuccessFilled/>
|
||||
</el-icon>
|
||||
<el-icon style="font-size: 20px; color: gray;" v-else>
|
||||
<WarningFilled/>
|
||||
</el-icon>
|
||||
</template>
|
||||
</el-step>
|
||||
</el-steps>
|
||||
</div>
|
||||
<!-- 步骤内容 -->
|
||||
<div>
|
||||
<slot name="content" :localActive="localActive"></slot>
|
||||
<!-- <template v-for="(item, index) in stepList" :key="item.key">
|
||||
<component v-if="localActive == index" v-bind="item.props || {}" :is="item.component" />
|
||||
</template> -->
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup lang="jsx">
|
||||
import {ElLoading, ElNotification} from 'element-plus';
|
||||
import {computed, onMounted, reactive, ref, watchEffect} from 'vue';
|
||||
import {useRoute} from 'vue-router';
|
||||
import {getBaseInfoApi} from './api';
|
||||
|
||||
import {useCacheStore} from '@/stores/cache.js'
|
||||
|
||||
import {toThousands} from '@/utils/changePrice.js'
|
||||
|
||||
const print = ref({
|
||||
id: 'printBox',//这里的id就是上面我们的打印区域id,实现指哪打哪
|
||||
popTitle: '配置页眉标题', // 打印配置页上方的标题
|
||||
extraHead: '', // 最上方的头部文字,附加在head标签上的额外标签,使用逗号分割
|
||||
preview: false, // 是否启动预览模式,默认是false
|
||||
previewTitle: '预览的标题', // 打印预览的标题
|
||||
previewPrintBtnLabel: '预览结束,开始打印', // 打印预览的标题下方的按钮文本,点击可进入打印
|
||||
zIndex: 20002, // 预览窗口的z-index,默认是20002,最好比默认值更高
|
||||
previewBeforeOpenCallback() {
|
||||
console.log('正在加载预览窗口!');
|
||||
}, // 预览窗口打开之前的callback
|
||||
previewOpenCallback() {
|
||||
console.log('已经加载完预览窗口,预览打开了!')
|
||||
}, // 预览窗口打开时的callback
|
||||
beforeOpenCallback() {
|
||||
console.log('开始打印之前!')
|
||||
}, // 开始打印之前的callback
|
||||
openCallback() {
|
||||
console.log('执行打印了!')
|
||||
}, // 调用打印时的callback
|
||||
closeCallback() {
|
||||
console.log('关闭了打印工具!')
|
||||
emits('closePrint')
|
||||
}, // 关闭打印的callback(无法区分确认or取消)
|
||||
clickMounted() {
|
||||
console.log('点击v-print绑定的按钮了!')
|
||||
},
|
||||
})
|
||||
|
||||
const props = defineProps({
|
||||
// 步骤对应内容list
|
||||
stepList: {
|
||||
@@ -58,19 +96,29 @@ const props = defineProps({
|
||||
reportType: {
|
||||
type: String,
|
||||
default: ''
|
||||
},
|
||||
//是否显示审批驳回按钮
|
||||
taskId: {
|
||||
type: String,
|
||||
default: ''
|
||||
},
|
||||
//当项目详情是编辑模式时按钮位置
|
||||
editShow: {
|
||||
type: String,
|
||||
default: ''
|
||||
},
|
||||
//当项目详情是提交模式还是重新提交时按钮位置
|
||||
mode: {
|
||||
type: String,
|
||||
default: ''
|
||||
}
|
||||
})
|
||||
|
||||
const route = useRoute()
|
||||
|
||||
const emits = defineEmits(['stepChange', 'setDetail'])
|
||||
|
||||
const cacheStore = useCacheStore()
|
||||
const emits = defineEmits(['stepChange', 'setDetail', 'openPrint'])
|
||||
const localData = reactive({})
|
||||
|
||||
const localActive = ref(0) // 当前激活步骤
|
||||
|
||||
const stepsShow = ref(false)
|
||||
|
||||
const localSteps = ref([
|
||||
{
|
||||
title: '需求征集',
|
||||
@@ -84,6 +132,10 @@ const localSteps = ref([
|
||||
title: '项目立项',
|
||||
key: 'approve',
|
||||
},
|
||||
{
|
||||
title: '项目实施',
|
||||
key: 'implement',
|
||||
},
|
||||
{
|
||||
title: '项目验收',
|
||||
key: 'execute',
|
||||
@@ -97,46 +149,278 @@ const localSteps = ref([
|
||||
// key: 'end',
|
||||
// },
|
||||
])
|
||||
|
||||
const baseForm = ref()
|
||||
|
||||
const baseFormData = ref([])
|
||||
const schema = computed(() => {
|
||||
return [
|
||||
{
|
||||
label: '承办单位',
|
||||
prop: 'affiliatedCompany',
|
||||
colProps: {
|
||||
span: 6
|
||||
}
|
||||
},
|
||||
{
|
||||
label: '项目名称',
|
||||
prop: 'projectName',
|
||||
colProps: {
|
||||
span: 8
|
||||
span: 6
|
||||
}
|
||||
},
|
||||
|
||||
{
|
||||
label: '开始时间',
|
||||
prop: 'startTime',
|
||||
colProps: {
|
||||
span: 6
|
||||
}
|
||||
},
|
||||
{
|
||||
label: '征集公司',
|
||||
prop: 'affiliatedCompany',
|
||||
label: '结束时间',
|
||||
prop: 'endTime',
|
||||
colProps: {
|
||||
span: 8
|
||||
span: 6
|
||||
}
|
||||
},
|
||||
{
|
||||
label: '征集名称',
|
||||
prop: 'requirementName',
|
||||
label: '项目类型',
|
||||
prop: 'projectType',
|
||||
colProps: {
|
||||
span: 8
|
||||
span: 6
|
||||
},
|
||||
component: () => (
|
||||
<div>
|
||||
{
|
||||
baseFormData.value?.projectType ?
|
||||
<span>{filterDict(cacheStore.getDict('project_type'), baseFormData.value?.projectType)}</span>
|
||||
: <span>{'--'}</span>
|
||||
}
|
||||
</div>
|
||||
)
|
||||
},
|
||||
{
|
||||
label: '研发主体',
|
||||
prop: 'rdSubject',
|
||||
colProps: {
|
||||
span: 6
|
||||
},
|
||||
component: () => (
|
||||
<div>
|
||||
{
|
||||
baseFormData.value?.rdSubject ?
|
||||
<span>{filterDict(cacheStore.getDict('rd_subject'), baseFormData.value?.rdSubject)}</span>
|
||||
: <span>{'--'}</span>
|
||||
}
|
||||
</div>
|
||||
)
|
||||
},
|
||||
{
|
||||
label: '出资类型',
|
||||
prop: 'investmentType',
|
||||
colProps: {
|
||||
span: 6
|
||||
},
|
||||
component: () => (
|
||||
<div>
|
||||
{
|
||||
baseFormData.value?.investmentType ?
|
||||
<span>{filterDict(cacheStore.getDict('invest_type'), baseFormData.value?.investmentType)}</span>
|
||||
: <span>{'--'}</span>
|
||||
}
|
||||
</div>
|
||||
)
|
||||
},
|
||||
{
|
||||
label: '业务板块',
|
||||
prop: 'businessSegment',
|
||||
colProps: {
|
||||
span: 6
|
||||
},
|
||||
component: () => (
|
||||
<div>
|
||||
{
|
||||
baseFormData.value?.businessSegment ?
|
||||
<span>{filterDict(cacheStore.getDict('business_segment'), baseFormData.value?.businessSegment)}</span>
|
||||
: <span>{'--'}</span>
|
||||
}
|
||||
</div>
|
||||
)
|
||||
},
|
||||
{
|
||||
label: '标准制定',
|
||||
prop: 'technicalStandard',
|
||||
colProps: {
|
||||
span: 6
|
||||
},
|
||||
component: () => (
|
||||
<div>
|
||||
{
|
||||
baseFormData.value?.technicalStandard ?
|
||||
<span>{filterDict(cacheStore.getDict('technical_standard'), baseFormData.value?.technicalStandard)}</span>
|
||||
: <span>{'--'}</span>
|
||||
}
|
||||
</div>
|
||||
)
|
||||
},
|
||||
{
|
||||
label: '项目影响',
|
||||
prop: 'projectImpact',
|
||||
colProps: {
|
||||
span: 6
|
||||
},
|
||||
component: () => (
|
||||
<div>
|
||||
{
|
||||
baseFormData.value?.projectImpact ?
|
||||
<span>{filterDict(cacheStore.getDict('project_impact'), baseFormData.value?.projectImpact)}</span>
|
||||
: <span>{'--'}</span>
|
||||
}
|
||||
</div>
|
||||
)
|
||||
},
|
||||
{
|
||||
label: '预估经费预算(元)',
|
||||
prop: 'economicEstimate',
|
||||
colProps: {
|
||||
span: 6
|
||||
},
|
||||
component: () => (
|
||||
<div>
|
||||
{
|
||||
baseFormData.value?.economicEstimate ?
|
||||
<span>{toThousands(baseFormData.value?.economicEstimate)}</span>
|
||||
: <span>{'--'}</span>
|
||||
}
|
||||
</div>
|
||||
)
|
||||
},
|
||||
{
|
||||
label: '实际经费预算(元)',
|
||||
prop: 'actualEconomicEstimate',
|
||||
colProps: {
|
||||
span: 6
|
||||
},
|
||||
component: () => (
|
||||
<div>
|
||||
{
|
||||
baseFormData.value?.actualEconomicEstimate ?
|
||||
<span>{toThousands(baseFormData.value?.actualEconomicEstimate)}</span>
|
||||
: <span>{'--'}</span>
|
||||
}
|
||||
</div>
|
||||
)
|
||||
},
|
||||
{
|
||||
label: '产学研联合',
|
||||
prop: 'industryUniversityResearch',
|
||||
colProps: {
|
||||
span: 6
|
||||
},
|
||||
component: () => (
|
||||
<div>
|
||||
{
|
||||
baseFormData.value?.industryUniversityResearch ?
|
||||
<span>{filterDict(cacheStore.getDict('industry_university'), baseFormData.value?.industryUniversityResearch)}</span>
|
||||
: <span>{'--'}</span>
|
||||
}
|
||||
</div>
|
||||
)
|
||||
},
|
||||
{
|
||||
label: '开展政府申报',
|
||||
prop: 'governmentDeclaration',
|
||||
colProps: {
|
||||
span: 6
|
||||
},
|
||||
component: () => (
|
||||
<div>
|
||||
{
|
||||
baseFormData.value?.governmentDeclaration ?
|
||||
<span>{filterDict(cacheStore.getDict('government_declaration'), baseFormData.value?.governmentDeclaration)}</span>
|
||||
: <span>{'--'}</span>
|
||||
}
|
||||
</div>
|
||||
)
|
||||
},
|
||||
{
|
||||
label: '所属专项资金',
|
||||
prop: 'specialFund',
|
||||
colProps: {
|
||||
span: 6
|
||||
}
|
||||
},
|
||||
{
|
||||
label: '征集描述',
|
||||
prop: 'collectExplain',
|
||||
label: '预估专项资金(元)',
|
||||
prop: 'forecastSpecialFundAmount',
|
||||
colProps: {
|
||||
span: 24
|
||||
span: 6
|
||||
},
|
||||
component: () => (
|
||||
<div>
|
||||
{
|
||||
baseFormData.value?.forecastSpecialFundAmount ?
|
||||
<span>{toThousands(baseFormData.value?.forecastSpecialFundAmount)}</span>
|
||||
: <span>{'--'}</span>
|
||||
}
|
||||
</div>
|
||||
)
|
||||
},
|
||||
{
|
||||
label: '实际专项资金(元)',
|
||||
prop: 'specialFundAmount',
|
||||
colProps: {
|
||||
span: 6
|
||||
},
|
||||
component: () => (
|
||||
<div>
|
||||
{
|
||||
baseFormData.value?.specialFundAmount ?
|
||||
<span>{toThousands(baseFormData.value?.specialFundAmount)}</span>
|
||||
: <span>{'--'}</span>
|
||||
}
|
||||
</div>
|
||||
)
|
||||
},
|
||||
{
|
||||
label: '是否在预算内',
|
||||
prop: 'isWithinBudget',
|
||||
colProps: {
|
||||
span: 6
|
||||
},
|
||||
component: () => (
|
||||
<div>
|
||||
{
|
||||
baseFormData.value?.isWithinBudget!=null ? baseFormData.value?.isWithinBudget?
|
||||
<span>{'预算内'}</span>
|
||||
: <span>{'预算外'}</span>:'--'
|
||||
}
|
||||
</div>
|
||||
)
|
||||
},
|
||||
{
|
||||
label: '部门分管领导',
|
||||
prop: 'optionalChargeLeadership',
|
||||
colProps: {
|
||||
span: 6
|
||||
}
|
||||
},
|
||||
{
|
||||
label: '主项目',
|
||||
prop: 'masterProjectName',
|
||||
colProps: {
|
||||
span: 6
|
||||
}
|
||||
}
|
||||
]
|
||||
})
|
||||
|
||||
const localStepSuccess = ref([])
|
||||
|
||||
const handlePrint = (print) => {
|
||||
emits('openPrint', print)
|
||||
}
|
||||
// 格式化详情步骤条
|
||||
const formatProcedure = (data) => {
|
||||
// console.info("🚀 ~method:formatProcedure -----", data)
|
||||
let arr = []
|
||||
if (data instanceof Array) {
|
||||
data.forEach(item => {
|
||||
@@ -148,12 +432,15 @@ const formatProcedure = (data) => {
|
||||
case '20':
|
||||
arr.push(1)
|
||||
break
|
||||
case '40':
|
||||
case '30':
|
||||
arr.push(2)
|
||||
break
|
||||
case '50':
|
||||
case '40':
|
||||
arr.push(3)
|
||||
break
|
||||
case '50':
|
||||
arr.push(4)
|
||||
break
|
||||
}
|
||||
} else {
|
||||
switch (item) {
|
||||
@@ -166,12 +453,15 @@ const formatProcedure = (data) => {
|
||||
case '20':
|
||||
arr.push(2)
|
||||
break
|
||||
case '40':
|
||||
case '30':
|
||||
arr.push(3)
|
||||
break
|
||||
case '50':
|
||||
case '40':
|
||||
arr.push(4)
|
||||
break
|
||||
case '50':
|
||||
arr.push(5)
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
@@ -179,7 +469,31 @@ const formatProcedure = (data) => {
|
||||
}
|
||||
return arr
|
||||
}
|
||||
|
||||
//匹配字典值,返回对应值的字典标签
|
||||
const filterDict = (data, value) => {
|
||||
if (data === undefined || value === undefined) return;
|
||||
let label = ''
|
||||
let result = []
|
||||
if (value instanceof Array) {
|
||||
value.forEach(item1 => {
|
||||
data.find(item => {
|
||||
if (item.value == item1) {
|
||||
result.push(item.label)
|
||||
}
|
||||
})
|
||||
})
|
||||
label = result.map(item => item).join(',')
|
||||
} else {
|
||||
if (data instanceof Array) {
|
||||
data.find(item => {
|
||||
if (item.value == value) {
|
||||
label = item.label
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
return label
|
||||
}
|
||||
// 反向格式化
|
||||
const formatReProcedure = (data) => {
|
||||
let arr = []
|
||||
@@ -195,12 +509,13 @@ const formatReProcedure = (data) => {
|
||||
case 2:
|
||||
arr.push('20')
|
||||
break
|
||||
// case 3: arr.push('30')
|
||||
// break
|
||||
case 3:
|
||||
arr.push('40')
|
||||
arr.push('30')
|
||||
break
|
||||
case 4:
|
||||
arr.push('40')
|
||||
break
|
||||
case 5:
|
||||
arr.push('50')
|
||||
break
|
||||
}
|
||||
@@ -219,9 +534,9 @@ const formatActive = (val) => {
|
||||
newVal == 0 && (active = '00')
|
||||
newVal == 1 && (active = '10')
|
||||
newVal == 2 && (active = '20')
|
||||
// val == 3 && (active = '30')
|
||||
newVal == 3 && (active = '40')
|
||||
newVal == 4 && (active = '50')
|
||||
newVal == 3 && (active = '30')
|
||||
newVal == 4 && (active = '40')
|
||||
newVal == 5 && (active = '50')
|
||||
return active
|
||||
}
|
||||
|
||||
@@ -245,9 +560,12 @@ const handleStep = (key, index) => {
|
||||
active = '20'
|
||||
break
|
||||
case 2:
|
||||
active = '40'
|
||||
active = '30'
|
||||
break
|
||||
case 3:
|
||||
active = '40'
|
||||
break
|
||||
case 4:
|
||||
active = '50'
|
||||
break
|
||||
}
|
||||
@@ -263,9 +581,12 @@ const handleStep = (key, index) => {
|
||||
active = '20'
|
||||
break
|
||||
case 3:
|
||||
active = '40'
|
||||
active = '30'
|
||||
break
|
||||
case 4:
|
||||
active = '40'
|
||||
break
|
||||
case 5:
|
||||
active = '50'
|
||||
break
|
||||
}
|
||||
@@ -286,7 +607,10 @@ const getBaseInfo = async () => {
|
||||
try {
|
||||
const {code, data} = await getBaseInfoApi(route.query.projectId)
|
||||
// console.log('data.procedure', data.procedure, route.query.step)
|
||||
if (route.query.step === '40') {
|
||||
if (route.query.step === '30' || route.query.step === '40') {
|
||||
if (data.procedure.indexOf('30') == -1) {
|
||||
data.procedure.push('30')
|
||||
}
|
||||
if (data.procedure.indexOf('40') == -1) {
|
||||
data.procedure.push('40')
|
||||
}
|
||||
@@ -297,6 +621,8 @@ const getBaseInfo = async () => {
|
||||
}
|
||||
localStepSuccess.value = formatProcedure(data.procedure)
|
||||
baseForm.value.setValues(data)
|
||||
baseFormData.value = data
|
||||
emits('getBasicData', data)
|
||||
emits('setDetail', formatActive(localActive.value))
|
||||
loading.close()
|
||||
nextTick(() => {
|
||||
@@ -322,7 +648,7 @@ watchEffect(() => {
|
||||
if (props.reportType === 'direct') {
|
||||
let steps = []
|
||||
for (const step of localSteps.value) {
|
||||
if (step.key !== 'collect'){
|
||||
if (step.key !== 'collect') {
|
||||
steps.push(step)
|
||||
}
|
||||
}
|
||||
@@ -333,7 +659,7 @@ watchEffect(() => {
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.steps-box {
|
||||
padding: 10px 0;
|
||||
//padding: 10px 0;
|
||||
}
|
||||
|
||||
.step-success {
|
||||
@@ -359,4 +685,5 @@ watchEffect(() => {
|
||||
:deep(.el-step__head.is-success) {
|
||||
border-color: #A8abb2;
|
||||
}
|
||||
|
||||
</style>
|
||||
|
||||
@@ -11,12 +11,12 @@
|
||||
v-bind="item.colProps || { span: 12}"
|
||||
:key="item.prop"
|
||||
>
|
||||
<el-form-item
|
||||
<el-form-item
|
||||
v-bind="item"
|
||||
:key="item.prop"
|
||||
>
|
||||
<template #default>
|
||||
<component
|
||||
<component
|
||||
v-if="item.component"
|
||||
:is="item.component"
|
||||
v-bind="item.props || {}"
|
||||
@@ -105,4 +105,4 @@ defineExpose({ getValues, setValues, validate, resetFields, formInstance, form }
|
||||
|
||||
<style lang="scss" scoped>
|
||||
|
||||
</style>
|
||||
</style>
|
||||
|
||||
@@ -5,6 +5,7 @@
|
||||
label-width="auto"
|
||||
ref="formInstance"
|
||||
class="search-form"
|
||||
@submit.prevent="getValues"
|
||||
>
|
||||
<el-row>
|
||||
<el-col
|
||||
@@ -24,12 +25,14 @@
|
||||
v-on="item.on || {}"
|
||||
v-model="form[item.prop]"
|
||||
@keyup.enter.native="getValues"
|
||||
@change="elChange"
|
||||
>
|
||||
</component>
|
||||
</template>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="filterConfig.length % 4 == 0 ? 4 : 6" class="btn-col">
|
||||
<!-- class="btn-col"-->
|
||||
<el-col :span="filterConfig.length % 4 == 0 ? 4 : 6" :offset="1">
|
||||
<el-form-item>
|
||||
<el-button v-if="searchConfig.length>=4" link type="primary" @click="showMore = !showMore">
|
||||
{{ showMore ? '收起' : '展开' }}
|
||||
@@ -49,6 +52,16 @@ const props = defineProps({
|
||||
searchConfig: {
|
||||
type: Array,
|
||||
default: []
|
||||
},
|
||||
//搜索参数
|
||||
searchProp: {
|
||||
type: String,
|
||||
default: ''
|
||||
},
|
||||
//搜索值
|
||||
searchValue: {
|
||||
type: String,
|
||||
default: ''
|
||||
}
|
||||
})
|
||||
|
||||
@@ -65,7 +78,10 @@ const filterConfig = computed(() => {
|
||||
})
|
||||
return arr.length >= 4 && showMore.value ? arr : arr.slice(0, 3)
|
||||
})
|
||||
|
||||
const setForm=(prop,value)=>{
|
||||
form.value[prop]=value
|
||||
return form.value;
|
||||
}
|
||||
// 搜索功能表单元素默认值
|
||||
// const setDefaultFormValues = () => {
|
||||
// filterConfig.value.forEach(item => {
|
||||
@@ -77,8 +93,17 @@ watchEffect(() => {
|
||||
if (filterConfig.value.length) {
|
||||
// setDefaultFormValues()
|
||||
}
|
||||
if(props.searchProp&&props.searchValue){
|
||||
setForm(props.searchProp,props.searchValue)
|
||||
}
|
||||
})
|
||||
|
||||
const elChange = () => {
|
||||
setTimeout(() => {
|
||||
getValues()
|
||||
}, 500)
|
||||
}
|
||||
|
||||
const getValues = () => {
|
||||
emits('search', form.value)
|
||||
return form.value
|
||||
@@ -110,4 +135,30 @@ onMounted(() => {
|
||||
justify-content: space-evenly;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
</style>
|
||||
<style lang="scss">
|
||||
.search-form{
|
||||
//绘制下拉选择框远程搜索时右侧的箭头
|
||||
.el-select {
|
||||
.el-select__wrapper {
|
||||
.el-select__suffix::before {
|
||||
content: "";
|
||||
width: 6px;
|
||||
height: 6px;
|
||||
border: solid #a8abb2;
|
||||
border-width: 0 0 1px 1px;
|
||||
transform: translate(-50%, -50%) rotate(-45deg);
|
||||
}
|
||||
}
|
||||
|
||||
.is-focused {
|
||||
.el-select__suffix::before {
|
||||
margin-top: 10px;
|
||||
transform: translate(-50%, -50%) rotate(-225deg) !important;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
</style>
|
||||
|
||||
@@ -1,5 +1,8 @@
|
||||
<template>
|
||||
<div class="fv-table-container">
|
||||
<el-button v-if="tableConfig.export && tableConfig.export.open&&changeExportPosition" @click="exportTable" color="#DED0B2"
|
||||
style="float: left;margin-right: 10px">导出
|
||||
</el-button>
|
||||
<!-- 表格头部按钮 -->
|
||||
<div class="fv-table-btn" v-if="tableConfig.btns">
|
||||
<div class="table-head-btn">
|
||||
@@ -15,11 +18,11 @@
|
||||
</el-button>
|
||||
</div>
|
||||
</div>
|
||||
<el-button v-if="tableConfig.export && tableConfig.export.open&&!changeExportPosition" @click="exportTable" color="#DED0B2"
|
||||
style="margin-bottom: 10px">导出
|
||||
</el-button>
|
||||
<!-- 列显示配置 -->
|
||||
<div v-if="isSettingCol" style="float: right">
|
||||
<el-button v-if="tableConfig.export && tableConfig.export.open" @click="exportTable" color="#DED0B2"
|
||||
style="margin-bottom: 10px">导出
|
||||
</el-button>
|
||||
<el-tooltip effect="dark" content="列配置" placement="bottom">
|
||||
<el-button ref="buttonRef" link>
|
||||
<el-icon size="18">
|
||||
@@ -59,7 +62,6 @@
|
||||
v-loading="localData.loading"
|
||||
:row-key="tableConfig?.rowKey || 'id'"
|
||||
v-bind="$attrs"
|
||||
table-layout="auto"
|
||||
:show-overflow-tooltip="true"
|
||||
highlight-current-row
|
||||
@selection-change="selectionChange"
|
||||
@@ -122,6 +124,11 @@ const props = defineProps({
|
||||
type: Boolean,
|
||||
default: true
|
||||
},
|
||||
//是否改变导出位置, 导出在btns前面
|
||||
changeExportPosition: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
},
|
||||
// 是否显示列配置
|
||||
isSettingCol: {
|
||||
type: Boolean,
|
||||
|
||||
@@ -115,6 +115,12 @@ const accountChange = (userId) => {
|
||||
authStore.userLogout()
|
||||
setToken(res.data)
|
||||
window.location.href = "/home"
|
||||
}else{
|
||||
ElNotification({
|
||||
title: '提示',
|
||||
message: res.msg,
|
||||
type: 'error'
|
||||
})
|
||||
}
|
||||
})
|
||||
}
|
||||
@@ -200,7 +206,7 @@ const handleLogout = () => {
|
||||
position: absolute;
|
||||
width: 280px;
|
||||
right: 0;
|
||||
z-index: 300;
|
||||
z-index: 3000;
|
||||
top: 54px;
|
||||
padding: 5px 0;
|
||||
border-radius: 4px;
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
<template>
|
||||
<div class="logo" ref="logo">
|
||||
<img src="../../assets/kylogo.png" alt="">
|
||||
<!-- <span v-if="!siderbarStore.isCollapse">科研管理平台</span> -->
|
||||
<!-- <span v-if="!siderbarStore.isCollapse">科技创新项目管理平台</span> -->
|
||||
<span v-if="!siderbarStore.isCollapse"></span>
|
||||
</div>
|
||||
<el-scrollbar :height="`calc(100vh - ${logoHeight}px)`" style="background-color: #ffffff">
|
||||
|
||||
@@ -1,7 +1,8 @@
|
||||
<template>
|
||||
<div class="link-box">
|
||||
<el-scrollbar noresize>
|
||||
<div>
|
||||
<el-scrollbar noresize height="36" >
|
||||
<!-- style="display: flex"-->
|
||||
<div >
|
||||
<router-link
|
||||
v-for="item in tagsViewStore.visitedViews"
|
||||
:key="item.path" :to="{ path: item.path, query: item.query }" class="tag"
|
||||
@@ -74,11 +75,13 @@ init()
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.link-box {
|
||||
//display: flex;
|
||||
position: relative;
|
||||
padding: 12px 0;
|
||||
line-height: 30px;
|
||||
line-height: 34px;
|
||||
|
||||
.tag {
|
||||
|
||||
padding: 6px;
|
||||
border: 1px solid darkgray;
|
||||
font-size: 13px;
|
||||
|
||||
@@ -19,6 +19,9 @@ import 'vite-plugin-svg-icons/register'
|
||||
import '@/assets/styles/index.scss'
|
||||
import '@/assets/styles/sidebar.scss'
|
||||
import '@/assets/styles/echartsEditor.scss'
|
||||
//引入
|
||||
import print from 'vue3-print-nb'
|
||||
//挂载
|
||||
|
||||
const app = createApp(App)
|
||||
for (const [key, component] of Object.entries(ElementPlusIconsVue)) {
|
||||
@@ -29,5 +32,5 @@ app.use(createPinia())
|
||||
app.use(router)
|
||||
app.directive('perm',hasPerm)
|
||||
app.directive('tabh',fixedHeight)
|
||||
|
||||
app.use(print)
|
||||
app.mount('#app')
|
||||
|
||||
@@ -35,11 +35,6 @@ const router = createRouter({
|
||||
name: 'specialFundDetailMobile',
|
||||
component: () => import('@/views/project-management/mobledetail/SpecialFundDetailMobile.vue')
|
||||
},
|
||||
{
|
||||
path: '/share/mobile',
|
||||
name: 'shareDetailMobile',
|
||||
component: () => import('@/views/project-management/mobledetail/ShareDetailMobile.vue')
|
||||
},
|
||||
{
|
||||
path: '/projectDemand/requirement/moblie',
|
||||
name: 'projectDemandRequirementMoblie',
|
||||
@@ -195,6 +190,24 @@ const router = createRouter({
|
||||
breadcrumb: false
|
||||
}
|
||||
},
|
||||
{
|
||||
path: '/todolist',
|
||||
name: 'Todolist',
|
||||
component: () => import('@/views/todoList/index.vue'),
|
||||
meta: {
|
||||
title: '待办',
|
||||
breadcrumb: false
|
||||
}
|
||||
},
|
||||
{
|
||||
path: '/donelist',
|
||||
name: 'Donelist',
|
||||
component: () => import('@/views/doneList/index.vue'),
|
||||
meta: {
|
||||
title: '已办',
|
||||
breadcrumb: false
|
||||
}
|
||||
},
|
||||
]
|
||||
},
|
||||
{
|
||||
|
||||
@@ -37,9 +37,11 @@ export const usePermisstionStroe = defineStore('permisstion', () => {
|
||||
if (res.code === 1000) {
|
||||
const sRouter = JSON.parse(JSON.stringify(res.data))
|
||||
const mData = JSON.parse(JSON.stringify(res.data))
|
||||
console.log(JSON.parse(JSON.stringify(sRouter)), 'sRouter');
|
||||
const firstFormat = setRouterLevel(JSON.parse(JSON.stringify(sRouter)))
|
||||
|
||||
console.log(firstFormat, 'firstFormat');
|
||||
asyncRouters.value = formatAsyncRouters(JSON.parse(JSON.stringify(firstFormat)))
|
||||
console.log('asyncRouters.value',firstFormat);
|
||||
menuList.value = [...menuList.value, ...generateMenu(mData)]
|
||||
addAsyncRouters(asyncRouters.value)
|
||||
isLoadRoutes.value = false
|
||||
@@ -52,16 +54,23 @@ export const usePermisstionStroe = defineStore('permisstion', () => {
|
||||
}
|
||||
|
||||
const setRouterLevel = (routers) => {
|
||||
|
||||
return routers.filter(item=>{
|
||||
if(item.component === 'Layout') {
|
||||
if(item.children) {
|
||||
// console.log("🚀 ~ file: item.children ", item.children )
|
||||
item.children.forEach(v=>{
|
||||
if(v.children) {
|
||||
slRouters.value = [...toRaw(slRouters.value), ...v.children]
|
||||
delete v.children
|
||||
// console.log("🚀 ~ file:item.children",item.children)
|
||||
// console.log("🚀 ~ file: v.children ", v.children )
|
||||
// slRouters.value = [ ...toRaw(v.children)]
|
||||
// delete v.children
|
||||
// slRouters.value = [ ...v.children]
|
||||
// return v.children
|
||||
item.children = [...item.children,...v.children]
|
||||
}
|
||||
})
|
||||
item.children = [...item.children, ...toRaw(slRouters.value)]
|
||||
|
||||
}
|
||||
}
|
||||
return true
|
||||
@@ -81,6 +90,7 @@ export const usePermisstionStroe = defineStore('permisstion', () => {
|
||||
}
|
||||
if (route.children !== null && route.children && route.children.length !== 0) {
|
||||
route.children = formatAsyncRouters(route.children)
|
||||
|
||||
}
|
||||
return true
|
||||
})
|
||||
@@ -90,6 +100,8 @@ export const usePermisstionStroe = defineStore('permisstion', () => {
|
||||
routers.forEach(route => {
|
||||
router.addRoute(route)
|
||||
})
|
||||
console.log("🚀 ~ file: ", routers)
|
||||
|
||||
}
|
||||
|
||||
const generateMenu = (routes) => {
|
||||
|
||||
@@ -59,7 +59,7 @@ export const useProcessStore = defineStore('process', () => {
|
||||
const getFormMap = () => {
|
||||
//表单映射对象
|
||||
const map = new Map();
|
||||
processData.value.formItems.forEach(item => itemToMap(map, item))
|
||||
processData.value.formItems?.forEach(item => itemToMap(map, item))
|
||||
return map
|
||||
}
|
||||
|
||||
|
||||
@@ -44,9 +44,9 @@ export const useTagsView = defineStore('tagsView',()=>{
|
||||
}
|
||||
|
||||
//删除其他标签页
|
||||
const delOtherVisitedViews = ({path,meta}) => {
|
||||
const delOtherVisitedViews = ({path,meta,query}) => {
|
||||
visitedViews.value = []
|
||||
visitedViews.value.push({path,meta})
|
||||
visitedViews.value.push({path,meta,query})
|
||||
toLastTagView(visitedViews)
|
||||
}
|
||||
|
||||
|
||||
@@ -33,11 +33,9 @@ export function downLoadExcel(url,params) {
|
||||
responseType: 'blob',
|
||||
headers: {'Authorization': getToken()}
|
||||
}).then(res => {
|
||||
console.log(res)
|
||||
try {
|
||||
resolveBlob(res, mimeMap.xlsx)
|
||||
}catch (e) {
|
||||
console.log(res)
|
||||
ElMessage.error(res.data.msg)
|
||||
}
|
||||
})
|
||||
@@ -55,7 +53,7 @@ export function resolveBlob(res, mimeType) {
|
||||
let reg = /fileName=([^&]+)/;
|
||||
let contentDisposition = decodeURI(res.headers['content-disposition'])
|
||||
let result = reg.exec(contentDisposition)
|
||||
console.log(result)
|
||||
// console.log(result)
|
||||
let fileName = result[1]
|
||||
fileName = fileName.replace(/\"/g, '')
|
||||
aLink.href = URL.createObjectURL(blob)
|
||||
@@ -63,4 +61,4 @@ export function resolveBlob(res, mimeType) {
|
||||
document.body.appendChild(aLink)
|
||||
aLink.click()
|
||||
document.body.appendChild(aLink)
|
||||
}
|
||||
}
|
||||
|
||||
298
src/views/article-management/add.vue
Normal file
@@ -0,0 +1,298 @@
|
||||
<template>
|
||||
<div v-loading="loading" class="add-block">
|
||||
<baseTitle title="文章信息录入"></baseTitle>
|
||||
<el-form :model="formData" ref="fundForm" :rules="rules" style="margin-left: 5px;margin-bottom: -18px">
|
||||
<el-row gutter="30">
|
||||
<el-col :span="6" style="margin-left: 10px">
|
||||
<el-form-item label="文章标题" prop="articleTitle">
|
||||
<el-input v-model="formData.articleTitle" placeholder="请输入文章标题" clearable></el-input>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="6">
|
||||
<el-form-item label="文章类型" prop="articleType">
|
||||
<el-select v-model="formData.articleType" placeholder="请选择文章类型" clearable filterable>
|
||||
<el-option
|
||||
v-for="item in cacheStore.getDict('article_type')"
|
||||
:key="item.value"
|
||||
:label="item.label"
|
||||
:value="item.value"
|
||||
/>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="6">
|
||||
<el-form-item label="发文单位" prop="remarks">
|
||||
<el-input v-model="formData.remarks" placeholder="请输入发文单位" clearable></el-input>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="24" style="margin-left: 10px">
|
||||
<el-form-item label="文章内容" prop="articleContent">
|
||||
<!-- link-->
|
||||
<Tinymce v-model:value="formData.articleContent"
|
||||
imageUrl="/workflow/process/file/upload" :height="500" v-if="showTinymce"
|
||||
:toolbar="['undo redo | styleselect | bold italic | alignleft aligncenter alignright alignjustify | bullist numlist outdent indent | image axupimgs']"/>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="24" style="margin-bottom: -10px">
|
||||
<el-form-item label="附件上传" prop="" style="margin-left: 20px;">
|
||||
<file-upload @getFile="getFiles"/>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="24" style="margin-left:90px;">
|
||||
|
||||
<!-- <el-form-item label="公告附件列表" prop=""-->
|
||||
<!-- style="display: flex;flex-direction: column;justify-content: flex-start;">-->
|
||||
<!-- <template #label>-->
|
||||
<!-- <div style="width: 100%;display: flex;align-items: center;justify-content: flex-start">-->
|
||||
<!-- <el-icon size="16">-->
|
||||
<!-- <Paperclip/>-->
|
||||
<!-- </el-icon>-->
|
||||
<!-- 公告附件列表-->
|
||||
<!-- </div>-->
|
||||
<!-- </template>-->
|
||||
<el-col :span="24" style="margin-left: -15px">
|
||||
<div style="display: flex;flex-direction: column">
|
||||
<div v-for="(item,index) in formData.fileList" style="display: flex;align-items: center;margin-bottom: 5px">
|
||||
附件{{ index + 1 }}: <a :href="item.url" style="color: #409eff;" class="a-style" target="_blank">{{ item.originalFileName }}</a>
|
||||
<el-icon size="18" style="margin:0 20px;cursor: pointer" color="#409eff" @click="handleDelete(item,index)">
|
||||
<CircleClose/>
|
||||
</el-icon>
|
||||
<el-button type="primary" link @click="handleDownload(item)" style="font-size: 16px;margin-left: 10px">下载</el-button>
|
||||
</div>
|
||||
</div>
|
||||
</el-col>
|
||||
<!-- </el-form-item>-->
|
||||
</el-col>
|
||||
</el-row>
|
||||
</el-form>
|
||||
<div class="oper-page-btn">
|
||||
<el-button color="#DED0B2" v-if="routerName === 'Article/add'" @click="handleSubmit(fundForm)">提交</el-button>
|
||||
<el-button color="#DED0B2" v-else @click="handleResubmit">提交</el-button>
|
||||
<el-button @click="handleBack">返回</el-button>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup lang="jsx">
|
||||
import {ElMessageBox, ElNotification} from "element-plus";
|
||||
import {addArticle, editArticle, getArticleDetail} from "@/api/article";
|
||||
import {useTagsView} from '@/stores/tagsview.js'
|
||||
import {useCacheStore} from "@/stores/cache.js";
|
||||
import {deleteFile, downloadFile} from "../../api/project-demand";
|
||||
import FileUpload from "../../components/FileUpload.vue";
|
||||
import Tinymce from "../../components/Tinymce.vue";
|
||||
|
||||
const cacheStore = useCacheStore();
|
||||
const tagsViewStore = useTagsView()
|
||||
const router = useRouter()
|
||||
const route = useRoute()
|
||||
const loading = ref(false)
|
||||
const showTinymce = ref(true)
|
||||
const fundForm = ref()
|
||||
const formData = ref({
|
||||
fileList:[]
|
||||
})
|
||||
const routerName = ref(router.currentRoute.value.name)
|
||||
const rules = reactive({
|
||||
articleTitle: [{required: true, message: '请输入文章标题', trigger: ['blur', 'change']}],
|
||||
articleType: [{required: true, message: '请输入文章类型', trigger: ['blur', 'change']}],
|
||||
articleContent: [{required: true, message: '请输入文章内容', trigger: ['blur', 'change']}],
|
||||
})
|
||||
const handleDelete = (row,index) => {
|
||||
ElMessageBox.confirm(`确认删除名称为${row.originalFileName}的文件吗?`, '系统提示', {
|
||||
confirmButtonText: '确定',
|
||||
cancelButtonText: '取消',
|
||||
type: 'warning'
|
||||
}).then(() => {
|
||||
deleteFile(row.fileId).then(res => {
|
||||
ElNotification({
|
||||
title: '提示',
|
||||
message: res.msg,
|
||||
type: res.code === 1000 ? 'success' : 'error'
|
||||
})
|
||||
if (res.code === 1000) {
|
||||
formData.value.fileList.splice(index, 1)
|
||||
}
|
||||
})
|
||||
})
|
||||
}
|
||||
const handleBack = () => {
|
||||
history.back()
|
||||
}
|
||||
const getFiles = (val) => {
|
||||
console.log("🚀 ~ file:val ", val)
|
||||
val.originalFileName=val.originalFilename
|
||||
let file = compositeParam(val)
|
||||
formData.value.fileList.push(file)
|
||||
}
|
||||
const handleDownload = (row) => {
|
||||
downloadFile(row.fileId).then(res => {
|
||||
const blob = new Blob([res])
|
||||
let a = document.createElement('a')
|
||||
a.href = URL.createObjectURL(blob)
|
||||
a.download = row.originalFileName
|
||||
a.click()
|
||||
})
|
||||
}
|
||||
const submitParam = (item) => {
|
||||
console.log("🚀 ~ file:item.fileList ", item.fileList)
|
||||
item.fileList= item.fileList.map((it)=>{
|
||||
return {
|
||||
...it,
|
||||
articleId:item.articleId
|
||||
}
|
||||
})
|
||||
return {
|
||||
articleContent: item.articleContent,
|
||||
articleTitle: item.articleTitle,
|
||||
articleType: item.articleType,
|
||||
remarks: item.remarks,
|
||||
articleId: item.articleId,
|
||||
fileList: item.fileList
|
||||
}
|
||||
}
|
||||
const compositeParam = (item) => {
|
||||
return {
|
||||
fileId: item.id,
|
||||
size: item.size,
|
||||
originalFileName: item.originalFilename,
|
||||
fileType: item.fileType,
|
||||
url: item.url,
|
||||
newFile: true,
|
||||
tag: 'article'
|
||||
}
|
||||
}
|
||||
const handleSubmit = async (instance) => {
|
||||
if (!instance) return
|
||||
instance.validate(async (valid) => {
|
||||
if (!valid) {
|
||||
ElNotification({
|
||||
title: '提示',
|
||||
message: '请完善数据,再提交!',
|
||||
type: 'error'
|
||||
})
|
||||
return;
|
||||
}
|
||||
const {msg, code} = await addArticle(submitParam(formData.value))
|
||||
ElNotification({
|
||||
title: '提示',
|
||||
message: msg,
|
||||
type: code === 1000 ? 'success' : 'error'
|
||||
})
|
||||
if (code === 1000) {
|
||||
tagsViewStore.delVisitedViews(router.currentRoute.value.path)
|
||||
await router.push({
|
||||
name: 'Manage'
|
||||
})
|
||||
}
|
||||
})
|
||||
}
|
||||
const handleResubmit = () => {
|
||||
if (!route.query.id) return
|
||||
let params = {
|
||||
articleId: route.query.id,
|
||||
...submitParam(formData.value)
|
||||
}
|
||||
console.log('params', params)
|
||||
editArticle(params).then(res => {
|
||||
ElNotification({
|
||||
title: '提示',
|
||||
message: res.msg,
|
||||
type: res.code === 1000 ? 'success' : 'error'
|
||||
})
|
||||
if (res.code === 1000) {
|
||||
tagsViewStore.delVisitedViews(router.currentRoute.value.path)
|
||||
router.push({
|
||||
name: 'Manage'
|
||||
})
|
||||
}
|
||||
})
|
||||
}
|
||||
const getDetailInfo = async () => {
|
||||
loading.value = true
|
||||
getArticleDetail(route.query.id).then(res => {
|
||||
if (res.code === 1000) {
|
||||
formData.value = res.data
|
||||
loading.value = false
|
||||
showTinymce.value = false
|
||||
nextTick(() => {
|
||||
showTinymce.value = true
|
||||
})
|
||||
} else {
|
||||
ElNotification({
|
||||
title: '提示',
|
||||
message: res.msg,
|
||||
type: 'error'
|
||||
})
|
||||
}
|
||||
})
|
||||
}
|
||||
onMounted(async () => {
|
||||
if (route.query.id) {
|
||||
await getDetailInfo()
|
||||
}
|
||||
})
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss">
|
||||
.a-style:hover{
|
||||
text-decoration: underline !important;
|
||||
}
|
||||
.company-select {
|
||||
:deep(.el-form-item__content .el-select__wrapper ) {
|
||||
width: 750px;
|
||||
}
|
||||
|
||||
.company-style {
|
||||
//width: 98%;
|
||||
min-height: 30px;
|
||||
max-height: 60px;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
-webkit-line-clamp: 2;
|
||||
display: -webkit-box;
|
||||
-webkit-box-orient: vertical;
|
||||
}
|
||||
|
||||
.company {
|
||||
color: #fff;
|
||||
height: auto;
|
||||
}
|
||||
}
|
||||
|
||||
:deep(.el-table--fit ) {
|
||||
height: 300px !important;
|
||||
}
|
||||
|
||||
.add-block {
|
||||
padding: 0 30px;
|
||||
}
|
||||
|
||||
:deep(.el-input-number) {
|
||||
width: 88.5%;
|
||||
|
||||
.el-input__wrapper {
|
||||
padding: 1px 11px !important;
|
||||
}
|
||||
|
||||
.el-input__inner {
|
||||
text-align: left;
|
||||
}
|
||||
}
|
||||
|
||||
:deep(.el-table__header) {
|
||||
.is-leaf:first-child {
|
||||
.cell {
|
||||
margin-left: -20px !important;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
:deep(.el-table__body) {
|
||||
.el-table__cell:first-child {
|
||||
.cell {
|
||||
margin-left: -10px !important;
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
152
src/views/article-management/detail.vue
Normal file
@@ -0,0 +1,152 @@
|
||||
<template>
|
||||
<div v-loading="loading" class="article-detail">
|
||||
<el-form :model="formData">
|
||||
<h2 class="article-title">{{ formData.articleTitle }}</h2>
|
||||
<div class="article-title">
|
||||
<Tag dictType="article_type" :value="formData.articleType"/>
|
||||
<span>{{ formData.articleTime }}</span>
|
||||
<span>发文单位:{{ formData.remarks }}</span>
|
||||
</div>
|
||||
<el-row gutter="20">
|
||||
<el-col :span="24">
|
||||
<el-form-item>
|
||||
<div class="article-a" v-html="formData.articleContent" @click="clickHandle"></div>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="24">
|
||||
<div style="display: flex;flex-direction: column">
|
||||
<div v-for="(item,index) in formData.fileList" style="display: flex;align-items: center;margin-bottom: 5px">
|
||||
附件{{ index + 1 }}: <a :href="item.url" style="color: #409eff;" class="a-style" target="_blank">{{ item.originalFileName }}</a>
|
||||
<el-button type="primary" link @click="handleDownload(item)" style="font-size: 16px;margin-left: 10px">下载</el-button>
|
||||
</div>
|
||||
</div>
|
||||
</el-col>
|
||||
</el-row>
|
||||
</el-form>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import {ElLoading, ElNotification} from "element-plus";
|
||||
import {getArticleDetail} from "@/api/article";
|
||||
import {downloadFile} from "@/api/project-demand";
|
||||
|
||||
const loading = ref(false)
|
||||
const formData = ref({})
|
||||
const route = useRoute()
|
||||
const clickHandle = (e) => {
|
||||
if (e.target.nodeName == "A") {
|
||||
e.preventDefault()
|
||||
let url = e.target.href.split('?')[0];
|
||||
const searchParams = new URLSearchParams(e.target.href.split('?')[1])
|
||||
const fileId = searchParams.get('fileId');
|
||||
const fileName = searchParams.get('fileName');
|
||||
// if(localStorage.getItem("fileUrlList")){
|
||||
// let fileUrlList=JSON.parse(localStorage.getItem("fileUrlList"));
|
||||
// fileUrlList.forEach(item=>{
|
||||
// if(item.url == e.target.href){
|
||||
// console.info("🚀 ~method:item -----", item)
|
||||
let item = {
|
||||
url,
|
||||
fileName
|
||||
}
|
||||
// handleDownload(fileId,fileName)
|
||||
// download(item)
|
||||
// }else {
|
||||
// e.preventDefault()
|
||||
// }
|
||||
// })
|
||||
// }
|
||||
}
|
||||
}
|
||||
// const handleDownload = (fileId,fileName) => {
|
||||
// const loading = ElLoading.service({fullscreen: true})
|
||||
// downloadFile(fileId).then(res => {
|
||||
// const blob = new Blob([res])
|
||||
// let a = document.createElement('a')
|
||||
// a.href = URL.createObjectURL(blob)
|
||||
// nextTick(() => {
|
||||
// a.download = fileName
|
||||
// a.click()
|
||||
// loading.close()
|
||||
// })
|
||||
// })
|
||||
// }
|
||||
const handleDownload = (row) => {
|
||||
downloadFile(row.fileId).then(res => {
|
||||
const blob = new Blob([res])
|
||||
let a = document.createElement('a')
|
||||
a.href = URL.createObjectURL(blob)
|
||||
a.download = row.originalFileName
|
||||
a.click()
|
||||
})
|
||||
}
|
||||
const download = (row) => {
|
||||
const x = new window.XMLHttpRequest();
|
||||
x.open('GET', row.url, true);
|
||||
x.responseType = 'blob';
|
||||
x.onload = () => {
|
||||
const url = window.URL.createObjectURL(x.response);
|
||||
const a = document.createElement('a');
|
||||
a.href = url;
|
||||
a.download = row.fileName;
|
||||
a.click();
|
||||
window.open(row.url,'_blank')
|
||||
};
|
||||
x.send();
|
||||
}
|
||||
const getDetailInfo = async () => {
|
||||
loading.value = true
|
||||
getArticleDetail(route.query.id).then(res => {
|
||||
if (res.code === 1000) {
|
||||
formData.value = res.data
|
||||
loading.value = false
|
||||
} else {
|
||||
ElNotification({
|
||||
title: '提示',
|
||||
message: res.msg,
|
||||
type: 'error'
|
||||
})
|
||||
}
|
||||
})
|
||||
}
|
||||
onMounted(async () => {
|
||||
if (route.query.id) {
|
||||
await getDetailInfo()
|
||||
}
|
||||
})
|
||||
</script>
|
||||
|
||||
<style lang="scss">
|
||||
|
||||
.article-a {
|
||||
a {
|
||||
color: #409eff !important;
|
||||
|
||||
&:hover {
|
||||
text-decoration: underline !important;
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
<style scoped lang="scss">
|
||||
.a-style:hover{
|
||||
text-decoration: underline !important;
|
||||
}
|
||||
.article-detail {
|
||||
padding: 0 30px;
|
||||
padding-top: 15px;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
|
||||
.article-title {
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
|
||||
> span:nth-child(2) {
|
||||
margin: 15px;
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
239
src/views/article-management/index.vue
Normal file
@@ -0,0 +1,239 @@
|
||||
<template>
|
||||
<fvSearchForm :searchConfig="articleSearchConfig" @search="searchArticle" searchProp="articleType" :searchValue="routeArticleType"
|
||||
style="margin-left: 16px"></fvSearchForm>
|
||||
<fvTable ref="tableIns" :tableConfig="articleTableConfig" @headBtnClick="headBtnClick">
|
||||
<template #empty>
|
||||
<el-empty description="暂无数据"/>
|
||||
</template>
|
||||
</fvTable>
|
||||
</template>
|
||||
|
||||
<script setup lang="jsx">
|
||||
import {ElNotification} from "element-plus";
|
||||
import {deleteArticle} from "@/api/article";
|
||||
import fvSelect from '@/fvcomponents/fvSelect/index.vue'
|
||||
|
||||
const router = useRouter();
|
||||
const route = useRoute();
|
||||
const routeArticleType = ref(route.query.type)
|
||||
const articleSearchConfig = reactive([
|
||||
{
|
||||
label: '文章标题',
|
||||
prop: 'articleTitle',
|
||||
component: 'el-input',
|
||||
props: {
|
||||
placeholder: '请输入文章标题查询',
|
||||
clearable: true,
|
||||
filterable: true,
|
||||
checkStrictly: true
|
||||
}
|
||||
},
|
||||
{
|
||||
label: '文章类型',
|
||||
prop: 'articleType',
|
||||
component: shallowRef(fvSelect),
|
||||
props: {
|
||||
placeholder: '请选择文章类型',
|
||||
clearable: true,
|
||||
filterable: true,
|
||||
checkStrictly: true,
|
||||
cacheKey: 'article_type',
|
||||
remote: true
|
||||
}
|
||||
},
|
||||
{
|
||||
label: '时间',
|
||||
prop: 'articleTime',
|
||||
component: 'el-date-picker',
|
||||
props: {
|
||||
placeholder: '请选择时间',
|
||||
clearable: true,
|
||||
type: 'date',
|
||||
format: 'YYYY-MM-DD',
|
||||
valueFormat: "YYYY-MM-DD"
|
||||
},
|
||||
colProps: {}
|
||||
},
|
||||
])
|
||||
const tableIns = ref()
|
||||
const articleTableConfig = reactive({
|
||||
columns: [
|
||||
{
|
||||
prop: 'index',
|
||||
type: 'index',
|
||||
label: '序号',
|
||||
align: 'center',
|
||||
width: 85,
|
||||
index: index => {
|
||||
return (tableIns.value.getQuery().pageNum - 1) * tableIns.value.getQuery().pageSize + index + 1
|
||||
}
|
||||
},
|
||||
{
|
||||
prop: 'articleTitle',
|
||||
label: '文章标题',
|
||||
align: 'center'
|
||||
},
|
||||
{
|
||||
prop: 'articleType',
|
||||
label: '文章类型',
|
||||
align: 'center',
|
||||
showOverflowTooltip: false,
|
||||
currentRender: ({row, index}) => {
|
||||
if (row.articleType == undefined || row.articleType == null) {
|
||||
return '--'
|
||||
} else {
|
||||
return (<Tag dictType={'article_type'} value={row.articleType}/>)
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
prop: 'articleTime',
|
||||
label: '时间',
|
||||
align: 'center'
|
||||
},
|
||||
{
|
||||
prop: 'remarks',
|
||||
label: '发文单位',
|
||||
align: 'center',
|
||||
currentRender: ({row, index}) => {
|
||||
if (!row.remarks|| row.remarks == undefined || row.remarks == null) {
|
||||
return '--'
|
||||
} else {
|
||||
return row.remarks
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
prop: 'oper',
|
||||
label: '操作',
|
||||
align: 'center',
|
||||
fixed: 'right',
|
||||
showOverflowTooltip: false,
|
||||
currentRender: ({row, index}) => {
|
||||
let btn = []
|
||||
btn.push({label: '详情', func: () => handleDetail(row), type: 'primary'})
|
||||
btn.push({label: '编辑', prem: ['mosr:article:edit'], func: () => handleEdit(row), type: 'primary'})
|
||||
return (
|
||||
<div style={{width: '100%'}}>
|
||||
{
|
||||
|
||||
btn.map(item => (
|
||||
item.prem ?
|
||||
<el-button
|
||||
type={item.type}
|
||||
v-perm={item.prem}
|
||||
onClick={() => item.func()}
|
||||
link
|
||||
>
|
||||
{item.label}
|
||||
</el-button> :
|
||||
<el-button
|
||||
type={item.type}
|
||||
onClick={() => item.func()}
|
||||
link
|
||||
>
|
||||
{item.label}
|
||||
</el-button>
|
||||
))
|
||||
}
|
||||
{
|
||||
<popover-delete name={row.articleTitle} type={'文章'} btnType={'danger'} perm={['mosr:article:del']}
|
||||
onDelete={() => handleDelete(row)}/>
|
||||
}
|
||||
</div>
|
||||
)
|
||||
}
|
||||
}
|
||||
],
|
||||
api: '/workflow/mosr/article/list',
|
||||
btns: [
|
||||
{name: '新增', key: 'add', color: '#DED0B2', auth: ['mosr:article:add']}
|
||||
],
|
||||
params: {}
|
||||
})
|
||||
|
||||
const searchArticle = (val) => {
|
||||
let obj = {...val}
|
||||
if (obj.dateValue) {
|
||||
obj.startGenerationTime = obj.dateValue[0]
|
||||
obj.endGenerationTime = obj.dateValue[1]
|
||||
delete obj.dateValue
|
||||
}
|
||||
articleTableConfig.params = obj
|
||||
tableIns.value.refresh()
|
||||
}
|
||||
const init = async () => {
|
||||
if(routeArticleType.value){
|
||||
nextTick(()=>{
|
||||
console.info("🚀 ~method:articleSearchConfig -----", articleSearchConfig[1].component.props)
|
||||
searchArticle({articleType:routeArticleType.value})
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
init()
|
||||
|
||||
const headBtnClick = (key) => {
|
||||
switch (key) {
|
||||
case 'add':
|
||||
handleAdd()
|
||||
break;
|
||||
}
|
||||
}
|
||||
const handleAdd = () => {
|
||||
router.push({
|
||||
name: 'Article/add',
|
||||
query: {}
|
||||
})
|
||||
}
|
||||
const handleDetail = (row) => {
|
||||
router.push({
|
||||
name: 'Article/detail',
|
||||
query: {
|
||||
id: row.articleId
|
||||
}
|
||||
})
|
||||
}
|
||||
const handleEdit = (row) => {
|
||||
router.push({
|
||||
name: 'Article/edit',
|
||||
query: {
|
||||
id: row.articleId
|
||||
}
|
||||
})
|
||||
}
|
||||
const handleDelete = (row) => {
|
||||
deleteArticle(row.articleId).then(res => {
|
||||
ElNotification({
|
||||
title: '提示',
|
||||
message: res.msg,
|
||||
type: res.code === 1000 ? 'success' : 'error'
|
||||
})
|
||||
if (res.code === 1000) {
|
||||
tableIns.value.refresh()
|
||||
}
|
||||
});
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss">
|
||||
:deep(.el-table__header) {
|
||||
.is-leaf:first-child {
|
||||
.cell {
|
||||
margin-left: -25px !important;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
:deep(.el-table__body) {
|
||||
.el-table__cell:first-child {
|
||||
.cell {
|
||||
margin-left: -13px !important;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
:deep(.el-date-editor--month) {
|
||||
width: 100%;
|
||||
}
|
||||
</style>
|
||||
@@ -1,8 +1,8 @@
|
||||
<template>
|
||||
<div class="my">
|
||||
<el-row :gutter="20">
|
||||
<el-col :span="10" :xs="24">
|
||||
<el-card class="box-card1">
|
||||
<el-col :span="12" :xs="24">
|
||||
<el-card>
|
||||
<!-- 标题 -->
|
||||
<template #header>
|
||||
<div class="card-header">
|
||||
@@ -28,24 +28,24 @@
|
||||
</div>
|
||||
<div>{{ userParams.nickName }}</div>
|
||||
</div>
|
||||
<div class="userInfo_item">
|
||||
<div style="display: flex;align-items: center">
|
||||
<el-icon size="18" style="margin-right: 5px">
|
||||
<Notification/>
|
||||
</el-icon>
|
||||
工号:
|
||||
</div>
|
||||
<div>{{ userParams.workCode }}</div>
|
||||
</div>
|
||||
<div class="userInfo_item">
|
||||
<div style="display: flex;align-items: center">
|
||||
<el-icon size="18" style="margin-right: 5px">
|
||||
<Phone/>
|
||||
</el-icon>
|
||||
电话号码:
|
||||
</div>
|
||||
<div>{{ userParams.mobile }}</div>
|
||||
</div>
|
||||
<!-- <div class="userInfo_item">-->
|
||||
<!-- <div style="display: flex;align-items: center">-->
|
||||
<!-- <el-icon size="18" style="margin-right: 5px">-->
|
||||
<!-- <Notification/>-->
|
||||
<!-- </el-icon>-->
|
||||
<!-- 工号:-->
|
||||
<!-- </div>-->
|
||||
<!-- <div>{{ userParams.workCode }}</div>-->
|
||||
<!-- </div>-->
|
||||
<!-- <div class="userInfo_item">-->
|
||||
<!-- <div style="display: flex;align-items: center">-->
|
||||
<!-- <el-icon size="18" style="margin-right: 5px">-->
|
||||
<!-- <Phone/>-->
|
||||
<!-- </el-icon>-->
|
||||
<!-- 电话号码:-->
|
||||
<!-- </div>-->
|
||||
<!-- <div>{{ userParams.mobile }}</div>-->
|
||||
<!-- </div>-->
|
||||
<div class="userInfo_item">
|
||||
<div style="display: flex;align-items: center">
|
||||
<el-icon size="18" style="margin-right: 5px">
|
||||
@@ -94,7 +94,70 @@
|
||||
</div>
|
||||
</el-card>
|
||||
</el-col>
|
||||
<el-col :span="14" :xs="24">
|
||||
<el-col :span="12" :xs="24">
|
||||
<el-card>
|
||||
<baseTitle title="设置代理" ></baseTitle>
|
||||
<el-form ref="userForm" :model="agentInfoForm" label-width="85px">
|
||||
<el-row gutter="30">
|
||||
<el-col :span="24">
|
||||
<el-form-item label="被代理人" prop="nickName">
|
||||
<span>{{ agentInfoForm.nickName }}</span>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="24">
|
||||
<el-form-item label="代理人" prop="" required >
|
||||
<el-button style="margin-right: 10px" color="#DED0B2" @click="handleShowAgentDialog">
|
||||
{{ agentUserList?.length !== 0 ? '更改' : '请选择' }}
|
||||
</el-button>
|
||||
<div v-for="item in agentUserList" :key="item.id" style="margin-right: 5px">
|
||||
{{ item.name }}
|
||||
</div>
|
||||
<user-picker :multiple="false" ref="agentUserPickerRef" title="请选择代理人"
|
||||
v-model:value="agentUserList" @ok="agentUserPickerOk"
|
||||
@cancelOrClear="agentUserPickerOk"/>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="24">
|
||||
<el-form-item label="代理状态" prop="agentState">
|
||||
<Tag dictType="agent_state" :value="agentInfoForm.agentState"/>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="24">
|
||||
<el-form-item label="开始时间" prop="agentStartTime">
|
||||
<el-config-provider>
|
||||
<el-date-picker
|
||||
v-model="agentInfoForm.agentStartTime"
|
||||
type="datetime"
|
||||
placeholder="请选择开始时间"
|
||||
value-format="YYYY-MM-DD HH:mm:ss"
|
||||
/>
|
||||
</el-config-provider>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="24">
|
||||
<el-form-item label="结束时间" prop="agentEndTime" :title="!agentInfoForm.agentStartTime?'请先选择开始时间!':''">
|
||||
<el-config-provider>
|
||||
<el-date-picker
|
||||
v-model="agentInfoForm.agentEndTime"
|
||||
type="datetime"
|
||||
placeholder="请选择结束时间"
|
||||
value-format="YYYY-MM-DD HH:mm:ss"
|
||||
:disabled="!agentInfoForm.agentStartTime"
|
||||
:disabled-date="disabledAgentEndTime"
|
||||
/>
|
||||
</el-config-provider>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-form-item>
|
||||
<el-button color="#DED0B2" @click="handleSubmitAgent" style="margin-left: 16px">提交</el-button>
|
||||
</el-form-item>
|
||||
</el-row>
|
||||
</el-form>
|
||||
</el-card>
|
||||
</el-col>
|
||||
</el-row>
|
||||
<el-row :gutter="20">
|
||||
<el-col :span="12" :xs="24">
|
||||
<el-card class="box-card">
|
||||
<!-- 标题 -->
|
||||
<template #header>
|
||||
@@ -113,8 +176,8 @@
|
||||
<el-input placeholder="请确认新密码" v-model="userPassword.confirmPassword" type="password"/>
|
||||
</el-form-item>
|
||||
<el-form-item>
|
||||
<el-button color="#DED0B2" @click="handleSubmit">提交</el-button>
|
||||
<el-button @click="close">关闭</el-button>
|
||||
<el-button color="#DED0B2" @click="handleSubmitPassword">提交</el-button>
|
||||
<el-button @click="closeIndividualCenter">关闭</el-button>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
</el-card>
|
||||
@@ -126,18 +189,23 @@
|
||||
import {ElNotification} from 'element-plus'
|
||||
import {useTagsView} from '@/stores/tagsview.js'
|
||||
import {getAuthInfo} from "@/api/login";
|
||||
import {editPassword, initPassword} from "@/api/auth/auth";
|
||||
import {editPassword, initPassword,getAgentInfo,editAgentInfo} from "@/api/auth/auth";
|
||||
import UserPicker from "@/views/workflow/process/common/UserPicker.vue";
|
||||
|
||||
const router = useRouter()
|
||||
const tagsViewStore = useTagsView()
|
||||
const isInitPassword = ref(false);
|
||||
const agentUserList = ref([])
|
||||
const agentUserPickerRef = ref()
|
||||
const userParams = ref({});
|
||||
const passwordRef = ref();
|
||||
const router = useRouter()
|
||||
const agentInfoForm = ref({});
|
||||
const userPassword = ref({
|
||||
oldPassword: '',
|
||||
newPassword: '',
|
||||
confirmPassword: ''
|
||||
});
|
||||
const tagsViewStore = useTagsView()
|
||||
|
||||
const validatePasswordComplexity = (rule, value, callback) => {
|
||||
const reg = /^(?=.*[a-zA-Z])(?=.*\d).{1,9}$/; //密码必须是至少包含字母、数字,1-9位
|
||||
if (!reg.test(value)) {
|
||||
@@ -176,21 +244,92 @@ const rules = reactive({
|
||||
}
|
||||
],
|
||||
})
|
||||
const disabledAgentEndTime = (time) => {
|
||||
return time.getTime() <= new Date(agentInfoForm.value.agentStartTime)-1 * 24 * 3600 * 1000
|
||||
}
|
||||
|
||||
const getInfo = async () => {
|
||||
const handleShowAgentDialog = () => {
|
||||
agentUserPickerRef.value.showUserPicker()
|
||||
}
|
||||
|
||||
const agentUserPickerOk = (userList) => {
|
||||
console.info("🚀 ~method:userList -----", userList)
|
||||
agentUserList.value = userList
|
||||
}
|
||||
const getUserInfo = async () => {
|
||||
await getAuthInfo().then(res => {
|
||||
userParams.value = res.data.user
|
||||
isInitPassword.value = res.data.initPassword
|
||||
if(res.code===1000){
|
||||
userParams.value = res.data.user
|
||||
isInitPassword.value = res.data.initPassword
|
||||
}else {
|
||||
ElNotification({
|
||||
title: '提示',
|
||||
message: res.msg,
|
||||
type: 'error'
|
||||
})
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
const getUserAgentInfo = async () => {
|
||||
await getAgentInfo().then(res => {
|
||||
if(res.code===1000){
|
||||
agentInfoForm.value=res.data
|
||||
if(res.data.agentUserId){
|
||||
agentUserList.value=[
|
||||
{
|
||||
id:res.data.agentUserId,
|
||||
name:res.data.agentNickName,
|
||||
companyName:res.data.agentCompanyName,
|
||||
}
|
||||
]
|
||||
}
|
||||
}else {
|
||||
ElNotification({
|
||||
title: '提示',
|
||||
message: res.msg,
|
||||
type: 'error'
|
||||
})
|
||||
}
|
||||
})
|
||||
}
|
||||
localStorage.removeItem('originallySelectedList')
|
||||
|
||||
const belongToRole = (roles) => {
|
||||
if (!roles) return;
|
||||
return roles.map(item => item.roleName).join(',')
|
||||
}
|
||||
|
||||
const handleSubmitAgent=()=>{
|
||||
let agentUserId=''
|
||||
if(agentUserList.value&&agentUserList.value.length>0){
|
||||
agentUserId=agentUserList.value[0]?.id
|
||||
}else {
|
||||
ElNotification({
|
||||
title: '提示',
|
||||
message: '请选择代理人!',
|
||||
type: 'error'
|
||||
})
|
||||
return;
|
||||
}
|
||||
let agentParams={
|
||||
agentUserId:agentUserId,
|
||||
agentStartTime:agentInfoForm.value.agentStartTime,
|
||||
agentEndTime:agentInfoForm.value.agentEndTime
|
||||
}
|
||||
console.info("🚀 ~method:agentParams -----", agentParams)
|
||||
editAgentInfo(agentParams).then(res => {
|
||||
ElNotification({
|
||||
title: '提示',
|
||||
message: res.msg,
|
||||
type: res.code === 1000 ? 'success' : 'error'
|
||||
})
|
||||
if (res.code === 1000) {
|
||||
getUserAgentInfo()
|
||||
}
|
||||
})
|
||||
}
|
||||
// 修改密码
|
||||
const handleSubmit = async () => {
|
||||
const handleSubmitPassword = async () => {
|
||||
if (isInitPassword.value) {
|
||||
editPassword({
|
||||
...userPassword.value
|
||||
@@ -221,23 +360,28 @@ const handleSubmit = async () => {
|
||||
}
|
||||
}
|
||||
// 关闭
|
||||
const close = () => {
|
||||
const closeIndividualCenter = () => {
|
||||
tagsViewStore.delVisitedViews(router.currentRoute.value.path)
|
||||
router.push('/')
|
||||
}
|
||||
onMounted(() => {
|
||||
getInfo()
|
||||
getUserInfo()
|
||||
getUserAgentInfo()
|
||||
})
|
||||
</script>
|
||||
<style lang="scss">
|
||||
.box-card {
|
||||
//margin-left: 10px;
|
||||
margin-top: 10px;
|
||||
}
|
||||
|
||||
body, div {
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
.my {
|
||||
margin: 0 auto;
|
||||
margin-top: 20px;
|
||||
margin: 20px auto 0;
|
||||
|
||||
.userDetail {
|
||||
.userImg {
|
||||
@@ -256,21 +400,14 @@ body, div {
|
||||
}
|
||||
|
||||
.userInfo_item {
|
||||
display: flex;align-items: center;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
height: 40px;
|
||||
border-bottom-style: solid;
|
||||
border-color: #daddd2;
|
||||
border-width: 1px;
|
||||
//text-align: left;
|
||||
//line-height: 40px;
|
||||
|
||||
}
|
||||
|
||||
//
|
||||
//.userInfo_item > div {
|
||||
// float: right;
|
||||
//}
|
||||
}
|
||||
|
||||
</style>
|
||||
|
||||
@@ -6,7 +6,6 @@ import {ElLoading} from 'element-plus'
|
||||
const authStore = useAuthStore()
|
||||
const router = useRouter();
|
||||
const tokenValue = reactive(router.currentRoute.value.query.token)
|
||||
console.log('tokenValue', tokenValue)
|
||||
const init = () => {
|
||||
const loading = ElLoading.service({
|
||||
lock: true,
|
||||
@@ -16,7 +15,6 @@ const init = () => {
|
||||
if (authStore.casToken(tokenValue)) {
|
||||
loading.close()
|
||||
const toView = sessionStorage.getItem('toView')
|
||||
console.log(toView, 'toView');
|
||||
if (toView) {
|
||||
let parse = JSON.parse(toView);
|
||||
window.location.href = window.location.origin + parse.path + parse.query
|
||||
|
||||
141
src/views/doneList/index.vue
Normal file
@@ -0,0 +1,141 @@
|
||||
<template>
|
||||
<fvTable ref="tableIns" :tableConfig="tableConfig" style="margin-top: 15px"></fvTable>
|
||||
</template>
|
||||
|
||||
<script setup lang="jsx">
|
||||
const router = useRouter()
|
||||
const tableIns = ref()
|
||||
const tableConfig = reactive({
|
||||
columns: [
|
||||
{
|
||||
prop: 'index',
|
||||
type: 'index',
|
||||
label: '序号',
|
||||
align: 'center',
|
||||
width:60,
|
||||
index: index => {
|
||||
return (tableIns.value.getQuery().pageNum - 1) * tableIns.value.getQuery().pageSize + index + 1
|
||||
}
|
||||
},
|
||||
{
|
||||
prop: 'targetName',
|
||||
label: '名称',
|
||||
align: 'center'
|
||||
},
|
||||
{
|
||||
prop: 'initiatorName',
|
||||
label: '发起人',
|
||||
align: 'center'
|
||||
},
|
||||
{
|
||||
prop: 'targetState',
|
||||
label: '流程类型',
|
||||
align: 'center',
|
||||
showOverflowTooltip: false,
|
||||
currentRender: ({row, index}) => {
|
||||
if (row.targetState !== null || row.targetState !== undefined) {
|
||||
return (<Tag dictType={'todo_type'} value={row.targetState}/>)
|
||||
} else {
|
||||
return '--'
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
prop: 'submitTime',
|
||||
label: '提交时间',
|
||||
align: 'center'
|
||||
},
|
||||
{
|
||||
prop: 'oper',
|
||||
label: '操作',
|
||||
align: 'center',
|
||||
fixed: 'right',
|
||||
width: 150,
|
||||
showOverflowTooltip: false,
|
||||
currentRender: ({row, index}) => {
|
||||
let btn = []
|
||||
btn.push({label: '查看', func: () => handleView(row), type: 'primary'})
|
||||
return (
|
||||
<div style={{width: '100%'}}>
|
||||
{
|
||||
btn.map(item => (
|
||||
<el-button
|
||||
type={item.type}
|
||||
onClick={() => item.func()}
|
||||
link
|
||||
>
|
||||
{item.label}
|
||||
</el-button>
|
||||
))
|
||||
}
|
||||
</div>
|
||||
)
|
||||
}
|
||||
}
|
||||
],
|
||||
api: '/workflow/mosr/process/task/about',
|
||||
})
|
||||
|
||||
const handleView = (row) => {
|
||||
if (row.targetState == '00' && row.targetId) {
|
||||
router.push({
|
||||
name: 'Requirement/detail',
|
||||
query: {
|
||||
id: row.targetId,
|
||||
source: 'home'
|
||||
}
|
||||
})
|
||||
}
|
||||
// else if (row.targetState == '10' && row.targetId) {
|
||||
// router.push({
|
||||
// name: 'Summary/detail',
|
||||
// query: {
|
||||
// projectId: row.targetId,
|
||||
// state: row.state,
|
||||
// source: 'home'
|
||||
// }
|
||||
// })
|
||||
// }
|
||||
else if (row.targetState == '10' ||row.targetState == '20' || row.targetState == '40' || row.targetState == '50') {
|
||||
router.push({
|
||||
name: 'Implementation/detail',
|
||||
query: {
|
||||
projectId: row.targetId,
|
||||
state: row.state,
|
||||
step: row.targetState,
|
||||
source: 'home'
|
||||
}
|
||||
})
|
||||
} else if (row.targetState == '70' && row.targetId) {
|
||||
router.push({
|
||||
name: 'Fund/detail',
|
||||
query: {
|
||||
id: row.targetId,
|
||||
state: row.state,
|
||||
source: 'home'
|
||||
}
|
||||
})
|
||||
} else if (row.targetState == '80' && row.targetId) {
|
||||
router.push({
|
||||
name: 'Share/detail',
|
||||
query: {
|
||||
id: row.targetId,
|
||||
state: row.state,
|
||||
source: 'home'
|
||||
}
|
||||
})
|
||||
} else if (row.targetState == '90' && row.targetId) {
|
||||
router.push({
|
||||
name: 'Phase/detail',
|
||||
query: {
|
||||
projectId: row.targetId,
|
||||
source: 'home'
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
|
||||
</style>
|
||||
275
src/views/expense-management/cost-detail/index.vue
Normal file
@@ -0,0 +1,275 @@
|
||||
<template>
|
||||
<fvSearchForm :searchConfig="searchConfig" @search="search" style="margin-left: 15px"></fvSearchForm>
|
||||
<div style="float: left">
|
||||
<import-cost-excel @success="importTheExpenseLedger"/>
|
||||
</div>
|
||||
<fvTable ref="tableIns" class="tablte" :tableConfig="tableConfig" @headBtnClick="headBtnClick" :changeExportPosition="true">
|
||||
<template #empty>
|
||||
<el-empty description="暂无数据"/>
|
||||
</template>
|
||||
</fvTable>
|
||||
</template>
|
||||
|
||||
<script setup lang="jsx">
|
||||
import {reactive, ref} from "vue";
|
||||
import {useRoute, useRouter} from "vue-router";
|
||||
import {costTemplateDownload, exportExcel, ledgerTemplateDownload} from "../../../api/project-manage";
|
||||
import ImportCostExcel from "@/components/ImportCostExcel.vue";
|
||||
const router = useRouter()
|
||||
const route = useRoute()
|
||||
const searchConfig = ref([
|
||||
|
||||
{
|
||||
label: '主项目',
|
||||
prop: 'masterProjectName',
|
||||
component: 'el-input',
|
||||
props: {
|
||||
placeholder: '请输入主项目查询',
|
||||
clearable: true,
|
||||
filterable: true,
|
||||
checkStrictly: true
|
||||
}
|
||||
},
|
||||
{
|
||||
label: '子项目',
|
||||
prop: 'subProjectName',
|
||||
component: 'el-input',
|
||||
props: {
|
||||
placeholder: '请输入子项目查询',
|
||||
clearable: true,
|
||||
filterable: true,
|
||||
checkStrictly: true
|
||||
}
|
||||
},
|
||||
{
|
||||
label: '会计凭证记载金额(元)',
|
||||
prop: 'recordedAmount',
|
||||
component: 'el-input',
|
||||
props: {
|
||||
placeholder: '请输入会计凭证记载金额查询',
|
||||
clearable: true,
|
||||
filterable: true,
|
||||
checkStrictly: true
|
||||
}
|
||||
},
|
||||
{
|
||||
label: '归集研发费用金额(元)',
|
||||
prop: 'rdAmount',
|
||||
component: 'el-input',
|
||||
props: {
|
||||
placeholder: '请输入归集研发费用金额查询',
|
||||
clearable: true,
|
||||
filterable: true,
|
||||
checkStrictly: true
|
||||
}
|
||||
},
|
||||
// {
|
||||
// label: '项目类型',
|
||||
// prop: 'projectType',
|
||||
// component: shallowRef(fvSelect),
|
||||
// props: {
|
||||
// placeholder: '请选择项目类型',
|
||||
// cacheKey: 'project_type',
|
||||
// clearable: true,
|
||||
// filterable: true,
|
||||
// remote: true
|
||||
// },
|
||||
// colProps: {}
|
||||
// },
|
||||
// {
|
||||
// label: '归档时间',
|
||||
// prop: 'filingTime',
|
||||
// component: 'el-date-picker',
|
||||
// props: {
|
||||
// placeholder: '请选择归档时间',
|
||||
// clearable: true,
|
||||
// type:'date',
|
||||
// format: 'YYYY-MM-DD HH:mm',
|
||||
// valueFormat:'YYYY-MM-DD HH:mm',
|
||||
// },
|
||||
// colProps: {}
|
||||
// },
|
||||
])
|
||||
const tableIns = ref()
|
||||
const tableConfig = reactive({
|
||||
columns: [
|
||||
// {
|
||||
// prop: 'name',
|
||||
// type: 'index',
|
||||
// label: '序号',
|
||||
// align: 'center',
|
||||
// width:85,
|
||||
// index: index => {
|
||||
// return (tableIns.value.getQuery().pageNum - 1) * tableIns.value.getQuery().pageSize + index + 1
|
||||
// }
|
||||
// },
|
||||
{
|
||||
prop: 'rdYear',
|
||||
label: '年',
|
||||
align: 'center',
|
||||
width: 80
|
||||
},
|
||||
{
|
||||
prop: 'rdMonth',
|
||||
label: '月',
|
||||
align: 'center',
|
||||
width: 80
|
||||
},
|
||||
{
|
||||
prop: 'rdDay',
|
||||
label: '日',
|
||||
align: 'center',
|
||||
width: 80
|
||||
},
|
||||
|
||||
{
|
||||
prop: 'masterProjectName',
|
||||
label: '主项目',
|
||||
align: 'center',
|
||||
width: 120,
|
||||
|
||||
},
|
||||
|
||||
{
|
||||
prop: 'subProjectName',
|
||||
label: '子项目',
|
||||
align: 'center',
|
||||
width: 120,
|
||||
},
|
||||
{
|
||||
prop: 'certificateDate',
|
||||
label: '凭证日期',
|
||||
align: 'center',
|
||||
width: 120,
|
||||
},
|
||||
{
|
||||
prop: 'voucherNumber',
|
||||
label: '凭证号',
|
||||
align: 'center'
|
||||
},
|
||||
{
|
||||
prop: 'entryNumber',
|
||||
label: '分录号',
|
||||
align: 'center',
|
||||
|
||||
},
|
||||
{
|
||||
prop: 'digest',
|
||||
label: '摘要',
|
||||
align: 'center',
|
||||
showOverflowTooltip: false,
|
||||
},
|
||||
{
|
||||
prop: 'accountCode',
|
||||
label: '科目编码',
|
||||
align: 'center',
|
||||
showOverflowTooltip: false,
|
||||
|
||||
},
|
||||
{
|
||||
prop: 'accountName',
|
||||
label: '科目名称',
|
||||
align: 'center',
|
||||
showOverflowTooltip: false,
|
||||
},
|
||||
{
|
||||
prop: 'auxiliaryItem',
|
||||
label: '辅助项',
|
||||
align: 'center',
|
||||
showOverflowTooltip: false,
|
||||
},
|
||||
{
|
||||
prop: 'recordedAmount',
|
||||
label: '会计凭证记载金额(元)',
|
||||
align: 'center',
|
||||
width: 170
|
||||
},
|
||||
{
|
||||
prop: 'rdAmount',
|
||||
label: '归集研发费用金额(元)',
|
||||
align: 'center',
|
||||
width: 170
|
||||
},
|
||||
],
|
||||
api: '/workflow/mosr/rd/expense/list',
|
||||
params: {},
|
||||
btns: [
|
||||
{name: '模板下载', key: 'down', color: '#DED0B2'},
|
||||
// {name: '导入', key: 'import', color: '#DED0B2'}
|
||||
],
|
||||
export:{
|
||||
open :true,
|
||||
fileName:`研发费用明细表`
|
||||
}
|
||||
})
|
||||
const search = (val) => {
|
||||
tableConfig.params = {...val}
|
||||
tableIns.value.refresh()
|
||||
}
|
||||
|
||||
const headBtnClick = (key) => {
|
||||
switch (key) {
|
||||
case 'down':
|
||||
handleImportTemplateDownload()
|
||||
break;
|
||||
case 'import':
|
||||
handleAdd()
|
||||
break;
|
||||
}
|
||||
}
|
||||
const exportTable = () => {
|
||||
const $e = tableIns.value.$el
|
||||
let $table = $e.querySelector('.el-table__fixed')
|
||||
if (!$table) {
|
||||
$table = $e
|
||||
}
|
||||
exportExcel($table, (5 + (Object.keys(tableData.value[0]).length - 5) * 5), "四川省国有资产经营投资管理有限责任公司科技创新项目人工成本分摊明细表", 2)
|
||||
}
|
||||
//导入模板下载
|
||||
const handleImportTemplateDownload=()=>{
|
||||
costTemplateDownload().then(res => {
|
||||
let link = document.createElement('a')
|
||||
try {
|
||||
let blob = new Blob([res.data],{type: 'application/vnd.ms-excel'});
|
||||
let _fileName = "研发费用明细表模板.xlsx"//文件名,中文无法解析的时候会显示 _(下划线),生产环境获取不到
|
||||
link.style.display='none';
|
||||
// 兼容不同浏览器的URL对象
|
||||
const url = window.URL || window.webkitURL || window.moxURL;
|
||||
link.href=url.createObjectURL(blob);
|
||||
link.setAttribute('download', _fileName.substring(_fileName.lastIndexOf('_')+1))
|
||||
document.body.appendChild(link);
|
||||
link.click();
|
||||
document.body.removeChild(link);
|
||||
url.revokeObjectURL(link.href);//销毁url对象
|
||||
}catch (e) {
|
||||
console.log('下载的文件出错',e)
|
||||
}
|
||||
})
|
||||
}
|
||||
const importTheExpenseLedger = () => {
|
||||
tableIns.value.refresh()
|
||||
}
|
||||
</script>
|
||||
<style scoped lang="scss">
|
||||
:deep(.el-form-item__label-wrap){
|
||||
margin-left: 0!important;
|
||||
}
|
||||
:deep(.el-table__header) {
|
||||
.is-leaf:first-child {
|
||||
.cell {
|
||||
margin-left: -25px !important;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
:deep(.el-table__body) {
|
||||
.el-table__cell:first-child {
|
||||
.cell {
|
||||
margin-left: -13px !important;
|
||||
}
|
||||
}
|
||||
}
|
||||
:deep(.el-date-editor--month){
|
||||
width: 100%;
|
||||
}
|
||||
</style>
|
||||
232
src/views/expense-management/expend-detail/index.vue
Normal file
@@ -0,0 +1,232 @@
|
||||
<template>
|
||||
<fvSearchForm :searchConfig="searchConfig" @search="search" ></fvSearchForm>
|
||||
<fvTable ref="tableIns" :tableConfig="tableConfig" >
|
||||
<template #empty>
|
||||
<el-empty description="暂无数据"/>
|
||||
</template>
|
||||
</fvTable>
|
||||
</template>
|
||||
|
||||
<script setup lang="jsx">
|
||||
import fvSelect from '@/fvcomponents/fvSelect/index.vue'
|
||||
import {toThousands} from '@/utils/changePrice.js'
|
||||
import { getSubCompOpt } from '@/api/user/user.js';
|
||||
const router = useRouter()
|
||||
const route = useRoute()
|
||||
const searchConfig = ref(
|
||||
[
|
||||
|
||||
{
|
||||
label: '主项目',
|
||||
prop: 'masterProjectName',
|
||||
component: 'el-input',
|
||||
props: {
|
||||
placeholder: '请输入主项目查询',
|
||||
clearable: true,
|
||||
filterable: true,
|
||||
checkStrictly: true
|
||||
}
|
||||
},
|
||||
{
|
||||
label: '子项目',
|
||||
prop: 'subProjectName',
|
||||
component: 'el-input',
|
||||
props: {
|
||||
placeholder: '请输入子项目查询',
|
||||
clearable: true,
|
||||
filterable: true,
|
||||
checkStrictly: true
|
||||
}
|
||||
},
|
||||
{
|
||||
label: '项目类型',
|
||||
prop: 'projectType',
|
||||
component: shallowRef(fvSelect),
|
||||
props: {
|
||||
placeholder: '请选择项目类型',
|
||||
cacheKey: 'project_type',
|
||||
clearable: true,
|
||||
filterable: true,
|
||||
remote: true
|
||||
},
|
||||
colProps: {}
|
||||
},
|
||||
// {
|
||||
// label: '归档时间',
|
||||
// prop: 'filingTime',
|
||||
// component: 'el-date-picker',
|
||||
// props: {
|
||||
// placeholder: '请选择归档时间',
|
||||
// clearable: true,
|
||||
// type:'date',
|
||||
// format: 'YYYY-MM-DD HH:mm',
|
||||
// valueFormat:'YYYY-MM-DD HH:mm',
|
||||
// },
|
||||
// colProps: {}
|
||||
// },
|
||||
])
|
||||
const tableIns = ref()
|
||||
const tableConfig = reactive({
|
||||
columns: [
|
||||
// {
|
||||
// prop: 'name',
|
||||
// type: 'index',
|
||||
// label: '序号',
|
||||
// align: 'center',
|
||||
// width:85,
|
||||
// index: index => {
|
||||
// return (tableIns.value.getQuery().pageNum - 1) * tableIns.value.getQuery().pageSize + index + 1
|
||||
// }
|
||||
// },
|
||||
{
|
||||
prop: 'paymentYear',
|
||||
label: '支付年份',
|
||||
align: 'center'
|
||||
},
|
||||
{
|
||||
prop: 'paymentMonth',
|
||||
label: '支付月份',
|
||||
align: 'center'
|
||||
},
|
||||
|
||||
{
|
||||
prop: 'masterProjectName',
|
||||
label: '主项目',
|
||||
align: 'center',
|
||||
width: 120,
|
||||
},
|
||||
|
||||
{
|
||||
prop: 'subProjectName',
|
||||
label: '子项目',
|
||||
align: 'center',
|
||||
width: 120,
|
||||
},
|
||||
{
|
||||
prop: 'projectType',
|
||||
label: '项目类型',
|
||||
align: 'center',
|
||||
width: 120,
|
||||
showOverflowTooltip: false,
|
||||
currentRender: ({row, index}) => {
|
||||
if (row.projectType&&row.projectType !== null&&row.projectType!==undefined) {
|
||||
return (<Tag dictType={'project_type'} value={row.projectType}/>)
|
||||
} else {
|
||||
return '--'
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
prop: 'rdType',
|
||||
label: 'R&D统计类型',
|
||||
align: 'center',
|
||||
width: 200
|
||||
},
|
||||
{
|
||||
prop: 'rdSub',
|
||||
label: 'R&D统计子项',
|
||||
align: 'center',
|
||||
width: 150
|
||||
},
|
||||
{
|
||||
prop: 'paymentProcessType',
|
||||
label: '付款流程类型',
|
||||
align: 'center',
|
||||
width: 150
|
||||
},
|
||||
{
|
||||
prop: 'processState',
|
||||
label: '流程状态',
|
||||
align: 'center',
|
||||
},
|
||||
{
|
||||
prop: 'filingTime',
|
||||
label: '归档时间',
|
||||
align: 'center',
|
||||
width: 180
|
||||
},
|
||||
{
|
||||
prop: 'paymentProcessNum',
|
||||
label: '付款流程编号',
|
||||
align: 'center',
|
||||
width: 150
|
||||
},
|
||||
{
|
||||
prop: 'paymentAmount',
|
||||
label: '付款金额',
|
||||
align: 'center',
|
||||
},
|
||||
{
|
||||
prop: 'paymentSubject',
|
||||
label: '付款/请款事由',
|
||||
align: 'center',
|
||||
width: 130
|
||||
},
|
||||
|
||||
{
|
||||
prop: 'contractNum',
|
||||
label: '合同编号',
|
||||
align: 'center',
|
||||
},
|
||||
{
|
||||
prop: 'contractName',
|
||||
label: '合同名称',
|
||||
align: 'center',
|
||||
},
|
||||
{
|
||||
prop: 'contractSumAmount',
|
||||
label: '合同总额(元)',
|
||||
align: 'center',
|
||||
width: 130
|
||||
},
|
||||
{
|
||||
prop: 'recipientName',
|
||||
label: '收款方名称',
|
||||
align: 'center',
|
||||
width: 130
|
||||
},
|
||||
{
|
||||
prop: 'remarks',
|
||||
label: '备注说明',
|
||||
align: 'center',
|
||||
},
|
||||
],
|
||||
api: '/workflow/mosr/payment/list',
|
||||
params: {},
|
||||
export:{
|
||||
open :true,
|
||||
fileName:`科研项日现金支出明细表`
|
||||
}
|
||||
})
|
||||
const search = (val) => {
|
||||
tableConfig.params = {...val}
|
||||
tableIns.value.refresh()
|
||||
}
|
||||
const init = async () => {
|
||||
const res = await getSubCompOpt()
|
||||
searchConfig.value.find(item=>item.prop == 'affiliatedCompanyIds').props.data = res.data
|
||||
}
|
||||
|
||||
// init()
|
||||
|
||||
</script>
|
||||
<style scoped lang="scss">
|
||||
:deep(.el-table__header) {
|
||||
.is-leaf:first-child {
|
||||
.cell {
|
||||
margin-left: -25px !important;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
:deep(.el-table__body) {
|
||||
.el-table__cell:first-child {
|
||||
.cell {
|
||||
margin-left: -13px !important;
|
||||
}
|
||||
}
|
||||
}
|
||||
:deep(.el-date-editor--month){
|
||||
width: 100%;
|
||||
}
|
||||
</style>
|
||||
@@ -1,5 +1,5 @@
|
||||
<template>
|
||||
<fvSearchForm :searchConfig="searchConfig" @search="search"></fvSearchForm>
|
||||
<fvSearchForm :searchConfig="searchConfig" @search="search" style="margin-left: 16px"></fvSearchForm>
|
||||
<fvTable ref="tableIns" :tableConfig="tableConfig">
|
||||
<template #empty>
|
||||
<el-empty description="暂无数据"/>
|
||||
@@ -10,9 +10,23 @@
|
||||
<script setup lang="jsx">
|
||||
import fvSelect from '@/fvcomponents/fvSelect/index.vue'
|
||||
import {toThousands} from '@/utils/changePrice.js'
|
||||
import { getSubCompOpt } from '@/api/user/user.js';
|
||||
const router = useRouter()
|
||||
const route = useRoute()
|
||||
const searchConfig = reactive([
|
||||
const searchConfig = ref([
|
||||
{
|
||||
label: '公司名称',
|
||||
prop: 'affiliatedCompanyIds',
|
||||
component: 'el-tree-select',
|
||||
props: {
|
||||
placeholder: '请输入公司名称查询',
|
||||
clearable: true,
|
||||
data: [],
|
||||
filterable: true,
|
||||
checkStrictly: true,
|
||||
remote: true
|
||||
}
|
||||
},
|
||||
{
|
||||
label: '项目名称',
|
||||
prop: 'projectName',
|
||||
@@ -24,19 +38,7 @@ const searchConfig = reactive([
|
||||
checkStrictly: true
|
||||
}
|
||||
},
|
||||
{
|
||||
label: '时间',
|
||||
prop: 'time',
|
||||
component: 'el-date-picker',
|
||||
props: {
|
||||
placeholder: '请选择时间',
|
||||
clearable: true,
|
||||
type:'month',
|
||||
format: 'YYYY-MM',
|
||||
valueFormat:'YYYY-MM',
|
||||
},
|
||||
colProps: {}
|
||||
},
|
||||
|
||||
{
|
||||
label: '项目费用',
|
||||
prop: 'projectCost',
|
||||
@@ -46,6 +48,7 @@ const searchConfig = reactive([
|
||||
clearable: true,
|
||||
filterable: true,
|
||||
cacheKey: 'project_cost',
|
||||
remote: true
|
||||
}
|
||||
},
|
||||
{
|
||||
@@ -58,8 +61,23 @@ const searchConfig = reactive([
|
||||
filterable: true,
|
||||
checkStrictly: true,
|
||||
cacheKey: 'fee_stage',
|
||||
remote: true
|
||||
}
|
||||
},
|
||||
|
||||
{
|
||||
label: '时间',
|
||||
prop: 'time',
|
||||
component: 'el-date-picker',
|
||||
props: {
|
||||
placeholder: '请选择时间',
|
||||
clearable: true,
|
||||
type:'month',
|
||||
format: 'YYYY-MM',
|
||||
valueFormat:'YYYY-MM',
|
||||
},
|
||||
colProps: {}
|
||||
},
|
||||
{
|
||||
label: '税后余额',
|
||||
prop: 'afterTax',
|
||||
@@ -90,22 +108,28 @@ const tableConfig = reactive({
|
||||
prop: 'name',
|
||||
type: 'index',
|
||||
label: '序号',
|
||||
width:'80',
|
||||
align: 'center',
|
||||
width:85,
|
||||
index: index => {
|
||||
return (tableIns.value.getQuery().pageNum - 1) * tableIns.value.getQuery().pageSize + index + 1
|
||||
}
|
||||
},
|
||||
{
|
||||
prop: 'affiliatedCompany',
|
||||
label: '公司名称',
|
||||
align: 'center'
|
||||
},
|
||||
{
|
||||
prop: 'projectName',
|
||||
label: '项目名称',
|
||||
align: 'center'
|
||||
},{
|
||||
prop: 'time',
|
||||
label: '时间',
|
||||
align: 'center'
|
||||
},
|
||||
|
||||
{
|
||||
prop: 'projectCost',
|
||||
label: '项目费用',
|
||||
align: 'center',
|
||||
width: 120,
|
||||
showOverflowTooltip: false,
|
||||
currentRender: ({row, index}) => {
|
||||
if (row.projectCost !== null&&row.projectCost !== null&&row.projectCost!==undefined) {
|
||||
@@ -119,6 +143,7 @@ const tableConfig = reactive({
|
||||
prop: 'researchStage',
|
||||
label: '研发阶段',
|
||||
align: 'center',
|
||||
width: 120,
|
||||
showOverflowTooltip: false,
|
||||
currentRender: ({row, index}) => {
|
||||
if (row.researchStage&&row.researchStage !== null&&row.researchStage!==undefined) {
|
||||
@@ -128,6 +153,12 @@ const tableConfig = reactive({
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
prop: 'time',
|
||||
label: '时间',
|
||||
align: 'center',
|
||||
width: 120,
|
||||
},
|
||||
{
|
||||
label: '摘要',
|
||||
prop: 'digest',
|
||||
@@ -156,14 +187,41 @@ const tableConfig = reactive({
|
||||
},
|
||||
],
|
||||
api: '/workflow/mosr/expense/ledger',
|
||||
params: {}
|
||||
params: {},
|
||||
export:{
|
||||
open :true,
|
||||
fileName:`科技创新项目费用台账.xlsx`
|
||||
}
|
||||
})
|
||||
const search = (val) => {
|
||||
tableConfig.params = {...val}
|
||||
tableIns.value.refresh()
|
||||
}
|
||||
const init = async () => {
|
||||
const res = await getSubCompOpt()
|
||||
searchConfig.value.find(item=>item.prop == 'affiliatedCompanyIds').props.data = res.data
|
||||
}
|
||||
|
||||
init()
|
||||
|
||||
</script>
|
||||
<style scoped lang="scss">
|
||||
:deep(.el-table__header) {
|
||||
.is-leaf:first-child {
|
||||
.cell {
|
||||
margin-left: -25px !important;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
<style scoped>
|
||||
|
||||
:deep(.el-table__body) {
|
||||
.el-table__cell:first-child {
|
||||
.cell {
|
||||
margin-left: -13px !important;
|
||||
}
|
||||
}
|
||||
}
|
||||
:deep(.el-date-editor--month){
|
||||
width: 100%;
|
||||
}
|
||||
</style>
|
||||
|
||||
333
src/views/expense-management/project-ledger/index.vue
Normal file
@@ -0,0 +1,333 @@
|
||||
<template>
|
||||
<fvSearchForm :searchConfig="searchConfig" @search="search" style="margin-left: 16px"></fvSearchForm>
|
||||
<fvTable ref="tableIns" :tableConfig="tableConfig">
|
||||
<template #empty>
|
||||
<el-empty description="暂无数据"/>
|
||||
</template>
|
||||
</fvTable>
|
||||
</template>
|
||||
|
||||
<script setup lang="jsx">
|
||||
import fvSelect from '@/fvcomponents/fvSelect/index.vue'
|
||||
import {toThousands} from '@/utils/changePrice.js'
|
||||
import { getSubCompOpt } from '@/api/user/user.js';
|
||||
|
||||
const route = useRoute()
|
||||
const router = useRouter()
|
||||
const shortcuts = [
|
||||
{
|
||||
text: '上周',
|
||||
value: () => {
|
||||
const end = new Date()
|
||||
const start = new Date()
|
||||
start.setTime(start.getTime() - 3600 * 1000 * 24 * 7)
|
||||
return [start, end]
|
||||
},
|
||||
},
|
||||
{
|
||||
text: '上月',
|
||||
value: () => {
|
||||
const end = new Date()
|
||||
const start = new Date()
|
||||
start.setTime(start.getTime() - 3600 * 1000 * 24 * 30)
|
||||
return [start, end]
|
||||
},
|
||||
},
|
||||
{
|
||||
text: '三月前',
|
||||
value: () => {
|
||||
const end = new Date()
|
||||
const start = new Date()
|
||||
start.setTime(start.getTime() - 3600 * 1000 * 24 * 90)
|
||||
return [start, end]
|
||||
},
|
||||
},
|
||||
]
|
||||
const searchConfig = ref([
|
||||
{
|
||||
label: '征集公司',
|
||||
prop: 'affiliatedCompanyId',
|
||||
component: 'el-tree-select',
|
||||
props: {
|
||||
placeholder: '请输入征集公司查询',
|
||||
clearable: true,
|
||||
data: [],
|
||||
filterable: true,
|
||||
checkStrictly: true,
|
||||
remote: true
|
||||
}
|
||||
},
|
||||
{
|
||||
label: '项目名称',
|
||||
prop: 'projectName',
|
||||
component: 'el-input',
|
||||
props: {
|
||||
placeholder: '请输入项目名称查询',
|
||||
clearable: true,
|
||||
filterable: true,
|
||||
checkStrictly: true
|
||||
}
|
||||
},
|
||||
{
|
||||
label: '项目类型',
|
||||
prop: 'projectType',
|
||||
component: shallowRef(fvSelect),
|
||||
props: {
|
||||
placeholder: '请选择项目类型',
|
||||
cacheKey: 'project_type',
|
||||
clearable: true,
|
||||
filterable: true,
|
||||
remote: true
|
||||
}
|
||||
},
|
||||
{
|
||||
label: '项目影响',
|
||||
prop: 'projectImpact',
|
||||
component: shallowRef(fvSelect),
|
||||
props: {
|
||||
placeholder: '请选择项目影响',
|
||||
cacheKey: 'project_impact',
|
||||
clearable: true,
|
||||
filterable: true,
|
||||
remote: true
|
||||
},
|
||||
colProps: {}
|
||||
},
|
||||
{
|
||||
label: '研发主体',
|
||||
prop: 'rdSubject',
|
||||
component: shallowRef(fvSelect),
|
||||
props: {
|
||||
placeholder: '请选择研发主体',
|
||||
cacheKey: 'rd_subject',
|
||||
clearable: true,
|
||||
filterable: true,
|
||||
remote: true
|
||||
}
|
||||
},
|
||||
{
|
||||
label: '起止时间',
|
||||
prop: 'dateValue',
|
||||
component: 'el-date-picker',
|
||||
props: {
|
||||
clearable: true,
|
||||
type: 'daterange',
|
||||
startPlaceholder: '开始日期',
|
||||
endPlaceholder: '结束日期',
|
||||
valueFormat: 'YYYY-MM-DD HH:mm:ss',
|
||||
shortcuts: shortcuts
|
||||
}
|
||||
}
|
||||
])
|
||||
const tableIns = ref()
|
||||
const tableConfig = reactive({
|
||||
columns: [
|
||||
// {
|
||||
// type: 'selection',
|
||||
// prop: 'selection'
|
||||
// },
|
||||
{
|
||||
prop: 'index',
|
||||
type: 'index',
|
||||
label: '序号',
|
||||
align: 'center',
|
||||
width:85,
|
||||
index: index => {
|
||||
return (tableIns.value.getQuery().pageNum - 1) * tableIns.value.getQuery().pageSize + index + 1
|
||||
}
|
||||
},
|
||||
{
|
||||
prop: 'affiliatedCompany',
|
||||
label: '征集公司',
|
||||
align: 'center'
|
||||
},
|
||||
{
|
||||
prop: 'projectName',
|
||||
label: '项目名称',
|
||||
align: 'center'
|
||||
},
|
||||
{
|
||||
prop: 'projectType',
|
||||
label: '项目类型',
|
||||
align: 'center',
|
||||
width: 100,
|
||||
showOverflowTooltip: false,
|
||||
currentRender: ({row, index}) => {
|
||||
if (row.projectType && row.projectType !== null && row.projectType !== undefined) {
|
||||
return (<Tag dictType={'project_type'} value={row.projectType}/>)
|
||||
} else {
|
||||
return '--'
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
prop: 'rdSubject',
|
||||
label: '研发主体',
|
||||
align: 'center',
|
||||
width: 100,
|
||||
showOverflowTooltip: false,
|
||||
currentRender: ({row, index}) => {
|
||||
if (row.rdSubject && row.rdSubject !== null && row.rdSubject !== undefined) {
|
||||
return (<Tag dictType={'rd_subject'} value={row.rdSubject}/>)
|
||||
} else {
|
||||
return '--'
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
prop: 'researchStage',
|
||||
label: '研发阶段',
|
||||
align: 'center',
|
||||
width: 100,
|
||||
showOverflowTooltip: false,
|
||||
currentRender: ({row, index}) => {
|
||||
if (row.researchStage && row.researchStage !== null && row.researchStage !== undefined) {
|
||||
return (<Tag dictType={'research_stage'} value={row.researchStage}/>)
|
||||
} else {
|
||||
return '--'
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
prop: 'projectImpact',
|
||||
label: '项目影响',
|
||||
align: 'center',
|
||||
width: 120,
|
||||
showOverflowTooltip: false,
|
||||
currentRender: ({row, index}) => {
|
||||
if (row.projectImpact && row.projectImpact !== null && row.projectImpact !== undefined) {
|
||||
return (<Tag dictType={'project_impact'} value={row.projectImpact}/>)
|
||||
} else {
|
||||
return '--'
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
prop: 'economicEstimate',
|
||||
label: '预估经费预算(元)',
|
||||
align: 'center',
|
||||
width: 150,
|
||||
currentRender:({row})=>{
|
||||
return <span>{toThousands(row.economicEstimate)}</span>
|
||||
}
|
||||
},
|
||||
{
|
||||
prop: 'startTime',
|
||||
label: '起止时间',
|
||||
align: 'center',
|
||||
currentRender: ({row}) => {
|
||||
return row.startTime + ' 至 ' + row.endTime
|
||||
}
|
||||
},
|
||||
{
|
||||
prop: 'approveName',
|
||||
label: '当前审批节点',
|
||||
align: 'center',
|
||||
width: 120,
|
||||
currentRender: ({row, index}) => {
|
||||
if(row.state=='3'||row.state=='4'){
|
||||
return <span>{row.taskNode}</span>
|
||||
}else if(row.state=='1'){
|
||||
return <span>{row.approveName}</span>
|
||||
}else {
|
||||
return <span>--</span>
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
prop: 'state',
|
||||
label: '状态',
|
||||
align: 'center',
|
||||
width: 100,
|
||||
showOverflowTooltip: false,
|
||||
currentRender: ({row, index}) => {
|
||||
if (row.state && row.state !== null && row.state !== undefined) {
|
||||
return (<Tag dictType={'project_implementation'} value={row.state}/>)
|
||||
} else {
|
||||
return '--'
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
prop: 'oper',
|
||||
label: '操作',
|
||||
align: 'center',
|
||||
fixed:'right',
|
||||
showOverflowTooltip: false,
|
||||
currentRender: ({row, index}) => {
|
||||
let btn = []
|
||||
let buttons = new Set(Array.from(row.buttons))
|
||||
if (buttons.has("standing")) {
|
||||
btn.push({label: '台账', prem: ['project:management:implementation:account'], func: () => handleStandingBook(row), type: 'primary'})
|
||||
}
|
||||
return (
|
||||
<div style={{width: '100%'}}>
|
||||
{
|
||||
btn.map(item => (
|
||||
<el-button
|
||||
type={item.type}
|
||||
v-perm={item.prem}
|
||||
onClick={() => item.func()}
|
||||
link
|
||||
>
|
||||
{item.label}
|
||||
</el-button>
|
||||
))
|
||||
}
|
||||
</div>
|
||||
)
|
||||
}
|
||||
}
|
||||
],
|
||||
api: '/workflow/mosr/project/implementation',
|
||||
params: {
|
||||
state:0
|
||||
},
|
||||
btns: [
|
||||
// {name: '生成分摊报表', key: '_export', color: '#DED0B2', auth: ''}
|
||||
]
|
||||
})
|
||||
|
||||
const search = (val) => {
|
||||
let obj = {...val}
|
||||
if(obj.dateValue) {
|
||||
obj.startTime = obj.dateValue[0]
|
||||
obj.endTime = obj.dateValue[1]
|
||||
delete obj.dateValue
|
||||
}
|
||||
tableConfig.params = obj
|
||||
tableIns.value.refresh()
|
||||
}
|
||||
|
||||
const handleStandingBook = (row) => {
|
||||
router.push({
|
||||
name: 'Implementation/account',
|
||||
query: {
|
||||
id: row.projectId
|
||||
}
|
||||
})
|
||||
}
|
||||
const init = async () => {
|
||||
const res = await getSubCompOpt()
|
||||
searchConfig.value.find(item=>item.prop == 'affiliatedCompanyId').props.data = res.data
|
||||
}
|
||||
|
||||
init()
|
||||
</script>
|
||||
<style scoped lang="scss">
|
||||
:deep(.el-table__header) {
|
||||
.is-leaf:first-child {
|
||||
.cell {
|
||||
margin-left: -25px !important;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
:deep(.el-table__body) {
|
||||
.el-table__cell:first-child {
|
||||
.cell {
|
||||
margin-left: -13px !important;
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
591
src/views/expense-management/share-detail/add.vue
Normal file
@@ -0,0 +1,591 @@
|
||||
<template>
|
||||
<div v-loading="loading" style="padding: 0 30px">
|
||||
<el-form :model="formData" ref="form" :rules="rules" style="margin-left: 5px;margin-top: 18px">
|
||||
<el-row :gutter="30">
|
||||
<!-- <el-col :span="6" style="margin-left: -15px">-->
|
||||
<!-- <el-form-item label="分摊名称" prop="shareName" >-->
|
||||
<!-- <el-input v-model="formData.shareName" placeholder="请输入分摊名称" clearable>-->
|
||||
<!-- </el-input>-->
|
||||
<!-- </el-form-item>-->
|
||||
<!-- </el-col>-->
|
||||
<el-col :span="6" style="margin-left: -10px">
|
||||
<el-form-item label="分摊月份" prop="apportionmentMonth" label-width="80">
|
||||
<el-date-picker
|
||||
v-model="formData.apportionmentMonth"
|
||||
type="month"
|
||||
format="YYYY-MM"
|
||||
value-format="YYYY-MM"
|
||||
placeholder="选择月"
|
||||
>
|
||||
</el-date-picker>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="3" >
|
||||
<el-button color="#DED0B2" @click="handleAdd" style="font-size: 16px">添加一行</el-button>
|
||||
</el-col>
|
||||
<el-table v-if="showTable" :data="formData.tableData" style="width: 100%">
|
||||
<el-table-column prop="projectId" label="项目名称" min-width="230">
|
||||
<template #default="scope">
|
||||
<el-form-item prop="time" :rules="scope.row.projectId?'1':rules.projectId">
|
||||
<el-select v-model="scope.row.projectId" placeholder="请选择项目名称" clearable filterable @change="selectProject(scope.row,scope.$index)">
|
||||
<el-option
|
||||
v-for="item in nameOptions"
|
||||
:key="item.value"
|
||||
:label="item.label"
|
||||
:value="item.value"
|
||||
>
|
||||
</el-option>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column prop="researchPersonnelId" label="研发人员" min-width="180">
|
||||
<template #default="scope">
|
||||
<el-form-item prop="researchPersonnelId">
|
||||
{{ scope.row.researchPersonnel }}
|
||||
<el-button color="#DED0B2" @click="showPersonnelPicker(scope.row,scope.$index)"
|
||||
style="margin-left: 10px">
|
||||
{{ scope.row.researchPersonnel ? '更改' : '请选择研发人员' }}
|
||||
</el-button>
|
||||
</el-form-item>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column prop="wagesPayable" label="当月总工时(天)" min-width="175">
|
||||
<template #default="scope">
|
||||
<el-form-item prop="time" :rules="scope.row.wagesPayable?'1':rules.wagesPayable">
|
||||
<div>21.75</div>
|
||||
</el-form-item>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column prop="researchDuration" label="当月研发工时(天)" min-width="175">
|
||||
<template #default="scope">
|
||||
<el-form-item prop="time" :rules="scope.row.researchDuration?'1':rules.researchDuration">
|
||||
<el-input-number v-model="scope.row.researchDuration" placeholder="请输入当月研发工时" :controls="false"/>
|
||||
</el-form-item>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column prop="oper" label="操作" min-width="130">
|
||||
<template #default="scope">
|
||||
<el-button type="primary" @click="handleCopy(scope.row)" link style="font-size: 16px">复制</el-button>
|
||||
<el-button type="primary" @click="handleDelete(scope.$index)" link style="font-size: 16px">删除</el-button>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
</el-row>
|
||||
</el-form>
|
||||
<user-picker :multiple="false" ref="userPicker" title="请选择研发人员" v-model:value="userList"
|
||||
@ok="selectedResearchPersonnel" @cancelOrClear="researchPersonnelPickerCancel"
|
||||
:setNullToSelectList="true" :isResearch="true"/>
|
||||
|
||||
|
||||
<div class="oper-page-btn">
|
||||
<el-button color="#DED0B2" v-if="routerName==='Sharedetail/add'" @click="handleSubmit(form)">提交</el-button>
|
||||
<el-button color="#DED0B2" v-else @click="handleResubmit(form)">重新提交</el-button>
|
||||
<el-button @click="handleBack">返回</el-button>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup lang="jsx">
|
||||
import {ElNotification} from "element-plus";
|
||||
import {useTagsView} from '@/stores/tagsview.js'
|
||||
import {
|
||||
addAllocation,
|
||||
getAllocationDetail,
|
||||
getAllocationProcess,
|
||||
getResearchUser,
|
||||
getProjectOption,
|
||||
editAllocation,
|
||||
getAllocationDetailList, addShare
|
||||
} from "@/api/expense-manage";
|
||||
import {useProcessStore} from '@/stores/processStore.js';
|
||||
import ProcessDiagramViewer from '@/views/workflow/common/ProcessDiagramViewer.vue';
|
||||
import OperationRender from '@/views/workflow/common/OperationRender.vue'
|
||||
import UserPicker from "@/views/workflow/process/common/UserPicker.vue";
|
||||
localStorage.removeItem('originallySelectedList')
|
||||
|
||||
const userList = ref([])
|
||||
const changeDiagram = ref(false)
|
||||
const rules = reactive({
|
||||
// shareName: [{required: true, message: '请输入分摊名称', trigger: ['blur', 'change']}],
|
||||
apportionmentMonth: [{required: true, message: '请选择月份', trigger: ['blur', 'change']}],
|
||||
projectId: [{required: true, message: '请选择项目名称', trigger: ['blur', 'change']}],
|
||||
// researchPersonnelId: [{required: true, message: '请选择研发人员', trigger: ['blur', 'change']}],
|
||||
// wagesPayable: [{required: true, message: '请输入应发工资', trigger: ['blur', 'change']}],
|
||||
// performance: [{required: true, message: '请输入绩效', trigger: ['blur', 'change']}],
|
||||
// reserveFund: [{required: true, message: '请输入公积金', trigger: ['blur', 'change']}],
|
||||
// socialSecurity: [{required: true, message: '请输入社保', trigger: ['blur', 'change']}],
|
||||
// annuity: [{required: true, message: '请输入年金', trigger: ['blur', 'change']}],
|
||||
// workday: [{required: true, message: '请输入工作日', trigger: ['blur', 'change']}],
|
||||
researchDuration: [{required: true, message: '请输入研发时长', trigger: ['blur', 'change']}],
|
||||
})
|
||||
const processStore = useProcessStore()
|
||||
const opentionData = ref({})
|
||||
const processInstanceData = ref()
|
||||
const processDiagramViewer = ref(false)
|
||||
const loading = ref(false)
|
||||
const isRepeatResearchPersonnel = ref(false)
|
||||
const showTable = ref(true)
|
||||
const route = useRoute()
|
||||
const router = useRouter()
|
||||
const routerName = ref(router.currentRoute.value.name)
|
||||
const tagsViewStore = useTagsView()
|
||||
const formData = ref({
|
||||
tableData: [
|
||||
{
|
||||
projectId: '',
|
||||
projectName: '',
|
||||
// researchPersonnelId: '',
|
||||
// wagesPayable: null,
|
||||
// performance: null,
|
||||
// reserveFund: null,
|
||||
// socialSecurity: null,
|
||||
// annuity: null,
|
||||
workday: '21.75',
|
||||
researchDuration: null,
|
||||
}
|
||||
]
|
||||
})
|
||||
const userPicker = ref()
|
||||
const form = ref()
|
||||
const currentReachPerson = ref({})
|
||||
const currentRow = ref()
|
||||
const currentIndex = ref()
|
||||
const nameOptions = ref([])
|
||||
const researchOptions = ref([])
|
||||
const showPersonnelPicker = (row, index) => {
|
||||
currentRow.value = row
|
||||
currentIndex.value = index
|
||||
if (row.companyName&&row.researchPersonnelId) {
|
||||
let userObj = {
|
||||
id: row.researchPersonnelId,
|
||||
name: row.researchPersonnel,
|
||||
companyName: row.companyName,
|
||||
accountType: row.accountType,
|
||||
}
|
||||
userList.value = [userObj]
|
||||
} else if (!row.researchPersonnel) {
|
||||
userList.value = []
|
||||
}
|
||||
nextTick(() => {
|
||||
userPicker.value.showUserPicker()
|
||||
})
|
||||
}
|
||||
const selectProject=(row,index)=>{
|
||||
console.log('row,index',row,index)
|
||||
//先选择人员, 再选择项目: 再添加一行,重复操作
|
||||
const projectIdArray = formData.value.tableData.map(item => item.projectId)
|
||||
const researchPersonnelIdArray = formData.value.tableData.map(item => item.researchPersonnelId)
|
||||
console.log('projectIdArray',projectIdArray)
|
||||
console.log('researchPersonnelIdArray',researchPersonnelIdArray)
|
||||
const projectNumObj = getSelectProjectAndResearchPersonnelNum(projectIdArray)
|
||||
const researchPersonnelNumObj = getSelectProjectAndResearchPersonnelNum(researchPersonnelIdArray)
|
||||
let repeatProjectName=getProjectName(row.projectId)
|
||||
// console.log('currentRow.value',currentRow.value)
|
||||
// for (let researchPersonnelIdKey in researchPersonnelNumObj) {//先判断人员是否重复
|
||||
// if(currentRow.value.projectId){
|
||||
// if(researchPersonnelNumObj[researchPersonnelIdKey]>1){
|
||||
// ElNotification({
|
||||
// title: '警告',
|
||||
// message: `${repeatProjectName} 项目下,同一个研发人员不能分摊多次!`,
|
||||
// type: 'warning',
|
||||
// })
|
||||
// row.researchPersonnelId = ''
|
||||
// row.researchPersonnel = ''
|
||||
// row.companyName = ''
|
||||
// row.accountType = ''
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// }
|
||||
// for (let projectIdKey in projectNumObj) {
|
||||
// // console.log('projectNumObjKey', projectIdKey, projectNumObj[projectIdKey])
|
||||
// if(projectNumObj[projectIdKey]>1){
|
||||
// // console.log('getProjectName(projectIdKey)',getProjectName(projectIdKey))
|
||||
// repeatProjectName=getProjectName(projectIdKey)
|
||||
//
|
||||
// }
|
||||
// }
|
||||
}
|
||||
const researchPersonnelPickerCancel = (select) => {
|
||||
console.log('select',select)
|
||||
if(select.length>0){
|
||||
formData.value.tableData?.forEach((item, index) => {
|
||||
if (index === currentIndex.value) {
|
||||
item.researchPersonnelId = select[0].id
|
||||
item.researchPersonnel = select[0].name
|
||||
item.companyName = select[0].companyName
|
||||
item.accountType = select[0].accountType
|
||||
}
|
||||
})
|
||||
}else{
|
||||
formData.value.tableData?.forEach((item, index) => {
|
||||
if (index === currentIndex.value) {
|
||||
item.researchPersonnelId = ''
|
||||
item.researchPersonnel = ''
|
||||
item.companyName = ''
|
||||
item.accountType = ''
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
const selectedResearchPersonnel = (select) => {
|
||||
if(select.length>0){
|
||||
formData.value.tableData?.forEach((item, index) => {
|
||||
if (index === currentIndex.value) {
|
||||
item.researchPersonnelId = select[0].id
|
||||
item.researchPersonnel = select[0].name
|
||||
item.companyName = select[0].companyName
|
||||
item.accountType = select[0].accountType
|
||||
}
|
||||
})
|
||||
}else{
|
||||
formData.value.tableData?.forEach((item, index) => {
|
||||
if (index === currentIndex.value) {
|
||||
item.researchPersonnelId = ''
|
||||
item.researchPersonnel = ''
|
||||
item.companyName = ''
|
||||
item.accountType = ''
|
||||
}
|
||||
})
|
||||
}
|
||||
//以下是为" 同一项目下,同一人不能分摊多次 "
|
||||
const projectIdArray = formData.value.tableData?.map(item => item.projectId)
|
||||
const researchPersonnelIdArray = formData.value.tableData?.map(item => item.researchPersonnelId)
|
||||
const projectNumObj = getSelectProjectAndResearchPersonnelNum(projectIdArray)
|
||||
const researchPersonnelNumObj = getSelectProjectAndResearchPersonnelNum(researchPersonnelIdArray)
|
||||
let repeatProjectName=''
|
||||
for (let projectIdKey in projectNumObj) {
|
||||
// console.log('projectNumObjKey', projectIdKey, projectNumObj[projectIdKey])
|
||||
if(projectNumObj[projectIdKey]>1){
|
||||
// console.log('getProjectName(projectIdKey)',getProjectName(projectIdKey))
|
||||
repeatProjectName=getProjectName(projectIdKey)
|
||||
}
|
||||
}
|
||||
// for (let researchPersonnelIdKey in researchPersonnelNumObj) {
|
||||
// // console.log('researchPersonnelIdKey', researchPersonnelIdKey, researchPersonnelNumObj[researchPersonnelIdKey])
|
||||
// if(researchPersonnelNumObj[researchPersonnelIdKey]>1&&repeatProjectName&¤tRow.value.projectId){
|
||||
// isRepeatResearchPersonnel.value=true
|
||||
// ElNotification({
|
||||
// title: '警告',
|
||||
// message: `${repeatProjectName} 项目下,同一个研发人员不能分摊多次!`,
|
||||
// type: 'warning',
|
||||
// })
|
||||
// formData.value.tableData.forEach((item,index)=>{
|
||||
// if (index === currentIndex.value) {
|
||||
// item.researchPersonnelId = ''
|
||||
// item.researchPersonnel = ''
|
||||
// item.companyName = ''
|
||||
// item.accountType = ''
|
||||
// }
|
||||
// })
|
||||
// }else{
|
||||
// userList.value = select
|
||||
// }
|
||||
// }
|
||||
|
||||
}
|
||||
/**
|
||||
* 获取一个项目/研发人员的选择次数
|
||||
* @param projectIdArray
|
||||
* @returns {{}}
|
||||
*/
|
||||
const getSelectProjectAndResearchPersonnelNum = (projectIdArray) => {
|
||||
const obj = {};
|
||||
for (let i = 0, l = projectIdArray.length; i < l; i++) {
|
||||
const item = projectIdArray[i];
|
||||
obj[item] = (obj[item] + 1) || 1;
|
||||
}
|
||||
return obj;
|
||||
}
|
||||
const getResearchOptions = async () => {
|
||||
const res = await getResearchUser()
|
||||
researchOptions.value = res.data
|
||||
}
|
||||
const getProjectOptions = async () => {
|
||||
const res = await getProjectOption()
|
||||
nameOptions.value = res.data
|
||||
}
|
||||
const getProjectName = (id) => {
|
||||
let label = ''
|
||||
nameOptions.value.forEach(item => {
|
||||
if (item.value == id) {
|
||||
label = item.label
|
||||
}
|
||||
})
|
||||
return label
|
||||
}
|
||||
const handleAdd = () => {
|
||||
let row = {
|
||||
projectId: '',
|
||||
projectName: '',
|
||||
researchPersonnelId: '',
|
||||
researchPersonnel: '',
|
||||
wagesPayable: null,
|
||||
performance: null,
|
||||
reserveFund: null,
|
||||
socialSecurity: null,
|
||||
annuity: null,
|
||||
workday: '21.75',
|
||||
researchDuration: null,
|
||||
}
|
||||
currentReachPerson.value.name = ''
|
||||
formData.value.tableData.push(row)
|
||||
}
|
||||
const handleCopy = (row) => {
|
||||
let copyObj = {
|
||||
projectId: row.projectId,
|
||||
projectName: '',
|
||||
// accountType: row.accountType,
|
||||
// companyName: row.companyName,
|
||||
// researchPersonnelId: row.researchPersonnelId,
|
||||
// researchPersonnel: row.researchPersonnel,
|
||||
wagesPayable: row.wagesPayable,
|
||||
performance: row.performance,
|
||||
reserveFund: row.reserveFund,
|
||||
socialSecurity: row.socialSecurity,
|
||||
annuity: row.annuity,
|
||||
workday: '21.75',
|
||||
researchDuration: row.researchDuration,
|
||||
}
|
||||
formData.value.tableData.push(copyObj)
|
||||
}
|
||||
const handleDelete = (index) => {
|
||||
formData.value.tableData.splice(index, 1)
|
||||
}
|
||||
const handleSubmit = (instance) => {
|
||||
console.log('tableData', formData.value.tableData)
|
||||
if (!instance) return
|
||||
instance.validate(async (valid) => {
|
||||
if (!valid) {
|
||||
ElNotification({
|
||||
title: '提示',
|
||||
message: '请完善数据,再提交!',
|
||||
type: 'error'
|
||||
})
|
||||
return;
|
||||
}
|
||||
let researchPersonnelId = ''
|
||||
formData.value.tableData.forEach(item => {
|
||||
item.projectName = getProjectName(item.projectId)
|
||||
researchPersonnelId = item.researchPersonnelId
|
||||
if (item.performance == 0) {
|
||||
item.performance = null
|
||||
}
|
||||
})
|
||||
if (!researchPersonnelId) {
|
||||
ElNotification({
|
||||
title: '提示',
|
||||
message: '请选择研发人员',
|
||||
type: 'error'
|
||||
})
|
||||
return;
|
||||
}
|
||||
let params = {
|
||||
apportionmentMonth: formData.value.apportionmentMonth,
|
||||
usrAllocations: formData.value.tableData,
|
||||
}
|
||||
console.log('params', params.usrAllocations, formData.value.tableData)
|
||||
const resultMap = params.usrAllocations.reduce((acc, item) => {
|
||||
if (!acc[item.researchPersonnelId]) {
|
||||
acc[item.researchPersonnelId] = [];
|
||||
}
|
||||
acc[item.researchPersonnelId].push(item);
|
||||
return acc;
|
||||
}, {});
|
||||
const exceedList = [];
|
||||
|
||||
Object.entries(resultMap).forEach(([id, items]) => {
|
||||
const totalDuration = items.reduce((sum, item) => sum + (item.researchDuration || 0), 0);
|
||||
const preciseTotalDuration = parseFloat(totalDuration.toFixed(2));
|
||||
|
||||
if (preciseTotalDuration > 21.75) {
|
||||
// 收集超出的研发人员ID及总工时
|
||||
exceedList.push({ id, totalDuration: preciseTotalDuration });
|
||||
}
|
||||
});
|
||||
// 从 resultMap 中获取 researchPersonnel
|
||||
const exceedResearchPersonnel = exceedList.map(item => {
|
||||
const id = item.id;
|
||||
const personnelItems = resultMap[id];
|
||||
// 获取第一个对象中的 researchPersonnel(假设所有对象的 researchPersonnel 相同)
|
||||
const researchPersonnel = personnelItems[0].researchPersonnel;
|
||||
return { id, researchPersonnel, totalDuration: item.totalDuration };
|
||||
});
|
||||
|
||||
console.log('超过21.75的研发人员:', exceedResearchPersonnel);
|
||||
|
||||
if (exceedResearchPersonnel.length > 0) {
|
||||
console.log('以下研发人员的总研发工时超过21.75天:', exceedResearchPersonnel);
|
||||
|
||||
ElNotification({
|
||||
title: '提示',
|
||||
message: `以下研发人员的总研发工时超过21.75天:${exceedResearchPersonnel.map(e => e.researchPersonnel).join(',')}`,
|
||||
type: 'warning'
|
||||
});
|
||||
}
|
||||
// 调用函数
|
||||
console.log('是大V',resultMap)
|
||||
const {code, msg} = await addShare(params)
|
||||
ElNotification({
|
||||
title: '提示',
|
||||
message: msg,
|
||||
type: code === 1000 ? 'success' : 'error'
|
||||
})
|
||||
if (code === 1000) {
|
||||
tagsViewStore.delVisitedViews(router.currentRoute.value.path)
|
||||
router.push({
|
||||
name: 'Share'
|
||||
})
|
||||
}
|
||||
})
|
||||
}
|
||||
const handleResubmit = (instance) => {
|
||||
if (!instance) return
|
||||
instance.validate(async (valid) => {
|
||||
if (!valid) {
|
||||
ElNotification({
|
||||
title: '提示',
|
||||
message: '请完善数据,再提交!',
|
||||
type: 'error'
|
||||
})
|
||||
return;
|
||||
}
|
||||
let researchPersonnelId = ''
|
||||
formData.value.tableData.forEach(item => {
|
||||
item.allocationId = formData.value.allocationId
|
||||
item.projectName = getProjectName(item.projectId)
|
||||
researchPersonnelId = item.researchPersonnelId
|
||||
if (item.performance == 0) {
|
||||
item.performance = null
|
||||
}
|
||||
})
|
||||
if (!researchPersonnelId) {
|
||||
ElNotification({
|
||||
title: '提示',
|
||||
message: '请选择研发人员',
|
||||
type: 'error'
|
||||
})
|
||||
return;
|
||||
}
|
||||
let params = {
|
||||
allocationId: formData.value.allocationId,
|
||||
shareName: formData.value.shareName,
|
||||
apportionmentMonth: formData.value.apportionmentMonth,
|
||||
usrAllocations: formData.value.tableData,
|
||||
deploymentId: processInstanceData.value.deploymentId,
|
||||
}
|
||||
// console.log('params', params, formData.value.tableData)
|
||||
const {code, msg} = await editAllocation(params)
|
||||
ElNotification({
|
||||
title: '提示',
|
||||
message: msg,
|
||||
type: code === 1000 ? 'success' : 'error'
|
||||
})
|
||||
if (code === 1000) {
|
||||
tagsViewStore.delVisitedViews(router.currentRoute.value.path)
|
||||
router.push({
|
||||
name: 'Share'
|
||||
})
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
const getDetailInfo = () => {
|
||||
loading.value = true
|
||||
getAllocationDetail(route.query.id).then(res => {
|
||||
ElNotification({
|
||||
title: '提示',
|
||||
message: res.msg,
|
||||
type: res.code === 1000 ? 'success' : 'error'
|
||||
})
|
||||
if (res.code === 1000) {
|
||||
getDetailList()
|
||||
formData.value = res.data.formData
|
||||
opentionData.value = res.data
|
||||
loading.value = false
|
||||
}
|
||||
})
|
||||
}
|
||||
const getDetailList = async () => {
|
||||
let params = {
|
||||
allocationId: route.query.id
|
||||
}
|
||||
showTable.value = false
|
||||
const {code, data, msg} = await getAllocationDetailList(params)
|
||||
if (code === 1000) {
|
||||
data.rows.forEach(item => {
|
||||
item.researchPersonnelId = Number(item.researchPersonnelId)
|
||||
})
|
||||
formData.value.tableData = data.rows
|
||||
nextTick(() => {
|
||||
showTable.value = true
|
||||
})
|
||||
} else {
|
||||
ElNotification({
|
||||
title: '提示',
|
||||
message: msg,
|
||||
type: 'error'
|
||||
})
|
||||
}
|
||||
}
|
||||
const init = async () => {
|
||||
processDiagramViewer.value = false
|
||||
await getResearchOptions()
|
||||
await getProjectOptions()
|
||||
getAllocationProcess().then(res => {
|
||||
if (res.code === 1000) {
|
||||
let data = res.data
|
||||
processInstanceData.value = data
|
||||
processStore.setDesign(data)
|
||||
processStore.runningList.value = data.runningList;
|
||||
processStore.endList.value = data.endList;
|
||||
processStore.noTakeList.value = data.noTakeList;
|
||||
processStore.refuseList.value = data.refuseList;
|
||||
processStore.passList.value = data.passList;
|
||||
nextTick(() => {
|
||||
processDiagramViewer.value = true
|
||||
})
|
||||
} else {
|
||||
ElNotification({
|
||||
title: '提示',
|
||||
message: res.msg,
|
||||
type: 'error'
|
||||
})
|
||||
}
|
||||
})
|
||||
}
|
||||
const handleBack = () => {
|
||||
history.back()
|
||||
}
|
||||
onMounted(() => {
|
||||
init()
|
||||
if (route.query.id) {
|
||||
getDetailInfo()
|
||||
}
|
||||
})
|
||||
</script>
|
||||
<style scoped lang="scss">
|
||||
:deep(.el-table--enable-row-transition) {
|
||||
.el-table__body td.el-table__cell {
|
||||
.cell {
|
||||
.el-form-item {
|
||||
margin-top: 20px;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
:deep(.el-date-editor--month) {
|
||||
width: 100% !important;
|
||||
}
|
||||
|
||||
:deep(.el-input-number) {
|
||||
width: 100%;
|
||||
|
||||
.el-input__inner {
|
||||
text-align: left;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
219
src/views/expense-management/share-detail/index.vue
Normal file
@@ -0,0 +1,219 @@
|
||||
<template>
|
||||
<fvSearchForm :searchConfig="searchConfig" @search="search" style="margin-left: 16px"></fvSearchForm>
|
||||
<!-- <el-button color="#DED0B2" style="float: left;margin: 0 10px 10px 0" @click="exportTable">导出</el-button>-->
|
||||
|
||||
<fvTable ref="tableIns" :tableConfig="tableConfig" @headBtnClick="headBtnClick" style="margin-top: 15px" @selectionChange="selectionChange">
|
||||
<template #empty>
|
||||
<el-empty description="暂无数据"/>
|
||||
</template>
|
||||
</fvTable>
|
||||
</template>
|
||||
|
||||
<script setup lang="jsx">
|
||||
import fvSelect from '@/fvcomponents/fvSelect/index.vue'
|
||||
|
||||
import { getSubCompOpt } from '@/api/user/user.js';
|
||||
import {reactive, ref} from "vue";
|
||||
import {shareDetailExport, shareExportExcel} from "@/api/expense-manage";
|
||||
import {ElMessage} from "element-plus";
|
||||
const router = useRouter()
|
||||
const route = useRoute()
|
||||
const searchConfig = reactive([
|
||||
{
|
||||
label: '子项目',
|
||||
prop: 'subProjectName',
|
||||
component: 'el-input',
|
||||
props: {
|
||||
placeholder: '请输入子项目查询',
|
||||
clearable: true,
|
||||
filterable: true,
|
||||
checkStrictly: true
|
||||
}
|
||||
},
|
||||
// {
|
||||
// label: '支付月份',
|
||||
// prop: 'apportionmentMonth',
|
||||
// component: 'el-date-picker',
|
||||
// props: {
|
||||
// placeholder: '请选择支付月份',
|
||||
// clearable: true,
|
||||
// type:'month',
|
||||
// format: 'YYYY-MM',
|
||||
// valueFormat:"YYYY-MM"
|
||||
// },
|
||||
// colProps: {}
|
||||
// },
|
||||
// {
|
||||
// label: '人员性质',
|
||||
// prop: 'personnelNature',
|
||||
// component: shallowRef(fvSelect),
|
||||
// props: {
|
||||
// placeholder: '请选择人员性质',
|
||||
// clearable: true,
|
||||
// filterable: true,
|
||||
// cacheKey: 'nature_of_personnel'
|
||||
// }
|
||||
// },
|
||||
])
|
||||
const tableIns = ref()
|
||||
const selectData = ref([])
|
||||
const tableConfig = reactive({
|
||||
columns: [
|
||||
{
|
||||
type: 'selection',
|
||||
prop: 'selection',
|
||||
},
|
||||
// {
|
||||
// prop: 'name',
|
||||
// type: 'index',
|
||||
// label: '序号',
|
||||
// align: 'center',
|
||||
// width:85,
|
||||
// index: index => {
|
||||
// return (tableIns.value.getQuery().pageNum - 1) * tableIns.value.getQuery().pageSize + index + 1
|
||||
// }
|
||||
// },
|
||||
{
|
||||
prop: 'paymentYear',
|
||||
label: '支付年份',
|
||||
align: 'center'
|
||||
},
|
||||
{
|
||||
prop: 'paymentMonth',
|
||||
label: '支付月份',
|
||||
align: 'center'
|
||||
},
|
||||
|
||||
{
|
||||
prop: 'masterProjectName',
|
||||
label: '主项目',
|
||||
align: 'center',
|
||||
},
|
||||
|
||||
{
|
||||
prop: 'subProjectName',
|
||||
label: '子项目',
|
||||
align: 'center',
|
||||
},
|
||||
{
|
||||
prop: 'researchPersonnel',
|
||||
label: '研发人员',
|
||||
align: 'center',
|
||||
showOverflowTooltip: false,
|
||||
},
|
||||
{
|
||||
prop: 'personnelNature',
|
||||
label: '人员性质',
|
||||
align: 'center',
|
||||
width: 120,
|
||||
showOverflowTooltip: false,
|
||||
currentRender: ({row, index}) => {
|
||||
if (row.personnelNature&&row.personnelNature !== null&&row.personnelNature!==undefined) {
|
||||
return (<Tag dictType={'nature_of_personnel'} value={row.personnelNature}/>)
|
||||
} else {
|
||||
return '--'
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
prop: 'researchDuration',
|
||||
label: '当月研发工时(天)',
|
||||
align: 'center',
|
||||
// currentRender:({row})=>{
|
||||
// return <span>{toThousands(row.afterTax)}</span>
|
||||
// }
|
||||
},
|
||||
{
|
||||
prop: 'workday',
|
||||
label: '当月总工时(天)',
|
||||
align: 'center',
|
||||
showOverflowTooltip: false,
|
||||
},
|
||||
{
|
||||
prop: 'subtotal',
|
||||
label: '人工成本分摊(元)',
|
||||
align: 'center',
|
||||
},
|
||||
|
||||
],
|
||||
api: '/workflow/mosr/cost/share',
|
||||
params: {},
|
||||
btns: [
|
||||
{name: '添加分摊', key: 'add', color: '#DED0B2'},
|
||||
{name: '导出', key: 'export', color: '#DED0B2'}
|
||||
],
|
||||
export:{
|
||||
open :false,
|
||||
}
|
||||
})
|
||||
|
||||
|
||||
const search = (val) => {
|
||||
tableConfig.params = {...val}
|
||||
tableIns.value.refresh()
|
||||
}
|
||||
const headBtnClick = (key) => {
|
||||
switch (key) {
|
||||
case 'add':
|
||||
handleAdd()
|
||||
break;
|
||||
case 'export':
|
||||
exportTable()
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
const selectionChange = (data) => {
|
||||
console.log('data', data)
|
||||
selectData.value=data.map(item=>item.id)
|
||||
}
|
||||
const exportTable = () => {
|
||||
console.log('selectData',selectData.value)
|
||||
if (selectData.value.length === 0) {
|
||||
ElMessage.warning('请选择要导出的费用分摊')
|
||||
return
|
||||
}
|
||||
shareDetailExport(selectData.value).then(res => {
|
||||
console.log(res)
|
||||
let fileName = `科技研发项目工时及成本分摊汇总表.xlsx`
|
||||
const blob = new Blob([res.data])
|
||||
let a = document.createElement('a')
|
||||
a.href = URL.createObjectURL(blob)
|
||||
a.download = fileName
|
||||
a.click()
|
||||
})
|
||||
}
|
||||
const handleAdd = () => {
|
||||
router.push({
|
||||
name: 'Sharedetail/add',
|
||||
query: {}
|
||||
})
|
||||
}
|
||||
const init = async () => {
|
||||
const res = await getSubCompOpt()
|
||||
searchConfig.value.find(item=>item.prop == 'affiliatedCompanyIds').props.data = res.data
|
||||
}
|
||||
|
||||
// init()
|
||||
|
||||
</script>
|
||||
<style scoped lang="scss">
|
||||
:deep(.el-table__header) {
|
||||
.is-leaf:first-child {
|
||||
.cell {
|
||||
//margin-left: -25px !important;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
:deep(.el-table__body) {
|
||||
.el-table__cell:first-child {
|
||||
.cell {
|
||||
//margin-left: -13px !important;
|
||||
}
|
||||
}
|
||||
}
|
||||
:deep(.el-date-editor--month){
|
||||
width: 100%;
|
||||
}
|
||||
</style>
|
||||
@@ -1,15 +1,15 @@
|
||||
<template>
|
||||
<div v-loading="loading">
|
||||
<el-form :model="formData" ref="form" class="query-form" :rules="rules">
|
||||
<el-row>
|
||||
<el-col :span="12">
|
||||
<el-form-item label="分摊名称" prop="shareName">
|
||||
<div v-loading="loading" style="padding: 0 30px">
|
||||
<el-form :model="formData" ref="form" :rules="rules" style="margin-left: 5px;margin-top: 18px">
|
||||
<el-row :gutter="30">
|
||||
<el-col :span="6" style="margin-left: -15px">
|
||||
<el-form-item label="分摊名称" prop="shareName" >
|
||||
<el-input v-model="formData.shareName" placeholder="请输入分摊名称" clearable>
|
||||
</el-input>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="12">
|
||||
<el-form-item label="分摊月份" prop="apportionmentMonth">
|
||||
<el-col :span="6">
|
||||
<el-form-item label="分摊月份" prop="apportionmentMonth" label-width="80">
|
||||
<el-date-picker
|
||||
v-model="formData.apportionmentMonth"
|
||||
type="month"
|
||||
@@ -24,7 +24,7 @@
|
||||
<el-table-column prop="projectId" label="项目名称" min-width="230">
|
||||
<template #default="scope">
|
||||
<el-form-item prop="time" :rules="scope.row.projectId?'1':rules.projectId">
|
||||
<el-select v-model="scope.row.projectId" placeholder="请选择项目名称" clearable filterable>
|
||||
<el-select v-model="scope.row.projectId" placeholder="请选择项目名称" clearable filterable @change="selectProject(scope.row,scope.$index)">
|
||||
<el-option
|
||||
v-for="item in nameOptions"
|
||||
:key="item.value"
|
||||
@@ -40,7 +40,8 @@
|
||||
<template #default="scope">
|
||||
<el-form-item prop="researchPersonnelId">
|
||||
{{ scope.row.researchPersonnel }}
|
||||
<el-button color="#DED0B2" @click="showPersonnelPicker(scope.row,scope.$index)" style="margin-left: 10px">
|
||||
<el-button color="#DED0B2" @click="showPersonnelPicker(scope.row,scope.$index)"
|
||||
style="margin-left: 10px">
|
||||
{{ scope.row.researchPersonnel ? '更改' : '请选择研发人员' }}
|
||||
</el-button>
|
||||
</el-form-item>
|
||||
@@ -97,31 +98,35 @@
|
||||
</el-table-column>
|
||||
<el-table-column prop="oper" label="操作" min-width="130">
|
||||
<template #default="scope">
|
||||
<el-button type="primary" @click="handleCopy(scope.row)" link style="font-size: 18px">复制</el-button>
|
||||
<el-button type="primary" @click="handleDelete(scope.$index)" link style="font-size: 18px">删除</el-button>
|
||||
<el-button type="primary" @click="handleCopy(scope.row)" link style="font-size: 16px">复制</el-button>
|
||||
<el-button type="primary" @click="handleDelete(scope.$index)" link style="font-size: 16px">删除</el-button>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
</el-row>
|
||||
</el-form>
|
||||
<user-picker :multiple="false" ref="userPicker" title="请选择研发人员" v-model:value="userList" @ok="selected"
|
||||
:setNullToSelectList="true"/>
|
||||
<user-picker :multiple="false" ref="userPicker" title="请选择研发人员" v-model:value="userList"
|
||||
@ok="selectedResearchPersonnel" @cancelOrClear="researchPersonnelPickerCancel"
|
||||
:setNullToSelectList="true" :isResearch="true"/>
|
||||
|
||||
<div style="width:100%;text-align: center;padding: 10px">
|
||||
<el-button type="primary" @click="handleAdd" link style="font-size: 18px">添加一行</el-button>
|
||||
<el-button type="primary" @click="handleAdd" link style="font-size: 16px">添加一行</el-button>
|
||||
</div>
|
||||
<div class="approval-record">
|
||||
<div class="approval-title">
|
||||
<baseTitle title="审批记录" v-if="processDiagramViewer&& opentionData?.operationList"></baseTitle>
|
||||
<div v-else></div>
|
||||
<div style="display: flex;align-items: center;justify-content: flex-start;">
|
||||
<div class="base-title" style="margin-left: 10px;margin-right: 10px">流程图</div>
|
||||
<!-- <baseTitle title="审批记录" v-if="processDiagramViewer&& opentionData?.operationList"></baseTitle>-->
|
||||
<!-- <div v-else></div>-->
|
||||
<baseTitle title="审批记录"></baseTitle>
|
||||
<div class="diagram">
|
||||
<div class="base-title">流程图</div>
|
||||
<el-switch
|
||||
v-model="changeDiagram"
|
||||
style="--el-switch-on-color:#BEA266 ; --el-switch-off-color:#cecdcd"
|
||||
style="--el-switch-on-color:#BEA266 ; --el-switch-off-color:#cecdcd;margin-top: 1px"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
<el-empty :image-size="100" description="暂无审批记录"
|
||||
v-if="processDiagramViewer&& !opentionData?.operationList&&!changeDiagram"/>
|
||||
<div class="process">
|
||||
<operation-render
|
||||
v-if="processDiagramViewer&& opentionData?.operationList && opentionData?.operationList.length > 0&&!changeDiagram"
|
||||
@@ -154,6 +159,7 @@ import {useProcessStore} from '@/stores/processStore.js';
|
||||
import ProcessDiagramViewer from '@/views/workflow/common/ProcessDiagramViewer.vue';
|
||||
import OperationRender from '@/views/workflow/common/OperationRender.vue'
|
||||
import UserPicker from "@/views/workflow/process/common/UserPicker.vue";
|
||||
localStorage.removeItem('originallySelectedList')
|
||||
|
||||
const userList = ref([])
|
||||
const changeDiagram = ref(false)
|
||||
@@ -171,10 +177,11 @@ const rules = reactive({
|
||||
researchDuration: [{required: true, message: '请输入研发时长', trigger: ['blur', 'change']}],
|
||||
})
|
||||
const processStore = useProcessStore()
|
||||
const opentionData = ref()
|
||||
const opentionData = ref({})
|
||||
const processInstanceData = ref()
|
||||
const processDiagramViewer = ref(false)
|
||||
const loading = ref(false)
|
||||
const isRepeatResearchPersonnel = ref(false)
|
||||
const showTable = ref(true)
|
||||
const route = useRoute()
|
||||
const router = useRouter()
|
||||
@@ -206,34 +213,148 @@ const researchOptions = ref([])
|
||||
const showPersonnelPicker = (row, index) => {
|
||||
currentRow.value = row
|
||||
currentIndex.value = index
|
||||
if(row.companyName){
|
||||
if (row.companyName&&row.researchPersonnelId) {
|
||||
let userObj = {
|
||||
id: row.researchPersonnelId,
|
||||
name: row.researchPersonnel,
|
||||
companyName: row.companyName,
|
||||
accountType: row.accountType,
|
||||
}
|
||||
userList.value=[userObj]
|
||||
}else if(!row.researchPersonnel){
|
||||
userList.value=[]
|
||||
userList.value = [userObj]
|
||||
} else if (!row.researchPersonnel) {
|
||||
userList.value = []
|
||||
}
|
||||
nextTick(() => {
|
||||
userPicker.value.showUserPicker()
|
||||
})
|
||||
}
|
||||
const selected = (select) => {
|
||||
if (!select || select.length === 0) {
|
||||
return
|
||||
}
|
||||
formData.value.tableData.forEach((item, index) => {
|
||||
if (index === currentIndex.value) {
|
||||
item.researchPersonnelId = select[0].id
|
||||
item.researchPersonnel = select[0].name
|
||||
item.companyName = select[0].companyName
|
||||
item.accountType = select[0].accountType
|
||||
const selectProject=(row,index)=>{
|
||||
console.log('row,index',row,index)
|
||||
//先选择人员, 再选择项目: 再添加一行,重复操作
|
||||
const projectIdArray = formData.value.tableData.map(item => item.projectId)
|
||||
const researchPersonnelIdArray = formData.value.tableData.map(item => item.researchPersonnelId)
|
||||
// console.log('projectIdArray',projectIdArray)
|
||||
// console.log('researchPersonnelIdArray',researchPersonnelIdArray)
|
||||
const projectNumObj = getSelectProjectAndResearchPersonnelNum(projectIdArray)
|
||||
const researchPersonnelNumObj = getSelectProjectAndResearchPersonnelNum(researchPersonnelIdArray)
|
||||
let repeatProjectName=getProjectName(row.projectId)
|
||||
// console.log('currentRow.value',currentRow.value)
|
||||
for (let researchPersonnelIdKey in researchPersonnelNumObj) {//先判断人员是否重复
|
||||
if(currentRow.value.projectId){
|
||||
if(researchPersonnelNumObj[researchPersonnelIdKey]>1){
|
||||
ElNotification({
|
||||
title: '警告',
|
||||
message: `${repeatProjectName} 项目下,同一个研发人员不能分摊多次!`,
|
||||
type: 'warning',
|
||||
})
|
||||
row.researchPersonnelId = ''
|
||||
row.researchPersonnel = ''
|
||||
row.companyName = ''
|
||||
row.accountType = ''
|
||||
}
|
||||
}
|
||||
})
|
||||
userList.value=select
|
||||
|
||||
}
|
||||
// for (let projectIdKey in projectNumObj) {
|
||||
// // console.log('projectNumObjKey', projectIdKey, projectNumObj[projectIdKey])
|
||||
// if(projectNumObj[projectIdKey]>1){
|
||||
// // console.log('getProjectName(projectIdKey)',getProjectName(projectIdKey))
|
||||
// repeatProjectName=getProjectName(projectIdKey)
|
||||
//
|
||||
// }
|
||||
// }
|
||||
}
|
||||
const researchPersonnelPickerCancel = (select) => {
|
||||
console.log('select',select)
|
||||
if(select.length>0){
|
||||
formData.value.tableData?.forEach((item, index) => {
|
||||
if (index === currentIndex.value) {
|
||||
item.researchPersonnelId = select[0].id
|
||||
item.researchPersonnel = select[0].name
|
||||
item.companyName = select[0].companyName
|
||||
item.accountType = select[0].accountType
|
||||
}
|
||||
})
|
||||
}else{
|
||||
formData.value.tableData?.forEach((item, index) => {
|
||||
if (index === currentIndex.value) {
|
||||
item.researchPersonnelId = ''
|
||||
item.researchPersonnel = ''
|
||||
item.companyName = ''
|
||||
item.accountType = ''
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
const selectedResearchPersonnel = (select) => {
|
||||
if(select.length>0){
|
||||
formData.value.tableData?.forEach((item, index) => {
|
||||
if (index === currentIndex.value) {
|
||||
item.researchPersonnelId = select[0].id
|
||||
item.researchPersonnel = select[0].name
|
||||
item.companyName = select[0].companyName
|
||||
item.accountType = select[0].accountType
|
||||
}
|
||||
})
|
||||
}else{
|
||||
formData.value.tableData?.forEach((item, index) => {
|
||||
if (index === currentIndex.value) {
|
||||
item.researchPersonnelId = ''
|
||||
item.researchPersonnel = ''
|
||||
item.companyName = ''
|
||||
item.accountType = ''
|
||||
}
|
||||
})
|
||||
}
|
||||
//以下是为" 同一项目下,同一人不能分摊多次 "
|
||||
const projectIdArray = formData.value.tableData?.map(item => item.projectId)
|
||||
const researchPersonnelIdArray = formData.value.tableData?.map(item => item.researchPersonnelId)
|
||||
const projectNumObj = getSelectProjectAndResearchPersonnelNum(projectIdArray)
|
||||
const researchPersonnelNumObj = getSelectProjectAndResearchPersonnelNum(researchPersonnelIdArray)
|
||||
let repeatProjectName=''
|
||||
for (let projectIdKey in projectNumObj) {
|
||||
// console.log('projectNumObjKey', projectIdKey, projectNumObj[projectIdKey])
|
||||
if(projectNumObj[projectIdKey]>1){
|
||||
// console.log('getProjectName(projectIdKey)',getProjectName(projectIdKey))
|
||||
repeatProjectName=getProjectName(projectIdKey)
|
||||
}
|
||||
}
|
||||
for (let researchPersonnelIdKey in researchPersonnelNumObj) {
|
||||
// console.log('researchPersonnelIdKey', researchPersonnelIdKey, researchPersonnelNumObj[researchPersonnelIdKey])
|
||||
if(researchPersonnelNumObj[researchPersonnelIdKey]>1&&repeatProjectName&¤tRow.value.projectId){
|
||||
isRepeatResearchPersonnel.value=true
|
||||
ElNotification({
|
||||
title: '警告',
|
||||
message: `${repeatProjectName} 项目下,同一个研发人员不能分摊多次!`,
|
||||
type: 'warning',
|
||||
})
|
||||
formData.value.tableData.forEach((item,index)=>{
|
||||
if (index === currentIndex.value) {
|
||||
item.researchPersonnelId = ''
|
||||
item.researchPersonnel = ''
|
||||
item.companyName = ''
|
||||
item.accountType = ''
|
||||
}
|
||||
})
|
||||
}else{
|
||||
userList.value = select
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
/**
|
||||
* 获取一个项目/研发人员的选择次数
|
||||
* @param projectIdArray
|
||||
* @returns {{}}
|
||||
*/
|
||||
const getSelectProjectAndResearchPersonnelNum = (projectIdArray) => {
|
||||
const obj = {};
|
||||
for (let i = 0, l = projectIdArray.length; i < l; i++) {
|
||||
const item = projectIdArray[i];
|
||||
obj[item] = (obj[item] + 1) || 1;
|
||||
}
|
||||
return obj;
|
||||
}
|
||||
const getResearchOptions = async () => {
|
||||
const res = await getResearchUser()
|
||||
@@ -246,7 +367,7 @@ const getProjectOptions = async () => {
|
||||
const getProjectName = (id) => {
|
||||
let label = ''
|
||||
nameOptions.value.forEach(item => {
|
||||
if (item.value === id) {
|
||||
if (item.value == id) {
|
||||
label = item.label
|
||||
}
|
||||
})
|
||||
@@ -273,10 +394,10 @@ const handleCopy = (row) => {
|
||||
let copyObj = {
|
||||
projectId: row.projectId,
|
||||
projectName: '',
|
||||
accountType: row.accountType,
|
||||
companyName: row.companyName,
|
||||
researchPersonnelId: row.researchPersonnelId,
|
||||
researchPersonnel: row.researchPersonnel,
|
||||
// accountType: row.accountType,
|
||||
// companyName: row.companyName,
|
||||
// researchPersonnelId: row.researchPersonnelId,
|
||||
// researchPersonnel: row.researchPersonnel,
|
||||
wagesPayable: row.wagesPayable,
|
||||
performance: row.performance,
|
||||
reserveFund: row.reserveFund,
|
||||
@@ -291,6 +412,7 @@ const handleDelete = (index) => {
|
||||
formData.value.tableData.splice(index, 1)
|
||||
}
|
||||
const handleSubmit = (instance) => {
|
||||
console.log('tableData', formData.value.tableData)
|
||||
if (!instance) return
|
||||
instance.validate(async (valid) => {
|
||||
if (!valid) {
|
||||
@@ -323,7 +445,7 @@ const handleSubmit = (instance) => {
|
||||
usrAllocations: formData.value.tableData,
|
||||
deploymentId: processInstanceData.value.deploymentId,
|
||||
}
|
||||
// console.log('params', params, formData.value.tableData)
|
||||
console.log('params', params, formData.value.tableData)
|
||||
const {code, msg} = await addAllocation(params)
|
||||
ElNotification({
|
||||
title: '提示',
|
||||
@@ -370,7 +492,7 @@ const handleResubmit = (instance) => {
|
||||
allocationId: formData.value.allocationId,
|
||||
shareName: formData.value.shareName,
|
||||
apportionmentMonth: formData.value.apportionmentMonth,
|
||||
usrAllocations:formData.value.tableData,
|
||||
usrAllocations: formData.value.tableData,
|
||||
deploymentId: processInstanceData.value.deploymentId,
|
||||
}
|
||||
// console.log('params', params, formData.value.tableData)
|
||||
@@ -473,4 +595,14 @@ onMounted(() => {
|
||||
}
|
||||
}
|
||||
}
|
||||
:deep(.el-date-editor--month){
|
||||
width: 100%!important;
|
||||
}
|
||||
:deep(.el-input-number) {
|
||||
width: 100%;
|
||||
|
||||
.el-input__inner {
|
||||
text-align: left;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
||||
@@ -1,12 +1,13 @@
|
||||
<template>
|
||||
<el-form :model="formData" ref="form" class="query-form" label-width="auto">
|
||||
<div style="padding: 0 30px">
|
||||
<el-form :model="formData" ref="form" label-width="auto" style="margin-top: 18px">
|
||||
<el-row>
|
||||
<el-col :span="12">
|
||||
<el-col :span="6">
|
||||
<el-form-item label="分摊名称">
|
||||
<span>{{ formData.shareName }}</span>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="12">
|
||||
<el-col :span="6">
|
||||
<el-form-item label="分摊月份">
|
||||
<span>{{ formData.apportionmentMonth }}</span>
|
||||
</el-form-item>
|
||||
@@ -52,7 +53,9 @@
|
||||
</div>
|
||||
</div>
|
||||
<opinion v-if="shareData.taskId" :formData="shareData.formData" :taskId="shareData.taskId"
|
||||
:taskUserOptionList="shareData.taskUserOptionList"
|
||||
v-model:value="auditOpinion"></opinion>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup lang="jsx">
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
<template>
|
||||
<fvSearchForm :searchConfig="searchConfig" @search="search"></fvSearchForm>
|
||||
<fvSearchForm :searchConfig="searchConfig" @search="search" style="margin-left: 16px"></fvSearchForm>
|
||||
<fvTable ref="tableIns" :tableConfig="tableConfig" @headBtnClick="headBtnClick">
|
||||
<template #empty>
|
||||
<el-empty description="暂无数据"/>
|
||||
@@ -96,6 +96,16 @@ const searchConfig = reactive([
|
||||
const tableIns = ref()
|
||||
const tableConfig = reactive({
|
||||
columns: [
|
||||
{
|
||||
prop: 'index',
|
||||
type: 'index',
|
||||
label: '序号',
|
||||
align: 'center',
|
||||
width:85,
|
||||
index: index => {
|
||||
return (tableIns.value.getQuery().pageNum - 1) * tableIns.value.getQuery().pageSize + index + 1
|
||||
}
|
||||
},
|
||||
{
|
||||
prop: 'shareName',
|
||||
label: '分摊名称',
|
||||
@@ -165,7 +175,6 @@ const tableConfig = reactive({
|
||||
{
|
||||
buttons.has("delete") ?
|
||||
<popover-delete name={row.shareName} type={'费用分摊'} btnType={'danger'}
|
||||
perm={['mosr:requirement:del']}
|
||||
onDelete={() => handleDelete(row)}/>
|
||||
: ''
|
||||
}
|
||||
@@ -234,6 +243,23 @@ const headBtnClick = (key) => {
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
<style scoped lang="scss">
|
||||
:deep(.el-table__header) {
|
||||
.is-leaf:first-child {
|
||||
.cell {
|
||||
margin-left: -25px !important;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
:deep(.el-table__body) {
|
||||
.el-table__cell:first-child {
|
||||
.cell {
|
||||
margin-left: -13px !important;
|
||||
}
|
||||
}
|
||||
}
|
||||
:deep(.el-date-editor--month){
|
||||
width: 100%;
|
||||
}
|
||||
</style>
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
<template>
|
||||
<div style="padding: 0 10px;">
|
||||
<baseTitle title="费用分摊详情"></baseTitle>
|
||||
<el-form :model="formData" ref="form" class="query-form" label-width="auto">
|
||||
<el-row>
|
||||
<el-col :span="24">
|
||||
@@ -53,6 +54,7 @@
|
||||
</div>
|
||||
</div>
|
||||
<opinion-moblie v-if="shareData.taskId" :formData="shareData.formData" :taskId="shareData.taskId"
|
||||
:taskUserOptionList="shareData.taskUserOptionList"
|
||||
v-model:value="auditOpinion"></opinion-moblie>
|
||||
</div>
|
||||
</template>
|
||||
@@ -65,8 +67,7 @@ import {useProcessStore} from '@/stores/processStore.js';
|
||||
import {getAllocationDetail} from "@/api/expense-manage";
|
||||
import AllocationSummaryDetailMoblie from './AllocationSummaryDetailMoblie.vue'
|
||||
import ExpenseDetailMoblie from './ExpenseDetailMoblie.vue'
|
||||
import OpinionMoblie from "@/views/project-demand/requirement/moblieDetail/OpinionMoblie.vue";
|
||||
|
||||
import OpinionMoblie from '@/views/project-management/mobledetail/OpinionMoblie.vue'
|
||||
const changeDiagram = ref(false)
|
||||
const processStore = useProcessStore()
|
||||
const route = useRoute()
|
||||
|
||||