Pārlūkot izejas kodu

添加安全检查

凉纪 2 gadi atpakaļ
vecāks
revīzija
df6a3c703b

+ 2 - 1
package.json

@@ -13,10 +13,12 @@
     "@riophae/vue-treeselect": "0.4.0",
     "amfe-flexible": "^2.2.1",
     "axios": "^1.3.4",
+    "better-scroll": "^2.5.1",
     "browser-fs-access": "^0.34.1",
     "core-js": "^3.23.3",
     "dayjs": "^1.11.9",
     "js-image-compressor": "^2.0.0",
+    "pdfjs-dist": "2.5.207",
     "regenerator-runtime": "^0.13.5",
     "v-calendar": "^2.4.1",
     "vant": "^2.12.54",
@@ -24,7 +26,6 @@
     "vue-easytable": "^2.27.1",
     "vue-esign": "^1.1.4",
     "vue-pdf": "4.2.0",
-    "pdfjs-dist": "2.5.207",
     "vue-router": "^3.6.5",
     "vuex": "^3.6.2"
   },

+ 166 - 0
src/components/SearchSelectCell/SelectPicker.vue

@@ -0,0 +1,166 @@
+<template>
+  <van-popup class="search-data-popup" round lazy-render v-model="show" position="bottom" >
+    <div class="header-line">
+      <div class="cancel" @click="onSearchCancel">取消</div>
+      <div class="title">{{ title }}</div>
+      <div class="sure" @click="onSearchConfirm">确定</div>
+    </div>
+    <van-search v-if="showSearch" placeholder="输入您想搜索的内容" v-model="searchValue" @input="inputSearchValue" />
+<!--    <div class="tip">已选{{temp_datas.length}}条</div>-->
+    <div v-if="itemList?.length >0"  class="lists">
+      <div  class="line" v-for="(item, index) in itemList" :key="item[valueKey]">
+
+        <van-cell
+          clickable
+          :key="item[valueKey]"
+          :title="item[valueKey]"
+          @click="click(item,index)">
+          <template #right-icon>
+            <van-checkbox v-model="item.checked"/>
+          </template>
+        </van-cell>
+      </div>
+    </div>
+    <div v-else class="lists">
+      <van-empty description="暂无数据" />
+    </div>
+  </van-popup>
+</template>
+<script>
+export default {
+  props: {
+    showPicker: {
+      types:Boolean,
+      default:false
+    }, //是否显示
+    options: {
+      type:Array,
+      default: ()=>[],
+    }, //未根据搜索内容筛选的所有列表数据
+    value: {
+      type:Array,
+      default: ()=>[],
+    },//默认选中数据
+    //自定义字段
+    valueKey:{
+      type: String,
+      default:'label'
+    },
+    showSearch:{
+      type:Boolean,
+      default:true
+    },
+    title: String //标题
+  },
+  data(){
+    return {
+      searchValue: "", //搜索框内容
+      itemList:[],
+    }
+  },
+  watch:{
+    temp_datas:{
+      handler(val){
+        this.itemList = val;
+      },
+      deep:true
+    },
+  },
+  computed: {
+    columns(){
+      return this.options
+    },
+    temp_datas(){
+      this.columns.forEach(v=>{
+        this.value.forEach((item)=>{
+          if(v[this.valueKey] === item[this.valueKey]){
+            v.checked = true;
+          }else {
+            v.checked = false;
+          }
+        })
+      })
+      return this.columns
+    },
+    show:{
+      get(){
+        return this.showPicker;
+      },
+      set(){
+        this.$emit("cancel");
+      },
+    },
+  },
+  methods: {
+    click(v,i){
+      this.$set(this.columns[i],'checked',!this.columns[i].checked);
+    },
+    inputSearchValue(query) {
+      if(query == ''){return this.itemList = this.options }
+      //搜索框值发生改变
+      setTimeout(() => {
+        this.itemList= this.temp_datas.filter(item => {
+          return item[this.valueKey].indexOf(query.toLowerCase()) > -1;
+        });
+      }, 200);
+    },
+    onSearchCancel() {
+      //取消
+      this.$emit("cancel");
+    },
+    onSearchConfirm() {
+      let arr = this.columns.filter(v=>v.checked === true)
+      //确认
+      this.$emit("confirm", arr);
+      this.show = false;
+    },
+  },
+}
+</script>
+<style scoped>
+.search-data-popup .tip {
+  color: #666;
+  padding-bottom: 5px;
+}
+.search-data-popup .header-line {
+  display: flex;
+  justify-content: space-between;
+  align-items: center;
+  height: 90px;
+}
+.search-data-popup .header-line .cancel {
+  padding: 0 30px;
+  font-size: 28px;
+  color: #969799;
+}
+.search-data-popup .header-line .title {
+  font-weight: 500;
+  font-size: 30px;
+  color: #343434;
+}
+.search-data-popup .header-line .sure {
+  padding: 0 30px;
+  font-size: 28px;
+  color: #1989fa;
+}
+.search-data-popup .lists {
+  display: flex;
+  flex-direction: column;
+  padding: 10px 12px 20px 12px;
+  min-height: 300px;
+  max-height: 700px;
+  overflow: auto;
+}
+.search-data-popup .lists .line {
+  line-height: 40px;
+  font-size: 16px;
+  color: #000;
+  display: flex;
+  justify-content: space-between;
+  align-items: center;
+}
+.search-data-popup .lists .line img {
+  width: 20px;
+  height: 20px;
+}
+</style>

+ 107 - 0
src/components/SearchSelectCell/index.vue

@@ -0,0 +1,107 @@
+<template>
+  <div class="date-cell">
+    <van-cell v-if="disabled" :required="required" :title="title" :label="label"/>
+    <van-cell v-else  :required="required" :title="title" :label="label" is-link  @click="clickItem"/>
+    <Select-picker
+      :options="dataList"
+      v-bind="$attrs"
+      :showPicker="showPicker"
+      title="选择角色"
+      :value-key="prop.label"
+      :value="selected"
+      @confirm="pickerConfirm"
+      @cancel="cancelPicker">
+    </Select-picker>
+  </div>
+</template>
+
+<script>
+import SelectPicker from './SelectPicker.vue'
+export default {
+  components:{
+    SelectPicker
+  },
+  props:{
+    //禁用
+    disabled:{
+      type: [Boolean,String],
+      default: false,
+    },
+    //双向绑定的数据
+    value:{
+      type: [String,Number],
+      default: null,
+    },
+    required:{
+      type: [Boolean,String],
+      default: false,
+    },
+    //标题
+    title:{
+      type: String,
+      default: null,
+    },
+    //父组件给的列表数据
+    dataList:{
+      type: Array,
+      default: ()=>[],
+    },
+    //自定义字段
+    prop:{
+      type: Object,
+      default: ()=>(
+        {
+          label:'label',
+          value:'value'
+        }
+      ) ,
+    }
+  },
+  data(){
+    return{
+      showPicker:false,
+      label:'',
+    }
+  },
+  computed:{
+    columns(){
+      return this.dataList;
+    },
+    selected(){
+      let val;
+      this.columns.forEach(v=> {
+        if (v[this.prop.value] === this.value) {
+          val.push(v[this.prop.label]);
+          this.label = val.toString();
+        }
+      });
+      return val;
+    },
+  },
+  methods:{
+    cancelPicker(){
+      this.showPicker = false;
+    },
+    pickerConfirm(val){
+      console.log(val,'234')
+      this.label = val.map(v=>v[this.prop.label]).toString();
+      this.showPicker = false;
+      let arr = val.map(v=>v[this.prop.value]);
+      this.$emit('change',arr)
+    },
+    clickItem(){
+      this.showPicker = true;
+    },
+  },
+  model:{
+    prop: 'value',
+    event: 'change',
+  }
+}
+</script>
+
+<style lang="scss" scoped>
+.van-cell__label{
+  margin: 0;
+}
+</style>

+ 4 - 1
src/components/list/index.vue

@@ -39,7 +39,10 @@ export default {
     }
   },
   props: {
-    list: { type: Function, required: true },
+    list: {
+      type: [Function, Array],
+      required: true
+    },
     params: {},
     wrap: {
       default() {

+ 11 - 4
src/components/orgTree/index.vue

@@ -5,10 +5,10 @@
       @select="onSelect"
       v-model="selected"
       :options="orgTree"
-      :clearable="false"
+      :clearable="clearable"
       label='检查机构'
       :backspaceRemoves="false"
-      placeholder="请选择机构"
+      :placeholder="placeholder"
       :normalizer="tenantIdnormalizer"
       :show-count="true"
       :noChildrenText="''">
@@ -27,6 +27,14 @@ export default {
     value: {
       type: [String,Number],
       default: null
+    },
+    placeholder: {
+      type: String,
+      default: '请选择机构'
+    },
+    clearable:{
+      type:Boolean,
+      default:false
     }
   },
   data() {
@@ -99,7 +107,6 @@ export default {
     height: 90px;
     line-height: 90px;
   }
-
   .vue-treeselect__menu {
     padding: 20px;
     width: 100%;
@@ -119,7 +126,7 @@ export default {
   }
   .vue-treeselect--open-below .vue-treeselect__menu{
     border: 1px solid #cfcfcf;
-    margin-top:6px;
+    margin-top:3px;
     box-shadow: 0 0 10px 0 rgba(0,0,0,.1);
   }
   .vue-treeselect--focused:not(.vue-treeselect--open) .vue-treeselect__control{

+ 257 - 0
src/components/scroll/scroll.vue

@@ -0,0 +1,257 @@
+<template>
+  <div ref="wrapper" class="better-scroll">
+    <div class="content">
+      <div v-if="pulldown" class="pulldown-tip">
+        <span>{{pulldownTip.text}}</span>
+      </div>
+      <div class="list">
+        <slot></slot>
+      </div>
+
+      <div v-if="pullupShow" class="pullup-tip">
+        <span>{{pullupTip.text}}</span>
+      </div>
+    </div>
+  </div>
+</template>
+
+<script>
+  import BScroll from 'better-scroll'
+    export default {
+      name: "scroll",
+      props: {
+        // 滚动的时候会触发scroll事件,会截流
+        // 滚动的时候实时触发scroll事件,不会截流
+        // 在swipe的情况下也能使用scroll事件
+        probeType: {
+          type: Number,
+          default: 3
+        },
+        //点击列表触发click事件
+        click: {
+          type: Boolean,
+          default: true
+        },
+         //开启横向滚动
+        scrollX: {
+          type: Boolean,
+          default: false
+        },
+        //滚动事件
+        listenScroll: {
+          type: Boolean,
+          default: false
+        },
+        //列表数据
+        data: {
+          type: Array,
+          default: null,
+        },
+        //滚动到底部事件,用于上拉加载
+        pullup: {
+          type: Boolean,
+          default: false
+        },
+        //顶部下拉事件,用于下拉刷新
+        pulldown: {
+          type: Boolean,
+          default: true
+        },
+        //列表滚动事件
+        beforeScroll: {
+          type: Boolean,
+          default: false
+        },
+        //刷新scroll延时。
+        refreshDelay: {
+          type: Number,
+          default: 20
+        },
+      },
+      data(){
+        return{
+          loadingConnecting: false,
+          pullupShow:false,
+          pulldownTip: {
+            text: '下拉刷新',
+            rotate: ''
+          },
+          pullupTip: {
+            text: '上拉加载',
+            rotate: ''
+          },
+        }
+      },
+      mounted() {
+        this.$nextTick(()=>{
+          this.initScroll();
+        })
+      },
+      methods: {
+        // initScroll(){
+        //   if (!this.$refs.wrapper) {
+        //     return;
+        //   }
+          // better-scroll的初始化
+          // this.scroll = new BScroll(this.$refs.wrapper, {
+          //   pullDownRefresh: true,
+          //   pullUpLoad: true
+          // });
+          // this.scroll.on('pullingDown', () => {
+          //   //this.scroll.finishPullDown()
+          // })
+          //
+          // this.scroll.on('pullingUp', () => {
+          //   //this.scroll.finishPullUp()
+          // })
+
+        //},
+        initScroll() {
+          if (!this.$refs.wrapper) {
+            return;
+          }
+          // better-scroll的初始化
+          this.scroll = new BScroll(this.$refs.wrapper, {
+            probeType: this.probeType,
+            click: this.click,
+            scrollX: this.scrollX
+          });
+
+          // 是否触发滚动事件
+          if (this.listenScroll || this.pulldown || this.pullup) {
+            //监听滚动事件
+            this.scroll.on('scroll', (pos) => {
+              if (this.listenScroll) {
+                this.$emit('scroll', pos);
+              }
+              // 下拉刷新
+              if (this.pulldown) {
+                if (pos.y > 50) {
+                  this.pulldownTip = {
+                    text: '松开立即刷新',
+                  }
+                } else {
+                  this.pulldownTip = {
+                    text: '下拉刷新',
+                  }
+                }
+              }
+              //上拉加载
+              if (this.pullup) {
+                if (pos.y < (this.scroll.maxScrollY + -50)) {
+                  this.pullupTip = {
+                    text: '加载中..',
+                  };
+                }else {
+                  this.pullupTip = {
+                    text: '上拉刷新',
+                  };
+                  this.pullupShow = true;
+                }
+              }else {
+                this.pullupShow = false;
+              }
+            })
+          }
+
+          // 底部上拉事件,上拉加载
+          if (this.pullup) {
+            this.scroll.on('touchEnd', (pos) => {
+              // 下拉动作
+              if (pos.y < -40) {
+                this.pulldownTip = {
+                  text: '下拉刷新',     // 松开立即刷新
+                };
+                this.$emit('pullup');
+              }
+            });
+          }
+          //顶部下拉事件,下拉刷新
+          if (this.pulldown) {
+            this.scroll.on('touchEnd', (pos) => {
+              // 下拉动作
+              if (pos.y > 50) {
+                // 重置提示信息
+                this.pulldownTip = {
+                  text: '下拉刷新',     // 松开立即刷新
+                };
+                this.$emit('pulldown');
+              }
+            });
+          }
+
+          // 是否派发列表滚动开始的事件
+          if (this.beforeScroll) {
+            this.scroll.on('beforeScrollStart', () => {
+              this.$emit('beforeScroll')
+            });
+          }
+        },
+        disable() {
+          // 代理better-scroll的disable方法
+          this.scroll && this.scroll.disable();
+        },
+        enable() {
+          // 代理better-scroll的enable方法
+          this.scroll && this.scroll.enable();
+        },
+        refresh() {
+          // 代理better-scroll的refresh方法
+          this.scroll && this.scroll.refresh();
+        },
+        scrollTo() {
+          // 代理better-scroll的scrollTo方法
+          this.scroll && this.scroll.scrollTo.apply(this.scroll, arguments);
+        },
+        scrollToElement() {
+          // 代理better-scroll的scrollToElement方法
+          this.scroll && this.scroll.scrollToElement.apply(this.scroll, arguments);
+        }
+      },
+      watch: {
+        data() {
+          setTimeout(() => {
+            this.refresh()
+          }, this.refreshDelay)
+        }
+      }
+    }
+</script>
+<style lang="scss">
+  .better-scroll{
+    height: 100%;
+    position: relative;
+    overflow: hidden;
+    .content {
+      min-height: calc(100% + 1px);
+      border-top: 1px solid #f2f2f2;
+      overflow: auto;
+    }
+    .list{
+      overflow: auto;
+    }
+    .pulldown-tip {
+      width: 100%;
+      display: flex;
+      justify-content: center;
+      align-items: center;
+      position: absolute;
+      top: -80px;
+      height: 80px;
+      line-height: 80px;
+      color: #bbb;
+      font-size: 3.5vw;
+      z-index: 1;
+    }
+    .pullup-tip{
+      box-sizing: border-box;
+      line-height: 80px;
+      width: 100%;
+      color: #bbb;
+      font-size: 3.5vw;
+      text-align: center;
+      margin: 0 auto;
+    }
+
+  }
+</style>

+ 20 - 2
src/router/router.config.js

@@ -7,7 +7,7 @@ export let routers = [
     path: '/',
     redirect:'/login'
   },
-  
+
   {
     path: '/login',
     component: () => import('@/views/login'),
@@ -200,7 +200,25 @@ export let routers = [
         path: '/securityCheckRegister',
         name: 'securityCheckRegister',
         component: () => import('@/views/menu/securityCheckRegister/index'),
-        meta: { title: '安全检查登记', keepAlive: false }
+        meta: { title: '安全检查登记', keepAlive: true }
+      },
+      {
+        path: '/securityDetail',
+        name: 'securityDetail',
+        component: () => import('@/views/menu/securityCheckRegister/detail'),
+        meta: { title: '安全检查详情', keepAlive: false }
+      },
+      {
+        path: '/addCheckRegister',
+        name: 'addCheckRegister',
+        component: () => import('@/views/menu/securityCheckRegister/addCheck'),
+        meta: { title: '添加检查内容', keepAlive: false ,hideTabBar:true}
+      },
+      {
+        path: '/addWorker',
+        name: 'addWorker',
+        component: () => import('@/views/menu/securityCheckRegister/addWorker'),
+        meta: { title: '选择授权人员', keepAlive: false ,hideTabBar:true}
       },
       {
         path: '/problemItem',

+ 3 - 3
src/views/menu/LZRegister/edit.vue

@@ -159,9 +159,9 @@
         </div >
         <p v-if="enable" class="warning-msg">需要完成所有区域的履职内容才能提交内容</p>
         <div v-if="enable" class="flex-box">
-          <van-button type="default" style="width: 28%;" plain  @click="goBack">取消</van-button>
-          <van-button type="info" style="width: 28%;" plain hairline @click="saveData">保存</van-button>
-          <van-button type="info" style="width: 28%;"  @click="submitData">提交</van-button>
+          <van-button type="default" style="width: 30%;" plain  @click="goBack">取消</van-button>
+          <van-button type="info" style="width: 30%;" plain hairline @click="saveData">保存</van-button>
+          <van-button type="info" style="width: 30%;"  @click="submitData">提交</van-button>
         </div>
       </fieldset>
     </div>

+ 8 - 7
src/views/menu/problemItem/index.vue

@@ -9,12 +9,12 @@
         <date-cell title="发现日期"  v-model="query.submitTime" date-type="date" @change="getDataList"/>
       </div>
       <div class="card-list">
-        <van-list
-          v-model="loading"
-          :finished="finished"
-          finished-text="没有更多了"
-          @load="getDataList"
-        >
+<!--        <van-list-->
+<!--          v-model="loading"-->
+<!--          :finished="finished"-->
+<!--          finished-text="没有更多了"-->
+<!--          @load="getDataList"-->
+<!--        >-->
           <van-empty description="暂无数据" v-if="!dataList || dataList.length === 0" />
             <template v-else>
               <van-cell-group  v-for="(v,i) in dataList">
@@ -66,7 +66,7 @@
                 </van-cell>
               </van-cell-group>
             </template>
-        </van-list>
+<!--        </van-list>-->
       </div>
     </div>
   </div>
@@ -138,6 +138,7 @@ export default {
       }
       if(!this.query.orgId) return this.$toast('请选择机构');
       dataList(data).then(res=>{
+        this.loading = false;
         this.dataList = [...this.dataList,...res.rows];
         this.query.pageNum = res.pageNum;
       })

+ 110 - 0
src/views/menu/securityCheckRegister/addCheck.vue

@@ -0,0 +1,110 @@
+<template>
+  <div class="addCheck">
+    <NavBar />
+    <div class="addCheck-container">
+      <div class="search-flex">
+        <van-search v-model="query.value" placeholder="请输入检查子项" />
+        <select-cell class="van-hairline--right" title="检查内容库" v-model="query.ruleId" :dataList="ruleList" :prop="prop" @change="getDataList"/>
+      </div>
+      <div class="card-list">
+        <Scroll
+          @pulldown="getDataList"
+          @pullup="getDataList"
+          :data='dataList'
+          :pullup="pullup"
+          class="wrapper"
+          ref="wrapper">
+          <van-empty description="暂无数据" v-if="!dataList || dataList.length === 0" />
+          <div  v-else class="list-item">
+            <van-cell
+              v-for="(item, index) in dataList"
+              clickable
+              :key="item.id"
+              :title="item.itemName"
+              :label="item.pointName"
+              @click="click(item,index)">
+              <template #right-icon>
+                <van-checkbox v-model="item.checked"/>
+              </template>
+            </van-cell>
+          </div>
+        </Scroll>
+      </div>
+      <div>
+        <van-button type="info" size="large" @click="addItem">确认选中</van-button>
+      </div>
+    </div>
+  </div>
+</template>
+
+<script>
+import NavBar from '@/components/NavBar'
+import SelectCell from '@/components/selectCell'
+import Scroll from '@/components/scroll/scroll'
+import {checkItemList,checkList} from './api'
+export default {
+  name: "addCheck",
+  components: {
+    NavBar,
+    Scroll,
+    SelectCell,
+  },
+  data(){
+    return {
+      query:{
+        value:'',
+        ruleId:null,
+        pageNum:1,
+        pageSize:10,
+      },
+      dataList:[],
+      ruleList:[],
+      selected:[],
+      prop:{
+        label:'name',
+        value:'id'
+      },
+      pullup:false,
+    }
+  },
+  mounted(){
+    this.getCheckItem();
+  },
+  methods:{
+    click(v,i){
+      this.$set(this.dataList[i],'checked',!this.dataList[i].checked);
+    },
+    addItem(){
+      this.selected = this.dataList.filter(v=>v.checked);
+      console.log(this.selected, 666)
+      this.$router.push({path:'/securityCheckRegister',params:{selected:this.selected}})
+    },
+    getCheckItem(){
+      let data = {orgType:4};
+      checkItemList(data).then(res=>{
+        this.ruleList = res.data;
+        this.query.ruleId = res.data[0].id;
+        this.getDataList()
+      })
+    },
+    getDataList(){
+      checkList(this.query).then(res=>{
+        res.rows.forEach(v=>{
+          v.checked = false;
+        });
+        this.dataList = res.rows
+      })
+    },
+  }
+}
+</script>
+
+<style lang="scss" scoped>
+.addCheck{
+
+}
+.card-list{
+  height: calc(100vh - 424px);
+  overflow: auto;
+}
+</style>

+ 13 - 0
src/views/menu/securityCheckRegister/addWorker.vue

@@ -0,0 +1,13 @@
+<template>
+
+</template>
+
+<script>
+export default {
+  name: "selectWorker"
+}
+</script>
+
+<style scoped>
+
+</style>

+ 27 - 4
src/views/menu/securityCheckRegister/api.js

@@ -1,17 +1,17 @@
 import request from "@/utils/request";
 //获取列表
-export function dataList(params) {
+export function dataList(data) {
   return request({
     url: "/core/safetycheck/register/page",
-    method: "get",
-    params,
+    method: "post",
+    data,
   });
 }
 
 //获取详情
 export function registerDetail(id){
   return request({
-    url: "/core/safetycheck/register/"+id,
+    url: "/core/safetycheck/register/app/"+id,
     method: "get",
   });
 }
@@ -34,5 +34,28 @@ export function registerGrant(data){
   });
 }
 
+//查询角色
+export function registerRole(orgId){
+  return request({
+    url: "/system/role/getnamesbyorgid/"+orgId,
+    method: "get",
+  });
+}
 
+//获取检查内容库
+export function checkItemList(params){
+  return request({
+    url: "core/safetycheck/rule/ruleListForOrg",
+    method: "get",
+    params
+  });
+}
+//
+export function checkList(params){
+  return request({
+    url: "core/safetycheck/ruleItem/pointSelectionPage",
+    method: "get",
+    params
+  });
+}
 

+ 441 - 0
src/views/menu/securityCheckRegister/detail.vue

@@ -0,0 +1,441 @@
+<template>
+  <div class="lz-edit">
+    <nav-bar></nav-bar>
+    <div class="page-container">
+      <!--   基本信息   -->
+      <div class="card" v-if="taskInfo">
+        <van-panel :title="taskInfo.taskName"  :status="getDictLabel(taskInfo.status,'safety_check_status')">
+          <van-cell title="日期时间" :value="rangDate(taskInfo.planstarttime,taskInfo.planendtime)" />
+          <van-cell title="受检机构" :value="taskInfo.beCheckedOrgName" />
+          <van-field
+            v-model="taskInfo.checkTeam"
+            label="检查组成员"
+            rows="2"
+            autosize
+            type="textarea"
+            placeholder="请输入用户名" />
+        </van-panel>
+      </div>
+
+
+      <!--  检查项目    -->
+      <fieldset class="fieldset"  :disabled="!enable">
+        <div class="card" >
+          <p class="legend">检查项目 <span @click="addCheck">添加检查内容</span></p>
+          <van-collapse v-model="activeNames" v-for="v in checkList" :key="v.areaId">
+            <van-collapse-item :title="v.itemName" :name="v.itemName" >
+              <div v-for="(item,index) in v.pointList" :key="item.itemId">
+                <van-cell :title="item.itemName">
+                  <template #right-icon>
+                    <van-switch
+                      v-if="enable"
+                      style="margin-left: 10px;"
+                      v-model="item.resvalue"
+                      :active-value="1"
+                      :inactive-value="0"
+                      inactive-color="#4fc08d"
+                      active-color="#ee0a24"
+                      @change="switchChange(item)"
+                      size="20" />
+                    <span v-else>
+<!--                      <van-icon  v-if="item.resvalue" name="success" color="#07c160" />-->
+<!--                      <van-icon v-else name="fail" color="#ee0a24"/>-->
+                      <van-tag v-if="item.resvalue" type="warning">隐患</van-tag>
+                      <van-tag v-else type="success">正常</van-tag>
+                    </span>
+                  </template>
+                </van-cell>
+                <van-cell-group v-show="item.resvalue">
+                  <select-cell required :disabled="!enable" title="整改期限" v-model="item.rectificationDeadline"  :data-list="dayList" />
+                  <van-field
+                    required
+                    v-model="item.resremark"
+                    rows="1"
+                    autosize
+                    label="情况描述:"
+                    type="textarea"
+                    placeholder="请输入"/>
+                  <div class="upload-box" >
+                    <uploader :maxCount="5" v-if="enable" v-model="item.imgData"/>
+                    <van-cell v-else>
+                      <div class="nfc-img van-hairline--surround" v-for="(v,i) in item.imgData" :key="v.imgPath" @click="clickWarnImage(item.imgData,i)">
+                        <img :src="imgUrl(v.imgPath)" alt="" >
+                        <span>{{v.checkName}}</span>
+                      </div>
+<!--                      <img class="nfc-img" v-for="v in item.imgData" :src="imgUrl(v.imgPath)" alt="" :key="v.id">-->
+                    </van-cell>
+                  </div>
+                </van-cell-group>
+                <date-cell
+                  :disabled="!enable"
+                  v-if="item.businessType === 1"
+                  v-for="(val,ind) in item.protectionVo"
+                  :title="val.protectionName"
+                  v-model="val.statusUpdateTime"
+                  :key="val.id"
+                  date-type="datetime" />
+              </div>
+            </van-collapse-item>
+          </van-collapse>
+        </div >
+
+        <div v-if="enable" class="flex-box">
+          <van-button type="default" style="width: 30%;" plain  @click="goBack">授权</van-button>
+          <van-button type="info" style="width: 30%;" plain hairline @click="saveData">保存</van-button>
+          <van-button type="info" style="width: 30%;"  @click="submitData">提交</van-button>
+        </div>
+      </fieldset>
+    </div>
+
+<!--    <van-image-preview v-model="showPreView" :images="preViewImages.images" :startPosition="preViewImages.startPosition">-->
+<!--      <template v-slot:index>第{{ index }}页</template>-->
+<!--    </van-image-preview>-->
+
+    <!--  nfc弹窗  -->
+    <nfc-popup v-if="enable" ref="NfcPopup" @change="changeNfcImg"></nfc-popup>
+  </div>
+</template>
+
+<script>
+import NavBar from '@/components/NavBar';
+import SelectCell from '@/components/selectCell';
+import DateCell from '@/components/dateCell';
+import Uploader from '@/components/upload/uploader';
+import NfcPopup from '@/components/nfcPopup/more';
+import {registerDetail,registerSubmit} from "./api";
+import {formatDate} from "@/filters/filter";
+import {getDict} from "@/api/toConsult";
+import {imgUrl} from "@/utils";
+import { ImagePreview } from 'vant';
+import {mapGetters} from "vuex";
+export default {
+  components:{NavBar,SelectCell,DateCell,Uploader,NfcPopup},
+  data(){
+    return {
+      activeNames: ['1'],
+      //基本信息
+      taskInfo:[],
+      NFCList:[],
+      //区域下检查内容列表
+      checkList:[],
+      //检查内容具体项列表
+      checkItemList:[],
+      //nfc扫描数量
+      NFCNum:0,
+      //所有检查项数量
+      allCheckNum:0,
+      //区域下检查项数量
+      checkNum:0,
+      //nfc图片
+      nfcImage:[],
+      enable:false,
+      stateList:[],
+      dayList:[],
+      preViewImages:{
+        images:[],
+        startPosition:0
+      },
+      dicts:['safety_check_status'],
+      showPreView:false,
+    }
+  },
+  computed:{
+    ...mapGetters(['dictionary'])
+  },
+  created() {
+    getDict( 'resumption_status' ).then(res => {
+      let { data } = res
+      this.stateList = data;
+    })
+    getDict( 'rectification_deadline' ).then(res => {
+      let { data } = res
+      this.dayList = data;
+    })
+  },
+  mounted() {
+    this.getData();
+  },
+  methods:{
+    addCheck(){
+      this.$router.push({path:'/addCheckRegister'});
+    },
+    clickWarnImage(arr,i){
+      this.preViewImages.images = arr.map(v=>imgUrl(v.imgPath));
+      this.preViewImages.startPosition = i;
+      ImagePreview(this.preViewImages)
+    },
+    preViewNFC(i){
+      this.preViewImages.images = this.nfcImage.map(v=>imgUrl(v.img));
+      this.preViewImages.startPosition = i;
+      ImagePreview(this.preViewImages)
+    },
+    getDicts(s){
+      return this.stateList.find(v=> s == v.dictValue)?.dictLabel;
+    },
+    //初始化数据
+    getData() {
+      let taskId = this.$route.query.id;
+      registerDetail(taskId).then(res=>{
+        console.log(res,'res')
+        this.taskInfo = res.data;
+        this.enable = this.taskInfo.status === 1 || this.taskInfo.status === 2; //是否可编辑
+        this.checkList = res.data.checkList;
+      })
+    },
+    //保存数据
+    saveData(){
+      let pointdata = [];
+      let checkNFC = [];
+      this.areaList.forEach(area=>{
+        area.nfclist.forEach(v=>{
+          if(v.status === 1){
+            checkNFC.push(v)
+          }
+        })
+        area.checklist.forEach(item=>{
+         item.checkitemlist.forEach(checkItem=>{
+            checkItem.protections = checkItem.protectionVo;
+            checkItem.resRemark = checkItem.resremark;
+            checkItem.resStatus = checkItem.resstatus;
+            checkItem.areaId = checkItem.areaid;
+            checkItem.id = checkItem.pointdataid;
+            checkItem.pointId = checkItem.pointid;
+            checkItem.resValue = checkItem.resvalue;
+            checkItem.resumptionId = this.$route.query.id;
+            pointdata.push(checkItem);
+          })
+        })
+      });
+      //验证必填项
+      let arr = pointdata.filter(v=>{
+        if(v.resvalue === 1 ){
+          return !v.resremark || !v.rectificationDeadline
+        }
+      })
+      if(arr.length) return this.$toast(`${arr[0].areaname}-${arr[0].itemname}:信息不完整请填写`);
+      let data = {
+        dateTime:new Date(),
+        isSubmit:0,
+        resumptionId:this.$route.query.id,
+        year: this.taskInfo.year,
+        quarter: this.taskInfo.quarter,
+        nfcData:checkNFC,
+        pointdata,
+      }
+      saveTaskData(data).then(res=>{
+        this.$toast('提交成功');
+        this.$router.go(-1);
+      })
+    },
+
+
+    //获取当前区域检查项数量
+    getCheckItemNum(){
+      let num = 0;
+      this.selectArea.checklist.forEach(v=>{
+        num += v.checkitemlist.length;
+      });
+      this.checkNum = num;
+    },
+    //获取当前区域nfc数量
+    getNFCItemNum(){
+      let num = 0;
+      this.selectArea.nfclist.forEach(v=>{
+        if(v.status === 0 || !v.img){
+          num++;
+        }
+      })
+      this.NFCNum = num;
+    },
+    //提交数据
+    submitData(){
+      let pointdata = [];
+      let checkNFC = [];
+      this.areaList.forEach(area=>{
+        area.nfclist.forEach(v=>{
+          if(v.status === 1){
+            checkNFC.push(v)
+          }
+        })
+        area.checklist.forEach(item=>{
+          item.checkitemlist.forEach(checkItem=>{
+            checkItem.protections = checkItem.protectionVo;
+            checkItem.resRemark = checkItem.resremark;
+            checkItem.resStatus = checkItem.resstatus;
+            checkItem.areaId = checkItem.areaid;
+            checkItem.id = checkItem.pointdataid;
+            checkItem.pointId = checkItem.pointid;
+            checkItem.resValue = checkItem.resvalue;
+            checkItem.resumptionId = this.$route.query.id;
+            pointdata.push(checkItem);
+          })
+
+        })
+      })
+
+      //验证必填项
+      let arr = pointdata.filter(v=>{
+        if(v.resvalue === 1 ){
+          console.log(v,'验证')
+          return !v.resremark || !v.rectificationDeadline
+        }
+      })
+      if(arr.length) return this.$toast(`${arr[0].areaname}-${arr[0].itemname}:信息不完整请填写`);
+
+      let data = {
+        dateTime:new Date(),
+        isSubmit:1,
+        resumptionId:this.$route.query.id,
+        year: this.taskInfo.year,
+        quarter: this.taskInfo.quarter,
+        nfcData:checkNFC,
+        pointdata,
+      }
+      saveTaskData(data).then(res=>{
+        this.$toast('提交成功');
+        this.$router.go(-1);
+      })
+    },
+
+    //返回
+    goBack(){
+      this.$router.go(-1);
+      this.clearData();
+    },
+    //点击NFC图标
+    clickNFC(){
+      if(!this.NFCNum) return;
+      let arr = this.selectArea.nfclist.filter(item=>{
+        return item.status == 0;
+      })
+      this.$refs.NfcPopup.show(arr);
+    },
+    //清空数据
+    clearData(){
+      this.areaList = [];
+      this.taskInfo= [];
+      this.selectArea = [];
+      this.NFCList = [];
+      this.checkList = [];
+      this.checkItemList = [];
+      this.NFCNum = 0;
+      this.enable = false;
+    },
+    //切换开关时添加操作时间
+    switchChange(item){
+      console.log(item,'666')
+      item.resTime = formatDate(new Date());
+    },
+    //添加图片时的回调
+    changeNfcImg(imgItem){
+      console.log(imgItem,this.selectArea.nfclist,'imgItem')
+      this.selectArea.nfclist.forEach(v=>{
+        if(v.nfccdoe === imgItem.nfcCode){
+          v.img = imgItem.url;
+          v.status = 1;
+          v.scanMethod = 1;
+          this.nfcImage.push(v);
+        }
+      })
+      console.log( this.selectArea.nfclist,this.nfcImage,'nfcObj')
+    },
+  }
+}
+</script>
+<style lang="scss" scoped>
+
+  .lz-edit{
+    height: 100%;
+    overflow: hidden;
+  }
+  .page-container{
+    height: calc(100vh - 194px);
+    overflow: auto;
+    padding: 20px;
+  }
+  .flex-box{
+    display: flex;
+    justify-content: space-between;
+    align-items: center;
+    >span{
+      margin: 0 20px;
+    }
+  }
+  .legend{
+    background-color: #fff;
+    padding: 0 20px;
+    height: 80px;
+    line-height: 80px;
+    font-size: 30px;
+    display: flex;
+    justify-content: space-between;
+    >span{
+      color: orange;
+    }
+  }
+  .card{
+    margin-bottom: 20px;
+    box-shadow: 0 10px 10px #eaeaea;
+  }
+  .check-area{
+    background-color: #f1f1f1;
+    margin: 10px;
+    padding:20px;
+    color:#aaa;
+    border-radius: 6px;
+    display: flex;
+    justify-content: space-between;
+    align-items: center;
+    box-shadow: 0 2px 6px #ddd;
+  }
+  .nfc-icon{
+    width: 50px;
+    height: 50px;
+    margin-left: 20px;
+  }
+  .custom-title {
+    align-self: center;
+    vertical-align: middle;
+  }
+  .upload-box{
+    margin: 30px;
+  }
+  .warning-msg{
+    color: orange;
+    text-align: center;
+    height: 80px;
+    line-height: 80px;
+  }
+  .active{
+    color: #fff;
+    background-color: #1989fa;
+  }
+  .nfc-img{
+    display: inline-block;
+    width: 140px;
+    height: 140px;
+    margin: 0 10px;
+    position: relative;
+    >img{
+      width: 100%;
+      height: 100%;
+      border: none;
+    }
+    >span{
+      position: absolute;
+      padding: 0 10px;
+      bottom: 0;
+      left: 0;
+      display: block;
+      width: 100%;
+      background-color: rgba(0,0,0,.2 );
+      color: #eaeaea;
+      font-size: 20px;
+      overflow: hidden;
+      text-overflow: ellipsis;
+      white-space: nowrap;
+      line-height: 30px;
+      height: 30px;
+    }
+  }
+</style>

+ 167 - 72
src/views/menu/securityCheckRegister/index.vue

@@ -3,58 +3,112 @@
     <NavBar />
     <div class="statistics-container">
       <!--   搜索   -->
-      <van-collapse v-model="active">
-        <van-collapse-item title="搜索条件" name="1">
-          <div class="org-line van-hairline--bottom">
-            <van-row>
-              <van-col span="5">
-                <div class="org-label">检查机构</div>
-              </van-col>
-              <van-col span="19">
-                <org-tree v-model="query.checkOrgId" @change="getDataList"></org-tree>
-              </van-col>
-            </van-row>
-          </div>
-          <div class="org-line van-hairline--bottom">
-            <van-row>
-              <van-col span="5">
-                <div class="org-label">受检机构</div>
-              </van-col>
-              <van-col span="19">
-                <org-tree v-model="query.beCheckedOrgId" @change="getDataList"></org-tree>
-              </van-col>
-            </van-row>
-          </div>
-          <div class="search-box van-hairline--bottom">
-            <select-cell title="检查角色" v-model="query.roldIds" :dataList="planList" :prop="prop" @change="getDataList"/>
-          </div>
-          <div class="search-box van-hairline--bottom">
-            <select-cell title="状态" v-model="query.planId" :dataList="planList" :prop="prop" @change="getDataList"/>
-            <date-cell title="截止日期"  v-model="query.taskTime" date-type="date" @change="getDataList"/>
-          </div>
-        </van-collapse-item>
-      </van-collapse>
+      <div style="background-color: #fff;">
+        <div class="org-line van-hairline--bottom">
+          <van-row>
+<!--            <van-col span="5">-->
+<!--              <div class="org-label">检查机构</div>-->
+<!--            </van-col>-->
+            <van-col span="24">
+              <org-tree v-model="query.checkOrgId" placeholder="选择检查机构" @change="getDataList"></org-tree>
+            </van-col>
+          </van-row>
+        </div>
+        <div class="org-line van-hairline--bottom">
+          <van-row>
+<!--            <van-col span="5">-->
+<!--              <div class="org-label">受检机构</div>-->
+<!--            </van-col>-->
+            <van-col span="24">
+              <org-tree v-model="query.beCheckedOrgId" clearable placeholder="选择受检机构" @change="getDataList"></org-tree>
+            </van-col>
+          </van-row>
+        </div>
+      </div>
+
+      <div class="van-hairline--bottom">
+        <search-select-cell title="检查角色" v-model="query.roldIds" :dataList="rolesList" :prop="prop" @change="getDataList"/>
+      </div>
+      <div class="van-hairline--bottom">
+        <date-cell title="检查日期"  v-model="query.taskTime" date-type="date" @change="getDataList"/>
+<!--        <select-cell title="状态" v-model="query.state" :dataList="getDictItem('safety_check_status')" @change="getDataList"/>-->
+      </div>
 
       <div class="card-list">
-        <k-list :list="dataList" :params="query" :auto="false" ref="list" >
-          <template slot-scope="{ data }">
-            <van-cell-group>
-              <van-cell :title="data.orgName" >
-                <template #extra>
-                  <div class="card-num">
-                    {{data.finishRate}}
-                  </div>
-                </template>
-                <template #label>
-                  <div class="flex-box">
-                    <div>应培训数:{{data.shouldFinish}}</div>
-                    <div>已培训数:{{data.finish}}</div>
-                  </div>
-                </template>
-              </van-cell>
-            </van-cell-group>
-          </template>
-        </k-list>
+        <Scroll
+          @pulldown="getDataList"
+          @pullup="getDataList"
+          :data='dataList'
+          :pullup="pullup"
+          class="wrapper"
+          ref="wrapper">
+          <van-empty description="暂无数据" v-if="!dataList || dataList.length === 0" />
+          <div  v-else class="list-item">
+            <van-panel v-for="(v,i) in dataList" :title="v.taskName" :desc="`${formatDate(v.planStartTime,'YYYY-MM-DD')}~${formatDate(v.planEndTime,'YYYY-MM-DD')}`" >
+<!--              <van-tabs v-model="active">-->
+<!--                <van-tab title="完成">-->
+<!--                  <van-collapse v-if="v.completed.length > 0" v-model="activeNames" :key="v.planId">-->
+<!--                    <van-collapse-item title="标题1" name="1"  >-->
+<!--                      <van-cell-->
+<!--                        v-for="(a,index) in v.completed" :key="a.taskId"-->
+<!--                        :title="a.beCheckedOrgName"-->
+<!--                        :value="getDictLabel(a.status,'safety_check_status')"-->
+<!--                        :to="{path:path,query:{id:a.taskId,enable:1}}"-->
+<!--                        is-link/>-->
+<!--                    </van-collapse-item>-->
+<!--                  </van-collapse>-->
+<!--                </van-tab>-->
+<!--                <van-tab title="未完成">-->
+<!--                  <van-collapse v-if="v.uncompleted.length > 0" v-model="activeNames" :key="v.planId">-->
+<!--                    <van-collapse-item title="标题1" name="1" >-->
+<!--                      <van-cell-->
+<!--                        v-for="(a,index) in v.uncompleted" :key="a.taskId"-->
+<!--                        :title="a.beCheckedOrgName"-->
+<!--                        :value="getDictLabel(a.status,'safety_check_status')"-->
+<!--                        :to="{path:path,query:{id:a.taskId,enable:1}}"-->
+<!--                        is-link/>-->
+<!--                    </van-collapse-item>-->
+<!--                  </van-collapse>-->
+<!--                </van-tab>-->
+<!--              </van-tabs>-->
+              <van-collapse v-model="activeNames" :key="v.planId">
+                <van-collapse-item name="1" >
+                  <template #title>
+                    <div class="collapse-title">
+                      <div :class="{'active':v.active==1}" @click.stop="changeList(v,1)">完成</div>
+                      <div :class="{'active':v.active==2}" @click.stop="changeList(v,2)">未完成</div>
+                    </div>
+                  </template>
+                    <van-cell
+                      v-if="v.active==1? v.completed.length > 0 : v.uncompleted.length > 0"
+                      v-for="(a,index) in v.active==1? v.completed:v.uncompleted" :key="a.taskId"
+                      :title="a.beCheckedOrgName"
+                      :value="getDictLabel(a.status,'safety_check_status')"
+                      :to="{path:path,query:{id:a.taskId,enable:1}}"
+                      is-link/>
+                </van-collapse-item>
+              </van-collapse>
+            </van-panel>
+          </div>
+
+
+<!--            <van-button type="info" @click="to">详情</van-button>-->
+<!--            <van-cell-group v-for="v in dataList">-->
+<!--              <van-cell :title="v.orgName" >-->
+<!--                <template #extra>-->
+<!--                  <div class="card-num">-->
+<!--                    {{v.finishRate}}-->
+<!--                  </div>-->
+<!--                </template>-->
+<!--                <template #label>-->
+<!--                  <div class="flex-box">-->
+<!--                    <div>应培训数:{{v.shouldFinish}}</div>-->
+<!--                    <div>已培训数:{{v.finish}}</div>-->
+<!--                  </div>-->
+<!--                </template>-->
+<!--              </van-cell>-->
+<!--            </van-cell-group>-->
+        </Scroll>
       </div>
 
     </div>
@@ -64,67 +118,92 @@
 import NavBar from '@/components/NavBar'
 import OrgTree from '@/components/orgTree'
 import KList from '@/components/list'
-import dateCell from '@/components/dateCell'
-import selectCell from '@/components/selectCell'
-import {dataList} from './api'
+import DateCell from '@/components/dateCell'
+import SelectCell from '@/components/selectCell'
+import SearchSelectCell from '@/components/SearchSelectCell'
+import Scroll from '@/components/scroll/scroll'
+import {dataList,registerRole} from './api'
 import {mapGetters} from "vuex";
 import {formatDate} from "@/filters/filter";
 export default {
   components: {
     NavBar,
     OrgTree,
-    dateCell,
-    selectCell,
-    KList
+    DateCell,
+    SelectCell,
+    SearchSelectCell,
+    KList,
+    Scroll
   },
   data() {
     return {
-      active:['1'],
+      activeNames:['1'],
+      //配置子页面路径
+      path:'/securityDetail',
       query:{
-        taskTime:null,
+        taskTime: null,
         checkOrgId:null,
         beCheckedOrgId:null,
         roldIds:null,
+        state:'1',
       },
-      planList:[],
+      rolesList:[],
       prop:{
         label:'name',
         value:'id',
       },
       loading:false,
-      //dataList:[]
+      dataList:[],
+      dicts:['safety_check_status'],
+      //控制上拉加载
+      pullup:false,
+      finishList:[],
+      unfinishedList:[],
     }
   },
   mounted() {
     this.initData();
   },
   computed:{
-    ...mapGetters(['orgId']),
+    ...mapGetters(['orgId','dictionary']),
   },
   watch:{
     'query.checkOrgId':{
       handler(v){
         this.getRoleList();
-      },
-      immediate:true
+      }
     }
   },
   methods: {
-    dataList,
+    formatDate,
+    changeList(item,type,event){
+      console.log(item,'eeeeeee')
+      this.$set(item,'active',type);
+    },
+
     initData(){
+      console.log('getDataList');
       this.query.checkOrgId = this.orgId;
-      this.getPlanList();
+      this.query.taskTime = formatDate(new Date(),'YYYY-MM-DD');
+      this.getDataList();
     },
     getRoleList(){
-
+      registerRole(this.query.checkOrgId).then(res=>{
+        this.rolesList = res.data;
+      })
     },
     getDataList(){
+      console.log('getDataList')
       let data = {
         ...this.query
       }
-      if(!this.query.orgId) return this.$toast('请选择机构');
+      if(!this.query.checkOrgId) return this.$toast('请选择机构');
       dataList(data).then(res=>{
-        this.dataList = res.data;
+        this.dataList = res.rows.map(v=>{
+          v.active = 1
+          return v
+        });
+        console.log(this.dataList,'ressssssss')
       })
     }
   }
@@ -149,7 +228,7 @@ export default {
 
 }
 .org-line{
-  padding-left:30px;
+  padding:0 10px;
   background-color: #fff;
 }
 .org-label{
@@ -160,16 +239,32 @@ export default {
   font-size: 28px;
 }
 .card-list{
-  padding: 20px;
-  height: calc(100vh - 550px);
+  height: calc(100vh - 580px);
   overflow: auto;
 }
+.list-item{
+  padding: 20px;
+}
 .card-num{
   display: flex;
   align-items: center;
   font-size: 28px;
   color: #009dff;
 }
+.collapse-title{
+  display: flex;
+  justify-content: flex-start;
+  align-items: center;
+  font-size: 28px;
+  color: #ccc;
+  >div{
+    width: 40%;
+    display: flex;
+  }
+  >div.active{
+    color: #009dff;
+  }
+}
 .flex-box{
   display: flex;
   align-items: center;
@@ -178,7 +273,7 @@ export default {
   }
 }
 .search-box{
-display: flex;
+ display: flex;
   justify-content: space-between;
   align-items: center;
   >div{

+ 123 - 0
yarn.lock

@@ -1206,6 +1206,109 @@
     "@babel/helper-validator-identifier" "^7.19.1"
     to-fast-properties "^2.0.0"
 
+"@better-scroll/core@^2.5.1":
+  version "2.5.1"
+  resolved "https://registry.npmmirror.com/@better-scroll/core/-/core-2.5.1.tgz#de53f089a2f53f51e58e5042556fe0d3e1655aa9"
+  integrity sha512-koKOuYA55dQ04FJRIVUpMGDr1hbCfWmfX0MGp1hKagkQSWSRpwblqACiwtggVauoj9aaJRJZ9hDsTM4weaavlg==
+  dependencies:
+    "@better-scroll/shared-utils" "^2.5.1"
+
+"@better-scroll/indicators@^2.5.1":
+  version "2.5.1"
+  resolved "https://registry.npmmirror.com/@better-scroll/indicators/-/indicators-2.5.1.tgz#a5d2da343fc6d0865846f1f8d2153eb423301be1"
+  integrity sha512-Hk+Y00pR6fTsu6C9HGg1yYZtsu1gAcTgcs4C9aM5h6fQANX/T2YIYrOSjZmdL+js2PTcXJWZS8VM4Xjoi1PbfQ==
+  dependencies:
+    "@better-scroll/core" "^2.5.1"
+
+"@better-scroll/infinity@^2.5.1":
+  version "2.5.1"
+  resolved "https://registry.npmmirror.com/@better-scroll/infinity/-/infinity-2.5.1.tgz#f834e9b31d4174eff25c42793efb0cf705b7fe8f"
+  integrity sha512-GKHrrasIh0KlGzhASHDo5hEEBJcDFpP4XaZGPH9Ey8+QBH6/O1ykAXS2ixkVAOTkBrv+KgFXoCUr4oN1xWeM+g==
+  dependencies:
+    "@better-scroll/core" "^2.5.1"
+
+"@better-scroll/mouse-wheel@^2.5.1":
+  version "2.5.1"
+  resolved "https://registry.npmmirror.com/@better-scroll/mouse-wheel/-/mouse-wheel-2.5.1.tgz#002d16264238122ecc7713c86eddc282ea52b79c"
+  integrity sha512-DGnrirRMY6zMM7xwgx09D/cA9A//3J1/uDkq8iBVEyE5p0sEr/keQpjEfFHGkBRa505BnbBwdbN6f5lugEDSPw==
+  dependencies:
+    "@better-scroll/core" "^2.5.1"
+
+"@better-scroll/movable@^2.5.1":
+  version "2.5.1"
+  resolved "https://registry.npmmirror.com/@better-scroll/movable/-/movable-2.5.1.tgz#65a8e0942087723172f91283363e2339ad567eaf"
+  integrity sha512-8bLPRY15bbK4K5+tjrtdaKsFFKmJx72wRdg+xz3xQGFcTD940HFkJiORSOcz8Ufue7eOJfcmreQJBw6XY+TqTw==
+  dependencies:
+    "@better-scroll/core" "^2.5.1"
+
+"@better-scroll/nested-scroll@^2.5.1":
+  version "2.5.1"
+  resolved "https://registry.npmmirror.com/@better-scroll/nested-scroll/-/nested-scroll-2.5.1.tgz#8aa07da6be3444eeaafe3f4b610f82785fd7f98a"
+  integrity sha512-3cRsARxf9tq1VWBq7YAaET0xGAmgY1ERMmnXDo2gHFrmsJoNOionlpAeHdZvKQp2jG7JrzJ1O27nGCXf40gnkw==
+  dependencies:
+    "@better-scroll/core" "^2.5.1"
+
+"@better-scroll/observe-dom@^2.5.1":
+  version "2.5.1"
+  resolved "https://registry.npmmirror.com/@better-scroll/observe-dom/-/observe-dom-2.5.1.tgz#7e69e46cba1a5b4aa36c498204e60379ac4191d8"
+  integrity sha512-TCMGFLRfpXBPIwtUV/efliUmfmrhSNI7NXdSyjdWjsLOS7dh3eFkmcom5ERVWMaXVELSmujGXLqobT+dT0C/jg==
+  dependencies:
+    "@better-scroll/core" "^2.5.1"
+
+"@better-scroll/observe-image@^2.5.1":
+  version "2.5.1"
+  resolved "https://registry.npmmirror.com/@better-scroll/observe-image/-/observe-image-2.5.1.tgz#2c8279e44fa8d24614d39b14063c0483c874827c"
+  integrity sha512-0Lhfj83o8EESwOxr8bfStCzNOokTm3KB7JeyMS8u/xl+3tyTuls9889cyAukYk4Yly1cS49pCGfj2P8YOiwtUg==
+  dependencies:
+    "@better-scroll/core" "^2.5.1"
+
+"@better-scroll/pull-down@^2.5.1":
+  version "2.5.1"
+  resolved "https://registry.npmmirror.com/@better-scroll/pull-down/-/pull-down-2.5.1.tgz#ad1c741ddda8f771767dc455906637d0567ae449"
+  integrity sha512-Y6XcGu2NlevPg3k9VBRRFvpmfoTA+rO96JGdog2qKHclIPNXnsVwsIHtZfAm9weE/f9UuC4BnB+VUFRlucfupg==
+  dependencies:
+    "@better-scroll/core" "^2.5.1"
+
+"@better-scroll/pull-up@^2.5.1":
+  version "2.5.1"
+  resolved "https://registry.npmmirror.com/@better-scroll/pull-up/-/pull-up-2.5.1.tgz#d5bcfd8343cdb0601b96484f410ee678c22a3a44"
+  integrity sha512-1hu3xSMxdB8T391KffpNZ7g93lMwZEHjfb1F1Y4KvIkciDt8nXqkGpqrZF+YwR+EJTgYcWqUO8kgmI6XXu7Pkg==
+  dependencies:
+    "@better-scroll/core" "^2.5.1"
+
+"@better-scroll/scroll-bar@^2.5.1":
+  version "2.5.1"
+  resolved "https://registry.npmmirror.com/@better-scroll/scroll-bar/-/scroll-bar-2.5.1.tgz#89f8aea8f6beec93ecefbf98e0cb9aa51322e62b"
+  integrity sha512-i6r60pWG/ztkFK2j5Gj54I0LJb2jGh5TWJNQBoW0gUkp28B+0JvBFTwZn9tF7beZCBorKR7Hvvu4O9A1TJy94Q==
+  dependencies:
+    "@better-scroll/core" "^2.5.1"
+
+"@better-scroll/shared-utils@^2.5.1":
+  version "2.5.1"
+  resolved "https://registry.npmmirror.com/@better-scroll/shared-utils/-/shared-utils-2.5.1.tgz#ed6a1b5713462fa50afd8bb7d172ca218a0b7f2e"
+  integrity sha512-AplkfSjXVYP9LZiD6JsKgmgQJ/mG4uuLmBuwLz8W5OsYc7AYTfN8kw6GqZ5OwCGoXkVhBGyd8NeC4xwYItp0aw==
+
+"@better-scroll/slide@^2.5.1":
+  version "2.5.1"
+  resolved "https://registry.npmmirror.com/@better-scroll/slide/-/slide-2.5.1.tgz#d61788b304f305915231430e7c38b22598bcb5b9"
+  integrity sha512-aDOrfsmjAcz6DXN7mDX3tPieAn195R43Yn9e3waI19TIEok/mQlI1a/kb5quqWOoxkiaZQ8xe3vx5ZTj9C+F6Q==
+  dependencies:
+    "@better-scroll/core" "^2.5.1"
+
+"@better-scroll/wheel@^2.5.1":
+  version "2.5.1"
+  resolved "https://registry.npmmirror.com/@better-scroll/wheel/-/wheel-2.5.1.tgz#941745457780584e2ccd385b1588c88c0550f2b0"
+  integrity sha512-fYLcEvkh88Z/2L+P5/+SGMunuc+HzAjGOiORIa/x21qb/knO2RFH4A/V1Rt3OIW4QluWzuFnU6jJRPlsQVZ4fg==
+  dependencies:
+    "@better-scroll/core" "^2.5.1"
+
+"@better-scroll/zoom@^2.5.1":
+  version "2.5.1"
+  resolved "https://registry.npmmirror.com/@better-scroll/zoom/-/zoom-2.5.1.tgz#f43813c9c6cf8aa0c5745fd0cf7c605416f84f1b"
+  integrity sha512-aGvFY5ooeZWS4RcxQLD+pGLpQHQxpPy0sMZV3yadcd2QK53PK9gS4Dp+BYfRv8lZ4/P2LoNEhr6Wq1DN6+uPlA==
+  dependencies:
+    "@better-scroll/core" "^2.5.1"
+
 "@discoveryjs/json-ext@0.5.7":
   version "0.5.7"
   resolved "https://registry.yarnpkg.com/@discoveryjs/json-ext/-/json-ext-0.5.7.tgz#1d572bfbbe14b7704e0ba0f39b74815b84870d70"
@@ -2199,6 +2302,26 @@ batch@0.6.1:
   resolved "https://registry.yarnpkg.com/batch/-/batch-0.6.1.tgz#dc34314f4e679318093fc760272525f94bf25c16"
   integrity sha512-x+VAiMRL6UPkx+kudNvxTl6hB2XNNCG2r+7wixVfIYwu/2HKRXimwQyaumLjMveWvT2Hkd/cAJw+QBMfJ/EKVw==
 
+better-scroll@^2.5.1:
+  version "2.5.1"
+  resolved "https://registry.npmmirror.com/better-scroll/-/better-scroll-2.5.1.tgz#36680afff3756b84296f40c70d9d1793527a7e63"
+  integrity sha512-OiF3cQroRfTzf+CRQH2z1G52ZAlNHINI6lCAvDmyFu0o0nRuTaV9F+fmBGIU2BL5p5IplUQ4E7sYa1TLfZarzQ==
+  dependencies:
+    "@better-scroll/core" "^2.5.1"
+    "@better-scroll/indicators" "^2.5.1"
+    "@better-scroll/infinity" "^2.5.1"
+    "@better-scroll/mouse-wheel" "^2.5.1"
+    "@better-scroll/movable" "^2.5.1"
+    "@better-scroll/nested-scroll" "^2.5.1"
+    "@better-scroll/observe-dom" "^2.5.1"
+    "@better-scroll/observe-image" "^2.5.1"
+    "@better-scroll/pull-down" "^2.5.1"
+    "@better-scroll/pull-up" "^2.5.1"
+    "@better-scroll/scroll-bar" "^2.5.1"
+    "@better-scroll/slide" "^2.5.1"
+    "@better-scroll/wheel" "^2.5.1"
+    "@better-scroll/zoom" "^2.5.1"
+
 big.js@^5.2.2:
   version "5.2.2"
   resolved "https://registry.yarnpkg.com/big.js/-/big.js-5.2.2.tgz#65f0af382f578bcdc742bd9c281e9cb2d7768328"