feat: improve code
This commit is contained in:
parent
1cb28f0309
commit
07c53a6d2e
@ -8,6 +8,13 @@ export default defineConfig({
|
||||
define: {
|
||||
'process.env.API_URL': process.env.API_URL,
|
||||
},
|
||||
proxy: {
|
||||
'/api': {
|
||||
'target': `http://localhost:${process.env.API_PORT}/`,
|
||||
'changeOrigin': true,
|
||||
'pathRewrite': { '^/api' : '/api' },
|
||||
},
|
||||
},
|
||||
// mfsu: {},
|
||||
// ssr: {},
|
||||
// exportStatic: {},
|
||||
|
17
mock/api.ts
17
mock/api.ts
@ -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);
|
||||
}
|
||||
},
|
||||
}
|
@ -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',
|
||||
},
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
},
|
||||
});
|
||||
}
|
@ -1,8 +0,0 @@
|
||||
import Mock from 'mockjs';
|
||||
|
||||
export async function list(req: any, res: any) {
|
||||
res.json({
|
||||
data: [],
|
||||
meta: {},
|
||||
});
|
||||
}
|
@ -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 };
|
@ -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`,
|
||||
},
|
||||
],
|
||||
},
|
||||
});
|
||||
}
|
@ -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'),
|
||||
},
|
||||
});
|
||||
}
|
@ -13,6 +13,13 @@ export default defineConfig({
|
||||
define: {
|
||||
'process.env.API_URL': process.env.API_URL,
|
||||
},
|
||||
proxy: {
|
||||
'/api': {
|
||||
'target': `http://localhost:${process.env.API_PORT}/`,
|
||||
'changeOrigin': true,
|
||||
'pathRewrite': { '^/api' : '/api' },
|
||||
},
|
||||
},
|
||||
routes: [
|
||||
{ path: '/', exact: false, component: '@/pages/index' },
|
||||
],
|
||||
|
@ -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);
|
||||
}
|
||||
},
|
||||
}
|
@ -1,8 +0,0 @@
|
||||
import Mock from 'mockjs';
|
||||
|
||||
export async function list(req: any, res: any) {
|
||||
res.json({
|
||||
data: [],
|
||||
meta: {},
|
||||
});
|
||||
}
|
@ -1,6 +0,0 @@
|
||||
|
||||
import * as routes from './routes';
|
||||
import * as users from './users';
|
||||
import * as examples from './examples';
|
||||
|
||||
export { routes, users, examples };
|
@ -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`,
|
||||
},
|
||||
],
|
||||
},
|
||||
});
|
||||
}
|
@ -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'),
|
||||
},
|
||||
});
|
||||
}
|
@ -24,6 +24,7 @@ request.use(async (ctx, next) => {
|
||||
if (token) {
|
||||
headers['Authorization'] = `Bearer ${token}`;
|
||||
}
|
||||
headers['X-Hostname'] = window.location.hostname;
|
||||
await next();
|
||||
});
|
||||
|
||||
|
@ -8,7 +8,7 @@ function createApp(opts) {
|
||||
database: {
|
||||
username: process.env.DB_USER,
|
||||
password: process.env.DB_PASSWORD,
|
||||
database: process.env.DB_DATABASE,
|
||||
database: name,
|
||||
host: process.env.DB_HOST,
|
||||
port: process.env.DB_PORT as any,
|
||||
dialect: process.env.DB_DIALECT as any,
|
||||
@ -32,33 +32,20 @@ function createApp(opts) {
|
||||
},
|
||||
},
|
||||
// 不能再 bodyParser,会卡死
|
||||
bodyParser: false,
|
||||
// bodyParser: false,
|
||||
// dataWrapping: false,
|
||||
resourcer: {
|
||||
prefix: `/api/multiapps/${name}`,
|
||||
prefix: '/api',
|
||||
// prefix: `/api/multiapps/${name}`,
|
||||
},
|
||||
};
|
||||
const app = new Application(options);
|
||||
|
||||
app.db.sequelize.beforeDefine((model, options) => {
|
||||
options.tableName = `multiapps_${name}_${
|
||||
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();
|
||||
},
|
||||
},
|
||||
});
|
||||
// app.db.sequelize.beforeDefine((model, options) => {
|
||||
// options.tableName = `multiapps_${name}_${
|
||||
// options.tableName || options.name.plural
|
||||
// }`;
|
||||
// });
|
||||
|
||||
const plugins = [
|
||||
'@nocobase/plugin-ui-schema',
|
||||
@ -86,10 +73,12 @@ function createApp(opts) {
|
||||
function multiApps({ getAppName }) {
|
||||
return async function (ctx: Koa.Context, next) {
|
||||
const appName = getAppName(ctx);
|
||||
console.log({ appName });
|
||||
if (!appName) {
|
||||
return next();
|
||||
}
|
||||
const App = ctx.db.getModel('applications');
|
||||
// @ts-ignore
|
||||
const App = ctx.app.db.getModel('applications');
|
||||
const model = await App.findOne({
|
||||
where: { name: appName },
|
||||
});
|
||||
@ -108,9 +97,11 @@ function multiApps({ getAppName }) {
|
||||
console.log('..........................start........................');
|
||||
// 完全隔离的做法
|
||||
const app = apps.get(appName) as Application;
|
||||
// @ts-ignore
|
||||
console.log(app.db.options);
|
||||
const bodyParser = async (ctx2, next) => {
|
||||
// @ts-ignore
|
||||
ctx2.request.body = ctx.request.body || {};
|
||||
// ctx2.request.body = ctx.request.body || {};
|
||||
await next();
|
||||
};
|
||||
app.middleware.unshift(bodyParser);
|
||||
@ -172,15 +163,23 @@ export default {
|
||||
},
|
||||
],
|
||||
});
|
||||
this.app.use(
|
||||
multiApps({
|
||||
getAppName(ctx) {
|
||||
return ctx.path.split('/')[3];
|
||||
},
|
||||
}),
|
||||
);
|
||||
this.app.middleware.unshift(multiApps({
|
||||
getAppName(ctx) {
|
||||
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) => {
|
||||
const name = model.get('name');
|
||||
await this.app.db.sequelize.query(`CREATE DATABASE "${name}";`);
|
||||
const app = createApp({
|
||||
name,
|
||||
});
|
||||
@ -193,7 +192,7 @@ export default {
|
||||
},
|
||||
});
|
||||
await app.emitAsync('db.init');
|
||||
await app.destroy();
|
||||
// await app.destroy();
|
||||
this.app['apps'].set(name, app);
|
||||
model.set('status', 'running');
|
||||
await model.save({ hooks: false });
|
||||
|
Loading…
Reference in New Issue
Block a user