| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272 |
- <template>
- <el-dialog
- :title="dialogTitle"
- v-model="innerVisible"
- width="640px"
- :close-on-click-modal="false"
- @close="handleCancel"
- >
- <el-form
- ref="form"
- :model="form"
- label-width="140px"
- label-position="right"
- >
- <el-form-item label="元标签规则" required>
- <el-select
- v-model="form.metaCode"
- placeholder="请选择"
- :disabled="readonly"
- style="width: 100%"
- @change="handleMetaChange"
- >
- <el-option
- v-for="meta in metaRules"
- :key="meta.code"
- :label="`${meta.code}-${meta.name}`"
- :value="meta.code"
- />
- </el-select>
- </el-form-item>
- <template v-if="currentMeta">
- <el-divider />
- <el-form-item label="规则名称">
- <el-input
- v-model="form.ruleName"
- :disabled="readonly"
- placeholder="便于识别该规则用途"
- maxlength="40"
- show-word-limit
- style="width: 100%"
- />
- </el-form-item>
- <el-form-item
- v-for="field in currentMeta.fields"
- :key="field.key"
- :label="field.label"
- :required="field.required"
- >
- <!-- 单选 -->
- <el-select
- v-if="field.type === 'select'"
- v-model="form.config[field.key]"
- :disabled="readonly"
- placeholder="请选择"
- clearable
- style="width: 100%"
- >
- <el-option
- v-for="opt in field.options"
- :key="String(opt.value)"
- :label="opt.label"
- :value="opt.value"
- />
- </el-select>
- <!-- 多选 -->
- <el-select
- v-else-if="field.type === 'multiSelect'"
- v-model="form.config[field.key]"
- :disabled="readonly"
- multiple
- collapse-tags
- placeholder="请选择"
- clearable
- style="width: 100%"
- >
- <el-option
- v-for="opt in field.options"
- :key="String(opt.value)"
- :label="opt.label"
- :value="opt.value"
- />
- </el-select>
- <!-- 日期 -->
- <el-date-picker
- v-else-if="field.type === 'datePicker'"
- v-model="form.config[field.key]"
- :disabled="readonly"
- type="date"
- placeholder="请选择日期"
- value-format="yyyy-MM-dd"
- style="width: 100%"
- />
- <!-- 月份 -->
- <el-date-picker
- v-else-if="field.type === 'monthPicker'"
- v-model="form.config[field.key]"
- :disabled="readonly"
- type="month"
- placeholder="请选择日期"
- value-format="yyyy-MM"
- style="width: 100%"
- />
- <!-- 数字 -->
- <el-input
- v-else-if="field.type === 'number'"
- v-model.number="form.config[field.key]"
- :disabled="readonly"
- type="number"
- :min="field.min"
- :max="field.max"
- placeholder="请输入"
- style="width: 100%"
- />
- <!-- 连续达标月数 / 时间范围 -->
- <div v-else-if="field.type === 'nm'" class="nm-input">
- <el-input
- v-model.number="form.config[field.key].n"
- :disabled="readonly"
- type="number"
- :min="1"
- style="width: 90px"
- />
- <span class="nm-sep">/</span>
- <el-input
- v-model.number="form.config[field.key].m"
- :disabled="readonly"
- type="number"
- :min="1"
- style="width: 90px"
- />
- </div>
- <!-- 文本 -->
- <el-input
- v-else
- v-model="form.config[field.key]"
- :disabled="readonly"
- placeholder="请输入"
- style="width: 100%"
- />
- </el-form-item>
- </template>
- </el-form>
- <template #footer>
- <div class="dialog-footer">
- <el-button @click="handleCancel">取 消</el-button>
- <el-button v-if="!readonly" type="primary" @click="handleSave">保 存</el-button>
- </div>
- </template>
- </el-dialog>
- </template>
- <script>
- import { ElMessage } from 'element-plus'
- import { META_RULES, getMetaRule } from '@/config/metaRules'
- const emptyForm = () => ({
- id: '',
- metaCode: '',
- ruleName: '',
- config: {}
- })
- export default {
- name: 'RuleEditDialog',
- props: {
- modelValue: { type: Boolean, default: false },
- rule: { type: Object, default: null },
- mode: { type: String, default: 'add' } // add | edit | view
- },
- emits: ['update:modelValue', 'save', 'cancel'],
- data() {
- return {
- form: emptyForm(),
- metaRules: META_RULES
- }
- },
- computed: {
- innerVisible: {
- get() { return this.modelValue },
- set(v) { this.$emit('update:modelValue', v) }
- },
- dialogTitle() {
- if (this.mode === 'edit') return '编辑规则信息'
- if (this.mode === 'view') return '查看规则信息'
- return '新增规则信息'
- },
- readonly() {
- return this.mode === 'view'
- },
- currentMeta() {
- return this.form.metaCode ? getMetaRule(this.form.metaCode) : null
- }
- },
- watch: {
- modelValue(v) {
- if (v) this.initForm()
- }
- },
- methods: {
- initForm() {
- if (this.rule) {
- this.form = {
- id: this.rule.id,
- metaCode: this.rule.metaCode,
- ruleName: this.rule.ruleName || '',
- config: JSON.parse(JSON.stringify(this.rule.config || {}))
- }
- } else {
- this.form = emptyForm()
- }
- },
- handleMetaChange(code) {
- const meta = getMetaRule(code)
- const config = {}
- if (meta) {
- meta.fields.forEach((f) => {
- if (f.type === 'multiSelect') config[f.key] = []
- else if (f.type === 'nm') config[f.key] = f.defaultValue ? { ...f.defaultValue } : { n: 3, m: 6 }
- else config[f.key] = ''
- })
- }
- this.form.config = config
- if (!this.form.ruleName && meta) {
- this.form.ruleName = meta.name
- }
- },
- validateConfig() {
- if (!this.form.metaCode) {
- ElMessage.error('请选择元标签规则')
- return false
- }
- const meta = this.currentMeta
- if (!meta) return false
- for (const f of meta.fields) {
- if (!f.required) continue
- const v = this.form.config[f.key]
- const empty = v === '' || v === null || v === undefined ||
- (Array.isArray(v) && v.length === 0)
- if (empty) {
- ElMessage.error(`请填写「${f.label}」`)
- return false
- }
- }
- return true
- },
- handleSave() {
- if (!this.validateConfig()) return
- this.$emit('save', {
- id: this.form.id || `r_${Date.now()}_${Math.random().toString(36).slice(2, 6)}`,
- metaCode: this.form.metaCode,
- ruleName: this.form.ruleName || this.currentMeta.name,
- config: JSON.parse(JSON.stringify(this.form.config))
- })
- this.innerVisible = false
- },
- handleCancel() {
- this.innerVisible = false
- this.$emit('cancel')
- }
- }
- }
- </script>
- <style scoped>
- .nm-input { display: flex; align-items: center; }
- .nm-sep { margin: 0 12px; color: #303133; font-size: 16px; }
- .dialog-footer { text-align: center; }
- </style>
|