feat: 版本详情完整功能 + 数据串联 + 登录模块
- 版本详情:关联需求Tab(从需求池添加已采纳需求/移除释放) - 版本详情:调研/产品方案/UI设计Tab(计划CRUD、完成提交成果、耗时统计) - 版本详情:超期校验(结束日期超版本截止需填写原因) - 版本详情:概览统计卡片(加班时长/排名/原因占比) - 数据串联:产品→项目→版本→需求→加班全链路贯通 - 版本管理:规划中版本可删除,删除释放关联需求 - 数据清理:仅保留翻台宝/值班,需求池10条值班待评审需求 - 修复:列表页overflow裁剪菜单问题(4个页面统一修复) - 新增:登录模块、AuthGuard、VersionPlan store Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
91
apps/web/stores/useAuthStore.ts
Normal file
91
apps/web/stores/useAuthStore.ts
Normal file
@@ -0,0 +1,91 @@
|
||||
'use client';
|
||||
|
||||
import { create } from 'zustand';
|
||||
|
||||
interface AuthUser {
|
||||
id: string;
|
||||
name: string;
|
||||
roleId: string;
|
||||
departmentId: string;
|
||||
phone: string;
|
||||
email: string;
|
||||
}
|
||||
|
||||
interface AuthState {
|
||||
user: AuthUser | null;
|
||||
isAuthenticated: boolean;
|
||||
login: (phone: string, password: string, remember: boolean) => boolean;
|
||||
logout: () => void;
|
||||
checkAuth: () => void;
|
||||
}
|
||||
|
||||
const SESSION_KEY = 'ftb_auth_session';
|
||||
const PERSIST_KEY = 'ftb_auth_persist';
|
||||
|
||||
export const useAuthStore = create<AuthState>((set) => ({
|
||||
user: null,
|
||||
isAuthenticated: false,
|
||||
|
||||
login: (phone, password, remember) => {
|
||||
const membersRaw = localStorage.getItem('ftb_members_v1');
|
||||
let members: any[] = [];
|
||||
if (membersRaw) {
|
||||
const parsed = JSON.parse(membersRaw);
|
||||
members = parsed.members || [];
|
||||
}
|
||||
|
||||
// fallback: 如果 localStorage 没有数据或为空,使用默认 mock
|
||||
if (members.length === 0) {
|
||||
members = [
|
||||
{ id: 'm-1', name: '张三', departmentId: 'dept-1', roleId: 'role-pm', phone: '13800138001', email: 'zhangsan@company.com', password: 'Ftb@2024' },
|
||||
{ id: 'm-2', name: '李四', departmentId: 'dept-2-1', roleId: 'role-dev', phone: '13900139002', email: 'lisi@company.com', password: 'Ftb@2024' },
|
||||
{ id: 'm-3', name: '王五', departmentId: 'dept-2-2', roleId: 'role-dev', phone: '13700137003', email: 'wangwu@company.com', password: 'Ftb@2024' },
|
||||
{ id: 'm-4', name: '赵六', departmentId: 'dept-2-3', roleId: 'role-test', phone: '13600136004', email: 'zhaoliu@company.com', password: 'Ftb@2024' },
|
||||
{ id: 'm-5', name: '孙七', departmentId: 'dept-3', roleId: 'role-design', phone: '13500135005', email: 'sunqi@company.com', password: 'Ftb@2024' },
|
||||
{ id: 'm-6', name: '周八', departmentId: 'dept-4', roleId: 'role-pm', phone: '13400134006', email: 'zhouba@company.com', password: 'Ftb@2024' },
|
||||
{ id: 'm-7', name: '吴九', departmentId: 'dept-2-1', roleId: 'role-dev', phone: '13300133007', email: 'wujiu@company.com', password: 'Ftb@2024' },
|
||||
{ id: 'm-8', name: '陈十', departmentId: 'dept-1', roleId: 'role-admin', phone: '13200132008', email: 'chenshi@company.com', password: 'Ftb@2024' },
|
||||
];
|
||||
}
|
||||
|
||||
const member = members.find((m: any) => m.phone === phone && (m.password || 'Ftb@2024') === password);
|
||||
if (!member) return false;
|
||||
|
||||
const user: AuthUser = {
|
||||
id: member.id,
|
||||
name: member.name,
|
||||
roleId: member.roleId,
|
||||
departmentId: member.departmentId,
|
||||
phone: member.phone,
|
||||
email: member.email,
|
||||
};
|
||||
|
||||
set({ user, isAuthenticated: true });
|
||||
sessionStorage.setItem(SESSION_KEY, JSON.stringify(user));
|
||||
if (remember) {
|
||||
localStorage.setItem(PERSIST_KEY, JSON.stringify(user));
|
||||
}
|
||||
return true;
|
||||
},
|
||||
|
||||
logout: () => {
|
||||
set({ user: null, isAuthenticated: false });
|
||||
sessionStorage.removeItem(SESSION_KEY);
|
||||
localStorage.removeItem(PERSIST_KEY);
|
||||
},
|
||||
|
||||
checkAuth: () => {
|
||||
const session = sessionStorage.getItem(SESSION_KEY);
|
||||
if (session) {
|
||||
set({ user: JSON.parse(session), isAuthenticated: true });
|
||||
return;
|
||||
}
|
||||
const persist = localStorage.getItem(PERSIST_KEY);
|
||||
if (persist) {
|
||||
const user = JSON.parse(persist);
|
||||
set({ user, isAuthenticated: true });
|
||||
sessionStorage.setItem(SESSION_KEY, JSON.stringify(user));
|
||||
return;
|
||||
}
|
||||
},
|
||||
}));
|
||||
Reference in New Issue
Block a user