Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
45 changes: 37 additions & 8 deletions packages/canvas/render/src/application-function/global-state.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,14 +13,43 @@ export function useGlobalState() {
watchEffect(() => {
reset(stores)
globalState.value.forEach(({ id, state = {}, getters = {} }) => {
const computedGetters = Object.keys(getters).reduce(
(acc, key) => ({
...acc,
[key]: new Func('return ' + getters[key])().call(acc, state) // parseData(getters[key], null, acc)?.call?.(acc, state) //理论上不应该走parseData, unibuy代码遗留
}),
{}
)
stores[id] = { ...state, ...computedGetters }
const hasGetters = Object.keys(getters).length > 0

if (Array.isArray(state)) {
if (!hasGetters) {
stores[id] = [...state]
} else {
const computedGetters = {}
Object.keys(getters).forEach((key) => {
try {
computedGetters[key] = new Func('return ' + getters[key])().call(computedGetters, state)
} catch (error) {
computedGetters[key] = undefined
}
})

const arrayWithGetters = [...state]
Object.assign(arrayWithGetters, computedGetters)
stores[id] = arrayWithGetters
}
} else if (typeof state !== 'object' || state === null) {
stores[id] = state
} else {
if (!hasGetters) {
stores[id] = { ...state }
} else {
const computedGetters = {}
Object.keys(getters).forEach((key) => {
try {
computedGetters[key] = new Func('return ' + getters[key])().call(computedGetters, state)
} catch (error) {
computedGetters[key] = undefined
}
})

stores[id] = Object.assign({}, state, computedGetters)
}
}
})
})
return {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -505,14 +505,17 @@ export default {
state.variables = {}

const stores = useResource().appSchemaState.globalState
stores.forEach(({ id, state: storeState = {}, getters = {} }) => {
const loadProp = (prop) => {
const propBinding = `${id}.${prop}`
state.variables[propBinding] = propBinding
}

Object.keys(storeState).forEach(loadProp)
Object.keys(getters).forEach(loadProp)
stores.forEach(({ id, state: _storeState = {}, _getters = {} }) => {
state.variables[id] = id
// fix: store 列表错误渲染成子属性列表
// store 值处理迁移到 global-state.ts 进行处理
// const loadProp = (prop) => {
// const propBinding = `${id}.${prop}`
// state.variables[propBinding] = propBinding
// }

// Object.keys(storeState).forEach(loadProp)
// Object.keys(getters).forEach(loadProp)
})
} else if (item.id === 'loop') {
state.bindPrefix = ''
Expand Down
4 changes: 2 additions & 2 deletions packages/plugins/materials/src/composable/useResource.js
Original file line number Diff line number Diff line change
Expand Up @@ -143,8 +143,8 @@ const fetchAppState = async () => {

appSchemaState.bridge = appData.bridge
appSchemaState.utils = appData.utils
appSchemaState.isDemo = appData.meta?.is_demo
appSchemaState.globalState = appData?.meta.global_state
appSchemaState.isDemo = appData.meta?.isDemo || appData.meta?.is_demo
appSchemaState.globalState = appData?.meta.globalState || appData?.meta.global_state

// 词条语言为空时使用默认的语言
const defaultLocales = [
Expand Down
9 changes: 9 additions & 0 deletions packages/toolbars/generate-code/src/Main.vue
Original file line number Diff line number Diff line change
Expand Up @@ -127,6 +127,15 @@ export default {
}
})

// 处理 i18n 对象中可能为 null 的情况
if (metaData.i18n) {
Object.keys(metaData.i18n).forEach((langKey) => {
metaData.i18n[langKey] = metaData.i18n[langKey] || {}
})
} else {
metaData.i18n = {}
}

const appSchema = {
// metaData 包含dataSource、utils、i18n、globalState
...metaData,
Expand Down
4 changes: 2 additions & 2 deletions scripts/buildMaterials.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -150,14 +150,14 @@ const generateComponents = () => {

componentsMap.push({ component, npm })

const { package: packageName = '', version = '', exportName = '' } = npm || {}

if (connection.connected) {
connection.initDB(material)
}

appInfo.materialHistory.components = componentsMap

const { package: packageName = '', version = '', exportName = '' } = npm || {}

const mapItem = {
componentName: component,
package: packageName,
Expand Down
50 changes: 37 additions & 13 deletions scripts/connection.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -15,9 +15,9 @@ dotenv.config({ path: `${pathsDotenv}.local` })
const { SQL_HOST, SQL_PORT, SQL_USER, SQL_PASSWORD, SQL_DATABASE } = process.env

// 组件表名称
const componentsTableName = 'user_components'
const componentsTableName = 't_component'
// 组件关联到物料资产包的id
const materialHistoryId = 639
const materialHistoryId = 1
// 数据库配置
const mysqlConfig = {
host: SQL_HOST, // 主机名(服务器地址)
Expand Down Expand Up @@ -202,9 +202,10 @@ class MysqlConnection {

/**
* 新建的组件关联物料资产包
* @deprecated 物料资产包已废弃,使用relationMaterialHistory替代
* @param {number} id 新建的组件id
*/
relationMaterialHistory(id) {
relationMaterialBlockHistory(id) {
const uniqSql = `SELECT * FROM \`material_histories_components__user_components_mhs\` WHERE \`material-history_id\`=${materialHistoryId} AND \`user-component_id\`=${id}`
this.query(uniqSql).then((result) => {
if (!result.length) {
Expand All @@ -215,6 +216,20 @@ class MysqlConnection {
})
}

/**
* 新建的组件关联物料资产包
* @param {number} id 新建的组件id
*/
relationMaterialHistory(id) {
const uniqSql = `SELECT * FROM \`r_material_history_component\` WHERE \`material_history_id\`=${materialHistoryId} AND \`component_id\`=${id}`
this.query(uniqSql).then((result) => {
if (!result.length) {
const sqlContent = `INSERT INTO \`r_material_history_component\` (\`material_history_id\`, \`component_id\`) VALUES (${materialHistoryId}, ${id})`
this.query(sqlContent)
}
})
}

Comment on lines +219 to +232
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue

Use parameterized queries to prevent SQL injection.
Directly concatenating id into the SQL statement may be risky if the value is not guaranteed to be an integer. Parameterized queries will secure this method and help avoid potential injection vulnerabilities.

Possible fix using placeholders (for example in MySQL Node libraries):

- const uniqSql = `SELECT * FROM \`r_material_history_component\` WHERE \`material_history_id\`=${materialHistoryId} AND \`component_id\`=${id}`
- ...
- const sqlContent = `INSERT INTO \`r_material_history_component\` (\`material_history_id\`, \`component_id\`) VALUES (${materialHistoryId}, ${id})`
+ const uniqSql = 'SELECT * FROM `r_material_history_component` WHERE `material_history_id` = ? AND `component_id` = ?'
+ ...
+ const sqlContent = 'INSERT INTO `r_material_history_component` (`material_history_id`, `component_id`) VALUES (?, ?)'
...

Committable suggestion skipped: line range outside the PR's diff.

/**
* 生成新增组件的sql语句
* @param {object} component 组件数据
Expand Down Expand Up @@ -282,10 +297,15 @@ class MysqlConnection {
isOfficial = 0,
isDefault = 0,
tiny_reserved = 0,
tenant = 1,
createBy = 86,
updatedBy = 86
component_metadata = null,
library_id = 1,
tenant_id = 1,
renter_id = 1,
site_id = 1,
created_by = 1,
last_updated_by = 1
} = component

const values = `('${version}',
'${this.formatSingleQuoteValue(JSON.stringify(name))}',
'${componentName}',
Expand All @@ -308,15 +328,19 @@ class MysqlConnection {
'${isOfficial}',
'${isDefault}',
'${tiny_reserved}',
'${tenant}',
'${createBy}',
'${updatedBy}'
'${component_metadata}',
'${library_id}',
'${tenant_id}',
'${renter_id}',
'${site_id}',
'${created_by}',
'${last_updated_by}'
);`

const sqlContent = `INSERT INTO ${componentsTableName} (version, name, component, icon, description, doc_url,
const sqlContent = `INSERT INTO ${componentsTableName} (version, name, name_en, icon, description, doc_url,
screenshot, tags, keywords, dev_mode, npm, \`group\`, \`category\`, priority, snippets,
schema_fragment, configure, \`public\`, framework, isOfficial, isDefault, tiny_reserved,
tenant, createdBy, updatedBy) VALUES ${values}`.replace(/\n/g, '')
schema_fragment, configure, \`public\`, framework, is_official, is_default, tiny_reserved,component_metadata,
library_id, tenant_id, renter_id, site_id, created_by, last_updated_by) VALUES ${values}`.replace(/\n/g, '')
Comment on lines +340 to +343
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue

Schema mismatch for “name_en” and “component_metadata”.
This insert statement references name_en and component_metadata, but the table definition does not declare a name_en column. This will fail unless the table schema is updated accordingly.

A possible fix in your CREATE TABLE statement might be:

  CREATE TABLE t_component (
    ...
+   name_en varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL,
    component_metadata longtext CHARACTER SET utf8 COLLATE utf8_general_ci NULL,
    ...
  );

Committable suggestion skipped: line range outside the PR's diff.


this.query(sqlContent, componentName)
.then((result) => {
Expand All @@ -335,7 +359,7 @@ class MysqlConnection {
* @param {object} component 组件数据
*/
initDB(component) {
const selectSqlContent = `SELECT * FROM ${this.config.database}.${componentsTableName} WHERE component = '${component.component}'`
const selectSqlContent = `SELECT * FROM ${this.config.database}.${componentsTableName} WHERE name_en = '${component.component}'`

this.query(selectSqlContent)
.then((result) => {
Expand Down