refactor: 项目架构重构 - 目录标准化 + 清理冗余

- 目录重命名: backend/wdkj-server/ → server/, frontend/ai-dimension/ → client/
- 删除 20+ 冗余文件(WDKJ 旧脚本、Windows 脚本、过时文档、设计稿)
- 更新 package.json 元数据(移除 wdkj 命名)
- 完善三级 .gitignore(根 + server + client)
- 重写 README.md 和 CHANGELOG.md
- 工具脚本移至 scripts/
This commit is contained in:
Yuzhiran Dev
2026-07-11 12:45:37 +08:00
parent 66ac576082
commit c1d6dd3b29
106 changed files with 17436 additions and 2311 deletions
+39
View File
@@ -0,0 +1,39 @@
import { defineStore } from 'pinia'
import { ref } from 'vue'
import { aiChatApi } from '@/utils/api'
export const useChatStore = defineStore('chat', () => {
const messages = ref([])
const quota = ref({ remaining: 0, total: 0 })
const loading = ref(false)
async function ask(question, dimension = 'general', token) {
loading.value = true
try {
const data = await aiChatApi.ask(question, dimension, token)
messages.value.push({ role: 'user', content: question })
messages.value.push({ role: 'assistant', content: data.answer })
quota.value.remaining = data.remainingQuota
return data
} finally {
loading.value = false
}
}
async function fetchQuota(token) {
try {
const data = await aiChatApi.quota(token)
quota.value = data
return data
} catch (err) {
console.error('[chatStore] fetchQuota failed:', err)
return null
}
}
function clearMessages() {
messages.value = []
}
return { messages, quota, loading, ask, fetchQuota, clearMessages }
})
+3
View File
@@ -0,0 +1,3 @@
export { useUserStore } from './user'
export { useKnowledgeStore } from './knowledge'
export { useChatStore } from './chat'
+58
View File
@@ -0,0 +1,58 @@
import { defineStore } from 'pinia'
import { ref } from 'vue'
import { knowledgeApi } from '@/utils/api'
export const useKnowledgeStore = defineStore('knowledge', () => {
const list = ref([])
const currentDetail = ref(null)
const loading = ref(false)
const collected = ref([])
async function fetchList(params = {}) {
loading.value = true
try {
const data = await knowledgeApi.list(params)
list.value = data.list || data.items || []
} finally {
loading.value = false
}
}
async function fetchDetail(id) {
try {
currentDetail.value = await knowledgeApi.detail(id)
return currentDetail.value
} catch (err) {
console.error('[knowledgeStore] fetchDetail failed:', err)
return null
}
}
async function fetchCollected(token) {
try {
collected.value = await knowledgeApi.collected(token)
return collected.value
} catch (err) {
console.error('[knowledgeStore] fetchCollected failed:', err)
return []
}
}
async function toggleCollect(id, token) {
try {
const item = collected.value.find(i => i.id === id)
if (item) {
await knowledgeApi.uncollect(id, token)
collected.value = collected.value.filter(i => i.id !== id)
} else {
await knowledgeApi.collect(id, token)
collected.value.push({ id })
}
} catch (err) {
console.error('[knowledgeStore] toggleCollect failed:', err)
throw err
}
}
return { list, currentDetail, loading, collected, fetchList, fetchDetail, fetchCollected, toggleCollect }
})
+108
View File
@@ -0,0 +1,108 @@
import { defineStore } from 'pinia'
import { ref, computed } from 'vue'
import { authApi } from '@/utils/api'
export const useUserStore = defineStore('user', () => {
const token = ref(uni.getStorageSync('token') || '')
const userInfo = ref(null)
const subInfo = ref(null) // 订阅信息
const quota = ref(null) // AI 问答配额
const isLoggedIn = computed(() => !!token.value)
const isSubscribed = computed(() => {
if (!subInfo.value) return false
const expires = new Date(subInfo.value.expiresAt)
return expires > new Date()
})
const subscriptionLevel = computed(() => {
if (!subInfo.value) return 'free'
const expires = new Date(subInfo.value.expiresAt)
if (expires <= new Date()) return 'free'
return subInfo.value.plan || 'pro'
})
async function login(code, userInfoData) {
const data = await authApi.login(code, userInfoData)
token.value = data.token
userInfo.value = data.userInfo
uni.setStorageSync('token', data.token)
return data
}
async function h5Login(username, password) {
const data = await authApi.h5Login(username, password)
token.value = data.token
userInfo.value = data.userInfo
uni.setStorageSync('token', data.token)
return data
}
async function h5Register(username, password, nickName) {
const data = await authApi.register(username, password, nickName)
token.value = data.token
userInfo.value = data.userInfo
uni.setStorageSync('token', data.token)
return data
}
async function fetchMe() {
try {
const data = await authApi.me(token.value)
userInfo.value = data
return data
} catch (err) {
console.error('[userStore] fetchMe failed:', err)
return null
}
}
async function fetchSubInfo(tokenVal) {
// 从后端获取订阅信息 - 复用 knowledgeApi 或专门接口
// 当前后端无单独订阅接口,从 /api/user/progress 中获取
const { userApi } = await import('@/utils/api')
try {
const progress = await userApi.progress(tokenVal)
if (progress && progress.subscription) {
subInfo.value = progress.subscription
}
} catch (err) {
console.error('[userStore] fetchSubInfo failed:', err)
}
}
async function fetchQuota(tokenVal) {
const { aiChatApi } = await import('@/utils/api')
try {
const data = await aiChatApi.quota(tokenVal)
quota.value = data
return data
} catch (err) {
console.error('[userStore] fetchQuota failed:', err)
return null
}
}
function logout() {
token.value = ''
userInfo.value = null
subInfo.value = null
quota.value = null
uni.removeStorageSync('token')
}
return {
token,
userInfo,
subInfo,
quota,
isLoggedIn,
isSubscribed,
subscriptionLevel,
login,
h5Login,
h5Register,
fetchMe,
fetchSubInfo,
fetchQuota,
logout
}
})