Browse Source

Merge branch 'master' of jianyu/jy-docs into tsz

汤世哲 4 năm trước cách đây
mục cha
commit
c71c80bed9
63 tập tin đã thay đổi với 1400 bổ sung162 xóa
  1. BIN
      jydocs-mobile/src/assets/icon/Union.png
  2. BIN
      jydocs-mobile/src/assets/icon/choose.png
  3. BIN
      jydocs-mobile/src/assets/icon/dataJianyubi.png
  4. BIN
      jydocs-mobile/src/assets/icon/dateGetBg.png
  5. BIN
      jydocs-mobile/src/assets/icon/dateGetClick.png
  6. BIN
      jydocs-mobile/src/assets/icon/excel.png
  7. BIN
      jydocs-mobile/src/assets/icon/guanzhu.png
  8. BIN
      jydocs-mobile/src/assets/icon/iconGetToday.png
  9. BIN
      jydocs-mobile/src/assets/icon/iconGot.png
  10. BIN
      jydocs-mobile/src/assets/icon/iconJianYu.png
  11. BIN
      jydocs-mobile/src/assets/icon/iconLogoDark.png
  12. BIN
      jydocs-mobile/src/assets/icon/iconLogoLight.png
  13. BIN
      jydocs-mobile/src/assets/icon/iconUnGot.png
  14. BIN
      jydocs-mobile/src/assets/icon/jubao.png
  15. BIN
      jydocs-mobile/src/assets/icon/myicons.png
  16. BIN
      jydocs-mobile/src/assets/icon/pdf.png
  17. BIN
      jydocs-mobile/src/assets/icon/ppt.png
  18. BIN
      jydocs-mobile/src/assets/icon/qiandao.png
  19. BIN
      jydocs-mobile/src/assets/icon/search.png
  20. BIN
      jydocs-mobile/src/assets/icon/weiguanzhu.png
  21. BIN
      jydocs-mobile/src/assets/icon/word.png
  22. BIN
      jydocs-mobile/src/assets/icon/厂商资料.png
  23. BIN
      jydocs-mobile/src/assets/icon/技术文献.png
  24. BIN
      jydocs-mobile/src/assets/icon/招标文件.png
  25. BIN
      jydocs-mobile/src/assets/icon/法律法规.png
  26. BIN
      jydocs-mobile/src/assets/icon/行业报告.png
  27. BIN
      jydocs-mobile/src/assets/icon/行业标准.png
  28. BIN
      jydocs-mobile/src/assets/images/banner.png
  29. BIN
      jydocs-mobile/src/assets/images/bgApp.png
  30. BIN
      jydocs-mobile/src/assets/images/bgWechat.png
  31. BIN
      jydocs-mobile/src/assets/images/headText1.png
  32. BIN
      jydocs-mobile/src/assets/images/headText2.png
  33. BIN
      jydocs-mobile/src/assets/images/inviteActive.png
  34. BIN
      jydocs-mobile/src/assets/images/inviteHome.png
  35. BIN
      jydocs-mobile/src/assets/images/shareActive.png
  36. BIN
      jydocs-mobile/src/assets/images/shareHome.png
  37. 63 0
      jydocs-mobile/src/components/Search.vue
  38. 12 2
      jydocs-mobile/src/style/_mixin.scss
  39. 46 0
      jydocs-mobile/src/style/_variables.scss
  40. 172 70
      jydocs-mobile/src/views/Home.vue
  41. 1 1
      jydocs-pc/.env.alone
  42. 1 1
      jydocs-pc/.env.development
  43. 1 1
      jydocs-pc/.env.production
  44. 2 1
      jydocs-pc/.eslintrc.js
  45. 19 1
      jydocs-pc/public/index.html
  46. 29 0
      jydocs-pc/src/api/mock/search.json
  47. 16 0
      jydocs-pc/src/api/modules/search.js
  48. BIN
      jydocs-pc/src/assets/images/no-data.png
  49. 4 4
      jydocs-pc/src/assets/style/_mixin.scss
  50. 9 5
      jydocs-pc/src/assets/style/_variables.scss
  51. 0 28
      jydocs-pc/src/components/CardItem.vue
  52. 34 0
      jydocs-pc/src/components/NoData.vue
  53. 8 2
      jydocs-pc/src/components/Search.vue
  54. 233 0
      jydocs-pc/src/components/doc-item-card/Card.vue
  55. 32 0
      jydocs-pc/src/components/doc-item-card/Price.vue
  56. 3 0
      jydocs-pc/src/main.js
  57. 50 0
      jydocs-pc/src/utils/functions/limit-input-numbers.js
  58. 26 0
      jydocs-pc/src/utils/globalDirectives.js
  59. 31 0
      jydocs-pc/src/utils/globalFilters.js
  60. 305 0
      jydocs-pc/src/utils/globalFunctions.js
  61. 4 0
      jydocs-pc/src/utils/index.js
  62. 133 30
      jydocs-pc/src/views/Home.vue
  63. 166 16
      jydocs-pc/src/views/Search.vue

BIN
jydocs-mobile/src/assets/icon/Union.png


BIN
jydocs-mobile/src/assets/icon/choose.png


BIN
jydocs-mobile/src/assets/icon/dataJianyubi.png


BIN
jydocs-mobile/src/assets/icon/dateGetBg.png


BIN
jydocs-mobile/src/assets/icon/dateGetClick.png


BIN
jydocs-mobile/src/assets/icon/excel.png


BIN
jydocs-mobile/src/assets/icon/guanzhu.png


BIN
jydocs-mobile/src/assets/icon/iconGetToday.png


BIN
jydocs-mobile/src/assets/icon/iconGot.png


BIN
jydocs-mobile/src/assets/icon/iconJianYu.png


BIN
jydocs-mobile/src/assets/icon/iconLogoDark.png


BIN
jydocs-mobile/src/assets/icon/iconLogoLight.png


BIN
jydocs-mobile/src/assets/icon/iconUnGot.png


BIN
jydocs-mobile/src/assets/icon/jubao.png


BIN
jydocs-mobile/src/assets/icon/myicons.png


BIN
jydocs-mobile/src/assets/icon/pdf.png


BIN
jydocs-mobile/src/assets/icon/ppt.png


BIN
jydocs-mobile/src/assets/icon/qiandao.png


BIN
jydocs-mobile/src/assets/icon/search.png


BIN
jydocs-mobile/src/assets/icon/weiguanzhu.png


BIN
jydocs-mobile/src/assets/icon/word.png


BIN
jydocs-mobile/src/assets/icon/厂商资料.png


BIN
jydocs-mobile/src/assets/icon/技术文献.png


BIN
jydocs-mobile/src/assets/icon/招标文件.png


BIN
jydocs-mobile/src/assets/icon/法律法规.png


BIN
jydocs-mobile/src/assets/icon/行业报告.png


BIN
jydocs-mobile/src/assets/icon/行业标准.png


BIN
jydocs-mobile/src/assets/images/banner.png


BIN
jydocs-mobile/src/assets/images/bgApp.png


BIN
jydocs-mobile/src/assets/images/bgWechat.png


BIN
jydocs-mobile/src/assets/images/headText1.png


BIN
jydocs-mobile/src/assets/images/headText2.png


BIN
jydocs-mobile/src/assets/images/inviteActive.png


BIN
jydocs-mobile/src/assets/images/inviteHome.png


BIN
jydocs-mobile/src/assets/images/shareActive.png


BIN
jydocs-mobile/src/assets/images/shareHome.png


+ 63 - 0
jydocs-mobile/src/components/Search.vue

@@ -0,0 +1,63 @@
+<template>
+  <van-sticky :offset-top="Offset">
+    <van-search class="my-search" left-icon="diy-search" v-model.trim="input" placeholder="搜索文档" />
+  </van-sticky>
+</template>
+
+<script lang="ts">
+import { Component, Vue, Prop } from 'vue-property-decorator'
+import { Icon, Search, Sticky } from 'vant'
+
+// @ is an alias to /src
+  @Component({
+    name: 'Search',
+    components: {
+      [Search.name]: Search,
+      [Sticky.name]: Sticky,
+      [Icon.name]: Icon
+    }
+  })
+export default class Empty extends Vue {
+    @Prop({ default: 'empty-image' }) state?: string | undefined;
+    input = ''
+
+    get Offset () {
+      const tempN = document.querySelector('.j-header.jy-app-header') as HTMLDivElement
+      if (tempN) {
+        return tempN.offsetHeight
+      } else {
+        return 0
+      }
+    }
+}
+</script>
+
+<style scoped lang="scss">
+.my-search {
+  &::v-deep.van-search {
+    padding: 7px 16px;
+    .van-search__content {
+      border-radius: 8px;
+      background: #F5F6F7;
+      border: 1px solid rgba(0, 0, 0, 0.05);
+    }
+    .van-cell {
+      align-items: center;
+      height: 38px;
+    }
+    .van-field__left-icon {
+      height: 20px;
+      margin-right: 8px;
+    }
+    .van-field__control {
+      color: #171826;
+      font-family: PingFang SC;
+      font-size: 14px;
+      letter-spacing: 0px;
+      text-align: left;
+    }
+  }
+
+  @include diy-icon('search', 20, 20)
+}
+</style>

+ 12 - 2
jydocs-mobile/src/style/_mixin.scss

@@ -89,7 +89,7 @@
     }
 }
 
-// clearfix 
+// clearfix
 @mixin clr {
     &:after {
         clear: both;
@@ -205,4 +205,14 @@
             }
         }
     }
-}
+}
+
+@mixin diy-icon ($name, $width: 24, $height: 24) {
+  ::v-deep .van-icon-diy-#{$name} {
+    background: url("~@/assets/icon/#{$name}.png") no-repeat;
+    background-size: cover;
+    display: inline-block;
+    width: #{$width}px;
+    height: #{$height}px;
+  }
+}

+ 46 - 0
jydocs-mobile/src/style/_variables.scss

@@ -1,6 +1,8 @@
 $tabbarHeight: 50px;
 $topNavHeight: 44px;
 
+$topSearchHeight: 54px;
+
 // 颜色区(背景颜色或者字体颜色)
 $color_main: #2ABED1;
 $color_warning: #FF9F40;
@@ -10,3 +12,47 @@ $color_danger: #FB483D;
   @return $a + $b;
 }
 
+
+.flex {
+  width: 100%;
+  flex: 1;
+}
+.flex-r-c {
+  display: flex;
+  flex-direction: row;
+  justify-content: space-between;
+  &.center {
+    align-items: center;
+    justify-content: center;
+    &.sb {
+      justify-content: space-between;
+    }
+  }
+  &.left {
+    justify-content: flex-start;
+  }
+  &.right {
+    justify-content: flex-start;
+  }
+  .bottom {
+    align-items: flex-end;
+  }
+  &.wrap {
+    flex-wrap: wrap;
+  }
+}
+.flex-c-c {
+  display: flex;
+  flex-direction: column;
+  justify-content: space-between;
+  &.center {
+    align-items: center;
+    justify-content: center;
+  }
+  &.right {
+    align-items: flex-end;
+  }
+  &.left {
+    align-items: flex-start;
+  }
+}

+ 172 - 70
jydocs-mobile/src/views/Home.vue

@@ -1,100 +1,202 @@
 <template>
-  <div class="users-page">
-    剑鱼文库首页
-    <!-- <div class="balance">
-      <div class="cumulative-sales balance-div">
-        <div class="sales-num balance-num">
-          <span class="money">¥</span>
-          <span class="money-num">{{ pageData.dis_sales | moneyLocal }}</span>
-        </div>
-        <span class="sales-text balance-text">累计销售</span>
+  <div class="pages--home">
+    <search></search>
+    <div class="new-group base-group">
+      <div class="title-group flex-r-c center left">
+        <span></span>
+        <h5>最新文档</h5>
       </div>
-      <div class="accumulated-commission balance-div">
-        <div class="commission-num balance-num">
-          <span class="money">¥</span>
-          <span class="money-num">{{ pageData.dis_commission | moneyLocal }}</span>
+      <div class="list-group flex-c-c">
+        <div class="list-item flex-r-c" v-for="item in pageData.new" :key="item.id" @click="goContent(item)">
+          <div class="flex flex-r-c center left">
+            <van-icon :name="'diy-' + item.type" />
+            <div class="flex">
+              <div class="van-ellipsis">{{item.title}}</div>
+            </div>
+          </div>
+          <div class="right-info flex-r-c center right">
+            <van-icon name="diy-iconJianYu" />
+            <span>{{item.money}}</span>
+          </div>
         </div>
-        <span class="commission-text balance-text">累计佣金</span>
       </div>
     </div>
-    <div class="commission">
-      <div style="display:flex;align-items:center;height:60px">
-        <span class="withdrawal"></span>
-        <div class="van-content">
-          <div class="van-left">
-            <div class="com-text">
-              <span class="wable">可提现佣金</span>
-              <span class="settlement">每月20号结算上月佣金</span>
+    <div class="hot-group base-group">
+      <div class="title-group flex-r-c center left">
+        <span></span>
+        <h5>热门下载</h5>
+      </div>
+      <div class="list-group flex-c-c">
+        <div class="list-item flex-r-c" v-for="item in pageData.new" :key="item.id" @click="goContent(item)">
+          <div class="flex flex-r-c center left">
+            <van-icon :name="'diy-' + item.type" />
+            <div class="flex">
+              <div class="van-ellipsis">{{item.title}}</div>
             </div>
           </div>
-          <div class="van-right">
-            <span class="money">¥</span>
-            <span class="com-money">{{ pageData.money | moneyLocal }}</span>
-            <a class="tixian" @click="goWithDraw" href="javascript:;">提现</a>
+          <div class="right-info flex-r-c center right">
+            <van-icon name="diy-iconJianYu" />
+            <span>{{item.money}}</span>
           </div>
         </div>
       </div>
-      <div style="display:flex;align-items:center;height:60px">
-        <span class="estimate"></span>
-        <div class="van-content">
-          <div class="van-left">
-            <div class="com-text">
-              <span class="wable">预估佣金</span>
-              <span class="settlement" v-if="pageData.partner_status !== 1">认证后预估佣金才能提现</span>
+    </div>
+    <div class="keep-group base-group">
+      <div class="title-group flex-r-c center left">
+        <span></span>
+        <h5>精选推荐</h5>
+      </div>
+      <div class="list-group flex-c-c">
+        <div class="list-item flex-r-c" v-for="item in pageData.new" :key="item.id" @click="goContent(item)">
+          <div class="flex flex-r-c center left">
+            <van-icon :name="'diy-' + item.type" />
+            <div class="flex">
+              <div class="van-ellipsis">{{item.title}}</div>
             </div>
           </div>
-          <div class="van-right">
-            <template>
-              <span class="estimate-money">¥</span>
-              <span class="estimate-money-num">{{ pageData.sum_commission | moneyLocal }}</span>
-            </template>
-            <div @click="goAuth" class="auth" href="javascript:;" v-if="canNeedAuth" :class="{stop: !canInAuth}">去认证</div>
+          <div class="right-info flex-r-c center right">
+            <van-icon name="diy-iconJianYu" />
+            <span>{{item.money}}</span>
           </div>
         </div>
       </div>
     </div>
-    <div class="options">
-      <router-link :to="item.to" class="option" v-for="(item, i) in navItem" :key="i" :class="item.className">
-        <span class="oicon"></span>
-        <div class="share-right">
-          <span class="share-text">{{item.name}}</span>
-          <van-icon name="arrow" />
-        </div>
-      </router-link>
-    </div> -->
   </div>
 </template>
 
 <script lang="ts">
 import { Component, Vue } from 'vue-property-decorator'
+import Search from '@/components/Search.vue'
 // import { Cell, CellGroup, Icon, Dialog, Toast } from 'vant'
+import { Icon } from 'vant'
 // import { mapActions } from 'vuex'
-// import { MixinTop } from '@/utils/mixin-top'
-
-@Component({
-  name: 'users',
-  // mixins: [MixinTop],
-  components: {
-    // [Cell.name]: Cell,
-    // [CellGroup.name]: CellGroup,
-    // [Icon.name]: Icon
-  },
-  methods: {
-    // ...mapActions({
-    //   ajaxData: 'main/getHome'
-    // })
-  }
-})
+  // import { MixinTop } from '@/utils/mixin-top'
+  @Component({
+    name: 'home',
+    // mixins: [MixinTop],
+    components: {
+      // [Cell.name]: Cell,
+      // [CellGroup.name]: CellGroup,
+      [Icon.name]: Icon,
+      Search
+    },
+    methods: {
+      // ...mapActions({
+      //   ajaxData: 'main/getHome'
+      // })
+    }
+  })
 
 export default class extends Vue {
-  // protected ajaxData: any
-  pageData: any = {}
+    // protected ajaxData: any
+    pageData: any = {}
 
-  created () {
-    console.log('111')
-  }
+    created () {
+      console.log('111')
+      this.pageData = {
+        new: [
+          {
+            type: 'pdf',
+            id: '1',
+            title: '优化招投标市场营商环境与国企优化招投标市场营商环境与国企...',
+            money: 200000
+          },
+          {
+            type: 'excel',
+            id: '2',
+            title: '优化招投标市场营商环境与国企优化招投标市场营商环境与国企...',
+            money: 200
+          },
+          {
+            type: 'word',
+            id: '3',
+            title: '优化招投标市场营商环境与国企优化招投标市场营商环境与国企...',
+            money: 200
+          },
+          {
+            type: 'ppt',
+            id: '4',
+            title: '优化招投标市场营商环境与国企优化招投标市场营商环境与国企...',
+            money: 200
+          },
+          {
+            type: 'other',
+            id: '5',
+            title: '优化招投标市场营商环境与国企优化招投标市场营商环境与国企...',
+            money: 200
+          }
+        ]
+      }
+    }
+
+    goContent (item: any) {
+      console.log(item)
+    }
 }
 </script>
-<style lang="scss">
+<style scoped lang="scss">
+.pages--home {
+  background: #F5F6F7;
+  padding-bottom: 40px;
+  box-sizing: border-box;
+
+  @include diy-icon('iconJianYu', 24);
+
+  @include diy-icon('pdf', 24);
+  @include diy-icon('word', 24);
+  @include diy-icon('excel', 24);
+  @include diy-icon('ppt', 24);
+
+  .base-group {
+    padding: 4px 19px 4px 16px;
+    box-sizing: border-box;
 
+    &.new-group {
+      margin-top: $topSearchHeight;
+    }
+
+    .list-group {
+      border-radius: 8px;
+      background: #FFFFFF;
+      padding: 8px 0;
+      box-sizing: border-box;
+      .list-item {
+        padding: 6px 12px;
+        box-sizing: border-box;
+        i {
+          flex-shrink: 0;
+          margin-right: 4px;
+        }
+        .flex {
+          min-width: 0;
+        }
+        .right-info {
+          margin-left: 4px;
+          flex-shrink: 0;
+        }
+      }
+    }
+
+    .title-group {
+      padding: 16px 0 6px 0;
+      margin-bottom: 4px;
+      box-sizing: border-box;
+      color: #171826;
+      font-family: PingFang SC;
+      font-size: 18px;
+      line-height: 26px;
+      letter-spacing: 0px;
+      text-align: left;
+
+      span {
+        display: inline-block;
+        width: 3px;
+        height: 16px;
+        border-radius: 11px;
+        background: #2ABED1;
+        margin-right: 8px;
+      }
+    }
+  }
+}
 </style>

+ 1 - 1
jydocs-pc/.env.alone

@@ -1,5 +1,5 @@
 NODE_ENV=development
-VUE_APP_BASE_API='/api-docs/'
+VUE_APP_BASE_API='/jydocs/'
 VUE_APP_BASE_URL='/'
 VUE_APP_MOCK=true
 VUE_APP_ALONE=true

+ 1 - 1
jydocs-pc/.env.development

@@ -1,5 +1,5 @@
 NODE_ENV=development
-VUE_APP_BASE_API='/api-docs/'
+VUE_APP_BASE_API='/jydocs/'
 VUE_APP_BASE_URL='/swordfish/docs/index'
 VUE_APP_MOCK=true
 VUE_APP_BASE_PUBLIC='http://localhost:8080/'

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

@@ -1,4 +1,4 @@
 NODE_ENV=production
-VUE_APP_BASE_API='/api-docs/'
+VUE_APP_BASE_API='/jydocs/'
 VUE_APP_BASE_URL='/swordfish/docs/index'
 VUE_APP_BASE_PUBLIC='/page_docs/'

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

@@ -8,7 +8,8 @@ module.exports = {
     '@vue/standard'
   ],
   globals: {
-    loginflag: true
+    loginflag: true,
+    $: true
   },
   parserOptions: {
     parser: 'babel-eslint'

+ 19 - 1
jydocs-pc/public/index.html

@@ -1,11 +1,29 @@
 <!DOCTYPE html>
-<html lang="en">
+<html>
   <head>
     <meta charset="utf-8">
     <meta http-equiv="X-UA-Compatible" content="IE=edge">
     <meta name="viewport" content="width=device-width,initial-scale=1.0">
     <link rel="icon" href="<%= BASE_URL %>favicon.ico">
     <title>app1</title>
+    <% if (process.env.NODE_ENV === 'development') { %>
+      <link href="https://web2-jytest.jianyu360.cn/css/bootstrap.min.css" rel="stylesheet">
+      <link href="https://web2-jytest.jianyu360.cn/css/bootswatch.min.css" rel="stylesheet">
+      <link href="https://web2-jytest.jianyu360.cn/css/font.css?v=6302" rel="stylesheet">
+      <link href="https://web2-jytest.jianyu360.cn/css/jy.css?v=6302" rel="stylesheet">
+      <link href="https://web2-jytest.jianyu360.cn/css/common.css?v=6302" rel="stylesheet">
+      <link href="https://web2-jytest.jianyu360.cn/css/animate.css" rel="stylesheet">
+      <link href="https://web2-jytest.jianyu360.cn/css/unicorn.main.css" rel="stylesheet" />
+      <link href="https://web2-jytest.jianyu360.cn/css/unicorn.grey.css" rel="stylesheet" />
+      <script src="https://web2-jytest.jianyu360.cn/js/jquery-3.2.1.min.js?v=6302"></script>
+      <script src="https://web2-jytest.jianyu360.cn/js/jquery.cookie.js"></script>
+      <script src="https://web2-jytest.jianyu360.cn/js/bootstrap.min.js"></script>
+
+      <link href='https://web2-jytest.jianyu360.cn/css/reset.css?v=6302' rel="stylesheet" type="text/css"/>
+      <link href='https://web2-jytest.jianyu360.cn/pccss/reset_pc.css' rel="stylesheet" type="text/css"/>
+      <link href='https://web2-jytest.jianyu360.cn/css/pc.css?v=6302' rel="stylesheet"/>
+      <link href='https://web2-jytest.jianyu360.cn/pccss/public-nav-1200.css?v=6302' rel="stylesheet" type="text/css"/>
+    <% } %>
   </head>
   <body>
     <noscript>

+ 29 - 0
jydocs-pc/src/api/mock/search.json

@@ -0,0 +1,29 @@
+{
+  "error_code": 0,
+  "error_msg": "",
+  "data": {
+    "total": 2,
+    "list": [
+      {
+        "docId": "RJ82241sM3DyHwrupW7w",
+        "docName": "软件单元、组装、确认测试系统-中标候选人公示",
+        "price": 359,
+        "docFileSize": 387,
+        "docPageSize": 5,
+        "uploadDate": "2021-03-17 15:46:04",
+        "docSummary": "公告软件单元、组装、确认测试系统-中标候选人公示(招标编号:ZKX20210231A002)公示开始时间:2021年01月28日09时00分00秒公示结束时间:2021年02月01日23时59分59秒本软件单元、组装、确认测试系统(招标项目",
+        "docFileType": "其他"
+      },
+      {
+        "docId": "PImyRKyNohbocfUbhIef",
+        "docName": "北京精密机电控制设备研究所软件单元、组装、确认测试系统",
+        "price": 193,
+        "docFileSize": 164,
+        "docPageSize": 3,
+        "uploadDate": "2021-03-17 15:46:05",
+        "docSummary": "1.招标条件本招标项目:软件单元、组装、确认测试系统已由中国航天科技集团有限公司部门批准建设,项目业主为北京精密机电控制设备研究所,建设资金及出资比例其他资金100.0%,招标人为北京精密机电控制设备研究所。项目已具备招标条件,中科信工程咨",
+        "docFileType": "pdf"
+      }
+    ]
+  }
+}

+ 16 - 0
jydocs-pc/src/api/modules/search.js

@@ -0,0 +1,16 @@
+import httpRequest from '@/api'
+import mockRequest from '@/api/mock'
+
+let request = httpRequest
+if (process.env.NODE_ENV === 'development' && process.env.VUE_APP_MOCK) {
+  // @ts-ignore
+  request = mockRequest
+}
+
+export function ajaxGetSearch (data) {
+  return request({
+    url: '/search',
+    method: 'post',
+    data
+  })
+}

BIN
jydocs-pc/src/assets/images/no-data.png


+ 4 - 4
jydocs-pc/src/assets/style/_mixin.scss

@@ -11,12 +11,12 @@
   @return $footerHeight + $a;
 }
 
-@mixin diy-icon ($name, $size: 24) {
-  .el-icon-jy-#{$name} {
+@mixin diy-icon ($name, $width: 24, $height: 24) {
+  ::v-deep .el-icon-jy-#{$name} {
     background: url("~@/assets/images/icon/#{$name}.png") no-repeat;
     background-size: cover;
     display: inline-block;
-    width: #{$size}px;
-    height: #{$size}px;
+    width: #{$width}px;
+    height: #{$height}px;
   }
 }

+ 9 - 5
jydocs-pc/src/assets/style/_variables.scss

@@ -17,12 +17,16 @@ $bg-color-6: linear-gradient(90deg, #7446A0 0%, #A380C4 100%);
 
 $font-text--title: 17px;
 
-$color-text--default: #ffffff;
-$color-text--active: #E9D596;
-$color-input--default: #BFBFBF;
-$color-text--highlight: #E9D596;
+$color-text--default: #1D1D1D;
+$color-text--active: #2CB7CA;
+$color-input--default: #1D1D1D;
+$color-text--highlight: #2CB7CA;
 
-$bg-main-color: #0D0F14;
+$bg-main-color: #fff;
+
+.highlight-text {
+  color: $color-text--highlight;
+}
 
 .flex {
   width: 100%;

+ 0 - 28
jydocs-pc/src/components/CardItem.vue

@@ -1,28 +0,0 @@
-<template>
-    <div class="card-item flex-r-c">
-        <img src="" alt="图片">
-        <div class="flex-c-c">
-            <span>优化招投标市场营商环境与国企采购人主体负责人责人.......</span>
-            <div class="flex-c-c">
-                <span>贡献者:xxx.......</span>
-                <span>2020次下载:xxx.......</span>
-            </div>
-            <span>500剑鱼币</span>
-        </div>
-    </div>
-</template>
-
-<script>
-export default {
-  name: 'Card-Item',
-  props: {
-    msg: String
-  }
-}
-</script>
-
-<style scoped lang="scss">
-    .card-item {
-
-    }
-</style>

+ 34 - 0
jydocs-pc/src/components/NoData.vue

@@ -0,0 +1,34 @@
+<template>
+  <div class="no-data">
+    <el-image :src="require('@/assets/images/no-data.png')"></el-image>
+    <div class="tip-text">
+      <slot><p>暂无数据</p></slot>
+    </div>
+  </div>
+</template>
+
+<script>
+import { Image } from 'element-ui'
+export default {
+  name: 'no-data',
+  components: {
+    [Image.name]: Image
+  }
+}
+</script>
+
+<style lang="scss" scoped>
+.no-data {
+  margin: 0 auto;
+  text-align: center;
+  .el-image {
+    width: 220px;
+  }
+  .tip-text {
+    margin-top: 14px;
+    color: #686868;
+    font-size: 16px;
+    line-height: 24px;
+  }
+}
+</style>

+ 8 - 2
jydocs-pc/src/components/Search.vue

@@ -50,10 +50,16 @@ export default {
       ]
     }
   },
-  beforeMount() {
+  beforeMount () {
     const qUrl = this.$route.query
-    qUrl && qUrl.text && (this.input = qUrl.text)
     qUrl && qUrl.type && (this.type = qUrl.type)
+    if (qUrl && qUrl.text) {
+      this.input = qUrl.text
+      this.$emit('recovery', {
+        type: this.type,
+        text: this.input
+      })
+    }
   },
   methods: {
     submitSearch () {

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

@@ -0,0 +1,233 @@
+<template>
+  <div class="docs-card-container" @click="clickCard">
+    <div class="docs-card hover flex-r-c" v-if="cardType === 'oneline'" key="docs-card">
+      <div class="docs-card-header flex-r-c flex">
+        <span class="card-title-icon" :class="docTypeIcon"></span>
+        <span class="card-title flex" v-html="hightLightTitle"></span>
+      </div>
+      <div class="subinfo-container">
+        <!-- 引用组件处如果使用了插槽。则会覆盖slot中的内容 -->
+        <slot name="default">
+          <span
+            class="subinfo-item noline"
+            :class="index === subInfo.length - 1 ? 'last' : ''"
+            v-for="(item, index) in subInfo"
+            :key="index"
+          >{{ item }}</span>
+        </slot>
+      </div>
+    </div>
+    <div class="docs-card hover flex-r-c" v-else-if="cardType === 'image'" key="docs-card">
+      <div class="image-container">
+        <el-image :src="imageSrc" lazy></el-image>
+        <span class="doc-type-icon" :class="docTypeIcon"></span>
+      </div>
+      <div class="image-info-container flex-c-c flex">
+        <div class="card-title">{{ title }}</div>
+        <div class="card-info">
+          <div class="card-info-item uploader" v-if="uploader">贡献者:{{ uploader }}</div>
+          <div class="card-info-item subinfo-container">
+            <span
+              class="subinfo-item"
+              :class="index === subInfo.length - 1 ? 'last' : ''"
+              v-for="(item, index) in subInfo"
+              :key="index"
+            >{{ item }}</span>
+          </div>
+          <div class="card-info-item price">
+            <Price :price="price" />
+          </div>
+        </div>
+      </div>
+    </div>
+    <div class="docs-card hover" v-else key="docs-card">
+      <div class="docs-card-header flex-r-c left">
+        <span class="card-title-icon" :class="docTypeIcon"></span>
+        <span class="card-title flex" v-html="hightLightTitle"></span>
+      </div>
+      <div class="docs-card-content">
+        <span class="card-desc" v-html="hightLightDesc"></span>
+      </div>
+      <div class="docs-card-footer flex-r-c">
+        <div class="c-f-left subinfo-container">
+          <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>
+        </div>
+        <div class="c-f-right flex-r-c">
+          <Price :price="price" />
+        </div>
+      </div>
+    </div>
+  </div>
+</template>
+
+<script>
+import { Image } from 'element-ui'
+import Price from '@/components/doc-item-card/Price'
+import { replaceKeyword } from '@/utils/'
+
+export default {
+  name: 'docs-card',
+  components: {
+    [Image.name]: Image,
+    Price
+  },
+  props: {
+    // online, image
+    cardType: {
+      type: String,
+      default: ''
+    },
+    highlightKey: {
+      type: Array,
+      default () {
+        return []
+      }
+    },
+    title: {
+      type: String,
+      required: true
+    },
+    desc: {
+      type: String,
+      default: ''
+    },
+    docType: {
+      type: String,
+      default: 'pdf'
+    },
+    subInfo: {
+      type: Array,
+      default () {
+        return []
+      }
+    },
+    imageSrc: {
+      type: String,
+      default: ''
+    },
+    uploader: {
+      type: String,
+      default: ''
+    },
+    price: {
+      type: [String, Number],
+      default: 0
+    }
+  },
+  computed: {
+    docTypeIcon () {
+      return `el-icon-jy-${this.docType}`
+    },
+    hightLightTitle () {
+      return replaceKeyword(this.title, this.highlightKey, [
+        '<span class="highlight-text">',
+        '</span>'
+      ])
+    },
+    hightLightDesc () {
+      return replaceKeyword(this.desc, this.highlightKey, [
+        '<span class="highlight-text">',
+        '</span>'
+      ])
+    }
+  },
+  methods: {
+    clickCard () {
+      this.$emit('onClick')
+    }
+  }
+}
+</script>
+
+<!-- Add "scoped" attribute to limit CSS to this component only -->
+<style lang="scss" scoped>
+.docs-card {
+  width: 100%;
+  padding: 18px;
+  font-size: 14px;
+  line-height: 24px;
+  border-bottom: 1px solid rgba($color: #000, $alpha: 0.05);
+  cursor: pointer;
+
+  @include diy-icon("word", 24);
+  @include diy-icon("excel", 24);
+  @include diy-icon("ppt", 24);
+  @include diy-icon("pdf", 24);
+
+  .docs-card-header {
+    font-size: 16px;
+    color: #1d1d1d;
+    .card-title-icon {
+      margin-right: 8px;
+    }
+    .card-title {
+      line-height: 24px;
+    }
+  }
+
+  .docs-card-content {
+    margin: 10px 0;
+    color: #686868;
+  }
+
+  .subinfo-container {
+    color: #999;
+    .subinfo-item {
+      position: relative;
+      margin-right: 16px;
+
+      &.noline:after,
+      &.last:after {
+        content: unset;
+      }
+
+      &:after {
+        content: "";
+        position: absolute;
+        top: 50%;
+        right: -8px;
+        margin-top: -6px;
+        width: 1px;
+        height: 12px;
+        background-color: rgba($color: #000, $alpha: 0.05);
+      }
+    }
+  }
+
+  .image-container {
+    position: relative;
+    width: 110px;
+    height: 150px;
+    border: 1px solid rgba($color: #000, $alpha: 0.05);
+    border-radius: 6px;
+    overflow: hidden;
+    .el-image {
+      width: 100%;
+      height: 100%;
+    }
+    .doc-type-icon {
+      position: absolute;
+      right: 2px;
+      bottom: 3px;
+    }
+  }
+  .image-info-container {
+    margin-left: 17px;
+    .card-info-item {
+      margin-top: 2px;
+    }
+  }
+
+  &.hover:hover {
+    background-color: #f5f6f7;
+    .card-title {
+      color: $color-text--highlight;
+    }
+  }
+}
+</style>

+ 32 - 0
jydocs-pc/src/components/doc-item-card/Price.vue

@@ -0,0 +1,32 @@
+<template>
+  <div class="price-container">
+    <span class="p-l el-icon-jy-iconLogoLight"></span>
+    <span class="p-r">{{ price }}</span>
+  </div>
+</template>
+
+<script>
+export default {
+  name: 'price',
+  props: {
+    price: {
+      type: [String, Number],
+      default: 0
+    }
+  }
+}
+</script>
+
+<style scoped lang="scss" scoped>
+.price-container {
+  display: flex;
+  align-items: center;
+  @include diy-icon("iconLogoLight", 24);
+
+  .p-r {
+    margin-left: 4px;
+    font-size: 18px;
+    color: #ff3a20;
+  }
+}
+</style>

+ 3 - 0
jydocs-pc/src/main.js

@@ -2,7 +2,10 @@ import Vue from 'vue'
 import App from './App.vue'
 import router from './router'
 import singleSpaVue from 'single-spa-vue'
+import { Loading } from 'element-ui'
+import '@/utils/'
 
+Vue.use(Loading.directive)
 Vue.config.productionTip = false
 
 const vueOptions = {

+ 50 - 0
jydocs-pc/src/utils/functions/limit-input-numbers.js

@@ -0,0 +1,50 @@
+// FROM: https://juejin.im/post/5b6b9308f265da0f4e62fecc
+// demo: http://192.168.3.207:10080/jianyu/page_h5/src/master/src/components/screen_price.vue
+// limit-input-number.js
+
+// 设置组件中的指定属性的值
+const setValue = function (exp, value, context) {
+  value = isNaN(value) ? '' : value
+  // eslint-disable-next-line
+  new Function ('context', 'value', `context.${exp} = value`)(context, value)
+}
+
+// 自定义指令
+export default {
+  bind (el, { expression }, { context }) {
+    // 初始化lastValue
+    el.lastValue = el.value
+    // 通过dataset 判断是否允许小数点
+    const allowDot = !!el.dataset.dotrange
+    const dotRange = el.dataset.dotrange || '{0,2}' // 默认
+    const pattern = `^[0-9]+${allowDot ? `(.[0-9]${dotRange})?` : ''}$`
+
+    if (!expression) {
+      throw new TypeError('请绑定expression')
+    }
+
+    el.handleInputEvent = function (e) {
+      setTimeout(() => {
+        if (e.target.value === '') {
+          setValue(expression, '', context)
+          // 遇到非法数值,则重置
+          e.target.value = ''
+        } else if (e.target.value !== '' && !new RegExp(pattern).test(e.target.value)) {
+          setValue(expression, parseFloat(e.target.lastValue), context)
+          // 遇到非法数值,则重置为lastValue
+          e.target.value = e.target.lastValue
+          if (allowDot) {
+            // 这个时候,根据业务逻辑,可以收起键盘,给出吐司提示
+            e.target.blur()
+            // context.showToast(`小数点后最多${dotRange.replace(/[}{]/g, '').split(',')[1]}位`)
+          }
+        }
+        e.target.lastValue = e.target.value
+      }, 0)
+    }
+    el.addEventListener('input', el.handleInputEvent, false)
+  },
+  unbind (el) {
+    el && el.removeEventListener('input', el.handleInputEvent, false)
+  }
+}

+ 26 - 0
jydocs-pc/src/utils/globalDirectives.js

@@ -0,0 +1,26 @@
+import Vue from 'vue'
+import limitInputNumbers from '@/utils/functions/limit-input-numbers'
+
+// 输入数字
+Vue.directive('limit-input-numbers', limitInputNumbers)
+
+// Vue自定义指令文档:https://cn.vuejs.org/v2/guide/custom-directive.html
+Vue.directive('auto-focus', {
+  // 当被绑定的元素插入到 DOM 中时……
+  inserted: function (el) {
+    const autoFocusArr = ['input', 'textarea']
+    const tagName = el.nodeName.toLowerCase()
+    const isTag = autoFocusArr.find((item) => {
+      return item === tagName
+    })
+
+    setTimeout(() => {
+      if (isTag) {
+        el.focus()
+      } else {
+        const dom = el.querySelector('.van-field__control')
+        dom.focus()
+      }
+    }, 30)
+  }
+})

+ 31 - 0
jydocs-pc/src/utils/globalFilters.js

@@ -0,0 +1,31 @@
+import Vue from 'vue'
+import {
+  dateFormatter,
+  dateFromNow,
+  addSpaceForTel,
+  upPrice,
+  formatPrice,
+  fen2Yuan,
+  addSpaceForBank,
+  addConfusionForBank
+} from './globalFunctions'
+
+// 注册全局过滤器
+// 时间格式化(同时间格式化函数)
+Vue.filter('dateFormatter', dateFormatter)
+// 时间戳转换 多少秒、多少分、多少小时前、多少天前  超出10天显示年月日
+Vue.filter('dateFromNow', dateFromNow)
+// 手机号加空格
+Vue.filter('addSpaceForTel', addSpaceForTel)
+
+// 分转元
+Vue.filter('fen2Yuan', fen2Yuan)
+// 金额大写
+Vue.filter('upPrice', upPrice)
+// 金额3位逗号分隔
+Vue.filter('formatPrice', formatPrice)
+
+// 银行卡号字符串加空格
+Vue.filter('addSpaceForBank', addSpaceForBank)
+// 银行卡加*
+Vue.filter('addConfusionForBank', addConfusionForBank)

+ 305 - 0
jydocs-pc/src/utils/globalFunctions.js

@@ -0,0 +1,305 @@
+// 字符串处理相关函数
+// 手机号中间4位加* ------------>
+export function addConfusionForTel (tel) {
+  const reg = /^(\d{3})\d{4}(\d{4})$/
+  return tel.replace(reg, '$1****$2')
+}
+// 手机号加空格 ------------>
+export function addSpaceForTel (tel) {
+  const regMap = {
+    isConfuse: /^(\d{3})\*{4}(\d{4})$/,
+    addSpace: /^(\d{3})(\d{4})(\d{4})$/
+  }
+  const confusion = regMap.isConfuse.test(tel)
+  if (confusion) {
+    return tel.replace(regMap.isConfuse, '$1 **** $2')
+  } else {
+    return tel.replace(regMap.addSpace, '$1 $2 $3')
+  }
+}
+// 银行卡加空格
+export function addSpaceForBank (v, hasConfusion = false) {
+  // 无*银行卡号加空格
+  if (hasConfusion) {
+    // 带有*的银行卡号字符串加空格
+    return v.replace(/\s/g, '').replace(/(.{4})/g, '$1 ')
+  } else {
+    // 纯数字银行卡号字符串加空格
+    return v.replace(/\s/g, '').replace(/(\d{4})(?=\d)/g, '$1 ')
+  }
+}
+// 银行卡加 **
+export function addConfusionForBank (v) {
+  if (String(v).length < 12) {
+    return v.replace(/\s/g, '').replace(/^(\d{2})\d+(\d{2})$/, '$1 **** **** $2')
+  } else {
+    return v.replace(/\s/g, '').replace(/^(\d{4})\d+(\d{4})$/, '$1 **** **** $2')
+  }
+}
+
+// 金额处理
+// 分转元
+export function fen2Yuan (v) {
+  return v / 100
+}
+
+// 金额大写,链接:https://juejin.im/post/5a2a7a5051882535cd4abfce
+// upDigit(1682) result:"人民币壹仟陆佰捌拾贰元整"
+// upDigit(-1693) result:"欠壹仟陆佰玖拾叁元整"
+export function upPrice (n) {
+  const fraction = ['角', '分', '厘']
+  const digit = ['零', '壹', '贰', '叁', '肆', '伍', '陆', '柒', '捌', '玖']
+  const unit = [
+    ['元', '万', '亿'],
+    ['', '拾', '佰', '仟']
+  ]
+  // const head = n < 0 ? '欠人民币' : '人民币'
+  const head = ''
+  n = Math.abs(n)
+  let s = ''
+  for (let i = 0; i < fraction.length; i++) {
+    s += (digit[Math.floor(n * 10 * Math.pow(10, i)) % 10] + fraction[i]).replace(/零./, '')
+  }
+  s = s || '整'
+  n = Math.floor(n)
+  for (let i = 0; i < unit[0].length && n > 0; i++) {
+    let p = ''
+    for (let j = 0; j < unit[1].length && n > 0; j++) {
+      p = digit[n % 10] + unit[1][j] + p
+      n = Math.floor(n / 10)
+    }
+    s = p.replace(/(零.)*零$/, '').replace(/^$/, '零') + unit[0][i] + s
+    // s = p + unit[0][i] + s;
+  }
+  return head + s.replace(/(零.)*零元/, '元').replace(/(零.)+/g, '零').replace(/^整$/, '零元整')
+}
+
+// 金额3位逗号分隔  ------------>
+/**
+ * @param s 要格式化的数字(四舍五入)
+ * @param n 保留几位小数(不传或者传-1 --> 如果为整数,则不保留小数。如果为浮点数,则保留两位小数)
+ * @param comma 是否小数点前每3位添加逗号
+ */
+export function newFormat (s = 0, n = -1, comma = false) {
+  n = n === -1 ? 0 : n
+  if (n > 20 || n < -1) {
+    n = 2
+  }
+  s = Number(s)
+  return s.toLocaleString('zh-CN', {
+    style: 'decimal',
+    useGrouping: comma,
+    minimumFractionDigits: n,
+    maximumFractionDigits: n
+  })
+}
+export function formatPrice (s, n = -1, comma = false) {
+  // 如果不传s或者s为空,则直接返回0
+  if (!s) return 0
+
+  if (n !== -1) n = n > 0 && n <= 20 ? n : 2
+  const intS = parseInt(String(s))
+  let point = '.'
+  let left = []
+  let right = ''
+  s = parseFloat((s + '').replace(/[^\d.-]/g, ''))
+  // 没传n或者n为-1,默认(如果为整数,则不保留小数。如果为浮点数,则保留两位小数)
+  if (n === -1) {
+    if (s === intS) {
+      n = 0
+      right = ''
+      point = ''
+    } else {
+      n = 2
+      s = s.toFixed(n)
+      right = s.split('.')[1]
+    }
+    s = s + ''
+    left = s.split('.')[0].split('').reverse()
+  } else {
+    s = parseFloat((s + '').replace(/[^\d.-]/g, '')).toFixed(n) + ''
+    left = s.split('.')[0].split('').reverse()
+    right = s.split('.')[1]
+  }
+
+  if (comma) {
+    let t = ''
+    for (let i = 0; i < left.length; i++) {
+      t += left[i] + ((i + 1) % 3 === 0 && (i + 1) !== left.length ? ',' : '')
+    }
+    return t.split('').reverse().join('') + point + right
+  }
+
+  return left.reverse().join('') + point + right
+}
+
+// 时间格式化相关函数
+/*
+* 时间格式化函数(将时间格式化为,2019年08月12日,2019-08-12,2019/08/12的形式)
+*   pattern参数(想要什么格式的数据就传入什么格式的数据)
+*     · 'yyyy-MM-dd'  ---> 输出如2019-09-20
+*     · 'yyyy-MM-dd HH:mm'  --->  输出如2019-09-20 18:20
+*     · 'yyyy-MM-dd HH:mm:ss'  --->  输出如2019-09-20 06:20:23
+*     · 'yyyy/MM/dd'  --->  输出如2019/09/20
+*     · 'yyyy年MM月dd日'  --->  输出如2019年09月20日
+*     · 'yyyy年MM月dd日 HH时mm分'  --->  输出如2019年09月20日 18时20分
+*     · 'yyyy年MM月dd日 HH时mm分ss秒'  --->  输出如2019年09月20日 18时20分23秒
+*     · 'yyyy年MM月dd日 HH时mm分ss秒 EE'  --->  输出如2019年09月20日 18时20分23秒 周二
+*     · 'yyyy年MM月dd日 HH时mm分ss秒 EEE'  --->  输出如2019年09月20日 18时20分23秒 星期二
+*  参考: https://www.cnblogs.com/mr-wuxiansheng/p/6296646.html
+*/
+export function dateFormatter (date, fmt = 'yyyy-MM-dd HH:mm:ss') {
+  // 将传入的date转为时间对象
+  if (!date) return ''
+  date = new Date(date)
+  const o = {
+    'y+': date.getFullYear(),
+    'M+': date.getMonth() + 1, // 月份
+    'd+': date.getDate(), // 日
+    // 12小时制
+    'h+': date.getHours() % 12 === 0 ? 12 : date.getHours() % 12, // 小时
+    // 24小时制
+    'H+': date.getHours(), // 小时
+    'm+': date.getMinutes(), // 分
+    's+': date.getSeconds(), // 秒
+    'q+': Math.floor((date.getMonth() + 3) / 3), // 季度
+    S: date.getMilliseconds(), // 毫秒
+    'E+': date.getDay() // 周
+  }
+  const week = ['日', '一', '二', '三', '四', '五', '六']
+
+  if (/(y+)/.test(fmt)) {
+    fmt = fmt.replace(RegExp.$1, (date.getFullYear() + '').substr(4 - RegExp.$1.length))
+  }
+  if (/(E+)/.test(fmt)) {
+    fmt = fmt.replace(RegExp.$1, ((RegExp.$1.length > 1) ? (RegExp.$1.length > 2 ? '星期' : '周') : '') + week[date.getDay()])
+  }
+  for (const k in o) {
+    if (new RegExp('(' + k + ')').test(fmt)) {
+      fmt = fmt.replace(RegExp.$1, (RegExp.$1.length === 1) ? (o[k]) : (('00' + o[k]).substr(('' + o[k]).length)))
+    }
+  }
+  return fmt
+}
+
+// 时间戳转换 多少秒、多少分、多少小时前、多少天前  超出10天显示年月日
+// 传入一个时间戳
+export function dateFromNow (timestamp) {
+  const date1 = new Date(timestamp) // 开始时间
+  const date2 = new Date() // 结束时间
+  const date3 = date2.getTime() - date1.getTime() // 时间差的毫秒数
+  // 计算出相差天数
+  const days = Math.floor(date3 / (24 * 3600 * 1000))
+  // 计算出小时数
+  const leave1 = date3 % (24 * 3600 * 1000) // 计算天数后剩余的毫秒数
+  const hours = Math.floor(leave1 / (3600 * 1000))
+  // 计算相差分钟数
+  const leave2 = leave1 % (3600 * 1000) // 计算小时数后剩余的毫秒数
+  const minutes = Math.floor(leave2 / (60 * 1000))
+  // 计算相差秒数
+  let td = '30秒前'
+  if (days > 0) {
+    if (days > 10) {
+      const date1year = date1.getFullYear()
+      const date2year = date2.getFullYear()
+      let date1month = date1.getMonth() + 1
+      let date1day = date1.getDate()
+      if (date1month < 10) {
+        date1month = '0' + date1month
+      }
+      if (date1day < 10) {
+        date1day = '0' + date1day
+      }
+      if (date1year < date2year) {
+        td = date1.getFullYear() + '-' + date1month + '-' + date1day
+      } else {
+        td = date1month + '-' + date1day
+      }
+    } else {
+      td = days + '天前'
+    }
+  } else if (hours > 0) {
+    td = hours + '小时前'
+  } else if (minutes > 0) {
+    td = minutes + '分钟前'
+  }
+  return td
+}
+
+/**
+ * 通用关键字高亮替换
+ * @param {String} value 要高亮的字符串
+ * @param {String|Array} oldChar 要被替换的字符串(或数组)
+ * @param {String|Array} newChar 要替换成的字符串(或数组)
+ *
+ * 比如:要将 - `剑鱼标讯工具函数` 字符串中的 `工具` 高亮
+ * 则此时 value -> `剑鱼标讯工具函数`
+ *        oldChar -> `工具`
+ *        newChar -> `<span class="highlight-text">工具</span>`
+ *
+ * 批量高亮-----
+ * 比如:要将 - `剑鱼标讯工具函数` 字符串中的 `工具` `剑鱼` 高亮
+ * 则此时 value -> `剑鱼标讯工具函数批量高亮`
+ *        oldChar -> ['工具', '剑鱼']
+ *        newChar -> ['<span class="highlight-text">', '</span>']
+ *
+ *   注意:此时newChar为一个长度为2的数组,数组中为高亮标签的起始标签和结束标签
+ *
+ */
+export function replaceKeyword (value, oldChar, newChar) {
+  if (!oldChar || !newChar) return value
+  // oldChar的字符串数组,用来循环替换
+  var oldCharArr = []
+
+  if (Array.isArray(oldChar)) {
+    oldCharArr = oldChar.concat()
+  } else {
+    oldCharArr.push(oldChar)
+  }
+
+  // 数组去重
+  oldCharArr = Array.from(new Set(oldCharArr))
+
+  try {
+    oldCharArr.forEach(function (item) {
+      // 去空格之后为空字符串,则直接跳过当前替换
+      if (item.replace(/\s+/g, '')) {
+        var oc = item
+        oc = oc.replace(/\$/g, '\\$')
+          .replace(/\(/g, '\\(')
+          .replace(/\)/g, '\\)')
+          .replace(/\*/g, '\\*')
+          .replace(/\+/g, '\\+')
+          .replace(/\./g, '\\.')
+          .replace(/\[/g, '\\[')
+          .replace(/\]/g, '\\]')
+          .replace(/\?/g, '\\?')
+          .replace(/\\/g, '\\')
+          .replace(/\//g, '\\/')
+          .replace(/\^/g, '\\^')
+          .replace(/\{/g, '\\{')
+          .replace(/\}/g, '\\}')
+          .replace(/\|/g, '\\|')
+
+        if (Array.isArray(newChar)) {
+          // 批量高亮
+          var tempV = value
+          value = value.replace(new RegExp('(' + oc + ')', 'gmi'), newChar[0] + oc + newChar[1])
+          if (value === tempV && oc.indexOf('+') !== -1) {
+            var splitReg = oc.split('\\+')
+            splitReg.map(function (v) {
+              value = value.replace(new RegExp('(' + v + ')', 'gmi'), newChar[0] + v + newChar[1])
+            })
+          }
+        } else {
+          // 普通单个高亮
+          value = value.replace(new RegExp('(' + oc + ')', 'gmi'), newChar)
+        }
+      }
+    })
+  } catch (e) {
+    console.log(e)
+    return value
+  }
+  return value
+}

+ 4 - 0
jydocs-pc/src/utils/index.js

@@ -0,0 +1,4 @@
+import './globalDirectives'
+import './globalFilters'
+
+export * from './globalFunctions'

+ 133 - 30
jydocs-pc/src/views/Home.vue

@@ -1,38 +1,77 @@
 <template>
   <div class="home">
+      <div class="top-search-group flex-c-c center">
+        <h5>剑鱼文库,最实用的招投标资料库</h5>
+        <search-input @submit="goSubmit"></search-input>
+      </div>
 
-      <search-input @submit="goSubmit"></search-input>
-
-      <h3>最新标讯</h3>
-      <div class="new-list-group flex-r-c">
-          <div class="flex-c-c">
-              <list-item></list-item>
-              <list-item></list-item>
-              <list-item></list-item>
-              <list-item></list-item>
-              <list-item></list-item>
+      <div class="new-group">
+          <div class="flex-r-c">
+              <div class="title-group flex-r-c center left">
+                  <h5>最新文档</h5>
+                  <i class="el-icon-jy-Frame"></i>
+              </div>
           </div>
-          <div class="flex-c-c">
-              <list-item></list-item>
-              <list-item></list-item>
-              <list-item></list-item>
-              <list-item></list-item>
-              <list-item></list-item>
+
+          <div class="new-list-group flex-r-c">
+              <div class="flex-c-c">
+                  <list-item></list-item>
+                  <list-item></list-item>
+                  <list-item></list-item>
+                  <list-item></list-item>
+                  <list-item></list-item>
+              </div>
+              <div class="flex-c-c">
+                  <list-item></list-item>
+                  <list-item></list-item>
+                  <list-item></list-item>
+                  <list-item></list-item>
+                  <list-item></list-item>
+              </div>
           </div>
       </div>
 
-      <h3>精选推荐</h3>
-      <div class="hot-keep-group flex-r-c wrap">
-          <card-item></card-item>
-          <card-item></card-item>
-          <card-item></card-item>
-          <card-item></card-item>
-          <card-item></card-item>
-          <card-item></card-item>
+      <div class="hot-down-group">
+          <div class="flex-r-c">
+              <div class="title-group flex-r-c center left">
+                  <h5>热门下载</h5>
+                  <i class="el-icon-jy-Frame-1"></i>
+              </div>
+          </div>
+
+          <div class="new-list-group flex-r-c">
+              <div class="flex-c-c">
+                  <list-item></list-item>
+                  <list-item></list-item>
+                  <list-item></list-item>
+                  <list-item></list-item>
+                  <list-item></list-item>
+              </div>
+              <div class="flex-c-c">
+                  <list-item></list-item>
+                  <list-item></list-item>
+                  <list-item></list-item>
+                  <list-item></list-item>
+                  <list-item></list-item>
+              </div>
+          </div>
       </div>
 
-      <el-button @click="getTest" :loading="fullscreenLoading" type="primary">模拟Ajax</el-button>
-      <el-button  @click="getLoginStatus" type="info" icon="el-icon-jy-search">获取登录状态</el-button>
+      <div class="keep-group">
+          <div class="flex-r-c">
+              <div class="title-group flex-r-c center left">
+                  <h5>精选推荐</h5>
+              </div>
+          </div>
+          <div class="hot-keep-group flex-r-c wrap">
+              <card-item></card-item>
+              <card-item></card-item>
+              <card-item></card-item>
+              <card-item></card-item>
+              <card-item></card-item>
+              <card-item></card-item>
+          </div>
+      </div>
   </div>
 </template>
 
@@ -41,12 +80,10 @@ import { ajaxGetTest } from '../api/modules/user'
 import { Button } from 'element-ui'
 import SearchInput from '../components/Search'
 import ListItem from '../components/ListItem'
-import CardItem from '../components/CardItem'
 
 export default {
   name: 'home',
   components: {
-    CardItem,
     ListItem,
     SearchInput,
     [Button.name]: Button
@@ -56,6 +93,12 @@ export default {
       fullscreenLoading: false
     }
   },
+  beforeCreate: function () {
+    $('body').addClass('view_index')
+  },
+  beforeDestroy: function () {
+    $('body').removeClass('view_index')
+  },
   methods: {
     goSubmit (search) {
       this.$router.push({
@@ -77,11 +120,71 @@ export default {
 }
 </script>
 <style lang="scss">
-    .link-item {
-        margin: 0 10px;
+  .page--docs--index.view_index {
+    .page-container {
+      background-image: url("~@/assets/images/wenkuBanner.png");
+      background-repeat: no-repeat;
     }
+  }
 
+</style>
+<style scoped lang="scss">
     @include diy-icon('search', 24);
+    @include diy-icon('Frame', 24);
+    @include diy-icon('Frame-1', 24);
+
+    .keep-group {
+        margin-top: 38px;
+        padding-bottom: 50px;
+    }
+
+    .new-group {
+        margin-top: 54px;
+    }
+
+    .hot-down-group {
+        border-radius: 12px;
+        background: url("~@/assets/images/dateGetBg.png") no-repeat;
+
+        background-size: 100% 100%;
+        width: 100%;
+        height: auto;
+        padding: 24px;
+        padding-bottom: 34px;
+        box-sizing: border-box;
+        margin-top: 40px;
+        .new-list-group {
+            background-color: white;
+            border-radius: 8px;
+        }
+    }
+
+    .title-group {
+        margin-bottom: 16px;
+        h5 {
+            color: #1D1D1D;
+            font-family: Microsoft YaHei;
+            font-size: 18px;
+            line-height: 28px;
+            letter-spacing: 0px;
+            text-align: left;
+            margin-right: 9px;
+        }
+    }
+
+    .top-search-group {
+      width: 100%;
+      height: 323px;
+      h5 {
+        color: #1D1D1D;
+        font-family: Microsoft YaHei;
+        font-size: 20px;
+        line-height: normal;
+        letter-spacing: 0px;
+        text-align: left;
+        margin-bottom: 40px;
+      }
+    }
 
     .new-list-group {
         .flex-c-c {

+ 166 - 16
jydocs-pc/src/views/Search.vue

@@ -1,25 +1,95 @@
 <template>
-  <div class="home">
-      <search-input @submit="goSubmit"></search-input>
-      <el-button @click="getTest" :loading="fullscreenLoading" type="primary">模拟Ajax</el-button>
-      <el-button  @click="getLoginStatus" type="info">获取登录状态</el-button>
+  <div class="search-container">
+    <search-input @submit="goSubmit" @recovery="getTest"></search-input>
+    <div class="search-result-container">
+      <div class="sort-list">
+        <span
+          class="sort-item"
+          v-for="(item, index) in sortList"
+          :key="index"
+          @click="sortAndSearch(item, index)"
+          :class="index === listState.sortActive ? 'active': ''"
+        >
+          <span class="sort-text">{{ item.name }}</span>
+          <span class="sort-icon" :class="item.sortBy ? 'el-icon-top' : 'el-icon-bottom'"></span>
+        </span>
+      </div>
+      <div class="search-result-list" v-loading="listState.loading">
+        <doc-card
+          :title="title"
+          desc="关于设计图。。。"
+          :highlightKey="['设计图','更新']"
+          :subInfo="['设计图','更新']"
+          @onClick="clickFn"
+        />
+        <no-data v-if="listState.list.length === 0 && listState.loaded">暂无我的文库</no-data>
+      </div>
+      <div class="search-pagination">
+        <el-pagination
+          background
+          layout="prev, pager, next, ->, total"
+          :hide-on-single-page="true"
+          :current-page="listState.currentPage"
+          :page-size="listState.pageSize"
+          :page-count="listState.pageCount"
+          :total="listState.total"
+          @current-change="onPageChange"
+        >
+        </el-pagination>
+      </div>
+    </div>
+    {{ajaxData}}
+    <button @click="getTest" type="primary">模拟Ajax</button>
+    <button  @click="getLoginStatus" type="info">获取登录状态</button>
   </div>
 </template>
 
 <script>
-import { ajaxGetTest } from '../api/modules/user'
-import { Button } from 'element-ui'
-import SearchInput from "../components/Search";
+import { Icon, Pagination, Image } from 'element-ui'
+import SearchInput from '@/components/Search'
+import DocCard from '@/components/doc-item-card/Card'
+import NoData from '@/components/NoData'
+import { ajaxGetSearch } from '../api/modules/search'
 
 export default {
-  name: 'home',
+  name: 'seach',
   components: {
+    [Icon.name]: Icon,
+    [Pagination.name]: Pagination,
+    [Image.name]: Image,
     SearchInput,
-    [Button.name]: Button
+    DocCard,
+    NoData
   },
   data () {
     return {
-      fullscreenLoading: false
+      sortList: [
+        {
+          name: '上传时间',
+          sortBy: 1
+        },
+        {
+          name: '下载次数',
+          sortBy: 0
+        },
+        {
+          name: '浏览人数',
+          sortBy: 0
+        }
+      ],
+      listState: {
+        loaded: false, // 是否已经搜索过
+        sortActive: 0,
+        loading: false,
+        currentPage: 2, // 当前页
+        pageSize: 10, // 每页多少条数据
+        pageCount: 10, // 一共多少页
+        total: 100, // 一共多少条数据
+        list: [] // 查询请求返回的数据
+      },
+      searchQuery: {},
+      ajaxData: {},
+      title: '设计图变动更新设计图变动更新设计图变动更新设计图变动更新'
     }
   },
   methods: {
@@ -28,18 +98,98 @@ export default {
         name: 'search',
         query: search
       })
-      console.log(search)
+      this.searchQuery = search
+      this.getTest(search)
     },
-    getTest () {
-      this.fullscreenLoading = true
-      ajaxGetTest().then(res => {
-        console.log(res)
-        this.fullscreenLoading = false
+    getTest (search) {
+      ajaxGetSearch({
+        keyWord: search.text,
+        tag: search.type,
+        // tSort时间倒叙 dSort下载倒叙 vSort浏览量倒叙
+        sort: 'tSort',
+        num: 1,
+        size: 10
+      }).then(res => {
+        console.log(res.data)
+        this.ajaxData = res.data
       })
     },
     getLoginStatus: function () {
       alert(loginflag)
+    },
+    sortAndSearch (item, index) {
+      console.log(...arguments)
+    },
+    clickFn () {
+      console.log('clickItem')
+    },
+    onPageChange (p) {
+      this.listState.currentPage = p
+      this.listState.loading = true
+      setTimeout(() => {
+        this.listState.loading = false
+      }, 2000)
+      console.log(JSON.stringify(this.listState, null, 4))
     }
   }
 }
 </script>
+<style lang="scss">
+.el-pagination.is-background .el-pager {
+  li {
+    background-color: #fff;
+    border: 1px solid rgba($color: #000, $alpha: 0.05);
+  }
+
+  li:not(.disabled):hover {
+    color: #fff;
+    background-color: $color-text--highlight;
+  }
+}
+</style>
+<style lang="scss" scoped>
+.search-result-container {
+  margin: 0 auto;
+  .sort-list {
+    display: flex;
+    align-items: center;
+    margin: 0 18px;
+    height: 48px;
+    border-radius: 4px;
+    background: #F5F6F7;
+    .sort-item {
+      display: flex;
+      align-items: center;
+      padding: 0 20px;
+      height: 100%;
+      font-size: 14px;
+      color: #686868;
+      cursor: pointer;
+      .sort-text {
+        margin-right: 4px;
+      }
+      .sort-icon {
+        color: #aaa;
+      }
+      &.active {
+        .sort-text,
+        .sort-icon {
+          color: $color-text--highlight;
+        }
+      }
+      &:hover {
+        .sort-text,
+        .sort-icon {
+          color: $color-text--highlight;
+        }
+      }
+    }
+  }
+  .search-result-list {
+    min-height: 500px;
+  }
+  .search-pagination {
+    text-align: right;
+  }
+}
+</style>