cardbuddy 0.22.0 → 0.24.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 +11 -11
- package/dist/cli.js +2 -2
- package/dist/config.js +3 -3
- package/dist/init.js +13 -13
- package/dist/mcp.js +1 -1
- package/dist/preview-editor/assets/{index-CPpLZZyi.js → index-BumNBo-n.js} +81 -80
- package/dist/preview-editor/assets/{index-CU8zVA2P.css → index-MWKPP9nd.css} +1 -1
- package/dist/preview-editor/index.html +2 -2
- package/dist/skills-upgrade.js +1 -1
- package/dist/standalone.js +2 -2
- package/dist/vendored/card-editor/runtime/adapter.js +10 -11
- package/dist/vendored/mcp/client.mjs +50 -13
- package/dist/vendored/mcp/tools.mjs +13 -7
- package/dist/vendored/server/core/ai-chat.js +540 -183
- package/dist/vendored/server/core/assetProxy.js +1 -1
- package/dist/vendored/server/core/browser.js +1 -1
- package/dist/vendored/server/core/cardCompile.js +202 -0
- package/dist/vendored/server/core/cardDigest.js +324 -0
- package/dist/vendored/server/core/cardExport.js +5 -5
- package/dist/vendored/server/core/cardFiles.js +1 -1
- package/dist/vendored/server/core/cardHistoryRemote.js +1 -1
- package/dist/vendored/server/core/cardImportMeta.js +1 -1
- package/dist/vendored/server/core/cardListCache.js +92 -10
- package/dist/vendored/server/core/cardPublish.js +11 -6
- package/dist/vendored/server/core/cardPublishVersions.js +8 -8
- package/dist/vendored/server/core/cardSave.js +14 -10
- package/dist/vendored/server/core/cardSidecar.js +3 -3
- package/dist/vendored/server/core/cardSync.js +35 -23
- package/dist/vendored/server/core/cardVersion.js +1 -1
- package/dist/vendored/server/core/flameCompile/client.js +466 -0
- package/dist/vendored/server/core/flameCompile/clientElements.js +372 -0
- package/dist/vendored/server/core/flameCompile/common.js +253 -0
- package/dist/vendored/server/core/flameCompile/h5.js +326 -0
- package/dist/vendored/server/core/flameCompile/index.js +126 -0
- package/dist/vendored/server/core/flameCompile/model.js +162 -0
- package/dist/vendored/server/core/index.js +12 -6
- package/dist/vendored/server/core/logger.js +1 -1
- package/dist/vendored/server/core/remoteCard.js +5 -5
- package/dist/vendored/server/core/skillPaths.js +1 -1
- package/dist/vendored/server/core/sliceUpload.js +4 -4
- package/dist/vendored/skills/README.md +13 -13
- package/dist/vendored/skills/card-doctor/SKILL.md +2 -2
- package/dist/vendored/skills/dsl-card-ai/SKILL.md +4 -4
- package/dist/vendored/skills/dsl-card-generator/SKILL.md +2 -2
- package/dist/vendored/skills/dsl-card-generator/references/amount_formatting.md +1 -1
- package/dist/vendored/skills/dsl-card-generator/references/build_protocol.md +54 -0
- package/dist/vendored/skills/dsl-card-generator/references/component_rules.md +2 -2
- package/dist/vendored/skills/dsl-card-generator/references/converge_protocol.md +36 -0
- package/dist/vendored/skills/dsl-card-generator/references/event_patterns.md +1 -1
- package/dist/vendored/skills/dsl-card-generator/references/generation_pitfalls.md +1 -1
- package/dist/vendored/skills/dsl-card-generator/references/image_to_card.md +1 -1
- package/dist/vendored/skills/dsl-card-generator/references/quickref.md +1 -1
- package/dist/vendored/skills/dsl-card-generator/references/recipes.md +4 -4
- package/dist/vendored/skills/dsl-card-generator/references/rules.md +1 -1
- package/dist/vendored/skills/dsl-card-generator/references/slices_convention.md +6 -6
- package/dist/vendored/skills/dsl-card-generator/scripts/inventory_schemas.py +1 -1
- package/dist/vendored/skills/dsl-card-generator/scripts/lib/scaffold.mjs +1 -1
- package/dist/vendored/skills/dsl-card-generator/scripts/lib/slice_dedupe.mjs +2 -2
- package/dist/vendored/skills/dsl-card-generator/vendor/preview/assets/standalone-CeVX_y-M.js +137 -0
- package/dist/vendored/skills/dsl-card-generator/vendor/preview/assets/standalone-DiEiY59H.css +1 -0
- package/dist/vendored/skills/dsl-card-generator/vendor/preview/standalone.html +2 -2
- package/dist/vendored/skills/{finmall-card-sync → platform-card-sync}/SKILL.md +26 -26
- package/dist/vendored/skills/{finmall-card-sync → platform-card-sync}/scripts/api_batch_sync.mjs +184 -162
- package/dist/vendored/skills/{finmall-card-sync → platform-card-sync}/scripts/slice_upload.mjs +48 -29
- package/dist/vendored/skills/{finmall-session-navigator → platform-session-navigator}/SKILL.md +13 -13
- package/dist/vendored/skills/{finmall-session-navigator → platform-session-navigator}/scripts/package-lock.json +2 -2
- package/dist/vendored/skills/{finmall-session-navigator → platform-session-navigator}/scripts/package.json +2 -2
- package/dist/vendored/skills/{finmall-session-navigator/scripts/finmall_login.mjs → platform-session-navigator/scripts/platform_login.mjs} +41 -31
- package/dist/vendored/skills/{finmall-session-navigator → platform-session-navigator}/scripts/session-manager.mjs +17 -17
- package/dist/vendored/skills/shared/README.md +21 -21
- package/dist/vendored/skills/shared/auth-model.md +8 -10
- package/dist/vendored/skills/shared/{finmall-config.mjs → platform-config.mjs} +10 -10
- package/dist/vendored/tools/{finmall-env.mjs → platform-env.mjs} +13 -13
- package/package.json +1 -1
- package/dist/vendored/skills/dsl-card-generator/vendor/preview/assets/standalone-BCLshIzC.css +0 -1
- package/dist/vendored/skills/dsl-card-generator/vendor/preview/assets/standalone-pP5kTKiI.js +0 -88
|
@@ -0,0 +1,466 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* 客户端产物编译(GaiaX 明文模板包)
|
|
3
|
+
*
|
|
4
|
+
* 1:1 迁移自 flame-release-mange(Java)的
|
|
5
|
+
* client/NativeEngine.java
|
|
6
|
+
* client/convert/{CardConvert,ComponentConvert,StyleConvert,PropertyConvert,
|
|
7
|
+
* EventActionConvert,DirectiveConvert,DataConvert,ConditionConvert}
|
|
8
|
+
* client/entity/*(TemplateEntity / JsonFileEntity / CssFileEntity / DataBindingFileEntity ...)
|
|
9
|
+
*
|
|
10
|
+
* 产物(每个模板一个目录):
|
|
11
|
+
* index.json 视图层级 { id, type:'gaia-template', sub-type?, package, layers }
|
|
12
|
+
* index.css `#nodeId { prop:value; }`
|
|
13
|
+
* index.databinding { data:{ nodeId:{...} }, event:{ nodeId:{...} } }
|
|
14
|
+
* index.data 卡片入参默认值(仅主模板)
|
|
15
|
+
* index.js Component({ onShow/onReady/... })
|
|
16
|
+
* index.style index.js 的 SM4-CBC 密文(iOS 侧优先读它,见 GXTemplateReader)
|
|
17
|
+
*
|
|
18
|
+
* 列表类组件(ListLayout / GridLayout)会拆成三级模板:
|
|
19
|
+
* <cardCode> ← 外层占位(grid 节点 + 属性绑定)
|
|
20
|
+
* <cardCode>_sub_<cid> ← 真正的 grid 模板(含 column 等)
|
|
21
|
+
* <cardCode>_sub_<cid>_item ← 循环项模板(子组件挂这里)
|
|
22
|
+
* 该结构由平台侧历史产物固化,客户端只认这套约定,不要简化成单层。
|
|
23
|
+
*/
|
|
24
|
+
|
|
25
|
+
import { elementOf, styleConst, styleVar } from './clientElements.js'
|
|
26
|
+
import { convertCondition, convertPropsClient, convertExpression, hasText } from './common.js'
|
|
27
|
+
|
|
28
|
+
/* ------------------------------- 文件实体 ------------------------------- */
|
|
29
|
+
|
|
30
|
+
function createTemplate(code) {
|
|
31
|
+
return {
|
|
32
|
+
code,
|
|
33
|
+
cssRules: [], // [{ name, contents: [] }]
|
|
34
|
+
dataProps: {}, // index.data
|
|
35
|
+
dataBind: { data: {}, event: {} }, // index.databinding
|
|
36
|
+
js: { onShow: [], onDataInit: [], onReady: [], onHide: [], onReuse: [], onDestroy: [] },
|
|
37
|
+
json: { code: '', type: '', subType: '', packageInfo: {}, other: {}, layers: [] },
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
function addDataBind(template, componentId, map) {
|
|
42
|
+
const bucket = template.dataBind.data
|
|
43
|
+
bucket[componentId] = Object.assign(bucket[componentId] || {}, map)
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
function ensureDataBind(template, componentId) {
|
|
47
|
+
const bucket = template.dataBind.data
|
|
48
|
+
if (!bucket[componentId]) bucket[componentId] = {}
|
|
49
|
+
return bucket[componentId]
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
function addEventBind(template, componentId, map) {
|
|
53
|
+
const bucket = template.dataBind.event
|
|
54
|
+
bucket[componentId] = Object.assign(bucket[componentId] || {}, map)
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
const LIFECYCLES = ['onShow', 'onDataInit', 'onReady', 'onHide', 'onReuse', 'onDestroy']
|
|
58
|
+
|
|
59
|
+
function addLifecycleCode(template, lifeCycle, code) {
|
|
60
|
+
if (LIFECYCLES.includes(lifeCycle)) template.js[lifeCycle].push(code)
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
/* ------------------------------- 属性转换 ------------------------------- */
|
|
64
|
+
|
|
65
|
+
/** 常量域:标量 JSON 编码,Map/List 递归(与 Java convertConstField 等价) */
|
|
66
|
+
function normalizeConst(value) {
|
|
67
|
+
if (value === null || value === undefined) return undefined
|
|
68
|
+
if (Array.isArray(value)) return value.map((item) => (item && typeof item === 'object' ? normalizeConstMap(item) : item))
|
|
69
|
+
if (typeof value === 'object') return normalizeConstMap(value)
|
|
70
|
+
return JSON.stringify(value)
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
function normalizeConstMap(map) {
|
|
74
|
+
const out = {}
|
|
75
|
+
for (const [k, v] of Object.entries(map)) {
|
|
76
|
+
const normalized = normalizeConst(v)
|
|
77
|
+
if (normalized !== undefined) out[k] = normalized
|
|
78
|
+
}
|
|
79
|
+
return out
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
/**
|
|
83
|
+
* 变量域合并:字符串非空才写入(表达式为空表示「沿用静态值」),
|
|
84
|
+
* 对象/数组递归合并,保证同一节点既有静态也有动态属性时不互相覆盖。
|
|
85
|
+
*/
|
|
86
|
+
function mergeVarField(target, key, value) {
|
|
87
|
+
if (value === null || value === undefined) return
|
|
88
|
+
if (Array.isArray(value)) {
|
|
89
|
+
const list = Array.isArray(target[key]) ? target[key] : []
|
|
90
|
+
target[key] = list
|
|
91
|
+
value.forEach((item, index) => {
|
|
92
|
+
if (!list[index]) list[index] = {}
|
|
93
|
+
if (item && typeof item === 'object') {
|
|
94
|
+
for (const [k, v] of Object.entries(item)) mergeVarField(list[index], k, v)
|
|
95
|
+
}
|
|
96
|
+
})
|
|
97
|
+
return
|
|
98
|
+
}
|
|
99
|
+
if (typeof value === 'object') {
|
|
100
|
+
const bucket = target[key] && typeof target[key] === 'object' ? target[key] : {}
|
|
101
|
+
target[key] = bucket
|
|
102
|
+
for (const [k, v] of Object.entries(value)) mergeVarField(bucket, k, v)
|
|
103
|
+
return
|
|
104
|
+
}
|
|
105
|
+
if (typeof value === 'string') {
|
|
106
|
+
if (hasText(value)) target[key] = value
|
|
107
|
+
return
|
|
108
|
+
}
|
|
109
|
+
target[key] = value
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
/** 组件属性 → databinding(静态走 const 归一化,动态覆盖) */
|
|
113
|
+
function convertComponentProps(component, template) {
|
|
114
|
+
const { const: constProps, var: varProps } = convertPropsClient(component.properties)
|
|
115
|
+
const out = normalizeConstMap(constProps)
|
|
116
|
+
|
|
117
|
+
for (const [key, value] of Object.entries(varProps)) mergeVarField(out, key, value)
|
|
118
|
+
|
|
119
|
+
addDataBind(template, component.componentId, out)
|
|
120
|
+
return { constProps, varProps, merged: out }
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
/* ------------------------------- 样式转换 ------------------------------- */
|
|
124
|
+
|
|
125
|
+
function convertStyle(className, style, template, componentId) {
|
|
126
|
+
const { const: constProps, var: varProps } = convertPropsClient(style.properties)
|
|
127
|
+
|
|
128
|
+
template.cssRules.push({ name: `#${componentId}`, contents: styleConst(className, constProps) })
|
|
129
|
+
|
|
130
|
+
const dynamic = {}
|
|
131
|
+
const vars = styleVar(varProps)
|
|
132
|
+
for (const [k, v] of Object.entries(vars)) {
|
|
133
|
+
if (hasText(v)) dynamic[k] = v
|
|
134
|
+
}
|
|
135
|
+
addDataBind(template, componentId, { extend: dynamic })
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
/* ------------------------------- 事件转换 ------------------------------- */
|
|
139
|
+
|
|
140
|
+
function convertEventBody(eventAction, component, engine, warnings) {
|
|
141
|
+
const actionType = eventAction.actionType
|
|
142
|
+
const { const: constProps } = convertPropsClient(eventAction.properties)
|
|
143
|
+
const desc = component ? elementOf(component.className) : null
|
|
144
|
+
let out = ''
|
|
145
|
+
|
|
146
|
+
// Canvas 的 onMeasured 前置:把画布尺寸换算进缩放坐标系
|
|
147
|
+
if (
|
|
148
|
+
component &&
|
|
149
|
+
desc &&
|
|
150
|
+
desc.type === 'canvas' &&
|
|
151
|
+
eventAction.eventKey === 'onMeasured' &&
|
|
152
|
+
actionType === 'customAction'
|
|
153
|
+
) {
|
|
154
|
+
out +=
|
|
155
|
+
'event.canvas = new Canvas(event.canvasId);' +
|
|
156
|
+
'event.canvas.zoom = (event.screenWidth || 375)/375;' +
|
|
157
|
+
'event.canvas.width = event.width/event.canvas.zoom;' +
|
|
158
|
+
'event.canvas.height = event.height/event.canvas.zoom;' +
|
|
159
|
+
'event.width = event.canvas.width;' +
|
|
160
|
+
'event.height = event.canvas.height;'
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
if (actionType === 'customAction') {
|
|
164
|
+
const fn = constProps.function
|
|
165
|
+
const code = fn && typeof fn === 'object' ? fn.code : null
|
|
166
|
+
if (typeof code === 'string') out += code
|
|
167
|
+
else warnings.push(`事件 ${eventAction.eventKey} 的 customAction 缺少 function.code,已跳过`)
|
|
168
|
+
} else if (actionType === 'closeAlertCard') {
|
|
169
|
+
out += `ynet.callJSAPI('${actionType}',${JSON.stringify({ cardCode: engine.code })});`
|
|
170
|
+
} else if (hasText(actionType)) {
|
|
171
|
+
out += `ynet.callJSAPI('${actionType}',${JSON.stringify(constProps)});`
|
|
172
|
+
}
|
|
173
|
+
|
|
174
|
+
if (
|
|
175
|
+
component &&
|
|
176
|
+
desc &&
|
|
177
|
+
desc.type === 'canvas' &&
|
|
178
|
+
eventAction.eventKey === 'onMeasured' &&
|
|
179
|
+
actionType === 'customAction'
|
|
180
|
+
) {
|
|
181
|
+
out += "\nevent.canvas.getContext('2d').endDraw();"
|
|
182
|
+
}
|
|
183
|
+
|
|
184
|
+
return out
|
|
185
|
+
}
|
|
186
|
+
|
|
187
|
+
function convertEventAction(eventAction, template, engine, component, warnings) {
|
|
188
|
+
if (!hasText(eventAction.eventKey) || !hasText(eventAction.actionType)) return
|
|
189
|
+
|
|
190
|
+
if (!component) {
|
|
191
|
+
// 卡片生命周期:包一层箭头函数隔离作用域,再在生命周期里立即执行
|
|
192
|
+
const body = convertEventBody(eventAction, null, engine, warnings)
|
|
193
|
+
addLifecycleCode(template, eventAction.eventKey, `((event) => {${body}\n})(event);`)
|
|
194
|
+
return
|
|
195
|
+
}
|
|
196
|
+
|
|
197
|
+
const cid = component.componentId
|
|
198
|
+
const body = convertEventBody(eventAction, component, engine, warnings)
|
|
199
|
+
const code =
|
|
200
|
+
`let ${cid}=this.getElementById('${cid}');` +
|
|
201
|
+
`if(${cid}){` +
|
|
202
|
+
`${cid}.addEventListener('${eventAction.eventKey}',(event)=>{${body}\n})` +
|
|
203
|
+
`}`
|
|
204
|
+
template.js.onReady.push(code)
|
|
205
|
+
}
|
|
206
|
+
|
|
207
|
+
/** 双向绑定:value 绑定到变量时补 input 监听,把输入写回状态 */
|
|
208
|
+
function convertTwoWayBinding(component, varProps, template) {
|
|
209
|
+
const desc = elementOf(component.className)
|
|
210
|
+
if (!desc.twoWayBinding) return
|
|
211
|
+
const modelVar = varProps.value
|
|
212
|
+
if (!hasText(modelVar)) return
|
|
213
|
+
const cid = component.componentId
|
|
214
|
+
template.js.onReady.push(
|
|
215
|
+
`let _${cid}_=this.getElementById('${cid}');` +
|
|
216
|
+
`if(_${cid}_){` +
|
|
217
|
+
`_${cid}_.addEventListener('input',(event)=>{` +
|
|
218
|
+
`this._syncData_(${JSON.stringify(modelVar)}, event)` +
|
|
219
|
+
`})` +
|
|
220
|
+
`}`
|
|
221
|
+
)
|
|
222
|
+
}
|
|
223
|
+
|
|
224
|
+
/* ------------------------------- 指令转换 ------------------------------- */
|
|
225
|
+
|
|
226
|
+
function convertDirectives(component, template, warnings) {
|
|
227
|
+
const { const: constProps } = convertPropsClient(component.directives)
|
|
228
|
+
const showProps = constProps['v-show']
|
|
229
|
+
if (!showProps || typeof showProps !== 'object') return
|
|
230
|
+
|
|
231
|
+
const showType = showProps.showType
|
|
232
|
+
if (showType === '00') return
|
|
233
|
+
|
|
234
|
+
const conditionMap = showProps.condition
|
|
235
|
+
if (!conditionMap || typeof conditionMap !== 'object') return
|
|
236
|
+
|
|
237
|
+
const bucket = ensureDataBind(template, component.componentId)
|
|
238
|
+
const extend = bucket.extend && typeof bucket.extend === 'object' ? bucket.extend : {}
|
|
239
|
+
bucket.extend = extend
|
|
240
|
+
|
|
241
|
+
const expression = conditionMap.expression
|
|
242
|
+
if (hasText(expression)) {
|
|
243
|
+
if (showType === '01') extend.display = `(${expression}) ? 'block' : 'none'`
|
|
244
|
+
else if (showType === '02') extend.display = `(${expression}) ? 'none' : 'block'`
|
|
245
|
+
return
|
|
246
|
+
}
|
|
247
|
+
|
|
248
|
+
if (Array.isArray(conditionMap.group) && conditionMap.group.length > 0) {
|
|
249
|
+
const expr = convertCondition(conditionMap.group)
|
|
250
|
+
if (showType === '01') extend.display = `${expr} ? 'block' : 'none'`
|
|
251
|
+
else if (showType === '02') extend.display = `${expr} ? 'none' : 'block'`
|
|
252
|
+
return
|
|
253
|
+
}
|
|
254
|
+
|
|
255
|
+
warnings.push(`组件 ${component.componentId} 的 v-show 条件为空,已忽略`)
|
|
256
|
+
}
|
|
257
|
+
|
|
258
|
+
/* -------------------------------- 引擎 --------------------------------- */
|
|
259
|
+
|
|
260
|
+
export function createClientCompiler(card, { version = '', warnings = [] } = {}) {
|
|
261
|
+
const engine = { code: card.code, version, templates: [] }
|
|
262
|
+
|
|
263
|
+
const newTemplate = () => {
|
|
264
|
+
const t = createTemplate('')
|
|
265
|
+
engine.templates.push(t)
|
|
266
|
+
return t
|
|
267
|
+
}
|
|
268
|
+
|
|
269
|
+
const convertBaseInfo = (code, subType, template, width) => {
|
|
270
|
+
template.json.code = code
|
|
271
|
+
template.json.type = 'gaia-template'
|
|
272
|
+
if (hasText(subType)) template.json.subType = subType
|
|
273
|
+
template.json.packageInfo = {
|
|
274
|
+
id: code,
|
|
275
|
+
version: engine.version,
|
|
276
|
+
dependencies: {},
|
|
277
|
+
}
|
|
278
|
+
if (width !== undefined) template.json.packageInfo.width = width
|
|
279
|
+
}
|
|
280
|
+
|
|
281
|
+
/* ---------------------------- 组件递归 ---------------------------- */
|
|
282
|
+
|
|
283
|
+
const convertArray = (components, template, layers) => {
|
|
284
|
+
for (const component of components) convert(component, template, layers)
|
|
285
|
+
}
|
|
286
|
+
|
|
287
|
+
const convert = (component, template, layers) => {
|
|
288
|
+
const desc = elementOf(component.className)
|
|
289
|
+
if (desc.unknown) warnings.push(`未识别的组件类型 ${component.className}(${component.componentId}),按 view 输出`)
|
|
290
|
+
|
|
291
|
+
if (desc.isNewTemplate) {
|
|
292
|
+
createComponentTemplate(component, template, layers, desc)
|
|
293
|
+
return
|
|
294
|
+
}
|
|
295
|
+
convertComponent(component, template, layers, desc)
|
|
296
|
+
}
|
|
297
|
+
|
|
298
|
+
const convertComponent = (component, template, layers, desc) => {
|
|
299
|
+
const layer = { id: component.componentId, type: desc.type, layers: [] }
|
|
300
|
+
layers.push(layer)
|
|
301
|
+
|
|
302
|
+
convertStyle(component.className, component.style, template, component.componentId)
|
|
303
|
+
|
|
304
|
+
const { varProps } = convertComponentProps(component, template)
|
|
305
|
+
convertTwoWayBinding(component, varProps, template)
|
|
306
|
+
|
|
307
|
+
for (const ea of component.eventactions) convertEventAction(ea, template, engine, component, warnings)
|
|
308
|
+
|
|
309
|
+
convertDirectives(component, template, warnings)
|
|
310
|
+
|
|
311
|
+
const slot = component.slots && component.slots[0]
|
|
312
|
+
if (slot) convertArray(slot.components, template, layer.layers)
|
|
313
|
+
}
|
|
314
|
+
|
|
315
|
+
/**
|
|
316
|
+
* 列表 / 网格:外层占位 + 子模板 + 循环项模板(三级)
|
|
317
|
+
* 注意:平台侧会把 componentId 改写成子模板编码,后续样式与绑定的 key 都用新编码。
|
|
318
|
+
*/
|
|
319
|
+
const createComponentTemplate = (component, template, layers, desc) => {
|
|
320
|
+
const newTemplateCode = `${engine.code}_sub_${component.componentId}`
|
|
321
|
+
component.componentId = newTemplateCode
|
|
322
|
+
|
|
323
|
+
layers.push({ id: newTemplateCode, type: 'gaia-template', subType: 'custom', layers: [] })
|
|
324
|
+
|
|
325
|
+
convertComponentProps(component, template)
|
|
326
|
+
template.json.packageInfo.dependencies[newTemplateCode] = engine.version
|
|
327
|
+
|
|
328
|
+
const componentTemplate = newTemplate()
|
|
329
|
+
componentTemplate.code = newTemplateCode
|
|
330
|
+
addDataBind(componentTemplate, newTemplateCode, { value: '$$' })
|
|
331
|
+
convertBaseInfo(newTemplateCode, desc.type, componentTemplate)
|
|
332
|
+
|
|
333
|
+
convertTemplateComponent(component, componentTemplate, desc)
|
|
334
|
+
}
|
|
335
|
+
|
|
336
|
+
const convertTemplateComponent = (component, template, desc) => {
|
|
337
|
+
convertStyle(component.className, component.style, template, component.componentId)
|
|
338
|
+
|
|
339
|
+
const { const: constProps } = convertPropsClient(component.properties)
|
|
340
|
+
const constTransferred = desc.newTemplatePropsConst
|
|
341
|
+
? desc.newTemplatePropsConst(constProps)
|
|
342
|
+
: constProps
|
|
343
|
+
for (const [k, v] of Object.entries(constTransferred)) template.json.other[k] = v
|
|
344
|
+
// 循环项数据由 databinding 的 `$$` 提供,模板顶层不保留 value
|
|
345
|
+
delete template.json.other.value
|
|
346
|
+
|
|
347
|
+
for (const ea of component.eventactions) convertEventAction(ea, template, engine, component, warnings)
|
|
348
|
+
convertDirectives(component, template, warnings)
|
|
349
|
+
|
|
350
|
+
const itemTemplateCode = `${component.componentId}_item`
|
|
351
|
+
template.json.layers.push({ id: itemTemplateCode, type: 'gaia-template', subType: 'custom', layers: [] })
|
|
352
|
+
template.json.packageInfo.dependencies[itemTemplateCode] = engine.version
|
|
353
|
+
|
|
354
|
+
const itemTemplate = newTemplate()
|
|
355
|
+
itemTemplate.code = itemTemplateCode
|
|
356
|
+
convertBaseInfo(itemTemplateCode, '', itemTemplate)
|
|
357
|
+
|
|
358
|
+
// 循环项样式:宽度由布局方向决定(横向列表 auto,其余撑满)
|
|
359
|
+
// 注意归属 —— 平台侧 StyleConvert.convertItem 收的是 itemComponentTemplate,
|
|
360
|
+
// 规则落在**第三层(_item)模板自己的 index.css** 里,不能挂到第二层。
|
|
361
|
+
if (desc.itemStyleConst) {
|
|
362
|
+
const contents = desc.itemStyleConst(constProps)
|
|
363
|
+
if (contents && contents.length) {
|
|
364
|
+
itemTemplate.cssRules.push({ name: `#${itemTemplateCode}`, contents })
|
|
365
|
+
}
|
|
366
|
+
}
|
|
367
|
+
|
|
368
|
+
const slot = component.slots && component.slots[0]
|
|
369
|
+
if (slot) convertArray(slot.components, itemTemplate, itemTemplate.json.layers)
|
|
370
|
+
}
|
|
371
|
+
|
|
372
|
+
/* ------------------------------ 卡片 ------------------------------ */
|
|
373
|
+
|
|
374
|
+
const convertCard = () => {
|
|
375
|
+
const template = newTemplate()
|
|
376
|
+
|
|
377
|
+
template.code = card.code
|
|
378
|
+
template.json.code = card.code
|
|
379
|
+
template.json.type = 'gaia-template'
|
|
380
|
+
template.json.packageInfo = {
|
|
381
|
+
id: card.code,
|
|
382
|
+
version: engine.version,
|
|
383
|
+
dependencies: {},
|
|
384
|
+
params: [],
|
|
385
|
+
}
|
|
386
|
+
if (card.width) template.json.packageInfo.width = card.width
|
|
387
|
+
|
|
388
|
+
// 数据定义:入参树进 package.params,默认值进 index.data
|
|
389
|
+
template.json.packageInfo.params = card.data.props.map(toParamField)
|
|
390
|
+
for (const field of card.data.props) {
|
|
391
|
+
template.dataProps[field.key] = field.defaultValue
|
|
392
|
+
}
|
|
393
|
+
|
|
394
|
+
convertStyle(card.className, card.style, template, card.code)
|
|
395
|
+
|
|
396
|
+
for (const ea of card.eventactions) convertEventAction(ea, template, engine, null, warnings)
|
|
397
|
+
|
|
398
|
+
convertArray(card.components, template, template.json.layers)
|
|
399
|
+
}
|
|
400
|
+
|
|
401
|
+
convertCard()
|
|
402
|
+
return engine
|
|
403
|
+
}
|
|
404
|
+
|
|
405
|
+
function toParamField(field) {
|
|
406
|
+
return {
|
|
407
|
+
name: field.key,
|
|
408
|
+
remark: field.name,
|
|
409
|
+
type: field.type,
|
|
410
|
+
child: (field.children || []).map(toParamField),
|
|
411
|
+
}
|
|
412
|
+
}
|
|
413
|
+
|
|
414
|
+
/* ------------------------------ 文件序列化 ------------------------------ */
|
|
415
|
+
|
|
416
|
+
export function serializeTemplateJson(template) {
|
|
417
|
+
const out = { ...template.json.other }
|
|
418
|
+
out.id = template.json.code
|
|
419
|
+
out.type = template.json.type
|
|
420
|
+
if (hasText(template.json.subType)) out['sub-type'] = template.json.subType
|
|
421
|
+
out.package = template.json.packageInfo
|
|
422
|
+
out.layers = serializeLayers(template.json.layers)
|
|
423
|
+
// 紧凑输出:平台侧走 fastjson 的 JSON.toJSONString,同样无缩进。
|
|
424
|
+
// 若这里加缩进,产物虽语义相同但字节全行不同,与线上产物对拍就失去意义。
|
|
425
|
+
return JSON.stringify(out)
|
|
426
|
+
}
|
|
427
|
+
|
|
428
|
+
function serializeLayers(layers) {
|
|
429
|
+
return layers.map((layer) => {
|
|
430
|
+
const out = { id: layer.id, type: layer.type }
|
|
431
|
+
if (hasText(layer.subType)) out['sub-type'] = layer.subType
|
|
432
|
+
if (layer.layers && layer.layers.length) out.layers = serializeLayers(layer.layers)
|
|
433
|
+
return out
|
|
434
|
+
})
|
|
435
|
+
}
|
|
436
|
+
|
|
437
|
+
export function serializeTemplateCss(template) {
|
|
438
|
+
return template.cssRules
|
|
439
|
+
.map((rule) => {
|
|
440
|
+
const body = rule.contents.map((line) => `${line};\n`).join('')
|
|
441
|
+
return `${rule.name}{\n${body}}\n`
|
|
442
|
+
})
|
|
443
|
+
.join('')
|
|
444
|
+
}
|
|
445
|
+
|
|
446
|
+
export function serializeTemplateDataBinding(template) {
|
|
447
|
+
const result = {}
|
|
448
|
+
if (Object.keys(template.dataBind.data).length) result.data = template.dataBind.data
|
|
449
|
+
if (Object.keys(template.dataBind.event).length) result.event = template.dataBind.event
|
|
450
|
+
return JSON.stringify(result)
|
|
451
|
+
}
|
|
452
|
+
|
|
453
|
+
export function serializeTemplateData(template) {
|
|
454
|
+
return JSON.stringify(template.dataProps)
|
|
455
|
+
}
|
|
456
|
+
|
|
457
|
+
export function serializeTemplateJs(template) {
|
|
458
|
+
let out = 'Component({'
|
|
459
|
+
for (const lifeCycle of LIFECYCLES) {
|
|
460
|
+
const codes = template.js[lifeCycle]
|
|
461
|
+
if (!codes.length) continue
|
|
462
|
+
out += `${lifeCycle}: function(event){${codes.join('')}},`
|
|
463
|
+
}
|
|
464
|
+
out += '});'
|
|
465
|
+
return out
|
|
466
|
+
}
|