Commit b8f9789d authored by 郭志伟's avatar 郭志伟

Merge branch 'feature/tenant' into 'master'

Feature/tenant

See merge request !50
parents 8aa05064 0687d3ca
import { Controller, Context } from 'egg'; import { Controller, Context } from 'egg';
import { trim, omitBy } from 'lodash'; import { omitBy } from 'lodash';
import { v1 as uuidv1 } from 'uuid'; import { v1 as uuidv1 } from 'uuid';
import * as path from 'path';
export default class EditorController extends Controller { export default class EditorController extends Controller {
public async login(ctx: Context) { public async login(ctx: Context) {
...@@ -9,17 +8,13 @@ export default class EditorController extends Controller { ...@@ -9,17 +8,13 @@ export default class EditorController extends Controller {
} }
public async home(ctx: Context) { public async home(ctx: Context) {
let apollo = {}; const apollo = ctx.app.config.apollo || {};
if (process.env.NODE_ENV === 'production' && process.env.EGG_SERVER_ENV === 'sit') {
apollo = ctx.app.config.apollo || {};
}
await ctx.renderClient('editor.js', { apollo }); await ctx.renderClient('editor.js', { apollo });
} }
public async save(ctx: Context) { public async save(ctx: Context) {
const pageInfo = ctx.request.body; const pageInfo = ctx.request.body;
const result = await ctx.model.PageInfo.create({ ...pageInfo, uuid: uuidv1().replace(/-/g, '')}); const result = await ctx.model.PageInfo.create({ ...pageInfo, uuid: uuidv1().replace(/-/g, ''), tenantId: ctx.headers['qg-tenant-id']});
await ctx.service.redis.set(`pageInfo:${result.dataValues.uuid}`, result.dataValues); await ctx.service.redis.set(`pageInfo:${result.dataValues.uuid}`, result.dataValues);
ctx.body = ctx.helper.ok(result); ctx.body = ctx.helper.ok(result);
} }
...@@ -29,7 +24,10 @@ export default class EditorController extends Controller { ...@@ -29,7 +24,10 @@ export default class EditorController extends Controller {
if (!pageInfo.uuid) { if (!pageInfo.uuid) {
pageInfo.uuid = uuidv1().replace(/-/g, ''); pageInfo.uuid = uuidv1().replace(/-/g, '');
} }
const result = await ctx.model.PageInfo.update(pageInfo, {where: { uuid: pageInfo.uuid }}); if (ctx.headers['qg-tenant-id']) {
pageInfo.tenantId = +ctx.headers['qg-tenant-id'];
}
const result = await ctx.model.PageInfo.update(pageInfo, {where: { uuid: pageInfo.uuid, tenantId: ctx.headers['qg-tenant-id'] }});
await ctx.service.redis.set(`pageInfo:${pageInfo.uuid}`, pageInfo); await ctx.service.redis.set(`pageInfo:${pageInfo.uuid}`, pageInfo);
await ctx.service.redis.del(`page:${pageInfo.uuid}`); await ctx.service.redis.del(`page:${pageInfo.uuid}`);
ctx.body = ctx.helper.ok(result); ctx.body = ctx.helper.ok(result);
...@@ -38,7 +36,14 @@ export default class EditorController extends Controller { ...@@ -38,7 +36,14 @@ export default class EditorController extends Controller {
public async get(ctx: Context) { public async get(ctx: Context) {
let pageInfo = await ctx.service.redis.get(`pageInfo:${ctx.params.uuid}`); let pageInfo = await ctx.service.redis.get(`pageInfo:${ctx.params.uuid}`);
if (!pageInfo) { if (!pageInfo) {
pageInfo = await ctx.model.PageInfo.findOne({where: { uuid: ctx.params.uuid }}); let pageInfo = await ctx.model.PageInfo.findOne({where: { uuid: ctx.params.uuid }});
if (ctx.query.lite && pageInfo) {
const page = JSON.parse(pageInfo.page || []);
for (let i = 0; i < page.elements.length; i++) {
delete page.elements[i].schame
}
pageInfo.page = JSON.stringify(page);
}
await ctx.service.redis.set(`pageInfo:${ctx.params.uuid}`, pageInfo); await ctx.service.redis.set(`pageInfo:${ctx.params.uuid}`, pageInfo);
} }
ctx.body = ctx.helper.ok(pageInfo); ctx.body = ctx.helper.ok(pageInfo);
...@@ -52,6 +57,7 @@ export default class EditorController extends Controller { ...@@ -52,6 +57,7 @@ export default class EditorController extends Controller {
pageName: pageName && { like: `%${pageName}%`}, pageName: pageName && { like: `%${pageName}%`},
pageDescribe: pageDescribe && { like: `%${pageDescribe}%`}, pageDescribe: pageDescribe && { like: `%${pageDescribe}%`},
isPublish, isPublish,
tenantId: ctx.headers['qg-tenant-id'],
enable: 1 enable: 1
}, v => !v); }, v => !v);
if (type === 'list') { if (type === 'list') {
...@@ -67,7 +73,7 @@ export default class EditorController extends Controller { ...@@ -67,7 +73,7 @@ export default class EditorController extends Controller {
} }
public async getTemplateList(ctx: Context) { public async getTemplateList(ctx: Context) {
const list = await ctx.model.PageInfo.findAll({ where: { isTemplate: 1 } }); const list = await ctx.model.PageInfo.findAll({ where: { isTemplate: 1, tenantId: ctx.headers['qg-tenant-id'] } });
ctx.body = ctx.helper.ok(list); ctx.body = ctx.helper.ok(list);
} }
...@@ -77,6 +83,7 @@ export default class EditorController extends Controller { ...@@ -77,6 +83,7 @@ export default class EditorController extends Controller {
[ctx.model.Sequelize.Op.lt]: Date.now(), [ctx.model.Sequelize.Op.lt]: Date.now(),
[ctx.model.Sequelize.Op.gt]: new Date(Date.now() - 1000 * 60 * 60 * 24 * 7) [ctx.model.Sequelize.Op.gt]: new Date(Date.now() - 1000 * 60 * 60 * 24 * 7)
}, },
tenantId: ctx.headers['qg-tenant-id'],
enable: 1, enable: 1,
isPublish: 1 isPublish: 1
}; };
...@@ -84,14 +91,15 @@ export default class EditorController extends Controller { ...@@ -84,14 +91,15 @@ export default class EditorController extends Controller {
attributes: ['uuid'], attributes: ['uuid'],
where where
}); });
pageInfo.forEach(async item => { for (const item of pageInfo) {
await ctx.service.redis.del(`page:${item.uuid}`); await ctx.service.redis.del(`page:${item.uuid}`);
}); ctx.logger.info(`del redis page key page:${item.uuid}`);
}
ctx.body = ctx.helper.ok(); ctx.body = ctx.helper.ok();
} }
public async delete(ctx: Context) { public async delete(ctx: Context) {
const pageInfo = await ctx.model.PageInfo.update({ enable: 0 }, {where: { id: +ctx.params.pageId }}); const pageInfo = await ctx.model.PageInfo.update({ enable: 0 }, {where: { id: +ctx.params.pageId, tenantId: ctx.headers['qg-tenant-id'] }});
ctx.body = ctx.helper.ok(pageInfo); ctx.body = ctx.helper.ok(pageInfo);
} }
} }
\ No newline at end of file
...@@ -86,6 +86,12 @@ export class PageInfo extends Model<PageInfo> { ...@@ -86,6 +86,12 @@ export class PageInfo extends Model<PageInfo> {
}, },
}) })
updatedAt: string; updatedAt: string;
@Column({
type: DataType.INTEGER(11),
field: 'tenant_id',
})
tenantId: number;
} }
export default () => PageInfo; export default () => PageInfo;
\ No newline at end of file
/**
* @desc 页面信息表
*/
import { AutoIncrement, Column, DataType, Model, PrimaryKey, Table, AllowNull } from 'sequelize-typescript';
@Table({
modelName: 'tenant_auth_info',
freezeTableName: true
})
export class TenantAuth extends Model<TenantAuth> {
@PrimaryKey
@AutoIncrement
@Column({
type: DataType.INTEGER(11)
})
id: number;
@AllowNull(false)
@Column({
type: DataType.INTEGER(11),
field: 'tenant_id',
})
tenantId: number;
@Column({
field: 'tenant_name',
type: DataType.STRING(32)
})
tenantName: string;
@Column({
field: 'auth_config',
type: DataType.TEXT
})
authConfig: string;
@Column({
field: 'config_desc',
type: DataType.STRING(255)
})
configDesc: string;
@Column({
type: DataType.INTEGER(1)
})
enable: number;
@Column({
type: DataType.DATE,
field: 'updated_at',
get() {
const moment = require('moment');
const updatedAt = this.getDataValue('updatedAt');
return moment(updatedAt).format('YYYY-MM-DD HH:mm:ss');
},
})
updatedAt: string;
}
export default () => TenantAuth;
\ No newline at end of file
...@@ -19,3 +19,9 @@ export function getUserInfo() { ...@@ -19,3 +19,9 @@ export function getUserInfo() {
accessToken: true accessToken: true
}); });
} }
// 获取权限
export function getMenuData() {
return http.get(`${config.opapiHost}/backStms/user/getresources/APP016`, {
accessToken: true
});
}
\ No newline at end of file
...@@ -3,7 +3,7 @@ ...@@ -3,7 +3,7 @@
<Row type="flex" class="layout-container" v-if="!isDashboard"> <Row type="flex" class="layout-container" v-if="!isDashboard">
<Sider collapsible :collapsed-width="71" style="z-index: 100" ref="sider" v-model="isCollapsed"> <Sider collapsible :collapsed-width="71" style="z-index: 100" ref="sider" v-model="isCollapsed">
<Menu :active-name="activeName" theme="dark" width="auto" :open-names="openNames" accordion @on-select="select" :class="menuitemClasses" ref="menus"> <Menu :active-name="activeName" theme="dark" width="auto" :open-names="openNames" accordion @on-select="select" :class="menuitemClasses" ref="menus">
<template v-for="(menu, index) in page"> <template v-for="(menu, index) in pageList">
<MenuItem style="background: #001529;" v-if="!isCollapsed" :name="index" :key="menu.name"> <MenuItem style="background: #001529;" v-if="!isCollapsed" :name="index" :key="menu.name">
<Icon :type="menu.icon"></Icon> <Icon :type="menu.icon"></Icon>
<span class="layout-text">{{ menu.name }}</span> <span class="layout-text">{{ menu.name }}</span>
...@@ -37,7 +37,8 @@ ...@@ -37,7 +37,8 @@
</div> </div>
</template> </template>
<script> <script>
export default { import { mapActions, mapState } from 'vuex';
export default {
data() { data() {
return { return {
showLoading: false, showLoading: false,
...@@ -65,6 +66,9 @@ ...@@ -65,6 +66,9 @@
} }
}, },
methods: { methods: {
...mapActions([
'fetchTenantAuthData'
]),
select(name) { select(name) {
console.log('select', name); console.log('select', name);
const current = this.page[name]; const current = this.page[name];
...@@ -79,9 +83,32 @@ ...@@ -79,9 +83,32 @@
}, },
}, },
created() { created() {
this.fetchTenantAuthData();
console.log('isDashboard', this.$route); console.log('isDashboard', this.$route);
}, },
watch: {
$route(to, from) {
console.log(to, from);
if (to.path !== from.path && to.path === '/list') {
this.activeName = 0;
}
},
},
computed: { computed: {
...mapState([ 'tmplList', 'draftList', 'workist' ]),
pageList() {
const pageList = JSON.parse(JSON.stringify(this.page));
if(this.tmplList) {
pageList.splice(2, 1);
}
if(this.draftList) {
pageList.splice(1, 1);
}
if(this.workist) {
pageList.splice(0, 1);
}
return pageList;
},
menuitemClasses: function() { menuitemClasses: function() {
return ['ivu-menu-dark', 'menu-item', this.isCollapsed ? 'collapsed-menu' : '']; return ['ivu-menu-dark', 'menu-item', this.isCollapsed ? 'collapsed-menu' : ''];
}, },
...@@ -90,7 +117,7 @@ ...@@ -90,7 +117,7 @@
return this.$route.name === 'detail'; return this.$route.name === 'detail';
} }
}, },
} }
</script> </script>
<style lang="less" scoped> <style lang="less" scoped>
.layout { .layout {
......
import { Action, State } from 'vuex-class';
import { Vue, Component, Prop, Watch } from 'vue-property-decorator'; import { Vue, Component, Prop, Watch } from 'vue-property-decorator';
import iView from 'iview'; import iView from 'iview';
import Raven from 'raven-js'; import Raven from 'raven-js';
...@@ -27,6 +28,8 @@ if (process.env.SENTRY_ENV !== 'test' && process.env.NODE_ENV === 'production') ...@@ -27,6 +28,8 @@ if (process.env.SENTRY_ENV !== 'test' && process.env.NODE_ENV === 'production')
export default class Layout extends Vue { export default class Layout extends Vue {
activeName: string = 'list'; activeName: string = 'list';
username: string = localStorage.get('user')?.name || '陌生人'; username: string = localStorage.get('user')?.name || '陌生人';
@Action('fetchTenantAuthData') fetchTenantAuthData;
@State(state => state.tenant) tenant;
get isDashboard() { get isDashboard() {
return this.activeName === 'detail'; return this.activeName === 'detail';
...@@ -48,7 +51,8 @@ export default class Layout extends Vue { ...@@ -48,7 +51,8 @@ export default class Layout extends Vue {
window.location.href = '/editor/login'; window.location.href = '/editor/login';
} }
created() { async created() {
await this.fetchTenantAuthData();
console.log('>>EASY_ENV_IS_NODE create', EASY_ENV_IS_NODE); console.log('>>EASY_ENV_IS_NODE create', EASY_ENV_IS_NODE);
} }
} }
\ No newline at end of file
...@@ -4,9 +4,9 @@ ...@@ -4,9 +4,9 @@
<i-col :span="3" class="layout-menu-left"> <i-col :span="3" class="layout-menu-left">
<Menu :active-name="activeName" theme="dark" width="auto" :open-names="['1']" accordion @on-select="select"> <Menu :active-name="activeName" theme="dark" width="auto" :open-names="['1']" accordion @on-select="select">
<div class="layout-logo-left">低代码平台</div> <div class="layout-logo-left">低代码平台</div>
<Menu-item name="list">作品列表</Menu-item> <Menu-item v-if="tenant.workist" name="list">作品列表</Menu-item>
<Menu-item name="my">我的草稿</Menu-item> <Menu-item v-if="tenant.draftList" name="my">我的草稿</Menu-item>
<Menu-item name="template">创意模板</Menu-item> <Menu-item v-if="tenant.tmplList" name="template">创意模板</Menu-item>
</Menu> </Menu>
</i-col> </i-col>
<i-col :span="21" class="layout-menu-right"> <i-col :span="21" class="layout-menu-right">
......
...@@ -6,7 +6,7 @@ ...@@ -6,7 +6,7 @@
<meta name="description" :content="description"> <meta name="description" :content="description">
<meta http-equiv="content-type" content="text/html;charset=utf-8"> <meta http-equiv="content-type" content="text/html;charset=utf-8">
<meta name="viewport" content="initial-scale=1, maximum-scale=1, user-scalable=no, minimal-ui"> <meta name="viewport" content="initial-scale=1, maximum-scale=1, user-scalable=no, minimal-ui">
<link rel="shortcut icon" href="/favicon.ico" type="image/x-icon" /> <link rel="shortcut icon" href="data:image/png;base64" type="image/x-icon" />
<link rel="stylesheet" href="/public/asset/css/reset.css"> <link rel="stylesheet" href="/public/asset/css/reset.css">
<link rel="stylesheet" href=""> <link rel="stylesheet" href="">
</head> </head>
......
...@@ -3,12 +3,17 @@ const protocol = EASY_ENV_IS_BROWSER ? window.location.protocol : 'http'; ...@@ -3,12 +3,17 @@ const protocol = EASY_ENV_IS_BROWSER ? window.location.protocol : 'http';
export default { export default {
apiHost: `http://localhost:7002/`, apiHost: `http://localhost:7002/`,
// apiHost: `http://192.168.28.199:7001/`, // apiHost: `http://192.168.28.199:7001/`,
// apiHost: 'https://quantum-blocks-bfe.liangkebang.net/', // apiHost: 'https://quantum-blocks-vcc3.liangkebang.net/',
h5Host: 'https://quantum-h5-bfe.liangkebang.net', h5Host: 'https://quantum-h5-vcc3.liangkebang.net',
qiniuHost: `https://appsync.lkbang.net`, qiniuHost: `https://appsync.lkbang.net`,
shenceUrl: `${protocol}//bn.xyqb.com/sa?project=default`, shenceUrl: `${protocol}//bn.xyqb.com/sa?project=default`,
opapiHost: `https://opapi-bfe.liangkebang.net`, opapiHost: `https://opapi-vcc3.liangkebang.net`,
qiniuUpHost: `${protocol}//up-z0.qiniup.com`, qiniuUpHost: `${protocol}//up-z0.qiniup.com`,
// kdspHost: 'https://kdsp-api-bfe.liangkebang.net', // kdspHost: 'https://kdsp-api-vcc3.liangkebang.net',
kdspHost: 'https://talos-bfe.liangkebang.net' kdspHost: 'https://talos-vcc3.liangkebang.net',
yxmTenantId: 560761,
appIdMap: {
560761: 'wxe16bf9293671506c',
560867: 'wxccb8435d68e8c7d6',
},
}; };
\ No newline at end of file
...@@ -7,7 +7,12 @@ const hostMap = { ...@@ -7,7 +7,12 @@ const hostMap = {
shenceUrl: `${protocol}//bn.xyqb.com/sa?project=production`, shenceUrl: `${protocol}//bn.xyqb.com/sa?project=production`,
opapiHost: `${protocol}//opapi.q-gp.com`, opapiHost: `${protocol}//opapi.q-gp.com`,
qiniuUpHost: `${protocol}//up-z0.qiniup.com`, qiniuUpHost: `${protocol}//up-z0.qiniup.com`,
kdspHost: `${protocol}//talos.q-gp.com` kdspHost: `${protocol}//talos.q-gp.com`,
yxmTenantId: 560761,
appIdMap: {
560761: 'wxb3e6270e1b1e0bc7',
560867: 'wxbd0bc68b270a1dab',
},
}; };
if (EASY_ENV_IS_BROWSER) { if (EASY_ENV_IS_BROWSER) {
......
...@@ -7,6 +7,7 @@ const hostMap = { ...@@ -7,6 +7,7 @@ const hostMap = {
qiniuHost: `${protocol}//appsync.lkbang.net`, qiniuHost: `${protocol}//appsync.lkbang.net`,
shenceUrl: `${protocol}//bn.xyqb.com/sa?project=default`, shenceUrl: `${protocol}//bn.xyqb.com/sa?project=default`,
qiniuUpHost: `${protocol}//up-z0.qiniup.com`, qiniuUpHost: `${protocol}//up-z0.qiniup.com`,
yxmTenantId: 560761
}; };
if (EASY_ENV_IS_BROWSER) { if (EASY_ENV_IS_BROWSER) {
......
import Vue from 'vue'; import Vue from 'vue';
import { sync } from 'vuex-router-sync'; import { sync } from 'vuex-router-sync';
export default class App { export default class App {
config: any; config: any;
constructor(config) { constructor(config) {
......
...@@ -12,6 +12,7 @@ import { getStyle } from '@service/utils.service'; ...@@ -12,6 +12,7 @@ import { getStyle } from '@service/utils.service';
export default class DynamicForm extends Vue { export default class DynamicForm extends Vue {
@Getter('pageInfo') pageInfo; @Getter('pageInfo') pageInfo;
@Getter('pageData') pageData; @Getter('pageData') pageData;
@State(state => state.tenant.cartAndShareBtn) cartAndShareBtn;
@Prop(Boolean) value; @Prop(Boolean) value;
showPopup: boolean = false; showPopup: boolean = false;
......
...@@ -14,7 +14,7 @@ ...@@ -14,7 +14,7 @@
<Upload v-model="formCustom.shareCoverImage" :show-input="false" /> <Upload v-model="formCustom.shareCoverImage" :show-input="false" />
<p class="basic-form__tip">可选,默认使用页面缩略图,建议图片比例1:1,图片格式jpg、png</p> <p class="basic-form__tip">可选,默认使用页面缩略图,建议图片比例1:1,图片格式jpg、png</p>
</FormItem> </FormItem>
<FormItem label="分享打开方式" prop="shareOpenMethod"> <FormItem label="分享打开方式" prop="shareOpenMethod" v-if="cartAndShareBtn">
<RadioGroup v-model="formCustom.shareOpenMethod"> <RadioGroup v-model="formCustom.shareOpenMethod">
<Radio :label="1" :disabled="!enableShare">小程序</Radio> <Radio :label="1" :disabled="!enableShare">小程序</Radio>
<Radio :label="2" :disabled="!enableShare">APP</Radio> <Radio :label="2" :disabled="!enableShare">APP</Radio>
......
...@@ -7,6 +7,7 @@ import { v4 as uuid } from 'uuid'; ...@@ -7,6 +7,7 @@ import { v4 as uuid } from 'uuid';
@Component({ name: 'DynamicComponent' }) @Component({ name: 'DynamicComponent' })
export default class DynamicComponent extends Vue { export default class DynamicComponent extends Vue {
@State(state => state.editor.gridLayout.colNum) colNum; @State(state => state.editor.gridLayout.colNum) colNum;
@State(state => state.tenant.financeTab) financeTab;
@Prop({ default: () => ([]), type: Array }) data; @Prop({ default: () => ([]), type: Array }) data;
@Prop(String) type; @Prop(String) type;
...@@ -14,6 +15,12 @@ export default class DynamicComponent extends Vue { ...@@ -14,6 +15,12 @@ export default class DynamicComponent extends Vue {
eleConfigMap: object = {}; eleConfigMap: object = {};
activeName: string = ''; activeName: string = '';
@Watch('financeTab', { immediate: true })
onFinanceTabChange(val) {
if (!val && this.eleConfigMap.fs) {
this.$delete(this.eleConfigMap, 'fs');
}
}
@Watch('data', { immediate: true }) @Watch('data', { immediate: true })
onDataChange(newVal) { onDataChange(newVal) {
if (this.type === 'business') { if (this.type === 'business') {
...@@ -23,6 +30,7 @@ export default class DynamicComponent extends Vue { ...@@ -23,6 +30,7 @@ export default class DynamicComponent extends Vue {
pre[cur.name] = { ...cur, children}; pre[cur.name] = { ...cur, children};
return pre; return pre;
}, {}); }, {});
this.onFinanceTabChange(this.financeTab);
} else { } else {
this.eleConfig = chunk(newVal, 2); this.eleConfig = chunk(newVal, 2);
} }
......
...@@ -27,6 +27,7 @@ const CONFIG_MAP = { ...@@ -27,6 +27,7 @@ const CONFIG_MAP = {
['自定义']: DEFAULT_CONFIG ['自定义']: DEFAULT_CONFIG
}; };
export default { export default {
name: 'BackTopPicker',
mixins: [FormList], mixins: [FormList],
data() { data() {
return { return {
......
...@@ -7,10 +7,15 @@ const couponTypeList: object[] = [ ...@@ -7,10 +7,15 @@ const couponTypeList: object[] = [
id: 2, id: 2,
name: '运费券', name: '运费券',
}, },
{
id: 3,
name: '现金券',
},
{ {
id: 21, id: 21,
name: '享花券', name: '享花券',
}, },
]; ];
const receiverTypeList: object[] = [ const receiverTypeList: object[] = [
{ {
......
...@@ -30,13 +30,17 @@ export default class CouponTableModal extends Vue { ...@@ -30,13 +30,17 @@ export default class CouponTableModal extends Vue {
// receiverType 领取方式 1:主动领取 2:自动发放 3:不限 // receiverType 领取方式 1:主动领取 2:自动发放 3:不限
const res = await operationApi.couponList({ ...data }); const res = await operationApi.couponList({ ...data });
const couponInfoList = res?.couponInfoList?.map(item => { const couponInfoList = res?.couponInfoList?.map(item => {
if (item.receiverStartTime && item.receiverEndTime) {
item.receiverTime = `${item.receiverStartTime.slice(0, 10)}--${item.receiverEndTime.slice(0, 10)}`; item.receiverTime = `${item.receiverStartTime.slice(0, 10)}--${item.receiverEndTime.slice(0, 10)}`;
}
if (item.useTimeStart && item.useTimeEnd) {
item.useTime = item.useTimeStart item.useTime = item.useTimeStart
? `${item.useTimeStart}-${item.useTimeEnd}` ? `${item.useTimeStart}-${item.useTimeEnd}`
: item.validHours : item.validHours
? `自领取后有效${item.validHours}小时` ? `自领取后有效${item.validHours}小时`
: `自领取${item.receiverDaysValid}天后生效,有效天数${item.validDays}天`; : `自领取${item.receiverDaysValid}天后生效,有效天数${item.validDays}天`;
// item.useTime = item.useTimeStart ? `${item.useTimeStart}-${item.useTimeEnd}` : `自领取${item.receiverDaysValid}天后生效,有效天数${item.validDays}天`; // item.useTime = item.useTimeStart ? `${item.useTimeStart}-${item.useTimeEnd}` : `自领取${item.receiverDaysValid}天后生效,有效天数${item.validDays}天`;
}
const selections = this.templates.length ? this.templates : this.coupon; const selections = this.templates.length ? this.templates : this.coupon;
console.log('query', selections, this.templates, this.coupon); console.log('query', selections, this.templates, this.coupon);
if (selections.some(v => v === item.id)) { if (selections.some(v => v === item.id)) {
......
...@@ -5,7 +5,7 @@ import DynamicPageForm from '@editor/component/DynamicPageForm/index.vue'; ...@@ -5,7 +5,7 @@ import DynamicPageForm from '@editor/component/DynamicPageForm/index.vue';
import DynamicComponentSort from '@editor/component/DynamicComponentSort/index.vue'; import DynamicComponentSort from '@editor/component/DynamicComponentSort/index.vue';
// import EventBus from '@service/eventBus.service'; // import EventBus from '@service/eventBus.service';
@Component({ components: { DynamicPageForm, DynamicForm, DynamicComponentSort }, name: 'RecordModal' }) @Component({ components: { DynamicPageForm, DynamicForm, DynamicComponentSort }, name: 'DynamicFormTabs' })
export default class DynamicFormTabs extends Vue { export default class DynamicFormTabs extends Vue {
@Getter('curRightTabName') curRightTabName!: string | null; @Getter('curRightTabName') curRightTabName!: string | null;
......
...@@ -10,11 +10,12 @@ import Number from '../DynamicForm/component/Number/index.vue'; ...@@ -10,11 +10,12 @@ import Number from '../DynamicForm/component/Number/index.vue';
import FormList from '../DynamicForm/component/FormList/index.vue'; import FormList from '../DynamicForm/component/FormList/index.vue';
import BackTopPicker from '../DynamicForm/component/BackTopPicker/index.vue'; import BackTopPicker from '../DynamicForm/component/BackTopPicker/index.vue';
import SwitchBtn from '../DynamicForm/component/SwitchBtn/index.vue'; import SwitchBtn from '../DynamicForm/component/SwitchBtn/index.vue';
import { SHOP_CART_CONFIG } from '@service/staticData.service'; import { SHOP_CART_CONFIG, DEFAULT_CONFIG } from '@service/staticData.service';
@Component({ components: { Upload, ColorSelector, BaseSelect, Textarea, Number, FormList, BackTopPicker, SwitchBtn }, name: 'DynamicPageForm' }) @Component({ components: { Upload, ColorSelector, BaseSelect, Textarea, Number, FormList, BackTopPicker, SwitchBtn }, name: 'DynamicPageForm' })
export default class DynamicPageForm extends Mixins(ContextMenuMixin) { export default class DynamicPageForm extends Mixins(ContextMenuMixin) {
@Getter('pageData') pageData; @Getter('pageData') pageData;
@State(state => state.tenant.cartAndShareBtn) cartAndShareBtn;
title: string = '页面'; title: string = '页面';
commonStyleForm: object = {}; commonStyleForm: object = {};
...@@ -148,12 +149,20 @@ export default class DynamicPageForm extends Mixins(ContextMenuMixin) { ...@@ -148,12 +149,20 @@ export default class DynamicPageForm extends Mixins(ContextMenuMixin) {
type: 'checkbox' type: 'checkbox'
} }
], ],
formDefault: SHOP_CART_CONFIG formDefault: {}
} }
]; ];
get propsSchema() { get propsSchema() {
return [...this.titleSchema, ...this.bottomSchema, ...this.floatSchema]; return [...this.titleSchema, ...this.bottomSchema, ...this.floatSchema];
} }
@Watch('cartAndShareBtn', { immediate: true })
onAuthStateChange(val) {
const options = val ? ['购物车', '分享', '自定义'] : ['自定义'];
this.$set(this.floatSchema[1].formControl[0], 'options', options);
this.$set(this.floatSchema[1], 'formDefault', val ? SHOP_CART_CONFIG : DEFAULT_CONFIG);
}
@Watch('pageData', { immediate: true, deep: true }) @Watch('pageData', { immediate: true, deep: true })
onElementChange() { onElementChange() {
this.commonStyleSchame.forEach(schame => { this.commonStyleSchame.forEach(schame => {
......
...@@ -3,7 +3,7 @@ import DynamicComponent from '@editor/component/DynamicComponent/index.vue'; ...@@ -3,7 +3,7 @@ import DynamicComponent from '@editor/component/DynamicComponent/index.vue';
import { basicComponents, businessComponents } from '@lib/config'; import { basicComponents, businessComponents } from '@lib/config';
import { State } from 'vuex-class'; import { State } from 'vuex-class';
@Component({ components: { DynamicComponent }, name: 'RecordModal' }) @Component({ components: { DynamicComponent }, name: 'DynamicForm' })
export default class DynamicForm extends Vue { export default class DynamicForm extends Vue {
@State(state => state.editor.templateList) templateList!: any[]; @State(state => state.editor.templateList) templateList!: any[];
......
...@@ -88,6 +88,11 @@ export default class DashBoard extends Mixins(ContextMenuMixin, GoodsTabsMixin, ...@@ -88,6 +88,11 @@ export default class DashBoard extends Mixins(ContextMenuMixin, GoodsTabsMixin,
pageData = this.handleComAchorScrollEnable(); pageData = this.handleComAchorScrollEnable();
pageData = this.handleGoodsTabs(); pageData = this.handleGoodsTabs();
const { pageName, pageDescribe, pageKeywords, coverImage, isPublish, isTemplate, shareCoverImage, shareOpenMethod, diversion } = pageConfig; const { pageName, pageDescribe, pageKeywords, coverImage, isPublish, isTemplate, shareCoverImage, shareOpenMethod, diversion } = pageConfig;
// !diversion shareCoverImage shareOpenMethod没有作为单独的sql字段存储下来,只是单纯的存储到的redis中
// 目前对此打了补丁,存放到page的props中
pageData.props.diversion = diversion;
pageData.props.shareCoverImage = shareCoverImage;
pageData.props.shareOpenMethod = shareOpenMethod;
const pageInfo = { diversion, page: JSON.stringify(pageData), author: user?.account, isPublish, pageName, pageDescribe, pageKeywords, coverImage, isTemplate, shareCoverImage, shareOpenMethod } as pageInfo; const pageInfo = { diversion, page: JSON.stringify(pageData), author: user?.account, isPublish, pageName, pageDescribe, pageKeywords, coverImage, isTemplate, shareCoverImage, shareOpenMethod } as pageInfo;
if (this.uuid) { pageInfo.uuid = this.uuid; } if (this.uuid) { pageInfo.uuid = this.uuid; }
await this.savePageData({ pageInfo, pageData: this.pageData }); await this.savePageData({ pageInfo, pageData: this.pageData });
...@@ -96,7 +101,7 @@ export default class DashBoard extends Mixins(ContextMenuMixin, GoodsTabsMixin, ...@@ -96,7 +101,7 @@ export default class DashBoard extends Mixins(ContextMenuMixin, GoodsTabsMixin,
// 清除新增数据时的缓存 // 清除新增数据时的缓存
if (!isCreate) { this.removeDefaultCache(); } if (!isCreate) { this.removeDefaultCache(); }
if (type === 'preview') { if (type === 'preview') {
window.open(`${config.h5Host}/activity/${this.uuid}`); window.open(`${config.h5Host}/activity/${this.uuid}?tenantId=${this.pageInfo.tenantId}`);
} else { } else {
this.$Notice.success({ title: '保存成功!' }); this.$Notice.success({ title: '保存成功!' });
} }
......
...@@ -50,7 +50,7 @@ ...@@ -50,7 +50,7 @@
background: #fff; background: #fff;
box-shadow: 0 2px 3px 0 hsla(0,0%,39.2%,.06); box-shadow: 0 2px 3px 0 hsla(0,0%,39.2%,.06);
font-size: 16px; font-size: 16px;
z-index: 901; z-index: 10;
.ivu-col { .ivu-col {
text-align: center; text-align: center;
button { button {
......
...@@ -5,7 +5,6 @@ ...@@ -5,7 +5,6 @@
:request="query" :request="query"
@newBtnClick="addPage" @newBtnClick="addPage"
> >
<Button type="default" class="btnStyle" @click="refreshData()">更新缓存</Button>
</QGTable> </QGTable>
</template> </template>
<script> <script>
...@@ -59,7 +58,7 @@ export default { ...@@ -59,7 +58,7 @@ export default {
[h( [h(
'img',{ 'img',{
attrs: { attrs: {
src: params.row.coverImage, src: params.row.coverImage + '?imageMogr2/format/jpg/thumbnail/!10p',
}, },
style: { style: {
width: '37.5px', width: '37.5px',
...@@ -76,7 +75,7 @@ export default { ...@@ -76,7 +75,7 @@ export default {
title: '链接', title: '链接',
hideSearch: true, hideSearch: true,
render: (h, params) => { render: (h, params) => {
return h('span', `${config.h5Host}/activity/${params.row.uuid}?vccToken={token}`) return h('span', `${config.h5Host}/activity/${params.row.uuid}?tenantId=${params.row.tenantId}&vccToken={token}`)
} }
}, },
{ {
...@@ -117,7 +116,7 @@ export default { ...@@ -117,7 +116,7 @@ export default {
}, },
on: { on: {
click: () => { click: () => {
window.open(`${config.h5Host}/activity/${params.row.uuid}`); window.open(`${config.h5Host}/activity/${params.row.uuid}?tenantId=${params.row.tenantId}`);
}, },
}, },
}, },
......
...@@ -3,6 +3,7 @@ import Vue from 'vue'; ...@@ -3,6 +3,7 @@ import Vue from 'vue';
import Vuex from 'vuex'; import Vuex from 'vuex';
import RootState from './state'; import RootState from './state';
import Editor from './modules/editor'; import Editor from './modules/editor';
import Tenant from './modules/tenant';
Vue.use(Vuex); Vue.use(Vuex);
...@@ -13,7 +14,8 @@ export default function createStore(initState: any = {}) { ...@@ -13,7 +14,8 @@ export default function createStore(initState: any = {}) {
return new Vuex.Store<RootState>({ return new Vuex.Store<RootState>({
state, state,
modules: { modules: {
editor: new Editor(editor) tenant: new Tenant(),
editor: new Editor(editor),
} }
}); });
} }
\ No newline at end of file
...@@ -57,6 +57,7 @@ export interface PageInfo { ...@@ -57,6 +57,7 @@ export interface PageInfo {
pageDescribe?: string; pageDescribe?: string;
pageKeywords?: string; pageKeywords?: string;
uuid?: string; uuid?: string;
tenantId?: number;
diversion?: string; diversion?: string;
} }
......
import { getMenuData } from '@api/user.api';
import { Module, GetterTree, ActionTree, MutationTree } from 'vuex';
import {
FETCH_AUTH_INFO
} from './type';
import RootState from '../../state';
import EditorAuthInfo from './state';
import Vue from 'vue';
export default class TenantModule implements Module<EditorAuthInfo, RootState> {
state: EditorAuthInfo;
getters: GetterTree<EditorAuthInfo, RootState> = {
authData(state: EditorAuthInfo) {
return state;
}
};
actions: ActionTree<EditorAuthInfo, RootState> = {
async fetchTenantAuthData({ commit }) {
const res: Record<any, any> = await getMenuData();
const authMap: EditorAuthInfo = {};
res.forEach(item => {
let { uri, code } = item.node;
uri = uri ? uri : '';
code = code ? code : '';
if (uri.indexOf('/template') > -1) {
authMap.tmplList = true;
}
if (uri === '/my') {
authMap.draftList = true;
}
if (uri === '/list') {
authMap.workist = true;
}
if (code === 'cartAndShareBtn') {
authMap.cartAndShareBtn = true;
}
if (code === 'financeTab') {
authMap.financeTab = true;
}
});
commit(FETCH_AUTH_INFO, authMap);
}
};
mutations: MutationTree<EditorAuthInfo> = {
[FETCH_AUTH_INFO](state, data) {
console.log(this.state.editor.pageInfo.uuid);
if (!data.cartAndShareBtn && !this.state.editor.pageInfo.uuid) {
Vue.set(this.state.editor.pageInfo.page.props, 'btAttachVal', []);
}
Vue.set(this.state, 'tenant', data);
}
};
constructor() {
this.state = {} as EditorAuthInfo;
}
}
\ No newline at end of file
export default interface EditorAuthInfo {
financeTab?: boolean;
cartAndShareBtn?: boolean;
workist?: boolean;
draftList?: boolean;
tmplList?: boolean;
}
\ No newline at end of file
'use strict';
export const FETCH_AUTH_INFO = 'FETCH_AUTH_INFO';
...@@ -96,7 +96,8 @@ instance.interceptors.request.use( ...@@ -96,7 +96,8 @@ instance.interceptors.request.use(
config.headers['X-Auth-Token'] = token; config.headers['X-Auth-Token'] = token;
if (config.accessToken) { config.headers['Access-Token'] = token; } if (config.accessToken) { config.headers['Access-Token'] = token; }
} }
const tenantId = localStorage.get('tenantId') || basicConfig.yxmTenantId || '';
config.headers['qg-tenant-id'] = tenantId || '';
return config; return config;
}, },
error => { error => {
......
...@@ -6,7 +6,7 @@ ...@@ -6,7 +6,7 @@
<meta name="description"> <meta name="description">
<meta http-equiv="content-type" content="text/html;charset=utf-8"> <meta http-equiv="content-type" content="text/html;charset=utf-8">
<meta name="viewport" content="initial-scale=1, maximum-scale=1, user-scalable=no, minimal-ui"> <meta name="viewport" content="initial-scale=1, maximum-scale=1, user-scalable=no, minimal-ui">
<link rel="shortcut icon" href="/favicon.ico" type="image/x-icon" /> <link rel="shortcut icon" href="data:image/png;base64" type="image/x-icon" />
<link href="https://activitystatic.lkbang.net/iview/2.9.0/styles/iview.css" rel="stylesheet"> <link href="https://activitystatic.lkbang.net/iview/2.9.0/styles/iview.css" rel="stylesheet">
<link rel="stylesheet" type="text/css" href="https://activitystatic.lkbang.net/swiper/4.5.1/css/swiper.min.css"> <link rel="stylesheet" type="text/css" href="https://activitystatic.lkbang.net/swiper/4.5.1/css/swiper.min.css">
<style> <style>
......
module.exports = {
extends: ['@commitlint/config-angular'],
};
import { EggAppConfig } from 'egg'; import { EggAppConfig } from 'egg';
import * as fs from 'fs'; import * as fs from 'fs';
import * as path from 'path'; import * as path from 'path';
const { mysql, redis, api, qiniu } = require(path.resolve(__dirname, './apollo.json'));
export default (appInfo: EggAppConfig) => { export default (appInfo: EggAppConfig) => {
const config: any = {}; const config: any = {};
config.siteFile = { config.siteFile = {
'/favicon.ico': fs.readFileSync(path.join(appInfo.baseDir, 'app/web/asset/images/favicon.ico'))
}; };
config.view = { config.view = {
...@@ -47,5 +47,18 @@ export default (appInfo: EggAppConfig) => { ...@@ -47,5 +47,18 @@ export default (appInfo: EggAppConfig) => {
} }
}; };
config.sequelize = {
dialect: 'mysql',
...mysql.low_code
};
config.redis = {
default: {
keyPrefix: appInfo.name + ':',
},
client: redis
};
config.apollo = { ...api, ...qiniu };
return config; return config;
}; };
...@@ -22,27 +22,6 @@ export default (appInfo: EggAppConfig) => { ...@@ -22,27 +22,6 @@ export default (appInfo: EggAppConfig) => {
injectCss: false injectCss: false
}; };
exports.sequelize = {
dialect: 'mysql',
username: 'qa',
password: 'qatest',
host: '172.17.5.46',
port: 30198,
database: 'low_code',
};
exports.redis = {
default: {
keyPrefix: appInfo.name + ':',
},
client: {
port: 31226, // Redis port
host: '172.17.5.14', // Redis host
password: '',
db: 0
}
};
exports.webpack = { exports.webpack = {
webpackConfigList: getWebpackConfig(), webpackConfigList: getWebpackConfig(),
browser: 'http://localhost:7002/editor/list' browser: 'http://localhost:7002/editor/list'
......
...@@ -2,9 +2,11 @@ ...@@ -2,9 +2,11 @@
* production * production
* *
* prod + default(override) * prod + default(override)
* 目前线上apollo还未启用
*/ */
import { Application, EggAppConfig } from 'egg'; import { Application, EggAppConfig } from 'egg';
import * as path from 'path';
export default (appInfo: EggAppConfig) => { export default (appInfo: EggAppConfig) => {
const exports: any = {}; const exports: any = {};
...@@ -13,27 +15,5 @@ export default (appInfo: EggAppConfig) => { ...@@ -13,27 +15,5 @@ export default (appInfo: EggAppConfig) => {
dir: '/home/quant_group/logs', dir: '/home/quant_group/logs',
}; };
exports.sequelize = {
dialect: 'mysql',
username: 'low_code_w',
password: 'B2pRHuGMLBNybuKp',
host: 'low-code-db.quantgroups.com',
port: 3306,
database: 'low_code',
};
exports.redis = {
default: {
keyPrefix: appInfo.name + ':',
},
client: {
port: 6379, // Redis port
host: 'front-redis.quantgroups.com', // Redis host
password: 'ln4^ESq80j4nrTMZ',
db: 0
}
};
return exports; return exports;
}; };
...@@ -2,23 +2,12 @@ ...@@ -2,23 +2,12 @@
const path = require('path'); const path = require('path');
import { Application, EggAppConfig } from 'egg'; import { Application, EggAppConfig } from 'egg';
const { mysql, redis, api, qiniu } = require(path.resolve(__dirname, './apollo.json'));
export default (appInfo: EggAppConfig) => { export default (appInfo: EggAppConfig) => {
const exports: any = {}; const exports: any = {};
exports.logger = { exports.logger = {
dir: '/home/quant_group/logs', dir: '/home/quant_group/logs',
}; };
exports.sequelize = { return exports;
dialect: 'mysql',
...mysql.low_code
};
exports.redis = {
default: {
keyPrefix: appInfo.name + ':',
},
client: redis
};
return {...exports, apollo: { ...api, ...qiniu }};
}; };
This source diff could not be displayed because it is too large. You can view the blob instead.
...@@ -3,14 +3,16 @@ ...@@ -3,14 +3,16 @@
"version": "1.0.0", "version": "1.0.0",
"description": "低代码平台", "description": "低代码平台",
"scripts": { "scripts": {
"start": "cross-env NODE_ENV=production APOLLO_CLUSTER=RC egg-scripts start --port 9050 --workers 1", "start": "cross-env NODE_ENV=production APOLLO_CLUSTER=3C egg-scripts start --port 9050 --workers 1",
"start:pre": "cross-env NODE_ENV=production APOLLO_CLUSTER=3PRE egg-scripts start --port 9050 --workers 1",
"test": "cross-env NODE_ENV=production EGG_SERVER_ENV=sit DEBUG=apollo APOLLO_CLUSTER=k8s NAMESPACE=qa2 egg-scripts start --port 80 --workers 1", "test": "cross-env NODE_ENV=production EGG_SERVER_ENV=sit DEBUG=apollo APOLLO_CLUSTER=k8s NAMESPACE=qa2 egg-scripts start --port 80 --workers 1",
"stop": "egg-scripts stop", "stop": "egg-scripts stop",
"backend": "nohup egg-scripts start --port 7001 --workers 4", "backend": "nohup egg-scripts start --port 7001 --workers 4",
"dev": "egg-bin dev -r egg-ts-helper/register --port 7002", "dev": "egg-bin dev -r egg-ts-helper/register --port 7002",
"debug": "egg-bin debug -r egg-ts-helper/register", "debug": "egg-bin debug -r egg-ts-helper/register",
"apollo": "node bin/apollo.js", "apollo": "node bin/apollo.js",
"build": "easy build --devtool", "build": "cross-env NODE_ENV=production APOLLO_CLUSTER=3C npm run apollo && cross-env COS_ENV=production easy build --devtool",
"build:pre": "cross-env NODE_ENV=production APOLLO_CLUSTER=3PRE npm run apollo && cross-env COS_ENV=production easy build --devtool",
"tsc": "ets && tsc -p tsconfig.json", "tsc": "ets && tsc -p tsconfig.json",
"clean": "ets clean", "clean": "ets clean",
"kill": "easy kill", "kill": "easy kill",
...@@ -27,7 +29,7 @@ ...@@ -27,7 +29,7 @@
"@hubcarl/json-typescript-mapper": "^2.0.0", "@hubcarl/json-typescript-mapper": "^2.0.0",
"@qg/apollo-nodejs": "^2.1.2", "@qg/apollo-nodejs": "^2.1.2",
"@qg/cherry-ui": "2.23.10", "@qg/cherry-ui": "2.23.10",
"@qg/citrus-ui": "0.3.16-bata2", "@qg/citrus-ui": "0.3.22",
"@riophae/vue-treeselect": "^0.4.0", "@riophae/vue-treeselect": "^0.4.0",
"@types/lodash": "^4.14.117", "@types/lodash": "^4.14.117",
"@types/node": "^10.12.0", "@types/node": "^10.12.0",
...@@ -79,7 +81,12 @@ ...@@ -79,7 +81,12 @@
"vuex-router-sync": "^5.0.0", "vuex-router-sync": "^5.0.0",
"webpack-sentry-plugin": "^2.0.3" "webpack-sentry-plugin": "^2.0.3"
}, },
"devDependencies": {}, "devDependencies": {
"husky": "^4.2.5",
"lint-staged": "^10.2.11",
"@commitlint/cli": "^13.2.1",
"@commitlint/config-angular": "^13.2.0"
},
"egg": { "egg": {
"typescript": true "typescript": true
}, },
...@@ -100,5 +107,17 @@ ...@@ -100,5 +107,17 @@
"commitizen": { "commitizen": {
"path": "./node_modules/cz-conventional-changelog" "path": "./node_modules/cz-conventional-changelog"
} }
},
"lint-staged": {
"src/**/*.{js,vue}": [
"tslint --fix --project . -c tslint.json 'app/web/**/*{.ts}'",
"git add"
]
},
"husky": {
"hooks": {
"pre-commit": "lint-staged",
"commit-msg": "commitlint -e $HUSKY_GIT_PARAMS"
}
} }
} }
#!/bin/sh
source /etc/profile
NODE_ENV=production APOLLO_CLUSTER=3PRE pm2 start bin/server.js --node-args=\"--harmony\" -n quantum-blocks
#!/bin/sh
source /etc/profile
pm2 start bin/server.js --node-args=\"--harmony\" -n quantum-blocks
#!/bin/sh
source /etc/profile
pm2 stop quantum-blocks
\ No newline at end of file
// This file is created by egg-ts-helper@1.26.0 // This file is created by egg-ts-helper@1.25.9
// Do not modify this file!!!!!!!!! // Do not modify this file!!!!!!!!!
import 'egg'; import 'egg';
......
// This file is created by egg-ts-helper@1.26.0 // This file is created by egg-ts-helper@1.25.9
// Do not modify this file!!!!!!!!! // Do not modify this file!!!!!!!!!
import 'egg'; import 'egg';
......
// This file is created by egg-ts-helper@1.26.0 // This file is created by egg-ts-helper@1.25.9
// Do not modify this file!!!!!!!!! // Do not modify this file!!!!!!!!!
import 'egg'; import 'egg';
......
// This file is created by egg-ts-helper@1.26.0 // This file is created by egg-ts-helper@1.25.9
// Do not modify this file!!!!!!!!! // Do not modify this file!!!!!!!!!
import 'egg'; import 'egg';
......
// This file is created by egg-ts-helper@1.26.0 // This file is created by egg-ts-helper@1.25.9
// Do not modify this file!!!!!!!!! // Do not modify this file!!!!!!!!!
import 'egg'; import 'egg';
import ExportPageInfo from '../../../app/model/pageInfo'; import ExportPageInfo from '../../../app/model/pageInfo';
import ExportTenantAuth from '../../../app/model/tenantAuth';
declare module 'egg' { declare module 'egg' {
interface IModel { interface IModel {
PageInfo: ReturnType<typeof ExportPageInfo>; PageInfo: ReturnType<typeof ExportPageInfo>;
TenantAuth: ReturnType<typeof ExportTenantAuth>;
} }
} }
// This file is created by egg-ts-helper@1.26.0 // This file is created by egg-ts-helper@1.25.9
// Do not modify this file!!!!!!!!! // Do not modify this file!!!!!!!!!
import 'egg'; import 'egg';
......
// This file is created by egg-ts-helper@1.26.0 // This file is created by egg-ts-helper@1.25.9
// Do not modify this file!!!!!!!!! // Do not modify this file!!!!!!!!!
import 'egg'; import 'egg';
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment