From 349f355e2c716522c3eaa737c097a50af1f86afb Mon Sep 17 00:00:00 2001 From: unknown Date: Wed, 2 Jan 2019 20:40:41 +0800 Subject: [PATCH] =?UTF-8?q?=E5=AE=8C=E6=88=90=E9=A6=96=E9=A1=B5ui=E9=83=A8?= =?UTF-8?q?=E5=88=86=E5=92=8C=E8=B4=A6=E6=9C=AC=E5=88=87=E6=8D=A2=E5=8A=9F?= =?UTF-8?q?=E8=83=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Bundle.js | 47 +++- app-web.js | 4 + index.template-web.nj.html | 2 +- server/app.js | 2 +- src/stores/commonStore.js | 37 ++- src/stores/pages/searchStore.js | 159 +++++++---- src/utils/fetchConfig.js | 74 ++++++ src/web/components/header/header.js | 2 + src/web/components/header/header.scss | 22 +- src/web/components/header/header.t.html | 14 +- src/web/css/app.scss | 20 +- src/web/images/blockheightIcon.svg | 1 + src/web/images/contractIcon.svg | 1 + src/web/images/ledgersIcon.svg | 1 + src/web/images/overview_bg.png | Bin 0 -> 25734 bytes src/web/images/transactionIcon.svg | 1 + src/web/images/userIcon.svg | 23 ++ src/web/pages/search/search.js | 338 +----------------------- src/web/pages/search/search.m.scss | 220 +++++++++------ src/web/pages/search/search.t.html | 258 +++++++++++++----- webpack.config.js | 15 +- 21 files changed, 702 insertions(+), 539 deletions(-) create mode 100644 src/utils/fetchConfig.js create mode 100644 src/web/images/blockheightIcon.svg create mode 100644 src/web/images/contractIcon.svg create mode 100644 src/web/images/ledgersIcon.svg create mode 100644 src/web/images/overview_bg.png create mode 100644 src/web/images/transactionIcon.svg create mode 100644 src/web/images/userIcon.svg diff --git a/Bundle.js b/Bundle.js index f64ad21f..198666e9 100644 --- a/Bundle.js +++ b/Bundle.js @@ -1,6 +1,7 @@ import { Component } from 'react'; import { capitalize } from './src/utils/util'; - +import Message from 'flarej/lib/components/antd/message'; +import notification from 'flarej/lib/components/antd/notification'; class Bundle extends Component { constructor(props) { super(props); @@ -11,7 +12,51 @@ class Bundle extends Component { } componentWillMount() { + // 销毁全局的消息提示 + Message.destroy(); + notification.destroy(); + // 初始化全局数据 + const { store:{common} } = this.props;debugger; + if (common&&common.ledgers.length==0) { + Promise.all([ + common.getLedgersInfo("") + ]).then(() => { + let ledgerDafault=localStorage.getItem("defaultledger"), + ledgers=common.ledgers; + if (ledgerDafault) { + for (let i = 0; i < ledgers.length; i++) { + if(ledgers[i].value==ledgerDafault){ + common.setDefaultLedger(ledgerDafault); + this.load(this.props); + return false; + } + } + if (ledgers.length>0) { + common.setDefaultLedger(ledgers[0].value); + localStorage.setItem('defaultledger',ledgers[0].value); + } + else{ + // 没有账本时的操作 + localStorage.removeItem("defaultledger"); + } + this.load(this.props); + } + else{ + if (ledgers.length>0) { + common.setDefaultLedger(ledgers[0].value); + localStorage.setItem('defaultledger',ledgers[0].value); + } + else{ + // 没有账本时的操作 + localStorage.removeItem("defaultledger"); + } + this.load(this.props); + } + }); + } + else{ this.load(this.props); + } } componentWillReceiveProps(nextProps) { diff --git a/app-web.js b/app-web.js index 395f9c4e..c315de9e 100644 --- a/app-web.js +++ b/app-web.js @@ -47,6 +47,10 @@ const renderApp = appRoutes => {
<${HeaderWithRouter} /> ${appRoutes()} +
+ Copyright © 2004-2019 JD.COM 京东版权所有 Power by +  京东区块链平台 +
diff --git a/index.template-web.nj.html b/index.template-web.nj.html index b030be7b..cc52dd8b 100644 --- a/index.template-web.nj.html +++ b/index.template-web.nj.html @@ -2,7 +2,7 @@ - react-mst-boilerplate + 区块链浏览器 diff --git a/server/app.js b/server/app.js index 2d8d189e..0c2b10c0 100644 --- a/server/app.js +++ b/server/app.js @@ -82,7 +82,7 @@ app.get('/common/logout', function(req, res) { res.redirect('http://localhost:8080/dist/web/home.html'); }); -let server = app.listen(8089, function() { +let server = app.listen(8088, function() { let host = server.address().address; let port = server.address().port; diff --git a/src/stores/commonStore.js b/src/stores/commonStore.js index 100725a2..561c25d7 100644 --- a/src/stores/commonStore.js +++ b/src/stores/commonStore.js @@ -10,13 +10,25 @@ export const UserInfo = types.model('UserInfo', { export const CommonStore = types .model('CommonStore', { userInfo: types.maybe(UserInfo), - }) + + }).volatile(self => ({ + ledgers: [], + defaultledger:'', + })) .views(self => ({ + get isDemo() { return self.userInfo.pin && self.userInfo.pin.trim().toLowerCase() === 'jd_653e751552511'; } })) .actions(self => ({ + //设置当前账本 + setDefaultLedger(v){ + self.defaultledger=v; + }, + getDefaultLedger(){ + return localStorage.getItem("clusterID"); + }, getCurrentUserInfo() { return fetchData(`${__HOST}/common/getCurrentUserInfo`, self.setCurrentUserInfo, @@ -37,7 +49,28 @@ export const CommonStore = types duration: null }); } - } + }, + getLedgersInfo() { + return fetchData(`${__HOST}/ledgers`, + self.setLedgersInfo, + null, { method: 'get' }) + .catch((ex) => { + Notification.error({ + description: '获取账本信息异常:' + ex, + duration: null + }); + }); + }, + setLedgersInfo(result) { + if (result.success) { + self.ledgers = result.data; + } else { + Notification.error({ + description: '获取账本信息错误:' + result.message, + duration: null + }); + } + }, })); export const Category = types.model('Category', { diff --git a/src/stores/pages/searchStore.js b/src/stores/pages/searchStore.js index 82ec37aa..e9865c4d 100644 --- a/src/stores/pages/searchStore.js +++ b/src/stores/pages/searchStore.js @@ -1,6 +1,6 @@ import { types } from 'mobx-state-tree'; import { observable, toJS } from 'mobx'; -import fetchData from 'flarej/lib/utils/fetchData'; +import { fetchData } from '../../utils/fetchConfig'; import Notification from '../../utils/notification'; const SearchStore = types @@ -27,53 +27,8 @@ const SearchStore = types menuIds: null, authTreeData: null, menuData: null, - detailData: [] - })) - .views(self => ({ - //获取树节点的展开形式 - getExpandedKeys(arr) { - return arr.filter(n => n.level == 1 || n.level == 2).map(m => { - return m.id.toString(); - }); - }, - - getDefaultCheckedKeys() { - let keys = []; - self.menuData.filter(n => n.level == 3) - .forEach(item => { - if (item.selected) { - keys.push(item.id.toString()); - } - }); - return keys; - }, - - getAuthTreeDataMap(authList) { - const authTreeDataMap = {}; - authList.forEach(node => { - authTreeDataMap[node.id] = node; - }); - - return authTreeDataMap; - }, - - getAuthTreeData(authList, authMap, level = 1, node, pids = []) { - if (level == 4) { - return null; - } - - return authList - .filter(n => n.level == level && (!node ? true : n.pid == node.id.toString())) - .map(n => { - authMap[n.id].pids = pids; - - return { - key: n.id.toString(), - title: n.name, - children: self.getAuthTreeData(authList, authMap, level + 1, n, [...pids, n.id.toString()]) - }; - }); - } + detailData: [], + blockHeight:0,// 区块高度 })) .actions(self => ({ afterCreate() { @@ -167,7 +122,7 @@ const SearchStore = types }, getRoleManagementData(params) { - return fetchData(`${__HOST}/search/getRoleManagementData`, + return fetchData(`${__HOST}/api/v1/search`, self.setRoleManagementData, params, { method: 'get' }) .catch((ex) => { @@ -282,7 +237,111 @@ const SearchStore = types } else { Notification.error({ description: '删除角色数据异常:' + result.message, duration: null }); } - } + }, + // 获取区块高度 + getBlockHeight(param) { + fetchData(`${__HOST}/ledgers/${param}/blocks/latest`, + self.setBlockHeight, + '', { + method: 'get', + headers: { + cookie: document.cookie, + } + } + ).catch(error => { + console.log(error); + }); + }, + + setBlockHeight(result) { + if (result&&result.success) { + self.blockHeight=result.data.height||0; + } + // let response = result; + // this.overviewHeadData.blockHeight = response && response.data && response.data.height ? response.data.height : 0; + }, + + // 获取交易总数 + getTransactionTotal() { + fetchData(`${G_WEB_DOMAIN}/ledgers/${localStorage.defaultValue}/txs/count`, + this.setTransactionTotal, + '', { + method: 'get', + headers: { + // accept: 'application/json', + cookie: document.cookie, + } + } + ).catch(error => { + console.log(error); + }); + }, + + setTransactionTotal(result) { + let response = result; + this.overviewHeadData.transactionTotal = response && response.data ? response.data : 0; + }, + + // 获取用户总数 + getUserTotal() { + fetchData(`${G_WEB_DOMAIN}/ledgers/${localStorage.defaultValue}/users/count`, + this.setUserTotal, + '', { + method: 'get', + headers: { + // accept: 'application/json', + cookie: document.cookie, + } + } + ).catch(error => { + console.log(error); + }); + }, + setUserTotal(result) { + let response = result; + this.overviewHeadData.userTotal = response && response.data ? response.data : 0; + }, + + // 获取数据账户总数 + getLedgerTotal() { + fetchData(`${G_WEB_DOMAIN}/ledgers/${localStorage.defaultValue}/accounts/count`, + this.setLedgerTotal, + '', { + method: 'get', + headers: { + // accept: 'application/json', + cookie: document.cookie, + } + } + ).catch(error => { + console.log(error); + }); + }, + + setLedgerTotal(result) { + let response = result; + this.overviewHeadData.dataLedgersTotal = response && response.data ? response.data : 0; + }, + + // 合约总数 + getContractTotal() { + fetchData(`${G_WEB_DOMAIN}/ledgers/${localStorage.defaultValue}/contracts/count`, + this.setContractTotal, + '', { + method: 'get', + headers: { + // accept: 'application/json', + cookie: document.cookie, + } + } + ).catch(error => { + console.log(error); + }); + }, + setContractTotal(result) { + let response = result; + this.overviewHeadData.contractTotal = response && response.data ? response.data : 0; + }, })); export default SearchStore; \ No newline at end of file diff --git a/src/utils/fetchConfig.js b/src/utils/fetchConfig.js new file mode 100644 index 00000000..0460bc4c --- /dev/null +++ b/src/utils/fetchConfig.js @@ -0,0 +1,74 @@ +import querystring from 'querystring'; +export function handleErrors(response) { + if (response.status*1==401) { + var keys=document.cookie.match(/[^ =;]+(?=\=)/g); + if (keys) { + for (var i = keys.length; i--;) { + document.cookie=keys[i]+'="";expires=' + new Date(0).toUTCString()+";path=/;"; + document.cookie=keys[i]+'="";expires=' + new Date(0).toUTCString()+";path=/;domain=."+window.location.hostname; + } + } + window.location.href="https://"+window.location.host+"/login"; + return; + } + if (response.status*1==400) { + return response; + } + if (!response.ok) { + throw Error(response.statusText); + } + return response; +} + +const _defaultOptions = { useApplicationJson: true }; +export function setDefaultOptions(options = {}) { + return Object.assign(_defaultOptions, options); +} + +export function fetchData(url, callback, params, cfgs) { + const configs = Object.assign({ + method: 'get', + credentials: 'include', + mode: 'cors', + cache: 'reload' + }, _defaultOptions, cfgs); + + configs.method = configs.method.toLowerCase(); + if (params) { + if (configs.method === 'get') { + if (url.indexOf('?')>-1) { + url +=querystring.encode(params); + } + else{ + url += '?' + querystring.encode(params); + } + } else if (configs.method === 'post' || configs.method === 'put' || configs.method === 'delete') { + if (configs.useApplicationJson) { + if (!configs.headers) { + configs.headers = {}; + } + if (!configs.headers.Accept) { + configs.headers.Accept = 'application/json'; + } + if (!configs.headers['Content-Type']) { + configs.headers['Content-Type'] = 'application/json'; + } + configs.body = JSON.stringify(params); + } else if (configs.useApplicationForm) { + if (!configs.headers['Content-Type']) { + configs.headers['Content-Type'] = 'application/x-www-form-urlencoded'; + } + configs.body = querystring.encode(params); + } else { + configs.body = params; + } + } + } + + return fetch(url, configs) + .then(handleErrors) + .then((response) => { + return response.json(); + }) + .then(callback); +} \ No newline at end of file diff --git a/src/web/components/header/header.js b/src/web/components/header/header.js index 2ede1039..3d381748 100644 --- a/src/web/components/header/header.js +++ b/src/web/components/header/header.js @@ -14,8 +14,10 @@ import template from './header.t.html'; export default class Header extends Component { render() { + const { store: { common } } = this.props; return template(this.props, this, { styles, + common, headerPic: require('../../images/pic-header.png') }); } diff --git a/src/web/components/header/header.scss b/src/web/components/header/header.scss index abe88388..89dd548d 100644 --- a/src/web/components/header/header.scss +++ b/src/web/components/header/header.scss @@ -2,13 +2,13 @@ font-size: 16px; height: 79px; border-bottom: 1px solid #ebebeb; - position: fixed; width: 100%; z-index: 100; transition: all 0.5s ease-out; box-shadow: 0 1px 3px 0 rgba(0, 34, 77, 0.05); background: linear-gradient(90deg,#5a77d3,#3c4c9c); display: flex; + flex: auto 0 0; .nav { font-size: 0.875rem; @@ -39,7 +39,7 @@ .note{ color: #fff; float:right; - padding-right: 30px; + padding: 22px; .value{ width: 200px; border: 1px solid #ADC6FF; @@ -54,7 +54,7 @@ float: left; text-align: center; line-height: 80px; - margin-left: 60px; + margin-left: 20px; position: relative; height: 79px; overflow: hidden; @@ -124,4 +124,20 @@ } } } + + .footContent { + display: flex; + justify-content: center; + align-items: center; + font-family: MicrosoftYaHei; + font-size: 12px; + color: #999999; + .linker { + text-decoration: none; + color: #5A77D3; + } + .linker:hover { + color: #5A77D3; + } +} } diff --git a/src/web/components/header/header.t.html b/src/web/components/header/header.t.html index 6bfc623a..c9dce6cb 100644 --- a/src/web/components/header/header.t.html +++ b/src/web/components/header/header.t.html @@ -1,10 +1,10 @@ \ No newline at end of file diff --git a/src/web/css/app.scss b/src/web/css/app.scss index d6c3d5c4..80dcf266 100644 --- a/src/web/css/app.scss +++ b/src/web/css/app.scss @@ -69,7 +69,7 @@ table { body { color: #333; - background: #f4f5f8; + background: #f2f3f5; -webkit-appearance: none; -webkit-font-smoothing: auto; font-size: 14px; @@ -224,3 +224,21 @@ div.fj-area-chart-area { margin-right: 30px; float: left; } + +.footContent{ + flex: 0 0 auto; + text-align: center; + line-height: 52px; + border-top: 1px solid #e8e8e9; + margin: 0 30px; +} + +#app,#outer-container{ + height: 100%; + display: flex; + flex-direction: column; + flex: auto; +} +#page-wrap{ + flex: auto; +} \ No newline at end of file diff --git a/src/web/images/blockheightIcon.svg b/src/web/images/blockheightIcon.svg new file mode 100644 index 00000000..6fa7fc7f --- /dev/null +++ b/src/web/images/blockheightIcon.svg @@ -0,0 +1 @@ +区块高度 icon \ No newline at end of file diff --git a/src/web/images/contractIcon.svg b/src/web/images/contractIcon.svg new file mode 100644 index 00000000..6cc42d71 --- /dev/null +++ b/src/web/images/contractIcon.svg @@ -0,0 +1 @@ +合约总数icon \ No newline at end of file diff --git a/src/web/images/ledgersIcon.svg b/src/web/images/ledgersIcon.svg new file mode 100644 index 00000000..6140d88f --- /dev/null +++ b/src/web/images/ledgersIcon.svg @@ -0,0 +1 @@ +账户总数icon \ No newline at end of file diff --git a/src/web/images/overview_bg.png b/src/web/images/overview_bg.png new file mode 100644 index 0000000000000000000000000000000000000000..7b703eb955a532534de87f2d0676f1fe961cc2e2 GIT binary patch literal 25734 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交易总数icon \ No newline at end of file diff --git a/src/web/images/userIcon.svg b/src/web/images/userIcon.svg new file mode 100644 index 00000000..3cae047a --- /dev/null +++ b/src/web/images/userIcon.svg @@ -0,0 +1,23 @@ + + + + 用户总数 icon + Created with Sketch. + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/src/web/pages/search/search.js b/src/web/pages/search/search.js index 19af9fac..60eb8e6f 100644 --- a/src/web/pages/search/search.js +++ b/src/web/pages/search/search.js @@ -14,7 +14,6 @@ import 'flarej/lib/components/antd/tree'; import 'flarej/lib/components/antd/checkbox'; import Modal from 'flarej/lib/components/antd/modal'; import Tree from 'flarej/lib/components/antd/tree'; -import Input from 'flarej/lib/components/antd/input'; import Message from 'flarej/lib/components/antd/message'; import Notification from '../../../utils/notification'; import styles from './search.m.scss'; @@ -36,352 +35,17 @@ export default class Search extends Component { const closeLoading = Message.loading('正在获取数据...', 0); Promise.all([ - search.getRoleManagementData(), - search.getRoleMenuTree().then(() => search.initTree()) + search.getBlockHeight(this.props.store.common.getDefaultLedger()), ]).then(() => { closeLoading(); }); } - @autobind - onInputRole(e) { - this.inputRole = e.target.value; - } - - @autobind - onSearch() { - if (this.inputRole == '') { - const closeLoading = Message.loading('正在获取数据...', 0); - Promise.all([ - this.props.store.search.getRoleManagementData(), - ]).then(() => { - closeLoading(); - }); - } else { - const { store: { search } } = this.props; - const searchRole = search.tableDataO.filter(n => n.name.indexOf(this.inputRole.trim()) > -1); - search.setTableData(searchRole); - } - } - - @autobind - onAddRole() { - const { store: { search } } = this.props; - search.setAddModalVisible(true); - search.setDisable(true); - search.setActiveKey('tab1'); - search.setAddInputRole(''); - search.setAddInputDes(''); - } - - @autobind - onDeleteRole() { - const { store: { search } } = this.props; - if (this.selectedRowKeys.length == 0) { - Notification.error({ description: '请勾选要删除的角色!', duration: 3 }); - } else { - Modal.confirm({ - title: '你确认要删除角色吗?', - onOk: () => { - const closeLoading = Message.loading('正在获取数据...', 0); - const roleId = this.selectedRows.map((item) => item.roleId); - - Promise.all([ - search.deleteRole({ roleId: roleId }) - ]).then(() => { - search.getRoleManagementData(); - }).then(() => { - this.selectedRowKeys = []; - closeLoading(); - }); - } - }); - } - } - - @computed get tableColumns() { - return [{ - title: '序号', - dataIndex: 'key', - }, { - title: '角色名称', - dataIndex: 'name', - }, { - title: '角色描述', - dataIndex: 'describe', - }, { - title: '创建时间', - dataIndex: 'cTime', - }, { - title: '修改时间', - dataIndex: 'mTime', - }, { - title: '操作', - dataIndex: 'handler', - render: (text, record, index) => nj ` - - this.onEdit(record, index)} className="btn-link">编辑 - this.onDetail(record, index)} className="btn-link">用户明细 - - ` (), - }]; - } - - @autobind - onEdit(record, index) { - const { store: { search } } = this.props; - search.setEditModalVisible(true); - search.setSaveBtnDisabled(true); - search.setActiveKey('tab1'); - search.setAddInputRole(record.name); - search.setAddInputDes(record.describe); - search.setRoleId(record.roleId); - search.setDisable(false); - - const closeLoading = Message.loading('正在获取数据...', 0); - Promise.all([ - search.getRoleMenuTree({ roleId: record.roleId }).then(() => search.initTree()), - ]).then(() => { - closeLoading(); - }); - } - - @autobind - onDetail(record, index) { - const { store: { search } } = this.props; - search.setDetailModalVisible(true); - search.setDetailData(record.users); - } - - getRowSelection() { - return { - selectedRowKeys: this.selectedRowKeys, - onChange: (selectedRowKeys, selectedRows) => { - this.selectedRowKeys = selectedRowKeys; - this.selectedRows = selectedRows; - } - }; - } - render() { const { store: { search } } = this.props; return tmpls.container(this.props, this, { styles, search, - tableData: toJS(search.tableData), - rowSelection: this.getRowSelection(), - }); - } -} - -@registerTmpl('ModalFormSearch') -@inject('store') -@observer -class ModalForm extends Component { - @observable autoExpandParent = false; - - //获取树节点的展开形式 - getExpandedKeys(arr) { - return arr.filter(n => n.level == 1 || n.level == 2).map(m => { return m.id.toString(); }); - } - - getDefaultCheckedKeys() { - let keys = []; - this.props.store.search.menuData.filter(n => n.level == 3) - .forEach(item => { - if (item.selected) { - keys.push(item.id.toString()); - } - }); - return keys; - } - - //获取选中的 checkbox 包含父级未选中状态 - getAllCheckedKeys(key) { - const _map = toJS(this.props.store.search.authTreeDataMap); - if (key.length > 1) { - let pids = key.map(item => { return _map[item].pids; }); - return Array.from(new Set([].concat(...pids))); - } else { - return _map[key].pids; - } - } - - @autobind - onExpand(expandedKeys) { - const { store: { search } } = this.props; - search.setExpandedKeys(expandedKeys); - this.autoExpandParent = true; - } - - @autobind - onCheck(checkedKeys) { - const { store: { search } } = this.props; - search.setSaveBtnDisabled(false); - search.setCheckedKeys(checkedKeys); - - if (checkedKeys.length == 0) { - search.setMenuIds([]); - } else { - let allChecked = Array.from(new Set(this.getAllCheckedKeys(checkedKeys).concat(checkedKeys))); - search.setMenuIds(allChecked); - } - } - - @autobind - onAddModalCancel() { - if (this.props.tabName == '增加角色') { - this.props.store.search.setAddModalVisible(false); - } - else { - this.props.store.search.setEditModalVisible(false); - } - this.props.store.search.setSaveBtnDisabled(false); - } - - @autobind - onTabChange(key) { - this.props.store.search.setActiveKey(key); - } - - @autobind - onAddInputRoleChange(e) { - this.props.store.search.setAddInputRole(e.target.value); - } - - @autobind - onAddInputDesChange(e) { - this.props.store.search.setAddInputDes(e.target.value); - } - - @autobind - onAddSaveRole() { - const { store: { search } } = this.props; - - if (search.addInputRole.trim() == '') { - Notification.error({ description: '请输入角色名称!', duration: 1 }); - } else { - const closeLoading = Message.loading('正在获取数据...', 0); - let params = { - roleName: search.addInputRole, - roleDescribe: search.addInputDes - }; - if (this.props.tabName == '编辑角色' && search.roleId != null) { - params.roleId = search.roleId; - } - - Promise.all([ - search.saveRole(params) - ]).then(() => { - search.getRoleManagementData(); - }).then(() => { - search.setActiveKey('tab2'); - closeLoading(); - }); - } - } - - @autobind - onAddCancel() { - const { store: { search } } = this.props; - if (this.props.tabName == '增加角色') { - search.setAddModalVisible(false); - } else { - search.setEditModalVisible(false); - } - } - - @autobind - onSavePermission() { - const { store: { search } } = this.props; - - if (this.props.tabName == '增加角色') { - console.log(search.menuIds); - search.saveRolePermission({ - roleId: search.addRoleId, - menuIds: search.menuIds - }).then(() => search.setAddModalVisible(false)); - } else { - search.saveRolePermission({ - roleId: search.roleId, - menuIds: search.menuIds - }).then(() => search.setEditModalVisible(false)); - } - } - - disabledTreeNodes = ['权限管理', '角色管理']; - - render() { - const { store: { search } } = this.props; - const TreeNode = Tree.TreeNode; - let level = 1; - const loop = data => data.map((item) => { - const disableCheckbox = this.disabledTreeNodes.indexOf(item.title) > -1 ? true : false; - - if (item.children) { - const disabled = level == 1 ? true : item.children.filter(n => this.disabledTreeNodes.indexOf(n.title) > -1).length > 0; - level++; - - return nj ` - <${TreeNode} key=${item.key} title=${item.title} disableCheckbox=${disableCheckbox} disabled=${disabled}> - ${loop(item.children)} - - ` (); - } - return nj `<${TreeNode} key=${item.key} title=${item.title} disableCheckbox=${disableCheckbox} />` (); - }); - - return tmpls.modalForm({ - components: { 'ant-TextArea': Input.TextArea }, - styles, - search, - loop, - treeData: toJS(search.authTreeData) || [], - }, this.props, this); - } -} - -@registerTmpl('ModalDetailSearch') -@inject('store') -@observer -class ModalDetail extends Component { - @autobind - onDetailModalCancel() { - const { store: { search } } = this.props; - search.setDetailModalVisible(false); - } - - @computed get detailColumns() { - return [{ - title: '序号', - dataIndex: 'key', - }, { - title: '登录名', - dataIndex: 'loginName', - }, { - title: '姓名', - dataIndex: 'name', - }, { - title: '邮箱', - dataIndex: 'email', - }, { - title: '部门', - dataIndex: 'department', - }, { - title: '职务', - dataIndex: 'duty', - }, { - title: '开通时间', - dataIndex: 'oTime', - }]; - } - - render() { - const { store: { search } } = this.props; - return tmpls.modalDetail(this.props, this, { - styles, - search, - getDetailRowKey: (record, index) => `${record.key}-${index}` }); } } \ No newline at end of file diff --git a/src/web/pages/search/search.m.scss b/src/web/pages/search/search.m.scss index ae7f4613..2f775279 100644 --- a/src/web/pages/search/search.m.scss +++ b/src/web/pages/search/search.m.scss @@ -1,92 +1,160 @@ .search { - background-color: #fff; - padding: 100px 40px 40px; + padding:0 30px; h2 { margin-bottom: 25px; - font-size: 16px; + font-size: 20px; + line-height: 70px; + height: 70px; + border-bottom: 1px solid #e8e8e9; } - .handlerBox { - margin-bottom: 20px; - border-bottom: 1px solid #eee; - padding-bottom: 20px; - } - - .handlerBox:after { - content: ''; - display: table; - clear: both; - } - - .lable { - float: left; - margin-right: 10px; - line-height: 28px; - } - - .input { - width: 200px; - margin-right: 20px; - border-color: #d9d9d9; - } -} - -.btnArea { - text-align: center; - padding: 10px; -} - -.treeWrap { - height: 420px; - overflow: scroll; - overflow-x: hidden; -} + .main{ + margin: 100px auto 0 auto; -.checks { - border-top: 1px solid #eaeaea; - margin-top: 15px; - padding: 15px 0; - text-align: center; -} - -:global { - .ant-table-thead tr th { - text-align: center; - } - - .ant-table-tbody tr td { - text-align: center; - padding: 10px 5px; - - .btn-link { - margin: 0 5px; + .headtitle{ + font-size: 36px; + font-weight: bold; + text-align: center; } - } - .frombox { - padding: 20px; - - li { - margin-bottom: 10px; - display: block; + .action{ + width:1000px; + height:100px; + margin: 15px auto 0 auto; + border-radius: 5px; + box-shadow: 0px 0px 14px #5a77d3; + background: linear-gradient(90deg, #5a77d3, #3c4c9c); + .bg{ + height: inherit; + background: url(../../images/overview_bg.png) no-repeat; + display: flex; + justify-content: center; + align-items: center; + + .title{ + font-size: 14px; + color: #fff; + } + + .input{ + width: 676px; + margin: 0 15px; + } + + .btn{ + background-color: #3c4c9c; + color: #fff; + border: 1px solid #819df3; + } + } } - - .textarea { + + .summary { width: 100%; - border: 1px solid #d9d9d9; + display: flex; + flex-direction: row; + justify-content: center; + margin-top: 100px; + margin-bottom: 30px; + // 区块高度等页签样式 + .tabs { + height: 132px; + width:243px; + margin-right: 30px; + padding: 24px; + box-shadow: 0 0 8px 0 rgba(0,0,0,0.08); + border-radius: 4px; + .span { + display: flex; + flex-direction: row; + .left { + width: 75%; + } + .right { + width: 25%; + .logo { + min-width: 60px; + background-size: 60px 67px; + width: 100%; + height: 160px; + } + .logoBH { + background: url('../../images/blockheightIcon.svg') no-repeat; + } + .logoTR { + background: url('../../images/transactionIcon.svg') no-repeat; + } + .logoUS { + background: url('../../images/userIcon.svg') no-repeat; + } + .logoLE { + background: url('../../images/ledgersIcon.svg') no-repeat; + } + .logoCO { + background: url('../../images/contractIcon.svg') no-repeat; + } + } + } + } + + .blockHeight { + background: #0DB18C; + background-image: url('../../images/overview_bg.png'); + background-repeat: no-repeat; + background-size: 250px; + } + + .transactions { + background: #10A647; + background-image: url('../../images/overview_bg.png'); + background-repeat: no-repeat; + background-size: 250px; + } + + .users { + background: #037CC1; + background-image: url('../../images/overview_bg.png'); + background-repeat: no-repeat; + background-size: 250px; + } + + .ledgers { + background: #5A77D2; + background-image: url('../../images/overview_bg.png'); + background-repeat: no-repeat; + background-size: 250px; + } + + .contracts { + background: #3C4C9C; + margin-right: 0; + background-image: url('../../images/overview_bg.png'); + background-repeat: no-repeat; + background-size: 250px; + } + + .title { + font-size: 14px; + color: #FFFFFF; + line-height: 14px; + } + + .data { + font-family: ArialMT; + font-size: 3em; + color: #FFFFFF; + line-height: 54px; + margin-top: 27px; + } + } - .red:before { - content: '*'; - color: red; - font-size: 14px; - position: absolute; - margin: 3px; + .list{ + width: 100%; + background: #fff; + border-radius: 4px; + padding: 30px; } } - - .btn { - margin-right: 20px; - } } diff --git a/src/web/pages/search/search.t.html b/src/web/pages/search/search.t.html index 7cb076e1..75cadcac 100644 --- a/src/web/pages/search/search.t.html +++ b/src/web/pages/search/search.t.html @@ -1,65 +1,203 @@ - - - - \ No newline at end of file diff --git a/webpack.config.js b/webpack.config.js index 3a9059fa..3d94d27d 100644 --- a/webpack.config.js +++ b/webpack.config.js @@ -8,6 +8,7 @@ const isProd = process.env.NODE_ENV == 'production'; const isTest = process.env.NODE_ENV == 'test'; const isLocal = process.env.Project == 'local'; +const isSelf = true;// true使用代理服务,false不使用 const pxToRem = require('postcss-pxtorem'); const VERSION = '20170928'; const modifyVars = Object.assign({}); @@ -204,6 +205,18 @@ module.exports = { ] } ] + }, + devServer: { + proxy: [ + { + context: ['/auth', '/api'], + target: 'http://192.168.151.39:10001', + }, + { + context: ['/ledgers'], + target: 'http://192.168.151.45:8081', + }, + ] } }; @@ -240,7 +253,7 @@ module.exports.plugins = [ new webpack.NamedModulesPlugin(), new webpack.DefinePlugin({ __ENV: isProd || isTest ? "'pro'" : "'dev'", - __HOST: isProd || isTest ? "''" : "'http://localhost:8089'", + __HOST: isProd || isTest || isSelf ? "''" : "'http://localhost:8088'", 'process.env': { NODE_ENV: JSON.stringify(isProd ? 'production' : 'development') } -- GitLab