feat: 计划作业-上次执行耗时 (#133)

Co-authored-by: tk <fiyne1a@dingtalk.com>
This commit is contained in:
nsnail 2024-06-04 11:57:15 +08:00 committed by GitHub
parent 127f6e9f6c
commit 57b71e1354
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
9 changed files with 73 additions and 41 deletions

View File

@ -19,11 +19,11 @@
<PrivateAssets>all</PrivateAssets> <PrivateAssets>all</PrivateAssets>
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets> <IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
</PackageReference> </PackageReference>
<PackageReference Include="Roslynator.Analyzers" Version="4.12.3"> <PackageReference Include="Roslynator.Analyzers" Version="4.12.4">
<PrivateAssets>all</PrivateAssets> <PrivateAssets>all</PrivateAssets>
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets> <IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
</PackageReference> </PackageReference>
<PackageReference Include="SonarAnalyzer.CSharp" Version="9.25.1.91650"> <PackageReference Include="SonarAnalyzer.CSharp" Version="9.26.0.92422">
<PrivateAssets>all</PrivateAssets> <PrivateAssets>all</PrivateAssets>
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets> <IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
</PackageReference> </PackageReference>

View File

@ -1,9 +1,9 @@
{ {
"version": "1.1.1", "version": "1.1.1",
"devDependencies": { "devDependencies": {
"cz-git": "^1.9.1", "cz-git": "^1.9.2",
"commitizen": "^4.3.0", "commitizen": "^4.3.0",
"prettier": "^3.2.5", "prettier": "^3.3.0",
"standard-version": "^9.5.0" "standard-version": "^9.5.0"
}, },
"config": { "config": {

View File

@ -37,6 +37,13 @@ public record Sys_Job : VersionEntity, IFieldEnabled, IFieldSummary
[JsonIgnore] [JsonIgnore]
public virtual string JobName { get; init; } public virtual string JobName { get; init; }
/// <summary>
/// 上次执行耗时
/// </summary>
[Column]
[JsonIgnore]
public virtual long? LastDuration { get; init; }
/// <summary> /// <summary>
/// 上次执行时间 /// 上次执行时间
/// </summary> /// </summary>

View File

@ -43,6 +43,10 @@ public sealed record QueryJobRsp : Sys_Job
[JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)]
public override string JobName { get; init; } public override string JobName { get; init; }
/// <inheritdoc cref="Sys_Job.LastDuration" />
[JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)]
public override long? LastDuration { get; init; }
/// <inheritdoc cref="Sys_Job.LastExecTime" /> /// <inheritdoc cref="Sys_Job.LastExecTime" />
[JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)]
public override DateTime? LastExecTime { get; init; } public override DateTime? LastExecTime { get; init; }

View File

@ -68,7 +68,7 @@ public sealed class ScheduledJob : WorkBase<ScheduledJob>, IJob
var request = BuildRequest(job); var request = BuildRequest(job);
var sw = new Stopwatch(); var sw = new Stopwatch();
sw.Start(); sw.Start();
var rsp = await request.SendAsync(cancelToken).ConfigureAwait(false); var rsp = await request.SendAsync(CancellationToken.None).ConfigureAwait(false);
if (rsp.StatusCode == HttpStatusCode.Unauthorized) { if (rsp.StatusCode == HttpStatusCode.Unauthorized) {
var loginRsp = await _userService.LoginByUserIdAsync(job.UserId).ConfigureAwait(false); var loginRsp = await _userService.LoginByUserIdAsync(job.UserId).ConfigureAwait(false);
#pragma warning disable S2696 #pragma warning disable S2696
@ -76,12 +76,13 @@ public sealed class ScheduledJob : WorkBase<ScheduledJob>, IJob
_refreshToken = loginRsp.RefreshToken; _refreshToken = loginRsp.RefreshToken;
#pragma warning restore S2696 #pragma warning restore S2696
request = BuildRequest(job); request = BuildRequest(job);
rsp = await request.SendAsync(cancelToken).ConfigureAwait(false); rsp = await request.SendAsync(CancellationToken.None).ConfigureAwait(false);
} }
sw.Stop(); sw.Stop();
await UowManager.AtomicOperateAsync(async () => { await UowManager.AtomicOperateAsync(async () => {
var rspBody = await rsp.Content.ReadAsStringAsync(cancelToken).ConfigureAwait(false); var rspBody = await rsp.Content.ReadAsStringAsync(CancellationToken.None)
.ConfigureAwait(false);
var jobRecord = new CreateJobRecordReq // var jobRecord = new CreateJobRecordReq //
{ {
Duration = sw.ElapsedMilliseconds Duration = sw.ElapsedMilliseconds
@ -97,7 +98,10 @@ public sealed class ScheduledJob : WorkBase<ScheduledJob>, IJob
}; };
_ = await _jobRecordService.CreateAsync(jobRecord).ConfigureAwait(false); _ = await _jobRecordService.CreateAsync(jobRecord).ConfigureAwait(false);
await _jobService await _jobService
.FinishJobAsync(job.Adapt<UpdateJobReq>() with { LastStatusCode = rsp.StatusCode }) .FinishJobAsync(job.Adapt<UpdateJobReq>() with {
LastStatusCode = rsp.StatusCode
, LastDuration = jobRecord.Duration
})
.ConfigureAwait(false); .ConfigureAwait(false);
}) })
.ConfigureAwait(false); .ConfigureAwait(false);

View File

@ -11,14 +11,14 @@
"dependencies": { "dependencies": {
"@element-plus/icons-vue": "^2.3.1", "@element-plus/icons-vue": "^2.3.1",
"@tinymce/tinymce-vue": "^5.1.1", "@tinymce/tinymce-vue": "^5.1.1",
"ace-builds": "^1.33.2", "ace-builds": "^1.34.2",
"axios": "^1.6.8", "axios": "^1.7.2",
"clipboard": "^2.0.11", "clipboard": "^2.0.11",
"core-js": "^3.37.1", "core-js": "^3.37.1",
"cropperjs": "^1.6.2", "cropperjs": "^1.6.2",
"crypto-js": "^4.2.0", "crypto-js": "^4.2.0",
"echarts": "^5.5.0", "echarts": "^5.5.0",
"element-plus": "^2.7.3", "element-plus": "^2.7.4",
"json-bigint": "^1.0.0", "json-bigint": "^1.0.0",
"json5-to-table": "^0.1.8", "json5-to-table": "^0.1.8",
"markdown-it": "^14.1.0", "markdown-it": "^14.1.0",
@ -36,16 +36,16 @@
"vue3-json-viewer": "^2.2.2", "vue3-json-viewer": "^2.2.2",
"vuedraggable": "^4.0.3", "vuedraggable": "^4.0.3",
"vuex": "^4.1.0", "vuex": "^4.1.0",
"xgplayer": "^3.0.17", "xgplayer": "^3.0.18",
"xgplayer-hls": "^3.0.17" "xgplayer-hls": "^3.0.18"
}, },
"devDependencies": { "devDependencies": {
"@vitejs/plugin-vue": "^5.0.4", "@vitejs/plugin-vue": "^5.0.5",
"prettier": "^3.2.5", "prettier": "^3.3.0",
"prettier-plugin-organize-attributes": "^1.0.0", "prettier-plugin-organize-attributes": "^1.0.0",
"sass": "^1.77.2", "sass": "^1.77.4",
"terser": "^5.31.0", "terser": "^5.31.0",
"vite": "^5.2.11" "vite": "^5.2.12"
}, },
"browserslist": [ "browserslist": [
"> 1%", "> 1%",

View File

@ -209,18 +209,14 @@
border-left: 0; border-left: 0;
} }
.el-table.el-table--large { .el-table * {
font-size: 0.9rem;
}
.el-table.el-table--large * {
font-size: 1rem; font-size: 1rem;
} }
.el-table.el-table--small {
font-size: 0.9rem;
}
.el-table {
font-size: 0.9rem;
}
.el-radio-button__inner { .el-radio-button__inner {
font-size: 0.9rem; font-size: 0.9rem;
} }

View File

@ -109,20 +109,33 @@
" "
prop="httpMethod" prop="httpMethod"
width="100" /> width="100" />
<el-table-column :label="$t('上次执行时间')" align="right" prop="lastExecTime" sortable="custom" width="120"> <el-table-column :label="$t('上次执行')" align="center">
<el-table-column :label="$t('状态')" align="center" prop="lastExecTime" sortable="custom" width="150">
<template #default="scope">
<div class="indicator">
<sc-status-indicator :type="scope.row.lastStatusCode === 'ok' ? 'success' : 'danger'" />
<span>{{
this.$GLOBAL.enums.httpStatusCodes[scope.row.lastStatusCode]
? this.$GLOBAL.enums.httpStatusCodes[scope.row.lastStatusCode][1]
: scope.row.lastStatusCode
}}</span>
</div>
</template>
</el-table-column>
<el-table-column :label="$t('时间')" align="right" prop="lastExecTime" sortable="custom" width="100">
<template #default="scope"> <template #default="scope">
<span v-if="scope.row.lastExecTime" v-time.tip="scope.row.lastExecTime"></span> <span v-if="scope.row.lastExecTime" v-time.tip="scope.row.lastExecTime"></span>
</template> </template>
</el-table-column> </el-table-column>
<na-col-indicator <el-table-column
:label="$t('上次执行状态')" :formatter="(row) => `${tool.groupSeparator(row.lastDuration.toFixed(0))} ms`"
:options=" :label="$t('耗时')"
Object.entries(this.$GLOBAL.enums.httpStatusCodes).map((x) => { align="right"
return { value: x[0], text: x[1][1], type: x[0] === 'ok' ? 'success' : null } prop="lastDuration"
}) sortable="custom"
" width="100">
prop="lastStatusCode" </el-table-column>
width="120" /> </el-table-column>
<el-table-column :label="$t('下次执行时间')" align="right" prop="nextExecTime" sortable="custom" width="170" /> <el-table-column :label="$t('下次执行时间')" align="right" prop="nextExecTime" sortable="custom" width="170" />
<el-table-column :label="$t('启用')" align="center" prop="enabled" sortable="custom" width="80"> <el-table-column :label="$t('启用')" align="center" prop="enabled" sortable="custom" width="80">
@ -151,7 +164,8 @@
}, },
) )
" "
:vue="this" /> :vue="this"
width="180" />
</sc-table> </sc-table>
</el-main> </el-main>
</el-container> </el-container>
@ -168,6 +182,7 @@ import saveDialog from './save'
import table from '@/config/table' import table from '@/config/table'
import naColOperation from '@/config/naColOperation' import naColOperation from '@/config/naColOperation'
import ScSelectFilter from '@/components/scSelectFilter/index.vue' import ScSelectFilter from '@/components/scSelectFilter/index.vue'
import tool from '@/utils/tool'
export default { export default {
components: { components: {
@ -199,6 +214,9 @@ export default {
}, },
watch: {}, watch: {},
computed: { computed: {
tool() {
return tool
},
naColOperation() { naColOperation() {
return naColOperation return naColOperation
}, },

View File

@ -27,6 +27,9 @@
<el-form-item v-if="mode === 'view'" :label="$t('上次执行时间')" prop="lastExecTime"> <el-form-item v-if="mode === 'view'" :label="$t('上次执行时间')" prop="lastExecTime">
<el-input v-model="form.lastExecTime" clearable /> <el-input v-model="form.lastExecTime" clearable />
</el-form-item> </el-form-item>
<el-form-item v-if="mode === 'view'" :label="$t('上次执行耗时ms')" prop="lastExecTime">
<el-input v-model="form.lastDuration" clearable />
</el-form-item>
<el-form-item v-if="mode === 'view'" :label="$t('下次执行时间')" prop="nextExecTime"> <el-form-item v-if="mode === 'view'" :label="$t('下次执行时间')" prop="nextExecTime">
<el-input v-model="form.nextExecTime" clearable /> <el-input v-model="form.nextExecTime" clearable />
</el-form-item> </el-form-item>