Compare commits

116 Commits
Author SHA1 Message Date
hajimi 73905453a5 . 2026-08-01 18:40:53 +08:00
hajimi 7f32c092c3 fix: align crawler network with test database 2026-08-01 18:17:51 +08:00
hajimi 5297f6220f fix: run kb worker on host network 2026-08-01 18:14:07 +08:00
hajimi d1e3d780ba fix: add mysql auth dependency to crawler 2026-08-01 18:09:11 +08:00
hajimi 597417bf08 feat: include crawler in development compose 2026-08-01 17:37:56 +08:00
hajimi ebbcb7f007 fix: run test docker gateway on host network 2026-08-01 17:34:04 +08:00
hajimi 9e44df3a73 fix: connect docker php to host-only test database 2026-08-01 17:24:13 +08:00
hajimi b490b08c7b fix: use accessible crawler build mirrors 2026-08-01 17:23:20 +08:00
hajimi b4c212f68f chore: use test host database and redis in dev compose 2026-08-01 17:09:24 +08:00
hajimi 40619e2335 chore: optimize local crawler image build 2026-08-01 17:01:29 +08:00
hajimi 9a83c8dfb7 fix: speed up local Docker PHP APIs 2026-08-01 16:18:19 +08:00
hajimi 42284ba6ac fix: default match tab to match center 2026-08-01 16:14:37 +08:00
hajimi 5633c9b51f feat: add local crontab scheduler service 2026-08-01 16:08:01 +08:00
hajimi 759ba34227 chore: connect local server to docker services 2026-08-01 15:27:24 +08:00
hajimi e75b949bab feat: add persistent mysql and redis services 2026-08-01 15:18:44 +08:00
hajimi 8f7e831270 feat: add local docker development stack 2026-08-01 14:56:01 +08:00
hajimi deb6ce0e97 feat(uniapp): restore home page design 2026-07-31 18:12:46 +08:00
hajimi fdf8022662 fix: 将 admin 改为普通目录 2026-07-31 16:39:16 +08:00
hajimi e7f9328611 no message 2026-07-31 16:25:07 +08:00
hajimi 2b2e3197be no message 2026-07-31 16:13:31 +08:00
hajimi c01bd53ea1 deploy: auto commit repo-root changes 2026-07-14 11:24:59 2026-07-14 11:24:59 +08:00
hajimi 98d2a23589 deploy: auto commit repo-root changes 2026-07-14 09:42:08 2026-07-14 09:42:08 +08:00
hajimi 33687e31b7 deploy: auto commit repo-root changes 2026-07-13 22:38:58 2026-07-13 22:38:58 +08:00
hajimi af8941e880 deploy: auto commit repo-root changes 2026-07-13 13:26:55 2026-07-13 13:26:56 +08:00
hajimi 8ebe30a077 deploy: auto commit repo-root changes 2026-07-12 23:46:58 2026-07-12 23:46:58 +08:00
hajimi 89d41de3dd deploy: auto commit repo-root changes 2026-07-11 13:14:53 2026-07-11 13:14:54 +08:00
hajimi 42d243971e deploy: auto commit repo-root changes 2026-07-11 12:03:08 2026-07-11 12:03:08 +08:00
hajimi 3a5d571e53 添加赔率 2026-07-11 11:19:43 +08:00
hajimi c9ac46faa7 deploy: auto commit repo-root changes 2026-07-10 10:47:39 2026-07-10 10:47:39 +08:00
hajimi 3b61f0ba38 deploy: auto commit repo-root changes 2026-07-10 01:01:12 2026-07-10 01:01:12 +08:00
hajimi 84a5fb43f5 deploy: auto commit server changes 2026-07-10 00:46:43 2026-07-10 00:46:43 +08:00
hajimi ad597d0a79 deploy: auto commit server changes 2026-07-10 00:14:05 2026-07-10 00:14:05 +08:00
hajimi 76ef84aa8f deploy: auto commit server changes 2026-07-10 00:08:55 2026-07-10 00:08:55 +08:00
hajimi b584a8f98e deploy: auto commit server changes 2026-07-09 23:59:25 2026-07-09 23:59:25 +08:00
hajimi 34ff61d1ee deploy: auto commit server changes 2026-07-09 23:26:59 2026-07-09 23:26:59 +08:00
hajimi 3362e1e072 deploy: auto commit server changes 2026-07-09 23:26:00 2026-07-09 23:26:00 +08:00
hajimi 66fd64ef0f deploy: auto commit docker changes 2026-07-09 22:54:47 2026-07-09 22:54:47 +08:00
hajimi 6d2302875b deploy: auto commit repo-root changes 2026-07-05 15:53:58 2026-07-05 15:53:58 +08:00
hajimi 299d508d7c deploy: auto commit repo-root changes 2026-07-05 13:47:57 2026-07-05 13:47:57 +08:00
hajimi f641276b9d deploy: auto commit repo-root changes 2026-07-05 12:33:57 2026-07-05 12:33:57 +08:00
hajimi 1954948445 deploy: auto commit repo-root changes 2026-07-05 12:03:49 2026-07-05 12:03:49 +08:00
hajimi 074aa7ab3e deploy: auto commit repo-root changes 2026-07-05 11:43:29 2026-07-05 11:43:30 +08:00
hajimi ffa60e6b26 deploy: auto commit repo-root changes 2026-07-05 00:07:03 2026-07-05 00:07:04 +08:00
hajimi 9f85b559b0 deploy: auto commit repo-root changes 2026-07-05 00:04:07 2026-07-05 00:04:07 +08:00
hajimi 354b100558 deploy: auto commit uniapp changes 2026-07-05 00:00:02 2026-07-05 00:00:02 +08:00
hajimi 675246cde2 deploy: auto commit uniapp changes 2026-07-04 23:59:31 2026-07-04 23:59:31 +08:00
hajimi 6081254d63 deploy: auto commit repo-root changes 2026-07-04 23:57:27 2026-07-04 23:57:28 +08:00
hajimi 2de27db0e6 deploy: auto commit repo-root changes 2026-07-03 22:36:29 2026-07-03 22:36:29 +08:00
hajimi 5a888a730e deploy: auto commit repo-root changes 2026-07-03 22:33:26 2026-07-03 22:33:26 +08:00
hajimi 311c6c6224 deploy: auto commit repo-root changes 2026-07-03 21:52:42 2026-07-03 21:52:42 +08:00
hajimi 204cb361c6 deploy: auto commit repo-root changes 2026-07-03 21:49:44 2026-07-03 21:49:44 +08:00
hajimi b1539d9baf deploy: auto commit repo-root changes 2026-07-03 21:46:58 2026-07-03 21:46:58 +08:00
hajimi 6229b98076 deploy: auto commit repo-root changes 2026-07-03 21:32:43 2026-07-03 21:32:43 +08:00
hajimi 33664adbe0 fix: sync yuyan anchor live stream task 2026-07-03 21:10:05 +08:00
hajimi 8c358dc376 deploy: auto commit repo-root changes 2026-07-03 19:33:14 2026-07-03 19:33:14 +08:00
hajimi bbb6e9ab69 deploy: auto commit repo-root changes 2026-07-03 19:05:07 2026-07-03 19:05:07 +08:00
hajimi a88764162d deploy: auto commit repo-root changes 2026-07-03 18:56:25 2026-07-03 18:56:25 +08:00
hajimi affb0a4002 fix: keep worldcup live cards above tabbar 2026-07-03 17:51:08 +08:00
hajimi 7c260b1f99 deploy: auto commit server/public/mobile changes 2026-07-03 17:48:34 2026-07-03 17:48:34 +08:00
hajimi 61310de5a0 deploy: auto commit repo-root changes 2026-07-03 17:27:21 2026-07-03 17:27:22 +08:00
hajimi b8203e6168 deploy: auto commit repo-root changes 2026-06-24 16:55:29 2026-06-24 16:55:29 +08:00
hajimi a281b5fa8e deploy: auto commit repo-root changes 2026-06-24 16:53:33 2026-06-24 16:53:33 +08:00
hajimi 0d985506ba deploy: auto commit repo-root changes 2026-06-24 00:25:10 2026-06-24 00:25:10 +08:00
hajimi 2ec3b2dab5 整理临时文件 2026-06-22 10:57:07 +08:00
hajimi 27334d8589 deploy: auto commit repo-root changes 2026-06-22 01:45:37 2026-06-22 01:45:37 +08:00
hajimi 51718e11f3 deploy: auto commit repo-root changes 2026-06-22 01:44:20 2026-06-22 01:44:20 +08:00
hajimi ee9a5a3d03 no message 2026-06-22 01:31:20 +08:00
hajimi 9994c71374 deploy: auto commit repo-root changes 2026-06-22 01:20:41 2026-06-22 01:20:41 +08:00
hajimi 166740a74c deploy: auto commit repo-root changes 2026-06-21 22:05:33 2026-06-21 22:05:33 +08:00
hajimi f6d967869d deploy: auto commit repo-root changes 2026-06-21 19:30:16 2026-06-21 19:30:17 +08:00
hajimi 980b019809 deploy: auto commit repo-root changes 2026-06-21 17:56:21 2026-06-21 17:56:21 +08:00
hajimi bb1a2ebb9e deploy: auto commit repo-root changes 2026-06-21 17:13:24 2026-06-21 17:13:25 +08:00
hajimi 5435fe3686 Merge branch 'codex/match-live-streams' into dev.1.0.0 2026-06-21 16:50:16 +08:00
hajimi a51ed4bb95 deploy: auto commit repo-root changes 2026-06-21 16:39:29 2026-06-21 16:39:29 +08:00
hajimi f654081e8f refactor: move match live admin ui to dedicated page 2026-06-21 16:30:28 +08:00
hajimi 6722f6f7cc deploy: auto commit repo-root changes 2026-06-21 16:10:02 2026-06-21 16:10:02 +08:00
hajimi 875a770c5a fix: correct match live menu seed sql 2026-06-21 13:49:35 +08:00
hajimi 229b70c1be fix: require match live menu parent 2026-06-21 13:47:07 +08:00
hajimi 75a529be35 fix: preserve live streams on title edits 2026-06-21 13:44:05 +08:00
hajimi 08c1affb14 test: cover match live stream repository updates 2026-06-21 13:41:56 +08:00
hajimi 4ab24a9ae8 Strengthen match live admin static QA 2026-06-21 13:21:55 +08:00
hajimi 173871cf6a Add static admin QA for match live table 2026-06-21 13:10:33 +08:00
hajimi a8a678a5f6 fix: map live fetch status failure code 2026-06-21 13:02:22 +08:00
hajimi c59b7ade29 fix: align uniapp live stream metadata fields 2026-06-21 12:57:27 +08:00
hajimi 5f2e2e6c00 feat: add uniapp match live stream switching 2026-06-21 12:46:53 +08:00
hajimi 750ef91e29 fix: expose match live stream task error on failure 2026-06-21 12:32:49 +08:00
hajimi a9281f27c7 fix: surface match live stream partial failures 2026-06-21 12:29:36 +08:00
hajimi ecef509037 fix: accept semicolon jsonp in live stream parser 2026-06-21 12:22:19 +08:00
hajimi 11b06be9b1 test: cover semicolon jsonp in match live stream parser 2026-06-21 12:21:48 +08:00
hajimi bc9aef5a2f feat: add docker match live stream crawler 2026-06-21 12:15:40 +08:00
hajimi 7ebd563134 fix: guard match live validator scalars 2026-06-21 12:08:40 +08:00
hajimi cd9530686c fix: harden match live validation 2026-06-21 12:04:01 +08:00
hajimi 80e0e6a8a6 feat: wire match live backend api 2026-06-21 11:52:02 +08:00
hajimi 8d528ba5fe test: enforce exact match live snippets 2026-06-21 11:43:29 +08:00
hajimi b133fd36ee test: harden match live static contract 2026-06-21 11:40:49 +08:00
hajimi dbdb418e15 feat: add match live service helpers 2026-06-21 11:32:08 +08:00
hajimi 2496050ee7 fix: align match live schema foundation 2026-06-21 11:21:21 +08:00
hajimi ee4f2504bd feat: add match live table foundation 2026-06-21 11:11:48 +08:00
hajimi 5a8585d027 docs: add match live streams design spec 2026-06-21 11:05:00 +08:00
hajimi 20f0b4b111 deploy: auto commit repo-root changes 2026-06-16 01:39:08 2026-06-16 01:39:09 +08:00
hajimi e501393b66 deploy: auto commit repo-root changes 2026-06-15 14:09:04 2026-06-15 14:09:04 +08:00
hajimi 127475e539 deploy: auto commit repo-root changes 2026-06-13 12:42:06 2026-06-13 12:42:06 +08:00
hajimi ed1733e49d deploy: auto commit repo-root changes 2026-06-13 11:53:47 2026-06-13 11:53:47 +08:00
hajimi d246ab44e2 deploy: auto commit repo-root changes 2026-06-13 11:43:39 2026-06-13 11:43:39 +08:00
hajimi 6b3bbab5ce docs: update lottery ai image localization progress 2026-06-13 11:36:18 +08:00
hajimi 93474019a4 deploy: auto commit repo-root changes 2026-06-13 11:35:15 2026-06-13 11:35:15 +08:00
hajimi 50f0b6aff5 no message 2026-06-13 10:47:34 +08:00
hajimi 186521392d deploy: auto commit repo-root changes 2026-06-13 00:33:38 2026-06-13 00:33:38 +08:00
hajimi c3385b0e04 deploy: auto commit repo-root changes 2026-06-13 00:17:26 2026-06-13 00:17:26 +08:00
hajimi 16b8d0365a deploy: auto commit repo-root changes 2026-06-12 23:16:53 2026-06-12 23:16:53 +08:00
hajimi 0d656e8076 deploy: auto commit repo-root changes 2026-06-12 23:11:28 2026-06-12 23:11:28 +08:00
hajimi cd44cd6e47 迁移目录 2026-06-12 22:27:18 +08:00
hajimi 7381097582 no message 2026-06-12 22:23:47 +08:00
hajimi 8dacaea803 deploy: auto commit repo-root changes 2026-06-12 21:09:54 2026-06-12 21:09:54 +08:00
hajimi 30d768a3e6 deploy: auto commit server changes 2026-06-12 18:38:59 2026-06-12 18:39:00 +08:00
hajimi 4509279ac7 deploy: auto commit server changes 2026-06-12 17:51:57 2026-06-12 17:51:58 +08:00
1209 changed files with 57728 additions and 2395 deletions
+7
View File
@@ -0,0 +1,7 @@
*
!docker/
!docker/Dockerfile.php
!docker/config/
!docker/config/php/
!docker/config/php/conf.d/
!docker/config/php/conf.d/zz-opcache.ini
+5
View File
@@ -28,3 +28,8 @@ bin-release/
**/.hbuilderx/ **/.hbuilderx/
**/unpackage/ **/unpackage/
qa/ qa/
.code-graph/
./vscode/
.tmp*
.codex/
docker/.env.server
@@ -0,0 +1 @@
[ 9545ms] [WARNING] Manifest: property 'start_url' ignored, should be same origin as document. @ https://git.zones.sbnews.net/assets/site-manifest.json:0
@@ -0,0 +1 @@
[ 11298ms] [WARNING] Manifest: property 'start_url' ignored, should be same origin as document. @ https://git.zones.sbnews.net/assets/site-manifest.json:0
@@ -0,0 +1,21 @@
[ 36930ms] [LOG] {highlight: , highlightAuto: , highlightAll: , highlightElement: , highlightBlock: } @ https://test-admin.sbnews.net/src/install/plugins/hljs.ts:3
[ 37002ms] CanceledError: get&adminapi/config/getConfig&&
at cancel (https://test-admin.sbnews.net/node_modules/.vite/deps/axios.js?v=3bc9d05f:3356:22)
at AxiosCancel.remove (https://test-admin.sbnews.net/src/utils/request/cancel.ts:24:17)
at AxiosCancel.add (https://test-admin.sbnews.net/src/utils/request/cancel.ts:14:10)
at Axios.addCancelToken (https://test-admin.sbnews.net/src/utils/request/axios.ts:80:39)
at https://test-admin.sbnews.net/src/utils/request/axios.ts:38:14
at async Axios.request (https://test-admin.sbnews.net/node_modules/.vite/deps/axios.js?v=3bc9d05f:3123:14)
[ 37002ms] CanceledError: get&adminapi/config/getConfig&&
at cancel (https://test-admin.sbnews.net/node_modules/.vite/deps/axios.js?v=3bc9d05f:3356:22)
at AxiosCancel.remove (https://test-admin.sbnews.net/src/utils/request/cancel.ts:24:17)
at AxiosCancel.add (https://test-admin.sbnews.net/src/utils/request/cancel.ts:14:10)
at Axios.addCancelToken (https://test-admin.sbnews.net/src/utils/request/axios.ts:80:39)
at https://test-admin.sbnews.net/src/utils/request/axios.ts:38:14
at async Axios.request (https://test-admin.sbnews.net/node_modules/.vite/deps/axios.js?v=3bc9d05f:3123:14)
[ 37100ms] [ERROR] Failed to load resource: the server responded with a status of 404 () @ https://test-admin.sbnews.net/favicon.ico:0
[ 37475ms] [ERROR] Mixed Content: The page at 'https://test-admin.sbnews.net/' was loaded over HTTPS, but requested an insecure favicon 'http://test-server.sbnews.net/uploads/images/20260411/20260411003702d55579016.png'. This request has been blocked; the content must be served over HTTPS. @ https://test-admin.sbnews.net/:0
[ 37490ms] [ERROR] Mixed Content: The page at 'https://test-admin.sbnews.net/' was loaded over HTTPS, but requested an insecure favicon 'http://test-server.sbnews.net/uploads/images/20260411/20260411003702d55579016.png'. This request has been blocked; the content must be served over HTTPS. @ https://test-admin.sbnews.net/:0
[ 38060ms] [WARNING] Mixed Content: The page at 'https://test-admin.sbnews.net/login?redirect=/' was loaded over HTTPS, but requested an insecure element 'http://test-server.sbnews.net/resource/image/adminapi/default/login_image.png'. This request was automatically upgraded to HTTPS, For more information see https://blog.chromium.org/2019/10/no-more-mixed-messages-about-https.html @ https://test-admin.sbnews.net/login?redirect=/:0
[ 38093ms] [ERROR] Mixed Content: The page at 'https://test-admin.sbnews.net/login?redirect=/' was loaded over HTTPS, but requested an insecure favicon 'http://test-server.sbnews.net/uploads/images/20260411/20260411003702d55579016.png'. This request has been blocked; the content must be served over HTTPS. @ https://test-admin.sbnews.net/login?redirect=/:0
[ 38094ms] [ERROR] Mixed Content: The page at 'https://test-admin.sbnews.net/login?redirect=/' was loaded over HTTPS, but requested an insecure favicon 'http://test-server.sbnews.net/uploads/images/20260411/20260411003702d55579016.png'. This request has been blocked; the content must be served over HTTPS. @ https://test-admin.sbnews.net/login?redirect=/:0
@@ -0,0 +1,29 @@
[ 37585ms] [LOG] %c uni-router %c v1.2.7 padding: 2px 1px; border-radius: 3px 0 0 3px; color: #fff; background: #606060; font-weight: bold; padding: 2px 1px; border-radius: 0 3px 3px 0; color: #fff; background: #42c02e; font-weight: bold; @ https://testh5.sbnews.net/node_modules/.vite/deps/uniapp-router-next.js?v=d65138d7:1179
[ 37623ms] [LOG] [app] onLaunch 开始执行 @ https://testh5.sbnews.net/src/App.vue?t=1785577437473:47
[ 37657ms] [LOG] [app] onLaunch 执行完毕 @ https://testh5.sbnews.net/src/App.vue?t=1785577437473:71
[ 37657ms] [LOG] [app] onShow: config未加载,重新拉取 @ https://testh5.sbnews.net/src/App.vue?t=1785577437473:76
[ 37666ms] [ERROR] Access to XMLHttpRequest at 'http://127.0.0.1:8000/api/index/decorate?id=5' from origin 'https://testh5.sbnews.net' has been blocked by CORS policy: Permission was denied for this request to access the `loopback` address space. @ https://testh5.sbnews.net/:0
[ 37666ms] [ERROR] Failed to load resource: net::ERR_FAILED @ http://127.0.0.1:8000/api/index/decorate?id=5:0
[ 37666ms] [ERROR] Access to XMLHttpRequest at 'http://127.0.0.1:8000/api/index/config' from origin 'https://testh5.sbnews.net' has been blocked by CORS policy: Permission was denied for this request to access the `loopback` address space. @ https://testh5.sbnews.net/:0
[ 37666ms] [ERROR] Failed to load resource: net::ERR_FAILED @ http://127.0.0.1:8000/api/index/config:0
[ 37732ms] Object
[ 37666ms] [ERROR] Access to XMLHttpRequest at 'http://127.0.0.1:8000/api/index/config' from origin 'https://testh5.sbnews.net' has been blocked by CORS policy: Permission was denied for this request to access the `loopback` address space. @ https://testh5.sbnews.net/:0
[ 37667ms] [ERROR] Failed to load resource: net::ERR_FAILED @ http://127.0.0.1:8000/api/index/config:0
[ 37667ms] [ERROR] Access to XMLHttpRequest at 'http://127.0.0.1:8000/api/device/register' from origin 'https://testh5.sbnews.net' has been blocked by CORS policy: Permission was denied for this request to access the `loopback` address space. @ https://testh5.sbnews.net/:0
[ 37671ms] [WARNING] [device] 设备信息上报失败: {errMsg: request:fail} @ https://testh5.sbnews.net/src/utils/device.ts?t=1785577437473:74
[ 37671ms] [ERROR] Failed to load resource: net::ERR_FAILED @ http://127.0.0.1:8000/api/device/register:0
[ 37732ms] Object
[ 37732ms] Object
[ 39200ms] [LOG] 获取分类失败=> {errMsg: request:fail abort} @ https://testh5.sbnews.net/src/pages/index/index.vue?t=1785577437465:82
[ 39203ms] [ERROR] Access to XMLHttpRequest at 'http://127.0.0.1:8000/api/match/lists' from origin 'https://testh5.sbnews.net' has been blocked by CORS policy: Permission was denied for this request to access the `loopback` address space. @ https://testh5.sbnews.net/:0
[ 39203ms] [LOG] 获取首页焦点赛程失败=> {errMsg: request:fail} @ https://testh5.sbnews.net/src/pages/index/index.vue?t=1785577437465:94
[ 39206ms] [ERROR] Failed to load resource: net::ERR_FAILED @ http://127.0.0.1:8000/api/match/lists:0
[ 39206ms] [ERROR] Access to XMLHttpRequest at 'http://127.0.0.1:8000/api/article/cate' from origin 'https://testh5.sbnews.net' has been blocked by CORS policy: Permission was denied for this request to access the `loopback` address space. @ https://testh5.sbnews.net/:0
[ 39207ms] [LOG] 获取分类失败=> {errMsg: request:fail} @ https://testh5.sbnews.net/src/pages/index/index.vue?t=1785577437465:82
[ 39207ms] [ERROR] Failed to load resource: net::ERR_FAILED @ http://127.0.0.1:8000/api/article/cate:0
[ 39222ms] [ERROR] Access to XMLHttpRequest at 'http://127.0.0.1:8000/api/popup/list?page_path=%2Fpages%2Findex%2Findex&platform=h5' from origin 'https://testh5.sbnews.net' has been blocked by CORS policy: Permission was denied for this request to access the `loopback` address space. @ https://testh5.sbnews.net/:0
[ 39223ms] [WARNING] [GlobalPopup] 拉取弹窗失败: {errMsg: request:fail} @ https://testh5.sbnews.net/src/components/global-popup/global-popup.vue:123
[ 39223ms] [ERROR] Failed to load resource: net::ERR_FAILED @ http://127.0.0.1:8000/api/popup/list?page_path=%2Fpages%2Findex%2Findex&platform=h5:0
[ 39223ms] [ERROR] Access to XMLHttpRequest at 'http://127.0.0.1:8000/api/article/lists?page_no=1&page_size=10&is_recommend=1' from origin 'https://testh5.sbnews.net' has been blocked by CORS policy: Permission was denied for this request to access the `loopback` address space. @ https://testh5.sbnews.net/:0
[ 39223ms] [LOG] 首页资讯加载失败=> {errMsg: request:fail} @ https://testh5.sbnews.net/src/pages/index/index.vue?t=1785577437465:141
[ 39225ms] [ERROR] Failed to load resource: net::ERR_FAILED @ http://127.0.0.1:8000/api/article/lists?page_no=1&page_size=10&is_recommend=1:0
@@ -0,0 +1,18 @@
[ 5931ms] [LOG] {highlight: , highlightAuto: , highlightAll: , highlightElement: , highlightBlock: } @ https://test-admin.sbnews.net/src/install/plugins/hljs.ts:3
[ 6130ms] CanceledError: get&adminapi/config/getConfig&&
at cancel (https://test-admin.sbnews.net/node_modules/.vite/deps/axios.js?v=3bc9d05f:3356:22)
at AxiosCancel.remove (https://test-admin.sbnews.net/src/utils/request/cancel.ts:24:17)
at AxiosCancel.add (https://test-admin.sbnews.net/src/utils/request/cancel.ts:14:10)
at Axios.addCancelToken (https://test-admin.sbnews.net/src/utils/request/axios.ts:80:39)
at https://test-admin.sbnews.net/src/utils/request/axios.ts:38:14
at async Axios.request (https://test-admin.sbnews.net/node_modules/.vite/deps/axios.js?v=3bc9d05f:3123:14)
[ 6131ms] CanceledError: get&adminapi/config/getConfig&&
at cancel (https://test-admin.sbnews.net/node_modules/.vite/deps/axios.js?v=3bc9d05f:3356:22)
at AxiosCancel.remove (https://test-admin.sbnews.net/src/utils/request/cancel.ts:24:17)
at AxiosCancel.add (https://test-admin.sbnews.net/src/utils/request/cancel.ts:14:10)
at Axios.addCancelToken (https://test-admin.sbnews.net/src/utils/request/axios.ts:80:39)
at https://test-admin.sbnews.net/src/utils/request/axios.ts:38:14
at async Axios.request (https://test-admin.sbnews.net/node_modules/.vite/deps/axios.js?v=3bc9d05f:3123:14)
[ 6380ms] [ERROR] Mixed Content: The page at 'https://test-admin.sbnews.net/login?redirect=/' was loaded over HTTPS, but requested an insecure favicon 'http://test-server.sbnews.net/uploads/images/20260411/20260411003702d55579016.png'. This request has been blocked; the content must be served over HTTPS. @ https://test-admin.sbnews.net/login?redirect=/:0
[ 6381ms] [ERROR] Mixed Content: The page at 'https://test-admin.sbnews.net/login?redirect=/' was loaded over HTTPS, but requested an insecure favicon 'http://test-server.sbnews.net/uploads/images/20260411/20260411003702d55579016.png'. This request has been blocked; the content must be served over HTTPS. @ https://test-admin.sbnews.net/login?redirect=/:0
[ 7366ms] [WARNING] Mixed Content: The page at 'https://test-admin.sbnews.net/login?redirect=/' was loaded over HTTPS, but requested an insecure element 'http://test-server.sbnews.net/resource/image/adminapi/default/login_image.png'. This request was automatically upgraded to HTTPS, For more information see https://blog.chromium.org/2019/10/no-more-mixed-messages-about-https.html @ https://test-admin.sbnews.net/login?redirect=/:0
@@ -0,0 +1,27 @@
[ 21198ms] [LOG] %c uni-router %c v1.2.7 padding: 2px 1px; border-radius: 3px 0 0 3px; color: #fff; background: #606060; font-weight: bold; padding: 2px 1px; border-radius: 0 3px 3px 0; color: #fff; background: #42c02e; font-weight: bold; @ https://testh5.sbnews.net/node_modules/.vite/deps/uniapp-router-next.js?v=d65138d7:1179
[ 21211ms] [LOG] [app] onLaunch 开始执行 @ https://testh5.sbnews.net/src/App.vue?t=1785577437473:47
[ 21214ms] [LOG] [app] onLaunch 执行完毕 @ https://testh5.sbnews.net/src/App.vue?t=1785577437473:71
[ 21215ms] [LOG] [app] onShow: config未加载,重新拉取 @ https://testh5.sbnews.net/src/App.vue?t=1785577437473:76
[ 21295ms] Object
[ 21256ms] [ERROR] Access to XMLHttpRequest at 'http://127.0.0.1:8000/api/device/register' from origin 'https://testh5.sbnews.net' has been blocked by CORS policy: Permission was denied for this request to access the `loopback` address space. @ https://testh5.sbnews.net/:0
[ 21258ms] [WARNING] [device] 设备信息上报失败: {errMsg: request:fail} @ https://testh5.sbnews.net/src/utils/device.ts?t=1785577437473:74
[ 21259ms] [ERROR] Failed to load resource: net::ERR_FAILED @ http://127.0.0.1:8000/api/device/register:0
[ 21259ms] [ERROR] Access to XMLHttpRequest at 'http://127.0.0.1:8000/api/index/decorate?id=5' from origin 'https://testh5.sbnews.net' has been blocked by CORS policy: Permission was denied for this request to access the `loopback` address space. @ https://testh5.sbnews.net/:0
[ 21259ms] [ERROR] Failed to load resource: net::ERR_FAILED @ http://127.0.0.1:8000/api/index/decorate?id=5:0
[ 21259ms] [ERROR] Access to XMLHttpRequest at 'http://127.0.0.1:8000/api/index/config' from origin 'https://testh5.sbnews.net' has been blocked by CORS policy: Permission was denied for this request to access the `loopback` address space. @ https://testh5.sbnews.net/:0
[ 21259ms] [ERROR] Failed to load resource: net::ERR_FAILED @ http://127.0.0.1:8000/api/index/config:0
[ 21306ms] Object
[ 21306ms] Object
[ 22145ms] [LOG] 获取分类失败=> {errMsg: request:fail abort} @ https://testh5.sbnews.net/src/pages/index/index.vue?t=1785577437465:82
[ 22148ms] [ERROR] Access to XMLHttpRequest at 'http://127.0.0.1:8000/api/match/lists' from origin 'https://testh5.sbnews.net' has been blocked by CORS policy: Permission was denied for this request to access the `loopback` address space. @ https://testh5.sbnews.net/:0
[ 22148ms] [LOG] 获取首页焦点赛程失败=> {errMsg: request:fail} @ https://testh5.sbnews.net/src/pages/index/index.vue?t=1785577437465:94
[ 22150ms] [ERROR] Failed to load resource: net::ERR_FAILED @ http://127.0.0.1:8000/api/match/lists:0
[ 22150ms] [ERROR] Access to XMLHttpRequest at 'http://127.0.0.1:8000/api/article/cate' from origin 'https://testh5.sbnews.net' has been blocked by CORS policy: Permission was denied for this request to access the `loopback` address space. @ https://testh5.sbnews.net/:0
[ 22150ms] [LOG] 获取分类失败=> {errMsg: request:fail} @ https://testh5.sbnews.net/src/pages/index/index.vue?t=1785577437465:82
[ 22151ms] [ERROR] Failed to load resource: net::ERR_FAILED @ http://127.0.0.1:8000/api/article/cate:0
[ 22151ms] [ERROR] Access to XMLHttpRequest at 'http://127.0.0.1:8000/api/popup/list?page_path=%2Fpages%2Findex%2Findex&platform=h5' from origin 'https://testh5.sbnews.net' has been blocked by CORS policy: Permission was denied for this request to access the `loopback` address space. @ https://testh5.sbnews.net/:0
[ 22151ms] [WARNING] [GlobalPopup] 拉取弹窗失败: {errMsg: request:fail} @ https://testh5.sbnews.net/src/components/global-popup/global-popup.vue:123
[ 22151ms] [ERROR] Failed to load resource: net::ERR_FAILED @ http://127.0.0.1:8000/api/popup/list?page_path=%2Fpages%2Findex%2Findex&platform=h5:0
[ 22153ms] [ERROR] Access to XMLHttpRequest at 'http://127.0.0.1:8000/api/article/lists?page_no=1&page_size=10&is_recommend=1' from origin 'https://testh5.sbnews.net' has been blocked by CORS policy: Permission was denied for this request to access the `loopback` address space. @ https://testh5.sbnews.net/:0
[ 22153ms] [LOG] 首页资讯加载失败=> {errMsg: request:fail} @ https://testh5.sbnews.net/src/pages/index/index.vue?t=1785577437465:141
[ 22155ms] [ERROR] Failed to load resource: net::ERR_FAILED @ http://127.0.0.1:8000/api/article/lists?page_no=1&page_size=10&is_recommend=1:0
@@ -0,0 +1,75 @@
- generic [active] [ref=e1]:
- generic [ref=e2]:
- navigation "导航栏" [ref=e3]:
- generic [ref=e4]:
- link "首页" [ref=e5] [cursor=pointer]:
- /url: /
- link "探索" [ref=e7] [cursor=pointer]:
- /url: /explore/repos
- link "帮助" [ref=e8] [cursor=pointer]:
- /url: https://docs.gitea.com
- generic [ref=e9]:
- link "注册" [ref=e10] [cursor=pointer]:
- /url: /user/sign_up
- link "登录" [ref=e14] [cursor=pointer]:
- /url: /user/login
- main "首页" [ref=e18]:
- generic [ref=e20]:
- img "Logo" [ref=e21]
- generic [ref=e22]:
- heading "HAHA" [level=1] [ref=e23]
- heading "一款极易搭建的自托管 Git 服务" [level=2] [ref=e24]
- generic [ref=e25]:
- generic [ref=e26]:
- heading "易安装" [level=1] [ref=e27]
- paragraph [ref=e30]:
- text: 直接
- link "运行适合您平台的二进制文件" [ref=e31] [cursor=pointer]:
- /url: https://docs.gitea.com/installation/install-from-binary
- text: ,通过
- link "Docker" [ref=e32] [cursor=pointer]:
- /url: https://github.com/go-gitea/gitea/tree/master/docker
- text: 部署,或使用
- link "软件包" [ref=e33] [cursor=pointer]:
- /url: https://docs.gitea.com/installation/install-from-package
- text: 安装。
- generic [ref=e34]:
- heading "跨平台" [level=1] [ref=e35]
- paragraph [ref=e38]:
- text: 任何
- link "Go 语言" [ref=e39] [cursor=pointer]:
- /url: https://go.dev/
- text: 支持的平台都可以运行 Gitea,包括 Windows、Mac、Linux 以及 ARM。挑一个您喜欢的就行!
- generic [ref=e40]:
- generic [ref=e41]:
- heading "轻量级" [level=1] [ref=e42]
- paragraph [ref=e45]: 一个廉价的树莓派就足以满足 Gitea 的最低系统硬件要求。最大程度节省您的服务器资源!
- generic [ref=e46]:
- heading "开源化" [level=1] [ref=e47]
- paragraph [ref=e50]:
- text: 所有代码都开源在
- link "gitea.dev" [ref=e51] [cursor=pointer]:
- /url: https://gitea.dev
- text: ,还等什么?赶快加入我们来
- link "共同发展" [ref=e52] [cursor=pointer]:
- /url: https://github.com/go-gitea/gitea
- text: 这个伟大的项目,成为贡献者吧!
- group "页脚" [ref=e53]:
- contentinfo "关于软件" [ref=e54]:
- link "由 Gitea 强力驱动" [ref=e55] [cursor=pointer]:
- /url: https://about.gitea.com
- generic [ref=e56]: "版本: 1.27.1"
- generic [ref=e57]:
- text: "页面:"
- strong [ref=e58]: 1ms
- text: "模板:"
- strong [ref=e59]: 1ms
- group "链接" [ref=e60]:
- menu [ref=e61] [cursor=pointer]:
- generic [ref=e62]: Auto
- menu [ref=e66] [cursor=pointer]:
- generic [ref=e67]: 简体中文
- link "许可证" [ref=e70] [cursor=pointer]:
- /url: /assets/licenses.txt
- link "API" [ref=e71] [cursor=pointer]:
- /url: /api/swagger
@@ -0,0 +1,75 @@
- generic [active] [ref=f1e1]:
- generic [ref=f1e2]:
- navigation "导航栏" [ref=f1e3]:
- generic [ref=f1e4]:
- link "首页" [ref=f1e5] [cursor=pointer]:
- /url: /
- link "探索" [ref=f1e7] [cursor=pointer]:
- /url: /explore/repos
- link "帮助" [ref=f1e8] [cursor=pointer]:
- /url: https://docs.gitea.com
- generic [ref=f1e9]:
- link "注册" [ref=f1e10] [cursor=pointer]:
- /url: /user/sign_up
- link "登录" [ref=f1e14] [cursor=pointer]:
- /url: /user/login
- main "首页" [ref=f1e18]:
- generic [ref=f1e20]:
- img "Logo" [ref=f1e21]
- generic [ref=f1e22]:
- heading "HAHA" [level=1] [ref=f1e23]
- heading "一款极易搭建的自托管 Git 服务" [level=2] [ref=f1e24]
- generic [ref=f1e25]:
- generic [ref=f1e26]:
- heading "易安装" [level=1] [ref=f1e27]
- paragraph [ref=f1e30]:
- text: 直接
- link "运行适合您平台的二进制文件" [ref=f1e31] [cursor=pointer]:
- /url: https://docs.gitea.com/installation/install-from-binary
- text: ,通过
- link "Docker" [ref=f1e32] [cursor=pointer]:
- /url: https://github.com/go-gitea/gitea/tree/master/docker
- text: 部署,或使用
- link "软件包" [ref=f1e33] [cursor=pointer]:
- /url: https://docs.gitea.com/installation/install-from-package
- text: 安装。
- generic [ref=f1e34]:
- heading "跨平台" [level=1] [ref=f1e35]
- paragraph [ref=f1e38]:
- text: 任何
- link "Go 语言" [ref=f1e39] [cursor=pointer]:
- /url: https://go.dev/
- text: 支持的平台都可以运行 Gitea,包括 Windows、Mac、Linux 以及 ARM。挑一个您喜欢的就行!
- generic [ref=f1e40]:
- generic [ref=f1e41]:
- heading "轻量级" [level=1] [ref=f1e42]
- paragraph [ref=f1e45]: 一个廉价的树莓派就足以满足 Gitea 的最低系统硬件要求。最大程度节省您的服务器资源!
- generic [ref=f1e46]:
- heading "开源化" [level=1] [ref=f1e47]
- paragraph [ref=f1e50]:
- text: 所有代码都开源在
- link "gitea.dev" [ref=f1e51] [cursor=pointer]:
- /url: https://gitea.dev
- text: ,还等什么?赶快加入我们来
- link "共同发展" [ref=f1e52] [cursor=pointer]:
- /url: https://github.com/go-gitea/gitea
- text: 这个伟大的项目,成为贡献者吧!
- group "页脚" [ref=f1e53]:
- contentinfo "关于软件" [ref=f1e54]:
- link "由 Gitea 强力驱动" [ref=f1e55] [cursor=pointer]:
- /url: https://about.gitea.com
- generic [ref=f1e56]: "版本: 1.27.1"
- generic [ref=f1e57]:
- text: "页面:"
- strong [ref=f1e58]: 3ms
- text: "模板:"
- strong [ref=f1e59]: 3ms
- group "链接" [ref=f1e60]:
- menu [ref=f1e61] [cursor=pointer]:
- generic [ref=f1e62]: Auto
- menu [ref=f1e66] [cursor=pointer]:
- generic [ref=f1e67]: 简体中文
- link "许可证" [ref=f1e70] [cursor=pointer]:
- /url: /assets/licenses.txt
- link "API" [ref=f1e71] [cursor=pointer]:
- /url: /api/swagger
@@ -0,0 +1,12 @@
- generic [active] [ref=f1e1]:
- generic [ref=f1e10]:
- generic [ref=f1e12]: 首页
- generic [ref=f1e17]: 赛事
- generic [ref=f1e22]: 加密行情
- generic [ref=f1e27]: 彩票
- generic [ref=f1e32]: 社区
- generic [ref=f1e37]: 我的
- generic:
- generic:
- generic:
- paragraph: 请求失败,请重试
@@ -0,0 +1,12 @@
- generic [active] [ref=f3e1]:
- generic [ref=f3e7]:
- generic [ref=f3e9]: 首页
- generic [ref=f3e14]: 赛事
- generic [ref=f3e19]: 加密行情
- generic [ref=f3e24]: 彩票
- generic [ref=f3e29]: 社区
- generic [ref=f3e34]: 我的
- generic:
- generic:
- generic:
- paragraph: 请求失败,请重试
+34 -5
View File
@@ -35,7 +35,7 @@
3. 相同或相似的功能必须封装为可复用的方法,避免重复代码。 3. 相同或相似的功能必须封装为可复用的方法,避免重复代码。
4. 查询字段、路由、菜单、配置前,优先以当前项目代码和 `sbnews.sql` / `docs/sql/` 中结构为准;如需线上核对,再按用户要求使用可用 MCP 或指定连接方式。 4. 查询字段、路由、菜单、配置前,优先以当前项目代码和 `sbnews.sql` / `docs/sql/` 中结构为准;如需线上核对,再按用户要求使用可用 MCP 或指定连接方式。
5. 不通过 WSL sshpass/scp 上传代码到服务器;项目代码更新由用户自行通过 SFTP 等方式处理。 5. 不通过 WSL sshpass/scp 上传代码到服务器;项目代码更新由用户自行通过 SFTP 等方式处理。
6. 项目级文档(如协作规范、业务进度、设计稿映射、产品方案、实现流程、爬虫说明等)统一存放在项目根目录;仅子项目专属文档放在对应子目录。 6. 新增项目级文档(如协作规范、业务进度、设计稿映射、产品方案、实现流程、爬虫说明等)统一存放在 `docs/`;根目录仅保留 `README.md``AGENTS.md``文档索引.md` 等入口文件。仅子项目专属的 README / AGENTS 等说明可放在对应子目录。
--- ---
@@ -48,6 +48,15 @@
| uniapp | `npm run dev:h5` | `npm run build:h5` | | uniapp | `npm run dev:h5` | `npm run build:h5` |
| pc | `npm run dev` | `npm run generate` / `npm run build` | | pc | `npm run dev` | `npm run generate` / `npm run build` |
## 自动化执行边界
- 除非用户在当前任务中明确要求,否则不要自动执行构建或测试。
- **持续授权:每次修改真实源码或运行配置后都必须创建 Git commit,无须再次询问。**说明文档及 `server/public/admin``server/public/mobile` 等生成产物不属于该触发范围。
- **`server/` 例外:**本次修改 `server/` 下的真实运行源码或运行配置时,除提交外还必须同步测试服;无需用户重复要求。
- `admin/``uniapp/``pc/``docker/``python/``qa/``scripts/` 等非 `server/` 源码改动只提交 commit,不自动同步测试站点;用户明确要求时除外。
- 用户明确要求“构建”“测试”“部署”“上线”“发布”等操作时,才执行对应命令;但 `server/` 源码变更适用上述持续授权同步例外。
- 对已经由用户给出的命令,可按用户原命令执行;不要额外扩展到未要求的构建、测试、提交或部署步骤。
## 数据库结构基准 ## 数据库结构基准
- 数据库表前缀:`la_` - 数据库表前缀:`la_`
@@ -77,7 +86,7 @@
## 代码修改后验证与评审 ## 代码修改后验证与评审
除非用户特别说明不需要验证,代码修改完成后按改动类型选择验证方式: 仅在用户明确要求验证、测试或构建时,代码修改完成后按改动类型选择验证方式;未明确要求时只列出建议命令,不自动执行
### 后端接口修改 ### 后端接口修改
@@ -104,13 +113,25 @@
| 5 | 命名一致性 | 字段、方法、路由命名与现有风格一致 | | 5 | 命名一致性 | 字段、方法、路由命名与现有风格一致 |
| 6 | 安全性 | SQL 拼接、用户输入、权限校验是否安全 | | 6 | 安全性 | SQL 拼接、用户输入、权限校验是否安全 |
| 7 | 幂等性 | SQL 初始化必须可重复执行 | | 7 | 幂等性 | SQL 初始化必须可重复执行 |
| 8 | 文档同步 | 功能完成后更新 `业务进度管理.md` | | 8 | 文档同步 | 功能完成后更新 `docs/业务进度管理.md` |
## 服务器源码变更后必须同步
- 每次修改 `server/` 下的真实运行源码或运行配置后,完成必要的静态检查后必须先创建 Git commit,再将代码同步到测试服;这是一项持续授权,不需要用户重复要求。
- 使用项目部署脚本并保留 `-Sudo` 参数,目标目录固定为 `/www/wwwroot/test-server.sbnews.net`,避免 Docker 创建的 root 权限文件中断更新。
- 默认使用以下命令将最新代码更新到测试服运行环境:
```powershell
Set-Location D:\www\gs-sport-era; powershell -ExecutionPolicy Bypass -File .\scripts\deploy-server.ps1 -Sudo -AutoIncremental -AutoIncrementalCommits 3 -RemoteDir /www/wwwroot/test-server.sbnews.net
```
- `admin/``uniapp/``pc/``docker/``python/``qa/``scripts/` 等非 `server/` 源码改动必须提交 commit,但不要因此自动同步服务器。`docs/` 等说明文档不触发自动提交或服务器同步。
## 设计稿映射 ## 设计稿映射
设计稿与页面/组件映射统一维护在: 设计稿与页面/组件映射统一维护在:
- [设计稿映射.md](./设计稿映射.md) - [设计稿映射.md](./docs/设计稿映射.md)
开发或还原视觉前,先确认设计稿名称、页面路径、实现状态与备注。 开发或还原视觉前,先确认设计稿名称、页面路径、实现状态与备注。
@@ -118,10 +139,18 @@
当前业务进度、待办事项、避坑记录统一维护在: 当前业务进度、待办事项、避坑记录统一维护在:
- [业务进度管理.md](./业务进度管理.md) - [业务进度管理.md](./docs/业务进度管理.md)
开发或接手任务前,先查看该文档确认已完成事项、进行中事项、待办事项与避坑记录。 开发或接手任务前,先查看该文档确认已完成事项、进行中事项、待办事项与避坑记录。
## 近期交接总结
- 当前真实开发目录以 `D:\www\gs-sport-era` 为准;Codex worktree(如 `C:\Users\Administrator\.codex\worktrees\...\gs-sport-era`)中的改动不会自动进入真实仓库、`git log` 或服务器运行目录。涉及可部署代码时,先确认改动已经同步到真实目录并形成清晰提交。
- 正确的服务器运行目录是 `/www/wwwroot/test-server.sbnews.net``/www/wwwroot/api.sbnews.net` 不是当前项目的有效同步目录,不要再部署到该路径。排查“代码已更新但服务器没生效”时,本地真实仓库看 `git log`,服务器侧看文件内容、修改时间、容器内 `/app` 文件与定时任务日志。
- Docker crawler 任务真实执行入口是 `sport-era-crawler` 容器。更新 `docker/crawler` 源码或 `config/crawler_tasks.yaml` 后,必须在服务器 `docker` 目录执行 `sudo docker compose -f docker-compose.crawler.yml build crawler``sudo docker compose -f docker-compose.crawler.yml up -d --no-deps crawler`;仅重启旧容器不能保证镜像内代码更新,必要时使用 `--no-cache` 重建。
- 重启 crawler 后必须核验容器内代码和 cron,而不是只看宿主机源码:例如检查 `/app/match_live_stream.py``/app/config/crawler_tasks.yaml`,以及 `cat /etc/cron.d/* | grep match_live_stream`
- 雨燕直播间任务 `match_live_stream` 当前应直接同步 `all_live_rooms.json`,写入主播 `anchor_id``anchor_name``anchor_avatar``anchor_level` 以及直播间观看/关注/公告/简介字段;对应 SQL 为 `docs/sql/alter_match_live_anchor_fields.sql``docs/sql/insert_crontab_match_live_stream.sql`。上线后用 `la_match_live` 主播字段统计和 `la_crawler_task_log` 最近任务状态共同确认是否生效。
## 近期踩坑 ## 近期踩坑
- `Validate::only()` 只限制校验字段范围,不会自动过滤请求参数;新增字段落库前,要同时检查 validate、logic、model、保存白名单和数据库列是否同步。 - `Validate::only()` 只限制校验字段范围,不会自动过滤请求参数;新增字段落库前,要同时检查 validate、logic、model、保存白名单和数据库列是否同步。
+54 -21
View File
@@ -14,11 +14,15 @@ Docker 只负责运行 Python 爬虫和容器内 cron。MySQL、Redis、Nginx
配置源: 配置源:
- Docker Compose`docker/docker-compose.crawler.yml` - Docker Compose`docker/docker-compose.crawler.yml`
- Compose 路径变量示例:`docker/.env.example`
- 环境变量示例:`docker/.env.docker.example` - 环境变量示例:`docker/.env.docker.example`
- 任务清单:`server/public/dongqiudi-crawler/config/crawler_tasks.yaml` - 爬虫源码:`docker/crawler`
- 任务清单:`docker/crawler/config/crawler_tasks.yaml`
- 任务日志:管理后台 `系统设置 -> 系统维护 -> 爬虫任务日志` - 任务日志:管理后台 `系统设置 -> 系统维护 -> 爬虫任务日志`
- 错误日志:管理后台 `系统设置 -> 系统维护 -> 爬虫错误日志` - 错误日志:管理后台 `系统设置 -> 系统维护 -> 爬虫错误日志`
`docker/docker-compose.crawler.yml` 默认使用 `./crawler` 作为构建上下文和 `logs/data` 挂载目录。如果服务器上的 `docker/.env` 已存在,需要确认里面是 `CRAWLER_DIR=./crawler`,或者删除该变量让 Compose 使用默认值。
禁用的定时任务不要放进 Docker 执行清单;如需临时停用某个 Docker 爬虫任务,将 `crawler_tasks.yaml` 对应任务的 `active` 改为 `false`,然后重建或重启 crawler 容器。 禁用的定时任务不要放进 Docker 执行清单;如需临时停用某个 Docker 爬虫任务,将 `crawler_tasks.yaml` 对应任务的 `active` 改为 `false`,然后重建或重启 crawler 容器。
### 当前 Docker 定时任务列表 ### 当前 Docker 定时任务列表
@@ -62,7 +66,7 @@ Docker 只负责运行 Python 爬虫和容器内 cron。MySQL、Redis、Nginx
```bash ```bash
ssh sbnews ssh sbnews
cd /www/wwwroot/test-server.sbnews.net/docker cd /www/wwwroot/api.sbnews.net/docker
``` ```
查看容器状态: 查看容器状态:
@@ -123,7 +127,7 @@ sudo docker exec sport-era-crawler python -c "import scrapling, browserforge; pr
```powershell ```powershell
cd D:\www\sport-era cd D:\www\sport-era
powershell -ExecutionPolicy Bypass -File .\scripts\deploy-server.ps1 -Sudo -RemoteDir /www/wwwroot/test-server.sbnews.net powershell -ExecutionPolicy Bypass -File .\scripts\deploy-server.ps1 -Sudo -RemoteDir /www/wwwroot/api.sbnews.net
``` ```
如果 `sbnews` 配置在 `C:\Users\Administrator\.ssh\config` 中,默认会使用 Windows 的 `ssh.exe` 读取该配置。 如果 `sbnews` 配置在 `C:\Users\Administrator\.ssh\config` 中,默认会使用 Windows 的 `ssh.exe` 读取该配置。
@@ -134,20 +138,29 @@ powershell -ExecutionPolicy Bypass -File .\scripts\deploy-server.ps1 -Sudo -Remo
```powershell ```powershell
cd D:\www\sport-era cd D:\www\sport-era
powershell -ExecutionPolicy Bypass -File .\scripts\deploy-server.ps1 -Sudo -RemoteDir /www/wwwroot/test-server.sbnews.net powershell -ExecutionPolicy Bypass -File .\scripts\deploy-server.ps1 -Sudo -RemoteDir /www/wwwroot/api.sbnews.net
``` ```
全量模式默认只打包以下目录: 全量模式默认以仓库根目录为源,只打包以下四个子目录:
```text ```text
server/app server/
server/config uniapp/
server/extend admin/
server/public/dongqiudi-crawler docker/
server/route
``` ```
默认会排除运行态或较大目录,例如 `.env``vendor``runtime``public/uploads``public/admin``public/mobile`、爬虫 `data/logs/venv`。如确实需要包含,可追加参数 也就是说,远端 `RemoteDir` 下最终会形成
```text
<RemoteDir>/server
<RemoteDir>/uniapp
<RemoteDir>/admin
<RemoteDir>/docker
<RemoteDir>/docker/crawler
```
默认会排除运行态、密钥或较大目录,例如 `server/.env``docker/.env``docker/.env.docker``server/vendor``server/runtime``server/public/uploads``server/public/admin``server/public/mobile`、爬虫 `data/logs/venv`,以及 `uniapp/node_modules``uniapp/dist``admin/node_modules``admin/dist`。如确实需要包含,可追加参数:
```bash ```bash
--include-env --include-env
@@ -164,14 +177,14 @@ server/route
```powershell ```powershell
cd D:\www\sport-era cd D:\www\sport-era
powershell -ExecutionPolicy Bypass -File .\scripts\deploy-server.ps1 -Sudo -From <old_commit> -To <new_commit> -RemoteDir /www/wwwroot/test-server.sbnews.net powershell -ExecutionPolicy Bypass -File .\scripts\deploy-server.ps1 -Sudo -From <old_commit> -To <new_commit> -RemoteDir /www/wwwroot/api.sbnews.net
``` ```
示例: 示例:
```powershell ```powershell
cd D:\www\sport-era cd D:\www\sport-era
powershell -ExecutionPolicy Bypass -File .\scripts\deploy-server.ps1 -Sudo -From abc1234 -To def5678 -RemoteDir /www/wwwroot/test-server.sbnews.net powershell -ExecutionPolicy Bypass -File .\scripts\deploy-server.ps1 -Sudo -From abc1234 -To def5678 -RemoteDir /www/wwwroot/api.sbnews.net
``` ```
### 自动增量发布 ### 自动增量发布
@@ -180,28 +193,28 @@ powershell -ExecutionPolicy Bypass -File .\scripts\deploy-server.ps1 -Sudo -From
```powershell ```powershell
cd D:\www\sport-era cd D:\www\sport-era
powershell -ExecutionPolicy Bypass -File .\scripts\deploy-server.ps1 -Sudo -AutoIncremental -RemoteDir /www/wwwroot/test-server.sbnews.net powershell -ExecutionPolicy Bypass -File .\scripts\deploy-server.ps1 -Sudo -AutoIncremental -RemoteDir /www/wwwroot/api.sbnews.net
``` ```
如果需要一次发布最近 N 个提交的后端改动,可以追加 `-AutoIncrementalCommits <n>`,例如发布最近 3 个提交会对比 `HEAD~3``HEAD` 如果需要一次发布最近 N 个提交的后端改动,可以追加 `-AutoIncrementalCommits <n>`,例如发布最近 3 个提交会对比 `HEAD~3``HEAD`
```powershell ```powershell
cd D:\www\sport-era cd D:\www\sport-era
powershell -ExecutionPolicy Bypass -File .\scripts\deploy-server.ps1 -Sudo -AutoIncremental -AutoIncrementalCommits 3 -RemoteDir /www/wwwroot/test-server.sbnews.net powershell -ExecutionPolicy Bypass -File .\scripts\deploy-server.ps1 -Sudo -AutoIncremental -AutoIncrementalCommits 3 -RemoteDir /www/wwwroot/api.sbnews.net
``` ```
先演练不上传: 先演练不上传:
```powershell ```powershell
cd D:\www\sport-era cd D:\www\sport-era
powershell -ExecutionPolicy Bypass -File .\scripts\deploy-server.ps1 -AutoIncremental -RemoteDir /www/wwwroot/test-server.sbnews.net -DryRun powershell -ExecutionPolicy Bypass -File .\scripts\deploy-server.ps1 -AutoIncremental -RemoteDir /www/wwwroot/api.sbnews.net -DryRun
``` ```
脚本会在打包和上传前先检查 `server` 工作区;如果 `server` 内存在未提交、删除或未跟踪文件,会先自动提交这些变更,再继续计算增量范围。可以通过 `-AutoCommitMessage "提交说明"` 自定义这次自动提交的说明。若存在合并冲突,需要先手动解决。 脚本会在打包和上传前先检查默认打包范围(`server` + `uniapp` + `admin` + `docker`);如果这些目录内存在未提交、删除或未跟踪文件,会先自动提交这些变更,再继续计算增量范围。可以通过 `-AutoCommitMessage "提交说明"` 自定义这次自动提交的说明。若存在合并冲突,需要先手动解决。
注意:自动增量只包含指定提交范围内已经提交到 Git 的差异,不会包含工作区未提交文件。需要指定任意起止提交时,继续使用 `-From <old_commit> -To <new_commit>` 注意:自动增量只包含指定提交范围内已经提交到 Git 的差异,不会包含工作区未提交文件。需要指定任意起止提交时,继续使用 `-From <old_commit> -To <new_commit>`
如果当前根目录 Git 只把 `server` 记录为 gitlink/submodule,且本机没有 `server/.git` 子仓库元数据,脚本无法拿到 `server` 内部的文件级差异;此时会自动降级为打包当前工作区默认的 5 个 server 目录,保证可以继续发布。 如果当前根目录 Git 只把 `server``uniapp``admin` 记录为 gitlink/submodule,脚本无法拿到对应目录内部的文件级差异;此时会跳过该 gitlink 的自动提交,并把该目录从当前工作区按源码目录补进增量包,保证可以继续发布。
### 只演练不上传 ### 只演练不上传
@@ -209,7 +222,7 @@ powershell -ExecutionPolicy Bypass -File .\scripts\deploy-server.ps1 -AutoIncrem
```powershell ```powershell
cd D:\www\sport-era cd D:\www\sport-era
powershell -ExecutionPolicy Bypass -File .\scripts\deploy-server.ps1 -RemoteDir /www/wwwroot/test-server.sbnews.net -DryRun powershell -ExecutionPolicy Bypass -File .\scripts\deploy-server.ps1 -RemoteDir /www/wwwroot/api.sbnews.net -DryRun
``` ```
脚本会在打包后打印 `update log`:增量模式包含 commit 范围、commit 摘要、变更文件和删除文件;全量模式包含当前最新 commit 和默认打包目录。 脚本会在打包后打印 `update log`:增量模式包含 commit 范围、commit 摘要、变更文件和删除文件;全量模式包含当前最新 commit 和默认打包目录。
@@ -222,17 +235,37 @@ powershell -ExecutionPolicy Bypass -File .\scripts\deploy-server.ps1 -RemoteDir
```powershell ```powershell
cd D:\www\sport-era cd D:\www\sport-era
powershell -ExecutionPolicy Bypass -File .\scripts\deploy-server.ps1 -Sudo -RemoteDir /www/wwwroot/test-server.sbnews.net -PostInstall "php think optimize:clear" powershell -ExecutionPolicy Bypass -File .\scripts\deploy-server.ps1 -Sudo -RemoteDir /www/wwwroot/api.sbnews.net -PostInstall "php think optimize:clear"
``` ```
### 发布 uniapp 源码到服务器并在服务器构建
默认发布命令会把 `server/``uniapp/``admin/``docker/` 一起同步到远端根目录;如果需要在服务器端构建 `uniapp`,建议在远端根目录执行构建,再把 H5 产物写回同一套代码下的 `server/public/mobile`
```powershell
cd D:\www\sport-era
powershell -ExecutionPolicy Bypass -File .\scripts\deploy-server.ps1 `
-Sudo `
-RemoteDir /www/wwwroot/api.sbnews.net `
-UniappReleasePath ../server/public/mobile `
-PostInstall "cd uniapp && npm install && npm run build:h5"
```
说明:
- `-RemoteDir` 指向服务器上的项目根目录,解压后里面会同时有 `server/``uniapp/``admin/``docker/`
- `-UniappReleasePath` 会通过环境变量 `UNIAPP_RELEASE_PATH` 传给 `uniapp/scripts/release.mjs`;这里传 `../server/public/mobile`,是因为构建命令会先 `cd uniapp`,再把 H5 产物回写到兄弟目录 `server/public/mobile`
- 服务器需要预先安装 `node >= 18.19.0``npm`,否则 `npm install` / `npm run build:h5` 无法执行。
### 常见问题 ### 常见问题
1. `ssh: Could not resolve hostname sbnews`:检查 Windows 的 `C:\Users\Administrator\.ssh\config` 是否存在 `Host sbnews`,或直接用 `-HostName <服务器IP>` 1. `ssh: Could not resolve hostname sbnews`:检查 Windows 的 `C:\Users\Administrator\.ssh\config` 是否存在 `Host sbnews`,或直接用 `-HostName <服务器IP>`
2. PowerShell 禁止执行脚本:使用示例中的 `-ExecutionPolicy Bypass -File`,或以管理员身份调整当前用户执行策略。 2. PowerShell 禁止执行脚本:使用示例中的 `-ExecutionPolicy Bypass -File`,或以管理员身份调整当前用户执行策略。
3. `tar: Cannot utime``Cannot change mode`:远端目录权限不足,请加 `-Sudo`。脚本会使用 `sudo tar` 覆盖解压,并默认跳过还原 owner/permission,减少权限冲突。 3. `tar: Cannot utime``Cannot change mode`:远端目录权限不足,请加 `-Sudo`。脚本会使用 `sudo tar` 覆盖解压,并默认跳过还原 owner/permission,减少权限冲突。
4. 增量发布提示 commit 无效:确认 commit id 属于当前根目录 Git 可识别的历史。 4. 增量发布提示 commit 无效:确认 commit id 属于当前根目录 Git 可识别的历史。
5. `server is tracked as a root gitlink`:脚本检测到根 Git 只记录了 `server` 指针,无法做文件级增量,会自动改为打包当前工作区默认 5 个 server 目录 5. `root gitlink include paths will be copied from working tree`:脚本检测到默认发布范围里仍有 gitlink/submodule 目录,会把这些目录从当前工作区源码补进增量包
6. 仍需使用 Bash 兼容版时,可继续运行 `bash ./scripts/deploy-server.sh ...` 6. 仍需使用 Bash 兼容版时,可继续运行 `bash ./scripts/deploy-server.sh ...`
7. 服务器运行 `uniapp``node: command not found``npm: command not found`:先在服务器安装 Node.js 18.19+ 与 npm,再执行 `-SourceDir uniapp` 的发布命令。
<a href="https://www.likeshop.cn">![likeshop全开源商城](https://server.likeshop.cn/uploads/gitad/fastbuildAI.png)</a><br> <a href="https://www.likeshop.cn">![likeshop全开源商城](https://server.likeshop.cn/uploads/gitad/fastbuildAI.png)</a><br>
<a href="https://www.likeshop.cn">![likeshop全开源商城](https://server.likeshop.cn/uploads/gitad/likeshop.png)</a><br> <a href="https://www.likeshop.cn">![likeshop全开源商城](https://server.likeshop.cn/uploads/gitad/likeshop.png)</a><br>
-43
View File
@@ -1,43 +0,0 @@
INSERT INTO `la_community_tag` (`name`, `icon`, `sort`, `post_count`, `is_hot`, `status`, `create_time`)
SELECT '世界杯', '', 90, 0, 1, 1, UNIX_TIMESTAMP()
WHERE NOT EXISTS (
SELECT 1 FROM `la_community_tag` WHERE `name` = '世界杯'
);
INSERT INTO `la_community_post` (`user_id`, `content`, `images`, `post_type`, `match_id`, `is_paid`, `price_points`, `free_content_len`, `status`, `create_time`, `update_time`)
SELECT 1, '世界杯开赛氛围越来越浓了,大家觉得本届最大的黑马会是谁?', '[]', 0, 0, 0, 0, 100, 1, UNIX_TIMESTAMP(), UNIX_TIMESTAMP()
WHERE NOT EXISTS (
SELECT 1 FROM `la_community_post` WHERE `content` = '世界杯开赛氛围越来越浓了,大家觉得本届最大的黑马会是谁?'
);
INSERT INTO `la_community_post` (`user_id`, `content`, `images`, `post_type`, `match_id`, `is_paid`, `price_points`, `free_content_len`, `status`, `create_time`, `update_time`)
SELECT 1, '我更看好防守稳一点的球队,世界杯这种大赛还是先稳住再说。', '[]', 0, 0, 0, 0, 100, 1, UNIX_TIMESTAMP(), UNIX_TIMESTAMP()
WHERE NOT EXISTS (
SELECT 1 FROM `la_community_post` WHERE `content` = '我更看好防守稳一点的球队,世界杯这种大赛还是先稳住再说。'
);
INSERT INTO `la_community_post` (`user_id`, `content`, `images`, `post_type`, `match_id`, `is_paid`, `price_points`, `free_content_len`, `status`, `create_time`, `update_time`)
SELECT 1, '这届世界杯的球员状态起伏很大,关键还是看临场调整和替补深度。', '[]', 0, 0, 0, 0, 100, 1, UNIX_TIMESTAMP(), UNIX_TIMESTAMP()
WHERE NOT EXISTS (
SELECT 1 FROM `la_community_post` WHERE `content` = '这届世界杯的球员状态起伏很大,关键还是看临场调整和替补深度。'
);
INSERT INTO `la_community_post_tag` (`post_id`, `tag_id`)
SELECT p.id, t.id
FROM `la_community_post` p
JOIN `la_community_tag` t ON t.`name` = '世界杯'
WHERE p.`content` IN (
'世界杯开赛氛围越来越浓了,大家觉得本届最大的黑马会是谁?',
'我更看好防守稳一点的球队,世界杯这种大赛还是先稳住再说。',
'这届世界杯的球员状态起伏很大,关键还是看临场调整和替补深度。'
)
ON DUPLICATE KEY UPDATE `post_id` = `post_id`;
UPDATE `la_community_tag` t
SET `post_count` = (
SELECT COUNT(*)
FROM `la_community_post_tag` pt
JOIN `la_community_post` p ON p.id = pt.post_id AND p.delete_time IS NULL
WHERE pt.tag_id = t.id
)
WHERE t.`name` = '世界杯';
-29
View File
@@ -1,29 +0,0 @@
INSERT INTO `la_community_post` (`user_id`, `content`, `images`, `post_type`, `match_id`, `is_paid`, `price_points`, `free_content_len`, `status`, `create_time`, `update_time`)
SELECT 1, '世界杯开赛氛围越来越浓了,大家觉得本届最大的黑马会是谁?', '[]', 0, 0, 0, 0, 100, 1, UNIX_TIMESTAMP(), UNIX_TIMESTAMP()
WHERE NOT EXISTS (
SELECT 1 FROM `la_community_post` WHERE `content` = '世界杯开赛氛围越来越浓了,大家觉得本届最大的黑马会是谁?'
);
INSERT INTO `la_community_post` (`user_id`, `content`, `images`, `post_type`, `match_id`, `is_paid`, `price_points`, `free_content_len`, `status`, `create_time`, `update_time`)
SELECT 1, '我更看好防守稳一点的球队,世界杯这种大赛还是先稳住再说。', '[]', 0, 0, 0, 0, 100, 1, UNIX_TIMESTAMP(), UNIX_TIMESTAMP()
WHERE NOT EXISTS (
SELECT 1 FROM `la_community_post` WHERE `content` = '我更看好防守稳一点的球队,世界杯这种大赛还是先稳住再说。'
);
INSERT INTO `la_community_post` (`user_id`, `content`, `images`, `post_type`, `match_id`, `is_paid`, `price_points`, `free_content_len`, `status`, `create_time`, `update_time`)
SELECT 1, '这届世界杯的球员状态起伏很大,关键还是看临场调整和替补深度。', '[]', 0, 0, 0, 0, 100, 1, UNIX_TIMESTAMP(), UNIX_TIMESTAMP()
WHERE NOT EXISTS (
SELECT 1 FROM `la_community_post` WHERE `content` = '这届世界杯的球员状态起伏很大,关键还是看临场调整和替补深度。'
);
INSERT INTO `la_community_post_tag` (`post_id`, `tag_id`)
SELECT p.id, 17
FROM `la_community_post` p
WHERE p.`content` IN (
'世界杯开赛氛围越来越浓了,大家觉得本届最大的黑马会是谁?',
'我更看好防守稳一点的球队,世界杯这种大赛还是先稳住再说。',
'这届世界杯的球员状态起伏很大,关键还是看临场调整和替补深度。'
)
ON DUPLICATE KEY UPDATE `post_id` = `post_id`;
UPDATE `la_community_tag` SET `post_count` = (SELECT COUNT(*) FROM `la_community_post_tag` WHERE tag_id = 17) WHERE id = 17;
Submodule admin deleted from 44251a602e
+4
View File
@@ -0,0 +1,4 @@
NODE_ENV = 'development'
# Base API
VITE_APP_BASE_URL=''
+3
View File
@@ -0,0 +1,3 @@
NODE_ENV = 'production'
# Base API
VITE_APP_BASE_URL=''
+4
View File
@@ -0,0 +1,4 @@
.vscode
.idea
dist/
node_modules/
+44
View File
@@ -0,0 +1,44 @@
/* eslint-env node */
require('@rushstack/eslint-patch/modern-module-resolution')
module.exports = {
root: true,
ignorePatterns: ['/auto-imports.d.ts', '/components.d.ts'],
extends: [
'plugin:vue/vue3-essential',
'eslint:recommended',
'@vue/eslint-config-typescript/recommended',
'@vue/eslint-config-prettier',
'./.eslintrc-auto-import.json'
],
plugins: ['simple-import-sort'],
rules: {
'simple-import-sort/imports': 'error', // 强制导入语句排序
'prettier/prettier': [
'warn',
{
semi: false,
singleQuote: true,
printWidth: 100,
proseWrap: 'preserve',
bracketSameLine: false,
endOfLine: 'lf',
tabWidth: 4,
useTabs: false,
trailingComma: 'none'
}
],
'vue/multi-word-component-names': 'off',
'@typescript-eslint/no-explicit-any': 'off',
'@typescript-eslint/ban-ts-comment': 'off',
'no-undef': 'off',
'vue/prefer-import-from-vue': 'off',
'no-prototype-builtins': 'off',
'prefer-spread': 'off',
'@typescript-eslint/no-non-null-assertion': 'off',
'@typescript-eslint/no-non-null-asserted-optional-chain': 'off'
},
globals: {
module: 'readonly'
}
}
+13
View File
@@ -0,0 +1,13 @@
### 该问题是怎么引起的?
### 重现步骤
### 报错信息
@@ -0,0 +1,12 @@
### 相关的Issue
### 原因(目的、解决的问题等)
### 描述(做了什么,变更了什么)
### 测试用例(新增、改动、可能影响的功能)
+36
View File
@@ -0,0 +1,36 @@
# Logs
logs
*.log
npm-debug.log*
yarn-debug.log*
yarn-error.log*
pnpm-debug.log*
lerna-debug.log*
node_modules
.DS_Store
dist
dist-ssr
coverage
*.local
# unplugin-auto-import
auto-imports.d.ts
components.d.ts
.eslintrc-auto-import.json
/cypress/videos/
/cypress/screenshots/
# Editor directories and files
.idea
.vscode
*.suo
*.ntvs*
*.njsproj
*.sln
*.sw?
# .env
.env.development
.env.production
+4
View File
@@ -0,0 +1,4 @@
.vscode
.idea
dist/
node_modules/
+11
View File
@@ -0,0 +1,11 @@
{
"semi": false,
"singleQuote": true,
"printWidth": 100,
"proseWrap": "preserve",
"bracketSameLine": false,
"endOfLine": "lf",
"tabWidth": 4,
"useTabs": false,
"trailingComma": "none"
}
+95
View File
@@ -0,0 +1,95 @@
# Admin Agent — Sport Era 管理后台
Vue 3 + Vite + Element Plus 管理后台 SPA。**消费 `server/app/adminapi/controller/` 的接口。**
## 技术栈
- **Vue** 3 + **TypeScript**
- **Vite**
- **Element Plus**
- **Pinia** 状态管理
- **Vue Router** 路由
- **Axios** HTTP 请求
## 项目结构
```text
src/
├── main.ts # 应用入口
├── App.vue # 根组件
├── permission.ts # 路由权限守卫
├── api/ # 接口请求模块(→ 后端 /adminapi/*
├── views/ # 页面组件
├── layout/ # 布局组件
├── components/ # 公共组件
├── stores/ # Pinia Store
├── router/ # 路由配置
├── hooks/ # 组合式函数
├── utils/ # 工具函数
├── enums/ # 枚举常量
├── config/ # 应用配置
├── styles/ # 全局样式
└── assets/ # 静态资源
```
## 运行命令
```bash
npm install
npm run dev
npm run build
```
---
## 并行协作协议
### 新功能开发时
#### Step 1: 等待或查阅后端 API 契约
查看 `server/app/adminapi/controller/` 下对应 controller,并结合 validate、logic、model 获取:
- 接口路径和方法
- 请求参数类型和必填项
- 响应数据结构
- 字段、状态、字典或配置来源
#### Step 2: 并行实现
```text
1. src/api/ 下新增或复用接口请求模块
2. src/views/ 下新增页面组件
3. 按现有路由/菜单机制配置页面入口
4. 如需菜单,配合后端菜单和权限节点
```
#### Step 3: 构建联调
```bash
npm run build
```
## 从后端 Agent 获取信息的方式
| 需要了解 | 查看位置 |
| ------------------ | ------------------------------------------------- |
| 接口路径/参数/响应 | `server/app/adminapi/controller/` 对应 controller |
| 参数校验 | `server/app/adminapi/validate/` 对应 validate |
| 业务字段 | `server/app/common/model/` 对应 model |
| 枚举/字典 | `server/app/common/enum/`、字典表、配置表 |
| Token 机制 | `server/app/common/cache/AdminTokenCache.php` |
## 代码约定
- API 请求统一通过 `src/api/` 模块,沿用现有请求封装。
- 列表页复用现有搜索表单、表格、分页和批量操作风格。
- 表单页复用 `el-form``el-dialog`、上传组件等现有封装。
- 状态管理用 PiniaStore 放在 `src/stores/`
- 新增视图先参考同业务目录的已有页面风格。
- **禁止前端硬编码业务枚举**:优先从字典接口、配置接口或后端返回字段读取。
- 顶级菜单需配 icon,二级及以下菜单 icon 留空。
## 近期踩坑
- 后台表单新增字段时,不能只改页面输入项;要同时核对后端接口字段白名单、数据库列和保存逻辑,否则会出现“能填但存不进去”的假象。
+36
View File
@@ -0,0 +1,36 @@
# sport-era-admin
#### Description
{**When you're done, you can delete the content in this README and update the file with details for others getting started with your repository**}
#### Software Architecture
Software architecture description
#### Installation
1. xxxx
2. xxxx
3. xxxx
#### Instructions
1. xxxx
2. xxxx
3. xxxx
#### Contribution
1. Fork the repository
2. Create Feat_xxx branch
3. Commit your code
4. Create Pull Request
#### Gitee Feature
1. You can use Readme\_XXX.md to support different languages, such as Readme\_en.md, Readme\_zh.md
2. Gitee blog [blog.gitee.com](https://blog.gitee.com)
3. Explore open source project [https://gitee.com/explore](https://gitee.com/explore)
4. The most valuable open source project [GVP](https://gitee.com/gvp)
5. The manual of Gitee [https://gitee.com/help](https://gitee.com/help)
6. The most popular members [https://gitee.com/gitee-stars/](https://gitee.com/gitee-stars/)
+39
View File
@@ -0,0 +1,39 @@
# sport-era-admin
#### 介绍
{**以下是 Gitee 平台说明,您可以替换此简介**
Gitee 是 OSCHINA 推出的基于 Git 的代码托管平台(同时支持 SVN)。专为开发者提供稳定、高效、安全的云端软件开发协作平台
无论是个人、团队、或是企业,都能够用 Gitee 实现代码托管、项目管理、协作开发。企业项目请看 [https://gitee.com/enterprises](https://gitee.com/enterprises)}
#### 软件架构
软件架构说明
#### 安装教程
1. xxxx
2. xxxx
3. xxxx
#### 使用说明
1. xxxx
2. xxxx
3. xxxx
#### 参与贡献
1. Fork 本仓库
2. 新建 Feat_xxx 分支
3. 提交代码
4. 新建 Pull Request
#### 特技
1. 使用 Readme\_XXX.md 来支持不同的语言,例如 Readme\_en.md, Readme\_zh.md
2. Gitee 官方博客 [blog.gitee.com](https://blog.gitee.com)
3. 你可以 [https://gitee.com/explore](https://gitee.com/explore) 这个地址来了解 Gitee 上的优秀开源项目
4. [GVP](https://gitee.com/gvp) 全称是 Gitee 最有价值开源项目,是综合评定出的优秀开源项目
5. Gitee 官方提供的使用手册 [https://gitee.com/help](https://gitee.com/help)
6. Gitee 封面人物是一档用来展示 Gitee 会员风采的栏目 [https://gitee.com/gitee-stars/](https://gitee.com/gitee-stars/)
+1
View File
@@ -0,0 +1 @@
/// <reference types="vite/client" />
+65
View File
@@ -0,0 +1,65 @@
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8" />
<link rel="icon" href="/favicon.ico" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>后台管理系统</title>
<style>
* {
margin: 0;
padding: 0;
}
.preload {
display: flex;
align-items: center;
justify-content: center;
height: 100vh;
width: 100vw;
}
.circular {
height: 42px;
width: 42px;
animation: loading-rotate 2s linear infinite;
}
.circular .path {
animation: loading-dash 1.5s ease-in-out infinite;
stroke-dasharray: 90, 150;
stroke-dashoffset: 0;
stroke-width: 2;
stroke: #4073fa;
stroke-linecap: round;
}
@keyframes loading-rotate {
100% {
transform: rotate(1turn);
}
}
@keyframes loading-dash {
0% {
stroke-dasharray: 90, 150;
stroke-dashoffset: -40px;
}
100% {
stroke-dasharray: 90, 150;
stroke-dashoffset: -120px;
}
}
</style>
</head>
<body>
<div id="app">
<div class="preload">
<svg viewBox="25 25 50 50" class="circular">
<circle cx="50" cy="50" r="20" fill="none" class="path"></circle>
</svg>
</div>
</div>
<script type="module" src="/src/main.ts"></script>
</body>
</html>
+12902
View File
File diff suppressed because it is too large Load Diff
+66
View File
@@ -0,0 +1,66 @@
{
"name": "vue-project",
"version": "0.0.0",
"license": "MIT",
"scripts": {
"dev": "vite",
"preview": "vite preview --port 4173",
"build": "vite build && node scripts/release.mjs",
"type-check": "vue-tsc --noEmit",
"lint": "eslint . --ext .vue,.js,.jsx,.cjs,.mjs,.ts,.tsx,.cts,.mts --fix --ignore-path .gitignore"
},
"dependencies": {
"@element-plus/icons-vue": "^2.3.1",
"@highlightjs/vue-plugin": "^2.1.0",
"@vue/shared": "^3.5.13",
"@vueuse/core": "^12.7.0",
"@wangeditor/editor": "^5.1.23",
"@wangeditor/editor-for-vue": "^5.1.12",
"axios": "^1.7.9",
"css-color-function": "^1.3.3",
"echarts": "^5.6.0",
"element-plus": "^2.9.4",
"highlight.js": "^11.11.1",
"lodash": "^4.17.21",
"lodash-es": "^4.17.21",
"nprogress": "^0.2.0",
"pinia": "^2.3.1",
"vue": "^3.5.13",
"vue-clipboard3": "^2.0.0",
"vue-echarts": "^6.7.3",
"vue-router": "^4.5.0",
"vuedraggable": "^4.1.0"
},
"devDependencies": {
"@rushstack/eslint-patch": "^1.10.5",
"@types/lodash-es": "^4.17.12",
"@types/node": "^22.13.4",
"@types/nprogress": "^0.2.3",
"@vitejs/plugin-legacy": "^6.0.1",
"@vitejs/plugin-vue": "^5.2.1",
"@vitejs/plugin-vue-jsx": "^4.1.1",
"@vue/eslint-config-prettier": "^10.2.0",
"@vue/eslint-config-typescript": "^14.4.0",
"@vue/tsconfig": "^0.7.0",
"autoprefixer": "^10.4.20",
"consola": "^3.4.0",
"eslint": "^9.10.0",
"eslint-plugin-simple-import-sort": "^12.1.1",
"eslint-plugin-vue": "^9.32.0",
"execa": "^9.5.2",
"fs-extra": "^11.3.0",
"postcss": "^8.5.3",
"prettier": "^3.5.1",
"sass": "1.79.6",
"tailwindcss": "^3.4.17",
"terser": "^5.39.0",
"typescript": "^5.7.3",
"unplugin-auto-import": "^19.1.0",
"unplugin-vue-components": "^28.4.0",
"vite": "^6.1.1",
"vite-plugin-style-import": "^2.0.0",
"vite-plugin-svg-icons": "^2.0.1",
"vite-plugin-vue-setup-extend": "^0.4.0",
"vue-tsc": "^2.2.2"
}
}
+6
View File
@@ -0,0 +1,6 @@
module.exports = {
plugins: {
tailwindcss: {},
autoprefixer: {}
}
}
+36
View File
@@ -0,0 +1,36 @@
import fsExtra from 'fs-extra'
import path from 'path'
const { existsSync, remove, copy } = fsExtra
const cwd = process.cwd()
//打包发布路径,谨慎改动
const releaseRelativePath = '../server/public/admin'
const distPath = path.resolve(cwd, 'dist')
const releasePath = path.resolve(cwd, releaseRelativePath)
async function build() {
if (existsSync(releasePath)) {
await remove(releasePath)
}
console.log(`文件正在复制 ==> ${releaseRelativePath}`)
try {
await copyFile(distPath, releasePath)
} catch (error) {
console.log(`\n ${error}`)
}
console.log(`文件已复制 ==> ${releaseRelativePath}`)
}
function copyFile(sourceDir, targetDir) {
return new Promise((resolve, reject) => {
copy(sourceDir, targetDir, (err) => {
if (err) {
reject(err)
} else {
resolve()
}
})
})
}
build()
+48
View File
@@ -0,0 +1,48 @@
<script setup lang="ts">
import { useDark, useThrottleFn, useWindowSize } from '@vueuse/core'
import zhCn from 'element-plus/es/locale/lang/zh-cn'
import { ScreenEnum } from './enums/appEnums'
import useAppStore from './stores/modules/app'
import useSettingStore from './stores/modules/setting'
const appStore = useAppStore()
const settingStore = useSettingStore()
const elConfig = {
zIndex: 3000,
locale: zhCn
}
const isDark = useDark()
onMounted(async () => {
//设置主题色
settingStore.setTheme(isDark.value)
})
const { width } = useWindowSize()
watch(
width,
useThrottleFn((value) => {
if (value > ScreenEnum.SM) {
appStore.setMobile(false)
appStore.toggleCollapsed(false)
} else {
appStore.setMobile(true)
appStore.toggleCollapsed(true)
}
if (value < ScreenEnum.MD) {
appStore.toggleCollapsed(true)
}
}),
{
immediate: true
}
)
</script>
<template>
<el-config-provider :locale="elConfig.locale" :z-index="elConfig.zIndex">
<router-view />
</el-config-provider>
</template>
<style></style>
+51
View File
@@ -0,0 +1,51 @@
import request from '@/utils/request'
// ========== AI配置 ==========
export function aiConfigLists(params?: any) {
return request.get({ url: '/ai.aiConfig/lists', params })
}
export function aiConfigDetail(params: any) {
return request.get({ url: '/ai.aiConfig/detail', params })
}
export function aiConfigEdit(params: any) {
return request.post({ url: '/ai.aiConfig/edit', params })
}
// ========== AI分析记录 ==========
export function aiAnalysisLists(params?: any) {
return request.get({ url: '/ai.aiAnalysis/lists', params })
}
// ========== AI日志 ==========
export function aiLogLists(params?: any) {
return request.get({ url: '/ai.aiLog/lists', params })
}
// ========== 知识库配置 ==========
export function kbConfigLists(params?: any) {
return request.get({ url: '/ai.kbConfig/lists', params })
}
export function kbConfigDetail(params: any) {
return request.get({ url: '/ai.kbConfig/detail', params })
}
export function kbConfigEdit(params: any) {
return request.post({ url: '/ai.kbConfig/edit', params })
}
// ========== 知识文档 ==========
export function kbDocumentLists(params?: any) {
return request.get({ url: '/ai.kbDocument/lists', params })
}
// ========== 同步任务 ==========
export function kbSyncJobLists(params?: any) {
return request.get({ url: '/ai.kbSyncJob/lists', params })
}
export function kbSyncJobRebuild(params: any) {
return request.post({ url: '/ai.kbSyncJob/rebuild', params })
}
// ========== 查询日志 ==========
export function kbQueryLogLists(params?: any) {
return request.get({ url: '/ai.kbQueryLog/lists', params })
}
+16
View File
@@ -0,0 +1,16 @@
import request from '@/utils/request'
// 配置
export function getConfig() {
return request.get({ url: '/config/getConfig' })
}
// 工作台主页
export function getWorkbench() {
return request.get({ url: '/workbench/index' })
}
//字典数据
export function getDictData(params: any) {
return request.get({ url: '/config/dict', params })
}
+10
View File
@@ -0,0 +1,10 @@
import request from '@/utils/request'
export function getRechargeConfig() {
return request.get({ url: '/recharge.recharge/getConfig' })
}
// 设置
export function setRechargeConfig(params: any) {
return request.post({ url: '/recharge.recharge/setConfig', params })
}
+31
View File
@@ -0,0 +1,31 @@
import request from '@/utils/request'
// 版本列表
export function appVersionLists(params?: any) {
return request.get({ url: '/app.appVersion/lists', params })
}
// 添加版本
export function appVersionAdd(params: any) {
return request.post({ url: '/app.appVersion/add', params })
}
// 编辑版本
export function appVersionEdit(params: any) {
return request.post({ url: '/app.appVersion/edit', params })
}
// 删除版本
export function appVersionDelete(params: any) {
return request.post({ url: '/app.appVersion/delete', params })
}
// 版本详情
export function appVersionDetail(params: any) {
return request.get({ url: '/app.appVersion/detail', params })
}
// 修改状态
export function appVersionStatus(params: any) {
return request.post({ url: '/app.appVersion/updateStatus', params })
}
+89
View File
@@ -0,0 +1,89 @@
import request from '@/utils/request'
// 文章分类列表
export function articleCateLists(params?: any) {
return request.get({ url: '/article.articleCate/lists', params })
}
// 文章分类列表
export function articleCateAll(params?: any) {
return request.get({ url: '/article.articleCate/all', params })
}
// 添加文章分类
export function articleCateAdd(params: any) {
return request.post({ url: '/article.articleCate/add', params })
}
// 编辑文章分类
export function articleCateEdit(params: any) {
return request.post({ url: '/article.articleCate/edit', params })
}
// 删除文章分类
export function articleCateDelete(params: any) {
return request.post({ url: '/article.articleCate/delete', params })
}
// 文章分类详情
export function articleCateDetail(params: any) {
return request.get({ url: '/article.articleCate/detail', params })
}
// 文章分类状态
export function articleCateStatus(params: any) {
return request.post({ url: '/article.articleCate/updateStatus', params })
}
// 文章列表
export function articleLists(params?: any) {
return request.get({ url: '/article.article/lists', params })
}
// 文章列表
export function articleAll(params?: any) {
return request.get({ url: '/article/all', params })
}
// 添加文章
export function articleAdd(params: any) {
return request.post({ url: '/article.article/add', params })
}
// 编辑文章
export function articleEdit(params: any) {
return request.post({ url: '/article.article/edit', params })
}
// 删除文章
export function articleDelete(params: any) {
return request.post({ url: '/article.article/delete', params })
}
// 文章详情
export function articleDetail(params: any) {
return request.get({ url: '/article.article/detail', params })
}
// 文章分类状态
export function articleStatus(params: any) {
return request.post({ url: '/article.article/updateStatus', params })
}
// 批量设置推荐
export function articleBatchRecommend(params: any) {
return request.post({ url: '/article.article/batchRecommend', params })
}
// AI评论任务列表
export function articleAiCommentTaskLists(params?: any) {
return request.get({ url: '/article.article_ai_comment_task/lists', params })
}
// 删除AI评论任务
export function articleAiCommentTaskDelete(params: { id: number }) {
return request.post({ url: '/article.article_ai_comment_task/delete', params })
}
// 重试AI评论任务
export function articleAiCommentTaskRetry(params: { id: number }) {
return request.post({ url: '/article.article_ai_comment_task/retry', params })
}
+11
View File
@@ -0,0 +1,11 @@
import request from '@/utils/request'
// H5渠道配置保存
export function setH5Config(params: any) {
return request.post({ url: '/channel.web_page_setting/setConfig', params })
}
// H5渠道配置详情
export function getH5Config() {
return request.get({ url: '/channel.web_page_setting/getConfig' })
}
+11
View File
@@ -0,0 +1,11 @@
import request from '@/utils/request'
// 微信开发平台配置保存
export function setOpenSettingConfig(params: any) {
return request.post({ url: '/channel.open_setting/setConfig', params })
}
// 微信开发平台配置详情
export function getOpenSettingConfig() {
return request.get({ url: '/channel.open_setting/getConfig' })
}
+11
View File
@@ -0,0 +1,11 @@
import request from '@/utils/request'
// 微信小程序配置保存
export function setWeappConfig(params: any) {
return request.post({ url: '/channel.mnp_settings/setConfig', params })
}
// 微信小程序配置详情
export function getWeappConfig() {
return request.get({ url: '/channel.mnp_settings/getConfig' })
}
+110
View File
@@ -0,0 +1,110 @@
import request from '@/utils/request'
// 微信公众号配置保存
export function setOaConfig(params: any) {
return request.post({ url: '/channel.official_account_setting/setConfig', params })
}
// 微信公众号配置详情
export function getOaConfig() {
return request.get({ url: '/channel.official_account_setting/getConfig' })
}
export interface Menu {
name: string
has_menu?: boolean
type?: string
url?: string
appid?: string
pagepath?: string
sub_button: Menu[] | any
}
/**
* @return { Promise }
* @description 获取菜单
*/
export function getOaMenu() {
return request.get({ url: '/channel.official_account_menu/detail' })
}
/**
* @return { Promise }
* @param { Menu } Menu
* @description 菜单保存
*/
export function setOaMenuSave(params: Menu | any) {
return request.post({ url: '/channel.official_account_menu/save', params })
}
/**
* @return { Promise }
* @param { Menu } Menu
* @description 菜单发布
*/
export function setOaMenuPublish(params: Menu | any) {
return request.post({ url: '/channel.official_account_menu/saveAndPublish', params })
}
/**
* @return { Promise }
* @param { string } reply_type
* @description 获取回复列表
*/
export function getOaReplyList(params: { reply_type: string }) {
return request.get({ url: '/channel.official_account_reply/lists', params })
}
/**
* @return { Promise }
* @param { number } id
* @description 回复列表删除
*/
export function oaReplyDel(params: { id: number }) {
return request.post({ url: '/channel.official_account_reply/delete', params })
}
/**
* @return { Promise }
* @param { number } id
* @description 回复状态修改
*/
export function changeOaReplyStatus(params: { id: number }) {
return request.post({ url: '/channel.official_account_reply/status', params })
}
export interface Reply {
content: string // 内容
content_type: number // 内容类型: 1=文本
keyword?: string // 关键词
matching_type?: number // 匹配方式: [1=全匹配, 2=模糊匹配]
name: string // 规则名称
status: number // 状态: 1=开启, 0=关闭
reply_type: number // 类型: 回复类型 1-关注回复 2-关键词回复 3-默认回复
reply_num: number // 回复数量`
sort: number // 排序
}
/**
* @return { Promise }
* @description 回复添加
*/
export function oaReplyAdd(params: Reply) {
return request.post({ url: '/channel.official_account_reply/add', params })
}
/**
* @return { Promise }
* @description 回复编辑
*/
export function oaReplyEdit(params: Reply) {
return request.post({ url: '/channel.official_account_reply/edit', params })
}
/**
* @return { Promise }
* @param { string } type
* @description 获取回复详情
*/
export function getOaReplyDetail(params: { id: number }) {
return request.get({ url: '/channel.official_account_reply/detail', params })
}
+81
View File
@@ -0,0 +1,81 @@
import request from '@/utils/request'
// 帖子列表
export function communityPostLists(params?: any) {
return request.get({ url: '/community.communityPost/lists', params })
}
// 帖子详情
export function communityPostDetail(params: any) {
return request.get({ url: '/community.communityPost/detail', params })
}
// 帖子审核状态
export function communityPostStatus(params: any) {
return request.post({ url: '/community.communityPost/updateStatus', params })
}
// 帖子置顶
export function communityPostSetTop(params: any) {
return request.post({ url: '/community.communityPost/setTop', params })
}
// 帖子设热门
export function communityPostSetHot(params: any) {
return request.post({ url: '/community.communityPost/setHot', params })
}
// 删除帖子
export function communityPostDelete(params: any) {
return request.post({ url: '/community.communityPost/delete', params })
}
// 标签列表
export function communityTagLists(params?: any) {
return request.get({ url: '/community.communityTag/lists', params })
}
// 全部标签
export function communityTagAll(params?: any) {
return request.get({ url: '/community.communityTag/all', params })
}
// 添加标签
export function communityTagAdd(params: any) {
return request.post({ url: '/community.communityTag/add', params })
}
// 编辑标签
export function communityTagEdit(params: any) {
return request.post({ url: '/community.communityTag/edit', params })
}
// 删除标签
export function communityTagDelete(params: any) {
return request.post({ url: '/community.communityTag/delete', params })
}
// 标签详情
export function communityTagDetail(params: any) {
return request.get({ url: '/community.communityTag/detail', params })
}
// 评论列表
export function communityCommentLists(params?: any) {
return request.get({ url: '/community.communityComment/lists', params })
}
// 评论账号列表
export function communityCommentAccountLists(params?: any) {
return request.get({ url: '/community.commentAccount/lists', params })
}
// 评论审核状态
export function communityCommentStatus(params: any) {
return request.post({ url: '/community.communityComment/updateStatus', params })
}
// 删除评论
export function communityCommentDelete(params: any) {
return request.post({ url: '/community.communityComment/delete', params })
}
+26
View File
@@ -0,0 +1,26 @@
import request from '@/utils/request'
// 用户列表
export function getUserList(params: any) {
return request.get({ url: '/user.user/lists', params }, { ignoreCancelToken: true })
}
// 用户详情
export function getUserDetail(params: any) {
return request.get({ url: '/user.user/detail', params })
}
// 用户编辑
export function userEdit(params: any) {
return request.post({ url: '/user.user/edit', params })
}
// 用户编辑
export function adjustMoney(params: any) {
return request.post({ url: '/user.user/adjustMoney', params })
}
// 调整用户账户(余额/积分)
export function adjustAccount(params: any) {
return request.post({ url: '/user.user/adjustAccount', params })
}
+26
View File
@@ -0,0 +1,26 @@
import request from '@/utils/request'
// 爬虫错误日志列表
export function crawlErrorLogLists(params?: any) {
return request.get({ url: '/crawler.crawlErrorLog/lists', params })
}
// 爬虫错误日志详情
export function crawlErrorLogDetail(params: any) {
return request.get({ url: '/crawler.crawlErrorLog/detail', params })
}
// 删除爬虫错误日志
export function crawlErrorLogDelete(params: any) {
return request.post({ url: '/crawler.crawlErrorLog/delete', params })
}
// Docker 爬虫任务日志列表
export function crawlerTaskLogLists(params?: any) {
return request.get({ url: '/crawler.taskLog/lists', params })
}
// Docker 爬虫任务日志详情
export function crawlerTaskLogDetail(params: any) {
return request.get({ url: '/crawler.taskLog/detail', params })
}
+31
View File
@@ -0,0 +1,31 @@
import request from '@/utils/request'
// 页面装修详情
export function getDecoratePages(params: any) {
return request.get({ url: '/decorate.page/detail', params }, { ignoreCancelToken: true })
}
// 页面装修保存
export function setDecoratePages(params: any) {
return request.post({ url: '/decorate.page/save', params })
}
// 获取首页文章数据
export function getDecorateArticle(params?: any) {
return request.get({ url: '/decorate.data/article', params })
}
// 底部导航详情
export function getDecorateTabbar(params?: any) {
return request.get({ url: '/decorate.tabbar/detail', params })
}
// 底部导航保存
export function setDecorateTabbar(params: any) {
return request.post({ url: '/decorate.tabbar/save', params })
}
// pc装修数据
export function getDecoratePc() {
return request.get({ url: '/decorate.data/pc' })
}
+42
View File
@@ -0,0 +1,42 @@
import request from '@/utils/request'
export function fileCateAdd(params: Record<string, any>) {
return request.post({ url: '/file/addCate', params })
}
export function fileCateEdit(params: Record<string, any>) {
return request.post({ url: '/file/editCate', params })
}
// 文件分类删除
export function fileCateDelete(params: Record<string, any>) {
return request.post({ url: '/file/delCate', params })
}
// 文件分类列表
export function fileCateLists(params: Record<string, any>) {
return request.get({ url: '/file/listCate', params })
}
// 文件列表
export function fileList(params: Record<string, any>) {
return request.get(
{ url: '/file/lists', params },
{ ignoreCancelToken: true, isOpenRetry: false }
)
}
// 文件删除
export function fileDelete(params: Record<string, any>) {
return request.post({ url: '/file/delete', params })
}
// 文件移动
export function fileMove(params: Record<string, any>) {
return request.post({ url: '/file/move', params })
}
// 文件重命名
export function fileRename(params: { id: number; name: string }) {
return request.post({ url: '/file/rename', params })
}
+46
View File
@@ -0,0 +1,46 @@
import request from '@/utils/request'
// 余额明细
export function accountLog(params?: any) {
return request.get({ url: '/finance.account_log/lists', params })
}
// 充值记录
export function rechargeLists(params?: any) {
return request.get({ url: '/recharge.recharge/lists', params }, { ignoreCancelToken: true })
}
// 余额变动类型
export function getUmChangeType(params?: any) {
return request.get({ url: '/finance.account_log/getUmChangeType', params })
}
//退款
export function refund(params?: any) {
return request.post({ url: '/recharge.recharge/refund', params })
}
//重新退款
export function refundAgain(params?: any) {
return request.post({ url: '/recharge.recharge/refundAgain', params })
}
//退款记录
export function refundRecord(params?: any) {
return request.get({ url: '/finance.refund/record', params })
}
//退款日志
export function refundLog(params?: any) {
return request.get({ url: '/finance.refund/log', params })
}
//退款统计
export function refundStat(params?: any) {
return request.get({ url: '/finance.refund/stat', params })
}
// 付费解锁记录
export function postPurchaseLists(params?: any) {
return request.get({ url: '/finance.postPurchase/lists', params })
}
+46
View File
@@ -0,0 +1,46 @@
import request from '@/utils/request'
// ========== 彩票地区 ==========
export function lotteryRegionLists(params?: any) {
return request.get({ url: '/lottery.lotteryRegion/lists', params })
}
export function lotteryRegionDetail(params: any) {
return request.get({ url: '/lottery.lotteryRegion/detail', params })
}
export function lotteryRegionAdd(params: any) {
return request.post({ url: '/lottery.lotteryRegion/add', params })
}
export function lotteryRegionEdit(params: any) {
return request.post({ url: '/lottery.lotteryRegion/edit', params })
}
export function lotteryRegionDelete(params: any) {
return request.post({ url: '/lottery.lotteryRegion/delete', params })
}
// ========== 彩种分类 ==========
export function lotteryCategoryLists(params?: any) {
return request.get({ url: '/lottery.lotteryCategory/lists', params })
}
export function lotteryCategoryDetail(params: any) {
return request.get({ url: '/lottery.lotteryCategory/detail', params })
}
export function lotteryCategoryAdd(params: any) {
return request.post({ url: '/lottery.lotteryCategory/add', params })
}
export function lotteryCategoryEdit(params: any) {
return request.post({ url: '/lottery.lotteryCategory/edit', params })
}
export function lotteryCategoryDelete(params: any) {
return request.post({ url: '/lottery.lotteryCategory/delete', params })
}
// ========== 开奖数据 ==========
export function lotteryDrawLists(params?: any) {
return request.get({ url: '/lottery.lotteryDraw/lists', params })
}
export function lotteryDrawDetail(params: any) {
return request.get({ url: '/lottery.lotteryDraw/detail', params })
}
export function lotteryDrawDelete(params: any) {
return request.post({ url: '/lottery.lotteryDraw/delete', params })
}
+71
View File
@@ -0,0 +1,71 @@
import request from '@/utils/request'
// 赛事列表
export function matchLists(params?: any) {
return request.get({ url: '/match.match/lists', params })
}
// 赛事详情
export function matchDetail(params: any) {
return request.get({ url: '/match.match/detail', params })
}
// 编辑赛事
export function matchEdit(params: any) {
return request.post({ url: '/match.match/edit', params })
}
// 删除赛事
export function matchDelete(params: any) {
return request.post({ url: '/match.match/delete', params })
}
// 赛事直播线路列表
export function matchLiveLists(params?: any) {
return request.get({ url: '/match.matchLive/lists', params })
}
// 赛事直播线路详情
export function matchLiveDetail(params: any) {
return request.get({ url: '/match.matchLive/detail', params })
}
// 新增赛事直播线路
export function matchLiveAdd(params: any) {
return request.post({ url: '/match.matchLive/add', params })
}
// 编辑赛事直播线路
export function matchLiveEdit(params: any) {
return request.post({ url: '/match.matchLive/edit', params })
}
// 删除赛事直播线路
export function matchLiveDelete(params: any) {
return request.post({ url: '/match.matchLive/delete', params })
}
// 赛事赔率列表
export function matchOddsLists(params?: any) {
return request.get({ url: '/match.matchOdds/lists', params })
}
// 联赛列表
export function leagueLists(params?: any) {
return request.get({ url: '/match.league/lists', params })
}
// 联赛详情
export function leagueDetail(params: any) {
return request.get({ url: '/match.league/detail', params })
}
// 编辑联赛
export function leagueEdit(params: any) {
return request.post({ url: '/match.league/edit', params })
}
// 删除联赛
export function leagueDelete(params: any) {
return request.post({ url: '/match.league/delete', params })
}
+31
View File
@@ -0,0 +1,31 @@
import request from '@/utils/request'
// 通知设置列表
export function noticeLists(params: any) {
return request.get({ url: '/notice.notice/settingLists', params })
}
// 通知设置详情
export function noticeDetail(params: any) {
return request.get({ url: '/notice.notice/detail', params })
}
// 通知设置保存
export function setNoticeConfig(params: any) {
return request.post({ url: '/notice.notice/set', params })
}
// 短信设置列表
export function smsLists() {
return request.get({ url: '/notice.sms_config/getConfig' })
}
// 短信设置详情
export function smsDetail(params: any) {
return request.get({ url: '/notice.sms_config/detail', params })
}
// 短信设置保存
export function setSmsConfig(params: any) {
return request.post({ url: '/notice.sms_config/setConfig', params })
}
+31
View File
@@ -0,0 +1,31 @@
import request from '@/utils/request'
// 部门列表
export function deptLists(params?: any) {
return request.get({ url: '/dept.dept/lists', params })
}
// 添加部门
export function deptAdd(params: any) {
return request.post({ url: '/dept.dept/add', params })
}
// 编辑部门
export function deptEdit(params: any) {
return request.post({ url: '/dept.dept/edit', params })
}
// 删除部门
export function deptDelete(params: any) {
return request.post({ url: '/dept.dept/delete', params })
}
// 部门详情
export function deptDetail(params: any) {
return request.get({ url: '/dept.dept/detail', params })
}
// 部门列表全部
export function deptAll() {
return request.get({ url: '/dept.dept/all' })
}
+31
View File
@@ -0,0 +1,31 @@
import request from '@/utils/request'
// 岗位列表
export function jobsLists(params: any) {
return request.get({ url: '/dept.jobs/lists', params }, { ignoreCancelToken: true })
}
// 岗位列表全部
export function jobsAll(params: any) {
return request.get({ url: '/dept.jobs/all', params })
}
// 添加岗位
export function jobsAdd(params: any) {
return request.post({ url: '/dept.jobs/add', params })
}
// 编辑岗位
export function jobsEdit(params: any) {
return request.post({ url: '/dept.jobs/edit', params })
}
// 删除岗位
export function jobsDelete(params: any) {
return request.post({ url: '/dept.jobs/delete', params })
}
// 岗位详情
export function jobsDetail(params: any) {
return request.get({ url: '/dept.jobs/detail', params })
}
+29
View File
@@ -0,0 +1,29 @@
import request from '@/utils/request'
// 管理员列表
export function adminLists(params: any) {
return request.get({ url: '/auth.admin/lists', params }, { ignoreCancelToken: true })
}
// 管理员列表全部
export function adminAll(params: any) {
return request.get({ url: '/auth.admin/all', params })
}
// 管理员添加
export function adminAdd(params: any) {
return request.post({ url: '/auth.admin/add', params })
}
// 管理员编辑
export function adminEdit(params: any) {
return request.post({ url: '/auth.admin/edit', params })
}
// 管理员删除
export function adminDelete(params: any) {
return request.post({ url: '/auth.admin/delete', params })
}
// 管理员详情
export function adminDetail(params: any) {
return request.get({ url: '/auth.admin/detail', params })
}
+30
View File
@@ -0,0 +1,30 @@
import request from '@/utils/request'
// 菜单列表
export function menuLists(params: Record<string, any>) {
return request.get({ url: '/auth.menu/lists', params })
}
// 菜单全部
export function menuAll(params?: Record<string, any>) {
return request.get({ url: '/auth.menu/all', params })
}
// 添加菜单
export function menuAdd(params: Record<string, any>) {
return request.post({ url: '/auth.menu/add', params })
}
// 编辑菜单
export function menuEdit(params: Record<string, any>) {
return request.post({ url: '/auth.menu/edit', params })
}
// 菜单删除
export function menuDelete(params: Record<string, any>) {
return request.post({ url: '/auth.menu/delete', params })
}
// 菜单详情
export function menuDetail(params: Record<string, any>) {
return request.get({ url: '/auth.menu/detail', params })
}
+27
View File
@@ -0,0 +1,27 @@
import request from '@/utils/request'
// 角色列表
export function roleLists(params: any) {
return request.get({ url: '/auth.role/lists', params })
}
// 角色列表全部
export function roleAll(params: any) {
return request.get({ url: '/auth.role/all', params })
}
// 添加角色
export function roleAdd(params: any) {
return request.post({ url: '/auth.role/add', params })
}
// 编辑角色
export function roleEdit(params: any) {
return request.post({ url: '/auth.role/edit', params })
}
// 删除角色
export function roleDelete(params: any) {
return request.post({ url: '/auth.role/delete', params })
}
// 角色详情
export function roleDetail(params: any) {
return request.get({ url: '/auth.role/detail', params })
}
+21
View File
@@ -0,0 +1,21 @@
import request from '@/utils/request'
export function pointsProductLists(params?: any) {
return request.get({ url: '/points.pointsProduct/lists', params })
}
export function pointsProductAdd(params: any) {
return request.post({ url: '/points.pointsProduct/add', params })
}
export function pointsProductEdit(params: any) {
return request.post({ url: '/points.pointsProduct/edit', params })
}
export function pointsProductDelete(params: any) {
return request.post({ url: '/points.pointsProduct/delete', params })
}
export function pointsProductDetail(params: any) {
return request.get({ url: '/points.pointsProduct/detail', params })
}
+43
View File
@@ -0,0 +1,43 @@
import request from '@/utils/request'
// === 弹窗 ===
export function popupLists(params?: any) {
return request.get({ url: '/popup.popup/lists', params })
}
export function popupAdd(params: any) {
return request.post({ url: '/popup.popup/add', params })
}
export function popupEdit(params: any) {
return request.post({ url: '/popup.popup/edit', params })
}
export function popupDelete(params: any) {
return request.post({ url: '/popup.popup/delete', params })
}
export function popupDetail(params: any) {
return request.get({ url: '/popup.popup/detail', params })
}
export function popupStatus(params: any) {
return request.post({ url: '/popup.popup/updateStatus', params })
}
// === 弹窗日志 ===
export function popupLogLists(params?: any) {
return request.get({ url: '/popup.popupLog/lists', params })
}
export function popupLogStats(params?: any) {
return request.get({ url: '/popup.popupLog/stats', params })
}
// === 设备 ===
export function deviceLists(params?: any) {
return request.get({ url: '/device.device/lists', params })
}
export function deviceDetail(params: any) {
return request.get({ url: '/device.device/detail', params })
}
export function deviceDelete(params: any) {
return request.post({ url: '/device.device/delete', params })
}
export function deviceStats(params?: any) {
return request.get({ url: '/device.device/stats', params })
}
+61
View File
@@ -0,0 +1,61 @@
import request from '@/utils/request'
// 字典类型列表
export function dictTypeLists(params: any) {
return request.get({ url: '/setting.dict.dict_type/lists', params })
}
// 字典类型列表全部
export function dictTypeAll(params: any) {
return request.get({ url: '/setting.dict.dict_type/all', params })
}
// 添加字典类型
export function dictTypeAdd(params: any) {
return request.post({ url: '/setting.dict.dict_type/add', params })
}
// 编辑字典类型
export function dictTypeEdit(params: any) {
return request.post({ url: '/setting.dict.dict_type/edit', params })
}
// 删除字典类型
export function dictTypeDelete(params: any) {
return request.post({ url: '/setting.dict.dict_type/delete', params })
}
// 字典类型详情
export function dictTypeDetail(params: any) {
return request.get({ url: '/setting.dict.dict_type/detail', params })
}
// 字典数据列表
export function dictDataLists(params: any) {
return request.get(
{ url: '/setting.dict.dict_data/lists', params },
{
ignoreCancelToken: true
}
)
}
// 添加字典数据
export function dictDataAdd(params: any) {
return request.post({ url: '/setting.dict.dict_data/add', params })
}
// 编辑字典数据
export function dictDataEdit(params: any) {
return request.post({ url: '/setting.dict.dict_data/edit', params })
}
// 删除字典数据
export function dictDataDelete(params: any) {
return request.post({ url: '/setting.dict.dict_data/delete', params })
}
// 字典数据详情
export function dictDataDetail(params: any) {
return request.get({ url: '/setting.dict.dict_data/detail', params })
}
+26
View File
@@ -0,0 +1,26 @@
import request from '@/utils/request'
// 获取支付方式
export function getPayWay() {
return request.get({ url: '/setting.pay.pay_way/getPayWay' })
}
// 设置支付方式
export function setPayWay(params: any) {
return request.post({ url: '/setting.pay.pay_way/setPayWay', params })
}
// 获取支付方式
export function getPayConfigLists() {
return request.get({ url: '/setting.pay.pay_config/lists' })
}
// 设置支付方式
export function setPayConfig(params: any) {
return request.post({ url: '/setting.pay.pay_config/setConfig', params })
}
// 设置支付方式
export function getPayConfig(params: any) {
return request.get({ url: '/setting.pay.pay_config/getConfig', params })
}
+27
View File
@@ -0,0 +1,27 @@
import request from '@/utils/request'
/**
* @return { Promise }
* @description 获取热门搜索数据
*/
export function getSearch() {
return request.get({ url: '/setting.hot_search/getConfig' })
}
export interface List {
name: string // 搜索关键字
sort: number // 热门搜索排序
}
export interface Search {
status: number // 是否开启搜索0/1
data: List[]
}
/**
* @return { Promise }
* @param { Search } Search
* @description 设置热门搜索
*/
export function setSearch(params: Search) {
return request.post({ url: '/setting.hot_search/setConfig', params })
}
+21
View File
@@ -0,0 +1,21 @@
import request from '@/utils/request'
// 获取存储引擎列表
export function storageLists() {
return request.get({ url: '/setting.storage/lists' })
}
// 设置存储引擎信息
export function storageChange(params: any) {
return request.post({ url: '/setting.storage/change', params })
}
// 设置存储引擎信息
export function storageSetup(params: any) {
return request.post({ url: '/setting.storage/setup', params })
}
// 获取存储配置信息
export function storageDetail(params: any) {
return request.get({ url: '/setting.storage/detail', params })
}
+66
View File
@@ -0,0 +1,66 @@
import request from '@/utils/request'
// 获取系统环境
export function systemInfo() {
return request.get({ url: '/setting.system.system/info' })
}
// 获取系统日志列表
export function systemLogLists(params: any) {
return request.get({ url: '/setting.system.log/lists', params }, { ignoreCancelToken: true })
}
// 清除系统缓存
export function systemCacheClear() {
return request.post({ url: '/setting.system.cache/clear' })
}
// 定时任务列表
export function crontabLists(params: any) {
return request.get({ url: '/crontab.crontab/lists', params })
}
// 添加定时任务
export function crontabAdd(params: any) {
return request.post({ url: '/crontab.crontab/add', params })
}
// 定时任务详情
export function crontabDetail(params: any) {
return request.get({ url: '/crontab.crontab/detail', params })
}
// 编辑定时任务
export function crontabEdit(params: any) {
return request.post({ url: '/crontab.crontab/edit', params })
}
// 删除定时任务
export function crontabDel(params: any) {
return request.post({ url: '/crontab.crontab/delete', params })
}
// 获取规则执行时间
export function crontabExpression(params: any) {
return request.get({ url: '/crontab.crontab/expression', params })
}
// 操作定时任务
export function srontabOperate(params: any) {
return request.post({ url: '/crontab.crontab/operate', params })
}
// 手动执行定时任务
export function crontabRun(params: any) {
return request.post({ url: '/crontab.crontab/run', params })
}
// 定时任务执行日志
export function crontabLogs(params: any) {
return request.get({ url: '/crontab.crontab/logs', params })
}
// 验证码记录列表
export function smsUploadLists(params: any) {
return request.get({ url: '/setting.sms_upload/lists', params })
}
+43
View File
@@ -0,0 +1,43 @@
import request from '@/utils/request'
/**
* @return { Promise }
* @description 获取用户设置
*/
export function getUserSetup() {
return request.get({ url: '/setting.user.user/getConfig' })
}
/**
* @return { Promise }
* @param { string } default_avatar 默认用户头像
* @description 设置用户设置
*/
export function setUserSetup(params: { default_avatar: string }) {
return request.post({ url: '/setting.user.user/setConfig', params })
}
/**
* @return { Promise }
* @description 设置登录注册规则
*/
export function getLogin() {
return request.get({ url: '/setting.user.user/getRegisterConfig' })
}
export interface LoginSetup {
login_way: number[] | any // 登录方式, 逗号隔开
coerce_mobile: number // 强制绑定手机 0/1
login_agreement: number // 是否开启协议 0/1
third_auth: number // 第三方登录 0/1
wechat_auth: number // 微信授权登录 0-关闭 1-开启
qq_auth: number // qq授权登录 0-关闭 1-开启
}
/**
* @return { Promise }
* @param { LoginSetup } LoginSetup
* @description 设置登录注册规则
*/
export function setLogin(params: LoginSetup) {
return request.post({ url: '/setting.user.user/setRegisterConfig', params })
}
+36
View File
@@ -0,0 +1,36 @@
import request from '@/utils/request'
// 获取备案信息
export function getCopyright() {
return request.get({ url: '/setting.web.web_setting/getCopyright' })
}
// 设置备案信息
export function setCopyright(params: any) {
return request.post({ url: '/setting.web.web_setting/setCopyright', params })
}
// 获取网站信息
export function getWebsite() {
return request.get({ url: '/setting.web.web_setting/getWebsite' })
}
// 设置网站信息
export function setWebsite(params: any) {
return request.post({ url: '/setting.web.web_setting/setWebsite', params })
}
// 获取政策协议
export function getProtocol() {
return request.get({ url: '/setting.web.web_setting/getAgreement' })
}
// 设置政策协议
export function setProtocol(params: any) {
return request.post({ url: '/setting.web.web_setting/setAgreement', params })
}
// 获取站点统计信息
export function getSiteStatistics() {
return request.get({ url: '/setting.web.web_setting/getSiteStatistics' })
}
// 设置网站信息
export function setSiteStatistics(params: any) {
return request.post({ url: '/setting.web.web_setting/setSiteStatistics', params })
}
+21
View File
@@ -0,0 +1,21 @@
import request from '@/utils/request'
// 短链接列表
export function shortLinkLists(params?: any) {
return request.get({ url: '/shortlink.shortLink/lists', params })
}
// 短链接点击日志
export function shortLinkLogLists(params?: any) {
return request.get({ url: '/shortlink.shortLink/logLists', params })
}
// 删除短链接
export function shortLinkDelete(params: any) {
return request.post({ url: '/shortlink.shortLink/delete', params })
}
// 重新生成二维码
export function shortLinkRegenerateQrcode(params: { id: number }) {
return request.post({ url: '/shortlink.shortLink/regenerateQrcode', params })
}
+51
View File
@@ -0,0 +1,51 @@
import request from '@/utils/request'
// 代码生成已选数据表列表接口
export function generateTable(params: any) {
return request.get({ url: '/tools.generator/generateTable', params })
}
// 数据表列表接口
export function dataTable(params: any) {
return request.get({ url: '/tools.generator/dataTable', params })
}
//选择要生成代码的数据表
export function selectTable(params: any) {
return request.post({ url: '/tools.generator/selectTable', params })
}
// 已选择的数据表详情
export function tableDetail(params: any) {
return request.get({ url: '/tools.generator/detail', params })
}
//同步字段
export function syncColumn(params: any) {
return request.post({ url: '/tools.generator/syncColumn', params })
}
//删除已选择的数据表
export function generateDelete(params: any) {
return request.post({ url: '/tools.generator/delete', params })
}
//编辑已选表字段
export function generateEdit(params: any) {
return request.post({ url: '/tools.generator/edit', params })
}
//预览代码
export function generatePreview(params: any) {
return request.post({ url: '/tools.generator/preview', params })
}
//生成代码
export function generateCode(params: any) {
return request.post({ url: '/tools.generator/generate', params })
}
//获取模型
export function getModels() {
return request.get({ url: '/tools.generator/getModels' })
}
+22
View File
@@ -0,0 +1,22 @@
import config from '@/config'
import request from '@/utils/request'
// 登录
export function login(params: Record<string, any>) {
return request.post({ url: '/login/account', params: { ...params, terminal: config.terminal } })
}
// 退出登录
export function logout() {
return request.post({ url: '/login/logout' })
}
// 用户信息
export function getUserInfo() {
return request.get({ url: '/auth.admin/mySelf' })
}
// 编辑管理员信息
export function setUserInfo(params: any) {
return request.post({ url: '/auth.admin/editSelf', params })
}
+21
View File
@@ -0,0 +1,21 @@
import request from '@/utils/request'
export function vipLevelLists(params?: any) {
return request.get({ url: '/vip.vipLevel/lists', params })
}
export function vipLevelAdd(params: any) {
return request.post({ url: '/vip.vipLevel/add', params })
}
export function vipLevelEdit(params: any) {
return request.post({ url: '/vip.vipLevel/edit', params })
}
export function vipLevelDelete(params: any) {
return request.post({ url: '/vip.vipLevel/delete', params })
}
export function vipLevelDetail(params: any) {
return request.get({ url: '/vip.vipLevel/detail', params })
}
+1
View File
@@ -0,0 +1 @@
<?xml version="1.0" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg class="icon" width="32px" height="32.00px" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg"><path d="M502.869333 201.408a32.853333 32.853333 0 0 1 0 45.44L276.906667 480h544.384a32 32 0 0 1 0 64H276.885333l225.984 233.130667a32.853333 32.853333 0 0 1 0 45.44 30.485333 30.485333 0 0 1-44.053333 0L179.776 534.741333a32.128 32.128 0 0 1-6.848-10.688 32.213333 32.213333 0 0 1-0.085333-23.808l0.106666-0.32c1.514667-3.861333 3.797333-7.488 6.826667-10.624L458.837333 201.386667a30.485333 30.485333 0 0 1 44.053334 0z" /></svg>

After

Width:  |  Height:  |  Size: 689 B

+1
View File
@@ -0,0 +1 @@
<?xml version="1.0" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg class="icon" width="32px" height="32.00px" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg"><path d="M853.333333 170.666667a85.333333 85.333333 0 0 1 85.333334 85.333333v426.666667a85.333333 85.333333 0 0 1-85.333334 85.333333H576v42.666667h74.666667a32 32 0 0 1 0 64h-277.333334a32 32 0 0 1 0-64H448v-42.666667H170.666667a85.333333 85.333333 0 0 1-85.333334-85.333333V256a85.333333 85.333333 0 0 1 85.333334-85.333333h682.666666z m-127.957333 213.333333c-37.056 0.277333-77.824 17.258667-77.824 58.666667 0 45.12 37.909333 56.042667 78.976 60.928 26.709333 2.88 46.506667 10.666667 46.506667 29.632 0 21.845333-22.4 30.186667-46.229334 30.186666-24.405333 0-47.658667-9.792-56.576-31.914666l-31.573333 16.384c14.933333 36.8 46.506667 49.450667 87.573333 49.450666 44.8 0 84.437333-19.264 84.437334-64.106666 0-46.506667-36.650667-58.24-77.056-63.616l-3.925334-0.512c-24.106667-2.88-44.8-7.765333-44.8-25.301334 0-14.933333 13.504-26.730667 41.642667-26.730666 21.824 0 40.768 10.922667 47.658667 22.421333l30.165333-15.530667C789.12 392.917333 756.672 384 725.376 384z m-280 7.189333H401.706667v201.258667h37.909333v-146.346667l64.042667 87.68h7.466666l65.472-87.381333v146.048h37.909334v-201.258667h-43.370667l-62.890667 86.549334-62.890666-86.549334z m-194.133333-0.298666H213.333333v201.258666h37.909334V503.04l84.138666 89.109333h46.805334v-2.282666l-96.768-101.504 89.301333-96.32v-1.152h-47.082667l-76.394666 85.12v-85.12z" /></svg>

After

Width:  |  Height:  |  Size: 1.6 KiB

+1
View File
@@ -0,0 +1 @@
<?xml version="1.0" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg class="icon" width="32px" height="32.00px" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg"><path d="M385.6 371.242667c12.16 113.578667 92.906667 206.634667 200 236.949333l1.664 0.448-2.453333 2.005333-317.888 237.418667c-12.16 9.066667-28.8 8.533333-40.32-0.917333l-2.410667-2.154667-28.928-28.885333c0.213333 1.898667 0.490667 3.797333 0.810667 5.717333 6.186667 35.754667 31.338667 57.962667 79.808 49.322667 26.986667-4.821333 44.117333-11.242667 63.509333-22.464l6.336-3.776 11.541333-7.168 5.397334-3.285334c35.562667-21.248 64.96-29.909333 117.973333-30.442666 69.909333-0.704 129.088 21.056 175.701333 65.173333a32.853333 32.853333 0 0 1 1.28 46.4 32.746667 32.746667 0 0 1-46.293333 1.28c-33.898667-32.042667-76.608-47.744-130.026667-47.210667-40.597333 0.426667-59.029333 5.632-84.864 21.056l-17.642666 10.88c-28.266667 17.216-53.461333 27.413333-91.413334 34.176-87.808 15.658667-144-33.92-155.882666-102.741333a151.765333 151.765333 0 0 1 4.522666-72.042667l1.066667-2.965333-20.778667-20.736a32.853333 32.853333 0 0 1-3.968-41.706667l2.048-2.688 268.437334-318.72c0.874667-1.045333 1.813333-2.005333 2.773333-2.922666z m4.181333 169.344l-2.474666 2.24-46.357334 46.421333-2.24 2.496a32.853333 32.853333 0 0 0 2.24 43.925333 32.746667 32.746667 0 0 0 43.861334 2.24l2.496-2.24 46.336-46.421333 2.261333-2.496a32.853333 32.853333 0 0 0-2.261333-43.925333 32.746667 32.746667 0 0 0-43.861334-2.24zM661.333333 85.333333c141.376 0 256 114.624 256 256s-114.624 256-256 256-256-114.624-256-256S519.957333 85.333333 661.333333 85.333333z" /></svg>

After

Width:  |  Height:  |  Size: 1.7 KiB

@@ -0,0 +1 @@
<?xml version="1.0" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg class="icon" width="32px" height="32.00px" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg"><path d="M579.2 874.666667a21.333333 21.333333 0 0 1 14.421333 37.056C574.037333 929.685333 546.837333 938.666667 512 938.666667s-62.037333-8.981333-81.621333-26.944A21.333333 21.333333 0 0 1 444.821333 874.666667h134.357334z m28.8-85.333334a32 32 0 0 1 0 64h-192a32 32 0 0 1 0-64h192zM512 85.333333c176.725333 0 320 143.274667 320 320 0 114.090667-59.733333 214.250667-149.610667 270.912A85.333333 85.333333 0 0 1 597.333333 768h-170.666666a85.333333 85.333333 0 0 1-85.098667-91.776C251.733333 619.584 192 519.424 192 405.333333c0-176.725333 143.274667-320 320-320z m29.098667 106.666667a29.098667 29.098667 0 1 0 0 58.176 126.08 126.08 0 0 1 126.058666 126.08 29.098667 29.098667 0 1 0 58.176 0A184.234667 184.234667 0 0 0 541.098667 192z" /></svg>

After

Width:  |  Height:  |  Size: 1008 B

+1
View File
@@ -0,0 +1 @@
<?xml version="1.0" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg class="icon" width="32px" height="32.00px" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg"><path d="M486.570667 97.216a33.130667 33.130667 0 0 1 51.264 0.512c34.709333 43.328 152.064 98.261333 307.776 117.034667 16.576 2.005333 29.056 16 29.056 32.64v372.629333a167.04 167.04 0 0 1-20.096 79.402667C761.813333 871.146667 633.770667 938.666667 511.530667 938.666667l-6.528-0.106667c-118.954667-3.413333-244.586667-70.741333-335.573334-239.125333a167.808 167.808 0 0 1-19.925333-71.914667L149.333333 620.032V247.402667c0-16.64 12.48-30.634667 29.056-32.64 152.426667-18.368 269.077333-72.277333 305.237334-114.005334z m25.408 67.178667l-1.792 1.450666c-52.693333 41.813333-163.456 91.882667-290.389334 109.802667l-4.416 0.597333v342.976l0.149334 5.866667c0.746667 15.104 4.864 29.866667 12.074666 43.221333 80.96 149.845333 188.714667 201.962667 278.826667 204.544l5.568 0.085334c92.522667 0 201.92-51.989333 284.373333-204.629334a101.546667 101.546667 0 0 0 12.224-48.277333V276.245333l-16.277333-2.325333c-120.938667-18.048-227.904-67.690667-278.954667-108.416l-1.386666-1.109333z m161.194666 250.517333a32.853333 32.853333 0 0 1 0 46.186667l-187.306666 190.656a32.256 32.256 0 0 1-45.845334 0l-89.173333-91.157334a32.853333 32.853333 0 0 1 0-46.208 32.256 32.256 0 0 1 45.845333 0l51.029334 52.416a21.333333 21.333333 0 0 0 30.165333 0.426667l0.341333-0.362667 149.077334-151.957333a32.256 32.256 0 0 1 45.866666 0z" /></svg>

After

Width:  |  Height:  |  Size: 1.6 KiB

+1
View File
@@ -0,0 +1 @@
<?xml version="1.0" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg class="icon" width="32px" height="32.00px" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg"><path d="M486.570667 97.216a33.130667 33.130667 0 0 1 51.264 0.512c34.709333 43.328 152.064 98.261333 307.776 117.034667 16.576 2.005333 29.056 16 29.056 32.64v372.629333a167.04 167.04 0 0 1-20.096 79.402667C761.813333 871.146667 633.770667 938.666667 511.530667 938.666667l-6.528-0.106667c-118.954667-3.413333-244.586667-70.741333-335.573334-239.125333a167.808 167.808 0 0 1-19.925333-71.914667L149.333333 620.032V247.402667c0-16.64 12.48-30.634667 29.056-32.64 152.426667-18.368 269.077333-72.277333 305.237334-114.005334z m186.602666 317.696a32.256 32.256 0 0 0-45.866666 0l-149.077334 151.957333-0.341333 0.341334a21.333333 21.333333 0 0 1-30.165333-0.405334l-51.029334-52.416a32.256 32.256 0 0 0-45.866666 0 32.853333 32.853333 0 0 0 0 46.208l89.194666 91.157334a32.256 32.256 0 0 0 45.866667 0l187.285333-190.656a32.853333 32.853333 0 0 0 0-46.186667z" /></svg>

After

Width:  |  Height:  |  Size: 1.1 KiB

+1
View File
@@ -0,0 +1 @@
<?xml version="1.0" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg class="icon" width="32px" height="32.00px" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg"><path d="M486.570667 97.216a33.130667 33.130667 0 0 1 51.264 0.512c34.709333 43.328 152.064 98.261333 307.776 117.034667 16.576 2.005333 29.056 16 29.056 32.64v372.629333a167.04 167.04 0 0 1-20.096 79.402667C761.813333 871.146667 633.770667 938.666667 511.530667 938.666667l-6.528-0.106667c-118.954667-3.413333-244.586667-70.741333-335.573334-239.125333a167.808 167.808 0 0 1-19.925333-71.914667L149.333333 620.032V247.402667c0-16.64 12.48-30.634667 29.056-32.64 152.426667-18.368 269.077333-72.277333 305.237334-114.005334z m186.602666 317.696a32.256 32.256 0 0 0-45.866666 0l-149.077334 151.957333-0.341333 0.341334a21.333333 21.333333 0 0 1-30.165333-0.405334l-51.029334-52.416a32.256 32.256 0 0 0-45.866666 0 32.853333 32.853333 0 0 0 0 46.208l89.194666 91.157334a32.256 32.256 0 0 0 45.866667 0l187.285333-190.656a32.853333 32.853333 0 0 0 0-46.186667z" /></svg>

After

Width:  |  Height:  |  Size: 1.1 KiB

+1
View File
@@ -0,0 +1 @@
<?xml version="1.0" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg class="icon" width="32px" height="32.00px" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg"><path d="M512 107.136v707.093333l-221.248 99.434667a32 32 0 0 1-44.586667-34.986667l41.834667-227.413333-182.826667-195.84a32 32 0 0 1 18.474667-53.461333l228.586667-35.733334 141.226666-248.298666A21.333333 21.333333 0 0 1 512 107.136z" /></svg>

After

Width:  |  Height:  |  Size: 503 B

+1
View File
@@ -0,0 +1 @@
<?xml version="1.0" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg class="icon" width="32px" height="32.00px" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg"><path d="M486.570667 97.216a33.130667 33.130667 0 0 1 51.264 0.512c34.709333 43.328 152.064 98.261333 307.776 117.034667 16.576 2.005333 29.056 16 29.056 32.64v372.629333a167.04 167.04 0 0 1-20.096 79.402667C761.813333 871.146667 633.770667 938.666667 511.530667 938.666667l-6.528-0.106667c-118.954667-3.413333-244.586667-70.741333-335.573334-239.125333a167.808 167.808 0 0 1-19.925333-71.914667L149.333333 620.032V247.402667c0-16.64 12.48-30.634667 29.056-32.64 152.426667-18.368 269.077333-72.277333 305.237334-114.005334z m-10.026667 256.213333h-122.090667v346.026667h38.442667V389.845333h45.205333c-9.045333 30.997333-21.845333 65.493333-38.058666 104.234667 24.490667 32.170667 36.906667 61.226667 36.906666 87.189333 0 6.186667-1.493333 10.453333-4.117333 12.8-3.029333 2.304-9.045333 3.861333-17.706667 4.629334-5.290667 0-12.053333-0.768-20.352-2.325334l12.437334 40.32c26.752-0.405333 45.589333-5.44 56.874666-15.509333 7.552-8.149333 11.306667-21.333333 11.306667-39.914667-2.261333-26.346667-14.293333-57.344-36.906667-93.397333a1520.768 1520.768 0 0 0 38.037334-104.234667v-30.208z m155.946667 148.8c-11.306667 58.112-24.106667 107.306667-39.168 147.626667h-132.608v38.741333h226.773333v-38.741333h-55.744c15.445333-40.32 28.629333-85.632 39.189333-136.789333l-38.442666-10.837334z m-121.685334 11.221334l-33.514666 11.626666c12.8 34.88 23.722667 71.68 32 110.058667l33.92-8.533333c-9.813333-42.624-20.352-80.213333-32.405334-113.152z m59.904-13.952l-33.514666 11.626666c11.306667 33.706667 20.330667 68.970667 27.861333 106.176l33.536-8.917333c-8.277333-41.066667-17.322667-77.098667-27.882667-108.885333z m21.12-158.869334h-34.688c-23.338667 51.541333-57.258667 93.397333-101.333333 125.930667l19.968 31.786667c13.568-9.685333 26.752-20.928 39.189333-33.322667v20.522667h120.533334v-19.370667a338.133333 338.133333 0 0 0 38.826666 32.554667l21.461334-33.706667c-49.344-35.648-84.010667-77.12-103.978667-124.373333z m-17.344 39.530667a279.530667 279.530667 0 0 0 44.821334 68.970667h-90.026667a370.410667 370.410667 0 0 0 45.205333-68.970667z" /></svg>

After

Width:  |  Height:  |  Size: 2.3 KiB

@@ -0,0 +1 @@
<?xml version="1.0" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg class="icon" width="32px" height="32.00px" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg"><path d="M789.333333 486.250667V746.666667c0 58.901333-124.16 106.666667-277.333333 106.666666-150.570667 0-273.109333-46.144-277.226667-103.68L234.666667 746.666667V486.250667l260.053333 115.285333a42.666667 42.666667 0 0 0 30.848 1.450667l3.733333-1.450667L789.333333 486.250667zM529.28 166.464l398.592 176.704a21.333333 21.333333 0 0 1 0 38.997333L874.666667 405.76 874.666667 603.093333A42.666667 42.666667 0 1 1 832 603.029333v-178.410666l-302.72 134.229333a42.666667 42.666667 0 0 1-34.56 0L96.106667 382.165333a21.333333 21.333333 0 0 1 0-38.997333l398.570666-176.704a42.666667 42.666667 0 0 1 34.602667 0z" /></svg>

After

Width:  |  Height:  |  Size: 880 B

+1
View File
@@ -0,0 +1 @@
<?xml version="1.0" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg class="icon" width="32px" height="32.00px" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg"><path d="M864 832a32 32 0 0 1 0 64h-704a32 32 0 0 1 0-64h704zM710.613333 152.533333l3.541334 3.413334 89.92 89.898666a95.36 95.36 0 0 1 3.370666 131.285334l-3.370666 3.562666-332.309334 332.309334c-9.386667 9.386667-21.077333 16.042667-33.856 19.349333l-4.842666 1.088-178.261334 33.642667a52.970667 52.970667 0 0 1-62.464-57.984l0.576-3.904L226.56 526.933333c2.453333-13.013333 8.362667-25.130667 17.045333-35.072l3.392-3.626666L579.306667 155.946667a95.36 95.36 0 0 1 131.285333-3.370667z m-83.946666 46.165334l-2.410667 2.176-332.309333 332.309333a10.602667 10.602667 0 0 0-2.517334 3.989333l-0.405333 1.536-30.741333 162.986667 119.978666-22.634667-51.968-51.968a31.786667 31.786667 0 1 1 44.949334-44.949333l70.72 70.72 317.141333-317.12a31.786667 31.786667 0 0 0 2.197333-42.538667l-2.197333-2.410666-89.898667-89.92a31.786667 31.786667 0 0 0-42.538666-2.176z" /></svg>

After

Width:  |  Height:  |  Size: 1.1 KiB

+1
View File
@@ -0,0 +1 @@
<?xml version="1.0" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg class="icon" width="32px" height="32.00px" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg"><path d="M512 85.333333c235.648 0 426.666667 191.018667 426.666667 426.666667s-191.018667 426.666667-426.666667 426.666667S85.333333 747.648 85.333333 512 276.352 85.333333 512 85.333333z m0 64C311.701333 149.333333 149.333333 311.701333 149.333333 512s162.368 362.666667 362.666667 362.666667 362.666667-162.368 362.666667-362.666667S712.298667 149.333333 512 149.333333z m-145.173333 471.338667A180.970667 180.970667 0 0 0 512 693.333333a180.650667 180.650667 0 0 0 128.746667-53.653333c5.888-5.930667 11.370667-12.266667 16.384-18.944a32 32 0 0 1 51.2 38.421333c-6.784 9.024-14.186667 17.578667-22.122667 25.6A244.629333 244.629333 0 0 1 512 757.333333c-78.208 0-150.357333-36.906667-196.373333-98.261333a32 32 0 1 1 51.2-38.4zM341.333333 384a42.666667 42.666667 0 1 1 0 85.333333 42.666667 42.666667 0 0 1 0-85.333333z m341.333334 0a42.666667 42.666667 0 1 1 0 85.333333 42.666667 42.666667 0 0 1 0-85.333333z" /></svg>

After

Width:  |  Height:  |  Size: 1.2 KiB

+1
View File
@@ -0,0 +1 @@
<?xml version="1.0" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg class="icon" width="32px" height="32.00px" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg"><path d="M512.042667 213.333333c82.752 0 161.088 24.106667 234.88 71.786667l53.525333-53.482667a32 32 0 1 1 45.248 45.248L287.573333 835.029333a32 32 0 1 1-45.248-45.248l44.693334-44.714666c-62.72-38.528-122.154667-93.909333-178.261334-165.802667a108.522667 108.522667 0 0 1-3.093333-130.56l3.136-4.202667 6.805333-8.64C233.045333 288.533333 365.546667 213.333333 512.042667 213.333333z m334.506666 153.216a842.88 842.88 0 0 1 68.693334 78.08 108.522667 108.522667 0 0 1 3.029333 130.688l-3.136 4.202667-6.826667 8.64C790.570667 735.466667 658.133333 810.666667 512.042667 810.666667a410.88 410.88 0 0 1-97.898667-11.733334l53.013333-52.970666a344.32 344.32 0 0 0 44.885334 2.901333c120.896 0 233.088-62.229333 337.408-189.482667l6.784-8.405333 6.613333-8.341333a49.344 49.344 0 0 0 0-61.226667 787.370667 787.370667 0 0 0-61.205333-69.973333l44.906666-44.885334z m-334.506666-91.413333c-121.28 0-233.493333 62.229333-337.557334 189.44l-6.784 8.405333-6.570666 8.341334a49.344 49.344 0 0 0 0.042666 61.205333c54.954667 70.442667 112.106667 122.581333 171.562667 156.8l92.864-92.885333a128 128 0 1 1 180.842667-180.842667l94.976-94.933333c-60.650667-37.184-123.733333-55.530667-189.376-55.530667zM512 443.072a68.906667 68.906667 0 0 0-44.522667 121.536l97.130667-97.130667A68.778667 68.778667 0 0 0 512 443.072z" /></svg>

After

Width:  |  Height:  |  Size: 1.5 KiB

+1
View File
@@ -0,0 +1 @@
<?xml version="1.0" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg class="icon" width="32px" height="32.00px" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg"><path d="M384 554.666667a85.333333 85.333333 0 0 1 85.333333 85.333333v170.666667a85.333333 85.333333 0 0 1-85.333333 85.333333h-170.666667a85.333333 85.333333 0 0 1-85.333333-85.333333v-170.666667a85.333333 85.333333 0 0 1 85.333333-85.333333h170.666667z m245.333333 213.333333a32 32 0 0 1 32 32v42.666667a32 32 0 0 1-64 0v-42.666667a32 32 0 0 1 32-32z m192-21.333333a32 32 0 0 1 32 32v64a32 32 0 0 1-64 0v-64a32 32 0 0 1 32-32zM384 618.666667h-170.666667a21.333333 21.333333 0 0 0-21.184 18.837333L192 640v170.666667a21.333333 21.333333 0 0 0 18.837333 21.184L213.333333 832h170.666667a21.333333 21.333333 0 0 0 21.184-18.837333L405.333333 810.666667v-170.666667a21.333333 21.333333 0 0 0-18.837333-21.184L384 618.666667z m245.333333-42.666667a32 32 0 0 1 32 32v85.333333a32 32 0 0 1-64 0v-85.333333a32 32 0 0 1 32-32z m192 0a32 32 0 0 1 32 32v64a32 32 0 0 1-64 0v-64a32 32 0 0 1 32-32zM384 128a85.333333 85.333333 0 0 1 85.333333 85.333333v170.666667a85.333333 85.333333 0 0 1-85.333333 85.333333h-170.666667a85.333333 85.333333 0 0 1-85.333333-85.333333v-170.666667a85.333333 85.333333 0 0 1 85.333333-85.333333h170.666667z m426.666667 0a85.333333 85.333333 0 0 1 85.333333 85.333333v170.666667a85.333333 85.333333 0 0 1-85.333333 85.333333h-170.666667a85.333333 85.333333 0 0 1-85.333333-85.333333v-170.666667a85.333333 85.333333 0 0 1 85.333333-85.333333h170.666667zM384 192h-170.666667a21.333333 21.333333 0 0 0-21.184 18.837333L192 213.333333v170.666667a21.333333 21.333333 0 0 0 18.837333 21.184L213.333333 405.333333h170.666667a21.333333 21.333333 0 0 0 21.184-18.837333L405.333333 384v-170.666667a21.333333 21.333333 0 0 0-18.837333-21.184L384 192z m426.666667 0h-170.666667a21.333333 21.333333 0 0 0-21.184 18.837333L618.666667 213.333333v170.666667a21.333333 21.333333 0 0 0 18.837333 21.184L640 405.333333h170.666667a21.333333 21.333333 0 0 0 21.184-18.837333L832 384v-170.666667a21.333333 21.333333 0 0 0-18.837333-21.184L810.666667 192z" /></svg>

After

Width:  |  Height:  |  Size: 2.2 KiB

+1
View File
@@ -0,0 +1 @@
<?xml version="1.0" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg class="icon" width="32px" height="32.00px" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg"><path d="M512 64C264.6 64 64 264.6 64 512s200.6 448 448 448 448-200.6 448-448S759.4 64 512 64z m265.9 713.9a377.2 377.2 0 0 1-119.6 80.6 377.5 377.5 0 0 1-292.6 0 377.1 377.1 0 0 1-200.2-200.2 377.5 377.5 0 0 1 0-292.6 377.1 377.1 0 0 1 200.2-200.2 377.5 377.5 0 0 1 292.6 0 377.1 377.1 0 0 1 200.2 200.2 377.5 377.5 0 0 1 0 292.6 377.2 377.2 0 0 1-80.6 119.6zM651.3 258.8a3.9 3.9 0 0 0-5.6 0L512 392.5 378.3 258.8a3.9 3.9 0 0 0-5.6 0l-39.6 39.6a3.9 3.9 0 0 0 0 5.6l102.3 102.4H376a4 4 0 0 0-4 4v56a4 4 0 0 0 4 4h104v80H376a4 4 0 0 0-4 4v56a4 4 0 0 0 4 4h104v148a4 4 0 0 0 4 4h56a4 4 0 0 0 4-4v-148h104a4 4 0 0 0 4-4v-56a4 4 0 0 0-4-4H544v-80h104a4 4 0 0 0 4-4v-56a4 4 0 0 0-4-4h-59.4L690.9 304a3.9 3.9 0 0 0 0-5.6z" /></svg>

After

Width:  |  Height:  |  Size: 981 B

+1
View File
@@ -0,0 +1 @@
<?xml version="1.0" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg class="icon" width="32px" height="32.00px" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg"><path d="M511 64C263.6 64 63 264.6 63 512s200.6 448 448 448 448-200.6 448-448S758.4 64 511 64z m265.9 713.9a377.2 377.2 0 0 1-119.6 80.6 377.5 377.5 0 0 1-292.6 0 377.1 377.1 0 0 1-200.2-200.2 377.5 377.5 0 0 1 0-292.6 377.1 377.1 0 0 1 200.2-200.2 377.5 377.5 0 0 1 292.6 0 377.1 377.1 0 0 1 200.2 200.2 377.5 377.5 0 0 1 0 292.6 377.2 377.2 0 0 1-80.6 119.6zM513.8 288.6a3.9 3.9 0 0 0-5.6 0L287.6 509.2a3.9 3.9 0 0 0 0 5.6l220.6 220.6a3.9 3.9 0 0 0 5.6 0l220.6-220.6a3.9 3.9 0 0 0 0-5.6zM511 636.5L386.5 512 511 387.5 635.5 512z" /></svg>

After

Width:  |  Height:  |  Size: 796 B

+1
View File
@@ -0,0 +1 @@
<?xml version="1.0" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg class="icon" width="32px" height="32.00px" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg"><path d="M285.8 406.9l137.3 83.7a7.7 7.7 0 0 0 11.8-6.6v-51.7h175a68.1 68.1 0 0 1 67.9 64.1 4.1 4.1 0 0 0 4 3.9h56.1a4.1 4.1 0 0 0 4-4.2c-2.2-70.8-60.6-127.8-132-127.8h-175v-51.8a7.7 7.7 0 0 0-11.8-6.6l-137.3 83.7a7.8 7.8 0 0 0 0 13.3z m452.4 210.2l-137.3-83.7a7.7 7.7 0 0 0-11.8 6.6v51.7h-175a68.1 68.1 0 0 1-67.9-64.1 4.1 4.1 0 0 0-4-3.9h-56.1a4.1 4.1 0 0 0-4 4.2c2.2 70.8 60.6 127.8 132 127.8h175v51.8a7.7 7.7 0 0 0 11.8 6.6l137.3-83.7a7.8 7.8 0 0 0 0-13.3zM856 128H168a40 40 0 0 0-40 40v688a40 40 0 0 0 40 40h688a40 40 0 0 0 40-40V168a40 40 0 0 0-40-40z m-32 696H200V200h624z" /></svg>

After

Width:  |  Height:  |  Size: 845 B

+1
View File
@@ -0,0 +1 @@
<?xml version="1.0" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg class="icon" width="32px" height="32.00px" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg"><path d="M512 106.666667c103.68 0 192.96 61.632 233.194667 150.250666C853.717333 266.944 938.666667 358.186667 938.666667 469.333333c0 95.509333-62.762667 176.362667-149.333334 203.562667V832a85.333333 85.333333 0 0 1-85.333333 85.333333H320a85.333333 85.333333 0 0 1-85.333333-85.333333v-180.437333C148.117333 624.384 85.333333 543.530667 85.333333 448c0-114.986667 90.944-208.704 204.8-213.162667A255.893333 255.893333 0 0 1 512 106.666667z m-104.725333 583.893333a25.557333 25.557333 0 0 0-36.949334 0 27.605333 27.605333 0 0 0 0 38.186667c78.250667 80.789333 205.098667 80.789333 283.349334 0a27.605333 27.605333 0 0 0 0-38.186667 25.557333 25.557333 0 0 0-36.949334 0 144.810667 144.810667 0 0 1-209.450666 0z" /></svg>

After

Width:  |  Height:  |  Size: 981 B

+1
View File
@@ -0,0 +1 @@
<?xml version="1.0" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg class="icon" width="32px" height="32.00px" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg"><path d="M880 184H712v-64c0-4.4-3.6-8-8-8h-56c-4.4 0-8 3.6-8 8v64H384v-64c0-4.4-3.6-8-8-8h-56c-4.4 0-8 3.6-8 8v64H144c-17.7 0-32 14.3-32 32v664c0 17.7 14.3 32 32 32h736c17.7 0 32-14.3 32-32V216c0-17.7-14.3-32-32-32z m-40 656H184V256h128v48c0 4.4 3.6 8 8 8h56c4.4 0 8-3.6 8-8v-48h256v48c0 4.4 3.6 8 8 8h56c4.4 0 8-3.6 8-8v-48h128v584zM688 420h-55.2c-5.1 0-10 2.5-13 6.6L468.9 634.4l-64.7-89c-3-4.1-7.8-6.6-13-6.6H336c-6.5 0-10.3 7.4-6.5 12.7l126.4 174c6.4 8.8 19.6 8.8 26 0l212.6-292.7c3.8-5.4 0-12.8-6.5-12.8z" /></svg>

After

Width:  |  Height:  |  Size: 775 B

+1
View File
@@ -0,0 +1 @@
<?xml version="1.0" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg class="icon" width="32px" height="32.00px" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg"><path d="M332.202667 347.136c12.16 12.373333 12.16 32.426667 0 44.821333-12.16 12.373333-31.893333 12.373333-44.053334 0l-151.04-115.584a32.085333 32.085333 0 0 1 0-44.842666l151.04-115.584c12.16-12.373333 31.893333-12.373333 44.053334 0 12.16 12.373333 12.16 32.448 0 44.842666l-85.290667 61.589334H565.333333c182.613333 0 330.666667 146.026667 330.666667 326.144 0 177.92-144.426667 322.538667-323.925333 326.08L565.333333 874.666667h-213.333333a31.786667 31.786667 0 0 1-32-31.573334c0-16.384 12.693333-29.866667 28.928-31.402666l3.072-0.149334h213.333333c147.285333 0 266.666667-117.76 266.666667-263.018666 0-143.082667-115.84-259.477333-260.096-262.933334l-6.570667-0.064-318.442666-0.021333 85.333333 61.632z" /></svg>

After

Width:  |  Height:  |  Size: 982 B

+1
View File
@@ -0,0 +1 @@
<?xml version="1.0" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg class="icon" width="32px" height="32.00px" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg"><path d="M853.333333 338.944V537.6c-32-16.362667-68.266667-25.6-106.666666-25.6-129.6 0-234.666667 105.066667-234.666667 234.666667 0 79.381333 39.424 149.546667 99.754667 192.021333L256 938.666667a85.333333 85.333333 0 0 1-85.333333-85.333334V338.965333a510.229333 510.229333 0 0 0 257.216 123.498667 85.312 85.312 0 0 0 168.192 0 510.165333 510.165333 0 0 0 257.28-123.52zM768 85.333333a85.333333 85.333333 0 0 1 85.333333 85.333334l0.021334 108.778666a468.437333 468.437333 0 0 1-260.842667 140.330667 85.354667 85.354667 0 0 0-161.088 0 468.373333 468.373333 0 0 1-260.778667-140.330667L170.666667 170.666667a85.333333 85.333333 0 0 1 85.333333-85.333334h512z m-21.354667 469.333334a191.957333 191.957333 0 0 1 168.597334 100.053333L746.666667 746.666667l135.765333 135.744A192 192 0 1 1 746.645333 554.666667z m32 106.666666a32 32 0 1 0 0-64 32 32 0 0 0 0 64z" /></svg>

After

Width:  |  Height:  |  Size: 1.1 KiB

@@ -0,0 +1 @@
<?xml version="1.0" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg class="icon" width="32px" height="32.00px" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg"><path d="M103.082667 632.704c1.493333 1.130667 3.093333 2.176 4.778666 3.136l2.56 1.344L490.666667 822.421333a49.066667 49.066667 0 0 0 38.976 1.621334l3.690666-1.621334 380.224-185.237333c2.624-1.28 5.077333-2.773333 7.36-4.458667 17.216 12.650667 22.954667 35.477333 12.544 54.4a45.162667 45.162667 0 0 1-19.904 18.752L533.333333 891.093333a49.024 49.024 0 0 1-42.666666 0L110.442667 705.877333c-22.784-11.093333-31.701333-37.482667-19.904-58.922666 3.072-5.546667 7.338667-10.410667 12.544-14.250667z m0-153.6c1.493333 1.130667 3.093333 2.176 4.778666 3.136l2.56 1.344L490.666667 668.821333a49.066667 49.066667 0 0 0 38.976 1.621334l3.690666-1.621334 380.224-185.237333c2.624-1.28 5.077333-2.773333 7.36-4.458667 17.216 12.650667 22.954667 35.477333 12.544 54.4a45.162667 45.162667 0 0 1-19.904 18.752L533.333333 737.493333a49.024 49.024 0 0 1-42.666666 0L110.442667 552.277333c-22.784-11.093333-31.701333-37.482667-19.904-58.922666 3.072-5.546667 7.338667-10.410667 12.544-14.250667zM533.333333 132.970667l380.224 187.968c22.784 11.264 31.701333 38.037333 19.904 59.776a45.44 45.44 0 0 1-19.904 19.008L533.333333 587.733333c-13.376 6.613333-29.290667 6.613333-42.666666 0L110.442667 399.722667c-22.784-11.264-31.701333-38.016-19.904-59.776a45.44 45.44 0 0 1 19.904-18.986667L490.666667 132.949333a48.362667 48.362667 0 0 1 42.666666 0z" /></svg>

After

Width:  |  Height:  |  Size: 1.6 KiB

+1
View File
@@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" width="32" height="32" viewBox="0 0 24 24"><path fill="currentColor" d="M11.28 9.53L8.81 12l2.47 2.47a.749.749 0 0 1-.326 1.275a.75.75 0 0 1-.734-.215l-3-3a.75.75 0 0 1 0-1.06l3-3a.749.749 0 0 1 1.275.326a.75.75 0 0 1-.215.734"/><path fill="currentColor" d="M3.75 2h16.5c.966 0 1.75.784 1.75 1.75v16.5A1.75 1.75 0 0 1 20.25 22H3.75A1.75 1.75 0 0 1 2 20.25V3.75C2 2.784 2.784 2 3.75 2M3.5 3.75v16.5c0 .138.112.25.25.25H15v-17H3.75a.25.25 0 0 0-.25.25m13 16.75h3.75a.25.25 0 0 0 .25-.25V3.75a.25.25 0 0 0-.25-.25H16.5Z"/></svg>

After

Width:  |  Height:  |  Size: 565 B

+1
View File
@@ -0,0 +1 @@
<?xml version="1.0" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg class="icon" width="32px" height="32.00px" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg"><path d="M857.770667 163.882667c75.157333 75.136 72.448 209.237333 6.122666 346.944-17.792 36.309333-41.130667 72.725333-69.248 107.904a64 64 0 1 0 48.533334 41.792 697.173333 697.173333 0 0 0 51.328-72.682667c33.962667 109.098667 24.277333 208.938667-36.736 269.930667-67.84 67.84-183.701333 72.234667-306.922667 23.658666l-1.642667-0.938666-2.816-1.237334a475.690667 475.690667 0 0 1-34.410666-14.784v-0.021333c-40.170667-19.093333-80.64-44.842667-119.530667-76.288a32 32 0 0 0-40.234667 49.792c26.368 21.312 53.504 40.32 80.96 56.746667-108.842667 33.728-208.426667 23.957333-269.290666-36.906667-73.749333-73.749333-72.533333-204.309333-9.749334-339.328l3.434667-7.253333c19.882667-34.432 45.141333-68.693333 74.986667-101.482667a64 64 0 1 0-43.733334-46.997333 688.085333 688.085333 0 0 0-60.394666 75.093333c-35.477333-110.656-26.304-212.202667 35.456-273.941333 75.136-75.157333 209.237333-72.448 346.944-6.122667 137.706667-66.325333 271.808-69.034667 346.944 6.122667z m-347.306667 261.248a85.333333 85.333333 0 1 0 0 170.666666 85.333333 85.333333 0 0 0 0-170.666666z" /></svg>

After

Width:  |  Height:  |  Size: 1.3 KiB

+1
View File
@@ -0,0 +1 @@
<?xml version="1.0" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg class="icon" width="32px" height="32.00px" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg"><path d="M683.918222 910.222222h-341.333333a227.555556 227.555556 0 0 1-227.555556-227.555555V341.333333a227.555556 227.555556 0 0 1 227.555556-227.555555h341.333333a227.555556 227.555556 0 0 1 227.555556 227.555555v341.333334a227.555556 227.555556 0 0 1-227.555556 227.555555z m-341.333333-728.177778a159.288889 159.288889 0 0 0-159.288889 159.288889v341.333334a159.288889 159.288889 0 0 0 159.288889 159.288889h341.333333a159.288889 159.288889 0 0 0 159.288889-159.288889V341.333333a159.288889 159.288889 0 0 0-159.288889-159.288889z" /><path d="M513.251556 711.111111a199.111111 199.111111 0 1 1 199.111111-199.111111 199.395556 199.395556 0 0 1-199.111111 199.111111z m0-329.955555a130.844444 130.844444 0 1 0 130.844444 130.844444 130.844444 130.844444 0 0 0-130.844444-130.901333z" /></svg>

After

Width:  |  Height:  |  Size: 1.0 KiB

+1
View File
@@ -0,0 +1 @@
<?xml version="1.0" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg class="icon" width="32px" height="32.00px" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg"><path d="M512 85.333333c235.648 0 426.666667 191.018667 426.666667 426.666667s-191.018667 426.666667-426.666667 426.666667S85.333333 747.648 85.333333 512 276.352 85.333333 512 85.333333z m0 64C311.701333 149.333333 149.333333 311.701333 149.333333 512s162.368 362.666667 362.666667 362.666667 362.666667-162.368 362.666667-362.666667S712.298667 149.333333 512 149.333333z" /></svg>

After

Width:  |  Height:  |  Size: 639 B

Some files were not shown because too many files have changed in this diff Show More