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,233 @@
1
+ import {
2
+ buildTamRequestPayload,
3
+ tamRequest,
4
+ type TamRequestPayload,
5
+ type TamResponse,
6
+ } from '@/api/tam'
7
+ import { useAppStore } from '@/stores/app'
8
+
9
+ export type RmbForecastRecord = {
10
+ /** 业务类型,用于映射列表中的业务名称。 */
11
+ busiType?: string
12
+ /** 客户名称,客户类型为空时作为展示兜底。 */
13
+ clientName?: string
14
+ /** 客户类型,用于映射列表中的客户类型文案。 */
15
+ clientType?: string
16
+ /** 交易对手名称,客户名称为空时作为展示兜底。 */
17
+ competName?: string
18
+ /** 落地机构,列表主标题展示字段。 */
19
+ groundBranch?: string
20
+ /** 预报金额,接口按元返回,页面转换为亿元展示。 */
21
+ predAmt?: string
22
+ /** 预报流水号,点击列表进入详情的主键。 */
23
+ predRefNo?: string
24
+ /** 预报状态,用于判断列表状态标签。 */
25
+ predStatus?: string
26
+ /** 交易日期,列表日期展示字段。 */
27
+ tranDate?: string
28
+ /** 核销状态,用于判断列表状态标签。 */
29
+ verifyStatus?: string
30
+ }
31
+
32
+ export type RmbForecastQueryForm = {
33
+ /** 交易时间,当前视图必填筛选项。 */
34
+ tranDate: string
35
+ /** 落地机构,当前视图按关键字查询。 */
36
+ groundBranch?: string
37
+ /** 起始金额,页面单位为亿元。 */
38
+ startTranAmt?: string
39
+ /** 截止金额,页面单位为亿元。 */
40
+ endTranAmt?: string
41
+ }
42
+
43
+ export type RmbForecastQueryPayload = {
44
+ appHead: TamRequestPayload<RmbForecastQueryBody>['appHead']
45
+ body: RmbForecastQueryBody
46
+ head: TamRequestPayload<RmbForecastQueryBody>['head']
47
+ }
48
+
49
+ export type RmbForecastQueryResult = {
50
+ body: RmbForecastQueryResultBody
51
+ head: TamResponse<RmbForecastQueryResultBody>['head']
52
+ }
53
+
54
+ export type RmbForecastDetailPayload = {
55
+ appHead: TamRequestPayload<RmbForecastDetailBody>['appHead']
56
+ body: RmbForecastDetailBody
57
+ head: TamRequestPayload<RmbForecastDetailBody>['head']
58
+ }
59
+
60
+ export type RmbForecastDetailResult = {
61
+ body: RmbForecastDetailRecord
62
+ head: TamResponse<RmbForecastDetailRecord>['head']
63
+ }
64
+
65
+ type RmbForecastQueryBody = {
66
+ /** 业务类型,当前视图未开放筛选,固定传空。 */
67
+ busiType: string
68
+ /** 客户名称,当前视图未开放筛选,固定传空。 */
69
+ clientName: string
70
+ /** 交易对手名称,当前视图未开放筛选,固定传空。 */
71
+ competName: string
72
+ /** 截止金额,页面亿元转换为接口元级整数字符串。 */
73
+ endTransAmt: string
74
+ /** 落地机构,来自当前视图输入框。 */
75
+ groundBranch: string
76
+ /** 支付渠道,当前视图未开放筛选,固定传空。 */
77
+ payChannel: string
78
+ /** 收支方向,当前视图未开放筛选,固定传空。 */
79
+ payDirec: string
80
+ /** 预报状态,当前视图未开放筛选,固定传空。 */
81
+ predStatus: string
82
+ /** 排序规则,当前视图未开放筛选,固定传空。 */
83
+ sortRule: string
84
+ /** 起始金额,页面亿元转换为接口元级整数字符串。 */
85
+ startTransAmt: string
86
+ /** 交易时间,接口格式为 YYYYMMDD。 */
87
+ tranDate: string
88
+ /** 核销状态,当前视图未开放筛选,固定传空。 */
89
+ verifyStatus: string
90
+ }
91
+
92
+ type RmbForecastQueryResultBody = {
93
+ resultList: RmbForecastRecord[]
94
+ totalCount: string
95
+ }
96
+
97
+ type RmbForecastDetailBody = {
98
+ /** 预报流水号,详情查询主键。 */
99
+ predRefNo: string
100
+ }
101
+
102
+ export type RmbForecastDetailRecord = {
103
+ /** 出票日 */
104
+ billDate?: string
105
+ /** 票号 */
106
+ billNo?: string
107
+ /** 业务类型 */
108
+ busiType?: string
109
+ /** 客户名称 */
110
+ clientName?: string
111
+ /** 客户类型 */
112
+ clientType?: string
113
+ /** 交易对手账号 */
114
+ competAcct?: string
115
+ /** 交易对手名称 */
116
+ competName?: string
117
+ /** 额度标志 */
118
+ eduFlag?: string
119
+ /** 落地机构名称 */
120
+ groundBranch?: string
121
+ /** 落地机构代码 */
122
+ groundBranchCode?: string
123
+ /** 联系人 */
124
+ linkMan?: string
125
+ /** 支付渠道 */
126
+ payChannel?: string
127
+ /** 收支方向 */
128
+ payDirec?: string
129
+ /** 联系电话 */
130
+ phoneNo?: string
131
+ /** 预报金额 */
132
+ predAmt?: string
133
+ /** 预报机构 */
134
+ predBranch?: string
135
+ /** 预报机构 */
136
+ predBranchName?: string
137
+ /** 预报人员编号 */
138
+ predCode?: string
139
+ /** 预报日期 */
140
+ predDate?: string
141
+ /** 预报人员姓名 */
142
+ predName?: string
143
+ /** 预报流水号 */
144
+ predRefNo?: string
145
+ /** 预报状态 */
146
+ predStatus?: string
147
+ /** 用途 */
148
+ purpose?: string
149
+ /** 备注 */
150
+ remark?: string
151
+ /** 标准名称 */
152
+ standardName?: string
153
+ /** 交易日期 */
154
+ tranDate?: string
155
+ /** 已核销金额 */
156
+ verifyAmt?: string
157
+ /** 核销状态 */
158
+ verifyStatus?: string
159
+ }
160
+
161
+ type QueryOptions = {
162
+ form: RmbForecastQueryForm
163
+ pageIndex: number
164
+ pageSize: number
165
+ }
166
+
167
+ const QUERY_TRAN_CODE = '/TAM/0001/140101001'
168
+ const DETAIL_TRAN_CODE = '/TAM/0001/140101002'
169
+
170
+ export function buildRmbForecastQueryPayload({
171
+ form,
172
+ pageIndex,
173
+ pageSize,
174
+ }: QueryOptions): RmbForecastQueryPayload {
175
+ const tranDate = normalizeDate(form.tranDate || useAppStore().systemWorkDate)
176
+
177
+ // 当前视图只提供交易日期、落地机构、起始金额、截止金额,其余查询字段按接口约定传空。
178
+ return buildTamRequestPayload({
179
+ tranCode: QUERY_TRAN_CODE,
180
+ pageIndex,
181
+ pageSize,
182
+ body: {
183
+ busiType: '',
184
+ clientName: '',
185
+ competName: '',
186
+ endTransAmt: toRequestAmount(form.endTranAmt),
187
+ groundBranch: form.groundBranch || '',
188
+ payChannel: '',
189
+ payDirec: '',
190
+ predStatus: '',
191
+ sortRule: '',
192
+ // 后端字段名为 TransAmt,保持与交易入参一致。
193
+ startTransAmt: toRequestAmount(form.startTranAmt),
194
+ tranDate,
195
+ verifyStatus: '',
196
+ },
197
+ })
198
+ }
199
+
200
+ export async function queryRmbForecastPage(
201
+ payload: RmbForecastQueryPayload,
202
+ ): Promise<RmbForecastQueryResult> {
203
+ return tamRequest<RmbForecastQueryBody, RmbForecastQueryResultBody>(payload)
204
+ }
205
+
206
+ export function buildRmbForecastDetailPayload(predRefNo: string): RmbForecastDetailPayload {
207
+ return buildTamRequestPayload({
208
+ tranCode: DETAIL_TRAN_CODE,
209
+ body: {
210
+ predRefNo,
211
+ },
212
+ })
213
+ }
214
+
215
+ export async function queryRmbForecastDetail(
216
+ payload: RmbForecastDetailPayload,
217
+ ): Promise<RmbForecastDetailResult> {
218
+ return tamRequest<RmbForecastDetailBody, RmbForecastDetailRecord>(payload)
219
+ }
220
+
221
+ function normalizeDate(value: string) {
222
+ // 日期选择器产出 YYYY-MM-DD;接口需要 YYYYMMDD。
223
+ if (/^\d{8}$/.test(value)) return value
224
+ return value.replaceAll('-', '')
225
+ }
226
+
227
+ function toRequestAmount(value?: string) {
228
+ if (!value?.trim()) return ''
229
+
230
+ // 页面按“亿元”录入,接口按元级整数金额查询。
231
+ const amount = Number(value)
232
+ return Number.isFinite(amount) ? String(Math.round(amount * 100000000)) : ''
233
+ }
package/src/api/tam.ts ADDED
@@ -0,0 +1,173 @@
1
+ import dayjs from 'dayjs'
2
+ import { request } from '@/core/request'
3
+ import { useAppStore } from '@/stores/app'
4
+ import { useUserStore } from '@/stores/user'
5
+
6
+ export type TamAppHead = {
7
+ fileName: string
8
+ opType: string
9
+ ip: string
10
+ }
11
+
12
+ export type TamHead = {
13
+ adminUserId: string
14
+ apprUserId: string
15
+ areaCode: string
16
+ branchId: string
17
+ consumerId: string
18
+ consumerSeqNo: string
19
+ digitalSign: string
20
+ fileFlag: string
21
+ filePath: string
22
+ isBatch: boolean
23
+ pageIndex: number
24
+ pageSize: number
25
+ spanId: string
26
+ traceId: string
27
+ tranCode: string
28
+ tranDate: string
29
+ tranTimestamp: string
30
+ userId: string
31
+ verifyUserId: string
32
+ versionId: string
33
+ }
34
+
35
+ export type TamRequestPayload<TBody> = {
36
+ appHead: TamAppHead
37
+ head: TamHead
38
+ body: TBody
39
+ }
40
+
41
+ export type TamResponseHead = Omit<TamHead, 'pageIndex' | 'pageSize'> & {
42
+ ctrlBits?: string
43
+ extra?: Record<string, unknown>
44
+ pageIndex: number | string
45
+ pageSize: number | string
46
+ retCode: string
47
+ retMsg: string
48
+ retStatus: string
49
+ }
50
+
51
+ export type TamResponse<TBody> = {
52
+ head: TamResponseHead
53
+ body: TBody
54
+ }
55
+
56
+ type BuildTamPayloadOptions<TBody> = {
57
+ tranCode: string
58
+ body: TBody
59
+ pageIndex?: number
60
+ pageSize?: number
61
+ appHead?: Partial<TamAppHead>
62
+ head?: Partial<TamHead>
63
+ }
64
+
65
+ let consumerSeqSeed = Math.floor(Math.random() * 100000000)
66
+
67
+ export function buildTamRequestPayload<TBody>({
68
+ tranCode,
69
+ body,
70
+ pageIndex = 1,
71
+ pageSize = 10,
72
+ appHead,
73
+ head,
74
+ }: BuildTamPayloadOptions<TBody>): TamRequestPayload<TBody> {
75
+ const now = dayjs()
76
+ const appStore = useAppStore()
77
+ const loginContext = getTamLoginContext()
78
+ const tranDate = appStore.systemWorkDateCompact
79
+
80
+ return {
81
+ appHead: {
82
+ fileName: '',
83
+ opType: '',
84
+ ip: loginContext.ip,
85
+ ...appHead,
86
+ },
87
+ head: {
88
+ adminUserId: '',
89
+ apprUserId: '',
90
+ areaCode: '0000',
91
+ branchId: loginContext.branchId,
92
+ consumerId: 'TAM001',
93
+ // 规则:当前登录用户 ID + 日期 + 8 位运行期递增序列。
94
+ consumerSeqNo: `${loginContext.userId}${tranDate}${createConsumerSeq()}`,
95
+ digitalSign: '',
96
+ fileFlag: 'N',
97
+ filePath: '',
98
+ isBatch: false,
99
+ pageIndex,
100
+ pageSize,
101
+ spanId: '',
102
+ traceId: '',
103
+ tranCode,
104
+ tranDate,
105
+ tranTimestamp: now.format('HHmmss'),
106
+ userId: loginContext.userId,
107
+ verifyUserId: '',
108
+ versionId: '0001',
109
+ ...head,
110
+ },
111
+ body,
112
+ }
113
+ }
114
+
115
+ export async function tamRequest<TBody, TResponseBody>(
116
+ payload: TamRequestPayload<TBody>,
117
+ ): Promise<TamResponse<TResponseBody>> {
118
+ const response = await request<TamResponse<TResponseBody>, TamRequestPayload<TBody>>({
119
+ url: payload.head.tranCode,
120
+ method: 'POST',
121
+ data: payload,
122
+ })
123
+ const result = response as unknown as TamResponse<TResponseBody>
124
+
125
+ if (result.head?.retStatus && result.head.retStatus !== 'S') {
126
+ throw new Error(result.head.retMsg || '交易失败')
127
+ }
128
+
129
+ return result
130
+ }
131
+
132
+ function getTamLoginContext() {
133
+ const userStore = useUserStore()
134
+ const principal = userStore.authPayload?.principal
135
+
136
+ return {
137
+ // TAM 用户号优先取登录返回的 userId,兼容只返回 username 的场景。
138
+ userId: firstText(principal?.userId, principal?.username, userStore.username),
139
+ // 当前登录机构来自 /uaa/user/getOrgByUserName 的第一条记录。
140
+ branchId: firstText(
141
+ userStore.loginOrg?.orgNo,
142
+ userStore.loginOrg?.orgId,
143
+ principal?.branchId,
144
+ principal?.orgId,
145
+ principal?.currentOrgId,
146
+ getLastText(principal?.orgIds),
147
+ ),
148
+ // appHead.ip 使用登录返回的请求 IP。
149
+ ip: firstText(principal?.reqIpAddr, principal?.ip, principal?.loginIp),
150
+ }
151
+ }
152
+
153
+ function createConsumerSeq() {
154
+ consumerSeqSeed = (consumerSeqSeed + 1) % 100000000
155
+ return String(consumerSeqSeed).padStart(8, '0')
156
+ }
157
+
158
+ function getLastText(value: unknown) {
159
+ if (!Array.isArray(value)) return undefined
160
+
161
+ return [...value].reverse().find((item) => typeof item === 'string' && item.trim())
162
+ }
163
+
164
+ function firstText(...values: unknown[]) {
165
+ for (const value of values) {
166
+ if (typeof value !== 'string') continue
167
+
168
+ const text = value.trim()
169
+ if (text) return text
170
+ }
171
+
172
+ return ''
173
+ }
@@ -0,0 +1,92 @@
1
+ import { request } from '@/core/request'
2
+ import { REFRESH_TOKEN_URL, type AuthTokenResponse } from '@/utils/auth-token'
3
+
4
+ interface UserInfo {
5
+ id: number
6
+ username: string
7
+ avatar: string
8
+ }
9
+
10
+ export type UserOrg = {
11
+ orgNo: string
12
+ orgCnAbre: string
13
+ SORTNO: number
14
+ orgId: string
15
+ }
16
+
17
+ export type LastLoginTimeInfo = {
18
+ loginTm?: string
19
+ userRealName?: string
20
+ reqMsg?: string
21
+ optType?: string
22
+ loginLogId?: string
23
+ optDesc?: string
24
+ loginUserName?: string
25
+ respMsg?: string
26
+ appDt?: string
27
+ respCd?: string
28
+ reqIpAddr?: string
29
+ }
30
+
31
+ export function getUserInfoApi(id: number) {
32
+ return request<UserInfo>({ url: `/user/${id}` })
33
+ }
34
+
35
+ export function getOrgByUserNameApi(username: string) {
36
+ return request<UserOrg[]>({
37
+ url: '/uaa/user/getOrgByUserName',
38
+ method: 'POST',
39
+ params: {
40
+ username,
41
+ },
42
+ })
43
+ }
44
+
45
+ export function getLastLoginTimeApi() {
46
+ return request<LastLoginTimeInfo>({
47
+ url: '/uaa/log/lastLoginTime',
48
+ method: 'GET',
49
+ })
50
+ }
51
+
52
+ export function loginApi(data: { username: string; password: string }) {
53
+ return request<AuthTokenResponse>({
54
+ url: '/uaa/oauth/token',
55
+ method: 'POST',
56
+ data,
57
+ auth: {
58
+ username: 'client',
59
+ password: 'secret',
60
+ },
61
+ skipAuth: true,
62
+ })
63
+ }
64
+ /**
65
+ * 通过敏行token换取业务登录信息
66
+ * @param appToken
67
+ */
68
+ export function loginByAppTokenApi(appToken: string) {
69
+ return request<AuthTokenResponse>({
70
+ url: '/uaa/oauth/mobile/token',
71
+ method: 'POST',
72
+ data: {
73
+ token: appToken,
74
+ },
75
+ skipAuth: true,
76
+ })
77
+ }
78
+
79
+ /**
80
+ * 通过 refresh token 刷新业务登录信息
81
+ * @param refreshToken
82
+ */
83
+ export function refreshMobileTokenApi(refreshToken: string) {
84
+ return request<AuthTokenResponse>({
85
+ url: REFRESH_TOKEN_URL,
86
+ method: 'POST',
87
+ data: {
88
+ refreshToken,
89
+ },
90
+ skipAuth: true,
91
+ })
92
+ }