commit 716a9e60b92135bc82137f26618e594deb005ad0 Author: mk <2403457699@qq.com> Date: Fri Jun 21 09:14:56 2024 +0800 init diff --git a/.editorconfig b/.editorconfig new file mode 100644 index 0000000..fd3eae8 --- /dev/null +++ b/.editorconfig @@ -0,0 +1,23 @@ +root = true + +[*] +charset = utf-8 +indent_style = space +end_of_line = lf +insert_final_newline = true +trim_trailing_whitespace = true + +[*.md] +trim_trailing_whitespace = false + +[*.js] +indent_size = 2 + +[*.vue] +indent_size = 2 + +[*.css] +indent_size = 2 + +[Makefile] +indent_style = tab diff --git a/.env.development b/.env.development new file mode 100644 index 0000000..a827138 --- /dev/null +++ b/.env.development @@ -0,0 +1,23 @@ +# just a flag +ENV='development' +port=3003 +# vue enviroment + +VUE_APP_ENVIRONMENT='development' +VUE_APP_CMS_INNER_BASE_URL='http://bipaas.elinkservice.cn/linkdata' +VUE_APP_BIPASS_API_SERVER='/linkdata/linkdata-gateway/route' +VUE_APP_CMS_BASE_URL='//store.linkkids.cn' +VUE_APP_OPTION_PAGE_URL='http://test.kiop.linkkids.cn/kiop-web/field/toRuleList.do' +VUE_APP_EXPORT_PAGE_URL='http://test.kiop.linkkids.cn/kiop-web/task/toTaskList.do' +VUE_APP_MINI_APP_URL='https://miniapi.linkkids.cn' +VUE_APP_BI_URL='http://49.234.48.41:3000' +VUE_APP_LAYOUT_URL='https://st.linkkids.cn' +VUE_APP_BI_DOMAIN='//linkdatatest.retailo2o.com' +VUE_APP_ST_DOMAIN='//st.retailo2o.com/p/h5-databi/' +VUE_APP_STORE_URL='//dev.retailo2o.com:3003' +VUE_APP_CSCS_URL='http://test.cscs.retailo2o.com' +VUE_APP_MINI_API_URL='//miniapi.retailo2o.com' +VUE_APP_LOWCODE_URL='//ams.retailo2o.com/api' +VUE_APP_LOWCODE_DESIGN='//ams.retailo2o.com/page-designer' +VUE_APP_LOWCODE_VIEWER='//ams.retailo2o.com/page-viewer' + \ No newline at end of file diff --git a/.env.production b/.env.production new file mode 100644 index 0000000..d1f78ba --- /dev/null +++ b/.env.production @@ -0,0 +1,24 @@ +# just a flag +ENV='production' +port=3003 +# vue enviroment + + +VUE_APP_ENVIRONMENT='development' +VUE_APP_CMS_INNER_BASE_URL='http://bipaas.elinkservice.cn/linkdata' +VUE_APP_CMS_BASE_URL='//store.linkkids.cn' +VUE_APP_BIPASS_API_SERVER = 'https://epmet-preview.elinkservice.cn/linkdata/linkdata-gateway/route' +VUE_APP_OPTION_PAGE_URL='http://test.kiop.linkkids.cn/kiop-web/field/toRuleList.do' +VUE_APP_EXPORT_PAGE_URL='http://test.kiop.linkkids.cn/kiop-web/task/toTaskList.do' +VUE_APP_MINI_APP_URL='https://miniapi.linkkids.cn' +VUE_APP_BI_URL='http://49.234.48.41:3000' +VUE_APP_LAYOUT_URL='https://st.linkkids.cn' +VUE_APP_BI_DOMAIN='//linkdatatest.retailo2o.com' +VUE_APP_ST_DOMAIN='//st.retailo2o.com/p/h5-databi/' +VUE_APP_STORE_URL='//dev.retailo2o.com:3003' +VUE_APP_CSCS_URL='http://test.cscs.retailo2o.com' +VUE_APP_MINI_API_URL='//miniapi.retailo2o.com' +VUE_APP_LOWCODE_URL='//ams.retailo2o.com/api' +VUE_APP_LOWCODE_DESIGN='//ams.retailo2o.com/page-designer' +VUE_APP_LOWCODE_VIEWER='//ams.retailo2o.com/page-viewer' + \ No newline at end of file diff --git a/.eslintignore b/.eslintignore new file mode 100644 index 0000000..e6529fc --- /dev/null +++ b/.eslintignore @@ -0,0 +1,4 @@ +build/*.js +src/assets +public +dist diff --git a/.eslintrc.js b/.eslintrc.js new file mode 100644 index 0000000..f7e9e91 --- /dev/null +++ b/.eslintrc.js @@ -0,0 +1,8 @@ +module.exports = { + root: true, + extends: [], + + // add your custom rules here + // it is base on https://github.com/vuejs/eslint-config-vue + rules: {}, +} diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..be2851a --- /dev/null +++ b/.gitignore @@ -0,0 +1,18 @@ +.DS_Store +node_modules/ +dist +dist* +npm-debug.log* +yarn-debug.log* +yarn-error.log* +package-lock.json +tests/**/coverage/ +.env.*.local +# Editor directories and files +.idea +.history +.vscode +*.suo +*.ntvs* +*.njsproj +*.sln diff --git a/.npmrc b/.npmrc new file mode 100644 index 0000000..4746105 --- /dev/null +++ b/.npmrc @@ -0,0 +1,2 @@ +sass_binary_site=https://npm.taobao.org/mirrors/node-sass/ +registry=http://npmneibu.linkkids.cn/ diff --git a/.travis.yml b/.travis.yml new file mode 100644 index 0000000..f4be7a0 --- /dev/null +++ b/.travis.yml @@ -0,0 +1,5 @@ +language: node_js +node_js: 10 +script: npm run test +notifications: + email: false diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000..6151575 --- /dev/null +++ b/LICENSE @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) 2017-present PanJiaChen + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/README.md b/README.md new file mode 100644 index 0000000..674af97 --- /dev/null +++ b/README.md @@ -0,0 +1,51 @@ +# vue-admin-template + +## 功能点 +- 集成了友盟的上报js +- 请求axios集成了上报功能 + +## 构建 + +```bash +# 克隆项目 +git clone http://code.linkkids.cn/fe_web_public/vue-admin-template.git + +# 进入项目目录 +cd vue-admin-template + +# 安装依赖 +npm install + +npm install --registry=http://npmneibu.linkkids.cn + +# 启动服务 +npm run dev +``` + +浏览器访问 [http://localhost:9528](http://localhost:9528) + +## 发布 + +```bash +# 构建测试环境 +npm run build:stage + +# 构建生产环境 +npm run build:prod +``` + +## 其它 + +```bash +# 预览发布环境效果 +npm run preview + +# 预览发布环境效果 + 静态资源分析 +npm run preview -- --report + +# 代码格式检查 +npm run lint + +# 代码格式检查并自动修复 +npm run lint -- --fix +``` diff --git a/babel.config.js b/babel.config.js new file mode 100644 index 0000000..5dc5c4a --- /dev/null +++ b/babel.config.js @@ -0,0 +1,24 @@ +const prodPlugins = [] +if (process.env.VUE_APP_CONSOLE_CLOSE === 'true') { + prodPlugins.push('transform-remove-console') +} +module.exports = { + presets: [ + [ + // https://github.com/vuejs/vue-cli/tree/master/packages/@vue/babel-preset-app + '@vue/cli-plugin-babel/preset', + { + useBuiltIns: 'usage', + corejs: '3.5', + }, + ], + ], + env: { + development: { + // babel-plugin-dynamic-import-node plugin only does one thing by converting all import() to require(). + // This plugin can significantly increase the speed of hot updates, when you have a large number of pages. + // https://panjiachen.github.io/vue-element-admin-site/guide/advanced/lazy-loading.html + plugins: ['dynamic-import-node', ...prodPlugins], + }, + }, +} diff --git a/build-hzw.sh b/build-hzw.sh new file mode 100644 index 0000000..baeeec6 --- /dev/null +++ b/build-hzw.sh @@ -0,0 +1,14 @@ +#!/bin/bash +NODE_HOME=/opt/nodejs/v11.6.1 +export PATH=$NODE_HOME/bin:$PATH +export NODE_PATH=$NODE_HOME/lib/node_modules +node -v +npm -v +ls -al +npm set registry http://npmneibu.linkkids.cn +npm install +if [ "$SER_ENV" == "IDC" ]; then + npm run build:hzw +else + npm run build:hzw-stage +fi diff --git a/build.sh b/build.sh new file mode 100644 index 0000000..f1d13b3 --- /dev/null +++ b/build.sh @@ -0,0 +1,14 @@ +#!/bin/bash +NODE_HOME=/opt/nodejs/v12.22.12 +export PATH=$NODE_HOME/bin:$PATH +export NODE_PATH=$NODE_HOME/lib/node_modules +node -v +npm -v +ls -al +npm set registry http://npmneibu.linkkids.cn +npm install +if [ "$ENV" == "prod" ]; then + npm run build:prod +else + npm run build:stage +fi diff --git a/build/index.js b/build/index.js new file mode 100644 index 0000000..0c57de2 --- /dev/null +++ b/build/index.js @@ -0,0 +1,35 @@ +const { run } = require('runjs') +const chalk = require('chalk') +const config = require('../vue.config.js') +const rawArgv = process.argv.slice(2) +const args = rawArgv.join(' ') + +if (process.env.npm_config_preview || rawArgv.includes('--preview')) { + const report = rawArgv.includes('--report') + + run(`vue-cli-service build ${args}`) + + const port = 9526 + const publicPath = config.publicPath + + var connect = require('connect') + var serveStatic = require('serve-static') + const app = connect() + + app.use( + publicPath, + serveStatic('./dist', { + index: ['index.html', '/'] + }) + ) + + app.listen(port, function () { + console.log(chalk.green(`> Preview at http://localhost:${port}${publicPath}`)) + if (report) { + console.log(chalk.green(`> Report at http://localhost:${port}${publicPath}report.html`)) + } + + }) +} else { + run(`vue-cli-service build ${args}`) +} diff --git a/jest.config.js b/jest.config.js new file mode 100644 index 0000000..4fa328a --- /dev/null +++ b/jest.config.js @@ -0,0 +1,23 @@ +module.exports = { + moduleFileExtensions: ['js', 'jsx', 'json', 'vue'], + transform: { + '^.+\\.vue$': 'vue-jest', + '.+\\.(css|styl|less|sass|scss|svg|png|jpg|ttf|woff|woff2)$': 'jest-transform-stub', + '^.+\\.jsx?$': 'babel-jest', + }, + moduleNameMapper: { + '^@/(.*)$': '/src/$1', + }, + snapshotSerializers: ['jest-serializer-vue'], + testMatch: ['**/tests/unit/**/*.spec.(js|jsx|ts|tsx)|**/__tests__/*.(js|jsx|ts|tsx)'], + collectCoverageFrom: [ + 'src/utils/**/*.{js,vue}', + '!src/utils/auth.js', + '!src/utils/request.js', + 'src/components/**/*.{js,vue}', + ], + coverageDirectory: '/tests/unit/coverage', + // 'collectCoverage': true, + coverageReporters: ['lcov', 'text-summary'], + testURL: 'http://localhost/', +} diff --git a/jsconfig.json b/jsconfig.json new file mode 100644 index 0000000..ed079e2 --- /dev/null +++ b/jsconfig.json @@ -0,0 +1,9 @@ +{ + "compilerOptions": { + "baseUrl": "./", + "paths": { + "@/*": ["src/*"] + } + }, + "exclude": ["node_modules", "dist"] +} diff --git a/package.json b/package.json new file mode 100644 index 0000000..34efa44 --- /dev/null +++ b/package.json @@ -0,0 +1,102 @@ +{ + "name": "data-bi", + "version": "1.0.0", + "description": "A project named template-manage", + "scripts": { + "dev": "vue-cli-service serve", + "build": "vue-cli-service build", + "build:prod": "vue-cli-service build", + "build:test": "vue-cli-service build --mode development", + "build:stage": "vue-cli-service build --mode staging", + "build:drtest": "vue-cli-service build --mode drtest", + "build:drprod": "vue-cli-service build --mode drprod", + "build:hzw": "vue-cli-service build --mode hzw", + "build:tm": "vue-cli-service build --mode tm", + "build:bx": "vue-cli-service build --mode bx", + "build:yl": "vue-cli-service build --mode yl", + "preview": "node build/index.js --preview", + "svgo": "svgo -f src/icons/svg --config=src/icons/svgo.yml", + "lint": "vue-cli-service lint", + "test:unit": "jest --clearCache && vue-cli-service test:unit", + "test:ci": "npm run lint && npm run test:unit", + "deploy:linkkids": "scp dist/index.html linkkids@10.250.14.5:/data/web/pc/linkbi && scp -r dist/* linkkids@10.250.14.5:/data/static/pc/linkbi/", + "deploy:elinkservice": "scp dist/index.html bizcent@10.254.0.144:/data/web/pc/linkbi && scp -r dist/* bizcent@10.254.0.144:/data/static/pc/linkbi/", + "deploylc:elinkservice": "scp dist/index.html bizcent@10.254.0.144:/data/web/pc/linkbi && scp -r dist/* bizcent@10.254.0.144:/data/static/pc/linkbi", + "deploy:bx": "scp -r dist/* root@10.0.2.13:/data/web/linkbi", + "deploy": "npm run deploy:linkkids && npm run deploy:elinkservice" + }, + "dependencies": { + "@sweetjs/link-style": "1.0.0-beta.3", + "@sweetjs/post-message-tool": "^1.0.4", + "@sweetjs/request": "2.0.9", + "@formily/core": "2.0.11", + "@formily/element": "2.0.11", + "@formily/vue": "2.0.11", + "@riophae/vue-treeselect": "^0.4.0", + "@vue/composition-api": "^1.4.6", + "axios": "^0.19.0", + "babel-plugin-transform-remove-console": "^6.9.4", + "clipboard": "^2.0.10", + "codemirror": "^5.63.3", + "core-js": "^3.37.1", + "crypto-js": "^4.1.1", + "dai-js": "^0.0.12", + "dayjs": "^1.11.3", + "echarts": "^5.4.1", + "element-theme-chalk": "^2.14.1", + "element-ui": "2.15.6", + "file-saver": "^2.0.5", + "js-cookie": "2.2.0", + "lodash-es": "^4.17.21", + "nanoid": "^4.0.0", + "normalize.css": "7.0.0", + "nprogress": "0.2.0", + "path-to-regexp": "2.4.0", + "relation-graph": "^2.0.24", + "uuid": "^8.3.2", + "v-jsoneditor": "^1.4.4", + "vue": "2.6.13", + "vue-router": "^3.5.3", + "vuedraggable": "^2.24.3", + "vuex": "3.1.0", + "vxe-table": "^2.10.22", + "xe-utils": "3.1.11" + }, + "devDependencies": { + "@vue/cli-plugin-babel": "4.4.4", + "@vue/cli-plugin-eslint": "4.4.4", + "@vue/cli-plugin-unit-jest": "4.4.4", + "@vue/cli-service": "4.4.4", + "@vue/test-utils": "1.0.0-beta.29", + "autoprefixer": "9.5.1", + "babel-eslint": "10.1.0", + "babel-jest": "23.6.0", + "babel-plugin-dynamic-import-node": "2.3.3", + "chalk": "2.4.2", + "connect": "3.6.6", + "eslint": "^7.22.0", + "eslint-plugin-import": "^2.22.1", + "eslint-plugin-prettier": "^3.3.1", + "eslint-plugin-vue": "^7.7.0", + "html-webpack-plugin": "3.2.0", + "mockjs": "1.0.1-beta3", + "prettier": "^2.2.1", + "runjs": "4.3.2", + "sass": "^1.52.1", + "sass-loader": "8.0.2", + "script-ext-html-webpack-plugin": "2.1.3", + "serve-static": "1.13.2", + "svg-sprite-loader": "4.1.3", + "svgo": "1.2.2", + "vue-template-compiler": "2.6.13" + }, + "browserslist": [ + "> 1%", + "last 2 versions" + ], + "engines": { + "node": ">=8.9", + "npm": ">= 3.0.0" + }, + "license": "MIT" +} diff --git a/postcss.config.js b/postcss.config.js new file mode 100644 index 0000000..2404286 --- /dev/null +++ b/postcss.config.js @@ -0,0 +1,8 @@ +// https://github.com/michael-ciniawsky/postcss-load-config + +module.exports = { + plugins: { + // to edit target browsers: use "browserslist" field in package.json + autoprefixer: {}, + }, +} diff --git a/public/css/lowcode-mobile.css b/public/css/lowcode-mobile.css new file mode 100644 index 0000000..ae187cf --- /dev/null +++ b/public/css/lowcode-mobile.css @@ -0,0 +1,45 @@ +body, +html { + height: 100%; + margin: 0; + padding: 0; +} +body { + background: #f0f4f7; +} +.page-root { + height: 100%; + display: flex; + flex-direction: column; +} +.page-root > [class^="page-node-"] { + margin: 5px 10px; +} + +.page-node-form-filter, +.page-node-table { + background: #fff; + border-radius: 4px; + padding: 3px 6px; + margin: 6px; + box-shadow: 0 0 6px 0 #dfdfdf; +} +.page-node-table { + flex: 1; + overflow: hidden; +} +:root { + --el-color-primary: #3862fe; + --el-color-danger: #f56c6c; + --el-color-danger-light-3: #ff3a00; + --el-color-success: #36850f; + --el-text-color-primary: #121212; + --el-text-color-regular: #121212; + --el-font-size-base: 12px; + --grid-item-content-border-radius:18px; +} +.el-button--primary.is-link, +.el-button--primary.is-plain, +.el-button--primary.is-text { + --el-button-text-color: #274ffb; +} diff --git a/public/css/lowcode.css b/public/css/lowcode.css new file mode 100644 index 0000000..42959dd --- /dev/null +++ b/public/css/lowcode.css @@ -0,0 +1,21 @@ +body,html{height:100%; margin:0;padding:0} +body{background:#f0f2f5} +.page-root{height:100%;display:flex;flex-direction:column} +.page-node-form-filter,.page-node-table{background:#fff;border-radius:4px;padding:3px 6px;margin:6px;box-shadow:0 0 6px 0 #dfdfdf} +.page-node-table{flex:1;overflow:hidden} +:root{ + --el-color-primary:#3862FE; + --el-color-danger:#F56C6C; + --el-color-danger-light-3:#FF3A00; + --el-color-success:#36850F; + --el-text-color-primary:#121212; + --el-text-color-regular:#121212; + --el-font-size-base:12px; +} +.el-button--primary.is-link, .el-button--primary.is-plain, .el-button--primary.is-text{ + --el-button-text-color:#274FFB; +} +.el-button.el-button--small { + font-size: 12px; + padding: 5px 11px; +} diff --git a/public/index.html b/public/index.html new file mode 100644 index 0000000..81c22bb --- /dev/null +++ b/public/index.html @@ -0,0 +1,17 @@ + + + + + + + + <%= webpackConfig.name %> + + + +
+ + + diff --git a/public/js/drtest-url-map.json b/public/js/drtest-url-map.json new file mode 100644 index 0000000..9029529 --- /dev/null +++ b/public/js/drtest-url-map.json @@ -0,0 +1,3 @@ +{ + "cjy-backend.darryring.com/linkdata-gateway":"cjy-testlinkdata.darryring.com/linkdata-gateway" +} diff --git a/public/js/url-map.json b/public/js/url-map.json new file mode 100644 index 0000000..0db3279 --- /dev/null +++ b/public/js/url-map.json @@ -0,0 +1,3 @@ +{ + +} diff --git a/src/App.vue b/src/App.vue new file mode 100644 index 0000000..5eec2e0 --- /dev/null +++ b/src/App.vue @@ -0,0 +1,11 @@ + + + diff --git a/src/api/bi.js b/src/api/bi.js new file mode 100644 index 0000000..21d527d --- /dev/null +++ b/src/api/bi.js @@ -0,0 +1,3 @@ +// const host = process.env.NODE_ENV === 'production' ? '10.250.14.114' : 'dev.linkkids.cn/_dev_proxy' + +export const COMMON_API = `${process.env.VUE_APP_BI_DOMAIN}/${process.env.VUE_APP_LINKDATA_GATEWAY || 'linkdata-gateway'}/route` diff --git a/src/api/cms.js b/src/api/cms.js new file mode 100644 index 0000000..81def10 --- /dev/null +++ b/src/api/cms.js @@ -0,0 +1,227 @@ +/* + * @Descripttion: + * @version: + * @Author: 张齐 + * @Date: 2021-07-12 19:33:47 + * @LastEditors: 张齐 + * @LastEditTime: 2021-07-28 18:57:42 + */ +import request from '@/utils/request' + +/** + * 新增CMS + * @param {*} elmentObj + * + */ +const addCMS = (elmentObj, site = 100996) => { + const addJson = { + type: 'add', // add/copy/link,默认add + page: { + // 初始化页面信息,type为add时可修改所有,type为copy/link时page字段可不传,如果修改,只能初始化page下name,outputPath,validityEnd + name: elmentObj.name || '新增页面', // 页面名,大于2字符 + description: '描述', + category: elmentObj.category || 'activity', // 分类,channel/activity/config,默认channel + htmlPath: '', // 前端页面地址,原样返回,[siteId][pageId]需前台自行替换 + outputPath: elmentObj.outputPath || '', // 自定义路径,默认为'' 只能是字母、数字、/、-、_,且最后文件名不能为纯数字,开头结尾不能为/ + autoPublish: true, // 是否自动发布,页面内容会随时间变化的选true,默认false + validityStart: 0, // 开始时间,默认0,时间戳或字符串(返回到前台,后台无逻辑处理) + validityEnd: '2099/12/31 00:00:00', // 结束时间,时间戳或字符串,默认一个月后,超过结束时间页面不会自动发布 + isV: false, // 是否可视化页面,默认false + outputType: 'json', // 输出类型 json/jsonp/html,默认json + template: { + // 输出类型为html,且isV为false时手动配置模板,默认可不填 + engine: '', // 目前只支持hbs + source: '', // 模板文件,有值时tmpl不起作用 + tmpl: '', // 模板内容 + layout: '', // 模板layout + }, + dataSchema: elmentObj.dataSchema, // type为add且isV为false时可初始化dataSchema,可不填 + data: elmentObj.data, // type为add且isV为false时可初始化data,可不填 + }, + sourceSiteId: 0, // type为copy/link时许指定源页面siteId + sourcePageId: 0, // type为copy/link时许指定源页面pageId + source: 'cms', + platform: elmentObj.platform, // 如果没有指定租户,则是100100租户 + } + return request.post(`${process.env.VUE_APP_CMS_INNER_BASE_URL}/v4/api/third/pages/${site}`, addJson) +} +/** + * 添加CMS页面 + * @param {*} initData + */ +const addCMSPage = (initData) => { + return addCMS({ + platform: initData.platform || '100100', + dataSchema: initData.dataSchema, + data: initData.data, + name: initData.name, + outputPath: initData.outputPath, + category: 'config', + }) +} +/** + * 导入Data和Dataschame + */ +const importschema = (elmentObj, siteId, pageId, platfrom = '100100') => { + return request.post(`${process.env.VUE_APP_CMS_INNER_BASE_URL}/v4/api/third/pages/${siteId}/importschema`, { + dataSchema: elmentObj.dataSchema, + data: elmentObj.data, + source: 'cms', + platform: platfrom, + pageId, + }) +} +/** + * 更新基础数据 + * @param {*} elmentObj + * @param {*} siteId + * @param {*} pageId + */ +const updateBaseInfo = (elmentObj, siteId, pageId, platform = '100100') => { + elmentObj.autoPublish = true + elmentObj.validityEnd = '2099/12/31 00:00:00' + return request.put(`${process.env.VUE_APP_CMS_INNER_BASE_URL}/v4/api/third/pages/${siteId}/baseinfo`, { + page: elmentObj, + source: 'cms', + platform, + pageId, + }) +} +/** + * 更新CMS + * @param {*} elmentObj + * @param {*} sitId + * @param {*} pageId + */ +const updateCMS = async (elmentObj, sitId, pageId, pageDes, platform = '100100') => { + // 如果有页面描述,此字段作为记录页面冗余字段携带 + if (pageDes) { + elmentObj.data.description.data = [{ value: JSON.stringify(pageDes) }] + } + const { code: inportCode } = await importschema(elmentObj, sitId, pageId, platform) + const { code: baseUpdateCode } = await updateBaseInfo(elmentObj, sitId, pageId, platform) + const importFlag = inportCode === 0 + const baseUpdateFlag = baseUpdateCode === 0 + return importFlag && baseUpdateFlag +} +/** + * 发布页面 + */ +const publishCMS = (siteId, pageId, platform = '100100') => { + return request.post(`${process.env.VUE_APP_CMS_INNER_BASE_URL}/v4/api/third/pages/${siteId}/publish`, { + source: 'cms', + platform, + pageId, + }) +} +/** + * 添加模板页面 + */ +const addCMSPage4Tem = async (name = '', outputPath = '') => { + const dataSchema = [ + { + name: 'config', + description: 'config', + tips: '', + dataType: 'input', + typeName: '文本', + meta: null, + api: null, + uuid: '74089936-252f-42cf-a640-0abff3c527dd', + index: '0', + count: 1, + path: ['config'], + key: 'config', + lock: false, + fieldsInfo: { + returnType: 2, + fieldType: 2, + fields: [{ type: 'input', name: '', desc: '', defaultValue: '' }], + }, + }, + ] + const data = { + config: { + data: [ + { + value: '', + }, + ], + dataType: 'input', + }, + } + return addCMSPage({ dataSchema, data, name, outputPath }) +} + +/** + * 服务端增加模板数据--增加 + */ +const addCMSPage4TemService = (params) => { + return request.post(`${process.env.VUE_APP_CMS_BASE_URL}/template/templateAdd`, params) +} +/** + * 服务端模板数据--编辑 + */ +const updateCMSPage4TemService = (params) => { + return request.post(`${process.env.VUE_APP_CMS_BASE_URL}/template/templateEdit`, params) +} + +/** + * 根据 outputPath 获取pageId + * @param {*} outputPath + */ +const getPageId = (outputPath, siteId = '100996') => { + return request.get( + `${process.env.VUE_APP_CMS_INNER_BASE_URL}/v4/api/third/pages/${siteId}/pageid?outputPath=${outputPath}&source=cms&_platform_num=100100` + ) +} +/** + * 根据siteId,pageId获取CMS + * @param {*} siteId + * @param {*} pageId + */ +const getCMS = (siteId, pageId, platfrom = '100100') => { + return request.get( + `${process.env.VUE_APP_CMS_INNER_BASE_URL}/v4/api/third/pages/${siteId}?platform=${platfrom}&source=cms&pageId=${pageId}` + ) +} +/** + * 获取站点下页面列表 + * @param {*} siteId + */ +const getPages = (siteId, platfrom = 100100) => { + return request.get( + `${process.env.VUE_APP_CMS_INNER_BASE_URL}/v4/api/third/pages/${siteId}/list?platform=${platfrom}&source=cms` + ) +} +// 获取模板数据 +const getTemsInfo = () => { + return request.get( + `${process.env.VUE_APP_MINI_APP_URL}/common/cms/publish/999/lowcode_templates.json?_platform_num=100100`, + { + withCredentials: false, + } + ) +} +const getDynamicTabList = () => { + return request.get( + `${process.env.VUE_APP_MINI_API_URL}/common/cms/publish/999/dynamic-tab.json?_platform_num=100100`, + { + withCredentials: false, + } + ) +} +export default { + addCMSPage, // 添加页面 + addCMSPage4Tem, // 添加模板页面 + updateBaseInfo, // 更新基础信息 + updateCMS, // 更新cms + publishCMS, // 发布cms + getCMS, // 根据siteId,pageId获取CMS + getPageId, // 根据 outputPath 获取pageId + getPages, // 获取站点下页面列表 + addCMSPage4TemService, // 服务端增加模板数据 + updateCMSPage4TemService, // 服务端模板数据--编辑 + getTemsInfo, // 获取模板数据 + getDynamicTabList, // 获取CMS动态Tab栏配置信息 +} diff --git a/src/api/demo.js b/src/api/demo.js new file mode 100644 index 0000000..2a85cec --- /dev/null +++ b/src/api/demo.js @@ -0,0 +1 @@ +export const DEMO_MOCK = `//mockneibu.linkkids.cn/mock/10/api/list` diff --git a/src/api/lowcode.js b/src/api/lowcode.js new file mode 100644 index 0000000..168e366 --- /dev/null +++ b/src/api/lowcode.js @@ -0,0 +1,39 @@ +import request from '@/utils/request' + +export function create(id, name, templateName = 'bireport', outputPath = '') { + if (!outputPath) { + outputPath = `${templateName}-${id}` + } + return request.axios.post(`${process.env.VUE_APP_LOWCODE_URL}/page`, { + targetType: '4', + name, + terminal: 'Web', + outputPath, + path: 'none', + visibility: 0, + canGrayscale: false, + templateName, + }) +} + +export function publish(id) { + return request.axios.post(`${process.env.VUE_APP_LOWCODE_URL}/page/publish`, { + id, + }) +} + +export function fetchDetail(id) { + return request.axios.post( + `${process.env.VUE_APP_BI_DOMAIN}/${ + process.env.VUE_APP_LINKDATA_GATEWAY || 'linkdata-gateway' + }/route?/api/queryPageConf`, + { + apiCode: '/api/queryPageConf', + dispatcherSystem: 'lowcode', + param: { + lowcode_id: id, + is_publish: 0, + }, + } + ) +} diff --git a/src/assets/404_images/404.png b/src/assets/404_images/404.png new file mode 100644 index 0000000..3d8e230 Binary files /dev/null and b/src/assets/404_images/404.png differ diff --git a/src/assets/404_images/404_cloud.png b/src/assets/404_images/404_cloud.png new file mode 100644 index 0000000..c6281d0 Binary files /dev/null and b/src/assets/404_images/404_cloud.png differ diff --git a/src/assets/datapre/icon01@3x.png b/src/assets/datapre/icon01@3x.png new file mode 100644 index 0000000..f7528e6 Binary files /dev/null and b/src/assets/datapre/icon01@3x.png differ diff --git a/src/assets/datapre/icon02@3x.png b/src/assets/datapre/icon02@3x.png new file mode 100644 index 0000000..b99c9cc Binary files /dev/null and b/src/assets/datapre/icon02@3x.png differ diff --git a/src/assets/datapre/icon03@3x.png b/src/assets/datapre/icon03@3x.png new file mode 100644 index 0000000..3a95d9d Binary files /dev/null and b/src/assets/datapre/icon03@3x.png differ diff --git a/src/assets/datapre/icon04@3x.png b/src/assets/datapre/icon04@3x.png new file mode 100644 index 0000000..58713a3 Binary files /dev/null and b/src/assets/datapre/icon04@3x.png differ diff --git a/src/assets/datapre/icon05@3x.png b/src/assets/datapre/icon05@3x.png new file mode 100644 index 0000000..6bf329a Binary files /dev/null and b/src/assets/datapre/icon05@3x.png differ diff --git a/src/assets/datapre/icon06@3x.png b/src/assets/datapre/icon06@3x.png new file mode 100644 index 0000000..7ee46bd Binary files /dev/null and b/src/assets/datapre/icon06@3x.png differ diff --git a/src/assets/exit-full-screen.png b/src/assets/exit-full-screen.png new file mode 100644 index 0000000..c52b433 Binary files /dev/null and b/src/assets/exit-full-screen.png differ diff --git a/src/assets/iphone_frame@3x.png b/src/assets/iphone_frame@3x.png new file mode 100644 index 0000000..4de2772 Binary files /dev/null and b/src/assets/iphone_frame@3x.png differ diff --git a/src/assets/svgData/fill-drip-solid.svg b/src/assets/svgData/fill-drip-solid.svg new file mode 100644 index 0000000..ae20ecb --- /dev/null +++ b/src/assets/svgData/fill-drip-solid.svg @@ -0,0 +1,27 @@ + + + icon_颜色@3x + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/src/assets/svgData/font-solid.svg b/src/assets/svgData/font-solid.svg new file mode 100644 index 0000000..9ca8e4a --- /dev/null +++ b/src/assets/svgData/font-solid.svg @@ -0,0 +1,16 @@ + + + icon_文字颜色@2x + + + + + + + + + + + + + \ No newline at end of file diff --git a/src/assets/svgData/icon-bars-solid.svg b/src/assets/svgData/icon-bars-solid.svg new file mode 100644 index 0000000..ef3bb9f --- /dev/null +++ b/src/assets/svgData/icon-bars-solid.svg @@ -0,0 +1 @@ + diff --git a/src/assets/svgData/icon-d-solid.svg b/src/assets/svgData/icon-d-solid.svg new file mode 100644 index 0000000..e1bcc65 --- /dev/null +++ b/src/assets/svgData/icon-d-solid.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/assets/svgData/icon-database-solid.svg b/src/assets/svgData/icon-database-solid.svg new file mode 100644 index 0000000..fb56b0f --- /dev/null +++ b/src/assets/svgData/icon-database-solid.svg @@ -0,0 +1 @@ + diff --git a/src/assets/svgData/icon-down-filled.svg b/src/assets/svgData/icon-down-filled.svg new file mode 100644 index 0000000..c3c47ab --- /dev/null +++ b/src/assets/svgData/icon-down-filled.svg @@ -0,0 +1,15 @@ + + + plan2_下降@3x + + + + + + + + + + + + \ No newline at end of file diff --git a/src/assets/svgData/icon-down-solid.svg b/src/assets/svgData/icon-down-solid.svg new file mode 100644 index 0000000..6e262d5 --- /dev/null +++ b/src/assets/svgData/icon-down-solid.svg @@ -0,0 +1,16 @@ + + + plan2_下降@3x + + + + + + + + + + + + + \ No newline at end of file diff --git a/src/assets/svgData/icon-download-solid.svg b/src/assets/svgData/icon-download-solid.svg new file mode 100644 index 0000000..d3a98c4 --- /dev/null +++ b/src/assets/svgData/icon-download-solid.svg @@ -0,0 +1 @@ + diff --git a/src/assets/svgData/icon-floppy-disk-solid.svg b/src/assets/svgData/icon-floppy-disk-solid.svg new file mode 100644 index 0000000..025a566 --- /dev/null +++ b/src/assets/svgData/icon-floppy-disk-solid.svg @@ -0,0 +1 @@ + diff --git a/src/assets/svgData/icon-green.png b/src/assets/svgData/icon-green.png new file mode 100644 index 0000000..8063816 Binary files /dev/null and b/src/assets/svgData/icon-green.png differ diff --git a/src/assets/svgData/icon-green.svg b/src/assets/svgData/icon-green.svg new file mode 100644 index 0000000..2e5c70a --- /dev/null +++ b/src/assets/svgData/icon-green.svg @@ -0,0 +1,15 @@ + + + icon_字体颜色备份 11@3x + + + + + + + + + + + + \ No newline at end of file diff --git a/src/assets/svgData/icon-n-solid.svg b/src/assets/svgData/icon-n-solid.svg new file mode 100644 index 0000000..6141229 --- /dev/null +++ b/src/assets/svgData/icon-n-solid.svg @@ -0,0 +1 @@ + diff --git a/src/assets/svgData/icon-orange.svg b/src/assets/svgData/icon-orange.svg new file mode 100644 index 0000000..ba6069a --- /dev/null +++ b/src/assets/svgData/icon-orange.svg @@ -0,0 +1,15 @@ + + + icon_字体颜色备份 12@3x + + + + + + + + + + + + \ No newline at end of file diff --git a/src/assets/svgData/icon-org.png b/src/assets/svgData/icon-org.png new file mode 100644 index 0000000..f4c5023 Binary files /dev/null and b/src/assets/svgData/icon-org.png differ diff --git a/src/assets/svgData/icon-play-skip-forward.svg b/src/assets/svgData/icon-play-skip-forward.svg new file mode 100644 index 0000000..4046425 --- /dev/null +++ b/src/assets/svgData/icon-play-skip-forward.svg @@ -0,0 +1,5 @@ + + + diff --git a/src/assets/svgData/icon-play-solid.svg b/src/assets/svgData/icon-play-solid.svg new file mode 100644 index 0000000..b91c897 --- /dev/null +++ b/src/assets/svgData/icon-play-solid.svg @@ -0,0 +1 @@ + diff --git a/src/assets/svgData/icon-red.png b/src/assets/svgData/icon-red.png new file mode 100644 index 0000000..e5f55ca Binary files /dev/null and b/src/assets/svgData/icon-red.png differ diff --git a/src/assets/svgData/icon-right-filled.svg b/src/assets/svgData/icon-right-filled.svg new file mode 100644 index 0000000..a894ca1 --- /dev/null +++ b/src/assets/svgData/icon-right-filled.svg @@ -0,0 +1,15 @@ + + + plan2_向右@3x + + + + + + + + + + + + \ No newline at end of file diff --git a/src/assets/svgData/icon-right-solid.svg b/src/assets/svgData/icon-right-solid.svg new file mode 100644 index 0000000..899786d --- /dev/null +++ b/src/assets/svgData/icon-right-solid.svg @@ -0,0 +1,16 @@ + + + plan2_向右@3x + + + + + + + + + + + + + \ No newline at end of file diff --git a/src/assets/svgData/icon-s-solid.svg b/src/assets/svgData/icon-s-solid.svg new file mode 100644 index 0000000..872260f --- /dev/null +++ b/src/assets/svgData/icon-s-solid.svg @@ -0,0 +1 @@ + diff --git a/src/assets/svgData/icon-satisfied.svg b/src/assets/svgData/icon-satisfied.svg new file mode 100644 index 0000000..f0a9fd1 --- /dev/null +++ b/src/assets/svgData/icon-satisfied.svg @@ -0,0 +1,18 @@ + + + plan3_满意@3x + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/src/assets/svgData/icon-solid.svg b/src/assets/svgData/icon-solid.svg new file mode 100644 index 0000000..662ebe8 --- /dev/null +++ b/src/assets/svgData/icon-solid.svg @@ -0,0 +1,26 @@ + + + icon_图标@2x + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/src/assets/svgData/icon-t-solid.svg b/src/assets/svgData/icon-t-solid.svg new file mode 100644 index 0000000..3a55269 --- /dev/null +++ b/src/assets/svgData/icon-t-solid.svg @@ -0,0 +1 @@ + diff --git a/src/assets/svgData/icon-table-cells-solid.svg b/src/assets/svgData/icon-table-cells-solid.svg new file mode 100644 index 0000000..6981a69 --- /dev/null +++ b/src/assets/svgData/icon-table-cells-solid.svg @@ -0,0 +1 @@ + diff --git a/src/assets/svgData/icon-top-filled.svg b/src/assets/svgData/icon-top-filled.svg new file mode 100644 index 0000000..7f6d995 --- /dev/null +++ b/src/assets/svgData/icon-top-filled.svg @@ -0,0 +1,15 @@ + + + plan2_上升@3x + + + + + + + + + + + + \ No newline at end of file diff --git a/src/assets/svgData/icon-top-solid.svg b/src/assets/svgData/icon-top-solid.svg new file mode 100644 index 0000000..b87217c --- /dev/null +++ b/src/assets/svgData/icon-top-solid.svg @@ -0,0 +1,16 @@ + + + plan2_上升@3x + + + + + + + + + + + + + \ No newline at end of file diff --git a/src/assets/svgData/icon-un-satisfied.svg b/src/assets/svgData/icon-un-satisfied.svg new file mode 100644 index 0000000..520c0d9 --- /dev/null +++ b/src/assets/svgData/icon-un-satisfied.svg @@ -0,0 +1,18 @@ + + + plan3_不满意@3x + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/src/assets/svgData/icon_act_collect_data_inter.svg b/src/assets/svgData/icon_act_collect_data_inter.svg new file mode 100644 index 0000000..c72b56d --- /dev/null +++ b/src/assets/svgData/icon_act_collect_data_inter.svg @@ -0,0 +1,18 @@ + + + icon_数据集成_hov@3x + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/src/assets/svgData/icon_act_collect_datasource.svg b/src/assets/svgData/icon_act_collect_datasource.svg new file mode 100644 index 0000000..ac1c0d2 --- /dev/null +++ b/src/assets/svgData/icon_act_collect_datasource.svg @@ -0,0 +1,23 @@ + + + icon_数据源_hov@3x + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/src/assets/svgData/icon_act_datasource.svg b/src/assets/svgData/icon_act_datasource.svg new file mode 100644 index 0000000..f822006 --- /dev/null +++ b/src/assets/svgData/icon_act_datasource.svg @@ -0,0 +1,21 @@ + + + icon_数据源_hov@3x + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/src/assets/svgData/icon_act_meta.svg b/src/assets/svgData/icon_act_meta.svg new file mode 100644 index 0000000..0bdaf3c --- /dev/null +++ b/src/assets/svgData/icon_act_meta.svg @@ -0,0 +1,16 @@ + + + icon_元数据_hov@3x + + + + + + + + + + + + + \ No newline at end of file diff --git a/src/assets/svgData/icon_act_quota.svg b/src/assets/svgData/icon_act_quota.svg new file mode 100644 index 0000000..b9a21ba --- /dev/null +++ b/src/assets/svgData/icon_act_quota.svg @@ -0,0 +1,17 @@ + + + icon_指标管理_hov@3x + + + + + + + + + + + + + + \ No newline at end of file diff --git a/src/assets/svgData/icon_act_service_list.svg b/src/assets/svgData/icon_act_service_list.svg new file mode 100644 index 0000000..65c1950 --- /dev/null +++ b/src/assets/svgData/icon_act_service_list.svg @@ -0,0 +1,19 @@ + + + icon_服务管理_hov@3x + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/src/assets/svgData/icon_act_service_monitor.svg b/src/assets/svgData/icon_act_service_monitor.svg new file mode 100644 index 0000000..176b701 --- /dev/null +++ b/src/assets/svgData/icon_act_service_monitor.svg @@ -0,0 +1,18 @@ + + + icon_服务监控_hov@3x + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/src/assets/svgData/icon_act_set.svg b/src/assets/svgData/icon_act_set.svg new file mode 100644 index 0000000..064eb48 --- /dev/null +++ b/src/assets/svgData/icon_act_set.svg @@ -0,0 +1,13 @@ + + + icon_数据集_hov@3x + + + + + + + + + + \ No newline at end of file diff --git a/src/assets/svgData/icon_act_system_authority.svg b/src/assets/svgData/icon_act_system_authority.svg new file mode 100644 index 0000000..41942e5 --- /dev/null +++ b/src/assets/svgData/icon_act_system_authority.svg @@ -0,0 +1,20 @@ + + + icon_权限管理_hov@3x + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/src/assets/svgData/icon_act_system_dataset.svg b/src/assets/svgData/icon_act_system_dataset.svg new file mode 100644 index 0000000..201578a --- /dev/null +++ b/src/assets/svgData/icon_act_system_dataset.svg @@ -0,0 +1,22 @@ + + + icon_数据集_hov@3x + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/src/assets/svgData/icon_act_system_monitor.svg b/src/assets/svgData/icon_act_system_monitor.svg new file mode 100644 index 0000000..b840ccc --- /dev/null +++ b/src/assets/svgData/icon_act_system_monitor.svg @@ -0,0 +1,25 @@ + + + icon_报表监控_hov@3x + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/src/assets/svgData/icon_act_system_report.svg b/src/assets/svgData/icon_act_system_report.svg new file mode 100644 index 0000000..184cab2 --- /dev/null +++ b/src/assets/svgData/icon_act_system_report.svg @@ -0,0 +1,26 @@ + + + icon_报表管理_hov@3x + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/src/assets/svgData/icon_act_system_role.svg b/src/assets/svgData/icon_act_system_role.svg new file mode 100644 index 0000000..6674670 --- /dev/null +++ b/src/assets/svgData/icon_act_system_role.svg @@ -0,0 +1,20 @@ + + + icon_角色管理_hov@3x + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/src/assets/svgData/icon_act_system_user.svg b/src/assets/svgData/icon_act_system_user.svg new file mode 100644 index 0000000..004b466 --- /dev/null +++ b/src/assets/svgData/icon_act_system_user.svg @@ -0,0 +1,19 @@ + + + icon_用户管理_hov@3x + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/src/assets/svgData/icon_act_tag.svg b/src/assets/svgData/icon_act_tag.svg new file mode 100644 index 0000000..78d86bb --- /dev/null +++ b/src/assets/svgData/icon_act_tag.svg @@ -0,0 +1,15 @@ + + + icon_标签管理_hov@3x + + + + + + + + + + + + \ No newline at end of file diff --git a/src/assets/svgData/icon_cell_close.svg b/src/assets/svgData/icon_cell_close.svg new file mode 100644 index 0000000..1764d8f --- /dev/null +++ b/src/assets/svgData/icon_cell_close.svg @@ -0,0 +1,6 @@ + + + + + + diff --git a/src/assets/svgData/icon_cell_open.svg b/src/assets/svgData/icon_cell_open.svg new file mode 100644 index 0000000..01327cf --- /dev/null +++ b/src/assets/svgData/icon_cell_open.svg @@ -0,0 +1,6 @@ + + + + + + diff --git a/src/assets/svgData/icon_collect_data_inter.svg b/src/assets/svgData/icon_collect_data_inter.svg new file mode 100644 index 0000000..a39ade5 --- /dev/null +++ b/src/assets/svgData/icon_collect_data_inter.svg @@ -0,0 +1,16 @@ + + + icon_数据集成_nor@3x + + + + + + + + + + + + + \ No newline at end of file diff --git a/src/assets/svgData/icon_collect_datasource.svg b/src/assets/svgData/icon_collect_datasource.svg new file mode 100644 index 0000000..07a4cb6 --- /dev/null +++ b/src/assets/svgData/icon_collect_datasource.svg @@ -0,0 +1,21 @@ + + + icon_数据源_nor@3x + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/src/assets/svgData/icon_data_datasource.svg b/src/assets/svgData/icon_data_datasource.svg new file mode 100644 index 0000000..3215dcf --- /dev/null +++ b/src/assets/svgData/icon_data_datasource.svg @@ -0,0 +1,23 @@ + + + icon_数据源_nor@3x + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/src/assets/svgData/icon_data_meta.svg b/src/assets/svgData/icon_data_meta.svg new file mode 100644 index 0000000..ea59c34 --- /dev/null +++ b/src/assets/svgData/icon_data_meta.svg @@ -0,0 +1,18 @@ + + + icon_元数据_nor@3x + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/src/assets/svgData/icon_data_quota.svg b/src/assets/svgData/icon_data_quota.svg new file mode 100644 index 0000000..6608c36 --- /dev/null +++ b/src/assets/svgData/icon_data_quota.svg @@ -0,0 +1,19 @@ + + + icon_指标管理_nor@3x + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/src/assets/svgData/icon_data_set.svg b/src/assets/svgData/icon_data_set.svg new file mode 100644 index 0000000..bf00264 --- /dev/null +++ b/src/assets/svgData/icon_data_set.svg @@ -0,0 +1,16 @@ + + + icon_数据集_nor@2x + + + + + + + + + + + + + \ No newline at end of file diff --git a/src/assets/svgData/icon_data_tag.svg b/src/assets/svgData/icon_data_tag.svg new file mode 100644 index 0000000..e3bc722 --- /dev/null +++ b/src/assets/svgData/icon_data_tag.svg @@ -0,0 +1,17 @@ + + + icon_标签管理_nor@3x + + + + + + + + + + + + + + \ No newline at end of file diff --git a/src/assets/svgData/icon_file_close.svg b/src/assets/svgData/icon_file_close.svg new file mode 100644 index 0000000..fa8dd86 --- /dev/null +++ b/src/assets/svgData/icon_file_close.svg @@ -0,0 +1,3 @@ + + + diff --git a/src/assets/svgData/icon_file_open.svg b/src/assets/svgData/icon_file_open.svg new file mode 100644 index 0000000..2bb4ba8 --- /dev/null +++ b/src/assets/svgData/icon_file_open.svg @@ -0,0 +1,6 @@ + + + + + + diff --git a/src/assets/svgData/icon_info.svg b/src/assets/svgData/icon_info.svg new file mode 100644 index 0000000..7b92732 --- /dev/null +++ b/src/assets/svgData/icon_info.svg @@ -0,0 +1 @@ + diff --git a/src/assets/svgData/icon_no_datasource.svg b/src/assets/svgData/icon_no_datasource.svg new file mode 100644 index 0000000..0984d94 --- /dev/null +++ b/src/assets/svgData/icon_no_datasource.svg @@ -0,0 +1,268 @@ + + + no_page2备份 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/src/assets/svgData/icon_service_list.svg b/src/assets/svgData/icon_service_list.svg new file mode 100644 index 0000000..d9c99e9 --- /dev/null +++ b/src/assets/svgData/icon_service_list.svg @@ -0,0 +1,17 @@ + + + icon_服务管理_nor@3x + + + + + + + + + + + + + + \ No newline at end of file diff --git a/src/assets/svgData/icon_service_monitor.svg b/src/assets/svgData/icon_service_monitor.svg new file mode 100644 index 0000000..24c2aed --- /dev/null +++ b/src/assets/svgData/icon_service_monitor.svg @@ -0,0 +1,16 @@ + + + icon_服务监控_nor@3x + + + + + + + + + + + + + \ No newline at end of file diff --git a/src/assets/svgData/icon_system_authority.svg b/src/assets/svgData/icon_system_authority.svg new file mode 100644 index 0000000..8ca88d5 --- /dev/null +++ b/src/assets/svgData/icon_system_authority.svg @@ -0,0 +1,18 @@ + + + icon_权限管理_nor@3x + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/src/assets/svgData/icon_system_dataset.svg b/src/assets/svgData/icon_system_dataset.svg new file mode 100644 index 0000000..817358d --- /dev/null +++ b/src/assets/svgData/icon_system_dataset.svg @@ -0,0 +1,22 @@ + + + icon_数据集_nor@3x + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/src/assets/svgData/icon_system_monitor.svg b/src/assets/svgData/icon_system_monitor.svg new file mode 100644 index 0000000..be3dde0 --- /dev/null +++ b/src/assets/svgData/icon_system_monitor.svg @@ -0,0 +1,23 @@ + + + icon_报表监控_nor@3x + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/src/assets/svgData/icon_system_report.svg b/src/assets/svgData/icon_system_report.svg new file mode 100644 index 0000000..9a85100 --- /dev/null +++ b/src/assets/svgData/icon_system_report.svg @@ -0,0 +1,24 @@ + + + icon_报表管理_nor@3x + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/src/assets/svgData/icon_system_role.svg b/src/assets/svgData/icon_system_role.svg new file mode 100644 index 0000000..84b1062 --- /dev/null +++ b/src/assets/svgData/icon_system_role.svg @@ -0,0 +1,18 @@ + + + icon_角色管理_nor@3x + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/src/assets/svgData/icon_system_user.svg b/src/assets/svgData/icon_system_user.svg new file mode 100644 index 0000000..22d145e --- /dev/null +++ b/src/assets/svgData/icon_system_user.svg @@ -0,0 +1,17 @@ + + + icon_用户管理_nor@3x + + + + + + + + + + + + + + \ No newline at end of file diff --git a/src/assets/svgData/icon_title_logo.svg b/src/assets/svgData/icon_title_logo.svg new file mode 100644 index 0000000..bfdd3be --- /dev/null +++ b/src/assets/svgData/icon_title_logo.svg @@ -0,0 +1,3 @@ + + + diff --git a/src/assets/svgData/icon_tra_close.svg b/src/assets/svgData/icon_tra_close.svg new file mode 100644 index 0000000..b563809 --- /dev/null +++ b/src/assets/svgData/icon_tra_close.svg @@ -0,0 +1,3 @@ + + + diff --git a/src/components/SvgIcon copy/index.vue b/src/components/SvgIcon copy/index.vue new file mode 100644 index 0000000..d1a877c --- /dev/null +++ b/src/components/SvgIcon copy/index.vue @@ -0,0 +1,63 @@ + + + + + diff --git a/src/components/SvgIcon/index.vue b/src/components/SvgIcon/index.vue new file mode 100644 index 0000000..2b8bbd9 --- /dev/null +++ b/src/components/SvgIcon/index.vue @@ -0,0 +1,56 @@ + + + + + diff --git a/src/components/dialog/index.js b/src/components/dialog/index.js new file mode 100644 index 0000000..fcbbe40 --- /dev/null +++ b/src/components/dialog/index.js @@ -0,0 +1,10 @@ +// 弹框组件 +import RetailDialog from './src/main.vue' + +// 为组件提供 install 安装方法,供按需引入 +RetailDialog.install = function (Vue) { + Vue.component(RetailDialog.name, RetailDialog) +} + +// 默认导出组件 +export default RetailDialog diff --git a/src/components/dialog/src/main.vue b/src/components/dialog/src/main.vue new file mode 100644 index 0000000..0bcf8c2 --- /dev/null +++ b/src/components/dialog/src/main.vue @@ -0,0 +1,164 @@ + + + + diff --git a/src/components/folder/index.vue b/src/components/folder/index.vue new file mode 100644 index 0000000..ae6ee59 --- /dev/null +++ b/src/components/folder/index.vue @@ -0,0 +1,68 @@ + + + diff --git a/src/components/generator/config.bak.js b/src/components/generator/config.bak.js new file mode 100644 index 0000000..843443a --- /dev/null +++ b/src/components/generator/config.bak.js @@ -0,0 +1,784 @@ +// 表单属性【右面板】 +export const formConf = { + formRef: 'elForm', + formModel: 'formData', + size: 'medium', + labelPosition: 'right', + labelWidth: 80, + formRules: 'rules', + gutter: 15, + disabled: false, + formBtns: true, +} + +// 输入型组件 【左面板】 +export const inputComponents = [ + { + // 组件的自定义配置 + __config__: { + label: '通用输入框', + labelWidth: null, + showLabel: true, + changeTag: false, + tag: 'el-input', + tagIcon: 'input', + type: 'input', + defaultValue: undefined, + required: false, + layout: 'colFormItem', + span: 6, + // 正则校验规则 + regList: [], + }, + // 组件的插槽属性 + __slot__: { + prepend: '', + append: '', + }, + // 其余的为可直接写在组件标签上的属性 + placeholder: '请输入', + style: { width: '100%' }, + clearable: true, + 'prefix-icon': '', + 'suffix-icon': '', + maxlength: null, + 'show-word-limit': false, + readonly: false, + disabled: false, + }, + { + // 组件的自定义配置 + __config__: { + label: '单选框', + labelWidth: null, + showLabel: false, + changeTag: false, + tag: 'el-radio', + type: 'radio', + tagIcon: 'input', + defaultValue: 1, + required: false, + layout: 'colFormItem', + span: 6, + }, + // 其余的为可直接写在组件标签上的属性 + disabled: false, + label: '单选框', // 此属性为了让单选框的文本显示在后面 + prop: '', + }, + { + // 组件的自定义配置 + __config__: { + label: '复选框', + labelWidth: null, + showLabel: false, + changeTag: false, + tag: 'el-checkbox', + type: 'checkbox', + tagIcon: 'input', + defaultValue: undefined, + required: false, + layout: 'colFormItem', + span: 6, + }, + disabled: false, + label: '复选框', // 此属性为了让单选框的文本显示在后面 + }, + { + __config__: { + label: '数字输入框', + showLabel: true, + changeTag: false, + labelWidth: null, + tag: 'el-input-number', + type: 'inputNumber', + tagIcon: 'number', + defaultValue: undefined, + span: 6, + layout: 'colFormItem', + required: false, + regList: [], + document: 'https://element.eleme.cn/#/zh-CN/component/input-number', + }, + placeholder: '', + min: undefined, + max: undefined, + step: 1, + 'step-strictly': false, + precision: undefined, + 'controls-position': 'right', + disabled: false, + }, + { + __config__: { + label: '级联选择', + url: 'https://www.fastmock.site/mock/f8d7a54fb1e60561e2f720d5a810009d/fg/cascaderList', + method: 'get', + dataPath: 'list', + dataConsumer: 'options', + showLabel: true, + labelWidth: null, + tag: 'el-cascader', + type: 'cascader', + tagIcon: 'cascader', + layout: 'colFormItem', + defaultValue: [], + dataType: 'dynamic', + span: 6, + required: false, + regList: [], + changeTag: false, + document: 'https://element.eleme.cn/#/zh-CN/component/cascader', + }, + options: [ + { + id: 1, + value: 1, + label: '选项1', + children: [ + { + id: 2, + value: 2, + label: '选项1-1', + }, + ], + }, + ], + placeholder: '请选择', + style: { width: '100%' }, + props: { + props: { + multiple: false, + label: 'label', + value: 'value', + children: 'children', + }, + }, + 'show-all-levels': true, + disabled: false, + clearable: true, + filterable: false, + separator: '/', + }, + // { + // __config__: { + // label: '多行文本', + // labelWidth: null, + // showLabel: true, + // tag: 'el-input', + // tagIcon: 'textarea', + // defaultValue: undefined, + // required:false, + // layout: 'colFormItem', + // span: 6, + // regList: [], + // changeTag: false, + // document: 'https://element.eleme.cn/#/zh-CN/component/input', + // }, + // type: 'textarea', + // placeholder: '请输入', + // autosize: { + // minRows: 4, + // maxRows: 4, + // }, + // style: { width: '100%' }, + // maxlength: null, + // 'show-word-limit': false, + // readonly: false, + // disabled: false, + // }, + // { + // __config__: { + // label: '密码', + // showLabel: true, + // labelWidth: null, + // changeTag: false, + // tag: 'el-input', + // tagIcon: 'password', + // defaultValue: undefined, + // layout: 'colFormItem', + // span: 6, + // required:false, + // regList: [], + // document: 'https://element.eleme.cn/#/zh-CN/component/input', + // }, + // __slot__: { + // prepend: '', + // append: '', + // }, + // placeholder: '请输入', + // 'show-password': true, + // style: { width: '100%' }, + // clearable: true, + // 'prefix-icon': '', + // 'suffix-icon': '', + // maxlength: null, + // 'show-word-limit': false, + // readonly: false, + // disabled: false, + // }, + + // { + // __config__: { + // label: '编辑器', + // showLabel: true, + // changeTag: false, + // labelWidth: null, + // tag: 'tinymce', + // tagIcon: 'rich-text', + // defaultValue: null, + // span: 6, + // layout: 'colFormItem', + // required:false, + // regList: [], + // document: 'http://tinymce.ax-z.cn', + // }, + // placeholder: '请输入', + // height: 300, // 编辑器高度 + // branding: false, // 隐藏右下角品牌烙印 + // }, +] + +// 选择型组件 【左面板】 +export const selectComponents = [ + { + __config__: { + label: '通用下拉框', + showLabel: true, + labelWidth: null, + tag: 'LinkCommonSelect', + type: 'select', + tagIcon: 'select', + layout: 'colFormItem', + span: 6, + required: false, + regList: [], + changeTag: false, + }, + __slot__: { + options: [ + { + label: '选项一', + value: 1, + }, + { + label: '选项二', + value: 2, + }, + ], + }, + placeholder: '请选择', + style: { width: '100%' }, + clearable: true, + disabled: false, + filterable: false, + multiple: false, + }, + { + __config__: { + label: '门店组件', + labelWidth: null, + showLabel: true, + tag: 'LinkSelectTreeDepartment', + type: 'storeSelect', + tagIcon: 'radio', + changeTag: false, + defaultValue: undefined, + layout: 'colFormItem', + span: 6, + optionType: 'default', + regList: [], + required: false, + border: false, + document: 'https://element.eleme.cn/#/zh-CN/component/radio', + }, + __slot__: { + options: [ + { + label: '选项一', + value: 1, + }, + { + label: '选项二', + value: 2, + }, + ], + }, + style: {}, + size: 'medium', + disabled: false, + }, + { + __config__: { + label: '时间组件', + tag: 'LinkDatePicker', + type: 'date', + tagIcon: 'checkbox', + layout: 'colFormItem', + value: [], + defaultValue: [], + clearable: true, + disableStart: false, + disableEnd: false, + showShortCutDate: false, + + span: 6, + showLabel: true, + labelWidth: null, + regList: [], + changeTag: false, + border: false, + }, + style: {}, + disabled: false, + }, + { + __config__: { + label: '复杂时间组件', + tag: 'LinkComplexTimePicker', + type: 'complexTime', + tagIcon: 'switch', + defaultValue: {}, + span: 6, + showLabel: true, + labelWidth: null, + layout: 'colFormItem', + required: false, + regList: [], + changeTag: false, + }, + style: {}, + disabled: false, + vModel: 'time', + }, + { + __config__: { + label: '品类组件', + tag: 'LinkCategoryPicker', + type: 'category', + tagIcon: 'switch', + defaultValue: [], + span: 6, + showLabel: true, + labelWidth: null, + layout: 'colFormItem', + required: false, + regList: [], + changeTag: false, + }, + style: {}, + disabled: false, + vModel: 'category', + isBeta: process.env.VUE_APP_ENVIRONMENT === 'development', + }, + { + __config__: { + label: '品牌组件', + tag: 'LinkSelectBrandSimple', + type: 'brand', + tagIcon: 'switch', + defaultValue: [], + span: 6, + showLabel: true, + labelWidth: null, + layout: 'colFormItem', + required: false, + regList: [], + changeTag: false, + }, + style: {}, + disabled: false, + vModel: 'brand', + isBeta: process.env.VUE_APP_ENVIRONMENT === 'development', + }, + { + __config__: { + label: '商品属性', + tag: 'LinkGoodsAttrPicker', + type: 'goodsAttr', + tagIcon: 'switch', + defaultValue: {}, + span: 6, + showLabel: true, + labelWidth: null, + layout: 'colFormItem', + required: false, + regList: [], + changeTag: false, + }, + style: {}, + disabled: false, + }, + { + __config__: { + label: '员工选择组件', + tag: 'LinkSelectUser', + type: 'selectUser', + tagIcon: 'switch', + defaultValue: [], + span: 6, + showLabel: true, + labelWidth: null, + layout: 'colFormItem', + required: false, + regList: [], + changeTag: false, + }, + style: {}, + disabled: false, + vModel: 'user', + isBeta: process.env.VUE_APP_ENVIRONMENT === 'development', + }, + // { + // __config__: { + // label: '滑块', + // tag: 'el-slider', + // tagIcon: 'slider', + // defaultValue: null, + // span: 6, + // showLabel: true, + // layout: 'colFormItem', + // labelWidth: null, + // required:false, + // regList: [], + // changeTag: false, + // document: 'https://element.eleme.cn/#/zh-CN/component/slider', + // }, + // disabled: false, + // min: 0, + // max: 100, + // step: 1, + // 'show-stops': false, + // range: false, + // }, + // { + // __config__: { + // label: '时间选择', + // tag: 'el-time-picker', + // tagIcon: 'time', + // defaultValue: null, + // span: 6, + // showLabel: true, + // layout: 'colFormItem', + // labelWidth: null, + // required:false, + // regList: [], + // changeTag: false, + // document: 'https://element.eleme.cn/#/zh-CN/component/time-picker', + // }, + // placeholder: '请选择', + // style: { width: '100%' }, + // disabled: false, + // clearable: true, + // 'picker-options': { + // selectableRange: '00:00:00-23:59:59', + // }, + // format: 'HH:mm:ss', + // 'value-format': 'HH:mm:ss', + // }, + // { + // __config__: { + // label: '时间范围', + // tag: 'el-time-picker', + // tagIcon: 'time-range', + // span: 6, + // showLabel: true, + // labelWidth: null, + // layout: 'colFormItem', + // defaultValue: null, + // required:false, + // regList: [], + // changeTag: false, + // document: 'https://element.eleme.cn/#/zh-CN/component/time-picker', + // }, + // style: { width: '100%' }, + // disabled: false, + // clearable: true, + // 'is-range': true, + // 'range-separator': '至', + // 'start-placeholder': '开始时间', + // 'end-placeholder': '结束时间', + // format: 'HH:mm:ss', + // 'value-format': 'HH:mm:ss', + // }, + // { + // __config__: { + // label: '日期选择', + // tag: 'el-date-picker', + // tagIcon: 'date', + // defaultValue: null, + // showLabel: true, + // labelWidth: null, + // span: 6, + // layout: 'colFormItem', + // required:false, + // regList: [], + // changeTag: false, + // document: 'https://element.eleme.cn/#/zh-CN/component/date-picker', + // }, + // placeholder: '请选择', + // type: 'date', + // style: { width: '100%' }, + // disabled: false, + // clearable: true, + // format: 'yyyy-MM-dd', + // 'value-format': 'yyyy-MM-dd', + // readonly: false, + // }, + // { + // __config__: { + // label: '日期范围', + // tag: 'el-date-picker', + // tagIcon: 'date-range', + // defaultValue: null, + // span: 6, + // showLabel: true, + // labelWidth: null, + // required:false, + // layout: 'colFormItem', + // regList: [], + // changeTag: false, + // document: 'https://element.eleme.cn/#/zh-CN/component/date-picker', + // }, + // style: { width: '100%' }, + // type: 'daterange', + // 'range-separator': '至', + // 'start-placeholder': '开始日期', + // 'end-placeholder': '结束日期', + // disabled: false, + // clearable: true, + // format: 'yyyy-MM-dd', + // 'value-format': 'yyyy-MM-dd', + // readonly: false, + // }, + // { + // __config__: { + // label: '评分', + // tag: 'el-rate', + // tagIcon: 'rate', + // defaultValue: 0, + // span: 6, + // showLabel: true, + // labelWidth: null, + // layout: 'colFormItem', + // required:false, + // regList: [], + // changeTag: false, + // document: 'https://element.eleme.cn/#/zh-CN/component/rate', + // }, + // style: {}, + // max: 5, + // 'allow-half': false, + // 'show-text': false, + // 'show-score': false, + // disabled: false, + // }, + // { + // __config__: { + // label: '颜色选择', + // tag: 'el-color-picker', + // tagIcon: 'color', + // span: 6, + // defaultValue: null, + // showLabel: true, + // labelWidth: null, + // layout: 'colFormItem', + // required:false, + // regList: [], + // changeTag: false, + // document: 'https://element.eleme.cn/#/zh-CN/component/color-picker', + // }, + // 'show-alpha': false, + // 'color-format': '', + // disabled: false, + // size: 'medium', + // }, + { + __config__: { + label: '汇总方式', + tag: 'LinkMoreTab', + type: 'summaryMethod', + placeholder: 'sss', + tagIcon: 'upload', + layout: 'colFormItem', + defaultValue: null, + showLabel: true, + labelWidth: null, + required: false, + span: 12, + showTip: false, + regList: [], + changeTag: false, + max: 5, + }, + __slot__: { + 'list-type': true, + }, + action: 'https://jsonplaceholder.typicode.com/posts/', + disabled: false, + accept: '', + name: 'file', + 'auto-upload': true, + 'list-type': 'text', + multiple: false, + alreadyHave: false, // 此字段用于控制汇总方式和导出组件是否可拖动 + vModel: 'supplier', + }, + { + __config__: { + label: '导出组件', + tag: 'LinkToolExportGroup', + layout: 'colFormItem', + tagIcon: 'upload', + defaultValue: null, + showLabel: true, + labelWidth: null, + required: false, + span: 12, + showTip: false, + }, + disabled: false, + accept: '', + name: 'file', + 'auto-upload': true, + 'list-type': 'text', + multiple: false, + alreadyHave: false, // 此字段用于控制汇总方式和导出组件是否可拖动 + }, +] + +// 布局型组件 【左面板】 +export const layoutComponents = [ + { + __config__: { + layout: 'rowFormItem', + tagIcon: 'row', + label: '行容器', + layoutTree: true, + }, + type: 'default', + justify: 'start', + align: 'top', + }, + // { + // __config__: { + // label: '按钮', + // showLabel: true, + // changeTag: false, + // labelWidth: null, + // tag: 'el-button', + // tagIcon: 'button', + // span: 6, + // layout: 'colFormItem', + // document: 'https://element.eleme.cn/#/zh-CN/component/button', + // }, + // __slot__: { + // default: '主要按钮', + // }, + // type: 'primary', + // icon: 'el-icon-search', + // round: false, + // size: 'medium', + // plain: false, + // circle: false, + // disabled: false, + // }, + // { + // __config__: { + // layout: 'colFormItem', + // tagIcon: 'table', + // tag: 'el-table', + // document: 'https://element.eleme.cn/#/zh-CN/component/table', + // span: 6, + // formId: 101, + // renderKey: 1595761764203, + // componentName: 'row101', + // showLabel: true, + // changeTag: false, + // labelWidth: null, + // label: '表格[开发中]', + // dataType: 'dynamic', + // method: 'get', + // dataPath: 'list', + // dataConsumer: 'data', + // url: 'https://www.fastmock.site/mock/f8d7a54fb1e60561e2f720d5a810009d/fg/tableData', + // children: [ + // { + // __config__: { + // layout: 'raw', + // tag: 'el-table-column', + // renderKey: 15957617660153, + // }, + // prop: 'date', + // label: '日期', + // }, + // { + // __config__: { + // layout: 'raw', + // tag: 'el-table-column', + // renderKey: 15957617660152, + // }, + // prop: 'address', + // label: '地址', + // }, + // { + // __config__: { + // layout: 'raw', + // tag: 'el-table-column', + // renderKey: 15957617660151, + // }, + // prop: 'name', + // label: '名称', + // }, + // { + // __config__: { + // layout: 'raw', + // tag: 'el-table-column', + // renderKey: 1595774496335, + // children: [ + // { + // __config__: { + // label: '按钮', + // tag: 'el-button', + // tagIcon: 'button', + // layout: 'raw', + // renderKey: 1595779809901, + // }, + // __slot__: { + // default: '主要按钮', + // }, + // type: 'primary', + // icon: 'el-icon-search', + // round: false, + // size: 'medium', + // }, + // ], + // }, + // label: '操作', + // }, + // ], + // }, + // data: [], + // directives: [ + // { + // name: 'loading', + // value: true, + // }, + // ], + // border: true, + // type: 'default', + // justify: 'start', + // align: 'top', + // }, +] + +export const EmptyComponents = [ + { + __config__: { + layout: 'colEmptyItem', + tagIcon: 'row', + label: '行容器', + layoutTree: true, + }, + }, +] diff --git a/src/components/generator/config.js b/src/components/generator/config.js new file mode 100644 index 0000000..0f49986 --- /dev/null +++ b/src/components/generator/config.js @@ -0,0 +1,655 @@ +// 表单属性【右面板】 +export const formConf = { + formRef: 'elForm', + formModel: 'formData', + size: 'medium', + labelPosition: 'right', + labelWidth: 80, + formRules: 'rules', + gutter: 0, + disabled: false, + formBtns: true, +} + +// 输入型组件 【左面板】 +export const inputComponents = [ + { + // 组件的自定义配置 + __config__: { + label: '文本输入框', + labelWidth: null, + showLabel: true, + changeTag: false, + tag: 'el-input', + tagIcon: 'input', + type: 'input', + defaultValue: undefined, + required: false, + layout: 'colFormItem', + span: 6, + // 正则校验规则 + regList: [], + component_id: '', + }, + // 增加此属性可以使组件可编辑 + __vModel__: 'input', + // 其余的为可直接写在组件标签上的属性 + placeholder: '请输入', + clearable: true, + disabled: false, + }, + { + __config__: { + label: '下拉框', + showLabel: true, + labelWidth: null, + tag: 'LinkCommonSelect', + type: 'select', + tagIcon: 'select', + layout: 'colFormItem', + span: 6, + required: false, + regList: [], + changeTag: false, + component_id: '', + }, + __slot__: { + options: [], + }, + __vModel__: 'select', + placeholder: '请选择', + style: { width: '100%' }, + clearable: true, + disabled: false, + filterable: false, + multiple: false, + }, + { + // 组件的自定义配置 + __config__: { + label: '单选框', + labelWidth: null, + showLabel: false, + changeTag: false, + tag: 'el-radio', + type: 'radio', + tagIcon: 'radio', + defaultValue: 1, + required: false, + layout: 'colFormItem', + span: 6, + component_id: '', + }, + // 其余的为可直接写在组件标签上的属性 + disabled: false, + // label: '单选框', // 此属性为了让单选框的文本显示在后面 + prop: '', + }, + { + // 组件的自定义配置 + __config__: { + label: '复选框', + labelWidth: null, + showLabel: false, + changeTag: false, + tag: 'el-checkbox', + type: 'checkbox', + tagIcon: 'checkbox', + defaultValue: undefined, + required: false, + layout: 'colFormItem', + span: 6, + component_id: '', + }, + disabled: false, + // label: '复选框', // 此属性为了让单选框的文本显示在后面 + }, + { + __config__: { + label: '数字输入框', + showLabel: true, + changeTag: false, + labelWidth: null, + tag: 'el-input-number', + type: 'inputNumber', + tagIcon: 'number', + defaultValue: undefined, + span: 6, + layout: 'colFormItem', + required: false, + regList: [], + document: 'https://element.eleme.cn/#/zh-CN/component/input-number', + component_id: '', + }, + placeholder: '', + min: undefined, + max: undefined, + step: 1, + 'step-strictly': false, + precision: undefined, + 'controls-position': 'right', + disabled: false, + }, + { + __config__: { + label: '数字区间', + tag: 'LinkNumberSection', + type: 'numberSection', + layout: 'colFormItem', + tagIcon: 'nested', + defaultValue: [], + showLabel: true, + labelWidth: null, + required: false, + regList: [], + span: 6, + showTip: false, + component_id: '', + }, + __vModel__: 'numberSection', + placeholder: '请选择', + style: { width: '100%' }, + disabled: false, + defaultData: [], + }, + // { + // __config__: { + // layout: 'colEmptyItem', + // tagIcon: 'row', + // label: '占位控件', + // layoutTree: true, + // component_id: '', + // span: 6, + // type: 'LinkEmpty', + // tag: 'LinkEmpty', + // }, + // }, + { + // 组件的自定义配置 + __config__: { + label: '单个时间', + labelWidth: null, + showLabel: true, + changeTag: false, + tag: 'el-datePicker', + type: 'singDate', + tagIcon: 'time', + defaultValue: '', + required: true, + layout: 'colFormItem', + span: 6, + component_id: '', + }, + // 其余的为可直接写在组件标签上的属性 + style: {}, + singDateType: 'date', + disabled: false, + }, + { + __config__: { + label: '时间区间', + tag: 'LinkDatePicker', + type: 'date', + tagIcon: 'time', + layout: 'colFormItem', + value: [], + defaultValue: [], + clearable: true, + disableStart: false, + disableEnd: false, + showShortCutDate: false, + + span: 6, + showLabel: true, + labelWidth: null, + regList: [], + changeTag: false, + border: false, + component_id: '', + }, + style: {}, + disabled: false, + }, + { + __config__: { + label: '复杂时间', + tag: 'LinkComplexTimePicker', + type: 'complexTime', + tagIcon: 'time-range', + defaultValue: {}, + span: 6, + showLabel: true, + labelWidth: null, + layout: 'colFormItem', + required: false, + regList: [], + changeTag: false, + component_id: '', + }, + style: {}, + disabled: false, + vModel: 'time', + }, + { + __config__: { + label: 'ABC组件', + tag: 'LinkAbcComp', + type: 'abcComp', + layout: 'colFormItem', + tagIcon: 'nested', + defaultValue: [], + showLabel: true, + labelWidth: null, + required: false, + regList: [], + span: 6, + showTip: false, + component_id: '', + }, + __vModel__: 'abcComp', + placeholder: '请选择', + style: { width: '100%' }, + disabled: false, + defaultData: [], + }, + { + __config__: { + label: '动态区间', + tag: 'LinkMoveSection', + type: 'moveSection', + layout: 'colFormItem', + tagIcon: 'nested', + defaultValue: [], + showLabel: true, + labelWidth: null, + required: false, + regList: [], + span: 6, + showTip: false, + component_id: '', + }, + __vModel__: 'moveSection', + placeholder: '请选择', + style: { width: '100%' }, + disabled: false, + defaultData: [], + }, + { + __config__: { + label: '级联选择', + url: 'https://www.fastmock.site/mock/f8d7a54fb1e60561e2f720d5a810009d/fg/cascaderList', + method: 'get', + dataPath: 'list', + dataConsumer: 'options', + showLabel: true, + labelWidth: null, + tag: 'el-cascader', + type: 'cascader', + tagIcon: 'cascader', + layout: 'colFormItem', + defaultValue: [], + dataType: 'dynamic', + span: 6, + required: false, + regList: [], + changeTag: false, + document: 'https://element.eleme.cn/#/zh-CN/component/cascader', + component_id: '', + }, + options: [ + { + id: 1, + value: 1, + label: '选项1', + children: [ + { + id: 2, + value: 2, + label: '选项1-1', + }, + ], + }, + ], + placeholder: '请选择', + style: { width: '100%' }, + props: { + props: { + multiple: false, + label: 'label', + value: 'value', + children: 'children', + }, + }, + 'show-all-levels': true, + disabled: false, + clearable: true, + filterable: false, + separator: '/', + }, +] + +// 选择型组件 【左面板】 +export const selectComponents = [ + { + __config__: { + label: '门店', + labelWidth: null, + showLabel: true, + tag: 'LinkSelectTreeDepartment', + type: 'storeSelect', + tagIcon: 'radio', + changeTag: false, + defaultValue: undefined, + layout: 'colFormItem', + span: 6, + optionType: 'default', + regList: [], + required: false, + border: false, + document: 'https://element.eleme.cn/#/zh-CN/component/radio', + component_id: '', + }, + __slot__: { + options: [ + { + label: '选项一', + value: 1, + }, + { + label: '选项二', + value: 2, + }, + ], + }, + __vModel__: 'department', + label: '门店', + size: 'medium', + disabled: false, + placeholder: '', + collapse: false, + charge: false, + checkedAll: false, + multi: false, + filterType: '', + tileModel: false, + ignoreDepts: [], + // 需要的时候就放开并配置好 + // platformNum, + // mode, + // departStatus, + // selectedOnlyOne, + }, + { + __config__: { + label: '人员', + tag: 'LinkSelectPersonnel', + type: 'personnel', + layout: 'colFormItem', + tagIcon: 'select', + defaultValue: [], + showLabel: true, + labelWidth: null, + required: false, + regList: [], + span: 6, + showTip: false, + component_id: '', + }, + __vModel__: 'personnel', + placeholder: '请选择', + style: { width: '100%' }, + disabled: false, + }, + { + __config__: { + label: '品类', + tag: 'LinkCategoryPicker', + type: 'category', + tagIcon: 'link', + defaultValue: [], + span: 6, + showLabel: true, + labelWidth: null, + layout: 'colFormItem', + required: false, + regList: [], + changeTag: false, + component_id: '', + }, + disabled: false, + vModel: 'category', + isBeta: process.env.VUE_APP_ENVIRONMENT === 'development', + }, + { + __config__: { + label: '品牌', + tag: 'LinkSelectBrandSimple', + type: 'brand', + tagIcon: 'nested', + defaultValue: [], + span: 6, + showLabel: true, + labelWidth: null, + layout: 'colFormItem', + required: false, + regList: [], + changeTag: false, + component_id: '', + }, + style: {}, + disabled: false, + vModel: 'brand', + isBeta: process.env.VUE_APP_ENVIRONMENT === 'development', + }, + { + __config__: { + label: '商品属性', + tag: 'LinkGoodsAttrPicker', + type: 'goodsAttr', + tagIcon: 'tree', + defaultValue: {}, + span: 6, + showLabel: true, + labelWidth: null, + layout: 'colFormItem', + required: false, + regList: [], + changeTag: false, + component_id: '', + }, + style: {}, + disabled: false, + }, + { + __config__: { + label: '活动属性', + tag: 'LinkGoodsAttrPicker', + type: 'activityAttr', + tagIcon: 'tree', + defaultValue: {}, + span: 6, + showLabel: true, + labelWidth: null, + layout: 'colFormItem', + required: false, + regList: [], + changeTag: false, + component_id: '', + remoteSettings: { + url: `${process.env.VUE_APP_CSCS_URL}/cscs-web-in/o/promoattr/getConvertAttrList.do`, + params: { + excludeStatus: 0, + status: 1, + }, + method: 'get', // 请求方法 + result: 'content.result.list', // 返回数据层级,逻辑参考lodash + codeFlag: 'code', + successCode: '0', + }, + }, + style: {}, + disabled: false, + }, + { + __config__: { + label: '商品条码', + tag: 'LinkSelectGoodsBarcode', + type: 'goodsBarcode', + layout: 'colFormItem', + tagIcon: 'nested', + defaultValue: [], + showLabel: true, + labelWidth: null, + required: false, + regList: [], + span: 6, + showTip: false, + component_id: '', + }, + __vModel__: 'goodsBarcode', + placeholder: '请选择', + style: { width: '100%' }, + disabled: false, + }, + // { + // __config__: { + // label: '员工选择组件', + // tag: 'LinkSelectUser', + // type: 'selectUser', + // tagIcon: 'user', + // defaultValue: [], + // span: 6, + // showLabel: true, + // labelWidth: null, + // layout: 'colFormItem', + // required: false, + // regList: [], + // changeTag: false, + // component_id: '', + // }, + // style: {}, + // disabled: false, + // vModel: 'user', + // isBeta: process.env.VUE_APP_ENVIRONMENT === 'development', + // }, + + // { + // __config__: { + // label: '导出组件', + // tag: 'LinkToolExportGroup', + // layout: 'colFormItem', + // tagIcon: 'example', + // defaultValue: null, + // showLabel: false, + // labelWidth: null, + // required: false, + // span: 12, + // showTip: false, + // component_id: '', + // }, + // disabled: false, + // }, + { + __config__: { + label: '供应商', + tag: 'LinkSelectSupplier', + type: 'selectSupplier', + layout: 'colFormItem', + tagIcon: 'nested', + defaultValue: [], + showLabel: true, + labelWidth: null, + required: false, + regList: [], + span: 6, + showTip: false, + component_id: '', + }, + __vModel__: 'selectSupplier', + placeholder: '请选择', + style: { width: '100%' }, + multiple: false, + disabled: false, + }, + { + __config__: { + label: '汇总方式', + tag: 'LinkMoreTab', + type: 'summaryMethod', + placeholder: '', + tagIcon: 'component', + layout: 'colFormItem', + defaultValue: null, + showLabel: true, + labelWidth: null, + required: false, + span: 6, + showTip: false, + regList: [], + changeTag: false, + max: 5, + component_id: '', + }, + __slot__: { + 'list-type': true, + }, + disabled: false, + name: 'file', + alreadyHave: false, // 此字段用于控制汇总方式和导出组件是否可拖动 + vModel: 'supplier', + }, + { + __config__: { + label: '汇总级别', + showLabel: true, + labelWidth: null, + tag: 'LinkCommonSelect', + type: 'summarySelect', + tagIcon: 'select', + layout: 'colFormItem', + span: 6, + required: false, + regList: [], + changeTag: false, + component_id: '', + }, + __slot__: { + options: [], + }, + __vModel__: 'select', + placeholder: '请选择', + style: { width: '100%' }, + clearable: true, + disabled: false, + filterable: false, + multiple: false, + }, +] + +// 布局型组件 【左面板】 +export const layoutComponents = [ + { + __config__: { + layout: 'rowFormItem', + tagIcon: 'row', + label: '行容器', + layoutTree: true, + component_id: '', + }, + type: 'default', + justify: 'start', + align: 'top', + }, +] + +export const EmptyComponents = [ + { + __config__: { + layout: 'colEmptyItem', + tagIcon: 'row', + label: '行容器', + layoutTree: true, + component_id: '', + }, + }, +] diff --git a/src/components/generator/css.js b/src/components/generator/css.js new file mode 100644 index 0000000..c078128 --- /dev/null +++ b/src/components/generator/css.js @@ -0,0 +1,18 @@ +const styles = { + 'el-rate': '.el-rate{display: inline-block; vertical-align: text-top;}', + 'el-upload': '.el-upload__tip{line-height: 1.2;}', +} + +function addCss(cssList, el) { + const css = styles[el.__config__.tag] + css && cssList.indexOf(css) === -1 && cssList.push(css) + if (el.__config__.children) { + el.__config__.children.forEach((el2) => addCss(cssList, el2)) + } +} + +export function makeUpCss(conf) { + const cssList = [] + conf.fields.forEach((el) => addCss(cssList, el)) + return cssList.join('\n') +} diff --git a/src/components/generator/drawingDefalut.js b/src/components/generator/drawingDefalut.js new file mode 100644 index 0000000..2589baa --- /dev/null +++ b/src/components/generator/drawingDefalut.js @@ -0,0 +1,39 @@ +export default [ + { + __config__: { + label: '单行文本', + labelWidth: null, + showLabel: true, + changeTag: true, + tag: 'el-input', + tagIcon: 'input', + defaultValue: undefined, + required: true, + layout: 'colFormItem', + span: 6, + document: 'https://element.eleme.cn/#/zh-CN/component/input', + // 正则校验规则 + regList: [ + { + pattern: '/^1(3|4|5|7|8|9)\\d{9}$/', + message: '手机号格式错误', + }, + ], + }, + // 组件的插槽属性 + __slot__: { + prepend: '', + append: '', + }, + __vModel__: 'mobile', + placeholder: '请输入手机号', + style: { width: '100%' }, + clearable: true, + 'prefix-icon': 'el-icon-mobile', + 'suffix-icon': '', + maxlength: 11, + 'show-word-limit': true, + readonly: false, + disabled: false, + }, +] diff --git a/src/components/generator/html.js b/src/components/generator/html.js new file mode 100644 index 0000000..a4fee41 --- /dev/null +++ b/src/components/generator/html.js @@ -0,0 +1,398 @@ +/* eslint-disable max-len */ +import ruleTrigger from './ruleTrigger' + +let confGlobal +let someSpanIsNot24 + +export function dialogWrapper(str) { + return ` + ${str} +
+ 取消 + 确定 +
+
` +} + +export function vueTemplate(str) { + return `` +} + +export function vueScript(str) { + return `` +} + +export function cssStyle(cssStr) { + return `` +} + +function buildFromBtns(scheme, type) { + let str = '' + if (scheme.formBtns && type === 'file') { + str = ` + 提交 + 重置 + ` + if (someSpanIsNot24) { + str = ` + ${str} + ` + } + } + return str +} + +function buildFormTemplate(scheme, child, type) { + let labelPosition = '' + if (scheme.labelPosition !== 'right') { + labelPosition = `label-position="${scheme.labelPosition}"` + } + const disabled = scheme.disabled ? `:disabled="${scheme.disabled}"` : '' + let str = ` + ${child} + ${buildFromBtns(scheme, type)} + ` + if (someSpanIsNot24) { + str = ` + ${str} + ` + } + return str +} + +// span不为24的用el-col包裹 +function colWrapper(scheme, str) { + if (someSpanIsNot24 || scheme.__config__.span !== 24) { + return ` + ${str} + ` + } + return str +} + +function attrBuilder(el) { + return { + tag: el.__config__.tag, + vModel: `v-model="${confGlobal.formModel}.${el.__vModel__}"`, + clearable: el.clearable ? 'clearable' : '', + placeholder: el.placeholder ? `placeholder="${el.placeholder}"` : '', + width: el.style && el.style.width ? ':style="{width: \'100%\'}"' : '', + disabled: el.disabled ? ":disabled='true'" : '', + } +} + +// el-buttin 子级 +function buildElButtonChild(scheme) { + const children = [] + const slot = scheme.__slot__ || {} + if (slot.default) { + children.push(slot.default) + } + return children.join('\n') +} + +// el-input 子级 +function buildElInputChild(scheme) { + const children = [] + const slot = scheme.__slot__ + if (slot && slot.prepend) { + children.push(``) + } + if (slot && slot.append) { + children.push(``) + } + return children.join('\n') +} + +// el-select 子级 +function buildElSelectChild(scheme) { + const children = [] + const slot = scheme.__slot__ + if (slot && slot.options && slot.options.length) { + children.push( + `` + ) + } + return children.join('\n') +} + +// el-radio-group 子级 +function buildElRadioGroupChild(scheme) { + const children = [] + const slot = scheme.__slot__ + const config = scheme.__config__ + if (slot && slot.options && slot.options.length) { + const tag = config.optionType === 'button' ? 'el-radio-button' : 'el-radio' + const border = config.border ? 'border' : '' + children.push( + `<${tag} v-for="(item, index) in ${scheme.__vModel__}Options" :key="index" :label="item.value" :disabled="item.disabled" ${border}>{{item.label}}` + ) + } + return children.join('\n') +} + +// el-checkbox-group 子级 +function buildElCheckboxGroupChild(scheme) { + const children = [] + const slot = scheme.__slot__ + const config = scheme.__config__ + if (slot && slot.options && slot.options.length) { + const tag = config.optionType === 'button' ? 'el-checkbox-button' : 'el-checkbox' + const border = config.border ? 'border' : '' + children.push( + `<${tag} v-for="(item, index) in ${scheme.__vModel__}Options" :key="index" :label="item.value" :disabled="item.disabled" ${border}>{{item.label}}` + ) + } + return children.join('\n') +} + +// el-upload 子级 +function buildElUploadChild(scheme) { + const list = [] + const config = scheme.__config__ + if (scheme['list-type'] === 'picture-card') list.push('') + else list.push(`${config.buttonText}`) + if (config.showTip) + list.push( + `
只能上传不超过 ${config.fileSize}${config.sizeUnit} 的${scheme.accept}文件
` + ) + return list.join('\n') +} + +const tags = { + 'el-button': (el) => { + const { tag, disabled } = attrBuilder(el) + const type = el.type ? `type="${el.type}"` : '' + const icon = el.icon ? `icon="${el.icon}"` : '' + const round = el.round ? 'round' : '' + const size = el.size ? `size="${el.size}"` : '' + const plain = el.plain ? 'plain' : '' + const circle = el.circle ? 'circle' : '' + let child = buildElButtonChild(el) + + if (child) child = `\n${child}\n` // 换行 + return `<${tag} ${type} ${icon} ${round} ${size} ${plain} ${disabled} ${circle}>${child}` + }, + 'el-input': (el) => { + const { tag, disabled, vModel, clearable, placeholder, width } = attrBuilder(el) + const maxlength = el.maxlength ? `:maxlength="${el.maxlength}"` : '' + const showWordLimit = el['show-word-limit'] ? 'show-word-limit' : '' + const readonly = el.readonly ? 'readonly' : '' + const prefixIcon = el['prefix-icon'] ? `prefix-icon='${el['prefix-icon']}'` : '' + const suffixIcon = el['suffix-icon'] ? `suffix-icon='${el['suffix-icon']}'` : '' + const showPassword = el['show-password'] ? 'show-password' : '' + const type = el.type ? `type="${el.type}"` : '' + const autosize = + el.autosize && el.autosize.minRows + ? `:autosize="{minRows: ${el.autosize.minRows}, maxRows: ${el.autosize.maxRows}}"` + : '' + let child = buildElInputChild(el) + + if (child) child = `\n${child}\n` // 换行 + return `<${tag} ${vModel} ${type} ${placeholder} ${maxlength} ${showWordLimit} ${readonly} ${disabled} ${clearable} ${prefixIcon} ${suffixIcon} ${showPassword} ${autosize} ${width}>${child}` + }, + 'el-input-number': (el) => { + const { tag, disabled, vModel, placeholder } = attrBuilder(el) + const controlsPosition = el['controls-position'] ? `controls-position=${el['controls-position']}` : '' + const min = el.min ? `:min='${el.min}'` : '' + const max = el.max ? `:max='${el.max}'` : '' + const step = el.step ? `:step='${el.step}'` : '' + const stepStrictly = el['step-strictly'] ? 'step-strictly' : '' + const precision = el.precision ? `:precision='${el.precision}'` : '' + + return `<${tag} ${vModel} ${placeholder} ${step} ${stepStrictly} ${precision} ${controlsPosition} ${min} ${max} ${disabled}>` + }, + 'el-select': (el) => { + const { tag, disabled, vModel, clearable, placeholder, width } = attrBuilder(el) + const filterable = el.filterable ? 'filterable' : '' + const multiple = el.multiple ? 'multiple' : '' + let child = buildElSelectChild(el) + + if (child) child = `\n${child}\n` // 换行 + return `<${tag} ${vModel} ${placeholder} ${disabled} ${multiple} ${filterable} ${clearable} ${width}>${child}` + }, + 'el-radio-group': (el) => { + const { tag, disabled, vModel } = attrBuilder(el) + const size = `size="${el.size}"` + let child = buildElRadioGroupChild(el) + + if (child) child = `\n${child}\n` // 换行 + return `<${tag} ${vModel} ${size} ${disabled}>${child}` + }, + 'el-checkbox-group': (el) => { + const { tag, disabled, vModel } = attrBuilder(el) + const size = `size="${el.size}"` + const min = el.min ? `:min="${el.min}"` : '' + const max = el.max ? `:max="${el.max}"` : '' + let child = buildElCheckboxGroupChild(el) + + if (child) child = `\n${child}\n` // 换行 + return `<${tag} ${vModel} ${min} ${max} ${size} ${disabled}>${child}` + }, + 'el-switch': (el) => { + const { tag, disabled, vModel } = attrBuilder(el) + const activeText = el['active-text'] ? `active-text="${el['active-text']}"` : '' + const inactiveText = el['inactive-text'] ? `inactive-text="${el['inactive-text']}"` : '' + const activeColor = el['active-color'] ? `active-color="${el['active-color']}"` : '' + const inactiveColor = el['inactive-color'] ? `inactive-color="${el['inactive-color']}"` : '' + const activeValue = el['active-value'] !== true ? `:active-value='${JSON.stringify(el['active-value'])}'` : '' + const inactiveValue = + el['inactive-value'] !== false ? `:inactive-value='${JSON.stringify(el['inactive-value'])}'` : '' + + return `<${tag} ${vModel} ${activeText} ${inactiveText} ${activeColor} ${inactiveColor} ${activeValue} ${inactiveValue} ${disabled}>` + }, + 'el-cascader': (el) => { + const { tag, disabled, vModel, clearable, placeholder, width } = attrBuilder(el) + const options = el.options ? `:options="${el.__vModel__}Options"` : '' + const props = el.props ? `:props="${el.__vModel__}Props"` : '' + const showAllLevels = el['show-all-levels'] ? '' : ':show-all-levels="false"' + const filterable = el.filterable ? 'filterable' : '' + const separator = el.separator === '/' ? '' : `separator="${el.separator}"` + + return `<${tag} ${vModel} ${options} ${props} ${width} ${showAllLevels} ${placeholder} ${separator} ${filterable} ${clearable} ${disabled}>` + }, + 'el-slider': (el) => { + const { tag, disabled, vModel } = attrBuilder(el) + const min = el.min ? `:min='${el.min}'` : '' + const max = el.max ? `:max='${el.max}'` : '' + const step = el.step ? `:step='${el.step}'` : '' + const range = el.range ? 'range' : '' + const showStops = el['show-stops'] ? `:show-stops="${el['show-stops']}"` : '' + + return `<${tag} ${min} ${max} ${step} ${vModel} ${range} ${showStops} ${disabled}>` + }, + 'el-time-picker': (el) => { + const { tag, disabled, vModel, clearable, placeholder, width } = attrBuilder(el) + const startPlaceholder = el['start-placeholder'] ? `start-placeholder="${el['start-placeholder']}"` : '' + const endPlaceholder = el['end-placeholder'] ? `end-placeholder="${el['end-placeholder']}"` : '' + const rangeSeparator = el['range-separator'] ? `range-separator="${el['range-separator']}"` : '' + const isRange = el['is-range'] ? 'is-range' : '' + const format = el.format ? `format="${el.format}"` : '' + const valueFormat = el['value-format'] ? `value-format="${el['value-format']}"` : '' + const pickerOptions = el['picker-options'] ? `:picker-options='${JSON.stringify(el['picker-options'])}'` : '' + + return `<${tag} ${vModel} ${isRange} ${format} ${valueFormat} ${pickerOptions} ${width} ${placeholder} ${startPlaceholder} ${endPlaceholder} ${rangeSeparator} ${clearable} ${disabled}>` + }, + 'el-date-picker': (el) => { + const { tag, disabled, vModel, clearable, placeholder, width } = attrBuilder(el) + const startPlaceholder = el['start-placeholder'] ? `start-placeholder="${el['start-placeholder']}"` : '' + const endPlaceholder = el['end-placeholder'] ? `end-placeholder="${el['end-placeholder']}"` : '' + const rangeSeparator = el['range-separator'] ? `range-separator="${el['range-separator']}"` : '' + const format = el.format ? `format="${el.format}"` : '' + const valueFormat = el['value-format'] ? `value-format="${el['value-format']}"` : '' + const type = el.type === 'date' ? '' : `type="${el.type}"` + const readonly = el.readonly ? 'readonly' : '' + + return `<${tag} ${type} ${vModel} ${format} ${valueFormat} ${width} ${placeholder} ${startPlaceholder} ${endPlaceholder} ${rangeSeparator} ${clearable} ${readonly} ${disabled}>` + }, + 'el-rate': (el) => { + const { tag, disabled, vModel } = attrBuilder(el) + const max = el.max ? `:max='${el.max}'` : '' + const allowHalf = el['allow-half'] ? 'allow-half' : '' + const showText = el['show-text'] ? 'show-text' : '' + const showScore = el['show-score'] ? 'show-score' : '' + + return `<${tag} ${vModel} ${max} ${allowHalf} ${showText} ${showScore} ${disabled}>` + }, + 'el-color-picker': (el) => { + const { tag, disabled, vModel } = attrBuilder(el) + const size = `size="${el.size}"` + const showAlpha = el['show-alpha'] ? 'show-alpha' : '' + const colorFormat = el['color-format'] ? `color-format="${el['color-format']}"` : '' + + return `<${tag} ${vModel} ${size} ${showAlpha} ${colorFormat} ${disabled}>` + }, + 'el-upload': (el) => { + const { tag } = el.__config__ + const disabled = el.disabled ? ":disabled='true'" : '' + const action = el.action ? `:action="${el.__vModel__}Action"` : '' + const multiple = el.multiple ? 'multiple' : '' + const listType = el['list-type'] !== 'text' ? `list-type="${el['list-type']}"` : '' + const accept = el.accept ? `accept="${el.accept}"` : '' + const name = el.name !== 'file' ? `name="${el.name}"` : '' + const autoUpload = el['auto-upload'] === false ? ':auto-upload="false"' : '' + const beforeUpload = `:before-upload="${el.__vModel__}BeforeUpload"` + const fileList = `:file-list="${el.__vModel__}fileList"` + const ref = `ref="${el.__vModel__}"` + let child = buildElUploadChild(el) + + if (child) child = `\n${child}\n` // 换行 + return `<${tag} ${ref} ${fileList} ${action} ${autoUpload} ${multiple} ${beforeUpload} ${listType} ${accept} ${name} ${disabled}>${child}` + }, + tinymce: (el) => { + const { tag, vModel, placeholder } = attrBuilder(el) + const height = el.height ? `:height="${el.height}"` : '' + const branding = el.branding ? `:branding="${el.branding}"` : '' + return `<${tag} ${vModel} ${placeholder} ${height} ${branding}>` + }, +} + +const layouts = { + colFormItem(scheme) { + const config = scheme.__config__ + let labelWidth = '' + let label = `label="${config.label}"` + if (config.labelWidth && config.labelWidth !== confGlobal.labelWidth) { + labelWidth = `label-width="${config.labelWidth}px"` + } + if (config.showLabel === false) { + labelWidth = 'label-width="0"' + label = '' + } + const required = !ruleTrigger[config.tag] && config.required ? 'required' : '' + const tagDom = tags[config.tag] ? tags[config.tag](scheme) : null + let str = ` + ${tagDom} + ` + str = colWrapper(scheme, str) + return str + }, + rowFormItem(scheme) { + const config = scheme.__config__ + const type = scheme.type === 'default' ? '' : `type="${scheme.type}"` + const justify = scheme.type === 'default' ? '' : `justify="${scheme.justify}"` + const align = scheme.type === 'default' ? '' : `align="${scheme.align}"` + const gutter = scheme.gutter ? `:gutter="${scheme.gutter}"` : '' + const children = config.children.map((el) => layouts[el.__config__.layout](el)) + let str = ` + ${children.join('\n')} + ` + str = colWrapper(scheme, str) + return str + }, +} + +/** + * 组装html代码。【入口函数】 + * @param {Object} formConfig 整个表单配置 + * @param {String} type 生成类型,文件或弹窗等 + */ +export function makeUpHtml(formConfig, type) { + const htmlList = [] + confGlobal = formConfig + // 判断布局是否都沾满了24个栅格,以备后续简化代码结构 + someSpanIsNot24 = formConfig.fields.some((item) => item.__config__.span !== 24) + // 遍历渲染每个组件成html + formConfig.fields.forEach((el) => { + htmlList.push(layouts[el.__config__.layout](el)) + }) + const htmlStr = htmlList.join('\n') + // 将组件代码放进form标签 + let temp = buildFormTemplate(formConfig, htmlStr, type) + // dialog标签包裹代码 + if (type === 'dialog') { + temp = dialogWrapper(temp) + } + confGlobal = null + return temp +} diff --git a/src/components/generator/js.js b/src/components/generator/js.js new file mode 100644 index 0000000..07c538e --- /dev/null +++ b/src/components/generator/js.js @@ -0,0 +1,280 @@ +import { isArray } from 'util' +import { exportDefault, titleCase, deepClone } from '@/utils/index' +import ruleTrigger from './ruleTrigger' + +const units = { + KB: '1024', + MB: '1024 / 1024', + GB: '1024 / 1024 / 1024', +} +let confGlobal +const inheritAttrs = { + file: '', + dialog: 'inheritAttrs: false,', +} + +// 在Created调用函数 +function callInCreated(methodName, created) { + created.push(`this.${methodName}()`) +} + +// 混入处理函数 +function mixinMethod(type) { + const list = [] + const minxins = { + file: confGlobal.formBtns + ? { + submitForm: `submitForm() { + this.$refs['${confGlobal.formRef}'].validate(valid => { + if(!valid) return + // TODO 提交表单 + }) + },`, + resetForm: `resetForm() { + this.$refs['${confGlobal.formRef}'].resetFields() + },`, + } + : null, + dialog: { + onOpen: 'onOpen() {},', + onClose: `onClose() { + this.$refs['${confGlobal.formRef}'].resetFields() + },`, + close: `close() { + this.$emit('update:visible', false) + },`, + handelConfirm: `handelConfirm() { + this.$refs['${confGlobal.formRef}'].validate(valid => { + if(!valid) return + this.close() + }) + },`, + }, + } + + const methods = minxins[type] + if (methods) { + Object.keys(methods).forEach((key) => { + list.push(methods[key]) + }) + } + + return list +} + +// 构建data +function buildData(scheme, dataList) { + const config = scheme.__config__ + if (scheme.__vModel__ === undefined) return + const defaultValue = JSON.stringify(config.defaultValue) + dataList.push(`${scheme.__vModel__}: ${defaultValue},`) +} + +// 构建校验规则 +function buildRules(scheme, ruleList) { + const config = scheme.__config__ + if (scheme.__vModel__ === undefined) return + const rules = [] + if (ruleTrigger[config.tag]) { + if (config.required) { + const type = isArray(config.defaultValue) ? "type: 'array'," : '' + let message = isArray(config.defaultValue) ? `请至少选择一个${config.label}` : scheme.placeholder + if (message === undefined) message = `${config.label}不能为空` + rules.push(`{ required: true, ${type} message: '${message}', trigger: '${ruleTrigger[config.tag]}' }`) + } + if (config.regList && isArray(config.regList)) { + config.regList.forEach((item) => { + if (item.pattern) { + rules.push( + // eslint-disable-next-line no-eval + `{ pattern: ${eval(item.pattern)}, message: '${item.message}', trigger: '${ruleTrigger[config.tag]}' }` + ) + } + }) + } + ruleList.push(`${scheme.__vModel__}: [${rules.join(',')}],`) + } +} + +// 构建options +function buildOptions(scheme, optionsList) { + if (scheme.__vModel__ === undefined) return + // el-cascader直接有options属性,其他组件都是定义在slot中,所以有两处判断 + let { options } = scheme + // eslint-disable-next-line prefer-destructuring + if (!options) options = scheme.__slot__.options + if (scheme.__config__.dataType === 'dynamic') { + options = [] + } + const str = `${scheme.__vModel__}Options: ${JSON.stringify(options)},` + optionsList.push(str) +} + +function buildProps(scheme, propsList) { + const str = `${scheme.__vModel__}Props: ${JSON.stringify(scheme.props.props)},` + propsList.push(str) +} + +// el-upload的BeforeUpload +function buildBeforeUpload(scheme) { + const config = scheme.__config__ + const unitNum = units[config.sizeUnit] + let rightSizeCode = '' + let acceptCode = '' + const returnList = [] + if (config.fileSize) { + rightSizeCode = `let isRightSize = file.size / ${unitNum} < ${config.fileSize} + if(!isRightSize){ + this.$message.error('文件大小超过 ${config.fileSize}${config.sizeUnit}') + }` + returnList.push('isRightSize') + } + if (scheme.accept) { + acceptCode = `let isAccept = new RegExp('${scheme.accept}').test(file.type) + if(!isAccept){ + this.$message.error('应该选择${scheme.accept}类型的文件') + }` + returnList.push('isAccept') + } + const str = `${scheme.__vModel__}BeforeUpload(file) { + ${rightSizeCode} + ${acceptCode} + return ${returnList.join('&&')} + },` + return returnList.length ? str : '' +} + +// el-upload的submit +function buildSubmitUpload(scheme) { + const str = `submitUpload() { + this.$refs['${scheme.__vModel__}'].submit() + },` + return str +} + +function buildOptionMethod(methodName, model, methodList, scheme) { + const config = scheme.__config__ + const str = `${methodName}() { + // 注意:this.$axios是通过Vue.prototype.$axios = axios挂载产生的 + this.$axios({ + method: '${config.method}', + url: '${config.url}' + }).then(resp => { + var { data } = resp + this.${model} = data.${config.dataPath} + }) + },` + methodList.push(str) +} + +// js整体拼接 +function buildexport(conf, type, data, rules, selectOptions, uploadVar, props, methods, created) { + const str = `${exportDefault}{ + ${inheritAttrs[type]} + components: {}, + props: [], + data () { + return { + ${conf.formModel}: { + ${data} + }, + ${conf.formRules}: { + ${rules} + }, + ${uploadVar} + ${selectOptions} + ${props} + } + }, + computed: {}, + watch: {}, + created () { + ${created} + }, + mounted () {}, + methods: { + ${methods} + } +}` + return str +} + +// 构建组件属性 +function buildAttributes(scheme, dataList, ruleList, optionsList, methodList, propsList, uploadVarList, created) { + const config = scheme.__config__ + const slot = scheme.__slot__ + buildData(scheme, dataList) + buildRules(scheme, ruleList) + + // 特殊处理options属性 + if (scheme.options || (slot && slot.options && slot.options.length)) { + buildOptions(scheme, optionsList) + if (config.dataType === 'dynamic') { + const model = `${scheme.__vModel__}Options` + const options = titleCase(model) + const methodName = `get${options}` + buildOptionMethod(methodName, model, methodList, scheme) + callInCreated(methodName, created) + } + } + + // 处理props + if (scheme.props && scheme.props.props) { + buildProps(scheme, propsList) + } + + // 处理el-upload的action + if (scheme.action && config.tag === 'el-upload') { + uploadVarList.push( + `${scheme.__vModel__}Action: '${scheme.action}', + ${scheme.__vModel__}fileList: [],` + ) + methodList.push(buildBeforeUpload(scheme)) + // 非自动上传时,生成手动上传的函数 + if (!scheme['auto-upload']) { + methodList.push(buildSubmitUpload(scheme)) + } + } + + // 构建子级组件属性 + if (config.children) { + config.children.forEach((item) => { + buildAttributes(item, dataList, ruleList, optionsList, methodList, propsList, uploadVarList, created) + }) + } +} + +/** + * 组装js 【入口函数】 + * @param {Object} formConfig 整个表单配置 + * @param {String} type 生成类型,文件或弹窗等 + */ +export function makeUpJs(formConfig, type) { + // eslint-disable-next-line no-multi-assign + confGlobal = formConfig = deepClone(formConfig) + const dataList = [] + const ruleList = [] + const optionsList = [] + const propsList = [] + const methodList = mixinMethod(type) + const uploadVarList = [] + const created = [] + + formConfig.fields.forEach((el) => { + buildAttributes(el, dataList, ruleList, optionsList, methodList, propsList, uploadVarList, created) + }) + + const script = buildexport( + formConfig, + type, + dataList.join('\n'), + ruleList.join('\n'), + optionsList.join('\n'), + uploadVarList.join('\n'), + propsList.join('\n'), + methodList.join('\n'), + created.join('\n') + ) + confGlobal = null + return script +} diff --git a/src/components/generator/ruleTrigger.js b/src/components/generator/ruleTrigger.js new file mode 100644 index 0000000..09effc0 --- /dev/null +++ b/src/components/generator/ruleTrigger.js @@ -0,0 +1,16 @@ +/** + * 用于生成表单校验,指定正则规则的触发方式。 + * 未在此处声明无触发方式的组件将不生成rule!! + */ +export default { + 'el-input': 'blur', + 'el-input-number': 'blur', + 'el-select': 'change', + 'el-radio-group': 'change', + 'el-checkbox-group': 'change', + 'el-cascader': 'change', + 'el-time-picker': 'change', + 'el-date-picker': 'change', + 'el-rate': 'change', + tinymce: 'blur', +} diff --git a/src/components/parser/Parser.vue b/src/components/parser/Parser.vue new file mode 100644 index 0000000..2c04d10 --- /dev/null +++ b/src/components/parser/Parser.vue @@ -0,0 +1,191 @@ + diff --git a/src/components/parser/README.md b/src/components/parser/README.md new file mode 100644 index 0000000..b91be7e --- /dev/null +++ b/src/components/parser/README.md @@ -0,0 +1,17 @@ +## form-generator JSON 解析器 +>用于将form-generator导出的JSON解析成一个表单。 + +### 安装组件 +``` +npm i form-gen-parser +``` +或者 +``` +yarn add form-gen-parser +``` + +### 使用示例 +> [查看在线示例](https://mrhj.gitee.io/form-generator/#/parser) + +示例代码: +> [src\components\parser\example\Index.vue](https://github.com/JakHuang/form-generator/blob/dev/src/components/parser/example/Index.vue) diff --git a/src/components/parser/example/Index.vue b/src/components/parser/example/Index.vue new file mode 100644 index 0000000..87d2a40 --- /dev/null +++ b/src/components/parser/example/Index.vue @@ -0,0 +1,320 @@ + + + + + diff --git a/src/components/parser/index.js b/src/components/parser/index.js new file mode 100644 index 0000000..0a44b2c --- /dev/null +++ b/src/components/parser/index.js @@ -0,0 +1,3 @@ +import Parser from './Parser' + +export default Parser diff --git a/src/components/preview/api/common.js b/src/components/preview/api/common.js new file mode 100644 index 0000000..c16f50c --- /dev/null +++ b/src/components/preview/api/common.js @@ -0,0 +1,196 @@ +import qs from 'qs' +import requestUtil from '@/utils/request' +import { handleEncryptParams } from '@/utils/aesCrypto' + + +// const REPORT_API = +// window.location.host.indexOf('test') !== -1 || window.location.protocol === 'http:' +// ? 'http://test.report.linkkids.cn' +// : 'https://report.linkkids.cn' +// const BASE_API = +// window.location.host.indexOf('test') !== -1 || window.location.protocol === 'http:' +// ? 'http://test.base.linkkids.cn' +// : 'https://base.linkkids.cn' +const BAPI_API = + window.location.host.indexOf('test') !== -1 || window.location.protocol === 'http:' + ? 'http://testbapi.linkkids.cn' + : 'https://bapi.linkkids.cn' +const BAPI_API2 = + window.location.host.indexOf('test') !== -1 || window.location.protocol === 'http:' + ? 'http://bapi.linkkids.cn' + : 'https://bapi.linkkids.cn' + +const ENCRYPT_LIST = [ + '/table/calculateCheck', + '/table/filterCheck', + '/table/saveSetting', + '/content/getTotal', + '/content/getData', + '/content/getTableHeaders', + '/content/getLayOutPageData', + '/content/getLayOutPageTotal', + '/data/getTableHeaders', + '/data/getLayOutPageTotal', + '/data/getLayOutPageData', + '/dataset/executeDataSet', + '/dataset/sqlDataSetSync', + '/dyna/getDynaParams', + '/component/addChart', + '/dashboardfile/save', + 'component/updateComponent', + '/content/saveTableOptions', + 'component/add', +] +const ENCRYPT_SET = new Set(ENCRYPT_LIST) + +export default { + // 请求远程配置 + remoteServiceRequest: async ({ url, params, formData, headers, method = 'post', withCredentials = true }) => { + const newParam = params.param + newParam.drill_condition = JSON.stringify(newParam.drill_condition) === '{}' ? null : newParam.drill_condition + newParam.skip_condition = newParam.skip_condition ? { skip_key: newParam.skip_condition } : null + if (ENCRYPT_SET.has(params.apiCode)) { + params.param = handleEncryptParams(newParam) + } else { + params.param = newParam + } + + const data = { + url: `${url}?${params.apiCode || (formData || {}).apiCode || ''}`, + method, + withCredentials, + [{ + get: 'params', + post: 'data', + put: 'data', + }[method.toLocaleLowerCase()]]: params, + } + if (headers) { + data.headers = headers + data.data = qs.stringify(data.data) + } + // if (['put', 'post'].includes(method.toLocaleLowerCase())) { + // headers = { + // 'Content-Type': 'application/x-www-form-urlencode', + // } + // data.headers = headers + // } + // if (headers) { + // data.headers = headers + // console.log('headers:', headers) + // const contentType = get(headers, 'Content-Type') + // if (contentType && contentType.indexOf('application/x-www-form-urlencode') > -1) { + // data.data = qs.stringify(data.data) + // } + // } + // 把数组参数join + if (data && data.data) { + Object.keys(data.data).forEach((item) => { + if (Array.isArray(data.data[item])) { + data.data[item] = data.data[item].join(',') + } + }) + } + if (data && data.params) { + Object.keys(data.params).forEach((item) => { + if (Array.isArray(data.params[item])) { + data.params[item] = data.params[item].join(',') + } + }) + } + if (formData) { + data.data = formData + } + console.log('转换之后的请求参数为:', data) + const res = await requestUtil(data) + return (res && res.data) || {} + }, + // 导出 + exportData: async (data) => { + const res = await requestUtil({ + url: `${process.env.VUE_APP_BI_DOMAIN}/${process.env.VUE_APP_LINKDATA_GATEWAY || 'linkdata-gateway'}/route?/content/export`, + method: 'post', + data, + }) + return (res && res.data) || {} + }, + // 导入 + addImport: async ({ params, formData: data }) => { + const res = await requestUtil({ + url: `${BAPI_API2}/czyl-file-api/task/addImport.do?${qs.stringify(params)}`, + method: 'post', + data, + headers: { + 'Content-Type': 'application/x-www-form-urlencoded', + }, + }) + return (res && res.data) || {} + }, + // 选项接口--查询默认配置(废弃) + queryTaskFieldConfig: async (data) => { + const res = await requestUtil({ + // url: `${BASE_API}/bmc/field/queryTaskFieldConfig.do`, + url: `${process.env.VUE_APP_BI_DOMAIN}/${process.env.VUE_APP_LINKDATA_GATEWAY || 'linkdata-gateway'}/route?/content/getTableHeaders`, + method: 'post', + data: { + ...data, + apiCode: '/content/getTableHeaders', + dispatcherSystem: 'report', + param: handleEncryptParams({ + report_id: data.report_id, + label_id: data.label_id, + }), + }, + }) + return (res && res.data) || {} + }, + // 选项接口--查询租户配置 + queryUserFieldConfig: async (data) => { + const drill = JSON.stringify(data.drill_condition) === '{}' ? null : data.drill_condition + const skip = data.skip_condition ? { skip_key: data.skip_condition } : null + const res = await requestUtil({ + // url: `${BASE_API}/bmc/field/queryUserFieldConfig.do`, + url: `${process.env.VUE_APP_BI_DOMAIN}/${process.env.VUE_APP_LINKDATA_GATEWAY || 'linkdata-gateway'}/route?/content/getTableHeaders`, + method: 'post', + data: { + apiCode: '/content/getTableHeaders', + dispatcherSystem: 'report', + param: handleEncryptParams({ + report_id: data.report_id, + label_id: data.label_id, + path: data.path, + drill_condition: drill, + skip_condition: skip, + checked_dimensions: data.checked_dimensions, + app_code: data.app_code, + }), + }, + }) + return (res && res.data) || {} + }, + skipKeyGenerator: async (data) => { + const res = await requestUtil({ + url: `${process.env.VUE_APP_BI_DOMAIN}/${process.env.VUE_APP_LINKDATA_GATEWAY || 'linkdata-gateway'}/route?/content/skipParamSave`, + method: 'post', + data: { + apiCode: '/content/skipParamSave', + dispatcherSystem: 'report', + param: { + path: data.path, + skip_condition: data.skipCondition, + app_code: data.app_code, + }, + }, + }) + return (res && res.data) || {} + }, + // 级联品类 + getGoodsCategory: async (params) => { + const res = await requestUtil({ + url: `${BAPI_API}/category-api/categoryNav/qryCategoryList.do`, + method: 'get', + params, + }) + return (res && res.data) || {} + }, +} diff --git a/src/components/preview/api/table.js b/src/components/preview/api/table.js new file mode 100644 index 0000000..e86d2ab --- /dev/null +++ b/src/components/preview/api/table.js @@ -0,0 +1,114 @@ +import qs from 'qs' +import { handleEncryptParams } from '@/utils/aesCrypto' +import request from '@/utils/request' + +const ENCRYPT_LIST = [ + '/table/calculateCheck', + '/table/filterCheck', + '/table/saveSetting', + '/content/getTotal', + '/content/getData', + '/content/getTableHeaders', + '/content/getLayOutPageData', + '/content/getLayOutPageTotal', + '/data/getTableHeaders', + '/data/getLayOutPageTotal', + '/data/getLayOutPageData', + '/dataset/executeDataSet', + '/dataset/sqlDataSetSync', + '/dyna/getDynaParams', + '/component/addChart', + '/dashboardfile/save', + 'component/updateComponent', + '/content/saveTableOptions', + 'component/add', +] +const ENCRYPT_SET = new Set(ENCRYPT_LIST) + +export default { + // 请求远程配置 + remoteServiceRequest: async ({ url, params, formData, headers, method = 'post', withCredentials = true }) => { + const newParam = params.param + newParam.drill_condition = JSON.stringify(newParam.drill_condition) === '{}' ? null : newParam.drill_condition + newParam.skip_condition = newParam.skip_condition ? { skip_key: newParam.skip_condition } : null + if (ENCRYPT_SET.has(params.apiCode)) { + params.param = handleEncryptParams(newParam) + } else { + params.param = newParam + } + + const data = { + url: `${url}?${params.apiCode || (formData || {}).apiCode || ''}`, + method, + withCredentials, + [{ + get: 'params', + post: 'data', + put: 'data', + }[method.toLocaleLowerCase()]]: params, + } + if (headers) { + data.headers = headers + data.data = qs.stringify(data.data) + } + // if (['put', 'post'].includes(method.toLocaleLowerCase())) { + // headers = { + // 'Content-Type': 'application/x-www-form-urlencode', + // } + // data.headers = headers + // } + // if (headers) { + // data.headers = headers + // console.log('headers:', headers) + // const contentType = get(headers, 'Content-Type') + // if (contentType && contentType.indexOf('application/x-www-form-urlencode') > -1) { + // data.data = qs.stringify(data.data) + // } + // } + // 把数组参数join + if (data && data.data) { + Object.keys(data.data).forEach((item) => { + if (Array.isArray(data.data[item])) { + data.data[item] = data.data[item].join(',') + } + }) + } + if (data && data.params) { + Object.keys(data.params).forEach((item) => { + if (Array.isArray(data.params[item])) { + data.params[item] = data.params[item].join(',') + } + }) + } + if (formData) { + data.data = formData + } + console.log('转换之后的请求参数为:', data) + const res = await request(data) + return (res && res.data) || {} + }, + // 选项接口--查询租户配置 + queryUserFieldConfig: async (data) => { + const drill = JSON.stringify(data.drill_condition) === '{}' ? null : data.drill_condition + const skip = data.skip_condition ? { skip_key: data.skip_condition } : null + const res = await request({ + // url: `${BASE_API}/bmc/field/queryUserFieldConfig.do`, + url: `${process.env.VUE_APP_BI_DOMAIN}/${process.env.VUE_APP_LINKDATA_GATEWAY || 'linkdata-gateway'}/route?/content/getTableHeaders`, + method: 'post', + data: { + apiCode: '/content/getTableHeaders', + dispatcherSystem: 'report', + param: handleEncryptParams({ + report_id: data.report_id, + label_id: data.label_id, + path: data.path, + drill_condition: drill, + skip_condition: skip, + checked_dimensions: data.checked_dimensions, + app_code: data.app_code, + }), + }, + }) + return (res && res.data) || {} + }, +} diff --git a/src/components/preview/components/addOrEditDialog.vue b/src/components/preview/components/addOrEditDialog.vue new file mode 100644 index 0000000..7845378 --- /dev/null +++ b/src/components/preview/components/addOrEditDialog.vue @@ -0,0 +1,184 @@ + + + diff --git a/src/components/preview/components/cascader.vue b/src/components/preview/components/cascader.vue new file mode 100644 index 0000000..f398877 --- /dev/null +++ b/src/components/preview/components/cascader.vue @@ -0,0 +1,191 @@ + + + diff --git a/src/components/preview/main.vue b/src/components/preview/main.vue new file mode 100644 index 0000000..fb3acbe --- /dev/null +++ b/src/components/preview/main.vue @@ -0,0 +1,3108 @@ + + + + + + diff --git a/src/components/preview/table.vue b/src/components/preview/table.vue new file mode 100644 index 0000000..37f2723 --- /dev/null +++ b/src/components/preview/table.vue @@ -0,0 +1,642 @@ + + + + diff --git a/src/components/preview/utils.js b/src/components/preview/utils.js new file mode 100644 index 0000000..3040c58 --- /dev/null +++ b/src/components/preview/utils.js @@ -0,0 +1,513 @@ +/* eslint-disable no-restricted-syntax */ +// import { Loading, Message } from 'element-ui' +import qs from 'qs' +import commonApi from './api/common' + +// 递归拿到列的配置,因为列有可能是合并过的 +function getColumn(columns, item) { + // 如果当前列包含了,直接返回 + let column = columns.find((perColumn) => perColumn.field === item.prop) + if (column) { + return column + } + // 如果当前列不包含,则从它的children中去找 + for (let i = 0; i < columns.length; i++) { + if (Array.isArray(columns[i].children)) { + column = getColumn(columns[i].children, item) + if (column) { + return column + } + } + } +} + +/** + * 处理url + * @param {string} url + * @returns {Object} + */ +export const getQueryObject = (url) => { + url = url == null ? window.location.href : url + const search = url.substring(url.lastIndexOf('?') + 1) + const obj = {} + const reg = /([^?&=]+)=([^?&=]*)/g + search.replace(reg, (rs, $1, $2) => { + const name = decodeURIComponent($1) + let val = decodeURIComponent($2) + val = String(val) + obj[name] = val + return rs + }) + return obj +} + +/** + * iframe打开新页面 + * @param str path,如果要跳rmc或者scm,请在path的query中添加domain=scm或者rmc + * @param str 新开iframe名称 + * @param number type 1 打开iframe 2 普通跳转 + * @returns null + */ +export const openInIframe = (path, name = 'tab', type = 1) => { + console.log('打开新窗口', type, path, name) + if (!path) return + const realPath = path.startsWith('http') ? path : `${location.protocol}${path}` + const { domain } = getQueryObject(path) + switch (+type) { + case 1: + console.log('进入跳转1', window.postMessage, parent !== window) + console.log("path.search('/scm/')", getQueryObject(path)) + console.log('domain:', domain) + if (window.postMessage && parent !== window) { + // scm,仅支持短链接 + // if (domain === 'scm') { + // console.log('进入scm跳转', path) + // // 单独给scm做处理,scm中tab标签路由必须是全匹配,不能带多余的参数,是个坑 + // const purePath = path.replace(/(\?|&)domain=scm/, '') + // console.log('处理之后的链接为:', purePath) + // window.parent.postMessage({ type: 'scmTabOperator', addTabPath: purePath }, '*') + // } + // // rmc + // if (path.search('/rmc/') !== -1 || domain === 'rmc') { + console.log('进入rmc跳转') + window.parent.postMessage('openInFarme_' + JSON.stringify({ path: realPath, name }), '*') + // } + } else { + console.log('非iframe打开新窗口:', realPath) + window.open(realPath, '_blank') + } + break + case 2: + console.log('case 2 打开新窗口:', realPath) + window.open(realPath, '_blank') + break + case 3: + console.log('case 3,location', realPath) + location.href = realPath + } +} + +// 操作列点击跳转事件 +export const redirectUrl = ({ row, openUrl }) => { + console.log('openUrl:', openUrl) + if (!openUrl) return + const queryObject = getQueryObject(openUrl) + console.log('queryObject:', queryObject) + const { openType, openTitle } = queryObject + const url = openUrl.split('?')[0] + const urlParams = JSON.parse(JSON.stringify(queryObject)) + delete urlParams.openType + delete urlParams.openTitle + // 动态参数 + const result = {} + Object.keys(urlParams).forEach((i) => { + result[i] = urlParams[i] + if (!urlParams[i]) result[i] = row[i] + }) + if (urlParams.params) { + const remoteParams = JSON.parse(urlParams.params.replace(/'/g, '"')) + Object.keys(remoteParams).forEach((i) => { + result[i] = remoteParams[i] + if (!remoteParams[i]) result[i] = row[i] + }) + } + // delete result.params + console.log('打开的url为:', `${url}?${qs.stringify(result)}`, openTitle, openType) + openInIframe(`${url}?${qs.stringify(result)}`, openTitle, openType) +} + +/* +转换字符串表达式 +data: 要转换的数据 +expression:要转换的表达式 +*/ +export const compileExpression = function (data, expression) { + try { + const keys = Object.keys(data) + // eslint-disable-next-line no-new-func + const f = new Function('row', `const { ${keys.join(',')} } = row;return ${expression}`) + return f(data) + } catch (e) { + console.warn('转换表达式失败', e, expression) + return '' + } +} + +/** + * [isJson 判断是否是json对象] + * @param {[object]} obj [对象] + * @return {Boolean} + */ +export const isJson = (obj) => Object.prototype.toString.call(obj).toLowerCase() === '[object object]' && !obj.length + +/** + * 合并列 + * @param {*} mergeColumns 合并的列,规则为 + * [ + { + "title": "会员信息", // 合并之后列的名称 + "children": [ + "xx", // 每一列的field + "xx", + .... + ] + }, + * @param {*} alreadyColumns 所有列 + * @param {*} position 合并之后在怎么插入到所有列之后,left:最左边,right: 最右边,common:在合并列的第一个位置 + * @returns + */ +export const mergeColumn = (mergeColumns, alreadyColumns, position = 'common') => { + const willDeleteList = [] + // 构造需要合并的列 + if (Array.isArray(mergeColumns) && mergeColumns.length > 0) { + // 遍历需要合并的列配置 + mergeColumns.forEach((item, rootIndex) => { + let currentIndex = Number.MAX_SAFE_INTEGER + const { children } = item + // 判断哪些列需要合并到一起 + if (Array.isArray(children)) { + children.forEach((child, childIndex) => { + // 找出field在列中的位置 + const index = alreadyColumns.findIndex((columns) => { + switch (typeof child) { + case 'string': + return columns.field === child + case 'object': + return columns.field === child.field + } + return -1 + }) + if (index > -1) { + // 如果找到,记下它的位置 + currentIndex = Math.min(index, currentIndex) + children[childIndex] = JSON.parse(JSON.stringify(alreadyColumns[index])) + delete children[childIndex].fixed + willDeleteList.push(alreadyColumns[index].field) + // children[childIndex] = alreadyColumns.splice(index, 1) + // 纪录它上一个值,用来做插入 + if (currentIndex >= 0) { + mergeColumns[rootIndex].firstField = alreadyColumns[currentIndex].field + } else { + mergeColumns[rootIndex].firstField = null + } + } + }) + } else { + console.warn('多表头配置错误:', item) + } + }) + } + switch (position) { + case 'common': { + // 把合并的列加入到列表 + mergeColumns.forEach((item) => { + const { firstField } = item + const firstIndex = alreadyColumns.findIndex((columns) => columns.field === firstField) + alreadyColumns.splice(Math.max(firstIndex, 0), 0, item) + }) + break + } + case 'left': { + alreadyColumns = mergeColumns.concat(alreadyColumns) + break + } + case 'right': { + alreadyColumns = alreadyColumns.concat(mergeColumns) + } + } + // 删除需要合并的列 + willDeleteList.forEach((deleteItem) => { + const index = alreadyColumns.findIndex((item) => item.field === deleteItem) + alreadyColumns.splice(index, 1) + }) + console.log('合并之后的列为:', alreadyColumns) + return alreadyColumns +} + +// 合并编辑列的数据 +// export const mergeEditRowData = (columns, row, params) => { +export const mergeRowData = ({ columns, row, form }) => { + if (Array.isArray(form)) { + form.forEach((item) => { + if (row) { + item.value = row[item.prop] + } + // const currentColumn = columns.find((column) => column.field === item.prop) + const currentColumn = getColumn(columns, item) + if (currentColumn) { + item.title = currentColumn.title + } else { + console.warn('【行编辑】编辑行找不到对应的列名称', item.prop) + } + }) + } else { + console.warn('【行编辑】编辑行配置form不是数组') + } + console.log('合并之后的form:', form) + return form +} + +// 错误消息键 +export const errMsgList = ['message', 'errMsg', 'msg'] + +// 从接口获取msg信息 +export const setErrorMsgFromAPI = function (res, defaultMsg = '操作失败') { + let err = '' + for (let i = 0; i < errMsgList.length; i++) { + if (res[errMsgList[i]]) { + err = res[errMsgList[i]] + break + } + } + defaultMsg = err || defaultMsg + return defaultMsg +} + +// 解析url,目前主要用在编辑场景,弹框编辑,行编辑 +// row:当前行数据 +// url:配置的url规则 +export const compileUrl = (row, url) => { + return url.replace(/\$\{(.+?)\}\$/g, function (item) { + const expression = item.substring(2, item.length - 2) + console.log('expression:', expression) + const value = compileExpression(row, expression) + console.log('value:', value) + if (isJson(value) || Array.isArray(value)) { + return JSON.stringify(value) + } + return value + }) +} + +/** + * 新增和行内编辑,弹框编辑时调用的方法 + * @param {configUrl} 请求的url + * @param {formData} 表单中的数据 + * @param {success} 表单中的数据 + * @param {callback} 成功之后的回调,编辑之后要更新当前列,新增之后刷新列表 + * @param {errorCallback} 失败之后的回调,编辑要恢复数据,新增要清空数据(可不传,关闭弹框已清除) + * @param {type} add or edit + * @param {global} 传入当前上下文,用来做message和loading + * + */ +export const requestEdit = async ({ configUrl, formData, success, callback, errorCallback, type = 'edit', global }) => { + const loading = global.$loading() + try { + const { method, params, header = 'json' } = getQueryObject(configUrl) + const url = configUrl.substring(0, configUrl.indexOf('?')) + const requestParam = {} + requestParam.url = url + requestParam.method = method + let mergeParams = {} + if (type === 'edit') { + // 合并参数, params为url配置的参数,formData为表单修改之后的数据,重复的数据以表单修改的数据为准 + mergeParams = { + ...JSON.parse(params), + ...formData, + } + } else { + mergeParams = { + ...formData, + } + } + requestParam.params = mergeParams + if (header === 'form') { + requestParam.headers = { + 'Content-Type': 'application/x-www-form-urlencoded;charset=UTF-8', + } + } + console.log('【编辑行】请求参数为:', requestParam, this) + const result = await commonApi.remoteServiceRequest(requestParam) + const { key, value } = success + console.log(result[key] === value) + if (result[key] === value) { + // Message.close() + loading.close() + global.$message.success('操作成功') + callback && callback(mergeParams) + } else { + const msg = setErrorMsgFromAPI(result, '操作失败') + // Message.close() + loading.close() + global.$message.warning(msg) + errorCallback && errorCallback() + } + // loading.close() + loading.close() + } catch (e) { + // loading.close() + loading.close() + } +} + +export const formatDate = function (fmt, date) { + let ret + const opt = { + 'Y+': date.getFullYear().toString(), // 年 + 'M+': (date.getMonth() + 1).toString(), // 月 + 'D+': date.getDate().toString(), // 日 + 'h+': date.getHours().toString(), // 时 + 'm+': date.getMinutes().toString(), // 分 + 's+': date.getSeconds().toString(), // 秒 + } + // eslint-disable-next-line no-restricted-syntax + // eslint-disable-next-line guard-for-in + // eslint-disable-next-line no-restricted-syntax + // eslint-disable-next-line guard-for-in + for (const k in opt) { + ret = new RegExp('(' + k + ')').exec(fmt) + if (ret) { + fmt = fmt.replace(ret[1], ret[1].length === 1 ? opt[k] : opt[k].padStart(ret[1].length, '0')) + } + } + return fmt +} + +// 遍历选中的项,目前仅支持两级 +export const getFullPathByNode = function (allSelectedNodes) { + const arr = [] + // 遍历所有选中的节点 + allSelectedNodes.forEach((node) => { + // 如果是一级节点,直接添加 + if (node.level === 1) { + arr.push(node) + } else { + // 如果不是一级节点,找出它的父节点 + const parentNode = node.parent + // 如果父节点没加入,递归找出所有选中的子节点,并且把父节点加入 + if (!arr.find((item) => item.value === parentNode.value)) { + parentNode.children2 = parentNode.children.filter((item) => item.checked) + arr.push(parentNode) + } else if (!Array.isArray(!parentNode.children2)) { + // 如果父节点已经选中,但是没有初始化children2 + parentNode.children2 = parentNode.children.filter((item) => item.checked) + } else if (!parentNode.children2.find((item) => item.value === node.value)) { + // 如果父节点已加入,但是当前节点没加入,把当前节点加入 + console.log('不存在节点,直接添加') + parentNode.children2.push(node) + } + } + }) + console.log('arr:', arr) + return arr +} + +// 递归编辑级联选择组件,获取值 +export const cleanCascaderData = function (arr, res) { + for (let i = 0; i < arr.length; i++) { + res.push({ + value: arr[i].value, + label: arr[i].label, + }) + if (arr[i].children2) { + res[i].children = [] + cleanCascaderData(arr[i].children2, res[i].children) + } + } +} + +// 规范化多级目录的选项 +export const setCascaderItem = function (list, itemLabel, itemValue) { + Array.isArray(list) && + list.forEach((item) => { + item.label = item[itemLabel] + item.value = item[itemValue] + if (Array.isArray(item.children)) { + setCascaderItem(item.children, itemLabel, itemValue) + } + }) + return list +} + +// 大数据默认query配置 +// 大数据需要同时读取数据和汇总数据,type:query 查询数据 type:summary汇总数据 +export const bigDataDefaultConfig = (type = 'query', isBeta) => { + const defaultConfig = { + // url: `//${isBeta ? 'test.' : ''}report.linkkids.cn/lkrpt/o/m/report/queryData.do`, + url: `${process.env.VUE_APP_BI_DOMAIN}/${process.env.VUE_APP_LINKDATA_GATEWAY || 'linkdata-gateway'}/route`, + method: 'post', + page: { + sizeKey: 'page_index', + indexKey: 'page_size', + }, + success: { + key: 'code', + value: 0, + }, + result: 'data', + total: 'data.count', + } + if (type === 'summary') { + // 汇总 + defaultConfig.total = 'total' + defaultConfig.result = 'data' + } + return defaultConfig +} + +// 获取门店数据,假设页面中有多个门店组件 +export const getDepartmentOptions = (searchForm, page) => { + const selectedItems = {} + searchForm.forEach((row) => { + row.forEach((item) => { + if (item.type === 'storeSelect') { + let currentObj = page.$refs[item.prop] + // 如果找到了组件 + if (Array.isArray(currentObj) && currentObj.length > 0) { + currentObj = currentObj[0] + const selectedOptions = page.searchFormData[item.prop] + // console.log('$$$$$$', selectedOptions, selectedOptions.length) + // 如果选中了值 + if (selectedOptions.length > 0) { + selectedItems[item.prop] = selectedOptions + // console.log('####',selectedItems[item.prop] ) + if (Array.isArray(selectedItems[item.prop]) && selectedItems[item.prop].length > 0) { + selectedItems[item.prop] = selectedItems[item.prop].reduce((pre, next) => { + if (!pre) { + return `'${next}'` + } + return `${pre},'${next}'` + }, '') + } + } else if (item.defaultSelectedAll) { + // 没有选中值,并且defaultSelectedAll为true,把所有的值全部带给接口 + selectedItems[item.prop] = currentObj.getAllStoreDepts() + if (Array.isArray(selectedItems[item.prop]) && selectedItems[item.prop].length > 0) { + selectedItems[item.prop] = selectedItems[item.prop].reduce((pre, next) => { + if (!pre) { + return `'${next}'` + } + return `${pre},'${next}'` + }, '') + } + } + } + } + }) + }) + // console.log('&&&&&', selectedItems) + return selectedItems +} + +// 把查询条件中的多选选项改为字符串形式 +// 目前使用场景:查询、导出、url弹框,搜索区域confirm按钮等 +export const setSearchParams = function (moreChoose, isNeedSingleQuotation = true) { + // 把搜索参数带入iframe,数组形式的数据转换为字符串,和查询保持一致 + const searchParams = JSON.parse(JSON.stringify(moreChoose)) + if (searchParams) { + Object.keys(searchParams).forEach((item) => { + if (Array.isArray(searchParams[item]) && searchParams[item].length > 0) { + // searchParams[item] = searchParams[item].join(',') + // to-do 是否全部处理 + if (isNeedSingleQuotation) { + searchParams[item] = searchParams[item].slice(1).reduce((pre, next) => { + return `${pre},'${next}'` + }, `'${searchParams[item][0]}'`) + } else { + searchParams[item] = searchParams[item].join(',') + } + } + }) + } + return searchParams +} diff --git a/src/components/preview/validate.js b/src/components/preview/validate.js new file mode 100644 index 0000000..071f013 --- /dev/null +++ b/src/components/preview/validate.js @@ -0,0 +1,91 @@ +const emailReg = /^\w+([-+.]\w+)*@\w+([-.]\w+)*\.\w+([-.]\w+)*$/ // 邮箱 +const phoneReg = /^(13[0-9]|14[5|7]|15[0|1|2|3|5|6|7|8|9]|18[0|1|2|3|5|6|7|8|9])\d{8}$/ // 手机号 +const charCNReg = /^[\u4e00-\u9fa5]{0,}$/ // 中文 +const charENReg = /^[A-Za-z]+$/ // 英文字符 +const charEnAndNumReg = /^[A-Za-z0-9]+$/ // 英文和数字 + +// const EMPTYMESSAGE = '必填项不能为空' +// const INFO = { +// number: { +// emptyMsg: EMPTYMESSAGE, +// wrongMsg: '请输入数字', +// }, +// email: { +// emptyMsg: EMPTYMESSAGE, +// wrongMsg: '请检查邮箱格式', +// }, +// phone: { +// emptyMsg: EMPTYMESSAGE, +// wrongMsg: '请检查手机号格式', +// }, +// charCN: { +// emptyMsg: EMPTYMESSAGE, +// wrongMsg: '请检查是否输入了非汉字字符', +// }, +// charEN: { +// emptyMsg: EMPTYMESSAGE, +// wrongMsg: '请检查是否输入了非英文字符', +// }, +// charEnAndNumReg: { +// emptyMsg: EMPTYMESSAGE, +// wrongMsg: '请检查是否输入了英文及数字以外的字符', +// }, +// } + +function validateFun(check, value, callback, msg) { + if (!value) { + return callback(new Error(msg)) + } + setTimeout(() => { + if (check) { + callback(new Error(msg)) + } else { + callback() + } + }) +} + +// 纯数字校验 +const number = (rule, value, callback) => { + const check = !Number.isInteger(value) + validateFun(check, value, callback, ' ') +} + +// 邮箱校验 +const email = (rule, value, callback) => { + const check = !emailReg.test(value) + validateFun(check, value, callback, ' ') +} + +// 手机号校验 +const phone = (rule, value, callback) => { + const check = !phoneReg.test(value) + validateFun(check, value, callback, ' ') +} + +// 纯汉字校验 +const charCN = (rule, value, callback) => { + const check = !charCNReg.test(value) + validateFun(check, value, callback, ' ') +} + +// 纯英文字符校验(不区分大小写) +const charEN = (rule, value, callback) => { + const check = !charENReg.test(value) + validateFun(check, value, callback, ' ') +} + +// 英文字符和数字校验(不区分大小写) +const charENandNumber = (rule, value, callback) => { + const check = !charEnAndNumReg.test(value) + validateFun(check, value, callback, ' ') +} + +export default { + number, // 纯数字校验 + email, // 邮箱校验 + phone, // 手机号校验 + charCN, // 纯汉字校验 + charEN, // 纯英文字符校验(不区分大小写) + charENandNumber, // 英文字符和数字校验(不区分大小写) +} diff --git a/src/components/render/render.js b/src/components/render/render.js new file mode 100644 index 0000000..389fa8d --- /dev/null +++ b/src/components/render/render.js @@ -0,0 +1,124 @@ +import { deepClone } from '@/utils/index' + +const componentChild = {} +/** + * 将./slots中的文件挂载到对象componentChild上 + * 文件名为key,对应JSON配置中的__config__.tag + * 文件内容为value,解析JSON配置中的__slot__ + */ +const slotsFiles = require.context('./slots', false, /\.js$/) +const keys = slotsFiles.keys() || [] +keys.forEach((key) => { + const tag = key.replace(/^\.\/(.*)\.\w+$/, '$1') + const value = slotsFiles(key).default + componentChild[tag] = value +}) + +function vModel(dataObject, defaultValue) { + dataObject.props.value = defaultValue + + dataObject.on.input = (val) => { + this.$emit('input', val) + } +} + +function mountSlotFiles(h, confClone, children) { + const childObjs = componentChild[confClone.__config__.tag] + if (childObjs) { + Object.keys(childObjs).forEach((key) => { + const childFunc = childObjs[key] + if (confClone.__slot__ && confClone.__slot__[key]) { + children.push(childFunc(h, confClone, key)) + } + }) + } +} + +function emitEvents(confClone) { + ;['on', 'nativeOn'].forEach((attr) => { + const eventKeyList = Object.keys(confClone[attr] || {}) + eventKeyList.forEach((key) => { + const val = confClone[attr][key] + if (typeof val === 'string') { + confClone[attr][key] = (event) => this.$emit(val, event) + } + }) + }) +} + +function clearAttrs(dataObject) { + delete dataObject.attrs.__config__ + delete dataObject.attrs.__slot__ + delete dataObject.attrs.__methods__ +} + +function buildDataObject(confClone, dataObject) { + Object.keys(confClone).forEach((key) => { + const val = confClone[key] + if (key === '__vModel__') { + vModel.call(this, dataObject, confClone.__config__.defaultValue) + } else if (dataObject[key] !== undefined) { + if ( + dataObject[key] === null || + dataObject[key] instanceof RegExp || + ['boolean', 'string', 'number', 'function'].includes(typeof dataObject[key]) + ) { + dataObject[key] = val + } else if (Array.isArray(dataObject[key])) { + dataObject[key] = [...dataObject[key], ...val] + } else { + dataObject[key] = { ...dataObject[key], ...val } + } + } else { + dataObject.attrs[key] = val + } + }) + + // 清理属性 + clearAttrs(dataObject) +} + +function makeDataObject() { + // 深入数据对象: + // https://cn.vuejs.org/v2/guide/render-function.html#%E6%B7%B1%E5%85%A5%E6%95%B0%E6%8D%AE%E5%AF%B9%E8%B1%A1 + return { + class: {}, + attrs: {}, + props: {}, + domProps: {}, + nativeOn: {}, + on: {}, + style: {}, + directives: [], + scopedSlots: {}, + slot: null, + key: null, + ref: null, + refInFor: true, + } +} + +export default { + props: { + conf: { + type: Object, + required: true, + }, + }, + render(h) { + const dataObject = makeDataObject() + const confClone = deepClone(this.conf) + const children = this.$slots.default || [] + + // 如果slots文件夹存在与当前tag同名的文件,则执行文件中的代码 + mountSlotFiles.call(this, h, confClone, children) + + // 将字符串类型的事件,发送为消息 + emitEvents.call(this, confClone) + + // 将json表单配置转化为vue render可以识别的 “数据对象(dataObject)” + buildDataObject.call(this, confClone, dataObject) + + return h(this.conf.__config__.tag, dataObject, children) + }, +} diff --git a/src/components/render/slots/el-button.js b/src/components/render/slots/el-button.js new file mode 100644 index 0000000..03d801d --- /dev/null +++ b/src/components/render/slots/el-button.js @@ -0,0 +1,5 @@ +export default { + default(h, conf, key) { + return conf.__slot__[key] + }, +} diff --git a/src/components/render/slots/el-checkbox-group.js b/src/components/render/slots/el-checkbox-group.js new file mode 100644 index 0000000..3250889 --- /dev/null +++ b/src/components/render/slots/el-checkbox-group.js @@ -0,0 +1,17 @@ +export default { + options(h, conf, key) { + const list = [] + conf.__slot__.options.forEach((item) => { + if (conf.__config__.optionType === 'button') { + list.push({item.label}) + } else { + list.push( + + {item.label} + + ) + } + }) + return list + }, +} diff --git a/src/components/render/slots/el-input.js b/src/components/render/slots/el-input.js new file mode 100644 index 0000000..3f54898 --- /dev/null +++ b/src/components/render/slots/el-input.js @@ -0,0 +1,8 @@ +export default { + prepend(h, conf, key) { + return + }, + append(h, conf, key) { + return + }, +} diff --git a/src/components/render/slots/el-radio-group.js b/src/components/render/slots/el-radio-group.js new file mode 100644 index 0000000..208cac6 --- /dev/null +++ b/src/components/render/slots/el-radio-group.js @@ -0,0 +1,17 @@ +export default { + options(h, conf, key) { + const list = [] + conf.__slot__.options.forEach((item) => { + if (conf.__config__.optionType === 'button') { + list.push({item.label}) + } else { + list.push( + + {item.label} + + ) + } + }) + return list + }, +} diff --git a/src/components/render/slots/el-select.js b/src/components/render/slots/el-select.js new file mode 100644 index 0000000..09ca4a1 --- /dev/null +++ b/src/components/render/slots/el-select.js @@ -0,0 +1,9 @@ +export default { + options(h, conf, key) { + const list = [] + conf.__slot__.options.forEach((item) => { + list.push() + }) + return list + }, +} diff --git a/src/components/render/slots/el-upload.js b/src/components/render/slots/el-upload.js new file mode 100644 index 0000000..bccd48a --- /dev/null +++ b/src/components/render/slots/el-upload.js @@ -0,0 +1,24 @@ +export default { + 'list-type': (h, conf, key) => { + const list = [] + const config = conf.__config__ + if (conf['list-type'] === 'picture-card') { + list.push() + } else { + list.push( + + {config.buttonText} + + ) + } + if (config.showTip) { + list.push( +
+ 只能上传不超过 {config.fileSize} + {config.sizeUnit} 的{conf.accept}文件 +
+ ) + } + return list + }, +} diff --git a/src/components/targetInfo/index.js b/src/components/targetInfo/index.js new file mode 100644 index 0000000..470df5c --- /dev/null +++ b/src/components/targetInfo/index.js @@ -0,0 +1,9 @@ +// 指标说明 +import RetailTargetInfo from './src/main.vue' + +// 为组件提供 install 安装方法,供按需引入 +RetailTargetInfo.install = function (Vue) { + Vue.component(RetailTargetInfo.name, RetailTargetInfo) +} + +export default RetailTargetInfo diff --git a/src/components/targetInfo/src/api/index.js b/src/components/targetInfo/src/api/index.js new file mode 100644 index 0000000..d5dcdbc --- /dev/null +++ b/src/components/targetInfo/src/api/index.js @@ -0,0 +1,22 @@ +import requestUtil from '@/utils/request' + +const request = requestUtil.axios +export default { + // 查询指标 + getTargetInfo: async (params) => { + const res = await request({ + url: `${process.env.VUE_APP_BI_DOMAIN}/${process.env.VUE_APP_LINKDATA_GATEWAY || 'linkdata-gateway'}/route?/quota/getQuotaList`, + method: 'post', + data: { + apiCode: '/quota/getQuotaList', + dispatcherSystem: 'common', + param: { + table_id: params.table_id, + report_id: params.report_id, + app_code: params.app_code, + }, + }, + }) + return (res && res.data) || {} + }, +} diff --git a/src/components/targetInfo/src/main.vue b/src/components/targetInfo/src/main.vue new file mode 100644 index 0000000..7419657 --- /dev/null +++ b/src/components/targetInfo/src/main.vue @@ -0,0 +1,174 @@ + + + + + diff --git a/src/components/tinymce/README.md b/src/components/tinymce/README.md new file mode 100644 index 0000000..65c01e2 --- /dev/null +++ b/src/components/tinymce/README.md @@ -0,0 +1,3 @@ +## 简介 +富文本编辑器tinymce的一个vue版本封装。使用cdn动态脚本引入的方式加载。 + diff --git a/src/components/tinymce/config.js b/src/components/tinymce/config.js new file mode 100644 index 0000000..74b9140 --- /dev/null +++ b/src/components/tinymce/config.js @@ -0,0 +1,8 @@ +/* eslint-disable max-len */ + +export const plugins = [ + 'advlist anchor autolink autosave code codesample directionality emoticons fullscreen hr image imagetools insertdatetime link lists media nonbreaking noneditable pagebreak paste preview print save searchreplace spellchecker tabfocus table template textpattern visualblocks visualchars wordcount', +] +export const toolbar = [ + 'code searchreplace bold italic underline strikethrough alignleft aligncenter alignright outdent indent blockquote removeformat subscript superscript codesample hr bullist numlist link image charmap preview anchor pagebreak insertdatetime media table emoticons forecolor backcolor fullscreen', +] diff --git a/src/components/tinymce/example/Index.vue b/src/components/tinymce/example/Index.vue new file mode 100644 index 0000000..b7a3bfb --- /dev/null +++ b/src/components/tinymce/example/Index.vue @@ -0,0 +1,26 @@ + + + diff --git a/src/components/tinymce/index.js b/src/components/tinymce/index.js new file mode 100644 index 0000000..1e83179 --- /dev/null +++ b/src/components/tinymce/index.js @@ -0,0 +1,3 @@ +import Index from './index.vue' + +export default Index diff --git a/src/components/tinymce/index.vue b/src/components/tinymce/index.vue new file mode 100644 index 0000000..4b2df8d --- /dev/null +++ b/src/components/tinymce/index.vue @@ -0,0 +1,88 @@ +