Files
webman-buildadmin-mall/web/src/views/backend/channel/manage/popupForm.vue

155 lines
6.6 KiB
Vue
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
<template>
<!-- 对话框表单 -->
<!-- 建议使用 Prettier 格式化代码 -->
<!-- el-form 内可以混用 el-form-itemFormItemba-input 等输入组件 -->
<el-dialog
class="ba-operate-dialog"
:close-on-click-modal="false"
:model-value="['Add', 'Edit'].includes(baTable.form.operate!)"
@close="baTable.toggleForm"
>
<template #header>
<div class="title" v-drag="['.ba-operate-dialog', '.el-dialog__header']" v-zoom="'.ba-operate-dialog'">
{{ baTable.form.operate ? t(baTable.form.operate) : '' }}
</div>
</template>
<el-scrollbar v-loading="baTable.form.loading" class="ba-table-form-scrollbar">
<div
class="ba-operate-form"
:class="'ba-' + baTable.form.operate + '-form'"
:style="config.layout.shrink ? '' : 'width: calc(100% - ' + baTable.form.labelWidth! / 2 + 'px)'"
>
<el-form
v-if="!baTable.form.loading"
ref="formRef"
@submit.prevent=""
@keyup.enter="baTable.onSubmit(formRef)"
:model="baTable.form.items"
:label-position="config.layout.shrink ? 'top' : 'right'"
:label-width="baTable.form.labelWidth + 'px'"
:rules="rules"
>
<FormItem
:label="t('channel.manage.name')"
type="string"
v-model="baTable.form.items!.name"
prop="name"
:placeholder="t('Please input field', { field: t('channel.manage.name') })"
/>
<el-form-item :label="t('channel.manage.ip_white')" prop="ip_white">
<div class="ba-ip-white-list">
<div class="ba-ip-white-item" v-for="(ip, idx) in ipWhiteList" :key="idx">
<el-input v-model="ipWhiteList[idx]" :placeholder="t('channel.manage.ip_placeholder')" clearable />
<el-button @click="onDelIpWhite(idx)" size="small" icon="el-icon-Delete" circle />
</div>
<el-button v-blur class="ba-add-ip-white" @click="onAddIpWhite" icon="el-icon-Plus">{{ t('Add') }}</el-button>
</div>
</el-form-item>
<FormItem
:label="t('channel.manage.title')"
type="string"
v-model="baTable.form.items!.title"
prop="title"
:placeholder="t('Please input field', { field: t('channel.manage.title') })"
/>
<FormItem
:label="t('channel.manage.remark')"
type="textarea"
v-model="baTable.form.items!.remark"
prop="remark"
:input-attr="{ rows: 3 }"
@keyup.enter.stop=""
@keyup.ctrl.enter="baTable.onSubmit(formRef)"
:placeholder="t('Please input field', { field: t('channel.manage.remark') })"
/>
<FormItem
:label="t('channel.manage.admin_id')"
type="remoteSelect"
v-model="baTable.form.items!.admin_id"
prop="admin_id"
:input-attr="{ pk: 'admin.id', field: 'username', remoteUrl: '/admin/auth.Admin/index' }"
:placeholder="t('Please select field', { field: t('channel.manage.admin_id') })"
/>
</el-form>
</div>
</el-scrollbar>
<template #footer>
<div :style="'width: calc(100% - ' + baTable.form.labelWidth! / 1.8 + 'px)'">
<el-button @click="baTable.toggleForm()">{{ t('Cancel') }}</el-button>
<el-button v-blur :loading="baTable.form.submitLoading" @click="baTable.onSubmit(formRef)" type="primary">
{{ baTable.form.operateIds && baTable.form.operateIds.length > 1 ? t('Save and edit next item') : t('Save') }}
</el-button>
</div>
</template>
</el-dialog>
</template>
<script setup lang="ts">
import type { FormItemRule } from 'element-plus'
import { inject, reactive, ref, useTemplateRef, watch } from 'vue'
import { useI18n } from 'vue-i18n'
import FormItem from '/@/components/formItem/index.vue'
import { useConfig } from '/@/stores/config'
import type baTableClass from '/@/utils/baTable'
import { buildValidatorData } from '/@/utils/validate'
const config = useConfig()
const formRef = useTemplateRef('formRef')
const baTable = inject('baTable') as baTableClass
const { t } = useI18n()
/** 将后端数据转为 IP 字符串数组(兼容旧格式 [{key,value}] 和新格式 [ip] */
function normalizeIpWhite(val: unknown): string[] {
if (!val || !Array.isArray(val)) return []
return val.map((item) => (typeof item === 'string' ? item : (item?.value ?? '')))
}
const ipWhiteList = ref<string[]>([])
// 仅当表单加载时从 form.items 同步到 ipWhiteList避免双向 watch 导致循环更新
watch(
() => baTable.form.items?.ip_white,
(val) => {
ipWhiteList.value = normalizeIpWhite(val)
},
{ immediate: true }
)
const onAddIpWhite = () => {
ipWhiteList.value.push('')
}
const onDelIpWhite = (idx: number) => {
ipWhiteList.value.splice(idx, 1)
}
// 将 ipWhiteList 暴露给 baTable供提交时同步
if (!baTable.form.extend) baTable.form.extend = {}
baTable.form.extend.ipWhiteListRef = ipWhiteList
const rules: Partial<Record<string, FormItemRule[]>> = reactive({
name: [buildValidatorData({ name: 'required', title: t('channel.manage.name') })],
title: [buildValidatorData({ name: 'required', title: t('channel.manage.title') })],
admin_id: [buildValidatorData({ name: 'required', title: t('channel.manage.admin_id') })],
create_time: [buildValidatorData({ name: 'date', title: t('channel.manage.create_time') })],
update_time: [buildValidatorData({ name: 'date', title: t('channel.manage.update_time') })],
})
</script>
<style scoped lang="scss">
.ba-ip-white-list {
.ba-ip-white-item {
display: flex;
align-items: center;
gap: 8px;
margin-bottom: 8px;
.el-input {
flex: 1;
}
}
.ba-add-ip-white {
margin-top: 4px;
}
}
</style>