minitest2.0 0.0.7 → 0.0.8

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
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "minitest2.0",
3
- "version": "0.0.7",
3
+ "version": "0.0.8",
4
4
  "private": false,
5
5
  "type": "module",
6
6
  "repository": {
@@ -0,0 +1,44 @@
1
+ import { buildTamRequestPayload, tamRequest } from '@/api/tam'
2
+
3
+ export type RmbDashboardBody = {
4
+ /** 城银账户资金余额 */
5
+ availCredit?: string
6
+ /** 跨境人民币可用余额 */
7
+ cipsAvailBal?: string
8
+ /** 数字人民币可用余额 */
9
+ dcpTotalAmt?: string
10
+ /** 人行账户资金余额 */
11
+ settleAccAmt?: string
12
+ }
13
+
14
+ export type ForeignDashboardBody = {
15
+ eurDomesticAmt?: string
16
+ eurOverseasAmt?: string
17
+ hkdDomesticAmt?: string
18
+ hkdOverseasAmt?: string
19
+ jpyDomesticAmt?: string
20
+ jpyOverseasAmt?: string
21
+ usdDomesticAmt?: string
22
+ usdOverseasAmt?: string
23
+ }
24
+
25
+ const RMB_DASHBOARD_TRAN_CODE = '/TAM/0001/140000007'
26
+ const FOREIGN_DASHBOARD_TRAN_CODE = '/TAM/0001/140000008'
27
+
28
+ export function queryRmbDashboard() {
29
+ return tamRequest<Record<string, never>, RmbDashboardBody>(
30
+ buildTamRequestPayload({
31
+ tranCode: RMB_DASHBOARD_TRAN_CODE,
32
+ body: {},
33
+ }),
34
+ )
35
+ }
36
+
37
+ export function queryForeignDashboard() {
38
+ return tamRequest<Record<string, never>, ForeignDashboardBody>(
39
+ buildTamRequestPayload({
40
+ tranCode: FOREIGN_DASHBOARD_TRAN_CODE,
41
+ body: {},
42
+ }),
43
+ )
44
+ }
@@ -26,79 +26,79 @@ const router = createRouter({
26
26
  {
27
27
  path: '/rmb-position',
28
28
  name: 'RmbPosition',
29
- component: () => import('@/views/rmb-position/index.vue'),
29
+ component: () => import('@/views/rmb/position/index.vue'),
30
30
  meta: { requiresAuth: true, title: '本币预报信息查询' },
31
31
  },
32
32
  {
33
33
  path: '/rmb-position/new',
34
34
  name: 'RmbPositionCreate',
35
- component: () => import('@/views/rmb-position-create/index.vue'),
35
+ component: () => import('@/views/rmb/position/create/index.vue'),
36
36
  meta: { requiresAuth: true, title: '新增本币预报' },
37
37
  },
38
38
  {
39
39
  path: '/rmb-position/:predRefNo',
40
40
  name: 'RmbPositionDetail',
41
- component: () => import('@/views/rmb-position-detail/index.vue'),
41
+ component: () => import('@/views/rmb/position/detail/index.vue'),
42
42
  meta: { requiresAuth: true, title: '预报详情' },
43
43
  },
44
44
  {
45
45
  path: '/foreign-position',
46
46
  name: 'ForeignPosition',
47
- component: () => import('@/views/foreign-position/index.vue'),
47
+ component: () => import('@/views/foreign/position/index.vue'),
48
48
  meta: { requiresAuth: true, title: '外币预报信息查询' },
49
49
  },
50
50
  {
51
51
  path: '/foreign-position/new',
52
52
  name: 'ForeignPositionCreate',
53
- component: () => import('@/views/foreign-position-create/index.vue'),
53
+ component: () => import('@/views/foreign/position/create/index.vue'),
54
54
  meta: { requiresAuth: true, title: '新增外币预报' },
55
55
  },
56
56
  {
57
57
  path: '/foreign-position/:predRefNo',
58
58
  name: 'ForeignPositionDetail',
59
- component: () => import('@/views/foreign-position-detail/index.vue'),
59
+ component: () => import('@/views/foreign/position/detail/index.vue'),
60
60
  meta: { requiresAuth: true, title: '外币预报详情' },
61
61
  },
62
62
  {
63
63
  path: '/pbc-position',
64
64
  name: 'PbcPosition',
65
- component: () => import('@/views/pbc-position/index.vue'),
65
+ component: () => import('@/views/rmb/pbc-position/index.vue'),
66
66
  meta: { requiresAuth: true, title: '人行头寸余额查询' },
67
67
  },
68
68
  {
69
69
  path: '/position-estimate',
70
70
  name: 'PositionEstimate',
71
- component: () => import('@/views/position-estimate/index.vue'),
71
+ component: () => import('@/views/rmb/position-estimate/index.vue'),
72
72
  meta: { requiresAuth: true, title: '头寸匡算' },
73
73
  },
74
74
  {
75
75
  path: '/position-estimate/report',
76
76
  name: 'PositionEstimateReport',
77
- component: () => import('@/views/position-estimate-report/index.vue'),
77
+ component: () => import('@/views/rmb/position-estimate/report/index.vue'),
78
78
  meta: { requiresAuth: true, title: '头寸匡算报表' },
79
79
  },
80
80
  {
81
81
  path: '/position-estimate/opening-reserve',
82
82
  name: 'OpeningReserveEstimate',
83
- component: () => import('@/views/opening-reserve-estimate/index.vue'),
83
+ component: () => import('@/views/rmb/position-estimate/opening-reserve/index.vue'),
84
84
  meta: { requiresAuth: true, title: '日初备款数匡算' },
85
85
  },
86
86
  {
87
87
  path: '/net-debit',
88
88
  name: 'NetDebit',
89
- component: () => import('@/views/net-debit/index.vue'),
89
+ component: () => import('@/views/rmb/net-debit/index.vue'),
90
90
  meta: { requiresAuth: true, title: '人民币净借记可用额度管理' },
91
91
  },
92
92
  {
93
93
  path: '/clearing-detail',
94
94
  name: 'ClearingDetail',
95
- component: () => import('@/views/clearing-detail/index.vue'),
95
+ component: () => import('@/views/rmb/clearing-detail/index.vue'),
96
96
  meta: { requiresAuth: true, title: '人民币小额网银清算场次明细' },
97
97
  },
98
98
  {
99
99
  path: '/warning',
100
100
  name: 'Warning',
101
- component: () => import('@/views/warning/index.vue'),
101
+ component: () => import('@/views/rmb/warning/index.vue'),
102
102
  meta: { requiresAuth: true, title: '头寸管理平台' },
103
103
  },
104
104
  {
@@ -110,25 +110,25 @@ const router = createRouter({
110
110
  {
111
111
  path: '/articles',
112
112
  name: 'Articles',
113
- component: () => import('@/views/articles/index.vue'),
113
+ component: () => import('@/views/announcement/index.vue'),
114
114
  meta: { requiresAuth: true, showTabbar: true, title: '公告' },
115
115
  },
116
116
  {
117
117
  path: '/articles/new',
118
118
  name: 'ArticlePublish',
119
- component: () => import('@/views/article-edit/index.vue'),
119
+ component: () => import('@/views/announcement/edit/index.vue'),
120
120
  meta: { requiresAuth: true, title: '发布公告' },
121
121
  },
122
122
  {
123
123
  path: '/articles/:id',
124
124
  name: 'ArticleDetail',
125
- component: () => import('@/views/article-detail/index.vue'),
125
+ component: () => import('@/views/announcement/detail/index.vue'),
126
126
  meta: { requiresAuth: true, title: '公告详情' },
127
127
  },
128
128
  {
129
129
  path: '/articles/:id/edit',
130
130
  name: 'ArticleEdit',
131
- component: () => import('@/views/article-edit/index.vue'),
131
+ component: () => import('@/views/announcement/edit/index.vue'),
132
132
  meta: { requiresAuth: true, title: '编辑公告' },
133
133
  },
134
134
  {
@@ -140,7 +140,7 @@ const router = createRouter({
140
140
  {
141
141
  path: '/settings',
142
142
  name: 'Settings',
143
- component: () => import('@/views/settings/index.vue'),
143
+ component: () => import('@/views/mine/settings/index.vue'),
144
144
  meta: { requiresAuth: true, title: '设置' },
145
145
  },
146
146
  ],
@@ -1,4 +1,6 @@
1
1
  <script setup lang="ts">
2
+ import { queryForeignDashboard, queryRmbDashboard } from '@/api/dashboard'
3
+
2
4
  defineOptions({ name: 'DashboardPage' })
3
5
 
4
6
  type DashboardMetric = {
@@ -37,12 +39,30 @@ const selectedUnitFactor = computed(
37
39
  () => unitOptions.find((unit) => unit.label === selectedUnit.value)?.factor || 1,
38
40
  )
39
41
 
40
- const cards: DashboardCard[] = [
42
+ const dashboardAmounts = reactive({
43
+ rmb: 0,
44
+ cityClearing: 0,
45
+ crossBorderRmb: 0,
46
+ digitalCurrency: 0,
47
+ usdDomestic: 0,
48
+ usdOverseas: 0,
49
+ eurDomestic: 0,
50
+ eurOverseas: 0,
51
+ hkdDomestic: 0,
52
+ hkdOverseas: 0,
53
+ jpyDomestic: 0,
54
+ jpyOverseas: 0,
55
+ })
56
+
57
+ const isDashboardLoading = ref(false)
58
+ const dashboardLoadError = ref('')
59
+
60
+ const cards = computed<DashboardCard[]>(() => [
41
61
  {
42
62
  name: '人民币',
43
63
  code: 'CNY',
44
64
  symbol: '¥',
45
- amount: 8888888.88,
65
+ amount: dashboardAmounts.rmb,
46
66
  image: dashboardImage('01-rmb-great-wall-bg.jpg'),
47
67
  accent: '#df2f38',
48
68
  position: 'center center',
@@ -51,7 +71,7 @@ const cards: DashboardCard[] = [
51
71
  name: '城银清',
52
72
  code: 'CNY',
53
73
  symbol: '¥',
54
- amount: 6888888.88,
74
+ amount: dashboardAmounts.cityClearing,
55
75
  image: dashboardImage('02-city-clearing-skyline-bg.jpg'),
56
76
  accent: '#0f4ca7',
57
77
  position: 'center center',
@@ -60,7 +80,7 @@ const cards: DashboardCard[] = [
60
80
  name: '跨境人民币',
61
81
  code: 'CNY',
62
82
  symbol: '¥',
63
- amount: 1888888.88,
83
+ amount: dashboardAmounts.crossBorderRmb,
64
84
  image: dashboardImage('03-cross-border-rmb-world-map-bg.jpg'),
65
85
  accent: '#078b95',
66
86
  position: 'center center',
@@ -69,7 +89,7 @@ const cards: DashboardCard[] = [
69
89
  name: '数字货币',
70
90
  code: 'CNY',
71
91
  symbol: '¥',
72
- amount: 888888.88,
92
+ amount: dashboardAmounts.digitalCurrency,
73
93
  image: dashboardImage('04-digital-currency-fintech-bg.jpg'),
74
94
  accent: '#4423b7',
75
95
  position: 'center center',
@@ -78,8 +98,8 @@ const cards: DashboardCard[] = [
78
98
  name: '美元',
79
99
  code: 'USD',
80
100
  metrics: [
81
- { label: '境内', symbol: '$', amount: 888888.88 },
82
- { label: '境外', symbol: '$', amount: 888888.88 },
101
+ { label: '境内', symbol: '$', amount: dashboardAmounts.usdDomestic },
102
+ { label: '境外', symbol: '$', amount: dashboardAmounts.usdOverseas },
83
103
  ],
84
104
  image: dashboardImage('05-usd-liberty-bg.jpg'),
85
105
  accent: '#0d8b3f',
@@ -89,8 +109,8 @@ const cards: DashboardCard[] = [
89
109
  name: '欧元',
90
110
  code: 'EUR',
91
111
  metrics: [
92
- { label: '境内', symbol: '€', amount: 888888.88 },
93
- { label: '境外', symbol: '€', amount: 888888.88 },
112
+ { label: '境内', symbol: '€', amount: dashboardAmounts.eurDomestic },
113
+ { label: '境外', symbol: '€', amount: dashboardAmounts.eurOverseas },
94
114
  ],
95
115
  image: dashboardImage('06-eur-europe-architecture-bg.jpg'),
96
116
  accent: '#1267d5',
@@ -100,8 +120,8 @@ const cards: DashboardCard[] = [
100
120
  name: '港元',
101
121
  code: 'HKD',
102
122
  metrics: [
103
- { label: '境内', symbol: 'HK$', amount: 888888.88 },
104
- { label: '境外', symbol: 'HK$', amount: 888888.88 },
123
+ { label: '境内', symbol: 'HK$', amount: dashboardAmounts.hkdDomestic },
124
+ { label: '境外', symbol: 'HK$', amount: dashboardAmounts.hkdOverseas },
105
125
  ],
106
126
  image: dashboardImage('07-hkd-hong-kong-skyline-bg.jpg'),
107
127
  accent: '#e06b00',
@@ -111,14 +131,18 @@ const cards: DashboardCard[] = [
111
131
  name: '日元',
112
132
  code: 'JPY',
113
133
  metrics: [
114
- { label: '境内', symbol: '¥', amount: 888888.88 },
115
- { label: '境外', symbol: '¥', amount: 888888.88 },
134
+ { label: '境内', symbol: '¥', amount: dashboardAmounts.jpyDomestic },
135
+ { label: '境外', symbol: '¥', amount: dashboardAmounts.jpyOverseas },
116
136
  ],
117
137
  image: dashboardImage('08-jpy-mount-fuji-bg.jpg'),
118
138
  accent: '#6125c8',
119
139
  position: 'center center',
120
140
  },
121
- ]
141
+ ])
142
+
143
+ onMounted(() => {
144
+ void loadDashboard()
145
+ })
122
146
 
123
147
  function getCardStyle(card: DashboardCard) {
124
148
  return {
@@ -150,11 +174,93 @@ function formatMoney(amount: number, symbol: string) {
150
174
 
151
175
  return `${symbol} ${formattedAmount}${unitSuffix}`
152
176
  }
177
+
178
+ async function loadDashboard() {
179
+ if (isDashboardLoading.value) return
180
+
181
+ isDashboardLoading.value = true
182
+ dashboardLoadError.value = ''
183
+
184
+ try {
185
+ const [rmbResult, foreignResult] = await Promise.allSettled([
186
+ queryRmbDashboard(),
187
+ queryForeignDashboard(),
188
+ ])
189
+ const errorMessages: string[] = []
190
+
191
+ if (rmbResult.status === 'fulfilled') {
192
+ applyRmbDashboardBody(rmbResult.value.body)
193
+ } else {
194
+ errorMessages.push(getErrorMessage(rmbResult.reason))
195
+ }
196
+
197
+ if (foreignResult.status === 'fulfilled') {
198
+ applyForeignDashboardBody(foreignResult.value.body)
199
+ } else {
200
+ errorMessages.push(getErrorMessage(foreignResult.reason))
201
+ }
202
+
203
+ if (errorMessages.length) {
204
+ dashboardLoadError.value = errorMessages.join(';')
205
+ }
206
+ } catch (error) {
207
+ console.error('[看板] 数据加载失败', error)
208
+ dashboardLoadError.value = getErrorMessage(error)
209
+ } finally {
210
+ isDashboardLoading.value = false
211
+ }
212
+ }
213
+
214
+ function applyRmbDashboardBody(body: Awaited<ReturnType<typeof queryRmbDashboard>>['body']) {
215
+ const result = body || {}
216
+
217
+ dashboardAmounts.rmb = toAmount(result.settleAccAmt)
218
+ dashboardAmounts.cityClearing = toAmount(result.availCredit)
219
+ dashboardAmounts.crossBorderRmb = toAmount(result.cipsAvailBal)
220
+ dashboardAmounts.digitalCurrency = toAmount(result.dcpTotalAmt)
221
+ }
222
+
223
+ function applyForeignDashboardBody(
224
+ body: Awaited<ReturnType<typeof queryForeignDashboard>>['body'],
225
+ ) {
226
+ const result = body || {}
227
+
228
+ dashboardAmounts.usdDomestic = toAmount(result.usdDomesticAmt)
229
+ dashboardAmounts.usdOverseas = toAmount(result.usdOverseasAmt)
230
+ dashboardAmounts.eurDomestic = toAmount(result.eurDomesticAmt)
231
+ dashboardAmounts.eurOverseas = toAmount(result.eurOverseasAmt)
232
+ dashboardAmounts.hkdDomestic = toAmount(result.hkdDomesticAmt)
233
+ dashboardAmounts.hkdOverseas = toAmount(result.hkdOverseasAmt)
234
+ dashboardAmounts.jpyDomestic = toAmount(result.jpyDomesticAmt)
235
+ dashboardAmounts.jpyOverseas = toAmount(result.jpyOverseasAmt)
236
+ }
237
+
238
+ function toAmount(value: unknown) {
239
+ const amount = Number(String(value ?? '').replaceAll(',', '').trim())
240
+
241
+ return Number.isFinite(amount) ? amount : 0
242
+ }
243
+
244
+ function getErrorMessage(error: unknown) {
245
+ if (error instanceof Error && error.message) return error.message
246
+
247
+ return '看板数据加载失败'
248
+ }
153
249
  </script>
154
250
 
155
251
  <template>
156
- <main class="dashboard-page">
252
+ <main class="dashboard-page" :aria-busy="isDashboardLoading">
157
253
  <div class="dashboard-toolbar" aria-label="看板设置">
254
+ <button
255
+ v-if="dashboardLoadError"
256
+ class="dashboard-retry"
257
+ type="button"
258
+ :disabled="isDashboardLoading"
259
+ @click="loadDashboard"
260
+ >
261
+ 刷新
262
+ </button>
263
+
158
264
  <label class="unit-switch">
159
265
  <span class="unit-switch__label">单位</span>
160
266
  <select v-model="selectedUnit" class="unit-switch__select" aria-label="切换金额单位">
@@ -180,8 +286,8 @@ function formatMoney(amount: number, symbol: string) {
180
286
  <span class="dashboard-card__code">{{ card.code }}</span>
181
287
  </header>
182
288
 
183
- <p v-if="card.amount" class="dashboard-card__amount">
184
- {{ formatMoney(card.amount, card.symbol || '') }}
289
+ <p v-if="!card.metrics" class="dashboard-card__amount">
290
+ {{ formatMoney(card.amount || 0, card.symbol || '') }}
185
291
  </p>
186
292
 
187
293
  <div v-else class="dashboard-card__metrics">
@@ -211,10 +317,29 @@ function formatMoney(amount: number, symbol: string) {
211
317
 
212
318
  .dashboard-toolbar {
213
319
  display: flex;
320
+ align-items: center;
214
321
  justify-content: flex-end;
215
322
  margin-bottom: 6px;
216
323
  }
217
324
 
325
+ .dashboard-retry {
326
+ height: 24px;
327
+ margin-right: auto;
328
+ border: 1px solid #ffd4d8;
329
+ border-radius: 5px;
330
+ padding: 0 10px;
331
+ color: #dc2735;
332
+ font: inherit;
333
+ font-size: 12px;
334
+ font-weight: 700;
335
+ line-height: 22px;
336
+ background: #fff5f6;
337
+ }
338
+
339
+ .dashboard-retry:disabled {
340
+ opacity: 0.62;
341
+ }
342
+
218
343
  .unit-switch {
219
344
  position: relative;
220
345
  display: inline-flex;
File without changes
File without changes
File without changes