index.vue 7.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223
  1. <template>
  2. <Page styleReset="headerClass">
  3. <template v-slot:headerLeft>
  4. <div class="homeheaderleft">
  5. <img src="/src/assets/image/home_logo.png">
  6. <div class="text-white">客户管家</div>
  7. </div>
  8. </template>
  9. <template v-slot:headerRight>
  10. <div class="newButton" @click="showModule = true">+ 新建</div>
  11. </template>
  12. <template v-slot:body>
  13. <div class="w-full h-full flex flex-col overflow-hidden">
  14. <!-- 头部 -->
  15. <div class="custom-tabs rounded-b-lg z-10">
  16. <div class="custom-tabs-box text-size-in custom-tabs-rad flex items-center overflow-hidden">
  17. <div :class="`w-1/2 h-full rounded-r-lg items-justify-center ${homepageType == 'workbench' ? 'themeTextColor bg-white font-bold' : ''}`" @click="homepageType = 'workbench'">工作台</div>
  18. <div :class="`w-1/2 h-full rounded-l-lg items-justify-center ${homepageType == 'dataAnalysis' ? 'themeTextColor bg-white font-bold' : ''}`" @click="homepageType = 'dataAnalysis'">数据分析</div>
  19. </div>
  20. </div>
  21. <!-- 内容 -->
  22. <div class="flex-1 overflow-y-auto relative aopiuyt">
  23. <Workbench v-if="homepageType == 'workbench'" />
  24. <DataAnalysis v-if="homepageType == 'dataAnalysis'" />
  25. </div>
  26. </div>
  27. <!-- 显示对应的模块 -->
  28. <van-popup v-model:show="showModule" closeable position="bottom" round>
  29. <div class="newModuleAdded relative">
  30. <div class="text-size-large text-[#474A56] absolute topTitle">客户管家</div>
  31. <div class="flex flex-wrap">
  32. <template v-for="(item) in moduleList" :key="item.id">
  33. <div class="w-16 flex flex-col items-center mrSpacing" @click.stop="toAddEditor(item)">
  34. <div class="newModuleImage">
  35. <img class="w-full h-full" :src="returnImageAddress(item)" alt="">
  36. </div>
  37. <div class="mt-3 text-[#474A56]">{{ item.name }}</div>
  38. </div>
  39. </template>
  40. </div>
  41. </div>
  42. </van-popup>
  43. </template>
  44. <template v-slot:footer>
  45. <Footer />
  46. </template>
  47. </Page>
  48. </template>
  49. <script setup>
  50. import { ref } from "vue";
  51. import { useLifecycle } from "@hooks/useCommon.js";
  52. import useInfoStore from "@store/useInfoStore"
  53. import useRouterStore from "@store/useRouterStore.js";
  54. import { routingInfos } from "@utility/generalVariables.js";
  55. import Footer from "@components/page/footer.vue";
  56. import Workbench from "./component/workbench.vue";
  57. import DataAnalysis from "./component/dataAnalysis.vue";
  58. import requests from "@common/requests"
  59. const userInfo = useInfoStore()
  60. const modulListss = userInfo.modularList.filter(item => item.path != '/biReport')
  61. const router = useRouterStore()
  62. const homepageType = ref('workbench')
  63. const showModule = ref(false)
  64. const moduleList = ref(modulListss)
  65. function toAddEditor(rows) {
  66. const jumpTo = routingInfos[rows.path.replace('/', '')]
  67. router.navigateTo({
  68. pathName: 'addEditor',
  69. success: () => {
  70. router.emit('addEditorParameter', {
  71. routerInfo: JSON.stringify(jumpTo)
  72. })
  73. }
  74. })
  75. }
  76. function returnImageAddress(rows) {
  77. const row = routingInfos[rows.path.replace('/', '')]
  78. return row.homeImage
  79. }
  80. function obtainEnterpriseWeChatParameters(data = {}) {
  81. const token = data.id
  82. // const curUrl = window.location.href.split('home')[0]
  83. const curUrl = window.location.href
  84. requests.post('/wxcorp/getCorpWXConfig', { url: curUrl, token }).then((res) => {
  85. wx.config({
  86. beta: true,
  87. debug: false, // 开启调试模式,调用的所有api的返回值会在客户端alert出来,若要查看传入的参数,可以在pc端打开,参数信息会通过log打出,仅在pc端时才会打印。
  88. appId: res.data.appid, // 必填,公众号的唯一标识
  89. timestamp: res.data.timestamp, // 必填,生成签名的时间戳
  90. nonceStr: res.data.noncestr, // 必填,生成签名的随机串
  91. signature: res.data.sign, // 必填,签名,见附录1
  92. jsApiList: ['chooseImage', 'previewImage', 'uploadImage', 'downloadImage', 'previewFile', 'getLocation', 'agentConfig']
  93. })
  94. wx.ready(function () {
  95. // config信息验证后会执行ready方法,所有接口调用都必须在config接口获得结果之后,config是一个客户端的异步操作,所以如果需要在页面加载时就调用相关接口,则须把相关接口放在ready函数中调用来确保正确执行。对于用户触发时才调用的接口,则可以直接调用,不需要放在ready函数中。
  96. requests.post('/wxcorp/getCorpWXAgentConfig', { url: curUrl, token }).then((res) => {
  97. console.log(res, '<====== 返回的参数 /wxcorp/getCorpWXAgentConfig')
  98. wx.agentConfig({
  99. corpid: res.data.corpid, // 必填,企业微信的corpid,必须与当前登录的企业一致
  100. agentid: res.data.agentid, // 必填,企业微信的应用id (e.g. 1000247)
  101. timestamp: res.data.timestamp, // 必填,生成签名的时间戳
  102. nonceStr: res.data.nonceStr, // 必填,生成签名的随机串
  103. signature: res.data.signature, // 必填,签名,见附录-JS-SDK使用权限签名算法
  104. jsApiList: ['selectExternalContact', 'openThirdAppServiceChat', 'openAppManage'], //必填,传入需要使用的接口名称
  105. success: function (result) {
  106. // wx.agentConfig成功回调后,WWOpenData 才会注入到 window 对象上面
  107. window.WWOpenData.bind(document.querySelector('ww-open-data'))
  108. },
  109. fail: function (res) {
  110. if (res.errMsg.indexOf('function not exist') > -1) {
  111. alert('版本过低请升级')
  112. }
  113. },
  114. })
  115. }).catch(err => {
  116. if (err.errMsg.indexOf('function not exist') > -1) {
  117. alert('版本过低请升级')
  118. }
  119. })
  120. })
  121. wx.error(function (res) {
  122. // config信息验证失败会执行error函数,如签名过期导致验证失败,具体错误信息可以打开config的debug模式查看,也可以在返回的res参数中查看,对于SPA可以在这里更新签名。
  123. // alert('wxConfig发生异常:'+JSON.stringify(res));
  124. // 企业第一次授权安装进入后会报not in reliable domain的错误,刷新后正常
  125. // location.reload();
  126. });
  127. }).catch(err => {
  128. alert(err);
  129. })
  130. }
  131. useLifecycle({
  132. load: () => {
  133. },
  134. init: () => {
  135. const currentEnvironment = navigator.userAgent.toLowerCase();
  136. const isCorpWX = currentEnvironment.indexOf("wxwork") > 0 ? true : false
  137. if(isCorpWX) {
  138. obtainEnterpriseWeChatParameters(userInfo.userInfo)
  139. }
  140. }
  141. });
  142. </script>
  143. <style lang="scss" scoped>
  144. :deep(.van-tabs__content) {
  145. flex: 1;
  146. overflow-y: auto;
  147. }
  148. :deep(.van-tabs__wrap) {
  149. background-color: $themeColor;
  150. }
  151. .homeheaderleft {
  152. font-size: 20px;
  153. font-weight: bold;
  154. display: flex;
  155. align-items: center;
  156. img {
  157. width: 30px;
  158. }
  159. div {
  160. margin-left: 10px;
  161. }
  162. }
  163. .newButton {
  164. width: 86px;
  165. line-height: 30px;
  166. background: #fff;
  167. color: $themeColor;
  168. border-radius: 75px;
  169. }
  170. .custom-tabs {
  171. background: $themeColor;
  172. padding: 22px 15px;
  173. color: #fff;
  174. }
  175. .custom-tabs-box {
  176. width: 100%;
  177. border: 1.5px solid #fff;
  178. height: 50px;
  179. }
  180. .custom-tabs-rad {
  181. border-radius: 6px;
  182. }
  183. .aopiuyt {
  184. margin-top: -6px;
  185. }
  186. .newModuleAdded {
  187. padding: 45px 25px 45px 25px;
  188. }
  189. .newModuleImage {
  190. width: 50px;
  191. height: 50px;
  192. border-radius: 10px;
  193. }
  194. .mrSpacing {
  195. margin-top: 16px;
  196. margin-right: 33px;
  197. &:nth-child(4n) {
  198. margin-right: 0;
  199. }
  200. }
  201. .topTitle {
  202. top: 14px;
  203. }
  204. </style>