vue 自定义指令 实现 滚动页面发送请求完成页面

1.自定义指令部分

export default {
  inserted(el, binding) {
    const domHeight = el.clientHeight;
    let distance = Number(binding.arg)
    if (Number.isNaN(distance)) distance = 0
    const { immediate } = binding.modifiers
    const cb = binding.value

    if (el.scrollHeight === 0) {
      console.log(`scollheigt == ${el.scrollHeight}, 请检查overflow属性`);
    }

    const handleScroll = () => {
      if (el.scrollHeight - el.scrollTop - distance <= domHeight) {
        console.log(el.scrollTop, 'bottom!');
        cb()
      }
    }
    el['ifsScope'] = { handleScroll }

    el.addEventListener('scroll', handleScroll)
    // childList:子节点的变动。
    // attributes:属性的变动。
    // characterData:节点内容或节点文本的变动。
    // subtree:所有后代节点的变动。
    if (immediate) {
      const observer = new MutationObserver(handleScroll)
      observer.observe(el, { childList: false, subtree: false })
      handleScroll()
    }
  },
  unbind(el) {
    const { handleScroll } = el['ifsScope']
    el.removeEventListener('scroll', handleScroll)
  }
}

2.页面使用部分

<template>
  <div
    class="recycle-scroller-demo"
    :class="{
      'page-mode': pageMode,
      'full-page': pageModeFullPage,
    }"
  >
  <div class="container">
    <div class="header-search-wrap">
      <div class="mr20">
         <span class="text-style">时间范围</span>
              <el-date-picker
                v-model="searchObj.timevalue"
                type="datetimerange"
                range-separator="至"
                start-placeholder="开始日期"
                end-placeholder="结束日期">
              </el-date-picker>
      </div>
      <div class="mr20">
        <span v-if="type != 'PARK'" class="text-style">所属区域</span>
          <el-cascader
            v-if="type !== 'PARK'"
            class="my-style"
            popper-class="site-cascader"
            style="width: 200px;height:36px;margin-right:10px"
            ref="casca"
            size="small"
            v-model="searchObj.treeIds"
            :options="treeData"
            :props="{ checkStrictly: false, value: 'id', label: 'name', children: 'childInfoVOList', emitPath: false, multiple: true }"
            clearable>
          </el-cascader>
      </div>
      <div class="mr20">
         <span class="text-style">项目名称</span>
         <el-input clearable v-model="searchObj.programName" placeholder="搜索项目名称" width="200"></el-input>
      </div>
      <div class="mr20">
          <span class="text-style" style="line-height: 36px;">污染程度</span><el-select v-model="searchObj.quality" placeholder="污染程度">
            <el-option
            v-for="item in optonsArr"
            :key="item.value"
            :label="item.label"
              :value="item.value">
              </el-option>
          </el-select>
      </div>
      <div class="mr20">
        <el-button type="primary" size="mini"  @click="fetchTableData">查 询</el-button>
        <el-button type="primary" size="mini"  @click="resetClick">重 置</el-button>
        <el-button type="primary" size="mini"  @click="exportTableData">导出数据</el-button>
      </div>
    </div>
      <div class="legend-wrap">
        <dl>
          <dd v-for="(item,index) in Object.keys(colorObj)" :key="index">
            <span>{{item}}</span><b :class="colorObj[item]"></b>
          </dd>
        </dl>
      </div>
    <div v-loading="loading" element-loading-text="拼命加载中"
    element-loading-spinner="el-icon-loading"
    element-loading-background="rgba(0, 0, 0, 0.8)" class="table-wrap" v-directive-list:[50]="getDataMy">
       <dl class="table-head">
            <dt>序号</dt>
            <dt>区域</dt>
            <dt>项目名称</dt>
            <dt>PM10(μg/)</dt>
            <dt>PM2.5</dt>
            <dt>统计时间</dt>
            <dt>污染程度</dt>
          </dl>
          <dl  class="table-body" v-for="(item,index) in items"		:key="index" :class="colorObj[item.airQuality]" >
                   <dd>{{index + 1}}</dd>
                    <dd >{{item.area}}</dd>
                    <dd @click="handleClickDialog(item)" style="cursor:pointer;">{{item.programName}}</dd>
                    <dd>{{item.pm10}}</dd>
                    <dd>{{item.pm25}}</dd>
                    <dd>{{item.statisticsTime}}</dd>
                    <dd>{{item.airQuality}}</dd>
                </dl>
    </div>
    </div>
    <MyDialog ref="myDialog" :dialogTitle ="dialogTitle" dialogWidth="90%">
            <GZNormalWrap style="background-color: #031439">
              <div class="header-search-wrap">
                  <el-date-picker
                  v-model="searchObj.timevalue"
                  type="datetimerange"
                  range-separator="至"
                  start-placeholder="开始日期"
                  end-placeholder="结束日期">
                </el-date-picker>
                <el-button type="primary" size="mini"  @click="fetchTableData" style="margin-left:20px">查 询</el-button>
              </div>
        <div style="width: 100%; min-height:500px; display: flex; flex-direction: column">
          <div class="dialog-content">
            <div style="flex: 1; margin-top: 12px;">
              <chart :options="options" auto-resize class="mycharts2"></chart>
            </div>
          </div>
        </div>
      </GZNormalWrap>
    </MyDialog>
  </div>
</template>
<script>
import api from 'api';
import GetUrlParams from 'mixins/getUrlParams'
import GZNormalWrap from '../../common/GZNormalWrap';
import MyDialog from 'plugin/MyDialog';
import directiveList from 'utils/directiveList';
import Axios from 'axios'
export default {
  directives: { directiveList },
  data() {
    return {
      searchObj: {
        timevalue: [new Date().getTime() - 2 * 60 * 60 * 1000, new Date().getTime()],
        areaCodes: [],
        programName: '',
        quality: ''
      },
      dialogVisible: false,
      dialogTitle: '',
      detailObj: {
        timevalue: [new Date().getTime() - 2 * 60 * 60 * 1000, new Date().getTime()]
      },
      loading: false,
      pageNo: 1,
      pageSize: 30,
      treeData: [],
      colorObj: { '优': 'level-class5', '良': 'level-class4', '轻度污染': 'level-class3', '中度污染': 'level-class2', '重度污染': 'level-class1', '严重污染': 'level-class', '0值': 'level-class6', '离线': 'level-class7' },
      count: 10000,
      renderScroller: true,
      showScroller: true,
      scopedSlots: false,
      buffer: 200,
      poolSize: 2000,
      enableLetters: true,
      pageMode: false,
      totalCount: 0,
      pageModeFullPage: true,
      options: {
        tooltip: {
          trigger: 'axis'
        },
        legend: {
          left: 'right',
          top: 0,
          textStyle: {
            color: 'fff',
            fontSize: 12
          }
        },
        grid: {
          left: 20,
          right: 10,
          bottom: 30,
          top: 30,
          containLabel: true
        },
        xAxis: {
          type: 'category',
          axisLabel: {
            show: true,
            // interval: 0,
            // rotate: -30,
            fontSize: 12,
            formatter: item => {
              if(item.split(' ').length > 1) {
                return item.replace(/(\d{4})-(\d{2})-(\d{2}) (\d{2}):(\d{2}):(\d{2})/g, '$4')
              } else {
                return item.replace(/(\d{4})-(\d{2})-/g, '')
              }
            },
            textStyle: {
              color: '#fff'
            }
          },
          axisLine: {
            // onZero: true,
            lineStyle: {
              color: '#0D85B4'
            }
          },
          axisTick: {
            show: false
          },
          data: []
        },
        yAxis: {
          name: 'PM10',
          nameTextStyle: {
            color: '#FFFFFF'
          },
          type: 'value',
          axisLabel: {
            show: true,
            fontSize: 12,
            textStyle: {
              color: '#fff'
            }
          },
          axisLine: {
            onZero: true,
            lineStyle: {
              color: '#00C6FF'
            }
          },
          axisTick: {
            show: false
          },
          splitLine: {
            show: true,
            lineStyle: {
              type: 'dashed',
              color: '#00C6FF',
              opacity: 0.3
            }
          }
        },
        color: ['#3399FF', '#61DDAA', '#65789B', '#F6BD16'],
        series: [
          {
            name: 'PM10',
            data: [],
            type: 'line',
            symbol: 'circle',
            smooth: true,
            symbolSize: 10
          },
          {
            name: 'PM25',
            data: [],
            type: 'line',
            symbol: 'circle',
            smooth: true,
            symbolSize: 10
          }
        ]
      },
      items: [
      ],
      qualityObj: { '优': 'GOOD', '良': 'MODERATE', '轻度污染': 'LIGHTLY_POLLUTED', '中度污染': 'MODERATELY_POLLUTED', '严重污染': 'SEVERELY_POLLUTED', '重度污染': 'HEAVILY_POLLUTED', '0值': 'ZERO', '离线': 'OFFLINE' },
      optonsArr: [{ label: '全部', value: '' }, { label: '优', value: 'GOOD' }, { label: '良', value: 'MODERATE' }, { label: '轻度污染', value: 'LIGHTLY_POLLUTED' }, { label: '中度污染', value: 'MODERATELY_POLLUTED' }, { label: '重度污染', value: 'HEAVILY_POLLUTED' }, { label: '严重污染', value: 'SEVERELY_POLLUTED' }, { label: '0值', value: 'ZERO' }, { label: '离线', value: 'OFFLINE' }]
    }
  },
  mixins: [GetUrlParams],
  components: {
    GZNormalWrap,
    MyDialog
  },
  mounted() {
    this.getChildExcludePark()
    window.scroller = this.$refs.scroller
    this.getDustMonitorOverview()
    this.intervalId = setInterval(() => {
      this.pageNo = 1
      this.getDustMonitorOverview()
      // clearInterval(intervalId);
    }, 5 * 60 * 1000);
  },
  destroyed() {
    clearInterval(this.intervalId)
  },
  methods: {
    getChildExcludePark() {
      const type = this.type;
      const id = this.id;
      this.$get(api.getChildExcludePark(this.globalTenantId, this.type, this.id), {
        tenantId: this.globalTenantId,
        type,
        id
      }).then(res => {
        if(res.data) {
          const walk = (arr) => {
            arr.forEach(item => {
              if(item.childInfoVOList && !item.childInfoVOList.length) {
                delete item.childInfoVOList
              }else {
                walk(item.childInfoVOList)
              }
            })
          }
          walk([res.data])
          this.treeData = [res.data];
        }
      })
    },
    exportTableData() {
      if(!this.searchObj.timevalue) {
        this.$message.warning('请选择时间范围')
        return
      }
      let startTime = ''
      let endTime = ''
      if(this.searchObj.timevalue[0] && isNaN(this.searchObj.timevalue[0])) {
        startTime = this.$moment(this.searchObj.timevalue[0].getTime()).format('YYYY-MM-DD HH:mm:ss')
        endTime = this.$moment(this.searchObj.timevalue[1].getTime()).format('YYYY-MM-DD HH:mm:ss')
      } else {
        startTime = this.$moment(this.searchObj.timevalue[0]).format('YYYY-MM-DD HH:mm:ss')
        endTime = this.$moment(this.searchObj.timevalue[1]).format('YYYY-MM-DD HH:mm:ss')
      }
      const tenantVOS = []
      const areaCodes = this.searchObj.treeIds
      const walk = (arr) => {
        arr.forEach(item => {
          if(areaCodes.includes(item.id)) {
            tenantVOS.push({
              'id': item.id, 'type': item.type
            })
          }
          if(item.childInfoVOList) {
            walk(item.childInfoVOList)
          }
        })
      }
      if(areaCodes && areaCodes.length > 0) {
        walk(this.treeData)
      }
      const params = {
        'pageNo': 1,
        'pageSize': 2000,
        'quality': this.searchObj.quality,
        'periodStartTime': startTime,
        'periodEndTime': endTime,
        'tenantVOS': tenantVOS,
        'programName': this.searchObj.programName
      }
      if(!this.searchObj.quality) {
        delete params.quality
      }
      Axios.post(
        api.getDustMonitorOverviewExport(
          this.globalTenantId,
          this.type,
          this.id
        ), params, {
          responseType: 'blob'
        }
      )
        .then(res => {
          const content = res.data;
          const blob = new Blob([content], { type: 'application/ms-excel' });
          let fileName = res.headers['content-disposition'].split('=')[1];
          /* let Base64 = require('js-base64').Base64;
            fileName = Base64.decode(fileName)*/
          fileName = '扬尘监测统计列表.xlsx' || decodeURIComponent(fileName);
          if ('download' in document.createElement('a')) {
            // 非IE下载
            const elink = document.createElement('a');
            elink.download = fileName;
            elink.style.display = 'none';
            elink.href = URL.createObjectURL(blob);
            document.body.appendChild(elink);
            elink.click();
            URL.revokeObjectURL(elink.href); // 释放URL 对象
            document.body.removeChild(elink);
          } else {
            // IE10+下载
            navigator.msSaveBlob(blob, fileName);
          }
        })
        .catch(mes => {
          console.log(mes)
        })
      // downloadExcle(api.getDustMonitorOverviewExport(this.globalTenantId, this.type, this.id), {
      //   ...params
      // }, '超标项目统计', this.getDustMonitorOverview(this.type, this.id))
    },
    getDataMy() {
      if(this.pageNo * this.pageSize > this.totalCount) {
        return
      }
      this.pageNo++
      this.getDustMonitorOverview()
    },
    handleClickDialog(val) {
      this.dialogTitle = val.programName
      this.dialogObj = val
      this.detailObj = this.$options.data().detailObj
      this.getDustMonitorOverviewDetail(val)
      this.$refs.myDialog.dialogVisible = true
    },
    fetchTableData() {
      this.pageNo = 1
      this.getDustMonitorOverview()
    },
    getDustMonitorOverview() {
      if(!this.searchObj.timevalue) {
        this.$message.warning('请选择时间范围')
        return
      }
      let startTime = ''
      let endTime = ''
      if(this.searchObj.timevalue[0] && isNaN(this.searchObj.timevalue[0])) {
        startTime = this.$moment(this.searchObj.timevalue[0].getTime()).format('YYYY-MM-DD HH:mm:ss')
        endTime = this.$moment(this.searchObj.timevalue[1].getTime()).format('YYYY-MM-DD HH:mm:ss')
      } else {
        startTime = this.$moment(this.searchObj.timevalue[0]).format('YYYY-MM-DD HH:mm:ss')
        endTime = this.$moment(this.searchObj.timevalue[1]).format('YYYY-MM-DD HH:mm:ss')
      }
      const tenantVOS = []
      const areaCodes = this.searchObj.treeIds
      const walk = (arr) => {
        arr.forEach(item => {
          if(areaCodes.includes(item.id)) {
            tenantVOS.push({
              'id': item.id, 'type': item.type
            })
          }
          if(item.childInfoVOList) {
            walk(item.childInfoVOList)
          }
        })
      }
      if(areaCodes && areaCodes.length > 0) {
        walk(this.treeData)
      }
      const params = {
        'pageNo': this.pageNo,
        'pageSize': this.pageSize,
        'quality': this.searchObj.quality,
        'periodStartTime': startTime,
        'periodEndTime': endTime,
        'tenantVOS': tenantVOS,
        'programName': this.searchObj.programName
      }
      if(!this.searchObj.quality) {
        delete params.quality
      }
      this.loading = true
      this.$post(
        api.getDustMonitorOverview(
          this.globalTenantId,
          this.type,
          this.id
        ), params
      )
        .then(res => {
          this.totalCount = res.data.totalCount
          if(this.pageNo === 1) {
            this.loading = false
            this.items = res.data.records
          } else {
            this.loading = false
            this.items = this.items.concat(res.data.records)
          }
        })
        .catch(mes => {
          this.loading = false
          console.log(mes)
        })
    },
    fetchTableDataDetail() {
      if(!this.detailObj.timevalue[0]) {
        this.$message.warning('请选择时间区域')
        return
      }
      let startTime = ''
      let endTime = ''
      if(this.detailObj.timevalue[0] && isNaN(this.detailObj.timevalue[0])) {
        startTime = this.$moment(this.detailObj.timevalue[0].getTime()).format('YYYY-MM-DD HH:mm:ss')
        endTime = this.$moment(this.detailObj.timevalue[1].getTime()).format('YYYY-MM-DD HH:mm:ss')
      } else {
        startTime = this.$moment(this.detailObj.timevalue[0]).format('YYYY-MM-DD HH:mm:ss')
        endTime = this.$moment(this.detailObj.timevalue[1]).format('YYYY-MM-DD HH:mm:ss')
      }
      const params = {
        'pageNo': 1,
        'pageSize': 10,
        'quality': this.qualityObj[this.dialogObj.airQuality],
        'periodStartTime': startTime,
        'periodEndTime': endTime,
        'programId': this.dialogObj.programId,
        'programName': this.dialogObj.programName
      }
      this.$post(
        api.getDustMonitorOverviewDetail(
          this.globalTenantId,
          this.type,
          this.id
        ), params
      )
        .then(res => {
          if(res.data) {
            const xdata = []
            const series = []
            res.data.forEach(item => {
              xdata.push(item.statisticsTime)
              series.push(item.pm10)
            })
            this.options.xAxis.data = xdata;
            this.options.series[0].data = series;
          }
        })
        .catch(mes => {
          console.log(mes)
        })
    },
    getDustMonitorOverviewDetail(val) {
      let startTime = ''
      let endTime = ''
      if(!this.detailObj.timevalue[0]) {
        this.$message.warning('请选择时间区域')
        return
      }
      if(this.detailObj.timevalue[0] && isNaN(this.detailObj.timevalue[0])) {
        startTime = this.$moment(this.detailObj.timevalue[0].getTime()).format('YYYY-MM-DD HH:mm:ss')
        endTime = this.$moment(this.detailObj.timevalue[1].getTime()).format('YYYY-MM-DD HH:mm:ss')
      } else {
        startTime = this.$moment(this.detailObj.timevalue[0]).format('YYYY-MM-DD HH:mm:ss')
        endTime = this.$moment(this.detailObj.timevalue[1]).format('YYYY-MM-DD HH:mm:ss')
      }
      const params = {
        'pageNo': 1,
        'pageSize': 10,
        'quality': this.qualityObj[this.dialogObj.airQuality],
        'periodStartTime': startTime,
        'periodEndTime': endTime,
        'programId': this.dialogObj.programId,
        'programName': this.dialogObj.programName
      }
      this.$post(
        api.getDustMonitorOverviewDetail(
          this.globalTenantId,
          this.type,
          this.id
        ), params
      )
        .then(res => {
          const xdata = []
          const series = []
          const series1 = []
          res.data.forEach(item => {
            xdata.push(item.statisticsTime)
            series.push(item.pm10)
            series1.push(item.pm25)
          })
          this.options.xAxis.data = xdata;
          this.options.series[0].data = series;
          this.options.series[1].data = series1;
        })
        .catch(mes => {
          console.log(mes)
        })
    },
    resetClick() {
      this.searchObj = this.$options.data().searchObj
      this.getDustMonitorOverview()
    },
    setOptions(series) {
      this.options.xAxis.data = this.xdata;
      this.options.series[0].data = series;
      // this.options.dataZoom = this.xdata.length > 50 ? [
      //   {
      //     startValue: 0,
      //     endValue: 8,
      //     type: 'slider',
      //     show: true,
      //     xAxisIndex: [0],
      //     handleSize: 0,
      //     height: 8,
      //     left: '4%',
      //     right: '2%',
      //     bottom: 0,
      //     borderColor: '#042e2c',
      //     fillerColor: 'rgba(64, 158, 255, 0.5)',
      //     borderRadius: 10,
      //     backgroundColor: '#04152e',
      //     showDataShadow: false,
      //     showDetail: false,
      //     realtime: true,
      //     filterMode: 'filter'
      //   }
      // ] : []
    }
  }
}
</script>

<style scoped lang="less">
.legend-wrap{
  // width: 300px;
  align-items: center;
  display: flex;
  margin-left: 10px;
  flex-wrap: wrap;
  dl{
    width: 100%;
    display: flex;
    flex-direction: row;
    flex-wrap: wrap;
    justify-content: flex-end;
    dd{
      margin-left: 5px;
      margin-bottom: 5px;
      white-space: nowrap;
      b{
        margin-left: 2px;
        display: inline-block;
        width: 10px;
        height: 10px;
        border-radius: 2px;
      }
    }
  }
}
.table-wrap{
  height: 100%;
  overflow: auto;
  padding-bottom: 80px;
}
.mr20{
  margin-right: 20px;
}
.mycharts2{
  width: 100%;
}
.level-class{
  background-color: rgba(138, 12, 16,.4);
}
.level-class1{
  background-color: rgb(206, 17, 24,.4);
}
.level-class2{
  background-color: rgba(244, 102, 73,.4);
}
.level-class3{
  background-color: rgb(246, 144, 61,.4);
}
.level-class4{
  background-color: rgba(246, 189, 22,.4);
}
.level-class5{
  background-color: rgba(97, 221, 170,.4);
}
.level-class6{
  background-color: rgb(51, 153, 255,.4);
}
.level-class7{
  background-color: rgb(101, 120, 155,.4);
}
.recycle-scroller-demo:not(.page-mode) {
  height: 100%;
}

.recycle-scroller-demo.page-mode:not(.full-page) {
  height: 100%;
}

.recycle-scroller-demo.page-mode {
  flex: auto 0 0;
}

.recycle-scroller-demo.page-mode .toolbar {
  border-bottom: solid 1px #e0edfa;
}

.content {
  height: 100%;
  flex: 100% 1 1;
  position: relative;
}

.recycle-scroller-demo.page-mode:not(.full-page) .content {
  overflow: auto;
}

.recycle-scroller-demo:not(.page-mode) .wrapper {
  overflow: hidden;
  position: absolute;
  top: 0;
  bottom: 0;
  left: 0;
  right: 0;
}

.scroller {
  width: 100%;
  height: 100%;
}

.container{
  // overflow: auto;
  height: 100%;
}
.content-wrap{
  overflow: auto;
  height: 100%;
}
/deep/ .vue-recycle-scroller__item-view{
  padding: 20px 10px;
  border-bottom: 1px solid #3399FF;
  border-left: 1px solid #3399FF;
  border-right: 1px solid #3399FF;
}

.container{
  .table-head{
    display: flex;
    flex-direction: row;
    justify-content: flex-start;
    border: 1px solid #3399FF;
    background: rgba(51, 153, 255,0.3);
    dt{
      padding: 10px 10px;
      width: 15%;
      color: #fff;
      opacity: 1;
    }
  }
  .table-body{
    display: flex;
    flex-direction: row;
    justify-content: flex-start;
    padding: 20px 10px;
    border-bottom: 1px solid #3399FF;
    border-left: 1px solid #3399FF;
    border-right: 1px solid #3399FF;
    dd{
      width: 15%;
    }
  }
}
  .header-search-wrap{
    display: flex;
    flex-direction: row;
    justify-content: flex-start;
    padding: 15px 0;
    .el-input{
      width: 200px;
    }
    /deep/ .el-input__inner{
      height: 40px;
      line-height: 40px;
      border: 1px solid rgba(16, 220, 250, 0.4);
      background-color: transparent;
      color: #fff;
    }
        /deep/ .el-input__inner{
          background-color: transparent;
          border: 1px solid rgba(16, 220, 250, 0.4);
          color: #fff;
        }
        /deep/	.el-input__inner:focus{
          opacity: 1;
        }
        .el-select{
            vertical-align: top;
          /deep/	.el-input{
            width: 160px;
            .el-input__inner{
              height: 36px;
              line-height: 36px;
              background-color: transparent;
              color: #fff;
              border: 1px solid rgba(16, 220, 250, 0.4);
            }
          }
        }
        .el-cascader{
          /deep/.el-input__inner{
            border: 1px solid rgba(16, 220, 250, 0.4);
            background-color: transparent;
            height: 36px;
          }
          /deep/.el-input__inner:hover{
            border: 1px solid rgba(16, 220, 250, 0.4);
            background-color: transparent;
          }
          /deep/.el-input__inner:focus{
            border: 1px solid rgba(16, 220, 250, 0.4);
            background-color: transparent;
          }
        }
        /deep/ .el-date-editor .el-range-input{
          color: #fff;
        }
        /deep/ .el-date-editor .el-range-separator{
          color: #fff;
        }
           .el-button--mini, .el-button--mini.is-round{
          padding: 11px 12px;
      }
      .el-button--primary{
          background: rgba(5, 35, 76, 0.2);
          border-radius: 4px;
          border: 1px solid  rgba(255, 255, 255, 0.4);
      }
      .el-button--primary:hover{
          color: #10DCFA;
          border: 1px solid  #10DCFA;
      }
      .el-button+.el-button{
          margin-left: 6px;
      }
  }
</style>
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值