diff --git a/paas-ce/lesscode/lib/client/build/conf.js b/paas-ce/lesscode/lib/client/build/conf.js index f6eddfc8d..ddb8b0eb3 100644 --- a/paas-ce/lesscode/lib/client/build/conf.js +++ b/paas-ce/lesscode/lib/client/build/conf.js @@ -24,7 +24,6 @@ module.exports = { APP_CODE: JSON.stringify(APP_CODE), AJAX_URL_PREFIX: JSON.stringify('/api'), ENV: JSON.stringify(ENV) - }, assetsPublicPath: '{{STATIC_URL}}', staticUrl: '/static', diff --git a/paas-ce/lesscode/lib/client/index-dev.html b/paas-ce/lesscode/lib/client/index-dev.html index 63229a9f9..7480b1a5e 100644 --- a/paas-ce/lesscode/lib/client/index-dev.html +++ b/paas-ce/lesscode/lib/client/index-dev.html @@ -15,7 +15,7 @@ - 蓝鲸智云MagicBox|可视化开发 + 可视化开发平台 | 蓝鲸智云社区版 diff --git a/paas-ce/lesscode/lib/client/src/common/bkmagic.js b/paas-ce/lesscode/lib/client/src/common/bkmagic.js index 471965ca1..85fcee2c7 100644 --- a/paas-ce/lesscode/lib/client/src/common/bkmagic.js +++ b/paas-ce/lesscode/lib/client/src/common/bkmagic.js @@ -10,7 +10,6 @@ */ import Vue from 'vue' - // 全量引入 import './fully-import' @@ -21,6 +20,26 @@ const Message = Vue.prototype.$bkMessage let messageInstance = null +export const messageHtmlError = (errMessage, delay = 3000, ellipsisLine = 0) => { + messageInstance && messageInstance.close() + const messageComponent = Vue.compile(errMessage) + const globalComponent = global.mainComponent + const { $options, $createElement } = globalComponent + const _staticRenderFns = $options.staticRenderFns + + $options.staticRenderFns = messageComponent.staticRenderFns + const message = messageComponent.render.call(globalComponent, $createElement) + $options.staticRenderFns = _staticRenderFns + + messageInstance = Message({ + message, + delay, + theme: 'error', + ellipsisLine, + extCls: 'auto-width' + }) +} + export const messageError = (message, delay = 3000, ellipsisLine = 0) => { messageInstance && messageInstance.close() messageInstance = Message({ @@ -59,6 +78,7 @@ export const messageWarn = (message, delay = 3000) => { }) } +Vue.prototype.messageHtmlError = messageHtmlError Vue.prototype.messageError = messageError Vue.prototype.messageSuccess = messageSuccess Vue.prototype.messageInfo = messageInfo diff --git a/paas-ce/lesscode/lib/client/src/components/header.vue b/paas-ce/lesscode/lib/client/src/components/header.vue index 6a26af36d..be1a0988b 100644 --- a/paas-ce/lesscode/lib/client/src/components/header.vue +++ b/paas-ce/lesscode/lib/client/src/components/header.vue @@ -80,7 +80,7 @@ 前端规范
- 设计规范 + 设计规范
辅助样式 diff --git a/paas-ce/lesscode/lib/client/src/components/methods/func-form.vue b/paas-ce/lesscode/lib/client/src/components/methods/func-form.vue index b302fe129..2067de78b 100644 --- a/paas-ce/lesscode/lib/client/src/components/methods/func-form.vue +++ b/paas-ce/lesscode/lib/client/src/components/methods/func-form.vue @@ -55,26 +55,37 @@ - + - + + + - - - + + + + + + diff --git a/paas-ce/lesscode/lib/client/src/components/methods/monaco-func.vue b/paas-ce/lesscode/lib/client/src/components/methods/monaco-func.vue new file mode 100644 index 000000000..8270a46c9 --- /dev/null +++ b/paas-ce/lesscode/lib/client/src/components/methods/monaco-func.vue @@ -0,0 +1,81 @@ + + + + + diff --git a/paas-ce/lesscode/lib/client/src/components/methods/monaco.vue b/paas-ce/lesscode/lib/client/src/components/methods/monaco.vue index e81c7a898..1ee91fbb5 100644 --- a/paas-ce/lesscode/lib/client/src/components/methods/monaco.vue +++ b/paas-ce/lesscode/lib/client/src/components/methods/monaco.vue @@ -1,20 +1,23 @@ - diff --git a/paas-ce/lesscode/lib/client/src/components/novice-guide/index.vue b/paas-ce/lesscode/lib/client/src/components/novice-guide/index.vue index d0f315794..0affa0262 100644 --- a/paas-ce/lesscode/lib/client/src/components/novice-guide/index.vue +++ b/paas-ce/lesscode/lib/client/src/components/novice-guide/index.vue @@ -41,9 +41,9 @@ 确定 取消 -
+
@@ -393,8 +393,10 @@ transform: translate(-50%, -50%); .wraper{ width: 500px; - height: 390px; - padding-top: 45px; + /* height: 390px; */ + /* padding-top: 45px; */ + height: 370px; + padding-top: 25px; text-align: center; border-radius: 2px; background: #fff; diff --git a/paas-ce/lesscode/lib/client/src/components/render/component-wrapper.js b/paas-ce/lesscode/lib/client/src/components/render/component-wrapper.js index 3f1a2d933..f247967a8 100644 --- a/paas-ce/lesscode/lib/client/src/components/render/component-wrapper.js +++ b/paas-ce/lesscode/lib/client/src/components/render/component-wrapper.js @@ -38,7 +38,11 @@ export default { }, dynamicProps) const renderStyles = Object.assign({}, renderData.renderStyles) - if (componentData.type !== 'img') delete renderStyles.width + + const widthChangeableCompoennts = ['img', 'p', 'span', 'bk-link', 'el-link'] + if (!widthChangeableCompoennts.includes(componentData.type)) delete renderStyles.width + + console.log('renderStyle', renderStyles) return h(renderData.type, { key: params['component-type'] === 'bk-sideslider' ? 'bk-slider' : refreshKey, // sideSlider 固定key,防止属性修改动画刷新 diff --git a/paas-ce/lesscode/lib/client/src/components/variable/variable-form/index.vue b/paas-ce/lesscode/lib/client/src/components/variable/variable-form/index.vue index 4396803d3..d5827cc8d 100644 --- a/paas-ce/lesscode/lib/client/src/components/variable/variable-form/index.vue +++ b/paas-ce/lesscode/lib/client/src/components/variable/variable-form/index.vue @@ -232,8 +232,7 @@ } return this.getAllVariable(params) }).catch((err) => { - const message = this.$createElement('pre', { style: { margin: 0 } }, [err.message]) - this.$bkMessage({ theme: 'error', message, ellipsisLine: 0, extCls: 'auto-width' }) + this.messageHtmlError(err.message) }).finally(() => { this.isSaving = false }) diff --git a/paas-ce/lesscode/lib/client/src/components/variable/variable-form/variable-code.vue b/paas-ce/lesscode/lib/client/src/components/variable/variable-form/variable-code.vue index f75d677f3..16d1632b5 100644 --- a/paas-ce/lesscode/lib/client/src/components/variable/variable-form/variable-code.vue +++ b/paas-ce/lesscode/lib/client/src/components/variable/variable-form/variable-code.vue @@ -2,7 +2,11 @@
@@ -10,13 +14,31 @@ diff --git a/paas-ce/lesscode/lib/client/src/element-materials/materials/bk/button/index.js b/paas-ce/lesscode/lib/client/src/element-materials/materials/bk/button/index.js index 53c2a9d11..87e5ec187 100644 --- a/paas-ce/lesscode/lib/client/src/element-materials/materials/bk/button/index.js +++ b/paas-ce/lesscode/lib/client/src/element-materials/materials/bk/button/index.js @@ -47,6 +47,12 @@ export default { type: 'boolean', val: false }, + icon: { + type: 'icon' + }, + 'icon-right': { + type: 'icon' + }, 'ext-cls': { type: 'string', tips: '配置自定义样式类名,传入的类会被加在组件最外层的 DOM 上' diff --git a/paas-ce/lesscode/lib/client/src/element-materials/materials/bk/link/index.js b/paas-ce/lesscode/lib/client/src/element-materials/materials/bk/link/index.js index 845b08e26..2e531348c 100644 --- a/paas-ce/lesscode/lib/client/src/element-materials/materials/bk/link/index.js +++ b/paas-ce/lesscode/lib/client/src/element-materials/materials/bk/link/index.js @@ -19,7 +19,8 @@ export default { events: [{ name: 'click' }], styles: ['size', 'margin', 'padding', 'display', 'textAlign'], renderStyles: { - display: 'inline-block' + display: 'inline-block', + textAlign: 'center' }, props: { theme: { diff --git a/paas-ce/lesscode/lib/client/src/element-materials/materials/bk/rate/index.js b/paas-ce/lesscode/lib/client/src/element-materials/materials/bk/rate/index.js index 0355798f1..55ddfdb54 100644 --- a/paas-ce/lesscode/lib/client/src/element-materials/materials/bk/rate/index.js +++ b/paas-ce/lesscode/lib/client/src/element-materials/materials/bk/rate/index.js @@ -20,11 +20,22 @@ export default { name: 'score', tips: '评分的时候触发该回调事件,回调参数为选中的分数' }], styles: ['margin', 'display'], + directives: [ + { + type: 'v-bind', + prop: 'rate', + propTypes: ['number'], + val: '', + valType: 'variable', + modifiers: ['sync'] + } + ], props: { rate: { type: 'number', val: 0, - tips: '显示的分数' + tips: '显示的分数', + modifiers: ['sync'] }, width: { type: 'number', diff --git a/paas-ce/lesscode/lib/client/src/element-materials/materials/bk/tag-input/index.js b/paas-ce/lesscode/lib/client/src/element-materials/materials/bk/tag-input/index.js index af480d2ed..a651c087c 100644 --- a/paas-ce/lesscode/lib/client/src/element-materials/materials/bk/tag-input/index.js +++ b/paas-ce/lesscode/lib/client/src/element-materials/materials/bk/tag-input/index.js @@ -29,6 +29,13 @@ export default { }], styles: ['size', 'margin', 'display'], directives: [ + { + type: 'v-model', + prop: 'value', + propTypes: ['array'], + val: '', + valType: 'variable' + }, { type: 'v-bind', prop: 'list', diff --git a/paas-ce/lesscode/lib/client/src/element-materials/materials/bk/transfer/index.js b/paas-ce/lesscode/lib/client/src/element-materials/materials/bk/transfer/index.js index 9d6ce05f7..05c96f890 100644 --- a/paas-ce/lesscode/lib/client/src/element-materials/materials/bk/transfer/index.js +++ b/paas-ce/lesscode/lib/client/src/element-materials/materials/bk/transfer/index.js @@ -22,6 +22,16 @@ export default { }], styles: ['size', 'margin'], directives: [ + { + type: 'v-bind', + prop: 'target-list', + propTypes: ['array'], + val: '', + valType: 'variable', + tips () { + return '已选择数据,数据格式[\'shenzhen\', \'guangzhou\']' + } + }, { type: 'v-bind', prop: 'source-list', @@ -76,7 +86,7 @@ export default { 'target-list': { type: 'array', val: [], - tips: '已选择的数据' + tips: '已选择数据,数据格式[\'shenzhen\', \'guangzhou\']' }, searchable: { type: 'boolean', diff --git a/paas-ce/lesscode/lib/client/src/element-materials/materials/element/cascade/index.js b/paas-ce/lesscode/lib/client/src/element-materials/materials/element/cascade/index.js index 9f508dbef..b21309354 100644 --- a/paas-ce/lesscode/lib/client/src/element-materials/materials/element/cascade/index.js +++ b/paas-ce/lesscode/lib/client/src/element-materials/materials/element/cascade/index.js @@ -254,7 +254,7 @@ export default { tips: '可选项数据源' }, props: { - type: 'object', + type: 'el-props', val: { multiple: false, expandTrigger: 'click', diff --git a/paas-ce/lesscode/lib/client/src/element-materials/materials/element/color-picker/index.js b/paas-ce/lesscode/lib/client/src/element-materials/materials/element/color-picker/index.js index bf4e9d266..6f8232c57 100644 --- a/paas-ce/lesscode/lib/client/src/element-materials/materials/element/color-picker/index.js +++ b/paas-ce/lesscode/lib/client/src/element-materials/materials/element/color-picker/index.js @@ -36,7 +36,7 @@ export default { ], props: { value: { - type: 'string', + type: 'color', val: '#3A84FF' }, size: { diff --git a/paas-ce/lesscode/lib/client/src/element-materials/materials/element/input/index.js b/paas-ce/lesscode/lib/client/src/element-materials/materials/element/input/index.js index 2d42cf5f4..aac2909ec 100644 --- a/paas-ce/lesscode/lib/client/src/element-materials/materials/element/input/index.js +++ b/paas-ce/lesscode/lib/client/src/element-materials/materials/element/input/index.js @@ -28,6 +28,9 @@ export default { name: 'clear', tips: '在点击由 clearable 属性生成的清空按钮时触发' }], styles: ['size', 'margin', 'display'], + renderStyles: { + width: '200px' + }, directives: [ { type: 'v-model', diff --git a/paas-ce/lesscode/lib/client/src/element-materials/materials/element/link/index.js b/paas-ce/lesscode/lib/client/src/element-materials/materials/element/link/index.js index 247884d2c..c4e155ebb 100644 --- a/paas-ce/lesscode/lib/client/src/element-materials/materials/element/link/index.js +++ b/paas-ce/lesscode/lib/client/src/element-materials/materials/element/link/index.js @@ -17,9 +17,10 @@ export default { displayName: '文字链接', group: '基础', events: [{ name: 'click' }], - styles: ['size', 'padding', 'margin', 'display'], + styles: ['size', 'padding', 'margin', 'display', 'text-align'], renderStyles: { - display: 'inline-flex' + display: 'inline-block', + textAlign: 'center' }, props: { type: { diff --git a/paas-ce/lesscode/lib/client/src/element-materials/materials/element/radio-group/index.js b/paas-ce/lesscode/lib/client/src/element-materials/materials/element/radio-group/index.js index 5457d4f65..6e08f9ba3 100644 --- a/paas-ce/lesscode/lib/client/src/element-materials/materials/element/radio-group/index.js +++ b/paas-ce/lesscode/lib/client/src/element-materials/materials/element/radio-group/index.js @@ -52,18 +52,13 @@ export default { }, value: { type: ['string', 'number', 'boolean'], - val: '' + val: '单选一' }, disabled: { type: 'boolean', val: false, 'v-bind': '', tips: '是否禁用状态' - }, - fill: { - type: 'string', - val: '#409EFF', - tips: '按钮形式的 Radio 激活时的填充色和边框色' } } } diff --git a/paas-ce/lesscode/lib/client/src/element-materials/materials/element/rate/index.js b/paas-ce/lesscode/lib/client/src/element-materials/materials/element/rate/index.js index 055eab9b6..a3ece873e 100644 --- a/paas-ce/lesscode/lib/client/src/element-materials/materials/element/rate/index.js +++ b/paas-ce/lesscode/lib/client/src/element-materials/materials/element/rate/index.js @@ -64,7 +64,7 @@ export default { tips: 'icon 的颜色。若传入数组,共有 3 个元素,为 3 个分段所对应的颜色;若传入对象,可自定义分段,键名为分段的界限值,键值为对应的颜色' }, 'void-color': { - type: 'string', + type: 'color', val: '#C6D1DE', tips: '未选中 icon 的颜色' }, @@ -79,7 +79,7 @@ export default { tips: '是否显示当前分数,show-score 和 show-text 不能同时为真' }, 'text-color': { - type: 'string', + type: 'color', val: '#1F2D3D', tips: '辅助文字的颜色' }, diff --git a/paas-ce/lesscode/lib/client/src/element-materials/materials/element/select/index.js b/paas-ce/lesscode/lib/client/src/element-materials/materials/element/select/index.js index 9bc6f4489..a6a2310cc 100644 --- a/paas-ce/lesscode/lib/client/src/element-materials/materials/element/select/index.js +++ b/paas-ce/lesscode/lib/client/src/element-materials/materials/element/select/index.js @@ -76,20 +76,6 @@ export default { val: false, tips: '是否可搜索' }, - // 'filter-method': { - // type: 'remote', - // tips: '自定义搜索方法' - // - // }, - // remote: { - // type: 'boolean', - // val: false, - // tips: '是否为远程搜索' - // }, - // 'remote-method': { - // type: 'remote', - // tips: '远程搜索方法' - // }, 'collapse-tags': { type: 'boolean', val: false, diff --git a/paas-ce/lesscode/lib/client/src/element-materials/materials/element/switcher/index.js b/paas-ce/lesscode/lib/client/src/element-materials/materials/element/switcher/index.js index 36f7045a0..0a4267d31 100644 --- a/paas-ce/lesscode/lib/client/src/element-materials/materials/element/switcher/index.js +++ b/paas-ce/lesscode/lib/client/src/element-materials/materials/element/switcher/index.js @@ -62,12 +62,12 @@ export default { tips: 'switch 关闭时的值' }, 'active-color': { - type: 'string', + type: 'color', val: '#409EFF', tips: 'switch 打开时的背景色' }, 'inactive-color': { - type: 'string', + type: 'color', val: '#C0CCDA', tips: 'switch 关闭时的背景色' } diff --git a/paas-ce/lesscode/lib/client/src/element-materials/modifier/component/props/components/render-prop.vue b/paas-ce/lesscode/lib/client/src/element-materials/modifier/component/props/components/render-prop.vue index 5f2a96dba..1fb3e36b2 100644 --- a/paas-ce/lesscode/lib/client/src/element-materials/modifier/component/props/components/render-prop.vue +++ b/paas-ce/lesscode/lib/client/src/element-materials/modifier/component/props/components/render-prop.vue @@ -90,6 +90,7 @@ import TypeIcon from './strategy/icon' import TypeFormItem from './strategy/form-item' import TypeColor from './strategy/color' + import TypleElProps from './strategy/el-props' import { transformTipsWidth } from '@/common/util' import safeStringify from '@/common/json-safe-stringify' @@ -182,7 +183,8 @@ 'timeline': TypeSlotWrapper, 'carousel': TypeSlotWrapper, 'el-radio': TypeSlotWrapper, - 'el-checkbox': TypeSlotWrapper + 'el-checkbox': TypeSlotWrapper, + 'el-props': TypleElProps } let realType = config.type @@ -218,7 +220,8 @@ 'timeline': 'timeline', 'carousel': 'carousel', 'el-radio': 'el-radio', - 'el-checkbox': 'el-checkbox' + 'el-checkbox': 'el-checkbox', + 'el-props': 'el-props' } const valueMap = { 'text': 'string', diff --git a/paas-ce/lesscode/lib/client/src/element-materials/modifier/component/props/components/strategy/el-props.vue b/paas-ce/lesscode/lib/client/src/element-materials/modifier/component/props/components/strategy/el-props.vue new file mode 100644 index 000000000..83dd4726c --- /dev/null +++ b/paas-ce/lesscode/lib/client/src/element-materials/modifier/component/props/components/strategy/el-props.vue @@ -0,0 +1,120 @@ + + + + + + diff --git a/paas-ce/lesscode/lib/client/src/element-materials/modifier/component/props/components/strategy/remote.vue b/paas-ce/lesscode/lib/client/src/element-materials/modifier/component/props/components/strategy/remote.vue index 2a008efd4..e76242a6d 100644 --- a/paas-ce/lesscode/lib/client/src/element-materials/modifier/component/props/components/strategy/remote.vue +++ b/paas-ce/lesscode/lib/client/src/element-materials/modifier/component/props/components/strategy/remote.vue @@ -14,7 +14,7 @@
{{title || (name === 'remoteOptions' ? '动态配置' : '远程函数')}}
- + 获取数据 @@ -74,6 +74,11 @@ this.saveChange() }, methods: { + changeFunc () { + this.saveChange() + this.getApiData() + }, + saveChange () { this.change(this.name, this.defaultValue, this.type, JSON.parse(JSON.stringify(this.remoteData))) }, @@ -84,10 +89,8 @@ if (curVar) { const { defaultValue, defaultValueType, valueType } = curVar let value = defaultValueType === 0 ? defaultValue.all : defaultValue.stag - if ([3, 4].includes(valueType) && typeof value === 'string') { - value = JSON.parse(value) - } if (valueType === 6) value = '' + if (valueType === 0) value = `'${value}'` return value } else { throw new Error(`函数【${funcName}】里引用的变量【${variableCode}】不存在,请检查`) @@ -110,13 +113,13 @@ const funcParams = (returnMethod.funcParams || []).join(', ') if (returnMethod.funcType === 1) { const remoteParams = (returnMethod.remoteParams || []).join(', ') - const data = { - url: this.processVarInFunParams(returnMethod.funcApiUrl, returnMethod.funcName), - type: returnMethod.funcMethod, - apiData: this.processVarInFunParams(returnMethod.funcApiData, returnMethod.funcName), - withToken: returnMethod.withToken - } - returnMethod.funcStr = `const ${returnMethod.funcName} = (${funcParams}) => { return this.$store.dispatch('getApiData', ${JSON.stringify(data)}).then((${remoteParams}) => { ${returnMethod.funcBody} }) };` + const data = `{ + url: '${this.processVarInFunParams(returnMethod.funcApiUrl, returnMethod.funcName)}', + type: '${returnMethod.funcMethod}', + apiData: ${this.processVarInFunParams(returnMethod.funcApiData, returnMethod.funcName) || "''"}, + withToken: ${returnMethod.withToken} + }` + returnMethod.funcStr = `const ${returnMethod.funcName} = (${funcParams}) => { return this.$store.dispatch('getApiData', ${data}).then((${remoteParams}) => { ${returnMethod.funcBody} }) };` } else { returnMethod.funcStr = `const ${returnMethod.funcName} = (${funcParams}) => { ${returnMethod.funcBody} };` } @@ -245,9 +248,10 @@ try { const sandBox = this.createSandBox() const res = await sandBox.exec(methodStr, this.remoteData.params) - const message = this.remoteValidate(res) + let message = this.remoteValidate(res) if (message) { - this.$bkMessage({ theme: 'error', message }) + message = '数据源设置成功,以下问题可能会导致组件表现异常,请检查:' + message + this.$bkMessage({ theme: 'warning', message }) } else { this.change(this.name, res, this.type, JSON.parse(JSON.stringify(this.remoteData))) if (this.name === 'remoteOptions') { diff --git a/paas-ce/lesscode/lib/client/src/router/index.js b/paas-ce/lesscode/lib/client/src/router/index.js index 310d608af..b976d8390 100644 --- a/paas-ce/lesscode/lib/client/src/router/index.js +++ b/paas-ce/lesscode/lib/client/src/router/index.js @@ -38,6 +38,8 @@ const Index = () => import(/* webpackChunkName: 'index' */'@/views/index/index') const Preview = () => import(/* webpackChunkName: 'preview' */'@/views/preview') const NotFound = () => import(/* webpackChunkName: 'none' */'@/views/status/404') +const HealthPage = () => import(/* webpackChunkName: 'none' */'@/views/system/health') + const MainHelpEntry = () => import(/* webpackChunkName: 'index' */'@/views/help') const Custom = () => import(/* webpackChunkName: 'custom' */'@/views/help/docs/custom.md') const Grid = () => import(/* webpackChunkName: 'grid' */'@/views/help/docs/grid.md') @@ -72,6 +74,10 @@ const routes = [ { path: 'free-layout', name: 'freeLayout', component: FreeLayoutDoc } ] }, + { + path: '/checkHealth', + component: HealthPage + }, { path: '/', component: SystemEntry, diff --git a/paas-ce/lesscode/lib/client/src/store/index.js b/paas-ce/lesscode/lib/client/src/store/index.js index e63369aaa..39f3e66d1 100644 --- a/paas-ce/lesscode/lib/client/src/store/index.js +++ b/paas-ce/lesscode/lib/client/src/store/index.js @@ -125,6 +125,13 @@ const store = new Vuex.Store({ }) }, + getHealthData ({ state }) { + return http.get('/health/check').then(response => { + const data = response.data || [] + return data + }) + }, + // x-table remove (context, params, config) { return http.delete(`/test/remove?${json2Query(params)}`, {}, config).then(res => { diff --git a/paas-ce/lesscode/lib/client/src/store/modules/functions.js b/paas-ce/lesscode/lib/client/src/store/modules/functions.js index 68f6f19f6..1e621d71c 100644 --- a/paas-ce/lesscode/lib/client/src/store/modules/functions.js +++ b/paas-ce/lesscode/lib/client/src/store/modules/functions.js @@ -8,9 +8,8 @@ * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the * specific language governing permissions and limitations under the License. */ -import { bkMessage } from 'bk-magic-vue' +import { messageHtmlError } from '../../common/bkmagic' import http from '@/api' -import router from '../../router' const perfix = '/function' export default { @@ -31,11 +30,10 @@ export default { }) }, - bulkAddFunc ({ state }, { groupId, funcList, h, varWhere }) { + bulkAddFunc ({ state }, { groupId, funcList, varWhere }) { return http.post(`${perfix}/bulkAddFunction`, { funcList, varWhere }).then((res = {}) => { if (res.code === 499) { - const message = h('pre', { style: { margin: 0 } }, [res.message]) - bkMessage({ theme: 'error', message, ellipsisLine: 0, extCls: 'auto-width' }) + messageHtmlError(res.message) return } const newFuncs = res.data || [] @@ -45,11 +43,10 @@ export default { }) }, - addFunc ({ state }, { groupId, func, h, varWhere }) { + addFunc ({ state }, { groupId, func, varWhere }) { return http.post(`${perfix}/addFunction`, { func, varWhere }).then((res = {}) => { if (res.code === 499) { - const message = h('pre', { style: { margin: 0 } }, [res.message]) - bkMessage({ theme: 'error', message, ellipsisLine: 0, extCls: 'auto-width' }) + messageHtmlError(res.message) return } const newFunc = res.data || {} @@ -68,11 +65,10 @@ export default { }) }, - editFunc ({ state }, { groupId, func, h, varWhere }) { + editFunc ({ state }, { func, varWhere }) { return http.put(`${perfix}/editFunction`, { func, varWhere }).then((res) => { if (res.code === 499) { - const message = h('pre', { style: { margin: 0 } }, [res.message]) - bkMessage({ theme: 'error', message, ellipsisLine: 0, extCls: 'auto-width' }) + messageHtmlError(res.message) return } const data = res.data || [] @@ -106,15 +102,8 @@ export default { return http.put(`${perfix}/editFuncGroups`, groups) }, - generateToken ({ state }, { appCode, id }) { - return http.get(`${perfix}/generateToken`, { params: { appCode, id } }) - }, - - getTokenList () { - const curRouter = router.currentRoute || {} - const params = curRouter.params || {} - const projectId = params.projectId || '' - return http.get(`${perfix}/getTokenList?projectId=${projectId}`) + fixFunByEslint (_, func) { + return http.post(`${perfix}/fixFunByEslint`, func) } } } diff --git a/paas-ce/lesscode/lib/client/src/store/modules/page.js b/paas-ce/lesscode/lib/client/src/store/modules/page.js index fce232a69..7eead8303 100644 --- a/paas-ce/lesscode/lib/client/src/store/modules/page.js +++ b/paas-ce/lesscode/lib/client/src/store/modules/page.js @@ -84,6 +84,22 @@ export default { return data }) }, + pageLockStatus ({ commit }, { pageId }) { + return http.get(`/page/pageLockStatus?pageId=${pageId}`).then(response => { + const data = response.data || '' + return data + }) + }, + updatePageLock ({ commit }, { data = {} }) { + return http.post('/page/updatePageActive', data).then(response => { + return response.data || '' + }) + }, + occupyPage ({ commit }, { data = {} }) { + return http.post('/page/occupyPage', data).then(response => { + return response.data || '' + }) + }, verify ({ commit }, { data, config }) { return http.post('/page/verify', data, config).then(response => { return response diff --git a/paas-ce/lesscode/lib/client/src/views/changelog/index.md b/paas-ce/lesscode/lib/client/src/views/changelog/index.md index e88708acf..f696278e5 100644 --- a/paas-ce/lesscode/lib/client/src/views/changelog/index.md +++ b/paas-ce/lesscode/lib/client/src/views/changelog/index.md @@ -2,6 +2,32 @@
+### v0.2.5 +###### 2021.08.03 + +* **[add]**: + - 画布: 画布编辑页面增加加锁和抢占功能 + - 画布: Element表单组件(标签输入、穿梭框、rate组件)加上v-model可以获取表单值 + - 画布: Element按钮组件增加icon设置属性 +* **[fix]**: + - 其他: 体验问题修复 + +--- + +### v0.2.4 +###### 2021.07.22 + +* **[add]**: + - 画布: Element 基础组件库组件丰富 + - 画布: 修改部署页面title + - 项目管理: 函数和计算变量添加自动fix eslint +* **[fix]**: + - 画布: 修复p标签与文字相关组件的对齐问题 + - 项目管理: 函数相关体验问题 + - 其他: 修改身份认证失败状态码 + +--- + ### v0.2.3 ###### 2021.07.01 diff --git a/paas-ce/lesscode/lib/client/src/views/help/docs/intro.md b/paas-ce/lesscode/lib/client/src/views/help/docs/intro.md index a702596d9..d508b19f4 100644 --- a/paas-ce/lesscode/lib/client/src/views/help/docs/intro.md +++ b/paas-ce/lesscode/lib/client/src/views/help/docs/intro.md @@ -8,6 +8,6 @@ - **布局模板**:提供多种导航布局模板 - **在线函数库管理**:支持在线灵活编写管理事件函数及远程接口返回数据清洗函数 - **在线组件配置**:支持组件样式、属性、事件在线配置 -- **二次开发能力**:生成的 Vue 源码文件支持无缝集成到蓝鲸前端开发框架([BKUI-CLI](https://bk.tencent.com/docs/document/5.1/19/583))进行二次开发 +- **二次开发能力**:生成的 Vue 源码文件支持无缝集成到蓝鲸前端开发框架([BKUI-CLI](https://bk.tencent.com/docs/document/6.0/130/5940))进行二次开发 - **支持自定义组件开发**:提供自定义组件开发规范及示例,开放自定义组件开发能力,满足业务场景组件集成需求 - **一键部署**:基于蓝鲸PaaS,支持在线拖拽布局后,一键部署至线上环境 diff --git a/paas-ce/lesscode/lib/client/src/views/index/index.vue b/paas-ce/lesscode/lib/client/src/views/index/index.vue index 267fb3ce9..a8b4876e1 100644 --- a/paas-ce/lesscode/lib/client/src/views/index/index.vue +++ b/paas-ce/lesscode/lib/client/src/views/index/index.vue @@ -321,6 +321,8 @@ baseComponentList.splice(0, 0, ...allComponentConf['bk']) return { + lockNotify: null, + lockCheckTimer: null, leftNavTabList: [ { icon: 'bk-drag-custom-comp-default', @@ -448,6 +450,7 @@ } }, computed: { + ...mapGetters(['user']), ...mapGetters(['mainContentLoading']), ...mapGetters('drag', [ 'draggableSourceGroup', @@ -499,9 +502,11 @@ targetData: { get () { + console.warn('get Target') return this.$store.state.drag.targetData }, set (value) { + console.warn('set Target') this.setTargetData(value) } }, @@ -522,6 +527,12 @@ this.panelMap.base.props.componentList = this.baseComponentList this.panelMap.base.props.componentGroupList = allComponentConf[`${v}ComponentGroupList`] + }, + targetData: { + deep: true, + handler () { + this.lockStatsuPolling('lock') + } } }, async created () { @@ -637,13 +648,17 @@ window.addEventListener('keyup', this.judgeCtrl) window.addEventListener('click', this.toggleQuickOperation, true) window.addEventListener('beforeunload', this.beforeunloadConfirm) + window.addEventListener('unload', this.relasePage) }, beforeDestroy () { window.removeEventListener('keydown', this.quickOperation) window.removeEventListener('keyup', this.judgeCtrl) window.removeEventListener('click', this.toggleQuickOperation, true) window.removeEventListener('beforeunload', this.beforeunloadConfirm) + window.removeEventListener('unload', this.relasePage) this.resizeObserve.disconnect() + this.relasePage() + this.lockNotify && this.lockNotify.close() }, beforeRouteLeave (to, from, next) { this.$bkInfo({ @@ -680,6 +695,144 @@ }) this.resizeObserve.observe(canvas) }, + relasePage () { + const data = new FormData() + data.append('activeUser', this.user.username) + data.append('pageId', this.pageId) + navigator.sendBeacon('/api/page/releasePage', data) + }, + async lockStatsuPolling (type) { + const interval = 20 * 1000 // 节流,状态检查每20s一次 + if (this.lockCheckTimer === null) { + await this.checkLockStatus(type) + this.lockCheckTimer = setTimeout(() => { + clearTimeout(this.lockCheckTimer) + this.lockCheckTimer = null + }, interval) + } + }, + async checkLockStatus (type) { + try { + const status = await this.$store.dispatch('page/pageLockStatus', { pageId: this.pageId }) + if (status.isLock) { + if (this.lockNotify !== null) return true// 当前有弹窗,代表无权限 + const messageType = `${type}-${status.accessible ? 'valiad' : 'invaliad'}` + this.lockNotify = this.$bkNotify({ + title: '暂无编辑权限', + theme: 'warning', + delay: 0, + onClose: () => { + this.lockNotify = null + }, + message: this.getLockMessage(messageType, status.activeUser) + }) + return true + } else { // 未加锁,更新当前画布的加锁者为当前用户 + this.$store.dispatch('page/updatePageLock', { data: { + pageId: this.pageId + } }) + return false + } + } catch (error) { + throw Error({ + message: error + }) + } + }, + userText (text) { + const h = this.$createElement + return h('span', { + style: { + color: '#EA3636' + } + }, [text]) + }, + hpyerTextGenerator (text, handler) { + const h = this.$createElement + return h('span', { + style: { + cursor: 'pointer', + color: '#3a84ff' + }, + on: { + click: handler + } + }, [text]) + }, + getLockMessage (type, user) { + const h = this.$createElement + switch (type) { + case 'lock-invaliad': + return h('p', { + style: { + 'line-height': '26px' + } + }, [ + '当前画布正在被', + this.userText(user), + '编辑,您暂无编辑权限,如需操作请联系其退出编辑,如仅需查看页面最新状态,请直接', + this.hpyerTextGenerator('刷新页面', location.reload.bind(location)) + + ]) + case 'lock-valiad': + return h('p', { + style: { + 'line-height': '26px' + } + }, [ + '当前页面正在被', + this.userText(user), + '编辑,如需获取操作,可点击', + this.hpyerTextGenerator('获取权限', this.occupyPage.bind(this)), + ',如仅需查看页面最新状态,请直接', + this.hpyerTextGenerator('刷新页面', location.reload.bind(location)) + ]) + case 'taked-invaliad': + return h('p', { + style: { + 'line-height': '26px' + } + }, [ + '由于您长时间未操作,页面编辑权已被释放;当前页面正在被', + this.userText(user), + '编辑,如仍需操作请联系其退出,如仅需查看页面最新状态,请直接', + this.hpyerTextGenerator('刷新页面', location.reload.bind(location)) + ]) + case 'taked-valiad': + return h('p', { + style: { + 'line-height': '26px' + } + }, [ + '由于您长时间未操作,页面编辑权已被释放;当前页面正在被', + this.userText(user), + '编辑,如需获取操作,可点击', + this.hpyerTextGenerator('获取权限', this.occupyPage.bind(this)), + '获取权限,如仅需查看页面最新状态,请直接', + this.hpyerTextGenerator('刷新页面', location.reload.bind(location)) + ]) + } + }, + async occupyPage () { + try { + const resp = await this.$store.dispatch('page/occupyPage', { + data: { + pageId: this.pageId + } + }) + if (resp.activeUser === this.user.username) { + this.lockNotify && this.lockNotify.close() + this.$bkMessage({ + message: '抢占成功', + theme: 'success' + }) + } + } catch (error) { + throw Error({ + message: error + }) + } + }, isToolItemActive (item) { if (item.text === '快捷键') { return this.showQuickOperation === true @@ -713,11 +866,15 @@ this.$store.dispatch('page/detail', { pageId: this.pageId }), this.$store.dispatch('page/getList', { projectId: this.projectId }), this.$store.dispatch('project/detail', { projectId: this.projectId }), + this.$store.dispatch('page/pageLockStatus', { pageId: this.pageId }), this.$store.dispatch('route/getProjectPageRoute', { projectId: this.projectId, config: { fromCache: true } }), this.$store.dispatch('layout/getPageLayout', { pageId: this.pageId }), this.$store.dispatch('components/componentNameMap'), this.getAllGroupFuncs(this.projectId) ]) + + await this.lockStatsuPolling('lock') // 处理加锁逻辑 + await this.getAllVariable({ projectId: this.projectId, pageCode: pageDetail.pageCode, effectiveRange: 0 }) // update targetdata const content = pageDetail.content @@ -1182,7 +1339,10 @@ /** * 清空页面已拖拽的元素 */ - handleClearAll () { + async handleClearAll () { + const isLock = await this.checkLockStatus('lock') + if (isLock) return // 如果被锁,不可清空 + const me = this me.$bkInfo({ title: '确定清空所有组件元素?', @@ -1319,6 +1479,9 @@ }, async handleSave (callBack, from) { + const isLock = await this.checkLockStatus('lock') + if (isLock) return // 如果被锁,不可保存 + if (this.isSaving) { return } @@ -1386,7 +1549,11 @@ const { modifiers, prop, type, val, valType } = dir function generateUseInfo (variableId) { const useInfo = { type, componentId: id, prop, modifiers, val } - const useInfos = usedVariableMap[variableId] || (usedVariableMap[variableId] = [], usedVariableMap[variableId]) + // const useInfos = usedVariableMap[variableId] || (usedVariableMap[variableId] = [], usedVariableMap[variableId]) + if (!usedVariableMap[variableId]) { + usedVariableMap[variableId] = [] + } + const useInfos = usedVariableMap[variableId] useInfos.push(useInfo) } if (val !== '' && valType === 'variable') { diff --git a/paas-ce/lesscode/lib/client/src/views/project/function-manage.vue b/paas-ce/lesscode/lib/client/src/views/project/function-manage.vue index 602a29fa9..ef34277e1 100644 --- a/paas-ce/lesscode/lib/client/src/views/project/function-manage.vue +++ b/paas-ce/lesscode/lib/client/src/views/project/function-manage.vue @@ -324,13 +324,12 @@ this.$refs.func.validate().then((postData) => { if (!postData) return this.funcObj.loading = true - const h = this.$createElement if (!postData.projectId) { postData.projectId = this.projectId } const varWhere = { projectId: this.projectId, effectiveRange: 0 } - const add = () => this.addFunc({ groupId: this.curGroupId, func: postData, h, varWhere }) - const edit = () => this.editFunc({ groupId: this.curGroupId, func: postData, h, varWhere }) + const add = () => this.addFunc({ groupId: this.curGroupId, func: postData, varWhere }) + const edit = () => this.editFunc({ groupId: this.curGroupId, func: postData, varWhere }) const curMethod = this.funcObj.isEdit ? edit : add curMethod().then((res) => { @@ -594,8 +593,7 @@ bulkAddFuncFromApi (funcList) { const varWhere = { projectId: this.projectId, effectiveRange: 0 } - const h = this.$createElement - const postData = { groupId: this.curGroupId, funcList, h, varWhere } + const postData = { groupId: this.curGroupId, funcList, varWhere } return this.bulkAddFunc(postData).then((res) => { if (!res) return const projectId = this.$route.params.projectId diff --git a/paas-ce/lesscode/lib/client/src/views/system/health.vue b/paas-ce/lesscode/lib/client/src/views/system/health.vue new file mode 100644 index 000000000..47c927353 --- /dev/null +++ b/paas-ce/lesscode/lib/client/src/views/system/health.vue @@ -0,0 +1,32 @@ + + + diff --git a/paas-ce/lesscode/lib/client/static/monaco-editor/min-maps/vs/base/worker/workerMain.js.map b/paas-ce/lesscode/lib/client/static/monaco-editor/min-maps/vs/base/worker/workerMain.js.map new file mode 100644 index 000000000..ef32b7a5b --- /dev/null +++ b/paas-ce/lesscode/lib/client/static/monaco-editor/min-maps/vs/base/worker/workerMain.js.map @@ -0,0 +1 @@ +{"version":3,"sources":["out-editor/vs/base/worker/fake","out-editor/vs/base/worker/vs/loader.js","out-editor/vs/base/worker/file:/C:/dev/microsoft/vscode/out-editor-src/vs/base/common/diff/diffChange.ts","out-editor/vs/base/worker/file:/C:/dev/microsoft/vscode/out-editor-src/vs/base/common/errors.ts","out-editor/vs/base/worker/file:/C:/dev/microsoft/vscode/out-editor-src/vs/base/common/iterator.ts","out-editor/vs/base/worker/file:/C:/dev/microsoft/vscode/out-editor-src/vs/base/common/keyCodes.ts","out-editor/vs/base/worker/file:/C:/dev/microsoft/vscode/out-editor-src/vs/base/common/lifecycle.ts","out-editor/vs/base/worker/file:/C:/dev/microsoft/vscode/out-editor-src/vs/base/common/linkedList.ts","out-editor/vs/base/worker/file:/C:/dev/microsoft/vscode/out-editor-src/vs/base/common/platform.ts","out-editor/vs/base/worker/file:/C:/dev/microsoft/vscode/out-editor-src/vs/base/common/process.ts","out-editor/vs/base/worker/file:/C:/dev/microsoft/vscode/out-editor-src/vs/base/common/path.ts","out-editor/vs/base/worker/file:/C:/dev/microsoft/vscode/out-editor-src/vs/base/common/stopwatch.ts","out-editor/vs/base/worker/file:/C:/dev/microsoft/vscode/out-editor-src/vs/base/common/event.ts","out-editor/vs/base/worker/file:/C:/dev/microsoft/vscode/out-editor-src/vs/base/common/cancellation.ts","out-editor/vs/base/worker/file:/C:/dev/microsoft/vscode/out-editor-src/vs/base/common/strings.ts","out-editor/vs/base/worker/file:/C:/dev/microsoft/vscode/out-editor-src/vs/base/common/hash.ts","out-editor/vs/base/worker/file:/C:/dev/microsoft/vscode/out-editor-src/vs/base/common/diff/diff.ts","out-editor/vs/base/worker/file:/C:/dev/microsoft/vscode/out-editor-src/vs/base/common/types.ts","out-editor/vs/base/worker/file:/C:/dev/microsoft/vscode/out-editor-src/vs/base/common/uint.ts","out-editor/vs/base/worker/file:/C:/dev/microsoft/vscode/out-editor-src/vs/base/common/uri.ts","out-editor/vs/base/worker/file:/C:/dev/microsoft/vscode/out-editor-src/vs/base/common/worker/simpleWorker.ts","out-editor/vs/base/worker/file:/C:/dev/microsoft/vscode/out-editor-src/vs/editor/common/core/characterClassifier.ts","out-editor/vs/base/worker/file:/C:/dev/microsoft/vscode/out-editor-src/vs/editor/common/core/position.ts","out-editor/vs/base/worker/file:/C:/dev/microsoft/vscode/out-editor-src/vs/editor/common/core/range.ts","out-editor/vs/base/worker/file:/C:/dev/microsoft/vscode/out-editor-src/vs/editor/common/core/selection.ts","out-editor/vs/base/worker/file:/C:/dev/microsoft/vscode/out-editor-src/vs/editor/common/core/token.ts","out-editor/vs/base/worker/file:/C:/dev/microsoft/vscode/out-editor-src/vs/editor/common/diff/diffComputer.ts","out-editor/vs/base/worker/file:/C:/dev/microsoft/vscode/out-editor-src/vs/editor/common/model/wordHelper.ts","out-editor/vs/base/worker/file:/C:/dev/microsoft/vscode/out-editor-src/vs/editor/common/modes/linkComputer.ts","out-editor/vs/base/worker/file:/C:/dev/microsoft/vscode/out-editor-src/vs/editor/common/modes/supports/inplaceReplaceSupport.ts","out-editor/vs/base/worker/file:/C:/dev/microsoft/vscode/out-editor-src/vs/editor/common/standalone/standaloneEnums.ts","out-editor/vs/base/worker/file:/C:/dev/microsoft/vscode/out-editor-src/vs/editor/common/standalone/standaloneBase.ts","out-editor/vs/base/worker/file:/C:/dev/microsoft/vscode/out-editor-src/vs/editor/common/viewModel/prefixSumComputer.ts","out-editor/vs/base/worker/file:/C:/dev/microsoft/vscode/out-editor-src/vs/editor/common/model/mirrorTextModel.ts","out-editor/vs/base/worker/file:/C:/dev/microsoft/vscode/out-editor-src/vs/editor/common/services/editorSimpleWorker.ts","out-editor/vs/base/worker/file:/C:/dev/microsoft/vscode/out-editor-src/vs/base/worker/workerMain.ts"],"sourcesContent":["}).call(this);","/*---------------------------------------------------------------------------------------------\n * Copyright (c) Microsoft Corporation. All rights reserved.\n * Licensed under the MIT License. See License.txt in the project root for license information.\n *--------------------------------------------------------------------------------------------*/\n'use strict';\n/*---------------------------------------------------------------------------------------------\n * Copyright (c) Microsoft Corporation. All rights reserved.\n * Licensed under the MIT License. See License.txt in the project root for license information.\n *--------------------------------------------------------------------------------------------*/\n/*---------------------------------------------------------------------------------------------\n *---------------------------------------------------------------------------------------------\n *---------------------------------------------------------------------------------------------\n *---------------------------------------------------------------------------------------------\n *---------------------------------------------------------------------------------------------\n * Please make sure to make edits in the .ts file at https://github.com/microsoft/vscode-loader/\n *---------------------------------------------------------------------------------------------\n *---------------------------------------------------------------------------------------------\n *---------------------------------------------------------------------------------------------\n *---------------------------------------------------------------------------------------------\n *--------------------------------------------------------------------------------------------*/\nvar _amdLoaderGlobal = this;\nvar _commonjsGlobal = typeof global === 'object' ? global : {};\nvar AMDLoader;\n(function (AMDLoader) {\n AMDLoader.global = _amdLoaderGlobal;\n var Environment = /** @class */ (function () {\n function Environment() {\n this._detected = false;\n this._isWindows = false;\n this._isNode = false;\n this._isElectronRenderer = false;\n this._isWebWorker = false;\n }\n Object.defineProperty(Environment.prototype, \"isWindows\", {\n get: function () {\n this._detect();\n return this._isWindows;\n },\n enumerable: false,\n configurable: true\n });\n Object.defineProperty(Environment.prototype, \"isNode\", {\n get: function () {\n this._detect();\n return this._isNode;\n },\n enumerable: false,\n configurable: true\n });\n Object.defineProperty(Environment.prototype, \"isElectronRenderer\", {\n get: function () {\n this._detect();\n return this._isElectronRenderer;\n },\n enumerable: false,\n configurable: true\n });\n Object.defineProperty(Environment.prototype, \"isWebWorker\", {\n get: function () {\n this._detect();\n return this._isWebWorker;\n },\n enumerable: false,\n configurable: true\n });\n Environment.prototype._detect = function () {\n if (this._detected) {\n return;\n }\n this._detected = true;\n this._isWindows = Environment._isWindows();\n this._isNode = (typeof module !== 'undefined' && !!module.exports);\n this._isElectronRenderer = (typeof process !== 'undefined' && typeof process.versions !== 'undefined' && typeof process.versions.electron !== 'undefined' && process.type === 'renderer');\n this._isWebWorker = (typeof AMDLoader.global.importScripts === 'function');\n };\n Environment._isWindows = function () {\n if (typeof navigator !== 'undefined') {\n if (navigator.userAgent && navigator.userAgent.indexOf('Windows') >= 0) {\n return true;\n }\n }\n if (typeof process !== 'undefined') {\n return (process.platform === 'win32');\n }\n return false;\n };\n return Environment;\n }());\n AMDLoader.Environment = Environment;\n})(AMDLoader || (AMDLoader = {}));\n/*---------------------------------------------------------------------------------------------\n * Copyright (c) Microsoft Corporation. All rights reserved.\n * Licensed under the MIT License. See License.txt in the project root for license information.\n *--------------------------------------------------------------------------------------------*/\nvar AMDLoader;\n(function (AMDLoader) {\n var LoaderEvent = /** @class */ (function () {\n function LoaderEvent(type, detail, timestamp) {\n this.type = type;\n this.detail = detail;\n this.timestamp = timestamp;\n }\n return LoaderEvent;\n }());\n AMDLoader.LoaderEvent = LoaderEvent;\n var LoaderEventRecorder = /** @class */ (function () {\n function LoaderEventRecorder(loaderAvailableTimestamp) {\n this._events = [new LoaderEvent(1 /* LoaderAvailable */, '', loaderAvailableTimestamp)];\n }\n LoaderEventRecorder.prototype.record = function (type, detail) {\n this._events.push(new LoaderEvent(type, detail, AMDLoader.Utilities.getHighPerformanceTimestamp()));\n };\n LoaderEventRecorder.prototype.getEvents = function () {\n return this._events;\n };\n return LoaderEventRecorder;\n }());\n AMDLoader.LoaderEventRecorder = LoaderEventRecorder;\n var NullLoaderEventRecorder = /** @class */ (function () {\n function NullLoaderEventRecorder() {\n }\n NullLoaderEventRecorder.prototype.record = function (type, detail) {\n // Nothing to do\n };\n NullLoaderEventRecorder.prototype.getEvents = function () {\n return [];\n };\n NullLoaderEventRecorder.INSTANCE = new NullLoaderEventRecorder();\n return NullLoaderEventRecorder;\n }());\n AMDLoader.NullLoaderEventRecorder = NullLoaderEventRecorder;\n})(AMDLoader || (AMDLoader = {}));\n/*---------------------------------------------------------------------------------------------\n * Copyright (c) Microsoft Corporation. All rights reserved.\n * Licensed under the MIT License. See License.txt in the project root for license information.\n *--------------------------------------------------------------------------------------------*/\nvar AMDLoader;\n(function (AMDLoader) {\n var Utilities = /** @class */ (function () {\n function Utilities() {\n }\n /**\n * This method does not take care of / vs \\\n */\n Utilities.fileUriToFilePath = function (isWindows, uri) {\n uri = decodeURI(uri).replace(/%23/g, '#');\n if (isWindows) {\n if (/^file:\\/\\/\\//.test(uri)) {\n // This is a URI without a hostname => return only the path segment\n return uri.substr(8);\n }\n if (/^file:\\/\\//.test(uri)) {\n return uri.substr(5);\n }\n }\n else {\n if (/^file:\\/\\//.test(uri)) {\n return uri.substr(7);\n }\n }\n // Not sure...\n return uri;\n };\n Utilities.startsWith = function (haystack, needle) {\n return haystack.length >= needle.length && haystack.substr(0, needle.length) === needle;\n };\n Utilities.endsWith = function (haystack, needle) {\n return haystack.length >= needle.length && haystack.substr(haystack.length - needle.length) === needle;\n };\n // only check for \"?\" before \"#\" to ensure that there is a real Query-String\n Utilities.containsQueryString = function (url) {\n return /^[^\\#]*\\?/gi.test(url);\n };\n /**\n * Does `url` start with http:// or https:// or file:// or / ?\n */\n Utilities.isAbsolutePath = function (url) {\n return /^((http:\\/\\/)|(https:\\/\\/)|(file:\\/\\/)|(\\/))/.test(url);\n };\n Utilities.forEachProperty = function (obj, callback) {\n if (obj) {\n var key = void 0;\n for (key in obj) {\n if (obj.hasOwnProperty(key)) {\n callback(key, obj[key]);\n }\n }\n }\n };\n Utilities.isEmpty = function (obj) {\n var isEmpty = true;\n Utilities.forEachProperty(obj, function () {\n isEmpty = false;\n });\n return isEmpty;\n };\n Utilities.recursiveClone = function (obj) {\n if (!obj || typeof obj !== 'object' || obj instanceof RegExp) {\n return obj;\n }\n if (!Array.isArray(obj) && Object.getPrototypeOf(obj) !== Object.prototype) {\n // only clone \"simple\" objects\n return obj;\n }\n var result = Array.isArray(obj) ? [] : {};\n Utilities.forEachProperty(obj, function (key, value) {\n if (value && typeof value === 'object') {\n result[key] = Utilities.recursiveClone(value);\n }\n else {\n result[key] = value;\n }\n });\n return result;\n };\n Utilities.generateAnonymousModule = function () {\n return '===anonymous' + (Utilities.NEXT_ANONYMOUS_ID++) + '===';\n };\n Utilities.isAnonymousModule = function (id) {\n return Utilities.startsWith(id, '===anonymous');\n };\n Utilities.getHighPerformanceTimestamp = function () {\n if (!this.PERFORMANCE_NOW_PROBED) {\n this.PERFORMANCE_NOW_PROBED = true;\n this.HAS_PERFORMANCE_NOW = (AMDLoader.global.performance && typeof AMDLoader.global.performance.now === 'function');\n }\n return (this.HAS_PERFORMANCE_NOW ? AMDLoader.global.performance.now() : Date.now());\n };\n Utilities.NEXT_ANONYMOUS_ID = 1;\n Utilities.PERFORMANCE_NOW_PROBED = false;\n Utilities.HAS_PERFORMANCE_NOW = false;\n return Utilities;\n }());\n AMDLoader.Utilities = Utilities;\n})(AMDLoader || (AMDLoader = {}));\n/*---------------------------------------------------------------------------------------------\n * Copyright (c) Microsoft Corporation. All rights reserved.\n * Licensed under the MIT License. See License.txt in the project root for license information.\n *--------------------------------------------------------------------------------------------*/\nvar AMDLoader;\n(function (AMDLoader) {\n function ensureError(err) {\n if (err instanceof Error) {\n return err;\n }\n var result = new Error(err.message || String(err) || 'Unknown Error');\n if (err.stack) {\n result.stack = err.stack;\n }\n return result;\n }\n AMDLoader.ensureError = ensureError;\n ;\n var ConfigurationOptionsUtil = /** @class */ (function () {\n function ConfigurationOptionsUtil() {\n }\n /**\n * Ensure configuration options make sense\n */\n ConfigurationOptionsUtil.validateConfigurationOptions = function (options) {\n function defaultOnError(err) {\n if (err.phase === 'loading') {\n console.error('Loading \"' + err.moduleId + '\" failed');\n console.error(err);\n console.error('Here are the modules that depend on it:');\n console.error(err.neededBy);\n return;\n }\n if (err.phase === 'factory') {\n console.error('The factory method of \"' + err.moduleId + '\" has thrown an exception');\n console.error(err);\n return;\n }\n }\n options = options || {};\n if (typeof options.baseUrl !== 'string') {\n options.baseUrl = '';\n }\n if (typeof options.isBuild !== 'boolean') {\n options.isBuild = false;\n }\n if (typeof options.paths !== 'object') {\n options.paths = {};\n }\n if (typeof options.config !== 'object') {\n options.config = {};\n }\n if (typeof options.catchError === 'undefined') {\n options.catchError = false;\n }\n if (typeof options.recordStats === 'undefined') {\n options.recordStats = false;\n }\n if (typeof options.urlArgs !== 'string') {\n options.urlArgs = '';\n }\n if (typeof options.onError !== 'function') {\n options.onError = defaultOnError;\n }\n if (!Array.isArray(options.ignoreDuplicateModules)) {\n options.ignoreDuplicateModules = [];\n }\n if (options.baseUrl.length > 0) {\n if (!AMDLoader.Utilities.endsWith(options.baseUrl, '/')) {\n options.baseUrl += '/';\n }\n }\n if (typeof options.cspNonce !== 'string') {\n options.cspNonce = '';\n }\n if (typeof options.preferScriptTags === 'undefined') {\n options.preferScriptTags = false;\n }\n if (!Array.isArray(options.nodeModules)) {\n options.nodeModules = [];\n }\n if (options.nodeCachedData && typeof options.nodeCachedData === 'object') {\n if (typeof options.nodeCachedData.seed !== 'string') {\n options.nodeCachedData.seed = 'seed';\n }\n if (typeof options.nodeCachedData.writeDelay !== 'number' || options.nodeCachedData.writeDelay < 0) {\n options.nodeCachedData.writeDelay = 1000 * 7;\n }\n if (!options.nodeCachedData.path || typeof options.nodeCachedData.path !== 'string') {\n var err = ensureError(new Error('INVALID cached data configuration, \\'path\\' MUST be set'));\n err.phase = 'configuration';\n options.onError(err);\n options.nodeCachedData = undefined;\n }\n }\n return options;\n };\n ConfigurationOptionsUtil.mergeConfigurationOptions = function (overwrite, base) {\n if (overwrite === void 0) { overwrite = null; }\n if (base === void 0) { base = null; }\n var result = AMDLoader.Utilities.recursiveClone(base || {});\n // Merge known properties and overwrite the unknown ones\n AMDLoader.Utilities.forEachProperty(overwrite, function (key, value) {\n if (key === 'ignoreDuplicateModules' && typeof result.ignoreDuplicateModules !== 'undefined') {\n result.ignoreDuplicateModules = result.ignoreDuplicateModules.concat(value);\n }\n else if (key === 'paths' && typeof result.paths !== 'undefined') {\n AMDLoader.Utilities.forEachProperty(value, function (key2, value2) { return result.paths[key2] = value2; });\n }\n else if (key === 'config' && typeof result.config !== 'undefined') {\n AMDLoader.Utilities.forEachProperty(value, function (key2, value2) { return result.config[key2] = value2; });\n }\n else {\n result[key] = AMDLoader.Utilities.recursiveClone(value);\n }\n });\n return ConfigurationOptionsUtil.validateConfigurationOptions(result);\n };\n return ConfigurationOptionsUtil;\n }());\n AMDLoader.ConfigurationOptionsUtil = ConfigurationOptionsUtil;\n var Configuration = /** @class */ (function () {\n function Configuration(env, options) {\n this._env = env;\n this.options = ConfigurationOptionsUtil.mergeConfigurationOptions(options);\n this._createIgnoreDuplicateModulesMap();\n this._createNodeModulesMap();\n this._createSortedPathsRules();\n if (this.options.baseUrl === '') {\n if (this.options.nodeRequire && this.options.nodeRequire.main && this.options.nodeRequire.main.filename && this._env.isNode) {\n var nodeMain = this.options.nodeRequire.main.filename;\n var dirnameIndex = Math.max(nodeMain.lastIndexOf('/'), nodeMain.lastIndexOf('\\\\'));\n this.options.baseUrl = nodeMain.substring(0, dirnameIndex + 1);\n }\n if (this.options.nodeMain && this._env.isNode) {\n var nodeMain = this.options.nodeMain;\n var dirnameIndex = Math.max(nodeMain.lastIndexOf('/'), nodeMain.lastIndexOf('\\\\'));\n this.options.baseUrl = nodeMain.substring(0, dirnameIndex + 1);\n }\n }\n }\n Configuration.prototype._createIgnoreDuplicateModulesMap = function () {\n // Build a map out of the ignoreDuplicateModules array\n this.ignoreDuplicateModulesMap = {};\n for (var i = 0; i < this.options.ignoreDuplicateModules.length; i++) {\n this.ignoreDuplicateModulesMap[this.options.ignoreDuplicateModules[i]] = true;\n }\n };\n Configuration.prototype._createNodeModulesMap = function () {\n // Build a map out of nodeModules array\n this.nodeModulesMap = Object.create(null);\n for (var _i = 0, _a = this.options.nodeModules; _i < _a.length; _i++) {\n var nodeModule = _a[_i];\n this.nodeModulesMap[nodeModule] = true;\n }\n };\n Configuration.prototype._createSortedPathsRules = function () {\n var _this = this;\n // Create an array our of the paths rules, sorted descending by length to\n // result in a more specific -> less specific order\n this.sortedPathsRules = [];\n AMDLoader.Utilities.forEachProperty(this.options.paths, function (from, to) {\n if (!Array.isArray(to)) {\n _this.sortedPathsRules.push({\n from: from,\n to: [to]\n });\n }\n else {\n _this.sortedPathsRules.push({\n from: from,\n to: to\n });\n }\n });\n this.sortedPathsRules.sort(function (a, b) {\n return b.from.length - a.from.length;\n });\n };\n /**\n * Clone current configuration and overwrite options selectively.\n * @param options The selective options to overwrite with.\n * @result A new configuration\n */\n Configuration.prototype.cloneAndMerge = function (options) {\n return new Configuration(this._env, ConfigurationOptionsUtil.mergeConfigurationOptions(options, this.options));\n };\n /**\n * Get current options bag. Useful for passing it forward to plugins.\n */\n Configuration.prototype.getOptionsLiteral = function () {\n return this.options;\n };\n Configuration.prototype._applyPaths = function (moduleId) {\n var pathRule;\n for (var i = 0, len = this.sortedPathsRules.length; i < len; i++) {\n pathRule = this.sortedPathsRules[i];\n if (AMDLoader.Utilities.startsWith(moduleId, pathRule.from)) {\n var result = [];\n for (var j = 0, lenJ = pathRule.to.length; j < lenJ; j++) {\n result.push(pathRule.to[j] + moduleId.substr(pathRule.from.length));\n }\n return result;\n }\n }\n return [moduleId];\n };\n Configuration.prototype._addUrlArgsToUrl = function (url) {\n if (AMDLoader.Utilities.containsQueryString(url)) {\n return url + '&' + this.options.urlArgs;\n }\n else {\n return url + '?' + this.options.urlArgs;\n }\n };\n Configuration.prototype._addUrlArgsIfNecessaryToUrl = function (url) {\n if (this.options.urlArgs) {\n return this._addUrlArgsToUrl(url);\n }\n return url;\n };\n Configuration.prototype._addUrlArgsIfNecessaryToUrls = function (urls) {\n if (this.options.urlArgs) {\n for (var i = 0, len = urls.length; i < len; i++) {\n urls[i] = this._addUrlArgsToUrl(urls[i]);\n }\n }\n return urls;\n };\n /**\n * Transform a module id to a location. Appends .js to module ids\n */\n Configuration.prototype.moduleIdToPaths = function (moduleId) {\n var isNodeModule = ((this.nodeModulesMap[moduleId] === true)\n || (this.options.amdModulesPattern instanceof RegExp && !this.options.amdModulesPattern.test(moduleId)));\n if (isNodeModule) {\n // This is a node module...\n if (this.isBuild()) {\n // ...and we are at build time, drop it\n return ['empty:'];\n }\n else {\n // ...and at runtime we create a `shortcut`-path\n return ['node|' + moduleId];\n }\n }\n var result = moduleId;\n var results;\n if (!AMDLoader.Utilities.endsWith(result, '.js') && !AMDLoader.Utilities.isAbsolutePath(result)) {\n results = this._applyPaths(result);\n for (var i = 0, len = results.length; i < len; i++) {\n if (this.isBuild() && results[i] === 'empty:') {\n continue;\n }\n if (!AMDLoader.Utilities.isAbsolutePath(results[i])) {\n results[i] = this.options.baseUrl + results[i];\n }\n if (!AMDLoader.Utilities.endsWith(results[i], '.js') && !AMDLoader.Utilities.containsQueryString(results[i])) {\n results[i] = results[i] + '.js';\n }\n }\n }\n else {\n if (!AMDLoader.Utilities.endsWith(result, '.js') && !AMDLoader.Utilities.containsQueryString(result)) {\n result = result + '.js';\n }\n results = [result];\n }\n return this._addUrlArgsIfNecessaryToUrls(results);\n };\n /**\n * Transform a module id or url to a location.\n */\n Configuration.prototype.requireToUrl = function (url) {\n var result = url;\n if (!AMDLoader.Utilities.isAbsolutePath(result)) {\n result = this._applyPaths(result)[0];\n if (!AMDLoader.Utilities.isAbsolutePath(result)) {\n result = this.options.baseUrl + result;\n }\n }\n return this._addUrlArgsIfNecessaryToUrl(result);\n };\n /**\n * Flag to indicate if current execution is as part of a build.\n */\n Configuration.prototype.isBuild = function () {\n return this.options.isBuild;\n };\n /**\n * Test if module `moduleId` is expected to be defined multiple times\n */\n Configuration.prototype.isDuplicateMessageIgnoredFor = function (moduleId) {\n return this.ignoreDuplicateModulesMap.hasOwnProperty(moduleId);\n };\n /**\n * Get the configuration settings for the provided module id\n */\n Configuration.prototype.getConfigForModule = function (moduleId) {\n if (this.options.config) {\n return this.options.config[moduleId];\n }\n };\n /**\n * Should errors be caught when executing module factories?\n */\n Configuration.prototype.shouldCatchError = function () {\n return this.options.catchError;\n };\n /**\n * Should statistics be recorded?\n */\n Configuration.prototype.shouldRecordStats = function () {\n return this.options.recordStats;\n };\n /**\n * Forward an error to the error handler.\n */\n Configuration.prototype.onError = function (err) {\n this.options.onError(err);\n };\n return Configuration;\n }());\n AMDLoader.Configuration = Configuration;\n})(AMDLoader || (AMDLoader = {}));\n/*---------------------------------------------------------------------------------------------\n * Copyright (c) Microsoft Corporation. All rights reserved.\n * Licensed under the MIT License. See License.txt in the project root for license information.\n *--------------------------------------------------------------------------------------------*/\nvar AMDLoader;\n(function (AMDLoader) {\n /**\n * Load `scriptSrc` only once (avoid multiple