增加电竞手册
This commit is contained in:
@@ -5,6 +5,7 @@ import { useProducts } from '@/composables/useProducts'
|
||||
import { useAccounts } from '@/composables/useAccounts'
|
||||
import { useScheduler } from '@/composables/useScheduler'
|
||||
import { useLogs } from '@/composables/useLogs'
|
||||
import { useActivity } from '@/composables/useActivity'
|
||||
import AppShell from '@/components/layout/AppShell.vue'
|
||||
import ToastContainer from '@/components/ToastContainer.vue'
|
||||
|
||||
@@ -14,6 +15,7 @@ const { loadAccounts, restoreSelection: restoreAccountSelection } = useAccounts(
|
||||
const { clearLogs, fetchServerLogs, checkResults } = useLogs()
|
||||
const { restoreSchedule, setRunState } = useScheduler()
|
||||
const { clearResults } = useLogs()
|
||||
const { loadActivities } = useActivity()
|
||||
|
||||
const version = ref('')
|
||||
const serverTime = ref('--')
|
||||
@@ -61,6 +63,7 @@ onMounted(async () => {
|
||||
|
||||
// 加载数据
|
||||
await loadAccounts()
|
||||
await loadActivities()
|
||||
await loadProducts(false)
|
||||
|
||||
// 获取版本号
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
<script setup lang="ts">
|
||||
import { useProducts } from '@/composables/useProducts'
|
||||
import { useActivity } from '@/composables/useActivity'
|
||||
import ProductSearch from '@/components/product/ProductSearch.vue'
|
||||
import ProductList from '@/components/product/ProductList.vue'
|
||||
import ProductCard from '@/components/product/ProductCard.vue'
|
||||
@@ -9,6 +10,15 @@ defineProps<{
|
||||
}>()
|
||||
|
||||
const { loadProducts, productInfo, filteredProducts, loading } = useProducts()
|
||||
const { activities, currentActivity, switching, switchActivity } = useActivity()
|
||||
|
||||
const onSwitchActivity = async (e: Event) => {
|
||||
const id = (e.target as HTMLSelectElement).value
|
||||
const ok = await switchActivity(id)
|
||||
if (ok) {
|
||||
await loadProducts(true)
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<template>
|
||||
@@ -22,6 +32,25 @@ const { loadProducts, productInfo, filteredProducts, loading } = useProducts()
|
||||
<span class="stat-pill">v{{ version }}</span>
|
||||
</div>
|
||||
|
||||
<!-- 活动选择 -->
|
||||
<div class="activity-box">
|
||||
<label class="activity-label">当前活动</label>
|
||||
<div class="activity-row">
|
||||
<select
|
||||
class="activity-select"
|
||||
:value="currentActivity?.id"
|
||||
:disabled="switching || activities.length === 0"
|
||||
@change="onSwitchActivity"
|
||||
>
|
||||
<option v-if="activities.length === 0" value="">加载中...</option>
|
||||
<option v-for="act in activities" :key="act.id" :value="act.id">
|
||||
{{ act.displayName }}
|
||||
</option>
|
||||
</select>
|
||||
<span v-if="switching" class="activity-spin">切换中…</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- 操作区 -->
|
||||
<div class="left-header">
|
||||
<div class="product-actions">
|
||||
@@ -85,6 +114,64 @@ const { loadProducts, productInfo, filteredProducts, loading } = useProducts()
|
||||
letter-spacing: .02em;
|
||||
}
|
||||
|
||||
.brand + .activity-box {
|
||||
border-top: 0;
|
||||
}
|
||||
|
||||
.activity-box {
|
||||
padding: 12px 18px;
|
||||
border-bottom: 1px solid var(--line);
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 6px;
|
||||
}
|
||||
|
||||
.activity-label {
|
||||
font-size: 11px;
|
||||
color: var(--muted);
|
||||
letter-spacing: .04em;
|
||||
}
|
||||
|
||||
.activity-row {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 8px;
|
||||
}
|
||||
|
||||
.activity-select {
|
||||
flex: 1;
|
||||
min-width: 0;
|
||||
appearance: none;
|
||||
background: var(--surface-2, var(--surface));
|
||||
color: var(--text-strong);
|
||||
border: 1px solid var(--line);
|
||||
border-radius: 8px;
|
||||
padding: 7px 10px;
|
||||
font-size: 13px;
|
||||
cursor: pointer;
|
||||
transition: border-color .15s ease;
|
||||
}
|
||||
|
||||
.activity-select:hover:not(:disabled) {
|
||||
border-color: var(--primary);
|
||||
}
|
||||
|
||||
.activity-select:focus {
|
||||
outline: none;
|
||||
border-color: var(--primary);
|
||||
}
|
||||
|
||||
.activity-select:disabled {
|
||||
opacity: .6;
|
||||
cursor: default;
|
||||
}
|
||||
|
||||
.activity-spin {
|
||||
font-size: 11px;
|
||||
color: var(--primary);
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
.left-header {
|
||||
padding: 14px 16px;
|
||||
border-bottom: 1px solid var(--line);
|
||||
|
||||
@@ -0,0 +1,64 @@
|
||||
import { ref } from 'vue'
|
||||
import { useToast } from './useToast'
|
||||
|
||||
// 活动项(与后端 types.ActivityInfo 对齐)
|
||||
export interface ActivityItem {
|
||||
id: string
|
||||
displayName: string
|
||||
}
|
||||
|
||||
// 模块级单例:活动列表与当前活动在所有组件中共享同一份状态
|
||||
const activities = ref<ActivityItem[]>([])
|
||||
const currentActivity = ref<ActivityItem | null>(null)
|
||||
const switching = ref(false)
|
||||
|
||||
// 与项目其他 composable 一致,直接走 Wails 运行时注入的 window.go.main.App
|
||||
const App = window.go.main.App
|
||||
|
||||
export function useActivity() {
|
||||
const { showToast } = useToast()
|
||||
|
||||
// 拉取全部活动与当前生效活动
|
||||
const loadActivities = async () => {
|
||||
try {
|
||||
const list = await App.GetActivities()
|
||||
activities.value = list || []
|
||||
try {
|
||||
currentActivity.value = await App.GetCurrentActivity()
|
||||
} catch {
|
||||
// 当前活动读取失败不阻塞列表展示
|
||||
}
|
||||
} catch (e: any) {
|
||||
showToast('读取活动列表失败', e?.message || '', 'error')
|
||||
}
|
||||
}
|
||||
|
||||
// 切换活动;成功返回 true,调用方可据此刷新商品等数据
|
||||
const switchActivity = async (id: string): Promise<boolean> => {
|
||||
if (id === currentActivity.value?.id) return true
|
||||
switching.value = true
|
||||
try {
|
||||
const d: Record<string, any> = await App.SwitchActivity(id)
|
||||
if (d && d.success) {
|
||||
currentActivity.value = { id: d.activity, displayName: d.displayName }
|
||||
showToast('活动已切换', (d.displayName || id) + ',正在刷新商品...', 'success')
|
||||
return true
|
||||
}
|
||||
showToast('切换失败', d?.error || '', 'error')
|
||||
return false
|
||||
} catch (e: any) {
|
||||
showToast('切换失败', e?.message || '', 'error')
|
||||
return false
|
||||
} finally {
|
||||
switching.value = false
|
||||
}
|
||||
}
|
||||
|
||||
return {
|
||||
activities,
|
||||
currentActivity,
|
||||
switching,
|
||||
loadActivities,
|
||||
switchActivity
|
||||
}
|
||||
}
|
||||
Vendored
+3
@@ -31,6 +31,9 @@ interface Window {
|
||||
ExportAccounts: (accountNames: string[], filename: string) => Promise<any>
|
||||
ExportAccountsWithProduct: (accountNames: string[], commodityID: string, commodityName: string) => Promise<any>
|
||||
OrganizeAccounts: (commodityID: string, commodityName: string, startTime: number, endTime: number) => Promise<any>
|
||||
GetActivities: () => Promise<Array<{ id: string; displayName: string }>>
|
||||
GetCurrentActivity: () => Promise<{ id: string; displayName: string }>
|
||||
SwitchActivity: (id: string) => Promise<{ success: boolean; activity?: string; displayName?: string; error?: string }>
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user