Эх сурвалжийг харах

feat: 移动端下载项目报告逻辑添加

cuiyalong 1 жил өмнө
parent
commit
5791826d24

+ 10 - 0
apps/mobile/src/api/modules/bigmember.js

@@ -139,3 +139,13 @@ export function ajaxGetAttachmentList(data) {
     data: qs.stringify(data)
   })
 }
+
+// 下载项目报告,获取报告url
+export function getProjectReport(data) {
+  data = qs.stringify(data)
+  return request({
+    url: '/bigmember/project/getPdfFile',
+    method: 'POST',
+    data
+  })
+}

+ 9 - 0
apps/mobile/src/api/modules/pay.js

@@ -281,3 +281,12 @@ export function useResourcePack(data) {
     data: qs.stringify(data)
   })
 }
+
+// 资源包兑换接口
+export function sendProjectPdfFile(data) {
+  return request({
+    url: '/jypay/sendMailNote/projectPdfFile',
+    method: 'post',
+    data: qs.stringify(data)
+  })
+}

+ 13 - 0
apps/mobile/src/utils/callFn/index.js

@@ -331,7 +331,20 @@ export function callGetToken() {
 export function downLoadFile(filename, filetype, fileurl, filesize) {
   if (inApp) {
     appDownLoadFile(filename, filetype, fileurl, filesize)
+  } else {
+    downLoadFileH5(filename, fileurl)
+  }
+}
+
+export function downLoadFileH5(name, url) {
+  const a = document.createElement('a')
+  const filename = name
+  a.href = url
+  a.target = '_blank'
+  if (filename) {
+    a.download = filename
   }
+  a.click()
 }
 
 /**

+ 25 - 10
apps/mobile/src/views/article/components/ContentProjectTimeline.vue

@@ -5,10 +5,13 @@
     v-if="stepList.length"
   >
     <div class="action-right-container" slot="header-actions">
-      <span class="action-item clickable download-project-doc" v-if="false">
-        <AppIcon name="xiazaixiangmubaogao"></AppIcon>
-        <span class="action-text">下载项目报告</span>
-      </span>
+      <DownProjectReport
+        class="action-item"
+        v-if="hasProject"
+        :id="content.id"
+        :name="projectName"
+        :beforeLeavePage="beforeLeavePage"
+      />
       <span class="action-item clickable follow-project">
         <QuickMonitor
           :beforeLeavePage="beforeLeavePage"
@@ -38,7 +41,8 @@
 <script>
 import ContentModuleCard from '@/views/article/ui/ContentModuleCard.vue'
 import QuickMonitor from '@/composables/quick-monitor/component/QuickMonitor.vue'
-import { AppIcon, TimeLine } from '@/ui'
+import DownProjectReport from '@/views/article/components/DownProjectReport.vue'
+import { TimeLine } from '@/ui'
 import { mapState, mapGetters } from 'vuex'
 import { replaceKeyword, openAppOrWxPage, formatMoney } from '@/utils'
 import { LINKS } from '@/data'
@@ -46,9 +50,9 @@ import { LINKS } from '@/data'
 export default {
   name: 'ContentProjectTimeline',
   components: {
-    AppIcon,
     TimeLine,
     QuickMonitor,
+    DownProjectReport,
     ContentModuleCard
   },
   props: {
@@ -82,9 +86,18 @@ export default {
   computed: {
     ...mapState({
       content: (state) => state.article.mainModel.content,
-      expandModel: (state) => state.article.expandModel
+      expandModel: (state) => state.article.expandModel,
+      otherModel: (state) => state.article.otherModel
     }),
     ...mapGetters('user', ['isNewBusiness']),
+    projectName() {
+      const projectProgress = this.expandModel.projectProgress || {}
+      const projectName = projectProgress.name || ''
+      return projectName
+    },
+    hasProject() {
+      return this.otherModel.hasProject
+    },
     stepList() {
       const projectProgress = this.expandModel.projectProgress || {}
       const projectName = projectProgress.name || ''
@@ -125,13 +138,15 @@ export default {
 </script>
 
 <style lang="scss" scoped>
+.action-right-container {
+  display: flex;
+  align-items: center;
+}
 .action-item {
+  margin-left: 16px;
   color: $main;
   font-size: 14px;
   line-height: 20px;
-  &:not(:last-of-type) {
-    margin-right: 16px;
-  }
   .action-text {
     margin-left: 4px;
   }

+ 176 - 0
apps/mobile/src/views/article/components/DownProjectReport.vue

@@ -0,0 +1,176 @@
+<template>
+  <TabActionItem
+    showText
+    :direction="direction"
+    class="download-project-doc"
+    @click.native.stop="doAction"
+  >
+    <AppIcon slot="icon" name="xiazaixiangmubaogao" size="20" />
+    <template #text>
+      <EmailDialog
+        v-model="dialog.show"
+        :email.sync="dialog.email"
+        title="发送邮箱地址"
+        contentTipText="项目报告文件将以邮件的形式发送至您的邮箱"
+        :beforeClose="beforeEmailDialogClose"
+      />
+      <span>下载项目报告</span>
+    </template>
+  </TabActionItem>
+</template>
+<script>
+import TabActionItem from '@/views/article/ui/TabActionItem.vue'
+import { AppIcon } from '@/ui'
+import { getProjectReport, sendProjectPdfFile } from '@/api/modules/'
+import { mapGetters } from 'vuex'
+import EmailDialog from '@/components/common/EmailDialog.vue'
+import { emailRegExp } from '@/utils/constant/'
+
+export default {
+  name: 'DownloadProjectReport',
+  components: {
+    TabActionItem,
+    EmailDialog,
+    AppIcon
+  },
+  props: {
+    id: {
+      type: String,
+      default: '',
+      required: true
+    },
+    name: {
+      type: String,
+      default: '',
+      required: true
+    },
+    direction: {
+      type: String,
+      default: 'row',
+      validator(d) {
+        return ['row', 'column'].includes(d)
+      }
+    },
+    beforeAction: Function,
+    beforeLeavePage: Function
+  },
+  data() {
+    return {
+      dialog: {
+        show: false,
+        email: ''
+      },
+      link: ''
+    }
+  },
+  computed: {
+    ...mapGetters('user', ['isFree'])
+  },
+  methods: {
+    // 下载(下载前校验)
+    async doAction() {
+      if (this.beforeAction) {
+        const r = await this.beforeAction()
+        if (!r) {
+          return
+        }
+      }
+      if (this.isFree) {
+        return this.goToSvipBuy()
+      }
+
+      if (this.link) {
+        return this.downFile(this.name, this.link)
+      }
+
+      const loading = this.$toast.loading({
+        message: '报告正在生成,请稍后~'
+      })
+      try {
+        const {
+          data,
+          error_code: code,
+          error_msg: msg
+        } = await getProjectReport({ sid: this.id })
+        if (code === 0 && data) {
+          this.link = data.path
+          this.doDownload(this.name, this.link)
+          loading.clear()
+        } else {
+          this.$toast(msg || '获取报告失败,请稍后再试')
+        }
+      } catch (error) {
+        loading.clear()
+        console.error(error)
+      }
+    },
+    doDownload(name, link) {
+      if (this.$envs.inIOS) {
+        this.dialog.show = true
+      } else {
+        this.downFile(name, link)
+      }
+    },
+    /**
+     * 下载文件
+     * @param name
+     * @param url
+     */
+    downFile(name, url) {
+      const a = document.createElement('a')
+      const filename = name
+      a.href = url
+      a.target = '_blank'
+      if (name) {
+        a.download = filename
+      }
+      a.click()
+    },
+    async beforeEmailDialogClose(action, done) {
+      if (action === 'cancel') {
+        return done()
+      }
+      const { email } = this.dialog
+      if (!emailRegExp.test(email)) {
+        done(false)
+        return this.$toast('邮箱地址格式错误')
+      } else {
+        await this.sendEmailConfirm(done)
+      }
+    },
+    async sendEmailConfirm(done) {
+      const { email } = this.dialog
+      const fileUrl = this.link
+      if (!email) {
+        done(false)
+        this.$toast('请输入邮箱地址')
+      }
+      if (!fileUrl) {
+        done(false)
+        this.$toast('报告附件异常')
+      }
+      const params = {
+        downurl: fileUrl,
+        email
+      }
+      const { error_msg: msg, error_code: code } = await sendProjectPdfFile(params)
+      if (code === 0) {
+        done && done()
+        // this.$toast(`已发送至 ${email}`)
+        this.$toast('邮件已发送,请注意查收')
+      } else {
+        done && done(false)
+        this.$toast(msg || '发送失败')
+      }
+    },
+    async goToSvipBuy() {
+      if (this.beforeLeavePage) {
+        await this.beforeLeavePage()
+      }
+      this.$router.push('/free/svip/buy')
+    }
+  }
+}
+</script>
+
+<style lang="scss" scoped></style>