feat: 多用户权限体系、AI 助手、SKU 目录与合同清洗(开源准备)
本地长期开发成果的整体入库快照,包含后端鉴权/权限、AI 接入、合同解析、 SKU 目录等模块,以及前端相应页面与样式改版。 后端 - 新增鉴权与会话:scrypt 密码哈希、HttpOnly cookie(happy_sid)、登录失败锁定 - 新增「角色 → 权限组 → 权限点」三级权限模型与审计日志 - 新增 AI 提供商接入与预设(兼容 OpenAI 协议,内置 DeepSeek / 通义千问等) - 新增合同解析、合同文件保留策略、客户归属与访问控制 - 新增 SKU 目录、组织品牌、新客开发、系统日志等路由 前端 - 新增登录页与用户 / 权限组 / 系统日志管理页 - 新增客户详情、客户公海、询盘详情、报价编辑器、合同清洗中心 - 新增 AI 配置、组织品牌、包装参数、SKU 选择器等组件 - 新增英文大写金额、未保存改动拦截、抽屉与骨架屏 - 新增 stage1 样式层;产品、供应商、订单等页面改版 - EmbeddedSku 页面并入现有产品体系后删除 开源准备 - 新增 AGPL-3.0 LICENSE - README:移除未启用的 SQLCipher 加密声明(改为如实的「已知限制」)、 补充环境变量说明、许可证由「私有项目」改为 AGPL-3.0 - 移除历史遗留的空文件 _index_backup.txt - 文档中的项目路径更新为 happy-export
This commit is contained in:
@@ -0,0 +1,33 @@
|
||||
import React, { useEffect } from 'react'
|
||||
import { CloseIcon } from './Icons'
|
||||
|
||||
/**
|
||||
* 右侧抽屉。产品页原本各自内联了一份同样的结构,这里抽出来给新页面复用,
|
||||
* 保持「遮罩点击关闭 / Esc 关闭 / 正文独立滚动」三件事的行为一致。
|
||||
*/
|
||||
function Drawer({ title, sub, onClose, children, footer, wide = false }) {
|
||||
useEffect(() => {
|
||||
const onKeyDown = (event) => { if (event.key === 'Escape') onClose() }
|
||||
window.addEventListener('keydown', onKeyDown)
|
||||
return () => window.removeEventListener('keydown', onKeyDown)
|
||||
}, [onClose])
|
||||
|
||||
return (
|
||||
<>
|
||||
<div className="drawer-backdrop" onClick={onClose} />
|
||||
<aside className={`drawer${wide ? ' drawer-wide' : ''}`} role="dialog" aria-modal="true" aria-label={title}>
|
||||
<div className="drawer-header">
|
||||
<div className="drawer-head-main">
|
||||
<h2 className="drawer-title">{title}</h2>
|
||||
{sub && <p className="drawer-sub">{sub}</p>}
|
||||
</div>
|
||||
<button type="button" className="icon-btn" onClick={onClose} aria-label="关闭"><CloseIcon size={16} /></button>
|
||||
</div>
|
||||
<div className="drawer-body">{children}</div>
|
||||
{footer && <div className="drawer-footer">{footer}</div>}
|
||||
</aside>
|
||||
</>
|
||||
)
|
||||
}
|
||||
|
||||
export default Drawer
|
||||
Reference in New Issue
Block a user