0.导入amis sdk
在github上下载 sdk.tar.gz:https://github.com/baidu/amis/releases
若网速不行,github下载不下来,可以这样:
yarn add amis,然后在 node_modules\amis\sdk 目录里就能找到相关资源
public/index.html中添加:
<link rel="stylesheet" href="amissdk/ang.css" />
<script src="amissdk/sdk.js"></script>
1.配置amis页面和web应用菜单的关联关系
最终生成的json如下
[{"path": "/develop",//顶部导航栏"title": "开发中心","icon": "md-code-working","hideSider": false,"name": "develop","children": [{"path": "/develop/datamodel", //侧边栏-目录"icon": "ios-barcode","title": "数据表模型","header": "develop","children": [{"path": "/develop/modelclass",//侧边栏-菜单"icon": "ios-list-box-outline","title": "表模型分类","nodeKey": 36,"meta": {"auth": true,"mclass": "base","template": "base.modelclass", //绑定的amis页面"type": "pagetpl","iframe": "","component": "","closable": true},"selected": true,"component": "default/default.tpl","name": "develop-modelclass","auth": ["admin","superadmin"],"nodeClass": "sider","target": "_self","hideSider": false,"headerDropdown": false,"menu": {"enable": true,"header": true},"divided": false,"childAddDisabled": true},{"path": "/develop/model","icon": "md-menu","title": "表模型管理","nodeKey": 37,"meta": {"auth": true,"mclass": "base","template": "base.modelinfo","type": "pagetpl","iframe": "","component": "","closable": true},"component": "default/default.tpl","selected": false,"name": "develop-modelinfo","auth": ["admin","superadmin"],"nodeClass": "sider","target": "_self","hideSider": false,"headerDropdown": false,"menu": {"enable": true,"header": true},"divided": false,"childAddDisabled": true}],"nodeKey": 35,"meta": {"auth": true,"type": "folder","iframe": "","component": "","closable": true},"selected": false,"expand": true,"name": "develop-model","nodeClass": "folder","target": "_self","hideSider": false,"headerDropdown": false,"menu": {"enable": true},"divided": false},],"nodeKey": 34,"expand": true,"meta": {"auth": true,"mclass": "","template": "","type": "pagetpl","iframe": "","component": "","closable": true},"selected": false,"redirect": "develop-page.pagetemplate","headerDropdown": false,"nodeClass": "header","target": "_self","menu": {"enable": true}}
]
2.根据关联关系生成动态路由
libs/util.js:
export const getRouterByAppMenu = (list, level) => {let routers = [];forEach(list, item => {let r = {};item.meta = item.meta || {};// let mPath = item.path.split("/");item.meta.auth = (item.auth && item.auth.length>0) ? true : false; //auth为[]时,不需要权限r = {// mpath: mPath[mPath.length - 1],path: item.path,name: item.name,meta: item.meta,}r.meta.title = item.title || '';r.meta.notCache = true;r.meta.actions = item.actions;r.meta.menu = item.menu;if (item.redirect) {r.redirect = { name: item.redirect };}if (item.children && item.children.length > 0) {r.component = vueCompontent[level];r.children = getRouterByAppMenu(item.children, level + 1);}else {r.component = resolve => require([`@/pages/${item.component || 'default/default.tpl'}.vue`], resolve);// r.meta.template = r.meta.template || 'none.initpage';}routers.push(r);})return routers;
}
router/index.js(动态路由)核心代码如下:
import Vue from 'vue';
import VueRouter from 'vue-router';
import util, { getRouterByAppMenu } from '@/libs/util'
import Setting from '@/setting';
import store from '@/store/index';
import routes from './routes';// 路由数据
import { loadApplicationMenu } from "../services/appmenu";
Vue.use(VueRouter);const router = new VueRouter({routes,mode: Setting.routerMode,base: Setting.routerBase
});(async () => {/*** 路由拦截,权限验证*/let app = await loadApplicationMenu(appname); //调用接口获取web应用信息let ROUTERS = getRouterByAppMenu(app.menu, 0); //封装配置的menu为routesfor (let i in ROUTERS) {let mRouter = ROUTERS[i];routes.push(mRouter);router.addRoute(mRouter);}let Router404 = {path: '*',name: '404',meta: {title: '404'},component: () => import('@/pages/system/error/404')};routes.push(Router404);router.addRoute(Router404);router.beforeResolve((to, from, next) => {// 判断是否需要登录才可以进入if (to.matched.some(_ => _.meta.auth)) {// 这里依据 token 判断是否登录,可视情况修改if (token && token !== 'undefined') {next();} else {// 没有登录的时候跳转到登录界面, 携带上登陆成功之后需要跳转的页面完整路径next({name: 'login',query: {redirect: to.fullPath}});}} else {// 不需要身份校验 直接通过next(); }});router.afterEach(to => {// 多页控制 打开新的页面store.dispatch('admin/page/open', to);// 更改标题util.title({title: to.meta.title});// 返回页面顶端window.scrollTo(0, 0);});
})();
export default router;
3.渲染amis页面
pages/default/default.tpl.vue(amis页面渲染器)核心代码如下:
import axios from "axios";
import store from '@/store';
import router from '@/router';
import {Notice,Message} from 'view-design';
import { loadPageTemplate } from "./services/system";
const amis = amisRequire("amis/embed");
import Setting from "@/setting";axios.interceptors.response.use(res => res, //res为axios封装后的结果,amis底层会进行.data取出接口数据error => {if (error.response.status == 401) { // token 过期router.app._route.name !== 'login' && store.dispatch('admin/account/logout');}return Promise.reject(error)});const amisEnv =
{// api接口调用fetcher实现fetcher: ({url, // 接口地址method, // 请求方法 get、post、put、deletedata, // 请求数据responseType,config, // 其他配置headers // 请求头}) => {config.withCredentials = true;responseType && (config.responseType = responseType);if (config.cancelExecutor) {config.cancelToken = new (axios).CancelToken(config.cancelExecutor);}config.headers = headers || {};config.headers["Authorization"]= `Bearer ${token}`;if (method !== 'post' && method !== 'put' && method !== 'patch') {if (data) {config.params = data;}return (axios)[method](url, config);} else if (data && data instanceof FormData) {// config.headers['Content-Type'] = 'multipart/form-data';} else if (data &&typeof data !== 'string' &&!(data instanceof Blob) &&!(data instanceof ArrayBuffer)) {data = JSON.stringify(data);config.headers['Content-Type'] = 'application/json';}return (axios)[method](url, data, config);},isCancel: (value) => { (axios).isCancel(value) },copy: content => {copy(content);toast.success('内容已复制到粘贴板');},// 用来实现通知,不传则使用amis内置notify: (type, msg) => {if (msg != 'Response is empty!') {let mtype = {success: '成功',error: '错误',info: '信息',warning: '警告',warn: '警惕'}Notice[type]({title: mtype[type],desc: msg.toString()});}},// 用来实现提示,不传则使用amis内置alert: content => {Message.info({content: content,duration: 3,closable: true});},// 用来实现确认框,不传则使用amis内置。// confirm: content => {}// 主题,默认是 default,还可以设置成 cxd 或 dark,但记得引用它们的 css,比如 sdk 目录下的 cxd.csstheme: "ang"
}//tracker可以在监听到指定事件触发后,进行相关处理。
// const tracker = (eventTrack, props) => {
// //tracker监听到FormItem改变后, 更新到vue中,可以用来做参数配置器
// if (eventTrack.eventType == 'formItemChange') {
// const formData = this.amisScoped.getComponentByName("mpage.mform")?.getValues();
// }
// }
// amisEnv.tracker = tracker;
// amisEnv.session = "global"export default {watch: {"$route.meta.template": {handler(template) {this.loadInit(template);},immediate: false,},},async mounted() {this.loadInit(this.$route.meta.template);},beforeDestroy() {this.amisScoped?.unmount();},methods: {async loadInit(id) {let pl = await loadPageTemplate(id); //获取amis页面信息const m = pl.data;if (m) {this.amisScoped?.unmount();const amisJSON = JSON.parse(template);amisJSON.data = { ...amisJSON.data, appname, user: this.userInfo }if(this.$refs["vnode"]){this.amisScoped = amis.embed(this.$refs["vnode"],amisJSON,{ theme: "ang" },amisEnv);}}}}
}