736 lines
18 KiB
Vue
736 lines
18 KiB
Vue
<template>
|
||
<div class="add-form" v-if="pageShow">
|
||
<div class="header-pic">
|
||
<image v-if="form.headPicture" :src="form.headPicture"/>
|
||
<span @click="upload">更换图片</span>
|
||
</div>
|
||
<div class="form-info">
|
||
<h2>文本选项</h2>
|
||
<div class="form-info__wrapper">
|
||
<textarea class="title" placeholder="请输入标题 (必填)" :maxlength="30" :auto-height="true"
|
||
v-model="form.title"></textarea>
|
||
<textarea
|
||
class="content"
|
||
border="none"
|
||
:clearable="false"
|
||
type="textarea"
|
||
v-model="form.tableExplain"
|
||
placeholder="请输入表单描述 (选填)"
|
||
:maxlength="255">
|
||
</textarea>
|
||
</div>
|
||
</div>
|
||
<draggable
|
||
class="components-list"
|
||
v-model="targetList"
|
||
:animation="340"
|
||
scroll
|
||
element="div"
|
||
:options="{
|
||
filter: '.components-item__title--right',
|
||
animation: 340,
|
||
handle: '.components-item__title'
|
||
}"
|
||
draggable=".components-item"
|
||
:sort="true">
|
||
<div class="components-item" v-for="(item, index) in targetList" :key="index"
|
||
@click="toFiledSetting(item, index)">
|
||
<div class="components-item__title">
|
||
<div class="components-item__title--left">
|
||
<em :style="{opacity: item.required ? 1 : 0}">*</em>
|
||
<i>{{ index + 1 }}.</i>
|
||
<h2>{{ item.label }}</h2>
|
||
</div>
|
||
<image class="components-item__title--right" :src="`${$cdn}askform/sc1.png`" @click.stop="removeComponent(index)" />
|
||
</div>
|
||
<div class="components-item__filed">
|
||
<template v-if="(item.type === 'radio')">
|
||
<u-radio-group v-model="item.value" wrap>
|
||
<u-radio class="u-radio" disabled style="display: block;" v-for="(field, i) in item.options" :key="i">
|
||
<image :src="field.img[0].url" v-if="field.img.length"/>
|
||
<span>{{ field.label }}</span>
|
||
</u-radio>
|
||
</u-radio-group>
|
||
</template>
|
||
<template v-if="(item.type === 'checkbox')">
|
||
<u-checkbox-group v-model="item.value" wrap>
|
||
<u-checkbox class="u-checkbox" disabled :name="field.label" v-for="(field, i) in item.options" :key="i">
|
||
<image :src="field.img[0].url" v-if="field.img.length"/>
|
||
<span>{{ field.label }}</span>
|
||
</u-checkbox>
|
||
</u-checkbox-group>
|
||
</template>
|
||
<template v-if="(item.type === 'select')">
|
||
<div class="components-item__select">
|
||
<span>{{ item.placeholder }}</span>
|
||
<u-icon name="arrow-down" color="#DEDFDF"/>
|
||
</div>
|
||
</template>
|
||
<template v-if="(item.type === 'upload')">
|
||
<div class="components-item__select components-item__textarea components-item__upload">
|
||
<image :src="`${$cdn}askform/upload.png`"/>
|
||
<span>选择图片(10M以内)</span>
|
||
</div>
|
||
</template>
|
||
<template v-if="(item.type === 'input')">
|
||
<div class="components-item__select">
|
||
<span>{{ item.placeholder }}</span>
|
||
</div>
|
||
</template>
|
||
<template v-if="(item.type === 'textarea')">
|
||
<div class="components-item__select components-item__textarea">
|
||
<span>{{ item.placeholder }}</span>
|
||
</div>
|
||
</template>
|
||
</div>
|
||
</div>
|
||
</draggable>
|
||
<div class="add-form__btn" @click="isShow = true">
|
||
<image :src="`${$cdn}askform/add.png`"/>
|
||
<span>添加问题</span>
|
||
</div>
|
||
<div class="add-form__footer">
|
||
<div class="add-form__footer--item-wrapper">
|
||
<div class="add-form__footer--item" @click="toPreview">
|
||
<image :src="`${$cdn}sass/preview.png`"/>
|
||
<span>预览</span>
|
||
</div>
|
||
<div class="add-form__footer--item" @click="toSetting">
|
||
<image :src="`${$cdn}sass/setting.png`"/>
|
||
<span>设置</span>
|
||
</div>
|
||
</div>
|
||
<div @click="onConfirm">立即发布</div>
|
||
</div>
|
||
<u-popup v-model="isShow" :closeable="false" mode="bottom" @close="isShow = false">
|
||
<div class="add-popup">
|
||
<div class="add-popup__title">
|
||
<h2>添加问题</h2>
|
||
<image :src="`${$cdn}askform/zk.png`" mode="aspectFit" @click="isShow = false"/>
|
||
</div>
|
||
<div class="add-popup__list">
|
||
<span @click="toFiledSetting('radio')">单选题</span>
|
||
<span @click="toFiledSetting('checkbox')">多选题</span>
|
||
<span @click="toFiledSetting('select')">单下拉框</span>
|
||
<span @click="toFiledSetting('input')">单行填空</span>
|
||
<span @click="toFiledSetting('textarea')">多行填空</span>
|
||
<span @click="toFiledSetting('upload')">上传图片</span>
|
||
</div>
|
||
</div>
|
||
</u-popup>
|
||
</div>
|
||
</template>
|
||
|
||
<script>
|
||
import draggable from 'vuedraggable'
|
||
import qs from "query-string"
|
||
|
||
export default {
|
||
data() {
|
||
return {
|
||
pageShow: false,
|
||
form: {
|
||
tableExplain: '详细描述',
|
||
title: '问卷调查',
|
||
isShowheadPicture: true,
|
||
isShowTableExplain: true,
|
||
isShowBtn: true,
|
||
headPicture: '',
|
||
commitType: '1',
|
||
periodValidityType: '0',
|
||
actionNotice: '1',
|
||
dynamicNotice: '1',
|
||
periodValidityEndTime: '',
|
||
shareStatus: '0',
|
||
count: 0,
|
||
wechatId: '0',
|
||
type: 0,
|
||
buttonExplain: '提交',
|
||
tips: true
|
||
},
|
||
templateType: 0,
|
||
targetList: [],
|
||
isShow: false,
|
||
type: 0,
|
||
id: '',
|
||
filedType: '',
|
||
filed: {},
|
||
filedIndex: '',
|
||
isQuote: false,
|
||
touchStart: 0,
|
||
formConfig: {}
|
||
}
|
||
},
|
||
components: {
|
||
draggable,
|
||
},
|
||
created() {
|
||
let {type, isQuote, id} = this.$route.query
|
||
document.title = !id ? '新建表单' : '编辑表单'
|
||
this.type = type
|
||
this.isQuote = !!isQuote
|
||
if (id) {
|
||
this.id = id
|
||
this.getInfo(id)
|
||
} else {
|
||
this.pageShow = true
|
||
}
|
||
this.init()
|
||
uni.$on('setting', res => {
|
||
this.form = {
|
||
...this.form,
|
||
...res
|
||
}
|
||
this.formConfig = res
|
||
})
|
||
uni.$on('filedConfig', res => {
|
||
console.log(res)
|
||
if (res.index < 0) {
|
||
this.targetList.push(res.config)
|
||
} else {
|
||
this.targetList.splice(res.index, 1, res.config)
|
||
}
|
||
})
|
||
},
|
||
methods: {
|
||
toSetting() {
|
||
let {formConfig} = this
|
||
localStorage.setItem("toFormSetting", JSON.stringify(formConfig))
|
||
uni.navigateTo({url: `./FormSetting`})
|
||
},
|
||
back() {
|
||
uni.navigateBack({})
|
||
},
|
||
|
||
toPreview() {
|
||
let {form, targetList} = this
|
||
localStorage.setItem("toPreviewForm", JSON.stringify({form, targetList}))
|
||
uni.navigateTo({url: `./PreviewForm`})
|
||
},
|
||
|
||
upload() {
|
||
let params = {
|
||
count: 1,
|
||
sizeType: ['compressed'],
|
||
sourceType: ['album', 'camera'],
|
||
success: (res) => {
|
||
let count = this.fileList?.length + (res.tempFiles?.length || res.tempFile ? 1 : 0)
|
||
if (count > 1) {
|
||
return this.$u.toast(`不能超过1个`)
|
||
}
|
||
if (res.tempFiles) {
|
||
res.tempFiles.map((item) => {
|
||
this.uploadFile(item)
|
||
})
|
||
} else if (res?.tempFile) {
|
||
this.uploadFile(res.tempFile)
|
||
}
|
||
}
|
||
}
|
||
uni.chooseImage(params)
|
||
},
|
||
|
||
removeComponent(index) {
|
||
this.$confirm('确定删除该题', '').then(() => {
|
||
this.targetList.splice(index, 1)
|
||
}).catch(() => {})
|
||
},
|
||
|
||
uploadFile(img) {
|
||
uni.showLoading({title: '上传中'})
|
||
let formData = new FormData()
|
||
formData.append('file', img)
|
||
this.$http.post('/admin/file/add2', formData).then((res) => {
|
||
uni.hideLoading()
|
||
if (res?.data) {
|
||
this.$u.toast('上传成功!')
|
||
this.form.headPicture = res.data.url
|
||
}
|
||
}).catch(res => {
|
||
this.$u.toast(res)
|
||
uni.hideLoading()
|
||
})
|
||
},
|
||
|
||
onConfirm() {
|
||
for (let item of this.targetList) {
|
||
if (item.isShowPoints) {
|
||
if (item.pointType === '0') {
|
||
if (!item.answer || JSON.stringify(item.answer) === '[]') {
|
||
return this.$u.toast(`请输入${item.label}正确答案`)
|
||
}
|
||
|
||
if (!item.points) {
|
||
return this.$u.toast(`请输入${item.label}的分值`)
|
||
}
|
||
}
|
||
|
||
if (item.pointType === '1') {
|
||
for (let option of item.options) {
|
||
if (!option.point) {
|
||
return this.$u.toast(`请输入${item.label}${option.label}的分值`)
|
||
}
|
||
}
|
||
}
|
||
|
||
if (item.pointType === '2') {
|
||
for (let option of item.options) {
|
||
if (!option.point) {
|
||
return this.$u.toast(`请输入${item.label}${option.label}的分值`)
|
||
}
|
||
}
|
||
|
||
if (!item.points) {
|
||
return this.$u.toast(`请输入${item.label}全部答对分值`)
|
||
}
|
||
}
|
||
}
|
||
}
|
||
|
||
const fields = this.targetList.map(item => {
|
||
return {
|
||
fieldType: item.type,
|
||
fieldName: item.label,
|
||
fieldInfo: JSON.stringify(item)
|
||
}
|
||
})
|
||
|
||
this.$loading()
|
||
this.$http.post(`/app/appquestionnairetemplate/addOrUpdate`, {
|
||
...this.form,
|
||
fields,
|
||
status: 1,
|
||
id: this.isQuote ? '' : this.id,
|
||
headPicture: this.form.headPicture,
|
||
type: this.type,
|
||
templateType: 0
|
||
}).then(res => {
|
||
if (res?.code == 0) {
|
||
uni.navigateTo({
|
||
url: `./Result?${qs.stringify({
|
||
linkUrl: res.data.linkUrl,
|
||
title: this.form.title,
|
||
tableExplain: this.form.tableExplain,
|
||
headPicture: this.form.headPicture
|
||
})}`
|
||
})
|
||
}
|
||
|
||
uni.hideLoading()
|
||
}).catch(e => {
|
||
this.$u.toast(e)
|
||
uni.hideLoading()
|
||
})
|
||
},
|
||
|
||
getInfo(id) {
|
||
uni.showLoading()
|
||
this.$http.post(`/app/appquestionnairetemplate/queryDetailById?id=${id}`).then(res => {
|
||
if (res.code == 0) {
|
||
this.form = {
|
||
...res.data,
|
||
headPicture: res.data.headPicture
|
||
}
|
||
|
||
this.type = res.data.type
|
||
|
||
this.targetList = res.data.fields.map(item => {
|
||
return JSON.parse(item.fieldInfo)
|
||
})
|
||
|
||
this.pageShow = true
|
||
} else {
|
||
this.$u.toast(res.msg)
|
||
}
|
||
uni.hideLoading()
|
||
}).catch(() => {
|
||
uni.hideLoading()
|
||
})
|
||
},
|
||
|
||
toFiledSetting(type, index) {
|
||
this.isShow = false
|
||
if (index > -1) {
|
||
this.filed = type
|
||
this.filedIndex = index
|
||
localStorage.setItem("toFiledConfig", JSON.stringify({index, filed: type, filedType: type.type}))
|
||
} else {
|
||
this.filedIndex = ''
|
||
localStorage.setItem("toFiledConfig", JSON.stringify({filed: '', filedType: type, index: -1}))
|
||
}
|
||
uni.navigateTo({url: `./FiledConfig`})
|
||
},
|
||
|
||
init() {
|
||
if (this.type == 0) {
|
||
this.form.headPicture = 'https://cdn.cunwuyun.cn/dvcp/h5/form/interview.png'
|
||
}
|
||
if (this.type == 1) {
|
||
this.form.title = '考试测评'
|
||
this.form.headPicture = 'https://cdn.cunwuyun.cn/dvcp/h5/form/exam.png'
|
||
}
|
||
if (this.type == 2) {
|
||
this.form.title = '报名登记'
|
||
this.form.headPicture = 'https://cdn.cunwuyun.cn/dvcp/h5/form/apply.png'
|
||
}
|
||
if (this.type == 3) {
|
||
this.form.title = '满意调查'
|
||
this.form.headPicture = 'https://cdn.cunwuyun.cn/dvcp/h5/form/satisfaction.png'
|
||
}
|
||
if (this.type == 4) {
|
||
this.form.title = '投票评选'
|
||
this.form.headPicture = 'https://cdn.cunwuyun.cn/dvcp/h5/form/vote.png'
|
||
}
|
||
}
|
||
}
|
||
}
|
||
</script>
|
||
|
||
<style lang="scss" scoped>
|
||
.add-form {
|
||
min-height: 100vh;
|
||
padding-bottom: 140px;
|
||
box-sizing: border-box;
|
||
background: #F3F6F9;
|
||
|
||
* {
|
||
box-sizing: border-box;
|
||
}
|
||
|
||
.components-list {
|
||
padding: 0 20px;
|
||
|
||
.components-item {
|
||
margin-top: 24px;
|
||
padding: 32px;
|
||
box-shadow: 0 4px 8px 4px rgba(233, 233, 233, 0.39);
|
||
border-radius: 8px;
|
||
overflow: hidden;
|
||
border: 1px solid #EEEFF0;
|
||
background: #fff;
|
||
|
||
.u-checkbox, .u-radio {
|
||
display: block;
|
||
|
||
image {
|
||
width: 100px;
|
||
height: 100px;
|
||
margin: 0 10px;
|
||
}
|
||
}
|
||
|
||
::v-deep .u-radio, ::v-deep .u-checkbox {
|
||
position: relative;
|
||
margin-bottom: 20px;
|
||
|
||
&:last-child {
|
||
margin-bottom: 0;
|
||
}
|
||
|
||
.u-checkbox__icon-wrap, .u-radio__icon-wrap {
|
||
position: absolute;
|
||
top: 4px;
|
||
}
|
||
|
||
.u-radio__label, .u-checkbox__label {
|
||
display: flex;
|
||
align-items: center;
|
||
margin-right: 0;
|
||
margin-left: 40px;
|
||
text-align: justify;
|
||
|
||
span {
|
||
line-height: 1.5;
|
||
}
|
||
}
|
||
}
|
||
|
||
span {
|
||
flex: 1;
|
||
color: #666;
|
||
font-size: 26px;
|
||
}
|
||
|
||
.components-item__select {
|
||
display: flex;
|
||
align-items: center;
|
||
justify-content: space-between;
|
||
width: 100%;
|
||
height: 80px;
|
||
margin-bottom: 8px;
|
||
padding: 0 26px;
|
||
border: 1px solid #DEDFDF;
|
||
|
||
&.components-item__textarea {
|
||
align-items: flex-start;
|
||
height: 160px;
|
||
padding-top: 20px;
|
||
|
||
image {
|
||
width: 46px;
|
||
height: 34px;
|
||
margin-right: 16px;
|
||
}
|
||
|
||
span {
|
||
color: #666;
|
||
font-size: 26px;
|
||
}
|
||
}
|
||
|
||
&.components-item__upload {
|
||
justify-content: center;
|
||
align-items: center;
|
||
}
|
||
}
|
||
|
||
.components-item__title {
|
||
display: flex;
|
||
align-items: center;
|
||
justify-content: space-between;
|
||
margin-bottom: 32px;
|
||
|
||
em {
|
||
margin-right: 4px;
|
||
font-style: normal;
|
||
color: rgb(226, 33, 32);;
|
||
}
|
||
|
||
image {
|
||
position: relative;
|
||
flex-shrink: 1;
|
||
right: 0;
|
||
width: 32px;
|
||
height: 32px;
|
||
box-sizing: content-box;
|
||
padding: 30px 20px 30px 50px;
|
||
}
|
||
|
||
div {
|
||
display: flex;
|
||
align-items: baseline;
|
||
max-width: 550px;
|
||
color: #333333;
|
||
font-size: 32px;
|
||
|
||
i {
|
||
font-style: normal;
|
||
}
|
||
|
||
h2 {
|
||
font-weight: 600;
|
||
font-size: 32px;
|
||
}
|
||
}
|
||
}
|
||
}
|
||
}
|
||
|
||
.add-popup {
|
||
height: 440px;
|
||
border-radius: 20px 20px 0 0;
|
||
background: #fff;
|
||
|
||
.add-popup__title {
|
||
display: flex;
|
||
position: relative;
|
||
align-items: center;
|
||
justify-content: center;
|
||
height: 96px;
|
||
border-bottom: 1px solid #E4E5E6;
|
||
|
||
h2 {
|
||
color: #333333;
|
||
font-size: 32px;
|
||
font-weight: 600;
|
||
}
|
||
|
||
image {
|
||
position: absolute;
|
||
right: 32px;
|
||
top: 50%;
|
||
width: 30px;
|
||
height: 20px;
|
||
transform: translateY(-50%);
|
||
}
|
||
}
|
||
|
||
.add-popup__list {
|
||
display: flex;
|
||
flex-wrap: wrap;
|
||
padding: 0 34px;
|
||
|
||
span {
|
||
width: calc((100% - 64px) / 3);
|
||
height: 78px;
|
||
line-height: 78px;
|
||
margin-top: 32px;
|
||
margin-right: 32px;
|
||
text-align: center;
|
||
color: #333333;
|
||
font-size: 28px;
|
||
border-radius: 8px;
|
||
border: 1px solid #E4E5E6;
|
||
|
||
&:nth-of-type(3n) {
|
||
margin-right: 0;
|
||
}
|
||
}
|
||
}
|
||
}
|
||
|
||
.add-form__footer {
|
||
display: flex;
|
||
align-items: center;
|
||
position: fixed;
|
||
left: 0;
|
||
bottom: 0;
|
||
z-index: 1;
|
||
width: 100%;
|
||
height: 112px;
|
||
text-align: center;
|
||
|
||
& > div {
|
||
display: flex;
|
||
align-items: center;
|
||
justify-content: center;
|
||
flex: 1;
|
||
height: 100%;
|
||
text-align: center;
|
||
background: #fff;
|
||
|
||
&:last-child {
|
||
color: #fff;
|
||
font-size: 36px;
|
||
background: #3192F4;
|
||
|
||
&:active {
|
||
opacity: 0.8;
|
||
}
|
||
}
|
||
|
||
span {
|
||
}
|
||
}
|
||
}
|
||
|
||
.add-form__footer--item-wrapper {
|
||
.add-form__footer--item {
|
||
display: flex;
|
||
align-items: center;
|
||
flex-direction: column;
|
||
flex: 1;
|
||
|
||
image {
|
||
display: block;
|
||
width: 48px;
|
||
height: 48px;
|
||
margin: 0 auto;
|
||
}
|
||
|
||
span {
|
||
display: block;
|
||
text-align: center;
|
||
color: #999;
|
||
font-size: 28px;
|
||
|
||
&:active {
|
||
background: #eee;
|
||
}
|
||
}
|
||
}
|
||
}
|
||
|
||
.add-form__btn {
|
||
display: flex;
|
||
align-items: center;
|
||
justify-content: center;
|
||
width: 214px;
|
||
height: 66px;
|
||
line-height: 66px;
|
||
margin: 64px auto 0;
|
||
background: #FFFFFF;
|
||
border-radius: 34px;
|
||
|
||
&:active {
|
||
opacity: 0.8;
|
||
}
|
||
|
||
image {
|
||
width: 28px;
|
||
height: 28px;
|
||
}
|
||
|
||
span {
|
||
margin-left: 16px;
|
||
color: #4392E6;
|
||
font-size: 28px;
|
||
}
|
||
}
|
||
|
||
* {
|
||
box-sizing: border-box;
|
||
}
|
||
|
||
.form-info {
|
||
padding: 0 20px;
|
||
|
||
& > h2 {
|
||
height: 76px;
|
||
line-height: 76px;
|
||
color: #999999;
|
||
font-weight: normal;
|
||
font-size: 28px;
|
||
}
|
||
|
||
.form-info__wrapper {
|
||
padding: 0 18px;
|
||
background: #fff;
|
||
|
||
.title {
|
||
width: 100%;
|
||
padding: 22px 0;
|
||
font-size: 36px;
|
||
border-bottom: 1px solid #F1F2F3;
|
||
}
|
||
|
||
.content {
|
||
width: 100%;
|
||
padding: 30px 0 !important;
|
||
color: #333;
|
||
font-size: 28px !important;
|
||
}
|
||
}
|
||
}
|
||
|
||
.header-pic {
|
||
position: relative;
|
||
font-size: 0;
|
||
|
||
span {
|
||
position: absolute;
|
||
bottom: 16px;
|
||
right: 16px;
|
||
z-index: 1;
|
||
width: 148px;
|
||
height: 56px;
|
||
line-height: 56px;
|
||
text-align: center;
|
||
color: #fff;
|
||
font-size: 26px;
|
||
background: rgba(0, 0, 0, 0.16);
|
||
border-radius: 28px;
|
||
}
|
||
|
||
image {
|
||
width: 100%;
|
||
height: 320px;
|
||
}
|
||
}
|
||
|
||
::v-deep .u-radio, ::v-deep .u-checkbox {
|
||
align-items: baseline;
|
||
}
|
||
}
|
||
</style>
|