refactor: frontend TS migration + Tailwind4/daisyUI5 unify + BUILDPLATFORM docker build

- migrate frontend to TypeScript (vue-tsc strict in build), upgrade all deps to latest (Vite 8, Tailwind 4, daisyUI 5, Pinia 4, vue-router 5)
- restructure frontend dirs (api/components/common/layouts/styles/types/views)
- drop Element Plus, add daisyUI TagInput; main CSS 490KB->163KB, entry JS 618KB->1.3KB
- rewrite Dockerfile(.cn): frontend/backend stages pinned to $BUILDPLATFORM, CGO_ENABLED=0 cross-compile, no QEMU in multi-arch builds; add .dockerignore
- local dev: Vite /api proxy + make dev targets; go:embed all:dist with .gitkeep so backend runs without prior frontend build
- fix latent bugs: Keys.vue users ref, Settings.vue undefined userStore, Login.vue Ref-as-error display, res.error misuse
- add REFACTOR_PLAN.md (phased refactor log)
This commit is contained in:
Sakurasan
2026-08-29 23:27:31 +08:00
parent 4a68ff6162
commit ac0a6808ec
55 changed files with 2497 additions and 2318 deletions
+139
View File
@@ -0,0 +1,139 @@
// src/stores/key.ts
import { defineStore } from 'pinia';
import { ref } from 'vue';
import type { AxiosResponse } from 'axios';
import request from '@/api/client';
import type { ApiKey, NewApiKeyPayload } from '@/types';
export const useKeyStore = defineStore('key', () => {
const loading = ref(false);
const error = ref<string | null>(null);
const totalKeys = ref(0);
const keys = ref<ApiKey[]>([]);
const key = ref<ApiKey | null>(null);
const fetchKeys = async (pageSize = 20, page = 1, active?: boolean | boolean[]) => {
loading.value = true;
error.value = null;
try {
const response = await request.get('/keys', {
params: {
pageSize,
page,
active,
},
});
keys.value = response.data.data?.keys ?? [];
totalKeys.value = response.data.data?.total ?? 0;
} catch (err: any) {
error.value = err.response?.data?.error || '获取ApiKeys失败';
throw error
} finally {
loading.value = false;
}
};
const fetchKey = async (id: number | string) => {
if (keys.value.length > 0) {
const findkey = keys.value.find(item => item.id === id)
if (findkey) {
key.value = findkey;
return;
}
}
loading.value = true;
error.value = null;
try {
const response = await request.get(`/keys/${id}`);
key.value = response.data.data;
if (key.value && (key.value.support_models?.length ?? 0) < 3) {
key.value.support_models = key.value.support_models_array ? JSON.stringify(key.value.support_models) : ''
}
if (key.value && !key.value.support_models_array) {
key.value.support_models_array = key.value.support_models ? JSON.parse(key.value.support_models) : []
}
} catch (err: any) {
error.value = err.response?.data?.error || '获取ApiKey失败';
throw error
} finally {
loading.value = false;
}
};
const refreshKey = async (id: number | string) => {
loading.value = true;
error.value = null;
try {
const response = await request.get(`/keys/${id}`);
key.value = response.data.data;
if (key.value && (key.value.support_models?.length ?? 0) < 3) {
key.value.support_models = key.value.support_models_array ? JSON.stringify(key.value.support_models) : ''
}
if (key.value && !key.value.support_models_array) {
key.value.support_models_array = key.value.support_models ? JSON.parse(key.value.support_models) : []
}
} catch (err: any) {
error.value = err.response?.data?.error || '获取ApiKey失败';
throw error
} finally {
loading.value = false;
}
}
const createKey = async (data: NewApiKeyPayload) => {
loading.value = true;
error.value = null;
try {
const response: AxiosResponse = await request.post('/keys', data);
return response;
} catch (err: any) {
error.value = err.response?.data?.error || '创建ApiKey失败';
throw error
} finally {
loading.value = false;
}
}
const updateKey = async (keyInfo: ApiKey) => {
loading.value = true;
error.value = null;
try {
const response: AxiosResponse = await request.put(`/keys/${keyInfo.id}`, keyInfo);
return response;
} catch (err: any) {
error.value = err.response?.data?.error || '更新ApiKey失败';
throw error
} finally {
loading.value = false;
}
}
const keyOption = async (option: string, ids: (number | string)[]) => {
loading.value = true;
error.value = null;
try {
const response: AxiosResponse = await request.post(`/keys/batch/${option}`, { ids });
return response
} catch (err: any) {
error.value = err.response?.data?.error || '操作失败';
throw err;
} finally {
loading.value = false;
}
}
//todo 更新 批量操作
return {
loading, error,
key, keys, totalKeys,
fetchKeys,
fetchKey,
refreshKey,
createKey,
updateKey,
keyOption,
}
});