@ysgroup/ui 0.1.25 → 0.1.27

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": "@ysgroup/ui",
3
- "version": "0.1.25",
3
+ "version": "0.1.27",
4
4
  "type": "module",
5
5
  "main": "src/index.ts",
6
6
  "types": "src/index.ts",
@@ -21,4 +21,4 @@
21
21
  "publishConfig": {
22
22
  "access": "public"
23
23
  }
24
- }
24
+ }
@@ -0,0 +1,25 @@
1
+ /** 各业务仓在启动时注册本系统表格列宽;查找只认 table.field,缺键告警并回退 140。 */
2
+
3
+ export type ColumnWidthMap = Record<string, Record<string, number>>;
4
+
5
+ const MISSING_WIDTH = 140;
6
+ let widths: ColumnWidthMap = {};
7
+ const warned = new Set<string>();
8
+
9
+ export function registerColumnWidths(map: ColumnWidthMap): void {
10
+ widths = map;
11
+ warned.clear();
12
+ }
13
+
14
+ export function columnWidth(table: string, field: string): number {
15
+ const width = widths[table]?.[field];
16
+ if (width == null) {
17
+ const key = `${table}.${field}`;
18
+ if (!warned.has(key)) {
19
+ warned.add(key);
20
+ console.warn(`[columnWidths] missing ${key}`);
21
+ }
22
+ return MISSING_WIDTH;
23
+ }
24
+ return width;
25
+ }
@@ -0,0 +1,30 @@
1
+ <script setup lang="ts">
2
+ import { CircleCheckFilled } from "@element-plus/icons-vue";
3
+
4
+ defineProps<{
5
+ value: unknown;
6
+ onLabel?: string;
7
+ offLabel?: string;
8
+ }>();
9
+ </script>
10
+
11
+ <template>
12
+ <el-icon class="ys-bool-mark" :class="value ? 'is-yes' : 'is-no'" :size="18" :title="value ? (onLabel ?? '是') : (offLabel ?? '否')">
13
+ <CircleCheckFilled v-if="value" />
14
+ <svg v-else viewBox="0 0 1024 1024" xmlns="http://www.w3.org/2000/svg">
15
+ <circle cx="512" cy="512" r="384" fill="none" stroke="currentColor" stroke-width="80" />
16
+ </svg>
17
+ </el-icon>
18
+ </template>
19
+
20
+ <style scoped>
21
+ .ys-bool-mark {
22
+ vertical-align: middle;
23
+ }
24
+ .ys-bool-mark.is-yes {
25
+ color: #5bb07a;
26
+ }
27
+ .ys-bool-mark.is-no {
28
+ color: #e6e9f0;
29
+ }
30
+ </style>
@@ -5,6 +5,8 @@
5
5
  import { computed, ref, watch } from "vue";
6
6
  import { FIELD_SPECS, ENUM_META } from "@ysgroup/contracts";
7
7
  import { enumLabel } from "../tokens-runtime";
8
+ import { columnWidth as lookupColumnWidth } from "../columnWidths";
9
+ import YsBoolMark from "./YsBoolMark.vue";
8
10
  import YsFormDialog from "./YsFormDialog.vue";
9
11
  import YsRowActionMenu from "./YsRowActionMenu.vue";
10
12
  import YsTableToolbar from "./YsTableToolbar.vue";
@@ -17,39 +19,6 @@ interface FieldSpec {
17
19
  sensitivity: string;
18
20
  }
19
21
 
20
- const COLUMN_WIDTHS: Record<string, number> = {
21
- enabled: 54,
22
- auto_trade: 72,
23
- cname: 120,
24
- account: 112,
25
- type: 110,
26
- trade_env: 72,
27
- owner_id: 120,
28
- team_id: 120,
29
- broker_id: 120,
30
- bank_card_id: 150,
31
- fee_rate: 76,
32
- commission_refund: 84,
33
- positions_refund: 84,
34
- interest: 72,
35
- cfmmc_username: 120,
36
- futures_app_id: 120,
37
- futures_auth_code: 130,
38
- name: 140,
39
- full_name: 200,
40
- code: 110,
41
- memo: 180,
42
- phone: 120,
43
- email: 180,
44
- role: 90,
45
- status: 80,
46
- max_sessions: 80,
47
- };
48
-
49
- function columnWidth(field: FieldSpec): number {
50
- return COLUMN_WIDTHS[field.key] ?? (field.widget === "switch" ? 64 : field.widget === "enum" ? 100 : 140);
51
- }
52
-
53
22
  const props = defineProps<{
54
23
  table: string;
55
24
  rows: Record<string, unknown>[];
@@ -79,6 +48,10 @@ const editing = ref<Record<string, unknown> | null>(null);
79
48
  const currentPage = ref(1);
80
49
  const pageSize = ref(20);
81
50
 
51
+ function columnWidth(field: FieldSpec): number {
52
+ return lookupColumnWidth(props.table, field.key);
53
+ }
54
+
82
55
  const allSpecs = computed<FieldSpec[]>(() => (FIELD_SPECS as unknown as Record<string, FieldSpec[]>)[props.table] ?? []);
83
56
 
84
57
  const displayColumns = computed<FieldSpec[]>(() => {
@@ -114,9 +87,17 @@ const paged = computed(() => {
114
87
  return filtered.value.slice(start, start + pageSize.value);
115
88
  });
116
89
 
90
+ function switchLabels(field: FieldSpec): { on: string; off: string } {
91
+ if (field.key === "enabled") return { on: "启用", off: "停用" };
92
+ return { on: "是", off: "否" };
93
+ }
94
+
117
95
  function display(row: Record<string, unknown>, f: FieldSpec): string {
118
96
  const v = props.rowDisplay ? props.rowDisplay(row, f.key, row[f.key]) : row[f.key];
119
- if (f.widget === "switch") return v ? "是" : "否";
97
+ if (f.widget === "switch") {
98
+ const labels = switchLabels(f);
99
+ return v ? labels.on : labels.off;
100
+ }
120
101
  if (f.widget === "enum" && f.enum && ENUM_META[f.enum as keyof typeof ENUM_META]) {
121
102
  return enumLabel(f.enum as keyof typeof ENUM_META, String(v ?? ""));
122
103
  }
@@ -159,8 +140,18 @@ function onSubmit(payload: Record<string, unknown>) {
159
140
  </YsTableToolbar>
160
141
 
161
142
  <el-table :fit="false" :data="paged" v-loading="loading" stripe border size="small" table-layout="fixed" row-key="_id">
162
- <el-table-column v-for="c in displayColumns" :key="c.key" :label="c.title" :width="columnWidth(c)" show-overflow-tooltip>
163
- <template #default="{ row }">{{ display(row, c) }}</template>
143
+ <el-table-column
144
+ v-for="c in displayColumns"
145
+ :key="c.key"
146
+ :label="c.title"
147
+ :width="columnWidth(c)"
148
+ :show-overflow-tooltip="c.widget !== 'switch'"
149
+ :align="c.widget === 'switch' ? 'center' : undefined"
150
+ >
151
+ <template #default="{ row }">
152
+ <YsBoolMark v-if="c.widget === 'switch'" :value="row[c.key]" :on-label="switchLabels(c).on" :off-label="switchLabels(c).off" />
153
+ <slot v-else name="cell" :row="row" :column="c" :text="display(row, c)">{{ display(row, c) }}</slot>
154
+ </template>
164
155
  </el-table-column>
165
156
  <el-table-column v-if="!readonly" label="操作栏" :width="actionWidth ?? 76" fixed="right" align="center">
166
157
  <template #default="{ row }">
@@ -176,6 +176,29 @@ function submit() {
176
176
  type="textarea"
177
177
  :rows="3"
178
178
  />
179
+ <el-date-picker
180
+ v-else-if="f.widget === 'datetime'"
181
+ v-model="form[f.key] as string"
182
+ type="datetime"
183
+ value-format="YYYY-MM-DD HH:mm:ss"
184
+ format="YYYY-MM-DD HH:mm:ss"
185
+ style="width: 100%"
186
+ />
187
+ <el-date-picker
188
+ v-else-if="f.widget === 'date'"
189
+ v-model="form[f.key] as string"
190
+ type="date"
191
+ value-format="YYYY-MM-DD"
192
+ format="YYYY-MM-DD"
193
+ style="width: 100%"
194
+ />
195
+ <el-time-picker
196
+ v-else-if="f.widget === 'time'"
197
+ v-model="form[f.key] as string"
198
+ value-format="HH:mm:ss"
199
+ format="HH:mm:ss"
200
+ style="width: 100%"
201
+ />
179
202
  <el-input v-else v-model="form[f.key] as string" />
180
203
  </el-form-item>
181
204
  </el-form>
package/src/index.ts CHANGED
@@ -12,4 +12,6 @@ export { default as YsLoginPage } from "./components/YsLoginPage.vue";
12
12
  export { default as YsSettingsCenterDialog } from "./components/YsSettingsCenterDialog.vue";
13
13
  export { default as YsPortalGrid } from "./components/YsPortalGrid.vue";
14
14
  export { default as YsRoleTag } from "./components/YsRoleTag.vue";
15
+ export { default as YsBoolMark } from "./components/YsBoolMark.vue";
15
16
  export { enumOptions, enumLabel, type EnumOption } from "./tokens-runtime";
17
+ export { registerColumnWidths, columnWidth, type ColumnWidthMap } from "./columnWidths";