fix: 修复三端路由引用并统一共享 Logo 静态资源

修正 admin/agent/player 路由与 agent App.vue 的 import 路径,三端 Vite 共用 packages/shared/public 下的 logo 与 favicon。

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
2026-06-02 15:01:55 +08:00
parent 4c92157299
commit 000bd8c956
18 changed files with 65 additions and 35 deletions

View File

@@ -3,6 +3,7 @@
<head> <head>
<meta charset="UTF-8" /> <meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" /> <meta name="viewport" content="width=device-width, initial-scale=1.0" />
<link rel="icon" type="image/svg+xml" href="/favicon.svg" />
<title>TheBet365 Admin</title> <title>TheBet365 Admin</title>
</head> </head>
<body> <body>

View File

@@ -23,7 +23,10 @@ const menus = [
<template> <template>
<el-container style="min-height: 100vh"> <el-container style="min-height: 100vh">
<el-aside width="200px" style="background: #1a2332"> <el-aside width="200px" style="background: #1a2332">
<div style="padding: 20px; color: #00a826; font-weight: 800">TheBet365 Admin</div> <div style="padding: 20px">
<img src="/logo.svg" alt="TheBet365" style="height: 28px; width: auto; display: block" />
<div style="margin-top: 8px; font-size: 12px; color: #888">平台后台</div>
</div>
<el-menu background-color="#1a2332" text-color="#ccc" active-text-color="#00a826" :default-active="route.path"> <el-menu background-color="#1a2332" text-color="#ccc" active-text-color="#00a826" :default-active="route.path">
<el-menu-item v-for="m in menus" :key="m.path" :index="m.path"> <el-menu-item v-for="m in menus" :key="m.path" :index="m.path">
<RouterLink :to="m.path" style="color: inherit; width: 100%">{{ m.label }}</RouterLink> <RouterLink :to="m.path" style="color: inherit; width: 100%">{{ m.label }}</RouterLink>

View File

@@ -3,20 +3,20 @@ import { createRouter, createWebHistory } from 'vue-router';
export default createRouter({ export default createRouter({
history: createWebHistory(), history: createWebHistory(),
routes: [ routes: [
{ path: '/login', component: () => import('./views/Login.vue') }, { path: '/login', component: () => import('../views/Login.vue') },
{ {
path: '/', path: '/',
component: () => import('./layouts/AdminLayout.vue'), component: () => import('../layouts/AdminLayout.vue'),
meta: { auth: true }, meta: { auth: true },
children: [ children: [
{ path: '', component: () => import('./views/Dashboard.vue') }, { path: '', component: () => import('../views/Dashboard.vue') },
{ path: 'users', component: () => import('./views/Users.vue') }, { path: 'users', component: () => import('../views/Users.vue') },
{ path: 'agents', component: () => import('./views/Agents.vue') }, { path: 'agents', component: () => import('../views/Agents.vue') },
{ path: 'matches', component: () => import('./views/Matches.vue') }, { path: 'matches', component: () => import('../views/Matches.vue') },
{ path: 'bets', component: () => import('./views/Bets.vue') }, { path: 'bets', component: () => import('../views/Bets.vue') },
{ path: 'settlement/:id', component: () => import('./views/Settlement.vue') }, { path: 'settlement/:id', component: () => import('../views/Settlement.vue') },
{ path: 'cashback', component: () => import('./views/Cashback.vue') }, { path: 'cashback', component: () => import('../views/Cashback.vue') },
{ path: 'audit', component: () => import('./views/Audit.vue') }, { path: 'audit', component: () => import('../views/Audit.vue') },
], ],
}, },
], ],

View File

@@ -25,7 +25,10 @@ async function login() {
<template> <template>
<div style="min-height: 100vh; display: flex; align-items: center; justify-content: center"> <div style="min-height: 100vh; display: flex; align-items: center; justify-content: center">
<el-card style="width: 400px"> <el-card style="width: 400px">
<h2 style="text-align: center; margin-bottom: 24px">平台后台登录</h2> <div style="text-align: center; margin-bottom: 24px">
<img src="/logo.svg" alt="TheBet365" style="height: 32px; width: auto" />
<h2 style="margin-top: 12px; font-size: 16px; font-weight: 500">平台后台登录</h2>
</div>
<el-form @submit.prevent="login"> <el-form @submit.prevent="login">
<el-form-item label="用户名"> <el-form-item label="用户名">
<el-input v-model="form.username" /> <el-input v-model="form.username" />

View File

@@ -1,8 +1,10 @@
import { defineConfig } from 'vite'; import { defineConfig } from 'vite';
import vue from '@vitejs/plugin-vue'; import vue from '@vitejs/plugin-vue';
import { resolve } from 'path';
export default defineConfig({ export default defineConfig({
plugins: [vue()], plugins: [vue()],
publicDir: resolve(__dirname, '../../packages/shared/public'),
server: { server: {
port: 5174, port: 5174,
proxy: { '/api': { target: 'http://localhost:3000', changeOrigin: true } }, proxy: { '/api': { target: 'http://localhost:3000', changeOrigin: true } },

View File

@@ -1,5 +1,5 @@
<!DOCTYPE html> <!DOCTYPE html>
<html lang="zh-CN"> <html lang="zh-CN">
<head><meta charset="UTF-8" /><title>TheBet365 Agent</title></head> <head><meta charset="UTF-8" /><link rel="icon" type="image/svg+xml" href="/favicon.svg" /><title>TheBet365 Agent</title></head>
<body><div id="app"></div><script type="module" src="/src/main.ts"></script></body> <body><div id="app"></div><script type="module" src="/src/main.ts"></script></body>
</html> </html>

View File

@@ -1 +1,4 @@
<script setup lang="ts"><template><router-view /></template></script> <script setup lang="ts">
import { RouterView } from 'vue-router';
</script>
<template><RouterView /></template>

View File

@@ -11,7 +11,10 @@ function logout() {
<template> <template>
<el-container style="min-height: 100vh"> <el-container style="min-height: 100vh">
<el-aside width="180px" style="background: #1a2332"> <el-aside width="180px" style="background: #1a2332">
<div style="padding: 16px; color: #00a826; font-weight: 700">代理后台</div> <div style="padding: 16px">
<img src="/logo.svg" alt="TheBet365" style="height: 24px; width: auto; display: block" />
<div style="margin-top: 8px; font-size: 12px; color: #888">代理后台</div>
</div>
<el-menu background-color="#1a2332" text-color="#ccc" active-text-color="#00a826"> <el-menu background-color="#1a2332" text-color="#ccc" active-text-color="#00a826">
<el-menu-item index="/"><RouterLink to="/" style="color: inherit">概览</RouterLink></el-menu-item> <el-menu-item index="/"><RouterLink to="/" style="color: inherit">概览</RouterLink></el-menu-item>
<el-menu-item index="/players"><RouterLink to="/players" style="color: inherit">直属玩家</RouterLink></el-menu-item> <el-menu-item index="/players"><RouterLink to="/players" style="color: inherit">直属玩家</RouterLink></el-menu-item>

View File

@@ -3,15 +3,15 @@ import { createRouter, createWebHistory } from 'vue-router';
export default createRouter({ export default createRouter({
history: createWebHistory(), history: createWebHistory(),
routes: [ routes: [
{ path: '/login', component: () => import('./views/Login.vue') }, { path: '/login', component: () => import('../views/Login.vue') },
{ {
path: '/', path: '/',
component: () => import('./layouts/AgentLayout.vue'), component: () => import('../layouts/AgentLayout.vue'),
children: [ children: [
{ path: '', component: () => import('./views/Dashboard.vue') }, { path: '', component: () => import('../views/Dashboard.vue') },
{ path: 'players', component: () => import('./views/Players.vue') }, { path: 'players', component: () => import('../views/Players.vue') },
{ path: 'agents', component: () => import('./views/SubAgents.vue') }, { path: 'agents', component: () => import('../views/SubAgents.vue') },
{ path: 'bets', component: () => import('./views/Bets.vue') }, { path: 'bets', component: () => import('../views/Bets.vue') },
], ],
}, },
], ],

View File

@@ -21,8 +21,11 @@ async function login() {
<template> <template>
<div style="min-height: 100vh; display: flex; align-items: center; justify-content: center"> <div style="min-height: 100vh; display: flex; align-items: center; justify-content: center">
<el-card style="width: 360px"> <el-card style="width: 360px">
<h2 style="text-align: center">代理后台登录</h2> <div style="text-align: center; margin-bottom: 20px">
<el-form @submit.prevent="login" style="margin-top: 20px"> <img src="/logo.svg" alt="TheBet365" style="height: 32px; width: auto" />
<h2 style="margin-top: 12px; font-size: 16px; font-weight: 500">代理后台登录</h2>
</div>
<el-form @submit.prevent="login" style="margin-top: 0">
<el-input v-model="form.username" placeholder="用户名" style="margin-bottom: 12px" /> <el-input v-model="form.username" placeholder="用户名" style="margin-bottom: 12px" />
<el-input v-model="form.password" type="password" placeholder="密码" style="margin-bottom: 12px" /> <el-input v-model="form.password" type="password" placeholder="密码" style="margin-bottom: 12px" />
<el-button type="primary" native-type="submit" style="width: 100%">登录</el-button> <el-button type="primary" native-type="submit" style="width: 100%">登录</el-button>

View File

@@ -1,8 +1,10 @@
import { defineConfig } from 'vite'; import { defineConfig } from 'vite';
import vue from '@vitejs/plugin-vue'; import vue from '@vitejs/plugin-vue';
import { resolve } from 'path';
export default defineConfig({ export default defineConfig({
plugins: [vue()], plugins: [vue()],
publicDir: resolve(__dirname, '../../packages/shared/public'),
server: { server: {
port: 5175, port: 5175,
proxy: { '/api': { target: 'http://localhost:3000', changeOrigin: true } }, proxy: { '/api': { target: 'http://localhost:3000', changeOrigin: true } },

View File

@@ -3,6 +3,7 @@
<head> <head>
<meta charset="UTF-8" /> <meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no" /> <meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no" />
<link rel="icon" type="image/svg+xml" href="/favicon.svg" />
<title>TheBet365</title> <title>TheBet365</title>
</head> </head>
<body> <body>

View File

@@ -27,7 +27,7 @@ function setLocale(code: string) {
<template> <template>
<div class="layout"> <div class="layout">
<header class="header"> <header class="header">
<span class="logo">TheBet365</span> <img src="/logo.svg" alt="TheBet365" class="logo" />
<div class="header-actions"> <div class="header-actions">
<select :value="locale" @change="setLocale(($event.target as HTMLSelectElement).value)" class="lang-select"> <select :value="locale" @change="setLocale(($event.target as HTMLSelectElement).value)" class="lang-select">
<option v-for="l in locales" :key="l.code" :value="l.code">{{ l.label }}</option> <option v-for="l in locales" :key="l.code" :value="l.code">{{ l.label }}</option>
@@ -61,7 +61,7 @@ function setLocale(code: string) {
display: flex; justify-content: space-between; align-items: center; display: flex; justify-content: space-between; align-items: center;
padding: 12px 16px; background: #1a2332; border-bottom: 1px solid var(--border); padding: 12px 16px; background: #1a2332; border-bottom: 1px solid var(--border);
} }
.logo { font-weight: 800; color: var(--primary); font-size: 18px; } .logo { height: 24px; width: auto; display: block; }
.header-actions { display: flex; gap: 12px; align-items: center; } .header-actions { display: flex; gap: 12px; align-items: center; }
.lang-select { background: var(--bg-card); color: #fff; border: 1px solid var(--border); padding: 4px 8px; border-radius: 4px; width: auto; } .lang-select { background: var(--bg-card); color: #fff; border: 1px solid var(--border); padding: 4px 8px; border-radius: 4px; width: auto; }
.balance { font-size: 13px; color: var(--text-muted); } .balance { font-size: 13px; color: var(--text-muted); }

View File

@@ -1,20 +1,20 @@
import { createRouter, createWebHistory } from 'vue-router'; import { createRouter, createWebHistory } from 'vue-router';
import { useAuthStore } from './stores/auth'; import { useAuthStore } from '../stores/auth';
const router = createRouter({ const router = createRouter({
history: createWebHistory(), history: createWebHistory(),
routes: [ routes: [
{ path: '/login', component: () => import('./views/LoginView.vue') }, { path: '/login', component: () => import('../views/LoginView.vue') },
{ {
path: '/', path: '/',
component: () => import('./layouts/MainLayout.vue'), component: () => import('../layouts/MainLayout.vue'),
meta: { requiresAuth: true }, meta: { requiresAuth: true },
children: [ children: [
{ path: '', component: () => import('./views/HomeView.vue') }, { path: '', component: () => import('../views/HomeView.vue') },
{ path: 'football', component: () => import('./views/FootballView.vue') }, { path: 'football', component: () => import('../views/FootballView.vue') },
{ path: 'match/:id', component: () => import('./views/MatchDetailView.vue') }, { path: 'match/:id', component: () => import('../views/MatchDetailView.vue') },
{ path: 'bets', component: () => import('./views/MyBetsView.vue') }, { path: 'bets', component: () => import('../views/MyBetsView.vue') },
{ path: 'profile', component: () => import('./views/ProfileView.vue') }, { path: 'profile', component: () => import('../views/ProfileView.vue') },
], ],
}, },
], ],

View File

@@ -28,7 +28,7 @@ async function submit() {
<template> <template>
<div class="login-page"> <div class="login-page">
<h1 class="logo">TheBet365</h1> <img src="/logo.svg" alt="TheBet365" class="logo" />
<form @submit.prevent="submit" class="login-form"> <form @submit.prevent="submit" class="login-form">
<label>{{ t('auth.username') }}</label> <label>{{ t('auth.username') }}</label>
<input v-model="username" required /> <input v-model="username" required />
@@ -47,7 +47,7 @@ async function submit() {
min-height: 100vh; display: flex; flex-direction: column; min-height: 100vh; display: flex; flex-direction: column;
align-items: center; justify-content: center; padding: 24px; align-items: center; justify-content: center; padding: 24px;
} }
.logo { color: var(--primary); font-size: 32px; margin-bottom: 32px; } .logo { height: 40px; width: auto; margin-bottom: 32px; }
.login-form { width: 100%; max-width: 320px; display: flex; flex-direction: column; gap: 12px; } .login-form { width: 100%; max-width: 320px; display: flex; flex-direction: column; gap: 12px; }
label { font-size: 13px; color: var(--text-muted); } label { font-size: 13px; color: var(--text-muted); }
.error { color: var(--danger); font-size: 13px; } .error { color: var(--danger); font-size: 13px; }

View File

@@ -1,8 +1,10 @@
import { defineConfig } from 'vite'; import { defineConfig } from 'vite';
import vue from '@vitejs/plugin-vue'; import vue from '@vitejs/plugin-vue';
import { resolve } from 'path';
export default defineConfig({ export default defineConfig({
plugins: [vue()], plugins: [vue()],
publicDir: resolve(__dirname, '../../packages/shared/public'),
server: { server: {
port: 5173, port: 5173,
proxy: { proxy: {

View File

@@ -0,0 +1,4 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 32 32" fill="none">
<rect width="32" height="32" rx="6" fill="#1a2332"/>
<text x="16" y="22" text-anchor="middle" font-family="Arial, Helvetica, sans-serif" font-size="14" font-weight="800" fill="#00a826">T</text>
</svg>

After

Width:  |  Height:  |  Size: 278 B

View File

@@ -0,0 +1,3 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 240 40" fill="none" role="img" aria-label="TheBet365">
<text x="0" y="30" font-family="Arial, Helvetica, sans-serif" font-size="28" font-weight="800" fill="#00a826">TheBet365</text>
</svg>

After

Width:  |  Height:  |  Size: 244 B