AppMain.vue 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568
  1. <template>
  2. <section class="app-main">
  3. <!-- -->
  4. <transition name="fade-transform" mode="out-in">
  5. <div>
  6. <router-view v-slot="{ Component }">
  7. <!-- <keep-alive>
  8. <component v-if="!keep" :is="Component" />
  9. </keep-alive> v-if="keep"-->
  10. <component :is="Component" />
  11. </router-view>
  12. <!-- <keep-alive exclude="nocatch">
  13. <router-view :key="key" v-if="needKeep" />
  14. </keep-alive>
  15. <router-view v-if="!needKeep" :key="key" /> -->
  16. </div>
  17. </transition>
  18. <serviceRemind />
  19. <div style="z-index: 5000">
  20. <el-dialog
  21. :visible.sync="guideVisible"
  22. width="680px"
  23. :modal="false"
  24. v-if="guideList.length > 0"
  25. append-to-body
  26. class="dialogGuide"
  27. >
  28. <template #title>
  29. <div class="dialogHead">
  30. <h2 class="guideH2">您需要完成以下设置</h2>
  31. <el-divider class="guideLine"></el-divider>
  32. </div>
  33. </template>
  34. <div class="guideWrap">
  35. <div class="guideItem" v-for="guide in guideList" :key="guide.name">
  36. <p>
  37. <span class="guideTitle">{{ guide.name }}</span>
  38. <el-button
  39. class="guideSet"
  40. type="text"
  41. @click="gotoSet(guide)"
  42. v-if="permission(guide.permission)"
  43. >立即设置 >></el-button
  44. >
  45. <span v-else>您暂无此设置权限,请联系机构管理员</span>
  46. </p>
  47. <p class="guideDesc">{{ guide.desc }}</p>
  48. </div>
  49. <!-- <el-button
  50. type="primary"
  51. style="width: 100%"
  52. @click="guideVisible = false"
  53. >暂不设置</el-button
  54. > -->
  55. </div>
  56. </el-dialog>
  57. </div>
  58. <div
  59. class="optionBtn"
  60. v-if="!outOptionvisible && isShowBtn"
  61. @click="openOptionMual"
  62. >
  63. 操作手册
  64. </div>
  65. <div class="chart-join">
  66. <el-badge
  67. :value="noReadNum"
  68. class="item"
  69. :max="99"
  70. :hidden="noReadNum <= 0"
  71. >
  72. <!-- <el-button size="small">评论</el-button> -->
  73. <svg
  74. t="1659606821949"
  75. class="icon optionMessage"
  76. viewBox="0 0 1024 1024"
  77. version="1.1"
  78. xmlns="http://www.w3.org/2000/svg"
  79. p-id="3078"
  80. width="48"
  81. height="48"
  82. @click="
  83. () => {
  84. chatVisible = true;
  85. this.$bus.$emit('scrollToBottom');
  86. }
  87. "
  88. >
  89. <path
  90. d="M512 796a456.672 456.672 0 0 1-74.768-6.4L262 896V718.976C170.64 654.832 112 556.48 112 446 112 252.704 291.088 96 512 96s400 156.704 400 350S732.912 796 512 796z m0-650c-193.296 0-350 134.32-350 300 0 101.664 59.2 191.344 149.376 245.6l-1.6 115.968 117.68-70.736a404.8 404.8 0 0 0 84.544 9.168c193.296 0 350-134.304 350-300S705.296 146 512 146zM336 400a48 48 0 1 1-48 48 48 48 0 0 1 48-48z m176 0a48 48 0 1 1-48 48 48 48 0 0 1 48-48z m176 0a48 48 0 1 1-48 48 48 48 0 0 1 48-48z"
  91. p-id="3079"
  92. ></path>
  93. </svg>
  94. </el-badge>
  95. </div>
  96. <el-drawer
  97. title="操作手册"
  98. :visible.sync="outOptionvisible"
  99. size="410px"
  100. :append-to-body="true"
  101. >
  102. <el-divider class="outOptionLine"></el-divider>
  103. <div class="drawerWrap">
  104. <el-form :model="form" :inline="true">
  105. <el-form-item>
  106. <el-input
  107. style="width: 265px !important"
  108. v-model="form.search"
  109. placeholder="请输入菜单名"
  110. clearable
  111. @clear="getMUal()"
  112. ></el-input>
  113. </el-form-item>
  114. <el-form-item>
  115. <el-button @click="getMUal()" type="danger">搜索</el-button>
  116. </el-form-item>
  117. <br />
  118. <!-- <div class="topline"></div> -->
  119. <div
  120. v-for="(item, index) in optionList"
  121. :key="index"
  122. class="line"
  123. @click="openDetail(item)"
  124. >
  125. <el-row>
  126. <el-col :span="23">{{ item.name }}</el-col>
  127. <el-col :span="1"><i class="el-icon-arrow-right"></i></el-col>
  128. </el-row>
  129. </div>
  130. </el-form>
  131. </div>
  132. </el-drawer>
  133. <el-drawer
  134. :title="activeRow.name"
  135. :append-to-body="true"
  136. v-if="activeRow"
  137. :visible.sync="innerDrawer"
  138. size="410px"
  139. custom-class="innerDrawer"
  140. >
  141. <p class="submitTitle">更新时间: {{ activeRow.updateTime }}</p>
  142. <el-tabs v-model="activeName" type="card" @tab-click="handleClick">
  143. <el-tab-pane label="操作流程" name="first">
  144. <div class="optionWrap">
  145. <el-image
  146. ref="previewImg"
  147. class="previewImg"
  148. :src="activeImg"
  149. :preview-src-list="[activeImg]"
  150. style="display: none"
  151. ></el-image>
  152. <div class="ql-editor" v-html="activeRow.opFlow"></div>
  153. </div>
  154. </el-tab-pane>
  155. <el-tab-pane label="功能规则" name="second">
  156. <div class="optionWrap">
  157. <div class="ql-editor" v-html="activeRow.funRule"></div>
  158. </div>
  159. </el-tab-pane>
  160. </el-tabs>
  161. </el-drawer>
  162. <el-drawer
  163. :append-to-body="true"
  164. :visible.sync="chatVisible"
  165. size="910px"
  166. :class="loadChatDom ? '' : 'drawer-container'"
  167. custom-class="innerDrawer"
  168. :withHeader="false"
  169. >
  170. <chat-model ref="chatModel" @close="chatVisible = false" />
  171. </el-drawer>
  172. </section>
  173. </template>
  174. <script>
  175. import notKeepAliveList from "@/router/notKeepAliveList";
  176. import serviceRemind from "@/components/serviceRemind"; // 续费弹窗
  177. import { permission } from "@/utils/directivePage";
  178. import { guideList } from "@/constant/guide";
  179. import chatModel from "./modal/chat-model";
  180. import {
  181. getSysManualList,
  182. getSysManualMenuIds
  183. } from "@/views/operationManual/api";
  184. import "quill/dist/quill.core.css";
  185. import "quill/dist/quill.snow.css";
  186. import "quill/dist/quill.bubble.css";
  187. import { core, CoreEvent } from "./imkit";
  188. import * as RongIMLib from "@rongcloud/imlib-next";
  189. import { custom_service } from "./modal/chat.js";
  190. // 接入时需要将 '请更换您应用的 appkey' 替换为您的应用的 appkey
  191. let libOption = { appkey: "c9kqb3rdc451j" };
  192. // 初始化 SDK
  193. core.init({
  194. service: custom_service,
  195. libOption: libOption,
  196. conversationPullCount: 20
  197. });
  198. export default {
  199. name: "AppMain",
  200. data() {
  201. return {
  202. guideVisible: false,
  203. guideList: [],
  204. outOptionvisible: false,
  205. optionList: [],
  206. form: {},
  207. activeRow: null,
  208. innerDrawer: false,
  209. activeName: "first",
  210. allIdList: [],
  211. isShow: false,
  212. activeImg: null,
  213. loadChatDom: false,
  214. chatVisible: true,
  215. noReadNum: 0 // 消息未读数
  216. };
  217. },
  218. components: { serviceRemind, chatModel },
  219. computed: {
  220. key() {
  221. return this.$route.path;
  222. },
  223. needKeep() {
  224. return !notKeepAliveList.includes(this.$route.path);
  225. },
  226. cachedViews() {
  227. return this.$store.state.tagsView.cachedViews;
  228. },
  229. keep() {
  230. return this.$route.meta.noCache * 1; // 0是缓存 1是不缓存
  231. },
  232. isShowBtn() {
  233. return this.allIdList.indexOf(this.$route.meta.id + "") != -1;
  234. }
  235. },
  236. async mounted() {
  237. console.log(this.$store.state.user, "userInfo");
  238. this.chatVisible = false;
  239. setTimeout(() => {
  240. this.loadChatDom = true;
  241. }, 1000);
  242. // console.log(this.$ref.chatModel);
  243. this.$bus.$on("showguide", obj => {
  244. this.guideList = [];
  245. obj.forEach(element => {
  246. if (guideList[element]) {
  247. this.guideList.push(guideList[element]);
  248. }
  249. });
  250. this.guideVisible = true;
  251. });
  252. try {
  253. const res = await getSysManualMenuIds();
  254. this.allIdList = res.data.split(",");
  255. } catch (e) {}
  256. this.init();
  257. this.$bus.$on("getNoReadNum", this.getNoReadMessage);
  258. },
  259. beforeDestroy() {
  260. this.$bus.$off("showguide", () => {});
  261. this.$bus.$off("getNoReadNum", this.getNoReadMessage);
  262. // core.off(CoreEvent.MESSAGES, this.handleMessages);
  263. const Events = RongIMLib.Events;
  264. RongIMLib.removeEventListener(Events.MESSAGES, this.handleMessages);
  265. },
  266. methods: {
  267. init() {
  268. core.connect(this.$store.state.user.imToken).then(res => {
  269. if (res.code === RongIMLib.ErrorCode.SUCCESS) {
  270. console.log("链接成功, 链接用户 id 为: ", res.data.userId);
  271. // this.isConnect = true;
  272. this.getNoReadMessage();
  273. } else {
  274. console.warn("链接失败, code:", res.code);
  275. }
  276. });
  277. // const Events = RongIMLib.Events;
  278. // RongIMLib.addEventListener(Events.MESSAGES, this.getNoReadMessage);
  279. // RongIMLib.addEventListener(Events.MESSAGE_RECEIPT_RESPONSE, message => {
  280. // console.log("121212", message);
  281. // });
  282. },
  283. handleMessages(newMessage) {
  284. console.log(newMessage, "newMessage");
  285. this.getNoReadMessage();
  286. },
  287. getNoReadMessage() {
  288. RongIMLib.getTotalUnreadCount().then(res => {
  289. if (res.code === 0) {
  290. console.log(res.code, res);
  291. this.noReadNum = res.data || 0;
  292. } else {
  293. console.log(res.code, res.msg, res);
  294. }
  295. });
  296. },
  297. showInstructions() {
  298. this.isShow = !this.isShow;
  299. },
  300. // openIns() {
  301. // this.$refs.instructions.showInstructions();
  302. // },
  303. gotoSet(guide) {
  304. // console.log();
  305. this.$router.push({ path: guide.path });
  306. this.guideVisible = false;
  307. },
  308. permission(str) {
  309. return permission(str);
  310. },
  311. async openOptionMual() {
  312. // this.outOptionvisible = true;
  313. await this.getMUal();
  314. this.outOptionvisible = true;
  315. },
  316. async getMUal() {
  317. let menuId = this.$route.meta.id;
  318. try {
  319. const res = await getSysManualList({
  320. menuId,
  321. page: 1,
  322. rows: 9999,
  323. search: this.form.search
  324. });
  325. this.optionList = res.data.rows;
  326. console.log(this.$route);
  327. } catch (e) {
  328. console.log(e);
  329. }
  330. },
  331. openDetail(row) {
  332. // console.log(row);
  333. this.activeRow = row;
  334. this.innerDrawer = true;
  335. this.$nextTick(res => {
  336. Array.from(document.querySelectorAll("img")).forEach(img => {
  337. img.addEventListener("click", this.previewImg, true);
  338. });
  339. });
  340. },
  341. handleClick(val) {
  342. this.activeName = val.name;
  343. },
  344. previewImg(data) {
  345. let imgSrc = data.target.getAttribute("src");
  346. this.activeImg = imgSrc;
  347. this.$refs.previewImg.clickHandler();
  348. }
  349. },
  350. watch: {
  351. innerDrawer(val) {
  352. if (!val) {
  353. this.activeName = "first";
  354. }
  355. }
  356. }
  357. };
  358. </script>
  359. <style lang="scss" scoped>
  360. .drawer-container {
  361. display: none !important;
  362. }
  363. .previewImg {
  364. }
  365. ::v-deep .el-drawer__header {
  366. font-size: 20px;
  367. margin-bottom: 0px;
  368. line-height: 24px;
  369. color: rgba(0, 0, 0, 0.9);
  370. font-weight: bold;
  371. }
  372. .outOptionLine {
  373. margin: 20px 0 0 0;
  374. background-color: #e5e5e5;
  375. }
  376. .innerDrawer {
  377. .submitTitle {
  378. margin: 10px 0;
  379. font-size: 12px;
  380. padding: 0 20px;
  381. color: #999;
  382. }
  383. .optionWrap {
  384. box-sizing: border-box;
  385. width: 100%;
  386. padding: 10px 8px;
  387. ::v-deep img {
  388. width: 100%;
  389. cursor: pointer;
  390. }
  391. ::v-deep p {
  392. line-height: 28px;
  393. font-size: 14px !important;
  394. }
  395. ::v-deep .ql-video {
  396. width: 100%;
  397. }
  398. }
  399. }
  400. .optionBtn {
  401. width: 35px;
  402. background-color: var(--color-primary);
  403. color: #fff;
  404. position: fixed;
  405. right: 0;
  406. top: 250px;
  407. padding: 10px;
  408. border-radius: 8px;
  409. cursor: pointer;
  410. z-index: 3999;
  411. }
  412. .chart-join {
  413. position: fixed;
  414. right: 36px;
  415. bottom: 36px;
  416. z-index: 99;
  417. ::v-deep .el-badge__content {
  418. display: flex;
  419. align-items: center;
  420. }
  421. }
  422. .optionMessage {
  423. cursor: pointer;
  424. padding: 6px;
  425. width: 46px;
  426. height: 46px;
  427. box-sizing: border-box;
  428. border-radius: 50%;
  429. background-color: #fff;
  430. border: 1px solid #dcdfe6;
  431. z-index: 99;
  432. }
  433. ::v-deep .line {
  434. height: 40px;
  435. line-height: 40px;
  436. color: rgba(#666, 0.9);
  437. padding: 0 17px;
  438. overflow: hidden;
  439. // background-color: #f9f9f9;
  440. cursor: pointer;
  441. margin-bottom: 10px;
  442. position: relative;
  443. border-radius: 4px;
  444. &:hover {
  445. background-color: transparent;
  446. color: var(--color-primary);
  447. font-weight: 600;
  448. &::after {
  449. content: "";
  450. width: 100%;
  451. height: 100%;
  452. background-color: var(--color-primary);
  453. opacity: 0.05;
  454. position: absolute;
  455. left: 0;
  456. top: 0;
  457. }
  458. }
  459. }
  460. .drawerWrap {
  461. padding: 20px;
  462. .topline {
  463. border-top: 1px solid #dcdfe6;
  464. }
  465. }
  466. .guideLine {
  467. margin: 18px 0 0px;
  468. }
  469. .guideWrap {
  470. .guideH2 {
  471. font-size: 20px;
  472. font-weight: 600;
  473. color: #212121;
  474. line-height: 28px;
  475. }
  476. .guideItem {
  477. margin-bottom: 30px;
  478. .guideTitle {
  479. width: 160px;
  480. text-align: left;
  481. font-weight: bold;
  482. display: inline-block;
  483. font-size: 16px;
  484. font-weight: 600;
  485. color: #212121;
  486. line-height: 22px;
  487. margin-bottom: 10px;
  488. }
  489. .guideDesc {
  490. color: #666666;
  491. line-height: 20px;
  492. font-size: 14px;
  493. }
  494. .guideSet {
  495. font-size: 16px;
  496. }
  497. }
  498. }
  499. .dialogGuide {
  500. border-radius: 6px;
  501. ::v-deep .el-dialog__header {
  502. background-color: #fff;
  503. padding-top: 15px;
  504. padding-bottom: 0;
  505. .el-dialog__headerbtn {
  506. top: 28px;
  507. .el-icon {
  508. color: #999;
  509. font-size: 20px;
  510. // font-weight: bold;
  511. }
  512. }
  513. }
  514. .dialogHead {
  515. background-color: #fff;
  516. padding-top: 10px;
  517. }
  518. }
  519. /*设置字体的大小*/
  520. </style>
  521. <style scoped>
  522. .app-main {
  523. /*50 = navbar */
  524. /* height: calc(100vh - 80px); */
  525. /* height: 100vh; */
  526. padding-top: 90px;
  527. /* min-width: 1440px; */
  528. position: relative;
  529. /* overflow: auto; */
  530. box-sizing: border-box;
  531. margin-left: 20px;
  532. margin-top: 20px;
  533. }
  534. .fixed-header + .app-main {
  535. padding-top: 90px;
  536. }
  537. </style>
  538. <style lang="scss">
  539. // fix css style bug in open el-dialog
  540. .el-popup-parent--hidden {
  541. .fixed-header {
  542. // padding-right: 15px;
  543. }
  544. }
  545. .el-image-viewer__close {
  546. display: none !important;
  547. }
  548. </style>