alvis 6 months ago
parent
commit
2943978b49
  1. 22
      LICENSE
  2. 23
      README.md
  3. 23
      README.zh-CN.md
  4. BIN
      img.png
  5. 13
      index.html
  6. 46
      package.json
  7. BIN
      public/code.png
  8. BIN
      public/favicon.ico
  9. BIN
      public/tinyengine.jpg
  10. 11
      src/App.vue
  11. 139
      src/http/axios.js
  12. 15
      src/http/config.js
  13. 22
      src/http/index.js
  14. 21
      src/i18n/index.js
  15. 19
      src/i18n/locale.js
  16. 13
      src/lowcode/bridge.js
  17. 105
      src/lowcode/dataSource.js
  18. 86
      src/lowcode/lowcode.js
  19. 25
      src/lowcode/store.js
  20. 13
      src/lowcode/utils.js
  21. 20
      src/main.js
  22. 27
      src/views/helloWorld.vue
  23. 23
      vite.config.js

22
LICENSE

@ -0,0 +1,22 @@ @@ -0,0 +1,22 @@
MIT License
Copyright (c) 2023 - present TinyEngine Authors.
Copyright (c) 2023 - present Huawei Cloud Computing Technologies Co., Ltd.
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.

23
README.md

@ -0,0 +1,23 @@ @@ -0,0 +1,23 @@
## Usage of Generated Source Code
This scaffold solves the problem of running after downloading the source code.
<b> Note: The template project started by low-code applications is based on the Tiny Vue component library.</b>
<br>
- Start this project:
```npm run dev```
<br>
When downloading the source code from the upper right corner of the engine, you can select the source code to be generated as required.
</br>
![img.png](img.png)
After you click OK, the engine automatically generates a src folder that contains the selected content.
For first-time users, you are advised to create a simple page that does not contain internationalization. Then copy the generated page to the src/view directory of the project and run it directly.
For users who use the source code for multiple times, you are advised to select the src of the project when generating the source code. When generating the source code, generate the corresponding file as required.

23
README.zh-CN.md

@ -0,0 +1,23 @@ @@ -0,0 +1,23 @@
## 生成源码的使用方式
本脚手架解决下载源代码后的运行问题。
<b> 注意:低代码应用启动的模板工程,基于 Tiny Vue 组件库</b>
<br>
- 启动本项目:
npm run dev
<br>
在通过引擎的右上角下载源码的时,可以根据需要选择要生成的源代码。
</br>
![img.png](img.png)
点击确定后,引擎会自动生成一个src的文件夹, 里面包含了勾选的内容。
对于初次使用的用户,建议搭建一个简单的页面,不包含国际化等内容。然后把生成的页面拷贝到本项目的src/view目录直接运行起来。
对于多次使用的用户,建议生成源码的时候,直接选择本项目的src。然后再生成源代码的时候,按需生成对应的文件即可。

BIN
img.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 32 KiB

13
index.html

@ -0,0 +1,13 @@ @@ -0,0 +1,13 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<link rel="icon" href="/favicon.ico" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>cce</title>
</head>
<body>
<div id="app"></div>
<script type="module" src="/src/main.js"></script>
</body>
</html>

46
package.json

@ -0,0 +1,46 @@ @@ -0,0 +1,46 @@
{
"name": "@opentiny/tiny-engine-preview-vue",
"version": "1.0.2",
"scripts": {
"dev": "vite",
"build": "vite build",
"preview": "vite preview"
},
"main": "dist/index.js",
"module": "dist/index.js",
"dependencies": {
"@opentiny/tiny-engine-i18n-host": "^1.0.0",
"@opentiny/vue": "^3.10.0",
"@opentiny/vue-icon": "^3.10.0",
"axios": "^0.21.1",
"axios-mock-adapter": "^1.19.0",
"vue": "^3.2.25",
"vue-i18n": "^9.2.0-beta.3",
"vue-router": "^4.0.0",
"pinia": "^2.1.7"
},
"devDependencies": {
"@vitejs/plugin-vue": "^2.3.1",
"@vitejs/plugin-vue-jsx": "^1.3.10",
"vite": "^2.9.5"
},
"homepage": "https://opentiny.design/tiny-engine",
"keywords": [
"vue",
"vue3",
"frontend",
"opentiny",
"lowcode",
"tiny-engine",
"tiny-engine-preview-template"
],
"repository": {
"type": "git",
"url": "https://github.com/opentiny/tiny-engine-generate-preview"
},
"bugs": {
"url": "https://github.com/opentiny/tiny-engine-generate-preview/issues"
},
"author": "OpenTiny Team",
"license": "MIT"
}

BIN
public/code.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 33 KiB

BIN
public/favicon.ico

Binary file not shown.

After

Width:  |  Height:  |  Size: 13 KiB

BIN
public/tinyengine.jpg

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.3 MiB

11
src/App.vue

@ -0,0 +1,11 @@ @@ -0,0 +1,11 @@
<template>
<router-view></router-view>
</template>
<script setup>
import { I18nInjectionKey } from 'vue-i18n'
import { provide } from 'vue'
import i18n from './i18n'
provide(I18nInjectionKey, i18n)
</script>

139
src/http/axios.js

@ -0,0 +1,139 @@ @@ -0,0 +1,139 @@
/**
* Copyright (c) 2023 - present TinyEngine Authors.
* Copyright (c) 2023 - present Huawei Cloud Computing Technologies Co., Ltd.
*
* Use of this source code is governed by an MIT-style license.
*
* THE OPEN SOURCE SOFTWARE IN THIS PRODUCT IS DISTRIBUTED IN THE HOPE THAT IT WILL BE USEFUL,
* BUT WITHOUT ANY WARRANTY, WITHOUT EVEN THE IMPLIED WARRANTY OF MERCHANTABILITY OR FITNESS FOR
* A PARTICULAR PURPOSE. SEE THE APPLICABLE LICENSES FOR MORE DETAILS.
*
*/
import axios from 'axios'
import MockAdapter from 'axios-mock-adapter'
export default (config) => {
const instance = axios.create(config)
const defaults = {}
let mock
if (typeof MockAdapter.prototype.proxy === 'undefined') {
MockAdapter.prototype.proxy = function ({ url, config = {}, proxy, response, handleData } = {}) {
let stream = this
const request = (proxy, any) => {
return (setting) => {
return new Promise((resolve) => {
config.responseType = 'json'
axios
.get(any ? proxy + setting.url + '.json' : proxy, config)
.then(({ data }) => {
/* eslint-disable no-useless-call */
typeof handleData === 'function' && (data = handleData.call(null, data, setting))
resolve([200, data])
})
.catch((error) => {
resolve([error.response.status, error.response.data])
})
})
}
}
if (url === '*' && proxy && typeof proxy === 'string') {
stream = proxy === '*' ? this.onAny().passThrough() : this.onAny().reply(request(proxy, true))
} else {
if (proxy && typeof proxy === 'string') {
stream = this.onAny(url).reply(request(proxy))
} else if (typeof response === 'function') {
stream = this.onAny(url).reply(response)
}
}
return stream
}
}
return {
request(config) {
return instance(config)
},
get(url, config) {
return instance.get(url, config)
},
delete(url, config) {
return instance.delete(url, config)
},
head(url, config) {
return instance.head(url, config)
},
post(url, data, config) {
return instance.post(url, data, config)
},
put(url, data, config) {
return instance.put(url, data, config)
},
patch(url, data, config) {
return instance.patch(url, data, config)
},
all(iterable) {
return axios.all(iterable)
},
spread(callback) {
return axios.spread(callback)
},
defaults(key, value) {
if (key && typeof key === 'string') {
if (typeof value === 'undefined') {
return instance.defaults[key]
}
instance.defaults[key] = value
defaults[key] = value
} else {
return instance.defaults
}
},
defaultSettings() {
return defaults
},
interceptors: {
request: {
use(fnHandle, fnError) {
return instance.interceptors.request.use(fnHandle, fnError)
},
eject(id) {
return instance.interceptors.request.eject(id)
}
},
response: {
use(fnHandle, fnError) {
return instance.interceptors.response.use(fnHandle, fnError)
},
eject(id) {
return instance.interceptors.response.eject(id)
}
}
},
mock(config) {
if (!mock) {
mock = new MockAdapter(instance)
}
if (Array.isArray(config)) {
config.forEach((item) => {
mock.proxy(item)
})
}
return mock
},
disableMock() {
mock && mock.restore()
mock = undefined
},
isMock() {
return typeof mock !== 'undefined'
},
CancelToken: axios.CancelToken,
isCancel: axios.isCancel
}
}

15
src/http/config.js

@ -0,0 +1,15 @@ @@ -0,0 +1,15 @@
/**
* Copyright (c) 2023 - present TinyEngine Authors.
* Copyright (c) 2023 - present Huawei Cloud Computing Technologies Co., Ltd.
*
* Use of this source code is governed by an MIT-style license.
*
* THE OPEN SOURCE SOFTWARE IN THIS PRODUCT IS DISTRIBUTED IN THE HOPE THAT IT WILL BE USEFUL,
* BUT WITHOUT ANY WARRANTY, WITHOUT EVEN THE IMPLIED WARRANTY OF MERCHANTABILITY OR FITNESS FOR
* A PARTICULAR PURPOSE. SEE THE APPLICABLE LICENSES FOR MORE DETAILS.
*
*/
export default {
withCredentials: false
}

22
src/http/index.js

@ -0,0 +1,22 @@ @@ -0,0 +1,22 @@
/**
* Copyright (c) 2023 - present TinyEngine Authors.
* Copyright (c) 2023 - present Huawei Cloud Computing Technologies Co., Ltd.
*
* Use of this source code is governed by an MIT-style license.
*
* THE OPEN SOURCE SOFTWARE IN THIS PRODUCT IS DISTRIBUTED IN THE HOPE THAT IT WILL BE USEFUL,
* BUT WITHOUT ANY WARRANTY, WITHOUT EVEN THE IMPLIED WARRANTY OF MERCHANTABILITY OR FITNESS FOR
* A PARTICULAR PURPOSE. SEE THE APPLICABLE LICENSES FOR MORE DETAILS.
*
*/
import axios from './axios'
import config from './config'
export default (dataHandler, errorHandler) => {
const http = axios(config)
http.interceptors.response.use(dataHandler, errorHandler)
return http
}

21
src/i18n/index.js

@ -0,0 +1,21 @@ @@ -0,0 +1,21 @@
/**
* Copyright (c) 2023 - present TinyEngine Authors.
* Copyright (c) 2023 - present Huawei Cloud Computing Technologies Co., Ltd.
*
* Use of this source code is governed by an MIT-style license.
*
* THE OPEN SOURCE SOFTWARE IN THIS PRODUCT IS DISTRIBUTED IN THE HOPE THAT IT WILL BE USEFUL,
* BUT WITHOUT ANY WARRANTY, WITHOUT EVEN THE IMPLIED WARRANTY OF MERCHANTABILITY OR FITNESS FOR
* A PARTICULAR PURPOSE. SEE THE APPLICABLE LICENSES FOR MORE DETAILS.
*
*/
import i18n from '@opentiny/tiny-engine-i18n-host'
import lowcode from '../lowcode/lowcode'
import locale from './locale'
i18n.lowcode = lowcode
i18n.global.mergeLocaleMessage('zh_CN', locale.zh)
i18n.global.mergeLocaleMessage('en_US', locale.en)
export default i18n

19
src/i18n/locale.js

@ -0,0 +1,19 @@ @@ -0,0 +1,19 @@
/**
* Copyright (c) 2023 - present TinyEngine Authors.
* Copyright (c) 2023 - present Huawei Cloud Computing Technologies Co., Ltd.
*
* Use of this source code is governed by an MIT-style license.
*
* THE OPEN SOURCE SOFTWARE IN THIS PRODUCT IS DISTRIBUTED IN THE HOPE THAT IT WILL BE USEFUL,
* BUT WITHOUT ANY WARRANTY, WITHOUT EVEN THE IMPLIED WARRANTY OF MERCHANTABILITY OR FITNESS FOR
* A PARTICULAR PURPOSE. SEE THE APPLICABLE LICENSES FOR MORE DETAILS.
*
*/
import zh from './zh.json'
import en from './en.json'
export default {
en,
zh
}

13
src/lowcode/bridge.js

@ -0,0 +1,13 @@ @@ -0,0 +1,13 @@
/**
* Copyright (c) 2023 - present TinyEngine Authors.
* Copyright (c) 2023 - present Huawei Cloud Computing Technologies Co., Ltd.
*
* Use of this source code is governed by an MIT-style license.
*
* THE OPEN SOURCE SOFTWARE IN THIS PRODUCT IS DISTRIBUTED IN THE HOPE THAT IT WILL BE USEFUL,
* BUT WITHOUT ANY WARRANTY, WITHOUT EVEN THE IMPLIED WARRANTY OF MERCHANTABILITY OR FITNESS FOR
* A PARTICULAR PURPOSE. SEE THE APPLICABLE LICENSES FOR MORE DETAILS.
*
*/
export default () => {}

105
src/lowcode/dataSource.js

@ -0,0 +1,105 @@ @@ -0,0 +1,105 @@
/**
* Copyright (c) 2023 - present TinyEngine Authors.
* Copyright (c) 2023 - present Huawei Cloud Computing Technologies Co., Ltd.
*
* Use of this source code is governed by an MIT-style license.
*
* THE OPEN SOURCE SOFTWARE IN THIS PRODUCT IS DISTRIBUTED IN THE HOPE THAT IT WILL BE USEFUL,
* BUT WITHOUT ANY WARRANTY, WITHOUT EVEN THE IMPLIED WARRANTY OF MERCHANTABILITY OR FITNESS FOR
* A PARTICULAR PURPOSE. SEE THE APPLICABLE LICENSES FOR MORE DETAILS.
*
*/
import useHttp from '../http'
import dataSources from './dataSource.json'
const dataSourceMap = {}
// 暂时使用 eval 解析 JSON 数据里的函数
const createFn = (fnContent) => {
return (...args) => {
// eslint-disable-next-line no-eval
window.eval('var fn = ' + fnContent)
// eslint-disable-next-line no-undef
return fn.apply(this, args)
}
}
const globalDataHandle = dataSources.dataHandler ? createFn(dataSources.dataHandler.value) : (res) => res
const globalErrorHandler = dataSources.errorHandler ? createFn(dataSources.errorHandler.value) : (err) => Promise.reject(err)
const globalWillFetch = dataSources.willFetch ? createFn(dataSources.willFetch.value) : (option) => option
const load = (http, options, dataSource, shouldFetch) => (params, customUrl) => {
// 如果没有配置远程请求,则直接返回静态数据,返回前可能会有全局数据处理
if (!options) {
return Promise.resolve(globalDataHandle(dataSource.config.data))
}
if (!shouldFetch()) {
return Promise.resolve()
}
dataSource.status = 'loading'
const { method, uri: url, params: defaultParams, timeout, headers } = options
const config = { method, url, headers, timeout }
const data = params || defaultParams
config.url = customUrl || config.url
if (method.toLowerCase() === 'get') {
config.params = data
} else {
config.data = data
}
return http.request(config)
}
dataSources.list.forEach((config) => {
const http = useHttp(globalDataHandle, globalErrorHandler)
const dataSource = { config }
dataSourceMap[config.name] = dataSource
const shouldFetch = config.shouldFetch?.value ? createFn(config.shouldFetch.value) : () => true
const willFetch = config.willFetch?.value ? createFn(config.willFetch.value) : (options) => options
const dataHandler = (res) => {
const data = config.dataHandler?.value ? createFn(config.dataHandler.value)(res) : res
dataSource.status = 'loaded'
dataSource.data = data
return data
}
const errorHandler = (error) => {
config.errorHandler?.value && createFn(config.errorHandler.value)(error)
dataSource.status = 'error'
dataSource.error = error
}
http.interceptors.request.use(willFetch, errorHandler)
http.interceptors.request.use(globalWillFetch, globalErrorHandler)
http.interceptors.response.use(dataHandler, errorHandler)
if (import.meta.env.VITE_APP_MOCK === 'mock') {
http.mock([
{
url: config.options?.uri,
response() {
return Promise.resolve([200, { data: config.data }])
}
},
{
url: '*',
proxy: '*'
}
])
}
dataSource.status = 'init'
dataSource.load = load(http, config.options, dataSource, shouldFetch)
})
export default dataSourceMap

86
src/lowcode/lowcode.js

@ -0,0 +1,86 @@ @@ -0,0 +1,86 @@
/**
* Copyright (c) 2023 - present TinyEngine Authors.
* Copyright (c) 2023 - present Huawei Cloud Computing Technologies Co., Ltd.
*
* Use of this source code is governed by an MIT-style license.
*
* THE OPEN SOURCE SOFTWARE IN THIS PRODUCT IS DISTRIBUTED IN THE HOPE THAT IT WILL BE USEFUL,
* BUT WITHOUT ANY WARRANTY, WITHOUT EVEN THE IMPLIED WARRANTY OF MERCHANTABILITY OR FITNESS FOR
* A PARTICULAR PURPOSE. SEE THE APPLICABLE LICENSES FOR MORE DETAILS.
*
*/
import { getCurrentInstance, nextTick, provide, inject } from 'vue'
import { useRouter, useRoute } from 'vue-router'
import { I18nInjectionKey } from 'vue-i18n'
import dataSourceMap from './dataSource'
import * as utils from './utils'
import * as bridge from './bridge'
import { useStores } from './store'
export const lowcodeWrap = (props, context) => {
const global = {}
const instance = getCurrentInstance()
const router = useRouter()
const route = useRoute()
const { t, locale } = inject(I18nInjectionKey).global
const emit = context.emit
const ref = (ref) => instance.refs[ref]
const setState = (newState, callback) => {
Object.assign(global.state, newState)
nextTick(() => callback.apply(global))
}
const getLocale = () => locale.value
const setLocale = (val) => {
locale.value = val
}
const location = () => window.location
const history = () => window.history
Object.defineProperties(global, {
props: { get: () => props },
emit: { get: () => emit },
setState: { get: () => setState },
router: { get: () => router },
route: { get: () => route },
i18n: { get: () => t },
getLocale: { get: () => getLocale },
setLocale: { get: () => setLocale },
location: { get: location },
history: { get: history },
utils: { get: () => utils },
bridge: { get: () => bridge },
dataSourceMap: { get: () => dataSourceMap },
$: { get: () => ref }
})
const wrap = (fn) => {
if (typeof fn === 'function') {
return (...args) => fn.apply(global, args)
}
Object.entries(fn).forEach(([name, value]) => {
Object.defineProperty(global, name, {
get: () => value
})
})
fn.t = t
return fn
}
return wrap
}
export default () => {
const i18n = inject(I18nInjectionKey)
provide(I18nInjectionKey, i18n)
const stores = useStores()
return { t: i18n.global.t, lowcodeWrap, stores }
}

25
src/lowcode/store.js

@ -0,0 +1,25 @@ @@ -0,0 +1,25 @@
/**
* Copyright (c) 2023 - present TinyEngine Authors.
* Copyright (c) 2023 - present Huawei Cloud Computing Technologies Co., Ltd.
*
* Use of this source code is governed by an MIT-style license.
*
* THE OPEN SOURCE SOFTWARE IN THIS PRODUCT IS DISTRIBUTED IN THE HOPE THAT IT WILL BE USEFUL,
* BUT WITHOUT ANY WARRANTY, WITHOUT EVEN THE IMPLIED WARRANTY OF MERCHANTABILITY OR FITNESS FOR
* A PARTICULAR PURPOSE. SEE THE APPLICABLE LICENSES FOR MORE DETAILS.
*
*/
import * as useDefinedStores from '@/stores'
const useStores = () => {
const stores = {}
Object.values(useDefinedStores || {}).forEach((store) => {
stores[store.$id] = store()
})
return stores
}
export { useStores }

13
src/lowcode/utils.js

@ -0,0 +1,13 @@ @@ -0,0 +1,13 @@
/**
* Copyright (c) 2023 - present TinyEngine Authors.
* Copyright (c) 2023 - present Huawei Cloud Computing Technologies Co., Ltd.
*
* Use of this source code is governed by an MIT-style license.
*
* THE OPEN SOURCE SOFTWARE IN THIS PRODUCT IS DISTRIBUTED IN THE HOPE THAT IT WILL BE USEFUL,
* BUT WITHOUT ANY WARRANTY, WITHOUT EVEN THE IMPLIED WARRANTY OF MERCHANTABILITY OR FITNESS FOR
* A PARTICULAR PURPOSE. SEE THE APPLICABLE LICENSES FOR MORE DETAILS.
*
*/
export {}

20
src/main.js

@ -0,0 +1,20 @@ @@ -0,0 +1,20 @@
/**
* Copyright (c) 2023 - present TinyEngine Authors.
* Copyright (c) 2023 - present Huawei Cloud Computing Technologies Co., Ltd.
*
* Use of this source code is governed by an MIT-style license.
*
* THE OPEN SOURCE SOFTWARE IN THIS PRODUCT IS DISTRIBUTED IN THE HOPE THAT IT WILL BE USEFUL,
* BUT WITHOUT ANY WARRANTY, WITHOUT EVEN THE IMPLIED WARRANTY OF MERCHANTABILITY OR FITNESS FOR
* A PARTICULAR PURPOSE. SEE THE APPLICABLE LICENSES FOR MORE DETAILS.
*
*/
import { createApp } from 'vue'
import router from './router'
import { createPinia } from 'pinia'
import App from './App.vue'
const pinia = createPinia()
createApp(App).use(pinia).use(router).mount('#app')

27
src/views/helloWorld.vue

@ -0,0 +1,27 @@ @@ -0,0 +1,27 @@
<template>
<div>
<h2>hello TinyEngine</h2>
<img src="../../public/tinyengine.jpg" alt="">
</div>
</template>
<script setup>
</script>
<style scoped>
body {
background-color: #eef0f5;
margin-bottom: 80px;
}
h2 {
text-align: center;
}
img {
width: 1000px;
display: block;
margin: 50px auto;
}
</style>

23
vite.config.js

@ -0,0 +1,23 @@ @@ -0,0 +1,23 @@
import { defineConfig } from 'vite'
import path from 'path'
import vue from '@vitejs/plugin-vue'
import vueJsx from '@vitejs/plugin-vue-jsx'
export default defineConfig({
resolve: {
alias: {
'@': path.resolve(__dirname, 'src'),
},
},
plugins: [vue(), vueJsx()],
define: {
'process.env': { ...process.env },
},
build: {
minify: true,
commonjsOptions: {
transformMixedEsModules: true,
},
cssCodeSplit: false,
},
})
Loading…
Cancel
Save