瀏覽代碼

feat:管理界面 10%

magic v 4 年之前
父節點
當前提交
e22ec514d7

+ 1 - 1
index.html

@@ -4,7 +4,7 @@
     <meta charset="utf-8" />
     <meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, minimum-scale=1, user-scalable=no" />
     <meta name="format-detection" content="telephone=yes" />
-    <title>完善就诊人信息</title>
+    <title>问卷调查</title>
     <style>
       html, body {
         margin: 0;

+ 1 - 1
src/pages/404.vue

@@ -2,7 +2,7 @@
   <div class="container-404">
     <div class="container-404-body">
       <span>404</span>
-      <p>&lt; 点击返回上一页</p>
+      <p @click="$router.back()">&lt; 点击返回上一页</p>
     </div>
   </div>
 </template>

+ 11 - 2
src/pages/FormVolume/Layout1/index.vue

@@ -8,7 +8,9 @@
     <transition-group name="list" class="volume-content" tag="ul">
       <li
         v-for="(item, index) in data.result"
-        :key="index + 1">
+        :key="index + 1"
+        :class="{ cur: edataItem === item }"
+        @click="$emit('selectItem', item)">
         <p>
           <label v-if="item.required">*</label>
           <span>{{index + 1}}. </span>
@@ -80,7 +82,7 @@
     <slot name="tel" />
   </div>
   
-  <div class="footer" v-if="!!data.result.length">
+  <div class="footer" v-if="isSubmit && !!data.result.length">
     <button class="btn primary" 
       :disabled="loading.submit || !data.result.length" 
       @click="$emit('submit')">提交</button>
@@ -100,6 +102,13 @@ export default {
     loading: {
       required: true,
       type: Object
+    },
+    isSubmit: {
+      type: Boolean,
+      default: true
+    },
+    edataItem: {
+      type: Object
     }
   }
 }

+ 8 - 0
src/pages/FormVolume/Layout1/style.scss

@@ -6,6 +6,7 @@
   .head {
     padding: 0 $sp-lg;
     border-bottom: 1px dashed $color-5;
+    padding-top: $sp-lg;
     > h1 {
       text-align: center;
       font-size: $size-xl;
@@ -26,6 +27,13 @@
       padding: $sp-lg;
       background: $color-f;
       border-bottom: 1px dashed $color-5;
+
+      &.cur {
+        box-shadow: 0 0px 4px 1px #ffd023;
+        z-index: 2;
+        position: relative;
+      }
+
       > p {
         margin: 0;
         font-weight: 500;

+ 11 - 2
src/pages/FormVolume/Layout2/index.vue

@@ -14,7 +14,9 @@
     <transition-group name="list" class="volume-content" tag="ul">
       <li
         v-for="(item, index) in data.result"
-        :key="index + 1">
+        :key="index + 1"
+        :class="{ cur: edataItem === item }"
+        @click="$emit('selectItem', item)">
         <p>
           <i :class="{cur: !!item.val && !!item.val.length}" />
           <label v-if="item.required">*</label>
@@ -87,7 +89,7 @@
     <slot name="tel" />
   </div>
   
-  <div class="footer" v-if="!!data.result.length">
+  <div class="footer" v-if="isSubmit && !!data.result.length">
     <button class="btn primary" 
       :disabled="loading.submit || !data.result.length" 
       @click="$emit('submit')">提交</button>
@@ -108,6 +110,13 @@ export default {
     loading: {
       required: true,
       type: Object
+    },
+    isSubmit: {
+      type: Boolean,
+      default: true
+    },
+    edataItem: {
+      type: Object
     }
   },
   data () {

+ 5 - 17
src/pages/FormVolume/index.vue

@@ -2,8 +2,11 @@
   <components 
     :is="layoutCurrent"
     :data="data"
+    :edataItem="edataItem"
     :loading="loading"
+    :isSubmit="!edata"
     @submit="btnSubmit"
+    @selectItem="item => $emit('selectItem', item)"
     v-if="layoutCurrent != 'van-empty' && !loading.empty">
     <div class="tel-message" slot="tel">
       <span>· 感谢您的支持与关注!任何问题,请您联系</span>
@@ -26,31 +29,16 @@
   <van-empty v-else
     style="height: 100%;"
     description="登录失效">
-    <van-button round type="danger" @click="$router.go(-1)" style="width: 80vw; max-width: 350px;">返回</van-button>
+    <van-button round type="danger" @click="$router.go(-1)" style="width: 220px; max-width: 350px;">返回</van-button>
   </van-empty>
 </template>
 
 <script>
 import mixins from './mixins';
-import Layout1 from './Layout1'
-import Layout2 from './Layout2'
 
 // 102 为定制版本,> 100 为定制,02 为 2 的定制
 export default {
-  components: {
-    Layout1,
-    Layout2,
-  },
-  mixins: [mixins],
-  data () {
-    return {
-      layoutCurrent: '',
-      layoutType: {
-        '1': 'Layout1',
-        '2': 'Layout2'
-      }
-    }
-  }
+  mixins: [mixins]
 }
 </script>
 <style lang="scss" scoped>

src/pages/FormVolume/mixins/custom.js → src/pages/FormVolume/js/custom.js


+ 68 - 24
src/pages/FormVolume/mixins/index.js

@@ -1,6 +1,20 @@
 import * as api from '@/api'
-import Custom from './custom'
+import Custom from '../js/custom'
+import Layout1 from '../Layout1'
+import Layout2 from '../Layout2'
 export default {
+  props: {
+    edata: {
+      type: Object
+    },
+    edataItem: {
+      type: Object
+    }
+  },
+  components: {
+    Layout1,
+    Layout2,
+  },
   data() {
     return {
       TITLE: '问卷调查',
@@ -8,6 +22,11 @@ export default {
         result: [],
         topic: {}
       },
+      layoutCurrent: '',
+      layoutType: {
+        '1': 'Layout1',
+        '2': 'Layout2'
+      },
       loading: {
         data: false,
         empty: false,
@@ -29,6 +48,9 @@ export default {
       if (from.name === 'FormVolume') {
         clearInterval(this.codeMess.t)
       }
+    },
+    edata () {
+      this.inData()
     }
   },
   destroyed() {
@@ -84,30 +106,22 @@ export default {
       this.loading.data = true
       this.loading.empty = false
       try {
-        let { result_id } = this.$route.query
-        let pm = result_id
-          ? api.apiGetVolumeResult({ result_id })
-          : api.apiGetVolumeInfo(this.$route.query)
-        let res = await pm
-        let data = res.data
-        let configType = {
-          'radio': '单选',
-          'checkbox': '多选'
-        }
-        data.result.forEach(item => {
-          item.layout_align = item.layout_align || data.topic.layout_align || 'left'
-          item.layout_inline = item.layout_inline || data.topic.layout_inline || 1
-          item.type_name = configType[item.type] || ''
-
-          // 自定义组件处理
-          Custom(item)
-        })
-        if (data.topic.memo) {
-          data.topic.memo = data.topic.memo.replace(/\n/g, '<br />')
-        }
-        if (this.layoutType) {
-          this.layoutCurrent = this.layoutType[data.topic.layout_type] || 'van-empty'
+        let data = null
+        if (this.edata) {
+          data = this.edata
+        } else {
+          let { result_id } = this.$route.query
+          let pm = result_id
+            ? api.apiGetVolumeResult({ result_id })
+            : api.apiGetVolumeInfo(this.$route.query)
+          let res = await pm
+          data = res.data
         }
+        
+        this.inTopicLayout(data)
+        this.inTopicAttr(data)
+        this.inTopicComponent(data)
+        
         this.$set(this, 'data', data)
       } catch (error) {
         this.loading.empty = true
@@ -115,6 +129,36 @@ export default {
       }
       this.loading.data = false
     },
+    // 问卷属性初始化
+    inTopicAttr (data) {
+      data = data || this.data
+      if (data.topic.memo) {
+        data.topic.memo = data.topic.memo.replace(/\n/g, '<br />')
+      }
+    },
+    // 问卷组件初始化
+    inTopicComponent (data) {
+      data = data || this.data
+      let configType = {
+        'radio': '单选',
+        'checkbox': '多选'
+      }
+      data.result.forEach(item => {
+        item.layout_align = item.layout_align || data.topic.layout_align || 'left'
+        item.layout_inline = item.layout_inline || data.topic.layout_inline || 1
+        item.type_name = configType[item.type] || ''
+
+        // 自定义组件处理
+        Custom(item)
+      })
+    },
+    // 问卷主题UI初始化
+    inTopicLayout (data) {
+      data = data || this.data
+      if (this.layoutType) {
+        this.layoutCurrent = this.layoutType[data.topic.layout_type] || 'van-empty'
+      }
+    },
     btnOpenSuccess(callback) {
       this.show.submit = true
       this.loopCode(this.codeMess.num, async () => {

+ 26 - 0
src/pages/Manager/common.scss

@@ -0,0 +1,26 @@
+@import '@/common/scss/base.scss';
+.card-doc {
+  font-size: $size-sm;
+  background: $color-6;
+  .card-header {
+    background: $color-f;
+    box-shadow: 0 2px 2px 0px $color-5;
+    display: flex;
+    justify-content: space-between;
+    align-items: center;
+    position: relative;
+    z-index: 3;
+    > h3 {
+      font-size: $size-sm;
+      margin: 0;
+      padding: $sp-md $sp-lg;
+      flex: 1;
+    }
+    .icon {
+      padding: 0 $sp-lg;
+      font-size: $size-md;
+    }
+  }
+}
+
+

+ 52 - 0
src/pages/Manager/index.vue

@@ -0,0 +1,52 @@
+<template>
+  <div class="manager-container">
+    <div class="manager-components"></div>
+    <div class="manager-template">
+      <LayoutVolume :edata="data" :edataItem="dataItem" @selectItem="item => dataItem = item" />
+    </div>
+    <div class="manager-attribute">
+      <div class="card-attr">
+        <div class="card-doc">
+          <div class="card-header">
+            <h3>表单属性</h3>
+            <van-icon name="arrow-down" class="icon" />
+          </div>
+          <div class="card-body">
+            <van-cell-group>
+              <van-field name="radio" label="主题">
+                <template #input>
+                  <van-radio-group v-model="data.topic.layout_type" direction="horizontal">
+                    <van-radio :name="1">主题1</van-radio>
+                    <van-radio :name="2">主题2</van-radio>
+                  </van-radio-group>
+                </template>
+              </van-field>
+              <van-field v-model="value" label="表单标题" placeholder="请输入用户名" />
+              <van-field
+                v-model="value"
+                label="表单描述"
+                placeholder="请输入用户名"
+                type="textarea"
+                rows="3"
+                autosize
+              />
+            </van-cell-group>
+            
+          </div>
+        </div>
+        <div class="card-doc"></div>
+      </div>
+    </div>
+  </div>
+</template>
+
+<script>
+import mixins from "./mixins";
+export default {
+  mixins: [mixins]
+};
+</script>
+<style lang="scss" scoped>
+@import "./common.scss";
+@import "./style.scss";
+</style>

+ 80 - 0
src/pages/Manager/js/config.js

@@ -0,0 +1,80 @@
+export default {
+  contentData: {
+    input: null,
+    textarea: null,
+    default: `{ "title": "选项值", "memo": "" }`
+  },
+  componentData: {
+    checkbox: '',
+    default: `{
+      "detail_id": 0,
+      "title": "题目问题",
+      "required": 0,
+      "val": "",
+      "layout_align": "left",
+      "layout_inline": 1
+    }`
+  },
+  localData: {
+    "result": [
+      {
+        "detail_id": 10,
+        "title": "请滑动评分来表达您是否愿意将铂林眼科推荐给朋友或家人。",
+        "type": "slider",
+        "required": 1,
+        "content": [
+          { "title": "1分", "memo": "不会推荐" },
+          { "title": "2分", "memo": "" },
+          { "title": "3分", "memo": "" },
+          { "title": "4分", "memo": "" },
+          { "title": "5分", "memo": "我会考虑" },
+          { "title": "6分", "memo": "" },
+          { "title": "7分", "memo": "" },
+          { "title": "8分", "memo": "" },
+          { "title": "9分", "memo": "" },
+          { "title": "10分", "memo": "非常愿意" }
+        ],
+        "val": "",
+        "layout_align": "left",
+        "layout_inline": 1
+      },
+      {
+        "detail_id": 11,
+        "title": "我们的服务还需要在哪些方面做出提升?",
+        "type": "checkbox",
+        "required": 1,
+        "content": [
+          { "title": "预约安排" },
+          { "title": "候诊时间" },
+          { "title": "医疗检查" },
+          { "title": "科普沟通" },
+          { "title": "就诊环境" },
+          { "title": "诊后提醒" }
+        ],
+        "val": [],
+        "layout_align": "left", "layout_inline": 2
+      },
+      {
+        "detail_id": 13,
+        "title": "针对医疗服务,有什么特别的话想对我们说吗?",
+        "type": "textarea",
+        "required": 0,
+        "content": [],
+        "val": "",
+        "layout_align": "left",
+        "layout_inline": 1
+      }
+    ],
+    "topic": {
+      "id": 2,
+      "name": "满意度调查问卷",
+      "memo": "尊敬的客户:\n  感谢您选择铂林眼科。我们非常期待您对本次服务的满意度反馈,这将对提升我们的服务非常重要。",
+      "layout_type": 2,
+      "layout_align": "left",
+      "layout_inline": 2,
+      "submessage": " 感谢您的支持与关注!",
+      "is_name": 1,
+      "is_memo": 1
+    }
+  }
+}

+ 105 - 0
src/pages/Manager/mixins/index.js

@@ -0,0 +1,105 @@
+import * as api from '@/api'
+import LayoutVolume from '../../FormVolume'
+import config from '../js/config'
+export default {
+  components: {
+    LayoutVolume
+  },
+  data() {
+    return {
+      TITLE: '问卷调查',
+      value: '',
+      radio: '',
+      data: config.localData,
+      dataItem: null,
+      loading: {
+        data: false,
+        empty: false,
+        submit: false
+      }
+    };
+  },
+  created() {
+    this.vueWatchRoute()
+  },
+  methods: {
+    vueWatchRoute () {
+      // this.inQuery()
+      // this.inData()
+    },
+    inQuery () {
+      let { title } = this.$route.query
+      if (title) {
+        this.TITLE = title
+      }
+    },
+    async inData() {
+      this.loading.data = true
+      this.loading.empty = false
+      try {
+        let { result_id } = this.$route.query
+        let pm = result_id
+          ? api.apiGetVolumeResult({ result_id })
+          : api.apiGetVolumeInfo(this.$route.query)
+        let res = await pm
+        let data = res.data
+        let configType = {
+          'radio': '单选',
+          'checkbox': '多选'
+        }
+        data.result.forEach(item => {
+          item.layout_align = item.layout_align || data.topic.layout_align || 'left'
+          item.layout_inline = item.layout_inline || data.topic.layout_inline || 1
+          item.type_name = configType[item.type] || ''
+
+          // 自定义组件处理
+          Custom(item)
+        })
+        if (data.topic.memo) {
+          data.topic.memo = data.topic.memo.replace(/\n/g, '<br />')
+        }
+        if (this.layoutType) {
+          this.layoutCurrent = this.layoutType[data.topic.layout_type] || 'van-empty'
+        }
+        this.$set(this, 'data', data)
+      } catch (error) {
+        this.loading.empty = true
+        console.log(error)
+      }
+      this.loading.data = false
+    },
+    async btnSubmit() {
+      this.loading.submit = true
+      let ld = null
+      try {
+        await this.isForm(item => {
+          this.$dialog.alert({
+            title: '必填项',
+            message: `${item.title}`,
+          })
+        })
+        await this.$dialog.confirm({
+          title: '提示',
+          message: '请确认无误提交?',
+        })
+        ld = this.$toast.loading({ message: '提交中...', duration: 0 })
+        let result = this.data.result.map(item => ({ detail_id: item.detail_id, val: item.val }))
+        let query = {
+          ...this.$route.query,
+          data: JSON.stringify(result)
+        }
+        await api.apiPostVolumeInfo(query)
+        this.btnOpenSuccess(() => {
+          let { go, replace } = this.$route.query
+          replace
+            ? this.$router.replace({ name: replace })
+            : this.$router.go(go || -1)
+        })
+      } catch (error) {
+        console.log(error)
+      }
+      ld && ld.clear()
+      this.loading.submit = false
+    }
+  }
+}

+ 30 - 0
src/pages/Manager/style.scss

@@ -0,0 +1,30 @@
+@import '@/common/scss/base.scss';
+.manager-container {
+  height: 100%;
+  min-width: 1200px;
+  margin: 0 auto;
+  display: flex;
+  justify-content: center;
+
+
+  .manager-components,
+  .manager-attribute {
+    min-width: 350px;
+    max-width: 500px;
+    flex: 1;
+    height: 100%;
+    overflow: auto;
+
+    border-left: 1px solid $color-6;
+    border-right: 1px solid $color-6;
+  }
+
+  .manager-template {
+    flex: 2;
+    max-width: 750px;
+    height: 100%;
+    overflow: auto;
+  }
+}
+
+

+ 6 - 0
src/router/index.js

@@ -5,6 +5,7 @@ import Router from 'vue-router'
 import Entry from '@/pages/Entry'
 import View404 from '@/pages/404'
 import FormVolume from '@/pages/FormVolume'
+import Manager from '@/pages/Manager'
 
 Vue.use(Router)
 
@@ -23,6 +24,11 @@ const routers = new Router({
         }
       ]
     },
+    {
+      path: '/Manager',
+      name: 'Manager',
+      component: Manager
+    },
     {
       path: '*',
       name: '404',