liweilong
2020-11-30 ad3cc54a2c55ac8cdfb290be3b1e7487f9293d97
优化http.js、添加模板表单、添加keepalive设置
5个文件已添加
4个文件已修改
12046 ■■■■■ 已修改文件
src/layout/components/AppMain.vue 7 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/mixins/keepAlive.js 19 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/pages/demo/form.vue 255 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/pages/system/admin.vue 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/router/demo_router.js 6 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/utils/area/data.js 11623 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/utils/area/index.js 108 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/utils/form_validate.js 21 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/utils/http.js 5 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/layout/components/AppMain.vue
@@ -1,7 +1,12 @@
<template>
  <section class="app-main">
    <transition name="fade-transform" mode="out-in">
      <router-view :key="key" />
      <div>
        <keep-alive>
          <router-view v-if="$route.meta.keepAlive" :key="key" />
        </keep-alive>
        <router-view v-if="!$route.meta.keepAlive" :key="key" />
      </div>
    </transition>
  </section>
</template>
src/mixins/keepAlive.js
New file
@@ -0,0 +1,19 @@
/**
 * 页面通用 keepAlive 处理
 *
 * 通过页面重置功能,实现刷新功能
 */
export default {
  // keep-alive用
  activated() {
    // 根据isBack进行刷新
    if (!this.$route.meta.isBack) {
      console.log('初始化')
      this.init && this.init()
    } else {
      console.log('返回')
      this.regInit && this.regInit()
    }
  }
}
src/pages/demo/form.vue
New file
@@ -0,0 +1,255 @@
<template>
  <div class="app-container">
    <el-form ref="couponForm" label-position="left" :model="mData" label-width="150px" :rules="rules">
      <el-form-item label="标题:" prop="title">
        <el-input v-model="mData.title" placeholder="请输入标题" class="com-edit-input" />
      </el-form-item>
      <el-form-item label="面值:" prop="valueMoney">
        <el-input v-model.number="mData.valueMoney" placeholder="请输入面值" class="com-edit-input" />
      </el-form-item>
      <el-form-item label="省市区" prop="provinces">
        <el-cascader
          v-model="mData.provinces"
          :options="areaOpts"
          placeholder="请选择省市区"
          style="width: 100%"
        />
      </el-form-item>
      <el-form-item label="有效日期" prop="dateValue">
        <el-date-picker
          v-model="mData.dateValue"
          value-format="yyyy-MM-dd"
          class="com-edit-input"
          type="daterange"
          range-separator="至"
          start-placeholder="开始日期"
          end-placeholder="结束日期"
        />
      </el-form-item>
      <el-form-item prop="uploadImgs">
        <span slot="label">
          图片:<br><span>(668*164像素)</span>
        </span>
        <!-- 上传图片组件(单图) -->
        <el-upload
          ref="refUploadImg"
          accept="image/jpeg,image/jpg,image/gif,image/png"
          :auto-upload="false"
          list-type="picture-card"
          :class="{disabled:uploadDisabled}"
          action="#"
          :limit="1"
          :file-list="mData.uploadImgs"
          :on-change="addUploadImg"
          :on-remove="delUploadImg"
          :http-request="uploadImg"
          :on-preview="uploadPreview"
          :before-upload="beforeUploadImg"
        >
          <i class="el-icon-plus" />
        </el-upload>
      </el-form-item>
      <el-form-item label="是否上架:">
        <el-switch v-model="mData.isUp" :active-value="1" :inactive-value="0" />
      </el-form-item>
      <el-form-item label="详情:" prop="content">
        <!-- 富文本 -->
        <WangEnduit :catchdata="catchData" :content="mData.content" :rangenum="rangenum" />
      </el-form-item>
    </el-form>
    <div class="com-edit-bottom-btns flex flex-align-center">
      <el-button size="mini" @click="jumpBack">取消</el-button>
      <el-button type="primary" size="mini" @click="submit">提交</el-button>
    </div>
    <!-- upload放大图片 -->
    <el-dialog :visible.sync="uploadPreviewVisible" style="text-align:center">
      <img style="max-width:100%" :src="uploadPreviewUrl" alt="">
    </el-dialog>
  </div>
</template>
<script>
import WangEnduit from '@/components/WangEnduit' // 富文本
import mixin_upload from '@/mixins/upload.js' // 通用上传图片预览
import Area from '@/utils/area' // 地区选择
export default {
  name: 'DemoForm',
  components: { WangEnduit },
  mixins: [
    mixin_upload
  ],
  data() {
    return {
      // 富文本
      rangenum: null,
      // 表单字段
      mData: {
        title: '', // 标题
        valueMoney: '', // 面值
        dateValue: [], // 有效日期(开始日期至结束日期)
        content: '', // 详情
        isUp: 1, // 是否上架
        uploadImgs: [], // 图片
        provinces: [],
        imgUrl: ''
      },
      // 初始化地区
      areaOpts: Area.getAreaOpts(Area.data), // 省市区数据
      // 表单校验
      rules: {
        title: [{
          required: true, message: '请填写优惠券标题', trigger: 'change'
        }],
        valueMoney: [{
          required: true, message: '请填写优惠券面值', trigger: 'change'
        }, {
          type: 'number', message: '面值必须为数字', trigger: 'change'
        }],
        dateValue: [{
          required: true, message: '请选择有效日期', trigger: 'change'
        }],
        provinces: [{
          required: true, message: '请选择地址', trigger: 'change'
        }],
        content: [{
          required: true, message: '请填写优惠券详情'
        }],
        uploadImgs: [{
          required: true, message: '请选择图片'
        }]
      }
    }
  },
  computed: {
    // 禁用上传图片功能
    uploadDisabled() {
      return this.mData.uploadImgs.length > 0
    }
  },
  mounted() {
    this.init()
  },
  methods: {
    init() {
    },
    jumpBack() {
      this.$router.go(-1)
    },
    // 富文本相关
    // 富文本编辑器的内容赋值
    catchData(content) {
      if (content === '<p><br></p>') content = ''
      try {
        const currentRange = window.getSelection().getRangeAt(0)
        this.rangenum = currentRange
      } catch (e) {
        //
      }
      this.mData.content = content
      this.$refs.couponForm.validateField('content')
    },
    // 富文本相关
    // 上传图片 ↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓
    // 上传前确认格式
    beforeUploadImg(file) {
      const isImg = file.type.indexOf('image/') > -1
      if (!isImg) {
        this.$message.error('必须是选择图片文件')
      }
      return isImg
    },
    // 增加图片
    addUploadImg(file, fileList) {
      this.mData.uploadImgs = fileList
      this.$refs.couponForm.validateField('uploadImgs')
    },
    // 删除图片
    delUploadImg(file, fileList) {
      this.mData.uploadImgs = fileList
    },
    // 上传图片
    uploadImg(res) {
      const file = res.file
      const formData = new FormData()
      formData.append('file', file)
      this.postFN({
        url: 'admin/image/upload',
        header: { 'Content-Type': 'multipart/form-data' },
        params: formData,
        mockData: {
          code: 100,
          msg: '',
          data: {
            imgUrl: 'xxxx'
          }
        }
      }, (inf) => {
        console.log('上传图成功')
        this.$set(this.mData, 'imgUrl', inf.imgUrl)
        console.log('上传图结束')
        // 上传完图片
        this.submitReq()
      })
    },
    // 上传图片 ↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑
    submit() {
      this.$refs['couponForm'].validate(valid => {
        if (valid) {
          if (this.checkNeedUpload(this.mData.uploadImgs)) {
            console.log('开始上传图片')
            // 先上传图片,再提交
            this.$refs.refUploadImg.submit()
          } else {
            // 提交
            this.submitReq()
          }
        }
      })
    },
    submitReq() {
      var { mData } = this
      console.log(mData)
      // 字段未写
      var params = {
        title: mData.title,
        priceStr: mData.valueMoney, // 元为单位
        startTime: mData.dateValue[0],
        endTime: mData.dateValue[1],
        imgUrl: mData.imgUrl,
        content: mData.content,
        isUp: mData.isUp
      }
      // 提交表单
      this.postFN({
        url: 'admin/coupon/add',
        params: params,
        mockData: {
          code: 100,
          msg: '',
          data: {}
        }
      }, () => {
        this.$messageSuc('保存成功')
        this.jumpBack()
      })
    }
  }
}
</script>
<style lang="scss" scoped>
</style>
src/pages/system/admin.vue
@@ -81,7 +81,7 @@
    <!-- 新增&编辑 -->
    <el-dialog :title="adminDialogData.type=='add'?'新增管理员':'编辑管理员'" width="500px" :visible.sync="isShowadminDialog" append-to-body>
      <el-form ref="adminDialog" :model="adminDialogData" label-width="80px" :rules="rules">
      <el-form ref="adminDialog" :model="adminDialogData" label-width="80px" :rules="rules" size="small">
        <el-form-item label="名称" prop="name">
          <el-input v-model="adminDialogData.name" placeholder="请输入名称" />
        </el-form-item>
src/router/demo_router.js
@@ -16,6 +16,12 @@
      component: () => import('@/pages/demo/index'), // Parent router-view
      name: 'demoIndex',
      meta: { title: '模板列表' }
    },
    {
      path: 'form',
      component: () => import('@/pages/demo/form'), // Parent router-view
      name: 'demoForm',
      meta: { title: '模板表单' }
    }
  ]
}
src/utils/area/data.js
New file
Diff too large
src/utils/area/index.js
New file
@@ -0,0 +1,108 @@
/**
 * 地址数据&方法
 */
import area from './data.js' // 引入地区数组
// import Req from '../http_install.js' // 引入请求方法
const axios = require('axios')
/**
 * 根据省名称获取城市数组
 * @param {string} province 省名
 * @return {object[]} 城市数组
 */
function getCitiesByLabel(province) {
  province = area.find(obj => province === obj.label)
  return province ? province.children : []
}
/**
 * 根据省市名称获取区数组
 * @param {string} province 省名
 * @param {string} city 城市名
 * @return {object[]} 区数组
 */
function getDistrictsByLabel(province, city) {
  var cities = getCitiesByLabel(province)
  city = cities.find(obj => city === obj.label)
  return city ? city.children : []
}
/**
 * 根据省市区获取区数据
 * @param {string} province 省名
 * @param {string} city 城市名
 * @param {string} district 区名
 * @return {object} 区对象数据
 */
function getDistrictsObjByLabel(province, city, district) {
  return getDistrictsByLabel(province, city).find(obj => obj.label === district)
}
/**
 * 初始化 elementUI Cascader 的 option
 * @param {object[]} areaArr 地区数据
 * @return {object[]} elementUI 级联选择组件用的 option 参数
 */
function getAreaOpts(areaArr) {
  if (!areaArr || !areaArr.length) {
    return
  }
  return areaArr.map((obj) => {
    return {
      value: obj.label,
      label: obj.label,
      code: obj.value,
      children: getAreaOpts(obj.children)
    }
  })
}
/**
 * 请求获取街道json数据 - 根据传入的区编号,请求对应的json文件
 * Promise
 * @param {string} districtCode 区编号
 * @param {VueObject} _this vue页面实例
 * @resolve {'街道号': '街道名', ...}
 */
function getStreetByDistrictCode(districtCode) {
  return new Promise((resolve, reject) => {
    if (!districtCode) {
      reject('缺失 districtCode')
    }
    // TODO 改为axios
    axios({
      method: 'GET',
      url: './static/town/' + districtCode + '.json',
      header: {
        'content-type': 'application/json' // 默认值
      }
    }).then((res) => {
      const result = []
      const data = res.data
      // 构建街道数组
      // 注:此处label与value一致,预留一个code字段保留街道编号
      if (data) {
        for (var i in data) {
          result.push({
            label: data[i],
            value: data[i],
            code: i
          })
        }
      }
      resolve(result)
    }).catch(() => {
      reject()
    })
  })
}
export default {
  data: area, getAreaOpts,
  getCitiesByLabel,
  getDistrictsByLabel,
  getDistrictsObjByLabel,
  getStreetByDistrictCode
}
src/utils/form_validate.js
New file
@@ -0,0 +1,21 @@
/**
 * 通用表单验证
 */
export default {
  /**
   * 验证电子邮箱
   * @param {string} value 电子邮箱字符串
   */
  validateEmail(value) {
    return /^(\w-*\.*)+@(\w-?)+(\.\w{2,})+$/.test(value)
  },
  /**
   * 验证手机号码
   * @param {string} value 手机号码
   */
  validateMobilePhoneNumber(value) {
    return /^1[0-9][0-9]\d{8}$/.test(value)
  }
}
src/utils/http.js
@@ -177,7 +177,10 @@
        // ...urlEncodes,
      }
      // // 将请求参数放到链接后面
      var paramsUrl = urlEncode(urlEncodes).replace('&', '?')
      var paramsUrl = urlEncode(urlEncodes)
      if(!/\?/.test(ajaxUrl)) {
          paramsUrl = paramsUrl.replace('&', '?')
      }
      ajaxUrl = ajaxUrl + paramsUrl
      // console.log(ajaxUrl)