chore: update project files
This commit is contained in:
@@ -101,6 +101,10 @@
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
71
demo/frontend/src/components/LanguageSwitcher.vue
Normal file
71
demo/frontend/src/components/LanguageSwitcher.vue
Normal file
@@ -0,0 +1,71 @@
|
||||
<template>
|
||||
<button class="language-switcher" @click="toggleLanguage" :title="currentLanguage === 'zh' ? '切换到英文' : 'Switch to Chinese'">
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 20 20" fill="none">
|
||||
<path d="M4.16602 12.4998V14.1665C4.16602 15.0452 4.84592 15.765 5.7083 15.8286L5.83268 15.8332H8.33268V17.4998H5.83268C3.99173 17.4998 2.49935 16.0074 2.49935 14.1665V12.4998H4.16602ZM14.9993 8.33317L18.666 17.4998H16.8702L15.8694 14.9998H12.461L11.4618 17.4998H9.66685L13.3327 8.33317H14.9993ZM14.166 10.7375L13.1268 13.3332H15.2035L14.166 10.7375ZM6.66602 1.6665V3.33317H9.99935V9.1665H6.66602V11.6665H4.99935V9.1665H1.66602V3.33317H4.99935V1.6665H6.66602ZM14.166 2.49984C16.0069 2.49984 17.4993 3.99222 17.4993 5.83317V7.49984H15.8327V5.83317C15.8327 4.9127 15.0865 4.1665 14.166 4.1665H11.666V2.49984H14.166ZM4.99935 4.99984H3.33268V7.49984H4.99935V4.99984ZM8.33268 4.99984H6.66602V7.49984H8.33268V4.99984Z" fill="currentColor"/>
|
||||
</svg>
|
||||
<span class="lang-text">{{ currentLanguage === 'zh' ? '中' : 'EN' }}</span>
|
||||
</button>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import { computed } from 'vue'
|
||||
import { useI18n } from 'vue-i18n'
|
||||
|
||||
const { locale } = useI18n()
|
||||
|
||||
const currentLanguage = computed(() => locale.value)
|
||||
|
||||
const toggleLanguage = () => {
|
||||
console.log('[LanguageSwitcher] 当前语言:', locale.value)
|
||||
|
||||
// 切换语言
|
||||
const newLang = locale.value === 'zh' ? 'en' : 'zh'
|
||||
console.log('[LanguageSwitcher] 切换到:', newLang)
|
||||
|
||||
// 直接更新 locale(响应式切换)
|
||||
locale.value = newLang
|
||||
|
||||
// 保存到 localStorage 以便下次刷新时使用
|
||||
localStorage.setItem('language', newLang)
|
||||
console.log('[LanguageSwitcher] localStorage 已保存:', localStorage.getItem('language'))
|
||||
console.log('[LanguageSwitcher] 语言切换完成(无刷新)')
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
.language-switcher {
|
||||
height: 36px;
|
||||
padding: 0 12px;
|
||||
border-radius: 18px;
|
||||
background: rgba(255, 255, 255, 0.12);
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
gap: 6px;
|
||||
border: none;
|
||||
cursor: pointer;
|
||||
transition: all 0.2s ease;
|
||||
color: white;
|
||||
}
|
||||
|
||||
.language-switcher:hover {
|
||||
background: rgba(255, 255, 255, 0.2);
|
||||
transform: scale(1.05);
|
||||
}
|
||||
|
||||
.language-switcher:active {
|
||||
transform: scale(0.95);
|
||||
}
|
||||
|
||||
.language-switcher svg {
|
||||
width: 20px;
|
||||
height: 20px;
|
||||
flex-shrink: 0;
|
||||
}
|
||||
|
||||
.lang-text {
|
||||
font-size: 13px;
|
||||
font-weight: 500;
|
||||
letter-spacing: 0.5px;
|
||||
}
|
||||
</style>
|
||||
@@ -4,7 +4,7 @@
|
||||
<!-- Logo -->
|
||||
<div class="navbar-brand">
|
||||
<router-link to="/" class="brand-link">
|
||||
<span class="brand-text">AIGC Demo</span>
|
||||
<img src="/images/backgrounds/logo.svg" alt="Logo" class="brand-logo" />
|
||||
</router-link>
|
||||
</div>
|
||||
|
||||
@@ -19,31 +19,31 @@
|
||||
@select="handleMenuSelect"
|
||||
>
|
||||
<el-menu-item index="/welcome">
|
||||
<span>欢迎页</span>
|
||||
<span>{{ $t('common.welcome') }}</span>
|
||||
</el-menu-item>
|
||||
|
||||
|
||||
<el-menu-item index="/home">
|
||||
<span>首页</span>
|
||||
<span>{{ $t('common.home') }}</span>
|
||||
</el-menu-item>
|
||||
|
||||
|
||||
<el-menu-item v-if="userStore.isAuthenticated" index="/profile">
|
||||
<span>个人主页</span>
|
||||
<span>{{ $t('common.profile') }}</span>
|
||||
</el-menu-item>
|
||||
|
||||
|
||||
<el-menu-item v-if="userStore.isAuthenticated" index="/orders">
|
||||
<span>订单管理</span>
|
||||
<span>{{ $t('common.orders') }}</span>
|
||||
</el-menu-item>
|
||||
|
||||
|
||||
<el-menu-item v-if="userStore.isAuthenticated" index="/payments">
|
||||
<span>支付记录</span>
|
||||
<span>{{ $t('common.payments') }}</span>
|
||||
</el-menu-item>
|
||||
|
||||
|
||||
<el-menu-item v-if="userStore.isAdmin" index="/admin/orders">
|
||||
<span>后台管理</span>
|
||||
<span>{{ $t('common.adminPanel') }}</span>
|
||||
</el-menu-item>
|
||||
|
||||
|
||||
<el-menu-item v-if="userStore.isAdmin" index="/admin/dashboard">
|
||||
<span>数据仪表盘</span>
|
||||
<span>{{ $t('dashboard.title') }}</span>
|
||||
</el-menu-item>
|
||||
</el-menu>
|
||||
|
||||
@@ -57,38 +57,40 @@
|
||||
<!-- 用户菜单 -->
|
||||
<div class="navbar-user">
|
||||
<template v-if="userStore.isAuthenticated">
|
||||
<LanguageSwitcher />
|
||||
<el-dropdown @command="handleUserCommand">
|
||||
<span class="user-dropdown">
|
||||
<span>{{ userStore.username }}</span>
|
||||
<el-tag v-if="userStore.user?.points" size="small" type="success" class="points-tag">
|
||||
{{ userStore.user.points }}积分
|
||||
<el-tag v-if="userStore.availablePoints > 0" size="small" type="success" class="points-tag">
|
||||
{{ userStore.availablePoints }}{{ $t('common.points') }}
|
||||
</el-tag>
|
||||
</span>
|
||||
<template #dropdown>
|
||||
<el-dropdown-menu>
|
||||
<el-dropdown-item command="profile">
|
||||
个人资料
|
||||
{{ $t('common.userProfile') }}
|
||||
</el-dropdown-item>
|
||||
<el-dropdown-item v-if="userStore.isAdmin" command="admin">
|
||||
后台管理
|
||||
{{ $t('common.adminPanel') }}
|
||||
</el-dropdown-item>
|
||||
<el-dropdown-item command="settings">
|
||||
设置
|
||||
{{ $t('common.settings') }}
|
||||
</el-dropdown-item>
|
||||
<el-dropdown-item divided command="logout">
|
||||
退出登录
|
||||
{{ $t('common.logout') }}
|
||||
</el-dropdown-item>
|
||||
</el-dropdown-menu>
|
||||
</template>
|
||||
</el-dropdown>
|
||||
</template>
|
||||
|
||||
|
||||
<template v-else>
|
||||
<LanguageSwitcher />
|
||||
<el-button type="primary" plain @click="$router.push('/login')">
|
||||
登录
|
||||
{{ $t('common.login') }}
|
||||
</el-button>
|
||||
<el-button type="success" plain @click="$router.push('/register')">
|
||||
注册
|
||||
{{ $t('common.register') }}
|
||||
</el-button>
|
||||
</template>
|
||||
</div>
|
||||
@@ -100,8 +102,11 @@
|
||||
import { ref, onMounted, onUnmounted } from 'vue'
|
||||
import { useUserStore } from '@/stores/user'
|
||||
import { useRouter } from 'vue-router'
|
||||
import { useI18n } from 'vue-i18n'
|
||||
import { ElMessage, ElMessageBox } from 'element-plus'
|
||||
import LanguageSwitcher from './LanguageSwitcher.vue'
|
||||
|
||||
const { t } = useI18n()
|
||||
const userStore = useUserStore()
|
||||
const router = useRouter()
|
||||
|
||||
@@ -130,29 +135,29 @@ const handleMenuSelect = (index) => {
|
||||
const handleUserCommand = async (command) => {
|
||||
switch (command) {
|
||||
case 'profile':
|
||||
ElMessage.info('个人资料功能开发中')
|
||||
ElMessage.info(t('common.profileDevMsg'))
|
||||
break
|
||||
case 'admin':
|
||||
// 检查管理员权限
|
||||
if (userStore.isAdmin) {
|
||||
router.push('/admin/dashboard')
|
||||
} else {
|
||||
ElMessage.warning('权限不足,只有管理员才能访问后台管理')
|
||||
ElMessage.warning(t('common.noPermissionMsg'))
|
||||
}
|
||||
break
|
||||
case 'settings':
|
||||
ElMessage.info('设置功能开发中')
|
||||
ElMessage.info(t('common.settingsDevMsg'))
|
||||
break
|
||||
case 'logout':
|
||||
try {
|
||||
await ElMessageBox.confirm('确定要退出登录吗?', '提示', {
|
||||
confirmButtonText: '确定',
|
||||
cancelButtonText: '取消',
|
||||
await ElMessageBox.confirm(t('common.logoutConfirm'), t('common.tip'), {
|
||||
confirmButtonText: t('common.confirm'),
|
||||
cancelButtonText: t('common.cancel'),
|
||||
type: 'warning'
|
||||
})
|
||||
|
||||
|
||||
await userStore.logoutUser()
|
||||
ElMessage.success('退出登录成功')
|
||||
ElMessage.success(t('common.logoutSuccess'))
|
||||
router.push('/')
|
||||
} catch (error) {
|
||||
// 用户取消
|
||||
@@ -191,6 +196,11 @@ const handleUserCommand = async (command) => {
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
.brand-logo {
|
||||
height: 40px;
|
||||
width: auto;
|
||||
}
|
||||
|
||||
.brand-icon {
|
||||
margin-right: 8px;
|
||||
font-size: 24px;
|
||||
|
||||
@@ -43,7 +43,7 @@
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="qr-tip">支付前请阅读《XX 付费服务协议》</div>
|
||||
<div class="qr-tip">支付前请阅读《Vionow支付服务条款》</div>
|
||||
</div>
|
||||
|
||||
<!-- 支付提示 -->
|
||||
@@ -76,7 +76,7 @@
|
||||
|
||||
<!-- 底部链接 -->
|
||||
<div class="footer-link">
|
||||
<a href="#" @click.prevent="showAgreement">《XX 付费服务协议》</a>
|
||||
<a href="#" @click.prevent="showAgreement">《Vionow支付服务条款》</a>
|
||||
</div>
|
||||
</div>
|
||||
</el-dialog>
|
||||
@@ -84,6 +84,7 @@
|
||||
|
||||
<script setup>
|
||||
import { ref, watch, onUnmounted } from 'vue'
|
||||
import { useRouter } from 'vue-router'
|
||||
import { ElMessage } from 'element-plus'
|
||||
import { CreditCard } from '@element-plus/icons-vue'
|
||||
import { createPayment, createAlipayPayment, getPaymentById, testPaymentComplete } from '@/api/payments'
|
||||
@@ -109,6 +110,7 @@ const props = defineProps({
|
||||
|
||||
const emit = defineEmits(['update:modelValue', 'pay-success', 'pay-error'])
|
||||
|
||||
const router = useRouter()
|
||||
const visible = ref(false)
|
||||
const selectedMethod = ref('alipay')
|
||||
const loading = ref(false)
|
||||
@@ -388,7 +390,7 @@ const handleTestPaymentComplete = async () => {
|
||||
|
||||
// 显示协议
|
||||
const showAgreement = () => {
|
||||
ElMessage.info('服务协议页面')
|
||||
router.push('/terms-of-service')
|
||||
}
|
||||
</script>
|
||||
|
||||
|
||||
Reference in New Issue
Block a user