business_tms_program 0.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (136) hide show
  1. package/.editorconfig +12 -0
  2. package/.eslintrc-auto-import.json +113 -0
  3. package/.eslintrc.js +121 -0
  4. package/.prettierrc.js +9 -0
  5. package/.stylelintignore +4 -0
  6. package/README.md +43 -0
  7. package/components.d.ts +23 -0
  8. package/index.html +20 -0
  9. package/package.json +70 -0
  10. package/shims-uni.d.ts +10 -0
  11. package/src/App.vue +81 -0
  12. package/src/api/afterSale.ts +184 -0
  13. package/src/api/context.ts +26 -0
  14. package/src/api/device.ts +134 -0
  15. package/src/api/index.ts +80 -0
  16. package/src/api/installtion.ts +155 -0
  17. package/src/api/model/index.ts +15 -0
  18. package/src/api/model/userModel.ts +62 -0
  19. package/src/api/order.ts +49 -0
  20. package/src/api/system.ts +19 -0
  21. package/src/api/user.ts +171 -0
  22. package/src/auto-imports.d.ts +108 -0
  23. package/src/components/ConfirmDialog.vue +101 -0
  24. package/src/components/DaySelect.vue +212 -0
  25. package/src/components/Drawer.vue +104 -0
  26. package/src/components/DrawerSelect.vue +105 -0
  27. package/src/components/DropMenu.vue +144 -0
  28. package/src/components/Empty.vue +49 -0
  29. package/src/components/Loading.vue +41 -0
  30. package/src/components/RippleBtn.vue +159 -0
  31. package/src/components/SinglePick.vue +120 -0
  32. package/src/components/Skeleton.vue +43 -0
  33. package/src/components/Timeline.vue +85 -0
  34. package/src/components/Upload.vue +217 -0
  35. package/src/config/app.ts +32 -0
  36. package/src/config/env.ts +29 -0
  37. package/src/dict/afterSale.ts +161 -0
  38. package/src/dict/device.ts +29 -0
  39. package/src/dict/installtion.ts +141 -0
  40. package/src/dict/systems.ts +4 -0
  41. package/src/env.d.ts +8 -0
  42. package/src/hooks/useForm.ts +222 -0
  43. package/src/hooks/useUpload.ts +80 -0
  44. package/src/main.ts +8 -0
  45. package/src/manifest.json +39 -0
  46. package/src/pages/acceptance/DeviceInfo.vue +132 -0
  47. package/src/pages/acceptance/list.vue +276 -0
  48. package/src/pages/afterSale/DeviceInfo.vue +128 -0
  49. package/src/pages/afterSale/Step.vue +0 -0
  50. package/src/pages/afterSale/faultReport.vue +552 -0
  51. package/src/pages/afterSale/orderDetail.vue +327 -0
  52. package/src/pages/afterSale/orderFinish.vue +517 -0
  53. package/src/pages/afterSale/orderList.vue +305 -0
  54. package/src/pages/afterSale/returnVisit.vue +288 -0
  55. package/src/pages/afterSale/searchDeviceList.vue +148 -0
  56. package/src/pages/device/Search.vue +201 -0
  57. package/src/pages/device/acceptance.vue +270 -0
  58. package/src/pages/device/detail.vue +165 -0
  59. package/src/pages/device/index.vue +322 -0
  60. package/src/pages/device/info.vue +140 -0
  61. package/src/pages/device/list.vue +219 -0
  62. package/src/pages/device/materialTowerCode.vue +589 -0
  63. package/src/pages/device/searchList.vue +224 -0
  64. package/src/pages/installtion/Record.vue +145 -0
  65. package/src/pages/installtion/StatusTimeline.vue +85 -0
  66. package/src/pages/installtion/addAcceptance.vue +409 -0
  67. package/src/pages/installtion/addRecord.vue +338 -0
  68. package/src/pages/installtion/orderDetail.vue +220 -0
  69. package/src/pages/installtion/orderList.vue +100 -0
  70. package/src/pages/user/component/PersonAgree.vue +226 -0
  71. package/src/pages/user/component/PrivayAgree.vue +221 -0
  72. package/src/pages/user/component/SliderCode.vue +173 -0
  73. package/src/pages/user/forgetPassword.vue +249 -0
  74. package/src/pages/user/index.vue +139 -0
  75. package/src/pages/user/login.vue +342 -0
  76. package/src/pages/user/register.vue +348 -0
  77. package/src/pages/user/repassword.vue +329 -0
  78. package/src/pages/user/utils/mcaptcha.js +75 -0
  79. package/src/pages/user/utils/verifyCode.ts +41 -0
  80. package/src/pages/workspace/index.vue +225 -0
  81. package/src/pages.json +203 -0
  82. package/src/shime-uni.d.ts +6 -0
  83. package/src/static/icon/system/breeder_icon.png +0 -0
  84. package/src/static/icon/system/check.png +0 -0
  85. package/src/static/icon/system/factory_icon.png +0 -0
  86. package/src/static/icon/system/plus.png +0 -0
  87. package/src/static/icon/system/right.png +0 -0
  88. package/src/static/icon/system/unCheck.png +0 -0
  89. package/src/static/icon/tab/search.png +0 -0
  90. package/src/static/icon/tab/user.png +0 -0
  91. package/src/static/icon/tab/user_active.png +0 -0
  92. package/src/static/icon/tab/workspace.png +0 -0
  93. package/src/static/icon/tab/workspace_active.png +0 -0
  94. package/src/static/img/active_dot.png +0 -0
  95. package/src/static/img/afterSale_icon.png +0 -0
  96. package/src/static/img/check.png +0 -0
  97. package/src/static/img/close.png +0 -0
  98. package/src/static/img/confirm.png +0 -0
  99. package/src/static/img/empty.png +0 -0
  100. package/src/static/img/equipment_icon.png +0 -0
  101. package/src/static/img/fault_icon.png +0 -0
  102. package/src/static/img/install_icon.png +0 -0
  103. package/src/static/img/login_bg2.png +0 -0
  104. package/src/static/img/movable_right.png +0 -0
  105. package/src/static/img/navigation.png +0 -0
  106. package/src/static/img/psw_off.png +0 -0
  107. package/src/static/img/psw_on.png +0 -0
  108. package/src/static/img/scan.png +0 -0
  109. package/src/static/img/scan_icon.png +0 -0
  110. package/src/static/img/search.png +0 -0
  111. package/src/static/img/turn_right.png +0 -0
  112. package/src/static/img/unActive_dot.png +0 -0
  113. package/src/static/img/verifyBg.png +0 -0
  114. package/src/stores/index.ts +11 -0
  115. package/src/stores/modules/customer.ts +146 -0
  116. package/src/stores/modules/installtion.ts +30 -0
  117. package/src/stores/modules/system.ts +56 -0
  118. package/src/stores/modules/user.ts +133 -0
  119. package/src/stores/types.ts +16 -0
  120. package/src/stores/utils.ts +6 -0
  121. package/src/styles/index.less +63 -0
  122. package/src/types/chengyiApi.d.ts +36 -0
  123. package/src/types/index.d.ts +95 -0
  124. package/src/utils/address.ts +17 -0
  125. package/src/utils/cipher.ts +61 -0
  126. package/src/utils/form.ts +155 -0
  127. package/src/utils/httpEnum.ts +31 -0
  128. package/src/utils/image.ts +21 -0
  129. package/src/utils/index.ts +111 -0
  130. package/src/utils/request.ts +139 -0
  131. package/src/utils/requestCancelHandle.ts +67 -0
  132. package/stylelint.config.js +87 -0
  133. package/tsconfig.docs.json +11 -0
  134. package/tsconfig.json +30 -0
  135. package/typedoc.json +6 -0
  136. package/vite.config.ts +55 -0
@@ -0,0 +1,165 @@
1
+ <script setup lang="ts">
2
+ import { ref } from 'vue'
3
+ import { queryDeviceDetail } from '@/api/device'
4
+ import Skeleton from '@/components/Skeleton.vue';
5
+ import { isCheckStatusEnum, DeviceMesStatusEnum, deviceMesStatusMap } from '@/dict/device'
6
+ defineOptions({
7
+ name: "deviceDetail"
8
+ });
9
+ const toDeviceAcceptance = () => {
10
+ uni.navigateTo({ url: `/pages/device/acceptance?deviceCode=${state.info.deviceCode}` })
11
+ }
12
+
13
+ const toDeviceInfo = () => {
14
+ uni.navigateTo({ url: `/pages/device/info?deviceCode=${state.info.deviceCode}` })
15
+ }
16
+ const state = reactive({
17
+ info: {} as any,
18
+ loading: false,
19
+ })
20
+ const fetchDetail = async (code: string) => {
21
+ state.loading = true;
22
+ const res = await queryDeviceDetail({
23
+ deviceCode: code,
24
+ });
25
+ state.loading = false;
26
+ if (res) {
27
+ state.info = res;
28
+ }
29
+ }
30
+ onLoad((event: any) => {
31
+ const { deviceCode } = event;
32
+ fetchDetail(deviceCode);
33
+ uni.$on('deviceList-updated-success', () => {
34
+ state.info.isCheckStatus = isCheckStatusEnum.YES;
35
+ });
36
+ });
37
+
38
+ // 监听页面显示,刷新设备信息
39
+ onShow(() => {
40
+ if (state.info.deviceCode) {
41
+ fetchDetail(state.info.deviceCode);
42
+ }
43
+ });
44
+ </script>
45
+
46
+ <template>
47
+ <view class="content">
48
+ <view class="skeleton-box" v-if="state.loading">
49
+ <Skeleton class="skeleton-container"></Skeleton>
50
+ <Skeleton class="skeleton-container"></Skeleton>
51
+ <Skeleton class="skeleton-container"></Skeleton>
52
+ <Skeleton class="skeleton-container"></Skeleton>
53
+ <Skeleton class="skeleton-container"></Skeleton>
54
+ </view>
55
+ <view v-else>
56
+ <view class="form-box">
57
+ <view class="text">产品名称:{{ state.info.productName }}</view>
58
+ <view class="text">设备编码:{{ state.info.deviceCode }}</view>
59
+ <view class="text">所属用户:{{ state.info.customerName }}</view>
60
+ </view>
61
+ <view class="uni-form-item" @click="toDeviceAcceptance">
62
+ <view class="l-label">
63
+ 设备客户验收
64
+ </view>
65
+ <view class="statusBox">
66
+ <view class="status-text">
67
+ {{ state.info.isCheckStatus === isCheckStatusEnum.YES ? '已验收' : '未验收'}}
68
+ </view>
69
+ <image class="right-icon" src="/static/img/turn_right.png" />
70
+ </view>
71
+ </view>
72
+ <view class="uni-form-item" @click="toDeviceInfo">
73
+ <view class="l-label">
74
+ 设备信息
75
+ </view>
76
+ <view class="statusBox">
77
+ <view class="status-text" :class="{ 'status-pending': state.info.deviceMesStatus === DeviceMesStatusEnum.PENDING }">
78
+ {{ state.info.deviceMesStatus ? deviceMesStatusMap[state.info.deviceMesStatus] : '待补充' }}
79
+ </view>
80
+ <image class="right-icon" src="/static/img/turn_right.png" />
81
+ </view>
82
+ </view>
83
+ </view>
84
+ </view>
85
+ </template>
86
+ <style scoped lang="less">
87
+ .content {
88
+ background-color: #F5F5F5;
89
+ min-height: 100vh;
90
+ padding: 32rpx;
91
+
92
+ .text {
93
+ margin-bottom: 22rpx;
94
+ font-weight: 400;
95
+ font-size: 28rpx;
96
+ color: #000000;
97
+ line-height: 40rpx;
98
+
99
+ &:last-child {
100
+ margin-bottom: 0;
101
+ }
102
+ }
103
+
104
+ .uni-form-item {
105
+ display: flex;
106
+ align-items: center;
107
+ justify-content: space-between;
108
+ background-color: #fff;
109
+ border-radius: 16rpx;
110
+ padding: 0 32rpx;
111
+ margin-top: 32rpx;
112
+
113
+ &:first-of-type {
114
+ margin-top: 0;
115
+ }
116
+
117
+ .l-label {
118
+ display: flex;
119
+ align-items: center;
120
+ padding: 32rpx 0;
121
+ font-size: 32rpx;
122
+ color: rgba(0, 0, 0, 0.6);
123
+ line-height: 48rpx;
124
+
125
+ .flag {
126
+ font-size: 32rpx;
127
+ color: #E34D59;
128
+ line-height: 38rpx;
129
+ }
130
+ }
131
+
132
+ .statusBox {
133
+ display: flex;
134
+ align-items: center;
135
+
136
+ .status-text {
137
+ font-size: 28rpx;
138
+ line-height: 40rpx;
139
+ color: rgba(0, 0, 0, 0.4);
140
+
141
+ &.status-pending {
142
+ color: rgba(0, 0, 0, 0.4);
143
+ }
144
+ }
145
+ }
146
+
147
+ // 设备客户验收的特殊样式
148
+ &:first-of-type .statusBox .status-text {
149
+ color: #F5894E;
150
+ }
151
+
152
+ .right-icon {
153
+ margin-left: 16rpx;
154
+ width: 32rpx;
155
+ height: 32rpx;
156
+ text-align: right;
157
+ }
158
+ }
159
+
160
+ .select-box {
161
+ flex: 1;
162
+ min-width: 0;
163
+ }
164
+ }
165
+ </style>
@@ -0,0 +1,322 @@
1
+ <script setup lang="ts">
2
+ import { ref } from 'vue'
3
+ import { isCheckStatusEnum } from '@/dict/device'
4
+ import { queryDevicePageList, queryCustomerCode } from '@/api/device'
5
+ import { set, throttle } from 'lodash-es';
6
+ import DropMenu from '@/components/DropMenu.vue'
7
+ import Skeleton from '@/components/Skeleton.vue';
8
+ import LoadingView from '@/components/Loading.vue';
9
+ import Empty from '@/components/Empty.vue';
10
+ import { debounce } from 'lodash-es';
11
+ defineOptions({
12
+ name: "deviceList"
13
+ });
14
+ const selectedValue = ref('customerCode')
15
+ const options = [
16
+ { value: 'customerCode', name: '客户名称' },
17
+ { value: 'deviceCode', name: '设备编号' },
18
+ ]
19
+ const state = reactive({
20
+ itemDatas: [] as any,
21
+ current: 1,
22
+ size: 10,
23
+ loadMore: false,
24
+ hasMore: true,
25
+ screenHeight: uni.getSystemInfoSync().windowHeight,
26
+ triggerRatio: 0.3, // 设置触发比例为屏幕高度的30%
27
+ loadingTop: false, // 顶部下拉刷新
28
+ customerCode: '',
29
+ searchValue: '', // 搜索框的值
30
+ hasSearch: false, // 是否有搜索过
31
+ customerSearchList: [] as any,
32
+ hasSearchCustomer: false, // 是否有搜索过
33
+ });
34
+ const loadData = async (page?: number) => {
35
+ if (state.loadMore) return;
36
+ state.loadMore = true;
37
+ const params = {
38
+ size: state.size,
39
+ current: page || state.current,
40
+ [selectedValue.value]: state.searchValue, // 动态查询字段
41
+ }
42
+ if (selectedValue.value === 'customerCode') {
43
+ params.customerCode = state.customerCode;
44
+ } else {
45
+ params.deviceCode = state.searchValue;
46
+ }
47
+ const { records, current } = await queryDevicePageList(params);
48
+ state.loadMore = false;
49
+ if (!records) {
50
+ return
51
+ }
52
+ const newData = records.map((item) => {
53
+ return { ...item, show: true };
54
+ });
55
+ if (page === 1) {
56
+ state.itemDatas = newData;
57
+ } else {
58
+ state.itemDatas = [...state.itemDatas,...newData];
59
+ }
60
+ state.current = current;
61
+ state.hasMore = records.length > 0;
62
+ if (!state.hasSearch) {
63
+ state.hasSearch = true;
64
+ }
65
+ state.hasSearchCustomer = false;
66
+ }
67
+ const searchDevice = async (value: string) => {
68
+ if (!value) {
69
+ return; // 输入为空时不进行搜索
70
+ }
71
+ state.customerCode = value; // 更新搜索条件
72
+ state.hasSearchCustomer = false; // 重置搜索状态
73
+ loadData(1); // 刷新数据
74
+ }
75
+ const searchCustomer = debounce(async (value: string) => {
76
+ state.itemDatas = [];
77
+ const res = await queryCustomerCode({
78
+ customerName: value, // 假设搜索字段为customerName
79
+ })
80
+ setTimeout(() => {
81
+ state.hasSearchCustomer = true;
82
+ }, 400);
83
+ if (!res) {
84
+ return; // 搜索失败时不更新数据
85
+ }
86
+ state.customerSearchList = res;
87
+ })
88
+ // 滚动到底部加载更多
89
+ const onScrollToLower = throttle(() => {
90
+ if (!state.loadMore && state.hasMore) {
91
+ state.current++;
92
+ nextTick(() => {
93
+ loadData(state.current);
94
+ })
95
+ }
96
+ }, 500);
97
+ const handleSearchInput = (e: any) => {
98
+ const { value } = e.detail;
99
+ if (value === state.searchValue) {
100
+ return; // 输入值未改变,不进行搜索
101
+ }
102
+ state.searchValue = value;
103
+ if (selectedValue.value === 'deviceCode') {
104
+ loadData(1);
105
+ return;
106
+ } else {
107
+ searchCustomer(state.searchValue);
108
+ }
109
+ }
110
+ const toSearch = () => {
111
+ if (selectedValue.value === 'customerCode') {
112
+ // nextTick(() => {
113
+ // searchCustomer(state.searchValue);
114
+ // })
115
+ } else {
116
+ loadData(1);
117
+ }
118
+ }
119
+ const resetSearch = () => {
120
+ state.hasSearchCustomer = false;
121
+ state.searchValue = ''; // 清空搜索框的值
122
+ state.customerCode = ''; // 清空搜索条件
123
+ loadData(1);
124
+ }
125
+ const toDeviceDetail = (item: any) => {
126
+ uni.navigateTo({ url: `/pages/device/detail?deviceCode=${item.deviceCode}` })
127
+ }
128
+ const changeSearchType = (value: string) => {
129
+ selectedValue.value = value; // 更新selectedValue的值
130
+ state.searchValue = ''; // 清空搜索框的值
131
+ state.hasSearch = false; // 重置搜索状态
132
+ state.hasMore = true; // 重置是否有更多数据
133
+ state.hasSearchCustomer = false; // 重置是否有搜索过
134
+ state.customerSearchList = []; // 清空搜索结果
135
+ state.customerCode = ''; // 清空搜索条件
136
+ nextTick(() => {
137
+ loadData(1); // 刷新数据
138
+ })
139
+ }
140
+ onMounted(async () => {
141
+ loadData(1);
142
+ uni.$on('deviceList-updated', () => {
143
+ state.searchValue = '';
144
+ state.hasSearch = false;
145
+ loadData(1); // 刷新数据
146
+ });
147
+ })
148
+ const showCustometList = computed(() => {
149
+ return state.hasSearchCustomer && selectedValue.value === 'customerCode';
150
+ })
151
+ </script>
152
+
153
+ <template>
154
+ <view class="content">
155
+ <view class="header">
156
+ <DropMenu v-model="selectedValue" :options="options" @change="changeSearchType"/>
157
+ <view class="input-wrapper">
158
+ <input class="search-input" @change="handleSearchInput" :value="state.searchValue" />
159
+ </view>
160
+ <image v-if="!showCustometList" @click="toSearch" class="uni-icon" src="/static/img/search.png" />
161
+ <view v-else class="back-icon" @click="resetSearch">取消</view>
162
+ </view>
163
+ <view class="skeleton-box" v-if="!state.hasSearch">
164
+ <Skeleton class="skeleton-container"></Skeleton>
165
+ <Skeleton class="skeleton-container"></Skeleton>
166
+ <Skeleton class="skeleton-container"></Skeleton>
167
+ <Skeleton class="skeleton-container"></Skeleton>
168
+ <Skeleton class="skeleton-container"></Skeleton>
169
+ </view>
170
+ <view class="customer-box" v-if="showCustometList">
171
+ <Empty v-if="state.customerSearchList.length === 0" desc="暂未搜索到相关客户"/>
172
+ <view class="customer-item"
173
+ v-else
174
+ v-for="item in state.customerSearchList" :key="item.customerCode"
175
+ @click="searchDevice(item.customerCode)"
176
+ >
177
+ {{ item.customerName }}<view class="code">{{ item.customerCode }}</view>
178
+ </view>
179
+ </view>
180
+ <scroll-view
181
+ v-else
182
+ class="scroll-view"
183
+ scroll-y
184
+ bounces
185
+ show-scrollbar
186
+ scroll-with-animation
187
+ @scrolltolower="onScrollToLower"
188
+ :lower-threshold="`${state.screenHeight * state.triggerRatio}`"
189
+ >
190
+ <view class="scroll-box">
191
+ <view class="record-box"
192
+ v-for="item in state.itemDatas"
193
+ :key="item.deviceCode"
194
+ @click="toDeviceDetail(item)"
195
+ >
196
+ <view class="img"></view>
197
+ <view class="info">
198
+ <view class="inlineBox">
199
+ <view class="code">{{item.deviceCode}}</view>
200
+ <view class="status" :class="{'unCheck': item.isCheckStatus === isCheckStatusEnum.NO}">
201
+ {{item.isCheckStatus === isCheckStatusEnum.YES ? '已验收' : '未验收'}}
202
+ </view>
203
+ </view>
204
+ <view class="contact">客户:{{item.customerName}}</view>
205
+ </view>
206
+ </view>
207
+ <Empty v-if="state.itemDatas.length === 0 && state.hasSearch" />
208
+ <LoadingView v-if="state.loadMore" class="loading-indicator" :size="50"></LoadingView>
209
+ <view v-if="state.itemDatas.length > 0 && !state.hasMore" class="noMore">没有更多数据了</view>
210
+ </view>
211
+ </scroll-view>
212
+ </view>
213
+ </template>
214
+ <style scoped lang="less">
215
+ .content {
216
+ background-color: #F5F5F5;
217
+ min-height: 100vh;
218
+ }
219
+ .header {
220
+ padding: 8rpx 12rpx;
221
+ background-color: #fff;
222
+ display: flex;
223
+ align-items: center;
224
+ width: 100vw;
225
+ height: 96rpx;
226
+ .input-wrapper{
227
+ flex: 1;
228
+ margin-left: 4rpx;
229
+ padding: 0 24rpx;
230
+ background: rgba(0,0,0,0.04);
231
+ border-radius: 8rpx;
232
+ display: flex;
233
+ align-items: center;
234
+ }
235
+ .search-input {
236
+ flex: 1;
237
+ margin-right: 12rpx;
238
+ font-size: 24rpx;
239
+ padding: 12rpx 0 12rpx 0;
240
+ color: rgba(0,0,0,0.4);
241
+ }
242
+ .uni-icon {
243
+ padding: 0 12rpx 0 16rpx;
244
+ width: 36rpx;
245
+ height: 36rpx;
246
+ }
247
+ .back-icon {
248
+ padding: 0 12rpx;
249
+ font-size: 24rpx;
250
+ color: rgba(0,0,0,0.6);
251
+ }
252
+ }
253
+ .scroll-view{
254
+ height: calc(100vh - 96rpx);
255
+ }
256
+ .scroll-box {
257
+ padding: 16rpx 32rpx;
258
+ box-sizing: border-box;
259
+ }
260
+ .record-box{
261
+ display: flex;
262
+ margin-bottom: 16rpx;
263
+ padding: 36rpx;
264
+ background: #FFFFFF;
265
+ border-radius: 16rpx;
266
+ .img{
267
+ margin-right: 16rpx;
268
+ width: 96rpx;
269
+ height: 96rpx;
270
+ background: #E8E8E8;
271
+ border-radius: 8rpx;
272
+ }
273
+ .inlineBox{
274
+ display: flex;
275
+ margin-bottom: 6rpx;
276
+ .code{
277
+ margin-right: 16rpx;
278
+ font-weight: bold;
279
+ font-size: 32rpx;
280
+ color: #000000;
281
+ line-height: 38rpx;
282
+ }
283
+ .status{
284
+ padding: 6rpx 16rpx 8rpx 16rpx;
285
+ font-weight: 400;
286
+ font-size: 24rpx;
287
+ color: #1D6FE9;
288
+ line-height: 34rpx;
289
+ border-radius: 24rpx;
290
+ background: rgba(29,111,233,0.1);
291
+ border: 1rpx solid #1D6FE9;
292
+ }
293
+ .unCheck {
294
+ color: #F5894E;
295
+ border: 1rpx solid #F5894E;
296
+ background: rgba(245,137,78,0.1);
297
+ }
298
+ }
299
+ .contact{
300
+ font-size: 28rpx;
301
+ color: rgba(0,0,0, 0.6);
302
+ line-height: 40rpx;
303
+ }
304
+ }
305
+ .customer-box{
306
+ padding: 18rpx 0rpx;
307
+ .customer-item{
308
+ display: flex;
309
+ align-items: flex-end;
310
+ background-color: #fff;
311
+ padding: 18rpx 16rpx 18rpx 42rpx;
312
+ font-size: 28rpx;
313
+ margin-bottom: 1rpx;
314
+ color: rgba(0,0,0,0.6);
315
+ .code{
316
+ margin-left: 24rpx;
317
+ font-size: 24rpx;
318
+ color: rgba(0,0,0,0.4);
319
+ }
320
+ }
321
+ }
322
+ </style>
@@ -0,0 +1,140 @@
1
+ <script setup lang="ts">
2
+ import { ref } from 'vue'
3
+ import { queryDeviceDetail } from '@/api/device'
4
+ import Skeleton from '@/components/Skeleton.vue';
5
+
6
+ defineOptions({
7
+ name: "deviceInfo"
8
+ });
9
+
10
+ const toMaterialTowerCode = () => {
11
+ uni.navigateTo({ url: `/pages/device/materialTowerCode?deviceCode=${state.info.deviceCode}` })
12
+ }
13
+
14
+ const state = reactive({
15
+ info: {} as any,
16
+ loading: false,
17
+ })
18
+
19
+ const fetchDetail = async (code: string) => {
20
+ state.loading = true;
21
+ const res = await queryDeviceDetail({
22
+ deviceCode: code,
23
+ });
24
+ state.loading = false;
25
+ if (res) {
26
+ state.info = res;
27
+ }
28
+ }
29
+
30
+ onLoad((event: any) => {
31
+ const { deviceCode } = event;
32
+ fetchDetail(deviceCode);
33
+ });
34
+
35
+ // 监听页面显示,刷新设备信息
36
+ onShow(() => {
37
+ if (state.info.deviceCode) {
38
+ fetchDetail(state.info.deviceCode);
39
+ }
40
+ });
41
+ </script>
42
+
43
+ <template>
44
+ <view class="content">
45
+ <view class="skeleton-box" v-if="state.loading">
46
+ <Skeleton class="skeleton-container"></Skeleton>
47
+ <Skeleton class="skeleton-container"></Skeleton>
48
+ <Skeleton class="skeleton-container"></Skeleton>
49
+ <Skeleton class="skeleton-container"></Skeleton>
50
+ <Skeleton class="skeleton-container"></Skeleton>
51
+ </view>
52
+ <view v-else>
53
+ <view class="form-box">
54
+ <view class="text">产品名称:{{ state.info.productName }}</view>
55
+ <view class="text">设备编码:{{ state.info.deviceCode }}</view>
56
+ <view class="text">所属用户:{{ state.info.customerName }}</view>
57
+ </view>
58
+ <view class="uni-form-item" @click="toMaterialTowerCode">
59
+ <view class="l-label">
60
+ 料塔编码
61
+ </view>
62
+ <view class="statusBox">
63
+ <view class="status-text">
64
+ {{ state.info.siloCode || '请选择' }}
65
+ </view>
66
+ <image class="right-icon" src="/static/img/turn_right.png" />
67
+ </view>
68
+ </view>
69
+ </view>
70
+ </view>
71
+ </template>
72
+
73
+ <style scoped lang="less">
74
+ .content {
75
+ background-color: #F5F5F5;
76
+ min-height: 100vh;
77
+ padding: 32rpx;
78
+
79
+ .text {
80
+ margin-bottom: 22rpx;
81
+ font-weight: 400;
82
+ font-size: 28rpx;
83
+ color: #000000;
84
+ line-height: 40rpx;
85
+
86
+ &:last-child {
87
+ margin-bottom: 0;
88
+ }
89
+ }
90
+
91
+ .uni-form-item {
92
+ display: flex;
93
+ align-items: center;
94
+ justify-content: space-between;
95
+ background-color: #fff;
96
+ border-radius: 16rpx;
97
+ padding: 0 32rpx;
98
+ margin-top: 32rpx;
99
+
100
+ .l-label {
101
+ display: flex;
102
+ align-items: center;
103
+ padding: 32rpx 0;
104
+ font-size: 32rpx;
105
+ color: rgba(0, 0, 0, 0.6);
106
+ line-height: 48rpx;
107
+
108
+ .flag {
109
+ font-size: 32rpx;
110
+ color: #E34D59;
111
+ line-height: 38rpx;
112
+ }
113
+ }
114
+
115
+ .statusBox {
116
+ display: flex;
117
+ align-items: center;
118
+
119
+ .status-text {
120
+ font-size: 28rpx;
121
+ line-height: 40rpx;
122
+ color: rgba(0, 0, 0, 0.4);
123
+ }
124
+ }
125
+
126
+ .right-icon {
127
+ margin-left: 16rpx;
128
+ width: 32rpx;
129
+ height: 32rpx;
130
+ text-align: right;
131
+ }
132
+ }
133
+
134
+ .select-box {
135
+ flex: 1;
136
+ min-width: 0;
137
+ }
138
+ }
139
+ </style>
140
+