🍒 feat(流水号): 增加流水号插槽、类型提供者接口,方便业务层扩展

This commit is contained in:
喵你个汪呀 2025-08-25 21:48:36 +08:00
parent 3f51f0123b
commit 334a9a327b
26 changed files with 451 additions and 72 deletions

View File

@ -22,7 +22,7 @@ public class TestCodeGenDemo : EntityBase
/// <summary>
/// 流水号
/// </summary>
[BindSerial(SerialTypeEnum.Other)]
[BindSerial(nameof(SysSerialTypeProvider.Test))]
[SugarColumn(ColumnDescription = "流水号", Length = 128)]
public string? SeqNo { get; set; }

View File

@ -0,0 +1,27 @@
// Admin.NET 项目的版权、商标、专利和其他相关权利均受相应法律法规的保护。使用本项目应遵守相关法律法规和许可证的要求。
//
// 本项目主要遵循 MIT 许可证和 Apache 许可证(版本 2.0)进行分发和使用。许可证位于源代码树根目录中的 LICENSE-MIT 和 LICENSE-APACHE 文件。
//
// 不得利用本项目从事危害国家安全、扰乱社会秩序、侵犯他人合法权益等法律法规禁止的活动!任何基于本项目二次开发而产生的一切法律纠纷和责任,我们不承担任何责任!
namespace Admin.NET.Application;
/// <summary>
/// 流水号种子数据
/// </summary>
[SeedData(500)]
[IncreSeed]
public class SysSerialSeedData : ISqlSugarEntitySeedData<SysSerial>
{
/// <summary>
/// 种子数据
/// </summary>
/// <returns></returns>
public IEnumerable<SysSerial> HasData()
{
return
[
new(){ Id=1300000000101, Type=SysSerialTypeProvider.Test, ResetInterval=ResetIntervalEnum.Day, Formater="T{yyyy}{MM}{SEQ}", Seq=0, Min=1, Max=9999999, Expy=DateTime.Parse("2025-01-01 12:00:00"), TenantId=SqlSugarConst.DefaultTenantId, OrderNo=100 },
];
}
}

View File

@ -0,0 +1,22 @@
// Admin.NET 项目的版权、商标、专利和其他相关权利均受相应法律法规的保护。使用本项目应遵守相关法律法规和许可证的要求。
//
// 本项目主要遵循 MIT 许可证和 Apache 许可证(版本 2.0)进行分发和使用。许可证位于源代码树根目录中的 LICENSE-MIT 和 LICENSE-APACHE 文件。
//
// 不得利用本项目从事危害国家安全、扰乱社会秩序、侵犯他人合法权益等法律法规禁止的活动!任何基于本项目二次开发而产生的一切法律纠纷和责任,我们不承担任何责任!
namespace Admin.NET.Application;
/// <summary>
/// 扩展流水号插槽
/// </summary>
public class SysSerialSlotProvider : ISysSerialSlotProvider
{
private static Lazy<UserManager> UserManager => new(() => App.GetService<UserManager>());
public Dictionary<string, Func<long, long, DateTime, string>> GetSlotMap()
{
return new()
{
{ "{Account}", (seq, max, nowDate) => UserManager.Value?.Account }
};
}
}

View File

@ -0,0 +1,19 @@
// Admin.NET 项目的版权、商标、专利和其他相关权利均受相应法律法规的保护。使用本项目应遵守相关法律法规和许可证的要求。
//
// 本项目主要遵循 MIT 许可证和 Apache 许可证(版本 2.0)进行分发和使用。许可证位于源代码树根目录中的 LICENSE-MIT 和 LICENSE-APACHE 文件。
//
// 不得利用本项目从事危害国家安全、扰乱社会秩序、侵犯他人合法权益等法律法规禁止的活动!任何基于本项目二次开发而产生的一切法律纠纷和责任,我们不承担任何责任!
namespace Admin.NET.Application;
/// <summary>
/// 业务流水号类型常量
/// </summary>
public class SysSerialTypeProvider : ISysSerialTypeProvider
{
/// <summary>
/// 测试流水号
/// </summary>
[Description("测试")]
public const string Test = nameof(Test);
}

View File

@ -10,12 +10,12 @@ namespace Admin.NET.Core;
/// 绑定序列号特性类
/// </summary>
[AttributeUsage(AttributeTargets.Property, AllowMultiple = true)]
public class BindSerialAttribute(SerialTypeEnum type, bool isGlobal = false) : Attribute
public class BindSerialAttribute(string type, bool isGlobal = false) : Attribute
{
/// <summary>
/// 序列号类型
/// </summary>
public SerialTypeEnum Type { get; set; } = type;
public string Type { get; set; } = type;
/// <summary>
/// 是否全局

View File

@ -125,4 +125,14 @@ public class CacheConst
/// 流水号分布式锁缓存
/// </summary>
public const string KeySerialLock = "sys_serial_lock";
/// <summary>
/// 流水号插槽缓存
/// </summary>
public const string KeySysSerialSlot = "sys_serial_slot";
/// <summary>
/// 流水号类型
/// </summary>
public const string KeySysSerialType = "sys_serial_type";
}

View File

@ -32,9 +32,10 @@ public class SysSerial : EntityTenantId
/// <summary>
/// 使用分类
/// </summary>
[SugarColumn(ColumnDescription = "使用分类")]
[SugarColumn(ColumnDescription = "使用分类", Length = 32)]
[MaxLength(32)]
[Required]
public virtual SerialTypeEnum Type { get; set; }
public virtual string Type { get; set; }
/// <summary>
/// 重置间隔

View File

@ -905,5 +905,11 @@ public enum ErrorCodeEnum
/// 无效的流水号重置类型
/// </summary>
[ErrorCodeItemMetadata("无效的流水号重置类型")]
S0006
S0006,
/// <summary>
/// 无效的流水号类型
/// </summary>
[ErrorCodeItemMetadata("无效的流水号类型:{0}")]
S0007,
}

View File

@ -24,7 +24,7 @@ public class SerialBaseInput
/// <summary>
/// 使用分类
/// </summary>
public virtual SerialTypeEnum? Type { get; set; }
public virtual string Type { get; set; }
/// <summary>
/// 重置间隔
@ -80,8 +80,7 @@ public class PageSerialInput : BasePageInput
/// <summary>
/// 使用分类
/// </summary>
[Dict(nameof(SerialTypeEnum))]
public SerialTypeEnum? Type { get; set; }
public string Type { get; set; }
/// <summary>
/// 状态
@ -99,8 +98,7 @@ public class AddSerialInput : SerialBaseInput
/// 使用分类
/// </summary>
[Required(ErrorMessage = "使用分类不能为空")]
[Enum]
public override SerialTypeEnum? Type { get; set; }
public override string Type { get; set; }
/// <summary>
/// 重置间隔
@ -160,9 +158,8 @@ public class UpdateSerialInput : SerialBaseInput
/// <summary>
/// 使用分类
/// </summary>
[Enum]
[Required(ErrorMessage = "使用分类不能为空")]
public override SerialTypeEnum? Type { get; set; }
public override string Type { get; set; }
/// <summary>
/// 重置间隔
@ -238,6 +235,5 @@ public class GetNextSeqInput
/// <summary>
/// 使用分类
/// </summary>
[Dict(nameof(SerialTypeEnum))]
public virtual SerialTypeEnum? Type { get; set; }
public virtual string Type { get; set; }
}

View File

@ -29,7 +29,7 @@ public class PageSerialOutput
/// <summary>
/// 使用分类
/// </summary>
public SerialTypeEnum? Type { get; set; }
public string Type { get; set; }
/// <summary>
/// 重置间隔

View File

@ -0,0 +1,15 @@
// Admin.NET 项目的版权、商标、专利和其他相关权利均受相应法律法规的保护。使用本项目应遵守相关法律法规和许可证的要求。
//
// 本项目主要遵循 MIT 许可证和 Apache 许可证(版本 2.0)进行分发和使用。许可证位于源代码树根目录中的 LICENSE-MIT 和 LICENSE-APACHE 文件。
//
// 不得利用本项目从事危害国家安全、扰乱社会秩序、侵犯他人合法权益等法律法规禁止的活动!任何基于本项目二次开发而产生的一切法律纠纷和责任,我们不承担任何责任!
namespace Admin.NET.Core.Service;
/// <summary>
/// 系统流水号插槽接口
/// </summary>
public interface ISysSerialSlotProvider
{
public Dictionary<string, Func<long, long, DateTime, string>> GetSlotMap();
}

View File

@ -1,4 +1,4 @@
// Admin.NET 项目的版权、商标、专利和其他相关权利均受相应法律法规的保护。使用本项目应遵守相关法律法规和许可证的要求。
// Admin.NET 项目的版权、商标、专利和其他相关权利均受相应法律法规的保护。使用本项目应遵守相关法律法规和许可证的要求。
//
// 本项目主要遵循 MIT 许可证和 Apache 许可证(版本 2.0)进行分发和使用。许可证位于源代码树根目录中的 LICENSE-MIT 和 LICENSE-APACHE 文件。
//
@ -7,14 +7,8 @@
namespace Admin.NET.Core;
/// <summary>
/// 系统流水号类型枚举
/// 系统流水号类型常量提供者接口
/// </summary>
[Description("系统流水号类型枚举")]
public enum SerialTypeEnum
public class ISysSerialTypeProvider
{
/// <summary>
/// 其他
/// </summary>
[Description("其他")]
Other = 999,
}

View File

@ -4,6 +4,8 @@
//
// 不得利用本项目从事危害国家安全、扰乱社会秩序、侵犯他人合法权益等法律法规禁止的活动!任何基于本项目二次开发而产生的一切法律纠纷和责任,我们不承担任何责任!
using Microsoft.AspNetCore.Mvc.Rendering;
namespace Admin.NET.Core.Service;
/// <summary>
@ -18,6 +20,11 @@ public class SysSerialService : IDynamicApiController, ITransient
private readonly UserManager _userManager;
private readonly ISqlSugarClient _db;
/// <summary>
/// 因为缓存的是代理,无法序列化,所以只能用字典缓存
/// </summary>
private readonly ConcurrentDictionary<string, Dictionary<string, Func<long, long, DateTime, string>>> _slotTempMap = new();
public SysSerialService(SqlSugarRepository<SysSerial> sysSerialRep,
SysCacheService sysCacheService, ISqlSugarClient db,
UserManager userManager)
@ -67,6 +74,8 @@ public class SysSerialService : IDynamicApiController, ITransient
[ApiDescriptionSettings(Name = "Add"), HttpPost]
public async Task<long> Add(AddSerialInput input)
{
var typeList = GetTypeList();
if (typeList.All(u => u.Value != input.Type)) throw Oops.Oh(ErrorCodeEnum.S0007, input.Type);
if (await _sysSerialRep.IsAnyAsync(u => u.Type == input.Type && u.TenantId == _userManager.TenantId)) throw Oops.Oh(ErrorCodeEnum.D1006);
var entity = input.Adapt<SysSerial>();
@ -84,6 +93,8 @@ public class SysSerialService : IDynamicApiController, ITransient
[ApiDescriptionSettings(Name = "Update"), HttpPost]
public async Task Update(UpdateSerialInput input)
{
var typeList = GetTypeList();
if (typeList.All(u => u.Value != input.Type)) throw Oops.Oh(ErrorCodeEnum.S0007, input.Type);
var seq = await _sysSerialRep.GetFirstAsync(u => u.Id == input.Id) ?? throw Oops.Oh(ErrorCodeEnum.D1002);
if (await _sysSerialRep.IsAnyAsync(u => u.Type == input.Type && u.TenantId == _userManager.TenantId && input.Id != seq.Id)) throw Oops.Oh(ErrorCodeEnum.D1006);
@ -116,6 +127,24 @@ public class SysSerialService : IDynamicApiController, ITransient
await _sysSerialRep.AsUpdateable().SetColumns(u => u.Status, input.Status).Where(u => u.Id == input.Id).ExecuteCommandAsync();
}
/// <summary>
/// 获取流水号类型
/// </summary>
/// <returns></returns>
[DisplayName("获取流水号类型"), HttpGet]
public List<SelectListItem> GetTypeList()
{
return _sysCacheService.GetOrAdd(CacheConst.KeySysSerialType, _ =>
{
return App.EffectiveTypes
.Where(u => !u.IsInterface && u.IsClass && u.HasImplementedRawGeneric(typeof(ISysSerialTypeProvider)))
.SelectMany(u => u.GetFields())
.DistinctBy(u => u.Name)
.Select(u => new SelectListItem(u.GetCustomAttribute<DescriptionAttribute>()?.Description ?? u.Name, u.Name))
.ToList();
});
}
/// <summary>
/// 获取流水号
/// </summary>
@ -169,7 +198,7 @@ public class SysSerialService : IDynamicApiController, ITransient
/// <param name="isTran">是否开启事务</param>
/// <returns></returns>
[NonAction]
public async Task<string> NextSeqNo(SerialTypeEnum? type, bool isGlobal = false, bool isTran = true)
public async Task<string> NextSeqNo(string type, bool isGlobal = false, bool isTran = true)
{
// 获取租户Id, 以及分布式锁缓存键名
long? tenantId = isGlobal ? SqlSugarConst.DefaultTenantId : _userManager.TenantId;
@ -279,18 +308,50 @@ public class SysSerialService : IDynamicApiController, ITransient
[NonAction]
private Dictionary<string, Func<string>> GetSlotMap(long seq, long max, DateTime nowDate)
{
// 使用 "插槽名 - 代理方法" 映射表,这样匹配到的插槽才渲染,减少不必要的运算
return new Dictionary<string, Func<string>>
// 获取插槽逻辑模板
var slotLogic = _slotTempMap.GetOrAdd(CacheConst.KeySysSerialSlot, _ =>
{
["{yyyy}"] = () => nowDate.Year.ToString(),
["{yy}"] = () => nowDate.Year.ToString()[2..],
["{MM}"] = () => nowDate.Month.ToString("D2"),
["{dd}"] = () => nowDate.Day.ToString("D2"),
["{HH}"] = () => nowDate.Hour.ToString("D2"),
["{mm}"] = () => nowDate.Minute.ToString("D2"),
["{ss}"] = () => nowDate.Second.ToString("D2"),
["{SEQ}"] = () => seq.ToString("D" + max.ToString().Length),
["{TenantId}"] = () => _userManager.TenantId.ToString(),
};
// 默认插槽逻辑
var logicMap = new Dictionary<string, Func<long, long, DateTime, string>>
{
// 序号格式化
["{SEQ}"] = (s, m, d) => s.ToString($"D{m.ToString().Length}"),
// 时间相关(依赖 nowDate
["{yyyy}"] = (_, _, d) => d.Year.ToString(),
["{yy}"] = (_, _, d) => d.Year.ToString().Substring(2),
["{MM}"] = (_, _, d) => d.Month.ToString("D2"),
["{dd}"] = (_, _, d) => d.Day.ToString("D2"),
["{HH}"] = (_, _, d) => d.Hour.ToString("D2"),
["{mm}"] = (_, _, d) => d.Minute.ToString("D2"),
["{ss}"] = (_, _, d) => d.Second.ToString("D2"),
["{TenantId}"] = (_, _, d) => _userManager?.TenantId.ToString(),
["{UserId}"] = (_, _, d) => _userManager?.UserId.ToString(),
["{OrgId}"] = (_, _, d) => _userManager?.OrgId.ToString(),
["{OrgType}"] = (_, _, d) => _userManager?.OrgType,
};
// 扩展插槽提供者
var providers = App.EffectiveTypes
.Where(u => !u.IsInterface && u.IsClass && u.HasImplementedRawGeneric(typeof(ISysSerialSlotProvider)))
.Select(u => (ISysSerialSlotProvider)Activator.CreateInstance(u))
.ToList();
foreach (var provider in providers)
{
var providerLogic = provider.GetSlotMap();
foreach (var kv in providerLogic) logicMap[kv.Key] = kv.Value;
}
logicMap.TryAdd("{TenantId}", (_, _, _) => _userManager.TenantId.ToString());
logicMap.TryAdd("{UserId}", (_, _, _) => _userManager.UserId.ToString());
logicMap.TryAdd("{OrgId}", (_, _, _) => _userManager.OrgId.ToString());
logicMap.TryAdd("{OrgType}", (_, _, _) => _userManager.OrgType);
return logicMap;
});
// 将逻辑模板绑定到当前参数,生成最终的 Func<string>
var result = new Dictionary<string, Func<string>>();
foreach (var kv in slotLogic) result.TryAdd(kv.Key, () => kv.Value(seq, max, nowDate));
return result;
}
}

View File

@ -19,6 +19,7 @@ import { Configuration } from '../configuration';
import { BASE_PATH, COLLECTION_FORMATS, RequestArgs, BaseAPI, RequiredError } from '../base';
import { AddSerialInput } from '../models';
import { AdminNETResultInt64 } from '../models';
import { AdminNETResultListSelectListItem } from '../models';
import { AdminNETResultListString } from '../models';
import { AdminNETResultSqlSugarPagedListPageSerialOutput } from '../models';
import { AdminNETResultString } from '../models';
@ -466,6 +467,49 @@ export const SysSerialApiAxiosParamCreator = function (configuration?: Configura
options: localVarRequestOptions,
};
},
/**
*
* @summary
* @param {*} [options] Override http request option.
* @throws {RequiredError}
*/
apiSysSerialTypeListGet: async (options: AxiosRequestConfig = {}): Promise<RequestArgs> => {
const localVarPath = `/api/sysSerial/typeList`;
// use dummy base URL string because the URL constructor only accepts absolute URLs.
const localVarUrlObj = new URL(localVarPath, 'https://example.com');
let baseOptions;
if (configuration) {
baseOptions = configuration.baseOptions;
}
const localVarRequestOptions :AxiosRequestConfig = { method: 'GET', ...baseOptions, ...options};
const localVarHeaderParameter = {} as any;
const localVarQueryParameter = {} as any;
// authentication Bearer required
// http bearer authentication required
if (configuration && configuration.accessToken) {
const accessToken = typeof configuration.accessToken === 'function'
? await configuration.accessToken()
: await configuration.accessToken;
localVarHeaderParameter["Authorization"] = "Bearer " + accessToken;
}
const query = new URLSearchParams(localVarUrlObj.search);
for (const key in localVarQueryParameter) {
query.set(key, localVarQueryParameter[key]);
}
for (const key in options.params) {
query.set(key, options.params[key]);
}
localVarUrlObj.search = (new URLSearchParams(query)).toString();
let headersFromBaseOptions = baseOptions && baseOptions.headers ? baseOptions.headers : {};
localVarRequestOptions.headers = {...localVarHeaderParameter, ...headersFromBaseOptions, ...options.headers};
return {
url: localVarUrlObj.pathname + localVarUrlObj.search + localVarUrlObj.hash,
options: localVarRequestOptions,
};
},
/**
*
* @summary
@ -648,6 +692,19 @@ export const SysSerialApiFp = function(configuration?: Configuration) {
return axios.request(axiosRequestArgs);
};
},
/**
*
* @summary
* @param {*} [options] Override http request option.
* @throws {RequiredError}
*/
async apiSysSerialTypeListGet(options?: AxiosRequestConfig): Promise<(axios?: AxiosInstance, basePath?: string) => Promise<AxiosResponse<AdminNETResultListSelectListItem>>> {
const localVarAxiosArgs = await SysSerialApiAxiosParamCreator(configuration).apiSysSerialTypeListGet(options);
return (axios: AxiosInstance = globalAxios, basePath: string = BASE_PATH) => {
const axiosRequestArgs :AxiosRequestConfig = {...localVarAxiosArgs.options, url: basePath + localVarAxiosArgs.url};
return axios.request(axiosRequestArgs);
};
},
/**
*
* @summary
@ -760,6 +817,15 @@ export const SysSerialApiFactory = function (configuration?: Configuration, base
async apiSysSerialSlotListGet(options?: AxiosRequestConfig): Promise<AxiosResponse<AdminNETResultListString>> {
return SysSerialApiFp(configuration).apiSysSerialSlotListGet(options).then((request) => request(axios, basePath));
},
/**
*
* @summary
* @param {*} [options] Override http request option.
* @throws {RequiredError}
*/
async apiSysSerialTypeListGet(options?: AxiosRequestConfig): Promise<AxiosResponse<AdminNETResultListSelectListItem>> {
return SysSerialApiFp(configuration).apiSysSerialTypeListGet(options).then((request) => request(axios, basePath));
},
/**
*
* @summary
@ -878,6 +944,16 @@ export class SysSerialApi extends BaseAPI {
public async apiSysSerialSlotListGet(options?: AxiosRequestConfig) : Promise<AxiosResponse<AdminNETResultListString>> {
return SysSerialApiFp(this.configuration).apiSysSerialSlotListGet(options).then((request) => request(this.axios, this.basePath));
}
/**
*
* @summary
* @param {*} [options] Override http request option.
* @throws {RequiredError}
* @memberof SysSerialApi
*/
public async apiSysSerialTypeListGet(options?: AxiosRequestConfig) : Promise<AxiosResponse<AdminNETResultListSelectListItem>> {
return SysSerialApiFp(this.configuration).apiSysSerialTypeListGet(options).then((request) => request(this.axios, this.basePath));
}
/**
*
* @summary

View File

@ -13,7 +13,6 @@
*/
import { ResetIntervalEnum } from './reset-interval-enum';
import { SerialTypeEnum } from './serial-type-enum';
import { StatusEnum } from './status-enum';
/**
*
@ -46,10 +45,12 @@ export interface AddSerialInput {
tenantId?: number | null;
/**
* @type {SerialTypeEnum}
* 使
*
* @type {string}
* @memberof AddSerialInput
*/
type: SerialTypeEnum;
type: string;
/**
* @type {ResetIntervalEnum}

View File

@ -0,0 +1,71 @@
/* tslint:disable */
/* eslint-disable */
/**
* Admin.NET
* .NET <br/><u><b><font color='FF0000'> 👮</font></b></u>
*
* OpenAPI spec version: 1.0.0
*
*
* NOTE: This class is auto generated by the swagger code generator program.
* https://github.com/swagger-api/swagger-codegen.git
* Do not edit the class manually.
*/
import { SelectListItem } from './select-list-item';
/**
*
*
* @export
* @interface AdminNETResultListSelectListItem
*/
export interface AdminNETResultListSelectListItem {
/**
*
*
* @type {number}
* @memberof AdminNETResultListSelectListItem
*/
code?: number;
/**
* successwarningerror
*
* @type {string}
* @memberof AdminNETResultListSelectListItem
*/
type?: string | null;
/**
*
*
* @type {string}
* @memberof AdminNETResultListSelectListItem
*/
message?: string | null;
/**
*
*
* @type {Array<SelectListItem>}
* @memberof AdminNETResultListSelectListItem
*/
result?: Array<SelectListItem> | null;
/**
*
*
* @type {any}
* @memberof AdminNETResultListSelectListItem
*/
extras?: any | null;
/**
*
*
* @type {Date}
* @memberof AdminNETResultListSelectListItem
*/
time?: Date;
}

View File

@ -12,7 +12,6 @@
* Do not edit the class manually.
*/
import { SerialTypeEnum } from './serial-type-enum';
/**
*
*
@ -22,8 +21,10 @@ import { SerialTypeEnum } from './serial-type-enum';
export interface GetNextSeqInput {
/**
* @type {SerialTypeEnum}
* 使
*
* @type {string}
* @memberof GetNextSeqInput
*/
type?: SerialTypeEnum;
type?: string | null;
}

View File

@ -69,6 +69,7 @@ export * from './admin-netresult-list-pos-output';
export * from './admin-netresult-list-report-data-source-output';
export * from './admin-netresult-list-role-output';
export * from './admin-netresult-list-role-table-output';
export * from './admin-netresult-list-select-list-item';
export * from './admin-netresult-list-stat-log-output';
export * from './admin-netresult-list-string';
export * from './admin-netresult-list-sys-code-gen-template';
@ -431,8 +432,9 @@ export * from './schema-serialization-mode';
export * from './search';
export * from './security-rule-set';
export * from './seed-type';
export * from './select-list-group';
export * from './select-list-item';
export * from './send-subscribe-message-input';
export * from './serial-type-enum';
export * from './serialization-format';
export * from './set-nick-name-input';
export * from './signature-input';

View File

@ -14,7 +14,6 @@
import { Filter } from './filter';
import { Search } from './search';
import { SerialTypeEnum } from './serial-type-enum';
import { StatusEnum } from './status-enum';
/**
*
@ -93,10 +92,12 @@ export interface PageSerialInput {
searchKey?: string | null;
/**
* @type {SerialTypeEnum}
* 使
*
* @type {string}
* @memberof PageSerialInput
*/
type?: SerialTypeEnum;
type?: string | null;
/**
* @type {StatusEnum}

View File

@ -13,7 +13,6 @@
*/
import { ResetIntervalEnum } from './reset-interval-enum';
import { SerialTypeEnum } from './serial-type-enum';
import { StatusEnum } from './status-enum';
/**
*
@ -48,10 +47,12 @@ export interface PageSerialOutput {
expy?: Date | null;
/**
* @type {SerialTypeEnum}
* 使
*
* @type {string}
* @memberof PageSerialOutput
*/
type?: SerialTypeEnum;
type?: string | null;
/**
* @type {ResetIntervalEnum}

View File

@ -12,12 +12,23 @@
* Do not edit the class manually.
*/
/**
* <br />&nbsp; Other = 999<br />
/**
*
*
* @export
* @enum {string}
* @interface SelectListGroup
*/
export enum SerialTypeEnum {
NUMBER_999 = 999
}
export interface SelectListGroup {
/**
* @type {boolean}
* @memberof SelectListGroup
*/
disabled?: boolean;
/**
* @type {string}
* @memberof SelectListGroup
*/
name?: string | null;
}

View File

@ -0,0 +1,53 @@
/* tslint:disable */
/* eslint-disable */
/**
* Admin.NET
* .NET <br/><u><b><font color='FF0000'> 👮</font></b></u>
*
* OpenAPI spec version: 1.0.0
*
*
* NOTE: This class is auto generated by the swagger code generator program.
* https://github.com/swagger-api/swagger-codegen.git
* Do not edit the class manually.
*/
import { SelectListGroup } from './select-list-group';
/**
*
*
* @export
* @interface SelectListItem
*/
export interface SelectListItem {
/**
* @type {boolean}
* @memberof SelectListItem
*/
disabled?: boolean;
/**
* @type {SelectListGroup}
* @memberof SelectListItem
*/
group?: SelectListGroup;
/**
* @type {boolean}
* @memberof SelectListItem
*/
selected?: boolean;
/**
* @type {string}
* @memberof SelectListItem
*/
text?: string | null;
/**
* @type {string}
* @memberof SelectListItem
*/
value?: string | null;
}

View File

@ -13,7 +13,6 @@
*/
import { ResetIntervalEnum } from './reset-interval-enum';
import { SerialTypeEnum } from './serial-type-enum';
import { StatusEnum } from './status-enum';
/**
*
@ -56,10 +55,12 @@ export interface SysSerial {
expy: Date;
/**
* @type {SerialTypeEnum}
* 使
*
* @type {string}
* @memberof SysSerial
*/
type: SerialTypeEnum;
type: string;
/**
* @type {ResetIntervalEnum}

View File

@ -13,7 +13,6 @@
*/
import { ResetIntervalEnum } from './reset-interval-enum';
import { SerialTypeEnum } from './serial-type-enum';
import { StatusEnum } from './status-enum';
/**
*
@ -48,10 +47,12 @@ export interface UpdateSerialInput {
seq: number;
/**
* @type {SerialTypeEnum}
* 使
*
* @type {string}
* @memberof UpdateSerialInput
*/
type: SerialTypeEnum;
type: string;
/**
* @type {ResetIntervalEnum}

View File

@ -16,7 +16,9 @@
</el-col>
<el-col :xs="24" :sm="12" :md="12" :lg="12" :xl="12" class="mb20">
<el-form-item label="使用分类" prop="type">
<g-sys-dict v-model="state.ruleForm.type" :code="'SerialTypeEnum'" render-as="select" clearable />
<el-select v-model="state.ruleForm.type" placeholder="分类">
<el-option v-for="item in state.typeData" :key="item.value" :label="item.text" :value="item.value" />
</el-select>
</el-form-item>
</el-col>
@ -98,6 +100,7 @@ const state = reactive({
loading: false,
showDialog: false,
previewSeqNo: '',
typeData: [] as any[],
slotList: [] as any[],
ruleForm: {} as UpdateSerialInput,
});
@ -119,8 +122,10 @@ onMounted(async () => {
});
//
const openDialog = async (row: any) => {
const openDialog = async (row: any, typeData: any[]) => {
state.ruleForm = JSON.parse(JSON.stringify(row));
state.ruleForm.formater ??= '';
state.typeData = typeData;
state.showDialog = true;
ruleFormRef.value?.resetFields();
};

View File

@ -5,7 +5,9 @@
<el-row :gutter="10">
<el-col class="mb5" :sm="12" :md="8" :lg="6" :xl="6">
<el-form-item label="分类" prop="type">
<g-sys-dict v-model="state.queryParams.type" :code="'SerialTypeEnum'" render-as="select" clearable @keyup.enter.native="handleQuery(false)" />
<el-select v-model="state.queryParams.type" placeholder="分类" clearable @keyup.enter.native="handleQuery(false)">
<el-option v-for="item in state.typeData" :key="item.value" :label="item.text" :value="item.value" />
</el-select>
</el-form-item>
</el-col>
<el-col class="mb5" :sm="12" :md="8" :lg="6" :xl="6">
@ -38,7 +40,7 @@
{{ commonFun.dateFormatYMDHMS(row, $index, row.expy) }}
</template>
<template #row_type="{ row, $index }">
<g-sys-dict v-model="row.type" :code="'SerialTypeEnum'" />
<el-tag v-for="item in state.typeData" v-show="item.value === row.type">{{ item.text }}</el-tag>
</template>
<template #row_resetInterval="{ row, $index }">
<g-sys-dict v-model="row.resetInterval" :code="'ResetIntervalEnum'" />
@ -86,6 +88,7 @@ const state = reactive({
pageSize: 20 as number,
defaultSort: { field: 'id', order: 'asc', descStr: 'desc' },
},
typeData: [] as any[],
visible: false,
title: '',
});
@ -99,14 +102,14 @@ const options = useVxeTable<PageSerialOutput>(
name: '流水号',
columns: [
// { type: 'checkbox', width: 40, fixed: 'left' },
// { field: 'seq', type: 'seq', title: '', width: 60, fixed: 'left' },
{ field: 'seq', title: '序列号', minWidth: 80, showOverflow: 'tooltip' },
{ field: 'expy', title: '有效期', minWidth: 150, showOverflow: 'tooltip', slots: { default: 'row_expy' } },
{ field: 'seq', type: 'seq', title: '序号', width: 60, fixed: 'left' },
{ field: 'type', title: '分类', minWidth: 150, showOverflow: 'tooltip', slots: { default: 'row_type' } },
{ field: 'resetInterval', title: '重置间隔', minWidth: 120, showOverflow: 'tooltip', slots: { default: 'row_resetInterval' } },
{ field: 'formater', title: '表达式', minWidth: 220, showOverflow: 'tooltip' },
{ field: 'seq', title: '当前序列号', minWidth: 80, showOverflow: 'tooltip' },
{ field: 'min', title: '最小值', minWidth: 80, showOverflow: 'tooltip' },
{ field: 'max', title: '最大值', minWidth: 150, showOverflow: 'tooltip' },
{ field: 'expy', title: '有效期', minWidth: 150, showOverflow: 'tooltip', slots: { default: 'row_expy' } },
{ field: 'orderNo', title: '排序', minWidth: 100, sortable: true, showOverflow: 'tooltip' },
{ field: 'status', title: '状态', minWidth: 100, showOverflow: 'tooltip', slots: { default: 'row_status' } },
{ field: 'remark', title: '备注', minWidth: 150, showOverflow: 'tooltip' },
@ -132,6 +135,7 @@ const options = useVxeTable<PageSerialOutput>(
//
onMounted(async () => {
state.localPageParam = Local.get(localPageParamKey) || state.localPageParam;
state.typeData = await getAPI(SysSerialApi).apiSysSerialTypeListGet().then(res => res.data.result ?? []);
handleQuery(true);
});
@ -158,13 +162,13 @@ const resetQuery = async () => {
//
const handleAdd = () => {
state.title = '添加流水号'; // i18n.t('message.list.addPosition');
editSerialRef.value?.openDialog({ type: 999, resetInterval: 1, min: 1, max: 99999999, status: 1, orderNo: 100 });
editSerialRef.value?.openDialog({ resetInterval: 1, min: 1, max: 99999999, status: 1, orderNo: 100 }, state.typeData);
};
//
const handleEdit = async (row: any) => {
state.title = '编辑流水号'; //i18n.t('message.list.editPosition');
editSerialRef.value?.openDialog(row);
editSerialRef.value?.openDialog(row, state.typeData);
};
//