@uxda/appkit 1.2.36 → 1.2.38

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.
@@ -0,0 +1,290 @@
1
+ <template>
2
+ <div class="notice-banner">
3
+ <DdNoticeBar
4
+ :class="{ show: key === activeKey }"
5
+ v-for="(item, key) in bannerMessages"
6
+ :key="key"
7
+ :showClose="item.noticeType === 0"
8
+ @close="onClose(item, key)"
9
+ >
10
+ <img
11
+ class="notice-banner-icon"
12
+ src="https://cdn.ddjf.com/static/images/customer-center/notice-icon.png"
13
+ alt=""
14
+ />
15
+ <div class="notice-banner-text">
16
+ {{ item.context }}
17
+ </div>
18
+ <div class="notice-banner-btn" @click="onDetail">详情</div>
19
+ </DdNoticeBar>
20
+ </div>
21
+
22
+ <!-- 系统公告强制弹框 -->
23
+ <template v-for="(item, key) in popMessages" :key="key">
24
+ <NoticePopup :message="item" @close="popMessages.splice(key, 1)" />
25
+ </template>
26
+ </template>
27
+
28
+ <script lang="ts" setup>
29
+ import { onMounted, ref } from 'vue'
30
+ import { useHttp } from '../api'
31
+ import { useAppKitOptions } from '../../Appkit'
32
+ import DdNoticeBar from '../../components/dd-notice-bar/index.vue'
33
+ import NoticePopup from './NoticePopup.vue'
34
+ import Taro from '@tarojs/taro'
35
+ import { useNotice } from './useNotice'
36
+
37
+ const props = withDefaults(
38
+ defineProps<{
39
+ app: string
40
+ }>(),
41
+ {
42
+ app: '',
43
+ }
44
+ )
45
+
46
+ const { toReadFun, noticeClick } = useNotice()
47
+ const bannerMessages = ref<any[]>([]) // 横幅消息
48
+ const popMessages = ref<any[]>([]) // 弹窗消息
49
+ const activeKey = ref(0)
50
+
51
+ onMounted(() => {
52
+ queryNoticeMsg()
53
+ })
54
+
55
+ // 查询当前用户当前应用系统消息
56
+ async function queryNoticeMsg() {
57
+ const appkitOptions = useAppKitOptions()
58
+
59
+ const $http = useHttp()
60
+ $http
61
+ .post('/cas/msg/queryNoticeMsg', {
62
+ device: 'MINI',
63
+ deviceType: 2,
64
+ msgType: 3,
65
+ appCode: props.app || appkitOptions.app(),
66
+ tenantId: appkitOptions.tenant(),
67
+ })
68
+ .then((result) => {
69
+ // const result = [
70
+ // {
71
+ // id: 92989,
72
+ // appCode: 'loankit',
73
+ // sendType: 11,
74
+ // isRead: 1,
75
+ // receiveTime: 1718189848000,
76
+ // textId: 173545,
77
+ // title: '测试消息',
78
+ // context:
79
+ // '尊敬的客户,为给您提供更加丰富和优质的金融产品及服为给您提供更加丰富和优质的金融产品及服',
80
+ // businessId: '123123',
81
+ // link: 'www.baidu.com',
82
+ // miniLink: 'www.baidu.com',
83
+ // appLink: '',
84
+ // source: '测试',
85
+ // msgType: 3,
86
+ // userName: 'gao',
87
+ // deviceType: 0,
88
+ // customerName: '',
89
+ // userId: '1580078112058789890',
90
+ // sendTenant: '',
91
+ // receiveTenant: '',
92
+ // popDevice: '',
93
+ // isPop: 1,
94
+ // expiryTime: '2025-06-09 14:35:28',
95
+ // noticeType: 0,
96
+ // noticeStatus: '0',
97
+ // },
98
+ // {
99
+ // id: 92989,
100
+ // appCode: 'loankit',
101
+ // sendType: 11,
102
+ // isRead: 1,
103
+ // receiveTime: 1718189848000,
104
+ // textId: 173545,
105
+ // title: '测试消息',
106
+ // context: '你好呀,我111',
107
+ // businessId: '123123',
108
+ // link: 'www.baidu.com',
109
+ // miniLink: 'www.baidu.com',
110
+ // appLink: '',
111
+ // source: '测试',
112
+ // msgType: 3,
113
+ // userName: 'gao',
114
+ // deviceType: 0,
115
+ // customerName: '',
116
+ // userId: '1580078112058789890',
117
+ // sendTenant: '',
118
+ // receiveTenant: '',
119
+ // popDevice: '',
120
+ // isPop: 1,
121
+ // expiryTime: '2025-06-09 14:35:28',
122
+ // noticeType: 0,
123
+ // noticeStatus: '0',
124
+ // },
125
+ // {
126
+ // id: 92989,
127
+ // appCode: 'loankit',
128
+ // sendType: 11,
129
+ // isRead: 1,
130
+ // receiveTime: 1718189848000,
131
+ // textId: 173545,
132
+ // title: '测试消息',
133
+ // context: '你好呀,我222',
134
+ // businessId: '123123',
135
+ // link: 'www.baidu.com',
136
+ // miniLink: 'www.baidu.com',
137
+ // appLink: '',
138
+ // source: '测试',
139
+ // msgType: 3,
140
+ // userName: 'gao',
141
+ // deviceType: 0,
142
+ // customerName: '',
143
+ // userId: '1580078112058789890',
144
+ // sendTenant: '',
145
+ // receiveTenant: '',
146
+ // popDevice: '',
147
+ // isPop: 1,
148
+ // expiryTime: '2025-06-09 14:35:28',
149
+ // noticeType: 0,
150
+ // noticeStatus: '0',
151
+ // },
152
+ // {
153
+ // id: 92989,
154
+ // appCode: 'loankit',
155
+ // sendType: 11,
156
+ // isRead: 1,
157
+ // receiveTime: 1718189848000,
158
+ // textId: 173545,
159
+ // title: '测试消息',
160
+ // context: '你好呀,我333',
161
+ // businessId: '123123',
162
+ // link: 'www.baidu.com',
163
+ // miniLink: 'www.baidu.com',
164
+ // appLink: '',
165
+ // source: '测试',
166
+ // msgType: 3,
167
+ // userName: 'gao',
168
+ // deviceType: 0,
169
+ // customerName: '',
170
+ // userId: '1580078112058789890',
171
+ // sendTenant: '',
172
+ // receiveTenant: '',
173
+ // popDevice: '',
174
+ // isPop: 1,
175
+ // expiryTime: '2025-06-09 14:35:28',
176
+ // noticeType: 0,
177
+ // noticeStatus: '0',
178
+ // },
179
+ // ]
180
+ bannerMessages.value = (result || []).filter((item: any) => item.noticeType !== undefined)
181
+ popMessages.value = (result || []).filter((item: any) => item.isPop)
182
+ startMessage()
183
+ })
184
+ }
185
+
186
+ let interval: any = null
187
+ // 启动消息轮播
188
+ function startMessage() {
189
+ clearInterval(interval)
190
+ if (bannerMessages.value.length > 1) {
191
+ interval = setInterval(() => {
192
+ startMessageCalc()
193
+ if (bannerMessages.value.length <= 1) {
194
+ clearInterval(interval)
195
+ }
196
+ }, 3000)
197
+ }
198
+ }
199
+ function startMessageCalc() {
200
+ if (activeKey.value < bannerMessages.value.length - 1) {
201
+ activeKey.value++
202
+ } else {
203
+ activeKey.value = 0
204
+ }
205
+ }
206
+
207
+ // 关闭横幅
208
+ function onClose(item: any, index: number) {
209
+ const $http = useHttp()
210
+ $http
211
+ .post('/cas/msg/setMsgStatus', {
212
+ device: 'PC',
213
+ deviceType: 0,
214
+ noticeStatus: 1,
215
+ receiveId: item.id,
216
+ })
217
+ .then(() => {
218
+ Taro.showToast({
219
+ title: '消息已关闭',
220
+ icon: 'none',
221
+ })
222
+ bannerMessages.value.splice(index, 1)
223
+
224
+ startMessage()
225
+
226
+ if (item.isRead === 0) {
227
+ toReadFun([item.id])
228
+ }
229
+ })
230
+ }
231
+
232
+ // 跳转详情
233
+ function onDetail(item) {
234
+ noticeClick(item, (url) => {
235
+ emits('detail', url)
236
+ })
237
+ }
238
+
239
+ // 父组件事件
240
+ const emits = defineEmits(['detail', 'close'])
241
+ </script>
242
+
243
+ <style lang="scss">
244
+ .notice-banner {
245
+ height: 30px;
246
+ margin-bottom: 8px;
247
+ .dd-notice-bar {
248
+ position: relative;
249
+ background: #f2f3ff;
250
+ font-size: 10px;
251
+ color: #000000e5;
252
+ padding: 0 8px;
253
+ height: 0;
254
+ min-height: auto;
255
+ transition: all 0.2s;
256
+ opacity: 0;
257
+ &.show {
258
+ height: 30px;
259
+ opacity: 1;
260
+ }
261
+ }
262
+ &-icon {
263
+ width: 22px;
264
+ height: 22px;
265
+ margin-right: 8px;
266
+ }
267
+ .dd-notice-bar__close-img {
268
+ display: none;
269
+ }
270
+ .dd-notice-bar__close {
271
+ background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='20' height='20' viewBox='0 0 20 20' fill='none'%3E %3Cpath d='M3.3335 3.33331L16.6668 16.6666' stroke='%23353535' stroke-width='1.66667' stroke-linecap='round' stroke-linejoin='round'/%3E %3Cpath d='M3.3335 16.6666L16.6668 3.33331' stroke='%23353535' stroke-width='1.66667' stroke-linecap='round' stroke-linejoin='round'/%3E%3C/svg%3E");
272
+ background-position: center;
273
+ background-repeat: no-repeat;
274
+ background-size: 12px 12px;
275
+ opacity: 0.6;
276
+ }
277
+ &-text {
278
+ flex: 1;
279
+ overflow: hidden;
280
+ text-overflow: ellipsis;
281
+ display: -webkit-box;
282
+ -webkit-line-clamp: 1;
283
+ -webkit-box-orient: vertical;
284
+ }
285
+ &-btn {
286
+ color: #017fff;
287
+ padding-left: 6px;
288
+ }
289
+ }
290
+ </style>
@@ -0,0 +1,156 @@
1
+ <template>
2
+ <nut-popup
3
+ pop-class="notice-popup"
4
+ :close-on-click-overlay="false"
5
+ v-model:visible="showPopup"
6
+ round
7
+ >
8
+ <div class="notice-popup-hd">
9
+ <img
10
+ class="notice-popup-hd-icon"
11
+ src="https://cdn.ddjf.com/static/images/customer-center/system-notice-1.png"
12
+ alt=""
13
+ />系统公告
14
+ </div>
15
+ <div class="notice-popup-bd">
16
+ {{ message.context }}
17
+ <div class="notice-popup-bd-link" @click="toAllSystemNotice">点击查看附件</div>
18
+ </div>
19
+ <div class="notice-popup-ft">
20
+ <div class="notice-popup-ft-btn" @click="onClose">我知道了</div>
21
+ </div>
22
+ </nut-popup>
23
+ </template>
24
+
25
+ <script lang="ts" setup>
26
+ import { onMounted, ref } from 'vue'
27
+ import { useHttp } from '../api'
28
+ import { useNotice } from './useNotice'
29
+
30
+ const props = withDefaults(
31
+ defineProps<{
32
+ message: any
33
+ }>(),
34
+ {
35
+ message: {},
36
+ }
37
+ )
38
+
39
+ const { toReadFun, noticeClick } = useNotice()
40
+ const showPopup = ref(true)
41
+
42
+ onMounted(() => {})
43
+
44
+ // 关闭
45
+ function onCancel() {
46
+ showPopup.value = false
47
+
48
+ emits('close')
49
+ }
50
+
51
+ // 查看全部系统公告
52
+ function toAllSystemNotice() {
53
+ noticeClick(props.message, () => {
54
+ onClose()
55
+
56
+ emits('view', props.message.id)
57
+ })
58
+ }
59
+
60
+ // 关闭弹框
61
+ async function onClose() {
62
+ const $http = useHttp()
63
+
64
+ $http
65
+ .post('/cas/msg/setMsgStatus', {
66
+ device: 'MINI',
67
+ receiveId: props.message.id,
68
+ })
69
+ .then(() => {
70
+ if (props.message.isRead === 0) {
71
+ toReadFun([props.message.id])
72
+ }
73
+ onCancel()
74
+ })
75
+ }
76
+
77
+ const emits = defineEmits(['close', 'view'])
78
+ </script>
79
+
80
+ <style lang="scss">
81
+ .notice-popup {
82
+ width: 280px;
83
+ padding: 20px 15px;
84
+ border-radius: 10px !important;
85
+ background: linear-gradient(136.72deg, #d0fdfe 6.02%, #a2b9ff 59.97%, #6593ff 108.78%);
86
+ &::after {
87
+ content: '';
88
+ position: absolute;
89
+ width: 100%;
90
+ height: 100%;
91
+ left: 0;
92
+ top: 0;
93
+ background: linear-gradient(360deg, #ffffff 4.73%, rgba(255, 255, 255, 0) 85.82%);
94
+ z-index: 1;
95
+ border-radius: 10px;
96
+ }
97
+ &::before {
98
+ content: '';
99
+ width: 236px;
100
+ height: 241px;
101
+ position: absolute;
102
+ top: 0;
103
+ right: 40px;
104
+ background: url('https://cdn.ddjf.com/static/images/customer-center/notice-modal-bg.png');
105
+ }
106
+
107
+ .nutui-popup__content-wrapper {
108
+ position: relative;
109
+ z-index: 2;
110
+ }
111
+
112
+ &-hd {
113
+ color: #0a2668;
114
+ font-size: 17px;
115
+ display: flex;
116
+ align-items: center;
117
+ margin-bottom: 20px;
118
+ &-icon {
119
+ width: 20px;
120
+ height: 20px;
121
+ margin-right: 4px;
122
+ }
123
+ }
124
+ &-bd {
125
+ color: #353535;
126
+ box-shadow: 0px 2px 8px 0px #ffffff33 inset, 0px 1px 1px 0px #ffffff80 inset,
127
+ 0px 0px 1px 0px #ffffffb2;
128
+ border-radius: 3px;
129
+ background: rgba(255, 255, 255, 0.6);
130
+ min-height: 160px;
131
+ margin-bottom: 20px;
132
+ padding: 15px 10px;
133
+ box-sizing: border-box;
134
+ font-size: 10px;
135
+ &-link {
136
+ color: #007fff;
137
+ margin-top: 2px;
138
+ }
139
+ }
140
+ &-ft {
141
+ display: flex;
142
+ align-items: center;
143
+ justify-content: center;
144
+ &-btn {
145
+ background: #007fff;
146
+ color: #fff;
147
+ width: 128px;
148
+ height: 30px;
149
+ display: flex;
150
+ align-items: center;
151
+ justify-content: center;
152
+ border-radius: 15px;
153
+ }
154
+ }
155
+ }
156
+ </style>
@@ -0,0 +1,134 @@
1
+ <template>
2
+ <div class="notice-view">
3
+ <dd-search
4
+ :bordered="false"
5
+ :focus="false"
6
+ :value="query.title"
7
+ placeholder="请输入客户姓名搜索"
8
+ @search="onSearch"
9
+ />
10
+
11
+ <div class="h-full box-border">
12
+ <div class="wrapper box-border" v-if="list.length">
13
+ <scroll-view
14
+ class="content box-border"
15
+ :scroll-y="true"
16
+ :refresher-enabled="true"
17
+ :refresherTriggered="isRefresh"
18
+ @refresherrefresh="onRefresh"
19
+ :lower-threshold="100"
20
+ @scrolltolower="runNext"
21
+ bindscroll=""
22
+ >
23
+ <div
24
+ class="card box-border"
25
+ :class="{ active: item.isRead != '1' }"
26
+ v-for="(item, index) in list"
27
+ :key="index"
28
+ @click="notifyRead(item, index)"
29
+ >
30
+ <div class="point"></div>
31
+ <template v-if="appCode === 'loankit'">
32
+ <div class="time">
33
+ {{ formatMinutes(item.receiveTime) }}
34
+ </div>
35
+ <div class="text" :class="{ gray: item.isRead == '1' }">
36
+ {{ item.context }}
37
+ </div>
38
+ </template>
39
+ <template v-else>
40
+ <div class="time">
41
+ {{ formatMinutes(item.receiveTime) }}
42
+ </div>
43
+ <div class="text tit" :class="{ gray: item.isRead == '1' }">
44
+ {{ item.title }}
45
+ </div>
46
+ <div class="text" :class="{ gray: item.isRead == '1' }">
47
+ <rich-text style="white-space: pre-wrap" :nodes="item.context"></rich-text>
48
+ </div>
49
+ </template>
50
+ </div>
51
+ <div v-if="isLast" class="cue-text" style="padding-bottom: 40px">没有更多了</div>
52
+ </scroll-view>
53
+ </div>
54
+ <div v-else class="no-data h-full">
55
+ <div class="w-238px h-157px mt-105px mb-19px">
56
+ <img
57
+ class="w-full h-full"
58
+ src="https://cdn.ddjf.com/static/images/loan-manage/no-data.png"
59
+ alt=""
60
+ />
61
+ </div>
62
+ <div class="text">暂无记录</div>
63
+ </div>
64
+ </div>
65
+ </div>
66
+ </template>
67
+
68
+ <script lang="ts" setup>
69
+ import { onMounted, ref } from 'vue'
70
+ import { useHttp } from '../api'
71
+ import { useAppKitOptions } from '../../Appkit'
72
+ import DdSearch from '../../components/dd-search/index.vue'
73
+
74
+ const props = withDefaults(
75
+ defineProps<{
76
+ app: string
77
+ }>(),
78
+ {
79
+ app: '',
80
+ }
81
+ )
82
+
83
+ // 父组件事件
84
+ const emits = defineEmits(['detail', 'close'])
85
+ </script>
86
+
87
+ <style lang="scss">
88
+ .notice-banner {
89
+ height: 30px;
90
+ margin-bottom: 8px;
91
+ .dd-notice-bar {
92
+ position: relative;
93
+ background: #f2f3ff;
94
+ font-size: 10px;
95
+ color: #000000e5;
96
+ padding: 0 8px;
97
+ height: 0;
98
+ min-height: auto;
99
+ transition: all 0.2s;
100
+ opacity: 0;
101
+ &.show {
102
+ height: 30px;
103
+ opacity: 1;
104
+ }
105
+ }
106
+ &-icon {
107
+ width: 22px;
108
+ height: 22px;
109
+ margin-right: 8px;
110
+ }
111
+ .dd-notice-bar__close-img {
112
+ display: none;
113
+ }
114
+ .dd-notice-bar__close {
115
+ background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='20' height='20' viewBox='0 0 20 20' fill='none'%3E %3Cpath d='M3.3335 3.33331L16.6668 16.6666' stroke='%23353535' stroke-width='1.66667' stroke-linecap='round' stroke-linejoin='round'/%3E %3Cpath d='M3.3335 16.6666L16.6668 3.33331' stroke='%23353535' stroke-width='1.66667' stroke-linecap='round' stroke-linejoin='round'/%3E%3C/svg%3E");
116
+ background-position: center;
117
+ background-repeat: no-repeat;
118
+ background-size: 12px 12px;
119
+ opacity: 0.6;
120
+ }
121
+ &-text {
122
+ flex: 1;
123
+ overflow: hidden;
124
+ text-overflow: ellipsis;
125
+ display: -webkit-box;
126
+ -webkit-line-clamp: 1;
127
+ -webkit-box-orient: vertical;
128
+ }
129
+ &-btn {
130
+ color: #017fff;
131
+ padding-left: 6px;
132
+ }
133
+ }
134
+ </style>
@@ -0,0 +1,4 @@
1
+ import NoticeBanner from './NoticeBanner.vue'
2
+ import LoginSetting from './LoginSetting.vue'
3
+
4
+ export { NoticeBanner, LoginSetting }
@@ -0,0 +1,35 @@
1
+ import { useHttp } from '../api'
2
+
3
+ export function useNotice() {
4
+ // 点击消息时
5
+ async function noticeClick(item: any, cb: Function) {
6
+ if (item.isRead === 0) {
7
+ await toReadFun([item.id ?? item.msgId])
8
+ }
9
+ if (item.link) {
10
+ cb && cb(item.link)
11
+ }
12
+ return true
13
+ }
14
+
15
+ // 请求-标记消息已读
16
+ async function toReadFun(msgIds: number[]) {
17
+ const $http = useHttp()
18
+
19
+ return new Promise<boolean>((resolve) => {
20
+ $http
21
+ .post('/cas/msg/read', msgIds)
22
+ .then(() => {
23
+ resolve(true)
24
+ })
25
+ .catch(() => {
26
+ resolve(false)
27
+ })
28
+ })
29
+ }
30
+
31
+ return {
32
+ noticeClick,
33
+ toReadFun,
34
+ }
35
+ }
@@ -0,0 +1 @@
1
+ export * from './components'