Browse Source

wenmenghao

yuelujie 9 months ago
parent
commit
cc1c023311

+ 4 - 2
jydocs-back/servers/stdDoc.go

@@ -186,11 +186,13 @@ func (stdDoc *StdDoc) GetDoc(sign string) {
 		if docId == "" {
 			return nil, fmt.Errorf("参数异常")
 		}
-		detail, isBuy, _, err := rpc.GetDocDetail(userId, docId, false)
+		detail, isBuy, _, err := rpc.GetDocDetail(userId, docId, true)
 		if err != nil {
 			return nil, err
 		}
-		if !isBuy {
+		if !isBuy && !(sign == "Show" && detail.Source == public.SourceJy) {
+			detail.OssPdfId = ""
+			detail.OssDocId = ""
 			return nil, fmt.Errorf("请先兑换文档")
 		}
 		fileId := detail.OssPdfId

+ 22 - 11
jydocs-mobile/src/components/docs-card/Card.vue

@@ -41,7 +41,9 @@
           <span class="f-l-item subinfo-item card-time" :class="index === subInfo.length - 1 ? 'last' : ''"
             v-for="(item, index) in subInfo" :key="index">{{ item }}</span>
           <slot name="leftEnd">
-            <div class="jydocs_vip" v-if="isVip">会员免费</div>
+           <span class="type-tag"
+            v-if="productType"
+            :class="productType === 2 ? 'boutique' : 'free'">{{ productType === 2 ? '付费精品' : '会员免费' }}</span>
           </slot>
         </div>
         <div class="c-f-right flex-r-c">
@@ -76,6 +78,7 @@ export default class DocsCard extends Vue {
   @Prop({ default: '' }) uploader?: string | undefined;
   @Prop({ default: -1 }) price?: string | number;
   @Prop({ default: false }) isVip?: boolean;
+  @Prop({ default: 0 }) productType?: number;
   @Prop({
     type: Array,
     default () {
@@ -120,16 +123,20 @@ export default class DocsCard extends Vue {
   box-sizing: border-box;
   background-color: #fff;
 
-  .jydocs_vip {
-    background: linear-gradient(98deg, #FFA674 0%, #F01212 100%);
-    width: 50px;
-    height: 18px;
-    border-radius: 4px;
-    display: inline-flex;
-    justify-content: center;
-    align-items: center;
-    color: #fff;
+  .type-tag {
+    padding: 4px 5px;
+    border-radius: 2px;
     font-size: 10px;
+    white-space: nowrap;
+
+    &.free {
+      background: linear-gradient(98deg, #FFA674 0%, #F01212 100%);
+      color: #fff;
+    }
+    &.boutique{
+      background: linear-gradient(270deg, #F1D090 0%, #FAE7CA 100%);
+      color: #C26F33;
+    }
   }
 
   &.oneline {
@@ -184,7 +191,11 @@ export default class DocsCard extends Vue {
 
     .subinfo-item {
       position: relative;
-      margin-right: 14px;
+      margin-right: 16px;
+
+      &.last {
+        margin-right: 8px;
+      }
 
       &.noline:after,
       &.last:after {

+ 2 - 2
jydocs-mobile/src/components/filters/index.vue

@@ -79,8 +79,8 @@ export default class extends Vue {
 
   typeList = [
     { label: '全部类型', value: 0 },
-    { label: '精品', value: 2 },
-    { label: '会员免费', value: 1 }
+    { label: '会员免费', value: 1 },
+    { label: '付费精品', value: 2 }
     // { label: '免费', value: 3 }
   ]
 

+ 4 - 1
jydocs-mobile/src/store/modules/main.ts

@@ -80,7 +80,8 @@ const modulesOption: modulesOption = {
     homePageData: recoveryPageData('jy-docs-home-page'),
     searchPageData: recoveryPageData('jy-docs-search-page'),
     userLib: recoveryPageData('jy-docs-user-lib'),
-    loginInfo: {}
+    loginInfo: {},
+    isLogin: false
   },
   mutations: {
     // 保存首页数据
@@ -94,7 +95,9 @@ const modulesOption: modulesOption = {
       state.loginInfo = data.data
       if (data.data.userId) {
         sessionStorage.setItem('jy-login-info', JSON.stringify(data.data))
+        state.isLogin = true
       } else {
+        state.isLogin = false
         sessionStorage.removeItem('jy-login-info')
       }
     },

+ 16 - 8
jydocs-mobile/src/views/Home.vue

@@ -100,7 +100,10 @@
                 <div class="mini-img-group">
                   <img :src="item.previewImgId || mr_image" alt="">
                   <van-icon :name="docTypeIcon(item.docFileType)" />
-                  <div class="vip-ic" v-if="item.productType === 1">会员免费</div>
+                  <span class="type-tag"
+                        :class="item.productType === 2 ? 'boutique' : 'free'">
+                    {{ item.productType === 2 ? '付费精品' : '会员免费' }}
+                  </span>
                 </div>
                 <div class="flex-c-c">
                   <div class="flex">
@@ -625,19 +628,24 @@ export default class extends Vue {
             height: 100%;
           }
 
-          .vip-ic {
+          .type-tag {
             position: absolute;
             left: 0;
             top: 0;
-            background: linear-gradient(98deg, #FFA674 0%, #F01212 100%);
-            width: 50px;
-            height: 18px;
-            border-radius: 4px 0px 4px 0px;
-            color: #fff;
+            border-radius: 4px 0 4px 0;
             font-size: 10px;
+            height: 18px;
             display: flex;
-            justify-content: center;
             align-items: center;
+            padding: 0 5px;
+            &.free {
+              background: linear-gradient(98deg, #FFA674 0%, #F01212 100%);
+              color: #fff;
+            }
+            &.boutique{
+              background: linear-gradient(270deg, #F1D090 0%, #FAE7CA 100%);
+              color: #C26F33;
+            }
           }
 
           i {

+ 1 - 1
jydocs-mobile/src/views/Search.vue

@@ -45,7 +45,7 @@
         class="more-list calc-height-1px" ref="vanList">
         <div>
           <Card v-for="(item, index) in listState.list" :key="index" :title="item.docName" :desc="item.docSummary"
-            :docType="item.docFileType" :isVip="item.productType === 1" :subInfo="calcSubInfo(item)"
+            :docType="item.docFileType" :productType="item.productType" :subInfo="calcSubInfo(item)"
             @onClick="toDocDetail(item)" />
         </div>
         <Empty v-if="listState.list.length === 0 && listState.loaded && !listState.loading" style="background: #fff;">

+ 260 - 28
jydocs-mobile/src/views/details/details.vue

@@ -4,7 +4,11 @@
       <div class="details-head">
         <div class="top-title-group flex-r-c">
           <van-icon :name="'diy-' + fileType(detailData.docFileType)"></van-icon>
-          <div class="flex">{{ detailData.docName }}</div>
+          <div class="flex">
+            <span class="docName">{{ detailData.docName}}</span>
+            <span class="type-tag"
+                  :class="detailData.productType === 2 ? 'boutique' : 'free'">{{ detailData.productType === 2 ? '付费精品' : '会员免费' }}</span>
+          </div>
         </div>
         <div class="details-tags">
           <div class="tag-item"><span>{{ detailData.viewTimes || 0 }}</span>次浏览</div>
@@ -13,12 +17,37 @@
           <div class="tag-item"><span>{{ dateFormatter(detailData.uploadDate, 'yyyy-MM-dd') }}</span>上传</div>
         </div>
       </div>
-      <div class="middles">
+      <div class="middles middles-summary" v-if=" buyed == 0 && detailData.source === 1 && !loginInfo">
         <h3>摘要</h3>
         <p>{{ detailData.docSummary }}</p>
         <div class="continue" v-show="buyed == 0">全文共{{ detailData.docPageSize }}页,<span @click="readAll">阅读全文<van-icon
               name="arrow-down" size="18" /></span></div>
       </div>
+
+      <div class="middles preview-page" v-if="buyed === 0 && (loginInfo || (!loginInfo && detailData.source === 2))">
+        <div>
+          <!--剑鱼文档全为PDF-->
+          <div class="pdf_" v-if="detailData.source === 1 && showfileType==='pdf'">
+            <pdf v-for="i in getPageNum" :key="i" :src="pdfPage.url" :page="i" @error="pdfError($event)"></pdf>
+          </div>
+          <div class="file-content file-word-docx" v-if="detailData.source !== 1">
+            <img v-for="(iUrl, ind) in previewConfig.docinImg" :key="'iUrl_' + ind" :src="iUrl" alt="预览" oncontextmenu="return false" >
+          </div>
+        </div>
+        <div
+            class="continue"
+            v-if="unreadPage > 0 && detailData.docPageSize > 1 && guideText"
+        >
+          <div class="unread-num">
+            <span class="line"></span>
+            剩余{{ unreadPage }}页未读
+            <span class="line"></span>
+          </div>
+         <div class="handle-span" @click="readAll">{{ guideText }}
+            <van-icon name="arrow-down" size="16" />
+         </div>
+        </div>
+      </div>
     </div>
     <van-sticky :offset-top="Offset" @scroll="stickyScroll" v-show="buyed == 1">
       <div class="head-tip" :class="{ 'is-fixed': fixed }">
@@ -29,10 +58,29 @@
         <!--              <span class="pages"><i id="page_num"></i> / <i>{{detailData.docPageSize}}</i></span>-->
       </div>
     </van-sticky>
-    <div class="botts" v-show="buyed == 1">
+<!--    已购买,但是加载失败-->
+    <div class="bottoms-preview" v-if="docLoadError && buyed === 1">
+      <div class="file-content">
+        <img v-for="(iUrl, ind) in previewConfig.docinImg"  :key="'iUrl_' + ind" :src="iUrl" alt="预览" oncontextmenu="return false">
+      </div>
+      <div
+          class="continue"
+          v-if="unreadPage > 0 && detailData.docPageSize > 1 && showfileType !== 'pdf'"
+      >
+        <div class="unread-num">
+          <span class="line"></span>
+          剩余{{ unreadPage }}页未读
+          <span class="line"></span>
+        </div>
+        <div class="handle-span" @click="readAll">{{ guideText }}
+          <van-icon name="arrow-down" size="16" />
+        </div>
+      </div>
+    </div>
+    <div class="botts" v-if="buyed == 1 && !docLoadError">
       <!-- showfileType -->
       <div class="pdf_" v-if="showfileType==='pdf'">
-        <pdf v-for="i in getPageNum" :key="i" :src="pdfPage.url" :page="i"></pdf>
+        <pdf v-for="i in getPageNum" :key="i" :src="pdfPage.url" :page="i" @error="pdfError($event)"></pdf>
       </div>
       <div class="doc_" v-if="showfileType==='docx'">
         <vue-office-docx
@@ -229,7 +277,7 @@
 
 <script lang="ts">
 import { Component, Vue } from 'vue-property-decorator'
-import { mapActions, mapMutations } from 'vuex'
+import { mapActions, mapMutations, mapState } from 'vuex'
 import { Icon, Toast, GoodsAction, GoodsActionIcon, GoodsActionButton, Sticky } from 'vant'
 import Recharge from '@/components/Recharge.vue'
 import sharePop from '@/components/SharePopup.vue'
@@ -250,6 +298,15 @@ import '@vue-office/docx/lib/index.css'
 import VueOfficeExcel from '@vue-office/excel'
 // 引入相关样式
 import '@vue-office/excel/lib/index.css'
+
+const config = {
+  PAGE_TO_VIEW: 0,
+  SCALE: 1.0,
+  CMAP_URL: 'https://cdn-common.jianyu360.com/cdn/lib/pdfjs-dist/2.1.266/cmaps/',
+  CMAP_PACKED: true,
+  workerSrc: 'https://cdn-common.jianyu360.com/cdn/lib/pdfjs-dist/2.1.266/build/pdf.worker.min.js'
+}
+
 @Component({
   name: 'details-p',
   mixins: [MixinTop],
@@ -267,6 +324,11 @@ import '@vue-office/excel/lib/index.css'
     VueOfficeDocx,
     VueOfficeExcel
   },
+  computed: {
+    ...mapState('main', {
+      loginInfo: (state: any) => state.isLogin
+    })
+  },
   methods: {
     dateFormatter,
     ...mapActions({
@@ -291,7 +353,7 @@ export default class extends Vue {
   getDown: any
   getShow: any
   getShare: any
-  loginInfo: any = sessionStorage.getItem('jy-login-info')
+  loginInfo: any
   links = ''
   docIds = ''
   fixed = false
@@ -328,7 +390,8 @@ export default class extends Vue {
   }
 
   TopConfig: any = {
-    actionRightText: this.loginInfo ? '<div style="display:flex;flex-direction: column;align-items: center;"><i class="j-icon icon-iconJianYu"></i><p style="color: #171826;font-size: 10px;line-height: 12px;margin-top:3px;">分享赚剑鱼币</p></div>' : '',
+    actionRightText: '',
+    // actionRightText: this.loginInfo ? '<div style="display:flex;flex-direction: column;align-items: center;"><i class="j-icon icon-iconJianYu"></i><p style="color: #171826;font-size: 10px;line-height: 12px;margin-top:3px;">分享赚剑鱼币</p></div>' : '',
     actionRightCallback: this.shared,
     actionRightStyle: {
       color: '#5F5E64',
@@ -340,7 +403,19 @@ export default class extends Vue {
   showPageNum = 2
   showPageNumT: any = ''
 
+  // 预览配置
+  previewConfig: any = {
+    pageNums: 1,
+    docinImg: []
+  }
+
+  // 文档加载失败
+  docLoadError = false
+
   created () {
+    if (this.loginInfo) {
+      this.TopConfig.actionRightText = '<div style="display:flex;flex-direction: column;align-items: center;"><i class="j-icon icon-iconJianYu"></i><p style="color: #171826;font-size: 10px;line-height: 12px;margin-top:3px;">分享赚剑鱼币</p></div>'
+    }
     this.docIds = this.$route.params.id
     this.getPower()
     this.onList()
@@ -395,6 +470,46 @@ export default class extends Vue {
     }
   }
 
+  get guideText () {
+    // P620需求:1、未购买预览时,引流文案
+    // 或者,购买豆丁文件加载时错误后,最多预览5页,最后的引流文案
+    // 未登录
+    if (!this.loginInfo) {
+      // 精品
+      if (this.detailData.productType === 2) {
+        return `开通文库会员${this.detailData.docMemberDiscount}折下载文档阅读全文`
+      } else {
+        // 会员免费文档
+        return '开通文库会员免费阅读全文'
+      }
+    }
+    if (this.docLoadError) {
+      return '下载文档阅读全文'
+    }
+    let btnText = '下载文档阅读全文'
+    if (this.isvipFree && this.buyed === 0 && this.isviper) { // 会员免费 未下载 会员
+      btnText = '下载文档阅读全文'
+    } else if ((this.power.freeDownload === 2 || this.power.freeDownload === 0) && this.isvipFree && this.buyed === 0 && !this.isviper) {
+      btnText = '使用免费下载特权阅读全文'
+    } else if (this.isvipFree && this.buyed === 0 && !this.isviper && this.power.freeDownload === 1) { // 会员免费 未下载 不是会员 使用过免费下载次数
+      btnText = '开通文库会员免费阅读全文'
+    } else if (this.boutique && this.buyed === 0 && this.isviper) {
+      btnText = '下载文档阅读全文'
+    } else if (this.boutique && this.buyed === 0 && !this.isviper) {
+      btnText = `开通文库会员${this.detailData.docMemberDiscount}折下载文档阅读全文`
+    } else if (this.buyed === 1 && this.showfileType !== 'pdf') {
+      btnText = '下载文档阅读全文'
+    } if (this.buyed === 1 && this.showfileType === 'pdf') {
+      btnText = ''
+    }
+    return btnText
+  }
+
+  // 未购买预览时,未读页码; 或者豆丁渲染错误,
+  get unreadPage () {
+    return this.detailData.docPageSize - this.previewConfig.pageNums
+  }
+
   rendered (res: any) {
     console.log('完成', res)
   }
@@ -419,7 +534,11 @@ export default class extends Vue {
     }
   }
 
-  errorHandler () { console.log('失败') }
+  errorHandler () {
+    console.log('失败')
+    this.ddErrorPreview()
+  }
+
   popBtn (obj: any) {
     switch (obj.btn) {
       case '立即充值': {
@@ -435,7 +554,6 @@ export default class extends Vue {
         break
     }
     (this.$refs[obj.type] as any).value = false
-    console.log(obj)
   }
 
   async bottomBtn (type: string) {
@@ -512,17 +630,26 @@ export default class extends Vue {
     }
   }
 
-  getNumPages (url: string) {
+  getNumPages (url: string, type: any) {
     try {
-      const loadingTask = pdf.createLoadingTask(url)
+      console.log(77777777)
+      const loadingTask = pdf.createLoadingTask({
+        url,
+        cMapUrl: config.CMAP_URL,
+        cMapPacked: config.CMAP_PACKED
+      })
+      console.log(loadingTask)
       loadingTask.promise.then((pdf: any) => {
+        const nums = type === 'preview' ? this.previewConfig.pageNums : pdf.numPages
         this.pdfPage.url = loadingTask
-        this.pdfPage.pageNum = pdf.numPages
+        this.pdfPage.pageNum = nums
       }).catch((err: any) => {
+        this.ddErrorPreview()
         console.error('pdf加载失败', err)
       })
     } catch (e: any) {
-
+      console.log(4444444444)
+      console.log(e)
     }
   }
 
@@ -587,12 +714,15 @@ export default class extends Vue {
     }
   }
 
-  buyShow () {
+  buyShow (type: any) {
     this.getShow({ docId: this.docIds }).then((res: any) => {
-      if (res.data.includes('.pdf') || this.detailData.docFileType === 2) {
-        this.getNumPages(res.data)
-      }
       this.buyShowUrl = res.data
+      if (res.data.includes('.pdf') || this.detailData.docFileType === 2 || !this.showfileType) {
+        this.getNumPages(res.data, type)
+      } else if (res.data.indexOf('.pdf') < 0) {
+        // 非PDF全部处理成图片预览
+        this.ddErrorPreview()
+      }
     })
   }
 
@@ -604,7 +734,10 @@ export default class extends Vue {
       this.buyed = res.data.status
       this.downloadStatus = res.data.downloadStatus
       if (res.data.status === 1) {
-        this.buyShow()
+        this.buyShow('all')
+      } else {
+        // 处理预览展示
+        this.disposePreviewContent()
       }
       this.collectd = res.data.collect
       this.getShareUrl()
@@ -615,6 +748,43 @@ export default class extends Vue {
     })
   }
 
+  // 处理预览展示
+  disposePreviewContent () {
+    this.previewConfig.docinImg = []
+    // P620需求 总页数≥3页:最多预览2页;总页数≤2页:最多预览1页。
+    // 预览页数
+    this.previewConfig.pageNums = this.detailData.docPageSize >= 3 ? 2 : 1
+    // 豆丁预览图片
+    // source 2豆丁 1 剑鱼
+    if (this.detailData.source === 2) {
+      for (let i = 1; i <= this.previewConfig.pageNums; i++) {
+        const ddUrl = `https://docimg1.docin.com/docinviewpic.jsp?file=${this.detailData.imgId}&width=800&pageno=${i}&sview=1&clogo=1`
+        this.previewConfig.docinImg.push(ddUrl)
+      }
+    } else {
+      // 剑鱼文档,返回的格式全部为pdf
+      this.buyShow('preview')
+    }
+  }
+
+  pdfError () {
+    console.log('---pdf渲染失败--')
+    if (this.detailData.source === 2) {
+      this.ddErrorPreview()
+    }
+  }
+
+  // 豆丁预览(如果购买后的全文加载失败,则走预览逻辑,PDF)
+  ddErrorPreview () {
+    this.docLoadError = true
+    this.previewConfig.docinImg = []
+    this.previewConfig.pageNums = this.detailData.docPageSize >= 5 ? 5 : this.detailData.docPageSize
+    for (let i = 1; i <= this.previewConfig.pageNums; i++) {
+      const ddUrl = `https://docimg1.docin.com/docinviewpic.jsp?file=${this.detailData.imgId}&width=800&pageno=${i}&sview=1&clogo=1`
+      this.previewConfig.docinImg.push(ddUrl)
+    }
+  }
+
   jubaod () {
     Toast({
       duration: 3500,
@@ -791,10 +961,30 @@ export default class extends Vue {
     line-height: 24px;
     letter-spacing: 0px;
     text-align: left;
-
     .van-icon {
       margin-right: 8px;
     }
+    .docName {
+      margin-right:5px;
+    }
+    .type-tag {
+      box-sizing: border-box;
+      border-radius: 2px;
+      font-size: 10px;
+      white-space: nowrap;
+      padding: 4px 5px;
+      margin-bottom: 2px;
+      vertical-align: middle;
+
+      &.free {
+        background: linear-gradient(98deg, #FFA674 0%, #F01212 100%);
+        color: #fff;
+      }
+      &.boutique{
+        background: linear-gradient(270deg, #F1D090 0%, #FAE7CA 100%);
+        color: #C26F33;
+      }
+    }
   }
 
   .details-tags {
@@ -857,12 +1047,19 @@ export default class extends Vue {
     }
   }
 
-  .middles {
-    padding: 16px 8px;
+  .middles, .bottoms-preview {
+    position: relative;
+    padding: 16px 0;
     background: #fff;
     margin: 8px;
     border-radius: 12px;
 
+    .file-content {
+      img:not(:first-of-type){
+        border-top: 3px solid #f2f2f2;
+      }
+    }
+
     h3 {
       font-size: 16px;
       line-height: 24px;
@@ -878,15 +1075,35 @@ export default class extends Vue {
     }
 
     .continue {
-      color: #5F5E64;
-      font-size: 14px;
-      line-height: 20px;
+      width: 100%;
+      position: absolute;
+      box-sizing: border-box;
+      color: #1B1A2A;
+      font-size: 12px;
+      line-height: 18px;
       text-align: center;
-      margin-top: 32px;
+      height: 360px;
+      padding-top:306px;
+      bottom: 0;
+      background: linear-gradient(180deg, rgba(255, 255, 255, 0) 0%, #fff 75%);
+      border-radius:  0 0 12px 12px;
+
+      .unread-num {
+       .line{
+          display: inline-block;
+          width: 20px;
+          height: 1px;
+          background: #1B1A2A;
+         margin-bottom: 4px;
+        }
+      }
 
-      span {
-        display: inline-flex;
+      .handle-span {
+        padding: 8px 0;
+        font-size:14px;
+        display: flex;
         align-items: center;
+        justify-content: center;
         color: #2ABED1;
         cursor: pointer;
 
@@ -896,6 +1113,15 @@ export default class extends Vue {
       }
     }
   }
+  .middles.middles-summary {
+    padding: 16px 8px;
+    .continue {
+      position: unset;
+      height:unset;
+      margin-top: 32px;
+      padding-top: 0;
+    }
+  }
 
   .head-tip {
     width: auto;
@@ -944,6 +1170,13 @@ export default class extends Vue {
       }
     }
   }
+  ::v-deep {
+    .pdf_ {
+      & > span:not(:first-of-type){
+        border-top: 3px solid #f2f2f2;
+      }
+    }
+  }
 
   .is-fixed {
     height: 40px;
@@ -1063,7 +1296,6 @@ export default class extends Vue {
       width: 165px;
       height: 40px;
     }
-
     ::v-deep .van-button--default {
       background-color: #2ABED1;
 

+ 1 - 1
jydocs-mobile/src/views/user/Library.vue

@@ -57,7 +57,7 @@
           :offset="myCollectionListState.offset" @load="onLoad" class="more-list" ref="vanList">
           <div>
             <Card v-for="(item, index) in myCollectionListState.list" :key="index" :title="item.DocName"
-              :desc="item.DocSummary" :docType="item.DocFileType" :isVip="item.productType === 1"
+              :desc="item.DocSummary" :docType="item.DocFileType" :productType="item.productType"
               :subInfo="calcSubInfoForColl(item)" @onClick="toDocDetail(item)">
             </Card>
           </div>

+ 2 - 2
jydocs-pc/public/index.html

@@ -18,8 +18,8 @@
       <script src="https://jybx3-webtest.jydev.jianyu360.com/js/jquery-3.2.1.min.js?v=6302"></script>
       <script src="https://jybx3-webtest.jydev.jianyu360.com/js/jquery.cookie.js"></script>
       <script src="https://jybx3-webtest.jydev.jianyu360.com/js/bootstrap.min.js"></script>
-      <script src="https://cdn.jsdelivr.net/npm/pdfjs-dist@2.1.266/build/pdf.min.js"></script>
-      <script src="https://cdn.jsdelivr.net/npm/pdfjs-dist@2.1.266/web/pdf_viewer.js"></script>
+      <script src="https://cdn-common.jianyu360.com/cdn/lib/pdfjs-dist/2.1.266/build/pdf.min.js"></script>
+      <script src="https://cdn-common.jianyu360.com/cdn/lib/pdfjs-dist/2.1.266/web/pdf_viewer.js"></script>
       <!-- <script src="https://cdn-common.jianyu360.com/cdn/lib/vue/2.6.11/vue.min.js"></script>
       <script src="https://jybx3-webtest.jydev.jianyu360.com/common-module/pc-dialog/js/pc-collect-user-info.min.js"></script>
       <link href='https://jybx3-webtest.jydev.jianyu360.com/common-module/pc-dialog/css/collect-user-info.css' rel="stylesheet" type="text/css"/> -->

+ 12 - 0
jydocs-pc/src/App.vue

@@ -63,6 +63,7 @@ export default {
     background-color: #fff;
   }
 }
+<<<<<<< HEAD
 .in-app{
   width: 100%;
   min-width: 1012px;
@@ -71,5 +72,16 @@ export default {
         min-width: auto!important;
       }
 
+=======
+::-webkit-scrollbar {
+  /*滚动条整体样式*/
+  width: 8px;
+}
+
+::-webkit-scrollbar-thumb {
+  /*滚动条里面小方块*/
+  border-radius: 3px;
+  background-color: #e0e0e0;
+>>>>>>> master
 }
 </style>

+ 12 - 6
jydocs-pc/src/components/doc-item-card/Card.vue

@@ -56,7 +56,7 @@
             v-for="(item, index) in subInfo"
             :key="index"
           >{{ item }}</span>
-          <span class="vip_mark" v-if="productType === 1">会员免费</span>
+          <span class="type-tag" v-if="productType" :class="productType === 2 ? 'boutique' : 'free'">{{productType === 2 ? '付费精品' : '会员免费' }}</span>
         </div>
         <div class="c-f-right flex-r-c">
           <slot name="price">
@@ -227,13 +227,19 @@ export default {
         background-color: rgba($color: #000, $alpha: 0.05);
       }
     }
-    .vip_mark{
-      padding: 1px 8px;
-      background: linear-gradient(to right, #FFA674 0%,#F01212 100%);
-      color: #fff;
+    .type-tag {
+      padding: 1px 8px 1px 8px;
       font-size: 12px;
-      border-radius: 4px;
       line-height: 18px;
+      border-radius: 4px;
+      &.free {
+        background: linear-gradient(98deg, #FFA674 0%, #F01212 100%);
+        color: #fff;
+      }
+      &.boutique{
+        background: linear-gradient(270deg, #F1D090 0%, #FAE7CA 100%);
+        color: #B1700E;
+      }
     }
   }
 

+ 262 - 59
jydocs-pc/src/views/Content.vue

@@ -1,7 +1,7 @@
 <template>
-  <div class="detail-main" v-loading="loading">
+  <div class="detail-main">
     <div class="c-details">
-      <div class="d-left">
+      <div class="d-left"  v-loading="loading">
         <div class="tops">
           <h1>
             <div>
@@ -12,6 +12,7 @@
           <div class="cd-tips">
             <ul>
               <li class="li-tags" v-for="item in getContentTags" :key="item">{{ item }}</li>
+              <li class="type-tag" :class="datas.productType === 2 ? 'boutique' : 'free'">{{ datas.productType === 2 ? '付费精品' : '会员免费' }}</li>
               <li>{{ datas.viewTimes || 0 }}次浏览<el-divider direction="vertical"></el-divider></li>
               <li>{{ datas.downTimes || 0 }}次下载<el-divider direction="vertical"></el-divider></li>
               <li>共{{ datas.docPageSize }}页<el-divider direction="vertical"></el-divider></li>
@@ -22,27 +23,56 @@
           </div>
           <el-divider class="heng-line" v-if="lineShow"></el-divider>
         </div>
-        <div class="middles" :class="{ 'actives': buyed == 0}">
+        <div class="middles middles-summary" :class="{ 'actives': buyed == 0}" v-if=" buyed == 0 && datas.source === 1 && !islogin">
           <h3>摘要</h3>
           <p>{{ datas.docSummary }}</p>
-          <div class="continue" v-show="buyed == 0">全文共{{ datas.docPageSize }}页,<span @click="continued">阅读全文<i
-                class="el-icon-arrow-down"></i></span></div>
+          <div class="continue" v-if="buyed == 0">全文共{{ datas.docPageSize }}页,<span @click="continued">阅读全文<i
+              class="el-icon-arrow-down"></i></span></div>
         </div>
-        <div class="head-tip" id="fixedTop" :class="{ 'is-fixed': fixed }">
+        <div class="middles preview-page" v-if="buyed === 0 && (islogin || (!islogin && datas.source === 2))">
+          <div class="preview-content">
+            <!--剑鱼文档全为PDF-->
+            <div v-if="datas.source === 1 ">
+              <div class="cont-p"  id="previewPdfPage"></div>
+            </div>
+            <div class="file-content file-word-docx" v-else>
+              <img v-for="(iUrl, ind) in previewConfig.docinImg" :key="'iUrl_' + ind" :src="iUrl" alt="预览" oncontextmenu="return false">
+            </div>
+          </div>
+          <div class="continue" v-if="unreadPage > 0 && datas.docPageSize > 1 && guideText">
+            剩余{{ unreadPage }}页未读,<span @click="continued">{{ guideText }}
+            <i class="el-icon-arrow-down"></i></span>
+          </div>
+        </div>
+        <div class="head-tip" id="fixedTop" :class="{ 'is-fixed': fixed }" v-if="!docLoadError">
           <h3 v-show="fixed">
             <i :class="'el-icon-jy-' + fileType(datas.docFileType)"></i>
             <span>{{ datas.docName }}</span>
           </h3>
           <span v-if="page_count" class="pages"><i>{{ page_num }}</i> / <i>{{ page_count }}</i></span>
         </div>
+<!--        豆丁的文档渲染错误后,需要处理成最多预览5页图片-->
+        <div class="bottoms-preview" v-if="docLoadError && buyed === 1">
+          <div class="preview-content">
+            <!--剑鱼文档全为PDF-->
+            <div class="file-content">
+              <img v-for="(iUrl, ind) in previewConfig.docinImg" :key="'iUrl_' + ind" :src="iUrl" alt="预览" oncontextmenu="return false" >
+            </div>
+            <div class="continue" v-if="unreadPage > 0 && datas.docPageSize > 1 && guideText">
+              剩余{{ unreadPage }}页未读,<span @click="continued">{{ guideText }}
+            <i class="el-icon-arrow-down"></i></span>
+            </div>
+          </div>
+        </div>
         <div class="bottoms" id="colWidth">
-          <div class="page">
+          <div class="page" v-show="!docLoadError">
             <div class="cont-p" v-show="fileTypeThis !== 'docx' && fileTypeThis !== 'xlsx'" id="pdfPage"></div>
             <div class="file-content file-word-docx" id="docxPage" v-if="fileTypeThis === 'docx'">
               <vue-office-docx
                   :src="fileSrc.docSrc"
                   style="margin-bottom: 24px; height: 100vh;"
                   @rendered="rendered"
+                  @error="errorHandler()"
               />
             </div>
             <div class="file-content file-word-docx" id="xlsxPage" v-if="fileTypeThis === 'xlsx' || fileTypeThis === 'xls'">
@@ -96,7 +126,7 @@
                     <span>{{ datas.price }}</span>
                     <span>原价下载</span>
                   </el-button>
-                  <el-button class="prime-cost" @click="downLoadFreeEvent" v-if="islogin && buyed !== 1 && !docsInfo.docStatus && docsInfo.freeDownload !== 1">
+                  <el-button class="prime-cost" @click="downLoadFreeEvent" v-if="islogin && buyed !== 1 && !isDocVip && docsInfo.freeDownload !== 1">
                     <span>使用免费下载特权</span>
                     <span>(1次机会)</span>
                   </el-button>
@@ -107,7 +137,7 @@
                 </div>
                 <!-- 精品文档 -->
                 <div class="file-action-content member-pay" v-else>
-                  <el-button class="prime-cost origin-cost" type="primary" @click="primeLoadFile" v-if="!docsInfo.docStatus && buyed === 0">
+                  <el-button class="prime-cost origin-cost" type="primary" @click="primeLoadFile" v-if="!isDocVip && buyed === 0">
                     <i class="el-icon-jy-iconJianYu"></i>
                     <span>{{ datas.price }}</span>
                     <span>原价下载</span>
@@ -212,9 +242,9 @@ export default {
       config: {
         PAGE_TO_VIEW: 0,
         SCALE: 1.0,
-        CMAP_URL: 'https://cdn.jsdelivr.net/npm/pdfjs-dist@2.1.266/cmaps/',
+        CMAP_URL: 'https://cdn-common.jianyu360.com/cdn/lib/pdfjs-dist/2.1.266/cmaps/',
         CMAP_PACKED: true,
-        workerSrc: 'https://cdn.jsdelivr.net/npm/pdfjs-dist@2.1.266/build/pdf.worker.min.js'
+        workerSrc: 'https://cdn-common.jianyu360.com/cdn/lib/pdfjs-dist/2.1.266/build/pdf.worker.min.js'
       },
       pData: {
         heightList: []
@@ -245,7 +275,13 @@ export default {
       fileTypeThis: '', // 当前文件类型
       excelOptions: {
         xls: false
-      }
+      },
+      previewConfig: {
+        pageNums: 1,
+        docinImg: []
+      },
+      // 文档加载失败
+      docLoadError: false
     }
   },
   created () {
@@ -284,8 +320,52 @@ export default {
       const nArr = arr.concat(oldArr)
       return nArr.splice(0, 3)
     },
+    isDocVip () {
+      return this.docsInfo.docStatus > 0
+    },
     showCostBtn () {
-      return (this.buyed !== 1 && !this.docsInfo.docStatus && this.docsInfo.freeDownload === 1 && this.downloadStatus !== 1) || !this.islogin
+      return (this.buyed !== 1 && !this.isDocVip && this.docsInfo.freeDownload === 1 && this.downloadStatus !== 1) || !this.islogin
+    },
+    // 未购买预览时,未读页码; 或者豆丁渲染错误,
+    unreadPage () {
+      return this.datas.docPageSize - this.previewConfig.pageNums
+    },
+    // P620需求:1、未购买预览时,引流文案
+    // 或者,购买豆丁文件加载时错误后,最多预览5页,最后的引流文案
+    guideText () {
+      // 未登录
+      if (!this.islogin) {
+        // 精品
+        if (this.datas.productType === 2) {
+          return `开通文库会员${this.datas.docMemberDiscount}折下载文档阅读全文`
+        } else {
+        // 会员免费文档
+          return '开通文库会员免费阅读全文'
+        }
+      }
+      // 预览加载错误直接展示该文案
+      if (this.docLoadError) {
+        return '下载文档阅读全文'
+      }
+      let btnText = '下载文档阅读全文'
+      // 会员
+      if (this.docsInfo?.docStatus > 0 || (this.buyed === 1 && this.datas.source === 2 && this.datas.docFileType !== 2)) {
+        btnText = '下载文档阅读全文'
+      } else if (this.docsInfo?.docStatus <= 0 && this.buyed === 0) {
+        if (this.datas.productType === 2) {
+          btnText = `开通文库会员${this.datas.docMemberDiscount}折下载文档阅读全文`
+        } else {
+          btnText = '开通文库会员免费阅读全文'
+        }
+      }
+      // 会员免费文档+未下载+不是会员+未使用1次免费下载特权
+      if (this.islogin && this.datas.productType === 1 && this.buyed === 0 && !this.isDocVip && this.docsInfo.freeDownload !== 1) {
+        btnText = '使用免费下载特权阅读全文'
+      }
+      if (this.buyed === 1 && this.datas.docFileType === 2) {
+        btnText = ''
+      }
+      return btnText
     }
   },
   watch: {
@@ -314,10 +394,11 @@ export default {
   },
   methods: {
     rendered () {
-      console.log("渲染完成")
+      console.log('渲染完成')
     },
     errorHandler () {
-      console.log("渲染失败")
+      this.ddNotPdfPreview()
+      console.log('渲染失败')
     },
     // 使用免费下载特权
     downLoadFreeEvent () {
@@ -374,7 +455,7 @@ export default {
         this.btnName = '下载文档'
       } else {
         if (this.datas.productType === 2) {
-          this.btnName = `开通文库会员${this.datas.docMemberDiscount}折下载`
+          this.btnName = `开通文库会员,享${this.datas.docMemberDiscount}折下载`
         } else {
           this.btnName = '开通文库会员免费下载'
         }
@@ -401,8 +482,12 @@ export default {
       this.$nextTick(() => {
         // 获取到达页面顶端的值
         const heights = document.getElementById('fixedTop')
-        // this.offsetTop = heights.offsetTop
-        this.offsetTop = heights.getBoundingClientRect().top
+        this.offsetTop = heights ? heights.getBoundingClientRect().top : 0
+        const headerNav = document.getElementById('public-nav')
+        if (headerNav && heights) {
+          const headerTop = headerNav.offsetHeight
+          heights.style.top = headerTop + 'px'
+        }
       })
     },
     initHeight () {
@@ -411,15 +496,16 @@ export default {
       this.fixed = !!(scrollTop > this.offsetTop && this.buyed)
       this.watchPage()
       let t = document.getElementById('pdfPage')
-      if (this.fileTypeThis === 'docx') {
-        t = document.getElementById('docxPage')
-      } else if (this.fileTypeThis === 'xlsx' || this.fileTypeThis === 'xls') {
-        t = document.getElementById('xlsxPage')
+      if (this.fileTypeThis !== 'pdf' && this.buyed) {
+        t = document.getElementsByClassName('bottoms-preview')[0]
+      }
+      if (!this.buyed) {
+        t = document.getElementsByClassName('preview-page')[0]
       }
       const targetElement = this.$refs.transitionDom
       const rect = targetElement.getBoundingClientRect()
       const innerHeight = window.innerHeight
-      const b = t.getBoundingClientRect().bottom
+      const b = t?.getBoundingClientRect().bottom || 0
       const dom = document.getElementById('footp')
       if (b < 500 || rect.top < innerHeight) {
         dom.style.position = 'unset'
@@ -441,8 +527,11 @@ export default {
         }
       }
     },
-    renders () {
-      const container = document.getElementById('pdfPage')
+    renders (type) {
+      let container = document.getElementById('pdfPage')
+      if (type === 'preview') {
+        container = document.getElementById('previewPdfPage')
+      }
       return this.pdfDocument.getPage(this.config.PAGE_TO_VIEW).then((pdfPage) => {
         var pdfPageView = new pdfjsViewer.PDFPageView({
           container: container,
@@ -457,7 +546,7 @@ export default {
         return pdfPageView.draw()
       })
     },
-    init () {
+    init (type) {
       pdfjsLib.GlobalWorkerOptions.workerSrc = this.config.workerSrc
       const loadingTask = pdfjsLib.getDocument({
         url: this.conts.data,
@@ -468,9 +557,19 @@ export default {
         this.pdfDocument = pdfDocument
         this.updateText({ type: 'count', value: this.pdfDocument.numPages })
         this.updateText({ type: 'num', value: 1 })
-        for (let i = 0; i < this.pdfDocument.numPages; i++) {
+        const numPages = type === 'preview' ? this.previewConfig.pageNums : this.pdfDocument.numPages
+        for (let i = 0; i < numPages; i++) {
           this.config.PAGE_TO_VIEW++
-          this.renders()
+          this.renders(type)
+        }
+        this.loading = false
+      }).catch((e) => {
+        console.log('-------加载错误了------')
+        console.warn(e)
+        this.loading = false
+        // 文档加载失败
+        if (this.datas.source === 2) {
+          this.ddNotPdfPreview()
         }
       })
     },
@@ -485,7 +584,8 @@ export default {
         }
       }
     },
-    buyShow () {
+    buyShow (type) {
+      this.loading = true
       getShow({ docId: this.docIds }).then(res => {
         if (res.data.error_code === 0) {
           this.conts = res.data
@@ -496,28 +596,39 @@ export default {
               FileIndex = index
             }
           })
+
           this.fileTypeThis = fileExtensions[FileIndex]
-          switch (fileExtensions[FileIndex]) {
-            case 'docx':
-              this.fileSrc.docSrc = res.data.data
-              break
-            case 'xlsx':
-              this.excelOptions.xls = false
-              this.fileSrc.excelSrc = res.data.data
-              break
-            case 'xls':
-              this.excelOptions.xls = true
-              this.fileSrc.excelSrc = res.data.data
-            default:
-              this.init()
-              break
+          // switch (fileExtensions[FileIndex]) {
+          //   case 'docx':
+          //     this.fileSrc.docSrc = res.data.data
+          //     break
+          //   case 'xlsx':
+          //     this.excelOptions.xls = false
+          //     this.fileSrc.excelSrc = res.data.data
+          //     break
+          //   case 'xls':
+          //     this.excelOptions.xls = true
+          //     this.fileSrc.excelSrc = res.data.data
+          //   default:
+          //     this.init(type)
+          //     break
+          // }
+          // P620购买后,由于excel以及word用插件加载会出现压缩的情况,所以直接用预览最多5张展示处理
+          if (fileExtensions[FileIndex] === 'pdf') {
+            this.init(type)
+          } else {
+            this.loading = false
+            this.ddNotPdfPreview()
           }
         } else {
+          this.loading = false
           Message({
             message: res.data.error_msg,
             type: 'warning'
           })
         }
+      }).catch(() => {
+        this.loading = false
       })
     },
     coined () {
@@ -584,6 +695,8 @@ export default {
             document.getElementById('footp').style.bottom = '0'
           } else {
             document.getElementById('fixedTop').style.display = 'none'
+            // 处理预览展示
+            this.disposePreviewContent(this.datas)
           }
           this.getDocInfo()
           this.coined()
@@ -595,7 +708,7 @@ export default {
           // 监听滚轮
           setTimeout(() => {
             this.initHeight()
-          }, 500);
+          }, 500)
         } else {
           Message({
             message: res.error_msg,
@@ -604,6 +717,41 @@ export default {
         }
       })
     },
+    // 处理预览展示
+    disposePreviewContent (details) {
+      this.previewConfig.docinImg = []
+      // P620需求 总页数≥3页:最多预览2页;总页数≤2页:最多预览1页。
+      // 预览页数
+      this.previewConfig.pageNums = details.docPageSize >= 3 ? 2 : 1
+      // 豆丁预览图片
+      // source 2豆丁 1 剑鱼
+      if (details.source === 2) {
+        for (let i = 1; i <= this.previewConfig.pageNums; i++) {
+          const ddUrl = `https://docimg1.docin.com/docinviewpic.jsp?file=${details.imgId}&width=920&pageno=${i}&sview=1&clogo=1`
+          this.previewConfig.docinImg.push(ddUrl)
+        }
+      } else {
+        // 剑鱼文档,返回的格式全部为pdf
+        if (this.islogin) {
+          this.buyShow('preview')
+        }
+      }
+    },
+    // 豆丁预览(如果购买后的全文加载失败,则走预览逻辑)、非pdf得也走预览逻辑
+    ddNotPdfPreview () {
+      this.docLoadError = true
+      this.fixed = true
+      this.previewConfig.docinImg = []
+      this.previewConfig.pageNums = this.datas.docPageSize >= 5 ? 5 : this.datas.docPageSize
+      for (let i = 1; i <= this.previewConfig.pageNums; i++) {
+        const ddUrl = `https://docimg1.docin.com/docinviewpic.jsp?file=${this.datas.imgId}&width=920&pageno=${i}&sview=1&clogo=1`
+        this.previewConfig.docinImg.push(ddUrl)
+      }
+      // 监听滚轮
+      setTimeout(() => {
+        this.initHeight()
+      }, 1000)
+    },
     adverse () {
       // 获取广告信息
       getJyAdListApi({ codes: ['jydoc-content-right', 'jy-pc-docmember-detail'] }).then(res => {
@@ -617,7 +765,7 @@ export default {
     shoucang () {
       if (!this.islogin) {
         try {
-          window.openLoginDig()
+          window.openLoginDig(false, 'reload')
         } catch (e) {
           console.log(e)
         }
@@ -648,13 +796,13 @@ export default {
     continued () {
       if (!this.islogin) {
         try {
-          window.openLoginDig()
+          window.openLoginDig(false, 'reload')
         } catch (e) {
           console.log(e)
         }
         return
       }
-      if (this.buyed !== 1 && !this.docsInfo.docStatus && this.docsInfo.freeDownload !== 1 && this.datas.productType === 1) {
+      if (this.buyed !== 1 && !this.isDocVip && this.docsInfo.freeDownload !== 1 && this.datas.productType === 1) {
         this.downLoadFreeEvent()
       } else {
         this.loadFile()
@@ -663,7 +811,7 @@ export default {
     loadFile () {
       if (!this.islogin) {
         try {
-          window.openLoginDig()
+          window.openLoginDig(false, 'reload')
         } catch (e) {
           console.log(e)
         }
@@ -743,7 +891,7 @@ export default {
     primeLoadFile () {
       if (!this.islogin) {
         try {
-          window.openLoginDig()
+          window.openLoginDig(false, 'reload')
         } catch (e) {
           console.log(e)
         }
@@ -790,7 +938,7 @@ export default {
 }
 .cont-p {
   .page, .canvasWrapper, canvas {
-    width: 100%!important;
+    max-width: 100% !important;
     height: auto;
   }
 }
@@ -881,7 +1029,22 @@ export default {
             border-right: none !important;
           }
         }
-
+        .type-tag {
+          padding: 1px 8px 1px 8px;
+          font-size: 12px;
+          line-height: 18px;
+          text-align: center;
+          margin-right: 8px;
+          border-radius: 4px;
+          &.free {
+            background: linear-gradient(98deg, #FFA674 0%, #F01212 100%);
+            color: #fff;
+          }
+          &.boutique{
+            background: linear-gradient(270deg, #F1D090 0%, #FAE7CA 100%);
+            color: #B1700E;
+          }
+        }
         .coin {
           display: flex;
           align-items: center;
@@ -1022,11 +1185,12 @@ export default {
       }
     }
 
-    .middles {
-      padding: 24px 40px;
+    .middles, .bottoms-preview {
+      padding: 24px 0;
       background: #fff;
       border-radius: 4px;
       margin: 16px 0;
+      position: relative;
 
       h3 {
         font-size: 18px;
@@ -1043,11 +1207,19 @@ export default {
       }
 
       .continue {
+        position: absolute;
+        width: 100%;
+        height: 400px;
         color: #686868;
         font-size: 16px;
         line-height: 24px;
-        text-align: center;
-        margin-top: 36px;
+        display: flex;
+        align-items: flex-end;
+        justify-content: center;
+        padding-bottom: 27px;
+        background: linear-gradient(180deg, rgba(255, 255, 255, 0) 0%, #fff 75%);
+        bottom: 24px;
+        left:0;
 
         span {
           color: #2CB7CA;
@@ -1059,7 +1231,15 @@ export default {
         }
       }
     }
-
+    .middles.middles-summary{
+      padding: 24px 40px;
+      .continue {
+        position: unset;
+        height: unset;
+        color: #686868;
+        margin-top: 36px;
+      }
+    }
     .actives {
       // height: 656px;
       padding: 24px 40px 48px;
@@ -1121,10 +1301,15 @@ export default {
       top: 0;
       width: 920px;
     }
-
+    .bottoms-preview{
+      padding: 24px 0;
+      background: #fff;
+      border-radius: 4px;
+      margin: 16px 0;
+    }
     .bottoms {
-      // position: fixed;
-      // bottom: 0;
+       //position: fixed;
+       //bottom: 0;
       display: flex;
       flex-direction: column;
 
@@ -1239,4 +1424,22 @@ export default {
     }
   }
 }
+
+::v-deep {
+  .page:not(:first-of-type) {
+    border-top: 6px solid #f2f2f2;
+  }
+  // pdf自带的注释层样式
+  .annotationLayer {
+    display: none;
+  }
+}
+.preview-content {
+  img:not(:first-of-type) {
+    border-top: 6px solid #f2f2f2;
+  }
+}
+.bottoms-preview{
+  top: 0 !important;
+}
 </style>

+ 40 - 13
jydocs-pc/src/views/Home.vue

@@ -20,7 +20,7 @@
                   {{item.value}}
                 </div>
               </div>
-              <div class="word-model-more" @click="launchActive = !launchActive">
+              <div class="word-model-more" @click="launchActive = !launchActive" v-if="canFold">
                 <span>{{ launchActive ? '收起' : '展开'}}</span>
                 <i :class="`el-icon-arrow-${launchActive ? 'up' : 'down'}`"></i>
               </div>
@@ -30,7 +30,7 @@
                 <div class="mini-img-group">
                   <img :src="item.img" alt="" @error="handleError">
                   <i class="word-type" :class="'el-icon-jy-' + item.type" ></i>
-                  <span v-if="item.productType === 1" class="word-vip-mark">会员免费</span>
+                  <span class="type-tag" :class="item.productType === 2 ? 'boutique' : 'free'">{{item.productType === 2 ? '付费精品' : '会员免费'}}</span>
                 </div>
                 <div class="word-file-name">{{ item.title }}</div>
               </div>
@@ -173,7 +173,8 @@ export default {
       jyPcDocRecommend: [], // 文库推荐广告位
       jyPcDocMember: [], // 文库会员广告位
       docsWordList: [],
-      launchActive: false
+      launchActive: false,
+      canFold: false
     }
   },
   created () {
@@ -208,6 +209,22 @@ export default {
     }
   },
   methods: {
+    // 热门文档的tag是否有多行
+    checkIsOneRow () {
+      const container = document.querySelector('.word-model-content')
+      if (!container) return
+      const items = container.querySelectorAll('.word-model-list')
+      // 获取所有子元素的top值,如果所有子元素的top值相同,则说明只有一行
+      const firstItemTop = items[0].offsetTop
+      let isOneRow = true
+      for (let i = 1; i < items.length; i++) {
+        if (items[i].offsetTop !== firstItemTop) {
+          isOneRow = false
+          break
+        }
+      }
+      this.canFold = !isOneRow
+    },
     handleError (img) {
       img.target.src = require('../assets/images/error.png')
     },
@@ -312,6 +329,9 @@ export default {
         const res = data.data
         if (res && res.error_code === 0) {
           this.wordModel = res.data.map((item, index) => ({ value: item, active: index === 0 ? true : false }))
+          this.$nextTick(() => {
+            this.checkIsOneRow()
+          })
           const localList = this.getLocalData(this.wordModel[0].value)
           if (localList && localList.length) {
             this.wordFileList = localList.map((v) => formatData(v))
@@ -611,22 +631,29 @@ export default {
               right: 4px;
               bottom: 2px;
             }
-            .word-vip-mark{
+            &>img{
+              width: 100%;
+              height: 184px;
+              border: 1px solid #ECECEC;
+              border-radius: 4px;
+            }
+            .type-tag {
               position: absolute;
               left: 0;
               top: 0;
               padding: 2px 5px;
+              border-radius: 4px 0px 9px 0px;
               font-size: 11px;
               line-height: 14px;
-              color: #fff;
-              border-radius: 4px 0px 9px 0px;
-              background: linear-gradient(to right, #FF7C32 0%, #F33838 100%);
-            }
-            &>img{
-              width: 100%;
-              height: 184px;
-              border: 1px solid #ECECEC;
-              border-radius: 4px;
+
+              &.free {
+                background: linear-gradient(to right, #FF7C32 0%, #F33838 100%);
+                color: #fff;
+              }
+              &.boutique{
+                background: linear-gradient(270deg, #F1D090 0%, #FAE7CA 100%);
+                color: #B1700E;
+              }
             }
           }
           .word-file-name{

+ 4 - 4
jydocs-pc/src/views/Search.vue

@@ -113,13 +113,13 @@ export default {
         }
       ],
       productTypeList: [
-        {
-          label: '精品',
-          value: 2
-        },
         {
           label: '会员免费',
           value: 1
+        },
+        {
+          label: '付费精品',
+          value: 2
         }
       ],
       sortTypeList: [

+ 1 - 1
jydocs-pc/src/views/UserDocs.vue

@@ -17,7 +17,7 @@
           cardType="oneline"
           :key="index"
           :title="item.DocName"
-          :productType="item.product_type ? 1 : 0"
+          :productType="item.product_type"
           :docType="item.DocFileType + ''"
           :subInfo="calcSubInfo(item)"
           @onClick="toDocDetail(item)"