Commit 506b792a authored by 郭志伟's avatar 郭志伟

Merge branch 'feat/v1.3-local' into 'feat/v1.3'

Feat/v1.3 local

See merge request !37
parents 86faf3e8 3ef4b77c
......@@ -12,10 +12,10 @@ export default class ActivityController extends Controller {
if (process.env.NODE_ENV === 'production' && process.env.EGG_SERVER_ENV === 'sit') {
apollo = ctx.app.config.apollo || {};
}
body = await ctx.renderView('activity.js', { url: ctx.url, apollo });
body = await ctx.renderToHtml('activity.js', { url: ctx.url, apollo });
await ctx.service.redis.set(redisKey, body);
}
ctx.body = body;
// ctx.body = await ctx.renderView('activity.js', { url: ctx.url });
// ctx.body = await ctx.renderToHtml('activity.js', { url: ctx.url });
}
}
\ No newline at end of file
......@@ -4,5 +4,8 @@ import config from '../config';
export default {
getPageById(params) {
return http.get(`${config.apiHost}/editor/get/${params.pageId}`);
},
getShopCartCount() {
return http.get(`${config.kdspApi}/api/kdsp/shop-cart/count`);
}
};
\ No newline at end of file
......@@ -7,6 +7,7 @@ import { release } from '@/.sentryclirc';
import '@/service/qg.service';
import SaDirective from '@qg/citrus-ui/src/helper/directives/saTrack.directive.js';
import config from '@qg/citrus-ui/src/config/index.js';
import { EventBus } from '@qg/citrus-ui/src/helper/service/eventBus';
import { getParameterByName } from '../../../service/utils.service';
import lazyload from '@qg/cherry-ui/src/lazyload/index';
......@@ -39,6 +40,16 @@ if (EASY_ENV_IS_BROWSER) {
Vue.use(lazyload);
const saDirective = new SaDirective();
Vue.directive('track', saDirective.directive);
window.xyqbNativeEvent = function(res) {
const json = typeof res === 'string' ? JSON.parse(res) : res;
console.log('xyqbNativeEvent toggle');
if (json.event === 'loginAndLogoutNotification') {
EventBus.$emit('NATIVE_EVENT_LOGIN', json);
}
if (json.event === 'getTokenSuccess') {
EventBus.$emit('NATIVE_EVENT_GET_TOKEN', json);
}
};
}
@Component({
name: 'Layout'
......
......@@ -3,6 +3,7 @@ const protocol = EASY_ENV_IS_BROWSER ? window.location.protocol : 'https';
const hostMap = {
apiHost: `${protocol}//quantum-blocks-vcc2.liangkebang.net`,
kdspApi: `${protocol}//talos-vcc2.liangkebang.net`,
shenceUrl: `${protocol}//bn.xyqb.com/sa?project=default`,
test: true
};
......
......@@ -2,6 +2,7 @@ const protocol = EASY_ENV_IS_BROWSER ? window.location.protocol : 'https';
export default {
apiHost: `https://quantum-blocks.q-gp.com`,
kdspApi: `${protocol}//talos.xyqb.com`,
shenceUrl: `${protocol}//bn.xyqb.com/sa?project=production`,
// opapiHost: `${protocol}//opapi.q-gp.com`,
test: false
......
......@@ -3,6 +3,7 @@ const protocol = EASY_ENV_IS_BROWSER ? window.location.protocol : 'https';
const hostMap = {
apiHost: `${protocol}//quantum-blocks-vcc2.liangkebang.net`,
kdspApi: `${protocol}//talos-vcc2.liangkebang.net`,
shenceUrl: `${protocol}//bn.xyqb.com/sa?project=default`,
test: true
};
......
......@@ -3,5 +3,6 @@ declare var EASY_ENV_IS_BROWSER: boolean;
type PlainObject<T = any> = { [key: string]: T };
interface Window {
__INITIAL_STATE__: string | any;
xyqbNativeEvent: any;
}
declare var apollo: any;
<template>
<div>
<cr-back-top :show-back-top="showBackTop && pageData.props.showBackTop" :list="backTopList" @click="handleBackTopClick" />
<cr-back-top :show-back-top="showBackTop && pageData.props.showBackTop" :list="backTopList" @click="handleBackTopClick" ref="crBackTop" />
<cr-popover
class="wxmp-tip"
:value="showMpTip"
......@@ -17,7 +17,10 @@
<script>
import Bridge from '@qg/js-bridge';
import { mapGetters } from 'vuex';
import { isApp, isWxMp } from '@/service/utils.service';
import { isApp, isWxMp, debounce } from '@/service/utils.service';
import localStorage from '@/service/localStorage.service';
import { registeredEvents } from '@/service/sa.service';
import api from '@/api/editor.api';
export default {
name: 'BackTop',
props: {
......@@ -28,7 +31,9 @@ export default {
...mapGetters(['pageInfo']),
backTopList() {
const btAttachVal = this.pageData && this.pageData.props.btAttachVal ? this.pageData.props.btAttachVal : [];
if (this.cartIndex !== null && btAttachVal.length) {
btAttachVal[this.cartIndex - 1].info = this.cartCount;
}
return isApp ? btAttachVal : isWxMp ? btAttachVal.filter(item => item.persets !== '购物车') : [];
}
},
......@@ -37,7 +42,10 @@ export default {
showMpTip: false,
tipTimer: null,
jsBridge: null,
wx: null
wx: null,
cartIndex: null,
cartCount: 0,
getCartCountDebounce: debounce(this.getCartCount, 2000)
};
},
created() {
......@@ -46,8 +54,19 @@ export default {
this.wx = require('weixin-js-sdk');
}
},
watch: {
backTopList(val) {
this.cartIndex = (val || []).findIndex(item => item.persets === '购物车') + 1;
this.getCartCountDebounce();
}
},
methods: {
handleBackTopClick(e) {
registeredEvents('PD_WUXIEC_H5ActivityPageSuspendedBtnClick', {
activity_id: this.pageInfo.uuid,
jump_url: e.url,
navigation_name: e.name,
});
if (e && e.persets === '分享') {
if (this.tipTimer) {
clearTimeout(this.tipTimer);
......@@ -88,6 +107,15 @@ export default {
this.showMpTip = false;
}, 10000);
},
async getCartCount() {
if (localStorage.get('vccToken') && this.cartIndex && isApp) {
const [res] = await api.getShopCartCount();
this.cartCount = res.count;
this.$nextTick(() => {
this.$refs.crBackTop.$forceUpdate();
});
}
}
},
}
</script>
......
<template>
<cr-empty
class="empty-state"
image="error"
description="你访问的页面不存在"
/>
</template>
<script>
export default {
name: 'EmptyState',
mounted() {
const loadingEle = document.querySelector('.mainload');
if (!loadingEle) { return; }
loadingEle.style.display = 'none';
}
}
</script>
<style lang="less" scoped>
.empty-state {
padding-top: 100px;
}
</style>
\ No newline at end of file
......@@ -12,6 +12,7 @@ export default class FreedomContainer extends Mixins(TransformStyleMixin, SaMixi
@Prop({type: Object, default: () => ({ child: [] })}) childItem;
@Prop({type: Object, default: () => ({})}) saInfo;
@Prop(String) link;
@Prop(String) backgroundImage;
mounted() {
......@@ -24,4 +25,5 @@ export default class FreedomContainer extends Mixins(TransformStyleMixin, SaMixi
// });
// }
}
}
\ No newline at end of file
<template>
<div class="freedom" v-track>
<div class="freedom" v-track="{ link }">
<div class="freedom-body">
<component :class="['freedom-body-item', { 'Fb-item_selected': curChildIndex === index }]" v-for="(item, index) in childItem.child" :style="transformStyle(item.commonStyle, 'container')" :is="item.name" :key="index" :sa-info="getSaInfo(item)" v-bind="item.props"></component>
</div>
......
......@@ -26,6 +26,11 @@
left: 0;
right: auto;
}
.vue-grid-item.no-transforms {
transform: none !important;
z-index: 3 !important;
overflow: visible !important;
}
.vue-grid-item.cssTransforms.render-rtl {
left: auto;
......@@ -133,6 +138,9 @@
required: false,
default: null
},
noTransforms: {
type: Boolean
},
/*useCssTransforms: {
type: Boolean,
required: true
......@@ -412,7 +420,8 @@
'cssTransforms' : this.useCssTransforms,
'render-rtl' : this.renderRtl,
'disable-userselect': this.isDragging,
'no-touch': this.isAndroid && this.draggableOrResizableAndNotStatic
'no-touch': this.isAndroid && this.draggableOrResizableAndNotStatic,
'no-transforms': this.noTransforms
}
},
resizableAndNotStatic(){
......
......@@ -2,6 +2,7 @@ import { Vue, Component, Watch, Provide, Mixins } from 'vue-property-decorator';
import { Getter, State, Mutation } from 'vuex-class';
import FreedomContainer from '../../component/FreedomContainer/index.vue';
import BackTop from '../../component/BackTop/index.vue';
import EmptyState from '../../component/EmptyState/index.vue';
import PageBottomTip from '../../component/PageBottomTip/index.vue';
import GridLayout from '../../component/VueGridLayout/GridLayout.vue';
import GridItem from '../../component/VueGridLayout/GridItem.vue';
......@@ -9,12 +10,17 @@ import TransformStyleMixin from '@/page/mixins/transformStyle.mixin';
import SaMixin from '@/page/mixins/sa.mixin';
import { getStyle, debounce, isApp, isWxMp } from '@/service/utils.service';
import { setAppTitleColor } from '@/service/color.service';
@Component({ components: { FreedomContainer, GridLayout, GridItem, PageBottomTip, BackTop }, name: 'Activity'})
import { EventBus } from '@qg/citrus-ui/src/helper/service/eventBus';
import localStorage from '@/service/localStorage.service';
@Component({ components: { FreedomContainer, GridLayout, GridItem, PageBottomTip, BackTop, EmptyState }, name: 'Activity'})
export default class Activity extends Mixins(TransformStyleMixin, SaMixin) {
@Getter('pageData') pageData;
@State(state => state.activity.pageInfo.pageName) pageName;
@State(state => state.activity.noPageData) noPageData;
@State(state => state.activity.pageInfo.appLoginState) appLoginState;
@State(state => state.activity.gridLayout.rowHeight) rowHeight;
@Mutation('SET_PAGE_ELEMENTS') setPageElement;
@Mutation('UPDATE_APP_LOGIN_STATE') updateAppLoginState;
@Provide() editor = this;
isEditor: boolean = false;
......@@ -41,7 +47,7 @@ export default class Activity extends Mixins(TransformStyleMixin, SaMixin) {
@Watch('pageData', { deep: true })
onPageDataChange(val) {
const lastGridItem = val.elements[val.elements.length - 1];
const lastGridItemPoint = lastGridItem.point;
const lastGridItemPoint = lastGridItem?.point;
if (lastGridItemPoint && lastGridItemPoint.w) {
this.bottomInfo = {
x: 0,
......@@ -53,6 +59,12 @@ export default class Activity extends Mixins(TransformStyleMixin, SaMixin) {
if (lastGridItemPoint.w > this.bottomInfo.w) { this.bottomInfo.w = lastGridItemPoint.w; }
this.bottomInfo.y = this.bottomInfo.y + lastGridItemPoint.y + lastGridItemPoint.h;
}
if (isApp) {
// 当页面数据改变,并且渲染完成后改变app 标题栏颜色
this.$nextTick(() => {
debounce(setAppTitleColor(this.pageData.props.titleBgColor), 300);
});
}
}
@Watch('pageName', { immediate: true })
......@@ -73,17 +85,38 @@ export default class Activity extends Mixins(TransformStyleMixin, SaMixin) {
this.modifyPoints();
}
}
mounted() {
this.targetEle = document.querySelector('body');
this.showBackTop = true;
this.pageVisibilityChange();
if (EASY_ENV_IS_BROWSER) {
EventBus.$on('NATIVE_EVENT_LOGIN', json => {
console.log('xyqbNativeEvent got', json);
if (json.event === 'loginAndLogoutNotification') {
const appData = json.data || {};
if (appData && appData.login) {
localStorage.set('vccToken', appData.token);
this.updateAppLoginState(true);
} else {
this.updateAppLoginState(false);
localStorage.remove('vccToken');
}
}
});
}
}
fetchApi(options) {
const { store, route } = options;
const { pageId } = route.params;
return store.dispatch('getPageDate', { pageId });
}
updateShopCartCount() {
if (EASY_ENV_IS_BROWSER) {
this.$nextTick(() => {
this.$refs.backTop.getCartCount();
});
}
}
modifyPoints() {
const clientWidth = document.documentElement.clientWidth > 768 ? 375 : document.documentElement.clientWidth;
const elements = this.pageData?.elements?.map(v => {
......@@ -103,7 +136,6 @@ export default class Activity extends Mixins(TransformStyleMixin, SaMixin) {
layoutReadyEvent(newLayout) {
this.$nextTick(() => {
console.log('layoutReadyEvent');
const loadingEle = document.querySelector('.mainload');
console.log('loadingEle', loadingEle);
if (!loadingEle) { return; }
......@@ -113,7 +145,19 @@ export default class Activity extends Mixins(TransformStyleMixin, SaMixin) {
}
});
}
getPageElements(ids = []) {
return ids.length === 0 ? this.pageData.elements : ids.map(item => {
const targetEl =
this.pageData.elements.find(it => it.id === (item.componentId || item));
return targetEl;
});
}
setGridItemTransform(index, status) {
console.log('setGridItemTransform', index, status);
const elements = JSON.parse(JSON.stringify(this.pageData?.elements));
elements[index].noTransforms = status;
this.setPageElement(elements);
}
layoutUpdatedEvent() {
console.log('layoutUpdatedEvent');
// 高度更新时重新计算导航组件样式
......@@ -124,6 +168,28 @@ export default class Activity extends Mixins(TransformStyleMixin, SaMixin) {
this.showBackTop = state;
}
// 计算商品导航组件位置
pageVisibilityChange() {
if (EASY_ENV_IS_NODE) { return; }
let hidden = 'hidden';
let visibilityChange = 'visibilitychange';
if (typeof document.hidden !== 'undefined') {
hidden = 'hidden';
visibilityChange = 'visibilitychange';
} else if (typeof document.webkitHidden !== 'undefined') {
hidden = 'webkitHidden';
visibilityChange = 'webkitvisibilitychange';
}
window.addEventListener(visibilityChange, () => {
this.handleChange(document[hidden]);
}, false);
}
handleChange(state) {
if (!state) {
if (isApp) {
setAppTitleColor(this.pageData.props.titleBgColor);
}
}
}
modfiTabsStyle() {
const tabsEle = document.querySelector('.tabs');
// console.log('tabsEle', tabsEle);
......@@ -136,7 +202,7 @@ export default class Activity extends Mixins(TransformStyleMixin, SaMixin) {
gridItemEle.classList.remove('del_transform');
}
const transform = getStyle(gridItemEle, 'transform');
if (transform && transform.length) {
if (transform && transform.length && transform !== 'none') {
const transformY = transform.split('(')[1].split(')')[0].split(',')[5];
gridItemEle.style.top = `${transformY}px`;
gridItemEle.className += ' del_transform';
......
<template>
<div class="activity" :style="transformStyle(pageData.commonStyle)">
<template v-if="!noPageData">
<grid-layout
:layout.sync="layout"
:isDraggable="false"
......@@ -22,6 +23,7 @@
:h="item.point.h"
:i="item.point.i"
:key="item.point.i"
:no-transforms="item.noTransforms"
@click.native="dot(item.title)"
>
<component :data-index="index" :id="item.id" :containerIndex="index" :childItem="item" :is="item.name" :key="item.id" :sa-info="getSaInfo(item)" v-bind="item.props"></component>
......@@ -39,7 +41,9 @@
<page-bottom-tip />
</grid-item>
</grid-layout>
<back-top :show-back-top="showBackTop" />
<back-top :show-back-top="showBackTop" ref="backTop" />
</template>
<empty-state v-else />
</div>
</template>
<script lang="ts" src="./index.ts"></script>
......
......@@ -6,8 +6,7 @@ import { Mutation } from 'vuex-class';
export default class TransformStyleMixin extends Vue {
@Mutation('SET_ELEMENT_POINT') setElementPoint;
transformStyle(styleObj, element) {
// console.log('transformStyle', styleObj, element);
transformStyle(styleObj, element = {}) {
const style = {
backgroundRepeat: 'no-repeat',
backgroundSize: 'cover'
......@@ -42,6 +41,5 @@ export default class TransformStyleMixin extends Vue {
this.setElementPoint({ id: eleId, data: point });
console.log('adjustHeight', height, component, element.getAttribute('id'), point);
// this.updatePageInfo({ containerIndex: this.curEleIndex, data: { ...elements, point: { ...elements.point, h: +height || elements.point.h } } });
}
}
import api from '@/api/editor.api';
import { Module, GetterTree, ActionTree, MutationTree } from 'vuex';
import Vue from 'vue';
import { UPDATE_PAGE_INFO, SET_PAGE_INFO, SET_PAGE_DATA, SET_PAGE_ELEMENTS, SET_ELEMENT_POINT} from './type';
import { UPDATE_PAGE_INFO, SET_PAGE_INFO, SET_PAGE_DATA, SET_PAGE_ELEMENTS, SET_ELEMENT_POINT, UPDATE_APP_LOGIN_STATE, SET_EMPTY_PAGE } from './type';
import RootState from '../../state';
import EditorState, { PageInfo, defaultState, Page, PageElement } from './state';
......@@ -21,8 +21,13 @@ export default class EditorModule implements Module<EditorState, RootState> {
actions: ActionTree<EditorState, RootState> = {
async getPageDate({ commit }, condition) {
const [res] = await api.getPageById(condition);
if (res) {
const { page, ...rest } = res as PageInfo;
commit(SET_PAGE_INFO, { ...rest, page: JSON.parse(page as string) });
commit(SET_EMPTY_PAGE, false);
} else {
commit(SET_EMPTY_PAGE, true);
}
}
};
......@@ -41,9 +46,15 @@ export default class EditorModule implements Module<EditorState, RootState> {
[SET_PAGE_DATA](state, data) {
state.pageInfo.page = data;
},
[UPDATE_APP_LOGIN_STATE](state, data) {
state.pageInfo.appLoginState = data;
},
[SET_PAGE_ELEMENTS](state, data) {
if (data) { (state.pageInfo.page as Page).elements = data; }
},
[SET_EMPTY_PAGE](state, data) {
state.noPageData = data;
},
[SET_ELEMENT_POINT](state, { id, data }) {
const elements = (state.pageInfo.page as Page).elements;
const element = elements.find(ele => ele.id === id);
......
......@@ -47,10 +47,11 @@ export interface PageInfo {
coverImage?: string;
isTemplate?: number;
isPublish?: number | boolean;
appLoginState?: boolean;
}
export const defaultState = {
curEleIndex: null,
noPageData: false,
curChildIndex: null,
pageInfo: {
id: 0,
......@@ -92,7 +93,7 @@ export const defaultState = {
export default interface EditorState {
pageInfo: PageInfo;
draggable: boolean;
curEleIndex: number | null;
noPageData: boolean;
curChildIndex: number | null;
templateList: any[];
rowHeight: number;
......
......@@ -14,3 +14,5 @@ export const UPDATE_PAGE_STYLE = 'UPDATE_PAGE_STYLE';
export const UPDATE_PAGE_PROPS = 'UPDATE_PAGE_PROPS';
export const SET_PAGE_ELEMENTS = 'SET_PAGE_ELEMENTS';
export const SET_ELEMENT_POINT = 'SET_ELEMENT_POINT';
export const SET_EMPTY_PAGE = 'SET_EMPTY_PAGE';
export const UPDATE_APP_LOGIN_STATE = 'UPDATE_APP_LOGIN_STATE';
......@@ -4,7 +4,7 @@ import Cookies from './cookieStorage.service';
import localStorage from './localStorage.service';
// formXcxPage:标识是从小程序跳转过来的;
const localStorageParams = ['creditToken', 'vccToken', 'vccChannel', 'sonVccChannel', 'formXcxPage'];
const cookiesParams = ['h', 'vccToken'];
const cookiesParams = ['h'];
export default {
// token校验,整个流程都是登陆后的
......
......@@ -26,7 +26,7 @@ import Vue from 'vue';
// Swipe,
// SwipeItem,
// Toast,
// BackTop
// BackTop,
// } from '@qg/cherry-ui';
// import { KaLoginForm } from '@qg/citrus-ui';
import Button from '@qg/cherry-ui/src/button';
......@@ -44,6 +44,7 @@ import Text from '@qg/cherry-ui/src/text';
import Tag from '@qg/cherry-ui/src/tag';
import Popover from '@qg/cherry-ui/src/popover';
import Icon from '@qg/cherry-ui/src/icon';
import Empty from '@qg/cherry-ui/src/empty';
Vue.use(Button);
Vue.use(Image);
......@@ -75,6 +76,7 @@ Vue.use(Text);
Vue.use(Tag);
Vue.use(Popover);
Vue.use(Icon);
Vue.use(Empty);
Vue.use(citrusUi);
......
import Vue from 'vue';
import sa from 'sa-sdk-javascript';
import config from '@/config';
import Storage from '@/service/localStorage.service';
import { getParameterByName, isWxMp, isApp } from '@/service/utils.service';
export function initSa(router) {
console.log('initSa', EASY_ENV_IS_BROWSER, config, window.location.pathname);
const sa = require('sa-sdk-javascript');
const activityId = window.location.pathname.split('/')?.[2] || '';
const vccChannel = getParameterByName('vccChannel') || getParameterByName('registerFrom');
const sonVccChannel = getParameterByName('sonVccChannel');
......@@ -38,11 +37,13 @@ export function initSa(router) {
}
export function registeredEvents(eventName, eventData) {
const sa = require('sa-sdk-javascript');
sa.track(eventName, eventData);
}
// 用户登录神策埋点
export function loginSa(uuid = Storage.get('uuid')) {
if (!uuid) { return; }
Storage.set('uuid', uuid);
const sa = require('sa-sdk-javascript');
sa.login(uuid);
}
......@@ -5,6 +5,7 @@ declare var EASY_ENV_IS_NODE: boolean;
interface Window {
__INITIAL_STATE__: any;
xyqbNativeEvent: any;
}
declare module 'axios' {
......
{
"api": {
"apiHost": "https://quantum-blocks-test1.liangkebang.net",
"h5Host": "https://quantum-h5-test1.liangkebang.net",
"opapiHost": "https://opapi-test1.liangkebang.net",
"passportHost": "https://passportapi-test1.liangkebang.net",
"kdspHost": "https://talos-test1.liangkebang.net",
"apiHost": "https://quantum-blocks-vcc2.liangkebang.net",
"h5Host": "https://quantum-h5-vcc2.liangkebang.net",
"opapiHost": "https://opapi-vcc2.liangkebang.net",
"passportHost": "https://passportapi-vcc2.liangkebang.net",
"kdspHost": "https://talos-vcc2.liangkebang.net",
"loginUrl": "",
"h5ShopHost": "https://tenet-test1.liangkebang.net/#"
"h5ShopHost": "https://tenet-vcc2.liangkebang.net/#"
},
"mysql": {
"low_code": {
......
{
"apiHost": "https://quantum-blocks-vcc2.liangkebang.net",
"h5Host": "https://quantum-h5-vcc2.liangkebang.net",
"opapiHost": "https://opapi-vcc2.liangkebang.net",
"passportHost": "https://passportapi-vcc2.liangkebang.net",
"kdspHost": "https://talos-vcc2.liangkebang.net",
"apiHost": "https://quantum-blocks-test1.liangkebang.net",
"h5Host": "https://quantum-h5-test1.liangkebang.net",
"opapiHost": "https://opapi-test1.liangkebang.net",
"passportHost": "https://passportapi-test1.liangkebang.net",
"kdspHost": "https://talos-test1.liangkebang.net",
"loginUrl": "",
"h5ShopHost": "https://tenet-vcc2.liangkebang.net/#",
"h5ShopHost": "https://tenet-test1.liangkebang.net/#",
"qiniuUpHost": "https://up-z0.qiniup.com",
"qiniuHost": "https://appsync.lkbang.net"
}
......@@ -29,8 +29,8 @@ export default (appInfo: EggAppConfig) => {
exports.redis = {
client: {
port: 31565, // Redis port
host: '172.17.5.13', // Redis host
port: 32625, // Redis port
host: '172.17.5.17', // Redis host
password: '',
db: 0
}
......
This diff is collapsed.
{
"name": "quantum-blocks-h5",
"version": "0.0.1",
"version": "1.0.0",
"description": "低代码平台",
"scripts": {
"start": "cross-env NODE_ENV=production APOLLO_CLUSTER=3C egg-scripts start --port 9050",
......@@ -23,9 +23,8 @@
"dependencies": {
"@better-scroll/core": "^2.0.5",
"@qg/apollo-nodejs": "^2.1.2",
"@qg/cherry-ui": "2.22.3",
"@qg/citrus-ui": "0.2.20",
"@qg/js-bridge": "^1.1.7",
"@qg/cherry-ui": "2.23.4",
"@qg/citrus-ui": "0.3.1",
"babel-plugin-transform-vue-jsx": "^4.0.1",
"cos-nodejs-sdk-v5": "^2.9.12",
"egg": "^2.3.0",
......
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