新增课程报名

dev
lion 1 year ago
parent 0cd8a3aa5d
commit afeb9e10f6

@ -0,0 +1,57 @@
import request from "@/utils/request";
function customParamsSerializer(params) {
let result = '';
for (let key in params) {
if (params.hasOwnProperty(key)) {
if (Array.isArray(params[key])) {
params[key].forEach((item,index) => {
if(item.key){
result += `${key}[${index}][key]=${item.key}&${key}[${index}][op]=${item.op}&${key}[${index}][value]=${item.value}&`;
}else{
result +=`${key}[${index}]=${item}&`
}
});
} else {
result += `${key}=${params[key]}&`;
}
}
}
return result.slice(0, -1);
}
export function index(params,isLoading = false) {
return request({
method: "get",
url: "/api/admin/course-forms/index",
params,
paramsSerializer: customParamsSerializer,
isLoading
})
}
export function show(params, isLoading = true) {
return request({
method: "get",
url: "/api/admin/course-forms/show",
params,
isLoading
})
}
export function save(data) {
return request({
method: "post",
url: "/api/admin/course-forms/save",
data
})
}
export function destroy(params) {
return request({
method: "get",
url: "/api/admin/course-forms/destroy",
params
})
}

@ -87,18 +87,29 @@ export default {
} }
this.$refs['elForm'].resetFields() this.$refs['elForm'].resetFields()
}, },
submit(){ submit(ischeck){
// ischeck
if(this.type === 'normal'){ if(this.type === 'normal'){
return return
} }
this.$refs['elForm'].validate().then(res=>{ this.$refs['elForm'].validate().then(res=>{
if(res)this.$emit('submit') if(res){
if(ischeck){
this.$emit('mysubmit',true)
}else{
this.$emit('submit')
}
}
}).catch(err => { }).catch(err => {
console.log("456")
this.$Message.warning({ this.$Message.warning({
content: "请填写完整信息", content: "请填写完整信息",
background: true, background: true,
duration: 1 duration: 1
}) })
if(ischeck){
this.$emit('mysubmit',false)
}
}) })
}, },
okClick(){ okClick(){

@ -150,6 +150,7 @@ const actions = {
state.formList.forEach((item,index) => { state.formList.forEach((item,index) => {
item.sort = index + 1 item.sort = index + 1
}) })
console.log("state.formList",state.formList)
res.fields = state.formList res.fields = state.formList
save(res).then(res1 => { save(res).then(res1 => {
Message({ Message({

@ -1,8 +1,21 @@
<template> <template>
<div> <div>
<xy-dialog ref="dialog" :width="70" :is-show.sync="isShow" :type="'form'" :title="type === 'add' ? '新增课程' : '编辑课程'" <xy-dialog ref="dialog" :width="70" :is-show.sync="isShow" :type="'form'" :title="type === 'add' ? '新增课程' : '编辑课程'"
:form="form" :rules='rules' @submit="submit"> :form="form" :rules='rules' @mysubmit="mysubmit">
<template v-slot:name> <template v-slot:step>
<div class="xy-table-item">
<div class="xy-table-item-label" style="font-weight: bold;display:none">
<span style="color: red;font-weight: bold;padding-right: 4px;"></span>
</div>
<div class="xy-table-item-content">
<el-steps :active="active" finish-status="success" simple>
<el-step title="课程信息"></el-step>
<el-step title="报名信息"></el-step>
</el-steps>
</div>
</div>
</template>
<template v-slot:name v-if="active===0">
<div class="xy-table-item"> <div class="xy-table-item">
<div class="xy-table-item-label" style="font-weight: bold"> <div class="xy-table-item-label" style="font-weight: bold">
<span style="color: red;font-weight: bold;padding-right: 4px;">*</span>课程名称 <span style="color: red;font-weight: bold;padding-right: 4px;">*</span>课程名称
@ -12,161 +25,160 @@
</div> </div>
</div> </div>
</template> </template>
<template v-slot:type> <template v-slot:type v-if="active===0">
<div class="xy-table-item"> <div class="xy-table-item">
<div class="xy-table-item-label" style="font-weight: bold"> <div class="xy-table-item-label" style="font-weight: bold">
<span style="color: red;font-weight: bold;padding-right: 4px;">*</span>课程类别 <span style="color: red;font-weight: bold;padding-right: 4px;">*</span>课程类别
</div> </div>
<div class="xy-table-item-content"> <div class="xy-table-item-content">
<el-select v-model="form.type" placeholder="请选择类别" clearable style="width: 100%;"> <el-select v-model="form.type" @change="changeType" placeholder="请选择类别" clearable style="width: 100%;">
<el-option v-for="item in course_type" :key="item.id" :label="item.value" :value="item.id"> <el-option v-for="item in course_type" :key="item.id" :label="item.value" :value="item.id">
</el-option> </el-option>
</el-select> </el-select>
</div> </div>
</div> </div>
</template> </template>
<template v-slot:image_id> <template v-slot:dateRange v-if="active===0">
<div class="xy-table-item"> <div class="xy-table-item">
<div class="xy-table-item-label" style="font-weight: bold;"> <div class="xy-table-item-label" style="font-weight: bold">
<span style="color: red;font-weight: bold;padding-right: 4px;">*</span>课程封面750*400 <span style="color: red;font-weight: bold;padding-right: 4px;">*</span>开课日期
</div> </div>
<div class="xy-table-item-content"> <div class="xy-table-item-content">
<el-upload :action="action" class='upload-demo' :limit="1" list-type="picture-card" :file-list="imgList" <el-date-picker @change="changeDateRange" style="width: 100%;" v-model="form.dateRange" type="daterange"
ref="pictureUpload" :before-upload="beforeUpload" :auto-upload="true" :on-success="uploadSuccess" range-separator="至" value-format="yyyy-MM-dd" format="yyyy-MM-dd" start-placeholder="开课日期"
:on-remove="uploadRemove"> end-placeholder="结束日期">
<i class="el-icon-plus"></i> </el-date-picker>
</el-upload>
</div> </div>
</div> </div>
</template> </template>
<template v-slot:content>
<template v-slot:total v-if="active===0">
<div class="xy-table-item"> <div class="xy-table-item">
<div class="xy-table-item-label" style="font-weight: bold"> <div class="xy-table-item-label" style="font-weight: bold">
<span style="color: red;font-weight: bold;padding-right: 4px;">*</span>课程简介 <span style="color: red;font-weight: bold;padding-right: 4px;"></span>开课人数
</div> </div>
<div class="xy-table-item-content"> <div class="xy-table-item-content">
<my-tinymce v-if="showTinymce" @input="saveContent" :value="form.content"></my-tinymce> <el-input style="width: 100%;" v-model="form.total" placeholder="请输入开课人数" clearable></el-input>
</div> </div>
</div> </div>
</template> </template>
<template v-slot:dateRange> <template v-slot:status v-if="active===0">
<div class="xy-table-item"> <div class="xy-table-item">
<div class="xy-table-item-label" style="font-weight: bold"> <div class="xy-table-item-label" style="font-weight: bold">
<span style="color: red;font-weight: bold;padding-right: 4px;">*</span>开课日期 <span style="color: red;font-weight: bold;padding-right: 4px;"></span>状态
</div> </div>
<div class="xy-table-item-content"> <div class="xy-table-item-content">
<el-date-picker @change="changeDateRange" style="width: 100%;" v-model="form.dateRange" <el-select style="width: 100%;" v-model="form.status" placeholder="请选择" clearable>
type="daterange" range-separator="至" <el-option v-for="item in course_status" :key="item.id" :label="item.value" :value="item.id">
value-format="yyyy-MM-dd" </el-option>
format="yyyy-MM-dd" </el-select>
start-placeholder="开课日期" end-placeholder="结束日期">
</el-date-picker>
</div> </div>
</div> </div>
</template> </template>
<template v-slot:is_arrange v-if="active===0">
<template v-slot:total>
<div class="xy-table-item"> <div class="xy-table-item">
<div class="xy-table-item-label" style="font-weight: bold"> <div class="xy-table-item-label" style="font-weight: bold">
<span style="color: red;font-weight: bold;padding-right: 4px;"></span>开课人数 <span style="color: red;font-weight: bold;padding-right: 4px;"></span>是否排课
</div> </div>
<div class="xy-table-item-content"> <div class="xy-table-item-content">
<el-input style="width: 100%;" v-model="form.total" placeholder="请输入开课人数" clearable></el-input> <el-radio-group style="width:100%" v-model="form.is_arrange">
<el-radio :label="1"></el-radio>
<el-radio :label="0"></el-radio>
</el-radio-group>
</div> </div>
</div> </div>
</template> </template>
<template v-slot:class> <template v-slot:is_fee v-if="active===0">
<div class="xy-table-item"> <div class="xy-table-item">
<div class="xy-table-item-label" style="font-weight: bold"> <div class="xy-table-item-label" style="font-weight: bold">
<span style="color: red;font-weight: bold;padding-right: 4px;"></span>所在班级地点 <span style="color: red;font-weight: bold;padding-right: 4px;"></span>是否缴费
</div> </div>
<div class="xy-table-item-content"> <div class="xy-table-item-content">
<el-input style="width: 100%;" v-model="form.class" placeholder="请输入所在班级(地点)" clearable></el-input> <el-radio-group style="width:100%" v-model="form.is_fee">
<el-radio :label="1"></el-radio>
<el-radio :label="0"></el-radio>
</el-radio-group>
</div> </div>
</div> </div>
</template> </template>
<template v-slot:company_type> <template v-slot:image_id v-if="active===0">
<div class="xy-table-item"> <div class="xy-table-item">
<div class="xy-table-item-label" style="font-weight: bold"> <div class="xy-table-item-label" style="font-weight: bold;">
<span style="color: red;font-weight: bold;padding-right: 4px;"></span>面向学员的企业性质 <span style="color: red;font-weight: bold;padding-right: 4px;">*</span>课程封面750*400
</div> </div>
<div class="xy-table-item-content"> <div class="xy-table-item-content">
<el-select style="width: 100%;" v-model="form.company_type" placeholder="请选择" clearable> <el-upload :action="action" class='upload-demo' :on-exceed="onExceed" :limit="1" list-type="picture-card"
<el-option v-for="item in course_type" :key="item.id" :label="item.value" :value="item.id"> :file-list="imgList" ref="pictureUpload" :before-upload="beforeUpload" :auto-upload="true"
</el-option> :on-success="uploadSuccess" :on-remove="uploadRemove">
</el-select> <i class="el-icon-plus"></i>
</el-upload>
</div> </div>
</div> </div>
</template> </template>
<template v-slot:industry> <template v-slot:publicize_ids v-if="active===0">
<div class="xy-table-item"> <div class="xy-table-item">
<div class="xy-table-item-label" style="font-weight: bold"> <div class="xy-table-item-label" style="font-weight: bold;">
<span style="color: red;font-weight: bold;padding-right: 4px;"></span>所属行业 <span style="color: red;font-weight: bold;padding-right: 4px;"></span>课程宣传页宽750
</div> </div>
<div class="xy-table-item-content"> <div class="xy-table-item-content">
<el-select style="width: 100%;" v-model="form.industry" placeholder="请选择" clearable> <el-upload :action="action" multiple class='upload-demo' list-type="picture-card" :file-list="publicizeList"
<el-option v-for="item in course_type" :key="item.id" :label="item.value" :value="item.id"> ref="pictureUpload" :auto-upload="true" :on-success="uploadSuccesspublic" :on-remove="uploadRemovepublic">
</el-option> <i class="el-icon-plus"></i>
</el-select> </el-upload>
</div> </div>
</div> </div>
</template> </template>
<template v-slot:status> <template v-slot:content v-if="active===0">
<div class="xy-table-item"> <div class="xy-table-item">
<div class="xy-table-item-label" style="font-weight: bold"> <div class="xy-table-item-label" style="font-weight: bold">
<span style="color: red;font-weight: bold;padding-right: 4px;"></span>状态 <span style="color: red;font-weight: bold;padding-right: 4px;">*</span>课程简介
</div> </div>
<div class="xy-table-item-content"> <div class="xy-table-item-content">
<el-select style="width: 100%;" v-model="form.status" placeholder="请选择" clearable> <my-tinymce v-if="showTinymce" @input="saveContent" :value="form.content"></my-tinymce>
<el-option v-for="item in course_status" :key="item.id" :label="item.value" :value="item.id">
</el-option>
</el-select>
</div> </div>
</div> </div>
</template> </template>
<template v-slot:settings>
<!-- 自定义报名 表单 -->
<template v-slot:applylabel v-if="active===1">
<div class="xy-table-item"> <div class="xy-table-item">
<div class="xy-table-item-label" style="font-weight: bold;display:none"> <div class="xy-table-item-label" style="font-weight: bold;display:none">
<span style="color: red;font-weight: bold;padding-right: 4px;"></span> <span style="color: red;font-weight: bold;padding-right: 4px;"></span>
</div> </div>
<div class="xy-table-item-content" style="flex-grow: 1;"> <div class="xy-table-item-content" style="min-height: 300px;">
课时设置<el-button type="primary" icon="md-add" style="margin-bottom: 10px" <div>
@click="courseSettings.push({ course_id:id,title: '',content:''})">新增</el-button> <el-dialog id="template-dialog" :title="'模板表单'"
<xy-table style="width: 100%" :height="260" :is-page="false" :list="courseSettings" style="position: relative; inset: 0 0 0 0; height: 100%;padding:20px 0" width="90%" top="0px"
:table-item="settings_Table"> :visible="true" :modal="false" :append-to-body="false" :show-close="false"
<template v-slot:title> :modal-append-to-body="false">
<el-table-column label="课时名称" width="180" header-align="center" align="center"> <template v-slot:title>
<template v-slot:default="scope"> <Button v-if="formList.length>0" ghost type="primary" @click="editForm('editor')"></Button>
<el-input v-model="scope.row.title"></el-input> <Button v-else ghost type="primary" @click="editForm('add')"></Button>
</template> </template>
</el-table-column> <el-form style="min-height: 300px;" label-width="80px" label-position="right" size="small">
</template> <el-form-item :label="i.name || '字段名称'" :required="
<template v-slot:content> i.rule ? !!i.rule.includes('required') : false
<el-table-column label="课时简介" width="600" header-align="center" align="center"> " v-for="(i, index) in formList" @click.native="selectPick(i, index)">
<template v-slot:default="scope"> <formSlotRender :config="i" :index="index"></formSlotRender>
<el-input v-model="scope.row.content"></el-input> </el-form-item>
</template> </el-form>
</el-table-column> </el-dialog>
</template> </div>
<template v-slot:btns>
<el-table-column label="操作" width="180" header-align="center" align="center">
<template v-slot:default="scope">
<div v-if="type==='editor'" style="display:inline-block">
<el-button type="primary" size="small" v-if="scope.row.id" @click="saveSetting(scope.$index)"></el-button>
<el-button type="primary" size="small" v-else @click="saveSetting(scope.$index)"></el-button>
</div>
<el-popconfirm style="margin:0 10px" @confirm="deleteList(scope.row.id,scope.$index)" title="确定删除吗?">
<el-button type="danger" size="small" slot="reference">删除</el-button>
</el-popconfirm>
</template>
</el-table-column>
</template>
</xy-table>
</div> </div>
</div> </div>
</template> </template>
<template v-slot:footerContent>
<Button ghost type="primary" v-if="active===1" @click="active=0"></Button>
<Button ghost type="primary" v-if="active===0" @click="next"></Button>
<Button type="primary" @click="checkSubmit"></Button>
<Button type="primary" @click="closeSubmit"></Button>
</template>
</xy-dialog> </xy-dialog>
<applyForm ref="applyForm" @refresh="getFormList"></applyForm>
</div> </div>
</template> </template>
@ -175,46 +187,45 @@
import { import {
show, show,
save save
} from "@/api/course/index.js" } from "@/api/course/index.js"
import { import {
index as settingIndex, index as formIndex
destroy as settingDestroy, } from "@/api/course/form";
save as settingSave, import {
settingImport deepCopy
} from "@/api/course/courseSetting.js" } from "@/utils";
import applyForm from "../components/applyForm.vue";
import formSlotRender from "@/views/system/components/formSlotRender.vue";
export default { export default {
mixins: [myMixins], mixins: [myMixins],
components: {
applyForm,
formSlotRender
},
data() { data() {
return { return {
isShow: false, isShow: false,
type: 'add', type: 'add',
active: 0,
id: '',
action: `${process.env.VUE_APP_UPLOAD_API}`, action: `${process.env.VUE_APP_UPLOAD_API}`,
id: '',
showTinymce: false, showTinymce: false,
imgList: [], imgList: [],
publicizeList: [],
form: { form: {
step: '', //
name: '', name: '',
type: '', type: 1,
image_id: '',
content: '',
dateRange: '', dateRange: '',
total: '', total: '',
class: '',
company_type: '',
industry: '',
status: 0, status: 0,
settings: [], is_arrange: 1,
}, is_fee: 1,
image_id: '',
courseSettings:[], publicize_ids: [],
settings_Table: [{ content: '',
label: "课时名称", applylabel: ''
prop:'title', },
width: 180,
}, {
label: "课时简介",
prop:'content'
}],
rules: { rules: {
name: [{ name: [{
required: true, required: true,
@ -223,40 +234,57 @@
type: [{ type: [{
required: true, required: true,
message: '请选择课程类别' message: '请选择课程类别'
}], }],
content: [{ image_id: [{
required: true, required: true,
message: '请输入课程简介' message: '请上传课程封面'
}],
content: [{
required: true,
message: '请输入课程简介'
}], }],
// image_id: [{ // image_id: [{
// required: true, // required: true,
// message: '' // message: ''
// }], // }],
dateRange:[{ dateRange: [{
required: true, required: true,
message: '请选择开课日期' message: '请选择开课日期'
}], }]
},
} //
selectForm: {
page: 1,
page_size: 999,
sort_name: 'sort',
sort_type: 'ASC'
},
formList: []
} }
}, },
created() {}, created() {},
methods: { methods: {
saveContent(e) { changeType(e) {
this.form.content = e if (e == 1) {
}, this.form.is_arrange = 1
changeDateRange(e){ this.form.is_fee = 1
if(e){ } else {
this.form.start_date = e[0] this.form.is_arrange = 0
this.form.end_date = e[1] this.form.is_fee = 0
console.log(e,this.form) }
}else{
this.form.start_date = ''
this.form.end_date = ''
}
}, },
uploadFail(err) { saveContent(e) {
console.log(err) this.form.content = e
},
changeDateRange(e) {
if (e) {
this.form.start_date = e[0]
this.form.end_date = e[1]
console.log(e, this.form)
} else {
this.form.start_date = ''
this.form.end_date = ''
}
}, },
beforeUpload(file) { beforeUpload(file) {
console.log(file) console.log(file)
@ -270,8 +298,11 @@
} }
return isImage && isLt2M; return isImage && isLt2M;
}, },
onExceed(file, fileList) {
console.log("file", file, fileList)
this.$Message.warning("课程封面只需上传一张")
},
uploadSuccess(response, file, fileList) { uploadSuccess(response, file, fileList) {
console.log(response, file, fileList)
this.form.image_id = response.id this.form.image_id = response.id
this.imgList = fileList this.imgList = fileList
}, },
@ -279,108 +310,95 @@
this.imgList = fileList this.imgList = fileList
this.form.image_id = '' this.form.image_id = ''
}, },
uploadSuccesspublic(response, file, fileList) {
this.publicizeList = fileList
},
uploadRemovepublic(file, fileList) {
this.publicizeList = fileList
},
// form
mysubmit(e) {
if (e) {
this.submit()
}
},
checkSubmit() {
this.$refs.dialog.submit(true)
},
submit() { submit() {
if (this.id) { if (this.id) {
this.form.id = this.id this.form.id = this.id
} }
if (this.type == 'add') { let pubFiles = []
this.form.id = '' if (this.publicizeList.length > 0) {
this.publicizeList.map(item => {
if (item.response.id) {
pubFiles.push(item.response.id)
} else {
pubFiles.push(item.id)
}
})
} }
this.form.publicize_ids = pubFiles
console.log("form", this.form)
save({ save({
...this.form ...this.form
}).then(res => { }).then(res => {
console.log('res',res) this.$message({
if(this.type=='add'){ type: 'success',
this.importSetting(res.id) message: '保存课程成功'
}else{ })
this.$message({ this.id = res.id
type: 'success', this.$emit('refresh')
message: '编辑课程成功' // this.active = 1
})
this.isShow = false
this.$emit('refresh')
}
}) })
}, },
closeSubmit() {
this.isShow = false
this.$emit('refresh')
},
getDetail() { getDetail() {
show({ show({
id: this.id, id: this.id,
// show_relation: ['image'] // show_relation:['image','publicize']
}).then(res => { }).then(res => {
this.form = this.base.requestToForm(res, this.form) this.form = this.base.requestToForm(res, this.form)
if(res.image){ if (res.image) {
this.imgList.push(res.image) this.imgList.push(res.image)
} }
this.form.dateRange = [res.start_date, res.end_date]
this.form.dateRange = [res.start_date,res.end_date] this.showTinymce = true
this.showTinymce = true
this.getSettingList()
}) })
},
next() {
if (this.id) {
this.active = 1
} else {
this.$Message.warning("请先保存课程信息")
}
},
//
async getFormList() {
const res = await formIndex({
filter: [{
key: 'course_id',
op: 'eq',
value: this.id
}],
...this.selectForm
})
this.formList = res.data
}, },
// //
async getSettingList() { editForm(type, id) {
const res = await settingIndex({ this.$refs.applyForm.formList = deepCopy(this.formList)
page: 1, this.$refs.applyForm.course_id = this.id
page_size: 999, this.$refs.applyForm.dialogVisible = true
sort_name:'created_at', }
sort_type:'ASC',
filter: [{
key: 'course_id',
op: 'eq',
value: this.id
}]
})
this.courseSettings = res.data
},
deleteList(id,index){
if(id){
settingDestroy({
id: id,
}).then(response => {
this.courseSettings.splice(index,1)
}).catch(error => {
console.log(error)
reject(error)
})
}else{
this.courseSettings.splice(index,1)
}
},
// course_id
saveSetting(index){
console.log(this.courseSettings[index])
settingSave({
...this.courseSettings[index]
}).then(res => {
this.$message({
type: 'success',
message: this.courseSettings[index].id ? '修改成功' : '保存成功'
})
this.getSettingList()
})
},
// id
importSetting(course_id){
if(this.courseSettings.length>0){
this.courseSettings.map(item=>{
item.course_id = course_id
})
settingImport({
data:this.courseSettings
}).then(res => {
this.$message({
type: 'success',
message: '新增课程成功'
})
this.isShow = false
this.$emit('refresh')
})
}
}
}, },
watch: { watch: {
@ -388,14 +406,31 @@
if (newVal) { if (newVal) {
if (this.type === 'editor') { if (this.type === 'editor') {
this.getDetail() this.getDetail()
}else{ this.getFormList()
this.showTinymce = true } else {
this.showTinymce = true
} }
} else { } else {
this.id = '' this.id = ''
this.showTinymce = false this.showTinymce = false
this.imgList = [] this.imgList = []
this.courseSettings = [] this.publicizeList = []
this.active = 0
this.formList = []
this.form = {
step: '', //
name: '',
type: 1,
dateRange: '',
total: '',
status: 0,
is_arrange: 1,
is_fee: 1,
image_id: '',
publicize_ids: [],
content: '',
applylabel: ''
},
this.$refs['dialog'].reset() this.$refs['dialog'].reset()
} }
}, },
@ -406,7 +441,21 @@
<style scoped lang="scss"> <style scoped lang="scss">
::v-deep .content, ::v-deep .content,
::v-deep .settings { ::v-deep .step,
::v-deep .applylabel,
::v-deep .image_id,
::v-deep .publicize_ids {
flex-basis: 100%; flex-basis: 100%;
} }
::v-deep .status,
::v-deep .is_arrange,
::v-deep .is_fee,
{
flex-basis: 33%;
}
::v-deep .el-step.is-simple .el-step__head {
display: flex
}
</style> </style>

@ -0,0 +1,257 @@
<template>
<div>
<el-dialog title="创建报名表单" :visible.sync="dialogVisible" :fullscreen="true" :modal='false'>
<div style="height: 100%">
<Split v-model="splitL" :min="0.05">
<template #left>
<draggable v-model="types" :sort="false" :group="{ name: 'items', pull: 'clone', put: false }">
<div class="type-item" v-for="item in types">
{{ item.name }}
</div>
</draggable>
</template>
<template #right>
<Split v-model="splitR" :min="0.2">
<template #left>
<div style="height: 100%">
<el-dialog id="template-dialog" :title="'模板表单'"
style="position: relative; inset: 0 0 0 0; height: 100%" width="600px" top="40px" :visible="true"
:modal="false" :append-to-body="false" :modal-append-to-body="false">
<el-form style="min-height: 200px;" label-width="80px" label-position="right" size="small">
<draggable :value="formList" group="items" @change="changeHandler">
<el-form-item :label="i.name || '字段名称'" :required="
i.rule ? !!i.rule.includes('required') : false
" v-for="(i, index) in formList" @click.native="selectPick(i, index)">
<formSlotRender :config="i" :index="index"></formSlotRender>
</el-form-item>
</draggable>
</el-form>
<div slot="footer">
<div>
<el-button type="primary"> </el-button>
</div>
</div>
</el-dialog>
</div>
</template>
<template #right>
<editPane ref="editPane" @refreshFormItem="refreshItem" :rules="rules" :types="types"
@refresh="getFormList"></editPane>
</template>
</Split>
</template>
</Split>
</div>
</el-dialog>
</div>
</template>
<script>
import {
config
} from "@/api/system/customFormField";
import {
index
} from "@/api/course/form";
import {
deepCopy
} from "@/utils";
import editPane from "../components/editPane.vue";
import formSlotRender from "@/views/system/components/formSlotRender.vue";
export default {
components: {
formSlotRender,
editPane
},
data() {
return {
course_id: "",
select: {
page: 1,
page_size: 999,
sort_name: 'sort',
sort_type: 'ASC'
},
dialogVisible: false,
formList: [],
types: [],
rules: {},
//
splitL: 0.13,
splitR: 0.7,
selectedForm: {},
selectedIndex: 0,
}
},
created() {
this.getConfig()
},
methods: {
// formitem
async getConfig() {
const {
edit_to_migration,
validation_rules
} = await config(false);
this.rules = validation_rules;
this.types = edit_to_migration.filter(item => item.edit_input !== 'textarea' && item.edit_input !== "richtext"
&& item.edit_input !== "file" && item.edit_input !== "map");
},
//
async getFormList() {
const res = await index({
filter: [{
key: 'course_id',
op: 'eq',
value: this.course_id
}],
...this.select
})
this.formList = res.data
},
//
changeHandler(e) {
if (e.added) {
const {
element,
newIndex
} = e.added;
const originalData = element;
const newItem = {
id: "",
course_id: this.course_id,
field: "",
name: "",
parameter_id: "",
edit_input: originalData.edit_input,
sort: newIndex,
help: "",
rule: "",
select_item: []
};
this.formList.splice(newIndex, 0, newItem)
}
if (e.moved) {
const {
element,
newIndex,
oldIndex
} = e.moved;
element.sort = newIndex;
if (element) {
this.formList.splice(oldIndex, 1);
this.formList.splice(newIndex, 0, element);
}
}
},
//
selectPick(i, index) {
this.$refs.editPane.selectedIndex = index
this.$refs.editPane.selectedForm = deepCopy(i)
this.$refs.editPane.showForm = true
},
// item
refreshItem(e, index) {
// id
if (e === 'save' || e === 'DelId') {
this.getFormList()
} else if (e === 'Del') {
this.formList.splice(index, 1)
}
}
},
watch: {
dialogVisible(newval) {
if (newval) {
console.log("this.course_id", this.course_id)
} else {
this.course_id = ''
this.$emit("refresh")
}
}
},
}
</script>
<style scoped lang="scss">
.title {
font-weight: 600;
letter-spacing: 2px;
padding: 0 20px;
}
.type-item {
min-width: 40px;
overflow: hidden;
white-space: nowrap;
text-overflow: ellipsis;
cursor: pointer;
color: $primaryColor;
border: solid 1px $primaryColor;
border-radius: 10px;
position: relative;
transition: all 0.2s ease-out;
padding:10px;
margin: 6px;
&:hover {
color: #fff;
background: $primaryColor;
}
}
::v-deep .el-dialog__headerbtn {
position: absolute;
top: 50%;
transform: translateY(-50%);
}
::v-deep .el-dialog__header {
padding: 10px !important;
box-shadow: 0 2px 10px 2px rgba(0, 0, 0, 0.2);
position: relative;
}
::v-deep .el-dialog__body {
height: calc(100% - 62px);
padding: 8px 0 !important;
}
#template-dialog {
::v-deep .el-dialog__header {
box-shadow: none;
padding: 20px;
position: relative;
}
::v-deep .el-dialog__body {
padding: 30px 20px !important;
}
}
::v-deep .ivu-split-trigger-vertical {
width: 2px;
}
::v-deep .ivu-split-trigger-bar-con.vertical {
display: none;
}
::v-deep .ivu-split-horizontal>.ivu-split-trigger-con {
width: 2px;
}
::v-deep .ivu-split-pane {
height: 100%;
overflow: scroll;
&::-webkit-scrollbar {
width: 2px;
}
}
</style>

@ -0,0 +1,267 @@
<template>
<div style="padding: 0 10px; height: 100%; overflow: scroll">
<template v-if="showForm">
<el-form
:rules="formRule"
ref="form"
:model="selectedForm"
label-width="80px"
>
<el-form-item prop="name" label="字段名称">
<el-input
v-model="selectedForm.name"
placeholder="请输入字段名称"
@input="inputHandler"
></el-input>
</el-form-item>
<el-form-item required prop="field" label="字段标识">
<el-input v-model="selectedForm.field"></el-input>
</el-form-item>
<el-form-item prop="help" label="帮助文字">
<el-input
v-model="selectedForm.help"
placeholder="请输入帮助文字"
></el-input>
</el-form-item>
<el-form-item prop="sort" label="排序">
<el-input
v-model="selectedForm.sort"
placeholder="请输入排序"
></el-input>
</el-form-item>
<el-form-item prop="select_item" label="下拉框选项">
<div class="select-item">
<div class="select-item__header">
<span></span>
<span></span>
</div>
<div class="select-item__body" v-for="(i, index) in selectItem">
<div><el-input v-model="i.key" size="mini"></el-input></div>
<div><el-input v-model="i.value" size="mini"></el-input></div>
<div>
<el-button
type="danger"
size="mini"
circle
icon="el-icon-delete"
@click="selectItem.splice(index, 1)"
></el-button>
</div>
</div>
<el-button
type="primary"
size="mini"
circle
icon="el-icon-plus"
@click="selectItem.push({ key: '', value: '' })"
></el-button>
</div>
</el-form-item>
<el-form-item prop="validation" label="校验规则">
<el-select
v-model="validation"
clearable
multiple
collapse-tags
:popper-append-to-body="false"
placeholder="请选择校验规则"
style="width: 100%"
>
<el-option
v-for="(value, key) in rules"
:key="key"
:label="value"
:value="key"
></el-option>
</el-select>
</el-form-item>
<el-form-item>
<el-button type="primary" @click="saveField"></el-button>
<el-popover
trigger="hover"
ref="el-popover"
placement="top"
width="160"
>
<p>确定删除字段吗</p>
<div style="text-align: right; margin: 0">
<el-button
size="mini"
type="text"
@click="$refs['el-popover'].doClose()"
>取消</el-button
>
<el-button
type="primary"
size="mini"
@click="destroyField"
>确定</el-button
>
</div>
<el-button
type="danger"
slot="reference"
@click="$refs['el-popover'].doShow()"
style="margin-left: 10px"
>删除</el-button
>
</el-popover>
</el-form-item>
</el-form>
</template>
<template v-else>
<el-empty
style="position: relative; top: 50%; transform: translateY(-50%)"
description="暂无选择"
></el-empty>
</template>
</div>
</template>
<script>
import { save,destroy } from "@/api/course/form";
import { translate } from "@/api/system/customFormField";
import { debounce } from "@/utils";
export default {
props: {
rules: Object,
types: Array,
},
data() {
return {
showForm:false,
debouncedInputHandler: null,
formRule: {
name: [
{ required: true, message: "请输入字段名称" }
],
},
selectedForm:{}, // item
selectedIndex:0, // item index
selectItem: [], //
validation:[], //
parameters: [], //
forms: [], //
};
},
methods: {
checkChinese(rule, value, callback) {
const reg = /^[\u4e00-\u9fa5]+$/;
if (reg.test(value)) {
callback();
} else {
callback(new Error("请输入中文姓名"));
}
},
inputHandler(e) {
this.debouncedInputHandler(e);
},
saveField() {
this.selectedForm.select_item = []
this.selectItem.forEach(i => {
this.selectedForm.select_item[i.key] = i.value;
})
this.selectedForm.rule = this.validation.join(",")
console.log("this.selectedForm",this.selectedForm)
save(this.selectedForm).then(res=>{
console.log("res",res)
this.$Message.success('保存成功')
this.$emit("refreshFormItem",'save')
})
},
destroyField () {
if(this.selectedForm.id){
destroy({
id:this.selectedForm.id
}).then(res=>{
this.$Message.success('删除成功')
this.showForm = false
this.$emit("refreshFormItem",'DelId',this.selectedIndex)
})
}else{
this.$Message.success('删除成功')
this.showForm = false
this.$emit("refreshFormItem",'Del',this.selectedIndex)
}
}
},
watch: {
selectedForm(newVal) {
console.log("newval",newVal)
if(newVal) {
this.selectItem = [];
if(newVal.select_item && typeof newVal.select_item === "Array") {
for(let key in newVal.select_item) {
this.selectItem.push({
key,
value: newVal.select_item[key]
})
}
}
this.validation = []
if(newVal.rule){
this.validation = newVal.rule.split(',')
}
}
}
},
created() {
this.debouncedInputHandler = debounce((e) => {
if (e) {
this.checkChinese("", e, (err) => {
if (!err) {
translate({
str: e,
}).then((en) => {
this.selectedForm.field = en.pinyin;
});
}
});
}
}, 1000);
},
};
</script>
<style scoped lang="scss">
::v-deep .el-input-number.is-without-controls .el-input__inner {
text-align: left;
}
.select-item {
text-align: center;
&__header {
font-weight: 600;
display: flex;
& > span {
flex-basis: 30%;
& + span {
margin-left: 10px;
}
}
}
&__body {
display: flex;
& > div {
flex-basis: 30%;
& + div {
margin-left: 10px;
}
}
}
}
</style>

@ -187,6 +187,8 @@ export default {
const { edit_to_migration, validation_rules } = await config(false); const { edit_to_migration, validation_rules } = await config(false);
this.types = edit_to_migration; this.types = edit_to_migration;
this.rules = validation_rules; this.rules = validation_rules;
console.log("draggable",this.types)
}, },
selectPick(i, index) { selectPick(i, index) {
@ -289,6 +291,7 @@ export default {
async dialogVisible(newVal) { async dialogVisible(newVal) {
if (newVal) { if (newVal) {
await this.$store.dispatch("form/getFormList", this.custom_form_id); await this.$store.dispatch("form/getFormList", this.custom_form_id);
console.log("formList",this.$store.dispatch("form/getFormList", this.custom_form_id))
} }
}, },
}, },

@ -12,6 +12,7 @@ export default {
}, },
methods: { methods: {
optionsRender(h) { optionsRender(h) {
console.log("this.config",this.config)
if(this.config.edit_input === "checkbox" || this.config.edit_input === "radio") { if(this.config.edit_input === "checkbox" || this.config.edit_input === "radio") {
return ['选项1','选项2','选项3'].map(i => h('el-option',{ props: { value: i,label: i } })) return ['选项1','选项2','选项3'].map(i => h('el-option',{ props: { value: i,label: i } }))
} }
@ -44,15 +45,16 @@ export default {
computed: { computed: {
hiddenClass() { hiddenClass() {
let classArr = [] let classArr = []
if(!this.config.list_show && !this.config.form_show) {
// classArr.push('no-all-show')
}
if(!this.config.list_show && this.config.form_show) { if(!this.config.list_show && this.config.form_show) {
classArr.push('no-list-show') classArr.push('no-list-show')
} }
if(!this.config.form_show && this.config.list_show) { if(!this.config.form_show && this.config.list_show) {
classArr.push('no-form-show') classArr.push('no-form-show')
} }
if(!this.config.list_show && !this.config.form_show) {
classArr.push('no-all-show')
}
return classArr; return classArr;
} }
}, },

Loading…
Cancel
Save