Compare commits
700 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 77140864ef | |||
| f70dbe4378 | |||
| 7a1cba4553 | |||
| e847252e12 | |||
| 922e86070d | |||
| 52529d1f58 | |||
| 16b22bc8a7 | |||
| 1739f7a2f9 | |||
| a62a124710 | |||
| 4c66d1fbe0 | |||
| c24a1495ff | |||
| a4e78b864a | |||
| 329d52f89f | |||
| ff50030364 | |||
| 73b1696b0a | |||
| 9af9dd0df7 | |||
| b3a8d504d1 | |||
| 30c2f655e7 | |||
| c64badfc23 | |||
| 2218457237 | |||
| d4168720ac | |||
| e393b11b61 | |||
| f7cef30b9c | |||
| 16203b14f6 | |||
| 9ce345eb76 | |||
| ec1efb4482 | |||
| 5462b7036a | |||
| ac6d8f01ba | |||
| 2efef9e8ee | |||
| 60b5c99e74 | |||
| 97cf167090 | |||
| f68ba190a8 | |||
| 4cfda0fbf1 | |||
| df77cbfb47 | |||
| 26210ed8d4 | |||
| 9e2a66f1d5 | |||
| 1fbf5d160a | |||
| cb8c1743dc | |||
| dc8fbd1839 | |||
| e01620689b | |||
| c36054b970 | |||
| c0b6ee1763 | |||
| fe62542b7c | |||
| bdd7820a69 | |||
| 1603359120 | |||
| 360684245e | |||
| da8b5018ea | |||
| 9ba946621e | |||
| e689699f44 | |||
| 521d4e3ac5 | |||
| 1708b6564b | |||
| 994819e8a0 | |||
| 4a5091825c | |||
| 1282e802b5 | |||
| 9ca92430ee | |||
| 964d055021 | |||
| cd5e00bbfb | |||
| ecf0a268d3 | |||
| d9833fab47 | |||
| f84afc7903 | |||
| fea7d97aa3 | |||
| a74cc2f19d | |||
| e297b5fe9f | |||
| edbd8de356 | |||
| cbb46aca69 | |||
| abd64ed20c | |||
| 13756956a6 | |||
| 121511523f | |||
| 1fe6531924 | |||
| 38ea7d0067 | |||
| 58ef46f754 | |||
| ec49ba3fd1 | |||
| b7c8b31a91 | |||
| f3fd40008b | |||
| 94fc5f6942 | |||
| c5a8c836c0 | |||
| 048530a893 | |||
| 7ed5fc8fd3 | |||
| 5f1afe4bdc | |||
| 0cd20d12dd | |||
| b4a94d1605 | |||
| 7879a9ef85 | |||
| d6a3614d98 | |||
| a58d66d72e | |||
| daf3055b42 | |||
| 3744ebcd5a | |||
| 6cac241144 | |||
| 76a800ddbb | |||
| bbc96a18bc | |||
| 23294c1f93 | |||
| 130f7c82a8 | |||
| 0ab67c7a9b | |||
| 5512841ba2 | |||
| 7fbd1bb92d | |||
| 5dd4cd4bc9 | |||
| a6c37bb112 | |||
| 3c3639613e | |||
| 74b5ef0b27 | |||
| 420521d90a | |||
| 73a37a07dd | |||
| 7dacb69275 | |||
| a712be7cd4 | |||
| 08d68cbcae | |||
| b779bd4fd5 | |||
| c3b2b4d4d0 | |||
| 1b3d022969 | |||
| ae8a913f9b | |||
| 421844895e | |||
| 64e6d8148e | |||
| 47983dec40 | |||
| 139b34ca19 | |||
| 9ef61e317c | |||
| fe0f1760bd | |||
| 4a2fbd4d3d | |||
| ee55d7fa72 | |||
| e06cd279cf | |||
| 6eecbb0e4b | |||
| 2ff561e185 | |||
| dd96e37116 | |||
| b55091a066 | |||
| 65363ea918 | |||
| c24e09f0c7 | |||
| c45fee2a26 | |||
| d4f2fcdeb7 | |||
| 3d082853d7 | |||
| 199c146672 | |||
| 98a4964c7c | |||
| 50b75165bd | |||
| ccdbe9d607 | |||
| 010275b09e | |||
| 1864223c9b | |||
| 0c6ec87ce5 | |||
| 1e069587fe | |||
| 8bb4682e98 | |||
| 2d538c15de | |||
| ec20847f31 | |||
| 6efedcebd4 | |||
| 448ddecb56 | |||
| b340652b4d | |||
| 562064712d | |||
| 90f84455d3 | |||
| 01bcf43ae8 | |||
| 2e0b10e643 | |||
| 15a7ef4015 | |||
| fad6441f4c | |||
| 96cb398315 | |||
| a90c5c41ea | |||
| 7f5bd7e42b | |||
| b00b4358e0 | |||
| cf552f6e5d | |||
| fb266f08da | |||
| 9c682af44a | |||
| dbffb0a7bd | |||
| 4f84034814 | |||
| 1e291f8408 | |||
| 87e547d2f1 | |||
| 529953d98d | |||
| 2d14e22322 | |||
| 267aeec5ba | |||
| 809860b8db | |||
| 5370b21ef9 | |||
| 17a7c63aec | |||
| 7a3e245887 | |||
| 3b3fc618d6 | |||
| f6abc362fd | |||
| 601955e60d | |||
| 6f7181db2f | |||
| c327fecb49 | |||
| 0446f88e9e | |||
| a01151130e | |||
| 9ca8da045c | |||
| 1ebf86b510 | |||
| 9e35d16fa6 | |||
| 315b06d103 | |||
| 95e8e7bca7 | |||
| 8d0e33ba23 | |||
| 3754f7da0d | |||
| 213aff3993 | |||
| e3c746d314 | |||
| 7377460ba0 | |||
| 2d8ed35096 | |||
| 8941c6b065 | |||
| 0798b371b6 | |||
| ea6bd6fabe | |||
| f83bdfc9ad | |||
| c5ac76823d | |||
| 35a9e02b8c | |||
| ccd65f26d4 | |||
| bf1234a9c2 | |||
| 92c448e2e1 | |||
| 2808f40737 | |||
| 61a44483d4 | |||
| 8ae3de511b | |||
| 58a374bde9 | |||
| 051813d39d | |||
| 843c5af4c2 | |||
| cd8a8ecf58 | |||
| 2ac126dd42 | |||
| 1fd4f923ad | |||
| f289f68898 | |||
| fa4a84b3e2 | |||
| 3406448475 | |||
| cb07146657 | |||
| b14477098d | |||
| 3238a83d4e | |||
| fe94d7ebc6 | |||
| 181075ad19 | |||
| 50562db4ef | |||
| 29a87ba93e | |||
| abf541df72 | |||
| cf10e108ef | |||
| a8e2452dcc | |||
| 5f74093660 | |||
| 8e0384c833 | |||
| 02c9bca336 | |||
| 777bbb5ae3 | |||
| 60f1fea356 | |||
| 84d5a4f005 | |||
| 9bdd7b8a58 | |||
| 23135c6f39 | |||
| 724dd54822 | |||
| bdbbec3d97 | |||
| 97bea2163c | |||
| af747c61cc | |||
| a907ef523c | |||
| 8f3cdf0dde | |||
| 53ca5d062c | |||
| a666557781 | |||
| 7386ac26f5 | |||
| d4cd3d4bb6 | |||
| 1808e994ae | |||
| 4828a00602 | |||
| c38fd1b7b7 | |||
| f86dd89cdd | |||
| 877a508f01 | |||
| 930e2052a4 | |||
| f82a19f591 | |||
| 9f9db03cc3 | |||
| ca05b65638 | |||
| 0971805caa | |||
| 1405cb0b99 | |||
| c4dc9669f3 | |||
| 78e7be8766 | |||
| 58868268dd | |||
| 738b433041 | |||
| 02d853d46a | |||
| 97f84286d8 | |||
| 7adfd160cc | |||
| cd5f444b24 | |||
| 920b5b12ec | |||
| 06cbe0e478 | |||
| 6649924d10 | |||
| c9bab8fb02 | |||
| 768e14bdb9 | |||
| 61773a13b4 | |||
| 90360cfeb5 | |||
| bcfda44730 | |||
| 063a10f6bb | |||
| 508caebdcd | |||
| e2d7b6a5e0 | |||
| 10ff5d7b27 | |||
| 4a7eef8ad6 | |||
| c4834255c0 | |||
| 6fdb083809 | |||
| ac08199580 | |||
| ba2f305f33 | |||
| acf05c6107 | |||
| d30e9cb30b | |||
| b55a56d6a7 | |||
| 706ba5a7a9 | |||
| f6cf6706c7 | |||
| 0311a93252 | |||
| a838a43ae5 | |||
| a01b94f131 | |||
| 18de0e8a43 | |||
| 328461b093 | |||
| 1bb1e032d6 | |||
| 97788e3c8f | |||
| 1e59bc8ca1 | |||
| 59263da76e | |||
| 103b5ddbd6 | |||
| d799c8df8b | |||
| a3c4cb1aea | |||
| fc8caee0c3 | |||
| 05afe870e7 | |||
| 349c1710fe | |||
| 690832e3eb | |||
| 5b295dbec3 | |||
| b96700ab30 | |||
| 6d85736eea | |||
| f1d1dd5684 | |||
| f974a8c846 | |||
| 1dcd2fcdf6 | |||
| eff2b1f8ba | |||
| 7efc16990e | |||
| 44d92ac1c6 | |||
| 733cc7e9a5 | |||
| 4fe2f35183 | |||
| 7bab761db6 | |||
| d7fb26d527 | |||
| 42258626b0 | |||
| 272dbd2107 | |||
| 895a870dfc | |||
| 6332d96131 | |||
| c90e3d6424 | |||
| fadeacf6f8 | |||
| 7c86193215 | |||
| 4e84cbd953 | |||
| 38f640c6d9 | |||
| 78fc0ada98 | |||
| 2ad71017f9 | |||
| 05f94aeadb | |||
| fdb5b222b9 | |||
| bf3a9112f2 | |||
| a3700ad685 | |||
| 61300fbcc3 | |||
| fc5a957ddd | |||
| 2580475f78 | |||
| 711151c7d6 | |||
| f839e8b3f0 | |||
| 24d9533dca | |||
| 0d1588f58a | |||
| e49f88d311 | |||
| bbeede8dbc | |||
| 434055f86c | |||
| 417590e99c | |||
| f5c3d5c56b | |||
| faedab24bf | |||
| 6c4c296071 | |||
| f3cdc2e765 | |||
| 8377962836 | |||
| 73226f6820 | |||
| b614117bd2 | |||
| 1db1e885c2 | |||
| e443cec064 | |||
| 97e7ffccae | |||
| db235c10e8 | |||
| 2d3e4b4a95 | |||
| 3d254c02c1 | |||
| e10d10e4f1 | |||
| 3ccebfcff1 | |||
| 1452a9698f | |||
| 7630fce9a3 | |||
| 5a08754735 | |||
| 220d306a54 | |||
| 08c12a7820 | |||
| 925d7c2ad2 | |||
| e297cb9b77 | |||
| c45ba9a34d | |||
| b7e87ba18d | |||
| 4667eb232c | |||
| 926677426e | |||
| fd0f185992 | |||
| c45c2b9aba | |||
| f42b42d6b1 | |||
| 8098cf3ee2 | |||
| 30a140f2d8 | |||
| a56d6f4bf5 | |||
| c8fc2c8b3f | |||
| a31a55601e | |||
| 46a8c12a7d | |||
| 8030690fe3 | |||
| 5dc1160666 | |||
| b1116e73c0 | |||
| 9a412ca570 | |||
| ebd5c09145 | |||
| 0f80ab8d5f | |||
| 7ac2e2e2ed | |||
| 39456923d3 | |||
| 1b728fffc7 | |||
| 8e5732d857 | |||
| 2fb6691ca6 | |||
| b3339f7fe0 | |||
| 68d42a514f | |||
| 1dfd7fa8c5 | |||
| 85d834432a | |||
| 7c0434d182 | |||
| 667e02460c | |||
| 0d19332730 | |||
| 0858901d31 | |||
| 76d824c16c | |||
| c7dd798af3 | |||
| 0232bb90dc | |||
| 0f903dacf6 | |||
| 14c778e32d | |||
| 0b57d9d7cb | |||
| c370b297d2 | |||
| 0141c68167 | |||
| e858a7c6db | |||
| e433b5f7da | |||
| 2a43a442de | |||
| 239b970055 | |||
| b2e7ed44f3 | |||
| fdd86ba5e9 | |||
| 1ae8deca99 | |||
| caade5c791 | |||
| 8f88e11403 | |||
| 25c71c60ac | |||
| 56890364fc | |||
| 80a1a12757 | |||
| 4d2b2c7a65 | |||
| a3b7d0d511 | |||
| d7c45f0e0d | |||
| 0f43fff242 | |||
| de18cfe596 | |||
| f86ccae28c | |||
| 0e9739af0b | |||
| db6a361857 | |||
| 090781db0c | |||
| e79465c90d | |||
| ab52e61ed1 | |||
| 73b25d2eec | |||
| b5ea28cd27 | |||
| fd37291716 | |||
| 2251f218d8 | |||
| dd246b2c16 | |||
| 6ab033c4cf | |||
| 421a0c36ed | |||
| f25696f22b | |||
| 4d4adc4fac | |||
| c7ea56bb7e | |||
| 8737e0a6eb | |||
| f5746423bf | |||
| 0873ce591f | |||
| af1f1e9fdf | |||
| 2f29c5f118 | |||
| 47b0646811 | |||
| a7f42a6459 | |||
| 0e2d961902 | |||
| 9517b0144f | |||
| 0fb61ce30e | |||
| 912cb397ea | |||
| cf13c87873 | |||
| 2f9d28beb0 | |||
| 5f3b95b699 | |||
| b8c2197e89 | |||
| e46f2b3390 | |||
| dd8267097e | |||
| c7b15e6b8b | |||
| c18f55d6dd | |||
| 163d09c71b | |||
| 3f264c17ba | |||
| 6a32cf28fb | |||
| f9e4a978fd | |||
| 14a2a09d7b | |||
| f099cf6d30 | |||
| 6cc719ebf5 | |||
| 81be6f375b | |||
| cd1bd1109c | |||
| cd45e55620 | |||
| 59f40dfd02 | |||
| 8416381fa0 | |||
| 72fb7031e5 | |||
| 2c5f610ed0 | |||
| 7246eb6ebc | |||
| fd52795f49 | |||
| 2b0bf6cbb7 | |||
| 033b8c702a | |||
| dd78dbde5c | |||
| 1cfd077ae7 | |||
| 9b729aa79b | |||
| ef914283aa | |||
| d1eef94e6b | |||
| 5a0e59b103 | |||
| 227f50b9d1 | |||
| fa6dfc6acb | |||
| 365994b1af | |||
| 201f230e80 | |||
| 42d2df07a7 | |||
| f9c12d7bd8 | |||
| be9ed269fa | |||
| 4438fee3ca | |||
| 2c8b06dc7b | |||
| ce31a604b2 | |||
| cbd7c91d26 | |||
| 285b240dec | |||
| a0aa6d25d4 | |||
| 09fb03a1ce | |||
| f72df9df27 | |||
| 5659bd96f2 | |||
| 2eb81924e4 | |||
| 0c2360972b | |||
| 93200ac057 | |||
| c2b08c2627 | |||
| 7eb8d76c87 | |||
| 03706c054d | |||
| 39b4218349 | |||
| 4c6c7182e2 | |||
| ec63e05575 | |||
| bb708d6084 | |||
| 2ee630e94c | |||
| aeb39e1476 | |||
| 723173426b | |||
| 44567e552a | |||
| 1e503f444b | |||
| a7709d06d1 | |||
| d1470bb19d | |||
| 614d771b84 | |||
| dd6388ca03 | |||
| 6c10f8dcb2 | |||
| 00ea1b898a | |||
| 120a54279f | |||
| 9241369cbb | |||
| 9455d9ed56 | |||
| d63dc106b3 | |||
| d69517b11e | |||
| 53efe20a86 | |||
| 2e08328ec1 | |||
| d0aa8b47af | |||
| 40726f1405 | |||
| a51da2059b | |||
| eee367c5a0 | |||
| 9939f2c2e1 | |||
| 3a4efcc1f8 | |||
| f610f45523 | |||
| 68d7d64ea7 | |||
| 8e57bc4e9b | |||
| caa22ae9d2 | |||
| e67d0f7d87 | |||
| 0b5baa70f0 | |||
| 9ed3cc5a74 | |||
| 03267b2051 | |||
| 3611ed6c88 | |||
| 07b3a8dfd8 | |||
| 0000c071e7 | |||
| aa63664892 | |||
| 3f65ad6ae6 | |||
| 31b8930222 | |||
| ec18ca0ee1 | |||
| 3273274369 | |||
| 95675de30b | |||
| 11591b9708 | |||
| ca1758dc48 | |||
| 59c21a9c8d | |||
| cdc86bbe47 | |||
| 2c963d9a7d | |||
| b8d9221d9b | |||
| 50c80614d1 | |||
| 1ae1767063 | |||
| 41643a729a | |||
| 9dcb9cee32 | |||
| 0ef19e91bb | |||
| 0b58ac5779 | |||
| c5f23fbd12 | |||
| 5e9707cf1a | |||
| 9f1f041494 | |||
| 44eb05fb5b | |||
| 92532333cb | |||
| b934128449 | |||
| 7bac88d593 | |||
| b8009142ed | |||
| f812e5f239 | |||
| e16618142a | |||
| 145d3580a0 | |||
| 83957db37f | |||
| 6d575649cf | |||
| 4c6096224d | |||
| 1270a60ad8 | |||
| 20466d07df | |||
| e04d82961f | |||
| 7bca6e1953 | |||
| 26593eda27 | |||
| d91e973639 | |||
| b060ab6315 | |||
| 16f84216f5 | |||
| c85ca31718 | |||
| 9192d5c11f | |||
| aa0af37e91 | |||
| ca63cbf801 | |||
| 08bafe09a7 | |||
| b3b04cfc54 | |||
| 08c8f46eb3 | |||
| b0a504a44c | |||
| fe5e448dfb | |||
| 5b9b93ffe0 | |||
| 0db0ea3a6b | |||
| 385404dcf7 | |||
| fc329c6428 | |||
| 546f11bdae | |||
| 189b247ad8 | |||
| c25803aa74 | |||
| 1fcb6fa911 | |||
| 64cc2d79da | |||
| 66ab4a4a8e | |||
| e4a80ce9b5 | |||
| 0ab7dee52d | |||
| aa0fe64afe | |||
| 4a6339c9db | |||
| 8d4846329e | |||
| 2a768b6fc8 | |||
| bf3930d29f | |||
| ea6cd5eca1 | |||
| e1f6cd70df | |||
| 4ec52b7033 | |||
| 1d66023bd1 | |||
| e35f81f2c8 | |||
| 6a825dca7d | |||
| 849b887201 | |||
| 7a2f4c1d56 | |||
| 4aa19ebae9 | |||
| f31b194a53 | |||
| 177eefc447 | |||
| f1f1ed4040 | |||
| dcb57c6c37 | |||
| aa59624208 | |||
| 4eadd201e5 | |||
| 8793e82f69 | |||
| b7d28cb36f | |||
| 25317d5f64 | |||
| e086456777 | |||
| 7dc8a0ac6b | |||
| 8fb63c94d3 | |||
| 8f2662b254 | |||
| 89745e1214 | |||
| 18c08b6aa3 | |||
| 4d30a8ade5 | |||
| d776ca32c5 | |||
| 6aadeb5b84 | |||
| d832015136 | |||
| 1fb43f2cda | |||
| 265842e7bf | |||
| 0303a74a33 | |||
| adc56ddd82 | |||
| d63aec2b3c | |||
| 6c2cb47bf8 | |||
| 653884e7b3 | |||
| 095e5131e8 | |||
| 4d0da8c4d2 | |||
| 7797bd2a9b | |||
| e9664e294b | |||
| 5ab84eb233 | |||
| 5af382dbc5 | |||
| 8cdaf4b9ed | |||
| 10fd966959 | |||
| 638dbef30a | |||
| d090d03da0 | |||
| 1b8ca0baae | |||
| 2ae815385b | |||
| aa3a1bebc8 | |||
| bb7b9ee591 | |||
| 34d33aae8e | |||
| 4c1c024afa | |||
| 110eccd9e4 | |||
| 72ca2d4564 | |||
| 1633764419 | |||
| 933572648c | |||
| ed3e40790e | |||
| 57b3f14de6 | |||
| db9f48ade0 | |||
| 65ca30a920 | |||
| 76bf2e3a53 | |||
| d1b48623d7 | |||
| 2dc35a21da | |||
| 633226fddc | |||
| c1a8a283f3 | |||
| 57a1d0ba48 | |||
| 983ec8fcf3 | |||
| 76cf93a2c9 | |||
| 14c88f23ff | |||
| 8db622eee4 | |||
| 9d2da393d7 | |||
| 1e68b02ed9 | |||
| ddf5f8bd9d | |||
| aa29b37144 | |||
| 699785f995 | |||
| f5ddd08ebf | |||
| f5ae16866d | |||
| 82b6bce847 | |||
| a8a627c918 | |||
| d1b3b739d3 | |||
| ca1ee9fc2b | |||
| 6ea3adbd55 | |||
| ae8cfa40be | |||
| bc80d7e91c | |||
| 907ccebfdf | |||
| 79b94168ba | |||
| 6b920a59f3 | |||
| 4a66919e5c | |||
| 2dd0dfac87 | |||
| aab33be34a | |||
| 4346720855 | |||
| 7392165189 | |||
| 6773c87d8e | |||
| 4353fe1bee | |||
| e0eac8f703 | |||
| b489f8f6f1 | |||
| cc1dc14c84 | |||
| aa9ec41921 | |||
| 519841c323 | |||
| cdc766c72b | |||
| 4ab3eb9ce8 | |||
| 56485f01b2 | |||
| 2125f32e53 | |||
| a02881fcaf | |||
| b5fae8f571 | |||
| e8e5a9b955 | |||
| b5ec7459a6 | |||
| aa57264d53 | |||
| f6ac12ee65 | |||
| 65fe7682ff |
@@ -0,0 +1,282 @@
|
||||
# Xboard 管理端前端 - 基础登录功能实施计划
|
||||
|
||||
## 任务类型
|
||||
|
||||
- [x] 前端 (Vue3 + TypeScript + Vite + Element Plus)
|
||||
- [ ] 后端 (无需改动,复用现有 API)
|
||||
- [ ] 全栈
|
||||
|
||||
## 需求概述
|
||||
|
||||
为 Xboard 创建独立的管理端前端项目,技术栈:Vue3 + TypeScript + Vite + Element Plus。第一阶段实现基础登录功能,包括:
|
||||
|
||||
- 管理员登录页面(邮箱 + 密码)
|
||||
- Token 认证与路由守卫
|
||||
- 登录后 Dashboard 占位页
|
||||
- 基础布局框架(侧边栏 + 顶栏)
|
||||
|
||||
## 技术方案
|
||||
|
||||
### 后端 API 契约(已存在,无需改动)
|
||||
|
||||
| 接口 | 方法 | URL | 说明 |
|
||||
|------|------|-----|------|
|
||||
| 登录 | POST | `/api/v2/passport/auth/login` | `{email, password}` → `{auth_data, is_admin, token}` |
|
||||
| 管理接口前缀 | - | `/api/v2/{secure_path}/...` | secure_path 从后端 admin_setting 获取 |
|
||||
| 系统状态探针 | GET | `/api/v2/{secure_path}/system/getSystemStatus` | 登录后验证 admin 权限 |
|
||||
|
||||
**关键发现:**
|
||||
- 登录接口是通用用户接口,`is_admin` 在响应中标识管理员身份
|
||||
- `auth_data`(格式 `Bearer xxx`)是鉴权凭证,`token` 是邀请码字段,不可用作认证
|
||||
- Admin 中间件使用 Sanctum guard,通过 `Authorization` header 传递 Bearer token
|
||||
- `secure_path` 是动态的,首期从 Laravel 的 `window.settings.secure_path` 获取
|
||||
|
||||
### 部署策略:独立源码 + Laravel 托管 dist
|
||||
|
||||
首期将 Vue3 项目构建产物放到 Laravel 的 `public/` 目录下,由 Laravel 的 `admin.blade.php` 通过 `window.settings` 注入运行时配置。这样 `secure_path` 自举最简单,无需跨域。
|
||||
|
||||
### 前端分析交叉验证(Codex 后端视角 + 前端 UI/UX 视角)
|
||||
|
||||
**一致观点(强信号):**
|
||||
- 方案 A(独立源码 + Laravel 托管 dist)是最务实的首期路线
|
||||
- `secure_path` 从运行时配置获取,不在前端推导
|
||||
- 登录后必须校验 `is_admin`
|
||||
|
||||
**前端分析补充建议(已纳入计划):**
|
||||
1. **工程化优化**:使用 `unplugin-auto-import` + `unplugin-vue-components` 实现 Element Plus 按需引入,优化包体积
|
||||
2. **暗色/亮色主题切换**:Element Plus 原生支持 dark mode,首期预留切换能力
|
||||
3. **前端登录频率限制提示**:在登录表单增加防抖,429 时显示倒计时提示
|
||||
4. **Token 过期自动重定向**:Axios 拦截器中 401 响应自动清除 token 并跳转登录页
|
||||
5. **动态路径策略**:`VITE_ADMIN_PATH` 环境变量作为 `secure_path` 的默认值,同时支持从 `window.settings.secure_path` 动态覆盖
|
||||
|
||||
### 项目结构
|
||||
|
||||
```
|
||||
admin-frontend/ # 独立前端项目根目录
|
||||
├── index.html
|
||||
├── package.json
|
||||
├── tsconfig.json
|
||||
├── tsconfig.node.json
|
||||
├── vite.config.ts
|
||||
├── env.d.ts
|
||||
├── .env
|
||||
├── .env.development
|
||||
├── .env.production
|
||||
├── public/
|
||||
│ └── favicon.ico
|
||||
└── src/
|
||||
├── main.ts # 应用入口
|
||||
├── App.vue # 根组件
|
||||
├── api/
|
||||
│ ├── client.ts # Axios 实例与拦截器
|
||||
│ ├── passport.ts # 登录相关 API
|
||||
│ └── admin.ts # 管理端 API(带 secure_path)
|
||||
├── stores/
|
||||
│ ├── auth.ts # 认证状态(Pinia)
|
||||
│ └── app.ts # 应用运行时配置
|
||||
├── router/
|
||||
│ ├── index.ts # 路由定义
|
||||
│ └── guards.ts # 路由守卫
|
||||
├── layouts/
|
||||
│ └── AdminLayout.vue # 管理端主布局
|
||||
├── views/
|
||||
│ ├── login/
|
||||
│ │ └── LoginView.vue # 登录页
|
||||
│ └── dashboard/
|
||||
│ └── DashboardView.vue # 仪表盘占位页
|
||||
├── types/
|
||||
│ ├── api.d.ts # API 响应类型
|
||||
│ └── env.d.ts # 环境变量类型
|
||||
├── utils/
|
||||
│ ├── token.ts # Token 存储工具
|
||||
│ └── runtime.ts # 运行时配置解析
|
||||
└── styles/
|
||||
└── index.scss # 全局样式
|
||||
```
|
||||
|
||||
## 实施步骤
|
||||
|
||||
### Step 1: 初始化项目骨架
|
||||
|
||||
**预期产物:** 可运行的空 Vue3 + TS 项目
|
||||
|
||||
- 使用 `npm create vite@latest admin-frontend -- --template vue-ts` 创建项目
|
||||
- 安装依赖:`element-plus`, `pinia`, `vue-router`, `axios`, `sass`, `@element-plus/icons-vue`
|
||||
- 安装开发依赖:`unplugin-auto-import`, `unplugin-vue-components`(Element Plus 按需引入)
|
||||
- 配置 `vite.config.ts`(代理、别名、构建输出路径、AutoImport 插件)
|
||||
- 配置 `tsconfig.json` 路径别名
|
||||
- 创建 `.env.development` 和 `.env.production`
|
||||
|
||||
**Vite 配置要点:**
|
||||
```typescript
|
||||
// vite.config.ts
|
||||
export default defineConfig({
|
||||
base: '/assets/admin/',
|
||||
resolve: { alias: { '@': '/src' } },
|
||||
plugins: [
|
||||
vue(),
|
||||
AutoImport({ resolvers: [ElementPlusResolver()] }),
|
||||
Components({ resolvers: [ElementPlusResolver()] }),
|
||||
],
|
||||
server: {
|
||||
port: 5173,
|
||||
proxy: {
|
||||
'/api': {
|
||||
target: 'http://localhost:8000',
|
||||
changeOrigin: true,
|
||||
}
|
||||
}
|
||||
},
|
||||
build: {
|
||||
outDir: '../public/assets/admin',
|
||||
emptyOutDir: true,
|
||||
}
|
||||
})
|
||||
```
|
||||
|
||||
**环境变量:**
|
||||
```
|
||||
# .env.development
|
||||
VITE_API_BASE_URL=/api/v2
|
||||
VITE_SECURE_PATH= # 开发时留空,由 proxy 转发
|
||||
|
||||
# .env.production
|
||||
VITE_API_BASE_URL=/api/v2
|
||||
# production 下 secure_path 从 window.settings 获取
|
||||
```
|
||||
|
||||
### Step 2: 基础设施层
|
||||
|
||||
**预期产物:** API client、Token 工具、运行时配置、类型定义
|
||||
|
||||
- **`src/types/api.d.ts`** - API 响应泛型、登录接口类型
|
||||
- **`src/utils/token.ts`** - Token 存取(sessionStorage 为默认,可选 localStorage 记住登录)
|
||||
- **`src/utils/runtime.ts`** - 解析 `window.settings` 和环境变量,提供 `getSecurePath()`、`getApiBaseUrl()`
|
||||
- `secure_path` 优先级:`window.settings.secure_path` > `VITE_ADMIN_PATH` 环境变量 > 启动报错
|
||||
- **`src/api/client.ts`** - 两个 Axios 实例:
|
||||
- `passportClient`:固定前缀 `/api/v2/passport`
|
||||
- `adminClient`:运行时拼接 `/api/v2/{secure_path}`
|
||||
- 统一响应拦截:错误归一化、401/403 自动清除 token 跳登录
|
||||
- **`src/api/passport.ts`** - `login(email, password)` 函数
|
||||
- **`src/api/admin.ts`** - `getSystemStatus()` 探针函数
|
||||
|
||||
### Step 3: 状态管理
|
||||
|
||||
**预期产物:** Pinia stores
|
||||
|
||||
- **`src/stores/auth.ts`**:
|
||||
- state: `authHeader`, `isAdmin`, `isLoading`
|
||||
- actions: `login()`, `logout()`, `validateAdmin()`, `initFromStorage()`
|
||||
- 登录流程:调用 API → 校验 `is_admin` → 保存 `authHeader` → admin 探针验证
|
||||
- 非 admin 用户登录后直接拒绝并提示"无管理员权限"
|
||||
- **`src/stores/app.ts`**:
|
||||
- state: `securePath`, `apiBaseUrl`, `sidebarCollapsed`
|
||||
- actions: `initConfig()` 从 runtime 解析配置
|
||||
|
||||
### Step 4: 路由与守卫
|
||||
|
||||
**预期产物:** 路由配置 + 权限守卫
|
||||
|
||||
- **`src/router/index.ts`**:
|
||||
- 使用 `createWebHashHistory()`(因为 Laravel 无 catch-all 路由,hash 模式避免刷新 404)
|
||||
- 路由表:
|
||||
```
|
||||
/login → LoginView (公开)
|
||||
/ → AdminLayout (需认证)
|
||||
/dashboard → DashboardView (需认证)
|
||||
```
|
||||
- **`src/router/guards.ts`**:
|
||||
- `beforeEach`:无 token → `/login`;有 token 但未验证 → 执行 admin 探针 → 失败清 token 回 `/login`
|
||||
- 已登录用户访问 `/login` → 重定向 `/dashboard`
|
||||
|
||||
### Step 5: 登录页面
|
||||
|
||||
**预期产物:** 功能完整的登录页
|
||||
|
||||
- **`src/views/login/LoginView.vue`**:
|
||||
- 简约卡片布局,深色渐变背景,居中展示
|
||||
- Element Plus 组件:`ElForm`, `ElFormItem`, `ElInput`, `ElButton`, `ElMessage`
|
||||
- 表单字段:
|
||||
- 邮箱(email 类型,必填,格式校验)
|
||||
- 密码(password 类型,必填,最少 8 位)
|
||||
- 记住登录(可选 checkbox,控制 token 存 localStorage vs sessionStorage)
|
||||
- 提交时 loading 状态,按钮禁用 + 防抖(防止重复提交)
|
||||
- 错误处理:
|
||||
- 400:邮箱或密码错误 → 表单级错误提示
|
||||
- 429:密码错误次数过多 → 显示倒计时提示(从响应 message 解析剩余分钟数)
|
||||
- 403/无权限:`is_admin=false` → 提示"该账号无管理员权限"
|
||||
- 网络错误:通用错误提示
|
||||
- 登录成功后跳转 `/dashboard`
|
||||
- 支持暗色/亮色主题切换(Element Plus 原生 dark mode)
|
||||
|
||||
### Step 6: 管理端布局与 Dashboard
|
||||
|
||||
**预期产物:** 基础布局框架 + Dashboard 占位页
|
||||
|
||||
- **`src/layouts/AdminLayout.vue`**:
|
||||
- Element Plus `ElContainer` + `ElAside` + `ElHeader` + `ElMain`
|
||||
- 左侧边栏(可折叠):Logo + 菜单项(首期仅 Dashboard)
|
||||
- 顶栏:面包屑 + 右侧用户操作区(登出按钮)
|
||||
- 响应式:小屏幕自动折叠侧边栏
|
||||
- **`src/views/dashboard/DashboardView.vue`**:
|
||||
- 占位页面,显示欢迎信息和系统基本信息
|
||||
- 后续迭代补充统计数据
|
||||
|
||||
### Step 7: 样式与全局配置
|
||||
|
||||
**预期产物:** 统一视觉风格
|
||||
|
||||
- **`src/styles/index.scss`**:
|
||||
- CSS 变量定义主题色
|
||||
- Element Plus 主题覆盖(主色调、边框、背景)
|
||||
- 登录页专用样式
|
||||
- 全局样式重置
|
||||
|
||||
### Step 8: 入口文件整合
|
||||
|
||||
**预期产物:** 完整可运行的应用
|
||||
|
||||
- **`src/main.ts`**:
|
||||
- 注册 Element Plus(通过 AutoImport 按需引入)
|
||||
- 注册 Pinia
|
||||
- 注册 Router
|
||||
- 初始化运行时配置(`appStore.initConfig()`)
|
||||
- 初始化认证状态(`authStore.initFromStorage()`)
|
||||
- 引入 Element Plus 暗色主题 CSS(`element-plus/theme-chalk/dark/css-vars.css`)
|
||||
- **`src/App.vue`**:`<RouterView />`
|
||||
|
||||
## 关键文件清单
|
||||
|
||||
| 文件 | 操作 | 说明 |
|
||||
|------|------|------|
|
||||
| `admin-frontend/package.json` | 新建 | 项目依赖与脚本 |
|
||||
| `admin-frontend/vite.config.ts` | 新建 | Vite 构建 + 代理配置 |
|
||||
| `admin-frontend/src/main.ts` | 新建 | 应用入口 |
|
||||
| `admin-frontend/src/api/client.ts` | 新建 | Axios 实例 + 拦截器 |
|
||||
| `admin-frontend/src/api/passport.ts` | 新建 | 登录 API |
|
||||
| `admin-frontend/src/api/admin.ts` | 新建 | Admin API 封装 |
|
||||
| `admin-frontend/src/utils/token.ts` | 新建 | Token 存储工具 |
|
||||
| `admin-frontend/src/utils/runtime.ts` | 新建 | 运行时配置解析 |
|
||||
| `admin-frontend/src/stores/auth.ts` | 新建 | 认证状态管理 |
|
||||
| `admin-frontend/src/stores/app.ts` | 新建 | 应用配置管理 |
|
||||
| `admin-frontend/src/router/index.ts` | 新建 | 路由定义 |
|
||||
| `admin-frontend/src/router/guards.ts` | 新建 | 路由守卫 |
|
||||
| `admin-frontend/src/views/login/LoginView.vue` | 新建 | 登录页 |
|
||||
| `admin-frontend/src/layouts/AdminLayout.vue` | 新建 | 管理端布局 |
|
||||
| `admin-frontend/src/views/dashboard/DashboardView.vue` | 新建 | 仪表盘占位 |
|
||||
|
||||
## 风险与缓解
|
||||
|
||||
| 风险 | 缓解措施 |
|
||||
|------|----------|
|
||||
| `secure_path` 在独立部署时无法从前端推导 | 首期用 Laravel 托管 dist,从 `window.settings` 获取;中长期可加 bootstrap API |
|
||||
| 登录接口是用户通用接口,非管理员也能登录 | 登录后立即校验 `is_admin`,非 admin 拒绝进入管理端 |
|
||||
| `token` 字段含义混淆(实际是邀请码) | 封装层仅暴露 `auth_data` 作为认证凭证,`token` 字段忽略 |
|
||||
| CORS `supports_credentials=false` | 前端走 Bearer token 无状态认证,不依赖 cookie |
|
||||
| Hash 路由不够优雅 | 首期务实选择,后续独立域名部署时可切 history 模式 |
|
||||
| 无专用 admin logout API | 前端清除本地 token 即可(Sanctum token 有 1 年有效期,不影响安全性) |
|
||||
|
||||
## SESSION_ID
|
||||
|
||||
- CODEX_SESSION: 019dac16-b724-73a2-a3ff-f6b2ac49e2bf
|
||||
- GEMINI_SESSION: (不可用,调用失败)
|
||||
@@ -0,0 +1,7 @@
|
||||
{
|
||||
"permissions": {
|
||||
"allow": [
|
||||
"mcp__contextweaver__codebase-retrieval"
|
||||
]
|
||||
}
|
||||
}
|
||||
Executable → Regular
@@ -0,0 +1,35 @@
|
||||
# Xboard protocol fusion entrypoint.
|
||||
#
|
||||
# Caddy listens on a single public port and dispatches HTTP traffic to Octane
|
||||
# while transparently upgrading WebSocket requests to the ws-server worker.
|
||||
# This lets every external reverse proxy (nginx, Cloudflare, the user's own
|
||||
# Caddy, ...) treat the panel as a single upstream and avoids exposing the
|
||||
# 8076 WebSocket port directly.
|
||||
{
|
||||
admin off
|
||||
auto_https off
|
||||
persist_config off
|
||||
log {
|
||||
output stdout
|
||||
format console
|
||||
}
|
||||
servers {
|
||||
trusted_proxies static 0.0.0.0/0 ::/0
|
||||
}
|
||||
}
|
||||
|
||||
:{$CADDY_LISTEN_PORT:7001} {
|
||||
@ws path /ws
|
||||
reverse_proxy @ws 127.0.0.1:{$WS_PORT:8076}
|
||||
|
||||
reverse_proxy 127.0.0.1:{$OCTANE_INTERNAL_PORT:7002} {
|
||||
header_up Host {host}
|
||||
# X-Forwarded-For is auto-appended with our remote_addr by Caddy
|
||||
# (enabled by the global trusted_proxies above), so Octane receives the
|
||||
# full proxy chain and Laravel's TrustProxies middleware resolves the
|
||||
# real client IP using its own trust list. We additionally surface the
|
||||
# directly-connected peer as X-Real-IP for downstream consumers (logs,
|
||||
# admin tools) that read it directly without TrustProxies.
|
||||
header_up X-Real-IP {remote_host}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,25 @@
|
||||
# Caddy config used by compose.split.yaml — the embedded image's Caddy is
|
||||
# disabled in this mode and a dedicated Caddy container fronts independent
|
||||
# web and ws-server containers reachable via the compose network.
|
||||
{
|
||||
admin off
|
||||
auto_https off
|
||||
persist_config off
|
||||
log {
|
||||
output stdout
|
||||
format console
|
||||
}
|
||||
servers {
|
||||
trusted_proxies static 0.0.0.0/0 ::/0
|
||||
}
|
||||
}
|
||||
|
||||
:7001 {
|
||||
@ws path /ws
|
||||
reverse_proxy @ws ws-server:8076
|
||||
|
||||
reverse_proxy web:7001 {
|
||||
header_up Host {host}
|
||||
header_up X-Real-IP {remote_host}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,153 @@
|
||||
#!/bin/sh
|
||||
set -e
|
||||
|
||||
# Resolve the binding scheme based on whether the embedded Caddy is enabled.
|
||||
#
|
||||
# When ENABLE_CADDY=true (default), Caddy owns the public port (7001) and
|
||||
# dispatches traffic internally; Octane and ws-server bind to localhost only
|
||||
# so they cannot be reached from outside the container.
|
||||
#
|
||||
# When ENABLE_CADDY=false (e.g. an external reverse proxy or split mode),
|
||||
# Octane takes the public port directly to keep behaviour identical to the
|
||||
# pre-Caddy releases.
|
||||
if [ "${ENABLE_CADDY}" = "true" ]; then
|
||||
: "${OCTANE_HOST:=127.0.0.1}"
|
||||
: "${OCTANE_PORT:=7002}"
|
||||
: "${WS_HOST:=127.0.0.1}"
|
||||
: "${WS_PORT:=8076}"
|
||||
: "${CADDY_LISTEN_PORT:=7001}"
|
||||
else
|
||||
: "${OCTANE_HOST:=0.0.0.0}"
|
||||
: "${OCTANE_PORT:=7001}"
|
||||
: "${WS_HOST:=0.0.0.0}"
|
||||
: "${WS_PORT:=8076}"
|
||||
fi
|
||||
export OCTANE_HOST OCTANE_PORT WS_HOST WS_PORT CADDY_LISTEN_PORT
|
||||
export OCTANE_INTERNAL_PORT="${OCTANE_PORT}"
|
||||
|
||||
# ---------------------------------------------------------------------------
|
||||
# Auto-tune worker counts based on the host (CPU + memory).
|
||||
#
|
||||
# Heuristic: each PHP worker (Octane/Horizon) costs ~80 MiB. After reserving
|
||||
# ~300 MiB for the always-on processes (caddy/redis/ws-server/masters), divide
|
||||
# the remaining budget across roles. Any user-set ENV wins.
|
||||
# ---------------------------------------------------------------------------
|
||||
detect_cpus() {
|
||||
if [ -r /sys/fs/cgroup/cpu.max ]; then
|
||||
# cgroup v2: "<quota> <period>" or "max <period>"
|
||||
read -r q p < /sys/fs/cgroup/cpu.max 2>/dev/null
|
||||
if [ "$q" != "max" ] && [ -n "$q" ] && [ -n "$p" ] && [ "$p" -gt 0 ]; then
|
||||
echo $(( (q + p - 1) / p ))
|
||||
return
|
||||
fi
|
||||
fi
|
||||
nproc 2>/dev/null || echo 1
|
||||
}
|
||||
|
||||
detect_mem_mib() {
|
||||
if [ -r /sys/fs/cgroup/memory.max ]; then
|
||||
m=$(cat /sys/fs/cgroup/memory.max 2>/dev/null)
|
||||
if [ "$m" != "max" ] && [ -n "$m" ]; then
|
||||
echo $(( m / 1024 / 1024 ))
|
||||
return
|
||||
fi
|
||||
fi
|
||||
# No cgroup limit: avoid over-provisioning on big hosts. Cap the assumed
|
||||
# budget to MEM_FALLBACK_MIB (default 1024) unless the user opts out by
|
||||
# setting it explicitly. Use whichever is smaller of MemAvailable and cap.
|
||||
avail=$(awk '/MemAvailable/ {print int($2/1024)}' /proc/meminfo 2>/dev/null || echo 1024)
|
||||
cap=${MEM_FALLBACK_MIB:-1024}
|
||||
[ "$avail" -lt "$cap" ] && echo "$avail" || echo "$cap"
|
||||
}
|
||||
|
||||
CPUS=$(detect_cpus)
|
||||
MEM_MIB=$(detect_mem_mib)
|
||||
|
||||
# Resource profile presets. RESOURCE_PROFILE selects ratios for the budget split:
|
||||
# minimal - smallest possible footprint (~250-350 MiB), single octane worker,
|
||||
# horizon capped to 1/1/1. Suitable for VPS with <=512 MiB RAM.
|
||||
# balanced - default; ~80 MiB per worker, octane gets 25% of slots.
|
||||
# performance - larger reserves for opcache/caches, more aggressive horizon caps.
|
||||
# auto - same as balanced.
|
||||
: "${RESOURCE_PROFILE:=auto}"
|
||||
case "$RESOURCE_PROFILE" in
|
||||
minimal) RESERVED_MIB=200; SLOT_MIB=100; OCT_NUM=1; OCT_DEN=1; OCT_FORCE=1; auto_horizon_mem=128; auto_octane_gc=64 ;;
|
||||
performance) RESERVED_MIB=400; SLOT_MIB=70; OCT_NUM=1; OCT_DEN=3; OCT_FORCE=0; auto_horizon_mem=384; auto_octane_gc=256 ;;
|
||||
balanced|auto|*) RESERVED_MIB=300; SLOT_MIB=80; OCT_NUM=1; OCT_DEN=4; OCT_FORCE=0; auto_horizon_mem=256; auto_octane_gc=128 ;;
|
||||
esac
|
||||
|
||||
BUDGET=$(( MEM_MIB - RESERVED_MIB ))
|
||||
[ "$BUDGET" -lt "$SLOT_MIB" ] && BUDGET=$SLOT_MIB
|
||||
SLOTS=$(( BUDGET / SLOT_MIB ))
|
||||
|
||||
clamp() { v=$1; lo=$2; hi=$3; [ "$v" -lt "$lo" ] && v=$lo; [ "$v" -gt "$hi" ] && v=$hi; echo "$v"; }
|
||||
|
||||
if [ "$OCT_FORCE" = "1" ]; then
|
||||
auto_octane=1
|
||||
auto_dp=1; auto_biz=1; auto_notif=1
|
||||
else
|
||||
auto_octane=$(clamp $(( (SLOTS * OCT_NUM) / OCT_DEN )) 1 "$CPUS")
|
||||
remaining=$(( SLOTS - auto_octane - 2 ))
|
||||
[ "$remaining" -lt 3 ] && remaining=3
|
||||
auto_dp=$(clamp $(( remaining / 2 )) 1 $(( CPUS * 2 )))
|
||||
auto_biz=$(clamp $(( remaining / 4 )) 1 "$CPUS")
|
||||
auto_notif=$(clamp $(( remaining / 4 )) 1 "$CPUS")
|
||||
fi
|
||||
|
||||
# User-set ENV always wins.
|
||||
: "${OCTANE_WORKERS:=$auto_octane}"
|
||||
: "${OCTANE_TASK_WORKERS:=1}"
|
||||
: "${OCTANE_MAX_REQUESTS:=500}"
|
||||
: "${OCTANE_GARBAGE_MB:=$auto_octane_gc}"
|
||||
: "${OCTANE_MAX_EXECUTION_TIME:=60}"
|
||||
: "${HORIZON_DATA_PIPELINE_MAX:=$auto_dp}"
|
||||
: "${HORIZON_BUSINESS_MAX:=$auto_biz}"
|
||||
: "${HORIZON_NOTIFICATION_MAX:=$auto_notif}"
|
||||
: "${HORIZON_WORKER_MEMORY_MB:=$auto_horizon_mem}"
|
||||
: "${HORIZON_WORKER_MAX_TIME:=0}"
|
||||
: "${HORIZON_WORKER_MAX_JOBS:=0}"
|
||||
: "${ENABLE_WEB:=true}"
|
||||
: "${ENABLE_SCHEDULE:=$ENABLE_WEB}"
|
||||
|
||||
export OCTANE_WORKERS OCTANE_TASK_WORKERS OCTANE_MAX_REQUESTS \
|
||||
OCTANE_GARBAGE_MB OCTANE_MAX_EXECUTION_TIME \
|
||||
HORIZON_DATA_PIPELINE_MAX HORIZON_BUSINESS_MAX HORIZON_NOTIFICATION_MAX \
|
||||
HORIZON_WORKER_MEMORY_MB HORIZON_WORKER_MAX_TIME HORIZON_WORKER_MAX_JOBS \
|
||||
RESOURCE_PROFILE ENABLE_SCHEDULE
|
||||
|
||||
echo "[entrypoint] Auto-tune (profile=${RESOURCE_PROFILE}): cpus=${CPUS} mem=${MEM_MIB}MiB slots=${SLOTS} -> octane=${OCTANE_WORKERS} horizon(dp/biz/notif)=${HORIZON_DATA_PIPELINE_MAX}/${HORIZON_BUSINESS_MAX}/${HORIZON_NOTIFICATION_MAX} horizon_worker_mem=${HORIZON_WORKER_MEMORY_MB}MB"
|
||||
echo "[entrypoint] Horizon supervisors use balance=auto with minProcesses=1, so they scale up to the cap on demand and back down when idle."
|
||||
|
||||
redis_reachable() {
|
||||
local host port
|
||||
host=$(grep -E '^REDIS_HOST=' /www/.env 2>/dev/null | tail -1 | cut -d= -f2- | tr -d '"' | tr -d "'")
|
||||
port=$(grep -E '^REDIS_PORT=' /www/.env 2>/dev/null | tail -1 | cut -d= -f2- | tr -d '"' | tr -d "'")
|
||||
command -v redis-cli >/dev/null 2>&1 || return 1
|
||||
[ -n "$host" ] || return 1
|
||||
case "$host" in
|
||||
/*) [ -S "$host" ] && redis-cli -s "$host" ping 2>/dev/null | grep -q PONG ;;
|
||||
*) redis-cli -h "$host" -p "${port:-6379}" ping 2>/dev/null | grep -q PONG ;;
|
||||
esac
|
||||
}
|
||||
|
||||
if [ ! -s /www/.env ] || ! grep -qE '^INSTALLED=(1|true)$' /www/.env || echo " $* " | grep -q ' xboard:install '; then
|
||||
echo "[entrypoint] Skipping xboard:update (not yet installed or running xboard:install)."
|
||||
else
|
||||
if redis_reachable; then
|
||||
echo "[entrypoint] Running xboard:update (redis reachable, real drivers)..."
|
||||
php /www/artisan xboard:update --no-interaction || \
|
||||
echo "[entrypoint] WARNING: xboard:update failed; continuing so supervisor can boot anyway." >&2
|
||||
else
|
||||
echo "[entrypoint] Running xboard:update (redis not yet up, using array/sync drivers)..."
|
||||
CACHE_DRIVER=array QUEUE_CONNECTION=sync SESSION_DRIVER=array \
|
||||
php /www/artisan xboard:update --no-interaction || \
|
||||
echo "[entrypoint] WARNING: xboard:update failed; continuing so supervisor can boot anyway." >&2
|
||||
fi
|
||||
fi
|
||||
|
||||
echo "[entrypoint] Starting services (caddy=${ENABLE_CADDY} web=${ENABLE_WEB} horizon=${ENABLE_HORIZON} scheduler=${ENABLE_SCHEDULE} ws=${ENABLE_WS_SERVER})..."
|
||||
# Drop stale Octane/WorkerMan state files so the new master does not signal
|
||||
# PIDs left over from a previous container run (causes Swoole kill EPERM).
|
||||
rm -f /www/storage/logs/octane-server-state.json /www/storage/logs/xboard-ws-server.pid 2>/dev/null || true
|
||||
chown -R www:www /www 2>/dev/null || true
|
||||
exec "$@"
|
||||
@@ -0,0 +1,17 @@
|
||||
; Slim PHP defaults for the all-in-one container.
|
||||
; Tunables are overridable via Docker ENV (PHP_MEMORY_LIMIT, etc.) if needed.
|
||||
|
||||
memory_limit = 256M
|
||||
|
||||
[opcache]
|
||||
opcache.enable = 1
|
||||
opcache.enable_cli = 0
|
||||
opcache.memory_consumption = 96
|
||||
opcache.interned_strings_buffer = 16
|
||||
opcache.max_accelerated_files = 10000
|
||||
opcache.validate_timestamps = 0
|
||||
opcache.revalidate_freq = 0
|
||||
opcache.fast_shutdown = 1
|
||||
|
||||
[swoole]
|
||||
swoole.use_shortname = Off
|
||||
@@ -0,0 +1,116 @@
|
||||
[supervisord]
|
||||
nodaemon=true
|
||||
user=root
|
||||
logfile=/dev/stdout
|
||||
logfile_maxbytes=0
|
||||
pidfil=/www/storage/logs/supervisor/supervisord.pid
|
||||
loglevel=info
|
||||
|
||||
[program:octane]
|
||||
process_name=%(program_name)s_%(process_num)02d
|
||||
command=php /www/artisan octane:start --host=%(ENV_OCTANE_HOST)s --port=%(ENV_OCTANE_PORT)s --workers=%(ENV_OCTANE_WORKERS)s --task-workers=%(ENV_OCTANE_TASK_WORKERS)s --max-requests=%(ENV_OCTANE_MAX_REQUESTS)s
|
||||
autostart=%(ENV_ENABLE_WEB)s
|
||||
autorestart=true
|
||||
user=www
|
||||
redirect_stderr=true
|
||||
stdout_logfile=/dev/stdout
|
||||
stdout_logfile_maxbytes=0
|
||||
stdout_logfile_backups=0
|
||||
numprocs=1
|
||||
stopwaitsecs=10
|
||||
stopsignal=QUIT
|
||||
stopasgroup=true
|
||||
killasgroup=true
|
||||
priority=100
|
||||
|
||||
[program:horizon]
|
||||
process_name=%(program_name)s_%(process_num)02d
|
||||
command=php /www/artisan horizon
|
||||
autostart=%(ENV_ENABLE_HORIZON)s
|
||||
autorestart=true
|
||||
user=www
|
||||
redirect_stderr=true
|
||||
stdout_logfile=/dev/stdout
|
||||
stdout_logfile_maxbytes=0
|
||||
stdout_logfile_backups=0
|
||||
numprocs=1
|
||||
stopwaitsecs=3
|
||||
stopsignal=SIGINT
|
||||
stopasgroup=true
|
||||
killasgroup=true
|
||||
priority=200
|
||||
|
||||
[program:scheduler]
|
||||
process_name=%(program_name)s_%(process_num)02d
|
||||
command=php /www/artisan schedule:work
|
||||
autostart=%(ENV_ENABLE_SCHEDULE)s
|
||||
autorestart=true
|
||||
user=www
|
||||
redirect_stderr=true
|
||||
stdout_logfile=/dev/stdout
|
||||
stdout_logfile_maxbytes=0
|
||||
stdout_logfile_backups=0
|
||||
numprocs=1
|
||||
stopwaitsecs=5
|
||||
stopsignal=TERM
|
||||
stopasgroup=true
|
||||
killasgroup=true
|
||||
priority=250
|
||||
|
||||
[program:redis]
|
||||
process_name=%(program_name)s_%(process_num)02d
|
||||
command=redis-server --dir /data
|
||||
--dbfilename dump.rdb
|
||||
--save 900 1
|
||||
--save 300 10
|
||||
--save 60 10000
|
||||
--port 0
|
||||
--unixsocket /data/redis.sock
|
||||
--unixsocketperm 777
|
||||
autostart=%(ENV_ENABLE_REDIS)s
|
||||
autorestart=true
|
||||
user=redis
|
||||
redirect_stderr=true
|
||||
stdout_logfile=/dev/stdout
|
||||
stdout_logfile_maxbytes=0
|
||||
stdout_logfile_backups=0
|
||||
numprocs=1
|
||||
stopwaitsecs=3
|
||||
stopsignal=TERM
|
||||
stopasgroup=true
|
||||
killasgroup=true
|
||||
priority=300
|
||||
|
||||
[program:ws-server]
|
||||
process_name=%(program_name)s_%(process_num)02d
|
||||
command=php /www/artisan ws-server start --host=%(ENV_WS_HOST)s --port=%(ENV_WS_PORT)s
|
||||
autostart=%(ENV_ENABLE_WS_SERVER)s
|
||||
autorestart=true
|
||||
user=www
|
||||
redirect_stderr=true
|
||||
stdout_logfile=/dev/stdout
|
||||
stdout_logfile_maxbytes=0
|
||||
stdout_logfile_backups=0
|
||||
numprocs=1
|
||||
stopwaitsecs=5
|
||||
stopsignal=SIGINT
|
||||
stopasgroup=true
|
||||
killasgroup=true
|
||||
priority=400
|
||||
|
||||
[program:caddy]
|
||||
process_name=%(program_name)s_%(process_num)02d
|
||||
command=caddy run --config /etc/caddy/Caddyfile --adapter caddyfile
|
||||
autostart=%(ENV_ENABLE_CADDY)s
|
||||
autorestart=true
|
||||
user=root
|
||||
redirect_stderr=true
|
||||
stdout_logfile=/dev/stdout
|
||||
stdout_logfile_maxbytes=0
|
||||
stdout_logfile_backups=0
|
||||
numprocs=1
|
||||
stopwaitsecs=5
|
||||
stopsignal=TERM
|
||||
stopasgroup=true
|
||||
killasgroup=true
|
||||
priority=500
|
||||
@@ -0,0 +1,28 @@
|
||||
/node_modules
|
||||
/config/v2board.php
|
||||
/public/hot
|
||||
/public/storage
|
||||
/public/env.example.js
|
||||
/storage/*.key
|
||||
/vendor
|
||||
.env
|
||||
.git
|
||||
.github
|
||||
.helloagents
|
||||
.env.backup
|
||||
.phpunit.result.cache
|
||||
.idea
|
||||
.lock
|
||||
Homestead.json
|
||||
Homestead.yaml
|
||||
npm-debug.log
|
||||
yarn-error.log
|
||||
composer.phar
|
||||
yarn.lock
|
||||
docker-compose.yml
|
||||
.DS_Store
|
||||
/docker
|
||||
storage/laravels.conf
|
||||
storage/laravels.pid
|
||||
storage/laravels-timer-process.pid
|
||||
/frontend
|
||||
Executable
+15
@@ -0,0 +1,15 @@
|
||||
root = true
|
||||
|
||||
[*]
|
||||
charset = utf-8
|
||||
end_of_line = lf
|
||||
insert_final_newline = true
|
||||
indent_style = space
|
||||
indent_size = 4
|
||||
trim_trailing_whitespace = true
|
||||
|
||||
[*.md]
|
||||
trim_trailing_whitespace = false
|
||||
|
||||
[*.{yml,yaml}]
|
||||
indent_size = 2
|
||||
Regular → Executable
+7
-7
@@ -1,11 +1,9 @@
|
||||
APP_NAME=XBoard
|
||||
APP_ENV=local
|
||||
APP_ENV=production
|
||||
APP_KEY=base64:PZXk5vTuTinfeEVG5FpYv2l6WEhLsyvGpiWK7IgJJ60=
|
||||
APP_DEBUG=false
|
||||
APP_URL=http://localhost
|
||||
|
||||
APP_RUNNING_IN_CONSOLE=true
|
||||
|
||||
LOG_CHANNEL=stack
|
||||
|
||||
DB_CONNECTION=mysql
|
||||
@@ -19,14 +17,16 @@ REDIS_HOST=127.0.0.1
|
||||
REDIS_PASSWORD=null
|
||||
REDIS_PORT=6379
|
||||
|
||||
#默认将队列驱动和缓存驱动都修改为了redis,请务必安装redis
|
||||
BROADCAST_DRIVER=log
|
||||
CACHE_DRIVER=redis
|
||||
QUEUE_CONNECTION=redis
|
||||
QUEUE_RETRY_AFTER=90
|
||||
MASS_EMAIL_HOURLY_LIMIT=500
|
||||
|
||||
MAIL_DRIVER=smtp
|
||||
MAIL_HOST=smtp.mailtrap.io
|
||||
MAIL_PORT=2525
|
||||
MAIL_TIMEOUT=30
|
||||
MAIL_USERNAME=null
|
||||
MAIL_PASSWORD=null
|
||||
MAIL_ENCRYPTION=null
|
||||
@@ -35,10 +35,10 @@ MAIL_FROM_NAME=null
|
||||
MAILGUN_DOMAIN=
|
||||
MAILGUN_SECRET=
|
||||
|
||||
# google cloud stoage
|
||||
# google cloud storage
|
||||
ENABLE_AUTO_BACKUP_AND_UPDATE=false
|
||||
GOOGLE_CLOUD_KEY_FILE=config/googleCloudStorageKey.json
|
||||
GOOGLE_CLOUD_STORAGE_BUCKET=
|
||||
|
||||
# 用于阻止重复安装
|
||||
INSTALLED=false
|
||||
# Prevent reinstallation
|
||||
INSTALLED=false
|
||||
|
||||
Executable
+5
@@ -0,0 +1,5 @@
|
||||
* text=auto
|
||||
*.css linguist-vendored
|
||||
*.scss linguist-vendored
|
||||
*.js linguist-vendored
|
||||
CHANGELOG.md export-ignore
|
||||
@@ -0,0 +1,39 @@
|
||||
---
|
||||
name: 🐛 问题反馈 | Bug Report
|
||||
about: 提交使用过程中遇到的问题 | Report an issue
|
||||
title: "Bug Report:"
|
||||
labels: '🐛 bug'
|
||||
assignees: ''
|
||||
---
|
||||
|
||||
<!-- 🔴 请注意:XrayR等非XBoard问题请前往相应项目提问 -->
|
||||
<!-- 🔴 Note: For XrayR and other non-XBoard issues, please report to their respective projects -->
|
||||
|
||||
> ⚠️ 请务必按照模板填写完整信息,没有详细描述的issue可能会被忽略或关闭
|
||||
> ⚠️ Please follow the template to provide complete information, issues without detailed description may be ignored or closed
|
||||
|
||||
**基本信息 | Basic Info**
|
||||
```yaml
|
||||
XBoard版本 | Version:
|
||||
部署方式 | Deployment: [Docker/手动部署]
|
||||
PHP版本 | Version:
|
||||
数据库 | Database:
|
||||
```
|
||||
|
||||
**问题描述 | Description**
|
||||
<!-- 简要描述你遇到的问题 -->
|
||||
|
||||
|
||||
**复现步骤 | Steps**
|
||||
<!-- 如何复现这个问题? -->
|
||||
1.
|
||||
2.
|
||||
|
||||
**相关截图 | Screenshots**
|
||||
<!-- 拖拽图片到这里(请注意隐藏敏感信息)-->
|
||||
|
||||
**日志信息 | Logs**
|
||||
<!-- storage/logs 目录下的日志 -->
|
||||
```log
|
||||
// 粘贴日志内容到这里
|
||||
```
|
||||
@@ -0,0 +1,28 @@
|
||||
---
|
||||
name: ✨ 功能请求 | Feature Request
|
||||
about: 提交新功能建议或改进意见 | Suggest an idea
|
||||
title: "Feature Request:"
|
||||
labels: '✨ enhancement'
|
||||
assignees: ''
|
||||
---
|
||||
|
||||
> ⚠️ 请务必按照模板详细描述你的需求,没有详细描述的issue可能会被忽略或关闭
|
||||
> ⚠️ Please follow the template to describe your request in detail, issues without detailed description may be ignored or closed
|
||||
|
||||
**需求描述 | Description**
|
||||
<!-- 描述你希望添加的功能或改进建议 -->
|
||||
|
||||
|
||||
**使用场景 | Use Case**
|
||||
<!-- 描述这个功能会在什么场景下使用,解决什么问题 -->
|
||||
|
||||
|
||||
**功能建议 | Suggestion**
|
||||
<!-- 你期望这个功能是什么样的?可以描述一下具体实现方式 -->
|
||||
```yaml
|
||||
功能形式 | Type: [新功能/功能优化/界面改进]
|
||||
预期效果 | Expected:
|
||||
```
|
||||
|
||||
**补充说明 | Additional**
|
||||
<!-- 其他补充说明或者参考示例 -->
|
||||
@@ -0,0 +1,82 @@
|
||||
name: Admin Frontend Docker Build and Publish
|
||||
|
||||
on:
|
||||
push:
|
||||
branches: ["master", "new-dev"]
|
||||
paths:
|
||||
- "admin-frontend/**"
|
||||
- ".github/workflows/admin-frontend-docker-publish.yml"
|
||||
workflow_dispatch:
|
||||
|
||||
concurrency:
|
||||
group: admin-frontend-docker-publish-${{ github.ref }}
|
||||
cancel-in-progress: true
|
||||
|
||||
env:
|
||||
REGISTRY: ghcr.io
|
||||
IMAGE_NAME: ${{ github.repository_owner }}/xboard-admin-frontend
|
||||
|
||||
jobs:
|
||||
build:
|
||||
runs-on: ubuntu-latest
|
||||
permissions:
|
||||
contents: read
|
||||
packages: write
|
||||
id-token: write
|
||||
|
||||
steps:
|
||||
- name: Checkout code
|
||||
uses: actions/checkout@v4
|
||||
with:
|
||||
fetch-depth: 1
|
||||
fetch-tags: true
|
||||
|
||||
- name: Set up Docker Buildx
|
||||
uses: docker/setup-buildx-action@v3
|
||||
with:
|
||||
platforms: linux/amd64
|
||||
driver-opts: |
|
||||
image=moby/buildkit:v0.20.0
|
||||
network=host
|
||||
|
||||
- name: Login to registry
|
||||
uses: docker/login-action@v3
|
||||
with:
|
||||
registry: ${{ env.REGISTRY }}
|
||||
username: ${{ github.actor }}
|
||||
password: ${{ secrets.GITHUB_TOKEN }}
|
||||
|
||||
- name: Get version
|
||||
id: get_version
|
||||
run: echo "version=$(git describe --tags --always)" >> "$GITHUB_OUTPUT"
|
||||
|
||||
- name: Extract metadata
|
||||
id: meta
|
||||
uses: docker/metadata-action@v5
|
||||
with:
|
||||
images: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}
|
||||
tags: |
|
||||
type=ref,event=branch
|
||||
type=sha,format=short,prefix=,enable=true
|
||||
type=raw,value=new,enable=${{ github.ref == 'refs/heads/master' }}
|
||||
type=raw,value=latest,enable=${{ github.ref == 'refs/heads/master' }}
|
||||
type=raw,value=${{ steps.get_version.outputs.version }}
|
||||
labels: |
|
||||
org.opencontainers.image.source=${{ github.server_url }}/${{ github.repository }}
|
||||
org.opencontainers.image.revision=${{ github.sha }}
|
||||
|
||||
- name: Build and push
|
||||
id: build-and-push
|
||||
uses: docker/build-push-action@v5
|
||||
with:
|
||||
context: ./admin-frontend
|
||||
file: ./admin-frontend/Dockerfile
|
||||
push: true
|
||||
platforms: linux/amd64
|
||||
cache-from: type=gha,scope=admin-frontend-docker-publish-${{ github.ref_name }}
|
||||
cache-to: type=gha,mode=min,scope=admin-frontend-docker-publish-${{ github.ref_name }},ignore-error=true
|
||||
tags: ${{ steps.meta.outputs.tags }}
|
||||
labels: ${{ steps.meta.outputs.labels }}
|
||||
build-args: |
|
||||
BUILDKIT_INLINE_CACHE=1
|
||||
provenance: false
|
||||
@@ -0,0 +1,92 @@
|
||||
name: Backend Docker Build and Publish
|
||||
|
||||
on:
|
||||
push:
|
||||
branches: ["master", "new-dev"]
|
||||
paths-ignore:
|
||||
- "admin-frontend/**"
|
||||
- ".helloagents/**"
|
||||
- ".github/workflows/admin-frontend-docker-publish.yml"
|
||||
workflow_dispatch:
|
||||
|
||||
concurrency:
|
||||
group: backend-docker-publish-${{ github.ref }}
|
||||
cancel-in-progress: true
|
||||
|
||||
env:
|
||||
REGISTRY: ghcr.io
|
||||
IMAGE_NAME: ${{ github.repository }}
|
||||
|
||||
jobs:
|
||||
build:
|
||||
runs-on: ubuntu-latest
|
||||
permissions:
|
||||
contents: read
|
||||
packages: write
|
||||
id-token: write
|
||||
|
||||
steps:
|
||||
- name: Checkout code
|
||||
uses: actions/checkout@v4
|
||||
with:
|
||||
fetch-depth: 1
|
||||
fetch-tags: true
|
||||
submodules: recursive
|
||||
|
||||
- name: Set up QEMU
|
||||
uses: docker/setup-qemu-action@v3
|
||||
with:
|
||||
platforms: arm64
|
||||
|
||||
- name: Set up Docker Buildx
|
||||
uses: docker/setup-buildx-action@v3
|
||||
with:
|
||||
platforms: linux/amd64,linux/arm64
|
||||
driver-opts: |
|
||||
image=moby/buildkit:v0.20.0
|
||||
network=host
|
||||
|
||||
- name: Login to registry
|
||||
uses: docker/login-action@v3
|
||||
with:
|
||||
registry: ${{ env.REGISTRY }}
|
||||
username: ${{ github.actor }}
|
||||
password: ${{ secrets.GITHUB_TOKEN }}
|
||||
|
||||
- name: Get version
|
||||
id: get_version
|
||||
run: echo "version=$(git describe --tags --always)" >> $GITHUB_OUTPUT
|
||||
|
||||
- name: Extract metadata
|
||||
id: meta
|
||||
uses: docker/metadata-action@v5
|
||||
with:
|
||||
images: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}
|
||||
tags: |
|
||||
type=ref,event=branch
|
||||
type=sha,format=short,prefix=,enable=true
|
||||
type=raw,value=new,enable=${{ github.ref == 'refs/heads/master' }}
|
||||
type=raw,value=latest,enable=${{ github.ref == 'refs/heads/master' }}
|
||||
type=raw,value=${{ steps.get_version.outputs.version }}
|
||||
labels: |
|
||||
org.opencontainers.image.source=${{ github.server_url }}/${{ github.repository }}
|
||||
org.opencontainers.image.revision=${{ github.sha }}
|
||||
|
||||
- name: Build and push
|
||||
id: build-and-push
|
||||
uses: docker/build-push-action@v5
|
||||
with:
|
||||
context: .
|
||||
push: true
|
||||
platforms: linux/amd64,linux/arm64
|
||||
cache-from: type=gha,scope=backend-docker-publish-${{ github.ref_name }}
|
||||
cache-to: type=gha,mode=max,scope=backend-docker-publish-${{ github.ref_name }}
|
||||
tags: ${{ steps.meta.outputs.tags }}
|
||||
labels: ${{ steps.meta.outputs.labels }}
|
||||
build-args: |
|
||||
BUILDKIT_INLINE_CACHE=1
|
||||
BUILDKIT_MULTI_PLATFORM=1
|
||||
provenance: false
|
||||
allow: |
|
||||
network.host
|
||||
|
||||
Executable
+33
@@ -0,0 +1,33 @@
|
||||
/node_modules
|
||||
/config/v2board.php
|
||||
/config/googleCloudStorageKey.json
|
||||
/public/hot
|
||||
/public/storage
|
||||
/public/env.example.js
|
||||
*.user.ini
|
||||
/storage/*.key
|
||||
/vendor
|
||||
.env
|
||||
.env.backup
|
||||
.phpunit.result.cache
|
||||
.idea
|
||||
Homestead.json
|
||||
Homestead.yaml
|
||||
npm-debug.log
|
||||
yarn-error.log
|
||||
composer.phar
|
||||
yarn.lock
|
||||
docker-compose.yml
|
||||
.DS_Store
|
||||
/docker
|
||||
storage/laravels.conf
|
||||
storage/laravels.pid
|
||||
storage/update_pending
|
||||
storage/laravels-timer-process.pid
|
||||
cli-php.ini
|
||||
frontend
|
||||
docker-compose.yaml
|
||||
bun.lockb
|
||||
compose.yaml
|
||||
.scribe
|
||||
.ace-tool/
|
||||
@@ -0,0 +1,3 @@
|
||||
[submodule "public/assets/admin"]
|
||||
path = public/assets/admin
|
||||
url = https://github.com/Micah123321/xboard-admin-dist.git
|
||||
@@ -0,0 +1,4 @@
|
||||
{
|
||||
"consecutive_failures": 12,
|
||||
"last_failure": "2026-04-24T15:49:44.925Z"
|
||||
}
|
||||
@@ -0,0 +1,19 @@
|
||||
{
|
||||
"updatedAt": "2026-04-24T15:11:19.543Z",
|
||||
"source": "manual",
|
||||
"originCommand": "generic-r2",
|
||||
"requirementsCoverage": {
|
||||
"status": "PASS",
|
||||
"summary": "已覆盖分页、父子筛选、单节点置顶、仅已勾选节点批量修改,以及 host/group_ids/rate 三项批量更新边界。"
|
||||
},
|
||||
"deliveryChecklist": {
|
||||
"status": "PASS",
|
||||
"summary": "admin-frontend 构建通过,节点页与后端批量修改链路已落地,知识库、归档索引、会话状态与交付证据已同步。"
|
||||
},
|
||||
"fingerprint": {
|
||||
"available": true,
|
||||
"unstaged": ".helloagents/.ralph-breaker.json | 4 +-\n .helloagents/.ralph-closeout.json | 12 +-\n .helloagents/.ralph-visual.json | 32 +-\n .helloagents/CHANGELOG.md | 39 +-\n .helloagents/archive/_index.md | 4 +\n .helloagents/context.md | 12 +-\n .helloagents/modules/admin-frontend.md | 19 +-\n .../.status.json | 10 +-\n .../contract.json | 27 +-\n .../proposal.md | 19 +-\n .../tasks.md | 14 +-\n .../2026-04-24T07-44-44-846Z-unknown-e3upr9.jsonl | 5 +\n .../2026-04-24T08-15-56-367Z-claude-u7aa37.jsonl | 3 +\n .helloagents/sessions/master/default/STATE.md | 18 +-\n admin-frontend/src/api/admin.ts | 31 ++\n admin-frontend/src/types/api.d.ts | 28 ++\n admin-frontend/src/types/components.d.ts | 1 +\n admin-frontend/src/utils/nodes.ts | 12 +\n admin-frontend/src/utils/orders.ts | 50 ++-\n admin-frontend/src/utils/users.ts | 352 ++++++++++++++-\n .../src/views/dashboard/DashboardView.vue | 162 +++++--\n admin-frontend/src/views/nodes/NodesView.vue | 260 ++++++++++-\n .../src/views/subscriptions/OrderAssignDrawer.vue | 3 +-\n .../src/views/subscriptions/OrderDetailDrawer.vue | 20 +-\n .../src/views/subscriptions/OrdersView.scss | 16 +\n .../src/views/subscriptions/OrdersView.vue | 225 +++++++++-\n admin-frontend/src/views/users/UsersView.vue | 490 ++++++++-------------\n admin-frontend/vite.config.ts | 3 +-\n .../V2/Admin/Server/ManageController.php | 13 +\n app/Http/Controllers/V2/Admin/UserController.php | 5 +-\n public/assets/admin | 0\n 31 files changed, 1442 insertions(+), 447 deletions(-)",
|
||||
"staged": "",
|
||||
"combined": ".helloagents/.ralph-breaker.json | 4 +-\n .helloagents/.ralph-closeout.json | 12 +-\n .helloagents/.ralph-visual.json | 32 +-\n .helloagents/CHANGELOG.md | 39 +-\n .helloagents/archive/_index.md | 4 +\n .helloagents/context.md | 12 +-\n .helloagents/modules/admin-frontend.md | 19 +-\n .../.status.json | 10 +-\n .../contract.json | 27 +-\n .../proposal.md | 19 +-\n .../tasks.md | 14 +-\n .../2026-04-24T07-44-44-846Z-unknown-e3upr9.jsonl | 5 +\n .../2026-04-24T08-15-56-367Z-claude-u7aa37.jsonl | 3 +\n .helloagents/sessions/master/default/STATE.md | 18 +-\n admin-frontend/src/api/admin.ts | 31 ++\n admin-frontend/src/types/api.d.ts | 28 ++\n admin-frontend/src/types/components.d.ts | 1 +\n admin-frontend/src/utils/nodes.ts | 12 +\n admin-frontend/src/utils/orders.ts | 50 ++-\n admin-frontend/src/utils/users.ts | 352 ++++++++++++++-\n .../src/views/dashboard/DashboardView.vue | 162 +++++--\n admin-frontend/src/views/nodes/NodesView.vue | 260 ++++++++++-\n .../src/views/subscriptions/OrderAssignDrawer.vue | 3 +-\n .../src/views/subscriptions/OrderDetailDrawer.vue | 20 +-\n .../src/views/subscriptions/OrdersView.scss | 16 +\n .../src/views/subscriptions/OrdersView.vue | 225 +++++++++-\n admin-frontend/src/views/users/UsersView.vue | 490 ++++++++-------------\n admin-frontend/vite.config.ts | 3 +-\n .../V2/Admin/Server/ManageController.php | 13 +\n app/Http/Controllers/V2/Admin/UserController.php | 5 +-\n public/assets/admin | 0\n 31 files changed, 1442 insertions(+), 447 deletions(-)\n---"
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,22 @@
|
||||
{
|
||||
"updatedAt": "2026-04-24T08:19:23.678Z",
|
||||
"source": "manual",
|
||||
"originCommand": "~verify",
|
||||
"reviewMode": "manual-self-review",
|
||||
"conclusion": "已按插件管理方案的 reviewerFocus 审阅列表工作台、动作边界与详情抽屉数据流;当前实现未发现阻断性交付问题。",
|
||||
"outcome": "clean",
|
||||
"findings": [],
|
||||
"fileReferences": [
|
||||
"admin-frontend/src/views/system/PluginManagementView.vue",
|
||||
"admin-frontend/src/views/system/PluginCard.vue",
|
||||
"admin-frontend/src/views/system/PluginDetailDrawer.vue",
|
||||
"admin-frontend/src/utils/plugins.ts",
|
||||
"admin-frontend/src/api/admin.ts"
|
||||
],
|
||||
"fingerprint": {
|
||||
"available": true,
|
||||
"unstaged": ".helloagents/.ralph-breaker.json | 4 +-\n .helloagents/.ralph-closeout.json | 14 +-\n .helloagents/.ralph-review.json | 23 +-\n .helloagents/.ralph-visual.json | 37 ++-\n .helloagents/CHANGELOG.md | 42 +++\n .helloagents/INDEX.md | 4 +-\n .helloagents/archive/_index.md | 6 +\n .helloagents/context.md | 16 +-\n .helloagents/modules/admin-frontend.md | 26 +-\n .../2026-04-23T15-07-42-905Z-unknown-t2hj2g.jsonl | 18 --\n .helloagents/sessions/master/default/STATE.md | 21 +-\n admin-frontend/src/api/admin.ts | 229 +++++++++++++++++\n admin-frontend/src/layouts/AdminLayout.vue | 4 +-\n admin-frontend/src/router/index.ts | 22 +-\n admin-frontend/src/types/api.d.ts | 281 ++++++++++++++++++++-\n admin-frontend/src/utils/plans.ts | 9 +\n .../src/views/subscriptions/PlansView.vue | 13 +-\n public/assets/admin | 0\n 18 files changed, 679 insertions(+), 90 deletions(-)",
|
||||
"staged": "",
|
||||
"combined": ".helloagents/.ralph-breaker.json | 4 +-\n .helloagents/.ralph-closeout.json | 14 +-\n .helloagents/.ralph-review.json | 23 +-\n .helloagents/.ralph-visual.json | 37 ++-\n .helloagents/CHANGELOG.md | 42 +++\n .helloagents/INDEX.md | 4 +-\n .helloagents/archive/_index.md | 6 +\n .helloagents/context.md | 16 +-\n .helloagents/modules/admin-frontend.md | 26 +-\n .../2026-04-23T15-07-42-905Z-unknown-t2hj2g.jsonl | 18 --\n .helloagents/sessions/master/default/STATE.md | 21 +-\n admin-frontend/src/api/admin.ts | 229 +++++++++++++++++\n admin-frontend/src/layouts/AdminLayout.vue | 4 +-\n admin-frontend/src/router/index.ts | 22 +-\n admin-frontend/src/types/api.d.ts | 281 ++++++++++++++++++++-\n admin-frontend/src/utils/plans.ts | 9 +\n .../src/views/subscriptions/PlansView.vue | 13 +-\n public/assets/admin | 0\n 18 files changed, 679 insertions(+), 90 deletions(-)\n---"
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,31 @@
|
||||
{
|
||||
"updatedAt": "2026-04-24T15:11:19.540Z",
|
||||
"source": "manual",
|
||||
"originCommand": "generic-r2",
|
||||
"reason": "节点管理本轮新增分页、父子筛选、已勾选批量修改与置顶动作,需要确认工作台节奏和批量作用域提示与 Apple 化后台契约一致。",
|
||||
"tooling": [
|
||||
"code inspection",
|
||||
"npm run build"
|
||||
],
|
||||
"screensChecked": [
|
||||
"#/nodes desktop"
|
||||
],
|
||||
"statesChecked": [
|
||||
"节点列表默认加载完成态",
|
||||
"节点列表已勾选批量操作可用态",
|
||||
"节点批量修改弹窗展开态",
|
||||
"节点父子筛选切换态"
|
||||
],
|
||||
"status": "PASS",
|
||||
"summary": "已通过代码级视觉验收确认节点页维持黑色 Hero + 白色工作台结构,工具条新增父/子节点筛选、批量修改和分页后仍保持高密度但可读的 Apple 化运营节奏。",
|
||||
"findings": [],
|
||||
"recommendations": [
|
||||
"建议在真实登录态下再手动确认跨分页勾选与批量修改对后端返回数据的联动表现。"
|
||||
],
|
||||
"fingerprint": {
|
||||
"available": true,
|
||||
"unstaged": ".helloagents/.ralph-breaker.json | 4 +-\n .helloagents/.ralph-closeout.json | 12 +-\n .helloagents/.ralph-visual.json | 32 +-\n .helloagents/CHANGELOG.md | 39 +-\n .helloagents/archive/_index.md | 4 +\n .helloagents/context.md | 12 +-\n .helloagents/modules/admin-frontend.md | 19 +-\n .../.status.json | 10 +-\n .../contract.json | 27 +-\n .../proposal.md | 19 +-\n .../tasks.md | 14 +-\n .../2026-04-24T07-44-44-846Z-unknown-e3upr9.jsonl | 5 +\n .../2026-04-24T08-15-56-367Z-claude-u7aa37.jsonl | 3 +\n .helloagents/sessions/master/default/STATE.md | 18 +-\n admin-frontend/src/api/admin.ts | 31 ++\n admin-frontend/src/types/api.d.ts | 28 ++\n admin-frontend/src/types/components.d.ts | 1 +\n admin-frontend/src/utils/nodes.ts | 12 +\n admin-frontend/src/utils/orders.ts | 50 ++-\n admin-frontend/src/utils/users.ts | 352 ++++++++++++++-\n .../src/views/dashboard/DashboardView.vue | 162 +++++--\n admin-frontend/src/views/nodes/NodesView.vue | 260 ++++++++++-\n .../src/views/subscriptions/OrderAssignDrawer.vue | 3 +-\n .../src/views/subscriptions/OrderDetailDrawer.vue | 20 +-\n .../src/views/subscriptions/OrdersView.scss | 16 +\n .../src/views/subscriptions/OrdersView.vue | 225 +++++++++-\n admin-frontend/src/views/users/UsersView.vue | 490 ++++++++-------------\n admin-frontend/vite.config.ts | 3 +-\n .../V2/Admin/Server/ManageController.php | 13 +\n app/Http/Controllers/V2/Admin/UserController.php | 5 +-\n public/assets/admin | 0\n 31 files changed, 1442 insertions(+), 447 deletions(-)",
|
||||
"staged": "",
|
||||
"combined": ".helloagents/.ralph-breaker.json | 4 +-\n .helloagents/.ralph-closeout.json | 12 +-\n .helloagents/.ralph-visual.json | 32 +-\n .helloagents/CHANGELOG.md | 39 +-\n .helloagents/archive/_index.md | 4 +\n .helloagents/context.md | 12 +-\n .helloagents/modules/admin-frontend.md | 19 +-\n .../.status.json | 10 +-\n .../contract.json | 27 +-\n .../proposal.md | 19 +-\n .../tasks.md | 14 +-\n .../2026-04-24T07-44-44-846Z-unknown-e3upr9.jsonl | 5 +\n .../2026-04-24T08-15-56-367Z-claude-u7aa37.jsonl | 3 +\n .helloagents/sessions/master/default/STATE.md | 18 +-\n admin-frontend/src/api/admin.ts | 31 ++\n admin-frontend/src/types/api.d.ts | 28 ++\n admin-frontend/src/types/components.d.ts | 1 +\n admin-frontend/src/utils/nodes.ts | 12 +\n admin-frontend/src/utils/orders.ts | 50 ++-\n admin-frontend/src/utils/users.ts | 352 ++++++++++++++-\n .../src/views/dashboard/DashboardView.vue | 162 +++++--\n admin-frontend/src/views/nodes/NodesView.vue | 260 ++++++++++-\n .../src/views/subscriptions/OrderAssignDrawer.vue | 3 +-\n .../src/views/subscriptions/OrderDetailDrawer.vue | 20 +-\n .../src/views/subscriptions/OrdersView.scss | 16 +\n .../src/views/subscriptions/OrdersView.vue | 225 +++++++++-\n admin-frontend/src/views/users/UsersView.vue | 490 ++++++++-------------\n admin-frontend/vite.config.ts | 3 +-\n .../V2/Admin/Server/ManageController.php | 13 +\n app/Http/Controllers/V2/Admin/UserController.php | 5 +-\n public/assets/admin | 0\n 31 files changed, 1442 insertions(+), 447 deletions(-)\n---"
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,481 @@
|
||||
# CHANGELOG
|
||||
|
||||
## [0.6.24] - 2026-05-01
|
||||
|
||||
### 新增
|
||||
- **[admin-frontend]**: 为工单工作台对话页新增“查看用户 / 用户订单”跳转入口;当前工单用户可直接进入用户管理并按 `user_id` 精准筛选,或进入订单管理查看该用户订单 — by yinjianm
|
||||
- 方案: [202605011828_admin-ticket-user-order-links](archive/2026-05/202605011828_admin-ticket-user-order-links/)
|
||||
- 决策: admin-ticket-user-order-links#D001(使用路由 query 承载跨页面用户作用域)
|
||||
|
||||
## [0.6.23] - 2026-04-29
|
||||
|
||||
### 新增
|
||||
- **[user-frontend-access]**: 新增用户前端访问开关;后台站点设置可切换 `frontend_enable`,关闭后仅用户首页 `/` 返回空 404,不渲染站点标题或用户主题内容,订阅/API、节点 API 与管理后台保持原有访问边界 — by yinjianm
|
||||
- 方案: [202604291559_user-frontend-access-toggle](archive/2026-04/202604291559_user-frontend-access-toggle/)
|
||||
- 决策: user-frontend-access-toggle#D001(使用路由级中间件控制用户入口)
|
||||
|
||||
## [0.6.22] - 2026-04-29
|
||||
|
||||
### 修复
|
||||
- **[node-traffic-limit]**: 修复父节点自动下线后子节点仍可能保持上线的问题;新增 `parent_auto_hidden` 标记和父节点显隐联动服务,自动上线离线、流量限额 suspended 会隐藏当时仍显示的直接子节点,自动恢复或限额重置后只恢复这批由联动逻辑隐藏的子节点,手动隐藏的子节点不被误上线 — by yinjianm
|
||||
- 方案: [202604290153_parent-node-auto-visibility](archive/2026-04/202604290153_parent-node-auto-visibility/)
|
||||
- 决策: parent-node-auto-visibility#D001(使用独立父级自动隐藏标记)
|
||||
|
||||
## [0.6.21] - 2026-04-29
|
||||
|
||||
### 修复
|
||||
- **[node-traffic-limit]**: 修正节点管理月额度使用量口径;同 `machine_id` 或同 host 节点现在共享当前账期用量,`server/manage/getNodes` 返回 `traffic_limit_snapshot`,mi-node 下发的 `traffic_limit.current_used` 也改为共享账期统计,管理端优先显示快照并保留旧 metrics / `u+d` 回退 — by yinjianm
|
||||
- 方案: [202604290132_shared-node-traffic-limit](archive/2026-04/202604290132_shared-node-traffic-limit/)
|
||||
- 决策: shared-node-traffic-limit#D001(共享范围优先 machine_id,兜底 host)
|
||||
|
||||
## [0.6.20] - 2026-04-29
|
||||
|
||||
### 新增
|
||||
- **[admin-frontend]**: 节点流量详情卡新增“昨日”统计;`server/manage/getNodes` 现在返回 `traffic_stats.today/yesterday/month/total`,今日、昨日和本月均使用半开时间窗口聚合,便于对比“今日下行多、本月上行多”的流量分布来源 — by yinjianm
|
||||
- 方案: [202604290123_node-traffic-yesterday-stats](archive/2026-04/202604290123_node-traffic-yesterday-stats/)
|
||||
- 决策: node-traffic-yesterday-stats#D001(保持 u/d 语义并新增后端 yesterday 字段)
|
||||
|
||||
## [0.6.19] - 2026-04-29
|
||||
|
||||
### 快速修改
|
||||
- **[node-traffic-limit]**: 修复节点提高月流量额度后管理端仍显示“已限额”的问题;保存配置、缓存 metrics 回写和节点下发配置现在都会按当前已用流量与新额度重新计算 suspended 状态,旧额度产生的 stale metrics 不会再把节点重新标记为限额下线 — by yinjianm
|
||||
- 类型: 快速修改(无方案包)
|
||||
- 文件: app/Services/ServerTrafficLimitService.php:16-320, app/Services/ServerService.php:247-252, tests/Unit/ServerTrafficLimitServiceTest.php:60-148, E:/code/go/mi-node/internal/trafficlimit/manager_test.go:120-157
|
||||
|
||||
## [0.6.18] - 2026-04-28
|
||||
|
||||
### 新增
|
||||
- **[node-traffic-limit]**: 新增节点月流量限额强制下线能力;Xboard 可为单节点配置月额度、重置日、重置时间和时区,下发 `traffic_limit` 给 mi-node,并在手动/定时重置和 metrics 回传时同步限额状态;管理端节点编辑与流量浮层同步展示限额配置、用量、状态和下次重置 — by yinjianm
|
||||
- 方案: [202604281921_node-traffic-limit-enforcement](archive/2026-04/202604281921_node-traffic-limit-enforcement/)
|
||||
- 决策: node-traffic-limit-enforcement#D001(由 mi-node 本地强制节点下线), node-traffic-limit-enforcement#D002(复用 `transfer_enable` 作为节点月额度)
|
||||
|
||||
## [0.6.17] - 2026-04-28
|
||||
|
||||
### 快速修改
|
||||
- **[ci-workflows]**: 修复后端 Docker 构建在 `composer dump-autoload` 阶段因旧锁文件中的 `laravel/reverb` provider 自动发现而失败的问题;项目未启用 Reverb,Composer package discovery 现在会跳过 `laravel/reverb` — by yinjianm
|
||||
- 类型: 快速修改(无方案包)
|
||||
- 文件: composer.json:53-60
|
||||
|
||||
## [0.6.16] - 2026-04-28
|
||||
|
||||
### 快速修改
|
||||
- **[ci-workflows]**: 优化后端 Docker 构建缓存命中;`composer.lock` 现在进入镜像构建上下文,Composer 依赖安装提前到源码复制前并使用 BuildKit 缓存挂载,构建期不再重复执行全量 `chown/chmod` — by yinjianm
|
||||
- 类型: 快速修改(无方案包)
|
||||
- 文件: Dockerfile:1-44, .dockerignore:18-22
|
||||
|
||||
## [0.6.15] - 2026-04-28
|
||||
|
||||
### 快速修改
|
||||
- **[admin-frontend]**: 修正节点 hover 流量详情的累计统计口径,今日、本月、累计现在全部从 `v2_stat_server` 按节点聚合,避免节点当前累计字段被重置后出现“本月大于累计”的展示错误 — by yinjianm
|
||||
- 类型: 快速修改(无方案包)
|
||||
- 文件: app/Http/Controllers/V2/Admin/Server/ManageController.php:34-66, .helloagents/modules/admin-frontend.md:49
|
||||
|
||||
## [0.6.14] - 2026-04-28
|
||||
|
||||
### 修复
|
||||
- **[admin-frontend]**: 修复复制节点后在自动上线开启状态下不会立即显示的问题;自动上线同步现在可针对单节点执行,管理端保存 / 开启自动上线、REST 心跳和 WebSocket 状态上报都会立即按在线与墙状态同步 `show`,`sync:server-auto-online` 继续作为定时兜底 — by yinjianm
|
||||
- 方案: [202604281632_admin-frontend-node-auto-online-immediate-sync](archive/2026-04/202604281632_admin-frontend-node-auto-online-immediate-sync/)
|
||||
|
||||
## [0.6.13] - 2026-04-28
|
||||
|
||||
### 新增
|
||||
- **[admin-frontend]**: 为节点管理页补齐节点名称 hover 流量详情;`server/manage/getNodes` 现在返回节点级 `traffic_stats.today/month/total`,前端展示今日、本月、累计的上行、下行和合计流量 — by yinjianm
|
||||
- 方案: [202604281625_admin-frontend-node-traffic-hover](archive/2026-04/202604281625_admin-frontend-node-traffic-hover/)
|
||||
- 决策: admin-frontend-node-traffic-hover#D001(在 getNodes 聚合节点流量而不是 hover 拉取)
|
||||
|
||||
## [0.6.12] - 2026-04-28
|
||||
|
||||
### 快速修改
|
||||
- **[admin-frontend]**: 为节点管理页搜索过滤增加显隐条件,可按全部、显示中、已隐藏筛选节点,并同步重置与分页刷新逻辑 — by yinjianm
|
||||
- 类型: 快速修改(无方案包)
|
||||
- 文件: admin-frontend/src/utils/nodes.ts, admin-frontend/src/views/nodes/NodesView.vue
|
||||
|
||||
## [0.6.11] - 2026-04-28
|
||||
|
||||
### 快速修改
|
||||
- **[ci-workflows]**: 优化管理端前端 Docker 发布耗时,默认只构建 `linux/amd64`,移除 QEMU/ARM64 跨架构构建,并将 BuildKit GHA 缓存导出收敛为 `mode=min` — by yinjianm
|
||||
- 类型: 快速修改(无方案包)
|
||||
- 文件: .github/workflows/admin-frontend-docker-publish.yml:34-82, .helloagents/modules/ci-workflows.md:14-15
|
||||
|
||||
## [0.6.10] - 2026-04-28
|
||||
|
||||
### 修复
|
||||
- **[node-gfw-check]**: 修复 `parent_id=0` 的父节点在管理端显示已开启墙检测托管、但不会被自动墙检任务入队而长期显示“未检测”的问题;自动墙检现在同时兼容 `parent_id IS NULL` 与 `parent_id=0`,并把未明确关闭的 `gfw_check_enabled` 视为开启,管理端自动墙检统计也改为只统计父节点 — by yinjianm
|
||||
- 方案: [202604281441_fix-admin-node-gfw-null-enabled](archive/2026-04/202604281441_fix-admin-node-gfw-null-enabled/)
|
||||
- 决策: fix-admin-node-gfw-null-enabled#D001(自动墙检查询对齐项目父节点与启用语义)
|
||||
|
||||
## [0.6.9] - 2026-04-28
|
||||
|
||||
### 修复
|
||||
- **[ci-workflows]**: 修复仅修改 `admin-frontend/**` 且附带 `.helloagents/**` 知识库记录时仍误触发后端 Docker 发布的问题;后端 workflow 现在会忽略 `.helloagents/**`,但混有后端相关文件时仍会正常运行 — by yinjianm
|
||||
- 方案: [202604281432_ci-ignore-helloagents-for-backend-docker](archive/2026-04/202604281432_ci-ignore-helloagents-for-backend-docker/)
|
||||
- 决策: ci-ignore-helloagents-for-backend-docker#D001(后端 Docker workflow 忽略 HelloAGENTS 知识库路径)
|
||||
|
||||
## [0.6.8] - 2026-04-28
|
||||
|
||||
### 快速修改
|
||||
- **[admin-frontend]**: 精简节点管理页批量操作与工作台说明文案,并在表格底部新增基于 `sync:server-gfw-checks` 30 分钟调度节奏估算的下次自动墙检倒计时提示 — by yinjianm
|
||||
- 类型: 快速修改(无方案包)
|
||||
- 文件: admin-frontend/src/views/nodes/NodesView.vue
|
||||
|
||||
## [0.6.7] - 2026-04-28
|
||||
|
||||
### 快速修改
|
||||
- **[deploy]**: 调整 `deploy/xboard-server` 更新脚本,改为拉取镜像后通过一次性 `web` 容器执行 `php artisan xboard:update`,再重新 `up -d` 拉起服务;README 同步更新后续升级命令 — by yinjianm
|
||||
- 类型: 快速修改(无方案包)
|
||||
- 文件: deploy/xboard-server/scripts/update.sh, deploy/xboard-server/README.md
|
||||
|
||||
## [0.6.6] - 2026-04-28
|
||||
|
||||
### 新增
|
||||
- **[deploy]**: 新增 `deploy/xboard-server` 可复用服务器部署模板,基于生产 compose 拓扑补齐 `scheduler` 服务,并提供 `.env.example`、初始化/部署/更新/状态检查脚本和部署说明 — by yinjianm
|
||||
- 方案: [202604281303_xboard-reusable-server-deploy](archive/2026-04/202604281303_xboard-reusable-server-deploy/)
|
||||
- 决策: xboard-reusable-server-deploy#D001(使用独立 scheduler 服务驱动 Laravel Scheduler), xboard-reusable-server-deploy#D002(默认不把 MySQL 纳入一键模板)
|
||||
|
||||
## [0.6.5] - 2026-04-28
|
||||
|
||||
### 修复
|
||||
- **[queue-mail]**: 修复 `SendEmailJob` 10 秒超时导致 `send_email` 队列邮件作业批量失败的问题;邮件 job 现在使用 60 秒超时、明确 backoff、timeout 失败直接 fail,并把邮件发送错误交给队列异常机制处理。同时新增 `MAIL_TIMEOUT` / `QUEUE_RETRY_AFTER` 配置、刷新 Horizon 长驻 worker 的运行时 mailer 配置,并对 `MailLog.config` 中的敏感字段脱敏 — by yinjianm
|
||||
- 方案: [202604281258_fix-send-email-job-timeout](archive/2026-04/202604281258_fix-send-email-job-timeout/)
|
||||
- 决策: fix-send-email-job-timeout#D001(保留队列结构并修复 job 与 mail transport 超时)
|
||||
|
||||
## [0.6.4] - 2026-04-28
|
||||
|
||||
### 修复
|
||||
- **[node-gfw-check]**: 修复墙检测任务卡在 `pending/checking` 后会长期占用 active 状态的问题;超过 5 分钟未被节点端领取或未上报的任务会标记为检测失败,管理端区分展示“等待节点领取”和“检测中”,并在开启父节点墙检测托管时立即发起一次检测。同时补齐 Docker/supervisor 的 `schedule:work` 进程和 compose scheduler 样例,确保自动墙检测调度会持续运行;修正 mi-node 的 ping 成功判定,避免正常可达但平均延迟解析不到时被误判为超时 — by yinjianm
|
||||
- 类型: 快速修改(无方案包)
|
||||
- 文件: app/Services/ServerGfwCheckService.php, app/Console/Commands/SyncServerGfwChecks.php, admin-frontend/src/utils/nodes.ts, admin-frontend/src/views/nodes/NodesView.vue, .docker/supervisor/supervisord.conf, .docker/entrypoint.sh, Dockerfile, compose.sample.yaml, E:/code/go/mi-node/internal/gfwcheck/gfwcheck.go
|
||||
|
||||
## [0.6.3] - 2026-04-28
|
||||
|
||||
### 新增
|
||||
- **[node-gfw-check]**: 为节点墙状态检测打通自动检测与自动显隐;`sync:server-gfw-checks` 会自动为开启托管的父节点创建检测任务,`blocked` 时自动隐藏节点并阻止自动上线重新发布,`normal` 时只恢复由墙检测自动隐藏的节点;管理端节点页新增刷新数据、墙检测托管开关和批量设置入口 — by yinjianm
|
||||
- 方案: [202604280024_node-gfw-auto-check-and-online](archive/2026-04/202604280024_node-gfw-auto-check-and-online/)
|
||||
- 决策: node-gfw-auto-check-and-online#D001(使用自动隐藏标记隔离管理员手动显隐), node-gfw-auto-check-and-online#D002(自动上线服务必须把 blocked 作为显示否决)
|
||||
|
||||
## [0.6.2] - 2026-04-27
|
||||
|
||||
### 新增
|
||||
- **[admin-frontend]**: 为节点管理新增可控“自动上线”能力;节点可单独或批量开启后台托管,`sync:server-auto-online` 会按在线状态自动同步前台显示,在线 / 待同步时显示,离线时隐藏,未开启自动上线的节点继续保持手动显隐控制 — by yinjianm
|
||||
- 方案: [202604272338_admin-frontend-node-auto-online](archive/2026-04/202604272338_admin-frontend-node-auto-online/)
|
||||
- 决策: admin-frontend-node-auto-online#D001(自动上线使用独立字段与独立同步服务)
|
||||
|
||||
## [0.6.1] - 2026-04-27
|
||||
|
||||
### 快速修改
|
||||
- **[admin-frontend]**: 修复独立 admin 前端容器内 `/upload/rest/upload` 返回 404 的问题;`Caddyfile` 现在会把 `/upload/*` 去掉 `/upload` 前缀后反向代理到 `XBOARD_UPLOAD_UPSTREAM`,默认对齐开发环境的图片上传服务 — by yinjianm
|
||||
- 类型: 快速修改(无方案包)
|
||||
- 文件: admin-frontend/Caddyfile:1-28
|
||||
|
||||
## [0.6.0] - 2026-04-27
|
||||
|
||||
### 新增
|
||||
- **[node-gfw-check]**: 新增节点墙状态检测闭环,管理端可对父节点发起检测并在节点列表展示、搜索和筛选正常 / 疑似被墙 / 部分异常 / 检测失败 / 未检测状态;子节点不单独检测并继承父节点状态,mi-node 支持 `gfw.check` WS 触发、REST 兜底领取和三网 ping 结果上报 — by yinjianm
|
||||
- 方案: [202604272325_node-gfw-check](archive/2026-04/202604272325_node-gfw-check/)
|
||||
- 决策: node-gfw-check#D001(使用 WS 触发 + REST 兜底), node-gfw-check#D002(子节点继承父节点墙状态)
|
||||
|
||||
## [0.5.19] - 2026-04-27
|
||||
|
||||
### 新增
|
||||
- **[admin-frontend]**: 为工单工作台回复区补齐图片拖拽上传与剪贴板粘贴上传,统一复用现有图片上传接口和 Markdown 图片插入逻辑,并将超大工单工作台组件拆分出上传 composable 与独立 SCSS 样式文件 — by yinjianm
|
||||
- 方案: [202604272310_ticket-chat-image-dnd-paste-upload](archive/2026-04/202604272310_ticket-chat-image-dnd-paste-upload/)
|
||||
- 决策: ticket-chat-image-dnd-paste-upload#D001(统一图片入口到现有 Markdown 上传链路)
|
||||
|
||||
## [0.5.18] - 2026-04-27
|
||||
|
||||
### 快速修改
|
||||
- **[admin-frontend]**: 调整节点管理状态筛选口径,“在线节点”现在同时包含显式在线与待同步节点,顶部在线节点统计同步采用相同口径;“离线节点”仍只匹配显式离线节点 — by yinjianm
|
||||
- 类型: 快速修改(无方案包)
|
||||
- 文件: admin-frontend/src/utils/nodes.ts:12-176
|
||||
|
||||
## [0.5.17] - 2026-04-25
|
||||
|
||||
### 修复
|
||||
- **[admin-frontend]**: 修复节点编辑 / 批量修改保存权限组后订阅侧无法命中节点的问题;前端提交 `group_ids / route_ids` 时统一序列化为字符串 ID,后端 `whereGroupId` 同时兼容历史字符串与数字 JSON 值,并补齐 TUIC V5/V4、ALPN 选项与 AnyTLS 完整默认 Padding Scheme — by yinjianm
|
||||
- 类型: 快速修改(无方案包)
|
||||
- 文件: admin-frontend/src/utils/nodeEditorMapper.ts, admin-frontend/src/utils/nodeEditorOptions.ts, admin-frontend/src/views/nodes/NodeEditorProtocolSection.vue, app/Models/Server.php
|
||||
|
||||
## [0.5.16] - 2026-04-25
|
||||
|
||||
### 新增
|
||||
- **[admin-frontend]**: 为用户管理高级筛选新增“活跃状态”条件,支持按“活跃 / 非活跃”筛选;后端 `user/fetch` 现可识别 `activity_status` 复合规则,并按“任意订阅 + 流量未用完 + 最后在线时间在半年内”为活跃标准返回结果 — by yinjianm
|
||||
- 方案: [202604250018_admin-frontend-user-activity-status-filter](archive/2026-04/202604250018_admin-frontend-user-activity-status-filter/)
|
||||
- 决策: admin-frontend-user-activity-status-filter#D001(活跃判断入口固定在高级筛选弹窗), admin-frontend-user-activity-status-filter#D002(复合活跃规则统一由后端 activity_status 承接), admin-frontend-user-activity-status-filter#D003(全部状态继续由无条件表达)
|
||||
|
||||
## [0.5.15] - 2026-04-25
|
||||
|
||||
### 新增
|
||||
- **[admin-frontend]**: 为节点管理工作台补齐“在线节点 / 离线节点”状态筛选,并新增针对已勾选节点的批量删除入口,接通真实 `server/manage/batchDelete` 后端链路;其中“离线节点”按本轮确认只筛显式离线状态,不包含待同步 / 已停用节点 — by yinjianm
|
||||
- 方案: [202604250015_admin-frontend-node-status-filter-batch-delete](plan/202604250015_admin-frontend-node-status-filter-batch-delete/)
|
||||
- 决策: admin-frontend-node-status-filter-batch-delete#D001(离线筛选仅匹配显式 offline 状态), admin-frontend-node-status-filter-batch-delete#D002(批量删除复用现有勾选工作流)
|
||||
|
||||
## [0.5.14] - 2026-04-25
|
||||
|
||||
### 修复
|
||||
- **[order-payment]**: 补齐订单支付成功快照保存链路;现在会在支付成功后保存支付渠道、支付方法、实际支付金额与支付 IP,并在后台订单详情中集中展示平台订单号 / 商户订单号 / 支付快照信息 — by yinjianm
|
||||
- 方案: [202604250002_order-payment-snapshot](archive/2026-04/202604250002_order-payment-snapshot/)
|
||||
- 决策: order-payment-snapshot#D001(支付快照优先展示真实快照并回退当前支付配置), order-payment-snapshot#D002(实际支付金额统一按“分”存储)
|
||||
|
||||
## [0.5.13] - 2026-04-25
|
||||
|
||||
### 修复
|
||||
- **[admin-frontend]**: 修复前后台已关闭工单无法再次回复的问题;现在用户与管理员再次回复 closed ticket 时都会自动重新开启工单,管理端工单工作台也补上“发送并重开”交互提示 — by yinjianm
|
||||
- 方案: [202604250006_ticket-closed-reply-reopen](plan/202604250006_ticket-closed-reply-reopen/)
|
||||
- 决策: ticket-closed-reply-reopen#D001(自动重开语义统一下沉到 TicketService::reply), ticket-closed-reply-reopen#D002(用户端优先通过后端语义修复打通), ticket-closed-reply-reopen#D003(管理端仅修复交互门禁)
|
||||
|
||||
## [0.5.12] - 2026-04-25
|
||||
|
||||
### 新增
|
||||
- **[admin-frontend]**: 为仪表盘顶部指标卡补齐快捷入口增强;“待处理工单 / 待处理佣金 / 总用户”现在可直接进入对应工作台,其中工单页与订单页还会自动识别 dashboard 来源并落在目标视图 — by yinjianm
|
||||
- 方案: [202604250002_admin-frontend-dashboard-shortcuts](plan/202604250002_admin-frontend-dashboard-shortcuts/)
|
||||
- 决策: admin-frontend-dashboard-shortcuts#D001(仅开放已有明确承接页的指标卡快捷入口), admin-frontend-dashboard-shortcuts#D002(用路由查询同步 dashboard 入口上下文)
|
||||
|
||||
## [0.5.11] - 2026-04-24
|
||||
|
||||
### 快速修改
|
||||
- **[admin-frontend]**: 修复节点管理页多选框点击后立即被程序化同步清空的问题;现在仅在分页切换时回填勾选状态,并在回填期间忽略内部 `selection-change` 事件,节点多选可正常选中与跨页恢复 — by yinjianm
|
||||
- 类型: 快速修改(无方案包)
|
||||
- 文件: admin-frontend/src/views/nodes/NodesView.vue:67,179-197,240-243,412-417
|
||||
|
||||
## [0.5.10] - 2026-04-24
|
||||
|
||||
### 快速修改
|
||||
- **[ci-workflows]**: 将后端镜像发布工作流显式命名为 `Backend Docker Build and Publish`,并对 `admin-frontend/**` 及其独立 workflow 启用 `paths-ignore`;现在仅修改 `admin-frontend` 源码时只触发前端镜像发布,不再误触发后端镜像发布 — by yinjianm
|
||||
- 类型: 快速修改(无方案包)
|
||||
- 文件: .github/workflows/docker-publish.yml:1-76
|
||||
|
||||
## [0.5.9] - 2026-04-24
|
||||
|
||||
### 新增
|
||||
- **[admin-frontend]**: 为节点管理工作台补齐本地分页、父/子节点筛选、单节点置顶与仅对已勾选节点生效的批量修改,支持统一更新 `host / group_ids / rate`,并接通真实 `server/manage/batchUpdate` 后端链路 — by yinjianm
|
||||
- 方案: [202604242245_admin-frontend-node-pagination-batch-edit](archive/2026-04/202604242245_admin-frontend-node-pagination-batch-edit/)
|
||||
- 决策: admin-frontend-node-pagination-batch-edit#D001(节点分页采用前端本地分页), admin-frontend-node-pagination-batch-edit#D002(批量修改范围固定为已勾选节点), admin-frontend-node-pagination-batch-edit#D003(置顶节点复用 server/manage/sort)
|
||||
|
||||
### 快速修改
|
||||
- **[admin-frontend]**: 为独立 `xboard-admin-frontend` 容器补齐 `/api` 反向代理到后端 `web` 服务的链路,并在 compose 分支 `admin` 服务中显式声明 `XBOARD_BACKEND_UPSTREAM=http://web:7001`;同时把镜像名对齐到当前 fork `ghcr.io/micah123321/*` — by yinjianm
|
||||
- 类型: 快速修改(无方案包)
|
||||
- 文件: admin-frontend/Caddyfile:1-17, E:/code/php/Xboard-new-compose/compose.yaml:1-26
|
||||
|
||||
## [0.5.8] - 2026-04-24
|
||||
|
||||
### 新增
|
||||
- **[admin-frontend]**: 为 `admin-frontend` 新增独立 Docker 镜像与 GHCR 自动发布链路,支持通过 `ADMIN_BUILD_OUT_DIR` 切换到容器专用 `dist` 输出,并在 `compose` 分支新增独立 `admin` 服务拉取 `ghcr.io/cedar2025/xboard-admin-frontend:new` 暴露运行 — by yinjianm
|
||||
- 方案: [202604242250_admin-frontend-ghcr-compose](plans/202604242250_admin-frontend-ghcr-compose/)
|
||||
- 决策: admin-frontend-ghcr-compose#D001(前端镜像发布链路独立于后端 docker-publish), admin-frontend-ghcr-compose#D002(容器内统一重定向到 /assets/admin/), admin-frontend-ghcr-compose#D003(compose 分支采用独立 admin 服务并暴露 7002)
|
||||
|
||||
## [0.5.7] - 2026-04-24
|
||||
|
||||
### 新增
|
||||
- **[admin-frontend]**: 为用户管理“更多操作”菜单补齐旧后台常用行级动作,新增分配订单、查看 TA 的订单、查看 TA 的邀请、查看 TA 的流量记录与重置流量,并接通订单页按用户过滤与真实 `traffic-reset/reset-user` 后端链路 — by yinjianm
|
||||
- 方案: [202604242236_admin-frontend-user-more-actions](plans/202604242236_admin-frontend-user-more-actions/)
|
||||
- 决策: admin-frontend-user-more-actions#D001(订单分配抽屉预填邮箱), admin-frontend-user-more-actions#D002(用户订单采用跳页 + user_id 过滤), admin-frontend-user-more-actions#D003(邀请结果复用当前用户页筛选视图)
|
||||
|
||||
## [0.5.6] - 2026-04-24
|
||||
|
||||
### 修复
|
||||
- **[admin-frontend]**: 修复订单管理页把无佣金订单误显示为“待确认”的问题;现在佣金状态会按真实佣金金额与发放链路判断,同时新增“确认佣金”菜单,可筛出真实待确认订单并在列表行级直接手动确认 — by yinjianm
|
||||
- 方案: [202604242217_admin-frontend-orders-commission-confirmation](archive/2026-04/202604242217_admin-frontend-orders-commission-confirmation/)
|
||||
- 决策: admin-frontend-orders-commission-confirmation#D001(真实佣金判定以金额和发放链路为准), admin-frontend-orders-commission-confirmation#D002(列表页新增确认佣金菜单与单行快捷确认)
|
||||
|
||||
## [0.5.5] - 2026-04-24
|
||||
|
||||
### 新增
|
||||
- **[admin-frontend]**: 为用户管理工作台新增高级筛选与批量操作能力,支持多条件筛选、批量发送邮件、导出 CSV、批量封禁,以及对筛选结果执行“恢复正常” — by yinjianm
|
||||
- 方案: [202604242200_admin-frontend-user-advanced-filter-batch-ops](plans/202604242200_admin-frontend-user-advanced-filter-batch-ops/)
|
||||
- 决策: admin-frontend-user-advanced-filter-batch-ops#D001(高级筛选采用独立弹窗), admin-frontend-user-advanced-filter-batch-ops#D002(批量作用域按 selected > filtered > all 解析), admin-frontend-user-advanced-filter-batch-ops#D003(恢复正常沿用 user/ban 并扩展 banned=0|1)
|
||||
|
||||
## [0.5.4] - 2026-04-24
|
||||
|
||||
### 修复
|
||||
- **[admin-frontend]**: 修复仪表盘“节点流量排行 / 用户流量排行”在 `24h` 视图下涨跌始终显示 `0%` 的问题;后端现在会把单日排行改为精确对比昨天整日统计,前端同步补上悬浮详情卡,并把当前流量值右移强化显示 — by yinjianm
|
||||
- 方案: [202604241925_admin-frontend-dashboard-rank-24h-compare](plan/202604241925_admin-frontend-dashboard-rank-24h-compare/)
|
||||
- 决策: admin-frontend-dashboard-rank-24h-compare#D001(仅修复 24h 与昨天对比逻辑,7天/30天 保持现状), admin-frontend-dashboard-rank-24h-compare#D002(排行项补充 hover 详情卡,并将当前流量右移显示)
|
||||
|
||||
## [0.5.3] - 2026-04-24
|
||||
|
||||
### 新增
|
||||
- **[admin-frontend]**: 完成节点管理真实新增 / 编辑 / 排序工作台,补齐 11 种协议的动态配置弹窗、动态倍率规则编辑、路由 / 权限组联动与排序保存流程,并接入真实 `server/manage/save`、`server/manage/sort`、`server/route/fetch` 后台接口 — by yinjianm
|
||||
- 方案: [202604241718_admin-frontend-node-management](plans/202604241718_admin-frontend-node-management/)
|
||||
- 决策: admin-frontend-node-management#D001(新增与编辑共用中央大弹窗), admin-frontend-node-management#D002(排序沿用本地草稿 + 上移 / 下移), admin-frontend-node-management#D003(协议配置采用通用字段 + 动态协议块)
|
||||
|
||||
## [0.5.2] - 2026-04-24
|
||||
|
||||
### 新增
|
||||
- **[admin-frontend]**: 开放“礼品卡管理”入口,完整交付模板管理、兑换码管理、使用记录与统计数据四页签工作台,并接入真实 `gift-card/*` 后台接口 — by yinjianm
|
||||
- 方案: [202604241703_admin-frontend-gift-card-management](archive/2026-04/202604241703_admin-frontend-gift-card-management/)
|
||||
- 决策: admin-frontend-gift-card-management#D001(礼品卡管理采用单页四页签导航), admin-frontend-gift-card-management#D002(模板编辑使用分组式大抽屉), admin-frontend-gift-card-management#D003(兑换码导出按当前批次显式执行)
|
||||
|
||||
## [0.5.1] - 2026-04-24
|
||||
|
||||
### 新增
|
||||
- **[admin-frontend]**: 完成“路由管理”真实工作台,支持路由列表、关键词搜索、新增/编辑弹窗、删除,以及基于节点 `route_ids` 推导的节点引用摘要,并接入真实 `server/route/*` 后台接口 — by yinjianm
|
||||
- 方案: [202604241701_admin-frontend-node-route-management](plan/202604241701_admin-frontend-node-route-management/)
|
||||
- 决策: admin-frontend-node-route-management#D001(列表页贴近用户截图并保留 Apple 化后台节奏), admin-frontend-node-route-management#D002(节点引用摘要先收敛为列表只读信息而不扩展拓扑视图), admin-frontend-node-route-management#D003(动作值仅在 dns/proxy 时显示独立输入)
|
||||
|
||||
## [0.5.0] - 2026-04-24
|
||||
|
||||
### 新增
|
||||
- **[admin-frontend]**: 将 `#/node-groups` 从占位页升级为真实权限组管理工作台,支持搜索、新增/编辑中央弹窗、删除确认,并补齐到 `#/nodes` 的权限组筛选联动入口 — by yinjianm
|
||||
- 方案: [202604241659_admin-frontend-node-group-management](archive/2026-04/202604241659_admin-frontend-node-group-management/)
|
||||
- 决策: admin-frontend-node-group-management#D001(权限组页采用截图导向的轻量工作台), admin-frontend-node-group-management#D002(新增与编辑复用同一中央弹窗), admin-frontend-node-group-management#D003(节点数量列承担跳转到节点筛选的联动入口)
|
||||
|
||||
## [0.4.8] - 2026-04-24
|
||||
|
||||
### 修复
|
||||
- **[admin-frontend]**: 修复 `#/system/knowledge` 仍回退到结构化占位页的问题,补齐真实知识库管理列表挂载、详情编辑加载与最新构建产物刷新 — by yinjianm
|
||||
- 方案: [202604241610_admin-frontend-knowledge-management](plan/202604241610_admin-frontend-knowledge-management/)
|
||||
- 决策: admin-frontend-knowledge-management#D001(编辑器采用轻量 Markdown 方案), admin-frontend-knowledge-management#D002(列表页采用真实表格与中央对话框), admin-frontend-knowledge-management#D003(排序采用本地草稿编辑后统一提交)
|
||||
|
||||
## [0.4.7] - 2026-04-24
|
||||
|
||||
### 修复
|
||||
- **[admin-frontend]**: 修复管理端侧边栏在低窗口高度下会裁切底部菜单的问题;现在顶部品牌区保持固定,菜单区可独立滚动访问“礼品卡管理”“系统管理”“支付配置”“知识库管理”等底部入口 — by yinjianm
|
||||
- 方案: [202604241655_admin-frontend-sidebar-height-overflow](archive/2026-04/202604241655_admin-frontend-sidebar-height-overflow/)
|
||||
- 决策: admin-frontend-sidebar-height-overflow#D001(固定品牌区 + 独立滚动菜单区)
|
||||
|
||||
## [0.4.6] - 2026-04-24
|
||||
|
||||
### 修复
|
||||
- **[subscription-protocols]**: 修复 `flag=stash` 订阅在未知版本或低版本客户端下仍导出 `AnyTLS` 节点的问题;现在只有 Stash `>= 3.3.0` 才会保留 `AnyTLS`,避免导入时报“**不支持 anytls 协议**” — by yinjianm
|
||||
- 方案: [202604241619_fix-stash-anytls-compat-filter](plan/202604241619_fix-stash-anytls-compat-filter/)
|
||||
- 决策: fix-stash-anytls-compat-filter#D001(未知版本按不支持 AnyTLS 处理), fix-stash-anytls-compat-filter#D002(仅在 Stash 导出器中做定点修复)
|
||||
|
||||
## [0.4.5] - 2026-04-24
|
||||
|
||||
### 新增
|
||||
- **[admin-frontend]**: 开放“订单管理”入口,完整交付真实订单列表、类型/周期/状态筛选、分配订单抽屉、详情抽屉、手动标记已支付与佣金状态维护,并接入 `order/*` 后台接口 — by yinjianm
|
||||
- 方案: [202604241620_admin-frontend-order-management](archive/2026-04/202604241620_admin-frontend-order-management/)
|
||||
- 决策: admin-frontend-order-management#D001(列表页贴近用户截图并保留 Apple 化后台节奏), admin-frontend-order-management#D002(详情操作收口到订单详情抽屉而不是额外操作列), admin-frontend-order-management#D003(订单金额统一按“分→元”格式化展示)
|
||||
|
||||
## [0.4.4] - 2026-04-24
|
||||
|
||||
### 新增
|
||||
- **[admin-frontend]**: 完成“支付配置”真实工作台,支持支付方式列表、关键词搜索、启停、删除、动态配置抽屉与排序模式,并接入真实 `payment/*` 后台接口 — by yinjianm
|
||||
- 方案: [202604241558_admin-frontend-payment-management](archive/2026-04/202604241558_admin-frontend-payment-management/)
|
||||
- 决策: admin-frontend-payment-management#D001(真实列表页+动态配置抽屉+排序对话框), admin-frontend-payment-management#D002(支付配置字段完全以后端动态表单为真相源), admin-frontend-payment-management#D003(启停继续沿用切换型接口并做同值短路保护)
|
||||
|
||||
## [0.4.3] - 2026-04-24
|
||||
|
||||
### 新增
|
||||
- **[admin-frontend]**: 将 `#/system/themes` 从结构化占位页升级为真实主题管理页面,接入主题列表、当前主题切换、动态主题配置抽屉与 zip 主题上传入口 — by yinjianm
|
||||
- 方案: [202604241607_admin-frontend-theme-management](archive/2026-04/202604241607_admin-frontend-theme-management/)
|
||||
- 决策: admin-frontend-theme-management#D001(主题切换复用 config/save(frontend_theme)), admin-frontend-theme-management#D002(主题配置统一放入抽屉)
|
||||
|
||||
## [0.4.3] - 2026-04-24
|
||||
|
||||
### 新增
|
||||
- **[admin-frontend]**: 将 `#/system/plugins` 从占位页升级为真实插件管理工作台,接入插件列表、类型 / 状态筛选、上传、安装、启停、升级、卸载,以及 README / 动态配置抽屉;同时补齐缺失的订单管理与知识库管理路由壳层以恢复 `npm run build` 通过 — by yinjianm
|
||||
- 方案: [202604241553_admin-frontend-plugin-management](archive/2026-04/202604241553_admin-frontend-plugin-management/)
|
||||
- 决策: admin-frontend-plugin-management#D001(插件管理采用卡片列表 + 详情抽屉), admin-frontend-plugin-management#D002(配置编辑使用动态 schema 渲染), admin-frontend-plugin-management#D003(README 与配置合并进同一个详情工作台)
|
||||
|
||||
## [0.4.2] - 2026-04-24
|
||||
|
||||
### 新增
|
||||
- **[admin-frontend]**: 完成“知识库管理”真实工作台,支持知识列表、标题搜索、分类筛选、显隐切换、新增/编辑弹窗、删除与排序模式,并接入真实 `knowledge/*` 后台接口 — by yinjianm
|
||||
- 方案: [202604241610_admin-frontend-knowledge-management](plan/202604241610_admin-frontend-knowledge-management/)
|
||||
- 决策: admin-frontend-knowledge-management#D001(编辑器采用轻量 Markdown 方案), admin-frontend-knowledge-management#D002(列表页采用真实表格与中央对话框), admin-frontend-knowledge-management#D003(排序采用本地草稿编辑后统一提交)
|
||||
|
||||
## [0.4.1] - 2026-04-24
|
||||
|
||||
### 新增
|
||||
- **[admin-frontend]**: 完成“公告管理”真实工作台,支持公告列表、标题搜索、显隐切换、新增/编辑弹窗、删除与排序模式,并接入真实 `notice/*` 后台接口 — by yinjianm
|
||||
- 方案: [202604241609_admin-frontend-notice-management](plan/202604241609_admin-frontend-notice-management/)
|
||||
- 决策: admin-frontend-notice-management#D001(真实列表页+编辑弹窗+排序对话框), admin-frontend-notice-management#D002(公告内容编辑继续使用轻量 Markdown 方案), admin-frontend-notice-management#D003(公告开关与标签统一归一化)
|
||||
|
||||
## [0.4.0] - 2026-04-24
|
||||
|
||||
### 新增
|
||||
- **[admin-frontend]**: 开放“优惠券管理”入口,完整交付优惠券列表、关键字搜索、类型筛选、启停、删除,以及接入真实 `coupon/*` 接口的新增/编辑弹窗 — by yinjianm
|
||||
- 方案: [202604241551_admin-frontend-coupon-management](archive/2026-04/202604241551_admin-frontend-coupon-management/)
|
||||
- 决策: admin-frontend-coupon-management#D001(优惠券列表采用真实接口+本地搜索筛选分页), admin-frontend-coupon-management#D002(新增与编辑共用同一弹窗并统一序列化), admin-frontend-coupon-management#D003(优惠券编辑采用居中弹窗而非抽屉)
|
||||
|
||||
## [0.3.2] - 2026-04-24
|
||||
|
||||
### 修复
|
||||
- **[admin-frontend]**: 修复 `#/subscriptions/plans` 页面首次加载时会误把套餐“新购”状态批量关闭的问题;现在会先归一化 `show / sell / renew` 开关值,并在同值事件下短路,避免浏览页面即触发真实写操作 — by yinjianm
|
||||
- 方案: [202604241542_admin-frontend-plan-toggle-regression](plan/202604241542_admin-frontend-plan-toggle-regression/)
|
||||
- 决策: admin-frontend-plan-toggle-regression#D001(前端入口先归一化套餐开关值), admin-frontend-plan-toggle-regression#D002(开关提交增加同值短路护栏)
|
||||
|
||||
## [0.3.0] - 2026-04-23
|
||||
|
||||
### 新增
|
||||
- **[admin-frontend]**: 新增“节点管理”侧边栏分组、节点管理工作台,以及权限组/路由管理占位页;同时补齐缺失的 `PlansView` 占位组件以恢复 `npm run build` 构建通过 — by yinjianm
|
||||
- 方案: [202604232320_admin-frontend-node-management](archive/2026-04/202604232320_admin-frontend-node-management/)
|
||||
- 决策: admin-frontend-node-management#D001(首批聚焦节点列表运营链路), admin-frontend-node-management#D002(权限组与路由管理先交付结构化占位页)
|
||||
|
||||
## [0.3.1] - 2026-04-23
|
||||
|
||||
### 新增
|
||||
- **[admin-frontend]**: 新增“系统管理”侧边栏分组,完整交付系统配置页,并接入插件/主题/公告/支付/知识库 5 个结构化占位页 — by yinjianm
|
||||
- 方案: [202604232329_admin-frontend-system-management](archive/2026-04/202604232329_admin-frontend-system-management/)
|
||||
- 决策: admin-frontend-system-management#D001(首批聚焦系统配置真实页), admin-frontend-system-management#D002(其余系统管理入口先交付结构化占位页), admin-frontend-system-management#D003(系统配置采用左侧分组导航与右侧连续 section)
|
||||
|
||||
## [0.1.0] - 2026-04-21
|
||||
|
||||
### 新增
|
||||
- **[admin-frontend]**: 完成深色 Composio 风格管理端仪表盘、登录回跳和真实统计面板接入 — by yinjianm
|
||||
- 方案: [202604210326_admin-frontend-composio-dashboard](archive/2026-04/202604210326_admin-frontend-composio-dashboard/)
|
||||
- 决策: admin-frontend-composio-dashboard#D001(采用深色 Composio 风格), admin-frontend-composio-dashboard#D002(趋势图使用自绘 SVG)
|
||||
|
||||
## [0.1.1] - 2026-04-21
|
||||
|
||||
### 修复
|
||||
- **[admin-frontend]**: 将登录页、主布局和仪表盘重构为 Apple 风格,并移除高成本视觉装饰以缓解页面卡顿 — by yinjianm
|
||||
- 方案: [202604210400_admin-frontend-apple-performance-refresh](archive/2026-04/202604210400_admin-frontend-apple-performance-refresh/)
|
||||
- 决策: admin-frontend-apple-performance-refresh#D001(采用 Apple 风格并优先性能减法), admin-frontend-apple-performance-refresh#D002(保留逻辑层只替换视图皮层)
|
||||
|
||||
## [0.1.2] - 2026-04-21
|
||||
|
||||
### 快速修改
|
||||
- **[admin-frontend]**: 修正仪表盘金额显示单位,将后端返回的“分”统一转换为“元”后再格式化 — by yinjianm
|
||||
- 类型: 快速修改(无方案包)
|
||||
- 文件: admin-frontend/src/utils/dashboard.ts:75
|
||||
|
||||
## [0.2.0] - 2026-04-21
|
||||
|
||||
### 新增
|
||||
- **[admin-frontend]**: 新增用户管理工作台、抽屉表单、用户操作菜单,以及“用户管理 / 工单管理”导航与路由骨架 — by yinjianm
|
||||
- 方案: [202604210441_admin-frontend-user-management](archive/2026-04/202604210441_admin-frontend-user-management/)
|
||||
- 决策: admin-frontend-user-management#D001(新增用户采用两段式创建), admin-frontend-user-management#D002(先补齐用户与工单入口结构)
|
||||
|
||||
## [0.2.1] - 2026-04-23
|
||||
|
||||
### 新增
|
||||
- **[admin-frontend]**: 为仪表盘收入趋势面板新增“按金额 / 按数量”切换,并让图表摘要、Y 轴标签与最近记录跟随口径同步 — by yinjianm
|
||||
- 方案: [202604232313_admin-frontend-dashboard-trend-count-toggle](archive/2026-04/202604232313_admin-frontend-dashboard-trend-count-toggle/)
|
||||
- 决策: admin-frontend-dashboard-trend-count-toggle#D001(采用单图切换而不是双图/双线), admin-frontend-dashboard-trend-count-toggle#D002(数量模式复用现有接口字段)
|
||||
|
||||
## [0.2.2] - 2026-04-23
|
||||
|
||||
### 新增
|
||||
- **[admin-frontend]**: 为仪表盘节点/用户流量排行新增 `10个 / 20个` 显示切换,并将长列表收进面板内滚动区域 — by yinjianm
|
||||
- 方案: [202604232318_admin-frontend-rank-limit-scroll](archive/2026-04/202604232318_admin-frontend-rank-limit-scroll/)
|
||||
- 决策: admin-frontend-rank-limit-scroll#D001(两个排行面板独立控制显示数量), admin-frontend-rank-limit-scroll#D002(使用固定高度滚动容器而不是整页自然拉伸)
|
||||
|
||||
## [0.2.3] - 2026-04-23
|
||||
|
||||
### 新增
|
||||
- **[admin-frontend]**: 为仪表盘“作业详情”面板新增“查看报错详情”入口,并通过弹窗展示失败作业的报错摘要、失败时间与队列信息 — by yinjianm
|
||||
- 方案: [202604232330_admin-frontend-queue-error-details](plan/202604232330_admin-frontend-queue-error-details/)
|
||||
- 决策: admin-frontend-queue-error-details#D001(使用弹窗承载失败作业详情), admin-frontend-queue-error-details#D002(前端兼容式解析 Horizon 失败作业字段)
|
||||
|
||||
## [0.2.4] - 2026-04-23
|
||||
|
||||
### 新增
|
||||
- **[admin-frontend]**: 为 traffic rank 前后端联动补齐 `limit=10|20` 支持,让排行数量切换真正驱动后端返回条数,并保留 24h 口径的涨跌展示 — by yinjianm
|
||||
- 方案: [202604232345_traffic-rank-limit-backend-adapt](archive/2026-04/202604232345_traffic-rank-limit-backend-adapt/)
|
||||
- 决策: traffic-rank-limit-backend-adapt#D001(在现有 getTrafficRank 接口上新增 limit 参数), traffic-rank-limit-backend-adapt#D002(24h 口径继续显示 change)
|
||||
|
||||
## [0.2.5] - 2026-04-23
|
||||
|
||||
### 新增
|
||||
- **[admin-frontend]**: 为 Apple 风格仪表盘新增 Hero 区“刷新全部数据”按钮,并补齐最后刷新时间、加载反馈与防重复触发状态 — by yinjianm
|
||||
- 方案: [202604231515_admin-frontend-dashboard-refresh-button](archive/2026-04/202604231515_admin-frontend-dashboard-refresh-button/)
|
||||
- 决策: admin-frontend-dashboard-refresh-button#D001(刷新入口放在 Hero 状态区), admin-frontend-dashboard-refresh-button#D002(复用 refreshDashboard 作为唯一全量刷新入口)
|
||||
|
||||
## [0.2.6] - 2026-04-23
|
||||
|
||||
### 新增
|
||||
- **[admin-frontend]**: 新增“订阅管理”侧边栏分组与套餐管理页面,支持真实套餐 CRUD、排序、价格矩阵与说明预览 — by yinjianm
|
||||
- 方案: [202604232325_admin-frontend-subscription-plan-management](plan/202604232325_admin-frontend-subscription-plan-management/)
|
||||
- 决策: admin-frontend-subscription-plan-management#D001(其余订阅菜单先保留禁用入口), admin-frontend-subscription-plan-management#D002(说明编辑采用轻量 Markdown 方案), admin-frontend-subscription-plan-management#D003(排序采用本地编辑对话框)
|
||||
@@ -0,0 +1,74 @@
|
||||
# Xboard-new 管理端设计系统
|
||||
|
||||
## 产品表面
|
||||
- `admin-frontend` 是数据密集型管理后台,当前核心界面包括仪表盘、用户管理、工单管理、节点管理、系统管理,以及本轮新增的订阅管理。
|
||||
- 侧边栏承担一级信息架构,页面主体承担筛选、批量判断和单行操作,不把复杂流程全部堆进列表页;新增业务域优先用独立分组承载。
|
||||
- 节点管理属于“高密度运营页”:用户需要在一个视图里快速判断节点状态、倍率、权限组与在线人数,再决定是否继续深入编辑。
|
||||
- 套餐管理属于“结构化配置页”:用户需要在一页内完成套餐开关、价格、分组、说明和排序维护,强调表格与抽屉之间的稳定切换。
|
||||
|
||||
## 美学方向
|
||||
- 延续 `apple/DESIGN.md` 的 Apple 风格:纯色分区、系统字体、克制阴影、低噪音交互。
|
||||
- 管理后台不追求营销式华丽,而是强调“黑白主场 + 蓝色交互 + 轻薄容器”的精密运营感。
|
||||
- 新页面应与现有仪表盘 / 用户管理保持同一视觉家族,避免出现另一套后台皮肤。
|
||||
|
||||
## 设计 token
|
||||
- 背景与表面继续复用 `admin-frontend/src/styles/index.scss` 中的 `--xboard-*` 变量。
|
||||
- 主色固定为 `#0071e3`,仅用于激活态、主按钮、焦点和核心交互反馈。
|
||||
- 文本层级固定为:`--xboard-text-strong` 主标题、`--xboard-text-secondary` 正文、`--xboard-text-muted` 辅助信息。
|
||||
- 表格、筛选器、状态徽章允许新增页面级局部变量,但不得绕开全局 token 直接堆随机颜色。
|
||||
|
||||
## 布局策略
|
||||
- 一级导航仍采用左侧固定侧边栏,节点相关入口归入独立的“节点管理”分组,不混入“用户管理”分组。
|
||||
- 订阅相关入口归入独立的“订阅管理”分组;未实现的订单/优惠券/礼品卡入口允许先以禁用态占位。
|
||||
- 系统相关能力归入独立的“系统管理”分组;长表单型配置页采用“左侧分组导航 + 右侧连续 section”的后台编辑结构。
|
||||
- 页面头部保持“大标题 + 一句说明 + 右侧操作”的双栏结构,首屏先给运营者建立页面心智,再进入列表。
|
||||
- 列表上方先放一层紧凑筛选工具条:搜索框、类型筛选、权限组筛选、主操作按钮,避免二次折叠菜单。
|
||||
- 宽表格在桌面优先完整呈现;窄屏时允许信息折行,但不牺牲主列的可读性。
|
||||
- 订阅页面优先采用“黑色首屏 + 白色工作台 + 右侧抽屉”的结构,让套餐列表、价格矩阵和说明编辑形成清晰主次。
|
||||
|
||||
## 组件与模式
|
||||
- 侧边栏分组标题使用 `ElSubMenu`,子项必须与业务域一一对应。
|
||||
- 列表页优先使用原生 `ElTable` + Apple 化外观,不重新发明表格基础能力。
|
||||
- 配置页优先使用原生 `ElForm`、`ElInput`、`ElSwitch`、`ElSelect` 与 `ElInputNumber` 组合,不在后台长表单里引入花哨交互。
|
||||
- 状态使用“圆点 + 文本/徽章”双信号表达,避免仅靠颜色辨识在线/离线。
|
||||
- 危险操作收入口袋菜单,主列表行只露出最常用的显隐切换与查看信息。
|
||||
- 未进入本轮范围的功能允许放入占位页,但要明确标注“下一阶段接入”,不能伪装成可用功能。
|
||||
|
||||
## 状态覆盖
|
||||
- 加载态:列表区域显示骨架或表格 loading,不让整页空白。
|
||||
- 空状态:给出“当前筛选条件下暂无节点”与一键清空筛选入口。
|
||||
- 错误态:保留用户当前筛选条件,并允许重试,不把失败吞掉。
|
||||
- 成功态:显隐切换、复制节点、删除节点等操作使用明确 toast 反馈。
|
||||
- 禁用态:未实现或不可用的操作按钮必须有禁用样式和原因说明。
|
||||
|
||||
## 记忆点
|
||||
- 让用户记住“黑色首屏 + 运营表格 + 左侧节点分组”这一套安静但高辨识度的 Apple 化后台结构。
|
||||
|
||||
## 动效策略
|
||||
- 只保留必要动效:筛选 pill 激活、按钮 hover、表格操作反馈、占位页轻微过渡。
|
||||
- 禁止厚重的卡片飞入、长时间遮罩和无意义动画;尊重 `prefers-reduced-motion`。
|
||||
|
||||
## 无障碍要求
|
||||
- 所有按钮、开关、下拉菜单都保留可见焦点。
|
||||
- 表格操作必须支持键盘聚焦,危险动作要有明确文案。
|
||||
- 在线状态除颜色外还要搭配文字或点位说明。
|
||||
|
||||
## 内容语气
|
||||
- 标题直接、运营化,不写营销语。
|
||||
- 空状态和占位提示应明确告诉用户“现在能做什么 / 下一阶段会补什么”。
|
||||
- 操作按钮统一使用动词短语,如“添加节点”“编辑排序”“复制节点”“删除节点”。
|
||||
|
||||
## 禁止事项
|
||||
- 禁止回到紫色渐变、玻璃拟态大面积模糊、厚重卡片堆叠。
|
||||
- 禁止把节点列表页做成营销落地页式大色块拼贴。
|
||||
- 禁止使用 emoji、随机插画或与 Xboard 运营后台无关的装饰元素。
|
||||
|
||||
## 约束定义
|
||||
- 主页面同时出现的主操作按钮不超过 2 个。
|
||||
- 同一页面强调色不超过 1 个,语义色只用于状态。
|
||||
- 列表工具条最多一行半,超过则折叠到二级策略,不无限横向增长。
|
||||
|
||||
## 实现备注
|
||||
- 全局 token 继续落在 `admin-frontend/src/styles/index.scss`。
|
||||
- 节点页相关的格式化与映射逻辑优先放到 `admin-frontend/src/utils/nodes.ts`。
|
||||
- 节点管理分组路由位于 `admin-frontend/src/router/index.ts`,页面实现位于 `admin-frontend/src/views/nodes/`。
|
||||
@@ -0,0 +1,31 @@
|
||||
# Xboard-new 知识库
|
||||
|
||||
```yaml
|
||||
kb_version: 2
|
||||
project: Xboard-new
|
||||
updated_at: 2026-04-29
|
||||
active_package: 无
|
||||
```
|
||||
|
||||
## 项目概览
|
||||
|
||||
- 类型: PHP Laravel 主仓 + `admin-frontend` Vue3 管理端前端
|
||||
- 当前重点模块: `admin-frontend`、`deploy`、`node-gfw-check`、`node-traffic-limit`、`order-payment`、`queue-mail`、`subscription-protocols`、`user-frontend-access`
|
||||
- 最新归档: `202604291559_user-frontend-access-toggle`
|
||||
|
||||
## 活跃模块
|
||||
|
||||
- [admin-frontend](modules/admin-frontend.md): 管理端登录、主布局、仪表盘、用户/节点/订阅/系统管理与管理 API 前端封装
|
||||
- [ci-workflows](modules/ci-workflows.md): GitHub Actions 后端与管理端前端镜像发布工作流、路径触发边界和 GHCR 发布规则
|
||||
- [deploy](modules/deploy.md): 可复制到服务器的 Xboard Compose 部署模板、环境变量模板和运维脚本
|
||||
- [node-gfw-check](modules/node-gfw-check.md): 节点墙状态检测任务、父/子节点继承规则、mi-node 检测上报链路
|
||||
- [node-traffic-limit](modules/node-traffic-limit.md): 节点月流量限额配置、共享账期用量、重置调度、metrics 状态回写与 mi-node 强制下线协作
|
||||
- [order-payment](modules/order-payment.md): 订单支付成功快照、第三方回调元信息透传与后台支付成功信息展示
|
||||
- [queue-mail](modules/queue-mail.md): 邮件发送队列、SMTP 运行时配置、Horizon 超时与失败重试边界
|
||||
- [subscription-protocols](modules/subscription-protocols.md): 客户端订阅导出入口、协议适配器与版本兼容过滤
|
||||
- [user-frontend-access](modules/user-frontend-access.md): 用户前端首页访问开关与 API 保留边界
|
||||
|
||||
## 归档与变更
|
||||
|
||||
- 归档索引: [archive/_index.md](archive/_index.md)
|
||||
- 变更日志: [CHANGELOG.md](CHANGELOG.md)
|
||||
@@ -0,0 +1,10 @@
|
||||
{
|
||||
"status": "completed",
|
||||
"completed": 6,
|
||||
"failed": 0,
|
||||
"pending": 0,
|
||||
"total": 6,
|
||||
"percent": 100,
|
||||
"current": "completed",
|
||||
"updated_at": "2026-04-16 17:04:30"
|
||||
}
|
||||
@@ -0,0 +1,135 @@
|
||||
# 变更提案: merge-upstream-preserve-local
|
||||
|
||||
## 元信息
|
||||
```yaml
|
||||
类型: 优化
|
||||
方案类型: implementation
|
||||
优先级: P1
|
||||
状态: 已确认
|
||||
创建: 2026-04-16
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 1. 需求
|
||||
|
||||
### 背景
|
||||
当前工作分支位于 `master`,本地相对 `upstream/master` 领先 15 个提交、落后 47 个提交。
|
||||
用户要求在保留所有本地改动与本地功能优先级的前提下,将 `https://github.com/cedar2025/Xboard`
|
||||
的最新代码合并到当前分支。现场还存在未跟踪的 `.helloagents/` 目录,以及
|
||||
`public/assets/admin` 子模块指针与 `upstream/master` 不一致,需要在合并时避免误覆盖。
|
||||
|
||||
### 目标
|
||||
- 将 `upstream/master` 的最新提交合并到当前分支。
|
||||
- 保留当前分支已有提交与本地工作树内容,不做重置、不强推、不丢改动。
|
||||
- 当出现文本冲突时优先保留当前分支的实现。
|
||||
- 当出现子模块指针冲突时,显式保留当前分支所指向的子模块版本,并完成核对。
|
||||
|
||||
### 约束条件
|
||||
```yaml
|
||||
时间约束: 当前回合内完成保护、合并、冲突处理和结果核验
|
||||
性能约束: N/A
|
||||
兼容性约束: 不改变当前分支名称,不破坏已有 Git 历史,避免影响未跟踪的本地目录
|
||||
业务约束: 发生冲突时以用户本地功能优先;不使用 reset --hard 或覆盖式同步
|
||||
```
|
||||
|
||||
### 验收标准
|
||||
- [ ] 已成功抓取并合并 `upstream/master` 到当前分支,且本地 15 个领先提交仍保留在历史中
|
||||
- [ ] 工作树中的本地未跟踪内容未丢失,合并冲突已处理完毕
|
||||
- [ ] 若产生冲突,文本文件优先保留当前分支实现;`public/assets/admin` 子模块指针按当前分支版本保留并确认
|
||||
- [ ] 合并后完成基本核验,包括分叉变化、工作树状态、子模块状态与冲突标记清零
|
||||
|
||||
---
|
||||
|
||||
## 2. 方案
|
||||
|
||||
### 技术方案
|
||||
采用“保护现场 + 常规 merge + 冲突偏向当前分支 + 显式核对子模块”的方案:
|
||||
|
||||
1. 记录当前现场,包括分支、工作树、与 `upstream/master` 的分叉和子模块指针。
|
||||
2. 创建本地安全锚点(备份分支或标签),确保任何一步异常都可回到操作前状态。
|
||||
3. 视需要暂存未跟踪内容,避免合并期间被意外干扰。
|
||||
4. 执行 `git merge -X ours upstream/master`,让文本冲突默认偏向当前分支。
|
||||
5. 如出现子模块指针冲突,手工恢复为当前分支所引用的子模块提交,而不是盲目接受上游版本。
|
||||
6. 完成后检查 `git status`、分叉计数、merge commit、子模块状态和冲突残留,确认结果满足“本地优先”要求。
|
||||
|
||||
### 影响范围
|
||||
```yaml
|
||||
涉及模块:
|
||||
- Git 历史: 当前分支将新增一次来自 upstream/master 的合并结果
|
||||
- 根仓工作树: 可能因上游更新而变更多个跟踪文件
|
||||
- public/assets/admin: 子模块指针可能出现冲突,需要显式保留本地版本
|
||||
- .helloagents/plan: 新增本次操作的方案包与执行记录
|
||||
预计变更文件: 多文件,数量取决于 upstream/master 与当前分支差异
|
||||
```
|
||||
|
||||
### 风险评估
|
||||
| 风险 | 等级 | 应对 |
|
||||
|------|------|------|
|
||||
| `-X ours` 仅对文本冲突生效,无法自动正确处理子模块指针 | 高 | 合并后单独检查 `public/assets/admin`,必要时显式 checkout 当前分支的子模块提交 |
|
||||
| 未跟踪的 `.helloagents/` 内容在操作中被误干扰 | 中 | 先记录现场,必要时仅暂存未跟踪内容,不删除任何本地文件 |
|
||||
| 上游 47 个提交引入的结构变化与本地 15 个提交存在深度冲突 | 中 | 保留备份锚点,逐项处理冲突并在结果核验中确认本地功能仍存在 |
|
||||
| 误把 `origin/master` 当作基线导致合并方向错误 | 低 | 固定以 `upstream/master` 为唯一上游基线执行本次合并 |
|
||||
|
||||
---
|
||||
|
||||
## 3. 技术设计(可选)
|
||||
|
||||
> 本次为 Git 合并操作,无架构/API/数据模型设计变更。
|
||||
|
||||
### 架构设计
|
||||
N/A
|
||||
|
||||
### API设计
|
||||
N/A
|
||||
|
||||
### 数据模型
|
||||
N/A
|
||||
|
||||
---
|
||||
|
||||
## 4. 核心场景
|
||||
|
||||
> 本次为仓库合并操作,不涉及业务模块文档同步场景。
|
||||
|
||||
### 场景: 当前分支合并 upstream/master
|
||||
**模块**: Git 仓库 / 子模块
|
||||
**条件**: 当前分支存在本地领先提交,且用户要求本地实现优先
|
||||
**行为**: 拉取 upstream 最新提交并合并到当前分支,冲突时优先保留当前分支内容,子模块指针冲突显式保留当前指针
|
||||
**结果**: 当前分支吸收上游更新,同时保住本地提交和本地优先实现
|
||||
|
||||
---
|
||||
|
||||
## 5. 技术决策
|
||||
|
||||
> 本方案涉及的技术决策,归档后成为决策的唯一完整记录
|
||||
|
||||
### merge-upstream-preserve-local#D001: 采用 merge 而非 reset、rebase 或手工摘取提交
|
||||
**日期**: 2026-04-16
|
||||
**状态**: ✅采纳
|
||||
**背景**: 用户要求“保留所有本地更改”并把远端最新代码合并到当前项目,同时冲突时本地功能优先。需要选择一种既能保留历史又便于冲突处理的更新方式。
|
||||
**选项分析**:
|
||||
| 选项 | 优点 | 缺点 |
|
||||
|------|------|------|
|
||||
| A: `git merge -X ours upstream/master` | 保留分支历史,适合把上游更新并入当前分支,文本冲突可偏向本地实现 | 不能自动正确处理子模块指针,需要额外检查 |
|
||||
| B: `git rebase upstream/master` | 历史更线性 | 会重写当前分支提交,冲突重放次数可能更多,不符合“尽量保留现状” |
|
||||
| C: `git reset --hard upstream/master` 后再回放本地改动 | 操作简单 | 高风险,会直接破坏当前现场,不符合需求 |
|
||||
**决策**: 选择方案 A
|
||||
**理由**: 常规 merge 最符合“保留本地提交和现场”的要求,结合 `-X ours` 能让文本冲突尽量偏向当前分支;剩余的子模块冲突可控且可显式核验。
|
||||
**影响**: 影响当前分支历史、根仓工作树状态,以及 `public/assets/admin` 子模块指针处理方式
|
||||
|
||||
---
|
||||
|
||||
## 6. 成果设计
|
||||
|
||||
> 含视觉产出的任务由 DESIGN Phase2 填充。非视觉任务整节标注"N/A"。
|
||||
|
||||
### 设计方向
|
||||
- N/A
|
||||
|
||||
### 视觉要素
|
||||
- N/A
|
||||
|
||||
### 技术约束
|
||||
- **可访问性**: N/A
|
||||
- **响应式**: N/A
|
||||
@@ -0,0 +1,58 @@
|
||||
# 任务清单: merge-upstream-preserve-local
|
||||
|
||||
> **@status:** completed | 2026-04-16 17:00
|
||||
|
||||
```yaml
|
||||
@feature: merge-upstream-preserve-local
|
||||
@created: 2026-04-16
|
||||
@status: completed
|
||||
@mode: R2
|
||||
```
|
||||
|
||||
## 进度概览
|
||||
|
||||
| 完成 | 失败 | 跳过 | 总数 |
|
||||
|------|------|------|------|
|
||||
| 6 | 0 | 0 | 6 |
|
||||
|
||||
---
|
||||
|
||||
## 任务列表
|
||||
|
||||
### 1. 现场保护与基线确认
|
||||
|
||||
- [√] 1.1 记录当前分支、工作树、与 `upstream/master` 的分叉、子模块指针和未跟踪内容,作为操作前证据 | depends_on: []
|
||||
- [√] 1.2 创建可回退的本地安全锚点,确保合并异常时能恢复到操作前状态 | depends_on: [1.1]
|
||||
|
||||
### 2. 执行合并并处理冲突
|
||||
|
||||
- [√] 2.1 在不丢失本地内容的前提下执行 `upstream/master` 合并到当前分支,并让文本冲突优先保留当前分支实现 | depends_on: [1.2]
|
||||
- [√] 2.2 若发生子模块或特殊冲突,显式保留当前分支的 `public/assets/admin` 指针与本地优先实现 | depends_on: [2.1]
|
||||
|
||||
### 3. 结果核验与交付
|
||||
|
||||
- [√] 3.1 核验合并结果,包括冲突清零、分叉变化、merge commit、子模块状态和工作树状态 | depends_on: [2.2]
|
||||
- [√] 3.2 输出本次操作结果、残留风险和必要的后续建议 | depends_on: [3.1]
|
||||
|
||||
---
|
||||
|
||||
## 执行日志
|
||||
|
||||
| 时间 | 任务 | 状态 | 备注 |
|
||||
|------|------|------|------|
|
||||
| 2026-04-16 16:55:00 | 方案包创建 | completed | 已创建 `202604161655_merge-upstream-preserve-local` |
|
||||
| 2026-04-16 17:01:00 | 1.1 | completed | 已记录当前分支、分叉 `47/15`、未跟踪方案包文件与子模块指针 `c5d9835` |
|
||||
| 2026-04-16 17:01:30 | 1.2 | completed | 已创建安全锚点分支 `backup/pre-upstream-merge-20260416-1701` |
|
||||
| 2026-04-16 17:03:30 | 2.1 | completed | 已执行 `git merge -X ours --no-edit upstream/master` 并生成 merge commit `abd64ed` |
|
||||
| 2026-04-16 17:04:00 | 2.2 | completed | 已保留 `app/Services/UserOnlineService.php` 与子模块指针 `public/assets/admin@c5d9835` 的当前分支版本 |
|
||||
| 2026-04-16 17:04:30 | 3.1/3.2 | completed | 已确认相对 `upstream/master` 为 `0/16`,工作树仅剩未跟踪的方案包文件 |
|
||||
|
||||
---
|
||||
|
||||
## 执行备注
|
||||
|
||||
> 记录执行过程中的重要说明、决策变更、风险提示等
|
||||
|
||||
- 当前基线远端已确认使用 `upstream/master`
|
||||
- 已识别 `public/assets/admin` 子模块指针与 `upstream/master` 不一致,需在合并时单独核验
|
||||
- `git diff --check --cached` 报告多处尾随空格,来源于合并后的暂存内容,未作为本次阻断项处理
|
||||
+10
@@ -0,0 +1,10 @@
|
||||
{
|
||||
"status": "completed",
|
||||
"completed": 5,
|
||||
"failed": 0,
|
||||
"pending": 0,
|
||||
"total": 5,
|
||||
"percent": 100,
|
||||
"current": "completed",
|
||||
"updated_at": "2026-04-16 17:08:30"
|
||||
}
|
||||
+128
@@ -0,0 +1,128 @@
|
||||
# 变更提案: create-git-merge-preserve-local-skill
|
||||
|
||||
## 元信息
|
||||
```yaml
|
||||
类型: 新功能
|
||||
方案类型: implementation
|
||||
优先级: P1
|
||||
状态: 已确认
|
||||
创建: 2026-04-16
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 1. 需求
|
||||
|
||||
### 背景
|
||||
本次已在 `Xboard-new` 仓库中完成一次“以 `upstream/master` 为基线、保留本地改动优先”的真实合并。
|
||||
这类需求在多仓协作中出现频率高,且容易踩到 dirty worktree、`modify/delete` 冲突、子模块 gitlink
|
||||
冲突、错误远端基线等问题,适合沉淀成一个可复用 skill。
|
||||
|
||||
### 目标
|
||||
- 在全局技能目录创建一个可自动发现的 skill。
|
||||
- 让 skill 能指导 Codex 安全地把远端最新代码合并到当前分支,同时尽量保住本地改动并在冲突时偏向本地实现。
|
||||
- 覆盖常见高风险场景,包括未提交改动、`modify/delete` 冲突、子模块冲突和合并后核验。
|
||||
|
||||
### 约束条件
|
||||
```yaml
|
||||
时间约束: 当前回合内完成创建、校验和可用性说明
|
||||
性能约束: N/A
|
||||
兼容性约束: skill 需放在 C:/Users/xiaohuli/.codex/skills 下以便全局自动发现
|
||||
业务约束: 说明必须体现“保本地优先”语义,避免把 merge 写成 rebase/reset/强推流程
|
||||
```
|
||||
|
||||
### 验收标准
|
||||
- [ ] `C:/Users/xiaohuli/.codex/skills/git-merge-preserve-local/` 下存在完整 skill 目录
|
||||
- [ ] `SKILL.md` 明确描述触发场景、工作流和关键风险点
|
||||
- [ ] 至少有一份参考文档沉淀具体命令模板与冲突处理要点
|
||||
- [ ] skill 通过 `quick_validate.py` 校验
|
||||
|
||||
---
|
||||
|
||||
## 2. 方案
|
||||
|
||||
### 技术方案
|
||||
创建一个轻量级 workflow skill:
|
||||
|
||||
1. 用 `init_skill.py` 在全局技能目录初始化 `git-merge-preserve-local`。
|
||||
2. 将核心触发条件和执行骨架写入 `SKILL.md`,保持内容精炼。
|
||||
3. 将具体命令模板、冲突配方和核验清单下沉到 `references/merge-playbook.md`。
|
||||
4. 用 `generate_openai_yaml.py` 生成 `agents/openai.yaml`,补齐 UI 元数据。
|
||||
5. 运行 `quick_validate.py` 做结构校验。
|
||||
|
||||
### 影响范围
|
||||
```yaml
|
||||
涉及模块:
|
||||
- 全局 Codex skills: 新增 git-merge-preserve-local skill
|
||||
- 当前仓库 .helloagents: 新增本次方案包与执行记录
|
||||
预计变更文件: 4-6
|
||||
```
|
||||
|
||||
### 风险评估
|
||||
| 风险 | 等级 | 应对 |
|
||||
|------|------|------|
|
||||
| 说明过长、触发词不清,导致 skill 不易命中或上下文成本过高 | 中 | 将流程骨架留在 `SKILL.md`,把命令细节下沉到 references |
|
||||
| 将“保本地优先”误写成 `reset`、`rebase` 或 `push --force` | 高 | 明确写出推荐 merge 路径与禁用路径 |
|
||||
| 忽略子模块 gitlink 冲突,导致 skill 在真实仓库里误导操作 | 高 | 单独增加子模块冲突章节和验证清单 |
|
||||
|
||||
---
|
||||
|
||||
## 3. 技术设计(可选)
|
||||
|
||||
> 本次为全局 skill 创建,不涉及业务系统架构/API/数据模型设计。
|
||||
|
||||
### 架构设计
|
||||
N/A
|
||||
|
||||
### API设计
|
||||
N/A
|
||||
|
||||
### 数据模型
|
||||
N/A
|
||||
|
||||
---
|
||||
|
||||
## 4. 核心场景
|
||||
|
||||
> 该 skill 面向 Git 合并流程复用,不同步项目业务模块文档。
|
||||
|
||||
### 场景: 将上游最新代码合并到当前分支且保留本地优先
|
||||
**模块**: 全局技能 / Git 工作流
|
||||
**条件**: 用户要求同步远端最新代码,但不希望丢失本地改动,且冲突时偏向本地实现
|
||||
**行为**: 先识别真实上游基线、保护现场,再执行 merge、处理冲突并核验
|
||||
**结果**: 能在真实仓库中复用一套较稳健的“保本地优先合并”操作流程
|
||||
|
||||
---
|
||||
|
||||
## 5. 技术决策
|
||||
|
||||
> 本方案涉及的技术决策,归档后成为决策的唯一完整记录
|
||||
|
||||
### create-git-merge-preserve-local-skill#D001: 采用“SKILL.md + references”而非附带脚本自动执行 merge
|
||||
**日期**: 2026-04-16
|
||||
**状态**: ✅采纳
|
||||
**背景**: 这类 Git 合并任务高度依赖现场状态,直接自动执行脚本容易因远端、分支、dirty worktree、子模块结构差异而误伤仓库。
|
||||
**选项分析**:
|
||||
| 选项 | 优点 | 缺点 |
|
||||
|------|------|------|
|
||||
| A: `SKILL.md + references` | 复用性高,允许结合现场状态判断,适合不同仓库差异 | 不是一键脚本,需要代理自己执行命令 |
|
||||
| B: 直接附自动 merge 脚本 | 执行更快 | 风险高,容易在错误远端/错误分支/脏工作树下误操作 |
|
||||
**决策**: 选择方案 A
|
||||
**理由**: 该问题的关键不是缺少命令,而是缺少“什么时候用什么命令”的判断框架;skill 更适合作为操作协议而不是盲目自动化脚本。
|
||||
**影响**: skill 主要由说明文档构成,强调流程判断、冲突配方和验证步骤
|
||||
|
||||
---
|
||||
|
||||
## 6. 成果设计
|
||||
|
||||
> 含视觉产出的任务由 DESIGN Phase2 填充。非视觉任务整节标注"N/A"。
|
||||
|
||||
### 设计方向
|
||||
- N/A
|
||||
|
||||
### 视觉要素
|
||||
- N/A
|
||||
|
||||
### 技术约束
|
||||
- **可访问性**: N/A
|
||||
- **响应式**: N/A
|
||||
+57
@@ -0,0 +1,57 @@
|
||||
# 任务清单: create-git-merge-preserve-local-skill
|
||||
|
||||
> **@status:** completed | 2026-04-16 17:09
|
||||
|
||||
```yaml
|
||||
@feature: create-git-merge-preserve-local-skill
|
||||
@created: 2026-04-16
|
||||
@status: completed
|
||||
@mode: R2
|
||||
```
|
||||
|
||||
## 进度概览
|
||||
|
||||
| 完成 | 失败 | 跳过 | 总数 |
|
||||
|------|------|------|------|
|
||||
| 5 | 0 | 0 | 5 |
|
||||
|
||||
---
|
||||
|
||||
## 任务列表
|
||||
|
||||
### 1. 方案与骨架
|
||||
|
||||
- [√] 1.1 初始化全局 skill 目录与基础骨架,确认目标路径和资源结构 | depends_on: []
|
||||
- [√] 1.2 编写 skill 的触发描述、主流程和风险约束 | depends_on: [1.1]
|
||||
|
||||
### 2. 参考资料与元数据
|
||||
|
||||
- [√] 2.1 编写 references 中的命令模板、冲突配方和核验清单 | depends_on: [1.2]
|
||||
- [√] 2.2 生成或补齐 `agents/openai.yaml` 元数据 | depends_on: [2.1]
|
||||
|
||||
### 3. 校验与交付
|
||||
|
||||
- [√] 3.1 运行 skill 校验并修复结构问题 | depends_on: [2.2]
|
||||
|
||||
---
|
||||
|
||||
## 执行日志
|
||||
|
||||
| 时间 | 任务 | 状态 | 备注 |
|
||||
|------|------|------|------|
|
||||
| 2026-04-16 17:03:00 | 方案包创建 | completed | 已创建 `202604161703_create-git-merge-preserve-local-skill` |
|
||||
| 2026-04-16 17:04:00 | 1.1 | completed | 已初始化 `C:/Users/xiaohuli/.codex/skills/git-merge-preserve-local`,并创建 `SKILL.md` |
|
||||
| 2026-04-16 17:07:00 | 1.2/2.1 | completed | 已写入主流程与 `references/merge-playbook.md` |
|
||||
| 2026-04-16 17:08:00 | 2.2 | completed | 已补齐 `agents/openai.yaml` |
|
||||
| 2026-04-16 17:08:30 | 3.1 | completed | `generate_openai_yaml.py` 与 `quick_validate.py` 因缺少 `yaml` 依赖失败,已改用手工结构校验并通过 |
|
||||
|
||||
---
|
||||
|
||||
## 执行备注
|
||||
|
||||
> 记录执行过程中的重要说明、决策变更、风险提示等
|
||||
|
||||
- 目标目录已确认使用 `C:/Users/xiaohuli/.codex/skills`
|
||||
- 计划创建 skill 名称为 `git-merge-preserve-local`
|
||||
- `agents/openai.yaml` 在首次初始化时因 `short_description` 超长未生成,后续已手工补齐
|
||||
- 本机 Python 环境缺少 `PyYAML`,因此未使用 `generate_openai_yaml.py` / `quick_validate.py` 完成最终步骤
|
||||
@@ -0,0 +1,10 @@
|
||||
{
|
||||
"status": "completed",
|
||||
"completed": 4,
|
||||
"failed": 0,
|
||||
"pending": 0,
|
||||
"total": 4,
|
||||
"percent": 100,
|
||||
"current": "completed",
|
||||
"updated_at": "2026-04-18 00:33:30"
|
||||
}
|
||||
@@ -0,0 +1,127 @@
|
||||
# 变更提案: fix-clashmeta-flow-map-export
|
||||
|
||||
## 元信息
|
||||
```yaml
|
||||
类型: 修复
|
||||
方案类型: implementation
|
||||
优先级: P1
|
||||
状态: 已确认
|
||||
创建: 2026-04-18
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 1. 需求
|
||||
|
||||
### 背景
|
||||
当前 Clash Meta 订阅模板本身是合法的 block style YAML,但服务端在导出订阅时会重新执行
|
||||
`Yaml::dump(...)`。由于 `inline` 深度设置过低,深层节点对象会被压成单行 flow map,
|
||||
例如 TUIC 节点被输出为 `{ name: ..., alpn: [h3, h2, http/1.1], ... }`。
|
||||
|
||||
在部分 Clash Meta 客户端中,这种超长单行 flow map 会触发:
|
||||
|
||||
`Flow map in block collection must be sufficiently indented and end with a }`
|
||||
|
||||
### 目标
|
||||
- 修复 Clash Meta 订阅导出,避免代理节点被压成易出错的单行 flow map。
|
||||
- 保持改动最小,仅影响 `ClashMeta` 导出链路。
|
||||
- 不改动模板文件和其他协议导出器。
|
||||
|
||||
### 约束条件
|
||||
```yaml
|
||||
时间约束: 当前回合内完成修复与静态验证
|
||||
性能约束: 不引入额外运行时依赖
|
||||
兼容性约束: 不改动节点字段语义,仅调整 YAML 序列化风格
|
||||
业务约束: 仅修复 Clash Meta;Clash / Stash 暂不联动修改
|
||||
```
|
||||
|
||||
### 验收标准
|
||||
- [ ] `app/Protocols/ClashMeta.php` 中 YAML 导出策略已调整,深层对象优先输出为 block style
|
||||
- [ ] 不再依赖单行 flow map 来表示 `proxies` 中的 TUIC 等节点对象
|
||||
- [ ] 改动范围限制在 `ClashMeta` 导出逻辑与方案包记录
|
||||
- [ ] 完成最小静态验证并明确运行验证受限原因
|
||||
|
||||
---
|
||||
|
||||
## 2. 方案
|
||||
|
||||
### 技术方案
|
||||
将 `ClashMeta` 中依赖 `Yaml::dump(...)` 的默认风格选择,替换为显式的 block style YAML 渲染,
|
||||
避免 `proxies`、`proxy-groups` 等深层结构被压缩成单行 flow map。
|
||||
|
||||
本次仅修改:
|
||||
|
||||
1. `app/Protocols/ClashMeta.php` 的 YAML 渲染路径;
|
||||
2. 在代码旁增加一行说明性注释,明确修复目的;
|
||||
3. 不改模板、不改节点字段构造、不改 Clash / Stash。
|
||||
|
||||
### 影响范围
|
||||
```yaml
|
||||
涉及模块:
|
||||
- ClashMeta 订阅导出: YAML 序列化风格调整
|
||||
- .helloagents 方案包: 记录本次修复过程
|
||||
预计变更文件: 2-4
|
||||
```
|
||||
|
||||
### 风险评估
|
||||
| 风险 | 等级 | 应对 |
|
||||
|------|------|------|
|
||||
| 导出 YAML 变得更“展开”,文件体积略增 | 低 | 只调整序列化风格,不改字段内容 |
|
||||
| 同类问题在 `Clash` / `Stash` 中也存在,但本次未修 | 中 | 范围明确限制为 Clash Meta,后续可按需补修 |
|
||||
| 本机无 PHP / vendor,无法直接做运行时生成验证 | 中 | 通过代码路径与参数语义做静态验证,并在结论中说明限制 |
|
||||
|
||||
---
|
||||
|
||||
## 3. 技术设计(可选)
|
||||
|
||||
> 本次为序列化参数修复,不涉及架构/API/数据模型设计。
|
||||
|
||||
### 架构设计
|
||||
N/A
|
||||
|
||||
### API设计
|
||||
N/A
|
||||
|
||||
### 数据模型
|
||||
N/A
|
||||
|
||||
---
|
||||
|
||||
## 4. 核心场景
|
||||
|
||||
### 场景: 导出含长 TUIC 节点的 Clash Meta 订阅
|
||||
**模块**: Clash Meta 订阅导出
|
||||
**条件**: 用户订阅中包含较长节点名、`alpn` 数组、`udp-relay-mode` 等字段
|
||||
**行为**: 服务端生成 YAML 订阅文本
|
||||
**结果**: 节点对象以 block style 输出,避免客户端在解析长单行 flow map 时失败
|
||||
|
||||
---
|
||||
|
||||
## 5. 技术决策
|
||||
|
||||
### fix-clashmeta-flow-map-export#D001: 显式渲染 block style YAML,不再依赖 dumper 的默认风格选择
|
||||
**日期**: 2026-04-18
|
||||
**状态**: ✅采纳
|
||||
**背景**: 问题的根源在序列化风格,而不是 TUIC 节点字段本身的构造。仅修改 `Yaml::dump` 参数后,服务器真值仍然返回单行 flow map。
|
||||
**选项分析**:
|
||||
| 选项 | 优点 | 缺点 |
|
||||
|------|------|------|
|
||||
| A: 继续微调 `Yaml::dump` 参数 | 改动小 | 已被服务器真值否定,不能保证摆脱 flow map |
|
||||
| B: 显式输出 block style YAML | 可完全控制 `proxies` / `proxy-groups` / `rules` 的格式 | 代码量更大,需要自定义渲染 |
|
||||
**决策**: 选择方案 B
|
||||
**理由**: 服务器真值已经证明仅调参数不够,必须显式控制 YAML 输出风格,才能彻底避免客户端继续收到 `- { ... }`。
|
||||
**影响**: 仅影响 Clash Meta 订阅的最终文本格式,不影响节点字段语义
|
||||
|
||||
---
|
||||
|
||||
## 6. 成果设计
|
||||
|
||||
### 设计方向
|
||||
- N/A
|
||||
|
||||
### 视觉要素
|
||||
- N/A
|
||||
|
||||
### 技术约束
|
||||
- **可访问性**: N/A
|
||||
- **响应式**: N/A
|
||||
@@ -0,0 +1,52 @@
|
||||
# 任务清单: fix-clashmeta-flow-map-export
|
||||
|
||||
> **@status:** completed | 2026-04-18 00:30
|
||||
|
||||
```yaml
|
||||
@feature: fix-clashmeta-flow-map-export
|
||||
@created: 2026-04-18
|
||||
@status: completed
|
||||
@mode: R2
|
||||
```
|
||||
|
||||
## 进度概览
|
||||
|
||||
| 完成 | 失败 | 跳过 | 总数 |
|
||||
|------|------|------|------|
|
||||
| 4 | 0 | 0 | 4 |
|
||||
|
||||
---
|
||||
|
||||
## 任务列表
|
||||
|
||||
### 1. 问题定位与修复
|
||||
|
||||
- [√] 1.1 确认报错来自 Clash Meta 导出后的单行 flow map,而不是原始模板语法 | depends_on: []
|
||||
- [√] 1.2 调整 `ClashMeta` 的 YAML dump 参数,避免深层代理对象被压成单行 flow map | depends_on: [1.1]
|
||||
|
||||
### 2. 验证与交付
|
||||
|
||||
- [√] 2.1 对修复做最小验证,确认改动路径和影响范围 | depends_on: [1.2]
|
||||
- [√] 2.2 总结修复结果、残留风险和后续建议 | depends_on: [2.1]
|
||||
|
||||
---
|
||||
|
||||
## 执行日志
|
||||
|
||||
| 时间 | 任务 | 状态 | 备注 |
|
||||
|------|------|------|------|
|
||||
| 2026-04-18 00:29:00 | 方案包创建 | completed | 已创建 `202604180029_fix-clashmeta-flow-map-export` |
|
||||
| 2026-04-18 00:31:00 | 1.1 | completed | 已确认问题点在 `ClashMeta.php` 的 `Yaml::dump(..., 2, 4, ...)` |
|
||||
| 2026-04-18 00:32:00 | 1.2 | completed | 初始尝试已将 `ClashMeta` dump inline 深度提升到 `10` |
|
||||
| 2026-04-18 00:33:00 | 2.1 | completed | 服务器真值显示 `?flag=meta` 仍返回 `- { ... }`,确认仅调参数无效 |
|
||||
| 2026-04-18 00:33:30 | 2.2 | completed | 已切换为显式 block style YAML 渲染方案,并保留运行验证受限说明 |
|
||||
|
||||
---
|
||||
|
||||
## 执行备注
|
||||
|
||||
> 记录执行过程中的重要说明、决策变更、风险提示等
|
||||
|
||||
- 本次只修 `ClashMeta`,未联动 `Clash` / `Stash`
|
||||
- 本机缺少 `php` 与 `vendor`,无法在当前工作区执行运行时订阅生成验证
|
||||
- 当前 diff 还包含换行符提示:Git 显示该文件后续可能按工作树策略从 LF 触碰为 CRLF
|
||||
+10
@@ -0,0 +1,10 @@
|
||||
{
|
||||
"status": "completed",
|
||||
"completed": 4,
|
||||
"failed": 0,
|
||||
"pending": 0,
|
||||
"total": 4,
|
||||
"percent": 100,
|
||||
"current": "completed",
|
||||
"updated_at": "2026-04-18 00:45:30"
|
||||
}
|
||||
+129
@@ -0,0 +1,129 @@
|
||||
# 变更提案: optimize-docker-publish-workflow
|
||||
|
||||
## 元信息
|
||||
```yaml
|
||||
类型: 优化
|
||||
方案类型: implementation
|
||||
优先级: P1
|
||||
状态: 已确认
|
||||
创建: 2026-04-18
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 1. 需求
|
||||
|
||||
### 背景
|
||||
当前 `.github/workflows/docker-publish.yml` 在每次 push 到 `master` / `new-dev` 时都会执行双架构镜像构建并推送。
|
||||
现有流程存在几个明显的性能与正确性问题:
|
||||
|
||||
- Dockerfile 在构建过程中重新 `git clone` 仓库和子模块,绕过了 Actions 已 checkout 的工作区。
|
||||
- workflow 通过 `CACHEBUST=${{ github.sha }}` 强制让源码层每次失去缓存,以确保 `git clone` 拉到新代码,但这也让缓存收益极低。
|
||||
- workflow 中“Get version”在“Extract metadata”之后,`steps.get_version.outputs.version` 的引用顺序不正确。
|
||||
- `build-push-action` 同时声明了 `push: true` 和 `outputs: type=registry,push=true`,存在冗余。
|
||||
- QEMU 配置包含 `amd64`,但原生 `ubuntu-latest` 已能直接构建 `amd64`。
|
||||
|
||||
### 目标
|
||||
- 在不改变现有分支触发与双架构产物策略的前提下,缩短 Docker 发布耗时。
|
||||
- 保持 `master` / `new-dev` 的镜像输出逻辑不变。
|
||||
- 修正 workflow 中的明显顺序与冗余配置问题。
|
||||
|
||||
### 约束条件
|
||||
```yaml
|
||||
时间约束: 当前回合内完成方案、实现和基本验证
|
||||
性能约束: 优先优化热路径,不引入新的外部依赖
|
||||
兼容性约束: 保持 master/new-dev 双架构发布行为不变
|
||||
业务约束: 不通过减少镜像产物种类来换速度
|
||||
```
|
||||
|
||||
### 验收标准
|
||||
- [ ] `docker-publish.yml` 保持 `master` / `new-dev` 触发和双架构推送
|
||||
- [ ] Dockerfile 改为使用 GitHub Actions 工作区源码,而不是在构建阶段重新 `git clone`
|
||||
- [ ] workflow 去除明显冗余和错误顺序配置
|
||||
- [ ] `.dockerignore` 收紧不必要上下文,减少上传到 BuildKit 的内容
|
||||
|
||||
---
|
||||
|
||||
## 2. 方案
|
||||
|
||||
### 技术方案
|
||||
采用“保留产物策略不变、优化构建输入与缓存路径”的方案:
|
||||
|
||||
1. `actions/checkout` 增加 `submodules: recursive`,让 CI 工作区直接具备完整源码与子模块。
|
||||
2. 修改 Dockerfile,删除构建期 `git clone` / `git submodule update` 逻辑,改为直接 `COPY` 工作区源码。
|
||||
3. 删除 workflow 中为配合构建期 `git clone` 而存在的 `CACHEBUST` build arg。
|
||||
4. 修正 metadata/version 步骤顺序,移除无效的“Update version in app.php”和冗余 `outputs` 配置。
|
||||
5. 收紧 `.dockerignore`,排除 `.git`、`.github`、`.helloagents` 等不会进入运行时镜像的目录。
|
||||
6. 保留双架构构建,但只在 QEMU 中声明需要模拟的 `arm64`。
|
||||
|
||||
### 影响范围
|
||||
```yaml
|
||||
涉及模块:
|
||||
- .github/workflows/docker-publish.yml: 发布编排与构建参数
|
||||
- Dockerfile: 镜像构建输入与缓存路径
|
||||
- .dockerignore: 构建上下文裁剪
|
||||
预计变更文件: 3
|
||||
```
|
||||
|
||||
### 风险评估
|
||||
| 风险 | 等级 | 应对 |
|
||||
|------|------|------|
|
||||
| 直接使用工作区源码后,若 checkout 未带子模块,构建会缺少 admin dist | 中 | 在 checkout 中显式启用 `submodules: recursive` |
|
||||
| `.dockerignore` 排除过多文件导致运行时缺资源 | 中 | 只排除明显不应进入镜像的 Git/CI/本地知识库目录 |
|
||||
| 删除构建期 `git clone` 后,版本号注入逻辑与现有预期不一致 | 低 | 移除当前本就不会进镜像的版本更新步骤,避免继续保留伪生效逻辑 |
|
||||
|
||||
---
|
||||
|
||||
## 3. 技术设计(可选)
|
||||
|
||||
> 本次为 CI 与构建链优化,不涉及业务 API 或数据模型设计。
|
||||
|
||||
### 架构设计
|
||||
N/A
|
||||
|
||||
### API设计
|
||||
N/A
|
||||
|
||||
### 数据模型
|
||||
N/A
|
||||
|
||||
---
|
||||
|
||||
## 4. 核心场景
|
||||
|
||||
### 场景: push 到发布分支时执行镜像发布
|
||||
**模块**: GitHub Actions / Docker Buildx
|
||||
**条件**: 开发者 push 到 `master` 或 `new-dev`
|
||||
**行为**: checkout 完整源码与子模块,直接用工作区作为 Docker 构建输入,利用 GHA 缓存构建并推送双架构镜像
|
||||
**结果**: 在不减少镜像产物的前提下减少无谓的源码重拉取、上下文与步骤浪费
|
||||
|
||||
---
|
||||
|
||||
## 5. 技术决策
|
||||
|
||||
### optimize-docker-publish-workflow#D001: 改为基于工作区源码构建镜像
|
||||
**日期**: 2026-04-18
|
||||
**状态**: ✅采纳
|
||||
**背景**: 当前 Dockerfile 构建期重新 `git clone`,导致必须用 `CACHEBUST` 强制刷新源码层,缓存收益差且 workflow 内对工作区做的修改无法进入镜像。
|
||||
**选项分析**:
|
||||
| 选项 | 优点 | 缺点 |
|
||||
|------|------|------|
|
||||
| A: 保持构建期 `git clone`,仅修修 workflow 小问题 | 改动小 | 无法根治缓存失效与无效步骤问题 |
|
||||
| B: 直接基于 Actions 工作区 `COPY` 构建 | 能复用 checkout 结果,减少源码重复获取,缓存路径更合理 | 需要同步处理子模块与构建上下文 |
|
||||
**决策**: 选择方案 B
|
||||
**理由**: 这是在不改变发布产物策略的前提下,收益最大且风险可控的提速路径。
|
||||
**影响**: workflow checkout 配置、Dockerfile 源码输入方式、`.dockerignore` 内容
|
||||
|
||||
---
|
||||
|
||||
## 6. 成果设计
|
||||
|
||||
### 设计方向
|
||||
- N/A
|
||||
|
||||
### 视觉要素
|
||||
- N/A
|
||||
|
||||
### 技术约束
|
||||
- **可访问性**: N/A
|
||||
- **响应式**: N/A
|
||||
@@ -0,0 +1,52 @@
|
||||
# 任务清单: optimize-docker-publish-workflow
|
||||
|
||||
> **@status:** completed | 2026-04-18 00:44
|
||||
|
||||
```yaml
|
||||
@feature: optimize-docker-publish-workflow
|
||||
@created: 2026-04-18
|
||||
@status: completed
|
||||
@mode: R2
|
||||
```
|
||||
|
||||
## 进度概览
|
||||
|
||||
| 完成 | 失败 | 跳过 | 总数 |
|
||||
|------|------|------|------|
|
||||
| 4 | 0 | 0 | 4 |
|
||||
|
||||
---
|
||||
|
||||
## 任务列表
|
||||
|
||||
### 1. 方案与上下文
|
||||
|
||||
- [√] 1.1 确认当前 workflow 和 Dockerfile 的主要耗时点与失效缓存路径 | depends_on: []
|
||||
|
||||
### 2. 工作流与构建链优化
|
||||
|
||||
- [√] 2.1 优化 `.github/workflows/docker-publish.yml` 的步骤顺序、checkout 配置和冗余项 | depends_on: [1.1]
|
||||
- [√] 2.2 优化 `Dockerfile` 以直接消费 CI 工作区源码并删除构建期重复拉仓逻辑 | depends_on: [2.1]
|
||||
- [√] 2.3 收紧 `.dockerignore`,减少不必要构建上下文 | depends_on: [2.2]
|
||||
|
||||
---
|
||||
|
||||
## 执行日志
|
||||
|
||||
| 时间 | 任务 | 状态 | 备注 |
|
||||
|------|------|------|------|
|
||||
| 2026-04-18 00:40:00 | 方案包创建 | completed | 已创建 `202604180040_optimize-docker-publish-workflow` |
|
||||
| 2026-04-18 00:42:00 | 1.1 | completed | 已确认主要瓶颈是构建期重复 `git clone`、`CACHEBUST` 强制失效缓存与 workflow 冗余步骤 |
|
||||
| 2026-04-18 00:44:00 | 2.1 | completed | 已优化 checkout、QEMU、metadata/version 顺序、缓存 scope 与冗余输出配置 |
|
||||
| 2026-04-18 00:45:00 | 2.2 | completed | 已移除 Dockerfile 中构建期 `git clone`/`git submodule update`,改为直接 `COPY` 工作区源码 |
|
||||
| 2026-04-18 00:45:30 | 2.3 | completed | 已在 `.dockerignore` 中排除 `.git`、`.github`、`.helloagents` 上下文 |
|
||||
|
||||
---
|
||||
|
||||
## 执行备注
|
||||
|
||||
> 记录执行过程中的重要说明、决策变更、风险提示等
|
||||
|
||||
- 目标是“低风险提速”,不调整双架构产物策略
|
||||
- 当前仓库不存在 `composer.lock`,本次不围绕 lockfile 进行优化
|
||||
- 未执行真实多架构镜像构建,仅完成文本级自检与配置核对
|
||||
+11
@@ -0,0 +1,11 @@
|
||||
{
|
||||
"status": "completed",
|
||||
"completed": 7,
|
||||
"failed": 0,
|
||||
"pending": 0,
|
||||
"total": 7,
|
||||
"done": 7,
|
||||
"percent": 100,
|
||||
"current": "开发实施完成,待归档",
|
||||
"updated_at": "2026-04-21 03:42:00"
|
||||
}
|
||||
+207
@@ -0,0 +1,207 @@
|
||||
# 变更提案: admin-frontend-composio-dashboard
|
||||
|
||||
## 元信息
|
||||
```yaml
|
||||
类型: 新功能 + 重构
|
||||
方案类型: implementation
|
||||
优先级: P1
|
||||
状态: 已完成
|
||||
创建: 2026-04-21
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 1. 需求
|
||||
|
||||
### 背景
|
||||
当前 `admin-frontend` 已完成基础登录、认证存储、路由守卫和一个占位版 `DashboardView`,但登录成功后的跳转仅固定到 `/dashboard`,无法保留原始访问意图;仪表盘也尚未接入管理端真实统计接口,无法承载后台运营视图。用户已明确要求继续沿 `.claude/plan/admin-frontend-login.md` 推进,并将视觉方向切换为深色 Composio 风格,同时保持参考图中的核心功能结构。
|
||||
|
||||
### 目标
|
||||
- 在不改后端 API 的前提下,实现登录成功后的可靠跳转,支持受保护路由回跳。
|
||||
- 基于现有管理端接口实现真实数据仪表盘,包括核心统计卡片、收入趋势、节点/用户流量排行、队列与系统状态。
|
||||
- 将后台主视觉统一到深色 Composio 风格,形成可继续扩展的管理端首页基线。
|
||||
|
||||
### 约束条件
|
||||
```yaml
|
||||
时间约束: 本轮在现有 admin-frontend 基础上增量完成,不扩展到更多后台业务页面
|
||||
性能约束: 仪表盘首版避免引入重型图表依赖,尽量复用现有 Vue3 + Element Plus 栈
|
||||
兼容性约束: 保持 Hash 路由、window.settings.secure_path 运行时配置、现有登录鉴权方式
|
||||
业务约束: 仅复用后端现有接口,不新增 Laravel Controller/Route,不改变 secure_path 自举逻辑
|
||||
```
|
||||
|
||||
### 验收标准
|
||||
- [ ] 未登录访问受保护页面时可带 `redirect` 回到目标页,登录成功后正确跳转。
|
||||
- [ ] 仪表盘成功调用 `stat/getStats`、`stat/getOrder`、`stat/getTrafficRank`、`system/getSystemStatus`、`system/getQueueStats` 并显示真实数据。
|
||||
- [ ] 首页包含深色 Composio 风格的统计卡片、收入趋势、节点排行、用户排行、队列/系统状态区块,并支持桌面与移动端。
|
||||
- [ ] `admin-frontend` 可以通过 `npm run build`。
|
||||
|
||||
---
|
||||
|
||||
## 2. 方案
|
||||
|
||||
### 技术方案
|
||||
在 `admin-frontend` 内完成三层增量改造:
|
||||
|
||||
1. 数据层
|
||||
扩展 `src/types/api.d.ts` 和 `src/api/admin.ts`,为管理端仪表盘建立明确的统计、趋势、排行、系统状态类型与请求封装。
|
||||
|
||||
2. 认证与导航层
|
||||
调整 `src/router/guards.ts` 和 `src/views/login/LoginView.vue`,在未登录时把目标路由写入 `redirect` 查询参数;登录成功后优先跳转目标路由,否则进入 `/dashboard`。
|
||||
|
||||
3. 视图与视觉层
|
||||
重构 `src/layouts/AdminLayout.vue`、`src/views/dashboard/DashboardView.vue` 与全局样式,采用深色 Composio 风格:
|
||||
- 近黑背景 + 低对比边框
|
||||
- `JetBrains Mono` 数字与技术标签
|
||||
- 冷蓝/青色信号强调
|
||||
- 以“夜间指挥中心”方式组织统计信息
|
||||
|
||||
趋势图首版采用自绘 SVG 折线图,避免为单页仪表盘引入新的重型图表库。
|
||||
|
||||
### 影响范围
|
||||
```yaml
|
||||
涉及模块:
|
||||
- admin-frontend/src/api: 新增后台仪表盘数据请求封装
|
||||
- admin-frontend/src/types: 补充管理端统计响应类型
|
||||
- admin-frontend/src/router: 调整登录回跳逻辑
|
||||
- admin-frontend/src/views/login: 登录成功跳转逻辑增强
|
||||
- admin-frontend/src/views/dashboard: 从占位页升级为真实运营仪表盘
|
||||
- admin-frontend/src/layouts: 主布局视觉升级
|
||||
- admin-frontend/src/styles: 统一深色视觉变量与全局基线
|
||||
预计变更文件: 8-10
|
||||
```
|
||||
|
||||
### 风险评估
|
||||
| 风险 | 等级 | 应对 |
|
||||
|------|------|------|
|
||||
| 后端接口字段与前端预期存在轻微偏差 | 中 | 直接以仓库内 Controller 返回结构为准建模,类型保持可扩展 |
|
||||
| 管理端趋势图无现成图表库 | 低 | 使用自绘 SVG,减少依赖和构建风险 |
|
||||
| 深色重构影响现有登录页与布局一致性 | 中 | 同步更新全局样式变量,确保登录页与后台主框架共享同一视觉系统 |
|
||||
| 移动端侧边栏与大屏布局冲突 | 中 | 采用断点折叠、卡片栈式布局和横向滚动安全兜底 |
|
||||
|
||||
---
|
||||
|
||||
## 3. 技术设计(可选)
|
||||
|
||||
> 涉及架构变更、API设计、数据模型变更时填写
|
||||
|
||||
### 架构设计
|
||||
```mermaid
|
||||
flowchart TD
|
||||
A[LoginView] --> B[AuthStore.login]
|
||||
B --> C[passport/auth/login]
|
||||
B --> D[getSystemStatus]
|
||||
A --> E[Router redirect]
|
||||
E --> F[DashboardView]
|
||||
F --> G[getStats]
|
||||
F --> H[getOrder]
|
||||
F --> I[getTrafficRank]
|
||||
F --> J[getSystemStatus]
|
||||
F --> K[getQueueStats]
|
||||
```
|
||||
|
||||
### API设计
|
||||
#### GET /api/v2/{secure_path}/stat/getStats
|
||||
- **请求**: 无
|
||||
- **响应**: `todayIncome/currentMonthIncome/traffic/users/onlineNodes` 等仪表盘总览数据
|
||||
|
||||
#### GET /api/v2/{secure_path}/stat/getOrder
|
||||
- **请求**: `start_date`, `end_date`, `type?`
|
||||
- **响应**: `list[] + summary`,用于收入趋势图与摘要
|
||||
|
||||
#### GET /api/v2/{secure_path}/stat/getTrafficRank
|
||||
- **请求**: `type=node|user`, `start_time`, `end_time`
|
||||
- **响应**: Top 10 排行及环比变化
|
||||
|
||||
#### GET /api/v2/{secure_path}/system/getSystemStatus
|
||||
- **请求**: 无
|
||||
- **响应**: `schedule`, `horizon`, `schedule_last_runtime`
|
||||
|
||||
#### GET /api/v2/{secure_path}/system/getQueueStats
|
||||
- **请求**: 无
|
||||
- **响应**: `failedJobs`, `jobsPerMinute`, `recentJobs`, `processes`, `wait`, `status`
|
||||
|
||||
### 数据模型
|
||||
| 字段 | 类型 | 说明 |
|
||||
|------|------|------|
|
||||
| DashboardStats | object | 仪表盘总览统计 |
|
||||
| OrderTrendPoint | object | 收入趋势日维度数据点 |
|
||||
| TrafficRankItem | object | 节点或用户排行项 |
|
||||
| QueueStats | object | Horizon/队列运行状态 |
|
||||
|
||||
---
|
||||
|
||||
## 4. 核心场景
|
||||
|
||||
> 执行完成后同步到对应模块文档
|
||||
|
||||
### 场景: 登录后回跳
|
||||
**模块**: auth / router / login
|
||||
**条件**: 用户未登录访问受保护路由
|
||||
**行为**: 路由守卫记录目标地址,登录成功后优先跳转原目标
|
||||
**结果**: 用户不会被强制打回固定首页
|
||||
|
||||
### 场景: 仪表盘总览
|
||||
**模块**: dashboard
|
||||
**条件**: 管理员登录成功并进入首页
|
||||
**行为**: 页面并行拉取总览、趋势、排行和系统状态数据
|
||||
**结果**: 用户看到真实的收入、用户、流量和队列运行信息
|
||||
|
||||
### 场景: 运营态分析
|
||||
**模块**: dashboard
|
||||
**条件**: 用户切换时间范围或排行类型
|
||||
**行为**: 页面重新请求对应接口并刷新局部区块
|
||||
**结果**: 后台可快速识别收入波动、流量头部节点与活跃用户
|
||||
|
||||
---
|
||||
|
||||
## 5. 技术决策
|
||||
|
||||
> 本方案涉及的技术决策,归档后成为决策的唯一完整记录
|
||||
|
||||
### admin-frontend-composio-dashboard#D001: 仪表盘视觉采用深色 Composio 风格而非参考图浅色风格
|
||||
**日期**: 2026-04-21
|
||||
**状态**: ✅采纳
|
||||
**背景**: 用户明确选择“以 DESIGN.md 为准,做深色 Composio 风格仪表盘,但功能结构对齐参考图”。
|
||||
**选项分析**:
|
||||
| 选项 | 优点 | 缺点 |
|
||||
|------|------|------|
|
||||
| A: 浅色还原参考图 | 更接近截图 | 与仓库既定 DESIGN.md 和现有深色登录页割裂 |
|
||||
| B: 深色 Composio 风格 | 与既定设计系统一致,辨识度更高 | 需要重做布局与视觉细节 |
|
||||
**决策**: 选择方案 B
|
||||
**理由**: 用户已明确选定深色方向,且当前登录页已具备深色基础,继续向“夜间控制台”统一更稳妥。
|
||||
**影响**: `AdminLayout`、`DashboardView`、`LoginView`、全局样式变量
|
||||
|
||||
### admin-frontend-composio-dashboard#D002: 趋势图采用自绘 SVG 而非新增图表依赖
|
||||
**日期**: 2026-04-21
|
||||
**状态**: ✅采纳
|
||||
**背景**: 当前项目仅需单个折线趋势图,引入 ECharts 等库会增加体积和维护成本。
|
||||
**选项分析**:
|
||||
| 选项 | 优点 | 缺点 |
|
||||
|------|------|------|
|
||||
| A: 引入图表库 | 功能全、配置丰富 | 增加依赖与样式整合成本 |
|
||||
| B: 自绘 SVG 折线图 | 体积轻、可完全匹配设计语言 | 需手工处理坐标和交互 |
|
||||
**决策**: 选择方案 B
|
||||
**理由**: 本轮诉求聚焦仪表盘首页,SVG 已足够覆盖折线图、悬浮提示和时间序列展示。
|
||||
**影响**: `DashboardView` 内部图表实现方式,不改构建依赖
|
||||
|
||||
---
|
||||
|
||||
## 6. 成果设计
|
||||
|
||||
> 含视觉产出的任务由 DESIGN Phase2 填充。非视觉任务整节标注"N/A"。
|
||||
|
||||
### 设计方向
|
||||
- **美学基调**: Nocturnal Command Center。像深夜运行的运维控制台,近黑背景中浮出冷蓝信号、低对比边框和技术排版,强调“被数据照亮”的感觉。
|
||||
- **记忆点**: 大面积近黑留白里嵌入发光式统计卡片与自绘蓝青折线图,数字像终端仪表一样被点亮。
|
||||
- **参考**: 仓库 [DESIGN.md](/E:/code/php/Xboard-new/DESIGN.md) 的 Composio 风格规范 + 用户提供的后台参考图功能结构
|
||||
|
||||
### 视觉要素
|
||||
- **配色**: 背景 `#0f0f0f` / 卡片内层 `#000000` / 线框 `rgba(255,255,255,0.08~0.12)` / 强调蓝 `#0007cd` / 信号青 `#00ffff`
|
||||
- **字体**: `IBM Plex Sans` 作为界面正文,`JetBrains Mono` 作为数字、标签和技术指标;中文回退到 `PingFang SC`、`Microsoft YaHei`
|
||||
- **布局**: 顶部密集统计卡片 + 中段趋势图双栏摘要 + 下段双排行 + 底部系统状态;桌面端强调控制台网格感,移动端改为单列堆叠
|
||||
- **动效**: 卡片和图表采用分层淡入、边框亮起与轻微上浮;筛选切换使用短时透明度过渡
|
||||
- **氛围**: 低对比边框、局部蓝青径向辉光、硬朗分割线和轻量噪点质感,避免普通 SaaS 白卡片质感
|
||||
|
||||
### 技术约束
|
||||
- **可访问性**: 保证关键指标和文字在深色背景上的对比度;图表与状态块提供文本值而非只靠颜色
|
||||
- **响应式**: `>=1280px` 四列指标卡,`768-1279px` 两列,`<768px` 单列;排行和图表区域允许安全降级为纵向布局
|
||||
@@ -0,0 +1,59 @@
|
||||
# 任务清单: admin-frontend-composio-dashboard
|
||||
|
||||
> **@status:** completed | 2026-04-21 03:43
|
||||
|
||||
```yaml
|
||||
@feature: admin-frontend-composio-dashboard
|
||||
@created: 2026-04-21
|
||||
@status: completed
|
||||
@mode: R2
|
||||
```
|
||||
|
||||
## 进度概览
|
||||
|
||||
| 完成 | 失败 | 跳过 | 总数 |
|
||||
|------|------|------|------|
|
||||
| 7 | 0 | 0 | 7 |
|
||||
|
||||
---
|
||||
|
||||
## 任务列表
|
||||
|
||||
### 1. 数据模型与接口
|
||||
|
||||
- [√] 1.1 在 `admin-frontend/src/types/api.d.ts` 中补充仪表盘、趋势、排行、队列状态的类型定义 | depends_on: []
|
||||
- [√] 1.2 在 `admin-frontend/src/api/admin.ts` 中实现总览、趋势、排行、系统与队列状态接口封装 | depends_on: [1.1]
|
||||
|
||||
### 2. 认证与跳转
|
||||
|
||||
- [√] 2.1 在 `admin-frontend/src/router/guards.ts` 中为受保护路由增加 `redirect` 回跳逻辑 | depends_on: [1.2]
|
||||
- [√] 2.2 在 `admin-frontend/src/views/login/LoginView.vue` 中实现登录成功后的目标路由跳转与错误处理增强 | depends_on: [2.1]
|
||||
|
||||
### 3. 布局与视觉
|
||||
|
||||
- [√] 3.1 在 `admin-frontend/src/layouts/AdminLayout.vue` 和 `admin-frontend/src/styles/index.scss` 中重构 Composio 风格后台框架与全局视觉变量 | depends_on: [2.2]
|
||||
|
||||
### 4. 仪表盘页面
|
||||
|
||||
- [√] 4.1 在 `admin-frontend/src/views/dashboard/DashboardView.vue` 中实现总览卡片、收入趋势图、节点/用户排行、系统状态区块 | depends_on: [1.2,3.1]
|
||||
- [√] 4.2 完成 `admin-frontend` 构建验证并修正类型/样式问题 | depends_on: [4.1]
|
||||
|
||||
---
|
||||
|
||||
## 执行日志
|
||||
|
||||
| 时间 | 任务 | 状态 | 备注 |
|
||||
|------|------|------|------|
|
||||
| 2026-04-21 03:26 | 方案包初始化 | completed | 已生成 proposal/tasks 并锁定深色 Composio 仪表盘方向 |
|
||||
| 2026-04-21 03:34 | 1.x / 2.x | completed | 已补充接口类型、管理端请求封装、登录回跳逻辑 |
|
||||
| 2026-04-21 03:39 | 3.1 / 4.1 | completed | 已完成深色后台框架、登录页重构与仪表盘主视图实现 |
|
||||
| 2026-04-21 03:40 | 4.2 | completed | `npm run build` 通过,产物输出到 `public/assets/admin` |
|
||||
| 2026-04-21 03:42 | 验收 | completed | 已启动 Vite 开发服务并确认 `/assets/admin/` 与 `/#/login` 可访问 |
|
||||
|
||||
---
|
||||
|
||||
## 执行备注
|
||||
|
||||
- 当前任务基于 `.claude/plan/admin-frontend-login.md` 续作,但以本方案包作为本轮实现和验收的事实记录。
|
||||
- 本轮不新增后端接口,仅消费仓库内已存在的管理端统计与系统状态接口。
|
||||
- 页面运行态验收已覆盖构建与静态入口访问;仪表盘真实业务数据联调仍依赖实际 `secure_path` 与管理员鉴权环境。
|
||||
+11
@@ -0,0 +1,11 @@
|
||||
{
|
||||
"status": "completed",
|
||||
"completed": 5,
|
||||
"failed": 0,
|
||||
"pending": 0,
|
||||
"total": 5,
|
||||
"done": 5,
|
||||
"percent": 100,
|
||||
"current": "Apple 风格性能重构完成,待归档",
|
||||
"updated_at": "2026-04-21 04:13:00"
|
||||
}
|
||||
+183
@@ -0,0 +1,183 @@
|
||||
# 变更提案: admin-frontend-apple-performance-refresh
|
||||
|
||||
## 元信息
|
||||
```yaml
|
||||
类型: 重构 + 优化
|
||||
方案类型: implementation
|
||||
优先级: P1
|
||||
状态: 已完成
|
||||
创建: 2026-04-21
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 1. 需求
|
||||
|
||||
### 背景
|
||||
上一轮管理端首页已完成深色 Composio 风格仪表盘,但用户反馈“页面非常卡顿”。结合当前实现可见,卡顿风险主要来自全局远程字体加载、固定噪点层、多个径向渐变与模糊装饰、较重阴影以及偏复杂的深色视觉特效。用户本轮明确要求改为 `apple/DESIGN.md` 设计体系,并将登录页、主布局和仪表盘统一重做。
|
||||
|
||||
### 目标
|
||||
- 将登录页、主布局、仪表盘首页整体切换为 Apple 风格视觉体系。
|
||||
- 明确降低页面运行时开销,优先删除高成本视觉装饰和非必要动画。
|
||||
- 保留现有数据接入、登录回跳和后台业务信息结构,不回退功能。
|
||||
|
||||
### 约束条件
|
||||
```yaml
|
||||
时间约束: 本轮仅重做 admin-frontend 的登录页、主布局、仪表盘首页
|
||||
性能约束: 去除远程字体依赖、固定背景噪点层、强滤镜和高频装饰性重绘
|
||||
兼容性约束: 保持现有 Vue3 + Vite + Element Plus 栈,不新增重型 UI 或图表依赖
|
||||
业务约束: 登录逻辑、secure_path、自定义 API 请求和统计接口保持不变
|
||||
```
|
||||
|
||||
### 验收标准
|
||||
- [ ] 登录页、主布局、仪表盘首页统一符合 Apple 设计系统,视觉更克制、轻量、清晰。
|
||||
- [ ] 移除当前页面中的高成本装饰层,首屏样式明显降载。
|
||||
- [ ] 仪表盘的数据接口、排行、趋势、系统状态功能保持可用。
|
||||
- [ ] `admin-frontend` 重新构建通过。
|
||||
|
||||
---
|
||||
|
||||
## 2. 方案
|
||||
|
||||
### 技术方案
|
||||
本轮采用“保留逻辑,重写视图皮层”的方式:
|
||||
|
||||
1. 全局样式降载
|
||||
在 `src/styles/index.scss` 中移除 Google Fonts、固定噪点遮罩、全局径向辉光与过重背景层,改为 Apple 风格的系统字体栈、纯色背景与轻量层次。
|
||||
|
||||
2. 登录页重构
|
||||
将当前双辉光深色登录页重构为 Apple 式大标题 + 清爽表单卡布局,保留登录回跳逻辑,只替换视觉和结构。
|
||||
|
||||
3. 主布局重构
|
||||
把当前“夜间控制台”侧栏和头部压缩为更克制的 Apple 导航语言,减少边框、渐变、信号灯和装饰芯片。
|
||||
|
||||
4. 仪表盘重构
|
||||
保留真实数据接口与 SVG 趋势图,但改成 Apple 风格的黑/浅灰分区、简洁卡片、单一蓝色交互重点和更轻的图表样式。
|
||||
|
||||
### 影响范围
|
||||
```yaml
|
||||
涉及模块:
|
||||
- admin-frontend/src/styles: 全局视觉与性能基线
|
||||
- admin-frontend/src/views/login: 登录页 Apple 风格重构
|
||||
- admin-frontend/src/layouts: 主布局和导航样式重构
|
||||
- admin-frontend/src/views/dashboard: 仪表盘内容重排与轻量样式替换
|
||||
预计变更文件: 4-6
|
||||
```
|
||||
|
||||
### 风险评估
|
||||
| 风险 | 等级 | 应对 |
|
||||
|------|------|------|
|
||||
| 视觉重构影响当前布局层级 | 中 | 保持数据结构和主要 DOM 分区稳定,只重写样式与局部布局 |
|
||||
| Apple 风格若过度追求极简导致信息密度下降 | 中 | 保留统计卡片、趋势图、排行和状态分区,只减少装饰噪音 |
|
||||
| 去除装饰层后页面可能显得“过空” | 低 | 用黑/浅灰区块切换、系统字体、轻阴影和单一蓝色 CTA 建立节奏 |
|
||||
|
||||
---
|
||||
|
||||
## 3. 技术设计(可选)
|
||||
|
||||
> 涉及架构变更、API设计、数据模型变更时填写
|
||||
|
||||
### 架构设计
|
||||
```mermaid
|
||||
flowchart TD
|
||||
A[index.scss] --> B[LoginView]
|
||||
A --> C[AdminLayout]
|
||||
A --> D[DashboardView]
|
||||
D --> E[getDashboardStats]
|
||||
D --> F[getOrderTrend]
|
||||
D --> G[getTrafficRank]
|
||||
D --> H[getSystemStatus/getQueueStats]
|
||||
```
|
||||
|
||||
### API设计
|
||||
#### GET /api/v2/{secure_path}/stat/getStats
|
||||
- **请求**: 无
|
||||
- **响应**: 仪表盘总览统计
|
||||
|
||||
#### GET /api/v2/{secure_path}/stat/getOrder
|
||||
- **请求**: `start_date`, `end_date`
|
||||
- **响应**: 收入趋势与汇总
|
||||
|
||||
#### GET /api/v2/{secure_path}/stat/getTrafficRank
|
||||
- **请求**: `type`, `start_time`, `end_time`
|
||||
- **响应**: 节点/用户排行
|
||||
|
||||
### 数据模型
|
||||
| 字段 | 类型 | 说明 |
|
||||
|------|------|------|
|
||||
| DashboardStats | object | 统计卡片数据 |
|
||||
| OrderTrendData | object | 收入趋势图数据 |
|
||||
| TrafficRankResponse | object | 排行区数据 |
|
||||
| QueueStats/SystemStatus | object | 作业详情与系统状态数据 |
|
||||
|
||||
---
|
||||
|
||||
## 4. 核心场景
|
||||
|
||||
> 执行完成后同步到对应模块文档
|
||||
|
||||
### 场景: 登录进入后台
|
||||
**模块**: LoginView / router
|
||||
**条件**: 用户访问登录页或被守卫重定向到登录页
|
||||
**行为**: 用户输入管理员账号密码并提交
|
||||
**结果**: 登录成功后按原有 redirect 规则返回目标页
|
||||
|
||||
### 场景: 查看首页经营数据
|
||||
**模块**: DashboardView
|
||||
**条件**: 管理员进入仪表盘
|
||||
**行为**: 页面加载总览、趋势、排行和系统状态
|
||||
**结果**: 页面用更轻量的 Apple 风格区块展示相同业务信息
|
||||
|
||||
---
|
||||
|
||||
## 5. 技术决策
|
||||
|
||||
> 本方案涉及的技术决策,归档后成为决策的唯一完整记录
|
||||
|
||||
### admin-frontend-apple-performance-refresh#D001: 采用 Apple 设计系统并优先做性能减法
|
||||
**日期**: 2026-04-21
|
||||
**状态**: ✅采纳
|
||||
**背景**: 用户已明确指出当前页面“非常卡顿”,并要求按 `apple/DESIGN.md` 重做。
|
||||
**选项分析**:
|
||||
| 选项 | 优点 | 缺点 |
|
||||
|------|------|------|
|
||||
| A: 保留 Composio 风格,仅做性能微调 | 改动小 | 无法满足用户指定的 Apple 方向 |
|
||||
| B: Apple 风格 + 性能减法重构 | 同时解决风格偏差和卡顿 | 需要重写多个页面的样式结构 |
|
||||
**决策**: 选择方案 B
|
||||
**理由**: 这次诉求的核心不是补功能,而是重新定义页面体验和运行成本。
|
||||
**影响**: 登录页、主布局、仪表盘、全局样式
|
||||
|
||||
### admin-frontend-apple-performance-refresh#D002: 维持现有数据逻辑,仅替换视图皮层
|
||||
**日期**: 2026-04-21
|
||||
**状态**: ✅采纳
|
||||
**背景**: 当前 API 封装和跳转逻辑已完成,不需要在本轮视觉重构中回退或重写。
|
||||
**选项分析**:
|
||||
| 选项 | 优点 | 缺点 |
|
||||
|------|------|------|
|
||||
| A: 连逻辑层一起重做 | 可重新整理代码 | 超出本轮目标,风险更高 |
|
||||
| B: 保留逻辑层,重构页面与样式 | 风险可控,收益集中 | 需要在旧结构中做设计转换 |
|
||||
**决策**: 选择方案 B
|
||||
**理由**: 用户反馈集中在“前端效果卡顿”,而不是数据和接口错误。
|
||||
**影响**: `api/*` 与 `router/*` 只做最小配合,改动集中于视图和样式
|
||||
|
||||
---
|
||||
|
||||
## 6. 成果设计
|
||||
|
||||
> 含视觉产出的任务由 DESIGN Phase2 填充。非视觉任务整节标注"N/A"。
|
||||
|
||||
### 设计方向
|
||||
- **美学基调**: Apple Product Editorial。像 Apple 产品页与系统面板的混合体,控制住装饰噪音,让内容像展品一样陈列。
|
||||
- **记忆点**: 黑色英雄区和浅灰信息区交替展开,单一 Apple Blue 成为全页唯一强调色。
|
||||
- **参考**: [apple/DESIGN.md](/E:/code/php/Xboard-new/apple/DESIGN.md)
|
||||
|
||||
### 视觉要素
|
||||
- **配色**: 黑色 `#000000`、浅灰 `#f5f5f7`、正文深灰 `#1d1d1f`、交互蓝 `#0071e3`
|
||||
- **字体**: 采用系统栈模拟 SF Pro 体验,优先 `-apple-system`, `BlinkMacSystemFont`, `SF Pro Display`, `SF Pro Text`, `Helvetica Neue`, Arial, sans-serif`
|
||||
- **布局**: 英雄区大标题 + 轻卡片信息区 + 简洁双列内容;信息通过区块切换而不是发光边框表达层级
|
||||
- **动效**: 仅保留轻量 hover 和淡入,不保留大面积 blur、辉光、滤镜动画
|
||||
- **氛围**: 纯色背景、轻阴影、玻璃感顶栏;不使用噪点、网格、径向发光和复杂纹理
|
||||
|
||||
### 技术约束
|
||||
- **可访问性**: 文字与背景维持高对比;交互色仅使用 Apple Blue
|
||||
- **响应式**: 登录页双栏在窄屏下改为单列;仪表盘卡片和内容区在平板/手机下自动折叠为单列
|
||||
+54
@@ -0,0 +1,54 @@
|
||||
# 任务清单: admin-frontend-apple-performance-refresh
|
||||
|
||||
> **@status:** completed | 2026-04-21 04:14
|
||||
|
||||
```yaml
|
||||
@feature: admin-frontend-apple-performance-refresh
|
||||
@created: 2026-04-21
|
||||
@status: completed
|
||||
@mode: R2
|
||||
```
|
||||
|
||||
## 进度概览
|
||||
|
||||
| 完成 | 失败 | 跳过 | 总数 |
|
||||
|------|------|------|------|
|
||||
| 5 | 0 | 0 | 5 |
|
||||
|
||||
---
|
||||
|
||||
## 任务列表
|
||||
|
||||
### 1. 全局视觉与性能基线
|
||||
|
||||
- [√] 1.1 在 `admin-frontend/src/styles/index.scss` 中移除高成本装饰层并建立 Apple 风格全局变量 | depends_on: []
|
||||
|
||||
### 2. 登录与布局
|
||||
|
||||
- [√] 2.1 在 `admin-frontend/src/views/login/LoginView.vue` 中将登录页重构为 Apple 风格轻量布局 | depends_on: [1.1]
|
||||
- [√] 2.2 在 `admin-frontend/src/layouts/AdminLayout.vue` 中重构主布局与头部导航,去除当前控制台式装饰 | depends_on: [1.1]
|
||||
|
||||
### 3. 仪表盘
|
||||
|
||||
- [√] 3.1 在 `admin-frontend/src/views/dashboard/DashboardView.vue` 中重构为 Apple 风格信息分区并保留现有统计功能 | depends_on: [1.1,2.2]
|
||||
- [√] 3.2 完成 `admin-frontend` 构建验证并修正重构引入的问题 | depends_on: [2.1,2.2,3.1]
|
||||
|
||||
---
|
||||
|
||||
## 执行日志
|
||||
|
||||
| 时间 | 任务 | 状态 | 备注 |
|
||||
|------|------|------|------|
|
||||
| 2026-04-21 04:00 | 方案包初始化 | completed | 已锁定 Apple 风格 + 性能减法方向 |
|
||||
| 2026-04-21 04:10 | 1.1 / 2.x | completed | 已移除远程字体与全局重装饰,完成登录页和主布局 Apple 化 |
|
||||
| 2026-04-21 04:12 | 3.1 | completed | 已将仪表盘重构为 Apple 风格分区,同时保留现有数据接口 |
|
||||
| 2026-04-21 04:12 | 3.2 | completed | `npm run build` 通过,运行态入口 `200` |
|
||||
|
||||
---
|
||||
|
||||
## 执行备注
|
||||
|
||||
> 记录执行过程中的重要说明、决策变更、风险提示等
|
||||
|
||||
- 本轮不回退上一轮的数据接入和登录回跳逻辑,仅重构视图皮层和高成本样式。
|
||||
- 运行态验证已确认 `/assets/admin/` 与 `/#/login` 可访问;真实性能评估仍建议在真实后台数据环境里再观察一次滚动与切换体验。
|
||||
@@ -0,0 +1 @@
|
||||
{"status":"completed","completed":8,"failed":0,"pending":0,"total":8,"done":8,"percent":100,"current":"已完成用户管理页面、路由与构建验证,待归档方案包","updated_at":"2026-04-21 05:05:00"}
|
||||
@@ -0,0 +1,208 @@
|
||||
# 变更提案: admin-frontend-user-management
|
||||
|
||||
## 元信息
|
||||
```yaml
|
||||
类型: 新功能
|
||||
方案类型: implementation
|
||||
优先级: P1
|
||||
状态: 已完成
|
||||
创建: 2026-04-21
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 1. 需求
|
||||
|
||||
### 背景
|
||||
当前 `admin-frontend` 已完成登录、主布局与仪表盘,但业务路由仍只有 `/dashboard`。用户本轮明确要求继续沿 [.claude/plan/admin-frontend-login.md](/E:/code/php/Xboard-new/.claude/plan/admin-frontend-login.md) 推进,按照 [apple/DESIGN.md](/E:/code/php/Xboard-new/apple/DESIGN.md) 的 Apple 风格,为后台补齐“用户管理 / 工单管理”入口,且优先完整实现“用户管理”页面。参考图已经给出了目标交互形态,包括左侧菜单分组、用户列表、行内更多操作菜单,以及右侧抽屉式新增/编辑用户表单。
|
||||
|
||||
### 目标
|
||||
- 在管理端新增“用户管理”业务页,完成菜单、路由、页面与真实接口接入。
|
||||
- 让用户管理页具备可用的搜索、分页、状态展示、更多操作菜单,以及新增/编辑用户抽屉。
|
||||
- 预留“工单管理”菜单与路由入口,使后台导航结构与参考图对齐,但本轮不展开工单业务实现。
|
||||
|
||||
### 约束条件
|
||||
```yaml
|
||||
时间约束: 本轮只完整实现“用户管理”,工单管理仅补路由入口和占位页
|
||||
性能约束: 保持当前轻量 Apple 风格,不新增重型表格或状态管理依赖
|
||||
兼容性约束: 保持现有 Vue3 + TypeScript + Vite + Element Plus 栈与 hash 路由模式
|
||||
业务约束: 后端接口沿用现有 `/api/v2/{secure_path}/user/*`、`/plan/fetch`,不改 Laravel API
|
||||
```
|
||||
|
||||
### 验收标准
|
||||
- [ ] 管理端左侧导航新增“用户管理”分组,包含“用户管理”和“工单管理”两个入口。
|
||||
- [ ] 用户管理页可通过真实接口完成列表读取、分页、基础筛选、状态/套餐/流量展示。
|
||||
- [ ] 用户管理页支持新增用户、编辑用户、复制订阅地址、重置密钥、封禁和删除等操作入口,并带明确确认反馈。
|
||||
- [ ] `admin-frontend` 构建通过,新增页面在桌面和移动端都能正常访问。
|
||||
|
||||
---
|
||||
|
||||
## 2. 方案
|
||||
|
||||
### 技术方案
|
||||
本轮采用“扩展现有管理壳层 + 新增用户管理业务模块”的方案:
|
||||
|
||||
1. 扩展管理端数据层
|
||||
在 `src/types/api.d.ts` 中补充用户、套餐、分页与表单类型;在 `src/api/admin.ts` 中新增用户列表、用户详情、套餐列表、用户创建/更新/重置密钥/封禁/删除等请求封装。
|
||||
|
||||
2. 新增用户管理视图
|
||||
在 `src/views/users/` 下拆分页面与抽屉组件。列表页负责搜索、表格、分页、更多操作菜单;抽屉组件负责新增/编辑表单。视觉上延续 Apple 风格的浅灰画布、白色内容区与单一蓝色交互重点。
|
||||
|
||||
3. 对齐后端真实创建能力
|
||||
后端 `user/generate` 只能直接创建基础字段(邮箱、密码、套餐、到期时间),无法一次性写入完整表单字段。因此新增用户时采用“两段式”流程:
|
||||
- 先调用 `user/generate` 创建基础账号
|
||||
- 再按邮箱回查用户 ID,并调用 `user/update` 补齐流量、余额、佣金、权限、限速、设备数、备注等扩展字段
|
||||
|
||||
4. 补齐导航与路由
|
||||
将当前仅有仪表盘的侧边栏调整为分组导航,新增 `/users` 路由和 `/tickets` 占位路由;本轮仅实现 `UsersView` 的完整业务功能。
|
||||
|
||||
### 影响范围
|
||||
```yaml
|
||||
涉及模块:
|
||||
- admin-frontend/src/router: 新增用户管理与工单管理路由
|
||||
- admin-frontend/src/layouts: 调整侧边栏菜单结构与导航文案
|
||||
- admin-frontend/src/api: 扩展用户与套餐相关请求
|
||||
- admin-frontend/src/types: 新增用户管理数据类型
|
||||
- admin-frontend/src/views/users: 新增用户列表页与表单抽屉
|
||||
- admin-frontend/src/views/tickets: 新增工单管理占位页
|
||||
预计变更文件: 7-9
|
||||
```
|
||||
|
||||
### 风险评估
|
||||
| 风险 | 等级 | 应对 |
|
||||
|------|------|------|
|
||||
| 后端新增用户接口字段不足,无法一次提交完整表单 | 中 | 前端采用 `generate + fetch + update` 两段式创建流程 |
|
||||
| 参考图中的“在线设备”字段后端列表接口未直接返回 | 中 | 本轮优先展示可用业务字段,设备相关展示使用已有限制字段和可退化文案 |
|
||||
| 用户删除属于破坏性操作 | 中 | 在前端增加显式确认和操作完成提示,避免误删 |
|
||||
|
||||
---
|
||||
|
||||
## 3. 技术设计(可选)
|
||||
|
||||
> 涉及路由扩展、API映射与表单编排,需填写。
|
||||
|
||||
### 架构设计
|
||||
```mermaid
|
||||
flowchart TD
|
||||
A[AdminLayout 侧边栏菜单] --> B[UsersView 用户管理页]
|
||||
A --> C[TicketsPlaceholderView 工单占位页]
|
||||
B --> D[UserToolbar 搜索与操作]
|
||||
B --> E[UserTable 列表与更多操作]
|
||||
B --> F[UserFormDrawer 新增/编辑抽屉]
|
||||
B --> G[admin.ts 用户管理接口]
|
||||
F --> G
|
||||
G --> H[/user/fetch]
|
||||
G --> I[/user/generate]
|
||||
G --> J[/user/update]
|
||||
G --> K[/user/resetSecret]
|
||||
G --> L[/user/ban]
|
||||
G --> M[/user/destroy]
|
||||
G --> N[/plan/fetch]
|
||||
```
|
||||
|
||||
### API设计
|
||||
#### ANY /api/v2/{secure_path}/user/fetch
|
||||
- **请求**: `current`, `pageSize`, `filter[]`, `sort[]`
|
||||
- **响应**: `{ data: UserListItem[], total: number }`
|
||||
|
||||
#### GET /api/v2/{secure_path}/user/getUserInfoById
|
||||
- **请求**: `id`
|
||||
- **响应**: 单个用户详情,含邀请人信息
|
||||
|
||||
#### POST /api/v2/{secure_path}/user/generate
|
||||
- **请求**: `email_prefix`, `email_suffix`, `password`, `plan_id`, `expired_at`
|
||||
- **响应**: `success(true)` 或批量结果
|
||||
|
||||
#### POST /api/v2/{secure_path}/user/update
|
||||
- **请求**: `id` + 用户扩展字段(余额、佣金、流量、权限、限速、设备数、备注等)
|
||||
- **响应**: `success(true)`
|
||||
|
||||
#### GET /api/v2/{secure_path}/plan/fetch
|
||||
- **请求**: 无
|
||||
- **响应**: 套餐列表,用于表单选择和表格展示
|
||||
|
||||
### 数据模型
|
||||
| 字段 | 类型 | 说明 |
|
||||
|------|------|------|
|
||||
| AdminUserListItem | object | 用户列表行数据,包含套餐、邀请人、权限组、流量、状态等 |
|
||||
| AdminUserFormModel | object | 抽屉表单模型,覆盖新增/编辑时的基础与扩展字段 |
|
||||
| AdminPlanOption | object | 订阅计划选项,用于表单下拉与列表展示 |
|
||||
| AdminPaginationResult<T> | object | 用户列表分页结果 |
|
||||
|
||||
---
|
||||
|
||||
## 4. 核心场景
|
||||
|
||||
> 执行完成后同步到对应模块文档
|
||||
|
||||
### 场景: 浏览用户列表
|
||||
**模块**: UsersView
|
||||
**条件**: 管理员已登录并进入 `/users`
|
||||
**行为**: 页面读取用户列表、套餐信息并渲染搜索栏、表格、分页
|
||||
**结果**: 管理员可快速查看用户状态、流量、到期时间与套餐
|
||||
|
||||
### 场景: 新增用户
|
||||
**模块**: UserFormDrawer / admin.ts
|
||||
**条件**: 管理员在用户管理页点击“创建用户”
|
||||
**行为**: 管理员填写抽屉表单,前端先生成基础账号,再补写扩展字段
|
||||
**结果**: 新用户创建成功,列表自动刷新并提示结果
|
||||
|
||||
### 场景: 编辑或执行行内操作
|
||||
**模块**: UsersView / UserFormDrawer
|
||||
**条件**: 列表中存在目标用户
|
||||
**行为**: 管理员打开更多菜单执行编辑、复制订阅地址、重置密钥、封禁或删除
|
||||
**结果**: 对应操作完成并反馈到列表状态
|
||||
|
||||
---
|
||||
|
||||
## 5. 技术决策
|
||||
|
||||
> 本方案涉及的技术决策,归档后成为决策的唯一完整记录
|
||||
|
||||
### admin-frontend-user-management#D001: 新增用户采用“两段式创建”以兼容现有后端接口
|
||||
**日期**: 2026-04-21
|
||||
**状态**: ✅采纳
|
||||
**背景**: 参考表单包含余额、佣金、流量、角色、限速、设备数、备注等字段,但后端 `user/generate` 仅支持基础创建字段。
|
||||
**选项分析**:
|
||||
| 选项 | 优点 | 缺点 |
|
||||
|------|------|------|
|
||||
| A: 仅用 `user/generate` 并缩减表单字段 | 实现简单 | 无法对齐参考页字段深度 |
|
||||
| B: 先 `generate`,再按邮箱回查并 `update` | 能保留完整表单能力 | 前端流程更复杂 |
|
||||
**决策**: 选择方案 B
|
||||
**理由**: 既不改后端,也能最大化还原参考抽屉中的管理能力。
|
||||
**影响**: `admin.ts`、`UsersView`、`UserFormDrawer`
|
||||
|
||||
### admin-frontend-user-management#D002: 先补齐用户/工单路由结构,但本轮仅交付完整用户页
|
||||
**日期**: 2026-04-21
|
||||
**状态**: ✅采纳
|
||||
**背景**: 用户要求“添加用户管理、工单管理路由,先完成用户管理”,既要有完整导航结构,又要控制当前实现范围。
|
||||
**选项分析**:
|
||||
| 选项 | 优点 | 缺点 |
|
||||
|------|------|------|
|
||||
| A: 只加用户管理,不处理工单入口 | 实现最小 | 与用户点名的导航结构不一致 |
|
||||
| B: 同时补齐用户/工单入口,工单先占位 | 与目标结构一致,后续扩展顺滑 | 需要新增一个占位页面 |
|
||||
**决策**: 选择方案 B
|
||||
**理由**: 先把信息架构铺平,后续实现工单页时不必再改侧边栏和路由骨架。
|
||||
**影响**: `router/index.ts`、`layouts/AdminLayout.vue`
|
||||
|
||||
---
|
||||
|
||||
## 6. 成果设计
|
||||
|
||||
> 含视觉产出的任务由 DESIGN Phase2 填充。非视觉任务整节标注"N/A"。
|
||||
|
||||
### 设计方向
|
||||
- **美学基调**: Apple Admin Ledger。像 Apple 系统设置和内部运营面板的结合体,用极少的颜色和干净层级承载高密度数据。
|
||||
- **记忆点**: 浅灰页面基底上嵌入一块大尺寸白色数据工作台,右侧抽屉像系统级面板一样滑入。
|
||||
- **参考**: 用户提供的用户列表、操作菜单、抽屉表单和侧边栏截图 + [apple/DESIGN.md](/E:/code/php/Xboard-new/apple/DESIGN.md)
|
||||
|
||||
### 视觉要素
|
||||
- **配色**: 背景 `#f5f5f7`、表格/抽屉 `#ffffff`、标题 `#1d1d1f`、强调蓝 `#0071e3`、危险态 `#c93428`
|
||||
- **字体**: 延续当前系统字体栈 `-apple-system`, `BlinkMacSystemFont`, `SF Pro Display`, `SF Pro Text`, `Helvetica Neue`, Arial, sans-serif`
|
||||
- **布局**: 页面顶部为标题与操作条,中部为单块白色表格工作区;抽屉从右侧进入,表单按字段组自然分段
|
||||
- **动效**: 仅保留表格 hover、高亮状态和抽屉进出动画,避免复杂动效
|
||||
- **氛围**: 轻边框、软阴影、玻璃顶栏,避免深色重装饰和泛滥卡片分割
|
||||
|
||||
### 技术约束
|
||||
- **可访问性**: 所有状态色均保留文字标签;删除、封禁等危险操作必须有二次确认
|
||||
- **响应式**: 窄屏下工具栏折行、表格横向滚动、抽屉宽度自适应到视口
|
||||
@@ -0,0 +1,62 @@
|
||||
# 任务清单: admin-frontend-user-management
|
||||
|
||||
> **@status:** completed | 2026-04-21 05:02
|
||||
|
||||
```yaml
|
||||
@feature: admin-frontend-user-management
|
||||
@created: 2026-04-21
|
||||
@status: completed
|
||||
@mode: R2
|
||||
```
|
||||
|
||||
## 进度概览
|
||||
|
||||
| 完成 | 失败 | 跳过 | 总数 |
|
||||
|------|------|------|------|
|
||||
| 8 | 0 | 0 | 8 |
|
||||
|
||||
---
|
||||
|
||||
## 任务列表
|
||||
|
||||
### 1. 数据层与类型
|
||||
|
||||
- [√] 1.1 在 `admin-frontend/src/types/api.d.ts` 中补充用户管理、套餐、分页和表单类型 | depends_on: []
|
||||
- [√] 1.2 在 `admin-frontend/src/api/admin.ts` 中新增用户列表、详情、创建、更新、套餐、重置密钥、封禁、删除等接口封装 | depends_on: [1.1]
|
||||
|
||||
### 2. 用户管理视图
|
||||
|
||||
- [√] 2.1 新增 `admin-frontend/src/views/users/UserFormDrawer.vue`,实现新增/编辑用户抽屉表单和两段式创建流程 | depends_on: [1.1,1.2]
|
||||
- [√] 2.2 新增 `admin-frontend/src/views/users/UsersView.vue`,实现搜索、列表、分页、状态展示和更多操作菜单 | depends_on: [1.1,1.2]
|
||||
- [√] 2.3 在 `admin-frontend/src/views/users/UsersView.vue` 中完成抽屉联动、复制订阅地址、重置密钥、封禁、删除与刷新反馈 | depends_on: [2.1,2.2]
|
||||
|
||||
### 3. 导航与路由
|
||||
|
||||
- [√] 3.1 在 `admin-frontend/src/router/index.ts` 与 `admin-frontend/src/layouts/AdminLayout.vue` 中补齐“用户管理 / 工单管理”菜单和路由结构 | depends_on: [2.2]
|
||||
- [√] 3.2 新增 `admin-frontend/src/views/tickets/TicketsView.vue` 作为工单管理占位页,保持后续扩展入口稳定 | depends_on: [3.1]
|
||||
|
||||
### 4. 验收
|
||||
|
||||
- [√] 4.1 完成 `admin-frontend` 构建验证并修正新增页面引入的问题 | depends_on: [2.3,3.2]
|
||||
|
||||
---
|
||||
|
||||
## 执行日志
|
||||
|
||||
| 时间 | 任务 | 状态 | 备注 |
|
||||
|------|------|------|------|
|
||||
| 2026-04-21 04:41 | 方案包初始化 | completed | 已确认本轮完整实现用户管理,工单管理仅补入口与占位页 |
|
||||
| 2026-04-21 04:49 | 1.1 / 1.2 | completed | 已补齐用户管理类型定义与 admin API 封装 |
|
||||
| 2026-04-21 04:54 | 2.1 / 2.2 / 2.3 | completed | 已完成用户列表页、抽屉表单和更多操作菜单联动 |
|
||||
| 2026-04-21 04:56 | 3.1 / 3.2 | completed | 已补齐用户管理 / 工单管理菜单与路由,并新增工单占位页 |
|
||||
| 2026-04-21 05:00 | 4.1 | completed | `npm run build` 通过;使用管理员账号验证登录后已跳转 `/users`,静态 preview 下真实数据请求因缺少 Laravel 运行环境未完成 |
|
||||
|
||||
---
|
||||
|
||||
## 执行备注
|
||||
|
||||
> 记录执行过程中的重要说明、决策变更、风险提示等
|
||||
|
||||
- 本轮新增用户需要兼容后端 `user/generate` 的字段限制,前端会做创建后补写。
|
||||
- 参考图中的工单管理仅作为下一步入口,本轮不实现工单列表、会话与回复逻辑。
|
||||
- 真实数据接口联调受当前终端无 `php` 运行环境限制,浏览器验证覆盖到登录成功、路由跳转和页面结构渲染,未覆盖 Laravel 注入的 `window.settings` 与真实后台数据返回。
|
||||
+11
@@ -0,0 +1,11 @@
|
||||
{
|
||||
"status": "completed",
|
||||
"completed": 4,
|
||||
"failed": 0,
|
||||
"pending": 0,
|
||||
"total": 4,
|
||||
"done": 4,
|
||||
"percent": 100,
|
||||
"current": "Dashboard 全量刷新按钮实现、验证与知识库同步完成,待归档",
|
||||
"updated_at": "2026-04-23 15:43:00"
|
||||
}
|
||||
+44
@@ -0,0 +1,44 @@
|
||||
{
|
||||
"version": 1,
|
||||
"source": "~auto",
|
||||
"originCommand": "auto",
|
||||
"verifyMode": "test-first",
|
||||
"reviewerFocus": [],
|
||||
"testerFocus": [
|
||||
"Hero 区刷新按钮是否触发整页数据刷新",
|
||||
"刷新中是否有明确状态反馈并阻止重复点击",
|
||||
"Dashboard 页面构建后是否保持现有 Apple 风格层级"
|
||||
],
|
||||
"ui": {
|
||||
"required": true,
|
||||
"designContract": true,
|
||||
"sourcePriority": [
|
||||
"proposal.md",
|
||||
".helloagents/DESIGN.md",
|
||||
"hello-ui"
|
||||
],
|
||||
"styleAdvisor": {
|
||||
"required": false,
|
||||
"reason": "",
|
||||
"focus": []
|
||||
},
|
||||
"visualValidation": {
|
||||
"required": true,
|
||||
"reason": "本轮为 Dashboard 顶部新增显式操作按钮,需要确认视觉风格与交互状态一致。",
|
||||
"screens": [
|
||||
"dashboard desktop",
|
||||
"dashboard mobile"
|
||||
],
|
||||
"states": [
|
||||
"refresh idle",
|
||||
"refresh loading"
|
||||
]
|
||||
}
|
||||
},
|
||||
"advisor": {
|
||||
"required": false,
|
||||
"reason": "",
|
||||
"focus": [],
|
||||
"preferredSources": []
|
||||
}
|
||||
}
|
||||
+92
@@ -0,0 +1,92 @@
|
||||
# 变更提案: admin-frontend-dashboard-refresh-button
|
||||
|
||||
## 元信息
|
||||
```yaml
|
||||
类型: 增强
|
||||
方案类型: implementation
|
||||
优先级: P2
|
||||
状态: 已完成
|
||||
创建: 2026-04-23
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 1. 需求
|
||||
|
||||
### 背景
|
||||
当前 `admin-frontend` 仪表盘已经具备总览、趋势、排行与系统状态的数据拉取能力,但缺少一个显式、统一的“全量刷新”入口。用户希望在 `http://localhost:5173/assets/admin/#/dashboard` 对应的首页,基于 `apple/DESIGN.md` 的 Apple 风格,为整页数据增加刷新按钮。
|
||||
|
||||
### 目标
|
||||
- 在 `admin-frontend/src/views/dashboard/DashboardView.vue` 中增加一个整页全量刷新按钮。
|
||||
- 刷新动作需要覆盖统计卡、收入趋势、节点/用户排行、系统与队列状态。
|
||||
- 刷新按钮的视觉语言需延续当前 Apple 风格,不引入额外的重装饰。
|
||||
|
||||
### 约束条件
|
||||
```yaml
|
||||
技术约束:
|
||||
- 保持现有 Vue3 + TypeScript + Vite + Element Plus 栈
|
||||
- 复用现有 refreshDashboard 数据流,不重复造接口层逻辑
|
||||
UI约束:
|
||||
- 以 apple/DESIGN.md 为设计基线
|
||||
- 使用单一蓝色强调与黑色 Hero 区的克制表达
|
||||
行为约束:
|
||||
- 刷新时需有明确加载反馈
|
||||
- 刷新中避免重复点击触发并发请求
|
||||
```
|
||||
|
||||
### 验收标准
|
||||
- [√] Hero 区新增“刷新全部数据”入口,桌面和移动端都可正常使用。
|
||||
- [√] 点击后会统一刷新总览、趋势、排行和系统状态。
|
||||
- [√] 刷新中有可见状态反馈,并阻止重复触发。
|
||||
- [√] `admin-frontend` 构建通过。
|
||||
- [√] 本地页面完成一次视觉验收,确认按钮与 Apple 风格一致。
|
||||
|
||||
---
|
||||
|
||||
## 2. 方案
|
||||
|
||||
### 技术方案
|
||||
1. 在仪表盘 Hero 右侧状态区加入全量刷新按钮,作为当前页面最直接的系统操作入口。
|
||||
2. 复用现有 `refreshDashboard()` 逻辑,对其补充成功提示、最后刷新时间记录与手动触发入口。
|
||||
3. 为按钮增加刷新中状态、旋转图标、禁用交互和辅助文案,保证状态完整。
|
||||
4. 保持当前卡片、趋势图与系统面板的数据结构不变,只增强顶部操作层。
|
||||
|
||||
### 影响范围
|
||||
```yaml
|
||||
涉及模块:
|
||||
- admin-frontend/src/views/dashboard/DashboardView.vue
|
||||
- .helloagents/CHANGELOG.md
|
||||
- .helloagents/modules/admin-frontend.md
|
||||
预计变更文件: 3
|
||||
```
|
||||
|
||||
### 风险评估
|
||||
| 风险 | 等级 | 应对 |
|
||||
|------|------|------|
|
||||
| Hero 区新增操作后破坏原有视觉平衡 | 中 | 采用胶囊按钮、弱对比边框和状态副文案,保持 Apple 风格节奏 |
|
||||
| 刷新逻辑重复触发导致请求堆叠 | 中 | 刷新中禁用按钮,并复用现有 loading 状态 |
|
||||
| 用户中途要求停止 playwright-cli,运行态截图验收受限 | 中 | 改为构建验证 + 结构化代码视觉自检,并记录为本轮视觉验收证据 |
|
||||
|
||||
---
|
||||
|
||||
## 3. 核心场景
|
||||
|
||||
### 场景: 管理员手动刷新仪表盘
|
||||
**模块**: DashboardView
|
||||
**条件**: 管理员已进入 `/dashboard`
|
||||
**行为**: 点击 Hero 区“刷新全部数据”按钮
|
||||
**结果**: 页面统一刷新统计卡、趋势、排行和系统状态,并反馈最新同步状态
|
||||
|
||||
---
|
||||
|
||||
## 4. 技术决策
|
||||
|
||||
### admin-frontend-dashboard-refresh-button#D001: 刷新入口放在 Hero 状态区
|
||||
**日期**: 2026-04-23
|
||||
**状态**: ✅采纳
|
||||
**理由**: Hero 区是仪表盘总控入口,能在不增加新卡片或工具栏负担的前提下,让刷新动作保持高可见性。
|
||||
|
||||
### admin-frontend-dashboard-refresh-button#D002: 复用 refreshDashboard 作为唯一全量刷新入口
|
||||
**日期**: 2026-04-23
|
||||
**状态**: ✅采纳
|
||||
**理由**: 当前页面已经通过 `refreshDashboard()` 聚合总览、趋势和排行的刷新逻辑,沿用该入口可避免逻辑分叉。
|
||||
+54
@@ -0,0 +1,54 @@
|
||||
# 任务清单: admin-frontend-dashboard-refresh-button
|
||||
|
||||
> **@status:** completed | 2026-04-23 15:43
|
||||
|
||||
```yaml
|
||||
@feature: admin-frontend-dashboard-refresh-button
|
||||
@created: 2026-04-23
|
||||
@status: completed
|
||||
@mode: R3
|
||||
```
|
||||
|
||||
## 进度概览
|
||||
|
||||
| 完成 | 失败 | 跳过 | 总数 |
|
||||
|------|------|------|------|
|
||||
| 4 | 0 | 0 | 4 |
|
||||
|
||||
---
|
||||
|
||||
## 任务列表
|
||||
|
||||
### 1. 方案与范围
|
||||
|
||||
- [√] 1.1 锁定刷新范围为整页全量刷新,并确认 Hero 区为按钮落点 | depends_on: []
|
||||
|
||||
### 2. 仪表盘实现
|
||||
|
||||
- [√] 2.1 在 `admin-frontend/src/views/dashboard/DashboardView.vue` 中增加 Hero 区全量刷新按钮与状态文案 | depends_on: [1.1]
|
||||
- [√] 2.2 在 `admin-frontend/src/views/dashboard/DashboardView.vue` 中补齐最后刷新时间、加载反馈与防重复触发逻辑 | depends_on: [2.1]
|
||||
|
||||
### 3. 验证与同步
|
||||
|
||||
- [√] 3.1 运行 `npm run build` 验证 `admin-frontend` 构建通过 | depends_on: [2.1,2.2]
|
||||
- [√] 3.2 完成本地视觉验收并同步知识库变更记录 | depends_on: [3.1]
|
||||
|
||||
---
|
||||
|
||||
## 执行日志
|
||||
|
||||
| 时间 | 任务 | 状态 | 备注 |
|
||||
|------|------|------|------|
|
||||
| 2026-04-23 15:15 | 方案包初始化 | completed | 已锁定整页全量刷新范围与 Apple 风格约束 |
|
||||
| 2026-04-23 15:24 | 2.1 / 2.2 | completed | 已在 Hero 区加入全量刷新按钮、最后刷新时间与加载反馈 |
|
||||
| 2026-04-23 15:26 | 3.1 | completed | `npm run build` 通过 |
|
||||
| 2026-04-23 15:42 | 3.2 | completed | 按用户要求停止 playwright-cli,改用结构化代码视觉自检并完成知识库同步 |
|
||||
|
||||
---
|
||||
|
||||
## 执行备注
|
||||
|
||||
> 记录执行过程中的重要说明、决策变更、风险提示等
|
||||
|
||||
- 本轮只增强仪表盘顶部操作层,不改动后端接口契约和图表数据结构。
|
||||
- 运行态视觉验收原计划使用浏览器自动化,但用户中途明确要求“不再运行 playwright-cli”,因此改为基于构建结果和代码结构的视觉自检。
|
||||
+11
@@ -0,0 +1,11 @@
|
||||
{
|
||||
"status": "completed",
|
||||
"completed": 4,
|
||||
"failed": 0,
|
||||
"pending": 0,
|
||||
"total": 4,
|
||||
"done": 4,
|
||||
"percent": 100,
|
||||
"current": "Dashboard 收入趋势金额/数量切换已完成,待归档",
|
||||
"updated_at": "2026-04-23 23:20:00"
|
||||
}
|
||||
+98
@@ -0,0 +1,98 @@
|
||||
# 变更提案: admin-frontend-dashboard-trend-count-toggle
|
||||
|
||||
## 元信息
|
||||
```yaml
|
||||
类型: 功能增强
|
||||
方案类型: implementation
|
||||
优先级: P1
|
||||
状态: 执行中
|
||||
创建: 2026-04-23
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 1. 需求
|
||||
|
||||
### 背景
|
||||
当前 `admin-frontend` 仪表盘的“收入趋势”模块仅支持按金额查看趋势线。用户希望在不破坏现有 Apple 风格页面结构的前提下,补充“按数量”视角,让管理员在同一图表区域中切换查看订单数量走势。
|
||||
|
||||
### 目标
|
||||
- 在 `admin-frontend/src/views/dashboard/DashboardView.vue` 的趋势面板中新增“金额 / 数量”切换。
|
||||
- 切换到“数量”后,图表 Y 轴、摘要卡片与最近记录同步以订单数量为主展示。
|
||||
- 保持 `apple/DESIGN.md` 的 Apple 风格约束:纯色分区、单一强调蓝、克制交互和低装饰噪音。
|
||||
|
||||
### 约束条件
|
||||
```yaml
|
||||
范围约束: 仅调整 admin-frontend 仪表盘趋势模块及其图表工具逻辑
|
||||
视觉约束: 延续 Apple 风格,不引入双图、双线、多色复杂图例
|
||||
技术约束: 不新增图表库,继续复用现有 SVG 图表实现
|
||||
业务约束: 不修改后端接口,前端基于现有趋势返回字段实现切换
|
||||
```
|
||||
|
||||
### 验收标准
|
||||
- [ ] 趋势面板新增“按金额 / 按数量”切换,默认保持“按金额”。
|
||||
- [ ] 切换到“按数量”时,图表线条、Y 轴标签、摘要卡片和最近记录与数量口径一致。
|
||||
- [ ] 视觉样式仍符合 `apple/DESIGN.md`,新增交互保持克制、清晰、可访问。
|
||||
- [ ] `admin-frontend` 构建通过,产物成功输出到 `public/assets/admin`。
|
||||
|
||||
---
|
||||
|
||||
## 2. 方案
|
||||
|
||||
### 技术方案
|
||||
1. 在 `src/utils/dashboard.ts` 中把趋势图构建逻辑参数化,支持金额/数量两种指标,并根据口径生成对应的 Y 轴标签格式。
|
||||
2. 在 `src/views/dashboard/DashboardView.vue` 中新增趋势显示模式状态、切换按钮和摘要视图模型。
|
||||
3. 保持现有 `getOrderTrend` 接口调用方式,直接复用响应中的 `paid_total`、`paid_count`、`commission_total`、`commission_count` 等字段完成数量视图。
|
||||
|
||||
### 影响范围
|
||||
```yaml
|
||||
涉及模块:
|
||||
- admin-frontend/src/views/dashboard/DashboardView.vue
|
||||
- admin-frontend/src/utils/dashboard.ts
|
||||
- public/assets/admin (构建产物输出)
|
||||
预计变更文件: 2-4
|
||||
```
|
||||
|
||||
### 风险评估
|
||||
| 风险 | 等级 | 应对 |
|
||||
|------|------|------|
|
||||
| 数量视图摘要语义不清 | 中 | 采用“成交订单 / 佣金订单 / 日均成交”三段式摘要,并保留金额作为辅助信息 |
|
||||
| 图表参数化后影响原金额模式 | 中 | 默认金额模式不变,并通过构建验证确保类型与模板连接正确 |
|
||||
| 子模块产物状态与根仓状态不同步 | 中 | 构建后同时检查根仓与 `public/assets/admin` 子模块状态 |
|
||||
|
||||
---
|
||||
|
||||
## 3. 成果设计
|
||||
|
||||
### 设计方向
|
||||
- **美学基调**: 延续当前 Apple 风格的浅灰内容面板 + 单一蓝色交互重点。
|
||||
- **交互模式**: 在现有时间筛选旁新增一组低干扰 segmented pills,用于切换“按金额 / 按数量”。
|
||||
- **记忆点**: 同一张克制的趋势图,在不增加视觉负担的情况下完成经营口径切换。
|
||||
|
||||
### 视觉要素
|
||||
- **配色**: 继续使用 `#0071e3` 作为唯一强调色;背景和卡片保持 `#ffffff / #f5f5f7 / #fbfbfd` 层次。
|
||||
- **排版**: 不新增标题层级,切换器作为次级控制区,与时间范围筛选并列。
|
||||
- **状态**: 激活态用浅蓝底 + 浅蓝边框,未激活态保持白底细边框。
|
||||
|
||||
### 实施结果
|
||||
- 已在趋势面板头部增加独立的“按金额 / 按数量”切换分组。
|
||||
- 已将趋势图 SVG 构建逻辑扩展为双口径模式,数量模式下自动切换 Y 轴标签为“笔”。
|
||||
- 已将摘要卡片和最近记录改为跟随当前口径同步展示。
|
||||
|
||||
---
|
||||
|
||||
## 4. 技术决策
|
||||
|
||||
### admin-frontend-dashboard-trend-count-toggle#D001: 采用单图切换而不是双图/双线
|
||||
**日期**: 2026-04-23
|
||||
**状态**: ✅采纳
|
||||
**背景**: 用户在确认环节明确选择“金额 / 数量切换”方案。
|
||||
**决策**: 在同一趋势图区域中,通过切换按钮切换图表口径和摘要信息。
|
||||
**理由**: 该方案最符合 Apple 风格的克制表达,同时不会显著增加页面密度。
|
||||
|
||||
### admin-frontend-dashboard-trend-count-toggle#D002: 数量模式复用现有接口字段,不新增后端联调
|
||||
**日期**: 2026-04-23
|
||||
**状态**: ✅采纳
|
||||
**背景**: 现有趋势接口已返回 `paid_count` 和 `commission_count` 等字段。
|
||||
**决策**: 前端直接基于现有响应切换图表指标和摘要视图。
|
||||
**理由**: 可以在最小范围内完成需求,避免扩展后端接口或引入新请求。
|
||||
+49
@@ -0,0 +1,49 @@
|
||||
# 任务清单: admin-frontend-dashboard-trend-count-toggle
|
||||
|
||||
> **@status:** completed | 2026-04-23 23:20
|
||||
|
||||
```yaml
|
||||
@feature: admin-frontend-dashboard-trend-count-toggle
|
||||
@created: 2026-04-23
|
||||
@status: completed
|
||||
@mode: R2
|
||||
```
|
||||
|
||||
## 进度概览
|
||||
|
||||
| 完成 | 失败 | 跳过 | 总数 |
|
||||
|------|------|------|------|
|
||||
| 4 | 0 | 0 | 4 |
|
||||
|
||||
---
|
||||
|
||||
## 任务列表
|
||||
|
||||
### 1. 趋势图模式切换
|
||||
|
||||
- [√] 1.1 在 `admin-frontend/src/utils/dashboard.ts` 中扩展趋势图构建逻辑,支持金额/数量双口径 | depends_on: []
|
||||
- [√] 1.2 在 `admin-frontend/src/views/dashboard/DashboardView.vue` 中加入“按金额 / 按数量”切换和对应摘要展示 | depends_on: [1.1]
|
||||
|
||||
### 2. 验证与产物
|
||||
|
||||
- [√] 2.1 运行 `admin-frontend` 构建验证,确认类型检查和 Vite 构建通过 | depends_on: [1.2]
|
||||
- [√] 2.2 复核根仓与 `public/assets/admin` 子模块状态,确保产物变更可见 | depends_on: [2.1]
|
||||
|
||||
---
|
||||
|
||||
## 执行日志
|
||||
|
||||
| 时间 | 任务 | 状态 | 备注 |
|
||||
|------|------|------|------|
|
||||
| 2026-04-23 23:13 | 方案包初始化 | completed | 已确认采用“金额 / 数量切换”并进入实现 |
|
||||
| 2026-04-23 23:17 | 1.1 / 1.2 | completed | 已完成趋势图双口径切换、摘要卡片和最近记录联动 |
|
||||
| 2026-04-23 23:20 | 2.1 / 2.2 | completed | `npm run build` 通过,根仓与 `public/assets/admin` 子模块均检测到产物变更 |
|
||||
|
||||
---
|
||||
|
||||
## 执行备注
|
||||
|
||||
> 记录执行过程中的重要说明、决策变更、风险提示等
|
||||
|
||||
- 当前仓已有一个未完成的旧方案包 `202604210515_admin-frontend-ticket-management`,本轮不复用其模板内容,单独创建新方案包以避免混淆。
|
||||
- 由于 `public/assets/admin` 是独立子模块,构建后前端产物变更主要体现在子模块工作区;根仓继续显示 `m public/assets/admin` 属于正常现象。
|
||||
+11
@@ -0,0 +1,11 @@
|
||||
{
|
||||
"status": "completed",
|
||||
"completed": 4,
|
||||
"failed": 0,
|
||||
"pending": 0,
|
||||
"total": 4,
|
||||
"done": 4,
|
||||
"percent": 100,
|
||||
"current": "排行面板 10/20 切换与滚动容器已完成,等待归档",
|
||||
"updated_at": "2026-04-23 23:38:00"
|
||||
}
|
||||
+92
@@ -0,0 +1,92 @@
|
||||
# 变更提案: admin-frontend-rank-limit-scroll
|
||||
|
||||
## 元信息
|
||||
```yaml
|
||||
类型: 功能增强
|
||||
方案类型: implementation
|
||||
优先级: P1
|
||||
状态: 已完成
|
||||
创建: 2026-04-23
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 1. 需求
|
||||
|
||||
### 背景
|
||||
当前 `admin-frontend` 仪表盘中的“节点流量排行”和“用户流量排行”都固定只显示前 6 条,列表区域也会随着内容高度自然撑开。用户希望在不破坏现有 Apple 风格基线的前提下,让两个排行面板都支持 `10 个 / 20 个` 显示切换,并将排行内容放进可滚动的展示区域,避免页面被长列表拉得过高。
|
||||
|
||||
### 目标
|
||||
- 在 `admin-frontend/src/views/dashboard/DashboardView.vue` 的两个流量排行面板中新增 `10 个 / 20 个` 显示数量切换。
|
||||
- 让节点排行和用户排行都支持独立控制显示数量,并在列表较长时使用固定高度滚动区域承载内容。
|
||||
- 延续 `apple/DESIGN.md` 的 Apple 风格:纯色分区、单一蓝色强调、低装饰噪音、清晰可访问的按钮状态。
|
||||
|
||||
### 约束条件
|
||||
```yaml
|
||||
范围约束: 仅调整 admin-frontend 仪表盘排行面板的交互和样式,不改后端接口
|
||||
视觉约束: 保持 Apple 风格,不引入表格化重组件或高密度控制栏
|
||||
技术约束: 继续复用现有 Vue3 + TypeScript + Element Plus + 原生样式体系
|
||||
工作树约束: 保留当前未提交的趋势图口径切换改动,在其基础上完成本轮排行增强
|
||||
```
|
||||
|
||||
### 验收标准
|
||||
- [ ] “节点流量排行”和“用户流量排行”均提供 `10 个 / 20 个` 数量切换。
|
||||
- [ ] 切换后列表展示条数与选择一致,且面板内容区域保持可滚动,不因为长列表破坏整体布局。
|
||||
- [ ] 新增交互仍符合 `apple/DESIGN.md` 的视觉基线,并具备可见焦点与明确激活态。
|
||||
- [ ] `admin-frontend` 构建通过,根仓与 `public/assets/admin` 子模块状态可见。
|
||||
|
||||
---
|
||||
|
||||
## 2. 方案
|
||||
|
||||
### 技术方案
|
||||
1. 在 `DashboardView.vue` 中新增节点排行和用户排行各自的显示条数状态,并通过计算属性统一产出当前应渲染的列表。
|
||||
2. 在排行面板头部保留现有时间范围筛选,同时补充轻量级 segmented pills 作为 `10 / 20` 显示数量切换控件。
|
||||
3. 为排行列表增加固定高度滚动容器、轻量滚动条样式和面板内边距节奏,让 20 条模式下仍维持 Apple 风格的整洁感。
|
||||
|
||||
### 影响范围
|
||||
```yaml
|
||||
涉及模块:
|
||||
- admin-frontend/src/views/dashboard/DashboardView.vue
|
||||
- public/assets/admin (构建产物输出)
|
||||
预计变更文件: 1-3
|
||||
```
|
||||
|
||||
### 风险评估
|
||||
| 风险 | 等级 | 应对 |
|
||||
|------|------|------|
|
||||
| 排行面板头部控件过多导致拥挤 | 中 | 把时间筛选与数量筛选分成两组,保持同一视觉语言但明确主次 |
|
||||
| 滚动容器高度不合适影响信息密度 | 中 | 采用按 10/20 模式自适应的最大高度,同时在移动端回退为更紧凑布局 |
|
||||
| 当前工作树已有趋势图增强改动 | 中 | 在现有未提交改动上增量实现,并通过构建验证确认两项增强可同时成立 |
|
||||
|
||||
---
|
||||
|
||||
## 3. 成果设计
|
||||
|
||||
### 设计方向
|
||||
- **美学基调**: 延续当前 Apple 风格浅色信息面板,让排行区域像可浏览的信息胶囊,而不是后台表格。
|
||||
- **交互模式**: 时间范围和显示数量都使用 pill 按钮;数量按钮作为次级控制,保持克制但清晰。
|
||||
- **记忆点**: 同一个排行面板中,长列表被收进柔和滚动视窗,滚动时仍保持整洁的白底与单一蓝色强调。
|
||||
|
||||
### 视觉要素
|
||||
- **配色**: 沿用 `#0071e3` 作为唯一强调色,滚动容器背景继续使用 `#fbfbfd` / `#ffffff` 层次。
|
||||
- **排版**: 面板头部分成信息区与控件区,控件区按分组排列;列表内部继续保留名称、流量值、蓝色进度条和涨跌百分比。
|
||||
- **状态**: 激活态为浅蓝底 + 浅蓝边框;滚动条使用低对比灰蓝色,避免视觉噪音。
|
||||
|
||||
---
|
||||
|
||||
## 4. 技术决策
|
||||
|
||||
### admin-frontend-rank-limit-scroll#D001: 两个排行面板独立控制显示数量
|
||||
**日期**: 2026-04-23
|
||||
**状态**: ✅采纳
|
||||
**背景**: 节点排行和用户排行虽然共享时间范围,但使用场景不同,用户可能需要分别查看不同数量。
|
||||
**决策**: 节点排行与用户排行分别维护自己的 `10 / 20` 数量切换状态。
|
||||
**理由**: 这样不会把两个排行耦合成单一控制,也更贴合面板级交互。
|
||||
|
||||
### admin-frontend-rank-limit-scroll#D002: 使用固定高度滚动容器而不是整页自然拉伸
|
||||
**日期**: 2026-04-23
|
||||
**状态**: ✅采纳
|
||||
**背景**: 20 条排行如果完全展开,会让 dashboard 纵向长度显著增加,破坏当前首页节奏。
|
||||
**决策**: 在排行面板内引入滚动容器,并按 10/20 模式设置不同的最大高度。
|
||||
**理由**: 能在保留更多信息的同时维持 Apple 风格的页面节奏和阅读效率。
|
||||
@@ -0,0 +1,49 @@
|
||||
# 任务清单: admin-frontend-rank-limit-scroll
|
||||
|
||||
> **@status:** completed | 2026-04-23 23:38
|
||||
|
||||
```yaml
|
||||
@feature: admin-frontend-rank-limit-scroll
|
||||
@created: 2026-04-23
|
||||
@status: completed
|
||||
@mode: R3
|
||||
```
|
||||
|
||||
## 进度概览
|
||||
|
||||
| 完成 | 失败 | 跳过 | 总数 |
|
||||
|------|------|------|------|
|
||||
| 4 | 0 | 0 | 4 |
|
||||
|
||||
---
|
||||
|
||||
## 任务列表
|
||||
|
||||
### 1. 排行交互增强
|
||||
|
||||
- [√] 1.1 在 `admin-frontend/src/views/dashboard/DashboardView.vue` 中新增节点排行和用户排行的 `10 / 20` 显示数量状态与计算视图 | depends_on: []
|
||||
- [√] 1.2 在 `admin-frontend/src/views/dashboard/DashboardView.vue` 中为两个排行面板加入数量切换控件,并调整头部布局 | depends_on: [1.1]
|
||||
- [√] 1.3 在 `admin-frontend/src/views/dashboard/DashboardView.vue` 中加入滚动容器和 Apple 风格滚动条样式 | depends_on: [1.2]
|
||||
|
||||
### 2. 验证与状态
|
||||
|
||||
- [√] 2.1 运行 `admin-frontend` 构建验证,并确认根仓与 `public/assets/admin` 子模块状态 | depends_on: [1.3]
|
||||
|
||||
---
|
||||
|
||||
## 执行日志
|
||||
|
||||
| 时间 | 任务 | 状态 | 备注 |
|
||||
|------|------|------|------|
|
||||
| 2026-04-23 23:18 | 方案包初始化 | completed | 已确认在 Apple 风格基线上为两个排行面板增加 10/20 切换和滚动容器 |
|
||||
| 2026-04-23 23:31 | 1.1 / 1.2 / 1.3 | completed | 已为两个排行面板补齐 10/20 切换、独立显示状态和滚动容器样式 |
|
||||
| 2026-04-23 23:37 | 2.1 | completed | `npm run build` 通过;浏览器直达 `/dashboard` 会因未提供管理员登录态跳转到 `/#/login?redirect=/dashboard` |
|
||||
|
||||
---
|
||||
|
||||
## 执行备注
|
||||
|
||||
> 记录执行过程中的重要说明、决策变更、风险提示等
|
||||
|
||||
- 当前工作树已存在一个未完成的趋势图口径切换方案包 `202604232313_admin-frontend-dashboard-trend-count-toggle`,本轮在保留其代码改动的前提下继续增强 dashboard 排行区域。
|
||||
- 本轮视觉联调受本地管理员登录态限制,已通过构建、代码级 UI 自检和浏览器路由快照完成兜底验证。
|
||||
+51
@@ -0,0 +1,51 @@
|
||||
{
|
||||
"updatedAt": "2026-04-23T15:23:18.713Z",
|
||||
"version": 1,
|
||||
"source": "~auto",
|
||||
"originCommand": "plan",
|
||||
"verifyMode": "review-first",
|
||||
"reviewerFocus": [
|
||||
"节点管理侧边栏分组是否清晰且与现有 Apple 风格后台一致",
|
||||
"未实现的创建/排序能力是否被透明标注为后续接入"
|
||||
],
|
||||
"testerFocus": [
|
||||
"节点列表是否真实连接 /server/manage/getNodes 与 /server/group/fetch",
|
||||
"搜索、类型筛选、权限组筛选与显隐切换是否存在真实数据流",
|
||||
"节点相关新路由是否可以正常进入"
|
||||
],
|
||||
"ui": {
|
||||
"required": true,
|
||||
"designContract": true,
|
||||
"sourcePriority": [
|
||||
"plan.md",
|
||||
".helloagents/DESIGN.md",
|
||||
"hello-ui"
|
||||
],
|
||||
"styleAdvisor": {
|
||||
"required": false,
|
||||
"reason": "",
|
||||
"focus": []
|
||||
},
|
||||
"visualValidation": {
|
||||
"required": true,
|
||||
"reason": "节点管理属于整页新建后台视图,需要确认导航、列表密度与占位页结构在浏览器中符合 Apple 风格契约",
|
||||
"screens": [
|
||||
"#/nodes desktop",
|
||||
"#/node-groups desktop",
|
||||
"#/node-routes desktop"
|
||||
],
|
||||
"states": [
|
||||
"节点列表默认加载完成态",
|
||||
"节点列表筛选结果态",
|
||||
"权限组管理占位态",
|
||||
"路由管理占位态"
|
||||
]
|
||||
}
|
||||
},
|
||||
"advisor": {
|
||||
"required": false,
|
||||
"reason": "",
|
||||
"focus": [],
|
||||
"preferredSources": []
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,54 @@
|
||||
# admin-frontend 节点管理首批交付 — 实施规划
|
||||
|
||||
## 目标与范围
|
||||
- 为 `admin-frontend` 增加节点管理信息架构,并先交付“节点管理”主页面。
|
||||
- 页面目标不是一次性做完整节点中后台,而是先打通“可看、可筛、可切显隐、可做基础行级操作”的运营主链路。
|
||||
|
||||
## 架构与实现策略
|
||||
- 在现有 `AdminLayout` 基础上新增“节点管理”二级分组,保持侧边栏结构统一。
|
||||
- 新增 `/nodes`、`/node-groups`、`/node-routes` 三个路由,其中 `/nodes` 为真实功能页,其余两页为明确占位页。
|
||||
- 节点列表页直接消费现有后端接口,不在前端猜测或重塑接口契约:
|
||||
- `/server/manage/getNodes`
|
||||
- `/server/group/fetch`
|
||||
- `/server/manage/update`
|
||||
- `/server/manage/copy`
|
||||
- `/server/manage/drop`
|
||||
- 复杂的节点格式化逻辑(地址、状态、标签、筛选选项)下沉到 `utils/nodes.ts`,避免页面组件膨胀。
|
||||
|
||||
## 完成定义
|
||||
- 侧边栏出现“节点管理”分组,且可以进入 3 个子入口。
|
||||
- `/nodes` 页面可真实拉取节点与权限组数据。
|
||||
- 用户可以通过搜索、节点类型和权限组筛选列表。
|
||||
- 用户可以切换节点显隐状态,并在界面中获得成功/失败反馈。
|
||||
- 用户可以通过更多菜单执行复制节点与删除节点;未覆盖的编辑/排序功能有明确边界提示。
|
||||
- 验证主路径:`review-first`
|
||||
- reviewer 关注边界:导航结构是否清晰、页面是否与 Apple 风格一致、未实现功能是否被透明标注。
|
||||
- tester 关注边界:构建是否通过、节点列表是否真实连接 API、筛选与显隐切换是否存在数据流。
|
||||
|
||||
## 文件结构
|
||||
- `admin-frontend/src/router/index.ts`
|
||||
- `admin-frontend/src/layouts/AdminLayout.vue`
|
||||
- `admin-frontend/src/api/admin.ts`
|
||||
- `admin-frontend/src/types/api.d.ts`
|
||||
- `admin-frontend/src/utils/nodes.ts`(新增)
|
||||
- `admin-frontend/src/views/nodes/NodesView.vue`(新增)
|
||||
- `admin-frontend/src/views/nodes/NodeGroupsView.vue`(新增)
|
||||
- `admin-frontend/src/views/nodes/NodeRoutesView.vue`(新增)
|
||||
|
||||
## UI / 设计约束
|
||||
- 节点管理首页保留黑色 hero + 白色表格壳层的 Apple 后台节奏。
|
||||
- 过滤器采用紧凑 pill / select 混合布局,优先满足快速运营判断。
|
||||
- 列表状态用圆点、标签和辅助文字三层表达,不只靠颜色。
|
||||
- 占位页不做空白页,而是交付可继续扩展的结构化提示页。
|
||||
|
||||
## 风险与验证
|
||||
- 风险 1:后端节点字段可能存在空值或差异,页面要做健壮格式化。
|
||||
- 风险 2:节点显隐切换的字段是 `show`,前端需保持与布尔/整型兼容。
|
||||
- 风险 3:权限组接口若返回结构偏轻,前端需要容错处理。
|
||||
- 验证方式:
|
||||
- `npm run build`
|
||||
- 本地预览 + 浏览器检查 `/nodes`、`/node-groups`、`/node-routes`
|
||||
|
||||
## 决策记录
|
||||
- [2026-04-23] 节点管理首批交付聚焦列表运营链路,不在本轮接入完整节点编辑表单,避免 UI 范围失控。
|
||||
- [2026-04-23] 权限组管理 / 路由管理先交付占位页,保证侧边栏信息架构先稳定下来。
|
||||
+37
@@ -0,0 +1,37 @@
|
||||
# admin-frontend 节点管理首批交付 — 需求
|
||||
|
||||
确认后冻结,执行阶段不可修改。如需变更必须回到设计阶段重新确认。
|
||||
|
||||
## 核心目标
|
||||
- 在 `admin-frontend` 中新增“节点管理”侧边栏分组。
|
||||
- 优先实现“节点管理”主页面,使管理者可以在 Apple 风格后台中查看、搜索、筛选和执行基础节点操作。
|
||||
- 页面视觉以 `apple/DESIGN.md` 为参考,并与现有 Apple 化仪表盘、用户管理、工单管理保持一致。
|
||||
|
||||
## 功能边界
|
||||
- 必须新增节点管理分组,包含:节点管理、权限组管理、路由管理 3 个入口。
|
||||
- 必须实现“节点管理”列表页,覆盖:
|
||||
- 节点列表拉取
|
||||
- 关键字段展示(节点 ID、显隐、节点、地址、在线人数、倍率、权限组)
|
||||
- 搜索
|
||||
- 类型筛选
|
||||
- 权限组筛选
|
||||
- 显隐切换
|
||||
- 行级更多操作菜单
|
||||
- 权限组管理、路由管理本轮只要求提供结构化占位页,为下一轮真实接入留入口。
|
||||
|
||||
## 非目标
|
||||
- 本轮不实现完整的节点创建 / 编辑大表单。
|
||||
- 本轮不实现拖拽排序或完整排序编辑器。
|
||||
- 本轮不重做后端接口,不新增 Laravel 管理端 API。
|
||||
|
||||
## 技术约束
|
||||
- 技术栈固定为 `Vue 3 + TypeScript + Vite + Element Plus`。
|
||||
- 后端真相源以现有 Laravel 管理接口为准,节点列表使用 `/server/manage/getNodes`。
|
||||
- 视觉契约优先级:本方案 > `.helloagents/DESIGN.md` > `apple/DESIGN.md` 的参考原则。
|
||||
- 构建验证使用 `admin-frontend/package.json` 中已有 `npm run build`。
|
||||
|
||||
## 质量要求
|
||||
- 页面必须保持 Apple 风格的一致性和高密度运营后台可读性。
|
||||
- 异步列表必须覆盖加载、空和错误反馈。
|
||||
- 危险操作要有确认提示。
|
||||
- 最终至少完成一次构建验证与一次浏览器级视觉验收。
|
||||
@@ -0,0 +1,13 @@
|
||||
# admin-frontend 节点管理首批交付 — 任务分解
|
||||
|
||||
## 任务列表
|
||||
- [x] 任务1:补齐本轮 UI 契约与方案产物(涉及文件:`.helloagents/DESIGN.md`、`.helloagents/plans/202604232320_admin-frontend-node-management/*`;完成标准:存在可执行需求、方案、任务与合同文件;验证方式:文件检查)
|
||||
- [x] 任务2:扩展后台导航与路由结构(涉及文件:`admin-frontend/src/router/index.ts`、`admin-frontend/src/layouts/AdminLayout.vue`;完成标准:侧边栏出现节点管理分组并可进入 3 个子页面;验证方式:`npm run build` + 浏览器检查导航)
|
||||
- [x] 任务3:接入节点管理数据模型与 API(涉及文件:`admin-frontend/src/api/admin.ts`、`admin-frontend/src/types/api.d.ts`、`admin-frontend/src/utils/nodes.ts`;完成标准:前端可拉取节点与权限组并完成必要格式化;验证方式:`npm run build`)
|
||||
- [x] 任务4:实现节点管理主页面(涉及文件:`admin-frontend/src/views/nodes/NodesView.vue`;完成标准:节点列表具备搜索、筛选、显隐切换、复制/删除基础能力,并覆盖加载/空/错误状态;验证方式:`npm run build` + 浏览器检查 `/nodes`)
|
||||
- [x] 任务5:实现权限组 / 路由管理占位页(涉及文件:`admin-frontend/src/views/nodes/NodeGroupsView.vue`、`admin-frontend/src/views/nodes/NodeRoutesView.vue`;完成标准:可从侧边栏进入,页面明确说明下一阶段接入范围;验证方式:`npm run build` + 浏览器检查对应路由)
|
||||
- [x] 任务6:完成验证、视觉验收与知识库同步(涉及文件:`.helloagents/CHANGELOG.md`、`.helloagents/.ralph-visual.json`、`.helloagents/.ralph-closeout.json`;完成标准:构建通过、视觉检查完成、知识库记录本轮变更;验证方式:命令输出 + 证据文件)
|
||||
|
||||
## 进度
|
||||
- [x] 已创建方案包并冻结首批交付范围。
|
||||
- [x] 已完成 admin-frontend 节点管理首批页面与知识库同步。
|
||||
+55
@@ -0,0 +1,55 @@
|
||||
{
|
||||
"updatedAt": "2026-04-23T15:35:17.621Z",
|
||||
"version": 1,
|
||||
"source": "~auto",
|
||||
"originCommand": "plan",
|
||||
"verifyMode": "review-first",
|
||||
"reviewerFocus": [
|
||||
"系统管理侧边栏分组是否清晰且与现有 Apple 风格后台一致",
|
||||
"系统配置页的左侧分组导航与右侧长表单结构是否清晰可读",
|
||||
"其余系统管理入口是否被透明标注为后续接入"
|
||||
],
|
||||
"testerFocus": [
|
||||
"系统管理新路由是否可以正常进入",
|
||||
"系统配置页是否真实连接 /config/fetch 与 /config/save",
|
||||
"保存反馈与辅助按钮是否存在真实数据流"
|
||||
],
|
||||
"ui": {
|
||||
"required": true,
|
||||
"designContract": true,
|
||||
"sourcePriority": [
|
||||
"plan.md",
|
||||
".helloagents/DESIGN.md",
|
||||
"hello-ui"
|
||||
],
|
||||
"styleAdvisor": {
|
||||
"required": false,
|
||||
"reason": "",
|
||||
"focus": []
|
||||
},
|
||||
"visualValidation": {
|
||||
"required": true,
|
||||
"reason": "系统管理属于整页新建后台视图,需要确认导航、系统配置长表单层级与占位页结构在浏览器中符合 Apple 风格契约",
|
||||
"screens": [
|
||||
"#/system/config desktop",
|
||||
"#/system/plugins desktop",
|
||||
"#/system/themes desktop",
|
||||
"#/system/notices desktop",
|
||||
"#/system/payments desktop",
|
||||
"#/system/knowledge desktop"
|
||||
],
|
||||
"states": [
|
||||
"系统配置默认加载完成态",
|
||||
"系统配置保存态",
|
||||
"系统配置错误/重试态",
|
||||
"系统模块占位态"
|
||||
]
|
||||
}
|
||||
},
|
||||
"advisor": {
|
||||
"required": false,
|
||||
"reason": "",
|
||||
"focus": [],
|
||||
"preferredSources": []
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,63 @@
|
||||
# admin-frontend 系统管理首批交付 — 实施规划
|
||||
|
||||
## 目标与范围
|
||||
- 为 `admin-frontend` 增加“系统管理”信息架构,并先交付“系统配置”主页面。
|
||||
- 页面目标不是一次性做完整后台系统中心,而是先打通“可进入、可读取、可编辑、可保存”的配置主链路,同时把其余 5 个系统管理入口先稳定为可访问占位页。
|
||||
|
||||
## 架构与实现策略
|
||||
- 在现有 `AdminLayout` 基础上新增“系统管理”二级分组,保持侧边栏结构统一。
|
||||
- 新增以下路由:
|
||||
- `/system/config` 为真实功能页
|
||||
- `/system/plugins`
|
||||
- `/system/themes`
|
||||
- `/system/notices`
|
||||
- `/system/payments`
|
||||
- `/system/knowledge`
|
||||
- 系统配置页直接消费现有后端接口,不在前端猜测或重塑接口契约:
|
||||
- `/config/fetch`
|
||||
- `/config/save`
|
||||
- `/config/testSendMail`
|
||||
- `/config/setTelegramWebhook`
|
||||
- 配置字段分组、控件元信息与序列化逻辑下沉到 `utils/systemConfig.ts`,避免页面组件膨胀。
|
||||
- 占位页使用统一的 `SystemPlaceholderView`,以一致的结构说明本轮范围与下一阶段扩展点。
|
||||
|
||||
## 完成定义
|
||||
- 侧边栏出现“系统管理”分组,且可以进入 6 个子入口。
|
||||
- `/system/config` 页面可真实拉取配置数据,并按 9 个配置分组组织内容。
|
||||
- 用户可以修改并保存系统配置,保存后获得成功/失败反馈。
|
||||
- 邮件设置与 Telegram 设置保留辅助动作入口(测试邮件 / 设置 Webhook),但不在本轮额外扩展复杂工作流。
|
||||
- 其余 5 个系统管理子页可从侧边栏正常进入,并明确标注“下一阶段接入”。
|
||||
- 验证主路径:`review-first`
|
||||
- reviewer 关注边界:系统管理信息架构是否清晰、系统配置表单层级是否贴近 Apple 风格后台、占位页是否透明说明未实现范围。
|
||||
- tester 关注边界:菜单与路由是否真实连通、系统配置页是否真实连接 `/config/fetch` 与 `/config/save`、保存链路与辅助按钮是否存在真实数据流。
|
||||
|
||||
## 文件结构
|
||||
- `admin-frontend/src/router/index.ts`
|
||||
- `admin-frontend/src/layouts/AdminLayout.vue`
|
||||
- `admin-frontend/src/api/admin.ts`
|
||||
- `admin-frontend/src/types/api.d.ts`
|
||||
- `admin-frontend/src/utils/systemConfig.ts`(新增)
|
||||
- `admin-frontend/src/views/system/SystemConfigView.vue`(新增)
|
||||
- `admin-frontend/src/views/system/SystemPlaceholderView.vue`(新增)
|
||||
- `.helloagents/DESIGN.md`
|
||||
|
||||
## UI / 设计约束
|
||||
- 系统配置首页保留黑色 hero + 白色配置壳层的 Apple 后台节奏。
|
||||
- 左侧使用紧凑分组导航,右侧使用连续表单 section,优先满足“快速定位配置块”的后台效率诉求。
|
||||
- 页面首屏只保留一个主保存动作和少量辅助描述,不堆砌营销式视觉元素。
|
||||
- 占位页不做空白页,而是交付可继续扩展的结构化提示页。
|
||||
|
||||
## 风险与验证
|
||||
- 风险 1:配置接口字段类型包含布尔、数值、数组和长文本,前端需要统一序列化与表单回填。
|
||||
- 风险 2:`/config/fetch` 返回分组对象,系统配置页必须避免直接把后端分组名暴露成低可读开发术语。
|
||||
- 风险 3:本地静态预览环境可能缺少 Laravel 注入或后台认证,浏览器验收要区分“结构验收”和“真实联调”边界。
|
||||
- 验证方式:
|
||||
- `npm run build`
|
||||
- 本地预览 + 浏览器检查 `#/system/config`
|
||||
- 浏览器检查 `#/system/plugins`、`#/system/themes`、`#/system/notices`、`#/system/payments`、`#/system/knowledge`
|
||||
|
||||
## 决策记录
|
||||
- [2026-04-23] 系统管理首批交付聚焦“系统配置真实页 + 其余入口占位页”,避免在一轮内同时展开多个 CRUD 模块。
|
||||
- [2026-04-23] “系统配置”保留左侧配置分组导航,优先满足后台场景中的长表单定位效率。
|
||||
- [2026-04-23] 前台主题相关配置不混入本轮系统配置页,而是留在“主题配置”入口的后续阶段实现。
|
||||
|
||||
+51
@@ -0,0 +1,51 @@
|
||||
# admin-frontend 系统管理首批交付 — 需求
|
||||
|
||||
确认后冻结,执行阶段不可修改。如需变更必须回到设计阶段重新确认。
|
||||
|
||||
## 核心目标
|
||||
- 在 `admin-frontend` 中新增“系统管理”一级侧边栏分组。
|
||||
- 优先实现“系统配置”页面,并尽量贴近用户提供的目标结构:左侧分组导航 + 右侧长表单编辑区。
|
||||
- 页面视觉以 `apple/DESIGN.md` 为参考,并与现有 Apple 化仪表盘、用户管理、工单管理保持同一后台设计语言。
|
||||
|
||||
## 功能边界
|
||||
- 必须新增系统管理分组,包含:
|
||||
- 系统配置
|
||||
- 插件管理
|
||||
- 主题配置
|
||||
- 公告管理
|
||||
- 支付配置
|
||||
- 知识库管理
|
||||
- 必须实现“系统配置”真实页面,覆盖:
|
||||
- 站点设置
|
||||
- 安全设置
|
||||
- 订阅设置
|
||||
- 邀请 & 佣金设置
|
||||
- 节点配置
|
||||
- 邮件设置
|
||||
- Telegram 设置
|
||||
- APP 设置
|
||||
- 订阅模板
|
||||
- “系统配置”必须接入现有 Laravel 管理接口的真实数据读取与保存链路。
|
||||
- 插件管理、主题配置、公告管理、支付配置、知识库管理本轮只要求提供结构化占位页,为下一轮真实接入留入口。
|
||||
|
||||
## 非目标
|
||||
- 本轮不实现插件、主题、公告、支付、知识库的完整 CRUD 页面。
|
||||
- 本轮不重做后端配置 API,不新增 Laravel 管理端接口。
|
||||
- 本轮不把前台主题配置混入“系统配置”页;主题能力保留在“主题配置”入口的后续阶段实现。
|
||||
|
||||
## 技术约束
|
||||
- 技术栈固定为 `Vue 3 + TypeScript + Vite + Element Plus`。
|
||||
- 后端真相源以现有 Laravel 管理接口为准,系统配置使用:
|
||||
- `GET /config/fetch`
|
||||
- `POST /config/save`
|
||||
- `POST /config/testSendMail`
|
||||
- `POST /config/setTelegramWebhook`
|
||||
- 视觉契约优先级:本方案 > `.helloagents/DESIGN.md` > `apple/DESIGN.md` 的参考原则。
|
||||
- 构建验证使用 `admin-frontend/package.json` 中已有 `npm run build`。
|
||||
|
||||
## 质量要求
|
||||
- 系统配置页必须保持 Apple 风格的一致性,并具备后台长表单的高可读性。
|
||||
- 异步页面必须覆盖加载、错误、保存成功与未修改状态反馈。
|
||||
- 表单交互需要明确区分主操作与辅助操作,避免一屏出现过多高强调按钮。
|
||||
- 最终至少完成一次构建验证与一次浏览器级视觉验收。
|
||||
|
||||
@@ -0,0 +1,13 @@
|
||||
# admin-frontend 系统管理首批交付 — 任务分解
|
||||
|
||||
## 任务列表
|
||||
- [x] 任务1:补齐本轮 UI 契约与方案产物(涉及文件:`.helloagents/DESIGN.md`、`.helloagents/plans/202604232329_admin-frontend-system-management/*`;完成标准:存在可执行需求、方案、任务与合同文件;验证方式:文件检查)
|
||||
- [x] 任务2:扩展后台导航与路由结构(涉及文件:`admin-frontend/src/router/index.ts`、`admin-frontend/src/layouts/AdminLayout.vue`;完成标准:侧边栏出现系统管理分组并可进入 6 个子页面;验证方式:`npm run build` + 浏览器检查导航)
|
||||
- [x] 任务3:接入系统配置数据模型与 API(涉及文件:`admin-frontend/src/api/admin.ts`、`admin-frontend/src/types/api.d.ts`、`admin-frontend/src/utils/systemConfig.ts`;完成标准:前端可拉取并保存系统配置,字段可完成必要的回填与序列化;验证方式:`npm run build`)
|
||||
- [x] 任务4:实现系统配置主页面(涉及文件:`admin-frontend/src/views/system/SystemConfigView.vue`;完成标准:页面具备 9 个配置分组、加载/错误/保存反馈、左侧导航与真实保存入口;验证方式:`npm run build` + 浏览器检查 `#/system/config`)
|
||||
- [x] 任务5:实现其余系统管理占位页(涉及文件:`admin-frontend/src/views/system/SystemPlaceholderView.vue`;完成标准:其余 5 个入口可正常访问,并明确说明下一阶段接入范围;验证方式:`npm run build` + 浏览器检查对应路由)
|
||||
- [x] 任务6:完成验证、视觉验收与知识库同步(涉及文件:`.helloagents/CHANGELOG.md`、`.helloagents/modules/admin-frontend.md`、`.helloagents/.ralph-visual.json`、`.helloagents/.ralph-closeout.json`;完成标准:构建通过、视觉检查完成、知识库记录本轮变更;验证方式:命令输出 + 证据文件)
|
||||
|
||||
## 进度
|
||||
- [x] 已冻结系统管理首批范围与系统配置优先级。
|
||||
- [x] 已完成 admin-frontend 系统管理导航、路由与系统配置页面。
|
||||
+11
@@ -0,0 +1,11 @@
|
||||
{
|
||||
"status": "completed",
|
||||
"completed": 4,
|
||||
"failed": 0,
|
||||
"pending": 0,
|
||||
"total": 4,
|
||||
"done": 4,
|
||||
"percent": 100,
|
||||
"current": "traffic rank 的 10/20 limit 联动已完成,待归档",
|
||||
"updated_at": "2026-04-23 23:52:00"
|
||||
}
|
||||
+89
@@ -0,0 +1,89 @@
|
||||
# 变更提案: traffic-rank-limit-backend-adapt
|
||||
|
||||
## 元信息
|
||||
```yaml
|
||||
类型: 功能增强 + 接口适配
|
||||
方案类型: implementation
|
||||
优先级: P1
|
||||
状态: 已完成
|
||||
创建: 2026-04-23
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 1. 需求
|
||||
|
||||
### 背景
|
||||
当前 `admin-frontend` 的节点/用户流量排行已经补上了 `10个 / 20个` 切换 UI,但后端 `stat/getTrafficRank` 接口仍固定只取前 10 条,所以前端切到 20 条时实际上拿不到更多数据。同时,用户进一步明确:24 小时口径下依然要显示增幅/减幅,不需要特殊隐藏。
|
||||
|
||||
### 目标
|
||||
- 让后端 `getTrafficRank` 支持按请求返回 `10` 或 `20` 条数据。
|
||||
- 让前端在节点排行/用户排行切换显示数量时,把对应的 `limit` 传给后端重新请求。
|
||||
- 保持 24h 口径下继续返回并显示涨幅/减幅,不额外关闭该能力。
|
||||
|
||||
### 约束条件
|
||||
```yaml
|
||||
范围约束: 仅调整 traffic rank 相关前后端逻辑,不扩展到其他 dashboard 模块
|
||||
接口约束: 不新增新接口,在现有 /stat/getTrafficRank 基础上增量支持 limit 参数
|
||||
业务约束: 24h / 7天 / 30天 都继续允许返回 change,前端不对 24h 单独隐藏
|
||||
工作树约束: 在当前脏工作树基础上最小增量修改,只触达本轮确有关系的文件
|
||||
```
|
||||
|
||||
### 验收标准
|
||||
- [ ] `stat/getTrafficRank` 接口支持接收 `limit=10|20`,并按参数返回对应条数。
|
||||
- [ ] dashboard 前端在节点/用户排行切换显示数量时,会向后端请求对应 limit,而不是仅前端截断。
|
||||
- [ ] 24h 口径下排行仍显示增幅/减幅,前后端都不额外屏蔽该字段。
|
||||
- [ ] `admin-frontend` 构建通过,相关 PHP 文件语法检查通过。
|
||||
|
||||
---
|
||||
|
||||
## 2. 方案
|
||||
|
||||
### 技术方案
|
||||
1. 在 `app/Http/Controllers/V2/Admin/StatController.php` 的 `getTrafficRank()` 中新增 `limit` 参数校验,并把当前节点/用户排行查询的 `limit(10)` 改为动态 limit。
|
||||
2. 在 `admin-frontend/src/api/admin.ts` 的 `getTrafficRank()` 中支持传入 `limit` 参数。
|
||||
3. 在 `admin-frontend/src/views/dashboard/DashboardView.vue` 的 `loadRankings()` 中分别把 `nodeRankLimit`、`userRankLimit` 传给对应接口,并在显示数量变化时重新请求排行数据。
|
||||
|
||||
### 影响范围
|
||||
```yaml
|
||||
涉及模块:
|
||||
- app/Http/Controllers/V2/Admin/StatController.php
|
||||
- admin-frontend/src/api/admin.ts
|
||||
- admin-frontend/src/views/dashboard/DashboardView.vue
|
||||
- public/assets/admin (构建产物输出)
|
||||
预计变更文件: 3-4
|
||||
```
|
||||
|
||||
### 风险评估
|
||||
| 风险 | 等级 | 应对 |
|
||||
|------|------|------|
|
||||
| limit 参数放开后请求值异常 | 中 | 后端仅允许 `10` 或 `20`,避免任意放大查询 |
|
||||
| 前端 limit 切换后仍沿用旧数据 | 中 | 对 `nodeRankLimit` / `userRankLimit` 增加 watch,变化即重新拉取 |
|
||||
| 当前工作树已有 dashboard 相关脏改动 | 中 | 只做最小补丁,并通过构建与 git diff 核对本轮触达文件 |
|
||||
|
||||
---
|
||||
|
||||
## 3. 成果设计
|
||||
|
||||
### 设计方向
|
||||
- **交互基线**: 维持现有 Apple 风格排行面板,不新增可视化噪音。
|
||||
- **数据行为**: 数量切换真正驱动后端返回更多排行项,而不是仅靠前端裁切。
|
||||
- **显示规则**: 24 小时口径仍保留涨跌百分比展示,与 7 天/30 天保持一致。
|
||||
|
||||
---
|
||||
|
||||
## 4. 技术决策
|
||||
|
||||
### traffic-rank-limit-backend-adapt#D001: 在现有 getTrafficRank 接口上新增 limit 参数
|
||||
**日期**: 2026-04-23
|
||||
**状态**: ✅采纳
|
||||
**背景**: 前端已经存在 10/20 切换控件,但后端固定 limit 10 导致能力不完整。
|
||||
**决策**: 不新增新接口,直接在 `getTrafficRank` 上增加受控 `limit` 参数。
|
||||
**理由**: 改动最小,且与现有 dashboard 请求模型保持一致。
|
||||
|
||||
### traffic-rank-limit-backend-adapt#D002: 24h 口径继续显示 change
|
||||
**日期**: 2026-04-23
|
||||
**状态**: ✅采纳
|
||||
**背景**: 用户明确要求 24 小时口径也允许展示增幅/减幅。
|
||||
**决策**: 保持后端始终返回 `change`,前端不为 24h 增加隐藏逻辑。
|
||||
**理由**: 行为统一,避免不同时间口径的 UI 规则分裂。
|
||||
@@ -0,0 +1,49 @@
|
||||
# 任务清单: traffic-rank-limit-backend-adapt
|
||||
|
||||
> **@status:** completed | 2026-04-23 23:52
|
||||
|
||||
```yaml
|
||||
@feature: traffic-rank-limit-backend-adapt
|
||||
@created: 2026-04-23
|
||||
@status: completed
|
||||
@mode: R2
|
||||
```
|
||||
|
||||
## 进度概览
|
||||
|
||||
| 完成 | 失败 | 跳过 | 总数 |
|
||||
|------|------|------|------|
|
||||
| 4 | 0 | 0 | 4 |
|
||||
|
||||
---
|
||||
|
||||
## 任务列表
|
||||
|
||||
### 1. 接口适配
|
||||
|
||||
- [√] 1.1 在 `app/Http/Controllers/V2/Admin/StatController.php` 中为 `getTrafficRank` 增加 `limit=10|20` 参数支持 | depends_on: []
|
||||
- [√] 1.2 在 `admin-frontend/src/api/admin.ts` 中为 `getTrafficRank` 透传 `limit` 参数 | depends_on: [1.1]
|
||||
- [√] 1.3 在 `admin-frontend/src/views/dashboard/DashboardView.vue` 中让 10/20 切换重新请求后端排行数据 | depends_on: [1.2]
|
||||
|
||||
### 2. 验证
|
||||
|
||||
- [√] 2.1 运行前后端验证(PHP 语法检查 + admin-frontend 构建),确认 24h change 未被关闭 | depends_on: [1.3]
|
||||
|
||||
---
|
||||
|
||||
## 执行日志
|
||||
|
||||
| 时间 | 任务 | 状态 | 备注 |
|
||||
|------|------|------|------|
|
||||
| 2026-04-23 23:45 | 方案包初始化 | completed | 已确认后端需支持 10/20 limit,且 24h 继续展示增幅/减幅 |
|
||||
| 2026-04-23 23:49 | 1.1 / 1.2 / 1.3 | completed | 已完成后端 limit 参数接入、前端 API 透传与排行数量切换后的重新请求 |
|
||||
| 2026-04-23 23:51 | 2.1 | completed | `npm run build` 通过;本机缺少 `php` CLI,无法直接执行 `php -l`,已以最小 PHP 补丁和代码复核兜底 |
|
||||
|
||||
---
|
||||
|
||||
## 执行备注
|
||||
|
||||
> 记录执行过程中的重要说明、决策变更、风险提示等
|
||||
|
||||
- 当前工作树已存在多项未提交 dashboard 相关改动;本轮仅聚焦 traffic rank 前后端适配。
|
||||
- 24h 涨跌展示未额外增加隐藏逻辑,前端仍直接渲染 `formatPercent(item.change)`;后端继续为所有时间口径返回 `change`。
|
||||
+11
@@ -0,0 +1,11 @@
|
||||
{
|
||||
"status": "completed",
|
||||
"completed": 6,
|
||||
"failed": 0,
|
||||
"pending": 0,
|
||||
"total": 6,
|
||||
"done": 6,
|
||||
"percent": 100,
|
||||
"current": "优惠券管理页面、弹窗与构建验证已完成,等待归档",
|
||||
"updated_at": "2026-04-24 16:28:00"
|
||||
}
|
||||
+196
@@ -0,0 +1,196 @@
|
||||
# 变更提案: admin-frontend-coupon-management
|
||||
|
||||
## 元信息
|
||||
```yaml
|
||||
类型: 新功能
|
||||
方案类型: implementation
|
||||
优先级: P1
|
||||
状态: 执行中
|
||||
创建: 2026-04-24
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 1. 需求
|
||||
|
||||
### 背景
|
||||
当前 `admin-frontend` 已完成仪表盘、用户管理、节点管理、套餐管理与系统配置,但“订阅管理”分组下的“优惠券管理”仍是禁用占位。用户本轮明确要求参考 `apple/DESIGN.md`、项目级 `.helloagents/DESIGN.md` 与提供的两张参考图,继续补完真正可用的优惠券管理页面,包括列表工作台与新增/编辑弹窗。
|
||||
|
||||
### 目标
|
||||
- 开放侧边栏中的“优惠券管理”入口,并接入真实页面与路由。
|
||||
- 基于现有 Laravel `coupon/*` 接口,完成优惠券列表、搜索、类型筛选、启停、删除、新增与编辑。
|
||||
- 页面视觉延续当前 Apple 化后台,尽量还原参考图中的黑白结构、紧凑表格与表单弹窗。
|
||||
|
||||
### 约束条件
|
||||
```yaml
|
||||
技术约束: 继续使用 Vue3 + TypeScript + Element Plus + Vite,不引入额外状态管理或重型日期/富文本依赖
|
||||
业务约束: 后端接口仅使用现有 `/coupon/fetch` `/coupon/generate` `/coupon/update` `/coupon/drop`,不改 Laravel API
|
||||
数据约束: 套餐限制项沿用现有 `/plan/fetch` 返回结果,优惠券周期限制遵循后端 legacy period 键值
|
||||
视觉约束: 遵循 `apple/DESIGN.md` 与 `.helloagents/DESIGN.md`,保持与仪表盘/套餐管理同一视觉家族
|
||||
```
|
||||
|
||||
### 验收标准
|
||||
- [ ] 左侧“订阅管理”分组中的“优惠券管理”由禁用态切换为真实可点击入口,并进入独立页面。
|
||||
- [ ] 优惠券管理页支持真实数据读取、关键字搜索、类型筛选、本地分页、启用开关、编辑和删除。
|
||||
- [ ] “添加优惠券 / 编辑优惠券”弹窗支持名称、批量生成数量、自定义优惠码、类型和值、有效期、总使用次数、每人使用次数、指定周期与指定订阅。
|
||||
- [ ] 页面中的类型标签、剩余次数、每人限制、有效期与过期提示可正确展示,并与后端字段含义一致。
|
||||
- [ ] `admin-frontend` 构建通过,且知识库同步反映“优惠券管理”已从占位入口升级为真实页面。
|
||||
|
||||
---
|
||||
|
||||
## 2. 方案
|
||||
|
||||
### 技术方案
|
||||
1. 扩展 `src/types/api.d.ts` 与 `src/api/admin.ts`,新增优惠券列表项、保存载荷、分页查询与计划选项的类型、请求封装。
|
||||
2. 新增 `src/utils/coupons.ts`,集中处理优惠券类型标签、legacy period 选项、时间范围换算、表单默认值、列表本地过滤与过期文案。
|
||||
3. 新增 `src/views/subscriptions/CouponsView.vue` 与 `CouponEditorDialog.vue`:
|
||||
- `CouponsView` 负责黑色首屏、工具条、表格、分页、行内开关与操作按钮。
|
||||
- `CouponEditorDialog` 负责新增/编辑表单、指定周期/订阅、时间范围和数值字段校验。
|
||||
4. 在 `AdminLayout.vue` 与 `router/index.ts` 中启用“优惠券管理”菜单与 `/subscriptions/coupons` 路由,同时保持“订单管理 / 礼品卡管理”为未完成状态。
|
||||
|
||||
### 影响范围
|
||||
```yaml
|
||||
涉及模块:
|
||||
- admin-frontend/src/layouts: 开放优惠券菜单入口
|
||||
- admin-frontend/src/router: 新增优惠券管理路由
|
||||
- admin-frontend/src/api: 新增 coupon 接口封装
|
||||
- admin-frontend/src/types: 新增优惠券类型定义
|
||||
- admin-frontend/src/utils: 新增优惠券数据转换与展示逻辑
|
||||
- admin-frontend/src/views/subscriptions: 新增优惠券页面、弹窗与样式
|
||||
预计变更文件: 7-9
|
||||
```
|
||||
|
||||
### 风险评估
|
||||
| 风险 | 等级 | 应对 |
|
||||
|------|------|------|
|
||||
| `/coupon/fetch` 的服务端筛选能力有限,关键字无法同时覆盖名称与券码 | 中 | 前端优先一次拉取合理数量后做本地搜索与分页,避免错误的 AND 过滤 |
|
||||
| 编辑接口复用 `/coupon/generate`,字段与新增表单共用,空值和 legacy period 容易提交错误 | 中 | 在 `utils/coupons.ts` 中统一序列化,空数组转 `undefined`,时间统一转 Unix 秒 |
|
||||
| 参考图包含较丰富的表格状态与表单布局,若实现不克制容易脱离既有后台风格 | 中 | 复用现有 Apple Admin token、表格与弹窗风格,不额外引入第二套后台皮肤 |
|
||||
|
||||
---
|
||||
|
||||
## 3. 技术设计(可选)
|
||||
|
||||
### 架构设计
|
||||
```mermaid
|
||||
flowchart TD
|
||||
A[CouponsView] --> B[admin.ts coupon 接口]
|
||||
A --> C[coupons.ts 展示/序列化工具]
|
||||
A --> D[CouponEditorDialog]
|
||||
D --> B
|
||||
D --> C
|
||||
D --> E[getPlans]
|
||||
```
|
||||
|
||||
### API设计
|
||||
#### GET /coupon/fetch
|
||||
- **请求**: `{ current, pageSize }`
|
||||
- **响应**: `{ total, current_page, per_page, last_page, data[] }`
|
||||
|
||||
#### POST /coupon/generate
|
||||
- **请求**: `{ id?, generate_count?, name, code?, type, value, started_at, ended_at, limit_use?, limit_use_with_user?, limit_plan_ids?, limit_period? }`
|
||||
- **响应**: `{ status, data }`
|
||||
|
||||
#### POST /coupon/update
|
||||
- **请求**: `{ id, show }`
|
||||
- **响应**: `{ status, data }`
|
||||
|
||||
### 数据模型
|
||||
| 字段 | 类型 | 说明 |
|
||||
|------|------|------|
|
||||
| id | number | 优惠券 ID |
|
||||
| show | boolean | 是否启用 |
|
||||
| name | string | 优惠券名称 |
|
||||
| type | 1 \| 2 | 1=按金额优惠,2=按比例优惠 |
|
||||
| value | number | 金额分/折扣整数 |
|
||||
| code | string | 券码 |
|
||||
| limit_use | number \| null | 总可用次数 |
|
||||
| limit_use_with_user | number \| null | 每人可用次数 |
|
||||
| limit_plan_ids | string[] \| null | 限制套餐 |
|
||||
| limit_period | string[] \| null | legacy 周期键 |
|
||||
| started_at / ended_at | number | 生效时间范围(Unix 秒) |
|
||||
|
||||
---
|
||||
|
||||
## 4. 核心场景
|
||||
|
||||
### 场景: 运营创建单张优惠券
|
||||
**模块**: admin-frontend/subscriptions
|
||||
**条件**: 管理员已登录,进入 `#/subscriptions/coupons`
|
||||
**行为**: 点击“添加优惠券”,填写名称、类型、金额、有效期并提交
|
||||
**结果**: 新优惠券保存成功,列表刷新并展示新记录
|
||||
|
||||
### 场景: 运营批量生成优惠码
|
||||
**模块**: admin-frontend/subscriptions
|
||||
**条件**: 管理员在新增弹窗中填写 `generate_count`
|
||||
**行为**: 提交批量生成请求
|
||||
**结果**: 后端批量创建优惠券,前端提示成功并刷新列表
|
||||
|
||||
### 场景: 运营筛选并停用过期优惠券
|
||||
**模块**: admin-frontend/subscriptions
|
||||
**条件**: 列表中存在多种类型与已过期记录
|
||||
**行为**: 使用关键字或类型筛选找到目标记录,关闭启用开关
|
||||
**结果**: 对应优惠券 `show=false`,列表状态即时更新
|
||||
|
||||
---
|
||||
|
||||
## 5. 技术决策
|
||||
|
||||
### admin-frontend-coupon-management#D001: 优惠券列表采用真实接口 + 本地搜索/筛选/分页
|
||||
**日期**: 2026-04-24
|
||||
**状态**: ✅采纳
|
||||
**背景**: 后端 `/coupon/fetch` 支持分页,但关键字筛选以 `where like` 串联多个字段时不适合做“名称或券码”搜索。
|
||||
**选项分析**:
|
||||
| 选项 | 优点 | 缺点 |
|
||||
|------|------|------|
|
||||
| A: 完全依赖后端筛选 | 数据量更轻 | 关键字搜索能力受限,名称/券码无法自然并行匹配 |
|
||||
| B: 拉取合理数量后本地搜索/筛选/分页 | 交互更贴近参考图,搜索更灵活 | 极大数据量下效率不如纯服务端 |
|
||||
**决策**: 选择方案 B
|
||||
**理由**: 当前后台优惠券数量通常不大,本地处理可更稳定满足截图中的使用方式。
|
||||
**影响**: `CouponsView.vue`、`admin.ts`、`coupons.ts`
|
||||
|
||||
### admin-frontend-coupon-management#D002: 新增与编辑共用同一弹窗,并统一序列化到 `/coupon/generate`
|
||||
**日期**: 2026-04-24
|
||||
**状态**: ✅采纳
|
||||
**背景**: 后端没有独立的 coupon save/update 表单接口,新增与编辑都通过 `generate` 处理。
|
||||
**选项分析**:
|
||||
| 选项 | 优点 | 缺点 |
|
||||
|------|------|------|
|
||||
| A: 新增/编辑拆两套表单 | 心智更直观 | 代码重复,字段校验需要维护两份 |
|
||||
| B: 共用一个表单模型与序列化逻辑 | 结构更稳定,便于维护 | 需要额外处理编辑态初始值 |
|
||||
**决策**: 选择方案 B
|
||||
**理由**: 与当前套餐编辑抽屉模式一致,能减少重复逻辑并提高一致性。
|
||||
**影响**: `CouponEditorDialog.vue`、`utils/coupons.ts`
|
||||
|
||||
### admin-frontend-coupon-management#D003: 编辑态继续采用居中弹窗而非侧边抽屉
|
||||
**日期**: 2026-04-24
|
||||
**状态**: ✅采纳
|
||||
**背景**: 参考图中优惠券编辑器为居中对话框,且字段密度更适合聚焦式表单。
|
||||
**选项分析**:
|
||||
| 选项 | 优点 | 缺点 |
|
||||
|------|------|------|
|
||||
| A: 复用抽屉模式 | 与套餐管理统一 | 与参考图差异更大,纵向表单视觉焦点分散 |
|
||||
| B: 改为居中弹窗 | 更贴近参考图,聚焦更强 | 需要单独编写对话框布局样式 |
|
||||
**决策**: 选择方案 B
|
||||
**理由**: 这页的主要新增价值就在参考图里的“表格 + 弹窗”组合,值得贴近还原。
|
||||
**影响**: `CouponEditorDialog.vue` 及其样式
|
||||
|
||||
---
|
||||
|
||||
## 6. 成果设计
|
||||
|
||||
### 设计方向
|
||||
- **美学基调**: Apple Admin Promotions。像 Apple 后台里的运营配置页,黑色首屏负责建立业务主题,正文工作台回到白底高密度表格,让折扣配置看起来更像精密运营台而不是营销页面。
|
||||
- **记忆点**: 大标题“优惠券管理”与白色表格之间形成明显的黑白切面;弹窗内部用整齐的双列字段和轻描边区块还原截图的“精密表单感”。
|
||||
- **参考**: `apple/DESIGN.md`、`.helloagents/DESIGN.md`、用户上传的优惠券列表与添加弹窗截图
|
||||
|
||||
### 视觉要素
|
||||
- **配色**: 首屏 `#000000`,工作区 `#ffffff`,页面背景 `#f5f5f7`,强调色 `#0071e3`,过期提示用浅红底 `rgba(201, 52, 40, 0.08)`
|
||||
- **字体**: 延续项目现有系统字体栈,标题走大字号紧行高,表格与辅助信息维持更轻的运营化层级
|
||||
- **布局**: 首屏 Hero + 工具条 + 表格工作台;编辑器采用居中弹窗,字段按双列网格排布,底部操作区固定在弹窗底部
|
||||
- **动效**: 保留开关切换、弹窗开合、按钮 hover 与筛选状态切换的轻量动效,不引入额外炫技动画
|
||||
- **氛围**: 工作台继续使用克制阴影、圆角白底与 Apple 式留白,避免多余卡片堆叠
|
||||
|
||||
### 技术约束
|
||||
- **可访问性**: 交互控件保留可见焦点,状态信息不只依赖颜色,危险操作保留明确文案
|
||||
- **响应式**: 桌面优先;窄屏下 Hero、工具条和弹窗网格折叠为单列,确保表单仍可完整操作
|
||||
@@ -0,0 +1,56 @@
|
||||
# 任务清单: admin-frontend-coupon-management
|
||||
|
||||
> **@status:** completed | 2026-04-24 16:28
|
||||
|
||||
```yaml
|
||||
@feature: admin-frontend-coupon-management
|
||||
@created: 2026-04-24
|
||||
@status: completed
|
||||
@mode: R2
|
||||
```
|
||||
|
||||
## 进度概览
|
||||
|
||||
| 完成 | 失败 | 跳过 | 总数 |
|
||||
|------|------|------|------|
|
||||
| 6 | 0 | 0 | 6 |
|
||||
|
||||
---
|
||||
|
||||
## 任务列表
|
||||
|
||||
### 1. 数据与路由准备
|
||||
|
||||
- [√] 1.1 在 `admin-frontend/src/types/api.d.ts` 与 `admin-frontend/src/api/admin.ts` 中补齐优惠券列表、保存载荷与接口封装 | depends_on: []
|
||||
- [√] 1.2 新增 `admin-frontend/src/utils/coupons.ts`,实现优惠券类型/周期选项、时间与表单转换、列表过滤与过期状态计算 | depends_on: [1.1]
|
||||
- [√] 1.3 在 `admin-frontend/src/layouts/AdminLayout.vue` 与 `admin-frontend/src/router/index.ts` 中开放“优惠券管理”菜单与路由 | depends_on: [1.1]
|
||||
|
||||
### 2. 优惠券页面实现
|
||||
|
||||
- [√] 2.1 新增 `admin-frontend/src/views/subscriptions/CouponsView.vue` 与样式,实现列表、搜索、类型筛选、本地分页、启停、编辑与删除入口 | depends_on: [1.1,1.2,1.3]
|
||||
- [√] 2.2 新增 `admin-frontend/src/views/subscriptions/CouponEditorDialog.vue` 与样式,实现新增/编辑弹窗、双列表单、指定周期/订阅、多码生成与提交保存 | depends_on: [1.1,1.2,1.3]
|
||||
|
||||
### 3. 验证与同步
|
||||
|
||||
- [√] 3.1 运行 `admin-frontend` 构建验证,并结合页面代码完成优惠券管理视觉/交互自检 | depends_on: [2.1,2.2]
|
||||
|
||||
---
|
||||
|
||||
## 执行日志
|
||||
|
||||
| 时间 | 任务 | 状态 | 备注 |
|
||||
|------|------|------|------|
|
||||
| 2026-04-24 15:51 | 方案包初始化 | completed | 已确认本轮范围为完整优惠券管理接入,采用 Apple 化后台风格 |
|
||||
| 2026-04-24 16:06 | 1.1 / 1.2 / 1.3 | completed | 已补齐 coupon 类型、接口、工具函数,并开放“优惠券管理”菜单与路由 |
|
||||
| 2026-04-24 16:18 | 2.1 / 2.2 | completed | 已完成优惠券列表页与新增/编辑弹窗,接入真实 coupon 接口与套餐限制项 |
|
||||
| 2026-04-24 16:28 | 3.1 | completed | `npm run build` 通过;当前环境缺少可复用浏览器与登录态,仅完成代码级视觉/交互自检 |
|
||||
|
||||
---
|
||||
|
||||
## 执行备注
|
||||
|
||||
> 记录执行过程中的重要说明、决策变更、风险提示等
|
||||
|
||||
- 当前工作树可能存在与本轮无关的其他改动,实施过程中需保持最小作用域,不覆盖既有未提交修改。
|
||||
- 当前后端缺少专门的 coupon detail/save 分离接口,编辑流程将复用 `coupon/generate`,并在前端统一做字段序列化。
|
||||
- 当前视觉验收受限于本地缺少可复用的后台登录态与浏览器截图工具,本轮已通过构建产物、组件结构与样式代码完成代码级验收,建议后续在真实管理登录态下补一次人工点检。
|
||||
+11
@@ -0,0 +1,11 @@
|
||||
{
|
||||
"status": "completed",
|
||||
"completed": 5,
|
||||
"failed": 0,
|
||||
"pending": 0,
|
||||
"total": 5,
|
||||
"done": 5,
|
||||
"percent": 100,
|
||||
"current": "插件管理工作台、详情抽屉与构建验证已完成",
|
||||
"updated_at": "2026-04-24 16:12:00"
|
||||
}
|
||||
+51
@@ -0,0 +1,51 @@
|
||||
{
|
||||
"updatedAt": "2026-04-24T07:55:29.737Z",
|
||||
"version": 1,
|
||||
"source": "manual",
|
||||
"originCommand": "plugin-management-r2",
|
||||
"verifyMode": "review-first",
|
||||
"reviewerFocus": [
|
||||
"插件管理页是否延续当前 Apple 风格后台,并形成真实工作台而不是占位页",
|
||||
"卡片动作优先级、危险动作和受保护插件边界是否清晰",
|
||||
"详情抽屉中的 README 与配置双视图是否易读且层级明确"
|
||||
],
|
||||
"testerFocus": [
|
||||
"插件列表、类型切换、状态筛选与搜索是否真实连接 /plugin/getPlugins 数据流",
|
||||
"上传、安装、启用、禁用、升级、卸载动作是否真实命中对应插件接口",
|
||||
"插件配置读取与保存是否真实命中 /plugin/config"
|
||||
],
|
||||
"ui": {
|
||||
"required": true,
|
||||
"designContract": true,
|
||||
"sourcePriority": [
|
||||
"plan.md",
|
||||
".helloagents/DESIGN.md",
|
||||
"hello-ui"
|
||||
],
|
||||
"styleAdvisor": {
|
||||
"required": false,
|
||||
"reason": "",
|
||||
"focus": []
|
||||
},
|
||||
"visualValidation": {
|
||||
"required": true,
|
||||
"reason": "插件管理属于整页 UI 重做,需确认卡片列表、筛选工具栏与详情抽屉层级符合 Apple 风格后台契约",
|
||||
"screens": [
|
||||
"#/system/plugins desktop",
|
||||
"#/system/plugins detail-drawer desktop"
|
||||
],
|
||||
"states": [
|
||||
"插件列表加载完成态",
|
||||
"插件列表空状态或错误态",
|
||||
"插件详情 README 态",
|
||||
"插件配置编辑态"
|
||||
]
|
||||
}
|
||||
},
|
||||
"advisor": {
|
||||
"required": false,
|
||||
"reason": "",
|
||||
"focus": [],
|
||||
"preferredSources": []
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,65 @@
|
||||
# admin-frontend 插件管理首版交付 — 实施规划
|
||||
|
||||
## 目标与范围
|
||||
- 把 `#/system/plugins` 从占位页升级为真实插件管理页面。
|
||||
- 本轮范围聚焦“单页工作台 + 详情抽屉”模型:列表承担检索、筛选和高频动作,抽屉承担 README、配置与补充说明。
|
||||
- 其余系统管理子页保持现状,不借本轮需求扩展其他模块。
|
||||
|
||||
## 架构与实现策略
|
||||
- 在 `admin-frontend/src/api/admin.ts` 与 `src/types/api.d.ts` 中补齐插件管理接口和类型定义,保证所有页面动作都走真实后端契约。
|
||||
- 新增 `src/utils/plugins.ts`,集中处理插件类型文案、状态判断、筛选、README 渲染与配置表单值序列化,避免视图组件堆积逻辑。
|
||||
- 将 `/system/plugins` 路由替换为独立的 `PluginManagementView.vue`,继续保留黑色 hero + 白色工作台层次,首屏承载搜索、类型切换、状态筛选、上传入口与运营摘要。
|
||||
- 新增 `PluginDetailDrawer.vue` 作为插件详情工作台:
|
||||
- 左侧 / 顶部展示插件基本信息与状态
|
||||
- 中部切换 README / 配置两个视图
|
||||
- 配置基于后端返回的动态 schema 渲染,不额外臆造字段
|
||||
- 列表卡片提供高频动作按钮:
|
||||
- 未安装:安装
|
||||
- 已安装未启用:启用、卸载
|
||||
- 已启用:禁用
|
||||
- 可升级:升级
|
||||
- 受保护 / 核心插件:明确显示保护边界,避免危险误操作
|
||||
|
||||
## 完成定义
|
||||
- `#/system/plugins` 能真实拉取插件列表,并按类型 / 状态 / 关键词筛选。
|
||||
- 页面支持上传 zip 插件包,并在上传成功后刷新列表。
|
||||
- 管理员可以对插件执行安装、启用、禁用、升级、卸载动作,并获得明确成功 / 失败反馈。
|
||||
- 详情抽屉可查看 README 和插件基础信息;对存在配置 schema 的插件,可读取并保存配置。
|
||||
- 验证主路径:`review-first`
|
||||
- reviewer 关注边界:
|
||||
- 插件管理首屏是否与现有 Apple 风格后台一致,且不像占位页
|
||||
- 列表动作优先级、危险按钮和受保护插件边界是否清晰
|
||||
- 详情抽屉的 README / 配置双视图是否足够清楚
|
||||
- tester 关注边界:
|
||||
- `/plugin/getPlugins`、`/plugin/upload`、`/plugin/install`、`/plugin/enable`、`/plugin/disable`、`/plugin/uninstall`、`/plugin/upgrade` 是否都已接入真实数据流
|
||||
- 插件配置读取 / 保存是否真实命中 `/plugin/config`
|
||||
- 搜索、类型切换、状态筛选是否真实影响渲染结果
|
||||
|
||||
## 文件结构
|
||||
- `admin-frontend/src/router/index.ts`
|
||||
- `admin-frontend/src/api/admin.ts`
|
||||
- `admin-frontend/src/types/api.d.ts`
|
||||
- `admin-frontend/src/utils/plugins.ts`(新增)
|
||||
- `admin-frontend/src/views/system/PluginManagementView.vue`(新增)
|
||||
- `admin-frontend/src/views/system/PluginManagementView.scss`(新增)
|
||||
- `admin-frontend/src/views/system/PluginDetailDrawer.vue`(新增)
|
||||
|
||||
## UI / 设计约束
|
||||
- 首屏延续当前系统管理模块的黑色 hero,右侧摘要卡片改为“插件总数 / 已启用 / 可升级 / 用户上传”等运营信息。
|
||||
- 列表采用大卡片而不是传统密表格,强调插件名称、类型、版本、作者、描述与状态标签,贴近用户截图的阅读方式。
|
||||
- 顶部筛选区使用轻量 segmented control + select + search 组合,不引入多层复杂过滤器。
|
||||
- 配置表单要兼容 `boolean / string / text / json / select` 等基础字段类型,字段说明与 placeholder 保持可见。
|
||||
- README 区域使用真实 Markdown 渲染,保留代码块、列表和标题层级。
|
||||
|
||||
## 风险与验证
|
||||
- 风险 1:后端返回的插件配置 schema 是动态结构,前端需要兼容多种字段类型与空配置插件。
|
||||
- 风险 2:`getPlugins` 已带部分配置和 README,但已安装插件的配置需要保证与 `/plugin/config` 拉取一致,避免抽屉内旧数据。
|
||||
- 风险 3:本地环境缺少真实登录态时,无法做完整浏览器联调;需要用 build + 代码级结构自检给出本轮 UI 验收结论。
|
||||
- 验证方式:
|
||||
- `npm run build`
|
||||
- 对构建产物与代码结构做 UI 自检,确认搜索、筛选、卡片操作与抽屉视图均已真实连接数据流
|
||||
|
||||
## 决策记录
|
||||
- [2026-04-24] D001:插件管理采用“卡片列表 + 详情抽屉”,不回退到纯表格,兼顾截图风格和后台可操作性。
|
||||
- [2026-04-24] D002:配置编辑采用动态 schema 渲染,不为单个插件写死字段。
|
||||
- [2026-04-24] D003:README 与配置合并进同一个详情工作台,避免列表页信息密度失控。
|
||||
+47
@@ -0,0 +1,47 @@
|
||||
# admin-frontend 插件管理首版交付 — 需求
|
||||
|
||||
确认后冻结,执行阶段不可修改。如需变更必须回到设计阶段重新确认。
|
||||
|
||||
## 核心目标
|
||||
- 在 `admin-frontend` 中把 `/system/plugins` 从结构化占位页升级为真实插件管理工作台。
|
||||
- 页面视觉继续遵循 `apple/DESIGN.md` 与当前后台 Apple 化风格,并尽量贴近用户提供的目标截图:顶部搜索 / 分组切换 / 状态筛选 / 上传入口,下方插件卡片列表。
|
||||
- 让管理员可以在同一页面完成插件浏览、筛选、上传、安装、启用 / 禁用、升级、卸载,以及 README / 配置查看与编辑。
|
||||
|
||||
## 功能边界
|
||||
- 必须接入现有 Laravel 管理接口的真实数据链路:
|
||||
- `GET /plugin/types`
|
||||
- `GET /plugin/getPlugins`
|
||||
- `POST /plugin/upload`
|
||||
- `POST /plugin/install`
|
||||
- `POST /plugin/uninstall`
|
||||
- `POST /plugin/enable`
|
||||
- `POST /plugin/disable`
|
||||
- `GET /plugin/config`
|
||||
- `POST /plugin/config`
|
||||
- `POST /plugin/upgrade`
|
||||
- 必须支持:
|
||||
- 按关键词搜索插件
|
||||
- 按插件类型切换(全部 / 功能 / 支付方式)
|
||||
- 按状态筛选(全部 / 已启用 / 已安装未启用 / 未安装 / 可升级)
|
||||
- 上传 zip 插件包
|
||||
- 列表中直接执行安装、启用、禁用、升级、卸载动作
|
||||
- 打开插件详情工作台,查看 README、基础元信息,并对可配置插件进行配置保存
|
||||
- 必须覆盖加载、空列表、错误、按钮提交中、配置保存成功 / 失败等状态。
|
||||
|
||||
## 非目标
|
||||
- 本轮不实现主题、公告、支付配置、知识库管理的真实 CRUD 页面。
|
||||
- 本轮不新增或重构 Laravel 插件管理接口。
|
||||
- 本轮不接入浏览器端拖拽上传、批量操作或插件市场远程下载能力。
|
||||
- 本轮不修改 `public/assets/admin` 子模块之外的发布流程。
|
||||
|
||||
## 技术约束
|
||||
- 技术栈固定为 `Vue 3 + TypeScript + Vite + Element Plus`。
|
||||
- 后端真相源以现有 `PluginController` / `PluginConfigService` / `PluginManager` 为准,不在前端猜测额外字段。
|
||||
- 视觉契约优先级:本方案 > `.helloagents/DESIGN.md` > `apple/DESIGN.md` 参考原则。
|
||||
- 构建验证使用 `admin-frontend/package.json` 中已有 `npm run build`。
|
||||
|
||||
## 质量要求
|
||||
- 插件管理页必须保持 Apple 风格后台的一致性,同时比现有占位页更强调运营效率与状态可读性。
|
||||
- 卡片与详情工作台中的插件状态、危险动作和受保护插件边界必须清晰可辨。
|
||||
- README 展示与配置编辑必须是真实数据流,不允许停留在纯展示占位。
|
||||
- 最终至少完成一次构建验证,并补一份本轮 UI 验收结论。
|
||||
@@ -0,0 +1,13 @@
|
||||
# admin-frontend 插件管理首版交付 — 任务分解
|
||||
|
||||
## 任务列表
|
||||
- [x] 任务1:冻结本轮插件管理方案包与状态上下文(涉及文件:`.helloagents/plan/202604241553_admin-frontend-plugin-management/requirements.md`、`.helloagents/plan/202604241553_admin-frontend-plugin-management/plan.md`、`.helloagents/plan/202604241553_admin-frontend-plugin-management/tasks.md`、`.helloagents/plan/202604241553_admin-frontend-plugin-management/contract.json`、`.helloagents/sessions/master/default/STATE.md`;完成标准:存在可执行的需求/方案/任务/合同文件,状态文件已切到插件管理主线;验证方式:文件检查)
|
||||
- [x] 任务2:补齐插件管理前端类型与 API(涉及文件:`admin-frontend/src/api/admin.ts`、`admin-frontend/src/types/api.d.ts`、`admin-frontend/src/utils/plugins.ts`;完成标准:存在插件列表、动作、配置、上传所需的真实接口封装与辅助类型 / 工具;验证方式:`npm run build`)
|
||||
- [x] 任务3:实现插件管理列表工作台(涉及文件:`admin-frontend/src/router/index.ts`、`admin-frontend/src/views/system/PluginManagementView.vue`、`admin-frontend/src/views/system/PluginManagementView.scss`;完成标准:`#/system/plugins` 能展示真实插件卡片、搜索、类型切换、状态筛选、上传入口与列表动作;验证方式:`npm run build`)
|
||||
- [x] 任务4:实现插件详情与配置工作台(涉及文件:`admin-frontend/src/views/system/PluginDetailDrawer.vue`、`admin-frontend/src/utils/plugins.ts`、`admin-frontend/src/api/admin.ts`;完成标准:可打开 README / 配置抽屉,并支持真实配置读取与保存;验证方式:`npm run build`)
|
||||
- [x] 任务5:完成验证、知识库同步与交付证据(涉及文件:`.helloagents/modules/admin-frontend.md`、`.helloagents/CHANGELOG.md`、`.helloagents/.ralph-visual.json`、`.helloagents/.ralph-closeout.json`、`.helloagents/archive/_index.md`、`.helloagents/sessions/master/default/STATE.md`;完成标准:构建通过,UI 验收结论与知识库记录同步完成;验证方式:命令输出 + 证据文件)
|
||||
|
||||
## 进度
|
||||
- [x] 已冻结插件管理首版交付范围。
|
||||
- [x] 已完成插件管理页面与详情工作台。
|
||||
- [x] 已完成验证与知识库同步。
|
||||
+11
@@ -0,0 +1,11 @@
|
||||
{
|
||||
"status": "completed",
|
||||
"completed": 6,
|
||||
"failed": 0,
|
||||
"pending": 0,
|
||||
"total": 6,
|
||||
"done": 6,
|
||||
"percent": 100,
|
||||
"current": "支付配置真实工作台已完成,等待归档与用户验收",
|
||||
"updated_at": "2026-04-24 16:14:00"
|
||||
}
|
||||
+206
@@ -0,0 +1,206 @@
|
||||
# 变更提案: admin-frontend-payment-management
|
||||
|
||||
## 元信息
|
||||
```yaml
|
||||
类型: 功能开发
|
||||
方案类型: implementation
|
||||
优先级: P1
|
||||
状态: 进行中
|
||||
创建: 2026-04-24
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 1. 需求
|
||||
|
||||
### 背景
|
||||
当前 `admin-frontend` 的“支付配置”仍是占位页,但 Laravel 后端已经提供 `payment/fetch`、`payment/getPaymentMethods`、`payment/getPaymentForm`、`payment/save`、`payment/show`、`payment/drop`、`payment/sort` 等完整管理接口。用户本轮明确选择“完整真实 CRUD”方案,并提供了支付列表、编辑抽屉与支付接口下拉截图,要求继续完成支付配置模块。
|
||||
|
||||
### 目标
|
||||
- 将 `#/system/payments` 从占位页升级为真实可用的支付配置页面。
|
||||
- 提供支付方式列表、关键词搜索、启停、新增/编辑、删除与排序能力。
|
||||
- 抽屉表单按所选支付接口动态拉取配置字段,保持与后端支付插件表单契约一致。
|
||||
- 视觉上延续 `apple/DESIGN.md` 与 `.helloagents/DESIGN.md` 的 Apple 风格后台体系。
|
||||
|
||||
### 约束条件
|
||||
```yaml
|
||||
范围约束: 仅实现支付配置工作台,不扩展插件/主题/知识库等其他系统模块
|
||||
技术约束: 继续使用 Vue3 + TypeScript + Element Plus,不新增第三方表单或拖拽依赖
|
||||
业务约束: 后端真实契约以 PaymentController / PaymentService / 插件 form() 返回字段为准,不在前端猜测额外支付字段
|
||||
数据约束: 排序继续调用 `/payment/sort`;启停继续调用 `/payment/show` 的“切换”语义接口
|
||||
视觉约束: 延续黑色 hero + 白色工作台 + 克制蓝色交互,保持与现有系统配置/套餐管理同一视觉家族
|
||||
```
|
||||
|
||||
### 验收标准
|
||||
- [ ] `#/system/payments` 可真实拉取支付方式列表,并显示 ID、启用状态、显示名称、支付接口、通知地址与操作列。
|
||||
- [ ] 页面支持关键词搜索,筛选后结果与分页计数同步更新。
|
||||
- [ ] 支持新增与编辑支付方式,字段覆盖显示名称、图标 URL、通知域名、百分比手续费、固定手续费、支付接口与动态支付配置字段。
|
||||
- [ ] 支持启停、删除与排序,并给出明确成功/失败反馈。
|
||||
- [ ] `admin-frontend` 执行 `npm run build` 通过。
|
||||
|
||||
---
|
||||
|
||||
## 2. 方案
|
||||
|
||||
### 页面结构
|
||||
1. 延续系统管理页面的 Apple 化后台结构,顶部使用黑色 hero 展示支付概览统计。
|
||||
2. 主工作区使用白色表格容器,提供“添加支付方式”“搜索支付方式”“编辑排序”三类核心操作。
|
||||
3. 支付方式编辑采用右侧抽屉,顶层字段集中展示显示名称、图标、通知域名、手续费与支付接口。
|
||||
4. 抽屉下半区按支付接口动态加载真实配置字段,保持与后端插件 `form()` 返回结果一致。
|
||||
5. 排序使用独立对话框,通过上移/下移维护本地顺序,再提交到 `/payment/sort`。
|
||||
|
||||
### 前端实现策略
|
||||
1. 在 `src/types/api.d.ts` 与 `src/api/admin.ts` 中补齐支付方式列表、动态配置字段与保存载荷类型 / API 封装。
|
||||
2. 新增 `src/utils/payments.ts`,集中处理支付方式归一化、关键词过滤、排序移动、手续费展示与动态配置序列化。
|
||||
3. 新增:
|
||||
- `src/views/system/SystemPaymentsView.vue`
|
||||
- `src/views/system/SystemPaymentsView.scss`
|
||||
- `src/views/system/SystemPaymentEditorDrawer.vue`
|
||||
- `src/views/system/SystemPaymentEditorDrawer.scss`
|
||||
4. 将 `/system/payments` 路由切换为真实页面,其余系统管理入口保持现状不动。
|
||||
|
||||
### 影响范围
|
||||
```yaml
|
||||
涉及模块:
|
||||
- admin-frontend/src/types: 补齐支付配置相关类型定义
|
||||
- admin-frontend/src/api: 新增 payment 管理接口封装
|
||||
- admin-frontend/src/utils: 新增支付数据转换、过滤、保存辅助逻辑
|
||||
- admin-frontend/src/views/system: 新增支付列表页与编辑抽屉
|
||||
- admin-frontend/src/router: 将支付配置路由切换到真实页面
|
||||
预计变更文件: 8-9
|
||||
```
|
||||
|
||||
### 风险评估
|
||||
| 风险 | 等级 | 应对 |
|
||||
| 后端 `/payment/show` 是切换型接口,不接受显式目标状态 | 中 | 前端只在用户主动切换时调用一次,并在成功后按目标值更新本地状态 |
|
||||
| 动态支付配置字段完全由插件 form() 返回,前端若自行假设字段会导致保存错位 | 高 | 抽屉内所有支付配置字段均通过 `/payment/getPaymentForm` 实时拉取,不写死配置项 |
|
||||
| 构建会刷新 `public/assets/admin` 子模块产物 | 中 | 仅执行 `admin-frontend` 构建验证,不自动代做子模块发布 |
|
||||
|
||||
---
|
||||
|
||||
## 3. 技术设计(可选)
|
||||
|
||||
### 架构设计
|
||||
```mermaid
|
||||
flowchart TD
|
||||
A[SystemPaymentsView] --> B[admin.ts payment API]
|
||||
A --> C[payments.ts]
|
||||
A --> D[SystemPaymentEditorDrawer]
|
||||
D --> B
|
||||
D --> C
|
||||
```
|
||||
|
||||
### API设计
|
||||
#### GET /payment/fetch
|
||||
- **请求**: 无
|
||||
- **响应**: `AdminPaymentListItem[]`
|
||||
|
||||
#### GET /payment/getPaymentMethods
|
||||
- **请求**: 无
|
||||
- **响应**: `string[]`
|
||||
|
||||
#### POST /payment/getPaymentForm
|
||||
- **请求**: `{ payment, id? }`
|
||||
- **响应**: `Record<string, AdminPaymentConfigField>`
|
||||
|
||||
#### POST /payment/save
|
||||
- **请求**: `{ id?, name, icon?, payment, config, notify_domain?, handling_fee_fixed?, handling_fee_percent? }`
|
||||
- **响应**: `{ status, data }`
|
||||
|
||||
### 数据模型
|
||||
| 字段 | 类型 | 说明 |
|
||||
|------|------|------|
|
||||
| id | number | 支付方式 ID |
|
||||
| payment | string | 支付接口代码,如 EPay / TokenPay |
|
||||
| name | string | 后台显示名称 |
|
||||
| icon | string \| null | 图标 URL |
|
||||
| notify_domain | string \| null | 自定义通知域名 |
|
||||
| notify_url | string \| null | 后端拼接后的完整通知地址 |
|
||||
| handling_fee_fixed | number \| null | 固定手续费 |
|
||||
| handling_fee_percent | number \| null | 百分比手续费 |
|
||||
| enable | boolean | 是否启用 |
|
||||
| config | Record<string, unknown> | 支付插件配置对象 |
|
||||
|
||||
---
|
||||
|
||||
## 4. 核心场景
|
||||
|
||||
### 场景: 运营新增支付方式
|
||||
**模块**: admin-frontend/system
|
||||
**条件**: 管理员已登录,进入 `#/system/payments`
|
||||
**行为**: 点击“添加支付方式”,选择支付接口并填写网关参数后提交
|
||||
**结果**: 新支付方式保存成功,列表刷新并展示新记录
|
||||
|
||||
### 场景: 运营切换支付启用状态
|
||||
**模块**: admin-frontend/system
|
||||
**条件**: 列表中存在可用支付方式
|
||||
**行为**: 在列表中切换启用开关
|
||||
**结果**: 对应支付方式状态被切换,并在当前列表中即时更新
|
||||
|
||||
### 场景: 运营维护支付排序
|
||||
**模块**: admin-frontend/system
|
||||
**条件**: 系统中存在多个支付方式
|
||||
**行为**: 打开“编辑排序”,调整上下顺序并保存
|
||||
**结果**: 后端 `/payment/sort` 接收新的排序序列,列表刷新为最新顺序
|
||||
|
||||
---
|
||||
|
||||
## 5. 技术决策
|
||||
|
||||
### admin-frontend-payment-management#D001: 支付配置采用“真实列表页 + 动态配置抽屉 + 独立排序对话框”
|
||||
**日期**: 2026-04-24
|
||||
**状态**: ✅采纳
|
||||
**背景**: 用户截图已经明确表达“列表 + 右侧编辑抽屉 + 编辑排序”的后台工作流结构。
|
||||
**选项分析**:
|
||||
| 选项 | 优点 | 缺点 |
|
||||
| A: 继续使用占位页 | 改动最小 | 无法完成真实支付配置任务 |
|
||||
| B: 列表页 + 动态配置抽屉 + 排序对话框 | 最贴近截图,也与套餐管理模式一致 | 需要新增更多前端结构与状态管理 |
|
||||
**决策**: 选择方案 B
|
||||
**理由**: 能同时覆盖用户截图中的真实使用方式与当前 Apple 风格后台架构。
|
||||
**影响**: `SystemPaymentsView.vue`、`SystemPaymentEditorDrawer.vue`
|
||||
|
||||
### admin-frontend-payment-management#D002: 支付配置字段完全以后端 `/payment/getPaymentForm` 为唯一真相源
|
||||
**日期**: 2026-04-24
|
||||
**状态**: ✅采纳
|
||||
**背景**: 各支付插件的配置字段由插件 `form()` 动态生成,字段集并不固定。
|
||||
**选项分析**:
|
||||
| 选项 | 优点 | 缺点 |
|
||||
|------|------|------|
|
||||
| A: 前端写死常见支付字段 | 实现快 | 无法覆盖不同插件,容易与后端表单脱节 |
|
||||
| B: 每次根据接口动态拉取字段 | 契约最稳定 | 需要额外处理加载与切换状态 |
|
||||
**决策**: 选择方案 B
|
||||
**理由**: 可同时兼容 EPay、TokenPay、AlipayF2F、Coinbase 等不同插件,不会因为字段假设错误而破坏保存链路。
|
||||
**影响**: `admin.ts`、`payments.ts`、`SystemPaymentEditorDrawer.vue`
|
||||
|
||||
### admin-frontend-payment-management#D003: 支付启停继续沿用现有“切换型接口”,前端做同值短路保护
|
||||
**日期**: 2026-04-24
|
||||
**状态**: ✅采纳
|
||||
**背景**: `/payment/show` 后端实现是直接反转状态,不接收目标状态。
|
||||
**选项分析**:
|
||||
| 选项 | 优点 | 缺点 |
|
||||
|------|------|------|
|
||||
| A: 前端假设为“设置型接口”并传目标值 | 交互直觉更强 | 与后端真实行为不一致,容易在重复事件下错位 |
|
||||
| B: 前端只做主动点击触发 + 成功后同步本地状态 | 与现有接口完全对齐 | 需要额外防止无效 change 事件 |
|
||||
**决策**: 选择方案 B
|
||||
**理由**: 能最小代价对齐后端现状,并避免初始化或重复事件导致的误切换。
|
||||
**影响**: `SystemPaymentsView.vue`
|
||||
|
||||
---
|
||||
|
||||
## 6. 成果设计
|
||||
|
||||
### 设计方向
|
||||
- **美学基调**: Apple Admin Payments。黑色首屏强调“系统级支付运营台”的沉稳感,正文回到白底高密度工作台,重点突出支付方式与通知链路,而不是营销化装饰。
|
||||
- **记忆点**: 支付配置列表里的“图标 + 名称 + 手续费摘要”组合,与右侧动态配置抽屉形成明显的黑白双层结构。
|
||||
- **参考**: `apple/DESIGN.md`、`.helloagents/DESIGN.md`、用户提供的支付列表 / 编辑抽屉 / 支付接口下拉截图
|
||||
|
||||
### 视觉要素
|
||||
- **配色**: 首屏 `#000000`,页面背景 `#f5f5f7`,工作区 `#ffffff`,强调色 `#0071e3`,危险动作保持 `var(--xboard-danger)`
|
||||
- **字体**: 延续项目现有系统字体栈,首屏标题保持大字号紧行高,列表和抽屉字段走轻量运营层级
|
||||
- **布局**: Hero + 工具条 + 表格工作台;编辑器采用右侧抽屉,表单上半部为顶层字段,下半部为动态支付配置
|
||||
- **动效**: 仅保留抽屉开合、按钮 hover、排序对话框切换与开关状态变化的轻量动效
|
||||
- **氛围**: 使用克制阴影、圆角白底、胶囊型通知地址与简洁图标预览,不堆叠过多卡片或装饰性标签
|
||||
|
||||
### 技术约束
|
||||
- **可访问性**: 开关、按钮、抽屉表单需保留可见焦点;错误和危险操作不能只靠颜色表达
|
||||
- **响应式**: 桌面优先;窄屏下 hero、工具条、排序对话框和抽屉字段网格需折叠为单列
|
||||
@@ -0,0 +1,53 @@
|
||||
# 任务清单: admin-frontend-payment-management
|
||||
|
||||
> **@status:** completed | 2026-04-24 16:14
|
||||
|
||||
```yaml
|
||||
@feature: admin-frontend-payment-management
|
||||
@created: 2026-04-24
|
||||
@status: completed
|
||||
@mode: R2
|
||||
```
|
||||
|
||||
## 进度概览
|
||||
|
||||
| 完成 | 失败 | 跳过 | 总数 |
|
||||
|------|------|------|------|
|
||||
| 6 | 0 | 0 | 6 |
|
||||
|
||||
---
|
||||
|
||||
## 任务列表
|
||||
|
||||
### 1. 数据与路由准备
|
||||
|
||||
- [√] 1.1 在 `admin-frontend/src/types/api.d.ts` 与 `admin-frontend/src/api/admin.ts` 中补齐支付方式列表、动态配置字段与接口封装 | depends_on: []
|
||||
- [√] 1.2 新增 `admin-frontend/src/utils/payments.ts`,实现支付方式归一化、过滤、排序移动与保存序列化 | depends_on: [1.1]
|
||||
- [√] 1.3 在 `admin-frontend/src/router/index.ts` 中将 `/system/payments` 切换到真实支付配置页面 | depends_on: [1.1]
|
||||
|
||||
### 2. 支付配置页面实现
|
||||
|
||||
- [√] 2.1 新增 `admin-frontend/src/views/system/SystemPaymentsView.vue` 与样式,实现列表、搜索、启停、删除、新增/编辑入口与排序对话框 | depends_on: [1.1,1.2,1.3]
|
||||
- [√] 2.2 新增 `admin-frontend/src/views/system/SystemPaymentEditorDrawer.vue` 与样式,实现动态支付接口配置抽屉与保存提交流程 | depends_on: [1.1,1.2,1.3]
|
||||
|
||||
### 3. 验证与同步
|
||||
|
||||
- [√] 3.1 运行 `admin-frontend` 构建验证,并结合页面代码完成支付配置视觉/交互自检 | depends_on: [2.1,2.2]
|
||||
|
||||
---
|
||||
|
||||
## 执行日志
|
||||
|
||||
| 时间 | 任务 | 状态 | 备注 |
|
||||
|------|------|------|------|
|
||||
| 2026-04-24 15:58 | 方案包初始化 | completed | 已确认本轮范围为支付配置完整 CRUD 工作台,目标对齐用户截图与 `/payment/*` 后端接口 |
|
||||
| 2026-04-24 16:05 | 1.1 / 1.2 / 1.3 | completed | 已补齐支付配置类型、API、工具层与真实路由切换 |
|
||||
| 2026-04-24 16:11 | 2.1 / 2.2 | completed | 已完成支付配置列表、排序对话框与动态支付配置抽屉 |
|
||||
| 2026-04-24 16:14 | 3.1 | completed | `npm run build` 通过;当前环境无浏览器自动化工具,已完成代码级视觉与交互自检 |
|
||||
|
||||
---
|
||||
|
||||
## 执行备注
|
||||
|
||||
- 当前工作树存在与本轮无关的其他未提交修改,实施时需保持最小作用域,不覆盖已有 in-progress 改动。
|
||||
- 构建验证会刷新 `public/assets/admin` 子模块产物,本轮仅提供功能实现与验证证据,不自动代做发布。
|
||||
+11
@@ -0,0 +1,11 @@
|
||||
{
|
||||
"status": "completed",
|
||||
"completed": 5,
|
||||
"failed": 0,
|
||||
"pending": 0,
|
||||
"total": 5,
|
||||
"done": 5,
|
||||
"percent": 100,
|
||||
"current": "主题管理页面、动态配置抽屉与构建验证已完成,等待交付",
|
||||
"updated_at": "2026-04-24 16:12:00"
|
||||
}
|
||||
@@ -0,0 +1,75 @@
|
||||
# 变更提案: admin-frontend-theme-management
|
||||
|
||||
## 元信息
|
||||
```yaml
|
||||
类型: 新功能
|
||||
方案类型: implementation
|
||||
优先级: P1
|
||||
状态: 已完成
|
||||
创建: 2026-04-24
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 1. 需求
|
||||
|
||||
### 背景
|
||||
当前 `admin-frontend` 已经完成系统配置真实页,但 `#/system/themes` 仍停留在结构化占位状态。用户本轮要求继续基于 `apple/DESIGN.md`、项目级 `.helloagents/DESIGN.md` 和提供的参考图,把“主题配置”升级为真实可用的主题管理页面。
|
||||
|
||||
### 目标
|
||||
- 将 `#/system/themes` 从占位页升级为真实主题管理工作台。
|
||||
- 展示可用主题列表、当前主题标记和主题基础信息。
|
||||
- 提供主题设置抽屉,支持动态主题配置保存。
|
||||
- 提供 zip 主题包上传入口,并支持把某个主题设为当前主题。
|
||||
|
||||
### 约束条件
|
||||
```yaml
|
||||
技术约束: 继续使用 Vue3 + TypeScript + Element Plus + Vite,不新增主题编辑器或上传库
|
||||
业务约束: 后端沿用现有 `theme/*` 与 `config/save(frontend_theme)` 能力,不修改 Laravel API
|
||||
范围约束: 本轮先完成主题列表、当前主题切换、主题设置与上传;删除主题保留到下一轮
|
||||
视觉约束: 保持 Apple 化后台语义,页面结构优先贴近参考图中的“标题 + 说明 + 主题卡片 + 上传入口”
|
||||
```
|
||||
|
||||
### 验收标准
|
||||
- [ ] `#/system/themes` 能展示真实主题列表,不再使用占位页。
|
||||
- [ ] 页面能明确标记当前主题,并允许把其他主题设为当前主题。
|
||||
- [ ] 点击“主题设置”可打开配置抽屉,按主题 schema 渲染字段并保存。
|
||||
- [ ] 页面提供 zip 主题包上传入口,并接入真实后端上传接口。
|
||||
- [ ] `admin-frontend` 构建通过,且知识库记录主题管理已从占位页升级为真实页面。
|
||||
|
||||
---
|
||||
|
||||
## 2. 方案
|
||||
|
||||
### 技术方案
|
||||
1. 在 `src/types/api.d.ts` 与 `src/api/admin.ts` 中补齐主题列表、主题配置和主题上传所需类型与接口封装。
|
||||
2. 新增 `src/utils/themes.ts`,统一处理主题列表排序、配置默认值回填和表单序列化。
|
||||
3. 新增 `src/views/system/ThemesView.vue` 与 `ThemeConfigDrawer.vue`:
|
||||
- `ThemesView` 负责标题区、当前主题/数量摘要、主题卡片、上传按钮与切换逻辑。
|
||||
- `ThemeConfigDrawer` 负责根据主题 schema 动态渲染配置项并保存。
|
||||
4. 在 `src/router/index.ts` 中把 `system/themes` 路由从占位页切换到真实页面组件。
|
||||
|
||||
### 风险评估
|
||||
| 风险 | 等级 | 应对 |
|
||||
|------|------|------|
|
||||
| 主题切换没有独立 `switchTheme` 路由 | 中 | 复用 `config/save` 的 `frontend_theme` 保存链路,由后端内部触发 `ThemeService::switch` |
|
||||
| 主题配置字段完全动态,前端容易误假设字段类型 | 中 | 仅支持后端 schema 已声明的 `input / textarea / select` 三类字段 |
|
||||
| 本地缺少后台登录态与浏览器截图工具 | 低 | 本轮以构建通过 + 代码级视觉自检作为验收证据,并在知识库中注明限制 |
|
||||
|
||||
---
|
||||
|
||||
## 3. 技术决策
|
||||
|
||||
### admin-frontend-theme-management#D001: 主题切换复用 `config/save(frontend_theme)`,不前端直连未开放路由
|
||||
**日期**: 2026-04-24
|
||||
**状态**: ✅采纳
|
||||
**背景**: 后端 `ThemeController` 存在 `switchTheme()`,但当前管理路由未公开对应 endpoint。
|
||||
**决策**: 前端将“设为当前主题”统一走 `saveAdminConfig({ frontend_theme })`。
|
||||
**理由**: 这条链路已被 `ConfigController` 正式支持,且内部会触发 `ThemeService->switch`,无需扩展后端接口。
|
||||
|
||||
### admin-frontend-theme-management#D002: 主题配置使用右侧抽屉,不在卡片内直接展开表单
|
||||
**日期**: 2026-04-24
|
||||
**状态**: ✅采纳
|
||||
**背景**: 参考图强调卡片式主题列表;主题配置字段是动态 schema,直接展开会破坏列表节奏。
|
||||
**决策**: 卡片只承载主题信息与主操作,详细配置统一放进 `ThemeConfigDrawer`。
|
||||
**理由**: 更贴合 Apple 化后台“主列表 + 聚焦设置面板”的结构,也便于后续扩展删除/预览等动作。
|
||||
@@ -0,0 +1,54 @@
|
||||
# 任务清单: admin-frontend-theme-management
|
||||
|
||||
> **@status:** completed | 2026-04-24 16:12
|
||||
|
||||
```yaml
|
||||
@feature: admin-frontend-theme-management
|
||||
@created: 2026-04-24
|
||||
@status: completed
|
||||
@mode: R2
|
||||
```
|
||||
|
||||
## 进度概览
|
||||
|
||||
| 完成 | 失败 | 跳过 | 总数 |
|
||||
|------|------|------|------|
|
||||
| 5 | 0 | 0 | 5 |
|
||||
|
||||
---
|
||||
|
||||
## 任务列表
|
||||
|
||||
### 1. 数据与路由准备
|
||||
|
||||
- [√] 1.1 在 `admin-frontend/src/types/api.d.ts` 与 `admin-frontend/src/api/admin.ts` 中补齐主题管理类型、配置接口与上传接口 | depends_on: []
|
||||
- [√] 1.2 新增 `admin-frontend/src/utils/themes.ts`,统一处理主题列表排序、动态配置默认值和序列化逻辑 | depends_on: [1.1]
|
||||
- [√] 1.3 在 `admin-frontend/src/router/index.ts` 中把 `system/themes` 路由切换到真实页面 | depends_on: [1.1]
|
||||
|
||||
### 2. 主题管理页面实现
|
||||
|
||||
- [√] 2.1 新增 `admin-frontend/src/views/system/ThemesView.vue`,实现标题区、主题卡片、当前主题标记、切换和上传按钮 | depends_on: [1.1,1.2,1.3]
|
||||
- [√] 2.2 新增 `admin-frontend/src/views/system/ThemeConfigDrawer.vue`,实现主题设置抽屉、动态字段表单与保存动作 | depends_on: [1.1,1.2]
|
||||
|
||||
### 3. 验证与同步
|
||||
|
||||
- [√] 3.1 运行 `admin-frontend` 构建验证,并结合页面代码完成主题管理视觉/交互自检 | depends_on: [2.1,2.2]
|
||||
|
||||
---
|
||||
|
||||
## 执行日志
|
||||
|
||||
| 时间 | 任务 | 状态 | 备注 |
|
||||
|------|------|------|------|
|
||||
| 2026-04-24 16:07 | 方案包初始化 | completed | 已确认本轮范围为主题列表、当前主题切换、主题设置抽屉与上传主题 |
|
||||
| 2026-04-24 16:09 | 1.1 / 1.2 / 1.3 | completed | 已补齐主题类型、API、工具函数,并将 `system/themes` 指向真实页面 |
|
||||
| 2026-04-24 16:11 | 2.1 / 2.2 | completed | 已完成主题卡片页与动态设置抽屉,接入真实主题配置/上传能力 |
|
||||
| 2026-04-24 16:12 | 3.1 | completed | `npm run build` 通过;当前环境缺少后台登录态与浏览器工具,已完成代码级视觉自检 |
|
||||
|
||||
---
|
||||
|
||||
## 执行备注
|
||||
|
||||
- “设为当前主题”当前复用 `config/save(frontend_theme)` 完成,因为管理路由中没有公开独立的主题切换 endpoint。
|
||||
- 本轮未实现删除主题,避免在没有额外确认和危险操作设计的情况下引入破坏性入口。
|
||||
- `public/assets/admin` 为构建产物子模块;本轮构建已刷新对应产物,但未代做子模块提交与根仓发布。
|
||||
+48
@@ -0,0 +1,48 @@
|
||||
{
|
||||
"updatedAt": "2026-04-24T16:20:00+08:00",
|
||||
"version": 1,
|
||||
"source": "manual",
|
||||
"originCommand": "generic-r2",
|
||||
"verifyMode": "build-first",
|
||||
"reviewerFocus": [
|
||||
"订单管理列表结构是否贴近用户提供的后台截图",
|
||||
"详情抽屉是否覆盖查看、手动支付、取消与佣金状态维护主链路"
|
||||
],
|
||||
"testerFocus": [
|
||||
"订单列表是否真实连接 /order/fetch,并响应搜索、筛选、排序与分页",
|
||||
"分配订单抽屉是否真实连接 /order/assign",
|
||||
"详情抽屉是否真实连接 /order/detail /order/paid /order/cancel /order/update"
|
||||
],
|
||||
"ui": {
|
||||
"required": true,
|
||||
"designContract": true,
|
||||
"sourcePriority": [
|
||||
"requirements.md",
|
||||
".helloagents/DESIGN.md",
|
||||
"hello-ui"
|
||||
],
|
||||
"styleAdvisor": {
|
||||
"required": false,
|
||||
"reason": "",
|
||||
"focus": []
|
||||
},
|
||||
"visualValidation": {
|
||||
"required": true,
|
||||
"reason": "订单管理属于真实后台业务页,需要确认列表结构、筛选条与详情抽屉在代码实现上与目标截图和 Apple 化后台契约一致。",
|
||||
"screens": [
|
||||
"#/subscriptions/orders desktop"
|
||||
],
|
||||
"states": [
|
||||
"订单列表默认加载完成态",
|
||||
"分配订单抽屉展开态",
|
||||
"订单详情抽屉展开态"
|
||||
]
|
||||
}
|
||||
},
|
||||
"advisor": {
|
||||
"required": false,
|
||||
"reason": "",
|
||||
"focus": [],
|
||||
"preferredSources": []
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,61 @@
|
||||
# admin-frontend 订单管理首版交付 — 实施规划
|
||||
|
||||
## 目标与范围
|
||||
- 在现有订阅管理分组中补齐订单管理真实页,替换原先的禁用态入口。
|
||||
- 页面聚焦“订单运营工作台”主链路:查订单、分配订单、看详情、手工补单、管理佣金状态。
|
||||
|
||||
## 架构与实现策略
|
||||
- 在现有 `AdminLayout` 中开放 `/subscriptions/orders` 导航入口,并新增对应路由。
|
||||
- 新增 `OrdersView` 作为真实列表页,整体结构参考用户截图:
|
||||
- 顶部标题与说明
|
||||
- “添加订单”主按钮
|
||||
- 搜索框
|
||||
- 类型 / 周期 / 订单状态 / 佣金状态筛选按钮
|
||||
- 数据表格与分页
|
||||
- 新增两个子组件:
|
||||
- `OrderAssignDrawer.vue`:负责手动分配订单
|
||||
- `OrderDetailDrawer.vue`:负责查看详情与行级动作
|
||||
- 在 `src/utils/orders.ts` 中集中处理:
|
||||
- 金额分→元格式化
|
||||
- 类型 / 状态 / 周期映射
|
||||
- 筛选参数组装
|
||||
- 分配订单周期选项生成
|
||||
- API 层在 `src/api/admin.ts` 中新增订单接口封装;类型定义统一收敛到 `src/types/api.d.ts`。
|
||||
|
||||
## 完成定义
|
||||
- 侧边栏中的“订单管理”不再是禁用入口,能正常进入 `#/subscriptions/orders`。
|
||||
- 订单列表可真实连接 `/order/fetch`,并响应搜索、筛选、排序与分页。
|
||||
- 订单详情抽屉可真实连接 `/order/detail`,且能触发已支付、取消、佣金状态更新。
|
||||
- 分配订单抽屉可真实连接 `/order/assign`。
|
||||
- 订单金额相关字段统一正确展示为人民币元值。
|
||||
|
||||
## 文件结构
|
||||
- `admin-frontend/src/router/index.ts`
|
||||
- `admin-frontend/src/layouts/AdminLayout.vue`
|
||||
- `admin-frontend/src/api/admin.ts`
|
||||
- `admin-frontend/src/types/api.d.ts`
|
||||
- `admin-frontend/src/utils/orders.ts`
|
||||
- `admin-frontend/src/views/subscriptions/OrdersView.vue`
|
||||
- `admin-frontend/src/views/subscriptions/OrdersView.scss`
|
||||
- `admin-frontend/src/views/subscriptions/OrderAssignDrawer.vue`
|
||||
- `admin-frontend/src/views/subscriptions/OrderDetailDrawer.vue`
|
||||
|
||||
## UI / 设计约束
|
||||
- 列表页以白色工作台为主,不堆叠多余卡片;重点放在表格可读性与运营效率。
|
||||
- 订单号作为主入口,点击后进入详情抽屉,不额外拉长操作列。
|
||||
- 筛选入口使用紧凑 pill 风格按钮,对齐截图中的轻量筛选条。
|
||||
- 详情抽屉用黑色 hero + 白色信息卡的节奏,兼顾 Apple 风格与运营后台的信息密度。
|
||||
|
||||
## 风险与验证
|
||||
- 风险 1:`/order/fetch` 返回的 `period` 已被后端转换成 legacy key,筛选时需要继续使用数据库真实值。
|
||||
- 风险 2:订单金额与佣金金额在后端仍以分为单位存储,若前端直接展示会再次出现后台金额口径错误。
|
||||
- 风险 3:本地环境缺少真实后台登录态时,只能做结构与构建验证,不能替代完整联调。
|
||||
- 验证方式:
|
||||
- `npm run build`
|
||||
- 代码级结构自检 `#/subscriptions/orders`
|
||||
- 结构化视觉验收记录(无浏览器工具时以 code inspection 说明边界)
|
||||
|
||||
## 决策记录
|
||||
- [2026-04-24] 订单主操作收口到详情抽屉,不额外新增宽操作列,优先对齐用户截图。
|
||||
- [2026-04-24] 金额展示统一由 `src/utils/orders.ts` 处理,避免分/元换算逻辑散落在页面组件。
|
||||
- [2026-04-24] 分配订单抽屉默认按所选套餐周期自动回填金额,但允许运营手动覆盖。
|
||||
+46
@@ -0,0 +1,46 @@
|
||||
# admin-frontend 订单管理首版交付 — 需求
|
||||
|
||||
确认后冻结,执行阶段不可修改。如需变更必须回到设计阶段重新确认。
|
||||
|
||||
## 核心目标
|
||||
- 在 `admin-frontend` 中开放“订阅管理 / 订单管理”入口,不再保留禁用态。
|
||||
- 参考用户提供的订单管理截图,交付真实订单列表页,覆盖搜索、筛选、排序、分页与详情查看。
|
||||
- 保持 `apple/DESIGN.md` 与 `.helloagents/DESIGN.md` 定义的 Apple 化后台视觉语言,但优先贴近截图中的数据密集型运营视图。
|
||||
|
||||
## 功能边界
|
||||
- 必须实现 `#/subscriptions/orders` 真实页面。
|
||||
- 页面必须包含:
|
||||
- 添加订单入口
|
||||
- 订单号搜索
|
||||
- 类型 / 周期 / 订单状态 / 佣金状态筛选
|
||||
- 支持排序的订单表格
|
||||
- 订单详情抽屉
|
||||
- 分配订单抽屉
|
||||
- 必须接入现有 Laravel 管理接口:
|
||||
- `GET /order/fetch`
|
||||
- `POST /order/detail`
|
||||
- `POST /order/assign`
|
||||
- `POST /order/paid`
|
||||
- `POST /order/cancel`
|
||||
- `POST /order/update`
|
||||
- 详情抽屉至少支持:
|
||||
- 查看订单核心信息与金额拆解
|
||||
- 对待支付订单手动标记已支付
|
||||
- 对待支付订单取消
|
||||
- 对有佣金金额的订单更新佣金状态
|
||||
|
||||
## 非目标
|
||||
- 本轮不实现礼品卡管理真实页面。
|
||||
- 本轮不改造 Laravel 订单后端接口逻辑。
|
||||
- 本轮不新增批量操作、多选导出或订单打印等扩展功能。
|
||||
|
||||
## 技术约束
|
||||
- 技术栈固定为 `Vue 3 + TypeScript + Vite + Element Plus`。
|
||||
- 后端真相源以仓库内 `App\Http\Controllers\V2\Admin\OrderController` 为准。
|
||||
- 构建验证使用 `admin-frontend/package.json` 中已有 `npm run build`。
|
||||
|
||||
## 质量要求
|
||||
- 订单页面需要对齐截图中的高密度表格工作流,同时保持 Apple 化后台的克制风格。
|
||||
- 金额字段必须统一处理“后端以分存储、前端以元展示”的换算。
|
||||
- 页面需覆盖加载、错误、空状态与成功反馈。
|
||||
- 最终至少完成一次构建验证,并留下结构化视觉验收与交付证据。
|
||||
@@ -0,0 +1,14 @@
|
||||
# admin-frontend 订单管理首版交付 — 任务分解
|
||||
|
||||
## 任务列表
|
||||
- [x] 任务1:补齐订单管理的方案与知识产物(涉及文件:`.helloagents/archive/2026-04/202604241620_admin-frontend-order-management/*`;完成标准:存在需求、方案、任务与合同文件;验证方式:文件检查)
|
||||
- [x] 任务2:开放导航与路由入口(涉及文件:`admin-frontend/src/layouts/AdminLayout.vue`、`admin-frontend/src/router/index.ts`;完成标准:侧边栏可进入 `#/subscriptions/orders`;验证方式:`npm run build`)
|
||||
- [x] 任务3:补齐订单 API、类型与工具层(涉及文件:`admin-frontend/src/api/admin.ts`、`admin-frontend/src/types/api.d.ts`、`admin-frontend/src/utils/orders.ts`;完成标准:前端可消费 `order/*` 接口并统一金额/状态映射;验证方式:`npm run build`)
|
||||
- [x] 任务4:实现订单列表页(涉及文件:`admin-frontend/src/views/subscriptions/OrdersView.vue`、`admin-frontend/src/views/subscriptions/OrdersView.scss`;完成标准:列表页支持搜索、筛选、排序、分页与详情入口;验证方式:`npm run build`)
|
||||
- [x] 任务5:实现分配订单与详情抽屉(涉及文件:`admin-frontend/src/views/subscriptions/OrderAssignDrawer.vue`、`admin-frontend/src/views/subscriptions/OrderDetailDrawer.vue`;完成标准:支持分配订单、查看详情、手动支付、取消订单与佣金状态维护;验证方式:`npm run build`)
|
||||
- [x] 任务6:完成验证与知识库同步(涉及文件:`.helloagents/CHANGELOG.md`、`.helloagents/context.md`、`.helloagents/modules/admin-frontend.md`、`.helloagents/.ralph-visual.json`、`.helloagents/.ralph-closeout.json`;完成标准:构建通过、知识库更新、交付证据写入;验证方式:命令输出 + 证据文件)
|
||||
|
||||
## 进度
|
||||
- [x] 已确认订单管理首版范围,聚焦真实列表、详情抽屉与分配订单。
|
||||
- [x] 已完成订单管理页面、抽屉与订单接口接入。
|
||||
- [x] 已完成构建验证,待输出最终交付摘要。
|
||||
+11
@@ -0,0 +1,11 @@
|
||||
{
|
||||
"status": "completed",
|
||||
"completed": 3,
|
||||
"failed": 0,
|
||||
"pending": 0,
|
||||
"total": 3,
|
||||
"done": 3,
|
||||
"percent": 100,
|
||||
"current": "全部任务已完成,等待归档方案包",
|
||||
"updated_at": "2026-04-24 17:07:00"
|
||||
}
|
||||
+108
@@ -0,0 +1,108 @@
|
||||
# 变更提案: admin-frontend-sidebar-height-overflow
|
||||
|
||||
## 元信息
|
||||
```yaml
|
||||
类型: 缺陷修复
|
||||
方案类型: implementation
|
||||
优先级: P1
|
||||
状态: 已确认
|
||||
创建: 2026-04-24
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 1. 需求
|
||||
|
||||
### 背景
|
||||
`admin-frontend` 新增系统管理与订阅管理分组后,左侧导航项明显增多。当前 `AdminLayout.vue` 的侧边栏仍采用“Logo + ElMenu 直接铺满”的结构,而 `body` 又被全局设置为 `overflow: hidden`。在用户截图所示的小窗口高度下,底部菜单会被直接裁切,导致“礼品卡管理”“系统管理”“支付配置”等入口无法完整访问。
|
||||
|
||||
### 目标
|
||||
- 修复管理端侧边栏在低视口高度下显示不全的问题。
|
||||
- 按用户已确认的方案,保留顶部 Logo/品牌区固定,仅让菜单区独立纵向滚动。
|
||||
- 保持现有 Apple 风格后台的导航层级、折叠行为和移动端体验不回退。
|
||||
|
||||
### 约束条件
|
||||
```yaml
|
||||
范围约束: 仅处理 admin 侧边栏在低高度下的可访问性与滚动行为,不扩展菜单信息架构
|
||||
技术约束: 继续使用 Vue3 + TypeScript + Element Plus,不新增依赖
|
||||
兼容性约束: 需兼容桌面展开态、折叠态以及现有移动端 fixed aside 行为
|
||||
视觉约束: 延续 apple/DESIGN.md 与 .helloagents/DESIGN.md 的纯白侧栏 + 单一蓝色激活态体系
|
||||
```
|
||||
|
||||
### 验收标准
|
||||
- [ ] 在窗口高度不足时,侧边栏底部菜单项仍可通过纵向滚动访问完整。
|
||||
- [ ] 顶部 Logo/品牌区保持固定,不跟随菜单滚动一起消失。
|
||||
- [ ] 折叠态与移动端侧边栏不出现新的遮挡、抖动或布局错位。
|
||||
- [ ] `admin-frontend` 执行 `npm run build` 通过。
|
||||
|
||||
---
|
||||
|
||||
## 2. 方案
|
||||
|
||||
### 技术方案
|
||||
1. 在 `AdminLayout.vue` 中把侧边栏拆成“固定头部品牌区 + 独立滚动的菜单容器”两层结构,而不是直接让 `ElMenu` 占满整个 `ElAside`。
|
||||
2. 为侧边栏与菜单滚动容器补齐 `min-height: 0`、`overflow-y: auto`、底部留白和滚动条细节,解决 flex 子项在固定高度容器中无法正确收缩的问题。
|
||||
3. 保持现有 `ElMenu`、`ElSubMenu` 和折叠逻辑不变,确保这次修复是针对根因的最小改动,而不是重写导航实现。
|
||||
|
||||
### 影响范围
|
||||
```yaml
|
||||
涉及模块:
|
||||
- admin-frontend: 更新主布局侧边栏结构与样式,修复低高度下菜单裁切
|
||||
- .helloagents/modules/admin-frontend.md: 记录侧边栏低高度滚动规则
|
||||
预计变更文件: 3
|
||||
```
|
||||
|
||||
### 风险评估
|
||||
| 风险 | 等级 | 应对 |
|
||||
|------|------|------|
|
||||
| Element Plus 菜单在滚动容器中出现高度塌陷或双滚动条 | 中 | 采用独立滚动容器并显式补齐 `min-height: 0` 与内边距,避免只在 `ElMenu` 上追加单点样式 |
|
||||
| 移动端 fixed aside 与桌面侧栏样式相互影响 | 中 | 仅在当前侧边栏作用域内增加滚动容器样式,保留现有移动端定位策略 |
|
||||
| 构建会刷新 `public/assets/admin` 构建产物 | 低 | 本轮仅完成本地构建验证,不自动代做子模块发布 |
|
||||
|
||||
---
|
||||
|
||||
## 3. 核心场景
|
||||
|
||||
### 场景: 低高度窗口中的侧边栏导航
|
||||
**模块**: admin-frontend
|
||||
**条件**: 浏览器窗口高度不足以同时容纳品牌区与全部菜单项
|
||||
**行为**: 用户在左侧导航区域滚动菜单
|
||||
**结果**: 顶部品牌区固定可见,菜单项可完整访问,激活态与分组结构保持正常
|
||||
|
||||
---
|
||||
|
||||
## 4. 技术决策
|
||||
|
||||
### admin-frontend-sidebar-height-overflow#D001: 侧边栏采用“固定品牌区 + 独立滚动菜单区”
|
||||
**日期**: 2026-04-24
|
||||
**状态**: ✅采纳
|
||||
**背景**: 用户明确选择“顶部 Logo/品牌区固定,仅菜单区域独立纵向滚动”的处理方式。
|
||||
**选项分析**:
|
||||
| 选项 | 优点 | 缺点 |
|
||||
|------|------|------|
|
||||
| A: 固定品牌区,菜单区独立滚动 | 保留品牌识别和导航定位,改动集中、体验最稳定 | 需要微调侧栏结构和滚动容器样式 |
|
||||
| B: 整个侧边栏整体滚动 | 实现简单 | 品牌区会被滚出视口,低高度下辨识度更差 |
|
||||
| C: 低高度自动折叠成图标栏 | 可压缩空间 | 会改变现有导航行为,且不是用户选定方案 |
|
||||
**决策**: 选择方案 A
|
||||
**理由**: 最符合用户已确认交互,也与当前 Apple 风格后台“固定品牌区 + 稳定导航层级”的设计基线一致。
|
||||
**影响**: 影响 `AdminLayout.vue` 侧边栏结构与样式,不涉及 API、路由或业务数据流。
|
||||
|
||||
---
|
||||
|
||||
## 5. 成果设计
|
||||
|
||||
### 设计方向
|
||||
- **美学基调**: 克制运营后台 —— 保留纯白侧栏、细边框、轻阴影和单一蓝色激活态,让修复更像“增强可用性”而非“换一套皮肤”
|
||||
- **记忆点**: 窗口再矮,顶部品牌区依旧稳定悬停,菜单像独立轨道一样顺滑滚动
|
||||
- **参考**: 现有 `apple/DESIGN.md` 与 `.helloagents/DESIGN.md` 的 Apple 风格后台规范
|
||||
|
||||
### 视觉要素
|
||||
- **配色**: 保持现有 `#ffffff` 侧栏底色、`#0071e3` 激活色和中性文字层级,不引入新强调色
|
||||
- **字体**: 延续全局系统字体栈 `--xboard-font-sans`,不新增字体
|
||||
- **布局**: 侧栏继续分为顶部品牌区与下方菜单区,但改为明确的上下分层,菜单区获得独立滚动上下文
|
||||
- **动效**: 保留当前宽度折叠过渡;滚动本身不增加额外装饰动画
|
||||
- **氛围**: 维持轻薄、低噪音的 Apple 化后台质感,仅补齐滚动可达性
|
||||
|
||||
### 技术约束
|
||||
- **可访问性**: 键盘聚焦与当前菜单激活态不可被滚动修复破坏
|
||||
- **响应式**: 桌面低高度、桌面折叠态和移动端 fixed aside 都需保持可用
|
||||
+42
@@ -0,0 +1,42 @@
|
||||
# 任务清单: admin-frontend-sidebar-height-overflow
|
||||
|
||||
> **@status:** completed | 2026-04-24 17:05
|
||||
|
||||
```yaml
|
||||
@feature: admin-frontend-sidebar-height-overflow
|
||||
@created: 2026-04-24
|
||||
@status: completed
|
||||
@mode: R2
|
||||
```
|
||||
|
||||
## 进度概览
|
||||
|
||||
| 完成 | 失败 | 跳过 | 总数 |
|
||||
|------|------|------|------|
|
||||
| 3 | 0 | 0 | 3 |
|
||||
|
||||
---
|
||||
|
||||
## 任务列表
|
||||
|
||||
- [√] 1. 审查 `admin-frontend/src/layouts/AdminLayout.vue` 当前侧边栏结构与低高度裁切根因,冻结“固定品牌区 + 菜单独立滚动”实现边界 | depends_on: []
|
||||
- [√] 2. 在 `admin-frontend/src/layouts/AdminLayout.vue` 中调整侧边栏结构与样式,修复低高度下菜单显示不全问题 | depends_on: [1]
|
||||
- [√] 3. 运行 `admin-frontend` 构建验证,并同步 `.helloagents/modules/admin-frontend.md` 与 `CHANGELOG.md` 记录本轮修复 | depends_on: [2]
|
||||
|
||||
---
|
||||
|
||||
## 执行日志
|
||||
|
||||
| 时间 | 任务 | 状态 | 备注 |
|
||||
|------|------|------|------|
|
||||
| 2026-04-24 16:55 | 方案包初始化 | completed | 已确认采用“顶部品牌区固定,菜单区域独立纵向滚动”的修复策略 |
|
||||
| 2026-04-24 16:58 | 根因分析 | completed | 已确认裁切来自 `ElAside` 固定高度 + `ElMenu` 缺少独立滚动上下文,菜单区可滚动高度不足 |
|
||||
| 2026-04-24 17:02 | 布局修复 | completed | 已将侧边栏拆为固定品牌区与独立滚动菜单区,并补齐 `min-height: 0` / `overflow-y: auto` 样式 |
|
||||
| 2026-04-24 17:07 | 验证与知识同步 | completed | `npm run build` 通过;Playwright 在 1200x540 视口下确认菜单区 `scrollHeight 1020 > clientHeight 442`,滚动到底后可见系统管理与知识库管理入口 |
|
||||
|
||||
---
|
||||
|
||||
## 执行备注
|
||||
|
||||
- 本轮只修复侧边栏低高度可访问性,不调整菜单信息架构与图标分组。
|
||||
- 构建验证会刷新 `public/assets/admin` 构建产物,本轮仅完成本地实现与验证,不自动代做子模块发布。
|
||||
+11
@@ -0,0 +1,11 @@
|
||||
{
|
||||
"status": "completed",
|
||||
"completed": 4,
|
||||
"failed": 0,
|
||||
"pending": 0,
|
||||
"total": 4,
|
||||
"done": 4,
|
||||
"percent": 100,
|
||||
"current": "权限组管理真实页、节点页联动与构建验证已完成",
|
||||
"updated_at": "2026-04-24 17:10:00"
|
||||
}
|
||||
+166
@@ -0,0 +1,166 @@
|
||||
# 变更提案: admin-frontend-node-group-management
|
||||
|
||||
## 元信息
|
||||
```yaml
|
||||
类型: 功能增强
|
||||
方案类型: implementation
|
||||
优先级: P1
|
||||
状态: 已完成
|
||||
创建: 2026-04-24
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 1. 需求
|
||||
|
||||
### 背景
|
||||
`admin-frontend` 的 `#/node-groups` 目前仍是结构化占位页,而用户已经提供了目标截图,明确要求继续完成“权限组管理”真实工作台。现有 Laravel 后端已经开放 `server/group/fetch`、`server/group/save` 与 `server/group/drop`,节点管理页也已接入权限组筛选,但缺少从权限组页进入节点筛选的维护闭环。
|
||||
|
||||
### 目标
|
||||
- 将 `#/node-groups` 从占位页升级为真实权限组管理页面,支持列表、搜索、添加、编辑、删除。
|
||||
- 列表中直接展示权限组 ID、组名称、用户数量、节点数量,并给出符合截图习惯的操作位。
|
||||
- 补齐与 `#/nodes` 的联动:从权限组页可以一键带筛选跳转到节点页,节点页也能快速回到权限组维护入口。
|
||||
|
||||
### 约束条件
|
||||
```yaml
|
||||
范围约束: 仅实现 admin-frontend 的权限组前端工作台与节点页联动,不改 Laravel 后端接口行为
|
||||
技术约束: 继续使用 Vue3 + TypeScript + Element Plus + 现有 axios/adminClient 栈,不新增第三方状态或表格依赖
|
||||
视觉约束: 以用户截图为直接参考,保留 Apple 化后台的克制留白、系统字体与轻量表格节奏,不套用订阅页黑色 Hero
|
||||
业务约束: 后端真相源固定为 server/group/fetch、server/group/save、server/group/drop;删除失败原因以前端透传后端文案为准
|
||||
```
|
||||
|
||||
### 验收标准
|
||||
- [√] `#/node-groups` 可以展示真实权限组列表,并支持关键字搜索与分页浏览。
|
||||
- [√] 页面支持新增、编辑、删除权限组;新增/编辑使用中央弹窗,删除前有明确确认。
|
||||
- [√] 节点数量支持跳转到 `#/nodes` 并自动带入对应权限组筛选;节点页提供回到权限组维护入口的联动按钮。
|
||||
- [√] `admin-frontend` 执行 `npm run build` 通过,产物可继续输出到 `public/assets/admin`。
|
||||
|
||||
---
|
||||
|
||||
## 2. 方案
|
||||
|
||||
### 技术方案
|
||||
1. 在 `src/types/api.d.ts` 与 `src/api/admin.ts` 中补齐权限组保存请求类型与 `save/delete` 封装。
|
||||
2. 新增 `src/utils/nodeGroups.ts`,统一处理权限组计数归一化、本地搜索和摘要计算,避免视图层堆积业务细节。
|
||||
3. 重写 `NodeGroupsView.vue`,采用“页头说明 + 紧凑工具条 + 白色表格工作台 + 中央编辑弹窗”的结构贴近截图。
|
||||
4. 新增 `NodeGroupEditorDialog.vue` 处理新增/编辑流程;节点数量使用按钮式链接跳转到 `/nodes?group={id}`。
|
||||
5. 轻量补齐 `NodesView.vue`:识别路由查询中的权限组筛选,并提供“管理权限组”入口形成维护闭环。
|
||||
|
||||
### 影响范围
|
||||
```yaml
|
||||
涉及模块:
|
||||
- admin-frontend: 权限组管理真实页、节点页筛选联动、API/类型/工具层补齐
|
||||
- .helloagents: 方案包、模块文档、CHANGELOG 与状态证据同步
|
||||
预计变更文件: 8
|
||||
```
|
||||
|
||||
### 风险评估
|
||||
| 风险 | 等级 | 应对 |
|
||||
|------|------|------|
|
||||
| 后端删除接口因用户/节点/订阅占用返回失败 | 中 | 前端保持后端错误透传,不自行猜测失败原因 |
|
||||
| 节点页联动仅靠前端路由查询,若权限组已删除会产生空筛选 | 低 | 页面加载后校验 query 对应分组是否存在,不存在则自动回退为“全部权限组” |
|
||||
| 新页面过度复用黑色 Hero 会与截图不一致 | 中 | 以截图为最高优先级,改为轻量标题区 + 高密度表格,不强行套用订阅页首屏模式 |
|
||||
|
||||
---
|
||||
|
||||
## 3. 技术设计(可选)
|
||||
|
||||
### API设计
|
||||
#### GET /server/group/fetch
|
||||
- **请求**: 无
|
||||
- **响应**: `AdminServerGroupItem[]`,包含 `id`、`name`、`users_count`、`server_count`
|
||||
|
||||
#### POST /server/group/save
|
||||
- **请求**: `{ id?: number, name: string }`
|
||||
- **响应**: `boolean`
|
||||
|
||||
#### POST /server/group/drop
|
||||
- **请求**: `{ id: number }`
|
||||
- **响应**: `boolean`
|
||||
|
||||
### 数据模型
|
||||
| 字段 | 类型 | 说明 |
|
||||
|------|------|------|
|
||||
| id | number | 权限组 ID |
|
||||
| name | string | 权限组名称 |
|
||||
| users_count | number | 绑定用户数量 |
|
||||
| server_count | number | 绑定节点数量 |
|
||||
|
||||
---
|
||||
|
||||
## 4. 核心场景
|
||||
|
||||
### 场景: 运营新增权限组
|
||||
**模块**: admin-frontend
|
||||
**条件**: 管理员进入 `#/node-groups`
|
||||
**行为**: 点击“添加权限组”,填写组名称并提交
|
||||
**结果**: 列表刷新并出现新的权限组记录
|
||||
|
||||
### 场景: 运营从权限组进入节点排查
|
||||
**模块**: admin-frontend
|
||||
**条件**: 某权限组已存在关联节点
|
||||
**行为**: 在权限组列表点击“节点数量”跳转
|
||||
**结果**: `#/nodes` 自动带入对应权限组筛选,仅展示该组关联节点
|
||||
|
||||
---
|
||||
|
||||
## 5. 技术决策
|
||||
|
||||
### admin-frontend-node-group-management#D001: 权限组页改为截图导向的轻量工作台,而不是延续黑色 Hero
|
||||
**日期**: 2026-04-24
|
||||
**状态**: ✅采纳
|
||||
**背景**: 用户提供的参考图就是目标界面,重点是轻量标题区、工具条和高密度表格。
|
||||
**选项分析**:
|
||||
| 选项 | 优点 | 缺点 |
|
||||
|------|------|------|
|
||||
| A: 延续节点/订阅页的黑色 Hero | 与部分已有页面一致 | 与当前截图不符,页面信息密度被拉低 |
|
||||
| B: 采用截图式轻量工作台 | 更贴近用户目标,便于高频运营维护 | 与部分页面的 Hero 结构不完全统一 |
|
||||
**决策**: 选择方案 B
|
||||
**理由**: 本轮任务已有明确视觉参考,参考优先级高于通用页面套路。
|
||||
**影响**: `NodeGroupsView.vue` 的首屏结构与样式策略
|
||||
|
||||
### admin-frontend-node-group-management#D002: 新增与编辑复用同一个中央弹窗
|
||||
**日期**: 2026-04-24
|
||||
**状态**: ✅采纳
|
||||
**背景**: 后端保存接口统一为 `server/group/save`,截图也展示了中央编辑弹窗。
|
||||
**选项分析**:
|
||||
| 选项 | 优点 | 缺点 |
|
||||
|------|------|------|
|
||||
| A: 新增/编辑拆成两个独立组件 | 职责更独立 | 代码重复,交互不连续 |
|
||||
| B: 统一弹窗组件按模式切换 | 与后端接口一致,界面行为稳定 | 组件需处理回填逻辑 |
|
||||
**决策**: 选择方案 B
|
||||
**理由**: 能最小化重复代码,同时贴合截图中的工作流。
|
||||
**影响**: `NodeGroupEditorDialog.vue` 的设计与表单逻辑
|
||||
|
||||
### admin-frontend-node-group-management#D003: 节点数量列承担“跳转到节点筛选”联动入口
|
||||
**日期**: 2026-04-24
|
||||
**状态**: ✅采纳
|
||||
**背景**: 用户选择了“完整闭环”,不仅要做权限组页,还要补齐节点页联动。
|
||||
**选项分析**:
|
||||
| 选项 | 优点 | 缺点 |
|
||||
|------|------|------|
|
||||
| A: 只做权限组页 CRUD | 实现最小 | 无法形成节点维护闭环 |
|
||||
| B: 在节点数量列加入带筛选跳转,并让节点页识别 query | 联动直接、改动范围可控 | 需要额外处理路由筛选同步 |
|
||||
**决策**: 选择方案 B
|
||||
**理由**: 这是当前范围内成本最低、用户价值最高的联动方式。
|
||||
**影响**: `NodeGroupsView.vue`、`NodesView.vue`
|
||||
|
||||
---
|
||||
|
||||
## 6. 成果设计
|
||||
|
||||
### 设计方向
|
||||
- **美学基调**: 精密运营台账风——保留 Apple 化后台的轻薄分区与系统字体,但将视觉重心收敛到“标题、工具条、表格、弹窗”四个层级,避免营销感首屏
|
||||
- **记忆点**: 大面积留白中的细线表格与圆角操作按钮,让“节点数量可跳转”的数据列成为页面最有识别度的互动点
|
||||
- **参考**: 用户提供的权限组管理截图与编辑弹窗截图
|
||||
|
||||
### 视觉要素
|
||||
- **配色**: 以 `#ffffff` / `#f5f5f7` 为背景层,正文使用 `--xboard-text-strong` 与 `--xboard-text-secondary`,交互强调保持 `#0071e3`
|
||||
- **字体**: 延续项目现有系统字体栈,不额外引入新字体;通过更克制的字号梯度和字重对比强化“台账式”阅读效率
|
||||
- **布局**: 顶部使用轻标题区,正文直接进入紧凑工具条与全宽表格;编辑器保持中央对话框,不用抽屉
|
||||
- **动效**: 仅保留按钮 hover、表格行内操作反馈、分页与弹窗开合的默认 Element Plus 过渡
|
||||
- **氛围**: 依靠细边框、极轻阴影、圆角输入框与足够留白构成“干净但不空”的后台质感
|
||||
|
||||
### 技术约束
|
||||
- **可访问性**: 搜索框、主按钮、编辑/删除操作与节点跳转入口都要保留可见焦点;危险删除继续使用明确确认文案
|
||||
- **响应式**: 桌面优先显示完整表格;窄屏下工具条允许换行,底部分页与统计信息可纵向堆叠
|
||||
+43
@@ -0,0 +1,43 @@
|
||||
# 任务清单: admin-frontend-node-group-management
|
||||
|
||||
> **@status:** completed | 2026-04-24 17:11
|
||||
|
||||
```yaml
|
||||
@feature: admin-frontend-node-group-management
|
||||
@created: 2026-04-24
|
||||
@status: completed
|
||||
@mode: R2
|
||||
```
|
||||
|
||||
## 进度概览
|
||||
|
||||
| 完成 | 失败 | 跳过 | 总数 |
|
||||
|------|------|------|------|
|
||||
| 4 | 0 | 0 | 4 |
|
||||
|
||||
---
|
||||
|
||||
## 任务列表
|
||||
|
||||
- [√] 1. 梳理 `server/group/*` 后端接口、现有 `admin-frontend` 设计契约与节点页联动边界 | depends_on: []
|
||||
- [√] 2. 补齐权限组 API / 类型 / 工具层,并实现新增 / 编辑弹窗 | depends_on: [1]
|
||||
- [√] 3. 重写 `NodeGroupsView` 真实工作台,并补齐 `NodesView` 的权限组筛选联动入口 | depends_on: [1, 2]
|
||||
- [√] 4. 运行 `admin-frontend` 构建验证,更新 `.helloagents` 文档与交付证据 | depends_on: [2, 3]
|
||||
|
||||
---
|
||||
|
||||
## 执行日志
|
||||
|
||||
| 时间 | 任务 | 状态 | 备注 |
|
||||
|------|------|------|------|
|
||||
| 2026-04-24 17:00 | 方案包初始化 | completed | 用户已选择“完整闭环”,本轮范围包含权限组真实页与节点页联动 |
|
||||
| 2026-04-24 17:04 | 页面实现 | completed | 已补齐权限组 API、工具层、中央编辑弹窗与真实列表工作台 |
|
||||
| 2026-04-24 17:07 | 联动实现 | completed | 节点数量列现可跳转 `#/nodes?group={id}`,节点页新增“管理权限组”入口 |
|
||||
| 2026-04-24 17:10 | 构建与文档同步 | completed | `npm run build` 通过,并已更新 `.helloagents` 文档与变更日志 |
|
||||
|
||||
---
|
||||
|
||||
## 执行备注
|
||||
|
||||
- 当前根仓存在其他未归档方案包与历史改动,本轮仅增量修改权限组管理及节点页联动相关文件。
|
||||
- `public/assets/admin` 为前端产物子模块;构建通过后需要同时复核根仓与子模块状态。
|
||||
+49
@@ -0,0 +1,49 @@
|
||||
{
|
||||
"updatedAt": "2026-04-24T09:09:46.384Z",
|
||||
"version": 1,
|
||||
"source": "manual",
|
||||
"originCommand": "generic-r2",
|
||||
"verifyMode": "test-first",
|
||||
"reviewerFocus": [
|
||||
"礼品卡管理整体结构是否贴近用户提供的四页签后台截图",
|
||||
"模板抽屉字段分组是否与截图和现有后端 JSON 结构一致"
|
||||
],
|
||||
"testerFocus": [
|
||||
"礼品卡管理是否真实连接 gift-card/templates、codes、usages、statistics、types 接口",
|
||||
"模板新增编辑是否能正确序列化 conditions、rewards、limits、special_config",
|
||||
"兑换码管理是否支持生成、导出、复制、启停、编辑和删除主链路"
|
||||
],
|
||||
"ui": {
|
||||
"required": true,
|
||||
"designContract": true,
|
||||
"sourcePriority": [
|
||||
"requirements.md",
|
||||
".helloagents/DESIGN.md",
|
||||
"hello-ui"
|
||||
],
|
||||
"styleAdvisor": {
|
||||
"required": false,
|
||||
"reason": "",
|
||||
"focus": []
|
||||
},
|
||||
"visualValidation": {
|
||||
"required": true,
|
||||
"reason": "礼品卡管理属于整页新增的真实后台业务页,需要确认四页签导航、模板表格、模板抽屉和统计卡片在代码结构上与目标截图及 Apple 化后台契约一致。",
|
||||
"screens": [
|
||||
"#/subscriptions/gift-cards desktop"
|
||||
],
|
||||
"states": [
|
||||
"模板管理默认加载完成态",
|
||||
"模板新增抽屉展开态",
|
||||
"兑换码管理列表态",
|
||||
"统计数据总览态"
|
||||
]
|
||||
}
|
||||
},
|
||||
"advisor": {
|
||||
"required": false,
|
||||
"reason": "",
|
||||
"focus": [],
|
||||
"preferredSources": []
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,59 @@
|
||||
# admin-frontend 礼品卡管理首版交付 — 实施规划
|
||||
|
||||
## 目标与范围
|
||||
- 在现有订阅管理分组中补齐礼品卡管理真实页,替换原先的禁用入口。
|
||||
- 页面聚焦“礼品卡运营工作台”主链路:建模板、生成兑换码、查看使用记录、追踪统计数据。
|
||||
|
||||
## 架构与实现策略
|
||||
- 在 `AdminLayout` 中开放 `/subscriptions/gift-cards` 导航入口,并在路由中新增对应页面。
|
||||
- 新增 `GiftCardsView` 作为整页工作台,整体结构参考用户截图:
|
||||
- 顶部标题与说明
|
||||
- 四段式分段导航(模板管理 / 兑换码管理 / 使用记录 / 统计数据)
|
||||
- 每个页签独立的筛选条、表格/卡片内容与操作按钮
|
||||
- 新增两个业务弹层组件:
|
||||
- `GiftCardTemplateDrawer.vue`:负责模板新增与编辑
|
||||
- `GiftCardCodeBatchDialog.vue`:负责批量生成兑换码
|
||||
- 在 `src/utils/giftCards.ts` 中集中处理:
|
||||
- 类型/状态映射
|
||||
- 模板表单序列化与反序列化
|
||||
- 金额(元)/流量(GB)/倍率/日期等展示与提交格式转换
|
||||
- 本地搜索筛选与统计卡片整理
|
||||
- API 层在 `src/api/admin.ts` 中新增礼品卡接口封装;类型定义统一补到 `src/types/api.d.ts`。
|
||||
|
||||
## 完成定义
|
||||
- 侧边栏中的“礼品卡管理”不再是禁用入口,能正常进入 `#/subscriptions/gift-cards`。
|
||||
- 模板管理页可真实连接模板列表与 CRUD 接口,支持搜索、筛选、启停与删除。
|
||||
- 模板抽屉可完整编辑截图展示的主要字段分组,并正确序列化为后端 `conditions / rewards / limits / special_config` 结构。
|
||||
- 兑换码页可真实连接兑换码列表,支持批量生成、复制、启停、导出当前批次、编辑有效期/次数与删除。
|
||||
- 使用记录与统计数据页可真实连接后端数据,不使用硬编码假数据。
|
||||
|
||||
## 文件结构
|
||||
- `admin-frontend/src/layouts/AdminLayout.vue`
|
||||
- `admin-frontend/src/router/index.ts`
|
||||
- `admin-frontend/src/api/admin.ts`
|
||||
- `admin-frontend/src/types/api.d.ts`
|
||||
- `admin-frontend/src/utils/giftCards.ts`
|
||||
- `admin-frontend/src/views/subscriptions/GiftCardsView.vue`
|
||||
- `admin-frontend/src/views/subscriptions/GiftCardsView.scss`
|
||||
- `admin-frontend/src/views/subscriptions/GiftCardTemplateDrawer.vue`
|
||||
- `admin-frontend/src/views/subscriptions/GiftCardCodeBatchDialog.vue`
|
||||
|
||||
## UI / 设计约束
|
||||
- 页面采用“标题说明 + 轻量分段页签 + 白色工作台”的 Apple 化运营后台节奏,不额外叠加夸张 hero 或营销化视觉。
|
||||
- 四个页签保持统一信息架构与表格密度,让用户能快速在模板、兑换码、记录、统计之间切换。
|
||||
- 模板抽屉使用分组 section 和双列表单布局,对齐截图中的信息分区;在窄屏下自动堆叠为单列。
|
||||
- 状态标签、奖励摘要、统计卡片继续沿用单一蓝色强调和语义色状态胶囊,不引入新配色体系。
|
||||
|
||||
## 风险与验证
|
||||
- 风险 1:模板表单字段较多,若直接散落在组件内易导致提交结构和展示结构不一致,因此统一收敛到 `src/utils/giftCards.ts`。
|
||||
- 风险 2:兑换码列表接口不支持关键词搜索,需要前端在当前拉取结果上做本地搜索,并明确这是列表内过滤。
|
||||
- 风险 3:本地环境缺少真实后台登录态时,只能做结构与构建验证,不能替代完整联调。
|
||||
- 验证方式:
|
||||
- `npm run build`
|
||||
- 代码级结构自检 `#/subscriptions/gift-cards`
|
||||
- 结构化视觉验收记录(无浏览器工具时以 code inspection 说明边界)
|
||||
|
||||
## 决策记录
|
||||
- [2026-04-24] 礼品卡管理采用单页四段式导航,而不是四个独立路由,以贴近用户截图中的运营切换路径。
|
||||
- [2026-04-24] 模板抽屉使用分组式大表单,不把复杂字段塞进居中弹窗,以保证高密度配置仍可读。
|
||||
- [2026-04-24] 兑换码导出先按“当前选中批次”提供显式出口,不额外扩展复杂多选批量导出流程。
|
||||
+49
@@ -0,0 +1,49 @@
|
||||
# admin-frontend 礼品卡管理首版交付 — 需求
|
||||
|
||||
确认后冻结,执行阶段不可修改。如需变更必须回到设计阶段重新确认。
|
||||
|
||||
## 核心目标
|
||||
- 在 `admin-frontend` 中开放“订阅管理 / 礼品卡管理”入口,不再保留禁用态。
|
||||
- 参考用户提供的 5 张截图,交付礼品卡管理真实工作台,覆盖模板管理、兑换码管理、使用记录与统计数据四个页签。
|
||||
- 保持 `apple/DESIGN.md` 与 `.helloagents/DESIGN.md` 定义的 Apple 化后台视觉语言,同时优先贴近截图中的高密度运营视图与轻量分段导航。
|
||||
|
||||
## 功能边界
|
||||
- 必须实现 `#/subscriptions/gift-cards` 真实页面。
|
||||
- 页面必须包含:
|
||||
- 顶部标题说明与四段式页签导航
|
||||
- 模板管理列表、搜索、类型/状态筛选、显隐切换、新增/编辑、删除
|
||||
- 模板新增/编辑大表单,覆盖基础配置、奖励内容、使用条件、使用限制、特殊配置、显示效果
|
||||
- 兑换码管理列表、模板/状态筛选、复制、启停、编辑、删除、批量生成、批次导出
|
||||
- 使用记录列表与用户邮箱搜索
|
||||
- 统计数据总览,至少展示模板总数、活跃模板数、兑换码总数、已使用兑换码
|
||||
- 必须接入现有 Laravel 管理接口:
|
||||
- `GET /gift-card/templates`
|
||||
- `POST /gift-card/create-template`
|
||||
- `POST /gift-card/update-template`
|
||||
- `POST /gift-card/delete-template`
|
||||
- `POST /gift-card/generate-codes`
|
||||
- `GET /gift-card/codes`
|
||||
- `POST /gift-card/toggle-code`
|
||||
- `GET /gift-card/export-codes`
|
||||
- `POST /gift-card/update-code`
|
||||
- `POST /gift-card/delete-code`
|
||||
- `GET /gift-card/usages`
|
||||
- `GET /gift-card/statistics`
|
||||
- `GET /gift-card/types`
|
||||
|
||||
## 非目标
|
||||
- 本轮不改造 Laravel 礼品卡后端逻辑、校验规则或数据库结构。
|
||||
- 本轮不实现用户端礼品卡兑换体验。
|
||||
- 本轮不引入复杂图表库,只使用现有栈完成统计展示。
|
||||
|
||||
## 技术约束
|
||||
- 技术栈固定为 `Vue 3 + TypeScript + Vite + Element Plus`。
|
||||
- 后端真相源以仓库内 `App\Http\Controllers\V2\Admin\GiftCardController`、`GiftCardTemplate`、`GiftCardCode` 与 `GiftCardUsage` 为准。
|
||||
- 构建验证使用 `admin-frontend/package.json` 中已有 `npm run build`。
|
||||
- 构建产物继续输出到 `public/assets/admin` 子模块。
|
||||
|
||||
## 质量要求
|
||||
- 礼品卡页面需要对齐截图中的运营后台结构:白色工作台、轻量页签、克制筛选条、高密度表格。
|
||||
- 表单字段需要覆盖加载、保存、取消、校验失败与成功提示等基本状态。
|
||||
- 金额、流量、时间与倍率展示必须按人类可读方式格式化,不直接暴露原始后端数值。
|
||||
- 最终至少完成一次构建验证,并留下结构化视觉验收与交付证据。
|
||||
+14
@@ -0,0 +1,14 @@
|
||||
# admin-frontend 礼品卡管理首版交付 — 任务分解
|
||||
|
||||
## 任务列表
|
||||
- [x] 任务1:补齐礼品卡管理方案与合同产物(涉及文件:`.helloagents/plans/202604241703_admin-frontend-gift-card-management/*`;完成标准:存在需求、方案、任务与合同文件;验证方式:文件检查)
|
||||
- [x] 任务2:开放礼品卡导航与路由入口(涉及文件:`admin-frontend/src/layouts/AdminLayout.vue`、`admin-frontend/src/router/index.ts`;完成标准:侧边栏可进入 `#/subscriptions/gift-cards`;验证方式:`npm run build`)
|
||||
- [x] 任务3:补齐礼品卡 API、类型与工具层(涉及文件:`admin-frontend/src/api/admin.ts`、`admin-frontend/src/types/api.d.ts`、`admin-frontend/src/utils/giftCards.ts`;完成标准:前端可消费 `gift-card/*` 接口并统一完成字段映射;验证方式:`npm run build`)
|
||||
- [x] 任务4:实现礼品卡管理主页面(涉及文件:`admin-frontend/src/views/subscriptions/GiftCardsView.vue`、`admin-frontend/src/views/subscriptions/GiftCardsView.scss`;完成标准:四个页签支持真实数据展示、搜索筛选、表格/统计渲染与关键操作入口;验证方式:`npm run build`)
|
||||
- [x] 任务5:实现模板抽屉与兑换码生成弹层(涉及文件:`admin-frontend/src/views/subscriptions/GiftCardTemplateDrawer.vue`、`admin-frontend/src/views/subscriptions/GiftCardCodeBatchDialog.vue`;完成标准:支持模板新增/编辑与兑换码批量生成;验证方式:`npm run build`)
|
||||
- [x] 任务6:完成验证与知识库同步(涉及文件:`.helloagents/CHANGELOG.md`、`.helloagents/context.md`、`.helloagents/modules/admin-frontend.md`、`.helloagents/.ralph-visual.json`、`.helloagents/.ralph-closeout.json`;完成标准:构建通过、知识库更新、交付证据写入;验证方式:命令输出 + 证据文件)
|
||||
|
||||
## 进度
|
||||
- [x] 已确认礼品卡管理按完整四页签首版推进。
|
||||
- [x] 已完成礼品卡管理真实页面、模板抽屉、兑换码生成弹层与后端接口接入。
|
||||
- [x] 已完成构建验证,待输出最终交付摘要。
|
||||
+11
@@ -0,0 +1,11 @@
|
||||
{
|
||||
"status": "completed",
|
||||
"completed": 5,
|
||||
"failed": 0,
|
||||
"pending": 0,
|
||||
"total": 5,
|
||||
"done": 5,
|
||||
"percent": 100,
|
||||
"current": "订单页佣金状态修复、真实待确认筛选与单行确认菜单已完成",
|
||||
"updated_at": "2026-04-24 22:26:00"
|
||||
}
|
||||
+179
@@ -0,0 +1,179 @@
|
||||
# 变更提案: admin-frontend-orders-commission-confirmation
|
||||
|
||||
## 元信息
|
||||
```yaml
|
||||
类型: 缺陷修复
|
||||
方案类型: implementation
|
||||
优先级: P1
|
||||
状态: 已完成
|
||||
创建: 2026-04-24
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 1. 需求
|
||||
|
||||
### 背景
|
||||
`admin-frontend` 的 `#/subscriptions/orders` 订单管理页目前直接按 `commission_status` 渲染佣金状态。由于后端很多“无佣金订单”默认也会带 `commission_status = 0`,页面把这些订单一并显示成“待确认”,造成运营误判。同时,列表页缺少直接面向“真实待确认佣金订单”的筛选与快捷确认入口,只能进入详情抽屉手动改状态,效率较低。
|
||||
|
||||
### 目标
|
||||
- 修复无佣金订单被误显示为“待确认”的问题,让列表与详情抽屉的佣金状态表达与真实业务一致。
|
||||
- 在订单页增加“确认佣金”菜单,能一键筛出真实待确认的佣金订单。
|
||||
- 在列表行级菜单中加入“确认佣金”快捷操作,把真实待确认订单手动确认到“发放中”。
|
||||
- 保留详情抽屉内现有佣金状态维护能力,确保列表与详情行为一致。
|
||||
|
||||
### 约束条件
|
||||
```yaml
|
||||
时间约束: 本轮只处理 admin 订单页佣金可视化与确认流程,不扩展到返佣任务或提现模块
|
||||
性能约束: 继续复用现有 order/fetch 与 order/update 接口,不新增重型列表查询
|
||||
兼容性约束: 保持现有订单详情抽屉、佣金状态枚举与 Apple 风格后台视觉一致
|
||||
业务约束: “真实待确认”必须排除无佣金订单;列表快捷确认仅把状态改为 1(发放中),不直接标记为已发放
|
||||
验证约束: 优先执行 admin-frontend 的 Vite 构建验证;本地不依赖额外后端联调环境
|
||||
```
|
||||
|
||||
### 验收标准
|
||||
- [ ] 无佣金订单在列表和详情中不再显示为“待确认”,而是明确显示“无佣金”
|
||||
- [ ] 点击“确认佣金”菜单后,可筛出真实待确认的佣金订单,不再混入无佣金订单
|
||||
- [ ] 列表行级菜单可直接对真实待确认订单执行“确认佣金”,并把状态更新为“发放中”
|
||||
- [ ] 详情抽屉中的佣金状态展示与可编辑条件和列表保持一致
|
||||
- [ ] `admin-frontend` 构建通过
|
||||
- [ ] `.helloagents` 文档与变更记录已同步
|
||||
|
||||
---
|
||||
|
||||
## 2. 方案
|
||||
|
||||
### 技术方案
|
||||
1. 在 `admin-frontend/src/utils/orders.ts` 中抽出“是否存在真实佣金”的统一判定逻辑,优先根据 `commission_balance` / `actual_commission_balance` 和已进入发放链路的状态综合判断,而不是单看默认的 `commission_status`。
|
||||
2. 调整佣金状态标签生成逻辑:无真实佣金的订单统一返回“无佣金”,佣金状态筛选仍保留原有枚举,但当前端进入佣金筛选场景时,自动附加后端已有的 `is_commission=true` 参数,利用服务端过滤能力排除无佣金订单。
|
||||
3. 在订单页工具栏增加“确认佣金”菜单,提供“真实待确认订单 / 全部佣金订单 / 清空佣金筛选”三个快捷入口,帮助运营快速切换到真实佣金工作流。
|
||||
4. 在列表新增行级操作列,保留“查看详情”,并对真实待确认订单提供“确认佣金”快捷项;执行时复用现有 `/order/update` 接口,把 `commission_status` 更新为 `1`。
|
||||
5. 同步更新订单详情抽屉的佣金状态文案与操作判定,确保列表页和详情页对“无佣金 / 待确认 / 发放中 / 已发放 / 无效”的解释一致。
|
||||
|
||||
### 影响范围
|
||||
```yaml
|
||||
涉及模块:
|
||||
- admin-frontend/src/utils/orders.ts: 统一佣金状态判定、筛选标签与可编辑条件
|
||||
- admin-frontend/src/views/subscriptions/OrdersView.vue: 增加确认佣金菜单、真实佣金筛选与行级快捷确认
|
||||
- admin-frontend/src/views/subscriptions/OrdersView.scss: 补充菜单/操作列样式
|
||||
- admin-frontend/src/views/subscriptions/OrderDetailDrawer.vue: 同步佣金状态文案与操作可见性
|
||||
预计变更文件: 4
|
||||
```
|
||||
|
||||
### 风险评估
|
||||
| 风险 | 等级 | 应对 |
|
||||
|------|------|------|
|
||||
| 历史订单存在 `commission_balance = 0` 但已进入发放链路 | 中 | 真实佣金判定同时纳入 `actual_commission_balance` 与已发放/无效状态,避免误判为无佣金 |
|
||||
| 列表快捷确认与详情抽屉状态维护不一致 | 中 | 两处统一复用 `orders.ts` 的判定与状态 meta,更新后统一刷新列表/详情 |
|
||||
| 佣金筛选逻辑过于隐蔽导致运营不易理解 | 低 | 工具栏新增显式“确认佣金”菜单,并在激活时显示提示文案,说明当前只展示真实佣金订单 |
|
||||
|
||||
---
|
||||
|
||||
## 3. 技术设计(可选)
|
||||
|
||||
> 本轮不新增接口与数据结构,复用现有后端能力,保留该节用于说明前后端数据流。
|
||||
|
||||
### 架构设计
|
||||
```mermaid
|
||||
flowchart TD
|
||||
A[OrdersView 工具栏菜单] --> B[fetchOrders is_commission=true]
|
||||
A --> C[行级操作菜单]
|
||||
C --> D[/order/update commission_status=1]
|
||||
B --> E[订单表格]
|
||||
E --> F[OrderDetailDrawer]
|
||||
F --> D
|
||||
```
|
||||
|
||||
### API设计
|
||||
#### GET /order/fetch
|
||||
- **请求**: 现有分页参数 + `filter` + `is_commission?: true`
|
||||
- **响应**: 订单列表;当前端处于佣金工作流时,由后端过滤掉无邀请人、待支付/已取消、佣金金额为 0 的记录
|
||||
|
||||
#### POST /order/update
|
||||
- **请求**: `{ trade_no: string, commission_status: 1 }`
|
||||
- **响应**: `ApiResponse<boolean>`
|
||||
|
||||
### 数据模型
|
||||
| 字段 | 类型 | 说明 |
|
||||
|------|------|------|
|
||||
| commission_balance | number | 应付佣金额;大于 0 时优先认定为真实佣金订单 |
|
||||
| actual_commission_balance | number \| null | 已实际发放佣金;用于兜底识别已进入发放链路的历史订单 |
|
||||
| commission_status | number \| null | 0 待确认 / 1 发放中 / 2 已发放 / 3 无效 |
|
||||
|
||||
---
|
||||
|
||||
## 4. 核心场景
|
||||
|
||||
> 执行完成后同步到对应模块文档
|
||||
|
||||
### 场景: 运营筛出真实待确认佣金订单
|
||||
**模块**: admin-frontend / subscriptions / orders
|
||||
**条件**: 订单列表页已加载,存在部分真实佣金待确认订单
|
||||
**行为**: 用户点击“确认佣金”菜单中的“真实待确认订单”
|
||||
**结果**: 列表切换为仅展示 `commission_status = 0` 且真实存在佣金的订单
|
||||
|
||||
### 场景: 运营在列表中手动确认佣金
|
||||
**模块**: admin-frontend / subscriptions / orders
|
||||
**条件**: 某条订单属于真实待确认佣金订单
|
||||
**行为**: 用户在该行操作菜单点击“确认佣金”
|
||||
**结果**: 调用 `/order/update` 把佣金状态更新为“发放中”,列表状态即时刷新
|
||||
|
||||
### 场景: 无佣金订单被正确标记
|
||||
**模块**: admin-frontend / subscriptions / orders
|
||||
**条件**: 订单的 `commission_balance = 0`,且未进入发放链路
|
||||
**行为**: 用户查看列表或详情抽屉中的佣金状态
|
||||
**结果**: 页面明确显示“无佣金”,不再误导为“待确认”
|
||||
|
||||
---
|
||||
|
||||
## 5. 技术决策
|
||||
|
||||
> 本方案涉及的技术决策,归档后成为决策的唯一完整记录
|
||||
|
||||
### admin-frontend-orders-commission-confirmation#D001: 真实佣金判定以金额和发放链路为准,不再单看默认 commission_status
|
||||
**日期**: 2026-04-24
|
||||
**状态**: ✅采纳
|
||||
**背景**: 当前无佣金订单也可能落在 `commission_status = 0`,如果前端只按状态展示,会把“默认值”误渲染成“待确认”。
|
||||
**选项分析**:
|
||||
| 选项 | 优点 | 缺点 |
|
||||
|------|------|------|
|
||||
| A: 继续只看 commission_status | 改动最小 | 会持续把无佣金订单误判成待确认 |
|
||||
| B: 以佣金金额/实际发放金额/已进入发放链路状态综合判断 | 业务语义更准确 | 需要统一封装前端判定逻辑 |
|
||||
**决策**: 选择方案 B
|
||||
**理由**: 能同时覆盖无佣金订单、已发放历史订单和无效佣金订单,最符合真实业务语义。
|
||||
**影响**: `orders.ts` 的状态映射、订单列表渲染、详情抽屉可编辑条件
|
||||
|
||||
### admin-frontend-orders-commission-confirmation#D002: 列表页新增“确认佣金”快捷菜单与单行确认,而不是只依赖详情抽屉
|
||||
**日期**: 2026-04-24
|
||||
**状态**: ✅采纳
|
||||
**背景**: 用户明确要求在当前页面把真实待确认佣金筛出来并能手动确认,同时在上一轮选择了“列表页新增单行快捷确认,并保留详情抽屉”。
|
||||
**选项分析**:
|
||||
| 选项 | 优点 | 缺点 |
|
||||
|------|------|------|
|
||||
| A: 只保留详情抽屉确认 | 实现最少 | 无法满足当前页快速筛选与快捷确认诉求 |
|
||||
| B: 列表页加快捷菜单与行级确认,详情抽屉保留完整状态维护 | 符合运营工作流,效率更高 | 需要补充操作列与筛选状态管理 |
|
||||
**决策**: 选择方案 B
|
||||
**理由**: 与用户确认选项一致,且能把“筛选 + 确认”闭环留在一个工作台内完成。
|
||||
**影响**: `OrdersView.vue` / `OrdersView.scss` 需要新增工具栏菜单、操作列和交互反馈
|
||||
|
||||
---
|
||||
|
||||
## 6. 成果设计
|
||||
|
||||
> 含视觉产出的任务由 DESIGN Phase2 填充。非视觉任务整节标注"N/A"。
|
||||
|
||||
### 设计方向
|
||||
- **美学基调**: Apple 风格的高密度运营工作台 —— 黑色静默首屏、白色精密工作区、蓝色交互信号,新增能力保持“像系统功能自然长出来”的克制感
|
||||
- **记忆点**: 订单页工具栏里新增一颗明确的“确认佣金”工作流胶囊按钮,进入后列表与行级操作形成连续确认闭环
|
||||
- **参考**: `apple/DESIGN.md`、`.helloagents/DESIGN.md`、当前订单页截图
|
||||
|
||||
### 视觉要素
|
||||
- **配色**: 延续现有 `#000000 / #f5f5f7 / #ffffff` 主场与 `#0071e3` 交互强调色;无佣金状态使用中性灰,不与真实待确认的橙色混淆
|
||||
- **字体**: 继续遵循项目既有 Apple 化系统字体栈,不引入新字体,只通过字重与字距维持信息层级
|
||||
- **布局**: 保持现有单层工具栏结构,在筛选胶囊群中补入“确认佣金”菜单;表格右侧新增轻量操作列,不打断订单号点击查看详情的主路径
|
||||
- **动效**: 仅保留按钮 hover、菜单展开和状态更新后的即时消息反馈,不引入额外炫技动画
|
||||
- **氛围**: 继续使用纯白工作台、轻阴影容器和圆角胶囊控件,让新增能力自然融入当前后台节奏
|
||||
|
||||
### 技术约束
|
||||
- **可访问性**: 菜单项与操作按钮保持可聚焦、文案明确,不只靠颜色传达佣金状态
|
||||
- **响应式**: 延续当前订单页在窄屏下工具栏换行与表格横向滚动策略,不额外引入新断点
|
||||
+50
@@ -0,0 +1,50 @@
|
||||
# 任务清单: admin-frontend-orders-commission-confirmation
|
||||
|
||||
> **@status:** completed | 2026-04-24 22:29
|
||||
|
||||
```yaml
|
||||
@feature: admin-frontend-orders-commission-confirmation
|
||||
@created: 2026-04-24
|
||||
@status: completed
|
||||
@mode: R2
|
||||
```
|
||||
|
||||
## 进度概览
|
||||
|
||||
| 完成 | 失败 | 跳过 | 总数 |
|
||||
|------|------|------|------|
|
||||
| 5 | 0 | 0 | 5 |
|
||||
|
||||
---
|
||||
|
||||
## 任务列表
|
||||
|
||||
### 1. 佣金状态判定与页面交互
|
||||
|
||||
- [√] 1.1 在 `admin-frontend/src/utils/orders.ts` 中统一真实佣金判定与状态映射,修复无佣金订单误显示为“待确认” | depends_on: []
|
||||
- [√] 1.2 在 `admin-frontend/src/views/subscriptions/OrdersView.vue` 中接入真实佣金筛选状态,新增“确认佣金”菜单并在列表请求中透传 `is_commission` | depends_on: [1.1]
|
||||
- [√] 1.3 在 `admin-frontend/src/views/subscriptions/OrdersView.vue` 与 `OrdersView.scss` 中增加行级操作列,为真实待确认订单提供“确认佣金”快捷操作与状态提示 | depends_on: [1.2]
|
||||
|
||||
### 2. 一致性与验收
|
||||
|
||||
- [√] 2.1 在 `admin-frontend/src/views/subscriptions/OrderDetailDrawer.vue` 中同步佣金状态文案与可编辑条件,确保列表与详情一致 | depends_on: [1.1]
|
||||
- [√] 2.2 执行 `admin-frontend` 构建验证,并同步 `.helloagents` 记录与变更说明 | depends_on: [1.3, 2.1]
|
||||
|
||||
---
|
||||
|
||||
## 执行日志
|
||||
|
||||
| 时间 | 任务 | 状态 | 备注 |
|
||||
|------|------|------|------|
|
||||
| 2026-04-24 22:17 | 方案设计 | completed | 已确认采用“列表页确认佣金菜单 + 单行快捷确认 + 保留详情抽屉”方案 |
|
||||
| 2026-04-24 22:20 | 佣金判定修复 | completed | `orders.ts` 新增真实佣金判定,列表/详情统一改为无佣金不再显示待确认 |
|
||||
| 2026-04-24 22:22 | 订单页交互增强 | completed | 订单工具栏新增“确认佣金”菜单,佣金状态筛选自动透传 `is_commission=true` |
|
||||
| 2026-04-24 22:24 | 行级确认接入 | completed | 列表新增操作列,可对真实待确认订单直接确认为“发放中” |
|
||||
| 2026-04-24 22:26 | 构建与文档同步 | completed | `npm run build` 通过,准备归档方案包并更新知识库记录 |
|
||||
|
||||
---
|
||||
|
||||
## 执行备注
|
||||
|
||||
- 当前后端已具备 `GET /order/fetch?is_commission=true` 与 `POST /order/update` 能力,本轮优先复用现有接口,不新增后端 API。
|
||||
- 若本地构建外存在后端联调缺口,需以 `admin-frontend` 构建结果作为本轮最低验证证据,并在交付中明确说明。
|
||||
+11
@@ -0,0 +1,11 @@
|
||||
{
|
||||
"status": "completed",
|
||||
"completed": 5,
|
||||
"failed": 0,
|
||||
"pending": 0,
|
||||
"total": 5,
|
||||
"done": 5,
|
||||
"percent": 100,
|
||||
"current": "节点管理分页、置顶、批量修改与父子筛选已完成",
|
||||
"updated_at": "2026-04-24 23:02:00"
|
||||
}
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user