From a8e0184c68add0ce36048bda0845a379761c699b Mon Sep 17 00:00:00 2001 From: terlinhe <312592676@qq.com> Date: Wed, 1 Dec 2021 02:16:52 -0600 Subject: [PATCH] lesscode-master: v0.3.0 (#663) --- paas-ce/lesscode/.babelrc | 9 +- paas-ce/lesscode/.eslintignore | 1 + paas-ce/lesscode/.eslintrc.js | 190 +++++++- paas-ce/lesscode/.gitignore | 3 + .../lib/client/build/webpack.base.conf.js | 160 ++++--- .../lesscode/lib/client/src/api/pureAxios.js | 17 +- .../lib/client/src/common/dom-to-image.js | 2 +- .../client/src/common/process-targetdata.js | 1 + .../client/src/common/tnpm-version-valid.js | 14 +- .../src/components/choose-data-table.vue | 65 +++ .../lib/client/src/components/copy-icon.js | 33 ++ .../components/field-table/field-table.css | 87 ++++ .../components/field-table/field-table.tsx | 385 ++++++++++++++++ .../methods/func-form/form-items/code.vue | 2 +- .../methods/func-form/form-items/detail.vue | 20 +- .../methods/func-form/form-items/monaco.vue | 28 +- .../methods/func-form/form-items/name.vue | 2 +- .../methods/func-form/form-items/project.vue | 2 +- .../{source-market.vue => source-func.vue} | 0 .../src/components/methods/function-helper.js | 23 +- .../client/src/components/methods/index.vue | 29 +- .../client/src/components/methods/monaco.vue | 5 +- .../components/methods/provide-completion.js | 4 +- .../src/components/methods/select-func.vue | 2 +- .../components/project-version-selector.vue | 139 ++++++ .../components/project/edit-route-dialog.vue | 3 + .../components/project/layout-thumb-list.vue | 44 +- .../src/components/project/page-dialog.vue | 10 +- .../project/page-from-template-dialog.vue | 20 +- .../components/render/component-wrapper.js | 4 +- .../src/components/render/component.css | 4 + .../render/save-template-dialog.vue | 9 +- .../src/components/ui/project-version-tag.vue | 24 + .../variable/variable-form/index.vue | 11 +- .../version-log.vue | 21 +- .../client/src/components/vue-code/index.vue | 10 +- .../widget/layout/components/complex.vue | 4 +- .../widget/layout/components/left-right.vue | 4 +- .../widget/layout/components/top-bottom.vue | 4 +- .../src/components/widget/layout/index.vue | 37 +- .../lesscode/lib/client/src/css/common.css | 37 ++ .../materials/bk/color-picker/index.js | 5 +- .../materials/bk/diff/index.js | 2 +- .../materials/bk/free-layout/index.js | 2 +- .../materials/bk/grid/extends.js | 2 +- .../materials/bk/input/index.js | 2 +- .../materials/bk/link/index.js | 2 +- .../materials/bk/select/index.js | 2 +- .../materials/bk/table/index.js | 2 +- .../materials/bk/timeline/index.js | 2 +- .../materials/bk/upload/index.js | 2 +- .../materials/element/table/index.js | 2 +- .../modifier/component/directives/index.vue | 1 + .../modifier/component/index.vue | 3 +- .../props/components/render-prop.vue | 30 +- .../props/components/strategy/data-source.vue | 57 +++ .../props/components/strategy/remote.vue | 12 +- .../components/strategy/table-column.vue | 2 +- .../components/strategy/table-data-source.vue | 80 ++++ .../slots/components/data-source.vue | 63 +++ .../slots/components/form-item-edit.vue | 26 +- .../component/slots/components/form-item.vue | 32 +- .../component/slots/components/table.vue | 11 +- .../modifier/component/slots/index.vue | 6 + .../component/slots/render-config/bk/index.js | 1 + .../slots/render-config/element/index.js | 1 + .../modifier/component/slots/slot.vue | 26 +- .../modifier/component/styles/index.vue | 4 +- .../component/styles/strategy/min-width.vue | 77 ++++ .../component/styles/strategy/size.vue | 44 +- paas-ce/lesscode/lib/client/src/main.js | 4 + .../lib/client/src/preview/component.js | 4 +- .../lesscode/lib/client/src/preview/index.js | 15 +- .../lesscode/lib/client/src/router/index.js | 58 ++- .../lesscode/lib/client/src/store/index.js | 6 +- .../client/src/store/modules/data-source.js | 87 ++++ .../lib/client/src/store/modules/functions.js | 4 +- .../lib/client/src/store/modules/layout.js | 12 +- .../client/src/store/modules/page-template.js | 14 +- .../lib/client/src/store/modules/page.js | 4 +- .../src/store/modules/project-version.js | 89 ++++ .../lib/client/src/store/modules/release.js | 8 +- .../lib/client/src/store/modules/route.js | 16 +- .../lib/client/src/store/modules/variable.js | 11 +- .../lib/client/src/views/changelog/index.md | 14 + .../lib/client/src/views/index/index.css | 32 +- .../lib/client/src/views/index/index.vue | 52 ++- .../src/views/preview/preview-template.vue | 54 ++- .../all/components/operation.vue | 2 +- .../all/components/render-list.vue | 2 +- .../views/project/component-manage/index.vue | 36 +- .../project/component-manage/useing/index.vue | 56 ++- .../common/confirm-dialog.vue | 85 ++++ .../data-source-manage/common/export.vue | 167 +++++++ .../data-source-manage/common/field-table.tsx | 340 ++++++++++++++ .../data-source-manage/common/header.tsx | 29 ++ .../data-source-manage/common/import.vue | 82 ++++ .../data-source-manage/common/info-table.vue | 171 +++++++ .../common/show-column-table.vue | 43 ++ .../data-source-manage/data-manage/index.vue | 266 +++++++++++ .../data-manage/render-api.vue | 233 ++++++++++ .../data-manage/render-data.vue | 416 ++++++++++++++++++ .../data-manage/render-function.vue | 247 +++++++++++ .../data-manage/render-struct.vue | 54 +++ .../project/data-source-manage/index.vue | 8 + .../table-design/composables/table-info.ts | 63 +++ .../table-design/create-table.vue | 226 ++++++++++ .../table-design/edit-table.vue | 244 ++++++++++ .../table-design/show-table.vue | 148 +++++++ .../table-design/table-list/index.vue | 42 ++ .../table-design/table-list/list/index.vue | 288 ++++++++++++ .../table-design/update-record.vue | 148 +++++++ .../src/views/project/function-manage.vue | 21 +- .../lib/client/src/views/project/index.vue | 141 ++++-- .../layout/components/layout-dialog.vue | 8 +- .../client/src/views/project/layout/index.vue | 11 +- .../client/src/views/project/page-setting.vue | 337 ++++++++++---- .../src/views/project/page-variable.vue | 2 + .../lib/client/src/views/project/page.vue | 31 +- .../src/views/project/router-manage/index.vue | 11 +- .../components/render-template.vue | 46 +- .../components/template-edit-dialog.vue | 25 +- .../components/template-import-dialog.vue | 194 ++++++++ .../components/template-mixin.js | 32 ++ .../src/views/project/variable-manage.vue | 6 +- .../children/form-sideslider.vue | 184 ++++++++ .../views/project/version-manage/index.vue | 274 ++++++++++++ .../system/components/download-dialog.vue | 3 +- .../system/components/template-dialog.vue | 2 +- .../src/views/system/function-market.vue | 8 +- .../lib/client/src/views/system/projects.vue | 6 +- .../src/views/system/template-market.vue | 11 +- .../lesscode/lib/client/typings/global.d.ts | 17 + .../lib/client/typings/shims-vue.d.ts | 24 + paas-ce/lesscode/lib/server/app.browser.js | 27 +- .../lib/server/conf/data-base.js.example | 30 +- .../lib/server/conf/data-source.js.example | 34 ++ .../lib/server/conf/demo-page-code.js | 6 +- .../server/conf/encrypt-secret-key.js.example | 17 + .../lesscode/lib/server/conf/eslint-config.js | 218 ++++++++- .../server/controller/component-category.js | 2 +- .../lib/server/controller/component.js | 31 +- .../lib/server/controller/data-source.js | 386 ++++++++++++++++ .../server/controller/db-migration-helper.js | 6 +- .../server/controller/db-upgrade-helper.js | 1 + .../lib/server/controller/function-market.js | 2 +- .../lib/server/controller/function.js | 6 +- .../lesscode/lib/server/controller/health.js | 39 +- .../lesscode/lib/server/controller/layout.js | 28 +- .../lib/server/controller/operation.js | 46 +- .../controller/page-template-category.js | 2 +- .../lib/server/controller/page-template.js | 106 ++++- .../lesscode/lib/server/controller/page.js | 53 ++- .../lib/server/controller/project-code.js | 11 +- .../lib/server/controller/project-version.js | 113 +++++ .../lesscode/lib/server/controller/project.js | 2 +- .../lesscode/lib/server/controller/route.js | 24 +- .../lib/server/controller/serverless-web.js | 44 ++ .../lib/server/controller/variable.js | 34 ++ .../lib/server/controller/vue-code.js | 14 +- paas-ce/lesscode/lib/server/custom-global.js | 4 +- .../server/decorator/authorization/index.js | 96 ++++ .../lib/server/decorator/controller/index.js | 13 + .../lib/server/decorator/controller/params.js | 183 ++++++++ .../lib/server/decorator/controller/router.js | 66 +++ .../lesscode/lib/server/decorator/index.js | 14 + .../lib/server/decorator/send/index.js | 95 ++++ paas-ce/lesscode/lib/server/logger.js | 2 +- .../lesscode/lib/server/middleware/auth.js | 5 +- .../lib/server/middleware/request-context.js | 8 +- paas-ce/lesscode/lib/server/model/common.js | 6 + .../server/model/data-table-modify-record.js | 32 ++ .../entities/data-table-modify-record.js | 34 ++ .../lib/server/model/entities/data-table.js | 40 ++ .../lib/server/model/entities/func-func.js | 6 + .../server/model/entities/func-variable.js | 6 + .../lib/server/model/entities/layout-inst.js | 6 + .../lib/server/model/entities/page-comp.js | 6 + .../lib/server/model/entities/page-func.js | 6 + .../lib/server/model/entities/page-route.js | 6 + .../server/model/entities/page-template.js | 6 + .../server/model/entities/page-variable.js | 6 + .../lib/server/model/entities/page.js | 6 + .../lib/server/model/entities/preview-db.js | 40 ++ .../model/entities/project-func-group.js | 6 + .../lib/server/model/entities/project-page.js | 6 + .../server/model/entities/project-version.js | 28 ++ .../lib/server/model/entities/project.js | 7 + .../lib/server/model/entities/role.js | 2 +- .../lib/server/model/entities/token.js | 2 +- .../server/model/entities/variable-func.js | 6 + .../model/entities/variable-variable.js | 6 + .../lib/server/model/entities/variable.js | 6 + paas-ce/lesscode/lib/server/model/function.js | 23 +- paas-ce/lesscode/lib/server/model/health.js | 4 +- paas-ce/lesscode/lib/server/model/layout.js | 4 +- .../migrations/20211014084206-update-sql.js | 53 +++ .../migrations/20211103024457-update-sql.js | 53 +++ .../migrations/20211109090310-update-sql.js | 53 +++ .../migrations/20211124155657-update-sql.js | 53 +++ .../sqls/20211014084206-update-sql-down.sql | 1 + .../sqls/20211014084206-update-sql-up.sql | 3 + .../sqls/20211103024457-update-sql-down.sql | 1 + .../sqls/20211103024457-update-sql-up.sql | 58 +++ .../sqls/20211109090310-update-sql-down.sql | 1 + .../sqls/20211109090310-update-sql-up.sql | 58 +++ .../sqls/20211124155657-update-sql-down.sql | 1 + .../sqls/20211124155657-update-sql-up.sql | 3 + .../lesscode/lib/server/model/page-code.js | 106 +++-- .../lesscode/lib/server/model/page-comp.js | 6 +- .../lib/server/model/page-template.js | 3 +- paas-ce/lesscode/lib/server/model/page.js | 20 +- .../lesscode/lib/server/model/project-code.js | 152 +++++-- .../lib/server/model/project-version.js | 23 + paas-ce/lesscode/lib/server/model/project.js | 3 +- .../lib/server/model/release-version.js | 1 + paas-ce/lesscode/lib/server/model/route.js | 15 +- .../lib/server/model/sql/20211014/update.sql | 3 + .../lib/server/model/sql/20211031/update.sql | 61 +++ .../lib/server/model/sql/20211109/update.sql | 56 +++ .../lib/server/model/sql/20211124/update.sql | 2 + paas-ce/lesscode/lib/server/model/variable.js | 7 +- paas-ce/lesscode/lib/server/model/vue-code.js | 4 +- .../project-template/data-base-template.js | 57 +++ .../data-migration-template.js | 10 + .../project-template/entity-template.js | 6 + .../project-init-code/.babelrc | 11 +- .../project-init-code/.eslintrc.js | 197 ++++++++- .../project-init-code/jsconfig.json | 5 + .../lib/client/src/api/pureAxios.js | 17 +- .../client/src/common/tnpm-version-valid.js | 14 +- .../project-init-code/lib/client/src/main.js | 4 +- .../lib/client/static/lib.bundle.js | 133 +++++- .../lib/server/app.browser.js | 29 +- .../lib/server/controller/data-source.js | 82 ++++ .../lib/server/controller/mock-data.js | 83 ++-- .../lib/server/controller/user.js | 18 +- .../lib/server/custom-global.js | 29 ++ .../lib/server/decorator/controller/index.js | 13 + .../lib/server/decorator/controller/params.js | 183 ++++++++ .../lib/server/decorator/controller/router.js | 66 +++ .../lib/server/decorator/index.js | 13 + .../lib/server/decorator/send/index.js | 26 ++ .../project-init-code/lib/server/logger.js | 75 +++- .../lib/server/middleware/request-context.js | 64 +++ .../lib/server/model/entities/base.js | 42 ++ .../lib/server/router/index.js | 25 +- .../lib/server/router/mock-data.js | 10 - .../lib/server/router/user.js | 10 - .../lib/server/service/data-service.js | 236 ++++++++++ .../project-init-code/lib/server/util.js | 22 + .../project-init-code/package.json | 11 + paas-ce/lesscode/lib/server/router/health.js | 15 +- paas-ce/lesscode/lib/server/router/index.js | 27 +- .../lib/server/router/page-template.js | 2 + .../lib/server/router/project-version.js | 46 ++ .../lesscode/lib/server/router/variable.js | 3 +- .../lib/server/service/data-service.js | 262 +++++++++++ .../lib/server/service/db-engine-service.js | 106 +++++ .../lesscode/lib/server/service/function.js | 90 ++++ paas-ce/lesscode/lib/server/service/layout.js | 39 ++ .../lib/server/service/online-db-service.js | 129 ++++++ paas-ce/lesscode/lib/server/service/page.js | 92 ++++ .../lib/server/service/preview-db-service.js | 131 ++++++ .../lib/server/service/project-version.js | 110 +++++ paas-ce/lesscode/lib/server/service/route.js | 57 +++ .../lesscode/lib/server/service/variable.js | 92 ++++ paas-ce/lesscode/lib/server/util.js | 64 ++- paas-ce/lesscode/lib/server/utils/constant.js | 2 +- .../lib/server/utils/file-service/index.js | 4 +- .../lesscode/lib/server/utils/http/index.js | 41 ++ .../lesscode/lib/server/utils/lc-compose.js | 43 ++ .../lesscode/lib/server/utils/npm/index.js | 2 +- .../lib/shared/data-source/constant.js | 130 ++++++ .../shared/data-source/data-parse/common.js | 144 ++++++ .../data-parse/data-parser/csv-parser.js | 55 +++ .../data-parse/data-parser/json-parser.js | 49 +++ .../data-parse/data-parser/sql-parser.js | 71 +++ .../shared/data-source/data-parse/index.js | 54 +++ .../data-parse/struct-parser/csv-parser.js | 61 +++ .../data-parse/struct-parser/json-parser.js | 40 ++ .../data-parse/struct-parser/sql-parser.js | 270 ++++++++++++ .../lesscode/lib/shared/data-source/helper.js | 71 +++ .../lesscode/lib/shared/data-source/index.js | 20 + .../lesscode/lib/shared/function/constant.js | 75 ++++ paas-ce/lesscode/lib/shared/function/index.js | 12 + paas-ce/lesscode/lib/shared/index.js | 18 + paas-ce/lesscode/lib/shared/util.js | 51 +++ .../lesscode/lib/shared/variable/constant.js | 44 ++ paas-ce/lesscode/package.json | 25 +- paas-ce/lesscode/tsconfig.json | 43 ++ 291 files changed, 13292 insertions(+), 907 deletions(-) create mode 100644 paas-ce/lesscode/.eslintignore create mode 100644 paas-ce/lesscode/lib/client/src/components/choose-data-table.vue create mode 100644 paas-ce/lesscode/lib/client/src/components/copy-icon.js create mode 100644 paas-ce/lesscode/lib/client/src/components/field-table/field-table.css create mode 100644 paas-ce/lesscode/lib/client/src/components/field-table/field-table.tsx rename paas-ce/lesscode/lib/client/src/components/methods/func-form/{source-market.vue => source-func.vue} (100%) create mode 100644 paas-ce/lesscode/lib/client/src/components/project-version-selector.vue create mode 100644 paas-ce/lesscode/lib/client/src/components/ui/project-version-tag.vue rename paas-ce/lesscode/lib/client/src/{views/project/component-manage => components}/version-log.vue (66%) create mode 100644 paas-ce/lesscode/lib/client/src/element-materials/modifier/component/props/components/strategy/data-source.vue create mode 100644 paas-ce/lesscode/lib/client/src/element-materials/modifier/component/props/components/strategy/table-data-source.vue create mode 100644 paas-ce/lesscode/lib/client/src/element-materials/modifier/component/slots/components/data-source.vue create mode 100644 paas-ce/lesscode/lib/client/src/element-materials/modifier/component/styles/strategy/min-width.vue create mode 100644 paas-ce/lesscode/lib/client/src/store/modules/data-source.js create mode 100644 paas-ce/lesscode/lib/client/src/store/modules/project-version.js create mode 100644 paas-ce/lesscode/lib/client/src/views/project/data-source-manage/common/confirm-dialog.vue create mode 100644 paas-ce/lesscode/lib/client/src/views/project/data-source-manage/common/export.vue create mode 100644 paas-ce/lesscode/lib/client/src/views/project/data-source-manage/common/field-table.tsx create mode 100644 paas-ce/lesscode/lib/client/src/views/project/data-source-manage/common/header.tsx create mode 100644 paas-ce/lesscode/lib/client/src/views/project/data-source-manage/common/import.vue create mode 100644 paas-ce/lesscode/lib/client/src/views/project/data-source-manage/common/info-table.vue create mode 100644 paas-ce/lesscode/lib/client/src/views/project/data-source-manage/common/show-column-table.vue create mode 100644 paas-ce/lesscode/lib/client/src/views/project/data-source-manage/data-manage/index.vue create mode 100644 paas-ce/lesscode/lib/client/src/views/project/data-source-manage/data-manage/render-api.vue create mode 100644 paas-ce/lesscode/lib/client/src/views/project/data-source-manage/data-manage/render-data.vue create mode 100644 paas-ce/lesscode/lib/client/src/views/project/data-source-manage/data-manage/render-function.vue create mode 100644 paas-ce/lesscode/lib/client/src/views/project/data-source-manage/data-manage/render-struct.vue create mode 100644 paas-ce/lesscode/lib/client/src/views/project/data-source-manage/index.vue create mode 100644 paas-ce/lesscode/lib/client/src/views/project/data-source-manage/table-design/composables/table-info.ts create mode 100644 paas-ce/lesscode/lib/client/src/views/project/data-source-manage/table-design/create-table.vue create mode 100644 paas-ce/lesscode/lib/client/src/views/project/data-source-manage/table-design/edit-table.vue create mode 100644 paas-ce/lesscode/lib/client/src/views/project/data-source-manage/table-design/show-table.vue create mode 100644 paas-ce/lesscode/lib/client/src/views/project/data-source-manage/table-design/table-list/index.vue create mode 100644 paas-ce/lesscode/lib/client/src/views/project/data-source-manage/table-design/table-list/list/index.vue create mode 100644 paas-ce/lesscode/lib/client/src/views/project/data-source-manage/table-design/update-record.vue create mode 100644 paas-ce/lesscode/lib/client/src/views/project/template-manage/components/template-import-dialog.vue create mode 100644 paas-ce/lesscode/lib/client/src/views/project/template-manage/components/template-mixin.js create mode 100644 paas-ce/lesscode/lib/client/src/views/project/version-manage/children/form-sideslider.vue create mode 100644 paas-ce/lesscode/lib/client/src/views/project/version-manage/index.vue create mode 100644 paas-ce/lesscode/lib/client/typings/global.d.ts create mode 100644 paas-ce/lesscode/lib/client/typings/shims-vue.d.ts create mode 100644 paas-ce/lesscode/lib/server/conf/data-source.js.example create mode 100644 paas-ce/lesscode/lib/server/conf/encrypt-secret-key.js.example create mode 100644 paas-ce/lesscode/lib/server/controller/data-source.js create mode 100644 paas-ce/lesscode/lib/server/controller/project-version.js create mode 100644 paas-ce/lesscode/lib/server/controller/serverless-web.js create mode 100644 paas-ce/lesscode/lib/server/decorator/authorization/index.js create mode 100644 paas-ce/lesscode/lib/server/decorator/controller/index.js create mode 100644 paas-ce/lesscode/lib/server/decorator/controller/params.js create mode 100644 paas-ce/lesscode/lib/server/decorator/controller/router.js create mode 100644 paas-ce/lesscode/lib/server/decorator/index.js create mode 100644 paas-ce/lesscode/lib/server/decorator/send/index.js create mode 100644 paas-ce/lesscode/lib/server/model/common.js create mode 100644 paas-ce/lesscode/lib/server/model/data-table-modify-record.js create mode 100644 paas-ce/lesscode/lib/server/model/entities/data-table-modify-record.js create mode 100644 paas-ce/lesscode/lib/server/model/entities/data-table.js create mode 100644 paas-ce/lesscode/lib/server/model/entities/preview-db.js create mode 100644 paas-ce/lesscode/lib/server/model/entities/project-version.js create mode 100644 paas-ce/lesscode/lib/server/model/migrations/20211014084206-update-sql.js create mode 100644 paas-ce/lesscode/lib/server/model/migrations/20211103024457-update-sql.js create mode 100644 paas-ce/lesscode/lib/server/model/migrations/20211109090310-update-sql.js create mode 100644 paas-ce/lesscode/lib/server/model/migrations/20211124155657-update-sql.js create mode 100644 paas-ce/lesscode/lib/server/model/migrations/sqls/20211014084206-update-sql-down.sql create mode 100644 paas-ce/lesscode/lib/server/model/migrations/sqls/20211014084206-update-sql-up.sql create mode 100644 paas-ce/lesscode/lib/server/model/migrations/sqls/20211103024457-update-sql-down.sql create mode 100644 paas-ce/lesscode/lib/server/model/migrations/sqls/20211103024457-update-sql-up.sql create mode 100644 paas-ce/lesscode/lib/server/model/migrations/sqls/20211109090310-update-sql-down.sql create mode 100644 paas-ce/lesscode/lib/server/model/migrations/sqls/20211109090310-update-sql-up.sql create mode 100644 paas-ce/lesscode/lib/server/model/migrations/sqls/20211124155657-update-sql-down.sql create mode 100644 paas-ce/lesscode/lib/server/model/migrations/sqls/20211124155657-update-sql-up.sql create mode 100644 paas-ce/lesscode/lib/server/model/project-version.js create mode 100644 paas-ce/lesscode/lib/server/model/sql/20211014/update.sql create mode 100644 paas-ce/lesscode/lib/server/model/sql/20211031/update.sql create mode 100644 paas-ce/lesscode/lib/server/model/sql/20211109/update.sql create mode 100644 paas-ce/lesscode/lib/server/model/sql/20211124/update.sql create mode 100644 paas-ce/lesscode/lib/server/project-template/data-base-template.js create mode 100644 paas-ce/lesscode/lib/server/project-template/data-migration-template.js create mode 100644 paas-ce/lesscode/lib/server/project-template/entity-template.js create mode 100644 paas-ce/lesscode/lib/server/project-template/project-init-code/jsconfig.json create mode 100644 paas-ce/lesscode/lib/server/project-template/project-init-code/lib/server/controller/data-source.js create mode 100644 paas-ce/lesscode/lib/server/project-template/project-init-code/lib/server/custom-global.js create mode 100644 paas-ce/lesscode/lib/server/project-template/project-init-code/lib/server/decorator/controller/index.js create mode 100644 paas-ce/lesscode/lib/server/project-template/project-init-code/lib/server/decorator/controller/params.js create mode 100644 paas-ce/lesscode/lib/server/project-template/project-init-code/lib/server/decorator/controller/router.js create mode 100644 paas-ce/lesscode/lib/server/project-template/project-init-code/lib/server/decorator/index.js create mode 100644 paas-ce/lesscode/lib/server/project-template/project-init-code/lib/server/decorator/send/index.js create mode 100644 paas-ce/lesscode/lib/server/project-template/project-init-code/lib/server/middleware/request-context.js create mode 100644 paas-ce/lesscode/lib/server/project-template/project-init-code/lib/server/model/entities/base.js delete mode 100644 paas-ce/lesscode/lib/server/project-template/project-init-code/lib/server/router/mock-data.js delete mode 100644 paas-ce/lesscode/lib/server/project-template/project-init-code/lib/server/router/user.js create mode 100644 paas-ce/lesscode/lib/server/project-template/project-init-code/lib/server/service/data-service.js create mode 100644 paas-ce/lesscode/lib/server/router/project-version.js create mode 100644 paas-ce/lesscode/lib/server/service/data-service.js create mode 100644 paas-ce/lesscode/lib/server/service/db-engine-service.js create mode 100644 paas-ce/lesscode/lib/server/service/function.js create mode 100644 paas-ce/lesscode/lib/server/service/layout.js create mode 100644 paas-ce/lesscode/lib/server/service/online-db-service.js create mode 100644 paas-ce/lesscode/lib/server/service/page.js create mode 100644 paas-ce/lesscode/lib/server/service/preview-db-service.js create mode 100644 paas-ce/lesscode/lib/server/service/project-version.js create mode 100644 paas-ce/lesscode/lib/server/service/route.js create mode 100644 paas-ce/lesscode/lib/server/service/variable.js create mode 100644 paas-ce/lesscode/lib/server/utils/http/index.js create mode 100644 paas-ce/lesscode/lib/server/utils/lc-compose.js create mode 100644 paas-ce/lesscode/lib/shared/data-source/constant.js create mode 100644 paas-ce/lesscode/lib/shared/data-source/data-parse/common.js create mode 100644 paas-ce/lesscode/lib/shared/data-source/data-parse/data-parser/csv-parser.js create mode 100644 paas-ce/lesscode/lib/shared/data-source/data-parse/data-parser/json-parser.js create mode 100644 paas-ce/lesscode/lib/shared/data-source/data-parse/data-parser/sql-parser.js create mode 100644 paas-ce/lesscode/lib/shared/data-source/data-parse/index.js create mode 100644 paas-ce/lesscode/lib/shared/data-source/data-parse/struct-parser/csv-parser.js create mode 100644 paas-ce/lesscode/lib/shared/data-source/data-parse/struct-parser/json-parser.js create mode 100644 paas-ce/lesscode/lib/shared/data-source/data-parse/struct-parser/sql-parser.js create mode 100644 paas-ce/lesscode/lib/shared/data-source/helper.js create mode 100644 paas-ce/lesscode/lib/shared/data-source/index.js create mode 100644 paas-ce/lesscode/lib/shared/function/constant.js create mode 100644 paas-ce/lesscode/lib/shared/function/index.js create mode 100644 paas-ce/lesscode/lib/shared/index.js create mode 100644 paas-ce/lesscode/lib/shared/util.js create mode 100644 paas-ce/lesscode/lib/shared/variable/constant.js create mode 100644 paas-ce/lesscode/tsconfig.json diff --git a/paas-ce/lesscode/.babelrc b/paas-ce/lesscode/.babelrc index 0beca1ece..a6abc5baf 100644 --- a/paas-ce/lesscode/.babelrc +++ b/paas-ce/lesscode/.babelrc @@ -10,6 +10,12 @@ }, "debug": false } + ], + [ + "@vue/babel-preset-jsx", + { + "compositionAPI": true + } ] ], "plugins": [ @@ -19,13 +25,14 @@ "@babel/plugin-syntax-dynamic-import", ["@babel/plugin-proposal-decorators", { "legacy": true }], ["@babel/plugin-proposal-class-properties", { "loose" : true }], + "babel-plugin-parameter-decorator", "@babel/plugin-proposal-function-sent", "@babel/plugin-proposal-export-namespace-from", "@babel/plugin-proposal-numeric-separator", "@babel/plugin-proposal-throw-expressions", "@babel/plugin-transform-async-to-generator", ["babel-plugin-import-bk-magic-vue", { "baseLibName": "bk-magic-vue" }], - "transform-vue-jsx" + "@babel/plugin-proposal-optional-chaining" ], "env": { "test": { diff --git a/paas-ce/lesscode/.eslintignore b/paas-ce/lesscode/.eslintignore new file mode 100644 index 000000000..5993a68ec --- /dev/null +++ b/paas-ce/lesscode/.eslintignore @@ -0,0 +1 @@ +lib/server/model/migrations/ diff --git a/paas-ce/lesscode/.eslintrc.js b/paas-ce/lesscode/.eslintrc.js index dcc7d46e4..d43881b56 100644 --- a/paas-ce/lesscode/.eslintrc.js +++ b/paas-ce/lesscode/.eslintrc.js @@ -1,7 +1,7 @@ module.exports = { root: true, parserOptions: { - parser: 'babel-eslint', + parser: '@typescript-eslint/parser', sourceType: 'module', ecmaFeatures: { legacyDecorators: true @@ -12,11 +12,13 @@ module.exports = { }, extends: [ 'plugin:vue/recommended', - 'standard' + 'standard', + '@vue/typescript' ], // required to lint *.vue files plugins: [ - 'vue' + 'vue', + '@typescript-eslint' ], // 代码中的全局变量,key 为全局变量名称,value 为 true 允许被重写,为 false 不允许被重写 globals: { @@ -31,6 +33,188 @@ module.exports = { }, // add your custom rules hered rules: { + '@typescript-eslint/adjacent-overload-signatures': 'error', + /** + * 类的只读属性若是一个字面量,则必须使用只读属性而不是 getter + */ + '@typescript-eslint/class-literal-property-style': [ + 'error', + 'fields' + ], + /** + * 类型断言必须使用 as Type,禁止使用 ,禁止对对象字面量进行类型断言(断言成 any 是允许的) + * @reason 容易被理解为 jsx + */ + '@typescript-eslint/consistent-type-assertions': [ + 'error', + { + assertionStyle: 'as', + objectLiteralTypeAssertions: 'never' + } + ], + /** + * 优先使用 interface 而不是 type + */ + '@typescript-eslint/consistent-type-definitions': 'off', + /** + * 必须设置类的成员的可访问性 + * @reason 将不需要公开的成员设为私有的,可以增强代码的可理解性,对文档输出也很友好 + */ + '@typescript-eslint/explicit-member-accessibility': 'off', + /** + * 要求或禁止在函数标识符和其调用之间有空格 + */ + '@typescript-eslint/func-call-spacing': [ + 'error', + 'never' + ], + /** + * 指定类成员的排序规则 + * @reason 优先级: + * 1. static > instance + * 2. field > constructor > method + * 3. public > protected > private + */ + '@typescript-eslint/member-ordering': [ + 'error', + { + default: [ + 'public-static-field', + 'protected-static-field', + 'private-static-field', + 'static-field', + 'public-static-method', + 'protected-static-method', + 'private-static-method', + 'static-method', + 'public-instance-field', + 'protected-instance-field', + 'private-instance-field', + 'public-field', + 'protected-field', + 'private-field', + 'instance-field', + 'field', + 'constructor', + 'public-instance-method', + 'protected-instance-method', + 'private-instance-method', + 'public-method', + 'protected-method', + 'private-method', + 'instance-method', + 'method' + ] + } + ], + /** + * 接口中的方法必须用属性的方式定义 + */ + '@typescript-eslint/method-signature-style': 'off', + /** 同 JS 规则的 TS 版本 */ + '@typescript-eslint/no-array-constructor': 'error', + /** 同 JS 规则的 TS 版本 */ + '@typescript-eslint/no-dupe-class-members': 'error', + /** + * 禁止定义空的接口 + */ + '@typescript-eslint/no-empty-interface': 'error', + /** + * 禁止给一个初始化时直接赋值为 number, string 的变量显式的声明类型 + * @reason 可以简化代码 + */ + '@typescript-eslint/no-inferrable-types': 'warn', + /** + * 禁止使用 namespace 来定义命名空间 + * @reason 使用 es6 引入模块,才是更标准的方式。 + * 但是允许使用 declare namespace ... {} 来定义外部命名空间 + */ + '@typescript-eslint/no-namespace': [ + 'error', + { + allowDeclarations: true, + allowDefinitionFiles: true + } + ], + /** + * 禁止在 optional chaining 之后使用 non-null 断言(感叹号) + * @reason optional chaining 后面的属性一定是非空的 + */ + '@typescript-eslint/no-non-null-asserted-optional-chain': 'error', + /** + * 禁止给类的构造函数的参数添加修饰符 + */ + '@typescript-eslint/no-parameter-properties': 'off', + /** + * 禁止无用的表达式 + */ + '@typescript-eslint/no-unused-expressions': [ + 'error', + { + allowShortCircuit: true, + allowTernary: true, + allowTaggedTemplates: true + } + ], + /** + * 禁止出现没必要的 constructor + */ + '@typescript-eslint/no-useless-constructor': 'warn', + /** + * 使用函数类型别名替代包含函数调用声明的接口 + */ + '@typescript-eslint/prefer-function-type': 'warn', + /** + * 禁止使用 module 来定义命名空间 + * @reason module 已成为 js 的关键字 + */ + '@typescript-eslint/prefer-namespace-keyword': 'error', + /** + * 使用 optional chaining 替代 && + */ + /** 同 JS 规则的 TS 版本 */ + '@typescript-eslint/quotes': [ + 'warn', + 'single', + { + allowTemplateLiterals: false + } + ], + /** + * 禁止使用三斜杠导入文件 + * @reason 三斜杠是已废弃的语法,但在类型声明文件中还是可以使用的 + */ + '@typescript-eslint/triple-slash-reference': [ + 'error', + { + path: 'never', + types: 'always', + lib: 'always' + } + ], + /** + * 在类型注释周围需要一致的间距 + */ + '@typescript-eslint/type-annotation-spacing': 'error', + /** + * interface 和 type 定义时必须声明成员的类型 + */ + '@typescript-eslint/typedef': [ + 'error', + { + arrayDestructuring: false, + arrowParameter: false, + memberVariableDeclaration: false, + objectDestructuring: false, + parameter: false, + propertyDeclaration: true, + variableDeclaration: false + } + ], + /** + * 函数重载时,若能通过联合类型将两个函数的类型声明合为一个,则使用联合类型而不是两个函数声明 + */ + '@typescript-eslint/unified-signatures': 'error', // https://eslint.org/docs/rules/brace-style 'brace-style': ['error', '1tbs', { 'allowSingleLine': false }], diff --git a/paas-ce/lesscode/.gitignore b/paas-ce/lesscode/.gitignore index fefb9ff79..269b1a369 100644 --- a/paas-ce/lesscode/.gitignore +++ b/paas-ce/lesscode/.gitignore @@ -32,11 +32,14 @@ upload !lib/client/src/element-materials/**/upload temp npmTemp +downloadTemp lib/server/conf/data-base.js lib/server/conf/http.js lib/server/conf/db-migrate.json lib/server/conf/npm.js lib/server/conf/bk-repo.js +lib/server/conf/data-source.js +lib/server/conf/encrypt-secret-key.js !lib/server/project-template/project-init-code/bin lib/server/project-template/project-target* diff --git a/paas-ce/lesscode/lib/client/build/webpack.base.conf.js b/paas-ce/lesscode/lib/client/build/webpack.base.conf.js index bf982dd0a..2cfd67944 100644 --- a/paas-ce/lesscode/lib/client/build/webpack.base.conf.js +++ b/paas-ce/lesscode/lib/client/build/webpack.base.conf.js @@ -13,8 +13,9 @@ const { resolve, posix } = require('path') const webpack = require('webpack') const CopyWebpackPlugin = require('copy-webpack-plugin') const { VueLoaderPlugin } = require('vue-loader') -const friendlyFormatter = require('eslint-friendly-formatter') +// const friendlyFormatter = require('eslint-friendly-formatter') // const MonacoWebpackPlugin = require('monaco-editor-webpack-plugin') +const ESLintPlugin = require('eslint-webpack-plugin') const clientConf = require('./conf') const mdLoaderOption = require('./md-loader-option') const { pathToNodeModules } = require('./util') @@ -23,6 +24,58 @@ const IS_DEV = process.env.NODE_ENV === 'development' const config = IS_DEV ? clientConf.dev : clientConf.build +const babelLoader = { + loader: resolve(__dirname, pathToNodeModules, 'babel-loader'), + options: { + include: [ + resolve(__dirname, '..', 'src'), + resolve(__dirname, pathToNodeModules, 'bk-magic-vue'), + resolve(__dirname, pathToNodeModules, 'monaco-editor'), + resolve(__dirname, pathToNodeModules, 'vue-echarts') + // resolve(__dirname, pathToNodeModules, 'resize-detector') + ], + cacheDirectory: resolve(__dirname, '..', '.webpack_cache'), + presets: [ + [ + resolve(__dirname, pathToNodeModules, '@babel/preset-env'), + { + modules: 'commonjs', + targets: { + browsers: ['> 1%', 'last 2 versions', 'not ie <= 8'], + node: 'current' + }, + debug: false + } + ] + ], + // plugins: [require('@babel/plugin-transform-object-rest-spread')], + plugins: [ + resolve(__dirname, pathToNodeModules, '@babel/plugin-syntax-dynamic-import'), + resolve(__dirname, pathToNodeModules, '@babel/plugin-transform-runtime'), + resolve(__dirname, pathToNodeModules, '@babel/plugin-transform-object-assign'), + resolve(__dirname, pathToNodeModules, '@babel/plugin-transform-async-to-generator'), + resolve(__dirname, pathToNodeModules, '@babel/plugin-transform-modules-commonjs'), + [ + resolve(__dirname, pathToNodeModules, '@babel/plugin-proposal-decorators'), + { legacy: true } + ], + resolve(__dirname, pathToNodeModules, '@babel/plugin-proposal-function-sent'), + resolve(__dirname, pathToNodeModules, '@babel/plugin-proposal-export-namespace-from'), + resolve(__dirname, pathToNodeModules, '@babel/plugin-proposal-numeric-separator'), + resolve(__dirname, pathToNodeModules, '@babel/plugin-proposal-throw-expressions'), + resolve(__dirname, pathToNodeModules, 'babel-plugin-add-module-exports'), + [ + resolve(__dirname, pathToNodeModules, 'babel-plugin-import-bk-magic-vue'), + { baseLibName: 'bk-magic-vue' } + ] + ], + // 确保 JS 的转译应用到 node_modules 的 Vue 单文件组件 + exclude: file => ( + /node_modules/.test(file) && !/\.vue\.js/.test(file) && !(/monaco-editor/.test(file)) + ) + } +} + module.exports = { watchOptions: { ignored: /node_modules/ @@ -38,28 +91,29 @@ module.exports = { // 指定以下目录寻找第三方模块,避免 webpack 往父级目录递归搜索, // 默认值为 ['node_modules'],会依次查找./node_modules、../node_modules、../../node_modules modules: [resolve(__dirname, '..', 'src'), resolve(__dirname, pathToNodeModules)], - extensions: ['.js', '.vue', '.json'], + extensions: ['.js', '.ts', '.tsx', '.vue', '.json'], alias: { vue$: resolve(__dirname, pathToNodeModules, 'vue/dist/vue.esm.js'), - '@': resolve(__dirname, '..', 'src') + '@': resolve(__dirname, '..', 'src'), + 'shared': resolve(__dirname, '..', '..', 'shared') } }, module: { rules: [ - { - test: /\.(js|vue)$/, - // loader: 'eslint-loader', - loader: resolve(__dirname, pathToNodeModules, 'eslint-loader'), - enforce: 'pre', - include: [ - resolve(__dirname, '..', 'src') - ], - exclude: /node_modules/, - options: { - formatter: friendlyFormatter - } - }, + // { + // test: /\.(js|vue)$/, + // // loader: 'eslint-loader', + // loader: resolve(__dirname, pathToNodeModules, 'eslint-loader'), + // enforce: 'pre', + // include: [ + // resolve(__dirname, '..', 'src') + // ], + // exclude: /node_modules/, + // options: { + // formatter: friendlyFormatter + // } + // }, { test: /\.vue$/, use: { @@ -90,58 +144,23 @@ module.exports = { ] }, { - test: /\.js$/, - use: { - loader: resolve(__dirname, pathToNodeModules, 'babel-loader'), - options: { - include: [ - resolve(__dirname, '..', 'src'), - resolve(__dirname, pathToNodeModules, 'bk-magic-vue'), - resolve(__dirname, pathToNodeModules, 'monaco-editor'), - resolve(__dirname, pathToNodeModules, 'vue-echarts') - // resolve(__dirname, pathToNodeModules, 'resize-detector') - ], - cacheDirectory: resolve(__dirname, '..', '.webpack_cache'), - presets: [ - [ - resolve(__dirname, pathToNodeModules, '@babel/preset-env'), - { - modules: 'commonjs', - targets: { - browsers: ['> 1%', 'last 2 versions', 'not ie <= 8'], - node: 'current' - }, - debug: false - } - ] - ], - // plugins: [require('@babel/plugin-transform-object-rest-spread')], - plugins: [ - resolve(__dirname, pathToNodeModules, '@babel/plugin-syntax-dynamic-import'), - resolve(__dirname, pathToNodeModules, '@babel/plugin-transform-runtime'), - resolve(__dirname, pathToNodeModules, '@babel/plugin-transform-object-assign'), - resolve(__dirname, pathToNodeModules, '@babel/plugin-transform-async-to-generator'), - resolve(__dirname, pathToNodeModules, '@babel/plugin-transform-modules-commonjs'), - [ - resolve(__dirname, pathToNodeModules, '@babel/plugin-proposal-decorators'), - { legacy: true } - ], - resolve(__dirname, pathToNodeModules, '@babel/plugin-proposal-function-sent'), - resolve(__dirname, pathToNodeModules, '@babel/plugin-proposal-export-namespace-from'), - resolve(__dirname, pathToNodeModules, '@babel/plugin-proposal-numeric-separator'), - resolve(__dirname, pathToNodeModules, '@babel/plugin-proposal-throw-expressions'), - resolve(__dirname, pathToNodeModules, 'babel-plugin-add-module-exports'), - [ - resolve(__dirname, pathToNodeModules, 'babel-plugin-import-bk-magic-vue'), - { baseLibName: 'bk-magic-vue' } - ] - ], - // 确保 JS 的转译应用到 node_modules 的 Vue 单文件组件 - exclude: file => ( - /node_modules/.test(file) && !/\.vue\.js/.test(file) && !(/monaco-editor/.test(file)) - ) + test: /\.tsx?$/, + use: [ + babelLoader, + { + loader: resolve(__dirname, pathToNodeModules, 'ts-loader'), + options: { + transpileOnly: true, + appendTsSuffixTo: [/\.vue$/], + happyPackMode: false + } } - } + ], + exclude: /node_modules/ + }, + { + test: /\.js$/, + use: babelLoader }, { test: /\.(png|jpe?g|gif|svg)(\?.*)?$/, @@ -185,6 +204,11 @@ module.exports = { to: resolve(__dirname, '..', 'dist/static/images'), toType: 'dir' } - ]) + ]), + new ESLintPlugin({ + context: resolve(__dirname, '..', 'src'), + extensions: ['js', 'ts', 'vue', 'jsx', 'tsx'], + lintDirtyModulesOnly: true + }) ] } diff --git a/paas-ce/lesscode/lib/client/src/api/pureAxios.js b/paas-ce/lesscode/lib/client/src/api/pureAxios.js index 2282d24a0..271ec706c 100644 --- a/paas-ce/lesscode/lib/client/src/api/pureAxios.js +++ b/paas-ce/lesscode/lib/client/src/api/pureAxios.js @@ -151,9 +151,20 @@ function handleReject (error, config) { } http.queue.delete(config.requestId) - let errMessage = error.message || error - if (typeof errMessage === 'string' && errMessage.match(/Network Error/)) errMessage = 'Network Error,网络不可用,有可能是跨域原因引起' - messageError(errMessage) + + let message = error.message || '接口异常,无法访问' + const { response } = error + if (response) { + // 默认提示 http 状态码错误标记 + message = response.statusText + // 兼容后端响应时通过body返回错误信息 + if (response.data && response.data.message) { + message = response.data.message + } + } + + if (typeof message === 'string' && message.match(/Network Error/)) message = 'Network Error,网络不可用,有可能是跨域原因引起' + messageError(message) console.error(error) return Promise.reject(error) } diff --git a/paas-ce/lesscode/lib/client/src/common/dom-to-image.js b/paas-ce/lesscode/lib/client/src/common/dom-to-image.js index c0747fff2..f65c19f88 100644 --- a/paas-ce/lesscode/lib/client/src/common/dom-to-image.js +++ b/paas-ce/lesscode/lib/client/src/common/dom-to-image.js @@ -557,7 +557,7 @@ function newUtil () { .replace(/:(\w+)/g, (match, p1) => p1) // .replace(/\:checked/g, 'checked') .replace(/\n/g, '%0A') - .replace(/"/g, "'") + .replace(/"/g, '\'') .replace(/%/g, '%25') .replace(/#/g, '%23') .replace(/{/g, '%7B') diff --git a/paas-ce/lesscode/lib/client/src/common/process-targetdata.js b/paas-ce/lesscode/lib/client/src/common/process-targetdata.js index bf5103fcd..9d82df94c 100644 --- a/paas-ce/lesscode/lib/client/src/common/process-targetdata.js +++ b/paas-ce/lesscode/lib/client/src/common/process-targetdata.js @@ -117,6 +117,7 @@ function getFuncList (targetData = [], funcGroups = []) { const funcIds = Object.keys(usedFuncMap) return funcIds.map(id => ({ + ...usedFuncMap[id], id, funcCode: usedFuncMap[id].funcCode })) diff --git a/paas-ce/lesscode/lib/client/src/common/tnpm-version-valid.js b/paas-ce/lesscode/lib/client/src/common/tnpm-version-valid.js index f0b098456..2c2a4e3f1 100644 --- a/paas-ce/lesscode/lib/client/src/common/tnpm-version-valid.js +++ b/paas-ce/lesscode/lib/client/src/common/tnpm-version-valid.js @@ -108,14 +108,14 @@ createToken('XRANGEPLAIN', `[v=\\s]*(${src[t.XRANGEIDENTIFIER]})` + `(?:\\.(${src[t.XRANGEIDENTIFIER]})` + `(?:${src[t.PRERELEASE]})?${ src[t.BUILD]}?` - + `)?)?`) + + ')?)?') createToken('XRANGEPLAINLOOSE', `[v=\\s]*(${src[t.XRANGEIDENTIFIERLOOSE]})` + `(?:\\.(${src[t.XRANGEIDENTIFIERLOOSE]})` + `(?:\\.(${src[t.XRANGEIDENTIFIERLOOSE]})` + `(?:${src[t.PRERELEASELOOSE]})?${ src[t.BUILD]}?` - + `)?)?`) + + ')?)?') createToken('XRANGE', `^${src[t.GTLT]}\\s*${src[t.XRANGEPLAIN]}$`) createToken('XRANGELOOSE', `^${src[t.GTLT]}\\s*${src[t.XRANGEPLAINLOOSE]}$`) @@ -126,7 +126,7 @@ createToken('COERCE', `${'(^|[^\\d])' + '(\\d{1,'}${MAX_SAFE_COMPONENT_LENGTH}})` + `(?:\\.(\\d{1,${MAX_SAFE_COMPONENT_LENGTH}}))?` + `(?:\\.(\\d{1,${MAX_SAFE_COMPONENT_LENGTH}}))?` - + `(?:$|[^\\d])`) + + '(?:$|[^\\d])') createToken('COERCERTL', src[t.COERCE], true) // Tilde ranges. @@ -164,14 +164,14 @@ exports.comparatorTrimReplace = '$1$2$3' // checked against either the strict or loose comparator form // later. createToken('HYPHENRANGE', `^\\s*(${src[t.XRANGEPLAIN]})` - + `\\s+-\\s+` + + '\\s+-\\s+' + `(${src[t.XRANGEPLAIN]})` - + `\\s*$`) + + '\\s*$') createToken('HYPHENRANGELOOSE', `^\\s*(${src[t.XRANGEPLAINLOOSE]})` - + `\\s+-\\s+` + + '\\s+-\\s+' + `(${src[t.XRANGEPLAINLOOSE]})` - + `\\s*$`) + + '\\s*$') // Star ranges basically just allow anything at all. createToken('STAR', '(<|>)?=?\\s*\\*') diff --git a/paas-ce/lesscode/lib/client/src/components/choose-data-table.vue b/paas-ce/lesscode/lib/client/src/components/choose-data-table.vue new file mode 100644 index 000000000..5acf0c704 --- /dev/null +++ b/paas-ce/lesscode/lib/client/src/components/choose-data-table.vue @@ -0,0 +1,65 @@ + + + diff --git a/paas-ce/lesscode/lib/client/src/components/copy-icon.js b/paas-ce/lesscode/lib/client/src/components/copy-icon.js new file mode 100644 index 000000000..cef082e27 --- /dev/null +++ b/paas-ce/lesscode/lib/client/src/components/copy-icon.js @@ -0,0 +1,33 @@ +import { bkMessage } from 'bk-magic-vue' + +function copyTxt (value) { + const input = document.createElement('input') + document.body.appendChild(input) + input.setAttribute('value', value) + input.select() + if (document.execCommand('copy')) { + document.execCommand('copy') + bkMessage({ theme: 'success', message: '复制成功' }) + } + document.body.removeChild(input) +} + +export default { + name: 'copy-icon', + + functional: true, + + props: ['value'], + + render (h, ctx) { + const props = ctx.props || {} + const value = props.value || '' + const style = { + cursor: 'pointer', + fontSize: '14px', + color: '#3a84ff', + marginLeft: '5px' + } + return copyTxt(value) }> + } +} diff --git a/paas-ce/lesscode/lib/client/src/components/field-table/field-table.css b/paas-ce/lesscode/lib/client/src/components/field-table/field-table.css new file mode 100644 index 000000000..d9d53598e --- /dev/null +++ b/paas-ce/lesscode/lib/client/src/components/field-table/field-table.css @@ -0,0 +1,87 @@ +.field-table { + width: 100%; + .asterisk { + margin-left: 5px; + color: #ea3636; + font-size: 14px; + } + .row-icons { + font-size: 16px; + position: absolute; + right: 22px; + top: 13px; + color: #EA3636; + } + .field-error { + border: 1px solid red !important; + } + tr.bk-table-row.hover-row { + .disable-row { + .bk-select.is-disabled, .bk-form-input[disabled] { + background-color: #fff !important; + } + } + > td { + background-color: #fff; + .field-table-input { + .bk-form-input { + border: none; + background: #f5f7fa; + } + } + .field-table-select { + background: #f5f7fa; + .icon-angle-down { + display: block; + } + } + } + .bk-select.is-disabled, .bk-form-input[disabled] { + background-color: #fafbfd !important; + } + } + .field-table-icon { + color: #c4c6cc; + cursor: pointer; + margin-left: 5px; + font-size: 16px; + } + .field-table-input { + position: relative; + .bk-form-input { + border: none; + &:focus { + background: #f5f7fa; + } + } + } + .config-input-error { + .bk-form-input { + border: 1px solid #ff5656; + } + } + .field-table-select { + border: none; + .icon-angle-down { + display: none; + } + } + .field-icon { + color: #c4c6cc; + font-size: 16px; + cursor: pointer; + &:first-child { + margin-right: 10px; + } + &:hover { + color: #979BA5; + } + } + .icon-disabled { + color: #dcdee5; + cursor: not-allowed; + } + .bk-select.is-disabled, .bk-form-input[disabled] { + background-color: #fff !important; + } + } \ No newline at end of file diff --git a/paas-ce/lesscode/lib/client/src/components/field-table/field-table.tsx b/paas-ce/lesscode/lib/client/src/components/field-table/field-table.tsx new file mode 100644 index 000000000..5b7be6009 --- /dev/null +++ b/paas-ce/lesscode/lib/client/src/components/field-table/field-table.tsx @@ -0,0 +1,385 @@ +/** + * Tencent is pleased to support the open source community by making 蓝鲸智云PaaS平台社区版 (BlueKing PaaS Community Edition) available. + * Copyright (C) 2017-2018 THL A29 Limited, a Tencent company. All rights reserved. + * Licensed under the MIT License (the "License"); you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * http://opensource.org/licenses/MIT + * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on + * 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 { defineComponent, toRef, reactive, watch } from '@vue/composition-api' +import Vue, { VNode } from 'vue' + +import './field-table.css' + +interface ISelectOption { + id: string + name: string +} +interface IPropsObject { + [key: string]: any +} + +interface IRuleItem { + validator: Function + message: string + } +interface IColumnItem { + name: string + type: string + prop: string + optionsList?: Function | ISelectOption[] + width?: string + isRequire?: boolean + inputType?: string + placeholder?: string + renderFn?: Function + /** 是否只读 */ + isReadonly?: Function | boolean + componentProps?: IPropsObject | Function + /** 校验规则 */ + rules?: IRuleItem[] +} +interface IError { + [key: string]: string +} +export default defineComponent({ + name: 'FieldTable', + components: {}, + props: { + data: Array, + column: Array, + isShowCheck: Boolean + }, + setup (props, { emit }) { + const tableList = toRef(props, 'data') + /** + * 校验报错信息,只显示第一个报错信息 + * key: column.prop_rowIndex + * value: error tips text + */ + const errorMap = reactive({}) + let renderColumns = reactive([]) + /** + * 生成随机ID + * @param {String} prefix 统一前缀 + * @param {Int} idLength 随机ID长度 + */ + const generateId = (prefix = '', length = 6) => { + let d = new Date().getTime() + const uuid = new Array(length).fill('x').join('').replace(/[xy]/g, c => { + const r = (d + Math.random() * 16) % 16 | 0 + d = Math.floor(d / 16) + return (c === 'x' ? r : (r & 0x7) | 0x8).toString(16) + }) + return `${prefix}${uuid}` + } + watch( + toRef(props, 'column'), + (val) => { + renderColumns = val.map((column: IColumnItem) => Object.assign({ + key: generateId(`field_table_column_${column.prop}`) + }, column)) + }, + { + immediate: true, + deep: true + } + ) + + /** 指定列/行disabled */ + const handleDisabled = (item: any, props: any) => { + const { row } = props + if (row.isReadonly) { + return row.isReadonly + } + if (typeof item.isReadonly === 'function') { + return item.isReadonly.apply(this, [item, props]) + } + return item.isReadonly + } + + const handleComponentProps = (item: any, props: any) => { + if (typeof item.componentProps === 'function') { + return item.componentProps.apply(this, [item, props]) + } + return item.componentProps + } + + const renderHeader = (h, { column, $index }, item) => { + return ( + + {column.label} + {item.isRequire ? : ''} + + ) + } + /** checkbox */ + const renderCheckbox = (item: IColumnItem, props: any) => { + const change = (value, row, item, index) => { + emit('change', value, row, item, index) + } + const { row, $index } = props + return + change(value, row, item, $index) + } + /> + } + /** input */ + const renderInput = (item: IColumnItem, props: any) => { + const change = (value, row, item, index) => { + emit('change', value, row, item, index) + } + const { row, $index } = props + return + change(value, row, item, $index) + } + onBlur={handleValidator.bind(this, props, item)} + {...{ props: (handleComponentProps(item, props)) }} /> + } + const handleChangeValue = (row: any, column: any, value: any) => { + if (typeof column.changeFn === 'function') { + column.changeFn(value, column, row) + return + } + row[column.prop] = value + } + const handleSelected = (props: any, column: any, value: any) => { + const { row, $index } = props + emit('change', value, row, column, $index) + handleChangeValue(props.row, column, value) + Object.keys(errorMap).map(item => item.endsWith($index) && Vue.delete(errorMap, item)) + handleValidator(props, column) + } + /** select */ + const renderSelect = (item: IColumnItem, props: any) => { + const { row } = props + const optionList = typeof item.optionsList === 'function' + ? item.optionsList.apply(this, [item, props]) : item.optionsList + const options = (optionList || []).map((option: any) => ( + + )) + return + {item.optionsList ? options : ''} + + } + /** 操作列 */ + const renderOperate = () => { + const handleAdd = (props) => { + const { row, $index } = props + emit('add', row, $index) + } + const handleDelete = (props) => { + const { row, $index } = props + if (row.isEdit) { + return + } + emit('delete', row, $index) + } + const scopedSlots = { + default: (props) => { + const { row } = props + const defaultSlot = ( + + { + handleAdd(props) + }} + /> + { + handleDelete(props) + }} + /> + + ) + return defaultSlot + } + } + return ( + + ) + } + + const isEmpty = (value: any) => { + return value === undefined || value === null || value === '' || (Array.isArray(value) && value.length === 0) + } + const updateColumnKey = (column: IColumnItem) => { + Vue.set(column, 'key', generateId(`field_table_column_${column.prop}`)) + } + /** 校验 */ + const handleValidator = async (props: any, column: any) => { + const { row, $index } = props + const value = row[column.prop] + const errorKey = `${column.prop}_${$index}` + // 必填校验 + if (column.isRequire && isEmpty(value)) { + Vue.set(errorMap, errorKey, `${column.name}是必填项`) + updateColumnKey(column) + return false + } + // 没有自定义校验规则 + if (!column.rules || !column.rules.length) { + if (errorMap[errorKey]) { + Vue.delete(errorMap, errorKey) + updateColumnKey(column) + } + return true + } + // 执行自定义校验 + let count = 0 + for (const rule of column.rules) { + const p = () => new Promise(async (resolve, reject) => { + try { + const result = await rule.validator(value, props.row) + if (result) { + resolve(rule) + } else { + reject(rule) + } + } catch (e) { + reject(rule) + } + }) + try { + await p() + ++count + } catch (e) { + Vue.set(errorMap, errorKey, rule.message) + updateColumnKey(column) + return false + } + if (count === column.rules.length && errorMap[errorKey]) { + Vue.delete(errorMap, errorKey) + updateColumnKey(column) + return true + } + } + } + + // 组件外可以直接调用该方法判断是否校验通过 + const verification = () => { + return new Promise((resolve, reject) => { + // 待校验完成,防止input失焦的时候同时调用该方法。 + setTimeout(async () => { + // 有未处理错误直接 reject + if (Object.keys(errorMap).length) { + reject(new Error(Object.values(errorMap)[0])) + } + const length = props.data.length + for (const item of renderColumns) { + // 自定义列且没有自定义rules则不校验 + if (item.type === 'custom' && !item?.rules?.length) continue + for (let i = 0; i < length; i++) { + const prop = { row: props.data[i], $index: i } + if (handleDisabled(item, prop)) continue + await handleValidator(prop, item) + } + } + // 统一校验完再次验证是否有错误没处理 + if (Object.keys(errorMap).length) { + reject(new Error(Object.values(errorMap)[0])) + } + resolve(true) + }, 400) + }) + } + + return { + errorMap, + renderCheckbox, + renderInput, + renderSelect, + renderOperate, + renderHeader, + verification, + tableList, + handleDisabled, + renderColumns, + handleComponentProps + } + }, + render (): VNode { + const renderSelection = + const dynamicProps = { + class: 'g-hairless-table', + props: { + data: this.tableList, + outerBorder: false, + headerBorder: false, + headerCellStyle: { + background: '#f0f1f5' + } + } + } + const typeList = { + input: 'renderInput', + select: 'renderSelect', + checkbox: 'renderCheckbox' + } + const renderColumn = (item: IColumnItem) => { + return { + default: (props: any) => { + /** 自定义 */ + if (item.type === 'custom') { + return item.renderFn && item.renderFn.apply(this, [props, this.errorMap]) + } + const { row } = props + const errorInfo = this.errorMap[`${item.prop}_${props.$index}`] + const defaultSlot =
+ { (this as any)[typeList[item.type]](item, props) } + { !!errorInfo + && } +
+ return defaultSlot + } + } + } + return ( +
+ + {this.isShowCheck ? renderSelection : ''} + {this.renderColumns.map((item: IColumnItem) => ( + + this.renderHeader(h, { column, $index }, item) + } + {...{ + scopedSlots: renderColumn(item) + }} + /> + ))} + {this.renderOperate()} + +
+ ) + } +}) diff --git a/paas-ce/lesscode/lib/client/src/components/methods/func-form/form-items/code.vue b/paas-ce/lesscode/lib/client/src/components/methods/func-form/form-items/code.vue index cf1b306e3..c8f57d4fc 100644 --- a/paas-ce/lesscode/lib/client/src/components/methods/func-form/form-items/code.vue +++ b/paas-ce/lesscode/lib/client/src/components/methods/func-form/form-items/code.vue @@ -33,7 +33,7 @@ return functionList.some((func) => (func.funcCode === val && func.id !== this.form.id)) }) }, - message: `函数标识在当前项目下重复,请修改后重试`, + message: '函数标识在当前项目下重复,请修改后重试', trigger: 'blur' }, codeRule: { diff --git a/paas-ce/lesscode/lib/client/src/components/methods/func-form/form-items/detail.vue b/paas-ce/lesscode/lib/client/src/components/methods/func-form/form-items/detail.vue index 4d5d0f80f..a28786913 100644 --- a/paas-ce/lesscode/lib/client/src/components/methods/func-form/form-items/detail.vue +++ b/paas-ce/lesscode/lib/client/src/components/methods/func-form/form-items/detail.vue @@ -87,6 +87,10 @@ + + diff --git a/paas-ce/lesscode/lib/client/src/components/project/edit-route-dialog.vue b/paas-ce/lesscode/lib/client/src/components/project/edit-route-dialog.vue index ee1900b4d..29ae82061 100644 --- a/paas-ce/lesscode/lib/client/src/components/project/edit-route-dialog.vue +++ b/paas-ce/lesscode/lib/client/src/components/project/edit-route-dialog.vue @@ -40,6 +40,7 @@ - diff --git a/paas-ce/lesscode/lib/client/src/components/vue-code/index.vue b/paas-ce/lesscode/lib/client/src/components/vue-code/index.vue index 36883d833..ffe642aa6 100644 --- a/paas-ce/lesscode/lib/client/src/components/vue-code/index.vue +++ b/paas-ce/lesscode/lib/client/src/components/vue-code/index.vue @@ -16,6 +16,7 @@ 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 8b7161648..3469dfc65 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 @@ -134,17 +134,19 @@ getMethodStr (returnMethod) { const funcParams = (returnMethod.funcParams || []).join(', ') + const hasAwait = /await\s/.test(returnMethod.funcBody) if (returnMethod.funcType === 1) { const remoteParams = (returnMethod.remoteParams || []).join(', ') + /* eslint-disable @typescript-eslint/quotes */ 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} }) };` + returnMethod.funcStr = `const ${returnMethod.funcName} = ${hasAwait ? 'async ' : ''}(${funcParams}) => { return this.$store.dispatch('getApiData', ${data}).then((${remoteParams}) => { ${returnMethod.funcBody} }) };` } else { - returnMethod.funcStr = `const ${returnMethod.funcName} = (${funcParams}) => { ${returnMethod.funcBody} };` + returnMethod.funcStr = `const ${returnMethod.funcName} = ${hasAwait ? 'async ' : ''}(${funcParams}) => { ${returnMethod.funcBody} };` } return returnMethod.funcStr }, @@ -265,7 +267,7 @@ let message = this.remoteValidate(res) if (message) { message = '数据源设置成功,以下问题可能会导致组件表现异常,请检查:' + message - this.$bkMessage({ theme: 'warning', message }) + this.messageWarn(message) } else { this.change(this.name, res, this.type, JSON.parse(JSON.stringify(this.remoteData))) if (this.name === 'remoteOptions') { @@ -305,6 +307,10 @@ border-bottom: 1px dashed #979ba5; } + .remote-button { + margin-top: 10px; + } + .remote-example { color: #3a84ff; cursor: pointer; diff --git a/paas-ce/lesscode/lib/client/src/element-materials/modifier/component/props/components/strategy/table-column.vue b/paas-ce/lesscode/lib/client/src/element-materials/modifier/component/props/components/strategy/table-column.vue index d632fea64..1fc570687 100644 --- a/paas-ce/lesscode/lib/client/src/element-materials/modifier/component/props/components/strategy/table-column.vue +++ b/paas-ce/lesscode/lib/client/src/element-materials/modifier/component/props/components/strategy/table-column.vue @@ -122,7 +122,7 @@ const generateCustomColumn = (index) => ({ type: 'customCol', label: `选项${index}`, - templateCol: `编辑`, + templateCol: '编辑', methodCode: [], sortable: false }) diff --git a/paas-ce/lesscode/lib/client/src/element-materials/modifier/component/props/components/strategy/table-data-source.vue b/paas-ce/lesscode/lib/client/src/element-materials/modifier/component/props/components/strategy/table-data-source.vue new file mode 100644 index 000000000..8f584ac90 --- /dev/null +++ b/paas-ce/lesscode/lib/client/src/element-materials/modifier/component/props/components/strategy/table-data-source.vue @@ -0,0 +1,80 @@ + + + diff --git a/paas-ce/lesscode/lib/client/src/element-materials/modifier/component/slots/components/data-source.vue b/paas-ce/lesscode/lib/client/src/element-materials/modifier/component/slots/components/data-source.vue new file mode 100644 index 000000000..a6ad2953c --- /dev/null +++ b/paas-ce/lesscode/lib/client/src/element-materials/modifier/component/slots/components/data-source.vue @@ -0,0 +1,63 @@ + + + diff --git a/paas-ce/lesscode/lib/client/src/element-materials/modifier/component/slots/components/form-item-edit.vue b/paas-ce/lesscode/lib/client/src/element-materials/modifier/component/slots/components/form-item-edit.vue index e1f4b96ce..59ed8095d 100644 --- a/paas-ce/lesscode/lib/client/src/element-materials/modifier/component/slots/components/form-item-edit.vue +++ b/paas-ce/lesscode/lib/client/src/element-materials/modifier/component/slots/components/form-item-edit.vue @@ -37,7 +37,8 @@
- 提交 + 提交 + 提交并继续新增 取消
@@ -47,6 +48,15 @@ diff --git a/paas-ce/lesscode/lib/client/src/element-materials/modifier/component/styles/strategy/size.vue b/paas-ce/lesscode/lib/client/src/element-materials/modifier/component/styles/strategy/size.vue index 73c321fb6..d4afb22a4 100644 --- a/paas-ce/lesscode/lib/client/src/element-materials/modifier/component/styles/strategy/size.vue +++ b/paas-ce/lesscode/lib/client/src/element-materials/modifier/component/styles/strategy/size.vue @@ -11,16 +11,25 @@ @@ -43,6 +52,10 @@ type: Object, required: true }, + type: { + type: String, + default: '' + }, change: { type: Function, required: true @@ -50,8 +63,10 @@ }, data () { return { + minWidthValue: splitValueAndUnit('value', this.value.minWidth), widthValue: splitValueAndUnit('value', this.value.width), heightValue: splitValueAndUnit('value', this.value.height), + minWidthUnit: splitValueAndUnit('unit', this.value.minWidth) || 'px', widthUnit: splitValueAndUnit('unit', this.value.width) || 'px', heightUnit: splitValueAndUnit('unit', this.value.height) || 'px' } @@ -60,7 +75,8 @@ handleInputChange (key, val) { const unitMap = { width: this.widthUnit, - height: this.heightUnit + height: this.heightUnit, + minWidth: this.minWidthUnit } const newValue = val === '' ? '' : val + unitMap[key] this.change(key, newValue) @@ -72,9 +88,13 @@ if (key === 'height' && this.heightValue !== '') { this.heightValue = Math.min(this.heightValue, unit === '%' ? 100 : this.heightValue) } + if (key === 'minWidth' && this.minWidthValue !== '') { + this.minWidthValue = Math.min(this.minWidthValue, unit === '%' ? 100 : this.minWidthValue) + } const valueMap = { width: this.widthValue, - height: this.heightValue + height: this.heightValue, + minWidth: this.minWidthValue } if (valueMap[key] !== '') { this.change(key, valueMap[key] + unit) diff --git a/paas-ce/lesscode/lib/client/src/main.js b/paas-ce/lesscode/lib/client/src/main.js index ae49382e3..6e8278337 100644 --- a/paas-ce/lesscode/lib/client/src/main.js +++ b/paas-ce/lesscode/lib/client/src/main.js @@ -12,6 +12,7 @@ import Vue from 'vue' import VueDraggable from 'vuedraggable' import mavonEditor from 'mavon-editor' +import VueCompositionAPI from '@vue/composition-api' import 'mavon-editor/dist/css/index.css' import '@/common/bkui-vue-complex' import '@/common/bkmagic' @@ -28,6 +29,7 @@ import Exception from '@/components/exception' import { bus } from '@/common/bus' import header from '@/components/header.vue' import renderHtml from '@/components/render/html.vue' +import ProjectVersionSelector from '@/components/project-version-selector.vue' import '@icon-cool/bk-icon-vue-drag-vis' import '@icon-cool/bk-icon-vue-drag-vis/src/index' @@ -45,11 +47,13 @@ Vue.prototype.$clearMenu = () => { } Vue.use(mavonEditor) +Vue.use(VueCompositionAPI) Vue.component('VueDraggable', VueDraggable) Vue.component('app-exception', Exception) Vue.component('app-header', header) Vue.component('render-html', renderHtml) +Vue.component('project-version-selector', ProjectVersionSelector) auth.requestCurrentUser().then(user => { injectCSRFTokenToHeaders() diff --git a/paas-ce/lesscode/lib/client/src/preview/component.js b/paas-ce/lesscode/lib/client/src/preview/component.js index 1488106d8..c5156e1b4 100644 --- a/paas-ce/lesscode/lib/client/src/preview/component.js +++ b/paas-ce/lesscode/lib/client/src/preview/component.js @@ -16,7 +16,7 @@ import '@/common/element' // 注入全局组件 import renderHtml from '@/components/render/html' -module.exports = (Vue, projectId) => { +module.exports = (Vue, projectId, versionId) => { return new Promise((resolve, reject) => { // 注入自定义组件 window.previewCustomCompontensPlugin = [] @@ -24,7 +24,7 @@ module.exports = (Vue, projectId) => { window.previewCustomCompontensPlugin.push(callback) } const script = document.createElement('script') - script.src = `/${parseInt(projectId)}/component/preview-register.js` + script.src = `/${parseInt(projectId)}/component/preview-register.js?v=${versionId || ''}` script.onload = () => { window.previewCustomCompontensPlugin.forEach(callback => { const [config, source] = callback(Vue) diff --git a/paas-ce/lesscode/lib/client/src/preview/index.js b/paas-ce/lesscode/lib/client/src/preview/index.js index 2f6f32a75..3d0d0b03d 100644 --- a/paas-ce/lesscode/lib/client/src/preview/index.js +++ b/paas-ce/lesscode/lib/client/src/preview/index.js @@ -20,6 +20,12 @@ const location = window.parent.location const projectIdReg = new RegExp(`${location.origin}/preview/project/(\\d+)`) const [, projectId] = projectIdReg.exec(location.href) || [] +const storageKey = `preview-project-version-${projectId}` +const versionId = new URLSearchParams(location.search).get('v') || sessionStorage.getItem(storageKey) || '' +if (versionId) { + sessionStorage.setItem(storageKey, versionId) +} + // 获取初始化路由 let proxyResolve const getDefaultRoute = new Promise(resolve => { @@ -34,7 +40,7 @@ window.addEventListener('message', ({ data }) => { }) auth(projectId).then(() => { - return Promise.all([pureAxios.get(`/projectCode/previewCode?projectId=${projectId}`), registerComponent(Vue, projectId)]).then(([res]) => { + return Promise.all([pureAxios.get(`/projectCode/previewCode?projectId=${projectId}&versionId=${versionId}`), registerComponent(Vue, projectId, versionId)]).then(([res]) => { Vue.prototype.$http = pureAxios const data = res.data || {} const projectPageRouteList = (data.pageRouteList || []).map(item => ({ @@ -43,11 +49,12 @@ auth(projectId).then(() => { })) const projectRouteList = (Object.values(data.routeGroup) || []).map(({ children }) => children) .reduce((pre, cur) => pre.concat(cur), []) - .map(({ id, layoutPath, path, redirect }) => ({ + .map(({ id, layoutPath, path, redirect, pageCode }) => ({ id, layoutPath, path, redirect, + pageCode, fullPath: `${layoutPath}${layoutPath.endsWith('/') ? '' : '/'}${path}` })) const { router, App } = generateRouter(data.routeGroup, projectPageRouteList) @@ -73,7 +80,7 @@ auth(projectId).then(() => { let pageRoute if (pageCode) { pageRoute = projectPageRouteList.find(item => item.pageCode === pageCode) - } else if (fullPath === '/') { + } else if (/^\/(\?v=\d+)*$/.test(fullPath)) { // 判定为项目预览,找到父路由是/的页面 pageRoute = this.getProjectDefaultHome() pageCode = '' @@ -89,7 +96,7 @@ auth(projectId).then(() => { // 绑定的跳转路由可能未绑定页面或路由 this.$router.replace({ path: '/404', query: { p: pageCode } }) } else { - this.$router.replace({ path: pageRoute.fullPath }) + this.$router.replace({ path: pageRoute.fullPath, query: { pageCode: pageRoute.pageCode } }) } } else { this.$router.replace({ path: '/404', query: { p: pageCode } }) diff --git a/paas-ce/lesscode/lib/client/src/router/index.js b/paas-ce/lesscode/lib/client/src/router/index.js index 0afb5e850..edb9c5a29 100644 --- a/paas-ce/lesscode/lib/client/src/router/index.js +++ b/paas-ce/lesscode/lib/client/src/router/index.js @@ -36,6 +36,7 @@ const RouterManage = () => import(/* webpackChunkName: 'route' */'@/views/projec const Basic = () => import(/* webpackChunkName: 'basic' */'@/views/project/basic') const Logs = () => import(/* webpackChunkName: 'basic' */'@/views/project/logs') const Layout = () => import(/* webpackChunkName: 'layout' */'@/views/project/layout') +const VersionManage = () => import(/* webpackChunkName: 'version' */'@/views/project/version-manage') const MainEntry = () => import(/* webpackChunkName: 'index' */'@/views') const Index = () => import(/* webpackChunkName: 'index' */'@/views/index/index') @@ -60,6 +61,15 @@ const Directive = () => import(/* webpackChunkName: 'directive' */'@/views/help/ const FreeLayoutDoc = () => import(/* webpackChunkName: 'grid' */'@/views/help/docs/free-layout.md') const Interactive = () => import(/* webpackChunkName: 'interactive' */'@/views/help/docs/interactive.md') +// 数据源管理 +const DataSourceHome = () => import(/* webpackChunkName: 'DataSource' */'@/views/project/data-source-manage/index.vue') +const DataSourceTableList = () => import(/* webpackChunkName: 'DataSource' */'@/views/project/data-source-manage/table-design/table-list/index.vue') +const DataSourceCreateTable = () => import(/* webpackChunkName: 'DataSource' */'@/views/project/data-source-manage/table-design/create-table.vue') +const DataSourceEditTable = () => import(/* webpackChunkName: 'DataSource' */'@/views/project/data-source-manage/table-design/edit-table.vue') +const DataSourceShowTable = () => import(/* webpackChunkName: 'DataSource' */'@/views/project/data-source-manage/table-design/show-table.vue') +const DataSourceUpdateRecord = () => import(/* webpackChunkName: 'DataSource' */'@/views/project/data-source-manage/table-design/update-record.vue') +const DataSourceDataManage = () => import(/* webpackChunkName: 'DataSource' */'@/views/project/data-source-manage/data-manage/index.vue') + // 运营统计 const OperationEntry = () => import(/* webpackChunkName: 'operation-stats-entry' */'@/views/system/operation/index.vue') const OperationStatsUser = () => import(/* webpackChunkName: 'operation-stats-user' */'@/views/system/operation/stats/user/index.vue') @@ -223,6 +233,44 @@ const routes = [ title: '变量管理' } }, + { + path: 'data-source-manage', + name: 'dataSourceManage', + component: DataSourceHome, + redirect: { name: 'tableList' }, + children: [ + { + path: '', + name: 'tableList', + component: DataSourceTableList + }, + { + path: 'create-table', + name: 'createTable', + component: DataSourceCreateTable + }, + { + path: 'edit-table', + name: 'editTable', + component: DataSourceEditTable + }, + { + path: 'show-table', + name: 'showTable', + component: DataSourceShowTable + }, + { + path: 'update-table-record', + name: 'updateTableRecord', + component: DataSourceUpdateRecord + }, + { + path: 'data-manage', + name: 'dataManage', + component: DataSourceDataManage + } + ] + }, { path: 'layout', name: 'layout', @@ -239,6 +287,14 @@ const routes = [ title: '路由配置' } }, + { + path: 'versions', + name: 'versions', + component: VersionManage, + meta: { + title: '版本管理' + } + }, { path: 'member-manage', name: 'memberManage', @@ -267,7 +323,7 @@ const routes = [ }, { name: 'page-entry', - path: `/project/:projectId/page/:pageId`, + path: '/project/:projectId/page/:pageId', components: { default: MainEntry, permission: require('@/views/status/non-exist-project').default diff --git a/paas-ce/lesscode/lib/client/src/store/index.js b/paas-ce/lesscode/lib/client/src/store/index.js index 83be3ef8f..8ce74dca5 100644 --- a/paas-ce/lesscode/lib/client/src/store/index.js +++ b/paas-ce/lesscode/lib/client/src/store/index.js @@ -28,6 +28,8 @@ import member from './modules/member' import logs from './modules/logs' import functionMarket from './modules/function-market' import perm from './modules/perm' +import projectVersion from './modules/project-version' +import dataSource from './modules/data-source' import http from '@/api' import router from '../router' import { unifyObjectStyle, json2Query } from '@/common/util' @@ -52,7 +54,9 @@ const store = new Vuex.Store({ member, logs, functionMarket, - perm + perm, + projectVersion, + dataSource }, // 公共 store state: { diff --git a/paas-ce/lesscode/lib/client/src/store/modules/data-source.js b/paas-ce/lesscode/lib/client/src/store/modules/data-source.js new file mode 100644 index 000000000..edda274e7 --- /dev/null +++ b/paas-ce/lesscode/lib/client/src/store/modules/data-source.js @@ -0,0 +1,87 @@ +/** + * Tencent is pleased to support the open source community by making 蓝鲸智云PaaS平台社区版 (BlueKing PaaS Community Edition) available. + * Copyright (C) 2017-2019 THL A29 Limited, a Tencent company. All rights reserved. + * Licensed under the MIT License (the "License"); you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * http://opensource.org/licenses/MIT + * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on + * 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 http from '@/api' +const perfix = 'data-source' + +export default { + namespaced: true, + state: { + tableList: [] + }, + mutations: { + setTableList (state, tableList) { + state.tableList = tableList || [] + } + }, + getters: { + }, + actions: { + enable (_, projectId) { + return http.post(`${perfix}/enable`, { projectId }).then(response => { + const data = response.data || [] + return data + }) + }, + list ({ commit }, params = {}) { + return http.get(`${perfix}/getTableList`, { params }).then(response => { + const data = response.data || [] + commit('setTableList', data?.list) + return data + }) + }, + add (_, postData) { + return http.post(`${perfix}/addTable`, postData).then(response => { + return response.data + }) + }, + delete (_, deleteData) { + return http.put(`${perfix}/deleteTable`, deleteData).then(response => { + return response.data + }) + }, + edit (_, postData) { + return http.put(`${perfix}/updateTable`, postData).then(response => { + return response.data + }) + }, + findOne (_, id) { + return http.get(`${perfix}/getTableDetail`, { params: { id } }).then(response => { + const data = response.data || [] + return data + }) + }, + modifyOnlineDb (_, data) { + return http.put(`${perfix}/modifyOnlineDb`, data).then(response => { + const data = response.data || [] + return data + }) + }, + tableRecordList (_, params) { + return http.post(`${perfix}/tableRecordList`, params).then(response => { + const data = response.data || [] + return data + }) + }, + getOnlineTableList (_, params) { + return http.get(`${perfix}/getOnlineTableList`, { params }).then(response => { + const data = response.data || [] + return data + }) + }, + getOnlineTableDatas (_, params) { + return http.get(`${perfix}/getOnlineTableDatas`, { params }).then(response => { + const data = response.data || [] + return data + }) + } + } +} 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 2bb492bc3..1202ec6d1 100644 --- a/paas-ce/lesscode/lib/client/src/store/modules/functions.js +++ b/paas-ce/lesscode/lib/client/src/store/modules/functions.js @@ -23,8 +23,8 @@ export default { funcGroups: state => state.funcGroups }, actions: { - getAllGroupFuncs ({ state }, projectId, isCommit = true) { - return http.get(`${perfix}/getAllGroupFunc`, { params: { projectId } }).then((res = {}) => { + getAllGroupFuncs ({ state }, params, isCommit = true) { + return http.get(`${perfix}/getAllGroupFunc`, { params }).then((res = {}) => { isCommit && (state.funcGroups = res.data || []) return res.data || [] }) diff --git a/paas-ce/lesscode/lib/client/src/store/modules/layout.js b/paas-ce/lesscode/lib/client/src/store/modules/layout.js index fef93197d..27ee5e001 100644 --- a/paas-ce/lesscode/lib/client/src/store/modules/layout.js +++ b/paas-ce/lesscode/lib/client/src/store/modules/layout.js @@ -31,14 +31,14 @@ export default { return data }) }, - getList ({ state }, { projectId }) { - return http.get(`/layout/getList?projectId=${projectId}`).then(response => { + getList ({ state }, params) { + return http.get('/layout/getList', { params }).then(response => { const data = response.data || [] return data }) }, - getFullList ({ state }, { projectId }) { - return http.get(`/layout/getFullList?projectId=${projectId}`).then(response => { + getFullList ({ state }, params) { + return http.get('/layout/getFullList', { params }).then(response => { const data = response.data return data }) @@ -51,13 +51,13 @@ export default { }) }, create ({ commit }, { data, config }) { - return http.post(`/layout/create`, data, config).then(response => { + return http.post('/layout/create', data, config).then(response => { const data = response.data || '' return data }) }, update ({ commit }, { data, config }) { - return http.post(`/layout/update`, data, config).then(response => { + return http.post('/layout/update', data, config).then(response => { const data = response.data || '' return data }) diff --git a/paas-ce/lesscode/lib/client/src/store/modules/page-template.js b/paas-ce/lesscode/lib/client/src/store/modules/page-template.js index e5a555680..0c869315a 100644 --- a/paas-ce/lesscode/lib/client/src/store/modules/page-template.js +++ b/paas-ce/lesscode/lib/client/src/store/modules/page-template.js @@ -39,19 +39,25 @@ export default { }) }, checkIsExist (state, params = {}) { - return http.post(`/pageTemplate/checkIsExist`, params).then(response => { + return http.post('/pageTemplate/checkIsExist', params).then(response => { const data = response.data || '' return data }) }, create (state, params) { - return http.post(`/pageTemplate/create`, params).then(response => { + return http.post('/pageTemplate/create', params).then(response => { const data = response.data || '' return data }) }, apply (state, params = {}) { - return http.post(`pageTemplate/apply`, params).then(response => { + return http.post('pageTemplate/apply', params).then(response => { + const data = response.data || '' + return data + }) + }, + import (state, params = {}) { + return http.post('pageTemplate/import', params).then(response => { const data = response.data || '' return data }) @@ -75,7 +81,7 @@ export default { }) }, categoryList (state, params = {}) { - return http.get(`/pageTemplateCategory/list`, { params }).then(response => { + return http.get('/pageTemplateCategory/list', { params }).then(response => { const data = response.data || '' return data }) 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 7eead8303..a4c36d450 100644 --- a/paas-ce/lesscode/lib/client/src/store/modules/page.js +++ b/paas-ce/lesscode/lib/client/src/store/modules/page.js @@ -43,8 +43,8 @@ export default { return data }) }, - getList ({ commit }, { projectId }) { - return http.get(`/page/getList?projectId=${projectId}`).then(response => { + getList ({ commit }, params) { + return http.get('/page/getList', { params }).then(response => { const data = response.data || '' return data }) diff --git a/paas-ce/lesscode/lib/client/src/store/modules/project-version.js b/paas-ce/lesscode/lib/client/src/store/modules/project-version.js new file mode 100644 index 000000000..97fab17a2 --- /dev/null +++ b/paas-ce/lesscode/lib/client/src/store/modules/project-version.js @@ -0,0 +1,89 @@ +/** + * Tencent is pleased to support the open source community by making 蓝鲸智云PaaS平台社区版 (BlueKing PaaS Community Edition) available. + * Copyright (C) 2017-2019 THL A29 Limited, a Tencent company. All rights reserved. + * Licensed under the MIT License (the "License"); you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * http://opensource.org/licenses/MIT + * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on + * 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 http from '@/api' + +const storageKey = 'project-version' + +export default { + namespaced: true, + state: { + versionList: [], + currentVersion: {} + }, + mutations: { + setVersionList (state, list) { + state.versionList = Object.freeze(list) + }, + setCurrentVersion (state, version) { + state.currentVersion = Object.freeze(version) + localStorage.setItem(storageKey, JSON.stringify(version)) + } + }, + getters: { + versionList: state => state.versionList, + currentVersion: state => state.currentVersion, + initialVersion: (state) => () => { + const storageVersion = localStorage.getItem(storageKey) + let version = {} + if (storageVersion) { + try { + const data = JSON.parse(storageVersion) + version = data + } catch (e) { + console.error(e) + } + } + return version + }, + currentVersionId: state => state.currentVersion.id || null, + currentVersionName: state => state.currentVersion.version || null, + getVersionById: state => id => state.versionList.find(v => v.id === id) || {} + }, + actions: { + create ({ commit }, data) { + return http.post('/projectVersion/create', data).then(response => { + const data = response.data || '' + return data + }) + }, + update ({ commit }, data) { + return http.put('/projectVersion/update', data).then(response => { + const data = response.data || '' + return data + }) + }, + getList ({ commit }, params) { + return http.get('/projectVersion/list', { params }).then(response => { + const data = response.data || '' + return data + }) + }, + getOptionList ({ commit }, params) { + return http.get('/projectVersion/optionList', { params }).then(response => { + const data = response.data || '' + return data + }) + }, + recover ({ commit }, data) { + return http.post('/projectVersion/recover', data).then(response => { + const data = response.data || '' + return data + }) + }, + archive ({ commit }, data) { + return http.post('/projectVersion/archive', data).then(response => { + const data = response.data || '' + return data + }) + } + } +} diff --git a/paas-ce/lesscode/lib/client/src/store/modules/release.js b/paas-ce/lesscode/lib/client/src/store/modules/release.js index e9063ef6b..b2e80471b 100644 --- a/paas-ce/lesscode/lib/client/src/store/modules/release.js +++ b/paas-ce/lesscode/lib/client/src/store/modules/release.js @@ -44,7 +44,7 @@ export default { }) }, detailInfo ({ state }, postData) { - return http.post(`/release/detailInfo`, postData).then(response => { + return http.post('/release/detailInfo', postData).then(response => { const data = response.data || {} return data }) @@ -74,19 +74,19 @@ export default { }) }, updateVersion ({ state }, { id, data }) { - return http.put(`/release/updateReleaseVersion`, { id, data }).then(response => { + return http.put('/release/updateReleaseVersion', { id, data }).then(response => { const data = response.data || '' return data }) }, checkAppInfoExist ({ state }, data) { - return http.post(`/release/checkAppInfoExist`, data).then(response => { + return http.post('/release/checkAppInfoExist', data).then(response => { const data = response.data || false return data }) }, offlineProject ({ state }, data) { - return http.post(`/release/offlineProject`, data).then(response => { + return http.post('/release/offlineProject', data).then(response => { const data = response.data || false return data }) diff --git a/paas-ce/lesscode/lib/client/src/store/modules/route.js b/paas-ce/lesscode/lib/client/src/store/modules/route.js index 8201a5b4e..403f5cc17 100644 --- a/paas-ce/lesscode/lib/client/src/store/modules/route.js +++ b/paas-ce/lesscode/lib/client/src/store/modules/route.js @@ -24,20 +24,20 @@ export default { getters: { }, actions: { - query ({ commit }, { projectId, config }) { - return http.get(`/route/query/${projectId}`, config).then(response => { + query ({ commit }, { projectId, versionId, config }) { + return http.get(`/route/query/${projectId}?versionId=${versionId}`, config).then(response => { const data = response.data || '' return data }) }, - getProjectRouteGroup ({ commit }, { projectId, config }) { - return http.get(`/route/project/${projectId}`, config).then(response => { + getProjectRouteGroup ({ commit }, { projectId, versionId, config }) { + return http.get(`/route/project/${projectId}`, { params: { versionId } }, config).then(response => { const data = response.data || '' return data }) }, - getProjectRouteTree ({ commit }, { projectId, config }) { - return http.get(`/route/project/${projectId}/tree`, config).then(response => { + getProjectRouteTree ({ commit }, { projectId, versionId, config }) { + return http.get(`/route/project/${projectId}/tree`, { params: { versionId } }, config).then(response => { const data = response.data || '' return data }) @@ -67,8 +67,8 @@ export default { return data }) }, - getProjectPageRoute ({ commit }, { projectId, config }) { - return http.get(`/route/project/${projectId}/page`, config).then(response => { + getProjectPageRoute ({ commit }, { projectId, versionId, config }) { + return http.get(`/route/project/${projectId}/page`, { params: { versionId } }, config).then(response => { const data = response.data || [] commit('setLayoutPageList', data) }) diff --git a/paas-ce/lesscode/lib/client/src/store/modules/variable.js b/paas-ce/lesscode/lib/client/src/store/modules/variable.js index 46ddfed68..6c85238ea 100644 --- a/paas-ce/lesscode/lib/client/src/store/modules/variable.js +++ b/paas-ce/lesscode/lib/client/src/store/modules/variable.js @@ -46,8 +46,8 @@ export default { commit('setVariableFormData', data) }, - getAllProjectVariable ({ commit }, projectId) { - return http.get(`${variablePerfix}/getAllVariable`, { params: { projectId } }).then(response => { + getAllProjectVariable ({ commit }, params) { + return http.get(`${variablePerfix}/getAllVariable`, { params }).then(response => { const data = response.data || [] return data }) @@ -61,6 +61,13 @@ export default { }) }, + getFunctionVariable ({ commit }, params) { + return http.post(`${variablePerfix}/getFunctionVariable`, params).then(response => { + const data = response.data || [] + return data + }) + }, + addVariable ({ commit }, data) { return http.put(`${variablePerfix}/addVariable`, data).then(response => { if (response.code === 499) throw new Error(response.message) 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 678c790bc..48b0bb4f6 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,20 @@
+### v0.3.0 +###### 2021.11.25 + +* **[add]**: + - 项目: 增加项目版本管理功能 + - 项目:增加在线建表、数据源管理模块 + - 项目:页面内容模板支持导入导出 + - 画布: 增加页面级别的样式配置,可在画布编辑页页面设置tab设置页面内容区域的样式 + - 画布: 表单容器表单项编辑增加保存并继续新增选项 + - 画布:组件样式补充(link、input、upload、timeline、diff、布局、colorpicker) +* **[fix]**: + - 画布: 画布拖拽体验问题优化 + - 画布: 修复编辑form-item导致表单组件内容被重置问题 + ### v0.2.9 ###### 2021.10.13 diff --git a/paas-ce/lesscode/lib/client/src/views/index/index.css b/paas-ce/lesscode/lib/client/src/views/index/index.css index 94892c34a..5fa7fff5d 100644 --- a/paas-ce/lesscode/lib/client/src/views/index/index.css +++ b/paas-ce/lesscode/lib/client/src/views/index/index.css @@ -76,7 +76,7 @@ $headerHeight: 64px; position: absolute; width: 530px; height: 230px; - left: 0; + right: 0; top: 60px; background: #fff; color: #000; @@ -90,7 +90,7 @@ $headerHeight: 64px; width: 12px; height: 12px; transform: rotate(45deg); - left: 13px; + right: 13px; top: -6px; background: #fff; } @@ -480,24 +480,38 @@ $headerHeight: 64px; } .name-content { + display: flex; + align-items: center; font-size: 14px; - margin-left: 10px; - width: 190px; - overflow: hidden; - white-space: nowrap; - text-overflow: ellipsis; + margin: 0 24px 0 10px; .project-name { color: #979BA5; } + + .col-name { + overflow: hidden; + white-space: nowrap; + text-overflow: ellipsis; + } + .col-version { + background: #dcdee5; + border-radius: 9px; + height: 18px; + font-size: 12px; + line-height: 18px; + color: #63656e; + padding: 0 8px; + white-space: nowrap; + } } - .select-page-box{ + .select-page-box { display: flex; flex: 1; align-items: center; height: 100%; .select-page { - width: 250px; + width: 290px; margin-left: 5px; border: none; background-color: #f0f1f5; 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 f82bfe3b5..a4c82d9e7 100644 --- a/paas-ce/lesscode/lib/client/src/views/index/index.vue +++ b/paas-ce/lesscode/lib/client/src/views/index/index.vue @@ -31,7 +31,8 @@ @selected="changeProjectPage">
- {{ pageDetail.pageName }}【{{ projectDetail.projectName }}】 +
{{ pageDetail.pageName }}【{{ projectDetail.projectName }}】
+
{{versionName}}
@@ -214,7 +215,7 @@
- +
@@ -503,6 +504,7 @@ ...mapGetters('layout', ['pageLayout']), ...mapGetters('components', ['interactiveComponents']), ...mapGetters('variable', ['variableList']), + ...mapGetters('projectVersion', { versionId: 'currentVersionId', versionName: 'currentVersionName', getInitialVersion: 'initialVersion' }), ...mapState('route', ['layoutPageList']), copyIconStyle () { return { @@ -622,6 +624,10 @@ target: '#editPageSwitchPage' } ] + + // 获取并设置当前版本信息 + this.$store.commit('projectVersion/setCurrentVersion', this.getInitialVersion()) + await this.fetchData() const mockCurSelectComponentData = { @@ -709,7 +715,7 @@ beforeRouteLeave (to, from, next) { this.$bkInfo({ title: '确认离开?', - subTitle: `您将离开画布编辑页面,请确认相应修改已保存`, + subTitle: '您将离开画布编辑页面,请确认相应修改已保存', confirmFn: async () => { next() } @@ -910,18 +916,23 @@ this.contentLoading = true const [pageDetail, pageList, projectDetail] = await Promise.all([ this.$store.dispatch('page/detail', { pageId: this.pageId }), - this.$store.dispatch('page/getList', { projectId: this.projectId }), + this.$store.dispatch('page/getList', { projectId: this.projectId, versionId: this.versionId }), this.$store.dispatch('project/detail', { projectId: this.projectId }), this.$store.dispatch('page/pageLockStatus', { pageId: this.pageId }), - this.$store.dispatch('route/getProjectPageRoute', { projectId: this.projectId }), + this.$store.dispatch('route/getProjectPageRoute', { projectId: this.projectId, versionId: this.versionId }), this.$store.dispatch('layout/getPageLayout', { pageId: this.pageId }), this.$store.dispatch('components/componentNameMap'), - this.getAllGroupFuncs(this.projectId) + this.getAllGroupFuncs({ projectId: this.projectId, versionId: this.versionId }) ]) - await this.lockStatsuPolling('lock') // 处理加锁逻辑 - - await this.getAllVariable({ projectId: this.projectId, pageCode: pageDetail.pageCode, effectiveRange: 0 }) + await Promise.all([ + // 处理加锁逻辑 + this.lockStatsuPolling('lock'), + // 添加变量 + this.getAllVariable({ projectId: this.projectId, versionId: this.versionId, pageCode: pageDetail.pageCode, effectiveRange: 0 }), + // 添加表 + this.$store.dispatch('dataSource/list', { projectId: this.projectId }) + ]) // update targetdata const content = pageDetail.content if (content) { @@ -1530,7 +1541,8 @@ try { localStorage.removeItem('layout-target-data') localStorage.setItem('layout-target-data', circleJSON(this.targetData)) - const routerUrl = `/preview/project/${this.projectId}/?pageCode=${this.pageDetail.pageCode}` + const versionQuery = `${this.versionId ? `&v=${this.versionId}` : ''}` + const routerUrl = `/preview/project/${this.projectId}/?pageCode=${this.pageDetail.pageCode}${versionQuery}` window.open(routerUrl, '_blank') } catch (err) { errTips = err.message || err || '预览异常' @@ -1574,6 +1586,7 @@ data: { from, projectId: this.projectId, + versionId: this.versionId, pageCode: this.pageDetail.pageCode, pageData: { id: parseInt(this.$route.params.pageId), @@ -1586,8 +1599,7 @@ } }) this.savePreviewImg() - const projectId = this.$route.params.projectId || 1 - this.getAllGroupFuncs(projectId) + this.getAllGroupFuncs({ projectId: this.projectId, versionId: this.versionId }) res && this.$bkMessage({ theme: 'success', message: '保存成功', @@ -1660,11 +1672,15 @@ const hasMethod = payload && payload.methodCode if (!hasMethod) errMessage = `组件【${component.componentId}】的属性【${key}】,类型为 remote 但未选择远程函数,请修改后再试` } + if (['data-source', 'table-data-source'].includes(type)) { + const hasTableName = payload?.sourceData?.tableName + if (!hasTableName) errMessage = `组件【${component.componentId}】的属性【${key}】,类型为数据源但未选择表,请修改后再试` + } }) const renderSlots = component.renderSlots || {} Object.keys(renderSlots).forEach((key) => { - const { type, payload = {} } = renderSlots[key] || {} + const { type, payload = {}, displayName } = renderSlots[key] || {} if (payload.variableData && payload.variableData.val) { const { val, valType } = payload.variableData @@ -1674,7 +1690,12 @@ if (type === 'remote') { const hasMethod = payload.methodData && payload.methodData.methodCode - if (!hasMethod) errMessage = `组件【${component.componentId}】的【${key}】插槽,类型为 remote 但未选择远程函数,请修改后再试` + if (!hasMethod) errMessage = `组件【${component.componentId}】的【${displayName}】插槽,类型为 remote 但未选择远程函数,请修改后再试` + } + + if (['data-source'].includes(type)) { + const hasTableName = payload?.sourceData?.tableName + if (!hasTableName) errMessage = `组件【${component.componentId}】的【${displayName}】插槽,类型为数据源但未选择表,请修改后再试` } }) @@ -1762,6 +1783,7 @@ this.$store.dispatch('page/update', { data: { projectId: this.projectId, + versionId: this.versionId, pageData: { id: parseInt(this.$route.params.pageId), previewImg: imgData || previewErrorImg @@ -1789,7 +1811,7 @@ } me.$bkInfo({ title: '确认离开?', - subTitle: `您将离开画布编辑页面,请确认相应修改已保存`, + subTitle: '您将离开画布编辑页面,请确认相应修改已保存', confirmFn: async () => { me.$router.push({ params: { diff --git a/paas-ce/lesscode/lib/client/src/views/preview/preview-template.vue b/paas-ce/lesscode/lib/client/src/views/preview/preview-template.vue index 0c132339c..11e250b56 100644 --- a/paas-ce/lesscode/lib/client/src/views/preview/preview-template.vue +++ b/paas-ce/lesscode/lib/client/src/views/preview/preview-template.vue @@ -64,11 +64,17 @@ }, templateId () { return this.$route.params.templateId || '' + }, + versionId () { + return this.$route.query.v || '' + }, + type () { + return this.$route.query.type || '' } }, async created () { const script = document.createElement('script') - script.src = `/${parseInt(this.projectId)}/component/preview-register.js` + script.src = `/${parseInt(this.projectId)}/component/preview-register.js?v=${this.versionId}` script.onload = () => { window.previewCustomCompontensPlugin.forEach(callback => { const [config, source] = callback(Vue) @@ -78,7 +84,16 @@ } document.body.appendChild(script) - this.detail = await this.$store.dispatch('pageTemplate/detail', { id: this.templateId }) + if (this.type === 'nav-template') { + try { + const { list } = await this.$store.dispatch('layout/getFullList', { projectId: this.projectId, versionId: this.versionId }) + this.detail = list.filter(item => item.id === parseInt(this.templateId))[0] + } catch (e) { + console.error(e) + } + } else { + this.detail = await this.$store.dispatch('pageTemplate/detail', { id: this.templateId }) + } await this.loadFile() }, @@ -93,7 +108,9 @@ async loadFile () { this.isLoading = true try { - this.targetData.push(JSON.parse(this.detail.content || {})) + if (this.type !== 'nav-template') { + this.targetData.push(JSON.parse(this.detail.content || {})) + } } catch (err) { this.$bkMesseage({ theme: 'error', @@ -104,16 +121,29 @@ try { console.log('预览 loadFile') const { targetData, projectId } = this - - let code = await this.$store.dispatch('vueCode/getPageCode', { - targetData, - projectId: projectId, - pageType: 'previewSingle', - fromPageCode: this.detail.fromPageCode - }) - + let code + if (this.type === 'nav-template') { + const layoutContent = JSON.parse(this.detail.content) + code = await this.$store.dispatch('vueCode/getPageCode', { + targetData: [], + pageType: 'previewSingle', + projectId: projectId, + versionId: this.detail.versionId, + layoutContent, + withNav: true, + layoutType: this.detail.type + }) + } else { + code = await this.$store.dispatch('vueCode/getPageCode', { + targetData, + projectId: projectId, + versionId: this.detail.versionId, + pageType: 'previewSingle', + fromPageCode: this.detail.fromPageCode + }) + } + code = code.replace('export default', 'module.exports =').replace('components: { chart: ECharts },', '') - console.log(code) const res = httpVueLoader(code) setTimeout(() => { Vue.component('preview-page', res) diff --git a/paas-ce/lesscode/lib/client/src/views/project/component-manage/all/components/operation.vue b/paas-ce/lesscode/lib/client/src/views/project/component-manage/all/components/operation.vue index c91536eab..302b7e475 100644 --- a/paas-ce/lesscode/lib/client/src/views/project/component-manage/all/components/operation.vue +++ b/paas-ce/lesscode/lib/client/src/views/project/component-manage/all/components/operation.vue @@ -157,7 +157,7 @@ 组件ID对应的组件包内config.json里的type配置,上传成功后会自动添加项目ID(${this.currentProject.projectCode})前缀,即:${this.currentProject.projectCode}-xxx; 组件源码须使用平台提供的打包工具打包生成min.js文件后再上传。 ` - this.versionLogPlaceholder = `eg: 新增 XXX 功能\n 优化 XXX 功能\n 修复 XXX 功能\n` + this.versionLogPlaceholder = 'eg: 新增 XXX 功能\n 优化 XXX 功能\n 修复 XXX 功能\n' this.markdownOption = { defaultOpen: 'edit' diff --git a/paas-ce/lesscode/lib/client/src/views/project/component-manage/all/components/render-list.vue b/paas-ce/lesscode/lib/client/src/views/project/component-manage/all/components/render-list.vue index 68588a91d..c31ace553 100644 --- a/paas-ce/lesscode/lib/client/src/views/project/component-manage/all/components/render-list.vue +++ b/paas-ce/lesscode/lib/client/src/views/project/component-manage/all/components/render-list.vue @@ -78,7 +78,7 @@ - diff --git a/paas-ce/lesscode/lib/client/src/views/project/component-manage/useing/index.vue b/paas-ce/lesscode/lib/client/src/views/project/component-manage/useing/index.vue index 589329609..7808283a8 100644 --- a/paas-ce/lesscode/lib/client/src/views/project/component-manage/useing/index.vue +++ b/paas-ce/lesscode/lib/client/src/views/project/component-manage/useing/index.vue @@ -1,7 +1,11 @@ + + diff --git a/paas-ce/lesscode/lib/client/src/views/project/data-source-manage/common/export.vue b/paas-ce/lesscode/lib/client/src/views/project/data-source-manage/common/export.vue new file mode 100644 index 000000000..a859a7c41 --- /dev/null +++ b/paas-ce/lesscode/lib/client/src/views/project/data-source-manage/common/export.vue @@ -0,0 +1,167 @@ + + + + + diff --git a/paas-ce/lesscode/lib/client/src/views/project/data-source-manage/common/field-table.tsx b/paas-ce/lesscode/lib/client/src/views/project/data-source-manage/common/field-table.tsx new file mode 100644 index 000000000..0fe77bb37 --- /dev/null +++ b/paas-ce/lesscode/lib/client/src/views/project/data-source-manage/common/field-table.tsx @@ -0,0 +1,340 @@ +/** + * Tencent is pleased to support the open source community by making 蓝鲸智云PaaS平台社区版 (BlueKing PaaS Community Edition) available. + * Copyright (C) 2017-2018 THL A29 Limited, a Tencent company. All rights reserved. + * Licensed under the MIT License (the "License"); you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * http://opensource.org/licenses/MIT + * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on + * 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 { + defineComponent, + watch, + reactive, + toRef, + ref +} from '@vue/composition-api' +import { VNode } from 'vue' +import fieldTable from '@/components/field-table/field-table' +import { uuid } from '@/common/util' +import { ORM_KEYS, BASE_COLUMNS } from 'shared/data-source/constant' + +export interface IFieldSelectOption { + id: string + name: string +} + +interface ITableFieldRule { + validator: Function, + message: string +} + +export interface ITableField { + name: string + type: string + prop: string + optionsList?: IFieldSelectOption[] + width?: string + isRequire?: boolean + inputType?: string + isReadonly?: boolean | Function, + componentProps?: Function | any, + rules?: ITableFieldRule[], + tips?: string +} + +export interface ITableStatus { + data: object[] +} + +function getDefaultRow () { + return { + type: '', + name: '', + primary: false, + index: false, + nullable: false, + default: '', + comment: '', + generated: false, + createDate: false, + updateDate: false, + length: '', + scale: '' + } +} + +/** + * orm 数据转为表格数据 + * @param item orm 数据 + * @returns 表格数据 + */ +function normalizeTableItem (item) { + const defaultRow = getDefaultRow() + const normalizedItem = Object.assign({}, defaultRow, item) + // 由于mysql限制,部分字段不可修改,需要设置默认值 + switch (normalizedItem.type) { + case 'int': + normalizedItem.length = 11 + normalizedItem.scale = 0 + break + case 'varchar': + normalizedItem.scale = 0 + break + case 'text': + normalizedItem.scale = 0 + normalizedItem.length = 65535 + normalizedItem.index = false + break + case 'datetime': + normalizedItem.scale = 0 + normalizedItem.length = 0 + normalizedItem.default = '' + break + default: + break + } + // 默认列不可修改 + if (BASE_COLUMNS.some(item => item.columnId === normalizedItem.columnId)) { + normalizedItem.isReadonly = true + } + // 每一行加id,用于 diff + if (!Reflect.has(normalizedItem, 'columnId')) { + normalizedItem.columnId = uuid(8) + } + return normalizedItem +} + +/** + * 表格数据转为orm 数据 + * @param item 表格数据 + * @returns orm 数据 + */ +function normalizeOrmItem (item) { + return ORM_KEYS.reduce((acc, cur) => { + if (Reflect.has(item, cur)) { + acc[cur] = item[cur] + } + return acc + }, {}) +} + +export default defineComponent({ + components: { + fieldTable + }, + + props: { + data: Array + }, + + setup (props: ITableStatus, { emit }) { + const tableFields: ITableField[] = [ + { + name: '字段名称', + type: 'input', + prop: 'name', + isRequire: true, + rules: [ + { + validator (val, row) { + return /^[a-zA-Z][a-zA-Z-_]*[a-zA-Z]$/.test(val) + }, + message: '开头和结尾需是大小写字母,中间可以是大小写字母、连字符和下划线。长度最少为2个字符' + }, + { + validator (val, row) { + return !tableList.find((table) => table.name === val && row.columnId !== table.columnId) + }, + message: '字段名称不能重复' + } + ] + }, + { + name: '字段类型', + type: 'select', + prop: 'type', + isRequire: true, + optionsList: [ + { + id: 'varchar', + name: 'varchar' + }, + { + id: 'int', + name: 'int' + }, + { + id: 'datetime', + name: 'datetime' + }, + { + id: 'text', + name: 'text' + }, + { + id: 'decimal', + name: 'decimal' + } + ] + }, + { + name: '长度', + type: 'input', + componentProps: { + type: 'number' + }, + prop: 'length', + isReadonly (item, props) { + return !['varchar', 'decimal'].includes(props?.row?.type) + }, + rules: [ + { + validator (val = 0, row) { + return row.type !== 'varchar' || (+val <= 15000 && +val > 0) + }, + message: 'varchar 类型的长度需大于 0 小于 15000' + }, + { + validator (val = 0, row) { + return row.type !== 'decimal' || (+val <= 65 && +val > 0) + }, + message: 'decimal 类型的长度需大于 0 小于 65' + } + ] + }, + { + name: '小数点', + type: 'input', + prop: 'scale', + componentProps: { + type: 'number' + }, + isReadonly (item, props) { + return !['decimal'].includes(props?.row?.type) + }, + rules: [ + { + validator (val = 0, row) { + return row.type !== 'decimal' || (+val > 0 && +val < +row.length) + }, + message: '小数点字段需要大于 0 且小于长度字段' + } + ] + }, + { + name: '索引', + type: 'checkbox', + prop: 'index', + width: '100px', + isReadonly (item, props) { + return props?.row?.type === 'text' + } + }, + { + name: '可空', + type: 'checkbox', + prop: 'nullable', + width: '100px' + }, + { + name: '默认值', + type: 'input', + prop: 'default', + isReadonly (item, props) { + return ['text', 'datetime'].includes(props?.row?.type) + }, + componentProps (item, props) { + if (['int', 'datetime', 'decimal'].includes(props?.row?.type)) { + return { + type: 'number', + precision: +props?.row?.scale + } + } else { + return { + type: 'text' + } + } + } + }, + { + name: '备注', + type: 'input', + prop: 'comment' + } + ] + const tableList = reactive([]) + const tableRef = ref(null) + + watch( + toRef(props, 'data'), + (val) => { + tableList.splice( + 0, + tableList.length, + ...val.map(normalizeTableItem) + ) + }, + { + immediate: true + } + ) + + const addField = (row, index) => { + const defaultRow = getDefaultRow() + tableList.splice(index + 1, 0, defaultRow) + emit('change') + } + + const deleteField = (row, index) => { + tableList.splice(index, 1) + emit('change') + } + + const changeData = (value, row, column, index) => { + // 设置值 + const currentRow = tableList[index] + Object.assign(currentRow, { [column.prop]: value }) + + // 标准化 + const normalizedItem = normalizeTableItem(currentRow) + Object.assign(currentRow, normalizedItem) + + // 触发 change 事件 + emit('change') + } + + const validate = () => { + return new Promise((resolve, reject) => { + tableRef.value?.verification().then(() => { + resolve(tableList.map(normalizeOrmItem)) + }).catch(reject) + }) + } + + return { + tableList, + tableFields, + tableRef, + addField, + deleteField, + changeData, + validate + } + }, + + render (): VNode { + return ( + + ) + } +}) diff --git a/paas-ce/lesscode/lib/client/src/views/project/data-source-manage/common/header.tsx b/paas-ce/lesscode/lib/client/src/views/project/data-source-manage/common/header.tsx new file mode 100644 index 000000000..bf0c171b3 --- /dev/null +++ b/paas-ce/lesscode/lib/client/src/views/project/data-source-manage/common/header.tsx @@ -0,0 +1,29 @@ +/** + * Tencent is pleased to support the open source community by making 蓝鲸智云PaaS平台社区版 (BlueKing PaaS Community Edition) available. + * Copyright (C) 2017-2018 THL A29 Limited, a Tencent company. All rights reserved. + * Licensed under the MIT License (the "License"); you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * http://opensource.org/licenses/MIT + * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on + * 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 { defineComponent } from '@vue/composition-api' +import { VNode } from 'vue' +import ExtraLinks from '@/components/ui/extra-links.vue' + +export default defineComponent({ + components: { + ExtraLinks + }, + + render (): VNode { + return ( + + ) + } +}) diff --git a/paas-ce/lesscode/lib/client/src/views/project/data-source-manage/common/import.vue b/paas-ce/lesscode/lib/client/src/views/project/data-source-manage/common/import.vue new file mode 100644 index 000000000..887ea1740 --- /dev/null +++ b/paas-ce/lesscode/lib/client/src/views/project/data-source-manage/common/import.vue @@ -0,0 +1,82 @@ + + + + + diff --git a/paas-ce/lesscode/lib/client/src/views/project/data-source-manage/common/info-table.vue b/paas-ce/lesscode/lib/client/src/views/project/data-source-manage/common/info-table.vue new file mode 100644 index 000000000..a96016deb --- /dev/null +++ b/paas-ce/lesscode/lib/client/src/views/project/data-source-manage/common/info-table.vue @@ -0,0 +1,171 @@ + + + + + diff --git a/paas-ce/lesscode/lib/client/src/views/project/data-source-manage/common/show-column-table.vue b/paas-ce/lesscode/lib/client/src/views/project/data-source-manage/common/show-column-table.vue new file mode 100644 index 000000000..79dcbff2a --- /dev/null +++ b/paas-ce/lesscode/lib/client/src/views/project/data-source-manage/common/show-column-table.vue @@ -0,0 +1,43 @@ + + + diff --git a/paas-ce/lesscode/lib/client/src/views/project/data-source-manage/data-manage/index.vue b/paas-ce/lesscode/lib/client/src/views/project/data-source-manage/data-manage/index.vue new file mode 100644 index 000000000..aa4a513d1 --- /dev/null +++ b/paas-ce/lesscode/lib/client/src/views/project/data-source-manage/data-manage/index.vue @@ -0,0 +1,266 @@ + + + + + diff --git a/paas-ce/lesscode/lib/client/src/views/project/data-source-manage/data-manage/render-api.vue b/paas-ce/lesscode/lib/client/src/views/project/data-source-manage/data-manage/render-api.vue new file mode 100644 index 000000000..d7c68f51e --- /dev/null +++ b/paas-ce/lesscode/lib/client/src/views/project/data-source-manage/data-manage/render-api.vue @@ -0,0 +1,233 @@ + + + + + diff --git a/paas-ce/lesscode/lib/client/src/views/project/data-source-manage/data-manage/render-data.vue b/paas-ce/lesscode/lib/client/src/views/project/data-source-manage/data-manage/render-data.vue new file mode 100644 index 000000000..2d3baa812 --- /dev/null +++ b/paas-ce/lesscode/lib/client/src/views/project/data-source-manage/data-manage/render-data.vue @@ -0,0 +1,416 @@ + + + + + diff --git a/paas-ce/lesscode/lib/client/src/views/project/data-source-manage/data-manage/render-function.vue b/paas-ce/lesscode/lib/client/src/views/project/data-source-manage/data-manage/render-function.vue new file mode 100644 index 000000000..bfedf71ec --- /dev/null +++ b/paas-ce/lesscode/lib/client/src/views/project/data-source-manage/data-manage/render-function.vue @@ -0,0 +1,247 @@ + + + + + diff --git a/paas-ce/lesscode/lib/client/src/views/project/data-source-manage/data-manage/render-struct.vue b/paas-ce/lesscode/lib/client/src/views/project/data-source-manage/data-manage/render-struct.vue new file mode 100644 index 000000000..38e60799a --- /dev/null +++ b/paas-ce/lesscode/lib/client/src/views/project/data-source-manage/data-manage/render-struct.vue @@ -0,0 +1,54 @@ + + + + + diff --git a/paas-ce/lesscode/lib/client/src/views/project/data-source-manage/index.vue b/paas-ce/lesscode/lib/client/src/views/project/data-source-manage/index.vue new file mode 100644 index 000000000..b1fcad3f9 --- /dev/null +++ b/paas-ce/lesscode/lib/client/src/views/project/data-source-manage/index.vue @@ -0,0 +1,8 @@ + + diff --git a/paas-ce/lesscode/lib/client/src/views/project/data-source-manage/table-design/composables/table-info.ts b/paas-ce/lesscode/lib/client/src/views/project/data-source-manage/table-design/composables/table-info.ts new file mode 100644 index 000000000..75a64aa69 --- /dev/null +++ b/paas-ce/lesscode/lib/client/src/views/project/data-source-manage/table-design/composables/table-info.ts @@ -0,0 +1,63 @@ +/** + * Tencent is pleased to support the open source community by making 蓝鲸智云PaaS平台社区版 (BlueKing PaaS Community Edition) available. + * Copyright (C) 2017-2018 THL A29 Limited, a Tencent company. All rights reserved. + * Licensed under the MIT License (the "License"); you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * http://opensource.org/licenses/MIT + * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on + * 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 { + reactive, + ref +} from '@vue/composition-api' + +export interface IBasicInfo { + tableName: string, + engine: string, + character: string, + comment: string +} + +export interface ITableField { + name?: string, + type: string, + generated?: boolean, + length?: number, + createDate?: boolean, + updateDate?: boolean, + default?: string | number, + comment?: string +} +export interface ITableStatus { + basicInfo: IBasicInfo, + data: ITableField[] +} + +/** + * 获取默认的 table 数据 + * @param status 传入初始化数据 + * @returns 返回表状态数据 + */ +export function useTableStatus (status = {}) { + const finalStatus = Object.assign({ + basicInfo: { + tableName: '', + engine: 'InnoDB', + character: 'utf8mb4', + comment: '' + }, + data: [] + }, status) + return { + tableStatus: reactive(finalStatus), + sql: ref(''), + isLoading: ref(false), + isSaving: ref(false), + hasEdit: ref(false), + showConfirmDialog: ref(false), + basicFormRef: ref(null), + fieldTableRef: ref(null) + } +} diff --git a/paas-ce/lesscode/lib/client/src/views/project/data-source-manage/table-design/create-table.vue b/paas-ce/lesscode/lib/client/src/views/project/data-source-manage/table-design/create-table.vue new file mode 100644 index 000000000..6ec36263b --- /dev/null +++ b/paas-ce/lesscode/lib/client/src/views/project/data-source-manage/table-design/create-table.vue @@ -0,0 +1,226 @@ + + + + + diff --git a/paas-ce/lesscode/lib/client/src/views/project/data-source-manage/table-design/edit-table.vue b/paas-ce/lesscode/lib/client/src/views/project/data-source-manage/table-design/edit-table.vue new file mode 100644 index 000000000..d1d29bf6d --- /dev/null +++ b/paas-ce/lesscode/lib/client/src/views/project/data-source-manage/table-design/edit-table.vue @@ -0,0 +1,244 @@ + + + + + diff --git a/paas-ce/lesscode/lib/client/src/views/project/data-source-manage/table-design/show-table.vue b/paas-ce/lesscode/lib/client/src/views/project/data-source-manage/table-design/show-table.vue new file mode 100644 index 000000000..7d2d7adef --- /dev/null +++ b/paas-ce/lesscode/lib/client/src/views/project/data-source-manage/table-design/show-table.vue @@ -0,0 +1,148 @@ + + + + + diff --git a/paas-ce/lesscode/lib/client/src/views/project/data-source-manage/table-design/table-list/index.vue b/paas-ce/lesscode/lib/client/src/views/project/data-source-manage/table-design/table-list/index.vue new file mode 100644 index 000000000..ab0adc1b7 --- /dev/null +++ b/paas-ce/lesscode/lib/client/src/views/project/data-source-manage/table-design/table-list/index.vue @@ -0,0 +1,42 @@ + + + diff --git a/paas-ce/lesscode/lib/client/src/views/project/data-source-manage/table-design/table-list/list/index.vue b/paas-ce/lesscode/lib/client/src/views/project/data-source-manage/table-design/table-list/list/index.vue new file mode 100644 index 000000000..fd1776a69 --- /dev/null +++ b/paas-ce/lesscode/lib/client/src/views/project/data-source-manage/table-design/table-list/list/index.vue @@ -0,0 +1,288 @@ + + + + + diff --git a/paas-ce/lesscode/lib/client/src/views/project/data-source-manage/table-design/update-record.vue b/paas-ce/lesscode/lib/client/src/views/project/data-source-manage/table-design/update-record.vue new file mode 100644 index 000000000..450f193ee --- /dev/null +++ b/paas-ce/lesscode/lib/client/src/views/project/data-source-manage/table-design/update-record.vue @@ -0,0 +1,148 @@ + + + + + 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 af029758b..926f724b5 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 @@ -210,6 +210,7 @@ ...mapGetters(['user']), ...mapGetters('functions', ['funcGroups']), ...mapGetters('member', ['userPerm']), + ...mapGetters('projectVersion', { versionId: 'currentVersionId', versionName: 'currentVersionName' }), projectId () { return parseInt(this.$route.params.projectId) }, @@ -317,7 +318,7 @@ if (!postData.projectId) { postData.projectId = this.projectId } - const varWhere = { projectId: this.projectId, effectiveRange: 0 } + const varWhere = { projectId: this.projectId, versionId: this.versionId, effectiveRange: 0 } const add = () => this.addFunc({ groupId: this.curGroupId, func: postData, varWhere }) const edit = () => this.editFunc({ groupId: this.curGroupId, func: postData, varWhere }) @@ -325,7 +326,7 @@ curMethod().then((res) => { if (!res) return const projectId = this.$route.params.projectId - return this.getAllGroupFuncs(projectId).then(() => { + return this.getAllGroupFuncs({ projectId, versionId: this.versionId }).then(() => { this.curGroupId = postData.funcGroupId this.closeAddFunction() this.$bkMessage({ theme: 'success', message: `${this.funcObj.title}成功` }) @@ -357,7 +358,11 @@ initData () { this.isLoadingGroup = true const projectId = this.$route.params.projectId - Promise.all([this.getAllGroupFuncs(projectId), this.getAllVariable({ projectId, effectiveRange: 0 })]).then(() => { + const versionId = this.versionId + Promise.all([ + this.getAllGroupFuncs({ projectId, versionId }), + this.getAllVariable({ projectId, versionId, effectiveRange: 0 }) + ]).then(() => { const firstGroup = this.funcGroups[0] || {} this.curGroupId = firstGroup.id }).finally(() => { @@ -430,7 +435,8 @@ const projectId = this.$route.params.projectId const postData = { inputStr: this.groupNameStr, - projectId + projectId, + versionId: this.versionId } this.addGroup(postData).then((res) => { this.groupNameStr = '' @@ -481,7 +487,8 @@ }, exportFunction () { - functionHelper.exportFunction(this.selectionData, `lesscode-${this.projectId}-func.json`) + const versionName = this.versionId ? `-${this.versionName}` : '' + functionHelper.exportFunction(this.selectionData, `lesscode-${this.projectId}${versionName}-func.json`) }, exportDemoFunction () { @@ -541,12 +548,12 @@ }, bulkAddFuncFromApi (funcList) { - const varWhere = { projectId: this.projectId, effectiveRange: 0 } + const varWhere = { projectId: this.projectId, versionId: this.versionId, effectiveRange: 0 } const postData = { groupId: this.curGroupId, funcList, varWhere } return this.bulkAddFunc(postData).then((res) => { if (!res) return const projectId = this.$route.params.projectId - return this.getAllGroupFuncs(projectId) + return this.getAllGroupFuncs({ projectId, versionId: this.versionId }) }) } } diff --git a/paas-ce/lesscode/lib/client/src/views/project/index.vue b/paas-ce/lesscode/lib/client/src/views/project/index.vue index 0053207aa..ec1561b91 100644 --- a/paas-ce/lesscode/lib/client/src/views/project/index.vue +++ b/paas-ce/lesscode/lib/client/src/views/project/index.vue @@ -26,18 +26,25 @@
- ' document.write(content) }) diff --git a/paas-ce/lesscode/lib/server/project-template/project-init-code/lib/client/static/lib.bundle.js b/paas-ce/lesscode/lib/server/project-template/project-init-code/lib/client/static/lib.bundle.js index 556fb2328..928c53e5d 100644 --- a/paas-ce/lesscode/lib/server/project-template/project-init-code/lib/client/static/lib.bundle.js +++ b/paas-ce/lesscode/lib/server/project-template/project-init-code/lib/client/static/lib.bundle.js @@ -1 +1,132 @@ -var lib_53739acf42e58eeed247=function(n){var e={};function t(r){if(e[r]){return e[r].exports}var a=e[r]={i:r,l:false,exports:{}};n[r].call(a.exports,a,a.exports,t);a.l=true;return a.exports}t.m=n;t.c=e;t.d=function(n,e,r){if(!t.o(n,e)){Object.defineProperty(n,e,{enumerable:true,get:r})}};t.r=function(n){if(typeof Symbol!=="undefined"&&Symbol.toStringTag){Object.defineProperty(n,Symbol.toStringTag,{value:"Module"})}Object.defineProperty(n,"__esModule",{value:true})};t.t=function(n,e){if(e&1)n=t(n);if(e&8)return n;if(e&4&&typeof n==="object"&&n&&n.__esModule)return n;var r=Object.create(null);t.r(r);Object.defineProperty(r,"default",{enumerable:true,value:n});if(e&2&&typeof n!="string")for(var a in n)t.d(r,a,function(e){return n[e]}.bind(null,a));return r};t.n=function(n){var e=n&&n.__esModule?function e(){return n["default"]}:function e(){return n};t.d(e,"a",e);return e};t.o=function(n,e){return Object.prototype.hasOwnProperty.call(n,e)};t.p="";return t(t.s=0)}({"./node_modules/axios/index.js":function(module,exports,__webpack_require__){eval('module.exports = __webpack_require__(/*! ./lib/axios */ "./node_modules/axios/lib/axios.js");\n\n//# sourceURL=webpack://%5Bname%5D_%5Bchunkhash%5D/./node_modules/axios/index.js?')},"./node_modules/axios/lib/adapters/xhr.js":function(module,exports,__webpack_require__){"use strict";eval("\n\nvar utils = __webpack_require__(/*! ./../utils */ \"./node_modules/axios/lib/utils.js\");\nvar settle = __webpack_require__(/*! ./../core/settle */ \"./node_modules/axios/lib/core/settle.js\");\nvar buildURL = __webpack_require__(/*! ./../helpers/buildURL */ \"./node_modules/axios/lib/helpers/buildURL.js\");\nvar buildFullPath = __webpack_require__(/*! ../core/buildFullPath */ \"./node_modules/axios/lib/core/buildFullPath.js\");\nvar parseHeaders = __webpack_require__(/*! ./../helpers/parseHeaders */ \"./node_modules/axios/lib/helpers/parseHeaders.js\");\nvar isURLSameOrigin = __webpack_require__(/*! ./../helpers/isURLSameOrigin */ \"./node_modules/axios/lib/helpers/isURLSameOrigin.js\");\nvar createError = __webpack_require__(/*! ../core/createError */ \"./node_modules/axios/lib/core/createError.js\");\n\nmodule.exports = function xhrAdapter(config) {\n return new Promise(function dispatchXhrRequest(resolve, reject) {\n var requestData = config.data;\n var requestHeaders = config.headers;\n\n if (utils.isFormData(requestData)) {\n delete requestHeaders['Content-Type']; // Let the browser set it\n }\n\n var request = new XMLHttpRequest();\n\n // HTTP basic authentication\n if (config.auth) {\n var username = config.auth.username || '';\n var password = config.auth.password || '';\n requestHeaders.Authorization = 'Basic ' + btoa(username + ':' + password);\n }\n\n var fullPath = buildFullPath(config.baseURL, config.url);\n request.open(config.method.toUpperCase(), buildURL(fullPath, config.params, config.paramsSerializer), true);\n\n // Set the request timeout in MS\n request.timeout = config.timeout;\n\n // Listen for ready state\n request.onreadystatechange = function handleLoad() {\n if (!request || request.readyState !== 4) {\n return;\n }\n\n // The request errored out and we didn't get a response, this will be\n // handled by onerror instead\n // With one exception: request that using file: protocol, most browsers\n // will return status as 0 even though it's a successful request\n if (request.status === 0 && !(request.responseURL && request.responseURL.indexOf('file:') === 0)) {\n return;\n }\n\n // Prepare the response\n var responseHeaders = 'getAllResponseHeaders' in request ? parseHeaders(request.getAllResponseHeaders()) : null;\n var responseData = !config.responseType || config.responseType === 'text' ? request.responseText : request.response;\n var response = {\n data: responseData,\n status: request.status,\n statusText: request.statusText,\n headers: responseHeaders,\n config: config,\n request: request\n };\n\n settle(resolve, reject, response);\n\n // Clean up request\n request = null;\n };\n\n // Handle browser request cancellation (as opposed to a manual cancellation)\n request.onabort = function handleAbort() {\n if (!request) {\n return;\n }\n\n reject(createError('Request aborted', config, 'ECONNABORTED', request));\n\n // Clean up request\n request = null;\n };\n\n // Handle low level network errors\n request.onerror = function handleError() {\n // Real errors are hidden from us by the browser\n // onerror should only fire if it's a network error\n reject(createError('Network Error', config, null, request));\n\n // Clean up request\n request = null;\n };\n\n // Handle timeout\n request.ontimeout = function handleTimeout() {\n var timeoutErrorMessage = 'timeout of ' + config.timeout + 'ms exceeded';\n if (config.timeoutErrorMessage) {\n timeoutErrorMessage = config.timeoutErrorMessage;\n }\n reject(createError(timeoutErrorMessage, config, 'ECONNABORTED',\n request));\n\n // Clean up request\n request = null;\n };\n\n // Add xsrf header\n // This is only done if running in a standard browser environment.\n // Specifically not if we're in a web worker, or react-native.\n if (utils.isStandardBrowserEnv()) {\n var cookies = __webpack_require__(/*! ./../helpers/cookies */ \"./node_modules/axios/lib/helpers/cookies.js\");\n\n // Add xsrf header\n var xsrfValue = (config.withCredentials || isURLSameOrigin(fullPath)) && config.xsrfCookieName ?\n cookies.read(config.xsrfCookieName) :\n undefined;\n\n if (xsrfValue) {\n requestHeaders[config.xsrfHeaderName] = xsrfValue;\n }\n }\n\n // Add headers to the request\n if ('setRequestHeader' in request) {\n utils.forEach(requestHeaders, function setRequestHeader(val, key) {\n if (typeof requestData === 'undefined' && key.toLowerCase() === 'content-type') {\n // Remove Content-Type if data is undefined\n delete requestHeaders[key];\n } else {\n // Otherwise add header to the request\n request.setRequestHeader(key, val);\n }\n });\n }\n\n // Add withCredentials to request if needed\n if (!utils.isUndefined(config.withCredentials)) {\n request.withCredentials = !!config.withCredentials;\n }\n\n // Add responseType to request if needed\n if (config.responseType) {\n try {\n request.responseType = config.responseType;\n } catch (e) {\n // Expected DOMException thrown by browsers not compatible XMLHttpRequest Level 2.\n // But, this can be suppressed for 'json' type as it can be parsed by default 'transformResponse' function.\n if (config.responseType !== 'json') {\n throw e;\n }\n }\n }\n\n // Handle progress if needed\n if (typeof config.onDownloadProgress === 'function') {\n request.addEventListener('progress', config.onDownloadProgress);\n }\n\n // Not all browsers support upload events\n if (typeof config.onUploadProgress === 'function' && request.upload) {\n request.upload.addEventListener('progress', config.onUploadProgress);\n }\n\n if (config.cancelToken) {\n // Handle cancellation\n config.cancelToken.promise.then(function onCanceled(cancel) {\n if (!request) {\n return;\n }\n\n request.abort();\n reject(cancel);\n // Clean up request\n request = null;\n });\n }\n\n if (requestData === undefined) {\n requestData = null;\n }\n\n // Send the request\n request.send(requestData);\n });\n};\n\n\n//# sourceURL=webpack://%5Bname%5D_%5Bchunkhash%5D/./node_modules/axios/lib/adapters/xhr.js?")},"./node_modules/axios/lib/axios.js":function(module,exports,__webpack_require__){"use strict";eval('\n\nvar utils = __webpack_require__(/*! ./utils */ "./node_modules/axios/lib/utils.js");\nvar bind = __webpack_require__(/*! ./helpers/bind */ "./node_modules/axios/lib/helpers/bind.js");\nvar Axios = __webpack_require__(/*! ./core/Axios */ "./node_modules/axios/lib/core/Axios.js");\nvar mergeConfig = __webpack_require__(/*! ./core/mergeConfig */ "./node_modules/axios/lib/core/mergeConfig.js");\nvar defaults = __webpack_require__(/*! ./defaults */ "./node_modules/axios/lib/defaults.js");\n\n/**\n * Create an instance of Axios\n *\n * @param {Object} defaultConfig The default config for the instance\n * @return {Axios} A new instance of Axios\n */\nfunction createInstance(defaultConfig) {\n var context = new Axios(defaultConfig);\n var instance = bind(Axios.prototype.request, context);\n\n // Copy axios.prototype to instance\n utils.extend(instance, Axios.prototype, context);\n\n // Copy context to instance\n utils.extend(instance, context);\n\n return instance;\n}\n\n// Create the default instance to be exported\nvar axios = createInstance(defaults);\n\n// Expose Axios class to allow class inheritance\naxios.Axios = Axios;\n\n// Factory for creating new instances\naxios.create = function create(instanceConfig) {\n return createInstance(mergeConfig(axios.defaults, instanceConfig));\n};\n\n// Expose Cancel & CancelToken\naxios.Cancel = __webpack_require__(/*! ./cancel/Cancel */ "./node_modules/axios/lib/cancel/Cancel.js");\naxios.CancelToken = __webpack_require__(/*! ./cancel/CancelToken */ "./node_modules/axios/lib/cancel/CancelToken.js");\naxios.isCancel = __webpack_require__(/*! ./cancel/isCancel */ "./node_modules/axios/lib/cancel/isCancel.js");\n\n// Expose all/spread\naxios.all = function all(promises) {\n return Promise.all(promises);\n};\naxios.spread = __webpack_require__(/*! ./helpers/spread */ "./node_modules/axios/lib/helpers/spread.js");\n\nmodule.exports = axios;\n\n// Allow use of default import syntax in TypeScript\nmodule.exports.default = axios;\n\n\n//# sourceURL=webpack://%5Bname%5D_%5Bchunkhash%5D/./node_modules/axios/lib/axios.js?')},"./node_modules/axios/lib/cancel/Cancel.js":function(module,exports,__webpack_require__){"use strict";eval("\n\n/**\n * A `Cancel` is an object that is thrown when an operation is canceled.\n *\n * @class\n * @param {string=} message The message.\n */\nfunction Cancel(message) {\n this.message = message;\n}\n\nCancel.prototype.toString = function toString() {\n return 'Cancel' + (this.message ? ': ' + this.message : '');\n};\n\nCancel.prototype.__CANCEL__ = true;\n\nmodule.exports = Cancel;\n\n\n//# sourceURL=webpack://%5Bname%5D_%5Bchunkhash%5D/./node_modules/axios/lib/cancel/Cancel.js?")},"./node_modules/axios/lib/cancel/CancelToken.js":function(module,exports,__webpack_require__){"use strict";eval("\n\nvar Cancel = __webpack_require__(/*! ./Cancel */ \"./node_modules/axios/lib/cancel/Cancel.js\");\n\n/**\n * A `CancelToken` is an object that can be used to request cancellation of an operation.\n *\n * @class\n * @param {Function} executor The executor function.\n */\nfunction CancelToken(executor) {\n if (typeof executor !== 'function') {\n throw new TypeError('executor must be a function.');\n }\n\n var resolvePromise;\n this.promise = new Promise(function promiseExecutor(resolve) {\n resolvePromise = resolve;\n });\n\n var token = this;\n executor(function cancel(message) {\n if (token.reason) {\n // Cancellation has already been requested\n return;\n }\n\n token.reason = new Cancel(message);\n resolvePromise(token.reason);\n });\n}\n\n/**\n * Throws a `Cancel` if cancellation has been requested.\n */\nCancelToken.prototype.throwIfRequested = function throwIfRequested() {\n if (this.reason) {\n throw this.reason;\n }\n};\n\n/**\n * Returns an object that contains a new `CancelToken` and a function that, when called,\n * cancels the `CancelToken`.\n */\nCancelToken.source = function source() {\n var cancel;\n var token = new CancelToken(function executor(c) {\n cancel = c;\n });\n return {\n token: token,\n cancel: cancel\n };\n};\n\nmodule.exports = CancelToken;\n\n\n//# sourceURL=webpack://%5Bname%5D_%5Bchunkhash%5D/./node_modules/axios/lib/cancel/CancelToken.js?")},"./node_modules/axios/lib/cancel/isCancel.js":function(module,exports,__webpack_require__){"use strict";eval("\n\nmodule.exports = function isCancel(value) {\n return !!(value && value.__CANCEL__);\n};\n\n\n//# sourceURL=webpack://%5Bname%5D_%5Bchunkhash%5D/./node_modules/axios/lib/cancel/isCancel.js?")},"./node_modules/axios/lib/core/Axios.js":function(module,exports,__webpack_require__){"use strict";eval("\n\nvar utils = __webpack_require__(/*! ./../utils */ \"./node_modules/axios/lib/utils.js\");\nvar buildURL = __webpack_require__(/*! ../helpers/buildURL */ \"./node_modules/axios/lib/helpers/buildURL.js\");\nvar InterceptorManager = __webpack_require__(/*! ./InterceptorManager */ \"./node_modules/axios/lib/core/InterceptorManager.js\");\nvar dispatchRequest = __webpack_require__(/*! ./dispatchRequest */ \"./node_modules/axios/lib/core/dispatchRequest.js\");\nvar mergeConfig = __webpack_require__(/*! ./mergeConfig */ \"./node_modules/axios/lib/core/mergeConfig.js\");\n\n/**\n * Create a new instance of Axios\n *\n * @param {Object} instanceConfig The default config for the instance\n */\nfunction Axios(instanceConfig) {\n this.defaults = instanceConfig;\n this.interceptors = {\n request: new InterceptorManager(),\n response: new InterceptorManager()\n };\n}\n\n/**\n * Dispatch a request\n *\n * @param {Object} config The config specific for this request (merged with this.defaults)\n */\nAxios.prototype.request = function request(config) {\n /*eslint no-param-reassign:0*/\n // Allow for axios('example/url'[, config]) a la fetch API\n if (typeof config === 'string') {\n config = arguments[1] || {};\n config.url = arguments[0];\n } else {\n config = config || {};\n }\n\n config = mergeConfig(this.defaults, config);\n\n // Set config.method\n if (config.method) {\n config.method = config.method.toLowerCase();\n } else if (this.defaults.method) {\n config.method = this.defaults.method.toLowerCase();\n } else {\n config.method = 'get';\n }\n\n // Hook up interceptors middleware\n var chain = [dispatchRequest, undefined];\n var promise = Promise.resolve(config);\n\n this.interceptors.request.forEach(function unshiftRequestInterceptors(interceptor) {\n chain.unshift(interceptor.fulfilled, interceptor.rejected);\n });\n\n this.interceptors.response.forEach(function pushResponseInterceptors(interceptor) {\n chain.push(interceptor.fulfilled, interceptor.rejected);\n });\n\n while (chain.length) {\n promise = promise.then(chain.shift(), chain.shift());\n }\n\n return promise;\n};\n\nAxios.prototype.getUri = function getUri(config) {\n config = mergeConfig(this.defaults, config);\n return buildURL(config.url, config.params, config.paramsSerializer).replace(/^\\?/, '');\n};\n\n// Provide aliases for supported request methods\nutils.forEach(['delete', 'get', 'head', 'options'], function forEachMethodNoData(method) {\n /*eslint func-names:0*/\n Axios.prototype[method] = function(url, config) {\n return this.request(utils.merge(config || {}, {\n method: method,\n url: url\n }));\n };\n});\n\nutils.forEach(['post', 'put', 'patch'], function forEachMethodWithData(method) {\n /*eslint func-names:0*/\n Axios.prototype[method] = function(url, data, config) {\n return this.request(utils.merge(config || {}, {\n method: method,\n url: url,\n data: data\n }));\n };\n});\n\nmodule.exports = Axios;\n\n\n//# sourceURL=webpack://%5Bname%5D_%5Bchunkhash%5D/./node_modules/axios/lib/core/Axios.js?")},"./node_modules/axios/lib/core/InterceptorManager.js":function(module,exports,__webpack_require__){"use strict";eval('\n\nvar utils = __webpack_require__(/*! ./../utils */ "./node_modules/axios/lib/utils.js");\n\nfunction InterceptorManager() {\n this.handlers = [];\n}\n\n/**\n * Add a new interceptor to the stack\n *\n * @param {Function} fulfilled The function to handle `then` for a `Promise`\n * @param {Function} rejected The function to handle `reject` for a `Promise`\n *\n * @return {Number} An ID used to remove interceptor later\n */\nInterceptorManager.prototype.use = function use(fulfilled, rejected) {\n this.handlers.push({\n fulfilled: fulfilled,\n rejected: rejected\n });\n return this.handlers.length - 1;\n};\n\n/**\n * Remove an interceptor from the stack\n *\n * @param {Number} id The ID that was returned by `use`\n */\nInterceptorManager.prototype.eject = function eject(id) {\n if (this.handlers[id]) {\n this.handlers[id] = null;\n }\n};\n\n/**\n * Iterate over all the registered interceptors\n *\n * This method is particularly useful for skipping over any\n * interceptors that may have become `null` calling `eject`.\n *\n * @param {Function} fn The function to call for each interceptor\n */\nInterceptorManager.prototype.forEach = function forEach(fn) {\n utils.forEach(this.handlers, function forEachHandler(h) {\n if (h !== null) {\n fn(h);\n }\n });\n};\n\nmodule.exports = InterceptorManager;\n\n\n//# sourceURL=webpack://%5Bname%5D_%5Bchunkhash%5D/./node_modules/axios/lib/core/InterceptorManager.js?')},"./node_modules/axios/lib/core/buildFullPath.js":function(module,exports,__webpack_require__){"use strict";eval('\n\nvar isAbsoluteURL = __webpack_require__(/*! ../helpers/isAbsoluteURL */ "./node_modules/axios/lib/helpers/isAbsoluteURL.js");\nvar combineURLs = __webpack_require__(/*! ../helpers/combineURLs */ "./node_modules/axios/lib/helpers/combineURLs.js");\n\n/**\n * Creates a new URL by combining the baseURL with the requestedURL,\n * only when the requestedURL is not already an absolute URL.\n * If the requestURL is absolute, this function returns the requestedURL untouched.\n *\n * @param {string} baseURL The base URL\n * @param {string} requestedURL Absolute or relative URL to combine\n * @returns {string} The combined full path\n */\nmodule.exports = function buildFullPath(baseURL, requestedURL) {\n if (baseURL && !isAbsoluteURL(requestedURL)) {\n return combineURLs(baseURL, requestedURL);\n }\n return requestedURL;\n};\n\n\n//# sourceURL=webpack://%5Bname%5D_%5Bchunkhash%5D/./node_modules/axios/lib/core/buildFullPath.js?')},"./node_modules/axios/lib/core/createError.js":function(module,exports,__webpack_require__){"use strict";eval("\n\nvar enhanceError = __webpack_require__(/*! ./enhanceError */ \"./node_modules/axios/lib/core/enhanceError.js\");\n\n/**\n * Create an Error with the specified message, config, error code, request and response.\n *\n * @param {string} message The error message.\n * @param {Object} config The config.\n * @param {string} [code] The error code (for example, 'ECONNABORTED').\n * @param {Object} [request] The request.\n * @param {Object} [response] The response.\n * @returns {Error} The created error.\n */\nmodule.exports = function createError(message, config, code, request, response) {\n var error = new Error(message);\n return enhanceError(error, config, code, request, response);\n};\n\n\n//# sourceURL=webpack://%5Bname%5D_%5Bchunkhash%5D/./node_modules/axios/lib/core/createError.js?")},"./node_modules/axios/lib/core/dispatchRequest.js":function(module,exports,__webpack_require__){"use strict";eval("\n\nvar utils = __webpack_require__(/*! ./../utils */ \"./node_modules/axios/lib/utils.js\");\nvar transformData = __webpack_require__(/*! ./transformData */ \"./node_modules/axios/lib/core/transformData.js\");\nvar isCancel = __webpack_require__(/*! ../cancel/isCancel */ \"./node_modules/axios/lib/cancel/isCancel.js\");\nvar defaults = __webpack_require__(/*! ../defaults */ \"./node_modules/axios/lib/defaults.js\");\n\n/**\n * Throws a `Cancel` if cancellation has been requested.\n */\nfunction throwIfCancellationRequested(config) {\n if (config.cancelToken) {\n config.cancelToken.throwIfRequested();\n }\n}\n\n/**\n * Dispatch a request to the server using the configured adapter.\n *\n * @param {object} config The config that is to be used for the request\n * @returns {Promise} The Promise to be fulfilled\n */\nmodule.exports = function dispatchRequest(config) {\n throwIfCancellationRequested(config);\n\n // Ensure headers exist\n config.headers = config.headers || {};\n\n // Transform request data\n config.data = transformData(\n config.data,\n config.headers,\n config.transformRequest\n );\n\n // Flatten headers\n config.headers = utils.merge(\n config.headers.common || {},\n config.headers[config.method] || {},\n config.headers\n );\n\n utils.forEach(\n ['delete', 'get', 'head', 'post', 'put', 'patch', 'common'],\n function cleanHeaderConfig(method) {\n delete config.headers[method];\n }\n );\n\n var adapter = config.adapter || defaults.adapter;\n\n return adapter(config).then(function onAdapterResolution(response) {\n throwIfCancellationRequested(config);\n\n // Transform response data\n response.data = transformData(\n response.data,\n response.headers,\n config.transformResponse\n );\n\n return response;\n }, function onAdapterRejection(reason) {\n if (!isCancel(reason)) {\n throwIfCancellationRequested(config);\n\n // Transform response data\n if (reason && reason.response) {\n reason.response.data = transformData(\n reason.response.data,\n reason.response.headers,\n config.transformResponse\n );\n }\n }\n\n return Promise.reject(reason);\n });\n};\n\n\n//# sourceURL=webpack://%5Bname%5D_%5Bchunkhash%5D/./node_modules/axios/lib/core/dispatchRequest.js?")},"./node_modules/axios/lib/core/enhanceError.js":function(module,exports,__webpack_require__){"use strict";eval("\n\n/**\n * Update an Error with the specified config, error code, and response.\n *\n * @param {Error} error The error to update.\n * @param {Object} config The config.\n * @param {string} [code] The error code (for example, 'ECONNABORTED').\n * @param {Object} [request] The request.\n * @param {Object} [response] The response.\n * @returns {Error} The error.\n */\nmodule.exports = function enhanceError(error, config, code, request, response) {\n error.config = config;\n if (code) {\n error.code = code;\n }\n\n error.request = request;\n error.response = response;\n error.isAxiosError = true;\n\n error.toJSON = function() {\n return {\n // Standard\n message: this.message,\n name: this.name,\n // Microsoft\n description: this.description,\n number: this.number,\n // Mozilla\n fileName: this.fileName,\n lineNumber: this.lineNumber,\n columnNumber: this.columnNumber,\n stack: this.stack,\n // Axios\n config: this.config,\n code: this.code\n };\n };\n return error;\n};\n\n\n//# sourceURL=webpack://%5Bname%5D_%5Bchunkhash%5D/./node_modules/axios/lib/core/enhanceError.js?")},"./node_modules/axios/lib/core/mergeConfig.js":function(module,exports,__webpack_require__){"use strict";eval("\n\nvar utils = __webpack_require__(/*! ../utils */ \"./node_modules/axios/lib/utils.js\");\n\n/**\n * Config-specific merge-function which creates a new config-object\n * by merging two configuration objects together.\n *\n * @param {Object} config1\n * @param {Object} config2\n * @returns {Object} New object resulting from merging config2 to config1\n */\nmodule.exports = function mergeConfig(config1, config2) {\n // eslint-disable-next-line no-param-reassign\n config2 = config2 || {};\n var config = {};\n\n var valueFromConfig2Keys = ['url', 'method', 'params', 'data'];\n var mergeDeepPropertiesKeys = ['headers', 'auth', 'proxy'];\n var defaultToConfig2Keys = [\n 'baseURL', 'url', 'transformRequest', 'transformResponse', 'paramsSerializer',\n 'timeout', 'withCredentials', 'adapter', 'responseType', 'xsrfCookieName',\n 'xsrfHeaderName', 'onUploadProgress', 'onDownloadProgress',\n 'maxContentLength', 'validateStatus', 'maxRedirects', 'httpAgent',\n 'httpsAgent', 'cancelToken', 'socketPath'\n ];\n\n utils.forEach(valueFromConfig2Keys, function valueFromConfig2(prop) {\n if (typeof config2[prop] !== 'undefined') {\n config[prop] = config2[prop];\n }\n });\n\n utils.forEach(mergeDeepPropertiesKeys, function mergeDeepProperties(prop) {\n if (utils.isObject(config2[prop])) {\n config[prop] = utils.deepMerge(config1[prop], config2[prop]);\n } else if (typeof config2[prop] !== 'undefined') {\n config[prop] = config2[prop];\n } else if (utils.isObject(config1[prop])) {\n config[prop] = utils.deepMerge(config1[prop]);\n } else if (typeof config1[prop] !== 'undefined') {\n config[prop] = config1[prop];\n }\n });\n\n utils.forEach(defaultToConfig2Keys, function defaultToConfig2(prop) {\n if (typeof config2[prop] !== 'undefined') {\n config[prop] = config2[prop];\n } else if (typeof config1[prop] !== 'undefined') {\n config[prop] = config1[prop];\n }\n });\n\n var axiosKeys = valueFromConfig2Keys\n .concat(mergeDeepPropertiesKeys)\n .concat(defaultToConfig2Keys);\n\n var otherKeys = Object\n .keys(config2)\n .filter(function filterAxiosKeys(key) {\n return axiosKeys.indexOf(key) === -1;\n });\n\n utils.forEach(otherKeys, function otherKeysDefaultToConfig2(prop) {\n if (typeof config2[prop] !== 'undefined') {\n config[prop] = config2[prop];\n } else if (typeof config1[prop] !== 'undefined') {\n config[prop] = config1[prop];\n }\n });\n\n return config;\n};\n\n\n//# sourceURL=webpack://%5Bname%5D_%5Bchunkhash%5D/./node_modules/axios/lib/core/mergeConfig.js?")},"./node_modules/axios/lib/core/settle.js":function(module,exports,__webpack_require__){"use strict";eval("\n\nvar createError = __webpack_require__(/*! ./createError */ \"./node_modules/axios/lib/core/createError.js\");\n\n/**\n * Resolve or reject a Promise based on response status.\n *\n * @param {Function} resolve A function that resolves the promise.\n * @param {Function} reject A function that rejects the promise.\n * @param {object} response The response.\n */\nmodule.exports = function settle(resolve, reject, response) {\n var validateStatus = response.config.validateStatus;\n if (!validateStatus || validateStatus(response.status)) {\n resolve(response);\n } else {\n reject(createError(\n 'Request failed with status code ' + response.status,\n response.config,\n null,\n response.request,\n response\n ));\n }\n};\n\n\n//# sourceURL=webpack://%5Bname%5D_%5Bchunkhash%5D/./node_modules/axios/lib/core/settle.js?")},"./node_modules/axios/lib/core/transformData.js":function(module,exports,__webpack_require__){"use strict";eval('\n\nvar utils = __webpack_require__(/*! ./../utils */ "./node_modules/axios/lib/utils.js");\n\n/**\n * Transform the data for a request or a response\n *\n * @param {Object|String} data The data to be transformed\n * @param {Array} headers The headers for the request or response\n * @param {Array|Function} fns A single function or Array of functions\n * @returns {*} The resulting transformed data\n */\nmodule.exports = function transformData(data, headers, fns) {\n /*eslint no-param-reassign:0*/\n utils.forEach(fns, function transform(fn) {\n data = fn(data, headers);\n });\n\n return data;\n};\n\n\n//# sourceURL=webpack://%5Bname%5D_%5Bchunkhash%5D/./node_modules/axios/lib/core/transformData.js?')},"./node_modules/axios/lib/defaults.js":function(module,exports,__webpack_require__){"use strict";eval("/* WEBPACK VAR INJECTION */(function(process) {\n\nvar utils = __webpack_require__(/*! ./utils */ \"./node_modules/axios/lib/utils.js\");\nvar normalizeHeaderName = __webpack_require__(/*! ./helpers/normalizeHeaderName */ \"./node_modules/axios/lib/helpers/normalizeHeaderName.js\");\n\nvar DEFAULT_CONTENT_TYPE = {\n 'Content-Type': 'application/x-www-form-urlencoded'\n};\n\nfunction setContentTypeIfUnset(headers, value) {\n if (!utils.isUndefined(headers) && utils.isUndefined(headers['Content-Type'])) {\n headers['Content-Type'] = value;\n }\n}\n\nfunction getDefaultAdapter() {\n var adapter;\n if (typeof XMLHttpRequest !== 'undefined') {\n // For browsers use XHR adapter\n adapter = __webpack_require__(/*! ./adapters/xhr */ \"./node_modules/axios/lib/adapters/xhr.js\");\n } else if (typeof process !== 'undefined' && Object.prototype.toString.call(process) === '[object process]') {\n // For node use HTTP adapter\n adapter = __webpack_require__(/*! ./adapters/http */ \"./node_modules/axios/lib/adapters/xhr.js\");\n }\n return adapter;\n}\n\nvar defaults = {\n adapter: getDefaultAdapter(),\n\n transformRequest: [function transformRequest(data, headers) {\n normalizeHeaderName(headers, 'Accept');\n normalizeHeaderName(headers, 'Content-Type');\n if (utils.isFormData(data) ||\n utils.isArrayBuffer(data) ||\n utils.isBuffer(data) ||\n utils.isStream(data) ||\n utils.isFile(data) ||\n utils.isBlob(data)\n ) {\n return data;\n }\n if (utils.isArrayBufferView(data)) {\n return data.buffer;\n }\n if (utils.isURLSearchParams(data)) {\n setContentTypeIfUnset(headers, 'application/x-www-form-urlencoded;charset=utf-8');\n return data.toString();\n }\n if (utils.isObject(data)) {\n setContentTypeIfUnset(headers, 'application/json;charset=utf-8');\n return JSON.stringify(data);\n }\n return data;\n }],\n\n transformResponse: [function transformResponse(data) {\n /*eslint no-param-reassign:0*/\n if (typeof data === 'string') {\n try {\n data = JSON.parse(data);\n } catch (e) { /* Ignore */ }\n }\n return data;\n }],\n\n /**\n * A timeout in milliseconds to abort a request. If set to 0 (default) a\n * timeout is not created.\n */\n timeout: 0,\n\n xsrfCookieName: 'XSRF-TOKEN',\n xsrfHeaderName: 'X-XSRF-TOKEN',\n\n maxContentLength: -1,\n\n validateStatus: function validateStatus(status) {\n return status >= 200 && status < 300;\n }\n};\n\ndefaults.headers = {\n common: {\n 'Accept': 'application/json, text/plain, */*'\n }\n};\n\nutils.forEach(['delete', 'get', 'head'], function forEachMethodNoData(method) {\n defaults.headers[method] = {};\n});\n\nutils.forEach(['post', 'put', 'patch'], function forEachMethodWithData(method) {\n defaults.headers[method] = utils.merge(DEFAULT_CONTENT_TYPE);\n});\n\nmodule.exports = defaults;\n\n/* WEBPACK VAR INJECTION */}.call(this, __webpack_require__(/*! ./../../process/browser.js */ \"./node_modules/process/browser.js\")))\n\n//# sourceURL=webpack://%5Bname%5D_%5Bchunkhash%5D/./node_modules/axios/lib/defaults.js?")},"./node_modules/axios/lib/helpers/bind.js":function(module,exports,__webpack_require__){"use strict";eval("\n\nmodule.exports = function bind(fn, thisArg) {\n return function wrap() {\n var args = new Array(arguments.length);\n for (var i = 0; i < args.length; i++) {\n args[i] = arguments[i];\n }\n return fn.apply(thisArg, args);\n };\n};\n\n\n//# sourceURL=webpack://%5Bname%5D_%5Bchunkhash%5D/./node_modules/axios/lib/helpers/bind.js?")},"./node_modules/axios/lib/helpers/buildURL.js":function(module,exports,__webpack_require__){"use strict";eval("\n\nvar utils = __webpack_require__(/*! ./../utils */ \"./node_modules/axios/lib/utils.js\");\n\nfunction encode(val) {\n return encodeURIComponent(val).\n replace(/%40/gi, '@').\n replace(/%3A/gi, ':').\n replace(/%24/g, '$').\n replace(/%2C/gi, ',').\n replace(/%20/g, '+').\n replace(/%5B/gi, '[').\n replace(/%5D/gi, ']');\n}\n\n/**\n * Build a URL by appending params to the end\n *\n * @param {string} url The base of the url (e.g., http://www.google.com)\n * @param {object} [params] The params to be appended\n * @returns {string} The formatted url\n */\nmodule.exports = function buildURL(url, params, paramsSerializer) {\n /*eslint no-param-reassign:0*/\n if (!params) {\n return url;\n }\n\n var serializedParams;\n if (paramsSerializer) {\n serializedParams = paramsSerializer(params);\n } else if (utils.isURLSearchParams(params)) {\n serializedParams = params.toString();\n } else {\n var parts = [];\n\n utils.forEach(params, function serialize(val, key) {\n if (val === null || typeof val === 'undefined') {\n return;\n }\n\n if (utils.isArray(val)) {\n key = key + '[]';\n } else {\n val = [val];\n }\n\n utils.forEach(val, function parseValue(v) {\n if (utils.isDate(v)) {\n v = v.toISOString();\n } else if (utils.isObject(v)) {\n v = JSON.stringify(v);\n }\n parts.push(encode(key) + '=' + encode(v));\n });\n });\n\n serializedParams = parts.join('&');\n }\n\n if (serializedParams) {\n var hashmarkIndex = url.indexOf('#');\n if (hashmarkIndex !== -1) {\n url = url.slice(0, hashmarkIndex);\n }\n\n url += (url.indexOf('?') === -1 ? '?' : '&') + serializedParams;\n }\n\n return url;\n};\n\n\n//# sourceURL=webpack://%5Bname%5D_%5Bchunkhash%5D/./node_modules/axios/lib/helpers/buildURL.js?")},"./node_modules/axios/lib/helpers/combineURLs.js":function(module,exports,__webpack_require__){"use strict";eval("\n\n/**\n * Creates a new URL by combining the specified URLs\n *\n * @param {string} baseURL The base URL\n * @param {string} relativeURL The relative URL\n * @returns {string} The combined URL\n */\nmodule.exports = function combineURLs(baseURL, relativeURL) {\n return relativeURL\n ? baseURL.replace(/\\/+$/, '') + '/' + relativeURL.replace(/^\\/+/, '')\n : baseURL;\n};\n\n\n//# sourceURL=webpack://%5Bname%5D_%5Bchunkhash%5D/./node_modules/axios/lib/helpers/combineURLs.js?")},"./node_modules/axios/lib/helpers/cookies.js":function(module,exports,__webpack_require__){"use strict";eval("\n\nvar utils = __webpack_require__(/*! ./../utils */ \"./node_modules/axios/lib/utils.js\");\n\nmodule.exports = (\n utils.isStandardBrowserEnv() ?\n\n // Standard browser envs support document.cookie\n (function standardBrowserEnv() {\n return {\n write: function write(name, value, expires, path, domain, secure) {\n var cookie = [];\n cookie.push(name + '=' + encodeURIComponent(value));\n\n if (utils.isNumber(expires)) {\n cookie.push('expires=' + new Date(expires).toGMTString());\n }\n\n if (utils.isString(path)) {\n cookie.push('path=' + path);\n }\n\n if (utils.isString(domain)) {\n cookie.push('domain=' + domain);\n }\n\n if (secure === true) {\n cookie.push('secure');\n }\n\n document.cookie = cookie.join('; ');\n },\n\n read: function read(name) {\n var match = document.cookie.match(new RegExp('(^|;\\\\s*)(' + name + ')=([^;]*)'));\n return (match ? decodeURIComponent(match[3]) : null);\n },\n\n remove: function remove(name) {\n this.write(name, '', Date.now() - 86400000);\n }\n };\n })() :\n\n // Non standard browser env (web workers, react-native) lack needed support.\n (function nonStandardBrowserEnv() {\n return {\n write: function write() {},\n read: function read() { return null; },\n remove: function remove() {}\n };\n })()\n);\n\n\n//# sourceURL=webpack://%5Bname%5D_%5Bchunkhash%5D/./node_modules/axios/lib/helpers/cookies.js?")},"./node_modules/axios/lib/helpers/isAbsoluteURL.js":function(module,exports,__webpack_require__){"use strict";eval('\n\n/**\n * Determines whether the specified URL is absolute\n *\n * @param {string} url The URL to test\n * @returns {boolean} True if the specified URL is absolute, otherwise false\n */\nmodule.exports = function isAbsoluteURL(url) {\n // A URL is considered absolute if it begins with "://" or "//" (protocol-relative URL).\n // RFC 3986 defines scheme name as a sequence of characters beginning with a letter and followed\n // by any combination of letters, digits, plus, period, or hyphen.\n return /^([a-z][a-z\\d\\+\\-\\.]*:)?\\/\\//i.test(url);\n};\n\n\n//# sourceURL=webpack://%5Bname%5D_%5Bchunkhash%5D/./node_modules/axios/lib/helpers/isAbsoluteURL.js?')},"./node_modules/axios/lib/helpers/isURLSameOrigin.js":function(module,exports,__webpack_require__){"use strict";eval("\n\nvar utils = __webpack_require__(/*! ./../utils */ \"./node_modules/axios/lib/utils.js\");\n\nmodule.exports = (\n utils.isStandardBrowserEnv() ?\n\n // Standard browser envs have full support of the APIs needed to test\n // whether the request URL is of the same origin as current location.\n (function standardBrowserEnv() {\n var msie = /(msie|trident)/i.test(navigator.userAgent);\n var urlParsingNode = document.createElement('a');\n var originURL;\n\n /**\n * Parse a URL to discover it's components\n *\n * @param {String} url The URL to be parsed\n * @returns {Object}\n */\n function resolveURL(url) {\n var href = url;\n\n if (msie) {\n // IE needs attribute set twice to normalize properties\n urlParsingNode.setAttribute('href', href);\n href = urlParsingNode.href;\n }\n\n urlParsingNode.setAttribute('href', href);\n\n // urlParsingNode provides the UrlUtils interface - http://url.spec.whatwg.org/#urlutils\n return {\n href: urlParsingNode.href,\n protocol: urlParsingNode.protocol ? urlParsingNode.protocol.replace(/:$/, '') : '',\n host: urlParsingNode.host,\n search: urlParsingNode.search ? urlParsingNode.search.replace(/^\\?/, '') : '',\n hash: urlParsingNode.hash ? urlParsingNode.hash.replace(/^#/, '') : '',\n hostname: urlParsingNode.hostname,\n port: urlParsingNode.port,\n pathname: (urlParsingNode.pathname.charAt(0) === '/') ?\n urlParsingNode.pathname :\n '/' + urlParsingNode.pathname\n };\n }\n\n originURL = resolveURL(window.location.href);\n\n /**\n * Determine if a URL shares the same origin as the current location\n *\n * @param {String} requestURL The URL to test\n * @returns {boolean} True if URL shares the same origin, otherwise false\n */\n return function isURLSameOrigin(requestURL) {\n var parsed = (utils.isString(requestURL)) ? resolveURL(requestURL) : requestURL;\n return (parsed.protocol === originURL.protocol &&\n parsed.host === originURL.host);\n };\n })() :\n\n // Non standard browser envs (web workers, react-native) lack needed support.\n (function nonStandardBrowserEnv() {\n return function isURLSameOrigin() {\n return true;\n };\n })()\n);\n\n\n//# sourceURL=webpack://%5Bname%5D_%5Bchunkhash%5D/./node_modules/axios/lib/helpers/isURLSameOrigin.js?")},"./node_modules/axios/lib/helpers/normalizeHeaderName.js":function(module,exports,__webpack_require__){"use strict";eval('\n\nvar utils = __webpack_require__(/*! ../utils */ "./node_modules/axios/lib/utils.js");\n\nmodule.exports = function normalizeHeaderName(headers, normalizedName) {\n utils.forEach(headers, function processHeader(value, name) {\n if (name !== normalizedName && name.toUpperCase() === normalizedName.toUpperCase()) {\n headers[normalizedName] = value;\n delete headers[name];\n }\n });\n};\n\n\n//# sourceURL=webpack://%5Bname%5D_%5Bchunkhash%5D/./node_modules/axios/lib/helpers/normalizeHeaderName.js?')},"./node_modules/axios/lib/helpers/parseHeaders.js":function(module,exports,__webpack_require__){"use strict";eval("\n\nvar utils = __webpack_require__(/*! ./../utils */ \"./node_modules/axios/lib/utils.js\");\n\n// Headers whose duplicates are ignored by node\n// c.f. https://nodejs.org/api/http.html#http_message_headers\nvar ignoreDuplicateOf = [\n 'age', 'authorization', 'content-length', 'content-type', 'etag',\n 'expires', 'from', 'host', 'if-modified-since', 'if-unmodified-since',\n 'last-modified', 'location', 'max-forwards', 'proxy-authorization',\n 'referer', 'retry-after', 'user-agent'\n];\n\n/**\n * Parse headers into an object\n *\n * ```\n * Date: Wed, 27 Aug 2014 08:58:49 GMT\n * Content-Type: application/json\n * Connection: keep-alive\n * Transfer-Encoding: chunked\n * ```\n *\n * @param {String} headers Headers needing to be parsed\n * @returns {Object} Headers parsed into an object\n */\nmodule.exports = function parseHeaders(headers) {\n var parsed = {};\n var key;\n var val;\n var i;\n\n if (!headers) { return parsed; }\n\n utils.forEach(headers.split('\\n'), function parser(line) {\n i = line.indexOf(':');\n key = utils.trim(line.substr(0, i)).toLowerCase();\n val = utils.trim(line.substr(i + 1));\n\n if (key) {\n if (parsed[key] && ignoreDuplicateOf.indexOf(key) >= 0) {\n return;\n }\n if (key === 'set-cookie') {\n parsed[key] = (parsed[key] ? parsed[key] : []).concat([val]);\n } else {\n parsed[key] = parsed[key] ? parsed[key] + ', ' + val : val;\n }\n }\n });\n\n return parsed;\n};\n\n\n//# sourceURL=webpack://%5Bname%5D_%5Bchunkhash%5D/./node_modules/axios/lib/helpers/parseHeaders.js?")},"./node_modules/axios/lib/helpers/spread.js":function(module,exports,__webpack_require__){"use strict";eval("\n\n/**\n * Syntactic sugar for invoking a function and expanding an array for arguments.\n *\n * Common use case would be to use `Function.prototype.apply`.\n *\n * ```js\n * function f(x, y, z) {}\n * var args = [1, 2, 3];\n * f.apply(null, args);\n * ```\n *\n * With `spread` this example can be re-written.\n *\n * ```js\n * spread(function(x, y, z) {})([1, 2, 3]);\n * ```\n *\n * @param {Function} callback\n * @returns {Function}\n */\nmodule.exports = function spread(callback) {\n return function wrap(arr) {\n return callback.apply(null, arr);\n };\n};\n\n\n//# sourceURL=webpack://%5Bname%5D_%5Bchunkhash%5D/./node_modules/axios/lib/helpers/spread.js?")},"./node_modules/axios/lib/utils.js":function(module,exports,__webpack_require__){"use strict";eval("\n\nvar bind = __webpack_require__(/*! ./helpers/bind */ \"./node_modules/axios/lib/helpers/bind.js\");\n\n/*global toString:true*/\n\n// utils is a library of generic helper functions non-specific to axios\n\nvar toString = Object.prototype.toString;\n\n/**\n * Determine if a value is an Array\n *\n * @param {Object} val The value to test\n * @returns {boolean} True if value is an Array, otherwise false\n */\nfunction isArray(val) {\n return toString.call(val) === '[object Array]';\n}\n\n/**\n * Determine if a value is undefined\n *\n * @param {Object} val The value to test\n * @returns {boolean} True if the value is undefined, otherwise false\n */\nfunction isUndefined(val) {\n return typeof val === 'undefined';\n}\n\n/**\n * Determine if a value is a Buffer\n *\n * @param {Object} val The value to test\n * @returns {boolean} True if value is a Buffer, otherwise false\n */\nfunction isBuffer(val) {\n return val !== null && !isUndefined(val) && val.constructor !== null && !isUndefined(val.constructor)\n && typeof val.constructor.isBuffer === 'function' && val.constructor.isBuffer(val);\n}\n\n/**\n * Determine if a value is an ArrayBuffer\n *\n * @param {Object} val The value to test\n * @returns {boolean} True if value is an ArrayBuffer, otherwise false\n */\nfunction isArrayBuffer(val) {\n return toString.call(val) === '[object ArrayBuffer]';\n}\n\n/**\n * Determine if a value is a FormData\n *\n * @param {Object} val The value to test\n * @returns {boolean} True if value is an FormData, otherwise false\n */\nfunction isFormData(val) {\n return (typeof FormData !== 'undefined') && (val instanceof FormData);\n}\n\n/**\n * Determine if a value is a view on an ArrayBuffer\n *\n * @param {Object} val The value to test\n * @returns {boolean} True if value is a view on an ArrayBuffer, otherwise false\n */\nfunction isArrayBufferView(val) {\n var result;\n if ((typeof ArrayBuffer !== 'undefined') && (ArrayBuffer.isView)) {\n result = ArrayBuffer.isView(val);\n } else {\n result = (val) && (val.buffer) && (val.buffer instanceof ArrayBuffer);\n }\n return result;\n}\n\n/**\n * Determine if a value is a String\n *\n * @param {Object} val The value to test\n * @returns {boolean} True if value is a String, otherwise false\n */\nfunction isString(val) {\n return typeof val === 'string';\n}\n\n/**\n * Determine if a value is a Number\n *\n * @param {Object} val The value to test\n * @returns {boolean} True if value is a Number, otherwise false\n */\nfunction isNumber(val) {\n return typeof val === 'number';\n}\n\n/**\n * Determine if a value is an Object\n *\n * @param {Object} val The value to test\n * @returns {boolean} True if value is an Object, otherwise false\n */\nfunction isObject(val) {\n return val !== null && typeof val === 'object';\n}\n\n/**\n * Determine if a value is a Date\n *\n * @param {Object} val The value to test\n * @returns {boolean} True if value is a Date, otherwise false\n */\nfunction isDate(val) {\n return toString.call(val) === '[object Date]';\n}\n\n/**\n * Determine if a value is a File\n *\n * @param {Object} val The value to test\n * @returns {boolean} True if value is a File, otherwise false\n */\nfunction isFile(val) {\n return toString.call(val) === '[object File]';\n}\n\n/**\n * Determine if a value is a Blob\n *\n * @param {Object} val The value to test\n * @returns {boolean} True if value is a Blob, otherwise false\n */\nfunction isBlob(val) {\n return toString.call(val) === '[object Blob]';\n}\n\n/**\n * Determine if a value is a Function\n *\n * @param {Object} val The value to test\n * @returns {boolean} True if value is a Function, otherwise false\n */\nfunction isFunction(val) {\n return toString.call(val) === '[object Function]';\n}\n\n/**\n * Determine if a value is a Stream\n *\n * @param {Object} val The value to test\n * @returns {boolean} True if value is a Stream, otherwise false\n */\nfunction isStream(val) {\n return isObject(val) && isFunction(val.pipe);\n}\n\n/**\n * Determine if a value is a URLSearchParams object\n *\n * @param {Object} val The value to test\n * @returns {boolean} True if value is a URLSearchParams object, otherwise false\n */\nfunction isURLSearchParams(val) {\n return typeof URLSearchParams !== 'undefined' && val instanceof URLSearchParams;\n}\n\n/**\n * Trim excess whitespace off the beginning and end of a string\n *\n * @param {String} str The String to trim\n * @returns {String} The String freed of excess whitespace\n */\nfunction trim(str) {\n return str.replace(/^\\s*/, '').replace(/\\s*$/, '');\n}\n\n/**\n * Determine if we're running in a standard browser environment\n *\n * This allows axios to run in a web worker, and react-native.\n * Both environments support XMLHttpRequest, but not fully standard globals.\n *\n * web workers:\n * typeof window -> undefined\n * typeof document -> undefined\n *\n * react-native:\n * navigator.product -> 'ReactNative'\n * nativescript\n * navigator.product -> 'NativeScript' or 'NS'\n */\nfunction isStandardBrowserEnv() {\n if (typeof navigator !== 'undefined' && (navigator.product === 'ReactNative' ||\n navigator.product === 'NativeScript' ||\n navigator.product === 'NS')) {\n return false;\n }\n return (\n typeof window !== 'undefined' &&\n typeof document !== 'undefined'\n );\n}\n\n/**\n * Iterate over an Array or an Object invoking a function for each item.\n *\n * If `obj` is an Array callback will be called passing\n * the value, index, and complete array for each item.\n *\n * If 'obj' is an Object callback will be called passing\n * the value, key, and complete object for each property.\n *\n * @param {Object|Array} obj The object to iterate\n * @param {Function} fn The callback to invoke for each item\n */\nfunction forEach(obj, fn) {\n // Don't bother if no value provided\n if (obj === null || typeof obj === 'undefined') {\n return;\n }\n\n // Force an array if not already something iterable\n if (typeof obj !== 'object') {\n /*eslint no-param-reassign:0*/\n obj = [obj];\n }\n\n if (isArray(obj)) {\n // Iterate over array values\n for (var i = 0, l = obj.length; i < l; i++) {\n fn.call(null, obj[i], i, obj);\n }\n } else {\n // Iterate over object keys\n for (var key in obj) {\n if (Object.prototype.hasOwnProperty.call(obj, key)) {\n fn.call(null, obj[key], key, obj);\n }\n }\n }\n}\n\n/**\n * Accepts varargs expecting each argument to be an object, then\n * immutably merges the properties of each object and returns result.\n *\n * When multiple objects contain the same key the later object in\n * the arguments list will take precedence.\n *\n * Example:\n *\n * ```js\n * var result = merge({foo: 123}, {foo: 456});\n * console.log(result.foo); // outputs 456\n * ```\n *\n * @param {Object} obj1 Object to merge\n * @returns {Object} Result of all merge properties\n */\nfunction merge(/* obj1, obj2, obj3, ... */) {\n var result = {};\n function assignValue(val, key) {\n if (typeof result[key] === 'object' && typeof val === 'object') {\n result[key] = merge(result[key], val);\n } else {\n result[key] = val;\n }\n }\n\n for (var i = 0, l = arguments.length; i < l; i++) {\n forEach(arguments[i], assignValue);\n }\n return result;\n}\n\n/**\n * Function equal to merge with the difference being that no reference\n * to original objects is kept.\n *\n * @see merge\n * @param {Object} obj1 Object to merge\n * @returns {Object} Result of all merge properties\n */\nfunction deepMerge(/* obj1, obj2, obj3, ... */) {\n var result = {};\n function assignValue(val, key) {\n if (typeof result[key] === 'object' && typeof val === 'object') {\n result[key] = deepMerge(result[key], val);\n } else if (typeof val === 'object') {\n result[key] = deepMerge({}, val);\n } else {\n result[key] = val;\n }\n }\n\n for (var i = 0, l = arguments.length; i < l; i++) {\n forEach(arguments[i], assignValue);\n }\n return result;\n}\n\n/**\n * Extends object a by mutably adding to it the properties of object b.\n *\n * @param {Object} a The object to be extended\n * @param {Object} b The object to copy properties from\n * @param {Object} thisArg The object to bind function to\n * @return {Object} The resulting value of object a\n */\nfunction extend(a, b, thisArg) {\n forEach(b, function assignValue(val, key) {\n if (thisArg && typeof val === 'function') {\n a[key] = bind(val, thisArg);\n } else {\n a[key] = val;\n }\n });\n return a;\n}\n\nmodule.exports = {\n isArray: isArray,\n isArrayBuffer: isArrayBuffer,\n isBuffer: isBuffer,\n isFormData: isFormData,\n isArrayBufferView: isArrayBufferView,\n isString: isString,\n isNumber: isNumber,\n isObject: isObject,\n isUndefined: isUndefined,\n isDate: isDate,\n isFile: isFile,\n isBlob: isBlob,\n isFunction: isFunction,\n isStream: isStream,\n isURLSearchParams: isURLSearchParams,\n isStandardBrowserEnv: isStandardBrowserEnv,\n forEach: forEach,\n merge: merge,\n deepMerge: deepMerge,\n extend: extend,\n trim: trim\n};\n\n\n//# sourceURL=webpack://%5Bname%5D_%5Bchunkhash%5D/./node_modules/axios/lib/utils.js?")},"./node_modules/process/browser.js":function(module,exports){eval("// shim for using process in browser\nvar process = module.exports = {};\n\n// cached from whatever global is present so that test runners that stub it\n// don't break things. But we need to wrap it in a try catch in case it is\n// wrapped in strict mode code which doesn't define any globals. It's inside a\n// function because try/catches deoptimize in certain engines.\n\nvar cachedSetTimeout;\nvar cachedClearTimeout;\n\nfunction defaultSetTimout() {\n throw new Error('setTimeout has not been defined');\n}\nfunction defaultClearTimeout () {\n throw new Error('clearTimeout has not been defined');\n}\n(function () {\n try {\n if (typeof setTimeout === 'function') {\n cachedSetTimeout = setTimeout;\n } else {\n cachedSetTimeout = defaultSetTimout;\n }\n } catch (e) {\n cachedSetTimeout = defaultSetTimout;\n }\n try {\n if (typeof clearTimeout === 'function') {\n cachedClearTimeout = clearTimeout;\n } else {\n cachedClearTimeout = defaultClearTimeout;\n }\n } catch (e) {\n cachedClearTimeout = defaultClearTimeout;\n }\n} ())\nfunction runTimeout(fun) {\n if (cachedSetTimeout === setTimeout) {\n //normal enviroments in sane situations\n return setTimeout(fun, 0);\n }\n // if setTimeout wasn't available but was latter defined\n if ((cachedSetTimeout === defaultSetTimout || !cachedSetTimeout) && setTimeout) {\n cachedSetTimeout = setTimeout;\n return setTimeout(fun, 0);\n }\n try {\n // when when somebody has screwed with setTimeout but no I.E. maddness\n return cachedSetTimeout(fun, 0);\n } catch(e){\n try {\n // When we are in I.E. but the script has been evaled so I.E. doesn't trust the global object when called normally\n return cachedSetTimeout.call(null, fun, 0);\n } catch(e){\n // same as above but when it's a version of I.E. that must have the global object for 'this', hopfully our context correct otherwise it will throw a global error\n return cachedSetTimeout.call(this, fun, 0);\n }\n }\n\n\n}\nfunction runClearTimeout(marker) {\n if (cachedClearTimeout === clearTimeout) {\n //normal enviroments in sane situations\n return clearTimeout(marker);\n }\n // if clearTimeout wasn't available but was latter defined\n if ((cachedClearTimeout === defaultClearTimeout || !cachedClearTimeout) && clearTimeout) {\n cachedClearTimeout = clearTimeout;\n return clearTimeout(marker);\n }\n try {\n // when when somebody has screwed with setTimeout but no I.E. maddness\n return cachedClearTimeout(marker);\n } catch (e){\n try {\n // When we are in I.E. but the script has been evaled so I.E. doesn't trust the global object when called normally\n return cachedClearTimeout.call(null, marker);\n } catch (e){\n // same as above but when it's a version of I.E. that must have the global object for 'this', hopfully our context correct otherwise it will throw a global error.\n // Some versions of I.E. have different rules for clearTimeout vs setTimeout\n return cachedClearTimeout.call(this, marker);\n }\n }\n\n\n\n}\nvar queue = [];\nvar draining = false;\nvar currentQueue;\nvar queueIndex = -1;\n\nfunction cleanUpNextTick() {\n if (!draining || !currentQueue) {\n return;\n }\n draining = false;\n if (currentQueue.length) {\n queue = currentQueue.concat(queue);\n } else {\n queueIndex = -1;\n }\n if (queue.length) {\n drainQueue();\n }\n}\n\nfunction drainQueue() {\n if (draining) {\n return;\n }\n var timeout = runTimeout(cleanUpNextTick);\n draining = true;\n\n var len = queue.length;\n while(len) {\n currentQueue = queue;\n queue = [];\n while (++queueIndex < len) {\n if (currentQueue) {\n currentQueue[queueIndex].run();\n }\n }\n queueIndex = -1;\n len = queue.length;\n }\n currentQueue = null;\n draining = false;\n runClearTimeout(timeout);\n}\n\nprocess.nextTick = function (fun) {\n var args = new Array(arguments.length - 1);\n if (arguments.length > 1) {\n for (var i = 1; i < arguments.length; i++) {\n args[i - 1] = arguments[i];\n }\n }\n queue.push(new Item(fun, args));\n if (queue.length === 1 && !draining) {\n runTimeout(drainQueue);\n }\n};\n\n// v8 likes predictible objects\nfunction Item(fun, array) {\n this.fun = fun;\n this.array = array;\n}\nItem.prototype.run = function () {\n this.fun.apply(null, this.array);\n};\nprocess.title = 'browser';\nprocess.browser = true;\nprocess.env = {};\nprocess.argv = [];\nprocess.version = ''; // empty string to avoid regexp issues\nprocess.versions = {};\n\nfunction noop() {}\n\nprocess.on = noop;\nprocess.addListener = noop;\nprocess.once = noop;\nprocess.off = noop;\nprocess.removeListener = noop;\nprocess.removeAllListeners = noop;\nprocess.emit = noop;\nprocess.prependListener = noop;\nprocess.prependOnceListener = noop;\n\nprocess.listeners = function (name) { return [] }\n\nprocess.binding = function (name) {\n throw new Error('process.binding is not supported');\n};\n\nprocess.cwd = function () { return '/' };\nprocess.chdir = function (dir) {\n throw new Error('process.chdir is not supported');\n};\nprocess.umask = function() { return 0; };\n\n\n//# sourceURL=webpack://%5Bname%5D_%5Bchunkhash%5D/./node_modules/process/browser.js?")},"./node_modules/setimmediate/setImmediate.js":function(module,exports,__webpack_require__){eval('/* WEBPACK VAR INJECTION */(function(global, process) {(function (global, undefined) {\n "use strict";\n\n if (global.setImmediate) {\n return;\n }\n\n var nextHandle = 1; // Spec says greater than zero\n var tasksByHandle = {};\n var currentlyRunningATask = false;\n var doc = global.document;\n var registerImmediate;\n\n function setImmediate(callback) {\n // Callback can either be a function or a string\n if (typeof callback !== "function") {\n callback = new Function("" + callback);\n }\n // Copy function arguments\n var args = new Array(arguments.length - 1);\n for (var i = 0; i < args.length; i++) {\n args[i] = arguments[i + 1];\n }\n // Store and register the task\n var task = { callback: callback, args: args };\n tasksByHandle[nextHandle] = task;\n registerImmediate(nextHandle);\n return nextHandle++;\n }\n\n function clearImmediate(handle) {\n delete tasksByHandle[handle];\n }\n\n function run(task) {\n var callback = task.callback;\n var args = task.args;\n switch (args.length) {\n case 0:\n callback();\n break;\n case 1:\n callback(args[0]);\n break;\n case 2:\n callback(args[0], args[1]);\n break;\n case 3:\n callback(args[0], args[1], args[2]);\n break;\n default:\n callback.apply(undefined, args);\n break;\n }\n }\n\n function runIfPresent(handle) {\n // From the spec: "Wait until any invocations of this algorithm started before this one have completed."\n // So if we\'re currently running a task, we\'ll need to delay this invocation.\n if (currentlyRunningATask) {\n // Delay by doing a setTimeout. setImmediate was tried instead, but in Firefox 7 it generated a\n // "too much recursion" error.\n setTimeout(runIfPresent, 0, handle);\n } else {\n var task = tasksByHandle[handle];\n if (task) {\n currentlyRunningATask = true;\n try {\n run(task);\n } finally {\n clearImmediate(handle);\n currentlyRunningATask = false;\n }\n }\n }\n }\n\n function installNextTickImplementation() {\n registerImmediate = function(handle) {\n process.nextTick(function () { runIfPresent(handle); });\n };\n }\n\n function canUsePostMessage() {\n // The test against `importScripts` prevents this implementation from being installed inside a web worker,\n // where `global.postMessage` means something completely different and can\'t be used for this purpose.\n if (global.postMessage && !global.importScripts) {\n var postMessageIsAsynchronous = true;\n var oldOnMessage = global.onmessage;\n global.onmessage = function() {\n postMessageIsAsynchronous = false;\n };\n global.postMessage("", "*");\n global.onmessage = oldOnMessage;\n return postMessageIsAsynchronous;\n }\n }\n\n function installPostMessageImplementation() {\n // Installs an event handler on `global` for the `message` event: see\n // * https://developer.mozilla.org/en/DOM/window.postMessage\n // * http://www.whatwg.org/specs/web-apps/current-work/multipage/comms.html#crossDocumentMessages\n\n var messagePrefix = "setImmediate$" + Math.random() + "$";\n var onGlobalMessage = function(event) {\n if (event.source === global &&\n typeof event.data === "string" &&\n event.data.indexOf(messagePrefix) === 0) {\n runIfPresent(+event.data.slice(messagePrefix.length));\n }\n };\n\n if (global.addEventListener) {\n global.addEventListener("message", onGlobalMessage, false);\n } else {\n global.attachEvent("onmessage", onGlobalMessage);\n }\n\n registerImmediate = function(handle) {\n global.postMessage(messagePrefix + handle, "*");\n };\n }\n\n function installMessageChannelImplementation() {\n var channel = new MessageChannel();\n channel.port1.onmessage = function(event) {\n var handle = event.data;\n runIfPresent(handle);\n };\n\n registerImmediate = function(handle) {\n channel.port2.postMessage(handle);\n };\n }\n\n function installReadyStateChangeImplementation() {\n var html = doc.documentElement;\n registerImmediate = function(handle) {\n // Create a