index.vue 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550
  1. <template>
  2. <view class="devic-box">
  3. <!-- 建议放在外层 -->
  4. <u-navbar
  5. :bgStatusImage="backPic0"
  6. :bgImage="backPic"
  7. title="设备监测"
  8. @leftClick="onLeftClick"
  9. :safeAreaInsetTop="true"
  10. :fixed="true"
  11. height="50px"
  12. bgColor="transparent"
  13. titleStyle="fw600 fs-18"
  14. leftIconColor="#303133"
  15. >
  16. <view class="u-nav-slot" slot="left">
  17. <!-- 菜单选择页显示三横线,选完设备类型进入列表后显示返回键 -->
  18. <view v-if="menushow" class="menu-icon">
  19. <view class="menu-line"></view>
  20. <view class="menu-line"></view>
  21. <view class="menu-line"></view>
  22. </view>
  23. <u-icon v-else name="arrow-left" size="20" color="#303133"></u-icon>
  24. </view>
  25. </u-navbar>
  26. <!-- 左上角三横线展开的菜单 -->
  27. <view
  28. v-if="navMenuShow"
  29. class="nav-menu-mask"
  30. @tap="navMenuShow = false"
  31. ></view>
  32. <view v-if="navMenuShow" class="nav-menu-panel">
  33. <view
  34. class="nav-menu-item"
  35. v-for="(item, index) in navMenuList"
  36. :key="index"
  37. @tap="navMenuClick(item)"
  38. >
  39. {{ item.name }}
  40. </view>
  41. </view>
  42. <view class="devic-box-content">
  43. <view v-if="menushow" class="menupage">
  44. <DeviceMenu @menuClick="menuClick"></DeviceMenu>
  45. </view>
  46. <!-- <u-tabs v-if="!menushow" class="devic-box-tab" :current="PageCur" :list="tabList" @click="NavChange"></u-tabs> -->
  47. <u-tabs
  48. v-if="!menushow"
  49. class="devic-box-tab"
  50. :current="pageCurNew"
  51. :list="tabListNew"
  52. activeStyle="color: #000000; font-weight: 700;"
  53. @click="NavChange"
  54. ></u-tabs>
  55. <!-- 安全监控:设备类型筛选(默认一氧化碳) -->
  56. <view v-if="!menushow && isSafeMonitor" class="devic-box-filter">
  57. <view class="filter-row" @click="openDataTypePicker">
  58. <text class="filter-label">设备类型</text>
  59. <text class="filter-value">{{
  60. dataTypeName || "请选择设备类型"
  61. }}</text>
  62. <u-icon
  63. :name="dataTypeShow ? 'arrow-up' : 'arrow-down'"
  64. size="12"
  65. color="#2b7cff"
  66. ></u-icon>
  67. </view>
  68. <!-- 下拉面板 -->
  69. <view v-if="dataTypeShow" class="filter-dropdown">
  70. <view class="filter-dropdown-scroll">
  71. <view class="filter-option-loading" v-if="!dataTypeLoaded">
  72. <text class="filter-option-text">加载中...</text>
  73. </view>
  74. <view
  75. class="filter-option"
  76. :class="{ active: item.code === dataTypeCode }"
  77. v-for="item in dataTypeOptions"
  78. :key="item.code"
  79. @click.stop="onDataTypeSelect(item)"
  80. >
  81. <text class="filter-option-text">{{ item.name }}</text>
  82. <u-icon
  83. v-if="item.code === dataTypeCode"
  84. name="checkbox-mark"
  85. size="12"
  86. color="#2b7cff"
  87. ></u-icon>
  88. </view>
  89. </view>
  90. </view>
  91. </view>
  92. <!-- 点空白处关闭下拉 -->
  93. <view
  94. v-if="dataTypeShow"
  95. class="filter-dropdown-mask"
  96. @touchmove.stop.prevent
  97. @click="dataTypeShow = false"
  98. ></view>
  99. <view v-if="!menushow" class="devic-box-list">
  100. <!-- <home cur="home" :showColum="showColum" v-if="pageCurNew == '0' && !menushow" :key="0" :deviceType="deviceType"
  101. @setMenushow="setMenushow"></home> -->
  102. <home
  103. ref="homeRef"
  104. cur="home"
  105. :showColum="showColum"
  106. v-if="!menushow"
  107. :key="0"
  108. :deviceType="deviceType"
  109. :filterParams="dataTypeFilterParams"
  110. @setMenushow="setMenushow"
  111. ></home>
  112. <!-- <history :key="1" cur="history" :showColum="showColum" :deviceType="deviceType"
  113. v-if="PageCur == '1' && !menushow" @setMenushow="setMenushow"></history>
  114. <operation :key="2" :showColum="showColum" :deviceType="deviceType" cur="operation"
  115. v-if="PageCur == '2' && !menushow" @setMenushow="setMenushow"></operation> -->
  116. </view>
  117. </view>
  118. </view>
  119. </template>
  120. <script>
  121. import api from "@/api/api";
  122. import DeviceMenu from "./devicemenu/devicemenu.vue";
  123. export default {
  124. components: {
  125. DeviceMenu,
  126. },
  127. data() {
  128. return {
  129. // backPic0: "url(/static/topnavbar0.png)",
  130. // backPic: "url(../../static/topnavbar.png)",
  131. backPic0: "",
  132. backPic: "",
  133. // PageCur: "0",
  134. pageCurNew: "",
  135. showColum: {},
  136. menushow: true,
  137. deviceType: "",
  138. deviceTypeName: "", //当前设备分类名称
  139. //左上角三横线菜单
  140. navMenuShow: false,
  141. navMenuList: [
  142. // component:切换到外层 index.vue 的 tab 组件;url:跳转独立页面
  143. { name: "瓦斯日报", component: "gasreport" },
  144. ],
  145. // tabList: [
  146. // {
  147. // name: "设备监测",
  148. // },
  149. // {
  150. // name: "历史数据",
  151. // },
  152. // {
  153. // name: "操作记录",
  154. // },
  155. // ],
  156. tabListNew: [],
  157. //安全监控的设备类型筛选(默认一氧化碳 0004)
  158. dataTypeList: [],
  159. dataTypeCode: "0004",
  160. dataTypeName: "一氧化碳",
  161. dataTypeShow: false,
  162. dataTypeLoaded: false,
  163. dataTypeLoading: false,
  164. };
  165. },
  166. computed: {
  167. //当前是否为安全监控分类(id 或名称两种方式兼容)
  168. isSafeMonitor() {
  169. const id = String(this.deviceType || "").toLowerCase();
  170. const name = String(this.deviceTypeName || "");
  171. return id.indexOf("safetymonitor") > -1 || name.indexOf("安全监控") > -1;
  172. },
  173. //下拉选项:“全部” + 接口返回的设备类型
  174. dataTypeOptions() {
  175. return [{ code: "", name: "全部" }].concat(this.dataTypeList || []);
  176. },
  177. //下发给列表的筛选条件:全部时传空对象
  178. dataTypeFilterParams() {
  179. if (!this.isSafeMonitor) {
  180. return null;
  181. }
  182. return this.dataTypeCode ? { dataTypeName: this.dataTypeCode } : {};
  183. },
  184. },
  185. watch: {
  186. //切到安全监控分类时拉取设备类型下拉项
  187. deviceType() {
  188. this.ensureDataTypeOptions();
  189. },
  190. deviceTypeName() {
  191. this.ensureDataTypeOptions();
  192. },
  193. },
  194. created() {
  195. this.getShowColum();
  196. },
  197. onLoad: function () {
  198. // this.PageCur = "0";
  199. },
  200. onShow() {
  201. // 从设备详情页返回时,恢复子组件的轮询并立即刷新数据
  202. this.$nextTick(() => {
  203. const homeRef = this.$refs.homeRef;
  204. if (homeRef && typeof homeRef.restartTimer === "function") {
  205. homeRef.restartTimer();
  206. }
  207. });
  208. },
  209. methods: {
  210. // 是安全监控分类时才去拉设备类型下拉项
  211. ensureDataTypeOptions() {
  212. if (this.isSafeMonitor) {
  213. this.loadDataTypeOptions();
  214. }
  215. },
  216. // 安全监控:拉取设备类型下拉项,默认选中一氧化碳
  217. loadDataTypeOptions() {
  218. if (this.dataTypeLoaded || this.dataTypeLoading) {
  219. return;
  220. }
  221. this.dataTypeLoading = true;
  222. api
  223. .getCodeDict({ devicetype: "safetymonitor", code: "dataTypeName" })
  224. .then((response) => {
  225. const raw = response && response.data;
  226. const list = Array.isArray(raw)
  227. ? raw
  228. : raw && Array.isArray(raw.result)
  229. ? raw.result
  230. : [];
  231. this.dataTypeList = list;
  232. this.dataTypeLoaded = true;
  233. // 默认选中一氧化碳,找不到就取第一项
  234. const target =
  235. list.find((item) => item.code === this.dataTypeCode) || list[0];
  236. if (target) {
  237. this.dataTypeCode = target.code;
  238. this.dataTypeName = target.name;
  239. }
  240. })
  241. .catch(() => {})
  242. .then(() => {
  243. this.dataTypeLoading = false;
  244. });
  245. },
  246. openDataTypePicker() {
  247. // 下拉浮层:选项未加载完时先拉一次
  248. if (!this.dataTypeLoaded) {
  249. this.loadDataTypeOptions();
  250. }
  251. this.dataTypeShow = !this.dataTypeShow;
  252. },
  253. onDataTypeSelect(item) {
  254. this.dataTypeShow = false;
  255. if (!item) {
  256. return;
  257. }
  258. // code 为空表示“全部”
  259. this.dataTypeCode = item.code || "";
  260. this.dataTypeName = item.name || "全部";
  261. },
  262. NavChange: function (item) {
  263. console.log("item", item);
  264. // this.PageCur = item.index;
  265. this.navMenuShow = false;
  266. this.deviceType = item.id;
  267. this.deviceTypeName = item.name || "";
  268. this.menushow = false;
  269. },
  270. devicemenuShow(e) {
  271. this.menushow = !this.menushow;
  272. },
  273. //左上角图标:菜单选择页展开三横线菜单,已进入列表页则返回菜单选择
  274. onLeftClick() {
  275. if (this.menushow) {
  276. this.toggleNavMenu();
  277. } else {
  278. this.navMenuShow = false;
  279. this.menushow = true;
  280. }
  281. },
  282. //左上角三横线菜单:展开/收起
  283. toggleNavMenu() {
  284. this.navMenuShow = !this.navMenuShow;
  285. },
  286. //点击菜单项:优先切换外层 tab 组件,否则跳转独立页面
  287. navMenuClick(item) {
  288. this.navMenuShow = false;
  289. if (!item) {
  290. return;
  291. }
  292. if (item.component) {
  293. this.$emit("changePage", item.component);
  294. return;
  295. }
  296. if (!item.url) {
  297. return;
  298. }
  299. uni.navigateTo({
  300. url: item.url,
  301. fail: () => {
  302. uni.showToast({ title: "页面不存在", icon: "none" });
  303. },
  304. });
  305. },
  306. menuClick(params) {
  307. debugger;
  308. this.navMenuShow = false;
  309. let data = params.menu
  310. .map((item) => item.children)
  311. .flatMap((i) => i)
  312. .map((v, index) => {
  313. return {
  314. name: v.itemText,
  315. id: v.itemValue,
  316. index: index,
  317. };
  318. });
  319. this.deviceType = params.id;
  320. this.tabListNew = data;
  321. const cur = this.tabListNew.find((item) => item.id == params.id);
  322. this.deviceTypeName = (cur && cur.name) || "";
  323. this.pageCurNew = cur ? cur.index : 0;
  324. console.log("data", data);
  325. this.menushow = false;
  326. },
  327. getShowColum() {
  328. new Promise((resolve, reject) => {
  329. api
  330. .getShowColum({})
  331. .then((response) => {
  332. if (response.data.code == 200) {
  333. var showlist = response.data.result;
  334. this.$store.commit("SET_SHOWCOLUM", showlist);
  335. this.showColum = showlist;
  336. console.log("showColum", this.showColum);
  337. } else {
  338. resolve(response);
  339. }
  340. })
  341. .catch((error) => {
  342. console.log("catch===>response", response);
  343. reject(error);
  344. });
  345. });
  346. },
  347. setMenushow(params) {
  348. if (params) {
  349. this.menushow = params.menushow;
  350. }
  351. },
  352. },
  353. };
  354. </script>
  355. <style lang="scss" scoped>
  356. // .devic-box {
  357. // // background: #f4f7fd;
  358. // }
  359. .devic-box-content {
  360. height: calc(100vh - 101px - var(--status-bar-height, 0px));
  361. margin-top: calc(50px + var(--status-bar-height, 0px));
  362. display: flex;
  363. flex-direction: column;
  364. overflow: hidden;
  365. // background: #f4f7fd;
  366. }
  367. /* u-tabs 固定在顶部,只有下方列表区域滚动 */
  368. .devic-box-tab {
  369. flex-shrink: 0;
  370. position: relative;
  371. z-index: 2;
  372. }
  373. /* 安全监控的设备类型筛选条,固定在 tab 下方 */
  374. .devic-box-filter {
  375. position: relative;
  376. z-index: 21;
  377. flex-shrink: 0;
  378. margin: 0px 15px;
  379. padding: 0px 16rpx;
  380. height: 72rpx;
  381. box-sizing: border-box;
  382. border-radius: 10rpx;
  383. background-color: #f9f9fb;
  384. border: 1rpx solid #fff;
  385. .filter-row {
  386. display: flex;
  387. flex-direction: row;
  388. align-items: center;
  389. height: 100%;
  390. }
  391. .filter-label {
  392. flex-shrink: 0;
  393. font-size: 26rpx;
  394. color: #303133;
  395. margin-right: 12rpx;
  396. }
  397. .filter-value {
  398. flex: 1;
  399. min-width: 0;
  400. font-size: 26rpx;
  401. color: #2b7cff;
  402. text-align: right;
  403. margin-right: 8rpx;
  404. overflow: hidden;
  405. white-space: nowrap;
  406. text-overflow: ellipsis;
  407. }
  408. /* 下拉面板:贴着筛选条下方展开,限制高度内部滚动 */
  409. .filter-dropdown {
  410. position: absolute;
  411. left: 0;
  412. right: 0;
  413. top: 100%;
  414. margin-top: 8rpx;
  415. max-height: 420rpx;
  416. background-color: #ffffff;
  417. border: 1rpx solid #e6ecf8;
  418. border-radius: 10rpx;
  419. box-shadow: 0 8rpx 24rpx rgba(43, 124, 255, 0.12);
  420. overflow: hidden;
  421. box-sizing: border-box;
  422. }
  423. .filter-dropdown-scroll {
  424. max-height: 420rpx;
  425. overflow-y: auto;
  426. }
  427. .filter-option,
  428. .filter-option-loading {
  429. display: flex;
  430. flex-direction: row;
  431. align-items: center;
  432. justify-content: space-between;
  433. height: 72rpx;
  434. padding: 0px 16rpx;
  435. box-sizing: border-box;
  436. }
  437. .filter-option-text {
  438. font-size: 26rpx;
  439. color: #303133;
  440. }
  441. .filter-option.active,
  442. .filter-option:active {
  443. background-color: #f2f7ff;
  444. }
  445. .filter-option.active .filter-option-text {
  446. color: #2b7cff;
  447. font-weight: 600;
  448. }
  449. }
  450. /* 下拉展开时的透明遮罩,点空白关闭 */
  451. .filter-dropdown-mask {
  452. position: fixed;
  453. left: 0;
  454. top: 0;
  455. right: 0;
  456. bottom: 0;
  457. z-index: 20;
  458. background: transparent;
  459. }
  460. .devic-box-list {
  461. flex: 1;
  462. min-height: 0;
  463. overflow-y: auto;
  464. }
  465. .menupage {
  466. flex: 1;
  467. min-height: 0;
  468. overflow-y: auto;
  469. // background: #f4f7fd;
  470. }
  471. ::v-deep .u-tabs__wrapper {
  472. margin: 0px 15px !important;
  473. }
  474. //左上角三横线图标
  475. .menu-icon {
  476. width: 18px;
  477. height: 14px;
  478. display: flex;
  479. flex-direction: column;
  480. justify-content: space-between;
  481. .menu-line {
  482. width: 18px;
  483. height: 2px;
  484. border-radius: 1px;
  485. background-color: #303133;
  486. }
  487. }
  488. //三横线展开的下拉菜单
  489. .nav-menu-mask {
  490. position: fixed;
  491. left: 0;
  492. top: 0;
  493. right: 0;
  494. bottom: 0;
  495. background-color: rgba(0, 0, 0, 0.15);
  496. z-index: 998;
  497. }
  498. .nav-menu-panel {
  499. position: fixed;
  500. left: 10px;
  501. top: calc(var(--status-bar-height) + 54px);
  502. width: 140px;
  503. padding: 4px 0px;
  504. box-sizing: border-box;
  505. border-radius: 8px;
  506. background-color: #fff;
  507. box-shadow: 0 4px 12px rgba(0, 0, 0, 0.12);
  508. z-index: 999;
  509. .nav-menu-item {
  510. height: 44px;
  511. padding: 0px 16px;
  512. display: flex;
  513. align-items: center;
  514. font-size: 14px;
  515. color: #303133;
  516. &:active {
  517. background-color: #f2f6ff;
  518. }
  519. & + .nav-menu-item {
  520. border-top: 1px solid #f0f2f5;
  521. }
  522. }
  523. }
  524. </style>