deviceExamDetail.vue 7.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329
  1. <route lang="json5" type="page">
  2. {
  3. layout: 'default',
  4. style: {
  5. navigationBarTitleText: '设备详情',
  6. navigationStyle: 'custom',
  7. },
  8. }
  9. </route>
  10. <template>
  11. <view class="detail-container">
  12. <!-- 导航栏 -->
  13. <NavBar title="设备详情" />
  14. <!-- Tab 栏 -->
  15. <view class="tab-bar">
  16. <view
  17. v-for="(tab, index) in tabList"
  18. :key="tab.id"
  19. class="tab-item"
  20. :class="{ 'tab-item-active': currentTab === index }"
  21. @click="switchTab(index)"
  22. >
  23. <text class="tab-text">{{ tab.value }}</text>
  24. </view>
  25. </view>
  26. <!-- 内容区域 -->
  27. <scroll-view class="scroll-content" scroll-y>
  28. <!-- 基本信息 -->
  29. <view v-if="currentTab === 0" class="tab-content">
  30. <component
  31. :is="BaseInfoComponent"
  32. v-if="dataSource"
  33. :data-source="dataSource"
  34. use-online="1"
  35. :can-edit="false"
  36. />
  37. </view>
  38. <!-- 设备信息 -->
  39. <view v-if="currentTab === 1" class="tab-content">
  40. <component
  41. :is="EquipmentInfoComponent"
  42. v-if="equipmentData"
  43. :equipment-data="equipmentData"
  44. use-online="1"
  45. :can-edit="false"
  46. />
  47. </view>
  48. <!-- 历史报告 -->
  49. <view v-if="currentTab === 2" class="tab-content">
  50. <HistoryReport :equip-id="id" use-online="1" />
  51. </view>
  52. </scroll-view>
  53. </view>
  54. </template>
  55. <script lang="ts" setup>
  56. import { ref, onMounted, computed } from 'vue'
  57. import { onLoad } from '@dcloudio/uni-app'
  58. import { EquipmentType } from '@/utils/dictMap'
  59. import { getEquipContainerById, getDeptListApi } from '@/api/index'
  60. import { useConfigStore } from '@/store/config'
  61. import { EquipFuncName, requestFunc } from '@/api/ApiRouter/equipment'
  62. import ContainerBaseInfo from '@/pages/equipment/detail/components/ContainerBaseInfo.vue'
  63. import BoilerBaseInfo from '@/pages/equipment/detail/components/BoilerBaseInfo.vue'
  64. import PipeBaseInfo from '@/pages/equipment/detail/components/PipeBaseInfo.vue'
  65. import ContainerEquipmentInfo from '@/pages/equipment/detail/components/ContainerEquipmentInfo.vue'
  66. import BoilerEquipmentInfo from '@/pages/equipment/detail/components/BoilerEquipmentInfo.vue'
  67. import PipeEquipmentInfo from '@/pages/equipment/detail/components/PipeEquipmentInfo.vue'
  68. import HistoryReport from '@/pages/equipment/detail/components/HistoryReport.vue'
  69. import NavBar from '@/components/NavBar/NavBar.vue'
  70. interface TabItem {
  71. value: string
  72. id: string
  73. }
  74. const storedEquipType = useConfigStore().equipType
  75. let equipType: EquipmentType = storedEquipType
  76. const BaseInfoComponent = computed(() => {
  77. switch (equipType) {
  78. case EquipmentType.BOILER:
  79. return BoilerBaseInfo
  80. case EquipmentType.PIPE:
  81. return PipeBaseInfo
  82. case EquipmentType.CONTAINER:
  83. return ContainerBaseInfo
  84. default:
  85. return ContainerBaseInfo
  86. }
  87. })
  88. const EquipmentInfoComponent = computed(() => {
  89. switch (equipType) {
  90. case EquipmentType.BOILER:
  91. return BoilerEquipmentInfo
  92. case EquipmentType.PIPE:
  93. return PipeEquipmentInfo
  94. case EquipmentType.CONTAINER:
  95. return ContainerEquipmentInfo
  96. default:
  97. return ContainerEquipmentInfo
  98. }
  99. })
  100. const currentTab = ref(0)
  101. const equipmentData = ref<any>({})
  102. const taskOrder = ref<any>({})
  103. const dataSource = ref<any>(null)
  104. const tabList: TabItem[] = [
  105. { value: '基本信息', id: 'baseInfo' },
  106. { value: '设备信息', id: 'equipmentInfo' },
  107. { value: '历史报告', id: 'historyReport' },
  108. ]
  109. let id = ''
  110. let pageType = 'baseInfo'
  111. onLoad((options: any) => {
  112. id = options.id || ''
  113. pageType = options.pageType || 'baseInfo'
  114. equipType = options.equipType || storedEquipType
  115. const initIndex = tabList.findIndex((item) => item.id === pageType)
  116. if (initIndex >= 0) {
  117. currentTab.value = initIndex
  118. }
  119. })
  120. // 切换 Tab
  121. const switchTab = (index: number) => {
  122. currentTab.value = index
  123. }
  124. // 获取设备详情
  125. const getEquipmentDetail = async () => {
  126. try {
  127. uni.showLoading({ title: '加载中...' })
  128. const result: any = await requestFunc(EquipFuncName.EquipDetail, equipType, { id })
  129. if (result?.data) {
  130. taskOrder.value = result.data
  131. let deptName = result.data.deptName
  132. if (result.data.deptId && !result.data.deptName) {
  133. try {
  134. const deptResult: any = await getDeptListApi({})
  135. if (deptResult?.code === 0 && deptResult?.data && Array.isArray(deptResult.data)) {
  136. const deptData = deptResult.data.find((dept: any) => dept.id === result.data.deptId)
  137. if (deptData?.name) {
  138. deptName = deptData.name
  139. }
  140. }
  141. } catch (error) {
  142. console.error('获取部门名称失败:', error)
  143. }
  144. }
  145. equipmentData.value = {
  146. ...result.data,
  147. deptName: deptName || result.data.deptName,
  148. }
  149. dataSource.value = {
  150. taskOrder: result.data,
  151. equipment: equipmentData.value,
  152. }
  153. }
  154. } catch (error) {
  155. console.error('获取设备详情失败:', error)
  156. uni.showToast({ title: '加载失败', icon: 'error' })
  157. } finally {
  158. uni.hideLoading()
  159. }
  160. }
  161. // 返回
  162. const goBack = () => {
  163. uni.navigateBack()
  164. }
  165. onMounted(() => {
  166. if (id) {
  167. getEquipmentDetail()
  168. }
  169. })
  170. </script>
  171. <style lang="scss" scoped>
  172. .detail-container {
  173. display: flex;
  174. flex-direction: column;
  175. height: 100vh;
  176. background-color: #f5f5f5;
  177. }
  178. .navigate-view {
  179. display: flex;
  180. flex-direction: row;
  181. align-items: center;
  182. justify-content: space-between;
  183. height: 44px;
  184. padding: 0 15px;
  185. background-color: #fff;
  186. border-bottom: 1px solid #eee;
  187. }
  188. .navigate-left {
  189. display: flex;
  190. align-items: center;
  191. }
  192. .back-icon {
  193. width: 20px;
  194. height: 20px;
  195. }
  196. .navigate-title {
  197. font-size: 17px;
  198. font-weight: 500;
  199. color: #333;
  200. }
  201. .navigate-right {
  202. width: 20px;
  203. }
  204. .tab-bar {
  205. display: flex;
  206. flex-direction: row;
  207. background-color: #fff;
  208. border-bottom: 1px solid #eee;
  209. }
  210. .tab-item {
  211. flex: 1;
  212. padding: 15px 0;
  213. text-align: center;
  214. border-bottom: 2px solid transparent;
  215. }
  216. .tab-item-active {
  217. border-bottom-color: rgb(47, 142, 255);
  218. }
  219. .tab-text {
  220. font-size: 15px;
  221. color: #666;
  222. }
  223. .tab-item-active .tab-text {
  224. font-weight: 500;
  225. color: rgb(47, 142, 255);
  226. }
  227. .scroll-content {
  228. flex: 1;
  229. padding: 10px;
  230. }
  231. .tab-content {
  232. min-height: 100%;
  233. }
  234. .section {
  235. margin-bottom: 10px;
  236. overflow: hidden;
  237. background-color: #fff;
  238. border-radius: 5px;
  239. }
  240. .section-header {
  241. padding: 15px;
  242. border-bottom: 1px solid #f0f0f0;
  243. }
  244. .section-title {
  245. font-size: 16px;
  246. font-weight: 600;
  247. color: #333;
  248. }
  249. .info-list {
  250. padding: 0 15px;
  251. }
  252. .info-item {
  253. display: flex;
  254. flex-direction: row;
  255. padding: 12px 0;
  256. border-bottom: 1px solid #f5f5f5;
  257. }
  258. .info-item:last-child {
  259. border-bottom: none;
  260. }
  261. .info-label {
  262. flex-shrink: 0;
  263. width: 100px;
  264. font-size: 14px;
  265. color: #666;
  266. }
  267. .info-value {
  268. flex: 1;
  269. font-size: 14px;
  270. color: #333;
  271. }
  272. .empty-state {
  273. display: flex;
  274. align-items: center;
  275. justify-content: center;
  276. padding: 40px 0;
  277. }
  278. .empty-text {
  279. font-size: 14px;
  280. color: #999;
  281. }
  282. </style>