├── static ├── .gitkeep └── test.json ├── rs_favicon.ico ├── .eslintignore ├── test ├── unit │ ├── setup.js │ ├── .eslintrc │ ├── specs │ │ └── HelloWorld.spec.js │ └── jest.conf.js └── e2e │ ├── specs │ └── test.js │ ├── custom-assertions │ └── elementCount.js │ ├── nightwatch.conf.js │ └── runner.js ├── config ├── prod.env.js ├── test.env.js ├── dev.env.js └── index.js ├── src ├── assets │ ├── chart │ │ ├── c1.gif │ │ ├── c2.gif │ │ ├── c3.gif │ │ ├── c4.gif │ │ ├── c5.gif │ │ ├── c6.gif │ │ ├── c7.gif │ │ ├── c8.gif │ │ ├── area.gif │ │ ├── bar.gif │ │ ├── c11.gif │ │ ├── c12.gif │ │ ├── c13.gif │ │ ├── c14.gif │ │ ├── c22.gif │ │ ├── c23.gif │ │ ├── c24.gif │ │ ├── c32.gif │ │ ├── c33.gif │ │ ├── c42.gif │ │ ├── c43.gif │ │ ├── c82.gif │ │ └── bar-2.gif │ ├── image │ │ ├── j1.png │ │ ├── j2.png │ │ ├── j3.png │ │ ├── w1.png │ │ ├── w2.png │ │ ├── w3.png │ │ ├── log2.png │ │ ├── xsqq.png │ │ ├── reload.png │ │ ├── wingrip.png │ │ ├── login_bg.jpg │ │ ├── exchangexs1.gif │ │ └── exchangexs2.gif │ └── layout │ │ ├── l1.png │ │ ├── l2.png │ │ ├── l3.png │ │ ├── l4.png │ │ ├── l5.png │ │ └── l6.png ├── common │ ├── serviceNames.js │ ├── errorHandler.js │ ├── Result.js │ ├── globalMixins.js │ ├── service-utils.js │ ├── loadScripts.js │ ├── biConfig.js │ └── index-db.js ├── store │ ├── plugin.js │ └── index.js ├── App.vue ├── view │ ├── NoFind.vue │ ├── Welcome.vue │ ├── bireport │ │ ├── KpiDesc.vue │ │ ├── bireportUtils.js │ │ ├── ReportTablePrint.vue │ │ ├── Print.vue │ │ ├── ReportSave.vue │ │ ├── TableDetailLink.vue │ │ ├── SelectCube.vue │ │ ├── ReportList.vue │ │ ├── chartUtils.js │ │ ├── Table2ChartDailog.vue │ │ ├── ReportParam.vue │ │ └── ChgChartDailog.vue │ ├── model │ │ ├── DsetView.vue │ │ ├── CubeAddGroup.vue │ │ ├── Index.vue │ │ ├── DsetColModify.vue │ │ ├── Cube.vue │ │ ├── Dsource.vue │ │ ├── Dset.vue │ │ └── DsetDynaCol.vue │ ├── portal │ │ ├── PortalShareView.vue │ │ ├── Print.vue │ │ ├── PortalText.vue │ │ ├── SelectDset.vue │ │ ├── view │ │ │ ├── Box.vue │ │ │ └── Table.vue │ │ ├── PortalLayoutDailog.vue │ │ ├── ChartSeriesColor.vue │ │ ├── prop │ │ │ ├── Grid.vue │ │ │ ├── Table.vue │ │ │ ├── Box.vue │ │ │ └── Text.vue │ │ ├── LayoutBottom.vue │ │ ├── PortalPushView.vue │ │ ├── LayoutRight.vue │ │ ├── PortalView.vue │ │ ├── data │ │ │ └── Box.vue │ │ ├── LayoutParam.vue │ │ └── PortalShare.vue │ ├── frame │ │ ├── RoleMenu.vue │ │ └── UserMenu.vue │ └── Main.vue ├── style │ └── mixin.less ├── components │ ├── UserInfo.vue │ ├── OperationDailog.vue │ ├── Password.vue │ └── FrameTop.vue ├── main.js └── router │ └── index.js ├── .editorconfig ├── index.html ├── .gitignore ├── .postcssrc.js ├── .babelrc ├── .eslintrc.js ├── README.md ├── README_en.md └── package.json /static/.gitkeep: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /static/test.json: -------------------------------------------------------------------------------- 1 | { 2 | "name":"jack", 3 | "age":22 4 | } 5 | -------------------------------------------------------------------------------- /rs_favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ruisibi/rsbi-vue/HEAD/rs_favicon.ico -------------------------------------------------------------------------------- /.eslintignore: -------------------------------------------------------------------------------- 1 | /build/ 2 | /config/ 3 | /dist/ 4 | /*.js 5 | /test/unit/coverage/ 6 | -------------------------------------------------------------------------------- /test/unit/setup.js: -------------------------------------------------------------------------------- 1 | import Vue from 'vue' 2 | 3 | Vue.config.productionTip = false 4 | -------------------------------------------------------------------------------- /config/prod.env.js: -------------------------------------------------------------------------------- 1 | 'use strict' 2 | module.exports = { 3 | NODE_ENV: '"production"' 4 | } 5 | -------------------------------------------------------------------------------- /src/assets/chart/c1.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ruisibi/rsbi-vue/HEAD/src/assets/chart/c1.gif -------------------------------------------------------------------------------- /src/assets/chart/c2.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ruisibi/rsbi-vue/HEAD/src/assets/chart/c2.gif -------------------------------------------------------------------------------- /src/assets/chart/c3.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ruisibi/rsbi-vue/HEAD/src/assets/chart/c3.gif -------------------------------------------------------------------------------- /src/assets/chart/c4.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ruisibi/rsbi-vue/HEAD/src/assets/chart/c4.gif -------------------------------------------------------------------------------- /src/assets/chart/c5.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ruisibi/rsbi-vue/HEAD/src/assets/chart/c5.gif -------------------------------------------------------------------------------- /src/assets/chart/c6.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ruisibi/rsbi-vue/HEAD/src/assets/chart/c6.gif -------------------------------------------------------------------------------- /src/assets/chart/c7.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ruisibi/rsbi-vue/HEAD/src/assets/chart/c7.gif -------------------------------------------------------------------------------- /src/assets/chart/c8.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ruisibi/rsbi-vue/HEAD/src/assets/chart/c8.gif -------------------------------------------------------------------------------- /src/assets/image/j1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ruisibi/rsbi-vue/HEAD/src/assets/image/j1.png -------------------------------------------------------------------------------- /src/assets/image/j2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ruisibi/rsbi-vue/HEAD/src/assets/image/j2.png -------------------------------------------------------------------------------- /src/assets/image/j3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ruisibi/rsbi-vue/HEAD/src/assets/image/j3.png -------------------------------------------------------------------------------- /src/assets/image/w1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ruisibi/rsbi-vue/HEAD/src/assets/image/w1.png -------------------------------------------------------------------------------- /src/assets/image/w2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ruisibi/rsbi-vue/HEAD/src/assets/image/w2.png -------------------------------------------------------------------------------- /src/assets/image/w3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ruisibi/rsbi-vue/HEAD/src/assets/image/w3.png -------------------------------------------------------------------------------- /src/assets/chart/area.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ruisibi/rsbi-vue/HEAD/src/assets/chart/area.gif -------------------------------------------------------------------------------- /src/assets/chart/bar.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ruisibi/rsbi-vue/HEAD/src/assets/chart/bar.gif -------------------------------------------------------------------------------- /src/assets/chart/c11.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ruisibi/rsbi-vue/HEAD/src/assets/chart/c11.gif -------------------------------------------------------------------------------- /src/assets/chart/c12.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ruisibi/rsbi-vue/HEAD/src/assets/chart/c12.gif -------------------------------------------------------------------------------- /src/assets/chart/c13.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ruisibi/rsbi-vue/HEAD/src/assets/chart/c13.gif -------------------------------------------------------------------------------- /src/assets/chart/c14.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ruisibi/rsbi-vue/HEAD/src/assets/chart/c14.gif -------------------------------------------------------------------------------- /src/assets/chart/c22.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ruisibi/rsbi-vue/HEAD/src/assets/chart/c22.gif -------------------------------------------------------------------------------- /src/assets/chart/c23.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ruisibi/rsbi-vue/HEAD/src/assets/chart/c23.gif -------------------------------------------------------------------------------- /src/assets/chart/c24.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ruisibi/rsbi-vue/HEAD/src/assets/chart/c24.gif -------------------------------------------------------------------------------- /src/assets/chart/c32.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ruisibi/rsbi-vue/HEAD/src/assets/chart/c32.gif -------------------------------------------------------------------------------- /src/assets/chart/c33.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ruisibi/rsbi-vue/HEAD/src/assets/chart/c33.gif -------------------------------------------------------------------------------- /src/assets/chart/c42.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ruisibi/rsbi-vue/HEAD/src/assets/chart/c42.gif -------------------------------------------------------------------------------- /src/assets/chart/c43.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ruisibi/rsbi-vue/HEAD/src/assets/chart/c43.gif -------------------------------------------------------------------------------- /src/assets/chart/c82.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ruisibi/rsbi-vue/HEAD/src/assets/chart/c82.gif -------------------------------------------------------------------------------- /src/assets/image/log2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ruisibi/rsbi-vue/HEAD/src/assets/image/log2.png -------------------------------------------------------------------------------- /src/assets/image/xsqq.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ruisibi/rsbi-vue/HEAD/src/assets/image/xsqq.png -------------------------------------------------------------------------------- /src/assets/layout/l1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ruisibi/rsbi-vue/HEAD/src/assets/layout/l1.png -------------------------------------------------------------------------------- /src/assets/layout/l2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ruisibi/rsbi-vue/HEAD/src/assets/layout/l2.png -------------------------------------------------------------------------------- /src/assets/layout/l3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ruisibi/rsbi-vue/HEAD/src/assets/layout/l3.png -------------------------------------------------------------------------------- /src/assets/layout/l4.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ruisibi/rsbi-vue/HEAD/src/assets/layout/l4.png -------------------------------------------------------------------------------- /src/assets/layout/l5.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ruisibi/rsbi-vue/HEAD/src/assets/layout/l5.png -------------------------------------------------------------------------------- /src/assets/layout/l6.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ruisibi/rsbi-vue/HEAD/src/assets/layout/l6.png -------------------------------------------------------------------------------- /src/assets/chart/bar-2.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ruisibi/rsbi-vue/HEAD/src/assets/chart/bar-2.gif -------------------------------------------------------------------------------- /src/assets/image/reload.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ruisibi/rsbi-vue/HEAD/src/assets/image/reload.png -------------------------------------------------------------------------------- /src/assets/image/wingrip.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ruisibi/rsbi-vue/HEAD/src/assets/image/wingrip.png -------------------------------------------------------------------------------- /test/unit/.eslintrc: -------------------------------------------------------------------------------- 1 | { 2 | "env": { 3 | "jest": true 4 | }, 5 | "globals": { 6 | } 7 | } 8 | -------------------------------------------------------------------------------- /src/assets/image/login_bg.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ruisibi/rsbi-vue/HEAD/src/assets/image/login_bg.jpg -------------------------------------------------------------------------------- /src/assets/image/exchangexs1.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ruisibi/rsbi-vue/HEAD/src/assets/image/exchangexs1.gif -------------------------------------------------------------------------------- /src/assets/image/exchangexs2.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ruisibi/rsbi-vue/HEAD/src/assets/image/exchangexs2.gif -------------------------------------------------------------------------------- /src/common/serviceNames.js: -------------------------------------------------------------------------------- 1 | let version = "rsbi-os-4.7"; 2 | export default { 3 | "Login":`/${version}/doLogin/action`,//登录 4 | } 5 | -------------------------------------------------------------------------------- /src/store/plugin.js: -------------------------------------------------------------------------------- 1 | export const plugin = store => { 2 | store.subscribe((mutation, state) => { 3 | localStorage.setItem("state",JSON.stringify(state)); 4 | }) 5 | } 6 | -------------------------------------------------------------------------------- /config/test.env.js: -------------------------------------------------------------------------------- 1 | 'use strict' 2 | const merge = require('webpack-merge') 3 | const devEnv = require('./dev.env') 4 | 5 | module.exports = merge(devEnv, { 6 | NODE_ENV: '"testing"' 7 | }) 8 | -------------------------------------------------------------------------------- /config/dev.env.js: -------------------------------------------------------------------------------- 1 | 'use strict' 2 | const merge = require('webpack-merge') 3 | const prodEnv = require('./prod.env') 4 | 5 | module.exports = merge(prodEnv, { 6 | NODE_ENV: '"development"' 7 | }) 8 | -------------------------------------------------------------------------------- /.editorconfig: -------------------------------------------------------------------------------- 1 | root = true 2 | 3 | [*] 4 | charset = utf-8 5 | indent_style = space 6 | indent_size = 2 7 | end_of_line = lf 8 | insert_final_newline = true 9 | trim_trailing_whitespace = true 10 | -------------------------------------------------------------------------------- /index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 睿思BI开源版 7 | 8 | 9 |
10 | 11 | 12 | -------------------------------------------------------------------------------- /src/App.vue: -------------------------------------------------------------------------------- 1 | 6 | 7 | 12 | 13 | 16 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | .DS_Store 2 | node_modules/ 3 | /dist/ 4 | npm-debug.log* 5 | yarn-debug.log* 6 | yarn-error.log* 7 | /test/unit/coverage/ 8 | /test/e2e/reports/ 9 | selenium-debug.log 10 | 11 | # Editor directories and files 12 | .idea 13 | .vscode 14 | *.suo 15 | *.ntvs* 16 | *.njsproj 17 | *.sln 18 | -------------------------------------------------------------------------------- /.postcssrc.js: -------------------------------------------------------------------------------- 1 | // https://github.com/michael-ciniawsky/postcss-load-config 2 | 3 | module.exports = { 4 | "plugins": { 5 | "postcss-import": {}, 6 | "postcss-url": {}, 7 | // to edit target browsers: use "browserslist" field in package.json 8 | "autoprefixer": {} 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /test/unit/specs/HelloWorld.spec.js: -------------------------------------------------------------------------------- 1 | import Vue from 'vue' 2 | import HelloWorld from '@/components/HelloWorld' 3 | 4 | describe('HelloWorld.vue', () => { 5 | it('should render correct contents', () => { 6 | const Constructor = Vue.extend(HelloWorld) 7 | const vm = new Constructor().$mount() 8 | expect(vm.$el.querySelector('.hello h1').textContent) 9 | .toEqual('Welcome to Your Vue.js App') 10 | }) 11 | }) 12 | -------------------------------------------------------------------------------- /src/store/index.js: -------------------------------------------------------------------------------- 1 | import Vue from 'vue' 2 | import Vuex from 'vuex' 3 | import {plugin} from "./plugin.js" 4 | Vue.use(Vuex) 5 | 6 | 7 | let initState = { 8 | count: 0 9 | } 10 | let state = JSON.parse(localStorage.getItem("state")) || initState; 11 | export const store = new Vuex.Store({ 12 | plugins: [plugin], 13 | state: state, 14 | mutations: { 15 | increment (state) { 16 | state.count++ 17 | } 18 | } 19 | }) 20 | -------------------------------------------------------------------------------- /src/common/errorHandler.js: -------------------------------------------------------------------------------- 1 | 2 | 3 | export let handleVueError = (err, vm, info) => { 4 | console.error(err, vm, info); 5 | } 6 | export let handleVueWarning = (msg, vm, trace) => { 7 | console.warn(msg, vm, trace); 8 | } 9 | export let handleGlobalError = (message, source, lineno, colno, error) => { 10 | console.error(message, source, lineno, colno, error); 11 | } 12 | export let handleGlobalRejection = (e) => { 13 | console.error(e); 14 | } 15 | -------------------------------------------------------------------------------- /.babelrc: -------------------------------------------------------------------------------- 1 | { 2 | "presets": [ 3 | ["env", { 4 | "modules": false, 5 | "targets": { 6 | "browsers": ["> 1%", "last 2 versions", "not ie <= 8"] 7 | } 8 | }], 9 | "stage-2" 10 | ], 11 | "plugins": ["transform-vue-jsx", "transform-runtime"], 12 | "env": { 13 | "test": { 14 | "presets": ["env", "stage-2"], 15 | "plugins": ["transform-vue-jsx", "transform-es2015-modules-commonjs", "dynamic-import-node"] 16 | } 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /src/common/Result.js: -------------------------------------------------------------------------------- 1 | 2 | 3 | export class Result{ 4 | status = 0; 5 | data = {}; 6 | msg = ""; 7 | constructor(options = {}){ 8 | this.status = options.status || 0; 9 | this.data = options.data || {}; 10 | this.msg = options.msg || ""; 11 | } 12 | static success = options => new Result(Object.assign(options,{status:1})); 13 | static fail = options => new Result(Object.assign(options,{status:0})); 14 | static build = res => new Result(res); 15 | get isSuccess(){ 16 | return this.status === 1; 17 | } 18 | } 19 | 20 | -------------------------------------------------------------------------------- /src/view/NoFind.vue: -------------------------------------------------------------------------------- 1 | 8 | 9 | 32 | 33 | 36 | -------------------------------------------------------------------------------- /test/e2e/specs/test.js: -------------------------------------------------------------------------------- 1 | // For authoring Nightwatch tests, see 2 | // http://nightwatchjs.org/guide#usage 3 | 4 | module.exports = { 5 | 'default e2e tests': function (browser) { 6 | // automatically uses dev Server port from /config.index.js 7 | // default: http://localhost:8080 8 | // see nightwatch.conf.js 9 | const devServer = browser.globals.devServerURL 10 | 11 | browser 12 | .url(devServer) 13 | .waitForElementVisible('#app', 5000) 14 | .assert.elementPresent('.hello') 15 | .assert.containsText('h1', 'Welcome to Your Vue.js App') 16 | .assert.elementCount('img', 1) 17 | .end() 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /test/unit/jest.conf.js: -------------------------------------------------------------------------------- 1 | const path = require('path') 2 | 3 | module.exports = { 4 | rootDir: path.resolve(__dirname, '../../'), 5 | moduleFileExtensions: [ 6 | 'js', 7 | 'json', 8 | 'vue' 9 | ], 10 | moduleNameMapper: { 11 | '^@/(.*)$': '/src/$1' 12 | }, 13 | transform: { 14 | '^.+\\.js$': '/node_modules/babel-jest', 15 | '.*\\.(vue)$': '/node_modules/vue-jest' 16 | }, 17 | testPathIgnorePatterns: [ 18 | '/test/e2e' 19 | ], 20 | snapshotSerializers: ['/node_modules/jest-serializer-vue'], 21 | setupFiles: ['/test/unit/setup'], 22 | mapCoverage: true, 23 | coverageDirectory: '/test/unit/coverage', 24 | collectCoverageFrom: [ 25 | 'src/**/*.{js,vue}', 26 | '!src/main.js', 27 | '!src/router/index.js', 28 | '!**/node_modules/**' 29 | ] 30 | } 31 | -------------------------------------------------------------------------------- /test/e2e/custom-assertions/elementCount.js: -------------------------------------------------------------------------------- 1 | // A custom Nightwatch assertion. 2 | // The assertion name is the filename. 3 | // Example usage: 4 | // 5 | // browser.assert.elementCount(selector, count) 6 | // 7 | // For more information on custom assertions see: 8 | // http://nightwatchjs.org/guide#writing-custom-assertions 9 | 10 | exports.assertion = function (selector, count) { 11 | this.message = 'Testing if element <' + selector + '> has count: ' + count 12 | this.expected = count 13 | this.pass = function (val) { 14 | return val === this.expected 15 | } 16 | this.value = function (res) { 17 | return res.value 18 | } 19 | this.command = function (cb) { 20 | var self = this 21 | return this.api.execute(function (selector) { 22 | return document.querySelectorAll(selector).length 23 | }, [selector], function (res) { 24 | cb.call(self, res) 25 | }) 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /.eslintrc.js: -------------------------------------------------------------------------------- 1 | // https://eslint.org/docs/user-guide/configuring 2 | 3 | module.exports = { 4 | root: true, 5 | parserOptions: { 6 | parser: 'babel-eslint' 7 | }, 8 | env: { 9 | browser: true, 10 | }, 11 | extends: [ 12 | // https://github.com/vuejs/eslint-plugin-vue#priority-a-essential-error-prevention 13 | // consider switching to `plugin:vue/strongly-recommended` or `plugin:vue/recommended` for stricter rules. 14 | 'plugin:vue/essential', 15 | // https://github.com/standard/standard/blob/master/docs/RULES-en.md 16 | 'standard' 17 | ], 18 | // required to lint *.vue files 19 | plugins: [ 20 | 'vue' 21 | ], 22 | // add your custom rules here 23 | rules: { 24 | // allow async-await 25 | 'generator-star-spacing': 'off', 26 | // allow debugger during development 27 | 'no-debugger': process.env.NODE_ENV === 'production' ? 'error' : 'off' 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /src/view/Welcome.vue: -------------------------------------------------------------------------------- 1 | 23 | 24 | 45 | 46 | 49 | -------------------------------------------------------------------------------- /test/e2e/nightwatch.conf.js: -------------------------------------------------------------------------------- 1 | require('babel-register') 2 | var config = require('../../config') 3 | 4 | // http://nightwatchjs.org/gettingstarted#settings-file 5 | module.exports = { 6 | src_folders: ['test/e2e/specs'], 7 | output_folder: 'test/e2e/reports', 8 | custom_assertions_path: ['test/e2e/custom-assertions'], 9 | 10 | selenium: { 11 | start_process: true, 12 | server_path: require('selenium-server').path, 13 | host: '127.0.0.1', 14 | port: 4444, 15 | cli_args: { 16 | 'webdriver.chrome.driver': require('chromedriver').path 17 | } 18 | }, 19 | 20 | test_settings: { 21 | default: { 22 | selenium_port: 4444, 23 | selenium_host: 'localhost', 24 | silent: true, 25 | globals: { 26 | devServerURL: 'http://localhost:' + (process.env.PORT || config.dev.port) 27 | } 28 | }, 29 | 30 | chrome: { 31 | desiredCapabilities: { 32 | browserName: 'chrome', 33 | javascriptEnabled: true, 34 | acceptSslCerts: true 35 | } 36 | }, 37 | 38 | firefox: { 39 | desiredCapabilities: { 40 | browserName: 'firefox', 41 | javascriptEnabled: true, 42 | acceptSslCerts: true 43 | } 44 | } 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /src/common/globalMixins.js: -------------------------------------------------------------------------------- 1 | import {sendRequest} from "./service-utils"; 2 | import {Result} from "../common/Result.js"; 3 | import {handleVueError,handleVueWarning,handleGlobalError,handleGlobalRejection} from "./errorHandler.js"; 4 | import {loadScripts,loadCss,removeScripts,removeCss} from "./loadScripts.js"; 5 | 6 | window.Result = Result; 7 | export const globalPlugin = { 8 | install(Vue){ 9 | Vue.config.productionTip = false; 10 | Vue.prototype.$sendRequest = sendRequest.bind(Vue.prototype,Vue.prototype); 11 | Vue.prototype.$isDev = process.env.NODE_ENV == 'development'; 12 | Vue.config.errorHandler = handleVueError; 13 | Vue.config.warnHandler = handleVueWarning; 14 | window.onerror = handleGlobalError; 15 | window.onunhandledrejection = handleGlobalRejection; 16 | Vue.prototype.loadScripts = loadScripts; 17 | Vue.prototype.loadCss = loadCss; 18 | Vue.prototype.removeScripts = removeScripts; 19 | Vue.prototype.removeCss = removeCss; 20 | } 21 | } 22 | export const globalMixins = { 23 | data(){ 24 | return{ 25 | 26 | } 27 | }, 28 | methods:{}, 29 | mounted(){ 30 | if(this.$isDev){ 31 | (window.comps || (window.comps = {}))[this.$options.name || "anonymous"] = this; 32 | } 33 | } 34 | } 35 | 36 | -------------------------------------------------------------------------------- /src/style/mixin.less: -------------------------------------------------------------------------------- 1 | @blue: #3190e8; 2 | @bc: #e4e4e4; 3 | @fc:#fff; 4 | 5 | // 背景图片地址和大小 6 | .bis(@url) { 7 | background-image: url(@url); 8 | background-repeat: no-repeat; 9 | background-size: 100% 100%; 10 | } 11 | 12 | //定位全屏 13 | .allcover{ 14 | position:absolute; 15 | top:0; 16 | right:0; 17 | } 18 | 19 | //transform上下左右居中 20 | .ctt { 21 | position: absolute; 22 | top: 50%; 23 | left: 50%; 24 | transform: translate(-50%, -50%); 25 | } 26 | //定位上下左右居中 27 | .ctp(@width, @height) { 28 | position: absolute; 29 | top: 50%; 30 | left: 50%; 31 | margin-top: -@height/2; 32 | margin-left: -@width/2; 33 | } 34 | 35 | //定位上下居中 36 | .tb { 37 | position: absolute; 38 | top: 50%; 39 | transform: translateY(-50%); 40 | } 41 | 42 | //定位左右居中 43 | .lr { 44 | position: absolute; 45 | left: 50%; 46 | transform: translateX(-50%); 47 | } 48 | 49 | //宽高 50 | .wh(@width, @height){ 51 | width: @width; 52 | height: @height; 53 | } 54 | 55 | //字体大小、行高、字体 56 | .ft(@size, @line-height) { 57 | font-size: @size; 58 | line-height:@line-height; 59 | } 60 | 61 | //字体大小,颜色 62 | .sc(@size, @color){ 63 | font-size: @size; 64 | color: @color; 65 | } 66 | 67 | //flex 布局和 子元素 对其方式 68 | .fj(@type: space-between){ 69 | display: flex; 70 | justify-content: @type; 71 | 72 | } -------------------------------------------------------------------------------- /src/view/bireport/KpiDesc.vue: -------------------------------------------------------------------------------- 1 | 15 | 16 | 48 | 49 | 52 | -------------------------------------------------------------------------------- /src/view/model/DsetView.vue: -------------------------------------------------------------------------------- 1 | 13 | 14 | 55 | 56 | 59 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # 睿思BI-开源版-前端 2 | 3 | - zh_CN [简体中文](README.md) 4 | - en [English](README_en.md) 5 | 6 | 睿思bi开源版前端框架-基于VUE
7 | ⚠️ 此项目后端框架基于springboot, 地址:https://github.com/ruisibi/rsbi-os ⚠️
8 | 9 | “睿思BI”商业智能系统是由[成都睿思商智科技有限公司](https://www.ruisitech.com)自主研发的企业数据分析系统。 开源版包含数据建模、数据报表、多维分析、权限管理等功能模块,方便用户快速建立一套易用,灵活、免费的数据分析平台,实现数据的快速分析及可视化。
10 | 11 | 快速开始:https://blog.csdn.net/zhuifengsn/article/details/138605460
12 | 13 | # 产品特点:
14 | 1.轻量级BI, 支持快速建模,快速可视化数据。
15 | 2.多维分析功能强大,支持下钻/上卷/排序/筛选/计算/聚合等多种操作方式。
16 | 3.报表使用简单,功能强大,通过拖放等方式构建分析界面, 0代码编写。
17 | 4.开放源码,采用apache2.0开源协议,用户可任意使用而不需我公司授权(企业版除外)。
18 |   19 | # 系统功能:
20 | 1.数据建模 (支持:mysql/oracle/sqlserver/db2/postgresql/hive/kylin)
21 | 2.多维分析
22 | 3.数据报表
23 | 4.权限管理
24 | 25 | # 技术支持:
26 | 请加QQ群 648548832, 此群为睿思bi技术交流。
27 |

28 | 29 | 文档地址: http://www.ruisibi.cn/book.htm
30 | 演示地址: http://bi.ruisitech.com/
31 |

32 | 33 | # 产品截图:
34 | 数据建模
35 | ![olap](https://www.ruisitech.com/img/kybpic0.jpg?v4)  
36 | 多维分析
37 | ![1](https://www.ruisitech.com/img/kybpic1.jpg?v5)  
38 | 数据报表
39 | ![2](https://www.ruisitech.com/img/kybpic2.jpg?v3)  
40 | 41 | ## Build Setup 42 | 43 | ``` bash 44 | # install dependencies 45 | npm install 46 | 47 | # serve with hot reload at localhost:8080 48 | npm run dev 49 | 50 | # build for production with minification 51 | npm run build 52 | ``` 53 | -------------------------------------------------------------------------------- /src/common/service-utils.js: -------------------------------------------------------------------------------- 1 | import $ from 'jquery' 2 | import {Result} from "./Result.js" 3 | 4 | export const sendRequest = (ins,url,params,showLoading=true,showError=true) => { 5 | return new Promise((resolve,reject) => { 6 | let loadingIns = null; 7 | if(showLoading){ 8 | loadingIns = ins.$loading(); 9 | } 10 | let o = { 11 | type: "POST", 12 | data:params, 13 | dataType:"JSON", 14 | xhrFields: {withCredentials: true}, 15 | contentType:"application/json; charset=utf-8", 16 | crossDomain: true, 17 | url:url, 18 | success:function(resp){ 19 | if(resp.result === 1){ 20 | resolve(Result.success({data:resp})) 21 | }else{ 22 | if(showError) ins.$notify.error({title: '系统出错',message:resp.msg,offset: 50}); 23 | resolve(Result.fail({data:resp})) 24 | } 25 | }, 26 | error: function(resp){ 27 | if(showError) ins.$notify.error({title: '系统出错',offset: 50}); 28 | resolve(Result.fail({msg:"系统出错",data:resp})) 29 | }, 30 | complete:function(resp){ 31 | if(showLoading){ 32 | setTimeout(() => { 33 | loadingIns.close(); 34 | },1000) 35 | } 36 | } 37 | }; 38 | try{ 39 | $.ajax(o); 40 | }catch(e){ 41 | if(showLoading){ 42 | setTimeout(() => { 43 | loadingIns.close(); 44 | },1000) 45 | } 46 | if(showError) ins.$notify.error({title: '系统出错',offset: 50}); 47 | resolve(Result.fail({msg:"程序出错"})) 48 | }finally{ 49 | 50 | } 51 | 52 | }); 53 | } 54 | -------------------------------------------------------------------------------- /src/components/UserInfo.vue: -------------------------------------------------------------------------------- 1 | 22 | 23 | 51 | 52 | 55 | -------------------------------------------------------------------------------- /src/main.js: -------------------------------------------------------------------------------- 1 | // The Vue build version to load with the `import` command 2 | // (runtime-only or standalone) has been set in webpack.base.conf with an alias. 3 | import Vue from 'vue' 4 | import Vuex from 'vuex' 5 | import VueI18n from 'vue-i18n' 6 | import App from './App' 7 | import router from './router' 8 | import ElementUI from 'element-ui' 9 | import 'element-ui/lib/theme-chalk/index.css' 10 | import 'bootstrap3/dist/css/bootstrap.min.css' 11 | import 'font-awesome/css/font-awesome.css' 12 | import {globalMixins,globalPlugin} from "./common/globalMixins.js" 13 | import {store} from "./store/index.js"; 14 | 15 | //配置elementui 的国际化 16 | import enlang from 'element-ui/lib/locale/lang/en' 17 | import zhlang from 'element-ui/lib/locale/lang/zh-CN' 18 | import twlang from 'element-ui/lib/locale/lang/zh-TW' 19 | import locale from 'element-ui/lib/locale' 20 | 21 | import zh from './language/zh.js' 22 | import zhHant from './language/zh-hant.js' 23 | import en from './language/en.js' 24 | 25 | Vue.use(ElementUI); 26 | Vue.use(globalPlugin); 27 | Vue.mixin(globalMixins); 28 | Vue.use(VueI18n); 29 | 30 | const messages = { 31 | en: en, 32 | zh: zh, 33 | zhHant: zhHant 34 | } 35 | 36 | const i18n = new VueI18n({ 37 | locale: 'zh', // 设置默认语言 38 | fallbackLocale:'zh', 39 | messages 40 | }) 41 | 42 | if(i18n.locale == 'en'){ 43 | locale.use(enlang) 44 | }else if(i18n.locale == 'zh'){ 45 | locale.use(zhlang) 46 | }else if(i18n.locale == 'zhHant'){ 47 | locale.use(twlang) 48 | } 49 | 50 | /* eslint-disable no-new */ 51 | new Vue({ 52 | el: '#app', 53 | router, 54 | store, 55 | i18n, 56 | components: { App }, 57 | template: '' 58 | }) 59 | 60 | export { 61 | i18n 62 | } 63 | -------------------------------------------------------------------------------- /test/e2e/runner.js: -------------------------------------------------------------------------------- 1 | // 1. start the dev server using production config 2 | process.env.NODE_ENV = 'testing' 3 | 4 | const webpack = require('webpack') 5 | const DevServer = require('webpack-dev-server') 6 | 7 | const webpackConfig = require('../../build/webpack.prod.conf') 8 | const devConfigPromise = require('../../build/webpack.dev.conf') 9 | 10 | let server 11 | 12 | devConfigPromise.then(devConfig => { 13 | const devServerOptions = devConfig.devServer 14 | const compiler = webpack(webpackConfig) 15 | server = new DevServer(compiler, devServerOptions) 16 | const port = devServerOptions.port 17 | const host = devServerOptions.host 18 | return server.listen(port, host) 19 | }) 20 | .then(() => { 21 | // 2. run the nightwatch test suite against it 22 | // to run in additional browsers: 23 | // 1. add an entry in test/e2e/nightwatch.conf.js under "test_settings" 24 | // 2. add it to the --env flag below 25 | // or override the environment flag, for example: `npm run e2e -- --env chrome,firefox` 26 | // For more information on Nightwatch's config file, see 27 | // http://nightwatchjs.org/guide#settings-file 28 | let opts = process.argv.slice(2) 29 | if (opts.indexOf('--config') === -1) { 30 | opts = opts.concat(['--config', 'test/e2e/nightwatch.conf.js']) 31 | } 32 | if (opts.indexOf('--env') === -1) { 33 | opts = opts.concat(['--env', 'chrome']) 34 | } 35 | 36 | const spawn = require('cross-spawn') 37 | const runner = spawn('./node_modules/.bin/nightwatch', opts, { stdio: 'inherit' }) 38 | 39 | runner.on('exit', function (code) { 40 | server.close() 41 | process.exit(code) 42 | }) 43 | 44 | runner.on('error', function (err) { 45 | server.close() 46 | throw err 47 | }) 48 | }) 49 | -------------------------------------------------------------------------------- /src/common/loadScripts.js: -------------------------------------------------------------------------------- 1 | export function loadScripts(srcs=[]){ 2 | for(let i=0;i{ 13 | var ret = null; 14 | for(var i=0; params&&i{ 25 | var ret = null; 26 | for(let i=0;i{ 36 | if(!type || type === 'error'){ 37 | Message.error({message:msg, type:"error",showClose: true}); 38 | }else{ 39 | Message.success({message:msg, type:"success",showClose: true}); 40 | } 41 | } 42 | 43 | export const kpiExist = (kpiId, kpis)=>{ 44 | var ret = false; 45 | if(!kpis || kpis == null){ 46 | return ret; 47 | } 48 | for(var i=0; i { 58 | var ret = false; 59 | if(!dims || dims == null){ 60 | return ret; 61 | } 62 | for(var i=0; i{ 72 | var ret = false; 73 | if(!dims || dims == null){ 74 | return ret; 75 | } 76 | for(let m=0; m 2 |

3 | 4 | 5 | 6 | 7 | 8 |
9 | 10 | 75 | 78 | -------------------------------------------------------------------------------- /src/view/bireport/ReportTablePrint.vue: -------------------------------------------------------------------------------- 1 | 2 | 63 | 64 | 87 | -------------------------------------------------------------------------------- /src/view/portal/Print.vue: -------------------------------------------------------------------------------- 1 | 9 | 10 | 78 | 79 | 82 | -------------------------------------------------------------------------------- /src/view/portal/PortalText.vue: -------------------------------------------------------------------------------- 1 | 14 | 15 | 77 | 78 | 81 | -------------------------------------------------------------------------------- /src/components/OperationDailog.vue: -------------------------------------------------------------------------------- 1 | 4 | 21 | 22 | 79 | 80 | 89 | -------------------------------------------------------------------------------- /src/view/bireport/Print.vue: -------------------------------------------------------------------------------- 1 | 8 | 9 | 81 | 82 | 85 | -------------------------------------------------------------------------------- /src/view/model/CubeAddGroup.vue: -------------------------------------------------------------------------------- 1 | 14 | 15 | 76 | 77 | 80 | -------------------------------------------------------------------------------- /README_en.md: -------------------------------------------------------------------------------- 1 | # Ruisi BI - Open Source Edition 2 | 3 | - zh_CN [简体中文](README.md) 4 | - en [English](README_en.md) 5 | 6 | Ruisibi Open Source Front-end Framework - Based on VUE
7 | ⚠️ The back-end framework of this project is based on springboot, address:https://github.com/ruisibi/rsbi-os ⚠️
8 | 9 | "Ruisi BI" business intelligence system is an enterprise data analysis system independently developed by [Chengdu Ruisi Business Intelligence Technology Co., Ltd.](https://www.ruisitech.com). The open source version includes data modelling, data reporting, multi-dimensional analysis, permission management and other functional modules, which is convenient for users to quickly establish a set of easy-to-use and flexible data analysis platforms to realise rapid analysis and visualisation of data.
10 | 11 | Quickly start: https://blog.csdn.net/zhuifengsn/article/details/138605460
12 | 13 | # Product features:
14 | 1.Lightweight BI supports rapid modelling and rapid visualisation of data.
15 | 2.Multi-dimensional analysis is powerful and supports a variety of operation methods such as drilling/upwinding/sorting/screening/calculation/aggregation.
16 | 3.The report is simple to use and powerful. It builds an analysis interface through drag-and-drop methods, and writes 0 code.
17 | 4.Open source code, using apache2.0 open source protocol, users can use it at will without our company's authorisation (except for the flagship version).
18 |   19 | # System function:
20 | 1.Data modelling (supports:mysql/oracle/sqlserver/db2/postgresql/hive/kylin)
21 | 2.Multidimensional analysis (OLAP)
22 | 3.Data report
23 | 4.Permission management
24 | 25 | # Technical support:
26 | Please add QQ group 648548832, this group is Ruisibi technology exchange.
27 |

28 | 29 | Document: http://www.ruisibi.cn/book.htm
30 | Demonstrate: http://bi.ruisitech.com/
31 |

32 | 33 | # Product screenshot:
34 | Data modelling
35 | ![olap](https://www.ruisitech.com/img/3461099639.png?v4)  
36 | Multidimensional analysis
37 | ![1](https://www.ruisitech.com/img/173641763.png?v5)  
38 | Data report
39 | ![2](https://www.ruisitech.com/img/1693025478.png?v3)  
40 | 41 | ## Build Setup 42 | 43 | ``` bash 44 | # install dependencies 45 | npm install 46 | 47 | # serve with hot reload at localhost:8080 48 | npm run dev 49 | 50 | # build for production with minification 51 | npm run build 52 | ``` 53 | -------------------------------------------------------------------------------- /src/view/bireport/ReportSave.vue: -------------------------------------------------------------------------------- 1 | 14 | 15 | 84 | 85 | 88 | -------------------------------------------------------------------------------- /src/view/portal/SelectDset.vue: -------------------------------------------------------------------------------- 1 | 21 | 22 | 78 | 79 | 82 | -------------------------------------------------------------------------------- /src/view/portal/view/Box.vue: -------------------------------------------------------------------------------- 1 | 91 | 92 | 95 | -------------------------------------------------------------------------------- /src/view/portal/PortalLayoutDailog.vue: -------------------------------------------------------------------------------- 1 | 21 | 22 | 80 | 81 | 90 | -------------------------------------------------------------------------------- /src/view/portal/ChartSeriesColor.vue: -------------------------------------------------------------------------------- 1 | 2 | 21 | 22 | 90 | 91 | 106 | -------------------------------------------------------------------------------- /config/index.js: -------------------------------------------------------------------------------- 1 | 'use strict' 2 | // Template version: 1.3.1 3 | // see http://vuejs-templates.github.io/webpack for documentation. 4 | 5 | const path = require('path') 6 | 7 | module.exports = { 8 | dev: { 9 | 10 | // Paths 11 | assetsSubDirectory: 'static', 12 | assetsPublicPath: '/', 13 | proxyTable: { 14 | "/": { 15 | target: "http://localhost:8080/", 16 | // changeOrigin: true, 17 | // pathRewrite: { 18 | // '^/': '/rsbi-os-4.7/' 19 | // } 20 | } 21 | }, 22 | 23 | // Various Dev Server settings 24 | host: 'localhost', // can be overwritten by process.env.HOST 25 | port: 8085, // can be overwritten by process.env.PORT, if port is in use, a free one will be determined 26 | autoOpenBrowser: false, 27 | errorOverlay: true, 28 | notifyOnErrors: true, 29 | poll: false, // https://webpack.js.org/configuration/dev-server/#devserver-watchoptions- 30 | 31 | // Use Eslint Loader? 32 | // If true, your code will be linted during bundling and 33 | // linting errors and warnings will be shown in the console. 34 | useEslint: false, 35 | // If true, eslint errors and warnings will also be shown in the error overlay 36 | // in the browser. 37 | showEslintErrorsInOverlay: false, 38 | 39 | /** 40 | * Source Maps 41 | */ 42 | 43 | // https://webpack.js.org/configuration/devtool/#development 44 | devtool: 'cheap-eval-source-map', 45 | 46 | // If you have problems debugging vue-files in devtools, 47 | // set this to false - it *may* help 48 | // https://vue-loader.vuejs.org/en/options.html#cachebusting 49 | cacheBusting: true, 50 | 51 | cssSourceMap: true 52 | }, 53 | 54 | build: { 55 | // Template for index.html 56 | index: path.resolve(__dirname, '../dist/index.html'), 57 | 58 | // Paths 59 | assetsRoot: path.resolve(__dirname, '../dist'), 60 | assetsSubDirectory: 'static', 61 | assetsPublicPath: './', 62 | 63 | /** 64 | * Source Maps 65 | */ 66 | 67 | productionSourceMap: true, 68 | // https://webpack.js.org/configuration/devtool/#production 69 | devtool: '#source-map', 70 | 71 | // Gzip off by default as many popular static hosts such as 72 | // Surge or Netlify already gzip all static assets for you. 73 | // Before setting to `true`, make sure to: 74 | // npm install --save-dev compression-webpack-plugin 75 | productionGzip: false, 76 | productionGzipExtensions: ['js', 'css'], 77 | 78 | // Run the build command with an extra argument to 79 | // View the bundle analyzer report after build finishes: 80 | // `npm run build --report` 81 | // Set to `true` or `false` to always turn it on or off 82 | bundleAnalyzerReport: process.env.npm_config_report 83 | } 84 | } 85 | -------------------------------------------------------------------------------- /src/view/portal/prop/Grid.vue: -------------------------------------------------------------------------------- 1 | 24 | 25 | 93 | 94 | 97 | -------------------------------------------------------------------------------- /src/view/bireport/TableDetailLink.vue: -------------------------------------------------------------------------------- 1 | 2 | 25 | 26 | 100 | 101 | 104 | -------------------------------------------------------------------------------- /src/components/Password.vue: -------------------------------------------------------------------------------- 1 | 20 | 21 | 87 | 88 | 91 | -------------------------------------------------------------------------------- /src/view/bireport/SelectCube.vue: -------------------------------------------------------------------------------- 1 | 29 | 30 | 102 | 103 | 108 | -------------------------------------------------------------------------------- /src/view/portal/LayoutBottom.vue: -------------------------------------------------------------------------------- 1 | 19 | 20 | 96 | 97 | 114 | -------------------------------------------------------------------------------- /src/view/model/Index.vue: -------------------------------------------------------------------------------- 1 | 39 | 40 | 101 | 102 | 105 | -------------------------------------------------------------------------------- /src/view/bireport/ReportList.vue: -------------------------------------------------------------------------------- 1 | 25 | 26 | 111 | 112 | 115 | -------------------------------------------------------------------------------- /src/router/index.js: -------------------------------------------------------------------------------- 1 | import Vue from 'vue' 2 | import Router from 'vue-router' 3 | import Login from '@/view/Login' 4 | import Main from '@/view/Main' 5 | import Welcome from '@/view/Welcome' 6 | import Menu from '@/view/frame/Menu' 7 | import Role from '@/view/frame/Role' 8 | import RoleMenu from '@/view/frame/RoleMenu' 9 | import User from '@/view/frame/User' 10 | import UserMenu from '@/view/frame/UserMenu' 11 | import Model from '@/view/model/Index' 12 | import PortalIndex from '@/view/portal/PortalIndex' 13 | import PortalCustomiz from '@/view/portal/PortalCustomiz' 14 | import PortalView from '@/view/portal/PortalView' 15 | import ReportDesign from '@/view/bireport/ReportDesign' 16 | import BireportPrint from '@/view/bireport/Print' 17 | import PortalPrint from '@/view/portal/Print' 18 | import PortalPushView from '@/view/portal/PortalPushView' 19 | import PortalShareView from '@/view/portal/PortalShareView' 20 | import NotFind from '@/view/NoFind' 21 | 22 | Vue.use(Router) 23 | 24 | let router = new Router({ 25 | routes: [ 26 | { 27 | path: '/', 28 | name: 'login', 29 | component: Login 30 | }, 31 | { 32 | path:'*', 33 | component:NotFind 34 | }, 35 | { 36 | path: '/main', 37 | name: 'main', 38 | component: Main, 39 | children: [ 40 | { 41 | path: '/Welcome', 42 | name: 'welcome', 43 | component: Welcome 44 | }, 45 | { 46 | path:'/frame/Menu', 47 | name:'menu', 48 | component:Menu 49 | }, 50 | { 51 | path:'/frame/User', 52 | name:'user', 53 | component:User 54 | }, 55 | { 56 | path:'/frame/Role', 57 | name:'role', 58 | component:Role 59 | }, 60 | { 61 | path:'/frame/RoleMenu', 62 | name:'roleMenu', 63 | component:RoleMenu 64 | }, 65 | { 66 | path:'/frame/UserMenu', 67 | name:'userMenu', 68 | component:UserMenu 69 | }, 70 | { 71 | path:'/model/Index', 72 | name:'model', 73 | component:Model 74 | }, 75 | { 76 | path:'/portal/Index', 77 | name:'portalIndex', 78 | component:PortalIndex 79 | }, 80 | { 81 | path:'/portal/View', 82 | name:'portalView', 83 | component:PortalView 84 | }, 85 | { 86 | path:"/portal/Customiz", 87 | name:"PortalCustomiz", 88 | component:PortalCustomiz 89 | } 90 | , 91 | { 92 | path:'/bireport/ReportDesign', 93 | name:'bireport', 94 | component:ReportDesign 95 | }, 96 | { 97 | path:'/portal/PushView', 98 | name:'portalPushView', 99 | component:PortalPushView 100 | } 101 | ] 102 | }, 103 | { 104 | path: '/bireport/Print', 105 | name: 'bireportPrint', 106 | component: BireportPrint 107 | }, 108 | { 109 | path:"/portal/Print", 110 | name:"portalPrint", 111 | component:PortalPrint 112 | }, 113 | { 114 | path:"/portal/ShareView", 115 | name:"portalShareView", 116 | component:PortalShareView 117 | } 118 | ] 119 | }) 120 | 121 | router.beforeEach((to, from, next) => { 122 | if(to.path != "/"){ 123 | // if(!checkIsLogin()){ 124 | // next("/") 125 | // return; 126 | // } 127 | } 128 | next(); 129 | }) 130 | 131 | export default router; 132 | -------------------------------------------------------------------------------- /src/view/portal/PortalPushView.vue: -------------------------------------------------------------------------------- 1 | 23 | 116 | 119 | -------------------------------------------------------------------------------- /src/view/model/DsetColModify.vue: -------------------------------------------------------------------------------- 1 | 34 | 35 | 109 | 110 | 113 | -------------------------------------------------------------------------------- /src/common/biConfig.js: -------------------------------------------------------------------------------- 1 | /** 2 | * 配置编译环境和线上环境之间的切换 3 | * 4 | * baseUrl: 域名地址 5 | * 6 | */ 7 | import $ from 'jquery' 8 | import { Message } from 'element-ui' 9 | import { i18n } from '@/main.js' 10 | 11 | const baseUrl = 'http://localhost:8080/'; 12 | //const baseUrl = "http://112.124.13.251:8081/"; 13 | 14 | export { 15 | baseUrl 16 | } 17 | /** 18 | * 封装Ajax请求 19 | * @param {*} cfg 20 | * @param {*} ts 21 | * @param {*} loadingObj loading对象,如果有 22 | */ 23 | export const ajax = (cfg, ts, loadingObj) => { 24 | let o = { 25 | type:cfg.type, 26 | data:cfg.data, 27 | dataType:"JSON", 28 | xhrFields: {withCredentials: true}, 29 | contentType: "application/json; charset=utf-8", 30 | crossDomain: true, 31 | url:baseUrl+cfg.url, 32 | success:function(resp){ 33 | if(loadingObj){ 34 | loadingObj.close(); 35 | } 36 | if(resp.result === 1){ 37 | cfg.success(resp); 38 | }else if(resp.result === 2){ 39 | if(!ts){ 40 | return; 41 | } 42 | if(ts.$route.path === '/'){ 43 | return; 44 | } 45 | ts.$notify.error({ 46 | title: i18n.tc('message.base.noLogin'), 47 | message:i18n.tc(resp.msg), 48 | offset: 50 49 | }); 50 | ts.$router.push("/"); 51 | }else if(resp.result === 0){ 52 | const h = ts.$createElement; 53 | let m = resp.msg; 54 | if(m && m.indexOf('message') >= 0){ 55 | m = i18n.tc(m); 56 | } 57 | Message.error({message:h('div',[h('h5',i18n.tc('message.base.sysError')), h('div', m)]), type:"error",showClose: true}); 58 | }else{ 59 | Message.error(baseUrl+cfg.url + i18n.tc('message.base.apiError')); 60 | if(errorCallback){ 61 | errorCallback(); 62 | } 63 | } 64 | }, 65 | error: function(){ 66 | if(loadingObj){ 67 | loadingObj.close(); 68 | } 69 | ts.$notify.error({ 70 | title: i18n.tc('message.base.sysError'), 71 | offset: 50 72 | }); 73 | } 74 | }; 75 | if(!cfg.postJSON || cfg.postJSON === false){ 76 | delete o.contentType; 77 | } 78 | if(cfg.async === false){ //同步请求 79 | o.async = cfg.async; 80 | } 81 | $.ajax(o); 82 | } 83 | 84 | //生成唯一标识 85 | export const newGuid = ()=> 86 | { 87 | var guid = ""; 88 | for (var i = 1; i <= 32; i++){ 89 | var n = Math.floor(Math.random()*16.0).toString(16); 90 | guid += n; 91 | //if((i==8)||(i==12)||(i==16)||(i==20)) 92 | // guid += "-"; 93 | } 94 | return guid; 95 | } 96 | //在textarea光标处插入文本 97 | export const insertText2focus = (obj,str) => { 98 | str = str + " "; 99 | obj.focus(); 100 | if (document.selection) { 101 | var sel = document.selection.createRange(); 102 | sel.text = str; 103 | } else if (typeof obj.selectionStart == 'number' && typeof obj.selectionEnd == 'number') { 104 | var startPos = obj.selectionStart, 105 | endPos = obj.selectionEnd, 106 | cursorPos = startPos, 107 | tmpStr = obj.value; 108 | obj.value = tmpStr.substring(0, startPos) + "" + str + tmpStr.substring(endPos, tmpStr.length); 109 | cursorPos += str.length; 110 | obj.selectionStart = obj.selectionEnd = cursorPos; 111 | } else { 112 | obj.value += str; 113 | } 114 | } 115 | 116 | /** 117 | * list 转 String 118 | * @param {*} ls 119 | */ 120 | export const list2string = (ls)=>{ 121 | if(!ls){ 122 | return ""; 123 | } 124 | return ls.join(","); 125 | } 126 | 127 | /** 128 | * 解析图形JSON中的f$标志为字符串 129 | * @param json 130 | */ 131 | export const loopChartJson = (json)=>{ 132 | const exec = (jsons)=>{ 133 | for(let key in jsons) { 134 | let o = jsons[key]; 135 | if(typeof o === 'object'){ 136 | exec(o); //如果是Object则递归 137 | }else if(typeof o === 'string'){ 138 | if(o.indexOf&&o.indexOf('f$')>-1){ //吧f$字符串解析成函数 139 | jsons[key] = eval("("+o.replace("f$", "")+")"); 140 | } 141 | } 142 | //else if(typeof o === 'number'){ 143 | 144 | //} 145 | } 146 | } 147 | exec(json); 148 | return json; 149 | } -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "rsbi-vue", 3 | "version": "1.0.0", 4 | "description": "睿思bi开源版前端项目", 5 | "author": "rsbi ", 6 | "private": true, 7 | "scripts": { 8 | "dev": "webpack-dev-server --inline --progress --config build/webpack.dev.conf.js", 9 | "start": "npm run dev", 10 | "unit": "jest --config test/unit/jest.conf.js --coverage", 11 | "e2e": "node test/e2e/runner.js", 12 | "test": "npm run unit && npm run e2e", 13 | "lint": "eslint --ext .js,.vue src test/unit test/e2e/specs", 14 | "build": "node build/build.js" 15 | }, 16 | "dependencies": { 17 | "@fortawesome/fontawesome": "^1.1.8", 18 | "@fortawesome/fontawesome-free-brands": "^5.0.13", 19 | "@fortawesome/fontawesome-free-regular": "^5.0.13", 20 | "@fortawesome/fontawesome-free-solid": "^5.0.13", 21 | "@fortawesome/vue-fontawesome": "^2.0.0", 22 | "bootstrap-table": "^1.18.0", 23 | "bootstrap3": "^3.3.5", 24 | "echarts": "^5.2.2", 25 | "element-ui": "^2.13.2", 26 | "font-awesome": "^4.7.0", 27 | "jquery": "^3.5.1", 28 | "jquery-contextmenu": "^2.9.2", 29 | "jquery-ui-dist": "^1.12.1", 30 | "jstree": "^3.3.10", 31 | "popper.js": "^1.16.1", 32 | "vue": "^2.5.2", 33 | "vue-i18n": "^8.23.0", 34 | "vue-router": "^3.0.1", 35 | "vuex": "^3.6.0" 36 | }, 37 | "devDependencies": { 38 | "autoprefixer": "^7.1.2", 39 | "babel-core": "^6.22.1", 40 | "babel-eslint": "^8.2.1", 41 | "babel-helper-vue-jsx-merge-props": "^2.0.3", 42 | "babel-jest": "^21.0.2", 43 | "babel-loader": "^7.1.1", 44 | "babel-plugin-dynamic-import-node": "^1.2.0", 45 | "babel-plugin-syntax-jsx": "^6.18.0", 46 | "babel-plugin-transform-es2015-modules-commonjs": "^6.26.0", 47 | "babel-plugin-transform-runtime": "^6.22.0", 48 | "babel-plugin-transform-vue-jsx": "^3.5.0", 49 | "babel-preset-env": "^1.3.2", 50 | "babel-preset-stage-2": "^6.22.0", 51 | "babel-register": "^6.22.0", 52 | "chalk": "^2.0.1", 53 | "chromedriver": "^2.27.2", 54 | "copy-webpack-plugin": "^4.0.1", 55 | "cross-spawn": "^5.0.1", 56 | "css-loader": "^0.28.11", 57 | "eslint": "^4.15.0", 58 | "eslint-config-standard": "^10.2.1", 59 | "eslint-friendly-formatter": "^3.0.0", 60 | "eslint-loader": "^1.7.1", 61 | "eslint-plugin-import": "^2.7.0", 62 | "eslint-plugin-node": "^5.2.0", 63 | "eslint-plugin-promise": "^3.4.0", 64 | "eslint-plugin-standard": "^3.0.1", 65 | "eslint-plugin-vue": "^4.0.0", 66 | "extract-text-webpack-plugin": "^3.0.0", 67 | "file-loader": "^1.1.4", 68 | "friendly-errors-webpack-plugin": "^1.6.1", 69 | "html-webpack-plugin": "^2.30.1", 70 | "jest": "^22.0.4", 71 | "jest-serializer-vue": "^0.3.0", 72 | "less": "^3.12.2", 73 | "less-loader": "^4.1.0", 74 | "nightwatch": "^0.9.12", 75 | "node-notifier": "^5.1.2", 76 | "optimize-css-assets-webpack-plugin": "^3.2.0", 77 | "ora": "^1.2.0", 78 | "portfinder": "^1.0.13", 79 | "postcss-import": "^11.0.0", 80 | "postcss-loader": "^2.0.8", 81 | "postcss-url": "^7.2.1", 82 | "rimraf": "^2.6.0", 83 | "sass": "^1.26.10", 84 | "sass-loader": "^10.0.2", 85 | "selenium-server": "^3.0.1", 86 | "semver": "^5.3.0", 87 | "shelljs": "^0.7.6", 88 | "style-loader": "^1.2.1", 89 | "stylus-loader": "^3.0.2", 90 | "uglifyjs-webpack-plugin": "^1.1.1", 91 | "url-loader": "^0.5.8", 92 | "vue-jest": "^1.0.2", 93 | "vue-loader": "^13.3.0", 94 | "vue-style-loader": "^3.0.1", 95 | "vue-template-compiler": "^2.5.2", 96 | "webpack": "^3.6.0", 97 | "webpack-bundle-analyzer": "^2.9.0", 98 | "webpack-dev-server": "^2.9.1", 99 | "webpack-merge": "^4.1.0" 100 | }, 101 | "engines": { 102 | "node": ">= 6.0.0", 103 | "npm": ">= 3.0.0" 104 | }, 105 | "browserslist": [ 106 | "> 1%", 107 | "last 2 versions", 108 | "not ie <= 8" 109 | ] 110 | } 111 | -------------------------------------------------------------------------------- /src/view/bireport/chartUtils.js: -------------------------------------------------------------------------------- 1 | /** 2 | * 图形的工具类 3 | */ 4 | import $ from 'jquery' 5 | import * as tools from '@/view/bireport/bireportUtils' 6 | 7 | export function findDimById(dimId, dims){ 8 | var ret = null; 9 | if(!dims || dims == null){ 10 | return ret; 11 | } 12 | for(var i=0; i 1){ 28 | json.kpiJson[0] = null; 29 | }else{ 30 | json.kpiJson = []; 31 | } 32 | } 33 | if(tp == 'y2col'){ 34 | if(json.kpiJson.length > 1){ 35 | json.kpiJson[1] = null; 36 | }else{ 37 | json.kpiJson = []; 38 | } 39 | } 40 | if(tp == 'y3col'){ 41 | json.kpiJson[2] = null; 42 | } 43 | if(tp == 'scol'){ 44 | delete json.chartJson.scol; 45 | } 46 | if(cb){ 47 | cb(); 48 | } 49 | } 50 | export function chartsort(sorttp, tp, json, cb){ 51 | if(tp == 'xcol'){ 52 | //清除度量排序,因为度量排序最优先 53 | delete json.kpiJson[0].sort; 54 | json.chartJson.xcol.dimord = sorttp; 55 | } 56 | if(tp == 'ycol'){ 57 | json.kpiJson[0].sort = sorttp; 58 | } 59 | if(tp == 'scol'){ 60 | //清除度量排序 61 | delete json.kpiJson[0].sort; 62 | json.chartJson.scol.dimord = sorttp; 63 | } 64 | if(cb){ 65 | cb(); 66 | } 67 | } 68 | //开始钻取图形 69 | export const drillingChart = (dimId, comp, pos, xvalue, oldDimId, cb)=>{ 70 | //设置当前维度值为过滤条件 71 | if(pos == "row"){ 72 | comp.chartJson.xcol.vals = [xvalue + ""]; 73 | //comp.chartJson.xcol.valDesc = xvalueDesc; 74 | comp.chartJson.xcol.pos = "row"; 75 | }else{ 76 | comp.chartJson.scol.vals = [xvalue + ""]; 77 | //comp.chartJson.scol.valDesc = xvalueDesc; 78 | comp.chartJson.scol.pos = "col"; 79 | } 80 | 81 | 82 | var dim = pos == "row" ? comp.chartJson.xcol : comp.chartJson.scol; 83 | dim.filtertype = 2; // 按值钻取 84 | if(dim.type == 'month'){ 85 | delete dim.startmt; 86 | delete dim.endmt; 87 | } 88 | if(dim.type == 'day'){ 89 | delete dim.startdt; 90 | delete dim.enddt; 91 | } 92 | //把当前维放入params 93 | //如果当前维度是合计,不用加入 94 | if(xvalue == '合计' && xvalueDesc == '合计'){ 95 | }else{ 96 | comp.chartJson.params.push(pos=="row"?comp.chartJson.xcol:comp.chartJson.scol); 97 | } 98 | //更新x轴 99 | var json = null; 100 | for(let j=0;j { 118 | var dims = comp.chartJson.params; 119 | //清除过滤条件 120 | //删除该维度以后的维度 121 | var idx = 0; 122 | var xcol = null; 123 | for(let i=0; i 2 |

3 |
4 |
5 |
{{title}}
6 |
7 | 8 |
9 |
10 |
11 | 12 | 13 | 14 | 15 | 16 |
17 |
18 |
19 | 20 | 21 | 110 | 111 | 140 | -------------------------------------------------------------------------------- /src/view/portal/PortalView.vue: -------------------------------------------------------------------------------- 1 | 25 | 110 | 113 | -------------------------------------------------------------------------------- /src/view/frame/RoleMenu.vue: -------------------------------------------------------------------------------- 1 | 21 | 22 | 120 | 121 | 124 | -------------------------------------------------------------------------------- /src/view/model/Cube.vue: -------------------------------------------------------------------------------- 1 | 66 | 67 | 138 | 139 | 142 | -------------------------------------------------------------------------------- /src/view/portal/data/Box.vue: -------------------------------------------------------------------------------- 1 | 14 | 15 | 102 | 103 | 145 | -------------------------------------------------------------------------------- /src/view/frame/UserMenu.vue: -------------------------------------------------------------------------------- 1 | 21 | 22 | 129 | 130 | 136 | -------------------------------------------------------------------------------- /src/view/portal/prop/Table.vue: -------------------------------------------------------------------------------- 1 | 31 | 32 | 128 | 129 | 132 | -------------------------------------------------------------------------------- /src/view/Main.vue: -------------------------------------------------------------------------------- 1 | 43 | 44 | 117 | 118 | 157 | -------------------------------------------------------------------------------- /src/view/model/Dsource.vue: -------------------------------------------------------------------------------- 1 | 76 | 77 | 150 | 151 | 154 | -------------------------------------------------------------------------------- /src/common/index-db.js: -------------------------------------------------------------------------------- 1 | const { Result } = require("./Result"); 2 | const { cat } = require("shelljs"); 3 | const { data } = require("jquery"); 4 | 5 | let tableNames = { 6 | "REQUESTS":"REQUESTS" 7 | }; 8 | let dbConfig = { 9 | databaseName:"test1", 10 | version:Date.now(), 11 | tables:{ 12 | [tableNames.REQUESTS]:{ 13 | keyPath: 'id' 14 | } 15 | } 16 | } 17 | 18 | class IndexedDB{ 19 | dbConfig = dbConfig; 20 | db = null; 21 | tables = {}; 22 | constructor(){ 23 | this.init() 24 | 25 | } 26 | async init(){ 27 | return new Promise((resolve,reject) => { 28 | try{ 29 | if(!window.indexedDB){ 30 | return resolve(Result.fail({msg:"浏览器不支持indexdb"})); 31 | } 32 | let request = window.indexedDB.open(dbConfig.databaseName, dbConfig.version); 33 | request.onerror = event => resolve(Result.fail({msg:"数据库打开报错"})); 34 | request.onsuccess = event => { 35 | // this.db = request.result; 36 | // resolve(Result.success({msg:"数据库打开成功",data:request.result})); 37 | }; 38 | request.onupgradeneeded = event => { 39 | this.db = request.result; 40 | for(let tablename in this.dbConfig.tables){ 41 | let objectStore = null; 42 | if(!this.db.objectStoreNames.contains(tablename)){ 43 | objectStore = this.db.createObjectStore(tablename,this.dbConfig.tables[tablename]); 44 | } 45 | this.tables[tablename] = objectStore; 46 | } 47 | resolve(Result.success({msg:"数据库打开成功",data:request.result})); 48 | }; 49 | }catch(e){ 50 | resolve(Result.fail({msg:"程序错误",data:e})) 51 | } 52 | }) 53 | } 54 | async add(tablename,data){ 55 | return new Promise((resolve,reject) => { 56 | if(this.db.objectStoreNames.contains(tablename)){ 57 | let request = this.db 58 | .transaction([tablename], 'readwrite') 59 | .objectStore(tablename) 60 | .add(data); 61 | request.onsuccess = function (event) { 62 | resolve(Result.success({msg:"数据写入成功",data:data})); 63 | }; 64 | request.onerror = function (event) { 65 | resolve(Result.success({msg:"数据写入失败",data:data})); 66 | } 67 | }else{ 68 | resolve(Result.fail({msg:`表${tablename}不存在`})) 69 | } 70 | }); 71 | } 72 | async get(tablename,key){ 73 | return new Promise((resolve,reject) => { 74 | if(this.db.objectStoreNames.contains(tablename)){ 75 | let request = this.db 76 | .transaction([tablename], 'readwrite') 77 | .objectStore(tablename) 78 | .get(key); 79 | request.onerror = function(event) { 80 | resolve(Result.fail({msg:"失败"})) 81 | }; 82 | request.onsuccess = function( event) { 83 | resolve(Result.success({msg:"查询成功",data:request.result||{}})) 84 | }; 85 | }else{ 86 | resolve(Result.fail({msg:`表${tablename}不存在`})) 87 | } 88 | }); 89 | } 90 | async put(tablename,data){ 91 | return new Promise((resolve,reject) => { 92 | if(this.db.objectStoreNames.contains(tablename)){ 93 | let request = this.db 94 | .transaction([tablename], 'readwrite') 95 | .objectStore(tablename) 96 | .put(data); 97 | request.onerror = function(event) { 98 | resolve(Result.fail({msg:`${tablename}更新失败`,data:data})); 99 | }; 100 | request.onsuccess = function( event) { 101 | resolve(Result.success({msg:`${tablename}更新成功`,data:data})); 102 | }; 103 | }else{ 104 | resolve(Result.fail({msg:`表${tablename}不存在`})) 105 | } 106 | }); 107 | } 108 | async delete(tablename,key){ 109 | return new Promise((resolve,reject) => { 110 | if(this.db.objectStoreNames.contains(tablename)){ 111 | let request = this.db 112 | .transaction([tablename], 'readwrite') 113 | .objectStore(tablename) 114 | .delete(key); 115 | request.onerror = function(event) { 116 | resolve(Result.fail({msg:`${tablename}删除${key}失败`})); 117 | }; 118 | request.onsuccess = function( event) { 119 | resolve(Result.success({msg:`${tablename}删除${key}成功`,data:key})); 120 | }; 121 | }else{ 122 | resolve(Result.fail({msg:`表${tablename}不存在`})) 123 | } 124 | }); 125 | } 126 | } 127 | let indexdb = new IndexedDB(); 128 | export { 129 | indexdb, 130 | tableNames 131 | }; 132 | -------------------------------------------------------------------------------- /src/view/portal/prop/Box.vue: -------------------------------------------------------------------------------- 1 | 47 | 48 | 128 | 129 | 132 | -------------------------------------------------------------------------------- /src/view/portal/prop/Text.vue: -------------------------------------------------------------------------------- 1 | 42 | 43 | 118 | 119 | 122 | -------------------------------------------------------------------------------- /src/components/FrameTop.vue: -------------------------------------------------------------------------------- 1 | 33 | 34 | 102 | 103 | 148 | -------------------------------------------------------------------------------- /src/view/bireport/Table2ChartDailog.vue: -------------------------------------------------------------------------------- 1 | 2 | 55 | 56 | -------------------------------------------------------------------------------- /src/view/bireport/ReportParam.vue: -------------------------------------------------------------------------------- 1 | 15 | 16 | 130 | 131 | 155 | -------------------------------------------------------------------------------- /src/view/portal/view/Table.vue: -------------------------------------------------------------------------------- 1 | 145 | 146 | 156 | -------------------------------------------------------------------------------- /src/view/model/Dset.vue: -------------------------------------------------------------------------------- 1 | 74 | 75 | 169 | 170 | 173 | -------------------------------------------------------------------------------- /src/view/portal/LayoutParam.vue: -------------------------------------------------------------------------------- 1 | 16 | 17 | 120 | 121 | 164 | -------------------------------------------------------------------------------- /src/view/portal/PortalShare.vue: -------------------------------------------------------------------------------- 1 | 35 | 36 | 151 | 152 | 160 | -------------------------------------------------------------------------------- /src/view/bireport/ChgChartDailog.vue: -------------------------------------------------------------------------------- 1 | 2 | 44 | 45 | 151 | 152 | 186 | -------------------------------------------------------------------------------- /src/view/model/DsetDynaCol.vue: -------------------------------------------------------------------------------- 1 | 41 | 42 | 165 | 166 | 169 | --------------------------------------------------------------------------------