😎1、增加生成种子提示 2、调整文件上传
This commit is contained in:
parent
63ad79b527
commit
ef08b47b8a
@ -37,7 +37,7 @@
|
||||
<PackageReference Include="SqlSugarCore" Version="5.1.4.160" />
|
||||
<PackageReference Include="SSH.NET" Version="2024.1.0" />
|
||||
<PackageReference Include="System.Linq.Dynamic.Core" Version="1.4.3" />
|
||||
<PackageReference Include="TencentCloudSDK.Sms" Version="3.0.1040" />
|
||||
<PackageReference Include="TencentCloudSDK.Sms" Version="3.0.1041" />
|
||||
<PackageReference Include="UAParser" Version="3.1.47" />
|
||||
<PackageReference Include="Yitter.IdGenerator" Version="1.0.14" />
|
||||
</ItemGroup>
|
||||
|
||||
28
Admin.NET/Admin.NET.Core/Attribute/NotEmptyAttribute.cs
Normal file
28
Admin.NET/Admin.NET.Core/Attribute/NotEmptyAttribute.cs
Normal file
@ -0,0 +1,28 @@
|
||||
// Admin.NET 项目的版权、商标、专利和其他相关权利均受相应法律法规的保护。使用本项目应遵守相关法律法规和许可证的要求。
|
||||
//
|
||||
// 本项目主要遵循 MIT 许可证和 Apache 许可证(版本 2.0)进行分发和使用。许可证位于源代码树根目录中的 LICENSE-MIT 和 LICENSE-APACHE 文件。
|
||||
//
|
||||
// 不得利用本项目从事危害国家安全、扰乱社会秩序、侵犯他人合法权益等法律法规禁止的活动!任何基于本项目二次开发而产生的一切法律纠纷和责任,我们不承担任何责任!
|
||||
|
||||
namespace Admin.NET.Core;
|
||||
|
||||
/// <summary>
|
||||
/// 校验集合不能为空
|
||||
/// </summary>
|
||||
[SuppressSniffer]
|
||||
public class NotEmptyAttribute : ValidationAttribute
|
||||
{
|
||||
/// <summary>
|
||||
/// 校验集合不能为空
|
||||
/// </summary>
|
||||
/// <param name="value"></param>
|
||||
/// <returns></returns>
|
||||
public override bool IsValid(object value) => (value as IEnumerable)?.GetEnumerator().MoveNext() ?? false;
|
||||
|
||||
/// <summary>
|
||||
/// 错误信息
|
||||
/// </summary>
|
||||
/// <param name="name"></param>
|
||||
/// <returns></returns>
|
||||
public override string FormatErrorMessage(string name) => base.FormatErrorMessage(name);
|
||||
}
|
||||
@ -655,6 +655,12 @@ public enum ErrorCodeEnum
|
||||
[ErrorCodeItemMetadata("不允许添加相同字段名")]
|
||||
db1002,
|
||||
|
||||
/// <summary>
|
||||
/// 实体文件不存在或匹配不到。如果是刚刚生成的实体,请重启服务后再试
|
||||
/// </summary>
|
||||
[ErrorCodeItemMetadata("实体文件不存在或匹配不到。如果是刚刚生成的实体,请重启服务后再试")]
|
||||
db1003,
|
||||
|
||||
/// <summary>
|
||||
/// 父节点不存在
|
||||
/// </summary>
|
||||
|
||||
@ -316,7 +316,7 @@ public class SysDatabaseService : IDynamicApiController, ITransient
|
||||
/// <param name="input"></param>
|
||||
[ApiDescriptionSettings(Name = "CreateSeedData"), HttpPost]
|
||||
[DisplayName("创建种子数据")]
|
||||
public async void CreateSeedData(CreateSeedDataInput input)
|
||||
public async Task CreateSeedData(CreateSeedDataInput input)
|
||||
{
|
||||
var config = App.GetOptions<DbConnectionOptions>().ConnectionConfigs.FirstOrDefault(u => u.ConfigId.ToString() == input.ConfigId);
|
||||
input.Position = string.IsNullOrWhiteSpace(input.Position) ? "Admin.NET.Core" : input.Position;
|
||||
@ -333,7 +333,7 @@ public class SysDatabaseService : IDynamicApiController, ITransient
|
||||
entityType = item.Type;
|
||||
break;
|
||||
}
|
||||
if (entityType == null) return;
|
||||
if (entityType == null) throw Oops.Oh(ErrorCodeEnum.db1003);
|
||||
|
||||
input.EntityName = entityType.Name;
|
||||
input.SeedDataName = entityType.Name + "SeedData";
|
||||
|
||||
@ -168,7 +168,7 @@ public class SysDictTypeService : IDynamicApiController, ITransient
|
||||
var ds = await _sysDictTypeRep.AsQueryable()
|
||||
.InnerJoin<SysDictData>((u, a) => u.Id == a.DictTypeId)
|
||||
.Where((u, a) => u.IsDelete == false && a.IsDelete == false && a.Status == StatusEnum.Enable)
|
||||
.Select((u, a) => new { TypeCode = u.Code, a.Code, a.Name, a.Value, a.Remark, a.OrderNo, a.TagType })
|
||||
.Select((u, a) => new { TypeCode = u.Code, a.Code, a.Name, a.Value, a.Remark, a.OrderNo, a.TagType, a.ExtData })
|
||||
.ToListAsync();
|
||||
return ds.OrderBy(u => u.OrderNo).GroupBy(u => u.TypeCode).ToDictionary(u => u.Key, u => u);
|
||||
}
|
||||
|
||||
@ -5,7 +5,6 @@
|
||||
// 不得利用本项目从事危害国家安全、扰乱社会秩序、侵犯他人合法权益等法律法规禁止的活动!任何基于本项目二次开发而产生的一切法律纠纷和责任,我们不承担任何责任!
|
||||
|
||||
using Aliyun.OSS.Util;
|
||||
using Furion.VirtualFileServer;
|
||||
using OnceMi.AspNetCore.OSS;
|
||||
|
||||
namespace Admin.NET.Core.Service;
|
||||
@ -112,7 +111,7 @@ public class SysFileService : IDynamicApiController, ITransient
|
||||
[DisplayName("根据文件Id或Url下载")]
|
||||
public async Task<IActionResult> DownloadFile(FileInput input)
|
||||
{
|
||||
var file = input.Id > 0 ? await GetFile(input) : await _sysFileRep.GetFirstAsync(u => u.Url == input.Url);
|
||||
var file = input.Id > 0 ? await GetFile(input) : await _sysFileRep.CopyNew().GetFirstAsync(u => u.Url == input.Url);
|
||||
var fileName = HttpUtility.UrlEncode(file.FileName, Encoding.GetEncoding("UTF-8"));
|
||||
|
||||
if (_OSSProviderOptions.IsEnable)
|
||||
@ -198,7 +197,7 @@ public class SysFileService : IDynamicApiController, ITransient
|
||||
}
|
||||
else if (App.Configuration["SSHProvider:IsEnable"].ToBoolean())
|
||||
{
|
||||
var sysFile = await _sysFileRep.GetFirstAsync(u => u.Url == url) ?? throw Oops.Oh($"文件不存在");
|
||||
var sysFile = await _sysFileRep.CopyNew().GetFirstAsync(u => u.Url == url) ?? throw Oops.Oh($"文件不存在");
|
||||
using (SSHHelper helper = new SSHHelper(App.Configuration["SSHProvider:Host"],
|
||||
App.Configuration["SSHProvider:Port"].ToInt(), App.Configuration["SSHProvider:Username"], App.Configuration["SSHProvider:Password"]))
|
||||
{
|
||||
@ -207,14 +206,17 @@ public class SysFileService : IDynamicApiController, ITransient
|
||||
}
|
||||
else
|
||||
{
|
||||
var sysFile = await _sysFileRep.GetFirstAsync(u => u.Url == url) ?? throw Oops.Oh($"文件不存在");
|
||||
var sysFile = await _sysFileRep.CopyNew().GetFirstAsync(u => u.Url == url) ?? throw Oops.Oh($"文件不存在");
|
||||
var filePath = Path.Combine(App.WebHostEnvironment.WebRootPath, sysFile.FilePath);
|
||||
if (!Directory.Exists(filePath))
|
||||
Directory.CreateDirectory(filePath);
|
||||
|
||||
var realFile = Path.Combine(filePath, $"{sysFile.Id}{sysFile.Suffix}");
|
||||
if (!File.Exists(realFile))
|
||||
throw Oops.Oh($"文件[{realFile}]不在存");
|
||||
{
|
||||
Log.Error($"DownloadFileBase64:文件[{realFile}]不存在");
|
||||
throw Oops.Oh($"文件[{sysFile.FilePath}]不存在");
|
||||
}
|
||||
byte[] fileBytes = File.ReadAllBytes(realFile);
|
||||
return Convert.ToBase64String(fileBytes);
|
||||
}
|
||||
@ -278,7 +280,7 @@ public class SysFileService : IDynamicApiController, ITransient
|
||||
/// <returns></returns>
|
||||
private async Task<SysFile> GetFile([FromQuery] FileInput input)
|
||||
{
|
||||
var file = await _sysFileRep.GetFirstAsync(u => u.Id == input.Id);
|
||||
var file = await _sysFileRep.CopyNew().GetFirstAsync(u => u.Id == input.Id);
|
||||
return file ?? throw Oops.Oh(ErrorCodeEnum.D8000);
|
||||
}
|
||||
|
||||
@ -321,6 +323,8 @@ public class SysFileService : IDynamicApiController, ITransient
|
||||
|
||||
// 获取文件后缀
|
||||
var suffix = Path.GetExtension(file.FileName).ToLower(); // 后缀
|
||||
if (string.IsNullOrWhiteSpace(suffix))
|
||||
suffix = string.Concat(".", file.ContentType.AsSpan(file.ContentType.LastIndexOf('/') + 1));
|
||||
if (!string.IsNullOrWhiteSpace(suffix))
|
||||
{
|
||||
//var contentTypeProvider = FS.GetFileExtensionContentTypeProvider();
|
||||
|
||||
@ -4,7 +4,7 @@
|
||||
<el-card :model="connection">
|
||||
<h1>连接参数(Configuration)</h1>
|
||||
<el-form label-position="top" :model="connection">
|
||||
<el-row :gutter="20">
|
||||
<el-row :gutter="6">
|
||||
<el-col :span="8">
|
||||
<el-form-item prop="host" label="协议|主机|端口">
|
||||
<el-input v-model="connection.host" :disabled="connSuccess" type="password" show-password>
|
||||
@ -49,7 +49,6 @@
|
||||
<el-button
|
||||
type="primary"
|
||||
:icon="Setting"
|
||||
size="default"
|
||||
class="sub-btn"
|
||||
:disabled="client.connected"
|
||||
@click="createConnection"
|
||||
@ -58,7 +57,7 @@
|
||||
>
|
||||
{{ client.connected ? '已连接(Connected)' : '连接(Connect)' }}
|
||||
</el-button>
|
||||
<el-button v-if="client.connected" type="warning" size="default" :icon="Discount" @click="destroyConnection" :loading="btnLoadingType === 'disconnect'"> 断开(Disconnect) </el-button>
|
||||
<el-button v-if="client.connected" class="sub-btn" type="warning" :icon="Discount" @click="destroyConnection" :loading="btnLoadingType === 'disconnect'"> 断开(Disconnect) </el-button>
|
||||
</el-col>
|
||||
</el-row>
|
||||
</el-form>
|
||||
@ -67,7 +66,7 @@
|
||||
<el-card shadow="hover">
|
||||
<h1>订阅(Subscribe)</h1>
|
||||
<el-form label-position="top" :model="subscription">
|
||||
<el-row :gutter="20">
|
||||
<el-row :gutter="6">
|
||||
<el-col :span="12">
|
||||
<el-form-item prop="topic" label="订阅主题(Topic)">
|
||||
<el-input v-model="connection.subTopics" :disabled="subscribedSuccess" type="password" show-password></el-input>
|
||||
@ -84,7 +83,6 @@
|
||||
<el-button
|
||||
type="primary"
|
||||
:icon="Connection"
|
||||
size="default"
|
||||
class="sub-btn"
|
||||
:style="{ display: subscribedSuccess ? 'none' : '' }"
|
||||
:loading="btnLoadingType === 'subscribe'"
|
||||
@ -93,16 +91,7 @@
|
||||
>
|
||||
{{ subscribedSuccess ? '已订阅(Subscribed)' : '订阅(Subscribe)' }}
|
||||
</el-button>
|
||||
<el-button
|
||||
v-if="subscribedSuccess"
|
||||
type="warning"
|
||||
:icon="Discount"
|
||||
size="default"
|
||||
class="sub-btn"
|
||||
:loading="btnLoadingType === 'unsubscribe'"
|
||||
:disabled="!client.connected"
|
||||
@click="doUnSubscribe"
|
||||
>
|
||||
<el-button v-if="subscribedSuccess" type="warning" :icon="Discount" class="sub-btn" :loading="btnLoadingType === 'unsubscribe'" :disabled="!client.connected" @click="doUnSubscribe">
|
||||
取消(Unsubscribe)
|
||||
</el-button>
|
||||
</el-col>
|
||||
@ -113,7 +102,7 @@
|
||||
<el-card shadow="hover">
|
||||
<h1>发布(Publish)</h1>
|
||||
<el-form label-position="top" :model="publish">
|
||||
<el-row :gutter="30">
|
||||
<el-row :gutter="6">
|
||||
<el-col :span="8">
|
||||
<el-form-item prop="topic" label="发布主题(Topic)">
|
||||
<el-input v-model="connection.pubTopic" type="password" show-password></el-input>
|
||||
@ -136,7 +125,7 @@
|
||||
</el-col>
|
||||
</el-row>
|
||||
|
||||
<el-row :gutter="30">
|
||||
<el-row :gutter="6">
|
||||
<el-col :span="16">
|
||||
<el-form-item prop="payload" label="操作指令(Payload)">
|
||||
<el-input v-model="publish.payload" clearable maxlength="64" show-word-limit>
|
||||
@ -158,15 +147,7 @@
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="8" class="text-right">
|
||||
<el-button
|
||||
type="success"
|
||||
:icon="Position"
|
||||
size="default"
|
||||
class="sub-btn"
|
||||
:loading="btnLoadingType === 'publish'"
|
||||
:disabled="!client.connected"
|
||||
@click="doPublish(publish.payload, connection.pubTopic)"
|
||||
>
|
||||
<el-button type="success" :icon="Position" class="sub-btn" :loading="btnLoadingType === 'publish'" :disabled="!client.connected" @click="doPublish(publish.payload, connection.pubTopic)">
|
||||
发布(Publish)
|
||||
</el-button>
|
||||
</el-col>
|
||||
@ -176,113 +157,104 @@
|
||||
|
||||
<el-card shadow="hover">
|
||||
<h1>
|
||||
<el-button @click="clsmsg" type="Success" size="default" :icon="Delete" title="点击清空历史记录">接收(Receive)</el-button>
|
||||
<el-tag size="default" title="接收次数">收 {{ recvnum }}</el-tag>
|
||||
<el-tag size="default" :title="dht_tm">{{ dht_wsd }}</el-tag>
|
||||
<el-tag size="default" title="设备已工作时长">{{ parseInt(runSeconds) }} 秒</el-tag>
|
||||
<el-button @click="clsmsg" type="success" :icon="Delete" title="点击清空历史记录">接收(Receive)</el-button>
|
||||
<el-tag title="接收次数">收 {{ recvnum }}</el-tag>
|
||||
<el-tag :title="dht_tm">{{ dht_wsd }}</el-tag>
|
||||
<el-tag title="设备已工作时长">{{ parseInt(runSeconds) }} 秒</el-tag>
|
||||
<el-button
|
||||
type="success"
|
||||
title="关闭一路"
|
||||
:disabled="!connection.onlineStatus | !client.connected"
|
||||
:disabled="!connection.onlineStatus || !client.connected"
|
||||
v-if="connection.ch1_Status"
|
||||
icon="ele-Check"
|
||||
size="default"
|
||||
id="ch1"
|
||||
v-preventReClick="2000"
|
||||
v-reclick="2000"
|
||||
@click="switchLight('55 AA AA AA AA 81 01 00')"
|
||||
>关闭</el-button
|
||||
>
|
||||
<el-button
|
||||
type="warning"
|
||||
title="打开一路"
|
||||
:disabled="!connection.onlineStatus | !client.connected"
|
||||
:disabled="!connection.onlineStatus || !client.connected"
|
||||
v-else="!connection.ch1_Status"
|
||||
icon="ele-CloseBold"
|
||||
size="default"
|
||||
id="ch1"
|
||||
v-preventReClick="2000"
|
||||
v-reclick="2000"
|
||||
@click="switchLight('55 AA AA AA AA 81 01 01')"
|
||||
>打开</el-button
|
||||
>
|
||||
<el-button
|
||||
type="success"
|
||||
title="关闭二路"
|
||||
:disabled="!connection.onlineStatus | !client.connected"
|
||||
:disabled="!connection.onlineStatus || !client.connected"
|
||||
v-if="connection.ch2_Status"
|
||||
icon="ele-Check"
|
||||
size="default"
|
||||
id="ch2"
|
||||
v-preventReClick="2000"
|
||||
v-reclick="2000"
|
||||
@click="switchLight('55 AA AA AA AA 81 02 00')"
|
||||
>关闭</el-button
|
||||
>
|
||||
<el-button
|
||||
type="warning"
|
||||
title="打开二路"
|
||||
:disabled="!connection.onlineStatus | !client.connected"
|
||||
:disabled="!connection.onlineStatus || !client.connected"
|
||||
v-else="!connection.ch2_Status"
|
||||
icon="ele-CloseBold"
|
||||
size="default"
|
||||
id="ch2"
|
||||
v-preventReClick="2000"
|
||||
v-reclick="2000"
|
||||
@click="switchLight('55 AA AA AA AA 81 02 01')"
|
||||
>打开</el-button
|
||||
>
|
||||
<el-button
|
||||
type="success"
|
||||
title="关闭三路"
|
||||
:disabled="!connection.onlineStatus | !client.connected"
|
||||
:disabled="!connection.onlineStatus || !client.connected"
|
||||
v-if="connection.ch3_Status"
|
||||
icon="ele-Check"
|
||||
size="default"
|
||||
id="ch3"
|
||||
v-preventReClick="2000"
|
||||
v-reclick="2000"
|
||||
@click="switchLight('55 AA AA AA AA 81 03 00')"
|
||||
>关闭</el-button
|
||||
>
|
||||
<el-button
|
||||
type="warning"
|
||||
title="打开三路"
|
||||
:disabled="!connection.onlineStatus | !client.connected"
|
||||
:disabled="!connection.onlineStatus || !client.connected"
|
||||
v-else="!connection.ch3_Status"
|
||||
icon="ele-CloseBold"
|
||||
size="default"
|
||||
id="ch3"
|
||||
v-preventReClick="2000"
|
||||
v-reclick="2000"
|
||||
@click="switchLight('55 AA AA AA AA 81 03 01')"
|
||||
>打开</el-button
|
||||
>
|
||||
<el-button
|
||||
type="success"
|
||||
title="关闭四路"
|
||||
:disabled="!connection.onlineStatus | !client.connected"
|
||||
:disabled="!connection.onlineStatus || !client.connected"
|
||||
v-if="connection.ch4_Status"
|
||||
icon="ele-Check"
|
||||
size="default"
|
||||
id="ch4"
|
||||
v-preventReClick="2000"
|
||||
v-reclick="2000"
|
||||
@click="switchLight('55 AA AA AA AA 81 04 00')"
|
||||
>关闭</el-button
|
||||
>
|
||||
<el-button
|
||||
type="warning"
|
||||
title="打开四路"
|
||||
:disabled="!connection.onlineStatus | !client.connected"
|
||||
:disabled="!connection.onlineStatus || !client.connected"
|
||||
v-else="!connection.ch4_Status"
|
||||
icon="ele-CloseBold"
|
||||
size="default"
|
||||
id="ch4"
|
||||
v-preventReClick="2000"
|
||||
v-reclick="2000"
|
||||
@click="switchLight('55 AA AA AA AA 81 04 01')"
|
||||
>打开</el-button
|
||||
>
|
||||
<el-button
|
||||
type="danger"
|
||||
title="四路全部关闭"
|
||||
:disabled="!connection.onlineStatus | !client.connected"
|
||||
:disabled="!connection.onlineStatus || !client.connected"
|
||||
v-if="connection.all_Status"
|
||||
icon="ele-SwitchButton"
|
||||
size="default"
|
||||
id="ch5"
|
||||
@click="switchLight('55 AA AA AA AA 81 A4 00')"
|
||||
>全关</el-button
|
||||
@ -290,16 +262,15 @@
|
||||
<el-button
|
||||
type="success"
|
||||
title="四路全部打开"
|
||||
:disabled="!connection.onlineStatus | !client.connected"
|
||||
:disabled="!connection.onlineStatus || !client.connected"
|
||||
v-else="!connection.all_Status"
|
||||
icon="ele-Switch"
|
||||
size="default"
|
||||
id="ch5"
|
||||
@click="switchLight('55 AA AA AA AA 81 A4 01')"
|
||||
>全开</el-button
|
||||
>
|
||||
|
||||
<el-alert v-if="!client.connected || !connection.onlineStatus" title="网络服务断开或设备离线!" center type="warning" effect="light" />
|
||||
<el-alert v-if="!client.connected || !connection.onlineStatus" title="网络服务断开或设备离线!" center type="warning" effect="light" style="margin-top: 4px" />
|
||||
</h1>
|
||||
<!-- 绑定接收日志,只读 -->
|
||||
<el-col :span="24">
|
||||
@ -347,7 +318,7 @@ const retryTimes = ref(0); //重连次数
|
||||
* ws -> 8083; wss -> 8084
|
||||
* By default, EMQX allows clients to connect without authentication.
|
||||
* https://docs.emqx.com/en/enterprise/v4.4/advanced/auth.html#anonymous-login
|
||||
|
||||
|
||||
* for more options and details, please refer to https://github.com/mqttjs/MQTT.js#mqttclientstreambuilder-options
|
||||
*/
|
||||
const connection = reactive({
|
||||
@ -748,20 +719,19 @@ const clsmsg = () => {
|
||||
<style lang="scss" scoped>
|
||||
.mqtt-box {
|
||||
max-width: 100%;
|
||||
padding: 4px;
|
||||
margin: 10px auto 0 auto;
|
||||
margin: 0 auto;
|
||||
}
|
||||
|
||||
.header {
|
||||
font-size: 24px;
|
||||
font-weight: bold;
|
||||
margin: -12px auto 8px auto;
|
||||
margin: -6px auto 0px auto;
|
||||
}
|
||||
|
||||
h1 {
|
||||
font-size: 16px;
|
||||
margin-top: 10px auto 20px auto;
|
||||
padding: 5px 0px 5px 0;
|
||||
padding: 6px 0px 6px 0;
|
||||
}
|
||||
|
||||
.el-col {
|
||||
@ -772,7 +742,7 @@ h1 {
|
||||
font-size: 13px;
|
||||
}
|
||||
.el-card {
|
||||
margin-bottom: 12px;
|
||||
margin-bottom: 6px;
|
||||
}
|
||||
.el-card__body {
|
||||
padding: 24px;
|
||||
|
||||
@ -32,7 +32,11 @@
|
||||
<el-button-group style="padding-left: 12px; padding-right: 12px">
|
||||
<el-button icon="ele-Plus" @click="showAddColumn"> 增加列 </el-button>
|
||||
<el-button icon="ele-Plus" @click="showGenDialog"> 生成实体 </el-button>
|
||||
<el-button icon="ele-Plus" @click="showGenSeedDataDialog"> 生成种子 </el-button>
|
||||
<el-popover placement="bottom" title="温馨提示" :width="200" trigger="hover" content="如果是刚刚生成的实体,请重启服务后再生成种子">
|
||||
<template #reference>
|
||||
<el-button icon="ele-Plus" @click="showGenSeedDataDialog"> 生成种子 </el-button>
|
||||
</template>
|
||||
</el-popover>
|
||||
</el-button-group>
|
||||
<el-button icon="ele-View" type="primary" @click="visualTable" plain> 可视化 </el-button>
|
||||
</template>
|
||||
|
||||
Loading…
Reference in New Issue
Block a user