Browse Source

添加数据开放策略 图表分发策略界面圆形 更新用户权限系统设计文档

xiaoct 7 years ago
parent
commit
9263c72bc9

+ 3 - 1
.gitignore

@@ -6,4 +6,6 @@ src/**/*.css
 .scannerwork/report-task.txt
 src/demo.jsx
 gitbook/dev/_book
-gitbook/dev/node_modules
+gitbook/dev/node_modules
+gitbook/BI商业智能平台 - 产品文档.pdf
+gitbook/BI商业智能平台 - 研发设计文档.pdf

BIN
gitbook/product/asset/image/dataAccess-UI.png


BIN
gitbook/product/asset/image/distributeAccess-UI-1.png


BIN
gitbook/product/asset/image/distributeAccess-UI-2.png


+ 23 - 7
gitbook/product/permission.md

@@ -1,8 +1,16 @@
-# 用户权限模型的设计概念
+# 用户权限模型的设计概念(初稿)
 ## 人员信息的导入与整理
 1. 使用UAS的用户验证机制校验密码,并且获取用户对应的姓名、部门和岗位字段
 2. 引入用户组概念,用户表下以用户组ID列表的方式标注其归属的用户组,一个用户可以属于多个组
 
+## 设置用户组
+1. 用户系统接入后,应当指定一个用户为管理员(即属于`管理员`用户组),由管理员来初始化`分析者`用户组
+2. 管理员设置用户组时,可以用以下方式筛选用户:
+    1. 用户名/姓名
+    2. 部门
+    3. 部门 + 岗位
+    4. 用户组
+3. 勾选目标用户后可以批量加入或移出用户组
 
 ## 业务流程
 1. 管理员配置好数据源后,管理员默认获得所有的权限
@@ -11,8 +19,9 @@
 
 ## 数据开放策略设计流程
 1. 设置开放对象(分析者):
-    1. 开放对象由多条判断语句定义,每条判断语句匹配到具体的用户,最后取其并集
-    2. 判断语句中可以按照四种方式定位应用对象:
+    1. 开放对象必须属于`分析者`用户组
+    2. 开放对象由多条判断语句定义,每条判断语句匹配到具体的用户,最后取其与并集
+    3. 判断语句中可以按照四种方式定位应用对象:
         1. 用户名/姓名
         2. 部门
         3. 部门 + 岗位
@@ -30,14 +39,15 @@
 ## 图表分发策略设计流程
 1. 设置分发对象(阅读者):
     1. 分发对象由多条判断语句定义,每条判断语句匹配到具体的用户,最后取其并集
-    2. 判断语句中可以按照四种方式定位应用对象:
+    2. 判断语句中可以按照四种方式定位分发对象:
         1. 用户名/姓名
         2. 部门
         3. 部门 + 岗位
         4. 用户组
 2. 设置分发策略:
-    1. 分发策略由多条判断语句定义,以筛选的方式作用于当前的数据,最后取其交集
-    2. 可以引入部门/岗位/用户组作为变量用于编写判断语句
+    1. 分发策略只是行策略,没有列策略
+    2. 分发策略由多条判断语句定义,以筛选的方式作用于当前的数据,最后取其交集
+    3. 可以引入部门/岗位/用户组作为变量用于编写判断语句
 3. 备注:
     1. 若出现阅读者适用多条图表分发策略的情况,其具体可阅读的图表取并集
         - 例如: 假设策略规定部门A的阅读者只能阅读图表1、部门B的阅读者只能阅读图表2, 若有员工既属于部门A也属于部门B, 则该员工能获阅读图表1和图表2。
@@ -92,4 +102,10 @@
 - 这种方案可以让看板作者在分发看板时无需考虑阅读者是否有看板内各图表的阅读权限。
 
 
-# 界面元素和原型图(待更新)
+# 界面元素和原型图(待更新)
+### 数据开放策略设置界面
+![数据开放策略设置界面](asset/image/dataAccess-UI.png)
+
+### 图表/看板分发策略设置界面
+![数据开放策略设置界面-1](asset/image/distributeAccess-UI-1.png)
+![数据开放策略设置界面-2](asset/image/distributeAccess-UI-2.png)

+ 2 - 2
src/components/chart/chooseDataSourceBox.jsx

@@ -33,7 +33,7 @@ class ChooseDataSourceBox extends React.Component {
 
     render() {
         const { selectedRecord } = this.state;
-        const { dataSource, visibleBox, hideBox } = this.props
+        const { dataSource, visibleChooseDataSourceBox, hideBox } = this.props
 
         const reg = new RegExp('([+ \\- & | ! ( ) { } \\[ \\] ^ \" ~ * ? : ( ) \/])', 'g'); // 需要转义的字符
         let filterLabel = this.state.filterLabel.replace(new RegExp('(\\\\)', 'g'), '\\$1').replace(reg, '\\$1'); // 添加转义符号
@@ -119,7 +119,7 @@ class ChooseDataSourceBox extends React.Component {
                         /></Col>
                     </Row>
                 }
-                visible={visibleBox}
+                visible={visibleChooseDataSourceBox}
                 onOk={this.okHandler}
                 onCancel={hideBox}
                 maskClosable={false}

+ 87 - 0
src/components/chart/distributeBox.jsx

@@ -0,0 +1,87 @@
+import React from 'react'
+import { Modal, Table, Col, Row, Button, Input} from 'antd'
+import { connect } from 'dva'
+
+const Search = Input.Search;
+
+const columns = [{
+    title: '策略名',
+    dataIndex: 'policyName',
+    render: policyName => <span>{policyName}</span>
+}, {
+    title: '分发对象',
+    dataIndex: 'targets',
+    render: targets => {return targets.map(item => {return <p>{item.value}</p>})}
+}, {
+    title: '行开放策略',
+    dataIndex: 'rowFilters',
+    render: rowFilters => {return rowFilters.map(filter => {return <p>{filter.value}</p>})}
+}]
+
+const data = [{
+    key: '1',
+    policyName: '分发策略1',
+    targets: [{value:'部门为销售'}, {value:'部门为售后'}],
+    rowFilters: [{value:'部门字段包含售后,销售'}, {value:'公司名包含公司A'}],
+    columns: [{name:'department', alias:'部门', enabled: true}, {name:'company', alias:'公司', enabled: false}]
+}];
+
+
+class DistributeBox extends React.Component {
+    constructor(props){
+        super(props);
+        this.state = {
+            filterLabel: '',
+        }
+    }
+    render() {
+        const { selectedRecord } = this.state;
+        const { dataSource, visibleDistributeBox, hideBox } = this.props
+        return (
+            <Modal
+                width={1200}
+                className='distribute-box'
+                title={
+                    <Row>图表分发策略
+                    </Row>
+                }
+                visible={visibleDistributeBox}
+                onOk={this.okHandler}
+                onCancel={hideBox}
+                maskClosable={false}
+                destroyOnClose={true}
+            >
+            <Table
+            columns={columns}
+            dataSource={data}
+            bordered
+            title={() => {
+                return (
+                    <div style={{display:"flex", justifyContent:"space-between"}}>
+                        <Col>
+                            <Search  
+                                style={{display:"inline"}}
+                                placeholder="input search text"
+                                onSearch={value => console.log(value)}
+                                enterButton
+                            />
+                        </Col>
+                        <Col>
+                            <Button>显示影响</Button>
+                            <Button>新增策略</Button>
+                        </Col>
+                    </div>) }
+            }
+        />
+            </Modal>
+        )
+
+    }
+    
+}
+
+function mapStateToProps({ present: { dataSource } }) {
+    return { dataSource: dataSource };
+}
+
+export default connect(mapStateToProps)(DistributeBox)

+ 18 - 6
src/components/chart/list.jsx

@@ -8,6 +8,7 @@ import Ellipsis from 'ant-design-pro/lib/Ellipsis'
 import 'ant-design-pro/dist/ant-design-pro.css'
 import GroupSelector from '../datasource/groupSelector'
 import Thumbnail from './thumbnail'
+import DistributeBox from './distributeBox';
 const { Content } = Layout
 const { Search } = Input
 const CardGrid = Card.Grid
@@ -19,7 +20,8 @@ class ChartList extends React.Component {
         super(props);
         this.state = {
             selectedRecord: null,
-            visibleBox: false,
+            visibleChooseDataSourceBox: false,
+            visibleDistributeBox: false,
             visibleGroupMenu: false, // 显示分组菜单
         }
     }
@@ -60,6 +62,11 @@ class ChartList extends React.Component {
 
         const operationMenu = (
             <Menu className='menu-operation'>
+                <Menu.Item onClick={() => {
+                    this.setState({visibleDistributeBox: true})
+                }}> 
+                    <Icon type='share-alt'/>分发
+                </Menu.Item>
                 <Menu.SubMenu className='setgroupmenu' title={<div><Icon style={{ marginRight: '6px' }} type='profile' />移动到</div>}>
                     {this.createGroupMenu(selectedRecord)}
                 </Menu.SubMenu>
@@ -181,7 +188,7 @@ class ChartList extends React.Component {
                     (p.code+'' === selectedRecord.groupCode+'' ? 'bold' : (
                         c.find(ch => ch.code+'' === selectedRecord.groupCode+'') && c.find(ch => ch.code+'' === selectedRecord.groupCode+'').pcode === p.code ? 'bold' : 'normal'
                     ))
-                 : chart.currentGroup[0].code === p.code ? 'bold' : 'normal' }}>{p.label}</span>} onTitleClick={(item) => {
+                : chart.currentGroup[0].code === p.code ? 'bold' : 'normal' }}>{p.label}</span>} onTitleClick={(item) => {
                     dispatch({ type: 'chart/setCurrentGroup', group1: p });
                     if(selectedRecord) {
                         dispatch({ type: 'chart/remoteSetChartGroup', chart: selectedRecord, group: p });
@@ -315,7 +322,7 @@ class ChartList extends React.Component {
     }
 
     render() {
-        const { visibleBox } = this.state;
+        const { visibleChooseDataSourceBox, visibleDistributeBox } = this.state;
         const { dispatch, chart } = this.props;
         const TAG_COLOR = ['blue'];
         return (
@@ -381,14 +388,19 @@ class ChartList extends React.Component {
                                     <Button onClick={() => {
                                         dispatch({ type: 'dataSource/fetchList' });
                                         this.setState({
-                                            visibleBox: true
+                                            visibleChooseDataSourceBox: true
                                         });
                                     }}>
                                         <Icon type="area-chart" />创建图表
                                     </Button>
-                                    <ChooseDataSourceBox visibleBox={visibleBox} hideBox={() => {
+                                    <ChooseDataSourceBox visibleChooseDataSourceBox={visibleChooseDataSourceBox} hideBox={() => {
+                                        this.setState({
+                                            visibleChooseDataSourceBox: false
+                                        });
+                                    }}/>
+                                    <DistributeBox visibleDistributeBox={visibleDistributeBox} selectedRecord={this.state.selectedRecord} hideBox={() => {
                                         this.setState({
-                                            visibleBox: false
+                                            visibleDistributeBox: false
                                         });
                                     }}/>
                                 </Col>

+ 51 - 1
src/components/datasource/accessConfig.jsx

@@ -1,11 +1,61 @@
 import React from 'react'
 import { connect } from 'dva'
 import '../../models/dataSource'
+import { Table, Input, Col, Button } from 'antd'
+
+const Search = Input.Search;
 
 const DataSourceAccessConfig = ({ dataSource, dispatch }) => {
 
+    const columns = [{
+        title: '策略名',
+        dataIndex: 'policyName',
+        render: policyName => <span>{policyName}</span>
+    }, {
+        title: '开放对象',
+        dataIndex: 'targets',
+        render: targets => {return targets.map(item => {return <p>{item.value}</p>})}
+    }, {
+        title: '行开放策略',
+        dataIndex: 'rowFilters',
+        render: rowFilters => {return rowFilters.map(filter => {return <p>{filter.value}</p>})}
+    }, {
+        title: '列开放策略',
+        dataIndex: 'columns',
+        render: columns => {return columns.filter((column) => !column.enabled).map(column => {return <p>屏蔽:{column.alias}</p>})}
+    }];
+
+    const data = [{
+        key: '1',
+        policyName: '开放策略1',
+        targets: [{value:'部门为销售'}, {value:'部门为售后'}],
+        rowFilters: [{value:'部门字段包含售后,销售'}, {value:'公司名包含公司A'}],
+        columns: [{name:'department', alias:'部门', enabled: true}, {name:'company', alias:'公司', enabled: false}]
+    }];
+
     return (
-        <div>Null</div>
+        <Table
+            columns={columns}
+            dataSource={data}
+            bordered
+            title={() => {
+                return (
+                    <div style={{display:"flex", justifyContent:"space-between"}}>
+                        <Col>
+                            <Search  
+                                style={{display:"inline"}}
+                                placeholder="input search text"
+                                onSearch={value => console.log(value)}
+                                enterButton
+                            />
+                        </Col>
+                        <Col>
+                            <Button>显示影响</Button>
+                            <Button>新增策略</Button>
+                        </Col>
+                    </div>) }
+            }
+        />
     );
 }
 

+ 2 - 2
src/components/datasource/dataSourceDetail.jsx

@@ -65,7 +65,7 @@ class DataSourceDetail extends React.Component {
             content: <ColumnConfig mode={mode} />
         }, {
             tabName: 'access',
-            title: '权限配置',
+            title: '数据开放策略',
             content: <AccessConfig mode={mode} />
         }, {
             tabName: 'other',
@@ -82,7 +82,7 @@ class DataSourceDetail extends React.Component {
             content: <ColumnConfig mode={mode} />
         }, {
             tabName: 'access',
-            title: '权限配置',
+            title: '数据开放策略',
             content: <AccessConfig mode={mode} />
         }];
         return (