feat: 实现需求管理、加班记录、成员/角色管理模块
- 需求模块:完整 CRUD、状态流转(采纳/拒绝/关闭)、详情抽屉、产品→项目级联选择 - 加班记录:产品→项目→版本三级联动、月份筛选(MonthPicker)、CSV 导出 - 成员管理:左右布局(部门树+成员列表)、手机号脱敏、初始密码自动生成及规则设置 - 角色管理:卡片列表、系统角色保护、CRUD - 通用组件:FilterSelect 下拉、MonthPicker 月份选择器、Pagination 分页 - 样式统一:状态标签加 border、日期输入现代化、筛选组件风格一致 Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
65
apps/web/lib/members.ts
Normal file
65
apps/web/lib/members.ts
Normal file
@@ -0,0 +1,65 @@
|
||||
export interface Department {
|
||||
id: string;
|
||||
name: string;
|
||||
parentId?: string;
|
||||
order: number;
|
||||
createdAt: string;
|
||||
}
|
||||
|
||||
export interface Member {
|
||||
id: string;
|
||||
name: string;
|
||||
departmentId: string;
|
||||
roleId: string;
|
||||
phone: string;
|
||||
email: string;
|
||||
password: string;
|
||||
createdAt: string;
|
||||
}
|
||||
|
||||
export interface RoleItem {
|
||||
id: string;
|
||||
name: string;
|
||||
description?: string;
|
||||
createdAt: string;
|
||||
isSystem?: boolean;
|
||||
}
|
||||
|
||||
export interface PasswordRule {
|
||||
prefix: string;
|
||||
length: number;
|
||||
includeUppercase: boolean;
|
||||
includeLowercase: boolean;
|
||||
includeNumbers: boolean;
|
||||
includeSpecial: boolean;
|
||||
}
|
||||
|
||||
export const DEFAULT_PASSWORD_RULE: PasswordRule = {
|
||||
prefix: 'Ftb',
|
||||
length: 8,
|
||||
includeUppercase: true,
|
||||
includeLowercase: true,
|
||||
includeNumbers: true,
|
||||
includeSpecial: false,
|
||||
};
|
||||
|
||||
export function generatePassword(rule: PasswordRule): string {
|
||||
let chars = '';
|
||||
if (rule.includeUppercase) chars += 'ABCDEFGHJKLMNPQRSTUVWXYZ';
|
||||
if (rule.includeLowercase) chars += 'abcdefghjkmnpqrstuvwxyz';
|
||||
if (rule.includeNumbers) chars += '23456789';
|
||||
if (rule.includeSpecial) chars += '!@#$%&*';
|
||||
if (!chars) chars = 'abcdefghjkmnpqrstuvwxyz23456789';
|
||||
|
||||
const randomLength = Math.max(rule.length - rule.prefix.length, 4);
|
||||
let result = rule.prefix;
|
||||
for (let i = 0; i < randomLength; i++) {
|
||||
result += chars[Math.floor(Math.random() * chars.length)];
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
export function maskPhone(phone: string): string {
|
||||
if (!phone || phone.length < 7) return phone;
|
||||
return phone.slice(0, 3) + '****' + phone.slice(7);
|
||||
}
|
||||
Reference in New Issue
Block a user