diff --git a/web-react/src/pages/system/machine/base.jsx b/web-react/src/pages/system/machine/base.jsx
index 9437b73..47403fe 100644
--- a/web-react/src/pages/system/machine/base.jsx
+++ b/web-react/src/pages/system/machine/base.jsx
@@ -13,7 +13,7 @@ export default class base extends Component {
{hostName}
diff --git a/web-react/src/pages/system/machine/index.jsx b/web-react/src/pages/system/machine/index.jsx
index fa6a8a9..55155a3 100644
--- a/web-react/src/pages/system/machine/index.jsx
+++ b/web-react/src/pages/system/machine/index.jsx
@@ -21,8 +21,10 @@ export default class index extends Component {
}
async componentDidMount() {
- const { data: base } = await api.sysMachineBase()
- this.setState({ loading: false, base })
+ try {
+ const { data: base } = await api.sysMachineBase()
+ this.setState({ loading: false, base })
+ } catch {}
}
render() {
diff --git a/web-react/src/pages/system/machine/use-charts.jsx b/web-react/src/pages/system/machine/use-charts.jsx
index 2693159..22f903b 100644
--- a/web-react/src/pages/system/machine/use-charts.jsx
+++ b/web-react/src/pages/system/machine/use-charts.jsx
@@ -14,6 +14,8 @@ export default class useCharts extends Component {
timer = null
timerMoment = null
+ actived = true
+
systemStart = moment()
now = Date.now()
@@ -27,6 +29,7 @@ export default class useCharts extends Component {
shouldComponentUpdate(props) {
// 当前页签未选中时停止获取状态
if (this.props.actived !== props.actived) {
+ this.actived = props.actived
if (props.actived) {
this.start()
} else {
@@ -53,9 +56,7 @@ export default class useCharts extends Component {
}
start() {
- this.timer = setInterval(() => {
- this.refreshData()
- }, 3000)
+ this.actived = true
this.refreshData()
this.timerMoment = setInterval(() => {
this.setState({ nowMoment: moment() })
@@ -63,7 +64,8 @@ export default class useCharts extends Component {
}
stop() {
- clearInterval(this.timer)
+ this.actived = false
+ clearTimeout(this.timer)
clearInterval(this.timerMoment)
}
@@ -91,6 +93,11 @@ export default class useCharts extends Component {
})
this.setState({ use })
+
+ if (this.actived)
+ this.timer = setTimeout(() => {
+ this.refreshData()
+ }, 3000)
}
initCpuChart() {
diff --git a/web-react/src/pages/system/notice/form.jsx b/web-react/src/pages/system/notice/form.jsx
new file mode 100644
index 0000000..190f4cd
--- /dev/null
+++ b/web-react/src/pages/system/notice/form.jsx
@@ -0,0 +1,156 @@
+import React, { Component } from 'react'
+import { Form, Spin, Input, Radio, Select } from 'antd'
+import { api } from 'common/api'
+import { AntIcon, BraftEditor } from 'components'
+import getDictData from 'util/dic'
+import { cloneDeep } from 'lodash'
+// import BraftEditor from 'braft-editor'
+// import 'braft-editor/dist/index.css'
+const initialValues = {}
+
+export default class form extends Component {
+ state = {
+ // 加载状态
+ loading: true,
+ options: {
+ userList: [],
+ },
+ codes: {
+ noticeType: [],
+ noticeStatus: [],
+ },
+ }
+
+ // 表单实例
+ form = React.createRef()
+
+ // 初始化数据
+ record = {}
+
+ /**
+ * mount后回调
+ */
+ componentDidMount() {
+ this.props.created && this.props.created(this)
+ this.isLivinig = true
+ // 3秒后更改编辑器内容
+ }
+
+ /**
+ * 填充数据
+ * 可以在设置this.record之后对其作出数据结构调整
+ * [异步,必要]
+ * @param {*} params
+ */
+ async fillData(params) {
+ //#region 从后端转换成前段所需格式,也可以在此处调用获取详细数据接口
+ if (params.id) {
+ this.record = (await api.sysNoticeDetail({ id: params.id })).data
+ }
+ const {
+ data: { items: userList },
+ } = await this.onLoadUser()
+ const codes = await getDictData('notice_status', 'notice_type')
+ //#endregion
+ this.form.current.setFieldsValue(this.record)
+
+ this.setState({
+ loading: false,
+ options: {
+ userList,
+ },
+ codes,
+ })
+ }
+ async onLoadUser() {
+ const data = await api.getUserPage()
+ return data
+ }
+ /**
+ * 获取数据
+ * 可以对postData进行数据结构调整
+ * [异步,必要]
+ * @returns
+ */
+ async getData() {
+ const form = this.form.current
+
+ const valid = await form.validateFields()
+ if (valid) {
+ const postData = form.getFieldsValue()
+ if (this.record) {
+ postData.id = this.record.id
+ }
+ //#region 从前段转换后端所需格式
+ //#endregion
+ return postData
+ }
+ }
+
+ //#region 自定义方法
+ //#endregion
+
+ render() {
+ const { options, codes } = this.state
+
+ return (
+
+ )
+ }
+}
diff --git a/web-react/src/pages/system/notice/index.jsx b/web-react/src/pages/system/notice/index.jsx
new file mode 100644
index 0000000..0b37040
--- /dev/null
+++ b/web-react/src/pages/system/notice/index.jsx
@@ -0,0 +1,279 @@
+import React, { Component } from 'react'
+import { Button, Card, Form, Input, message as Message, Popconfirm, Select } from 'antd'
+import { AntIcon, Auth, Container, ModalForm, QueryTable, QueryTableActions } from 'components'
+import { api } from 'common/api'
+import auth from 'components/authorized/handler'
+import { isEqual } from 'lodash'
+import getDictData from 'util/dic'
+import { toCamelCase } from 'util/format'
+import FormBody from './form'
+
+/**
+ * 注释段[\/**\/]为必须要改
+ */
+
+/**
+ * 配置页面所需接口函数
+ */
+const apiAction = {
+ page: api.sysNoticePage,
+ add: api.sysNoticeAdd,
+ edit: api.sysNoticeEdit,
+ delete: api.sysNoticeDelete,
+ Detail: api.sysNoticeDetail,
+ Status: api.sysNoticeChangeStatus,
+}
+
+/**
+ * 用于弹窗标题
+ * [必要]
+ */
+const name = '通知公告'
+
+/**
+ * 统一配置权限标识
+ * [必要]
+ */
+const authName = '/**/'
+
+export default class index extends Component {
+ state = {
+ codes: {
+ noticeStatus: [],
+ noticeType: [],
+ },
+ }
+
+ // 表格实例
+ table = React.createRef()
+
+ // 新增窗口实例
+ addForm = React.createRef()
+ // 编辑窗口实例
+ editForm = React.createRef()
+
+ columns = [
+ {
+ title: '标题',
+ dataIndex: 'title',
+ },
+ {
+ title: '类型',
+ dataIndex: 'type',
+ render: text => this.bindCodeValue(text, 'notice_type'),
+ },
+ {
+ title: '状态',
+ dataIndex: 'status',
+ render: text => this.bindCodeValue(text, 'notice_status'),
+ },
+ ]
+
+ /**
+ * 构造函数,在渲染前动态添加操作字段等
+ * @param {*} props
+ */
+ constructor(props) {
+ super(props)
+
+ const flag = auth({ [authName]: [['edit'], ['delete']] })
+
+ if (flag) {
+ this.columns.push({
+ title: '操作',
+ width: 150,
+ dataIndex: 'actions',
+ render: (text, record) => (
+
+
+ this.onOpen(this.editForm, record.id)}>编辑
+
+
+ this.onDelete(record.id)}
+ >
+ 删除
+
+
+
+ ),
+ })
+ }
+ }
+
+ /**
+ * 阻止外部组件引发的渲染,提升性能
+ * 可自行添加渲染条件
+ * [必要]
+ * @param {*} props
+ * @param {*} state
+ * @returns
+ */
+ shouldComponentUpdate(props, state) {
+ return !isEqual(this.state, state)
+ }
+
+ /**
+ * 加载字典数据,之后开始加载表格数据
+ * 如果必须要加载字典数据,可直接对表格设置autoLoad=true
+ */
+ componentDidMount() {
+ const { onLoading, onLoadData } = this.table.current
+ onLoading()
+ getDictData('notice_status', 'notice_type').then(codes => {
+ this.setState({ codes }, () => {
+ onLoadData()
+ })
+ })
+ }
+
+ /**
+ * 调用加载数据接口,可在调用前对query进行处理
+ * [异步,必要]
+ * @param {*} params
+ * @param {*} query
+ * @returns
+ */
+ loadData = async (params, query) => {
+ const { data } = await apiAction.page({
+ ...params,
+ ...query,
+ })
+ return data
+ }
+
+ /**
+ * 绑定字典数据
+ * @param {*} code
+ * @param {*} name
+ * @returns
+ */
+ bindCodeValue(code, name) {
+ name = toCamelCase(name)
+ const codes = this.state.codes[name]
+ if (codes) {
+ const c = codes.find(p => p.code == code)
+ if (c) {
+ return c.value
+ }
+ }
+ return null
+ }
+
+ /**
+ * 打开新增/编辑弹窗
+ * @param {*} modal
+ * @param {*} id
+ */
+ onOpen(modal, id) {
+ modal.current.open({
+ id,
+ })
+ }
+
+ /**
+ * 对表格上的操作进行统一处理
+ * [异步]
+ * @param {*} action
+ * @param {*} successMessage
+ */
+ async onAction(action, successMessage) {
+ const { onLoading, onLoaded, onReloadData } = this.table.current
+ onLoading()
+ try {
+ if (action) {
+ await action
+ }
+ if (successMessage) {
+ Message.success(successMessage)
+ }
+ onReloadData()
+ } catch {
+ onLoaded()
+ }
+ }
+
+ /**
+ * 删除
+ * @param {*} id
+ */
+ onDelete(id) {
+ this.onAction(apiAction.delete({ id }), '删除成功')
+ }
+
+ //#region 自定义方法
+ //#endregion
+
+ render() {
+ const { codes } = this.state
+ return (
+
+
+
+
+
+
+
+
+
+
+
+ }
+ operator={
+
+ }
+ onClick={() => this.onOpen(this.addForm)}
+ >
+ 新增{name}
+
+
+ }
+ />
+
+
+
+ this.table.current.onReloadData()}
+ >
+
+
+
+
+
+ this.table.current.onReloadData()}
+ >
+
+
+
+
+ )
+ }
+}
diff --git a/web-react/src/pages/system/org/index.jsx b/web-react/src/pages/system/org/index.jsx
index d671ce5..76ac8f1 100644
--- a/web-react/src/pages/system/org/index.jsx
+++ b/web-react/src/pages/system/org/index.jsx
@@ -1,5 +1,5 @@
import React, { Component } from 'react'
-import { Button, Card, Form, Input, message as Message, Popconfirm } from 'antd'
+import { Button, Card, Form, Input, message as Message, Popconfirm, Select } from 'antd'
import {
AntIcon,
Auth,
@@ -159,7 +159,10 @@ export default class index extends Component {
...query,
pid: this.selectId,
}
-
+ if (params) {
+ params.sortField = 'areaCode'
+ params.sortOrder = 'ascend'
+ }
const { data } = await apiAction.page({
...params,
...query,
@@ -270,6 +273,17 @@ export default class index extends Component {
+
+
+
}
operator={
diff --git a/web-react/src/pages/system/user/form.jsx b/web-react/src/pages/system/user/form.jsx
index 204c88a..a33b5ed 100644
--- a/web-react/src/pages/system/user/form.jsx
+++ b/web-react/src/pages/system/user/form.jsx
@@ -298,7 +298,7 @@ export default class form extends Component {
>
- {this.props.mode == 'add' && (
+ {/* {this.props.mode == 'add' && (
<>
>
- )}
+ )} */}
@@ -350,10 +350,31 @@ export default class form extends Component {
-
+
-
+
diff --git a/web-react/src/pages/system/user/index.jsx b/web-react/src/pages/system/user/index.jsx
index 080b4e0..d87b3ad 100644
--- a/web-react/src/pages/system/user/index.jsx
+++ b/web-react/src/pages/system/user/index.jsx
@@ -183,10 +183,10 @@ export default class index extends Component {
/**
* 删除
- * @param {*} record
+ * @param {*} id
*/
- onDelete(record) {
- this.onAction(apiAction.delete(record), '删除成功')
+ onDelete(id) {
+ this.onAction(apiAction.delete({ id }), '删除成功')
}
//#region 自定义方法
@@ -322,6 +322,17 @@ export default class index extends Component {
})}
+
+
+
}
operator={
diff --git a/web-react/src/store/reducer/layout.js b/web-react/src/store/reducer/layout.js
index 1441e84..776fdc9 100644
--- a/web-react/src/store/reducer/layout.js
+++ b/web-react/src/store/reducer/layout.js
@@ -3,7 +3,8 @@ import { SIDER_BREAK_POINT } from "util/global"
const defaultState = {
siderCollapsed: false,
- allowSiderCollapsed: true
+ allowSiderCollapsed: true,
+ theme: 'default'
}
const localStorageState = () => {
@@ -36,6 +37,7 @@ const layout = (state = mergeState, action) => {
window.localStorage.setItem(SETTING_KEY, JSON.stringify(_state))
return _state
}
+ // 自动收起侧边
case 'AUTO_TOGGLE_COLLAPSED':
{
const _state = {
@@ -45,6 +47,13 @@ const layout = (state = mergeState, action) => {
}
return _state
}
+ // 切换主题
+ case 'SET_THEME':
+ {
+ const _state = { ...state, theme: action.theme }
+ window.localStorage.setItem(SETTING_KEY, JSON.stringify(_state))
+ return _state
+ }
default:
return state
}
diff --git a/web-react/src/views/login/index.jsx b/web-react/src/views/login/index.jsx
index a431711..0e9b331 100644
--- a/web-react/src/views/login/index.jsx
+++ b/web-react/src/views/login/index.jsx
@@ -1,11 +1,10 @@
import React, { Component } from 'react'
-import { Button, Form, Input, message as Message } from 'antd'
+import { Alert, Button, Form, Input, message as Message, Modal } from 'antd'
import Container from 'components/container'
import { encryptByRSA } from 'util/rsa'
import { RSA_PUBLIC_KEY } from 'util/global'
import { api } from 'common/api'
import { token } from 'common/token'
-import './index.less'
export default class index extends Component {
state = {
@@ -15,6 +14,10 @@ export default class index extends Component {
focusPassword: false,
btnDisabled: true,
+
+ pattern: '',
+ descriptions: '',
+ visible: false,
}
backgroundImage = require(`assets/image/login-bg-0${Math.floor(Math.random() * 4)}.jpg`)
@@ -34,9 +37,19 @@ export default class index extends Component {
api.login({ account, password })
.then(({ success, data, message }) => {
if (success) {
- token.value = data
- Message.success('登录成功')
- this.props.history.replace('/')
+ const { passed, pattern, descriptions, token } = data
+ // 简单密码需要更改
+ if (!passed) {
+ this.setState({
+ visible: true,
+ loading: false,
+ btnDisabled: true,
+ pattern,
+ descriptions,
+ })
+ } else {
+ this.onLoginSuccess(token)
+ }
} else {
this.setState({ loading: false })
Message.error(message)
@@ -50,8 +63,52 @@ export default class index extends Component {
})
}
+ onLoginPass = values => {
+ this.setState({ loading: true })
+ const account = this.form.current.getFieldValue('account')
+ let { password, newPassword } = values
+ password = encryptByRSA(password, RSA_PUBLIC_KEY)
+ newPassword = encryptByRSA(newPassword, RSA_PUBLIC_KEY)
+ const confirm = newPassword // 前端验证两次密码即可.不需要加密
+
+ api.loginPass({ account, password, newPassword, confirm })
+ .then(({ success, data, message }) => {
+ if (success) {
+ const { passed, pattern, descriptions, token } = data
+ // 简单密码需要更改
+ if (!passed) {
+ this.setState({
+ visible: true,
+ loading: false,
+ btnDisabled: true,
+ pattern,
+ descriptions,
+ })
+ } else {
+ this.onLoginSuccess(token)
+ }
+ } else {
+ this.setState({ loading: false })
+ Message.error(message)
+ }
+ })
+ .catch(({ message }) => {
+ if (typeof message === 'object' && message[0]) {
+ Message.error(message[0].messages[0])
+ }
+ this.setState({ loading: false })
+ })
+ }
+
+ onLoginSuccess(jwtToken) {
+ token.value = jwtToken
+ Message.success('登录成功')
+ this.props.history.replace('/')
+ }
+
render() {
- const { loading, focusUser, focusPassword, btnDisabled } = this.state
+ const { loading, focusUser, focusPassword, btnDisabled, visible, pattern, descriptions } =
+ this.state
return (
@@ -85,6 +142,7 @@ export default class index extends Component {
}}
size="large"
autoComplete="off"
+ placeholder={focusUser && '请输入用户名/手机号/邮箱'}
/>
@@ -122,6 +181,54 @@ export default class index extends Component {
+
+
+
+
+
+
+
+
)
}
diff --git a/web-react/src/views/main/_layout/header/index.jsx b/web-react/src/views/main/_layout/header/index.jsx
index ccf9f9d..0cdf6c8 100644
--- a/web-react/src/views/main/_layout/header/index.jsx
+++ b/web-react/src/views/main/_layout/header/index.jsx
@@ -1,10 +1,13 @@
-import React, { Component } from 'react'
-import { Layout, Badge } from 'antd'
+import React, { Component, useState } from 'react'
+import { Layout, Badge, Popover, Menu, Modal, Tooltip, Popconfirm } from 'antd'
import { AntIcon, Container } from 'components'
-import Logo from '../logo'
-import User from './user'
-import Search from './search'
import store from 'store'
+import { api } from 'common/api'
+
+import Logo from '../logo'
+import Search from './search'
+import Notice from './notice'
+import User from './user'
const { getState, subscribe, dispatch } = store
@@ -33,8 +36,7 @@ export default class index extends Component {
}
render() {
- const { allowSiderCollapsed } = this.state
-
+ const { allowSiderCollapsed, theme } = this.state
return (