chore: establish V1.1 recovery baseline

This commit is contained in:
2026-09-09 22:05:00 +08:00
commit b46b48eb33
947 changed files with 155471 additions and 0 deletions
+45
View File
@@ -0,0 +1,45 @@
/**
* Textarea 多行输入(规范 §18, §35:自我介绍 20~500 字)
*
* 内置字数计数 + 字数下限/上限提示 + 错误态。
* 用法:
* <ui-textarea label="自我介绍" value="{{intro}}" minlength="20" maxlength="500"
* placeholder="简单介绍一下你自己…" error="{{errors.intro}}"
* bind:input="onIntroInput" />
*/
Component({
options: { addGlobalClass: true },
properties: {
label: { type: String, value: '' },
placeholder: { type: String, value: '' },
value: { type: String, value: '' },
minlength: { type: Number, value: 0 },
maxlength: { type: Number, value: 500 },
showCount: { type: Boolean, value: true },
error: { type: String, value: '' },
disabled: { type: Boolean, value: false },
autoHeight: { type: Boolean, value: true },
rows: { type: Number, value: 3 },
},
data: {
currentLen: 0,
},
observers: {
value(val) {
this.setData({ currentLen: (val || '').length });
},
},
methods: {
onInput(e) {
const val = e.detail.value;
this.setData({ currentLen: (val || '').length });
this.triggerEvent('input', { value: val });
},
onFocus(e) {
this.triggerEvent('focus', e.detail);
},
onBlur(e) {
this.triggerEvent('blur', { value: e.detail.value });
},
},
});
+4
View File
@@ -0,0 +1,4 @@
{
"component": true,
"usingComponents": {}
}
+27
View File
@@ -0,0 +1,27 @@
<view class="ui-textarea {{error ? 'ui-textarea--error' : ''}} {{disabled ? 'ui-textarea--disabled' : ''}}">
<view wx:if="{{label}}" class="ui-textarea__label">{{label}}</view>
<view class="ui-textarea__field-wrap">
<textarea
class="ui-textarea__field"
value="{{value}}"
placeholder="{{placeholder}}"
placeholder-class="ui-textarea__placeholder"
maxlength="{{maxlength}}"
disabled="{{disabled}}"
auto-height="{{autoHeight}}"
style="min-height: {{rows * 48}}rpx;"
bindinput="onInput"
bindfocus="onFocus"
bindblur="onBlur"
/>
</view>
<view class="ui-textarea__footer">
<view wx:if="{{error}}" class="ui-textarea__error">{{error}}</view>
<view wx:elif="{{minlength > 0 && currentLen < minlength}}" class="ui-textarea__hint">
至少还需 {{minlength - currentLen}} 字
</view>
<view wx:if="{{showCount}}" class="ui-textarea__count">
{{currentLen}}/{{maxlength}}
</view>
</view>
</view>
+56
View File
@@ -0,0 +1,56 @@
.ui-textarea {
padding: var(--spacing-3) 0;
border-bottom: 1rpx solid var(--color-border);
}
.ui-textarea__label {
font-size: var(--font-size-sm);
color: var(--color-text-tertiary);
margin-bottom: var(--spacing-2);
}
.ui-textarea__field-wrap {
background: var(--color-bg-card);
border-radius: var(--radius-md);
padding: var(--spacing-2) var(--spacing-3);
border: 1rpx solid var(--color-border);
}
.ui-textarea__field {
width: 100%;
font-size: var(--font-size-base);
color: var(--color-text-primary);
line-height: var(--line-height-normal);
min-height: 144rpx;
}
.ui-textarea__placeholder {
color: var(--color-text-placeholder);
}
.ui-textarea__footer {
display: flex;
justify-content: space-between;
align-items: flex-start;
margin-top: var(--spacing-1);
min-height: 28rpx;
}
.ui-textarea__error {
color: var(--color-danger);
font-size: var(--font-size-xs);
flex: 1;
}
.ui-textarea__hint {
color: var(--color-warning);
font-size: var(--font-size-xs);
flex: 1;
}
.ui-textarea__count {
color: var(--color-text-tertiary);
font-size: var(--font-size-xs);
margin-left: var(--spacing-2);
}
.ui-textarea--error .ui-textarea__field-wrap {
border-color: var(--color-border-error);
}
.ui-textarea--disabled .ui-textarea__field {
color: var(--color-text-disabled);
}
.ui-textarea--disabled .ui-textarea__field-wrap {
background: var(--color-bg-disabled);
}