Przeglądaj źródła

Merge remote-tracking branch 'origin/master'

wangkaiyue 4 lat temu
rodzic
commit
acfcf76b8b
38 zmienionych plików z 922 dodań i 178 usunięć
  1. 2 0
      .gitignore
  2. 18 0
      README.md
  3. 1 1
      jydocs-mobile/.env.production
  4. 5 0
      jydocs-mobile/.env.test
  5. 2 1
      jydocs-mobile/.eslintrc.js
  6. 3 0
      jydocs-mobile/package.json
  7. 2 0
      jydocs-mobile/public/index.html
  8. 13 5
      jydocs-mobile/src/api/index.ts
  9. 14 1
      jydocs-mobile/src/api/main.ts
  10. 16 7
      jydocs-mobile/src/components/SharePopup.vue
  11. 13 9
      jydocs-mobile/src/components/docs-card/Card.vue
  12. 10 2
      jydocs-mobile/src/components/docs-card/Price.vue
  13. 1 1
      jydocs-mobile/src/router/index.ts
  14. 2 1
      jydocs-mobile/src/router/modules/main.ts
  15. 1 0
      jydocs-mobile/src/store/index.ts
  16. 17 1
      jydocs-mobile/src/store/modules/main.ts
  17. 5 0
      jydocs-mobile/src/style/pic-icon.scss
  18. 10 4
      jydocs-mobile/src/utils/globalFunctions.ts
  19. 1 1
      jydocs-mobile/src/utils/globalFunctionsForApp.ts
  20. 29 2
      jydocs-mobile/src/utils/index.ts
  21. 1 1
      jydocs-mobile/src/utils/mixin-top.ts
  22. 450 0
      jydocs-mobile/src/utils/wx-js-sdk-register.ts
  23. 1 1
      jydocs-mobile/src/views/Search.vue
  24. 93 49
      jydocs-mobile/src/views/details/details.vue
  25. 52 28
      jydocs-mobile/src/views/purchase/purchase.vue
  26. 17 14
      jydocs-mobile/src/views/user/Library.vue
  27. 4 7
      jydocs-mobile/vue.config.js
  28. 10 0
      jydocs-mobile/yarn.lock
  29. 0 1
      jydocs-pc/package.json
  30. 4 4
      jydocs-pc/src/api/modules/detail.js
  31. 11 0
      jydocs-pc/src/api/modules/purchase.js
  32. BIN
      jydocs-pc/src/assets/images/icon/ipt_corret.jpg
  33. BIN
      jydocs-pc/src/assets/images/icon/ipt_error.jpg
  34. 3 0
      jydocs-pc/src/components/doc-item-card/Card.vue
  35. 7 1
      jydocs-pc/src/utils/globalFunctions.js
  36. 39 29
      jydocs-pc/src/views/Content.vue
  37. 63 7
      jydocs-pc/src/views/purchase/purchase.vue
  38. 2 0
      jydocs-pc/vue.config.js

+ 2 - 0
.gitignore

@@ -29,3 +29,5 @@ yarn-error.log*
 *.7z
 .vscode
 jydocs-mobile/page_docs_app
+jydocs-pc/pc
+jydocs-pc/app

+ 18 - 0
README.md

@@ -100,3 +100,21 @@ location ^~/page_docs {
 }
 ```
 
+```
+# 静态资源配置
+# 1. 禁止html缓存
+location ~ ^\/(.*).html {
+    add_header         Pragma   no-cache;
+    add_header         Expires  0;
+    add_header         Cache-Control no-cache,no-store,must-revalidate;
+    
+    root html;
+}
+# 2. 静态资源配置(vue程序刷新404问题)
+location ~ ^\/page_(.*?)\/ {
+    root html;
+    index index.html;
+    try_files $uri $uri/ /page_$1/index.html;
+}
+```
+

+ 1 - 1
jydocs-mobile/.env.production

@@ -2,4 +2,4 @@ NODE_ENV=production
 VUE_APP_BASE_API='/jydocs/'
 BASE_URL = '/page_docs_app/'
 VUE_APP_BASE_URL = '/page_docs_app/'
-VUE_APP_LOG_URL='https://web2-jytest.jianyu360.cn/jyintegral/pointsLogs?logAction='
+VUE_APP_LOG_URL='https://web2-jytest.jydev.jianyu360.com/jyLogs/pointsLogs?logAction='

+ 5 - 0
jydocs-mobile/.env.test

@@ -0,0 +1,5 @@
+NODE_ENV=production
+VUE_APP_BASE_API='/jydocs/'
+BASE_URL = '/page_docs_app/'
+VUE_APP_BASE_URL = '/page_docs_app/'
+VUE_APP_LOG_URL='https://web2-jytest.jydev.jianyu360.com/jyLogs/pointsLogs?logAction='

+ 2 - 1
jydocs-mobile/.eslintrc.js

@@ -17,6 +17,7 @@ module.exports = {
     'no-any': [0, { 'ignore-rest-args': 0 }],
     "@typescript-eslint/ban-ts-ignore": ['off'],
     '@typescript-eslint/no-explicit-any': ['off'],
-    '@typescript-eslint/camelcase': ['off']
+    '@typescript-eslint/camelcase': ['off'],
+    '@typescript-eslint/no-var-requires': 0,
   }
 }

+ 3 - 0
jydocs-mobile/package.json

@@ -5,6 +5,7 @@
   "scripts": {
     "serve": "vue-cli-service serve",
     "build": "vue-cli-service build",
+    "build:test": "vue-cli-service build --mode test",
     "lint": "vue-cli-service lint"
   },
   "dependencies": {
@@ -13,6 +14,7 @@
     "html2canvas": "^1.0.0-rc.6",
     "js-cookie": "^2.2.1",
     "moment": "^2.24.0",
+    "pdfjs-dist": "^2.6.347",
     "vant": "^2.8.2",
     "vue": "^2.6.11",
     "vue-class-component": "^7.2.3",
@@ -22,6 +24,7 @@
   },
   "devDependencies": {
     "@types/js-cookie": "^2.2.6",
+    "@types/pdfjs-dist": "^2.7.0",
     "@types/qs": "^6.9.4",
     "@typescript-eslint/eslint-plugin": "^2.33.0",
     "@typescript-eslint/parser": "^2.33.0",

+ 2 - 0
jydocs-mobile/public/index.html

@@ -33,6 +33,8 @@
 <!-- built files will be auto injected -->
 <% if (process.env.NODE_ENV === 'production') { %>
   <script src="/page_partner/js/commonForVue.js?v=<%= htmlWebpackPlugin.options.version %>"></script>
+<% } else if (process.env.NODE_ENV === 'development') { %>
+  <script src="//res.wx.qq.com/open/js/jweixin-1.6.0.js"></script>
 <% } %>
 
 <!-- vConsole debug -->

+ 13 - 5
jydocs-mobile/src/api/index.ts

@@ -1,9 +1,17 @@
 import request from '@/api/ajax'
-import mock from '@/api/mock'
+import qs from 'qs'
 
-let $request: any = request
-if (process.env.NODE_ENV === 'development' && process.env.VUE_APP_MOCK === 'true') {
-  $request = mock
+export function getWxSdkSign (data: any) {
+  data = qs.stringify(data)
+  return request({
+    baseURL: '',
+    url: '/jypay/wx/getwxSdkSign',
+    method: 'post',
+    headers: {
+      noToast: 1
+    },
+    data
+  })
 }
 
-export default $request
+export default request

+ 14 - 1
jydocs-mobile/src/api/main.ts

@@ -92,7 +92,8 @@ export function getRemove (data: any) {
 export function getCoin (data: any) {
   console.log(data)
   return $request({
-    url: '/jyintegral/getList',
+    baseURL: '/jyintegral',
+    url: '/getList',
     method: 'post',
     data
   })
@@ -126,3 +127,15 @@ export function getListDetail (data: any) {
     params: data
   })
 }
+
+// 获取绑定的手机号
+
+export function getAccountInfo (data: any) {
+  data = qs.stringify(data)
+  return $request({
+    baseURL: '',
+    url: '/jypay/user/getAccountInfo',
+    method: 'post',
+    params: data
+  })
+}

+ 16 - 7
jydocs-mobile/src/components/SharePopup.vue

@@ -13,11 +13,11 @@
             <span class="share_detail">了解详情</span>
         </div>
         <div class="share_channel">
-            <div class="share_c_wx share_out">
+            <div class="share_c_wx share_out" @click="shareClick('1')">
                 <img src="../assets/icon/weixin.png" class="share_out_img" alt="">
                 <span class="wx_text out_text">微信</span>
             </div>
-            <div class="share_c_pyq share_out">
+            <div class="share_c_pyq share_out" @click="shareClick('3')">
                 <img src="../assets/icon/pengyouquan.png" class="share_out_img" alt="">
                 <span class="pyq_text out_text">朋友圈</span>
             </div>
@@ -26,8 +26,9 @@
 </template>
 
 <script lang="ts">
-import { Component, Vue } from 'vue-property-decorator'
+import { Component, Prop, Vue } from 'vue-property-decorator'
 import { Icon, Popup, Sticky } from 'vant'
+import { shareToOthers } from '@/utils/globalFunctionsForApp'
 
 // @ is an alias to /src
   @Component({
@@ -36,16 +37,24 @@ import { Icon, Popup, Sticky } from 'vant'
       [Popup.name]: Popup,
       [Sticky.name]: Sticky,
       [Icon.name]: Icon
-    },
-    created () {
-      console.log('111')
     }
   })
 export default class extends Vue {
-    show = true
+    @Prop() links: any
+    @Prop() detailData: any
+    show = false
     closePopup () {
       this.show = false
     }
+
+    shareClick (num: string) {
+      shareToOthers({
+        type: num, // options.type--1微信分享,2qq分享,3朋友圈分享
+        title: this.detailData.docName,
+        content: this.detailData.docSummary,
+        link: this.links.url
+      })
+    }
 }
 </script>
 

+ 13 - 9
jydocs-mobile/src/components/docs-card/Card.vue

@@ -27,18 +27,18 @@
             </div>
           </div>
           <div class="card-info-item price">
-            <slot name="price"><Price :price="price" /></slot>
+            <slot name="price"><Price :price="price" v-if="price !== -1" /></slot>
           </div>
         </div>
       </div>
     </div>
     <div class="docs-card" v-else key="docs-card">
-      <div class="docs-header flex-r-c center">
+      <div class="docs-header flex-r-c">
         <van-icon :name="docTypeIcon" />
         <div class="d-title flex van-ellipsis" v-html="hightLightTitle"></div>
       </div>
       <div class="docs-content docs-desc van-multi-ellipsis--l2" v-if="hightLightDesc" v-html="hightLightDesc"></div>
-      <div class="docs-footer flex-r-c">
+      <div class="docs-footer flex-r-c center">
         <div class="c-f-left subinfo-container">
           <span
             class="f-l-item subinfo-item card-time"
@@ -48,7 +48,7 @@
           >{{ item }}</span>
         </div>
         <div class="c-f-right flex-r-c">
-          <slot name="price"><Price :price="price" /></slot>
+          <slot name="price"><Price :price="price" v-if="price !== -1" /></slot>
         </div>
       </div>
     </div>
@@ -75,7 +75,7 @@ export default class DocsCard extends Vue {
   @Prop({ default: 'pdf' }) docType?: string | undefined; // 文档类型
   @Prop({ default: '' }) imageSrc?: string | undefined;
   @Prop({ default: '' }) uploader?: string | undefined;
-  @Prop({ default: 0 }) price?: string | number;
+  @Prop({ default: -1 }) price?: string | number;
 
   @Prop({
     type: Array,
@@ -129,16 +129,19 @@ export default class DocsCard extends Vue {
     }
   }
 
-  @include diy-icon('pdf', 24);
-  @include diy-icon('word', 24);
-  @include diy-icon('excel', 24);
-  @include diy-icon('ppt', 24);
+  @include diy-icon('pdf');
+  @include diy-icon('word');
+  @include diy-icon('excel');
+  @include diy-icon('ppt');
 
   .docs-header {
     .d-title {
       margin-left: 4px;
       font-size: 16px;
       color: #171826;
+      em {
+        color: $color_main;
+      }
     }
   }
 
@@ -151,6 +154,7 @@ export default class DocsCard extends Vue {
 
   .docs-footer {
     margin-top: 8px;
+    justify-content: space-between;
   }
 
   .subinfo-container {

+ 10 - 2
jydocs-mobile/src/components/docs-card/Price.vue

@@ -1,7 +1,7 @@
 <template>
   <div class="price-container">
-    <van-icon name="diy-iconLogoLight" />
-    <span class="p-r">{{ price }}</span>
+    <van-icon name="diy-iconLogoLight" v-if="!alreadyBuy" />
+    <span class="p-r" :class="{bought: alreadyBuy}">{{ price }}</span>
   </div>
 </template>
 <script lang="ts">
@@ -17,6 +17,10 @@ import { Icon } from 'vant'
 
 export default class Price extends Vue {
   @Prop({ default: '' }) price?: string | undefined;
+
+  get alreadyBuy () {
+    return this.price === '已购买'
+  }
 }
 </script>
 
@@ -30,6 +34,10 @@ export default class Price extends Vue {
     margin-left: 4px;
     font-size: 18px;
     color: #ff3a20;
+    &.bought {
+      color: $color_main;
+      font-size: 14px;
+    }
   }
 }
 </style>

+ 1 - 1
jydocs-mobile/src/router/index.ts

@@ -11,7 +11,7 @@ if (process.env.NODE_DEV !== 'production') {
 let routes = [
   {
     path: '/',
-    redirect: 'demo'
+    redirect: 'home'
   },
   {
     path: '/home',

+ 2 - 1
jydocs-mobile/src/router/modules/main.ts

@@ -28,7 +28,8 @@ export default [
     name: 'details',
     component: () => import('@/views/details/details.vue'),
     meta: {
-      title: '文库详情'
+      title: '文库详情',
+      layoutConf: true
     }
   },
   {

+ 1 - 0
jydocs-mobile/src/store/index.ts

@@ -66,6 +66,7 @@ export default new Vuex.Store({
       for (const key in conf) {
         state.layoutConf[key] = conf[key]
       }
+      console.log(state.layoutConf)
     },
     // 将数据恢复默认状态
     clearLayoutConfig (state: any) {

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

@@ -12,8 +12,10 @@ import {
   getRemove,
   getAdd,
   getCoin,
+  getShare,
   getDocPay,
-  getIndexTags
+  getIndexTags,
+  getAccountInfo
 } from '@/api/main'
 
 interface InterfaceStore<S> extends StoreOptions<S> {
@@ -180,6 +182,13 @@ const modulesOption: modulesOption = {
         return res.data
       } catch (error) {}
     },
+    async getShare (state, data) {
+      try {
+        const res = await getShare(data)
+        console.log(res)
+        return res.data
+      } catch (error) {}
+    },
     // 文库购买
     async getDocPay (state, data) {
       try {
@@ -218,6 +227,13 @@ const modulesOption: modulesOption = {
         console.log(res)
         return res.data
       } catch (error) {}
+    },
+    // 获取绑定手机号
+    async getAccountInfo (state, data) {
+      try {
+        const res = await getAccountInfo(data)
+        return res.data
+      } catch (error) {}
     }
   },
   getters: {}

+ 5 - 0
jydocs-mobile/src/style/pic-icon.scss

@@ -62,3 +62,8 @@
     background-color: $color_main;
   }
 }
+
+.icon-iconJianYu {
+  background: url("~@/assets/icon/iconJianYu.png") no-repeat;
+  background-size: cover;
+}

+ 10 - 4
jydocs-mobile/src/utils/globalFunctions.ts

@@ -313,14 +313,14 @@ export function removeSpace (str: string) {
 }
 
 // 文件大小格式化
-export function formatSize (size: string | number, pointLength: number, units: Array<string>) {
+export function formatSize (size: string | number, pointLength = 2) {
+  const units = ['B', 'K', 'M', 'G', 'TB']
   size = Number(size)
   let unit: string | undefined = ''
-  units = units || ['B', 'K', 'M', 'G', 'TB']
   while ((unit = units.shift()) && size > 1024) {
     size = size / 1024
   }
-  return (unit === 'B' ? size : size.toFixed(pointLength === undefined ? 2 : pointLength)) + (unit || '')
+  return (unit === 'B' ? size : size.toFixed(pointLength)) + (unit || '')
 }
 
 // 文件类型转换
@@ -331,7 +331,13 @@ export function docTypeConvert (docType = 'pdf') {
     xls: 'excel',
     xlsx: 'excel',
     ppt: 'ppt',
-    pdf: 'pdf'
+    pdf: 'pdf',
+    1: 'word', // doc
+    2: 'pdf',
+    3: 'excel', // xls
+    4: 'ppt',
+    5: 'txt',
+    6: '其他'
   }
   const type = typeMap[docType]
   return type || docType // map中不存在的,则返回原始类型

+ 1 - 1
jydocs-mobile/src/utils/globalFunctionsForApp.ts

@@ -26,7 +26,7 @@ export function shareToOthers (options: any = {}) {
     // app分享
     try {
       // options.type--1微信分享,2qq分享,3朋友圈分享
-      JyObj.share(options.type, options.title, options.link)
+      JyObj.share(options.type, options.title, options.content, options.link)
     } catch (error) {
       console.log(error)
     }

+ 29 - 2
jydocs-mobile/src/utils/index.ts

@@ -1,19 +1,46 @@
 import Vue from 'vue'
 import './globalDirectives'
 import './globalFilters'
-import { isWeiXinBrowser } from '@/utils/globalFunctions'
+import WeiXinSDK from '@/utils/wx-js-sdk-register.ts'
+import { isWeiXinBrowser, androidOrIOS } from '@/utils/globalFunctions'
+import { getWxSdkSign } from '@/api/index.ts'
 
 declare module 'vue/types/vue' {
   interface Vue {
     $env: any;
+    $registerWxSdk: any;
+    $wxSdk: any;
   }
 }
 
 const inWeiXinBrowser = isWeiXinBrowser()
+const isAndroidOrIos = androidOrIOS()
 
 Vue.prototype.$env = {
   isWeiXinBrowser: inWeiXinBrowser,
-  platform: inWeiXinBrowser ? 'wx' : 'app'
+  platform: inWeiXinBrowser ? 'wx' : 'app',
+  isAndroid: isAndroidOrIos === 'android',
+  isIOS: isAndroidOrIos === 'ios'
+}
+
+// 如果是微信浏览器, 注册一个微信SDK初始化函数
+if (!inWeiXinBrowser) {
+  Vue.prototype.$registerWxSdk = async () => {
+    const sdkInfo = await getWxSdkSign({ url: location.href.split('#')[0] })
+    if (!sdkInfo) return
+    const info = sdkInfo.data
+    if (info && info.wxsdk && Array.isArray(info.wxsdk)) {
+      const sdk = info.wxsdk
+      Vue.prototype.$wxSdk = new WeiXinSDK({
+        appId: sdk[0],
+        timestamp: sdk[1],
+        nonceStr: sdk[2],
+        signature: sdk[3]
+      })
+    }
+    return info
+  }
+  Vue.prototype.$registerWxSdk()
 }
 
 // 正式环境下屏蔽console.log

+ 1 - 1
jydocs-mobile/src/utils/mixin-top.ts

@@ -17,7 +17,7 @@ export const MixinTop = {
   },
   beforeRouteEnter (to: any, form: any, next: any) {
     next((vm: any) => {
-      console.log(vm.TopConfig.actionRightCallback)
+      console.log(vm.TopConfig)
       vm.upTopConfig()
     })
   },

+ 450 - 0
jydocs-mobile/src/utils/wx-js-sdk-register.ts

@@ -0,0 +1,450 @@
+declare const wx: any
+declare const WeixinJSBridge: any
+
+// 官方文档
+// https://developers.weixin.qq.com/doc/offiaccount/OA_Web_Apps/JS-SDK.html
+
+// 参考1: https://github.com/wxt365/JWeixinApi/blob/master/jweixinapi.js
+// 参考2: https://my.oschina.net/u/2405644/blog/492396
+class WeiXinSDK {
+  env = {
+    // 微信JSSDK版本
+    version: '1.6.0',
+    isWeiXinBrowser: navigator.userAgent.toLowerCase().indexOf('micromessenger') !== -1
+  }
+
+  config = {
+    // 是否开启调试
+    WeiXinDebugMode: false,
+    // 当前url(发送到后端进行注册的,包含参数)
+    configUrl: location.href.split('#')[0],
+    // 分享配置文件中的url
+    shareUrl: location.href.split('?')[0],
+    configData: {
+      // 公众号的唯一标识
+      appId: '',
+      // 生成签名的时间戳
+      timestamp: '',
+      // 生成签名的随机串
+      nonceStr: '',
+      // 签名,见附录1
+      signature: ''
+    },
+    jsApiList: [
+      // 自定义“分享给朋友”及“分享到QQ”按钮的分享内容
+      'updateAppMessageShareData',
+      // 自定义“分享到朋友圈”及“分享到QQ空间”按钮的分享内容
+      'updateTimelineShareData',
+      // 获取“分享到腾讯微博”按钮点击状态及自定义分享内容接口
+      // 'onMenuShareWeibo',
+      // 图片预览
+      // 'imagePreview',
+      // 获取网络状态接口
+      // 'getNetworkType',
+      // 获取地理位置接口
+      // 'getLocation',
+      // 使用微信内置地图<查看>位置接口
+      // 'openLocation',
+      // 批量隐藏功能按钮接口
+      // 'hideMenuItems',
+      // 批量显示功能按钮接口
+      // 'showMenuItems',
+      // 隐藏所有非基础按钮接口
+      // 'hideAllNonBaseMenuItem',
+      // 显示所有功能按钮接口
+      // 'showAllNonBaseMenuItem',
+      // 调起微信扫一扫接口
+      // 'scanQRCode',
+      // 关闭当前网页窗口接口
+      'closeWindow',
+      // 发起一个微信支付请求
+      'chooseWXPay'
+    ]
+  }
+
+  currentLocation = {
+    // 纬度,浮点数,范围为90 ~ -90
+    latitude: 0,
+    // 经度,浮点数,范围为180 ~ -180
+    longitude: 0,
+    // 速度,以米/每秒计
+    speed: 0,
+    // 位置精度
+    accuracy: 0
+  }
+
+  defaultShareInfo = {
+    // 分享标题
+    title: '剑鱼标讯',
+    // 分享描述
+    desc: '全国招标信息免费看,不遮挡',
+    // 分享链接,该链接域名或路径必须与当前页面对应的公众号JS安全域名一致
+    link: this.config.shareUrl,
+    // 分享图标
+    imgUrl: 'https://cdn-ali.jianyu360.com/images/appext/fixed-sm.jpg'
+  }
+
+  constructor (data: object) {
+    if (!this.env.isWeiXinBrowser) return
+    this.initSignature(data)
+  }
+
+  initSignature (data: object) {
+    this.setConfigData(data)
+    this.setConfig()
+  }
+
+  // 将constructor中传入的值赋值到全局
+  setConfigData (data: any) {
+    for (const key in this.config.configData) {
+      const d = this.config.configData as any
+      d[key] = data[key]
+    }
+  }
+
+  // wxJSSDK注册
+  setConfig () {
+    wx.config({
+      // 开启调试模式,调用的所有api的返回值会在客户端alert出来,若要查看传入的参数,可以在pc端打开,参数信息会通过log打出,仅在pc端时才会打印。
+      debug: this.config.WeiXinDebugMode,
+      // // 必填,公众号的唯一标识
+      // appId: data.appId,
+      // // 必填,生成签名的时间戳
+      // timestamp: data.timestamp,
+      // // 必填,生成签名的随机串
+      // nonceStr: data.nonceStr,
+      // // 必填,签名,见附录1
+      // signature: data.signature,
+      ...this.config.configData,
+      // 必填,需要使用的JS接口列表
+      jsApiList: this.config.jsApiList
+    })
+  }
+
+  // 将分享数据整理
+  getShareInfo (data: any) {
+    // 如果是null或者空对象
+    if (!data || (data && Object.keys(data).length === 0)) {
+      return this.defaultShareInfo
+    } else {
+      const shareInfo = JSON.parse(JSON.stringify(this.defaultShareInfo))
+      for (const key in shareInfo) {
+        if (data[key]) {
+          shareInfo[key] = data[key]
+        }
+      }
+      return shareInfo
+    }
+  }
+
+  // 检查微信api是否可用
+  checkJsApi (apiList: any = [], callback?: Function) {
+    apiList = apiList.length === 0 ? this.config.jsApiList : apiList
+    wx.checkJsApi({
+      // 需要检测的JS接口列表
+      jsApiList: apiList,
+      success: (res: any) => {
+        // 以键值对的形式返回,可用的api值true,不可用为false
+        // 如:{"checkResult":{"chooseImage":true},"errMsg":"checkJsApi:ok"}
+        console.log(res)
+        callback && callback(res)
+      }
+    })
+  }
+
+  ready (callback?: Function) {
+    wx.ready(() => {
+      if (typeof callback === 'function') {
+        // callback && callback.call(this)
+        callback && callback()
+      }
+    })
+  }
+
+  // 自定义“分享给朋友”及“分享到QQ”按钮的分享内容
+  shareToFriendAndQQ (options: any = {}) {
+    // 如果不传配置,就使用默认的配置
+    const config = this.getShareInfo(options.config)
+    // 执行分享
+    this.ready(() => {
+      wx.updateAppMessageShareData({
+        ...config,
+        // title: config.title,
+        // desc: config.desc,
+        // link: config.link,
+        // imgUrl: config.imgUrl,
+        success: () => {
+          // 用户确认分享后执行的回调函数
+          options && options.success && options.success()
+        },
+        cancel: () => {
+          // 用户取消分享后执行的回调函数
+          options && options.cancel && options.cancel()
+        },
+        fail: () => {
+          // 接口调用失败时执行的回调函数
+          options && options.fail && options.fail()
+        },
+        complete: () => {
+          // 接口调用完成时执行的回调函数,无论成功或失败都会执行。
+          options && options.complete && options.complete()
+        }
+      })
+    })
+  }
+
+  // 自定义“分享到朋友圈”及“分享到QQ空间”按钮的分享内容
+  shareToFriendsAndQZone (options: any = {}) {
+    // 如果不传配置,就使用默认的配置
+    const config = this.getShareInfo(options.config)
+    // 执行分享
+    this.ready(() => {
+      wx.updateTimelineShareData({
+        ...config,
+        // title: config.title,
+        // desc: config.desc,
+        // link: config.link,
+        // imgUrl: config.imgUrl,
+        success: () => {
+          // 用户确认分享后执行的回调函数
+          options && options.success && options.success()
+        },
+        cancel: () => {
+          // 用户取消分享后执行的回调函数
+          options && options.cancel && options.cancel()
+        },
+        fail: () => {
+          // 接口调用失败时执行的回调函数
+          options && options.fail && options.fail()
+        },
+        complete: () => {
+          // 接口调用完成时执行的回调函数,无论成功或失败都会执行。
+          options && options.complete && options.complete()
+        }
+      })
+    })
+  }
+
+  // 自定义“分享到微博”
+  shareToWeiBo (options: any = {}) {
+    // 如果不传配置,就使用默认的配置
+    const config = this.getShareInfo(options.config)
+    // 执行分享
+    wx.onMenuShareWeibo({
+      ...config,
+      // title: config.title,
+      // desc: config.desc,
+      // link: config.link,
+      // imgUrl: config.imgUrl,
+      success: () => {
+        // 用户确认分享后执行的回调函数
+        options && options.success && options.success()
+      },
+      cancel: () => {
+        // 用户取消分享后执行的回调函数
+        options && options.cancel && options.cancel()
+      },
+      fail: () => {
+        // 接口调用失败时执行的回调函数
+        options && options.fail && options.fail()
+      },
+      complete: () => {
+        // 接口调用完成时执行的回调函数,无论成功或失败都会执行。
+        options && options.complete && options.complete()
+      }
+    })
+  }
+
+  // 微信js-sdk支付
+  chooseWXPay (options: any) {
+    // 执行支付
+    wx.chooseWXPay({
+      // appId: this.config.configData.appId,
+      ...options.config,
+      // timestamp: config.timestamp,
+      // nonceStr: config.nonceStr,
+      // package: config.package,
+      // signType: config.signType,
+      // paySign: config.paySign,
+      success: () => {
+        // 用户确认支付后执行的回调函数
+        options && options.success && options.success()
+      },
+      cancel: () => {
+        // 用户取消支付后执行的回调函数
+        options && options.cancel && options.cancel()
+      },
+      fail: () => {
+        // 接口调用失败时执行的回调函数
+        options && options.fail && options.fail()
+      },
+      complete: () => {
+        // 接口调用完成时执行的回调函数,无论成功或失败都会执行。
+        options && options.complete && options.complete()
+      }
+    })
+  }
+
+  // https://pay.weixin.qq.com/wiki/doc/api/jsapi.php?chapter=7_7&index=6
+  chooseWXPayForWeiXinJSBridge (options: any) {
+    // 调用WeixinJSBridge支付
+    WeixinJSBridge.invoke('getBrandWCPayRequest', {
+      appId: options.config.appId,
+      timeStamp: options.config.timestamp,
+      nonceStr: options.config.nonceStr,
+      package: options.config.package,
+      signType: options.config.signType,
+      paySign: options.config.paySign
+    }, (res: any) => {
+      if (res.err_msg === 'get_brand_wcpay_request:ok') {
+        // 使用以上方式判断前端返回,微信团队郑重提示:
+        // res.err_msg将在用户支付成功后返回ok,但并不保证它绝对可靠。
+        options && options.success && options.success()
+      } else if (res.err_msg === 'get_brand_wcpay_request:cancel') {
+        options && options.cancel && options.cancel()
+      } else {
+        options && options.fail && options.fail()
+      }
+    })
+  }
+
+  closeWindow () {
+    wx.closeWindow()
+  }
+
+  hideOptionMenu () {
+    wx.hideOptionMenu()
+  }
+
+  showOptionMenu () {
+    wx.showOptionMenu()
+  }
+
+  hideMenuItems (menuList = []) {
+    // 要隐藏的菜单项,只能隐藏“传播类”和“保护类”按钮,所有menu项见附录3
+    wx.hideMenuItems({
+      menuList
+    })
+  }
+
+  showMenuItems (menuList = []) {
+    // 要显示的菜单项,所有menu项见附录3
+    wx.showMenuItems({
+      menuList
+    })
+  }
+
+  hideAllNonBaseMenuItem () {
+    wx.hideAllNonBaseMenuItem()
+  }
+
+  showAllNonBaseMenuItem () {
+    wx.showAllNonBaseMenuItem()
+  }
+
+  getNetworkType (options: any) {
+    wx.getNetworkType({
+      success: (res: any) => {
+        // 用户确认支付后执行的回调函数
+        // 返回网络类型2g,3g,4g,wifi
+        options && options.success && options.success(res)
+      },
+      cancel: () => {
+        // 用户取消支付后执行的回调函数
+        options && options.cancel && options.cancel()
+      },
+      fail: () => {
+        // 接口调用失败时执行的回调函数
+        options && options.fail && options.fail()
+      },
+      complete: () => {
+        // 接口调用完成时执行的回调函数,无论成功或失败都会执行。
+        options && options.complete && options.complete()
+      }
+    })
+  }
+
+  /**
+   * 调起微信Native的图片播放组件。
+   * 这里必须对参数进行强检测,如果参数不合法,直接会导致微信客户端crash
+   *
+   * @param {String} curSrc 当前播放的图片地址
+   * @param {Array} srcList 图片地址列表
+   */
+  imagePreview (curSrc: string, srcList: Array<string>) {
+    if (!curSrc || !srcList || srcList.length === 0) {
+      return
+    }
+    wx.previewImage({
+      // 当前显示图片的http地址
+      current: curSrc,
+      // 需要预览的图片http地址列表
+      urls: srcList
+    })
+  }
+
+  getLocation (options: any) {
+    wx.getLocation({
+      // 默认为wgs84的gps坐标,如果要返回直接给openLocation用的火星坐标,可传入'gcj02'
+      type: options.type === undefined ? 'wgs84' : options.type,
+      success: (res: any) => {
+        // for (const key in this.currentLocation) {
+        //   this.currentLocation[key] = res[key]
+        // }
+        this.currentLocation = res
+        options && options.success && options.success(res)
+      },
+      cancel: (res: any) => {
+        // 用户取消支付后执行的回调函数
+        options && options.cancel && options.cancel(res)
+      },
+      fail: (res: any) => {
+        // 接口调用失败时执行的回调函数
+        options && options.fail && options.fail(res)
+      },
+      complete: () => {
+        // 接口调用完成时执行的回调函数,无论成功或失败都会执行。
+        options && options.complete && options.complete()
+      }
+    })
+  }
+
+  openLocation (data: object) {
+    wx.openLocation({
+      ...data
+      // latitude: 0, // 纬度,浮点数,范围为90 ~ -90
+      // longitude: 0, // 经度,浮点数,范围为180 ~ -180。
+      // name: '', // 位置名
+      // address: '', // 地址详情说明
+      // scale: 1, // 地图缩放级别,整形值,范围从1~28。默认为最大
+      // infoUrl: '' // 在查看位置界面底部显示的超链接,可点击跳转
+    })
+  }
+
+  // 调起微信扫一扫接口
+  scanQRCode (options: any) {
+    wx.scanQRCode({
+      needResult: options.needResult === undefined ? 0 : options.needResult, // 默认为0,扫描结果由微信处理,1则直接返回扫描结果
+      scanType: ['qrCode', 'barCode'], // 可以指定扫二维码还是一维码,默认二者都有
+      success: (res: any) => {
+        // 当needResult 为 1 时,扫码返回的结果
+        console.log(res.resultStr)
+        options && options.success && options.success(res)
+      },
+      cancel: (res: any) => {
+        // 用户取消支付后执行的回调函数
+        options && options.cancel && options.cancel(res)
+      },
+      fail: (res: any) => {
+        // 接口调用失败时执行的回调函数
+        options && options.fail && options.fail(res)
+      },
+      complete: () => {
+        // 接口调用完成时执行的回调函数,无论成功或失败都会执行。
+        options && options.complete && options.complete()
+      }
+    })
+  }
+}
+
+export default WeiXinSDK

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

@@ -65,7 +65,7 @@ import { mapState, mapMutations, mapActions } from 'vuex'
 import { dateFormatter } from '@/utils/globalFunctions'
 
 @Component({
-  name: 'home',
+  name: 'search-page',
   components: {
     [Tab.name]: Tab,
     [Tabs.name]: Tabs,

+ 93 - 49
jydocs-mobile/src/views/details/details.vue

@@ -12,8 +12,8 @@
             <div class="continue" v-show="!buyed">全文共{{detailData.docPageSize}}页,<span @click="continued">继续阅读<van-icon name="arrow-down" size="18" /></span></div>
         </div>
         <div class="botts" v-show="buyed">
-            <div class="cont-page" id="pdfPage">
-                <iframe :src="conts" width="100%" height="100%"></iframe>
+            <div class="cont-page" id="pdfPage" style="width: 375px">
+                <!-- <iframe :src="conts" width="100%" height="100%"></iframe> -->
             </div>
         </div>
         <van-goods-action>
@@ -29,8 +29,8 @@
         </van-goods-action>
         <!-- 充值 -->
         <recharge ref="charge" :detailData="detailData" :coins="coins"></recharge>
-        <!-- 购买 -->
-        <purchase ref="buys" :detailData="detailData" :coins="coins"></purchase>
+        <!-- 分享 -->
+        <share-pop ref="shares" :detailData="detailData" :links="links"></share-pop>
     </div>
 </template>
 
@@ -39,22 +39,28 @@ import { Component, Vue } from 'vue-property-decorator'
 import { mapActions } from 'vuex'
 import { Icon, Toast, GoodsAction, GoodsActionIcon, GoodsActionButton } from 'vant'
 import Recharge from '@/components/Recharge.vue'
-import Purchase from '@/components/RechargeHave.vue'
+import sharePop from '@/components/SharePopup.vue'
+import { MixinTop } from '@/utils/mixin-top'
+const pdfjsLib = require('pdfjs-dist/build/pdf.js')
+const pdfjsViewer = require('pdfjs-dist/web/pdf_viewer.js')
+
 @Component({
   name: 'details-p',
+  mixins: [MixinTop],
   components: {
     [Icon.name]: Icon,
     [GoodsAction.name]: GoodsAction,
     [GoodsActionIcon.name]: GoodsActionIcon,
     [GoodsActionButton.name]: GoodsActionButton,
     Recharge,
-    Purchase
+    sharePop
   },
   methods: {
     ...mapActions({
       getDetails: 'main/getDetails',
       getShow: 'main/getShow',
       getCoin: 'main/getCoin',
+      getShare: 'main/getShare',
       getAdd: 'main/getAdd',
       getRemove: 'main/getRemove'
     })
@@ -64,6 +70,8 @@ export default class extends Vue {
   getDetails: any
   getCoin: any
   getShow: any
+  getShare: any
+  links: any = []
   docIds = ''
   coins: any = []
   conts: any = []
@@ -76,16 +84,28 @@ export default class extends Vue {
   pdfDocument: any
   config: any = {
     PAGE_TO_VIEW: 0,
-    SCALE: 1.0
+    SCALE: 0.9,
+    CMAP_URL: 'https://cdn.jsdelivr.net/npm/pdfjs-dist@2.6.347/cmaps/',
+    CMAP_PACKED: true,
+    workerSrc: 'https://cdn.jsdelivr.net/npm/pdfjs-dist@2.6.347/es5/build/pdf.worker.min.js'
   }
 
   pData: any = {
     heightList: []
   }
 
+  TopConfig: any = {
+    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>',
+    actionRightCallback: this.shared,
+    actionRightStyle: {
+      color: '#5F5E64',
+      fontSize: '20px',
+      paddingLeft: '10px'
+    }
+  }
+
   created () {
     this.docIds = this.$route.params.id
-    // this.docIds = '19d53d64-8890-11eb-8699-0050568f51e7'
     this.onList()
   }
 
@@ -98,6 +118,14 @@ export default class extends Vue {
     window.removeEventListener('scroll', this.watchPage)
   }
 
+  shared () {
+    ;(this.$refs.shares as any).show = true
+    this.getShare({ docId: this.docIds }).then((res: any) => {
+      console.log(res)
+      this.links = res.data
+    })
+  }
+
   // updateText (type: any, value = '') {
   //   switch (type) {
   //     case 'count': {
@@ -111,39 +139,42 @@ export default class extends Vue {
   //   }
   // }
 
-  // renders () {
-  //   const container = document.getElementById('pdfPage')
-  //   return this.pdfDocument.getPage(this.config.PAGE_TO_VIEW).then((pdfPage: any) => {
-  //     const pdfPageView = new pdfjsViewer.PDFPageView({
-  //       container: container,
-  //       id: this.config.PAGE_TO_VIEW,
-  //       scale: this.config.SCALE,
-  //       defaultViewport: pdfPage.getViewport({ scale: this.config.SCALE }),
-  //       eventBus: new pdfjsViewer.EventBus(),
-  //       annotationLayerFactory: new pdfjsViewer.DefaultAnnotationLayerFactory()
-  //     })
-  //     pdfPageView.setPdfPage(pdfPage)
-  //     this.pData.heightList.push(pdfPageView.viewport.height)
-  //     return pdfPageView.draw()
-  //   })
-  // }
+  renders () {
+    const container = document.getElementById('pdfPage')
+    return this.pdfDocument.getPage(this.config.PAGE_TO_VIEW).then((pdfPage: any) => {
+      const pdfPageView = new pdfjsViewer.PDFPageView({
+        container: container,
+        id: this.config.PAGE_TO_VIEW,
+        scale: this.config.SCALE,
+        defaultViewport: pdfPage.getViewport({ scale: this.config.SCALE }),
+        eventBus: new pdfjsViewer.EventBus(),
+        annotationLayerFactory: new pdfjsViewer.DefaultAnnotationLayerFactory()
+      })
+      pdfPageView.setPdfPage(pdfPage)
+      this.pData.heightList.push(pdfPageView.viewport.height)
+      return pdfPageView.draw()
+    })
+  }
 
-  // init () {
-  //   console.log(this.conts)
-  //   const loadingTask = pdfjsLib.getDocument({
-  //     url: this.conts
-  //   })
-  //   loadingTask.promise.then((pdfDocument: any) => {
-  //     this.pdfDocument = pdfDocument
-  //     console.log(this.pdfDocument.numPages)
-  //     // this.updateText({type: 'count', value: this.pdfDocument.numPages})
-  //     // this.updateText({type: 'num', value: 1})
-  //     for (let i = 0; i < this.pdfDocument.numPages; i++) {
-  //       this.config.PAGE_TO_VIEW++
-  //       this.renders()
-  //     }
-  //   })
-  // }
+  init () {
+    console.log(this.conts)
+    pdfjsLib.GlobalWorkerOptions.workerSrc = this.config.workerSrc
+    const loadingTask = pdfjsLib.getDocument({
+      url: this.conts,
+      cMapUrl: this.config.CMAP_URL,
+      cMapPacked: this.config.CMAP_PACKED
+    })
+    loadingTask.promise.then((pdfDocument: any) => {
+      this.pdfDocument = pdfDocument
+      console.log(this.pdfDocument.numPages)
+      // this.updateText({type: 'count', value: this.pdfDocument.numPages})
+      // this.updateText({type: 'num', value: 1})
+      for (let i = 0; i < this.pdfDocument.numPages; i++) {
+        this.config.PAGE_TO_VIEW++
+        this.renders()
+      }
+    })
+  }
 
   watchPage () {
     const top = window.scrollY
@@ -157,21 +188,28 @@ export default class extends Vue {
     }
   }
 
+  buyShow () {
+    this.getShow({ docId: this.docIds }).then((res: any) => {
+      console.log(res.data)
+      this.conts = res.data
+      this.init()
+    })
+  }
+
   onList () {
-    this.getDetails({ docId: this.docIds }).then((res: any) => {
+    this.getDetails({ docId: this.docIds, from: this.$route.query.from }).then((res: any) => {
       console.log(res.data)
       this.detailData = res.data.detail
       this.buyed = res.data.status
-      this.collectd = res.data.docCang
+      if (res.data.status === 1) {
+        this.buyShow()
+      }
+      this.collectd = res.data.collect
     })
     this.getCoin({ B: true }).then((res: any) => {
       console.log(res.data.data)
       this.coins = res.data.data.points
     })
-    this.getShow({ docId: this.docIds }).then((res: any) => {
-      console.log(res.data)
-      this.conts = res.data
-    })
   }
 
   jubaod () {
@@ -206,13 +244,15 @@ export default class extends Vue {
   }
 
   uploaded () {
+    Toast('点击按钮')
     if (this.buyed === 1) {
       this.$router.push('/')
     } else {
+      console.log('111')
       if (this.coins.balance < this.detailData.price) {
         ;(this.$refs.charge as any).show = true
       } else {
-        ;(this.$refs.buys as any).show = true
+        this.$router.push({ path: '/purchase', query: { id: this.detailData.docId } })
       }
     }
   }
@@ -243,6 +283,7 @@ export default class extends Vue {
 @include diy-icon('jubao', 20, 20);
 @include diy-icon('weiguanzhu', 20, 20);
 @include diy-icon('guanzhu', 20, 20);
+@include diy-icon('iconJianYu', 24, 24);
 .details-p {
     display: flex;
     flex-direction: column;
@@ -254,6 +295,7 @@ export default class extends Vue {
         h3 {
             display: flex;
             flex-direction: initial;
+            width: 100%;
             color: #171826;
             font-weight: 500;
             font-size: 20px;
@@ -300,10 +342,12 @@ export default class extends Vue {
         }
     }
     .botts {
-        padding: 16px 24px;
+        // padding: 16px 24px;
+        // width: 375px;
         background: #fff;
         .cont-page {
-            height: 900px;
+          // width: 375px;
+          background: #fff;
         }
     }
     .van-goods-action {

+ 52 - 28
jydocs-mobile/src/views/purchase/purchase.vue

@@ -34,18 +34,18 @@
         </div>
       </div>
       <div class="docs_phone">
-        <!-- <van-cell-group>
-          <van-field v-model="tel" type="number" label="手机号码" placeholder="请输入手机号码" />
-        </van-cell-group> -->
-        <van-field
-          class="editable"
-          v-model="tel"
-          name="phone"
-          type="tel"
-          label="手机号码"
-          placeholder="请输入手机号码"
-          :rules="phoneRules"
-        />
+        <van-form validate-first>
+          <van-field
+            class="editable"
+            v-model="tel"
+            name="validator"
+            type="tel"
+            label="手机号码"
+            placeholder="请输入手机号码"
+            @input="iptValue()"
+            :rules="[{ validator, message: '手机号格式错误' }]"
+          />
+        </van-form>
       </div>
     </div>
     <div class="j-footer exchange_footer">
@@ -62,7 +62,7 @@
         <van-checkbox v-model="checked" checked-color="#2ABED1" >我已阅读并同意<a href="javascript:;" class="clause" @click="clause()">《剑鱼文库线上购买及服务条款》</a><a href="javascript:;" class="clause" @click="clause2()">《剑鱼标讯产品与服务线上购买服务条款》</a></van-checkbox>
       </div>
       <div class="apply_footer">
-        <button class="apply_button" :disabled="!this.checked" @click="exchange()">确定兑换</button>
+        <button class="apply_button" :disabled="!this.btnChecked" @click="exchange()">确定兑换</button>
       </div>
     </div>
   </div>
@@ -70,23 +70,24 @@
 
 <script lang="ts">
 import { Component, Vue } from 'vue-property-decorator'
-import { Checkbox, CheckboxGroup, Field, CellGroup } from 'vant'
+import { Checkbox, CheckboxGroup, Field, CellGroup, Form } from 'vant'
 import { mapActions } from 'vuex'
 // import { getDocPay } from '../../api/main'
-const regPhoneExg = /^(0|86|17951)?(13[0-9]|15[012356789]|166|17[3678]|18[0-9]|14[57]|19[0-9])[0-9]{8}$/
 @Component({
   name: 'purchase-page',
   components: {
     [Checkbox.name]: Checkbox,
     [CheckboxGroup.name]: CheckboxGroup,
     [Field.name]: Field,
+    [Form.name]: Form,
     [CellGroup.name]: CellGroup
   },
   methods: {
     ...mapActions({
       getDocPay: 'main/getDocPay',
       getDetails: 'main/getDetails',
-      getListDetail: 'main/getListDetail'
+      getListDetail: 'main/getListDetail',
+      getAccountInfo: 'main/getAccountInfo'
     })
   }
 })
@@ -94,8 +95,11 @@ export default class extends Vue {
   protected getDocPay!: any
   protected getDetails!: any
   protected getListDetail!: any
+  protected getAccountInfo!: any
   checked = false
+  btnChecked = true
   tel = ''
+  regPhoneExg = /^(0|86|17951)?(13[0-9]|15[012356789]|166|17[3678]|18[0-9]|14[57]|19[0-9])[0-9]{8}$/
   query: any
   $router: any
   response = {
@@ -111,6 +115,38 @@ export default class extends Vue {
   created () {
     this.query = location.href.split('/')[location.href.split('/').length - 1] // 获取id
     this.getWordInfor()
+    this.getBindPhone()
+  }
+
+  validator (val: any) {
+    console.log(val)
+    if (this.tel === '') {
+      return true
+    }
+    return this.regPhoneExg.test(val)
+  }
+
+  // 判断按钮是否可以点击
+  iptValue () {
+    let bool = this.validator(this.tel)
+    if (this.tel === '') {
+      bool = true
+    } else {
+      bool = false
+    }
+    if (this.checked === true && bool === true) {
+      this.btnChecked = true
+    } else {
+      this.btnChecked = false
+    }
+  }
+
+  // 获取绑定的手机号
+  getBindPhone () {
+    this.getAccountInfo().then((res: any) => {
+      console.log(res)
+      this.tel = res.data.phone
+    })
   }
 
   // 文档信息
@@ -147,18 +183,6 @@ export default class extends Vue {
     })
   }
 
-  phoneRules = [{
-    validator: (val: string) => {
-      const status = regPhoneExg.test(val)
-      if (val === '') {
-        console.log(true)
-        return true
-      }
-      return status
-    },
-    message: '手机号格式错误'
-  }]
-
   // 剑鱼文库线上购买及服务条款
   clause () {
     this.$router.push('/onlineterm')

+ 17 - 14
jydocs-mobile/src/views/user/Library.vue

@@ -22,11 +22,9 @@
             <Card
               v-for="(item, index) in myLibListState.list"
               :key="index"
-              :title="item.docName"
-              :desc="item.docSummary"
-              :docType="item.docFileType"
-              :price="item.price"
-              :subInfo="calcSubInfo(item)"
+              :title="item.DocName"
+              :docType="item.DocFileType"
+              :subInfo="calcSubInfoForLib(item)"
               @onClick="toDocDetail(item)"
             />
           </div>
@@ -47,11 +45,11 @@
             <Card
               v-for="(item, index) in myCollectionListState.list"
               :key="index"
-              :title="item.docName"
-              :desc="item.docSummary"
-              :docType="item.docFileType"
-              :price="item.price"
-              :subInfo="calcSubInfo(item)"
+              :title="item.DocName"
+              :desc="item.DocSummary"
+              :docType="item.DocFileType"
+              :price="item.Cost"
+              :subInfo="calcSubInfoForColl(item)"
               @onClick="toDocDetail(item)"
             />
           </div>
@@ -67,7 +65,7 @@ import { Tabs, Tab, List } from 'vant'
 import { mapState, mapMutations, mapActions } from 'vuex'
 import Card from '@/components/docs-card/Card.vue'
 import Empty from '@/components/common/Empty.vue'
-import { dateFormatter } from '@/utils/globalFunctions'
+import { dateFormatter, formatSize } from '@/utils/globalFunctions'
 
 @Component({
   name: 'user-library',
@@ -165,9 +163,14 @@ export default class UserLibrary extends Vue {
     })
   }
 
-  calcSubInfo (item: any) {
-    const { uploadDate, downTimes } = item
-    return [dateFormatter(uploadDate, 'yyyy/MM/dd'), `${downTimes}次下载`]
+  calcSubInfoForLib (item: any) {
+    const { UpdateAt, DocFileSize } = item
+    return [`${dateFormatter(UpdateAt * 1000, 'yyyy/MM/dd')}下载`, formatSize(DocFileSize)]
+  }
+
+  calcSubInfoForColl (item: any) {
+    const { DocPageSize, DocFileSize } = item
+    return [`共${DocPageSize}页`, formatSize(DocFileSize)]
   }
 
   async onLoad () {

+ 4 - 7
jydocs-mobile/vue.config.js

@@ -29,7 +29,7 @@ const cdn = {
     '//cdn.jsdelivr.net/npm/axios@0.19.2/dist/axios.min.js',
     '//cdn.jsdelivr.net/npm/js-cookie@2.2.1/src/js.cookie.min.js',
     '//cdn.jsdelivr.net/npm/moment@2.26.0/moment.min.js',
-    // '//res.wx.qq.com/open/js/jweixin-1.6.0.js'
+    '//res.wx.qq.com/open/js/jweixin-1.6.0.js'
   ]
 }
 
@@ -53,13 +53,10 @@ module.exports = {
           '^/dev/api': '/jydocs'
         }
       },
-      '^/jydocs': {
-        target: '192.168.20.180:821',
+      '^/jypay': {
+        target: 'http://192.168.20.145:86',
         changeOrigin: true,
-        logLevel: 'debug',
-        pathRewrite: {
-          '^/jydocs': '/jydocs'
-        }
+        logLevel: 'debug'
       }
     }
   },

+ 10 - 0
jydocs-mobile/yarn.lock

@@ -1001,6 +1001,11 @@
   resolved "https://registry.npm.taobao.org/@types/normalize-package-data/download/@types/normalize-package-data-2.4.0.tgz#e486d0d97396d79beedd0a6e33f4534ff6b4973e"
   integrity sha1-5IbQ2XOW15vu3QpuM/RTT/a0lz4=
 
+"@types/pdfjs-dist@^2.7.0":
+  version "2.7.0"
+  resolved "https://registry.npm.taobao.org/@types/pdfjs-dist/download/@types/pdfjs-dist-2.7.0.tgz#2fca369320ce87c0a0d09e1fc7840adb5ae7de68"
+  integrity sha1-L8o2kyDOh8Cg0J4fx4QK21rn3mg=
+
 "@types/q@^1.5.1":
   version "1.5.4"
   resolved "https://registry.npm.taobao.org/@types/q/download/@types/q-1.5.4.tgz#15925414e0ad2cd765bfef58842f7e26a7accb24"
@@ -6942,6 +6947,11 @@ pbkdf2@^3.0.3:
     safe-buffer "^5.0.1"
     sha.js "^2.4.8"
 
+pdfjs-dist@^2.6.347:
+  version "2.6.347"
+  resolved "https://registry.npm.taobao.org/pdfjs-dist/download/pdfjs-dist-2.6.347.tgz#f257ed66e83be900cd0fd28524a2187fb9e25cd5"
+  integrity sha1-8lftZug76QDND9KFJKIYf7niXNU=
+
 performance-now@^2.1.0:
   version "2.1.0"
   resolved "https://registry.npm.taobao.org/performance-now/download/performance-now-2.1.0.tgz#6309f4e0e5fa913ec1c69307ae364b4b377c9e7b"

+ 0 - 1
jydocs-pc/package.json

@@ -13,7 +13,6 @@
     "axios": "^0.21.1",
     "core-js": "^3.4.3",
     "element-ui": "^2.15.1",
-    "pdfh5": "^1.3.20",
     "pdfjs-dist": "^2.6.347",
     "single-spa-vue": "^1.5.4",
     "systemjs-webpack-interop": "^1.1.2",

+ 4 - 4
jydocs-pc/src/api/modules/detail.js

@@ -11,7 +11,7 @@ export function getDetails (data) {
   return request({
     url: '/detail',
     method: 'post',
-    data: data
+    data
   })
 }
 
@@ -19,7 +19,7 @@ export function getShow (data) {
   return request({
     url: '/getShow',
     method: 'post',
-    data: data
+    data
   })
 }
 
@@ -27,7 +27,7 @@ export function getDown (data) {
   return request({
     url: '/getDown',
     method: 'post',
-    data: data
+    data
   })
 }
 
@@ -35,7 +35,7 @@ export function getAdverse (data) {
   return request({
     url: '/getAdvertisement',
     method: 'post',
-    data: data
+    data
   })
 }
 

+ 11 - 0
jydocs-pc/src/api/modules/purchase.js

@@ -37,3 +37,14 @@ export function getDetails (data) {
     data: data
   })
 }
+
+// 获取已绑定的手机号
+export function getBindPhone (data) {
+  data = qs.stringify(data)
+  return request({
+    baseURL: '',
+    url: '/jypay/user/getAccountInfo',
+    method: 'post',
+    data: data
+  })
+}

BIN
jydocs-pc/src/assets/images/icon/ipt_corret.jpg


BIN
jydocs-pc/src/assets/images/icon/ipt_error.jpg


+ 3 - 0
jydocs-pc/src/components/doc-item-card/Card.vue

@@ -168,6 +168,9 @@ export default {
     }
     .card-title {
       line-height: 24px;
+      em {
+        color: $color-text--highlight;
+      }
     }
   }
 

+ 7 - 1
jydocs-pc/src/utils/globalFunctions.js

@@ -245,7 +245,13 @@ export function docTypeConvert (docType = 'pdf') {
     xls: 'excel',
     xlsx: 'excel',
     ppt: 'ppt',
-    pdf: 'pdf'
+    pdf: 'pdf',
+    1: 'word', // doc
+    2: 'pdf',
+    3: 'excel', // xls
+    4: 'ppt',
+    5: 'txt',
+    6: '其他'
   }
   const type = typeMap[docType]
   return type || docType // map中不存在的,则返回原始类型

+ 39 - 29
jydocs-pc/src/views/Content.vue

@@ -12,13 +12,13 @@
                       <li>{{datas.viewTimes}}次浏览<el-divider direction="vertical"></el-divider></li>
                       <li>{{datas.downTimes}}次下载<el-divider direction="vertical"></el-divider></li>
                       <li>共{{datas.docPageSize}}页<el-divider direction="vertical"></el-divider></li>
-                      <li>{{datas.docFileSize}}k<el-divider direction="vertical"></el-divider></li>
-                      <li class="no-line">{{datas.uploadDate | dateFormatter}}上传</li>
+                      <li>{{datas.docFileSize}}<el-divider direction="vertical"></el-divider></li>
+                      <li class="no-line">{{datas.uploadDate}}上传</li>
                   </ul>
                   <div class="coin"><i class="el-icon-jy-iconJianYu"></i><span>{{datas.price}}</span></div>
               </div>
-              <div class="buyed" v-if="buyed">您已兑换过该文档,可直接下载</div>
-              <div class="buyed no-buyed" v-else-if="datas.price > coinNum && !buyed">剑鱼币余额不足,现有 {{coinNum}} 剑鱼币,还需 {{datas.price - coinNum}} 剑鱼币,请先充值</div>
+              <div class="buyed" v-if="buyed == 1">您已兑换过该文档,可直接下载</div>
+              <div class="buyed no-buyed" v-else-if="datas.price > coinNum && buyed == 0">剑鱼币余额不足,现有 {{coinNum}} 剑鱼币,还需 {{datas.price - coinNum}} 剑鱼币,请先充值</div>
               <el-divider class="heng-line" v-else></el-divider>
               <div class="load-doc">
                   <el-button type="primary" @click="loadFile">{{btnName}}</el-button>
@@ -39,17 +39,17 @@
           </div>
           <div class="middles">
               <h3>摘要</h3>
-              <p>{{datas.docSummary}}</p>
-              <div class="continue" v-show="!buyed">全文共18页,<span @click="continued">继续阅读<i class="el-icon-arrow-down"></i></span></div>
+              <p>{{datas.docSummary + datas.docSummary.length >= 500 ? '...' : ''}}</p>
+              <div class="continue" v-show="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="head-tip" id="fixedTop" :class="{'is-fixed':fixed}" v-show="buyed == 1">
                 <h3 v-show="fixed">
                 <i :class="'el-icon-jy-' + fileType(datas.docFileType)"></i>
                 <span>{{datas.docName}}</span>
                 </h3>
                 <span class="pages"><i id="page_num"></i> / <i id="page_count"></i></span>
           </div>
-          <div class="bottoms" id="colWidth" v-show="buyed">
+          <div class="bottoms" id="colWidth" v-show="buyed == 1">
               <div class="page">
                   <div class="cont-p" id="pdfPage"></div>
               </div>
@@ -75,9 +75,9 @@
       </div>
       <div class="d-right">
           <div class="r-tops">
-              <router-link v-for="item in adsUrl" :key="item.s_pic" :to="item.s_link">
+              <a :href="item.s_link" v-for="item in adsUrl" :key="item.s_pic">
                 <img :src="item.s_pic">
-              </router-link>
+              </a>
           </div>
       </div>
   </div>
@@ -86,6 +86,7 @@
 <script>
 import { Button, Tooltip, Divider, Message } from 'element-ui'
 import { getDetails, getShow, getDown, getAdverse, getCoin, getAdd, getRemove } from '../api/modules/detail'
+import { formatSize, dateFormatter } from '@/utils/'
 const pdfjsLib = require('pdfjs-dist/build/pdf.js')
 const pdfjsViewer = require('pdfjs-dist/web/pdf_viewer.js')
 export default {
@@ -104,7 +105,7 @@ export default {
       adsUrl: [],
       coinNum: 0,
       btnName: '',
-      buyed: false,
+      buyed: 0,
       collectd: 0,
       offsetTop: 0,
       offsetWidth: 0,
@@ -126,7 +127,6 @@ export default {
   },
   created () {
     this.docIds = this.$route.params.id
-    // this.docIds = '19d53d64-8890-11eb-8699-0050568f51e7'
     this.locaHref = window.location.origin
     this.setTop()
     this.adverse()
@@ -205,21 +205,20 @@ export default {
         }
       }
     },
-    details () {
-      getDetails({ docId: this.docIds, from: this.$route.query.from }).then(res => {
-        console.log(res)
+    buyShow () {
+      getShow({ docId: this.docIds }).then(res => {
         if (res.data.error_code === 0) {
-          this.datas = res.data.data.detail
-          this.datas.tags = this.datas.tags.split(',')
-          this.buyed = !!(res.data.data.status)
-          this.collectd = res.data.data.collect
+          this.conts = res.data
+          this.init()
         }
       })
+    },
+    coined () {
       getCoin({ B: true }).then(res => {
-        console.log(res.data, '111111')
         if (res.data.error_code === 0) {
           this.coinNum = res.data.data.points.balance
-          if (this.buyed) {
+          console.log(this.buyed)
+          if (this.buyed === 1) {
             this.btnName = '下载文档'
           } else {
             if (this.coinNum < this.datas.price) {
@@ -230,16 +229,27 @@ export default {
           }
         }
       })
-      getShow({ docId: this.docIds }).then(res => {
+    },
+    details () {
+      getDetails({ docId: this.docIds, from: this.$route.query.from }).then(res => {
         if (res.data.error_code === 0) {
-          this.conts = res.data
-          this.init()
+          this.datas = res.data.data.detail
+          this.datas.docFileSize = formatSize(this.datas.docFileSize)
+          this.datas.uploadDate = dateFormatter(this.datas.uploadDate, 'yyyy-MM-ss')
+          this.datas.tags = this.datas.tags.split(',')
+          this.buyed = res.data.data.status
+          console.log(res.data.data.status)
+          this.coined()
+          if (res.data.data.status === 1) {
+            this.buyShow()
+          }
+          this.collectd = res.data.data.collect
         }
       })
     },
     adverse () {
-      getAdverse({ code: this.docIds, num: 1 }).then(res => {
-        console.log(res)
+      getAdverse({ code: 'jydoc-content-right', num: 1 }).then(res => {
+        console.log(res.data.data)
         this.adsUrl = res.data.data
       })
     },
@@ -282,7 +292,7 @@ export default {
       this.loadFile()
     },
     loadFile () {
-      if (this.buyed) {
+      if (this.buyed === 1) {
         getDown({ docId: this.docIds }).then(res => {
           if (res.data.error_code === 0) {
             window.location.href = res.data.data
@@ -290,9 +300,9 @@ export default {
         })
       } else {
         if (this.coinNum < this.datas.price) {
-          window.location.href = '/page_points/recharge?id=' + this.datas.docId
+          window.location.href = '/swordfish/integral/index/recharge?id=' + this.datas.docId
         } else {
-          this.$router.push({ name: 'purchase', params: { id: this.datas.docId } })
+          this.$router.push('/purchase/' + this.datas.docId)
         }
       }
     },

+ 63 - 7
jydocs-pc/src/views/purchase/purchase.vue

@@ -41,7 +41,12 @@
         </div>
         <div class="doc_bindphone">
           <div class="phone_label">手机号码</div>
-          <input type="text" :value="tel" placeholder="请输入您的手机号码"  class="phone_ipt">
+          <el-input v-model="tel" @input="getValue()" placeholder="请输入您的手机号码" class="phone_ipt"></el-input>
+          <!-- <input type="text" :value="tel"   placeholder="请输入您的手机号码"  class="phone_ipt"> -->
+          <p class="phone_tips" v-show="setShow" >
+            <span class="icon_error"></span>
+            <span class="tip_text">手机号格式不正确</span>
+          </p>
         </div>
         <div class="doc_balance">
           <span class="balance_label">剑鱼币余额:</span>
@@ -58,7 +63,7 @@
           <el-checkbox v-model="checked" >我已阅读并同意<a href="/front/staticPage/serviceterms.html" class="agree_link">《剑鱼标讯线上购买与服务条款》</a></el-checkbox>
         </div>
         <div class="doc_surepur">
-          <button class="btnsure" @click="setExhange()" :disabled="!this.checked" id="btnsure">确定兑换</button>
+          <button class="btnsure" @click="setExhange()" :disabled="!this.btnChecked" id="btnsure">确定兑换</button>
         </div>
       </div>
     </div>
@@ -66,19 +71,23 @@
 </template>
 
 <script>
-import { checkbox } from 'element-ui'
-import { getDocPays, getJYchannel, getDetails } from '../../api/modules/purchase'
+import { checkbox, input } from 'element-ui'
+import { getDocPays, getJYchannel, getDetails, getBindPhone } from '../../api/modules/purchase'
 
 export default {
   name: 'purchasePage',
   components: {
-    [checkbox.name]: checkbox
+    [checkbox.name]: checkbox,
+    [input.name]: input
   },
   data () {
     return {
       checked: true,
+      phoneChecked: true,
+      btnChecked: true,
       query: '',
       tel: '',
+      setShow: false,
       response: {
         docName: '',
         price: '',
@@ -119,6 +128,10 @@ export default {
           this.response.channel = res.data.data.points.balance
         }
       })
+      getBindPhone().then((res) => {
+        console.log(res)
+        this.tel = res.data.data.phone
+      })
     },
     // 确定兑换
     setExhange () {
@@ -129,6 +142,27 @@ export default {
           this.$router.push('/purchasesuccess/' + this.response.price)
         }
       })
+    },
+    // 手机号输入事件
+    getValue () {
+      var regex = /^(0|\+?86|17951)?(13[0-9]|15[012356789]|17[013678]|18[0-9]|14[57])[0-9]{8}$/
+      var bool = regex.test(this.tel)
+      if (bool || this.tel === '') {
+        this.setShow = false
+        this.phoneChecked = true
+      } else {
+        this.setShow = true
+        this.phoneChecked = false
+      }
+      this.btnSure()
+    },
+    // 判断按钮是否可以点击
+    btnSure () {
+      if (this.checked === true && this.phoneChecked === true) {
+        this.btnChecked = true
+      } else {
+        this.btnChecked = false
+      }
     }
   }
 }
@@ -275,6 +309,7 @@ export default {
         }
       }
       .doc_bindphone{
+          position: relative;
         display: flex;
         align-items: center;
         margin-top: 21px;
@@ -289,19 +324,40 @@ export default {
           padding: 6px 10px;
           margin-left: 64px;
           width: 570px;
-          height: 36px;
+          // height: 36px;
           border-radius: 4px;
           background: #FFFFFF;
           border: none;
           outline: none;
           box-shadow:none;
-          border: 1px solid #E0E0E0;
+          // border: 1px solid #E0E0E0;
+          .el-input__inner{
+            height: 36px;
+          }
         }
         .phone_ipt::placeholder{
           color: #AAAAAA;
           font-size: 14px;
           line-height: 36px;
         }
+        .phone_tips{
+          display: flex;
+          align-items: center;
+          position: absolute;
+          right: 286px;
+          .icon_error{
+            margin-right: 4px;
+            display: flex;
+            width: 16px;
+            height: 16px;
+            background: url(data:image/jpg;base64,/9j/4AAQSkZJRgABAQAAAQABAAD/2wBDAAMCAgMCAgMDAwMEAwMEBQgFBQQEBQoHBwYIDAoMDAsKCwsNDhIQDQ4RDgsLEBYQERMUFRUVDA8XGBYUGBIUFRT/2wBDAQMEBAUEBQkFBQkUDQsNFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBT/wAARCAAwADADASIAAhEBAxEB/8QAGQABAAMBAQAAAAAAAAAAAAAACAAFBwEJ/8QALhAAAQMDAQYFBAMBAAAAAAAAAQIDBAUGEQAIEiExYYETIiVRcQdDkbEys/BB/8QAFwEAAwEAAAAAAAAAAAAAAAAABAUHBv/EAC0RAAEBBAcHBQEAAAAAAAAAAAECAAMREgQFBhMxQYEUFSEyUZHBFiJiofCS/9oADAMBAAIRAxEAPwD1T1VXFdNKtKAZlXnNQY/IFw+ZZ9kpHFR6AHUum44lpW/Nq004jxkbxA5qPJKR1JIHfQvu27qt9QrgVMmrcfedXuR4zeVJbBPlbQn8dSeugaTSQ4EBxJbYWfs+uuVqePFSuk4nMnoPJybdKvtU0mM8pFNosqcgHHiPupYB6gAKP5xqUnappUh1KajRJUJB5rYdS9jsQnRzqFNl0mY5EnRnocpv+bL6Chaf+jIPHUp1Nl1eY3EgxnpkpzO4ywgrWrAycAceWlG2v5sdINUfSVS3UZOEOaY98YfTOi3LppV208TaTNbmxzwJRwUk+ykniD0I1a6DVo3dVfp9cCJsJa2Xml7j8ZeUpdSDxQtP56g9dNC1rii3bb8GrwzliU2FhJOSg8lJPUEEH403o1JD8QPAhpdaCz66mWlbtUzpWBzB6Hwc2yPapqzke36JTkqwiVIW8se/hpAH9mjnTahIpFQjTornhSYzqXml4zuqScg4+RpGbVNIck2/RakhJUiJIWyvA5BxIIJ7t476OdNp8irVCNBiN+LKkupZaQDjeUo4Ayep0ops20HSDVGyV1uVEYQ903c46QZAejbRts/apl5wW/gLH7LZPdJPXzT0bZytn7VTvOc38hA/YbB7qI6eWejbOVs/aqd5zm/kIH7DYPdRHTyz0baNtn7VMvOC38BY/ZbJ7pJ6+Yvtew/atlf63dN++V3N+ix/qVQkVeoSZ0pzxZMl1Tzq8Y3lKOScfJ0jNlaruSbfrVNWoqREkIeRk8g4kggd2899HOo09+k1CTBlN+FJjOqZdRkHdWkkEZHUaReytSXI9v1uoqThEqQhlB9/DSSf7NCUKa/GsW1Vrbrcq4Qh7Ze4w0i2u3TbsW7bfnUiYMsSmygqAyUHmlQ6ggHtoXXfaNV+n9wLgzULZeaXvMSUZCXUg8FoP+IPDnpzaqrjtalXdTzCq8JubHPEBfBST7pUOKT1B03pNGD8RHAhpdZ+0C6mWpDxMzpWIzB6jyM2C06oSqpKXJmyXpclf83n3CtavknidSBUZdKlolQpT0OSjO69HcKFpyMHChxGkZVtlalSHVKp1blQkHkh9pL2O4KddpGytSozyV1KtSpyAc+GwylgHoSSo/jSjYqRNhrFqj6tqW65zhyynthD7bCrQtCq3/X0QYLa3nXFbz8heSlpJPFaz/iTy46aNrW5EtG34VJhDEeMjdBPNR5qUepJJ765blrUq0aeIVIgtQmBxIQPMs+6lHio9SdW2m9GowcCJ4ktLrQWgXXKw7diV0nAZk9T4GTf/9k=) no-repeat;
+            background-size: contain;
+          }
+          .tip_text{
+            font-size: 14px;
+            color: #FF3A20;
+          }
+        }
       }
       .doc_balance{
         margin-top: 20px;

+ 2 - 0
jydocs-pc/vue.config.js

@@ -9,6 +9,7 @@ module.exports = {
     disableHostCheck: true,
     proxy: {
       '^/jydocs': {
+        // target: 'http://web2-jytest.jydev.jianyu360.com',
         target: 'http://192.168.20.180:821',
         changeOrigin: true,
         logLevel: 'debug',
@@ -17,6 +18,7 @@ module.exports = {
         }
       },
       '^/jyintegral': {
+        // target: 'http://web2-jytest.jydev.jianyu360.com',
         target: 'http://192.168.20.145:820',
         changeOrigin: true,
         logLevel: 'debug',