af-mobile-client-vue3 1.3.91 → 1.3.92
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.
package/package.json
CHANGED
|
@@ -0,0 +1,319 @@
|
|
|
1
|
+
<script setup lang="ts">
|
|
2
|
+
import { post } from '@af-mobile-client-vue3/services/restTools'
|
|
3
|
+
import useUserStore from '@af-mobile-client-vue3/stores/modules/user'
|
|
4
|
+
import { mobileUtil } from '@af-mobile-client-vue3/utils/mobileUtil'
|
|
5
|
+
import { Badge as VanBadge, Icon as VanIcon } from 'vant'
|
|
6
|
+
import { onMounted, onUnmounted, ref } from 'vue'
|
|
7
|
+
import { closeWebSocket, initWebSocket } from './webSocket'
|
|
8
|
+
import 'vant/es/badge/style'
|
|
9
|
+
import 'vant/es/icon/style'
|
|
10
|
+
|
|
11
|
+
const userInfo = useUserStore().getUserInfo()
|
|
12
|
+
|
|
13
|
+
// 未读消息数量
|
|
14
|
+
const unreadCount = ref(0)
|
|
15
|
+
|
|
16
|
+
// 打开消息下拉菜单
|
|
17
|
+
const isShowMessageDropdown = ref(false)
|
|
18
|
+
|
|
19
|
+
// 消息列表数据
|
|
20
|
+
const messages = ref<any[]>([])
|
|
21
|
+
|
|
22
|
+
// 组件根元素的引用
|
|
23
|
+
const messageNotificationRef = ref<HTMLElement | null>(null)
|
|
24
|
+
|
|
25
|
+
// 获取消息数据
|
|
26
|
+
async function fetchMessages() {
|
|
27
|
+
const param = {
|
|
28
|
+
userId: `${userInfo.id}:phone`, // |phone
|
|
29
|
+
typeList: '\'phone\'', // phone
|
|
30
|
+
pageNo: 1,
|
|
31
|
+
pageSize: 100,
|
|
32
|
+
}
|
|
33
|
+
const res = await post('/af-system/logic/getNotificationListByType', param)
|
|
34
|
+
messages.value = (res || []).map((item: any) => {
|
|
35
|
+
const event: any = JSON.parse(item.f_event || '{}')
|
|
36
|
+
return {
|
|
37
|
+
id: item.id,
|
|
38
|
+
type: event.type,
|
|
39
|
+
time: item.f_input_date,
|
|
40
|
+
title: event.title || '',
|
|
41
|
+
status: item.f_state,
|
|
42
|
+
content: event.description || '',
|
|
43
|
+
}
|
|
44
|
+
})
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
// 获取未读消息数量
|
|
48
|
+
async function fetchMessagesCount() {
|
|
49
|
+
const param = {
|
|
50
|
+
userId: `${userInfo.id}:phone`, // |phone
|
|
51
|
+
typeList: '\'phone\'', // phone
|
|
52
|
+
}
|
|
53
|
+
const count = await post('/af-system/logic/getNotificationCount', param)
|
|
54
|
+
unreadCount.value = count.count
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
// 处理 WebSocket 消息
|
|
58
|
+
function createMessageCallback(message: any) {
|
|
59
|
+
fetchMessagesCount()
|
|
60
|
+
fetchMessages()
|
|
61
|
+
}
|
|
62
|
+
// 处理 不同的业务
|
|
63
|
+
function sendMessageCallback(message: any) {
|
|
64
|
+
console.log('>>>> 处理业务', JSON.stringify(message))
|
|
65
|
+
if (message.businessType === 'audio') {
|
|
66
|
+
// 播放响铃, 响铃文件为 message.audioName
|
|
67
|
+
mobileUtil.execute({
|
|
68
|
+
funcName: 'playAudio',
|
|
69
|
+
param: {
|
|
70
|
+
fileName: message.audioName,
|
|
71
|
+
},
|
|
72
|
+
callbackFunc: (result: any) => {
|
|
73
|
+
// {"status":"success","data":{"message":"音频播放成功","fileName":"anjian.mp3","path":"assets/audio/anjian.mp3"}}
|
|
74
|
+
},
|
|
75
|
+
})
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
// 全部标记为已读(清空消息列表)
|
|
80
|
+
function markAllAsRead() {
|
|
81
|
+
if (messages.value.length === 0)
|
|
82
|
+
return
|
|
83
|
+
|
|
84
|
+
const messageIds = messages.value.map(msg => msg.id).join(',')
|
|
85
|
+
markAsRead(messageIds)
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
// 单条消息标记为已读
|
|
89
|
+
function markAsRead(id: string | number) {
|
|
90
|
+
post('/af-system/logic/confirmMessage', {
|
|
91
|
+
id,
|
|
92
|
+
f_state: 2,
|
|
93
|
+
}).then(() => {
|
|
94
|
+
fetchMessages()
|
|
95
|
+
fetchMessagesCount()
|
|
96
|
+
})
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
function handleIconClick(message: any) {
|
|
100
|
+
// 乐观更新为已读状态,使图标立刻变绿
|
|
101
|
+
message.status = 2
|
|
102
|
+
setTimeout(() => {
|
|
103
|
+
markAsRead(message.id)
|
|
104
|
+
}, 200)
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
function showMessageDropdown() {
|
|
108
|
+
isShowMessageDropdown.value = !isShowMessageDropdown.value
|
|
109
|
+
if (isShowMessageDropdown.value) {
|
|
110
|
+
fetchMessages()
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
// 处理全局点击事件
|
|
115
|
+
function handleDocumentClick(event: MouseEvent) {
|
|
116
|
+
if (messageNotificationRef.value && !messageNotificationRef.value.contains(event.target as Node)) {
|
|
117
|
+
isShowMessageDropdown.value = false
|
|
118
|
+
}
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
onMounted(() => {
|
|
122
|
+
fetchMessages()
|
|
123
|
+
fetchMessagesCount()
|
|
124
|
+
// 初始化 WebSocket 连接
|
|
125
|
+
initWebSocket(userInfo.id, sendMessageCallback, createMessageCallback)
|
|
126
|
+
// 添加全局点击事件监听器
|
|
127
|
+
document.addEventListener('click', handleDocumentClick)
|
|
128
|
+
})
|
|
129
|
+
|
|
130
|
+
onUnmounted(() => {
|
|
131
|
+
closeWebSocket()
|
|
132
|
+
// 移除全局点击事件监听器
|
|
133
|
+
document.removeEventListener('click', handleDocumentClick)
|
|
134
|
+
})
|
|
135
|
+
</script>
|
|
136
|
+
|
|
137
|
+
<template>
|
|
138
|
+
<div ref="messageNotificationRef" class="message_icon" @click="showMessageDropdown">
|
|
139
|
+
<VanBadge v-if="unreadCount > 0" :content="unreadCount" max="99">
|
|
140
|
+
<VanIcon name="bell" />
|
|
141
|
+
</VanBadge>
|
|
142
|
+
<VanIcon v-else name="bell" />
|
|
143
|
+
</div>
|
|
144
|
+
|
|
145
|
+
<div v-if="isShowMessageDropdown" class="message_overlay" @click="isShowMessageDropdown = false" />
|
|
146
|
+
|
|
147
|
+
<div v-show="isShowMessageDropdown" class="message_dropdown" @click.stop>
|
|
148
|
+
<div class="message_header">
|
|
149
|
+
<span class="label">消息通知</span>
|
|
150
|
+
<span class="action" @click="markAllAsRead">全部已读</span>
|
|
151
|
+
</div>
|
|
152
|
+
<div class="message_list">
|
|
153
|
+
<template v-if="messages.length > 0">
|
|
154
|
+
<div
|
|
155
|
+
v-for="message in messages"
|
|
156
|
+
:key="message.id"
|
|
157
|
+
class="message_item"
|
|
158
|
+
:class="{ info: message.type === 'info', warning: message.type === 'warning' }"
|
|
159
|
+
>
|
|
160
|
+
<!-- 第一行:div1 + div2 -->
|
|
161
|
+
<div class="message_row">
|
|
162
|
+
<!-- div1:标题+时间 -->
|
|
163
|
+
<div class="message_left">
|
|
164
|
+
<p class="message_title">
|
|
165
|
+
{{ message.title }}
|
|
166
|
+
</p>
|
|
167
|
+
<p class="message_time">
|
|
168
|
+
{{ message.time }}
|
|
169
|
+
</p>
|
|
170
|
+
</div>
|
|
171
|
+
<!-- div2:图标 -->
|
|
172
|
+
<div class="message_right">
|
|
173
|
+
<VanIcon
|
|
174
|
+
name="checked"
|
|
175
|
+
:color="message.status === 2 ? '#52c41a' : '#999'"
|
|
176
|
+
size="28"
|
|
177
|
+
@click.stop="handleIconClick(message)"
|
|
178
|
+
/>
|
|
179
|
+
</div>
|
|
180
|
+
</div>
|
|
181
|
+
<!-- 第二行:div3 内容 -->
|
|
182
|
+
<div class="message_content">
|
|
183
|
+
<p class="message_text">
|
|
184
|
+
{{ message.content }}
|
|
185
|
+
</p>
|
|
186
|
+
</div>
|
|
187
|
+
</div>
|
|
188
|
+
</template>
|
|
189
|
+
<div v-else class="empty_message">
|
|
190
|
+
暂无未读消息
|
|
191
|
+
</div>
|
|
192
|
+
</div>
|
|
193
|
+
</div>
|
|
194
|
+
</template>
|
|
195
|
+
|
|
196
|
+
<style scoped lang="less">
|
|
197
|
+
.message_dropdown {
|
|
198
|
+
position: absolute;
|
|
199
|
+
top: 56px;
|
|
200
|
+
left: 0;
|
|
201
|
+
right: 0;
|
|
202
|
+
background-color: #fff;
|
|
203
|
+
box-shadow: 0 12px 24px rgba(0, 0, 0, 0.2);
|
|
204
|
+
z-index: 60;
|
|
205
|
+
max-height: 400px;
|
|
206
|
+
overflow-y: auto;
|
|
207
|
+
|
|
208
|
+
.message_header {
|
|
209
|
+
display: flex;
|
|
210
|
+
justify-content: space-between;
|
|
211
|
+
align-items: center;
|
|
212
|
+
padding: 12px 16px;
|
|
213
|
+
border-bottom: 1px solid #eee;
|
|
214
|
+
|
|
215
|
+
.label {
|
|
216
|
+
font-size: 14px;
|
|
217
|
+
color: #999;
|
|
218
|
+
}
|
|
219
|
+
.action {
|
|
220
|
+
font-size: 14px;
|
|
221
|
+
color: #1989fa;
|
|
222
|
+
cursor: pointer;
|
|
223
|
+
}
|
|
224
|
+
}
|
|
225
|
+
|
|
226
|
+
.message_list {
|
|
227
|
+
.message_item {
|
|
228
|
+
padding: 12px 16px;
|
|
229
|
+
border-bottom: 1px solid #f5f5f5;
|
|
230
|
+
|
|
231
|
+
&.info {
|
|
232
|
+
background-color: #eff6ff;
|
|
233
|
+
}
|
|
234
|
+
&.warning {
|
|
235
|
+
background-color: #fff7ed;
|
|
236
|
+
}
|
|
237
|
+
|
|
238
|
+
.message_row {
|
|
239
|
+
display: flex;
|
|
240
|
+
justify-content: space-between;
|
|
241
|
+
align-items: flex-start;
|
|
242
|
+
}
|
|
243
|
+
|
|
244
|
+
.message_left {
|
|
245
|
+
flex: 1;
|
|
246
|
+
min-width: 0;
|
|
247
|
+
|
|
248
|
+
.message_title {
|
|
249
|
+
font-size: 14px;
|
|
250
|
+
font-weight: 500;
|
|
251
|
+
color: #333;
|
|
252
|
+
margin: 0;
|
|
253
|
+
white-space: nowrap;
|
|
254
|
+
overflow: hidden;
|
|
255
|
+
text-overflow: ellipsis;
|
|
256
|
+
}
|
|
257
|
+
|
|
258
|
+
.message_time {
|
|
259
|
+
font-size: 12px;
|
|
260
|
+
color: #999;
|
|
261
|
+
margin: 4px 0 0 0;
|
|
262
|
+
}
|
|
263
|
+
}
|
|
264
|
+
|
|
265
|
+
.message_right {
|
|
266
|
+
flex: 0 0 auto;
|
|
267
|
+
display: flex;
|
|
268
|
+
align-items: center;
|
|
269
|
+
padding-left: 8px;
|
|
270
|
+
|
|
271
|
+
.van-icon {
|
|
272
|
+
font-size: 18px;
|
|
273
|
+
color: #999;
|
|
274
|
+
}
|
|
275
|
+
}
|
|
276
|
+
|
|
277
|
+
.message_content {
|
|
278
|
+
margin-top: 8px;
|
|
279
|
+
|
|
280
|
+
.message_text {
|
|
281
|
+
border-radius: 4px;
|
|
282
|
+
font-size: 13px;
|
|
283
|
+
color: #666;
|
|
284
|
+
background-color: #fafafc;
|
|
285
|
+
margin: 0;
|
|
286
|
+
padding: 8px 12px;
|
|
287
|
+
line-height: 1.4;
|
|
288
|
+
}
|
|
289
|
+
}
|
|
290
|
+
}
|
|
291
|
+
|
|
292
|
+
.empty_message {
|
|
293
|
+
padding: 60px 0;
|
|
294
|
+
text-align: center;
|
|
295
|
+
color: #999;
|
|
296
|
+
font-size: 14px;
|
|
297
|
+
}
|
|
298
|
+
}
|
|
299
|
+
}
|
|
300
|
+
|
|
301
|
+
.message_overlay {
|
|
302
|
+
position: fixed;
|
|
303
|
+
inset: 0;
|
|
304
|
+
background: rgba(0, 0, 0, 0.45);
|
|
305
|
+
z-index: 50;
|
|
306
|
+
margin-top: 56px;
|
|
307
|
+
margin-bottom: 50px;
|
|
308
|
+
}
|
|
309
|
+
.message_icon {
|
|
310
|
+
padding: 8px;
|
|
311
|
+
position: relative;
|
|
312
|
+
cursor: pointer;
|
|
313
|
+
|
|
314
|
+
.van-icon {
|
|
315
|
+
font-size: 20px;
|
|
316
|
+
color: #666;
|
|
317
|
+
}
|
|
318
|
+
}
|
|
319
|
+
</style>
|
|
@@ -0,0 +1,112 @@
|
|
|
1
|
+
let heartCheckTimer: number | null = null
|
|
2
|
+
let reconnectTimer: number | null = null
|
|
3
|
+
let websocket: WebSocket | null = null
|
|
4
|
+
|
|
5
|
+
let notifyId = ''
|
|
6
|
+
let sendMessageCallback: ((message: any) => void) | null = null
|
|
7
|
+
let createMessageCallback: ((message: any) => void) | null = null
|
|
8
|
+
|
|
9
|
+
function reloadInitWebSocket() {
|
|
10
|
+
initWebSocket(notifyId, sendMessageCallback, createMessageCallback)
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
export function initWebSocket(notify: string | null = null, sendCallback: (message: any) => void, createCallback: (message: any) => void) {
|
|
14
|
+
if (notify) {
|
|
15
|
+
notifyId = notify
|
|
16
|
+
}
|
|
17
|
+
if (sendCallback) {
|
|
18
|
+
sendMessageCallback = sendCallback
|
|
19
|
+
}
|
|
20
|
+
if (createCallback) {
|
|
21
|
+
createMessageCallback = createCallback
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
// 已有连接则不重复连接(包括正在连接或已连接的状态)
|
|
25
|
+
if (websocket && (websocket.readyState === WebSocket.OPEN || websocket.readyState === WebSocket.CONNECTING)) {
|
|
26
|
+
console.log('>>>> webSocket 连接 已存在')
|
|
27
|
+
return
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
// 初始化 WebSocket
|
|
31
|
+
websocket = new WebSocket(`ws:${window.location.host}/socket/af-system/sendMessage?userId=${notifyId}:phone`)
|
|
32
|
+
|
|
33
|
+
// WebSocket 打开连接时触发
|
|
34
|
+
websocket.onopen = () => {
|
|
35
|
+
startHeartCheck()
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
// WebSocket 连接发生错误时触发
|
|
39
|
+
websocket.onerror = () => {
|
|
40
|
+
reconnect()
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
// WebSocket 接收到消息时触发
|
|
44
|
+
websocket.onmessage = (event: MessageEvent) => {
|
|
45
|
+
try {
|
|
46
|
+
if (event.data === 'phone_ping')
|
|
47
|
+
return
|
|
48
|
+
const message = JSON.parse(event.data)
|
|
49
|
+
if (message && message.sendMessage === true) {
|
|
50
|
+
// 接收消息 处理自己的业务, 不再 提示列表中展示 (后端直接调用system-sendMessage)
|
|
51
|
+
sendMessageCallback?.(message)
|
|
52
|
+
}
|
|
53
|
+
else {
|
|
54
|
+
// 消息数据 处理 更新消息列表展示
|
|
55
|
+
createMessageCallback?.(message)
|
|
56
|
+
sendMessageCallback?.(message)
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
catch (e) {
|
|
60
|
+
console.error('WebSocket message parsing error:', e)
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
// WebSocket 连接关闭时触发
|
|
65
|
+
websocket.onclose = () => {
|
|
66
|
+
stopHeartCheck()
|
|
67
|
+
reconnect()
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
// 停止心跳检测
|
|
72
|
+
function stopHeartCheck() {
|
|
73
|
+
if (heartCheckTimer !== null) {
|
|
74
|
+
clearInterval(heartCheckTimer)
|
|
75
|
+
heartCheckTimer = null
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
// 心跳机制
|
|
80
|
+
function startHeartCheck() {
|
|
81
|
+
stopHeartCheck()
|
|
82
|
+
heartCheckTimer = window.setInterval(() => {
|
|
83
|
+
if (websocket && websocket.readyState === WebSocket.OPEN) {
|
|
84
|
+
websocket.send(JSON.stringify({ event: 'phone_ping', userList: [`${notifyId}:phone`] }))
|
|
85
|
+
}
|
|
86
|
+
}, 30000)
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
function reconnect() {
|
|
90
|
+
// 防止频繁重连
|
|
91
|
+
if (reconnectTimer !== null) {
|
|
92
|
+
return
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
reconnectTimer = window.setTimeout(() => {
|
|
96
|
+
reloadInitWebSocket() // 重新初始化 WebSocket
|
|
97
|
+
reconnectTimer = null
|
|
98
|
+
}, 5000) // 5秒尝试重连
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
// 关闭 WebSocket 连接
|
|
102
|
+
export function closeWebSocket() {
|
|
103
|
+
if (websocket) {
|
|
104
|
+
websocket.close()
|
|
105
|
+
websocket = null
|
|
106
|
+
}
|
|
107
|
+
stopHeartCheck()
|
|
108
|
+
if (reconnectTimer !== null) {
|
|
109
|
+
clearTimeout(reconnectTimer)
|
|
110
|
+
reconnectTimer = null
|
|
111
|
+
}
|
|
112
|
+
}
|
|
@@ -9,27 +9,87 @@ const emit = defineEmits(['deleteRow'])
|
|
|
9
9
|
// 访问路由
|
|
10
10
|
const router = useRouter()
|
|
11
11
|
// 获取默认值
|
|
12
|
-
const idKey = ref('o_id')
|
|
12
|
+
// const idKey = ref('o_id')
|
|
13
13
|
|
|
14
14
|
// 简易crud表单测试
|
|
15
15
|
const configName = ref('ceshiCRUD')
|
|
16
|
-
const serviceName = ref('af-
|
|
16
|
+
const serviceName = ref('af-safecheck')
|
|
17
17
|
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
18
|
+
// 资源权限测试
|
|
19
|
+
// const configName = ref('crud_sources_test')
|
|
20
|
+
// const serviceName = ref('af-system')
|
|
21
21
|
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
22
|
+
// 实际业务测试
|
|
23
|
+
// const configName = ref('lngChargeAuditMobileCRUD')
|
|
24
|
+
// const serviceName = ref('af-gaslink')
|
|
25
25
|
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
26
|
+
// 跳转到详情页面
|
|
27
|
+
// function toDetail(item) {
|
|
28
|
+
// router.push({
|
|
29
|
+
// name: 'XCellDetailView',
|
|
30
|
+
// params: { id: item[idKey.value] }, // 如果使用命名路由,推荐使用路由参数而不是直接构建 URL
|
|
31
|
+
// query: {
|
|
32
|
+
// operName: item[operNameKey.value],
|
|
33
|
+
// method:item[methodKey.value],
|
|
34
|
+
// requestMethod:item[requestMethodKey.value],
|
|
35
|
+
// operatorType:item[operatorTypeKey.value],
|
|
36
|
+
// operUrl:item[operUrlKey.value],
|
|
37
|
+
// operIp:item[operIpKey.value],
|
|
38
|
+
// costTime:item[costTimeKey.value],
|
|
39
|
+
// operTime:item[operTimeKey.value],
|
|
40
|
+
//
|
|
41
|
+
// title: item[titleKey.value],
|
|
42
|
+
// businessType: item[businessTypeKey.value],
|
|
43
|
+
// status:item[statusKey.value]
|
|
44
|
+
// }
|
|
45
|
+
// })
|
|
46
|
+
// }
|
|
29
47
|
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
48
|
+
// 跳转到表单——以表单组来渲染纯表单
|
|
49
|
+
// function toDetail(item) {
|
|
50
|
+
// router.push({
|
|
51
|
+
// name: 'XFormGroupView',
|
|
52
|
+
// query: {
|
|
53
|
+
// id: item[idKey.value],
|
|
54
|
+
// // id: item.rr_id,
|
|
55
|
+
// // o_id: item.o_id,
|
|
56
|
+
// },
|
|
57
|
+
// })
|
|
58
|
+
// }
|
|
59
|
+
|
|
60
|
+
// 新增功能
|
|
61
|
+
// function addOption(totalCount) {
|
|
62
|
+
// router.push({
|
|
63
|
+
// name: 'XFormView',
|
|
64
|
+
// params: { id: totalCount, openid: totalCount },
|
|
65
|
+
// query: {
|
|
66
|
+
// configName: configName.value,
|
|
67
|
+
// serviceName: serviceName.value,
|
|
68
|
+
// mode: '新增',
|
|
69
|
+
// },
|
|
70
|
+
// })
|
|
71
|
+
// }
|
|
72
|
+
|
|
73
|
+
// 修改功能
|
|
74
|
+
// function updateRow(result) {
|
|
75
|
+
// router.push({
|
|
76
|
+
// name: 'XFormView',
|
|
77
|
+
// params: { id: result.o_id, openid: result.o_id },
|
|
78
|
+
// query: {
|
|
79
|
+
// configName: configName.value,
|
|
80
|
+
// serviceName: serviceName.value,
|
|
81
|
+
// mode: '修改',
|
|
82
|
+
// },
|
|
83
|
+
// })
|
|
84
|
+
// }
|
|
85
|
+
|
|
86
|
+
// 删除功能
|
|
87
|
+
// function deleteRow(result) {
|
|
88
|
+
// emit('deleteRow', result.o_id)
|
|
89
|
+
// }
|
|
90
|
+
// const fixQueryForm = ref({
|
|
91
|
+
// f_operator_id: '487184754014158848',
|
|
92
|
+
// })
|
|
33
93
|
</script>
|
|
34
94
|
|
|
35
95
|
<template>
|
|
@@ -38,10 +98,6 @@ function toDetail(row) {
|
|
|
38
98
|
<XCellList
|
|
39
99
|
:config-name="configName"
|
|
40
100
|
:service-name="serviceName"
|
|
41
|
-
@add="add"
|
|
42
|
-
@add-o="addO"
|
|
43
|
-
@aaa="aaa"
|
|
44
|
-
@toDetail="toDetail"
|
|
45
101
|
/>
|
|
46
102
|
</template>
|
|
47
103
|
</NormalDataLayout>
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
<script setup lang="ts">
|
|
2
2
|
import type { PhoneLocationStatus } from '@af-mobile-client-vue3/components/data/XOlMap/types'
|
|
3
|
+
import MessageNotification from '@af-mobile-client-vue3/components/core/MessageNotification/MessageNotification.vue'
|
|
3
4
|
import useSettingStore from '@af-mobile-client-vue3/stores/modules/setting'
|
|
4
5
|
import useUserStore from '@af-mobile-client-vue3/stores/modules/user'
|
|
5
6
|
import { mobileUtil } from '@af-mobile-client-vue3/utils/mobileUtil'
|
|
@@ -165,6 +166,9 @@ const webMobileConfig = useSettingStore().getSetting()
|
|
|
165
166
|
<!-- <div class="setting_section"> -->
|
|
166
167
|
<!-- <van-icon name="setting-o" class="setting-icon" /> -->
|
|
167
168
|
<!-- </div> -->
|
|
169
|
+
<div class="action_section">
|
|
170
|
+
<MessageNotification />
|
|
171
|
+
</div>
|
|
168
172
|
</div>
|
|
169
173
|
</nav>
|
|
170
174
|
</VanSticky>
|
|
@@ -481,5 +485,9 @@ const webMobileConfig = useSettingStore().getSetting()
|
|
|
481
485
|
}
|
|
482
486
|
}
|
|
483
487
|
}
|
|
488
|
+
.action_section {
|
|
489
|
+
display: flex;
|
|
490
|
+
align-items: center;
|
|
491
|
+
}
|
|
484
492
|
}
|
|
485
493
|
</style>
|