新增:系统配置完善
parent
9568ac0e00
commit
03f51f3706
|
@ -283,26 +283,29 @@ class SystemConfig(CoreModel):
|
||||||
parent = models.ForeignKey(to='self', verbose_name='父级', on_delete=models.CASCADE,
|
parent = models.ForeignKey(to='self', verbose_name='父级', on_delete=models.CASCADE,
|
||||||
db_constraint=False, null=True, blank=True, help_text="父级")
|
db_constraint=False, null=True, blank=True, help_text="父级")
|
||||||
title = models.CharField(max_length=50, verbose_name="标题", help_text="标题")
|
title = models.CharField(max_length=50, verbose_name="标题", help_text="标题")
|
||||||
key = models.CharField(max_length=20, verbose_name="键", help_text="键")
|
key = models.CharField(max_length=20, verbose_name="键", help_text="键", db_index=True)
|
||||||
value = models.JSONField(max_length=100, verbose_name="值", help_text="值", null=True, blank=True)
|
value = models.JSONField(max_length=100, verbose_name="值", help_text="值", null=True, blank=True)
|
||||||
sort = models.IntegerField(default=0, verbose_name="排序", help_text="排序", blank=True)
|
sort = models.IntegerField(default=0, verbose_name="排序", help_text="排序", blank=True)
|
||||||
status = models.BooleanField(default=False, verbose_name="启用状态", help_text="启用状态")
|
status = models.BooleanField(default=False, verbose_name="启用状态", help_text="启用状态")
|
||||||
data_options = models.JSONField(verbose_name="数据options", help_text="数据options", null=True, blank=True)
|
data_options = models.JSONField(verbose_name="数据options", help_text="数据options", null=True, blank=True)
|
||||||
FORM_ITEM_TYPE_LIST = (
|
FORM_ITEM_TYPE_LIST = (
|
||||||
(0, 'text'),
|
(0, 'text'),
|
||||||
(1, 'textarea'),
|
(1, 'datetime'),
|
||||||
(2, 'number'),
|
(2, 'date'),
|
||||||
(3, 'select'),
|
(3, 'textarea'),
|
||||||
(4, 'radio'),
|
(4, 'select'),
|
||||||
(5, 'checkbox'),
|
(5, 'checkbox'),
|
||||||
(6, 'date'),
|
(6, 'radio'),
|
||||||
(7, 'datetime'),
|
(7, 'img'),
|
||||||
(8, 'time'),
|
(8, 'file'),
|
||||||
(9, 'imgs'),
|
(9, 'switch'),
|
||||||
(10, 'files'),
|
(10, 'number'),
|
||||||
(11, 'array'),
|
(11, 'array'),
|
||||||
(12, 'foreignkey'),
|
(12, 'imgs'),
|
||||||
(13, 'manytomany'),
|
(13, 'foreignkey'),
|
||||||
|
(14, 'manytomany'),
|
||||||
|
(15, 'time'),
|
||||||
|
|
||||||
)
|
)
|
||||||
form_item_type = models.IntegerField(choices=FORM_ITEM_TYPE_LIST, verbose_name="表单类型", help_text="表单类型", default=0,
|
form_item_type = models.IntegerField(choices=FORM_ITEM_TYPE_LIST, verbose_name="表单类型", help_text="表单类型", default=0,
|
||||||
blank=True)
|
blank=True)
|
||||||
|
@ -315,6 +318,7 @@ class SystemConfig(CoreModel):
|
||||||
verbose_name = '系统配置表'
|
verbose_name = '系统配置表'
|
||||||
verbose_name_plural = verbose_name
|
verbose_name_plural = verbose_name
|
||||||
ordering = ('sort',)
|
ordering = ('sort',)
|
||||||
|
unique_together = (("key", "parent_id"),)
|
||||||
|
|
||||||
def __str__(self):
|
def __str__(self):
|
||||||
return f"{self.title}"
|
return f"{self.title}"
|
||||||
|
|
|
@ -16,9 +16,16 @@
|
||||||
<el-form-item label="表单类型" prop="form_item_type">
|
<el-form-item label="表单类型" prop="form_item_type">
|
||||||
<el-select v-model="form.form_item_type" placeholder="请选择" clearable>
|
<el-select v-model="form.form_item_type" placeholder="请选择" clearable>
|
||||||
<el-option :label="item.label" :value="item.value" :key="index"
|
<el-option :label="item.label" :value="item.value" :key="index"
|
||||||
v-for="(item,index) in typeOptions"></el-option>
|
v-for="(item,index) in dictionary('config_form_type')"></el-option>
|
||||||
</el-select>
|
</el-select>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
|
<el-form-item
|
||||||
|
v-if="[4,5,6].indexOf(form.form_item_type)>-1"
|
||||||
|
label="字典key"
|
||||||
|
prop="setting"
|
||||||
|
:rules="[{required: true,message: '不能为空'}]">
|
||||||
|
<el-input v-model="form.setting" placeholder="请输入dictionary中key值" clearable></el-input>
|
||||||
|
</el-form-item>
|
||||||
<div v-if="[13,14].indexOf(form.form_item_type)>-1">
|
<div v-if="[13,14].indexOf(form.form_item_type)>-1">
|
||||||
<associationTable ref="associationTable" v-model="form.setting"
|
<associationTable ref="associationTable" v-model="form.setting"
|
||||||
@updateVal="associationTableUpdate"></associationTable>
|
@updateVal="associationTableUpdate"></associationTable>
|
||||||
|
@ -81,8 +88,8 @@ export default {
|
||||||
message: '请输入'
|
message: '请输入'
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
pattern: /^[A-Za-z0-9]+$/,
|
pattern: /^[A-Za-z0-9_]+$/,
|
||||||
message: '只支持字母和数字的输入'
|
message: '请输入数字、字母或下划线'
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
form_item_type: [
|
form_item_type: [
|
||||||
|
@ -94,23 +101,6 @@ export default {
|
||||||
},
|
},
|
||||||
// 父级内容
|
// 父级内容
|
||||||
parentOptions: [],
|
parentOptions: [],
|
||||||
// 表单类型
|
|
||||||
typeOptions: [
|
|
||||||
{ value: 0, label: '短文本' },
|
|
||||||
{ value: 1, label: '长文本' },
|
|
||||||
{ value: 2, label: '数字框' },
|
|
||||||
{ value: 3, label: '选择框' },
|
|
||||||
{ value: 4, label: '单选框' },
|
|
||||||
{ value: 5, label: '复选框' },
|
|
||||||
{ value: 6, label: '日期' },
|
|
||||||
{ value: 7, label: '日期时间' },
|
|
||||||
{ value: 8, label: '时间' },
|
|
||||||
{ value: 9, label: '图片' },
|
|
||||||
{ value: 10, label: '文件' },
|
|
||||||
{ value: 11, label: '数组' },
|
|
||||||
{ value: 12, label: '关联表' },
|
|
||||||
{ value: 13, label: '关联表(多选)' }
|
|
||||||
],
|
|
||||||
ruleOptions: [
|
ruleOptions: [
|
||||||
{
|
{
|
||||||
label: '必填项',
|
label: '必填项',
|
||||||
|
@ -119,6 +109,10 @@ export default {
|
||||||
{
|
{
|
||||||
label: '邮箱',
|
label: '邮箱',
|
||||||
value: '{ "type": "email", "message": "请输入正确的邮箱地址"}'
|
value: '{ "type": "email", "message": "请输入正确的邮箱地址"}'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: 'URL地址',
|
||||||
|
value: '{ "type": "url", "message": "请输入正确的URL地址"}'
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
@ -162,7 +156,6 @@ export default {
|
||||||
const that = this
|
const that = this
|
||||||
return new Promise(function (resolve, reject) {
|
return new Promise(function (resolve, reject) {
|
||||||
if (that.$refs.associationTable) {
|
if (that.$refs.associationTable) {
|
||||||
console.log(that.$refs.associationTable.onSubmit())
|
|
||||||
if (!that.$refs.associationTable.onSubmit()) {
|
if (!that.$refs.associationTable.onSubmit()) {
|
||||||
// eslint-disable-next-line prefer-promise-reject-errors
|
// eslint-disable-next-line prefer-promise-reject-errors
|
||||||
return reject(false)
|
return reject(false)
|
|
@ -17,12 +17,74 @@
|
||||||
:type="item.form_item_type_label"
|
:type="item.form_item_type_label"
|
||||||
v-model="form[item.key]" :placeholder="item.placeholder" clearable></el-input>
|
v-model="form[item.key]" :placeholder="item.placeholder" clearable></el-input>
|
||||||
|
|
||||||
<el-input-number :key="index" v-else-if="item.form_item_type_label==='number'" v-model="form[item.key]"
|
<el-input-number :key="index" v-else-if="item.form_item_type_label === 'number'" v-model="form[item.key]"
|
||||||
:min="0"></el-input-number>
|
:min="0"></el-input-number>
|
||||||
|
<!-- datetime、date、time -->
|
||||||
|
<el-date-picker
|
||||||
|
v-else-if="['datetime','date','time'].indexOf(item.form_item_type_label) >-1"
|
||||||
|
v-model="form[item.key]"
|
||||||
|
:key="index"
|
||||||
|
:type="item.form_item_type_label"
|
||||||
|
:placeholder="item.placeholder">
|
||||||
|
</el-date-picker>
|
||||||
|
<!-- select -->
|
||||||
|
<el-select
|
||||||
|
:key="index"
|
||||||
|
v-else-if="item.form_item_type_label === 'select'"
|
||||||
|
v-model="form[item.key]"
|
||||||
|
:placeholder="item.placeholder"
|
||||||
|
clearable
|
||||||
|
>
|
||||||
|
<el-option
|
||||||
|
v-for="item in dictionary(item.setting) || []"
|
||||||
|
:key="item.value"
|
||||||
|
:label="item.label"
|
||||||
|
:value="item.value">
|
||||||
|
</el-option>
|
||||||
|
</el-select>
|
||||||
|
<!-- checkbox -->
|
||||||
|
<el-checkbox-group
|
||||||
|
:key="index"
|
||||||
|
v-else-if="item.form_item_type_label === 'checkbox'"
|
||||||
|
v-model="form[item.key]"
|
||||||
|
:placeholder="item.placeholder"
|
||||||
|
>
|
||||||
|
<el-checkbox
|
||||||
|
v-for="item in dictionary(item.setting) || []"
|
||||||
|
:key="item.value"
|
||||||
|
:label="item.value"
|
||||||
|
:value="item.value">
|
||||||
|
{{ item.label }}
|
||||||
|
</el-checkbox>
|
||||||
|
</el-checkbox-group>
|
||||||
|
<!-- radio -->
|
||||||
|
<el-radio-group
|
||||||
|
:key="index"
|
||||||
|
v-else-if="item.form_item_type_label === 'radio'"
|
||||||
|
v-model="form[item.key]"
|
||||||
|
:placeholder="item.placeholder"
|
||||||
|
clearable
|
||||||
|
>
|
||||||
|
<el-radio
|
||||||
|
v-for="item in dictionary(item.setting) || []"
|
||||||
|
:key="item.value"
|
||||||
|
:label="item.label"
|
||||||
|
:value="item.value">
|
||||||
|
{{ item.label }}
|
||||||
|
</el-radio>
|
||||||
|
</el-radio-group>
|
||||||
|
<!-- switch -->
|
||||||
|
<el-switch
|
||||||
|
:key="index"
|
||||||
|
v-else-if="item.form_item_type_label === 'switch'"
|
||||||
|
v-model="form[item.key]"
|
||||||
|
active-color="#13ce66"
|
||||||
|
inactive-color="#ff4949">
|
||||||
|
</el-switch>
|
||||||
<!-- 图片 -->
|
<!-- 图片 -->
|
||||||
<div v-else-if="['img','imgs'].indexOf(item.form_item_type_label) >-1" :key="index">
|
<div v-else-if="['img','imgs'].indexOf(item.form_item_type_label) >-1" :key="index">
|
||||||
<el-upload
|
<el-upload
|
||||||
:action="imgUploadUrl"
|
:action="uploadUrl"
|
||||||
:headers="uploadHeaders"
|
:headers="uploadHeaders"
|
||||||
name="url"
|
name="url"
|
||||||
:accept="'image/*'"
|
:accept="'image/*'"
|
||||||
|
@ -43,6 +105,29 @@
|
||||||
<img width="100%" :src="dialogImageUrl" alt="">
|
<img width="100%" :src="dialogImageUrl" alt="">
|
||||||
</el-dialog>
|
</el-dialog>
|
||||||
</div>
|
</div>
|
||||||
|
<!-- 文件 -->
|
||||||
|
<div v-else-if="['file'].indexOf(item.form_item_type_label) >-1" :key="index">
|
||||||
|
<el-upload
|
||||||
|
:action="uploadUrl"
|
||||||
|
:headers="uploadHeaders"
|
||||||
|
name="url"
|
||||||
|
:on-preview="handlePictureCardPreview"
|
||||||
|
:on-success="(response, file, fileList)=>{handleUploadSuccess(response, file, fileList,item.key)}"
|
||||||
|
:on-error="handleError"
|
||||||
|
:on-exceed="handleExceed"
|
||||||
|
:limit="item.form_item_type_label==='img'?1:5"
|
||||||
|
:ref="'fileUpload_'+item.key"
|
||||||
|
:data-keyname="item.key"
|
||||||
|
:file-list="item.value?item.value:[]"
|
||||||
|
list-type="picture-card"
|
||||||
|
>
|
||||||
|
<i class="el-icon-plus"></i>
|
||||||
|
<div slot="tip" class="el-upload__tip">选取图片后,需手动上传到服务器,并且只能上传jpg/png文件</div>
|
||||||
|
</el-upload>
|
||||||
|
<el-dialog :visible.sync="dialogImgVisible">
|
||||||
|
<img width="100%" :src="dialogImageUrl" alt="">
|
||||||
|
</el-dialog>
|
||||||
|
</div>
|
||||||
<!-- 关联表 -->
|
<!-- 关联表 -->
|
||||||
<div v-else-if="['foreignkey','manytomany'].indexOf(item.form_item_type_label) >-1" :key="index">
|
<div v-else-if="['foreignkey','manytomany'].indexOf(item.form_item_type_label) >-1" :key="index">
|
||||||
<table-selector
|
<table-selector
|
||||||
|
@ -56,7 +141,7 @@
|
||||||
label: item.setting.field,
|
label: item.setting.field,
|
||||||
}"
|
}"
|
||||||
:pagination="true"
|
:pagination="true"
|
||||||
:multiple="item.form_item_type_label==='manytomany'?true:false"
|
:multiple="item.form_item_type_label ==='manytomany'"
|
||||||
></table-selector>
|
></table-selector>
|
||||||
</div>
|
</div>
|
||||||
<!-- 数组 -->
|
<!-- 数组 -->
|
||||||
|
@ -171,8 +256,7 @@ export default {
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
imgUploadUrl: util.baseURL() + 'api/system/img/',
|
uploadUrl: util.baseURL() + 'api/system/file/',
|
||||||
// imgUploadUrl: 'http://public.yuanxiaotian.com:8000/api/system/img/',
|
|
||||||
uploadHeaders: {
|
uploadHeaders: {
|
||||||
Authorization: 'JWT ' + util.cookies.get('token')
|
Authorization: 'JWT ' + util.cookies.get('token')
|
||||||
},
|
},
|
||||||
|
@ -191,7 +275,15 @@ export default {
|
||||||
const form = {}
|
const form = {}
|
||||||
for (const item of data) {
|
for (const item of data) {
|
||||||
const key = item.key
|
const key = item.key
|
||||||
form[key] = item.value
|
if (item.value) {
|
||||||
|
form[key] = item.value
|
||||||
|
} else {
|
||||||
|
if ([5, 12, 14].indexOf(item.form_item_type) !== -1) {
|
||||||
|
form[key] = []
|
||||||
|
} else {
|
||||||
|
form[key] = undefined
|
||||||
|
}
|
||||||
|
}
|
||||||
if (item.form_item_type_label === 'array') {
|
if (item.form_item_type_label === 'array') {
|
||||||
that.$nextTick(() => {
|
that.$nextTick(() => {
|
||||||
const tableName = 'xTable_' + key
|
const tableName = 'xTable_' + key
|
||||||
|
@ -209,6 +301,7 @@ export default {
|
||||||
const form = JSON.parse(JSON.stringify(this.form))
|
const form = JSON.parse(JSON.stringify(this.form))
|
||||||
const keys = Object.keys(form)
|
const keys = Object.keys(form)
|
||||||
const values = Object.values(form)
|
const values = Object.values(form)
|
||||||
|
console.log(111, form)
|
||||||
for (const index in this.formList) {
|
for (const index in this.formList) {
|
||||||
const item = this.formList[index]
|
const item = this.formList[index]
|
||||||
// eslint-disable-next-line camelcase
|
// eslint-disable-next-line camelcase
|
||||||
|
@ -237,20 +330,22 @@ export default {
|
||||||
item.value = tableData
|
item.value = tableData
|
||||||
}
|
}
|
||||||
// 赋值操作
|
// 赋值操作
|
||||||
if (keys[index] === item.key) {
|
keys.map((mapKey, mapIndex) => {
|
||||||
if (item.form_item_type_label !== 'array') {
|
if (mapKey === item.key) {
|
||||||
item.value = values[index]
|
if (item.form_item_type_label !== 'array') {
|
||||||
}
|
item.value = values[mapIndex]
|
||||||
// 必填项的验证
|
}
|
||||||
if (['img', 'imgs'].indexOf(item.form_item_type_label) > -1) {
|
// 必填项的验证
|
||||||
for (const arr of item.rule) {
|
if (['img', 'imgs'].indexOf(item.form_item_type_label) > -1) {
|
||||||
if (arr.required && item.value === null) {
|
for (const arr of item.rule) {
|
||||||
that.$message.error(item.title + '不能为空')
|
if (arr.required && item.value === null) {
|
||||||
return
|
that.$message.error(item.title + '不能为空')
|
||||||
|
return
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
})
|
||||||
}
|
}
|
||||||
that.$refs.form.clearValidate()
|
that.$refs.form.clearValidate()
|
||||||
that.$refs.form.validate((valid) => {
|
that.$refs.form.validate((valid) => {
|
||||||
|
@ -272,10 +367,16 @@ export default {
|
||||||
const $table = this.$refs[tableName][0]
|
const $table = this.$refs[tableName][0]
|
||||||
const { tableData } = $table.getTableData()
|
const { tableData } = $table.getTableData()
|
||||||
const tableLength = tableData.length
|
const tableLength = tableData.length
|
||||||
if (tableLength !== 0) {
|
if (tableLength === 0) {
|
||||||
|
const { row: newRow } = $table.insert()
|
||||||
|
console.log(newRow)
|
||||||
|
} else {
|
||||||
const errMap = await $table.validate().catch(errMap => errMap)
|
const errMap = await $table.validate().catch(errMap => errMap)
|
||||||
if (errMap) {
|
if (errMap) {
|
||||||
this.$message.error('校验不通过!')
|
this.$message.error('校验不通过!')
|
||||||
|
} else {
|
||||||
|
const { row: newRow } = $table.insert()
|
||||||
|
console.log(newRow)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
@ -292,13 +393,6 @@ export default {
|
||||||
this.dialogImageUrl = file.url
|
this.dialogImageUrl = file.url
|
||||||
this.dialogImgVisible = true
|
this.dialogImgVisible = true
|
||||||
},
|
},
|
||||||
// 上传提交
|
|
||||||
submitUpload (key) {
|
|
||||||
const refName = 'imgUpload_' + key
|
|
||||||
const ref = this.$refs[refName][0]
|
|
||||||
ref.submit()
|
|
||||||
this.uploadImgKey = key
|
|
||||||
},
|
|
||||||
// 判断是否为图片
|
// 判断是否为图片
|
||||||
// 封装一个判断图片文件后缀名的方法
|
// 封装一个判断图片文件后缀名的方法
|
||||||
isImage (fileName) {
|
isImage (fileName) {
|
|
@ -58,17 +58,23 @@
|
||||||
:label="item.title"
|
:label="item.title"
|
||||||
:name="item.key"
|
:name="item.key"
|
||||||
>
|
>
|
||||||
<formContent :options="item" :editableTabsItem="item"></formContent>
|
<span slot="label" v-if="item.icon"><i :class="item.icon" style="font-weight: 1000;font-size: 16px;"></i></span>
|
||||||
|
<el-row v-if="item.icon">
|
||||||
|
<el-col :offset="4" :span="8">
|
||||||
|
<addContent></addContent>
|
||||||
|
</el-col>
|
||||||
|
</el-row>
|
||||||
|
<formContent v-else :options="item" :editableTabsItem="item"></formContent>
|
||||||
</el-tab-pane>
|
</el-tab-pane>
|
||||||
</el-tabs>
|
</el-tabs>
|
||||||
</d2-container>
|
</d2-container>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
import addTabs from './components/addTabs'
|
import addTabs from '@/views/system/config/components/addTabs'
|
||||||
import * as api from './api'
|
import * as api from './api'
|
||||||
import addContent from './components/addContent'
|
import addContent from '@/views/system/config/components/addContent'
|
||||||
import formContent from './components/formContent'
|
import formContent from '@/views/system/config/components/formContent'
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
name: 'config',
|
name: 'config',
|
||||||
|
@ -81,7 +87,7 @@ export default {
|
||||||
return {
|
return {
|
||||||
tabsDrawer: false,
|
tabsDrawer: false,
|
||||||
contentDrawer: false,
|
contentDrawer: false,
|
||||||
editableTabsValue: 'basic',
|
editableTabsValue: 'base',
|
||||||
editableTabs: [],
|
editableTabs: [],
|
||||||
tabIndex: 2
|
tabIndex: 2
|
||||||
}
|
}
|
||||||
|
@ -93,6 +99,11 @@ export default {
|
||||||
parent__isnull: true
|
parent__isnull: true
|
||||||
}).then(res => {
|
}).then(res => {
|
||||||
const { data } = res.data
|
const { data } = res.data
|
||||||
|
data.push({
|
||||||
|
title: '无',
|
||||||
|
icon: 'el-icon-plus',
|
||||||
|
key: 'null'
|
||||||
|
})
|
||||||
this.editableTabs = data
|
this.editableTabs = data
|
||||||
})
|
})
|
||||||
}
|
}
|
Loading…
Reference in New Issue