openxiangda 1.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.
- package/README.md +58 -0
- package/bin/openxiangda.js +11 -0
- package/lib/cli.js +2423 -0
- package/lib/config.js +121 -0
- package/lib/http.js +47 -0
- package/lib/skills.js +371 -0
- package/lib/utils.js +87 -0
- package/lib/workspace-init.js +139 -0
- package/openxiangda-skills/SKILL.md +128 -0
- package/openxiangda-skills/references/architecture-patterns.md +242 -0
- package/openxiangda-skills/references/automation-v3.md +129 -0
- package/openxiangda-skills/references/component-guide.md +198 -0
- package/openxiangda-skills/references/forms/component-registry.md +53 -0
- package/openxiangda-skills/references/forms/form-schema.md +109 -0
- package/openxiangda-skills/references/forms/layout-and-rules.md +24 -0
- package/openxiangda-skills/references/openxiangda-api.md +466 -0
- package/openxiangda-skills/references/pages/page-sdk.md +13 -0
- package/openxiangda-skills/references/pages/publish-flow.md +36 -0
- package/openxiangda-skills/references/pages/workspace-structure.md +38 -0
- package/openxiangda-skills/references/permissions-settings.md +147 -0
- package/openxiangda-skills/references/platform-data-model.md +305 -0
- package/openxiangda-skills/references/style-system.md +492 -0
- package/openxiangda-skills/references/troubleshooting.md +246 -0
- package/openxiangda-skills/references/workflow-v3.md +105 -0
- package/openxiangda-skills/references/workspace-state.md +45 -0
- package/openxiangda-skills/skills/openxiangda-app/SKILL.md +64 -0
- package/openxiangda-skills/skills/openxiangda-core/SKILL.md +143 -0
- package/openxiangda-skills/skills/openxiangda-form/SKILL.md +76 -0
- package/openxiangda-skills/skills/openxiangda-inspect/SKILL.md +40 -0
- package/openxiangda-skills/skills/openxiangda-page/SKILL.md +62 -0
- package/openxiangda-skills/skills/openxiangda-permission-settings/SKILL.md +95 -0
- package/openxiangda-skills/skills/openxiangda-workflow-automation/SKILL.md +97 -0
- package/package.json +126 -0
- package/packages/sdk/bin/lowcode-workspace.mjs +4 -0
- package/packages/sdk/dist/build/index.cjs +33 -0
- package/packages/sdk/dist/build/index.cjs.map +1 -0
- package/packages/sdk/dist/build/index.d.mts +40 -0
- package/packages/sdk/dist/build/index.d.ts +40 -0
- package/packages/sdk/dist/build/index.mjs +8 -0
- package/packages/sdk/dist/build/index.mjs.map +1 -0
- package/packages/sdk/dist/components/index.cjs +18700 -0
- package/packages/sdk/dist/components/index.cjs.map +1 -0
- package/packages/sdk/dist/components/index.d.mts +2094 -0
- package/packages/sdk/dist/components/index.d.ts +2094 -0
- package/packages/sdk/dist/components/index.mjs +18649 -0
- package/packages/sdk/dist/components/index.mjs.map +1 -0
- package/packages/sdk/dist/runtime/index.cjs +1469 -0
- package/packages/sdk/dist/runtime/index.cjs.map +1 -0
- package/packages/sdk/dist/runtime/index.d.mts +831 -0
- package/packages/sdk/dist/runtime/index.d.ts +831 -0
- package/packages/sdk/dist/runtime/index.mjs +1420 -0
- package/packages/sdk/dist/runtime/index.mjs.map +1 -0
- package/packages/sdk/dist/styles/antd-theme.cjs +60 -0
- package/packages/sdk/dist/styles/antd-theme.cjs.map +1 -0
- package/packages/sdk/dist/styles/antd-theme.d.mts +5 -0
- package/packages/sdk/dist/styles/antd-theme.d.ts +5 -0
- package/packages/sdk/dist/styles/antd-theme.mjs +35 -0
- package/packages/sdk/dist/styles/antd-theme.mjs.map +1 -0
- package/packages/sdk/dist/styles/tailwind-preset.cjs +2641 -0
- package/packages/sdk/dist/styles/tailwind-preset.cjs.map +1 -0
- package/packages/sdk/dist/styles/tailwind-preset.d.mts +75 -0
- package/packages/sdk/dist/styles/tailwind-preset.d.ts +75 -0
- package/packages/sdk/dist/styles/tailwind-preset.mjs +2618 -0
- package/packages/sdk/dist/styles/tailwind-preset.mjs.map +1 -0
- package/packages/sdk/dist/styles/tokens.css +73 -0
- package/packages/sdk/src/build-source/README.md +9 -0
- package/packages/sdk/src/build-source/bin/lowcode-workspace.mjs +7 -0
- package/packages/sdk/src/build-source/package.json +34 -0
- package/packages/sdk/src/build-source/scripts/build-forms.mjs +824 -0
- package/packages/sdk/src/build-source/scripts/build-forms.runtime-entry.test.ts +18 -0
- package/packages/sdk/src/build-source/scripts/build-pages.mjs +793 -0
- package/packages/sdk/src/build-source/scripts/build-workspace.mjs +64 -0
- package/packages/sdk/src/build-source/scripts/publish-all.mjs +127 -0
- package/packages/sdk/src/build-source/scripts/publish-oss.mjs +149 -0
- package/packages/sdk/src/build-source/scripts/register-bundle.mjs +1 -0
- package/packages/sdk/src/build-source/scripts/register.mjs +329 -0
- package/packages/sdk/src/build-source/scripts/sync-schema.mjs +301 -0
- package/packages/sdk/src/build-source/scripts/utils/form-api.mjs +639 -0
- package/packages/sdk/src/build-source/scripts/utils/form-api.test.ts +244 -0
- package/packages/sdk/src/build-source/scripts/utils/form-runtime-assets.mjs +57 -0
- package/packages/sdk/src/build-source/scripts/utils/form-runtime-assets.test.ts +135 -0
- package/packages/sdk/src/build-source/scripts/utils/incremental.mjs +210 -0
- package/packages/sdk/src/build-source/scripts/utils/load-config.mjs +257 -0
- package/packages/sdk/src/build-source/scripts/utils/load-config.test.ts +44 -0
- package/packages/sdk/src/build-source/scripts/utils/mime-types.mjs +70 -0
- package/packages/sdk/src/build-source/scripts/utils/namespace-css.mjs +61 -0
- package/packages/sdk/src/build-source/scripts/utils/oss-client.mjs +128 -0
- package/packages/sdk/src/build-source/scripts/utils/pages.mjs +80 -0
- package/packages/sdk/src/build-source/scripts/utils/progress.mjs +57 -0
- package/packages/sdk/src/build-source/scripts/utils/register-payload.mjs +89 -0
- package/packages/sdk/src/build-source/scripts/utils/register-payload.test.ts +76 -0
- package/packages/sdk/src/build-source/scripts/utils/runtime-css-check.mjs +44 -0
- package/packages/sdk/src/build-source/scripts/utils/runtime-css-check.test.ts +54 -0
- package/packages/sdk/src/build-source/scripts/utils/schema-transform.mjs +130 -0
- package/packages/sdk/src/build-source/scripts/utils/schema-transform.test.ts +141 -0
- package/packages/sdk/src/build-source/scripts/utils/tailwind-config.mjs +227 -0
- package/packages/sdk/src/build-source/scripts/utils/tailwind-config.test.ts +187 -0
- package/packages/sdk/src/build-source/src/cli.mjs +679 -0
- package/templates/sy-lowcode-app-workspace/app-workspace.config.ts +34 -0
- package/templates/sy-lowcode-app-workspace/examples/forms/customer/page.tsx +1 -0
- package/templates/sy-lowcode-app-workspace/examples/forms/customer/schema.ts +35 -0
- package/templates/sy-lowcode-app-workspace/index.html +12 -0
- package/templates/sy-lowcode-app-workspace/package.json +49 -0
- package/templates/sy-lowcode-app-workspace/postcss.config.cjs +6 -0
- package/templates/sy-lowcode-app-workspace/scripts/build-js-code.mjs +100 -0
- package/templates/sy-lowcode-app-workspace/src/dev/App.tsx +26 -0
- package/templates/sy-lowcode-app-workspace/src/forms/.gitkeep +1 -0
- package/templates/sy-lowcode-app-workspace/src/forms/README.md +48 -0
- package/templates/sy-lowcode-app-workspace/src/index.css +28 -0
- package/templates/sy-lowcode-app-workspace/src/js-code-nodes/.gitkeep +1 -0
- package/templates/sy-lowcode-app-workspace/src/js-code-nodes/types.d.ts +3 -0
- package/templates/sy-lowcode-app-workspace/src/main.tsx +36 -0
- package/templates/sy-lowcode-app-workspace/src/pages/.gitkeep +1 -0
- package/templates/sy-lowcode-app-workspace/src/shared/form-schema.ts +128 -0
- package/templates/sy-lowcode-app-workspace/src/types/app-workspace.types.ts +31 -0
- package/templates/sy-lowcode-app-workspace/tailwind.config.cjs +30 -0
- package/templates/sy-lowcode-app-workspace/tsconfig.app.json +24 -0
- package/templates/sy-lowcode-app-workspace/tsconfig.js-code-nodes.json +15 -0
- package/templates/sy-lowcode-app-workspace/tsconfig.json +7 -0
- package/templates/sy-lowcode-app-workspace/tsconfig.node.json +10 -0
- package/templates/sy-lowcode-app-workspace/vite.config.ts +32 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { default } from "./schema";
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
import { createFormSchema } from "../../../src/shared/form-schema";
|
|
2
|
+
|
|
3
|
+
export default createFormSchema({
|
|
4
|
+
formMeta: {
|
|
5
|
+
formUuid: "",
|
|
6
|
+
appType: process.env.OPENXIANGDA_APP_TYPE || "APP_XXXX",
|
|
7
|
+
title: "客户信息",
|
|
8
|
+
},
|
|
9
|
+
fields: [
|
|
10
|
+
{
|
|
11
|
+
fieldId: "customer_name",
|
|
12
|
+
componentName: "TextField",
|
|
13
|
+
label: "客户名称",
|
|
14
|
+
required: true,
|
|
15
|
+
rules: [{ required: true, message: "请填写客户名称" }],
|
|
16
|
+
placeholder: "请输入客户名称",
|
|
17
|
+
},
|
|
18
|
+
{
|
|
19
|
+
fieldId: "customer_phone",
|
|
20
|
+
componentName: "TextField",
|
|
21
|
+
label: "联系电话",
|
|
22
|
+
rules: [{ preset: "phone", message: "请输入有效手机号" }],
|
|
23
|
+
placeholder: "请输入联系电话",
|
|
24
|
+
},
|
|
25
|
+
{
|
|
26
|
+
fieldId: "customer_type",
|
|
27
|
+
componentName: "SelectField",
|
|
28
|
+
label: "客户类型",
|
|
29
|
+
options: [
|
|
30
|
+
{ value: "enterprise", label: "企业客户" },
|
|
31
|
+
{ value: "individual", label: "个人客户" },
|
|
32
|
+
],
|
|
33
|
+
},
|
|
34
|
+
],
|
|
35
|
+
});
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
<!doctype html>
|
|
2
|
+
<html lang="zh-CN">
|
|
3
|
+
<head>
|
|
4
|
+
<meta charset="UTF-8" />
|
|
5
|
+
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
|
6
|
+
<title>OpenXiangda Workspace</title>
|
|
7
|
+
</head>
|
|
8
|
+
<body>
|
|
9
|
+
<div id="root"></div>
|
|
10
|
+
<script type="module" src="/src/main.tsx"></script>
|
|
11
|
+
</body>
|
|
12
|
+
</html>
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "__WORKSPACE_PACKAGE_NAME__",
|
|
3
|
+
"private": true,
|
|
4
|
+
"version": "0.1.0",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"scripts": {
|
|
7
|
+
"dev": "vite",
|
|
8
|
+
"build": "lowcode-workspace build",
|
|
9
|
+
"build:forms": "lowcode-workspace build-forms",
|
|
10
|
+
"build:pages": "lowcode-workspace build-pages",
|
|
11
|
+
"build:force": "lowcode-workspace build --force",
|
|
12
|
+
"build-js-code": "node scripts/build-js-code.mjs",
|
|
13
|
+
"build:js-code": "node scripts/build-js-code.mjs",
|
|
14
|
+
"typecheck:js-code": "tsc -p tsconfig.js-code-nodes.json --noEmit",
|
|
15
|
+
"sync-schema": "lowcode-workspace sync-schema",
|
|
16
|
+
"publish:oss": "lowcode-workspace publish-oss",
|
|
17
|
+
"register": "lowcode-workspace register",
|
|
18
|
+
"register-bundle": "lowcode-workspace register",
|
|
19
|
+
"publish:all": "lowcode-workspace publish-all",
|
|
20
|
+
"openxiangda:publish": "lowcode-workspace publish-all",
|
|
21
|
+
"ai:update": "pnpm dlx openxiangda@latest lowcode-workspace update --channel latest",
|
|
22
|
+
"ai:migrate": "pnpm dlx openxiangda@latest lowcode-workspace migrate",
|
|
23
|
+
"typecheck": "tsc -p tsconfig.app.json --noEmit",
|
|
24
|
+
"check": "pnpm typecheck && pnpm build"
|
|
25
|
+
},
|
|
26
|
+
"dependencies": {
|
|
27
|
+
"@ant-design/cssinjs": "^1.23.0",
|
|
28
|
+
"@ant-design/icons": "^6",
|
|
29
|
+
"antd": "^6.3.7",
|
|
30
|
+
"antd-mobile": "^5.37.0",
|
|
31
|
+
"dayjs": "^1.11.20",
|
|
32
|
+
"echarts": "^6.0.0",
|
|
33
|
+
"echarts-for-react": "^3.0.6",
|
|
34
|
+
"openxiangda": "latest",
|
|
35
|
+
"react": "18.3.1",
|
|
36
|
+
"react-dom": "18.3.1"
|
|
37
|
+
},
|
|
38
|
+
"devDependencies": {
|
|
39
|
+
"@types/node": "^22.0.0",
|
|
40
|
+
"@types/react": "^18.3.18",
|
|
41
|
+
"@types/react-dom": "^18.3.5",
|
|
42
|
+
"@vitejs/plugin-react": "^4.3.0",
|
|
43
|
+
"autoprefixer": "^10.4.21",
|
|
44
|
+
"postcss": "^8.5.0",
|
|
45
|
+
"tailwindcss": "^3.4.17",
|
|
46
|
+
"typescript": "^5.7.0",
|
|
47
|
+
"vite": "^6.0.0"
|
|
48
|
+
}
|
|
49
|
+
}
|
|
@@ -0,0 +1,100 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import { builtinModules } from "node:module";
|
|
3
|
+
import { spawnSync } from "node:child_process";
|
|
4
|
+
import { existsSync } from "node:fs";
|
|
5
|
+
import { readdir, stat } from "node:fs/promises";
|
|
6
|
+
import path from "node:path";
|
|
7
|
+
import { fileURLToPath } from "node:url";
|
|
8
|
+
import { build } from "vite";
|
|
9
|
+
|
|
10
|
+
const rootDir = fileURLToPath(new URL("..", import.meta.url));
|
|
11
|
+
const sourceRoot = path.join(rootDir, "src", "js-code-nodes");
|
|
12
|
+
const outputRoot = path.join(rootDir, "dist", "js-code-nodes");
|
|
13
|
+
const args = process.argv.slice(2);
|
|
14
|
+
|
|
15
|
+
function readArg(name) {
|
|
16
|
+
const prefix = `--${name}=`;
|
|
17
|
+
const inline = args.find((arg) => arg.startsWith(prefix));
|
|
18
|
+
if (inline) return inline.slice(prefix.length);
|
|
19
|
+
const index = args.indexOf(`--${name}`);
|
|
20
|
+
return index >= 0 ? args[index + 1] : undefined;
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
async function listScriptCodes() {
|
|
24
|
+
if (!existsSync(sourceRoot)) return [];
|
|
25
|
+
const entries = await readdir(sourceRoot);
|
|
26
|
+
const result = [];
|
|
27
|
+
for (const entry of entries) {
|
|
28
|
+
const entryDir = path.join(sourceRoot, entry);
|
|
29
|
+
const entryStat = await stat(entryDir);
|
|
30
|
+
if (!entryStat.isDirectory()) continue;
|
|
31
|
+
if (existsSync(path.join(entryDir, "index.ts"))) result.push(entry);
|
|
32
|
+
}
|
|
33
|
+
return result.sort();
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
function typecheckScripts() {
|
|
37
|
+
const result = spawnSync(
|
|
38
|
+
"pnpm",
|
|
39
|
+
["exec", "tsc", "-p", "tsconfig.js-code-nodes.json", "--noEmit"],
|
|
40
|
+
{
|
|
41
|
+
cwd: rootDir,
|
|
42
|
+
stdio: "inherit",
|
|
43
|
+
},
|
|
44
|
+
);
|
|
45
|
+
if (result.status !== 0) throw new Error("JS_CODE TypeScript validation failed");
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
async function buildScript(scriptCode) {
|
|
49
|
+
const entry = path.join(sourceRoot, scriptCode, "index.ts");
|
|
50
|
+
if (!existsSync(entry)) throw new Error(`JS_CODE script not found: ${entry}`);
|
|
51
|
+
|
|
52
|
+
const outDir = path.join(outputRoot, scriptCode);
|
|
53
|
+
const external = Array.from(
|
|
54
|
+
new Set([...builtinModules, ...builtinModules.map((name) => `node:${name}`)]),
|
|
55
|
+
);
|
|
56
|
+
|
|
57
|
+
await build({
|
|
58
|
+
configFile: false,
|
|
59
|
+
root: rootDir,
|
|
60
|
+
logLevel: "warn",
|
|
61
|
+
resolve: {
|
|
62
|
+
alias: {
|
|
63
|
+
"@": path.join(rootDir, "src"),
|
|
64
|
+
},
|
|
65
|
+
},
|
|
66
|
+
build: {
|
|
67
|
+
ssr: entry,
|
|
68
|
+
outDir,
|
|
69
|
+
emptyOutDir: true,
|
|
70
|
+
target: "node20",
|
|
71
|
+
minify: false,
|
|
72
|
+
sourcemap: true,
|
|
73
|
+
rollupOptions: {
|
|
74
|
+
external,
|
|
75
|
+
output: {
|
|
76
|
+
format: "cjs",
|
|
77
|
+
entryFileNames: "index.cjs",
|
|
78
|
+
inlineDynamicImports: true,
|
|
79
|
+
exports: "auto",
|
|
80
|
+
},
|
|
81
|
+
},
|
|
82
|
+
},
|
|
83
|
+
});
|
|
84
|
+
|
|
85
|
+
console.log(`built ${scriptCode} -> ${path.relative(rootDir, path.join(outDir, "index.cjs"))}`);
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
const onlyScript = readArg("script");
|
|
89
|
+
const scriptCodes = onlyScript ? [onlyScript] : await listScriptCodes();
|
|
90
|
+
|
|
91
|
+
if (scriptCodes.length === 0) {
|
|
92
|
+
console.log("no JS_CODE scripts found under src/js-code-nodes/<scriptCode>/index.ts");
|
|
93
|
+
process.exit(0);
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
typecheckScripts();
|
|
97
|
+
|
|
98
|
+
for (const scriptCode of scriptCodes) {
|
|
99
|
+
await buildScript(scriptCode);
|
|
100
|
+
}
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import { Card, Space, Typography } from "antd";
|
|
2
|
+
|
|
3
|
+
const { Paragraph, Text, Title } = Typography;
|
|
4
|
+
|
|
5
|
+
export default function App() {
|
|
6
|
+
return (
|
|
7
|
+
<main style={{ maxWidth: 960, margin: "0 auto", padding: 24 }}>
|
|
8
|
+
<Card>
|
|
9
|
+
<Space direction="vertical" size={12}>
|
|
10
|
+
<Title level={3} style={{ margin: 0 }}>
|
|
11
|
+
OpenXiangda Workspace
|
|
12
|
+
</Title>
|
|
13
|
+
<Paragraph style={{ margin: 0 }}>
|
|
14
|
+
Add form pages under <Text code>src/forms</Text>, code pages under{" "}
|
|
15
|
+
<Text code>src/pages</Text>, and JS_CODE nodes under{" "}
|
|
16
|
+
<Text code>src/js-code-nodes</Text>.
|
|
17
|
+
</Paragraph>
|
|
18
|
+
<Paragraph style={{ margin: 0 }}>
|
|
19
|
+
Publish from this workspace with{" "}
|
|
20
|
+
<Text code>openxiangda workspace publish --profile <name></Text>.
|
|
21
|
+
</Paragraph>
|
|
22
|
+
</Space>
|
|
23
|
+
</Card>
|
|
24
|
+
</main>
|
|
25
|
+
);
|
|
26
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
# Forms
|
|
2
|
+
|
|
3
|
+
Create form source under `src/forms/<formCode>/schema.ts`.
|
|
4
|
+
|
|
5
|
+
Use `defineFormSchema` from `openxiangda` and default-export the schema:
|
|
6
|
+
|
|
7
|
+
```ts
|
|
8
|
+
import { defineFormSchema } from "openxiangda";
|
|
9
|
+
|
|
10
|
+
export default defineFormSchema({
|
|
11
|
+
formMeta: {
|
|
12
|
+
formUuid: "",
|
|
13
|
+
appType: process.env.OPENXIANGDA_APP_TYPE || "APP_XXXX",
|
|
14
|
+
title: "客户信息",
|
|
15
|
+
},
|
|
16
|
+
fields: [
|
|
17
|
+
{
|
|
18
|
+
fieldId: "customer_name",
|
|
19
|
+
componentName: "TextField",
|
|
20
|
+
label: "客户名称",
|
|
21
|
+
required: true,
|
|
22
|
+
rules: [{ required: true, message: "请填写客户名称" }],
|
|
23
|
+
},
|
|
24
|
+
],
|
|
25
|
+
});
|
|
26
|
+
```
|
|
27
|
+
|
|
28
|
+
Important: top-level `schema.rules` is for dynamic effects with `when` and `then`, not validation. Put validation on field-level `rules`.
|
|
29
|
+
|
|
30
|
+
Option components must always include an `options` array. For `SelectField`, `MultiSelectField`, `RadioField`, `CheckboxField`, and `CascadeSelectField`, use `options: []` when values will be wired later; omitting `options` can crash the runtime with `Cannot read properties of undefined (reading 'map')`.
|
|
31
|
+
|
|
32
|
+
For generated apps with many forms, prefer the safe helper in `src/shared/form-schema.ts`:
|
|
33
|
+
|
|
34
|
+
```ts
|
|
35
|
+
import { createFormSchema } from "../../shared/form-schema";
|
|
36
|
+
|
|
37
|
+
export default createFormSchema({
|
|
38
|
+
formMeta: {
|
|
39
|
+
formUuid: "",
|
|
40
|
+
appType: process.env.OPENXIANGDA_APP_TYPE || "APP_XXXX",
|
|
41
|
+
title: "客户信息",
|
|
42
|
+
},
|
|
43
|
+
fields: [{ fieldId: "customer_name", componentName: "TextField", label: "客户名称", required: true }],
|
|
44
|
+
});
|
|
45
|
+
```
|
|
46
|
+
|
|
47
|
+
The helper adds field-level required validation and never emits top-level validation rules.
|
|
48
|
+
It also normalizes option components without `options` to `options: []` as a runtime guard.
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
@import "openxiangda/styles/tokens.css";
|
|
2
|
+
|
|
3
|
+
@layer tailwind-base {
|
|
4
|
+
@tailwind base;
|
|
5
|
+
}
|
|
6
|
+
|
|
7
|
+
@tailwind components;
|
|
8
|
+
@tailwind utilities;
|
|
9
|
+
|
|
10
|
+
* {
|
|
11
|
+
box-sizing: border-box;
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
body {
|
|
15
|
+
margin: 0;
|
|
16
|
+
min-width: 320px;
|
|
17
|
+
background: var(--sy-color-bg-layout);
|
|
18
|
+
color: var(--sy-color-text);
|
|
19
|
+
font-family:
|
|
20
|
+
-apple-system,
|
|
21
|
+
BlinkMacSystemFont,
|
|
22
|
+
"Segoe UI",
|
|
23
|
+
sans-serif;
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
#root {
|
|
27
|
+
min-height: 100dvh;
|
|
28
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
import { StrictMode } from "react";
|
|
2
|
+
import { createRoot } from "react-dom/client";
|
|
3
|
+
import { StyleProvider } from "@ant-design/cssinjs";
|
|
4
|
+
import { App as AntdApp, ConfigProvider } from "antd";
|
|
5
|
+
import zhCN from "antd/locale/zh_CN";
|
|
6
|
+
import "antd-mobile/es/global";
|
|
7
|
+
import { antdTheme } from "openxiangda/antd-theme";
|
|
8
|
+
|
|
9
|
+
import App from "./dev/App";
|
|
10
|
+
import "./index.css";
|
|
11
|
+
|
|
12
|
+
createRoot(document.getElementById("root")!).render(
|
|
13
|
+
<StrictMode>
|
|
14
|
+
<StyleProvider hashPriority="high">
|
|
15
|
+
<ConfigProvider
|
|
16
|
+
locale={zhCN}
|
|
17
|
+
prefixCls="sy-ant"
|
|
18
|
+
iconPrefixCls="sy-anticon"
|
|
19
|
+
theme={antdTheme}
|
|
20
|
+
getPopupContainer={() =>
|
|
21
|
+
document.querySelector(".sy-app-workspace") as HTMLElement
|
|
22
|
+
}
|
|
23
|
+
getTargetContainer={() =>
|
|
24
|
+
(document.querySelector(".sy-app-workspace") as HTMLElement) ||
|
|
25
|
+
document.body
|
|
26
|
+
}
|
|
27
|
+
>
|
|
28
|
+
<AntdApp>
|
|
29
|
+
<div className="sy-app-workspace">
|
|
30
|
+
<App />
|
|
31
|
+
</div>
|
|
32
|
+
</AntdApp>
|
|
33
|
+
</ConfigProvider>
|
|
34
|
+
</StyleProvider>
|
|
35
|
+
</StrictMode>,
|
|
36
|
+
);
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
|
|
@@ -0,0 +1,128 @@
|
|
|
1
|
+
import { defineFormSchema } from "openxiangda";
|
|
2
|
+
|
|
3
|
+
export type FormComponentName =
|
|
4
|
+
| "TextField"
|
|
5
|
+
| "TextAreaField"
|
|
6
|
+
| "NumberField"
|
|
7
|
+
| "DateField"
|
|
8
|
+
| "CascadeDateField"
|
|
9
|
+
| "SelectField"
|
|
10
|
+
| "MultiSelectField"
|
|
11
|
+
| "RadioField"
|
|
12
|
+
| "CheckboxField"
|
|
13
|
+
| "UserSelectField"
|
|
14
|
+
| "DepartmentSelectField"
|
|
15
|
+
| "AttachmentField"
|
|
16
|
+
| "ImageField"
|
|
17
|
+
| "AddressField"
|
|
18
|
+
| "CascadeSelectField"
|
|
19
|
+
| "LocationField"
|
|
20
|
+
| "EditorField"
|
|
21
|
+
| "JSONField"
|
|
22
|
+
| "SubFormField";
|
|
23
|
+
|
|
24
|
+
export type FormOption = {
|
|
25
|
+
label: string;
|
|
26
|
+
value: string;
|
|
27
|
+
color?: string;
|
|
28
|
+
disabled?: boolean;
|
|
29
|
+
};
|
|
30
|
+
|
|
31
|
+
export type FieldDefinition = {
|
|
32
|
+
fieldId: string;
|
|
33
|
+
componentName: FormComponentName;
|
|
34
|
+
label: string;
|
|
35
|
+
required?: boolean;
|
|
36
|
+
rules?: Array<{
|
|
37
|
+
required?: boolean;
|
|
38
|
+
message?: string;
|
|
39
|
+
min?: number;
|
|
40
|
+
max?: number;
|
|
41
|
+
minLength?: number;
|
|
42
|
+
maxLength?: number;
|
|
43
|
+
preset?: "phone" | "idCard" | "email" | "url" | "bankCard";
|
|
44
|
+
pattern?: RegExp | string;
|
|
45
|
+
}>;
|
|
46
|
+
placeholder?: string;
|
|
47
|
+
tips?: string;
|
|
48
|
+
options?: FormOption[];
|
|
49
|
+
defaultValue?: unknown;
|
|
50
|
+
columns?: FieldDefinition[];
|
|
51
|
+
[key: string]: unknown;
|
|
52
|
+
};
|
|
53
|
+
|
|
54
|
+
export type OpenXiangdaFormSchemaInput = {
|
|
55
|
+
formMeta: {
|
|
56
|
+
formUuid: string;
|
|
57
|
+
appType: string;
|
|
58
|
+
title: string;
|
|
59
|
+
};
|
|
60
|
+
fields: FieldDefinition[];
|
|
61
|
+
};
|
|
62
|
+
|
|
63
|
+
export function option(value: string, label = value): FormOption {
|
|
64
|
+
return { label, value };
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
export function options(values: string[]): FormOption[] {
|
|
68
|
+
return values.map((value) => option(value));
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
export function createFormSchema(input: OpenXiangdaFormSchemaInput) {
|
|
72
|
+
return defineFormSchema({
|
|
73
|
+
formMeta: input.formMeta,
|
|
74
|
+
fields: input.fields.map(normalizeField),
|
|
75
|
+
layout: input.fields.map((field) => ({
|
|
76
|
+
id: `layout_${field.fieldId}`,
|
|
77
|
+
type: "field" as const,
|
|
78
|
+
fieldId: field.fieldId,
|
|
79
|
+
})),
|
|
80
|
+
});
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
function normalizeField(field: FieldDefinition): FieldDefinition {
|
|
84
|
+
return {
|
|
85
|
+
...field,
|
|
86
|
+
options:
|
|
87
|
+
needsOptionsArray(field.componentName) && !Array.isArray(field.options)
|
|
88
|
+
? []
|
|
89
|
+
: field.options,
|
|
90
|
+
columns: field.columns?.map(normalizeField),
|
|
91
|
+
rules:
|
|
92
|
+
field.rules ||
|
|
93
|
+
(field.required
|
|
94
|
+
? [
|
|
95
|
+
{
|
|
96
|
+
required: true,
|
|
97
|
+
message: `${needsSelectVerb(field.componentName) ? "请选择" : "请填写"}${field.label}`,
|
|
98
|
+
},
|
|
99
|
+
]
|
|
100
|
+
: undefined),
|
|
101
|
+
};
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
function needsOptionsArray(componentName: FormComponentName): boolean {
|
|
105
|
+
return [
|
|
106
|
+
"SelectField",
|
|
107
|
+
"MultiSelectField",
|
|
108
|
+
"RadioField",
|
|
109
|
+
"CheckboxField",
|
|
110
|
+
"CascadeSelectField",
|
|
111
|
+
].includes(componentName);
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
function needsSelectVerb(componentName: FormComponentName): boolean {
|
|
115
|
+
return [
|
|
116
|
+
"SelectField",
|
|
117
|
+
"MultiSelectField",
|
|
118
|
+
"RadioField",
|
|
119
|
+
"CheckboxField",
|
|
120
|
+
"UserSelectField",
|
|
121
|
+
"DepartmentSelectField",
|
|
122
|
+
"DateField",
|
|
123
|
+
"CascadeDateField",
|
|
124
|
+
"CascadeSelectField",
|
|
125
|
+
"ImageField",
|
|
126
|
+
"AttachmentField",
|
|
127
|
+
].includes(componentName);
|
|
128
|
+
}
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
export interface AppWorkspaceConfig {
|
|
2
|
+
appType: string;
|
|
3
|
+
appName: string;
|
|
4
|
+
platformUrl: string;
|
|
5
|
+
servicePrefix: string;
|
|
6
|
+
appKey: string;
|
|
7
|
+
appSecret: string;
|
|
8
|
+
userId: string;
|
|
9
|
+
version: string;
|
|
10
|
+
buildId: string;
|
|
11
|
+
oss: {
|
|
12
|
+
region: string;
|
|
13
|
+
bucket: string;
|
|
14
|
+
accessKeyId: string;
|
|
15
|
+
accessKeySecret: string;
|
|
16
|
+
pathPrefix: string;
|
|
17
|
+
};
|
|
18
|
+
defaults: {
|
|
19
|
+
protocolVersion: string;
|
|
20
|
+
frameworkVersion: string;
|
|
21
|
+
cssIsolation: "namespace" | "shadow" | "none";
|
|
22
|
+
formMenuParentId: string;
|
|
23
|
+
formMenuIcon: string;
|
|
24
|
+
pageMenuParentId: string;
|
|
25
|
+
pageMenuIcon: string;
|
|
26
|
+
};
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
export function defineAppWorkspaceConfig<T extends AppWorkspaceConfig>(config: T): T {
|
|
30
|
+
return config;
|
|
31
|
+
}
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
const syLowcodePath = require("node:path");
|
|
2
|
+
const syLowcodePresetModule = require("openxiangda/tailwind-preset");
|
|
3
|
+
const syLowcodePreset = syLowcodePresetModule.default ?? syLowcodePresetModule;
|
|
4
|
+
|
|
5
|
+
function resolveOpenXiangdaContent() {
|
|
6
|
+
try {
|
|
7
|
+
const packagePath = require.resolve("openxiangda");
|
|
8
|
+
const distDir = syLowcodePath.dirname(packagePath);
|
|
9
|
+
return [syLowcodePath.join(distDir, "..", "**/*.{js,mjs,cjs}")];
|
|
10
|
+
} catch {
|
|
11
|
+
return [];
|
|
12
|
+
}
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
const openxiangdaContent = resolveOpenXiangdaContent();
|
|
16
|
+
|
|
17
|
+
/** @type {import('tailwindcss').Config} */
|
|
18
|
+
module.exports = {
|
|
19
|
+
content: [
|
|
20
|
+
"./index.html",
|
|
21
|
+
"./src/**/*.{js,ts,jsx,tsx}",
|
|
22
|
+
...openxiangdaContent,
|
|
23
|
+
],
|
|
24
|
+
blocklist: ["[-:T]", "[-:TZ.]"],
|
|
25
|
+
presets: [syLowcodePreset],
|
|
26
|
+
theme: {
|
|
27
|
+
extend: {},
|
|
28
|
+
},
|
|
29
|
+
plugins: [],
|
|
30
|
+
};
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
{
|
|
2
|
+
"compilerOptions": {
|
|
3
|
+
"target": "ES2022",
|
|
4
|
+
"useDefineForClassFields": true,
|
|
5
|
+
"lib": ["ES2022", "DOM", "DOM.Iterable"],
|
|
6
|
+
"allowJs": false,
|
|
7
|
+
"skipLibCheck": true,
|
|
8
|
+
"esModuleInterop": true,
|
|
9
|
+
"allowSyntheticDefaultImports": true,
|
|
10
|
+
"strict": true,
|
|
11
|
+
"forceConsistentCasingInFileNames": true,
|
|
12
|
+
"module": "ESNext",
|
|
13
|
+
"moduleResolution": "Bundler",
|
|
14
|
+
"resolveJsonModule": true,
|
|
15
|
+
"isolatedModules": true,
|
|
16
|
+
"noEmit": true,
|
|
17
|
+
"jsx": "react-jsx",
|
|
18
|
+
"baseUrl": ".",
|
|
19
|
+
"paths": {
|
|
20
|
+
"@/*": ["src/*"]
|
|
21
|
+
}
|
|
22
|
+
},
|
|
23
|
+
"include": ["src", "app-workspace.config.ts", "vite.config.ts"]
|
|
24
|
+
}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
{
|
|
2
|
+
"compilerOptions": {
|
|
3
|
+
"target": "ES2022",
|
|
4
|
+
"module": "ESNext",
|
|
5
|
+
"moduleResolution": "Bundler",
|
|
6
|
+
"strict": true,
|
|
7
|
+
"skipLibCheck": true,
|
|
8
|
+
"types": ["node"],
|
|
9
|
+
"baseUrl": ".",
|
|
10
|
+
"paths": {
|
|
11
|
+
"@/*": ["src/*"]
|
|
12
|
+
}
|
|
13
|
+
},
|
|
14
|
+
"include": ["src/js-code-nodes/**/*.ts"]
|
|
15
|
+
}
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
import react from "@vitejs/plugin-react";
|
|
2
|
+
import { fileURLToPath } from "node:url";
|
|
3
|
+
import { defineConfig } from "vite";
|
|
4
|
+
|
|
5
|
+
export default defineConfig({
|
|
6
|
+
define: {
|
|
7
|
+
"process.env.NODE_ENV": JSON.stringify(process.env.NODE_ENV || "development"),
|
|
8
|
+
},
|
|
9
|
+
plugins: [react()],
|
|
10
|
+
resolve: {
|
|
11
|
+
alias: [
|
|
12
|
+
{
|
|
13
|
+
find: "@",
|
|
14
|
+
replacement: fileURLToPath(new URL("./src", import.meta.url)),
|
|
15
|
+
},
|
|
16
|
+
],
|
|
17
|
+
dedupe: [
|
|
18
|
+
"react",
|
|
19
|
+
"react-dom",
|
|
20
|
+
"antd",
|
|
21
|
+
"@ant-design/cssinjs",
|
|
22
|
+
"@ant-design/icons",
|
|
23
|
+
],
|
|
24
|
+
},
|
|
25
|
+
optimizeDeps: {
|
|
26
|
+
include: ["antd", "@ant-design/cssinjs", "@ant-design/icons", "antd-mobile"],
|
|
27
|
+
},
|
|
28
|
+
server: {
|
|
29
|
+
host: "127.0.0.1",
|
|
30
|
+
port: 5174,
|
|
31
|
+
},
|
|
32
|
+
});
|