| # | 功能 | 出现位置 | 一句话说明 |
|---|---|---|---|
| 1 | 隐藏网格 + 高亮隐藏参数 | 画布底部工具条 | 进入编辑器自动隐藏网格,并打开「高亮隐藏参数」 |
| 2 | 参数提示框顺序优化 | 参数输入框的补全浮层 | 把浮层前两项顺序调换,避免挡手 |
| 3 | 更新商品名称 | 右键属性栏 | 一键把当前商品名称同步更新 |
| 4 | 关闭所有干涉 | 部件栏 | 批量关闭干涉检测 |
| 5 | 分类隐藏 | 部件栏 | 按分类批量隐藏部件 |
| 6 | 锁定值 + 回车确定 + 自动聚焦 | 属性下拉浮层 | 「锁定」链接;填值时回车=确定;浮层弹出自动聚焦 |
| 7 | 属性行快捷按钮(W / D / H) | 尺寸、物理属性行 | 一键把尺寸填成参数引用或增减 90° |
| 8 | 引用名按钮 + 鼠标拖拽 | 部件属性行 | 一键填同名参数;拖拽交换 / 赋值 |
| 9 | 悬停显示实际值 | 所有可编辑控件 | 鼠标移入时在鼠标上方显示站点算出来的真实值 |
| 10 | 左栏多布尔内嵌多选 | 左栏「当前值」单元格 | 多布尔参数渲染成下拉框样式,点整框直接勾选,不用开设置弹窗 |
| 11 | 结构导航面板图钉 | 结构导航浮动面板标题栏 | 「收起」图标换成图钉,可钉住常显 / 取消钉住后鼠标移出自动收起 |
进入编辑器后自动执行:
目的:建模时画面干净,且隐藏的部件一眼可见。
参数输入框的自动补全浮层(.auto-complete-select-list)弹出时,把前两个子项顺序调换,
让鼠标不用移太远就能选到第二项。
属性栏里加一个按钮,点击后用当前值刷新商品名称。
在部件栏的按钮组后插入一个 「关闭所有干涉」 按钮,一次关掉全部干涉检测。
按分类批量隐藏部件(如「布尔」「隐藏」等分组)。
针对带自定义输入的下拉浮层(.attr-select-input-dropdown + .custom-input):
| 增强 | 行为 |
|---|---|
| 锁定链接 | 每个下拉选项后追加「锁定」,点了以后该值被锁住 |
| 回车 = 确定 | 浮层输入框有内容且处于焦点时,按 Enter 等同点「确定」 |
| 自动聚焦 | 浮层弹出后输入框自动获得焦点,光标移到末尾 |
两条必须遵守的边界:
position: fixed 且按需创建,offsetParent 恒为 null
→ 判「浮层是否可见」只能看 display / visibility / opacity + getBoundingClientRect() 有没有实际尺寸。Enter 必须让给站点(把第一条候选填进输入框),
绝不能替用户点「确定」。尺寸、物理属性行后面追加小按钮,一键把该行填成对应的参数引用(或用 #REF±90 形式做角度换算)。
显示规则
li.attr-group-container,
按 .attr-group-header 文本判定)。尺寸属性 / 物理属性 / 系统属性 / 前端使用属性
这些分组里的行不显示按钮;.attr-select-input)立即显示按钮,不等浮层展开;.multi-input-select-wrap,如「材质」「倒角情况」)不显示——这种行用不到;点击行为
把该行的值直接写成 #<本行引用名>。
引用名从标签 id 取:
label.id = attr-list-item-<REF>→REF就是引用名。 例如标签 id 为attr-list-item-KC1,点按钮就把值写成#KC1。
| 拖拽 | 起点 → 落点 | 结果 |
|---|---|---|
| ① 按钮 → 按钮 | 行 A 的按钮 → 行 B 的按钮 | 两行同名参数引用名互换:A 写 #B的引用名,B 写 #A的引用名(不是对调现有值) |
| ② 按钮 → 控件 | 行 A 的按钮 → 行 B 的输入框/下拉框 | 把 A 的当前值写进 B |
| ③ 标签 → 标签 | 行 A 的左侧标签文字 → 行 B 的标签文字 | 两行当前值互换 |
限制
li.closest('li.attr-group-container') + .attr-group-header 文本含「部件属性」。| 落点 | 高亮对象 | class |
|---|---|---|
| 按钮 | 该按钮 | .kjl-drop-hit-el |
| 值控件 | 该控件 | .kjl-drop-hit-el |
| 整行(仅标签拖拽) | li |
.kjl-drop-hit |
平时只有「部件属性」里的行标签显示抓手光标(li[data-kjl-part="1"] .item-title),其余分组保持默认光标——否则看着像能拖,实际拖不动。
拖拽期间:html.kjl-drag-active 生效 → 全局抓手光标、禁止选中文本、清掉 mousedown 产生的选区。
拖到合法落点即弹出预览(跟随鼠标,优先显示在鼠标上方,上方不够则显示在下方):
| 场景 | 形态 | 「新值」列的含义 |
|---|---|---|
| ① 按钮→按钮 | 「交换值」,两行 | #对方引用名 |
| ③ 标签→标签 | 「交换值」,两行 | 对方的当前值 |
| ② 按钮→控件 | 「赋值」,一行 | 源行的当前值 |
样式:白底、1px 边框、圆角 8px、外阴影,13px 字号,width: max-content(自适应内容,不截断)。
实现要点:没有用 HTML5
draggable。本站drop事件根本不触发(dragover收到了, 但preventDefault无效、dropEffect一改就被取消)。改为鼠标事件自实现:document级mousedown委托 + 移动阈值判定 + 释放时按落点元素决定动作。
onChange无论是点按钮还是拖拽,落值都走数据层,不去改 DOM 输入框、也不去「展开下拉 → 填值 → 点确定」:
props.onChange({ eventKey: props.eventKey, value: '#新值' })
eventKey 形如 4/14/3FO3VWBVOB5E,每行不同,必须从当前 fiber 现取;缺它会抛
Cannot read properties of undefined (reading 'split');.custom-input input → 点 .custom-input-btn」。鼠标移入任一可编辑控件,在鼠标上方弹出小面板(上方空间不够时显示在下方):
┌────────────────┐
│ 整 无孔 0 │ ← ①参数类型首字(13px 灰)②枚举展示名(13px 黑)③真实值(15px 蓝加粗)
└────────────────┘
参数类型前缀:类型名取第一个字(浮 / 整 / 字 / 布 / 多 / 材 / 轮 / 样),字号与展示名一致(13px)、无边框、灰色 #86909c,后面留 5px。
类型来自参数自身的 valueType,映射:
| valueType | 参数类型 | 前缀 |
|---|---|---|
float |
浮点数 | 浮 |
int |
整数 | 整 |
string |
字符串 | 字 |
boolean |
布尔值 | 布 |
booleanlist |
多布尔 | 多 |
material |
材质 | 材 |
profile / contour |
轮廓 | 轮 |
style |
样式 | 样 |
不显示行名(鼠标本来就在那一行上,名字是多余的);
不显示原始内容(#EC4 / 公式这类,行里本来就显示着,再抄一遍纯属噪音);
枚举行会在数值左边补展示名:后连接 = #EC4 算出来是 0,按该行的选项表
[{value:"0",label:"无孔"},{value:"1",label:"有孔"}] 翻成 无孔 0;
反过来也成立:如果是下拉里直接选中的(控件显示的就是展示名,如「有孔」),
会按选项表反查它的值,同样显示成 有孔 1;
展示名和值相同的(如 平铺=平铺、单面油漆=单面油漆)只显示一次;
纯文字值只显示一行。
覆盖的控件类型
| 控件 | 选择器 |
|---|---|
| 下拉框 | .attr-select-input |
| 输入框 | .auto-input-container / 行内 input(排除浮层里的) |
| 组合框(如材质) | .multi-input-select-wrap |
| 左栏「当前值」 | .param-row-item-value-column |
不显示的几处(鼠标移上去不会弹提示):
.attr-select-input-dropdown:选项列表 / 自定义参数 / 确定按钮).tui-select-dropdown).formula-result-trigger,站点自己会在那里显示结果).kjl-ref,那是「动作」不是「值」)值是怎么算出来的(关键)
复用站点自己的计算入口——就是「输入框右边那个计算器按钮,鼠标移上去会显示结果」用的同一套:
// 任一 auto-input / formula-result-trigger 组件的 props 上都挂着这个函数
calculateFormula: function (formula, valueType) {
return s.formulaCenter.calculateFormula(formula, valueType);
}
POST https://www.kujiale.com/editor/api/site/formula,返回
{ id, error, value, valueType },异步约 80~160ms;formulaCenter,抓到一次就能算任意表达式;valueType 必须按行传(int / float / string / …),否则会算错或直接报错。
实测:#DS(单双面油漆)按 string → "双面油漆";按 float → VALUE_PARSE_ERROR。labelFor(rowId, value)(算完公式后调用);
名→值走 optionValueOf(rowId, text)(纯文字表达式用,事件 kjl-opt → kjl-opt-result)。props.options = [{value:"",label:"未选择"},{value:"0",label:"无孔"},{value:"1",label:"有孔"}]。
下拉闭合时浮层根本不在 DOM 里,只能从 props 取;取值时字符串比一次、数值比一次
(0 / 0.0 / "0.00" 视为同一个)。实测对照(脚本显示值 == 站点计算器悬停显示值):
| 行 | 原始内容 | 显示 |
|---|---|---|
| 宽度 | #W |
600 |
| 深度 | #D-#FBH |
382 |
| 单双面油漆 | #DS |
双面油漆 |
| 锁孔朝向 | #CC_FX==0?1:0 |
0 |
| 图框材质抓取 | #ZCZQ |
1 |
| 左连接 | #EC3 |
1 |
| 材质角度 | #CZFX |
0 |
左栏是另一套 DOM(.param-row),同样支持悬停显示,规则一致:
| 部分 | 怎么取 |
|---|---|
| 值 | 行组件 props.data.value。它是原始值(可能是 #YG_HBL、#W 这类引用),含 # 时按 props.data.valueType 调站点 calculateFormula 再算一次;为空则退回单元格文本 |
| 展示名 | ① 下拉行(.tui-select)直接用单元格里显示的文字(有孔、底部、上);② 否则按引用名借右栏同名属性行的选项表反查 |
实测:
| 参数 | 单元格形态 | 提示 |
|---|---|---|
宽度 W |
数字输入 600 | 600 |
高度 H |
文本 #YG_HBL |
18(公式已算) |
实际深 CPK |
文本 #D |
400 |
板件正面朝向 CX |
下拉「上」 | 上 0 |
厚 YG_HBL |
下拉「18」 | 18 |
左栏下拉浮层(
.tui-select-dropdown)内部同样不显示提示。
交互细节