535 lines
14 KiB
Vue
535 lines
14 KiB
Vue
<template>
|
|
<div class="form-config">
|
|
<div class="config-group">
|
|
<div class="config-item">
|
|
<u-input class="form-maintitle" :maxlength="200" v-model="config.label"
|
|
:placeholder="`请输入${config.fixedLabel||''}标题 ${config.required ? '(必填)' : ''}`"
|
|
placeholder-style="color: #999999; font-weight: 600"/>
|
|
</div>
|
|
<div class="config-item__select--wrapper" v-if="['radio', 'select', 'checkbox'].includes(config.type)">
|
|
<div class="config-item__select" v-for="(item, index) in config.options" :key="index">
|
|
<image class="config-icon" :src="`${$cdn}askform/del.png`" @click="removeOptions(index)"/>
|
|
<div class="config-item__upload" v-if="config.type !== 'select'" @click="upload(index)">
|
|
<u-icon color="#8c9dc3" name="plus" v-if="!item.img.length"></u-icon>
|
|
<image v-else :src="item.img[0].url"/>
|
|
</div>
|
|
<div class="textarea">
|
|
<textarea type="textarea" placeholder-style="color: #CDCDCF" :auto-height="true" v-model="item.label"
|
|
:maxlength="100" placeholder="请输入选项"/>
|
|
</div>
|
|
</div>
|
|
<div class="config-item__select config-item__select--add" @click="addOptions">
|
|
<image class="config-icon" :src="`${$cdn}askform/zj.png`"/>
|
|
<span>添加选项</span>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
<div class="config-group">
|
|
<div class="config-item" v-if="!['radio', 'upload', 'checkbox', 'select'].includes(config.type)">
|
|
<div class="config-item__left">
|
|
<span>说明文字</span>
|
|
</div>
|
|
<div class="config-item__right">
|
|
<u-input v-model="config.placeholder" placeholder="请输入说明文字" input-align="right"/>
|
|
</div>
|
|
</div>
|
|
<div class="config-item">
|
|
<div class="config-item__left">
|
|
<span>是否必填</span>
|
|
</div>
|
|
<div class="config-item__right">
|
|
<u-switch v-model="config.required" active-value="1" inactive-value="0" :size="40"
|
|
active-color="#1088F9"></u-switch>
|
|
</div>
|
|
</div>
|
|
<div class="config-item" v-if="!['upload'].includes(config.type)">
|
|
<div class="config-item__left">
|
|
<span>答案与分值</span>
|
|
</div>
|
|
<div class="config-item__right">
|
|
<u-switch v-model="config.isShowPoints" :size="40" active-color="#1088F9"></u-switch>
|
|
</div>
|
|
</div>
|
|
<div class="config-item" v-if="['input', 'textarea'].includes(config.type) && config.isShowPoints">
|
|
<div class="config-item__left">
|
|
<span>正确答案</span>
|
|
</div>
|
|
<div class="config-item__right">
|
|
<u-input v-model="config.answer" placeholder="请输入正确答案" input-align="right"/>
|
|
</div>
|
|
</div>
|
|
<div class="config-item"
|
|
v-if="['radio', 'select'].includes(config.type) && config.isShowPoints && config.pointType === '0'">
|
|
<div class="config-item__left">
|
|
<span>正确答案</span>
|
|
</div>
|
|
<div class="config-item__right config-item__text" @click="isShowAnswer = true">
|
|
<span>{{ config.answer ? config.answer : '请选择正确答案' }}</span>
|
|
<u-icon name="arrow-down-fill" color="#c0c4cc" size="24"></u-icon>
|
|
</div>
|
|
</div>
|
|
<div class="config-item config-item__checkbox"
|
|
v-if="config.isShowPoints && ['radio', 'select', 'checkbox'].includes(config.type)">
|
|
<div class="config-item__left">
|
|
<span>计分方式</span>
|
|
</div>
|
|
<div class="config-item__right" @click="isShowType = true">
|
|
<span>{{ pointTypeName ? pointTypeName : '请选择' }}</span>
|
|
<u-icon name="arrow-right" color="#E1E2E3"/>
|
|
</div>
|
|
</div>
|
|
<div class="config-item config-item__answer config-item__checkbox"
|
|
v-if="['checkbox'].includes(config.type) && config.isShowPoints && config.pointType === '0'">
|
|
<div class="config-item__left">
|
|
<span>正确答案</span>
|
|
</div>
|
|
<div class="config-item__right">
|
|
<u-checkbox-group wrap @change="onCheckboxChange">
|
|
<u-checkbox v-model="field.checked" :name="field.label" v-if="field.label"
|
|
v-for="(field, i) in config.options" :key="i">
|
|
<span>{{ field.label }}</span>
|
|
</u-checkbox>
|
|
</u-checkbox-group>
|
|
</div>
|
|
</div>
|
|
<div class="config-item" v-if="config.isShowPoints && config.pointType === '0'">
|
|
<div class="config-item__left">
|
|
<span>本题分值</span>
|
|
</div>
|
|
<div class="config-item__right">
|
|
<u-input v-model="config.points" type="number" placeholder="请输入本题分值" input-align="right"/>
|
|
</div>
|
|
</div>
|
|
<div v-if="config.isShowPoints && config.pointType === '1'">
|
|
<div class="config-item" v-for="(item, index) in config.options" :key="index">
|
|
<div class="config-item__left">
|
|
<span>{{ item.label }}</span>
|
|
</div>
|
|
<div class="config-item__right">
|
|
<u-input v-model="item.point" placeholder="请输入分值" input-align="right"/>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
<div class="config-item config-item__point" v-if="config.isShowPoints && config.pointType === '2'">
|
|
<u-checkbox-group wrap @change="onCheckboxChange">
|
|
<u-checkbox v-model="field.checked" :name="field.label" v-if="field.label"
|
|
v-for="(field, i) in config.options" :key="i">
|
|
<span>{{ field.label }}</span>
|
|
<u-input v-model="field.point" type="number" placeholder="请输入分值" input-align="right"/>
|
|
</u-checkbox>
|
|
</u-checkbox-group>
|
|
</div>
|
|
<div class="config-item" v-if="config.isShowPoints && config.pointType === '2'">
|
|
<div class="config-item__left" style="padding-left: 20px">
|
|
<span>全部答对</span>
|
|
</div>
|
|
<div class="config-item__right">
|
|
<u-input v-model="config.points" type="number" placeholder="请输入全部答对分值" input-align="right"/>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
<u-select :list="config.options" :default-value="defaultAnswer" value-name="value" label-name="label"
|
|
v-model="isShowAnswer" @confirm="answerChange"></u-select>
|
|
<u-select :list="config.pointDict" :default-value="defaultType" value-name="dictValue" label-name="dictName"
|
|
v-model="isShowType" @confirm="pointTypeChange"></u-select>
|
|
<div class="add-form__footer">
|
|
<div @click="back">
|
|
<span>取消</span>
|
|
</div>
|
|
<div @click="confirm">确定</div>
|
|
</div>
|
|
</div>
|
|
</template>
|
|
|
|
<script>
|
|
import {components} from './components/config'
|
|
|
|
export default {
|
|
data() {
|
|
let params = localStorage.getItem("toFiledConfig") || {}
|
|
if (params) {
|
|
params = JSON.parse(params)
|
|
params.config = params.index > -1 ? params.filed : JSON.parse(JSON.stringify(components.filter(v => v.type === params.filedType)[0]))
|
|
localStorage.removeItem("toFiledConfig")
|
|
}
|
|
return {
|
|
...params,
|
|
isShowType: false,
|
|
isShowAnswer: false
|
|
}
|
|
},
|
|
computed: {
|
|
pointTypeName() {
|
|
if (!this.config.pointDict) return ''
|
|
|
|
return this.config.pointDict.filter(v => v.dictValue === this.config.pointType)[0].dictName
|
|
},
|
|
defaultType() {
|
|
if (!this.config.pointType) return [0]
|
|
|
|
return [Number(this.config.pointType)]
|
|
},
|
|
defaultAnswer() {
|
|
if (!this.config.answer) return [0]
|
|
let index = 0
|
|
if (this.config.answer) {
|
|
this.config.options?.forEach((v, i) => {
|
|
if (v.label === this.config.answer) {
|
|
index = i
|
|
}
|
|
})
|
|
}
|
|
|
|
return [index]
|
|
}
|
|
},
|
|
methods: {
|
|
answerChange(e) {
|
|
this.config.answer = e[0].label
|
|
},
|
|
|
|
pointTypeChange(e) {
|
|
this.config.pointType = e[0].value
|
|
},
|
|
|
|
onCheckboxChange(e) {
|
|
this.config.answer = e
|
|
},
|
|
|
|
upload(index) {
|
|
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, index)
|
|
})
|
|
}
|
|
}
|
|
}
|
|
uni.chooseImage(params)
|
|
},
|
|
|
|
uploadFile(img, index) {
|
|
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.$set(this.config.options[index], 'img', [res.data])
|
|
}
|
|
}).catch(res => {
|
|
this.$u.toast(res)
|
|
uni.hideLoading()
|
|
})
|
|
},
|
|
|
|
removeOptions(index) {
|
|
const len = this.config.options.length
|
|
const label = this.config.options[index].label
|
|
if (len === 2) {
|
|
return this.$u.toast('选项不能少于2个')
|
|
}
|
|
|
|
if (this.config.type === 'checkbox') {
|
|
const answerIndex = this.config.answer.indexOf(label)
|
|
if (answerIndex > -1) {
|
|
this.config.answer.splice(answerIndex, 1)
|
|
}
|
|
} else {
|
|
if (label === this.config.answer) {
|
|
this.config.answer = ''
|
|
}
|
|
}
|
|
|
|
this.config.options.splice(index, 1)
|
|
},
|
|
|
|
back() {
|
|
uni.navigateBack({})
|
|
},
|
|
|
|
confirm() {
|
|
uni.$emit('filedConfig', {
|
|
config: this.config,
|
|
index: this.index === '' ? '-1' : this.index
|
|
})
|
|
this.back()
|
|
},
|
|
|
|
addOptions() {
|
|
const len = this.config.options.length
|
|
let label = `选项${len + 1}`
|
|
|
|
const index = this.config.options.findIndex(v => label === v.label)
|
|
if (index > -1) {
|
|
label = `新选项${len + 1}`
|
|
}
|
|
|
|
this.config.options.push({
|
|
label: label,
|
|
value: '',
|
|
point: '',
|
|
img: '',
|
|
checked: false
|
|
})
|
|
},
|
|
}
|
|
}
|
|
</script>
|
|
|
|
<style lang="scss" scoped>
|
|
.form-config {
|
|
box-sizing: border-box;
|
|
padding-bottom: 130px;
|
|
|
|
.form-maintitle {
|
|
::v-deep .uni-input-input {
|
|
font-size: 36px;
|
|
font-weight: 600;
|
|
}
|
|
}
|
|
|
|
.config-item__select--wrapper {
|
|
.config-item__select {
|
|
display: flex;
|
|
align-items: center;
|
|
|
|
::v-deep .u-input__input {
|
|
height: 100%;
|
|
}
|
|
|
|
.textarea {
|
|
flex: 1;
|
|
display: flex;
|
|
align-items: center;
|
|
min-height: 104px;
|
|
padding: 16px 0;
|
|
font-size: 28px;
|
|
border-bottom: 1px solid #dfe8f8;
|
|
}
|
|
|
|
textarea {
|
|
width: 100%;
|
|
font-size: 28px;
|
|
}
|
|
|
|
.config-icon {
|
|
width: 36px;
|
|
height: 36px;
|
|
margin-right: 12px;
|
|
}
|
|
}
|
|
|
|
.config-item__select--add {
|
|
height: 120px;
|
|
|
|
.config-icon {
|
|
margin-right: 18px;
|
|
}
|
|
|
|
span {
|
|
color: #1D74F4;
|
|
font-size: 30px;
|
|
}
|
|
}
|
|
}
|
|
|
|
.config-group {
|
|
margin-bottom: 32px;
|
|
padding: 0 32px;
|
|
background: #fff;
|
|
|
|
.config-item__upload {
|
|
display: flex;
|
|
align-items: center;
|
|
justify-content: center;
|
|
width: 60px;
|
|
height: 60px;
|
|
margin-right: 20px;
|
|
border: 1px solid rgb(208, 212, 220);
|
|
background-color: #fbfdff;
|
|
|
|
image {
|
|
width: 100%;
|
|
height: 100%;
|
|
}
|
|
}
|
|
|
|
.config-item {
|
|
display: flex;
|
|
align-items: center;
|
|
justify-content: space-between;
|
|
min-height: 100px;
|
|
padding: 16px 0;
|
|
border-bottom: 1px solid #dfe8f8;
|
|
|
|
&:last-child {
|
|
border: none;
|
|
}
|
|
|
|
::v-deep .u-radio__label, ::v-deep .u-checkbox__label {
|
|
margin-right: 0;
|
|
font-size: 28px;
|
|
|
|
span {
|
|
max-width: 400 rpx;
|
|
line-height: 1.2;
|
|
}
|
|
}
|
|
|
|
.config-item__left {
|
|
max-width: 400px;
|
|
}
|
|
|
|
.config-item__right {
|
|
flex: 1;
|
|
text-align: right;
|
|
padding-left: 30px;
|
|
|
|
&.config-item__text {
|
|
display: flex;
|
|
align-items: center;
|
|
justify-content: flex-end;
|
|
|
|
span {
|
|
max-width: 400px;
|
|
margin-right: 10px;
|
|
overflow: hidden;
|
|
text-overflow: ellipsis;
|
|
white-space: nowrap;
|
|
word-break: keep-all;
|
|
}
|
|
}
|
|
|
|
.text {
|
|
}
|
|
}
|
|
|
|
&.config-item__answer {
|
|
display: block;
|
|
padding: 20px 0;
|
|
|
|
.config-item__left {
|
|
margin-bottom: 32 rpx;
|
|
|
|
span {
|
|
word-break: break-all;
|
|
color: #333;
|
|
font-size: 30px;
|
|
}
|
|
}
|
|
|
|
.config-item__right {
|
|
width: 100%;
|
|
padding-left: 0;
|
|
text-align: left;
|
|
}
|
|
}
|
|
}
|
|
|
|
::v-deep .u-checkbox {
|
|
align-items: baseline;
|
|
}
|
|
|
|
.config-item__checkbox {
|
|
height: auto;
|
|
padding: 14px 0;
|
|
|
|
::v-deep .u-checkbox, ::v-deep .u-radio {
|
|
// justify-content: flex-end;
|
|
}
|
|
}
|
|
|
|
.config-item__point {
|
|
height: auto;
|
|
padding: 0;
|
|
|
|
::v-deep .u-checkbox {
|
|
justify-content: inherit;
|
|
min-height: 100px;
|
|
padding: 14px 0;
|
|
border-bottom: 1px solid #eee;
|
|
|
|
&:last-child {
|
|
border: none;
|
|
}
|
|
|
|
.u-checkbox__label {
|
|
display: flex;
|
|
align-items: center;
|
|
justify-content: space-between;
|
|
flex: 1;
|
|
margin-right: 0;
|
|
|
|
.u-input {
|
|
flex: 1;
|
|
max-width: 400px;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
* {
|
|
box-sizing: border-box;
|
|
}
|
|
|
|
.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;
|
|
|
|
&:first-child:active {
|
|
background: #eee;
|
|
}
|
|
|
|
&:last-child {
|
|
color: #fff;
|
|
font-size: 36px;
|
|
background: #3192F4;
|
|
|
|
&:active {
|
|
opacity: 0.8;
|
|
}
|
|
}
|
|
|
|
span {
|
|
flex: 1;
|
|
height: 100%;
|
|
line-height: 112px;
|
|
color: #333333;
|
|
font-size: 32px;
|
|
|
|
&:active {
|
|
background: #eee;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
</style>
|