Index.vue 26 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027
  1. <template>
  2. <el-row :gutter="24">
  3. <el-col :span="16">
  4. <el-card class="box-card" v-loading="auditLoading">
  5. <template #header>
  6. <div class="card-header">
  7. <span>
  8. <img :src="ywdbIcon" alt="" />
  9. 待办
  10. </span>
  11. <!-- <el-button link type="default"-->
  12. <!-- >查看更多 <el-icon><ArrowRight /></el-icon-->
  13. <!-- ></el-button>-->
  14. </div>
  15. </template>
  16. <div v-if="showTodoList" class="audit-list">
  17. <template v-for="todo in todoList" :key="todo.title">
  18. <div
  19. v-show="todo.task > 0"
  20. class="audit-item cursor-pointer"
  21. @click="() => handleRouteTo(todo)"
  22. >
  23. <img :src="todo.iconUrl" alt="" />
  24. <div>
  25. <i v-if="typeof todo.task === 'number'">{{ todo.task }}</i>
  26. <span class="todo-title-row">
  27. <span v-if="todo.equipType === 'boiler'" class="equip-tag-boiler">[锅]</span>
  28. <span v-if="todo.equipType === 'pipe'" class="equip-tag-pipe">[管]</span>
  29. {{ todo.title }}
  30. </span>
  31. </div>
  32. </div>
  33. </template>
  34. </div>
  35. <el-empty v-else description="暂无待办数据" />
  36. </el-card>
  37. <el-card class="box-card" v-loading="auditLoading">
  38. <template #header>
  39. <div class="card-header">
  40. <span>
  41. <img :src="ywdbIcon" alt="" />
  42. 审批
  43. </span>
  44. <!-- <el-button link type="default"-->
  45. <!-- >查看更多 <el-icon><ArrowRight /></el-icon-->
  46. <!-- ></el-button>-->
  47. </div>
  48. </template>
  49. <div v-if="showAuditList" class="audit-list">
  50. <template v-for="todo in auditTodoList" :key="todo.title">
  51. <div
  52. v-show="todo.task > 0"
  53. class="audit-item cursor-pointer"
  54. @click="() => handleRouteTo(todo)"
  55. >
  56. <img :src="todo.iconUrl" alt="" />
  57. <div>
  58. <i>{{ todo.task }}</i>
  59. <span class="todo-title-row">
  60. <span v-if="todo.equipType === 'boiler'" class="equip-tag-boiler">[锅]</span>
  61. <span v-if="todo.equipType === 'pipe'" class="equip-tag-pipe">[管]</span>
  62. {{ todo.title }}
  63. </span>
  64. </div>
  65. </div>
  66. </template>
  67. </div>
  68. <el-empty v-else description="暂无审批数据" />
  69. </el-card>
  70. <el-card class="box-card">
  71. <template #header>
  72. <div class="card-header">
  73. <span>
  74. <img :src="tzIcon" alt="" />
  75. 通知公告
  76. </span>
  77. <!-- <el-button v-if="noticeList.length" link type="default" @click="toMoreNotice"-->
  78. <!-- >查看更多 <el-icon><ArrowRight /></el-icon-->
  79. <!-- ></el-button>-->
  80. </div>
  81. </template>
  82. <div class="todo-list">
  83. <template v-if="noticeList.length">
  84. <div
  85. class="notice-item"
  86. v-for="notice in noticeList"
  87. :key="notice.title"
  88. @click="
  89. toPage(
  90. '/fwpt/noticeMgn/detail',
  91. {
  92. id: notice.id
  93. },
  94. 1
  95. )
  96. "
  97. >
  98. <div class="title ellipsis1" style="min-width: 0">
  99. <span class="newFlag color-#fff text-12px" v-if="notice.readStatus == 0">NEW</span>
  100. {{ notice.title }}
  101. </div>
  102. <div class="sub-info">
  103. <span
  104. >来自于 <i>{{ msgTypeMap[notice.type] || '未知' }}</i></span
  105. >
  106. <span>{{
  107. notice.createTime ? dayJs(notice.createTime).format('YYYY-MM-DD HH:mm:ss') : '-'
  108. }}</span>
  109. </div>
  110. </div>
  111. </template>
  112. <template v-else>
  113. <el-empty style="flex: 1" description="暂无公告" />
  114. </template>
  115. </div>
  116. </el-card>
  117. </el-col>
  118. <el-col :span="8">
  119. <div class="risk-alert-wrap">
  120. <RiskAlertCard
  121. equip-type="boiler"
  122. :fetch-my="getBoilerMyAlert"
  123. :fetch-dept="getBoilerDeptAlert"
  124. />
  125. <RiskAlertCard
  126. equip-type="pipe"
  127. :fetch-my="getPipeMyAlert"
  128. :fetch-dept="getPipeDeptAlert"
  129. />
  130. </div>
  131. <el-card class="box-card">
  132. <template #header>
  133. <div class="card-header">
  134. <span>
  135. <img :src="kjrkIcon" alt="" />
  136. 快捷入口
  137. </span>
  138. </div>
  139. </template>
  140. <div class="todo-list quick-access-list">
  141. <div
  142. v-for="todo in quickAccessList"
  143. :key="todo.title"
  144. class="todo-item quick-access-item cursor-pointer"
  145. @click="() => handleRouteTo(todo)"
  146. >
  147. <img :src="todo.iconUrl" alt="" />
  148. <div>
  149. <span>{{ todo.title }}</span>
  150. </div>
  151. </div>
  152. </div>
  153. </el-card>
  154. </el-col>
  155. </el-row>
  156. </template>
  157. <script lang="ts" setup>
  158. import { useUserStore } from '@/store/modules/user'
  159. import { useWatermark } from '@/hooks/web/useWatermark'
  160. import { ArrowRight, List } from '@element-plus/icons-vue'
  161. import {
  162. getTodoList,
  163. getAuditTodoList,
  164. getBoilerMyAlert,
  165. getBoilerDeptAlert,
  166. getPipeMyAlert,
  167. getPipeDeptAlert
  168. } from '@/api/common/home'
  169. import { IndexTodoApi } from '@/api/pressure2/indextodo'
  170. import RiskAlertCard from './components/RiskAlertCard.vue'
  171. import yjIcon from '@/assets/imgs/index_imgs/约检@2x.png'
  172. import jhpqIcon from '@/assets/imgs/index_imgs/计划排期@2x.png'
  173. import jhdtIcon from '@/assets/imgs/index_imgs/计划待调@2x.png'
  174. import zlfpIcon from '@/assets/imgs/index_imgs/资料分配@2x.png'
  175. import zlshIcon from '@/assets/imgs/index_imgs/资料审核@2x.png'
  176. import rwdshIcon from '@/assets/imgs/index_imgs/任务单审核@2x.png'
  177. import rwdzfIcon from '@/assets/imgs/index_imgs/任务单作废@2x.png'
  178. import jljhIcon from '@/assets/imgs/index_imgs/记录校合@2x.png'
  179. import bgspIcon from '@/assets/imgs/index_imgs/报告审批@2x.png'
  180. import jjgqbgIcon from '@/assets/imgs/index_imgs/部门快要过期的报告@2x.png'
  181. import lqapIcon from '@/assets/imgs/index_imgs/临期临安排计划的企业.png'
  182. import ywdbIcon from '@/assets/imgs/index_imgs/业务待办@2x.png'
  183. import fxIcon from '@/assets/imgs/index_imgs/风险@2x.png'
  184. import tzIcon from '@/assets/imgs/index_imgs/通知@2x.png'
  185. import zldjIcon from '@/assets/imgs/index_imgs/资料登记@2x.png'
  186. import qtyjIcon from '@/assets/imgs/index_imgs/前台约检@2x.png'
  187. import shzxIcon from '@/assets/imgs/index_imgs/审核中心@2x.png'
  188. import gdyyIcon from '@/assets/imgs/index_imgs/更多应用@2x.png'
  189. import kjrkIcon from '@/assets/imgs/index_imgs/快捷入口@2x.png'
  190. import { noticeApi } from '@/api/laboratory/noticeService'
  191. import dayJs from 'dayjs'
  192. import { useRouter } from 'vue-router'
  193. const router = useRouter()
  194. const msgTypeMap = {
  195. 1: '系统公告',
  196. 2: '系统消息'
  197. }
  198. // 业务待办列表(锅炉和管道分别显示)
  199. const todoList = ref([
  200. {
  201. title: '计划表',
  202. key: 'boilerScheduleCount',
  203. equipType: 'boiler',
  204. iconUrl: zlfpIcon,
  205. task: 0,
  206. routerName: 'ScheduleBoiler'
  207. },
  208. {
  209. title: '任务确认',
  210. key: 'boilerTaskOrderConfirmCount',
  211. equipType: 'boiler',
  212. iconUrl: jhpqIcon,
  213. task: 0,
  214. routerName: 'BoilerCheckerTaskList'
  215. },
  216. {
  217. title: '检验录入',
  218. key: 'boilerMyTaskCount',
  219. equipType: 'boiler',
  220. iconUrl: jhdtIcon,
  221. task: 0,
  222. routerName: 'BoilerMyTask'
  223. },
  224. {
  225. title: '报告编制',
  226. key: 'boilerPrepareReportCount',
  227. equipType: 'boiler',
  228. iconUrl: zlfpIcon,
  229. task: 0,
  230. routerName: 'BoilerReportPreparationList'
  231. },
  232. {
  233. title: '计划表',
  234. key: 'pipeScheduleCount',
  235. equipType: 'pipe',
  236. iconUrl: zlfpIcon,
  237. task: 0,
  238. routerName: 'SchedulePipe'
  239. },
  240. {
  241. title: '任务确认',
  242. key: 'pipeTaskOrderConfirmCount',
  243. equipType: 'pipe',
  244. iconUrl: jhpqIcon,
  245. task: 0,
  246. routerName: 'PipeCheckerTaskList'
  247. },
  248. {
  249. title: '检验录入',
  250. key: 'pipeMyTaskCount',
  251. equipType: 'pipe',
  252. iconUrl: jhdtIcon,
  253. task: 0,
  254. routerName: 'PipeMyTask'
  255. },
  256. {
  257. title: '报告编制',
  258. key: 'pipePrepareReportCount',
  259. equipType: 'pipe',
  260. iconUrl: zlfpIcon,
  261. task: 0,
  262. routerName: 'PipeReportPreparationList'
  263. }
  264. ])
  265. // 业务审批列表(锅炉和管道分别显示)
  266. const auditLoading = ref(false)
  267. const auditTodoList = ref([
  268. {
  269. title: '模板审核',
  270. key: 'reportTemplateCount',
  271. iconUrl: bgspIcon,
  272. task: 0,
  273. routerName: 'TemplateAudit'
  274. },
  275. {
  276. title: '记录校核',
  277. key: 'boilerRecheckOrderItemCount',
  278. equipType: 'boiler',
  279. iconUrl: jljhIcon,
  280. task: 0,
  281. routerName: 'BoilerCheckerRecordCheck'
  282. },
  283. {
  284. title: '上报市局审核',
  285. key: 'boilerReportCityBureauCount',
  286. equipType: 'boiler',
  287. iconUrl: rwdshIcon,
  288. task: 0,
  289. routerName: 'appointmentconfirmorderCityBureauListPressure2'
  290. },
  291. {
  292. title: '受理单审核',
  293. key: 'boilerAcceptOrderCount',
  294. equipType: 'boiler',
  295. iconUrl: jljhIcon,
  296. task: 0,
  297. routerName: 'AcceptOrderAuditBoiler'
  298. },
  299. {
  300. title: '缴费单待校核',
  301. key: 'boilerPressureNonTaxCount',
  302. equipType: 'boiler',
  303. iconUrl: zlshIcon,
  304. task: 0,
  305. routerName: 'PaymentReceiptApprovePressure2'
  306. },
  307. {
  308. title: '任务单修改审核',
  309. key: 'boilerTaskOrderCount',
  310. equipType: 'boiler',
  311. iconUrl: rwdshIcon,
  312. task: 0,
  313. routerName: 'TaskOrderReviewBoiler'
  314. },
  315. {
  316. title: '检验意见通知书审核',
  317. key: 'boilerPressureInspectionOpinionNoticeCount',
  318. equipType: 'boiler',
  319. iconUrl: jljhIcon,
  320. task: 0,
  321. routerName: 'AuditInspectionCommentsNoticeBoiler'
  322. },
  323. {
  324. title: '检验方案审核',
  325. key: 'boilerPressureInspectionSchemeCount',
  326. equipType: 'boiler',
  327. iconUrl: zlshIcon,
  328. task: 0,
  329. routerName: 'InspectionPlanAuditBoiler'
  330. },
  331. {
  332. title: '操作指导书审核',
  333. key: 'boilerPressureWorkingInstructionCount',
  334. equipType: 'boiler',
  335. iconUrl: rwdshIcon,
  336. task: 0,
  337. routerName: 'WorkInstructionAuditBoiler'
  338. },
  339. // OA流程:锅炉审核/审批
  340. { title: '锅炉审核', key: 'boilerCheckCount', equipType: 'boiler', iconUrl: bgspIcon, task: 0, routerPath: '/gljy/report-check-boiler', oaType: true },
  341. { title: '锅炉审批', key: 'boilerRatifyCount', equipType: 'boiler', iconUrl: bgspIcon, task: 0, routerPath: '/gljy/report-ratify-boiler', oaType: true },
  342. {
  343. title: '记录校核',
  344. key: 'pipeRecheckOrderItemCount',
  345. equipType: 'pipe',
  346. iconUrl: jljhIcon,
  347. task: 0,
  348. routerName: 'PipeCheckerRecordCheck'
  349. },
  350. {
  351. title: '上报市局审核',
  352. key: 'pipeReportCityBureauCount',
  353. equipType: 'pipe',
  354. iconUrl: rwdshIcon,
  355. task: 0,
  356. routerName: 'appointmentconfirmorderCityBureauListPressure2'
  357. },
  358. {
  359. title: '受理单审核',
  360. key: 'pipeAcceptOrderCount',
  361. equipType: 'pipe',
  362. iconUrl: jljhIcon,
  363. task: 0,
  364. routerName: 'AcceptOrderAuditPipe'
  365. },
  366. {
  367. title: '缴费单待校核',
  368. key: 'pipePressureNonTaxCount',
  369. equipType: 'pipe',
  370. iconUrl: zlshIcon,
  371. task: 0,
  372. routerName: 'PaymentReceiptApprovePressure2'
  373. },
  374. {
  375. title: '任务单修改审核',
  376. key: 'pipeTaskOrderCount',
  377. equipType: 'pipe',
  378. iconUrl: rwdshIcon,
  379. task: 0,
  380. routerName: 'TaskOrderReviewPipe'
  381. },
  382. {
  383. title: '检验意见通知书审核',
  384. key: 'pipePressureInspectionOpinionNoticeCount',
  385. equipType: 'pipe',
  386. iconUrl: jljhIcon,
  387. task: 0,
  388. routerName: 'AuditInspectionCommentsNoticePipe'
  389. },
  390. {
  391. title: '检验方案审核',
  392. key: 'pipePressureInspectionSchemeCount',
  393. equipType: 'pipe',
  394. iconUrl: zlshIcon,
  395. task: 0,
  396. routerName: 'InspectionPlanAuditPipe'
  397. },
  398. {
  399. title: '操作指导书审核',
  400. key: 'pipePressureWorkingInstructionCount',
  401. equipType: 'pipe',
  402. iconUrl: rwdshIcon,
  403. task: 0,
  404. routerName: 'WorkInstructionAuditPipe'
  405. },
  406. // OA流程:管道审核/审批
  407. { title: '管道审核', key: 'pipeCheckCount', equipType: 'pipe', iconUrl: bgspIcon, task: 0, routerPath: '/gdjy/report-check-pipe', oaType: true },
  408. { title: '管道审批', key: 'pipeRatifyCount', equipType: 'pipe', iconUrl: bgspIcon, task: 0, routerPath: '/gdjy/report-ratify-pipe', oaType: true },
  409. ])
  410. const showAuditList = computed(() => {
  411. return auditTodoList.value.some((item: any) => item.task > 0)
  412. })
  413. const showTodoList = computed(() => {
  414. return todoList.value.some((item: any) => item.task > 0)
  415. })
  416. // 风险预警列表
  417. const riskTodoList = ref([
  418. {
  419. title: '部门快要过期的报告',
  420. iconUrl: jjgqbgIcon,
  421. task: 0
  422. },
  423. {
  424. title: '临期临安排计划的企业',
  425. iconUrl: lqapIcon,
  426. task: 0
  427. }
  428. ])
  429. // 快捷入口
  430. const quickAccessList = ref([
  431. {
  432. title: '锅炉档案',
  433. iconUrl: zldjIcon,
  434. routerUrl: '',
  435. routerName: 'EquipBoiler'
  436. },
  437. {
  438. title: '管道档案',
  439. iconUrl: shzxIcon,
  440. routerUrl: '',
  441. routerName: 'PipeEquipment'
  442. },
  443. {
  444. title: '前台约检',
  445. iconUrl: qtyjIcon,
  446. routerUrl: '',
  447. routerName: 'NewPressurePlan'
  448. },
  449. {
  450. title: '更多应用',
  451. iconUrl: gdyyIcon,
  452. routerUrl: ''
  453. }
  454. ])
  455. const userStore = useUserStore()
  456. const handleRouteTo = (item: any) => {
  457. const { id } = userStore.getUser
  458. // 支持直接路径跳转(OA审批卡片等)
  459. if (item.routerPath) {
  460. router.push({ path: item.routerPath })
  461. return
  462. }
  463. if (item.routerName) {
  464. // 特殊处理任务单跳转:默认带上 inspectorIds 和 taskStatusList 参数
  465. const query: any = {
  466. //bpmUserId: id,
  467. ...(item.routerQuery || {})
  468. }
  469. router.push({
  470. name: item.routerName,
  471. query
  472. })
  473. }
  474. }
  475. // 获取首页待办/审核统计数据(新接口:压力2 index-todo 表,锅炉管道分别展示)
  476. const fetchAllCounts = async () => {
  477. auditLoading.value = true
  478. try {
  479. const result = await IndexTodoApi.getTodoCount()
  480. // 直接映射 API 返回字段到待办/审核列表的 key
  481. todoList.value = todoList.value.map((item: any) => {
  482. if (result[item.key] !== undefined) {
  483. item.task = result[item.key]
  484. }
  485. return item
  486. })
  487. auditTodoList.value = auditTodoList.value.map((item: any) => {
  488. // OA类型的卡片(锅炉/管道审核审批)使用独立接口加载数据,此处跳过
  489. if (item.oaType) return item
  490. if (result[item.key] !== undefined) {
  491. item.task = result[item.key]
  492. }
  493. return item
  494. })
  495. } finally {
  496. auditLoading.value = false
  497. }
  498. }
  499. // 获取OA待办中锅炉/管道审核、审批数量(独立接口,不阻塞首页主查询)
  500. const fetchOATodoCount = async () => {
  501. try {
  502. const result = await IndexTodoApi.getOATodoCount()
  503. auditTodoList.value = auditTodoList.value.map((item: any) => {
  504. if (item.oaType && result[item.key] !== undefined) {
  505. item.task = result[item.key]
  506. }
  507. return item
  508. })
  509. } catch (err) {
  510. console.error('获取OA待办统计失败', err)
  511. }
  512. }
  513. // 旧逻辑保留(注释)
  514. // const fetchTodoList = ...
  515. // const fetchAuditTodoList = ...
  516. // 通知公告
  517. const noticeList = ref<any>([])
  518. /**
  519. * 查询公告列表(前5条)
  520. */
  521. const selectNoticeList = async () => {
  522. try {
  523. const res = await noticeApi.getNoticeList({
  524. pageNo: 1,
  525. pageSize: 5
  526. })
  527. let { list = [] } = res
  528. noticeList.value = list
  529. } catch (err) {}
  530. }
  531. /**
  532. * 跳转页面
  533. * @param path 跳转路径
  534. * @param query 跳转参数
  535. * @param type 跳转类型 1 点击公告进行阅读功能 2 普通跳转
  536. */
  537. const toPage = async (path = '', query: Record<string, any> = {}, type = 2) => {
  538. if (!path) {
  539. ElMessage.warning('暂无配置跳转路径')
  540. return
  541. }
  542. try {
  543. if (type === 1) {
  544. const { id } = query
  545. if (id) {
  546. await noticeApi.readNotice({ laboratoryAnnouncementId: id, readStatus: 1 })
  547. }
  548. }
  549. await router.push({
  550. path,
  551. query
  552. })
  553. } catch (error) {
  554. console.error('页面跳转失败:', error)
  555. ElMessage.error('页面跳转失败')
  556. }
  557. }
  558. /**
  559. * 去往查看更多公告页面
  560. */
  561. const toMoreNotice = () => {
  562. if (!noticeList.value.length) {
  563. ElMessage.warning('暂无更多公告可查看')
  564. return
  565. }
  566. router.push({
  567. path: '/laboratory/allNotice'
  568. })
  569. }
  570. // fetchTodoList()
  571. // fetchAuditTodoList()
  572. fetchAllCounts()
  573. fetchOATodoCount()
  574. selectNoticeList()
  575. </script>
  576. <style lang="scss" scoped>
  577. .newFlag {
  578. background: linear-gradient(270deg, #ff6341 0%, #ff3618 100%);
  579. border-radius: 4px 0px 4px 0px;
  580. line-height: 22px;
  581. padding: 2px 6px;
  582. margin-right: 8px;
  583. }
  584. .ellipsis1 {
  585. text-overflow: -o-ellipsis-lastline;
  586. overflow: hidden;
  587. text-overflow: ellipsis;
  588. display: -webkit-box;
  589. -webkit-line-clamp: 1;
  590. line-clamp: 1;
  591. -webkit-box-orient: vertical;
  592. word-break: break-all;
  593. }
  594. .box-card {
  595. margin-bottom: 20px;
  596. border-radius: 12px;
  597. box-shadow: 0px 2px 14px 0px rgba(43, 99, 255, 0.1);
  598. padding: 17px 22px 24px;
  599. :deep(.el-card__header) {
  600. padding: 0 0 8px 0;
  601. }
  602. :deep(.el-card__body) {
  603. padding: 0;
  604. padding-top: 16px;
  605. .todo-list {
  606. display: flex;
  607. flex-direction: row;
  608. flex-wrap: wrap;
  609. width: 100%;
  610. gap: 16px;
  611. .todo-item {
  612. display: flex;
  613. align-items: flex-end;
  614. flex: 1 0 calc(25% - 16px);
  615. padding: 15px 13px 11px;
  616. background: rgba(73, 120, 246, 0.05);
  617. border-radius: 4px;
  618. img {
  619. width: 54px;
  620. height: 54px;
  621. }
  622. div {
  623. padding-left: 9px;
  624. padding-bottom: 5px;
  625. i,
  626. span {
  627. display: block;
  628. font-style: initial;
  629. }
  630. i {
  631. font-family: Arial, Arial;
  632. color: #4978f6;
  633. font-size: 20px;
  634. }
  635. span {
  636. font-weight: 600;
  637. font-size: 14px;
  638. color: #41475c;
  639. line-height: 20px;
  640. }
  641. }
  642. &:nth-child(5) {
  643. flex: 0 0 calc(25% - 12px);
  644. }
  645. &:last-child {
  646. flex-grow: 1;
  647. max-width: 100%;
  648. margin-right: 0;
  649. }
  650. &:hover {
  651. transform: translateY(-3px); // 轻微上浮效果
  652. box-shadow: 0 4px 12px rgba(73, 120, 246, 0.15); // 添加阴影
  653. background: rgba(73, 120, 246, 0.1); // 背景色加深
  654. img {
  655. transform: scale(1.05); // 图片轻微放大
  656. }
  657. span {
  658. color: #2c64ff; // 文字颜色变化
  659. }
  660. }
  661. }
  662. // .task-todo-item:last-child {
  663. // justify-content: center;
  664. // align-items: center;
  665. // div {
  666. // display: flex;
  667. // align-items: center;
  668. // span {
  669. // color: #4978f6;
  670. // }
  671. // }
  672. // }
  673. .risk-todo-item {
  674. position: relative;
  675. height: 110px;
  676. align-items: center;
  677. padding-left: 24px;
  678. box-sizing: border-box;
  679. img {
  680. position: absolute;
  681. left: 0;
  682. top: 0;
  683. width: 100%;
  684. height: 100%;
  685. }
  686. div {
  687. position: relative;
  688. z-index: 2;
  689. padding: 0;
  690. span {
  691. margin-bottom: 8px;
  692. font-size: 18px;
  693. color: #41475c;
  694. line-height: 28px;
  695. font-weight: 600;
  696. }
  697. i {
  698. font-size: 20px;
  699. color: #e0534e;
  700. line-height: 28px;
  701. font-weight: 600;
  702. }
  703. }
  704. }
  705. .quick-access-item {
  706. transition: all 0.3s ease;
  707. flex: 1 0 calc(50% - 16px);
  708. flex-direction: column;
  709. align-items: flex-start;
  710. &:hover {
  711. transform: translateY(-3px); // 轻微上浮效果
  712. box-shadow: 0 4px 12px rgba(73, 120, 246, 0.15); // 添加阴影
  713. background: rgba(73, 120, 246, 0.1); // 背景色加深
  714. img {
  715. transform: scale(1.05); // 图片轻微放大
  716. }
  717. span {
  718. color: #2c64ff; // 文字颜色变化
  719. }
  720. }
  721. span {
  722. transition: color 0.3s ease; // 文字颜色过渡
  723. }
  724. img {
  725. width: auto;
  726. height: 44px;
  727. object-fit: cover;
  728. transition: transform 0.3s ease; // 图片过渡效果
  729. }
  730. div {
  731. padding: 0;
  732. padding-top: 13px;
  733. }
  734. }
  735. .notice-item {
  736. padding: 12px;
  737. background: rgba(73, 120, 246, 0.05);
  738. border-radius: 4px;
  739. width: 100%;
  740. cursor: pointer;
  741. &:hover {
  742. background: rgba(73, 120, 246, 0.1); // 悬停时背景色加深
  743. transform: translateY(-2px); // 轻微上浮效果
  744. box-shadow: 0 2px 8px rgba(73, 120, 246, 0.1); // 添加阴影
  745. .title {
  746. color: #2c64ff; // 标题颜色变化
  747. }
  748. .sub-info {
  749. i {
  750. color: #4978f6; // 来源文字颜色变化
  751. }
  752. }
  753. }
  754. .title {
  755. font-family:
  756. PingFangSC,
  757. PingFang SC;
  758. font-weight: 500;
  759. font-size: 14px;
  760. color: rgba(0, 0, 0, 0.85);
  761. line-height: 22px;
  762. text-align: left;
  763. font-style: normal;
  764. }
  765. .sub-info {
  766. display: flex;
  767. justify-content: space-between;
  768. margin-top: 12px;
  769. font-size: 12px;
  770. color: rgba(0, 0, 0, 0.5);
  771. i {
  772. font-style: normal;
  773. color: #2c64ff;
  774. }
  775. }
  776. }
  777. }
  778. .audit-list {
  779. display: grid;
  780. grid-template-columns: repeat(4, 1fr);
  781. width: 100%;
  782. gap: 16px;
  783. .audit-item {
  784. display: flex;
  785. align-items: flex-end;
  786. padding: 15px 13px 11px;
  787. background: rgba(73, 120, 246, 0.05);
  788. border-radius: 4px;
  789. img {
  790. width: 54px;
  791. height: 54px;
  792. }
  793. div {
  794. padding-left: 9px;
  795. padding-bottom: 5px;
  796. i,
  797. span {
  798. display: block;
  799. font-style: initial;
  800. }
  801. i {
  802. font-family: Arial, Arial;
  803. color: #4978f6;
  804. font-size: 20px;
  805. }
  806. span {
  807. font-weight: 600;
  808. font-size: 14px;
  809. color: #41475c;
  810. line-height: 20px;
  811. }
  812. }
  813. &:hover {
  814. transform: translateY(-3px); // 轻微上浮效果
  815. box-shadow: 0 4px 12px rgba(73, 120, 246, 0.15); // 添加阴影
  816. background: rgba(73, 120, 246, 0.1); // 背景色加深
  817. img {
  818. transform: scale(1.05); // 图片轻微放大
  819. }
  820. span {
  821. color: #2c64ff; // 文字颜色变化
  822. }
  823. }
  824. }
  825. .task-todo-item:last-child {
  826. justify-content: center;
  827. align-items: center;
  828. div {
  829. display: flex;
  830. align-items: center;
  831. span {
  832. color: #4978f6;
  833. }
  834. }
  835. }
  836. .risk-todo-item {
  837. position: relative;
  838. height: 110px;
  839. align-items: center;
  840. padding-left: 24px;
  841. box-sizing: border-box;
  842. img {
  843. position: absolute;
  844. left: 0;
  845. top: 0;
  846. width: 100%;
  847. height: 100%;
  848. }
  849. div {
  850. position: relative;
  851. z-index: 2;
  852. padding: 0;
  853. span {
  854. margin-bottom: 8px;
  855. font-size: 18px;
  856. color: #41475c;
  857. line-height: 28px;
  858. font-weight: 600;
  859. }
  860. i {
  861. font-size: 20px;
  862. color: #e0534e;
  863. line-height: 28px;
  864. font-weight: 600;
  865. }
  866. }
  867. }
  868. .quick-access-item {
  869. transition: all 0.3s ease;
  870. flex: 1 0 calc(50% - 16px);
  871. flex-direction: column;
  872. align-items: flex-start;
  873. &:hover {
  874. transform: translateY(-3px); // 轻微上浮效果
  875. box-shadow: 0 4px 12px rgba(73, 120, 246, 0.15); // 添加阴影
  876. background: rgba(73, 120, 246, 0.1); // 背景色加深
  877. img {
  878. transform: scale(1.05); // 图片轻微放大
  879. }
  880. span {
  881. color: #2c64ff; // 文字颜色变化
  882. }
  883. }
  884. span {
  885. transition: color 0.3s ease; // 文字颜色过渡
  886. }
  887. img {
  888. width: auto;
  889. height: 44px;
  890. object-fit: cover;
  891. transition: transform 0.3s ease; // 图片过渡效果
  892. }
  893. div {
  894. padding: 0;
  895. padding-top: 13px;
  896. }
  897. }
  898. .notice-item {
  899. padding: 12px;
  900. background: rgba(73, 120, 246, 0.05);
  901. border-radius: 4px;
  902. width: 100%;
  903. cursor: pointer;
  904. &:hover {
  905. background: rgba(73, 120, 246, 0.1); // 悬停时背景色加深
  906. transform: translateY(-2px); // 轻微上浮效果
  907. box-shadow: 0 2px 8px rgba(73, 120, 246, 0.1); // 添加阴影
  908. .title {
  909. color: #2c64ff; // 标题颜色变化
  910. }
  911. .sub-info {
  912. i {
  913. color: #4978f6; // 来源文字颜色变化
  914. }
  915. }
  916. }
  917. .title {
  918. font-family:
  919. PingFangSC,
  920. PingFang SC;
  921. font-weight: 500;
  922. font-size: 14px;
  923. color: rgba(0, 0, 0, 0.85);
  924. line-height: 22px;
  925. text-align: left;
  926. font-style: normal;
  927. }
  928. .sub-info {
  929. display: flex;
  930. justify-content: space-between;
  931. margin-top: 12px;
  932. font-size: 12px;
  933. color: rgba(0, 0, 0, 0.5);
  934. i {
  935. font-style: normal;
  936. color: #2c64ff;
  937. }
  938. }
  939. }
  940. }
  941. }
  942. }
  943. .card-header {
  944. display: flex;
  945. justify-content: space-between;
  946. span {
  947. display: flex;
  948. align-items: center;
  949. font-size: 18px;
  950. font-weight: 600;
  951. img {
  952. width: 24px;
  953. height: 24px;
  954. margin-right: 4px;
  955. }
  956. :deep(.el-button) {
  957. font-size: 14px;
  958. }
  959. }
  960. }
  961. .todo-title-row {
  962. display: flex !important;
  963. align-items: center;
  964. gap: 4px;
  965. }
  966. .equip-tag-boiler {
  967. color: #f56c6c !important;
  968. }
  969. .equip-tag-pipe {
  970. color: #67c23a !important;
  971. }
  972. .risk-alert-wrap {
  973. display: flex;
  974. flex-direction: column;
  975. gap: 16px;
  976. margin-bottom: 20px;
  977. }
  978. </style>