feat: access and model done

This commit is contained in:
万纯 2020-12-17 16:54:50 +08:00
parent 050e4a7b10
commit 8103071168
11 changed files with 127 additions and 138 deletions

View File

@ -49,7 +49,7 @@ export default (api) => {
}
]);
api.addRuntimePluginKey(() => 'notAllowHandler');
api.addRuntimePluginKey(() => 'noAccessHandler');
api.addRuntimePlugin(() => `@@/${absRuntimeFilePath}`);
};

View File

@ -1,4 +1,6 @@
import { reactive, computed } from "vue";
import { reactive, computed, inject } from "vue";
const accessKey = Symbol("plugin-access");
function isPromise(obj) {
return (
@ -106,32 +108,38 @@ const match = (path, accessIds) => {
}
}
return false;
}
const hasLoading = ()=>{
return rolePromiseList.length || accessPromiseList.length
}
const hasAccess = async (path) => {
if(!hasLoading()){
return match(path, getAllowAccessIds())
}
await Promise.all(rolePromiseList.concat(accessPromiseList));
return match(path, getAllowAccessIds())
};
const allowPageIds = computed(getAllowAccessIds);
const hasLoading = () => {
return rolePromiseList.length || accessPromiseList.length;
};
const hasAccess = async (path) => {
if (!hasLoading()) {
return match(path, getAllowAccessIds());
}
await Promise.all(rolePromiseList.concat(accessPromiseList));
return match(path, getAllowAccessIds());
};
export const install = (app) => {
const allowPageIds = computed(getAllowAccessIds);
const useAccess = (path) => {
const result = computed(() => {
return match(path, allowPageIds.value);
});
return result;
};
app.provide(accessKey, useAccess);
};
export const access = {
hasAccess,
hasLoading,
setRole,
setAccess
}
setAccess,
};
export const useAccess = (path) => {
const result = computed(() => {
return match(path, allowPageIds.value);
});
return result;
}
return inject(accessKey)(path);
};

View File

@ -1,15 +1,6 @@
import { access } from "./core";
import { access, install } from "./core";
import { plugin, ApplyPluginsType } from "@@/core/coreExports";
async function getInitialState() {
const appGetInitialState = plugin.applyPlugins({
key: "getInitialState",
type: ApplyPluginsType.modify,
initialValue: {},
});
return await appGetInitialState;
}
export function onRouterCreated({ router }) {
router.beforeEach(async (to, from, next) => {
let path;
@ -18,21 +9,23 @@ export function onRouterCreated({ router }) {
} else {
path = to.path;
}
// 等待初始化数据
await getInitialState();
const canRoute = await access.hasAccess(path);
if (canRoute) {
next();
} else {
const notAllowHandler = plugin.applyPlugins({
key: "notAllowHandler",
const noAccessHandler = plugin.applyPlugins({
key: "noAccessHandler",
type: ApplyPluginsType.modify,
initialValue: null,
});
if (notAllowHandler && typeof notAllowHandler === "function") {
notAllowHandler(router, to, from);
if (noAccessHandler && typeof noAccessHandler === "function") {
noAccessHandler(router, to, from);
}
next(false);
}
});
}
export function onAppCreated({ app }) {
install(app)
}

View File

@ -16,6 +16,8 @@ export default function (api) {
key: 'addRuntimePluginKey',
type: api.ApplyPluginsType.add,
initialValue: [
// 初始化数据
'beforeRender',
'modifyClientRenderOpts',
'rootContainer',
// app生成时触发
@ -25,9 +27,7 @@ export default function (api) {
// 修改路由
'patchRoutes',
// 生成router时触发
'onRouterCreated',
// 初始化数据
'getInitialState'
'onRouterCreated'
]
});
const plugins = await api.applyPlugins({

View File

@ -13,7 +13,7 @@ import { getRoutes } from './core/routes/routes';
{{{ entryCodeAhead }}}
const renderClient = (opts = {}) => {
const { plugin, routes, rootElement } = opts;
const { plugin, routes, rootElement, initialState } = opts;
const rootContainer = plugin.applyPlugins({
type: ApplyPluginsType.modify,
key: 'rootContainer',
@ -25,6 +25,7 @@ const renderClient = (opts = {}) => {
});
const app = createApp(rootContainer);
app.provide("initialState", initialState);
plugin.applyPlugins({
key: 'onAppCreated',
@ -32,7 +33,6 @@ const renderClient = (opts = {}) => {
args: { app },
});
// TODO other plugins install
if (rootElement) {
app.mount(rootElement);
}
@ -47,6 +47,7 @@ const getClientRender = (args = {}) => plugin.applyPlugins({
key: 'modifyClientRenderOpts',
type: ApplyPluginsType.modify,
initialValue: {
initialState: args.initialState,
routes: args.routes || getRoutes(),
plugin,
rootElement: '{{{ rootElement }}}',
@ -60,8 +61,35 @@ const getClientRender = (args = {}) => plugin.applyPlugins({
args,
});
const clientRender = getClientRender();
export default clientRender();
const beforeRenderConfig = plugin.applyPlugins({
key: "beforeRender",
type: ApplyPluginsType.modify,
initialValue: {
loading: defineComponent(() => () => <></>),
action: () => {},
},
});
const beforeRender = async () => {
if (typeof beforeRenderConfig.action === "function") {
const app = createApp(beforeRenderConfig.loading);
app.mount("#app");
const initialState = await beforeRenderConfig.action();
app.unmount();
return initialState;
}
};
const render = async () => {
const initialState = await beforeRender();
const clientRender = getClientRender({initialState});
clientRender();
};
render();
{{{ entryCode }}}

View File

@ -83,8 +83,5 @@ export default (api) => {
}
]);
// 注册 initialStateConfig 方法
api.addRuntimePluginKey(() => 'initialStateConfig');
api.addRuntimePlugin(() => `@@/${absRuntimeFilePath}`);
};

View File

@ -1,34 +1,12 @@
import { reactive, toRefs, onMounted } from "vue";
import { plugin, ApplyPluginsType } from "@@/core/coreExports";
async function getInitialState() {
const appGetInitialState = plugin.applyPlugins({
key: "getInitialState",
type: ApplyPluginsType.modify,
initialValue: {},
});
return await appGetInitialState;
}
const initState = reactive({
initialState: undefined,
loading: true,
error: undefined,
});
import { reactive, toRefs, inject } from "vue";
export default function initalModel() {
const refresh = async () => {
initState.loading = true;
initState.error = undefined;
try {
const res = await getInitialState();
initState.initialState = res;
initState.loading = false;
} catch (e) {
console.error(e)
initState.loading = false;
initState.error = e;
}
const initialState = reactive(inject("initialState"));
const setInitialState = (obj) => {
initState = reactive(obj);
};
onMounted(refresh);
return toRefs(initState);
return toRefs({
initialState,
setInitialState
});
}

View File

@ -1,3 +1,7 @@
import { inject } from "vue";
const modelKey = Symbol("plugin-model");
{{{userImports}}}
{{{extraImports}}}
@ -10,16 +14,26 @@ export const models = {
{{/userModels}}
}
const cache = new Map();
export const install = (app)=>{
const useModel = (name) => {
const model = models[name];
if(model === undefined){
throw new Error("[plugin-model]: useModel, name is undefined.");
}
if (typeof model !== "function") {
throw new Error("[plugin-model]: useModel is not a function.");
}
if(!cache.has(name)){
cache.set(name, model())
}
return cache.get(name)
};
app.provide(modelKey, useModel);
}
export const useModel = (name) => {
const model = models[name];
if(model === undefined){
throw new Error("[plugin-model]: useModel, name is undefined.");
}
if (typeof model !== "function") {
throw new Error("[plugin-model]: useModel is not a function.");
}
if(!cache.has(name)){
cache.set(name, model())
}
return cache.get(name)
};
return inject(modelKey)(name);
};

View File

@ -1,26 +1,5 @@
import { plugin, ApplyPluginsType } from "@@/core/coreExports";
import { useModel } from "./core.js";
import { install } from "./core";
export function rootContainer(childComponent, args) {
const useRuntimeConfig =
plugin.applyPlugins({
key: "initialStateConfig",
type: ApplyPluginsType.modify,
initialValue: {},
}) || {};
return {
setup() {
const { loading } = useModel("@@initialState") || {};
return () => {
if (loading.value) {
return useRuntimeConfig.loading ? (
<useRuntimeConfig.loading />
) : (
<></>
);
}
return <childComponent />;
};
},
};
export function onAppCreated({ app }) {
install(app)
}

View File

@ -1,27 +1,19 @@
import { access } from '@webank/fes';
import PageLoading from '@/components/PageLoading.vue';
/**
* 获取用户信息比较慢的时候会展示一个 loading
*/
export const initialStateConfig = {
loading: <PageLoading />
};
/**
* 设置页面初始化状态
*/
export async function getInitialState() {
const { setRole } = access;
const syncFunc = () => new Promise((resolve) => {
setTimeout(() => {
setRole('admin');
resolve({
a: 1,
b: 2
});
}, 3000);
});
const res = await syncFunc();
return res;
}
export const beforeRender = {
loading: <PageLoading />,
action() {
const { setRole } = access;
return new Promise((resolve) => {
setTimeout(() => {
setRole('admin');
resolve({
a: 1,
b: 2
});
}, 3000);
});
}
};

View File

@ -20,7 +20,7 @@ export default {
const router = useRouter();
onMounted(() => {
console.log(router);
console.log(initialState.value);
console.log(initialState);
console.log('mounted1!!');
// router.push('/onepiece');
});