chore: sync various improvements and fixes
- Update gitignore and serena config - Improve connection and voting stores - Enhance admin routes and socket handling - Update client-screen views - Add auth middleware Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
1
packages/client-mobile/src/components.d.ts
vendored
1
packages/client-mobile/src/components.d.ts
vendored
@@ -12,7 +12,6 @@ declare module 'vue' {
|
||||
ProgramCard: typeof import('./components/ProgramCard.vue')['default']
|
||||
RouterLink: typeof import('vue-router')['RouterLink']
|
||||
RouterView: typeof import('vue-router')['RouterView']
|
||||
StampDock: typeof import('./components/StampDock.vue')['default']
|
||||
VanButton: typeof import('vant/es')['Button']
|
||||
VanCell: typeof import('vant/es')['Cell']
|
||||
VanCellGroup: typeof import('vant/es')['CellGroup']
|
||||
|
||||
@@ -18,7 +18,7 @@ type GalaSocket = Socket<ServerToClientEvents, ClientToServerEvents>;
|
||||
const STORAGE_KEYS = {
|
||||
USER_ID: 'gala_user_id',
|
||||
USER_NAME: 'gala_user_name',
|
||||
DEPARTMENT: 'gala_department',
|
||||
SESSION_TOKEN: 'gala_session_token',
|
||||
};
|
||||
|
||||
// Helper functions for localStorage
|
||||
@@ -50,7 +50,7 @@ export const useConnectionStore = defineStore('connection', () => {
|
||||
const reconnectAttempts = ref(0);
|
||||
const userId = ref<string | null>(loadFromStorage(STORAGE_KEYS.USER_ID, null));
|
||||
const userName = ref<string | null>(loadFromStorage(STORAGE_KEYS.USER_NAME, null));
|
||||
const department = ref<string | null>(loadFromStorage(STORAGE_KEYS.DEPARTMENT, null));
|
||||
const sessionToken = ref<string | null>(loadFromStorage(STORAGE_KEYS.SESSION_TOKEN, null));
|
||||
const votedCategories = ref<VoteCategory[]>([]);
|
||||
|
||||
// Computed
|
||||
@@ -85,6 +85,7 @@ export const useConnectionStore = defineStore('connection', () => {
|
||||
reconnectionDelayMax: CONFIG.RECONNECTION_DELAY_MAX_MS,
|
||||
timeout: CONFIG.HEARTBEAT_TIMEOUT_MS,
|
||||
transports: ['websocket', 'polling'],
|
||||
auth: sessionToken.value ? { token: sessionToken.value } : undefined,
|
||||
});
|
||||
|
||||
// Connection events
|
||||
@@ -193,8 +194,8 @@ export const useConnectionStore = defineStore('connection', () => {
|
||||
{
|
||||
userId: userId.value,
|
||||
userName: userName.value || 'Guest',
|
||||
department: department.value || '未知部门',
|
||||
role: 'user',
|
||||
sessionToken: sessionToken.value || undefined,
|
||||
},
|
||||
(response: any) => {
|
||||
if (response.success) {
|
||||
@@ -264,15 +265,17 @@ export const useConnectionStore = defineStore('connection', () => {
|
||||
/**
|
||||
* Set user info (and persist to localStorage)
|
||||
*/
|
||||
function setUser(id: string, name: string, dept: string) {
|
||||
function setUser(id: string, name: string, token?: string) {
|
||||
userId.value = id;
|
||||
userName.value = name;
|
||||
department.value = dept;
|
||||
if (token) {
|
||||
sessionToken.value = token;
|
||||
saveToStorage(STORAGE_KEYS.SESSION_TOKEN, token);
|
||||
}
|
||||
|
||||
// Persist to localStorage
|
||||
saveToStorage(STORAGE_KEYS.USER_ID, id);
|
||||
saveToStorage(STORAGE_KEYS.USER_NAME, name);
|
||||
saveToStorage(STORAGE_KEYS.DEPARTMENT, dept);
|
||||
|
||||
// Rejoin if already connected
|
||||
if (socket.value?.connected) {
|
||||
@@ -287,13 +290,13 @@ export const useConnectionStore = defineStore('connection', () => {
|
||||
// Clear state
|
||||
userId.value = null;
|
||||
userName.value = null;
|
||||
department.value = null;
|
||||
votedCategories.value = [];
|
||||
sessionToken.value = null;
|
||||
|
||||
// Clear localStorage
|
||||
localStorage.removeItem(STORAGE_KEYS.USER_ID);
|
||||
localStorage.removeItem(STORAGE_KEYS.USER_NAME);
|
||||
localStorage.removeItem(STORAGE_KEYS.DEPARTMENT);
|
||||
localStorage.removeItem(STORAGE_KEYS.SESSION_TOKEN);
|
||||
|
||||
// Disconnect socket
|
||||
disconnect();
|
||||
@@ -333,7 +336,7 @@ export const useConnectionStore = defineStore('connection', () => {
|
||||
reconnectAttempts,
|
||||
userId,
|
||||
userName,
|
||||
department,
|
||||
sessionToken,
|
||||
votedCategories,
|
||||
|
||||
// Computed
|
||||
|
||||
@@ -152,6 +152,10 @@ export const useVotingStore = defineStore('voting', () => {
|
||||
showToast({ message: '请先选择一个奖项', position: 'bottom' });
|
||||
return false;
|
||||
}
|
||||
if (!connectionStore.sessionToken) {
|
||||
showToast({ message: '请先扫码登录', position: 'bottom' });
|
||||
return false;
|
||||
}
|
||||
|
||||
// 检查是否已为该节目投过票(任何奖项)
|
||||
const existingAward = getProgramAward(programId);
|
||||
|
||||
@@ -14,7 +14,6 @@ const isValidating = ref<boolean>(true);
|
||||
const isValid = ref<boolean>(false);
|
||||
const isSubmitting = ref<boolean>(false);
|
||||
const userName = ref<string>('');
|
||||
const department = ref<string>('技术部');
|
||||
const errorMessage = ref<string>('');
|
||||
|
||||
// API base URL - use LAN IP for mobile access
|
||||
@@ -22,7 +21,7 @@ const apiUrl = import.meta.env.VITE_API_URL || 'http://192.168.1.5:3000';
|
||||
|
||||
// Computed
|
||||
const canSubmit = computed(() => {
|
||||
return userName.value.trim().length > 0 && department.value.trim().length > 0;
|
||||
return userName.value.trim().length > 0;
|
||||
});
|
||||
|
||||
// Validate token on mount
|
||||
@@ -92,7 +91,6 @@ async function handleSubmit() {
|
||||
body: JSON.stringify({
|
||||
scanToken: token.value,
|
||||
userName: userName.value.trim(),
|
||||
department: department.value.trim(),
|
||||
}),
|
||||
});
|
||||
|
||||
@@ -101,8 +99,9 @@ async function handleSubmit() {
|
||||
|
||||
if (result.success) {
|
||||
// Set user info in connection store
|
||||
const userId = result.data?.sessionToken || `user_${Date.now()}`;
|
||||
connectionStore.setUser(userId, userName.value.trim(), department.value.trim());
|
||||
const userId = result.data?.userId || `user_${Date.now()}`;
|
||||
const sessionToken = result.data?.sessionToken;
|
||||
connectionStore.setUser(userId, userName.value.trim(), sessionToken);
|
||||
|
||||
showToast({ message: '登录成功!', type: 'success' });
|
||||
|
||||
@@ -156,13 +155,6 @@ async function handleSubmit() {
|
||||
:rules="[{ required: true, message: '请输入姓名' }]"
|
||||
maxlength="20"
|
||||
/>
|
||||
<van-field
|
||||
v-model="department"
|
||||
label="部门"
|
||||
placeholder="请输入您的部门"
|
||||
:rules="[{ required: true, message: '请输入部门' }]"
|
||||
maxlength="20"
|
||||
/>
|
||||
</van-cell-group>
|
||||
|
||||
<div class="button-wrapper">
|
||||
|
||||
Reference in New Issue
Block a user