调查问卷

This commit is contained in:
yanran200730
2021-11-23 11:51:14 +08:00
parent 2ccd572a11
commit 2fba037d57
10 changed files with 325 additions and 215 deletions

View File

@@ -1,69 +1,57 @@
<template>
<div class="form">
<div class="form-content">
<add-list ref="addList" v-if="currIndex === 1"></add-list>
<list ref="list" v-if="currIndex === 0"></list>
</div>
<ai-tabbar :active.sync="currIndex" :list="tabBar"/>
<div class="form-footer"></div>
<component
:is="component"
@change="onChange"
:params="params">
</component>
</div>
</template>
<script>
import addList from './components/addList.vue'
import list from './components/list.vue'
import AiTabbar from '../../components/AiTabbar'
import Tabbar from './components/Tabbar.vue'
import AddForm from './components/AddForm.vue'
export default {
name: 'AppAskForm',
appName: '问卷表单',
export default {
name: 'AppAskForm',
appName: '问卷表单',
data () {
return {
currIndex: 0
}
},
components: {
addList,
AiTabbar,
list
},
computed: {
tabBar () {
const link = icon => `${this.$cdn}askform/${icon}.png`
return [
{text: "表单列表", iconPath: "bdlb1", selectedIconPath: "bdlb2" },
{text: "新建项目", iconPath: "xjxm1", selectedIconPath: "xjxm2" }
].map(e => ({
...e,
iconPath: link(e.iconPath),
selectedIconPath: link(e.selectedIconPath)
}))
}
},
onLoad () {
uni.$on('reload', () => {
if (this.currIndex === 0) {
this.$refs.list.reload()
} else {
this.$refs.addList.getList()
data () {
return {
component: 'Tabbar',
params: {}
}
})
},
},
onReachBottom() {
if (this.currIndex === 0) {
this.$refs.list.getList()
components: {
Tabbar,
AddForm
},
onLoad () {
uni.$on('reload', () => {
if (this.currIndex === 0) {
this.$refs.list.reload()
} else {
this.$refs.addList.getList()
}
})
},
methods: {
onChange (e) {
this.params = e.params
this.component = e.type
},
},
onReachBottom() {
if (this.currIndex === 0) {
this.$refs.list.getList()
}
}
}
}
</script>
<style lang="scss" scoped>
.form {
padding-bottom: 98px;
}
</style>

View File

@@ -1,117 +1,137 @@
<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>
<u-input class="content" :clearable="false" type="textarea" v-model="form.tableExplain" placeholder="请输入表单描述 (选填)" :height="80" :auto-height="true" :maxlength="255"></u-input>
<div v-show="!isShowConfig">
<div class="header-pic">
<image v-if="form.headPicture" :src="form.headPicture" />
<span @click="upload">更换图片</span>
</div>
</div>
<draggable
class="components-list"
v-model="targetList"
:animation="340"
scroll
element="div"
:options="{
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 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
style="wdith: 100%"
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="{
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 :src="`${$cdn}askform/sc1.png`" @click.stop="removeComponent(index)" @touchstart.stop="removeComponent(index)" />
</div>
<div class="components-item__filed">
<template v-if="(item.type === 'radio')">
<radio-group v-model="item.value">
<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>
</radio>
</radio-group>
</template>
<template v-if="(item.type === 'checkbox')">
<checkbox-group v-model="item.value" wrap>
<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>
</checkbox>
</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>选择图片2M以内</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>
<image :src="`${$cdn}askform/sc1.png`" @click.stop="removeComponent(index)" @touchstart.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 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-radio>
</u-radio-group>
</template>
<template v-if="(item.type === 'checkbox')">
<u-checkbox-group v-model="item.value" wrap>
<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>选择图片2M以内</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>
</draggable>
<div class="add-form__btn" @click="isShow = true">
<image :src="`${$cdn}askform/add.png`" />
<span>添加问题</span>
</div>
</draggable>
<div class="add-form__btn" @click="isShow = true">
<image :src="`${$cdn}askform/add.png`" />
<span>添加问题</span>
<div class="add-form__footer">
<div>
<span @click="toPreview">预览</span>
<span @click="toSetting">设置</span>
</div>
<div @click="onConfirm">立即发布</div>
</div>
<u-popup :show="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>
<AiBack custom @back="back"></AiBack>
</div>
<div class="add-form__footer">
<div>
<span @click="toPreview">预览</span>
<span @click="toSetting">设置</span>
</div>
<div @click="onConfirm">立即发布</div>
<div class="detail" v-if="isShowConfig">
<component :is="component" @change="onChange" @back="isShowConfig = false" :id="id" :type="type" :formConfig="formConfig"></component>
</div>
<u-popup v-model="isShow" :closeable="false" mode="bottom">
<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>
<AiBack></AiBack>
</div>
</template>
<script>
import AiBack from "@/components/AiBack";
import draggable from 'vuedraggable'
import FiledConfig from './FiledConfig'
import FormSetting from './FormSetting'
export default {
props: ['params'],
data () {
return {
pageShow: false,
isShowConfig: false,
form: {
tableExplain: '详细描述',
title: '问卷调查',
@@ -138,28 +158,32 @@
id: '',
isQuote: false,
touchStart: 0,
component: '',
formConfig: {}
}
},
components: {
AiBack,
draggable
draggable,
FormSetting,
// FiledConfig
},
onLoad (query) {
this.type = Number(query.type)
mounted () {
this.type = Number(this.params.type)
if (query.isQuote) {
if (this.params.isQuote) {
this.isQuote = true
}
if (query.id) {
this.id = query.id
this.getInfo(query.id)
if (this.params.id) {
this.id = this.params.id
this.getInfo(this.params.id)
} else {
this.pageShow = true
}
this.init()
uni.$on('setting', res => {
@@ -181,11 +205,23 @@
methods: {
toSetting () {
uni.navigateTo({
url: `/pages/askForm/formSetting?id=${this.id}&formConfig=${JSON.stringify(this.formConfig)}`
// uni.navigateTo({
// url: `/pages/askForm/formSetting?id=${this.id}&formConfig=${JSON.stringify(this.formConfig)}`
// })
this.component = 'FormSetting'
this.isShowConfig = true
},
back () {
this.$emit('change', {
type: 'Tabbar'
})
},
onChange (e) {
},
removeComponent (index) {
this.targetList.splice(index, 1)
},
@@ -394,6 +430,15 @@
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;
@@ -417,12 +462,6 @@
span {
line-height: 1.5;
}
image {
width: 100px;
height: 100px;
margin: 0 10px;
}
}
}
span {
@@ -657,13 +696,10 @@
}
.content {
width: 100%;
padding: 30px 0!important;
font-size: 28px;
::v-deep textarea {
color: #333;
font-size: 28px!important;
}
color: #333;
font-size: 28px!important;
}
}
}

View File

@@ -9,8 +9,8 @@
</div>
<div class="setting-item__right">
<u-radio-group v-model="periodValidityType" active-color="#1088F9">
<u-radio name="0">永久有效</u-radio>
<u-radio name="1">自定义时间</u-radio>
<u-radio name="0" label="永久有效" style="padding-right: 20rpx;"></u-radio>
<u-radio name="1" label="自定义时间"></u-radio>
</u-radio-group>
<u-icon name="arrow-right" color="#E1E2E3" />
</div>
@@ -40,8 +40,8 @@
</div>
<div class="setting-item__right">
<u-radio-group v-model="commitType" active-color="#1088F9">
<u-radio name="0">不限次数</u-radio>
<u-radio name="1">限提交一次</u-radio>
<u-radio name="0" label="不限次数" style="padding-right: 20rpx;"></u-radio>
<u-radio name="1" label="限提交一次"></u-radio>
</u-radio-group>
</div>
</div>
@@ -51,7 +51,7 @@
<image :src="`${$cdn}askform/bz.png`" @click="tips = '当客户点击或者发布表单时,发送表单的员工将会受到消息提醒' , isShowModal = true" />
</div>
<div class="setting-item__right">
<u-switch v-model="actionNotice" active-value="1" inactive-value="0" :size="40" active-color="#1088F9"></u-switch>
<u-switch v-model="actionNotice" active-value="1" :size="20" active-color="#1088F9"></u-switch>
</div>
</div>
<div class="setting-item">
@@ -60,7 +60,7 @@
<image :src="`${$cdn}askform/bz.png`" @click="tips = '当客户点击或者发布表单时,会将客户的打开行为记录在客户动态里' , isShowModal = true" />
</div>
<div class="setting-item__right">
<u-switch v-model="dynamicNotice" active-value="1" inactive-value="0" :size="40" active-color="#1088F9"></u-switch>
<u-switch v-model="dynamicNotice" active-value="1" :size="20" active-color="#1088F9"></u-switch>
</div>
</div>
</div>
@@ -70,23 +70,25 @@
</div>
<div @click="confirm">{{ type === 'edit' ? '发布' : '确定' }}</div>
</div>
<u-modal v-model="isShowModal" :content="tips"></u-modal>
<u-picker mode="time" v-model="isShowTime" :show-time-tag="true" @confirm="onTimeChange" :params="params"></u-picker>
<u-modal :show="isShowModal" :content="tips"></u-modal>
<u-datetime-picker
mode="datetime"
:value="periodValidityEndTime"
:show="isShowTime"
:show-time-tag="true"
@cancel="isShowTime = false"
@close="isShowTime = false"
@confirm="onTimeChange">
</u-datetime-picker>
</div>
</template>
<script>
export default {
props: ['id', 'formConfig', 'type'],
data () {
return {
params: {
year: true,
month: true,
day: true,
hour: true,
minute: true,
second: true
},
tips: '',
isShowModal: false,
actionNotice: true,
@@ -95,19 +97,17 @@ export default {
wechatId: '0',
periodValidityEndTime: '',
isShowTime: false,
periodValidityType: '0',
type: '',
id: ''
periodValidityType: '0'
}
},
onLoad (query) {
if (query.id) {
this.id = query.id
this.getInfo(query.id)
this.type = query.type
} else if (query.formConfig && query.formConfig !== '{}') {
const res = JSON.parse(query.formConfig)
mounted () {
if (this.id) {
this.id = this.id
this.getInfo(this.id)
this.type = this.type
} else if (this.formConfig) {
const res = this.formConfig
this.periodValidityType = res.periodValidityType
this.commitType = res.commitType
this.actionNotice = res.actionNotice === '1'
@@ -121,13 +121,12 @@ export default {
methods: {
onTimeChange (e) {
this.periodValidityEndTime = `${e.year}-${e.month}-${e.day} ${e.hour}:${e.minute}:${e.second}`
this.isShowTime = false
this.periodValidityEndTime = uni.$u.timeFormat(e.value, 'yyyy-mm-dd hh:MM:ss')
},
back () {
uni.navigateBack({
delta: 1
})
this.$emit('back')
},
getInfo (id) {

View File

@@ -0,0 +1,74 @@
<template>
<div class="form">
<div class="form-content">
<add-list ref="addList" v-if="currIndex === 1" @change="onChange"></add-list>
<list ref="list" v-if="currIndex === 0" @change="onChange"></list>
</div>
<ai-tabbar :active.sync="currIndex" :list="tabBar"/>
</div>
</template>
<script>
import AddList from './AddList.vue'
import List from './List.vue'
import AiTabbar from '@/components/AiTabbar'
export default {
name: 'AppAskForm',
appName: '问卷表单',
data () {
return {
currIndex: 0
}
},
components: {
AddList,
AiTabbar,
List
},
computed: {
tabBar () {
const link = icon => `${this.$cdn}askform/${icon}.png`
return [
{text: "表单列表", iconPath: "bdlb1", selectedIconPath: "bdlb2" },
{text: "新建项目", iconPath: "xjxm1", selectedIconPath: "xjxm2" }
].map(e => ({
...e,
iconPath: link(e.iconPath),
selectedIconPath: link(e.selectedIconPath)
}))
}
},
onLoad () {
uni.$on('reload', () => {
if (this.currIndex === 0) {
this.$refs.list.reload()
} else {
this.$refs.addList.getList()
}
})
},
methods: {
onChange (e) {
this.$emit('change', e)
}
},
onReachBottom() {
if (this.currIndex === 0) {
this.$refs.list.getList()
}
}
}
</script>
<style lang="scss" scoped>
.form {
padding-bottom: 98px;
}
</style>

View File

@@ -3,7 +3,7 @@
<div class="form-list">
<div
class="form-list__item"
@click="toAdd(`/pages/askForm/addForm?type=${index}`)"
@click="toAdd(index)"
:style="{'background-image': `url(${$cdn}askform/${index + 1}.png)`}"
v-for="(item, index) in itemList"
:key="index">
@@ -51,15 +51,22 @@ export default {
},
methods: {
toAdd (url) {
uni.navigateTo({
url
toAdd (type) {
this.$emit('change', {
type: 'AddForm',
params: {
type
}
})
},
quote (id) {
uni.navigateTo({
url: `/pages/askForm/addForm?isQuote=1&id=${id}`
this.$emit('change', {
type: 'AddForm',
params: {
id,
isQuote: 1
}
})
},

View File

@@ -29,7 +29,7 @@
</div>
<ai-empty v-if="!list.length && isMore"></ai-empty>
</div>
<u-popup :show="isShow" :closeable="false" mode="bottom" :z-index="11">
<u-popup :show="isShow" :closeable="false" mode="bottom" @close="isShow = false">
<div class="popup">
<h2>{{ info.title }}</h2>
<div class="operate-list">
@@ -98,6 +98,7 @@ export default {
templateType: 0,
title: ''
},
value: '',
id: '',
info: {},
isMore: false,
@@ -204,13 +205,16 @@ export default {
this.isShow = false
},
toEdit() {
toEdit () {
if (this.info.dataCount !== 0) {
return this.$u.toast('该表单已有数据,无法编辑!')
}
uni.navigateTo({
url: `/pages/askForm/addForm?id=${this.id}`
this.$emit('change', {
type: 'AddForm',
params: {
id: this.id
}
})
this.isShow = false
@@ -294,6 +298,10 @@ export default {
.form {
::v-deep .u-search {
margin-bottom: 0 !important;
.u-search__content__input {
height: 100%;
}
}
.popup {

View File

@@ -1,9 +1,7 @@
<template>
<section class="formList">
<ai-top-fixed>
<u-search placeholder="请输入标题" :show-action="false" search-icon-color="#ccc"
v-model="search.title" @search="page.current=1,getList()"/>
<u-search placeholder="请输入标题" :show-action="false" search-icon-color="#ccc" v-model="search.title" @search="page.current=1,getList()"/>
</ai-top-fixed>
<div class="mainPane">
<div class="formBox column" flex v-for="op in list" :key="op.id">