diff --git a/package.json b/package.json index 5fb4b98..3834c4b 100644 --- a/package.json +++ b/package.json @@ -9,8 +9,6 @@ "preview": "vite preview" }, "dependencies": { - "tailwindcss": "^4.1.4", - "vue": "^3.5.13", "@ant-design-vue/pro-layout": "^3.2.5", "@ant-design/icons-vue": "^7.0.1", "@fortawesome/fontawesome-free": "^6.7.2", @@ -18,11 +16,14 @@ "@vueuse/head": "^2.0.0", "ant-design-vue": "^4.1.1", "axios": "^1.6.2", + "exceljs": "^4.4.0", "lucide-vue-next": "^0.507.0", + "md-editor-v3": "^7.1.0", "pinia": "^2.1.7", "swiper": "^11.0.5", + "tailwindcss": "^4.1.4", + "vue": "^3.5.13", "vue-router": "^4.2.5", - "exceljs": "^4.4.0", "xlsx": "^0.18.5" }, "devDependencies": { diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 1823c26..3954006 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -35,6 +35,9 @@ importers: lucide-vue-next: specifier: ^0.507.0 version: 0.507.0(vue@3.5.13) + md-editor-v3: + specifier: ^7.1.0 + version: 7.1.0(vue@3.5.13) pinia: specifier: ^2.1.7 version: 2.3.1(vue@3.5.13) @@ -109,6 +112,96 @@ packages: resolution: {integrity: sha512-H45s8fVLYjbhFH62dIJ3WtmJ6RSPt/3DRO0ZcT2SUiYiQyz3BLVb9ADEnLl91m74aQPS3AzzeajZHYOalWe3bg==} engines: {node: '>=6.9.0'} + '@codemirror/autocomplete@6.20.3': + resolution: {integrity: sha512-tlosUqb+3BbxCxZdu4tKeRghPFC+QM7q4X5YhKV2eCmPG+1r2F3f4AaSz5sCrFqUtX4Jh20VFTKecl16MgiV9g==} + + '@codemirror/commands@6.11.1': + resolution: {integrity: sha512-O/4hG3SC1YwcmQ0d2UVNDs+AsaNWd1iHVxbTeEBuqH+6bExAiPK3iS/BvpY6rZGURALv4ZD3sIgcCmRvw3ehBg==} + + '@codemirror/lang-angular@0.1.4': + resolution: {integrity: sha512-oap+gsltb/fzdlTQWD6BFF4bSLKcDnlxDsLdePiJpCVNKWXSTAbiiQeYI3UmES+BLAdkmIC1WjyztC1pi/bX4g==} + + '@codemirror/lang-cpp@6.0.3': + resolution: {integrity: sha512-URM26M3vunFFn9/sm6rzqrBzDgfWuDixp85uTY49wKudToc2jTHUrKIGGKs+QWND+YLofNNZpxcNGRynFJfvgA==} + + '@codemirror/lang-css@6.3.1': + resolution: {integrity: sha512-kr5fwBGiGtmz6l0LSJIbno9QrifNMUusivHbnA1H6Dmqy4HZFte3UAICix1VuKo0lMPKQr2rqB+0BkKi/S3Ejg==} + + '@codemirror/lang-go@6.0.1': + resolution: {integrity: sha512-7fNvbyNylvqCphW9HD6WFnRpcDjr+KXX/FgqXy5H5ZS0eC5edDljukm/yNgYkwTsgp2busdod50AOTIy6Jikfg==} + + '@codemirror/lang-html@6.4.12': + resolution: {integrity: sha512-pw2ReWKUqSkbvh76RAT4NYxiogRu+PWkR2ukAwO9uOgrm8uipkzjtKKtNpyeAQwHOqxEeSvAXZ6vr3AfyB9y/w==} + + '@codemirror/lang-java@6.0.2': + resolution: {integrity: sha512-m5Nt1mQ/cznJY7tMfQTJchmrjdjQ71IDs+55d1GAa8DGaB8JXWsVCkVT284C3RTASaY43YknrK2X3hPO/J3MOQ==} + + '@codemirror/lang-javascript@6.2.5': + resolution: {integrity: sha512-zD4e5mS+50htS7F+TYjBPsiIFGanfVqg4HyUz6WNFikgOPf2BgKlx+TQedI1w6n/IqRBVBbBWmGFdLB/7uxO4A==} + + '@codemirror/lang-jinja@6.0.1': + resolution: {integrity: sha512-P5kyHLObzjtbGj16h+hyvZTxJhSjBEeSx4wMjbnAf3b0uwTy2+F0zGjMZL4PQOm/mh2eGZ5xUDVZXgwP783Nsw==} + + '@codemirror/lang-json@6.0.2': + resolution: {integrity: sha512-x2OtO+AvwEHrEwR0FyyPtfDUiloG3rnVTSZV1W8UteaLL8/MajQd8DpvUb2YVzC+/T18aSDv0H9mu+xw0EStoQ==} + + '@codemirror/lang-less@6.0.2': + resolution: {integrity: sha512-EYdQTG22V+KUUk8Qq582g7FMnCZeEHsyuOJisHRft/mQ+ZSZ2w51NupvDUHiqtsOy7It5cHLPGfHQLpMh9bqpQ==} + + '@codemirror/lang-liquid@6.3.2': + resolution: {integrity: sha512-6PDVU3ZnfeYyz1at1E/ttorErZvZFXXt1OPhtfe1EZJ2V2iDFa0CwPqPgG5F7NXN0yONGoBogKmFAafKTqlwIw==} + + '@codemirror/lang-markdown@6.5.2': + resolution: {integrity: sha512-AwBOdkWYuA//WcM0xO5PfHPUcmz/O2i5o0Nsg1U69SII/loCJlFI1Romd9xp2HYb1kYJRGZotyqRghuHH5n8Kw==} + + '@codemirror/lang-php@6.0.2': + resolution: {integrity: sha512-ZKy2v1n8Fc8oEXj0Th0PUMXzQJ0AIR6TaZU+PbDHExFwdu+guzOA4jmCHS1Nz4vbFezwD7LyBdDnddSJeScMCA==} + + '@codemirror/lang-python@6.2.1': + resolution: {integrity: sha512-IRjC8RUBhn9mGR9ywecNhB51yePWCGgvHfY1lWN/Mrp3cKuHr0isDKia+9HnvhiWNnMpbGhWrkhuWOc09exRyw==} + + '@codemirror/lang-rust@6.0.2': + resolution: {integrity: sha512-EZaGjCUegtiU7kSMvOfEZpaCReowEf3yNidYu7+vfuGTm9ow4mthAparY5hisJqOHmJowVH3Upu+eJlUji6qqA==} + + '@codemirror/lang-sass@6.0.2': + resolution: {integrity: sha512-l/bdzIABvnTo1nzdY6U+kPAC51czYQcOErfzQ9zSm9D8GmNPD0WTW8st/CJwBTPLO8jlrbyvlSEcN20dc4iL0Q==} + + '@codemirror/lang-sql@6.10.0': + resolution: {integrity: sha512-6ayPkEd/yRw0XKBx5uAiToSgGECo/GY2NoJIHXIIQh1EVwLuKoU8BP/qK0qH5NLXAbtJRLuT73hx7P9X34iO4w==} + + '@codemirror/lang-vue@0.1.3': + resolution: {integrity: sha512-QSKdtYTDRhEHCfo5zOShzxCmqKJvgGrZwDQSdbvCRJ5pRLWBS7pD/8e/tH44aVQT6FKm0t6RVNoSUWHOI5vNug==} + + '@codemirror/lang-wast@6.0.2': + resolution: {integrity: sha512-Imi2KTpVGm7TKuUkqyJ5NRmeFWF7aMpNiwHnLQe0x9kmrxElndyH0K6H/gXtWwY6UshMRAhpENsgfpSwsgmC6Q==} + + '@codemirror/lang-xml@6.1.0': + resolution: {integrity: sha512-3z0blhicHLfwi2UgkZYRPioSgVTo9PV5GP5ducFH6FaHy0IAJRg+ixj5gTR1gnT/glAIC8xv4w2VL1LoZfs+Jg==} + + '@codemirror/lang-yaml@6.1.3': + resolution: {integrity: sha512-AZ8DJBuXGVHybpBQhmZtgew5//4hv3tdkXnr3vDmOUMJRuB6vn/uuwtmTOTlqEaQFg3hQSVeA90NmvIQyUV6FQ==} + + '@codemirror/language-data@6.5.2': + resolution: {integrity: sha512-CPkWBKrNS8stYbEU5kwBwTf3JB1kghlbh4FSAwzGW2TEscdeHHH4FGysREW86Mqnj3Qn09s0/6Ea/TutmoTobg==} + + '@codemirror/language@6.12.4': + resolution: {integrity: sha512-1q4PaT+o6PbgpkJt4Q8Fv5XJxTy4FUZ4MWETtyiDw3J0Pyr9E2vqcKL+k9wcvjNTIsauxvE7OfmWj3FRPHQ76A==} + + '@codemirror/legacy-modes@6.5.4': + resolution: {integrity: sha512-/cZr6qZyl08iYNLGsJ862CXXNI51LryRFRE40ejgoIjXZz0C1rGkD3/Ek5jM/8w1ceRjqtt4qx/KLMh4zBTgew==} + + '@codemirror/lint@6.9.7': + resolution: {integrity: sha512-28/+iWLYxKxsvGYhSYL7zaCZqLz5+FFFDq9tVsvGv9kv8RY4fFAchJ5WX9M3YrrRlTIsECjsXPqeNgnSmNP2dg==} + + '@codemirror/search@6.7.2': + resolution: {integrity: sha512-gUYkYhT2+n/+VGZ+8EzE5WFkYZUZYm1VOKDudIsNqh42uRVQJ0a6Yss9sdKT3MeOYfuL1N6AZA57oza0Oyr0LA==} + + '@codemirror/state@6.7.6': + resolution: {integrity: sha512-kAz+AncRtKuIknedxT1bq4XwXv4UowhbkHU1myPrtVb/jZtImWuV5BXzv5vK6i3kYACsdiZiQKFQQ5Mq7elW8w==} + + '@codemirror/view@6.43.13': + resolution: {integrity: sha512-sihaFrUzAsYBQsL9J2t69y8nfMQGwcYmggAZsk+kjPbjYZMyuf2hU8tUNTZ+P+isb6XRr8JE22TZlJxBoVdH1A==} + '@ctrl/tinycolor@3.6.1': resolution: {integrity: sha512-SITSV6aIXsuVNV3f3O0f2n/cgyEDWoSqtZMYiAmcsYHydcKrOz3gUxB/iXd/Qf08+IZX4KpgNbvUdMBmWz+kcA==} engines: {node: '>=10'} @@ -282,6 +375,65 @@ packages: '@jridgewell/sourcemap-codec@1.5.0': resolution: {integrity: sha512-gv3ZRaISU3fjPAgNsriBRqGWQL6quFx04YMPW/zD8XMLsU32mhCCbfbO6KZFLjvYpCZ8zyDEgqsgf+PwPaM7GQ==} + '@lezer/common@1.5.3': + resolution: {integrity: sha512-H0iErY4e43LpXbYDyBci5W4v/RwTgGV3YzYOlJPiGZ8RY8w51kVE+xLn1tg3Z6UmSfyETvtsUK3r7YsgDQEI7Q==} + + '@lezer/cpp@1.1.6': + resolution: {integrity: sha512-vh9gWWJOXFVY8HBHK3Twzq8MgwG2iN4GSyzBP9sCGTe37P15x2R14VaBQk0VA0ezTRN1KHYBBsHhvpGZ2Xy/pA==} + + '@lezer/css@1.3.8': + resolution: {integrity: sha512-EJn1zcL9qoDptief6ipWKZKLiOpXkxSe0+t8CH9oiMVcZlq7NBWrjCqnc/41EIjeo/ITj1gFFiATdTkaJDL+Og==} + + '@lezer/go@1.0.1': + resolution: {integrity: sha512-xToRsYxwsgJNHTgNdStpcvmbVuKxTapV0dM0wey1geMMRc9aggoVyKgzYp41D2/vVOx+Ii4hmE206kvxIXBVXQ==} + + '@lezer/highlight@1.2.5': + resolution: {integrity: sha512-O1GMVKgtf5YspFaRzpmqkVgMtIk2HG9uMAbH6wdAIdNh3TVzCsch/+cRi+6l2//UGDKe6NB9BW3cvuR5ezMQ0w==} + + '@lezer/html@1.3.13': + resolution: {integrity: sha512-oI7n6NJml729m7pjm9lvLvmXbdoMoi2f+1pwSDJkl9d68zGr7a9Btz8NdHTGQZtW2DA25ybeuv/SyDb9D5tseg==} + + '@lezer/java@1.1.4': + resolution: {integrity: sha512-gQylJ2xHV2xXsVqtnAcJrcROvLZJaQiC0tR//+q0k961BxqvyYttusPkJ8d9T1fPDJKHJW2etUH8XbIn9jhVUg==} + + '@lezer/javascript@1.5.5': + resolution: {integrity: sha512-sWg4yX1J6XW67AaAynVt0iwF0M5c+np36TEu+P2ifAJ8haRYvHnWDV28r1jdwnJehWCwXECutAUy56K4RBZIyg==} + + '@lezer/json@1.0.3': + resolution: {integrity: sha512-BP9KzdF9Y35PDpv04r0VeSTKDeox5vVr3efE7eBbx3r4s3oNLfunchejZhjArmeieBH+nVOpgIiBJpEAv8ilqQ==} + + '@lezer/lr@1.4.10': + resolution: {integrity: sha512-rnCpTIBafOx4mRp43xOxDJbFipJm/c0cia/V5TiGlhmMa+wsSdoGmUN3w5Bqrks/09Q/D4tNAmWaT8p6NRi77A==} + + '@lezer/markdown@1.7.2': + resolution: {integrity: sha512-iTkYvoVcKt3WkeL7qUDyXHONZEwLio4wj8KTNi2dnjQEXBZKMV63BpQrPqfsM+OkvuRbiSTAcycYAsQzLhRNoQ==} + + '@lezer/php@1.0.6': + resolution: {integrity: sha512-QJ2xNXPmsm/Z3IpThq8fnJrEIVpxhsIoj6GZBW0JYEd/l9zxpJZW216X4fzqQY4vgpdGIumypvI4uQjd4tnYtw==} + + '@lezer/python@1.1.19': + resolution: {integrity: sha512-MhQIURHRytsNzP/YXnqpYKW6la6voAH3kyplTOOiCdjyFY6cWWGFVmYVdHIPrElqSDf4iCDktQCockB9FxuhzQ==} + + '@lezer/rust@1.0.3': + resolution: {integrity: sha512-XxErOjZzQ7yJt1agUT4fu9qQvESZ3acgoxpPaPTPOiUx+duCjaVAtZGFIgphkHxlN05djdVAIOy/wItShMEjqQ==} + + '@lezer/sass@1.1.0': + resolution: {integrity: sha512-3mMGdCTUZ/84ArHOuXWQr37pnf7f+Nw9ycPUeKX+wu19b7pSMcZGLbaXwvD2APMBDOGxPmpK/O6S1v1EvLoqgQ==} + + '@lezer/xml@1.0.6': + resolution: {integrity: sha512-CdDwirL0OEaStFue/66ZmFSeppuL6Dwjlk8qk153mSQwiSH/Dlri4GNymrNWnUmPl2Um7QfV1FO9KFUyX3Twww==} + + '@lezer/yaml@1.0.4': + resolution: {integrity: sha512-2lrrHqxalACEbxIbsjhqGpSW8kWpUKuY6RHgnSAFZa6qK62wvnPxA8hGOwOoDbwHcOFs5M4o27mjGu+P7TvBmw==} + + '@lucide/vue@1.48.0': + resolution: {integrity: sha512-3/Nwx/RsqQ4ZrrSML1GNsSWCSDyLnBgoF/eEr1q9G6iZymn3+WKtzIj7Dbc/Nxrt9WOPuGrJ58S+CBiamK+36w==} + peerDependencies: + vue: '>=3.0.1' + + '@marijn/find-cluster-break@1.0.4': + resolution: {integrity: sha512-Wy0V7+SGUjnF9/TkiM1hKVDPj7jKXduPNboMVtHTA8dySMURWqfg/JZ9E2Sq8JgSJmkl7k7Qe9FLeMSrSraWmQ==} + '@parcel/watcher-android-arm64@2.5.1': resolution: {integrity: sha512-KF8+j9nNbUN8vzOFDpRMsaKBHZ/mcjEjMToVMJOhTozkDonQFFrRcfdLWn6yWKCmJKmdVxSgHiYvTCef4/qcBA==} engines: {node: '>= 10.0.0'} @@ -581,6 +733,15 @@ packages: '@types/estree@1.0.7': resolution: {integrity: sha512-w28IoSUCJpidD/TGviZwwMJckNESJZXFu7NBZ5YJ4mEUnNraUn9Pm8HSZm/jDF1pDWYKspWE7oVphigUPRakIQ==} + '@types/linkify-it@5.0.0': + resolution: {integrity: sha512-sVDA58zAw4eWAffKOaQH5/5j3XeayukzDk+ewSsnv3p4yJEZHCCzMDiZM8e0OUrRvmpGZ85jf4yDHkHsgBNr9Q==} + + '@types/markdown-it@14.2.0': + resolution: {integrity: sha512-NoQ2yGlLWj4wpxMs+TYmRKk3thDrQ97agr7sFqfLsAlvoS8SNQuTrlObhFqG9iugdTtgOE9jpJ6FNM4ZGsa5xQ==} + + '@types/mdurl@2.0.0': + resolution: {integrity: sha512-RGdgjQUZba5p6QEFAVx2OGb8rQDL/cPRG7GiedRzMcJ1tYnUANBncjbSB1NRGwbvjcPeikRABz2nshyPk1bhWg==} + '@types/node@14.18.63': resolution: {integrity: sha512-fAtCfv4jJg+ExtXhvCkCqUKZ+4ok/JQk01qDKhL5BDDoS3AxKXhV5/MAVUZyQnSEd2GT92fkgZl0pz0Q0AzcIQ==} @@ -601,6 +762,15 @@ packages: peerDependencies: vue: '>=2.7 || >=3' + '@vavt/copy2clipboard@1.0.3': + resolution: {integrity: sha512-HtG48r2FBYp9eRvGB3QGmtRBH1zzRRAVvFbGgFstOwz4/DDaNiX0uZc3YVKPydqgOav26pibr9MtoCaWxn7aeA==} + + '@vavt/markdown-theme@6.0.1': + resolution: {integrity: sha512-S6HClmYtnrBuAm+6aeAKRtMwy6cTv+7QlGQYlpNHwumoFr3x86X6uGtJbvrv3ReoKx40vCOJR7h+1OiflKJOWA==} + + '@vavt/util@2.1.2': + resolution: {integrity: sha512-L3UbSJthJwr3wq0x93O5TrCepimrmVZaIl2ciZbeL18G5++gBhJXNhcH7RcVk/6rr3SavWOvwhig0mqRLoR7dw==} + '@vitejs/plugin-vue@5.2.3': resolution: {integrity: sha512-IYSLEQj4LgZZuoVpdSUCw3dIynTWQgPlaRP6iAvMle4My0HdYwr5g5wQAfwOeHQBmYwEkqF70nRpSilr6PoUDg==} engines: {node: ^18.0.0 || >=20.0.0} @@ -667,6 +837,9 @@ packages: resolution: {integrity: sha512-+25nxyyznAXF7Nef3y0EbBeqmGZgeN/BxHX29Rs39djAfaFalmQ89SE6CWyDCHzGL0yt/ycBtNOmGTW0FyGWNw==} engines: {node: '>= 10'} + argparse@2.0.1: + resolution: {integrity: sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==} + array-tree-filter@2.1.0: resolution: {integrity: sha512-4ROwICNlNw/Hqa9v+rk5h22KjmzB1JGTMVKP2AKJBOCgb0yL0ASf0+YvCcLNNwquOHNX48jkeZIJ3a+oOQqKcw==} @@ -740,6 +913,9 @@ packages: resolution: {integrity: sha512-Qgzu8kfBvo+cA4962jnP1KkS6Dop5NS6g7R5LFYJr4b8Ub94PPQXUksCw9PvXoeXPRRddRNC5C1JQUR2SMGtnA==} engines: {node: '>= 14.16.0'} + codemirror@6.0.2: + resolution: {integrity: sha512-VhydHotNW5w1UGK0Qj96BwSk/Zqbp9WbnyK2W/eVMv4QyF41INRGpjUhFJY7/uDNuudSc33a/PKr4iDqRduvHw==} + codepage@1.15.0: resolution: {integrity: sha512-3g6NUTPd/YtuuGrhMnOMRjFc+LJw/bnMp3+0r/Wcz3IXUuCosKRJvMphm5+Q+bvTVGcJJuRvVLuYba+WojaFaA==} engines: {node: '>=0.8'} @@ -748,6 +924,9 @@ packages: resolution: {integrity: sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==} engines: {node: '>= 0.8'} + commander@2.20.3: + resolution: {integrity: sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==} + compress-commons@4.1.2: resolution: {integrity: sha512-D3uMHtGc/fcO1Gt1/L7i1e33VOvD4A9hfQLP+6ewd+BvG/gQ84Yh4oftEhAdjSMgBgwGL+jsppT7JYNpo6MHHg==} engines: {node: '>= 10'} @@ -773,6 +952,12 @@ packages: resolution: {integrity: sha512-NT7w2JVU7DFroFdYkeq8cywxrgjPHWkdX1wjpRQXPX5Asews3tA+Ght6lddQO5Mkumffp3X7GEqku3epj2toIw==} engines: {node: '>= 10'} + crelt@1.0.7: + resolution: {integrity: sha512-aK6BbWfhf4U/wCcLHKPJl/xa6VkVstRaPywWtMKGwuOLc/wZTyQYuoxgvZnNsBvv7Kg3YTBQYYBCggcviQczuA==} + + cssfilter@0.0.10: + resolution: {integrity: sha512-FAaLDaplstoRsDR8XGYH51znUN0UY7nMc6Z9/fvE8EXGwvJE9hu7W2vHwx1+bd6gCYnln9nLbzxFTrcO9YQDZw==} + csstype@3.1.3: resolution: {integrity: sha512-M1uQkMl8rQK/szD0LNhtqxIPLpimGm8sOBwU7lLnCpSbTyY3yeU1Vc7l4KT5zT4s/yOxHH5O7tIuuLOCnLADRw==} @@ -972,6 +1157,11 @@ packages: js-tokens@4.0.0: resolution: {integrity: sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==} + json5@2.2.3: + resolution: {integrity: sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg==} + engines: {node: '>=6'} + hasBin: true + jszip@3.10.2: resolution: {integrity: sha512-3l+rb15IOWtUhU0H5MFqES/T6Kh7abYwjosBey/vD6hDt8zoEffkSC5Ws5SGtgVw3gBx2NEbhTeSW1+kWkpyTQ==} @@ -1050,6 +1240,9 @@ packages: resolution: {integrity: sha512-6b6gd/RUXKaw5keVdSEtqFVdzWnU5jMxTUjA2bVcMNPLwSQ08Sv/UodBVtETLCn7k4S1Ibxwh7k68IwLZPgKaA==} engines: {node: '>= 12.0.0'} + linkify-it@5.0.2: + resolution: {integrity: sha512-ONTm2jCMAVZjgQa/Fy1kScXsuOoF5NPTsoFBdE1KVIZ2vAh/r9+Bqo+0jINCBYnavTPQZz38QzFTme79ENoN3Q==} + listenercount@1.0.1: resolution: {integrity: sha512-3mk/Zag0+IJxeDrxSgaDPy4zZ3w05PRZeJNnlWhzFz5OkX49J4krc+A8X2d2M69vGMBEX0uyl8M+W+8gH+kBqQ==} @@ -1112,10 +1305,37 @@ packages: magic-string@0.30.17: resolution: {integrity: sha512-sNPKHvyjVf7gyjwS4xGTaW/mCnF8wnjtifKBEhxfZ7E/S8tQ0rssrwGNn6q8JH/ohItJfSQp9mBtQYuTlH5QnA==} + markdown-it-image-figures@2.1.1: + resolution: {integrity: sha512-mwXSQ2nPeVUzCMIE3HlLvjRioopiqyJLNph0pyx38yf9mpqFDhNGnMpAXF9/A2Xv0oiF2cVyg9xwfF0HNAz05g==} + engines: {node: '>=12.0.0'} + peerDependencies: + markdown-it: '*' + + markdown-it-sub@2.0.0: + resolution: {integrity: sha512-iCBKgwCkfQBRg2vApy9vx1C1Tu6D8XYo8NvevI3OlwzBRmiMtsJ2sXupBgEA7PPxiDwNni3qIUkhZ6j5wofDUA==} + + markdown-it-sup@2.0.0: + resolution: {integrity: sha512-5VgmdKlkBd8sgXuoDoxMpiU+BiEt3I49GItBzzw7Mxq9CxvnhE/k09HFli09zgfFDRixDQDfDxi0mgBCXtaTvA==} + + markdown-it@14.3.2: + resolution: {integrity: sha512-sHHjZ5fJKlgrG4qns2YwVcdNep35h5fERrfkD2YNsb9UFk0UIHarbiTaHKVMlPuWAoiilyK8Fv/jAm11slsY7Q==} + hasBin: true + math-intrinsics@1.1.0: resolution: {integrity: sha512-/IXtbwEk5HTPyEwyKX6hGkYXxM9nbj64B+ilVJnC/R6B0pH5G4V3b0pVbL7DBj4tkhBAppbQUlf6F6Xl9LHu1g==} engines: {node: '>= 0.4'} + md-editor-v3@7.1.0: + resolution: {integrity: sha512-+byIdwES9aGEeDDxcxx7LiVX8g31VgwJqETtfFvGjsGuwEAuMeuPZ6vV8/vltNa+SCBrigbwQxLb1R47mxaWfg==} + peerDependencies: + vue: ^3.5.3 + + mdurl@2.1.0: + resolution: {integrity: sha512-1+HBaOx0zi/dQWht8rNv9MYf9qqpqL/kxI0hXImU6Y547zM6Sni8BQibt7ifgMcYtQg41ao3Ivd6cnSM86inpg==} + + medium-zoom@1.1.0: + resolution: {integrity: sha512-ewyDsp7k4InCUp3jRmwHBRFGyjBimKps/AJLjRSox+2q/2H4p/PNpQf+pwONWlJiOudkBXtbdmVbFjqyybfTmQ==} + micromatch@4.0.8: resolution: {integrity: sha512-PXwfBhYu0hBCPw8Dn0E+WDYb7af3dSLVWKi3HGv84IdF4TyFoC0ysxFd0Goxw7nSv4T/PzEJQxsYsEiFCKo2BA==} engines: {node: '>=8.6'} @@ -1203,6 +1423,10 @@ packages: proxy-from-env@1.1.0: resolution: {integrity: sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg==} + punycode.js@2.3.1: + resolution: {integrity: sha512-uxFIHU0YlHYhDQtV4R9J6a52SLx28BCjT+4ieh7IGbgwVJWO+km431c4yRlREUAsAmt/uMjQUyQHNEPf0M39CA==} + engines: {node: '>=6'} + readable-stream@2.3.8: resolution: {integrity: sha512-8p0AUk4XODgIewSi0l8Epjs+EVnWiK7NoDIEGU0HhE7+ZyY8D1IMY7odu5lRrFXGg71L15KG8QrPmum45RTtdA==} @@ -1268,6 +1492,9 @@ packages: string_decoder@1.3.0: resolution: {integrity: sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==} + style-mod@4.1.4: + resolution: {integrity: sha512-XXWIQt633/EpAFx8aZDOTjBzrCaGmhvEQlQo6MVPfa2OzO2cWo+4hV9h+6UkHYlXGfy+ODXKUdP7Pthmcu5ATw==} + stylis@4.3.6: resolution: {integrity: sha512-yQ3rwFWRfwNUY7H5vpU0wfdkNSnvnJinhF9830Swlaxl03zsOjCfmX0ugac+3LtK0lYSgwL/KXc8oYL3mG4YFQ==} @@ -1305,6 +1532,9 @@ packages: traverse@0.3.9: resolution: {integrity: sha512-iawgk0hLP3SxGKDfnDJf8wTz4p2qImnyihM5Hh/sGvQ3K37dPi/w8sRhdNIxYA1TwFwc5mDhIJq+O0RsvXBKdQ==} + uc.micro@2.1.0: + resolution: {integrity: sha512-ARDJmphmdvUk6Glw7y9DQ2bFkKBHwQHLi2lsaH6PPmz/Ka9sFOBsBluozhDltWmnv9u/cF6Rt87znRTPV+yp/A==} + unhead@1.11.20: resolution: {integrity: sha512-3AsNQC0pjwlLqEYHLjtichGWankK8yqmocReITecmpB1H0aOabeESueyy+8X1gyJx4ftZVwo9hqQ4O3fPWffCA==} @@ -1389,6 +1619,9 @@ packages: typescript: optional: true + w3c-keyname@2.2.8: + resolution: {integrity: sha512-dpojBhNsCNN7T82Tm7k26A6G9ML3NkhDsnw9n/eoxSRlVBB4CEtIQ/KTCLI2Fwf3ataSXRhYFkQi3SlnFwPvPQ==} + warning@4.0.3: resolution: {integrity: sha512-rpJyN222KWIvHJ/F53XSZv0Zl/accqHR8et1kpaMTD/fLCRxtV8iX8czMzY7sVZupTI3zcUTg8eycS2kNF9l6w==} @@ -1411,6 +1644,11 @@ packages: xmlchars@2.2.0: resolution: {integrity: sha512-JZnDKK8B0RCDw84FNdDAIpZK+JuJw+s7Lz8nksI7SIuU3UXJJslUthsi+uWBUYOwPFwW7W7PRLRfUKpxjtjFCw==} + xss@1.0.15: + resolution: {integrity: sha512-FVdlVVC67WOIPvfOwhoMETV72f6GbW7aOabBC3WxN/oUdoEMDyLz4OgRv5/gck2ZeNqEQu+Tb0kloovXOfpYVg==} + engines: {node: '>= 0.10.0'} + hasBin: true + zhead@2.2.4: resolution: {integrity: sha512-8F0OI5dpWIA5IGG5NHUg9staDwz/ZPxZtvGVf01j7vHqSyZ0raHY+78atOVxRqb73AotX22uV1pXt3gYSstGag==} @@ -1460,6 +1698,257 @@ snapshots: '@babel/helper-string-parser': 7.25.9 '@babel/helper-validator-identifier': 7.25.9 + '@codemirror/autocomplete@6.20.3': + dependencies: + '@codemirror/language': 6.12.4 + '@codemirror/state': 6.7.6 + '@codemirror/view': 6.43.13 + '@lezer/common': 1.5.3 + + '@codemirror/commands@6.11.1': + dependencies: + '@codemirror/language': 6.12.4 + '@codemirror/state': 6.7.6 + '@codemirror/view': 6.43.13 + '@lezer/common': 1.5.3 + + '@codemirror/lang-angular@0.1.4': + dependencies: + '@codemirror/lang-html': 6.4.12 + '@codemirror/lang-javascript': 6.2.5 + '@codemirror/language': 6.12.4 + '@lezer/common': 1.5.3 + '@lezer/highlight': 1.2.5 + '@lezer/lr': 1.4.10 + + '@codemirror/lang-cpp@6.0.3': + dependencies: + '@codemirror/language': 6.12.4 + '@lezer/cpp': 1.1.6 + + '@codemirror/lang-css@6.3.1': + dependencies: + '@codemirror/autocomplete': 6.20.3 + '@codemirror/language': 6.12.4 + '@codemirror/state': 6.7.6 + '@lezer/common': 1.5.3 + '@lezer/css': 1.3.8 + + '@codemirror/lang-go@6.0.1': + dependencies: + '@codemirror/autocomplete': 6.20.3 + '@codemirror/language': 6.12.4 + '@codemirror/state': 6.7.6 + '@lezer/common': 1.5.3 + '@lezer/go': 1.0.1 + + '@codemirror/lang-html@6.4.12': + dependencies: + '@codemirror/autocomplete': 6.20.3 + '@codemirror/lang-css': 6.3.1 + '@codemirror/lang-javascript': 6.2.5 + '@codemirror/language': 6.12.4 + '@codemirror/state': 6.7.6 + '@codemirror/view': 6.43.13 + '@lezer/common': 1.5.3 + '@lezer/css': 1.3.8 + '@lezer/html': 1.3.13 + + '@codemirror/lang-java@6.0.2': + dependencies: + '@codemirror/language': 6.12.4 + '@lezer/java': 1.1.4 + + '@codemirror/lang-javascript@6.2.5': + dependencies: + '@codemirror/autocomplete': 6.20.3 + '@codemirror/language': 6.12.4 + '@codemirror/lint': 6.9.7 + '@codemirror/state': 6.7.6 + '@codemirror/view': 6.43.13 + '@lezer/common': 1.5.3 + '@lezer/javascript': 1.5.5 + + '@codemirror/lang-jinja@6.0.1': + dependencies: + '@codemirror/autocomplete': 6.20.3 + '@codemirror/lang-html': 6.4.12 + '@codemirror/language': 6.12.4 + '@codemirror/state': 6.7.6 + '@codemirror/view': 6.43.13 + '@lezer/common': 1.5.3 + '@lezer/highlight': 1.2.5 + '@lezer/lr': 1.4.10 + + '@codemirror/lang-json@6.0.2': + dependencies: + '@codemirror/language': 6.12.4 + '@lezer/json': 1.0.3 + + '@codemirror/lang-less@6.0.2': + dependencies: + '@codemirror/lang-css': 6.3.1 + '@codemirror/language': 6.12.4 + '@lezer/common': 1.5.3 + '@lezer/highlight': 1.2.5 + '@lezer/lr': 1.4.10 + + '@codemirror/lang-liquid@6.3.2': + dependencies: + '@codemirror/autocomplete': 6.20.3 + '@codemirror/lang-html': 6.4.12 + '@codemirror/language': 6.12.4 + '@codemirror/state': 6.7.6 + '@codemirror/view': 6.43.13 + '@lezer/common': 1.5.3 + '@lezer/highlight': 1.2.5 + '@lezer/lr': 1.4.10 + + '@codemirror/lang-markdown@6.5.2': + dependencies: + '@codemirror/autocomplete': 6.20.3 + '@codemirror/lang-html': 6.4.12 + '@codemirror/language': 6.12.4 + '@codemirror/state': 6.7.6 + '@codemirror/view': 6.43.13 + '@lezer/common': 1.5.3 + '@lezer/markdown': 1.7.2 + + '@codemirror/lang-php@6.0.2': + dependencies: + '@codemirror/lang-html': 6.4.12 + '@codemirror/language': 6.12.4 + '@codemirror/state': 6.7.6 + '@lezer/common': 1.5.3 + '@lezer/php': 1.0.6 + + '@codemirror/lang-python@6.2.1': + dependencies: + '@codemirror/autocomplete': 6.20.3 + '@codemirror/language': 6.12.4 + '@codemirror/state': 6.7.6 + '@lezer/common': 1.5.3 + '@lezer/python': 1.1.19 + + '@codemirror/lang-rust@6.0.2': + dependencies: + '@codemirror/language': 6.12.4 + '@lezer/rust': 1.0.3 + + '@codemirror/lang-sass@6.0.2': + dependencies: + '@codemirror/lang-css': 6.3.1 + '@codemirror/language': 6.12.4 + '@codemirror/state': 6.7.6 + '@lezer/common': 1.5.3 + '@lezer/sass': 1.1.0 + + '@codemirror/lang-sql@6.10.0': + dependencies: + '@codemirror/autocomplete': 6.20.3 + '@codemirror/language': 6.12.4 + '@codemirror/state': 6.7.6 + '@lezer/common': 1.5.3 + '@lezer/highlight': 1.2.5 + '@lezer/lr': 1.4.10 + + '@codemirror/lang-vue@0.1.3': + dependencies: + '@codemirror/lang-html': 6.4.12 + '@codemirror/lang-javascript': 6.2.5 + '@codemirror/language': 6.12.4 + '@lezer/common': 1.5.3 + '@lezer/highlight': 1.2.5 + '@lezer/lr': 1.4.10 + + '@codemirror/lang-wast@6.0.2': + dependencies: + '@codemirror/language': 6.12.4 + '@lezer/common': 1.5.3 + '@lezer/highlight': 1.2.5 + '@lezer/lr': 1.4.10 + + '@codemirror/lang-xml@6.1.0': + dependencies: + '@codemirror/autocomplete': 6.20.3 + '@codemirror/language': 6.12.4 + '@codemirror/state': 6.7.6 + '@codemirror/view': 6.43.13 + '@lezer/common': 1.5.3 + '@lezer/xml': 1.0.6 + + '@codemirror/lang-yaml@6.1.3': + dependencies: + '@codemirror/autocomplete': 6.20.3 + '@codemirror/language': 6.12.4 + '@codemirror/state': 6.7.6 + '@lezer/common': 1.5.3 + '@lezer/highlight': 1.2.5 + '@lezer/lr': 1.4.10 + '@lezer/yaml': 1.0.4 + + '@codemirror/language-data@6.5.2': + dependencies: + '@codemirror/lang-angular': 0.1.4 + '@codemirror/lang-cpp': 6.0.3 + '@codemirror/lang-css': 6.3.1 + '@codemirror/lang-go': 6.0.1 + '@codemirror/lang-html': 6.4.12 + '@codemirror/lang-java': 6.0.2 + '@codemirror/lang-javascript': 6.2.5 + '@codemirror/lang-jinja': 6.0.1 + '@codemirror/lang-json': 6.0.2 + '@codemirror/lang-less': 6.0.2 + '@codemirror/lang-liquid': 6.3.2 + '@codemirror/lang-markdown': 6.5.2 + '@codemirror/lang-php': 6.0.2 + '@codemirror/lang-python': 6.2.1 + '@codemirror/lang-rust': 6.0.2 + '@codemirror/lang-sass': 6.0.2 + '@codemirror/lang-sql': 6.10.0 + '@codemirror/lang-vue': 0.1.3 + '@codemirror/lang-wast': 6.0.2 + '@codemirror/lang-xml': 6.1.0 + '@codemirror/lang-yaml': 6.1.3 + '@codemirror/language': 6.12.4 + '@codemirror/legacy-modes': 6.5.4 + + '@codemirror/language@6.12.4': + dependencies: + '@codemirror/state': 6.7.6 + '@codemirror/view': 6.43.13 + '@lezer/common': 1.5.3 + '@lezer/highlight': 1.2.5 + '@lezer/lr': 1.4.10 + style-mod: 4.1.4 + + '@codemirror/legacy-modes@6.5.4': + dependencies: + '@codemirror/language': 6.12.4 + + '@codemirror/lint@6.9.7': + dependencies: + '@codemirror/state': 6.7.6 + '@codemirror/view': 6.43.13 + crelt: 1.0.7 + + '@codemirror/search@6.7.2': + dependencies: + '@codemirror/state': 6.7.6 + '@codemirror/view': 6.43.13 + crelt: 1.0.7 + + '@codemirror/state@6.7.6': + dependencies: + '@marijn/find-cluster-break': 1.0.4 + + '@codemirror/view@6.43.13': + dependencies: + '@codemirror/state': 6.7.6 + crelt: 1.0.7 + style-mod: 4.1.4 + w3c-keyname: 2.2.8 + '@ctrl/tinycolor@3.6.1': {} '@emotion/hash@0.9.2': {} @@ -1564,6 +2053,105 @@ snapshots: '@jridgewell/sourcemap-codec@1.5.0': {} + '@lezer/common@1.5.3': {} + + '@lezer/cpp@1.1.6': + dependencies: + '@lezer/common': 1.5.3 + '@lezer/highlight': 1.2.5 + '@lezer/lr': 1.4.10 + + '@lezer/css@1.3.8': + dependencies: + '@lezer/common': 1.5.3 + '@lezer/highlight': 1.2.5 + '@lezer/lr': 1.4.10 + + '@lezer/go@1.0.1': + dependencies: + '@lezer/common': 1.5.3 + '@lezer/highlight': 1.2.5 + '@lezer/lr': 1.4.10 + + '@lezer/highlight@1.2.5': + dependencies: + '@lezer/common': 1.5.3 + + '@lezer/html@1.3.13': + dependencies: + '@lezer/common': 1.5.3 + '@lezer/highlight': 1.2.5 + '@lezer/lr': 1.4.10 + + '@lezer/java@1.1.4': + dependencies: + '@lezer/common': 1.5.3 + '@lezer/highlight': 1.2.5 + '@lezer/lr': 1.4.10 + + '@lezer/javascript@1.5.5': + dependencies: + '@lezer/common': 1.5.3 + '@lezer/highlight': 1.2.5 + '@lezer/lr': 1.4.10 + + '@lezer/json@1.0.3': + dependencies: + '@lezer/common': 1.5.3 + '@lezer/highlight': 1.2.5 + '@lezer/lr': 1.4.10 + + '@lezer/lr@1.4.10': + dependencies: + '@lezer/common': 1.5.3 + + '@lezer/markdown@1.7.2': + dependencies: + '@lezer/common': 1.5.3 + '@lezer/highlight': 1.2.5 + + '@lezer/php@1.0.6': + dependencies: + '@lezer/common': 1.5.3 + '@lezer/highlight': 1.2.5 + '@lezer/lr': 1.4.10 + + '@lezer/python@1.1.19': + dependencies: + '@lezer/common': 1.5.3 + '@lezer/highlight': 1.2.5 + '@lezer/lr': 1.4.10 + + '@lezer/rust@1.0.3': + dependencies: + '@lezer/common': 1.5.3 + '@lezer/highlight': 1.2.5 + '@lezer/lr': 1.4.10 + + '@lezer/sass@1.1.0': + dependencies: + '@lezer/common': 1.5.3 + '@lezer/highlight': 1.2.5 + '@lezer/lr': 1.4.10 + + '@lezer/xml@1.0.6': + dependencies: + '@lezer/common': 1.5.3 + '@lezer/highlight': 1.2.5 + '@lezer/lr': 1.4.10 + + '@lezer/yaml@1.0.4': + dependencies: + '@lezer/common': 1.5.3 + '@lezer/highlight': 1.2.5 + '@lezer/lr': 1.4.10 + + '@lucide/vue@1.48.0(vue@3.5.13)': + dependencies: + vue: 3.5.13 + + '@marijn/find-cluster-break@1.0.4': {} + '@parcel/watcher-android-arm64@2.5.1': optional: true @@ -1757,6 +2345,15 @@ snapshots: '@types/estree@1.0.7': {} + '@types/linkify-it@5.0.0': {} + + '@types/markdown-it@14.2.0': + dependencies: + '@types/linkify-it': 5.0.0 + '@types/mdurl': 2.0.0 + + '@types/mdurl@2.0.0': {} + '@types/node@14.18.63': {} '@unhead/dom@1.11.20': @@ -1787,6 +2384,12 @@ snapshots: unhead: 1.11.20 vue: 3.5.13 + '@vavt/copy2clipboard@1.0.3': {} + + '@vavt/markdown-theme@6.0.1': {} + + '@vavt/util@2.1.2': {} + '@vitejs/plugin-vue@5.2.3(vite@6.3.3(jiti@2.4.2)(lightningcss@1.29.2)(sass@1.88.0))(vue@3.5.13)': dependencies: vite: 6.3.3(jiti@2.4.2)(lightningcss@1.29.2)(sass@1.88.0) @@ -1920,6 +2523,8 @@ snapshots: tar-stream: 2.2.0 zip-stream: 4.1.1 + argparse@2.0.1: {} + array-tree-filter@2.1.0: {} async-validator@4.2.5: {} @@ -1998,12 +2603,24 @@ snapshots: dependencies: readdirp: 4.1.2 + codemirror@6.0.2: + dependencies: + '@codemirror/autocomplete': 6.20.3 + '@codemirror/commands': 6.11.1 + '@codemirror/language': 6.12.4 + '@codemirror/lint': 6.9.7 + '@codemirror/search': 6.7.2 + '@codemirror/state': 6.7.6 + '@codemirror/view': 6.43.13 + codepage@1.15.0: {} combined-stream@1.0.8: dependencies: delayed-stream: 1.0.0 + commander@2.20.3: {} + compress-commons@4.1.2: dependencies: buffer-crc32: 0.2.13 @@ -2026,6 +2643,10 @@ snapshots: crc-32: 1.2.2 readable-stream: 3.6.2 + crelt@1.0.7: {} + + cssfilter@0.0.10: {} + csstype@3.1.3: {} dayjs@1.11.13: {} @@ -2235,6 +2856,8 @@ snapshots: js-tokens@4.0.0: {} + json5@2.2.3: {} + jszip@3.10.2: dependencies: lie: 3.3.0 @@ -2295,6 +2918,10 @@ snapshots: lightningcss-win32-arm64-msvc: 1.29.2 lightningcss-win32-x64-msvc: 1.29.2 + linkify-it@5.0.2: + dependencies: + uc.micro: 2.1.0 + listenercount@1.0.1: {} lodash-es@4.17.21: {} @@ -2339,8 +2966,55 @@ snapshots: dependencies: '@jridgewell/sourcemap-codec': 1.5.0 + markdown-it-image-figures@2.1.1(markdown-it@14.3.2): + dependencies: + markdown-it: 14.3.2 + + markdown-it-sub@2.0.0: {} + + markdown-it-sup@2.0.0: {} + + markdown-it@14.3.2: + dependencies: + argparse: 2.0.1 + entities: 4.5.0 + linkify-it: 5.0.2 + mdurl: 2.1.0 + punycode.js: 2.3.1 + uc.micro: 2.1.0 + math-intrinsics@1.1.0: {} + md-editor-v3@7.1.0(vue@3.5.13): + dependencies: + '@codemirror/autocomplete': 6.20.3 + '@codemirror/commands': 6.11.1 + '@codemirror/lang-markdown': 6.5.2 + '@codemirror/language': 6.12.4 + '@codemirror/language-data': 6.5.2 + '@codemirror/search': 6.7.2 + '@codemirror/state': 6.7.6 + '@codemirror/view': 6.43.13 + '@lezer/highlight': 1.2.5 + '@lucide/vue': 1.48.0(vue@3.5.13) + '@types/markdown-it': 14.2.0 + '@vavt/copy2clipboard': 1.0.3 + '@vavt/markdown-theme': 6.0.1 + '@vavt/util': 2.1.2 + codemirror: 6.0.2 + json5: 2.2.3 + markdown-it: 14.3.2 + markdown-it-image-figures: 2.1.1(markdown-it@14.3.2) + markdown-it-sub: 2.0.0 + markdown-it-sup: 2.0.0 + medium-zoom: 1.1.0 + vue: 3.5.13 + xss: 1.0.15 + + mdurl@2.1.0: {} + + medium-zoom@1.1.0: {} + micromatch@4.0.8: dependencies: braces: 3.0.3 @@ -2413,6 +3087,8 @@ snapshots: proxy-from-env@1.1.0: {} + punycode.js@2.3.1: {} + readable-stream@2.3.8: dependencies: core-util-is: 1.0.3 @@ -2505,6 +3181,8 @@ snapshots: dependencies: safe-buffer: 5.2.1 + style-mod@4.1.4: {} + stylis@4.3.6: {} swiper@11.2.6: {} @@ -2537,6 +3215,8 @@ snapshots: traverse@0.3.9: {} + uc.micro@2.1.0: {} + unhead@1.11.20: dependencies: '@unhead/dom': 1.11.20 @@ -2597,6 +3277,8 @@ snapshots: '@vue/server-renderer': 3.5.13(vue@3.5.13) '@vue/shared': 3.5.13 + w3c-keyname@2.2.8: {} + warning@4.0.3: dependencies: loose-envify: 1.4.0 @@ -2619,6 +3301,11 @@ snapshots: xmlchars@2.2.0: {} + xss@1.0.15: + dependencies: + commander: 2.20.3 + cssfilter: 0.0.10 + zhead@2.2.4: {} zip-stream@4.1.1: diff --git a/src/api/request.js b/src/api/request.js index d235cfb..9662812 100644 --- a/src/api/request.js +++ b/src/api/request.js @@ -25,6 +25,9 @@ service.interceptors.request.use( ); // 响应拦截器 +// 401 跳转防抖:并发请求同时 401 时只提示/跳转一次 +let redirectingToLogin = false + service.interceptors.response.use( response => { const {code, result, message} = response.data; @@ -32,13 +35,17 @@ service.interceptors.response.use( return result; } else { if (code === 401) { - msg.error(message).then(r => { + // 登录态失效(已退出/token 过期):立即清态并回登录页。 + // 不能等 message.close 的 promise —— 那会让页面卡在原处约 3 秒才跳(用户感知为「不跳转」)。 + if (!redirectingToLogin) { + redirectingToLogin = true localStorage.removeItem('token'); localStorage.removeItem('user'); - window.location.href = '/' - msg.destroy() - }) - return; + msg.error(message || '登录已过期,请重新登录'); + const redirect = encodeURIComponent(window.location.pathname + window.location.search) + window.location.href = `/login?redirect=${redirect}` + } + return Promise.reject({code, message, result}); } // 4009 = 布局版本冲突(CAS 失败)。契约约定:该错误不携带最新布局(result 恒为 null), // 需由调用方(设计器)自行重拉详情并提示,故仅此一个 code 走 reject, @@ -69,10 +76,13 @@ const post = (url, data = {}) => { return service.post(url, data); }; -// 封装上传文件请求 -const upload = (url, file) => { +// 封装上传文件请求(fields 用于附加表单字段,如上传场景 scene) +const upload = (url, file, fields = {}) => { const formData = new FormData(); formData.append('file', file); + Object.keys(fields).forEach((k) => { + if (fields[k] !== undefined && fields[k] !== null) formData.append(k, fields[k]); + }); return service.post(url, formData, { headers: { 'Content-Type': 'multipart/form-data' diff --git a/src/api/request/attachment.js b/src/api/request/attachment.js new file mode 100644 index 0000000..8f221b3 --- /dev/null +++ b/src/api/request/attachment.js @@ -0,0 +1,26 @@ +import { get, post, upload } from '../request.js' + +/** + * 附件管理接口(迭代-2026-09-29)。 + * + * 所有上传(含用户端头像)都登记在附件表;删除为「记录软删 + 文件本体按引用检查」: + * 响应 removed_file=false 表示文件仍被头像/封面等引用,仅移除了登记记录。 + */ + +/** + * 管理端上传。scene:cover=服务封面(仅图片 ≤5MB)| attachment=通用附件(≤20MB)。 + * 返回 { id, url, path, file_name, ext, size_bytes };库内只存 path(相对路径)。 + */ +export function adminUploadApi(file, scene) { + return upload('admin/upload', file, { scene }) +} + +/** 附件列表。params: { keyword, scene, page, pageSize } */ +export function attachmentListApi(params) { + return get('admin/attachment/list', params) +} + +/** 删除附件。返回 { removed_file } */ +export function attachmentDeleteApi(data) { + return post('admin/attachment/delete', data) +} diff --git a/src/api/request/project.js b/src/api/request/project.js new file mode 100644 index 0000000..547eb25 --- /dev/null +++ b/src/api/request/project.js @@ -0,0 +1,160 @@ +import { get, post } from '../request.js' + +/** + * 开发项目管理接口(迭代-2026-09-30 三期)。 + * + * 流程:建单(生成绑定令牌)→ 生成绑定小程序码(/qrcode/...)→ 用户扫码绑定; + * 阶段/小节点/交付物均为即时保存接口。阶段状态变更 / 交付物上传 / 交付 会推站内信给用户。 + */ + +export const PROJECT_STATUS_OPTIONS = [ + { value: 1, label: '进行中', color: 'processing' }, + { value: 2, label: '已交付', color: 'success' }, + { value: 3, label: '已关闭', color: 'default' }, +] + +export const STAGE_STATUS_OPTIONS = [ + { value: 0, label: '未开始' }, + { value: 1, label: '进行中' }, + { value: 2, label: '已完成' }, +] + +export function projectStatusLabel(status) { + return PROJECT_STATUS_OPTIONS.find((s) => s.value === status)?.label || '未知' +} + +export function stageStatusLabel(status) { + return STAGE_STATUS_OPTIONS.find((s) => s.value === status)?.label || '未开始' +} + +/** 项目列表 */ +export function projectListApi(params) { + return get('admin/service/project/list', params) +} + +/** 项目详情(管理态全量:阶段/节点/文件) */ +export function projectDetailApi(id) { + return get('admin/service/project/detail', { id }) +} + +/** + * 保存项目(新增 id=0 会生成绑定令牌并返回;userId>0 直接绑定该用户)。 + * @param {object} data { id, title, description, priceCents, priceNote, dueNote, status, userId } + */ +export function projectSaveApi(data) { + return post('admin/service/project/save', data) +} + +/** 删除项目(软删;阶段/节点/文件一并清除) */ +export function projectDeleteApi(data) { + return post('admin/service/project/delete', data) +} + +/** 生成/刷新绑定小程序码(微信 getUnlimited) */ +export function projectQrcodeApi(data) { + return post('admin/service/project/qrcode', data) +} + +/** 保存阶段 */ +export function projectStageSaveApi(data) { + return post('admin/service/project/stage/save', data) +} + +/** 删除阶段(节点/文件一并删除) */ +export function projectStageDeleteApi(data) { + return post('admin/service/project/stage/delete', data) +} + +/** 保存小节点(isDone 即时生效) */ +export function projectNodeSaveApi(data) { + return post('admin/service/project/node/save', data) +} + +/** 删除小节点 */ +export function projectNodeDeleteApi(data) { + return post('admin/service/project/node/delete', data) +} + +/** 登记交付物(先走 adminUploadApi 上传拿 path) */ +export function projectFileAddApi(data) { + return post('admin/service/project/file/add', data) +} + +/** 删除交付物登记 */ +export function projectFileDeleteApi(data) { + return post('admin/service/project/file/delete', data) +} + +// ---------- 四期:维护模板 / 付款分期模板 / 分期到账 / 维护期 / 提醒设置 ---------- + +/** 维护模板列表(含停用) */ +export function maintainPlanListApi() { + return get('admin/service/maintain-plan/list') +} + +/** 保存维护模板 { id, name, freeYears, yearlyFeeCents, sourceOnly, sort, isEnabled, remark } */ +export function maintainPlanSaveApi(data) { + return post('admin/service/maintain-plan/save', data) +} + +/** 删除维护模板 */ +export function maintainPlanDeleteApi(data) { + return post('admin/service/maintain-plan/delete', data) +} + +/** 付款分期模板列表(含停用) */ +export function payPlanListApi() { + return get('admin/service/pay-plan/list') +} + +/** 保存付款分期模板 { id, name, schedule(JSON 串), sort, isEnabled, remark } */ +export function payPlanSaveApi(data) { + return post('admin/service/pay-plan/save', data) +} + +/** 删除付款分期模板 */ +export function payPlanDeleteApi(data) { + return post('admin/service/pay-plan/delete', data) +} + +/** 标记分期到账 { id, paidNote }(用户端推站内信) */ +export function projectPayMarkApi(data) { + return post('admin/service/project/pay/mark', data) +} + +/** 撤销分期到账 */ +export function projectPayUnmarkApi(data) { + return post('admin/service/project/pay/unmark', data) +} + +/** 维护费续收一年 */ +export function projectMaintainRenewApi(data) { + return post('admin/service/project/maintain/renew', data) +} + +/** 调整维护期起算日 { id, startAt: 'YYYY-MM-DD' } */ +export function projectMaintainAdjustApi(data) { + return post('admin/service/project/maintain/adjust', data) +} + +/** 维护费提醒设置读取 */ +export function maintainRemindGetApi() { + return get('admin/service/maintain-remind/get') +} + +/** 维护费提醒设置保存 { remindDays, adminNotifyUserId } */ +export function maintainRemindSaveApi(data) { + return post('admin/service/maintain-remind/save', data) +} + +/** 分期触发节点文案(与后端 consts.go 对齐) */ +export const PAY_TRIGGER_OPTIONS = [ + { value: 'start', label: '开工前(定金)' }, + { value: 'mid_demo', label: '中期演示确认后' }, + { value: 'online_before', label: '上线前' }, + { value: 'online_after', label: '上线后' }, +] + +export function payTriggerLabel(trigger) { + return PAY_TRIGGER_OPTIONS.find((t) => t.value === trigger)?.label || trigger +} diff --git a/src/api/request/service.js b/src/api/request/service.js new file mode 100644 index 0000000..012781f --- /dev/null +++ b/src/api/request/service.js @@ -0,0 +1,87 @@ +import { get, post } from '../request.js' + +/** + * 软件开发服务二期接口(迭代-2026-09-30):介绍页模块 / 作品案例 / 报价申请。 + * + * 契约约定:请求体 camelCase / 响应 snake_case(与 software.js 一致)。 + * 图片库内只存相对路径:保存时提交上传接口返回的 path;响应里的 *_url 已是 + * 后端按 site.base_url 拼好的绝对地址,直接展示。 + */ + +/** 介绍页模块类型(与后端 consts.go 对齐;每种类型对应一种预设排版布局) */ +export const SERVICE_BLOCK_KINDS = [ + { value: 'hero', label: '头图横幅', hint: '大标题 + 标语,页面开场;标题支持 **高亮** 与换行' }, + { value: 'flow', label: '服务流程', hint: '时间轴排版;正文每行「标题|描述」,如 需求沟通|澄清目标与边界' }, + { value: 'checklist', label: '交付清单', hint: '勾选卡片;正文每行一项,如 需求文档' }, + { value: 'price', label: '价格卡', hint: '三列价格卡;正文每行「名称|描述|价格」,如 官网展示型|官网搭建|3万起' }, + { value: 'rich', label: '富文本', hint: 'Markdown 图文混排,适合大段介绍' }, + { value: 'image_text', label: '图文', hint: '一张图 + 说明文字,上图下文' }, + { value: 'image_list', label: '图片列表', hint: '多图网格展示,点击可预览' }, + { value: 'developer', label: '开发者简介', hint: '橙环头像 + 一句话亮点 + 技术栈行(介绍文字选填)' }, + { value: 'works', label: '作品模块入口', hint: '展示作品精选封面,点击进作品列表' }, + { value: 'goods', label: '服务入口', hint: '不单独成卡;作为「查看全部服务」并入「服务与价格」区块底部(需配合价格卡区块)' }, +] + +export function serviceBlockKindLabel(kind) { + return SERVICE_BLOCK_KINDS.find((k) => k.value === kind)?.label || kind +} + +// ---------- 介绍页模块 ---------- + +/** 模块列表(含停用,按 sort 升序) */ +export function serviceBlockListApi() { + return get('admin/service/block/list') +} + +/** + * 保存模块(新增 id=0 / 编辑 id>0)。 + * @param {object} data { id, kind, title, subtitle, imagePath, images[], content, sort, isEnabled } + */ +export function serviceBlockSaveApi(data) { + return post('admin/service/block/save', data) +} + +/** 删除模块 */ +export function serviceBlockDeleteApi(data) { + return post('admin/service/block/delete', data) +} + +// ---------- 作品案例 ---------- + +/** 作品列表(管理端,含下架) */ +export function serviceWorkListApi(params) { + return get('admin/service/work/list', params) +} + +/** 作品详情(编辑回填,含 content_md 与图集) */ +export function serviceWorkDetailApi(id) { + return get('admin/service/work/detail', { id }) +} + +/** + * 保存作品(新增 id=0 / 编辑 id>0)。 + * @param {object} data { id, category, title, summary, contentMd, coverPath, images[], priceCents, priceNote, sort, isEnabled } + */ +export function serviceWorkSaveApi(data) { + return post('admin/service/work/save', data) +} + +/** 删除作品(软删除) */ +export function serviceWorkDeleteApi(data) { + return post('admin/service/work/delete', data) +} + +// ---------- 报价申请 ---------- + +/** 报价申请列表(status 传 undefined = 全部) */ +export function serviceQuoteListApi(params) { + return get('admin/service/quote/list', params) +} + +/** + * 处理报价申请:填报价金额(分)+ 说明 + 状态。保存后向用户推站内信。 + * @param {object} data { id, status, quoteCents, quoteNote } + */ +export function serviceQuoteHandleApi(data) { + return post('admin/service/quote/handle', data) +} diff --git a/src/api/request/setting.js b/src/api/request/setting.js new file mode 100644 index 0000000..92b6718 --- /dev/null +++ b/src/api/request/setting.js @@ -0,0 +1,18 @@ +import { get, post } from '../request.js' + +/** + * 系统配置接口(迭代-2026-09-29)。 + * + * 白名单键读写(当前仅 site.base_url —— 图片等静态资源的对外拼接前缀, + * 留空时后端按请求 Host 动态拼接)。键值存 settings 表,保存立即生效。 + */ + +/** 读取配置项列表:[{ key, value, remark }] */ +export function settingGetApi() { + return get('admin/setting/get') +} + +/** 保存一项配置 { key, value } */ +export function settingSaveApi(data) { + return post('admin/setting/save', data) +} diff --git a/src/api/request/software.js b/src/api/request/software.js new file mode 100644 index 0000000..4dfd53c --- /dev/null +++ b/src/api/request/software.js @@ -0,0 +1,49 @@ +import { get, post } from '../request.js' + +/** + * 软件开发服务接口(迭代-2026-09-29)。 + * + * 契约约定:请求体 camelCase / 响应 snake_case(与 promo.js 一致)。 + * 响应 cover_url 已是后端按 site.base_url 拼好的绝对地址,前端直接展示; + * 保存时提交 coverPath(上传接口返回的相对路径),库内不落域名。 + */ + +/** 服务分类(与后端 consts.go 对齐) */ +export const GOODS_CATEGORY_OPTIONS = [ + { value: 1, label: '网站开发系列' }, + { value: 2, label: '小程序开发系列' }, + { value: 3, label: 'App 开发系列' }, + { value: 4, label: '桌面程序开发系列' }, +] + +export function goodsCategoryLabel(category) { + return GOODS_CATEGORY_OPTIONS.find((c) => c.value === category)?.label || '其他' +} + +/** 分(int)→ 元展示串('面议' 由调用方处理 0 值) */ +export function yuanFromCents(cents) { + return (Number(cents || 0) / 100).toFixed(2).replace(/\.00$/, '') +} + +/** 服务列表(管理端,含下架) */ +export function goodsListApi(params) { + return get('admin/goods/list', params) +} + +/** 服务详情(编辑回填,含 content_md) */ +export function goodsDetailApi(id) { + return get('admin/goods/detail', { id }) +} + +/** + * 保存服务(新增 id=0 / 编辑 id>0)。 + * @param {object} data { id, category, title, summary, contentMd, priceCents, priceNote, coverPath, sort, isEnabled } + */ +export function goodsSaveApi(data) { + return post('admin/goods/save', data) +} + +/** 删除服务(软删除) */ +export function goodsDeleteApi(data) { + return post('admin/goods/delete', data) +} diff --git a/src/components/BrandLogo.vue b/src/components/BrandLogo.vue new file mode 100644 index 0000000..af9a301 --- /dev/null +++ b/src/components/BrandLogo.vue @@ -0,0 +1,156 @@ + + + + + diff --git a/src/layouts/AdminLayout.vue b/src/layouts/AdminLayout.vue index 763aeb9..774d9c9 100644 --- a/src/layouts/AdminLayout.vue +++ b/src/layouts/AdminLayout.vue @@ -1,13 +1,14 @@ + + + + diff --git a/src/views/service/ProjectsManage.vue b/src/views/service/ProjectsManage.vue new file mode 100644 index 0000000..ccb7261 --- /dev/null +++ b/src/views/service/ProjectsManage.vue @@ -0,0 +1,1101 @@ + + + + + diff --git a/src/views/service/QuotesManage.vue b/src/views/service/QuotesManage.vue new file mode 100644 index 0000000..1d614ce --- /dev/null +++ b/src/views/service/QuotesManage.vue @@ -0,0 +1,231 @@ + + + + + diff --git a/src/views/service/ServicePageEdit.vue b/src/views/service/ServicePageEdit.vue new file mode 100644 index 0000000..d726a9f --- /dev/null +++ b/src/views/service/ServicePageEdit.vue @@ -0,0 +1,485 @@ + + + + + diff --git a/src/views/service/WorksManage.vue b/src/views/service/WorksManage.vue new file mode 100644 index 0000000..d74df3c --- /dev/null +++ b/src/views/service/WorksManage.vue @@ -0,0 +1,496 @@ + + + + + diff --git a/src/views/software/SoftwareManage.vue b/src/views/software/SoftwareManage.vue new file mode 100644 index 0000000..340737d --- /dev/null +++ b/src/views/software/SoftwareManage.vue @@ -0,0 +1,443 @@ + + + + + diff --git a/src/views/system/SystemConfig.vue b/src/views/system/SystemConfig.vue new file mode 100644 index 0000000..e3c71c2 --- /dev/null +++ b/src/views/system/SystemConfig.vue @@ -0,0 +1,261 @@ + + + + + diff --git a/vite.config.js b/vite.config.js index 2b9ac4c..8e561b8 100644 --- a/vite.config.js +++ b/vite.config.js @@ -30,6 +30,12 @@ export default defineConfig({ '/qrcode': { target: 'http://127.0.0.1:8000', changeOrigin: true + }, + // 上传的静态资源(头像/封面/附件):库内只存相对路径(/static/...), + // 附件管理与系统配置页的预览按相对路径直出,需同源代理(不做 rewrite) + '/static': { + target: 'http://127.0.0.1:8000', + changeOrigin: true } } }