feat(dev): 本地开发工具集 v0.5.6-dev-tooling
包含本地 dev 链路完整跑通的工具集(不进生产): backend: - dev_auth.py: /api/dev/login Mock 企微 OAuth(/dev/* 路由) - messages.py: dev 模式短路企微推送,避免 invalid corpid 噪音 - main.py: dev 模式启动时建 5 条 demo conversation,让前端有数据可测 frontend: - PortalSelect.vue: dev 模式 enterRole 跳完整 URL(5173/5174/5175 端口),生产仍走相对路径 infrastructure: - docker-compose.dev.yml: dev compose(包含 backend/postgres/redis) scripts(Windows PowerShell): - dev-frontend-install.ps1: 一次性装 4 个前端依赖 - dev-frontend-start.ps1: 后台起 4 个前端 dev server - dev-check-schema-drift.ps1: 对比 SQLAlchemy 模型 vs Postgres schema,漂移 exit 1 docs: - CURRENT-FOCUS.md: 项目状态看板(每次 session 维护)
This commit is contained in:
@@ -140,12 +140,16 @@ const selectedRole = ref<string | null>(null)
|
||||
|
||||
// ==================== 生命周期 ====================
|
||||
|
||||
onMounted(async () => {
|
||||
/**
|
||||
* 初始化门户会话(可重入)
|
||||
* 流程:OAuth2 回调 → 缓存 token → 没登录就尝试 Mock(OAuth2 失败时)→ 加载用户信息
|
||||
*/
|
||||
async function initPortalSession(): Promise<boolean> {
|
||||
const urlParams = new URLSearchParams(window.location.search)
|
||||
const token = urlParams.get('token')
|
||||
const code = urlParams.get('code')
|
||||
|
||||
// 1. 企微 OAuth2 回调:URL 中有 code 参数
|
||||
// 1. 企微 OAuth2 回调:URL 中有 code 参数
|
||||
if (code && !token) {
|
||||
loading.value = true
|
||||
try {
|
||||
@@ -197,6 +201,30 @@ onMounted(async () => {
|
||||
}
|
||||
}
|
||||
// 无 corpId 或获取失败:显示错误(开发环境可 Mock 登录)
|
||||
// DEV_MODE 兜底:本地 dev 环境自动调 /api/dev/login 拿 token
|
||||
if (import.meta.env.DEV || import.meta.env.VITE_DEV_MODE === 'true') {
|
||||
try {
|
||||
loading.value = true
|
||||
const devResp = await apiClient.get('/dev/login', {
|
||||
params: {
|
||||
userid: 'dev-multi-001', // 多角色用户,可以看到完整角色选择
|
||||
name: 'Dev User',
|
||||
dept: '信息技术部',
|
||||
},
|
||||
})
|
||||
const devToken = devResp.data?.data?.token
|
||||
if (devToken) {
|
||||
portalStore.setToken(devToken)
|
||||
// 直接刷新页面,onMounted 重跑,这时 token 已在 localStorage 里
|
||||
window.location.reload()
|
||||
return
|
||||
}
|
||||
} catch (devErr) {
|
||||
console.error('DEV_MODE Mock 登录失败:', devErr)
|
||||
} finally {
|
||||
loading.value = false
|
||||
}
|
||||
}
|
||||
error.value = '未登录,请通过企业微信工作台访问'
|
||||
return
|
||||
}
|
||||
@@ -218,6 +246,13 @@ onMounted(async () => {
|
||||
}
|
||||
}
|
||||
// 否则:显示角色选择页面(让用户选择)
|
||||
}
|
||||
|
||||
/**
|
||||
* 钩到 Vue 生命周期:挂载时执行一次
|
||||
*/
|
||||
onMounted(() => {
|
||||
initPortalSession()
|
||||
})
|
||||
|
||||
// ==================== 方法 ====================
|
||||
@@ -237,11 +272,20 @@ function enterRole(role: string) {
|
||||
localStorage.setItem('portal_selected_role', role)
|
||||
|
||||
// 跳转到对应的工作台
|
||||
const roleUrls: Record<string, string> = {
|
||||
user: '/itdesk/',
|
||||
agent: '/itagent/',
|
||||
admin: '/itadmin/',
|
||||
}
|
||||
// dev 模式:4 个前端在不同端口,要用完整 URL(从 import.meta.env 读)
|
||||
// 生产模式:nnginx 同一域名不同子路径,直接用相对路径
|
||||
const isDev = import.meta.env.DEV
|
||||
const roleUrls: Record<string, string> = isDev
|
||||
? {
|
||||
user: import.meta.env.VITE_DESK_URL_DEV || 'http://localhost:5174/itdesk/',
|
||||
agent: import.meta.env.VITE_AGENT_URL_DEV || 'http://localhost:5173/itagent/',
|
||||
admin: import.meta.env.VITE_ADMIN_URL_DEV || 'http://localhost:5175/itadmin/',
|
||||
}
|
||||
: {
|
||||
user: '/itdesk/',
|
||||
agent: '/itagent/',
|
||||
admin: '/itadmin/',
|
||||
}
|
||||
|
||||
const url = roleUrls[role]
|
||||
if (url) {
|
||||
|
||||
Reference in New Issue
Block a user