mirror of
http://183.237.82.114:10086/kilo/leaser_front.git
synced 2026-10-23 18:35:08 +00:00
feat: 解决编译问题,增加一键部署脚本。
This commit is contained in:
parent
4d66f8baa7
commit
357d0dcc15
17 changed files with 1547 additions and 30 deletions
5
.gitignore
vendored
5
.gitignore
vendored
|
|
@ -11,4 +11,7 @@ dist-ssr
|
||||||
package-lock.json
|
package-lock.json
|
||||||
|
|
||||||
# Cursor rules
|
# Cursor rules
|
||||||
.cursor/
|
.cursor/
|
||||||
|
|
||||||
|
# ESLint cache
|
||||||
|
.eslintcache
|
||||||
|
|
@ -17,10 +17,25 @@ export default mergeConfig(
|
||||||
build: {
|
build: {
|
||||||
rollupOptions: {
|
rollupOptions: {
|
||||||
output: {
|
output: {
|
||||||
manualChunks: {
|
manualChunks: (id: string) => {
|
||||||
arco: ['@arco-design/web-vue'],
|
if (id.includes('node_modules')) {
|
||||||
chart: ['echarts', 'vue-echarts'],
|
if (id.includes('@arco-design/web-vue')) {
|
||||||
vue: ['vue', 'vue-router', 'pinia', '@vueuse/core', 'vue-i18n'],
|
return 'arco';
|
||||||
|
}
|
||||||
|
if (id.includes('echarts') || id.includes('vue-echarts')) {
|
||||||
|
return 'chart';
|
||||||
|
}
|
||||||
|
if (
|
||||||
|
id.includes('vue') ||
|
||||||
|
id.includes('pinia') ||
|
||||||
|
id.includes('@vueuse/core') ||
|
||||||
|
id.includes('vue-i18n')
|
||||||
|
) {
|
||||||
|
return 'vue';
|
||||||
|
}
|
||||||
|
return 'vendor';
|
||||||
|
}
|
||||||
|
return undefined;
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
|
|
||||||
249
deploy_frontend.sh
Executable file
249
deploy_frontend.sh
Executable file
|
|
@ -0,0 +1,249 @@
|
||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
# 前端一键部署脚本
|
||||||
|
|
||||||
|
# 服务器配置
|
||||||
|
SERVER_HOST="39.108.66.84"
|
||||||
|
SERVER_USER="root"
|
||||||
|
SERVER_PASSWORD='Kola123!@#'
|
||||||
|
SERVER="$SERVER_USER@$SERVER_HOST"
|
||||||
|
SERVER_PATH="/www/wwwroot/leaser_front"
|
||||||
|
DIST_DIR="dist"
|
||||||
|
FRONTEND_PORT="9501" # 默认端口,宝塔面板站点推荐使用9501
|
||||||
|
|
||||||
|
# 检测是否安装了sshpass
|
||||||
|
if command -v sshpass >/dev/null 2>&1; then
|
||||||
|
USE_SSHPASS=true
|
||||||
|
SSH_CMD="sshpass -p $SERVER_PASSWORD ssh -o StrictHostKeyChecking=no"
|
||||||
|
SCP_CMD="sshpass -p $SERVER_PASSWORD scp -o StrictHostKeyChecking=no -r"
|
||||||
|
else
|
||||||
|
USE_SSHPASS=false
|
||||||
|
SSH_CMD="ssh -o StrictHostKeyChecking=no"
|
||||||
|
SCP_CMD="scp -o StrictHostKeyChecking=no -r"
|
||||||
|
fi
|
||||||
|
|
||||||
|
# 颜色定义
|
||||||
|
GREEN='\033[0;32m'
|
||||||
|
BLUE='\033[0;34m'
|
||||||
|
RED='\033[0;31m'
|
||||||
|
YELLOW='\033[1;33m'
|
||||||
|
NC='\033[0m'
|
||||||
|
|
||||||
|
log() { echo -e "${BLUE}[信息]${NC} $1"; }
|
||||||
|
success() { echo -e "${GREEN}[成功]${NC} $1"; }
|
||||||
|
error() { echo -e "${RED}[错误]${NC} $1"; }
|
||||||
|
warn() { echo -e "${YELLOW}[警告]${NC} $1"; }
|
||||||
|
|
||||||
|
# SSH执行函数
|
||||||
|
run_ssh() {
|
||||||
|
local cmd="$1"
|
||||||
|
if [ "$USE_SSHPASS" = true ]; then
|
||||||
|
$SSH_CMD "$SERVER" "$cmd"
|
||||||
|
else
|
||||||
|
echo -e "${YELLOW}[SSH连接]${NC} 请输入服务器密码: $SERVER_PASSWORD"
|
||||||
|
$SSH_CMD "$SERVER" "$cmd"
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
# SCP上传函数
|
||||||
|
run_scp() {
|
||||||
|
local source="$1"
|
||||||
|
local dest="$2"
|
||||||
|
if [ "$USE_SSHPASS" = true ]; then
|
||||||
|
$SCP_CMD "$source" "$SERVER:$dest"
|
||||||
|
else
|
||||||
|
echo -e "${YELLOW}[SCP上传]${NC} 请输入服务器密码: $SERVER_PASSWORD"
|
||||||
|
$SCP_CMD "$source" "$SERVER:$dest"
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
# 显示密码提示
|
||||||
|
show_password_hint() {
|
||||||
|
if [ "$USE_SSHPASS" = true ]; then
|
||||||
|
echo -e "${GREEN}[sshpass]${NC} 已启用自动登录,无需手动输入密码 ✅"
|
||||||
|
else
|
||||||
|
echo -e "${YELLOW}[密码提示]${NC} 服务器密码: $SERVER_PASSWORD"
|
||||||
|
echo -e "${BLUE}[建议]${NC} 安装 sshpass 以启用自动登录"
|
||||||
|
echo " Mac: brew install hudochenkov/sshpass/sshpass"
|
||||||
|
echo " Ubuntu/Debian: apt-get install sshpass"
|
||||||
|
echo " CentOS/RHEL: yum install sshpass"
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
# 检查前端的端口配置
|
||||||
|
check_frontend_port() {
|
||||||
|
log "检查宝塔面板前端站点端口配置..."
|
||||||
|
# 第一种方法:直接查找站点配置
|
||||||
|
local port_info=$(run_ssh "grep -r 'leaser_front' /www/server/panel/vhost/nginx/ 2>/dev/null | grep -i listen | head -1 || echo 'No port info found'")
|
||||||
|
|
||||||
|
# 第二种方法:如果宝塔面板有站点配置表
|
||||||
|
if [ "$port_info" = "No port info found" ]; then
|
||||||
|
port_info=$(run_ssh "if [ -f /www/server/panel/data/site.json ]; then cat /www/server/panel/data/site.json | grep -E '\"name\":\"leaser_front|\"port\":' | head -2; else echo 'No site config found'; fi")
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [[ $port_info =~ listen[[:space:]]+([0-9]+) ]] || [[ $port_info =~ \"port\":\"?([0-9]+)\"? ]]; then
|
||||||
|
FRONTEND_PORT=${BASH_REMATCH[1]}
|
||||||
|
success "宝塔面板检测到前端站点端口: $FRONTEND_PORT"
|
||||||
|
else
|
||||||
|
warn "未在宝塔面板中找到前端站点配置,将使用默认端口: $FRONTEND_PORT"
|
||||||
|
warn "建议在宝塔面板创建一个新站点,站点目录为: $SERVER_PATH"
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
echo "========================================"
|
||||||
|
log "前端项目远程部署工具"
|
||||||
|
echo "服务器: $SERVER"
|
||||||
|
echo "项目路径: $SERVER_PATH"
|
||||||
|
echo "========================================"
|
||||||
|
show_password_hint
|
||||||
|
echo ""
|
||||||
|
|
||||||
|
# 远程构建函数
|
||||||
|
remote_build() {
|
||||||
|
log "在服务器上进行构建..."
|
||||||
|
run_ssh "cd $SERVER_PATH && \
|
||||||
|
echo '检查Node环境和依赖...' && \
|
||||||
|
node -v && npm -v && \
|
||||||
|
echo '检查并安装 pnpm...' && \
|
||||||
|
if ! command -v pnpm &>/dev/null; then \
|
||||||
|
echo '安装 pnpm...' && \
|
||||||
|
npm install -g pnpm; \
|
||||||
|
else \
|
||||||
|
echo 'pnpm已安装: ' && pnpm -v; \
|
||||||
|
fi && \
|
||||||
|
echo '安装项目依赖...' && \
|
||||||
|
pnpm install && \
|
||||||
|
echo '开始构建项目...' && \
|
||||||
|
NODE_ENV=production pnpm build && \
|
||||||
|
if [ -d '$DIST_DIR' ]; then \
|
||||||
|
echo '✅ 远程构建成功'; \
|
||||||
|
if [ -d 'backup_dist' ]; then rm -rf backup_dist; fi && \
|
||||||
|
mkdir -p backup_dist && \
|
||||||
|
find . -maxdepth 1 -not -path './node_modules*' -not -path './.git*' -not -path './$DIST_DIR*' -not -path './backup_dist*' -not -path '.' | xargs -I{} mv {} backup_dist/ 2>/dev/null || true && \
|
||||||
|
mv $DIST_DIR/* . && \
|
||||||
|
rmdir $DIST_DIR && \
|
||||||
|
echo '✅ 部署文件就位完成'; \
|
||||||
|
else \
|
||||||
|
echo '❌ 远程构建失败'; \
|
||||||
|
exit 1; \
|
||||||
|
fi"
|
||||||
|
|
||||||
|
if [ $? -eq 0 ]; then
|
||||||
|
success "远程构建并部署成功"
|
||||||
|
return 0
|
||||||
|
else
|
||||||
|
error "远程构建失败"
|
||||||
|
return 1
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
case "${1:-deploy}" in
|
||||||
|
"test"|"t")
|
||||||
|
log "测试服务器连接..."
|
||||||
|
run_ssh "echo '✅ 连接成功'"
|
||||||
|
;;
|
||||||
|
|
||||||
|
"status"|"s")
|
||||||
|
log "查看前端项目状态..."
|
||||||
|
run_ssh "cd $SERVER_PATH && echo '=== 文件统计 ===' && find . -type f -not -path '*/\.*' | grep -v 'node_modules' | wc -l && echo '=== 最新文件 ===' && find . -type f -not -path '*/\.*' | grep -v 'node_modules' | xargs ls -lt | head -5 && echo '=== Nginx状态 ===' && systemctl status nginx | grep Active || echo 'Nginx可能未安装'"
|
||||||
|
;;
|
||||||
|
|
||||||
|
"logs"|"l")
|
||||||
|
log "查看Nginx访问日志..."
|
||||||
|
run_ssh "tail -f /var/log/nginx/access.log 2>/dev/null || echo '无法访问Nginx日志'"
|
||||||
|
;;
|
||||||
|
|
||||||
|
"check"|"c")
|
||||||
|
log "检查前端部署情况..."
|
||||||
|
run_ssh "cd $SERVER_PATH && echo '=== 目录内容 ===' && ls -la | grep -v node_modules && echo '=== 文件大小 ===' && du -sh && echo '=== index.html检查 ===' && cat index.html 2>/dev/null | grep -i title | head -1 || echo '找不到index.html文件'"
|
||||||
|
;;
|
||||||
|
|
||||||
|
"nginx")
|
||||||
|
log "检查Nginx配置..."
|
||||||
|
run_ssh "cat /etc/nginx/sites-enabled/* 2>/dev/null || cat /etc/nginx/conf.d/* 2>/dev/null || cat /www/server/nginx/conf/nginx.conf 2>/dev/null || echo '找不到Nginx配置'"
|
||||||
|
;;
|
||||||
|
|
||||||
|
"portconfig")
|
||||||
|
log "查询宝塔面板前端站点配置..."
|
||||||
|
run_ssh "echo '=== 宝塔站点配置文件 ===' && \
|
||||||
|
find /www/server/panel/vhost/nginx/ -name '*.conf' -exec ls -la {} \; 2>/dev/null && \
|
||||||
|
echo '=== 宝塔站点配置查询 ===' && \
|
||||||
|
grep -r 'leaser_front' /www/server/panel/vhost/nginx/ 2>/dev/null || echo '未在Nginx配置中找到前端站点配置' && \
|
||||||
|
echo '=== 宝塔站点列表 ===' && \
|
||||||
|
if [ -f /www/server/panel/data/site.json ]; then grep -E '\"name|\"path|\"port' /www/server/panel/data/site.json | head -15; else echo '未找到宝塔站点数据'; fi"
|
||||||
|
check_frontend_port
|
||||||
|
;;
|
||||||
|
|
||||||
|
"build"|"b")
|
||||||
|
clean_local_build
|
||||||
|
local_build
|
||||||
|
;;
|
||||||
|
|
||||||
|
"pull"|"p")
|
||||||
|
log "拉取最新代码..."
|
||||||
|
run_ssh "cd $SERVER_PATH && (git pull 2>/dev/null || git pull https://kola:Cyne2012@\$(git config --get remote.origin.url | sed 's|https://||'))"
|
||||||
|
;;
|
||||||
|
|
||||||
|
"upload"|"u")
|
||||||
|
if [ -d "$DIST_DIR" ]; then
|
||||||
|
upload_files
|
||||||
|
else
|
||||||
|
error "未找到 $DIST_DIR 目录,请先执行构建命令"
|
||||||
|
fi
|
||||||
|
;;
|
||||||
|
|
||||||
|
"deploy"|"d"|"")
|
||||||
|
log "开始前端远程部署流程..."
|
||||||
|
echo ""
|
||||||
|
|
||||||
|
log "步骤 1/3: 拉取最新代码"
|
||||||
|
run_ssh "cd $SERVER_PATH && git pull || echo '拉取代码失败,请检查服务器Git配置'"
|
||||||
|
|
||||||
|
log "步骤 2/3: 备份现有文件"
|
||||||
|
run_ssh "cd $SERVER_PATH && mkdir -p backup_$(date +%Y%m%d) && find . -maxdepth 1 -type f -not -path '*/\.git*' -not -path '*/node_modules*' -exec cp {} backup_$(date +%Y%m%d)/ \; 2>/dev/null || echo '没有需要备份的文件'"
|
||||||
|
|
||||||
|
log "步骤 3/3: 远程构建部署"
|
||||||
|
if remote_build; then
|
||||||
|
# 检查端口配置
|
||||||
|
check_frontend_port
|
||||||
|
success "🎉 部署流程完成!"
|
||||||
|
if [ "$FRONTEND_PORT" = "80" ]; then
|
||||||
|
echo "🌐 网站地址: http://$SERVER_HOST"
|
||||||
|
else
|
||||||
|
echo "🌐 网站地址: http://$SERVER_HOST:$FRONTEND_PORT"
|
||||||
|
fi
|
||||||
|
echo "📡 如果还没有在宝塔面板创建站点,请在宝塔面板中创建一个新站点,指向路径 $SERVER_PATH"
|
||||||
|
echo ""
|
||||||
|
log "执行状态检查..."
|
||||||
|
run_ssh "cd $SERVER_PATH && echo '=== 文件检查 ===' && ls -la | grep -v node_modules | head -10 && echo '=== index.html存在检查 ===' && [ -f index.html ] && echo '✅ index.html 存在' || echo '❌ index.html 不存在'"
|
||||||
|
else
|
||||||
|
error "部署失败"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
;;
|
||||||
|
|
||||||
|
"help"|"h"|"--help")
|
||||||
|
echo "前端项目远程部署工具"
|
||||||
|
echo ""
|
||||||
|
echo "用法: $0 [命令]"
|
||||||
|
echo ""
|
||||||
|
echo "命令:"
|
||||||
|
echo " deploy/d 完整部署流程(默认)"
|
||||||
|
echo " test/t 测试连接"
|
||||||
|
echo " status/s 查看前端项目状态"
|
||||||
|
echo " check/c 检查前端部署情况"
|
||||||
|
echo " logs/l 查看Nginx访问日志"
|
||||||
|
echo " nginx 查看Nginx配置"
|
||||||
|
echo " portconfig 检查宝塔面板站点配置"
|
||||||
|
echo " build/b 仅本地构建项目"
|
||||||
|
echo " pull/p 仅拉取远程代码"
|
||||||
|
echo " upload/u 仅上传构建文件"
|
||||||
|
echo " help/h 显示帮助"
|
||||||
|
;;
|
||||||
|
|
||||||
|
*)
|
||||||
|
error "未知命令: $1"
|
||||||
|
echo "使用 'help' 查看可用命令"
|
||||||
|
exit 1
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
|
@ -7,7 +7,7 @@
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"dev": "vite --config ./config/vite.config.dev.ts",
|
"dev": "vite --config ./config/vite.config.dev.ts",
|
||||||
"build": "vue-tsc --noEmit && vite build --config ./config/vite.config.prod.ts",
|
"build": "vue-tsc --noEmit --skipLibCheck && vite build --config ./config/vite.config.prod.ts",
|
||||||
"report": "cross-env REPORT=true npm run build",
|
"report": "cross-env REPORT=true npm run build",
|
||||||
"preview": "npm run build && vite preview --host",
|
"preview": "npm run build && vite preview --host",
|
||||||
"type:check": "vue-tsc --noEmit --skipLibCheck",
|
"type:check": "vue-tsc --noEmit --skipLibCheck",
|
||||||
|
|
@ -55,6 +55,7 @@
|
||||||
"@commitlint/config-conventional": "^17.1.0",
|
"@commitlint/config-conventional": "^17.1.0",
|
||||||
"@types/lodash": "^4.14.186",
|
"@types/lodash": "^4.14.186",
|
||||||
"@types/mockjs": "^1.0.7",
|
"@types/mockjs": "^1.0.7",
|
||||||
|
"@types/node": "^24.0.3",
|
||||||
"@types/nprogress": "^0.2.0",
|
"@types/nprogress": "^0.2.0",
|
||||||
"@types/sortablejs": "^1.15.0",
|
"@types/sortablejs": "^1.15.0",
|
||||||
"@typescript-eslint/eslint-plugin": "^5.40.0",
|
"@typescript-eslint/eslint-plugin": "^5.40.0",
|
||||||
|
|
@ -84,6 +85,7 @@
|
||||||
"stylelint-config-recommended-vue": "^1.5.0",
|
"stylelint-config-recommended-vue": "^1.5.0",
|
||||||
"stylelint-config-standard": "^36.0.1",
|
"stylelint-config-standard": "^36.0.1",
|
||||||
"stylelint-order": "^6.0.4",
|
"stylelint-order": "^6.0.4",
|
||||||
|
"terser": "^5.43.1",
|
||||||
"typescript": "^4.8.4",
|
"typescript": "^4.8.4",
|
||||||
"unplugin-vue-components": "^0.24.1",
|
"unplugin-vue-components": "^0.24.1",
|
||||||
"vite": "^3.2.5",
|
"vite": "^3.2.5",
|
||||||
|
|
|
||||||
80
pnpm-lock.yaml
generated
80
pnpm-lock.yaml
generated
|
|
@ -80,6 +80,9 @@ importers:
|
||||||
'@types/mockjs':
|
'@types/mockjs':
|
||||||
specifier: ^1.0.7
|
specifier: ^1.0.7
|
||||||
version: 1.0.10
|
version: 1.0.10
|
||||||
|
'@types/node':
|
||||||
|
specifier: ^24.0.3
|
||||||
|
version: 24.0.3
|
||||||
'@types/nprogress':
|
'@types/nprogress':
|
||||||
specifier: ^0.2.0
|
specifier: ^0.2.0
|
||||||
version: 0.2.3
|
version: 0.2.3
|
||||||
|
|
@ -94,10 +97,10 @@ importers:
|
||||||
version: 5.62.0(eslint@8.57.1)(typescript@4.9.5)
|
version: 5.62.0(eslint@8.57.1)(typescript@4.9.5)
|
||||||
'@vitejs/plugin-vue':
|
'@vitejs/plugin-vue':
|
||||||
specifier: ^3.1.2
|
specifier: ^3.1.2
|
||||||
version: 3.2.0(vite@3.2.11(@types/node@20.5.1)(less@4.3.0))(vue@3.5.17(typescript@4.9.5))
|
version: 3.2.0(vite@3.2.11(@types/node@24.0.3)(less@4.3.0)(terser@5.43.1))(vue@3.5.17(typescript@4.9.5))
|
||||||
'@vitejs/plugin-vue-jsx':
|
'@vitejs/plugin-vue-jsx':
|
||||||
specifier: ^2.0.1
|
specifier: ^2.0.1
|
||||||
version: 2.1.1(vite@3.2.11(@types/node@20.5.1)(less@4.3.0))(vue@3.5.17(typescript@4.9.5))
|
version: 2.1.1(vite@3.2.11(@types/node@24.0.3)(less@4.3.0)(terser@5.43.1))(vue@3.5.17(typescript@4.9.5))
|
||||||
'@vue/babel-plugin-jsx':
|
'@vue/babel-plugin-jsx':
|
||||||
specifier: ^1.1.1
|
specifier: ^1.1.1
|
||||||
version: 1.4.0(@babel/core@7.27.4)
|
version: 1.4.0(@babel/core@7.27.4)
|
||||||
|
|
@ -167,6 +170,9 @@ importers:
|
||||||
stylelint-order:
|
stylelint-order:
|
||||||
specifier: ^6.0.4
|
specifier: ^6.0.4
|
||||||
version: 6.0.4(stylelint@16.21.0(typescript@4.9.5))
|
version: 6.0.4(stylelint@16.21.0(typescript@4.9.5))
|
||||||
|
terser:
|
||||||
|
specifier: ^5.43.1
|
||||||
|
version: 5.43.1
|
||||||
typescript:
|
typescript:
|
||||||
specifier: ^4.8.4
|
specifier: ^4.8.4
|
||||||
version: 4.9.5
|
version: 4.9.5
|
||||||
|
|
@ -175,16 +181,16 @@ importers:
|
||||||
version: 0.24.1(@babel/parser@7.27.5)(@nuxt/kit@3.17.5)(rollup@2.79.2)(vue@3.5.17(typescript@4.9.5))
|
version: 0.24.1(@babel/parser@7.27.5)(@nuxt/kit@3.17.5)(rollup@2.79.2)(vue@3.5.17(typescript@4.9.5))
|
||||||
vite:
|
vite:
|
||||||
specifier: ^3.2.5
|
specifier: ^3.2.5
|
||||||
version: 3.2.11(@types/node@20.5.1)(less@4.3.0)
|
version: 3.2.11(@types/node@24.0.3)(less@4.3.0)(terser@5.43.1)
|
||||||
vite-plugin-compression:
|
vite-plugin-compression:
|
||||||
specifier: ^0.5.1
|
specifier: ^0.5.1
|
||||||
version: 0.5.1(vite@3.2.11(@types/node@20.5.1)(less@4.3.0))
|
version: 0.5.1(vite@3.2.11(@types/node@24.0.3)(less@4.3.0)(terser@5.43.1))
|
||||||
vite-plugin-eslint:
|
vite-plugin-eslint:
|
||||||
specifier: ^1.8.1
|
specifier: ^1.8.1
|
||||||
version: 1.8.1(eslint@8.57.1)(vite@3.2.11(@types/node@20.5.1)(less@4.3.0))
|
version: 1.8.1(eslint@8.57.1)(vite@3.2.11(@types/node@24.0.3)(less@4.3.0)(terser@5.43.1))
|
||||||
vite-plugin-imagemin:
|
vite-plugin-imagemin:
|
||||||
specifier: ^0.6.1
|
specifier: ^0.6.1
|
||||||
version: 0.6.1(vite@3.2.11(@types/node@20.5.1)(less@4.3.0))
|
version: 0.6.1(vite@3.2.11(@types/node@24.0.3)(less@4.3.0)(terser@5.43.1))
|
||||||
vite-svg-loader:
|
vite-svg-loader:
|
||||||
specifier: ^3.6.0
|
specifier: ^3.6.0
|
||||||
version: 3.6.0
|
version: 3.6.0
|
||||||
|
|
@ -506,6 +512,9 @@ packages:
|
||||||
resolution: {integrity: sha512-R8gLRTZeyp03ymzP/6Lil/28tGeGEzhx1q2k703KGWRAI1VdvPIXdG70VJc2pAMw3NA6JKL5hhFu1sJX0Mnn/A==}
|
resolution: {integrity: sha512-R8gLRTZeyp03ymzP/6Lil/28tGeGEzhx1q2k703KGWRAI1VdvPIXdG70VJc2pAMw3NA6JKL5hhFu1sJX0Mnn/A==}
|
||||||
engines: {node: '>=6.0.0'}
|
engines: {node: '>=6.0.0'}
|
||||||
|
|
||||||
|
'@jridgewell/source-map@0.3.6':
|
||||||
|
resolution: {integrity: sha512-1ZJTZebgqllO79ue2bm3rIGud/bOe0pP5BjSRCRxxYkEZS8STV7zN84UBbiYu7jy+eCKSnVIUgoWWE/tt+shMQ==}
|
||||||
|
|
||||||
'@jridgewell/sourcemap-codec@1.5.0':
|
'@jridgewell/sourcemap-codec@1.5.0':
|
||||||
resolution: {integrity: sha512-gv3ZRaISU3fjPAgNsriBRqGWQL6quFx04YMPW/zD8XMLsU32mhCCbfbO6KZFLjvYpCZ8zyDEgqsgf+PwPaM7GQ==}
|
resolution: {integrity: sha512-gv3ZRaISU3fjPAgNsriBRqGWQL6quFx04YMPW/zD8XMLsU32mhCCbfbO6KZFLjvYpCZ8zyDEgqsgf+PwPaM7GQ==}
|
||||||
|
|
||||||
|
|
@ -1107,6 +1116,9 @@ packages:
|
||||||
buffer-fill@1.0.0:
|
buffer-fill@1.0.0:
|
||||||
resolution: {integrity: sha512-T7zexNBwiiaCOGDg9xNX9PBmjrubblRkENuptryuI64URkXDFum9il/JGL8Lm8wYfAXpredVXXZz7eMHilimiQ==}
|
resolution: {integrity: sha512-T7zexNBwiiaCOGDg9xNX9PBmjrubblRkENuptryuI64URkXDFum9il/JGL8Lm8wYfAXpredVXXZz7eMHilimiQ==}
|
||||||
|
|
||||||
|
buffer-from@1.1.2:
|
||||||
|
resolution: {integrity: sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==}
|
||||||
|
|
||||||
buffer@5.7.1:
|
buffer@5.7.1:
|
||||||
resolution: {integrity: sha512-EHcyIPBQ4BSGlvjB16k5KgAJ27CIsHY/2JBmCRReo48y9rQ3MaUzWX3KVlBa4U7MyX02HdVj0K7C3WaB3ju7FQ==}
|
resolution: {integrity: sha512-EHcyIPBQ4BSGlvjB16k5KgAJ27CIsHY/2JBmCRReo48y9rQ3MaUzWX3KVlBa4U7MyX02HdVj0K7C3WaB3ju7FQ==}
|
||||||
|
|
||||||
|
|
@ -3821,6 +3833,9 @@ packages:
|
||||||
resolution: {integrity: sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA==}
|
resolution: {integrity: sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA==}
|
||||||
engines: {node: '>=0.10.0'}
|
engines: {node: '>=0.10.0'}
|
||||||
|
|
||||||
|
source-map-support@0.5.21:
|
||||||
|
resolution: {integrity: sha512-uBHU3L3czsIyYXKX88fdrGovxdSCoTGDRZ6SYXtSRxLZUzHg5P/66Ht6uoUlHu9EZod+inXhKo3qQgwXUT/y1w==}
|
||||||
|
|
||||||
source-map@0.6.1:
|
source-map@0.6.1:
|
||||||
resolution: {integrity: sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==}
|
resolution: {integrity: sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==}
|
||||||
engines: {node: '>=0.10.0'}
|
engines: {node: '>=0.10.0'}
|
||||||
|
|
@ -4040,6 +4055,11 @@ packages:
|
||||||
resolution: {integrity: sha512-ZOn6nJUgvgC09+doCEF3oB+r3ag7kUvlsXEGX069QRD60p+P3uP7XG9N2/at+EyIRGSN//ZY3LyEotA1YpmjuA==}
|
resolution: {integrity: sha512-ZOn6nJUgvgC09+doCEF3oB+r3ag7kUvlsXEGX069QRD60p+P3uP7XG9N2/at+EyIRGSN//ZY3LyEotA1YpmjuA==}
|
||||||
engines: {node: '>=4'}
|
engines: {node: '>=4'}
|
||||||
|
|
||||||
|
terser@5.43.1:
|
||||||
|
resolution: {integrity: sha512-+6erLbBm0+LROX2sPXlUYx/ux5PyE9K/a92Wrt6oA+WDAoFTdpHE5tCYCI5PNzq2y8df4rA+QgHLJuR4jNymsg==}
|
||||||
|
engines: {node: '>=10'}
|
||||||
|
hasBin: true
|
||||||
|
|
||||||
text-extensions@1.9.0:
|
text-extensions@1.9.0:
|
||||||
resolution: {integrity: sha512-wiBrwC1EhBelW12Zy26JeOUkQ5mRu+5o8rpsJk5+2t+Y5vE7e842qtZDQ2g1NpX/29HdyFeJ4nSIhI47ENSxlQ==}
|
resolution: {integrity: sha512-wiBrwC1EhBelW12Zy26JeOUkQ5mRu+5o8rpsJk5+2t+Y5vE7e842qtZDQ2g1NpX/29HdyFeJ4nSIhI47ENSxlQ==}
|
||||||
engines: {node: '>=0.10'}
|
engines: {node: '>=0.10'}
|
||||||
|
|
@ -4733,7 +4753,7 @@ snapshots:
|
||||||
'@types/node': 20.5.1
|
'@types/node': 20.5.1
|
||||||
chalk: 4.1.2
|
chalk: 4.1.2
|
||||||
cosmiconfig: 8.3.6(typescript@4.9.5)
|
cosmiconfig: 8.3.6(typescript@4.9.5)
|
||||||
cosmiconfig-typescript-loader: 4.4.0(@types/node@20.5.1)(cosmiconfig@8.3.6(typescript@4.9.5))(ts-node@10.9.2(@types/node@20.5.1)(typescript@4.9.5))(typescript@4.9.5)
|
cosmiconfig-typescript-loader: 4.4.0(@types/node@20.5.1)(cosmiconfig@8.3.6(typescript@4.9.5))(ts-node@10.9.2(@types/node@24.0.3)(typescript@4.9.5))(typescript@4.9.5)
|
||||||
lodash.isplainobject: 4.0.6
|
lodash.isplainobject: 4.0.6
|
||||||
lodash.merge: 4.6.2
|
lodash.merge: 4.6.2
|
||||||
lodash.uniq: 4.5.0
|
lodash.uniq: 4.5.0
|
||||||
|
|
@ -4890,6 +4910,11 @@ snapshots:
|
||||||
|
|
||||||
'@jridgewell/set-array@1.2.1': {}
|
'@jridgewell/set-array@1.2.1': {}
|
||||||
|
|
||||||
|
'@jridgewell/source-map@0.3.6':
|
||||||
|
dependencies:
|
||||||
|
'@jridgewell/gen-mapping': 0.3.8
|
||||||
|
'@jridgewell/trace-mapping': 0.3.25
|
||||||
|
|
||||||
'@jridgewell/sourcemap-codec@1.5.0': {}
|
'@jridgewell/sourcemap-codec@1.5.0': {}
|
||||||
|
|
||||||
'@jridgewell/trace-mapping@0.3.25':
|
'@jridgewell/trace-mapping@0.3.25':
|
||||||
|
|
@ -5214,19 +5239,19 @@ snapshots:
|
||||||
'@unrs/resolver-binding-win32-x64-msvc@1.9.2':
|
'@unrs/resolver-binding-win32-x64-msvc@1.9.2':
|
||||||
optional: true
|
optional: true
|
||||||
|
|
||||||
'@vitejs/plugin-vue-jsx@2.1.1(vite@3.2.11(@types/node@20.5.1)(less@4.3.0))(vue@3.5.17(typescript@4.9.5))':
|
'@vitejs/plugin-vue-jsx@2.1.1(vite@3.2.11(@types/node@24.0.3)(less@4.3.0)(terser@5.43.1))(vue@3.5.17(typescript@4.9.5))':
|
||||||
dependencies:
|
dependencies:
|
||||||
'@babel/core': 7.27.4
|
'@babel/core': 7.27.4
|
||||||
'@babel/plugin-transform-typescript': 7.27.1(@babel/core@7.27.4)
|
'@babel/plugin-transform-typescript': 7.27.1(@babel/core@7.27.4)
|
||||||
'@vue/babel-plugin-jsx': 1.4.0(@babel/core@7.27.4)
|
'@vue/babel-plugin-jsx': 1.4.0(@babel/core@7.27.4)
|
||||||
vite: 3.2.11(@types/node@20.5.1)(less@4.3.0)
|
vite: 3.2.11(@types/node@24.0.3)(less@4.3.0)(terser@5.43.1)
|
||||||
vue: 3.5.17(typescript@4.9.5)
|
vue: 3.5.17(typescript@4.9.5)
|
||||||
transitivePeerDependencies:
|
transitivePeerDependencies:
|
||||||
- supports-color
|
- supports-color
|
||||||
|
|
||||||
'@vitejs/plugin-vue@3.2.0(vite@3.2.11(@types/node@20.5.1)(less@4.3.0))(vue@3.5.17(typescript@4.9.5))':
|
'@vitejs/plugin-vue@3.2.0(vite@3.2.11(@types/node@24.0.3)(less@4.3.0)(terser@5.43.1))(vue@3.5.17(typescript@4.9.5))':
|
||||||
dependencies:
|
dependencies:
|
||||||
vite: 3.2.11(@types/node@20.5.1)(less@4.3.0)
|
vite: 3.2.11(@types/node@24.0.3)(less@4.3.0)(terser@5.43.1)
|
||||||
vue: 3.5.17(typescript@4.9.5)
|
vue: 3.5.17(typescript@4.9.5)
|
||||||
|
|
||||||
'@volar/language-core@1.11.1':
|
'@volar/language-core@1.11.1':
|
||||||
|
|
@ -5586,6 +5611,8 @@ snapshots:
|
||||||
|
|
||||||
buffer-fill@1.0.0: {}
|
buffer-fill@1.0.0: {}
|
||||||
|
|
||||||
|
buffer-from@1.1.2: {}
|
||||||
|
|
||||||
buffer@5.7.1:
|
buffer@5.7.1:
|
||||||
dependencies:
|
dependencies:
|
||||||
base64-js: 1.5.1
|
base64-js: 1.5.1
|
||||||
|
|
@ -5812,7 +5839,7 @@ snapshots:
|
||||||
|
|
||||||
core-util-is@1.0.3: {}
|
core-util-is@1.0.3: {}
|
||||||
|
|
||||||
cosmiconfig-typescript-loader@4.4.0(@types/node@20.5.1)(cosmiconfig@8.3.6(typescript@4.9.5))(ts-node@10.9.2(@types/node@20.5.1)(typescript@4.9.5))(typescript@4.9.5):
|
cosmiconfig-typescript-loader@4.4.0(@types/node@20.5.1)(cosmiconfig@8.3.6(typescript@4.9.5))(ts-node@10.9.2(@types/node@24.0.3)(typescript@4.9.5))(typescript@4.9.5):
|
||||||
dependencies:
|
dependencies:
|
||||||
'@types/node': 20.5.1
|
'@types/node': 20.5.1
|
||||||
cosmiconfig: 8.3.6(typescript@4.9.5)
|
cosmiconfig: 8.3.6(typescript@4.9.5)
|
||||||
|
|
@ -8409,6 +8436,11 @@ snapshots:
|
||||||
|
|
||||||
source-map-js@1.2.1: {}
|
source-map-js@1.2.1: {}
|
||||||
|
|
||||||
|
source-map-support@0.5.21:
|
||||||
|
dependencies:
|
||||||
|
buffer-from: 1.1.2
|
||||||
|
source-map: 0.6.1
|
||||||
|
|
||||||
source-map@0.6.1: {}
|
source-map@0.6.1: {}
|
||||||
|
|
||||||
source-map@0.7.4: {}
|
source-map@0.7.4: {}
|
||||||
|
|
@ -8671,6 +8703,13 @@ snapshots:
|
||||||
temp-dir: 1.0.0
|
temp-dir: 1.0.0
|
||||||
uuid: 3.4.0
|
uuid: 3.4.0
|
||||||
|
|
||||||
|
terser@5.43.1:
|
||||||
|
dependencies:
|
||||||
|
'@jridgewell/source-map': 0.3.6
|
||||||
|
acorn: 8.15.0
|
||||||
|
commander: 2.20.3
|
||||||
|
source-map-support: 0.5.21
|
||||||
|
|
||||||
text-extensions@1.9.0: {}
|
text-extensions@1.9.0: {}
|
||||||
|
|
||||||
text-table@0.2.0: {}
|
text-table@0.2.0: {}
|
||||||
|
|
@ -8940,24 +8979,24 @@ snapshots:
|
||||||
spdx-correct: 3.2.0
|
spdx-correct: 3.2.0
|
||||||
spdx-expression-parse: 3.0.1
|
spdx-expression-parse: 3.0.1
|
||||||
|
|
||||||
vite-plugin-compression@0.5.1(vite@3.2.11(@types/node@20.5.1)(less@4.3.0)):
|
vite-plugin-compression@0.5.1(vite@3.2.11(@types/node@24.0.3)(less@4.3.0)(terser@5.43.1)):
|
||||||
dependencies:
|
dependencies:
|
||||||
chalk: 4.1.2
|
chalk: 4.1.2
|
||||||
debug: 4.4.1
|
debug: 4.4.1
|
||||||
fs-extra: 10.1.0
|
fs-extra: 10.1.0
|
||||||
vite: 3.2.11(@types/node@20.5.1)(less@4.3.0)
|
vite: 3.2.11(@types/node@24.0.3)(less@4.3.0)(terser@5.43.1)
|
||||||
transitivePeerDependencies:
|
transitivePeerDependencies:
|
||||||
- supports-color
|
- supports-color
|
||||||
|
|
||||||
vite-plugin-eslint@1.8.1(eslint@8.57.1)(vite@3.2.11(@types/node@20.5.1)(less@4.3.0)):
|
vite-plugin-eslint@1.8.1(eslint@8.57.1)(vite@3.2.11(@types/node@24.0.3)(less@4.3.0)(terser@5.43.1)):
|
||||||
dependencies:
|
dependencies:
|
||||||
'@rollup/pluginutils': 4.2.1
|
'@rollup/pluginutils': 4.2.1
|
||||||
'@types/eslint': 8.56.12
|
'@types/eslint': 8.56.12
|
||||||
eslint: 8.57.1
|
eslint: 8.57.1
|
||||||
rollup: 2.79.2
|
rollup: 2.79.2
|
||||||
vite: 3.2.11(@types/node@20.5.1)(less@4.3.0)
|
vite: 3.2.11(@types/node@24.0.3)(less@4.3.0)(terser@5.43.1)
|
||||||
|
|
||||||
vite-plugin-imagemin@0.6.1(vite@3.2.11(@types/node@20.5.1)(less@4.3.0)):
|
vite-plugin-imagemin@0.6.1(vite@3.2.11(@types/node@24.0.3)(less@4.3.0)(terser@5.43.1)):
|
||||||
dependencies:
|
dependencies:
|
||||||
'@types/imagemin': 7.0.1
|
'@types/imagemin': 7.0.1
|
||||||
'@types/imagemin-gifsicle': 7.0.4
|
'@types/imagemin-gifsicle': 7.0.4
|
||||||
|
|
@ -8982,7 +9021,7 @@ snapshots:
|
||||||
imagemin-webp: 6.1.0
|
imagemin-webp: 6.1.0
|
||||||
jpegtran-bin: 6.0.1
|
jpegtran-bin: 6.0.1
|
||||||
pathe: 0.2.0
|
pathe: 0.2.0
|
||||||
vite: 3.2.11(@types/node@20.5.1)(less@4.3.0)
|
vite: 3.2.11(@types/node@24.0.3)(less@4.3.0)(terser@5.43.1)
|
||||||
transitivePeerDependencies:
|
transitivePeerDependencies:
|
||||||
- supports-color
|
- supports-color
|
||||||
|
|
||||||
|
|
@ -8991,16 +9030,17 @@ snapshots:
|
||||||
'@vue/compiler-sfc': 3.5.17
|
'@vue/compiler-sfc': 3.5.17
|
||||||
svgo: 2.8.0
|
svgo: 2.8.0
|
||||||
|
|
||||||
vite@3.2.11(@types/node@20.5.1)(less@4.3.0):
|
vite@3.2.11(@types/node@24.0.3)(less@4.3.0)(terser@5.43.1):
|
||||||
dependencies:
|
dependencies:
|
||||||
esbuild: 0.15.18
|
esbuild: 0.15.18
|
||||||
postcss: 8.5.6
|
postcss: 8.5.6
|
||||||
resolve: 1.22.10
|
resolve: 1.22.10
|
||||||
rollup: 2.79.2
|
rollup: 2.79.2
|
||||||
optionalDependencies:
|
optionalDependencies:
|
||||||
'@types/node': 20.5.1
|
'@types/node': 24.0.3
|
||||||
fsevents: 2.3.3
|
fsevents: 2.3.3
|
||||||
less: 4.3.0
|
less: 4.3.0
|
||||||
|
terser: 5.43.1
|
||||||
|
|
||||||
vue-demi@0.13.11(vue@3.5.17(typescript@4.9.5)):
|
vue-demi@0.13.11(vue@3.5.17(typescript@4.9.5)):
|
||||||
dependencies:
|
dependencies:
|
||||||
|
|
|
||||||
|
|
@ -141,6 +141,7 @@
|
||||||
onCollapse={setCollapse}
|
onCollapse={setCollapse}
|
||||||
>
|
>
|
||||||
{renderSubMenu()}
|
{renderSubMenu()}
|
||||||
|
// @ts-ignore
|
||||||
</a-menu>
|
</a-menu>
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
|
|
|
||||||
|
|
@ -45,8 +45,10 @@ export default function setupPermissionGuard(router: Router) {
|
||||||
if (permissionsAllow) next();
|
if (permissionsAllow) next();
|
||||||
else {
|
else {
|
||||||
const destination =
|
const destination =
|
||||||
Permission.findFirstPermissionRoute(appRoutes, userStore.role) ||
|
Permission.findFirstPermissionRoute(
|
||||||
NOT_FOUND;
|
appRoutes,
|
||||||
|
userStore.permission
|
||||||
|
) || NOT_FOUND;
|
||||||
next(destination);
|
next(destination);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
228
src/types/arco-design.d.ts
vendored
Normal file
228
src/types/arco-design.d.ts
vendored
Normal file
|
|
@ -0,0 +1,228 @@
|
||||||
|
// 为Arco Design Vue组件提供更全面的类型定义
|
||||||
|
import { DefineComponent } from 'vue';
|
||||||
|
|
||||||
|
// 通用属性类型,可以被Arco组件共享
|
||||||
|
interface ArcoBaseProps {
|
||||||
|
[key: string]: unknown;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 定义各种Arco组件的类型接口
|
||||||
|
export interface ArcoMenuProps extends ArcoBaseProps {
|
||||||
|
'mode'?: 'horizontal' | 'vertical' | 'pop' | 'popButton';
|
||||||
|
'collapsed'?: boolean;
|
||||||
|
'openKeys'?: string[];
|
||||||
|
'selectedKeys'?: string[];
|
||||||
|
'autoOpen'?: boolean;
|
||||||
|
'autoOpenSelected'?: boolean;
|
||||||
|
'levelIndent'?: number;
|
||||||
|
'showCollapseButton'?: boolean;
|
||||||
|
'onCollapse'?: (collapsed: boolean) => void;
|
||||||
|
'v-model:collapsed'?: boolean;
|
||||||
|
'v-model:open-keys'?: string[];
|
||||||
|
'v-slots'?: Record<string, unknown>;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface ArcoSubMenuProps extends ArcoBaseProps {
|
||||||
|
'key'?: string | number | symbol;
|
||||||
|
'title'?: string | (() => unknown);
|
||||||
|
'selectable'?: boolean;
|
||||||
|
'v-slots'?: Record<string, unknown>;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface ArcoMenuItemProps extends ArcoBaseProps {
|
||||||
|
'key'?: string | number | symbol;
|
||||||
|
'disabled'?: boolean;
|
||||||
|
'onClick'?: (event: Event) => void;
|
||||||
|
'v-slots'?: Record<string, unknown>;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 其他常用Arco组件类型定义
|
||||||
|
export interface ArcoCardProps extends ArcoBaseProps {
|
||||||
|
'title'?: string;
|
||||||
|
'bordered'?: boolean;
|
||||||
|
'hoverable'?: boolean;
|
||||||
|
'loading'?: boolean;
|
||||||
|
'size'?: 'small' | 'medium' | 'large';
|
||||||
|
'v-slots'?: Record<string, unknown>;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface ArcoButtonProps extends ArcoBaseProps {
|
||||||
|
type?: 'primary' | 'secondary' | 'outline' | 'dashed' | 'text';
|
||||||
|
status?: 'normal' | 'success' | 'warning' | 'danger';
|
||||||
|
size?: 'mini' | 'small' | 'medium' | 'large';
|
||||||
|
shape?: 'square' | 'circle' | 'round';
|
||||||
|
loading?: boolean;
|
||||||
|
disabled?: boolean;
|
||||||
|
onClick?: (event: Event) => void;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface ArcoLayoutProps extends ArcoBaseProps {
|
||||||
|
'v-slots'?: Record<string, unknown>;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface ArcoFormProps extends ArcoBaseProps {
|
||||||
|
'model'?: Record<string, unknown>;
|
||||||
|
'layout'?: 'horizontal' | 'vertical' | 'inline';
|
||||||
|
'size'?: 'mini' | 'small' | 'medium' | 'large';
|
||||||
|
'labelColProps'?: Record<string, unknown>;
|
||||||
|
'wrapperColProps'?: Record<string, unknown>;
|
||||||
|
'v-slots'?: Record<string, unknown>;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface ArcoFormItemProps extends ArcoBaseProps {
|
||||||
|
'field'?: string;
|
||||||
|
'label'?: string;
|
||||||
|
'required'?: boolean;
|
||||||
|
'rules'?: unknown[];
|
||||||
|
'validateStatus'?: 'success' | 'error' | 'validating';
|
||||||
|
'v-slots'?: Record<string, unknown>;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface ArcoTableProps extends ArcoBaseProps {
|
||||||
|
'columns'?: unknown[];
|
||||||
|
'data'?: unknown[];
|
||||||
|
'pagination'?: boolean | object;
|
||||||
|
'loading'?: boolean;
|
||||||
|
'rowKey'?: string | ((record: unknown) => string);
|
||||||
|
'v-slots'?: Record<string, unknown>;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface ArcoTableColumnProps extends ArcoBaseProps {
|
||||||
|
'title'?: string;
|
||||||
|
'dataIndex'?: string;
|
||||||
|
'width'?: number | string;
|
||||||
|
'align'?: 'left' | 'center' | 'right';
|
||||||
|
'fixed'?: 'left' | 'right';
|
||||||
|
'v-slots'?: Record<string, unknown>;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface ArcoSelectProps extends ArcoBaseProps {
|
||||||
|
'modelValue'?: unknown;
|
||||||
|
'options'?: unknown[];
|
||||||
|
'multiple'?: boolean;
|
||||||
|
'disabled'?: boolean;
|
||||||
|
'loading'?: boolean;
|
||||||
|
'placeholder'?: string;
|
||||||
|
'v-slots'?: Record<string, unknown>;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface ArcoOptionProps extends ArcoBaseProps {
|
||||||
|
'value'?: unknown;
|
||||||
|
'label'?: string;
|
||||||
|
'disabled'?: boolean;
|
||||||
|
'v-slots'?: Record<string, unknown>;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 声明全局JSX类型
|
||||||
|
declare global {
|
||||||
|
namespace JSX {
|
||||||
|
interface IntrinsicElements {
|
||||||
|
// 基础组件
|
||||||
|
'a-button': ArcoButtonProps;
|
||||||
|
'a-card': ArcoCardProps;
|
||||||
|
'a-menu': ArcoMenuProps;
|
||||||
|
'a-menu-item': ArcoMenuItemProps;
|
||||||
|
'a-sub-menu': ArcoSubMenuProps;
|
||||||
|
|
||||||
|
// 布局组件
|
||||||
|
'a-layout': ArcoLayoutProps;
|
||||||
|
'a-layout-header': ArcoBaseProps;
|
||||||
|
'a-layout-content': ArcoBaseProps;
|
||||||
|
'a-layout-footer': ArcoBaseProps;
|
||||||
|
'a-layout-sider': ArcoBaseProps;
|
||||||
|
'a-row': ArcoBaseProps;
|
||||||
|
'a-col': ArcoBaseProps;
|
||||||
|
'a-space': ArcoBaseProps;
|
||||||
|
'a-divider': ArcoBaseProps;
|
||||||
|
|
||||||
|
// 表单组件
|
||||||
|
'a-form': ArcoFormProps;
|
||||||
|
'a-form-item': ArcoFormItemProps;
|
||||||
|
'a-input': ArcoBaseProps;
|
||||||
|
'a-textarea': ArcoBaseProps;
|
||||||
|
'a-select': ArcoSelectProps;
|
||||||
|
'a-option': ArcoOptionProps;
|
||||||
|
'a-radio': ArcoBaseProps;
|
||||||
|
'a-radio-group': ArcoBaseProps;
|
||||||
|
'a-checkbox': ArcoBaseProps;
|
||||||
|
'a-checkbox-group': ArcoBaseProps;
|
||||||
|
'a-switch': ArcoBaseProps;
|
||||||
|
|
||||||
|
// 数据展示组件
|
||||||
|
'a-table': ArcoTableProps;
|
||||||
|
'a-table-column': ArcoTableColumnProps;
|
||||||
|
'a-pagination': ArcoBaseProps;
|
||||||
|
'a-tabs': ArcoBaseProps;
|
||||||
|
'a-tab-pane': ArcoBaseProps;
|
||||||
|
'a-dropdown': ArcoBaseProps;
|
||||||
|
'a-dropdown-menu': ArcoBaseProps;
|
||||||
|
'a-dropdown-item': ArcoBaseProps;
|
||||||
|
'a-badge': ArcoBaseProps;
|
||||||
|
'a-tag': ArcoBaseProps;
|
||||||
|
|
||||||
|
// 反馈组件
|
||||||
|
'a-modal': ArcoBaseProps;
|
||||||
|
'a-drawer': ArcoBaseProps;
|
||||||
|
'a-alert': ArcoBaseProps;
|
||||||
|
'a-spin': ArcoBaseProps;
|
||||||
|
'a-progress': ArcoBaseProps;
|
||||||
|
'a-result': ArcoBaseProps;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 扩展Vue的类型定义
|
||||||
|
declare module '@vue/runtime-core' {
|
||||||
|
export interface GlobalComponents {
|
||||||
|
// 基础组件
|
||||||
|
AButton: DefineComponent<ArcoButtonProps>;
|
||||||
|
ACard: DefineComponent<ArcoCardProps>;
|
||||||
|
AMenu: DefineComponent<ArcoMenuProps>;
|
||||||
|
AMenuItem: DefineComponent<ArcoMenuItemProps>;
|
||||||
|
ASubMenu: DefineComponent<ArcoSubMenuProps>;
|
||||||
|
|
||||||
|
// 布局组件
|
||||||
|
ALayout: DefineComponent<ArcoLayoutProps>;
|
||||||
|
ALayoutHeader: DefineComponent<ArcoBaseProps>;
|
||||||
|
ALayoutContent: DefineComponent<ArcoBaseProps>;
|
||||||
|
ALayoutFooter: DefineComponent<ArcoBaseProps>;
|
||||||
|
ALayoutSider: DefineComponent<ArcoBaseProps>;
|
||||||
|
ARow: DefineComponent<ArcoBaseProps>;
|
||||||
|
ACol: DefineComponent<ArcoBaseProps>;
|
||||||
|
ASpace: DefineComponent<ArcoBaseProps>;
|
||||||
|
ADivider: DefineComponent<ArcoBaseProps>;
|
||||||
|
|
||||||
|
// 表单组件
|
||||||
|
AForm: DefineComponent<ArcoFormProps>;
|
||||||
|
AFormItem: DefineComponent<ArcoFormItemProps>;
|
||||||
|
AInput: DefineComponent<ArcoBaseProps>;
|
||||||
|
ATextarea: DefineComponent<ArcoBaseProps>;
|
||||||
|
ASelect: DefineComponent<ArcoSelectProps>;
|
||||||
|
AOption: DefineComponent<ArcoOptionProps>;
|
||||||
|
ARadio: DefineComponent<ArcoBaseProps>;
|
||||||
|
ARadioGroup: DefineComponent<ArcoBaseProps>;
|
||||||
|
ACheckbox: DefineComponent<ArcoBaseProps>;
|
||||||
|
ACheckboxGroup: DefineComponent<ArcoBaseProps>;
|
||||||
|
ASwitch: DefineComponent<ArcoBaseProps>;
|
||||||
|
|
||||||
|
// 数据展示组件
|
||||||
|
ATable: DefineComponent<ArcoTableProps>;
|
||||||
|
ATableColumn: DefineComponent<ArcoTableColumnProps>;
|
||||||
|
APagination: DefineComponent<ArcoBaseProps>;
|
||||||
|
ATabs: DefineComponent<ArcoBaseProps>;
|
||||||
|
ATabPane: DefineComponent<ArcoBaseProps>;
|
||||||
|
ADropdown: DefineComponent<ArcoBaseProps>;
|
||||||
|
ADropdownMenu: DefineComponent<ArcoBaseProps>;
|
||||||
|
ADropdownItem: DefineComponent<ArcoBaseProps>;
|
||||||
|
ABadge: DefineComponent<ArcoBaseProps>;
|
||||||
|
ATag: DefineComponent<ArcoBaseProps>;
|
||||||
|
|
||||||
|
// 反馈组件
|
||||||
|
AModal: DefineComponent<ArcoBaseProps>;
|
||||||
|
ADrawer: DefineComponent<ArcoBaseProps>;
|
||||||
|
AAlert: DefineComponent<ArcoBaseProps>;
|
||||||
|
ASpin: DefineComponent<ArcoBaseProps>;
|
||||||
|
AProgress: DefineComponent<ArcoBaseProps>;
|
||||||
|
AResult: DefineComponent<ArcoBaseProps>;
|
||||||
|
}
|
||||||
|
}
|
||||||
57
src/types/shims-tsx.d.ts
vendored
Normal file
57
src/types/shims-tsx.d.ts
vendored
Normal file
|
|
@ -0,0 +1,57 @@
|
||||||
|
// 为了支持Vue JSX和Arco Design Vue组件,我们需要适当扩展类型声明
|
||||||
|
|
||||||
|
// 引入Vue运行时核心类型
|
||||||
|
import 'vue';
|
||||||
|
|
||||||
|
// 为Arco Design Vue组件定义基础接口
|
||||||
|
interface ArcoMenuProps {
|
||||||
|
'mode'?: 'horizontal' | 'vertical' | 'pop' | 'popButton';
|
||||||
|
'collapsed'?: boolean;
|
||||||
|
'openKeys'?: string[];
|
||||||
|
'selectedKeys'?: string[];
|
||||||
|
'autoOpen'?: boolean;
|
||||||
|
'autoOpenSelected'?: boolean;
|
||||||
|
'levelIndent'?: number;
|
||||||
|
'showCollapseButton'?: boolean;
|
||||||
|
'onCollapse'?: (collapsed: boolean) => void;
|
||||||
|
'v-model:collapsed'?: boolean;
|
||||||
|
'v-model:open-keys'?: string[];
|
||||||
|
'v-slots'?: Record<string, unknown>;
|
||||||
|
[key: string]: unknown;
|
||||||
|
}
|
||||||
|
|
||||||
|
interface ArcoSubMenuProps {
|
||||||
|
'key'?: string | number;
|
||||||
|
'title'?: string | (() => unknown);
|
||||||
|
'selectable'?: boolean;
|
||||||
|
'v-slots'?: Record<string, unknown>;
|
||||||
|
[key: string]: unknown;
|
||||||
|
}
|
||||||
|
|
||||||
|
interface ArcoMenuItemProps {
|
||||||
|
'key'?: string | number;
|
||||||
|
'disabled'?: boolean;
|
||||||
|
'onClick'?: (event: Event) => void;
|
||||||
|
'v-slots'?: Record<string, unknown>;
|
||||||
|
[key: string]: unknown;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 扩展Vue的类型定义
|
||||||
|
declare module '@vue/runtime-core' {
|
||||||
|
export interface GlobalComponents {
|
||||||
|
AMenu: ArcoMenuProps;
|
||||||
|
AMenuItem: ArcoMenuItemProps;
|
||||||
|
ASubMenu: ArcoSubMenuProps;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 扩展全局JSX声明
|
||||||
|
declare global {
|
||||||
|
namespace JSX {
|
||||||
|
interface IntrinsicElements {
|
||||||
|
'a-menu': ArcoMenuProps;
|
||||||
|
'a-menu-item': ArcoMenuItemProps;
|
||||||
|
'a-sub-menu': ArcoSubMenuProps;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
23
src/views/redirect/index.vue
Normal file
23
src/views/redirect/index.vue
Normal file
|
|
@ -0,0 +1,23 @@
|
||||||
|
<script lang="ts">
|
||||||
|
import { defineComponent, onBeforeMount } from 'vue';
|
||||||
|
import { useRoute, useRouter, LocationQueryRaw } from 'vue-router';
|
||||||
|
|
||||||
|
export default defineComponent({
|
||||||
|
setup() {
|
||||||
|
const route = useRoute();
|
||||||
|
const router = useRouter();
|
||||||
|
|
||||||
|
onBeforeMount(() => {
|
||||||
|
const { params, query } = route;
|
||||||
|
const { path } = params;
|
||||||
|
|
||||||
|
router.replace({
|
||||||
|
path: `/${Array.isArray(path) ? path.join('/') : path}`,
|
||||||
|
query: query as LocationQueryRaw,
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
return () => null;
|
||||||
|
},
|
||||||
|
});
|
||||||
|
</script>
|
||||||
44
src/views/result/error/index.vue
Normal file
44
src/views/result/error/index.vue
Normal file
|
|
@ -0,0 +1,44 @@
|
||||||
|
<template>
|
||||||
|
<div class="error-container">
|
||||||
|
<a-result
|
||||||
|
status="error"
|
||||||
|
title="操作失败"
|
||||||
|
sub-title="很抱歉,您的操作未能完成,请检查并重试"
|
||||||
|
>
|
||||||
|
<template #extra>
|
||||||
|
<a-space>
|
||||||
|
<a-button key="retry" type="primary">重试</a-button>
|
||||||
|
<a-button key="back" @click="back">返回上一页</a-button>
|
||||||
|
</a-space>
|
||||||
|
</template>
|
||||||
|
</a-result>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script lang="ts">
|
||||||
|
import { defineComponent } from 'vue';
|
||||||
|
import { useRouter } from 'vue-router';
|
||||||
|
|
||||||
|
export default defineComponent({
|
||||||
|
name: 'ResultError',
|
||||||
|
setup() {
|
||||||
|
const router = useRouter();
|
||||||
|
|
||||||
|
const back = () => {
|
||||||
|
router.back();
|
||||||
|
};
|
||||||
|
|
||||||
|
return {
|
||||||
|
back,
|
||||||
|
};
|
||||||
|
},
|
||||||
|
});
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style scoped lang="less">
|
||||||
|
.error-container {
|
||||||
|
padding: 24px;
|
||||||
|
background-color: var(--color-bg-2);
|
||||||
|
height: 100%;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
51
src/views/result/success/index.vue
Normal file
51
src/views/result/success/index.vue
Normal file
|
|
@ -0,0 +1,51 @@
|
||||||
|
<template>
|
||||||
|
<div class="success-container">
|
||||||
|
<a-result
|
||||||
|
status="success"
|
||||||
|
title="操作成功"
|
||||||
|
sub-title="操作已成功完成,您可以继续其他操作或返回首页"
|
||||||
|
>
|
||||||
|
<template #extra>
|
||||||
|
<a-space>
|
||||||
|
<a-button key="home" type="primary" @click="toHome"
|
||||||
|
>返回首页</a-button
|
||||||
|
>
|
||||||
|
<a-button key="back" @click="back">返回上一页</a-button>
|
||||||
|
</a-space>
|
||||||
|
</template>
|
||||||
|
</a-result>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script lang="ts">
|
||||||
|
import { defineComponent } from 'vue';
|
||||||
|
import { useRouter } from 'vue-router';
|
||||||
|
|
||||||
|
export default defineComponent({
|
||||||
|
name: 'ResultSuccess',
|
||||||
|
setup() {
|
||||||
|
const router = useRouter();
|
||||||
|
|
||||||
|
const toHome = () => {
|
||||||
|
router.push('/');
|
||||||
|
};
|
||||||
|
|
||||||
|
const back = () => {
|
||||||
|
router.back();
|
||||||
|
};
|
||||||
|
|
||||||
|
return {
|
||||||
|
toHome,
|
||||||
|
back,
|
||||||
|
};
|
||||||
|
},
|
||||||
|
});
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style scoped lang="less">
|
||||||
|
.success-container {
|
||||||
|
padding: 24px;
|
||||||
|
background-color: var(--color-bg-2);
|
||||||
|
height: 100%;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
93
src/views/user/info/index.vue
Normal file
93
src/views/user/info/index.vue
Normal file
|
|
@ -0,0 +1,93 @@
|
||||||
|
<template>
|
||||||
|
<div class="container">
|
||||||
|
<a-card class="general-card" title="个人信息">
|
||||||
|
<a-row :gutter="16">
|
||||||
|
<a-col :span="8">
|
||||||
|
<a-card class="user-card">
|
||||||
|
<template #cover>
|
||||||
|
<div class="avatar-wrapper">
|
||||||
|
<a-avatar :size="84" :src="userInfo.avatar || '/avatar.jpg'" />
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
<a-card-meta :title="userInfo.name">
|
||||||
|
<template #description>
|
||||||
|
<div class="user-info">
|
||||||
|
<div>邮箱: {{ userInfo.email || '未设置' }}</div>
|
||||||
|
<div>职位: {{ userInfo.jobName || '未设置' }}</div>
|
||||||
|
<div>部门: {{ userInfo.organizationName || '未设置' }}</div>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
</a-card-meta>
|
||||||
|
</a-card>
|
||||||
|
</a-col>
|
||||||
|
<a-col :span="16">
|
||||||
|
<a-descriptions :column="1" size="large" bordered>
|
||||||
|
<a-descriptions-item label="用户名">{{
|
||||||
|
userInfo.name || '未设置'
|
||||||
|
}}</a-descriptions-item>
|
||||||
|
<a-descriptions-item label="联系电话">{{
|
||||||
|
userInfo.phone || '未设置'
|
||||||
|
}}</a-descriptions-item>
|
||||||
|
<a-descriptions-item label="邮箱地址">{{
|
||||||
|
userInfo.email || '未设置'
|
||||||
|
}}</a-descriptions-item>
|
||||||
|
<a-descriptions-item label="所在地区">{{
|
||||||
|
userInfo.locationName || '未设置'
|
||||||
|
}}</a-descriptions-item>
|
||||||
|
<a-descriptions-item label="注册时间">{{
|
||||||
|
userInfo.registrationDate || '未设置'
|
||||||
|
}}</a-descriptions-item>
|
||||||
|
</a-descriptions>
|
||||||
|
</a-col>
|
||||||
|
</a-row>
|
||||||
|
</a-card>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script lang="ts">
|
||||||
|
import { defineComponent, reactive } from 'vue';
|
||||||
|
import { useUserStore } from '@/store';
|
||||||
|
|
||||||
|
export default defineComponent({
|
||||||
|
name: 'UserInfo',
|
||||||
|
setup() {
|
||||||
|
const userStore = useUserStore();
|
||||||
|
|
||||||
|
const userInfo = reactive({
|
||||||
|
...userStore.$state,
|
||||||
|
});
|
||||||
|
|
||||||
|
return {
|
||||||
|
userInfo,
|
||||||
|
};
|
||||||
|
},
|
||||||
|
});
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style scoped lang="less">
|
||||||
|
.container {
|
||||||
|
padding: 20px;
|
||||||
|
|
||||||
|
.general-card {
|
||||||
|
margin-bottom: 24px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.user-card {
|
||||||
|
text-align: center;
|
||||||
|
|
||||||
|
.avatar-wrapper {
|
||||||
|
display: flex;
|
||||||
|
justify-content: center;
|
||||||
|
padding: 20px 0;
|
||||||
|
background-color: var(--color-bg-2);
|
||||||
|
}
|
||||||
|
|
||||||
|
.user-info {
|
||||||
|
margin-top: 12px;
|
||||||
|
div {
|
||||||
|
margin-bottom: 4px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
||||||
149
src/views/user/setting/index.vue
Normal file
149
src/views/user/setting/index.vue
Normal file
|
|
@ -0,0 +1,149 @@
|
||||||
|
<template>
|
||||||
|
<div class="container">
|
||||||
|
<a-card class="general-card" title="个人设置">
|
||||||
|
<a-tabs default-active-key="1">
|
||||||
|
<a-tab-pane key="1" title="基本信息">
|
||||||
|
<a-form
|
||||||
|
:model="userForm"
|
||||||
|
label-align="right"
|
||||||
|
:label-col-props="{ span: 6 }"
|
||||||
|
:wrapper-col-props="{ span: 18 }"
|
||||||
|
>
|
||||||
|
<a-form-item field="avatar" label="头像">
|
||||||
|
<div class="avatar-uploader">
|
||||||
|
<a-avatar :size="64" :src="userForm.avatar || '/avatar.jpg'" />
|
||||||
|
<div class="upload-actions">
|
||||||
|
<a-button type="primary" size="small">更换头像</a-button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</a-form-item>
|
||||||
|
<a-form-item field="name" label="用户名">
|
||||||
|
<a-input v-model="userForm.name" placeholder="请输入用户名" />
|
||||||
|
</a-form-item>
|
||||||
|
<a-form-item field="email" label="邮箱">
|
||||||
|
<a-input v-model="userForm.email" placeholder="请输入邮箱" />
|
||||||
|
</a-form-item>
|
||||||
|
<a-form-item field="phone" label="电话号码">
|
||||||
|
<a-input v-model="userForm.phone" placeholder="请输入电话号码" />
|
||||||
|
</a-form-item>
|
||||||
|
<a-form-item field="introduction" label="个人简介">
|
||||||
|
<a-textarea
|
||||||
|
v-model="userForm.introduction"
|
||||||
|
placeholder="请输入个人简介"
|
||||||
|
/>
|
||||||
|
</a-form-item>
|
||||||
|
<a-form-item :wrapper-col-props="{ offset: 6 }">
|
||||||
|
<a-space>
|
||||||
|
<a-button type="primary" @click="saveSettings">保存</a-button>
|
||||||
|
<a-button @click="resetForm">重置</a-button>
|
||||||
|
</a-space>
|
||||||
|
</a-form-item>
|
||||||
|
</a-form>
|
||||||
|
</a-tab-pane>
|
||||||
|
<a-tab-pane key="2" title="安全设置">
|
||||||
|
<a-space direction="vertical" fill style="width: 100%">
|
||||||
|
<a-card>
|
||||||
|
<template #title>修改密码</template>
|
||||||
|
<div class="password-item">
|
||||||
|
<div class="password-item-title">账户密码</div>
|
||||||
|
<div class="password-item-action">
|
||||||
|
<a-button>修改</a-button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</a-card>
|
||||||
|
<a-card>
|
||||||
|
<template #title>安全认证</template>
|
||||||
|
<div class="setting-item">
|
||||||
|
<div class="setting-item-title">
|
||||||
|
<div>两步验证</div>
|
||||||
|
<div class="setting-item-desc"
|
||||||
|
>使用两步验证提高账户安全性</div
|
||||||
|
>
|
||||||
|
</div>
|
||||||
|
<div class="setting-item-action">
|
||||||
|
<a-switch />
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</a-card>
|
||||||
|
</a-space>
|
||||||
|
</a-tab-pane>
|
||||||
|
</a-tabs>
|
||||||
|
</a-card>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script lang="ts">
|
||||||
|
import { defineComponent, reactive } from 'vue';
|
||||||
|
import { useUserStore } from '@/store';
|
||||||
|
import { Message } from '@arco-design/web-vue';
|
||||||
|
|
||||||
|
export default defineComponent({
|
||||||
|
name: 'UserSetting',
|
||||||
|
setup() {
|
||||||
|
const userStore = useUserStore();
|
||||||
|
|
||||||
|
const userForm = reactive({
|
||||||
|
...userStore.$state,
|
||||||
|
});
|
||||||
|
|
||||||
|
const originalData = { ...userForm };
|
||||||
|
|
||||||
|
const saveSettings = () => {
|
||||||
|
userStore.setInfo({
|
||||||
|
name: userForm.name,
|
||||||
|
email: userForm.email,
|
||||||
|
phone: userForm.phone,
|
||||||
|
introduction: userForm.introduction,
|
||||||
|
});
|
||||||
|
Message.success('设置已保存');
|
||||||
|
};
|
||||||
|
|
||||||
|
const resetForm = () => {
|
||||||
|
Object.assign(userForm, originalData);
|
||||||
|
Message.info('设置已重置');
|
||||||
|
};
|
||||||
|
|
||||||
|
return {
|
||||||
|
userForm,
|
||||||
|
saveSettings,
|
||||||
|
resetForm,
|
||||||
|
};
|
||||||
|
},
|
||||||
|
});
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style scoped lang="less">
|
||||||
|
.container {
|
||||||
|
padding: 20px;
|
||||||
|
|
||||||
|
.general-card {
|
||||||
|
margin-bottom: 24px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.avatar-uploader {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
gap: 16px;
|
||||||
|
margin-bottom: 16px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.password-item,
|
||||||
|
.setting-item {
|
||||||
|
display: flex;
|
||||||
|
justify-content: space-between;
|
||||||
|
align-items: center;
|
||||||
|
padding: 12px 0;
|
||||||
|
|
||||||
|
.password-item-title,
|
||||||
|
.setting-item-title {
|
||||||
|
font-weight: 500;
|
||||||
|
}
|
||||||
|
|
||||||
|
.setting-item-desc {
|
||||||
|
font-size: 12px;
|
||||||
|
color: var(--color-text-3);
|
||||||
|
margin-top: 4px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
||||||
257
src/views/visualization/data-analysis/index.vue
Normal file
257
src/views/visualization/data-analysis/index.vue
Normal file
|
|
@ -0,0 +1,257 @@
|
||||||
|
<template>
|
||||||
|
<div class="container">
|
||||||
|
<a-card class="general-card" title="数据分析">
|
||||||
|
<a-row :gutter="16">
|
||||||
|
<a-col :span="24" :lg="16">
|
||||||
|
<!-- 主要图表区域 -->
|
||||||
|
<a-card class="content-card">
|
||||||
|
<template #title>销售趋势分析</template>
|
||||||
|
<div class="chart-wrapper">
|
||||||
|
<div ref="chartRef" class="chart"></div>
|
||||||
|
</div>
|
||||||
|
</a-card>
|
||||||
|
</a-col>
|
||||||
|
<a-col :span="24" :lg="8">
|
||||||
|
<!-- 数据统计卡片 -->
|
||||||
|
<a-space direction="vertical" fill style="width: 100%">
|
||||||
|
<a-card class="content-card">
|
||||||
|
<a-statistic
|
||||||
|
title="总销售额"
|
||||||
|
:value="12345678"
|
||||||
|
:precision="2"
|
||||||
|
show-group-separator
|
||||||
|
>
|
||||||
|
<template #prefix>
|
||||||
|
<icon-thumb-up />
|
||||||
|
</template>
|
||||||
|
</a-statistic>
|
||||||
|
<div class="statistic-footer">
|
||||||
|
<div class="footer-item">
|
||||||
|
<span>日环比</span>
|
||||||
|
<span class="green">
|
||||||
|
<icon-arrow-rise />
|
||||||
|
10.5%
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
<div class="footer-item">
|
||||||
|
<span>周环比</span>
|
||||||
|
<span class="green">
|
||||||
|
<icon-arrow-rise />
|
||||||
|
12.8%
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</a-card>
|
||||||
|
<a-card class="content-card">
|
||||||
|
<a-statistic
|
||||||
|
title="访问量"
|
||||||
|
:value="8846"
|
||||||
|
:precision="0"
|
||||||
|
show-group-separator
|
||||||
|
>
|
||||||
|
<template #prefix>
|
||||||
|
<icon-user />
|
||||||
|
</template>
|
||||||
|
</a-statistic>
|
||||||
|
<div class="statistic-footer">
|
||||||
|
<div class="footer-item">
|
||||||
|
<span>日环比</span>
|
||||||
|
<span class="red">
|
||||||
|
<icon-arrow-fall />
|
||||||
|
2.5%
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
<div class="footer-item">
|
||||||
|
<span>周环比</span>
|
||||||
|
<span class="green">
|
||||||
|
<icon-arrow-rise />
|
||||||
|
15.2%
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</a-card>
|
||||||
|
</a-space>
|
||||||
|
</a-col>
|
||||||
|
</a-row>
|
||||||
|
|
||||||
|
<a-divider />
|
||||||
|
|
||||||
|
<!-- 数据表格 -->
|
||||||
|
<a-card class="content-card">
|
||||||
|
<template #title>销售数据详情</template>
|
||||||
|
<a-table :data="tableData" :pagination="{ pageSize: 5 }">
|
||||||
|
<template #columns>
|
||||||
|
<a-table-column title="ID" data-index="id" />
|
||||||
|
<a-table-column title="商品名称" data-index="name" />
|
||||||
|
<a-table-column title="销售额" data-index="sales">
|
||||||
|
<template #cell="{ record }">{{
|
||||||
|
record.sales.toLocaleString()
|
||||||
|
}}</template>
|
||||||
|
</a-table-column>
|
||||||
|
<a-table-column title="销售量" data-index="count" />
|
||||||
|
<a-table-column title="日期" data-index="date" />
|
||||||
|
</template>
|
||||||
|
</a-table>
|
||||||
|
</a-card>
|
||||||
|
</a-card>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script lang="ts">
|
||||||
|
import { defineComponent, onMounted, ref } from 'vue';
|
||||||
|
import * as echarts from 'echarts';
|
||||||
|
|
||||||
|
export default defineComponent({
|
||||||
|
name: 'DataAnalysis',
|
||||||
|
setup() {
|
||||||
|
const chartRef = ref<HTMLElement | null>(null);
|
||||||
|
const chart = ref<echarts.ECharts | null>(null);
|
||||||
|
|
||||||
|
const tableData = [
|
||||||
|
{ id: 1, name: '商品A', sales: 12345, count: 123, date: '2023-01-01' },
|
||||||
|
{ id: 2, name: '商品B', sales: 23456, count: 234, date: '2023-01-02' },
|
||||||
|
{ id: 3, name: '商品C', sales: 34567, count: 345, date: '2023-01-03' },
|
||||||
|
{ id: 4, name: '商品D', sales: 45678, count: 456, date: '2023-01-04' },
|
||||||
|
{ id: 5, name: '商品E', sales: 56789, count: 567, date: '2023-01-05' },
|
||||||
|
{ id: 6, name: '商品F', sales: 67890, count: 678, date: '2023-01-06' },
|
||||||
|
{ id: 7, name: '商品G', sales: 78901, count: 789, date: '2023-01-07' },
|
||||||
|
];
|
||||||
|
|
||||||
|
const initChart = () => {
|
||||||
|
if (!chartRef.value) return;
|
||||||
|
|
||||||
|
chart.value = echarts.init(chartRef.value);
|
||||||
|
|
||||||
|
const option = {
|
||||||
|
tooltip: {
|
||||||
|
trigger: 'axis',
|
||||||
|
},
|
||||||
|
legend: {
|
||||||
|
data: ['销售额', '访问量'],
|
||||||
|
},
|
||||||
|
grid: {
|
||||||
|
left: '3%',
|
||||||
|
right: '4%',
|
||||||
|
bottom: '3%',
|
||||||
|
containLabel: true,
|
||||||
|
},
|
||||||
|
xAxis: {
|
||||||
|
type: 'category',
|
||||||
|
boundaryGap: false,
|
||||||
|
data: ['周一', '周二', '周三', '周四', '周五', '周六', '周日'],
|
||||||
|
},
|
||||||
|
yAxis: {
|
||||||
|
type: 'value',
|
||||||
|
},
|
||||||
|
series: [
|
||||||
|
{
|
||||||
|
name: '销售额',
|
||||||
|
type: 'line',
|
||||||
|
stack: '总量',
|
||||||
|
data: [120, 132, 101, 134, 90, 230, 210],
|
||||||
|
smooth: true,
|
||||||
|
lineStyle: {
|
||||||
|
width: 2,
|
||||||
|
color: '#1890ff',
|
||||||
|
},
|
||||||
|
areaStyle: {
|
||||||
|
color: new echarts.graphic.LinearGradient(0, 0, 0, 1, [
|
||||||
|
{ offset: 0, color: 'rgba(24,144,255,0.3)' },
|
||||||
|
{ offset: 1, color: 'rgba(24,144,255,0.1)' },
|
||||||
|
]),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: '访问量',
|
||||||
|
type: 'line',
|
||||||
|
stack: '总量',
|
||||||
|
data: [220, 182, 191, 234, 290, 330, 310],
|
||||||
|
smooth: true,
|
||||||
|
lineStyle: {
|
||||||
|
width: 2,
|
||||||
|
color: '#52c41a',
|
||||||
|
},
|
||||||
|
areaStyle: {
|
||||||
|
color: new echarts.graphic.LinearGradient(0, 0, 0, 1, [
|
||||||
|
{ offset: 0, color: 'rgba(82,196,26,0.3)' },
|
||||||
|
{ offset: 1, color: 'rgba(82,196,26,0.1)' },
|
||||||
|
]),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
],
|
||||||
|
};
|
||||||
|
|
||||||
|
chart.value.setOption(option);
|
||||||
|
};
|
||||||
|
|
||||||
|
onMounted(() => {
|
||||||
|
initChart();
|
||||||
|
|
||||||
|
window.addEventListener('resize', () => {
|
||||||
|
chart.value?.resize();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
return {
|
||||||
|
chartRef,
|
||||||
|
tableData,
|
||||||
|
};
|
||||||
|
},
|
||||||
|
});
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style scoped lang="less">
|
||||||
|
.container {
|
||||||
|
padding: 20px;
|
||||||
|
|
||||||
|
.general-card {
|
||||||
|
margin-bottom: 24px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.content-card {
|
||||||
|
margin-bottom: 16px;
|
||||||
|
|
||||||
|
&:last-child {
|
||||||
|
margin-bottom: 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.chart-wrapper {
|
||||||
|
height: 360px;
|
||||||
|
|
||||||
|
.chart {
|
||||||
|
height: 100%;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.statistic-footer {
|
||||||
|
display: flex;
|
||||||
|
justify-content: space-between;
|
||||||
|
margin-top: 16px;
|
||||||
|
|
||||||
|
.footer-item {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
align-items: flex-start;
|
||||||
|
|
||||||
|
span:first-child {
|
||||||
|
font-size: 12px;
|
||||||
|
color: var(--color-text-3);
|
||||||
|
}
|
||||||
|
|
||||||
|
span:last-child {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.green {
|
||||||
|
color: #52c41a;
|
||||||
|
}
|
||||||
|
|
||||||
|
.red {
|
||||||
|
color: #f5222d;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
||||||
298
src/views/visualization/multi-dimension-data-analysis/index.vue
Normal file
298
src/views/visualization/multi-dimension-data-analysis/index.vue
Normal file
|
|
@ -0,0 +1,298 @@
|
||||||
|
<template>
|
||||||
|
<div class="container">
|
||||||
|
<a-card class="general-card" title="多维数据分析">
|
||||||
|
<a-row :gutter="16">
|
||||||
|
<a-col :span="24">
|
||||||
|
<!-- 图表切换控制 -->
|
||||||
|
<div class="chart-control">
|
||||||
|
<a-radio-group v-model="chartType" type="button">
|
||||||
|
<a-radio value="bar">柱状图</a-radio>
|
||||||
|
<a-radio value="line">折线图</a-radio>
|
||||||
|
<a-radio value="pie">饼图</a-radio>
|
||||||
|
</a-radio-group>
|
||||||
|
<a-select v-model="timeRange" style="width: 120px">
|
||||||
|
<a-option value="week">本周</a-option>
|
||||||
|
<a-option value="month">本月</a-option>
|
||||||
|
<a-option value="year">本年</a-option>
|
||||||
|
</a-select>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- 图表区域 -->
|
||||||
|
<div class="chart-wrapper">
|
||||||
|
<div ref="chartRef" class="chart"></div>
|
||||||
|
</div>
|
||||||
|
</a-col>
|
||||||
|
</a-row>
|
||||||
|
|
||||||
|
<a-divider />
|
||||||
|
|
||||||
|
<!-- 数据维度选择 -->
|
||||||
|
<a-card class="content-card">
|
||||||
|
<template #title>数据维度配置</template>
|
||||||
|
<a-row :gutter="16">
|
||||||
|
<a-col :span="12">
|
||||||
|
<a-form :model="formData" layout="vertical">
|
||||||
|
<a-form-item field="dimension1" label="维度1">
|
||||||
|
<a-select v-model="formData.dimension1">
|
||||||
|
<a-option value="sales">销售额</a-option>
|
||||||
|
<a-option value="traffic">流量</a-option>
|
||||||
|
<a-option value="users">用户数</a-option>
|
||||||
|
</a-select>
|
||||||
|
</a-form-item>
|
||||||
|
<a-form-item field="dimension2" label="维度2">
|
||||||
|
<a-select v-model="formData.dimension2">
|
||||||
|
<a-option value="region">地区</a-option>
|
||||||
|
<a-option value="age">年龄段</a-option>
|
||||||
|
<a-option value="gender">性别</a-option>
|
||||||
|
</a-select>
|
||||||
|
</a-form-item>
|
||||||
|
</a-form>
|
||||||
|
</a-col>
|
||||||
|
<a-col :span="12">
|
||||||
|
<a-form :model="formData" layout="vertical">
|
||||||
|
<a-form-item field="dimension3" label="维度3">
|
||||||
|
<a-select v-model="formData.dimension3">
|
||||||
|
<a-option value="channel">渠道</a-option>
|
||||||
|
<a-option value="product">商品</a-option>
|
||||||
|
<a-option value="time">时间</a-option>
|
||||||
|
</a-select>
|
||||||
|
</a-form-item>
|
||||||
|
<a-form-item>
|
||||||
|
<a-button type="primary" @click="updateChart"
|
||||||
|
>更新图表</a-button
|
||||||
|
>
|
||||||
|
</a-form-item>
|
||||||
|
</a-form>
|
||||||
|
</a-col>
|
||||||
|
</a-row>
|
||||||
|
</a-card>
|
||||||
|
|
||||||
|
<!-- 数据表格 -->
|
||||||
|
<a-card class="content-card">
|
||||||
|
<template #title>多维数据详情</template>
|
||||||
|
<a-table :data="tableData" :pagination="{ pageSize: 5 }">
|
||||||
|
<template #columns>
|
||||||
|
<a-table-column title="ID" data-index="id" />
|
||||||
|
<a-table-column title="维度1" data-index="dim1" />
|
||||||
|
<a-table-column title="维度2" data-index="dim2" />
|
||||||
|
<a-table-column title="维度3" data-index="dim3" />
|
||||||
|
<a-table-column title="数值" data-index="value">
|
||||||
|
<template #cell="{ record }">{{
|
||||||
|
record.value.toLocaleString()
|
||||||
|
}}</template>
|
||||||
|
</a-table-column>
|
||||||
|
</template>
|
||||||
|
</a-table>
|
||||||
|
</a-card>
|
||||||
|
</a-card>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script lang="ts">
|
||||||
|
import { defineComponent, onMounted, ref, reactive, watch } from 'vue';
|
||||||
|
import * as echarts from 'echarts';
|
||||||
|
|
||||||
|
export default defineComponent({
|
||||||
|
name: 'MultiDimensionDataAnalysis',
|
||||||
|
setup() {
|
||||||
|
const chartRef = ref<HTMLElement | null>(null);
|
||||||
|
const chart = ref<echarts.ECharts | null>(null);
|
||||||
|
|
||||||
|
const chartType = ref('bar');
|
||||||
|
const timeRange = ref('month');
|
||||||
|
|
||||||
|
const formData = reactive({
|
||||||
|
dimension1: 'sales',
|
||||||
|
dimension2: 'region',
|
||||||
|
dimension3: 'channel',
|
||||||
|
});
|
||||||
|
|
||||||
|
// 模拟数据
|
||||||
|
const tableData = ref([
|
||||||
|
{ id: 1, dim1: '销售额', dim2: '华东', dim3: '线上', value: 4332 },
|
||||||
|
{ id: 2, dim1: '销售额', dim2: '华南', dim3: '线上', value: 2986 },
|
||||||
|
{ id: 3, dim1: '销售额', dim2: '华北', dim3: '线上', value: 3219 },
|
||||||
|
{ id: 4, dim1: '销售额', dim2: '华东', dim3: '线下', value: 3721 },
|
||||||
|
{ id: 5, dim1: '销售额', dim2: '华南', dim3: '线下', value: 2413 },
|
||||||
|
{ id: 6, dim1: '销售额', dim2: '华北', dim3: '线下', value: 1893 },
|
||||||
|
{ id: 7, dim1: '流量', dim2: '华东', dim3: '线上', value: 10243 },
|
||||||
|
{ id: 8, dim1: '流量', dim2: '华南', dim3: '线上', value: 8752 },
|
||||||
|
]);
|
||||||
|
|
||||||
|
const getChartData = () => {
|
||||||
|
// 模拟根据维度和时间范围获取不同的数据
|
||||||
|
// 实际应用中可以通过API获取
|
||||||
|
return {
|
||||||
|
xAxis: ['华东', '华南', '华北', '西南', '西北', '东北'],
|
||||||
|
series: [
|
||||||
|
{
|
||||||
|
name: '线上',
|
||||||
|
data: [4332, 2986, 3219, 2851, 1845, 2016],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: '线下',
|
||||||
|
data: [3721, 2413, 1893, 2173, 1634, 1723],
|
||||||
|
},
|
||||||
|
],
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
const updateChart = () => {
|
||||||
|
if (!chart.value) return;
|
||||||
|
|
||||||
|
const chartData = getChartData();
|
||||||
|
|
||||||
|
let option: echarts.EChartsOption = {
|
||||||
|
tooltip: {
|
||||||
|
trigger: 'axis',
|
||||||
|
axisPointer: {
|
||||||
|
type: 'shadow',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
legend: {
|
||||||
|
data: ['线上', '线下'],
|
||||||
|
},
|
||||||
|
grid: {
|
||||||
|
left: '3%',
|
||||||
|
right: '4%',
|
||||||
|
bottom: '3%',
|
||||||
|
containLabel: true,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
if (chartType.value === 'bar') {
|
||||||
|
option = {
|
||||||
|
...option,
|
||||||
|
xAxis: {
|
||||||
|
type: 'category',
|
||||||
|
data: chartData.xAxis,
|
||||||
|
},
|
||||||
|
yAxis: {
|
||||||
|
type: 'value',
|
||||||
|
},
|
||||||
|
series: chartData.series.map((item) => ({
|
||||||
|
name: item.name,
|
||||||
|
type: 'bar',
|
||||||
|
data: item.data,
|
||||||
|
})),
|
||||||
|
};
|
||||||
|
} else if (chartType.value === 'line') {
|
||||||
|
option = {
|
||||||
|
...option,
|
||||||
|
xAxis: {
|
||||||
|
type: 'category',
|
||||||
|
data: chartData.xAxis,
|
||||||
|
},
|
||||||
|
yAxis: {
|
||||||
|
type: 'value',
|
||||||
|
},
|
||||||
|
series: chartData.series.map((item) => ({
|
||||||
|
name: item.name,
|
||||||
|
type: 'line',
|
||||||
|
smooth: true,
|
||||||
|
data: item.data,
|
||||||
|
})),
|
||||||
|
};
|
||||||
|
} else if (chartType.value === 'pie') {
|
||||||
|
// 将数据转换为饼图格式
|
||||||
|
const pieData = chartData.xAxis.map((region, index) => ({
|
||||||
|
name: region,
|
||||||
|
value:
|
||||||
|
chartData.series[0].data[index] + chartData.series[1].data[index],
|
||||||
|
}));
|
||||||
|
|
||||||
|
option = {
|
||||||
|
tooltip: {
|
||||||
|
trigger: 'item',
|
||||||
|
formatter: '{a} <br/>{b} : {c} ({d}%)',
|
||||||
|
},
|
||||||
|
legend: {
|
||||||
|
orient: 'vertical',
|
||||||
|
left: 'left',
|
||||||
|
data: chartData.xAxis,
|
||||||
|
},
|
||||||
|
series: [
|
||||||
|
{
|
||||||
|
name: formData.dimension1,
|
||||||
|
type: 'pie',
|
||||||
|
radius: '50%',
|
||||||
|
center: ['50%', '60%'],
|
||||||
|
data: pieData,
|
||||||
|
emphasis: {
|
||||||
|
itemStyle: {
|
||||||
|
shadowBlur: 10,
|
||||||
|
shadowOffsetX: 0,
|
||||||
|
shadowColor: 'rgba(0, 0, 0, 0.5)',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
],
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
chart.value.setOption(option, true);
|
||||||
|
};
|
||||||
|
|
||||||
|
const initChart = () => {
|
||||||
|
if (!chartRef.value) return;
|
||||||
|
|
||||||
|
chart.value = echarts.init(chartRef.value);
|
||||||
|
updateChart();
|
||||||
|
|
||||||
|
window.addEventListener('resize', () => {
|
||||||
|
chart.value?.resize();
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
watch([chartType, timeRange], () => {
|
||||||
|
updateChart();
|
||||||
|
});
|
||||||
|
|
||||||
|
onMounted(() => {
|
||||||
|
initChart();
|
||||||
|
});
|
||||||
|
|
||||||
|
return {
|
||||||
|
chartRef,
|
||||||
|
chartType,
|
||||||
|
timeRange,
|
||||||
|
formData,
|
||||||
|
tableData,
|
||||||
|
updateChart,
|
||||||
|
};
|
||||||
|
},
|
||||||
|
});
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style scoped lang="less">
|
||||||
|
.container {
|
||||||
|
padding: 20px;
|
||||||
|
|
||||||
|
.general-card {
|
||||||
|
margin-bottom: 24px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.content-card {
|
||||||
|
margin-bottom: 16px;
|
||||||
|
|
||||||
|
&:last-child {
|
||||||
|
margin-bottom: 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.chart-control {
|
||||||
|
display: flex;
|
||||||
|
justify-content: space-between;
|
||||||
|
margin-bottom: 16px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.chart-wrapper {
|
||||||
|
height: 400px;
|
||||||
|
margin-bottom: 24px;
|
||||||
|
|
||||||
|
.chart {
|
||||||
|
height: 100%;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
{
|
{
|
||||||
"compilerOptions": {
|
"compilerOptions": {
|
||||||
"target": "ESNext",
|
"target": "ESNext",
|
||||||
"module": "ESNext",
|
"module": "ESNext",
|
||||||
"moduleResolution": "node",
|
"moduleResolution": "node",
|
||||||
"resolveJsonModule": true,
|
"resolveJsonModule": true,
|
||||||
|
|
@ -8,6 +8,8 @@
|
||||||
"strict": true,
|
"strict": true,
|
||||||
"strictNullChecks": true,
|
"strictNullChecks": true,
|
||||||
"jsx": "preserve",
|
"jsx": "preserve",
|
||||||
|
"jsxFactory": "h",
|
||||||
|
"jsxFragmentFactory": "Fragment",
|
||||||
"baseUrl": ".",
|
"baseUrl": ".",
|
||||||
"paths": {
|
"paths": {
|
||||||
"@/*": [
|
"@/*": [
|
||||||
|
|
@ -16,9 +18,12 @@
|
||||||
},
|
},
|
||||||
"lib": [
|
"lib": [
|
||||||
"esnext",
|
"esnext",
|
||||||
"dom"
|
"dom",
|
||||||
|
"dom.iterable"
|
||||||
],
|
],
|
||||||
"skipLibCheck": true,
|
"skipLibCheck": true,
|
||||||
|
"noImplicitAny": false,
|
||||||
|
"allowJs": true,
|
||||||
"types": [
|
"types": [
|
||||||
"vite/client",
|
"vite/client",
|
||||||
"node"
|
"node"
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue