openxiangda 1.0.260 → 1.0.261

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 (36) hide show
  1. package/README.md +12 -1
  2. package/lib/skills.js +56 -0
  3. package/openxiangda-skills/SKILL.md +12 -1
  4. package/openxiangda-skills/references/pages/page-sdk.md +3 -0
  5. package/openxiangda-skills/references/permission-design-patterns.md +5 -0
  6. package/openxiangda-skills/references/school-contact-relations.md +131 -0
  7. package/openxiangda-skills/skills/openxiangda-page/SKILL.md +3 -0
  8. package/package.json +2 -1
  9. package/packages/sdk/dist/runtime/index.cjs +26 -26
  10. package/packages/sdk/dist/runtime/index.d.mts +1 -1
  11. package/packages/sdk/dist/runtime/index.d.ts +1 -1
  12. package/packages/sdk/dist/runtime/index.mjs +29 -29
  13. package/packages/sdk/dist/runtime/react.cjs +42 -42
  14. package/packages/sdk/dist/runtime/react.d.mts +75 -1
  15. package/packages/sdk/dist/runtime/react.d.ts +75 -1
  16. package/packages/sdk/dist/runtime/react.mjs +43 -43
  17. package/templates/openxiangda-react-spa/AGENTS.md +2 -0
  18. package/templates/sy-lowcode-app-workspace/AGENTS.md +2 -0
  19. package/v2/README.md +35 -0
  20. package/v2/skills/manifest.json +45 -0
  21. package/v2/skills/openxiangda-v1-maintenance/SKILL.md +21 -0
  22. package/v2/skills/openxiangda-v1-maintenance/agents/openai.yaml +4 -0
  23. package/v2/skills/openxiangda-v2/SKILL.md +38 -0
  24. package/v2/skills/openxiangda-v2/agents/openai.yaml +4 -0
  25. package/v2/skills/openxiangda-v2-architecture/SKILL.md +29 -0
  26. package/v2/skills/openxiangda-v2-architecture/agents/openai.yaml +4 -0
  27. package/v2/skills/openxiangda-v2-backend/SKILL.md +28 -0
  28. package/v2/skills/openxiangda-v2-backend/agents/openai.yaml +4 -0
  29. package/v2/skills/openxiangda-v2-data-authz/SKILL.md +28 -0
  30. package/v2/skills/openxiangda-v2-data-authz/agents/openai.yaml +4 -0
  31. package/v2/skills/openxiangda-v2-delivery/SKILL.md +30 -0
  32. package/v2/skills/openxiangda-v2-delivery/agents/openai.yaml +4 -0
  33. package/v2/skills/openxiangda-v2-frontend/SKILL.md +21 -0
  34. package/v2/skills/openxiangda-v2-frontend/agents/openai.yaml +4 -0
  35. package/v2/skills/openxiangda-v2-workflow-events/SKILL.md +28 -0
  36. package/v2/skills/openxiangda-v2-workflow-events/agents/openai.yaml +4 -0
package/README.md CHANGED
@@ -3,11 +3,20 @@
3
3
 
4
4
  OpenXiangda is a lightweight CLI and skill package for private low-code platforms.
5
5
 
6
+ ## Two runtime generations
7
+
8
+ OpenXiangda now has two deliberately separate development tracks:
9
+
10
+ - `openxiangda` 1.x maintains existing resource-based applications and its legacy Delivery V2 protocol. Stable applications keep this runtime and are not migrated by a platform upgrade.
11
+ - `v2/` contains the new platform-2.0 application toolchain: `create-openxiangda`, `@openxiangda/cli`, `@openxiangda/mcp`, standard React/NestJS packages, typed configuration, domain skills, and application-level deployment.
12
+
13
+ For a new 2.0 application, start with [`v2/docs/getting-started.md`](v2/docs/getting-started.md). A 2.0 workspace has `openxiangda.config.ts`, `apps/web`, and `apps/server`; it must not use the 1.x resource/SDD publishing commands.
14
+
6
15
  Normal OpenXiangda app development uses platform-user login tokens through `/openxiangda-api/v1`; it does not use AK/SK. External backend and third-party integrations use the separate `openxiangda-open-api` skill, `/dingtalk-api/v1.0`, and a platform-managed AK/SK credential.
7
16
 
8
17
  Private platform routing is fixed: backend APIs are under `/service`, platform management is under `/platform`, and app runtime access is under `/view`. Passing a root domain such as `https://yida.wisejob.cn/` to the CLI is supported; OpenXiangda stores the API base as `https://yida.wisejob.cn/service`.
9
18
 
10
- ## Delivery V2
19
+ ## OpenXiangda 1.x Delivery V2 (maintenance)
11
20
 
12
21
  New workspaces declare `deliveryVersion: 2`. The release flow is intentionally
13
22
  small and deterministic:
@@ -406,6 +415,8 @@ openxiangda form export customer --mode package --profile dev --output ./exports
406
415
 
407
416
  运行时页面读取当前用户信息时,优先使用 `sdk.user.getCurrent<PageUserRecord>()`。用户对象会返回常规组织成员关系 `departments`,也会返回系统维护的所属单位字段 `affiliatedDepartmentId` / `affiliatedDepartment`。`departments` 表示用户真实所在的部门、班级、专业等成员关系;`affiliatedDepartment` 表示业务上用于统计、筛选和展示的归属单位,通常是学院、单位或在源单位缺失时可用的具体部门节点,不用于替代权限部门成员关系。
408
417
 
418
+ 钉钉家校通讯录的家长、学生、教师身份和明确监护关系使用 `sdk.organization.schoolContact.*`(页面)或 `ctx.organization.schoolContact.*`(App Function)。角色声明 `app:organization:school-contact:read` 后默认可查询当前租户全部关系,返回平台用户 ID、手机号、钉钉 userid 和姓名;可选 `:self:read` / `:class:read` 用于收紧。完整示例见 [`docs/dingtalk-school-contact-relations.md`](docs/dingtalk-school-contact-relations.md)。
419
+
409
420
  ```ts
410
421
  import type { PageUserRecord } from "openxiangda/runtime"
411
422
 
package/lib/skills.js CHANGED
@@ -82,6 +82,62 @@ const SKILL_SPECS = [
82
82
  sourceRelativePath: 'openxiangda-skills/skills/openxiangda-open-api',
83
83
  type: 'subskill',
84
84
  },
85
+ {
86
+ name: 'openxiangda-v2',
87
+ displayName: 'OpenXiangda 2.0',
88
+ shortDescription: '标准 React/NestJS 应用与应用级交付入口。',
89
+ sourceRelativePath: 'v2/skills/openxiangda-v2',
90
+ type: 'subskill',
91
+ },
92
+ {
93
+ name: 'openxiangda-v2-architecture',
94
+ displayName: 'OpenXiangda 2.0 Architecture',
95
+ shortDescription: '设计 2.0 应用边界与类型化平台契约。',
96
+ sourceRelativePath: 'v2/skills/openxiangda-v2-architecture',
97
+ type: 'subskill',
98
+ },
99
+ {
100
+ name: 'openxiangda-v2-frontend',
101
+ displayName: 'OpenXiangda 2.0 Frontend',
102
+ shortDescription: '开发 React、Ant Design 与标准后台页面。',
103
+ sourceRelativePath: 'v2/skills/openxiangda-v2-frontend',
104
+ type: 'subskill',
105
+ },
106
+ {
107
+ name: 'openxiangda-v2-backend',
108
+ displayName: 'OpenXiangda 2.0 Backend',
109
+ shortDescription: '开发平台托管的标准 NestJS 应用后端。',
110
+ sourceRelativePath: 'v2/skills/openxiangda-v2-backend',
111
+ type: 'subskill',
112
+ },
113
+ {
114
+ name: 'openxiangda-v2-data-authz',
115
+ displayName: 'OpenXiangda 2.0 Data and AuthZ',
116
+ shortDescription: '设计 Data API、RBAC 与上下文数据权限。',
117
+ sourceRelativePath: 'v2/skills/openxiangda-v2-data-authz',
118
+ type: 'subskill',
119
+ },
120
+ {
121
+ name: 'openxiangda-v2-workflow-events',
122
+ displayName: 'OpenXiangda 2.0 Workflow and Events',
123
+ shortDescription: '开发 Workflow Kernel v2 与持久事件消费者。',
124
+ sourceRelativePath: 'v2/skills/openxiangda-v2-workflow-events',
125
+ type: 'subskill',
126
+ },
127
+ {
128
+ name: 'openxiangda-v2-delivery',
129
+ displayName: 'OpenXiangda 2.0 Delivery',
130
+ shortDescription: '构建、部署、观察、晋级和回滚完整应用。',
131
+ sourceRelativePath: 'v2/skills/openxiangda-v2-delivery',
132
+ type: 'subskill',
133
+ },
134
+ {
135
+ name: 'openxiangda-v1-maintenance',
136
+ displayName: 'OpenXiangda 1.x Maintenance',
137
+ shortDescription: '不迁移地安全维护稳定 1.x 应用。',
138
+ sourceRelativePath: 'v2/skills/openxiangda-v1-maintenance',
139
+ type: 'subskill',
140
+ },
85
141
  ];
86
142
 
87
143
  function getDefaultCodexSkillsDir(env = process.env) {
@@ -10,7 +10,13 @@ OpenXiangda connects an AI coding workspace to the private low-code platform thr
10
10
 
11
11
  This file is a router and safety card. Read only the one or two subskills selected below; do not load every OpenXiangda reference into the same turn.
12
12
 
13
- ## Delivery V2 is the normal release path
13
+ ## Select the runtime generation first
14
+
15
+ If the workspace contains `openxiangda.config.ts`, `apps/web`, and `apps/server`, it is a platform-2.0 application. Stop this 1.x resource flow and use `$openxiangda-v2` plus its architecture, frontend, backend, data-authz, workflow-events, and delivery skills. The 2.0 CLI operates on one immutable application package and does not use SDD or per-resource publishing.
16
+
17
+ If the workspace contains `app-workspace.config.ts`, forms/pages/resource manifests, or an existing 1.x state directory, continue with this router. Never migrate a stable 1.x application merely because platform 2.0 is available.
18
+
19
+ ## 1.x Delivery V2 is the normal 1.x release path
14
20
 
15
21
  When `app-workspace.config.ts` declares `deliveryVersion: 2`, all later V1 SDD,
16
22
  Git-mainline, candidate/ship, `--change`, and `--only` release rules are
@@ -60,6 +66,7 @@ content/source/parent verification and never overwrites immutable storage.
60
66
  | React/classic page | `openxiangda-page` | inspect the target route/page |
61
67
  | Function, automation, workflow, JS_CODE | `openxiangda-workflow-automation` | inspect the exact resource codes |
62
68
  | Roles, permission groups, data scope | `openxiangda-permission-settings` | produce the permission matrix |
69
+ | DingTalk school-contact guardian/student relationships | `openxiangda-page` plus `references/school-contact-relations.md` | use the platform relationship SDK, defaulting to unrestricted tenant scope |
63
70
  | New app architecture, auth, public access | `openxiangda-architecture-design` plus the relevant domain skill | run the design gate |
64
71
  | External backend/OpenAPI/AK-SK | `openxiangda-open-api` | describe the exact operation |
65
72
 
@@ -184,6 +191,10 @@ The lease is app-level promotion ownership, while worktree ownership prevents tw
184
191
  - Use platform roles, permission groups, public grants, and backend Function checks for authorization; frontend hiding is presentation only.
185
192
  - Keep tokens and secrets out of project files and chat.
186
193
  - Use official public SDK entrypoints and platform form/file components.
194
+ - Read school-contact guardian/student relationships through
195
+ `sdk.organization.schoolContact` or the trusted App Function bridge. Keep the
196
+ default tenant-wide scope unless the product explicitly requires self/class
197
+ restrictions; never infer relations from department membership.
187
198
  - Report platform defects or repeated workarounds with `openxiangda feedback submit --yes` when a configured feedback channel is available.
188
199
  - Run `openxiangda update check --json` once at the start of substantial work, when a version mismatch is suspected, or when the cached check is older than one day. Do not repeat it on every confirmation turn.
189
200
  - Install an available update with `openxiangda update install`; it reuses the npm cache, avoids peer-resolution stalls, emits a heartbeat, and has a bounded timeout. Do not replace it with a bare repeated `npm install -g` unless bootstrapping the CLI for the first time.
@@ -19,6 +19,7 @@ Guidelines:
19
19
  - Use `sdk.export.create` and `sdk.export.get` for asynchronous XLSX exports. Simple pages may send a declarative workbook definition. Complex or reusable exports should send only a published App Function `definitionCode`, the current query snapshot, export scope, and stable selected row IDs. The server executes `structured_export_provider_v1` with fresh user permissions; never upload executable rendering code from the browser. See `docs/structured-export-v1.md`.
20
20
  - Use `AttachmentPreviewList`, `ImagePreviewGrid`, or `useFilePreview` from `openxiangda/runtime/react` for in-page attachment previews in a custom React SPA page. They use the current PageSdk context and enforce the platform capability and ticket contracts. Use `sdk.createFileAccessTicket(bucketName, objectName, fileName, "preview", { appType })` only when the page needs a shareable or new-window preview link. `appType` defaults to the current page context. Open `response.result.previewPageUrl`; do not use `previewUrl` or `/service/file/preview-by-ticket/:ticket` as the page entry.
21
21
  - Use `sdk.organization.departments.*` and `sdk.organization.accounts.*` only for intentional organization pages. Read-only list/detail pages need `app:organization:read` or `app:organization:manage`; writes and password operations need `app:organization:manage`. Do not call legacy `/user` or `/department` endpoints from pages.
22
+ - Use `sdk.organization.schoolContact.*` for synchronized guardian/student relationships. Declare `app:organization:school-contact:read`; it defaults to all relationships in the current tenant. Use the optional `self:read` or `class:read` permission only when the product explicitly needs a narrower data scope. The response intentionally includes platform user ID, mobile, DingTalk userid, and name. Read `references/school-contact-relations.md` before building a family or class page.
22
23
  - Use `sdk.workCenter.listItems({ boxType })` and `sdk.workCenter.getStats()` for current-user work center lists and counts. `boxType` is one of `todo`, `done`, `cc`, or `initiated`. This is the end-user task/handled/cc/initiated surface; do not build todo pages by reading workflow operation logs, automation logs, or raw process-task tables.
23
24
  - `sdk.form.create` returns identifiers and generated serial number values only. Treat `formInstId` / `formInstanceId` as the required success contract; `serialNumber` / `serialNumbers` are present only when the form has `SerialNumberField`. Do not expect the save response to contain the full row, formula results, or other server-generated field values. Call `sdk.form.getDetail` explicitly after create when those values are needed.
24
25
  - Missing `formInstId` / `formInstanceId` is a real error in strict mode. Do not create fake IDs, mock rows, or fallback display data to hide it.
@@ -251,6 +252,8 @@ await sdk.organization.accounts.resetPassword("alice", {
251
252
 
252
253
  Use `ctx.organization.departments.*` and `ctx.organization.accounts.*` inside App Functions or trusted JS nodes for the same capability. Runtime service principals must resolve a real operator/audit actor; permission is checked against that user, not against the runtime service account. Keep password changes on dedicated endpoints: update account metadata with `update`, reset another user's password with `resetPassword`, and change the current user's password with `changeMyPassword({ oldPassword, newPassword })`.
253
254
 
255
+ For synchronized school-contact relationships, use `sdk.organization.schoolContact.relations.list`, `children.list`, `guardians.list`, or `myFamily.get`; App Functions use the same paths under `ctx.organization.schoolContact`. Do not infer a family relationship from class membership or persist a second relationship master inside application forms. See `references/school-contact-relations.md` for permission codes, filters, response fields, and examples.
256
+
254
257
  Work center:
255
258
 
256
259
  ```ts
@@ -275,6 +275,9 @@ Before implementation, write a matrix with at least these columns:
275
275
  - Query parameters as sensitive authorization.
276
276
  - Frontend-only button hiding or route hiding.
277
277
  - Hardcoded role strings scattered through pages.
278
+ - OR data policies whose role-specific rules omit `roleCodes`; otherwise a
279
+ user's applicant rule can remain active after switching to an administrator
280
+ RoleSession.
278
281
  - Delegated administrators without `app:role:manage` or required permission
279
282
  group management API permissions.
280
283
  - New roles created by delegated administrators without their own
@@ -301,6 +304,8 @@ Before implementation, write a matrix with at least these columns:
301
304
  matched grants, cache state, and final policy for at least one allow and one
302
305
  deny case.
303
306
  - Allowed role paths and denied role paths are both tested.
307
+ - A multi-role user is tested after switching RoleSession, and rules bound to
308
+ the previously selected role no longer contribute to row visibility.
304
309
  - Query parameter tampering does not expand sensitive access.
305
310
  - App Functions that mutate sensitive data verify `ctx.operator.roleCodes`,
306
311
  `ctx.operator.currentRoleCode`, business scope, or explicit public ticket.
@@ -0,0 +1,131 @@
1
+ # 家校通讯录关系
2
+
3
+ 家校关系由平台组织中心统一同步和维护。应用不得直连钉钉,也不得根据班级成员自行推断家长和学生关系。
4
+
5
+ ## 权限与默认范围
6
+
7
+ 需要查询家校关系的应用角色在 `src/resources/roles/<code>.json` 的 `apiPermissionCodes` 中声明:
8
+
9
+ ```json
10
+ {
11
+ "apiPermissionCodes": [
12
+ "app:organization:school-contact:read"
13
+ ]
14
+ }
15
+ ```
16
+
17
+ `app:organization:school-contact:read` 默认允许当前租户内全部关系,不按本人或班级限制。只有产品明确要求收紧时,才改用以下权限之一:
18
+
19
+ - `app:organization:school-contact:self:read`:只返回当前操作者作为家长或学生直接参与的关系。
20
+ - `app:organization:school-contact:class:read`:只返回当前操作者以 `teacher` 身份加入的班级关系。
21
+
22
+ 默认全量可见不等于公开访问:跨租户、游客和匿名页面仍然拒绝。不要通过公开访问策略给游客授予家庭关系能力。
23
+
24
+ ## 页面 SDK
25
+
26
+ 在 React SPA 或代码页中通过 Page SDK 查询,不要硬编码接口地址:
27
+
28
+ ```ts
29
+ const response = await sdk.organization.schoolContact.relations.list({
30
+ name: keyword,
31
+ classId,
32
+ page: 1,
33
+ pageSize: 20,
34
+ })
35
+
36
+ const relations = response.result?.items || []
37
+ ```
38
+
39
+ 常用方法:
40
+
41
+ ```ts
42
+ await sdk.organization.schoolContact.children.list(guardianUserId, {
43
+ page: 1,
44
+ pageSize: 20,
45
+ })
46
+
47
+ await sdk.organization.schoolContact.guardians.list(studentUserId, {
48
+ page: 1,
49
+ pageSize: 20,
50
+ })
51
+
52
+ await sdk.organization.schoolContact.myFamily.get({ pageSize: 50 })
53
+ ```
54
+
55
+ 关系列表支持以下服务端过滤条件:
56
+
57
+ - `userId`、`guardianUserId`、`studentUserId`:平台用户 ID。
58
+ - `dingtalkUserId`:钉钉 userid。
59
+ - `mobile`:精确手机号。
60
+ - `name`:家长或学生姓名。
61
+ - `classId`:平台家校班级 ID 或钉钉教育 `class_id`。
62
+ - `role`:`guardian` 或 `student`,用于限定通用人员过滤作用在哪一端。
63
+ - `relationCode`、`page`、`pageSize`;`pageSize` 最大为 100。
64
+
65
+ ## App Function
66
+
67
+ App Function、Automation 或 Workflow 中需要复用关系时,调用对应的受控后端桥接:
68
+
69
+ ```ts
70
+ export default async function(ctx, input) {
71
+ const result = await ctx.organization.schoolContact.relations.list({
72
+ guardianUserId: input.guardianUserId,
73
+ page: 1,
74
+ pageSize: 20,
75
+ })
76
+
77
+ return result.items
78
+ }
79
+ ```
80
+
81
+ 对应方法为:
82
+
83
+ ```ts
84
+ ctx.organization.schoolContact.relations.list(params)
85
+ ctx.organization.schoolContact.children.list(userId, params)
86
+ ctx.organization.schoolContact.guardians.list(userId, params)
87
+ ctx.organization.schoolContact.myFamily.get(params)
88
+ ```
89
+
90
+ 运行时使用平台提供的真实操作者做权限校验。不要信任页面 input 中伪造的租户、角色或当前用户 ID。
91
+
92
+ ## 返回结构
93
+
94
+ ```ts
95
+ interface SchoolContactRelation {
96
+ relationId: string
97
+ relationCode: string | null
98
+ relationName: string | null
99
+ guardian: {
100
+ userId: string
101
+ dingtalkUserId: string
102
+ name: string
103
+ mobile: string | null
104
+ }
105
+ student: {
106
+ userId: string
107
+ dingtalkUserId: string
108
+ name: string
109
+ mobile: string | null
110
+ }
111
+ class: {
112
+ id: string
113
+ dingtalkClassId: string
114
+ name: string
115
+ campusName: string | null
116
+ periodName: string | null
117
+ gradeName: string | null
118
+ }
119
+ syncedAt: string
120
+ syncState: "current" | "not_synced" | "disabled"
121
+ }
122
+ ```
123
+
124
+ 手机号可能为空。`sync.state=disabled` 表示管理员关闭了后续同步,现有数据仍保留但可能过期;业务页面在对时效敏感时应展示 `lastSuccessfulSyncAt`。
125
+
126
+ ## 持久化边界
127
+
128
+ - 平台关系是当前事实,不要复制全量关系到应用表单或 Data View。
129
+ - 业务单据确实需要历史证据时,只保存 `relationId`、双方平台用户 ID 和当时的最小显示快照。
130
+ - 不保存或依赖 `unionid`、同步原文、行业部门 ID,也不要假设行业 `dept_id` 等于教育 `class_id`。
131
+ - 所有列表保持分页;不要拉取全部关系后在浏览器过滤。
@@ -36,6 +36,7 @@ openxiangda workspace publish --profile <name> --page <pageCode>
36
36
  - ✅ For external APIs use `src/resources/connectors/<code>.json` + `sdk.connector.invoke()`; for joined read-only lists use row data views + `sdk.dataView.query`; for stable dashboard metrics use aggregate data views + `sdk.dataView.stats`.
37
37
  - ✅ Choose data view `storageMode` deliberately: `materialized` for refreshed reports/lists that tolerate delay, `live` for bounded real-time multi-form reads.
38
38
  - ✅ For reusable backend orchestration use App Function (`src/functions/<functionCode>/index.ts` + `src/resources/functions/<functionCode>.json`) and call `sdk.function.invoke(code, { input })`; keep page components out of multi-table business orchestration.
39
+ - ✅ 家长、学生、教师身份或监护关系页面使用 `sdk.organization.schoolContact.*`;先读 `references/school-contact-relations.md`,声明家校关系读取权限并保持服务端分页。
39
40
  - ✅ Filters, search bars, modal forms, drawers, and inline edits use platform components for platform data fields, otherwise `antd` / `antd-mobile` controls.
40
41
  - ❌ Single-file giant pages. Split per `references/best-practices.md`.
41
42
  - ❌ Hardcoded `/view/...&isRenderNav=false` URLs scattered through page code; use the runtime navigation helper.
@@ -114,6 +115,7 @@ Read these references only when editing page code:
114
115
  - `references/pages/app-shell.md` — formal backend / PC portal / mobile portal entry pattern. Read before creating any user-facing main entry or admin console.
115
116
  - `references/best-practices.md` — initialized examples for modular pages, status lifecycles, role governance, high-performance queries, portal shells, and interactive workbenches. Read before scaffolding complex pages or data management pages.
116
117
  - `references/pages/page-sdk.md`
118
+ - `references/school-contact-relations.md` — 家校关系权限、分页查询、返回字段以及 Page SDK/App Function 示例。创建家长、学生或班级关系页面前读取。
117
119
  - `references/notifications.md` — notification resources and `sdk.notification` usage. Read before adding reminders, alerts, or message templates to a page.
118
120
  - `references/pages/publish-flow.md`
119
121
  - `references/style-system.md` — style isolation defaults, Tailwind/CSS guidance, and legacy namespace compatibility. Read before writing substantial page CSS or Tailwind classes.
@@ -130,6 +132,7 @@ Read these references only when editing page code:
130
132
  - All visible page copy must be end-user-facing business text. Do not put developer explanations, implementation notes, schema descriptions, or "this module is generated by..." text into sections, cards, alerts, empty states, tooltips, or helper copy.
131
133
  - Store live `pageId`, `routeKey`, and `legacyFormUuid` under the current profile only.
132
134
  - Use `openxiangda/runtime` for platform data access instead of hardcoding backend URLs in page code.
135
+ - 家校关系必须通过 `sdk.organization.schoolContact` / `ctx.organization.schoolContact` 读取;不要直连钉钉、查询系统表或用同班成员推断亲属关系。
133
136
  - For reminders, alerts, and business messages, declare `src/resources/notifications/` first and call `sdk.notification`; do not hardcode notification API URLs.
134
137
  - For backend business logic shared by pages, automations, or workflows, declare an App Function and call `sdk.function.invoke`; do not duplicate the same multi-form query/connector/notification orchestration in page code.
135
138
  - Before hand-writing mature UI behavior, consult `references/component-guide.md` and use established libraries: platform components for platform data fields, antd/antd-mobile for controls and overlays, ECharts for charts, GSAP for complex animation timelines, and maintained packages such as dnd-kit for drag/drop. Do not rebuild mature controls with raw DOM/native inputs.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "openxiangda",
3
- "version": "1.0.260",
3
+ "version": "1.0.261",
4
4
  "description": "OpenXiangda CLI, workspace build tools, runtime SDK, and form components.",
5
5
  "private": false,
6
6
  "bin": {
@@ -55,6 +55,7 @@
55
55
  "bin/",
56
56
  "lib/",
57
57
  "openxiangda-skills/",
58
+ "v2/skills/",
58
59
  "policy/",
59
60
  "templates/",
60
61
  "packages/sdk/bin/",