parent
2077481d89
commit
555b67132e
@ -0,0 +1,115 @@ |
|||||||
|
# 基于 Vite2.x + Vue3.x + TypeScript H5 低代码平台 |
||||||
|
|
||||||
|
[![license](https://img.shields.io/github/license/buqiyuan/vite-vue3-lowcode.svg)](LICENSE) |
||||||
|
|
||||||
|
**中文** | [English](./README.md) |
||||||
|
|
||||||
|
## 克隆主分支,忽略 git-pages 等无关分支 |
||||||
|
|
||||||
|
```shell |
||||||
|
git clone --single-branch https://github.com/buqiyuan/vite-vue3-lowcode.git |
||||||
|
# or |
||||||
|
git clone --single-branch https://gitee.com/buqiyuan/vite-vue3-lowcode.git |
||||||
|
``` |
||||||
|
|
||||||
|
## 技术栈 |
||||||
|
|
||||||
|
- 编程语言:[TypeScript 4.x](https://www.typescriptlang.org/zh/) + [JavaScript](https://www.javascript.com/) |
||||||
|
- 构建工具:[Vite 2.x](https://cn.vitejs.dev/) |
||||||
|
- 前端框架:[Vue 3.x](https://v3.cn.vuejs.org/) |
||||||
|
- 路由工具:[Vue Router 4.x](https://next.router.vuejs.org/zh/index.html) |
||||||
|
- 状态管理:[Vuex 4.x](https://next.vuex.vuejs.org/) |
||||||
|
- PC 端 UI 框架:[Element Plus](https://element-plus.org/#/zh-CN) |
||||||
|
- H5 端 UI 框架:[vant](https://vant-contrib.gitee.io/vant/v3/#/zh-CN/) |
||||||
|
- CSS 预编译:[Stylus](https://stylus-lang.com/) / [Sass](https://sass.bootcss.com/documentation) / [Less](http://lesscss.cn/) |
||||||
|
- HTTP 工具:[Axios](https://axios-http.com/) |
||||||
|
- Git Hook 工具:[husky](https://typicode.github.io/husky/#/) + [lint-staged](https://github.com/okonet/lint-staged) |
||||||
|
- 代码规范:[EditorConfig](http://editorconfig.org) + [Prettier](https://prettier.io/) + [ESLint](https://eslint.org/) + [Airbnb JavaScript Style Guide](https://github.com/airbnb/javascript#translation) |
||||||
|
- 提交规范:[Commitizen](http://commitizen.github.io/cz-cli/) + [Commitlint](https://commitlint.js.org/#/) |
||||||
|
- 单元测试:[vue-test-utils](https://next.vue-test-utils.vuejs.org/) + [jest](https://jestjs.io/) + [vue-jest](https://github.com/vuejs/vue-jest) + [ts-jest](https://kulshekhar.github.io/ts-jest/) |
||||||
|
- 自动部署:[GitHub Actions](https://docs.github.com/cn/actions/learn-github-actions) |
||||||
|
|
||||||
|
### 功能清单 |
||||||
|
|
||||||
|
- [x] 动态添加页面 |
||||||
|
- [x] 拖拽式生成组件 |
||||||
|
- [ ] service worker + indexeddb 实现无服务端的前端交互 |
||||||
|
- [ ] 数据源管理 |
||||||
|
- [ ] 提供预置函数 |
||||||
|
- [ ] 更多组件的封装 |
||||||
|
- [ ] 其他... |
||||||
|
|
||||||
|
### 简易说明 |
||||||
|
|
||||||
|
目前在使用表单时,需要把相关的`表单控件`放到`表单容器`内部,并且需要将`按钮`放到`表单容器`内, |
||||||
|
然后再讲`按钮的type`设置为`表单提交按钮`这时候点击提交按钮才会自动收集表单容器内部的所有字段和值 |
||||||
|
|
||||||
|
### 快速生成组件属性 |
||||||
|
|
||||||
|
```javascript |
||||||
|
// 在vant文档中 chrome控制台输入以下代码,快速生成组件属性 |
||||||
|
let propObj = { |
||||||
|
string: (config) => `createEditorInputProp(${JSON.stringify(config)})`, |
||||||
|
number: (config) => `createEditorInputNumberProp(${JSON.stringify(config)})`, |
||||||
|
boolean: (config) => `createEditorSwitchProp(${JSON.stringify(config)})` |
||||||
|
} |
||||||
|
|
||||||
|
$$('#props + table tr').reduce((prev, curr) => { |
||||||
|
const children = curr.children |
||||||
|
const key = children[0].textContent.replace(/-([a-z])/g, (all, i) => i.toUpperCase()) |
||||||
|
const value = (propObj[children[2].textContent] ?? propObj['string'])({ |
||||||
|
label: `'${children[1].textContent}'` |
||||||
|
}).replaceAll('"', '') |
||||||
|
prev[key] = value |
||||||
|
return prev |
||||||
|
}, {}) |
||||||
|
``` |
||||||
|
|
||||||
|
## 浏览器支持 |
||||||
|
|
||||||
|
本地开发推荐使用`Chrome 80+` 浏览器 |
||||||
|
|
||||||
|
支持现代浏览器, 不支持 IE |
||||||
|
|
||||||
|
| [<img src="https://raw.githubusercontent.com/alrra/browser-logos/master/src/edge/edge_48x48.png" alt=" Edge" width="24px" height="24px" />](http://godban.github.io/browsers-support-badges/)</br>IE | [<img src="https://raw.githubusercontent.com/alrra/browser-logos/master/src/edge/edge_48x48.png" alt=" Edge" width="24px" height="24px" />](http://godban.github.io/browsers-support-badges/)</br>Edge | [<img src="https://raw.githubusercontent.com/alrra/browser-logos/master/src/firefox/firefox_48x48.png" alt="Firefox" width="24px" height="24px" />](http://godban.github.io/browsers-support-badges/)</br>Firefox | [<img src="https://raw.githubusercontent.com/alrra/browser-logos/master/src/chrome/chrome_48x48.png" alt="Chrome" width="24px" height="24px" />](http://godban.github.io/browsers-support-badges/)</br>Chrome | [<img src="https://raw.githubusercontent.com/alrra/browser-logos/master/src/safari/safari_48x48.png" alt="Safari" width="24px" height="24px" />](http://godban.github.io/browsers-support-badges/)</br>Safari | |
||||||
|
| :--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------: | :----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------: | :---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------: | :-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------: | :-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------: | |
||||||
|
| not support | last 2 versions | last 2 versions | last 2 versions | last 2 versions | |
||||||
|
|
||||||
|
### 提交规范 |
||||||
|
|
||||||
|
- `feat` 增加新功能 |
||||||
|
- `fix` 修复问题/BUG |
||||||
|
- `style` 代码风格相关无影响运行结果的 |
||||||
|
- `perf` 优化/性能提升 |
||||||
|
- `refactor` 重构 |
||||||
|
- `revert` 撤销修改 |
||||||
|
- `test` 测试相关 |
||||||
|
- `docs` 文档/注释 |
||||||
|
- `build` 对构建系统或者外部依赖项进行了修改 |
||||||
|
- `chore` 依赖更新/脚手架配置修改等 |
||||||
|
- `workflow` 工作流改进 |
||||||
|
- `ci` 持续集成 |
||||||
|
- `types` 类型定义文件更改 |
||||||
|
- `wip` 开发中 |
||||||
|
|
||||||
|
## 快速开始 |
||||||
|
|
||||||
|
### 安装依赖 |
||||||
|
|
||||||
|
```sh |
||||||
|
npm install |
||||||
|
# or |
||||||
|
yarn add |
||||||
|
``` |
||||||
|
|
||||||
|
### 启动项目 |
||||||
|
|
||||||
|
```sh |
||||||
|
npm run dev |
||||||
|
``` |
||||||
|
|
||||||
|
### 项目打包 |
||||||
|
|
||||||
|
```sh |
||||||
|
npm run build |
||||||
|
``` |
@ -0,0 +1,133 @@ |
|||||||
|
/* |
||||||
|
* @Author: 卜启缘 |
||||||
|
* @Date: 2021-06-10 16:23:06 |
||||||
|
* @LastEditTime: 2021-06-10 16:46:36 |
||||||
|
* @LastEditors: 卜启缘 |
||||||
|
* @Description: 组件属性编辑器 |
||||||
|
* @FilePath: \vite-vue3-lowcode\src\visual-editor\components\right-attribute-panel\components\AttrEditor.tsx |
||||||
|
*/ |
||||||
|
import { defineComponent } from 'vue' |
||||||
|
import { |
||||||
|
ElColorPicker, |
||||||
|
ElForm, |
||||||
|
ElFormItem, |
||||||
|
ElInput, |
||||||
|
ElInputNumber, |
||||||
|
ElOption, |
||||||
|
ElSelect, |
||||||
|
ElSwitch, |
||||||
|
ElPopover |
||||||
|
} from 'element-plus' |
||||||
|
import { VisualEditorProps, VisualEditorPropsType } from '@/visual-editor/visual-editor.props' |
||||||
|
import { TablePropEditor } from './' |
||||||
|
import { useDotProp } from '@/visual-editor/hooks/useDotProp' |
||||||
|
import { useVisualData } from '@/visual-editor/hooks/useVisualData' |
||||||
|
|
||||||
|
export const AttrEditor = defineComponent({ |
||||||
|
setup() { |
||||||
|
const { visualConfig, currentBlock } = useVisualData() |
||||||
|
|
||||||
|
const renderEditor = (propName: string, propConfig: VisualEditorProps) => { |
||||||
|
const { propObj, prop } = useDotProp(currentBlock.value.props, propName) |
||||||
|
|
||||||
|
return { |
||||||
|
[VisualEditorPropsType.input]: () => ( |
||||||
|
<ElInput v-model={propObj[prop]} placeholder={propConfig.tips || propConfig.label} /> |
||||||
|
), |
||||||
|
[VisualEditorPropsType.inputNumber]: () => <ElInputNumber v-model={propObj[prop]} />, |
||||||
|
[VisualEditorPropsType.switch]: () => <ElSwitch v-model={propObj[prop]} />, |
||||||
|
[VisualEditorPropsType.color]: () => <ElColorPicker v-model={propObj[prop]} />, |
||||||
|
[VisualEditorPropsType.select]: () => ( |
||||||
|
<ElSelect v-model={propObj[prop]} valueKey={'value'} multiple={propConfig.multiple}> |
||||||
|
{propConfig.options?.map((opt) => ( |
||||||
|
<ElOption label={opt.label} value={opt.value} /> |
||||||
|
))} |
||||||
|
</ElSelect> |
||||||
|
), |
||||||
|
[VisualEditorPropsType.table]: () => ( |
||||||
|
<TablePropEditor v-model={propObj[prop]} propConfig={propConfig} /> |
||||||
|
) |
||||||
|
}[propConfig.type]() |
||||||
|
} |
||||||
|
|
||||||
|
// 表单项
|
||||||
|
const FormEditor = () => { |
||||||
|
const content: JSX.Element[] = [] |
||||||
|
if (!currentBlock.value) { |
||||||
|
content.push( |
||||||
|
<> |
||||||
|
<ElFormItem label="容器宽度"> |
||||||
|
<ElInputNumber v-model={currentBlock.value.width} {...({ step: 100 } as any)} /> |
||||||
|
</ElFormItem> |
||||||
|
<ElFormItem label="容器高度"> |
||||||
|
<ElInputNumber v-model={currentBlock.value.height} {...({ step: 100 } as any)} /> |
||||||
|
</ElFormItem> |
||||||
|
</> |
||||||
|
) |
||||||
|
} else { |
||||||
|
const { componentKey } = currentBlock.value |
||||||
|
const component = visualConfig.componentMap[componentKey] |
||||||
|
console.log('props.block:', currentBlock.value) |
||||||
|
content.push( |
||||||
|
<> |
||||||
|
<ElFormItem label="组件ID" labelWidth={'76px'}> |
||||||
|
{currentBlock.value._vid} |
||||||
|
<ElPopover |
||||||
|
width={200} |
||||||
|
trigger="hover" |
||||||
|
content={`你可以利用该组件ID。对该组件进行获取和设置其属性,组件可用属性可在控制台输入:$$refs.${currentBlock.value._vid} 进行查看`} |
||||||
|
> |
||||||
|
{{ |
||||||
|
reference: () => ( |
||||||
|
<i style={{ marginLeft: '6px' }} class={'el-icon-warning-outline'}></i> |
||||||
|
) |
||||||
|
}} |
||||||
|
</ElPopover> |
||||||
|
</ElFormItem> |
||||||
|
</> |
||||||
|
) |
||||||
|
if (!!component) { |
||||||
|
if (!!component.props) { |
||||||
|
content.push( |
||||||
|
...Object.entries(component.props || {}).map(([propName, propConfig]) => ( |
||||||
|
<> |
||||||
|
<ElFormItem key={currentBlock.value._vid + propName}> |
||||||
|
{{ |
||||||
|
label: () => |
||||||
|
propConfig.tips ? ( |
||||||
|
<> |
||||||
|
<ElPopover width={200} trigger={'hover'} content={propConfig.tips}> |
||||||
|
{{ |
||||||
|
reference: () => <i class={'el-icon-warning-outline'}></i> |
||||||
|
}} |
||||||
|
</ElPopover> |
||||||
|
{propConfig.label} |
||||||
|
</> |
||||||
|
) : ( |
||||||
|
propConfig.label |
||||||
|
), |
||||||
|
default: () => renderEditor(propName, propConfig) |
||||||
|
}} |
||||||
|
</ElFormItem> |
||||||
|
</> |
||||||
|
)) |
||||||
|
) |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
return ( |
||||||
|
<> |
||||||
|
<ElForm size="mini" label-position="left"> |
||||||
|
{content} |
||||||
|
</ElForm> |
||||||
|
</> |
||||||
|
) |
||||||
|
} |
||||||
|
|
||||||
|
return () => ( |
||||||
|
<> |
||||||
|
<FormEditor /> |
||||||
|
</> |
||||||
|
) |
||||||
|
} |
||||||
|
}) |
Loading…
Reference in new issue