d6af211a8ef9adaa174b75a798472ed7ddbd72a9
6
Commits
| Author | SHA1 | Message | Date | |
|---|---|---|---|---|
|
|
f8b1b96fd7 |
v39 第 39 批:观影弹框(antd 中文化 + 影院搜索 + 简介备注各占一行 + 海报照片对齐)
用户原话(四条):
①「观影模块的时间控件,比如说时间呀,还有下面的确定按钮啊。现在显示的都是英文,
应该给它设置成中文。」
②「影院那个地方应该有一个搜索的功能,下拉的地方上面有一个搜索筛选的功能。」
③「简介和备注不要放在一行,也就是说一个字段它就占一行。所以简介后面是一行,
备注后面是一行。」
④「海报和观影照片为什么和上面的标题不一样呢?海报的字体和简介是一样的,也带一个冒号。
然后把后面点击或拖动进行上传往后放,和简介后面的输入框保持一样大小。观影照片也是
类似的,观影照片也是加粗。和简介的字体保持一致,不带冒号,后面放上点击或拖动进行上传。」
① antd 中文化 —— 三个条件缺一不可(缺任一条按钮就还是英文)
· 🔴 **英文的真根因**:`antd.min.js` 这个产物**不含 locale 包**
(实测 `window.antd.locales` 是 undefined)⇒ 只能用它内置的英文默认值。
**换文件**才解决,不是加参数 ⇒ 改用 `antd-with-locales.min.js`
(多带各语言包,全局多挂 `antd.locales`,`antd.locales.zh_CN` 即简体中文包)。
· 🔴 dayjs 的中文 locale 是**单独一个文件**(核心包只有 en)⇒ 引 `dayjs-zh-cn.js`
并调 `dayjs.locale('zh-cn')`(星期/月份由 dayjs 出)。
· 🔴 必须用 `<ConfigProvider locale={zh_CN}>` 包住控件 —— antd 读的是**上下文里的**
locale,不包的话**日历文字会变中文、按钮却仍是英文**(最容易误判成"已经中文化了")。
· 独立探针 `_tooling/_antd_probe/{zh.html,zh_probe.py}` 9/0 把这三条钉死。
· 删除不再引用的 `assets/vendor/antd/antd.min.js`(1.5MB 冗余,留着会让
"两个 antd 哪个是真的"变成下一个坑);部署断言改为钉四资源 + ConfigProvider + zh-cn。
② 影院下拉加搜索筛选
· 搜索框放在弹出列表**内部**(`.cs-search` 吸顶),打开下拉**即聚焦**;回车选第一项。
· 🔴 `.cs-item[hidden] { display: none; }` **必须显式写** —— `.cs-item` 自己声明了
`display:flex`,会盖过浏览器默认的 `[hidden]{display:none}` ⇒ 过滤"看着完全没生效"
(项目第 11 批选人组件踩过同一个坑)。
· 三个事件都 stopPropagation,否则冒到 document 的"点外面关"⇒ 一点搜索框下拉就没了。
· 「不记录影院」恒保留(清空选择的出口);收起时清空搜索词(否则下次带着旧过滤)。
③ 简介 / 备注各占一行
· 撤销 v38 的 `.mv-pair` 并排(半宽的多行文本框每行都换行,更难读);
CSS 与模板里的并排容器**全部清干净**。
④ 海报 / 观影照片与简介对齐 —— 它们本来就不需要特殊规则
· 用户看到的"更窄/不一样"有两个原因:① 海报那块被误包进 `.mv-grid.mv-pair`
且**里面只有一个孩子** ⇒ grid 两列让它只占**半宽**;② 标签被一条
"宽度自适应、左对齐"的规则覆盖掉了固定 62px 右对齐 + 冒号。
· ⇒ 两块都改成普通 `.mv-row.mv-row-media`,标签用 `.mv-lb`(**继承**简介那套),
内容包 `.mv-media-body`(占满剩余);观影照片标签加 `.no-colon`。
实测:所有控件左缘 **424**、宽度 **624**,与简介**完全一致**。
· 🔴🔴 **通识**:v38 的 `.mv-media`(手填 margin-left:72px)是**被一个取错元素的
探针误导出来的** —— 它按文档序取"第一个非标签子元素",而 `_stage_drop.php` 吐的
`.sr-only` 文件框是 `position:absolute`(**脱离文档流、不参与 flex**),却被算成
"控件",于是得出"1px 隐框把上传框推走 130px"的**假结论**。
⇒ "对齐"类断言必须取直接子元素、且只取真正参与布局的那个;量到反常数字先怀疑探针。
验证(全部真机 + 反向验证):
· _fb_b39_movie.py **39/0**(中文化三条 + 搜索框打开即聚焦/输入即过滤/无匹配空态/
点搜索框不关下拉/回车选中/重开已清词 + 简介备注各占一行且占整行宽 +
海报照片标签字重字号同简介/海报带冒号/照片不带/上传框左缘与宽度同简介);
· _fb_b39_narrow.py **21/0**(宽 1440 / 平板 768 / 窄屏 390:不横向溢出、
标签与控件仍同行、影院下拉不出视口、搜索框可用);
· _fb_b39_falsify.py **14/0**(四处各自证伪成功:拿掉 ConfigProvider→按钮变英文、
藏起搜索框→②红、塞回两列并排→③红、标签退回普通 span→④红;复原回全绿);
· v38 两套按 v39 更新后 **36/0**(新增"已无 mv-pair / 主列 6 行");
v38 的旧窄屏套件(断言"简介备注并排")已作废删除,由 v39 窄屏完全覆盖;
· 全路由 e2e **1503/0**、日期控件真机 **53/0** + 反向 **7/0**、v37 两套、
观影照片两套、b30 三件套、各批真机与 DAV 三套、部署静态断言空跑 —— 全绿;
· 线上四个 antd 资源 HTTP **200 可达**;app.js / app.css / form.php / layout.php
的 SHA256 与本地**逐字节一致**。
⚠️ 顺带修的探针/夹具问题(都不是页面 bug):
· 夹具库重铺后 `cinemas` 是**空的** ⇒ v39 探针**自带播种**(造两家影院),
不再依赖别的套件先跑过(与 v38 的"名册只有 1 人"同类:页面没问题,是夹具没数据);
· 部署断言第一版按裸词 grep `mv-pair`,把注释里那句"已撤销 .mv-pair"当成回归
⇒ 改为只认 `class="...mv-pair..."` 这种**真的类名用法**;
· v39 探针第一版判"简介/备注各占一行"看的是"是不是同一个 DOM 节点"——
那个在**并排**时也是 false(并排仍是两个 .mv-row),连并排都抓不住
(反向验证当场抓到 13/1)⇒ 改为按**垂直位置**判(top 相差 ≥20px)。
|
||
|
|
8661ab6475 |
v38 第 38 批:观影试点 Ant Design 日期控件 + 弹框内联排版(对齐)+ 去提示 + 默认带自己
用户原话(四条):
①「我终于找到了一个我比较认可的日期选择插件
https://ant-design.antgroup.com/components/date-picker-cn 现在观影这个模块进行
测试吧,测试那个有开始、结束时间的。等这个模块测试完没问题了,再更新到其他的模块。」
②「记录一场电影,这个弹框因为标题和下面的输入框都是两行的,所以导致弹框非常长。
能不能排排版,让前面的标题后面加个冒号,后面的输入框直接跟在它后面,这样就变成一行。
包括开始、结束时间、影院、同行的人、简介等等,能把它排成一行的都排成一行,
但是一定要注意对齐的问题,如果不对齐的话可能不好看。」
③「里面的一些提示,比如片名可以从豆瓣自动补充,还有刚新建的影院会自动选中,
观影照片可以放这里且可多选,这些都把它去掉吧,节省一下上下的空间。」
④「另外一个同行的人,这里每个人添加的时候,应该默认带上自己,也就是自己不用选择
就应该已经选上了。」
① Ant Design RangePicker —— **只在观影试点**(用户明确"试完再推广")
· 资源 `assets/vendor/antd/{antd.min.js, dayjs.min.js, reset.css}`(unpkg 下载、随包上线);
layout.php 加 `fb-antd` 清单;`_datetime.php` 加 `$dtPlugin = 'antd'` 开关 +
`data-dt-antd="1"` 标记;app.js 加 `bootAntd()` / `mountAntd()`(按需加载)。
· 🔴 UMD 的硬依赖:antd 从**全局**取 React / ReactDOM / dayjs。缺 React 的报错是
`Cannot read properties of undefined (reading 'createContext')` —— 表现是"控件完全
不出现",不是样式问题。项目本来就有一套 React 18.3.1(Semi 用的),直接复用同一份。
· 🔴 实测出的关键行为(独立探针 `_antd_probe`,15/0):面板里有 **42 个日期格 +
2 个内联时间列(84 项)+ 「确定」按钮** —— 正是之前 Semi 缺的那两样;
且 **`onChange` 只在两端都齐了才触发**,单端改动走 `onCalendarChange` ⇒
回写必须两个都挂,否则"只填了开始时间就提交"会丢值。
· ⚠️ 原生那对下拉**全部保留**(值载体 + 拉不动时的兜底),挂上 antd 后用 clip 视觉收起
(不用 display:none —— 保持可聚焦)。
· 部署断言钉住试点边界:日程/任务**不该**出现 `$dtPlugin = 'antd'`。
② 弹框排版:标签内联 + 控件左缘对齐
· `.mv-row` = 标签(固定 62px、右对齐、**冒号由 CSS ::after 给**):控件(占满剩余)。
· 并排对:简介+备注、海报+观影照片 → `.mv-pair`(grid 1fr 1fr 保证两列等宽);窄屏回单列。
· 🔴 真机量出**两个真对齐缺陷**(不是猜的):
1) 时间行的控件左缘比别的行**偏 8px** —— `.dt-cols` 是 `gap: 10px 18px`(列距 18),
而普通 `.mv-row` 只有 `gap:10px` ⇒ 改 `.mv-row.dt-range.dt-cols { column-gap: 10px }`;
2) 海报/观影照片两行歪了 **130px** —— `_stage_drop.php` 在最前面插的 `.sr-only`
`<input>`(绝对定位 1px)**占掉了一整份 flex:1 1 auto**,把上传框推出去
⇒ 这两块改纵向 `.mv-media`(标签一行、内容从 72px 起,与主列对齐)。
⇒ 现在**所有字段控件左缘都是 444**;A/B 实测**弹框 1036px → 817px(矮 219px)**。
③ 删掉三句冗余提示(豆瓣补充 / 新建影院自动选中 / 观影照片),简介 rows 6→3。
④ 同行的人默认带上自己:新增时预置 `[我]`;编辑以库值为准;`old()` 存在时尊重用户上次勾选。
🔴 顺带修的真 bug:**antd 面板与弹框抢 Esc** —— 两个处理器都挂 document 上,
按一次 Esc 把日期面板和整个弹框一起关掉。已改成"antd 面板开着时弹框不吃 Esc"。
验证(全部真机 + 反向验证):
· _fb_b38_movie_form.py **33/0**(antd 挂上/面板有时间列与确定/值写回隐藏 *_date/
标签同行与左缘对齐/三句提示消失/默认带自己/试点边界);
· _fb_b38_narrow.py **6/0**(宽屏并排、窄屏回单列、无横向溢出);
· _fb_b38_falsify.py **8/0**(排版退回上下两行、antd 只挂 onChange、不预置自己 → 各自必须红);
· e2e **1503/0**、日期控件真机 **53/0** + 反向 **7/0**、v37 两套 **27/0 + 5/0**、
观影照片 **16/0** + **8/0**、b30 三件套、b18 选人 **10/0**、几何交互 **109/0**、
DAV 三套、部署静态断言空跑 —— 全绿;
· 线上 app.js / app.css / antd.min.js 的 SHA256 与本地一致。
⚠️ 顺带修了探针/夹具的三处**测试侧**问题(都不是页面 bug):
· e2e 里 6 条 jsdom 用例(测选人弹框"暂存区机制")前提是"一个都没选",
默认带自己后全假红 ⇒ 在**测试自己的 HTML 副本**上清掉 `data-pp-selected`;
· `_fb_b18_picker` 真机探针同理,改成**点 chip 上的 ×**(组件把已选存在闭包里,
改属性没用 —— 试过两种写法都是白试);
· `_fb_b34_dtrange` 的"标签文案"断言写死了「开始 / 结束」,
而 v38 把观影的标签简化成了「时间」⇒ 改成"有非空标签即可";
另补一条 antd 分支(挂 antd 后原生被裁成 1px,`1px > 0` 会让旧判据**假通过**)。
· 顺带:夹具名册只有 1 人时会误报"无法验证多选",已把实际候选数打出来。
|
||
|
|
5d80b9480b |
v24 第 11 批:7 大条 20 子项(首页/名册/观影/裁剪/日程/财务)
用户 2026-10-04 第 11 批,7 大条: - #1 首页:未来七天过滤掉「农历」(每日一条会淹掉真日程);右侧日历本标签 从灰字(.dash-tag)改成**实心色块**(底色=日历色、白字、text-shadow 兜底浅色)。 - #2 名册:分组改**居中模态框**(用户要"像选观影人一样")。修掉"点第二次失效" ——根因是旧实现用**捕获阶段**监听 document click 做"点外面就关",与触发按钮 的 click 打架;模态把关闭收敛到遮罩/✕/取消。卡片「编辑」后加「删除」 (→ people/destroy);详情页底部删除改成 btn-danger + btn-block-lg 大红按钮 + 两步确认。 - #3 名册详情页重排:.detail(260px+1fr) → .pcard(头像左上 + 右侧姓名/标签) + .detail-stack 全宽往下。旧布局头像卡比右栏矮,头像下留一大片空白。 - #4 观影:影院下拉换**自定义组件**(原生 <option> 画不了色块)——按钮+列表、 每行色点,值仍写隐藏 input[name=cinema_id];「管理影院」→「新建影院」弹框 (带 back=movies/new,存完回本页并 ?cinema=<id> 自动选中)。 修「开始/结束时间标签跑到控件下面」:upgradeRange 原来 insertBefore(host, group.firstChild) 把控件插到了 label 之上 —— 改成插在第一个原生控件之前。 - #5 裁剪改 **Cropper.js**(assets/vendor/cropper/,按需加载走 fb-cropper meta): 弹框 overflow:hidden + 固定画布(**无滚动条**)、**去掉缩放条**改滚轮 wheelZoomRatio、 viewMode:1 + autoCropArea 保证框小于画布、8 个触点全露。 结果仍写 *_crop = 归一化 x,y,w,h(提交契约不变)。 - #6 日程:内置节假日原来每天只标**一天**(国庆只出一条)→ FIXED 改成 [名字, 放假天数] 按区间铺;月视图从周日改**周一**起(表头同步); 跳转日期从"长条+原生框"改成**单个 btn-icon**,点开弹 Semi 日期选择器。 - #7 财务:单条曲线无盘点时只回一个点(图看着像全 0)→ 改成"从创建日(0)画到今天"; 图下条目从"每账目一张小图卡"改成**一张 chart_multi 多线图 + 颜色图例** (Ledger::LEGEND_COLORS 按 id 取模,保证颜色稳定);账目页卡顿同源治理 (行上只留按钮、表单全页一份 #ledPanels);修改按钮改弹框并回填归属人。 ## 顺带修的真 bug(本批最要紧的三条) 1. **观影表单提交静默失效**:「新建影院」弹框被误嵌在观影主表单 <form> 内。 HTML 不允许 form 嵌套 → 浏览器拆开内层,弹框里 required 的"影院名称"变成 主表单必填项、又因 hidden 无法聚焦 → 点「记下这场电影」什么都不发生 (Chrome: invalid form control with name='name' is not focusable)。 → 弹框移到主表单之后。部署脚本加防线:按顺序配平 form 开闭判断是否嵌套。 2. **裁剪取消没清空文件框**(换 Cropper 时丢)→ close(cancelled),4 个取消入口 传 true 清空;否则"点了取消"仍会把没裁的原图传上去。 3. **裁剪预览退化成原图**(同批丢)→ 用 canvas 按 Cropper 的原图像素矩形重画, toDataURL 写回预览,恢复"所见即所得"。 ## 连带修复:选人组件懒渲染(线上实测的必要性) 线上真实数据下账目页 6939 KB / 16788 个 input、观影表单 1194 个 input —— 根因是 _person_picker.php 首屏就把**全部候选人**渲成 <label>+<input>。 改成:首屏只留「不选」+ data-pp-people(JSON),**打开弹框时**才 buildList(); 无 JS 兜底走 <noscript>(HTML5 规定启用脚本时其内容按纯文本解析,不产生节点)。 新增 window.ppSetSelected / decorateItems(动态项要补算首字母)。 实测账目页 6939 KB → 544 KB。新增 _fb_picker_lazy_check.py(11/0 + 反向 2 红)。 验证:e2e 786/0、交互 90/0、半集成 27/0、batch_e 91/0、batch10 46/0、batch9 38/0、 crop 17/0(+反向)、picker_unify 28/0、picker_lazy 11/0(+反向)、formbloat 9/0、 upgrade 126/0、mobile 688/0、drag 5/0、geom 5/5。 线上自检 19/19;线上真实账号验收 7/0(含"主表单无隐藏必填""线上 Cropper 接管+取消清空")。 |
||
|
|
52cc1ecccb |
v24 第 9 批:名册九条(分组按钮/加入名册/生日月日/地址四级/千人性能/拖动修复/删除人员/返回名册/Semi DatePicker)
- #131 名册卡片加「分组」按钮(details+radio,显示当前分组,选中即改) - #132 修复「从已有人里加入名册」无反应 - #133 生日只显示月和日(阳历 MM-DD / 农历中文名),PersonQuery::birthdaysOf 取代 birthdayOf - #134 地址结构化为 国家/省/市/区+详细:regions 表(3429 行全国区划)+ Region.php + ?r=regions 级联接口 + 表单 .addr-grid + 老地址回填(Schema v16) - #135 千人名册性能:.person content-visibility:auto + 名册页 ob_gzhandler (实测 服务端 1.15s/3.8MB → 0.17s/87KB;客户端导航→load 1.35s → 0.37s) - #136 拖动排序改 Pointer Events(Chrome 下 HTML5 DnD 在 DOM 变动时断) - #137 个人详情页底部「删除人员」 - #138 编辑资料页加「返回名册」 - #139 所有日期选择换 Semi Design DatePicker(渐进增强:原生四字段保 POST 契约, 懒加载 vendor semi UMD,值回写原字段;工作经历 type=month 一并升级;宣纸主题对齐) 验证:e2e 785/0、batch9 37/0、upgrade 126/0、picker 28/0、mobile 688/0、interact 97/0、 batch_e 91/0、import 21/0、douban 22/0、drag 5/0、semi-integrate 28/0、semi-probe 17/0、 geom 5/5;部署后线上自检 16/16(含 4 个 semi 资源 200 + regions 路由)。 |
||
|
|
c9037f79be |
家谱 v22:改按 family-chart 官方用法接,并放开代数上限
用户指出「只需要按照 json 格式,把以我为中心的关联数据全部取出来,
全都封装进去就行了,id 用用户表的 id,性别名字生日头像都是现成的,
只需要把配偶、父母和孩子放进去用 id 关联」——并强调「之前一定是你
调用的方法不对」。
== 验证结论(先量再改)==
用**官方示例自己的数据**(donatso 的 data.json,13 人,格式完全官方)
跑了一遍:库画出 11 人,**配偶 Andrea 的父母 Zadro/Zadra 一个都没画**。
那两位就在数据里、rels.parents 也指向他们、格式与官方示例一字不差。
→ 说明「按格式全塞进去就能画全」在**姻亲**这一项上不成立:
库的算法只走「树根的祖先链 + 后代 + 树根的兄弟姐妹 + 各人配偶」,
**不会从配偶继续向上/向下 walk**。这是库的算法边界,不是格式/关联问题。
== 但用户的批评有一半是对的:调用方式确实有我没做足的地方 ==
官方示例是:<div id="FamilyChart" class="f3"> + 引 family-chart.css。
我之前**既没加 f3 类、也没引库 CSS**,而是自己在 app.css 里手补
`.kin-chart svg.main_svg{width:100%;height:100%}` 去绕开 300×150 那个坑 ——
属于"用歪门邪道达到同样效果"。现在按官方来:
· 容器加 `f3` 类(库的 CSS 全部以 .f3 作用域)
· 引入官方 family-chart.css(新增 vendor 文件)
· 在 app.css 里把库的深色主题变量覆盖成家书宣纸色
(--male-color / --background-color / --text-color 等)
· 自己的 svg 撑满那条规则删掉(官方 CSS 已提供)
== 放开代数上限(用户要求「全部取出来」)==
官方示例**不调** setAncestryDepth / setProgenyDepth —— 库在"未设置"时
会跳过深度截断,等于不限代数。我之前写死了 2/3,真实家庭一超过就被砍。
现在不设这两个值。服务端 familyMap 的 up/down 也从 (2,2) 放到 (9,9)
(这两个参数只影响**代数标号**,超出会压到边界档导致曾祖辈与祖辈混层;
遍历本身是走遍整个连通图的,人员收录数不受影响)。
== 工具同步 ==
- familybook_deploy.sh:新增 v22 三条契约(vendor CSS 在 / 模板引了它 /
容器有 f3 类),并加**反向断言**「不许再出现 setAncestryDepth|setProgenyDepth」;
旧的"卡片尺寸/间距"断言同步。
- _fb_kin_geom_falsify.py:注入②的原锚点(setProgenyDepth)已随本次删除,
换成「禁掉上溯循环」——树根退回「我」,伯父/堂兄/堂嫂/堂侄/侄子那批旁支
会离开画面,J 项必须红。3/3 全抓住。
- ⚠️ 又踩一次「注释撞断言字面量」:新写的注释里提到 setProgenyDepth 函数名,
把「不许再设代数上限」这条反向断言直接打红。改注释避开字面量后恢复。
== 战绩 ==
e2e 549/0 · 桌面几何 368/0 · 移动端 516/0 · 交互 97/0 · 升级专测 123/0
家谱可视化 24/0 · 家谱版面 10/0 · 反向验证 3/3 · 静态断言空跑 RC=0
部署 + 线上自检全过。
|
||
|
|
7f00d3e553 |
feat(kin,movies): 家谱改用第三方库 family-chart;观影设置按钮改纯图标并统一页头度量
家谱(v13): - 自研布局是死结,不是样式问题:连线的横杆是网格项,只能横跨「父母列→子女列」 整段区间,中间夹着与血缘无关的人(如媳妇那侧的岳父母)时必然从卡片上穿过。 换成 family-chart(D3 生态,MIT)后,排布只走本家血脉 + 配偶,姻亲不进画布, 这个死结在构造上就不存在了。 - 接入踩到并修掉的坑:main_id = data[0].id(「我」必须排最前); 卡片回调里自定义字段在 d.data.data(双层);库的 family-chart.css 是死文件 (全挂在 .f3 作用域,运行时没有 .f3 元素);库的 svg 撑满选择器永不命中 (必须自己补 .kin-chart svg.main_svg);setCanAdd/setOnCardClick 不在 chart 上 (写错会抛异常,把 updateTree 一起带走 → 整张图空白,页面照样 200)。 - 关掉 setSingleParentEmptyCard:库默认给孩子只登记一位父母的人自动补一张无名 配偶卡,看着像「凭空多出一个配偶」。 - 卡片用原生 <a> 链成员页,不依赖库的点击回调。 观影按钮(用户本轮原话): - 「记一场电影」与「设置」高度仍不一致 —— 根因是文字按钮高度由 padding+line-height 自然推出(43.8px),而 .btn-icon 写死了 40px。抽出 --act-* / --act-h 变量,两边同源。 - 设置按钮去掉「设置」二字,只留图标,图标换成三条横线(☰)。 - 设置按钮在所有页面排最右(.movie-set 用 margin-left:auto 顶到行尾)。 - 除设置外其他按钮都有颜色,与设置区分(主按钮实心 / 次要浅底 / 危险淡红)。 顺带修掉一个特异性 bug:删除按钮被 .btn 品牌底盖成实心红,与「编辑」难分辨。 - 设置下拉四个条目文字前都加图标(行内 SVG,不引外部字体)。 测试与部署: - 新增 _fb_kin_check.py(桌面,12 条)+ _fb_kin_falsify.py(6/6)证明 「整张家谱空白」这类只靠通用几何抓不到的坏法能被抓住。 - _fb_geom_mobile.py 家谱段重写为窄屏语义(库按容器 fit 缩放是正常行为, 改为断「比例没被压扁 / 缩放不至于看不清」),并加 _fb_kin_mobile_falsify.py(4/4)。 - _fb_btn_check.py(59 条)+ _fb_btn_falsify.py(3/3)覆盖观影页头按钮五条需求。 - familybook_deploy.sh / familybook_smoke.sh 的家谱断言改为第三方库形态, 设置按钮断言改为 btn-icon 纯图标 + 三条横线 + 条目图标。 - 新增 .gitattributes:vendor 库与 .min.js 标 -text,原样入库不被改写行尾。 |