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,221 @@
1
+ <script setup lang="ts">
2
+ import { useAppStore } from '@/stores/app'
3
+ import { showAppToast } from '@/utils/toast'
4
+
5
+ defineOptions({ name: 'RmbPositionCreatePage' })
6
+
7
+ type PendingForecast = {
8
+ institution: string
9
+ date: string
10
+ customerType: string
11
+ business: string
12
+ amount: number
13
+ }
14
+
15
+ const route = useRoute()
16
+ const router = useRouter()
17
+ const appStore = useAppStore()
18
+ const pendingForecastKey = 'rmb-position:pending-create'
19
+
20
+ const form = reactive({
21
+ tranDate: getInitialTranDate(),
22
+ institution: '北京银行总行核算中心',
23
+ customerType: '其他用户',
24
+ business: '',
25
+ amount: '',
26
+ })
27
+
28
+ const submitting = ref(false)
29
+
30
+ function getInitialTranDate() {
31
+ const tranDate = route.query.tranDate
32
+
33
+ if (typeof tranDate === 'string' && /^\d{4}-\d{2}-\d{2}$/.test(tranDate)) {
34
+ return tranDate
35
+ }
36
+
37
+ return appStore.systemWorkDate
38
+ }
39
+
40
+ function parseAmount(value: string) {
41
+ if (!value.trim()) return undefined
42
+
43
+ const amount = Number(value)
44
+ return Number.isFinite(amount) ? amount : undefined
45
+ }
46
+
47
+ function submitCreate() {
48
+ if (submitting.value) return
49
+
50
+ const amount = parseAmount(form.amount)
51
+
52
+ if (!form.tranDate) {
53
+ showAppToast('请选择交易日期')
54
+ return
55
+ }
56
+
57
+ if (!form.institution.trim() || !form.business.trim()) {
58
+ showAppToast('请补充落地机构和业务类型')
59
+ return
60
+ }
61
+
62
+ if (form.amount && amount === undefined) {
63
+ showAppToast('请输入正确的预报金额')
64
+ return
65
+ }
66
+
67
+ submitting.value = true
68
+
69
+ const pendingForecast: PendingForecast = {
70
+ institution: form.institution.trim(),
71
+ date: form.tranDate,
72
+ customerType: form.customerType.trim() || '其他用户',
73
+ business: form.business.trim(),
74
+ amount: amount ?? 0,
75
+ }
76
+
77
+ sessionStorage.setItem(pendingForecastKey, JSON.stringify(pendingForecast))
78
+ showAppToast('新增预报成功')
79
+ router.replace({ name: 'RmbPosition' })
80
+ }
81
+ </script>
82
+
83
+ <template>
84
+ <main class="create-page">
85
+ <section class="form-card" aria-label="新增本币预报表单">
86
+ <van-cell-group inset class="forecast-form">
87
+ <van-field
88
+ v-model="form.tranDate"
89
+ label="交易日期"
90
+ type="date"
91
+ inputmode="numeric"
92
+ placeholder="请选择交易日期"
93
+ />
94
+ <van-field v-model.trim="form.institution" label="落地机构" placeholder="请输入落地机构" />
95
+ <van-field v-model.trim="form.customerType" label="客户类型" placeholder="请输入客户类型" />
96
+ <van-field v-model.trim="form.business" label="业务类型" placeholder="请输入业务类型" />
97
+ <van-field
98
+ v-model.trim="form.amount"
99
+ label="预报金额"
100
+ type="number"
101
+ inputmode="decimal"
102
+ placeholder="请输入金额"
103
+ >
104
+ <template #right-icon>亿元</template>
105
+ </van-field>
106
+ </van-cell-group>
107
+ </section>
108
+
109
+ <footer class="action-bar">
110
+ <button class="cancel-btn" type="button" @click="router.back()">取消</button>
111
+ <button class="submit-btn" type="button" :disabled="submitting" @click="submitCreate">
112
+ 确认新增
113
+ </button>
114
+ </footer>
115
+ </main>
116
+ </template>
117
+
118
+ <style scoped>
119
+ .create-page {
120
+ width: 100%;
121
+ max-width: 750px;
122
+ min-height: var(--app-page-min-height, 100vh);
123
+ margin: 0 auto;
124
+ padding: 13px 13px calc(env(safe-area-inset-bottom, 0px) + 88px);
125
+ color: #080d1f;
126
+ background:
127
+ radial-gradient(circle at 50% 0%, rgba(255, 242, 243, 0.92), transparent 118px),
128
+ linear-gradient(180deg, #ffffff 0%, #fbfcfd 54%, #ffffff 100%);
129
+ box-sizing: border-box;
130
+ }
131
+
132
+ .form-card {
133
+ margin-top: 15px;
134
+ border-radius: 13px;
135
+ padding: 8px 0;
136
+ background: rgba(255, 255, 255, 0.96);
137
+ box-shadow: 0 7px 22px rgba(21, 28, 45, 0.055);
138
+ }
139
+
140
+ .forecast-form {
141
+ margin: 0;
142
+ overflow: hidden;
143
+ border-radius: 13px;
144
+ background: transparent;
145
+ }
146
+
147
+ .forecast-form :deep(.van-cell) {
148
+ min-height: 56px;
149
+ align-items: center;
150
+ padding: 10px 14px;
151
+ background: transparent;
152
+ }
153
+
154
+ .forecast-form :deep(.van-field__label) {
155
+ width: 72px;
156
+ color: #111728;
157
+ font-size: 14px;
158
+ font-weight: 650;
159
+ }
160
+
161
+ .forecast-form :deep(.van-field__control) {
162
+ color: #202638;
163
+ font-size: 14px;
164
+ text-align: right;
165
+ }
166
+
167
+ .forecast-form :deep(.van-field__right-icon) {
168
+ min-width: 28px;
169
+ color: #7f8798;
170
+ font-size: 12px;
171
+ text-align: right;
172
+ }
173
+
174
+ .action-bar {
175
+ position: fixed;
176
+ right: max(13px, calc((100vw - 750px) / 2 + 13px));
177
+ bottom: calc(env(safe-area-inset-bottom, 0px) + 14px);
178
+ left: max(13px, calc((100vw - 750px) / 2 + 13px));
179
+ z-index: 20;
180
+ display: grid;
181
+ grid-template-columns: 96px 1fr;
182
+ gap: 10px;
183
+ }
184
+
185
+ .cancel-btn,
186
+ .submit-btn {
187
+ display: flex;
188
+ align-items: center;
189
+ justify-content: center;
190
+ height: 44px;
191
+ border-radius: 22px;
192
+ font-size: 15px;
193
+ font-weight: 650;
194
+ }
195
+
196
+ .cancel-btn {
197
+ border: 1px solid #e5e8ef;
198
+ color: #303747;
199
+ background: rgba(255, 255, 255, 0.94);
200
+ }
201
+
202
+ .submit-btn {
203
+ color: #ffffff;
204
+ background: linear-gradient(135deg, #ff3340 0%, #ff1d34 100%);
205
+ box-shadow: 0 9px 18px rgba(255, 36, 52, 0.18);
206
+ }
207
+
208
+ .submit-btn:disabled {
209
+ opacity: 0.68;
210
+ }
211
+
212
+ @media (max-width: 340px) {
213
+ .forecast-form :deep(.van-field__label) {
214
+ width: 64px;
215
+ }
216
+
217
+ .action-bar {
218
+ grid-template-columns: 82px 1fr;
219
+ }
220
+ }
221
+ </style>
@@ -0,0 +1,355 @@
1
+ <script setup lang="ts">
2
+ import {
3
+ buildRmbForecastDetailPayload,
4
+ queryRmbForecastDetail,
5
+ type RmbForecastDetailRecord,
6
+ } from '@/api/rmb-position'
7
+ import {
8
+ formatForecastAmountText,
9
+ formatRmbForecastDate,
10
+ resolveBusinessType,
11
+ resolveClientType,
12
+ resolveForecastStatus,
13
+ } from '@/utils/rmb-forecast'
14
+ import { showAppToast } from '@/utils/toast'
15
+
16
+ defineOptions({ name: 'RmbPositionDetailPage' })
17
+
18
+ type DetailField = {
19
+ label: string
20
+ value: string
21
+ }
22
+
23
+ type DetailSection = {
24
+ title: string
25
+ fields: DetailField[]
26
+ }
27
+
28
+ const route = useRoute()
29
+ const router = useRouter()
30
+
31
+ const predRefNo = computed(() => String(route.params.predRefNo || ''))
32
+ const detail = ref<RmbForecastDetailRecord>()
33
+ const loading = ref(false)
34
+ const loadError = ref(false)
35
+ const statusOption = computed(() => resolveForecastStatus(detail.value?.predStatus))
36
+ const heroAmount = computed(() => formatForecastAmountText(detail.value?.predAmt))
37
+ const heroDate = computed(() => formatRmbForecastDate(detail.value?.tranDate))
38
+
39
+ const detailSections = computed<DetailSection[]>(() => {
40
+ const item = detail.value
41
+
42
+ if (!item) return []
43
+
44
+ return [
45
+ {
46
+ title: '基础信息',
47
+ fields: [
48
+ { label: '预报流水号', value: fieldText(item.predRefNo) },
49
+ { label: '交易日期', value: formatRmbForecastDate(item.tranDate) },
50
+ { label: '预报日期', value: formatRmbForecastDate(item.predDate) },
51
+ { label: '预报状态', value: statusOption.value.label },
52
+ { label: '核销状态', value: fieldText(item.verifyStatus) },
53
+ { label: '额度标志', value: fieldText(item.eduFlag) },
54
+ ],
55
+ },
56
+ {
57
+ title: '机构与人员',
58
+ fields: [
59
+ { label: '预报机构', value: fieldText(item.predBranchName || item.predBranch) },
60
+ { label: '预报机构代码', value: fieldText(item.predBranch) },
61
+ { label: '预报人员编号', value: fieldText(item.predCode) },
62
+ { label: '预报人员姓名', value: fieldText(item.predName) },
63
+ { label: '落地机构名称', value: fieldText(item.groundBranch) },
64
+ { label: '落地机构代码', value: fieldText(item.groundBranchCode) },
65
+ ],
66
+ },
67
+ {
68
+ title: '业务信息',
69
+ fields: [
70
+ { label: '业务类型', value: resolveBusinessType(item.busiType) },
71
+ { label: '客户类型', value: resolveClientType(item.clientType) },
72
+ { label: '客户名称', value: fieldText(item.clientName) },
73
+ { label: '交易对手名称', value: fieldText(item.competName) },
74
+ { label: '交易对手账号', value: fieldText(item.competAcct) },
75
+ { label: '标准名称', value: fieldText(item.standardName) },
76
+ { label: '用途', value: fieldText(item.purpose) },
77
+ { label: '备注', value: fieldText(item.remark) },
78
+ ],
79
+ },
80
+ {
81
+ title: '支付与金额',
82
+ fields: [
83
+ { label: '预报金额', value: formatForecastAmountText(item.predAmt) },
84
+ { label: '已核销金额', value: formatForecastAmountText(item.verifyAmt) },
85
+ { label: '支付渠道', value: fieldText(item.payChannel) },
86
+ { label: '收支方向', value: fieldText(item.payDirec) },
87
+ ],
88
+ },
89
+ {
90
+ title: '票据与联系',
91
+ fields: [
92
+ { label: '出票日', value: formatRmbForecastDate(item.billDate) },
93
+ { label: '票号', value: fieldText(item.billNo) },
94
+ { label: '联系人', value: fieldText(item.linkMan) },
95
+ { label: '联系电话', value: fieldText(item.phoneNo) },
96
+ ],
97
+ },
98
+ ]
99
+ })
100
+
101
+ onMounted(() => {
102
+ loadDetail()
103
+ })
104
+
105
+ async function loadDetail() {
106
+ if (!predRefNo.value) {
107
+ loadError.value = true
108
+ return
109
+ }
110
+
111
+ loading.value = true
112
+ loadError.value = false
113
+
114
+ const payload = buildRmbForecastDetailPayload(predRefNo.value)
115
+ console.log('[人民币预报详情入参]', payload)
116
+
117
+ try {
118
+ const response = await queryRmbForecastDetail(payload)
119
+ detail.value = response.body
120
+ } catch (error) {
121
+ console.error('[人民币预报详情加载失败]', error)
122
+ loadError.value = true
123
+ showAppToast('详情加载失败,请重试')
124
+ } finally {
125
+ loading.value = false
126
+ }
127
+ }
128
+
129
+ function fieldText(value?: string) {
130
+ const text = value?.trim()
131
+ return text || '-'
132
+ }
133
+ </script>
134
+
135
+ <template>
136
+ <main class="detail-page">
137
+ <section v-if="loading" class="state-section">
138
+ <van-loading vertical>加载中...</van-loading>
139
+ </section>
140
+
141
+ <template v-else-if="detail">
142
+ <section class="hero-card" aria-label="预报详情概要">
143
+ <div class="hero-topline">
144
+ <span class="status-tag" :class="statusOption.className">{{ statusOption.label }}</span>
145
+ <span class="hero-date">{{ heroDate }}</span>
146
+ </div>
147
+ <strong>{{ heroAmount }}</strong>
148
+ <p>{{ detail.predRefNo || predRefNo }}</p>
149
+ </section>
150
+
151
+ <section
152
+ v-for="section in detailSections"
153
+ :key="section.title"
154
+ class="detail-card"
155
+ :aria-label="section.title"
156
+ >
157
+ <h2>{{ section.title }}</h2>
158
+ <dl class="detail-list">
159
+ <div v-for="field in section.fields" :key="`${section.title}-${field.label}`">
160
+ <dt>{{ field.label }}</dt>
161
+ <dd>{{ field.value }}</dd>
162
+ </div>
163
+ </dl>
164
+ </section>
165
+ </template>
166
+
167
+ <van-empty v-else image="error" :description="loadError ? '详情加载失败' : '详情不存在'">
168
+ <van-button v-if="loadError" round type="danger" @click="loadDetail">重试</van-button>
169
+ <van-button v-else round type="danger" @click="router.replace('/rmb-position')">
170
+ 返回列表
171
+ </van-button>
172
+ </van-empty>
173
+ </main>
174
+ </template>
175
+
176
+ <style scoped>
177
+ .detail-page {
178
+ width: 100%;
179
+ max-width: 750px;
180
+ min-height: var(--app-page-min-height, 100vh);
181
+ margin: 0 auto;
182
+ padding: 13px 13px calc(env(safe-area-inset-bottom, 0px) + 24px);
183
+ color: #080d1f;
184
+ background:
185
+ radial-gradient(circle at 50% 0%, rgba(255, 242, 243, 0.92), transparent 118px),
186
+ linear-gradient(180deg, #ffffff 0%, #fbfcfd 54%, #ffffff 100%);
187
+ box-sizing: border-box;
188
+ }
189
+
190
+ button {
191
+ border: 0;
192
+ padding: 0;
193
+ background: transparent;
194
+ appearance: none;
195
+ }
196
+
197
+ .state-section {
198
+ display: flex;
199
+ justify-content: center;
200
+ padding-top: 120px;
201
+ }
202
+
203
+ .hero-card {
204
+ margin-top: 15px;
205
+ border-radius: 13px;
206
+ padding: 16px;
207
+ color: #ffffff;
208
+ background: linear-gradient(135deg, #f22f3d 0%, #ff5660 100%);
209
+ box-shadow: 0 13px 28px rgba(244, 29, 48, 0.18);
210
+ }
211
+
212
+ .hero-topline {
213
+ display: flex;
214
+ align-items: center;
215
+ justify-content: space-between;
216
+ gap: 10px;
217
+ }
218
+
219
+ .hero-card strong {
220
+ display: block;
221
+ margin-top: 18px;
222
+ font-size: 27px;
223
+ font-weight: 800;
224
+ line-height: 1.1;
225
+ }
226
+
227
+ .hero-card p {
228
+ overflow: hidden;
229
+ margin: 12px 0 0;
230
+ color: rgba(255, 255, 255, 0.82);
231
+ font-size: 12px;
232
+ line-height: 1.3;
233
+ text-overflow: ellipsis;
234
+ white-space: nowrap;
235
+ }
236
+
237
+ .hero-date {
238
+ color: rgba(255, 255, 255, 0.88);
239
+ font-size: 13px;
240
+ font-weight: 650;
241
+ }
242
+
243
+ .detail-card {
244
+ margin-top: 10px;
245
+ border-radius: 13px;
246
+ padding: 15px;
247
+ background: rgba(255, 255, 255, 0.96);
248
+ box-shadow: 0 7px 22px rgba(21, 28, 45, 0.055);
249
+ }
250
+
251
+ .detail-card h2 {
252
+ margin: 0;
253
+ color: #111728;
254
+ font-size: 15px;
255
+ font-weight: 760;
256
+ line-height: 1.2;
257
+ }
258
+
259
+ .detail-list {
260
+ margin: 12px 0 0;
261
+ }
262
+
263
+ .detail-list div {
264
+ display: grid;
265
+ grid-template-columns: 96px minmax(0, 1fr);
266
+ gap: 12px;
267
+ padding: 10px 0;
268
+ border-top: 1px solid #eef0f4;
269
+ }
270
+
271
+ .detail-list div:first-child {
272
+ border-top: 0;
273
+ }
274
+
275
+ .detail-list dt,
276
+ .detail-list dd {
277
+ margin: 0;
278
+ font-size: 13px;
279
+ line-height: 1.42;
280
+ }
281
+
282
+ .detail-list dt {
283
+ color: #7f8798;
284
+ }
285
+
286
+ .detail-list dd {
287
+ overflow-wrap: anywhere;
288
+ color: #151827;
289
+ font-weight: 650;
290
+ text-align: right;
291
+ }
292
+
293
+ .status-tag {
294
+ display: inline-flex;
295
+ align-items: center;
296
+ justify-content: center;
297
+ min-height: 20px;
298
+ border: 1px solid transparent;
299
+ border-radius: 4px;
300
+ padding: 2px 7px;
301
+ font-size: 11px;
302
+ font-weight: 650;
303
+ line-height: 1.25;
304
+ white-space: nowrap;
305
+ }
306
+
307
+ .status-tag-normal {
308
+ border-color: #b7ebc9;
309
+ color: #0b8f3a;
310
+ background: #e4f8eb;
311
+ }
312
+
313
+ .status-tag-delayed {
314
+ border-color: #ffd99a;
315
+ color: #a05a00;
316
+ background: #fff4d8;
317
+ }
318
+
319
+ .status-tag-normal-delete {
320
+ border-color: #b7d7ff;
321
+ color: #1d5fbf;
322
+ background: #e6f0ff;
323
+ }
324
+
325
+ .status-tag-normal-delay-delete {
326
+ border-color: #d5c2ff;
327
+ color: #6e43c4;
328
+ background: #f0eaff;
329
+ }
330
+
331
+ .status-tag-delayed-late-delete {
332
+ border-color: #ffc0cb;
333
+ color: #bf2549;
334
+ background: #ffe8ed;
335
+ }
336
+
337
+ .status-tag-late-delay-delete {
338
+ border-color: #a7dced;
339
+ color: #08768f;
340
+ background: #dff6fb;
341
+ }
342
+
343
+ .status-tag-unknown {
344
+ border-color: #d6dbe3;
345
+ color: #687083;
346
+ background: #f3f5f8;
347
+ }
348
+
349
+ @media (max-width: 340px) {
350
+ .detail-list div {
351
+ grid-template-columns: 84px minmax(0, 1fr);
352
+ gap: 8px;
353
+ }
354
+ }
355
+ </style>
@@ -0,0 +1,67 @@
1
+ <script setup lang="ts">
2
+ import { useAppStore } from '@/stores/app'
3
+
4
+ defineOptions({ name: 'SettingsPage' })
5
+
6
+ const appStore = useAppStore()
7
+
8
+ const showDashboardTab = computed({
9
+ get: () => appStore.showDashboardTab,
10
+ set: (value: boolean) => appStore.setShowDashboardTab(value),
11
+ })
12
+
13
+ const showAnnouncementTab = computed({
14
+ get: () => appStore.showAnnouncementTab,
15
+ set: (value: boolean) => appStore.setShowAnnouncementTab(value),
16
+ })
17
+ </script>
18
+
19
+ <template>
20
+ <main class="settings-page">
21
+ <section class="settings-section">
22
+ <van-cell-group inset>
23
+ <van-cell title="显示看板" label="控制底部导航栏是否显示看板入口" center>
24
+ <template #right-icon>
25
+ <van-switch v-model="showDashboardTab" size="22px" active-color="#f22f3d" />
26
+ </template>
27
+ </van-cell>
28
+ <van-cell title="显示公告" label="控制底部导航栏是否显示公告入口" center>
29
+ <template #right-icon>
30
+ <van-switch v-model="showAnnouncementTab" size="22px" active-color="#f22f3d" />
31
+ </template>
32
+ </van-cell>
33
+ </van-cell-group>
34
+ </section>
35
+ </main>
36
+ </template>
37
+
38
+ <style scoped>
39
+ .settings-page {
40
+ width: 100%;
41
+ max-width: 750px;
42
+ min-height: var(--app-page-min-height, 100vh);
43
+ margin: 0 auto;
44
+ padding: 14px 11px 28px;
45
+ color: #171b20;
46
+ background: #f7f8fa;
47
+ box-sizing: border-box;
48
+ }
49
+
50
+ .settings-section {
51
+ margin-top: 0;
52
+ }
53
+
54
+ .settings-section :deep(.van-cell-group--inset) {
55
+ margin: 0;
56
+ border-radius: 8px;
57
+ }
58
+
59
+ .settings-section :deep(.van-cell) {
60
+ align-items: center;
61
+ min-height: 62px;
62
+ }
63
+
64
+ .settings-section :deep(.van-cell__title) {
65
+ min-width: 0;
66
+ }
67
+ </style>
@@ -0,0 +1,26 @@
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
+ .page-body {
18
+ padding: 24px 0;
19
+ }
20
+ .placeholder {
21
+ text-align: center;
22
+ color: #969799;
23
+ font-size: 14px;
24
+ padding-top: 120px;
25
+ }
26
+ </style>
@@ -0,0 +1,18 @@
1
+ {
2
+ "extends": "@vue/tsconfig/tsconfig.dom.json",
3
+ "include": ["env.d.ts", "auto-imports.d.ts", "components.d.ts", "src/**/*", "src/**/*.vue"],
4
+ "exclude": ["src/**/__tests__/*"],
5
+ "compilerOptions": {
6
+ // Extra safety for array and object lookups, but may have false positives.
7
+ "noUncheckedIndexedAccess": true,
8
+
9
+ // Path mapping for cleaner imports.
10
+ "paths": {
11
+ "@/*": ["./src/*"]
12
+ },
13
+
14
+ // `vue-tsc --build` produces a .tsbuildinfo file for incremental type-checking.
15
+ // Specified here to keep it out of the root directory.
16
+ "tsBuildInfoFile": "./node_modules/.tmp/tsconfig.app.tsbuildinfo"
17
+ }
18
+ }
package/tsconfig.json ADDED
@@ -0,0 +1,11 @@
1
+ {
2
+ "files": [],
3
+ "references": [
4
+ {
5
+ "path": "./tsconfig.node.json"
6
+ },
7
+ {
8
+ "path": "./tsconfig.app.json"
9
+ }
10
+ ]
11
+ }