feat: improve code

This commit is contained in:
chenos 2021-09-30 15:16:41 +08:00
parent 1cb28f0309
commit 07c53a6d2e
17 changed files with 46 additions and 523 deletions

View File

@ -8,6 +8,13 @@ export default defineConfig({
define: { define: {
'process.env.API_URL': process.env.API_URL, 'process.env.API_URL': process.env.API_URL,
}, },
proxy: {
'/api': {
'target': `http://localhost:${process.env.API_PORT}/`,
'changeOrigin': true,
'pathRewrite': { '^/api' : '/api' },
},
},
// mfsu: {}, // mfsu: {},
// ssr: {}, // ssr: {},
// exportStatic: {}, // exportStatic: {},

View File

View File

@ -1,17 +0,0 @@
import Mock from 'mockjs';
import * as resources from './resources';
export default {
'/api/:resource::action': (req: any, res: any) => {
const action = resources[req.params.resource][req.params.action];
if (action) {
return action(req, res);
}
},
'/api/:resource::action/:resourceIndex': (req: any, res: any) => {
const action = resources[req.params.resource][req.params.action];
if (action) {
return action(req, res);
}
},
}

View File

@ -1,37 +0,0 @@
import Mock from 'mockjs';
export async function getOptions(req: any, res: any) {
res.json({
data: {
name: 'grid1',
'x-component': 'GridBlock',
blocks: [
{
name: 'form1',
resource: {
resourceName: 'users',
resourceKey: 1,
},
fields: [
{
interface: 'string',
type: 'string',
title: `单行文本`,
name: 'username',
required: true,
component: {
type: 'string',
default: 'abcdefg',
'x-decorator': 'FormItem',
'x-component': 'Input',
'x-component-props': {
placeholder: 'please enter',
},
},
},
],
},
],
},
});
}

View File

@ -1,8 +0,0 @@
import Mock from 'mockjs';
export async function list(req: any, res: any) {
res.json({
data: [],
meta: {},
});
}

View File

@ -1,7 +0,0 @@
import * as blocks from './blocks';
import * as routes from './routes';
import * as users from './users';
import * as examples from './examples';
export { blocks, routes, users, examples };

View File

@ -1,184 +0,0 @@
import Mock from 'mockjs';
export async function getAccessible(req: any, res: any) {
res.json({
data: [
{
type: 'redirect',
from: '/admin',
to: '/admin/welcome',
exact: true,
},
{
type: 'redirect',
from: '/',
to: '/admin',
exact: true,
},
{
path: '/admin/:name(.+)?',
component: 'AdminLayout',
title: `后台 - ${Mock.mock('@string')}`,
// providers: ['CurrentUserProvider', 'MenuProvider'],
},
{
component: 'AuthLayout',
routes: [
{
name: 'login',
path: '/login',
component: 'PageTemplate',
title: `登录 - ${Mock.mock('@string')}`,
},
{
name: 'register',
path: '/register',
component: 'PageTemplate',
title: `注册 - ${Mock.mock('@string')}`,
},
],
},
],
});
}
export async function getMenu(req: any, res: any) {
res.json({
data: [
{
name: 'welcome',
title: `欢迎 - ${Mock.mock('@string')}`,
children: [
{
name: 'page2',
title: '页面2',
},
],
},
{
name: 'users',
title: `用户 - ${Mock.mock('@string')}`,
},
],
});
}
export async function getPage(req: any, res: any) {
const fields = [
{
interface: 'string',
type: 'string',
title: `单行文本 - ${Mock.mock('@string')}`,
name: 'input',
required: true,
component: {
type: 'string',
default: 'aa',
'x-decorator': 'FormItem',
'x-component': 'Input',
'x-component-props': {},
},
},
{
interface: 'textarea',
type: 'text',
title: `多行文本框 - ${Mock.mock('@string')}`,
name: 'textarea',
required: true,
component: {
type: 'string',
'x-decorator': 'FormItem',
'x-component': 'Input.TextArea',
'x-component-props': {},
},
},
];
res.json({
data: {
title: `page - ${req.query.slug} - ${Mock.mock('@string')}`,
blocks: [
{
interface: 'form',
type: 'form',
component: {
'x-component': 'Form',
},
fields,
},
{
interface: 'table',
type: 'table',
component: {
'x-component': 'Table',
},
fields,
},
{
interface: 'calendar',
type: 'calendar',
component: {
'x-component': 'Calendar',
},
},
{
interface: 'kanban',
type: 'kanban',
component: {
'x-component': 'Kanban',
},
},
{
interface: 'grid',
type: 'grid',
component: {
'x-component': 'Grid',
},
rowProps: {
gutter: 16,
},
colsProps: [12, 12],
blocks: [
{
interface: 'markdown',
type: 'markdown',
component: {
'x-component': 'Markdown',
},
content: `# Markdown Content 1`,
rowOrder: 1,
columnOrder: 1,
},
{
interface: 'markdown',
type: 'markdown',
component: {
'x-component': 'Markdown',
},
content: `# Markdown Content 2`,
rowOrder: 2,
columnOrder: 2,
},
{
interface: 'markdown',
type: 'markdown',
component: {
'x-component': 'Markdown',
},
content: `# Markdown Content 1`,
rowOrder: 1,
columnOrder: 2,
},
],
},
{
interface: 'markdown',
type: 'markdown',
component: {
'x-component': 'Markdown',
},
content: `# Markdown Content`,
},
],
},
});
}

View File

@ -1,19 +0,0 @@
import Mock from 'mockjs';
export async function check(req: any, res: any) {
res.json({
data: {
username: `username - ${Mock.mock('@string')}`,
token: Mock.mock('@string'),
},
});
}
export async function get(req: any, res: any) {
res.json({
data: {
username: `username - ${Mock.mock('@string')}`,
token: Mock.mock('@string'),
},
});
}

View File

@ -13,6 +13,13 @@ export default defineConfig({
define: { define: {
'process.env.API_URL': process.env.API_URL, 'process.env.API_URL': process.env.API_URL,
}, },
proxy: {
'/api': {
'target': `http://localhost:${process.env.API_PORT}/`,
'changeOrigin': true,
'pathRewrite': { '^/api' : '/api' },
},
},
routes: [ routes: [
{ path: '/', exact: false, component: '@/pages/index' }, { path: '/', exact: false, component: '@/pages/index' },
], ],

View File

@ -1,11 +0,0 @@
import Mock from 'mockjs';
import * as resources from './resources';
export default {
'/api/:resource::action': (req: any, res: any) => {
const action = resources[req.params.resource][req.params.action];
if (action) {
return action(req, res);
}
},
}

View File

@ -1,8 +0,0 @@
import Mock from 'mockjs';
export async function list(req: any, res: any) {
res.json({
data: [],
meta: {},
});
}

View File

@ -1,6 +0,0 @@
import * as routes from './routes';
import * as users from './users';
import * as examples from './examples';
export { routes, users, examples };

View File

@ -1,184 +0,0 @@
import Mock from 'mockjs';
export async function getAccessible(req: any, res: any) {
res.json({
data: [
{
type: 'redirect',
from: '/admin',
to: '/admin/welcome',
exact: true,
},
{
type: 'redirect',
from: '/',
to: '/admin',
exact: true,
},
{
path: '/admin/:name(.+)?',
component: 'AdminLayout',
title: `后台 - ${Mock.mock('@string')}`,
// providers: ['CurrentUserProvider', 'MenuProvider'],
},
{
component: 'AuthLayout',
routes: [
{
name: 'login',
path: '/login',
component: 'PageTemplate',
title: `登录 - ${Mock.mock('@string')}`,
},
{
name: 'register',
path: '/register',
component: 'PageTemplate',
title: `注册 - ${Mock.mock('@string')}`,
},
],
},
],
});
}
export async function getMenu(req: any, res: any) {
res.json({
data: [
{
name: 'welcome',
title: `欢迎 - ${Mock.mock('@string')}`,
children: [
{
name: 'page2',
title: '页面2',
},
],
},
{
name: 'users',
title: `用户 - ${Mock.mock('@string')}`,
},
],
});
}
export async function getPage(req: any, res: any) {
const fields = [
{
interface: 'string',
type: 'string',
title: `单行文本 - ${Mock.mock('@string')}`,
name: 'input',
required: true,
component: {
type: 'string',
default: 'aa',
'x-decorator': 'FormItem',
'x-component': 'Input',
'x-component-props': {},
},
},
{
interface: 'textarea',
type: 'text',
title: `多行文本框 - ${Mock.mock('@string')}`,
name: 'textarea',
required: true,
component: {
type: 'string',
'x-decorator': 'FormItem',
'x-component': 'Input.TextArea',
'x-component-props': {},
},
},
];
res.json({
data: {
title: `page - ${req.query.slug} - ${Mock.mock('@string')}`,
blocks: [
{
interface: 'form',
type: 'form',
component: {
'x-component': 'Form',
},
fields,
},
{
interface: 'table',
type: 'table',
component: {
'x-component': 'Table',
},
fields,
},
{
interface: 'calendar',
type: 'calendar',
component: {
'x-component': 'Calendar',
},
},
{
interface: 'kanban',
type: 'kanban',
component: {
'x-component': 'Kanban',
},
},
{
interface: 'grid',
type: 'grid',
component: {
'x-component': 'Grid',
},
rowProps: {
gutter: 16,
},
colsProps: [12, 12],
blocks: [
{
interface: 'markdown',
type: 'markdown',
component: {
'x-component': 'Markdown',
},
content: `# Markdown Content 1`,
rowOrder: 1,
columnOrder: 1,
},
{
interface: 'markdown',
type: 'markdown',
component: {
'x-component': 'Markdown',
},
content: `# Markdown Content 2`,
rowOrder: 2,
columnOrder: 2,
},
{
interface: 'markdown',
type: 'markdown',
component: {
'x-component': 'Markdown',
},
content: `# Markdown Content 1`,
rowOrder: 1,
columnOrder: 2,
},
],
},
{
interface: 'markdown',
type: 'markdown',
component: {
'x-component': 'Markdown',
},
content: `# Markdown Content`,
},
],
},
});
}

View File

@ -1,10 +0,0 @@
import Mock from 'mockjs';
export async function check(req: any, res: any) {
res.json({
data: {
username: `username - ${Mock.mock('@string')}`,
token: Mock.mock('@string'),
},
});
}

View File

@ -24,6 +24,7 @@ request.use(async (ctx, next) => {
if (token) { if (token) {
headers['Authorization'] = `Bearer ${token}`; headers['Authorization'] = `Bearer ${token}`;
} }
headers['X-Hostname'] = window.location.hostname;
await next(); await next();
}); });

View File

@ -8,7 +8,7 @@ function createApp(opts) {
database: { database: {
username: process.env.DB_USER, username: process.env.DB_USER,
password: process.env.DB_PASSWORD, password: process.env.DB_PASSWORD,
database: process.env.DB_DATABASE, database: name,
host: process.env.DB_HOST, host: process.env.DB_HOST,
port: process.env.DB_PORT as any, port: process.env.DB_PORT as any,
dialect: process.env.DB_DIALECT as any, dialect: process.env.DB_DIALECT as any,
@ -32,33 +32,20 @@ function createApp(opts) {
}, },
}, },
// 不能再 bodyParser会卡死 // 不能再 bodyParser会卡死
bodyParser: false, // bodyParser: false,
// dataWrapping: false, // dataWrapping: false,
resourcer: { resourcer: {
prefix: `/api/multiapps/${name}`, prefix: '/api',
// prefix: `/api/multiapps/${name}`,
}, },
}; };
const app = new Application(options); const app = new Application(options);
app.db.sequelize.beforeDefine((model, options) => { // app.db.sequelize.beforeDefine((model, options) => {
options.tableName = `multiapps_${name}_${ // options.tableName = `multiapps_${name}_${
options.tableName || options.name.plural // options.tableName || options.name.plural
}`; // }`;
}); // });
app.resource({
name: 'saas',
actions: {
async getInfo(ctx, next) {
ctx.body = {
m: Object.values(ctx.db.sequelize.models).map(
(m: any) => m.tableName,
),
};
await next();
},
},
});
const plugins = [ const plugins = [
'@nocobase/plugin-ui-schema', '@nocobase/plugin-ui-schema',
@ -86,10 +73,12 @@ function createApp(opts) {
function multiApps({ getAppName }) { function multiApps({ getAppName }) {
return async function (ctx: Koa.Context, next) { return async function (ctx: Koa.Context, next) {
const appName = getAppName(ctx); const appName = getAppName(ctx);
console.log({ appName });
if (!appName) { if (!appName) {
return next(); return next();
} }
const App = ctx.db.getModel('applications'); // @ts-ignore
const App = ctx.app.db.getModel('applications');
const model = await App.findOne({ const model = await App.findOne({
where: { name: appName }, where: { name: appName },
}); });
@ -108,9 +97,11 @@ function multiApps({ getAppName }) {
console.log('..........................start........................'); console.log('..........................start........................');
// 完全隔离的做法 // 完全隔离的做法
const app = apps.get(appName) as Application; const app = apps.get(appName) as Application;
// @ts-ignore
console.log(app.db.options);
const bodyParser = async (ctx2, next) => { const bodyParser = async (ctx2, next) => {
// @ts-ignore // @ts-ignore
ctx2.request.body = ctx.request.body || {}; // ctx2.request.body = ctx.request.body || {};
await next(); await next();
}; };
app.middleware.unshift(bodyParser); app.middleware.unshift(bodyParser);
@ -172,15 +163,23 @@ export default {
}, },
], ],
}); });
this.app.use( this.app.middleware.unshift(multiApps({
multiApps({
getAppName(ctx) { getAppName(ctx) {
return ctx.path.split('/')[3]; const hostname = ctx.get('X-Hostname');
if (!hostname) {
return;
}
const keys = hostname.split('.');
if (keys.length < 4) {
return;
}
console.log('ctx.hostname', ctx.get('X-Hostname'));
return keys.shift();
}, },
}), }));
);
this.app.db.on('applications.afterCreate', async (model: Model) => { this.app.db.on('applications.afterCreate', async (model: Model) => {
const name = model.get('name'); const name = model.get('name');
await this.app.db.sequelize.query(`CREATE DATABASE "${name}";`);
const app = createApp({ const app = createApp({
name, name,
}); });
@ -193,7 +192,7 @@ export default {
}, },
}); });
await app.emitAsync('db.init'); await app.emitAsync('db.init');
await app.destroy(); // await app.destroy();
this.app['apps'].set(name, app); this.app['apps'].set(name, app);
model.set('status', 'running'); model.set('status', 'running');
await model.save({ hooks: false }); await model.save({ hooks: false });