wangqing 4 years ago
parent
commit
8021767ff2
  1. 34
      src/components/generator/config.js
  2. 5
      src/router/modules/root.js
  3. 26
      src/utils/convert.js
  4. 3
      src/utils/index.js
  5. 13
      src/views/account/login.vue
  6. 7
      src/views/form/ProjectForm.vue
  7. 47
      src/views/form/index.vue
  8. 285
      src/views/form/logic.vue
  9. 9
      src/views/form/publish.vue
  10. 6
      src/views/form/write.vue
  11. 8
      src/views/project/MyProject.vue

34
src/components/generator/config.js

@ -20,7 +20,7 @@ export const formConf = {
export const inputComponents = [
{
// 组件的自定义配置
typeId: 1,
typeId: 'INPUT',
__config__: {
label: '单行文本',
labelWidth: null,
@ -53,7 +53,7 @@ export const inputComponents = [
disabled: false
},
{
typeId: 2,
typeId: 'TEXTAREA',
__config__: {
label: '多行文本',
labelWidth: null,
@ -113,7 +113,7 @@ export const inputComponents = [
// disabled: false
// },
{
typeId: 4,
typeId: 'NUMBER_INPUT',
__config__: {
label: '计数器',
showLabel: true,
@ -142,7 +142,7 @@ export const inputComponents = [
// 选择型组件 【左面板】
export const selectComponents = [
{
typeId: 5,
typeId: 'SELECT',
__config__: {
label: '下拉选择',
showLabel: true,
@ -173,7 +173,7 @@ export const selectComponents = [
multiple: false
},
{
typeId: 6,
typeId: 'CASCADER',
__config__: {
label: '级联选择',
url: 'https://www.fastmock.site/mock/f8d7a54fb1e60561e2f720d5a810009d/fg/cascaderList',
@ -219,7 +219,7 @@ export const selectComponents = [
separator: '/'
},
{
typeId: 7,
typeId: 'RADIO',
__config__: {
label: '单选框组',
labelWidth: null,
@ -250,7 +250,7 @@ export const selectComponents = [
disabled: false
},
{
typeId: 8,
typeId: 'CHECKBOX',
__config__: {
label: '多选框组',
tag: 'el-checkbox-group',
@ -283,7 +283,7 @@ export const selectComponents = [
disabled: false
},
{
typeId: 9,
typeId: 'SWITCH',
__config__: {
label: '开关',
tag: 'el-switch',
@ -308,7 +308,7 @@ export const selectComponents = [
'inactive-value': false
},
{
typeId: 10,
typeId: 'SLIDER',
__config__: {
label: '滑块',
tag: 'el-slider',
@ -331,7 +331,7 @@ export const selectComponents = [
range: false
},
{
typeId: 11,
typeId: 'TIME',
__config__: {
label: '时间选择',
tag: 'el-time-picker',
@ -357,7 +357,7 @@ export const selectComponents = [
'value-format': 'HH:mm:ss'
},
{
typeId: 12,
typeId: 'TIME_RANGE',
__config__: {
label: '时间范围',
tag: 'el-time-picker',
@ -383,7 +383,7 @@ export const selectComponents = [
'value-format': 'HH:mm:ss'
},
{
typeId: 13,
typeId: 'DATE',
__config__: {
label: '日期选择',
tag: 'el-date-picker',
@ -408,7 +408,7 @@ export const selectComponents = [
readonly: false
},
{
typeId: 14,
typeId: 'DATE_RANGE',
__config__: {
label: '日期范围',
tag: 'el-date-picker',
@ -435,7 +435,7 @@ export const selectComponents = [
readonly: false
},
{
typeId: 15,
typeId: 'RATE',
__config__: {
label: '评分',
tag: 'el-rate',
@ -458,7 +458,7 @@ export const selectComponents = [
disabled: false
},
{
typeId: 16,
typeId: 'COLOR',
__config__: {
label: '颜色选择',
tag: 'el-color-picker',
@ -479,7 +479,7 @@ export const selectComponents = [
size: 'medium'
},
{
typeId: 17,
typeId: 'UPLOAD',
__config__: {
label: '上传',
tag: 'el-upload',
@ -516,7 +516,7 @@ export const selectComponents = [
// 布局型组件 【左面板】
export const imageComponents = [
{
typeId: 18,
typeId: 'IMAGE',
__config__: {
label: '图片展示',
showLabel: false,

5
src/router/modules/root.js

@ -107,6 +107,11 @@ export default [
meta: {requireLogin: false},
component: () => import(/* webpackChunkName: 'root' */ '@/views/form/ProjectForm.vue')
},
{
path: '/s/:key',
meta: {requireLogin: false},
component: () => import(/* webpackChunkName: 'root' */ '@/views/form/write.vue')
},
{
path: '/project/write',
meta: {requireLogin: false},

26
src/utils/convert.js

@ -90,19 +90,19 @@ export function dbDataConvertForItemJson(data) {
let dataParams = {
//单行文本
1: {
'INPUT': {
'prepend': '__slot__.prepend',
'maxlength': 'maxlength',
'append': '__slot__.append'
},
// 多行文本
2: {
'TEXTAREA': {
'minRows': 'autosize.minRows',
'maxRows': 'autosize.maxRows',
'maxlength': 'maxlength'
},
//计数器
4: {
'NUMBER_INPUT': {
'min': 'min',
'max': 'max',
'maxlength': 'maxlength',
@ -112,44 +112,44 @@ let dataParams = {
'controls-position': 'controls-position'
},
//下拉选择
5: {
'SELECT': {
'options': '__slot__.options',
'filterable': 'filterable',
'multiple': 'multiple'
},
//级联选择
6: {
'CASCADER': {
'options': 'options',
'filterable': 'filterable',
'multiple': 'props.props.multiple'
},
//单选框组
7: {
'RADIO': {
'options': '__slot__.options',
'filterable': 'filterable',
'multiple': 'props.props.multiple'
},
//多选框组
8: {
'CHECKBOX': {
'optionType': '__config__.optionType',
'size': 'size',
'options': '__slot__.options',
'max': 'max',
'min': 'min'
}, //开关
9: {},
'SWITCH': {},
//滑块
10: {
'SLIDER': {
'min': 'min',
'max': 'max',
'step': 'step'
},//时间选择
11: {},
15: {
'TIME': {},
'RATE': {
'max': 'max'
},
//文件上传
17: {
'UPLOAD': {
'buttonText': '__config__.buttonText',
'showTip': '__config__.showTip',
'fileSize': '__config__.fileSize',
@ -160,7 +160,7 @@ let dataParams = {
},
//图片
18: {
'IMAGE': {
'src': 'src',
'alt': 'alt'
}

3
src/utils/index.js

@ -108,6 +108,9 @@ export function jsonClone(obj) {
return parse(stringify(obj))
}
export function jsonSimpleClone(obj){
return JSON.parse(JSON.stringify(obj))
}
// 深拷贝对象
export function deepClone(obj) {
const _toString = Object.prototype.toString

13
src/views/account/login.vue

@ -60,9 +60,10 @@
<el-tab-pane label="账号密码登录" name="account">
<el-form ref="accountLoginForm" label-position="top" size="small" :model="accountForm"
:rules="accountLoginRules"
status-icon
hide-required-asterisk
class="account-login-form"
status-icon hide-required-asterisk @key.enter.native="loginHandle"
@keyup.enter="loginHandle"
>
<el-form-item label="手机号/邮箱登录" prop="account">
<el-input v-model="accountForm.account" placeholder="请输入手机号/邮箱" autocomplete="off" />
@ -86,7 +87,9 @@
</el-link>
</el-col>
<el-col :span="6" :offset="1">
<el-link :underline="false" type="primary" class="protocol-tip" @click="toForgetPwdHandle">
<el-link :underline="false" type="primary" class="protocol-tip"
@click="toForgetPwdHandle"
>
忘记密码
</el-link>
</el-col>
@ -302,9 +305,7 @@ export default {
qqLoginAuthorizeUrl: ''
}
},
watch: {
},
watch: {},
created() {
this.getLoginWxQrCode()
this.refreshWxQrcodeTimer = setInterval(() => {

7
src/views/form/ProjectForm.vue

@ -121,9 +121,10 @@ export default {
return projectItem
})
this.formConf.fields = fields
this.formConf.title = res.data.project.name
this.formConf.description = res.data.project.describe
this.formConf.description = res.data.project.describe
if (res.data.project) {
this.formConf.title = res.data.project.name
this.formConf.description = res.data.project.describe
}
if (res.data.userProjectTheme) {
this.projectTheme = res.data.userProjectTheme
let {submitBtnText, showNumber, btnsColor} = res.data.userProjectTheme

47
src/views/form/index.vue

@ -8,22 +8,24 @@
</el-button>
</el-col>
<el-col :span="10" :offset="3">
<el-menu :default-active="activeIndex" @select="handleSelect" style="background-color: transparent"
<el-menu :default-active="activeTab" @select="handleSelect" style="background-color: transparent"
mode="horizontal">
<el-menu-item index="1">编辑</el-menu-item>
<el-menu-item index="2">外观</el-menu-item>
<el-menu-item index="3">设置</el-menu-item>
<el-menu-item index="4">发布</el-menu-item>
<el-menu-item index="5">统计</el-menu-item>
<el-menu-item index="editor">编辑</el-menu-item>
<el-menu-item index="logic">逻辑</el-menu-item>
<el-menu-item index="theme">外观</el-menu-item>
<el-menu-item index="setting">设置</el-menu-item>
<el-menu-item index="publish">发布</el-menu-item>
<el-menu-item index="statistics">统计</el-menu-item>
</el-menu>
</el-col>
</el-row>
<div v-if="projectKey" style="overflow-y: hidden">
<editor :projectKey="projectKey" :is-edit="isEdit" v-if="activeIndex==1"/>
<theme :projectKey="projectKey" v-if="activeIndex==2"/>
<setting :projectKey="projectKey" v-if="activeIndex==3"/>
<publish :projectKey="projectKey" v-if="activeIndex==4"/>
<statistics :projectKey="projectKey" v-if="activeIndex==5"/>
<div v-if="projectKey">
<editor :projectKey="projectKey" :is-edit="isEdit" v-if="activeTab=='editor'"/>
<logic :projectKey="projectKey" v-if="activeTab=='logic'"/>
<theme :projectKey="projectKey" v-if="activeTab=='theme'"/>
<setting :projectKey="projectKey" v-if="activeTab=='setting'"/>
<publish :projectKey="projectKey" v-if="activeTab=='publish'"/>
<statistics :projectKey="projectKey" v-if="activeTab=='statistics'"/>
</div>
</div>
</template>
@ -34,6 +36,7 @@ import theme from './theme'
import setting from './setting'
import publish from './publish'
import statistics from './statistics'
import logic from './logic'
export default {
components: {
@ -41,11 +44,12 @@ export default {
theme,
setting,
publish,
statistics
statistics,
logic
},
data() {
return {
activeIndex: '1',
activeTab: 'editor',
isEdit: false,
projectKey: ''
}
@ -56,24 +60,25 @@ export default {
this.projectKey = this.$route.query.key
this.isEdit = !!this.$route.query.active
if (this.$route.query.active) {
this.activeIndex = this.$route.query.active
this.activeTab = this.$route.query.active
}
},
methods: {
handleSelect(key, keyPath) {
if (key) {
this.activeIndex = key
handleSelect(type, keyPath) {
if (type) {
this.activeTab = type
this.$router.replace({path: '/project/form', query: {key: this.projectKey, active: type}})
}
}
}
}
</script>
<style lang='scss' >
.container{
<style lang='scss'>
.container {
position: relative;
width: 100%;
height: 100%;
overflow-y: hidden;
//overflow-y: hidden;
}
</style>

285
src/views/form/logic.vue

@ -0,0 +1,285 @@
<template>
<div class="project-logic-container">
<el-scrollbar style="height: 90vh;">
<el-row type="flex" style="width: 230px" justify="center" align="middle">
<el-col :span="12">
<p class="logic_title">显示逻辑</p>
</el-col>
<el-col :span="12">
<el-tooltip popper-class="question-popper" placement="top">
<div slot="content">符合某项条件则显示某道题<br/>点击查看帮助</div>
<i class="el-icon-question"></i>
</el-tooltip>
</el-col>
</el-row>
<div class="show-logic-container">
<div v-if="!logicList.length">
<el-row>
<el-col :offset="10">
<el-button type="text" @click="addLogicHandle">
<i class="el-icon-circle-plus-outline" style="font-size: 20px"></i>
<span style="font-size: 18px">添加逻辑</span>
</el-button>
</el-col>
</el-row>
</div>
<div v-else>
<el-row>
<el-col :span="12">
<p style="font-size: 14px;color: #aaa"> {{ logicList.length + 1 }}. 条显示逻辑</p>
</el-col>
<el-col :span="6" :offset="6">
<el-button type="primary" size="mini" @click="addLogicHandle">
<i class="el-icon-plus"></i>
<span style="font-size: 18px">添加逻辑</span>
</el-button>
</el-col>
</el-row>
<el-divider/>
<div v-for="(logicItem,index) in logicList"
:key="index">
<el-row type="flex" align="middle" justify="center">
<el-col :offset="1" :span="6">
<span style="margin-right: 8px">{{ index + 1 }}.</span>
<el-select
:disabled="!!logicItem.showFormItemId"
v-model="logicItem.showFormItemId" placeholder="请选择问题">
<el-option
v-for="item in getProjectItemList() "
:key="item.id"
:label="item.label"
:value="item.id">
</el-option>
</el-select>
</el-col>
<el-col :span="2">
<span>符合以下</span>
</el-col>
<el-col :span="4">
<el-select v-model="logicItem.showExpression" placeholder="请选择">
<el-option
v-for="item in questionOptions"
:key="item.value"
:label="item.label"
:value="item.value">
</el-option>
</el-select>
</el-col>
<el-col :offset="1" :span="10">
<span>条件时显示此问题</span>
</el-col>
</el-row>
<el-row
v-for="(cItem,cIndex) in logicItem.conditionList"
:key="cIndex"
:gutter="20"
style="margin-top: 5px" type="flex" align="middle" justify="center">
<el-col :offset="1" :span="6">
<el-select v-model="cItem.formItemId" placeholder="请选择题目">
<el-option
v-for="item in getConditionProjectItemList(logicItem)"
:key="item.id"
:label="item.label"
:value="item.id">
</el-option>
</el-select>
</el-col>
<el-col :span="5">
<el-select v-model="cItem.expression" placeholder="请选择条件">
<el-option
v-for="item in conditionOptions"
:key="item.value"
:label="item.label"
:value="item.value">
</el-option>
</el-select>
</el-col>
<el-col :span="6">
<el-select v-model="cItem.optionValue" placeholder="请选择选项">
<el-option
v-for="item in getFormItemOptions(cItem.formItemId)"
:key="item.value"
:label="item.label"
:value="item.value">
</el-option>
</el-select>
</el-col>
<el-col :span="9">
<el-button type="text" @click="addConditionHandle(logicItem)">
<i class="el-icon-circle-plus-outline"
style="font-size: 24px"/>
</el-button>
<el-button type="text"
style="color: #ff4949"
@click="removeConditionHandle(logicItem,index,cIndex)">
<i class="el-icon-remove-outline"
style="font-size: 24px"/>
</el-button>
</el-col>
</el-row>
<el-divider/>
</div>
</div>
</div>
</el-scrollbar>
</div>
</template>
<script>
import _ from 'lodash'
import {jsonSimpleClone} from '@/utils/index'
export default {
name: 'ProjectLogic',
components: {},
props: {
projectKey: ''
},
mounted() {
this.queryProjectItems()
},
data() {
return {
//
defaultLogicItem: {
showFormItemId: null,
showExpression: 'all',
conditionList: [
{
formItemId: null,
expression: null,
optionValue: null
}
]
},
conditionOptions: [{
value: 'checked',
label: '选中'
}, {
value: 'unchecked',
label: '未选中'
}],
questionOptions: [{
value: 'all',
label: '全部'
}, {
value: 'any',
label: '任意'
}],
allProjectItemList: [],
logicList: []
}
}, methods: {
addConditionHandle(logicItem) {
logicItem.conditionList.push({})
},
removeConditionHandle(logicItem, logicIndex, index) {
logicItem.conditionList.splice(index, 1)
if (logicItem.conditionList.length == 0) {
this.logicList.splice(logicIndex, 1)
}
},
addLogicHandle() {
this.logicList.push(jsonSimpleClone(this.defaultLogicItem))
},
getConditionProjectItemList(logicItem) {
let showFormItemId = logicItem.showFormItemId
if (!showFormItemId) {
return
}
//使
let conditionProjectItemList = jsonSimpleClone(this.allProjectItemList)
let index = conditionProjectItemList.findIndex(item => item.id == showFormItemId)
conditionProjectItemList = _.slice(conditionProjectItemList, 0, index)
conditionProjectItemList = conditionProjectItemList.filter((item) => {
return ['RADIO'].includes(item.type)
})
return conditionProjectItemList
},
getProjectItemList() {
//
let selectedFormItemList = this.logicList.map(item => item.showFormItemId)
let projectItemList = jsonSimpleClone(this.allProjectItemList)
projectItemList.shift()
return projectItemList.filter((item) => {
return !selectedFormItemList.includes(item.id)
})
},
getFormItemOptions(formItemId) {
let formItem = this.allProjectItemList.find(item => item.id == formItemId)
if (formItem) {
return formItem.expand.options
}
return []
},
queryProjectItems() {
this.$api.get(`/user/project/item/list`, {params: {key: this.projectKey}}).then(res => {
this.allProjectItemList = res.data
// //
// let projectItemList = res.data
// projectItemList.shift()
// this.projectItemList = projectItemList
})
}
}
}
</script>
<style scoped>
.project-logic-container {
width: 100%;
padding: 0px;
margin: 0;
background-color: #F7F7F7;
min-height: 84vh;
min-width: 80vw;
display: flex;
justify-content: center;
}
.project-logic-container .logic_title {
font-size: 18px;
height: 45px;
line-height: 45px;
color: #484848;
text-indent: 20px;
padding-top: 20px;
}
.el-icon-question {
font-size: 23px;
height: 50px;
line-height: 50px;
text-indent: 20px;
padding-top: 23px;
color: #D8D8D8;
}
.show-logic-container {
padding: 10px;
min-width: 950px;
background-color: #FFFFFF;
box-shadow: 0 2px 4px rgba(0, 0, 0, .12), 0 0 6px rgba(0, 0, 0, .04)
}
</style>
<style>
.question-popper.el-tooltip__popper[x-placement^="top"] .popper__arrow {
/*border-top-color: #205bb5 !important;*/
}
.question-popper.el-tooltip__popper[x-placement^="top"] .popper__arrow:after {
/*border-top-color: #205bb5 !important;*/
}
.question-popper {
padding: 10px;
color: #000000 !important;
border-color: #205bb5 !important;
background: #FFFFFF !important;
}
</style>

9
src/views/form/publish.vue

@ -30,7 +30,7 @@
v-clipboard:error="()=>{this.msgError('复制失败')}" type="primary">复制链接
</el-button>
</el-col>
<el-col :span="6" >
<el-col :span="6">
<el-button
@click="stopPublishProject"
type="danger">停止发布
@ -77,7 +77,7 @@ export default {
},
mounted() {
let url = window.location.protocol + '//' + window.location.host
this.writeLink = `${url}/project/write?key=${this.projectKey}`
this.writeLink = `${url}/s/${this.projectKey}`
this.getProjectStatus()
},
data() {
@ -91,7 +91,7 @@ export default {
this.$api.get(`/user/project/${this.projectKey}`).then(res => {
if (res.data.status == 2) {
this.publishStatus = true
}else{
} else {
this.publishStatus = false
}
})
@ -117,7 +117,7 @@ export default {
let aLink = document.createElement('a')
let blob = this.base64ToBlob(content) //new Blob([content]);
let evt = document.createEvent('HTMLEvents')
evt.initEvent('click', true, true)//initEvent FF
evt.initEvent('click', true, true)//initEvent FF
aLink.download = fileName
aLink.href = URL.createObjectURL(blob)
// aLink.dispatchEvent(evt);
@ -152,7 +152,6 @@ export default {
padding: 0px;
margin: 0;
background-color: #F7F7F7;
font-family: "Helvetica Neue", Helvetica, "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei", "微软雅黑", Arial, sans-serif;
min-height: 84vh;
display: flex;
align-items: center;

6
src/views/form/write.vue

@ -74,7 +74,7 @@ export default {
document.getElementsByTagName('head')[0].appendChild(meta)
},
created() {
let key = this.$route.query.key
let key = this.$route.query.key || this.$route.params.key
this.projectConfig.projectKey = key
let wxCode = getQueryString('code')
if (wxCode) {
@ -89,7 +89,6 @@ export default {
this.wxSignature = res.data
this.setWxConfig()
})
console.log(ua)
},
mounted() {
this.viewProjectHandle()
@ -263,12 +262,11 @@ export default {
.write-container {
margin: 0;
padding: 0;
//height: 100%;
height: 100%;
width: 100%;
}
.title-icon-view {
display: flex;
align-items: center;

8
src/views/project/MyProject.vue

@ -93,13 +93,13 @@
>
<p class="project-grid-view-time">创建时间{{ p.createTime | formatDate }}</p>
<div class="gird-operating-btns">
<el-button type="text" @click="toProjectHandle(p.key,1)">
<el-button type="text" @click="toProjectHandle(p.key,'editor')">
<i class="el-icon-edit" />
编辑
</el-button>
<span>
<el-button
v-if="p.status!=1" type="text" @click="toProjectHandle(p.key,5)"
v-if="p.status!=1" type="text" @click="toProjectHandle(p.key,'statistics')"
>
<i class="el-icon-data-analysis" />
统计
@ -187,7 +187,7 @@
<el-table-column label="操作">
<template slot-scope="scope">
<el-button type="text"
@click="toProjectHandle(scope.row.key,1)"
@click="toProjectHandle(scope.row.key,'editor')"
>
编辑
</el-button>
@ -196,7 +196,7 @@
v-if="scope.row.status!=1"
type="text"
class="green-text-btn"
@click="toProjectHandle(scope.row.key,5)"
@click="toProjectHandle(scope.row.key,'statistics')"
>
统计
</el-button>

Loading…
Cancel
Save