1.支持url路由跳转对应的配置页面
2.支持历史记录修改
3.支持预览
4.支持重置
5.支持配置更新前端lowcode页面(不用敲代码喽!!!)
6.通过路由及项目名配置查询
7.支持切换环境
npm i //安装依赖npm run start //通过devserve启动前端页面npm run server//启动node服务,默认3001端口
{"json": {"type": "page","title": "Hello world","body": []},"routeName": "test2.json","itemName": "cms2"
}
//src/App.tsximport React from 'react';
import { Editor } from 'amis-editor';
import './App.css'
import axios from 'axios'
interface StateType {json: anyrouteName: stringitemName: stringpreview: booleanhistoryList: any[]step: numbermaxHistoryNum: numberbaseURL: stringuseTestBaseURL: stringisLocalTest: boolean
}
class App extends React.Component {constructor(props: any) {super(props)this.state = {json: {type: "page"//确保是页面层级},routeName: 'client-admin', //默认为''itemName: "cms2", //默认为''preview: false,historyList: [],step: 0,maxHistoryNum: 10,baseURL: window.localStorage.getItem('baseURL') || 'https://dev.zzss.com', //正式开发使用useTestBaseURL: 'http://localhost:3001', //本地调试环境切换使用isLocalTest: true,//用于本地调试环境,正式开发请设置为false}}componentDidMount() {//获取url querythis.checkQuery()setTimeout(() => {this.getJSON()}, 0)}getJSON = () => {let { routeName, itemName, isLocalTest, baseURL, useTestBaseURL, } = this.stateif (!routeName || !itemName) {alert('请传入必要参数')return}let url = isLocalTest ? useTestBaseURL : baseURL//这里要请求对应的路由数据axios.post(url + '/api/getJSON',{routeName: this.state.routeName,itemName: this.state.itemName},).then((res: any) => {if (res.data.success === false) {alert(res.data.msg)return}let obj = res.datathis.clearJSON()let newObj = this.changeBaseURLtoDomain(obj)this.setState({json: newObj,historyList: [...this.state.historyList, newObj],}, () => {console.log("获取到最新的JSON", this.state.json);})}).catch((e) => {alert("获取后端json失败" + JSON.stringify(e))})}sendJSON = () => {let { routeName, itemName, isLocalTest, baseURL, useTestBaseURL } = this.stateif (this.state.json.type !== 'page') {alert('请确保在页面层级更新json')return}if (!routeName || !itemName) {alert('请传入必要参数')return}let obj = this.chengeDomaintoBaseURL(this.state.json)let url = isLocalTest ? useTestBaseURL : baseURLaxios.post(url + '/api/setJSON', {json: obj,routeName: this.state.routeName,itemName: this.state.itemName},{headers: {'Content-Type': 'application/json'}}).then((res) => {if (res.data.success === false) {alert(res.data.msg)return}if (res && res.data && res.data.json) {alert("配置成功")let obj = res.data.jsonthis.setState({json: obj})}}).catch((e) => {alert("存入配置失败" + JSON.stringify(e))})}//监听lowcode的json改变handleChange = (e: any) => {if (!e) returnthis.setState({json: e,historyList: [...this.state.historyList, e],step: this.state.step + 1}, () => {let { historyList, maxHistoryNum } = this.stateif (historyList.length > maxHistoryNum) {let limitObj = [...historyList].splice(-maxHistoryNum)this.setState({historyList: limitObj,step: this.state.step - 1})}console.log("change", this.state.historyList);})}//获取querycheckQuery = () => {let itemName = this.getQueryString('itemName')let routeName = this.getQueryString('routeName')if (itemName && routeName) {this.setState({itemName,routeName})}}// 获取查询字符串getQueryString = (name: string) => {var reg = new RegExp("(^|&)" + name + "=([^&]*)(&|$)");var r = window.location.search.substr(1).match(reg);if (r != null) {return unescape(r[2]);} else {return null};}//监听项目名输入inputItemName = () => {//@ts-ignorelet val = this.refs.itemName.value;this.setState({itemName: val})}//监听路由输入inputRouteName = () => {//@ts-ignorelet val = this.refs.routeName.value;this.setState({routeName: val})}//开始预览startPreview = () => {this.setState({preview: !this.state.preview})}//重置clearJSON = () => {this.setState({json: {}})}//上一步backHistoryJSON = () => {let { step, historyList } = this.stateif (step - 1 >= 0) {this.setState({step: step - 1,}, () => {this.setState({json: historyList[this.state.step]})})} else {alert('您当前没有历史记录')}}//下一步goHistoryJSON = () => {let { step, historyList } = this.statelet curStep = historyList.length - 1if (step < curStep) {this.setState({step: step + 1,}, () => {this.setState({json: historyList[this.state.step]})})} else {alert('已经是最新!')}}//根路径inputUrlName = () => {//@ts-ignorelet val = this.refs.baseURL.value;this.setState({baseURL: val,}, () => {window.localStorage.setItem('baseURL', this.state.baseURL)})}//转为domainchangeBaseURLtoDomain = (obj: any) => {let { baseURL } = this.stateif (!baseURL) returnlet str = JSON.stringify(obj)let res = str.replace(/${baseURL}/g, baseURL)return JSON.parse(res)}//转为${baseURL}chengeDomaintoBaseURL = (obj: any) => {let { baseURL } = this.stateif (!baseURL) returnlet str = JSON.stringify(obj)let urlReg = new RegExp(baseURL, 'g')let res = str.replace(urlReg, '${baseURL}')return JSON.parse(res)}render() {return (<>项目名: this.inputItemName()} />路由名: this.inputRouteName()} />设置baseURL: this.inputUrlName()} /> >)}
}
export default App;
//server/app.js用于调试服务端
const http = require("http");
const fs = require('fs');
const path = require('path');
/**
* 失败数据模型
* @param {*} msg 消息
*/
function errModel (msg) {let obj = {success: false,msg}return JSON.stringify(obj)
}
http.createServer(function (req, res) {res.setHeader('Access-Control-Allow-Origin', '*');res.setHeader('Access-Control-Allow-Headers', 'Content-Type');res.setHeader('Content-Type', 'application/json;');res.setHeader("Access-Control-Allow-Methods", "DELETE,PUT,POST,GET,OPTIONS");console.log(req.url);console.log(req.method);if (req.method == 'OPTIONS') {res.writeHead(200, {'Content-Type': 'text/plain','Access-Control-Allow-Origin': '*','Access-Control-Allow-Headers': 'Content-Type, Content-Length, Authorization, Accept, X-Requested-With , yourHeaderFeild, sessionToken','Access-Control-Allow-Methods': 'PUT, POST, GET, DELETE, OPTIONS'});res.end('');}if (req.method === 'POST' && req.url === '/api/setJSON') {let item = '';// 读取每次发送的数据req.on('data', function (chunk) {item += chunk.toString();});// 数据发送完成req.on('end', function () {let items = JSON.parse(item)if (items.routeName && items.itemName) {let file = path.join(__dirname, `${items.routeName}.json`)// json文件需要存入路径fs.writeFileSync(file, item)//将数据返回到客户端res.write(item);res.end();} else {res.write(errModel('文件配置失败, 检查路由或项目名是否正确'));res.end();}});}if (req.method === 'POST' && req.url === '/api/getJSON') {let item = '';// 读取每次发送的数据req.on('data', function (chunk) {item += chunk.toString();});// 数据发送完成req.on('end', function () {let items = JSON.parse(item)if (items.routeName && items.itemName) {let file = path.join(__dirname, `${items.routeName}.json`)fs.readFile(file, 'utf-8', function (err, data) {if (err) {console.log(err);res.write(errModel('请检查路由是否正确'));res.end();} else {let obj = JSON.parse(data)res.write(JSON.stringify(obj.json));res.end();}});} else {res.write(errModel('请检查路由或项目名是否正确'));res.end();}});}
}).listen(3001); // 监听的端口
import Vue from 'vue'import defaultConfig from "./config";import axios from 'axios'var timer = nulllet defaultOptions = {method: 'local', // 'http' | 'local' 通过接口返回或者本地静态文件夹获取routeName: '', //输入路由名(必填)itemName: '', //项目名(必填)}let newOptions//修改后的配置/** * 在路由允许的情况下调用可生成对应lowcode页面 * @param {DOM} DOM * @param {Object} options */export const getLowcodePage = (DOM, options = {}) => {newOptions = Object.assign(defaultOptions, options)let { routeName } = newOptionsif (
{let { data } = resstartAmis(data)console.log('http', data);}).catch((e) => {alert("获取后端json失败" + JSON.stringify(e))})}}//amis renderconst startAmis = (jsonObj) => {console.log("jsonObj", jsonObj);let amis = window.amisRequire('amis/embed');amis.embed(DOM, jsonObj, {data: {baseURL: process.env.VUE_APP_API_BASE_URL}}, defaultConfig)}//entrancecheck(routeName)}" style="margin: auto" />
//vue.config.jsdevServer: {proxy: {//测试lowcode使用'/api': {target: 'http://localhost:3001',changeOrigin: true,},}},