18 Commits
main ... test

Author SHA1 Message Date
b4ed4f3264 ci(other): ci脚本换源
All checks were successful
CI Build & Deploy / build-and-deploy-dev (push) Successful in 1m55s
CI Build & Deploy / build-and-deploy-prod (push) Has been skipped
2025-11-05 11:42:48 +08:00
e0ee232f5f ci: update ci
All checks were successful
CI Build & Deploy / build-and-deploy-dev (push) Successful in 2m27s
CI Build & Deploy / build-and-deploy-prod (push) Has been skipped
2025-10-31 18:01:01 +08:00
0bb91567d9 Merge branch 'dev' into test
All checks were successful
CI Build & Deploy / build-and-deploy-dev (push) Successful in 32m55s
CI Build & Deploy / build-and-deploy-prod (push) Has been skipped
# Conflicts:
#	.gitea/workflows/ci.yaml
2025-10-31 17:08:50 +08:00
f8df513e10 ci: ci test 2025-10-31 17:06:08 +08:00
b20ae843d6 ci: test ci
Some checks failed
CI Build & Deploy / build-and-deploy-dev (push) Has been cancelled
CI Build & Deploy / build-and-deploy-prod (push) Has been cancelled
2025-10-31 16:54:11 +08:00
afbc4bac90 ci: test ci 2025-10-31 16:51:29 +08:00
90b920b9b4 ci: test ci 2025-10-31 16:44:32 +08:00
77bfbf1982 ci: test ci
All checks were successful
continuous-integration/drone/push Build is passing
2025-10-31 16:41:38 +08:00
7c198fac43 build(deps): 依赖升级
Some checks failed
continuous-integration/drone/push Build is failing
2025-10-31 15:37:57 +08:00
c3547feebd build(deps): 依赖升级
All checks were successful
continuous-integration/drone/push Build is passing
2025-10-31 14:47:49 +08:00
f231939ae9 refactor: 活动订单id显示变更嘉联
Some checks failed
continuous-integration/drone/push Build is failing
2025-10-31 14:39:18 +08:00
038f67ec2a refactor: 活动订单id显示变更嘉联
All checks were successful
continuous-integration/drone/push Build is passing
2025-10-31 14:36:56 +08:00
914c25e962 feat(custom): 多API版本
All checks were successful
continuous-integration/drone/push Build is passing
2025-09-23 18:27:19 +08:00
d754bd45c9 feat(custom): 多API版本
All checks were successful
continuous-integration/drone/push Build is passing
2025-09-23 18:24:41 +08:00
4261f8c5f1 feat(custom): 订单列表支付方式筛选增加新条件
All checks were successful
continuous-integration/drone/push Build is passing
2025-05-29 15:33:56 +08:00
e90e74ff40 mod(custom): \! 2025-05-29 15:33:56 +08:00
0ff7154101 feat(custom): 订单列表支付方式筛选增加新条件 2025-05-29 15:33:18 +08:00
e0632136d7 mod(custom): \!
All checks were successful
continuous-integration/drone/push Build is passing
2024-10-05 04:22:55 +08:00
27 changed files with 4050 additions and 6251 deletions

View File

@@ -1,158 +0,0 @@
kind: pipeline
type: docker
name: default
platform:
os: linux
arch: amd64
steps:
- name: 测试服-依赖安装&&编译打包
pull: if-not-exists
image: node:20-alpine
when:
branch:
- test
commands:
- npm config set registry https://registry.npmmirror.com/
- npm install -g pnpm
- pnpm install
- pnpm build:test
- rm -rf dist.tar
- rm -rf node_modules
- tar -zcvf dist.tar ./dist ./default.conf ./Dockerfile
- name: 正式服-依赖安装&&编译打包
pull: if-not-exists
image: node:20-alpine
when:
branch:
- main
commands:
- npm config set registry https://registry.npmmirror.com/
- npm install -g pnpm
- pnpm install
- pnpm build:prod
- rm -rf dist.tar
- rm -rf node_modules
- tar -zcvf dist.tar ./dist ./default.conf ./Dockerfile
- name: 测试服-产物上传
pull: if-not-exists
image: appleboy/drone-scp
when:
branch:
- test
settings:
host:
from_secret: HOST_DEV
username:
from_secret: USER_DEV
password:
from_secret: PWD_DEV
port: 22
strip_components: 1
target: /www/builder
source:
- ./dist.tar
- name: 测试服-部署
pull: if-not-exists
image: appleboy/drone-ssh
when:
branch:
- test
settings:
host:
from_secret: HOST_DEV
username:
from_secret: USER_DEV
password:
from_secret: PWD_DEV
port: 22
script:
- cd /www/builder
- mkdir jdt-admin-dev
- tar -xzvf dist.tar -C /www/builder/jdt-admin-dev
- rm -rf dist.tar
- cd jdt-admin-dev
- docker build -t jdt-admin-dev .
- docker stop jdt-admin-dev
- docker rm jdt-admin-dev
- docker run -d -p 8085:80 --restart=always --name jdt-admin-dev jdt-admin-dev
- cd ..
- rm -rf jdt-admin-dev
- name: 正式服-产物上传
pull: if-not-exists
image: appleboy/drone-scp
when:
branch:
- main
settings:
host:
from_secret: HOST_PROD
username:
from_secret: USER_PROD
password:
from_secret: PWD_PROD
port: 22
strip_components: 1
target: /www/builder
source:
- ./dist.tar
- name: 正式服-部署
pull: if-not-exists
image: appleboy/drone-ssh
when:
branch:
- main
settings:
host:
from_secret: HOST_PROD
username:
from_secret: USER_PROD
password:
from_secret: PWD_PROD
port: 22
script:
- cd /www/builder
- mkdir jdt-admin-prod
- tar -xzvf dist.tar -C /www/builder/jdt-admin-prod
- rm -rf dist.tar
- cd jdt-admin-prod
- docker build -t jdt-admin-prod .
- docker stop jdt-admin-prod
- docker rm jdt-admin-prod
- docker run -d -p 8085:80 --restart=always --name jdt-admin-prod jdt-admin-prod
- cd ..
- rm -rf jdt-admin-prod
- name: 企业微信通知
pull: if-not-exists
image: plugins/webhook
when:
branch:
- test
- main
status:
- success
- failure
settings:
urls: https://qyapi.weixin.qq.com/cgi-bin/webhook/send?key=a2065e21-4f92-4f5b-a432-2c0cd1d965b5
content_type: application/json
template: |
{
"msgtype": "markdown",
"markdown": {
"content": "{{#success build.status}}✅{{else}}❌{{/success}}**{{ repo.owner }}/{{ repo.name }}** (Build #{{build.number}})\n
>**构建结果**: {{ build.status }}
>**构建详情**: [点击查看]({{ build.link }})
>**代码分支**: {{ build.branch }}
>**提交标识**: {{ build.commit }}
>**提交发起**: {{ build.author }}
>**提交信息**: {{ build.message }}
"
}
}

View File

@@ -8,7 +8,12 @@ VITE_USE_MOCK=false
VITE_USE_PROXY=true VITE_USE_PROXY=true
# base api # base api
VITE_BASE_API='https://test.wanzhuanyongcheng.cn/admin' VITE_BASE_API='/api'
VITE_BASE_API_1='/api1'
# VITE_BASE_API='https://test.wanzhuanyongcheng.cn/admin'
# VITE_BASE_API_1='https://api.gxwzwh.com/admin'
VITE_WS1_URL='game.wanzhuanyongcheng.cn/dice/home' VITE_WS1_URL='game.wanzhuanyongcheng.cn/dice/home'

View File

@@ -6,6 +6,7 @@ VITE_USE_MOCK=false
# base api # base api
VITE_BASE_API='//www.wanzhuanyongcheng.cn/admin' VITE_BASE_API='//www.wanzhuanyongcheng.cn/admin'
VITE_BASE_API_1='//api.gxwzwh.com/admin'
# 是否启用压缩 # 是否启用压缩
VITE_USE_COMPRESS=true VITE_USE_COMPRESS=true

162
.gitea/workflows/ci.yaml Normal file
View File

@@ -0,0 +1,162 @@
name: CI Build & Deploy
on:
push:
branches:
- test
- main
jobs:
build-and-deploy-dev:
if: gitea.ref_name == 'test'
runs-on: gitea_act_runner
container:
image: node:24-alpine
steps:
- name: Checkout
uses: actions/checkout@v4
- name: Setup pnpm
uses: pnpm/action-setup@v3
with:
version: 8
- name: Install deps
run: |
npm config set registry https://registry.npmmirror.com/
pnpm install
- name: Build (test)
run: pnpm build:test
- name: Pack artifacts
run: |
rm -rf dist.tar
tar -zcvf dist.tar ./dist ./default.conf ./Dockerfile
- name: Upload artifacts to server
uses: appleboy/scp-action@v0.1.7
with:
host: ${{ secrets.HOST_DEV }}
username: ${{ secrets.USER_DEV }}
password: ${{ secrets.PWD_DEV }}
port: 22
source: 'dist.tar'
target: '/www/builder'
strip_components: 0
- name: Deploy over SSH
uses: appleboy/ssh-action@v1.0.3
with:
host: ${{ secrets.HOST_DEV }}
username: ${{ secrets.USER_DEV }}
password: ${{ secrets.PWD_DEV }}
port: 22
script: |
set -e
cd /www/builder
rm -rf jdt-admin-dev
mkdir -p jdt-admin-dev
tar -xzvf dist.tar -C /www/builder/jdt-admin-dev
rm -rf dist.tar
cd jdt-admin-dev
docker build -t jdt-admin-dev .
docker stop jdt-admin-dev || true
docker rm jdt-admin-dev || true
docker run -d -p 8085:80 --restart=always --name jdt-admin-dev jdt-admin-dev
cd ..
rm -rf jdt-admin-dev
- name: Notify WeCom (Dev)
if: always()
env:
WEBHOOK_KEY: ${{ secrets.QYWX_WEBHOOK_KEY }}
STATUS: ${{ job.status }}
REPO: ${{ gitea.repository }}
RUN_URL: ${{ gitea.server_url }}/${{ gitea.repository }}/actions/runs/${{ gitea.run_id }}
BRANCH: ${{ gitea.ref_name }}
COMMIT: ${{ gitea.sha }}
ACTOR: ${{ gitea.actor }}
run: |
sed -i 's/dl-cdn.alpinelinux.org/mirrors.aliyun.com/g' /etc/apk/repositories || true
apk add --no-cache curl jq
EMOJI=$( [ "$STATUS" = "success" ] && echo "✅" || echo "❌" )
MSG="$(printf "%s**%s** (Run #%s)\n>**构建结果**: %s\n>**构建详情**: [点击查看](%s)\n>**代码分支**: %s\n>**提交标识**: %s\n>**提交发起**: %s\n" "$EMOJI" "$REPO" "${{ gitea.run_number }}" "$STATUS" "$RUN_URL" "$BRANCH" "$COMMIT" "$ACTOR")"
curl -sS -H 'Content-Type: application/json' -d "{\"msgtype\":\"markdown\",\"markdown\":{\"content\":\"$MSG\"}}" "https://qyapi.weixin.qq.com/cgi-bin/webhook/send?key=${WEBHOOK_KEY}"
build-and-deploy-prod:
if: gitea.ref_name == 'main'
runs-on: gitea_act_runner
container:
image: node:24-alpine
steps:
- name: Checkout
uses: actions/checkout@v4
- name: Setup pnpm
uses: pnpm/action-setup@v3
with:
version: 8
- name: Install deps
run: |
npm config set registry https://registry.npmmirror.com/
pnpm install
- name: Build (prod)
run: pnpm build:prod
- name: Pack artifacts
run: |
rm -rf dist.tar
tar -zcvf dist.tar ./dist ./default.conf ./Dockerfile
- name: Upload artifacts to server
uses: appleboy/scp-action@v0.1.7
with:
host: ${{ secrets.HOST_PROD }}
username: ${{ secrets.USER_PROD }}
password: ${{ secrets.PWD_PROD }}
port: 22
source: 'dist.tar'
target: '/www/builder'
strip_components: 0
- name: Deploy over SSH
uses: appleboy/ssh-action@v1.0.3
with:
host: ${{ secrets.HOST_PROD }}
username: ${{ secrets.USER_PROD }}
password: ${{ secrets.PWD_PROD }}
port: 22
script: |
set -e
cd /www/builder
rm -rf jdt-admin-prod
mkdir -p jdt-admin-prod
tar -xzvf dist.tar -C /www/builder/jdt-admin-prod
rm -rf dist.tar
cd jdt-admin-prod
docker build -t jdt-admin-prod .
docker stop jdt-admin-prod || true
docker rm jdt-admin-prod || true
docker run -d -p 8085:80 --restart=always --name jdt-admin-prod jdt-admin-prod
cd ..
rm -rf jdt-admin-prod
- name: Notify WeCom (Prod)
if: always()
env:
WEBHOOK_KEY: ${{ secrets.QYWX_WEBHOOK_KEY }}
STATUS: ${{ job.status }}
REPO: ${{ gitea.repository }}
RUN_URL: ${{ gitea.server_url }}/${{ gitea.repository }}/actions/runs/${{ gitea.run_id }}
BRANCH: ${{ gitea.ref_name }}
COMMIT: ${{ gitea.sha }}
ACTOR: ${{ gitea.actor }}
run: |
sed -i 's/dl-cdn.alpinelinux.org/mirrors.aliyun.com/g' /etc/apk/repositories || true
apk add --no-cache curl jq
EMOJI=$( [ "$STATUS" = "success" ] && echo "✅" || echo "❌" )
MSG="$(printf "%s**%s** (Run #%s)\n>**构建结果**: %s\n>**构建详情**: [点击查看](%s)\n>**代码分支**: %s\n>**提交标识**: %s\n>**提交发起**: %s\n" "$EMOJI" "$REPO" "${{ gitea.run_number }}" "$STATUS" "$RUN_URL" "$BRANCH" "$COMMIT" "$ACTOR")"
curl -sS -H 'Content-Type: application/json' -d "{\"msgtype\":\"markdown\",\"markdown\":{\"content\":\"$MSG\"}}" "https://qyapi.weixin.qq.com/cgi-bin/webhook/send?key=${WEBHOOK_KEY}"

5
.idea/.gitignore generated vendored Normal file
View File

@@ -0,0 +1,5 @@
# 默认忽略的文件
/shelf/
/workspace.xml
# 基于编辑器的 HTTP 客户端请求
/httpRequests/

57
.idea/codeStyles/Project.xml generated Normal file
View File

@@ -0,0 +1,57 @@
<component name="ProjectCodeStyleConfiguration">
<code_scheme name="Project" version="173">
<HTMLCodeStyleSettings>
<option name="HTML_SPACE_INSIDE_EMPTY_TAG" value="true" />
</HTMLCodeStyleSettings>
<JSCodeStyleSettings version="0">
<option name="FORCE_SEMICOLON_STYLE" value="true" />
<option name="SPACE_BEFORE_FUNCTION_LEFT_PARENTH" value="false" />
<option name="FORCE_QUOTE_STYlE" value="true" />
<option name="ENFORCE_TRAILING_COMMA" value="Remove" />
<option name="SPACES_WITHIN_OBJECT_LITERAL_BRACES" value="true" />
<option name="SPACES_WITHIN_IMPORTS" value="true" />
</JSCodeStyleSettings>
<TypeScriptCodeStyleSettings version="0">
<option name="FORCE_SEMICOLON_STYLE" value="true" />
<option name="SPACE_BEFORE_FUNCTION_LEFT_PARENTH" value="false" />
<option name="FORCE_QUOTE_STYlE" value="true" />
<option name="ENFORCE_TRAILING_COMMA" value="Remove" />
<option name="SPACES_WITHIN_OBJECT_LITERAL_BRACES" value="true" />
<option name="SPACES_WITHIN_IMPORTS" value="true" />
</TypeScriptCodeStyleSettings>
<VueCodeStyleSettings>
<option name="INTERPOLATION_NEW_LINE_AFTER_START_DELIMITER" value="false" />
<option name="INTERPOLATION_NEW_LINE_BEFORE_END_DELIMITER" value="false" />
</VueCodeStyleSettings>
<codeStyleSettings language="HTML">
<option name="SOFT_MARGINS" value="80" />
<indentOptions>
<option name="INDENT_SIZE" value="2" />
<option name="CONTINUATION_INDENT_SIZE" value="2" />
<option name="TAB_SIZE" value="2" />
</indentOptions>
</codeStyleSettings>
<codeStyleSettings language="JavaScript">
<option name="SOFT_MARGINS" value="80" />
<indentOptions>
<option name="INDENT_SIZE" value="2" />
<option name="CONTINUATION_INDENT_SIZE" value="2" />
<option name="TAB_SIZE" value="2" />
</indentOptions>
</codeStyleSettings>
<codeStyleSettings language="TypeScript">
<option name="SOFT_MARGINS" value="80" />
<indentOptions>
<option name="INDENT_SIZE" value="2" />
<option name="CONTINUATION_INDENT_SIZE" value="2" />
<option name="TAB_SIZE" value="2" />
</indentOptions>
</codeStyleSettings>
<codeStyleSettings language="Vue">
<option name="SOFT_MARGINS" value="80" />
<indentOptions>
<option name="CONTINUATION_INDENT_SIZE" value="2" />
</indentOptions>
</codeStyleSettings>
</code_scheme>
</component>

5
.idea/codeStyles/codeStyleConfig.xml generated Normal file
View File

@@ -0,0 +1,5 @@
<component name="ProjectCodeStyleConfiguration">
<state>
<option name="USE_PER_PROJECT_SETTINGS" value="true" />
</state>
</component>

6
.idea/git_toolbox_blame.xml generated Normal file
View File

@@ -0,0 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="GitToolBoxBlameSettings">
<option name="version" value="2" />
</component>
</project>

View File

@@ -0,0 +1,6 @@
<component name="InspectionProjectProfileManager">
<profile version="1.0">
<option name="myName" value="Project Default" />
<inspection_tool class="Eslint" enabled="true" level="WARNING" enabled_by_default="true" />
</profile>
</component>

12
.idea/jdt-admin.iml generated Normal file
View File

@@ -0,0 +1,12 @@
<?xml version="1.0" encoding="UTF-8"?>
<module type="WEB_MODULE" version="4">
<component name="NewModuleRootManager">
<content url="file://$MODULE_DIR$">
<excludeFolder url="file://$MODULE_DIR$/.tmp" />
<excludeFolder url="file://$MODULE_DIR$/temp" />
<excludeFolder url="file://$MODULE_DIR$/tmp" />
</content>
<orderEntry type="inheritedJdk" />
<orderEntry type="sourceFolder" forTests="false" />
</component>
</module>

8
.idea/modules.xml generated Normal file
View File

@@ -0,0 +1,8 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="ProjectModuleManager">
<modules>
<module fileurl="file://$PROJECT_DIR$/.idea/jdt-admin.iml" filepath="$PROJECT_DIR$/.idea/jdt-admin.iml" />
</modules>
</component>
</project>

6
.idea/vcs.xml generated Normal file
View File

@@ -0,0 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="VcsDirectoryMappings">
<mapping directory="" vcs="Git" />
</component>
</project>

View File

@@ -2,32 +2,23 @@ export const OUTPUT_DIR = 'dist'
export const PROXY_CONFIG = { export const PROXY_CONFIG = {
/** /**
* @desc 替换匹配值 * @desc 主接口代理
* @请求路径 http://localhost:3100/api/user * @请求路径 http://localhost:3100/api/login
* @转发路径 http://localhost:8080/user * @转发路径 http://localhost:3000/api/login
*/ */
'/admin': { '/api': {
target: 'https://test.wanzhuanyongcheng.cn', target: 'https://test.wanzhuanyongcheng.cn',
changeOrigin: true, changeOrigin: true,
// rewrite: (path) => path.replace(new RegExp('^/api'), ''), rewrite: (path) => path.replace(/^\/api/, '/admin'),
}, },
/** /**
* @desc 不替换匹配值 * @desc 备用接口代理
* @请求路径 http://localhost:3100/api/v2/user * @请求路径 http://localhost:3100/api1/login
* @转发路径 http://localhost:8080/api/v2/user * @转发路径 http://localhost:3001/api/login
*/ */
// '/api/v2': { '/api1': {
// target: 'http://localhost:8080', target: 'https://api.gxwzwh.com',
// changeOrigin: true, changeOrigin: true,
// }, rewrite: (path) => path.replace(/^\/api1/, '/admin'),
/** },
* @desc 替换部分匹配值
* @请求路径 http://localhost:3100/api/v3/user
* @转发路径 http://localhost:8080/user
*/
// '/api/v3': {
// target: 'http://localhost:8080',
// changeOrigin: true,
// rewrite: (path) => path.replace(new RegExp('^/api'), ''),
// },
} }

View File

@@ -15,7 +15,6 @@
}, },
"lint-staged": { "lint-staged": {
"*.{js,vue}": [ "*.{js,vue}": [
"npx prettier --write --end-of-line lf .",
"eslint --ext .js,.vue ." "eslint --ext .js,.vue ."
] ]
}, },
@@ -33,45 +32,45 @@
}, },
"dependencies": { "dependencies": {
"@unocss/eslint-config": "^0.55.7", "@unocss/eslint-config": "^0.55.7",
"@vueuse/core": "^10.11.0", "@vueuse/core": "^10.11.1",
"@wangeditor/editor": "^5.1.23", "@wangeditor/editor": "^5.1.23",
"@wangeditor/editor-for-vue": "^5.1.12", "@wangeditor/editor-for-vue": "^5.1.12",
"axios": "^1.7.2", "axios": "^1.13.1",
"dayjs": "^1.11.11", "dayjs": "^1.11.19",
"echarts": "^5.5.1", "echarts": "^5.6.0",
"file-saver": "^2.0.5", "file-saver": "^2.0.5",
"jszip": "^3.10.1", "jszip": "^3.10.1",
"lodash-es": "^4.17.21", "lodash-es": "^4.17.21",
"md-editor-v3": "^4.17.3", "md-editor-v3": "^4.21.3",
"mockjs": "^1.1.0", "mockjs": "^1.1.0",
"pinia": "^2.1.7", "pinia": "^2.3.1",
"vite": "^4.5.3", "vite": "^4.5.14",
"vue": "3.3.4", "vue": "3.3.4",
"vue-echarts": "^6.7.3", "vue-echarts": "^6.7.3",
"vue-router": "^4.2.5", "vue-router": "^4.6.3",
"xlsx": "^0.18.5" "xlsx": "^0.18.5"
}, },
"devDependencies": { "devDependencies": {
"@commitlint/cli": "^17.8.1", "@commitlint/cli": "^17.8.1",
"@commitlint/config-conventional": "^17.8.1", "@commitlint/config-conventional": "^17.8.1",
"@iconify/json": "^2.2.228", "@iconify/json": "^2.2.402",
"@iconify/vue": "^4.1.2", "@iconify/vue": "^4.3.0",
"@unocss/preset-rem-to-px": "^0.55.7", "@unocss/preset-rem-to-px": "^0.55.7",
"@vitejs/plugin-vue": "^4.6.2", "@vitejs/plugin-vue": "^4.6.2",
"@vue/compiler-sfc": "^3.4.32", "@vue/compiler-sfc": "^3.5.22",
"@zclzone/eslint-config": "^0.0.4", "@zclzone/eslint-config": "^0.0.4",
"chalk": "^5.3.0", "chalk": "^5.6.2",
"commitizen": "^4.3.0", "commitizen": "^4.3.1",
"cz-conventional-changelog": "^3.3.0", "cz-conventional-changelog": "^3.3.0",
"cz-customizable": "^7.1.0", "cz-customizable": "^7.5.1",
"dotenv": "^16.4.5", "dotenv": "^16.6.1",
"esno": "^0.17.0", "esno": "^0.17.0",
"fs-extra": "^11.2.0", "fs-extra": "^11.3.2",
"husky": "^8.0.3", "husky": "^8.0.3",
"lint-staged": "^13.3.0", "lint-staged": "^13.3.0",
"naive-ui": "^2.39.0", "naive-ui": "^2.43.1",
"rollup-plugin-visualizer": "^5.12.0", "rollup-plugin-visualizer": "^5.14.0",
"sass": "^1.77.8", "sass": "^1.93.2",
"unocss": "0.55.0", "unocss": "0.55.0",
"unplugin-auto-import": "^0.16.7", "unplugin-auto-import": "^0.16.7",
"unplugin-icons": "^0.16.6", "unplugin-icons": "^0.16.6",

9441
pnpm-lock.yaml generated

File diff suppressed because it is too large Load Diff

View File

@@ -9,10 +9,14 @@ import { setupRouter } from '@/router'
import { setupStore } from '@/store' import { setupStore } from '@/store'
import App from './App.vue' import App from './App.vue'
import { setupNaiveDiscreteApi } from './utils' import { setupNaiveDiscreteApi } from './utils'
import { initApiEndpoint } from '@/utils/api-config'
async function setupApp() { async function setupApp() {
const app = createApp(App) const app = createApp(App)
// 初始化接口配置
initApiEndpoint()
setupStore(app) setupStore(app)
setupNaiveDiscreteApi() setupNaiveDiscreteApi()

View File

@@ -1,4 +1,5 @@
import { getToken, isNullOrWhitespace } from '@/utils' import { getToken, isNullOrWhitespace } from '@/utils'
import { addDynamicRoutes } from '@/router'
const WHITE_LIST = ['/login', '/404'] const WHITE_LIST = ['/login', '/404']
export function createPermissionGuard(router) { export function createPermissionGuard(router) {
@@ -14,7 +15,20 @@ export function createPermissionGuard(router) {
/** 有token的情况 */ /** 有token的情况 */
if (to.path === '/login') return { path: '/' } if (to.path === '/login') return { path: '/' }
// refreshAccessToken() // 确保动态路由已加载
if (token && !router.hasRoute('Dashboard')) {
try {
await addDynamicRoutes()
// 如果当前路径不存在,重定向到工作台
if (to.path !== '/' && !router.hasRoute(to.name)) {
return { path: '/workbench' }
}
} catch (error) {
console.error('动态路由加载失败:', error)
return { path: '/login' }
}
}
return true return true
}) })
} }

View File

@@ -30,11 +30,44 @@ export async function addDynamicRoutes() {
try { try {
const permissionStore = usePermissionStore() const permissionStore = usePermissionStore()
const accessRoutes = permissionStore.generateRoutes() const accessRoutes = permissionStore.generateRoutes()
// 确保路由按正确顺序添加
accessRoutes.forEach((route) => { accessRoutes.forEach((route) => {
!router.hasRoute(route.name) && router.addRoute(route) if (!router.hasRoute(route.name)) {
router.addRoute(route)
}
}) })
router.hasRoute(EMPTY_ROUTE.name) && router.removeRoute(EMPTY_ROUTE.name)
// 移除空路由添加404路由
if (router.hasRoute(EMPTY_ROUTE.name)) {
router.removeRoute(EMPTY_ROUTE.name)
}
router.addRoute(NOT_FOUND_ROUTE) router.addRoute(NOT_FOUND_ROUTE)
// 确保根路径重定向到工作台
// if (!router.hasRoute('workbench')) {
// const workbenchRoute = {
// name: 'workbench',
// path: '/',
// component: () => import('@/views/workbench/index.vue'),
// redirect: '/workbench',
// // children: [
// // {
// // name: 'Workbench',
// // path: 'workbench',
// // component: () => import('@/views/workbench/index.vue'),
// // meta: {
// // title: '工作台',
// // icon: 'mdi:index',
// // order: 0,
// // },
// // },
// // ],
// }
// router.addRoute(workbenchRoute)
// }
// console.log(router)
} catch (error) { } catch (error) {
console.error(error) console.error(error)
throw error throw error

View File

@@ -58,7 +58,7 @@ function filterAsyncRoutes(routes = [], firstRoute = true) {
const curRoute = { const curRoute = {
path: route.route, path: route.route,
name: route.name, name: route.route,
isHidden, isHidden,
meta, meta,
children: [], children: [],

View File

@@ -18,10 +18,7 @@ export const useUserStore = defineStore('user', {
return this.userInfo?.name return this.userInfo?.name
}, },
avatar() { avatar() {
return ( return this.userInfo?.avatar || 'https://v2.xxapi.cn/api/head?return=302'
this.userInfo?.avatar ||
'https://pic3.58cdn.com.cn/nowater/webim/big/n_v21bc7874294754e63a22b80febac9cf51.jpg'
)
}, },
role() { role() {
return this.userInfo?.role || [] return this.userInfo?.role || []

61
src/utils/api-config.js Normal file
View File

@@ -0,0 +1,61 @@
// 判断是否为开发环境
const isDev = import.meta.env.DEV
// API接口线路配置管理
export const API_ENDPOINTS = {
primary: {
name: '主要线路',
baseURL: import.meta.env.VITE_BASE_API,
timeout: 10000,
},
backup1: {
name: '备用线路',
baseURL: import.meta.env.VITE_BASE_API_1,
timeout: 10000,
},
}
// 调试信息
console.log('=== 多接口配置信息 ===')
console.log('当前环境:', isDev ? '开发环境' : '生产环境')
console.log('API配置:', API_ENDPOINTS)
console.log('环境变量 VITE_BASE_API:', import.meta.env.VITE_BASE_API)
console.log('环境变量 VITE_BASE_API_1:', import.meta.env.VITE_BASE_API_1)
console.log('是否使用代理:', import.meta.env.VITE_USE_PROXY)
// 当前使用的接口线路
let currentEndpoint = 'primary'
// 获取当前接口配置
export function getCurrentEndpoint() {
return {
key: currentEndpoint,
...API_ENDPOINTS[currentEndpoint],
}
}
// 设置当前接口
export function setCurrentEndpoint(endpoint) {
if (API_ENDPOINTS[endpoint]) {
currentEndpoint = endpoint
localStorage.setItem('api_endpoint', endpoint)
return true
}
return false
}
// 获取所有可用接口
export function getAvailableEndpoints() {
return Object.entries(API_ENDPOINTS).map(([key, config]) => ({
key,
...config,
}))
}
// 初始化时从本地存储恢复接口选择
export function initApiEndpoint() {
const savedEndpoint = localStorage.getItem('api_endpoint')
if (savedEndpoint && API_ENDPOINTS[savedEndpoint]) {
currentEndpoint = savedEndpoint
}
}

View File

@@ -1,5 +1,6 @@
import axios from 'axios' import axios from 'axios'
import { resReject, resResolve, reqReject, reqResolve } from './interceptors' import { resReject, resResolve, reqReject, reqResolve } from './interceptors'
import { getCurrentEndpoint, getAvailableEndpoints } from '../api-config'
export function createAxios(options = {}) { export function createAxios(options = {}) {
const defaultOptions = { const defaultOptions = {
@@ -14,6 +15,93 @@ export function createAxios(options = {}) {
return service return service
} }
export const request = createAxios({ // 创建支持多接口的请求实例
baseURL: import.meta.env.VITE_BASE_API, export function createMultiEndpointRequest() {
}) let instances = null
// 延迟创建axios实例
function ensureInstances() {
if (!instances) {
instances = {}
const endpoints = getAvailableEndpoints()
console.log('创建axios实例接口列表:', endpoints)
endpoints.forEach((endpoint) => {
console.log(`创建实例 ${endpoint.key}:`, endpoint.baseURL)
instances[endpoint.key] = createAxios({
baseURL: endpoint.baseURL,
timeout: endpoint.timeout,
})
})
}
return instances
}
return {
// 使用当前选中的接口发送请求
async request(config) {
const instances = ensureInstances()
const currentEndpoint = getCurrentEndpoint()
console.log('当前接口配置:', currentEndpoint)
console.log('可用实例:', Object.keys(instances))
const instance = instances[currentEndpoint.key]
if (!instance) {
throw new Error(`接口实例不存在: ${currentEndpoint.key}`)
}
console.log(`使用接口: ${currentEndpoint.name} (${currentEndpoint.baseURL})`)
console.log('请求配置:', config)
return await instance(config)
},
// 获取当前接口实例
getCurrentInstance() {
const instances = ensureInstances()
const currentEndpoint = getCurrentEndpoint()
return instances[currentEndpoint.key]
},
// 获取所有接口实例
getAllInstances() {
return ensureInstances()
},
}
}
// export const request = createAxios({
// baseURL: import.meta.env.VITE_BASE_API,
// })
// 支持多接口的请求实例
export const multiRequest = createMultiEndpointRequest()
// 创建自动适配多接口的request实例
const multiEndpointInstance = createMultiEndpointRequest()
// 创建支持axios方法的request实例
export const request = {
// 基础请求方法
request: (config) => multiEndpointInstance.request(config),
// 自动适配axios方法
get: (url, config = {}) => multiEndpointInstance.request({ method: 'get', url, ...config }),
post: (url, data, config = {}) =>
multiEndpointInstance.request({ method: 'post', url, data, ...config }),
put: (url, data, config = {}) =>
multiEndpointInstance.request({ method: 'put', url, data, ...config }),
delete: (url, config = {}) => multiEndpointInstance.request({ method: 'delete', url, ...config }),
patch: (url, data, config = {}) =>
multiEndpointInstance.request({ method: 'patch', url, data, ...config }),
head: (url, config = {}) => multiEndpointInstance.request({ method: 'head', url, ...config }),
options: (url, config = {}) =>
multiEndpointInstance.request({ method: 'options', url, ...config }),
// 获取当前接口实例用于直接访问axios实例
getCurrentInstance: () => multiEndpointInstance.getCurrentInstance(),
getAllInstances: () => multiEndpointInstance.getAllInstances(),
}

View File

@@ -369,7 +369,7 @@ const columns = ref([
window.open( window.open(
`${import.meta.env.VITE_MER_LOGIN_URL}?redirect=/workbench&type=${ `${import.meta.env.VITE_MER_LOGIN_URL}?redirect=/workbench&type=${
res.data.type res.data.type
}&tk=${res.data.token}` }&tk=${res.data.token}&api=${localStorage.getItem('api_endpoint')}`
) )
}, },
}, },

View File

@@ -1,5 +1,13 @@
import { request } from '@/utils' import { request, multiRequest } from '@/utils'
export default { export default {
login: (data) => request.post('/login', data, { noNeedToken: true }), login: (data) => request.post('/login', data, { noNeedToken: true }),
// 使用多接口的登录方法
loginWithMultiEndpoint: (data) =>
multiRequest.request({
method: 'post',
url: '/login',
data,
noNeedToken: true,
}),
} }

View File

@@ -14,7 +14,17 @@
<img src="@/assets/images/logo.png" height="50" class="mr-10" /> <img src="@/assets/images/logo.png" height="50" class="mr-10" />
{{ title }} {{ title }}
</h5> </h5>
<div mt-30> <!-- 接口线路选择 -->
<div mt-20>
<n-select
v-model:value="selectedEndpoint"
:options="endpointOptions"
placeholder="选择接口线路"
size="large"
@update:value="handleEndpointChange"
/>
</div>
<div mt-10>
<n-input <n-input
v-model:value="loginInfo.name" v-model:value="loginInfo.name"
autofocus autofocus
@@ -23,7 +33,7 @@
:maxlength="20" :maxlength="20"
/> />
</div> </div>
<div mt-30> <div mt-10>
<n-input <n-input
v-model:value="loginInfo.password" v-model:value="loginInfo.password"
class="h-50 items-center pl-10 text-16" class="h-50 items-center pl-10 text-16"
@@ -67,6 +77,12 @@ import { useStorage } from '@vueuse/core'
import bgImg from '@/assets/images/login_bg.webp' import bgImg from '@/assets/images/login_bg.webp'
import api from './api' import api from './api'
import { addDynamicRoutes } from '@/router' import { addDynamicRoutes } from '@/router'
import {
getAvailableEndpoints,
setCurrentEndpoint,
getCurrentEndpoint,
initApiEndpoint,
} from '@/utils/api-config'
const title = import.meta.env.VITE_TITLE const title = import.meta.env.VITE_TITLE
@@ -90,6 +106,61 @@ function initLoginInfo() {
const isRemember = useStorage('isRemember', false) const isRemember = useStorage('isRemember', false)
const loading = ref(false) const loading = ref(false)
// 接口线路相关
const selectedEndpoint = ref('primary')
const endpointOptions = ref([])
// 初始化接口配置
initApiEndpoint()
const currentEndpoint = getCurrentEndpoint()
selectedEndpoint.value = currentEndpoint.key
// 加载接口选项
function loadEndpointOptions() {
const endpoints = getAvailableEndpoints()
endpointOptions.value = endpoints.map((endpoint) => ({
label: endpoint.name,
value: endpoint.key,
}))
}
// 处理接口切换
function handleEndpointChange(value) {
if (setCurrentEndpoint(value)) {
selectedEndpoint.value = value
$message.success(`已切换到${endpointOptions.value.find((opt) => opt.value === value)?.label}`)
} else {
$message.error('接口切换失败')
}
}
// 初始化
onMounted(() => {
loadEndpointOptions()
})
// 获取第一个可用的路由页面
function getFirstAvailableRoute(menuData) {
if (!menuData || !Array.isArray(menuData)) return null
// 递归查找第一个type为2的路由页面路由
function findFirstPageRoute(routes) {
for (const route of routes) {
if (route.type === 2 && route.route) {
return route.route
}
if (route.subMenu && route.subMenu.length) {
const found = findFirstPageRoute(route.subMenu)
if (found) return found
}
}
return null
}
return findFirstPageRoute(menuData)
}
async function handleLogin() { async function handleLogin() {
const { name, password } = loginInfo.value const { name, password } = loginInfo.value
if (!name || !password) { if (!name || !password) {
@@ -99,7 +170,14 @@ async function handleLogin() {
try { try {
loading.value = true loading.value = true
$message.loading('正在验证...') $message.loading('正在验证...')
const res = await api.login({ phone: name, password: password.toString() })
console.log('开始登录请求...')
console.log('登录数据:', { phone: name, password: password.toString() })
console.log('当前选中接口:', selectedEndpoint.value)
const res = await api.loginWithMultiEndpoint({ phone: name, password: password.toString() })
console.log('登录响应:', res)
$message.success('登录成功') $message.success('登录成功')
window.localStorage.setItem('menu', JSON.stringify(res.data.auth)) window.localStorage.setItem('menu', JSON.stringify(res.data.auth))
setToken(res.data.token) setToken(res.data.token)
@@ -108,17 +186,23 @@ async function handleLogin() {
} else { } else {
lStorage.remove('loginInfo') lStorage.remove('loginInfo')
} }
// 先添加动态路由
await addDynamicRoutes() await addDynamicRoutes()
// console.log(query)
// 获取第一个可用的路由页面
const firstRoute = getFirstAvailableRoute(res.data.auth)
if (query.redirect) { if (query.redirect) {
const path = query.redirect const path = query.redirect
Reflect.deleteProperty(query, 'redirect') Reflect.deleteProperty(query, 'redirect')
router.push({ path, query }) router.push({ path, query })
} else { } else {
router.push('/workbench') // 跳转到第一个可用路由,如果没有则跳转到工作台
router.push(firstRoute || '/workbench')
} }
// router.push('/workbench')
} catch (error) { } catch (error) {
console.error('登录请求失败:', error)
$message.removeMessage() $message.removeMessage()
} }
loading.value = false loading.value = false

View File

@@ -58,9 +58,13 @@
value: 2, value: 2,
}, },
{ {
label: '小猪积分', label: '智多鑫积分',
value: 3, value: 3,
}, },
{
label: '渔乐潮玩积分',
value: 5,
},
]" ]"
:key="song.value" :key="song.value"
:value="song.value" :value="song.value"
@@ -182,12 +186,11 @@ const selectOptions = ref([
label: '商家名称', label: '商家名称',
}, },
]) ])
const columns = ref([ const columns = ref([
{ {
title: '订单号', title: '订单号',
align: 'center', align: 'center',
key: 'oid', key: 'jl_oid',
width: 200, width: 200,
fixed: 'left', fixed: 'left',
}, },

View File

@@ -13,6 +13,13 @@ export default defineConfig(({ command, mode }) => {
const viteEnv = convertEnv(env) const viteEnv = convertEnv(env)
const { VITE_PORT, VITE_PUBLIC_PATH, VITE_USE_PROXY, VITE_BASE_API, VITE_SENTRY } = viteEnv const { VITE_PORT, VITE_PUBLIC_PATH, VITE_USE_PROXY, VITE_BASE_API, VITE_SENTRY } = viteEnv
// 调试代理配置
console.log('=== Vite代理配置调试 ===')
console.log('VITE_USE_PROXY:', VITE_USE_PROXY)
console.log('VITE_BASE_API:', VITE_BASE_API)
console.log('PROXY_CONFIG:', PROXY_CONFIG)
console.log('所有环境变量:', viteEnv)
return { return {
base: VITE_PUBLIC_PATH || '/', base: VITE_PUBLIC_PATH || '/',
resolve: { resolve: {
@@ -26,12 +33,10 @@ export default defineConfig(({ command, mode }) => {
host: '0.0.0.0', host: '0.0.0.0',
port: VITE_PORT, port: VITE_PORT,
open: false, open: false,
proxy: VITE_USE_PROXY proxy: {
? { '/api1': PROXY_CONFIG['/api1'],
[VITE_BASE_API]: PROXY_CONFIG[VITE_BASE_API], '/api': PROXY_CONFIG['/api'],
'/api/v2': PROXY_CONFIG['/api/v2'], },
}
: undefined,
}, },
build: { build: {
target: 'es2015', target: 'es2015',