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:
@@ -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 }
|
||||
})
|
||||
@@ -0,0 +1,3 @@
|
||||
export { useUserStore } from './user'
|
||||
export { useKnowledgeStore } from './knowledge'
|
||||
export { useChatStore } from './chat'
|
||||
@@ -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 }
|
||||
})
|
||||
@@ -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
|
||||
}
|
||||
})
|
||||
Reference in New Issue
Block a user