Browse Source

更新库存快照定时任务实现方式,添加任务完成自动通知前端功能

master
wanggang 1 year ago
parent
commit
d228196a96
  1. 18
      code/WebApp/vue3/package-lock.json
  2. 4
      code/WebApp/vue3/package.json
  3. 3
      code/WebApp/vue3/src/main.js
  4. 1
      code/src/Modules/SettleAccount/host/SettleAccount.HttpApi.Host/wwwroot/components/list/index.js
  5. 1
      code/src/Modules/SettleAccount/host/SettleAccount.HttpApi.Host/wwwroot/index.html
  6. 17
      code/src/Modules/SettleAccount/host/SettleAccount.HttpApi.Host/wwwroot/views/base-data/job-item.js
  7. 13
      code/src/Modules/SettleAccount/src/SettleAccount.Application/Entities/BQ/JobHostdService.cs
  8. 14
      code/src/Modules/SettleAccount/src/SettleAccount.Application/Entities/BQ/JobItemAppService.cs
  9. 14
      code/src/Modules/SettleAccount/src/SettleAccount.Application/Entities/BQ/VmiAppService.cs
  10. 4
      code/src/Modules/SettleAccount/src/SettleAccount.Domain/Entities/BQ/Vmi/IJobService.cs

18
code/WebApp/vue3/package-lock.json

@ -38,7 +38,9 @@
"vue-echarts": "^6.6.0", "vue-echarts": "^6.6.0",
"vue-i18n": "^9.2.2", "vue-i18n": "^9.2.2",
"vue-router": "^4.2.2", "vue-router": "^4.2.2",
"wsmock-js": "^1.1.1" "vxe-table": "^4.5.0-beta.16",
"wsmock-js": "^1.1.1",
"xe-utils": "^3.5.11"
}, },
"devDependencies": { "devDependencies": {
"@iconify/json": "^2.2.83", "@iconify/json": "^2.2.83",
@ -13223,6 +13225,15 @@
"vue": "^3.2.0" "vue": "^3.2.0"
} }
}, },
"node_modules/vxe-table": {
"version": "4.5.0-beta.16",
"resolved": "https://registry.npmjs.org/vxe-table/-/vxe-table-4.5.0-beta.16.tgz",
"integrity": "sha512-rSChkgl1cIJzEr99WS2YZyqkOm3bqMtD2d2RrCSB3VVepWJe7B7jMYazGi6L32Y0J3ZM8rNOipFyB3W0j96mHA==",
"peerDependencies": {
"vue": "^3.2.28",
"xe-utils": "^3.5.0"
}
},
"node_modules/webpack-sources": { "node_modules/webpack-sources": {
"version": "3.2.3", "version": "3.2.3",
"resolved": "https://registry.npmjs.org/webpack-sources/-/webpack-sources-3.2.3.tgz", "resolved": "https://registry.npmjs.org/webpack-sources/-/webpack-sources-3.2.3.tgz",
@ -13475,6 +13486,11 @@
"integrity": "sha512-GojqklwG8gpzOVEVki5KudKNoq7MbbjYZCbyWzEz7tyPA7eleiE0+ePwOWQQRb5fm86rD3S8Tc0tSFf3AOv50w==", "integrity": "sha512-GojqklwG8gpzOVEVki5KudKNoq7MbbjYZCbyWzEz7tyPA7eleiE0+ePwOWQQRb5fm86rD3S8Tc0tSFf3AOv50w==",
"dev": true "dev": true
}, },
"node_modules/xe-utils": {
"version": "3.5.11",
"resolved": "https://registry.npmjs.org/xe-utils/-/xe-utils-3.5.11.tgz",
"integrity": "sha512-lyKc/lTBga1Zb63p+FED8mtxLnYIjSS8PVJM1N64NGdCu/3d1XubaVeke2p91RHssP0ExVAl2LUqZYperoz76Q=="
},
"node_modules/xml-name-validator": { "node_modules/xml-name-validator": {
"version": "4.0.0", "version": "4.0.0",
"resolved": "https://registry.npmjs.org/xml-name-validator/-/xml-name-validator-4.0.0.tgz", "resolved": "https://registry.npmjs.org/xml-name-validator/-/xml-name-validator-4.0.0.tgz",

4
code/WebApp/vue3/package.json

@ -71,7 +71,9 @@
"vue-echarts": "^6.6.0", "vue-echarts": "^6.6.0",
"vue-i18n": "^9.2.2", "vue-i18n": "^9.2.2",
"vue-router": "^4.2.2", "vue-router": "^4.2.2",
"wsmock-js": "^1.1.1" "vxe-table": "^4.5.0-beta.16",
"wsmock-js": "^1.1.1",
"xe-utils": "^3.5.11"
}, },
"devDependencies": { "devDependencies": {
"@iconify/json": "^2.2.83", "@iconify/json": "^2.2.83",

3
code/WebApp/vue3/src/main.js

@ -1,7 +1,8 @@
import './style.css'; import './style.css';
import { createApp } from 'vue'; import { createApp } from 'vue';
import VXETable from 'vxe-table';
import App from './App.vue'; import App from './App.vue';
createApp(App).mount('#app'); createApp(App).use(VXETable).mount('#app');

1
code/src/Modules/SettleAccount/host/SettleAccount.HttpApi.Host/wwwroot/components/list/index.js

@ -865,7 +865,6 @@ export default {
await load(); await load();
} }
}); });
context.expose({ load });
return { return {
load, load,
config, config,

1
code/src/Modules/SettleAccount/host/SettleAccount.HttpApi.Host/wwwroot/index.html

@ -64,6 +64,7 @@
"nprogress": "./lib/nprogress/nprogress.vite-esm.js", "nprogress": "./lib/nprogress/nprogress.vite-esm.js",
"echarts/core": "./lib/echarts/echarts.esm.min.js", "echarts/core": "./lib/echarts/echarts.esm.min.js",
"vue-echarts": "./lib/vue-echarts/index.esm.min.js", "vue-echarts": "./lib/vue-echarts/index.esm.min.js",
"xe-echarts": "./lib/vue-echarts/index.esm.min.js",
"resize-detector": "./lib/resize-detector/index.js", "resize-detector": "./lib/resize-detector/index.js",
"@vue-office/excel": "./lib/@vue-office/excel/vue-office-excel.mjs", "@vue-office/excel": "./lib/@vue-office/excel/vue-office-excel.mjs",
"@vue/devtools-api": "./lib/@vue/devtools-api/shim.js", "@vue/devtools-api": "./lib/@vue/devtools-api/shim.js",

17
code/src/Modules/SettleAccount/host/SettleAccount.HttpApi.Host/wwwroot/views/base-data/job-item.js

@ -1,15 +1,14 @@
import AppList from "../../components/list/index.js"; import AppList from "../../components/list/index.js";
import html from "html"; import html from "html";
import useConfig from "../../models/job-item.js"; import useConfig from "../../models/job-item.js";
import { defineAsyncComponent, ref, reactive, onMounted, watch } from "vue"; import { ref, nextTick, onMounted, onUnmounted } from "vue";
import useConfig2 from "../../models/job-log.js"; import useConfig2 from "../../models/job-log.js";
export default { export default {
components: { AppList }, components: { AppList },
template: html`<app-list :config="config" @command="onCommand" ref="appListRef" />`, template: html`<app-list v-if="refresh" :config="config" @command="onCommand" />`,
setup() { setup() {
const config = useConfig(); const config = useConfig();
const appListRef = ref(null);
const onCommand = async (item, rows, showList) => { const onCommand = async (item, rows, showList) => {
console.log(item.path, item, rows); console.log(item.path, item, rows);
console.log(showList); console.log(showList);
@ -17,6 +16,16 @@ export default {
config.query.schema.properties.filters.default[0].value = rows[0].id; config.query.schema.properties.filters.default[0].value = rows[0].id;
showList({ test: "test" }, "/base-data/job-log", config); showList({ test: "test" }, "/base-data/job-log", config);
}; };
return { config, onCommand }; const refresh = ref(true);
onMounted(async () => {
PubSub.subscribe("JobItem", () => {
refresh.value = false;
nextTick(() => (refresh.value = true));
});
});
onUnmounted(() => {
PubSub.unsubscribe(onMonitor);
});
return { config, onCommand, refresh };
}, },
}; };

13
code/src/Modules/SettleAccount/src/SettleAccount.Application/Entities/BQ/JobHostdService.cs

@ -78,10 +78,11 @@ public class JobHostdService : BackgroundService, IApplicationService
if (!jobItem.IsRunning) if (!jobItem.IsRunning)
{ {
jobLogId = this.JobItemStart(job.Id); jobLogId = this.JobItemStart(job.Id);
} if (jobLogId.HasValue)
{
try try
{ {
jobService.Invoke(); await jobService.Invoke().ConfigureAwait(false);
this.JobItemSuccess(job.Id, jobLogId.Value); this.JobItemSuccess(job.Id, jobLogId.Value);
Debug.WriteLine($"{job.Name} 定时任务执行成功"); Debug.WriteLine($"{job.Name} 定时任务执行成功");
} }
@ -94,6 +95,8 @@ public class JobHostdService : BackgroundService, IApplicationService
} }
} }
} }
}
}
catch (Exception ex) catch (Exception ex)
{ {
Console.WriteLine(ex.ToString()); Console.WriteLine(ex.ToString());
@ -105,8 +108,10 @@ public class JobHostdService : BackgroundService, IApplicationService
{ {
Console.WriteLine(ex.ToString()); Console.WriteLine(ex.ToString());
} }
}); })
thread.IsBackground = true; {
IsBackground = true
};
if (this.Jobs.TryAdd(job, new Tuple<CancellationTokenSource, Thread>(source, thread))) if (this.Jobs.TryAdd(job, new Tuple<CancellationTokenSource, Thread>(source, thread)))
{ {
thread.Start(); thread.Start();

14
code/src/Modules/SettleAccount/src/SettleAccount.Application/Entities/BQ/JobItemAppService.cs

@ -4,7 +4,9 @@ using System.Linq;
using System.Linq.Dynamic.Core; using System.Linq.Dynamic.Core;
using System.Threading.Tasks; using System.Threading.Tasks;
using Microsoft.AspNetCore.Mvc; using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.SignalR;
using Omu.ValueInjecter; using Omu.ValueInjecter;
using SettleAccount.Job.SignalR;
using Volo.Abp.Application.Dtos; using Volo.Abp.Application.Dtos;
using Volo.Abp.Application.Services; using Volo.Abp.Application.Services;
using Volo.Abp.DependencyInjection; using Volo.Abp.DependencyInjection;
@ -19,11 +21,13 @@ public class JobItemAppService : ApplicationService, ITransientDependency
{ {
private readonly INormalEfCoreRepository<JobItem, Guid> _repository; private readonly INormalEfCoreRepository<JobItem, Guid> _repository;
private readonly JobHostdService _jobHostdService; private readonly JobHostdService _jobHostdService;
private readonly IHubContext<PageHub> _hubContext;
public JobItemAppService(INormalEfCoreRepository<JobItem, Guid> repository, JobHostdService jobHostdService) public JobItemAppService(INormalEfCoreRepository<JobItem, Guid> repository, JobHostdService jobHostdService, IHubContext<PageHub> hubContext)
{ {
this._repository = repository; this._repository = repository;
this._jobHostdService = jobHostdService; this._jobHostdService = jobHostdService;
this._hubContext = hubContext;
} }
[HttpPost] [HttpPost]
@ -31,6 +35,7 @@ public class JobItemAppService : ApplicationService, ITransientDependency
{ {
var entity = await _repository.InsertAsync(input).ConfigureAwait(false); var entity = await _repository.InsertAsync(input).ConfigureAwait(false);
this._jobHostdService.AddJob(entity); this._jobHostdService.AddJob(entity);
this.Notify();
return entity; return entity;
} }
@ -43,6 +48,7 @@ public class JobItemAppService : ApplicationService, ITransientDependency
await _repository.DeleteAsync(item).ConfigureAwait(false); await _repository.DeleteAsync(item).ConfigureAwait(false);
this._jobHostdService.RemoveJob(item); this._jobHostdService.RemoveJob(item);
} }
this.Notify();
return entites.Count > 0; return entites.Count > 0;
} }
@ -73,8 +79,14 @@ public class JobItemAppService : ApplicationService, ITransientDependency
this._jobHostdService.RemoveJob(entity); this._jobHostdService.RemoveJob(entity);
this._jobHostdService.AddJob(entity); this._jobHostdService.AddJob(entity);
} }
this.Notify();
return input; return input;
} }
private void Notify()
{
this._hubContext.Clients.All.ServerToClient("JobItem", "refresh", "");
}
} }
[Route("api/settleaccount/[controller]/[action]")] [Route("api/settleaccount/[controller]/[action]")]

14
code/src/Modules/SettleAccount/src/SettleAccount.Application/Entities/BQ/VmiAppService.cs

@ -1,7 +1,6 @@
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.ComponentModel.DataAnnotations; using System.ComponentModel.DataAnnotations;
using System.Diagnostics;
using System.Globalization; using System.Globalization;
using System.IO; using System.IO;
using System.Linq; using System.Linq;
@ -13,11 +12,13 @@ using InfluxDB.LineProtocol.Client;
using Magicodes.ExporterAndImporter.Core.Extension; using Magicodes.ExporterAndImporter.Core.Extension;
using Microsoft.AspNetCore.Authorization; using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc; using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.SignalR;
using Microsoft.EntityFrameworkCore; using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Infrastructure; using Microsoft.EntityFrameworkCore.Infrastructure;
using Microsoft.EntityFrameworkCore.Storage; using Microsoft.EntityFrameworkCore.Storage;
using Microsoft.Extensions.Configuration; using Microsoft.Extensions.Configuration;
using Microsoft.OpenApi.Extensions; using Microsoft.OpenApi.Extensions;
using SettleAccount.Job.SignalR;
using Volo.Abp.Application.Dtos; using Volo.Abp.Application.Dtos;
using Volo.Abp.Application.Services; using Volo.Abp.Application.Services;
using Volo.Abp.BlobStoring; using Volo.Abp.BlobStoring;
@ -51,18 +52,21 @@ public class VmiAppService : ApplicationService, IVmiService, IJobService, ITran
private readonly INormalEfCoreRepository<VmiLog, Guid> _logRepository; private readonly INormalEfCoreRepository<VmiLog, Guid> _logRepository;
private readonly INormalEfCoreRepository<VmiSnapshot, Guid> _snapshotRepository; private readonly INormalEfCoreRepository<VmiSnapshot, Guid> _snapshotRepository;
private readonly IBlobContainer<MyFileContainer> _fileContainer; private readonly IBlobContainer<MyFileContainer> _fileContainer;
private readonly IHubContext<PageHub> _hubContext;
public VmiAppService(IConfiguration cfg, public VmiAppService(IConfiguration cfg,
INormalEfCoreRepository<VmiBalance, Guid> balanceRepository, INormalEfCoreRepository<VmiBalance, Guid> balanceRepository,
INormalEfCoreRepository<VmiLog, Guid> logRepository, INormalEfCoreRepository<VmiLog, Guid> logRepository,
INormalEfCoreRepository<VmiSnapshot, Guid> snapshotRepository, INormalEfCoreRepository<VmiSnapshot, Guid> snapshotRepository,
IBlobContainer<MyFileContainer> fileContainer) IBlobContainer<MyFileContainer> fileContainer,
IHubContext<PageHub> hubContext)
{ {
this._cfg = cfg; this._cfg = cfg;
this._balanceRepository = balanceRepository; this._balanceRepository = balanceRepository;
this._logRepository = logRepository; this._logRepository = logRepository;
this._snapshotRepository = snapshotRepository; this._snapshotRepository = snapshotRepository;
this._fileContainer = fileContainer; this._fileContainer = fileContainer;
this._hubContext = hubContext;
} }
/// <summary> /// <summary>
@ -70,8 +74,9 @@ public class VmiAppService : ApplicationService, IVmiService, IJobService, ITran
/// </summary> /// </summary>
[HttpPost] [HttpPost]
[UnitOfWork] [UnitOfWork]
public void Invoke() public virtual Task Invoke()
{ {
this._hubContext.Clients.All.ServerToClient("JobItem", "refresh", "");
Directory.CreateDirectory(Path.Combine(Directory.GetCurrentDirectory(), "wwwroot/files/vmi")); Directory.CreateDirectory(Path.Combine(Directory.GetCurrentDirectory(), "wwwroot/files/vmi"));
var date = DateTime.Now.ToString("yyyyMMddHH"); var date = DateTime.Now.ToString("yyyyMMddHH");
var connectionString = $"Data Source=wwwroot/files/vmi/{date}.db"; var connectionString = $"Data Source=wwwroot/files/vmi/{date}.db";
@ -87,7 +92,8 @@ public class VmiAppService : ApplicationService, IVmiService, IJobService, ITran
var snapshot = new VmiSnapshot { Name = date, Path = connectionString }; var snapshot = new VmiSnapshot { Name = date, Path = connectionString };
this._snapshotRepository.InsertAsync(snapshot).Wait(); this._snapshotRepository.InsertAsync(snapshot).Wait();
} }
Debug.WriteLine($"{nameof(VmiAppService)}:{DateTime.Now}"); this._hubContext.Clients.All.ServerToClient("JobItem", "refresh", "");
return Task.CompletedTask;
} }
/// <summary> /// <summary>

4
code/src/Modules/SettleAccount/src/SettleAccount.Domain/Entities/BQ/Vmi/IJobService.cs

@ -1,6 +1,8 @@
using System.Threading.Tasks;
namespace Win.Sfs.SettleAccount.Entities.BQ.Vmi; namespace Win.Sfs.SettleAccount.Entities.BQ.Vmi;
public interface IJobService public interface IJobService
{ {
void Invoke(); Task Invoke();
} }

Loading…
Cancel
Save