Jelajahi Sumber

feat: 提取组合式函数、优化组件

zhangyuhan 1 tahun lalu
induk
melakukan
87bb6a798a

+ 73 - 21
apps/bigmember_pc/src/views/article-content/components/ContentHeader.vue

@@ -1,8 +1,17 @@
 <script setup>
 import shareBox from '@/components/shareBox/index.vue'
+import powerPerson from '@/components/subscribe-manager/powerPerson.vue'
 import { contentModel } from '@jy/data-models'
-import { onMounted, ref } from 'vue'
+import { computed, getCurrentInstance, onMounted, ref } from 'vue'
 import { useRoute } from 'vue-router/composables'
+import { useStore } from '@/store'
+import { useDistribute } from '@/views/article-content/composables/useDistribute'
+import { useShare } from '@/views/article-content/composables/useShare'
+
+const getters = useStore().getters
+const vt = computed(() => {
+  return useStore().getters['user/vt']
+})
 
 const headerType = '业主委托项目'
 
@@ -17,21 +26,14 @@ const keepLabel = [
   }
 ]
 
-// 打开弹框
-const useShareBox = ref(null)
+const params = useRoute().params
+const wxShareImgURL = '/biddetail/normal/qr/' + params.id
 
-onMounted(() => {
-  const params = useRoute().params
-  useShareBox.value.sendData({
-    code: 1,
-    stype: params.content,
-    id: params.id,
-    link: window.location.href
-  })
-})
-function openShare() {
-  useShareBox.value.showNewuserDialog = true
-}
+// 分享
+const { openShare, useShareRef } = useShare()
+// 分发
+const { doSubmitDistribute, openDistribute, usePowerRef } = useDistribute()
+// 监控
 </script>
 
 <template>
@@ -39,7 +41,9 @@ function openShare() {
     <div class="before-type" v-if="contentModel.isSelfSite">
       {{ headerType }}
     </div>
-    <h1 class="title">{{ contentModel.title }}</h1>
+    <h1 class="title">
+      {{ contentModel.title }}
+    </h1>
     <div class="tags">
       <a
         :href="item.link"
@@ -51,19 +55,35 @@ function openShare() {
     <div class="actions-info">
       <div class="time-label">{{ contentModel.time }}</div>
       <div class="actions">
+        <div class="action-item" @click="openDistribute">
+          <span class="iconfont icon-shoudongfenfa"></span>
+          <span class="text">分发</span>
+        </div>
         <div class="action-item" @click="openShare">
           <span class="iconfont icon-fenxiang"></span>
           <span class="text">转给同事</span>
         </div>
+
         <div class="action-item">
-          <span class="iconfont icon-fenxiang"></span>
+          <el-popover
+            class="action-wx-popover"
+            placement="bottom"
+            title="微信扫一扫"
+            width="120"
+            :append-to-body="false"
+            trigger="hover"
+          >
+            <img :src="wxShareImgURL" alt="微信分享" />
+            <div class="action-item" slot="reference">
+              <span class="iconfont icon-weixin_line"></span>
+              <span class="text">微信分享</span>
+            </div>
+          </el-popover>
         </div>
+
         <div class="action-item">
           <span class="iconfont icon-canbiao"></span>
         </div>
-        <div class="action-item">
-          <span class="iconfont icon-weixin_line"></span>
-        </div>
         <div class="action-item">
           <span class="iconfont icon-shoucang_weishoucang"></span>
           <span class="iconfont icon-shoucang"></span>
@@ -83,7 +103,13 @@ function openShare() {
       </div>
     </div>
     <!-- 分享弹窗 -->
-    <shareBox ref="useShareBox"></shareBox>
+    <shareBox ref="useShareRef"></shareBox>
+    <!-- 分发人员弹窗 -->
+    <powerPerson
+      ref="usePowerRef"
+      :vt="vt"
+      @manualDiatribution="doSubmitDistribute"
+    ></powerPerson>
   </div>
 </template>
 
@@ -178,6 +204,32 @@ function openShare() {
           margin-left: 2px;
         }
       }
+
+      .action-wx-popover {
+        ::v-deep {
+          .el-popover {
+            width: 120px;
+            min-width: unset;
+            display: flex;
+            flex-direction: column;
+            align-items: center;
+            padding: 0;
+            padding-top: 12px;
+          }
+          .el-popover__title {
+            font-size: 14px;
+            line-height: 18px;
+            color: #1d1d1d;
+            font-weight: bold;
+            margin-bottom: 0;
+          }
+        }
+
+        img {
+          min-width: 120px;
+          height: 120px;
+        }
+      }
     }
   }
   .expands-info {

+ 0 - 33
apps/bigmember_pc/src/views/article-content/components/ContentSummary.vue

@@ -50,39 +50,6 @@ const contentSummaryTable = computed(() => {
   return result
 })
 
-const contentSummaryTable2 = [
-  [
-    {
-      label: '采购单位'
-    },
-    {
-      label: '大通回族土族自治县住房和城乡建设局',
-      type: 'unit'
-    },
-    {
-      label: '采购联系人/电话'
-    },
-    {
-      label: '0371-5454545',
-      type: 'phone'
-    }
-  ],
-  [
-    {
-      label: '招标代理机构'
-    },
-    {
-      label: '青海川泽工程咨询有限公司'
-    },
-    {
-      label: '采购联系人/电话'
-    },
-    {
-      label: '0371-5454545'
-    }
-  ]
-]
-
 function getCellClassName({ row, column, rowIndex, columnIndex }) {
   if (columnIndex === 0 || columnIndex === 2) {
     return 'label-col'

+ 231 - 0
apps/bigmember_pc/src/views/article-content/components/RecommendEnt.vue

@@ -0,0 +1,231 @@
+<script setup>
+import { summaryModel } from '@jy/data-models'
+import { computed, onMounted, ref, reactive, watch } from 'vue'
+import { ajaxGetMiniEntInfo } from '@/api/modules/detail'
+import { formatMoney } from "@/utils";
+
+const recommendEntList = ref([])
+function getRecommendEntInfo(list) {
+  const resultList = []
+  for (let i = 0; i < list.length; i++) {
+    const item = list[i]
+    const type = item?.id ? 'winner' : 'buyer'
+    const key = item?.id || item.name
+    ajaxGetMiniEntInfo(type, key).then((res) => {
+      if (res.error_code === 0) {
+        const item = res.data
+        resultList[i] = {
+          type,
+          id: item?.winnerId || '',
+          name: item.companyName,
+          tags: [
+            {
+              value: item.contactCount,
+              unit: '个',
+              label: '联系人'
+            },
+            {
+              value: item.biddingCount,
+              unit: '条',
+              label: '招标动态'
+            },
+            {
+              value: item.projectCount,
+              unit: '个',
+              label: '采购项目数量'
+            },
+            {
+              value: formatMoney(item.bidamountCount, { type: 'number'}),
+              unit: formatMoney(item.bidamountCount, { type: 'unit'}),
+              label: '采购规模'
+            },
+            {
+              value: item.cooperate,
+              unit: '个',
+              label: '合作企业'
+            }
+          ],
+          ...res.data
+        }
+        recommendEntList.value = [].concat(resultList)
+      }
+    })
+  }
+}
+
+const list = computed(() => {
+  const result = [].concat(
+    summaryModel.value.buyers,
+    summaryModel.value.winners
+  )
+  return result
+})
+
+watch(list, () => {
+  getRecommendEntInfo(list.value)
+})
+
+function doOpen (item) {
+  console.log(item);
+}
+</script>
+
+<template>
+  <div v-if="recommendEntList">
+    <div
+      class="recommend-info-card"
+      v-for="(item, index) in recommendEntList"
+      :key="index"
+    >
+      <div class="type-info-header">
+        <div class="type-infos">
+          <span
+            class="type-label"
+            :class="{ 'blue-type': (item && item.type) === 'buyer' }"
+          >
+            {{ item.type === 'buyer' ? '采购单位' : '中标单位' }}画像
+          </span>
+          <h3>{{item.companyName}}</h3>
+          <div class="monitor-action">
+            <span class="iconfont icon-jiankong"></span>
+            <span class="iconfont icon-yijiankong"></span>
+            监控
+          </div>
+        </div>
+        <span class="type-info-time">数据统计范围:{{item.timeFrame}}</span>
+      </div>
+      <div class="content-number-info">
+        <div class="number-infos">
+          <div class="number-info-item" v-for="(tag, i) in item.tags" :key="i">
+            <div class="highlight-number">
+              <span class="highlight-number-label">{{tag.value}}</span>
+              <span>{{tag.unit}}</span>
+            </div>
+            <span>{{tag.label}}</span>
+          </div>
+        </div>
+        <el-button class="detail-action" type="primary" @click="doOpen(item)">查看详情</el-button>
+      </div>
+    </div>
+  </div>
+</template>
+
+<style lang="scss" scoped>
+.recommend-info-card {
+  margin-top: 16px;
+  border-radius: 8px;
+  background: #f7f9fc;
+  padding: 16px 20px;
+  .type-info-header {
+    display: flex;
+    flex-direction: row;
+    align-items: flex-end;
+    justify-content: space-between;
+  }
+  .type-info-time {
+    color: #999;
+    text-align: right;
+    font-size: 12px;
+    font-style: normal;
+    font-weight: 400;
+    line-height: 18px;
+  }
+
+  .content-number-info {
+    display: flex;
+    flex-direction: row;
+    align-items: center;
+    justify-content: space-between;
+    font-size: 14px;
+    line-height: 22px;
+    color: #686868;
+
+    .detail-action {
+      width: 160px;
+      height: 46px;
+      font-size: 16px;
+    }
+
+    .number-infos {
+      display: flex;
+      flex-direction: row;
+      align-items: center;
+      width: 680px;
+      height: 78px;
+    }
+    .number-info-item {
+      position: relative;
+      flex: 1;
+      display: flex;
+      flex-direction: column;
+      align-items: center;
+      &:last-child::after {
+        content: unset;
+      }
+      &::after {
+        content: '';
+        position: absolute;
+        right: 0;
+        top: 4px;
+        display: inline-block;
+        width: 1px;
+        height: 46px;
+        background: #ececec;
+      }
+    }
+    .highlight-number {
+      color: #2abed1;
+    }
+    .highlight-number-label {
+      font-size: 20px;
+      line-height: 32px;
+    }
+  }
+
+  .type-infos {
+    display: flex;
+    flex-direction: row;
+    align-items: center;
+
+    .type-label {
+      margin-right: 16px;
+      border-radius: 4px;
+      border: 1px solid #ff9f40;
+      padding: 1px 10px;
+      background: rgba(255, 159, 64, 0.1);
+      color: #ff9f40;
+      text-align: center;
+      font-size: 14px;
+      font-style: normal;
+      font-weight: 400;
+      line-height: 22px;
+      &.blue-type {
+        border-color: #05a5f2;
+        background: rgba(5, 166, 243, 0.1);
+        color: #05a5f2;
+      }
+    }
+    h3 {
+      color: #1d1d1d;
+      font-size: 16px;
+      font-style: normal;
+      font-weight: 400;
+      line-height: normal;
+    }
+    .monitor-action {
+      margin-left: 12px;
+      color: #1d1d1d;
+      font-size: 13px;
+      font-style: normal;
+      font-weight: 400;
+      line-height: 20px;
+      cursor: pointer;
+      .iconfont {
+        margin-right: 2px;
+        font-size: 18px;
+        color: #9b9ca3;
+      }
+    }
+  }
+}
+</style>

+ 40 - 0
apps/bigmember_pc/src/views/article-content/composables/useDistribute.js

@@ -0,0 +1,40 @@
+import { getCurrentInstance, ref } from 'vue'
+import { ajaxSetDidDistributor } from '@/api/modules'
+import { useRoute } from 'vue-router/composables'
+
+export function useDistribute() {
+  const params = useRoute().params
+  const usePowerRef = ref(null)
+  function openDistribute(e) {
+    usePowerRef.value.titleMsg = '选择接收人员'
+    usePowerRef.value.searchVal = ''
+    usePowerRef.value.centerDialogVisible = true
+    usePowerRef.value.selectDataIds = [params.id]
+    usePowerRef.value.getData('yes')
+  }
+
+  // 提交分发
+  function doSubmitDistribute(data) {
+    ajaxSetDidDistributor({
+      infoids: [params.id],
+      staffs: data
+    }).then((res) => {
+      const $message = getCurrentInstance().proxy.$message
+      if (res.error_code === 0) {
+        if (res.data === 1) {
+          $message({ message: '分发成功', type: 'success' })
+        } else {
+          $message({ message: res.error_msg, type: 'warning' })
+        }
+      } else {
+        $message({ message: res.error_msg, type: 'warning' })
+      }
+    })
+  }
+
+  return {
+    usePowerRef,
+    openDistribute,
+    doSubmitDistribute
+  }
+}

+ 25 - 0
apps/bigmember_pc/src/views/article-content/composables/useShare.js

@@ -0,0 +1,25 @@
+import { onMounted, ref } from 'vue'
+import { useRoute } from 'vue-router/composables'
+
+export function useShare() {
+  // 打开弹框
+  const useShareRef = ref(null)
+
+  const params = useRoute().params
+  onMounted(() => {
+    useShareRef.value.sendData({
+      code: 1,
+      stype: params.content,
+      id: params.id,
+      link: window.location.href
+    })
+  })
+  function openShare() {
+    useShareRef.value.showNewuserDialog = true
+  }
+
+  return {
+    useShareRef,
+    openShare
+  }
+}

+ 4 - 179
apps/bigmember_pc/src/views/article-content/pages/Article.vue

@@ -13,6 +13,7 @@ import { throttle } from 'lodash'
 import { ajaxGetContentInfo } from '@/api/modules/detail'
 import { useContentInfo, summaryModel, contentModel } from '@jy/data-models'
 import ContentSummary from '@/views/article-content/components/ContentSummary.vue'
+import RecommendEnt from '@/views/article-content/components/RecommendEnt.vue'
 
 ajaxGetContentInfo({}).then((res) => {
   if (res.error_code === 0) {
@@ -60,34 +61,6 @@ function doSelectTab(item) {
   scrollToTop(goElement, 45)
 }
 
-function addTableItem(item) {
-  const TypeLabels = {
-    buyerunit: '采购单位',
-    buyerphone: '采购联系人/电话',
-    proxyunit: '招标代理机构',
-    proxyphone: '代理联系人/电话'
-  }
-  contentSummaryTable.push({
-    label: item?.label || TypeLabels[item?.key] || '-'
-  })
-
-  let valueItem = {
-    label: item?.value
-  }
-
-  switch (item.type) {
-    case 'unit': {
-      valueItem.id = 'xx'
-      break
-    }
-    case 'phone': {
-      valueItem.more = true
-    }
-  }
-
-  contentSummaryTable.push(valueItem)
-}
-
 const testTitle = replaceKeyword(
   '淮安市高级职业技术学校台式电脑采购项目二次招标中标公告',
   '淮安市高级职业技术学校',
@@ -282,41 +255,11 @@ onBeforeMount(() => {
 
       <div class="content-card watch-tab-content" name="公告摘要">
         <content-summary />
+        <recommend-ent />
       </div>
 
-      <div class="article-content-container watch-tab-content" name="公告摘要">
-        <div class="recommend-info-card" v-for="i in 2" :key="i">
-          <div class="type-info-header">
-            <div class="type-infos">
-              <span class="type-label" :class="{ 'blue-type': i === 2 }"
-                >采购单位画像</span
-              >
-              <h3>大通回族土族自治县住房和城乡建设局</h3>
-              <div class="monitor-action">
-                <span class="iconfont icon-jiankong"></span>
-                <span class="iconfont icon-yijiankong"></span>
-                监控
-              </div>
-            </div>
-            <span class="type-info-time"
-              >数据统计范围:2018/01/01-2020/09/30</span
-            >
-          </div>
-          <div class="content-number-info">
-            <div class="number-infos">
-              <div class="number-info-item" v-for="i in 5" :key="i">
-                <div class="highlight-number">
-                  <span class="highlight-number-label">20</span>
-                  <span>个</span>
-                </div>
-                <span>联系人</span>
-              </div>
-            </div>
-            <el-button class="detail-action" type="primary">查看详情</el-button>
-          </div>
-        </div>
-
-        <div class="content-main-container watch-tab-content" name="公告正文">
+      <div class="content-card watch-tab-content" name="公告正文">
+        <div class="content-main-container">
           <div class="content-block-header">公告正文</div>
           <div class="content-detail-container">
             北京汇诚金桥国际招标有限公司受北京联合大学的委托,就北京联合大学中央支持地方专项-科技创新服务能力建设-虚拟现实创新应用实验教学平台(中央资金)项目(第一~四包)项目(项目编号:BJJQ-2017-638-01、02、03、04)组织采购,评标工作已经结束,中标结果如下:
@@ -732,124 +675,6 @@ onBeforeMount(() => {
   }
 }
 
-.recommend-info-card {
-  margin-top: 16px;
-  border-radius: 8px;
-  background: #f7f9fc;
-  padding: 16px 20px;
-  .type-info-header {
-    display: flex;
-    flex-direction: row;
-    align-items: flex-end;
-    justify-content: space-between;
-  }
-  .type-info-time {
-    color: #999;
-    text-align: right;
-    font-size: 12px;
-    font-style: normal;
-    font-weight: 400;
-    line-height: 18px;
-  }
-
-  .content-number-info {
-    display: flex;
-    flex-direction: row;
-    align-items: center;
-    justify-content: space-between;
-    font-size: 14px;
-    line-height: 22px;
-    color: #686868;
-
-    .detail-action {
-      width: 160px;
-      height: 46px;
-      font-size: 16px;
-    }
-
-    .number-infos {
-      display: flex;
-      flex-direction: row;
-      align-items: center;
-      width: 680px;
-      height: 78px;
-    }
-    .number-info-item {
-      position: relative;
-      flex: 1;
-      display: flex;
-      flex-direction: column;
-      align-items: center;
-      &:last-child::after {
-        content: unset;
-      }
-      &::after {
-        content: '';
-        position: absolute;
-        right: 0;
-        top: 4px;
-        display: inline-block;
-        width: 1px;
-        height: 46px;
-        background: #ececec;
-      }
-    }
-    .highlight-number {
-      color: #2abed1;
-    }
-    .highlight-number-label {
-      font-size: 20px;
-      line-height: 32px;
-    }
-  }
-
-  .type-infos {
-    display: flex;
-    flex-direction: row;
-    align-items: center;
-
-    .type-label {
-      margin-right: 16px;
-      border-radius: 4px;
-      border: 1px solid #ff9f40;
-      padding: 1px 10px;
-      background: rgba(255, 159, 64, 0.1);
-      color: #ff9f40;
-      text-align: center;
-      font-size: 14px;
-      font-style: normal;
-      font-weight: 400;
-      line-height: 22px;
-      &.blue-type {
-        border-color: #05a5f2;
-        background: rgba(5, 166, 243, 0.1);
-        color: #05a5f2;
-      }
-    }
-    h3 {
-      color: #1d1d1d;
-      font-size: 16px;
-      font-style: normal;
-      font-weight: 400;
-      line-height: normal;
-    }
-    .monitor-action {
-      margin-left: 12px;
-      color: #1d1d1d;
-      font-size: 13px;
-      font-style: normal;
-      font-weight: 400;
-      line-height: 20px;
-      cursor: pointer;
-      .iconfont {
-        margin-right: 2px;
-        font-size: 18px;
-        color: #9b9ca3;
-      }
-    }
-  }
-}
-
 .article-container {
   width: 980px;
   margin: 20px;