openxiangda-cli 2.0.0-alpha.59 → 2.0.0-alpha.61

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.
@@ -0,0 +1,125 @@
1
+ import type { DataResourceSurface } from 'openxiangda-contracts/browser';
2
+
3
+ export type FieldKind =
4
+ | 'text'
5
+ | 'textarea'
6
+ | 'number'
7
+ | 'date'
8
+ | 'boolean'
9
+ | 'select'
10
+ | 'multi'
11
+ | 'email'
12
+ | 'phone'
13
+ | 'file'
14
+ | 'scope'
15
+ | 'directory-user'
16
+ | 'directory-department';
17
+
18
+ export interface InstrumentField {
19
+ key: string;
20
+ label: string;
21
+ kind: FieldKind;
22
+ section: keyof typeof sectionTitles;
23
+ required?: boolean;
24
+ system?: boolean;
25
+ createCapability?: string;
26
+ updateCapability?: string;
27
+ multiple?: boolean;
28
+ maxCount?: number;
29
+ accept?: string;
30
+ options?: Array<{ label: string; value: string }>;
31
+ }
32
+
33
+ const options = (pairs: Array<[string, string]>) =>
34
+ pairs.map(([label, value]) => ({ label, value }));
35
+
36
+ const listFieldCodes = new Set([
37
+ 'image',
38
+ 'chineseName',
39
+ 'specModel',
40
+ 'instrumentCode',
41
+ 'assetCode',
42
+ 'collegeId',
43
+ 'instrumentAdminIds',
44
+ 'instrumentStatus',
45
+ 'openToOutside',
46
+ ]);
47
+ const searchableFieldCodes = new Set(['chineseName', 'instrumentCode', 'assetCode']);
48
+ const sortableFieldCodes = new Set(['chineseName', 'instrumentCode', 'assetCode']);
49
+
50
+ export const sectionTitles = {
51
+ basic: '基本信息',
52
+ asset: '资产信息',
53
+ usage: '使用与归属',
54
+ management: '管理与联系',
55
+ materials: '地址与资料',
56
+ } as const;
57
+
58
+ // The declaration is shared by the platform resource and browser renderers.
59
+ export const instrumentFields: InstrumentField[] = [
60
+ { key: 'id', label: '记录 ID', kind: 'text', section: 'basic', system: true },
61
+ { key: 'revision', label: '修订版本', kind: 'number', section: 'basic', system: true },
62
+ { key: 'instrumentCode', label: '仪器编码', kind: 'text', section: 'basic', required: true, createCapability: 'app:instrument-center:instrument:field:instrument-code:create', updateCapability: 'app:instrument-center:instrument:field:instrument-code:update' },
63
+ { key: 'chineseName', label: '仪器中文名', kind: 'text', section: 'basic', required: true },
64
+ { key: 'englishName', label: '仪器英文名', kind: 'text', section: 'basic' },
65
+ { key: 'aliasName', label: '别名', kind: 'text', section: 'basic' },
66
+ { key: 'image', label: '仪器图片', kind: 'file', section: 'basic', maxCount: 1, accept: 'image/*' },
67
+ { key: 'specModel', label: '规格型号', kind: 'text', section: 'basic', required: true },
68
+ { key: 'categoryId', label: '仪器分类', kind: 'select', section: 'basic', required: true, options: options([['显微成像', 'analysis_microscope'], ['光谱分析', 'analysis_spectrum'], ['色谱质谱', 'analysis_ms']]) },
69
+ { key: 'instrumentSource', label: '仪器来源', kind: 'select', section: 'basic', options: options([['购置', 'purchase'], ['捐赠', 'donation'], ['调拨', 'transfer']]) },
70
+ { key: 'manufacturer', label: '制造商', kind: 'text', section: 'basic' },
71
+ { key: 'assetCode', label: '资产编码', kind: 'text', section: 'asset', required: true, createCapability: 'app:instrument-center:instrument:field:asset-code:create', updateCapability: 'app:instrument-center:instrument:field:asset-code:update' },
72
+ { key: 'assetValue', label: '资产价值(元)', kind: 'number', section: 'asset', createCapability: 'app:instrument-center:instrument:field:asset-value:create', updateCapability: 'app:instrument-center:instrument:field:asset-value:update' },
73
+ { key: 'enabledDate', label: '启用日期', kind: 'date', section: 'asset', required: true },
74
+ { key: 'usageStatus', label: '使用状况', kind: 'select', section: 'usage', required: true, options: options([['在用', 'active'], ['闲置', 'idle'], ['借出', 'lent']]) },
75
+ { key: 'instrumentStatus', label: '仪器状态', kind: 'select', section: 'usage', required: true, options: options([['正常', 'normal'], ['维修', 'maintenance'], ['停用', 'disabled'], ['报废', 'scrapped']]) },
76
+ { key: 'openToOutside', label: '是否对外开放', kind: 'boolean', section: 'usage', required: true },
77
+ { key: 'subjectAreas', label: '学科领域', kind: 'multi', section: 'usage', options: options([['材料', 'material'], ['生命科学', 'life'], ['化学', 'chemistry'], ['物理', 'physics']]) },
78
+ { key: 'platformProperty', label: '平台属性', kind: 'select', section: 'usage', options: options([['共享平台设备', 'shared'], ['课题组设备', 'research']]) },
79
+ { key: 'collegeId', label: '所属学院', kind: 'scope', section: 'usage', required: true, createCapability: 'app:instrument-center:instrument:field:college-id:create', updateCapability: 'app:instrument-center:instrument:field:college-id:update' },
80
+ { key: 'manageDepartmentId', label: '管理部门', kind: 'directory-department', section: 'management', required: true },
81
+ { key: 'useDepartmentId', label: '使用部门', kind: 'directory-department', section: 'management', required: true },
82
+ { key: 'instrumentAdminIds', label: '仪器管理员', kind: 'directory-user', section: 'management', required: true, multiple: true, createCapability: 'app:instrument-center:instrument:field:instrument-admin-ids:create', updateCapability: 'app:instrument-center:instrument:field:instrument-admin-ids:update' },
83
+ { key: 'contactUserIds', label: '联系人', kind: 'directory-user', section: 'management', required: true, multiple: true },
84
+ { key: 'contactPhone', label: '联系电话', kind: 'phone', section: 'management', required: true },
85
+ { key: 'contactEmail', label: '联系邮箱', kind: 'email', section: 'management' },
86
+ { key: 'locationId', label: '存放点', kind: 'select', section: 'materials', options: options([['A 区 101', 'A-101'], ['B 区 203', 'B-203']]) },
87
+ { key: 'address', label: '详细地址', kind: 'textarea', section: 'materials' },
88
+ { key: 'serviceContent', label: '服务内容与主要功能', kind: 'textarea', section: 'materials' },
89
+ { key: 'attachments', label: '仪器资料', kind: 'file', section: 'materials', multiple: true, maxCount: 8 },
90
+ ];
91
+
92
+ export const instrumentSurface: DataResourceSurface = {
93
+ // This resource keeps custom scope, file and audit UX; simple resources use the generated CRUD pages.
94
+ generated: false,
95
+ fields: Object.fromEntries(
96
+ instrumentFields.map(field => [
97
+ field.key,
98
+ {
99
+ label: field.label,
100
+ widget: field.kind,
101
+ section: field.section,
102
+ ...(field.required !== undefined ? { requiredHint: field.required } : {}),
103
+ ...(field.system !== undefined ? { system: field.system } : {}),
104
+ ...(field.createCapability ? { createCapability: field.createCapability } : {}),
105
+ ...(field.updateCapability ? { updateCapability: field.updateCapability } : {}),
106
+ ...(field.multiple !== undefined ? { multiple: field.multiple } : {}),
107
+ ...(field.maxCount !== undefined ? { maxCount: field.maxCount } : {}),
108
+ ...(field.accept ? { accept: field.accept } : {}),
109
+ ...(field.options ? { options: field.options } : {}),
110
+ ...(listFieldCodes.has(field.key) ? { list: true } : {}),
111
+ ...(searchableFieldCodes.has(field.key) ? { searchable: true } : {}),
112
+ ...(sortableFieldCodes.has(field.key) ? { sortable: true } : {}),
113
+ },
114
+ ])
115
+ ),
116
+ list: {
117
+ defaultPageSize: 20,
118
+ searchableFields: ['chineseName', 'instrumentCode', 'assetCode'],
119
+ filterFields: ['collegeId', 'instrumentAdminIds', 'instrumentStatus', 'openToOutside', 'enabledDate', 'assetValue'],
120
+ defaultSort: { field: 'instrumentCode', order: 'asc' },
121
+ },
122
+ form: { layout: 'sections' },
123
+ detail: { layout: 'sections' },
124
+ mobile: { enabled: true },
125
+ };
@@ -1,4 +1,5 @@
1
1
  import { SCHEMA_VERSIONS, type DataResource } from 'openxiangda-contracts';
2
+ import { instrumentSurface } from './instrument-surface.js';
2
3
 
3
4
  export const protectedFieldCapabilities = {
4
5
  instrumentCode: {
@@ -62,6 +63,7 @@ export const instruments: DataResource = {
62
63
  { code: 'attachments', type: 'file', file: { multiple: true, maxCount: 8, maxSizeMb: 50 } },
63
64
  ],
64
65
  },
66
+ surface: instrumentSurface,
65
67
  capabilities: {
66
68
  read: 'app:instrument-center:data:instruments:read',
67
69
  create: 'app:instrument-center:data:instruments:create',