refactor(components): 统一多端textarea配置与高度计算逻辑
1. 对齐ns-form和ns-newform的textarea配置参数,新增textareaRows和textareaLineHeight配置 2. 移除平台分支判断,所有平台统一使用:rows+行高计算高度的方案 3. 适配鸿蒙ArkUI原生TextArea,通过:rows控制行数,JS动态计算高度 4. 移除textarea硬编码高度,改为通过formConfig动态控制
This commit is contained in:
@@ -209,6 +209,10 @@ export default {
|
||||
// 占位符:遗漏会被 ns-newform SCSS 默认值回退覆盖
|
||||
placeholderColor: pick('placeholderColor', 'placeholder_color'),
|
||||
placeholderFontSize: pick('placeholderFontSize', 'placeholder_font_size'),
|
||||
// textarea 显示行数 / 行高(透传给 ns-newform,与 ns-form 保持一致)
|
||||
// 不传时 ns-newform 走自己的默认 4 行 / 44rpx
|
||||
textareaRows: pick('textareaRows', 'textarea_rows'),
|
||||
textareaLineHeight: pick('textareaLineHeight', 'textarea_line_height'),
|
||||
// 输入框视觉增强(与 ns-newform 对齐)
|
||||
inputBorderColor: pick('inputBorderColor', 'input_border_color'),
|
||||
inputBgColor: pick('inputBgColor', 'input_bg_color'),
|
||||
|
||||
@@ -26,29 +26,17 @@
|
||||
<text class="required" :style="{ color: requiredColor }">{{ item.value.required ? '*' : '' }}</text>
|
||||
</view>
|
||||
<view class="box">
|
||||
<!-- #ifdef MP-HARMONY -->
|
||||
<!-- 鸿蒙元服务渲染为原生 ArkUI TextArea,必须用 :rows 控制初始显示行数;CSS height 在原生组件上不生效 -->
|
||||
<!-- 所有平台统一通过 formConfig.textareaRows / item.value.rows 控制显示行数:
|
||||
- H5 / 微信:原生 textarea 识别 :rows 属性,可视高度 = rows × line-height(CSS 控制 line-height);
|
||||
- 鸿蒙:渲染为原生 ArkUI TextArea,CSS height 不生效,必须靠 :rows 控制。
|
||||
行数和行高全部由 formConfig 动态下发,不再硬编码 176rpx / row=2。 -->
|
||||
<textarea
|
||||
:rows="item.value.rows || 2"
|
||||
:placeholder="item.value.placeholder"
|
||||
placeholder-class="placeholder color-tip"
|
||||
v-model="item.val"
|
||||
:style="inputStyle"
|
||||
></textarea>
|
||||
<!-- #endif -->
|
||||
<!-- #ifdef MP-WEIXIN || H5 -->
|
||||
<!-- 微信小程序原生 textarea:
|
||||
不用 auto-height(会随内容无限扩展遮挡后续组件),改用 textareaStyle 中
|
||||
固定 height 176rpx(约 4 行)+ line-height 44rpx,可视区域比原 88rpx 翻倍,
|
||||
内容多时内部滚动条 thumb 比例改善一倍,且高度可控。 -->
|
||||
<textarea
|
||||
:rows="item.value.rows || 2"
|
||||
:rows="item.value.rows || textareaRowsValue"
|
||||
:placeholder="item.value.placeholder"
|
||||
placeholder-class="placeholder color-tip"
|
||||
v-model="item.val"
|
||||
:style="textareaStyle"
|
||||
></textarea>
|
||||
<!-- #endif -->
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
@@ -292,6 +280,11 @@
|
||||
checkedColor: '#ff4544',
|
||||
placeholderColor: '#909399',
|
||||
placeholderFontSize: 28,
|
||||
// textarea 显示行数 / 行高(与 ns-newform 对齐)
|
||||
// 改用 :rows + line-height 驱动高度:rows 给原生 <textarea>(H5/微信原生层/鸿蒙 ArkUI 都识别),
|
||||
// line-height 用于在 textareaStyle 里算出对应的 px 高度;不再写死 176rpx。
|
||||
textareaRows: 4,
|
||||
textareaLineHeight: 44,
|
||||
// 输入框视觉增强(与 ns-newform 对齐)
|
||||
inputBorderColor: '#e5e7eb',
|
||||
inputBgColor: '#f9fafb',
|
||||
@@ -325,6 +318,8 @@
|
||||
checkedColor: pick('checkedColor', 'checked_color'),
|
||||
placeholderColor: pick('placeholderColor', 'placeholder_color'),
|
||||
placeholderFontSize: pick('placeholderFontSize', 'placeholder_font_size'),
|
||||
textareaRows: pick('textareaRows', 'textarea_rows'),
|
||||
textareaLineHeight: pick('textareaLineHeight', 'textarea_line_height'),
|
||||
inputBorderColor: pick('inputBorderColor', 'input_border_color'),
|
||||
inputBgColor: pick('inputBgColor', 'input_bg_color'),
|
||||
inputFocusBorderColor: pick('inputFocusBorderColor', 'input_focus_border_color'),
|
||||
@@ -385,6 +380,8 @@
|
||||
'--checked-color': cfg.checkedColor,
|
||||
'--placeholder-color': cfg.placeholderColor,
|
||||
'--placeholder-font-size': this.$util.rpx(num(cfg.placeholderFontSize, 28)),
|
||||
'--textarea-rows': num(cfg.textareaRows, 4),
|
||||
'--textarea-line-height': this.$util.rpx(num(cfg.textareaLineHeight, 44)),
|
||||
// 输入框视觉增强(与 ns-newform 对齐)
|
||||
'--input-border-color': cfg.inputBorderColor,
|
||||
'--input-bg-color': cfg.inputBgColor,
|
||||
@@ -425,21 +422,37 @@
|
||||
'line-height': this.$util.rpx(this.config.inputHeight)
|
||||
});
|
||||
},
|
||||
// textarea 专用 inline style(仅微信小程序端使用,见 template 中 #ifdef MP-WEIXIN 分支)
|
||||
// textarea 显示行数(来自 formConfig.textareaRows,未配置时回退到默认 4)
|
||||
textareaRowsValue() {
|
||||
const n = parseInt(this.config.textareaRows, 10);
|
||||
return Number.isFinite(n) && n > 0 ? n : 4;
|
||||
},
|
||||
// textarea 行高(来自 formConfig.textareaLineHeight,用于 :rows × line-height 算出固定可视高度)
|
||||
textareaLineHeightValue() {
|
||||
const n = parseInt(this.config.textareaLineHeight, 10);
|
||||
return Number.isFinite(n) && n > 0 ? n : 44;
|
||||
},
|
||||
// textarea 专用 inline style(所有平台统一使用,见 template 中 textarea 节点)
|
||||
// 设计要点:
|
||||
// 1) 不复用 inputStyle 的 min-height / line-height:这两个值取自 inputHeight(默认 60rpx),
|
||||
// 对 textarea 太小,会让微信小程序原生 textarea 单行过高、可视区域过小,
|
||||
// 内容稍多即溢出导致原生滚动条 thumb 异常小;
|
||||
// 2) 不使用 auto-height:在微信小程序原生 textarea 上,auto-height 会让 textarea 随内容
|
||||
// 无限扩展,遮挡后续组件,导致"看不到下面的其他组件";
|
||||
// 3) 改用固定 height 176rpx(约 4 行,line-height 44rpx),相比原 CSS height: 88rpx(2 行)
|
||||
// 可视区域翻倍,内容多时内部滚动条 thumb 比例改善一倍,且高度可控不会遮挡后续组件。
|
||||
// 1) 不复用 inputStyle 的 min-height / line-height:那两个值取自 inputHeight(默认 60rpx),
|
||||
// 对 textarea 太小,会让原生 textarea 单行过高、可视区域过小;
|
||||
// 2) 不使用 auto-height:原生 textarea 上 auto-height 会让组件随内容无限扩展,
|
||||
// 遮挡后续组件,导致"看不到下面的其他组件";
|
||||
// 3) 高度 = rows × lineHeight(两个值都由 formConfig 动态下发,不再写死 176rpx):
|
||||
// - H5 浏览器 / 微信原生层:原生 <textarea> 同时识别 :rows 和 CSS line-height,
|
||||
// 高度由浏览器自然算出,与 :rows 完全一致;
|
||||
// - 鸿蒙 ArkUI:原生 TextArea 只识别 :rows,不识别 CSS height,所以我们在 JS 里
|
||||
// 显式算 height = rows × lineHeight 反向写出,保证三端可视高度像素级一致。
|
||||
textareaStyle() {
|
||||
const h = this.$util.rpx(176);
|
||||
const lh = this.$util.rpx(this.textareaLineHeightValue);
|
||||
const rows = this.textareaRowsValue;
|
||||
// 加上 padding(12rpx 上下) 和 border(1rpx 上下) 的占用,避免与 :rows 算出的高度不一致时被截断
|
||||
const paddings = this.$util.rpx(24) + this.$util.rpx(2);
|
||||
const h = (this.$util.rpx(this.textareaLineHeightValue * (rows - 1)) + lh) + paddings;
|
||||
return this.$util.objToStyle({
|
||||
'height': h,
|
||||
'min-height': h,
|
||||
'line-height': this.$util.rpx(44),
|
||||
'line-height': lh,
|
||||
'border-radius': this.$util.rpx(this.config.inputRadius),
|
||||
'font-size': this.$util.rpx(this.config.labelFontSize),
|
||||
'color': this.config.labelColor
|
||||
@@ -950,6 +963,9 @@
|
||||
--placeholder-font-size: 28rpx;
|
||||
--checked-color: #ff4544;
|
||||
--placeholder-color: #909399;
|
||||
// textarea 行数 / 行高(运行时被 formWrapStyle 注入的 inline 覆盖;这里是兜底)
|
||||
--textarea-rows: 4;
|
||||
--textarea-line-height: 44rpx;
|
||||
// 输入框视觉增强(与 ns-newform 对齐)
|
||||
--input-border-color: #e5e7eb;
|
||||
--input-bg-color: #f9fafb;
|
||||
@@ -1085,11 +1101,12 @@
|
||||
font-size: var(--label-font-size, $font-size-base);
|
||||
width: 100%;
|
||||
color: var(--label-color, #1f2937);
|
||||
// 鸿蒙元服务渲染为原生 ArkUI TextArea,不识别 CSS height,由 :rows 控制行数;
|
||||
// 这里给所有端都设一个最小高度基线,避免空内容时塌缩
|
||||
min-height: 88rpx;
|
||||
height: 88rpx;
|
||||
line-height: 44rpx;
|
||||
// 行高由 formConfig.textareaLineHeight(兜底 44rpx)控制;
|
||||
// 高度 = rows × line-height + padding + border,所有值都从 CSS 变量读取,
|
||||
// 真正做到了"rows 改 → 高度自动改"。
|
||||
line-height: var(--textarea-line-height, 44rpx);
|
||||
min-height: calc(var(--textarea-rows, 4) * var(--textarea-line-height, 44rpx) + 26rpx);
|
||||
height: calc(var(--textarea-rows, 4) * var(--textarea-line-height, 44rpx) + 26rpx);
|
||||
text-align: left;
|
||||
border-radius: var(--input-radius, 0rpx);
|
||||
box-sizing: border-box;
|
||||
|
||||
@@ -27,10 +27,16 @@
|
||||
<text class="required" :style="{ color: requiredColor }">{{ item.value.required ? '*' : '' }}</text>
|
||||
</view>
|
||||
<view :class="['box', 'align-left']" :style="item._boxAlignStyle">
|
||||
<!-- 所有平台统一通过 formConfig.textareaRows / item.value.rows 控制显示行数:
|
||||
- H5 / 微信:原生 textarea 识别 :rows 属性;
|
||||
- 鸿蒙:渲染为 ArkUI 原生 TextArea,CSS height 不生效,必须靠 :rows 控制。
|
||||
rows 全部由 formConfig 动态下发,与 ns-form 行为保持一致。 -->
|
||||
<textarea
|
||||
:rows="item.value.rows || textareaRowsValue"
|
||||
:placeholder="item.value.placeholder"
|
||||
placeholder-class="placeholder color-tip"
|
||||
v-model="item.val"
|
||||
:style="textareaStyle"
|
||||
></textarea>
|
||||
</view>
|
||||
</view>
|
||||
@@ -377,6 +383,10 @@ export default {
|
||||
checkedColor: '#ff4544',
|
||||
placeholderColor: '#ddd',
|
||||
placeholderFontSize: 28,
|
||||
// textarea 显示行数 / 行高(与 ns-form 保持一致,由 formConfig 覆盖)
|
||||
// 改用 :rows + line-height 驱动高度,rows 给原生 <textarea>,line-height 在 textareaStyle 算 px 高度
|
||||
textareaRows: 4,
|
||||
textareaLineHeight: 44,
|
||||
// 输入框视觉增强(可由后端 form_config 覆盖)
|
||||
inputBorderColor: '#e5e7eb',
|
||||
inputBgColor: '#f9fafb',
|
||||
@@ -452,6 +462,9 @@ export default {
|
||||
'--checked-color': cfg.checkedColor,
|
||||
'--placeholder-color': cfg.placeholderColor,
|
||||
'--placeholder-font-size': this.$util.rpx(num(cfg.placeholderFontSize, 28)),
|
||||
// textarea 行数 / 行高(CSS 兜底 + JS 算高度都用得到)
|
||||
'--textarea-rows': num(cfg.textareaRows, 4),
|
||||
'--textarea-line-height': this.$util.rpx(num(cfg.textareaLineHeight, 44)),
|
||||
// 输入框视觉增强(边框 / 背景 / 聚焦 / label 字重)
|
||||
'--input-border-color': cfg.inputBorderColor,
|
||||
'--input-bg-color': cfg.inputBgColor,
|
||||
@@ -497,6 +510,30 @@ export default {
|
||||
'border-radius': this.$util.rpx(this.config.inputRadius)
|
||||
});
|
||||
},
|
||||
// textarea 显示行数(来自 formConfig.textareaRows,未配置时回退到默认 4)
|
||||
textareaRowsValue() {
|
||||
const n = parseInt(this.config.textareaRows, 10);
|
||||
return Number.isFinite(n) && n > 0 ? n : 4;
|
||||
},
|
||||
// textarea 行高(来自 formConfig.textareaLineHeight,用于 :rows × line-height 算出可视高度)
|
||||
textareaLineHeightValue() {
|
||||
const n = parseInt(this.config.textareaLineHeight, 10);
|
||||
return Number.isFinite(n) && n > 0 ? n : 44;
|
||||
},
|
||||
// textarea 专用 inline style(所有平台统一使用,见 template 中 textarea 节点)
|
||||
// 高度 = rows × lineHeight + padding + border,由 formConfig 动态控制,与 ns-form 同公式
|
||||
textareaStyle() {
|
||||
const lh = this.$util.rpx(this.textareaLineHeightValue);
|
||||
const rows = this.textareaRowsValue;
|
||||
const paddings = this.$util.rpx(24) + this.$util.rpx(2); // padding 12rpx 上下 + border 1rpx 上下
|
||||
const h = (this.$util.rpx(this.textareaLineHeightValue * (rows - 1)) + lh) + paddings;
|
||||
return this.$util.objToStyle({
|
||||
'height': h,
|
||||
'min-height': h,
|
||||
'line-height': lh,
|
||||
'border-radius': this.$util.rpx(this.config.inputRadius)
|
||||
});
|
||||
},
|
||||
labelStyle() {
|
||||
const style = {
|
||||
fontSize: this.$util.rpx(this.config.labelFontSize),
|
||||
@@ -997,6 +1034,9 @@ export default {
|
||||
--submit-bg-color: #ff4544;
|
||||
--placeholder-color: #ddd;
|
||||
--placeholder-font-size: 28rpx;
|
||||
// textarea 行数 / 行高(运行时被 formWrapStyle 注入的 inline 覆盖;这里是兜底)
|
||||
--textarea-rows: 4;
|
||||
--textarea-line-height: 44rpx;
|
||||
// 输入框视觉增强(边框 / 背景 / 聚焦 / label 字重)
|
||||
--input-border-color: #e5e7eb;
|
||||
--input-bg-color: #f9fafb;
|
||||
@@ -1234,8 +1274,10 @@ export default {
|
||||
::v-deep textarea {
|
||||
font-size: var(--label-font-size, 28rpx);
|
||||
width: 100%;
|
||||
min-height: 120rpx;
|
||||
line-height: 1.5;
|
||||
// 行高 / 高度全部由 formConfig 动态决定(CSS 兜底公式与 JS textareaStyle 一致)
|
||||
line-height: var(--textarea-line-height, 44rpx);
|
||||
min-height: calc(var(--textarea-rows, 4) * var(--textarea-line-height, 44rpx) + 26rpx);
|
||||
height: calc(var(--textarea-rows, 4) * var(--textarea-line-height, 44rpx) + 26rpx);
|
||||
text-align: left;
|
||||
border: 1rpx solid var(--input-border-color, #e5e7eb);
|
||||
border-radius: var(--input-radius, 10rpx);
|
||||
@@ -1244,7 +1286,6 @@ export default {
|
||||
color: var(--label-color, #1f2937);
|
||||
transition: all 0.3s ease;
|
||||
box-sizing: border-box;
|
||||
height: auto;
|
||||
|
||||
&:focus {
|
||||
background: var(--input-focus-bg-color, #ffffff);
|
||||
@@ -1260,8 +1301,10 @@ export default {
|
||||
textarea {
|
||||
font-size: var(--label-font-size, 28rpx);
|
||||
width: 100%;
|
||||
min-height: 120rpx;
|
||||
line-height: 1.5;
|
||||
// 行高 / 高度全部由 formConfig 动态决定(与 ::v-deep textarea 同步)
|
||||
line-height: var(--textarea-line-height, 44rpx);
|
||||
min-height: calc(var(--textarea-rows, 4) * var(--textarea-line-height, 44rpx) + 26rpx);
|
||||
height: calc(var(--textarea-rows, 4) * var(--textarea-line-height, 44rpx) + 26rpx);
|
||||
text-align: left;
|
||||
border: 1rpx solid var(--input-border-color, #e5e7eb);
|
||||
border-radius: var(--input-radius, 10rpx);
|
||||
@@ -1270,7 +1313,6 @@ export default {
|
||||
color: var(--label-color, #1f2937);
|
||||
transition: all 0.3s ease;
|
||||
box-sizing: border-box;
|
||||
height: auto;
|
||||
|
||||
&:focus {
|
||||
background: var(--input-focus-bg-color, #ffffff);
|
||||
|
||||
Reference in New Issue
Block a user