Drsakura and Claude Opus 5
3380dbc9d7
chore(release): v1.1.0
...
本次内容:
fix 客户联系人新增 / 跟进编辑补归属校验(两处越权,已实测利用成功再封堵)
feat 订单支出台账 —— 快递费、吊卡费等杂费挂到订单上,带跨币种汇率快照
feat 产品速查浮层 Ctrl/⌘+J —— 报价时就地查采购价、起订量、箱规
三处 package.json 一起改:lib/updater.js 的 currentVersion() 按
「仓库根 → backend」的顺序找版本号,只改一处的话,部署形态变了版本号就不对。
Co-Authored-By: Claude Opus 5 <[email protected] >
2026-10-22 15:23:21 +08:00
Drsakura and Claude Opus 5
226949fa53
feat(sku): 产品速查浮层(Ctrl/⌘+J)
...
报价报到一半想确认某个货的采购价、起订量、箱规时用。跟已有的两个东西都
不是一件事:
⌘K 全局搜索 是「找到后跳过去」—— 一跳走,正在写的报价就断了
SkuPicker 是「挑一个塞进表单」—— 要点产品组再点货号,两层
速查 是「就地看数」—— 不跳转、不改任何东西,Esc 回到刚才的地方
· 新接口 GET /api/sku/quick:一次把采购价、起订量、供应商、规格、箱规、
阶梯价全带回来,不返回 path(它不是用来跳转的)。
· 货号精确/前缀命中排最前。报价时多半直接敲货号,让它跟在一堆品名模糊
匹配后面就等于没做速查。
· 箱规拼成「40×30×25cm / 12.5kg / 装 24」一句话 —— 报价要的是这一句,
不是四个分开的数字。
· 点货号或价格可复制;clipboard API 在非 HTTPS 内网下不可用,退回
execCommand。
· 没占 ⌘K,因为那已经是全局搜索了,抢掉会打断老习惯。
· 页脚写死「价格是采购价,不是报价」防手滑。
Co-Authored-By: Claude Opus 5 <[email protected] >
2026-10-22 15:23:10 +08:00
Drsakura and Claude Opus 5
f32a2daaef
feat(order): 订单支出台账(快递费/吊卡费等杂费)
...
订单上原本只有「卖给客户多少钱」,而一张单真实花出去的还有寄样品的快递费、
印吊卡的费用、商检报关拖车。不记下来就算不出这单赚没赚 —— 小单子几百块
杂费能把毛利吃掉一截。
· 新表 order_expenses,一张订单挂多笔:类型/金额/币种/日期/收款方/单号/
已付未付/备注。单独成表而不是往 orders 加列,因为杂费是多笔不定项的,
寄三次样品就是三条快递费,各有单号;塞进 orders 只能存一个合计,事后
对不出「这 800 块是哪来的」。
· 跨币种强制填汇率并存快照。杂费基本是人民币、订单常是美元;不存快照的话
汇率一变历史订单毛利跟着变,账永远对不上。同币种强制按 1,防止前端传个
7.2 把美元支出又乘一遍。
· 新权限点 order.expense,不复用 order.edit。掏钱寄样品的是销售业务员,
而销售业务组只有 order.view —— 挂在 order.edit 上要么他记不了账,要么
为了让他记账得把「改订单金额」一起给他。启动时 syncNewPermissions()
会自动把这个新点补给四个默认组。
· 订单列表加「杂费」列(合计 + 未付)。SUM 外层再 ROUND 一次:不加会漏出
348.15999999999997 这种浮点尾巴直接显示在页面上。
· 金额逐行取两位再相加,保证明细几行加起来等于合计。
Co-Authored-By: Claude Opus 5 <[email protected] >
2026-10-22 15:22:56 +08:00
Drsakura
13d67c804f
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
2026-09-17 14:53:02 +08:00
Drsakura
436519e0a6
feat(embed): 合同导入与工作台融成一体(主题/字体/配色/滚动全对齐)
...
深色外壳里嵌一张米白纸、外加两层滚动条,是「没浑然一体」的根源:
- 宿主把当前主题下的设计令牌 postMessage 给嵌入页(跨源读不到对方的
CSS 变量),两边共用同一套配色/字体/圆角;切主题即时跟随,不用刷新
(src 里的 theme 只作首帧初值,避免换主题触发 iframe 重载白闪)
- 收起嵌入页里重复的部件:自带侧栏、顶栏指标条(货号总数/供应商/待核对)、
右下角「问一句」悬浮球(宿主已有小皮)
- 只留一层滚动:路由区固定为视口高度,滚动交给 iframe 内部
- 输入框沿用宿主的「无方框」规则:去掉描边与焦点光环,改底色区分
- 页面头去掉「新窗口打开」(打开的是裸 SKU 页),刷新改成图标按钮
- 令牌名对不上时会告警,免得嵌入页悄悄回落到旧配色
2026-09-11 12:53:22 +08:00
Drsakura
453f3b1583
fix(header): 顶栏搜索框补 type="text"(最后一个裸 input,避免再掉进浏览器默认样式)
2026-09-11 11:48:07 +08:00
Drsakura
fa4dd6482b
feat(ui): 助手正名「小皮」+ 全站输入框去掉描边方框
...
助手改名
- 「小屁」→「小皮」(AI 浮窗标题/按钮/占位文案/工作台引导语 + 注释)
输入框一律无方框(靠底色区分,聚焦换成 primary 底色)
- 根因一:全局选择器写成 input[type="text"] 列表,AI 浮窗输入框没写 type
完全没吃到样式,渲染成浏览器默认的 2px 灰直角框(就是「丑出天际」那个),
顺手补上 input:not([type]) 兜底 + 给该输入框补 type="text"
- 根因二:聚焦时同时叠了 input[type] 的 1px 描边 + 3px 光环,以及
:focus-visible 的 2px 外描边(鼠标点文本框也会命中),一共三层方框
- 覆盖范围:全局 form 控件、顶栏搜索、汇率金额、备忘录添加行、
日历添加日程、跳转浮层年月输入框、设置里 API Key / 下拉
2026-09-11 11:45:20 +08:00
Drsakura
850abe9327
feat(calendar): 跳转浮层年月改为直接输入,回车快速跳转
...
- 点开 🗓 后的浮层标题由「弹出拨盘」改为输入框:前 4 位是年、后 1~2 位是月,
只填 4 位则沿用当前月;回车跳转并关闭编辑态,Esc 取消且不关浮层
- 非数字自动过滤、上限 6 位;月越界或年份越界标红提示且保留焦点
- 进入编辑态时把「2026年9月」换成「202609」并全选,两种触发(鼠标按下/聚焦)都稳
- 工具条上的年月文字仍保留 iOS 拨盘入口
2026-09-11 11:22:04 +08:00
Drsakura
0453a49e4e
feat(calendar): 年月拨盘(iOS 闹钟式滚轮)替换工具条的月份文字
...
- 新增 components/MonthYearWheel.jsx:年、月两列滚轮
· scroll-snap 吸附 + 指针按住拖动 + 鼠标滚轮/触摸板,停稳 140ms 后落值
· 滚动过程中实时算居中行,中间行放大加粗高亮、相邻行缩小淡出(像苹果拨盘)
· 点某一行直接跳到该行;「回到今天」一键回当月
· 年份范围默认前后 12/20 年,两侧夹在视口内,下方放不下自动翻到上方
- 两个入口:
· 工具条上的「2026年9月」由 <strong> 换成按钮,点击弹出拨盘,再点一次收起
· 日期跳转浮层里的标题同样可点:点击后浮层收起、同位弹出拨盘
- 拨盘选完年月,主日历与跳转浮层同步过去
修掉一个竞态:两列在同一帧内先后停稳时,后一次会读到渲染期闭包里的旧值,
把前一次的结果覆盖(滚到 2028年12月 会退回 2026年12月)。
改为组件内用 ref 保存最新年月、每次落值先更新 ref 再回调。
顺带修正跳转浮层标题多出来的一个右花括号。
2026-09-11 11:06:36 +08:00
Drsakura
4c3ec995b6
feat(workspace): 日历再瘦身 + 右侧面板等高填满 + 日期跳转按钮 + 小屁浮窗化
...
日历
- 单元格 72→60px,日号 19→17px、字号 11→10px,事件条与周标同步收紧,
标题区 padding 与提示文案一起压小
- 工具条右边的「月」按钮删掉,换成日历小图标按钮:悬浮/展开变蓝(primary 实底),
点击弹出迷你月历(自带年月切换 + 回到今天),点某天即跳月并选中该日
右侧面板
- 「今日 to do」与「待办事项」改成按列高 58/42 平分,列表自身 flex 撑满并可滚动;
之前待办被挤到底部只剩一条空文案,现在两块都填满整列
- 跳转浮层 z-index 82,压过小屁浮窗(78);设置遮罩提到 90,保证仍是最高层
AI 助手 → 小屁
- 全屏遮罩 + 右侧整条抽屉删掉,改成右上角 348px 宽浮动小窗:
可拖动(位置记 localStorage,越界自动夹回视口)、可最小化成小条、双击标题栏切换
- App.jsx 不再因为小屁打开而 inert 主界面(只有设置才是模态),
所以可以一边让小屁干活一边自己点系统:实测开着窗导航、选日期、填备忘录都正常
- 文案全部改名小屁,顶栏按钮、面板标题、工作台摘要里的引导语一并更新
顺手
- 顶栏搜索的 ⌘K 提示块加 nowrap,1024 宽度下不再折成两行
2026-09-10 23:56:52 +08:00
Drsakura
b9d6296591
feat(workspace): 日历瘦身 + 右侧「今日 to do / 选中日待办」双面板
...
日历
- 行高 92→72px,行程条只留 2 条(超出折成 +N 并压缩成小 chip),标题区与周标同步收窄
- 选中态重做:去掉了原来生硬的 2px 内描边,改成单元格内嵌圆角环 + 淡入缩放动画;
「今天」改为日号描边圆环,与「选中」的实心日号区分开
- 侧栏宽度不足时(≤1200px)自动改为上下排布
右侧新增两块
- 「今日 to do」:备忘录性质。底部常驻加号输入框,回车即建;建完前面出现勾选框,
勾选后划线变淡并沉到已完成组末尾(输入框始终在最后一行);可取消勾选回到未完成组;
悬浮出现删除按钮;列表过长可滚动,勾选后自动滚进视野
- 「待办事项」:显示日历上选中那天的日程与节日(未选中时默认今天),
带优先级点与说明,右上角「新建」直接为该日添加日程
- 原左栏重复的 [TASK QUEUE] 面板移到这里后删除,避免同名面板出现两次
后端
- todos 增加 list 列(schedule 日历日程 / memo 备忘录待办),老库启动时自动补列
- GET /api/todos 支持 list=memo;POST 支持 list,memo 不写日期
- 新增 PATCH /api/todos/:id(勾选完成/取消、改标题等)与 DELETE /api/todos/:id
2026-09-10 23:35:20 +08:00
Drsakura
33dc71f8c3
feat(calendar): 工作日历选中态 + 再次单击添加日程 + 日程/节日悬浮详情
...
- 单击日期选中(主题色底 + 内描边环),再次单击同一日期弹出「添加日程」浮层
- 浮层支持标题 / 优先级 / 备注,保存后写库并即时刷新日历与工作台待办
- 悬浮日程或节日显示详情小窗:日程含日期/优先级/状态/客户/备注,
节日含外贸视角的具体说明(对出货、订舱、客户响应的影响)
- 节日补充春节(2025–2035 逐年查表)、感恩节与黑色星期五
- 超过 3 项时折叠为 +N,悬浮查看剩余条目
- 后端新增 GET /api/todos(按日期范围)与 POST /api/todos
- 浮层用 fixed 定位 + 视口翻转/夹取,渲染后按真实高度校正一次;
滚动跟随锚点;Esc 与点击外部关闭;日期格支持键盘 Enter/Space
2026-09-10 23:16:29 +08:00
Drsakura
02e985c011
fix(suppliers): 主营类目去重,消除 React 重复 key 警告
...
splitCats 未去重,源数据里同一类目重复登记时(如「游标卡尺;游标卡尺」)
会渲染出两个 key 相同的 chip。React 会因此报
'Encountered two children with the same key',且该行为官方标注为 unsupported。
在 splitCats 出口处按原顺序去重,既消警告也避免卡片上出现重复标签。
由无头浏览器全站巡检发现(供应商页原本有 22 条此类警告)。
2026-09-10 17:52:56 +08:00
Drsakura
46a963e23d
feat(header): 顶栏时钟可切时区 + 汇率计算器;工作台移除运行日期
...
1) 工作台
- 删掉欢迎区右侧的「运行日期」卡片,含 luxury.css 里对应样式与窄屏残留
2) 顶栏时钟(仿小满 CRM)
- 新增 TimeZoneClock:时钟图标 +「东八区:北京,上海 ⌄」+ 大号时间(20px 等宽,
tabular-nums 保证秒位不跳动),下方小字带日期
- 点整块展开时区列表,23 个时区由西向东排列,每行右侧实时显示该地时间与 UTC 偏移
- 时区用 IANA 名(Europe/London 等)而非写死偏移,夏令时自动正确;
打开列表会自动滚到当前选中项;选择记 localStorage('happy.clockZone')
- 新增 src/timezones.js 集中时区表与格式化工具
3) 顶栏汇率计算器
- 新增 FxCalculator:计算器图标点开浮层,默认 USD→CNY
- 左右两侧各带可搜索的币种下拉(币种来自接口返回的全部币种,常用币种排前),
中间一键互换;任一框输入另一框实时反算;显示主汇率与倒数汇率
- 换币种时锁住所改那一侧的数字(与 Google 换算一致)
- 金额按数量级自动取精度(USD→VND 与 CNY→USD 都不出现一堆无意义的零)
- 新增 src/currencies.js(币种中文名 + 排序 + 交叉汇率与格式化)
4) 后端汇率接口
- 新增 /api/fx/rates:以 USD 为基准返回全量汇率,前端据此算任意币种交叉汇率
- 主源 open.er-api.com(166 币种),备源 frankfurter.app(欧洲央行);
内存 + 落盘缓存 1 小时,并发请求只发一次网络
- 网络不可用时依次回退「上次成功的数据」→「内置离线汇率表」,
并在响应里用 source/warning 标注,前端明确提示数据来源
5) 顶栏排布
- 时钟变宽后中等屏会溢出,新增 ≤1440px 断点收紧留白/品牌区/搜索框;
搜索框允许收缩;1280/1100/980/700 各档实测无横向溢出
- 移动端(≤680px)汇率浮层改用固定定位铺满两侧,避免左侧被裁
6) .gitignore
- backend/data/ 整体忽略(trade.db、fx-cache.json 等全是运行时产物)
2026-09-10 17:44:36 +08:00
Drsakura
1edf5ac995
feat(nav): 侧栏高对比度 + 顶栏已打开页面标签 + 折叠态只留日夜切换 + 换明月图标
...
1) 侧边栏对比度
- 新增 --sb-* 专属色板(固定深色底,不随日夜主题翻转),文字 #c3d7e3、
hover 纯白、选中纯白 + 品牌色强调条 + 内描边,参考 GoodJob 的 Command Deck
- 原过渡曲线(--transition-fast/base)保持不变
- luxury.css 里把侧栏刷回浅底的覆盖一并改为同一套色板
2) 顶栏「已打开页面」标签
- 新增 src/navigation.js:NAV_GROUPS 与 PAGE_LABELS 单点维护,App 与顶栏共用
- GlobalHeader 用 useLocation 自动登记访问过的页面,工作台恒定置顶且不可关闭,
其余按最近使用排序,可单独关闭,最多 10 个,落 localStorage(happy.openTabs)
- 关掉当前标签会退到剩下的最近一个,没有则回工作台
3) 折叠态页脚
- .sidebar.collapsed .settings-btn 隐藏,76px 宽度下只留一个日夜切换按钮
4) 明月图标
- MoonIcon → MoonStarsIcon,造型取自 igoutu.cn/icon/101343/moon-and-stars,
重绘为矢量(月牙 = 两段圆弧相减,两枚凹边圆角四角星),走 currentColor 随主题变色
- 源图存 design-refs/(已忽略,不入库)
5) 顶栏排布修正
- 标签条加入后头部变挤,收窄品牌区/搜索框,按钮加 nowrap 防止文字折行
- ≤1280px 隐藏标签条
2026-09-10 17:25:38 +08:00
Drsakura
d650ff9c4d
refactor(layout): 顶栏横跨整宽并压在侧边栏之上,侧栏去标题、按钮移到工作台右侧
...
- App.jsx: 新增 .app-shell / .app-body 两层结构,GlobalHeader 提到侧边栏之前;
inert 上移到 .app-shell,行为不变
- 侧边栏删除带 happy出口通 的 .sidebar-header(logo 与名字统一交给顶栏,且更大)
- 折叠/展开按钮从侧栏标题栏移到「工作台」右侧(.sidebar-top),收起时自动落到工作台下方
- 新增 --header-height 变量(80px,≤680px 时 62px),顶栏 min-height 与侧栏 sticky top/
height、route-content min-height 全部据此计算
- 移除已失效的 .sidebar-header 规则(含 ≤900px 媒体查询)
2026-09-10 17:04:05 +08:00
Drsakura
47f6214056
feat: 品牌标识用云+数据库矢量图标(favicon + 页眉品牌标)
...
- Icons.jsx 新增 CloudDbIcon:照 icons8-云 重绘为矢量,左云随主题色、右圆柱用品牌蓝
- GlobalHeader 品牌区前置该图标,原「系统在线」绿点改为挂在其右下角
- index.html 增加 rel=icon / mask-icon 指向 public/favicon.svg
- luxury.css 补品牌样式,并让 :not() 选择器排除 .brand-mark 避免样式误伤
2026-09-10 16:58:52 +08:00
Drsakura
e4537d5bf0
feat: 设置页新增「系统与更新」,按 GitHub 版本号检查更新
...
- 顶层 package.json 作为应用版本唯一来源(happy-export v1.0.0)
- backend/lib/updater.js:查 GitHub Release(优先)或 tag,与本机版本做 semver 比对
- backend/routes/system.js:GET /api/system/info、GET /api/system/check-update(30s 缓存)
- /api/health 版本号改为读真实版本
- 设置页新增第 4 个分类:当前版本 / 更新源仓库 / 检查更新(含更新说明折叠)
- 新增 RefreshIcon
2026-09-10 16:23:42 +08:00
Drsakura
d8df2c3960
chore: happy 出口通初始提交(前端 React + 后端 Express,采购管理已原生化)
2026-09-10 16:16:59 +08:00