2021-10-26 vue 拖拽

  <Layout class="router-inner">

      <a @click="goBack" style="position:absolute;right:20px;">返回

      <Button :disabled="isDis" type="primary" :loading="subLoad" @click="throttleSave">保存模板

      <Article class="" :isLoading="typeLoading">

        <div class="leftMenu">

          <p>模板名称

          <div class="menuItem">

            <Input :disabled="isDis" v-model="aModel.name" :maxlength="30" />

          <p>区域设置

          <div class="menuItem">

              :disabled="isDis"

              :multiple="true"

              v-model="aModel.areaCodeArr"

              filterable

clearable

              :linline="false"

            >

                v-for="(o, i)in regionOptions"

                :key="i"

                :value="o.businessCityId"

                :label="o.businessCityName"

              />

          <p>模板字段

          <div class="menuItem items">

            <CheckboxGroup v-model="aModel.itemArr">

                v-for="oin templateFields"

                :key="o.code"

                :disabled="isDis || o.isMust"

                @on-change="itemArrChange(o.code)"

                :label="o.code"

                :value="o.isMust">

                {{ o.name }}

        <Layout class="contentLay">

          <Article class="router-inner" :isLoading="typeLoading">

            <div class="leftMenu">

              <p>已选字段

              <div class="dragWrapper">

                <transition-group name="flip-list">

                    :class="['dragItem', o.code ===dragEnter ?'dragEnter' :'']"

                    v-for="(o, i)in aModel.itemModelList"

                    :key="i +1"

                    :label="o.code"

                    :disabled="o.isMust">

                    <div class="sortNum">{{ i + 1 }}

                    <div v-if="isDis" class="dragLabel">

                      <span>{{ o.name }}

                      v-else

                      class="dragLabel"

                      draggable="true"

                      @dragstart="dragstart(o)"

                      @dragenter="dragenter(o)"

                      @dragend="dragend(o)">

                      <span>{{ o.name }}

                      <img class="sortImage" :src="sortSvg" />

            <h3 class="previewTitle">预览模板

              stripe

              :loading="tableLoading"

              :columns="columns"

              :data="tableData"

            />

import sortSvgfrom '@/assets/images/sort.png'

import resetPagefrom '@/mixins/resetPage'

import {save, read }from '@/storage'

import combinTablefrom '@/mixins/combinTable'

import {mapActions }from 'vuex'

import {customerCategorys, templateTypes }from '@/constants/rulesConfig'

export default {

name:'EditTemplate',

  mixins: [combinTable, resetPage],

  props: {},

  data () {

return {

sortSvg,

      subLoad:false,

      aModel: {

id:'',

        areaCode:'',

        areaCodeArr: [],

        areaName:'',

        itemModelList: [],

        itemName:'',

        itemCode:'',

        itemArr: [],

        name:'',

        typeCode:''

      },

      templateTypes,

      customerCategorys,

      btnModel: {

outputBtu: {

btuName:'导出',

          postion:'right',

          icon:'iconexport',

          fontFamily:'business_ui',

          type:'icon',

          disabled:false

        },

        settingBtu: {

slot:true,

          btuName:'表格设置', // 按钮名称

          postion:'right', // 位置区域

          icon:'iconconfiguration-form',

          fontFamily:'business_ui',

          hide:false,

          type:'icon' // 按钮等级

        }

},

      columns: [],

      tableData: [],

      templateFields: [],

      typeLoading:false,

      tableLoading:false,

      regionOptions: [],

      templatetypeList: [],

      queryModel: {

typeCode:''

      },

      records: {},

      templateId:'',

      templatePageType:'',

      isDis:false,

      dragItem: {

oldItem: {},

        newItem: {},

        isActive:undefined

      },

      dragEnter:''

    }

},

  activated () {

this.templateId =read('templateId')

this.templatePageType =read('templatePageType')

this.isDis =this.templatePageType ==='SEE'

    this.getDefaultConfig()

},

  deactivated () {

// this.setDefault()

  },

  watch: {

'aModel.itemArr': {

handler (list) {

if (this.templateFields.length) {

this.tableLoading =true

          // 表头

          this.columns = list.map((li, index) => {

let obj =this.templateFields.find(a => a.code === li)

if (obj) {

return {

title: obj.name,

                key: obj.code,

                tooltip:true,

                width: obj.name.length *30,

                fixed: (index ===0 ?'left' :'')

}

}else {

return {}

}

})

// 已选数据

          this.aModel.itemModelList =this.columns

            .map(a => {

return {name: a.title, code: a.key }

})

this.columns &&this.columns.length &&

this.formatTableColumns(this.columns, document.querySelector('.previewTitle').offsetWidth)

let obj = {}

// 填充表格

          list.forEach(co => {

Object.defineProperty(obj, co, {

value:'',

              writable:false

            })

return obj

})

this.tableData =Array.from({length:8 },

            (v, i) => {

obj.id = i

return obj

})

this.tableLoading =false

        }

},

      immediate:true

    },

    'aModel.name' (name) {

this.aModel.name = name.trim()

}

},

  methods: {

...mapActions([

'billTemplateItemList', // 全量模板字段

      'getUserAreaInfo',

      'updateBillTemplate',

      'addBillTemplate',

      'getTemplateInfo'

    ]),

    async getDefaultConfig () {

const {

templateId,

        templatePageType,

        getUserAreaInfo,

        getTemplateInfo,

        billTemplateItemList

} =this

      // 模板字段

      this.tableLoading =true

      let bType =await billTemplateItemList({typeCode:read('typeCode') })

if (bType.data && bType.data.length) {

// 默认的全量字段

        this.templateFields = bType.data

        // 必选字段需要保存

        let tempItemArr = [...this.aModel.itemArr]

bType.data

          .filter(a => {

return a.isMust && !this.aModel.itemArr.some(c => c === a.code)

})

.forEach(a => {

tempItemArr.push(a.code)

})

this.aModel.itemArr = [...tempItemArr]

this.tableLoading =false

      }

// 新建、编辑、复制、查看

      if (templatePageType !=='ADD') {

if (templateId) {

let info =await getTemplateInfo(templateId)

Object.assign(this.aModel, this.$utils.pick(

info.data,

            'id',

            'areaCode',

            'areaName',

            'name',

            'itemModelList',

            'typeCode'

          ))

const { itemModelList, areaCode } = info.data

          this.aModel.areaCodeArr = areaCode.split(',')

// 模板字段中存在该字段才加入到用户已选数据

          this.aModel.itemArr = itemModelList

.filter(t =>this.templateFields.some(s => s.code === t.code))

.map(a => a.code)

// 复制当前模板则去掉id

          if (templatePageType ==='COPY') {

this.aModel.name =this.aModel.name +'(1)'

            delete this.aModel.id

          }

}

}else {

for (let iin this.$data.aModel) {

i !=='itemArr' && (this.$data.aModel[i] =this.$options.data.call(this).aModel[i])

}

}

// 新建需要加typeCode

      this.aModel.typeCode =read('typeCode')

// 区域

      let res =await getUserAreaInfo()

if (res.data) {

let regionArr =Array.isArray(res.data) ? res.data : []

this.regionOptions = regionArr

this.typeLoading =false

      }

},

    throttleSave () {

this.$utils.throttle(this.saveForm, 450)

},

    async saveForm () {

const {

aModel,

        addBillTemplate,

        updateBillTemplate,

        regionOptions,

        $utils

} =this

      // 校验

      if (!aModel.name) {

this.$message({type:'warning', message:`请填写模板名称` })

return

      }

if (!aModel.areaCodeArr || !aModel.areaCodeArr.length) {

this.$message({type:'warning', message:`请选择区域设置` })

return

      }

let params = $utils.pick(

aModel,

        'id',

        'areaCode',

        'areaName',

        'itemModelList',

        'itemName',

        'itemCode',

        'name',

        'typeCode'

      )

params.areaCode = aModel.areaCodeArr.join(',')

params.areaName = regionOptions

.filter(r => aModel.areaCodeArr.some(a => a === r.businessCityId))

.map(r => r.businessCityName).join(',')

// 处理成后台需要的数据

      for (let iin params.itemModelList) {

params.itemName =`${params.itemName}${i !=='0' ?',' :''}${params.itemModelList[i].name}`

        params.itemCode =`${params.itemCode}${i !=='0' ?',' :''}${params.itemModelList[i].code}`

      }

this.subLoad =true

      try {

let res = params.id

          ?await updateBillTemplate(params)

:await addBillTemplate(params)

if (res.status ===200) {

// 新建或复制的则存一下id保证刷新后页面变为编辑页面

          if (!params.id) {

this.aModel.id = res.data

            save('templateId', res.data)

save('templatePageType', 'EDIT')

}

this.$message({type:'success', message:`${params.id ?'修改成功' :'新建成功'}` })

}

this.subLoad =false

      }catch (err) {

this.subLoad =false

      }

},

    dragstart (val) {

this.oldItem = val

this.isActive = val

},

    dragend (val) {

if (this.oldItem !==this.newItem) {

let oldIndex =this.aModel.itemModelList.indexOf(this.oldItem)

let newIndex =this.aModel.itemModelList.indexOf(this.newItem)

let newItems = [...this.aModel.itemModelList]

newItems.splice(oldIndex, 1)

newItems.splice(newIndex, 0, this.oldItem)

this.aModel.itemArr = [...newItems].map(a => a.code)

this.$message({type:'warning', message:'点击【保存模板】按钮后顺序才会保存' })

this.isActive = -1

      }

this.dragEnter =''

    },

    // 记录移动过程中信息

    dragenter (val) {

this.dragEnter = val.code

      this.newItem = val

},

    itemArrChange (code) {

this.aModel.itemArr.push(code)

},

    setDefault () {

save('templateId', '')

save('templatePageType', 'SEE')

},

    findName (dicts, code) {

if (this[dicts]) {

if (code) {

let obj =this[dicts].find(s => s.value === code ?0 :1)

if (obj) {

return obj.label

          }

}else return '-'

      }else return '-'

    },

    goBack () {

this.jumpTo('/spm/templateManage/templateList', '对账单模板管理', {}, `/spm/templateManage/editTemplate`)

}

}

}

<style lang="less" scoped>

@deep: ~'>>>';

.sh-header {

position:relative;

  border-bottom:1px solid #DCDCDC;

  display:flex;

  align-items:center;

  margin-bottom:20px;

}

.sh-content {

width: ~'calc(100% - 240px)';

}

.leftMenu {

color:#262626;

  border:1px solid #DCDCDC;

  min-height:500px;

  p {

padding:10px;

    font-size:14px;

    text-align:left;

    border-bottom:1px solid #EEEEEE;

  }

.menuItem {

padding:10px;

    font-size:14px;

    cursor:pointer;

    border-bottom:1px solid #EEEEEE;

  }

.menuItemActive {

color:#3377FF;

  }

.items {

display:flex;

    flex-direction:column;

    @{deep}.sh-checkbox-wrapper {

display:flex;

      margin:0;

      padding:7px 5px;

    }

}

.dragWrapper {

.dragItem {

font-size:12px;

      display:flex;

      padding:7px 0 0 5px;

      align-items:center;

      cursor:pointer;

      -webkit-touch-callout:none;

      -webkit-user-select:none;

      -khtml-user-select:none;

      -moz-user-select:none;

      -ms-user-select:none;

      user-select:none;

      .sortNum {

color:#ABABAB;

        width:18px;

        height:100%;

      }

.dragLabel {

display:flex;

        padding:4px 10px 7px 4px;

        align-items:center;

        justify-content:space-between;

        flex:1;

        border-bottom:1px solid #EEE;

      }

.sortImage {

opacity:0.4;

        width:14px;

        height:14px;

        float:right;

      }

}

.dragItem:hover {

box-shadow:0px 0px 2px rgba(0, 0, 0, 0.2);

      border-bottom:1px dashed #EEE;

    }

.dragEnter {

box-shadow:0px 0px 5px rgba(0, 0, 0, 0.6);

    }

}

}

.previewTitle {

width:100%;

  text-align:center;

  padding-bottom:14px;

}

.contentLay .sh-article {

padding-top:0;

}

.flip-list-move {

transition:transform 0.3s ease-in;

}

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 216,470评论 6 501
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 92,393评论 3 392
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 162,577评论 0 353
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 58,176评论 1 292
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 67,189评论 6 388
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,155评论 1 299
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,041评论 3 418
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,903评论 0 274
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,319评论 1 310
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,539评论 2 332
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,703评论 1 348
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,417评论 5 343
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 41,013评论 3 325
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,664评论 0 22
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,818评论 1 269
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,711评论 2 368
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,601评论 2 353

推荐阅读更多精彩内容

  • 基础部分 模版语法 1.computed和watch的区别 计算属性computed :支持缓存,data数据不变...
    王蕾_fd49阅读 570评论 0 0
  • 一、Web端 https://www.nowcoder.com/discuss/588372 1.float如何清...
    陈一季阅读 4,227评论 2 18
  • Nuxt爬坑 第一节:nuxt.js相关概述 nuxt.js简单的说是Vue.js的通用框架,最常用的就是用来作S...
    阿_军阅读 1,005评论 0 0
  • 移动端项目-信息管理系统 项目依赖 项目基本依赖-S:vuevue-router-D:编译打包:webpack w...
    果木山阅读 1,877评论 0 0
  • Vue面试题 v-html 会有XSS风险,会覆盖子组件 computed 有缓存,data不变则不会重新计算 w...
    play_0阅读 2,989评论 0 6