From 779d8e511a84d2be91d74ea308c22b969d6963f3 Mon Sep 17 00:00:00 2001 From: tk Date: Tue, 13 Aug 2024 11:34:28 +0800 Subject: [PATCH] =?UTF-8?q?feat:=20=E2=9C=A8=20=E6=9F=A5=E8=AF=A2=E8=BF=87?= =?UTF-8?q?=E6=BB=A4=E5=99=A8=E4=BF=9D=E5=AD=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 页面定时刷新 WebSocket断线自动重连 --- package.json | 2 +- .../Dto/Sys/Config/QueryConfigRsp.cs | 2 - .../Dto/Sys/LoginLog/QueryLoginLogRsp.cs | 1 - .../Dto/Sys/RequestLog/QueryRequestLogRsp.cs | 3 - .../Dto/Sys/SiteMsg/QuerySiteMsgRsp.cs | 3 - .../Services/Sys/UserService.cs | 17 ++- .../admin/src/components/naSearch/index.vue | 139 +++++++++++++++++- .../src/components/naVersionUpdater/index.vue | 40 +++-- .../admin/src/components/scDialog/index.vue | 2 +- .../admin/src/layout/components/tags.vue | 60 +++++--- src/frontend/admin/src/layout/index.vue | 17 ++- src/frontend/admin/src/locales/lang/en.js | 8 +- src/frontend/admin/src/locales/lang/zh-cn.js | 8 +- src/frontend/admin/src/style/app.scss | 4 + .../admin/src/views/sys/job/all/index.vue | 1 + .../admin/src/views/sys/role/save.vue | 4 +- .../admin/src/views/sys/user/index.vue | 2 +- src/frontend/admin/vite.config.js | 5 + 18 files changed, 247 insertions(+), 71 deletions(-) diff --git a/package.json b/package.json index 86c727bf..3115a3ef 100644 --- a/package.json +++ b/package.json @@ -11,4 +11,4 @@ "path": "node_modules/cz-git" } } -} +} \ No newline at end of file diff --git a/src/backend/NetAdmin.Domain/Dto/Sys/Config/QueryConfigRsp.cs b/src/backend/NetAdmin.Domain/Dto/Sys/Config/QueryConfigRsp.cs index 84938ed3..4224a6c0 100644 --- a/src/backend/NetAdmin.Domain/Dto/Sys/Config/QueryConfigRsp.cs +++ b/src/backend/NetAdmin.Domain/Dto/Sys/Config/QueryConfigRsp.cs @@ -25,7 +25,6 @@ public record QueryConfigRsp : Sys_Config public override bool UserRegisterConfirm { get; init; } /// - [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] public new virtual QueryDeptRsp UserRegisterDept { get; init; } /// @@ -33,7 +32,6 @@ public record QueryConfigRsp : Sys_Config public override long UserRegisterDeptId { get; init; } /// - [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] public new virtual QueryRoleRsp UserRegisterRole { get; init; } /// diff --git a/src/backend/NetAdmin.Domain/Dto/Sys/LoginLog/QueryLoginLogRsp.cs b/src/backend/NetAdmin.Domain/Dto/Sys/LoginLog/QueryLoginLogRsp.cs index d1431490..c7cf3f0d 100644 --- a/src/backend/NetAdmin.Domain/Dto/Sys/LoginLog/QueryLoginLogRsp.cs +++ b/src/backend/NetAdmin.Domain/Dto/Sys/LoginLog/QueryLoginLogRsp.cs @@ -48,7 +48,6 @@ public record QueryLoginLogRsp : Sys_LoginLog public override string LoginUserName { get; protected init; } /// - [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] public new virtual QueryUserRsp Owner { get; init; } /// diff --git a/src/backend/NetAdmin.Domain/Dto/Sys/RequestLog/QueryRequestLogRsp.cs b/src/backend/NetAdmin.Domain/Dto/Sys/RequestLog/QueryRequestLogRsp.cs index 66c0f7a8..b4851e54 100644 --- a/src/backend/NetAdmin.Domain/Dto/Sys/RequestLog/QueryRequestLogRsp.cs +++ b/src/backend/NetAdmin.Domain/Dto/Sys/RequestLog/QueryRequestLogRsp.cs @@ -17,7 +17,6 @@ public record QueryRequestLogRsp : Sys_RequestLog public new virtual string CreatedClientIp => base.CreatedClientIp?.ToIpV4(); /// - [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] public new virtual QueryApiRsp Api { get; init; } /// @@ -29,7 +28,6 @@ public record QueryRequestLogRsp : Sys_RequestLog public override DateTime CreatedTime { get; init; } /// - [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] public new virtual QueryRequestLogDetailRsp Detail { get; init; } /// @@ -45,7 +43,6 @@ public record QueryRequestLogRsp : Sys_RequestLog public override int HttpStatusCode { get; init; } /// - [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] public new virtual QueryUserRsp Owner { get; init; } /// diff --git a/src/backend/NetAdmin.Domain/Dto/Sys/SiteMsg/QuerySiteMsgRsp.cs b/src/backend/NetAdmin.Domain/Dto/Sys/SiteMsg/QuerySiteMsgRsp.cs index 3c77ba3f..b3f80ee7 100644 --- a/src/backend/NetAdmin.Domain/Dto/Sys/SiteMsg/QuerySiteMsgRsp.cs +++ b/src/backend/NetAdmin.Domain/Dto/Sys/SiteMsg/QuerySiteMsgRsp.cs @@ -24,7 +24,6 @@ public record QuerySiteMsgRsp : Sys_SiteMsg public override string CreatedUserName { get; init; } /// - [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] public new virtual IEnumerable Depts { get; init; } /// @@ -45,7 +44,6 @@ public record QuerySiteMsgRsp : Sys_SiteMsg public QuerySiteMsgFlagRsp MyFlags { get; init; } /// - [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] public new virtual IEnumerable Roles { get; init; } /// @@ -62,7 +60,6 @@ public record QuerySiteMsgRsp : Sys_SiteMsg public override string Title { get; init; } /// - [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] public new virtual IEnumerable Users { get; init; } /// diff --git a/src/backend/NetAdmin.SysComponent.Application/Services/Sys/UserService.cs b/src/backend/NetAdmin.SysComponent.Application/Services/Sys/UserService.cs index b8c785b4..96e1e6c6 100644 --- a/src/backend/NetAdmin.SysComponent.Application/Services/Sys/UserService.cs +++ b/src/backend/NetAdmin.SysComponent.Application/Services/Sys/UserService.cs @@ -207,7 +207,9 @@ public sealed class UserService( .ConfigureAwait(false); } - return dbUser == null ? throw new NetAdminInvalidOperationException(Ln.用户名或密码错误) : LoginInternal(dbUser); + return dbUser == null + ? throw new NetAdminInvalidOperationException(Ln.用户名或密码错误) + : await LoginInternalAsync(dbUser).ConfigureAwait(false); } /// @@ -221,7 +223,9 @@ public sealed class UserService( } var dbUser = await Rpo.Where(a => a.Mobile == req.DestDevice).ToOneAsync().ConfigureAwait(false); - return dbUser == null ? throw new NetAdminInvalidOperationException(Ln.用户不存在) : LoginInternal(dbUser); + return dbUser == null + ? throw new NetAdminInvalidOperationException(Ln.用户不存在) + : await LoginInternalAsync(dbUser).ConfigureAwait(false); } /// @@ -229,7 +233,7 @@ public sealed class UserService( { var dbUser = await Rpo.Where(a => a.Id == userId).ToOneAsync().ConfigureAwait(false); - return LoginInternal(dbUser); + return await LoginInternalAsync(dbUser).ConfigureAwait(false); } /// @@ -464,14 +468,15 @@ public sealed class UserService( return dept.Count != 1 ? throw new NetAdminInvalidOperationException(Ln.部门不存在) : roles; } - private LoginRsp LoginInternal(Sys_User dbUser) + private async Task LoginInternalAsync(Sys_User dbUser) { if (!dbUser.Enabled) { throw new NetAdminInvalidOperationException(Ln.请联系管理员激活账号); } - _ = UpdateAsync(dbUser with { LastLoginTime = DateTime.Now }, [nameof(Sys_User.LastLoginTime)] -, ignoreVersion: true); + _ = await UpdateAsync(dbUser with { LastLoginTime = DateTime.Now }, [nameof(Sys_User.LastLoginTime)] +, ignoreVersion: true) + .ConfigureAwait(false); var tokenPayload = new Dictionary { { nameof(ContextUserToken), dbUser.Adapt() } }; diff --git a/src/frontend/admin/src/components/naSearch/index.vue b/src/frontend/admin/src/components/naSearch/index.vue index 72444429..c0b72b1c 100644 --- a/src/frontend/admin/src/components/naSearch/index.vue +++ b/src/frontend/admin/src/components/naSearch/index.vue @@ -76,15 +76,59 @@ {{ $t('查询') }} - + +

+ {{ $t('全局') }} + + + + + {{ $t('保存') }} + {{ $t('删除') }} + +

+

+ {{ $t('本页') }} + + + + + {{ $t('保存') }} + {{ $t('删除') }} + +

+

+ {{ $t('JSON 格式化') }} + + {{ $t('重新查询') }} + + +

@@ -96,7 +140,7 @@ import tool from '@/utils/tool' import vkbeautify from 'vkbeautify/index' export default { - emits: ['search', 'reset'], + emits: ['search', 'reset', 'reSearch'], props: { dateField: { type: String, default: 'createdTime' }, hasDate: { type: Boolean, default: true }, @@ -108,6 +152,11 @@ export default { }, data() { return { + autoResearchTimer: null, + queryApi: null, + popWidth: '40rem', + selectFilterKey: 0, + aceEditorValue: null, selectInputKey: null, dateShortCuts: [ { @@ -356,8 +405,23 @@ export default { }, } }, - mounted() {}, + mounted() { + this.queryApi = this.vue.$refs.table.queryApi.url.toUpperCase() + }, + watch: { + 'vue.query': { + immediate: true, + deep: true, + handler: function (o, n) { + this.aceEditorValue = this.vkbeautify.json(n, 2) + }, + }, + }, async created() { + if (document.body.clientWidth < 1000) { + this.popWidth = '100%' + } + this.aceEditorValue = this.vkbeautify.json(this.vue.query, 2) this.selectInputKey = this.controls.find((x) => x.type === 'select-input')?.field[1][0].key if (this.dateType === 'datetimerange') { this.dateShortCuts.unshift( @@ -405,8 +469,70 @@ export default { tool() { return tool }, + vkbeautify() { + return vkbeautify + }, }, methods: { + jsonFormat() { + try { + this.aceEditorValue = vkbeautify.json(this.aceEditorValue, 2) + } catch { + this.$message.error(this.$t('格式错误')) + } + }, + async reSearch(sec) { + const newParam = JSON.parse(this.aceEditorValue) + this.vue.$refs.table.tableParams = newParam + this.vue.$refs.table.upData() + await this.$nextTick() + this.vue.$refs.table.tableParams = this.vue.query + this.$emit('reSearch', newParam) + + if (typeof sec !== 'number') return + const timerEl = document.getElementsByClassName('autoResearchTimer')[0] + if (!timerEl) { + this.$message({ + showClose: true, + onClose: () => clearInterval(this.autoResearchTimer), + type: 'warning', + customClass: 'autoResearchTimer', + message: this.$t('{s} 秒后刷新...', { s: sec }), + duration: 0, + }) + this.autoResearchTimer = setInterval(() => { + const el = document.getElementsByClassName('autoResearchTimer')[0].getElementsByClassName('el-message__content')[0] + let num = parseInt(/(\d+)/.exec(el.innerHTML)[0]) + if (num === 1) { + this.reSearch() + num = sec + 1 + } + el.innerHTML = el.innerHTML.replace(/\d+/, (num - 1).toString()) + }, 1000) + } + }, + async delFilter(isGlobal) { + const key = isGlobal ? 'APP_SET_QUERY_FILTERS' : 'APP_SET_QUERY_FILTERS_' + this.queryApi + let filters = this.$TOOL.data.get(key) || [] + filters = filters.filter((x) => x.value !== this.aceEditorValue) + await this.$TOOL.data.set(key, filters) + this.$message.success(this.$t('删除成功')) + this.selectFilterKey = Math.random() + }, + async saveFilter(isGlobal) { + const key = isGlobal ? 'APP_SET_QUERY_FILTERS' : 'APP_SET_QUERY_FILTERS_' + this.queryApi + try { + const filterName = await this.$prompt('设置一个过滤器名称', '保存查询条件', { + inputPattern: /\S/, + inputErrorMessage: '名称不能为空', + }) + let filters = this.$TOOL.data.get(key) || [] + filters = filters.filter((x) => x.name !== filterName.value) + filters.push({ name: filterName.value, value: this.aceEditorValue }) + await this.$TOOL.data.set(key, filters) + this.$message.success(this.$t('保存成功')) + } catch {} + }, trimSpaces(key) { this.form[key][this.selectInputKey] = this.form[key][this.selectInputKey].replace(/^\s*(.*?)\s*$/g, '$1') }, @@ -415,9 +541,6 @@ export default { delete this.form[item.field[0]][field.key] } }, - vkbeautify() { - return vkbeautify - }, search() { const parentQuery = this.clearParentQuery() Object.assign(parentQuery, this.form.root || {}) diff --git a/src/frontend/admin/src/components/naVersionUpdater/index.vue b/src/frontend/admin/src/components/naVersionUpdater/index.vue index 5addaa07..b6ccc7af 100644 --- a/src/frontend/admin/src/components/naVersionUpdater/index.vue +++ b/src/frontend/admin/src/components/naVersionUpdater/index.vue @@ -6,24 +6,36 @@ import config from '@/config' export default { data() { - return {} + return { + ws: null, + } }, async created() { - const ws = new WebSocket(`ws://${config.API_URL.replace('http://', '')}/ws/version`) - ws.onopen = () => { - ws.send('1') - } - ws.onmessage = async (res) => { - if (res.data !== this.$TOOL.data.get('APP_VERSION')) { - await this.$TOOL.data.set('APP_VERSION', res.data) - this.showTip(res.data.slice(0, res.data.indexOf('+'))) - } else { - await new Promise((x) => setTimeout(x, 10000)) - ws.send('1') - } - } + this.connectWebSocket() }, methods: { + connectWebSocket() { + this.ws = new WebSocket( + import.meta.env.MODE === 'production' + ? `wss://${config.API_URL.replace('https://', '')}/ws/version` + : `ws://${window.location.host}/ws/version`, + ) + this.ws.onopen = () => { + this.ws.send('1') + } + this.ws.onmessage = async (res) => { + if (res.data !== this.$TOOL.data.get('APP_VERSION')) { + await this.$TOOL.data.set('APP_VERSION', res.data) + this.showTip(res.data.slice(0, res.data.indexOf('+'))) + } else { + await new Promise((x) => setTimeout(x, 10000)) + this.ws.send('1') + } + } + this.ws.onclose = () => { + setTimeout(this.connectWebSocket, 5000) // 5秒后重试 + } + }, /** * 通知消息 */ diff --git a/src/frontend/admin/src/components/scDialog/index.vue b/src/frontend/admin/src/components/scDialog/index.vue index df32510b..4dcda1ff 100644 --- a/src/frontend/admin/src/components/scDialog/index.vue +++ b/src/frontend/admin/src/components/scDialog/index.vue @@ -9,7 +9,7 @@