build(通用功能): 前端拆分构建产物,减少打包体积

This commit is contained in:
baiqi 2023-05-29 11:52:29 +08:00 committed by fit2-zhao
parent 1045257972
commit c275ee1567
119 changed files with 35960 additions and 378 deletions

View File

@ -5,7 +5,8 @@
"scripts": {
"api": "vue-cli-service serve",
"build": "vue-cli-service build",
"lint": "vue-cli-service lint"
"lint": "vue-cli-service lint",
"report": "NODE_ENV=analyze vue-cli-service build"
},
"dependencies": {
"@ckeditor/ckeditor5-build-classic": "^18.0.0",
@ -78,6 +79,7 @@
"@vue/cli-plugin-babel": "^5.0.7",
"@vue/cli-plugin-eslint": "^5.0.7",
"@vue/cli-service": "^5.0.7",
"add-asset-html-webpack-plugin": "^6.0.0",
"core-js": "^3.19.1",
"eslint": "^7.32.0",
"eslint-plugin-vue": "^7.20.0",
@ -85,7 +87,9 @@
"sass": "^1.43.4",
"sass-loader": "^10.1.1",
"svg-sprite-loader": "^6.0.11",
"vue-template-compiler": "^2.7.3"
"vue-template-compiler": "^2.7.3",
"webpack-bundle-analyzer": "^4.8.0",
"webpack-cli": "^5.1.1"
},
"eslintConfig": {
"root": true,

View File

@ -6,7 +6,23 @@
<meta name="viewport" content="width=device-width,initial-scale=1.0" />
<link rel="icon" href="<%= BASE_URL %>favicon.ico" />
<title><%= htmlWebpackPlugin.options.title %></title>
<% if (process.env.NODE_ENV==='development' ) { %>
<link rel="stylesheet" href="http://localhost:3000/js/dev/element-ui/element-ui.css" />
<script src="http://localhost:3000/js/dev/vue.js"></script>
<script src="http://localhost:3000/js/dev/element-ui/element-ui.js"></script>
<script src="http://localhost:3000/js/dev/vue-router.js"></script>
<script src="http://localhost:3000/js/prd/vue-shepherd.min.js"></script>
<script src="http://localhost:3000/js/prd/mavon-editor.js"></script>
<% } else { %>
<link rel="stylesheet" href="<%= BASE_URL %>js/prd/element-ui/element-ui.min.css" />
<script src="<%= BASE_URL %>js/prd/vue.min.js"></script>
<script src="<%= BASE_URL %>js/prd/element-ui/element-ui.min.js"></script>
<script src="<%= BASE_URL %>js/prd/vue-router.min.js"></script>
<script src="<%= BASE_URL %>js/prd/vue-shepherd.min.js"></script>
<script src="<%= BASE_URL %>js/prd/mavon-editor.js"></script>
<% } %>
</head>
<body>
<noscript>
<strong

View File

@ -115,13 +115,14 @@ import { getUUID } from 'metersphere-frontend/src/utils';
import { hasPermission } from 'metersphere-frontend/src/utils/permission';
import { PROJECT_ID, WORKSPACE_ID } from 'metersphere-frontend/src/utils/constants';
import { buildTree } from 'metersphere-frontend/src/model/NodeTree';
import {diff} from 'jsondiffpatch';
import { getScenarioById, getScenarioByTrash } from '@/api/scenario';
import { getOwnerProjectIds, getProject, getProjectConfig } from '@/api/project';
import { getModuleByProjectId } from '@/api/scenario-module';
import { useApiStore } from '@/store';
const store = useApiStore();
const jsondiffpatch = require('jsondiffpatch');
export default {
name: 'ApiAutomation',
components: {
@ -484,7 +485,7 @@ export default {
}
let delta;
if (v1 && v3) {
delta = jsondiffpatch.diff(JSON.parse(JSON.stringify(v1)), JSON.parse(JSON.stringify(v3)));
delta = diff(JSON.parse(JSON.stringify(v1)), JSON.parse(JSON.stringify(v3)));
}
if (delta) {
this.isSave = true;

View File

@ -586,7 +586,6 @@ import { getDefaultVersion, setLatestVersionById } from 'metersphere-frontend/sr
const store = useApiStore();
let jsonPath = require('jsonpath');
export default {
name: 'EditApiScenario',
props: {

View File

@ -318,8 +318,8 @@
import { getApiScenarioEnv } from '@/api/scenario';
import { API_STATUS, PRIORITY } from '../../../definition/model/JsonData';
import { parseEnvironment } from '@/business/environment/model/EnvironmentModel';
import { ELEMENT_TYPE, STEP } from '../Setting';
import { exportPdf, getUUID, strMapToObj } from 'metersphere-frontend/src/utils';
import { STEP } from '../Setting';
import { getUUID, strMapToObj } from 'metersphere-frontend/src/utils';
import { getCurrentProjectID } from 'metersphere-frontend/src/utils/token';
import { hasLicense } from 'metersphere-frontend/src/utils/permission';
import OutsideClick from '../common/outside-click';
@ -328,7 +328,7 @@ import { buttons, setComponent } from '../menu/Menu';
import MsContainer from 'metersphere-frontend/src/components/MsContainer';
import MsMainContainer from 'metersphere-frontend/src/components/MsMainContainer';
import MsAsideContainer from 'metersphere-frontend/src/components/MsAsideContainer';
import html2canvas from 'html2canvas';
// import html2canvas from 'html2canvas';
import { getEnvironmentByProjectId } from 'metersphere-frontend/src/api/environment';
import { useApiStore } from '@/store';
import { getPluginList } from '@/api/plugin';
@ -1263,18 +1263,18 @@ export default {
item.checkBox = this.isBatchProcess;
});
},
handleExport() {
let name = this.$t('commons.report_statistics.test_case_analysis');
this.$nextTick(function () {
setTimeout(() => {
html2canvas(document.getElementById('reportAnalysis'), {
scale: 2,
}).then(function (canvas) {
exportPdf(name, [canvas]);
});
}, 1000);
});
},
// handleExport() {
// let name = this.$t('commons.report_statistics.test_case_analysis');
// this.$nextTick(function () {
// setTimeout(() => {
// html2canvas(document.getElementById('reportAnalysis'), {
// scale: 2,
// }).then(function (canvas) {
// exportPdf(name, [canvas]);
// });
// }, 1000);
// });
// },
stop() {
this.debugLoading = false;
this.$emit('stop');

View File

@ -212,12 +212,12 @@ import BatchAddParameter from '../../../definition/components/basis/BatchAddPara
import { KeyValue } from '../../../definition/model/ApiTestModel';
import { REQUEST_HEADERS } from 'metersphere-frontend/src/utils/constants';
import {diff} from 'jsondiffpatch';
import MsTable from 'metersphere-frontend/src/components/table/MsTable';
import MsTableColumn from 'metersphere-frontend/src/components/table/MsTableColumn';
import { getCustomTableHeader, getCustomTableWidth } from 'metersphere-frontend/src/utils/tableUtils';
import VariableImport from '@/business/automation/scenario/variable/VariableImport';
const jsondiffpatch = require('jsondiffpatch');
export default {
name: 'MsVariableList',
@ -494,8 +494,8 @@ export default {
this.selectType = 'CONSTANT';
this.editData = {};
if (
jsondiffpatch.diff(JSON.parse(JSON.stringify(this.variables)), this.variablesOld) ||
jsondiffpatch.diff(JSON.parse(JSON.stringify(this.headers)), this.headersOld)
diff(JSON.parse(JSON.stringify(this.variables)), this.variablesOld) ||
diff(JSON.parse(JSON.stringify(this.headers)), this.headersOld)
) {
this.$emit('setVariables', saveVariables, this.headers);
}

View File

@ -24,5 +24,3 @@ export default {
},
};
</script>
<style scoped></style>

View File

@ -12,10 +12,24 @@
<script>
import { formatJson, formatXml } from 'metersphere-frontend/src/utils/format-utils';
import toDiffableHtml from 'diffable-html';
import editor from 'vue2-ace-editor';
import 'brace/ext/language_tools'; //language extension prerequisite...
import 'brace/mode/text';
import 'brace/mode/json';
import 'brace/mode/xml';
import 'brace/mode/html';
import 'brace/mode/java';
import 'brace/mode/python';
import 'brace/mode/sql';
import 'brace/mode/javascript';
import 'brace/mode/yaml';
import 'brace/theme/chrome';
import 'brace/theme/eclipse';
import 'brace/snippets/javascript'; //snippet
export default {
name: 'MsCodeEdit',
components: { editor: require('vue2-ace-editor') },
components: { editor },
data() {
return {
formatData: '',
@ -78,12 +92,21 @@ export default {
}
},
editorInit: function (editor) {
require('brace/ext/language_tools'); //language extension prerequisite...
this.modes.forEach((mode) => {
require('brace/mode/' + mode); //language
});
require('brace/theme/' + this.theme);
require('brace/snippets/javascript'); //snippet
// require('brace/ext/language_tools'); //language extension prerequisite...
// require('brace/mode/text');
// require('brace/mode/json');
// require('brace/mode/xml');
// require('brace/mode/html');
// require('brace/mode/java');
// require('brace/mode/python');
// require('brace/mode/sql');
// require('brace/mode/javascript');
// require('brace/mode/yaml');
// // this.modes.forEach((mode) => {
// // require('brace/mode/' + mode); //language
// // });
// require('brace/theme/' + this.theme);
// require('brace/snippets/javascript'); //snippet
if (this.readOnly) {
editor.setReadOnly(true);
}

View File

@ -15,6 +15,8 @@
</template>
<script>
import Vue from 'vue'
import JsonPathPicker from 'vue-jsonpath-picker';
import MsDrawer from 'metersphere-frontend/src/components/MsDrawer';
import MsInstructionsIcon from 'metersphere-frontend/src/components/MsInstructionsIcon';
@ -46,7 +48,7 @@ const clickoutside = {
delete el.__vueClickOutside__;
},
};
Vue.use(JsonPathPicker)
export default {
name: 'MsApiJsonpathSuggest',
components: { MsInstructionsIcon, MsDrawer },

View File

@ -26,8 +26,9 @@
</template>
<script>
const jsondiffpatch = require('jsondiffpatch');
const formattersHtml = jsondiffpatch.formatters.html;
import {formatters, diff} from 'jsondiffpatch';
const formattersHtml = formatters.html;
export default {
name: 'MsHistoryDetail',
components: {},
@ -55,10 +56,10 @@ export default {
methods: {
getDiff(v1, v2) {
if (this.detail.columnName === 'request' && v1 && v2) {
let delta = jsondiffpatch.diff(JSON.parse(JSON.stringify(v1)), JSON.parse(JSON.stringify(v2)));
let delta = diff(JSON.parse(JSON.stringify(v1)), JSON.parse(JSON.stringify(v2)));
return formattersHtml.format(delta, JSON.parse(JSON.stringify(v1)));
}
let delta = jsondiffpatch.diff(v1, v2);
let delta = diff(v1, v2);
return formattersHtml.format(delta, v1);
},
handleClose() {

View File

@ -107,9 +107,9 @@
<script>
import MsJsonCodeEdit from './json-view/ComparedEditor';
import MsApiKeyValueDetail from './common/ApiKeyValueDetail';
import {formatters, diff} from 'jsondiffpatch';
const jsondiffpatch = require('jsondiffpatch');
const formattersHtml = jsondiffpatch.formatters.html;
const formattersHtml = formatters.html;
export default {
name: 'MsApiHttpRequestParams',
@ -180,7 +180,7 @@ export default {
this.reloadCodeEdit();
},
getDiff(v1, v2) {
let delta = jsondiffpatch.diff(v1, v2);
let delta = diff(v1, v2);
return formattersHtml.format(delta, v1);
},
reloadCodeEdit() {

View File

@ -42,9 +42,9 @@
<script>
import MsApiKeyValueDetail from './common/ApiKeyValueDetail';
import {formatters, diff} from 'jsondiffpatch';
const jsondiffpatch = require('jsondiffpatch');
const formattersHtml = jsondiffpatch.formatters.html;
const formattersHtml = formatters.html;
export default {
name: 'MsApiJdbcParameters',
@ -96,7 +96,7 @@ export default {
computed: {},
methods: {
getDiff(v1, v2) {
let delta = jsondiffpatch.diff(v1, v2);
let delta = diff(v1, v2);
return formattersHtml.format(delta, v1);
},
},

View File

@ -80,9 +80,9 @@
<script>
import MsJsonCodeEdit from './json-view/ComparedEditor';
import MsApiKeyValueDetail from './common/ApiKeyValueDetail';
import {formatters, diff} from 'jsondiffpatch';
const jsondiffpatch = require('jsondiffpatch');
const formattersHtml = jsondiffpatch.formatters.html;
const formattersHtml = formatters.html;
export default {
name: 'MsApiTcpParameters',
@ -161,7 +161,7 @@ export default {
},
methods: {
getDiff(v1, v2) {
let delta = jsondiffpatch.diff(v1, v2);
let delta = diff(v1, v2);
return formattersHtml.format(delta, v1);
},
},

View File

@ -147,9 +147,9 @@
<script>
import MsJsonCodeEdit from './json-view/ComparedEditor';
import {formatters, diff} from 'jsondiffpatch';
const jsondiffpatch = require('jsondiffpatch');
const formattersHtml = jsondiffpatch.formatters.html;
const formattersHtml = formatters.html;
export default {
name: 'EnvironmentEditParams',
@ -218,10 +218,10 @@ export default {
},
getDiff(v1, v2) {
if (typeof v1 === 'string' && typeof v2 === 'string' && v1.indexOf('{') !== -1 && v2.indexOf('{') !== -1) {
let delta = jsondiffpatch.diff(JSON.parse(v1), JSON.parse(v2));
let delta = diff(JSON.parse(v1), JSON.parse(v2));
return formattersHtml.format(delta, delta);
} else {
let delta = jsondiffpatch.diff(v1, v2);
let delta = diff(v1, v2);
return formattersHtml.format(delta, v1);
}
},

View File

@ -2,7 +2,6 @@ import Vue from 'vue';
import VueI18n from 'vue-i18n';
Vue.use(VueI18n);
// 直接加载翻译的语言文件
const LOADED_LANGUAGES = ['zh-CN', 'zh-TW', 'en-US'];
const LANG_FILES = require.context('./lang', true, /\.js$/);

View File

@ -1,4 +1,4 @@
import el from 'element-ui/lib/locale/lang/en';
import el from 'metersphere-frontend/src/i18n/lang/ele-en-US';
import fu from 'fit2cloud-ui/src/locale/lang/en_US'; // 加载fit2cloud的内容
import mf from 'metersphere-frontend/src/i18n/lang/en-US';

View File

@ -1,4 +1,4 @@
import el from 'element-ui/lib/locale/lang/zh-CN'; // 加载element的内容
import el from 'metersphere-frontend/src/i18n/lang/ele-zh-CN'; // 加载element的内容
import fu from 'fit2cloud-ui/src/locale/lang/zh-CN'; // 加载fit2cloud的内容
import mf from 'metersphere-frontend/src/i18n/lang/zh-CN';

View File

@ -1,4 +1,4 @@
import el from 'element-ui/lib/locale/lang/zh-TW';
import el from 'metersphere-frontend/src/i18n/lang/ele-zh-TW';
import fu from 'fit2cloud-ui/src/locale/lang/zh-TW'; // 加载fit2cloud的内容
import mf from 'metersphere-frontend/src/i18n/lang/zh-TW';

View File

@ -15,11 +15,8 @@ import filters from 'metersphere-frontend/src/filters';
import 'metersphere-frontend/src/router/permission';
import chart from 'metersphere-frontend/src/chart';
import VueFab from 'vue-float-action-button';
import JSONPathPicker from 'vue-jsonpath-picker';
import VueClipboard from 'vue-clipboard2';
import formCreate from '@form-create/element-ui';
import mavonEditor from 'mavon-editor';
import 'mavon-editor/dist/css/index.css';
// import formCreate from '@form-create/element-ui';
import VuePapaParse from 'vue-papa-parse';
import VueShepherd from 'vue-shepherd'; // 新手引导
import 'metersphere-frontend/src/assets/shepherd/shepherd-theme.css';
@ -43,9 +40,8 @@ Vue.use(PiniaVuePlugin);
Vue.use(chart);
Vue.use(VueClipboard);
Vue.use(VueFab);
Vue.use(JSONPathPicker);
Vue.use(mavonEditor);
Vue.use(formCreate);
// Vue.use(JSONPathPicker);
// Vue.use(formCreate);
Vue.use(VuePapaParse);
Vue.use(VueShepherd);

View File

@ -6,6 +6,10 @@
<meta name="viewport" content="width=device-width,initial-scale=1.0" />
<link rel="shortcut icon" href="<%= BASE_URL %>favicon.ico" />
<title>MeterSphere Api Document</title>
<link rel="stylesheet" href="<%= BASE_URL %>js/prd/element-ui/element-ui.min.css" />
<script src="<%= BASE_URL %>js/prd/vue.min.js"></script>
<script src="<%= BASE_URL %>js/prd/element-ui/element-ui.min.js"></script>
<script src="<%= BASE_URL %>js/prd/mavon-editor.js"></script>
</head>
<body>
<div id="shareDocument"></div>

View File

@ -5,6 +5,9 @@
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<meta name="viewport" content="width=device-width,initial-scale=1.0" />
<link rel="shortcut icon" href="<%= BASE_URL %>favicon.ico" />
<link rel="stylesheet" href="<%= BASE_URL %>js/prd/element-ui/element-ui.min.css" />
<script src="<%= BASE_URL %>js/prd/vue.min.js"></script>
<script src="<%= BASE_URL %>js/prd/element-ui/element-ui.min.js"></script>
</head>
<body>
<div id="shareApiReport"></div>

View File

@ -1,5 +1,6 @@
const path = require('path');
const { name } = require('./package');
const BundleAnalyzerPlugin = require('webpack-bundle-analyzer').BundleAnalyzerPlugin;
function resolve(dir) {
return path.join(__dirname, dir);
@ -51,6 +52,9 @@ module.exports = {
resolve: {
alias: {
'@': resolve('src'),
'mockjs': resolve('node_modules/mockjs'),
'vue-i18n': resolve('node_modules/vue-i18n'),
'jsondiffpatch': resolve('node_modules/jsondiffpatch'),
},
},
output: {
@ -62,6 +66,96 @@ module.exports = {
filename: `js/${name}-[name].[contenthash:8].js`,
chunkFilename: `js/${name}-[name].[contenthash:8].js`,
},
externals: {
vue: 'Vue',
'vue-router': 'VueRouter',
// 'echarts': 'echarts',
// 'echarts/core': 'echarts', // TODO:外链使用的话需要改造导入及 vue-echarts 的源码
// brace: 'brace', // TODO:暂时未发现能外链的方法本体包未提供cdn 外链形式的包
'element-ui': 'ELEMENT',
'mavon-editor': 'MavonEditor',
'vue-shepherd': 'VueShepherd',
},
optimization: {
splitChunks: {
cacheGroups: {
'chunk-vendors': {
test: /[\\/]node_modules[\\/]/,
name: 'chunk-vendors',
priority: 1,
minChunks: 3,
chunks: 'all',
},
'chunk-common': {
test: /[\\/]src[\\/]/,
name: 'chunk-common',
priority: 1,
minChunks: 5,
chunks: 'all',
},
html2canvas: {
test: /[\\/]html2canvas[\\/]/,
name: 'html2canvas',
priority: 2,
chunks: 'all',
},
fortawesome: {
test: /[\\/]@fortawesome[\\/]/,
name: 'fortawesome',
priority: 2,
chunks: 'all',
},
'el-tree-transfer': {
test: /[\\/]el-tree-transfer[\\/]/,
name: 'el-tree-transfer',
priority: 2,
chunks: 'all',
},
pinia: {
test: /[\\/]pinia[\\/]/,
name: 'pinia',
priority: 3,
chunks: 'all',
},
brace: {
test: /[\\/]brace[\\/]/,
name: 'brace',
priority: 3,
chunks: 'all',
},
echarts: {
test: /[\\/](echarts|zrender)[\\/]/,
name: 'echarts',
priority: 3,
chunks: 'all',
},
jspdf: {
test: /[\\/]jspdf[\\/]/,
name: 'jspdf',
priority: 2,
chunks: 'all',
},
jsondiffpatch: {
test: /[\\/]jsondiffpatch[\\/]/,
name: 'jsondiffpatch',
priority: 2,
chunks: 'all',
},
jsencrypt: {
test: /[\\/]jsencrypt[\\/]/,
name: 'jsencrypt',
priority: 2,
chunks: 'all',
},
mockjs: {
test: /[\\/]mockjs[\\/]/,
name: 'mockjs',
priority: 2,
chunks: 'all',
},
},
},
},
},
css: {
// 将组件内的 CSS 提取到一个单独的 CSS 文件 (只用在生产环境中)
@ -86,5 +180,15 @@ module.exports = {
.options({
symbolId: 'icon-[name]',
});
if (process.env.NODE_ENV === 'analyze') {
config.plugin('webpack-report').use(BundleAnalyzerPlugin, [
{
analyzerMode: 'static',
reportFilename: './webpack-report.html',
openAnalyzer: false,
},
]);
}
},
};

View File

@ -7,7 +7,8 @@
"gateway": "vue-cli-service serve",
"build": "vue-cli-service build",
"build-lib": "vue-cli-service build --target lib --name metersphere-frontend --dest lib ./src/index.js --formats commonjs",
"lint": "vue-cli-service lint"
"lint": "vue-cli-service lint",
"report": "NODE_ENV=analyze vue-cli-service build"
},
"files": [
"src"
@ -25,6 +26,7 @@
"js-cookie": "^2.2.1",
"jsencrypt": "^3.1.0",
"jsondiffpatch": "^0.4.1",
"lodash-es": "^4.17.21",
"mavon-editor": "2.10.4",
"normalize.css": "^8.0.1",
"nprogress": "^0.2.0",
@ -52,7 +54,8 @@
"sass": "^1.43.4",
"sass-loader": "^10.1.1",
"svg-sprite-loader": "^6.0.11",
"vue-template-compiler": "^2.7.3"
"vue-template-compiler": "^2.7.3",
"webpack-bundle-analyzer": "^4.8.0"
},
"eslintConfig": {
"root": true,

View File

@ -5,6 +5,23 @@
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width,initial-scale=1.0">
<link rel="icon" href="<%= BASE_URL %>favicon.ico">
<% if (process.env.NODE_ENV==='development' ) { %>
<link rel="stylesheet" href="<%= BASE_URL %>js/dev/element-ui/element-ui.css" />
<script src="<%= BASE_URL %>js/dev/qiankun.umd.js"></script>
<script src="<%= BASE_URL %>js/dev/vue.js"></script>
<script src="<%= BASE_URL %>js/dev/element-ui/element-ui.js"></script>
<script src="<%= BASE_URL %>js/dev/vue-router.js"></script>
<script src="<%= BASE_URL %>js/prd/vue-shepherd.min.js"></script>
<script src="<%= BASE_URL %>js/prd/mavon-editor.js"></script>
<% } else { %>
<link rel="stylesheet" href="<%= BASE_URL %>js/prd/element-ui/element-ui.min.css" />
<script src="<%= BASE_URL %>js/prd/qiankun.umd.min.js"></script>
<script src="<%= BASE_URL %>js/prd/vue.min.js"></script>
<script src="<%= BASE_URL %>js/prd/element-ui/element-ui.min.js"></script>
<script src="<%= BASE_URL %>js/prd/vue-router.min.js"></script>
<script src="<%= BASE_URL %>js/prd/vue-shepherd.min.js"></script>
<script src="<%= BASE_URL %>js/prd/mavon-editor.js"></script>
<% } %>
</head>
<body>
<noscript>

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because it is too large Load Diff

File diff suppressed because one or more lines are too long

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@ -1,16 +1,27 @@
import ECharts from 'vue-echarts'
import 'echarts/lib/chart/line'
import 'echarts/lib/chart/bar'
import 'echarts/lib/chart/pie'
import 'echarts/lib/chart/graph'
import 'echarts/lib/component/tooltip'
import 'echarts/lib/component/title'
import 'echarts/lib/component/toolbox';
import 'echarts/lib/component/dataZoom';
import 'echarts/lib/component/legend';
import 'zrender/lib/svg/svg' // initOption 支持使用svg
import 'zrender/lib/canvas/canvas' // initOption 支持使用canvas
import 'echarts/lib/component/grid'
import * as echarts from 'echarts/core';
import { LineChart, BarChart, PieChart, GraphChart } from 'echarts/charts'
import { TooltipComponent, TitleComponent, ToolboxComponent, DataZoomComponent, LegendComponent, GridComponent } from 'echarts/components'
import {
CanvasRenderer, SVGRenderer
} from 'echarts/renderers';
echarts.use(
[
TitleComponent,
TooltipComponent,
GridComponent,
ToolboxComponent,
LegendComponent,
DataZoomComponent,
BarChart,
PieChart,
LineChart,
GraphChart,
CanvasRenderer,
SVGRenderer
]
);
export default {
install(Vue) {

View File

@ -5,10 +5,24 @@
<script>
import {formatJson, formatXml} from "../utils/format-utils";
import toDiffableHtml from 'diffable-html';
import editor from 'vue2-ace-editor';
import 'brace/ext/language_tools'; //language extension prerequisite...
import 'brace/mode/text';
import 'brace/mode/json';
import 'brace/mode/xml';
import 'brace/mode/html';
import 'brace/mode/java';
import 'brace/mode/python';
import 'brace/mode/sql';
import 'brace/mode/javascript';
import 'brace/mode/yaml';
import 'brace/theme/chrome';
import 'brace/theme/eclipse';
import 'brace/snippets/javascript'; //snippet
export default {
name: "MsCodeEdit",
components: {editor: require('vue2-ace-editor')},
components: {editor},
data() {
return {
formatData: ''
@ -76,12 +90,21 @@ export default {
}
},
editorInit: function (editor) {
require('brace/ext/language_tools') //language extension prerequisite...
this.modes.forEach(mode => {
require('brace/mode/' + mode); //language
});
require('brace/theme/' + this.theme)
require('brace/snippets/javascript') //snippet
// require('brace/ext/language_tools') //language extension prerequisite...
// require('brace/mode/text');
// require('brace/mode/json');
// require('brace/mode/xml');
// require('brace/mode/html');
// require('brace/mode/java');
// require('brace/mode/python');
// require('brace/mode/sql');
// require('brace/mode/javascript');
// require('brace/mode/yaml');
// this.modes.forEach((mode) => {
// require('brace/mode/' + mode); //language
// });
// require('brace/theme/' + this.theme)
// require('brace/snippets/javascript') //snippet
if (this.readOnly) {
editor.setReadOnly(true);
}

View File

@ -19,6 +19,8 @@
</template>
<script>
import {mavonEditor} from 'mavon-editor';
import 'mavon-editor/dist/css/index.css';
import {getCurrentUser} from "../utils/token";
import {getUUID} from "../utils";
import {deleteMarkDownImg, uploadMarkDownImg} from "../api/img";
@ -26,7 +28,7 @@ import {DEFAULT_XSS_ATTR} from "../utils/constants";
export default {
name: "MsMarkDownText",
components: {},
components: {mavonEditor},
props: {
data: Object,
placeholder: String,

View File

@ -36,7 +36,7 @@
<script>
import components from "./search/search-components";
import {cloneDeep, concat, slice} from "lodash";
import {cloneDeep, concat, slice} from "lodash-es";
import {_findByKey, _findIndexByKey} from "./search/custom-component";
export default {

View File

@ -170,7 +170,7 @@ import ApiVariableSetting from './ApiVariableSetting';
import CsvFileUpload from './variable/CsvFileUpload';
import { downloadFile, getUUID, operationConfirm } from '../../../utils';
import VariableImport from './variable/VariableImport';
import _ from 'lodash';
import {forEach} from 'lodash-es';
import MsTablePagination from '../../pagination/TablePagination';
export default {
@ -546,7 +546,7 @@ export default {
this.items.push(new KeyValue({ enable: true, scope: 'api' }));
} else {
// api
_.forEach(this.items, (item) => {
forEach(this.items, (item) => {
delete item.hidden;
if (!item.scope) {
this.$set(item, 'scope', 'api');

View File

@ -21,8 +21,8 @@
</template>
<script>
const jsondiffpatch = require('jsondiffpatch');
const formattersHtml = jsondiffpatch.formatters.html;
import {formatters,diff} from 'jsondiffpatch';
const formattersHtml = formatters.html;
export default {
name: "MsEnvHistoryDetail",
components: {},
@ -39,10 +39,10 @@
methods: {
getDiff(v1, v2) {
if (this.detail.columnName==='request' && v1 && v2){
let delta = jsondiffpatch.diff(JSON.parse(JSON.stringify(v1)), JSON.parse(JSON.stringify(v2)));
let delta = diff(JSON.parse(JSON.stringify(v1)), JSON.parse(JSON.stringify(v2)));
return formattersHtml.format(delta, JSON.parse(JSON.stringify(v1)));
}
let delta = jsondiffpatch.diff(v1 , v2);
let delta = diff(v1 , v2);
return formattersHtml.format(delta, v1);
},
handleClose() {

View File

@ -102,8 +102,8 @@
</template>
<script>
const jsondiffpatch = require('jsondiffpatch');
const formattersHtml = jsondiffpatch.formatters.html;
import {formatters,diff} from 'jsondiffpatch';
const formattersHtml = formatters.html;
export default {
name: "EnvironmentEditParams",
components: {},
@ -155,10 +155,10 @@ export default {
},
getDiff(v1, v2) {
if (typeof v1 === 'string' && typeof v2 === 'string' && v1.indexOf("{") !== -1 && v2.indexOf("{") !== -1) {
let delta = jsondiffpatch.diff(JSON.parse(v1), JSON.parse(v2));
let delta = diff(JSON.parse(v1), JSON.parse(v2));
return formattersHtml.format(delta, delta);
} else {
let delta = jsondiffpatch.diff(v1, v2);
let delta = diff(v1, v2);
return formattersHtml.format(delta, v1);
}
},

View File

@ -21,9 +21,9 @@
</template>
<script>
import * as jsondiffpatch from 'jsondiffpatch';
import { formatters, diff } from 'jsondiffpatch';
const formattersHtml = jsondiffpatch.formatters.html;
const formattersHtml = formatters.html;
export default {
name: "MsHistoryDetail",
components: {},
@ -40,10 +40,10 @@ export default {
methods: {
getDiff(v1, v2) {
if (this.detail.columnName === 'request' && v1 && v2) {
let delta = jsondiffpatch.diff(JSON.parse(JSON.stringify(v1)), JSON.parse(JSON.stringify(v2)));
let delta = diff(JSON.parse(JSON.stringify(v1)), JSON.parse(JSON.stringify(v2)));
return formattersHtml.format(delta, JSON.parse(JSON.stringify(v1)));
}
let delta = jsondiffpatch.diff(v1, v2);
let delta = diff(v1, v2);
return formattersHtml.format(delta, v1);
},
handleClose() {

View File

@ -35,7 +35,7 @@
<script>
import components from "../search/search-components";
import {cloneDeep, concat, slice} from "lodash";
import {cloneDeep, concat, slice} from "lodash-es";
import {_findByKey, _findIndexByKey} from "../search/custom-component";
export default {

View File

@ -31,7 +31,7 @@
<script>
import components from "./search-components";
import {cloneDeep, concat, slice} from "lodash";
import {cloneDeep, concat, slice} from "lodash-es";
import {_findByKey, _findIndexByKey} from "./custom-component";
export default {

View File

@ -41,7 +41,7 @@
</template>
<script>
import {concat} from "lodash";
import {concat} from "lodash-es";
import {_findByKey} from "./custom-component";
export default {

View File

@ -49,7 +49,7 @@
<script>
import MsTableSearchComponent from "./MsTableSearchComponet";
import MsNodeTree from "../module/MsNodeTree";
import {cloneDeep} from "lodash";
import {cloneDeep} from "lodash-es";
import {getCurrentProjectID} from "../../utils/token";
import {get, post} from "../../plugins/request";

View File

@ -0,0 +1,123 @@
export default {
el: {
colorpicker: {
confirm: 'OK',
clear: 'Clear'
},
datepicker: {
now: 'Now',
today: 'Today',
cancel: 'Cancel',
clear: 'Clear',
confirm: 'OK',
selectDate: 'Select date',
selectTime: 'Select time',
startDate: 'Start Date',
startTime: 'Start Time',
endDate: 'End Date',
endTime: 'End Time',
prevYear: 'Previous Year',
nextYear: 'Next Year',
prevMonth: 'Previous Month',
nextMonth: 'Next Month',
year: '',
month1: 'January',
month2: 'February',
month3: 'March',
month4: 'April',
month5: 'May',
month6: 'June',
month7: 'July',
month8: 'August',
month9: 'September',
month10: 'October',
month11: 'November',
month12: 'December',
week: 'week',
weeks: {
sun: 'Sun',
mon: 'Mon',
tue: 'Tue',
wed: 'Wed',
thu: 'Thu',
fri: 'Fri',
sat: 'Sat'
},
months: {
jan: 'Jan',
feb: 'Feb',
mar: 'Mar',
apr: 'Apr',
may: 'May',
jun: 'Jun',
jul: 'Jul',
aug: 'Aug',
sep: 'Sep',
oct: 'Oct',
nov: 'Nov',
dec: 'Dec'
}
},
select: {
loading: 'Loading',
noMatch: 'No matching data',
noData: 'No data',
placeholder: 'Select'
},
cascader: {
noMatch: 'No matching data',
loading: 'Loading',
placeholder: 'Select',
noData: 'No data'
},
pagination: {
goto: 'Go to',
pagesize: '/page',
total: 'Total {total}',
pageClassifier: ''
},
messagebox: {
title: 'Message',
confirm: 'OK',
cancel: 'Cancel',
error: 'Illegal input'
},
upload: {
deleteTip: 'press delete to remove',
delete: 'Delete',
preview: 'Preview',
continue: 'Continue'
},
table: {
emptyText: 'No Data',
confirmFilter: 'Confirm',
resetFilter: 'Reset',
clearFilter: 'All',
sumText: 'Sum'
},
tree: {
emptyText: 'No Data'
},
transfer: {
noMatch: 'No matching data',
noData: 'No data',
titles: ['List 1', 'List 2'], // to be translated
filterPlaceholder: 'Enter keyword', // to be translated
noCheckedFormat: '{total} items', // to be translated
hasCheckedFormat: '{checked}/{total} checked' // to be translated
},
image: {
error: 'FAILED'
},
pageHeader: {
title: 'Back' // to be translated
},
popconfirm: {
confirmButtonText: 'Yes',
cancelButtonText: 'No'
},
empty: {
description: 'No Data'
}
}
}

View File

@ -0,0 +1,123 @@
export default {
el: {
colorpicker: {
confirm: '确定',
clear: '清空'
},
datepicker: {
now: '此刻',
today: '今天',
cancel: '取消',
clear: '清空',
confirm: '确定',
selectDate: '选择日期',
selectTime: '选择时间',
startDate: '开始日期',
startTime: '开始时间',
endDate: '结束日期',
endTime: '结束时间',
prevYear: '前一年',
nextYear: '后一年',
prevMonth: '上个月',
nextMonth: '下个月',
year: '年',
month1: '1 月',
month2: '2 月',
month3: '3 月',
month4: '4 月',
month5: '5 月',
month6: '6 月',
month7: '7 月',
month8: '8 月',
month9: '9 月',
month10: '10 月',
month11: '11 月',
month12: '12 月',
// week: '周次',
weeks: {
sun: '日',
mon: '一',
tue: '二',
wed: '三',
thu: '四',
fri: '五',
sat: '六'
},
months: {
jan: '一月',
feb: '二月',
mar: '三月',
apr: '四月',
may: '五月',
jun: '六月',
jul: '七月',
aug: '八月',
sep: '九月',
oct: '十月',
nov: '十一月',
dec: '十二月'
}
},
select: {
loading: '加载中',
noMatch: '无匹配数据',
noData: '无数据',
placeholder: '请选择'
},
cascader: {
noMatch: '无匹配数据',
loading: '加载中',
placeholder: '请选择',
noData: '暂无数据'
},
pagination: {
goto: '前往',
pagesize: '条/页',
total: '共 {total} 条',
pageClassifier: '页'
},
messagebox: {
title: '提示',
confirm: '确定',
cancel: '取消',
error: '输入的数据不合法!'
},
upload: {
deleteTip: '按 delete 键可删除',
delete: '删除',
preview: '查看图片',
continue: '继续上传'
},
table: {
emptyText: '暂无数据',
confirmFilter: '筛选',
resetFilter: '重置',
clearFilter: '全部',
sumText: '合计'
},
tree: {
emptyText: '暂无数据'
},
transfer: {
noMatch: '无匹配数据',
noData: '无数据',
titles: ['列表 1', '列表 2'],
filterPlaceholder: '请输入搜索内容',
noCheckedFormat: '共 {total} 项',
hasCheckedFormat: '已选 {checked}/{total} 项'
},
image: {
error: '加载失败'
},
pageHeader: {
title: '返回'
},
popconfirm: {
confirmButtonText: '确定',
cancelButtonText: '取消'
},
empty: {
description: '暂无数据'
}
}
}

View File

@ -0,0 +1,123 @@
export default {
el: {
colorpicker: {
confirm: '確認',
clear: '清空'
},
datepicker: {
now: '現在',
today: '今天',
cancel: '取消',
clear: '清空',
confirm: '確認',
selectDate: '選擇日期',
selectTime: '選擇時間',
startDate: '開始日期',
startTime: '開始時間',
endDate: '結束日期',
endTime: '結束時間',
prevYear: '前一年',
nextYear: '後一年',
prevMonth: '上個月',
nextMonth: '下個月',
year: '年',
month1: '1 月',
month2: '2 月',
month3: '3 月',
month4: '4 月',
month5: '5 月',
month6: '6 月',
month7: '7 月',
month8: '8 月',
month9: '9 月',
month10: '10 月',
month11: '11 月',
month12: '12 月',
// week: '周次',
weeks: {
sun: '日',
mon: '一',
tue: '二',
wed: '三',
thu: '四',
fri: '五',
sat: '六'
},
months: {
jan: '一月',
feb: '二月',
mar: '三月',
apr: '四月',
may: '五月',
jun: '六月',
jul: '七月',
aug: '八月',
sep: '九月',
oct: '十月',
nov: '十一月',
dec: '十二月'
}
},
select: {
loading: '加載中',
noMatch: '無匹配資料',
noData: '無資料',
placeholder: '請選擇'
},
cascader: {
noMatch: '無匹配資料',
loading: '加載中',
placeholder: '請選擇',
noData: '無資料'
},
pagination: {
goto: '前往',
pagesize: '項/頁',
total: '共 {total} 項',
pageClassifier: '頁'
},
messagebox: {
title: '提示',
confirm: '確定',
cancel: '取消',
error: '輸入的資料不符規定!'
},
upload: {
deleteTip: '按 delete 鍵可刪除',
delete: '刪除',
preview: '查看圖片',
continue: '繼續上傳'
},
table: {
emptyText: '暫無資料',
confirmFilter: '篩選',
resetFilter: '重置',
clearFilter: '全部',
sumText: 'Sum' // to be translated
},
tree: {
emptyText: '暫無資料'
},
transfer: {
noMatch: '無匹配資料',
noData: '無資料',
titles: ['List 1', 'List 2'], // to be translated
filterPlaceholder: 'Enter keyword', // to be translated
noCheckedFormat: '{total} items', // to be translated
hasCheckedFormat: '{checked}/{total} checked' // to be translated
},
image: {
error: '加載失敗'
},
pageHeader: {
title: '返回'
},
popconfirm: {
confirmButtonText: 'Yes', // to be translated
cancelButtonText: 'No' // to be translated
},
empty: {
description: '暫無資料'
}
}
};

View File

@ -1,4 +1,4 @@
import el from "element-ui/lib/locale/lang/en";
import el from "./ele-en-US";
import fu from "fit2cloud-ui/src/locale/lang/en_US"; // 加载fit2cloud的内容
import test_track from "./track/en-US";

View File

@ -1,4 +1,4 @@
import el from "element-ui/lib/locale/lang/zh-CN"; // 加载element的内容
import el from "./ele-zh-CN"; // 加载element的内容
import fu from "fit2cloud-ui/src/locale/lang/zh-CN"; // 加载fit2cloud的内容
import test_track from "./track/zh-CN";

View File

@ -1,4 +1,4 @@
import el from "element-ui/lib/locale/lang/zh-TW";
import el from "./ele-zh-TW";
import fu from "fit2cloud-ui/src/locale/lang/zh-TW"; // 加载fit2cloud的内容
import test_track from "./track/zh-TW";

View File

@ -1,12 +1,56 @@
import {library} from '@fortawesome/fontawesome-svg-core'
import {fas} from '@fortawesome/free-solid-svg-icons'
import {far} from '@fortawesome/free-regular-svg-icons'
import {fab} from '@fortawesome/free-brands-svg-icons'
import {FontAwesomeIcon} from '@fortawesome/vue-fontawesome'
import { library } from "@fortawesome/fontawesome-svg-core";
import { faBars } from "@fortawesome/free-solid-svg-icons/faBars";
import { faTimes } from "@fortawesome/free-solid-svg-icons/faTimes";
import { faExpandAlt } from "@fortawesome/free-solid-svg-icons/faExpandAlt";
import { faCompressAlt } from "@fortawesome/free-solid-svg-icons/faCompressAlt";
import { faSitemap } from "@fortawesome/free-solid-svg-icons/faSitemap";
import { faListUl } from "@fortawesome/free-solid-svg-icons/faListUl";
import { faQuestionCircle } from "@fortawesome/free-solid-svg-icons/faQuestionCircle";
import { faLanguage } from "@fortawesome/free-solid-svg-icons/faLanguage";
import { faPlus } from "@fortawesome/free-solid-svg-icons/faPlus";
import { faBell } from "@fortawesome/free-solid-svg-icons/faBell";
import { faCompass } from "@fortawesome/free-solid-svg-icons/faCompass";
import { faChevronDown } from "@fortawesome/free-solid-svg-icons/faChevronDown";
import { faCircleNotch } from "@fortawesome/free-solid-svg-icons/faCircleNotch";
import { faTasks } from "@fortawesome/free-solid-svg-icons/faTasks";
import { faTag } from "@fortawesome/free-solid-svg-icons/faTag";
import { faAlignJustify } from "@fortawesome/free-solid-svg-icons/faAlignJustify";
import { faCheckCircle } from "@fortawesome/free-regular-svg-icons/faCheckCircle";
import { faCircle } from "@fortawesome/free-regular-svg-icons/faCircle";
import { faAddressCard } from "@fortawesome/free-regular-svg-icons/faAddressCard";
import { faListAlt } from "@fortawesome/free-regular-svg-icons/faListAlt";
import { faArrowRight } from "@fortawesome/free-solid-svg-icons/faArrowRight";
import { faGithubSquare } from "@fortawesome/free-brands-svg-icons/faGithubSquare";
import { FontAwesomeIcon } from "@fortawesome/vue-fontawesome";
export default {
install(Vue) {
library.add(fas, far, fab);
Vue.component('font-awesome-icon', FontAwesomeIcon);
}
}
library.add(
faBars,
faTimes,
faExpandAlt,
faCompressAlt,
faSitemap,
faListUl,
faQuestionCircle,
faLanguage,
faPlus,
faBell,
faCompass,
faChevronDown,
faCheckCircle,
faCircleNotch,
faTasks,
faTag,
faAlignJustify,
faAddressCard,
faListAlt,
faArrowRight,
faGithubSquare,
faCircle
);
Vue.component("font-awesome-icon", FontAwesomeIcon);
},
};

View File

@ -1,6 +1,5 @@
import Vue from "vue";
import "@/styles/index.scss";
import ElementUI from "element-ui";
import App from "./App.vue";
import i18n from "./i18n";
import router from "./router/index";
@ -13,8 +12,6 @@ import directives from "./directive";
import filters from "./filters";
import "./router/permission";
import "./micro-app";
import mavonEditor from 'mavon-editor';
import 'mavon-editor/dist/css/index.css';
import VueShepherd from 'vue-shepherd' // 新手引导
import './assets/shepherd/shepherd-theme.css'
import { gotoCancel, gotoNext } from "./utils";
@ -24,18 +21,12 @@ Vue.config.productionTip = false
const pinia = createPinia()
pinia.use(PersistedState)//开启缓存存储在localstorage
Vue.use(ElementUI, {
i18n: (key, value) => i18n.t(key, value)
});
Vue.use(icons);
Vue.use(svg);
Vue.use(plugins);
Vue.use(directives);
Vue.use(filters);
Vue.use(PiniaVuePlugin);
Vue.use(mavonEditor);
Vue.use(VueShepherd)
Vue.prototype.gotoCancel = gotoCancel

View File

@ -1,5 +1,5 @@
const path = require('path');
const {name} = require('./package');
const BundleAnalyzerPlugin = require('webpack-bundle-analyzer').BundleAnalyzerPlugin;
function resolve(dir) {
return path.join(__dirname, dir);
@ -32,6 +32,66 @@ module.exports = {
'@': resolve('src')
}
},
externals: {
vue: 'Vue',
'vue-router': 'VueRouter',
qiankun: 'qiankun',
// 'echarts': 'echarts',
// 'echarts/core': 'echarts', // TODO:外链使用的话需要改造导入及 vue-echarts 的源码
// brace: 'brace', // TODO:暂时未发现能外链的方法本体包未提供cdn 外链形式的包
'element-ui': 'ELEMENT',
'vue-shepherd': 'VueShepherd',
},
optimization: {
splitChunks: {
cacheGroups: {
'chunk-vendors': {
test: /[\\/]node_modules[\\/]/,
name: 'chunk-vendors',
priority: 1,
minChunks: 3,
chunks: 'all',
},
'chunk-common': {
test: /[\\/]src[\\/]/,
name: 'chunk-common',
priority: 1,
minChunks: 5,
chunks: 'all',
},
html2canvas: {
test: /[\\/]html2canvas[\\/]/,
name: 'html2canvas',
priority: 2,
chunks: 'all',
},
fortawesome: {
test: /[\\/]@fortawesome[\\/]/,
name: 'fortawesome',
priority: 2,
chunks: 'all',
},
pinia: {
test: /[\\/]pinia[\\/]/,
name: 'pinia',
priority: 3,
chunks: 'all',
},
jspdf: {
test: /[\\/]jspdf[\\/]/,
name: 'jspdf',
priority: 2,
chunks: 'all',
},
jsencrypt: {
test: /[\\/]jsencrypt[\\/]/,
name: 'jsencrypt',
priority: 2,
chunks: 'all',
},
},
},
},
},
chainWebpack: config => {
config.devtool('source-map')
@ -52,5 +112,15 @@ module.exports = {
.options({
symbolId: 'icon-[name]'
})
if (process.env.NODE_ENV === 'analyze') {
config.plugin('webpack-report').use(BundleAnalyzerPlugin, [
{
analyzerMode: 'static',
reportFilename: './webpack-report.html',
openAnalyzer: false,
},
]);
}
}
};

View File

@ -5,7 +5,8 @@
"scripts": {
"performance": "vue-cli-service serve",
"build": "vue-cli-service build",
"lint": "vue-cli-service lint"
"lint": "vue-cli-service lint",
"report": "NODE_ENV=analyze vue-cli-service build"
},
"dependencies": {
"@ckeditor/ckeditor5-build-classic": "^18.0.0",
@ -83,7 +84,8 @@
"sass": "^1.43.4",
"sass-loader": "^10.1.1",
"svg-sprite-loader": "^6.0.11",
"vue-template-compiler": "^2.7.3"
"vue-template-compiler": "^2.7.3",
"webpack-bundle-analyzer": "^4.8.0"
},
"eslintConfig": {
"root": true,

View File

@ -6,6 +6,21 @@
<meta name="viewport" content="width=device-width,initial-scale=1.0">
<link rel="icon" href="<%= BASE_URL %>favicon.ico">
<title><%= htmlWebpackPlugin.options.title %></title>
<% if (process.env.NODE_ENV==='development' ) { %>
<link rel="stylesheet" href="http://localhost:3000/js/dev/element-ui/element-ui.css" />
<script src="http://localhost:3000/js/dev/vue.js"></script>
<script src="http://localhost:3000/js/dev/element-ui/element-ui.js"></script>
<script src="http://localhost:3000/js/dev/vue-router.js"></script>
<script src="http://localhost:3000/js/prd/vue-shepherd.min.js"></script>
<script src="http://localhost:3000/js/prd/mavon-editor.js"></script>
<% } else { %>
<link rel="stylesheet" href="<%= BASE_URL %>js/prd/element-ui/element-ui.min.css" />
<script src="<%= BASE_URL %>js/prd/vue.min.js"></script>
<script src="<%= BASE_URL %>js/prd/element-ui/element-ui.min.js"></script>
<script src="<%= BASE_URL %>js/prd/vue-router.min.js"></script>
<script src="<%= BASE_URL %>js/prd/vue-shepherd.min.js"></script>
<script src="<%= BASE_URL %>js/prd/mavon-editor.js"></script>
<% } %>
</head>
<body>
<noscript>

View File

@ -3,7 +3,7 @@
</template>
<script>
import echarts from 'echarts'
// import echarts from 'echarts'
import MsChart from "metersphere-frontend/src/components/chart/MsChart";
export default {

View File

@ -1,4 +1,4 @@
import el from "element-ui/lib/locale/lang/en";
import el from "metersphere-frontend/src/i18n/lang/ele-en-US";
import fu from "fit2cloud-ui/src/locale/lang/en_US"; // 加载fit2cloud的内容
import mf from "metersphere-frontend/src/i18n/lang/en-US"

View File

@ -1,4 +1,4 @@
import el from "element-ui/lib/locale/lang/zh-CN"; // 加载element的内容
import el from "metersphere-frontend/src/i18n/lang/ele-zh-CN"; // 加载element的内容
import fu from "fit2cloud-ui/src/locale/lang/zh-CN"; // 加载fit2cloud的内容
import mf from "metersphere-frontend/src/i18n/lang/zh-CN"

View File

@ -1,4 +1,4 @@
import el from "element-ui/lib/locale/lang/zh-TW";
import el from "metersphere-frontend/src/i18n/lang/ele-zh-TW";
import fu from "fit2cloud-ui/src/locale/lang/zh-TW"; // 加载fit2cloud的内容
import mf from "metersphere-frontend/src/i18n/lang/zh-TW"

View File

@ -1,11 +1,17 @@
<!DOCTYPE html>
<html lang="zh">
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width,initial-scale=1.0">
<link rel="shortcut icon" href="<%= BASE_URL %>favicon.ico">
<meta charset="utf-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<meta name="viewport" content="width=device-width,initial-scale=1.0" />
<link rel="shortcut icon" href="<%= BASE_URL %>favicon.ico" />
<title>Performance Report</title>
<link
rel="stylesheet"
href="<%= BASE_URL %>js/prd/element-ui/element-ui.min.css"
/>
<script src="<%= BASE_URL %>js/prd/vue.min.js"></script>
<script src="<%= BASE_URL %>js/prd/element-ui/element-ui.min.js"></script>
</head>
<body>
<div id="sharePerformanceReport"></div>

View File

@ -1,5 +1,7 @@
const path = require('path');
const {name} = require('./package');
const path = require("path");
const { name } = require("./package");
const BundleAnalyzerPlugin =
require("webpack-bundle-analyzer").BundleAnalyzerPlugin;
function resolve(dir) {
return path.join(__dirname, dir);
@ -10,54 +12,148 @@ module.exports = {
devServer: {
port: 4003,
client: {
webSocketTransport: 'sockjs',
webSocketTransport: "sockjs",
},
allowedHosts: 'all',
webSocketServer: 'sockjs',
allowedHosts: "all",
webSocketServer: "sockjs",
proxy: {
['^((?!/login)(?!/document))']: {
target: 'http://localhost:8003',
ws: false
["^((?!/login)(?!/document))"]: {
target: "http://localhost:8003",
ws: false,
},
'/websocket': {
target: 'http://localhost:8003',
ws: true
"/websocket": {
target: "http://localhost:8003",
ws: true,
},
},
// 跨域
headers: {
'Access-Control-Allow-Origin': '*',
"Access-Control-Allow-Origin": "*",
},
},
pages: {
index: {
entry: "src/main.js",
template: "public/index.html",
filename: "index.html"
filename: "index.html",
},
sharePerformanceReport: {
entry: "src/template/report/performance/share/share-performance-report.js",
template: "src/template/report/performance/share/share-performance-report.html",
entry:
"src/template/report/performance/share/share-performance-report.js",
template:
"src/template/report/performance/share/share-performance-report.html",
filename: "share-performance-report.html",
},
},
configureWebpack: {
devtool: 'cheap-module-source-map',
devtool: "cheap-module-source-map",
resolve: {
alias: {
'@': resolve('src')
"@": resolve("src"),
'html2canvas': resolve('node_modules/html2canvas'),
'vue-i18n': resolve('node_modules/vue-i18n'),
},
fallback: {"stream": require.resolve("stream-browserify")}
fallback: { stream: require.resolve("stream-browserify") },
},
output: {
// 把子应用打包成 umd 库格式(必须)
library: `${name}-[name]`,
libraryTarget: 'umd',
libraryTarget: "umd",
chunkLoadingGlobal: `webpackJsonp_${name}`,
// 打包后js的名称
filename: `js/${name}-[name].[contenthash:8].js`,
chunkFilename: `js/${name}-[name].[contenthash:8].js`,
},
externals: {
vue: "Vue",
"vue-router": "VueRouter",
// 'echarts': 'echarts',
// 'echarts/core': 'echarts', // TODO:外链使用的话需要改造导入及 vue-echarts 的源码
// brace: 'brace', // TODO:暂时未发现能外链的方法本体包未提供cdn 外链形式的包
"element-ui": "ELEMENT",
"mavon-editor": "MavonEditor",
"vue-shepherd": "VueShepherd",
},
optimization: {
splitChunks: {
cacheGroups: {
"chunk-vendors": {
test: /[\\/]node_modules[\\/]/,
name: "chunk-vendors",
priority: 1,
minChunks: 3,
chunks: "all",
},
"chunk-common": {
test: /[\\/]src[\\/]/,
name: "chunk-common",
priority: 1,
minChunks: 5,
chunks: "all",
},
html2canvas: {
test: /[\\/]html2canvas[\\/]/,
name: "html2canvas",
priority: 2,
chunks: "all",
},
fortawesome: {
test: /[\\/]@fortawesome[\\/]/,
name: "fortawesome",
priority: 2,
chunks: "all",
},
"el-tree-transfer": {
test: /[\\/]el-tree-transfer[\\/]/,
name: "el-tree-transfer",
priority: 2,
chunks: "all",
},
pinia: {
test: /[\\/]pinia[\\/]/,
name: "pinia",
priority: 3,
chunks: "all",
},
brace: {
test: /[\\/]brace[\\/]/,
name: "brace",
priority: 3,
chunks: "all",
},
echarts: {
test: /[\\/](echarts|zrender)[\\/]/,
name: "echarts",
priority: 3,
chunks: "all",
},
jspdf: {
test: /[\\/]jspdf[\\/]/,
name: "jspdf",
priority: 2,
chunks: "all",
},
jsondiffpatch: {
test: /[\\/]jsondiffpatch[\\/]/,
name: "jsondiffpatch",
priority: 2,
chunks: "all",
},
jsencrypt: {
test: /[\\/]jsencrypt[\\/]/,
name: "jsencrypt",
priority: 2,
chunks: "all",
},
mockjs: {
test: /[\\/]mockjs[\\/]/,
name: "mockjs",
priority: 2,
chunks: "all",
},
},
},
},
},
css: {
// 将组件内的 CSS 提取到一个单独的 CSS 文件 (只用在生产环境中)
@ -67,23 +163,37 @@ module.exports = {
extract: {
ignoreOrder: true,
filename: `css/${name}-[name].[contenthash:8].css`,
chunkFilename: `css/${name}-[name].[contenthash:8].css`
chunkFilename: `css/${name}-[name].[contenthash:8].css`,
},
},
chainWebpack: config => {
chainWebpack: (config) => {
config.module
.rule('svg')
.exclude.add(resolve('../../framework/sdk-parent/frontend/src/assets/module'))
.end()
.rule("svg")
.exclude.add(
resolve("../../framework/sdk-parent/frontend/src/assets/module")
)
.end();
config.module
.rule('icons')
.rule("icons")
.test(/\.svg$/)
.include.add(resolve('../../framework/sdk-parent/frontend/src/assets/module'))
.include.add(
resolve("../../framework/sdk-parent/frontend/src/assets/module")
)
.end()
.use('svg-sprite-loader')
.loader('svg-sprite-loader')
.use("svg-sprite-loader")
.loader("svg-sprite-loader")
.options({
symbolId: 'icon-[name]'
})
symbolId: "icon-[name]",
});
if (process.env.NODE_ENV === "analyze") {
config.plugin("webpack-report").use(BundleAnalyzerPlugin, [
{
analyzerMode: "static",
reportFilename: "./webpack-report.html",
openAnalyzer: false,
},
]);
}
},
};

View File

@ -5,7 +5,8 @@
"scripts": {
"project": "vue-cli-service serve",
"build": "vue-cli-service build",
"lint": "vue-cli-service lint"
"lint": "vue-cli-service lint",
"report": "NODE_ENV=analyze vue-cli-service build"
},
"dependencies": {
"@ckeditor/ckeditor5-build-classic": "^18.0.0",
@ -34,6 +35,7 @@
"jsoneditor": "^9.5.6",
"jsonpath": "^1.1.0",
"jspdf": "^2.3.1",
"lodash-es": "^4.17.21",
"lodash.isboolean": "^3.0.3",
"lodash.isempty": "^4.4.0",
"lodash.isinteger": "^4.0.4",
@ -51,6 +53,7 @@
"pinia": "^2.0.14",
"pinia-plugin-persistedstate": "^1.6.3",
"sha.js": "^2.4.11",
"shepherd.js": "^10.0.0",
"vue": "^2.7.3",
"vue-calendar-heatmap": "^0.8.4",
"vue-clipboard2": "^0.3.1",
@ -62,13 +65,12 @@
"vue-papa-parse": "^2.0.0",
"vue-pdf": "^4.2.0",
"vue-router": "^3.1.3",
"vue-shepherd": "^0.3.0",
"vue-virtual-scroll-list": "^2.3.3",
"vue2-ace-editor": "0.0.15",
"vuedraggable": "^2.24.3",
"xml-js": "^1.6.11",
"yan-progress": "^1.0.3",
"vue-shepherd": "^0.3.0",
"shepherd.js": "^10.0.0"
"yan-progress": "^1.0.3"
},
"devDependencies": {
"@babel/core": "^7.12.16",
@ -83,7 +85,8 @@
"sass": "^1.43.4",
"sass-loader": "^10.1.1",
"svg-sprite-loader": "^6.0.11",
"vue-template-compiler": "^2.7.3"
"vue-template-compiler": "^2.7.3",
"webpack-bundle-analyzer": "^4.8.0"
},
"eslintConfig": {
"root": true,

View File

@ -6,6 +6,21 @@
<meta name="viewport" content="width=device-width,initial-scale=1.0">
<link rel="icon" href="<%= BASE_URL %>favicon.ico">
<title><%= htmlWebpackPlugin.options.title %></title>
<% if (process.env.NODE_ENV==='development' ) { %>
<link rel="stylesheet" href="http://localhost:3000/js/dev/element-ui/element-ui.css" />
<script src="http://localhost:3000/js/dev/vue.js"></script>
<script src="http://localhost:3000/js/dev/element-ui/element-ui.js"></script>
<script src="http://localhost:3000/js/dev/vue-router.js"></script>
<script src="http://localhost:3000/js/prd/vue-shepherd.min.js"></script>
<script src="http://localhost:3000/js/prd/mavon-editor.js"></script>
<% } else { %>
<link rel="stylesheet" href="<%= BASE_URL %>js/prd/element-ui/element-ui.min.css" />
<script src="<%= BASE_URL %>js/prd/vue.min.js"></script>
<script src="<%= BASE_URL %>js/prd/element-ui/element-ui.min.js"></script>
<script src="<%= BASE_URL %>js/prd/vue-router.min.js"></script>
<script src="<%= BASE_URL %>js/prd/vue-shepherd.min.js"></script>
<script src="<%= BASE_URL %>js/prd/mavon-editor.js"></script>
<% } %>
</head>
<body>
<noscript>

View File

@ -212,7 +212,7 @@ import {TYPE_TO_C} from "metersphere-frontend/src/model/Setting";
import MsTableSearchBar from "metersphere-frontend/src/components/MsTableSearchBar";
import MsTableAdvSearchBar from "metersphere-frontend/src/components/search/MsTableAdvSearchBar";
import ListItemDeleteConfirm from "metersphere-frontend/src/components/ListItemDeleteConfirm";
import _ from "lodash";
import {set} from "lodash-es";
import MsSearch from "metersphere-frontend/src/components/search/MsSearch";
import PlanStatusTableItem from "@/business/menu/environment/components/ui-related/PlanStatusTableItem";
import PriorityTableItem from "@/business/menu/common/PriorityTableItem";
@ -776,7 +776,7 @@ export default {
this.runRequest = run;
this.$refs.runMode.open();
this.runRows = new Set();
this.runRows.add(_.set(this.orderBySelectRows("row")));
this.runRows.add(set(this.orderBySelectRows("row")));
},
orderBySelectRows(type) {
let selectIds = this.$refs.scenarioTable.selectIds;

View File

@ -156,7 +156,7 @@ import ApiVariableSetting from "metersphere-frontend/src/components/environment/
import CsvFileUpload from "metersphere-frontend/src/components/environment/commons/variable/CsvFileUpload";
import {downloadFile, getUUID, operationConfirm} from "metersphere-frontend/src/utils";
import VariableImport from "metersphere-frontend/src/components/environment/VariableImport";
import _ from "lodash";
import {cloneDeep} from "lodash-es";
import MiniTimingItem from "metersphere-frontend/src/components/environment/commons/MiniTimingItem";
import UiScenarioEditRelevance from "@/business/menu/environment/components/ui-related/UiScenarioEditRelevance";
import {getCurrentProjectID, getCurrentWorkspaceId} from "metersphere-frontend/src/utils/token";
@ -376,7 +376,7 @@ export default {
},
filterScope(scope) {
let datas = [];
let variables = _.cloneDeep(this.variables);
let variables = cloneDeep(this.variables);
variables.forEach((item) => {
if (scope == "api") {
if (

View File

@ -250,7 +250,7 @@ import {TYPE_TO_C} from "metersphere-frontend/src/model/Setting";
import MsTableSearchBar from "metersphere-frontend/src/components/MsTableSearchBar";
import MsTableAdvSearchBar from "metersphere-frontend/src/components/search/MsTableAdvSearchBar";
import ListItemDeleteConfirm from "metersphere-frontend/src/components/ListItemDeleteConfirm";
import _ from "lodash";
import {set} from "lodash-es";
import MsSearch from "metersphere-frontend/src/components/search/MsSearch";
import MsTablePagination from "metersphere-frontend/src/components/pagination/TablePagination"
import {getUiAutomationList} from "@/business/menu/environment/components/ui-related/ui-scenario";
@ -861,7 +861,7 @@ export default {
this.runRequest = run;
this.$refs.runMode.open();
this.runRows = new Set();
this.runRows.add(_.set(this.orderBySelectRows("row")));
this.runRows.add(set(this.orderBySelectRows("row")));
},
orderBySelectRows(type) {
let selectIds = this.$refs.scenarioTable.selectIds;

View File

@ -58,8 +58,8 @@
import {getLogDetailById} from "../../../api/log";
import RequestLogDetail from "./RequestLogDetail";
const jsondiffpatch = require('jsondiffpatch');
const formattersHtml = jsondiffpatch.formatters.html;
import {formatters, diff} from 'jsondiffpatch';
const formattersHtml = formatters.html;
export default {
name: "MsLogDetail",
@ -146,10 +146,10 @@ const jsondiffpatch = require('jsondiffpatch');
},
getDiff(v1, v2) {
if(typeof v1 === 'string' && typeof v2 === 'string' && v1.indexOf("{") !==-1 && v2.indexOf("{") !==-1 ){
let delta = jsondiffpatch.diff(JSON.parse(v1), JSON.parse(v2));
let delta = diff(JSON.parse(v1), JSON.parse(v2));
return formattersHtml.format(delta,delta);
}else{
let delta = jsondiffpatch.diff(v1, v2);
let delta = diff(v1, v2);
return formattersHtml.format(delta,v1);
}
},

View File

@ -1,4 +1,4 @@
import el from "element-ui/lib/locale/lang/en";
import el from "metersphere-frontend/src/i18n/lang/ele-en-US";
import fu from "fit2cloud-ui/src/locale/lang/en_US"; // 加载fit2cloud的内容
import mf from "metersphere-frontend/src/i18n/lang/en-US";

View File

@ -1,4 +1,4 @@
import el from "element-ui/lib/locale/lang/zh-CN"; // 加载element的内容
import el from "metersphere-frontend/src/i18n/lang/ele-zh-CN"; // 加载element的内容
import fu from "fit2cloud-ui/src/locale/lang/zh-CN"; // 加载fit2cloud的内容
import mf from "metersphere-frontend/src/i18n/lang/zh-CN";

View File

@ -1,4 +1,4 @@
import el from "element-ui/lib/locale/lang/zh-TW";
import el from "metersphere-frontend/src/i18n/lang/ele-zh-TW";
import fu from "fit2cloud-ui/src/locale/lang/zh-TW"; // 加载fit2cloud的内容
import mf from "metersphere-frontend/src/i18n/lang/zh-TW";

View File

@ -13,8 +13,6 @@ import plugins from "metersphere-frontend/src/plugins";
import directives from "metersphere-frontend/src/directive";
import filters from "metersphere-frontend/src/filters";
import "metersphere-frontend/src/router/permission";
import mavonEditor from "mavon-editor";
import "mavon-editor/dist/css/index.css";
import VuePapaParse from "vue-papa-parse";
import VueShepherd from 'vue-shepherd' // 新手引导
import 'metersphere-frontend/src/assets/shepherd/shepherd-theme.css'
@ -29,7 +27,6 @@ Vue.use(ElementUI, {
i18n: (key, value) => i18n.t(key, value),
});
Vue.use(mavonEditor);
Vue.use(svg);
Vue.use(icons);
Vue.use(plugins);

View File

@ -1,5 +1,7 @@
const path = require('path');
const {name} = require('./package');
const path = require("path");
const { name } = require("./package");
const BundleAnalyzerPlugin =
require("webpack-bundle-analyzer").BundleAnalyzerPlugin;
function resolve(dir) {
return path.join(__dirname, dir);
@ -10,41 +12,127 @@ module.exports = {
devServer: {
port: 4002,
client: {
webSocketTransport: 'sockjs',
webSocketTransport: "sockjs",
},
allowedHosts: 'all',
webSocketServer: 'sockjs',
allowedHosts: "all",
webSocketServer: "sockjs",
proxy: {
['^((?!/login)(?!/document))']: {
target: 'http://localhost:8002',
ws: false
["^((?!/login)(?!/document))"]: {
target: "http://localhost:8002",
ws: false,
},
'/websocket': {
target: 'http://localhost:8002',
ws: true
"/websocket": {
target: "http://localhost:8002",
ws: true,
},
},
// 跨域
headers: {
'Access-Control-Allow-Origin': '*',
"Access-Control-Allow-Origin": "*",
},
},
configureWebpack: {
devtool: 'cheap-module-source-map',
devtool: "cheap-module-source-map",
resolve: {
alias: {
'@': resolve('src')
}
"@": resolve("src"),
'vue-i18n': resolve('node_modules/vue-i18n'),
'jsondiffpatch': resolve('node_modules/jsondiffpatch'),
},
},
output: {
// 把子应用打包成 umd 库格式(必须)
library: `${name}-[name]`,
libraryTarget: 'umd',
libraryTarget: "umd",
chunkLoadingGlobal: `webpackJsonp_${name}`,
// 打包后js的名称
filename: `js/${name}-[name].[contenthash:8].js`,
chunkFilename: `js/${name}-[name].[contenthash:8].js`,
},
externals: {
vue: "Vue",
"vue-router": "VueRouter",
// 'echarts': 'echarts',
// 'echarts/core': 'echarts', // TODO:外链使用的话需要改造导入及 vue-echarts 的源码
// brace: 'brace', // TODO:暂时未发现能外链的方法本体包未提供cdn 外链形式的包
"element-ui": "ELEMENT",
"mavon-editor": "MavonEditor",
"vue-shepherd": "VueShepherd",
},
optimization: {
splitChunks: {
cacheGroups: {
"chunk-vendors": {
test: /[\\/]node_modules[\\/]/,
name: "chunk-vendors",
priority: 1,
minChunks: 3,
chunks: "all",
},
"chunk-common": {
test: /[\\/]src[\\/]/,
name: "chunk-common",
priority: 1,
minChunks: 5,
chunks: "all",
},
html2canvas: {
test: /[\\/]html2canvas[\\/]/,
name: "html2canvas",
priority: 2,
chunks: "all",
},
fortawesome: {
test: /[\\/]@fortawesome[\\/]/,
name: "fortawesome",
priority: 2,
chunks: "all",
},
"el-tree-transfer": {
test: /[\\/]el-tree-transfer[\\/]/,
name: "el-tree-transfer",
priority: 2,
chunks: "all",
},
pinia: {
test: /[\\/]pinia[\\/]/,
name: "pinia",
priority: 3,
chunks: "all",
},
brace: {
test: /[\\/]brace[\\/]/,
name: "brace",
priority: 3,
chunks: "all",
},
jspdf: {
test: /[\\/]jspdf[\\/]/,
name: "jspdf",
priority: 2,
chunks: "all",
},
jsondiffpatch: {
test: /[\\/]jsondiffpatch[\\/]/,
name: "jsondiffpatch",
priority: 2,
chunks: "all",
},
jsencrypt: {
test: /[\\/]jsencrypt[\\/]/,
name: "jsencrypt",
priority: 2,
chunks: "all",
},
mockjs: {
test: /[\\/]mockjs[\\/]/,
name: "mockjs",
priority: 2,
chunks: "all",
},
},
},
},
},
css: {
// 将组件内的 CSS 提取到一个单独的 CSS 文件 (只用在生产环境中)
@ -54,23 +142,37 @@ module.exports = {
extract: {
ignoreOrder: true,
filename: `css/${name}-[name].[contenthash:8].css`,
chunkFilename: `css/${name}-[name].[contenthash:8].css`
chunkFilename: `css/${name}-[name].[contenthash:8].css`,
},
},
chainWebpack: config => {
chainWebpack: (config) => {
config.module
.rule('svg')
.exclude.add(resolve('../../framework/sdk-parent/frontend/src/assets/module'))
.end()
.rule("svg")
.exclude.add(
resolve("../../framework/sdk-parent/frontend/src/assets/module")
)
.end();
config.module
.rule('icons')
.rule("icons")
.test(/\.svg$/)
.include.add(resolve('../../framework/sdk-parent/frontend/src/assets/module'))
.include.add(
resolve("../../framework/sdk-parent/frontend/src/assets/module")
)
.end()
.use('svg-sprite-loader')
.loader('svg-sprite-loader')
.use("svg-sprite-loader")
.loader("svg-sprite-loader")
.options({
symbolId: 'icon-[name]'
})
symbolId: "icon-[name]",
});
if (process.env.NODE_ENV === "analyze") {
config.plugin("webpack-report").use(BundleAnalyzerPlugin, [
{
analyzerMode: "static",
reportFilename: "./webpack-report.html",
openAnalyzer: false,
},
]);
}
},
};

View File

@ -5,7 +5,8 @@
"scripts": {
"report": "vue-cli-service serve",
"build": "vue-cli-service build",
"lint": "vue-cli-service lint"
"lint": "vue-cli-service lint",
"build:report": "NODE_ENV=analyze vue-cli-service build"
},
"dependencies": {
"@ckeditor/ckeditor5-build-classic": "^18.0.0",
@ -83,7 +84,8 @@
"sass": "^1.43.4",
"sass-loader": "^10.1.1",
"svg-sprite-loader": "^6.0.11",
"vue-template-compiler": "^2.7.3"
"vue-template-compiler": "^2.7.3",
"webpack-bundle-analyzer": "^4.8.0"
},
"eslintConfig": {
"root": true,

View File

@ -6,6 +6,21 @@
<meta name="viewport" content="width=device-width,initial-scale=1.0">
<link rel="icon" href="<%= BASE_URL %>favicon.ico">
<title><%= htmlWebpackPlugin.options.title %></title>
<% if (process.env.NODE_ENV==='development' ) { %>
<link rel="stylesheet" href="http://localhost:3000/js/dev/element-ui/element-ui.css" />
<script src="http://localhost:3000/js/dev/vue.js"></script>
<script src="http://localhost:3000/js/dev/element-ui/element-ui.js"></script>
<script src="http://localhost:3000/js/dev/vue-router.js"></script>
<script src="http://localhost:3000/js/prd/vue-shepherd.min.js"></script>
<script src="http://localhost:3000/js/prd/mavon-editor.js"></script>
<% } else { %>
<link rel="stylesheet" href="<%= BASE_URL %>js/prd/element-ui/element-ui.min.css" />
<script src="<%= BASE_URL %>js/prd/vue.min.js"></script>
<script src="<%= BASE_URL %>js/prd/element-ui/element-ui.min.js"></script>
<script src="<%= BASE_URL %>js/prd/vue-router.min.js"></script>
<script src="<%= BASE_URL %>js/prd/vue-shepherd.min.js"></script>
<script src="<%= BASE_URL %>js/prd/mavon-editor.js"></script>
<% } %>
</head>
<body>
<noscript>

View File

@ -43,7 +43,7 @@
<script>
import { hasPermission } from "metersphere-frontend/src/utils/permission";
import html2canvas from "html2canvas";
// import html2canvas from "html2canvas";
export default {
name: "ReportHeader",

View File

@ -108,7 +108,7 @@ import TestAnalysisContainer from "@/business/projectstatistics/track/TestAnalys
import MsDrawer from "metersphere-frontend/src/components/MsDrawer";
import ReportHeader from "@/business/base/ReportHeader";
import TestCaseCountContainer from "@/business/projectstatistics/casecount/TestCaseCountContainer";
import html2canvas from "html2canvas";
// import html2canvas from "html2canvas";
export default {
name: "ReportAnalysis",

View File

@ -87,7 +87,7 @@
<script>
import MsChart from "metersphere-frontend/src/components/chart/MsChart";
import html2canvas from "html2canvas";
// import html2canvas from "html2canvas";
export default {
name: "TestCaseCountChart",

View File

@ -71,7 +71,7 @@
<script>
//
import echarts from "echarts";
// import echarts from "echarts";
import MsChart from "metersphere-frontend/src/components/chart/MsChart";
export default {

View File

@ -1,4 +1,4 @@
import el from "element-ui/lib/locale/lang/en";
import el from "metersphere-frontend/src/i18n/lang/ele-en-US";
import fu from "fit2cloud-ui/src/locale/lang/en_US"; // 加载fit2cloud的内容
import mf from "metersphere-frontend/src/i18n/lang/en-US"

View File

@ -1,4 +1,4 @@
import el from "element-ui/lib/locale/lang/zh-CN"; // 加载element的内容
import el from "metersphere-frontend/src/i18n/lang/ele-zh-CN"; // 加载element的内容
import fu from "fit2cloud-ui/src/locale/lang/zh-CN"; // 加载fit2cloud的内容
import mf from "metersphere-frontend/src/i18n/lang/zh-CN"

View File

@ -1,4 +1,4 @@
import el from "element-ui/lib/locale/lang/zh-TW";
import el from "metersphere-frontend/src/i18n/lang/ele-zh-TW";
import fu from "fit2cloud-ui/src/locale/lang/zh-TW"; // 加载fit2cloud的内容
import mf from "metersphere-frontend/src/i18n/lang/zh-TW"

View File

@ -14,8 +14,6 @@ import directives from "metersphere-frontend/src/directive";
import filters from "metersphere-frontend/src/filters";
import "metersphere-frontend/src/router/permission";
import chart from "metersphere-frontend/src/chart"
import mavonEditor from 'mavon-editor';
import 'mavon-editor/dist/css/index.css'
import VueShepherd from 'vue-shepherd'; // 新手引导
import 'metersphere-frontend/src/assets/shepherd/shepherd-theme.css';
import { gotoCancel, gotoNext } from "metersphere-frontend/src/utils";
@ -37,7 +35,6 @@ Vue.use(directives);
Vue.use(filters);
Vue.use(PiniaVuePlugin);
Vue.use(chart);
Vue.use(mavonEditor)
Vue.use(VueShepherd);
Vue.prototype.gotoCancel = gotoCancel;

View File

@ -1,11 +1,18 @@
<!DOCTYPE html>
<html lang="zh">
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width,initial-scale=1.0">
<link rel="shortcut icon" href="<%= BASE_URL %>favicon.ico">
<meta charset="utf-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<meta name="viewport" content="width=device-width,initial-scale=1.0" />
<link rel="shortcut icon" href="<%= BASE_URL %>favicon.ico" />
<title>Enterprise Report</title>
<link
rel="stylesheet"
href="<%= BASE_URL %>js/prd/element-ui/element-ui.min.css"
/>
<script src="<%= BASE_URL %>js/prd/vue.min.js"></script>
<script src="<%= BASE_URL %>js/prd/element-ui/element-ui.min.js"></script>
<script src="<%= BASE_URL %>js/prd/mavon-editor.js"></script>
</head>
<body>
<div id="shareEnterpriseReport"></div>

View File

@ -1,5 +1,7 @@
const path = require('path');
const {name} = require('./package');
const path = require("path");
const { name } = require("./package");
const BundleAnalyzerPlugin =
require("webpack-bundle-analyzer").BundleAnalyzerPlugin;
function resolve(dir) {
return path.join(__dirname, dir);
@ -10,30 +12,30 @@ module.exports = {
devServer: {
port: 4006,
client: {
webSocketTransport: 'sockjs',
webSocketTransport: "sockjs",
},
allowedHosts: 'all',
webSocketServer: 'sockjs',
allowedHosts: "all",
webSocketServer: "sockjs",
proxy: {
['^((?!/login)(?!/document))']: {
target: 'http://localhost:8006',
ws: false
["^((?!/login)(?!/document))"]: {
target: "http://localhost:8006",
ws: false,
},
'/websocket': {
target: 'http://localhost:8006',
ws: true
"/websocket": {
target: "http://localhost:8006",
ws: true,
},
},
// 跨域
headers: {
'Access-Control-Allow-Origin': '*',
"Access-Control-Allow-Origin": "*",
},
},
pages: {
index: {
entry: "src/main.js",
template: "public/index.html",
filename: "index.html"
filename: "index.html",
},
shareEnterpriseReport: {
entry: "src/template/enterprise/share/share-enterprise-report.js",
@ -42,21 +44,101 @@ module.exports = {
},
},
configureWebpack: {
devtool: 'cheap-module-source-map',
devtool: "cheap-module-source-map",
resolve: {
alias: {
'@': resolve('src')
}
"@": resolve("src"),
'vue-i18n': resolve('node_modules/vue-i18n'),
'html2canvas': resolve('node_modules/html2canvas'),
},
},
output: {
// 把子应用打包成 umd 库格式(必须)
library: `${name}-[name]`,
libraryTarget: 'umd',
libraryTarget: "umd",
chunkLoadingGlobal: `webpackJsonp_${name}`,
// 打包后js的名称
filename: `js/${name}-[name].[contenthash:8].js`,
chunkFilename: `js/${name}-[name].[contenthash:8].js`,
},
externals: {
vue: "Vue",
"vue-router": "VueRouter",
// 'echarts': 'echarts',
// 'echarts/core': 'echarts', // TODO:外链使用的话需要改造导入及 vue-echarts 的源码
// brace: 'brace', // TODO:暂时未发现能外链的方法本体包未提供cdn 外链形式的包
"element-ui": "ELEMENT",
"mavon-editor": "MavonEditor",
"vue-shepherd": "VueShepherd",
},
optimization: {
splitChunks: {
cacheGroups: {
"chunk-vendors": {
test: /[\\/]node_modules[\\/]/,
name: "chunk-vendors",
priority: 1,
minChunks: 3,
chunks: "all",
},
"chunk-common": {
test: /[\\/]src[\\/]/,
name: "chunk-common",
priority: 1,
minChunks: 5,
chunks: "all",
},
html2canvas: {
test: /[\\/]html2canvas[\\/]/,
name: "html2canvas",
priority: 2,
chunks: "all",
},
fortawesome: {
test: /[\\/]@fortawesome[\\/]/,
name: "fortawesome",
priority: 2,
chunks: "all",
},
"el-tree-transfer": {
test: /[\\/]el-tree-transfer[\\/]/,
name: "el-tree-transfer",
priority: 2,
chunks: "all",
},
pinia: {
test: /[\\/]pinia[\\/]/,
name: "pinia",
priority: 3,
chunks: "all",
},
brace: {
test: /[\\/]brace[\\/]/,
name: "brace",
priority: 3,
chunks: "all",
},
echarts: {
test: /[\\/](echarts|zrender)[\\/]/,
name: "echarts",
priority: 3,
chunks: "all",
},
jspdf: {
test: /[\\/]jspdf[\\/]/,
name: "jspdf",
priority: 2,
chunks: "all",
},
jsencrypt: {
test: /[\\/]jsencrypt[\\/]/,
name: "jsencrypt",
priority: 2,
chunks: "all",
},
},
},
},
},
css: {
// 将组件内的 CSS 提取到一个单独的 CSS 文件 (只用在生产环境中)
@ -66,23 +148,37 @@ module.exports = {
extract: {
ignoreOrder: true,
filename: `css/${name}-[name].[contenthash:8].css`,
chunkFilename: `css/${name}-[name].[contenthash:8].css`
chunkFilename: `css/${name}-[name].[contenthash:8].css`,
},
},
chainWebpack: config => {
chainWebpack: (config) => {
config.module
.rule('svg')
.exclude.add(resolve('../../framework/sdk-parent/frontend/src/assets/module'))
.end()
.rule("svg")
.exclude.add(
resolve("../../framework/sdk-parent/frontend/src/assets/module")
)
.end();
config.module
.rule('icons')
.rule("icons")
.test(/\.svg$/)
.include.add(resolve('../../framework/sdk-parent/frontend/src/assets/module'))
.include.add(
resolve("../../framework/sdk-parent/frontend/src/assets/module")
)
.end()
.use('svg-sprite-loader')
.loader('svg-sprite-loader')
.use("svg-sprite-loader")
.loader("svg-sprite-loader")
.options({
symbolId: 'icon-[name]'
})
symbolId: "icon-[name]",
});
if (process.env.NODE_ENV === "analyze") {
config.plugin("webpack-report").use(BundleAnalyzerPlugin, [
{
analyzerMode: "static",
reportFilename: "./webpack-report.html",
openAnalyzer: false,
},
]);
}
},
};

View File

@ -5,7 +5,8 @@
"scripts": {
"setting": "vue-cli-service serve",
"build": "vue-cli-service build",
"lint": "vue-cli-service lint"
"lint": "vue-cli-service lint",
"report": "NODE_ENV=analyze vue-cli-service build"
},
"dependencies": {
"@ckeditor/ckeditor5-build-classic": "^18.0.0",
@ -83,7 +84,8 @@
"sass": "^1.43.4",
"sass-loader": "^10.1.1",
"svg-sprite-loader": "^6.0.11",
"vue-template-compiler": "^2.7.3"
"vue-template-compiler": "^2.7.3",
"webpack-bundle-analyzer": "^4.8.0"
},
"eslintConfig": {
"root": true,

View File

@ -6,6 +6,21 @@
<meta name="viewport" content="width=device-width,initial-scale=1.0">
<link rel="icon" href="<%= BASE_URL %>favicon.ico">
<title><%= htmlWebpackPlugin.options.title %></title>
<% if (process.env.NODE_ENV==='development' ) { %>
<link rel="stylesheet" href="http://localhost:3000/js/dev/element-ui/element-ui.css" />
<script src="http://localhost:3000/js/dev/vue.js"></script>
<script src="http://localhost:3000/js/dev/element-ui/element-ui.js"></script>
<script src="http://localhost:3000/js/dev/vue-router.js"></script>
<script src="http://localhost:3000/js/prd/vue-shepherd.min.js"></script>
<script src="http://localhost:3000/js/prd/mavon-editor.js"></script>
<% } else { %>
<link rel="stylesheet" href="<%= BASE_URL %>js/prd/element-ui/element-ui.min.css" />
<script src="<%= BASE_URL %>js/prd/vue.min.js"></script>
<script src="<%= BASE_URL %>js/prd/element-ui/element-ui.min.js"></script>
<script src="<%= BASE_URL %>js/prd/vue-router.min.js"></script>
<script src="<%= BASE_URL %>js/prd/vue-shepherd.min.js"></script>
<script src="<%= BASE_URL %>js/prd/mavon-editor.js"></script>
<% } %>
</head>
<body>
<noscript>

View File

@ -58,8 +58,8 @@
import {getLogDetailById} from "../../api/operating-log";
import RequestLogDetail from "@/business/common/RequestLogDetail";
const jsondiffpatch = require('jsondiffpatch');
const formattersHtml = jsondiffpatch.formatters.html;
import {formatters, diff} from 'jsondiffpatch';
const formattersHtml = formatters.html;
export default {
name: "MsLogDetail",
@ -147,10 +147,10 @@ const jsondiffpatch = require('jsondiffpatch');
},
getDiff(v1, v2) {
if(typeof v1 === 'string' && typeof v2 === 'string' && v1.indexOf("{") !==-1 && v2.indexOf("{") !==-1 ){
let delta = jsondiffpatch.diff(JSON.parse(v1), JSON.parse(v2));
let delta = diff(JSON.parse(v1), JSON.parse(v2));
return formattersHtml.format(delta,delta);
}else{
let delta = jsondiffpatch.diff(v1, v2);
let delta = diff(v1, v2);
return formattersHtml.format(delta,v1);
}
},

View File

@ -1,4 +1,4 @@
import el from "element-ui/lib/locale/lang/en";
import el from "metersphere-frontend/src/i18n/lang/ele-en-US";
import fu from "fit2cloud-ui/src/locale/lang/en_US"; // 加载fit2cloud的内容
import mf from "metersphere-frontend/src/i18n/lang/en-US"

View File

@ -1,4 +1,4 @@
import el from "element-ui/lib/locale/lang/zh-CN"; // 加载element的内容
import el from "metersphere-frontend/src/i18n/lang/ele-zh-CN"; // 加载element的内容
import fu from "fit2cloud-ui/src/locale/lang/zh-CN"; // 加载fit2cloud的内容
import mf from "metersphere-frontend/src/i18n/lang/zh-CN"

View File

@ -1,4 +1,4 @@
import el from "element-ui/lib/locale/lang/zh-TW";
import el from "metersphere-frontend/src/i18n/lang/ele-zh-TW";
import fu from "fit2cloud-ui/src/locale/lang/zh-TW"; // 加载fit2cloud的内容
import mf from "metersphere-frontend/src/i18n/lang/zh-TW"

View File

@ -1,5 +1,7 @@
const path = require('path');
const {name} = require('./package');
const path = require("path");
const { name } = require("./package");
const BundleAnalyzerPlugin =
require("webpack-bundle-analyzer").BundleAnalyzerPlugin;
function resolve(dir) {
return path.join(__dirname, dir);
@ -10,41 +12,127 @@ module.exports = {
devServer: {
port: 4001,
client: {
webSocketTransport: 'sockjs',
webSocketTransport: "sockjs",
},
allowedHosts: 'all',
webSocketServer: 'sockjs',
allowedHosts: "all",
webSocketServer: "sockjs",
proxy: {
['^((?!/login)(?!/document))']: {
target: 'http://localhost:8001',
ws: false
["^((?!/login)(?!/document))"]: {
target: "http://localhost:8001",
ws: false,
},
'/websocket': {
target: 'http://localhost:8001',
ws: true
"/websocket": {
target: "http://localhost:8001",
ws: true,
},
},
// 跨域
headers: {
'Access-Control-Allow-Origin': '*',
"Access-Control-Allow-Origin": "*",
},
},
configureWebpack: {
devtool: 'cheap-module-source-map',
devtool: "cheap-module-source-map",
resolve: {
alias: {
'@': resolve('src')
}
"@": resolve("src"),
'vue-i18n': resolve('node_modules/vue-i18n'),
'jsondiffpatch': resolve('node_modules/jsondiffpatch'),
},
},
output: {
// 把子应用打包成 umd 库格式(必须)
library: `${name}-[name]`,
libraryTarget: 'umd',
libraryTarget: "umd",
chunkLoadingGlobal: `webpackJsonp_${name}`,
// 打包后js的名称
filename: `js/${name}-[name].[contenthash:8].js`,
chunkFilename: `js/${name}-[name].[contenthash:8].js`,
},
externals: {
vue: "Vue",
"vue-router": "VueRouter",
// 'echarts': 'echarts',
// 'echarts/core': 'echarts', // TODO:外链使用的话需要改造导入及 vue-echarts 的源码
// brace: 'brace', // TODO:暂时未发现能外链的方法本体包未提供cdn 外链形式的包
"element-ui": "ELEMENT",
"mavon-editor": "MavonEditor",
"vue-shepherd": "VueShepherd",
},
optimization: {
splitChunks: {
cacheGroups: {
"chunk-vendors": {
test: /[\\/]node_modules[\\/]/,
name: "chunk-vendors",
priority: 1,
minChunks: 3,
chunks: "all",
},
"chunk-common": {
test: /[\\/]src[\\/]/,
name: "chunk-common",
priority: 1,
minChunks: 5,
chunks: "all",
},
html2canvas: {
test: /[\\/]html2canvas[\\/]/,
name: "html2canvas",
priority: 2,
chunks: "all",
},
fortawesome: {
test: /[\\/]@fortawesome[\\/]/,
name: "fortawesome",
priority: 2,
chunks: "all",
},
"el-tree-transfer": {
test: /[\\/]el-tree-transfer[\\/]/,
name: "el-tree-transfer",
priority: 2,
chunks: "all",
},
pinia: {
test: /[\\/]pinia[\\/]/,
name: "pinia",
priority: 3,
chunks: "all",
},
brace: {
test: /[\\/]brace[\\/]/,
name: "brace",
priority: 3,
chunks: "all",
},
jspdf: {
test: /[\\/]jspdf[\\/]/,
name: "jspdf",
priority: 2,
chunks: "all",
},
jsondiffpatch: {
test: /[\\/]jsondiffpatch[\\/]/,
name: "jsondiffpatch",
priority: 2,
chunks: "all",
},
jsencrypt: {
test: /[\\/]jsencrypt[\\/]/,
name: "jsencrypt",
priority: 2,
chunks: "all",
},
mockjs: {
test: /[\\/]mockjs[\\/]/,
name: "mockjs",
priority: 2,
chunks: "all",
},
},
},
},
},
css: {
// 将组件内的 CSS 提取到一个单独的 CSS 文件 (只用在生产环境中)
@ -54,23 +142,37 @@ module.exports = {
extract: {
ignoreOrder: true,
filename: `css/${name}-[name].[contenthash:8].css`,
chunkFilename: `css/${name}-[name].[contenthash:8].css`
chunkFilename: `css/${name}-[name].[contenthash:8].css`,
},
},
chainWebpack: config => {
chainWebpack: (config) => {
config.module
.rule('svg')
.exclude.add(resolve('../../framework/sdk-parent/frontend/src/assets/module'))
.end()
.rule("svg")
.exclude.add(
resolve("../../framework/sdk-parent/frontend/src/assets/module")
)
.end();
config.module
.rule('icons')
.rule("icons")
.test(/\.svg$/)
.include.add(resolve('../../framework/sdk-parent/frontend/src/assets/module'))
.include.add(
resolve("../../framework/sdk-parent/frontend/src/assets/module")
)
.end()
.use('svg-sprite-loader')
.loader('svg-sprite-loader')
.use("svg-sprite-loader")
.loader("svg-sprite-loader")
.options({
symbolId: 'icon-[name]'
})
symbolId: "icon-[name]",
});
if (process.env.NODE_ENV === "analyze") {
config.plugin("webpack-report").use(BundleAnalyzerPlugin, [
{
analyzerMode: "static",
reportFilename: "./webpack-report.html",
openAnalyzer: false,
},
]);
}
},
};

View File

@ -5,7 +5,8 @@
"scripts": {
"track": "vue-cli-service serve",
"build": "vue-cli-service build",
"lint": "vue-cli-service lint"
"lint": "vue-cli-service lint",
"report": "NODE_ENV=analyze vue-cli-service build"
},
"dependencies": {
"@ckeditor/ckeditor5-build-classic": "^18.0.0",
@ -16,7 +17,6 @@
"@fortawesome/free-regular-svg-icons": "^5.12.0",
"@fortawesome/free-solid-svg-icons": "^5.12.0",
"@fortawesome/vue-fontawesome": "^0.1.9",
"stream-browserify": "^2.0.1",
"axios": "^0.27.2",
"diffable-html": "^4.0.0",
"echarts": "^5.0.2",
@ -52,6 +52,8 @@
"pinia": "^2.0.14",
"pinia-plugin-persistedstate": "^1.6.3",
"sha.js": "^2.4.11",
"shepherd.js": "^10.0.0",
"stream-browserify": "^2.0.1",
"vue": "^2.7.3",
"vue-calendar-heatmap": "^0.8.4",
"vue-clipboard2": "^0.3.1",
@ -62,13 +64,12 @@
"vue-minder-editor-plus": "1.1.8",
"vue-papa-parse": "^2.0.0",
"vue-router": "^3.1.3",
"vue-shepherd": "^0.3.0",
"vue-virtual-scroll-list": "^2.3.3",
"vue2-ace-editor": "0.0.15",
"vuedraggable": "^2.24.3",
"xml-js": "^1.6.11",
"yan-progress": "^1.0.3",
"vue-shepherd": "^0.3.0",
"shepherd.js": "^10.0.0"
"yan-progress": "^1.0.3"
},
"devDependencies": {
"@babel/core": "^7.12.16",
@ -80,12 +81,14 @@
"core-js": "^3.19.1",
"eslint": "^7.32.0",
"eslint-plugin-vue": "^7.20.0",
"html-webpack-inline-source-plugin": "1.0.0-beta.2",
"inline-source-webpack-plugin": "^3.0.1",
"mockjs": "^1.1.0",
"sass": "^1.43.4",
"sass-loader": "^10.1.1",
"svg-sprite-loader": "^6.0.11",
"vue-template-compiler": "^2.7.3",
"html-webpack-inline-source-plugin": "1.0.0-beta.2"
"webpack-bundle-analyzer": "^4.8.0"
},
"eslintConfig": {
"root": true,

Some files were not shown because too many files have changed in this diff Show More