vue 进入页面,原生js实现滚动到高亮的分类

注意:scrollTo方法,动画属性在ios不生效,在移动端不建议用

<template>
  <div class="template-page">
    <div class="header">
      <form class='header-input' action="javascript:;">
        <span class='input-icon'></span>
        <input class='input-box'
          type="search"
          v-model.trim='searchValue'
          placeholder="搜索海量模板"
          ref='searchRef'
          :class='{isAndroid: !isIOS()}'
          @keyup='handleKeyChange($event)'>
      </form>
    </div>
    <div class="main">
      <section class="category-wrapper"
        ref="categoryWrapper">
        <div class="category-list"
          ref="categoryList">
          <van-sidebar
            v-model="activeIndex"
            @change="onChange">
            <van-sidebar-item
              v-for="(info, i) in categoryList"
              :key="`sidebar${i}`"
              :title="info.name"/>
          </van-sidebar>
        </div>
      </section>
      <section class="cont-wrapper">
        <div class="poster-wrapper">
          <scroll
            :isEnd='isEnd'
            @pullup='loadMore'
            :isLoading='true'
            :preventDefaultException='{ tagName: /^(INPUT|TEXTAREA|BUTTON|SELECT|AUDIO)$/ }'
            :tagException='{ className: /(^|\s)chat-box(\s|$)/ }'
            ref='scrollBox'>
            <ul class="poster-list"
              v-if="templateList.length">
              <li class="poster-item"
                v-for="(tempInfo, i) in templateList"
                :key="`poster${i}`"
                @click.stop="editPoster(tempInfo, i)">
                <div class="item-header">
                  <p class="name">{{tempInfo.name}}</p>
                </div>
                <div class="item-cont"
                  :style="{height: `${(132 / tempInfo.content.width) * tempInfo.content.height}px` }">
                  <img :src="tempInfo.content.thumb" alt=""/>
                </div>
                <div class="item-footer">{{formatDate(tempInfo.updatedAt)}}</div>
              </li>
            </ul>
          </scroll>
        </div>
      </section>
    </div>
    <div class="footer-wrapper">
      <tabBar/>
    </div>
  </div>
</template>
<script>
import { Sidebar, SidebarItem } from 'vant'
import scroll from '@/components/scroll'
import tabBar from '@/views/template/components/tabBar'

import axios from 'axios'
import ZhihuiEditor from 'zhihui-editor-mobile-sdk'
import { sigCode, getTimeStamp } from '@/utils/zhihuiSig'
export default {
  name: 'templateCenter',
  components: {
    [Sidebar.name]: Sidebar,
    [SidebarItem.name]: SidebarItem,
    scroll,
    tabBar
  },
  data () {
    return {
      // 调用腾讯云智绘API所需参数
      // 获取账户信息
      editorUserInfo: {
        secretId: '',
        secretKey: '',
        uin: '',
        userId: ''
      },
      // 获取access_token用的sig
      accessTokenSig: '',
      accessToken: '', // access_token
      // 获取存储信息
      editorAppInfo: {
        appid: '',
        appKey: '',
        channel: '',
        stamp: 'testUserId',
        timestamp: getTimeStamp(),
        scope: 'all'
      },
      // 获取编辑器信息
      editorSig: '',
      editorToken: '',
      // 左侧分类
      activeIndex: 0,
      categoryList: [],
      searchValue: '',
      currPage: 1,
      pageSize: 20,
      currCategoryId: [],
      templateList: [],
      isEnd: true,
      // 流媒体布局
      waterFallOptions: {
        containerSelector: '.poster-list',
        cardSelector: '.poster-item',
        paddingLeft: 0,
        paddingRight: 0,
        paddingTop: 0,
        paddingBottom: 10,
        distanceX: 10,
        distanceY: 10,
        cardWidth: 132,
        animation: true
      }
    }
  },
  methods: {
    // 编辑模板
    editPoster (info, index) {
      this.currTemplateInfo = info
      this.currTemplateIndex = index
      this.initEditor()
    },
    /**
     * 参数说明
     * @stamp 业务方用户id
     * @templateId 模板ID
     * 1、来源于智绘系统提供的模版id,如果需要可以联系管理员。2、如果是用户自定义的模版数据,也就是from为userConfig时,那么此字段为时间戳
     */
    initEditor () {
      if (!this.editorToken) {
        return this.$toast('token获取失败,请刷新页面')
      }
      // let templateId = this.currTemplateInfo && this.currTemplateInfo.recordId ? this.currTemplateInfo.recordId : '6254db7bccc34b01db8666ec'
      let templateId = this.currTemplateInfo && this.currTemplateInfo._id ? this.currTemplateInfo._id : '6254db7bccc34b01db8666ec'
      // templateId: 61277c23c96d087b42c7276b
      let option = {
        appid: this.editorAppInfo.appid,
        channel: this.editorAppInfo.channel,
        stamp: this.editorAppInfo.stamp,
        timestamp: this.editorAppInfo.timestamp,
        scope: this.editorAppInfo.scope, // 注意此处的scope是按照字符串传入
        templateId: templateId,
        from: 'material',
        // 添加时通过修改模板创建
        // from: this.currTemplateInfo ? 'record' : 'material',
        // 添加时通过自定义模板创建
        // from: this.currTemplateInfo ? 'record' : 'userConfig',
        // // from为'userConfig'时,templateDataConfig必须填写
        // templateDataConfig: [
        //   // 初始化模板大小
        //   {
        //     id: 'workarea', // 必须包含此id
        //     top: 0,
        //     left: 0,
        //     width: 1242,
        //     height: 2208
        //   }
        // ],
        token: this.editorToken,
        /**
         * loading配置,修改加载时logo的显示
         */
        loadingConfig: {
          logoUrl: 'https://medchat.yuemia.com/storage/b55c/e68c/png/facea3c43fa3dc95a464e83d6f30ad71.png'
        },
        /**
         * 头部配置
         */
        headConfig: {
          logoUrl: 'https://medchat.yuemia.com/storage/b55c/e68c/png/facea3c43fa3dc95a464e83d6f30ad71.png', // 头部的logo
          downloadName: '完成', // 下载按钮的名称
          // 用户点击下载按钮callback
          onClickDownload: res => {
            // console.log('res', res)
            this.zhihuiEditor.closeIframe()
            // 完成后进入做题记录页
            this.$router.push({ name: 'templateRecord' })
          },
          isDownloadImg: false // 点击下载按钮后是否下载图片
        }
      }
      // console.log('option', option)
      this.zhihuiEditor = new ZhihuiEditor(option)
      this.zhihuiEditor.openIframe()
    },
    // 切换分类
    onChange (index) {
      this.isEnd = false
      this.activeIndex = index
      let categoryInfo = this.categoryList[index]
      let categoryId = ''
      categoryId = categoryInfo ? categoryInfo['_id'] : ''
      this.currCategoryId = [categoryId]
      this.currPage = 1
      this.templateList = []
      this.fetchTemplateList()
    },
    // 关键词搜索
    handleKeyChange (event) {
      if (event.keyCode === 13) {
        if (!this.searchValue) {
          return this.$toast('请输入关键词')
        }
        this.isEnd = false
        this.currPage = 1
        this.templateList = []
        this.fetchTemplateList()
      }
    },
    loadMore () {
      this.lazyloadId = this.createUniqueId()
      this.currPage += 1
      this.fetchTemplateList()
    },
    refreshScroll () {
      setTimeout(() => {
        if (this.$refs.scrollBox) {
          this.$refs.scrollBox.refresh()
        }
      }, 0)
    },
    // 获取智慧云账号和用户信息
    fetchEditorUserInfo () {
      return new Promise((resolve, reject) => {
        let url = `/zhihui/index`
        this.$get(url).then(res => {
          if (res.code === 200) {
            resolve(res)
          } else {
            this.$_load.hide()
            reject(res.messgae)
          }
        }).catch(err => {
          this.$_load.hide()
          reject(err)
        })
      })
    },
    // 获取access_token用的sig
    fetchAccessTokenSig () {
      let params = {
        id: this.editorUserInfo.userId, // 用户 userId
        secretId: this.editorUserInfo.secretId // 分配的密钥 Id
      }
      let key = this.editorUserInfo.secretKey
      // console.log('sig-params', params)
      // console.log('sig-key', key)
      return sigCode(params, key)
    },
    // 获取 access_token
    fetchAccessToken () {
      return new Promise((resolve, reject) => {
        let url = `获取token的接口`
        let params = {
          id: this.editorUserInfo.userId, // 用户 userId
          secretId: this.editorUserInfo.secretId, // 分配的密钥 Id
          sig: this.accessTokenSig
        }
        // console.log('params', params)
        axios.post(url, params).then(res => {
          // console.log('res', res)
          if (res) {
            resolve(res)
          } else {
            this.$_load.hide()
            // reject('无返回值')
          }
        }).catch(err => {
          this.$_load.hide()
          reject(err)
        })
      })
    },
    // 初始化获取模板素材
    initZhihui () {
      this.$_load.show()
      this.fetchEditorUserInfo().then(res => {
        let data = res.data
        // console.log('info-data', data)
        if (data) {
          this.editorUserInfo = {
            secretId: data.secretId,
            secretKey: data.secretKey,
            uin: data.uin,
            userId: data.userId
          }
          let accessTokenSig = this.fetchAccessTokenSig()
          this.accessTokenSig = accessTokenSig
          // console.log('accessTokenSig', accessTokenSig)
          this.fetchAccessToken().then(res => {
            // console.log('fetchAccessToken', res)
            let data = res.data.data
            if (data) {
              this.accessToken = data.access_token
              this.fetchCategoryList()
            }
          })
        }
      })
    },
    // 获取分类
    fetchCategoryList () {
      if (!this.accessToken) {
        return this.$toast('token获取失败,请刷新页面')
      }
      let url = `获取分类的接口`
      axios.get(url, {
        headers: {
          'Authorization': 'Bearer ' + this.accessToken
        }
      }).then(res => {
        let data = res.data.data
        if (data) {
          this.categoryList = data
          if (!this.currCategoryId) {
            let categoryId = ''
            let categoryInfo = this.categoryList[0]
            categoryId = categoryInfo ? categoryInfo['_id'] : ''
            this.currCategoryId = [categoryId]
          } else {
            let currIndex = this.categoryList.findIndex(item => item._id === this.currCategoryId[0])
            this.activeIndex = currIndex < 1 ? 0 : currIndex
            this.initCurrCategory()
          }
          this.fetchTemplateList()
        }
      }).catch(err => {
        this.$_load.hide()
        this.handleError(err)
      })
    },
    // 获取模板列表
    fetchTemplateList () {
      if (!this.accessToken) {
        return this.$toast('token获取失败,请刷新页面')
      }
      let url = `获取模板的接口`
      let params = {
        filter: { state: 'success', type: 'image' }, // 不需要更改
        filterTermArr: this.currCategoryId, // 根据检索的分类id进行修改
        hideObjects: true, // 不需要更改
        keyword: this.searchValue || null, // 不需要更改
        pageNumber: this.currPage, // 当前页码
        pageSize: this.pageSize, // 每页数量
        sort: { id: 'desc' } // 排序
      }
      if (this.loading) {
        return
      }
      this.loading = true
      axios.post(url, params, {
        headers: {
          'Authorization': 'Bearer ' + this.accessToken
        }
      }).then(res => {
        this.loading = false
        let data = res.data.data
        if (data) {
          this.count = data.info.total
          let templateList = data.items
          this.templateList = this.templateList.concat(templateList)
          this.$nextTick(() => {
            this.handleWaterFall()
          })
          if (this.count > this.templateList.length) {
            this.isEnd = false
          } else {
            this.isEnd = true
          }
          this.refreshScroll()
        }
        this.$_load.hide()
      }).catch(err => {
        this.loading = false
        this.$_load.hide()
        this.handleError(err)
      })
    },
    initZhihui2 () {
      // 获取appid、channel、scope、appKey
      this.fetchEditorUserInfo().then(res => {
        let data = res.data
        // console.log('data', data)
        if (data) {
          this.editorAppInfo = {
            appid: data.appid,
            channel: data.channel,
            stamp: 'testUserId',
            timestamp: getTimeStamp(),
            // timestamp: 1629711353224,
            scope: data.scope,
            appKey: data.appKey
          }
          let sig = this.fetchSig()
          this.editorSig = sig
          // console.log('sig', sig)
          this.fetchEditorToken().then(res => {
            let data = res.data.data
            if (data) {
              let token = data.access_token
              this.editorToken = token
              // console.log('token', token)
            }
          })
        }
      })
    },
    // 获取sig签名
    fetchSig () {
      let params = Object.assign({}, this.editorAppInfo)
      let key = this.editorAppInfo.appKey
      // 注意此处scope参数是按照数组形式传入
      params.scope = [this.editorAppInfo.scope]
      delete params.appKey
      // console.log('sig-params', params)
      // console.log('sig-key', key)
      return sigCode(params, key)
    },
    // 发送请求获取token
    fetchEditorToken () {
      return new Promise((resolve, reject) => {
        let url = `获取token的接口`
        let params = Object.assign({}, this.editorAppInfo)
        // 注意此处scope参数是按照数组形式传入
        params.scope = [this.editorAppInfo.scope]
        params.sig = this.editorSig
        delete params.appKey
        // console.log('token', params)
        axios.post(url, params).then(res => {
          // console.log('res', res)
          if (res) {
            resolve(res)
          } else {
            // reject('无返回值')
          }
        }).catch(err => {
          reject(err)
        })
      })
    },
    // 初始化分类,滚动到高亮位置
    initCurrCategory () {
      this.$nextTick(() => {
        // 获取bScroll的外层容器及高度
        let wrapperBox = this.$refs.categoryWrapper
        let wrapperDomOffsetTop = wrapperBox.offsetTop
        // 获取当前高亮元素
        // 计算出栏目列表的总长度
        let categoryList = this.$refs.categoryList
        let listWrapper = categoryList.getElementsByClassName('van-sidebar')[0]
        let listItemsArr = Array.prototype.slice.call(listWrapper.childNodes)
        let currIndex = this.activeIndex
        let currLabelDom = listItemsArr[currIndex]
        let currDomOffsetTop = currLabelDom.offsetTop
        wrapperBox.scrollTo({ top: currDomOffsetTop - wrapperDomOffsetTop - 50, behavior: 'smooth' })
      })
    }
  },
  created () {
    if (this.$route.query.categoryId) {
      this.currCategoryId = [this.$route.query.categoryId]
    }
    this.initZhihui()
    this.initZhihui2()

    this.handleWaterFall = this.waterFall.bind(this, this.waterFallOptions)
    window.addEventListener('resize', this.handleWaterFall)
  },
  beforeDestroy () {
    window.removeEventListener('resize', this.handleWaterFall)
    // 跳出该页面关闭编辑器
    if (this.zhihuiEditor) {
      this.zhihuiEditor.closeIframe()
    }
  }
}
</script>
<style lang="stylus" scoped>
.template-page
  width 100%
  height 100vh
  background #fff
  padded_box(border-box, 0 0 50px)
  position relative
  .header
    width 100%
    height 56px
    padded_box(border-box, 10px)
    .header-input
      height: 36px;
      background: #F0F1F3;
      // border-radius: 18px;
      border-radius 6px
      display flex
      align-items center
      padding 0 12px
      .input-icon
        flex none
        width 20px
        height 20px
        margin-right 3px
        background url('~assets/img/home_ic_search@3x.png') no-repeat center / 100%
      .input-box
        flex 1
        height 24px
        line-height 24px
        color: #646363
        font-size 14px
        border none
        outline none
        &::-webkit-input-placeholder
          color rgba(100, 99, 99, 0.5)
        &::-webkit-search-cancel-button
          -webkit-appearance: none
        &.isAndroid
          position relative
          top -1px
          &::-webkit-input-placeholder
            position relative
            top 1px
  .main
    width 100%
    height: calc(100% - 56px)
    display: flex
    .category-wrapper
      width auto
      height 100%
      overflow-x hidden
      overflow-y: auto
      .category-list
        width auto
        height: 100%
    .cont-wrapper
      flex: 1
      height 100%
      padded_box(border-box, 0 10px 10px)
      .poster-wrapper
        width 100%
        height 100%
        overflow: auto
        position: relative
        .poster-list
          width 100%
          display flex
          flex-wrap wrap
          .poster-item
            width: 132px;
            // max-height: 500px;
            background: #FFFFFF;
            border: 1px solid #D0D0D1;
            border-radius: 4px;
            margin 0 0 10px 0
            overflow: hidden
            position relative
            &:nth-of-type(2n+1)
              margin-right 10px
            .item-header
              display: flex
              justify-content: space-between
              align-items: center
              width 100%
              height: 32px;
              line-height 16px
              font-size 12px
              padded_box(border-box,8px)
              .name
                width 100%
                height 16px
                line-height 16px
                noWrap()
            .item-cont
              width 100%
              img
                width 100%
                // max-height 454px
                height 100%
            .item-footer
              width 100%
              height: 32px;
              line-height 16px
              font-size 12px
              color #fff
              padded_box(border-box, 8px)
              background-image: linear-gradient(180deg, rgba(0,0,0,0.00) 0%, rgba(0,0,0,0.50) 100%);
              position absolute
              left 0
              right 0
              bottom 0
  .footer-wrapper
    width 100%
    height 50px
    padded_box(border-box, 0 10px)
    position: absolute
    left 0
    right 0
    bottom: 0
    z-index 1000
</style>
14785216-d567c66033844f3b(1).png
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 218,204评论 6 506
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 93,091评论 3 395
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 164,548评论 0 354
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 58,657评论 1 293
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 67,689评论 6 392
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,554评论 1 305
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,302评论 3 418
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 39,216评论 0 276
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,661评论 1 314
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,851评论 3 336
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,977评论 1 348
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,697评论 5 347
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 41,306评论 3 330
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,898评论 0 22
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 33,019评论 1 270
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 48,138评论 3 370
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,927评论 2 355

推荐阅读更多精彩内容