diff --git a/Api/Ewide.Core/Ewide.Core.xml b/Api/Ewide.Core/Ewide.Core.xml index c89a9df..bb4748b 100644 --- a/Api/Ewide.Core/Ewide.Core.xml +++ b/Api/Ewide.Core/Ewide.Core.xml @@ -7189,6 +7189,13 @@ 检验验证码并且绑定 + + + 获取密码强度配置 + + + + 发送验证码间隔时间(秒) @@ -7271,6 +7278,13 @@ + + + 检测是否重复 + + + + 邮箱类 diff --git a/Api/Ewide.Core/Extension/DataFilter/Entity/FilterInfo.cs b/Api/Ewide.Core/Extension/DataFilter/Entity/FilterInfo.cs index a7087be..42b1d2d 100644 --- a/Api/Ewide.Core/Extension/DataFilter/Entity/FilterInfo.cs +++ b/Api/Ewide.Core/Extension/DataFilter/Entity/FilterInfo.cs @@ -34,6 +34,7 @@ namespace Ewide.Core.Extension.DataFilter.Entity /// public void SetSearchInfo(SearchInfo[] searchInfo, IEnumerable filterFields) { + if (searchInfo == null) return; try { foreach (var elem in searchInfo) diff --git a/Api/Ewide.Core/Service/Notice/SysNoticeService.cs b/Api/Ewide.Core/Service/Notice/SysNoticeService.cs index dba5165..b182d18 100644 --- a/Api/Ewide.Core/Service/Notice/SysNoticeService.cs +++ b/Api/Ewide.Core/Service/Notice/SysNoticeService.cs @@ -232,7 +232,7 @@ WHERE SNU.UserId = @UserId AND SN.Status = @Status"; }, new[] { - "Type","Title" + "Type","Title","ReadStatus" } ); @@ -254,8 +254,10 @@ WHERE SNU.UserId = @UserId AND SN.Status = @Status"; [HttpGet("/sysNotice/unread")] public async Task GetUnreadCount() { - var noticeList = await _sysNoticeRep.Where(u => u.Status != (int)NoticeStatus.DELETED).Select(s => s.Id).ToListAsync(); - return await _sysNoticeUserRep.Where(u => u.UserId == _userManager.UserId && noticeList.Contains(u.NoticeId) && u.ReadStatus == (int)NoticeUserStatus.UNREAD).CountAsync(); + //删除 或者 草稿都不让显示 + var noticeList = await _sysNoticeRep.Where(u => u.Status != (int)NoticeStatus.DELETED&& u.Status != (int)NoticeStatus.DRAFT).Select(s => s.Id).ToListAsync(); + var noticeUserList = await _sysNoticeUserRep.Where(u => u.UserId == _userManager.UserId && noticeList.Contains(u.NoticeId) && u.ReadStatus == (int)NoticeUserStatus.UNREAD).ToListAsync(); + return noticeUserList.Count(); } /// diff --git a/Api/Ewide.Core/Service/User/Dto/UserInput.cs b/Api/Ewide.Core/Service/User/Dto/UserInput.cs index a096e4c..8b0c679 100644 --- a/Api/Ewide.Core/Service/User/Dto/UserInput.cs +++ b/Api/Ewide.Core/Service/User/Dto/UserInput.cs @@ -128,7 +128,6 @@ namespace Ewide.Core.Service /// 新密码 /// [Required(ErrorMessage = "新密码不能为空")] - [StringLength(32, MinimumLength = 5, ErrorMessage = "密码需要大于5个字符")] public string NewPassword { get; set; } /// diff --git a/Api/Ewide.Core/Service/User/ISysUserService.cs b/Api/Ewide.Core/Service/User/ISysUserService.cs index a021e77..a0c9cda 100644 --- a/Api/Ewide.Core/Service/User/ISysUserService.cs +++ b/Api/Ewide.Core/Service/User/ISysUserService.cs @@ -29,7 +29,7 @@ namespace Ewide.Core.Service Task SendCode(Usermailphone input); Task CheckBindcode(Usermailphone input); - + Task GetPwdRule(); Task GetOrgUserTree(OrgUserInput input); } } \ No newline at end of file diff --git a/Api/Ewide.Core/Service/User/SysUserService.cs b/Api/Ewide.Core/Service/User/SysUserService.cs index d8c0c65..72d56f2 100644 --- a/Api/Ewide.Core/Service/User/SysUserService.cs +++ b/Api/Ewide.Core/Service/User/SysUserService.cs @@ -1,6 +1,7 @@ using Ewide.Core.Service.Role; using Ewide.Core.Service.User.Dto; using Ewide.Core.Util; +using Furion; using Furion.DatabaseAccessor; using Furion.DatabaseAccessor.Extensions; using Furion.DataEncryption; @@ -312,11 +313,26 @@ namespace Ewide.Core.Service public async Task UpdateUserPwd(ChangePasswordUserInput input) { var user = await _sysUserRep.FirstOrDefaultAsync(u => u.Id == _userManager.UserId); - if (MD5Encryption.Encrypt(input.Password) != user.Password) - throw Oops.Oh(ErrorCode.D1004); - if (MD5Encryption.Encrypt(input.NewPassword).Equals(user.Password)) + var Password = RSAHandler.RSADecrypt(input.Password); + Password = MD5Encryption.Encrypt(Password); + if (Password != user.Password) + { + throw Oops.Oh("旧密码不正确"); + } + var newPassword = RSAHandler.RSADecrypt(input.NewPassword); + // 验证新密码强度 + var pattern = App.Configuration.GetSection("SimplePassword:Pattern").Value; + if (!Regex.Match(newPassword, pattern).Success) + { + throw Oops.Oh("新密码强度不符合规则"); + } + + newPassword = MD5Encryption.Encrypt(newPassword); + if (newPassword.Equals(user.Password)) throw Oops.Oh(ErrorCode.D10041); - user.Password = MD5Encryption.Encrypt(input.NewPassword); + + user.Password = newPassword; + } /// @@ -467,7 +483,7 @@ namespace Ewide.Core.Service var Mailcode_Key = "ewide_mailcode"; var Regex_phone = @"^((13[0-9])|(14[5,7])|(15[^4,\\D])|(17[0,1,3,6-8])|(18[0-9])|(19[8,9])|(166))[0-9]{8}$"; var Regex_Email = @"^\w+([-+.]\w+)*@\w+([-.]\w+)*\.\w+([-.]\w+)*$"; - CodeHelper ch = new CodeHelper(_iMemoryCache); + CodeHelper ch = new CodeHelper(_iMemoryCache, _sysUserRep, _userManager); //Type为1时,给原手机号发送验证码 if (input.Type == 1) { @@ -484,7 +500,7 @@ namespace Ewide.Core.Service //Type为2时,给原邮箱发送验证码 else if (input.Type == 2) { - if (new Regex(@"^\w+([-+.]\w+)*@\w+([-.]\w+)*\.\w+([-.]\w+)*$").IsMatch(_userManager.User.Email)) + if (new Regex(Regex_Email).IsMatch(_userManager.User.Email)) { try { @@ -500,6 +516,7 @@ namespace Ewide.Core.Service //Type为null时,则发验证码 else { + await ch.CheckRepeat(input.Target); //通过正则判断绑定类型 if (new Regex(Regex_phone).IsMatch(input.Target)) { @@ -542,7 +559,7 @@ namespace Ewide.Core.Service var Regex_phone = @"^((13[0-9])|(14[5,7])|(15[^4,\\D])|(17[0,1,3,6-8])|(18[0-9])|(19[8,9])|(166))[0-9]{8}$"; var Regex_Email = @"^\w+([-+.]\w+)*@\w+([-.]\w+)*\.\w+([-.]\w+)*$"; var user = await _sysUserRep.FirstOrDefaultAsync(u => u.Id == _userManager.UserId); - CodeHelper ch = new CodeHelper(_iMemoryCache); + CodeHelper ch = new CodeHelper(_iMemoryCache, _sysUserRep,_userManager); if (input.Type == 1) { if (ch.Checkcode(_userManager.User.Phone, input.Orgcode, Orgcode_Key)) @@ -655,6 +672,23 @@ namespace Ewide.Core.Service } } + /// + /// 获取密码强度配置 + /// + /// + /// + [HttpPost("/sysUser/getPwdRule")] + public async Task GetPwdRule() + { + return new LoginOutput + { + Pattern = App.Configuration.GetSection("SimplePassword:Pattern").Value, + Descriptions = App.Configuration.GetSection("SimplePassword:Descriptions").Value + }; + } + + + [HttpPost("/sysUser/GetOrgUserTree")] public async Task GetOrgUserTree(OrgUserInput input) { diff --git a/Api/Ewide.Core/Util/CodeHelper.cs b/Api/Ewide.Core/Util/CodeHelper.cs index 9ae5256..00fe3a4 100644 --- a/Api/Ewide.Core/Util/CodeHelper.cs +++ b/Api/Ewide.Core/Util/CodeHelper.cs @@ -2,7 +2,9 @@ using Aliyun.Acs.Core.Exceptions; using Aliyun.Acs.Core.Profile; using Furion; +using Furion.DatabaseAccessor; using Furion.FriendlyException; +using Microsoft.EntityFrameworkCore; using Microsoft.Extensions.Caching.Memory; using Newtonsoft.Json; using Newtonsoft.Json.Linq; @@ -19,9 +21,17 @@ namespace Ewide.Core.Util public class CodeHelper { private readonly IMemoryCache _IMemoryCache; - public CodeHelper(IMemoryCache IMemoryCache) - { + private readonly IRepository _sysUserRep; // 用户表仓储 + private readonly IUserManager _userManager; + + public CodeHelper( + IMemoryCache IMemoryCache, + IRepository sysUserRep, + IUserManager userManager + ){ _IMemoryCache = IMemoryCache; + _sysUserRep = sysUserRep; + _userManager = userManager; } public static string Aliyun_AccessKey = App.Configuration["SmsHelper:Aliyun_AccessKey"]; public static string Aliyun_AccessSecret = App.Configuration["SmsHelper:Aliyun_AccessSecret"]; @@ -246,7 +256,25 @@ namespace Ewide.Core.Util throw Oops.Oh(ErrorCode.xg1100); } } - - + + /// + /// 检测是否重复 + /// + /// + /// + public async Task CheckRepeat(string Target) + { + var Regex_phone = @"^((13[0-9])|(14[5,7])|(15[^4,\\D])|(17[0,1,3,6-8])|(18[0-9])|(19[8,9])|(166))[0-9]{8}$"; + var Regex_Email = @"^\w+([-+.]\w+)*@\w+([-.]\w+)*\.\w+([-.]\w+)*$"; + if(new Regex(Regex_phone).IsMatch(Target)){ + var isExist = await _sysUserRep.DetachedEntities.AnyAsync(u => (u.Id != _userManager.UserId ) && (u.Account == Target || u.Phone == Target)); + if (isExist) throw Oops.Oh("手机号与他人账号或者手机号重复"); + }else if(new Regex(Regex_Email).IsMatch(Target)) + { + var isExist3 = await _sysUserRep.DetachedEntities.AnyAsync(u => (u.Id != _userManager.UserId) && (u.Account == Target || u.Email == Target)); + if (isExist3) throw Oops.Oh("邮箱与他人账号或者邮箱重复"); + } + return true; + } } } diff --git a/web-react/src/common/api/requests/sys/userManage.js b/web-react/src/common/api/requests/sys/userManage.js index 2d9a478..8307459 100644 --- a/web-react/src/common/api/requests/sys/userManage.js +++ b/web-react/src/common/api/requests/sys/userManage.js @@ -85,6 +85,11 @@ const urls = { */ sysUserCheckBindcode: ['/sysUser/checkBindcode', 'post'], + /** + * 获取密码验证配置 + */ + getPwdRule: ['/sysUser/getPwdRule', 'post'], + } export default urls \ No newline at end of file diff --git a/web-react/src/pages/system/account/base.jsx b/web-react/src/pages/system/account/base.jsx index 298f2b4..c44719d 100644 --- a/web-react/src/pages/system/account/base.jsx +++ b/web-react/src/pages/system/account/base.jsx @@ -78,7 +78,15 @@ export default class base extends Component { {user.name} {user.nickName} {user.account} - {user.sex} + + {user.sex === 0 + ? '保密' + : user.sex === 1 + ? '男性' + : user.sex === 2 + ? '女性' + : '保密'} + {user.birthday && (typeof user.birthday === 'string' diff --git a/web-react/src/pages/system/account/setting/satety/index.jsx b/web-react/src/pages/system/account/setting/satety/index.jsx index e6ab368..d5f276b 100644 --- a/web-react/src/pages/system/account/setting/satety/index.jsx +++ b/web-react/src/pages/system/account/setting/satety/index.jsx @@ -115,9 +115,9 @@ export default class form extends Component { )} /> - - - + {/* */} + + {/* */} diff --git a/web-react/src/pages/system/account/setting/satety/mail.jsx b/web-react/src/pages/system/account/setting/satety/mail.jsx index 4a8467a..4bdb602 100644 --- a/web-react/src/pages/system/account/setting/satety/mail.jsx +++ b/web-react/src/pages/system/account/setting/satety/mail.jsx @@ -107,7 +107,7 @@ export default class form extends Component { const data = form.getFieldsValue() try { await api.sysUserSendCode(data) - const typeName = data.type ? [, '手机', '邮箱'][data.type] : '手机' + const typeName = data.type ? [, '手机', '邮箱'][data.type] : '邮箱' Message.success(`已发送验证码到${typeName},请注意查收`) this.addTime() this.showCountDown() diff --git a/web-react/src/pages/system/account/setting/satety/password.jsx b/web-react/src/pages/system/account/setting/satety/password.jsx index 6e0c9db..b37eb86 100644 --- a/web-react/src/pages/system/account/setting/satety/password.jsx +++ b/web-react/src/pages/system/account/setting/satety/password.jsx @@ -1,24 +1,68 @@ import React, { Component } from 'react' -import { Form, Input } from 'antd' +import { Form, Input, message as Message, Modal } from 'antd' +import { api } from 'common/api' +import { RSA_PUBLIC_KEY } from 'util/global' +import { cloneDeep } from 'lodash' +import { Button } from 'antd/lib/radio' +import { encryptByRSA } from 'util/rsa' + +const initData = { + exist: false, + pattern: '', + descriptions: '', + visible: false, +} export default class form extends Component { - state = { - // 加载状态 - exist: false, - } + state = cloneDeep(initData) // 表单实例 form = React.createRef() // 初始化数据 record = {} + open = () => { + this.setState({ visible: true }) + } + /** * mount后回调 */ componentDidMount() { this.props.created && this.props.created(this) + api.getPwdRule({}).then(({ success, data, message }) => { + if (success) { + const { pattern, descriptions } = data + this.setState({ + pattern, + descriptions, + }) + } else { + Message.Error(message) + } + }) } + updatePwd(values) { + let { password, newPassword } = values.current.getFieldsValue() + password = encryptByRSA(password, RSA_PUBLIC_KEY) + newPassword = encryptByRSA(newPassword, RSA_PUBLIC_KEY) + const confirm = newPassword + api.sysUserUpdatePwd({ password, newPassword, confirm }).then( + ({ success, data, message }) => { + if (success) { + Message.success('密码修改完成') + this.close() + } else { + Message.warn(message) + } + } + ) + } + + close() { + this.setState(cloneDeep(initData)) + } /** * 填充数据 * 可以在设置this.record之后对其作出数据结构调整 @@ -46,42 +90,56 @@ export default class form extends Component { } render() { + const { pattern, descriptions, visible } = this.state return ( -
-
- - - - - - - ({ - validator(_, value) { - if (!value || getFieldValue('newPassword') === value) { - return Promise.resolve() - } - return Promise.reject(new Error('确认新密码不匹配')) - }, - }), - ]} - name="confirm" - > - - -
-
+ this.close()} + onOk={() => this.updatePwd(this.form)} + visible={visible} + className="yo-modal-form" + title="更新密码" + > +
+
+ + + + + + + ({ + validator(_, value) { + if (!value || getFieldValue('newPassword') === value) { + return Promise.resolve() + } + return Promise.reject(new Error('确认新密码不匹配')) + }, + }), + ]} + name="confirm" + > + + +
+
+
) } } diff --git a/web-react/src/pages/system/notice/form.jsx b/web-react/src/pages/system/notice/form.jsx index b4ae8fc..13c8fe4 100644 --- a/web-react/src/pages/system/notice/form.jsx +++ b/web-react/src/pages/system/notice/form.jsx @@ -139,7 +139,6 @@ export default class form extends Component { */ async getData() { const form = this.form.current - console.log(this.record) const valid = await form.validateFields() if (valid) { const postData = form.getFieldsValue() diff --git a/web-react/src/pages/system/notice/index.jsx b/web-react/src/pages/system/notice/index.jsx index 555fe0e..0f43dfa 100644 --- a/web-react/src/pages/system/notice/index.jsx +++ b/web-react/src/pages/system/notice/index.jsx @@ -56,28 +56,38 @@ export default class index extends Component { { title: '标题', dataIndex: 'title', + width: 300, + sorter: true, }, { title: '发布人', dataIndex: 'publicUserName', + width: 120, + sorter: true, }, { title: '发布时间', dataIndex: 'createdTime', + width: 150, + sorter: true, }, { title: '发布单位', dataIndex: 'publicOrgName', - width: 200, + width: 150, + sorter: true, }, { title: '类型', dataIndex: 'type', + width: 120, + sorter: true, render: text => this.bindCodeValue(text, 'notice_type'), }, { title: '状态', dataIndex: 'status', + width: 120, render: text => this.bindCodeValue(text, 'notice_status'), }, ] @@ -94,7 +104,7 @@ export default class index extends Component { if (flag) { this.columns.push({ title: '操作', - width: 150, + width: 200, dataIndex: 'actions', render: (text, record) => ( @@ -178,6 +188,7 @@ export default class index extends Component { }) }) } + subUniqueKey(text, index) { return text.substr(index, 5) } @@ -252,26 +263,23 @@ export default class index extends Component { * @param {*} id */ onDelete(id) { - this.onAction(apiAction.Status({ id, Status: 3 }), '删除成功') + this.onAction(apiAction.Status({ id, status: 3 }), '删除成功') } /** * 发布 * @param {*} id */ onPublish(id) { - this.onAction(apiAction.Status({ id, Status: 1 }), '发布成功') + this.onAction(apiAction.Status({ id, status: 1 }), '发布成功') } /** * 撤回 * @param {*} id */ onGoBack(id) { - this.onAction(apiAction.Status({ id, Status: 2 }), '撤回成功') + this.onAction(apiAction.Status({ id, status: 2 }), '撤回成功') } // - //#region 自定义方法 - //#endregion - render() { const { codes } = this.state return ( @@ -280,7 +288,6 @@ export default class index extends Component { record.id} autoLoad={false} loadData={this.loadData} columns={this.columns} diff --git a/web-react/src/pages/system/noticeReceived/form.jsx b/web-react/src/pages/system/noticeReceived/form.jsx index e4d73c9..44465b1 100644 --- a/web-react/src/pages/system/noticeReceived/form.jsx +++ b/web-react/src/pages/system/noticeReceived/form.jsx @@ -1,15 +1,18 @@ import React, { Component } from 'react' -import { Spin, Divider, Modal, Row } from 'antd' +import { Spin, Divider, Modal, Row, Form, Upload } from 'antd' import { api } from 'common/api' import { AntIcon } from 'components' +import { BlobToBase64, GetFileName, PreviewFile } from 'util/file' export default class form extends Component { state = { detailVisible: false, detailLoading: false, detailData: {}, + fileValue: false, } + filedu = React.createRef() /** * mount后回调 */ @@ -20,12 +23,57 @@ export default class form extends Component { async onOpenDetail(id) { this.setState({ detailLoading: true, detailVisible: true }) const { data } = await api.sysNoticeDetail({ id }) + this.setState({ detailLoading: false, detailData: data, + fileValue: false, }) + + if (data) { + const { attachments } = data + if (attachments) { + const fileValue = [] + const fileList = attachments.split(',') + for (const fileId of fileList) { + try { + const file = await PreviewFile(fileId) + const base64 = await BlobToBase64(file) + fileValue.push({ + uid: fileId, + response: fileId, + name: file.name, + url: base64, + status: 'done', + }) + } catch { + const { data: file } = await api.sysFileInfoDetail({ id: fileId }) + fileValue.push({ + uid: fileId, + response: '文件已丢失', + name: file.fileOriginName, + status: 'error', + }) + } + } + this.setState({ + fileValue, + }) + } + } } + async onFileDownload(file) { + const { data, headers } = await api.sysFileInfoDownload({ id: file.response }) + const url = window.URL.createObjectURL(data) + const fileName = GetFileName(headers['content-disposition']) + const a = document.createElement('a') + a.href = url + a.download = fileName + a.click() + window.URL.revokeObjectURL(url) + a.remove() + } render() { const { detailLoading, detailVisible, detailData } = this.state return ( @@ -43,6 +91,21 @@ export default class form extends Component { dangerouslySetInnerHTML={{ __html: detailData.content }} > + {this.state.fileValue && ( + + + 查看附件 + this.onFileDownload(file)} + > + + + )} + 发布人:{detailData.publicUserName} 发布时间:{detailData.publicTime} diff --git a/web-react/src/pages/system/noticeReceived/index.jsx b/web-react/src/pages/system/noticeReceived/index.jsx index 3c5452f..d4b580f 100644 --- a/web-react/src/pages/system/noticeReceived/index.jsx +++ b/web-react/src/pages/system/noticeReceived/index.jsx @@ -20,6 +20,7 @@ export default class index extends Component { codes: { noticeStatus: [], noticeType: [], + readStatus: [], }, } @@ -33,25 +34,39 @@ export default class index extends Component { { title: '标题', dataIndex: 'title', + width: 300, + sorter: true, }, { title: '发布人', dataIndex: 'publicUserName', + width: 150, + sorter: true, }, { title: '发布时间', dataIndex: 'createdTime', + width: 200, + sorter: true, }, { title: '发布单位', dataIndex: 'publicOrgName', width: 200, + sorter: true, }, { title: '类型', dataIndex: 'type', + width: 120, render: text => this.bindCodeValue(text, 'notice_type'), }, + { + title: '已读未读', + dataIndex: 'readStatus', + width: 120, + render: text => this.bindCodeValue(text, 'read_status'), + }, ] /** @@ -94,33 +109,13 @@ export default class index extends Component { componentDidMount() { const { onLoading, onLoadData } = this.table.current onLoading() - getDictData('notice_status', 'notice_type').then(codes => { + getDictData('notice_status', 'notice_type', 'read_status').then(codes => { this.setState({ codes }, () => { onLoadData() }) }) } - /** - * 对表格上的操作进行统一处理 - * [异步] - * @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() - } - } + /** * 调用加载数据接口,可在调用前对query进行处理 * [异步,必要] @@ -134,6 +129,7 @@ export default class index extends Component { queryType: { type: QueryType.Equal, title: QueryType.Like, + readStatus: QueryType.Equal, }, }) @@ -200,6 +196,19 @@ export default class index extends Component { ))} + + + } /> diff --git a/web-react/src/views/main/_layout/header/notice.jsx b/web-react/src/views/main/_layout/header/notice.jsx index d0d2ec6..58abf17 100644 --- a/web-react/src/views/main/_layout/header/notice.jsx +++ b/web-react/src/views/main/_layout/header/notice.jsx @@ -1,8 +1,9 @@ import React, { Component } from 'react' -import { Badge, Button, Divider, List, Menu, Modal, Popover, Row, Spin } from 'antd' +import { Badge, Button, Divider, List, Menu, Modal, Popover, Row, Spin, Upload, Tag } from 'antd' import { AntIcon, Image } from 'components' import { api } from 'common/api' import InfiniteScroll from 'react-infinite-scroller' +import { BlobToBase64, GetFileName, PreviewFile } from 'util/file' import moment from 'moment' export default class notice extends Component { @@ -16,6 +17,7 @@ export default class notice extends Component { detailVisible: false, detailLoading: false, detailData: {}, + fileValue: false, } async componentDidMount() { @@ -42,7 +44,6 @@ export default class notice extends Component { sortField: 'createdTime', sortOrder: 'descend', }) - if (!items.length) { return this.finish() } @@ -59,7 +60,51 @@ export default class notice extends Component { this.setState({ detailLoading: false, detailData: data, + fileValue: false, }) + + if (data) { + const { attachments } = data + if (attachments) { + const fileValue = [] + const fileList = attachments.split(',') + for (const fileId of fileList) { + try { + const file = await PreviewFile(fileId) + const base64 = await BlobToBase64(file) + fileValue.push({ + uid: fileId, + response: fileId, + name: file.name, + url: base64, + status: 'done', + }) + } catch { + const { data: file } = await api.sysFileInfoDetail({ id: fileId }) + fileValue.push({ + uid: fileId, + response: '文件已丢失', + name: file.fileOriginName, + status: 'error', + }) + } + } + this.setState({ + fileValue, + }) + } + } + } + async onFileDownload(file) { + const { data, headers } = await api.sysFileInfoDownload({ id: file.response }) + const url = window.URL.createObjectURL(data) + const fileName = GetFileName(headers['content-disposition']) + const a = document.createElement('a') + a.href = url + a.download = fileName + a.click() + window.URL.revokeObjectURL(url) + a.remove() } renderList() { @@ -88,6 +133,13 @@ export default class notice extends Component { } + description={ + item.readStatus == 0 ? ( + 未读 + ) : ( + 已读 + ) + } />
{item.content}
@@ -140,6 +192,21 @@ export default class notice extends Component { dangerouslySetInnerHTML={{ __html: detailData.content }} > + {this.state.fileValue && ( + + + 查看附件 + this.onFileDownload(file)} + > + + + )} + 发布人:{detailData.publicUserName} 发布时间:{detailData.publicTime}