diff --git a/backend/Dockerfile b/backend/Dockerfile index 8c9878d..a485855 100644 --- a/backend/Dockerfile +++ b/backend/Dockerfile @@ -1,4 +1,4 @@ -FROM node:18-alpine +FROM node:18-alpine3.18 # 设置工作目录 WORKDIR /app @@ -8,17 +8,21 @@ RUN apk add --no-cache \ python3 \ make \ g++ \ - curl + curl \ + openssl1.1-compat # 复制 package.json 和 package-lock.json COPY package*.json ./ # 安装依赖 -RUN npm ci --only=production && npm cache clean --force +RUN npm install # 复制源代码 COPY . . +# 构建项目 +RUN npm run build + # 创建非root用户 RUN addgroup -g 1001 -S nodejs RUN adduser -S nodejs -u 1001 @@ -30,9 +34,10 @@ USER nodejs # 暴露端口 EXPOSE 3001 +RUN npx prisma generate # 健康检查 HEALTHCHECK --interval=30s --timeout=3s --start-period=5s --retries=3 \ CMD curl -f http://localhost:3001/health || exit 1 # 启动命令 -CMD ["npm", "run", "dev"] \ No newline at end of file +CMD [ "sh", "-c", "npm run db:push && npm run db:seed && npm run start" ] \ No newline at end of file diff --git a/backend/prisma/schema.prisma b/backend/prisma/schema.prisma index 289fbd8..0a08e8a 100644 --- a/backend/prisma/schema.prisma +++ b/backend/prisma/schema.prisma @@ -14,8 +14,6 @@ model User { id String @id @default(cuid()) username String @unique password String - firstName String? - lastName String? isActive Boolean @default(true) isAdmin Boolean @default(false) lastLoginAt DateTime? diff --git a/backend/prisma/seed.ts b/backend/prisma/seed.ts index 3b0895c..48efd57 100644 --- a/backend/prisma/seed.ts +++ b/backend/prisma/seed.ts @@ -9,138 +9,37 @@ async function main() { // 创建管理员用户 const adminPassword = await bcrypt.hash('admin123', 12); const admin = await prisma.user.upsert({ - where: { email: 'admin@pandora.com' }, + where: { username: 'admin' }, update: {}, create: { - email: 'admin@pandora.com', username: 'admin', password: adminPassword, - firstName: '管理员', - lastName: '系统', isAdmin: true, isActive: true, - emailVerified: true, }, }); - // 创建测试用户 - const userPassword = await bcrypt.hash('user123', 12); - const user = await prisma.user.upsert({ - where: { email: 'user@pandora.com' }, - update: {}, - create: { - email: 'user@pandora.com', - username: 'testuser', - password: userPassword, - firstName: '测试', - lastName: '用户', - isAdmin: false, - isActive: true, - emailVerified: true, - }, - }); - - // 创建网站账号 - const accounts = [ - { - website: 'claude.ai', - accountName: 'claude_pro_1', - token: 'sk-ant-api03-xxx-claude-pro-1', - maxUsers: 3, - currentUsers: 0, - }, - { - website: 'openai.com', - accountName: 'gpt4_plus_1', - token: 'sk-xxx-gpt4-plus-1', - maxUsers: 2, - currentUsers: 0, - }, - { - website: 'gemini.google.com', - accountName: 'gemini_pro_1', - token: 'AIzaSyCxxx-gemini-pro-1', - maxUsers: 1, - currentUsers: 0, - }, - ]; - - for (const accountData of accounts) { - await prisma.websiteAccount.upsert({ - where: { - website_accountName: { - website: accountData.website, - accountName: accountData.accountName, - } - }, - update: {}, - create: accountData, - }); - } - // 为管理员分配所有账号 - const allAccounts = await prisma.websiteAccount.findMany(); - for (const account of allAccounts) { - await prisma.accountAssignment.upsert({ - where: { - userId_accountId: { - userId: admin.id, - accountId: account.id, - } - }, - update: {}, - create: { - userId: admin.id, - accountId: account.id, - isActive: true, - }, - }); - } - - // 为用户分配部分账号 - const userAccounts = await prisma.websiteAccount.findMany({ - where: { - website: { - in: ['claude.ai', 'openai.com'] - } - } - }); - - for (const account of userAccounts) { - await prisma.accountAssignment.upsert({ - where: { - userId_accountId: { - userId: user.id, - accountId: account.id, - } - }, - update: {}, - create: { - userId: user.id, - accountId: account.id, - isActive: true, - }, - }); - } - - // 更新账号当前用户数 - for (const account of allAccounts) { - const userCount = await prisma.accountAssignment.count({ - where: { - accountId: account.id, - isActive: true, - } - }); - - await prisma.websiteAccount.update({ - where: { id: account.id }, - data: { currentUsers: userCount } - }); - } + // const allAccounts = await prisma.websiteAccount.findMany(); + // for (const account of allAccounts) { + // await prisma.accountAssignment.upsert({ + // where: { + // userId_accountId: { + // userId: admin.id, + // accountId: account.id, + // } + // }, + // update: {}, + // create: { + // userId: admin.id, + // accountId: account.id, + // isActive: true, + // }, + // }); + // } console.log('数据库初始化完成!'); - console.log('管理员账户:', admin.email, '密码: admin123'); - console.log('测试用户账户:', user.email, '密码: user123'); + console.log('管理员账户:', admin.username, '密码: admin123'); } main() diff --git a/backend/src/controllers/accountController.ts b/backend/src/controllers/accountController.ts index 18e4cfa..fa6d46f 100644 --- a/backend/src/controllers/accountController.ts +++ b/backend/src/controllers/accountController.ts @@ -51,8 +51,6 @@ export const accountController = { select: { id: true, username: true, - firstName: true, - lastName: true, } } } diff --git a/backend/src/controllers/authController.ts b/backend/src/controllers/authController.ts index 9b1c4d4..12469ca 100644 --- a/backend/src/controllers/authController.ts +++ b/backend/src/controllers/authController.ts @@ -46,7 +46,7 @@ async function createSession(userId: string, token: string, req: Request) { export const authController = { // 用户注册 async register(req: Request, res: Response) { - const { username, password, confirmPassword, firstName, lastName } = req.body; + const { username, password, confirmPassword } = req.body; // 验证密码确认 if (password !== confirmPassword) { @@ -74,8 +74,6 @@ export const authController = { data: { username, password: hashedPassword, - firstName, - lastName, isActive: false, // 新注册用户默认为禁用状态 }, }); @@ -97,8 +95,6 @@ export const authController = { user: { id: user.id, username: user.username, - firstName: user.firstName, - lastName: user.lastName, isAdmin: user.isAdmin, isActive: user.isActive, } @@ -237,8 +233,6 @@ export const authController = { user: { id: user.id, username: user.username, - firstName: user.firstName, - lastName: user.lastName, isAdmin: user.isAdmin, } }); @@ -283,8 +277,6 @@ export const authController = { select: { id: true, username: true, - firstName: true, - lastName: true, isAdmin: true, isActive: true, lastLoginAt: true, diff --git a/backend/src/controllers/userController.ts b/backend/src/controllers/userController.ts index 7fa7fc5..a9c121c 100644 --- a/backend/src/controllers/userController.ts +++ b/backend/src/controllers/userController.ts @@ -2,6 +2,7 @@ import { Request, Response } from 'express'; import { prisma } from '../config/database'; import { AuthRequest } from '../middleware/auth'; import bcrypt from 'bcryptjs'; +import type { PrismaClient } from '@prisma/client'; export const userController = { // 获取所有用户 (管理员) @@ -18,8 +19,6 @@ export const userController = { if (search) { where.OR = [ { username: { contains: search as string, mode: 'insensitive' } }, - { firstName: { contains: search as string, mode: 'insensitive' } }, - { lastName: { contains: search as string, mode: 'insensitive' } } ]; } @@ -40,11 +39,8 @@ export const userController = { select: { id: true, username: true, - firstName: true, - lastName: true, isAdmin: true, isActive: true, - totpEnabled: true, lastLoginAt: true, createdAt: true, accountAssignments: { @@ -65,12 +61,9 @@ export const userController = { users: users.map((user: any) => ({ id: user.id, username: user.username, - firstName: user.firstName, - lastName: user.lastName, role: user.isAdmin ? 'admin' : 'user', isAdmin: user.isAdmin, isActive: user.isActive, - totpEnabled: user.totpEnabled, lastLoginAt: user.lastLoginAt, createdAt: user.createdAt, accounts: user.accountAssignments.map((assignment: any) => assignment.accountId) @@ -102,11 +95,8 @@ export const userController = { select: { id: true, username: true, - firstName: true, - lastName: true, isAdmin: true, isActive: true, - totpEnabled: true, lastLoginAt: true, createdAt: true, } @@ -120,11 +110,8 @@ export const userController = { user: { id: user.id, username: user.username, - firstName: user.firstName, - lastName: user.lastName, isAdmin: user.isAdmin, isActive: user.isActive, - totpEnabled: user.totpEnabled, lastLoginAt: user.lastLoginAt, createdAt: user.createdAt } @@ -134,9 +121,7 @@ export const userController = { // 更新用户信息 async updateUser(req: AuthRequest, res: Response) { const { id } = req.params; - const { username, role, firstName, lastName, isActive, loginAttempts } = req.body; - - console.log('收到更新请求:', req.body); + const { username, role, isActive, loginAttempts } = req.body; if (!id) { return res.status(400).json({ error: '用户ID是必需的' }); @@ -157,9 +142,6 @@ export const userController = { if (typeof isActive === 'boolean') updateData.isActive = isActive; } - // 普通用户可以修改这些字段 - if (firstName !== undefined) updateData.firstName = firstName; - if (lastName !== undefined) updateData.lastName = lastName; // 新增:处理密码修改 if (req.body.password && typeof req.body.password === 'string' && req.body.password.trim() !== '') { @@ -191,11 +173,8 @@ export const userController = { select: { id: true, username: true, - firstName: true, - lastName: true, isAdmin: true, isActive: true, - totpEnabled: true, lastLoginAt: true, createdAt: true, password: true, @@ -207,11 +186,8 @@ export const userController = { user: { id: user.id, username: user.username, - firstName: user.firstName, - lastName: user.lastName, isAdmin: user.isAdmin, isActive: user.isActive, - totpEnabled: user.totpEnabled, lastLoginAt: user.lastLoginAt, createdAt: user.createdAt, password: user.password, @@ -254,7 +230,7 @@ export const userController = { } // 使用事务来确保数据一致性 - await prisma.$transaction(async (tx) => { + await prisma.$transaction(async (tx: PrismaClient) => { // 删除用户现有的所有账号分配 await tx.accountAssignment.deleteMany({ where: { userId: id } @@ -336,11 +312,8 @@ export const userController = { select: { id: true, username: true, - firstName: true, - lastName: true, isAdmin: true, isActive: true, - totpEnabled: true, lastLoginAt: true, createdAt: true, } @@ -351,12 +324,9 @@ export const userController = { user: { id: user.id, username: user.username, - firstName: user.firstName, - lastName: user.lastName, role: user.isAdmin ? 'admin' : 'user', isAdmin: user.isAdmin, isActive: user.isActive, - totpEnabled: user.totpEnabled, lastLoginAt: user.lastLoginAt, createdAt: user.createdAt } diff --git a/backend/src/routes/auth.ts b/backend/src/routes/auth.ts index ef54c58..47f40aa 100644 --- a/backend/src/routes/auth.ts +++ b/backend/src/routes/auth.ts @@ -16,8 +16,6 @@ router.post('/register', [ } return true; }), - body('firstName').optional().isLength({ max: 50 }), - body('lastName').optional().isLength({ max: 50 }), validateRequest ], authController.register); @@ -31,15 +29,6 @@ router.post('/login', [ // Logout router.post('/logout', authMiddleware, authController.logout); -// Setup TOTP -router.post('/setup-totp', authMiddleware, authController.setupTOTP); - -// Verify TOTP -router.post('/verify-totp', [ - body('token').notEmpty(), - validateRequest -], authMiddleware, authController.verifyTOTP); - // Get current user router.get('/me', authMiddleware, authController.getCurrentUser); diff --git a/docker-compose.yml b/docker-compose.yml index edce753..6dbc82d 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -14,7 +14,6 @@ services: networks: - pandora_network restart: always - command: npm run start # 前端应用 frontend: @@ -33,7 +32,6 @@ services: networks: - pandora_network restart: always - command: npm run start volumes: sqlite_data: diff --git a/frontend/Dockerfile b/frontend/Dockerfile index 326724c..f735e4c 100644 --- a/frontend/Dockerfile +++ b/frontend/Dockerfile @@ -11,11 +11,14 @@ RUN apk add --no-cache \ COPY package*.json ./ # 安装依赖 -RUN npm ci +RUN npm install # 复制源代码 COPY . . +# 构建项目 +RUN npm run build + # 创建非root用户 RUN addgroup -g 1001 -S nodejs RUN adduser -S nodejs -u 1001 @@ -30,6 +33,5 @@ EXPOSE 3000 # 健康检查 HEALTHCHECK --interval=30s --timeout=3s --start-period=5s --retries=3 \ CMD curl -f http://localhost:3000 || exit 1 - -# 启动命令 - 支持环境变量 -CMD ["npm", "run", "dev", "--", "--host", "0.0.0.0"] \ No newline at end of file +# 启动命令 +CMD ["npm", "run", "start"] \ No newline at end of file diff --git a/frontend/package.json b/frontend/package.json index 6888f81..acb8e4f 100644 --- a/frontend/package.json +++ b/frontend/package.json @@ -4,8 +4,9 @@ "description": "Pandora 前端应用", "type": "module", "scripts": { + "start": "vite preview --host 0.0.0.0 --port 3000", "dev": "vite", - "build": "vue-tsc && vite build", + "build": "vite build", "preview": "vite preview", "test": "vitest", "test:ui": "vitest --ui", @@ -13,17 +14,19 @@ "format": "prettier --write src/" }, "dependencies": { - "vue": "^3.3.8", - "vue-router": "^4.2.5", - "pinia": "^2.1.7", - "@vueuse/core": "^10.4.1", - "vee-validate": "^4.10.5", - "vue-toastification": "^2.0.0-rc.5", - "axios": "^1.5.0", "@headlessui/vue": "^1.7.16", "@heroicons/vue": "^2.0.18", + "@vue/runtime-core": "^3.3.4", + "@vue/runtime-dom": "^3.3.4", + "@vueuse/core": "^10.4.1", + "axios": "^1.5.0", "clsx": "^2.0.0", - "tailwind-merge": "^1.14.0" + "pinia": "^2.1.7", + "tailwind-merge": "^1.14.0", + "vee-validate": "^4.10.5", + "vue": "^3.3.4", + "vue-router": "^4.2.4", + "vue-toastification": "^2.0.0-rc.5" }, "devDependencies": { "@types/node": "^20.6.3", @@ -38,13 +41,13 @@ "postcss": "^8.4.29", "prettier": "^3.0.3", "tailwindcss": "^3.3.3", - "typescript": "~5.2.0", + "typescript": "^5.8.3", "vite": "^4.4.11", "vitest": "^0.34.4", - "vue-tsc": "^1.8.15" + "vue-tsc": "^3.0.1" }, "engines": { "node": ">=18.0.0", "npm": ">=8.0.0" } -} \ No newline at end of file +} diff --git a/frontend/src/config/websites.ts b/frontend/src/config/websites.ts index 17be843..e3bb90c 100644 --- a/frontend/src/config/websites.ts +++ b/frontend/src/config/websites.ts @@ -11,11 +11,11 @@ export interface WebsiteConfig { const getWebsiteUrls = () => { // 检查是否在浏览器环境中 if (typeof window !== 'undefined') { - // 在客户端,使用Vite定义的全局变量 + // 在客户端,使用Vite注入的环境变量 return { - claude: (window as any).__CLAUDE_URL__ || 'https://chat.micar9.com:8443', - chatgpt: (window as any).__CHATGPT_URL__ || 'https://chat.openai.com', - grok: (window as any).__GROK_URL__ || 'https://grok-mirror.micar9.com:8443' + claude: import.meta.env.CLAUDE_TARGET_URL || 'https://chat.micar9.com:8443', + chatgpt: import.meta.env.CHATGPT_TARGET_URL || 'https://chat.openai.com', + grok: import.meta.env.GROK_TARGET_URL || 'https://grok-mirror.micar9.com:8443' } } diff --git a/frontend/src/router/index.ts b/frontend/src/router/index.ts index 3afacb2..0c7010e 100644 --- a/frontend/src/router/index.ts +++ b/frontend/src/router/index.ts @@ -1,9 +1,7 @@ +import type { RouteRecordRaw, NavigationGuardNext, RouteLocationNormalized } from 'vue-router' import { createRouter, createWebHistory } from 'vue-router' -import type { RouteRecordRaw } from 'vue-router' import { useAuthStore } from '@/stores/auth' -import { useAdminStore } from '@/stores/admin' import { adminAuth } from '@/utils/auth' -import { useToast } from 'vue-toastification' const routes: RouteRecordRaw[] = [ { @@ -74,17 +72,18 @@ const router = createRouter({ }) // 路由守卫 -router.beforeEach((to: any, from: any, next: any) => { +router.beforeEach(async ( + to: RouteLocationNormalized, + _from: RouteLocationNormalized, + next: NavigationGuardNext +) => { // 设置页面标题 - document.title = `${to.meta.title} - Pandora` - - // 获取认证状态 - const authStore = useAuthStore() - const adminStore = useAdminStore() - const toast = useToast() + const title = to.meta.title as string + document.title = `${title} - Pandora` // 检查是否需要用户认证 if (to.meta.requiresAuth) { + const authStore = useAuthStore() if (!authStore.isLoggedIn) { next('/') return diff --git a/frontend/src/stores/admin.ts b/frontend/src/stores/admin.ts index 85d0847..8487227 100644 --- a/frontend/src/stores/admin.ts +++ b/frontend/src/stores/admin.ts @@ -2,7 +2,7 @@ import { defineStore } from 'pinia' import { ref, computed } from 'vue' import { adminAPI } from '@/utils/api' import { adminAuth } from '@/utils/auth' -import type { User, PaginatedResponse } from '@/types' +import type { User } from '@/types' export const useAdminStore = defineStore('admin', () => { // 状态 diff --git a/frontend/src/stores/auth.ts b/frontend/src/stores/auth.ts index 88bfa80..45cf696 100644 --- a/frontend/src/stores/auth.ts +++ b/frontend/src/stores/auth.ts @@ -138,45 +138,6 @@ export const useAuthStore = defineStore('auth', () => { } } - // 设置TOTP - const setupTOTP = async () => { - loading.value = true - error.value = null - - try { - const response = await authAPI.setupTOTP() - return response - } catch (err: any) { - error.value = err.response?.data?.message || '设置二步验证失败' - throw err - } finally { - loading.value = false - } - } - - // 验证TOTP - const verifyTOTP = async (totpToken: string) => { - loading.value = true - error.value = null - - try { - const response = await authAPI.verifyTOTP(totpToken) - - // 更新用户信息 - if (user.value && token.value) { - user.value.totpEnabled = true - userAuth.setLogin(token.value, user.value) - } - - return response - } catch (err: any) { - error.value = err.response?.data?.message || '验证失败' - throw err - } finally { - loading.value = false - } - } - // 获取用户信息 const getProfile = async () => { loading.value = true @@ -238,8 +199,6 @@ export const useAuthStore = defineStore('auth', () => { resendVerification, forgotPassword, resetPassword, - setupTOTP, - verifyTOTP, getProfile, logout, clearError diff --git a/frontend/src/types/index.ts b/frontend/src/types/index.ts index 7a58738..1022a15 100644 --- a/frontend/src/types/index.ts +++ b/frontend/src/types/index.ts @@ -2,12 +2,13 @@ export interface User { id: string username: string + email: string role: string isActive: boolean emailVerified?: boolean - totpEnabled: boolean createdAt: string updatedAt: string + accounts?: string[] } // 网站账号相关类型 @@ -47,15 +48,10 @@ export interface Session { // 审计日志相关类型 export interface AuditLog { id: string - userId: string action: string - resource: string - resourceId?: string - details?: any - ipAddress?: string - userAgent?: string - createdAt: string - user: User + description: string + time: string + ipAddress: string } // API响应类型 @@ -116,4 +112,37 @@ export interface Notification { message: string duration?: number createdAt: string +} + +export interface Account { + id: string + username: string + description: string +} + +export interface SystemSettings { + allowRegistration: boolean + sessionTimeout: number + [key: string]: any +} + +export interface AdminMenu { + id: string + name: string + description: string + icon: string + path: string +} + +export interface AdminUser { + id: string + username: string + role: string +} + +export interface SystemStats { + totalUsers: number + totalAccounts: number + todayVisits: number + alerts: number } \ No newline at end of file diff --git a/frontend/src/utils/api.ts b/frontend/src/utils/api.ts index eceff11..cea9a69 100644 --- a/frontend/src/utils/api.ts +++ b/frontend/src/utils/api.ts @@ -113,17 +113,6 @@ export const authAPI = { return response.data }, - // 设置TOTP - async setupTOTP() { - const response = await api.post('/auth/setup-totp') - return response.data - }, - - // 验证TOTP - async verifyTOTP(token: string) { - const response = await api.post('/auth/verify-totp', { token }) - return response.data - }, // 获取用户信息 async getProfile() { @@ -147,26 +136,7 @@ export const authAPI = { const response = await api.post('/auth/logout') return response.data }, - - // 获取TOTP二维码 - async getTOTPQRCode() { - const response = await api.get('/auth/totp/qr-code') - return response.data - }, - - // 启用TOTP - async enableTOTP(token: string) { - const response = await api.post('/auth/totp/enable', { token }) - return response.data - }, - - // 禁用TOTP - async disableTOTP(password: string) { - const response = await api.post('/auth/totp/disable', { password }) - return response.data - } } - // 账号管理API export const accountAPI = { // 获取用户可用账号 diff --git a/frontend/src/views/Admin.vue b/frontend/src/views/Admin.vue index a22e79f..defd4c9 100644 --- a/frontend/src/views/Admin.vue +++ b/frontend/src/views/Admin.vue @@ -301,70 +301,94 @@ import { ref, onMounted } from 'vue' import { useRouter } from 'vue-router' import { useAdminStore } from '@/stores/admin' +import type { AdminMenu, AdminUser, SystemStats } from '@/types' import { adminAuth } from '@/utils/auth' -import { useToast } from 'vue-toastification' const router = useRouter() const adminStore = useAdminStore() -const toast = useToast() -// 管理菜单 -const adminMenus = ref([ - { - id: 1, - name: '用户管理', - description: '管理用户账号和权限', - icon: 'UserIcon', - route: '/admin/users' - }, - { - id: 2, - name: '账号管理', - description: '管理网站账号和token', - icon: 'KeyIcon', - route: '/admin/accounts' - }, - { - id: 3, - name: '权限管理', - description: '配置用户访问权限', - icon: 'ShieldIcon', - route: '/admin/permissions' - }, - { - id: 4, - name: '系统监控', - description: '查看系统运行状态', - icon: 'ChartIcon', - route: '/admin/monitor' - } -]) - -// 统计数据 -const stats = ref({ +const adminUser = ref(null) +const stats = ref({ totalUsers: 0, totalAccounts: 0, todayVisits: 0, alerts: 0 }) -// 最近活动 -const recentActivities = ref([]) +const adminMenus: AdminMenu[] = [ + { + id: 'users', + name: '用户管理', + description: '管理系统用户', + icon: 'UserIcon', + path: '/admin/users' + }, + { + id: 'accounts', + name: '账号管理', + description: '管理网站账号', + icon: 'KeyIcon', + path: '/admin/accounts' + }, + { + id: 'permissions', + name: '权限管理', + description: '配置访问权限', + icon: 'ShieldIcon', + path: '/admin/permissions' + }, + { + id: 'monitor', + name: '系统监控', + description: '监控系统状态', + icon: 'ChartIcon', + path: '/admin/monitor' + } +] // 导航到菜单 -const navigateToMenu = (menu: any) => { - router.push(menu.route) +const navigateToMenu = (menu: AdminMenu) => { + router.push(menu.path) } -// 管理员用户信息 -const adminUser = ref(null) - // 退出登录 -const handleLogout = () => { - adminAuth.logout() - router.push('/admin/login') +const handleLogout = async () => { + try { + await adminStore.logout() + router.push('/admin/login') + } catch (error) { + console.error('退出登录失败:', error) + } } +// 加载管理员信息 +const loadAdminInfo = async () => { + try { + // 从adminAuth获取管理员信息 + const adminInfo = adminAuth.getAdminInfo() + if (adminInfo) { + adminUser.value = adminInfo + } + } catch (error) { + console.error('加载管理员信息失败:', error) + } +} + +// 加载系统统计数据 +const loadStats = async () => { + try { + const response = await adminStore.getStats() + if (response && response.stats) { + stats.value = response.stats + } + } catch (error) { + console.error('加载系统统计失败:', error) + } +} + +// 最近活动 +const recentActivities = ref([]) + // 格式化时间 const formatTime = (time: string) => { const date = new Date(time) @@ -382,40 +406,6 @@ const formatTime = (time: string) => { } } -// 加载统计数据 -const loadStats = async () => { - try { - console.log('开始加载统计数据...') - const response = await adminStore.getStats() - console.log('统计数据响应:', response) - - if (response.success && response.data) { - stats.value = response.data - console.log('统计数据加载成功:', stats.value) - } else { - console.error('统计数据格式错误:', response) - toast.error('统计数据格式错误') - // 设置默认值 - stats.value = { - totalUsers: 0, - totalAccounts: 0, - todayVisits: 0, - alerts: 0 - } - } - } catch (error) { - console.error('加载统计数据失败:', error) - toast.error('加载统计数据失败') - // 设置默认值 - stats.value = { - totalUsers: 0, - totalAccounts: 0, - todayVisits: 0, - alerts: 0 - } - } -} - // 加载最近活动 const loadRecentActivities = async () => { try { @@ -423,50 +413,22 @@ const loadRecentActivities = async () => { const response = await adminStore.getRecentActivities() console.log('最近活动响应:', response) - if (response.success && response.data) { - recentActivities.value = response.data.activities || [] + if (response && response.activities) { + recentActivities.value = response.activities console.log('最近活动加载成功:', recentActivities.value) } else { console.error('最近活动数据格式错误:', response) - toast.error('最近活动数据格式错误') recentActivities.value = [] } } catch (error) { console.error('加载最近活动失败:', error) - toast.error('加载最近活动失败') recentActivities.value = [] } } -// 组件挂载时获取数据 onMounted(async () => { - - // 检查管理员登录状态 - if (!adminAuth.isLoggedIn()) { - router.push('/admin/login') - return - } - - // 获取管理员用户信息 - const adminInfo = adminAuth.getAdminInfo() - - if (!adminInfo) { - // 如果没有管理员信息,清除登录状态并跳转到登录页 - adminAuth.logout() - router.push('/admin/login') - return - } - - adminUser.value = adminInfo - - // 加载数据 - try { - await Promise.all([ - loadStats(), - loadRecentActivities() - ]) - } catch (error) { - console.error('加载数据失败:', error) - } + await loadAdminInfo() + await loadStats() + await loadRecentActivities() }) \ No newline at end of file diff --git a/frontend/src/views/AdminPermissions.vue b/frontend/src/views/AdminPermissions.vue index 4ab7e53..0b0f6b1 100644 --- a/frontend/src/views/AdminPermissions.vue +++ b/frontend/src/views/AdminPermissions.vue @@ -164,23 +164,6 @@

安全设置

-
-
-

二步验证

-

是否启用TOTP二步验证

-
- -
-

会话超时

@@ -241,85 +224,62 @@ import { ref, computed, onMounted } from 'vue' import { useAdminStore } from '@/stores/admin' import { useToast } from 'vue-toastification' +import type { User, Account, SystemSettings } from '@/types' const adminStore = useAdminStore() const toast = useToast() -// 搜索和筛选 +const users = ref([]) +const availableAccounts = ref([]) const searchQuery = ref('') const accountFilter = ref('') - -// 用户列表 -const users = ref([]) -const filteredUsers = computed(() => { - let filtered = users.value - - if (searchQuery.value) { - filtered = filtered.filter((user: any) => - user.username.toLowerCase().includes(searchQuery.value.toLowerCase()) || - user.email.toLowerCase().includes(searchQuery.value.toLowerCase()) - ) - } - - if (accountFilter.value) { - filtered = filtered.filter((user: any) => - user.accounts?.includes(accountFilter.value) - ) - } - - return filtered -}) - -// 可用账号 -const availableAccounts = ref([]) - -// 加载可用账号 -const loadAvailableAccounts = async () => { - try { - const response = await adminStore.getAccounts() - availableAccounts.value = response.accounts || [] - } catch (error) { - console.error('加载可用账号失败:', error) - // 如果加载失败,使用默认数据 - availableAccounts.value = [ - { id: 'account1', username: '账号1', description: '第一个登录账号' }, - { id: 'account2', username: '账号2', description: '第二个登录账号' }, - { id: 'account3', username: '账号3', description: '第三个登录账号' } - ] - } -} - -// 系统设置 -const systemSettings = ref({ - allowRegistration: true, - enableTOTP: false, +const showAccountModal = ref(false) +const selectedUser = ref(null) +const selectedUserAccounts = ref([]) +const systemSettings = ref({ + allowRegistration: false, sessionTimeout: 24 }) -// 模态框状态 -const showAccountModal = ref(false) -const selectedUser = ref(null) -const selectedUserAccounts = ref([]) +// 过滤用户列表 +const filteredUsers = computed(() => { + return users.value.filter(user => { + const matchesSearch = !searchQuery.value || + user.username.toLowerCase().includes(searchQuery.value.toLowerCase()) || + user.email.toLowerCase().includes(searchQuery.value.toLowerCase()) + + const matchesAccount = !accountFilter.value || + (user.accounts && user.accounts.includes(accountFilter.value)) + + return matchesSearch && matchesAccount + }) +}) -// 搜索处理 -const handleSearch = () => { - // 这里可以添加实际的搜索逻辑 - console.log('搜索:', searchQuery.value, '账号筛选:', accountFilter.value) -} - -// 根据账户ID获取账户名称 -const getAccountName = (accountId: string) => { +// 获取账号名称 +const getAccountName = (accountId: string): string => { const account = availableAccounts.value.find(acc => acc.id === accountId) return account ? account.username : accountId } // 编辑用户账号权限 -const editUserAccounts = (user: any) => { - selectedUser.value = { ...user } - selectedUserAccounts.value = [...(user.accounts || [])] +const editUserAccounts = (user: User) => { + selectedUser.value = user + selectedUserAccounts.value = user.accounts || [] showAccountModal.value = true } +// 切换系统设置 +const toggleSystemSetting = (setting: keyof SystemSettings) => { + if (typeof systemSettings.value[setting] === 'boolean') { + systemSettings.value[setting] = !systemSettings.value[setting] + } +} + +// 搜索处理 +const handleSearch = () => { + // 实现搜索逻辑 +} + // 切换用户账号权限 const toggleUserAccount = (accountId: string) => { const index = selectedUserAccounts.value.indexOf(accountId) @@ -333,22 +293,25 @@ const toggleUserAccount = (accountId: string) => { // 保存用户账号权限 const saveUserAccounts = async () => { try { + if (!selectedUser.value?.id) { + toast.error('用户ID不存在') + return + } + // 调用API保存用户账号权限到后端 await adminStore.updateUserAccounts(selectedUser.value.id, selectedUserAccounts.value) - console.log('保存用户账号权限:', selectedUser.value?.id, selectedUserAccounts.value) + console.log('保存用户账号权限:', selectedUser.value.id, selectedUserAccounts.value) // 直接更新本地用户数据 - if (selectedUser.value) { - const userIndex = users.value.findIndex((user: any) => user.id === selectedUser.value.id) - console.log('找到用户索引:', userIndex, '用户ID:', selectedUser.value.id) - if (userIndex !== -1) { - // 使用Vue的响应式更新机制 - users.value[userIndex] = { - ...users.value[userIndex], - accounts: [...selectedUserAccounts.value] - } - console.log('更新后的用户数据:', users.value[userIndex]) + const userIndex = users.value.findIndex((user: any) => user.id === selectedUser.value!.id) + console.log('找到用户索引:', userIndex, '用户ID:', selectedUser.value.id) + if (userIndex !== -1) { + // 使用Vue的响应式更新机制 + users.value[userIndex] = { + ...users.value[userIndex], + accounts: [...selectedUserAccounts.value] } + console.log('更新后的用户数据:', users.value[userIndex]) } toast.success('权限保存成功') @@ -359,12 +322,6 @@ const saveUserAccounts = async () => { } } -// 切换系统设置 -const toggleSystemSetting = (setting: string) => { - systemSettings.value[setting] = !systemSettings.value[setting] - console.log('切换系统设置:', setting, systemSettings.value[setting]) -} - // 加载用户列表 const loadUsers = async () => { try { @@ -380,6 +337,22 @@ const loadUsers = async () => { } } +// 加载可用账号 +const loadAvailableAccounts = async () => { + try { + const response = await adminStore.getAccounts() + availableAccounts.value = response.accounts || [] + } catch (error) { + console.error('加载可用账号失败:', error) + // 如果加载失败,使用默认数据 + availableAccounts.value = [ + { id: 'account1', username: '账号1', description: '第一个登录账号' }, + { id: 'account2', username: '账号2', description: '第二个登录账号' }, + { id: 'account3', username: '账号3', description: '第三个登录账号' } + ] + } +} + // 组件挂载时加载数据 onMounted(async () => { await loadUsers() diff --git a/frontend/src/views/AdminUsers.vue b/frontend/src/views/AdminUsers.vue index 8c18881..a244c50 100644 --- a/frontend/src/views/AdminUsers.vue +++ b/frontend/src/views/AdminUsers.vue @@ -103,9 +103,6 @@
{{ user.username }}
-
- {{ user.firstName || user.lastName ? `${user.firstName || ''} ${user.lastName || ''}`.trim() : '未设置姓名' }} -
@@ -269,7 +266,7 @@ const showCreateModal = ref(false) const createForm = reactive({ username: '', password: '', - role: 'user' + role: 'user' as string }) // 编辑用户模态框 @@ -277,7 +274,7 @@ const showEditModal = ref(false) const editForm = reactive({ id: '', username: '', - role: 'user', + role: 'user' as string, isActive: true, password: '' }) @@ -324,7 +321,11 @@ const changePage = async (page: number) => { // 创建用户 const handleCreateUser = async () => { try { - await adminStore.createUser(createForm) + await adminStore.createUser({ + username: createForm.username, + password: createForm.password, + role: createForm.role + }) toast.success('用户创建成功') showCreateModal.value = false diff --git a/frontend/src/views/Dashboard.vue b/frontend/src/views/Dashboard.vue index 172bf5f..4af81bb 100644 --- a/frontend/src/views/Dashboard.vue +++ b/frontend/src/views/Dashboard.vue @@ -226,7 +226,7 @@ onMounted(async () => { // 加载用户账号 await loadUserAccounts() - } catch (error) { + } catch (error: any) { console.error('Dashboard初始化失败:', error) // 如果是认证错误,重定向到登录页面 diff --git a/frontend/vite.config.ts b/frontend/vite.config.ts index fb85a28..bb44473 100644 --- a/frontend/vite.config.ts +++ b/frontend/vite.config.ts @@ -10,20 +10,12 @@ export default defineConfig({ '@': resolve(__dirname, 'src'), }, }, - define: { - // 定义环境变量,使其在客户端可用 - VITE_API_URL: JSON.stringify(process.env.VITE_API_URL || 'http://localhost:3001'), - VITE_APP_NAME: JSON.stringify(process.env.VITE_APP_NAME || 'Pandora'), - VITE_CLAUDE_TARGET_URL: JSON.stringify(process.env.CLAUDE_TARGET_URL || 'https://claude.ai'), - VITE_CHATGPT_TARGET_URL: JSON.stringify(process.env.CHATGPT_TARGET_URL || 'https://chat.openai.com'), - VITE_GROK_TARGET_URL: JSON.stringify(process.env.GROK_TARGET_URL || 'https://grok.x.ai'), - }, server: { port: 3000, host: '0.0.0.0', proxy: { '/api': { - target: 'http://localhost:3001', + target: 'http://backend:3001', changeOrigin: true, secure: false, }, diff --git a/package-lock.json b/package-lock.json index bc9edd0..182b29a 100644 --- a/package-lock.json +++ b/package-lock.json @@ -27,7 +27,6 @@ "license": "ISC", "dependencies": { "@prisma/client": "^5.7.1", - "@types/http-proxy-middleware": "^0.19.3", "bcryptjs": "^2.4.3", "cors": "^2.8.5", "dotenv": "^16.3.1", @@ -36,12 +35,8 @@ "express-rate-limit": "^7.1.5", "express-validator": "^7.0.1", "helmet": "^7.1.0", - "http-proxy-middleware": "^3.0.5", "jsonwebtoken": "^9.0.2", "nodemailer": "^6.9.7", - "qrcode": "^1.5.3", - "redis": "^4.6.11", - "speakeasy": "^2.0.0", "winston": "^3.11.0" }, "devDependencies": { @@ -51,42 +46,28 @@ "@types/jsonwebtoken": "^9.0.5", "@types/node": "^20.10.5", "@types/nodemailer": "^6.4.14", - "@types/qrcode": "^1.5.5", - "@types/speakeasy": "^2.0.10", "nodemon": "^3.0.2", "prisma": "^5.7.1", "ts-node": "^10.9.2", "typescript": "^5.3.3" } }, - "backend/node_modules/typescript": { - "version": "5.8.3", - "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.8.3.tgz", - "integrity": "sha512-p1diW6TqL9L07nNxvRMM7hMMw4c5XOo/1ibL4aAIGmSAt9slTE1Xgw5KWuof2uTOvCg9BY7ZRi+GaF+7sfgPeQ==", - "dev": true, - "license": "Apache-2.0", - "bin": { - "tsc": "bin/tsc", - "tsserver": "bin/tsserver" - }, - "engines": { - "node": ">=14.17" - } - }, "frontend": { "name": "pandora-frontend", "version": "1.0.0", "dependencies": { "@headlessui/vue": "^1.7.16", "@heroicons/vue": "^2.0.18", + "@vue/runtime-core": "^3.3.4", + "@vue/runtime-dom": "^3.3.4", "@vueuse/core": "^10.4.1", "axios": "^1.5.0", "clsx": "^2.0.0", "pinia": "^2.1.7", "tailwind-merge": "^1.14.0", "vee-validate": "^4.10.5", - "vue": "^3.3.8", - "vue-router": "^4.2.5", + "vue": "^3.3.4", + "vue-router": "^4.2.4", "vue-toastification": "^2.0.0-rc.5" }, "devDependencies": { @@ -102,16 +83,31 @@ "postcss": "^8.4.29", "prettier": "^3.0.3", "tailwindcss": "^3.3.3", - "typescript": "~5.2.0", + "typescript": "^5.8.3", "vite": "^4.4.11", "vitest": "^0.34.4", - "vue-tsc": "^1.8.15" + "vue-tsc": "^3.0.1" }, "engines": { "node": ">=18.0.0", "npm": ">=8.0.0" } }, + "frontend/node_modules/vue-router": { + "version": "4.2.4", + "resolved": "https://registry.npmjs.org/vue-router/-/vue-router-4.2.4.tgz", + "integrity": "sha512-9PISkmaCO02OzPVOMq2w82ilty6+xJmQrarYZDkjZBfl4RvYAlt4PKnEX21oW4KTtWfa9OuO/b3qk1Od3AEdCQ==", + "license": "MIT", + "dependencies": { + "@vue/devtools-api": "^6.5.0" + }, + "funding": { + "url": "https://github.com/sponsors/posva" + }, + "peerDependencies": { + "vue": "^3.2.0" + } + }, "node_modules/@alloc/quick-lru": { "version": "5.2.0", "resolved": "https://registry.npmjs.org/@alloc/quick-lru/-/quick-lru-5.2.0.tgz", @@ -772,6 +768,29 @@ "dev": true, "license": "BSD-3-Clause" }, + "node_modules/@isaacs/balanced-match": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/@isaacs/balanced-match/-/balanced-match-4.0.1.tgz", + "integrity": "sha512-yzMTt9lEb8Gv7zRioUilSglI0c0smZ9k5D65677DLWLtWJaXIS3CqcGyUFByYKlnUj6TkjLVs54fBl6+TiGQDQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": "20 || >=22" + } + }, + "node_modules/@isaacs/brace-expansion": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/@isaacs/brace-expansion/-/brace-expansion-5.0.0.tgz", + "integrity": "sha512-ZT55BDLV0yv0RBm2czMiZ+SqCGO7AvmOM3G/w2xhVPH+te0aKgFjmBvGlL1dH+ql2tgGO3MVrbb3jCKyvpgnxA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@isaacs/balanced-match": "^4.0.1" + }, + "engines": { + "node": "20 || >=22" + } + }, "node_modules/@isaacs/cliui": { "version": "8.0.2", "resolved": "https://registry.npmjs.org/@isaacs/cliui/-/cliui-8.0.2.tgz", @@ -1007,65 +1026,6 @@ "@prisma/debug": "5.22.0" } }, - "node_modules/@redis/bloom": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/@redis/bloom/-/bloom-1.2.0.tgz", - "integrity": "sha512-HG2DFjYKbpNmVXsa0keLHp/3leGJz1mjh09f2RLGGLQZzSHpkmZWuwJbAvo3QcRY8p80m5+ZdXZdYOSBLlp7Cg==", - "license": "MIT", - "peerDependencies": { - "@redis/client": "^1.0.0" - } - }, - "node_modules/@redis/client": { - "version": "1.6.1", - "resolved": "https://registry.npmjs.org/@redis/client/-/client-1.6.1.tgz", - "integrity": "sha512-/KCsg3xSlR+nCK8/8ZYSknYxvXHwubJrU82F3Lm1Fp6789VQ0/3RJKfsmRXjqfaTA++23CvC3hqmqe/2GEt6Kw==", - "license": "MIT", - "dependencies": { - "cluster-key-slot": "1.1.2", - "generic-pool": "3.9.0", - "yallist": "4.0.0" - }, - "engines": { - "node": ">=14" - } - }, - "node_modules/@redis/graph": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/@redis/graph/-/graph-1.1.1.tgz", - "integrity": "sha512-FEMTcTHZozZciLRl6GiiIB4zGm5z5F3F6a6FZCyrfxdKOhFlGkiAqlexWMBzCi4DcRoyiOsuLfW+cjlGWyExOw==", - "license": "MIT", - "peerDependencies": { - "@redis/client": "^1.0.0" - } - }, - "node_modules/@redis/json": { - "version": "1.0.7", - "resolved": "https://registry.npmjs.org/@redis/json/-/json-1.0.7.tgz", - "integrity": "sha512-6UyXfjVaTBTJtKNG4/9Z8PSpKE6XgSyEb8iwaqDcy+uKrd/DGYHTWkUdnQDyzm727V7p21WUMhsqz5oy65kPcQ==", - "license": "MIT", - "peerDependencies": { - "@redis/client": "^1.0.0" - } - }, - "node_modules/@redis/search": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/@redis/search/-/search-1.2.0.tgz", - "integrity": "sha512-tYoDBbtqOVigEDMAcTGsRlMycIIjwMCgD8eR2t0NANeQmgK/lvxNAvYyb6bZDD4frHRhIHkJu2TBRvB0ERkOmw==", - "license": "MIT", - "peerDependencies": { - "@redis/client": "^1.0.0" - } - }, - "node_modules/@redis/time-series": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/@redis/time-series/-/time-series-1.1.0.tgz", - "integrity": "sha512-c1Q99M5ljsIuc4YdaCwfUEXsofakb9c8+Zse2qxTadu8TalLXuAESzLvFAvNVbkmSlvlzIQOLpBCmWI9wTOt+g==", - "license": "MIT", - "peerDependencies": { - "@redis/client": "^1.0.0" - } - }, "node_modules/@sinclair/typebox": { "version": "0.27.8", "resolved": "https://registry.npmjs.org/@sinclair/typebox/-/typebox-0.27.8.tgz", @@ -1176,6 +1136,7 @@ "version": "3.4.38", "resolved": "https://registry.npmjs.org/@types/connect/-/connect-3.4.38.tgz", "integrity": "sha512-K6uROf1LD88uDQqJCktA4yzL1YYAK6NgfsI0v/mTgyPKWsX1CnJ0XPSDhViejru1GcRkLWb8RlzFYJRqGUbaug==", + "dev": true, "license": "MIT", "dependencies": { "@types/node": "*" @@ -1224,26 +1185,6 @@ "dev": true, "license": "MIT" }, - "node_modules/@types/http-proxy": { - "version": "1.17.16", - "resolved": "https://registry.npmjs.org/@types/http-proxy/-/http-proxy-1.17.16.tgz", - "integrity": "sha512-sdWoUajOB1cd0A8cRRQ1cfyWNbmFKLAqBB89Y8x5iYyG/mkJHc0YUH8pdWBy2omi9qtCpiIgGjuwO0dQST2l5w==", - "license": "MIT", - "dependencies": { - "@types/node": "*" - } - }, - "node_modules/@types/http-proxy-middleware": { - "version": "0.19.3", - "resolved": "https://registry.npmjs.org/@types/http-proxy-middleware/-/http-proxy-middleware-0.19.3.tgz", - "integrity": "sha512-lnBTx6HCOUeIJMLbI/LaL5EmdKLhczJY5oeXZpX/cXE4rRqb3RmV7VcMpiEfYkmTjipv3h7IAyIINe4plEv7cA==", - "license": "MIT", - "dependencies": { - "@types/connect": "*", - "@types/http-proxy": "*", - "@types/node": "*" - } - }, "node_modules/@types/json-schema": { "version": "7.0.15", "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.15.tgz", @@ -1280,6 +1221,7 @@ "version": "20.19.4", "resolved": "https://registry.npmjs.org/@types/node/-/node-20.19.4.tgz", "integrity": "sha512-OP+We5WV8Xnbuvw0zC2m4qfB/BJvjyCwtNjhHdJxV1639SGSKrLmJkc3fMnp2Qy8nJyHp8RO6umxELN/dS1/EA==", + "dev": true, "license": "MIT", "dependencies": { "undici-types": "~6.21.0" @@ -1295,16 +1237,6 @@ "@types/node": "*" } }, - "node_modules/@types/qrcode": { - "version": "1.5.5", - "resolved": "https://registry.npmjs.org/@types/qrcode/-/qrcode-1.5.5.tgz", - "integrity": "sha512-CdfBi/e3Qk+3Z/fXYShipBT13OJ2fDO2Q2w5CIP5anLTLIndQG9z6P1cnm+8zCWSpm5dnxMFd/uREtb0EXuQzg==", - "dev": true, - "license": "MIT", - "dependencies": { - "@types/node": "*" - } - }, "node_modules/@types/qs": { "version": "6.14.0", "resolved": "https://registry.npmjs.org/@types/qs/-/qs-6.14.0.tgz", @@ -1349,16 +1281,6 @@ "@types/send": "*" } }, - "node_modules/@types/speakeasy": { - "version": "2.0.10", - "resolved": "https://registry.npmjs.org/@types/speakeasy/-/speakeasy-2.0.10.tgz", - "integrity": "sha512-QVRlDW5r4yl7p7xkNIbAIC/JtyOcClDIIdKfuG7PWdDT1MmyhtXSANsildohy0K+Lmvf/9RUtLbNLMacvrVwxA==", - "dev": true, - "license": "MIT", - "dependencies": { - "@types/node": "*" - } - }, "node_modules/@types/triple-beam": { "version": "1.3.5", "resolved": "https://registry.npmjs.org/@types/triple-beam/-/triple-beam-1.3.5.tgz", @@ -1693,34 +1615,32 @@ } }, "node_modules/@volar/language-core": { - "version": "1.11.1", - "resolved": "https://registry.npmjs.org/@volar/language-core/-/language-core-1.11.1.tgz", - "integrity": "sha512-dOcNn3i9GgZAcJt43wuaEykSluAuOkQgzni1cuxLxTV0nJKanQztp7FxyswdRILaKH+P2XZMPRp2S4MV/pElCw==", + "version": "2.4.17", + "resolved": "https://registry.npmjs.org/@volar/language-core/-/language-core-2.4.17.tgz", + "integrity": "sha512-chmRZMbKmcGpKMoO7Reb70uiLrzo0KWC2CkFttKUuKvrE+VYgi+fL9vWMJ07Fv5ulX0V1TAyyacN9q3nc5/ecA==", "dev": true, "license": "MIT", "dependencies": { - "@volar/source-map": "1.11.1" + "@volar/source-map": "2.4.17" } }, "node_modules/@volar/source-map": { - "version": "1.11.1", - "resolved": "https://registry.npmjs.org/@volar/source-map/-/source-map-1.11.1.tgz", - "integrity": "sha512-hJnOnwZ4+WT5iupLRnuzbULZ42L7BWWPMmruzwtLhJfpDVoZLjNBxHDi2sY2bgZXCKlpU5XcsMFoYrsQmPhfZg==", + "version": "2.4.17", + "resolved": "https://registry.npmjs.org/@volar/source-map/-/source-map-2.4.17.tgz", + "integrity": "sha512-QDybtQyO3Ms/NjFqNHTC5tbDN2oK5VH7ZaKrcubtfHBDj63n2pizHC3wlMQ+iT55kQXZUUAbmBX5L1C8CHFeBw==", "dev": true, - "license": "MIT", - "dependencies": { - "muggle-string": "^0.3.1" - } + "license": "MIT" }, "node_modules/@volar/typescript": { - "version": "1.11.1", - "resolved": "https://registry.npmjs.org/@volar/typescript/-/typescript-1.11.1.tgz", - "integrity": "sha512-iU+t2mas/4lYierSnoFOeRFQUhAEMgsFuQxoxvwn5EdQopw43j+J27a4lt9LMInx1gLJBC6qL14WYGlgymaSMQ==", + "version": "2.4.17", + "resolved": "https://registry.npmjs.org/@volar/typescript/-/typescript-2.4.17.tgz", + "integrity": "sha512-3paEFNh4P5DkgNUB2YkTRrfUekN4brAXxd3Ow1syMqdIPtCZHbUy4AW99S5RO/7mzyTWPMdDSo3mqTpB/LPObQ==", "dev": true, "license": "MIT", "dependencies": { - "@volar/language-core": "1.11.1", - "path-browserify": "^1.0.1" + "@volar/language-core": "2.4.17", + "path-browserify": "^1.0.1", + "vscode-uri": "^3.0.8" } }, "node_modules/@vue/compiler-core": { @@ -1785,6 +1705,17 @@ "@vue/shared": "3.5.17" } }, + "node_modules/@vue/compiler-vue2": { + "version": "2.7.16", + "resolved": "https://registry.npmjs.org/@vue/compiler-vue2/-/compiler-vue2-2.7.16.tgz", + "integrity": "sha512-qYC3Psj9S/mfu9uVi5WvNZIzq+xnXMhOwbTFKKDD7b1lhpnn71jXSFdTQ+WsIEk0ONCd7VV2IMm7ONl6tbQ86A==", + "dev": true, + "license": "MIT", + "dependencies": { + "de-indent": "^1.0.2", + "he": "^1.2.0" + } + }, "node_modules/@vue/devtools-api": { "version": "6.6.4", "resolved": "https://registry.npmjs.org/@vue/devtools-api/-/devtools-api-6.6.4.tgz", @@ -1856,21 +1787,20 @@ } }, "node_modules/@vue/language-core": { - "version": "1.8.27", - "resolved": "https://registry.npmjs.org/@vue/language-core/-/language-core-1.8.27.tgz", - "integrity": "sha512-L8Kc27VdQserNaCUNiSFdDl9LWT24ly8Hpwf1ECy3aFb9m6bDhBGQYOujDm21N7EW3moKIOKEanQwe1q5BK+mA==", + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/@vue/language-core/-/language-core-3.0.1.tgz", + "integrity": "sha512-sq+/Mc1IqIexWEQ+Q2XPiDb5SxSvY5JPqHnMOl/PlF5BekslzduX8dglSkpC17VeiAQB6dpS+4aiwNLJRduCNw==", "dev": true, "license": "MIT", "dependencies": { - "@volar/language-core": "~1.11.1", - "@volar/source-map": "~1.11.1", - "@vue/compiler-dom": "^3.3.0", - "@vue/shared": "^3.3.0", - "computeds": "^0.0.1", - "minimatch": "^9.0.3", - "muggle-string": "^0.3.1", - "path-browserify": "^1.0.1", - "vue-template-compiler": "^2.7.14" + "@volar/language-core": "2.4.17", + "@vue/compiler-dom": "^3.5.0", + "@vue/compiler-vue2": "^2.7.16", + "@vue/shared": "^3.5.0", + "alien-signals": "^2.0.5", + "minimatch": "^10.0.1", + "muggle-string": "^0.4.1", + "path-browserify": "^1.0.1" }, "peerDependencies": { "typescript": "*" @@ -1881,6 +1811,22 @@ } } }, + "node_modules/@vue/language-core/node_modules/minimatch": { + "version": "10.0.3", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-10.0.3.tgz", + "integrity": "sha512-IPZ167aShDZZUMdRk66cyQAW3qr0WzbHkPdMYa8bzZhlHhO3jALbKdxcaak7W9FfT2rZNpQuUu4Od7ILEpXSaw==", + "dev": true, + "license": "ISC", + "dependencies": { + "@isaacs/brace-expansion": "^5.0.0" + }, + "engines": { + "node": "20 || >=22" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, "node_modules/@vue/reactivity": { "version": "3.5.17", "resolved": "https://registry.npmjs.org/@vue/reactivity/-/reactivity-3.5.17.tgz", @@ -2075,10 +2021,18 @@ "url": "https://github.com/sponsors/epoberezkin" } }, + "node_modules/alien-signals": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/alien-signals/-/alien-signals-2.0.5.tgz", + "integrity": "sha512-PdJB6+06nUNAClInE3Dweq7/2xVAYM64vvvS1IHVHSJmgeOtEdrAGyp7Z2oJtYm0B342/Exd2NT0uMJaThcjLQ==", + "dev": true, + "license": "MIT" + }, "node_modules/ansi-regex": { "version": "5.0.1", "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", + "dev": true, "license": "MIT", "engines": { "node": ">=8" @@ -2088,6 +2042,7 @@ "version": "4.3.0", "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, "license": "MIT", "dependencies": { "color-convert": "^2.0.1" @@ -2228,12 +2183,6 @@ "dev": true, "license": "MIT" }, - "node_modules/base32.js": { - "version": "0.0.1", - "resolved": "https://registry.npmjs.org/base32.js/-/base32.js-0.0.1.tgz", - "integrity": "sha512-EGHIRiegFa62/SsA1J+Xs2tIzludPdzM064N9wjbiEgHnGnJ1V0WEpA4pEwCYT5nDvZk3ubf0shqaCS7k6xeUQ==", - "license": "MIT" - }, "node_modules/bcryptjs": { "version": "2.4.3", "resolved": "https://registry.npmjs.org/bcryptjs/-/bcryptjs-2.4.3.tgz", @@ -2334,6 +2283,7 @@ "version": "3.0.3", "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.3.tgz", "integrity": "sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==", + "dev": true, "license": "MIT", "dependencies": { "fill-range": "^7.1.1" @@ -2439,15 +2389,6 @@ "node": ">=6" } }, - "node_modules/camelcase": { - "version": "5.3.1", - "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-5.3.1.tgz", - "integrity": "sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==", - "license": "MIT", - "engines": { - "node": ">=6" - } - }, "node_modules/camelcase-css": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/camelcase-css/-/camelcase-css-2.0.1.tgz", @@ -2643,15 +2584,6 @@ "node": ">=6" } }, - "node_modules/cluster-key-slot": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/cluster-key-slot/-/cluster-key-slot-1.1.2.tgz", - "integrity": "sha512-RMr0FhtfXemyinomL4hrWcYJxmX6deFdCxpJzhDttxgO1+bcCnkk+9drydLVDmAMG7NE6aN/fl4F7ucU/90gAA==", - "license": "Apache-2.0", - "engines": { - "node": ">=0.10.0" - } - }, "node_modules/color": { "version": "3.2.1", "resolved": "https://registry.npmjs.org/color/-/color-3.2.1.tgz", @@ -2666,6 +2598,7 @@ "version": "2.0.1", "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, "license": "MIT", "dependencies": { "color-name": "~1.1.4" @@ -2737,13 +2670,6 @@ "node": ">=14" } }, - "node_modules/computeds": { - "version": "0.0.1", - "resolved": "https://registry.npmjs.org/computeds/-/computeds-0.0.1.tgz", - "integrity": "sha512-7CEBgcMjVmitjYo5q8JTJVra6X5mQ20uTThdK+0kR7UEaDrAWEQcRiBtWJzga4eRpP6afNwwLsX2SET2JhVB1Q==", - "dev": true, - "license": "MIT" - }, "node_modules/concat-map": { "version": "0.0.1", "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", @@ -2958,6 +2884,7 @@ "version": "4.4.1", "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.1.tgz", "integrity": "sha512-KcKCqiftBJcZr++7ykoDIEwSa3XWowTfNPo92BYxjXiyYEVrUQh2aLyhxBCwww+heortUFxEJYcRzosstTEBYQ==", + "dev": true, "license": "MIT", "dependencies": { "ms": "^2.1.3" @@ -2971,15 +2898,6 @@ } } }, - "node_modules/decamelize": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-1.2.0.tgz", - "integrity": "sha512-z2S+W9X73hAUUki+N+9Za2lBlun89zigOyGrsax+KUQ6wKW4ZoWpEYBkGhQjwAjjDCkWxhY0VKEhk8wzY7F5cA==", - "license": "MIT", - "engines": { - "node": ">=0.10.0" - } - }, "node_modules/decimal.js": { "version": "10.5.0", "resolved": "https://registry.npmjs.org/decimal.js/-/decimal.js-10.5.0.tgz", @@ -3062,12 +2980,6 @@ "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, - "node_modules/dijkstrajs": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/dijkstrajs/-/dijkstrajs-1.0.3.tgz", - "integrity": "sha512-qiSlmBq9+BCdCA/L46dw8Uy93mloxsPSbwnm5yrKn2vMPiy8KyAskTF6zuV/j5BMsmOGZDPs7KjU+mjb670kfA==", - "license": "MIT" - }, "node_modules/dir-glob": { "version": "3.0.1", "resolved": "https://registry.npmjs.org/dir-glob/-/dir-glob-3.0.1.tgz", @@ -3609,12 +3521,6 @@ "node": ">= 0.6" } }, - "node_modules/eventemitter3": { - "version": "4.0.7", - "resolved": "https://registry.npmjs.org/eventemitter3/-/eventemitter3-4.0.7.tgz", - "integrity": "sha512-8guHBZCwKnFhYdHr2ysuRWErTwhoN2X8XELRlrRwpmfeY2jjuUN4taQMsULKUVo1K4DvZl+0pgfyoysHxvmvEw==", - "license": "MIT" - }, "node_modules/express": { "version": "4.21.2", "resolved": "https://registry.npmjs.org/express/-/express-4.21.2.tgz", @@ -3804,6 +3710,7 @@ "version": "7.1.1", "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.1.1.tgz", "integrity": "sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==", + "dev": true, "license": "MIT", "dependencies": { "to-regex-range": "^5.0.1" @@ -4006,19 +3913,11 @@ "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/generic-pool": { - "version": "3.9.0", - "resolved": "https://registry.npmjs.org/generic-pool/-/generic-pool-3.9.0.tgz", - "integrity": "sha512-hymDOu5B53XvN4QT9dBmZxPX4CWhBPPLguTZ9MMFeFa/Kg0xWVfylOVNlJji/E7yTZWFd/q9GO5TxDLq156D7g==", - "license": "MIT", - "engines": { - "node": ">= 4" - } - }, "node_modules/get-caller-file": { "version": "2.0.5", "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz", "integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==", + "dev": true, "license": "ISC", "engines": { "node": "6.* || 8.* || >= 10.*" @@ -4280,20 +4179,6 @@ "node": ">= 0.8" } }, - "node_modules/http-proxy": { - "version": "1.18.1", - "resolved": "https://registry.npmjs.org/http-proxy/-/http-proxy-1.18.1.tgz", - "integrity": "sha512-7mz/721AbnJwIVbnaSv1Cz3Am0ZLT/UBwkC92VlxhXv/k/BBQfM2fXElQNC27BVGr0uwUpplYPQM9LnaBMR5NQ==", - "license": "MIT", - "dependencies": { - "eventemitter3": "^4.0.0", - "follow-redirects": "^1.0.0", - "requires-port": "^1.0.0" - }, - "engines": { - "node": ">=8.0.0" - } - }, "node_modules/http-proxy-agent": { "version": "5.0.0", "resolved": "https://registry.npmjs.org/http-proxy-agent/-/http-proxy-agent-5.0.0.tgz", @@ -4309,23 +4194,6 @@ "node": ">= 6" } }, - "node_modules/http-proxy-middleware": { - "version": "3.0.5", - "resolved": "https://registry.npmjs.org/http-proxy-middleware/-/http-proxy-middleware-3.0.5.tgz", - "integrity": "sha512-GLZZm1X38BPY4lkXA01jhwxvDoOkkXqjgVyUzVxiEK4iuRu03PZoYHhHRwxnfhQMDuaxi3vVri0YgSro/1oWqg==", - "license": "MIT", - "dependencies": { - "@types/http-proxy": "^1.17.15", - "debug": "^4.3.6", - "http-proxy": "^1.18.1", - "is-glob": "^4.0.3", - "is-plain-object": "^5.0.0", - "micromatch": "^4.0.8" - }, - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" - } - }, "node_modules/https-proxy-agent": { "version": "5.0.1", "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-5.0.1.tgz", @@ -4470,6 +4338,7 @@ "version": "2.1.1", "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", "integrity": "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==", + "dev": true, "license": "MIT", "engines": { "node": ">=0.10.0" @@ -4479,6 +4348,7 @@ "version": "3.0.0", "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", + "dev": true, "license": "MIT", "engines": { "node": ">=8" @@ -4488,6 +4358,7 @@ "version": "4.0.3", "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz", "integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==", + "dev": true, "license": "MIT", "dependencies": { "is-extglob": "^2.1.1" @@ -4500,6 +4371,7 @@ "version": "7.0.0", "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", + "dev": true, "license": "MIT", "engines": { "node": ">=0.12.0" @@ -4515,15 +4387,6 @@ "node": ">=8" } }, - "node_modules/is-plain-object": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-5.0.0.tgz", - "integrity": "sha512-VRSzKkbMm5jMDoKLbltAkFQ5Qr7VDiTFGXxYFXXowVj387GeGNOCsOH6Msy00SGZ3Fp84b1Naa1psqgcCIEP5Q==", - "license": "MIT", - "engines": { - "node": ">=0.10.0" - } - }, "node_modules/is-potential-custom-element-name": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/is-potential-custom-element-name/-/is-potential-custom-element-name-1.0.1.tgz", @@ -4974,6 +4837,7 @@ "version": "4.0.8", "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.8.tgz", "integrity": "sha512-PXwfBhYu0hBCPw8Dn0E+WDYb7af3dSLVWKi3HGv84IdF4TyFoC0ysxFd0Goxw7nSv4T/PzEJQxsYsEiFCKo2BA==", + "dev": true, "license": "MIT", "dependencies": { "braces": "^3.0.3", @@ -5075,9 +4939,9 @@ "license": "MIT" }, "node_modules/muggle-string": { - "version": "0.3.1", - "resolved": "https://registry.npmjs.org/muggle-string/-/muggle-string-0.3.1.tgz", - "integrity": "sha512-ckmWDJjphvd/FvZawgygcUeQCxzvohjFO5RxTjj4eq8kw359gFF3E1brjfI+viLMxss5JrHTDRHZvu2/tuy0Qg==", + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/muggle-string/-/muggle-string-0.4.1.tgz", + "integrity": "sha512-VNTrAak/KhO2i8dqqnqnAHOa3cYBwXEZe9h+D5h/1ZqFSTEFHdM65lR7RoIqq3tBBYavsOXV84NoHXZ0AkPyqQ==", "dev": true, "license": "MIT" }, @@ -5387,15 +5251,6 @@ "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/p-try": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/p-try/-/p-try-2.2.0.tgz", - "integrity": "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==", - "license": "MIT", - "engines": { - "node": ">=6" - } - }, "node_modules/package-json-from-dist": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/package-json-from-dist/-/package-json-from-dist-1.0.1.tgz", @@ -5457,6 +5312,7 @@ "version": "4.0.0", "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==", + "dev": true, "license": "MIT", "engines": { "node": ">=8" @@ -5555,6 +5411,7 @@ "version": "2.3.1", "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz", "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==", + "dev": true, "license": "MIT", "engines": { "node": ">=8.6" @@ -5624,15 +5481,6 @@ "dev": true, "license": "MIT" }, - "node_modules/pngjs": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/pngjs/-/pngjs-5.0.0.tgz", - "integrity": "sha512-40QW5YalBNfQo5yRYmiw7Yz6TKKVr3h6970B2YE+3fQpsWcrbj1PzJgxeJ19DRQjhMbKPIuMY8rFaXc8moolVw==", - "license": "MIT", - "engines": { - "node": ">=10.13.0" - } - }, "node_modules/postcss": { "version": "8.5.6", "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.5.6.tgz", @@ -5925,161 +5773,6 @@ "node": ">=6" } }, - "node_modules/qrcode": { - "version": "1.5.4", - "resolved": "https://registry.npmjs.org/qrcode/-/qrcode-1.5.4.tgz", - "integrity": "sha512-1ca71Zgiu6ORjHqFBDpnSMTR2ReToX4l1Au1VFLyVeBTFavzQnv5JxMFr3ukHVKpSrSA2MCk0lNJSykjUfz7Zg==", - "license": "MIT", - "dependencies": { - "dijkstrajs": "^1.0.1", - "pngjs": "^5.0.0", - "yargs": "^15.3.1" - }, - "bin": { - "qrcode": "bin/qrcode" - }, - "engines": { - "node": ">=10.13.0" - } - }, - "node_modules/qrcode/node_modules/cliui": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/cliui/-/cliui-6.0.0.tgz", - "integrity": "sha512-t6wbgtoCXvAzst7QgXxJYqPt0usEfbgQdftEPbLL/cvv6HPE5VgvqCuAIDR0NgU52ds6rFwqrgakNLrHEjCbrQ==", - "license": "ISC", - "dependencies": { - "string-width": "^4.2.0", - "strip-ansi": "^6.0.0", - "wrap-ansi": "^6.2.0" - } - }, - "node_modules/qrcode/node_modules/emoji-regex": { - "version": "8.0.0", - "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", - "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", - "license": "MIT" - }, - "node_modules/qrcode/node_modules/find-up": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz", - "integrity": "sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==", - "license": "MIT", - "dependencies": { - "locate-path": "^5.0.0", - "path-exists": "^4.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/qrcode/node_modules/locate-path": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz", - "integrity": "sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==", - "license": "MIT", - "dependencies": { - "p-locate": "^4.1.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/qrcode/node_modules/p-limit": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", - "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==", - "license": "MIT", - "dependencies": { - "p-try": "^2.0.0" - }, - "engines": { - "node": ">=6" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/qrcode/node_modules/p-locate": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-4.1.0.tgz", - "integrity": "sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==", - "license": "MIT", - "dependencies": { - "p-limit": "^2.2.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/qrcode/node_modules/string-width": { - "version": "4.2.3", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", - "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", - "license": "MIT", - "dependencies": { - "emoji-regex": "^8.0.0", - "is-fullwidth-code-point": "^3.0.0", - "strip-ansi": "^6.0.1" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/qrcode/node_modules/wrap-ansi": { - "version": "6.2.0", - "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-6.2.0.tgz", - "integrity": "sha512-r6lPcBGxZXlIcymEu7InxDMhdW0KDxpLgoFLcguasxCaJ/SOIZwINatK9KY/tf+ZrlywOKU0UDj3ATXUBfxJXA==", - "license": "MIT", - "dependencies": { - "ansi-styles": "^4.0.0", - "string-width": "^4.1.0", - "strip-ansi": "^6.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/qrcode/node_modules/y18n": { - "version": "4.0.3", - "resolved": "https://registry.npmjs.org/y18n/-/y18n-4.0.3.tgz", - "integrity": "sha512-JKhqTOwSrqNA1NY5lSztJ1GrBiUodLMmIZuLiDaMRJ+itFd+ABVE8XBjOvIWL+rSqNDC74LCSFmlb/U4UZ4hJQ==", - "license": "ISC" - }, - "node_modules/qrcode/node_modules/yargs": { - "version": "15.4.1", - "resolved": "https://registry.npmjs.org/yargs/-/yargs-15.4.1.tgz", - "integrity": "sha512-aePbxDmcYW++PaqBsJ+HYUFwCdv4LVvdnhBy78E57PIor8/OVvhMrADFFEDh8DHDFRv/O9i3lPhsENjO7QX0+A==", - "license": "MIT", - "dependencies": { - "cliui": "^6.0.0", - "decamelize": "^1.2.0", - "find-up": "^4.1.0", - "get-caller-file": "^2.0.1", - "require-directory": "^2.1.1", - "require-main-filename": "^2.0.0", - "set-blocking": "^2.0.0", - "string-width": "^4.2.0", - "which-module": "^2.0.0", - "y18n": "^4.0.0", - "yargs-parser": "^18.1.2" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/qrcode/node_modules/yargs-parser": { - "version": "18.1.3", - "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-18.1.3.tgz", - "integrity": "sha512-o50j0JeToy/4K6OZcaQmW6lyXXKhq7csREXcDwk2omFPJEwUNOVtJKvmDr9EI1fAJZUyZcRF7kxGBWmRXudrCQ==", - "license": "ISC", - "dependencies": { - "camelcase": "^5.0.0", - "decamelize": "^1.2.0" - }, - "engines": { - "node": ">=6" - } - }, "node_modules/qs": { "version": "6.13.0", "resolved": "https://registry.npmjs.org/qs/-/qs-6.13.0.tgz", @@ -6203,42 +5896,21 @@ "node": ">=8.10.0" } }, - "node_modules/redis": { - "version": "4.7.1", - "resolved": "https://registry.npmjs.org/redis/-/redis-4.7.1.tgz", - "integrity": "sha512-S1bJDnqLftzHXHP8JsT5II/CtHWQrASX5K96REjWjlmWKrviSOLWmM7QnRLstAWsu1VBBV1ffV6DzCvxNP0UJQ==", - "license": "MIT", - "workspaces": [ - "./packages/*" - ], - "dependencies": { - "@redis/bloom": "1.2.0", - "@redis/client": "1.6.1", - "@redis/graph": "1.1.1", - "@redis/json": "1.0.7", - "@redis/search": "1.2.0", - "@redis/time-series": "1.1.0" - } - }, "node_modules/require-directory": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz", "integrity": "sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q==", + "dev": true, "license": "MIT", "engines": { "node": ">=0.10.0" } }, - "node_modules/require-main-filename": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/require-main-filename/-/require-main-filename-2.0.0.tgz", - "integrity": "sha512-NKN5kMDylKuldxYLSUfrbo5Tuzh4hd+2E8NPPX02mZtn1VuREQToYe/ZdlJy+J3uCpfaiGF05e7B8W0iXbQHmg==", - "license": "ISC" - }, "node_modules/requires-port": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/requires-port/-/requires-port-1.0.0.tgz", "integrity": "sha512-KigOCHcocU3XODJxsu8i/j8T9tzT4adHiecwORRQ0ZZFcp7ahwXuRU1m+yuO90C5ZUyGeGfocHDI14M3L3yDAQ==", + "dev": true, "license": "MIT" }, "node_modules/resolve": { @@ -6533,12 +6205,6 @@ "node": ">= 0.8.0" } }, - "node_modules/set-blocking": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/set-blocking/-/set-blocking-2.0.0.tgz", - "integrity": "sha512-KiKBS8AnWGEyLzofFfmvKwpdPzqiy16LvQfK3yv/fVH7Bj13/wl3JSR1J+rfgRE9q7xUJK4qvgS8raSOeLUehw==", - "license": "ISC" - }, "node_modules/setprototypeof": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.2.0.tgz", @@ -6720,18 +6386,6 @@ "integrity": "sha512-zC8zGoGkmc8J9ndvml8Xksr1Amk9qBujgbF0JAIWO7kXr43w0h/0GJNM/Vustixu+YE8N/MTrQ7N31FvHUACxQ==", "dev": true }, - "node_modules/speakeasy": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/speakeasy/-/speakeasy-2.0.0.tgz", - "integrity": "sha512-lW2A2s5LKi8rwu77ewisuUOtlCydF/hmQSOJjpTqTj1gZLkNgTaYnyvfxy2WBr4T/h+9c4g8HIITfj83OkFQFw==", - "license": "MIT", - "dependencies": { - "base32.js": "0.0.1" - }, - "engines": { - "node": ">= 0.10.0" - } - }, "node_modules/speakingurl": { "version": "14.0.1", "resolved": "https://registry.npmjs.org/speakingurl/-/speakingurl-14.0.1.tgz", @@ -6856,6 +6510,7 @@ "version": "6.0.1", "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "dev": true, "license": "MIT", "dependencies": { "ansi-regex": "^5.0.1" @@ -7116,6 +6771,7 @@ "version": "5.0.1", "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==", + "dev": true, "license": "MIT", "dependencies": { "is-number": "^7.0.0" @@ -7319,9 +6975,9 @@ } }, "node_modules/typescript": { - "version": "5.2.2", - "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.2.2.tgz", - "integrity": "sha512-mI4WrpHsbCIcwT9cF4FZvr80QUeKvsUsUvKDoR+X/7XHQH98xYD8YHZg7ANtz2GtZt/CBq2QJ0thkGJMHfqc1w==", + "version": "5.8.3", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.8.3.tgz", + "integrity": "sha512-p1diW6TqL9L07nNxvRMM7hMMw4c5XOo/1ibL4aAIGmSAt9slTE1Xgw5KWuof2uTOvCg9BY7ZRi+GaF+7sfgPeQ==", "devOptional": true, "license": "Apache-2.0", "bin": { @@ -7350,6 +7006,7 @@ "version": "6.21.0", "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-6.21.0.tgz", "integrity": "sha512-iwDZqg0QAGrg9Rav5H4n0M64c3mkR59cJ6wQp+7C4nI0gsmExaedaYLNO44eT4AtBBwjbTiGPMlt2Md0T9H9JQ==", + "dev": true, "license": "MIT" }, "node_modules/universalify": { @@ -7655,6 +7312,13 @@ } } }, + "node_modules/vscode-uri": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/vscode-uri/-/vscode-uri-3.1.0.tgz", + "integrity": "sha512-/BpdSx+yCQGnCvecbyXdxHDkuk55/G3xwnC0GqY4gmQ3j+A+g8kzzgB4Nk/SINjqn6+waqw3EgbVF2QKExkRxQ==", + "dev": true, + "license": "MIT" + }, "node_modules/vue": { "version": "3.5.17", "resolved": "https://registry.npmjs.org/vue/-/vue-3.5.17.tgz", @@ -7734,32 +7398,6 @@ "eslint": ">=6.0.0" } }, - "node_modules/vue-router": { - "version": "4.5.1", - "resolved": "https://registry.npmjs.org/vue-router/-/vue-router-4.5.1.tgz", - "integrity": "sha512-ogAF3P97NPm8fJsE4by9dwSYtDwXIY1nFY9T6DyQnGHd1E2Da94w9JIolpe42LJGIl0DwOHBi8TcRPlPGwbTtw==", - "license": "MIT", - "dependencies": { - "@vue/devtools-api": "^6.6.4" - }, - "funding": { - "url": "https://github.com/sponsors/posva" - }, - "peerDependencies": { - "vue": "^3.2.0" - } - }, - "node_modules/vue-template-compiler": { - "version": "2.7.16", - "resolved": "https://registry.npmjs.org/vue-template-compiler/-/vue-template-compiler-2.7.16.tgz", - "integrity": "sha512-AYbUWAJHLGGQM7+cNTELw+KsOG9nl2CnSv467WobS5Cv9uk3wFcnr1Etsz2sEIHEZvw1U+o9mRlEO6QbZvUPGQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "de-indent": "^1.0.2", - "he": "^1.2.0" - } - }, "node_modules/vue-toastification": { "version": "2.0.0-rc.5", "resolved": "https://registry.npmjs.org/vue-toastification/-/vue-toastification-2.0.0-rc.5.tgz", @@ -7770,21 +7408,20 @@ } }, "node_modules/vue-tsc": { - "version": "1.8.27", - "resolved": "https://registry.npmjs.org/vue-tsc/-/vue-tsc-1.8.27.tgz", - "integrity": "sha512-WesKCAZCRAbmmhuGl3+VrdWItEvfoFIPXOvUJkjULi+x+6G/Dy69yO3TBRJDr9eUlmsNAwVmxsNZxvHKzbkKdg==", + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/vue-tsc/-/vue-tsc-3.0.1.tgz", + "integrity": "sha512-UvMLQD0hAGL1g/NfEQelnSVB4H5gtf/gz2lJKjMMwWNOUmSNyWkejwJagAxEbSjtV5CPPJYslOtoSuqJ63mhdg==", "dev": true, "license": "MIT", "dependencies": { - "@volar/typescript": "~1.11.1", - "@vue/language-core": "1.8.27", - "semver": "^7.5.4" + "@volar/typescript": "2.4.17", + "@vue/language-core": "3.0.1" }, "bin": { "vue-tsc": "bin/vue-tsc.js" }, "peerDependencies": { - "typescript": "*" + "typescript": ">=5.0.0" } }, "node_modules/w3c-xmlserializer": { @@ -7863,12 +7500,6 @@ "node": ">= 8" } }, - "node_modules/which-module": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/which-module/-/which-module-2.0.1.tgz", - "integrity": "sha512-iBdZ57RDvnOR9AGBhML2vFZf7h8vmBjhoaZqODJBFWHVtKkDmKuHai3cx5PgVMrX5YDNp27AofYbAwctSS+vhQ==", - "license": "ISC" - }, "node_modules/why-is-node-running": { "version": "2.3.0", "resolved": "https://registry.npmjs.org/why-is-node-running/-/why-is-node-running-2.3.0.tgz", @@ -8089,12 +7720,6 @@ "node": ">=10" } }, - "node_modules/yallist": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", - "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", - "license": "ISC" - }, "node_modules/yaml": { "version": "2.8.0", "resolved": "https://registry.npmjs.org/yaml/-/yaml-2.8.0.tgz",