OB公司业务笔记

CSS中xs,sm,md,lg是什么意思

<a-col :xs="24" :sm="24" :md="12" :lg="12" :xl="12"> </a-col>

1.col-xs用于超小型设备,(max-width:768px);
2.col-sm一般用于小屏设备,(min-width:768px);
3.col-md一般用于中屏设备,(min-width:992px);
4.col-lg一般用于大屏设备,(min-width:1200px);
后面跟数字是几,也就是占几份(每个占据12份中的几份),
比如是4,也就是一行可以显示3个; 12/4=3 ;或者12,就是一行可以显示1个。 12/12=1

<a-row :gutter="48">

一卡通主要业务_自动续费功能

前端设置一个开关 以便开启自动续费的功能
重点:方法调用接口
难点:给接口传递参数前先创建一个对象包裹参数
参数:卡号,开关状态

/**
* 自动续费
*
* @author Ryane
* @date 2021/08/16 11:39
*/
export function changeAutomatic(parameter) {
  return axios({
    url: '/vipCardMainBusiness/changeAutomatic',
    method: 'post',
    // 总结:
    //params: parameter   post请求需要改成data
    data: parameter
  })
}
onState(e) {
  this.checked = !this.checked // 点击开关就取反
  //console.log('当前开关状态是' + this.checked)
  let obj = {}
  obj.cardNo = this.detailData.cardNo
  obj.automatic = this.checked

  changeAutomatic(obj).then((res) => {
    if (res.success) {
      
      // 之前此处是res.message
      //this.$message.success(res.message)
      
      // 此处的res.data是控制台Network-changeAutomatic-Preview-success-data: "续费开启成功/续费关闭成功"
      this.$message.success(res.data)
    
    } else {
      //console.log(obj)
      this.$message.info('续费失败' + res.message)
    }
  })
},

会员中心_用户管理 新增用户时校验账号重复

自定义校验规则 传递三个参数,callback 必须被调用
后端要求:传递user字段
在接口调用前 用对象包裹 user: value

<a-input
  placeholder="请输入账号"
  v-decorator="['account', {rules: [
  {pattern:RegexUtil.REGEX_ENGLISH_AND_NUMBER,message: '账号仅可输入英文和数字!'},
  {required: true, min: 5, message: '请输入至少五个字符的账号!'},

  <!--设置自定义校验,名称为validationDuplication-->
  {validator: validationDuplication, }
<!--如果为true,则这一校验不通过 不会进行下面的校验-->
  ],validateFirst:true}]"/>
/**
  * 校验账号重复
*/
validationDuplication(rule,value,callback){
  /*
  * 只能改变第一页的内容
  getUserPage().then((res) => {
    console.log(res.data.rows.account)
    for (let i = 0; i < res.data.rows.length; i++) {
      console.log(res.data.rows[i].account)
      if (value == res.data.rows[i].account){
        callback('账号已存在,请重新输入')
      }
    }
  })*/
  // 网页F12查看接口时给后端传送的拼接字段名
  // checkUser是后端接口名称
  // user是给后端接口传递的字段名称
  // Request URL: http://192.168.2.21:8081/sysUser/checkUser?user=11111
  let requestParam = {
    user: value
  }
  sysCheckUser(requestParam).then((res) => {
    if (res.code == 500){
      callback('账号已存在')
    }else {
      callback() // 什么也不回传,通过校验
    }
  })
}

会员中心 门店收银_增加/取出 弹出窗口 输入卡号检验BUG

校验接了两个接口 不能随意callback() 否则不会校验另一个接口[页面不显示]

<a-input
  placeholder="请输入卡号"
  oninput="if(value.length > 20)value = value.slice(0, 20)"
  v-decorator="['cardNo', {rules: [
    {required: true,validator: checkCard}],validateFirst:true}]"/>
/**
 * 获得持卡人
 */
checkCard(rule, value, callback) {
  const reg=RegexUtil.REGEX_CARD
  const inputCardId = value
  if (!reg.test(value)) {
    callback('请输入正确的卡号!')
  }else if (inputCardId.length>=5 && inputCardId.length<=20){
    typeFilter({cardNo: inputCardId}).then((res) => {
      if (res.code == 500){
        callback(res.message)
      }else {
        // callback() 加到这行解决BUG
        callback()
      }
    })
    detail({cardNo: inputCardId}).then((res) => {
      if (res.success && res.data != null) {
        //获得持卡人姓名,并设置显示
        this.cardInfo = res.data
        this.cardNo=res.data.cardNo
        if (res.data.userName==null){
          callback('该卡尚未绑定')
        }else {
          cardDetail({id : res.data.cardType}).then((result) => {
            if (result.success && result.data!=null){
              this.proportion=result.data.proportion
              getCutPoints({cardNo: inputCardId}).then((resData) => {
                this.cardInfo.canInterestAmount=sub(this.cardInfo.interestAmount,resData.data)
                this.cardInfo.canInterestPoints=sub(this.cardInfo.interestPoints,mul(resData.data,this.cardInfo.proportion))
                this.form.setFieldsValue({
                  cutPoints:resData.data
                })
              })
              // BUG问题出现在这
              // callback()
              return
            }else {
              callback(res.message)
            }
          })
        }
      } else {
        //避免关闭窗体后依旧提示
        if (this.visible) {
          callback(res.message)
          this.cardInfo = {}
        }
      }
    })

  }else {
    callback('请输入正确的卡号!')
  }
},

会员中心_门店管理 门店收银 加载页面时不显示数据 只有输入查询条件才会显示对应数据

<!--:localLoadingType="false"  -->
<s-table
  ref="table"
  size="default"
  :columns="columns"
  :data="loadData"
  :alert="true"
  :rowKey="(record) => record.cardNo"
  :localLoadingType="false" <!--如果不写 效果为一直加载的样式-->
    >

<!-- 查询按钮绑定事件,原方案是绑定封装好的组件  @click="getTableData()"-->
<a-col :md="!advanced && 8 || 24" :sm="24">
  <span class="table-page-search-submitButtons" :style="advanced && { float: 'right', overflow: 'hidden' } || {} ">
    <!--原方案:<a-button type="primary" @click="$refs.table.refresh(true)">查询</a-button>-->
    <a-button type="primary" @click="getTableData()">查询</a-button>
    <a-button style="margin-left: 8px" @click="() => queryParam = {}">重置</a-button>
  </span>
</a-col>
data() {
  return {
    // 加载数据方法 必须为 Promise 对象
    loadData: parameter => {
      if ((undefined == this.queryParam.userName || null == this.queryParam.userName || this.queryParam.userName == '')
          && (undefined == this.queryParam.cardNo || null == this.queryParam.cardNo ||this.queryParam.cardNo == '')
          && (undefined == this.queryParam.phoneNumber || null == this.queryParam.phoneNumber || this.queryParam.phoneNumber == '')
          && (undefined == this.queryParam.idNo || null == this.queryParam.idNo || this.queryParam.idNo == '')
          && (undefined == this.queryParam.createTime || null == this.queryParam.createTime || this.queryParam.createTime == '' )
          && (undefined == this.queryParam.createUser || null == this.queryParam.createUser || this.queryParam.createUser == '')){
        // console.log("1111111111111111111111")
        return ''
      }
      return page(Object.assign(parameter, this.queryParam)).then((res) => {
        this.$refs.table.clearSelected()
        return res.data
      })
    },
  }
},
methods: {
    getTableData() {
      if (this.queryParam.userName == undefined
        && this.queryParam.cardNo == undefined
        && this.queryParam.phoneNumber == undefined
        && this.queryParam.idNo == undefined
        && this.queryParam.createTime == undefined
        && this.queryParam.createUser == undefined){
        // 清table
        this.$refs.table.localDataSource = []
      }else {
        this.$refs.table.refresh(true)
      }
    }
  }  

会员档案 更多-会员卡_绑定会员卡 卡号校验BUG

<a-input placeholder="请输入新的卡号"
         v-decorator="['cardNo', {rules: [
           { required: true, message: '请输入会员卡号!'},
           { validator: cardNoChange }
           ]}]"></a-input>
cardNoChange(rule,e,callback) {
  let requestParam = {
    // cardNo: e.target.value 如果加校验不能这么写 控制台不会报错 也不会进行下面的语句 除非方法的形参只有一个e
    cardNo: e
  }
  getCardType(requestParam).then((res) => {
    if (res.code === 200 || res.success) {
      this.cardTypeData = res.data
      callback()
    } else {
      this.$message.error('失败:' + res.message)
      callback(res.message)
    }
  })
},

会员档案_设置主副卡

设置主卡
1.后端要求前端传递四个参数userId cardType cardNo isMasterCard 且用对象包裹传递
2.调用设置主卡接口的前面 新建对象obj
3.传递表格当前行的参数 ,用到record 可以log测
4.obj.userId = record.userCode 依次给对象新增属性

<a-form :form="form">
  <s-table ref="table"size="default":columns="columns":data="loadData":alert="true":rowKey="(record) => record.code"> 
    <span slot="action" slot-scope="text, record">
      <a @click="showModal(record.orderNo)">详情</a>
        <a-divider type="vertical"/>
        <a-popconfirm placement="topRight" title="确认设置为主卡?" @confirm="() => setMasterCard(record)">
        <a>设置为主卡</a>
        </a-popconfirm>
        </span>
        </s-table>
        <add-form ref="addForm" @ok="handleOk"/>
        <edit-form ref="editForm" @ok="handleOk"/>
        </a-form>
loadData: parameter => {
  return page(Object.assign(parameter, this.queryParam)).then((res) => {
    for (let i = 0; i < res.data.rows.length; i++) {
      if (res.data.rows[i].isMasterCard == 1){
        res.data.rows[i].isMasterCard = "主卡"
        this.MasterCard = res.data.rows[i].isMasterCard
      }else{
        res.data.rows[i].isMasterCard = "副卡"
      }
    }
    return res.data
  })
},
 // 后端要求前端传递四个参数userId cardType cardNo isMasterCard 且用对象包裹传递
    setMasterCard(record){
      let obj = {}
      obj.userId = record.userCode
      obj.cardType = record.cardType
      obj.cardNo = record.cardNo

      obj.isMasterCard = record.isMasterCard;
      if (obj.isMasterCard == "副卡"){
        obj.isMasterCard = 0
      }
      if (obj.isMasterCard == "主卡"){
        obj.isMasterCard = 1
      }
      console.log(obj)
      // console.log(obj)
      // console.log(this.resData)
      // this.resData.rows
      // console.log(this.$refs.table)

      // for (let i = 0; i < this.resData.rows.length; i++) {
      //   console.log(this.$refs.resData.rows[i])
      //   // this.resData.rows[i].cardType
      // }
      /*detail(orderNo).then((record)=>{
        this.resultData=record.data
        console.log(record.data)
      })*/

      console.log(record)

      // 设置主卡的接口
      setUpMasterCard(obj).then((res)=>{
        console.log(res)
        if (res.success) {
          console.log(record.isMasterCard)
          record.isMasterCard = "主卡"
          this.$message.success('设置主卡成功')
        }else{
          // record.isMasterCard = "主卡"
          console.log(record.isMasterCard)
          this.$message.info('设置主卡失败')
        }
      })
    }

储值活动管理BUG

:::danger
BUG修改了一个月
:::

//:key="index"和v-decorator="[`activityConfigs[${k}][inventoryId][${index}]`、
//v-decorator="[`activityConfigs[${k}][numberOfGifts][${index}]`的index要保持一致
<a-row v-for="(i, index) in giftListIndex[k]" :key="index" >
  <a-col :span="activityType==2?6:12">
    <a-form-item label="礼物" :labelCol="labelCol" :wrapperCol="wrapperCol">
      <a-select :disabled="disabled"
                ref="formInventoryIdRef"
                v-decorator="[`activityConfigs[${k}][inventoryId][${index}]`,{rules: [{required: false, message: '请选择需要赠送的礼品!'}]}]" placeholder="请选择需要赠送的礼品">
        <a-select-option v-for="item in giftDropList" :key="item.codeBar" :value="item.id">{{ item.itemName + '(' + item.unit + ')-' + item.costPurchasePrice + '元' }}
				</a-select-option>
      </a-select>
    </a-form-item>
  </a-col>
</a-row>
        // -------------------------------------------------礼物BUG-------------------------------------------------
        validateFields((errors, values) => {
          if (!errors) {
            //拷贝对象,处理时间范围信息
              const addData = Object.assign({}, values)
              //数据时间数据
              addData.beginTime = values.activityRange[0]
              addData.endTime = values.activityRange[1]
              if (addData.activityConfigs!==null){
                addData.activityConfigs = addData.activityConfigs.filter(item => item !== null && item !== undefined)
                for (var i=0;i<addData.activityConfigs.length;i++){
                  var inventoryIdArr=[]
                  var numberOfGiftsArr=[]
                  for (var j=0;j<this.giftListIndex[i].length;j++){
                    var inventoryId = addData.activityConfigs[i]['inventoryId'][this.giftListIndex[i][j]]
                    
                    // 当这个礼物数组本身不为空时候 ,直接在数组后面添加就可以加上新元素
                    if (inventoryId != null && inventoryId != undefined){
                      inventoryIdArr.push(inventoryId)
                      numberOfGiftsArr.push(addData.activityConfigs[i]['numberOfGifts'][this.giftListIndex[i][j]])
                    }
                    
                    // 当这个礼物数组本身为空时候 ,上述方法无法使用,必须新建一个数组
                    // 并使这个空数组的内容等于礼物列表的下标值
                    if (inventoryId == null && inventoryId == undefined){
                      console.log("44444444")

                      // 获取当前表单下拉框选中的选项 inventoryId字段是礼物下拉选项在下拉列表中的下标值
                      console.log(this.form.getFieldValue('activityConfigs['+i+'][inventoryId]'))

                      let newInventoryIdArr = []
                      newInventoryIdArr = this.form.getFieldValue('activityConfigs['+i+'][inventoryId]')

                      let newNumberOfGiftsArr = []
                      newNumberOfGiftsArr = this.form.getFieldValue('activityConfigs['+i+'][numberOfGifts]')
                      // console.log(newNumberOfGifts)
                      // console.log(newInventoryId)
                      // console.log(newData)

                      // console.log(addData.activityConfigs[i]['inventoryId'][this.giftListIndex[i][j]])

                      // inventoryIdArr.push(newInventoryId)
                      inventoryIdArr = newInventoryIdArr
                      // numberOfGiftsArr.push(newNumberOfGifts)
                      numberOfGiftsArr = newNumberOfGiftsArr

                      // inventoryIdArr.push(inventoryId)
                      // numberOfGiftsArr.push(addData.activityConfigs[i]['numberOfGifts'][this.giftListIndex[i][j]])
                    }
                  }
                  addData.activityConfigs[i]['inventoryId'] = inventoryIdArr
                  addData.activityConfigs[i]['numberOfGifts'] = numberOfGiftsArr
                }
              }
        // -------------------------------------------------礼物BUG-------------------------------------------------
if (inventoryId == null && inventoryId == undefined){
  let newInventoryIdArr = []
  newInventoryIdArr = this.form.getFieldValue('activityConfigs['+i+'][inventoryId]')
  let newNumberOfGiftsArr = []
  newNumberOfGiftsArr = this.form.getFieldValue('activityConfigs['+i+'][numberOfGifts]')
  inventoryIdArr = newInventoryIdArr
  numberOfGiftsArr = newNumberOfGiftsArr
}

You cannot set a form field before rendering a field associated with the value.

使用antd的Form组件setFieldsValue可能会出现
You cannot set a form field before rendering a field associated with the value.
警告,字面意义去看是说在 render之前设置了表单值的问题。

那么怎么解决呢
1、在form组件显示出后,再用this.form.setFieldsValue
2、在this.$nextTick()中使用this.form.setFieldsValue
3、如果要表单绑定的数据和属性不匹配也会出现这个问题,这时就要使用第三种处理方法:在使用this.form.setFieldsValue时,赋值的数据要一一匹配field,用不到的不要赋值即可,这样操作之后错误提示就不再提醒了

找到问题了 是输入框有几个 setFieldsValue 里面就有几个 对不上就报这个错
<!-- 如:此处cutPoints已经被注释掉了 -->
<!-- <div v-if="type==3">
  <a-form-item
    label="冻结两天利息"
    :labelCol="labelCol"
    :wrapperCol="wrapperCol"
    has-feedback="">
    <a-input placeholder="请输入卡号" disabled v-decorator="['cutPoints']"/>
  </a-form-item>
</div> -->
<script>
	getCutPoints({cardNo: inputCardId}).then((resData) => {
	    this.cardInfo.canInterestAmount=sub(this.cardInfo.interestAmount,resData.data)
	    this.cardInfo.canInterestPoints=sub(this.cardInfo.interestPoints,mul(resData.data,this.cardInfo.proportion))
	    this.$nextTick(() => {
	      this.form.setFieldsValue({
	      	// 此处cutPoints如果没有相应的注释掉 导致warning
	        // cutPoints:resData.data
	    })})
  	})

CSS之让尾部永远固定在页面最下方

一、开发可能遇到的问题

当你做一个项目的时候,可能有多个页面,但是每个页面用到的头部导航栏和尾部信息栏可能一样,所以就可以把他们写到一个公共的css文件。
现在思考一个问题,当一个页面显示的内容特别少的时候,可能只占整个可视区域的30%,这种情况下,怎么让尾部永远固定在页面最下方呢?也就是说,当内容少的时候,尾部直接显示在可视区域最下方,当内容多的时候,我们最初只能看到内容,看不到尾部,但随着滚动条的滚动,可以看到尾部位于页面最下方。

我做项目的时候遇到过这样一个问题,我通过定位将其直接固定在页面最下方,乍一看,没什么问题,但是当你缩放浏览器可是窗口的时候,奇怪的事情发生了。底部竟然随着滚动条的滚动,悬浮在了可视区域,而不是页面最下方了。

当一个HTML页面中含有较少的内容时,Web页面的“footer”部分随着飘上来,处在页面的半腰中间,给视觉效果带来极大的影响,让你的页面看上去很不好看,特别是现在宽屏越来越多,这种现象更是常见。

二、如何解决

那么如何将Web页面的“footer”部分永远固定在页面的底部呢?注意了这里所说的是页脚footer永远固定在页面的底部,而不是永远固定在显示器屏幕的底部,换句话说,就是当内容只有一点点时,Web页面页脚显示在浏览器底部,当内容高度超过浏览器高度时,Web页面的footer部分会在页面的可用高度的最底部,总而言之Web页面的footer部分永远在页面的底部,换句说,Footer部分永远沉底。

方法一

利用footer的margin-top负值来实现footer永远固定在页面的底部效果
先上代码

<!DOCTYPE html>
<html>
  <head>
    <meta charset="utf-8">
    <title></title>
    <link rel="stylesheet" type="text/css" href="css/index.css"/>
  </head>
  <body>
    <div id="container">
      <div id="header">头部</div>
      <div id="content" class="clearfix">
        <div id="left">
          <p>xxxxx</p>
          <p>xxxxx</p>
          <p>xxxxx</p>

        </div>
        <div id="center">xxxxx</div>
        <div id="right">xxxxxx</div>
      </div>
    </div>
    <div id="footer">底部</div>
  </body>
</html>
* {
  margin: 0;
  padding: 0;
}
html,
body {
  height: 100%;
}
#container {
  min-height: 100%;
  height: auto !important;
}
#content {
  display: flex;
  padding-bottom: 60px;/*高度等于footer的高度*/
}
#footer {
  position: relative;
  margin-top: -60px;/*等于footer的高度*/
  height: 60px;
  background: #c6f;
}
/*==========其他div==========*/
#header {
  height: 50px;
  background-color: lime;
}

#left {
  width: 18%;
  margin-right: 2%;
  background-color: orange;
}

#center{
  width: 60%;
  margin-right: 2%;
  background-color: green;
}
#right {
  width: 18%;
  background-color: yellow;
}

分析一下原理:

1、html和body标签中必须将高度(height)设置为“100%”,这样我们就可以在容器上设置百分比高度
2、container容器必须设置一个最小高度(min-height)为100%;这主要使他在内容很少(或没有内容)情况下,能保持100%的高度
3、content这个容器有一个很关键的设置,需要在这个容器上设置一个padding-bottom值,而且这个值要等于或略大于)页脚footer的高度(height)值
4、footer容器必须设置一个固定高度,单位可以是px(或em)。footer还需要进行绝对定位,并且设置bottom:0;让footer固定在容器container的底部,这样就可以实现我们前面所说的效果,当内容只有一点时,footer固定在屏幕的底部(因为container设置了 一个min-height:100%),当内容高度超过屏幕的高度,div#footer也固定在container底部,也就是固定在页面的底部
5、注意footer放在container容器外面,也就是说两者是同级关系,如果你有新元素需要放置在与container容器同级,那你需要将此元素进行绝对定位,不然将会破坏container容器的min-height值;
6、footer进行margin-top的负值设置,并且此值等于footer的高度值,而且也要和content容器的padding-bottom值相等。

方法二
<!DOCTYPE html>
<html>
  <head>
    <meta charset="utf-8">
    <title></title>
    <link rel="stylesheet" type="text/css" href="css/index.css"/>
  </head>
  <body>
    <div id="container">
      <div id="header">头部</div>
      <div id="content" class="clearfix">
        <div id="left">
          <p>xxxxxx</p>
          <p>xxxxxx</p>
        </div>
        <div id="center">xxxxxx</div>
        <div id="right">xxxxx</div>
      </div>
      <div class="push"></div>
    </div>
    <div id="footer">底部</div>
  </body>
</html>
html,
body{
  height: 100%;
  margin:0;
  padding:0;
}
#container {
  min-height: 100%;
  height: auto !important;
  margin: 0 auto -60px;/*margin-bottom的负值等于footer高度*/
}
.push,
#footer {
  height: 60px;
}
/*==========其他div效果==========*/
#header {
  padding: 10px;
  background-color: pink;
}
#content {
  display: flex;
}
#left {
  width: 33.3%;
  background-color: orange;
}
#center{
  width: 33.3%;
  background-color: green;
}
#right {
  width: 33.3%;
  background-color: yellow;
}
#footer {
  background-color: pink;
}

分析一下原理

这个方法在container容器中还增加了一个div.push用来把footer推下去,下面我们就一起看看这种方法是怎么实现页脚永远固定在页面底部的
1、html,body标签和前面方法一样,需要设置“height:100%”并重置“margin”和“padding”为0;
2、关键部分就在于div#container的设置,首先需要设置其最小高度(min-height)为100%,另外这里还有一个关键点在container容器上需要设置一个margin-bottom,并且给其取负值,而且值的大小等于 footer和div.push的高度
3、在div.push中我们不应该放置任何内容,而且这个div必须放置在container容器中,而且是最底部,并且需要设置其高度值等于footer的值,push容器在此处所起的作用就是将footer往下推

三、公司案例

<template>
  <div id="app">
    <div style="overflow: auto" id="container">
      <van-row>
        <img src="../../assets/images/oneCardTitle.png" style="width: 100%;">
        </van-row>
      <!--<van-row @click="toDetailPage(membershipCard)" class="cardBody" v-for="membershipCard in membershipCardList">-->

      <div v-for="membershipCard in membershipCardList">

        <van-row @click="toDetailPage(membershipCard)" class="cardBody" :style="{backgroundImage: 'url('+require('../../assets/images/card1.png')+')'}">

          <van-col class="nameMargin">
            <van-col class="cardName carWeight">
              {{ membershipCard.userName }}
            </van-col>
            <van-col class="cardOneName carWeight">
              {{ membershipCard.cardTypeName }}
            </van-col>
          </van-col>
          <van-col class="nameMargin cardNumber">
            {{ membershipCard.cardNo }}
          </van-col>
        </van-row>
      </div>
      <div class="push"></div>
    </div>
    <div class="bindingBottom" @click="skip('/oneCard/signIn')">
      <van-button class="bindingFont">
        <van-icon style="font-weight: 900;color: rgb(118, 118, 118);" name="plus" /> 绑定新卡
      </van-button>
    </div>
  </div>
</template>

<style lang='scss'>
  .cardBody{
    //background: url('../../assets/images/card1.png');
    background-size: 100% 100%;
    width: 94%;
    height: 200px;
    margin: 3%;
    background-repeat: no-repeat;
    display: flex;
    flex-direction: column;
    justify-content: space-around;
    border-radius: 20px;
  }
  .carWeight{
    font-weight: 900;
  }
  .cardName{
    color: rgb(244,162,182);
    font-size: 1.1em;
  }
  .cardOneName{
    font-size: 2.5em;
    color: #fff;
  }
  .cardNumber{
    font-size: 1em;
    color: #fff;
    font-weight: 600;
    letter-spacing: 1px;
  }
  .nameMargin{
    margin-left: 8%;
    display: flex;
    padding-top: 2.4em;
    flex-direction: column;
  }

  .bindingFont{
    width: 90%;
    border-radius:25px;
    font-weight: 600;
    font-size: 1.2em;
    background-color:#fff;
    box-shadow: 0px 20px 40px 25px rgba(0, 0, 0, .2);
  }
  body{
    background: rgb(239,239,239);
  }
  #app{
    height: 100%;
    margin:0;
      padding:0;
      }
      #container{
      min-height: 100%;
      height: auto !important;
      margin: 0 auto -60px;/*margin-bottom的负值等于footer高度*/
      }
      .push,
      .bindingBottom{
      text-align: center;
      //position: absolute;
      //bottom: 20px;
      //width: 100%;
      height: 60px;
      }
      </style>

样式修改前

image.pngimage.png

二次确认对话框

this.$modal.confirm({title:'提示',content:'是否确认此操作?',okText:'确定',cancelText:'取消',onOk:()=>{
  // 点击确认执行的代码块
},onCancel:()=>{
  // 点击取消执行的代码块
    this.confirmLoading = false
    this.spinning=false
  }
handleSubmit() {
  this.$modal.confirm({title:'提示',content:'是否确认此操作?',okText:'确定',cancelText:'取消',onOk:()=>{
    const {form: {validateFields}} = this
    this.confirmLoading = true
    this.spinning=true
    // this.form.getFieldDecorator('type', {initialValue: this.type})
    validateFields((errors, values) => {
      if (!errors) {
        //根据类型分别对不同请求处理(便于记录操作日志)
        if (this.cardInfo.userName!=null){
          values.name=this.cardInfo.userName
        }
        if (this.cardInfo.idNo!=null){
          values.idNo=this.cardInfo.idNo
        }
        values.type=this.type

        switch (this.type) {
          case 2:
            add(values).then((res) => {
              if (res.success) {
                this.$message.info('增加成功')
                this.handleCancel()
                this.$emit('ok', values)
              } else {
                this.$message.info(res.message)
              }
            }).catch((err) => {
              this.$message.error(err.message)
            }).finally(() => {
              this.confirmLoading = false
              this.spinning=false
            })
            break
          case 3:
            // let cutPoints=this.form.getFieldValue('cutPoints')== undefined?0:Number(this.form.getFieldValue('cutPoints'))
            // values.changeCash=Number(values.changeCash)+cutPoints
            takeOut(values).then((res) => {
              if (res.success) {
                this.$message.info('取出成功')
                this.handleCancel()
                this.$emit('ok', values)
              } else {
                this.$message.info(res.message)
              }
            }).catch((err) => {
              this.$message.error(err.message)
            }).finally(() => {
              this.confirmLoading = false
              this.spinning=false
            })
            break
        }
      } else {
        this.confirmLoading = false
        this.spinning=false
      }
    })
  },onCancel:()=>{
    this.confirmLoading = false
    this.spinning=false
  }});

},

推送积分业务,输入卡号后,显示该卡有多少积分为不可取

GET请求调用/new/interal-interest/getNotWithdrawablelnterest接口,传入cardNo,返
回该卡号对应的不可取积分总数量

<a-descriptions-item label="不可取积分"><span v-text="cardInfo.inadvisablePoints"/></a-descriptions-item>
/**
     * 获得持卡人
     */
    checkCard(rule, value, callback) {
      const reg=RegexUtil.REGEX_CARD
      const inputCardId = value
      if (!reg.test(value)) {
        callback('请输入正确的卡号!')
      }else if (inputCardId.length>=5 && inputCardId.length<=20){
        getNotWithdrawablelnterest({cardNo: inputCardId}).then((res) => {
          console.log(res)
          this.cardInfo.inadvisablePoints = res.data
        })}}

vue页面跳转之后,页面的样式错乱

vue页面跳转之后,之前页面的样式错乱,刷新之后又恢复正常。

这是css引用错乱导致的,也就是本页面被自动使用了其它页面的css样式。
为了防止这种错乱产生,需要给每个页面加上scoped,表示此css样式只在本页面进行使用。

一卡通主要业务,添加搜索条件 开始结束时间

image.png
image.png

image.png

  1. 先写模板样式
<a-col :md="5" :sm="24">
  <a-form-item label="合同开始日期">
    <a-range-picker
      v-model="queryParam.depositStartTime"
      valueFormat="YYYY-MM- DD"
      style="width: 100%"
      :ranges="{ Today: [moment(), moment()], 'This Month': [moment(), moment().endOf('month')] }"/>
  </a-form-item>
</a-col>
<a-col :md="5" :sm="24">
  <a-form-item label="合同结束日期">
    <a-range-picker
      v-model="queryParam.depositEndTime"
      valueFormat="YYYY-MM-DD"
      style="width: 100%"
      :ranges="{ Today: [moment(), moment()], 'This Month': [moment(), moment().endOf('month')] }"/>
  </a-form-item>
</a-col>
  1. 找到page接口
/**
 * 分页查询vip_card_main_business
 *
 * @author ns
 * @date 2021/08/16 11:39
 */
export function page(parameter) {
  changeRnagePicker(parameter)
  return axios({
    url: '/vipCardMainBusiness/page',
    method: 'get',
    params: parameter
  })
}
  1. 找到page接口中的方法
  2. 添加查询字段
/**
 * 在传递携带查询日期的参数时,请调用这个方法对内容进行处理
 * @param parameter
 */
function changeRnagePicker(parameter) {
  if (parameter.dateInterval !== undefined && parameter.dateInterval.length === 2) {
    //日期转换并定义参数
    parameter.beginTime = moment(parameter.dateInterval[0]).format('YYYY-MM-DD');
    parameter.endTime = moment(parameter.dateInterval[1]).format('YYYY-MM-DD');
    delete parameter.dateInterval
  }
  // 新增部分 查询条件 
  if (parameter.depositStartTime !== undefined && parameter.depositStartTime.length === 2) {
    //日期转换并定义参数
    parameter.depositStartTimeConditionStart = moment(parameter.depositStartTime[0]).format('YYYY-MM-DD');
    parameter.depositStartTimeConditionEnd = moment(parameter.depositStartTime[1]).format('YYYY-MM-DD');
    delete parameter.depositStartTime
  }
  if (parameter.depositEndTime !== undefined && parameter.depositEndTime.length === 2) {
    //日期转换并定义参数
    parameter.depositEndTimeConditionStart = moment(parameter.depositEndTime[0]).format('YYYY-MM-DD');
    parameter.depositEndTimeConditionEnd = moment(parameter.depositEndTime[1]).format('YYYY-MM-DD');
    delete parameter.depositEndTime
  }
}

antD图片上传

添加

<template>
  <a-modal
    title="新增会员卡类别"
    :width="900"
    :visible="visible"
    :confirmLoading="confirmLoading"
    @ok="handleSubmit"
    @cancel="handleCancel">

    <a-spin :spinning="confirmLoading">
      <a-form :form="form">

        <a-form-item
          label="会员卡名称"
          :labelCol="labelCol"
          :wrapperCol="wrapperCol"
          has-feedback=""
          >
          <a-input placeholder="请输入会员卡名称" v-decorator="['name', {rules: [
            {required: true, message: '请输入会员卡名称!'},
            {pattern:RegexUtil.REGEX_COMMON_AND_SPECIAL,message:'不能含有特殊字符!'}
            ]}]"/>
        </a-form-item>

        <a-form-item
          label="会员卡类型"
          :labelCol="labelCol"
          :wrapperCol="wrapperCol"
          >
          <a-select style="width: 70%;margin-right: 20px" placeholder="请选择会员卡类型" :allowClear="true"
            v-decorator="['type', {rules: [{ required: true, message: '请选择会员卡类型' }]}]">
            <a-select-option style="width: 100%" v-for="item in cardTypeDictionary" :key="item.id"
              :value="item.code">
              {{ item.name }}
            </a-select-option>
          </a-select>
          <a-button type="primary" v-if="hasPerm('sysDictData:add')" icon="plus"
            @click="$refs.dictAddForm.add('1417290081737039874')">新增卡类型
          </a-button>
        </a-form-item>

        <a-form-item
          label="会员卡等级"
          :labelCol="labelCol"
          :wrapperCol="wrapperCol"
          has-feedback=""
          >
          <a-input placeholder="请输入会员卡等级,默认为0" type="number"
            v-decorator="['level',{rules: [{pattern:RegexUtil.REGEX_NUMBER,message:'会员等级不能输入小数!'}]}]"/>
        </a-form-item>

        <a-form-item
          label="兑换比例"
          :labelCol="labelCol"
          :wrapperCol="{
          xs: {span: 24},
          sm: {span: 10}
          }"
          >
          <a-col :span="5">
            一元兑换
          </a-col>
          <a-col :span="10">
            <a-input placeholder="请输入兑换比例" type="number"
              v-decorator="['proportion', {rules: [{required: true, message: '请输入兑换比例!'}]}]"/>
          </a-col>
          <a-col :span="4" offset="1">
            积分
          </a-col>
          <a-col :span="2">
            <a-tooltip>
              <template slot="title">
                积分与人民币兑换的比例
              </template>
<span class="action">
  <a-icon type="question-circle-o"></a-icon>
</span>
</a-tooltip>
  </a-col>
  </a-form-item>

  <a-form-item
  label="优先使用"
  :labelCol="labelCol"
  :wrapperCol="wrapperCol"
    >
    <a-radio-group v-decorator="['useOrder',{rules: [{ required: true, message: '请选择使用顺序!' }]}]">
    <a-radio value="1">本金积分</a-radio>
    <a-radio value="2">赠送积分</a-radio>
    </a-radio-group>
    </a-form-item>

    <a-form-item
  label="使用范围"
    :labelCol="labelCol"
    :wrapperCol="wrapperCol"
    >
    <a-checkbox-group v-decorator="['useRange',{rules: [{ required: true, message: '请选择使用范围!' }]}]">
    <a-checkbox v-for="item in cardUseRangeDictionary" :key="item.id" :value="item.code">{{ item.name }}
    </a-checkbox>
    </a-checkbox-group>
    </a-form-item>

    <a-form-item
    label="使用城市"
    :labelCol="labelCol"
    :wrapperCol="wrapperCol"
    >
    <a-checkbox-group v-decorator="['useCity',{rules: [{ required: true, message: '请选择使用城市!' }]}]">
    <a-checkbox v-for="item in cardUseCityDictionary" :key="item.id" :value="item.code">{{ item.name }}
    </a-checkbox>
    </a-checkbox-group>
    </a-form-item>

    <a-form-item
    label="卡片描述"
    :labelCol="labelCol"
    :wrapperCol="wrapperCol"
    has-feedback=""
    >
    <a-textarea :rows="4" placeholder="请输入卡片描述" v-decorator="['description']"></a-textarea>
    </a-form-item>

    <a-form-item label="图片上传" :labelCol="labelCol" :wrapperCol="wrapperCol" has-feedback="">
    <a-upload name="file" v-decorator="['cardImage']" list-type="picture-card" :file-list="fileList" :showUploadList="true"
    data-type="jpg|png|jpeg" ref="files" :before-upload="beforeUpload" @change="handleChange"
    :remove="handleRemove" @preview="handlePreview"  style="margin-left: 10%">
    <div v-if="fileList.length < 9" id="container">
    <a-icon type="plus" />
    <div class="ant-upload-text">上传</div>
    </div>
    </a-upload>
    <a-modal :visible="previewVisible" :footer="null" @cancel="handleCancel1">
    <img alt="example" style="width: 100%" :src="previewImage"/>
    </a-modal>
    </a-form-item>
    </a-form>
    <type-dict-add-form ref="dictAddForm" @ok="handleOk"/>
    </a-spin>
    </a-modal>
    </template>

    <script>
    import {add, upload} from '@/api/modular/vipCardType/vipCardTypeManage'
    import typeDictAddForm from '@/views/system/dict/dictdata/addForm'
    import {mapActions} from 'vuex'
    import RegexUtil from "@/utils/RegexUtil";

    function getBase64 (file) {
    return new Promise((resolve, reject) => {
    const reader = new FileReader()
    reader.readAsDataURL(file)
    reader.onload = () => resolve(reader.result)
    reader.onerror = error => reject(error)
    })
    }

    export default {
    components: {
    typeDictAddForm
    },
    data() {
    return {
    ...mapActions(['dictTypeData']),
    labelCol: {
    xs: {span: 24},
    sm: {span: 5}
    },
    wrapperCol: {
    xs: {span: 24},
    sm: {span: 15}
    },
    visible: false,
    confirmLoading: false,
    form: this.$form.createForm(this),
    cardTypeDictionary: [],
    cardUseRangeDictionary: [],
    cardUseCityDictionary: [],
    RegexUtil,

    fileList: [],
    flag: true,
    fileId: '',
    previewVisible: false,
    previewImage: ''
    }
    },
    methods: {
    add() {
    this.cardTypeDictionary = this.$options.filters['dictData']('card_type')
    this.cardUseCityDictionary = this.$options.filters['dictData']('card_use_city')
    this.cardUseRangeDictionary = this.$options.filters['dictData']('card_use_range')
    this.visible = true
    },
    handleSubmit() {
    const {form: {validateFields}} = this
    this.confirmLoading = true


    validateFields((errors, values) => {
    if (!errors) {
    values.cardImage = this.fileId
    add(values).then((res) => {
    this.confirmLoading = false
    if (res.success) {
    this.$message.success('新增成功')
    this.handleCancel()
    this.$emit('ok', values)
    } else {
    this.$message.info('新增失败:' + res.message)
    }
    }).finally((res) => {
    this.confirmLoading = false
    })
    } else {
    this.confirmLoading = false
    }
    })
    },
    handleCancel() {
    this.form.resetFields()
    this.visible = false
    },
    handleOk() {
    this.dictTypeData().then(() => {
    this.cardTypeDictionary = this.$options.filters['dictData']('card_type')
    this.$emit('refresh-dict')
    })
    },
    handleCancel1 () {
    this.previewImage = ''
    this.previewVisible = false
    },
    // 打开模态框(图片预览)
    async handlePreview (file) {
    if (!file.url && !file.preview) {
    file.preview = await getBase64(file.originFileObj)
    }
    this.previewImage = file.url || file.preview
    this.previewVisible = true
    },
    // 删除照片
    handleRemove (file) {
    const index = this.fileList.indexOf(file)
    const newFileList = this.fileList.slice()
    newFileList.splice(index, 1)
    this.fileList = newFileList
    this.flag = false
    },
    // 上传图片之前的校验
    beforeUpload (file) {
    if (this.fileList.length === 10) {
    this.$message.warn('只能上传9个文件')
    const newFileList = this.fileList.slice()
    newFileList.splice(-1, 7)
    this.fileList = newFileList
    } else {
    this.fileList = [...this.fileList, file]
    }
    // 获得允许上传的文件类型
    var type = this.$refs.files.$attrs['data-type']
    for (let item of this.fileList) {
    var exName = item.name.split('.')[1]
    if (type.indexOf(exName) === -1) {
    this.$message.error('请检查文件类型,只允许上传图片文件')
    const index = this.fileList.indexOf(file)
    this.fileList.splice(index, 1)
    break
    }
    // 判断文件大小
    if (item.size / 1024 / 1024 > 20) {
    this.$message.error('上传文件大小不能超过20MB')
    break
    }
    }
    return false
    },
    // 上传图片方法
    handleChange (file) {
    // 当删除的时候会触发onchange事件 因此使用flag控制onchange事件
    if (this.flag === true) {
    const formData = new FormData()
    formData.append('file', file.file)
    this.fileList = file.fileList
    upload(formData).then((res) => {
    this.fileId = res.data
    if (res.data.code === '500') {
    this.$message.error(res.data.message)
    this.fileList = []
    }
    if (res.data.code === '200') {
    this.$message.success(res.data.message)

    }
    })
    } else{
    this.flag = true
    }
    }
    }
    }
    </script>

编辑

<template>
  <a-modal
    title="编辑会员卡类别"
    :width="900"
    :visible="visible"
    :confirmLoading="confirmLoading"
    @ok="handleSubmit"
    @cancel="handleCancel">

    <a-spin :spinning="confirmLoading">
      <a-form :form="form">

        <a-form-item
          style="display: none"
          :labelCol="labelCol"
          :wrapperCol="wrapperCol"
          has-feedback=""
        >
          <a-input v-decorator="['id']"/>
        </a-form-item>

        <a-form-item
          label="会员卡名称"
          :labelCol="labelCol"
          :wrapperCol="wrapperCol"
          has-feedback=""
        >
          <a-input placeholder="请输入会员卡名称" v-decorator="['name', {rules: [
            {required: true, message: '请输入会员卡名称!'},
            {pattern:RegexUtil.REGEX_COMMON_AND_SPECIAL,message:'不能含有特殊字符!'}
            ]}]"/>
        </a-form-item>

        <a-form-item
          label="会员卡类型"
          :labelCol="labelCol"
          :wrapperCol="wrapperCol"
          has-feedback=""
        >
          <a-select style="width: 100%" placeholder="请选择会员卡类型" :allowClear="true"
                    v-decorator="['type', {rules: [{ required: true, message: '请选择会员卡类型!' }]}]">
            <a-select-option v-for='item in cardTypeDictionary' :key="item.id" :value="item.code">{{item.name}}
            </a-select-option>
          </a-select>
        </a-form-item>

        <a-form-item
          label="会员卡等级"
          :labelCol="labelCol"
          :wrapperCol="wrapperCol"
          has-feedback=""
        >
          <a-input placeholder="请输入会员卡等级,默认为0" type="number" v-decorator="['level',{rules: [{pattern:RegexUtil.REGEX_NUMBER,message:'会员等级不能输入小数!'}]}]"/>
        </a-form-item>

        <a-form-item
          label="兑换比例"
          :labelCol="labelCol"
          :wrapperCol="{
            xs: {span: 24},
            sm: {span: 10}
          }"
        >
          <a-col :span="5">
            一元兑换
          </a-col>
          <a-col :span="14">
            <a-input placeholder="请输入兑换比例" type="number"
                     v-decorator="['proportion', {rules: [{required: true, message: '请输入兑换比例!'}]}]"/>
          </a-col>
          <a-col :span="4" offset="1">
            积分
          </a-col>

        </a-form-item>

        <a-form-item
          label="优先使用"
          :labelCol="labelCol"
          :wrapperCol="wrapperCol"
        >
          <a-radio-group  v-decorator="['useOrder',{rules: [{ required: true, message: '请选择使用顺序!' }]}]">
            <a-radio value="1">本金积分</a-radio>
            <a-radio value="2">赠送积分</a-radio>
          </a-radio-group>
        </a-form-item>

        <a-form-item
          label="使用范围"
          :labelCol="labelCol"
          :wrapperCol="wrapperCol"
        >
          <a-checkbox-group v-decorator="['useRange',{rules: [{ required: true, message: '请选择使用范围!' }]}]">
            <a-checkbox v-for="item in cardUseRangeDictionary" :key="item.id" :value="item.code">{{item.name}}
            </a-checkbox>
          </a-checkbox-group>
        </a-form-item>

        <a-form-item
          label="使用城市"
          :labelCol="labelCol"
          :wrapperCol="wrapperCol"
        >
          <a-checkbox-group v-decorator="['useCity',{rules: [{ required: true, message: '请选择使用城市!' }]}]">
            <a-checkbox v-for="item in cardUseCityDictionary" :key="item.id" :value="item.code">{{item.name}}
            </a-checkbox>
          </a-checkbox-group>
        </a-form-item>

        <a-form-item
          label="描述"
          :labelCol="labelCol"
          :wrapperCol="wrapperCol"
          has-feedback=""
        >
          <a-textarea :rows="4" placeholder="请输入描述" v-decorator="['description']"></a-textarea>
        </a-form-item>

        <a-form-item label="图片上传" :labelCol="labelCol" :wrapperCol="wrapperCol" has-feedback="">
          <a-upload name="file" v-decorator="['cardImage']" list-type="picture-card" :file-list="fileList" :showUploadList="true"
                    data-type="jpg|png|jpeg" ref="files" :before-upload="beforeUpload" @change="handleChange"
                    :remove="handleRemove" @preview="handlePreview"  style="margin-left: 10%">
            <div v-if="fileList.length < 1" id="container">
              <a-icon type="plus" />
              <div class="ant-upload-text">上传</div>
            </div>
          </a-upload>
          <a-modal :visible="previewVisible" :footer="null" @cancel="handleCancel1">
            <img alt="无法加载" style="width: 100%" :src="previewImage"/>
          </a-modal>
        </a-form-item>

      </a-form>
    </a-spin>
  </a-modal>
</template>

<script>
import {detail, edit, upload} from '@/api/modular/vipCardType/vipCardTypeManage'
import RegexUtil from "@/utils/RegexUtil";

function getBase64 (file) {
  return new Promise((resolve, reject) => {
    const reader = new FileReader()
    reader.readAsDataURL(file)
    reader.onload = () => resolve(reader.result)
    reader.onerror = error => reject(error)

  })
}

export default {
  data() {
    return {
      labelCol: {
        xs: {span: 24},
        sm: {span: 5}
      },
      wrapperCol: {
        xs: {span: 24},
        sm: {span: 15}
      },
      visible: false,
      confirmLoading: false,
      cardTypeDictionary: [],
      cardUseRangeDictionary: [],
      cardUseCityDictionary: [],
      cardUseCity: [],
      oldData: {},
      form: this.$form.createForm(this),
      RegexUtil,

      flag: true,
      fileList: [],
      fileId: '',
      previewVisible: false,
      previewImage: '',
      newfileArr: [],
      fUid: '',
      fName: '',
      newFlag: false,
    }
  },
  methods: {
    edit(typeId) {
      this.visible = true
      this.confirmLoading=true
      this.cardTypeDictionary = this.$options.filters['dictData']('card_type')
      this.cardUseCityDictionary = this.$options.filters['dictData']('card_use_city')
      this.cardUseRangeDictionary = this.$options.filters['dictData']('card_use_range')
      detail({id: typeId}).then((res) => {


          setTimeout(() => {
            if (res.success) {
              let record = res.data
              this.oldData = res.data
              this.form.setFieldsValue({
                id: record.id,
                name: record.name,
                type: record.type,
                level: record.level,
                proportion: record.proportion,
                useRange: record.useRange.split(','),
                useCity: record.useCity.split(','),
                description: record.description,
                useOrder: record.useOrder,
              })
              this.cardImage = res.data.cardImage
              // 必须要给fileList绑定这些数据 否则会报错
              let newFileArr = {
                // uid: this.fUid,
                uid: '1111',
                // name: this.fName,
                name: '2222',
                url: this.cardImage,
                status: 'done'
              }

              this.fileList.push(newFileArr)
            } else {
              this.$message.error("获取数据失败")
            }
          }, 100)
        }
      ).catch((err) => {
        this.$message.error("获取数据失败")
      }).finally(() => {
          this.confirmLoading = false
        }
      )
    },
    handleSubmit() {
      const {form: {validateFields}} = this
      this.confirmLoading = true

      validateFields((errors, values) => {
        if (!errors) {

          values.cardImage = this.fileId
          edit(values).then((res) => {
            this.confirmLoading = false
            if (res.success) {
              this.$message.success('编辑成功')
              this.handleCancel()
              this.$emit('ok', values)
            } else {
              this.$message.info('编辑失败:' + res.message)
            }
          }).finally((res) => {
            this.confirmLoading = false
          })
        } else {
          this.confirmLoading = false
        }
      })
    },
    handleCancel() {
      this.form.resetFields()
      this.visible = false
      this.fileList = []
    },
    handleCancel1 () {
      this.previewImage = ''
      this.previewVisible = false
    },
    // 打开模态框(图片预览)
    async handlePreview (file) {
      if (!file.url && !file.preview) {
        file.preview = await getBase64(file.originFileObj)
      }
      this.previewImage = file.url || file.preview
      this.previewVisible = true
    },
    // 删除照片
    handleRemove (file) {
      const index = this.fileList.indexOf(file)
      const newFileList = this.fileList.slice()
      newFileList.splice(index, 1)
      this.fileList = newFileList
      this.flag = false
      this.newFlag = true
      this.cardImage = ''
    },
    // 上传图片之前的校验
    beforeUpload (file) {
      if (this.fileList.length === 1) {
        this.$message.warn('只能上传1个文件')
        const newFileList = this.fileList.slice()
        newFileList.splice(-1, 7)
        this.fileList = newFileList
        return
      } else {
        this.fileList = [...this.fileList, file]
      }
      // 获得允许上传的文件类型
      var type = this.$refs.files.$attrs['data-type']
      for (let item of this.fileList) {
        var exName = item.name.split('.')[1]
        if (type.indexOf(exName) === -1) {
          this.$message.error('请检查文件类型,只允许上传图片文件')
          const index = this.fileList.indexOf(file)
          this.fileList.splice(index, 1)
          break
        }
        // 判断文件大小
        if (item.size / 1024 / 1024 > 20) {
          this.$message.error('上传文件大小不能超过20MB')
          break
        }
      }
      return false
    },
    // 上传图片方法
    handleChange (file) {
      // 当删除的时候会触发onchange事件 因此使用flag控制onchange事件
      if (this.flag === true) {
        const formData = new FormData()
        formData.append('file', file.file)
        this.fileList = file.fileList
        upload(formData).then((res) => {
          this.fileId = res.data
          this.cardImage = this.fileId
          if (res.data.code === '500') {
            this.$message.error(res.data.message)
            this.fileList = []
          }
          if (res.data.code === '200') {
            this.$message.success(res.data.message)
          }
        })
      } else {
        this.flag = true
      }
    }
  }
}
</script>

/**
 * 上传图片
 * @param parameter
 * @returns {AxiosPromise}
 */
export function upload(parameter) {
  return axios({
    url: '/sysFileInfo/uploadFile',
    method: 'post',
    data: parameter
  })
}

url拼接

原版:绑定的背景图片是本地

<van-row @click="toDetailPage(membershipCard)" class="cardBody" :style="{backgroundImage: 'url('+require('../../assets/images/card1.png')+')'}">
<template>
  <div id="app">
    <div style="overflow: auto" id="container">
      <van-row>
        <img src="../../assets/images/oneCardTitle.png" style="width: 100%;">
      </van-row>
      <!--<van-row @click="toDetailPage(membershipCard)" class="cardBody" v-for="membershipCard in membershipCardList">-->

      <div v-for="membershipCard in membershipCardList">

        <!--<van-row @click="toDetailPage(membershipCard)" class="cardBody" :style="{backgroundImage: 'url('+require('../../assets/images/card1.png')+')'}">-->
        <!--<van-row @click="toDetailPage(membershipCard)" class="cardBody" :style="bg">-->

				
        <van-row @click="toDetailPage(membershipCard)" class="cardBody" :style="{backgroundImage: 'url('+require(''+ bgUrl + '')+')'}">
        <!--lfh改版后-->
        <van-row @click="toDetailPage(membershipCard)" class="cardBody" :style="{backgroundImage: 'url('+ bgUrl +')'}">
        <van-row @click="toDetailPage(membershipCard)" class="cardBody" :style="{backgroundImage: 'url('+ membershipCard.cardImage + ')'}">

          <van-col class="nameMargin">
            <van-col class="cardName carWeight">
              {{ membershipCard.userName }}
            </van-col>
            <van-col class="cardOneName carWeight">
              {{ membershipCard.cardTypeName }}
            </van-col>
          </van-col>
          <van-col class="nameMargin cardNumber">
            {{ membershipCard.cardNo }}
          </van-col>
        </van-row>

      </div>

      <div class="push"></div>

    </div>
    <div class="bindingBottom" @click="skip('/oneCard/signIn')">
      <van-button class="bindingFont">
        <van-icon style="font-weight: 900;color: rgb(118, 118, 118);" name="plus" /> 绑定新卡
      </van-button>
    </div>

  </div>
</template>

<script>
import { getUserInfo } from '@/utils/auth'
import {getList} from "@/api/oneCard/signIn";
export default {
  name: '',
  data() {
    return {
      url: '',
      membershipCardList: [],
      // bg: {backgroundImage: 'url('+require('../../assets/images/card1.png')+')'}
      // bg: {backgroundImage: 'url('+require('https://info.lbbjt.com/image/system/1638079146562400257.png')+')'}
      // bg: {backgroundImage: url('https://info.lbbjt.com/image/system/1638079146562400257.png')}
      bgUrl: 'https://info.lbbjt.com/image/system/1638079146562400257.png',
    }
  },
  watch: {
  },
  mounted() {

  },
  created() {

    getList(getUserInfo().wechatOpenId).then((res) => {
      this.membershipCardList = res.data.data
    }).catch((e) => {
      console.log(e)
    })
  },
  methods: {
    skip(url) {
      this.$router.push(url)
    },
    toDetailPage(membershipCard) {
      this.$router.push({
        path: '/oneCard/cardDetails',
        // name: 'cardDetails',
        query: {
          // membershipCard: membershipCard
          userName: membershipCard.userName,
          cardTypeName: membershipCard.cardTypeName,
          cardNo: membershipCard.cardNo
        }
      })
    }
  }
}
</script>

<style lang='scss' scoped>
.cardBody{
  //background: url('../../assets/images/card1.png');
  background-size: 100% 100%;
  width: 94%;
  height: 200px;
  margin: 3%;
  background-repeat: no-repeat;
  display: flex;
  flex-direction: column;
  justify-content: space-around;
  border-radius: 20px;
}
.carWeight{
  font-weight: 900;
}
.cardName{
  color: rgb(244,162,182);
  font-size: 1.1em;
}
.cardOneName{
  font-size: 2.5em;
  color: #fff;
}
.cardNumber{
  font-size: 1em;
  color: #fff;
  font-weight: 600;
  letter-spacing: 1px;
}
.nameMargin{
  margin-left: 8%;
  display: flex;
  padding-top: 2.4em;
  flex-direction: column;
}

.bindingFont{
  width: 90%;
  border-radius:25px;
  font-weight: 600;
  font-size: 1.2em;
  background-color:#fff;
  box-shadow: 0px 20px 40px 25px rgba(0, 0, 0, .2);
}
body{
  background: rgb(239,239,239);
}
#app{
  height: 100%;
  margin:0;
  padding:0;
}
#container{
  min-height: 100%;
  height: auto !important;
  margin: 0 auto -60px;/*margin-bottom的负值等于footer高度*/
}
.push,
.bindingBottom{
  text-align: center;
  //position: absolute;
  //bottom: 20px;
  //width: 100%;
  height: 60px;
}
</style>

访问http图片拼接

<van-row @click="toDetailPage(membershipCard)" class="cardBody" :style="{backgroundImage: 'url('+ membershipCard.cardImage + ')'}">

div的v-for写法

image.png
res
image.png

会员卡页面维护

从卡页面跳转到详情页

  1. 点击卡面跳转时,会进入方法传递参数
  2. 跳转到卡详情页面后,在created处绑定卡面的数据

会员卡页面-一张卡的样式
点击卡面的方法
跳转到会员卡详情页面的赋值
image.png image.png

前端Select下拉框动态赋值

image.png
image.png
image.png

一定要拿对象包裹参数 id name

image.png

add方法是活动管理页面跳转进来

image.png

在每次关闭对话框的时候清空数组,
否则第二次点开对话框会报错,

image.png
image.png
image.png

关于此处报错问题

image.png

回到代码发现是下拉框变更的方法出了问题
大概是因为点击清除按钮后,找不到data,此时option是undefined
所以添加了if判断

image.png

antD中 v-decorator=[‘xxx’] 的取值问题

image.png
image.png

关闭子模态框后刷新父模态框

image.png

expandedRowRender and scroll

warning: [antdv: expandedRowRender and scroll are not compatible. Please use one of them at one time.]
展开和固定头部或列不能一起使用 不影响效果
image.png
image.png
image.png

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值