Преглед изворни кода

feat: pc投标信用报告功能

Signed-off-by: tangshizhe <48740614+tangshizhe@users.noreply.github.com>
tangshizhe пре 3 месеци
родитељ
комит
8f36496acb

+ 9 - 0
apps/bigmember_pc/src/api/modules/common.js

@@ -15,3 +15,12 @@ export function getCustomInfo (data) {
     data
   })
 }
+
+// 附件上传
+export function ajaxUploadFile(data) {
+  return request({
+    url: '/front/filemanage/upload',
+    method: 'post',
+    data
+  })
+}

+ 38 - 1
apps/bigmember_pc/src/api/modules/pay.js

@@ -72,7 +72,7 @@ export function getPDFPackDetail(params) {
 export function getPDFPackBalance() {
   return request({
     url: '/jypay/pdfExportPack/account',
-    method: 'post',
+    method: 'post'
   })
 }
 
@@ -128,3 +128,40 @@ export function getGiftRecordDetail(data) {
     data: qs.stringify(data)
   })
 }
+
+// 投标企业信用报告-信用报告查询
+export function ajaxGetCreditReport(data) {
+  data = qs.stringify(data)
+  return request({
+    url: '/subscribepay/bidCreditReport/report/get',
+    method: 'post',
+    data
+  })
+}
+
+// 投标企业信用报告-信用报告修改
+export function ajaxUpdateCreditReport(data) {
+  return request({
+    url: '/subscribepay/bidCreditReport/report/update',
+    method: 'post',
+    data
+  })
+}
+
+// 投标企业信用报告-投标企业名称联想
+export function ajaxBiddingEntSearch(data) {
+  data = qs.stringify(data)
+  return request({
+    url: '/subscribepay/bidCreditReport/entSearch',
+    method: 'post',
+    data
+  })
+}
+
+// 投标企业信用报告-获取配置项
+export function ajaxGetConfig() {
+  return request({
+    url: '/subscribepay/config',
+    method: 'post'
+  })
+}

BIN
apps/bigmember_pc/src/assets/images/credit-report-icon.png


BIN
apps/bigmember_pc/src/assets/images/投标企业信用报告(样例_剑鱼标讯).pdf


+ 20 - 1
apps/bigmember_pc/src/router/modules/order.js

@@ -284,7 +284,26 @@ export default [
             }
           }
         ]
-      }
+      },
+      {
+        path: 'credit-report',
+        components: commonOrder({
+          info: () => import('@/views/order/components/credit-report/info.vue')
+        }),
+        children: [
+          {
+            path: '',
+            meta: {
+              title: '购买投标企业信用报告',
+              productId: 150
+            },
+            components: {
+              'buy-tip': () =>
+                import('@/views/order/components/credit-report/buy-tip.vue')
+            }
+          }
+        ]
+      },
     ]
   }
 ]

+ 22 - 4
apps/bigmember_pc/src/router/modules/report.js

@@ -9,7 +9,7 @@ export default [
     },
     component: () => import('@/views/reportDownload/index.vue')
   },
-  //下载的PDF
+  // 下载的PDF
   {
     path: '/report/pdf',
     name: 'report_download_pdf',
@@ -18,20 +18,38 @@ export default [
       {
         path: 'market',
         name: 'pdf_market',
-        component: () => import('@/views/download-pdf/marketReport.vue'),
+        component: () => import('@/views/download-pdf/marketReport.vue')
       },
       // 企业中标分析
       {
         path: 'ent',
         name: 'pdf_ent',
-        component: () => import('@/views/download-pdf/entReport.vue'),
+        component: () => import('@/views/download-pdf/entReport.vue')
       },
       // 业主采购分析
       {
         path: 'prop',
         name: 'pdf_prop',
-        component: () => import('@/views/download-pdf/propReport.vue'),
+        component: () => import('@/views/download-pdf/propReport.vue')
       }
     ]
+  },
+  // 报告样例/报告预览
+  {
+    path: '/free/report/preview',
+    name: 'report_preview',
+    meta: {
+      title: '报告预览'
+    },
+    component: () => import('@/views/reportDownload/preview.vue')
+  },
+  // 报告审核
+  {
+    path: '/free/report/examine',
+    name: 'report_examine',
+    meta: {
+      title: '报告审核'
+    },
+    component: () => import('@/views/reportDownload/examine.vue')
   }
 ]

+ 2 - 1
apps/bigmember_pc/src/store/order.js

@@ -71,7 +71,8 @@ const productNameMap = {
   118: '剑鱼文库会员',
   201: '企业中标分析报告下载包',
   202: '业主采购分析报告下载包',
-  203: '市场分析定制报告下载包'
+  203: '市场分析定制报告下载包',
+  150: '投标企业信用报告'
 }
 
 const Hooks = {

+ 86 - 20
apps/bigmember_pc/src/views/article-content/components/ContentHeader.vue

@@ -7,7 +7,8 @@ import {
   ContentModel,
   ContentId,
   IsSunPublishContent,
-  useRenMaiModel
+  useRenMaiModel,
+  showCreditReportButton
 } from '@/views/article-content/composables/useContentStore'
 import { computed, getCurrentInstance, onMounted, ref } from 'vue'
 import { useRoute } from 'vue-router/composables'
@@ -19,7 +20,10 @@ import BidrenewalDialog from '@/views/BidrenewalDialog/index.vue'
 import { useQuickJoinBidModel } from '@/composables/quick-join-bid'
 import WorkspaceButtonGroup from '@/components/dialog/WorkspaceButtonGroup.vue'
 import ContentBIActions from '@/views/article-content/components/ContentBIActions.vue'
-import { GetInWhichContainer } from '@/views/article-content/composables/useArticleUtil'
+import {
+  GetInWhichContainer,
+  doOpenCreditReportPage
+} from '@/views/article-content/composables/useArticleUtil'
 
 const getters = useStore().getters
 const vt = computed(() => {
@@ -36,7 +40,9 @@ const headerType = computed(() => {
 
 const sunPublishContent = computed(() => IsSunPublishContent.value)
 
-const headerTypeShow = computed(() => ContentModel.value.isSelfSite || sunPublishContent.value)
+const headerTypeShow = computed(
+  () => ContentModel.value.isSelfSite || sunPublishContent.value
+)
 
 const keepLabel = [
   {
@@ -108,6 +114,13 @@ const {
   showRenMaiButton,
   loading: remMaiLoading
 } = useRenMaiModel(ContentModel)
+
+// console.log(ContentModel.value, ContentModel.value?._ob?.topType, ContentModel.value?._ob?.subType, ContentModel.value.isCaigouyixiang)
+const buyerName = ref('')
+buyerName.value = ContentModel.value?._summary?._s?.buyer || ''
+const infoType = computed(() => {
+  return ContentModel.value?._ob?.topType || ContentModel.value?._ob?.subType
+})
 </script>
 
 <template>
@@ -153,7 +166,6 @@ const {
             <span class="text">转给同事</span>
           </div>
         </template>
-        
 
         <div class="action-item">
           <el-popover
@@ -206,7 +218,6 @@ const {
             ></article-star>
           </div>
         </template>
-        
       </div>
       <div class="actions" v-if="isUseBIActions">
         <content-b-i-actions
@@ -258,18 +269,37 @@ const {
         </div>
       </div>
     </div>
-    <div class="expands-actions" v-if="!sunPublishContent">
-      <div class="expands-actions-l"></div>
-      <div class="expands-actions-r">
-        <el-button
-          type="primary"
-          v-if="showRenMaiButton"
-          :loading="remMaiLoading"
-          class="relationship-button"
-          @click="findRenMai"
-        >
-          <i class="iconfont icon-renmai"></i>找人脉
-        </el-button>
+    <div
+      class="flex flex-(items-center justify-end)"
+      v-if="showCreditReportButton"
+    >
+      <div class="credit-report">
+        <div class="report-container">
+          <div class="report-text">
+            通过信用背书、风险预警、政策适配,赋能投标突围
+          </div>
+          <button
+            class="report-btn"
+            :data-info-type="infoType"
+            @click="doOpenCreditReportPage($event, buyerName)"
+          >
+            投标企业信用报告
+          </button>
+        </div>
+      </div>
+      <div class="expands-actions" v-if="!sunPublishContent">
+        <div class="expands-actions-l"></div>
+        <div class="expands-actions-r">
+          <el-button
+            type="primary"
+            v-if="showRenMaiButton"
+            :loading="remMaiLoading"
+            class="relationship-button"
+            @click="findRenMai"
+          >
+            <i class="iconfont icon-renmai"></i>找人脉
+          </el-button>
+        </div>
       </div>
     </div>
     <!-- 分享弹窗 -->
@@ -348,10 +378,10 @@ const {
   .tags {
     margin-top: 12px;
     .tag-orange {
-      color: #FA6F33;
-      background-color: #FFF1EB;
+      color: #fa6f33;
+      background-color: #fff1eb;
       &.border {
-        border: 1px solid #F56500;
+        border: 1px solid #f56500;
       }
     }
   }
@@ -487,10 +517,46 @@ const {
   justify-content: space-between;
 }
 .relationship-button {
+  margin-left: 10px;
   padding: 6px 20px;
   height: 30px;
+  background: linear-gradient(281deg, #28c1e2 3.53%, #5fd4e3 98.32%);
+  border: 0;
   .iconfont {
     margin-right: 2px;
   }
 }
+.credit-report {
+  display: flex;
+  justify-content: flex-end;
+  .report-container {
+    display: flex;
+    height: 30px;
+    margin-top: 8px;
+    align-items: center;
+    background: rgba(42, 190, 209, 0.16);
+    border-radius: 4px;
+    border: 1px solid rgba(42, 190, 209, 0.16);
+  }
+  .report-text {
+    flex: 1;
+    display: flex;
+    align-items: center;
+    height: 30px;
+    padding: 0 12px;
+    color: #2abed1;
+    font-size: 14px;
+  }
+  .report-btn {
+    display: flex;
+    align-items: center;
+    height: 30px;
+    margin-right: -1px;
+    color: #fff;
+    padding: 0 12px;
+    font-size: 14px;
+    border-radius: 4px;
+    background: linear-gradient(281deg, #28c1e2 3.53%, #5fd4e3 98.32%);
+  }
+}
 </style>

+ 14 - 0
apps/bigmember_pc/src/views/article-content/composables/useArticleUtil.js

@@ -88,3 +88,17 @@ export function GetInWhichContainer() {
   const InWhichContainer = window.parent !== window ? 'in-app' : 'in-web'
   return InWhichContainer
 }
+
+// 打开企业信用报告购买页
+export function doOpenCreditReportPage(event, buyer = '') {
+  const btnName = event.target.textContent.trim() || '投标企业信用报告'
+  const infoType = event.target.dataset.infoType || event.currentTarget.dataset.infoType || ''
+  const breakName = `${btnName}_${infoType}`
+  // 自定义埋点上报事件(数据统计需求:点击信用报告按钮要求统计到当前标讯的信息类型)
+  try {
+    window.__EasyJTrack.addTrack(breakName)
+    window.open('/swordfish/page_big_pc/order/credit-report?buyer=' + buyer, '_blank')
+  } catch (error) {
+    window.open('/swordfish/page_big_pc/order/credit-report?buyer=' + buyer, '_blank')
+  }
+}

+ 11 - 2
apps/bigmember_pc/src/views/article-content/composables/useContentStore.js

@@ -103,7 +103,8 @@ async function useContentStore() {
       ContentPageLoading.value = false
       if (IsSunPublishContent.value && model.content.changedTitle) {
         setPageTDK(model.content.tdk, window.top.document)
-      } else {
+      }
+      else {
         setPageTDK(model.content.tdk)
       }
     })
@@ -185,6 +186,13 @@ function useRenMaiModel(ContentModel) {
   }
 }
 
+const showCreditReportButton = computed(() => {
+  return (
+    ['采购意向', '预告', '招标'].includes(ContentModel.value?._ob?.topType)
+    || ContentModel.value.isCaigouyixiang
+  )
+})
+
 export {
   useContentStore,
   useRenMaiModel,
@@ -198,5 +206,6 @@ export {
   hasPowerToReadSunPublishContent,
   IsSunPublishContent,
   ContentIsError,
-  ContentErrorText
+  ContentErrorText,
+  showCreditReportButton
 }

+ 1 - 1
apps/bigmember_pc/src/views/order/components/common/form.vue

@@ -61,7 +61,7 @@ export default {
             phone: this.form.phone
           },
           this.form,
-          { phone: data.phone }
+          { phone: data.phone, reportMail: data.reportMail }
         )
         this.updateFormStatus(this.form)
       }

+ 22 - 0
apps/bigmember_pc/src/views/order/components/credit-report/buy-tip.vue

@@ -0,0 +1,22 @@
+<template>
+  <div class="buy-tip">
+    <p>购买须知:</p>
+    <p>剑鱼平台产品与服务属于虚拟数字产品,鉴于服务的特殊性,一旦开通权益不支持退款,请确认无误后进行支付。</p>
+  </div>
+</template>
+
+<script>
+export default {
+  name: 'buy-tip',
+}
+</script>
+
+<style scoped>
+.buy-tip {
+  margin-top: 28px;
+  font-size: 12px;
+  font-weight: 400;
+  color: #888888;
+  line-height: 16px;
+}
+</style>

+ 353 - 0
apps/bigmember_pc/src/views/order/components/credit-report/info.vue

@@ -0,0 +1,353 @@
+<template>
+  <div class="report-order-info">
+    <div class="report-order-info__header flex flex-justify-between">
+      <div>
+        <p class="report-role">报告作用:</p>
+        <p class="report-desc">
+          信用报告通过信用背书、风险预警、政策适配,三大核心作用,成为投标企业参与市场竞争的关键工具。
+        </p>
+      </div>
+      <button type="button" class="sample-btn" @click="onViewReportSample">
+        查看报告样例
+      </button>
+    </div>
+    <div class="report-order-info__main">
+      <el-form
+        :model="ruleForm"
+        :rules="rules"
+        ref="ruleForm"
+        label-width="104px"
+        @validate="updateFormState"
+      >
+        <el-form-item label="投标企业名称" prop="biddingName">
+          <el-select
+            v-model="ruleForm.biddingCode"
+            filterable
+            remote
+            :remote-method="querySearchEnt"
+            :loading="loading"
+            placeholder="必填"
+            :popper-append-to-body="false"
+            @change="selectBiddingName"
+          >
+            <el-option
+              v-for="item in biddingOptions"
+              :key="item.value"
+              :label="item.label"
+              :value="item.value"
+            />
+          </el-select>
+        </el-form-item>
+        <el-form-item label="招标单位名称" prop="buyerName">
+          <el-autocomplete
+            class="inline-input"
+            v-model="ruleForm.buyerName"
+            :fetch-suggestions="querySearchBuyer"
+            :popper-append-to-body="false"
+            :highlight-first-item="true"
+            placeholder="必填"
+            @select="selectBuyerName"
+          ></el-autocomplete>
+        </el-form-item>
+        <el-form-item label="邮箱" prop="email">
+          <el-input
+            v-model="ruleForm.email"
+            placeholder="必填,报告将发送至邮箱"
+          ></el-input>
+        </el-form-item>
+        <p class="buy-notify">
+          支付成功后,系统将在{{
+            bidCreditReport_makeTime
+          }}内将报告发送至您的邮箱,您也可前往“资产-报告下载记录”查看详情。
+        </p>
+      </el-form>
+    </div>
+  </div>
+</template>
+
+<script>
+import { Form, FormItem, Input, Autocomplete, Select, Option } from 'element-ui'
+import { mapActions, mapMutations, mapGetters } from 'vuex'
+import {
+  ajaxGetConfig,
+  getBuyerAssociation,
+  ajaxBiddingEntSearch
+} from '@/api/modules'
+
+export default {
+  name: 'credit-report-order-info',
+  components: {
+    [Form.name]: Form,
+    [FormItem.name]: FormItem,
+    [Input.name]: Input,
+    [Autocomplete.name]: Autocomplete,
+    [Select.name]: Select,
+    [Option.name]: Option
+  },
+  data() {
+    const validateEmail = (rule, value, callback) => {
+      const status = /\w+([-+.]\w+)*@\w+([-.]\w+)*\.\w+([-.]\w+)*/.test(value)
+      if (value === '') {
+        return callback(new Error('邮箱不能为空'))
+      } else {
+        if (!status) {
+          return callback(new Error('邮箱格式错误'))
+        } else {
+          callback()
+        }
+      }
+    }
+    return {
+      ruleForm: {
+        biddingName: '',
+        biddingCode: '',
+        buyerName: '',
+        email: ''
+      },
+      rules: {
+        biddingName: [
+          { required: true, message: '投标企业名称不能为空', trigger: 'change' }
+        ],
+        buyerName: [
+          { required: true, message: '招标单位名称不能为空', trigger: 'change' }
+        ],
+        email: [{ required: true, validator: validateEmail, trigger: 'change' }]
+      },
+      reportInfo: {},
+      biddingOptions: [],
+      buyerOptions: [],
+      loading: false,
+      bidCreditReport_makeTime: ''
+    }
+  },
+  computed: {
+    ...mapGetters('order', ['productFormInfo']),
+    pass() {
+      const emailPass =
+        this.ruleForm.email &&
+        /\w+([-+.]\w+)*@\w+([-.]\w+)*\.\w+([-.]\w+)*/.test(this.ruleForm.email)
+      return Boolean(
+        this.ruleForm.biddingName && this.ruleForm.buyerName && emailPass
+      )
+    },
+    reportMail() {
+      return this.productFormInfo?.reportMail || ''
+    }
+  },
+  watch: {
+    reportMail: {
+      immediate: true,
+      handler(newVal) {
+        if (newVal) {
+          this.ruleForm.email = newVal
+        }
+      }
+    }
+  },
+  async created() {
+    if (this.$route.query && this.$route.query.buyer) {
+      this.ruleForm.buyerName = this.$route.query.buyer
+    }
+    this.getConfigInfo()
+    // 获取产品信息
+    await this.setProductInfo({
+      id: this.$route.meta.productId,
+      hooks: {
+        submit: this.doSubmit.bind(this)
+      }
+    })
+    this.updateUI({
+      submitText: '立即抢购'
+    })
+    this.updateFormState()
+  },
+  methods: {
+    ...mapMutations('order', ['updateUI', 'updateCanNextMap']),
+    ...mapActions('order', ['setProductInfo']),
+    updateFormState() {
+      this.updateCanNextMap({
+        spec: this.pass
+      })
+    },
+    selectBiddingName(value) {
+      const selected = this.biddingOptions.find((item) => item.value === value)
+      if (selected) {
+        this.ruleForm.biddingName = selected.label
+      }
+    },
+    async querySearchEnt(queryString) {
+      if (queryString) {
+        this.loading = true
+        const { error_code: code, data } = await ajaxBiddingEntSearch({
+          entName: queryString
+        })
+        if (code === 0) {
+          this.biddingOptions = data?.map((item) => ({
+            value: item.cert_no,
+            label: item.name
+          }))
+        }
+        this.loading = false
+      } else {
+        this.biddingOptions = []
+      }
+    },
+    async querySearchBuyer(queryString, cb) {
+      if (queryString) {
+        const { error_code: code, data } = await getBuyerAssociation({
+          name: queryString
+        })
+        if (code === 0 && data && data?.list.length) {
+          this.buyerOptions = data?.list.map((item) => ({
+            value: item,
+            label: item
+          }))
+          cb(this.buyerOptions)
+        } else {
+          cb([])
+        }
+      } else {
+        cb([])
+      }
+    },
+    selectBuyerName(item) {
+      this.ruleForm.buyerName = item.label
+    },
+    async getConfigInfo() {
+      const { error_code: code, data } = await ajaxGetConfig()
+      if (code === 0 && data) {
+        this.bidCreditReport_makeTime = data?.bidCreditReport_makeTime || ''
+      }
+    },
+    onViewReportSample() {
+      // const link = this.$router.resolve({
+      //   path: '/free/report/preview',
+      //   query: {
+      //     source: 'bidCreditReportPreview'
+      //   }
+      // })
+      // window.open(link.href, '_blank')
+      window.open(
+        '/swordfish/page_big_pc/free/report/preview?source=bidCreditReportPreview',
+        '_blank'
+      )
+    },
+    /**
+     * 订单提交事件
+     * @param payload
+     * @param next
+     * @returns {Promise<*>}
+     */
+    async doSubmit(payload, next) {
+      // 处理参数格式化
+      const params = {
+        product: payload.productName,
+        productId: payload.productSpecId,
+        discountId: payload.offersId,
+        lotteryId: payload.offersId,
+        activityType: payload.activityType,
+        data: {
+          company: this.ruleForm.biddingName,
+          cert_no: this.ruleForm.biddingCode,
+          buyer: this.ruleForm.buyerName,
+          email: this.ruleForm.email,
+          order_phone: this.productFormInfo?.phone
+        }
+      }
+      // 发送请求
+      const { data, error_code: code, error_msg: message } = await next(params)
+      if (code === 0 && data?.needPay) {
+        const orderCode = data.order_code
+        location.href = '/front/creditReport/orderPay/' + orderCode
+      } else {
+        this.$message({
+          message: message || '创建订单失败,请刷新重试',
+          type: 'warning'
+        })
+      }
+      // 处理成功回调
+      return true
+    }
+  }
+}
+</script>
+
+<style lang="scss" scoped>
+.report-order-info {
+  padding: 0 32px;
+  &__header {
+    padding: 24px 0;
+    border-bottom: 1px solid #e0e0e0;
+  }
+  .report-role {
+    font-size: 14px;
+    line-height: 24px;
+    color: #1d1d1d;
+  }
+  .report-desc {
+    font-size: 14px;
+    line-height: 22px;
+    color: #686868;
+  }
+  .sample-btn {
+    width: 100px;
+    height: 30px;
+    line-height: 30px;
+    background: $color_main;
+    border-radius: 4px;
+    color: #fff;
+    font-size: 14px;
+  }
+  &__main {
+    padding: 24px 0 16px;
+    .buy-notify {
+      padding-left: 104px;
+      font-size: 14px;
+      color: #686868;
+      line-height: 22px;
+    }
+  }
+  ::v-deep {
+    .el-form-item__label {
+      padding-right: 8px;
+      font-size: 14px;
+      color: #1d1d1d;
+      line-height: 22px;
+      text-align: left;
+    }
+    .el-input__inner {
+      width: 590px;
+      height: 36px;
+      padding: 0 12px;
+      line-height: 36px;
+      color: #1d1d1d;
+    }
+    .el-form-item {
+      display: flex;
+      align-items: center;
+      margin-bottom: 20px;
+      &:last-of-type {
+        margin-bottom: 8px;
+        &.is-error {
+          margin-bottom: 20px;
+        }
+      }
+    }
+    .el-form-item__content {
+      margin-left: 0 !important;
+    }
+    .el-form-item.is-required:not(.is-no-asterisk)
+      .el-form-item__label-wrap
+      > .el-form-item__label:before,
+    .el-form-item.is-required:not(.is-no-asterisk)
+      > .el-form-item__label:before {
+      color: #ff3a20;
+    }
+  }
+}
+</style>
+<style>
+.selector-card.vip-sub-list-item.order-form {
+  display: none !important;
+}
+</style>

+ 498 - 0
apps/bigmember_pc/src/views/reportDownload/examine.vue

@@ -0,0 +1,498 @@
+<template>
+  <section class="report-examine v-w1200">
+    <el-form v-if="hasRecord" ref="form" :model="form" label-width="240px">
+      <el-form-item
+        label="无政府采购严重违法行为记录证明:"
+        prop="prove_purchase"
+      >
+        <el-upload
+          action="string"
+          :key="'upload-prove_purchase-' + form.prove_purchase"
+          :http-request="(file) => uploadFileHandle(file, 'prove_purchase')"
+          :limit="1"
+          :show-file-list="false"
+          :before-upload="beforeUpload"
+          accept="image/jpeg, image/jpg, image/png"
+        >
+          <div class="upload-container">
+            <div
+              v-if="form.prove_purchase"
+              class="avatar-container"
+              @click.stop
+            >
+              <img :src="domain + form.prove_purchase" class="avatar" />
+              <i
+                class="el-icon-error"
+                @click.stop="removeImg('prove_purchase')"
+              ></i>
+            </div>
+            <i v-else class="el-icon-plus avatar-uploader-icon"></i>
+          </div>
+          <div slot="tip" class="el-upload__tip">上传jpeg/jpg/png图片文件</div>
+        </el-upload>
+      </el-form-item>
+      <el-form-item label="有无政府采购严重违法行为:">
+        <el-radio-group v-model="form.prove_purchase_status">
+          <el-radio :label="0">无风险</el-radio>
+          <el-radio :label="1">有风险</el-radio>
+        </el-radio-group>
+      </el-form-item>
+      <el-form-item label="·无被执行记录证明:" prop="prove_executed">
+        <el-upload
+          action="string"
+          :key="'upload-prove_executed-' + form.prove_executed"
+          :http-request="(file) => uploadFileHandle(file, 'prove_executed')"
+          :limit="1"
+          :show-file-list="false"
+          :before-upload="beforeUpload"
+          accept="image/jpeg, image/jpg, image/png"
+        >
+          <div class="upload-container">
+            <div
+              v-if="form.prove_executed"
+              class="avatar-container"
+              @click.stop
+            >
+              <img :src="domain + form.prove_executed" class="avatar" />
+              <i
+                class="el-icon-error"
+                @click.stop="removeImg('prove_executed')"
+              ></i>
+            </div>
+            <i v-else class="el-icon-plus avatar-uploader-icon"></i>
+          </div>
+          <div slot="tip" class="el-upload__tip">上传jpeg/jpg/png图片文件</div>
+        </el-upload>
+      </el-form-item>
+      <el-form-item label="有无被执行记录:">
+        <el-radio-group v-model="form.prove_executed_status">
+          <el-radio :label="0">无风险</el-radio>
+          <el-radio :label="1">有风险</el-radio>
+        </el-radio-group>
+      </el-form-item>
+      <el-form-item label="无失信被执行记录证明:" prop="prove_dishonesty">
+        <el-upload
+          action="string"
+          :key="'upload-prove_dishonesty-' + form.prove_dishonesty"
+          :http-request="(file) => uploadFileHandle(file, 'prove_dishonesty')"
+          :limit="1"
+          :show-file-list="false"
+          :before-upload="beforeUpload"
+          accept="image/jpeg, image/jpg, image/png"
+        >
+          <div class="upload-container">
+            <div
+              v-if="form.prove_dishonesty"
+              class="avatar-container"
+              @click.stop
+            >
+              <img :src="domain + form.prove_dishonesty" class="avatar" />
+              <i
+                class="el-icon-error"
+                @click.stop="removeImg('prove_dishonesty')"
+              ></i>
+            </div>
+            <i v-else class="el-icon-plus avatar-uploader-icon"></i>
+          </div>
+          <div slot="tip" class="el-upload__tip">上传jpeg/jpg/png图片文件</div>
+        </el-upload>
+      </el-form-item>
+      <el-form-item label="有无失信被执行记录:">
+        <el-radio-group v-model="form.prove_dishonesty_status">
+          <el-radio :label="0">无风险</el-radio>
+          <el-radio :label="1">有风险</el-radio>
+        </el-radio-group>
+      </el-form-item>
+      <el-form-item label="无安全生产严重失信记录证明:" prop="prove_produce">
+        <el-upload
+          action="string"
+          :key="'upload-prove_produce-' + form.prove_produce"
+          :http-request="(file) => uploadFileHandle(file, 'prove_produce')"
+          :limit="1"
+          :show-file-list="false"
+          :before-upload="beforeUpload"
+          accept="image/jpeg, image/jpg, image/png"
+        >
+          <div class="upload-container">
+            <div v-if="form.prove_produce" class="avatar-container" @click.stop>
+              <img :src="domain + form.prove_produce" class="avatar" />
+              <i
+                class="el-icon-error"
+                @click.stop="removeImg('prove_produce')"
+              ></i>
+            </div>
+            <i v-else class="el-icon-plus avatar-uploader-icon"></i>
+          </div>
+          <div slot="tip" class="el-upload__tip">上传jpeg/jpg/png图片文件</div>
+        </el-upload>
+      </el-form-item>
+      <el-form-item label="有无安全生产严重失信记录:">
+        <el-radio-group v-model="form.prove_produce_status">
+          <el-radio :label="0">无风险</el-radio>
+          <el-radio :label="1">有风险</el-radio>
+        </el-radio-group>
+      </el-form-item>
+      <el-form-item label="信用中国:">
+        <el-upload
+          action="string"
+          :key="'upload-creditchina-' + form.creditchina"
+          :http-request="(file) => uploadFileHandle(file, 'creditchina')"
+          :limit="1"
+          :show-file-list="false"
+          :before-upload="beforeUpload"
+          accept=".pdf"
+        >
+          <div class="upload-container">
+            <el-tag
+              v-if="form.creditchina"
+              type="success"
+              closable
+              @close="removePdf"
+              @click.stop="handlePreviewPdf(form.creditchina)"
+            >
+              {{ pdfName }}
+            </el-tag>
+            <i v-else class="el-icon-plus avatar-uploader-icon"></i>
+          </div>
+          <div slot="tip" class="el-upload__tip">上传pdf文件</div>
+        </el-upload>
+      </el-form-item>
+      <el-form-item>
+        <el-button :disabled="disabled" type="primary" @click="onSubmit"
+          >提交</el-button
+        >
+      </el-form-item>
+    </el-form>
+    <Empty v-else>
+      <p>该记录不存在</p>
+    </Empty>
+    <el-dialog
+      title="提示"
+      :visible.sync="collectDialogVisible"
+      width="380px"
+      custom-class="collect-dialog"
+      :close-on-click-modal="false"
+      :close-on-press-escape="false"
+      center
+    >
+      <div class="dialog-content">
+        <p>该报告的表单信息已经收集过。</p>
+        <p v-if="reportInfo.confirmTime">
+          表单提交时间:
+          <span class="highlight-text">{{ reportInfo.confirmTime }}</span>
+        </p>
+        <p v-if="reportInfo.reportTime">
+          报告生成时间:
+          <span class="highlight-text">{{ reportInfo.reportTime }}</span>
+        </p>
+        <p v-if="reportInfo.emailTime">
+          邮件发送时间:
+          <span class="highlight-text">{{ reportInfo.emailTime }}</span>
+        </p>
+      </div>
+      <span slot="footer" class="dialog-footer">
+        <el-button type="primary" @click="collectDialogVisible = false"
+          >我知道了</el-button
+        >
+      </span>
+    </el-dialog>
+    <el-dialog
+      title="提示"
+      :visible.sync="againDialogVisible"
+      width="380px"
+      custom-class="collect-dialog"
+      :close-on-click-modal="false"
+      :close-on-press-escape="false"
+      center
+    >
+      <div class="dialog-content">
+        <p>该报告的表单信息已经收集过,是否重新提交?</p>
+      </div>
+      <span slot="footer" class="dialog-footer">
+        <el-button @click="againDialogVisible = false">取 消</el-button>
+        <el-button type="primary" @click="confirmFn">确 定</el-button>
+      </span>
+    </el-dialog>
+  </section>
+</template>
+
+<script>
+import {
+  Form,
+  FormItem,
+  Radio,
+  RadioGroup,
+  Button,
+  Upload,
+  Tag,
+  Icon,
+  Dialog
+} from 'element-ui'
+import {
+  ajaxUploadFile,
+  ajaxUpdateCreditReport,
+  ajaxGetCreditReport
+} from '@/api/modules'
+import Empty from '@/components/common/Empty.vue'
+export default {
+  name: 'report-examine',
+  components: {
+    [Form.name]: Form,
+    [FormItem.name]: FormItem,
+    [Radio.name]: Radio,
+    [RadioGroup.name]: RadioGroup,
+    [Button.name]: Button,
+    [Upload.name]: Upload,
+    [Tag.name]: Tag,
+    [Icon.name]: Icon,
+    [Dialog.name]: Dialog,
+    Empty
+  },
+  data() {
+    return {
+      hasRecord: true,
+      id: '',
+      form: {
+        prove_purchase: '',
+        prove_purchase_status: 0,
+        prove_executed: '',
+        prove_executed_status: 0,
+        prove_dishonesty: '',
+        prove_dishonesty_status: 0,
+        prove_produce: '',
+        prove_produce_status: 0,
+        creditchina: ''
+      },
+      pdfName: '',
+      domain: window.location.origin,
+      reportInfo: {
+        confirmTime: null,
+        reportTime: null,
+        emailTime: null,
+        status: 0
+      },
+      collectDialogVisible: false,
+      againDialogVisible: false
+    }
+  },
+  computed: {
+    disabled() {
+      return (
+        !this.form.prove_purchase ||
+        !this.form.prove_executed ||
+        !this.form.prove_dishonesty ||
+        !this.form.prove_produce ||
+        !this.form.creditchina
+      )
+    }
+  },
+  created() {
+    this.id = this.$route.query?.id
+    if (this.id) {
+      this.getCreditReportForm()
+    }
+  },
+  methods: {
+    async getCreditReportForm() {
+      const { data, status, msg } = await ajaxGetCreditReport({ id: this.id })
+      if (status === 1) {
+        this.hasRecord = true
+        const {
+          prove_purchase,
+          prove_purchase_status,
+          prove_executed,
+          prove_executed_status,
+          prove_dishonesty,
+          prove_dishonesty_status,
+          prove_produce,
+          prove_produce_status,
+          creditchina
+        } = data
+        this.reportInfo.status = data.status
+        if (data.status > 0) {
+          this.form = {
+            prove_purchase,
+            prove_purchase_status,
+            prove_executed,
+            prove_executed_status,
+            prove_dishonesty,
+            prove_dishonesty_status,
+            prove_produce,
+            prove_produce_status,
+            creditchina
+          }
+          if (creditchina) {
+            const filename = creditchina.split('/').pop()
+            this.pdfName = filename
+          }
+          this.reportInfo.confirmTime = data.submit_time
+          this.reportInfo.reportTime = data.complete_time
+          this.reportInfo.emailTime = data.send_mail_time
+          this.collectDialogVisible = true
+          return
+        }
+      } else {
+        this.$toast(msg)
+        this.hasRecord = false
+      }
+    },
+    async uploadFileHandle(file, filed) {
+      const params = new FormData()
+      params.append('type', 'bidCreditReportFile')
+      params.append('bidCreditReportFile', file.file)
+      try {
+        const { error: code, url, filename } = await ajaxUploadFile(params)
+        if (code === 0 && url) {
+          this.form[filed] = url
+          if (filed === 'creditchina') {
+            this.pdfName = filename
+          }
+        } else {
+          this.form[filed] = ''
+        }
+      } catch (error) {
+        console.error('上传失败:', error)
+      }
+    },
+    handlePreviewPdf(url) {
+      if (!url) return
+      const pdfUrl = window.location.origin + url
+      window.open(pdfUrl, '_blank')
+    },
+    removePdf() {
+      this.form.creditchina = ''
+      this.pdfName = ''
+    },
+    removeImg(file) {
+      this.form[file] = ''
+    },
+    beforeUpload(file) {
+      const isLt2M = file.size / 1024 / 1024 < 10
+      if (!isLt2M) {
+        this.$toast('上传文件大小不能超过 10MB!')
+      }
+      return isLt2M
+    },
+    async confirmFn() {
+      const { error_code: code, error_msg: msg } = await ajaxUpdateCreditReport(
+        { ...this.form, id: this.id }
+      )
+      if (code === 0) {
+        this.$toast('提交成功')
+        window.location.reload()
+      } else {
+        this.$toast(msg)
+      }
+    },
+    onSubmit() {
+      if (this.reportInfo.status > 0) {
+        this.againDialogVisible = true
+        return
+      } else {
+        this.confirmFn()
+      }
+    }
+  }
+}
+</script>
+
+<style lang="scss" scoped>
+.report-examine {
+  background: #fff;
+  ::v-deep {
+    .el-form {
+      padding: 30px;
+    }
+    .el-form-item:nth-child(odd) {
+      margin-bottom: 10px;
+    }
+    .el-upload__input {
+      display: none !important;
+    }
+    .upload-container {
+      text-align: left;
+    }
+    .avatar-uploader .el-upload {
+      border: 1px dashed #d9d9d9;
+      border-radius: 6px;
+      cursor: pointer;
+      position: relative;
+      overflow: hidden;
+    }
+    .avatar-uploader .el-upload:hover {
+      border-color: #409eff;
+    }
+    .avatar-uploader-icon {
+      font-size: 28px;
+      color: #8c939d;
+      width: 120px;
+      height: 120px;
+      line-height: 120px;
+      text-align: center;
+      border: 1px dashed #d9d9d9;
+    }
+    .avatar-container {
+      position: relative;
+      width: 120px;
+      height: 120px;
+      border: 1px dashed #d9d9d9;
+      border-radius: 6px;
+      // overflow: hidden;
+    }
+    .el-icon-error {
+      display: none;
+      position: absolute;
+      right: -6px;
+      top: -6px;
+      z-index: 10;
+      font-size: 22px;
+      color: #1d1d1d;
+      &:hover {
+        color: #1d1d1d;
+      }
+    }
+    .avatar {
+      width: 100%;
+      height: 100%;
+      display: block;
+      z-index: 9;
+    }
+    .avatar-container:hover {
+      .el-icon-error {
+        display: block;
+      }
+    }
+  }
+}
+::v-deep {
+  .empty-container {
+    height: 500px;
+  }
+  .collect-dialog {
+    margin: 0 auto !important;
+    position: absolute;
+    top: 50%;
+    left: 50%;
+    transform: translate(-50%, -50%);
+    border-radius: 8px;
+    .el-dialog__body {
+      padding: 20px 30px;
+    }
+    .el-dialog__footer {
+      padding: 10px 30px 24px;
+      .el-button {
+        padding: 10px 40px;
+        border-radius: 4px;
+      }
+    }
+    .dialog-content {
+      p {
+        margin-bottom: 8px;
+        line-height: 24px;
+        font-size: 14px;
+        color: #333;
+      }
+    }
+  }
+}
+</style>

+ 153 - 0
apps/bigmember_pc/src/views/reportDownload/preview.vue

@@ -0,0 +1,153 @@
+<template>
+  <div class="report-sample">
+    <div
+      class="sample-container"
+      ref="sampleContainer"
+      :style="{ 'padding-bottom': !loginFlag ? adHeight + 'px' : 0 }"
+      v-loading="loading"
+    >
+      <!-- <iframe
+        class="iframe"
+        :src="pdfUrl"
+        :style="{ height: iframeHeight }"
+        frameborder="0"
+        type="application/pdf"
+      ></iframe> -->
+      <object
+        class="iframe"
+        :data="pdfUrl"
+        :style="{ height: iframeHeight }"
+        type="application/pdf"
+        style="width: 100%; height: 100%"
+      >
+        <p>您的浏览器不支持PDF预览,请<a :href="pdfUrl">点击下载</a></p>
+      </object>
+      <AdSense
+        v-show="!loginFlag"
+        ref="adSense"
+        class="ad-sense ad-fixed"
+        :code="code"
+        @openUrl="openUrl"
+      ></AdSense>
+    </div>
+  </div>
+</template>
+
+<script>
+import { mapGetters } from 'vuex'
+import { getAssetsFile } from '@/utils'
+import AdSense from '@/views/order/components/adsense/index.vue'
+export default {
+  name: 'report-sample',
+  components: {
+    AdSense
+  },
+  data() {
+    return {
+      pdfUrl: '',
+      code: 'pc-credit-report-sample',
+      adHeight: 0,
+      loading: true
+    }
+  },
+  computed: {
+    ...mapGetters('user', ['loginFlag']),
+    iframeHeight() {
+      return this.adHeight ? `calc(100% - ${this.adHeight}px)` : '100%'
+    }
+  },
+  created() {
+    // 新增路由参数处理
+    if (!this.$route.query.source) {
+      this.$router.replace({
+        query: {
+          ...this.$route.query,
+          source: 'bidCreditReportPreview'
+        }
+      })
+    }
+    if (this.$route.query && this.$route.query.url) {
+      this.pdfUrl = decodeURIComponent(this.$route.query.url)
+      this.loading = false
+    } else {
+      this.pdfUrl = getAssetsFile('投标企业信用报告(样例_剑鱼标讯).pdf')
+      this.loading = false
+    }
+  },
+  mounted() {
+    setTimeout(() => {
+      this.getAdStyle()
+    }, 300)
+    if (!this.loginFlag) {
+      window.top.addEventListener('scroll', (event) => {
+        const jBottom = window.top.document.querySelector('.j-bottom')
+        if (!jBottom) return
+        // 计算元素位置
+        const rect = jBottom.getBoundingClientRect()
+        // 当元素顶部进入视口时(阈值设为窗口高度)
+        const isVisible = rect.top <= window.top.innerHeight
+        // 获取广告DOM元素
+        const adElement = this.$refs.adSense?.$el
+        const container = document.querySelector('.sample-container')
+        if (isVisible) {
+          adElement?.classList.remove('ad-fixed')
+          container?.style.setProperty('padding-bottom', 0)
+        } else {
+          adElement?.classList.add('ad-fixed')
+          container?.style.setProperty('padding-bottom', this.adHeight + 'px')
+        }
+        // 触发广告高度重新计算
+        this.getAdStyle()
+      })
+    }
+  },
+  methods: {
+    getAdStyle() {
+      this.$nextTick(() => {
+        if (this.$refs.adSense && this.$refs.adSense.$el) {
+          const adElement = this.$refs.adSense.$el
+          const height = adElement.clientHeight
+          this.adHeight = height
+        }
+      })
+    },
+    openUrl() {
+      // 打开登录弹框or跳转登录页面
+      // location.href = '/notin/page?source=bidCreditReportPreview'
+      const redirectUrl = '/swordfish/page_big_pc/order/credit-report'
+      this.$showLoginDialog(false, redirectUrl)
+    }
+  }
+}
+</script>
+
+<style lang="scss" scoped>
+.report-sample {
+  height: 100vh;
+  .sample-container {
+    display: flex;
+    flex-direction: column;
+    height: 100%;
+  }
+  .iframe {
+    flex: 1;
+    width: 1200px !important;
+    margin: 0 auto;
+  }
+  .adsense {
+    padding: 0;
+  }
+}
+</style>
+<style>
+.adsense .content {
+  padding: 0 !important;
+  cursor: pointer;
+}
+.ad-fixed {
+  position: fixed;
+  bottom: 0;
+  left: 0;
+  width: 100%;
+}
+</style>

+ 458 - 276
apps/bigmember_pc/src/views/reportDownload/record.vue

@@ -2,46 +2,74 @@
   <div class="report-download-record">
     <div class="page-header">
       <h1>报告下载记录</h1>
-      <em>注:请在有效期内使用,过期清零,不可转赠。</em>
     </div>
     <section class="box-container balance-box">
-      <div class="box-title">报告下载余额</div>
+      <div class="box-title">
+        报告下载余额<em class="balance-tips"
+          >注:请在有效期内使用,过期清零,不可转赠。</em
+        >
+      </div>
       <div class="card-row">
         <div class="card-col" v-for="item in cardList">
           <p class="title">{{ item.title }}</p>
           <div class="num">
-            <span><strong>{{ item.total }}</strong>份</span>
-            <el-button class="recharge-button" type="primary" @click="goRecharge(item)">立即充值</el-button>
+            <span
+              ><strong>{{ item.total }}</strong
+              >份</span
+            >
+            <el-button
+              class="recharge-button"
+              type="primary"
+              @click="goRecharge(item)"
+              >立即充值</el-button
+            >
           </div>
           <p class="date">
             <span v-if="item.total">最近有效期至:{{ item.minEndTime }}</span>
-            <span class="text-button" @click="goBalance(item)">查明细<i class="iconfont icon-more"></i></span>
+            <span class="text-button" @click="goBalance(item)"
+              >查明细<i class="iconfont icon-more"></i
+            ></span>
           </p>
         </div>
       </div>
     </section>
+    <section class="flex flex-(justify-between items-center) credit-report-box">
+      <div class="flex flex-items-center credit-report-content">
+        <p class="credit-report-title">投标企业信用报告</p>
+        <p class="credit-report-desc">
+          信用报告通过信用背书、风险预警、政策适配,三大核心作用,成为投标企业参与市场竞争的关键工具‌
+        </p>
+        <img
+          class="credit-report-icon"
+          src="@/assets/images/credit-report-icon.png"
+          alt="信用报告"
+        />
+      </div>
+      <div class="flex flex-items-center report-action">
+        <span class="view-report-sample" @click="goViewSample"
+          >查看报告样例</span
+        >
+        <button class="report-to-buy" @click="goBuyCreditReport">去购买</button>
+      </div>
+    </section>
     <section class="box-container record-box">
       <p class="box-title">报告下载记录</p>
-      <el-table
-        :data="listState.list"
-        v-show="!showEmpty"
-      >
+      <el-table :data="listState.list" v-show="!showEmpty">
         <el-table-column label="下载时间" width="170" align="center">
           <template slot-scope="scope">
             <span class="max-line-3">{{
-                (scope.row.l_createTime * 1000) | formatTime('yyyy-MM-dd HH:mm')
-              }}</span>
+              (scope.row.l_createTime * 1000) | formatTime('yyyy-MM-dd HH:mm')
+            }}</span>
           </template>
         </el-table-column>
         <el-table-column label="报告类型" width="230" align="center">
           <template slot-scope="scope">
-            {{scope.row.type | formatType}}
+            {{ scope.row.type | formatType }}
           </template>
-
         </el-table-column>
         <el-table-column label="报告说明" min-width="400">
           <template slot-scope="scope">
-           <!-- 市场分析报告-->
+            <!-- 市场分析报告-->
             <el-tooltip
               v-if="scope.row.type === '3'"
               effect="dark"
@@ -67,24 +95,30 @@
                 <div>
                   <span>成交时间:</span
                   ><span
-                >{{
-                    scope.row.rangeTimeStart | formatTime('yyyy-MM-dd')
-                  }}至{{
-                    scope.row.rangeTimeEnd | formatTime('yyyy-MM-dd')
-                  }}</span
-                >
+                    >{{
+                      scope.row.rangeTimeStart | formatTime('yyyy-MM-dd')
+                    }}至{{
+                      scope.row.rangeTimeEnd | formatTime('yyyy-MM-dd')
+                    }}</span
+                  >
                 </div>
                 <div v-if="scope.row.s_area && scope.row.s_area !== '{}'">
                   <span>项目地区:</span
                   ><span>{{ scope.row.s_area | formatArea }}</span>
                 </div>
-                <div v-if="scope.row.s_industry && scope.row.s_industry !== '{}'">
+                <div
+                  v-if="scope.row.s_industry && scope.row.s_industry !== '{}'"
+                >
                   <span>行业:</span
-                  ><span>{{ scope.row.s_industry | formatMarketIndustry }}</span>
+                  ><span>{{
+                    scope.row.s_industry | formatMarketIndustry
+                  }}</span>
                 </div>
                 <div v-if="scope.row.s_buyerClass">
                   <span>采购单位类型:</span
-                  ><span>{{ getFormatBuyerClass(scope.row.s_buyerClass) }}</span>
+                  ><span>{{
+                    getFormatBuyerClass(scope.row.s_buyerClass)
+                  }}</span>
                 </div>
               </div>
               <div>
@@ -100,128 +134,190 @@
                   <div>
                     <span>成交时间:</span
                     ><span
-                  >{{
-                      scope.row.rangeTimeStart | formatTime('yyyy-MM-dd')
-                    }}至{{
-                      scope.row.rangeTimeEnd | formatTime('yyyy-MM-dd')
-                    }}</span
-                  >
+                      >{{
+                        scope.row.rangeTimeStart | formatTime('yyyy-MM-dd')
+                      }}至{{
+                        scope.row.rangeTimeEnd | formatTime('yyyy-MM-dd')
+                      }}</span
+                    >
                   </div>
-                  <div class="ellipsis-1" v-if="scope.row.s_area && scope.row.s_area !== '{}'">
+                  <div
+                    class="ellipsis-1"
+                    v-if="scope.row.s_area && scope.row.s_area !== '{}'"
+                  >
                     <span>项目地区:</span
                     ><span>{{ scope.row.s_area | formatArea }}</span>
                   </div>
-                  <div class="ellipsis-1" v-if="scope.row.s_industry && scope.row.s_industry !== '{}'">
+                  <div
+                    class="ellipsis-1"
+                    v-if="scope.row.s_industry && scope.row.s_industry !== '{}'"
+                  >
                     <span>行业:</span
-                    ><span>{{ scope.row.s_industry | formatMarketIndustry }}</span>
+                    ><span>{{
+                      scope.row.s_industry | formatMarketIndustry
+                    }}</span>
                   </div>
-                  <div  class="ellipsis-1" v-if="scope.row.s_buyerClass">
+                  <div class="ellipsis-1" v-if="scope.row.s_buyerClass">
                     <span>采购单位类型:</span
-                    ><span>{{ getFormatBuyerClass(scope.row.s_buyerClass) }}</span>
+                    ><span>{{
+                      getFormatBuyerClass(scope.row.s_buyerClass)
+                    }}</span>
                   </div>
                 </div>
               </div>
             </el-tooltip>
+            <div v-else-if="scope.row.type === '4'" class="">
+              <div>
+                <span>投标企业名称:</span>
+                <span>{{ scope.row.ent }}</span>
+              </div>
+              <div>
+                <span>招标单位名称:</span>
+                <span>{{ scope.row.buyer }}</span>
+              </div>
+            </div>
             <!-- 业主采购、企业中标分析报告-->
             <el-tooltip
-                v-else
-                effect="dark"
-                placement="right"
-                popper-class="analyse-condition-tooltip"
-              >
-                <div
-                  slot="content"
-                  style="
+              v-else
+              effect="dark"
+              placement="right"
+              popper-class="analyse-condition-tooltip"
+            >
+              <div
+                slot="content"
+                style="
                   max-width: 300px !important;
                   font-size: 12px;
                   line-height: 22px;
                 "
-                >
+              >
+                <div v-if="scope.row.type === '1'">
+                  <span>目标企业:</span>
+                  <span
+                    class="highlight-name"
+                    @click="goEntPortrayal(scope.row.ent)"
+                    >{{ scope.row.entName }}</span
+                  >
+                </div>
+                <div v-if="scope.row.type === '2'">
+                  <span>目标业主:</span>
+                  <span
+                    class="highlight-name"
+                    @click="goUnitPortrayal(scope.row.ent)"
+                    >{{ scope.row.entName }}</span
+                  >
+                </div>
+                <div>
+                  <span>成交时间:</span
+                  ><span
+                    >{{ scope.row.rangeTimeStart }}至{{
+                      scope.row.rangeTimeEnd
+                    }}</span
+                  >
+                </div>
+                <div v-if="scope.row.match">
+                  <span>关键词:</span>
+                  <span>{{
+                    scope.row.match +
+                    (scope.row.exactMatch === '1' ? '(精准)' : '(模糊)')
+                  }}</span>
+                </div>
+                <div v-if="scope.row.matchRange">
+                  <span>搜索范围:</span
+                  ><span>{{ scope.row.matchRange | formatSelectType }}</span>
+                </div>
+                <div v-if="scope.row.area">
+                  <span>项目地区:</span><span>{{ scope.row.area }}</span>
+                </div>
+                <div v-if="scope.row.scopeClass">
+                  <span>行业:</span
+                  ><span>{{ getFormatIndustry(scope.row.scopeClass) }}</span>
+                </div>
+                <div v-if="scope.row.buyerClass && scope.row.type === '1'">
+                  <span>采购单位类型:</span
+                  ><span>{{ getFormatBuyerClass(scope.row.buyerClass) }}</span>
+                </div>
+              </div>
+              <div>
+                <div class="analyse-condition">
                   <div v-if="scope.row.type === '1'">
                     <span>目标企业:</span>
-                    <span class="highlight-name" @click="goEntPortrayal(scope.row.ent)">{{scope.row.entName}}</span>
+                    <span
+                      class="highlight-name"
+                      @click="goEntPortrayal(scope.row.ent)"
+                      >{{ scope.row.entName }}</span
+                    >
                   </div>
                   <div v-if="scope.row.type === '2'">
                     <span>目标业主:</span>
-                    <span class="highlight-name" @click="goUnitPortrayal(scope.row.ent)">{{scope.row.entName}}</span>
+                    <span
+                      class="highlight-name"
+                      @click="goUnitPortrayal(scope.row.ent)"
+                      >{{ scope.row.entName }}</span
+                    >
                   </div>
                   <div>
                     <span>成交时间:</span
                     ><span
-                  >{{scope.row.rangeTimeStart }}至{{scope.row.rangeTimeEnd }}</span>
+                      >{{ scope.row.rangeTimeStart }}至{{
+                        scope.row.rangeTimeEnd
+                      }}</span
+                    >
                   </div>
-                  <div v-if="scope.row.match">
+                  <div class="ellipsis-1" v-if="scope.row.match">
                     <span>关键词:</span>
-                    <span>{{ scope.row.match + (scope.row.exactMatch === '1' ? '(精准)': '(模糊)')}}</span>
+                    <span>{{
+                      scope.row.match +
+                      (scope.row.exactMatch === '1' ? '(精准)' : '(模糊)')
+                    }}</span>
                   </div>
-                  <div v-if="scope.row.matchRange">
+                  <div class="ellipsis-1" v-if="scope.row.matchRange">
                     <span>搜索范围:</span
                     ><span>{{ scope.row.matchRange | formatSelectType }}</span>
                   </div>
-                  <div v-if="scope.row.area">
-                    <span>项目地区:</span
-                    ><span>{{ scope.row.area }}</span>
+                  <div class="ellipsis-1" v-if="scope.row.area">
+                    <span>项目地区:</span><span>{{ scope.row.area }}</span>
                   </div>
-                  <div v-if="scope.row.scopeClass">
+                  <div class="ellipsis-1" v-if="scope.row.scopeClass">
                     <span>行业:</span
                     ><span>{{ getFormatIndustry(scope.row.scopeClass) }}</span>
                   </div>
-                  <div v-if="scope.row.buyerClass && scope.row.type === '1'">
-                    <span>采购单位类型:</span
-                    ><span>{{ getFormatBuyerClass(scope.row.buyerClass)}}</span>
-                  </div>
-                </div>
-                <div>
-                  <div class="analyse-condition">
-                    <div v-if="scope.row.type === '1'">
-                      <span>目标企业:</span>
-                      <span class="highlight-name" @click="goEntPortrayal(scope.row.ent)">{{scope.row.entName}}</span>
-                    </div>
-                    <div v-if="scope.row.type === '2'">
-                      <span>目标业主:</span>
-                      <span class="highlight-name" @click="goUnitPortrayal(scope.row.ent)">{{scope.row.entName}}</span>
-                    </div>
-                    <div>
-                    <span>成交时间:</span
-                    ><span
-                    >{{scope.row.rangeTimeStart }}至{{scope.row.rangeTimeEnd }}</span>
-                    </div>
-                    <div class="ellipsis-1" v-if="scope.row.match" >
-                      <span>关键词:</span>
-                      <span>{{ scope.row.match  + (scope.row.exactMatch === '1' ? '(精准)': '(模糊)')}}</span>
-                    </div>
-                    <div class="ellipsis-1" v-if="scope.row.matchRange">
-                    <span>搜索范围:</span
-                    ><span>{{ scope.row.matchRange | formatSelectType }}</span>
-                    </div>
-                    <div class="ellipsis-1"  v-if="scope.row.area">
-                    <span>项目地区:</span
-                    ><span>{{ scope.row.area }}</span>
-                    </div>
-                    <div class="ellipsis-1"  v-if="scope.row.scopeClass">
-                    <span>行业:</span
-                    ><span>{{ getFormatIndustry(scope.row.scopeClass)}}</span>
-                    </div>
-                    <div class="ellipsis-1"  v-if="scope.row.buyerClass && scope.row.type === '1'">
+                  <div
+                    class="ellipsis-1"
+                    v-if="scope.row.buyerClass && scope.row.type === '1'"
+                  >
                     <span>采购单位类型:</span
-                    ><span>{{ getFormatBuyerClass(scope.row.buyerClass)}}</span>
-                    </div>
+                    ><span>{{
+                      getFormatBuyerClass(scope.row.buyerClass)
+                    }}</span>
                   </div>
                 </div>
-              </el-tooltip>
+              </div>
+            </el-tooltip>
           </template>
         </el-table-column>
         <el-table-column min-width="100" label="操作" align="center">
           <template slot-scope="scope">
-            <a v-if="scope.row.s_pdfUrl" class="text-button" :download="scope.row.fileName + '.pdf'" :href="scope.row.s_pdfUrl" target="_blank">下载</a>
+            <a
+              v-if="scope.row.s_pdfUrl"
+              class="text-button"
+              :download="scope.row.fileName + '.pdf'"
+              :href="scope.row.s_pdfUrl"
+              target="_blank"
+              >下载</a
+            >
             <span v-else>--</span>
           </template>
         </el-table-column>
       </el-table>
-      <empty  v-show="showEmpty">
+      <empty v-show="showEmpty">
         <div class="flex-c-c center">
-          <div style="width:310px;text-align: center">暂无下载记录,您可前往查看市场分析定制报告,精准分析客户、竞对、市场</div>
-          <el-button class="view-report-btn" type="primary" @click="viewReport">查看报告</el-button>
+          <div style="width: 310px; text-align: center">
+            暂无下载记录,您可前往查看市场分析定制报告,精准分析客户、竞对、市场
+          </div>
+          <el-button class="view-report-btn" type="primary" @click="viewReport"
+            >查看报告</el-button
+          >
         </div>
       </empty>
 
@@ -241,7 +337,6 @@
         </el-pagination>
       </div>
     </section>
-
   </div>
 </template>
 
@@ -255,7 +350,7 @@ export default {
   components: {
     Empty
   },
-  data () {
+  data() {
     return {
       listState: {
         loaded: true, // 是否已经搜索过
@@ -292,9 +387,10 @@ export default {
         }
       ],
       typeObj: {
-        '1': '企业中标分析报告',
-        '2': '业主采购分析报告',
-        '3': '市场分析定制报告'
+        1: '企业中标分析报告',
+        2: '业主采购分析报告',
+        3: '市场分析定制报告',
+        4: '投标企业信用报告'
       }
     }
   },
@@ -344,7 +440,7 @@ export default {
         if (!value[key].length) {
           keyArr.push(key)
         } else {
-          for(const item of value[key]) {
+          for (const item of value[key]) {
             valueArr.push(key + '_' + item)
           }
         }
@@ -354,17 +450,17 @@ export default {
       return obj.industryText
     },
     FormatKeys: function (keys) {
-      if(!keys) return '-'
+      if (!keys) return '-'
       let tempStr = '-'
       const tempResult = []
       const tempList = JSON.parse(keys)
       tempList.forEach(function (v) {
         v.a_key.forEach(function (k) {
           let key = []
-          if(k.key) {
+          if (k.key) {
             key = key.concat(k.key)
           }
-          if(k.appendkey) {
+          if (k.appendkey) {
             key = key.concat(k.appendkey)
           }
           tempResult.push({
@@ -376,11 +472,12 @@ export default {
       tempStr = tempResult
         .map(function (v) {
           return v.key.join(' ') + '(' + v.type + ')'
-        }).join(',')
+        })
+        .join(',')
       return tempStr
     },
     formatSelectType: function (value) {
-      if(!value) return '-'
+      if (!value) return '-'
       const arr = value.split(',')
       const strArr = []
       const str = ''
@@ -390,15 +487,15 @@ export default {
         winner: '中标企业',
         agency: '招标代理机构'
       }
-      for(let item of arr) {
+      for (let item of arr) {
         strArr.push(obj[item])
       }
       return strArr.join(',')
     },
     formatType: function (value) {
-      if(!value) return '-'
+      if (!value) return '-'
       let result = ''
-      switch(Number(value)) {
+      switch (Number(value)) {
         case 1:
           result = '企业中标分析报告'
           break
@@ -408,14 +505,15 @@ export default {
         case 3:
           result = '市场分析定制报告'
           break
+        case 4:
+          result = '投标企业信用报告'
+          break
       }
       return result
     }
   },
   computed: {
-    ...mapGetters('user', [
-      'isMember'
-    ]),
+    ...mapGetters('user', ['isMember']),
     showEmpty() {
       return this.listState.list.length === 0 && this.listState.loaded
     }
@@ -431,7 +529,7 @@ export default {
       return obj.industryText
     },
     // 格式化采购单位
-    getFormatBuyerClass (val) {
+    getFormatBuyerClass(val) {
       const obj = formatBuyerClass(val)
       return obj.buyerClassText
     },
@@ -443,7 +541,7 @@ export default {
       const text = map[m] || map.content
       return text
     },
-    async getList () {
+    async getList() {
       try {
         const query = {
           page: this.listState.pageNum,
@@ -458,21 +556,30 @@ export default {
           if (this.listState.pageNum === 1) {
             this.listState.total = data.count
           }
-          const list = data.list?.map((v) => {
-            if (v.s_rangeTime) {
-              const rangeTimeArr = v.s_rangeTime.split('-')
-              v.rangeTimeStart = new Date(rangeTimeArr[0] * 1000).getTime()
-              v.rangeTimeEnd = new Date(rangeTimeArr[1] * 1000).getTime()
-            } else if(v.timeRange) {
-              const rangeTimeArr = v.timeRange.split('_')
-              v.rangeTimeStart = rangeTimeArr[0]
-              v.rangeTimeEnd = rangeTimeArr[1]
-            }
-            const creatTime = v.l_createTime ? new Date(v.l_createTime * 1000).pattern('yyyyMMdd') : new Date().pattern('yyyyMMdd')
-            const typeName = v.type ? this.typeObj[v.type.toString()] : '分析报告'
-            v.fileName = `剑鱼标讯-${typeName}-${creatTime}`
-            return v
-          }) || []
+          const list =
+            data.list?.map((v) => {
+              if (v.s_rangeTime) {
+                const rangeTimeArr = v.s_rangeTime.split('-')
+                v.rangeTimeStart = new Date(rangeTimeArr[0] * 1000).getTime()
+                v.rangeTimeEnd = new Date(rangeTimeArr[1] * 1000).getTime()
+              } else if (v.timeRange) {
+                const rangeTimeArr = v.timeRange.split('_')
+                v.rangeTimeStart = rangeTimeArr[0]
+                v.rangeTimeEnd = rangeTimeArr[1]
+              }
+              const creatTime = v.l_createTime
+                ? new Date(v.l_createTime * 1000).pattern('yyyyMMdd')
+                : new Date().pattern('yyyyMMdd')
+              if (v.type === '4') {
+                v.fileName = v.ent
+              } else {
+                const typeName = v.type
+                  ? this.typeObj[v.type.toString()]
+                  : '分析报告'
+                v.fileName = `剑鱼标讯-${typeName}-${creatTime}`
+              }
+              return v
+            }) || []
           this.listState.list = list || []
         } else {
           throw new Error(code)
@@ -493,11 +600,11 @@ export default {
       this.listState.pageSize = size
       this.getList()
     },
-    async getBalanceList () {
+    async getBalanceList() {
       const { data = {}, error_code: code } = await getPDFPackBalance()
-      if(code === 0 && data) {
-        for(let item of this.cardList) {
-          if(data[item.type]) {
+      if (code === 0 && data) {
+        for (let item of this.cardList) {
+          if (data[item.type]) {
             item.total = data[item.type].total
             item.minEndTime = data[item.type].minEndTime
           }
@@ -505,11 +612,14 @@ export default {
       }
     },
     // 立即充值
-    goRecharge (item) {
-      window.open(`/swordfish/page_big_pc/order/download-pack/${item.flag}`, '_self')
+    goRecharge(item) {
+      window.open(
+        `/swordfish/page_big_pc/order/download-pack/${item.flag}`,
+        '_self'
+      )
     },
     // 查看余额明细页面
-    goBalance (item) {
+    goBalance(item) {
       this.$router.push({
         path: '/report/download_record',
         query: {
@@ -519,184 +629,256 @@ export default {
       })
     },
     // 查看报告
-    viewReport () {
+    viewReport() {
       this.$router.push('/desktop/report_analysis')
     },
     // 跳转企业画像
-    goEntPortrayal (id) {
-      if(this.isMember) {
+    goEntPortrayal(id) {
+      if (this.isMember) {
         // 大会员
         window.open(`/swordfish/page_big_pc/ent_portrait/${id}`, '_blank')
       } else {
         // 非大会员
-        window.open(`/swordfish/page_big_pc/svip/ent_ser_portrait/${id}`, '_blank')
+        window.open(
+          `/swordfish/page_big_pc/svip/ent_ser_portrait/${id}`,
+          '_blank'
+        )
       }
     },
     // 进入采购单位画像
-    goUnitPortrayal (name) {
+    goUnitPortrayal(name) {
       window.open(`/swordfish/page_big_pc/unit_portrayal/${name}`, '_blank')
+    },
+    goViewSample() {
+      // const link = this.$router.resolve({
+      //   path: '/free/report/preview',
+      //   query: {
+      //     source: 'bidCreditReportPreview'
+      //   }
+      // })
+      // window.open(link.href, '_blank')
+      window.open(
+        '/swordfish/page_big_pc/free/report/preview?source=bidCreditReportPreview',
+        '_blank'
+      )
+    },
+    goBuyCreditReport() {
+      window.open('/swordfish/page_big_pc/order/credit-report', '_blank')
     }
   }
 }
-
 </script>
 
 <style lang="scss" scoped>
-  $char_color: #1d1d1d;
-  .in-app {
-    .report-download-record {
-      padding: 24px;
-    }
+$char_color: #1d1d1d;
+.in-app {
+  .report-download-record {
+    padding: 24px;
   }
+}
 
-  .report-download-record{
-    margin: 0 auto;
-    .page-header{
-      height: 40px;
-      line-height:40px;
-      vertical-align: text-bottom;
-      h1{
-        display: inline-block;
-        font-size: 24px;
-        line-height:38px;
-        color: $char_color;
-        margin-right: 12px;
-      }
-      em{
-        font-size:12px;
-        color: #999;
-        line-height:18px;
-      }
+.report-download-record {
+  margin: 0 auto;
+  .page-header {
+    height: 40px;
+    line-height: 40px;
+    vertical-align: text-bottom;
+    h1 {
+      display: inline-block;
+      font-size: 24px;
+      line-height: 38px;
+      color: $char_color;
+      margin-right: 12px;
     }
-    .box-container{
-      border-radius: 4px;
-      background: #fff;
-      .box-title{
-        font-size:16px;
-        color: $char_color;
-        line-height:24px;
-        margin-bottom: 12px;
-      }
+  }
+  .box-container {
+    border-radius: 4px;
+    background: #fff;
+    .box-title {
+      font-size: 16px;
+      color: $char_color;
+      line-height: 24px;
+      margin-bottom: 12px;
     }
-    .balance-box{
-      margin: 24px 0 16px;
-      padding: 12px 24px 32px;
-      .card-row{
-        display: grid;
-        grid-template-columns: 1fr 1fr 1fr;
-        grid-column-gap: 24px;
-      }
-      .card-col{
-        background: url(~@/assets/images/report/balance-bg.png) no-repeat center;
-        background-size: cover;
-        padding: 24px 32px;
-        border-radius: 8px;
-        box-shadow: 0 4px 8px rgba(0,0,0, 0.08);
-        font-size: 16px;
-        color: $char_color;
-        .num{
-          margin: 14px 0 20px;
-          display: flex;
-          align-items: flex-end;
-          strong {
-            font-size:40px;
-          }
-          >span{
-            margin-right: 11px;
-          }
+    .balance-tips {
+      margin-left: 12px;
+      font-size: 12px;
+      color: #999;
+      line-height: 18px;
+    }
+  }
+  .balance-box {
+    margin: 24px 0 16px;
+    padding: 12px 24px 32px;
+    .card-row {
+      display: grid;
+      grid-template-columns: 1fr 1fr 1fr;
+      grid-column-gap: 24px;
+    }
+    .card-col {
+      background: url(~@/assets/images/report/balance-bg.png) no-repeat center;
+      background-size: cover;
+      padding: 24px 32px;
+      border-radius: 8px;
+      box-shadow: 0 4px 8px rgba(0, 0, 0, 0.08);
+      font-size: 16px;
+      color: $char_color;
+      .num {
+        margin: 14px 0 20px;
+        display: flex;
+        align-items: flex-end;
+        strong {
+          font-size: 40px;
         }
+        > span {
+          margin-right: 11px;
+        }
+      }
 
-        .date{
-          font-size:14px;
-          color: #999;
-          line-height:22px;
+      .date {
+        font-size: 14px;
+        color: #999;
+        line-height: 22px;
 
-          span:nth-of-type(1) {
-            margin-right: 12px;
-          }
+        span:nth-of-type(1) {
+          margin-right: 12px;
         }
       }
     }
-    .record-box{
-      padding: 12px 20px 24px;
-    }
-    .recharge-button{
-      padding: 4px 17px;
-      font-size: 14px;
-      line-height: 22px;
+  }
+  .record-box {
+    padding: 12px 20px 24px;
+  }
+  .recharge-button {
+    padding: 4px 17px;
+    font-size: 14px;
+    line-height: 22px;
+  }
+  .text-button {
+    font-size: 14px;
+    line-height: 22px;
+    color: #2abed1;
+    cursor: pointer;
+  }
+  .highlight-name {
+    color: #2abed1;
+    cursor: pointer;
+    text-decoration: underline;
+  }
+  .icon-more {
+    font-size: 14px;
+    margin-left: 4px;
+    font-weight: bold;
+  }
+  .max-line-6 {
+    display: -webkit-box;
+    overflow: hidden;
+    text-overflow: ellipsis;
+    -webkit-line-clamp: 6;
+    line-clamp: 6;
+    -webkit-box-orient: vertical;
+    box-orient: vertical;
+  }
+  .ellipsis-1 {
+    display: -webkit-box;
+    overflow: hidden;
+    text-overflow: ellipsis;
+    -webkit-line-clamp: 1;
+    line-clamp: 1;
+    -webkit-box-orient: vertical;
+    box-orient: vertical;
+  }
+  .analyse-condition {
+    color: #1d1d1d;
+    font-size: 14px;
+    line-height: 22px;
+    &:hover {
+      color: #2abed1;
     }
-    .text-button{
+  }
+  .el-pagination-container {
+    margin-right: 0;
+    margin-top: 24px;
+    padding-bottom: 18px;
+  }
+  .view-report-btn {
+    font-size: 16px;
+    line-height: 24px;
+    padding: 6px 34px;
+    margin-top: 56px;
+    border-radius: 6px;
+  }
+  ::v-deep {
+    .el-table .cell {
       font-size: 14px;
+      font-weight: 400;
+      color: #1d1d1d;
       line-height: 22px;
-      color: #2abed1;
-      cursor: pointer;
+      border-bottom-color: rgba(255, 255, 255, 0.5);
     }
-    .highlight-name{
-      color: #2abed1;
-      cursor: pointer;
-      text-decoration: underline;
-    }
-    .icon-more{
-      font-size:14px;
-      margin-left: 4px;
-      font-weight:bold;
+    .el-table th.is-leaf {
+      line-height: 18px;
+      background: #f7f9fc;
+      border-bottom-color: transparent;
     }
-    .max-line-6 {
-      display: -webkit-box;
-      overflow: hidden;
-      text-overflow: ellipsis;
-      -webkit-line-clamp: 6;
-      line-clamp: 6;
-      -webkit-box-orient: vertical;
-      box-orient: vertical;
+    .empty-content-position.v-column .empty-main {
+      margin-top: 0;
     }
-    .ellipsis-1 {
-      display: -webkit-box;
-      overflow: hidden;
-      text-overflow: ellipsis;
-      -webkit-line-clamp: 1;
-      line-clamp: 1;
-      -webkit-box-orient: vertical;
-      box-orient: vertical;
+  }
+  .credit-report-box {
+    height: 60px;
+    padding: 0 24px;
+    margin-bottom: 16px;
+    background: linear-gradient(90deg, #e3fcff 0%, #ffffff 100%);
+    border-radius: 4px;
+    border: 1px solid #87dfea;
+    overflow: hidden;
+    .credit-report-content {
+      position: relative;
     }
-    .analyse-condition {
+    .credit-report-title {
+      margin-right: 12px;
       color: #1d1d1d;
+      font-size: 16px;
+      line-height: 24px;
+      white-space: nowrap;
+    }
+    .credit-report-desc {
+      position: relative;
+      color: #686868;
       font-size: 14px;
       line-height: 22px;
-      &:hover {
-        color: #2abed1;
-      }
+      z-index: 10;
     }
-    .el-pagination-container {
-      margin-right: 0;
-      margin-top:24px;
-      padding-bottom: 18px;
+    .report-action {
+      position: relative;
+      z-index: 10;
+      white-space: nowrap;
     }
-    .view-report-btn{
-      font-size:16px;
-      line-height: 24px;
-      padding: 6px 34px;
-      margin-top:56px;
-      border-radius: 6px;
+    .view-report-sample {
+      color: $color_main;
+      cursor: pointer;
+      font-size: 14px;
+      line-height: 22px;
     }
-    ::v-deep {
-      .el-table .cell {
-        font-size: 14px;
-        font-weight: 400;
-        color: #1d1d1d;
-        line-height: 22px;
-        border-bottom-color: rgba(255, 255, 255, 0.5);
-      }
-      .el-table th.is-leaf {
-        line-height: 18px;
-        background: #f7f9fc;
-        border-bottom-color: transparent;
-      }
-      .empty-content-position.v-column .empty-main {
-        margin-top:0;
-      }
+    .report-to-buy {
+      margin-left: 20px;
+      background: $color_main;
+      color: #fff;
+      font-size: 14px;
+      line-height: 22px;
+      padding: 4px 24px;
+      border-radius: 4px;
+    }
+    .credit-report-icon {
+      position: absolute;
+      top: 50%;
+      right: -80px;
+      width: 112px;
+      height: 60px;
+      transform: translateY(-50%);
+      z-index: 9;
     }
   }
-
-
+}
 </style>