index.vue 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701
  1. <template>
  2. <view class="index-v">
  3. <!-- #ifndef MP -->
  4. <uni-nav-bar class='nav' :fixed="true" :statusBar="true" :border="false" :right-icon="rightIcon"
  5. @clickRight="scan">
  6. <!-- 左边插槽 -->
  7. <template #left>
  8. <view class="">
  9. <uni-icons class='icon-ym icon-ym-app-role-toggle' color="#222222" size="20"
  10. @click="showSelectBox(0)" />
  11. </view>
  12. </template>
  13. <template #default>
  14. <view class="nav-left">
  15. <view class="nav-left-text">
  16. USKY快速开发平台
  17. </view>
  18. </view>
  19. </template>
  20. </uni-nav-bar>
  21. <template v-if="userInfo.appPortalId">
  22. <view class="portal-select" v-if="columnList.length">
  23. <view class="u-flex portal-select-inner" @click.stop="showSelectBox(1)">
  24. <text class="portal-select-text u-line-1">
  25. {{portalTitle}}
  26. </text>
  27. <uni-icons class='right-icons' type="down" color="#000000" size="14"
  28. v-if="portalList.length > 0 && userInfo.appPortalId"
  29. :class="{'select-right-icons':showSelect && type ==1}" />
  30. </view>
  31. </view>
  32. <mescroll-body ref="mescrollRef" @init="mescrollInit" @down="downCallback" :down="downOption"
  33. @up="upCallback" :up="upOption" :bottombar="false" top='10'>
  34. <view class="portal-v" v-if="authConfig.type==0">
  35. <template v-if="formData.length">
  36. <view class="portal-box" v-for="(item,index) in formData" :key="index">
  37. <portalItem :item='item' ref="portalItem" :key="key" v-if="item.show" />
  38. </view>
  39. </template>
  40. <view v-else class="portal-v portal-nodata">
  41. <view class="u-flex-col" style="align-items: center;">
  42. <u-image width="280rpx" height="280rpx" :src="emptyImg1"></u-image>
  43. <text class="u-m-t-20" style="color: #909399;">{{$t('common.noData')}}</text>
  44. </view>
  45. </view>
  46. </view>
  47. <template v-if="authConfig.type==1">
  48. <!-- #ifdef APP -->
  49. <view v-if="authConfig.linkType==1 && showWebView">
  50. <web-view :src="authConfig.customUrl"></web-view>
  51. </view>
  52. <!-- #endif -->
  53. <!-- #ifdef H5 -->
  54. <view v-if="authConfig.linkType==1 && showWebView">
  55. <web-view :src="authConfig.customUrl" :fullscreen="false"
  56. style="width: 100%;height: calc(100vh - 300rpx);"></web-view>
  57. </view>
  58. <!-- #endif -->
  59. <view v-else class="portal-v portal-nodata">
  60. <view class="u-flex-col" style="align-items: center;">
  61. <u-image width="280rpx" height="280rpx" :src="emptyImg"></u-image>
  62. <text class="u-m-t-20" style="color: #909399;">当前内容无法在APP上显示,请前往PC门户查看~~</text>
  63. </view>
  64. </view>
  65. </template>
  66. </mescroll-body>
  67. </template>
  68. <view class="portal-v" style="padding-top: 20rpx;" v-else>
  69. <view class="portal-box">
  70. <defaultPortal></defaultPortal>
  71. </view>
  72. </view>
  73. <u-popup v-model="showSelect" mode="bottom" class="select-box" height="600rpx" @close="closePopup">
  74. <view class="search-box" v-if="type == 1">
  75. <u-search :placeholder="$t('app.apply.pleaseKeyword')" v-model="keyword" height="72"
  76. :show-action="false" bg-color="#f0f2f6" shape="square" search-icon-color="#909399" />
  77. </view>
  78. <view v-for="(item,index) in columnList" :key="index" class="select-item" @click="selectItem(item,index)">
  79. <text class="u-m-r-12 u-font-30"
  80. :class="[item.icon,{'currentItem':item.isDefault || item.id === item.appPortalId }]" />
  81. <text class="item-text sysName"
  82. :class="{'currentItem':item.isDefault || item.id === item.appPortalId}">{{item.fullName}}</text>
  83. <u-icon name="checkbox-mark " class="currentItem"
  84. v-if="item.isDefault || item.id === item.appPortalId"></u-icon>
  85. </view>
  86. </u-popup>
  87. <PasswordPopup @submit="dataFormSubmit" :passwordShow="passwordShow" :formData="baseForm"></PasswordPopup>
  88. <!-- #endif -->
  89. <!-- #ifdef MP -->
  90. <view>
  91. <web-view :src="mpPortalUrl"></web-view>
  92. </view>
  93. <!-- #endif -->
  94. </view>
  95. </template>
  96. <script>
  97. var wv; //计划创建的webview
  98. import {
  99. PortalList,
  100. SetPortal
  101. } from '@/api/portal/portal.js'
  102. // #ifndef MP
  103. import MescrollMixin from "@/uni_modules/mescroll-uni/components/mescroll-uni/mescroll-mixins.js"
  104. import IndexMixin from './mixin.js'
  105. import portalItem from '@/pages/portal/components/index.vue'
  106. import defaultPortal from '@/pages/portal/components/defaultPortal.vue'
  107. import {
  108. auth
  109. } from '@/api/portal/portal.js'
  110. // #endif
  111. import resources from '@/libs/resources.js'
  112. import emptyImg from '@/static/image/defPortal.png'
  113. import PasswordPopup from './components/PasswordPopup'
  114. import chat from '@/libs/chat.js'
  115. import {
  116. useChatStore
  117. } from '@/store/modules/chat'
  118. import {
  119. useUserStore
  120. } from '@/store/modules/user'
  121. import {
  122. getUserOrganizes,
  123. updatePassword,
  124. getSystemConfig,
  125. updatePasswordMessage,
  126. setMajor
  127. } from '@/api/common.js'
  128. import {
  129. refreshCurrentPage
  130. } from '@/utils/refreshCurrent.js'
  131. export default {
  132. // #ifndef MP
  133. mixins: [MescrollMixin, IndexMixin],
  134. // #endif
  135. components: {
  136. // #ifndef MP
  137. portalItem,
  138. defaultPortal,
  139. PasswordPopup
  140. // #endif
  141. },
  142. data() {
  143. return {
  144. passwordShow: false,
  145. keyword: '',
  146. showWebView: true,
  147. emptyImg: emptyImg,
  148. emptyImg1: resources.message.nodata,
  149. rightIcon: '',
  150. key: +new Date(),
  151. formData: [],
  152. portalTitle: '门户',
  153. statusBarHeight: '',
  154. showSelect: false,
  155. selectData: {
  156. name: '',
  157. id: ''
  158. },
  159. upOption: {
  160. page: {
  161. num: 0,
  162. size: 50,
  163. time: null
  164. },
  165. empty: {
  166. use: false,
  167. },
  168. textNoMore: this.$t('app.apply.noMoreData'),
  169. },
  170. portalList: [],
  171. id: '',
  172. userInfo: {},
  173. downOption: {
  174. use: true,
  175. auto: true
  176. },
  177. authConfig: {},
  178. token: '',
  179. mpPortalUrl: '',
  180. timer: null,
  181. type: 0,
  182. baseForm: {
  183. passwordStrengthLimit: 0,
  184. passwordLengthMin: false,
  185. passwordLengthMinNumber: 0,
  186. containsNumbers: false,
  187. includeLowercaseLetters: false,
  188. includeUppercaseLetters: false,
  189. containsCharacters: false,
  190. mandatoryModificationOfInitialPassword: 0,
  191. },
  192. userOrganizes: '',
  193. oldUserOrganizes: ''
  194. };
  195. },
  196. onShow() {
  197. this.token = uni.getStorageSync('token')
  198. this.mpPortalUrl = this.define.baseURL + '/pages/portal/mpPortal/index?token=' + this.token
  199. this.userInfo = uni.getStorageSync('userInfo') || {}
  200. this.showSelect = false
  201. if (!this.userInfo.appPortalId) return
  202. // #ifndef MP
  203. this.getPortalList()
  204. this.$nextTick(() => {
  205. this.mescroll.resetUpScroll();
  206. this.portalList = []
  207. })
  208. // #endif
  209. // #ifdef APP
  210. this.rightIcon = 'scan'
  211. // #endif
  212. },
  213. onReady() {
  214. // #ifdef APP
  215. this.setWebview()
  216. // #endif
  217. },
  218. onLoad(e) {
  219. // #ifndef MP
  220. this.token = uni.getStorageSync('token')
  221. // #endif
  222. const chatStore = useChatStore()
  223. if (!chatStore.getSocket) chat && chat.initSocket()
  224. },
  225. computed: {
  226. isPortalListValid() {
  227. return Array.isArray(this.portalList) && this.portalList.length;
  228. },
  229. columnList() {
  230. return this.portalList.filter((o) => (o.fullName && o.fullName.match(this.keyword)))
  231. }
  232. },
  233. methods: {
  234. dataFormSubmit(query) {
  235. updatePassword(query).then((res) => {
  236. const userStore = useUserStore()
  237. userStore.logout().then(() => {
  238. uni.reLaunch({
  239. url: "/pages/login/index",
  240. });
  241. });
  242. })
  243. },
  244. setWebview() {
  245. if (this.authConfig.linkType == 1) {
  246. var currentWebview = this.$scope
  247. .$getAppWebview() //此对象相当于html5plus里的plus.webview.currentWebview()。在uni-app里vue页面直接使用plus.webview.currentWebview()无效
  248. let height = 0;
  249. uni.getSystemInfo({
  250. //成功获取的回调函数,返回值为系统信息
  251. success: (sysinfo) => {
  252. height = sysinfo.windowHeight - 50; //自行修改,自己需要的高度 此处如底部有其他内容,可以直接---(-50)这种
  253. },
  254. complete: () => {}
  255. });
  256. this.$nextTick(() => {
  257. setTimeout(() => {
  258. wv = currentWebview.children()[0]
  259. wv.setStyle({
  260. top: 80,
  261. height,
  262. scalable: true
  263. })
  264. }, 500); //如果是页面初始化调用时,需要延时一下
  265. })
  266. }
  267. },
  268. getSystemConfig() {
  269. updatePasswordMessage();
  270. getSystemConfig().then((res) => {
  271. if (this.userInfo.changePasswordDate == null && res.data
  272. .mandatoryModificationOfInitialPassword == 1) this.passwordShow = true;
  273. this.baseForm = res.data;
  274. });
  275. },
  276. upCallback(keyword) {
  277. auth(this.userInfo.appPortalId).then(res => {
  278. this.authConfig = res.data || {}
  279. let data = JSON.parse(res.data.formData) || {};
  280. this.formData = data.layout ? JSON.parse(JSON.stringify(data.layout)) : [];
  281. this.handelFormData(data);
  282. this.getSystemConfig()
  283. if (data.refresh.autoRefresh) {
  284. this.timer && clearInterval(this.timer);
  285. this.timer = setInterval(() => {
  286. uni.$emit('proRefresh')
  287. }, data.refresh.autoRefreshTime * 60000)
  288. }
  289. this.mescroll.endSuccess(this.formData.length);
  290. this.key = +new Date()
  291. // #ifdef APP
  292. this.setWebview()
  293. // #endif
  294. }).catch(() => {
  295. this.formData = []
  296. this.mescroll.endSuccess(0);
  297. this.mescroll.endErr();
  298. this.key = +new Date()
  299. })
  300. },
  301. handelFormData(data) {
  302. const loop = (list) => {
  303. list.forEach(o => {
  304. o.allRefresh = data.refresh
  305. o.show = false
  306. if (o.visibility && o.visibility.length && o.visibility.includes('app')) o.show =
  307. true
  308. if (o.children && o.children.length) loop(o.children)
  309. })
  310. this.key = +new Date()
  311. }
  312. loop(this.formData)
  313. this.dataList = this.formData.filter(o => o.show)
  314. if (this.dataList.length < 1) {
  315. this.formData = this.dataList
  316. this.mescroll.endSuccess(this.dataList.length);
  317. }
  318. },
  319. isJSON(str) {
  320. try {
  321. var obj = JSON.parse(str);
  322. if (typeof obj == 'object' && obj) {
  323. return true;
  324. } else {
  325. return false;
  326. }
  327. } catch (e) {
  328. return false;
  329. }
  330. },
  331. scan() {
  332. uni.scanCode({
  333. success: res => {
  334. let url = ""
  335. if (this.isJSON(res.result.trim())) {
  336. const result = JSON.parse(res.result.trim())
  337. if (result.t === 'ADP') {
  338. let config = {
  339. isPreview: 1,
  340. moduleId: result.id,
  341. previewType: result.previewType
  342. }
  343. url = '/pages/apply/dynamicModel/index?config=' + this.jnpf.base64.encode(JSON
  344. .stringify(config))
  345. }
  346. if (result.t === 'DFD') {
  347. url = '/pages/apply/dynamicModel/scanForm?config=' + JSON.stringify(result)
  348. }
  349. if (result.t === 'WFP') {
  350. url = '/pages/workFlow/scanForm/index?config=' + JSON.stringify(result)
  351. }
  352. if (result.t === 'report') {
  353. let url_ =
  354. `${this.report}/preview.html?id=${result.id}&token=${this.token}&page=1&from=menu`
  355. url = '/pages/apply/externalLink/index?url=' + encodeURIComponent(url_) +
  356. '&fullName= ' + result.fullName
  357. }
  358. if (result.t === 'portal') {
  359. url = '/pages/portal/scanPortal/index?id=' + result.id
  360. }
  361. if (result.t === 'login') {
  362. url = '/pages/login/scanLogin?id=' + result.id
  363. }
  364. } else {
  365. url = '/pages/my/scanResult/index?result=' + res.result
  366. }
  367. uni.navigateTo({
  368. url,
  369. fail: (err) => {
  370. this.$u.toast("暂无此页面")
  371. }
  372. })
  373. }
  374. });
  375. },
  376. getPortalList() {
  377. PortalList().then(res => {
  378. let list = res.data.list || [];
  379. this.portalList = []
  380. list.map(o => {
  381. o.children && this.portalList.push(...o.children)
  382. this.portalList.forEach(o => {
  383. o.appPortalId = this.userInfo.appPortalId
  384. if (o.id === o.appPortalId) this.portalTitle = o.fullName
  385. })
  386. })
  387. })
  388. },
  389. closePopup() {
  390. // #ifdef APP
  391. this.setWebview()
  392. uni.$emit('showVideo', true)
  393. this.showWebView = true
  394. // #endif
  395. },
  396. showSelectBox(type) {
  397. this.type = type;
  398. if (type === 0) {
  399. getUserOrganizes().then(res => {
  400. this.portalList = res.data;
  401. this.portalList.forEach(o => {
  402. o.icon = 'icon-ym icon-ym-flow-node-condition';
  403. });
  404. if (this.isPortalListValid) this.showSelect = !this.showSelect;
  405. });
  406. } else {
  407. if (this.isPortalListValid) this.showSelect = !this.showSelect;
  408. // #ifndef MP
  409. this.getPortalList();
  410. // #endif
  411. // #ifdef APP
  412. uni.$emit('showVideo', false);
  413. this.showWebView = false;
  414. this.setWebview();
  415. // #endif
  416. }
  417. },
  418. getStatusBarHeight() {
  419. let that = this;
  420. wx.getSystemInfo({
  421. success: function(res) {
  422. that.statusBarHeight = res.statusBarHeight;
  423. },
  424. });
  425. },
  426. /* 组织切换 */
  427. selectItem(item, index) {
  428. if (this.type === 1) {
  429. this.handleTypeOneSelection(item, index);
  430. } else {
  431. this.handleOtherTypeSelection(item);
  432. }
  433. },
  434. handleTypeOneSelection(item, index) {
  435. SetPortal(item.id).then(res => {
  436. this.portalTitle = this.portalList[index].fullName;
  437. this.userInfo.appPortalId = item.id;
  438. // #ifndef MP
  439. this.mescroll.triggerDownScroll();
  440. // #endif
  441. this.showSelectBox(false);
  442. uni.setStorageSync('userInfo', this.userInfo);
  443. });
  444. },
  445. handleOtherTypeSelection(item) {
  446. this.userOrganizes = item.id;
  447. this.portalList = this.portalList.map(o => {
  448. o.isDefault = o.id === item.id;
  449. return o;
  450. });
  451. this.changeMajor(item.id, this.majorType);
  452. },
  453. changeMajor(majorId, majorType) {
  454. let query = {
  455. majorId,
  456. majorType: 'Organize'
  457. }
  458. setMajor(query).then(res => {
  459. return this.getCurrentUser()
  460. }).catch(() => {})
  461. },
  462. getCurrentUser() {
  463. const userStore = useUserStore()
  464. userStore.getCurrentUser().then(() => {
  465. /* 刷新当前页 */
  466. refreshCurrentPage();
  467. })
  468. }
  469. }
  470. }
  471. </script>
  472. <style lang="scss">
  473. page {
  474. background-color: #f0f2f6;
  475. }
  476. .index-v {
  477. .portal-v {
  478. padding: 0 20rpx 20rpx 20rpx;
  479. .portal-box {
  480. width: 100%;
  481. height: 100%;
  482. .htabs {
  483. .u-scroll-box {
  484. height: 80rpx;
  485. .u-tab-item {
  486. border-right: 1px solid #e4e7ed;
  487. &::before {
  488. content: "";
  489. }
  490. }
  491. }
  492. }
  493. .card-v {
  494. &.u-card {
  495. margin: 0rpx !important;
  496. padding: 0rpx !important;
  497. }
  498. }
  499. }
  500. }
  501. .nav {
  502. z-index: 99999;
  503. ::v-deep .uni-navbar__content {
  504. z-index: 99999;
  505. }
  506. ::v-deep .uni-navbar__header-container {
  507. justify-content: center;
  508. }
  509. .nav-left {
  510. max-width: 100%;
  511. display: flex;
  512. align-items: center;
  513. .nav-left-text {
  514. font-weight: 700;
  515. font-size: 32rpx;
  516. flex: 1;
  517. min-width: 0;
  518. white-space: nowrap;
  519. overflow: hidden;
  520. text-overflow: ellipsis;
  521. }
  522. }
  523. }
  524. .portal-select {
  525. background-color: #fff;
  526. height: 80rpx;
  527. padding-left: 20rpx;
  528. line-height: 80rpx;
  529. .portal-select-inner {
  530. width: 200rpx;
  531. height: 100%;
  532. .portal-select-text {
  533. color: #303133;
  534. }
  535. }
  536. .right-icons {
  537. font-weight: 700;
  538. margin-top: 2px;
  539. margin-left: 4px;
  540. transition-duration: 0.3s;
  541. color: #606266 !important;
  542. }
  543. .select-right-icons {
  544. transform: rotate(-180deg);
  545. }
  546. }
  547. .select-box {
  548. overflow-y: scroll;
  549. .search-box {
  550. height: 112rpx;
  551. width: 100%;
  552. padding: 20rpx 20rpx;
  553. z-index: 10000;
  554. background: #fff;
  555. &::after {
  556. content: " ";
  557. position: absolute;
  558. left: 2%;
  559. top: 62px;
  560. box-sizing: border-box;
  561. width: 96%;
  562. height: 1px;
  563. transform: scale(1, .3);
  564. border: 0 solid #e4e7ed;
  565. z-index: 2;
  566. border-bottom-width: 1px;
  567. }
  568. }
  569. .currentItem {
  570. color: #02a7f0;
  571. }
  572. .select-item {
  573. height: 88rpx;
  574. display: flex;
  575. align-items: center;
  576. padding: 0 20rpx;
  577. font-size: 30rpx;
  578. color: #303133;
  579. text-align: left;
  580. position: relative;
  581. &::after {
  582. content: " ";
  583. position: absolute;
  584. left: 2%;
  585. bottom: 0;
  586. box-sizing: border-box;
  587. width: 96%;
  588. height: 1px;
  589. transform: scale(1, .3);
  590. border: 0 solid #e4e7ed;
  591. z-index: 2;
  592. border-bottom-width: 1px;
  593. }
  594. .sysName {
  595. flex: 1;
  596. overflow: auto;
  597. min-width: 0;
  598. font-size: 28rpx;
  599. }
  600. }
  601. }
  602. .popup {
  603. position: absolute;
  604. top: 244rpx;
  605. z-index: 99999;
  606. width: 70%;
  607. height: 200px;
  608. border: 1px solid #ccc;
  609. background-color: #fff;
  610. left: 283rpx;
  611. border-radius: 4rpx;
  612. transform: translate(-50%, -50%) scale(0);
  613. animation: popup-animation 0.4s ease-in-out forwards;
  614. }
  615. .uni-select--mask {
  616. position: fixed;
  617. top: 0;
  618. bottom: 0;
  619. right: 0;
  620. left: 0;
  621. z-index: 2;
  622. }
  623. @keyframes popup-animation {
  624. from {
  625. transform: translate(-50%, -50%) scale(0);
  626. opacity: 0;
  627. }
  628. to {
  629. transform: translate(-50%, -50%) scale(1);
  630. opacity: 1;
  631. }
  632. }
  633. .nav {
  634. z-index: 99999;
  635. ::v-deep .uni-navbar__content {
  636. z-index: 99999;
  637. }
  638. ::v-deep .uni-navbar__header-container {
  639. justify-content: center;
  640. }
  641. .nav-left {
  642. max-width: 100%;
  643. display: flex;
  644. align-items: center;
  645. .nav-left-text {
  646. font-weight: 700;
  647. font-size: 29rpx;
  648. flex: 1;
  649. min-width: 0;
  650. white-space: nowrap;
  651. overflow: hidden;
  652. text-overflow: ellipsis;
  653. }
  654. }
  655. }
  656. }
  657. .portal-nodata {
  658. position: absolute;
  659. top: 450rpx;
  660. width: 100%;
  661. text-align: center;
  662. z-index: 100;
  663. background-color: #f0f2f6;
  664. }
  665. </style>