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,276 @@
1
+ <script setup lang="ts">
2
+ import { ref } from 'vue'
3
+ import { installAcceptanceStatusEnum } from '@/dict/installtion'
4
+ import { getInstalltionStatusOrderList } from '@/api/installtion'
5
+ import { throttle } from 'lodash-es';
6
+ import DeviceInfo from './DeviceInfo.vue';
7
+ import Skeleton from '@/components/Skeleton.vue';
8
+ import LoadingView from '@/components/Loading.vue';
9
+ import Empty from '@/components/Empty.vue';
10
+ defineOptions({
11
+ name: "orderList"
12
+ });
13
+ const acticveTab = ref(installAcceptanceStatusEnum.NO)
14
+ const orderTabList = [
15
+ {
16
+ name: '安装待验收',
17
+ value: installAcceptanceStatusEnum.NO,
18
+ },
19
+ {
20
+ name: '安装已验收',
21
+ value: installAcceptanceStatusEnum.YES,
22
+ }
23
+ ]
24
+ const state = reactive({
25
+ itemDatas: [],
26
+ current: 1,
27
+ size: 5,
28
+ loadMore: false,
29
+ hasMore: true,
30
+ screenHeight: uni.getSystemInfoSync().windowHeight,
31
+ triggerRatio: 0.3, // 设置触发比例为屏幕高度的30%
32
+ loadingTop: false, // 顶部下拉刷新
33
+ total: 0,
34
+ hasSearch: false, // 是否有搜索过
35
+ });
36
+ const completeState = reactive({
37
+ itemDatas: [],
38
+ current: 1,
39
+ size: 5,
40
+ loadMore: false,
41
+ screenHeight: uni.getSystemInfoSync().windowHeight,
42
+ triggerRatio: 0.3, // 设置触发比例为屏幕高度的30%
43
+ hasMore: true,
44
+ loadingTop: false, // 顶部下拉刷新
45
+ total: 0,
46
+ hasSearch: false, // 是否有搜索过
47
+ });
48
+ const handleTabChange = (value: number) => {
49
+ acticveTab.value = value
50
+ }
51
+ const loadData = async (page?: number) => {
52
+ if (state.loadMore) return;
53
+ state.loadMore = true;
54
+ try {
55
+ const { records, current, total } = await getInstalltionStatusOrderList({
56
+ size: state.size,
57
+ current: page || state.current,
58
+ status: installAcceptanceStatusEnum.NO,
59
+ });
60
+ const newData = records.map((item) => {
61
+ return { ...item, show: true };
62
+ });
63
+ if (page === 1) {
64
+ state.itemDatas = newData;
65
+ } else {
66
+ state.itemDatas = [...state.itemDatas,...newData];
67
+ }
68
+ state.current = current;
69
+ state.hasMore = records.length > 0;
70
+ state.total = total;
71
+ if (!state.hasSearch) {
72
+ state.hasSearch = true;
73
+ }
74
+ } catch (error) {
75
+ console.error('获取数据失败', error);
76
+ }
77
+ state.loadMore = false;
78
+ }
79
+ const loadCompleteData = async (page?: number) => {
80
+ if (completeState.loadMore) return;
81
+ completeState.loadMore = true;
82
+ try {
83
+ const { records, current, total } = await getInstalltionStatusOrderList({
84
+ size: completeState.size,
85
+ current: page || completeState.current,
86
+ status: installAcceptanceStatusEnum.YES,
87
+ });
88
+ const newData = records.map((item) => {
89
+ return { ...item, show: true };
90
+ });
91
+ if (page === 1) {
92
+ completeState.itemDatas = newData;
93
+ } else {
94
+ completeState.itemDatas = [...completeState.itemDatas, ...newData];
95
+ }
96
+ completeState.current = current;
97
+ completeState.hasMore = records.length > 0;
98
+ completeState.total = total;
99
+ if (!completeState.hasSearch) {
100
+ completeState.hasSearch = true;
101
+ }
102
+ } catch (error) {
103
+ console.error('获取数据失败', error);
104
+ }
105
+ completeState.loadMore = false;
106
+ }
107
+ // 滚动到底部加载更多
108
+ const onScrollToLower = throttle(() => {
109
+ if (!state.loadMore && state.hasMore) {
110
+ state.current++;
111
+ nextTick(() => {
112
+ loadData(state.current);
113
+ })
114
+ }
115
+ }, 500);
116
+ const onCompleteScrollToLower = throttle(() => {
117
+ if (!completeState.loadMore && completeState.hasMore) {
118
+ completeState.current++;
119
+ nextTick(() => {
120
+ loadCompleteData(completeState.current);
121
+ })
122
+ }
123
+ }, 500);
124
+ // 跳转工单详情
125
+ const toDetail = (item?: any) => {
126
+ uni.navigateTo({ url: `/pages/installtion/orderDetail?deviceId=${item.id}&workOrderCode=${item.workOrderCode}&type=toAcceptance` })
127
+ }
128
+ onMounted(async () => {
129
+ loadData(1);
130
+ loadCompleteData(1);
131
+ // uni.$on('orderList-updated', () => {
132
+ // loadData(1); // 刷新数据
133
+ // loadCompleteData(1); // 刷新数据
134
+ // });
135
+ })
136
+ onShow(() => {
137
+ loadData(1); // 刷新数据
138
+ loadCompleteData(1); // 刷新数据
139
+ })
140
+ </script>
141
+
142
+ <template>
143
+ <view class="content">
144
+ <view class="header">
145
+ <view class="tabList">
146
+ <view v-for="item in orderTabList" :key="item.value" class="tabItem" @click="handleTabChange(item.value)"
147
+ :class="{ 'active': item.value === acticveTab }">
148
+ {{ `${item.name}(${item.value === installAcceptanceStatusEnum.NO ? state.total : completeState.total})` }}
149
+ </view>
150
+ </view>
151
+ </view>
152
+ <scroll-view v-if="acticveTab === installAcceptanceStatusEnum.NO" class="scroll-view" scroll-y style="height: 100vh;"
153
+ bounces show-scrollbar scroll-with-animation @scrolltolower="onScrollToLower"
154
+ :lower-threshold="`${state.screenHeight * state.triggerRatio}`">
155
+ <view class="skeleton-box" v-if="!state.hasSearch">
156
+ <Skeleton class="skeleton-container"></Skeleton>
157
+ <Skeleton class="skeleton-container"></Skeleton>
158
+ <Skeleton class="skeleton-container"></Skeleton>
159
+ </view>
160
+ <view class="scroll-box">
161
+ <view class="record-box" v-for="item in state.itemDatas" :key="item.id">
162
+ <DeviceInfo :data="item" @clickDevice="toDetail" />
163
+ </view>
164
+ <Empty v-if="state.itemDatas.length === 0 && state.hasSearch" />
165
+ <LoadingView v-if="state.loadMore" class="loading-indicator" :size="50"></LoadingView>
166
+ <view v-if="state.itemDatas.length > 0 && !state.hasMore" class="noMore">没有更多数据了</view>
167
+ </view>
168
+ </scroll-view>
169
+ <scroll-view v-else class="scroll-view" scroll-y style="height: 100vh;" bounces show-scrollbar scroll-with-animation
170
+ @scrolltolower="onCompleteScrollToLower"
171
+ :lower-threshold="`${completeState.screenHeight * completeState.triggerRatio}`">
172
+ <view class="skeleton-box" v-if="!completeState.hasSearch">
173
+ <Skeleton class="skeleton-container"></Skeleton>
174
+ <Skeleton class="skeleton-container"></Skeleton>
175
+ <Skeleton class="skeleton-container"></Skeleton>
176
+ </view>
177
+ <view class="scroll-box">
178
+ <view class="record-box" v-for="item in completeState.itemDatas" :key="item.id">
179
+ <DeviceInfo :data="item" @clickDevice="toDetail" />
180
+ </view>
181
+ <Empty v-if="completeState.itemDatas.length === 0 && completeState.hasSearch" />
182
+ <LoadingView v-if="completeState.loadMore" class="loading-indicator" :size="50"></LoadingView>
183
+ <view v-if="completeState.itemDatas.length > 0 && !completeState.hasMore" class="noMore">没有更多数据了</view>
184
+ </view>
185
+ </scroll-view>
186
+ </view>
187
+ </template>
188
+ <style scoped lang="less">
189
+ .content {
190
+ background-color: #F5F5F5;
191
+ min-height: 100vh;
192
+ }
193
+
194
+ .header {
195
+ position: fixed;
196
+ width: 100%;
197
+ padding: 12rpx 32rpx;
198
+ background-color: #fff;
199
+ top: 0rpx;
200
+ left: 0;
201
+ z-index: 100;
202
+
203
+ .tabList {
204
+ display: flex;
205
+ border-radius: 16rpx;
206
+ border: 1rpx solid #1D6FE9; // 选中状态的边框颜色;
207
+ overflow: hidden;
208
+ font-size: 28rpx;
209
+ line-height: 40rpx;
210
+
211
+ .tabItem {
212
+ flex: 1; // 使两个tabItem平分宽度
213
+ text-align: center; // 文字居中
214
+ padding: 16rpx 0; // 添加一些内边距
215
+ border-bottom-color: #1D6FE9;
216
+ color: #1D6FE9; // 选中状态的文字颜色
217
+ padding: 12rpx 0;
218
+
219
+ &.active {
220
+ color: #fff;
221
+ background-color: #1D6FE9;
222
+ }
223
+ }
224
+ }
225
+ }
226
+
227
+ .scroll-box {
228
+ padding: 88rpx 32rpx 32rpx 32rpx;
229
+ box-sizing: border-box;
230
+ }
231
+
232
+ .record-box {
233
+ margin-top: 32rpx;
234
+ background-color: #fff;
235
+ border-radius: 16rpx;
236
+ padding: 32rpx;
237
+ position: relative;
238
+ .device-box {
239
+ padding: 16rpx 16rpx 24rpx 16rpx;
240
+ background-color: rgba(0, 0, 0, 0.05);
241
+
242
+ .deviceName {
243
+ margin-bottom: 16rpx;
244
+ font-size: 28rpx;
245
+ color: #000000;
246
+ line-height: 40rpx;
247
+ }
248
+
249
+ .deviceCode {
250
+ font-size: 28rpx;
251
+ color: rgba(0, 0, 0, 0.4);
252
+ line-height: 34px;
253
+ }
254
+
255
+ .addressInfo {
256
+ display: flex;
257
+ }
258
+
259
+ .address {
260
+ flex: 1;
261
+ width: 380rpx;
262
+ font-size: 28rpx;
263
+ color: #000000;
264
+ line-height: 40rpx;
265
+ }
266
+
267
+ .address-icon {
268
+ width: 48rpx;
269
+ height: 48rpx;
270
+ image-rendering: -webkit-optimize-contrast; /* 优化图片渲染 */
271
+ image-rendering: pixelated; /* 像素化渲染 */
272
+ transform: translateZ(0); /* 开启GPU加速 */
273
+ }
274
+ }
275
+ }
276
+ </style>
@@ -0,0 +1,128 @@
1
+ <script setup lang="ts">
2
+ import { PLACEHOLDER } from '@/config/app'
3
+ const props = defineProps({
4
+ data: {
5
+ type: Object,
6
+ default: {}
7
+ },
8
+ })
9
+ const toDetail = () => {
10
+ if (!props.data.id) {
11
+ return
12
+ }
13
+ uni.navigateTo({ url: `/pages/afterSale/orderDetail?orderId=${props.data.id}`})
14
+ }
15
+ const chooseAddress = () => {
16
+ const { latitude, longitude } = props.data;
17
+ uni.openLocation({
18
+ latitude: Number(latitude),
19
+ longitude: Number(longitude),
20
+ success: (res) => {
21
+ console.log(res);
22
+ },
23
+ fail: (err) => {
24
+ uni.showToast({ title: '获取位置失败', icon: 'error' })
25
+ }
26
+ })
27
+ }
28
+ </script>
29
+ <template>
30
+ <view>
31
+ <view @click="toDetail">
32
+ <view class="urgency" v-if="data.isUrgency">紧急</view>
33
+ <view class="customerName">{{ data.customerName || PLACEHOLDER }}</view>
34
+ <view class="orderCode">{{ data.orderCode || PLACEHOLDER }}</view>
35
+ <view class="contact">
36
+ <view class="name">联系人姓名:{{ data.contactsName || PLACEHOLDER }}</view>
37
+ <view class="mobile">联系电话:{{ data.contactsMobile || PLACEHOLDER }}</view>
38
+ </view>
39
+ </view>
40
+ <view class="device-box" @click.stop ="chooseAddress">
41
+ <view class="deviceName">{{ data.deviceName || PLACEHOLDER }}</view>
42
+ <view class="deviceCode">{{ data.deviceCode || PLACEHOLDER }}</view>
43
+ <view class="addressInfo" >
44
+ 设备地址:
45
+ <view class="address">{{ data.address || data.deviceAddress || PLACEHOLDER }}</view>
46
+ <image class="address-icon" src="/static/img/navigation.png" />
47
+ </view>
48
+ </view>
49
+ </view>
50
+ </template>
51
+
52
+ <style scoped>
53
+ .urgency {
54
+ position: absolute;
55
+ right: 32rpx;
56
+ top: 32rpx;
57
+ display: block;
58
+ padding: 6rpx 16rpx 8rpx 16rpx;
59
+ font-size: 24rpx;
60
+ color: #E34D59;
61
+ line-height: 34rpx;
62
+ background: rgba(227,77,89,0.1);
63
+ border-radius: 8rpx;
64
+ border: 1rpx solid #E34D59;
65
+ }
66
+ .customerName {
67
+ font-size: 32rpx;
68
+ color: #000000;
69
+ line-height: 48rpx;
70
+ margin-bottom: 16rpx;
71
+ font-weight: 600;
72
+ }
73
+
74
+ .orderCode {
75
+ font-size: 28rpx;
76
+ color: rgba(0, 0, 0, 0.4);
77
+ line-height: 34rpx;
78
+ margin-bottom: 16rpx;
79
+ }
80
+
81
+ .contact {
82
+ display: flex;
83
+ justify-content: space-between;
84
+ margin-bottom: 32rpx;
85
+ font-size: 28rpx;
86
+ color: #000000;
87
+ line-height: 40rpx;
88
+ }
89
+ .device-box {
90
+ padding: 24rpx 16rpx 24rpx 24rpx;
91
+ background-color: #F3F8FE;
92
+ border-radius: 8rpx;
93
+
94
+ .deviceName {
95
+ font-size: 28rpx;
96
+ color: #000000;
97
+ line-height: 40rpx;
98
+ font-weight: 500;
99
+ }
100
+
101
+ .deviceCode {
102
+ font-size: 28rpx;
103
+ color: rgba(0, 0, 0, 0.4);
104
+ line-height: 34px;
105
+ }
106
+
107
+ .addressInfo {
108
+ display: flex;
109
+ font-size: 28rpx;
110
+ }
111
+
112
+ .address {
113
+ flex: 1;
114
+ width: 380rpx;
115
+ font-size: 28rpx;
116
+ color: #000000;
117
+ line-height: 40rpx;
118
+ }
119
+
120
+ .address-icon {
121
+ width: 48rpx;
122
+ height: 48rpx;
123
+ image-rendering: -webkit-optimize-contrast; /* 优化图片渲染 */
124
+ image-rendering: pixelated; /* 像素化渲染 */
125
+ transform: translateZ(0); /* 开启GPU加速 */
126
+ }
127
+ }
128
+ </style>
File without changes