history.vue 24 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890
  1. <template>
  2. <view class="container">
  3. <!-- 建议放在外层 -->
  4. <!-- <u-navbar
  5. title="历史数据"
  6. @leftClick="devicemenuShow"
  7. :safeAreaInsetTop="true"
  8. >
  9. <view class="u-nav-slot" slot="left">
  10. <u-icon name="list" size="20"> </u-icon>
  11. </view>
  12. </u-navbar> -->
  13. <!-- 侧边栏 -->
  14. <view v-show="menushow" class="menupage">
  15. <DeviceMenu @menuClick="menuClick"></DeviceMenu>
  16. </view>
  17. <!-- 历史数据列表页 -->
  18. <view v-if="!menushow" class="main">
  19. <view class="u-page">
  20. <!-- 一、查询条件:上为选择设备 / 间隔时间,下为时间查询 / 查询 -->
  21. <view class="query-card">
  22. <!-- 选择设备 / 间隔时间 -->
  23. <view class="query-row">
  24. <view class="query-btn" @click="deviceShow = true">
  25. {{ deviceName ? deviceName : "选择设备" }}
  26. </view>
  27. <view class="query-btn" @click="show = true">
  28. {{ lable ? lable : "间隔时间" }}
  29. </view>
  30. </view>
  31. <!-- 时间查询 + 查询按钮 -->
  32. <view class="query-row">
  33. <uni-datetime-picker
  34. class="query-item"
  35. type="datetime"
  36. :hideSecond="true"
  37. @confirm="selectStartTime"
  38. v-model="StartTime"
  39. >
  40. <view class="query-picker-inner">
  41. <u-icon name="calendar" size="16" color="#2277fb"></u-icon>
  42. <text class="query-picker-text">{{
  43. StartTime ? StartTime.slice(0, 10) : "开始日期"
  44. }}</text>
  45. </view>
  46. </uni-datetime-picker>
  47. <uni-datetime-picker
  48. class="query-item"
  49. type="datetime"
  50. :hideSecond="true"
  51. @confirm="selectEndTime"
  52. v-model="EndTime"
  53. >
  54. <view class="query-picker-inner">
  55. <u-icon name="calendar" size="16" color="#2277fb"></u-icon>
  56. <text class="query-picker-text">{{
  57. EndTime ? EndTime.slice(0, 10) : "结束日期"
  58. }}</text>
  59. </view>
  60. </uni-datetime-picker>
  61. <view class="query-btn query-btn-query" @click="checkHistory">
  62. 查询
  63. </view>
  64. </view>
  65. <u-picker
  66. :show="deviceShow"
  67. :columns="[devices]"
  68. @cancel="deviceShow = false"
  69. @confirm="selectDevice"
  70. keyName="strinstallpos"
  71. >
  72. </u-picker>
  73. <u-picker
  74. :show="deviceShow1"
  75. :columns="devices1"
  76. @cancel="deviceShow1 = false"
  77. @confirm="selectDevice1"
  78. keyName="label"
  79. ></u-picker>
  80. <u-picker
  81. :show="show"
  82. :columns="timeColumns"
  83. @cancel="show = false"
  84. keyName="label"
  85. @confirm="selectSkipTime"
  86. ></u-picker>
  87. </view>
  88. <u-list class="historycontainer">
  89. <template v-if="historyData.length > 0">
  90. <u-list-item
  91. class="itemback"
  92. v-for="(item, index) in historyData"
  93. :key="index"
  94. >
  95. <u-row
  96. gutter="5"
  97. customStyle="margin-bottom: 10px;color: #ddd;font-weight: bold;"
  98. >
  99. <u-col span="24">
  100. <u--text :text="item.ginstallpos || item.devicePos"></u--text>
  101. </u-col>
  102. </u-row>
  103. <u-row gutter="5" customStyle="margin-bottom: 10px">
  104. <u-col span="4">
  105. <div v-if="item.netStatus == 0" class="error-tag1">
  106. <image
  107. src="/static/model/connectFalse.svg"
  108. alt=""
  109. class="icon-style"
  110. />
  111. <span style="float: right; margin-right: 12rpx">断开</span>
  112. </div>
  113. <div v-else class="success-tag">
  114. <image
  115. src="/static/model/connectTrue.svg"
  116. alt=""
  117. class="icon-style"
  118. />
  119. <span style="float: right; margin-right: 20rpx">连接</span>
  120. </div>
  121. </u-col>
  122. </u-row>
  123. <view class="data-grid">
  124. <view
  125. class="datacard"
  126. v-for="(showitem, sIndex) in deviceShowList"
  127. :key="sIndex"
  128. v-if="
  129. showitem.appShow == 1 &&
  130. showitem.monitorcode != 'strinstallpos' &&
  131. showitem.monitorcode != 'gdevicename' &&
  132. showitem.monitorcode != 'ginstallpos' &&
  133. showitem.monitorcode != 'netStatus' &&
  134. showitem.monitorcode != 'warnFlag' &&
  135. showitem.monitorcode != 'gcreatetime' &&
  136. showitem.monitorcode != 'ttime' &&
  137. showitem.monitorcode != 'time'
  138. "
  139. >
  140. <view class="data-icon">
  141. <view class="data-icon-glass">
  142. <image
  143. class="data-icon-img"
  144. :src="getWindowIcon(showitem)"
  145. mode="aspectFit"
  146. ></image>
  147. </view>
  148. </view>
  149. <view class="data-text">
  150. <text class="data-value">{{
  151. formatFieldValue(item, showitem)
  152. }}</text>
  153. <text class="data-label">{{ showitem.des }}</text>
  154. </view>
  155. </view>
  156. <view class="datacard">
  157. <view class="data-icon">
  158. <view class="data-icon-glass">
  159. <image
  160. class="data-icon-img"
  161. src="/static/warndata/shijian.svg"
  162. mode="aspectFit"
  163. ></image>
  164. </view>
  165. </view>
  166. <view class="data-text">
  167. <text class="data-value">{{
  168. item.time || item.ttime || "-"
  169. }}</text>
  170. <text class="data-label">更新时间</text>
  171. </view>
  172. </view>
  173. </view>
  174. </u-list-item>
  175. </template>
  176. <template v-else>
  177. <!-- 空数据状态 -->
  178. <view class="empty-box">
  179. <image
  180. class="empty-img"
  181. src="/static/empty.png"
  182. mode="widthFix"
  183. ></image>
  184. <text class="empty-text">数据为空</text>
  185. </view>
  186. </template>
  187. </u-list>
  188. </view>
  189. </view>
  190. </view>
  191. </template>
  192. <script>
  193. import api from "@/api/api";
  194. import dayjs from "dayjs";
  195. import DeviceMenu from "../../pages/device/devicemenu/devicemenu";
  196. import uniDatetimePicker from "../../uni_modules/uni-datetime-picker/components/uni-datetime-picker/uni-datetime-picker.vue";
  197. export default {
  198. data() {
  199. return {
  200. menushow: false,
  201. TabCur: "gate",
  202. curlist: [],
  203. colums: [],
  204. deviceList: {},
  205. startDate: null,
  206. endDate: null,
  207. show: false,
  208. deviceShow: false,
  209. deviceShow1: false,
  210. dataShow: false,
  211. dataShow1: false,
  212. StartTime: "", //起始时间
  213. EndTime: "", //结束时间
  214. devices: [], //设备类型数组
  215. devices1: [
  216. [
  217. {
  218. label: "1#风机",
  219. value: "fan1",
  220. },
  221. {
  222. label: "2#风机",
  223. value: "fan2",
  224. },
  225. ],
  226. ], //子设备类型数组
  227. deviceName: "", //设备名称
  228. labelName: "", //子设备名称
  229. timeS: "", //间隔时间
  230. lable: "", //间隔时间
  231. timeColumns: [
  232. [
  233. {
  234. label: "1秒",
  235. value: "1",
  236. value1: "1s",
  237. },
  238. {
  239. label: "5秒",
  240. value: "2",
  241. value1: "5s",
  242. },
  243. {
  244. label: "10秒",
  245. value: "3",
  246. value1: "10s",
  247. },
  248. {
  249. label: "30秒",
  250. value: "4",
  251. value1: "30s",
  252. },
  253. {
  254. label: "1分钟",
  255. value: "5",
  256. value1: "1m",
  257. },
  258. {
  259. label: "10分钟",
  260. value: "6",
  261. value1: "10m",
  262. },
  263. {
  264. label: "30分钟",
  265. value: "7",
  266. value1: "30m",
  267. },
  268. {
  269. label: "1小时",
  270. value: "8",
  271. value1: "1h",
  272. },
  273. ],
  274. ],
  275. deviceID: "", //设备ID
  276. deviceType1: "", //设备类型
  277. skip: 8, //时间间隔
  278. interval: "1h", //时间间隔
  279. dataTime: dayjs().format("YYYY-MM-DD HH:mm:ss"),
  280. historyData: [], //历史数据
  281. deviceShowList: [],
  282. loading: false, // 是否正在加载数据
  283. hasMoreData: true, // 是否还有更多数据可以加载
  284. pageNo: 1, // 当前页码(用于请求数据时分页)
  285. stationType: "plc1", // 站点类型(用于请求数据时的参数)
  286. strType: "", //设备小类
  287. sysId: "",
  288. };
  289. },
  290. components: {
  291. DeviceMenu,
  292. uniDatetimePicker,
  293. },
  294. props: ["showColum", "deviceType"],
  295. watch: {
  296. deviceType: {
  297. async handler(data) {
  298. if (data) {
  299. this.TabCur = data;
  300. console.log(this.TabCur, "设备");
  301. this.curlist = this.deviceList[this.TabCur];
  302. if (this.curlist == null) {
  303. this.curlist = [];
  304. }
  305. // 选择设备分类,重新获取数据
  306. await this.loadData(this.TabCur);
  307. this.$emit("setMenushow", {
  308. menushow: false,
  309. });
  310. }
  311. },
  312. immediate: true,
  313. },
  314. },
  315. created() {
  316. this.colums = this.showColum;
  317. const startTime = new Date().getTime() - 3600 * 1000 * 24 * 30;
  318. const endTime = new Date();
  319. this.StartTime = dayjs(startTime).format("YYYY-MM-DD HH:mm:ss");
  320. this.EndTime = dayjs(endTime).format("YYYY-MM-DD HH:mm:ss");
  321. },
  322. mounted() {
  323. // this.TabCur = deviceType;
  324. if (this.TabCur.startsWith("sys_")) {
  325. this.loadNewData(this.TabCur);
  326. } else {
  327. this.loadData(this.TabCur);
  328. }
  329. },
  330. computed: {},
  331. methods: {
  332. loadData(type) {
  333. new Promise((resolve, reject) => {
  334. api
  335. .getDeviceMonitor({
  336. devicetype: type,
  337. pagetype: "normal",
  338. filterParams: {},
  339. })
  340. .then((response) => {
  341. if (response.data.code == 200) {
  342. this.deviceList[type] = response.data.result.msgTxt[0].datalist;
  343. this.curlist = this.deviceList[type];
  344. this.setData(this.curlist);
  345. } else {
  346. resolve(response);
  347. }
  348. })
  349. .catch((error) => {
  350. reject(error);
  351. });
  352. });
  353. },
  354. loadNewData(type) {
  355. return new Promise((resolve, reject) => {
  356. api
  357. .getSysList({
  358. strtype: type,
  359. pagetype: "normal",
  360. })
  361. .then((response) => {
  362. if (response.data.code == 200) {
  363. this.sysId = response.data.result.records[0].id;
  364. this.loadSysData({
  365. devicetype: "sys",
  366. systemID: this.sysId,
  367. });
  368. } else {
  369. resolve(response);
  370. }
  371. })
  372. .catch((error) => {
  373. // console.log("catch===>response", response);
  374. reject(error);
  375. });
  376. });
  377. },
  378. //加载场景类数据
  379. loadSysData(data) {
  380. new Promise((resolve, reject) => {
  381. api
  382. .getDeviceMonitor(data)
  383. .then((response) => {
  384. if (response.data.code == 200) {
  385. this.deviceList[this.TabCur] =
  386. response.data.result.msgTxt[0].datalist;
  387. this.curlist = this.deviceList[this.TabCur];
  388. this.setData(this.curlist);
  389. } else {
  390. resolve(response);
  391. }
  392. })
  393. .catch((error) => {
  394. reject(error);
  395. });
  396. });
  397. },
  398. //选择设备选择器 保存对应的id
  399. setData(data) {
  400. this.devices = [];
  401. data.forEach((element) => {
  402. const deviceObj = {
  403. // id: element.deviceID,
  404. ID: element.deviceID,
  405. strinstallpos: element.strinstallpos,
  406. type: element.deviceType,
  407. stationtype: element.stationtype,
  408. strtype: element.strtype,
  409. };
  410. this.devices.push(deviceObj);
  411. });
  412. },
  413. //选择设备 点击确定按钮 保存id
  414. selectDevice(e) {
  415. // this.deviceId = e.value[0].id;
  416. this.deviceID = e.value[0].ID;
  417. this.stationType = e.value[0].stationtype;
  418. this.strType = e.value[0].type;
  419. this.deviceType1 = e.value[0].type;
  420. this.deviceName = e.value[0].strinstallpos;
  421. this.deviceShow = false;
  422. let original = this.TabCur;
  423. let newName = original.startsWith("sys_")
  424. ? original.substring(4)
  425. : original;
  426. const key = newName + "_history";
  427. const key1 = this.deviceType1 + "_history";
  428. console.log(key1, "key1");
  429. if (this.showColum?.[key1]?.length > 0) {
  430. this.deviceShowList = this.showColum[key1];
  431. } else {
  432. this.deviceShowList = this.showColum[key] ?? [];
  433. }
  434. },
  435. selectDevice1(e) {
  436. this.deviceNum = e.value[0].value;
  437. this.labelName = e.value[0].label;
  438. this.deviceShow1 = false;
  439. },
  440. // 根据字段中文名或编码返回 static/window 内对应图标
  441. getWindowIcon(showitem) {
  442. const des = (showitem.des || "").toString();
  443. const code = (showitem.monitorcode || "").toString().toLowerCase();
  444. if (des.indexOf("气源") > -1) return "/static/window/SourcePressure.svg";
  445. if (des.indexOf("压差") > -1 || des.indexOf("压力") > -1)
  446. return "/static/window/Pressure.svg";
  447. if (des.indexOf("前窗开启面积") > -1)
  448. return "/static/window/WindowOpenArea.svg";
  449. if (des.indexOf("前窗风量") > -1)
  450. return "/static/window/WindowAirflow.svg";
  451. if (des.indexOf("后窗开启面积") > -1)
  452. return "/static/window/RearOpen.svg";
  453. if (des.indexOf("后窗风量") > -1) return "/static/window/AirFlow.svg";
  454. if (des.indexOf("开度") > -1) return "/static/window/MaxArea.svg";
  455. if (des.indexOf("面积") > -1) return "/static/window/AirArea.svg";
  456. if (code.indexOf("source") > -1 && code.indexOf("press") > -1)
  457. return "/static/window/SourcePressure.svg";
  458. if (code.indexOf("press") > -1 || code.indexOf("pressure") > -1)
  459. return "/static/window/Pressure.svg";
  460. if (code.indexOf("area") > -1) return "/static/window/AirArea.svg";
  461. if (
  462. code.indexOf("flow") > -1 ||
  463. code.indexOf("m3") > -1 ||
  464. code.indexOf("va") > -1
  465. )
  466. return "/static/window/AirFlow.svg";
  467. return "/static/window/Pressure.svg";
  468. },
  469. // 指标取值(doorUse 特殊处理)
  470. formatFieldValue(item, showitem) {
  471. if (showitem.monitorcode == "doorUse") {
  472. const val = item[showitem.monitorcode];
  473. if (val == "2") return "行人";
  474. if (val == "1") return "行车";
  475. if (val == "3") return "短路";
  476. return "-";
  477. }
  478. const val = item[showitem.monitorcode];
  479. if (val == null || val == "") return "-";
  480. return val;
  481. },
  482. //选择起始时间
  483. selectStartTime(e) {
  484. const startTime = e.value;
  485. const formattedTime = dayjs(startTime).format("YYYY-MM-DD HH:mm:ss");
  486. this.StartTime = formattedTime;
  487. this.dataShow = false;
  488. },
  489. //选择结束时间
  490. selectEndTime(e) {
  491. const endTime = e.value;
  492. const formattedTime = dayjs(endTime).format("YYYY-MM-DD HH:mm:ss");
  493. this.EndTime = formattedTime;
  494. this.dataShow1 = false;
  495. },
  496. //选择间隔时间
  497. selectSkipTime(e) {
  498. this.skip = e.value[0].value;
  499. this.interval = e.value[0].value1;
  500. this.lable = e.value[0].label;
  501. this.show = false;
  502. },
  503. //查询历史数据 getDeviceHistory
  504. checkHistory() {
  505. this.historyData = []; // 清空历史数据
  506. if (this.stationType !== "redis") {
  507. this.getHistoryData();
  508. } else {
  509. this.getHistoryData2();
  510. }
  511. },
  512. // 查询历史数据
  513. getHistoryData() {
  514. const params = {
  515. ttime_begin: this.StartTime,
  516. ttime_end: this.EndTime,
  517. gdeviceid: this.deviceID,
  518. skip: this.skip,
  519. pageNo: this.pageNo,
  520. pageSize: 10,
  521. strtype: this.strType,
  522. };
  523. new Promise((resolve, reject) => {
  524. api
  525. .getDeviceHistory(params)
  526. .then((response) => {
  527. if (response.data.code == 200) {
  528. const infolist = response.data.result;
  529. const result = infolist.datalist.records;
  530. result.forEach((item) => {
  531. const newData = { ...item, ...item.readData };
  532. this.historyData.push(newData);
  533. });
  534. this.pageNo = response.data.result.datalist.current;
  535. } else {
  536. resolve(response);
  537. }
  538. })
  539. .catch((error) => {
  540. reject(error);
  541. });
  542. });
  543. },
  544. getHistoryData2() {
  545. const params = {
  546. startTime: this.StartTime,
  547. endTime: this.EndTime,
  548. deviceId: this.deviceID,
  549. interval: this.interval,
  550. isEmployee: this.TabCur.startsWith("vehicle") ? false : true,
  551. pageNum: 1,
  552. pageSize: 10,
  553. strtype:
  554. (this.TabCur.startsWith("sys_")
  555. ? this.TabCur.substring(4)
  556. : this.TabCur) + "*",
  557. };
  558. if (this.TabCur.startsWith("sys")) {
  559. params.sysId = this.sysId;
  560. }
  561. new Promise((resolve, reject) => {
  562. api
  563. .getDeviceHistory2(params)
  564. .then((response) => {
  565. if (response.data.code === 200) {
  566. const result1 = response.data.result;
  567. if (result1.records.length != 0) {
  568. this.historyData = result1.records;
  569. }
  570. // this.pageNo = response1.data.result.datalist.current;
  571. } else {
  572. resolve(response);
  573. }
  574. })
  575. .catch((error) => {
  576. reject(error);
  577. });
  578. });
  579. },
  580. async loadMoreData() {
  581. if (this.loading || !this.hasMoreData) return;
  582. this.loading = true;
  583. try {
  584. // 如果新数据为空,则表示没有更多数据了
  585. if (this.historyData.length === 0) {
  586. this.hasMoreData = false;
  587. } else {
  588. // 将新数据追加到数据列表中
  589. this.historyData = [...this.historyData, ...newData];
  590. // 更新页码以便下次加载下一页数据
  591. this.pageNo += 1;
  592. }
  593. } catch (error) {
  594. // 处理请求错误
  595. console.error("加载数据失败:", error);
  596. } finally {
  597. // 无论请求成功还是失败,都要将加载状态设置为false
  598. this.loading = false;
  599. }
  600. },
  601. devicemenuShow(e) {
  602. this.menushow = !this.menushow;
  603. },
  604. menuClick(id) {
  605. this.TabCur = id;
  606. console.log(this.TabCur);
  607. // 显示该分类的数据
  608. this.curlist = this.deviceList[this.TabCur];
  609. if (this.curlist == null) {
  610. this.curlist = [];
  611. }
  612. // 选择设备分类,重新获取数据
  613. this.loadData(this.TabCur);
  614. this.menushow = false;
  615. },
  616. },
  617. destroyed() {
  618. // 停止定时器
  619. },
  620. onReachBottom() {
  621. // uni-app提供的页面滚动到底部钩子函数
  622. console.log("上拉加载更多数据");
  623. // this.loadMoreData();
  624. },
  625. };
  626. </script>
  627. <style lang="scss" scoped>
  628. .container {
  629. padding: 0 !important;
  630. }
  631. .u-page {
  632. padding: 20rpx 0;
  633. box-sizing: border-box;
  634. }
  635. /* ===== 一、查询条件 ===== */
  636. .query-card {
  637. padding: 24rpx;
  638. background-color: #ffffff;
  639. border-radius: 16rpx;
  640. box-shadow: 0 4rpx 16rpx rgba(41, 121, 255, 0.06);
  641. margin-bottom: 20rpx;
  642. }
  643. .query-row {
  644. display: flex;
  645. align-items: center;
  646. }
  647. .query-row + .query-row {
  648. margin-top: 20rpx;
  649. }
  650. .query-row > * {
  651. flex: 1;
  652. min-width: 0;
  653. margin-right: 20rpx;
  654. }
  655. .query-row > *:last-child {
  656. margin-right: 0;
  657. }
  658. .query-item {
  659. flex: 1;
  660. min-width: 0;
  661. }
  662. .query-picker-inner {
  663. height: 64rpx;
  664. padding: 0 12rpx;
  665. border: 1rpx solid #2277fb;
  666. border-radius: 8rpx;
  667. background: #ffffff;
  668. display: flex;
  669. align-items: center;
  670. justify-content: center;
  671. box-sizing: border-box;
  672. }
  673. .query-picker-text {
  674. margin-left: 8rpx;
  675. font-size: 24rpx;
  676. font-weight: 500;
  677. color: #2277fb;
  678. overflow: hidden;
  679. white-space: nowrap;
  680. text-overflow: ellipsis;
  681. }
  682. /* 选择设备 / 间隔时间 / 查询 */
  683. .query-btn {
  684. height: 64rpx;
  685. line-height: 64rpx;
  686. padding: 0 8rpx;
  687. text-align: center;
  688. color: #2277fb;
  689. font-size: 24rpx;
  690. border: 1rpx solid #2277fb;
  691. border-radius: 8rpx;
  692. background: #ffffff;
  693. overflow: hidden;
  694. white-space: nowrap;
  695. text-overflow: ellipsis;
  696. box-sizing: border-box;
  697. }
  698. .query-btn-query {
  699. flex: 0 0 auto;
  700. width: 128rpx;
  701. font-weight: 600;
  702. font-size: 26rpx;
  703. color: #ffffff;
  704. border: none;
  705. background: #2277fb;
  706. }
  707. .time-bg {
  708. background-color: #cce6fb;
  709. border-radius: 5px;
  710. height: 26px;
  711. line-height: 25px;
  712. text-align: center;
  713. float: right;
  714. }
  715. .timetext {
  716. text-align: center;
  717. color: #2591eb;
  718. }
  719. /* ===== 二、数据区(与查询条件分为两部分展示) ===== */
  720. .historycontainer {
  721. background-color: #ffffff;
  722. border-radius: 16rpx;
  723. box-shadow: 0 4rpx 16rpx rgba(41, 121, 255, 0.06);
  724. overflow: hidden;
  725. }
  726. /* 空数据状态 */
  727. .empty-box {
  728. display: flex;
  729. flex-direction: column;
  730. align-items: center;
  731. padding: 60rpx 40rpx 40rpx;
  732. }
  733. .empty-img {
  734. width: 60%;
  735. }
  736. .empty-text {
  737. margin-top: 30rpx;
  738. font-size: 32rpx;
  739. font-weight: bold;
  740. color: #000000;
  741. }
  742. .content {
  743. width: 100%;
  744. display: flex;
  745. flex-direction: column;
  746. }
  747. .main {
  748. /* margin-top: 100rpx; */
  749. display: flex;
  750. flex-direction: column;
  751. }
  752. .menupage {
  753. position: absolute;
  754. z-index: 2;
  755. top: 40rpx;
  756. height: calc(100% - 40rpx);
  757. width: 100%;
  758. }
  759. .flcard {
  760. padding: 20rpx;
  761. background-color: #ffffff;
  762. margin-bottom: 5rpx;
  763. }
  764. .itemback {
  765. padding: 20rpx;
  766. background-color: #ffffff;
  767. margin-bottom: 5rpx;
  768. }
  769. .data-grid {
  770. display: flex;
  771. flex-wrap: wrap;
  772. }
  773. .datacard {
  774. width: calc(50% - 8rpx);
  775. margin: 4rpx;
  776. box-sizing: border-box;
  777. display: flex;
  778. flex-direction: row;
  779. align-items: center;
  780. padding: 16rpx 12rpx;
  781. border-radius: 12rpx;
  782. background: linear-gradient(
  783. to bottom,
  784. rgba(175, 195, 252, 0.6) 0%,
  785. rgba(175, 195, 252, 0.1) 100%
  786. );
  787. }
  788. .datacard-full {
  789. width: calc(100% - 8rpx);
  790. }
  791. .data-icon {
  792. position: relative;
  793. width: 56rpx;
  794. height: 56rpx;
  795. border-radius: 12rpx;
  796. background: #2b7cff;
  797. box-sizing: border-box;
  798. box-shadow: 0 4rpx 10rpx rgba(43, 124, 255, 0.22);
  799. flex-shrink: 0;
  800. margin-right: 12rpx;
  801. }
  802. .data-icon-glass {
  803. position: absolute;
  804. left: -6rpx;
  805. bottom: -6rpx;
  806. width: 50rpx;
  807. height: 50rpx;
  808. border-radius: 12rpx;
  809. background: transparent;
  810. border: none;
  811. box-shadow: 0 0 0 0.6px #ffffff inset;
  812. box-sizing: border-box;
  813. backdrop-filter: blur(4rpx);
  814. -webkit-backdrop-filter: blur(4rpx);
  815. display: flex;
  816. align-items: center;
  817. justify-content: center;
  818. }
  819. .data-icon-img {
  820. width: 28rpx;
  821. height: 28rpx;
  822. }
  823. .data-text {
  824. flex: 1;
  825. min-width: 0;
  826. display: flex;
  827. flex-direction: column;
  828. }
  829. .data-value {
  830. font-size: 24rpx;
  831. font-weight: 700;
  832. color: #287bfb;
  833. line-height: 1.3;
  834. overflow: hidden;
  835. white-space: nowrap;
  836. text-overflow: ellipsis;
  837. }
  838. .data-label {
  839. margin-top: 4rpx;
  840. font-size: 22rpx;
  841. color: #000000;
  842. line-height: 1.3;
  843. }
  844. .error-tag {
  845. border-radius: 10%;
  846. display: inline-block;
  847. color: #e90000;
  848. line-height: 50rpx;
  849. font-size: 14px;
  850. text-align: center;
  851. width: 120rpx;
  852. height: 50rpx;
  853. background-color: rgba(233, 0, 0, 0.2);
  854. }
  855. .error-tag1 {
  856. border-radius: 10%;
  857. display: inline-block;
  858. color: #696969;
  859. line-height: 50rpx;
  860. font-size: 14px;
  861. text-align: center;
  862. width: 120rpx;
  863. height: 50rpx;
  864. background-color: rgba(105, 105, 105, 0.2);
  865. }
  866. .success-tag {
  867. border-radius: 10%;
  868. color: #5acc1f;
  869. line-height: 50rpx;
  870. font-size: 14px;
  871. width: 148rpx;
  872. height: 50rpx;
  873. display: inline-block;
  874. border: 1rpx solid #ace392;
  875. box-sizing: border-box;
  876. background-color: rgba(226, 250, 214, 0.5);
  877. }
  878. .icon-style {
  879. margin: 15rpx;
  880. width: 14px;
  881. height: 14px;
  882. }
  883. </style>