vue3-element-plus-app-chu 0.0.16 → 0.0.18

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/README.md CHANGED
@@ -16,7 +16,7 @@ pnpm dev:backend # 只启动后端(backend/ 目录,tsx watch)
16
16
 
17
17
  应用外壳位于 `src/layout/index.vue`,由 `App.vue` 通过 `RouterView` 挂载,统一承载侧边导航、折叠状态和业务页面内容。菜单配置在 `src/router/menus.ts`,路由表在 `src/router/index.ts`,新增业务页面时两处各追加一项即可。业务地址、浏览器前进后退和刷新都由 vue-router 驱动;头寸预报列表页由 `KeepAlive` 缓存,返回时保留筛选和分页状态。
18
18
 
19
- “注资/预注资管理”为一级分组菜单,下设“数字人民币注资明细查询”和“数字人民币账户行余额查询申请”。页面目录统一放在 `src/view/dcps/injection-management/` 下,路由分别为 `/injection-management/injection` 和 `/injection-management/balance`;旧地址 `/injection`、`/balance` 继续可用。
19
+ “注资/预注资管理”为一级分组菜单,下设“数字人民币注资明细查询”和“数字人民币账户行余额查询申请”。页面目录统一放在 `src/view/dcps/funding/` 下,路由分别为 `/funding/injection` 和 `/funding/balance`;旧地址 `/injection`、`/balance` 继续可用。
20
20
 
21
21
  ## 数字人民币头寸预报
22
22
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "vue3-element-plus-app-chu",
3
- "version": "0.0.16",
3
+ "version": "0.0.18",
4
4
  "private": false,
5
5
  "type": "module",
6
6
  "files": [
@@ -1,9 +1,9 @@
1
1
  import { createRouter, createWebHistory, type RouteRecordRaw } from 'vue-router'
2
2
  import AppLayout from '@/layout/index.vue'
3
3
  import DigitalRmbAuthorization from '@/view/dcps/auth/index.vue'
4
- import DigitalRmbAccountBalance from '@/view/dcps/injection-management/balance/index.vue'
4
+ import DigitalRmbAccountBalance from '@/view/dcps/funding/balance/index.vue'
5
5
  import DigitalRmbForecast from '@/view/dcps/forecast/index.vue'
6
- import DigitalRmbInjection from '@/view/dcps/injection-management/injection/index.vue'
6
+ import DigitalRmbInjection from '@/view/dcps/funding/injection/index.vue'
7
7
  import DigitalRmbWriteOff from '@/view/dcps/write-off/index.vue'
8
8
  import DigitalRmbPositionEstimation from '@/view/dcps/estimation/index.vue'
9
9
 
@@ -65,8 +65,8 @@ const routes: RouteRecordRaw[] = [
65
65
  meta: { menu: 'estimation', title: '数字人民币头寸匡算' },
66
66
  },
67
67
  {
68
- path: 'injection-management',
69
- name: 'injection-management',
68
+ path: 'funding',
69
+ name: 'funding',
70
70
  redirect: { name: 'injection' },
71
71
  meta: { title: '注资/预注资管理' },
72
72
  children: [
@@ -15,7 +15,7 @@ export const layoutMenus: LayoutMenu[] = [
15
15
  { name: 'forecast', title: '数字人民币头寸预报', compactTitle: '头寸预报' },
16
16
  { name: 'estimation', title: '数字人民币头寸匡算', compactTitle: '匡算' },
17
17
  {
18
- name: 'injection-management',
18
+ name: 'funding',
19
19
  title: '注资/预注资管理',
20
20
  compactTitle: '注资管理',
21
21
  children: [
@@ -1,8 +1,10 @@
1
1
  # DCPS 页面文件结构
2
2
 
3
- `src/view/dcps` 下每个业务页面统一保持三个文件,不再拆分子组件、工具文件或运行时配置:
3
+ `src/view/dcps` 下每个业务页面统一保持三个文件,不再拆分子组件、工具文件:
4
4
 
5
- 一级菜单为分组时,页面放在该分组目录下。例如“注资/预注资管理”的两个页面分别位于 `injection-management/injection/` 和 `injection-management/balance/`,各自保留下面三个文件。
5
+ 跨页面共用的运行时配置(默认查询日期、审批人等)和公共日期工具统一放在 `src/view/dcps/runtime.ts`,页面按需通过 `../runtime`(分组子页面为 `../../runtime`)引入;各页面不再内联重复定义。
6
+
7
+ 一级菜单为分组时,页面放在该分组目录下。例如“注资/预注资管理”的两个页面分别位于 `funding/injection/` 和 `funding/balance/`,各自保留下面三个文件。
6
8
 
7
9
  | 文件 | 用途 |
8
10
  | --- | --- |
@@ -30,9 +32,9 @@
30
32
  | `/forecast/:predRefNo/edit` | `forecast-edit` | `forecast/index.vue` | 修改(`mode: 'edit'`) | 修改数字人民币头寸预报 |
31
33
  | `/forecast/:predRefNo` | `forecast-detail` | `forecast/index.vue` | 详情(`mode: 'detail'`) | 数字人民币头寸预报详情 |
32
34
  | `/estimation` | `estimation` | `estimation/index.vue` | 页面 | 数字人民币头寸匡算 |
33
- | `/injection-management` | `injection-management` | — | 重定向到 `injection` | 注资/预注资管理 |
34
- | `/injection-management/injection` | `injection` | `injection-management/injection/index.vue` | 页面 | 数字人民币注资明细查询 |
35
- | `/injection-management/balance` | `balance` | `injection-management/balance/index.vue` | 页面 | 数字人民币账户行余额查询申请 |
35
+ | `/funding` | `funding` | — | 重定向到 `injection` | 注资/预注资管理 |
36
+ | `/funding/injection` | `injection` | `funding/injection/index.vue` | 页面 | 数字人民币注资明细查询 |
37
+ | `/funding/balance` | `balance` | `funding/balance/index.vue` | 页面 | 数字人民币账户行余额查询申请 |
36
38
  | `/auth` | `auth` | `auth/index.vue` | 页面 | 数字人民币授权 |
37
39
  | `/write-off` | `write-off` | `write-off/index.vue` | 页面 | 数字人民币核销 |
38
40
  | `/` | — | 重定向到 `forecast` | — | — |
@@ -43,13 +45,13 @@
43
45
  - 头寸预报的列表、新增、修改、详情共用 `forecast/index.vue`,通过路由 `props.mode` 切换页面形态;修改和详情通过 `props.predRefNo` 接收路由参数。
44
46
  - `forecast/index.vue` 顶部使用一个普通 `<script>` 块保存列表记录缓存,跳转修改或详情前暂存列表行,用于补齐详情接口未返回的字段。
45
47
  - 侧边菜单配置在 `src/router/menus.ts`,其中 `name` 必须与对应路由的 `name` 保持一致;分组菜单通过 `children` 配置二级页面,页面的 `meta.menu` 指向自己的菜单项。
46
- - “注资/预注资管理”对应 `injection-management` 分组,包含注资明细查询和账户行余额查询申请两个页面;访问子页面时自动展开父菜单。旧地址 `/injection`、`/balance` 保留为对应页面的别名。
48
+ - “注资/预注资管理”对应 `funding` 分组,包含注资明细查询和账户行余额查询申请两个页面;访问子页面时自动展开父菜单。旧地址 `/injection`、`/balance` 保留为对应页面的别名。
47
49
  - `src/layout/index.vue` 使用 `<KeepAlive include="DcpsForecastPage">` 缓存头寸预报页面;新增、修改、详情按路由 `key` 分别缓存,返回列表时自动重新查询。
48
50
 
49
51
  ## 新增页面检查清单
50
52
 
51
53
  1. 在 `src/view/dcps/<模块>/` 下新建 `index.vue`;如归属某个分组,放在 `src/view/dcps/<分组>/<模块>/` 下,并添加 `defineOptions({ name: 'Dcps<模块>Page' })`。
52
- 2. 同目录补充 `api.ts`、`typs.ts`;不要再创建 `components/`、`utils.ts`、`runtime.ts` 等额外文件。
54
+ 2. 同目录补充 `api.ts`、`typs.ts`;不要再创建 `components/`、`utils.ts` 等额外文件。默认日期、审批人等运行时默认值统一加入根目录 `runtime.ts`,不要在页面里重复定义。
53
55
  3. 弹窗、子表格、表单直接写在 `index.vue` 中;工具函数写在 `index.vue` 的 `<script setup>` 内。
54
56
  4. 在 `src/router/index.ts` 中新增路由;分组页面添加到对应分组路由的 `children` 下,配置 `path`、`name`、`component`、`meta.menu`、`meta.title`。
55
57
  5. 如需出现在侧边菜单,在 `src/router/menus.ts` 中追加菜单项或添加到分组的 `children` 中,`name` 与对应路由名一致。
@@ -3,19 +3,12 @@ import { computed, onBeforeUnmount, onMounted, reactive, ref } from 'vue'
3
3
  import { ElMessage } from 'element-plus'
4
4
  import { ArtDataTable, type ColumnOption, type PaginationOptions, type TableSettings } from '@/components/table'
5
5
  import API from './api'
6
+ import { authRuntime } from '../runtime'
6
7
  import type { AuthorizationFilters, AuthorizationQueryParams, AuthorizationTask } from './typs'
7
8
 
8
9
  defineOptions({ name: 'DcpsAuthPage' })
9
10
 
10
11
  type Decision = 'approve' | 'reject'
11
-
12
- // 授权页面的审批人和默认创建日期;日期格式为 YYYYMMDD。
13
- const authorizationRuntime = {
14
- approverId: '10092', // 审批人工号。
15
- approverName: '王干事', // 审批人姓名。
16
- createTmBegin: '20261012', // 默认创建开始日期。
17
- createTmEnd: '20261012', // 默认创建结束日期。
18
- }
19
12
  type AmountSortOrder = 'ascending' | 'descending' | null
20
13
 
21
14
  // 初始查询条件;空字符串表示不限制该条件,重置时恢复此配置。
@@ -28,8 +21,8 @@ const defaultFilters: AuthorizationFilters = {
28
21
  }
29
22
  // 默认创建日期范围:[开始日期, 结束日期],格式为 YYYYMMDD,查询重置时使用。
30
23
  const defaultDates: [string, string] = [
31
- authorizationRuntime.createTmBegin,
32
- authorizationRuntime.createTmEnd,
24
+ authRuntime.createTmBegin,
25
+ authRuntime.createTmEnd,
33
26
  ]
34
27
 
35
28
  // 重复输入项共用一份配置,依次为字段、名称和长度限制。
@@ -277,8 +270,8 @@ const getQueryFilters = () => ({
277
270
  payeeName: filters.value.payeeName.trim(), // 收款人名称。
278
271
  platfSeqNo: filters.value.platfSeqNo.trim(), // 平台流水号。
279
272
  taskSts: filters.value.taskSts, // 任务状态,空值表示全部。
280
- createTmBegin: dateRange.value?.[0] || authorizationRuntime.createTmBegin, // 创建开始日期,格式为 YYYYMMDD,未选择时取默认值。
281
- createTmEnd: dateRange.value?.[1] || dateRange.value?.[0] || authorizationRuntime.createTmEnd, // 创建结束日期,格式为 YYYYMMDD,缺失时回退到开始日期或默认值。
273
+ createTmBegin: dateRange.value?.[0] || authRuntime.createTmBegin, // 创建开始日期,格式为 YYYYMMDD,未选择时取默认值。
274
+ createTmEnd: dateRange.value?.[1] || dateRange.value?.[0] || authRuntime.createTmEnd, // 创建结束日期,格式为 YYYYMMDD,缺失时回退到开始日期或默认值。
282
275
  })
283
276
  // 仅查询、重置时更新;翻页和刷新沿用这份条件。
284
277
  let appliedQuery = getQueryFilters()
@@ -362,8 +355,8 @@ const openDecisionDialog = (task: any) => {
362
355
  const submitDecision = async (decision: Decision) => {
363
356
  const platfSeqNo = selectedTask.value?.platfSeqNo?.trim() // 本次审批任务的平台流水号,用于唯一定位任务。
364
357
  if (!canApprove(selectedTask.value) || !platfSeqNo || pendingDecision.value || loading.value) return
365
- const approverId = authorizationRuntime.approverId.trim() // 本次提交的审批人工号,同时作为公共用户标识。
366
- const approverName = authorizationRuntime.approverName.trim() // 本次提交的审批人姓名。
358
+ const approverId = authRuntime.approverId.trim() // 本次提交的审批人工号,同时作为公共用户标识。
359
+ const approverName = authRuntime.approverName.trim() // 本次提交的审批人姓名。
367
360
  const remarkText = remark.value.trim() // 去除首尾空白后的备注或拒绝原因。
368
361
  if (!approverId || !approverName) {
369
362
  ElMessage.warning('审批人信息未设置')
@@ -578,12 +571,12 @@ onBeforeUnmount(() => {
578
571
  <el-row :gutter="14">
579
572
  <el-col :xs="24" :sm="12">
580
573
  <el-form-item label="审批人工号">
581
- <el-input :model-value="authorizationRuntime.approverId" disabled />
574
+ <el-input :model-value="authRuntime.approverId" disabled />
582
575
  </el-form-item>
583
576
  </el-col>
584
577
  <el-col :xs="24" :sm="12">
585
578
  <el-form-item label="审批人姓名">
586
- <el-input :model-value="authorizationRuntime.approverName" readonly />
579
+ <el-input :model-value="authRuntime.approverName" readonly />
587
580
  </el-form-item>
588
581
  </el-col>
589
582
  </el-row>
@@ -2,6 +2,7 @@
2
2
  import { computed, onBeforeUnmount, onMounted, reactive, ref } from 'vue'
3
3
  import { ElMessage } from 'element-plus'
4
4
  import API from './api'
5
+ import { getToday } from '../runtime'
5
6
  import type {
6
7
  EstimationAmounts, EstimationCell, EstimationPredRow, EstimationQueryParams, EstimationTranRow,
7
8
  } from './typs'
@@ -40,15 +41,6 @@ const getErrorMessage = (error: unknown): string => {
40
41
  return '操作失败,请稍后重试'
41
42
  }
42
43
 
43
- /** 业务日期始终按上海时区生成,不依赖浏览器所在时区,格式为 YYYYMMDD。 */
44
- const getToday = (): string => {
45
- const parts = new Intl.DateTimeFormat('en-CA', {
46
- timeZone: 'Asia/Shanghai', year: 'numeric', month: '2-digit', day: '2-digit',
47
- }).formatToParts(new Date())
48
- const read = (type: Intl.DateTimeFormatPartTypes) => parts.find((part) => part.type === type)?.value || ''
49
- return read('year') + read('month') + read('day')
50
- }
51
-
52
44
  /** 判断是否为合法的 YYYYMMDD 日期。 */
53
45
  const isValidDate = (value: string): boolean => {
54
46
  if (!/^\d{8}$/.test(value)) return false
@@ -24,6 +24,7 @@ import { computed, onActivated, onBeforeUnmount, reactive, ref, watch } from 'vu
24
24
  import { useRouter } from 'vue-router'
25
25
  import { ElMessage, ElMessageBox } from 'element-plus'
26
26
  import API from './api'
27
+ import { forecastRuntime, getToday } from '../runtime'
27
28
  import { ArtDataTable, type ColumnOption, type PaginationOptions, type TableSettings } from '@/components/table'
28
29
  import type {
29
30
  ApiResponse,
@@ -78,15 +79,6 @@ const getErrorMessage = (error: unknown): string => {
78
79
  return '操作失败,请稍后重试'
79
80
  }
80
81
 
81
- /** 业务日期始终按上海时区生成,不依赖浏览器所在时区,格式为 YYYYMMDD。 */
82
- const getToday = (): string => {
83
- const parts = new Intl.DateTimeFormat('en-CA', {
84
- timeZone: 'Asia/Shanghai', year: 'numeric', month: '2-digit', day: '2-digit',
85
- }).formatToParts(new Date())
86
- const read = (type: Intl.DateTimeFormatPartTypes) => parts.find((part) => part.type === type)?.value || ''
87
- return read('year') + read('month') + read('day')
88
- }
89
-
90
82
  /** 判断是否为合法的 YYYYMMDD 日期。 */
91
83
  const isValidDate = (value: string): boolean => {
92
84
  if (!/^\d{8}$/.test(value)) return false
@@ -225,7 +217,7 @@ onBeforeUnmount(() => { disposed = true })
225
217
 
226
218
  type ListMutation = 'delete' | null
227
219
  const createFilters = (): ForecastFilters => ({
228
- tranDate: getToday(), clientName: '', competName: '', payDirec: '', busiType: '', payChannel: '',
220
+ tranDate: forecastRuntime.tranDate, clientName: '', competName: '', payDirec: '', busiType: '', payChannel: '',
229
221
  groundBranch: '', predStatus: '', verifyStatus: '', startTransAmt: '', endTransAmt: '', sortRule: '',
230
222
  })
231
223
  const listFilters = ref(createFilters())
@@ -245,7 +245,7 @@ onBeforeUnmount(() => {
245
245
  <span v-if="lastQueryTime" class="balance-updated">最近查询:{{ lastQueryTime }}</span>
246
246
  <span class="balance-actions">
247
247
  <el-button @click="openCreateDialog">注资/预注资发起</el-button>
248
- <el-button type="primary" :loading="loading">查询</el-button>
248
+ <el-button type="primary" :loading="loading" @click="query()">查询</el-button>
249
249
  </span>
250
250
  </div>
251
251
  </el-card>
@@ -0,0 +1,35 @@
1
+ /**
2
+ * dcps 各页面共用的运行时配置;默认日期、审批人等全局默认值统一维护在本文件,
3
+ * 页面通过 `../runtime`(或分组子页面的 `../../runtime`)按需引入。
4
+ */
5
+
6
+ /**
7
+ * 业务日期始终按上海时区生成,不依赖浏览器所在时区,格式为 YYYYMMDD。
8
+ * 供各页面的默认查询日期和新增表单初始值使用。
9
+ */
10
+ export const getToday = (): string => {
11
+ const parts = new Intl.DateTimeFormat('en-CA', {
12
+ timeZone: 'Asia/Shanghai', year: 'numeric', month: '2-digit', day: '2-digit',
13
+ }).formatToParts(new Date())
14
+ const read = (type: Intl.DateTimeFormatPartTypes) => parts.find((part) => part.type === type)?.value || ''
15
+ return read('year') + read('month') + read('day')
16
+ }
17
+
18
+ /** 预报页面的默认查询日期;日期格式为 YYYYMMDD。 */
19
+ export const forecastRuntime = {
20
+ tranDate: getToday(), // 默认交易日期,查询和重置时使用。
21
+ }
22
+
23
+ /** 授权页面的审批人和默认创建日期;日期格式为 YYYYMMDD,当前使用固定日期。 */
24
+ export const authRuntime = {
25
+ approverId: '10092', // 审批人工号。
26
+ approverName: '王干事', // 审批人姓名。
27
+ createTmBegin: '20261012', // 默认创建开始日期。
28
+ createTmEnd: '20261012', // 默认创建结束日期。
29
+ }
30
+
31
+ /** 按模块名聚合的运行时配置;也可从本文件直接引入单个模块的配置。 */
32
+ export default {
33
+ forecast: forecastRuntime,
34
+ auth: authRuntime,
35
+ }
@@ -2,6 +2,7 @@
2
2
  import { computed, onBeforeUnmount, onMounted, reactive, ref } from 'vue'
3
3
  import { ElMessage, ElMessageBox } from 'element-plus'
4
4
  import API from './api'
5
+ import { getToday } from '../runtime'
5
6
  import { ArtDataTable, type ColumnOption, type PaginationOptions, type TableSettings } from '@/components/table'
6
7
  import type {
7
8
  CancelWriteOffPredItem, EditVerifyFormValues, FlowRow, ForecastRow, WriteOffFlowInput, WriteOffForecastItem, WriteOffItemInput,
@@ -51,15 +52,6 @@ const getErrorMessage = (error: unknown): string => {
51
52
  return '操作失败,请稍后重试'
52
53
  }
53
54
 
54
- /** 业务日期始终按上海时区生成,不依赖浏览器所在时区,格式为 YYYYMMDD。 */
55
- const getToday = (): string => {
56
- const parts = new Intl.DateTimeFormat('en-CA', {
57
- timeZone: 'Asia/Shanghai', year: 'numeric', month: '2-digit', day: '2-digit',
58
- }).formatToParts(new Date())
59
- const read = (type: Intl.DateTimeFormatPartTypes) => parts.find((part) => part.type === type)?.value || ''
60
- return read('year') + read('month') + read('day')
61
- }
62
-
63
55
  /** 判断是否为合法的 YYYYMMDD 日期。 */
64
56
  const isValidDate = (value: string): boolean => {
65
57
  if (!/^\d{8}$/.test(value)) return false