Skip to content
Open
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
2 changes: 2 additions & 0 deletions packages/canvas/render/src/page-block-function/schema.ts
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,8 @@ export function useSchema(
bridge,
stores,
state,
// 追加一个 globalState,指向 stores,用于全局状态管理
globalState: stores,
props,
dataSourceMap: {},
emit: () => {} // 兼容访问器中getter和setter中this.emit写法
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -142,7 +142,7 @@ const { EXPRESSION_TYPE } = constants
const CONSTANTS = {
THIS: 'this.',
STATE: 'this.state.',
STORE: 'this.stores.',
STORE: 'this.globalState.',
PROPS: 'this.props.',
COLLECTION: 'Collection',
ITEM: 'item',
Expand Down
4 changes: 2 additions & 2 deletions packages/vue-generator/src/generator/page.js
Original file line number Diff line number Diff line change
Expand Up @@ -407,7 +407,7 @@ const generateVueCode = ({ schema, name, type, componentsMap }) => {
? `const [${componentNames.join(',')}] = [${exportNames.map((name) => `${name}()`).join(',')}]`
: ''

const contextArr = ['stores', 'state', ...methodsName]
const contextArr = ['stores', 'state', 'globalState', ...methodsName]

const result = `
<template>
Expand All @@ -420,7 +420,7 @@ ${imports.join('\n')}
const props = defineProps({${propsArr.join(',\n')}})
const emit = defineEmits(${JSON.stringify(emitsArr)})

const { t, lowcodeWrap, stores } = vue.inject(I18nInjectionKey).lowcode()
const { t, lowcodeWrap, stores, globalState } = vue.inject(I18nInjectionKey).lowcode()
const wrap = lowcodeWrap(props, { emit })

${iconStatement}
Expand Down
93 changes: 49 additions & 44 deletions packages/vue-generator/src/plugins/genGlobalState.js
Original file line number Diff line number Diff line change
Expand Up @@ -31,63 +31,68 @@ function genDependenciesPlugin(options = {}) {
run(schema) {
const globalState = parseSchema(schema)

let importStatement = "import { defineStore } from 'pinia'"
const state = {}
const getters = {}
const actions = {}

const res = []
const ids = []

for (const stateItem of globalState) {
let importStatement = "import { defineStore } from 'pinia'"
const { id, state, getters, actions } = stateItem

ids.push(id)
const { id, state: stateValue, getters: gettersValue = [], actions: actionsValue = [] } = stateItem

const stateExpression = `() => ({ ${Object.entries(state)
.map((item) => {
let [key, value] = item

if (typeof value === 'string') {
value = `'${value}'`
state[id] = stateValue
Object.keys(gettersValue).forEach((key) => {
if (typeof gettersValue[key] === 'object' && gettersValue[key].type === 'JSFunction') {
if (gettersValue[key].value.includes('this')) {
gettersValue[key].value = gettersValue[key].value.replace(/this\./g, `this.${id}.`)
}

if (value && typeof value === 'object') {
value = JSON.stringify(value)
getters[key] = gettersValue[key].value
}
})
Object.keys(actionsValue).forEach((key) => {
if (typeof actionsValue[key] === 'object' && actionsValue[key].type === 'JSFunction') {
if (actionsValue[key].value.includes('this')) {
actionsValue[key].value = actionsValue[key].value.replace(/this\./g, `this.${id}.`)
}

return [key, value].join(':')
})
.join(',')} })`

const getterExpression = Object.entries(getters)
.filter((item) => item[1]?.type === 'JSFunction')
.map(([key, value]) => `${key}: ${value.value}`)
.join(',')

const actionExpressions = Object.entries(actions)
.filter((item) => item[1]?.type === 'JSFunction')
.map(([key, value]) => `${key}: ${value.value}`)
.join(',')

const storeFiles = `
${importStatement}
export const ${id} = defineStore({
id: '${id}',
state: ${stateExpression},
getters: { ${getterExpression} },
actions: { ${actionExpressions} }
})
`
res.push({
fileType: 'js',
fileName: `${id}.js`,
path,
fileContent: storeFiles
actions[key] = actionsValue[key].value
}
Comment on lines 41 to +59
Copy link
Member

Choose a reason for hiding this comment

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

这里简单粗暴的合并感觉会风险:
1.
假如定义了两个 store:

store1: {
  name: 'user1'
}
store2: {
   name: 'title'
}

合并后:

{
   store1: {
     name: 'user1'
   },
   store2: {
      name: 'title'
   }
}

这样的话,就要求在设计态绑定变量的地方,有相关的提示,绑定 this.globalState.store1.name,而不是 this.stores.store1.name

  1. getter 和 setter 方法名冲突

这里 gettter 和 setter 没有以 id 为维度进行区分,假如两个 store 中都有同样名称的 getter 或者 setter,会造成覆盖冲突。

  1. this 引用修正问题:

this. 直接正则替换成 this.${id} 的方式可能不利于后续的拓展或者造成错误的替换。
比如:如果用户的 gettter 方法或者 setter 方法有关于 this. 的字符串,会造成误替换。
如果后续我们要支持使用 this.utils,即在全局状态中访问 utils 方法,这里可能就需要重新实现。不利于拓展。

})
}

const globalStateFiles = `
${importStatement}
export const globalState = defineStore('globalState', {
state: () => (${JSON.stringify(state, null, 2)}),
getters: {${Object.entries(getters)
.map(([key, value]) => `${key}: ${value}`)
.join(',')}},
actions: {${Object.entries(actions)
.map(([key, value]) => `${key}: ${value}`)
.join(',')}}
})

export const useGlobalState = () => {
// 获取 globalState 实例
const globalStateInstance = globalState();

return globalStateInstance;
};

`

res.push({
fileType: 'js',
fileName: 'globalState.js',
path: './src/stores',
fileContent: globalStateFiles
})

res.push({
fileType: 'js',
fileName: 'index.js',
path,
fileContent: ids.map((item) => `export { ${item} } from './${item}'`).join('\n')
fileContent: `export { globalState } from './globalState'`
})

return res
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ import dataSourceMap from './dataSource'
import * as utils from '../utils'
import * as bridge from './bridge'
import { useStores } from './store'
import { useGlobalState } from '@/stores/globalState'

export const lowcodeWrap = (props, context) => {
const global = {}
Expand Down Expand Up @@ -81,6 +82,7 @@ export default () => {
provide(I18nInjectionKey, i18n)

const stores = useStores()
const globalState = useGlobalState()

return { t: i18n.global.t, lowcodeWrap, stores }
return { t: i18n.global.t, lowcodeWrap, stores, globalState }
}