Compare commits

..
2 Commits
Author SHA1 Message Date
wc24 3b0887b126 fix(edit): 清空字段能真正提交(undefined→null,避免 JSON 丢键)
清空 relation/select 时 el-* 常 emit undefined,进 submitData 后 JSON.stringify 丢键 →
后端收不到、看似'提交无效'。修:
- handleSave 编辑 diff 把值归一成 null(??null),清空 → null → 提交 → 后端置空
- FieldRelation 清空归一成 null(单)/[](多),避免 ObjectId 存 '' cast 报错
2026-06-29 21:17:38 +08:00
wc24 bba08dadcc feat(fields): 可选字段(非 required)编辑态可清空,统一 :clearable=!required
之前 Select/Relation 编辑态根本没 clearable(可选也删不掉),String/Textarea/Date 又恒清。
现统一 String/Textarea/Select/Relation/Date 的 edit 控件 clearable=!required:可选给清空、必填不给。
Relation 清空归一成 null(el-select 单选清空发 '',ObjectId 存 '' 会 cast 报错)。
已知例外:Number 用 el-input-number 无 clearable 属性,只能手动清空输入框、无按钮。
2026-06-29 21:11:58 +08:00
7 changed files with 17 additions and 8 deletions
+1 -1
View File
@@ -1,6 +1,6 @@
{
"name": "shrimp-admin",
"version": "0.3.6",
"version": "0.3.8",
"private": true,
"description": "Shrimp 框架前端 — 消费 ShrimpServer + ShrimpTable 契约的经典 Vue3 + Element Plus 实现",
"main": "src/index.ts",
+4 -2
View File
@@ -334,8 +334,10 @@ async function handleSave() {
formFields.value.forEach(field => {
if (field.editable === 'readonly') return
if (field.editable === 'addOnly') return
const newValue = formData.value[field.key]
const oldValue = originalData.value[field.key]
// 清空字段值为 undefined 时,JSON.stringify 会丢键 → 后端收不到、看似"提交无效"。
// 归一成 null:既保证清空能提交(后端置空),又让"两边都空"不误判为有改动。
const newValue = formData.value[field.key] ?? null
const oldValue = originalData.value[field.key] ?? null
if (newValue === oldValue) return
submitData[field.key] = newValue
})
+1 -1
View File
@@ -42,7 +42,7 @@
style="width: 100%"
/>
<el-date-picker v-else :model-value="modelValue" @update:model-value="$emit('update:modelValue', $event)" :disabled="disabled"
type="datetime" style="width: 100%" />
type="datetime" :clearable="!field.required" style="width: 100%" />
</template>
<script lang="ts" setup>
+8 -2
View File
@@ -18,7 +18,7 @@
>
<el-option v-for="opt in options" :key="opt.value" :label="opt.label" :value="opt.value" />
</el-select>
<el-select v-else :model-value="stringValue" @update:model-value="$emit('update:modelValue', $event)" :disabled="disabled" :multiple="field.multiple" filterable remote :remote-method="onSearch" :loading="loading" style="width: 100%">
<el-select v-else :model-value="stringValue" @update:model-value="onEdit" :disabled="disabled" :multiple="field.multiple" :clearable="!field.required" filterable remote :remote-method="onSearch" :loading="loading" style="width: 100%">
<el-option v-for="opt in options" :key="opt.value" :label="opt.label" :value="opt.value" />
</el-select>
</template>
@@ -35,10 +35,16 @@ const props = defineProps<{
disabled?: boolean
}>()
defineEmits<{
const emit = defineEmits<{
'update:modelValue': [value: any]
}>()
// 编辑态清空:el-select 单选清空发 '' 或 undefined,relation 是 ObjectId、且 undefined 会被
// JSON.stringify 丢键 → 都归一成 null(取消关联)。多选清空是 [],原样。
function onEdit(v: any) {
emit('update:modelValue', v === '' || v == null ? (props.field.multiple ? [] : null) : v)
}
const options = ref<{ label: string; value: string }[]>([])
const loading = ref(false)
+1
View File
@@ -21,6 +21,7 @@
@update:model-value="$emit('update:modelValue', $event)"
:disabled="disabled"
:multiple="field.multiple"
:clearable="!field.required"
style="width: 100%"
>
<el-option v-for="opt in resolvedOptions" :key="opt.value" :label="vueAdmin.t(opt.label)" :value="opt.value" />
+1 -1
View File
@@ -9,7 +9,7 @@
</el-tag>
<el-input v-model="inputValue" @keyup.enter="addTag" @blur="addTag" :placeholder="$t('base.pressEnter')" />
</div>
<el-input v-else :model-value="modelValue" @update:model-value="$emit('update:modelValue', $event)" :disabled="disabled" clearable />
<el-input v-else :model-value="modelValue" @update:model-value="$emit('update:modelValue', $event)" :disabled="disabled" :clearable="!field.required" />
</template>
<script lang="ts" setup>
+1 -1
View File
@@ -19,7 +19,7 @@
:model-value="modelValue"
@update:model-value="$emit('update:modelValue', $event)"
:disabled="disabled"
clearable
:clearable="!field.required"
/>
</template>