minitest2.0 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 (89) hide show
  1. package/.editorconfig +8 -0
  2. package/.env.development +3 -0
  3. package/.env.production +3 -0
  4. package/.env.test +3 -0
  5. package/.gitattributes +1 -0
  6. package/.oxlintrc.json +10 -0
  7. package/.prettierrc.json +6 -0
  8. package/.vscode/extensions.json +9 -0
  9. package/.vscode/settings.json +13 -0
  10. package/README.md +179 -0
  11. package/auto-imports.d.ts +629 -0
  12. package/components.d.ts +21 -0
  13. package/design-qa.md +36 -0
  14. package/docs/MX_API.md +244 -0
  15. package/docs/REQUEST.md +217 -0
  16. package/docs/jsapi.js +515 -0
  17. package/docs/package-json-guide.md +132 -0
  18. package/env.d.ts +15 -0
  19. package/eslint.config.ts +26 -0
  20. package/index.html +16 -0
  21. package/package.json +83 -0
  22. package/plugins/bump-version.ts +61 -0
  23. package/postcss.config.ts +15 -0
  24. package/public/favicon.ico +0 -0
  25. package/public/images/12a73787-86a9-4891-a65f-66104746f6a8.png +0 -0
  26. package/public/images/5798d7aa-ba8b-4605-8079-58b35495ac55.png +0 -0
  27. package/public/images/73fef1e4-0fd0-4a1a-9b8b-a70a5b6acbbc.png +0 -0
  28. package/public/images/bc685b4c-0cca-4a79-924c-a8ee10e6f8eb.png +0 -0
  29. package/public/images/c3dbbd9d-be56-490e-b9f4-6ee17ebefffc.png +0 -0
  30. package/public/images/ea745a10-42aa-4f44-8d7f-3ab02cc0adcd.png +0 -0
  31. package/public/images/f5876785-b927-4347-ba19-999114240649.png +0 -0
  32. package/public/images/img.png +0 -0
  33. package/public/images/opening-reserve-estimate.png +0 -0
  34. package/public/images/position-estimate-report.png +0 -0
  35. package/src/App.vue +131 -0
  36. package/src/api/announcement.ts +405 -0
  37. package/src/api/health.ts +13 -0
  38. package/src/api/pbc-position.ts +178 -0
  39. package/src/api/rmb-position.ts +233 -0
  40. package/src/api/tam.ts +173 -0
  41. package/src/api/user.ts +92 -0
  42. package/src/auto-imports.d.ts +633 -0
  43. package/src/components/AppTitleBar.vue +376 -0
  44. package/src/components.d.ts +33 -0
  45. package/src/config/config.properties +3 -0
  46. package/src/config/env.ts +6 -0
  47. package/src/config/plugin.properties.pro +6 -0
  48. package/src/config/plugin.properties.test +6 -0
  49. package/src/core/mxApi/index.ts +451 -0
  50. package/src/core/request/index.ts +135 -0
  51. package/src/main.ts +40 -0
  52. package/src/router/index.ts +144 -0
  53. package/src/stores/app.ts +103 -0
  54. package/src/stores/counter.ts +12 -0
  55. package/src/stores/user.ts +137 -0
  56. package/src/styles/nprogress.css +22 -0
  57. package/src/styles/vant-overrides.css +42 -0
  58. package/src/types/api.d.ts +14 -0
  59. package/src/types/nprogress.d.ts +8 -0
  60. package/src/utils/auth-token.ts +241 -0
  61. package/src/utils/code-highlight.ts +165 -0
  62. package/src/utils/copy.ts +36 -0
  63. package/src/utils/query.ts +27 -0
  64. package/src/utils/request.ts +238 -0
  65. package/src/utils/rmb-forecast.ts +84 -0
  66. package/src/utils/toast.ts +61 -0
  67. package/src/views/article-detail/index.vue +289 -0
  68. package/src/views/article-edit/index.vue +600 -0
  69. package/src/views/articles/index.vue +293 -0
  70. package/src/views/clearing-detail/index.vue +26 -0
  71. package/src/views/dashboard/index.vue +18 -0
  72. package/src/views/foreign-position/index.vue +26 -0
  73. package/src/views/home/index.vue +213 -0
  74. package/src/views/login/index.vue +275 -0
  75. package/src/views/mine/index.vue +147 -0
  76. package/src/views/net-debit/index.vue +26 -0
  77. package/src/views/opening-reserve-estimate/index.vue +28 -0
  78. package/src/views/pbc-position/index.vue +357 -0
  79. package/src/views/position-estimate/index.vue +67 -0
  80. package/src/views/position-estimate-report/index.vue +28 -0
  81. package/src/views/rmb-position/index.vue +1013 -0
  82. package/src/views/rmb-position-create/index.vue +221 -0
  83. package/src/views/rmb-position-detail/index.vue +355 -0
  84. package/src/views/settings/index.vue +67 -0
  85. package/src/views/warning/index.vue +26 -0
  86. package/tsconfig.app.json +18 -0
  87. package/tsconfig.json +11 -0
  88. package/tsconfig.node.json +28 -0
  89. package/vite.config.ts +100 -0
@@ -0,0 +1,357 @@
1
+ <script setup lang="ts">
2
+ import {
3
+ buildPbcPositionSendPayload,
4
+ queryPbcPositionBalance,
5
+ sendPbcPositionRequest,
6
+ type PbcPositionBalance,
7
+ } from '@/api/pbc-position'
8
+ import { showAppToast } from '@/utils/toast'
9
+
10
+ defineOptions({ name: 'PbcPositionPage' })
11
+
12
+ type PositionItem = {
13
+ label: string
14
+ value: string
15
+ icon: string
16
+ highlight?: boolean
17
+ }
18
+
19
+ type PositionSection = {
20
+ key: string
21
+ items: PositionItem[]
22
+ }
23
+
24
+ const balanceDetail = ref<PbcPositionBalance | null>(null)
25
+ const sending = ref(false)
26
+ const querying = ref(false)
27
+
28
+ const actionDisabled = computed(() => sending.value || querying.value)
29
+ const requestRefNo = computed(() => balanceDetail.value?.requestRefNo || '')
30
+
31
+ const positionSections = computed<PositionSection[]>(() => {
32
+ const detail = balanceDetail.value
33
+
34
+ return [
35
+ {
36
+ key: 'basic',
37
+ items: [
38
+ { label: '清算账户账号', value: fieldText(detail?.settleBankNo), icon: 'manager' },
39
+ { label: '更新时间', value: fieldText(detail?.updateTime), icon: 'clock' },
40
+ {
41
+ label: '申请平台流水号',
42
+ value: fieldText(detail?.refNo || detail?.requestRefNo),
43
+ icon: 'description',
44
+ },
45
+ { label: '清算账户行号', value: fieldText(detail?.settleBankNo), icon: 'hotel-o' },
46
+ { label: '应答平台流水号', value: fieldText(detail?.resRefNo), icon: 'cluster' },
47
+ ],
48
+ },
49
+ {
50
+ key: 'balance',
51
+ items: [
52
+ {
53
+ label: '清算账户余额(亿元)',
54
+ value: formatYuanToBillionText(detail?.settleBal),
55
+ icon: 'balance-o',
56
+ highlight: true,
57
+ },
58
+ { label: '可用头寸(亿元)', value: formatYuanToBillionText(detail?.avaAmt), icon: 'card' },
59
+ {
60
+ label: '预期头寸(亿元)',
61
+ value: formatYuanToBillionText(detail?.expectAmt),
62
+ icon: 'chart-trending-o',
63
+ },
64
+ ],
65
+ },
66
+ {
67
+ key: 'queue',
68
+ items: [
69
+ {
70
+ label: '排队借记总金额(亿元)',
71
+ value: formatYuanToBillionText(detail?.lineDrAmt),
72
+ icon: 'gold-coin-o',
73
+ },
74
+ {
75
+ label: '排队贷记总金额(亿元)',
76
+ value: formatYuanToBillionText(detail?.lineCrAmt),
77
+ icon: 'card',
78
+ },
79
+ { label: '所辖非清算账户数', value: fieldText(detail?.subAcctNumber), icon: 'friends' },
80
+ {
81
+ label: '所辖非清算总余额(亿元)',
82
+ value: formatYuanToBillionText(detail?.subAcctAmt),
83
+ icon: 'paid',
84
+ },
85
+ ],
86
+ },
87
+ ]
88
+ })
89
+
90
+ async function handleSend() {
91
+ if (actionDisabled.value) return
92
+
93
+ sending.value = true
94
+ const payload = buildPbcPositionSendPayload()
95
+ console.log('[人行头寸余额发送入参]', payload)
96
+
97
+ try {
98
+ const response = await sendPbcPositionRequest(payload)
99
+ const refNo = response.body.refNo || ''
100
+
101
+ balanceDetail.value = {
102
+ requestRefNo: refNo,
103
+ refNo,
104
+ }
105
+ showAppToast(refNo ? `发送成功:${refNo}` : '发送成功')
106
+ } catch (error) {
107
+ console.error('[人行头寸余额发送失败]', error)
108
+ showAppToast(getErrorMessage(error, '发送失败,请重试'))
109
+ } finally {
110
+ sending.value = false
111
+ }
112
+ }
113
+
114
+ async function handleQuery() {
115
+ if (actionDisabled.value) return
116
+
117
+ if (!requestRefNo.value) {
118
+ showDialog({
119
+ title: '提示',
120
+ message: '请先点击发送获取编号',
121
+ confirmButtonText: '知道了',
122
+ })
123
+ return
124
+ }
125
+
126
+ querying.value = true
127
+
128
+ try {
129
+ balanceDetail.value = await queryPbcPositionBalance(requestRefNo.value)
130
+ showAppToast('查询完成')
131
+ } catch (error) {
132
+ console.error('[人行头寸余额查询失败]', error)
133
+ showAppToast(getErrorMessage(error, '查询失败,请重试'))
134
+ } finally {
135
+ querying.value = false
136
+ }
137
+ }
138
+
139
+ function fieldText(value?: string) {
140
+ const text = value?.trim()
141
+ return text || '-'
142
+ }
143
+
144
+ function formatYuanToBillionText(value?: string) {
145
+ if (!value?.trim()) return '-'
146
+
147
+ const amount = Number(value.replaceAll(',', ''))
148
+ if (!Number.isFinite(amount)) return '-'
149
+
150
+ return new Intl.NumberFormat('zh-CN', {
151
+ minimumFractionDigits: 2,
152
+ maximumFractionDigits: 2,
153
+ }).format(amount / 100000000)
154
+ }
155
+
156
+ function getErrorMessage(error: unknown, fallback: string) {
157
+ return error instanceof Error && error.message ? error.message : fallback
158
+ }
159
+ </script>
160
+
161
+ <template>
162
+ <main class="pbc-page">
163
+ <section class="balance-card" aria-label="人行头寸余额">
164
+ <div v-for="section in positionSections" :key="section.key" class="info-section">
165
+ <dl class="info-list">
166
+ <div v-for="item in section.items" :key="`${section.key}-${item.label}`" class="info-row">
167
+ <dt>
168
+ <span class="field-icon" aria-hidden="true">
169
+ <van-icon :name="item.icon" />
170
+ </span>
171
+ <span class="field-label">{{ item.label }}</span>
172
+ </dt>
173
+ <dd :class="{ highlight: item.highlight }">{{ item.value }}</dd>
174
+ </div>
175
+ </dl>
176
+ </div>
177
+ </section>
178
+
179
+ <nav class="action-bar" aria-label="人行头寸操作">
180
+ <button
181
+ class="action-btn send-btn"
182
+ type="button"
183
+ :disabled="actionDisabled"
184
+ @click="handleSend"
185
+ >
186
+ <span>{{ sending ? '发送中' : '发送' }}</span>
187
+ </button>
188
+ <button
189
+ class="action-btn query-btn"
190
+ type="button"
191
+ :disabled="actionDisabled"
192
+ @click="handleQuery"
193
+ >
194
+ <span>{{ querying ? '查询中' : '查询' }}</span>
195
+ </button>
196
+ </nav>
197
+ </main>
198
+ </template>
199
+
200
+ <style scoped>
201
+ .pbc-page {
202
+ width: 100%;
203
+ max-width: 750px;
204
+ min-height: var(--app-page-min-height, 100vh);
205
+ margin: 0 auto;
206
+ padding-bottom: calc(env(safe-area-inset-bottom, 0px) + 82px);
207
+ color: #181d28;
208
+ box-sizing: border-box;
209
+ }
210
+
211
+ button {
212
+ border: 0;
213
+ padding: 0;
214
+ font: inherit;
215
+ background: transparent;
216
+ appearance: none;
217
+ }
218
+
219
+ .balance-card {
220
+ overflow: hidden;
221
+ margin: 17px 13px 0;
222
+ border: 1px solid #edf0f4;
223
+ border-radius: 19px;
224
+ background: rgba(255, 255, 255, 0.98);
225
+ box-shadow: 0 8px 24px rgba(32, 38, 55, 0.06);
226
+ }
227
+
228
+ .info-section + .info-section {
229
+ border-top: 8px solid #f7f7f8;
230
+ }
231
+
232
+ .info-list {
233
+ margin: 0;
234
+ padding: 8px 13px;
235
+ }
236
+
237
+ .info-row {
238
+ display: grid;
239
+ grid-template-columns: minmax(0, 1fr) auto;
240
+ align-items: center;
241
+ min-height: 37px;
242
+ column-gap: 10px;
243
+ }
244
+
245
+ .info-row + .info-row {
246
+ border-top: 1px solid #edf0f2;
247
+ }
248
+
249
+ .info-row dt {
250
+ display: flex;
251
+ align-items: center;
252
+ min-width: 0;
253
+ margin: 0;
254
+ }
255
+
256
+ .field-icon {
257
+ display: inline-flex;
258
+ align-items: center;
259
+ justify-content: center;
260
+ width: 26px;
261
+ height: 26px;
262
+ flex: 0 0 26px;
263
+ border-radius: 7px;
264
+ color: #ef252d;
265
+ font-size: 18px;
266
+ background: linear-gradient(135deg, #fff1f2 0%, #ffe8ea 100%);
267
+ box-shadow: 0 4px 11px rgba(236, 42, 50, 0.1);
268
+ }
269
+
270
+ .field-label {
271
+ overflow: hidden;
272
+ margin-left: 14px;
273
+ color: #202532;
274
+ font-size: 14px;
275
+ font-weight: 520;
276
+ line-height: 1.25;
277
+ text-overflow: ellipsis;
278
+ white-space: nowrap;
279
+ }
280
+
281
+ .info-row dd {
282
+ margin: 0;
283
+ color: #1a1f2a;
284
+ font-size: 14px;
285
+ font-weight: 500;
286
+ line-height: 1.2;
287
+ text-align: right;
288
+ white-space: nowrap;
289
+ }
290
+
291
+ .info-row dd.highlight {
292
+ color: #c91b20;
293
+ font-size: 22px;
294
+ font-weight: 760;
295
+ letter-spacing: 0;
296
+ }
297
+
298
+ .action-bar {
299
+ position: fixed;
300
+ right: 0;
301
+ bottom: calc(env(safe-area-inset-bottom, 0px) + 15px);
302
+ left: 50%;
303
+ z-index: 10;
304
+ display: grid;
305
+ grid-template-columns: 1fr 1fr;
306
+ gap: 19px;
307
+ width: 100%;
308
+ max-width: 750px;
309
+ padding: 0 13px;
310
+ transform: translateX(-50%);
311
+ box-sizing: border-box;
312
+ pointer-events: none;
313
+ }
314
+
315
+ .action-btn {
316
+ display: inline-flex;
317
+ align-items: center;
318
+ justify-content: center;
319
+ height: 44px;
320
+ border-radius: 24px;
321
+ font-size: 18px;
322
+ font-weight: 580;
323
+ line-height: 1;
324
+ pointer-events: auto;
325
+ }
326
+
327
+ .action-btn:disabled {
328
+ cursor: not-allowed;
329
+ opacity: 0.68;
330
+ }
331
+
332
+ .send-btn {
333
+ color: #ffffff;
334
+ background: linear-gradient(135deg, #ff3338 0%, #ff232b 100%);
335
+ box-shadow:
336
+ 0 12px 22px rgba(255, 44, 50, 0.24),
337
+ inset 0 1px 0 rgba(255, 255, 255, 0.22);
338
+ }
339
+
340
+ .query-btn {
341
+ border: 1px solid #ff3038;
342
+ color: #ef252d;
343
+ background: rgba(255, 255, 255, 0.98);
344
+ box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.9);
345
+ }
346
+
347
+ @media (max-width: 350px) {
348
+ .field-label,
349
+ .info-row dd {
350
+ font-size: 13px;
351
+ }
352
+
353
+ .info-row dd.highlight {
354
+ font-size: 19px;
355
+ }
356
+ }
357
+ </style>
@@ -0,0 +1,67 @@
1
+ <script setup lang="ts">
2
+ const router = useRouter()
3
+
4
+ const estimateItems = [
5
+ {
6
+ title: '头寸匡算报表',
7
+ route: '/position-estimate/report',
8
+ image: `${import.meta.env.BASE_URL}images/position-estimate-report.png`,
9
+ },
10
+ {
11
+ title: '日初备款数匡算',
12
+ route: '/position-estimate/opening-reserve',
13
+ image: `${import.meta.env.BASE_URL}images/opening-reserve-estimate.png`,
14
+ },
15
+ ]
16
+ </script>
17
+
18
+ <template>
19
+ <main class="page">
20
+ <section class="nav-list" aria-label="头寸匡算功能导航">
21
+ <button
22
+ v-for="item in estimateItems"
23
+ :key="item.route"
24
+ class="nav-item"
25
+ type="button"
26
+ :aria-label="item.title"
27
+ @click="router.push(item.route)"
28
+ >
29
+ <img class="nav-image" :src="item.image" :alt="item.title" />
30
+ </button>
31
+ </section>
32
+ </main>
33
+ </template>
34
+
35
+ <style scoped>
36
+ .page {
37
+ max-width: 750px;
38
+ min-height: var(--app-page-min-height, 100vh);
39
+ margin: 0 auto;
40
+ padding: 42px 26px 24px;
41
+ background: #ffffff;
42
+ box-sizing: border-box;
43
+ }
44
+
45
+ .nav-list {
46
+ display: flex;
47
+ flex-direction: column;
48
+ gap: 34px;
49
+ }
50
+
51
+ .nav-item {
52
+ display: block;
53
+ width: 100%;
54
+ overflow: hidden;
55
+ padding: 0;
56
+ border: 0;
57
+ border-radius: 18px;
58
+ background: transparent;
59
+ appearance: none;
60
+ }
61
+
62
+ .nav-image {
63
+ display: block;
64
+ width: 100%;
65
+ height: auto;
66
+ }
67
+ </style>
@@ -0,0 +1,28 @@
1
+ <template>
2
+ <main class="page">
3
+ <section class="page-body">
4
+ <p class="placeholder">页面建设中…</p>
5
+ </section>
6
+ </main>
7
+ </template>
8
+
9
+ <style scoped>
10
+ .page {
11
+ max-width: 750px;
12
+ min-height: var(--app-page-min-height, 100vh);
13
+ margin: 0 auto;
14
+ padding: 0 11px;
15
+ background: #f7f8fa;
16
+ }
17
+
18
+ .page-body {
19
+ padding: 24px 0;
20
+ }
21
+
22
+ .placeholder {
23
+ padding-top: 120px;
24
+ color: #969799;
25
+ font-size: 14px;
26
+ text-align: center;
27
+ }
28
+ </style>