nankai-cms-admin/src/components/cms/category/OperaCategoryWindow.vue
2025-03-13 09:50:20 +08:00

311 lines
8.5 KiB
Vue

<!-- 获取验证字段 -->
<template>
<GlobalWindow
:title="title"
v-model:visible="visible"
:confirm-working="isWorking"
width="750px"
@confirm="confirm"
>
<el-form :model="form" ref="form" :rules="rules">
<el-form-item label="上级栏目" prop="parentId">
<CategorySelect v-model="form.parentId" :multiple="false" :clearable="true"/>
</el-form-item>
<el-form-item label="栏目标题" prop="title" required>
<el-input
v-model="form.title"
placeholder="请输入栏目标题"
v-trim
maxlength="200"
@input="paddingUid"
/>
</el-form-item>
<el-form-item label="栏目图标" prop="icon">
<IconSelect v-if="visible" v-model="form.icon"/>
</el-form-item>
<el-form-item label="唯一标识" prop="uid" required>
<el-input
v-model="form.uid"
placeholder="请输入唯一标识"
v-trim
maxlength="50"
/>
</el-form-item>
<el-form-item label="类型" prop="type" required>
<DictRadioGroup code="CATEGORY_TYPES" v-model="form.type" @change="handleTypeChange"/>
</el-form-item>
<el-form-item
v-if="form.type === $const.CATEGORY_TYPE.IN_LINK || form.type === $const.CATEGORY_TYPE.OUT_LINK"
label="链接地址"
prop="uri"
required
>
<el-input
v-model="form.uri"
placeholder="请输入链接地址"
v-trim
maxlength="200"
/>
</el-form-item>
<el-form-item
v-if="visible && form.type === $const.CATEGORY_TYPE.DEFAULT"
label="模板"
prop="templateId"
>
<TemplateSelect
ref="templateSelect"
v-model="form.templateId"
v-model:parameters="form.templateParameters"
/>
</el-form-item>
<el-form-item label="状态" prop="hidden" required>
<el-switch
v-model="form.hidden"
active-text="显示"
:active-value="false"
inactive-text="隐藏"
:inactive-value="true"
/>
</el-form-item>
<el-form-item label="排序" prop="sort" required>
<el-input-number
v-model="form.sort"
placeholder="请输入排序"
:controls="false"
:min="1"
v-trim
maxlength="200"
/>
</el-form-item>
<el-form-item v-if="form.type === $const.CATEGORY_TYPE.DEFAULT" label="权限码" prop="permission">
<el-input
v-model="form.permission"
placeholder="请输入权限码"
v-trim
maxlength="50"
/>
</el-form-item>
<el-form-item label="栏目配置" prop="config">
<el-input
type="textarea"
:rows="10"
v-model="form.config"
placeholder="请输入栏目配置"
v-trim
show-word-limit
maxlength="2000"
/>
<FormItemTip>栏目配置用于对栏目做进一步自定义设置,无需配置可不填写。</FormItemTip>
</el-form-item>
</el-form>
</GlobalWindow>
</template>
<script>
import BaseOpera from '@/components/base/BaseOpera'
import GlobalWindow from '@/components/common/GlobalWindow'
import CategorySelect from '@/components/cms/category/CategorySelect'
import TemplateSelect from '@/components/cms/template/TemplateSelect'
import IconSelect from '@/components/system/icon/IconSelect'
import { pinyin } from 'pinyin-pro'
import { checkUrl, checkRelativeUrl } from '@/core/utils/form'
export default {
name: 'OperaCategoryWindow',
extends: BaseOpera,
components: {
IconSelect,
TemplateSelect,
CategorySelect,
GlobalWindow
},
data () {
const _this = this
return {
// 父栏目
parent: null,
// 原唯一标识
originUid: null,
// 表单数据
form: {
id: null,
parentId: null,
uid: '',
title: '',
type: 'DEFAULT',
uri: '',
icon: '',
permission: '',
templateId: null,
templateParameters: null,
hidden: false,
sort: 1,
config: ''
},
// 验证规则
rules: {
title: [
{ required: true, message: '请输入栏目标题' }
],
uid: [
{ required: true, message: '请输入唯一标识' }
],
type: [
{ required: true, message: '请输入类型' }
],
uri: [
{ required: true, message: '请输入链接地址' },
{ validator: _this.checkLink }
],
sort: [
{ required: true, message: '请输入排序' }
]
}
}
},
methods: {
/**
* 打开窗口
*
* @param title 窗口标题
* @param target 行对象(仅编辑需该参数)
* @param parent 父栏目
*/
open (title, target, parent) {
this.title = title
this.parent = parent
this.visible = true
// 新建
if (target == null) {
this.$nextTick(() => {
this.$refs.form.resetFields()
this.form[this.configData['field.id']] = null
this.form.parentId = parent == null ? null : parent.id
this.form.templateId = null
this.form.templateParameters = null
})
return
}
// 编辑
this.$nextTick(() => {
for (const key in this.form) {
this.form[key] = target[key]
}
// 拷贝原始唯一标识
this.originUid = this.form.uid
// 初始化数据参数
this.form.templateParameters = target.templateParameters == null || target.templateParameters === '' ?
[] : JSON.parse(this.form.templateParameters)
})
},
/**
* 确认(点击确认按钮后触发)
*/
confirm () {
if (this.form[this.configData['field.id']] == null || this.form[this.configData['field.id']] === '') {
this.__confirmCreate()
return
}
if (this.form.uid === this.originUid) {
this.__confirmEdit()
return
}
// 修改了唯一标识
this.$dialog.confirm('唯一标识可能会在源码中使用,修改后需及时修改源码,确认修改吗?如不确定,请咨询超级管理员!', '提示', {
confirmButtonText: '确认修改',
confirmButtonClass: 'el-button--danger',
cancelButtonText: '取消',
type: 'warning'
}).then(() => {
this.__confirmEdit()
}).catch(() => {})
},
// 切换类型
handleTypeChange () {
if (this.form.type === this.$const.CATEGORY_TYPE.DEFAULT) {
this.form.uri = ''
}
if (this.form.type === this.$const.CATEGORY_TYPE.IN_LINK || this.form.type === this.$const.CATEGORY_TYPE.OUT_LINK) {
this.form.templateId = null
this.form.templateParameters = null
}
},
/**
* 补充uid
*
* @param name 栏目名称
*/
paddingUid (name) {
// 编辑时不补充
if (this.form.id != null) {
return
}
this.form.uid = pinyin(name, {
toneType: 'none',
type: 'array'
}).map(item => item.substring(0,1)).join('')
},
// 验证链接地址
checkLink (rule, value, callback) {
if (this.form.type === this.$const.CATEGORY_TYPE.IN_LINK) {
checkRelativeUrl(rule, value, callback)
} else {
checkUrl(rule, value, callback)
}
},
/**
* 获取新增编辑表单对象
*
* @returns {*}
* @private
*/
__getForm () {
const form = JSON.parse(JSON.stringify(this.form))
// 将模板参数转为JSON字符串
if (form.templateParameters != null) {
form.templateParameters = JSON.stringify(form.templateParameters)
}
return form
},
/**
* 验证表单
*
* @param callback 验证回调
* @private
*/
__validateForm (callback) {
this.$refs.form.validate((valid) => {
if (!valid) {
callback(valid)
return
}
if (!this.$refs.templateSelect) {
callback(valid)
return
}
this.$refs.templateSelect.validateForm()
.then(() => {
callback(true)
})
.catch(() => {
callback(false)
})
})
}
},
async created () {
this.config({
api: await import('@/api/cms/category'),
'field.id': 'id'
})
}
}
</script>
<style scoped lang="scss">
:deep(.el-input-number) {
.el-input__inner {
text-align: left;
}
}
</style>