新增:系统配置完善

pull/57/head
李强 2022-05-13 20:37:28 +08:00
parent 9568ac0e00
commit 03f51f3706
7 changed files with 165 additions and 63 deletions

View File

@ -283,26 +283,29 @@ class SystemConfig(CoreModel):
parent = models.ForeignKey(to='self', verbose_name='父级', on_delete=models.CASCADE,
db_constraint=False, null=True, blank=True, 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)
sort = models.IntegerField(default=0, verbose_name="排序", help_text="排序", blank=True)
status = models.BooleanField(default=False, verbose_name="启用状态", help_text="启用状态")
data_options = models.JSONField(verbose_name="数据options", help_text="数据options", null=True, blank=True)
FORM_ITEM_TYPE_LIST = (
(0, 'text'),
(1, 'textarea'),
(2, 'number'),
(3, 'select'),
(4, 'radio'),
(1, 'datetime'),
(2, 'date'),
(3, 'textarea'),
(4, 'select'),
(5, 'checkbox'),
(6, 'date'),
(7, 'datetime'),
(8, 'time'),
(9, 'imgs'),
(10, 'files'),
(6, 'radio'),
(7, 'img'),
(8, 'file'),
(9, 'switch'),
(10, 'number'),
(11, 'array'),
(12, 'foreignkey'),
(13, 'manytomany'),
(12, 'imgs'),
(13, 'foreignkey'),
(14, 'manytomany'),
(15, 'time'),
)
form_item_type = models.IntegerField(choices=FORM_ITEM_TYPE_LIST, verbose_name="表单类型", help_text="表单类型", default=0,
blank=True)
@ -315,6 +318,7 @@ class SystemConfig(CoreModel):
verbose_name = '系统配置表'
verbose_name_plural = verbose_name
ordering = ('sort',)
unique_together = (("key", "parent_id"),)
def __str__(self):
return f"{self.title}"

View File

@ -16,9 +16,16 @@
<el-form-item label="表单类型" prop="form_item_type">
<el-select v-model="form.form_item_type" placeholder="请选择" clearable>
<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-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">
<associationTable ref="associationTable" v-model="form.setting"
@updateVal="associationTableUpdate"></associationTable>
@ -81,8 +88,8 @@ export default {
message: '请输入'
},
{
pattern: /^[A-Za-z0-9]+$/,
message: '只支持字母和数字的输入'
pattern: /^[A-Za-z0-9_]+$/,
message: '请输入数字、字母或下划线'
}
],
form_item_type: [
@ -94,23 +101,6 @@ export default {
},
//
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: [
{
label: '必填项',
@ -119,6 +109,10 @@ export default {
{
label: '邮箱',
value: '{ "type": "email", "message": "请输入正确的邮箱地址"}'
},
{
label: 'URL地址',
value: '{ "type": "url", "message": "请输入正确的URL地址"}'
}
]
}
@ -162,7 +156,6 @@ export default {
const that = this
return new Promise(function (resolve, reject) {
if (that.$refs.associationTable) {
console.log(that.$refs.associationTable.onSubmit())
if (!that.$refs.associationTable.onSubmit()) {
// eslint-disable-next-line prefer-promise-reject-errors
return reject(false)

View File

@ -17,12 +17,74 @@
:type="item.form_item_type_label"
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>
<!-- datetimedatetime -->
<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">
<el-upload
:action="imgUploadUrl"
:action="uploadUrl"
:headers="uploadHeaders"
name="url"
:accept="'image/*'"
@ -43,6 +105,29 @@
<img width="100%" :src="dialogImageUrl" alt="">
</el-dialog>
</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">
<table-selector
@ -56,7 +141,7 @@
label: item.setting.field,
}"
:pagination="true"
:multiple="item.form_item_type_label==='manytomany'?true:false"
:multiple="item.form_item_type_label ==='manytomany'"
></table-selector>
</div>
<!-- 数组 -->
@ -171,8 +256,7 @@ export default {
}
]
},
imgUploadUrl: util.baseURL() + 'api/system/img/',
// imgUploadUrl: 'http://public.yuanxiaotian.com:8000/api/system/img/',
uploadUrl: util.baseURL() + 'api/system/file/',
uploadHeaders: {
Authorization: 'JWT ' + util.cookies.get('token')
},
@ -191,7 +275,15 @@ export default {
const form = {}
for (const item of data) {
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') {
that.$nextTick(() => {
const tableName = 'xTable_' + key
@ -209,6 +301,7 @@ export default {
const form = JSON.parse(JSON.stringify(this.form))
const keys = Object.keys(form)
const values = Object.values(form)
console.log(111, form)
for (const index in this.formList) {
const item = this.formList[index]
// eslint-disable-next-line camelcase
@ -237,20 +330,22 @@ export default {
item.value = tableData
}
//
if (keys[index] === item.key) {
if (item.form_item_type_label !== 'array') {
item.value = values[index]
}
//
if (['img', 'imgs'].indexOf(item.form_item_type_label) > -1) {
for (const arr of item.rule) {
if (arr.required && item.value === null) {
that.$message.error(item.title + '不能为空')
return
keys.map((mapKey, mapIndex) => {
if (mapKey === item.key) {
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 (arr.required && item.value === null) {
that.$message.error(item.title + '不能为空')
return
}
}
}
}
}
})
}
that.$refs.form.clearValidate()
that.$refs.form.validate((valid) => {
@ -272,10 +367,16 @@ export default {
const $table = this.$refs[tableName][0]
const { tableData } = $table.getTableData()
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)
if (errMap) {
this.$message.error('校验不通过!')
} else {
const { row: newRow } = $table.insert()
console.log(newRow)
}
}
},
@ -292,13 +393,6 @@ export default {
this.dialogImageUrl = file.url
this.dialogImgVisible = true
},
//
submitUpload (key) {
const refName = 'imgUpload_' + key
const ref = this.$refs[refName][0]
ref.submit()
this.uploadImgKey = key
},
//
//
isImage (fileName) {

View File

@ -58,17 +58,23 @@
:label="item.title"
: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-tabs>
</d2-container>
</template>
<script>
import addTabs from './components/addTabs'
import addTabs from '@/views/system/config/components/addTabs'
import * as api from './api'
import addContent from './components/addContent'
import formContent from './components/formContent'
import addContent from '@/views/system/config/components/addContent'
import formContent from '@/views/system/config/components/formContent'
export default {
name: 'config',
@ -81,7 +87,7 @@ export default {
return {
tabsDrawer: false,
contentDrawer: false,
editableTabsValue: 'basic',
editableTabsValue: 'base',
editableTabs: [],
tabIndex: 2
}
@ -93,6 +99,11 @@ export default {
parent__isnull: true
}).then(res => {
const { data } = res.data
data.push({
title: '无',
icon: 'el-icon-plus',
key: 'null'
})
this.editableTabs = data
})
}