Index.vue 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334
  1. <script setup>
  2. import Aside from "./component/Aside.vue";
  3. import { useStore } from "vuex";
  4. import { computed, ref,watch } from "vue";
  5. import moment from "moment";
  6. import { useRouter } from "vue-router";
  7. const router=useRouter()
  8. const store = useStore();
  9. store.dispatch('getUserInfo')//获取个人信息
  10. const userInfo = computed(() => store.state.userInfo);
  11. const lastTime = computed(() => {
  12. let timeArr = [];
  13. store.state.userInfo.permission_list &&
  14. store.state.userInfo.permission_list.forEach((item) => {
  15. item.permission_list.forEach((item2) => {
  16. timeArr.push(new Date(item2.end_date));
  17. });
  18. });
  19. let maxTime = Math.max(...timeArr);
  20. if (timeArr.length === 0) {
  21. return "";
  22. } else {
  23. return moment(maxTime).format("YYYY.MM.DD");
  24. }
  25. });
  26. import { apiGetPermissionList } from "@/api/common.js";
  27. let permissionList = ref([]);
  28. const getPermissionList = async () => {
  29. const res = await apiGetPermissionList();
  30. if (res.code === 200) {
  31. permissionList.value = res.data;
  32. }
  33. };
  34. getPermissionList();
  35. let permission_list_str = computed(() => {
  36. let hasArr = [];
  37. store.state.userInfo.permission_list &&
  38. store.state.userInfo.permission_list.forEach((item) => {
  39. item.permission_list.forEach((item2) => {
  40. hasArr.push(item2.name);
  41. });
  42. });
  43. let arr = permissionList.value.filter((item) => {
  44. if (hasArr.find((e) => e === item.permission_name)) return item;
  45. });
  46. let arr2=arr.map(item=>item.name)
  47. return arr2.join('/')
  48. });
  49. //我的中点击去申请权限
  50. import { ElMessageBox,ElMessage } from 'element-plus'
  51. import {apiLastApplyRecord} from '@/api/user'
  52. const handleGoApplyPermission=async ()=>{
  53. const res=await apiLastApplyRecord()
  54. if(res.code===200){
  55. if(res.data){
  56. const htmlStr=`<p style="text-align:center;">您已提交过申请,请耐心等待</p>`
  57. ElMessageBox({
  58. title:'申请提醒',
  59. message:htmlStr,
  60. dangerouslyUseHTMLString: true,
  61. confirmButtonText:'知道了',
  62. confirmButtonClass:'self-elmessage-confirm-btn'
  63. })
  64. }else{
  65. router.push({
  66. path:'/apply/permission',
  67. query:{
  68. source:1,
  69. fromPage:'我的'
  70. }
  71. })
  72. }
  73. }
  74. }
  75. //我的中点击联系销售
  76. import {apiApplyPermission} from '@/api/user'
  77. const handleContact=async ()=>{
  78. const res=await apiApplyPermission({
  79. company_name:userInfo.value.company_name,
  80. real_name:userInfo.value.real_name,
  81. source:1,
  82. from_page:'我的',
  83. })
  84. if(res.code===200){
  85. console.log('主动申请成功');
  86. }
  87. const htmlStr=`<p>请联系对口销售--${userInfo.value.seal_name}:${userInfo.value.seal_mobile}</p>`
  88. ElMessageBox({
  89. title:'申请提醒',
  90. message:htmlStr,
  91. dangerouslyUseHTMLString: true,
  92. confirmButtonText:'知道了',
  93. confirmButtonClass:'self-elmessage-confirm-btn'
  94. })
  95. }
  96. // 全局返回按钮
  97. const goBack=()=>{
  98. if(window.history.state.back){
  99. console.log('返回上一页');
  100. router.go(-1)
  101. }else{
  102. console.log('返回首页');
  103. router.push({path:'/'})
  104. }
  105. }
  106. // 音频切换
  107. const handleAudioChange=(e)=>{
  108. store.commit('changeAudio',e)
  109. }
  110. // 关闭音频
  111. const handleAudioClose=()=>{
  112. store.commit('closeAudio')
  113. }
  114. //音频状态改变
  115. const handleAudioStatus=(e)=>{
  116. store.commit('audioStatusChange',e)
  117. }
  118. const globalAudioIns=ref(null)
  119. store.state.audioData.INS=globalAudioIns
  120. </script>
  121. <template>
  122. <div class="layout-wrap">
  123. <el-container style="width: 100%;height:100%">
  124. <Aside></Aside>
  125. <el-main>
  126. <img v-if="$route.meta.hasBack" @click="goBack" class="back-icon" src="@/assets/icon-back.png" alt="">
  127. <!-- <router-view /> -->
  128. <router-view v-slot="{ Component }">
  129. <keep-alive>
  130. <component :is="Component" v-if="$route.meta.keepAlive" />
  131. </keep-alive>
  132. <component :is="Component" v-if="!$route.meta.keepAlive" />
  133. </router-view>
  134. </el-main>
  135. <!-- 个人信息模块 -->
  136. <div class="userinfo-wrap">
  137. <el-popover :width="400" popper-style="box-shadow: rgb(14 18 22 / 35%) 0px 10px 38px -10px, rgb(14 18 22 / 20%) 0px 10px 20px -15px; padding: 20px;">
  138. <template #reference>
  139. <img class="icon-scan" src="@/assets/icon-scan.png" alt="" />
  140. </template>
  141. <template #default>
  142. <div class="flex" style="justify-content: space-between">
  143. <div style="flex: 1; text-align: center">
  144. <img style="width: 121px" src="@/assets/xcx-img.png" alt="" />
  145. <p>手机扫码<br />体验更多小程序功能</p>
  146. </div>
  147. <div style="flex: 1; text-align: center">
  148. <img style="width: 121px" src="@/assets/gzh-img.png" alt="" />
  149. <p>关注弘则研报公众号<br />及时获取活动和报告通知</p>
  150. </div>
  151. </div>
  152. </template>
  153. </el-popover>
  154. <el-popover :width="400" popper-style="box-shadow: rgb(14 18 22 / 35%) 0px 10px 38px -10px, rgb(14 18 22 / 20%) 0px 10px 20px -15px; padding: 20px;">
  155. <template #reference>
  156. <el-avatar shape="square" :size="50" :src="$store.state.globalImgUrls.defaultAvatar"></el-avatar>
  157. </template>
  158. <template #default>
  159. <div class="userinfo-box" v-if="userInfo">
  160. <div class="top">
  161. <el-avatar shape="square" :size="50" :src="$store.state.globalImgUrls.defaultAvatar"></el-avatar>
  162. <p style="font-size: 20px">{{ userInfo.real_name||'--' }}</p>
  163. <p>{{ userInfo.mobile||userInfo.email }}</p>
  164. </div>
  165. <div class="flex info-item">
  166. <div class="label">公司</div>
  167. <div class="con">{{ userInfo.company_name||'--' }}</div>
  168. </div>
  169. <div class="flex info-item">
  170. <div class="label">品种权限</div>
  171. <div class="con" v-if="userInfo.status=='冻结'||(userInfo.status=='试用'&&userInfo.is_suspend==1)">
  172. <span>暂无权限</span>
  173. <span class="btn" @click="handleContact">联系销售</span>
  174. </div>
  175. <div class="con" v-else-if="userInfo.permission_list.length==0">
  176. <span>暂无权限</span>
  177. <span class="btn" @click="handleGoApplyPermission">立即申请</span>
  178. </div>
  179. <div class="con" v-else>{{permission_list_str}}</div>
  180. </div>
  181. <div class="flex info-item">
  182. <div class="label">服务截至日期</div>
  183. <div class="con">{{ lastTime }}</div>
  184. </div>
  185. </div>
  186. </template>
  187. </el-popover>
  188. </div>
  189. </el-container>
  190. <!-- 全局音频模块 -->
  191. <div class="global-audio-box" v-if="$store.state.audioData.list.length>0" v-drag="{'zIndex':100}">
  192. <div style="height:10px;cursor: move;" draggable="true">
  193. <svg @click="handleAudioClose" class="icon" width="20" height="20" viewBox="0 0 1024 1024" xmlns="http://www.w3.org/2000/svg" data-v-042ca774=""><path fill="currentColor" d="M764.288 214.592L512 466.88 259.712 214.592a31.936 31.936 0 00-45.12 45.12L466.752 512 214.528 764.224a31.936 31.936 0 1045.12 45.184L512 557.184l252.288 252.288a31.936 31.936 0 0045.12-45.12L557.12 512.064l252.288-252.352a31.936 31.936 0 10-45.12-45.184z"></path></svg>
  194. </div>
  195. <h2 style="text-align:center;font-size:14px;padding:0 20px">{{$store.state.audioData.list[$store.state.audioData.index].voiceName}}</h2>
  196. <audio
  197. controls
  198. autoplay
  199. @ended="handleAudioChange('auto')"
  200. @pause="handleAudioStatus('paused')"
  201. @play="handleAudioStatus('paly')"
  202. :src="$store.state.audioData.list[$store.state.audioData.index].voiceUrl"
  203. ref="globalAudioIns"
  204. ></audio>
  205. <div style="text-align:center;margin:4px 0 10px 0">
  206. <img src="@/assets/audio-before-grey.png" alt="" style="width:30px;margin-right:20px;cursor: pointer;" @click="handleAudioChange('before')">
  207. <img src="@/assets/audio-before-grey.png" alt="" style="width:30px;transform: rotate(180deg);cursor: pointer;" @click="handleAudioChange('next')">
  208. </div>
  209. </div>
  210. </div>
  211. </template>
  212. <style lang="scss" scoped>
  213. .layout-wrap {
  214. width: 100%;
  215. height: 100%;
  216. background-color: #fff;
  217. position: relative;
  218. }
  219. .el-main {
  220. min-width: 580px;
  221. max-width: 1800px;
  222. background-color: #fff;
  223. padding-left: 60px;
  224. padding-top: 0;
  225. margin-left: auto;
  226. margin-right: auto;
  227. position: relative;
  228. .back-icon{
  229. position: fixed;
  230. left: 180px;
  231. top: 23px;
  232. width: 30px;
  233. height: 30px;
  234. cursor: pointer;
  235. }
  236. }
  237. .userinfo-wrap {
  238. background-color: #fff;
  239. width: 186px;
  240. padding: 20px;
  241. text-align: center;
  242. flex-shrink: 0;
  243. .icon-scan {
  244. width: 26px;
  245. height: 26px;
  246. position: relative;
  247. margin-right: 20px;
  248. top: -10px;
  249. }
  250. }
  251. .userinfo-box {
  252. .top {
  253. text-align: center;
  254. margin-bottom: 31px;
  255. p {
  256. margin: 0;
  257. }
  258. }
  259. .info-item {
  260. padding: 20px 26px 20px 20px;
  261. border-top: 1px solid #ebebeb;
  262. position: relative;
  263. .label {
  264. width: 90px;
  265. margin-right: 19px;
  266. flex-shrink: 0;
  267. }
  268. .con{
  269. .btn{
  270. width: 97px;
  271. height: 30px;
  272. border-radius: 8px;
  273. border: 1px solid #DAB37C;
  274. font-size: 16px;
  275. color: #DAB37C;
  276. display: inline-block;
  277. text-align: center;
  278. line-height: 30px;
  279. position: absolute;
  280. right: 0;
  281. top: 50%;
  282. transform: translateY(-50%);
  283. cursor: pointer;
  284. }
  285. }
  286. }
  287. }
  288. .global-audio-box{
  289. position: fixed;
  290. width: 485px;
  291. height: 150px;
  292. background: #FFFFFF;
  293. box-shadow: 0px 3px 12px 0px rgba(81, 88, 101, 0.16);
  294. border-radius: 8px;
  295. border: 1px solid #EBEBEB;
  296. left: 50%;
  297. bottom: 30px;
  298. transform: translateX(-50%);
  299. z-index: 999;
  300. .icon{
  301. float: right;
  302. position: relative;
  303. right: 10px;
  304. cursor: pointer;
  305. }
  306. audio{
  307. width: 90%;
  308. height: 30px;
  309. display: block;
  310. margin-left: auto;
  311. margin-right: auto;
  312. margin-top: 9px;
  313. }
  314. }
  315. </style>