| ¶Ô±ÈÐÂÎļþ |
| | |
| | | using System; |
| | | using System.Collections.Generic; |
| | | using System.Linq; |
| | | using System.Text; |
| | | using System.Text.Json.Serialization; |
| | | using System.Threading.Tasks; |
| | | |
| | | namespace CMS.Plugin.PipeLineLems.Application.Contracts.Dtos.WorkPlan |
| | | { |
| | | public class MesOrderResponse |
| | | { |
| | | [JsonPropertyName("code")] |
| | | public string Code { get; set; } |
| | | |
| | | [JsonPropertyName("data")] |
| | | public object Data { get; set; } |
| | | |
| | | [JsonPropertyName("fail")] |
| | | public bool Fail { get; set; } |
| | | |
| | | [JsonPropertyName("mesg")] |
| | | public string Mesg { get; set; } |
| | | |
| | | [JsonPropertyName("success")] |
| | | public bool Success { get; set; } |
| | | |
| | | [JsonPropertyName("time")] |
| | | public DateTime Time { get; set; } |
| | | } |
| | | } |
| | |
| | | public string TaskCode { get; set; } |
| | | |
| | | /// <summary> |
| | | /// åæç¼å· |
| | | /// </summary> |
| | | public string OrgMaterialCode { get; set; } |
| | | |
| | | |
| | | /// <summary> |
| | | /// å·¥å代ç ï¼çäº§å·¥åæ è¯ï¼ |
| | | /// </summary> |
| | | public string FactoryCode { get; set; } |
| | |
| | | public string PipeFittingCode { get; set; } |
| | | |
| | | /// <summary> |
| | | /// é¢åºå·ï¼é¢å¤çåºåå·ï¼ |
| | | /// 顺åºå·ï¼é¢å¤çåºåå·ï¼ |
| | | /// </summary> |
| | | public string PreSerialNumber { get; set; } |
| | | |
| | | /// <summary> |
| | | /// èµææ è¯ï¼æ°æ®åºåæ è¯ï¼ |
| | | /// åææ è¯ï¼æ°æ®åºåæ è¯ï¼ |
| | | /// </summary> |
| | | public string DataIdentifier { get; set; } |
| | | |
| | |
| | | using CMS.Plugin.PipeLineLems.Application.Contracts.Dtos.MyTestEntityNames; |
| | | using CMS.Plugin.PipeLineLems.Application.Contracts.Dtos.WorkPlan; |
| | | using Volo.Abp.Application.Services; |
| | | |
| | | namespace CMS.Plugin.PipeLineLems.Application.Contracts.Services; |
| | |
| | | /// <summary> |
| | | /// MESåºç¨æå¡ |
| | | /// </summary> |
| | | public interface IMesAppService : ICrudAppService<MyTestEntityNameDto, Guid, GetMyTestEntityNamesInput, MyTestEntityNameCreateDto, MyTestEntityNameUpdateDto> |
| | | public interface IMesAppService |
| | | { |
| | | /// <summary> |
| | | /// Clones the asynchronous. |
| | | /// </summary> |
| | | /// <param name="ids">The ids.</param> |
| | | /// <returns></returns> |
| | | Task<List<MyTestEntityNameDto>> CloneAsync(IEnumerable<Guid> ids); |
| | | |
| | | |
| | | Task<MesOrderResponse> CreateAsync(List<WorkPlanInput> input); |
| | | } |
| | |
| | | using CMS.Plugin.FormulaManagement.Abstractions; |
| | | using CMS.Plugin.MesSuite.Abstractions.Events; |
| | | using CMS.Plugin.OrderManagement.Abstractions.Enums; |
| | | using CMS.Plugin.OrderManagement.Abstractions.Models; |
| | | using CMS.Plugin.OrderManagement.Abstractions; |
| | | using CMS.Plugin.PipeLineLems.Application.Contracts.Dtos.MyTestEntityNames; |
| | | using CMS.Plugin.PipeLineLems.Application.Contracts.Services; |
| | | using CMS.Plugin.PipeLineLems.Domain.MyTestEntityNames; |
| | | using CMS.Plugin.PipeLineLems.Domain.Shared; |
| | | using CMS.Plugin.PipeLineLems.Domain.Shared.MyTestEntityNames; |
| | | using CMS.Plugin.ProductManagement.Abstractions; |
| | | using Microsoft.Extensions.DependencyInjection; |
| | | using Volo.Abp; |
| | | using Volo.Abp.Application.Dtos; |
| | | using Volo.Abp.Data; |
| | | using Volo.Abp.ObjectExtending; |
| | | using CMS.Plugin.PipeLineLems.Application.Contracts.Dtos.WorkPlan; |
| | | using Volo.Abp.EventBus; |
| | | |
| | | namespace CMS.Plugin.PipeLineLems.Application.Implements; |
| | | |
| | | /// <inheritdoc /> |
| | | public class MesAppService : CMSPluginAppService, IMesAppService |
| | | public class MesAppService : IMesAppService |
| | | { |
| | | private readonly IMyTestEntityNameRepository _mytestentitynameRepository; |
| | | private readonly IServiceProvider _serviceProvider; |
| | | |
| | | /// <summary> |
| | | /// Initializes a new instance of the <see cref="MyTestEntityNameAppService"/> class. |
| | | /// </summary> |
| | | /// <param name="mytestentitynameRepository">The task job repository.</param> |
| | | public MesAppService(IMyTestEntityNameRepository mytestentitynameRepository) |
| | | //private readonly IEventBus _eventBus; |
| | | |
| | | public MesAppService(IServiceProvider serviceProvider |
| | | //, IEventBus eventBus |
| | | ) |
| | | { |
| | | _mytestentitynameRepository = mytestentitynameRepository; |
| | | _serviceProvider = serviceProvider; |
| | | // _eventBus = eventBus; |
| | | } |
| | | |
| | | /// <inheritdoc /> |
| | | public virtual async Task<MyTestEntityNameDto> GetAsync(Guid id) |
| | | public async Task<MesOrderResponse> CreateAsync(List<WorkPlanInput> input) |
| | | { |
| | | return ObjectMapper.Map<MyTestEntityName, MyTestEntityNameDto>(await _mytestentitynameRepository.GetAsync(id)); |
| | | } |
| | | |
| | | /// <inheritdoc /> |
| | | public virtual async Task<PagedResultDto<MyTestEntityNameDto>> GetListAsync(GetMyTestEntityNamesInput input) |
| | | { |
| | | Check.NotNull(input, nameof(input)); |
| | | |
| | | if (input.Sorting.IsNullOrWhiteSpace()) |
| | | if (input == null) |
| | | { |
| | | input.Sorting = nameof(MyTestEntityName.Sort); |
| | | throw new UserFriendlyException("è¾å
¥åæ°ä¸è½ä¸ºç©º"); |
| | | } |
| | | |
| | | var specification = new MyTestEntityNameSpecification(input.Name); |
| | | var count = await _mytestentitynameRepository.GetCountAsync(input.Filter, specification); |
| | | var list = await _mytestentitynameRepository.GetListAsync(input.Sorting, input.MaxResultCount, input.SkipCount, input.Filter, specification); |
| | | |
| | | return new PagedResultDto<MyTestEntityNameDto>(count, ObjectMapper.Map<List<MyTestEntityName>, List<MyTestEntityNameDto>>(list)); |
| | | } |
| | | |
| | | /// <inheritdoc /> |
| | | public virtual async Task<MyTestEntityNameDto> CreateAsync(MyTestEntityNameCreateDto input) |
| | | { |
| | | await CheckCreateOrUpdateDtoAsync(input); |
| | | |
| | | var exist = await _mytestentitynameRepository.NameExistAsync(input.Name); |
| | | if (exist) |
| | | if (input.Count == 0) |
| | | { |
| | | throw new UserFriendlyException(L[CMSPluginDomainErrorCodes.NameAlreadyExists, input.Name]); |
| | | throw new UserFriendlyException("è¾å
¥åæ°Dataä¸è½ä¸ºç©º"); |
| | | } |
| | | |
| | | var maxSort = await _mytestentitynameRepository.GetMaxSortAsync(); |
| | | var sort = input.Sort ?? maxSort; |
| | | var mytestentityname = new MyTestEntityName(GuidGenerator.Create(), input.Code, input.Name, sort, input.Remark); |
| | | input.MapExtraPropertiesTo(mytestentityname, MappingPropertyDefinitionChecks.None); |
| | | |
| | | await _mytestentitynameRepository.InsertAsync(mytestentityname); |
| | | |
| | | if (input.Sort.HasValue && mytestentityname.Sort != maxSort) |
| | | var orderManager = _serviceProvider.GetRequiredService<IOrderManager>(); |
| | | var productProvider = _serviceProvider.GetRequiredService<IProductProvider>(); |
| | | var formulaProvider = _serviceProvider.GetRequiredService<IFormulaProvider>(); |
| | | List<OrderModel> orderModels = new List<OrderModel>(); |
| | | //æç
§ä»»å¡ç¼å·åç» |
| | | var groupTask = input.GroupBy(x => x.TaskCode); |
| | | foreach (var gTask in groupTask) |
| | | { |
| | | await AdjustSortAsync(mytestentityname.Id, mytestentityname.Sort); |
| | | } |
| | | |
| | | return ObjectMapper.Map<MyTestEntityName, MyTestEntityNameDto>(mytestentityname); |
| | | } |
| | | |
| | | /// <inheritdoc /> |
| | | public virtual async Task<MyTestEntityNameDto> UpdateAsync(Guid id, MyTestEntityNameUpdateDto input) |
| | | { |
| | | await CheckCreateOrUpdateDtoAsync(input); |
| | | |
| | | var mytestentityname = await _mytestentitynameRepository.GetAsync(id); |
| | | var exist = await _mytestentitynameRepository.NameExistAsync(input.Name, mytestentityname.Id); |
| | | if (exist) |
| | | { |
| | | throw new UserFriendlyException(L[CMSPluginDomainErrorCodes.NameAlreadyExists, input.Name]); |
| | | } |
| | | |
| | | mytestentityname.SetConcurrencyStampIfNotNull(input.ConcurrencyStamp); |
| | | input.MapExtraPropertiesTo(mytestentityname, MappingPropertyDefinitionChecks.None); |
| | | |
| | | mytestentityname.Update(input.Code, input.Name, input.Remark); |
| | | |
| | | await _mytestentitynameRepository.UpdateAsync(mytestentityname); |
| | | |
| | | return ObjectMapper.Map<MyTestEntityName, MyTestEntityNameDto>(mytestentityname); |
| | | } |
| | | |
| | | /// <inheritdoc /> |
| | | public async Task<List<MyTestEntityNameDto>> CloneAsync(IEnumerable<Guid> ids) |
| | | { |
| | | var mytestentitynames = new List<MyTestEntityName>(); |
| | | if (ids != null) |
| | | { |
| | | var sort = await _mytestentitynameRepository.GetMaxSortAsync(); |
| | | foreach (var id in ids) |
| | | var taskCode = gTask.Key; |
| | | var order = await orderManager.GetByCodeAsync(taskCode); |
| | | if (order != null) |
| | | { |
| | | var mytestentityname = await _mytestentitynameRepository.FindAsync(id); |
| | | if (mytestentityname != null) |
| | | { |
| | | var name = mytestentityname.Name + MyTestEntityNameConsts.CloneTag; |
| | | var notExist = false; |
| | | while (!notExist) |
| | | { |
| | | var exist = await _mytestentitynameRepository.NameExistAsync(name); |
| | | if (exist || mytestentitynames.Any(x => x.Name == name)) |
| | | { |
| | | name += MyTestEntityNameConsts.CloneTag; |
| | | continue; |
| | | } |
| | | |
| | | notExist = true; |
| | | } |
| | | |
| | | mytestentityname = await _mytestentitynameRepository.InsertAsync(mytestentityname.Clone(GuidGenerator.Create(), name, sort++)); |
| | | mytestentitynames.Add(mytestentityname); |
| | | } |
| | | } |
| | | } |
| | | |
| | | return ObjectMapper.Map<List<MyTestEntityName>, List<MyTestEntityNameDto>>(mytestentitynames); |
| | | } |
| | | |
| | | /// <inheritdoc /> |
| | | public virtual Task DeleteAsync(Guid id) |
| | | { |
| | | return _mytestentitynameRepository.DeleteAsync(id); |
| | | } |
| | | |
| | | /// <inheritdoc /> |
| | | public async Task DeleteManyAsync(IEnumerable<Guid> ids) |
| | | { |
| | | foreach (var id in ids) |
| | | { |
| | | await DeleteAsync(id); |
| | | } |
| | | } |
| | | |
| | | /// <inheritdoc /> |
| | | public virtual async Task AdjustSortAsync(Guid id, int sort) |
| | | { |
| | | var list = await _mytestentitynameRepository.GetListAsync(nameof(MyTestEntityName.Sort)); |
| | | if (list != null && list.Any()) |
| | | { |
| | | var initSort = 1; |
| | | list.ForEach(x => x.AdjustSort(initSort++)); |
| | | var entity = list.FirstOrDefault(x => x.Id == id); |
| | | if (entity != null) |
| | | { |
| | | if (sort == 1) |
| | | { |
| | | list.Where(x => x.Id != id).ToList()?.ForEach(x => x.AdjustSort(x.Sort + 1)); |
| | | } |
| | | else if (entity.Sort > sort) |
| | | { |
| | | list.Where(x => x.Id != id && x.Sort >= sort).ToList()?.ForEach(x => x.AdjustSort(x.Sort + 1)); |
| | | list.Where(x => x.Id != id && x.Sort < sort).ToList()?.ForEach(x => x.AdjustSort(x.Sort - 1)); |
| | | } |
| | | else if (entity.Sort < sort) |
| | | { |
| | | list.Where(x => x.Id != id && x.Sort > sort).ToList()?.ForEach(x => x.AdjustSort(x.Sort + 1)); |
| | | list.Where(x => x.Id != id && x.Sort <= sort).ToList()?.ForEach(x => x.AdjustSort(x.Sort - 1)); |
| | | } |
| | | |
| | | entity.AdjustSort(sort); |
| | | } |
| | | } |
| | | |
| | | await _mytestentitynameRepository.UpdateManyAsync(list); |
| | | } |
| | | |
| | | /// <inheritdoc /> |
| | | public async Task ImportAsync(MyTestEntityNamesImportModel input) |
| | | { |
| | | Check.NotNull(input, nameof(input)); |
| | | |
| | | var mytestentitynameCreateDtos = new List<(int RowIndex, MyTestEntityNameCreateDto Item)>(); |
| | | var mytestentitynameUpdateDtos = new List<(int RowIndex, Guid Id, MyTestEntityNameUpdateDto Item)>(); |
| | | var mytestentitynames = input.MyTestEntityNames; |
| | | |
| | | if (mytestentitynames != null && mytestentitynames.Any()) |
| | | { |
| | | #region 导å
¥æ ¡éª |
| | | |
| | | // 夿åç§°æ¯å¦éå¤ï¼å¹¶è¾åºç¬¬å è¡éå¤ |
| | | var duplicateMyTestEntityNames = mytestentitynames.GroupBy(x => x.Name).Where(x => x.Count() > 1).ToList(); |
| | | if (duplicateMyTestEntityNames?.Any() == true) |
| | | { |
| | | var duplicateMyTestEntityNameMsgs = duplicateMyTestEntityNames.Select(x => $"第 {string.Join(",", x.Select(x => x.RowIndex))} è¡ï¼{x.Key} åç§°éå¤"); |
| | | var errorMsg = $"导å
¥å¤±è´¥ï¼é
ç½®ï¼ {string.Join(",", duplicateMyTestEntityNameMsgs)}ï¼ç»æ¢å¯¼å
¥"; |
| | | throw new UserFriendlyException(errorMsg); |
| | | throw new UserFriendlyException($"å·¥å[{taskCode}]å·²åå¨"); |
| | | } |
| | | |
| | | #endregion |
| | | |
| | | foreach (var mytestentityname in mytestentitynames) |
| | | //var product = await productProvider.FindByNameAsync(orderItem.PipeSectionName); |
| | | //if (product == null) |
| | | //{ |
| | | // throw new UserFriendlyException($"产ååç§°[{orderItem.PipeSectionName}]ä¸åå¨"); |
| | | //} |
| | | |
| | | //var formula = await formulaProvider.GetFormulaAsync(product.Id); |
| | | //if (formula == null) |
| | | //{ |
| | | // throw new UserFriendlyException($"产ååå·[{orderItem.MaterialCode}]æ å
³èé
æ¹"); |
| | | //} |
| | | //é¦å
è¦å建 æç åå²çå·¥å |
| | | var productForCut = await productProvider.FindByNameAsync("åå²åæç®¡"); |
| | | if (productForCut == null) |
| | | { |
| | | if (mytestentityname.Code.IsNullOrWhiteSpace() && mytestentityname.Name.IsNullOrWhiteSpace()) |
| | | throw new UserFriendlyException($"产ååç§°[åå²åæç®¡]ä¸åå¨"); |
| | | } |
| | | var formulaForCut = await formulaProvider.GetFormulaAsync(productForCut.Id); |
| | | if (formulaForCut == null) |
| | | { |
| | | throw new UserFriendlyException($"产ååç§°[åå²åæç®¡]æ å
³èé
æ¹"); |
| | | } |
| | | //åç»æ°æ® |
| | | var group = gTask.ToList().GroupBy(x => x.DataIdentifier); |
| | | foreach (var item in group) |
| | | { |
| | | OrderModel orderModelForCut = new OrderModel() |
| | | { |
| | | continue; |
| | | Id = Guid.NewGuid(), |
| | | Code = "Cut_" + taskCode, |
| | | Source = "APSæ¨é", |
| | | PlanStartTime = gTask.ToList().First().PlannedStartTime, |
| | | PlanFinishTime = gTask.ToList().First().PlannedEndTime, |
| | | PlanQty = (ulong)item.ToList().Count, |
| | | Status = OrderStatus.NotActive, |
| | | Product = new AssociationProductModel() { Id = productForCut.Id, Name = productForCut.Name, Model = productForCut.Model, ShortNumber = productForCut.ShortNumber }, |
| | | Formula = new AssociationFormulaModel() { Id = formulaForCut.Id, Code = formulaForCut.Code, Name = formulaForCut.Name } |
| | | }; |
| | | orderModelForCut.ExtraProperties["OuterDiameter"] = gTask.ToList().First().OuterDiameter;//å¤å¾ |
| | | orderModelForCut.ExtraProperties["Material"] = gTask.ToList().First().Material;//æè´¨ |
| | | orderModelForCut.ExtraProperties["Length"] = gTask.ToList().First().Length;//é¿åº¦ |
| | | |
| | | var orderForCut = await orderManager.GetByCodeAsync(orderModelForCut.Code); |
| | | if (orderForCut != null) |
| | | { |
| | | //throw new UserFriendlyException($"å·¥å[{orderModelForCut.Code}]å·²åå¨"); |
| | | //ä¸åæå¼å¸¸ï¼ç´æ¥è·³è¿ |
| | | break; |
| | | } |
| | | |
| | | if (mytestentityname.Name.IsNullOrWhiteSpace()) |
| | | var orderModelResultForCut = await orderManager.CreateAsync(orderModelForCut); |
| | | if (orderModelResultForCut == null) |
| | | { |
| | | var errorMsg = $"导å
¥å¤±è´¥ï¼é
ç½®ï¼ç¬¬{mytestentityname.RowIndex}è¡ï¼MyTestEntityNameåç§°ä¸è½ä¸ºç©º"; |
| | | throw new UserFriendlyException(errorMsg); |
| | | throw new UserFriendlyException($"å·¥å[{orderModelForCut.Code}]å建失败"); |
| | | } |
| | | orderModels.Add(orderModelResultForCut); |
| | | |
| | | var oldMyTestEntityName = await _mytestentitynameRepository.FindByNameAsync(mytestentityname.Name); |
| | | if (oldMyTestEntityName != null) |
| | | { |
| | | var mytestentitynameUpdateDto = new MyTestEntityNameUpdateDto |
| | | { |
| | | Code = mytestentityname.Code, |
| | | Name = mytestentityname.Name, |
| | | Remark = mytestentityname.Remark, |
| | | }; |
| | | |
| | | mytestentitynameUpdateDtos.Add((mytestentityname.RowIndex, oldMyTestEntityName.Id, mytestentitynameUpdateDto)); |
| | | } |
| | | else |
| | | { |
| | | var mytestentitynameCreateDto = new MyTestEntityNameCreateDto |
| | | { |
| | | Code = mytestentityname.Code, |
| | | Name = mytestentityname.Name, |
| | | Remark = mytestentityname.Remark, |
| | | }; |
| | | |
| | | mytestentitynameCreateDtos.Add((mytestentityname.RowIndex, mytestentitynameCreateDto)); |
| | | } |
| | | //OrderModel orderModel = new OrderModel(); |
| | | //orderModel.Id = Guid.NewGuid(); |
| | | //orderModel.Code = orderItem.TaskCode; |
| | | //orderModel.Source = "APSæ¨é"; |
| | | //orderModel.Product = new AssociationProductModel() { Id = product.Id, Name = product.Name, Model = product.Model, ShortNumber = product.ShortNumber }; |
| | | ////orderModel.Formula = new AssociationFormulaModel() { Id = formula.Id, Code = formula.Code, Name = formula.Name }; |
| | | //orderModel.PlanStartTime = orderItem.PlannedStartTime; |
| | | //orderModel.PlanFinishTime = orderItem.PlannedEndTime; |
| | | //orderModel.PlanQty = (ulong?)orderItem.OrderQty; |
| | | //orderModel.Status = OrderStatus.NotActive; |
| | | //orderModel.ExtraProperties["Source"] = "ddd"; |
| | | //var source = orderModel.ExtraProperties["Source"]; |
| | | //var orderModelResult = await orderManager.CreateAsync(orderModel); |
| | | //if (orderModelResult == null) |
| | | //{ |
| | | // throw new UserFriendlyException($"å·¥å[{orderItem.TaskCode}]å建失败"); |
| | | //} |
| | | //orderModels.Add(orderModelResult); |
| | | } |
| | | |
| | | } |
| | | |
| | | // æ°å¢ |
| | | foreach (var mytestentitynameDto in mytestentitynameCreateDtos) |
| | | // åå¸äºä»¶ |
| | | //await _eventBus.PublishAsync(new EntityChangedEto("MESCREATE", input, null, EntityChangeType.Add, true)); |
| | | |
| | | var response = new MesOrderResponse |
| | | { |
| | | try |
| | | { |
| | | await CreateAsync(mytestentitynameDto.Item); |
| | | } |
| | | catch (Exception e) |
| | | { |
| | | var errorMsg = $"导å
¥å¤±è´¥ï¼é
ç½®ï¼ç¬¬{mytestentitynameDto.RowIndex}è¡ï¼{e.Message}ï¼ç»æ¢å¯¼å
¥"; |
| | | throw new UserFriendlyException(errorMsg); |
| | | } |
| | | } |
| | | |
| | | // æ´æ° |
| | | foreach (var mytestentitynameDto in mytestentitynameUpdateDtos) |
| | | { |
| | | try |
| | | { |
| | | await UpdateAsync(mytestentitynameDto.Id, mytestentitynameDto.Item); |
| | | } |
| | | catch (Exception e) |
| | | { |
| | | var errorMsg = $"导å
¥å¤±è´¥ï¼é
ç½®ï¼ç¬¬{mytestentitynameDto.RowIndex}è¡ï¼{e.Message}ï¼ç»æ¢å¯¼å
¥"; |
| | | throw new UserFriendlyException(errorMsg); |
| | | } |
| | | } |
| | | } |
| | | |
| | | /// <inheritdoc /> |
| | | public async Task<(Dictionary<string, object> Sheets, string FileName)> ExportAsync(GetMyTestEntityNamesInput input) |
| | | { |
| | | Check.NotNull(input, nameof(input)); |
| | | |
| | | if (input.Sorting.IsNullOrWhiteSpace()) |
| | | { |
| | | input.Sorting = nameof(MyTestEntityName.Sort); |
| | | } |
| | | |
| | | var specification = new MyTestEntityNameSpecification(input.Name); |
| | | var list = await _mytestentitynameRepository.GetListAsync(input.Sorting, input.MaxResultCount, input.SkipCount, input.Filter, specification, includeDetails: true); |
| | | var result = ObjectMapper.Map<List<MyTestEntityName>, List<MyTestEntityNameDto>>(list); |
| | | |
| | | var sheets = new Dictionary<string, object> |
| | | { |
| | | ["é
ç½®"] = result.Select(x => x.GetExportData()).ToList(), |
| | | Code = "000000", |
| | | Data = orderModels, |
| | | Fail = false, |
| | | Mesg = "å¤çæå", |
| | | Success = true, |
| | | Time = DateTime.UtcNow |
| | | }; |
| | | |
| | | var fileName = result.Count > 1 ? "MyTestEntityNameå表" : result.Count == 1 ? result.First()?.Name : "MyTestEntityName模ç"; |
| | | return (sheets, fileName); |
| | | } |
| | | |
| | | /// <summary> |
| | | /// Checks the create or update dto asynchronous. |
| | | /// </summary> |
| | | /// <param name="input">The input.</param> |
| | | protected Task CheckCreateOrUpdateDtoAsync(MyTestEntityNameCreateOrUpdateDtoBase input) |
| | | { |
| | | Check.NotNull(input, nameof(input)); |
| | | Check.NotNullOrWhiteSpace(input.Code, "ç¼å·", MyTestEntityNameConsts.MaxCodeLength); |
| | | Check.NotNullOrWhiteSpace(input.Name, "åç§°", MyTestEntityNameConsts.MaxNameLength); |
| | | Check.Length(input.Remark, "夿³¨", MyTestEntityNameConsts.MaxRemarkLength); |
| | | return Task.CompletedTask; |
| | | return response; |
| | | } |
| | | } |
| | |
| | | using Volo.Abp.BackgroundWorkers; |
| | | using Volo.Abp.DependencyInjection; |
| | | using Volo.Abp.Modularity.PlugIns; |
| | | using CMS.Plugin.PipeLineLems.Application.Contracts.Services; |
| | | using CMS.Plugin.PipeLineLems.Application.Implements; |
| | | |
| | | namespace CMS.Plugin.PipeLineLems; |
| | | |
| | |
| | | context.Services.AddScoped<IProjectRuntimeMigrator, CMSPluginRuntimeMigrator>(); |
| | | context.Services.AddSingleton<IProjectService, PipeLineLemsProjectService>(); |
| | | |
| | | context.Services.AddScoped<IMesAppService, MesAppService>(); |
| | | |
| | | context.Services.AddScoped<IEFDataProvider>(p => |
| | | { |
| | | var cfg = p.GetRequiredService<IDataRuntimeConfig>(); |
| | |
| | | using CMS.Extensions.Abp.AspNetCore.Mvc.Filters; |
| | | using CMS.Plugin.PipeLineLems.Application.Contracts.Dtos.WorkPlan; |
| | | using CMS.Plugin.PipeLineLems.Application.Contracts.Services; |
| | | using Microsoft.AspNetCore.Mvc; |
| | | using System.Reflection; |
| | | |
| | |
| | | public class WorkPlanController : ControllerBase |
| | | { |
| | | |
| | | |
| | | private readonly IMesAppService _mesAppService; |
| | | /// <summary> |
| | | /// Initializes a new instance of the <see cref="TestEntityNameController"/> class. |
| | | /// </summary> |
| | | /// <param name="testentitynameAppService">The testentityname application service.</param> |
| | | public WorkPlanController() |
| | | public WorkPlanController(IMesAppService mesAppService) |
| | | { |
| | | |
| | | _mesAppService = mesAppService; |
| | | } |
| | | |
| | | /// <summary> |
| | |
| | | /// </summary> |
| | | /// <param name="input">æ è¯ç¬¦.</param> |
| | | /// <returns></returns> |
| | | [HttpGet] |
| | | public virtual Task GetWorkPlanAsync([FromQuery] List<WorkPlanInput> input) |
| | | [HttpPost] |
| | | public virtual async Task<MesOrderResponse> GetWorkPlanAsync([FromBody] List<WorkPlanInput> input) |
| | | { |
| | | // å
é¨ä¸å¡é»è¾ææ¶ä¸ºç©º |
| | | return null; |
| | | return await _mesAppService.CreateAsync(input); |
| | | } |
| | | |
| | | |
| | |
| | | VITE_APP_TITLE= CMS |
| | | |
| | | VITE_API_URL = 'http://192.168.5.94:18000' # å¼åç-è²èª |
| | | |
| | | # productionåªè½è®¾ç½®ä¸ºç©ºï¼éæhostèµæºæå¡å°å |
| | | VITE_STATIC_URL='' |
| | | |
| | | VITE_PROJECT_API_URL='http://127.0.0.1:8800' |
| | | |
| | |
| | | |
| | | VITE_APP_NAMESPACE= 'cs' |
| | | |
| | | # VITE_API_URL = 'http://192.168.2.13:18000' |
| | | VITE_API_URL = 'http://192.168.1.18:18000' |
| | | VITE_API_URL = 'http://localhost:18000' |
| | | |
| | | VITE_PROJECT_API_URL='http://127.0.0.1:8800' |
| | | VITE_STATIC_URL = 'http://192.168.2.206:18000' |
| | | # VITE_APP_PROJECT_ID = 2 |
| | |
| | | |
| | | VITE_APP_NAMESPACE= 'cs' |
| | | |
| | | VITE_APP_VERSION = 'beta-9' |
| | | VITE_APP_VERSION = '2.0.0-release' |
| | | |
| | | # productionåªè½è®¾ç½®ä¸ºç©ºï¼éæhostèµæºæå¡å°å |
| | | VITE_STATIC_URL='' |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | # Logs |
| | | logs |
| | | *.log |
| | | npm-debug.log* |
| | | yarn-debug.log* |
| | | yarn-error.log* |
| | | pnpm-debug.log* |
| | | lerna-debug.log* |
| | | |
| | | node_modules |
| | | .DS_Store |
| | | dist |
| | | dist-ssr |
| | | coverage |
| | | *.local |
| | | auto-imports.d.ts |
| | | components.d.ts |
| | | /cypress/videos/ |
| | | /cypress/screenshots/ |
| | | |
| | | # Editor directories and files |
| | | .vscode/* |
| | | !.vscode/extensions.json |
| | | .idea |
| | | *.suo |
| | | *.ntvs* |
| | | *.njsproj |
| | | *.sln |
| | | *.sw? |
| | | |
| | | /widgets |
| | | *.ts.timestamp* |
| | | wwwroot |
| | | src/config/menu.ts |
| | | cms_back |
| | | rust/target |
| | | .argv |
| | | docs/.vitepress/cache |
| | | publish |
| | | information-ui |
| | | widgets_bak |
| | | src/widgets/**/* |
| | | src/widgets |
| | | .build.local |
| | | *.zip |
| | | src/assets/**/* |
| | | src/assets |
| | | |
| | | cross-env/* |
| | | rust |
| | | app/tmp/* |
| | | app/build/www |
| | | app/build/www.exe |
| | | |
| | |
| | | # information-standard-tpl |
| | | # information-standard |
| | | |
| | | ## å®è£
ç¯å¢ |
| | | |
| | | å®è£
[nodeJs](https://nodejs.cn/)ç¯å¢,ä¸è½½ nodejsï¼å®è£
宿åï¼ |
| | | |
| | | ```js |
| | | node - v |
| | | ``` |
| | | |
| | | ## å®è£
yarn |
| | | |
| | | ```js |
| | | npm install -g yarn |
| | | ``` |
| | | |
| | | ## å®è£
ä¾èµ |
| | | ## å®è£
|
| | | |
| | | ```js |
| | | yarn |
| | |
| | | |------hook.ts //é©å |
| | | |------... |
| | | index.html |
| | | ``` |
| | | |
| | | ## å¿«éå¼å§ |
| | | |
| | | ### å¼åå为主ä»åºåºåº§ï¼ information-base åæ åç»ä»¶åå®å¶åç»ä»¶ |
| | | |
| | | å¼åæµç¨ä¸ºï¼ |
| | | |
| | | #### 1ãæååºåº§ä»åº |
| | | |
| | | ```bash |
| | | git clone https://gitlab.syc-cms.com/lmes-plugin/web/information-base.git |
| | | ``` |
| | | |
| | | #### 2ãæååä»åºç»ä»¶ |
| | | |
| | | ```bash |
| | | yarn pull |
| | | ``` |
| | | |
| | | #### 3ãæéè¦æ¯å¦å°ææç»ä»¶åæ¢å°æå®åæ¯ |
| | | |
| | | ``` |
| | | yarn checkout ã忝åã |
| | | ``` |
| | | |
| | | ## åè½ |
| | |
| | | onClick={onAddProcess} |
| | | type="primary" |
| | | > |
| | | æ·»å MyEntityName |
| | | æ·»å å·¥åº |
| | | </IconButton> |
| | | |
| | | ``` |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | #!/bin/bash |
| | | |
| | | GOOS=darwin GOARCH=amd64 go build -ldflags "-s -w" -o ./build/www main.go |
| | | # GOOS=darwin GOARCH=arm64 go build -ldflags "-s -w" -o ./build/www_arm main.go |
| | | GOOS=windows GOARCH=amd64 go build -ldflags "-s -w" -o ./build/www.exe main.go |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | registry=https://registry.npmjs.org/ |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | { |
| | | "name": "lmes-create-widget", |
| | | "version": "1.0.3", |
| | | "main": "./www", |
| | | "scripts": { |
| | | "test": "echo \"Error: no test specified\" && exit 1" |
| | | }, |
| | | "author": "", |
| | | "license": "ISC", |
| | | "description": "" |
| | | } |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | package controllers |
| | | |
| | | import ( |
| | | "app/dto" |
| | | "app/service" |
| | | "app/utils" |
| | | "net/http" |
| | | "os" |
| | | "path/filepath" |
| | | |
| | | "github.com/gin-gonic/gin" |
| | | ) |
| | | |
| | | // HomeHandler å¤çé¦é¡µè¯·æ± |
| | | func HomeHandler(c *gin.Context) { |
| | | c.JSON(http.StatusOK, gin.H{ |
| | | "message": "Hello, World!", |
| | | }) |
| | | } |
| | | |
| | | /** |
| | | * 读åæä»¶ |
| | | **/ |
| | | func FileHandler(c *gin.Context) { |
| | | query := c.Request.URL.Query() |
| | | absPath, err := filepath.Abs("../" + query.Get("name")) |
| | | if err != nil { |
| | | c.JSON(http.StatusOK, gin.H{ |
| | | "message": err, |
| | | }) |
| | | } else { |
| | | path := filepath.ToSlash(absPath) |
| | | envLocal, err := os.ReadFile(path) |
| | | if err != nil { |
| | | c.JSON(http.StatusOK, gin.H{ |
| | | "message": err, |
| | | }) |
| | | } else { |
| | | c.JSON(http.StatusOK, gin.H{ |
| | | "data": string(envLocal), |
| | | }) |
| | | } |
| | | } |
| | | } |
| | | |
| | | // å建ç»ä»¶ |
| | | func CreateWidget(c *gin.Context) { |
| | | var body dto.RequestBody |
| | | err := c.ShouldBindJSON(&body) |
| | | if err != nil { |
| | | utils.HandlerErr(c, err) |
| | | return |
| | | } |
| | | service.CreateService(c, body) |
| | | |
| | | } |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | package dto |
| | | |
| | | type RequestBody struct { |
| | | WidgetName string `json:"widgetName"` |
| | | WidgetId string `json:"widgetId"` |
| | | Menu []map[string]interface{} `json:"menu"` |
| | | MenuMap map[string]map[string]interface{} `json:"menuMap"` |
| | | Type int `json:"type"` |
| | | } |
| | | |
| | | type MenuConfig struct { |
| | | Menu []map[string]interface{} |
| | | MenuMap map[string]map[string]interface{} |
| | | } |
| | | |
| | | type ErrorType struct { |
| | | string |
| | | int |
| | | error |
| | | } |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | module app |
| | | |
| | | go 1.23.0 |
| | | |
| | | require github.com/gin-gonic/gin v1.10.0 |
| | | |
| | | require ( |
| | | github.com/bytedance/sonic v1.11.6 // indirect |
| | | github.com/bytedance/sonic/loader v0.1.1 // indirect |
| | | github.com/cloudwego/base64x v0.1.4 // indirect |
| | | github.com/cloudwego/iasm v0.2.0 // indirect |
| | | github.com/gabriel-vasile/mimetype v1.4.3 // indirect |
| | | github.com/gin-contrib/sse v0.1.0 // indirect |
| | | github.com/go-playground/locales v0.14.1 // indirect |
| | | github.com/go-playground/universal-translator v0.18.1 // indirect |
| | | github.com/go-playground/validator/v10 v10.20.0 // indirect |
| | | github.com/goccy/go-json v0.10.2 // indirect |
| | | github.com/json-iterator/go v1.1.12 // indirect |
| | | github.com/klauspost/cpuid/v2 v2.2.7 // indirect |
| | | github.com/leodido/go-urn v1.4.0 // indirect |
| | | github.com/mattn/go-isatty v0.0.20 // indirect |
| | | github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect |
| | | github.com/modern-go/reflect2 v1.0.2 // indirect |
| | | github.com/otiai10/copy v1.14.1 // indirect |
| | | github.com/otiai10/mint v1.6.3 // indirect |
| | | github.com/pelletier/go-toml/v2 v2.2.2 // indirect |
| | | github.com/twitchyliquid64/golang-asm v0.15.1 // indirect |
| | | github.com/ugorji/go/codec v1.2.12 // indirect |
| | | golang.org/x/arch v0.8.0 // indirect |
| | | golang.org/x/crypto v0.23.0 // indirect |
| | | golang.org/x/net v0.25.0 // indirect |
| | | golang.org/x/sync v0.8.0 // indirect |
| | | golang.org/x/sys v0.24.0 // indirect |
| | | golang.org/x/text v0.15.0 // indirect |
| | | google.golang.org/protobuf v1.34.1 // indirect |
| | | gopkg.in/yaml.v3 v3.0.1 // indirect |
| | | ) |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | github.com/bytedance/sonic v1.11.6 h1:oUp34TzMlL+OY1OUWxHqsdkgC/Zfc85zGqw9siXjrc0= |
| | | github.com/bytedance/sonic v1.11.6/go.mod h1:LysEHSvpvDySVdC2f87zGWf6CIKJcAvqab1ZaiQtds4= |
| | | github.com/bytedance/sonic/loader v0.1.1 h1:c+e5Pt1k/cy5wMveRDyk2X4B9hF4g7an8N3zCYjJFNM= |
| | | github.com/bytedance/sonic/loader v0.1.1/go.mod h1:ncP89zfokxS5LZrJxl5z0UJcsk4M4yY2JpfqGeCtNLU= |
| | | github.com/cloudwego/base64x v0.1.4 h1:jwCgWpFanWmN8xoIUHa2rtzmkd5J2plF/dnLS6Xd/0Y= |
| | | github.com/cloudwego/base64x v0.1.4/go.mod h1:0zlkT4Wn5C6NdauXdJRhSKRlJvmclQ1hhJgA0rcu/8w= |
| | | github.com/cloudwego/iasm v0.2.0 h1:1KNIy1I1H9hNNFEEH3DVnI4UujN+1zjpuk6gwHLTssg= |
| | | github.com/cloudwego/iasm v0.2.0/go.mod h1:8rXZaNYT2n95jn+zTI1sDr+IgcD2GVs0nlbbQPiEFhY= |
| | | github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= |
| | | github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= |
| | | github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= |
| | | github.com/gabriel-vasile/mimetype v1.4.3 h1:in2uUcidCuFcDKtdcBxlR0rJ1+fsokWf+uqxgUFjbI0= |
| | | github.com/gabriel-vasile/mimetype v1.4.3/go.mod h1:d8uq/6HKRL6CGdk+aubisF/M5GcPfT7nKyLpA0lbSSk= |
| | | github.com/gin-contrib/sse v0.1.0 h1:Y/yl/+YNO8GZSjAhjMsSuLt29uWRFHdHYUb5lYOV9qE= |
| | | github.com/gin-contrib/sse v0.1.0/go.mod h1:RHrZQHXnP2xjPF+u1gW/2HnVO7nvIa9PG3Gm+fLHvGI= |
| | | github.com/gin-gonic/gin v1.10.0 h1:nTuyha1TYqgedzytsKYqna+DfLos46nTv2ygFy86HFU= |
| | | github.com/gin-gonic/gin v1.10.0/go.mod h1:4PMNQiOhvDRa013RKVbsiNwoyezlm2rm0uX/T7kzp5Y= |
| | | github.com/go-playground/assert/v2 v2.2.0 h1:JvknZsQTYeFEAhQwI4qEt9cyV5ONwRHC+lYKSsYSR8s= |
| | | github.com/go-playground/assert/v2 v2.2.0/go.mod h1:VDjEfimB/XKnb+ZQfWdccd7VUvScMdVu0Titje2rxJ4= |
| | | github.com/go-playground/locales v0.14.1 h1:EWaQ/wswjilfKLTECiXz7Rh+3BjFhfDFKv/oXslEjJA= |
| | | github.com/go-playground/locales v0.14.1/go.mod h1:hxrqLVvrK65+Rwrd5Fc6F2O76J/NuW9t0sjnWqG1slY= |
| | | github.com/go-playground/universal-translator v0.18.1 h1:Bcnm0ZwsGyWbCzImXv+pAJnYK9S473LQFuzCbDbfSFY= |
| | | github.com/go-playground/universal-translator v0.18.1/go.mod h1:xekY+UJKNuX9WP91TpwSH2VMlDf28Uj24BCp08ZFTUY= |
| | | github.com/go-playground/validator/v10 v10.20.0 h1:K9ISHbSaI0lyB2eWMPJo+kOS/FBExVwjEviJTixqxL8= |
| | | github.com/go-playground/validator/v10 v10.20.0/go.mod h1:dbuPbCMFw/DrkbEynArYaCwl3amGuJotoKCe95atGMM= |
| | | github.com/goccy/go-json v0.10.2 h1:CrxCmQqYDkv1z7lO7Wbh2HN93uovUHgrECaO5ZrCXAU= |
| | | github.com/goccy/go-json v0.10.2/go.mod h1:6MelG93GURQebXPDq3khkgXZkazVtN9CRI+MGFi0w8I= |
| | | github.com/google/go-cmp v0.5.5 h1:Khx7svrCpmxxtHBq5j2mp/xVjsi8hQMfNLvJFAlrGgU= |
| | | github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= |
| | | github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= |
| | | github.com/json-iterator/go v1.1.12 h1:PV8peI4a0ysnczrg+LtxykD8LfKY9ML6u2jnxaEnrnM= |
| | | github.com/json-iterator/go v1.1.12/go.mod h1:e30LSqwooZae/UwlEbR2852Gd8hjQvJoHmT4TnhNGBo= |
| | | github.com/klauspost/cpuid/v2 v2.0.9/go.mod h1:FInQzS24/EEf25PyTYn52gqo7WaD8xa0213Md/qVLRg= |
| | | github.com/klauspost/cpuid/v2 v2.2.7 h1:ZWSB3igEs+d0qvnxR/ZBzXVmxkgt8DdzP6m9pfuVLDM= |
| | | github.com/klauspost/cpuid/v2 v2.2.7/go.mod h1:Lcz8mBdAVJIBVzewtcLocK12l3Y+JytZYpaMropDUws= |
| | | github.com/knz/go-libedit v1.10.1/go.mod h1:MZTVkCWyz0oBc7JOWP3wNAzd002ZbM/5hgShxwh4x8M= |
| | | github.com/leodido/go-urn v1.4.0 h1:WT9HwE9SGECu3lg4d/dIA+jxlljEa1/ffXKmRjqdmIQ= |
| | | github.com/leodido/go-urn v1.4.0/go.mod h1:bvxc+MVxLKB4z00jd1z+Dvzr47oO32F/QSNjSBOlFxI= |
| | | github.com/mattn/go-isatty v0.0.20 h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWEY= |
| | | github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y= |
| | | github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= |
| | | github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd h1:TRLaZ9cD/w8PVh93nsPXa1VrQ6jlwL5oN8l14QlcNfg= |
| | | github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= |
| | | github.com/modern-go/reflect2 v1.0.2 h1:xBagoLtFs94CBntxluKeaWgTMpvLxC4ur3nMaC9Gz0M= |
| | | github.com/modern-go/reflect2 v1.0.2/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjYzDa0/r8luk= |
| | | github.com/otiai10/copy v1.14.1 h1:5/7E6qsUMBaH5AnQ0sSLzzTg1oTECmcCmT6lvF45Na8= |
| | | github.com/otiai10/copy v1.14.1/go.mod h1:oQwrEDDOci3IM8dJF0d8+jnbfPDllW6vUjNc3DoZm9I= |
| | | github.com/otiai10/mint v1.6.3 h1:87qsV/aw1F5as1eH1zS/yqHY85ANKVMgkDrf9rcxbQs= |
| | | github.com/otiai10/mint v1.6.3/go.mod h1:MJm72SBthJjz8qhefc4z1PYEieWmy8Bku7CjcAqyUSM= |
| | | github.com/pelletier/go-toml/v2 v2.2.2 h1:aYUidT7k73Pcl9nb2gScu7NSrKCSHIDE89b3+6Wq+LM= |
| | | github.com/pelletier/go-toml/v2 v2.2.2/go.mod h1:1t835xjRzz80PqgE6HHgN2JOsmgYu/h4qDAS4n929Rs= |
| | | github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= |
| | | github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= |
| | | github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= |
| | | github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw= |
| | | github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo= |
| | | github.com/stretchr/objx v0.5.2/go.mod h1:FRsXN1f5AsAjCGJKqEizvkpNtU+EGNCLh3NxZ/8L+MA= |
| | | github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= |
| | | github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= |
| | | github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= |
| | | github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU= |
| | | github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4= |
| | | github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo= |
| | | github.com/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsTg= |
| | | github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY= |
| | | github.com/twitchyliquid64/golang-asm v0.15.1 h1:SU5vSMR7hnwNxj24w34ZyCi/FmDZTkS4MhqMhdFk5YI= |
| | | github.com/twitchyliquid64/golang-asm v0.15.1/go.mod h1:a1lVb/DtPvCB8fslRZhAngC2+aY1QWCk3Cedj/Gdt08= |
| | | github.com/ugorji/go/codec v1.2.12 h1:9LC83zGrHhuUA9l16C9AHXAqEV/2wBQ4nkvumAE65EE= |
| | | github.com/ugorji/go/codec v1.2.12/go.mod h1:UNopzCgEMSXjBc6AOMqYvWC1ktqTAfzJZUZgYf6w6lg= |
| | | golang.org/x/arch v0.0.0-20210923205945-b76863e36670/go.mod h1:5om86z9Hs0C8fWVUuoMHwpExlXzs5Tkyp9hOrfG7pp8= |
| | | golang.org/x/arch v0.8.0 h1:3wRIsP3pM4yUptoR96otTUOXI367OS0+c9eeRi9doIc= |
| | | golang.org/x/arch v0.8.0/go.mod h1:FEVrYAQjsQXMVJ1nsMoVVXPZg6p2JE2mx8psSWTDQys= |
| | | golang.org/x/crypto v0.23.0 h1:dIJU/v2J8Mdglj/8rJ6UUOM3Zc9zLZxVZwwxMooUSAI= |
| | | golang.org/x/crypto v0.23.0/go.mod h1:CKFgDieR+mRhux2Lsu27y0fO304Db0wZe70UKqHu0v8= |
| | | golang.org/x/net v0.25.0 h1:d/OCCoBEUq33pjydKrGQhw7IlUPI2Oylr+8qLx49kac= |
| | | golang.org/x/net v0.25.0/go.mod h1:JkAGAh7GEvH74S6FOH42FLoXpXbE/aqXSrIQjXgsiwM= |
| | | golang.org/x/sync v0.8.0 h1:3NFvSEYkUoMifnESzZl15y791HH1qU2xm6eCJU5ZPXQ= |
| | | golang.org/x/sync v0.8.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk= |
| | | golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= |
| | | golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= |
| | | golang.org/x/sys v0.20.0 h1:Od9JTbYCk261bKm4M/mw7AklTlFYIa0bIp9BgSm1S8Y= |
| | | golang.org/x/sys v0.20.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= |
| | | golang.org/x/sys v0.24.0 h1:Twjiwq9dn6R1fQcyiK+wQyHWfaz/BJB+YIpzU/Cv3Xg= |
| | | golang.org/x/sys v0.24.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= |
| | | golang.org/x/text v0.15.0 h1:h1V/4gjBv8v9cjcR6+AR5+/cIYK5N/WAgiv4xlsEtAk= |
| | | golang.org/x/text v0.15.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU= |
| | | golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543 h1:E7g+9GITq07hpfrRu66IVDexMakfv52eLZ2CXBWiKr4= |
| | | golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= |
| | | google.golang.org/protobuf v1.34.1 h1:9ddQBjfCyZPOHPUiPxpYESBLc+T8P3E+Vo4IbKZgFWg= |
| | | google.golang.org/protobuf v1.34.1/go.mod h1:c6P6GXX6sHbq/GpV6MGZEdwhWPcYBgnhAHhKbcUYpos= |
| | | gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM= |
| | | gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= |
| | | gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= |
| | | gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= |
| | | gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= |
| | | nullprogram.com/x/optparse v1.0.0/go.mod h1:KdyPE+Igbe0jQUrVfMqDMeJQIJZEuyV7pjYmp6pbG50= |
| | | rsc.io/pdf v0.1.1/go.mod h1:n8OzWcQ6Sp37PL01nO98y4iUCRdTGarVfzxY20ICaU4= |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | package main |
| | | |
| | | import ( |
| | | "app/routes" |
| | | "os" |
| | | |
| | | "github.com/gin-gonic/gin" |
| | | ) |
| | | |
| | | func main() { |
| | | env := os.Getenv("ENV") |
| | | if env == "production" { |
| | | gin.SetMode(gin.ReleaseMode) // ç产ç¯å¢ |
| | | } else { |
| | | gin.SetMode(gin.DebugMode) // å¼åç¯å¢ |
| | | } |
| | | r := gin.Default() |
| | | // 注åè·¯ç± |
| | | routes.RegisterRoutes(r) |
| | | |
| | | // è¿è¡æå¡å¨ |
| | | r.Run(":8800") |
| | | } |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | package routes |
| | | |
| | | import ( |
| | | "app/controllers" |
| | | |
| | | "github.com/gin-gonic/gin" |
| | | ) |
| | | |
| | | // RegisterRoutes æ³¨åææè·¯ç± |
| | | func RegisterRoutes(r *gin.Engine) { |
| | | prefixRoute := r.Group("/projectApi") |
| | | prefixRoute.GET("/", controllers.HomeHandler) // 主页 |
| | | prefixRoute.GET("/env", controllers.FileHandler) // æä»¶ |
| | | prefixRoute.POST("create", controllers.CreateWidget) |
| | | } |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | package service |
| | | |
| | | import ( |
| | | "app/dto" |
| | | "app/utils" |
| | | "encoding/json" |
| | | "fmt" |
| | | "os" |
| | | "path/filepath" |
| | | "strings" |
| | | |
| | | "github.com/gin-gonic/gin" |
| | | cp "github.com/otiai10/copy" |
| | | ) |
| | | |
| | | // å建service |
| | | func CreateService(c *gin.Context, body dto.RequestBody) { |
| | | // å¤å¶æä»¶å°ä¸ä¸å± |
| | | absPath, _ := filepath.Abs("../src") |
| | | tplAbsPath, _ := filepath.Abs("../src/MyPluginName") |
| | | sourceAbsPath, _ := filepath.Abs("./template") |
| | | menuAbsPath, _ := filepath.Abs("../src/config/menu.ts") |
| | | widgetPath := filepath.ToSlash(absPath) |
| | | sourcePath := filepath.ToSlash(sourceAbsPath) |
| | | tplPath := filepath.ToSlash(tplAbsPath) |
| | | upWidget := utils.CapitalizeFirstLetter(body.WidgetId) |
| | | s, _ := filepath.Abs("../src/" + upWidget) |
| | | t, _ := filepath.Abs("../src/widgets/" + upWidget) |
| | | widgetSourcePath := filepath.ToSlash(s) |
| | | widgetTargetPath := filepath.ToSlash(t) |
| | | menuPath := filepath.ToSlash(menuAbsPath) |
| | | |
| | | cpErr := cp.Copy(sourcePath, widgetPath) |
| | | if cpErr != nil { |
| | | utils.HandlerErr(c, cpErr) |
| | | return |
| | | } |
| | | |
| | | // æ«æå¤å¶çæä»¶å¤¹ |
| | | var matchDirs []string |
| | | filepath.WalkDir(tplPath, func(path string, d os.DirEntry, err error) error { |
| | | if err != nil { |
| | | utils.HandlerErr(c, err) |
| | | return err |
| | | } |
| | | matchDirs = append(matchDirs, path) |
| | | return nil |
| | | }) |
| | | entityName := body.WidgetId + "Entity" |
| | | for _, dir := range matchDirs { |
| | | // æ¿æ¢æä»¶å
容 |
| | | utils.ReplaceFileContent(dir, []string{body.WidgetId, entityName, "MyPluginName", "MyEntityName"}, body.WidgetName) |
| | | // ä¿®æ¹æä»¶åç§° |
| | | if strings.Contains(dir, "MyPluginName") { |
| | | if !strings.Contains(dir, "MyEntityName") { |
| | | utils.RenameFile(dir, body.WidgetId, "MyPluginName") |
| | | } else { |
| | | utils.RenameFile(dir, body.WidgetId, "MyPluginName", entityName, "MyEntityName") |
| | | } |
| | | } |
| | | |
| | | } |
| | | // å é¤ç®å½ |
| | | fileErr := os.RemoveAll(tplAbsPath) |
| | | if fileErr != nil { |
| | | utils.HandlerErr(c, fileErr) |
| | | return |
| | | } |
| | | // ç§»å¨ç®å½ï¼ |
| | | // err := os.Rename(widgetSourcePath, widgetTargetPath) |
| | | err := cp.Copy(widgetSourcePath, widgetTargetPath) |
| | | <<<<<<< HEAD |
| | | fmt.Print(widgetSourcePath,widgetTargetPath,err,"================================") |
| | | |
| | | ======= |
| | | if err != nil { |
| | | utils.HandlerErr(c, err) |
| | | return |
| | | } |
| | | // å é¤ç®å½ |
| | | moveErr := os.RemoveAll(widgetSourcePath) |
| | | if moveErr != nil { |
| | | utils.HandlerErr(c, moveErr) |
| | | return |
| | | } |
| | | >>>>>>> 3e0cd197c07476292ecb2980eec427fa8e40d1a0 |
| | | // æ´æ° menu.ts |
| | | newMenuMap := map[string]interface{}{ |
| | | "icon": "p", |
| | | "name": body.WidgetName, |
| | | "notPage": false, |
| | | "patchName": body.WidgetId, |
| | | "path": "/information-base/" + body.WidgetId, |
| | | } |
| | | body.Menu = append(body.Menu, newMenuMap) |
| | | body.MenuMap[body.WidgetId] = newMenuMap |
| | | menuStr, menuErr := generateMenuStr(body.Menu, 1) |
| | | if menuErr != nil { |
| | | utils.HandlerErr(c, menuErr) |
| | | } |
| | | menuMapStr, menuMapErr := generateMenuStr(body.MenuMap, 2) |
| | | if menuMapErr != nil { |
| | | utils.HandlerErr(c, menuMapErr) |
| | | } |
| | | menuSumStr := menuStr + menuMapStr |
| | | // åå
¥æä»¶ |
| | | os.WriteFile(menuPath, []byte(menuSumStr), 0777) |
| | | appendFileContent(body.WidgetId, body.Type) |
| | | } |
| | | |
| | | func generateMenuStr[T any](menuConfig T, menuType int) (string, error) { |
| | | menuJson, menuErr := json.Marshal(menuConfig) |
| | | var menuKey string |
| | | var menuTypeKey string |
| | | if menuType == 1 { |
| | | menuKey = "menu" |
| | | menuTypeKey = "Record<string,any>[]" |
| | | } else { |
| | | menuKey = "menuMap" |
| | | menuTypeKey = "Record<string,any>" |
| | | } |
| | | str := fmt.Sprintf("export const %s: %s = ", menuKey, menuTypeKey) |
| | | menuStr := str + string(menuJson) + "\n" |
| | | return menuStr, menuErr |
| | | } |
| | | |
| | | func appendFileContent(widgetId string, fileType int) (string, error) { |
| | | absPath, _ := filepath.Abs("../.build.local") |
| | | prodPath, _ := filepath.Abs("../.build.prod") |
| | | local := filepath.ToSlash(absPath) |
| | | prod := filepath.ToSlash(prodPath) |
| | | |
| | | var name string |
| | | if fileType == 1 { |
| | | name = local |
| | | } else { |
| | | name = prod |
| | | } |
| | | // æå¼æä»¶ï¼å¦ææä»¶ä¸åå¨åå建 |
| | | file, err := os.OpenFile(name, os.O_APPEND|os.O_CREATE|os.O_WRONLY, 0777) |
| | | if err != nil { |
| | | |
| | | return widgetId, err |
| | | } |
| | | defer file.Close() |
| | | |
| | | // 追å å
容尿件 |
| | | _, err = file.WriteString("\n" + widgetId + "\n") |
| | | if err != nil { |
| | | return widgetId, err |
| | | } |
| | | return widgetId, err |
| | | } |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | package utils |
| | | |
| | | import ( |
| | | "net/http" |
| | | "os" |
| | | "path/filepath" |
| | | "strings" |
| | | "unicode" |
| | | |
| | | "github.com/gin-gonic/gin" |
| | | cp "github.com/otiai10/copy" |
| | | ) |
| | | |
| | | // ç»ä¸å¤çé误 |
| | | func HandlerErr(c *gin.Context, err error) error { |
| | | c.JSON(http.StatusBadRequest, gin.H{"message": err}) |
| | | return err |
| | | } |
| | | |
| | | // é¦åæ¯å¤§å |
| | | func CapitalizeFirstLetter(s string) string { |
| | | if s == "" { |
| | | return s |
| | | } |
| | | runes := []rune(s) |
| | | runes[0] = unicode.ToUpper(runes[0]) |
| | | return string(runes) |
| | | } |
| | | |
| | | // é¦åæ¯å°å |
| | | func DecapitalizeFirstLetter(s string) string { |
| | | if s == "" { |
| | | return s |
| | | } |
| | | runes := []rune(s) |
| | | runes[0] = unicode.ToLower(runes[0]) |
| | | return string(runes) |
| | | } |
| | | |
| | | func isDirectory(path string) bool { |
| | | info, err := os.Stat(path) |
| | | if err != nil { |
| | | return false // åºéï¼ä¾å¦è·¯å¾ä¸åå¨ï¼ï¼é»è®¤è¿å false |
| | | } |
| | | return info.IsDir() // 妿æ¯ç®å½ï¼è¿å true |
| | | } |
| | | |
| | | // 读åæä»¶åï¼å¹¶æ¿æ¢æä»¶å
容ï¼åæ¥ |
| | | func ReplaceFileContent(sourceFile string, configArr []string, widgetName string) { |
| | | name := configArr[0] |
| | | entityName := configArr[1] |
| | | oldName := configArr[2] |
| | | oldEntityName := configArr[3] |
| | | sFile, _ := filepath.Abs(sourceFile) |
| | | // æä»¶å |
| | | upName := CapitalizeFirstLetter(name) |
| | | lowName := DecapitalizeFirstLetter(name) |
| | | // æ§æä»¶å |
| | | upOldName := CapitalizeFirstLetter(oldName) |
| | | lowOldName := DecapitalizeFirstLetter(oldName) |
| | | // æ°å®ä½å |
| | | upEntityName := CapitalizeFirstLetter(entityName) |
| | | lowEntityName := DecapitalizeFirstLetter(entityName) |
| | | // æ§å®ä½å |
| | | upOldEntityName := CapitalizeFirstLetter(oldEntityName) |
| | | lowOldEntityName := DecapitalizeFirstLetter(oldEntityName) |
| | | // tFile, _ := filepath.Abs(targetFile) |
| | | content, err := os.ReadFile(sFile) |
| | | if err != nil { |
| | | return |
| | | } |
| | | |
| | | newContentStr := strings.ReplaceAll(string(content), "${{widgetName}}", widgetName) |
| | | newStr := strings.ReplaceAll(string(newContentStr), upOldName, upName) |
| | | pluginStr := strings.ReplaceAll(newStr, lowOldName, lowName) |
| | | entityStr := strings.ReplaceAll(pluginStr, upOldEntityName, upEntityName) |
| | | entityLowStr := strings.ReplaceAll(entityStr, lowOldEntityName, lowEntityName) |
| | | // åå
¥å°æä»¶ä¸ |
| | | os.WriteFile(sourceFile, []byte(entityLowStr), 0777) |
| | | } |
| | | |
| | | // ä¿®æ¹æä»¶åç§° |
| | | func RenameFile(dir string, targetName string, oldName string, entity ...string) { |
| | | slashDir := filepath.ToSlash(dir) |
| | | targetDir := strings.ReplaceAll(slashDir, oldName, targetName) |
| | | if len(entity) == 0 { |
| | | |
| | | if strings.Contains(targetDir, "MyPluginName") || strings.Contains(targetDir, "MyEntityName") { |
| | | return |
| | | } |
| | | if !isDirectory(slashDir) { |
| | | cp.Copy(slashDir, targetDir) |
| | | } |
| | | } else { |
| | | targetEntityDir := strings.ReplaceAll(targetDir, entity[1], entity[0]) |
| | | if strings.Contains(targetEntityDir, "MyPluginName") || strings.Contains(targetEntityDir, "MyEntityName") { |
| | | return |
| | | } |
| | | if !isDirectory(slashDir) { |
| | | cp.Copy(slashDir, targetEntityDir) |
| | | } |
| | | } |
| | | } |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | #!/bin/bash |
| | | |
| | | # é»è®¤ç»ä»¶æ°ç» |
| | | widget_Array=() |
| | | |
| | | # æå®åæ¯åä½ä¸ºåæ°ä¼ å
¥ |
| | | target_branch=$1 |
| | | |
| | | if [[ -z "$target_branch" ]]; then |
| | | echo "请æå®ç®æ 忝ï¼ä¾å¦: bash $0 feature/wg/test" |
| | | exit 1 |
| | | fi |
| | | # 读å .build.prod æä»¶å
容 |
| | | if [[ -f ./.build.prod ]]; then |
| | | while IFS= read -r line || [ -n "$line" ]; do |
| | | widget_Array+=("$line") |
| | | done < ./.build.prod |
| | | fi |
| | | |
| | | # 读å .build æä»¶å
容 |
| | | if [[ -f ./.build ]]; then |
| | | while IFS= read -r line || [ -n "$line" ]; do |
| | | widget_Array+=("$line") |
| | | done < ./.build |
| | | fi |
| | | |
| | | # 读å .build æä»¶å
容 |
| | | if [[ -f ./.build.local ]]; then |
| | | while IFS= read -r line || [ -n "$line" ]; do |
| | | widget_Array+=("$line") |
| | | done < ./.build.local |
| | | fi |
| | | |
| | | # å»é |
| | | widget_Array=($(echo "${widget_Array[@]}" | tr ' ' '\n' | sort -u | tr '\n' ' ')) |
| | | |
| | | # åå¨åæ¢ä¿¡æ¯çæ°ç» |
| | | declare -a switch_info |
| | | |
| | | # 循ç¯éåç»ä»¶æ°ç» |
| | | for widgetName in "${widget_Array[@]}"; do |
| | | # æ£æ¥ç»ä»¶ç®å½æ¯å¦åå¨ |
| | | if [[ -d "src/widgets/$widgetName" ]]; then |
| | | # è¿å
¥ç»ä»¶ç®å½ |
| | | cd "src/widgets/$widgetName" || { echo "æ æ³è¿å
¥ç®å½ src/widgets/$widgetName"; continue; } |
| | | |
| | | # è·åå½å忝å |
| | | current_branch=$(git symbolic-ref --short HEAD) |
| | | |
| | | # 妿å½ååæ¯ä»£ç æåå¨ï¼æäº¤åæ´ |
| | | if [[ -n "$(git status --porcelain)" ]]; then |
| | | git add . |
| | | git commit -m 'merge' |
| | | fi |
| | | |
| | | # å°è¯åæ¢å°æå®åæ¯ |
| | | if git show-ref --verify --quiet refs/heads/"$target_branch"; then |
| | | git checkout "$target_branch" |
| | | else |
| | | # å¦ææ²¡ææå®åæ¯ï¼å建ä¸ä¸ª |
| | | git checkout -b "$target_branch" |
| | | fi |
| | | |
| | | # è·å忢åç忝å |
| | | new_branch=$(git symbolic-ref --short HEAD) |
| | | |
| | | # æ¨éæå®åæ¯å°è¿ç¨ |
| | | # git push --set-upstream origin "$target_branch" |
| | | |
| | | # æ·»å åæ¢ä¿¡æ¯å°æ°ç» |
| | | switch_info+=("$widgetName: $current_branch -> $new_branch") |
| | | |
| | | # è¿åå°ä¸ä¸çº§ç®å½ |
| | | cd - > /dev/null || exit |
| | | else |
| | | echo "ç®å½ src/widgets/$widgetName ä¸åå¨" |
| | | fi |
| | | done |
| | | |
| | | # ç»ä¸è¾åºåæ¢ä¿¡æ¯ |
| | | echo "åæ¢ä¿¡æ¯ï¼" |
| | | for info in "${switch_info[@]}"; do |
| | | echo "$info" |
| | | done |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | # # port 端å£å· |
| | | VITE_PORT = 5173 |
| | | |
| | | VITE_API_URL = 'http://192.168.1.18:18000' # å¼åç-è²èª |
| | | VITE_APP_NAMESPACE= 'cs' |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | # # |
| | | # # 请å¤å¶æ¤æä»¶å¹¶å½å为 `.env.development.local` |
| | | # # 个人å¼åè¯·å¨ `.env.development.local` æä»¶ä¸æ¹å¨ |
| | | # # |
| | | |
| | | # # æ¬å°ç¯å¢ |
| | | # ENV = 'development' |
| | | |
| | | # VITE_APP_TITLE= CMS |
| | | |
| | | # VITE_APP_NAMESPACE= 'cs' |
| | | |
| | | # # VITE_API_URL = 'http://192.168.2.13:18000' |
| | | # VITE_API_URL = 'http://192.168.2.158:18000' |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | import { defineConfig } from 'vitepress' |
| | | export default defineConfig({ |
| | | title: 'ä¿¡æ¯åç»ä»¶åº', |
| | | description: 'å端信æ¯åç»ä»¶åº', |
| | | base: '/info', |
| | | |
| | | themeConfig: { |
| | | nav: [ |
| | | { text: 'Home', link: '/' }, |
| | | { text: 'å¿«éå¼å§', link: '/quick-start' }, |
| | | ], |
| | | |
| | | sidebar: { |
| | | '/components': [ |
| | | { |
| | | text: 'BaseContent å
容æ¡', |
| | | link: '/components/BaseContent', |
| | | }, |
| | | { |
| | | text: 'BaseDialog å¯¹è¯æ¡', |
| | | link: '/components/BaseDialog', |
| | | }, |
| | | { |
| | | text: 'BaseDrawer æ½å±', |
| | | link: '/components/BaseDrawer', |
| | | }, |
| | | { |
| | | text: 'BaseInput è¾å
¥æ¡', |
| | | link: '/components/BaseInput', |
| | | }, |
| | | { |
| | | text: 'ConfirmBox 确认æ¡', |
| | | link: '/components/ConfirmBox', |
| | | }, |
| | | { |
| | | text: 'Container 容å¨', |
| | | link: '/components/Container', |
| | | }, |
| | | { |
| | | text: 'Content å
容åº', |
| | | link: '/components/Content', |
| | | }, |
| | | { |
| | | text: 'DialogPreView å¼¹çªé¢è§', |
| | | link: '/components/DialogPreView', |
| | | }, |
| | | { |
| | | text: 'Dyform å¨æè¡¨å', |
| | | link: '/components/Dyform', |
| | | }, |
| | | { |
| | | text: 'Empty 空', |
| | | link: '/components/Empty', |
| | | }, |
| | | { |
| | | text: 'Flow æ¾ç¤º', |
| | | link: '/components/Flow', |
| | | }, |
| | | { |
| | | text: 'Icon 徿 ', |
| | | link: '/components/Icon', |
| | | }, |
| | | { |
| | | text: 'IconButon 徿 æé®', |
| | | link: '/components/IconButton', |
| | | }, |
| | | { |
| | | text: 'Pdf Pdf', |
| | | link: '/components/Pdf', |
| | | }, |
| | | { |
| | | text: 'PreviewDialog é¢è§å¼¹çªiframe', |
| | | link: '/components/PreviewDialog', |
| | | }, |
| | | { |
| | | text: 'Search æç´¢', |
| | | link: '/components/Search', |
| | | }, |
| | | { |
| | | text: 'SearchInput éæ©è¾å
¥ç»ä»¶', |
| | | link: '/components/SearchInput', |
| | | }, |
| | | { |
| | | text: 'Tag æ ç¾', |
| | | link: '/components/Tag', |
| | | }, |
| | | { |
| | | text: 'Tab æç´¢', |
| | | link: '/components/Tab', |
| | | }, |
| | | { |
| | | text: 'Table è¡¨æ ¼', |
| | | link: '/components/Table', |
| | | }, |
| | | { |
| | | text: 'TableFilter è¡¨æ ¼çé', |
| | | link: '/components/TableFilter', |
| | | }, |
| | | { |
| | | text: 'TdButton tdæé®', |
| | | link: '/components/TdButton', |
| | | }, |
| | | { |
| | | text: 'Text ææ¬', |
| | | link: '/components/Text', |
| | | }, |
| | | { |
| | | text: 'Title æ é¢', |
| | | link: '/components/Title', |
| | | }, |
| | | { |
| | | text: 'TouchScale 缩æ¾', |
| | | link: '/components/TouchScale', |
| | | }, |
| | | { |
| | | text: 'Upload ä¸ä¼ ', |
| | | link: '/components/Upload', |
| | | }, |
| | | { |
| | | text: 'Variable åé', |
| | | link: '/components/Variable', |
| | | }, |
| | | ], |
| | | }, |
| | | |
| | | socialLinks: [ |
| | | { |
| | | icon: 'github', |
| | | link: 'https://gitlab.syc-cms.com:8443/lmes-plugin/web/information-ui', |
| | | }, |
| | | ], |
| | | }, |
| | | }) |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | import type { Theme } from 'vitepress' |
| | | import Layout from '../../Layout/Layout.tsx' |
| | | import DefaultTheme from 'vitepress/theme' |
| | | import './style.css' |
| | | |
| | | export default { |
| | | extends: DefaultTheme, |
| | | enhanceApp({ app }) { |
| | | // 注åèªå®ä¹å
¨å±ç»ä»¶ |
| | | // @ts-ignore |
| | | app.component('Layout', Layout) |
| | | }, |
| | | } satisfies Theme |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | :root { |
| | | /* æ é¢ */ |
| | | --vp-home-hero-name-color: transparent; |
| | | --vp-home-hero-name-background: linear-gradient( |
| | | 135deg, |
| | | #fff886 10%, |
| | | #f072b6 100% |
| | | ); |
| | | |
| | | /* 徿 èæ¯ */ |
| | | --vp-home-hero-image-background-image: linear-gradient( |
| | | 135deg, |
| | | #fff886 10%, |
| | | #f072b6 100% |
| | | ); |
| | | --vp-home-hero-image-filter: blur(150px); |
| | | --vp-c-indigo-1: #f072b6; |
| | | --vp-c-indigo-2: #f072b6; |
| | | --vp-c-indigo-3: #f072b6; |
| | | /* 徿 èæ¯ */ |
| | | --vp-home-hero-image-background-image: linear-gradient( |
| | | 135deg, |
| | | #f6ceec 10%, |
| | | #d939cd 100% |
| | | ); |
| | | --vp-home-hero-image-filter: blur(150px); |
| | | } |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | .el-message { |
| | | display: none!important; |
| | | } |
| | | |
| | | .hover { |
| | | &:hover { |
| | | background-color: #ddd; |
| | | } |
| | | &:active { |
| | | background-color: #ccc; |
| | | } |
| | | } |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | import { defineComponent } from 'vue' |
| | | import './Layout.scss' |
| | | import 'vxe-table/lib/style.css' |
| | | |
| | | export default defineComponent({ |
| | | name: 'layout', |
| | | setup(props, { slots, attrs }) { |
| | | return () => { |
| | | return ( |
| | | <el-config-provider {...attrs} namespace="cs"> |
| | | <ClientOnly>{slots.default?.()}</ClientOnly> |
| | | </el-config-provider> |
| | | ) |
| | | } |
| | | }, |
| | | }) |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | --- |
| | | outline: deep |
| | | --- |
| | | |
| | | # Runtime API Examples |
| | | |
| | | This page demonstrates usage of some of the runtime APIs provided by VitePress. |
| | | |
| | | The main `useData()` API can be used to access site, theme, and page data for the current page. It works in both `.md` and `.vue` files: |
| | | |
| | | ```md |
| | | <script setup> |
| | | import { useData } from 'vitepress' |
| | | |
| | | const { theme, page, frontmatter } = useData() |
| | | </script> |
| | | |
| | | ## Results |
| | | |
| | | ### Theme Data |
| | | <pre>{{ theme }}</pre> |
| | | |
| | | ### Page Data |
| | | <pre>{{ page }}</pre> |
| | | |
| | | ### Page Frontmatter |
| | | <pre>{{ frontmatter }}</pre> |
| | | ``` |
| | | |
| | | <script setup> |
| | | import { useData } from 'vitepress' |
| | | |
| | | const { site, theme, page, frontmatter } = useData() |
| | | </script> |
| | | |
| | | ## Results |
| | | |
| | | ### Theme Data |
| | | <pre>{{ theme }}</pre> |
| | | |
| | | ### Page Data |
| | | <pre>{{ page }}</pre> |
| | | |
| | | ### Page Frontmatter |
| | | <pre>{{ frontmatter }}</pre> |
| | | |
| | | ## More |
| | | |
| | | Check out the documentation for the [full list of runtime APIs](https://vitepress.dev/reference/runtime-api#usedata). |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | # BaseContent |
| | | |
| | | `BaseContent` ç»ä»¶ç¨äºæ¾ç¤ºå¸¦ææ é¢ãå
容åºååå¯é页èçå
容ã |
| | | |
| | | ## 示ä¾ç¨æ³ |
| | | |
| | | <script setup> |
| | | import BaseContent from '@/components/BaseContent/BaseContent.tsx' |
| | | </script> |
| | | |
| | | <BaseContent title='æµè¯' icon='banben'> |
| | | <div style="width: 100%;height: 500px"> |
| | | å
å®¹åº |
| | | </div> |
| | | </BaseContent> |
| | | |
| | | ```vue |
| | | <template> |
| | | <BaseContent title="ç³»ç»é
ç½®" icon="settings"> |
| | | <div> |
| | | <!-- è¿éæ¾ç½®ä½ çå
容 --> |
| | | </div> |
| | | <template #footer> |
| | | <div> |
| | | <!-- è¿éæ¾ç½®é¡µèå
容 --> |
| | | </div> |
| | | </template> |
| | | </BaseContent> |
| | | </template> |
| | | |
| | | <script> |
| | | import { defineComponent } from 'vue' |
| | | import BaseContent from '@/components/BaseContent' |
| | | |
| | | export default defineComponent({ |
| | | components: { |
| | | BaseContent, |
| | | }, |
| | | // å
¶ä»ç»ä»¶é项... |
| | | }) |
| | | </script> |
| | | ``` |
| | | |
| | | å¨ä¸é¢ç示ä¾ä¸ï¼æä»¬ä½¿ç¨äº `BaseContent` ç»ä»¶ï¼æ é¢ä¸º "ç³»ç»é
ç½®"ï¼å¾æ 为 "settings"ãæä»¬è¿å¨é»è®¤ææ§½ä¸æä¾äºå
容ï¼å¨é¡µèææ§½ä¸æä¾äºé¡µèå
容ã |
| | | |
| | | ## 屿§ |
| | | |
| | | | 屿§ | æè¿° | ç±»å | é»è®¤å¼ | 示ä¾å¼ | |
| | | | ----- | -------------------------- | ------ | ------ | ---------- | |
| | | | title | 卿 颿 䏿¾ç¤ºçæ é¢ | String | 'æ é¢' | 'ç³»ç»é
ç½®' | |
| | | | icon | 卿 颿 䏿¾ç¤ºç徿 çåç§° | String | '' | 'settings' | |
| | | |
| | | ## ææ§½ |
| | | |
| | | | åç§° | æè¿° | |
| | | | ------- | ---------------------------- | |
| | | | default | è¦æ¾ç¤ºå¨å
容åºåä¸ç主è¦å
容 | |
| | | | footer | å¯éç页èå
容 | |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | # BaseDialog |
| | | |
| | | å¨ä¿çå½å页é¢ç¶æçæ
åµä¸ï¼åç¥ç¨æ·å¹¶æ¿è½½ç¸å
³æä½ã |
| | | åºç¡å±æ§ä¸ element-plus 屿§ç¸å |
| | | |
| | | ## ç¤ºä¾ |
| | | |
| | | <script setup> |
| | | import BaseDialog from '@/components/BaseDialog/index.vue' |
| | | import { ref } from 'vue' |
| | | const visible = ref(false) |
| | | |
| | | </script> |
| | | <Layout> |
| | | <el-button type='primary' @click="visible=true">æå¼</el-button> |
| | | <BaseDialog |
| | | v-model="visible" |
| | | @close="visible = false" |
| | | @confirm="visible = true" |
| | | width="500" |
| | | height="300"> |
| | | ææ¯å¯¹è¯æ¡ |
| | | </BaseDialog> |
| | | </Layout> |
| | | |
| | | ```js-vue |
| | | <template> |
| | | <el-button type='primary' @click="visible=true">æå¼</el-button> |
| | | <BaseDialog |
| | | v-model="visible" |
| | | @close="visible = false" |
| | | @confirm="visible = true" |
| | | width="500" |
| | | height="300"> |
| | | ææ¯å¯¹è¯æ¡ |
| | | </BaseDialog> |
| | | </template> |
| | | |
| | | <script setup> |
| | | import BaseDialog from '@/components/BaseDialog/index.vue' |
| | | import { ref } from 'vue' |
| | | const visible = ref(false) |
| | | </script> |
| | | |
| | | ``` |
| | | |
| | | ## 屿§ |
| | | |
| | | | 屿§ | ç±»å | 说æ | |
| | | | ------------- | -------- | ------------------------------------ | |
| | | | className | 计ç®å±æ§ | è®¾ç½®å¯¹è¯æ¡çèªå®ä¹ç±»åã | |
| | | | attrs | 计ç®å±æ§ | è·åä¼ éç»å¯¹è¯æ¡ç»ä»¶çææå±æ§ã | |
| | | | props | 屿§å®ä¹ | å¯¹è¯æ¡ç»ä»¶ç props 对象ã | |
| | | | footer | 计ç®å±æ§ | æ£æµæ¯å¦åå¨å¯¹è¯æ¡åºé¨çèªå®ä¹å
容ã | |
| | | | currentHeight | 计ç®å±æ§ | å½åå¯¹è¯æ¡çé«åº¦ã | |
| | | |
| | | ## äºä»¶ |
| | | |
| | | | äºä»¶ | 说æ | |
| | | | ------- | ------------ | |
| | | | close | å
³éå¯¹è¯æ¡ã | |
| | | | confirm | ç¡®è®¤å¯¹è¯æ¡ã | |
| | | | open | æå¼å¯¹è¯æ¡ã | |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | # BaseDrawer |
| | | |
| | | æäºæ¶å, Dialog ç»ä»¶å¹¶ä¸æ»¡è¶³æä»¬çéæ±, æ¯å¦ä½ ç表åå¾é¿, äº¦ææ¯ä½ éè¦ä¸´æ¶å±ç¤ºä¸äºææ¡£, Drawer æ¥æå Dialog å ä¹ç¸åç API, å¨ UI ä¸å¸¦æ¥ä¸ä¸æ ·çä½éª. |
| | | åºç¡å±æ§ä¸ element-plus 屿§ç¸å |
| | | |
| | | ## ææ¡£ |
| | | |
| | | è¿ä¸ªç¤ºä¾å±ç¤ºäºä¸ä¸ªç®åçæ½å±ç»ä»¶ãå½ç¨æ·ç¹å»"æå¼æ½å±"æé®æ¶ï¼`showDrawer` æ¹æ³ä¼è¢«è°ç¨ï¼æ¾ç¤ºä¸ä¸ªå为 "ç¤ºä¾æ½å±" çæ½å±ï¼ç¨æ·å¯ä»¥å¨æ½å±ä¸ç¹å»ç¡®å®æåæ¶æé®ï¼åå«è§¦å对åºçäºä»¶å¤ç彿° `handleConfirm` å `closeDrawer`ã |
| | | |
| | | ## ç¤ºä¾ |
| | | |
| | | <script setup> |
| | | import BaseDrawer from '@/components/BaseDrawer/BaseDrawer.tsx' |
| | | import { ref } from 'vue' |
| | | |
| | | const drawerVisible = ref(false) |
| | | |
| | | const showDrawer = () => { |
| | | drawerVisible.value = true |
| | | } |
| | | |
| | | const closeDrawer = () => { |
| | | drawerVisible.value = false |
| | | } |
| | | |
| | | const handleConfirm = () => { |
| | | console.log('ç¨æ·ç¹å»äºç¡®è®¤æé®') |
| | | closeDrawer() |
| | | } |
| | | </script> |
| | | |
| | | <Layout> |
| | | <el-button type="primary" @click="showDrawer">æå¼æ½å±</el-button> |
| | | <BaseDrawer width="40%" title="ç¤ºä¾æ½å±" v-model="drawerVisible" @close="closeDrawer" @confirm="handleConfirm"> |
| | | <p>è¿æ¯æ½å±çå
容ã</p> |
| | | </BaseDrawer> |
| | | </Layout> |
| | | |
| | | ```js-vue |
| | | <template> |
| | | <div> |
| | | <el-button type="primary" @click="showDrawer">æå¼æ½å±</el-button> |
| | | <BaseDrawer title="ç¤ºä¾æ½å±" v-model="drawerVisible" @close="closeDrawer" @confirm="handleConfirm"> |
| | | <p>è¿æ¯æ½å±çå
容ã</p> |
| | | </BaseDrawer> |
| | | </div> |
| | | </template> |
| | | |
| | | <script setup> |
| | | import BaseDrawer from './BaseDrawer.vue' |
| | | import { ref } from 'vue' |
| | | |
| | | const drawerVisible = ref(false) |
| | | |
| | | const showDrawer = () => { |
| | | drawerVisible.value = true |
| | | } |
| | | |
| | | const closeDrawer = () => { |
| | | drawerVisible.value = false |
| | | } |
| | | |
| | | const handleConfirm = () => { |
| | | console.log('ç¨æ·ç¹å»äºç¡®è®¤æé®') |
| | | closeDrawer() |
| | | } |
| | | </script> |
| | | ``` |
| | | |
| | | ## 屿§ |
| | | |
| | | | 屿§ | ç±»å | é»è®¤å¼ | 说æ | |
| | | | --------- | ------- | ------ | -------------- | |
| | | | clickable | Boolean | false | é®ç½©æ¯å¦å¯ç¹å» | |
| | | | title | String | '' | æ½å±æ é¢ | |
| | | | width | String | '' | æ½å±å®½åº¦ | |
| | | |
| | | ## äºä»¶ |
| | | |
| | | | äºä»¶ | 说æ | |
| | | | ----------------- | ---------------- | |
| | | | close | å
³éæ½å± | |
| | | | confirm | 确认æ½å± | |
| | | | update:modelValue | æ´æ° modelValue | |
| | | | open | æå¼æ½å± | |
| | | | beforeClose | å
³éæ½å±åçäºä»¶ | |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | # BaseInput |
| | | |
| | | åºç¡ inputï¼ä¸å
嫿 ·å¼ |
| | | |
| | | ## ç¤ºä¾ |
| | | |
| | | <script setup> |
| | | import BaseInput from '@/components/BaseInput/BaseInput.tsx' |
| | | import { ref } from 'vue' |
| | | const value = ref('') |
| | | </script> |
| | | |
| | | <Layout> |
| | | <BaseInput v-model="value" placeholder="请è¾å
¥" style="border: 1px solid #ccc"/> |
| | | </Layout> |
| | | |
| | | ```js-vue |
| | | <template> |
| | | <Layout> |
| | | <Base v-model="value" style="border: 1px solid #ccc"/> |
| | | </Layout> |
| | | </template> |
| | | <script> |
| | | import BaseDrawer from '@/components/BaseInput/BaseInput.tsx' |
| | | import { ref } from 'vue' |
| | | const value = ref('') |
| | | </script> |
| | | |
| | | ``` |
| | | |
| | | ## 屿§ |
| | | |
| | | | 屿§ | ç±»å | é»è®¤å¼ | 说æ | |
| | | | ----------- | ------------- | -------- | -------------- | |
| | | | modelValue | String/Number | '' | è¾å
¥æ¡çå¼ | |
| | | | placeholder | String | '请è¾å
¥' | è¾å
¥æ¡çå ä½ç¬¦ | |
| | | |
| | | ## äºä»¶ |
| | | |
| | | | äºä»¶ | 说æ | |
| | | | ----------------- | ---------------------- | |
| | | | update:modelValue | æ´æ°è¾å
¥æ¡çå¼ | |
| | | | click | ç¹å»è¾å
¥æ¡æ¶è§¦åçäºä»¶ | |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | # ConfirmBox |
| | | |
| | | ## ä½¿ç¨ææ¡£ |
| | | |
| | | ç¡®è®¤å¼¹çª |
| | | |
| | | ## ç¤ºä¾ |
| | | |
| | | <script setup> |
| | | import { ConfirmBox } from '@/components/ConfirmBox/ConfirmBox.tsx' |
| | | import { ref } from 'vue' |
| | | |
| | | const handleConfirm = async () => { |
| | | try { |
| | | const result = await ConfirmBox('ç¡®å®è¦å é¤åï¼', 'å é¤ç¡®è®¤') |
| | | if (result) { |
| | | console.log('ç¨æ·ç¹å»äºç¡®è®¤æé®') |
| | | // æ§è¡å é¤æä½ |
| | | } else { |
| | | console.log('ç¨æ·ç¹å»äºåæ¶æé®') |
| | | } |
| | | } catch (error) { |
| | | console.log('å¯¹è¯æ¡å
³éæåºç°é误:', error) |
| | | } |
| | | } |
| | | </script> |
| | | |
| | | <Layout> |
| | | <el-button type='primary' @click="handleConfirm">æå¼</el-button> |
| | | </Layout> |
| | | |
| | | ```js-vue |
| | | |
| | | <script setup> |
| | | import ConfirmBox from '@/components/ConfirmBox/ConfirmBox.tsx' |
| | | import { ref } from 'vue' |
| | | |
| | | const handleConfirm = async () => { |
| | | try { |
| | | const result = await ConfirmBox('ç¡®å®è¦å é¤åï¼', 'å é¤ç¡®è®¤') |
| | | if (result) { |
| | | console.log('ç¨æ·ç¹å»äºç¡®è®¤æé®') |
| | | // æ§è¡å é¤æä½ |
| | | } else { |
| | | console.log('ç¨æ·ç¹å»äºåæ¶æé®') |
| | | } |
| | | } catch (error) { |
| | | console.log('å¯¹è¯æ¡å
³éæåºç°é误:', error) |
| | | } |
| | | } |
| | | </script> |
| | | |
| | | <template> |
| | | <Layout> |
| | | <el-button @click="handleConfirm">æå¼</el-button> |
| | | </Layout> |
| | | </template> |
| | | ``` |
| | | |
| | | è¿ä¸ªç¤ºä¾å±ç¤ºäºå¦ä½ä½¿ç¨ `ConfirmBox` 彿°æ¥æ¾ç¤ºä¸ä¸ªå¸¦æç¡®è®¤ååæ¶æé®çå¯¹è¯æ¡ï¼å¹¶æ ¹æ®ç¨æ·çæä½æ§è¡ç¸åºçæä½ã |
| | | |
| | | ## 屿§ |
| | | |
| | | | 屿§å | ç±»å | é»è®¤å¼ | 说æ | |
| | | | ------------- | ------------- | -------- | --------------------------------------------- | |
| | | | `modelValue` | Boolean | false | æ§å¶å¯¹è¯æ¡çæ¾ç¤ºä¸éèï¼ä½¿ç¨ `v-model` ç»å®ã | |
| | | | `title` | String | '' | å¯¹è¯æ¡çæ é¢ã | |
| | | | `width` | String | '' | å¯¹è¯æ¡ç宽度ã | |
| | | | `clickable` | Boolean | false | é®ç½©æ¯å¦å¯ç¹å»ã | |
| | | | `placeholder` | String | '请è¾å
¥' | è¾å
¥æ¡çå ä½ç¬¦ã | |
| | | | `modelValue` | String/Number | '' | è¾å
¥æ¡çå¼ã | |
| | | |
| | | ## äºä»¶ |
| | | |
| | | | äºä»¶å | åæ° | 说æ | |
| | | | ------------------- | ---------------- | ------------------------ | |
| | | | `update:modelValue` | `value: boolean` | æ´æ°å¯¹è¯æ¡çæ¾ç¤ºç¶æã | |
| | | | `close` | - | å
³éå¯¹è¯æ¡æ¶è§¦åã | |
| | | | `confirm` | - | ç¨æ·ç¡®è®¤å¯¹è¯æ¡æ¶è§¦åã | |
| | | | `open` | - | æå¼å¯¹è¯æ¡æ¶è§¦åã | |
| | | | `beforeClose` | - | å
³éå¯¹è¯æ¡å触åçäºä»¶ã | |
| | | | `click` | `event: Event` | ç¹å»è¾å
¥æ¡æ¶è§¦åçäºä»¶ã | |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | # Container å®¹å¨ |
| | | |
| | | 该ç»ä»¶ç¨äºæ¾ç¤ºä¸ä¸ªéç¨ç页é¢å¤´é¨ï¼å¯ä»¥å
嫿 é¢åæç´¢åè½ã |
| | | |
| | | ## ç¤ºä¾ |
| | | |
| | | <Layout> |
| | | <Container |
| | | title="éç¨å¤´é¨ç¤ºä¾" |
| | | :placeholder="'æç´¢å
容'" |
| | | :modelValue="searchValue" |
| | | @confirm="handleSearch"> |
| | | |
| | | <!-- è¿éæ¾å
¶ä»å
容 --> |
| | | |
| | | </Container> |
| | | </Layout> |
| | | |
| | | <script setup> |
| | | import { ref } from 'vue' |
| | | import Container from '@/components/Container/Container.tsx' |
| | | |
| | | const searchValue = ref('') |
| | | |
| | | const handleSearch = (value) => { |
| | | console.log('ç¨æ·æç´¢:', value) |
| | | // æ§è¡æç´¢æä½ |
| | | } |
| | | </script> |
| | | |
| | | ```vue |
| | | <template> |
| | | <Container |
| | | title="éç¨å¤´é¨ç¤ºä¾" |
| | | :placeholder="'æç´¢å
容'" |
| | | :modelValue="searchValue" |
| | | @confirm="handleSearch" |
| | | > |
| | | <!-- è¿éæ¾å
¶ä»å
容 --> |
| | | </Container> |
| | | </template> |
| | | |
| | | <script> |
| | | import { ref } from 'vue' |
| | | import Container from '@/components/Container/Container.tsx' |
| | | |
| | | export default { |
| | | components: { |
| | | Container, |
| | | }, |
| | | setup() { |
| | | const searchValue = ref('') |
| | | |
| | | const handleSearch = (value) => { |
| | | console.log('ç¨æ·æç´¢:', value) |
| | | // æ§è¡æç´¢æä½ |
| | | } |
| | | |
| | | return { |
| | | searchValue, |
| | | handleSearch, |
| | | } |
| | | }, |
| | | } |
| | | </script> |
| | | ``` |
| | | |
| | | å¨è¯¥ç¤ºä¾ä¸ï¼`UniversalHeader` ç»ä»¶è¢«ä½¿ç¨ï¼å¹¶éè¿å±æ§ä¼ éäºæ é¢ãæç´¢æ¡çå ä½ç¬¦ä»¥åæç´¢æ¡çå¼ãå½ç¨æ·ç¡®è®¤æç´¢æ¶ï¼`confirm` äºä»¶è¢«è§¦åï¼è°ç¨ `handleSearch` æ¹æ³æ§è¡æç´¢æä½ã |
| | | |
| | | ## 屿§ |
| | | |
| | | | 屿§å | ç±»å | é»è®¤å¼ | å¿
å¡« | æè¿° | |
| | | | ----------- | ------- | ------------ | ---- | ------------------ | |
| | | | title | String | - | æ¯ | 头鍿 é¢ | |
| | | | placeholder | String | '请è¾å
¥æç´¢' | å¦ | æç´¢è¾å
¥æ¡çå ä½ç¬¦ | |
| | | | modelValue | String | '' | å¦ | æç´¢è¾å
¥æ¡çå¼ | |
| | | | isSearch | Boolean | true | å¦ | æ¯å¦æ¾ç¤ºæç´¢è¾å
¥æ¡ | |
| | | |
| | | ## äºä»¶ |
| | | |
| | | | äºä»¶å | åæ° | æè¿° | |
| | | | ------- | ------------- | ------------------------------ | |
| | | | confirm | value: String | å½ç¨æ·æä¸å车é®ç¡®è®¤æç´¢æ¶è§¦å | |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | # Content å
容ç»ä»¶ |
| | | |
| | | ## ç¤ºä¾ |
| | | |
| | | <Layout> |
| | | <Content title="éç¨å
容示ä¾"> |
| | | <div style="width:100%;height:500px"> |
| | | <!-- è¿éæ¾å
容 --> |
| | | ææ¯å
容 |
| | | </div> |
| | | </Content> |
| | | </Layout> |
| | | |
| | | <script setup> |
| | | import Content from '@/components/Content/Content.tsx' |
| | | </script> |
| | | |
| | | ```vue |
| | | <template> |
| | | <Content title="éç¨å
容示ä¾"> |
| | | <div style="width:100%;height:500px"> |
| | | <!-- è¿éæ¾å
容 --> |
| | | ææ¯å
容 |
| | | </div> |
| | | </Content> |
| | | </template> |
| | | |
| | | <script setup> |
| | | import Content from '@/components/Content/Content.tsx' |
| | | |
| | | export default { |
| | | components: { |
| | | Content, |
| | | }, |
| | | } |
| | | </script> |
| | | ``` |
| | | |
| | | å¨è¯¥ç¤ºä¾ä¸ï¼`Content` ç»ä»¶è¢«ä½¿ç¨ï¼å¹¶éè¿å±æ§ä¼ éäºæ é¢ãå¨ç»ä»¶å
é¨ï¼å¯ä»¥éè¿ææ§½æ¾ç½®å
¶ä»å
容ã |
| | | |
| | | 该ç»ä»¶ç¨äºæ¾ç¤ºéç¨çå
容åºåï¼å
嫿 é¢åå
容ã |
| | | |
| | | ## 屿§ |
| | | |
| | | | 屿§å | ç±»å | é»è®¤å¼ | å¿
å¡« | æè¿° | |
| | | | ------ | ------ | ------ | ---- | -------- | |
| | | | title | String | 'æ é¢' | å¦ | å
容æ é¢ | |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | # DialogPreView å¯¹è¯æ¡é¢è§ç»ä»¶ |
| | | |
| | | 该ç»ä»¶ç¨äºæ¾ç¤ºå¯¹è¯æ¡é¢è§ï¼å¯ä»¥å±ç¤ºå¾è¡¨æè
å¾çå表ã |
| | | |
| | | ## ç¤ºä¾ |
| | | |
| | | <Layout> |
| | | <el-button @click="dialogVisible = true" type='primary'>echartæå¼</el-button> |
| | | |
| | | <DialogPreView |
| | | title="å¯¹è¯æ¡é¢è§ç¤ºä¾" |
| | | :isChart="true" |
| | | :chartOptions="chartOptions" |
| | | :picList="picList" |
| | | v-model="dialogVisible" |
| | | @close="handleClose" |
| | | @confirm="handleConfirm"></DialogPreView> |
| | | |
| | | ```vue |
| | | <template> |
| | | <Layout> |
| | | <DialogPreView |
| | | title="å¯¹è¯æ¡é¢è§ç¤ºä¾" |
| | | :isChart="isChart" |
| | | :chartOptions="chartOptions" |
| | | :picList="picList" |
| | | v-model:visible="dialogVisible" |
| | | @close="handleClose" |
| | | @confirm="handleConfirm" |
| | | > |
| | | </DialogPreView> |
| | | </Layout> |
| | | </template> |
| | | |
| | | <script setup> |
| | | import { ref } from 'vue' |
| | | import DialogPreView from '@/components/DialogPreView/DialogPreView.vue' |
| | | |
| | | const dialogVisible = ref(false) |
| | | const isChart = ref(true) |
| | | const chartOptions = ref({ |
| | | xAxis: { |
| | | type: 'category', |
| | | data: ['Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat', 'Sun'], |
| | | }, |
| | | yAxis: { |
| | | type: 'value', |
| | | }, |
| | | series: [ |
| | | { |
| | | data: [120, 200, 150, 80, 70, 110, 130], |
| | | type: 'bar', |
| | | }, |
| | | ], |
| | | }) |
| | | const picList = ref([]) |
| | | |
| | | const handleClose = () => { |
| | | console.log('å¯¹è¯æ¡å
³é') |
| | | } |
| | | |
| | | const handleConfirm = () => { |
| | | console.log('确认æé®è¢«ç¹å»') |
| | | } |
| | | </script> |
| | | ``` |
| | | |
| | | <el-button @click="dialogVisible1 = true" type='primary'>å¾çæå¼</el-button> |
| | | <DialogPreView |
| | | title="å¯¹è¯æ¡é¢è§ç¤ºä¾" |
| | | :isChart="false" |
| | | :chartOptions="chartOptions" |
| | | :picList="picList" |
| | | v-model="dialogVisible1" |
| | | @close="handleClose" |
| | | @confirm="handleConfirm"></DialogPreView> |
| | | </Layout> |
| | | |
| | | <script setup> |
| | | import { ref } from 'vue' |
| | | import DialogPreView from '@/components/DialogPreView/DialogPreView.tsx' |
| | | const ROOT_PATH = 'https://echarts.apache.org/examples'; |
| | | const dialogVisible = ref(false) |
| | | const dialogVisible1 = ref(false) |
| | | const isChart = ref(true) |
| | | const chartOptions = ref({ |
| | | xAxis: { |
| | | type: 'category', |
| | | data: ['Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat', 'Sun'], |
| | | }, |
| | | yAxis: { |
| | | type: 'value', |
| | | }, |
| | | series: [ |
| | | { |
| | | data: [120, 200, 150, 80, 70, 110, 130], |
| | | type: 'bar', |
| | | }, |
| | | ], |
| | | }) |
| | | const picList = ref(['https://copyright.bdstatic.com/vcg/creative/cc9c744cf9f7c864889c563cbdeddce6.jpg@h_1280']) |
| | | |
| | | |
| | | const handleClose = () => { |
| | | console.log('å¯¹è¯æ¡å
³é') |
| | | } |
| | | |
| | | const handleConfirm = () => { |
| | | console.log('确认æé®è¢«ç¹å»') |
| | | } |
| | | </script> |
| | | |
| | | ```vue |
| | | <template> |
| | | <Layout> |
| | | <DialogPreView |
| | | title="å¯¹è¯æ¡é¢è§ç¤ºä¾" |
| | | :isChart="isChart" |
| | | :chartOptions="chartOptions" |
| | | :picList="picList" |
| | | v-model:visible="dialogVisible" |
| | | @close="handleClose" |
| | | @confirm="handleConfirm" |
| | | > |
| | | </DialogPreView> |
| | | </Layout> |
| | | </template> |
| | | |
| | | <script setup> |
| | | import { ref } from 'vue' |
| | | import DialogPreView from '@/components/DialogPreView/DialogPreView.vue' |
| | | |
| | | const dialogVisible = ref(false) |
| | | const isChart = ref(true) |
| | | const chartOptions = ref({}) |
| | | const picList = ref([ |
| | | 'https://copyright.bdstatic.com/vcg/creative/cc9c744cf9f7c864889c563cbdeddce6.jpg@h_1280', |
| | | ]) |
| | | |
| | | const handleClose = () => { |
| | | console.log('å¯¹è¯æ¡å
³é') |
| | | } |
| | | |
| | | const handleConfirm = () => { |
| | | console.log('确认æé®è¢«ç¹å»') |
| | | } |
| | | </script> |
| | | ``` |
| | | |
| | | ## 屿§ |
| | | |
| | | | 屿§å | ç±»å | é»è®¤å¼ | å¿
å¡« | æè¿° | |
| | | | ------------ | --------------- | ------ | ---- | -------------- | |
| | | | title | String | 'é¢è§' | å¦ | å¯¹è¯æ¡æ é¢ | |
| | | | isChart | Boolean | false | å¦ | æ¯å¦ä¸ºå¾è¡¨é¢è§ | |
| | | | chartOptions | Object | {} | å¦ | å¾è¡¨é
置项 | |
| | | | picList | Array\<string\> | [] | å¦ | å¾çå表 | |
| | | |
| | | ## äºä»¶ |
| | | |
| | | | äºä»¶å | åæ° | æè¿° | |
| | | | ----------------- | ------- | -------------------------------- | |
| | | | update:modelValue | Boolean | å½å¯¹è¯æ¡çæ¾ç¤ºç¶æåçæ¹åæ¶è§¦å | |
| | | | close | - | å½å¯¹è¯æ¡å
³éæ¶è§¦å | |
| | | | confirm | - | å½ç¡®è®¤æé®è¢«ç¹å»æ¶è§¦å | |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | # DyForm å¨æè¡¨åç»ä»¶ |
| | | |
| | | 该ç»ä»¶ç¨äºçæå¨æè¡¨åï¼å¯ä»¥æ ¹æ®ä¼ å
¥çé
置项渲æä¸åç表å项ã |
| | | |
| | | ## ç¤ºä¾ |
| | | |
| | | <Layout> |
| | | <DyForm |
| | | labelWidth="100px" |
| | | labelPosition="left" |
| | | ref='formRef' |
| | | v-model:formData="formData" |
| | | :formItemProps="formItemProps" |
| | | :inLine="false" |
| | | /> |
| | | <el-button @click="valid" type='primary'>æäº¤</el-button> |
| | | </Layout> |
| | | |
| | | <script setup> |
| | | import { ref, h } from 'vue' |
| | | import DyForm from '@/components/DyForm/DyForm.tsx' |
| | | |
| | | const formRef = ref() |
| | | const formData = ref({}) |
| | | const formItemProps = ref([ |
| | | { |
| | | label: 'å§å', |
| | | prop: 'name', |
| | | el: 'input', |
| | | placeholder: '请è¾å
¥å§å', |
| | | rules: [{ required: true, message: 'å§å', trigger: 'blur' }], |
| | | }, |
| | | { |
| | | label: 'ç¼ç ', |
| | | prop: 'code', |
| | | el: 'input', |
| | | placeholder: '请è¾å
¥ç¼ç ', |
| | | rules: [ |
| | | { required: true, message: 'ä¸è½ä¸ºç©ºæç©ºç½å符ï¼', trigger: 'blur' }, |
| | | ], |
| | | }, |
| | | { |
| | | label: 'å°å', |
| | | prop: 'addr', |
| | | el: 'select', |
| | | placeholder: 'è¯·éæ©', |
| | | options: [{ |
| | | label: '广ä¸', |
| | | value: '222' |
| | | }] |
| | | }, |
| | | { |
| | | label: 'å
¬å¸', |
| | | prop: 'company', |
| | | el: (props, {attrs}) => h('div', null, 'çåæ'), |
| | | } |
| | | ]) |
| | | |
| | | const handleUpdateFormData = (data) => { |
| | | console.log('è¡¨åæ°æ®å·²æ´æ°:', data) |
| | | } |
| | | |
| | | const valid = () => { |
| | | formRef.value?.validate() |
| | | } |
| | | |
| | | // 坿 ¹æ®éè¦è®¾ç½® formData å formItemProps |
| | | </script> |
| | | |
| | | ```vue |
| | | <template> |
| | | <Layout> |
| | | <DyForm |
| | | labelWidth="100px" |
| | | labelPosition="left" |
| | | ref="formRef" |
| | | v-model:formData="formData" |
| | | :formItemProps="formItemProps" |
| | | :inLine="false" |
| | | /> |
| | | <el-button @click="valid" type="primary">æäº¤</el-button> |
| | | /> |
| | | </Layout> |
| | | </template> |
| | | |
| | | <script setup> |
| | | import { ref } from 'vue' |
| | | import DyForm from '@/components/DyForm/DyForm.tsx' |
| | | |
| | | const formRef = ref() |
| | | const formData = ref({}) |
| | | const formItemProps = ref([ |
| | | { |
| | | label: 'å§å', |
| | | prop: 'name', |
| | | el: 'input', |
| | | placeholder: '请è¾å
¥å§å', |
| | | rules: [{ required: true, message: 'å§å', trigger: 'blur' }], |
| | | }, |
| | | { |
| | | label: 'ç¼ç ', |
| | | prop: 'code', |
| | | el: 'input', |
| | | placeholder: '请è¾å
¥ç¼ç ', |
| | | rules: [ |
| | | { required: true, message: 'ä¸è½ä¸ºç©ºæç©ºç½å符ï¼', trigger: 'blur' }, |
| | | ], |
| | | }, |
| | | { |
| | | label: 'å°å', |
| | | prop: 'addr', |
| | | el: 'select', |
| | | placeholder: 'è¯·éæ©', |
| | | options: [{ |
| | | label: 'xxx' |
| | | value: '222' |
| | | }] |
| | | |
| | | }, |
| | | ]) |
| | | |
| | | const handleUpdateFormData = (data) => { |
| | | console.log('è¡¨åæ°æ®å·²æ´æ°:', data) |
| | | } |
| | | |
| | | const valid = () => { |
| | | formRef.value?.validate() |
| | | } |
| | | </script> |
| | | ``` |
| | | |
| | | å¨è¯¥ç¤ºä¾ä¸ï¼`DyForm` ç»ä»¶è¢«ä½¿ç¨ï¼å¹¶éè¿å±æ§ä¼ éäºè¡¨åæ°æ®å¯¹è±¡ `formData` å表å项é
ç½®æ°ç» `formItemProps`ãå½è¡¨åæ°æ®å¯¹è±¡åçæ¹åæ¶ï¼è§¦å `update:formData` äºä»¶ï¼è°ç¨ `handleUpdateFormData` æ¹æ³æ´æ°è¡¨åæ°æ®ã |
| | | |
| | | ## 屿§ |
| | | |
| | | | 屿§å | ç±»å | é»è®¤å¼ | å¿
å¡« | æè¿° | |
| | | | ------------- | ------- | ------- | ---- | ------------------ | |
| | | | labelWidth | String | '100px' | å¦ | 表å项æ ç¾å®½åº¦ | |
| | | | labelPosition | String | 'left' | å¦ | 表å项æ ç¾ä½ç½® | |
| | | | formData | Object | {} | å¦ | è¡¨åæ°æ®å¯¹è±¡ | |
| | | | formItemProps | Array | [] | å¦ | 表å项é
ç½®æ°ç» | |
| | | | inLine | Boolean | false | å¦ | æ¯å¦ä¸ºè¡å
表åå¸å± | |
| | | |
| | | ## 表å项é
ç½®å±æ§ï¼formItemPropsï¼ |
| | | |
| | | | 屿§å | ç±»å | é»è®¤å¼ | å¿
å¡« | æè¿° | |
| | | | --------- | ------------------- | ------ | ---- | -------------------------------------------- | |
| | | | el | String or Component | - | æ¯ | 表å项类åï¼æ¯æé¢è®¾çå符串类åæèªå®ä¹ç»ä»¶ | |
| | | | prop | String | - | æ¯ | 表åé¡¹æ°æ®å¯¹è±¡ä¸ç屿§å | |
| | | | label | String | - | å¦ | 表å项æ ç¾æå | |
| | | | rules | Array | [] | å¦ | 表å项éªè¯è§å | |
| | | | width | String | - | å¦ | 表å项宽度 | |
| | | | height | String | - | å¦ | 表å项é«åº¦ | |
| | | | labelIcon | String | - | å¦ | 表å项æ ç¾å¾æ | |
| | | | options | Array | [] | å¦ | é项类å表å项çé项æ°ç» | |
| | | | isHide | Boolean | false | å¦ | æ¯å¦éè表å项 | |
| | | | isTitle | Boolean | false | å¦ | æ¯å¦ä¸ºæ é¢ | |
| | | | title | String or Component | - | å¦ | æ é¢å
容ï¼ä»
å½ isTitle 为 true æ¶çæ | |
| | | |
| | | ## æ¹æ³ |
| | | |
| | | | æ¹æ³å | åæ° | è¿åå¼ | æè¿° | |
| | | | --------- | ---- | ------- | ---------------------- | |
| | | | validate | - | Promise | éªè¯è¡¨å项æ¯å¦éè¿éªè¯ | |
| | | | resetForm | - | - | é置表å项çå¼ | |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | # Empty ç©ºæ°æ®ç»ä»¶ |
| | | |
| | | 该ç»ä»¶ç¨äºå¨é¡µé¢ä¸å±ç¤ºææ æ°æ®çæç¤ºä¿¡æ¯ã |
| | | |
| | | ## 屿§ |
| | | |
| | | | 屿§å | ç±»å | é»è®¤å¼ | å¿
å¡« | æè¿° | |
| | | | ------ | ------ | ---------- | ---- | ------------ | |
| | | | text | String | 'ææ æ°æ®' | å¦ | æç¤ºä¿¡æ¯ææ¬ | |
| | | |
| | | ## ç¤ºä¾ |
| | | |
| | | <Empty text="ææ æ°æ®ï¼è¯·ç¨ååè¯" /> |
| | | |
| | | <script setup> |
| | | import Empty from '@/components/Empty/Empty.tsx' |
| | | </script> |
| | | |
| | | ```vue |
| | | <template> |
| | | <Empty text="ææ æ°æ®ï¼è¯·ç¨ååè¯" /> |
| | | </template> |
| | | |
| | | <script setup> |
| | | import Empty from '@/components/Empty/Empty.tsx' |
| | | </script> |
| | | ``` |
| | | |
| | | å¨è¯¥ç¤ºä¾ä¸ï¼`Empty` ç»ä»¶è¢«ä½¿ç¨ï¼å¹¶éè¿å±æ§è®¾ç½®äºæç¤ºä¿¡æ¯ææ¬ä¸º "ææ æ°æ®ï¼è¯·ç¨ååè¯"ã |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | # Flow æµç¨æ¾ç¤ºæ ç¾ç»ä»¶ |
| | | |
| | | 该ç»ä»¶ç¨äºæ¾ç¤ºæµç¨æ ç¾ï¼æ¯ææ ¹æ®ä¼ å
¥çæ°æ®æ¸²ææ ç¾ã |
| | | |
| | | ## 屿§ |
| | | |
| | | | 屿§å | ç±»å | é»è®¤å¼ | å¿
å¡« | æè¿° | |
| | | | ---------- | ------- | ------ | ---- | ------------ | |
| | | | modelValue | Array | [] | å¦ | æµç¨æ°æ®æ°ç» | |
| | | | disabled | Boolean | false | å¦ | æ¯å¦ç¦ç¨ç»ä»¶ | |
| | | |
| | | ## äºä»¶ |
| | | |
| | | | äºä»¶å | åæ° | æè¿° | |
| | | | ------ | ---- | ---------------- | |
| | | | click | - | å½ç¹å»æ ç¾æ¶è§¦å | |
| | | |
| | | ## ç¤ºä¾ |
| | | |
| | | <Layout> |
| | | <Flow v-model="flowData" :disabled="isDisabled" @click="handleClick" /> |
| | | </Layout> |
| | | |
| | | <script setup> |
| | | import { ref } from 'vue' |
| | | import Flow from '@/components/Flow/Flow.tsx' |
| | | |
| | | const flowData = ref([ |
| | | { name: 'æµç¨1', description: 'è¿æ¯æµç¨1' }, |
| | | { name: 'æµç¨2', description: 'è¿æ¯æµç¨2' }, |
| | | { name: 'æµç¨3', description: 'è¿æ¯æµç¨3' }, |
| | | ]) |
| | | const isDisabled = ref(false) |
| | | |
| | | const handleClick = () => { |
| | | console.log('ç¹å»äºæµç¨æ ç¾') |
| | | } |
| | | </script> |
| | | |
| | | ```vue |
| | | <template> |
| | | <Flow v-model="flowData" :disabled="isDisabled" @click="handleClick" /> |
| | | </template> |
| | | |
| | | <script setup> |
| | | import Flow from '@/components/Flow/Flow.tsx' |
| | | |
| | | const flowData = ref([ |
| | | { name: 'æµç¨1', description: 'è¿æ¯æµç¨1' }, |
| | | { name: 'æµç¨2', description: 'è¿æ¯æµç¨2' }, |
| | | { name: 'æµç¨3', description: 'è¿æ¯æµç¨3' }, |
| | | ]) |
| | | const isDisabled = ref(false) |
| | | |
| | | const handleClick = () => { |
| | | console.log('ç¹å»äºæµç¨æ ç¾') |
| | | } |
| | | </script> |
| | | ``` |
| | | |
| | | å¨è¯¥ç¤ºä¾ä¸ï¼`Flow` ç»ä»¶è¢«ä½¿ç¨ï¼å¹¶éè¿å±æ§ä¼ éäºæµç¨æ°æ®æ°ç» `flowData` åç¦ç¨ç¶æ `isDisabled`ãå½ç¹å»æ ç¾æ¶ï¼è§¦å `click` äºä»¶ï¼è°ç¨ `handleClick` æ¹æ³ã |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | # Icon 徿 ç»ä»¶ |
| | | |
| | | 该ç»ä»¶ç¨äºæ¾ç¤ºå¾æ ï¼æ¯æèªå®ä¹å¾æ åç§°ã宽度åé«åº¦ï¼å¹¶å¯ä»¥ååºç¹å»äºä»¶ã |
| | | |
| | | ## ç¤ºä¾ |
| | | |
| | | <Layout> |
| | | <div style=" |
| | | display: flex; |
| | | justify-content: flex-start; |
| | | align-items: center; |
| | | flex-wrap: wrap; |
| | | "> |
| | | <span |
| | | :title="name" |
| | | style=" |
| | | flex-shrink: 0; |
| | | margin-right: 10px; |
| | | cursor: pointer; |
| | | display: flex; |
| | | justify-content: space-between; |
| | | padding: 20px 0; |
| | | align-items: center; |
| | | flex-direction: column; |
| | | width: 100px; |
| | | height: 100px; |
| | | overflow:hidden; |
| | | " |
| | | v-for="name in icons" |
| | | class='hover' |
| | | @click="() => handleClick(name)" |
| | | :key="name"> |
| | | <Icon :icon="name" :width="20" :height="20" /> |
| | | <span>{{name}}</span> |
| | | </span> |
| | | </div> |
| | | |
| | | </Layout> |
| | | |
| | | <script setup> |
| | | import { ref } from 'vue' |
| | | import Icon from '@/components/Icon/Icon.tsx' |
| | | const iconMap = import.meta.glob('../../src/assets/images/*.png', { |
| | | eager: true, |
| | | }) |
| | | const icons = ref([]) |
| | | |
| | | const extractFileNameWithoutExtension = (filePath) => { |
| | | const parts = filePath.split('/') |
| | | const fileNameWithExtension = parts[parts.length - 1] |
| | | const fileNameParts = fileNameWithExtension.split('.') |
| | | return fileNameParts[0] |
| | | } |
| | | const fallbackCopyTextToClipboard = (text) => { |
| | | var textArea = document.createElement("textarea"); |
| | | textArea.value = text; |
| | | |
| | | // Avoid scrolling to bottom |
| | | textArea.style.top = "0"; |
| | | textArea.style.left = "0"; |
| | | textArea.style.position = "fixed"; |
| | | |
| | | document.body.appendChild(textArea); |
| | | textArea.focus(); |
| | | textArea.select(); |
| | | |
| | | try { |
| | | var successful = document.execCommand('copy'); |
| | | var msg = successful ? 'successful' : 'unsuccessful'; |
| | | console.log('Fallback: Copying text command was ' + msg); |
| | | } catch (err) { |
| | | console.error('Fallback: Oops, unable to copy', err); |
| | | } |
| | | |
| | | document.body.removeChild(textArea); |
| | | } |
| | | const copyTextToClipboard = (text) => { |
| | | if (!navigator.clipboard) { |
| | | fallbackCopyTextToClipboard(text); |
| | | return; |
| | | } |
| | | navigator.clipboard.writeText(text).then(() => { |
| | | console.log('å¤å¶æå'); |
| | | }, function(err) { |
| | | console.error('å¤å¶å¤±è´¥', err); |
| | | }); |
| | | } |
| | | Object.entries(iconMap).forEach(([key, v]) => { |
| | | const name = extractFileNameWithoutExtension(key) |
| | | icons.value.push(name) |
| | | }) |
| | | const handleClick = (name) => { |
| | | copyTextToClipboard(`<Icon :icon="${name}" :width="24" :height="24" />`) |
| | | alert('å¤å¶æå') |
| | | } |
| | | </script> |
| | | |
| | | ```vue |
| | | <template> |
| | | <Icon icon="logo" width="24" height="24" @click="handleClick" /> |
| | | </template> |
| | | |
| | | <script setup> |
| | | import Icon from '@/components/Icon/Icon.tsx' |
| | | |
| | | const handleClick = (evt) => { |
| | | console.log('ç¹å»äºå¾æ ') |
| | | } |
| | | </script> |
| | | ``` |
| | | |
| | | å¨è¯¥ç¤ºä¾ä¸ï¼`Icon` ç»ä»¶è¢«ä½¿ç¨ï¼å¹¶éè¿å±æ§è®¾ç½®äºå¾æ å称为 "logo"ï¼å®½åº¦ä¸º 24ï¼é«åº¦ä¸º 24ãå½ç¹å»å¾æ æ¶ï¼è§¦å `click` äºä»¶ï¼è°ç¨ `handleClick` æ¹æ³ã |
| | | |
| | | ## 屿§ |
| | | |
| | | | 屿§å | ç±»å | é»è®¤å¼ | å¿
å¡« | æè¿° | |
| | | | ------ | ------ | ------ | ---- | -------- | |
| | | | icon | String | '' | å¦ | 徿 åç§° | |
| | | | width | Number | 12 | å¦ | 徿 宽度 | |
| | | | height | Number | 12 | å¦ | 徿 é«åº¦ | |
| | | |
| | | ## äºä»¶ |
| | | |
| | | | äºä»¶å | åæ° | æè¿° | |
| | | | ------ | ----- | ---------------- | |
| | | | click | Event | å½ç¹å»å¾æ æ¶è§¦å | |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | # IconButton 徿 æé®ç»ä»¶ |
| | | |
| | | 该ç»ä»¶ç¨äºæ¾ç¤ºå¸¦å¾æ çæé®ï¼æ¯æèªå®ä¹å¾æ ãæé®ç±»åãå¼¹åºæ¡å®½åº¦ç屿§ï¼å¹¶å¯ä»¥ååºç¹å»äºä»¶ã |
| | | |
| | | <Layout> |
| | | <IconButton icon="search" type="primary" @click="handleClick"> |
| | | <template #content> |
| | | å
容 |
| | | </template> |
| | | åç» |
| | | </IconButton> |
| | | |
| | | <IconButton icon="g"> |
| | | å
容 |
| | | </IconButton> |
| | | </Layout> |
| | | |
| | | <script setup> |
| | | import IconButton from '@/components/IconButton/IconButton.tsx' |
| | | |
| | | const handleClick = (evt) => { |
| | | console.log('ç¹å»äºå¾æ æé®') |
| | | } |
| | | </script> |
| | | |
| | | ## ç¤ºä¾ |
| | | |
| | | ```vue |
| | | <template> |
| | | <IconButton icon="search" type="primary" @click="handleClick"> |
| | | <template #content> å
容 </template> |
| | | æç´¢ |
| | | </IconButton> |
| | | <IconButton icon="g"> åç» </IconButton> |
| | | </template> |
| | | |
| | | <script setup> |
| | | import IconButton from '@/components/IconButton/IconButton.tsx' |
| | | |
| | | const handleClick = (evt) => { |
| | | console.log('ç¹å»äºå¾æ æé®') |
| | | } |
| | | </script> |
| | | ``` |
| | | |
| | | å¨è¯¥ç¤ºä¾ä¸ï¼`IconButton` ç»ä»¶è¢«ä½¿ç¨ï¼å¹¶éè¿å±æ§è®¾ç½®äºå¾æ å称为 "search"ï¼æé®ç±»å为 "primary"ãå½ç¹å»æé®æ¶ï¼è§¦å `click` äºä»¶ï¼è°ç¨ `handleClick` æ¹æ³ã |
| | | |
| | | ## 屿§ |
| | | |
| | | | 屿§å | ç±»å | é»è®¤å¼ | å¿
å¡« | æè¿° | |
| | | | ------------ | ------ | ------ | ---- | ------------ | |
| | | | icon | String | - | å¦ | 徿 åç§° | |
| | | | type | String | - | å¦ | æé®ç±»å | |
| | | | popoverWidth | Number | - | å¦ | å¼¹åºæ¡å®½åº¦ | |
| | | | content | slots | - | å¦ | å¼¹çª | |
| | | | å
¶ä» | any | - | å¦ | å
¶ä»æé®å±æ§ | |
| | | |
| | | ## äºä»¶ |
| | | |
| | | | äºä»¶å | åæ° | æè¿° | |
| | | | ------ | ----- | ---------------- | |
| | | | click | Event | å½ç¹å»æé®æ¶è§¦å | |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | # PDFViewer ç»ä»¶ |
| | | |
| | | 该ç»ä»¶ç¨äºæ¾ç¤º PDF æä»¶çé¢è§ãæ¯æå¨å¯¹è¯æ¡ä¸å±ç¤º PDF æä»¶å
容ï¼å¹¶æä¾å
³éå确认åè½ã |
| | | |
| | | ## ç¤ºä¾ |
| | | |
| | | <Layout> |
| | | <el-button type='primary' @click="showDialog = true">pdfå¼¹çª </el-button> |
| | | <PDFViewer v-model="showDialog" pdfSrc="/path/to/pdf/file.pdf" /> |
| | | </Layout> |
| | | |
| | | <script setup> |
| | | import PDFViewer from '@/components/Pdf/index.vue' |
| | | import { ref } from 'vue' |
| | | |
| | | const showDialog = ref(false) |
| | | </script> |
| | | |
| | | ```vue |
| | | <template> |
| | | <PDFViewer :v-model="showDialog" pdfSrc="/path/to/pdf/file.pdf" /> |
| | | </template> |
| | | |
| | | <script setup> |
| | | import PDFViewer from '@/components/Pdf/index.vue' |
| | | import { ref } from 'vue' |
| | | |
| | | const showDialog = ref(false) |
| | | </script> |
| | | ``` |
| | | |
| | | å¨è¯¥ç¤ºä¾ä¸ï¼`PDFViewer` ç»ä»¶è¢«ä½¿ç¨ï¼å¹¶ä¼ éäº `modelValue` æ§å¶å¯¹è¯æ¡çæ¾ç¤ºç¶æï¼ä»¥å `pdfSrc` 屿§æå® PDF æä»¶çè·¯å¾ã |
| | | |
| | | ## 屿§ |
| | | |
| | | | 屿§å | ç±»å | é»è®¤å¼ | å¿
å¡« | æè¿° | |
| | | | ---------- | ------- | ------ | ---- | -------------- | |
| | | | modelValue | Boolean | - | æ¯ | æ§å¶å¯¹è¯æ¡æ¾ç¤º | |
| | | | pdfSrc | String | - | æ¯ | PDF æä»¶çè·¯å¾ | |
| | | |
| | | ## äºä»¶ |
| | | |
| | | | äºä»¶å | åæ° | æè¿° | |
| | | | ----------------- | ------- | ------------------ | |
| | | | update:modelValue | Boolean | æ´æ°å¯¹è¯æ¡æ¾ç¤ºç¶æ | |
| | | | close | - | å
³éå¯¹è¯æ¡æ¶è§¦å | |
| | | | confirm | - | 确认æä½æ¶è§¦å | |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | # PreviewDialog é¢è§å¯¹è¯æ¡ç»ä»¶ |
| | | |
| | | 该ç»ä»¶ç¨äºæ¾ç¤ºé¢è§å
å®¹ï¼æ¯æå¨å¯¹è¯æ¡ä¸å±ç¤ºæå® URL çå
容ï¼å¹¶æä¾å
³éåè½ã |
| | | |
| | | ## ç¤ºä¾ |
| | | |
| | | <Layout> |
| | | <el-button type='primary' @click="showDialog = true">å¼¹çª </el-button> |
| | | <PreviewDialog v-model="showDialog" url="https://www.shengyc.com/" /> |
| | | </Layout> |
| | | |
| | | <script setup> |
| | | import PreviewDialog from '@/components/PreviewDialog/index.vue' |
| | | import { ref } from 'vue' |
| | | |
| | | const showDialog = ref(false) |
| | | </script> |
| | | |
| | | ```vue |
| | | <template> |
| | | <PreviewDialog v-model="showDialog" url="https://www.shengyc.com/" /> |
| | | </template> |
| | | |
| | | <script setup> |
| | | import PreviewDialog from '@/components/PreviewDialog/index.vue' |
| | | import { ref } from 'vue' |
| | | |
| | | const showDialog = ref(false) |
| | | </script> |
| | | ``` |
| | | |
| | | å¨è¯¥ç¤ºä¾ä¸ï¼`PreviewDialog` ç»ä»¶è¢«ä½¿ç¨ï¼å¹¶ä¼ éäº `modelValue` æ§å¶å¯¹è¯æ¡çæ¾ç¤ºç¶æï¼ä»¥å `url` 屿§æå®é¢è§å
容ç URLã |
| | | |
| | | ## 屿§ |
| | | |
| | | | 屿§å | ç±»å | é»è®¤å¼ | å¿
å¡« | æè¿° | |
| | | | -------------- | ------- | ---------------------- | ---- | ------------------------------ | |
| | | | modelValue | Boolean | - | æ¯ | æ§å¶å¯¹è¯æ¡æ¾ç¤º | |
| | | | url | String | 'http://www.baidu.com' | å¦ | é¢è§å
容ç URL | |
| | | | append-to-body | Boolean | true | å¦ | æ¯å¦å°å¯¹è¯æ¡æå
¥å° body å
ç´ å
| |
| | | | width | Number | 1200 | å¦ | å¯¹è¯æ¡å®½åº¦ | |
| | | | show-close | Boolean | true | å¦ | æ¯å¦æ¾ç¤ºå
³éæé® | |
| | | |
| | | ## äºä»¶ |
| | | |
| | | | äºä»¶å | åæ° | æè¿° | |
| | | | ----------------- | ------- | ------------------ | |
| | | | update:modelValue | Boolean | æ´æ°å¯¹è¯æ¡æ¾ç¤ºç¶æ | |
| | | | close | - | å
³éå¯¹è¯æ¡æ¶è§¦å | |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | # Search æç´¢è¾å
¥ç»ä»¶ |
| | | |
| | | 该ç»ä»¶ç¨äºå±ç¤ºä¸ä¸ªæç´¢è¾å
¥æ¡ï¼æ¯æç¨æ·è¾å
¥å
³é®åè¿è¡æç´¢ï¼å¹¶æä¾ç¡®è®¤æç´¢åè½ã |
| | | |
| | | ## ç¤ºä¾ |
| | | |
| | | <Layout> |
| | | <Search v-model="searchValue" placeholder="æç´¢å
容" :tableRef="tableRef" field="Name" @confirm="handleSearch" /> |
| | | </Layout> |
| | | |
| | | <script setup> |
| | | import Search from '@/components/Search/Search.tsx' |
| | | import { ref } from 'vue' |
| | | |
| | | const searchValue = ref('') |
| | | const tableRef = ref(null) |
| | | |
| | | const handleSearch = (value) => { |
| | | console.log('ç¨æ·æç´¢:', value) |
| | | // æ§è¡æç´¢æä½ |
| | | // æ¤å¤æ¼ç¤º |
| | | if (tableRef.value) { |
| | | tableRef.value.getList({ Name: value }) |
| | | } |
| | | } |
| | | </script> |
| | | |
| | | ```vue |
| | | <template> |
| | | <Search |
| | | :modelValue="searchValue" |
| | | placeholder="æç´¢å
容" |
| | | :tableRef="tableRef" |
| | | field="Name" |
| | | @confirm="handleSearch" |
| | | /> |
| | | </template> |
| | | |
| | | <script setup> |
| | | import Search from '@/components/Search/Search.tsx' |
| | | import { ref } from 'vue' |
| | | |
| | | const searchValue = ref('') |
| | | const tableRef = ref(null) |
| | | |
| | | const handleSearch = (value) => { |
| | | console.log('ç¨æ·æç´¢:', value) |
| | | // æ§è¡æç´¢æä½ |
| | | // æ¤å¤æ¼ç¤º |
| | | if (tableRef.value) { |
| | | tableRef.value.getList({ Name: value }) |
| | | } |
| | | } |
| | | </script> |
| | | ``` |
| | | |
| | | å¨è¯¥ç¤ºä¾ä¸ï¼`Search` ç»ä»¶è¢«ä½¿ç¨ï¼å¹¶éè¿å±æ§ä¼ éäºæç´¢æ¡çå ä½ç¬¦ãè¡¨æ ¼çå¼ç¨ä»¥åæ§è¡æç´¢æä½æ¶æå®çåæ®µåãå½ç¨æ·ç¡®è®¤æç´¢æ¶ï¼`confirm` äºä»¶è¢«è§¦åï¼è°ç¨ `handleSearch` æ¹æ³æ§è¡æç´¢æä½ã |
| | | |
| | | ## 屿§ |
| | | |
| | | | 屿§å | ç±»å | é»è®¤å¼ | å¿
å¡« | æè¿° | |
| | | | ----------- | ------ | ------------ | ---- | ---------------------------- | |
| | | | placeholder | String | '请è¾å
¥æç´¢' | å¦ | æç´¢è¾å
¥æ¡çå ä½ç¬¦ | |
| | | | modelValue | String | '' | å¦ | æç´¢è¾å
¥æ¡çå¼ | |
| | | | tableRef | Object | null | å¦ | è¡¨æ ¼çå¼ç¨ï¼ç¨äºæ§è¡æç´¢æä½ | |
| | | | field | String | '' | å¦ | æ§è¡æç´¢æä½æ¶æå®çåæ®µå | |
| | | |
| | | ## äºä»¶ |
| | | |
| | | | äºä»¶å | åæ° | æè¿° | |
| | | | ------- | ------ | ------------------------------------ | |
| | | | confirm | string | ç¨æ·ç¡®è®¤æç´¢æ¶è§¦åï¼åæ°ä¸ºæç´¢å
³é®å | |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | # SelectInput éæ©è¾å
¥ç»ä»¶ |
| | | |
| | | 该ç»ä»¶ç¨äºå±ç¤ºä¸ä¸ªå¸¦æéæ©æé®çè¾å
¥æ¡ï¼åæ¶å¯ä»¥å±ç¤ºéæ©çæ ç¾ã |
| | | |
| | | ## ç¤ºä¾ |
| | | |
| | | <Layout> |
| | | <SelectInput v-model="selectedValues" @click="handleClick" /> |
| | | </Layout> |
| | | |
| | | <script setup> |
| | | import SelectInput from '@/components/SelectInput/SelectInput.tsx' |
| | | import { ref } from 'vue' |
| | | |
| | | const selectedValues = ref([]) |
| | | |
| | | const handleClick = () => { |
| | | // å¤çç¹å»éæ©æé®çé»è¾ |
| | | } |
| | | </script> |
| | | |
| | | ```vue |
| | | <template> |
| | | <SelectInput v-model="selectedValues" @click="handleClick" /> |
| | | </template> |
| | | |
| | | <script setup> |
| | | import SelectInput from '@/components/SelectInput/SelectInput.tsx' |
| | | import { ref } from 'vue' |
| | | |
| | | const selectedValues = ref([]) |
| | | |
| | | const handleClick = () => { |
| | | // å¤çç¹å»éæ©æé®çé»è¾ |
| | | } |
| | | </script> |
| | | ``` |
| | | |
| | | å¨è¯¥ç¤ºä¾ä¸ï¼`SelectInput` ç»ä»¶è¢«ä½¿ç¨ï¼å¹¶éè¿ `v-model` ååç»å®äºéæ©è¾å
¥æ¡çå¼ãå½ç¹å»éæ©æé®æ¶ï¼ä¼è§¦å `click` äºä»¶ï¼è°ç¨ `handleClick` æ¹æ³å¤çç¹å»äºä»¶ã |
| | | |
| | | ## 屿§ |
| | | |
| | | | 屿§å | ç±»å | é»è®¤å¼ | å¿
å¡« | æè¿° | |
| | | | ---------- | ----- | ------ | ---- | -------------- | |
| | | | modelValue | Array | [] | å¦ | éæ©è¾å
¥æ¡çå¼ | |
| | | |
| | | ## äºä»¶ |
| | | |
| | | | äºä»¶å | åæ° | æè¿° | |
| | | | ----------------- | ----- | ------------------------ | |
| | | | click | - | ç¹å»éæ©æé®æ¶è§¦å | |
| | | | update:modelValue | Array | æ´æ°éæ©è¾å
¥æ¡ç弿¶è§¦å | |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | # Tab æ ç¾é¡µç»ä»¶ |
| | | |
| | | ## 该ç»ä»¶ç¨äºå±ç¤ºå¤ä¸ªæ ç¾é¡µï¼å¹¶æ¯æåæ¢æ ç¾é¡µåè½ã |
| | | |
| | | ## ç¤ºä¾ 1 |
| | | |
| | | <Layout> |
| | | <Tab :data="tabData" v-model:active="activeTab" size="small" @tab="handleTabChange"> |
| | | <TabPane v-for="item in tabData" :key="item.name" :name="item.name" :label="item.label"> |
| | | <component :is="item.component"/> |
| | | </TabPane> |
| | | </Tab> |
| | | </Layout> |
| | | |
| | | <script setup> |
| | | import Tab from '@/components/Tab/Tab.tsx' |
| | | import TabPane from '@/components/Tab/TabPane.tsx' |
| | | import { ref, h } from 'vue' |
| | | |
| | | const activeTab = ref('') |
| | | const tabData = ref([ |
| | | { name: 'tab1', label: 'æ ç¾é¡µ1', component: h('div', null, '1') }, |
| | | { name: 'tab2', label: 'æ ç¾é¡µ2', component: h('div', null, '2') }, |
| | | { name: 'tab3', label: 'æ ç¾é¡µ3', component: h('div', null, '3') }, |
| | | ]) |
| | | |
| | | const handleTabChange = (tabName) => { |
| | | activeTab.value = tabName |
| | | } |
| | | </script> |
| | | |
| | | ```vue |
| | | <template> |
| | | <Tab |
| | | :data="tabData" |
| | | v-model:active="activeTab" |
| | | size="small" |
| | | @tab="handleTabChange" |
| | | > |
| | | <template #default> |
| | | <TabPane |
| | | v-for="item in tabData" |
| | | :key="item.name" |
| | | :name="item.name" |
| | | :label="item.label" |
| | | > |
| | | <item.component /> |
| | | </TabPane> |
| | | </template> |
| | | </Tab> |
| | | </template> |
| | | |
| | | <script setup> |
| | | import Tab from '@/components/Tab/Tab.tsx' |
| | | import TabPane from '@/components/Tab/TabPane.tsx' |
| | | import { ref, h } from 'vue' |
| | | |
| | | const activeTab = ref('') |
| | | const tabData = ref([ |
| | | { name: 'tab1', label: 'æ ç¾é¡µ1', component: h('div', null, '1') }, |
| | | { name: 'tab2', label: 'æ ç¾é¡µ2', component: h('div', null, '2') }, |
| | | { name: 'tab3', label: 'æ ç¾é¡µ3', component: h('div', null, '3') }, |
| | | ]) |
| | | |
| | | const handleTabChange = (tabName) => { |
| | | activeTab.value = tabName |
| | | } |
| | | </script> |
| | | ``` |
| | | |
| | | ## ç¤ºä¾ 2 |
| | | |
| | | <Layout> |
| | | <Tab :data="tabData" v-model:active="activeTab" size="small" @tab="handleTabChange"> |
| | | |
| | | </Tab> |
| | | </Layout> |
| | | |
| | | ```vue |
| | | <template> |
| | | <Tab |
| | | :data="tabData" |
| | | v-model:active="activeTab" |
| | | size="small" |
| | | @tab="handleTabChange" |
| | | ></Tab> |
| | | </template> |
| | | |
| | | <script setup> |
| | | import Tab from '@/components/Tab/Tab.tsx' |
| | | import TabPane from '@/components/Tab/TabPane.tsx' |
| | | import { ref, h } from 'vue' |
| | | |
| | | const activeTab = ref('') |
| | | const tabData = ref([ |
| | | { name: 'tab1', label: 'æ ç¾é¡µ1', component: h('div', null, '1') }, |
| | | { name: 'tab2', label: 'æ ç¾é¡µ2', component: h('div', null, '2') }, |
| | | { name: 'tab3', label: 'æ ç¾é¡µ3', component: h('div', null, '3') }, |
| | | ]) |
| | | |
| | | const handleTabChange = (tabName) => { |
| | | activeTab.value = tabName |
| | | } |
| | | </script> |
| | | ``` |
| | | |
| | | å¨è¯¥ç¤ºä¾ä¸ï¼`Tab` ç»ä»¶ç¨äºå±ç¤ºå¤ä¸ªæ ç¾é¡µï¼éè¿ `data` 屿§ä¼ å
¥æ ç¾é¡µçæ°æ®æ°ç»ï¼éè¿ `v-model:active` å®ç°å¯¹å½åæ¿æ´»æ ç¾é¡µçæ§å¶ãæ ç¾é¡µçå
容éè¿é»è®¤ææ§½ä¼ å
¥ï¼æ¯ä¸ªæ ç¾é¡µå¯¹åºä¸ä¸ª `TabPane` ç»ä»¶ï¼å¹¶ä¼ å
¥ç¸åºçç»ä»¶ä½ä¸ºå
容ã |
| | | |
| | | ## 屿§ |
| | | |
| | | | 屿§å | ç±»å | é»è®¤å¼ | å¿
å¡« | æè¿° | |
| | | | ------ | ------------- | ------ | ---- | -------------------------- | |
| | | | data | Array | [] | å¦ | æ ç¾é¡µæ°æ®æ°ç» | |
| | | | size | String | '' | å¦ | æ ç¾é¡µå°ºå¯¸ | |
| | | | active | String/Number | '' | å¦ | å½åæ¿æ´»çæ ç¾é¡µåç§°æç´¢å¼ | |
| | | | type | String | 'list' | å¦ | æ ç¾é¡µç±»å | |
| | | |
| | | ## äºä»¶ |
| | | |
| | | | äºä»¶å | åæ° | æè¿° | |
| | | | ------ | ------ | ------------------------------------ | |
| | | | tab | String | 忢æ ç¾é¡µæ¶è§¦åï¼åæ°ä¸ºæ ç¾é¡µçåç§° | |
| | | |
| | | ## ææ§½ |
| | | |
| | | | åç§° | æè¿° | |
| | | | ---- | ---------- | |
| | | | é»è®¤ | æ ç¾é¡µå
容 | |
| | | |
| | | ## TabPane æ ç¾é¡µç»ä»¶ |
| | | |
| | | 该ç»ä»¶ç¨äºå®ä¹å个æ ç¾é¡µã |
| | | |
| | | ## 屿§ |
| | | |
| | | | 屿§å | ç±»å | é»è®¤å¼ | å¿
å¡« | æè¿° | |
| | | | ------ | ------ | ------ | ---- | ---------- | |
| | | | label | String | - | æ¯ | æ ç¾é¡µæ é¢ | |
| | | | name | String | - | æ¯ | æ ç¾é¡µåç§° | |
| | | | ... | - | - | - | å
¶ä»å±æ§ | |
| | | |
| | | ## ææ§½ |
| | | |
| | | | åç§° | æè¿° | |
| | | | ---- | ---------- | |
| | | | é»è®¤ | æ ç¾é¡µå
容 | |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | æ±æï¼ä»¥ä¸æ¯æ¨æä¾çç»ä»¶ä»£ç çææ¡£ï¼ |
| | | |
| | | # Table ç»ä»¶ |
| | | |
| | | ## æè¿° |
| | | |
| | | 该ç»ä»¶ç¨äºå±ç¤ºæ°æ®è¡¨æ ¼ï¼å¹¶æä¾äºä¸ç³»ååè½ï¼å
æ¬ææ½ãå页ãæåºãå³é®èåçã |
| | | |
| | | ## 使ç¨ç¤ºä¾ |
| | | |
| | | #### ç±äº vitepress çè¡¨æ ¼æ ·å¼é®é¢ï¼å¯¼è´ç»ä»¶è¡¨æ ¼æ ·å¼å²çªï¼è¿éå°±å±ç¤ºè¡¨æ ¼ç¤ºä¾äºï¼ææªå¾æ¾ä¸å» |
| | | |
| | |  |
| | | |
| | | <!-- |
| | | ::: raw |
| | | <Layout> |
| | | |
| | | <div class="vp-raw"> |
| | | <Table |
| | | ref="tableRef" |
| | | v-model:dataSource="dataSource" |
| | | id='name' |
| | | max-height="300" |
| | | height="auto" |
| | | :columns="columns" |
| | | :contextMenu="contextMenu" |
| | | :isSort="true" |
| | | :isDrag="true" |
| | | :isCheck="true"> |
| | | </Table> |
| | | </div> |
| | | </Layout> |
| | | ::: --> |
| | | <script setup> |
| | | import { ref } from 'vue' |
| | | import Table from '@/components/Table/Table.tsx' |
| | | const tableRef = ref() |
| | | const dataSource = ref([ |
| | | { |
| | | name: 'å¼ ä¸', |
| | | age: 18, |
| | | sex: 'ç·', |
| | | }, |
| | | { |
| | | name: 'æå', |
| | | age: 19, |
| | | sex: 'ç·', |
| | | } |
| | | ]) |
| | | const columns = [{ |
| | | title: 'åºå·', |
| | | field: 'seq', |
| | | type: 'seq' |
| | | },{ |
| | | title: 'å§å', |
| | | field: 'name', |
| | | }, |
| | | { |
| | | title: 'å¹´é¾', |
| | | field: 'age', |
| | | }, |
| | | { |
| | | title: 'æ§å«', |
| | | field: 'sex', |
| | | }] |
| | | const selectedItems = ref([]) |
| | | const contextMenu = [ |
| | | { |
| | | label: '详æ
', |
| | | fn: (c) => {}, |
| | | divided: true, |
| | | icon: 'o', |
| | | }, |
| | | { |
| | | label: 'å é¤', |
| | | fn: async (c) => {}, |
| | | icon: 'close', |
| | | }, |
| | | ] |
| | | |
| | | </script> |
| | | |
| | | ```vue |
| | | <template> |
| | | <template> |
| | | <Table |
| | | ref="tableRef" |
| | | v-model:dataSource="dataSource" |
| | | id="name" |
| | | :columns="columns" |
| | | :contextMenu="contextMenu" |
| | | :isSort="true" |
| | | > |
| | | </Table> |
| | | </template> |
| | | |
| | | <script setup> |
| | | import { ref } from 'vue' |
| | | import Table from '@/components/Table/Table.tsx' |
| | | const tableRef = ref() |
| | | const dataSource = ref([ |
| | | { |
| | | name: 'å¼ ä¸', |
| | | age: 18, |
| | | sex: 'ç·', |
| | | }, |
| | | { |
| | | name: 'æå', |
| | | age: 19, |
| | | sex: 'ç·', |
| | | }, |
| | | ]) |
| | | const columns = [ |
| | | { |
| | | title: 'åºå·', |
| | | field: 'seq', |
| | | type: 'seq', |
| | | }, |
| | | { |
| | | title: 'å§å', |
| | | field: 'name', |
| | | }, |
| | | { |
| | | title: 'å¹´é¾', |
| | | field: 'age', |
| | | }, |
| | | { |
| | | title: 'æ§å«', |
| | | field: 'sex', |
| | | }, |
| | | ] |
| | | const selectedItems = ref([]) |
| | | const contextMenu = [ |
| | | { |
| | | label: '详æ
', |
| | | fn: (c) => {}, |
| | | divided: true, |
| | | icon: 'o', |
| | | }, |
| | | { |
| | | label: 'å é¤', |
| | | fn: async (c) => {}, |
| | | icon: 'close', |
| | | }, |
| | | ] |
| | | </script> |
| | | </template> |
| | | ``` |
| | | |
| | | 以䏿¯æ¥å£çææ¡£ï¼ |
| | | |
| | | ## ParamsItem æ¥å£ |
| | | |
| | | ç¨äºæè¿°è¡¨æ ¼è¯·æ±åæ°çæ°æ®ç»æã |
| | | |
| | | | åæ®µå | ç±»å | æè¿° | |
| | | | -------------- | ---------------- | ---------------- | |
| | | | Sorting | string | æåºå段 | |
| | | | SkipCount | string \| number | è·³è¿çè®°å½æ° | |
| | | | MaxResultCount | number | è¿åçæå¤§è®°å½æ° | |
| | | | å
¶ä»å段 | any | å
¶ä»èªå®ä¹åæ° | |
| | | |
| | | ## ColumnType æ¥å£ |
| | | |
| | | ç¨äºæè¿°è¡¨æ ¼åçæ°æ®ç»æã |
| | | |
| | | | åæ®µå | ç±»å | æè¿° | |
| | | | -------- | ---------------- | -------------- | |
| | | | title | string | åæ é¢ | |
| | | | field | string | ååæ®µå | |
| | | | width | string \| number | å宽度 | |
| | | | sortable | boolean | æ¯å¦å¯æåº | |
| | | | required | boolean | æ¯å¦å¿
å¡« | |
| | | | å
¶ä»å段 | any | å
¶ä»èªå®ä¹åæ° | |
| | | |
| | | ## TablePropsItemType æ¥å£ |
| | | |
| | | ç¨äºæè¿°è¡¨æ ¼ç»ä»¶ç屿§ã |
| | | |
| | | | åæ®µå | ç±»å | é»è®¤å¼ | æè¿° | |
| | | | ----------------- | ----------------- | ------ | -------------------- | |
| | | | selections | string[] | - | é¢éä¸é¡¹ç id æ°ç» | |
| | | | autoFirstClickRow | boolean | false | æ¯å¦èªå¨éä¸ç¬¬ä¸è¡ | |
| | | | params | ParamsItem | - | 请æ±åæ° | |
| | | | dataSource | any[] | [] | æ°æ®æº | |
| | | | columns | ColumnType[] | [] | åé
置项 | |
| | | | pageSize | number | - | æ¯é¡µæ¡æ° | |
| | | | total | number | - | æ»æ¡æ° | |
| | | | isHidePagination | boolean | false | æ¯å¦éèå页 | |
| | | | isChecked | boolean | - | æ¯å¦å¤é | |
| | | | isSeq | boolean | - | æ¯å¦æ¾ç¤ºåºå· | |
| | | | isSort | boolean | - | æ¯å¦æåº | |
| | | | id | string | - | æ°æ®é¡¹çå¯ä¸æ è¯å段 | |
| | | | showDarg | boolean \| string | false | æ¯å¦åºç°ææ½ | |
| | | | isDrag | boolean \| string | - | æ¯å¦ææ½ | |
| | | | disabledDrag | boolean | - | æ¯å¦ç¦ç¨ææ½ | |
| | | | height | string | - | è¡¨æ ¼é«åº¦ | |
| | | | maxHeight | string | - | è¡¨æ ¼æå¤§é«åº¦ | |
| | | | isVScroll | boolean | - | æ¯å¦å¼å¯èææ»å¨ | |
| | | | border | string \| any | - | è¾¹æ¡æ ·å¼ | |
| | | | url | string | - | æ°æ®è¯·æ±å°å | |
| | | | sortUrlTpl | string | - | æåºè¯·æ±å°åæ¨¡æ¿ | |
| | | | isFooter | boolean | - | æ¯å¦æ¾ç¤ºåºé¨ | |
| | | | gt | number | - | - | |
| | | | contextMenu | Object[] | - | å³é®èå项æ°ç» | |
| | | | rowConfig | any | - | è¡é
置项 | |
| | | | size | string | - | è¡¨æ ¼å°ºå¯¸ | |
| | | | isStop | boolean | - | æ¯å¦é»æ¢å泡 | |
| | | | å
¶ä»å段 | any | - | å
¶ä»èªå®ä¹åæ° | |
| | | |
| | | ## MenuOptionType æ¥å£ |
| | | |
| | | ç¨äºæè¿°å³é®èåéé¡¹çæ°æ®ç»æã |
| | | |
| | | | åæ®µå | ç±»å | æè¿° | |
| | | | -------- | ------ | -------- | |
| | | | zIndex | number | å±çº§ | |
| | | | minWidth | number | æå°å®½åº¦ | |
| | | | x | number | X è½´åæ | |
| | | | y | number | Y è½´åæ | |
| | | |
| | | ## contextMenuItemType æ¥å£ |
| | | |
| | | ç¨äºæè¿°å³é®èåçç¶ææ°æ®ç»æã |
| | | |
| | | | åæ®µå | ç±»å | æè¿° | |
| | | | ------- | --------------------------- | ------------------ | |
| | | | show | boolean | æ¯å¦æ¾ç¤ºå³é®èå | |
| | | | current | Record<string, any> \| null | å½åå³é®èåé¡¹æ°æ® | |
| | | | options | any | èåé项 | |
| | | |
| | | ## äºä»¶ |
| | | |
| | | | äºä»¶å | åæ° | æè¿° | |
| | | | ----------------- | ----------------------- | -------------------- | |
| | | | drag | newIndex, oldIndex, row | ææ½æåºäºä»¶ | |
| | | | check | records | éæ©äºä»¶ | |
| | | | sort | row | æåºæ¹åäºä»¶ | |
| | | | page | current | å页æ¹åäºä»¶ | |
| | | | rowClick | tableData | è¡ç¹å»äºä»¶ | |
| | | | update:dataSource | dataSource | æ´æ°æ°æ®æºäºä»¶ | |
| | | | clickFooter | - | ç¹å»åºé¨æ·»å æé®äºä»¶ | |
| | | | update | exposeMap | æ´æ°æ´é²æ¹æ³äºä»¶ | |
| | | | load | - | å è½½å®æäºä»¶ | |
| | | | beforeLoad | - | å è½½åäºä»¶ | |
| | | | reload | - | éæ°å è½½äºä»¶ | |
| | | | update:total | total | æ´æ°æ»æ°äºä»¶ | |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | çè§£äºï¼æä¼å°å±æ§ãäºä»¶çä¿¡æ¯ç¨è¡¨æ ¼çå½¢å¼å±ç¤ºåºæ¥ï¼è®©ææ¡£æ´å æ¸
æ°æè¯»ãä¸é¢æ¯æ´æ°åçææ¡£èç¨¿ï¼ |
| | | |
| | | --- |
| | | |
| | | # TableFilter è¡¨æ ¼çéç»ä»¶ææ¡£ |
| | | |
| | | ## ç®ä» |
| | | |
| | | TableFilter æ¯ä¸ä¸ªç¨äºå®ç°è¡¨æ ¼çéåè½ç Vue ç»ä»¶ãå®å¯ä»¥è®©ç¨æ·è½»æ¾å°æ·»å ãå é¤åä¿®æ¹è¡¨æ ¼ççéæ¡ä»¶ï¼æåäºç¨æ·å¯¹è¡¨æ ¼æ°æ®çæ§å¶åæä½ä½éªã |
| | | |
| | | ## ä½¿ç¨æ¹å¼ |
| | | |
| | | <Layout> |
| | | <TableFilter icon='add-p' :columns="columns" :tableRef="tableRef" > |
| | | <IconButton icon="f">ç¹æçé</IconButton> |
| | | </TableFilter> |
| | | </Layout> |
| | | |
| | | <script setup> |
| | | import TableFilter from '@/components/TableFilter/TableFilter.tsx' |
| | | import IconButton from '@/components/IconButton/IconButton.tsx' |
| | | import { ref } from 'vue' |
| | | const columns = [ |
| | | { |
| | | prop: 'name', |
| | | title: 'å§å', |
| | | el: 'input', |
| | | placeholder: '请è¾å
¥å§å', |
| | | } |
| | | ] |
| | | const tableRef = ref(null) |
| | | </script> |
| | | |
| | | ```vue |
| | | <template> |
| | | <TableFilter icon="add-p" :columns="columns" :tableRef="tableRef"> |
| | | <IconButton icon="f">ç¹æçé</IconButton> |
| | | </TableFilter> |
| | | </template> |
| | | |
| | | <script setup> |
| | | import TableFilter from '@/components/TableFilter/TableFilter.tsx' |
| | | import IconButton from '@/components/IconButton/IconButton.tsx' |
| | | import { ref } from 'vue' |
| | | const columns = [ |
| | | { |
| | | prop: 'name', |
| | | title: 'å§å', |
| | | el: 'input', |
| | | placeholder: '请è¾å
¥å§å', |
| | | }, |
| | | ] |
| | | const tableRef = ref(null) |
| | | </script> |
| | | ``` |
| | | |
| | | ## Props |
| | | |
| | | | 屿§å | ç±»å | é»è®¤å¼ | 说æ | |
| | | | -------------- | ------ | ------ | ------------ | |
| | | | columns | Array | [] | è¡¨æ ¼çåé
ç½® | |
| | | | tableRef | Object | null | è¡¨æ ¼çå¼ç¨ | |
| | | | modelValue | Object | null | å½åç»ä»¶çå¼ | |
| | | | text | String | '' | æé®ææ¬ | |
| | | | fieldMap | Object | {} | åæ®µæ å° | |
| | | | options | Array | [] | é项 | |
| | | | defaultOptions | Array | [] | é»è®¤é项 | |
| | | |
| | | ## Events |
| | | |
| | | | äºä»¶å | 说æ | |
| | | | ----------------- | ---------------- | |
| | | | update:modelValue | æ´æ°ç»ä»¶çå¼ | |
| | | | data | åéæ°æ®äºä»¶ | |
| | | | change | ç鿡件ååäºä»¶ | |
| | | |
| | | ## ææ§½ |
| | | |
| | | | åç§° | 说æ | |
| | | | ------- | ------------------------ | |
| | | | default | ç¨äºèªå®ä¹è§¦åçéçå
容 | |
| | | |
| | | ## æ¹æ³ |
| | | |
| | | | æ¹æ³å | 说æ | |
| | | | ------------- | ------------ | |
| | | | onAddFilter | æ·»å ç鿡件 | |
| | | | onReset | éç½®ç鿡件 | |
| | | | onSearchTable | æç´¢è¡¨æ ¼æ°æ® | |
| | | |
| | | ## 注æäºé¡¹ |
| | | |
| | | - éè¦æä¾åéç `columns` é
ç½®å `tableRef` å¼ç¨æè½æ£å¸¸ä½¿ç¨ç»ä»¶ã |
| | | - å¯ä»¥æ ¹æ®å
·ä½ä¸å¡éæ±ï¼éè¿ææ§½èªå®ä¹è§¦åçéçå
容ã |
| | | |
| | | --- |
| | | |
| | | è¿æ ·çè¡¨æ ¼å½¢å¼æ´å ç´è§ï¼æ¹ä¾¿ç¨æ·æ¥é
ç»ä»¶ç屿§ãäºä»¶åæ¹æ³ã |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | # Tag æ ç¾ç»ä»¶ææ¡£ |
| | | |
| | | ## ç®ä» |
| | | |
| | | Tag æ¯ä¸ä¸ªç¨äºæ¾ç¤ºæ ç¾æè
䏿鿩ç Vue ç»ä»¶ãå®å¯ä»¥æ ¹æ®ä¼ å
¥çæ°æ®åé
ç½®ï¼å±ç¤ºä¸åæ ·å¼ååè½çæ ç¾ï¼æä¾ä¸°å¯çç¨æ·äº¤äºä½éªã |
| | | |
| | | ## ä½¿ç¨æ¹å¼ |
| | | |
| | | <Layout> |
| | | åæ ç¾ |
| | | <div v-for='v in [1,2,3,4]' style="width: 150px; margin-bottom: 5px;"> |
| | | <Tag>æ ç¾{{v}}</Tag> |
| | | </div> |
| | | å¤ä¸ªæ¾ç¤ºtip |
| | | <Tag :data="[ |
| | | {label: 'æ ç¾ä¸', value: 1}, |
| | | {label: 'æ ç¾äº', value: 2}, |
| | | ]">æ ç¾ä¸</Tag> |
| | | |
| | | å个æ¾ç¤º tip |
| | | <Tag :showTip="true" :data="[ |
| | | {label: 'æ ç¾ä¸', value: 1}, |
| | | {label: 'æ ç¾äº', value: 2}, |
| | | ]">æ ç¾ä¸</Tag> |
| | | |
| | | å个æ¾ç¤º tip,è¶
åºæ¾ç¤º+ |
| | | <Tag :max="3" :showTip="true" :data="[ |
| | | {label: 'æ ç¾ä¸', value: 1}, |
| | | {label: 'æ ç¾äº', value: 2}, |
| | | {label: 'æ ç¾ä¸', value: 3}, |
| | | {label: 'æ ç¾å', value: 4}, |
| | | ]"></Tag> |
| | | éæ© tag |
| | | <br/> |
| | | <Tag v-model="v" :options="[ |
| | | {label: 'æ ç¾ä¸', value: 1}, |
| | | {label: 'æ ç¾äº', value: 2}, |
| | | {label: 'æ ç¾ä¸', value: 3}, |
| | | {label: 'æ ç¾å', value: 4}, |
| | | ]">æ ç¾ä¸</Tag> |
| | | </Layout> |
| | | |
| | | <script setup> |
| | | import Tag from '@/components/Tag/Tag.tsx' |
| | | import {ref } from 'vue' |
| | | const v = ref(1) |
| | | |
| | | </script> |
| | | |
| | | ```vue |
| | | <template> |
| | | åæ ç¾ |
| | | <div v-for="v in [1, 2, 3, 4]" style="width: 150px; margin-bottom: 5px;"> |
| | | <Tag>æ ç¾{{ v }}</Tag> |
| | | </div> |
| | | å¤ä¸ªæ¾ç¤ºtip |
| | | <Tag |
| | | :data="[ |
| | | { label: 'æ ç¾ä¸', value: 1 }, |
| | | { label: 'æ ç¾äº', value: 2 }, |
| | | ]" |
| | | >æ ç¾ä¸</Tag |
| | | > |
| | | |
| | | å个æ¾ç¤º tip |
| | | <Tag |
| | | :showTip="true" |
| | | :data="[ |
| | | { label: 'æ ç¾ä¸', value: 1 }, |
| | | { label: 'æ ç¾äº', value: 2 }, |
| | | ]" |
| | | >æ ç¾ä¸</Tag |
| | | > |
| | | |
| | | å个æ¾ç¤º tip,è¶
åºæ¾ç¤º+ |
| | | <Tag |
| | | :max="3" |
| | | :showTip="true" |
| | | :data="[ |
| | | { label: 'æ ç¾ä¸', value: 1 }, |
| | | { label: 'æ ç¾äº', value: 2 }, |
| | | { label: 'æ ç¾ä¸', value: 3 }, |
| | | { label: 'æ ç¾å', value: 4 }, |
| | | ]" |
| | | ></Tag> |
| | | éæ© tag |
| | | <br /> |
| | | <Tag |
| | | v-model="v" |
| | | :options="[ |
| | | { label: 'æ ç¾ä¸', value: 1 }, |
| | | { label: 'æ ç¾äº', value: 2 }, |
| | | { label: 'æ ç¾ä¸', value: 3 }, |
| | | { label: 'æ ç¾å', value: 4 }, |
| | | ]" |
| | | >æ ç¾ä¸</Tag |
| | | > |
| | | </template> |
| | | |
| | | <script setup> |
| | | import Tag from '@/components/Tag/Tag.tsx' |
| | | import { ref } from 'vue' |
| | | const v = ref(1) |
| | | </script> |
| | | ``` |
| | | |
| | | ## Props |
| | | |
| | | | 屿§å | ç±»å | é»è®¤å¼ | 说æ | |
| | | | ------------ | ------------- | ------- | ---------------------- | |
| | | | data | Array/Object | null | æ ç¾æ°æ® | |
| | | | options | Array | null | 䏿é项 | |
| | | | modelValue | String/Number | '' | ç»ä»¶çå¼ | |
| | | | trigger | String | 'hover' | è§¦åæ¹å¼ | |
| | | | showClose | Boolean | false | æ¯å¦æ¾ç¤ºå
³éæé® | |
| | | | showTip | Boolean | false | æ¯å¦æ¾ç¤ºæç¤º | |
| | | | valueKey | String | 'value' | æ°æ®å¼å¯¹åºçé®å | |
| | | | labelKey | String | 'label' | æ ç¾æ¾ç¤ºææ¬å¯¹åºçé®å | |
| | | | defaultValue | String | '' | é»è®¤å¼ | |
| | | | max | Number | 999 | æå¤§å¼ | |
| | | |
| | | ## Events |
| | | |
| | | | äºä»¶å | 说æ | |
| | | | ----------------- | ------------ | |
| | | | click | ç¹å»äºä»¶ | |
| | | | update:modelValue | æ´æ°ç»ä»¶çå¼ | |
| | | | change | å¼ååäºä»¶ | |
| | | | mouseenter | é¼ æ ç§»å
¥äºä»¶ | |
| | | | update:data | æ´æ°æ°æ®äºä»¶ | |
| | | |
| | | ## æ¹æ³ |
| | | |
| | | | æ¹æ³å | 说æ | |
| | | | --------------- | ---------------------- | |
| | | | onCommand | é项å½ä»¤äºä»¶ | |
| | | | onClose | å
³éæ ç¾äºä»¶ | |
| | | | onVisibleChange | 䏿鿩å¯è§æ§ååäºä»¶ | |
| | | | onClick | ç¹å»äºä»¶ | |
| | | | onMouseenter | é¼ æ ç§»å
¥äºä»¶ | |
| | | |
| | | ## ææ§½ |
| | | |
| | | | åç§° | 说æ | |
| | | | ------- | ------------ | |
| | | | default | é»è®¤å
å®¹ææ§½ | |
| | | |
| | | --- |
| | | |
| | | è¿æ ·çè¡¨æ ¼å½¢å¼è½å¤æ´æ¸
æ°å°å±ç¤ºç»ä»¶çå项屿§ãäºä»¶ãæ¹æ³åææ§½ï¼ä¾¿äºç¨æ·å¿«éæ¥é
å使ç¨ã |
| | | |
| | | ``` |
| | | |
| | | ``` |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | # TdButton åå
æ ¼æé®ç»ä»¶ææ¡£ |
| | | |
| | | ## ç®ä» |
| | | |
| | | TdButton æ¯ä¸ä¸ªç¨äºåå
æ ¼ä¸æ¾ç¤ºæé®ç Vue ç»ä»¶ãå®å¯ä»¥æ ¹æ®ä¼ å
¥çææ¬ã徿 åé
ç½®ï¼å±ç¤ºä¸åæ ·å¼ååè½çæé®ï¼å¹¶æ¯æç¦ç¨ç¶æåé¼ æ æ¬åææã |
| | | |
| | | ## ä½¿ç¨æ¹å¼ |
| | | |
| | | <Layout> |
| | | <div style="width: 300px;"> |
| | | <TdButton |
| | | :text="text" |
| | | icon="add-p" |
| | | tip="æé®ææ¬" |
| | | :disabled="disabled" |
| | | > |
| | | æé®ææ¬ |
| | | </TdButton> |
| | | </div> |
| | | </Layout> |
| | | |
| | | <script setup> |
| | | import { ref } from 'vue' |
| | | import TdButton from '@/components/TdButton/TdButton.tsx' |
| | | |
| | | const text = ref('æµè¯') // æé®ææ¬ |
| | | const icon = ref('') // æé®å¾æ |
| | | const tip = ref('') // æé®æç¤ºä¿¡æ¯ |
| | | const disabled = ref(false) // æ¯å¦ç¦ç¨æé® |
| | | </script> |
| | | |
| | | ```vue |
| | | <template> |
| | | <div style="width: 300px;"> |
| | | <TdButton :text="text" icon="add-p" tip="æé®ææ¬" :disabled="disabled"> |
| | | æé®ææ¬ |
| | | </TdButton> |
| | | </div> |
| | | </template> |
| | | |
| | | <script setup> |
| | | import { ref } from 'vue' |
| | | import TdButton from '@/components/TdButton/TdButton.tsx' |
| | | |
| | | const text = ref('æµè¯') // æé®ææ¬ |
| | | const icon = ref('') // æé®å¾æ |
| | | const tip = ref('') // æé®æç¤ºä¿¡æ¯ |
| | | const disabled = ref(false) // æ¯å¦ç¦ç¨æé® |
| | | </script> |
| | | ``` |
| | | |
| | | ## Props |
| | | |
| | | | 屿§å | ç±»å | é»è®¤å¼ | 说æ | |
| | | | -------- | ------- | ------ | -------------------- | |
| | | | text | String | '' | æé®ææ¬ | |
| | | | icon | String | '' | æé®å¾æ | |
| | | | tip | String | '' | æé®æç¤ºä¿¡æ¯ | |
| | | | disabled | Boolean | false | æ¯å¦ç¦ç¨æé® | |
| | | | hover | Boolean | false | æ¯å¦æ¾ç¤ºé¼ æ æ¬åææ | |
| | | | style | Object | {} | èªå®ä¹æ ·å¼ | |
| | | |
| | | ## Events |
| | | |
| | | | äºä»¶å | 说æ | |
| | | | ------ | -------- | |
| | | | click | ç¹å»äºä»¶ | |
| | | |
| | | ## ææ§½ |
| | | |
| | | | åç§° | 说æ | |
| | | | ------- | ------------ | |
| | | | default | é»è®¤å
å®¹ææ§½ | |
| | | |
| | | --- |
| | | |
| | | è¿æ ·çææ¡£å½¢å¼æ¸
æ°å°å±ç¤ºäºç»ä»¶ç屿§ãäºä»¶åææ§½ï¼åæ¶ä½¿ç¨äº `setup` 彿°ç®¡çç»ä»¶çç¶æåé»è¾ï¼ä½¿ä»£ç æ´å ç®æ´åå¯ç»´æ¤ã |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | # Text ææ¬ç»ä»¶ææ¡£ |
| | | |
| | | ## ç®ä» |
| | | |
| | | Text æ¯ä¸ä¸ªç¨äºæ¾ç¤ºææ¬å
容ç Vue ç»ä»¶ã宿¯æææ¬æªæãèªå®ä¹æ ç¾ãè¡æ°éå¶ãæç¤ºä¿¡æ¯ä»¥åæ ·å¼è®¾ç½®ã |
| | | |
| | | ## ä½¿ç¨æ¹å¼ |
| | | |
| | | <Text> |
| | | <Text |
| | | :truncated="truncated" |
| | | :tag="tag" |
| | | :lineClamp="lineClamp" |
| | | :tip="tip" |
| | | :fontSize="fontSize" |
| | | :color="color" |
| | | @click="handleClick" |
| | | > |
| | | <!-- ææ¬å
å®¹ææ§½ --> |
| | | ææ¯ææ¬å
容 |
| | | </Text> |
| | | </Text> |
| | | |
| | | <script setup> |
| | | import { ref } from 'vue' |
| | | import Text from '@/components/Text/Text.tsx' |
| | | |
| | | const truncated = ref(false) // æ¯å¦ææ¬æªæ |
| | | const tag = ref('span') // èªå®ä¹æ ç¾ï¼é»è®¤ä¸º span |
| | | const lineClamp = ref(1) // è¡æ°éå¶ï¼é»è®¤ä¸º 1 |
| | | const tip = ref('1111') // æç¤ºä¿¡æ¯ |
| | | const fontSize = ref('') // åä½å¤§å° |
| | | const color = ref('') // ææ¬é¢è² |
| | | |
| | | const handleClick = () => { |
| | | // ç¹å»äºä»¶å¤çé»è¾ |
| | | } |
| | | </script> |
| | | |
| | | ```vue |
| | | <template> |
| | | <Text |
| | | :truncated="truncated" |
| | | :tag="tag" |
| | | :lineClamp="lineClamp" |
| | | :tip="tip" |
| | | :fontSize="fontSize" |
| | | :color="color" |
| | | @click="handleClick" |
| | | > |
| | | <!-- ææ¬å
å®¹ææ§½ --> |
| | | ææ¯ææ¬å
容 |
| | | </Text> |
| | | </template> |
| | | |
| | | <script setup> |
| | | import { ref } from 'vue' |
| | | import Text from '@/components/Text/Text.tsx' |
| | | |
| | | const truncated = ref(false) // æ¯å¦ææ¬æªæ |
| | | const tag = ref('span') // èªå®ä¹æ ç¾ï¼é»è®¤ä¸º span |
| | | const lineClamp = ref(1) // è¡æ°éå¶ï¼é»è®¤ä¸º 1 |
| | | const tip = ref('') // æç¤ºä¿¡æ¯ |
| | | const fontSize = ref('') // åä½å¤§å° |
| | | const color = ref('') // ææ¬é¢è² |
| | | |
| | | const handleClick = () => { |
| | | // ç¹å»äºä»¶å¤çé»è¾ |
| | | } |
| | | </script> |
| | | ``` |
| | | |
| | | ## Props |
| | | |
| | | | 屿§å | ç±»å | é»è®¤å¼ | 说æ | |
| | | | --------- | ------- | ------ | ----------------------- | |
| | | | truncated | Boolean | false | æ¯å¦ææ¬æªæ | |
| | | | tag | String | 'span' | èªå®ä¹æ ç¾ï¼é»è®¤ä¸º span | |
| | | | lineClamp | Number | 1 | è¡æ°éå¶ï¼é»è®¤ä¸º 1 | |
| | | | tip | String | '' | æç¤ºä¿¡æ¯ | |
| | | | fontSize | String | '' | åä½å¤§å° | |
| | | | color | String | '' | ææ¬é¢è² | |
| | | |
| | | ## Events |
| | | |
| | | | äºä»¶å | 说æ | |
| | | | ------ | -------- | |
| | | | click | ç¹å»äºä»¶ | |
| | | |
| | | ## ææ§½ |
| | | |
| | | | åç§° | 说æ | |
| | | | ------- | ------------ | |
| | | | default | ææ¬å
å®¹ææ§½ | |
| | | |
| | | --- |
| | | |
| | | è¿æ ·çææ¡£å½¢å¼æ¸
æ°å°å±ç¤ºäºç»ä»¶ç屿§ãäºä»¶åææ§½ï¼åæ¶ä½¿ç¨äº `setup` 彿°ç®¡çç»ä»¶çç¶æåé»è¾ï¼ä½¿ä»£ç æ´å ç®æ´åå¯ç»´æ¤ã |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | # Title æ é¢ç»ä»¶ææ¡£ |
| | | |
| | | ## ç®ä» |
| | | |
| | | Title ç»ä»¶ç¨äºæ¾ç¤ºé¡µé¢æ 颿另ææè¿°çæ é¢ã宿¯æè®¾ç½®æè¿°ä¿¡æ¯ãä¸è¾¹è·åä¸è¾¹è·ï¼å¹¶æä¾ç¹å»äºä»¶ã |
| | | |
| | | ## ä½¿ç¨æ¹å¼ |
| | | |
| | | <Layout> |
| | | <Title |
| | | :desc="desc" |
| | | :top="top" |
| | | :bottom="bottom" |
| | | @click="handleClick" |
| | | > |
| | | <!-- æ é¢å
å®¹ææ§½ --> |
| | | æ é¢å
容 |
| | | <!-- æè¿°å
å®¹ææ§½ --> |
| | | <template #content> |
| | | æè¿°å
容 |
| | | </template> |
| | | </Title> |
| | | </Layout> |
| | | |
| | | <script setup> |
| | | import { ref } from 'vue' |
| | | import Title from '@/components/Title/Title.tsx' |
| | | |
| | | const desc = ref('') // æè¿°ä¿¡æ¯ |
| | | const top = ref(0) // ä¸è¾¹è· |
| | | const bottom = ref(0) // ä¸è¾¹è· |
| | | |
| | | const handleClick = () => { |
| | | // ç¹å»äºä»¶å¤çé»è¾ |
| | | } |
| | | </script> |
| | | |
| | | ```vue |
| | | <template> |
| | | <Title :desc="desc" :top="top" :bottom="bottom" @click="handleClick"> |
| | | <!-- æ é¢å
å®¹ææ§½ --> |
| | | æ é¢å
容 |
| | | <!-- æè¿°å
å®¹ææ§½ --> |
| | | <template #content> æè¿°å
容 </template> |
| | | </Title> |
| | | </template> |
| | | |
| | | <script setup> |
| | | import { ref } from 'vue' |
| | | import Title from '@/components/Title/Title.tsx' |
| | | |
| | | const desc = ref('') // æè¿°ä¿¡æ¯ |
| | | const top = ref(0) // ä¸è¾¹è· |
| | | const bottom = ref(0) // ä¸è¾¹è· |
| | | |
| | | const handleClick = () => { |
| | | // ç¹å»äºä»¶å¤çé»è¾ |
| | | } |
| | | </script> |
| | | ``` |
| | | |
| | | ## Props |
| | | |
| | | | 屿§å | ç±»å | é»è®¤å¼ | 说æ | |
| | | | ------ | ------ | ------ | -------- | |
| | | | desc | String | '' | æè¿°ä¿¡æ¯ | |
| | | | top | Number | 0 | ä¸è¾¹è· | |
| | | | bottom | Number | 0 | ä¸è¾¹è· | |
| | | |
| | | ## Events |
| | | |
| | | | äºä»¶å | 说æ | |
| | | | ------ | -------- | |
| | | | click | ç¹å»äºä»¶ | |
| | | |
| | | ## ææ§½ |
| | | |
| | | | åç§° | 说æ | |
| | | | ------- | ------------ | |
| | | | default | æ é¢å
å®¹ææ§½ | |
| | | | content | æè¿°å
å®¹ææ§½ | |
| | | |
| | | --- |
| | | |
| | | è¿æ ·çææ¡£å½¢å¼æ¸
æ°å°å±ç¤ºäºç»ä»¶ç屿§ãäºä»¶åææ§½ï¼åæ¶ä½¿ç¨äº `setup` 彿°ç®¡çç»ä»¶çç¶æåé»è¾ï¼ä½¿ä»£ç æ´å ç®æ´åå¯ç»´æ¤ã |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | # TouchScale 触æ¸ç¼©æ¾ç»ä»¶ææ¡£ |
| | | |
| | | ## ç®ä» |
| | | |
| | | TouchScale ç»ä»¶ç¨äºå®ç°è§¦æ¸å±ä¸çå¾åç¼©æ¾ææãéè¿è§¦æ¸å±å¹ï¼ç¨æ·å¯ä»¥å¯¹å¾åè¿è¡æ¾å¤§ã缩å°åç§»å¨æä½ã |
| | | |
| | | ## ä½¿ç¨æ¹å¼ |
| | | |
| | | <Layout> |
| | | ç¨æè§¦æ¸å±å¹ï¼å¯¹å¾åè¿è¡æ¾å¤§ã缩å°åç§»å¨æä½ã |
| | | <TouchScale> |
| | | <!-- å¾åå
å®¹ææ§½ --> |
| | | <img src="https://images.pexels.com/photos/7945944/pexels-photo-7945944.jpeg?auto=compress&cs=tinysrgb&w=1260&h=750&dpr=1" alt="..." /> |
| | | </TouchScale> |
| | | </Layout> |
| | | |
| | | <script setup> |
| | | import TouchScale from '@/components/TouchScale/index.vue' |
| | | </script> |
| | | |
| | | ```vue |
| | | <template> |
| | | <TouchScale> |
| | | <!-- å¾åå
å®¹ææ§½ --> |
| | | <img |
| | | src="https://images.pexels.com/photos/7945944/pexels-photo-7945944.jpeg?auto=compress&cs=tinysrgb&w=1260&h=750&dpr=1" |
| | | alt="..." |
| | | /> |
| | | </TouchScale> |
| | | </template> |
| | | |
| | | <script setup> |
| | | import TouchScale from '@/components/TouchScale/index.vue' |
| | | </script> |
| | | ``` |
| | | |
| | | ## ææ§½ |
| | | |
| | | | åç§° | 说æ | |
| | | | ------- | ------------ | |
| | | | default | å¾åå
å®¹ææ§½ | |
| | | |
| | | ## 屿§ |
| | | |
| | | TouchScale ç»ä»¶æä¸æ¯æä»»ä½å±æ§ã |
| | | |
| | | ## äºä»¶ |
| | | |
| | | TouchScale ç»ä»¶æä¸æ¯æä»»ä½äºä»¶ã |
| | | |
| | | ## æ ·å¼ |
| | | |
| | | TouchScale ç»ä»¶æä¾äºåºæ¬çæ ·å¼ï¼å¯ä»¥éè¿ä»¥ä¸æ¹å¼è¿è¡å®å¶ï¼ |
| | | |
| | | ```scss |
| | | // èªå®ä¹æ ·å¼ |
| | | ._touchScale { |
| | | /* Your styles here */ |
| | | } |
| | | |
| | | ._touch-mask { |
| | | /* Your styles here */ |
| | | } |
| | | ``` |
| | | |
| | | --- |
| | | |
| | | è¿æ ·çææ¡£å½¢å¼æ¸
æ°å°ä»ç»äºç»ä»¶çåè½åç¨æ³ï¼å¹¶æä¾äºæ ·å¼å®å¶ç示ä¾ã |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | # ä¸ä¼ ç»ä»¶ææ¡£ |
| | | |
| | | ## ç®ä» |
| | | |
| | | ä¸ä¼ ç»ä»¶æä¾äºä¸ä¸ªæ¹ä¾¿çæ¹å¼æ¥å°æä»¶ä¸ä¼ å°æå¡å¨ãå®å©ç¨äº Element Plus ä¸ç `el-upload` ç»ä»¶ï¼å¹¶æä¾äºèªå®ä¹é项ã |
| | | |
| | | ## ä½¿ç¨æ¹æ³ |
| | | |
| | | <Layout> |
| | | <Upload |
| | | accept=".pdf,.doc,.docx" |
| | | showFileList |
| | | :msg="uploadMessage" |
| | | @success="handleUploadSuccess" |
| | | > |
| | | <el-button type='primary'> ç¹å»ä¸ä¼ æä»¶ </el-button> |
| | | </Upload> |
| | | </Layout> |
| | | |
| | | <script setup> |
| | | import Upload from '@/components/Upload/index.vue' |
| | | |
| | | const uploadMessage = 'æä»¶ä¸ä¼ æå' |
| | | |
| | | const handleUploadSuccess = (data) => { |
| | | console.log('æä»¶å·²ä¸ä¼ :', data) |
| | | } |
| | | </script> |
| | | |
| | | ```vue |
| | | <template> |
| | | <Upload |
| | | accept=".pdf,.doc,.docx" |
| | | showFileList |
| | | :msg="uploadMessage" |
| | | @success="handleUploadSuccess" |
| | | > |
| | | <el-button type="primary"> ç¹å»ä¸ä¼ æä»¶ </el-button> |
| | | </Upload> |
| | | </template> |
| | | |
| | | <script setup> |
| | | import Upload from '@/components/Upload/index.vue' |
| | | |
| | | const uploadMessage = 'æä»¶ä¸ä¼ æå' |
| | | |
| | | const handleUploadSuccess = (data) => { |
| | | console.log('æä»¶å·²ä¸ä¼ :', data) |
| | | } |
| | | </script> |
| | | ``` |
| | | |
| | | ## ææ§½ |
| | | |
| | | | åç§° | æè¿° | |
| | | | ------- | ---------------- | |
| | | | default | é»è®¤ææ§½å
容 | |
| | | | text | ä¸ä¼ æé®ææ¬ææ§½ | |
| | | |
| | | ## 屿§ |
| | | |
| | | | åç§° | ç±»å | é»è®¤å¼ | æè¿° | |
| | | | ------------ | ------ | ------ | ---------------------------------- | |
| | | | accept | å符串 | | æå®æä»¶ç±»åï¼å¤ä¸ªç±»å使ç¨éå·åé | |
| | | | showFileList | å¸å°å¼ | false | æ¯å¦å¨ä¸ä¼ åæ¾ç¤ºæä»¶å表 | |
| | | | msg | å符串 | | ä¸ä¼ æååæ¾ç¤ºçæç¤ºä¿¡æ¯ | |
| | | |
| | | ## äºä»¶ |
| | | |
| | | | åç§° | æè¿° | |
| | | | ------- | ------------------------ | |
| | | | success | æä»¶ä¸ä¼ æåæ¶è§¦åçäºä»¶ | |
| | | |
| | | ## æ¹æ³ |
| | | |
| | | ä¸ä¼ ç»ä»¶ä¸æ´é²ä»»ä½èªå®ä¹æ¹æ³ã |
| | | |
| | | ## æ ·å¼ |
| | | |
| | | ä¸ä¼ ç»ä»¶æä¾äºåºæ¬æ ·å¼ï¼å¯ä»¥ä½¿ç¨ CSS è¿è¡èªå®ä¹ã以䏿¯ä¸ä¸ªç¤ºä¾ï¼ |
| | | |
| | | ```scss |
| | | .upload { |
| | | font-size: 25px; |
| | | color: #777; |
| | | } |
| | | ``` |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | # åéç»ä»¶ææ¡£ |
| | | |
| | | ## ç®ä» |
| | | |
| | | åéç»ä»¶ç¨äºéæ©æè¾å
¥åéå¼ã宿ä¾äºéæ©åéçåè½ï¼å¹¶æ¯æå¤éåå鿍¡å¼ã |
| | | |
| | | ## ä½¿ç¨æ¹æ³ |
| | | |
| | | è¾å
¥æ¡ç±»å为 `é»è®¤` |
| | | <Layout> |
| | | <Variable |
| | | v-model="variableValue" |
| | | :isClose="true" |
| | | :clearable="true" |
| | | :isMultiple="false" |
| | | /> |
| | | </Layout> |
| | | |
| | | è¾å
¥æ¡ç±»å为 `input` |
| | | <Layout> |
| | | <Variable |
| | | v-model="variableValue" |
| | | :isClose="true" |
| | | :clearable="true" |
| | | :isMultiple="false" |
| | | type="input" |
| | | /> |
| | | </Layout> |
| | | |
| | | è¾å
¥æ¡ç±»å为 `select` |
| | | <Layout> |
| | | <Variable |
| | | v-model="variableValue" |
| | | :isClose="true" |
| | | :clearable="true" |
| | | :isMultiple="false" |
| | | type="select"/> |
| | | </Layout> |
| | | |
| | | <script setup> |
| | | import Variable from '@/components/Variable/Variable.tsx' |
| | | import {ref} from 'vue' |
| | | const variableValue = ref('') // ç»å®çåéå¼ |
| | | |
| | | </script> |
| | | |
| | | ```vue |
| | | <template> |
| | | <Variable |
| | | v-model="variableValue" |
| | | :isClose="true" |
| | | :clearable="true" |
| | | :isMultiple="false" |
| | | type="input" |
| | | /> |
| | | </template> |
| | | |
| | | <script setup> |
| | | import Variable from '@/components/Variable/Variable.tsx' |
| | | import { ref } from 'vue' |
| | | |
| | | const variableValue = ref('') // ç»å®çåéå¼ |
| | | </script> |
| | | ``` |
| | | |
| | | ## 屿§ |
| | | |
| | | | 屿§åç§° | ç±»å | é»è®¤å¼ | æè¿° | |
| | | | ---------- | ------------- | ------ | -------------------------------------------- | |
| | | | modelValue | String/Number | - | ç»å®çåéå¼ | |
| | | | isClose | Boolean | false | æ¯å¦æ¾ç¤ºå
³é徿 ï¼ä»
对 `input` ç±»åææï¼ | |
| | | | clearable | Boolean | false | æ¯å¦å¯æ¸
é¤è¾å
¥å
容ï¼ä»
对 `input` ç±»åææï¼ | |
| | | | dataSource | Array | [] | æ°æ®æºï¼ä»
对å¤éæ¨¡å¼ææï¼ | |
| | | | isMultiple | Boolean | false | æ¯å¦æ¯æå¤éæ¨¡å¼ | |
| | | | index | Number | 0 | æ°æ®æºç´¢å¼ï¼ä»
对å¤éæ¨¡å¼ææï¼ | |
| | | | field | String | '' | æ°æ®æºå段åç§°ï¼ä»
对å¤éæ¨¡å¼ææï¼ | |
| | | | type | String | '' | è¾å
¥æ¡ç±»åï¼å¯éå¼ä¸º `'input'` æ `'select'` | |
| | | |
| | | ## äºä»¶ |
| | | |
| | | | äºä»¶åç§° | æè¿° | |
| | | | ----------------- | ---------------------- | |
| | | | update:modelValue | åé弿´æ°æ¶è§¦åçäºä»¶ | |
| | | | update:dataSource | æ°æ®æºæ´æ°æ¶è§¦åçäºä»¶ | |
| | | | change | åéå¼ååæ¶è§¦åçäºä»¶ | |
| | | |
| | | ## ææ§½ |
| | | |
| | | | ææ§½åç§° | æè¿° | |
| | | | -------- | ---------------- | |
| | | | é»è®¤ææ§½ | æ¿æ¢é»è®¤å
容 | |
| | | | text | æ¿æ¢ä¸ä¼ æé®ææ¬ | |
| | | |
| | | ## æ¹æ³ |
| | | |
| | | åéç»ä»¶ä¸æ´é²ä»»ä½èªå®ä¹æ¹æ³ã |
| | | |
| | | ## æ ·å¼ |
| | | |
| | | åéç»ä»¶æä¾äºåºæ¬æ ·å¼ï¼å¯ä»¥ä½¿ç¨ CSS è¿è¡èªå®ä¹ã以䏿¯ä¸ä¸ªç¤ºä¾ï¼ |
| | | |
| | | ```scss |
| | | .variable { |
| | | font-size: 16px; |
| | | color: #333; |
| | | } |
| | | ``` |
| | | |
| | | --- |
| | | |
| | | è¯¥ææ¡£æä¾äº "åé" ç»ä»¶ç详ç»ä»ç»ï¼å
æ¬å±æ§ãäºä»¶ãææ§½ãæ¹æ³åæ ·å¼é项ã |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | --- |
| | | # https://vitepress.dev/reference/default-theme-home-page |
| | | layout: home |
| | | |
| | | hero: |
| | | name: 'information-ui' |
| | | text: 'å端信æ¯åç»ä»¶åº' |
| | | tagline: 'åºäºVue3.xå¼åçç»ä»¶åº' |
| | | image: |
| | | # æ³æ§è¡è¯¥å½ä»¤ï¼éè¦å
ævueçæ¬å级å°3.3+,æè
æpackage.jsonä¸çvueå é¤ï¼éæ°å®è£
ï¼ç¼è¯å¥½äºåï¼åæ¢å¤ |
| | | src: /tt.png |
| | | alt: lems |
| | | actions: |
| | | - theme: brand |
| | | text: å¿«éå¼å§ |
| | | link: /quick-start |
| | | - theme: alt |
| | | text: æ¥çç»ä»¶ |
| | | link: /components/BaseContent |
| | | |
| | | features: |
| | | - title: éæ |
| | | details: éæäºä¿¡æ¯åæ åç»ä»¶å¼å |
| | | - title: å¤ç¨ |
| | | details: ç»ä»¶APIå¤ç¨ï¼åå°å¼åææ¬ |
| | | - title: æ ·å¼ç»ä¸ |
| | | details: æ ·å¼åºäºä¿¡æ¯åç»ä»¶æ åï¼ç廿 ·å¼èµ°æ¥æ¥éª¤ |
| | | --- |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | # Markdown Extension Examples |
| | | |
| | | This page demonstrates some of the built-in markdown extensions provided by VitePress. |
| | | |
| | | ## Syntax Highlighting |
| | | |
| | | VitePress provides Syntax Highlighting powered by [Shiki](https://github.com/shikijs/shiki), with additional features like line-highlighting: |
| | | |
| | | **Input** |
| | | |
| | | ````md |
| | | ```js{4} |
| | | export default { |
| | | data () { |
| | | return { |
| | | msg: 'Highlighted!' |
| | | } |
| | | } |
| | | } |
| | | ``` |
| | | ```` |
| | | |
| | | **Output** |
| | | |
| | | ```js{4} |
| | | export default { |
| | | data () { |
| | | return { |
| | | msg: 'Highlighted!' |
| | | } |
| | | } |
| | | } |
| | | ``` |
| | | |
| | | ## Custom Containers |
| | | |
| | | **Input** |
| | | |
| | | ```md |
| | | ::: info |
| | | This is an info box. |
| | | ::: |
| | | |
| | | ::: tip |
| | | This is a tip. |
| | | ::: |
| | | |
| | | ::: warning |
| | | This is a warning. |
| | | ::: |
| | | |
| | | ::: danger |
| | | This is a dangerous warning. |
| | | ::: |
| | | |
| | | ::: details |
| | | This is a details block. |
| | | ::: |
| | | ``` |
| | | |
| | | **Output** |
| | | |
| | | ::: info |
| | | This is an info box. |
| | | ::: |
| | | |
| | | ::: tip |
| | | This is a tip. |
| | | ::: |
| | | |
| | | ::: warning |
| | | This is a warning. |
| | | ::: |
| | | |
| | | ::: danger |
| | | This is a dangerous warning. |
| | | ::: |
| | | |
| | | ::: details |
| | | This is a details block. |
| | | ::: |
| | | |
| | | ## More |
| | | |
| | | Check out the documentation for the [full list of markdown extensions](https://vitepress.dev/guide/markdown). |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | import { postcssIsolateStyles } from 'vitepress' |
| | | import tailwindcss from 'tailwindcss' |
| | | import autoprefixer from 'autoprefixer' |
| | | |
| | | export default { |
| | | plugins: [ |
| | | postcssIsolateStyles({ |
| | | includeFiles: [/vp-doc\.css/], |
| | | }), |
| | | tailwindcss(), |
| | | autoprefixer(), |
| | | ], |
| | | } |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | # å¿«éå¼å§ |
| | | |
| | | ### æ¬èå°ä»ç»å¦ä½å¨é¡¹ç®ä¸ä½¿ç¨ Information Uiã |
| | | |
| | | ## å®è£
|
| | | |
| | | ```js |
| | | npm install information-ui --save |
| | | or |
| | | yarn add information-ui |
| | | ``` |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | import { defineConfig, loadEnv } from 'vite' |
| | | import vueJsx from '@vitejs/plugin-vue-jsx' |
| | | import path from 'path' |
| | | import VueTypeImports from 'vite-plugin-vue-type-imports' |
| | | import { ElementPlusResolver } from 'unplugin-vue-components/resolvers' |
| | | import Components from 'unplugin-vue-components/vite' |
| | | const nodeEnv = process.env.NODE_ENV || 'production' |
| | | const env = loadEnv(nodeEnv, __dirname) |
| | | // import { postcssIsolateStyles } from 'vitepress' |
| | | // import tailwindcss from 'tailwindcss' |
| | | // import autoprefixer from 'autoprefixer' |
| | | const suffix = process.env.NODE_ENV === 'development' ? '' : '.ssr' |
| | | console.log(suffix, 'suffix') |
| | | export default defineConfig({ |
| | | ssr: { |
| | | noExternal: ['element-plus'], |
| | | }, |
| | | plugins: [ |
| | | vueJsx(), |
| | | VueTypeImports(), |
| | | Components({ |
| | | include: [/\.vue$/, /\.vue\?vue/, /\.md$/, /\.tsx/, /\.jsx/], |
| | | resolvers: [ |
| | | ElementPlusResolver({ |
| | | importStyle: 'sass', |
| | | }), |
| | | ], |
| | | }), |
| | | ], |
| | | |
| | | resolve: { |
| | | alias: { |
| | | '@': path.resolve(__dirname, '../src'), |
| | | components: path.resolve(__dirname, '../src/components'), |
| | | sdk: path.resolve(__dirname, `../src/cms/sdk.es${suffix}.js`), |
| | | }, |
| | | }, |
| | | server: { |
| | | host: '0.0.0.0', |
| | | headers: { |
| | | 'Access-Control-Allow-Origin': '*', |
| | | }, |
| | | origin: `//localhost:${env.VITE_PORT}`, |
| | | // open: true, |
| | | port: env.VITE_PORT, |
| | | cors: true, |
| | | proxy: { |
| | | '/api': { |
| | | target: env.VITE_API_URL, |
| | | changeOrigin: true, |
| | | }, |
| | | '/hubs': { |
| | | target: env.VITE_API_URL, |
| | | changeOrigin: true, |
| | | ws: true, |
| | | }, |
| | | }, |
| | | }, |
| | | build: { |
| | | outDir: 'dist', |
| | | sourcemap: false, |
| | | chunkSizeWarningLimit: 1500, |
| | | target: 'ES2022', |
| | | rollupOptions: {}, |
| | | // output: { |
| | | // entryFileNames: `index.js`, |
| | | // }, |
| | | }, |
| | | css: { |
| | | // postcss: { |
| | | // plugins: [ |
| | | // postcssIsolateStyles({ |
| | | // includeFiles: [/vp-doc\.css/], |
| | | // }), |
| | | // tailwindcss(), |
| | | // autoprefixer(), |
| | | // ], |
| | | // }, |
| | | preprocessorOptions: { |
| | | scss: { |
| | | additionalData: ` |
| | | @use "@/assets/styles/element.scss" as *; |
| | | `, |
| | | }, |
| | | }, |
| | | }, |
| | | }) |
| | |
| | | } |
| | | |
| | | declare module 'koa-compose' |
| | | declare module 'd3' |
| | |
| | | <meta charset="UTF-8" /> |
| | | <link rel="icon" href="/favicon.ico" /> |
| | | <meta name="viewport" content="width=device-width, initial-scale=1.0" /> |
| | | <!-- <link rel="stylesheet" href="http://at.alicdn.com/t/font_3273823_ids2nmnjyss.css"> --> |
| | | <title>information-standard</title> |
| | | <title>ä¿¡æ¯åç»ä»¶LMES</title> |
| | | <script> |
| | | window.cmstype = 'Web' |
| | | </script> |
| | | </head> |
| | | |
| | | <body> |
| | | <div id="app"></div> |
| | | <script type="module" src="/src/main.ts"></script> |
| | |
| | | { |
| | | "name": "information-base", |
| | | "version": "1.0.0", |
| | | "version": "2.3.0", |
| | | "files": [ |
| | | "sdk", |
| | | "packages.json" |
| | | ], |
| | | "scripts": { |
| | | "menu": "node ./script/autoMenu.js", |
| | | "menu": "node ./script/generateMenu.js", |
| | | "pull": "bash pull.sh", |
| | | "checkout": "bash checkout.sh", |
| | | "dev": "npm run menu && vite --host", |
| | | "docs:dev": "vitepress dev docs", |
| | | "docs:build": "vitepress build docs", |
| | | "docs:preview": "vitepress preview docs", |
| | | "tag": "bash release.sh", |
| | | "mac": "cd ./script/ && ./menu && cd ../ && vite --host", |
| | | "open": "vite --host --open", |
| | | "build": "node ./script/build.js", |
| | | "build:go": "cd app && bash build.sh", |
| | | "build:all": "npm run menu && vite build", |
| | | "build-lib": "vite build --config=vite.lib.config.ts", |
| | | "build-lib": "cross-env NODE_OPTIONS=--max-old-space-size=8192 vite build --config=vite.lib.config.ts --mode", |
| | | "build:custom": "cross-env NODE_OPTIONS=--max-old-space-size=8192 NODE_TYPE=custom vite build --config=vite.lib.config.ts", |
| | | "build:widget": "cross-env NODE_OPTIONS=--max-old-space-size=8192 vite build --config=vite.build.config.ts && node ./script/replace.ts", |
| | | "widgets": "vite build --config=vite.lib.config.ts", |
| | | "serve": "vite preview --host --port=8888", |
| | | "build-serve": "npm run build && npm run serve", |
| | | "vue-tsc": "vue-tsc --noEmit", |
| | | "test": "jest" |
| | | "test": "jest", |
| | | "publish:prod:ui": "npm run build:widget && cd publish/information-ui && npm publish", |
| | | "publish:beta": "node --experimental-json-modules publish.js beta", |
| | | "publish:prod": "node --experimental-json-modules publish.js", |
| | | "rust": "cd rust && cargo run" |
| | | }, |
| | | "engines": { |
| | | "node": ">=18.0.0" |
| | | }, |
| | | "dependencies": { |
| | | "@antv/g6": "4.8.24", |
| | |
| | | "axios": "0.24.0", |
| | | "chalk": "4.1.2", |
| | | "cross-env": "7.0.3", |
| | | "cross-spawn": "7.0.5", |
| | | "d3": "7.9.0", |
| | | "d3-hierarchy": "3.1.2", |
| | | "dayjs": "1.11.10", |
| | |
| | | "vue-i18n": "9.1.9", |
| | | "vue-router": "4.0.11", |
| | | "vue-virtual-scroller": "1.1.2", |
| | | "vue3-cookies": "^1.0.6", |
| | | "vuex": "4.0.2", |
| | | "vxe-table": "4.6.20", |
| | | "vxe-table-plugin-element": "3.1.0", |
| | |
| | | "zip-a-folder": "3.1.7" |
| | | }, |
| | | "devDependencies": { |
| | | "cross-spawn": "7.0.5", |
| | | "@arco-plugins/vite-vue": "1.4.5", |
| | | "@babel/core": "7.26.0", |
| | | "@babel/preset-typescript": "7.16.7", |
| | |
| | | "jest": "27.5.1", |
| | | "kill-port": "^2.0.1", |
| | | "less": "^4.2.2", |
| | | "lmes-create-widget": "1.0.6", |
| | | "lmes-create-widget": "^1.0.2", |
| | | "postcss": "8.4.38", |
| | | "postcss-prefix-selector": "1.16.0", |
| | | "rollup-plugin-copy": "3.5.0", |
| | |
| | | "vitepress": "1.0.1", |
| | | "vue-tsc": "^2.1.10" |
| | | } |
| | | } |
| | | } |
| | |
| | | { |
| | | "MesSuite": { "æµè¯": "test" } |
| | | } |
| | | "BarcodeManagement": { |
| | | "æ·»å æ¡ç 段": "Add barcode segment", |
| | | "è¯·éæ©å·¥åº": "Please select a process", |
| | | "è¯·éæ©äº§å": "Please select a product", |
| | | "éç¨äº§å": "Applicable product", |
| | | "éç¨å·¥åº": "Applicable process", |
| | | "éæ©": "Select", |
| | | "è§£æè§å": "Parsing rule", |
| | | "æ ¡éªè§å": "Verification rule", |
| | | "3ã产ååå·ï¼åæ ¡éªæ¡ç ç该段ä¸è¯¥å·¥åºç产åå·è¿è¡æ¯å¯¹": "3. Product model: Compare the section of the verification barcode with the production model of the process.", |
| | | "4ãåºå®å符ï¼åå®é
çæ¡ç æ®µä¸å½åè§£æçæ¡ç 段å
容è¿è¡æ¯å¯¹": "4. Fixed characters: Compare the actual barcode segment with the content of the currently parsed barcode segment.", |
| | | "åºå®åç¬¦æ ¡éª": "Fixed character check", |
| | | "æ¡ç 段类å": "Barcode Segment Type", |
| | | "æ¡ç åæ®µ": "Barcode Field", |
| | | "æåº": "Sort", |
| | | "æ ¼å¼": "Format", |
| | | "èªå¢æ°åç±»åæ¶ï¼æåå·/æ¥æèªå¢": "For auto-incrementing number type, increment by model/date", |
| | | "ä¸å¡å¯¹è±¡": "Business Object", |
| | | "å
³èåæ®µè¯¦æ
": "Details of Associated Fields", |
| | | "ç¶çº§ID": "Parent ID", |
| | | "å
³èæ¡ç 䏿æ¡å¯¹åºç䏿æ¡keyå¼": "Key value of the drop-down box corresponding to the associated barcode drop-down box", |
| | | "åéå": "Variable Name", |
| | | "ç¶æ": "Status", |
| | | "æ¡ç æ®µç»æ": "Barcode Segment Composition", |
| | | "æ´æ°æ¶é´": "Update Time", |
| | | "æä½": "Operation", |
| | | "å
·ä½è§å": "Specific Rules", |
| | | "èµ·æ¢ç¬¦å·": "Start and End Symbols", |
| | | "æ ¡éªæ¡ç 段": "Verification Barcode Segment", |
| | | "æ ¡éªç±»å䏿": "Verification Type (Chinese)", |
| | | "æ ¡éªæ¡ç ": "Verification Barcode", |
| | | "åå§æ¡ç ": "Original Barcode", |
| | | "è§£ææ¡ç æ®µ": "Parsed Barcode Segment", |
| | | "æ¡ç è§£æè§å": "Barcode parsing rules", |
| | | "æ¡ç çæè§å": "Barcode generation rules", |
| | | "æ¡ç æ ¡éªè§å": "Barcode verification rules", |
| | | "æ°å¢": "Add", |
| | | "ç¼è¾": "Edit", |
| | | "å é¤": "Delete", |
| | | "æ¥ç": "View", |
| | | "请è¾å
¥è§£æè§ååç§°": "Please enter the name of the parsing rule", |
| | | "使ç¨ä¸": "In use", |
| | | "æªä½¿ç¨": "Not in use", |
| | | "è¯·éæ©ä¸ä¸ªè§åè¿è¡æ¥ç!": "Please select a rule to view!", |
| | | "ä»
æ¯æç¼è¾å个æ¥ç!": "Only single viewing for editing is supported!", |
| | | "è¯·éæ©ä¸ä¸ªè§åè¿è¡ç¼è¾!": "Please select a rule to edit!", |
| | | "ä»
æ¯æç¼è¾å个è§å!": "Only a single rule can be edited!", |
| | | "è¯·éæ©æ¡ç è¿è¡å é¤!": "Please select barcodes to delete!", |
| | | "æ¡ç å é¤åä¸å¯æ¢å¤ï¼æ¯å¦ç¡®è®¤å é¤ï¼": "Once barcodes are deleted, they cannot be recovered. Are you sure you want to delete them?", |
| | | "å 餿å": "Delete successful", |
| | | "æ¥çè§å": "View rules", |
| | | "ç¼è¾è§å": "Edit rules", |
| | | "æ°å¢è§å": "Add rules", |
| | | "è§ååç§°": "Rule name", |
| | | "æ¡ç 示ä¾": "Barcode example", |
| | | "è§£æç±»å": "Parsing type", |
| | | "è¾å
¥æ°ååè±æéå·ï¼ä»¥,å·åå²": "Enter numbers and English commas, separated by commas", |
| | | "ä¾å¦ï¼2,12,1": "For example: 2, 12, 1", |
| | | "åé符å·": "Separator symbol", |
| | | "èµ·å§ç¬¦å·": "Starting symbol", |
| | | "ç»æ¢ç¬¦å·": "Ending symbol", |
| | | "è§£æ": "Parse", |
| | | "åºå®é¿åº¦": "Fixed length", |
| | | "åºå·": "Serial number", |
| | | "æ¡ç 段åç§°": "Barcode segment name", |
| | | "æ¡ç 段å
容": "Barcode segment content", |
| | | "使°": "Number of digits", |
| | | "åå¨éå¤çæ¡ç 段åå": "There are duplicate barcode segment names", |
| | | "ä¿åæå": "Save successful", |
| | | "请è¾å
¥çæè§ååç§°": "Please enter the name of the generation rule", |
| | | "请è¾å
¥æ ¡éªè§ååç§°": "Please enter the name of the verification rule", |
| | | "请è¾å
¥": "Please enter", |
| | | "æ ¡éªç±»å": "check type", |
| | | "é¿åº¦æ ¡éª": "Length verification", |
| | | "æ¡ç 段": "Barcode segment", |
| | | "æ ¹æ®æ¡ç è§£æè§åè§£æåºæ¥æ¡ç 段ï¼éæ©éè¦æ£éªçæ¡ç 段": "Parse out barcode segments according to the barcode parsing rules and select the barcode segments that need to be verified", |
| | | "1ãé¿åº¦ï¼åæ ¡éªæ¡ç 该段è¿è¡é¿åº¦æ¯å¯¹": "1. Length: Take this segment of the verification barcode for length comparison", |
| | | "2ãç©æç¼å·ï¼åæ ¡éªæ¡ç ç该段ä¸è¯¥å·¥åºç产æéçç©æç¼å·è¿è¡æ¯å¯¹": "2. Material number: Take this segment of the verification barcode and compare it with the material number required for production in this process", |
| | | "é¿åº¦": "Length", |
| | | "ç©æç¼å·": "Material number", |
| | | "产ååå·": "Product model", |
| | | "夿³¨": "Remarks", |
| | | "è³å°æä¸ä¸ªæ¡ç æ®µéæ©äºæ ¡éªç±»å": "At least one barcode segment has selected a verification type", |
| | | "æ¡ç è§ååç§°": "Barcode rule name", |
| | | "èªå®ä¹æ¡ç 段": "Custom barcode segment", |
| | | "æ·»å ": "Add", |
| | | "æ¡ç æ®µæ¥æº": "Barcode source", |
| | | "çææ¡ç ææ": "Generated barcode effect", |
| | | "æ¶é´æ ¼å¼æ ¡éªä¸æ£ç¡®ï¼è¯·éæ°è¾å
¥": "The time format verification is incorrect. Please re-enter.", |
| | | "æ¡ç 段åç§°éå¤": "Barcode segment names are duplicated", |
| | | "请è¾å
¥å¿
填项": "Please enter the required items", |
| | | "æ¡ç ç¼è¾æå": "Barcode editing is successful", |
| | | "æ¡ç 段示ä¾": "Barcode segment example", |
| | | "èªå¢æ°åè§å": "Auto-incrementing number rule", |
| | | "ç§»å¨å¤±è´¥": "Move failed", |
| | | "è¯·éæ©": "Please select", |
| | | "èªå¢æ°åè¿å¶": "Auto-incrementing number system", |
| | | "åæ®µç±»å": "Field type", |
| | | "æ ¹æ®æ¡ç è§£æè§åè§£æåºæ¥æ¡ç 段ï¼éæ©éè¦ç¨äºçæè§åçæ¡ç æ®µ": "Parse out barcode segments according to the barcode parsing rules and select the barcode segments that need to be used for the generation rule", |
| | | "ç³»ç»æ¶é´": "System time", |
| | | "æ¶é´æ ¼å¼": "Time format", |
| | | "å
³èè§å": "Associated rule", |
| | | "å
³èåæ®µ": "Associated field", |
| | | "å
³èåé": "Associated variable", |
| | | "æå·¥åèªå¢": "Auto-increment by work order", |
| | | "æåå·èªå¢": "Auto-increment by model", |
| | | "ææ¥æèªå¢": "Auto-increment by date", |
| | | "åè¿å¶": "Decimal system", |
| | | "äºè¿å¶": "Binary system", |
| | | "å
«è¿å¶": "Octal system", |
| | | "åå
è¿å¶": "Hexadecimal system", |
| | | "ç³»ç»å段": "System field", |
| | | "ä¸å¡å段": "Business field", |
| | | "åºå®å符": "Fixed character", |
| | | "èªå¢æ°å": "Auto-incrementing number", |
| | | "ä¸è½ä¸ºç©º": "Cannot be empty", |
| | | "å·¥å": "Work order", |
| | | "åæ®µåç§°": "Field name", |
| | | "æ»ä½æ°æ ¡éª": "Total digit verification", |
| | | "æ¡ç æ®µä½æ°æ ¡éª": "Barcode segment digit verification", |
| | | "æ¡ç 段å
å®¹æ ¡éª": "Barcode segment content verification", |
| | | "æç¤º": "Prompt", |
| | | "åæ¶": "Cancel", |
| | | "确认": "Confirm", |
| | | "è§åè§£æå段": "Rule parsing field", |
| | | "æåå·/æ¥æèªå¢": "Auto-increment by model/date", |
| | | "æå·¥å/æ¥æèªå¢": "Auto-increment by work order/date", |
| | | "æ·»å /ç¼è¾æ¡ç 段": "Add/edit barcode segment", |
| | | "æ¡ç é¿åº¦": "Barcode length" |
| | | }, |
| | | "InspectionManagement": { |
| | | "å·¥åºåç§°": "Process Name", |
| | | "æ¯å¦å¼å§ç¹æ£ä»»å¡": "Do you want to start the inspection task", |
| | | "产线段": "Production Line Segment", |
| | | "å¼å§æ¶é´": "Start Time", |
| | | "ç»ææ¶é´": "End Time", |
| | | "请è¾å
¥æ¨¡çåç§°": "Please input template name", |
| | | "产ååç§°": "Product name", |
| | | "模çåç§°": "Template name", |
| | | "å³ä¾§ä¸ºå®é
ç»æ": "The actual results are on the right side", |
| | | "å·¦ä¾§ä¸ºé¢æç»æ": "The expected results are on the left side", |
| | | "ç¹æ£æç»": "Details of spot inspection", |
| | | "æªæ¿æ´»": "Not activated", |
| | | "ç¹æ£ä»»å¡ç®¡ç": "Spot inspection task management", |
| | | "ç¹æ£è®°å½": "Spot inspection records", |
| | | "ç¹æ£è¿½æº¯æ¥è¡¨": "Spot inspection traceability reports", |
| | | "æ¥è¡¨é
ç½®": "Report configuration", |
| | | "åºå·": "Serial number", |
| | | "产ååå·": "Product model", |
| | | "æä½æ¶é´": "Operation time", |
| | | "æä½äºº": "Operator", |
| | | "æä½": "Operation", |
| | | "æ·»å ": "Add", |
| | | "ç¹æ£ä»»å¡æ¨¡æ¿": "Inspection task template", |
| | | "详æ
": "Details", |
| | | "å·²æ¿æ´»": "Activated", |
| | | "å¼å§": "Start", |
| | | "æå": "Pause", |
| | | "ç»æ": "End", |
| | | "æ¿æ´»": "Activate", |
| | | "ç¼è¾": "Edit", |
| | | "æ¥ç": "View", |
| | | "å é¤": "Delete", |
| | | "æ¶é´èå´": "Time range", |
| | | "请è¾å
¥å
³é®å": "Please enter keywords", |
| | | "ç¹æ£ä»»å¡åç§°": "Inspection task name", |
| | | "å建æ¶é´": "Creation time", |
| | | "æä½ç¨æ·": "Operating user", |
| | | "ç¹æ£ä»¶åç§°": "Inspection part name", |
| | | "ç¹æ£ä»¶ID": "Check item ID", |
| | | "ç¹æ£ç±»å": "Check type", |
| | | "第": "The", |
| | | "次": "th time", |
| | | "宿æ¡ä»¶": "Completion condition", |
| | | "ç¹æ£æ¬¡æ°": "Number of inspection times", |
| | | "ç¶æ": "Status", |
| | | "ç»æ": "Result", |
| | | "ç¹æ£è·¯çº¿": "Inspection route", |
| | | "夿³¨": "Remarks", |
| | | "åå»ºå¯æ¬": "Create a copy", |
| | | "ç¹æ£ä»¶ç¼å·": "Inspection part number", |
| | | "é
æ¹": "Formula", |
| | | "æ°å¢ç¹æ£æ¨¡æ¿": "Add inspection template", |
| | | "ç¹æ£ç»ææ¥ç": "Check result viewing", |
| | | "æ·»å ä»»å¡": "Add task", |
| | | "请è¾å
¥ç¹æ£ä»¶åç§°": "Please enter the inspection part name", |
| | | "ç¹æ£ä»¶åç§°ä¸å
许为空": "The inspection part name is not allowed to be empty", |
| | | "请è¾å
¥ç¹æ£ä»¶ç¼å·": "Please enter the inspection part number", |
| | | "请è¾å
¥é
æ¹": "Please enter the formula", |
| | | "é
æ¹ä¸å
许为空": "The formula is not allowed to be empty", |
| | | "请è¾å
¥å¤æ³¨": "Please enter the remarks", |
| | | "确认å é¤é䏿¨¡ç": "Confirm to delete the selected template", |
| | | "è¯·éæ©ä»»å¡æ¨¡ç": "Please select the task template", |
| | | "å¤å¶æå": "Copy successful", |
| | | "ä¸éè¿": "Fail", |
| | | "éè¿": "Pass", |
| | | "请è¾å
¥": "Please enter", |
| | | "ä¿®æ¹": "Modify", |
| | | "ä¿®æ¹ç»æ": "Modify result", |
| | | "ç¹æ£ç»æ": "Inspection result", |
| | | "é¢æç»æ": "Expected result", |
| | | "详æ
åæ°": "Detail parameters", |
| | | "ç¹æ£è¯¦æ
åæ°æ¥ç": "Inspection detail parameter viewing", |
| | | "è¯·éæ©ç¹æ£ä»»å¡": "Please select the inspection task", |
| | | "确认å é¤éæ©ä»»å¡": "Confirm to delete the selected task", |
| | | "å 餿å": "Delete successful", |
| | | "导å
¥æå": "Import successful", |
| | | "导å
¥æä»¶æ ¼å¼ä¸æ£ç¡®ï¼è¯·å¯¼å
¥.xlsx/.xlsä¸.csvæ ¼å¼çæä»¶": "The import file format is incorrect. Please import files in.xlsx/.xls or.csv format.", |
| | | "导å
¥å¤±è´¥": "Import failed", |
| | | "ç¹æ£ä»»å¡æ¨¡ç": "template", |
| | | "è¯·éæ©ä»»å¡": "Please select the task", |
| | | "æ¿æ´»æå": "Activation successful", |
| | | "æ¯å¦æåç¹æ£ä»»å¡": "Whether to pause the inspection task", |
| | | "æåæå": "Pause successful", |
| | | "å¼å§æå": "Start successful", |
| | | "æ¯å¦ç»æç¹æ£ä»»å¡": "Whether to end the inspection task", |
| | | "å·²ç»æ": "Ended", |
| | | "æ¯å¦å é¤ç¹æ£ä»»å¡": "Whether to delete the inspection task", |
| | | "å·²å é¤": "Deleted", |
| | | "æ·»å ç¹æ£ä»¶": "Add inspection item", |
| | | "缺çä¿¡æ¯è®°å½": "Missing piece information record", |
| | | "ä¿åæå": "Save successful", |
| | | "ç¹æ£ä»»å¡": "Inspection task", |
| | | "请è¾å
¥ç¹æ£ä»»å¡": "Please enter the inspection task", |
| | | "è¯·éæ©ç¹æ£ç±»å": "Please select the inspection type", |
| | | "ç¹æ£æ¨¡ç": "Inspection template", |
| | | "è¯·éæ©ç¹æ£æ¨¡ç": "Please select the inspection template", |
| | | "è¯·éæ©äº§ååå·": "Please select the product model", |
| | | "è¾¾ææ¬¡æ°ï¼å½è¯¥ä»»å¡ææç¹æ£æ¬¡æ°é½å®æå宿任å¡": "Number of completions: The task is completed when all inspection times of the task are completed.", |
| | | "æ»¡è¶³é¢æï¼å½è¯¥ä»»å¡ç¹æ£ç»æä¸é¢æå¹é
å宿任å¡": "Meet expectations: The task is completed when the inspection result of the task matches the expectation.", |
| | | "请è¾å
¥å®ææ¡ä»¶": "Please enter the completion condition", |
| | | "è¯·éæ©å®ææ¡ä»¶": "Please select the completion condition", |
| | | "请è¾å
¥ç¹æ£æ¬¡æ°": "Please enter the number of inspection times" |
| | | }, |
| | | "SopManagement": { |
| | | "导å
¥æå": "Import success", |
| | | "导å
¥å¤±è´¥": "Import Fail", |
| | | "导å
¥æä»¶æ ¼å¼ä¸æ£ç¡®ï¼è¯·å¯¼å
¥.xlsx/.xlsä¸.csvæ ¼å¼çæä»¶": "Import file format is incorrect, please import .xlsx/.xls and .csv format files", |
| | | "导å
¥": "Import", |
| | | "å·¥åºéæ©": "Process Selection", |
| | | "SOP管ç": "SOP Management", |
| | | "SOPæ¥å¿": "SOP Log", |
| | | "æ°å¢": "Add", |
| | | "å¤å¶": "Copy", |
| | | "ç¼è¾": "Edit", |
| | | "å é¤": "Delete", |
| | | "请è¾å
¥å
³é®å": "Please enter keywords", |
| | | "详æ
": "Details", |
| | | "ç¼è¾SOP": "Edit SOP", |
| | | "ç»ææ¶é´èå´ï¼": "End time range:", |
| | | "导åº": "Export", |
| | | "å䏿·»å ä¸è¡": "Add a row upward", |
| | | "å䏿·»å ä¸è¡": "Add a row downward", |
| | | "æ¥çSop": "View Sop", |
| | | "éä»¶": "Attachment", |
| | | "æ°å¢SOP": "Add SOP", |
| | | "è¯·éæ©å·¥åº": "Please select the process", |
| | | "å·¥åºåç§°": "Process name", |
| | | "è¯·éæ©é
æ¹": "Please select the formula", |
| | | "é
æ¹åç§°": "Formula name", |
| | | "请è¾å
¥é
æ¹åç§°": "Please enter the formula name", |
| | | "SOPæä»¶å表": "SOP file list", |
| | | "åæ¶": "Cancel", |
| | | "确认": "Confirm", |
| | | "æ·»å ": "Add", |
| | | "请è¾å
¥æä»¶å": "Please enter the file name", |
| | | "请è¾å
¥å·¥åºåç§°": "Please enter the process name", |
| | | "é¢è§": "Preview", |
| | | "æ·»å æ¬å°æä»¶": "Add local file", |
| | | "ææ½è³è¿éä¸ä¼ ": "Drag and drop here to upload", |
| | | "ææ éä»¶": "No attachment", |
| | | "ä¸åæå": "Issuance successful", |
| | | "å·¥ä½åç§°": "Workstation name", |
| | | "ç¹æ£ç¶æ": "Inspection status", |
| | | "æä½": "Add", |
| | | "ç¹æ£SOP": "Spot check SOP", |
| | | "ä¿åæå": "Save successful", |
| | | "åºå·": "Serial number", |
| | | "SOPåç§°": "SOP name", |
| | | "使ç¨å·¥åº": "Used process", |
| | | "å·²å
³èé
æ¹": "Related formula", |
| | | "夿³¨": "Remarks", |
| | | "è¯·éæ©ä¸ä¸ªSOPè¿è¡ç¼è¾!": "Please select an SOP to edit!", |
| | | "ä»
æ¯æç¼è¾å个SOP!": "Only a single SOP can be edited!", |
| | | "è¯·éæ©ä¸ä¸ªSOPè¿è¡å¤å¶!": "Please select an SOP to copy!", |
| | | "æ¯æ¬¡ä»
æ¯æå¤å¶å个SOP!": "Only a single SOP can be copied at a time!", |
| | | "æ¯å¦ç¡®è®¤å¤å¶éä¸SOPï¼": "Are you sure to copy the selected SOP?", |
| | | "å¤å¶æå": "Copy successful", |
| | | "è¯·éæ©SOPè¿è¡å é¤!": "Please select SOPs to delete!", |
| | | "æ¯å¦ç¡®è®¤å é¤éä¸SOPï¼": "Are you sure to delete the selected SOP?", |
| | | "å 餿å": "Delete successful", |
| | | "ç¨æ·åç§°": "User name", |
| | | "æ¶é´": "Time", |
| | | "产åID": "Product ID", |
| | | "çäº§åæ°": "Production parameters", |
| | | "ç©æåæ°": "Material parameters", |
| | | "sopæ§è¡æ¥å¿": "SOP execution log", |
| | | "å¯¼åºæå": "Export successful", |
| | | "请è¾å
¥SOPåç§°": "Please enter the SOP name", |
| | | "SOPåç§°ä¸å
许为空ï¼": "The SOP name is not allowed to be empty!", |
| | | "å·¥åº": "Process", |
| | | "é
æ¹": "Formula", |
| | | "请è¾å
¥å¤æ³¨": "Please enter the remarks", |
| | | "å·¥æ¥ç®¡ç": "Work step management", |
| | | "å·¥æ¥åç§°ä¸å
许为空ï¼": "The work step name is not allowed to be empty!", |
| | | "å·¥æ¥æè¿°ä¸å
许为空ï¼": "The work step description is not allowed to be empty!", |
| | | "æ°å¢æå": "Add successful", |
| | | "ç¼è¾æå": "Edit successful", |
| | | "è¯·éæ©éè¦å é¤çæä»¶": "Please select the files to be deleted", |
| | | "æ¯å¦ç¡®è®¤å é¤é䏿件ï¼": "Are you sure to delete the selected files?", |
| | | "æªå¼å§": "Not started", |
| | | "ç¹æ£ä¸": "In inspection", |
| | | "åæ ¼": "Qualified", |
| | | "ä¸åæ ¼": "Unqualified", |
| | | "产线段åç§°": "Production line segment name", |
| | | "é
æ¹ç¼å·": "Formula number", |
| | | "产ååå·": "Product model", |
| | | "å·¥æ¥åç§°": "Work step name", |
| | | "æä½æè¿°": "Operation description", |
| | | "æä»¶å": "File name" |
| | | }, |
| | | "ConsoleManagement": { |
| | | "è¯·éæ©å·¥åº": "Please select a process", |
| | | "å·¥ä½": "Workstation", |
| | | "æ§å¶å°": "Console", |
| | | "è¯·éæ©æµç¨": "Please select the process", |
| | | "æä½æå": "Operation successful", |
| | | "è¦å": "Warning", |
| | | "æ¯å¦éç½®æææµç¨?": "Whether to reset all processes?", |
| | | "æ¯å¦éç½®WCSæµç¨?": "Whether to reset the WCS processes?", |
| | | "è¯·éæ©å·¥ä½": "Please select the workstation", |
| | | "æ¶é´": "Time", |
| | | "è³": "To", |
| | | "å¼å§æ¶é´": "Start time", |
| | | "ç»ææ¶é´": "End time", |
| | | "æ¥è¯¢": "Search", |
| | | "请è¾å
¥æ¥è¯¢å
容": "Please enter the search content", |
| | | "æ§å¶è®°å½": "Control record", |
| | | "导å
¥æå": "Import successful", |
| | | "å¯¼åºæå": "Export successful", |
| | | "å¼å§æ¶é´ä¸è½å¤§äºç»ææ¶é´": "The start time cannot be greater than the end time", |
| | | "æ¶é´èå´éå¶ä¸å¤©": "The time range is limited to seven days", |
| | | "å
³é®åé¿åº¦éå¶2-200": "The keyword length is limited to 2-200", |
| | | "请è¾å
¥å
³é®è¯è¿è¡æ£ç´¢ï¼": "Please enter keywords for retrieval!", |
| | | "æµç¨æ§å¶ç¡®è®¤": "Process control confirmation", |
| | | "æ¯å¦ç¡®è®¤æ§è¡": "Are you sure to execute", |
| | | "æä½": "Operation", |
| | | "夿³¨": "Remarks", |
| | | "æµç¨åè½è®¾ç½®": "Process function settings", |
| | | "åè½åç§°": "Function name", |
| | | "åè½æè¿°": "Function description", |
| | | "æªå¯å¨": "Not started", |
| | | "è¿è¡ä¸": "Running", |
| | | "é¨åè¿è¡": "Partially running", |
| | | "请å
鿩工ä½": "Please select the workstation first", |
| | | "æ¥çæµç¨": "View process", |
| | | "ä¸é®éå¯æææµç¨": "Restart all processes with one click", |
| | | "è°è¯æ¥å¿": "Debug log", |
| | | "ä¸åæä½": "Issue operation", |
| | | "åè½å段æä½": "Function field operation", |
| | | "åéå¼": "Variable value", |
| | | "请è¾å
¥åéå¼": "Please enter the variable value", |
| | | "请è¾å
¥å¤æ³¨": "Please enter the remarks", |
| | | "æ¥å¿ç级": "Log level", |
| | | "å
¨é¨": "All", |
| | | "å
³é®è¯": "Keyword", |
| | | "请è¾å
¥å
³é®å": "Please enter the keyword", |
| | | "èç¹åç§°": "Node name", |
| | | "æç´¢": "Search", |
| | | "导åº": "Export", |
| | | "åå²": "History", |
| | | "宿¶": "Real-time", |
| | | "å
³é®æ¥å¿": "Key logs", |
| | | "å®ä½": "Locate", |
| | | "åºå·": "Serial number", |
| | | "åæ°": "Parameters", |
| | | "å¿«æ·æä½": "Quick operations", |
| | | "åæ°ä¿¡å·æä½": "Parameter signal operations", |
| | | "åè½å段": "Function field", |
| | | "æè¿°": "Description", |
| | | "åéå": "Variable name", |
| | | "ç±»å": "Type", |
| | | "ä¸å": "Issue", |
| | | "ææ æ°æ®": "No data available", |
| | | "ç¨æ·å": "Username", |
| | | "å·¥åº": "Process", |
| | | "å·¥ä½åç§°": "Workstation name", |
| | | "æµç¨åç§°": "Process name", |
| | | "æä½åç§°": "Operation name", |
| | | "åæ¶æµç¨å°ç»æ¢ææå®ä¾ï¼ç´å°ä¸æ¬¡å¯å¨ï¼": "Canceling the process will terminate all instances until the next startup!", |
| | | "æ¯å¦ç¡®è®¤åæ¶": "Are you sure to cancel", |
| | | "æ§å¶é¡µé¢": "Control page" |
| | | }, |
| | | "ControlPanel": { |
| | | "è¯·éæ©å·¥åº": "Please select a process", |
| | | "å·¥ä½": "Workstation", |
| | | "æ§å¶å°": "Console", |
| | | "è¯·éæ©æµç¨": "Please select the process", |
| | | "æä½æå": "Operation successful", |
| | | "è¦å": "Warning", |
| | | "æ¯å¦éç½®æææµç¨?": "Whether to reset all processes?", |
| | | "æ¯å¦éç½®WCSæµç¨?": "Whether to reset the WCS processes?", |
| | | "è¯·éæ©å·¥ä½": "Please select the workstation", |
| | | "æ¶é´": "Time", |
| | | "è³": "To", |
| | | "å¼å§æ¶é´": "Start time", |
| | | "ç»ææ¶é´": "End time", |
| | | "æ¥è¯¢": "Search", |
| | | "请è¾å
¥æ¥è¯¢å
容": "Please enter the search content", |
| | | "æ§å¶è®°å½": "Control record", |
| | | "导å
¥æå": "Import successful", |
| | | "å¯¼åºæå": "Export successful", |
| | | "å¼å§æ¶é´ä¸è½å¤§äºç»ææ¶é´": "The start time cannot be greater than the end time", |
| | | "æ¶é´èå´éå¶ä¸å¤©": "The time range is limited to seven days", |
| | | "å
³é®åé¿åº¦éå¶2-200": "The keyword length is limited to 2-200", |
| | | "请è¾å
¥å
³é®è¯è¿è¡æ£ç´¢ï¼": "Please enter keywords for retrieval!", |
| | | "æµç¨æ§å¶ç¡®è®¤": "Process control confirmation", |
| | | "æ¯å¦ç¡®è®¤æ§è¡": "Are you sure to execute", |
| | | "æä½": "Operation", |
| | | "夿³¨": "Remarks", |
| | | "æµç¨åè½è®¾ç½®": "Process function settings", |
| | | "åè½åç§°": "Function name", |
| | | "åè½æè¿°": "Function description", |
| | | "æªå¯å¨": "Not started", |
| | | "è¿è¡ä¸": "Running", |
| | | "é¨åè¿è¡": "Partially running", |
| | | "请å
鿩工ä½": "Please select the workstation first", |
| | | "æ¥çæµç¨": "View process", |
| | | "ä¸é®éå¯æææµç¨": "Restart all processes with one click", |
| | | "è°è¯æ¥å¿": "Debug log", |
| | | "ä¸åæä½": "Issue operation", |
| | | "åè½å段æä½": "Function field operation", |
| | | "åéå¼": "Variable value", |
| | | "请è¾å
¥åéå¼": "Please enter the variable value", |
| | | "请è¾å
¥å¤æ³¨": "Please enter the remarks", |
| | | "æ¥å¿ç级": "Log level", |
| | | "å
¨é¨": "All", |
| | | "å
³é®è¯": "Keyword", |
| | | "请è¾å
¥å
³é®å": "Please enter the keyword", |
| | | "èç¹åç§°": "Node name", |
| | | "æç´¢": "Search", |
| | | "导åº": "Export", |
| | | "åå²": "History", |
| | | "宿¶": "Real-time", |
| | | "å
³é®æ¥å¿": "Key logs", |
| | | "å®ä½": "Locate", |
| | | "åºå·": "Serial number", |
| | | "åæ°": "Parameters", |
| | | "å¿«æ·æä½": "Quick operations", |
| | | "åæ°ä¿¡å·æä½": "Parameter signal operations", |
| | | "åè½å段": "Function field", |
| | | "æè¿°": "Description", |
| | | "åéå": "Variable name", |
| | | "ç±»å": "Type", |
| | | "ä¸å": "Issue", |
| | | "ææ æ°æ®": "No data available", |
| | | "ç¨æ·å": "Username", |
| | | "å·¥åº": "Process", |
| | | "å·¥ä½åç§°": "Workstation name", |
| | | "æµç¨åç§°": "Process name", |
| | | "æä½åç§°": "Operation name", |
| | | "åæ¶æµç¨å°ç»æ¢ææå®ä¾ï¼ç´å°ä¸æ¬¡å¯å¨ï¼": "Canceling the process will terminate all instances until the next startup!", |
| | | "æ¯å¦ç¡®è®¤åæ¶": "Are you sure to cancel", |
| | | "æ§å¶é¡µé¢": "Control page", |
| | | "å¯å¨": "Start", |
| | | "忢": "Stop" |
| | | }, |
| | | "BOMManagement": { |
| | | "å
¨é¨": "All", |
| | | "å·¥åº": "Process", |
| | | "ç¨é": "Dosage", |
| | | "è¯·éæ©å·¥åº": "Please select a process", |
| | | "è¯·éæ©ç©æç±»å": "Please select a material type", |
| | | "æ°å»ºç©æ": "New Material", |
| | | "ç¼è¾ç©æ": "Edit Material", |
| | | "å 餿å": "Deleted successfully", |
| | | "产ååç§°": "Product Name", |
| | | "产ååå·": "Product Model", |
| | | "BOMåç§°": "BOM Name", |
| | | "æä½æå": "Operation Successful", |
| | | "BOM管ç.xlsx": "BOM Management.xlsx", |
| | | "BOMåç§°éå¤": "BOM Name Duplicated", |
| | | "BOMå表": "Bom list", |
| | | "åºå·": "Serial number", |
| | | "ç©æç¼å·": "Material code", |
| | | "ç©æåç§°": "Material name", |
| | | "ç©æç±»å": "Material type", |
| | | "åä½": "Unit", |
| | | "æ¡ç è§å": "Barcode rule", |
| | | "BOM管ç": "Bill of Material (BOM) management", |
| | | "导å
¥": "Import", |
| | | "导åº": "Export", |
| | | "产ååç§°ï¼": "Product name:", |
| | | "产ååå·ï¼": "Product model:", |
| | | "æ·»å ": "Add", |
| | | "ç¼è¾": "Edit", |
| | | "å é¤": "Delete", |
| | | "çé": "Filter", |
| | | "ç¨éä¸å
许为空ï¼": "Dosage cannot be empty!", |
| | | "æ£æ°ï¼å¯æ´åãæµ®ç¹å": "Positive number, can be integer or floating-point type", |
| | | "å·¥åºä¸å
许为空ï¼": "Process cannot be empty!", |
| | | "ç©æç¼å·ä¸å
许为空ï¼": "Material code cannot be empty!", |
| | | "请è¾å
¥éæ©å·¥åº": "Please enter and select the process", |
| | | "请è¾å
¥ç©æç¼å·": "Please enter the material code", |
| | | "请è¾å
¥ç¨é": "Please enter the dosage", |
| | | "å建æå": "Creation successful", |
| | | "ä¿®æ¹æå": "Modification successful", |
| | | "è¯·éæ©äº§åè¿è¡æ·»å ": "Please select a product to add", |
| | | "è¯·éæ©ä¸ä¸ªç©æè¿è¡ç¼è¾!": "Please select a material to edit!", |
| | | "ä»
æ¯æç¼è¾åä¸ªç©æ!": "Only single material editing is supported!", |
| | | "è¯·éæ©ç©æè¿è¡å é¤!": "Please select materials to delete!", |
| | | "ç©æå é¤åï¼ç¸å
³çäº§æ°æ®æ æ³æ¢å¤ï¼æ¯å¦ç¡®è®¤å é¤ï¼": "After the materials are deleted, the related production data cannot be recovered. Are you sure to delete?" |
| | | }, |
| | | "BusinessFieldSetting": { |
| | | "导å
¥æå": "Import success", |
| | | "导å
¥å¤±è´¥": "Import Fail", |
| | | "导å
¥æä»¶æ ¼å¼ä¸æ£ç¡®ï¼è¯·å¯¼å
¥.xlsx/.xlsä¸.csvæ ¼å¼çæä»¶": "Import file format is incorrect, please import .xlsx/.xls and .csv format files", |
| | | "导å
¥": "Import", |
| | | "导åº": "Export", |
| | | "ä¿åæå": "Save successful", |
| | | "ä¿å": "Save", |
| | | "åºå·": "Serial number", |
| | | "åæ®µåç§°": "Field name", |
| | | "åé": "Variable", |
| | | "夿³¨": "Remarks", |
| | | "ä¸å¡å段设置": "Business field settings" |
| | | }, |
| | | "FlowManagement": { |
| | | "æµç¨ç¼å·": "Flow number", |
| | | "ç³»ç»å
ç½®": "System built-in", |
| | | "æ¯": "Yes", |
| | | "å¦": "No", |
| | | "å 餿å": "Delete success", |
| | | "确认å é¤é䏿°æ®?": "Are you sure to delete the selected data?", |
| | | "å¯ç¨": "Enable", |
| | | "ç¦ç¨": "Disable", |
| | | "å
é": "Clone", |
| | | "请è¾å
¥æµç¨æè¿°": "Please input flow desc", |
| | | "æµç¨æè¿°": "FLow Description", |
| | | "æµç¨ç®¡ç": "Flow Management", |
| | | "å
¨é¨": "All", |
| | | "æµç¨": "Flow", |
| | | "åæ°ä¿¡å·é
ç½®": "Parameter Signal Configuration", |
| | | "åè½é
ç½®": "Parameter config", |
| | | "åæ®µé
ç½®": "Field Configuration", |
| | | "åè½åç§°": "Function Name", |
| | | "åè½æè¿°": "Function Description", |
| | | "åè½æ è¯": "Function Identifier", |
| | | "åè½é项": "Function Options", |
| | | "åç»åç§°": "Group Name", |
| | | "åæ®µåç§°": "Field Name", |
| | | "åæ®µæè¿°": "Field Description", |
| | | "åæ®µç±»å": "Field Type", |
| | | "åæ®µæ è¯": "Field Identifier", |
| | | "æ¾ç¤º": "Display", |
| | | "é»è®¤å¼": "Default Value", |
| | | "åªè¯»": "Read Only", |
| | | "å¿
å¡«": "Required", |
| | | "åç§°": "Name", |
| | | "æè¿°": "Description", |
| | | "é项å¼": "Option Value", |
| | | "æä½": "Operation", |
| | | "æµç¨åæ°é
置弹çª": "Flow Parameter Configuration Pop-up Window", |
| | | "æµç¨å¼¹çª": "Flow Pop-up Window", |
| | | "请è¾å
¥æµç¨åç§°": "Please enter the flow name", |
| | | "è¯·éæ©äº¤äºç±»å": "Please select the interaction type", |
| | | "æ´æ°æå": "Update successful", |
| | | "æ·»å æå": "Add successful", |
| | | "å
éæå": "Clone successful", |
| | | "导å
¥æå": "Import successful", |
| | | "导å
¥å¤±è´¥": "Import failed", |
| | | "导å
¥æä»¶æ ¼å¼ä¸æ£ç¡®ï¼è¯·å¯¼å
¥.xlsx/.xlsä¸.csvæ ¼å¼çæä»¶": "The import file format is incorrect. Please import files in.xlsx/.xls and.csv formats.", |
| | | "确认å é¤": "Confirm deletion", |
| | | "å¯ç¨æå": "Enable successful", |
| | | "ç¦ç¨æå": "Disable successful", |
| | | "è¯·éæ©æµç¨": "Please select the flow", |
| | | "åºå·": "Serial Number", |
| | | "æµç¨åç§°": "Flow Name", |
| | | "交äºç±»å": "Interaction Type", |
| | | "åè½é¡¹": "Function Items", |
| | | "å
³èå·¥åº": "Associated Processes", |
| | | "夿³¨": "Remarks", |
| | | "ç¶æ": "Status", |
| | | "å·²ç¦ç¨": "Disabled", |
| | | "å·²å¯ç¨": "Enabled", |
| | | "æ¥ç": "View", |
| | | "ç¼è¾": "Edit", |
| | | "设计": "Design", |
| | | "å é¤": "Delete", |
| | | "æ¹éé
ç½®": "Batch Configuration", |
| | | "æ·»å ": "Add", |
| | | "çé": "Filter", |
| | | "导å
¥": "Import", |
| | | "导åº": "Export", |
| | | "åè½é项ä¸è½ä¸ºç©º": "Function options cannot be empty", |
| | | "åè½é项åç§°ä¸è½éå¤": "Function option names cannot be duplicated", |
| | | "é项å¼ä¸è½éå¤": "Option values cannot be duplicated", |
| | | "è¯·éæ©": "Please select", |
| | | "åè½éé¡¹å¯¹è¯æ¡": "Function Option Dialog", |
| | | "æ¹éé
ç½®å¯¹è¯æ¡": "Batch Configuration Dialog", |
| | | "G6æµç¨": "G6 Flow", |
| | | "表头å
容": "Header Content", |
| | | "æç´¢": "Search", |
| | | "鿩工åº": "Select Work Section", |
| | | "确认工åº": "Confirm Work Section", |
| | | "确认æµç¨": "Confirm Flow", |
| | | "ç¼è¾åºç¡æµç¨": "Edit Base Flow", |
| | | "å 餿µç¨": "Delete Flow", |
| | | "å¤å¶æµç¨": "Copy Flow", |
| | | "确认æµç¨è¡¨å": "Confirm Flow Form", |
| | | "ç¹å»æ·»å ": "Click Add", |
| | | "ä¸ä¼ æå": "Upload Success", |
| | | "ä¸ä¼ 失败": "Upload Failure", |
| | | "ä¸ä¼ å": "Before Upload", |
| | | "ä¸ä¸æèå": "Context Menu", |
| | | "è·å详æ
æ°æ®": "Get Detail Data", |
| | | "åæ°é
ç½®": "Param config", |
| | | "æ·»å æµç¨": "Add Flow", |
| | | "å
³é": "Close", |
| | | "确认": "Confirm" |
| | | }, |
| | | "MesSuite": { |
| | | "è¯·éæ©è§£æè§å": "Please select the parse rule", |
| | | "请è¾å
¥æ»è¡¨åç§°": "Please enter the total table name", |
| | | "æ§å¶é¡µé¢": "Control Page", |
| | | "æ§å¶è®°å½": "Control Record", |
| | | "ç¹æ£ä»»å¡ç®¡ç": "Inspection Task Management", |
| | | "ç¹æ£è®°å½": "Inspection Record", |
| | | "ç¹æ£è¿½æº¯æ¥è¡¨": "Inspection Traceability Report", |
| | | "ç©æç®¡ç": "Material Management", |
| | | "ç©æè®°å½": "Material Record", |
| | | "å·¥åºå表": "Process List", |
| | | "å·¥ä½å表": "Workstation List", |
| | | "SOP管ç": "SOP Management", |
| | | "SOPæ¥å¿": "SOP Log", |
| | | "使ç¨ä¸": "In use", |
| | | "æªä½¿ç¨": "Not in use", |
| | | "请è¾å
¥è§£æè§ååç§°": "Please enter the parsing rule name", |
| | | "ç¨æ·æ²¡æè¯¥æéï¼": "User does not have this permission!", |
| | | "产åä¿¡æ¯ä¸åé
ç½®": "Product Information Distribution Configuration", |
| | | "è¯·éæ©ä¸ä¸ªé
ç½®ï¼": "Please select a configuration!", |
| | | "è§£æè§å": "Parsing rule", |
| | | "æ ¡éªè§å": "Verification rule", |
| | | "忶坼å
¥æå": "Cancel import successful", |
| | | "æ¯å¦åæ¶å¯¼å
¥": "Are you sure to cancel import?", |
| | | "导å
¥æä»¶æ ¼å¼ä¸æ£ç¡®ï¼è¯·å¯¼å
¥.xlsx/.xlsä¸.csvæ ¼å¼çæä»¶": "The import file format is incorrect. Please import files in.xlsx/.xls and.csv formats.", |
| | | "导å
¥è¿åº¦": "Import Progress", |
| | | "å·²ç¨æ¶é´": "Used Time", |
| | | "å©ä½æ¶é´": "Remaining Time", |
| | | "计ç®ä¸...": "Calculating...", |
| | | "忶坼å
¥": "Cancel Import", |
| | | "è¯·éæ©ä¸æ¡è§£æè§å": "Please select one parsing rule", |
| | | "æ¡ç è§£æè§å": "Barcode parsing rules", |
| | | "请å¿éæ©å¤ä¸ªé
ç½®æä½ï¼": "Please don't select multiple configuration operations!", |
| | | "é
æ¹è¿ç¨å¼": "Formula Process Value", |
| | | "è¯·éæ©ä¸ä¸ªåæ°ï¼": "Please select a parameter!", |
| | | "ééåæ°": "Collection Parameters", |
| | | "åæ°å": "Parameter Name", |
| | | "åæ°æè¿°": "Parameter description", |
| | | "é
æ¹åæ°": "Formula Parameters", |
| | | "ç©æåæ°": "Material parameter", |
| | | "æ°å¢äº§åä¸ååæ°å¼é
ç½®": "Add Product Information Distribution Parameter Value Configuration", |
| | | "产åä¸åä¿¡æ¯": "Product Information Distribution", |
| | | "æ°æ®æº": "Data Source", |
| | | "ç±»å": "Type", |
| | | "æ°å¢": "Add", |
| | | "ç¼è¾": "Edit", |
| | | "ä¸åç±»å": "Issue Type", |
| | | "ä¸åæ°æ®": "Issue Data", |
| | | "æç管ç": "Pallet Management", |
| | | "æçç»å®è®°å½": "Pallet Binding Record", |
| | | "æä»¶é误,ä¸è½½å¤±è´¥": "File error, download failed", |
| | | "æ¯å¦åæ¶ä¸æ": "Whether to cancel the material", |
| | | "è¯·éæ©æ°æ®": "Please select the data", |
| | | "ç©æç¼å·": "Material Code", |
| | | "ç©æåç§°": "Material Name", |
| | | "ä¸æç©æç ": "Material Code", |
| | | "å®é
ç©æç ": "Actual Material Code", |
| | | "è¯·éæ©å
容": "Please Select Content", |
| | | "使ç¨è¯¦æ
": "Use Detail", |
| | | "ç©æç ": "Material Code", |
| | | "忶䏿": "Cancel Material", |
| | | "模æ¿åç§°": "Template Name", |
| | | "é¢è§": "Preview", |
| | | "åç§°": "Name", |
| | | "å
³é®å": "Keyword", |
| | | "请è¾å
¥å
³é®å": "Please Enter Keywords", |
| | | "ä»
æ¯æå¯¹ä¸æ¡æ°æ®è¿è¡æä½!": "Only supports operations on one piece of data!", |
| | | "æè¿°": "Description", |
| | | "å·¥ä½éæ©": "Station Selection", |
| | | "å·¥ä½åç§°": "Station name", |
| | | "åé": "Variable", |
| | | "åæ®µ": "Field", |
| | | "æ¡ç çæè§å": "Barcode generation rules", |
| | | "æµç¨ä¸ä¸æ": "Flow Context", |
| | | "æ è¯": "FLag", |
| | | "æ°æ®ç±»å": "Data Type", |
| | | "çæè§å": "generation rules", |
| | | "ä¸ååé": "Issue Variable", |
| | | "è§åç±»å": "Rule type", |
| | | "æ¡ç æ®µç»æ": "Barcode Segment Composition", |
| | | "æ¡ç 示ä¾": "Barcode example", |
| | | "æ´æ°æ¶é´": "Update Time", |
| | | "æ ç¾ç®¡ç": "Label Management", |
| | | "æ ç¾è®°å½": "Label Record", |
| | | "è¿ç«ãåºç«ç交äºç±»ååªè½éæ©ä¸ä¸ªï¼è¯·æ£æ¥ï¼": "Only one interaction type of entry and exit can be selected. Please check!", |
| | | "å
³èæ¡ç çæè§å": "Associated barcode generation rule", |
| | | "æ¡ç åç§°": "Barcode name", |
| | | "产å管ç": "Product Management", |
| | | "产åè¯å«ç ": "Product identification code", |
| | | "çæ¬åç§°": "Version name", |
| | | "夿³¨": "Remarks", |
| | | "产ååç§°": "Product Name", |
| | | "产ååå·": "Product Model", |
| | | "产å": "Product", |
| | | "éæ©äº§ååå·": "Select Product Model", |
| | | "æå°æºéæ©": "Printer selection", |
| | | "请è¾å
¥æå°æºåç§°": "Please enter the printer name", |
| | | "æå°æº": "Printer", |
| | | "产线段é
ç½®": "Product segment config", |
| | | "é
æ¹éæ©": "Formula select", |
| | | "å·¥å管ç": "Work Order Management", |
| | | "å·¥åè®°å½": "Work Order Records", |
| | | "请è¾å
¥æç´¢": "Please input search", |
| | | "è¯¥ç¹æ£ä»»å¡æ²¡æå¯ä½¿ç¨ç产线段": "There are no available production lines for this inspection task", |
| | | "éæ©": "Select", |
| | | "é
æ¹ç®¡ç": "Formula management", |
| | | "é
æ¹åºç¨": "Formula application", |
| | | "é
æ¹æ¥å¿": "Formula log", |
| | | "å¼å§æ¶é´å¿
é¡»æ¯ç»ææ¶é´å°": "Start time must be to low end time", |
| | | "è¯·éæ©å¼å§æ¶é´": "Please select start time", |
| | | "è¯·éæ©ç»ææ¶é´": "Please select end time", |
| | | "æ¶é´èå´": "Time Range", |
| | | "产éç»è®¡": "Production Statistics", |
| | | "å·¥åºèæåæ": "Process Beat Analysis", |
| | | "ä¸åæ ¼ç»è®¡åæ": "Unqualified Statistics Analysis", |
| | | "å¾
åä¸è¯å": "Pending Defective Products", |
| | | "产åå¤å®è®°å½": "Product Judgment Record", |
| | | "ä¸ç åæº¯": "One-Code Traceability", |
| | | "产线段": "Production Line Segment", |
| | | "è¯¥å·¥åæ²¡æå¯ä½¿ç¨ç产线段": "There are no available production line segments for this work order.", |
| | | "è¯·éæ©äº§çº¿æ®µ": "Please select production line segments", |
| | | "å䏿·»å ä¸è¡": "Add a row above", |
| | | "å䏿·»å ä¸è¡": "Add a row below", |
| | | "å é¤": "Delete", |
| | | "ä¸è½ä¸ºç©º": "Cannot be empty", |
| | | "ç¡®å®": "Confirm", |
| | | "æ¥è¯¢": "search", |
| | | "åæ¶": "Cancel", |
| | | "追溯æ¥è¡¨": "Traceability report", |
| | | "æ¥è¡¨é
ç½®": "Report configuration", |
| | | "å
±": "Total", |
| | | "页": "Pages", |
| | | "å½å第": "Current", |
| | | "æ¯é¡µ": "Per Page", |
| | | "æ¡è®°å½": "Records", |
| | | "第": "th", |
| | | "å·¥åºéæ©": "Process selection", |
| | | "å·¥èºè·¯çº¿": "Process route", |
| | | "å·¥åºæ®µ": "Process section", |
| | | "è¯·éæ©å·¥åºæ®µ": "Please select a process segment", |
| | | "å
¨é¨": "All", |
| | | "å·¥åº": "working procedure", |
| | | "请è¾å
¥å·¥åºåç§°": "Please enter the process name", |
| | | "å·¥åºæ®µåç§°": "Process segment name", |
| | | "å·¥åºç¼å·": "Process number", |
| | | "å·¥åºåç§°": "Process name", |
| | | "æ¥ç": "View", |
| | | "åºå·": "Seq", |
| | | "导å
¥å¤±è´¥": "Import Fail", |
| | | "ä¿åæå": "Save success", |
| | | "æ¥ç屿§": "View Props", |
| | | "å¤å¶": "Copy", |
| | | "éå": "Set", |
| | | "æ¡ä»¶é": "Condition Set", |
| | | "请è¾å
¥æ ç¾å
容": "Please enter label content", |
| | | "NodeDrawer": "èç¹æ½å±", |
| | | "æ´æ°": "Update", |
| | | "å
³é": "Close", |
| | | "确认": "Confirm", |
| | | "å¤åæ¡ä»¶": "Composite Condition", |
| | | "æ¡ä»¶": "Condition", |
| | | "æ ¼å¼é误": "Format error", |
| | | "ææ æ°æ®": "No data available", |
| | | "è¯·éæ©": "Please select", |
| | | "请è¾å
¥": "Please enter", |
| | | "请è¾å
¥æ¥éª¤åç§°": "Please enter the step name", |
| | | "èç¹åç§°éå¤ï¼è¯·æ£æ¥åéè¯": "The node name is duplicated. Please check and try again.", |
| | | "æ¤é": "Undo", |
| | | "æ¢å¤": "Redo", |
| | | "æ¾å¤§": "Enlarge", |
| | | "缩å°": "Reduce", |
| | | "ç¾å": "Beautify", |
| | | "ä¸è½½": "Download", |
| | | "导å
¥": "Import", |
| | | "导åº": "Export", |
| | | "å¯¼åºæå": "Export successful", |
| | | "导å
¥æå": "Import successful", |
| | | "æ´»å¨èç¹": "Active Node" |
| | | }, |
| | | "FormulaManagement": { |
| | | "é
æ¹å¼": "Formula value", |
| | | "åæ°ç±»å": "Parameter type", |
| | | "SOPåç§°": "SOP name", |
| | | "è¯·éæ©ç¶æ": "Please select Status", |
| | | "使ç¨ä¸": "In use", |
| | | "æªä½¿ç¨": "Not in use", |
| | | "-é
æ¹çæ¬ç®¡ç": "-Formula verison Management", |
| | | "å½åçæ¬": "Current version", |
| | | "ç¶æ": "Status", |
| | | "é
æ¹å表": "Formula list", |
| | | "æ¯å¦ç¡®è®¤ä¸å": "Are you sure to issue?", |
| | | "ä¸åæå": "Issuance successful", |
| | | "è¯·éæ©SOP": "Please select SOP", |
| | | "æ°å»ºé
æ¹": "New Formula", |
| | | "ç¼è¾é
æ¹": "Edit Formula", |
| | | "è¯·éæ©ä¸ä¸ªé
æ¹è¿è¡ç¼è¾!": "Please select a formula to edit!", |
| | | "ä»
æ¯æç¼è¾å个é
æ¹!": "Only single formula editing is supported!", |
| | | "å½åé
æ¹æ£å¨ç产ä¸ï¼ä¸å
许ç¼è¾": "The current formula is in production and editing is not allowed.", |
| | | "è¯·éæ©é
æ¹è¿è¡å é¤!": "Please select formulas to delete!", |
| | | "ç产ä¸çé
æ¹ä¸æ¯æå é¤ï¼": "Formulas in production are not supported to be deleted!", |
| | | "é
æ¹å é¤åï¼ç¸å
³çäº§æ°æ®æ æ³æ¢å¤ï¼æ¯å¦ç¡®è®¤å é¤ï¼": "After the formula is deleted, the related production data cannot be recovered. Are you sure to delete it?", |
| | | "å 餿å": "Delete successful", |
| | | "è¯·éæ©ä¸ä¸ªé
æ¹è¿è¡åå»ºå¯æ¬!": "Please select a formula to create a copy!", |
| | | "åªè½éæ©ä¸ä¸ªé
æ¹åå»ºå¯æ¬!": "Only one formula can be selected to create a copy!", |
| | | "è¯·éæ©ä¸ä¸ªé
æ¹è¿è¡çæ¬ç®¡ç!": "Please select a formula for version management!", |
| | | "ä»
æ¯æå个é
æ¹è¿è¡çæ¬ç®¡ç!": "Only single formula version management is supported!", |
| | | "é
æ¹çæ¬ç®¡ç": "Formula Version Management", |
| | | "é
æ¹åç§°ä¸å
许为空ï¼": "The formula name cannot be empty!", |
| | | "é
æ¹ç¼å·ä¸å
许为空ï¼": "The formula code cannot be empty!", |
| | | "å·¥èºè·¯çº¿ä¸å
许为空ï¼": "The process route cannot be empty!", |
| | | "请è¾å
¥é
æ¹ç¼å·": "Please enter the formula code", |
| | | "请è¾å
¥å·¥èºè·¯çº¿": "Please enter the process route", |
| | | "åå»ºå¯æ¬æå": "Copy creation successful", |
| | | "å建æå": "Creation successful", |
| | | "ä¿®æ¹æå": "Modification successful", |
| | | "é
æ¹ç¼å·": "Formula number", |
| | | "é
æ¹çæ¬": "Formula version", |
| | | "å·¥ä½åç§°": "Workstation name", |
| | | "è®°å½æ¶é´": "Recording time", |
| | | "åæ°åç§°": "Parameter name", |
| | | "æ´æ°å
容": "Updated content", |
| | | "è¯·éæ©é
æ¹åç§°": "Please select formula name", |
| | | "è¯·éæ©å·¥åºåç§°": "Please select process name", |
| | | "é
æ¹æ¥å¿.xlsx": "Formula log.xlsx", |
| | | "æä½æå": "Operation successful", |
| | | "åæ°æè¿°": "Parameter description", |
| | | "å卿ªä¿åæ°æ®ï¼æ¯å¦éè¦ä¿å": "There is unsaved data. Do you need to save it?", |
| | | "åæ°å": "Parameter name", |
| | | "æ åå¼": "Standard value", |
| | | "ä¸é": "Lower limit", |
| | | "ä¸é": "Upper limit", |
| | | "设å®å¼": "Set value", |
| | | "宿¶å¼": "Real-time value", |
| | | "è¯·éæ©çæ¬": "Please select version", |
| | | "å·¥åºç±»å": "Process type", |
| | | "SOP": "SOP", |
| | | "è¯·éæ©å·¥åºç±»å": "Please select process type", |
| | | "产åè¯å«ç ": "Product identification code", |
| | | "çæ¬åç§°": "Version name", |
| | | "夿³¨": "Remarks", |
| | | "çæ¬åç§°ä¸è½ä¸ºç©º!": "Version name cannot be empty!", |
| | | "çæ¬åç§°ä¸è½éå¤!": "Version names cannot be duplicated!", |
| | | "æ¯å¦å é¤éä¸ççæ¬": "Whether to delete the selected version", |
| | | "å½åä»
æä¸ä¸ªé
æ¹çæ¬ï¼å é¤å¤±è´¥ï¼": "There is only one formula version currently, and the deletion failed!", |
| | | "çæ¬æ£å¨åºç¨ï¼ä¸å¯å é¤": "The version is currently in use and cannot be deleted", |
| | | "è¯·éæ©ä¸ä¸ªçæ¬": "Please select a version", |
| | | "请å¿éæ©å¤ä¸ªçæ¬æä½ï¼": "Please do not select multiple versions for operation!", |
| | | "å½åçæ¬ä¸å¯åå»ºå¯æ¬": "The current version cannot create a copy", |
| | | "æ¯å¦ç¡®è®¤å°": "Whether to confirm to set", |
| | | "çæ¬è®¾ä¸ºè¯¥é
æ¹å½åçæ¬ï¼": "as the current version of this formula?", |
| | | "é
æ¹åç§°": "Formula name", |
| | | "产ååå·": "Product model", |
| | | "产ååç§°": "Product name", |
| | | "å·¥åºç¼å·": "Process number", |
| | | "å·¥åºæ®µåç§°": "Process segment name", |
| | | "åºå·": "Serial number", |
| | | "ç¼è¾": "Edit", |
| | | "导å
¥": "Import", |
| | | "å·¥èºåæ°": "Process parameters", |
| | | "请è¾å
¥åæ°å": "Please enter parameter name", |
| | | "çæ¬": "Version", |
| | | "宿¶æ´æ°": "Real-time update", |
| | | "åæ¶": "Cancel", |
| | | "æ´æ°": "Update", |
| | | "æ°å»ºçæ¬": "Create a new version", |
| | | "è¯·éæ©æ´æ°å½åçæ¬ææ°å»ºçæ¬ï¼": "Please choose to update the current version or create a new version?", |
| | | "å·¥èºé
æ¹": "Process formula", |
| | | "é
æ¹": "Formula", |
| | | "请è¾å
¥é
æ¹åç§°": "Please enter formula name", |
| | | "请è¾å
¥äº§ååå·": "Please enter product model", |
| | | "é
æ¹å½åçæ¬": "Current version of the formula", |
| | | "å·¥èºè·¯çº¿": "Process route", |
| | | "å·¥åºåç§°": "Process name", |
| | | "å·¥åº": "Process", |
| | | "å·¥åºæ®µ": "Process segment", |
| | | "è¯·éæ©å·¥åºæ®µ": "Please select process segment", |
| | | "å
¨é¨": "All", |
| | | "请è¾å
¥å·¥åºåç§°": "Please enter process name", |
| | | "é
æ¹ä¸å": "Formula distribution", |
| | | "SOPéæ©": "SOP selection", |
| | | "é
æ¹å¼¹çª": "Formula pop-up window", |
| | | "å·¥èºè·¯çº¿è®¾ç½®": "Process route setting", |
| | | "åæ°éæ©": "Parameter selection", |
| | | "ééåæ°": "Acquisition parameters", |
| | | "é
æ¹åæ°": "Formula parameters", |
| | | "请è¾å
¥åæ°åæåæ°æè¿°": "Please enter parameter name or parameter description", |
| | | "éæ©äº§ååå·": "Select product model", |
| | | "产å": "Product", |
| | | "çæ¬ç®¡ç": "Version management", |
| | | "å½åçæ¬ï¼": "Current version:", |
| | | "æ·»å ": "Add", |
| | | "å é¤": "Delete", |
| | | "åå»ºå¯æ¬": "Create a copy", |
| | | "设为å½å": "Set as current", |
| | | "请è¾å
¥çæ¬åç§°": "Please enter version name", |
| | | "ç©æç®¡ç": "Material management", |
| | | "æ·»å æ¡ä»¶": "Add conditions", |
| | | "çé": "Filter", |
| | | "导åº": "Export", |
| | | "é
æ¹ç®¡ç": "Formula management", |
| | | "é
æ¹åºç¨": "Formula application", |
| | | "é
æ¹æ¥å¿": "Formula log", |
| | | "é
æ¹éæ©": "Formula select" |
| | | }, |
| | | "MaterialManagement": { |
| | | "æ¯å¦åæ¶ä¸æ": "Whether to cancel the material", |
| | | "è¯·éæ©ç©æç¼å·è¿è¡å é¤!": "Please select the material code to delete!", |
| | | "æ¹æ¬¡æä½¿ç¨æ»è§": "Overall Usage Overview of Batch Materials", |
| | | "å·¥åºæ®µ": "Process Section", |
| | | "è¯·éæ©å·¥åºæ®µ": "Please select the process section", |
| | | "请è¾å
¥å·¥ä½": "Please enter the workstation", |
| | | "æç´¢": "Search", |
| | | "ä¸å": "Issue", |
| | | "å·¥ä½å表": "Workstation List", |
| | | "æ¹æ¬¡æå表": "Batch Material List", |
| | | "å·¥åºåç§°": "Process Name", |
| | | "å·¥ä½åç§°": "Workstation Name", |
| | | "ä¸æç©æç ": "Loading Material Code", |
| | | "å®é
ç©æç ": "Actual Material Code", |
| | | "è¯·éæ©å
容": "Please select the content", |
| | | "è¯·éæ©æ°æ®": "Please select the data", |
| | | "æ¯å¦éæ°ä¸åç©æç ": "Whether to reissue the material code", |
| | | "ä¸åæå": "Issued successfully", |
| | | "å·¥ä½": "Workstation", |
| | | "è¯·éæ©å·¥ä½": "Please Select Station", |
| | | "è¯·éæ©": "Please Select", |
| | | "请è¾å
¥": "Please Enter", |
| | | "ç¶æ": "Status", |
| | | "éæ©": "Select", |
| | | "æ¹æ¬¡æä¸æ": "Batch material feeding", |
| | | "ä¸æè¯¦æ
": "Loading details", |
| | | "䏿æå": "Loading successful", |
| | | "ä¸å
è®¸åæ¶å¯¹å¤ä¸ªç©æç¼å·ä¸æ!": "", |
| | | "请è¾å
¥ç©æç¼å·": "Please enter the material code", |
| | | "请è¾å
¥åä½": "Please input unit", |
| | | "请è¾å
¥æç´¢": "Please input search", |
| | | "æ°å»ºç©æ": "New Material", |
| | | "ç¼è¾ç©æ": "Edit Material", |
| | | "æä½æå": "Operation successful", |
| | | "è¯·éæ©ä¸ä¸ªç©æè¿è¡ç¼è¾!": "Please select a material to edit!", |
| | | "ä»
æ¯æç¼è¾åä¸ªç©æ!": "Only single material editing is supported!", |
| | | "ç©æå é¤åï¼ç¸å
³çäº§æ°æ®æ æ³æ¢å¤ï¼æ¯å¦ç¡®è®¤å é¤ï¼": "After the material is deleted, the related production data cannot be recovered. Are you sure to delete it?", |
| | | "æ°å»ºç©æç¼å·": "New Material Code", |
| | | "ç¼è¾ç©æç¼å·": "Edit Material Code", |
| | | "ç©æç¼å·å é¤åï¼ç¸å
³çäº§æ°æ®æ æ³æ¢å¤ï¼æ¯å¦ç¡®è®¤å é¤ï¼": "After the material code is deleted, the related production data cannot be recovered. Are you sure to delete it?", |
| | | "å 餿å": "Delete successful", |
| | | "è¯·éæ©ä¸ä¸ªç©æç¼å·è¿è¡ç¼è¾!": "Please select a material code to edit!", |
| | | "ä»
æ¯æç¼è¾åä¸ªç©æç¼å·!": "Only single material code editing is supported!", |
| | | "è¯·éæ©ä¸ä¸ªç©æç¼å·": "Please select a material code", |
| | | "å
¥åºæå": "Warehousing successful", |
| | | "æ ¡åæå": "Calibration successful", |
| | | "ç©æç¼å·ä¸å
许为空ï¼": "The material code cannot be empty!", |
| | | "è¯·éæ©æ¡ç è§å": "Please select the barcode rule", |
| | | "请è¾å
¥ç©æåç§°": "Please enter the material name", |
| | | "请è¾å
¥éæ©ç©æç±»å": "Please enter and select the material type", |
| | | "ç©æåç§°ä¸å
许为空ï¼": "The material name cannot be empty!", |
| | | "ç©æç±»åä¸å
许为空ï¼": "The material type cannot be empty!", |
| | | "åä½ä¸å
许为空ï¼": "The unit cannot be empty!", |
| | | "请è¾å
¥å¤æ³¨è¯´æ": "Please enter the remarks", |
| | | "å建æå": "Creation successful", |
| | | "ä¿®æ¹æå": "Modification successful", |
| | | "å建åºä½": "Create Location", |
| | | "导å
¥æå": "Import successful", |
| | | "导å
¥å¤±è´¥": "Import failed", |
| | | "导å
¥æä»¶æ ¼å¼ä¸æ£ç¡®ï¼è¯·å¯¼å
¥.xlsx/.xlsä¸.csvæ ¼å¼çæä»¶": "The import file format is incorrect. Please import files in.xlsx/.xls and.csv formats.", |
| | | "产ååç§°": "Product Name", |
| | | "产ååå·": "Product Model", |
| | | "ç©æå表": "Material List", |
| | | "导å
¥": "Import", |
| | | "导åº": "Export", |
| | | "夿³¨": "Remarks", |
| | | "ç©æç¼å·å表": "Material Code List", |
| | | "æ·»å ": "Add", |
| | | "ç¼è¾": "Edit", |
| | | "å
¥åº": "Warehousing", |
| | | "æ ¡å": "Calibration", |
| | | "å é¤": "Delete", |
| | | "åºå": "Inventory", |
| | | "产åç ": "Product Code", |
| | | "ä½¿ç¨æ¶é´": "Usage Time", |
| | | "ç©æç ": "Material Code", |
| | | "ç©æä½¿ç¨é": "Material Usage Quantity", |
| | | "æ¶é´èå´": "Time Range", |
| | | "å¼å§æ¶é´": "Start Time", |
| | | "ç»ææ¶é´": "End Time", |
| | | "请è¾å
¥å
³é®å": "Please enter keywords", |
| | | "éæ©äº§ååå·": "Select Product Model", |
| | | "åºå·": "Serial Number", |
| | | "ç©æç¼å·": "Material Code", |
| | | "ç©æåç§°": "Material Name", |
| | | "ç©æç±»å": "Material Type", |
| | | "åä½": "Unit", |
| | | "æ¡ç è§å": "Barcode Rule", |
| | | "夿³¨è¯´æ": "Remarks", |
| | | "ç©æç®¡ç": "Material Management", |
| | | "ç©æè®°å½": "Material Record" |
| | | }, |
| | | "OrderManagement": { |
| | | "工忍¡ç": "Order Template", |
| | | "å¼å§æå": "Start successfully", |
| | | "忢æå": "Stop successfully", |
| | | "çäº§ç¶æ": "Product Status", |
| | | "æªç产": "no Production", |
| | | "å¼å§": "Start", |
| | | "忢": "Stop", |
| | | "å·²æ´æ°": "Has been updated", |
| | | "å
¨é¨": "All", |
| | | "导åº": "Export", |
| | | "å·¥åæååï¼å·²ä¸çº¿äº§åä¼ç»§ç»çäº§ï¼æ¯å¦ç¡®è®¤æåå·¥åï¼": "After the work order is suspended, the products that have already been launched will continue to be produced. Are you sure you want to suspend the work order?", |
| | | "å 餿å": "Delete success", |
| | | "æ¤éæå": "Revocation successful", |
| | | "æ¯å¦ç¡®è®¤å®æå·¥åï¼": "Are you sure to complete the work order?", |
| | | "ç¼è¾å·¥å": "Edit Order", |
| | | "请è³å°éæ©ä¸ä¸ªå·¥åè¿è¡æä½": "Please select at least one work order for operation", |
| | | "å·¥åå é¤åä¸å¯æ¢å¤ï¼æ¯å¦ç¡®è®¤å é¤": "The work order cannot be restored after deletion. Are you sure to delete it", |
| | | "工忤éåï¼ç¶æå为åå§å¾
æ¿æ´»ç¶æ;æ¯å¦ç¡®è®¤æ¤éå·¥åï¼": "After the work order is cancelled, the status changes to the initial pending activation state; Are you sure to cancel the work order?", |
| | | "ä¸é": "No limit", |
| | | "å建工å": "Create Order", |
| | | "请è¾å
¥": "Please Enter", |
| | | "è¯·éæ©ä¸ä¸ªå·¥åè¿è¡æä½": "Please select order only a data of action", |
| | | "æªæ¿æ´»": "Not activated", |
| | | "å·²æå": "Paused", |
| | | "å¾
ç产": "To be produced", |
| | | "已宿": "Completed", |
| | | "å·²ç»æ": "Ended", |
| | | "æåº": "Sort", |
| | | "å·¥åç产è¿åº¦": "Work Order Production Progress", |
| | | "å·¥åºåºå·": "Process Sequence Number", |
| | | "å·¥èºè·¯çº¿çæ¬": "Process Route Version", |
| | | "å·¥èºè·¯çº¿": "Process Route", |
| | | "å·¥åºæ åææ¬ç ": "Process Standard Text Code", |
| | | "å·¥åºåç§°": "Process Name", |
| | | "åä¸å·¥åºææ¬ç ": "Previous Process Text Code", |
| | | "åä¸å·¥åºææ¬ç ": "Next Process Text Code", |
| | | "对åºä¸»å·¥èºè·¯çº¿": "Corresponding Main Process Route", |
| | | "BOMç¼å·": "BOM Number", |
| | | "ç©ææè¿°": "Material Description", |
| | | "æ°é": "Quantity", |
| | | "éè¦è¿½æº¯ä»¶": "Important Traceability Parts", |
| | | "æå±å·¥åº": "Belonging Process", |
| | | "LOTå·": "LOT Number", |
| | | "LOTæè¿°": "LOT Description", |
| | | "LOTç¶æ": "LOT Status", |
| | | "LOTç±»å": "LOT Type", |
| | | "åºåå·": "Serial Number", |
| | | "å¯¼åºæ¨¡æ¿": "Export Template", |
| | | "导å
¥": "Import", |
| | | "ä¸å": "Deliver", |
| | | "æ¿æ´»": "Activate", |
| | | "ç¼è¾": "Edit", |
| | | "æå": "Pause", |
| | | "æ¤é": "Revoke", |
| | | "宿": "Complete", |
| | | "ç»æ": "Finish", |
| | | "å é¤": "Delete", |
| | | "ç产ä¸": "In Production", |
| | | "å·²ç»æ¯ç¬¬ä¸ä½ï¼æ æ³ååä¸è°æ´æåº": "It's already in the first position and cannot be adjusted upward any more.", |
| | | "å·²ç»æ¯æåä¸ä½ï¼æ æ³ååä¸è°æ´æåº": "It's already in the last position and cannot be adjusted downward any more.", |
| | | "è·åå·¥å": "Get Work Order", |
| | | "è¾å
¥è®¢åå·æäº§åLOT ID": "Enter the order number or product LOT ID", |
| | | "ç»æå·¥å": "Finish Work Order", |
| | | "请填åç»æåå ": "Please fill in the reason for finishing.", |
| | | "请填åå·¥åç»æåå ": "Please fill in the reason for the work order to be finished.", |
| | | "工忣å¨çäº§ï¼æ¯å¦å¼ºå¶ç»æï¼": "The work order is in production. Do you want to force it to finish?", |
| | | "æç¤º": "Tip", |
| | | "确认": "Confirm", |
| | | "æä½æå": "Operation successful", |
| | | "è¯·éæ©": "Please Select", |
| | | "éè¦": "Important", |
| | | "ééè¦": "Unimportant", |
| | | "æç´¢": "Search", |
| | | "æ¥è¯¢": "Query", |
| | | "æ¹æ¬¡ç©ææ¸
å": "Batch Bill of Materials", |
| | | "æ¡ç ä¿¡æ¯ï¼": "Barcode Information:", |
| | | "䏿è¿åº¦ï¼": "Feeding Progress:", |
| | | "计åå¼å§ï¼": "Planned Start:", |
| | | "计åç»æï¼": "Planned Finish:", |
| | | "ç©æç¼å·": "Material Code", |
| | | "ç©æåç§°": "Material Name", |
| | | "ç¨æå·¥åº": "Material Usage Process", |
| | | "ç¨é": "Usage Quantity", |
| | | "ä¸æç¶æ": "Feeding Status", |
| | | "æªä¸æ": "Not Fed", |
| | | "已䏿": "Fed", |
| | | "åæ¶": "Cancel", |
| | | "ç¡®å®": "OK", |
| | | "å·¥å夿": "Work Order Material Preparation", |
| | | "æ¿æ´»æå": "Activation Successful", |
| | | "åºç¡ä¿¡æ¯": "Basic Information", |
| | | "å·¥åå·ï¼": "Work Order Number:", |
| | | "产ååå·ï¼": "Product Model:", |
| | | "å·¥èºé
æ¹ï¼": "Process Formula:", |
| | | "è®¡åæ°éï¼": "Planned Quantity:", |
| | | "计åå¼å§æ¶é´ï¼": "Planned Start Time:", |
| | | "计åç»ææ¶é´ï¼": "Planned Finish Time:", |
| | | "åæ®µä¸è½ä¸ºç©º": "Field cannot be empty", |
| | | "è®¡åæ°é请è¾å
¥æ£æ´æ°": "Please enter a positive integer for the planned quantity.", |
| | | "æ´æ°": "Update", |
| | | "æ°å¢": "Add", |
| | | "æå": "Successful", |
| | | "æ¯å¦ä¿åå·¥å设置ï¼": "Do you want to save the work order settings?", |
| | | "æ°å»ºå·¥å": "Create Work Order", |
| | | "æ·»å æ¡ä»¶": "Add Conditions", |
| | | "çé": "Filter", |
| | | "æ¶é´èå´ï¼": "Time Range:", |
| | | "产线段": "Production Line Segment", |
| | | "å¼å§æ¶é´": "Start Time", |
| | | "ç»ææ¶é´": "End Time", |
| | | "å·¥åå·": "Work Order Number", |
| | | "工忥æº": "Work Order Source", |
| | | "计åå¼å§æ¶é´": "Planned Start Time", |
| | | "计åç»ææ¶é´": "Planned Finish Time", |
| | | "产ååå·": "Product Model", |
| | | "å·¥èºé
æ¹": "Process Formula", |
| | | "è®¡åæ°é": "Planned Quantity", |
| | | "æäº§æ°é": "Production Quantity", |
| | | "åæ ¼æ°": "Qualified Quantity", |
| | | "çæ¬¡": "Shift", |
| | | "å®é
å¼å§æ¶é´": "Actual Start Time", |
| | | "å®é
ç»ææ¶é´": "Actual End Time", |
| | | "å·¥åç¶æ": "Work Order Status", |
| | | "è®¢ï¿½ï¿½ç»æåå ": "Order End Reason", |
| | | "å·¥å管ç": "Work Order Management", |
| | | "å·¥åè®°å½": "Work Order Records" |
| | | }, |
| | | "ProcessConfiguration": { |
| | | "产åä¿¡æ¯ä¸åé
ç½®": "Product Information Distribution Configuration", |
| | | "产åä¿¡æ¯ä¸å": "Product Information Distribution", |
| | | "产åä¸åä¿¡æ¯": "Product Information Distribution", |
| | | "产åä¿¡æ¯ä¸å设置": "Product Information Distribution Settings", |
| | | "ç±»å": "Type", |
| | | "ä¸åç±»å": "Issue Type", |
| | | "ä¸åæ°æ®": "Issue Data", |
| | | "æ°æ®æº": "Data Source", |
| | | "å·¥åºæ®µ": "Process Section", |
| | | "æ¼å·¥åºé
置弹çª": "Missing Process Configuration Pop-up Window", |
| | | "æ¾ç¤ºéè": "Visible or Hidden", |
| | | "åºç¡æ°æ®": "Base Data", |
| | | "æç´¢å¼": "Search Value", |
| | | "éæ©çå¼": "Selected Values", |
| | | "å
³é": "Close", |
| | | "确认": "Confirm", |
| | | "éæ©": "Select", |
| | | "鿩工åº": "Select Process", |
| | | "æ´æ°é
ç½®": "Update Configuration", |
| | | "è¯·éæ©é¨å": "Please Select Component", |
| | | "è¯·éæ©äº§çº¿æ®µ": "Please Select Production Line Segment", |
| | | "主产å": "Main Product", |
| | | "è¯·éæ©ä¸ä¸ªé
ç½®ï¼": "Please select a configuration!", |
| | | "请å¿éæ©å¤ä¸ªé
ç½®æä½ï¼": "Please don't select multiple configuration operations!", |
| | | "è¯·éæ©å·¥åºï¼": "Please select a process!", |
| | | "è¯·éæ©äº§çº¿æ®µï¼": "", |
| | | "æ£æµé
ç½®": "Check Config", |
| | | "æ´æ°å·¥åº": "Update Process", |
| | | "æ£æµå·¥åº": "Check Process", |
| | | "导å
¥æå": "Import successful", |
| | | "æ¼å·¥åºæ£æµé
ç½®": "Missing Process Detection Configuration", |
| | | "æ£æµ": "Detection", |
| | | "产åç æ´æ°é
ç½®": "Product Code Update Configuration", |
| | | "æ´æ°": "Update", |
| | | "产åç¶ææ£æµé
ç½®": "Product Status Detection Configuration", |
| | | "å¹é
": "Matching ", |
| | | "é¨å": "Parts", |
| | | "å¹é
é¨å": "Matching Parts", |
| | | "æ£æµé¨å": "Detection Parts", |
| | | "æ´æ°äº§çº¿æ®µ": "Updated Production Line Segment", |
| | | "æ£æµäº§çº¿æ®µ": "Detection Production Line Segment", |
| | | "æ´æ°å·¥åºåç§°": "Updated Process Name", |
| | | "æ£æµå·¥åºåç§°": "Detection Process Name", |
| | | "æ¯å¦å é¤éä¸çé
ç½®": "Whether to delete the selected configuration", |
| | | "ä¿åæåï¼": "Saved successfully!", |
| | | "é
æ¹åç§°": "Formula Name", |
| | | "产åç¶ææ£æµ": "Product Status Detection", |
| | | "æå": "Success", |
| | | "åºå·": "Serial Number", |
| | | "产ååå·": "Product Model", |
| | | "è¯·éæ©æå±äº§ååå·": "Please select the affiliated product model", |
| | | "产线段": "Production Line Segment", |
| | | "è¯·éæ©æå±äº§çº¿æ®µ": "Please select the affiliated production line segment", |
| | | "å·¥åºç¼å·": "Process Code", |
| | | "å·¥åºåç§°": "Process Name", |
| | | "æ¼å·¥åºæ£æµ": "Missing Process Detection", |
| | | "产åç æ´æ°": "Product Code Update", |
| | | "æ·»å ": "Add", |
| | | "çé": "Filter", |
| | | "请è¾å
¥å
³é®å": "Please enter keywords", |
| | | "鿩工åºé
ç½®": "Choose Process Configuration", |
| | | "æ°å¢": "Add", |
| | | "ç¼è¾": "Edit", |
| | | "è¯·éæ©ä¸ä¸ªè®¾ç½®ï¼": "Please select one setting!", |
| | | "请å¿éæ©å¤ä¸ªè®¾ç½®æä½ï¼": "Please don't select multiple setting operations!", |
| | | "å·¥èºè·¯çº¿é¦å·¥åºä¸æ¯æé
ç½®ï¼": "The first process of the process route does not support configuration!", |
| | | "å
³èç©æ": "Related Materials", |
| | | "æ¼å·¥åºæ£æµè®¾ç½®": "Missing Process Detection Settings", |
| | | "产åç æ´æ°è®¾ç½®": "Product Code Update Settings", |
| | | "产åç¶ææ£æµè®¾ç½®": "Product Status Detection Settings", |
| | | "åºæ¬": "Basic", |
| | | "ä¿¡æ¯": "Information", |
| | | "产ååå·ï¼": "Product Model:", |
| | | "å½åå·¥åºï¼": "Current Process:", |
| | | "é
ç½®": "Configuration", |
| | | "å é¤": "Delete", |
| | | "è¿ç¨é
ç½®": "Process Configuration", |
| | | "è¿ç¨è®¾ç½®": "Process Settings" |
| | | }, |
| | | "ProcessManagement": { |
| | | "ç©æåæ°å": "Material Parameter Name", |
| | | "åæ°ä¼ é": "Params Transfer", |
| | | "åæ°åç§°": "Parameter Name", |
| | | "触åä¿¡å·": "Trigger Signal", |
| | | "åå§åé": "Initial Variable", |
| | | "ç®æ åé": "Target Variable", |
| | | "ä¼ éç»æ": "Transfer Result", |
| | | "ç©ææ£æµ": "Material inspection", |
| | | "å·¥ä½ç¼å·": "WorkStation code", |
| | | "请è¾å
¥å·¥ä½ç¼å·": "Please Enter WorkStation code", |
| | | "æ ¹æ®å½åç产åé
æ¹å
³èçBOM表é¢è®¾çç¨éè¿è¡æ£å": "Deduct based on the preset usage of the BOM table associated with the current product formula", |
| | | "è¿ç«ãåºç«ç交äºç±»ååªè½éæ©ä¸ä¸ªï¼è¯·æ£æ¥ï¼": "Only one interaction type of entry and exit can be selected. Please check!", |
| | | "ææ æ°æ®": "No data", |
| | | "è¯·éæ©": "Please select", |
| | | "å·¥åºå表": "WorkSection Report", |
| | | "å·¥ä½å表": "Workstations Report", |
| | | "详æ
": "details", |
| | | "çé": "Filter", |
| | | "æ·»å æ¡ä»¶": "Add Condition", |
| | | "æ·»å å·¥åº": "Add WorkSection", |
| | | "å·¥åºè®¾ç½®": "WorkSection Settings", |
| | | "åç»æ¡ä»¶": "Group Condition", |
| | | "æå±äº§çº¿æ®µ": "Belonging production line segment", |
| | | "è¯·éæ©æå±äº§çº¿æ®µ": "Please select Belonging production line segment", |
| | | "å
³èæµç¨": "Associated Flow", |
| | | "è¯·éæ©å
³èæµç¨": "Please select Associated Flow", |
| | | "åç»": "Group", |
| | | "导å
¥": "Import", |
| | | "导åº": "Export", |
| | | "请è¾å
¥": "Please enter", |
| | | "请è¾å
¥å
³é®å": "Please enter keywords", |
| | | "åºå·": "Number", |
| | | "å·¥åºåç§°": "WorkSection Name", |
| | | "å·¥åºç¼å·": "WorkSection Number", |
| | | "å·¥ä½åç§°": "Workstation Name", |
| | | "æå±å·¥åº": "Belonging WorkSection", |
| | | "è¯·éæ©æå±å·¥åº": "Please select Belonging WorkSection", |
| | | "çæ¿IP": "Dashboard IP", |
| | | "SOPä¿¡å·": "SOP Signal", |
| | | "æ´æ°ç åé": "Update code variable", |
| | | "夿³¨": "Remark", |
| | | "æ¹éé
ç½®": "Batch configuration", |
| | | "åæ°é
ç½®": "Parameter configuration", |
| | | "æ¯æé
ç½®äº§çº¿äº§åæ¡ç ä¸å¯ä¸æçè£
é
ç»å®å
³ç³»": "Support configuration production line product barcode and unique material assembly binding relationship", |
| | | "ç©æäº§åå
³èå·¥åº": "Material product assembly work section", |
| | | "è¿ç«ç»æå¼é
ç½®": "Entry station result value configuration", |
| | | "å·¥åºç»æå¼é
ç½®": "WorkSection result value configuration", |
| | | "è¡¥å
è¯´ææ å°": "Supplementary description mapping relationship", |
| | | "å
³èæ¡ç çæè§å": "Associated barcode generation rule", |
| | | "æ¡ç åç§°": "Barcode name", |
| | | "æµç¨åç§°": "Flow name", |
| | | "éæ©": "Select", |
| | | "å
³èç©æ": "Associated material", |
| | | "å
³é®å": "Keyword", |
| | | "åæ°ä¿¡å·é
ç½®": "Parameter signal configuration", |
| | | "导å
¥æå": "Import success", |
| | | "å¯¼åºæå": "Export success", |
| | | "åè½é
ç½®": "Function configuration", |
| | | "ééåæ°": "Collection parameter", |
| | | "é
æ¹åæ°": "Formula parameter", |
| | | "ä¸è¯åå ": "Defect reason", |
| | | "ç©æåæ°": "Material parameter", |
| | | "å±å¼å·¥åºè¯¦æ
": "Expand work section details", |
| | | "å䏿·»å å·¥åº": "Add work section upwards", |
| | | "å䏿·»å å·¥åº": "Add work section downwards", |
| | | "å建工åºå¯æ¬": "Create work section copy", |
| | | "åå»ºå¯æ¬æå": "Create copy success", |
| | | "å é¤å·¥åº": "Delete work section", |
| | | "æ¯å¦å é¤": "Are you sure to delete", |
| | | "å 餿å": "Delete success", |
| | | "å·¥åº": "WorkSection", |
| | | "导å
¥å¤±è´¥": "Import fail", |
| | | "导å
¥æä»¶æ ¼å¼ä¸æ£ç¡®ï¼è¯·å¯¼å
¥.xlsx/.xlsä¸.csvæ ¼å¼çæä»¶": "Import file format is incorrect, please import .xlsx/.xls and .csv format files", |
| | | "请è¾å
¥å·¥åºåç§°": "Please enter workSection name", |
| | | "è¯·éæ©äº§çº¿æ®µ": "Please select production line segment", |
| | | "ç©æåç§°": "Material name", |
| | | "ç©æç±»å": "Material type", |
| | | "åæ°å": "Parameter name", |
| | | "åæ°æè¿°": "Parameter description", |
| | | "å½åå·¥åºæ°æ®æªä¿åï¼æ¯å¦ç¡®è®¤å
³éï¼": "Current work section data has not been saved, do you want to close?", |
| | | "ä¿åæåï¼æ³¨æé坿µç¨æå¡ï¼": "Save success, please restart the flow service!", |
| | | "产线段": "Production line segment", |
| | | "ç»å®å¯ä¸æ": "Binding unique material", |
| | | "è¿ç«ç»æ": "Entry station result", |
| | | "åºç«ç»æ": "Exit station result", |
| | | "ä¸åå¼": "Issued value", |
| | | "åå§å¼": "Original value", |
| | | "æ å°å¼": "Mapping value", |
| | | "ä¿åæå": "Save success", |
| | | "å±å¼å·¥ä½è¯¦æ
": "Expand workstation details", |
| | | "å䏿·»å å·¥ä½": "Add workstation upwards", |
| | | "å䏿·»å å·¥ä½": "Add workstation downwards", |
| | | "æ·»å å·¥ä½": "Add Workstation", |
| | | "å建工ä½å¯æ¬": "Create workstation copy", |
| | | "å建工ä½å¯æ¬æå": "Create workstation copy success", |
| | | "å é¤å·¥ä½": "Delete workstation", |
| | | "å·¥ä½": "Workstation", |
| | | "å½å工使°æ®æªä¿åï¼æ¯å¦ç¡®è®¤å
³éï¼": "Current workstation data has not been saved, do you want to close?", |
| | | "请è¾å
¥å·¥ä½åç§°": "Please enter workstation name", |
| | | "请è¾å
¥å·¥åºç¼å·": "Please enter workSection Number", |
| | | "ä¸è½ä¸ºç©ºæç©ºç½å符ï¼": "Cannot be empty or blank characters!", |
| | | "çæ¿IPå°å": "Dashboard IP address", |
| | | "请è¾å
¥çæ¿IPå°å": "Please enter dashboard IP address", |
| | | "è¯·éæ©æ´æ°ç ": "Please select update code", |
| | | "æ´æ°ç ": "Update code", |
| | | "è¯·éæ©SOPä¿¡å·": "Please select SOP signal", |
| | | "ç©ææ£éªä¿¡å·": "Material inspection signal", |
| | | "ç©ææ¡ç åé": "Material barcode variable", |
| | | "ç©ææ ¡éªç»æ": "Material check result", |
| | | "ç»å®ç©æ": "Binding material", |
| | | "ç©ææ¡ç ä¿¡æ¯ç¼ååé": "Material barcode information cache variable", |
| | | "ä¸è¯ååå åç§°": "Defect reason name", |
| | | "夿å¼": "Judgment value", |
| | | "ä¸è¯ååå åé": "Defect reason variable", |
| | | "åè½åç§°": "Function name", |
| | | "æå±æµç¨": "Belonging flow", |
| | | "åè½æè¿°": "Function description", |
| | | "åè½é项": "Function option", |
| | | "ééåé": "Collection variable", |
| | | "ä¸åå
³èåé": "Issued related variable", |
| | | "çå¬å
³èåé": "Listen related variable", |
| | | "åè½å段": "Function field", |
| | | "æè¿°": "Description", |
| | | "åéè§å": "Variable rule", |
| | | "ç©æç¼å·": "Material number", |
| | | "å
³èå·¥åº": "Related workSection", |
| | | "åä½": "Unit", |
| | | "è§åç±»å": "Rule type", |
| | | "æ¡ç æ®µç»æ": "Barcode segment composition", |
| | | "æ¡ç 示ä¾": "Barcode example", |
| | | "æ´æ°æ¶é´": "Update time", |
| | | "æ ¡éªç±»å": "Check type", |
| | | "æ ¡éªæ¡ç ": "Check barcode", |
| | | "交äºç±»å": "Interaction type", |
| | | "åè½é¡¹": "Function item", |
| | | "å·¥åºå表-å表": "WorkSection Report-List", |
| | | "å·¥ä½-å表": "Workstations Report-List", |
| | | "å·¥åºå表-æ·»å ": "WorkSection Report-Add", |
| | | "å·¥åºå表-设置": "WorkSection Report-Settings", |
| | | "å·¥åºå表-è¿æ»¤": "WorkSection Report-Filter", |
| | | "å·¥åºå表-åç»": "WorkSection Report-Group", |
| | | "å·¥åºå表-导å
¥": "WorkSection Report-Import", |
| | | "å·¥åºå表-è¾åº": "WorkSection Report-Export", |
| | | "å·¥ä½å表-æ·»å ": "Workstations Report-Add", |
| | | "å·¥ä½å表-æ¹éé
ç½®": "Workstations Report-Batch Settings", |
| | | "å·¥ä½å表-è¿æ»¤": "Workstations Report-Filter", |
| | | "å·¥ä½å表-åç»": "Workstations Report-Group", |
| | | "å·¥ä½å表-导å
¥": "Workstations Report-Import", |
| | | "å·¥ä½å表-è¾åº": "Workstations Report-Export", |
| | | "ç¡®å®": "Confirm", |
| | | "æ¥è¯¢": "search", |
| | | "确认": "Confirm", |
| | | "åæ¶": "Cancel", |
| | | "追溯æ¥è¡¨": "Traceability report", |
| | | "æ¥è¡¨é
ç½®": "Report configuration", |
| | | "å
±": "Total", |
| | | "页": "Pages", |
| | | "å½å第": "Current", |
| | | "æ¯é¡µ": "Per Page", |
| | | "æ¡è®°å½": "Records", |
| | | "第": "th", |
| | | "æä½": "Operation", |
| | | "å¼å¸¸åå ": "Abnormal reason", |
| | | "ç»æè¯´æ": "Result Explanation", |
| | | "ç©ææ£åä¿¡å·": "Material Deduction Signal", |
| | | "ç©ææ¡ç ": "Material Barcode", |
| | | "ç©æç¨éæä¾æ¹å¼": "Material Usage Provision Method", |
| | | "è®¾å¤æä¾": "Provided by Equipment", |
| | | "BOMæä¾": "Provided by BOM", |
| | | "ç©æä½¿ç¨é": "Material Usage Quantity", |
| | | "æ£åç»æ": "Deduction Result", |
| | | "ç©ææ£å": "Material Deduction", |
| | | "å·¥åºç±»å": "Process Type", |
| | | "è¯·éæ©å·¥åºç±»å": "Please select the process type", |
| | | "è¿è¡ç¶æ": "Running State", |
| | | "è¯·éæ©è¿è¡ç¶æ": "Please select the running state", |
| | | "空é²ç¶æï¼å·¥ä½æ²¡æè¿è¡ä¸çå·¥åãä»»å¡": "Idle state, there are no ongoing work orders or tasks at the station", |
| | | "çäº§ç¶æï¼å卿£å¸¸ç产çå·¥å": "Production state, there are normal production work orders", |
| | | "ç¹æ£ç¶æï¼åå¨ç¹æ£çä»»å¡": "Inspection state, there are inspection tasks" |
| | | }, |
| | | "ProductionTracking": { |
| | | "çäº§è¿½è¸ªæ°æ®": "Production Tracking Data", |
| | | "å
¨é¨": "All", |
| | | "ç产è·è¸ª": "Production Tracking", |
| | | "追溯": "Traceability", |
| | | "产ååå·": "Product Model", |
| | | "è¯·éæ©": "Please Select", |
| | | "å·¥åº": "Process" |
| | | }, |
| | | "ProductManagement": { |
| | | "ææ æ°æ®": "No data", |
| | | "产å管ç": "Product management", |
| | | "æ·»å ": "Add", |
| | | "ç¼è¾": "Edit", |
| | | "导å
¥": "Import", |
| | | "导åº": "Export", |
| | | "SOP管ç": "SOP management", |
| | | "SOPé
ç½®": "SOP configuration", |
| | | "å é¤": "Delete", |
| | | "请è¾å
¥äº§ååç§°ã产ååå·ãå产åç®ç ": "Enter product name,model,code", |
| | | "åºå·": "Serial number", |
| | | "产ååç§°": "Product name", |
| | | "产ååå·": "Product model", |
| | | "产åç®å·": "Product code", |
| | | "é
æ¹åç§°": "Recipe name", |
| | | "å·¥èºè·¯çº¿": "Process route", |
| | | "夿³¨": "Remark", |
| | | "é¢è§": "Preview", |
| | | "æ·»å æ¬å°æä»¶": "Add local file", |
| | | "ææ½è³è¿éä¸ä¼ ": "Drag and drop here to upload", |
| | | "å·¥åºæ®µ": "Process segment", |
| | | "è¯·éæ©å·¥åºæ®µ": "Please select a process segment", |
| | | "å
¨é¨": "All", |
| | | "å·¥åº": "Process", |
| | | "请è¾å
¥å·¥åºåç§°": "Enter process name", |
| | | "å·¥æ¥ç®¡ç": "Workstep management", |
| | | "æ°å¢": "Add", |
| | | "éä»¶": "Attachment", |
| | | "å·¥æ¥åå·¥æ¥æè¿°ä¸ºå¿
å¡«": "Workstep and description are required", |
| | | "å·¥æ¥åç§°ä¸å¯ä»¥éå¤": "Workstep name cannot be repeated", |
| | | "å·¥æ¥": "Workstep", |
| | | "æä½æè¿°": "Operation description", |
| | | "è¯·éæ©å·¥åº": "Please select a process", |
| | | "è¯·éæ©éè¦å é¤çå·¥æ¥": "Please select the workstep to be deleted", |
| | | "å·¥åºç¼å·": "Process number", |
| | | "å·¥åºåç§°": "Process name", |
| | | "å·¥åºæ®µåç§°": "Process segment name", |
| | | "æä½æå": "Operation successful", |
| | | "产ååç§°ä¸å
许为空ï¼": "Product name cannot be empty!", |
| | | "请è¾å
¥äº§ååç§°": "Please enter product name", |
| | | "产ååå·ä¸å
许为空ï¼": "Product model cannot be empty!", |
| | | "请è¾å
¥äº§ååå·": "Please enter product model", |
| | | "请è¾å
¥äº§åç®å·": "Please enter product code", |
| | | "å建æå": "Creation successful", |
| | | "ä¿®æ¹æå": "Modification successful", |
| | | "å 餿å": "Deletion successful", |
| | | "è¯·éæ©äº§åè¿è¡å é¤!": "Please select a product to delete!", |
| | | "产åå é¤åï¼ç¸å
³çäº§æ°æ®æ æ³æ¢å¤ï¼æ¯å¦ç¡®è®¤å é¤ï¼": "Product deletion cannot be recovered, are you sure to delete?", |
| | | "æ°å»ºäº§å": "New product", |
| | | "è¯·éæ©ä¸ä¸ªäº§åè¿è¡ç¼è¾": "Please select a product to edit", |
| | | "è¯·éæ©ä¸ä¸ªäº§åè¿è¡æä½!": "Please select a product to operate!", |
| | | "ä»
æ¯æç¼è¾å个产å": "Only support editing a single product", |
| | | "该产ååå·æ£å¨ç产ä¸ï¼ä¸å¯æä½ï¼": "The product model is in production, cannot be operated!", |
| | | "ä»
æ¯æå¯¹ä¸ä¸ªäº§ååå·è¿è¡æä½!": "Only support operating on a single product model!", |
| | | "äº§åæ£å¨ç产ä¸ï¼ä¸å
许ç¼è¾!": "Product is in production, cannot be edited!", |
| | | "ç¼è¾äº§å": "Edit product", |
| | | "ç¡®å®": "Confirm", |
| | | "æ¥è¯¢": "search", |
| | | "确认": "Confirm", |
| | | "åæ¶": "Cancel", |
| | | "追溯æ¥è¡¨": "Traceability report", |
| | | "æ¥è¡¨é
ç½®": "Report configuration", |
| | | "å
±": "Total", |
| | | "页": "Pages", |
| | | "å½å第": "Current", |
| | | "æ¯é¡µ": "Per Page", |
| | | "æ¡è®°å½": "Records", |
| | | "第": "th", |
| | | "产åè¯å«ç ": "Product identification code", |
| | | "请è¾å
¥äº§åè¯å«ç ": "Please enter product identification code" |
| | | }, |
| | | "SystemManagement": { |
| | | "å¹´": "Year", |
| | | "æ": "Month", |
| | | "å¨": "Week", |
| | | "æ¥": "Day", |
| | | "追溯æ¥è¡¨": "Traceability report", |
| | | "çäº§æ°æ®æ¥è¯¢æ¶é¿": "Production data query duration", |
| | | "导åºè®¾ç½®": "Export settings", |
| | | "ç¾åæ¯": "Percentage", |
| | | "è®¡åæ°éçäºæäº§æ°éç»æ": "Planned quantity equals the end of the production quantity", |
| | | "å·¥åå¼å¯é»è¾": "Work order start logic", |
| | | "æåè¡¨é¡ºåºæäº§": "Arrange production according to the list order", |
| | | "å·¥åç»æé»è¾": "Work order end logic", |
| | | "ç»ææé®": "End button", |
| | | "å¼å§æé®": "Start button", |
| | | "èªå¨æ§å¶": "Automatic control", |
| | | "æå¨æ§å¶": "Manual control", |
| | | "工忧嶿¹å¼": "Work order control mode", |
| | | "请è¾å
¥å¿
填项": "Please enter the required items", |
| | | "è¿æ¥æå": "Connection successful", |
| | | "æå°è®¾ç½®": "Print settings", |
| | | "ä¸è½½": "Download", |
| | | "æµè¯é¾æ¥": "Test link", |
| | | "å¤å¶": "Copy", |
| | | "å é¤": "Delete", |
| | | "åºå·": "Serial number", |
| | | "请è¾å
¥æ¨¡æ¿è·¯å¾": "Please enter the template path", |
| | | "模æ¿è·¯å¾": "Template path", |
| | | "请è¾å
¥ ip": "Please enter the IP", |
| | | "请è¾å
¥æå°æºåç§°": "Please enter the printer name", |
| | | "æå°æºåç§°": "Printer name", |
| | | "请è¾å
¥": "Please Enter", |
| | | "请è¾å
¥èªå®ä¹åç§°": "Please Enter Custom Name", |
| | | "èªå®ä¹åç§°": "Custom name", |
| | | "ææ¬åç§°": "Text name", |
| | | "ç³»ç»ææ¬èµæºï¼ç¨æ·å¯èªå®ä¹å
¶å±ç¤ºææ¬": "System text resources, users can customize their display text", |
| | | "ææ¬èµæº": "Text Resource", |
| | | "å·¥å设置": "Order Settings", |
| | | "ææ¬è®¾ç½®": "Text Settings", |
| | | "æ´æ°é
ç½®": "Update configuration", |
| | | "产线设置": "Line Settings", |
| | | "产线代ç ": "Line Code", |
| | | "èªå®ä¹è¾å
¥ï¼é¿åº¦ä¸º20å符": "Custom input, length is 20 characters", |
| | | "请è¾å
¥äº§çº¿ä»£ç ": "Please enter the line code", |
| | | "设置产线代ç ï¼ä½ä¸ºäº§çº¿çå¯ä¸æ è¯ä»£ç ": "Set the line code as the unique identifier for the line", |
| | | "äº§çº¿ç»æ": "Line Structure", |
| | | "产线-å·¥åº-å·¥ä½": "Line-Process-Station", |
| | | "产线-产线段(工段)-å·¥åº-å·¥ä½": "Line-Line Segment (Process Segment)-Process-Station", |
| | | "设置产线ç屿¬¡ç»æï¼ç¨äºå·¥åºç产线建模": "Set the hierarchy of the line for process line modeling", |
| | | "è°è¯æ¨¡å¼": "Debug Mode", |
| | | "å¯ç¨è°è¯æ¨¡å¼": "Enable Debug Mode", |
| | | "å¼": "On", |
| | | "å
³": "Off", |
| | | "å¯ç¨åæ¯æå·¥åä¸ååä¿®æ¹å·¥åºé
ç½®ãå·¥èºé
æ¹è¦æ±": "Support modifying process configuration and process recipe requirements after the work order is issued", |
| | | "产å管ç": "Product Management", |
| | | "SOPé
ç½®": "SOP Configuration", |
| | | "ç¦ç¨": "Disable", |
| | | "å¯ç¨": "Enable", |
| | | "å·¥èºé
æ¹": "Process Recipe", |
| | | "ä¸åæ¹å¼": "Distribution Method", |
| | | "ä¸åå·¥åèå¨é
æ¹ä¸å": "Distribute recipe along with work order", |
| | | "é
æ¹åºç¨é¡µé¢æå¨ä¸å": "Manual distribution on recipe application page", |
| | | "å·¥åºè¯å«äº§åæ¶ä¸åé
æ¹": "Distribute recipe when the process gets the product", |
| | | "é
置工èºé
æ¹çä¸åæ¹å¼": "Configure the distribution method of the process recipe", |
| | | "åè½æ¨¡å": "Functional Module", |
| | | "å·¥åç®¡çæ¨¡å": "Order Management Module", |
| | | "产线段å®ä¹": "Line Segment Definition", |
| | | "ç³»ç»è®¾ç½®å¯ç¨åï¼æ¯æå¯¹äº§çº¿æ®µå®ä¹": "Support line segment definition after system settings are enabled", |
| | | "产线段å é¤åï¼å¼ç¨å
³ç³»ä¸å¹¶å é¤": "When the line segment is deleted, the reference relationships are deleted together", |
| | | "è¿ç¨è®¾ç½®": "Process Settings", |
| | | "æ£æµæ¶é´èå´": "Detection Time Range", |
| | | "é
置产åç¶ææ£æµãæ¼å·¥åºãéç å产åç æ´æ°ç¸å
³ä¸å¡å¨è¿½æº¯æ¥è¡¨çæ°æ®æ¥è¯¢èå´": "Configure the data query range for product status detection, missing process, duplicate code, and product code update related business in traceability reports", |
| | | "è¿ç¨åæ°": "Process Parameters", |
| | | "è¿ä¿®æ°æ®å±ç¤º": "Rework Data Display", |
| | | "å±ç¤ºæææ°æ®": "Show All Data", |
| | | "å±ç¤ºææ°æ°æ®": "Show Latest Data", |
| | | "éæ©è¿ä¿®äº§åçè¿ç¨åæ°å±ç¤ºæ¹å¼": "Choose the display method of process parameters for reworked products", |
| | | "ä¸è¯å管ç": "Defective Product Management", |
| | | "å¤å®ç»æéæ©é¡¹": "Judgment Result Options", |
| | | "设å¤è¿ä¿®": "Equipment Repair", |
| | | "人工è¿ä¿®": "Manual Repair", |
| | | "äº§åæ¥åº": "Product Scrap", |
| | | "NGåæµåº": "NG Product Outflow", |
| | | "éæ©ä¸åæ ¼åå¤ççå¤å®ç»æé项": "Choose judgment result options for defective product handling", |
| | | "产线段ä¸å¯éå¤ï¼è¯·æ£æ¥": "", |
| | | "ä¿åæå": "Save Success", |
| | | "è¿": "In the past ", |
| | | "天": "days", |
| | | "产线段åç§°": "Name of production line segment", |
| | | "请è¾å
¥äº§çº¿æ®µåç§°": "Please enter the name of the production line segment", |
| | | "å 工产ååç§°": "Processing product name", |
| | | "请è¾å
¥å 工产ååç§°": "Please enter the name of the processed product", |
| | | "æä½": "operation", |
| | | "éç¨è®¾ç½®": "General settings", |
| | | "åè½è®¾ç½®": "Function settings", |
| | | "åºæ¬è®¾ç½®": "Basic settings", |
| | | "ä¸è¯å设置": "Defective product settings", |
| | | "é
æ¹æ§å¶": "Formula control", |
| | | "ç³»ç»è®¾ç½®": "System settings", |
| | | "å¼å¯åï¼äº§åç®¡çæ¨¡åï¼æä¾SOP管çæé®ï¼å¯ä¸ä¼ ç»´æ¤SOPæä»¶": "After activation, the Product Management module provides an SOP management button for uploading and maintaining SOP files", |
| | | "å
³éåï¼å·¥å模åä¸å¯ç¨ï¼ææç产æµç¨ä¸åæ¶åå·¥ååè½": "After deactivation, the Work Order module is unavailable and all production processes no longer involve the work order function", |
| | | "é«çº§è®¾ç½®": "Advanced settings" |
| | | }, |
| | | "TraceManagement": { |
| | | "ä¸çº¿æ¶é´ä¸ºæ»è¡¨é
ç½®ä¸æ«å·¥åºçè®°å½æ¶é´": "The online time is the recording time of the final process in the summary table configuration", |
| | | "é¨å": "Parts", |
| | | "é¨ååç§°": "Parts Name", |
| | | "é¨åæ¥æºå·¥åº": "Parts Source Process", |
| | | "è¯·éæ©è§£æè§å": "Please select the parse rule", |
| | | "导åºä¸ï¼è¯·ç¨å...": "Exporting, please wait...", |
| | | "æ¶é´èå´ä¸è½è¶
è¿": "The time range cannot exceed", |
| | | "请è¾å
¥æ»è¡¨åç§°": "Please enter the total table name", |
| | | "å¹´": "Year", |
| | | "æ": "Month", |
| | | "å¨": "Week", |
| | | "天": "Day", |
| | | "ä¿åæå": "Save successful", |
| | | "è§£æè§å": "Parse Rule", |
| | | "æ¡ç 段": "Barcode Segment", |
| | | "追溯": "Trace", |
| | | "追溯æ¥è¡¨.xlsx": "Traceability Report.xlsx", |
| | | "å·¥åº/æ»è¡¨": "Process/General List", |
| | | "ææ°å å·¥æ¶é´ä¸ºäº§åæè¿å å·¥æ¶é´": "The latest processing time is the latest processing time of the product", |
| | | "ä¸çº¿æ¶é´ä¸ºå·¥èºè·¯çº¿é¦å·¥åºçè®°å½æ¶é´": "The online time is the recorded time of the first process of the process route", |
| | | "è¿ä¿®å¤å®": "Repair Flag", |
| | | "ç¹æ£ID": "Inspect ID", |
| | | "ç¹æ£ä»»å¡åç§°": "Inspection task name", |
| | | "ç©æåæ°": "Material parameter", |
| | | "éæ©åæ°ç±»å": "Select params type", |
| | | "追溯æ¥è¡¨": "Traceability Report", |
| | | "æ¥è¡¨é
ç½®": "Report Configuration", |
| | | "请è¾å
¥èªç¶æ°ï¼": "Please enter a natural number!", |
| | | "è¾å
¥æ°é大äºåæ°æ°éï¼è¯·éæ°è¾å
¥": "The input quantity is greater than the parameter quantity. Please enter again.", |
| | | "å»ç»åæ°ä¸è½å
å«å¤çº§è¡¨å¤´ï¼è¯·éæ°è¾å
¥": "The frozen column count cannot include multi-level headers. Please enter again.", |
| | | "ä¸å¡å段é
ç½®": "Business Field Configuration", |
| | | "å±ç¤ºé
ç½®": "Display Configuration", |
| | | "æ»è¡¨é
ç½®": "Overall Table Configuration", |
| | | "ä¿åæåï¼": "Saved successfully!", |
| | | "ä¿å失败ï¼": "Failed to save!", |
| | | "æç¤º": "Tip", |
| | | "æ¯å¦å é¤": "Do you want to delete?", |
| | | "æ¯": "Yes", |
| | | "å¦": "No", |
| | | "åºå·": "Serial Number", |
| | | "产ååç§°": "Product Name", |
| | | "产ååå·": "Product Model", |
| | | "夿³¨": "Remarks", |
| | | "ææ æ°æ®": "No data available", |
| | | "请å¾éå¤éæ¡ï¼": "Please check the checkbox!", |
| | | "è¯·éæ©å·¥åºï¼": "Please select a process!", |
| | | "è¯·éæ©åæ°ï¼": "Please select parameters!", |
| | | "ä¸é": "Upper Limit", |
| | | "æä½": "Operation", |
| | | "ä¿®æ¹": "Modify", |
| | | "æ»è¡¨åç§°": "Overall Table Name", |
| | | "ç»åå·¥åº": "Combined Process", |
| | | "æä½æ¶é´": "Operation Time", |
| | | "æä½äºº": "Operator", |
| | | "æ¥ç": "View", |
| | | "æ°å»º": "New", |
| | | "å·¥åºæ®µ": "Process Segment", |
| | | "å·¥åºåç§°": "Process Name", |
| | | "éæ©": "Select", |
| | | "å é¤": "Delete", |
| | | "æ°å»ºæ»è¡¨": "New Overall Table", |
| | | "ä¿®æ¹æ»è¡¨": "Modify Overall Table", |
| | | "å
±": "Total", |
| | | "页": "Pages", |
| | | "å½å第": "Current", |
| | | "æ¯é¡µ": "Per Page", |
| | | "æ¡è®°å½": "Records", |
| | | "å¯¼åºæ¶é´èå´": "Export Time Range", |
| | | "å·¥åº": "Process", |
| | | "åæ°": "Parameter", |
| | | "ä¸éå¼": "Upper Limit Value", |
| | | "ä¸éå¼": "Lower Limit Value", |
| | | "è¿å": "Restore", |
| | | "å·¥åºåæ°ç±»å": "Process Parameter Type", |
| | | "å·¥åºåæ°": "Process Parameter", |
| | | "产线段åç§°": "Production Line Segment Name", |
| | | "å·¥åºç¼å·": "Process Number", |
| | | "åæ°ç±»å": "Parameter Type", |
| | | "åæ°åç§°": "Parameter Name", |
| | | "ééåæ°": "Collected Parameters", |
| | | "ä¸ååæ°": "Issued Parameters", |
| | | "æ¯å¦åæ ¼": "Qualified or Not", |
| | | "æ¶é´èå´": "Time Range", |
| | | "ç©æè¯å«ç ": "Material Identification Code", |
| | | "å·¥åå·": "Work Order Number", |
| | | "è¿ç¨åæ°æ²çº¿": "Process Curve Parameters", |
| | | "导åº": "Export", |
| | | "å å·¥æ°": "Processing Quantity", |
| | | "åæ ¼æ°": "Qualified Quantity", |
| | | "åæ ¼ç": "Pass Rate", |
| | | "ä¸åæ ¼æ°": "Unqualified Quantity", |
| | | "ä¸åæ ¼ç": "Failure Rate", |
| | | "å»ç»åæ°": "Frozen Column Count", |
| | | "åæ®µåç§°": "Field Name", |
| | | "æ°æ®æº": "Datasource", |
| | | "éç¨åå·": "Auto mode", |
| | | "è®°å½æ¶é´": "Recording time", |
| | | "æ·»å ": "Add", |
| | | "æ¥è¯¢": "Search", |
| | | "产åID": "Product ID", |
| | | "æ´æ°ç ": "Update Code", |
| | | "æ¨¡ç³æ¥è¯¢": "Fuzzy Query", |
| | | "精确æ¥è¯¢": "Accurate query", |
| | | "å
¨é¨": "All", |
| | | "导åºç¡®è®¤": "Export Confirmation", |
| | | "ä¸é": "No limit", |
| | | "ä¸é": "Lower limit", |
| | | "请è¾å
¥": "Please enter the content", |
| | | "è¯·éæ©": "Please Select", |
| | | "请è¾å
¥æç´¢": "Please input search", |
| | | "å建æåï¼": "Create successfully", |
| | | "请å¾é两个æä¸¤ä¸ªä»¥ä¸çå·¥åºï¼": "Please check two or more processes!", |
| | | "ç»ææ¶é´ä¸è½å°äºå¼å§æ¶é´": "The end time cannot be less than the start time", |
| | | "宿¶": "Real time", |
| | | "åå²": "History", |
| | | "å·¥åºæ¥æºåæ¢": "Process source switching", |
| | | "å·¥åºéæ©": "Process selection", |
| | | "忥工èºè·¯çº¿": "Synchronous process route", |
| | | "èªå®ä¹éæ©": "Custom Selection", |
| | | "è¿ç¨åæ°": "Process Parameters", |
| | | "é
æ¹åæ°": "Formula Parameters", |
| | | "ç©æç ": "Material Code", |
| | | "请è¾å
¥ä¸ç ": "Please enter the code", |
| | | "ä¸ä¼ æå": "Upload successful", |
| | | "请è¾å
¥æ¥è¯¢å
容ï¼": "Please enter the query content!", |
| | | "å䏿å
¥ä¸è¡": "Insert a row upward", |
| | | "å䏿å
¥ä¸è¡": "Insert a row downward", |
| | | "å¯¼åºæå": "Export successful", |
| | | "æä½æå": "Operation successful", |
| | | "导å
¥å¤±è´¥ï¼è¯·æ£æ¥æä»¶æ°æ®": "Import failed. Please check the file data", |
| | | "ä¸ç ": "One code", |
| | | "æ²çº¿": "Curve", |
| | | "ä½ç§»(mm)": "Displacement (mm)", |
| | | "åå(N)": "Pressure (N)", |
| | | "ä¸éï¼": "Lower limit:", |
| | | "ä¸éï¼": "Upper limit:", |
| | | "宿¶ï¼": "Real-time:", |
| | | "ç»æï¼": "Result:", |
| | | "å®é
å¼ï¼": "Actual value:", |
| | | "设å®å¼ï¼": "Set value:", |
| | | "ç©ææ¡ç ï¼": "Material barcode:", |
| | | "æ¹é导åº": "Batch Export", |
| | | "æ¹é导åºç¡®è®¤": "Batch Export Confirmation", |
| | | "è¿è¡æ¹é导åº": "Perform Batch Export", |
| | | "说æï¼": "Instructions:", |
| | | "1ãä¸è¿°è¾å
¥æ¡ç ï¼éæ¯æ£ç¡®çæ»æç ãæ§è¡å¨ç ãéä½ç ãçµæºç ï¼PCBAç çï¼äº§åç æç©æç ï¼ï¼": "1. The following input barcodes: They need to be correct assembly codes, actuator codes, valve body codes, motor codes, PCBA codes, etc. (product codes or material codes);", |
| | | "2ã导å
¥æä»¶æ ¼å¼è¦æ±ä¸º.xlsx/.xlsï¼": "2. The format of the imported file is required to be.xlsx/.xls;", |
| | | "3ãç³»ç»ä¼æ ¹æ®è¾å
¥æ¡ç æ¥è¯¢ç¸å
³çå 工信æ¯è¿è¡å¯¼åºã": "3. The system will query the relevant processing information according to the input barcodes for export.", |
| | | "è¾å
¥æ¡ç æ°æ®ï¼": "Input barcode data:", |
| | | "导å
¥": "Import", |
| | | "ä¸ç åæº¯": "One-Code Traceability", |
| | | "ä¸ä¼ MES": "Upload MES", |
| | | "NGå·¥åºï¼": "NG Process:", |
| | | "è¾å
¥IDï¼": "Input ID:", |
| | | "产ååå·ï¼": "Product Model:", |
| | | "æ¯å¦åæ ¼ï¼": "Whether Qualified:", |
| | | "OK": "Qualified", |
| | | "NG": "Not Qualified", |
| | | "产åIDï¼": "Product ID:", |
| | | "æ´æ°ç ï¼": "Update Code:", |
| | | "è®°å½æ¶é´ï¼": "Record Time:" |
| | | }, |
| | | "QualityManagement": { |
| | | "è§£ç»": "Unbind", |
| | | "ä¸è§£ç»": "Bind", |
| | | "ç©æå¤ç": "MATERIAL HANDLING", |
| | | "æ¹éæä½": "bulk operation", |
| | | "ç©æè§£ç»": "Unbinding of materials", |
| | | "请è¾å
¥ç©æåç§°": "Please enter the material name", |
| | | "æ ¹æ®æéçè¿ä¿®å·¥åºå±ç¤º": "Display based on the selected repair process", |
| | | "ç©æåç§°": "Material Name", |
| | | "ç©æç¼å·": "Material Code", |
| | | "ç©ææ¡ç ": "Material Barcode", |
| | | "ç©æç±»å": "Material Type", |
| | | "åä½": "Unit", |
| | | "ç¨é": "Dosage", |
| | | "æä½": "Operation", |
| | | "è¯·éæ©éè¦æä½çæ°æ®": "Please Need Data", |
| | | "åæ°ä¸é": "Parameter Down", |
| | | "åæ°ä¸é": "Parameter Up", |
| | | "åæ°å¼": "Parameter Value", |
| | | "åæ°åç§°": "Parameter Name", |
| | | "å
¨é¨": "All", |
| | | "åå æªç¥": "Reason unknown", |
| | | "æç¤º": "Prompt", |
| | | "ç¡®å®": "Confirm", |
| | | "åæ¶": "Cancel", |
| | | "产åå¤å®": "Product Judgment", |
| | | "åºç¡ä¿¡æ¯": "Basic Information", |
| | | "ææ æ°æ®": "No Data", |
| | | "çäº§æ°æ®": "Production Data", |
| | | "å±ç¤ºè¯¥äº§åå¨å å·¥è¿çå·¥åºï¼ä¸è¯å·¥åºä»¥çº¢è²æ è®°": "Display the processes that the product has been processed through, and mark the defective processes in red", |
| | | "å·¥åº": "Process", |
| | | "è®°å½æ¶é´": "Record Time", |
| | | "以å¤å®æ¶é´æäº¤": "Submit with the judgment time", |
| | | "ä¸è¯åå¤ç": "Defective Product Handling", |
| | | "OK": "Qualified", |
| | | "NG": "Not Qualified", |
| | | "æ°æ®è¡¥å
": "Data Supplement:", |
| | | "å
³é失败ï¼è¯·å
å é¤å·²æ·»å å·¥åº": "Closing failed. Please delete the added processes first.", |
| | | "å¤å®æå": "Judgment Successful", |
| | | "ä¸è¯åå é
ç½®": "Defective Reason Configuration", |
| | | "请è¾å
¥å
³é®å": "Please Enter Keywords", |
| | | "å é¤": "Delete", |
| | | "ä¸è¯åå ä¸è½ä¸ºç©º": "Defective reason cannot be empty", |
| | | "ä¿åæåï¼": "Saved successfully!", |
| | | "ä¿å失败ï¼": "Save failed!", |
| | | "çé": "Filter", |
| | | "导åº": "Export", |
| | | "å¤å®ç»æ": "Judgment Result", |
| | | "æ¯å¦åæ ¼": "Whether Qualified", |
| | | "è¿ä¿®å·¥åº": "Repair Process", |
| | | "å¤å®äººå": "Judgment Personnel", |
| | | "å¤å®æ¶é´": "Judgment Time", |
| | | "å¤å®è¯¦æ
": "Judgment Details", |
| | | "å¤ç说æ": "Processing Instructions", |
| | | "æ¶é´èå´æå¤§è·¨åº¦ä¸º60天": "The maximum time range span is 60 days", |
| | | "产åå¤å®è®°å½.xlsx": "Product Judgment Record.xlsx", |
| | | "æ·»å ": "Add", |
| | | "产ååå·": "Product Model", |
| | | "å¤å®": "Judge", |
| | | "é
ç½®": "Configure", |
| | | "æ¶é´èå´ï¼": "Time Range:", |
| | | "产åç ": "Product Code", |
| | | "å·¥åå·": "Work Order Number", |
| | | "请è¾å
¥": "Please Enter", |
| | | "åºå·": "Serial Number", |
| | | "ä¸è¯å·¥åº": "Defective Process", |
| | | "ä¸è¯åå ": "Defective Reason", |
| | | "æåè®°å½æ¶é´": "Last Record Time", |
| | | "å¼å§æ¶é´ä¸è½å¤§äºç»ææ¶é´": "The start time cannot be greater than the end time", |
| | | "æ¶é´èå´æå¤§è·¨åº¦ä¸º90天": "The maximum time range span is 90 days", |
| | | "å¾
åä¸è¯å": "Pending Defective Products", |
| | | "产åå¤å®è®°å½": "Product Judgment Record" |
| | | }, |
| | | "SopWidgetBox": { |
| | | "请é
ç½®ä¸å¡å段åé": "Please Configture bussiness field variable", |
| | | "æå": "Success", |
| | | "é误": "Error", |
| | | "请è¾å
¥ç©æç ": "Please Enter Material Code", |
| | | "ç©æåç§°": "Material Name", |
| | | "ç©æç¼å·": "Material Code", |
| | | "ç©æç±»å": "Material Type", |
| | | "ç©æç ": "Material Code", |
| | | "åæ°åç§°": "Parameter Name", |
| | | "ä¸é": "Upper Limit", |
| | | "ä¸é": "Lower Limit", |
| | | "æ°å¼": "Value", |
| | | "请è¾å
¥æ°å¼": "Please Enter Value", |
| | | "å·²æ´æ°": "Has been updated", |
| | | "å·¥åºéæ©": "Process Selection", |
| | | "è¯·éæ©å·¥åº": "Please Select Process", |
| | | "å·¥ä½éæ©": "Station Selection", |
| | | "è¯·éæ©å·¥ä½": "Please Select Station", |
| | | "请è¾å
¥": "Please Enter", |
| | | "ç产è¾å
¥": "Production Input", |
| | | "ç产æ§å¶": "Production Control", |
| | | "对ä¸èµ·ï¼æ¨çæµè§å¨ä¸æ¯æè¯¥è§é¢æ ¼å¼": "Sorry, your browser does not support this video format", |
| | | "ææ æä»¶": "No files available", |
| | | "ææ å¾ç": "No pictures available", |
| | | "åºå·": "Serial Number", |
| | | "å·¥æ¥": "Work Step", |
| | | "æä½æè¿°": "Operation Description", |
| | | "ç¶æ": "Status" |
| | | }, |
| | | "StationBeatAnalysis": { |
| | | "饼å¾": "Pie chart", |
| | | "å·¥åºå¹³åå¼": "Process average value", |
| | | "åæå·¥åº": "Analyze the process", |
| | | "å·¥åºå 工卿ï¼sï¼": "Process processing cycle (s)", |
| | | "产åç ": "Product Code", |
| | | "çæ¬¡å计": "Total number of shifts", |
| | | "å·¥åºåç»": "Process group", |
| | | "å·¥ä½ç论å 工卿": "Station theoretical processing cycle", |
| | | "å·¥ä½è¯¦æ
åæ": "Station detail analysis", |
| | | "åæå·¥ä½": "Analysis station", |
| | | "ææ": "All", |
| | | "å·¥ä½å¨å¶åçå¾
æ
åµå¯¹æ¯": "Station production waiting comparison", |
| | | "ææä¸": "Monday", |
| | | "ææäº": "Tuesday", |
| | | "ææä¸": "Wednesday", |
| | | "ææå": "Thursday", |
| | | "ææäº": "Friday", |
| | | "ææå
": "Saturday", |
| | | "æææ¥": "Sunday", |
| | | "å·¥ä½åç§°": "Station name", |
| | | "å·¥ä½äº§éåå¸åååå¹
度": "Station output distribution and change amplitude", |
| | | "å·¥ä½å å·¥è½å对æ¯": "Station processing capability comparison", |
| | | "å使¶é´äº§é": "Unit time output", |
| | | "å·¥ä½å¹³åå¼": "Station average value", |
| | | "å å·¥ç»æåç»": "Processing result grouping", |
| | | "产åå 工详æ
": "Product processing details", |
| | | "å·¥ä½è¿è¡æ¥å¿": "Station operation log", |
| | | "åä½äº§åçå¾
æ¶é¿": "Unit product waiting time", |
| | | "å¾
å å·¥æ°é": "Number of waiting processing", |
| | | "åä½äº§åå 工卿": "Unit product processing cycle", |
| | | "ç§»å¨æå·®MR": "Range control chart", |
| | | "åçå·¥ä½": "Occurrence station", |
| | | "çäº§çæ¬¡": "Production shift", |
| | | "è¿ç«æ¶é´": "Arrival time", |
| | | "åºç«æ¶é´": "Departure time", |
| | | "å å·¥ç»æ": "Processing result", |
| | | "å·¥ä½å 工卿ï¼sï¼": "Station processing cycle (s)", |
| | | "è¿è¡ç¶æ": "Running status", |
| | | "å¼å§æ¶é´": "Start time", |
| | | "ç»ææ¶é´": "End time", |
| | | "æç»æ¶é¿ï¼sï¼": "Duration (s)", |
| | | "确认": "Confirm", |
| | | "åæ¶": "Cancel", |
| | | "ææ æ°æ®": "No data", |
| | | "å
±": "Total", |
| | | "页": "Pages", |
| | | "å½å第": "Current", |
| | | "æ¯é¡µ": "Per Page", |
| | | "æ¡è®°å½": "Records", |
| | | "第": "th", |
| | | "æä½": "Operation", |
| | | "产é": "Production Volume", |
| | | "æ¶é´åç»": "Time Grouping", |
| | | "产éç»è®¡": "Production Statistics", |
| | | "å·¥åºåç§°": "Process Name", |
| | | "ä¿åæå": "Saved successfully", |
| | | "ææ": "Week", |
| | | "å·¥åºäº§éåå¸åååå¹
度": "Distribution and Magnitude of Changes in Process Output", |
| | | "忝åéå¹
": "Year-on-year Increase/Decrease", |
| | | "ç¯æ¯åéå¹
": "Sequential Increase/Decrease", |
| | | "åæ ¼æ°é": "Qualified Quantity", |
| | | "ä¸è¯æ°é": "Unqualified Quantity", |
| | | "产éï¼pcs": "Production: pcs", |
| | | "å¹
度ï¼": "Amplitude:", |
| | | "çæ¬¡åç»": "Shift Grouping", |
| | | "å·¥åºå å·¥è½å对æ¯": "Comparison of Workstation Processing Capabilities", |
| | | "å使¶é´äº§éï¼pcs/h": "Production per Unit Time: pcs/h", |
| | | "ç论å 工卿": "Theoretical Processing Cycle", |
| | | "å®é
å 工卿": "Actual Processing Cycle", |
| | | "åä½äº§åå 工卿ï¼s": "Unit Product Processing Cycle: s", |
| | | "å·¥åºå¨å¶åçå¾
æ
åµå¯¹æ¯": "Comparison of Work-in-Progress Waiting Status in Processes", |
| | | "åä½äº§åçå¾
æ¶é¿ï¼s": "Unit Product Waiting Time: s", |
| | | "å¾
å å·¥æ°éï¼pcs": "Quantity to be Processed: pcs", |
| | | "ç§»å¨æå·®æ§å¶å¾": "Moving Range Control Chart", |
| | | "UCL": "Upper Control Limit", |
| | | "CL": "Center Line", |
| | | "LCL": "Lower Control Limit", |
| | | "颿°": "Frequency", |
| | | "èæåæ": "Beat Analysis", |
| | | "产线设置": "Production Line Settings", |
| | | "çäº§æ¥æ": "Production Date", |
| | | "ç®æ 产é": "Target Production", |
| | | "请è¾å
¥": "Please Enter", |
| | | "ä¿å": "Save", |
| | | "å·¥åºç论å 工卿": "Theoretical Processing Cycle of Processes", |
| | | "å·¥åºè¯¦æ
åæ": "Process Detail Analysis", |
| | | "产线æ´ä½æ¦åµ": "Overall Production Line Overview", |
| | | "彿¥äº§éï¼pcsï¼": "Daily Production (pcs)", |
| | | "ä¸å¨åæ¯": "Year-on-year Comparison with Last Week", |
| | | "æ¨æ¥ç¯æ¯": "Sequential Comparison with Yesterday", |
| | | "å使¶é´äº§éï¼pcs/hï¼": "Production per Unit Time (pcs/h)", |
| | | "å¹³åç产èæï¼sï¼": "Average Production Rhythm (s)", |
| | | "彿¥å®æç": "Daily Completion Rate", |
| | | "产åå 工卿åæ": "Product Processing Cycle Analysis", |
| | | "æ ·æ¬æ°": "Sample Size", |
| | | "å¹³åå¼": "Average Value", |
| | | "æå¤§å¼": "Maximum Value", |
| | | "æå°å¼": "Minimum Value", |
| | | "æå·®å¼": "Range Value", |
| | | "颿°åå¸ç´æ¹å¾": "Frequency Distribution Histogram", |
| | | "æ¥è¯¢æ¶é´é´éä¸è½è¶
è¿30天": "The query time interval cannot exceed 30 days", |
| | | "çæä¸": "Generating", |
| | | "ä¸åæ ¼åç»è®¡": "Unqualified Products Statistics", |
| | | "å¸ç´¯æå¾": "Pareto Chart", |
| | | "产线段": "Production Line Segment", |
| | | "产ååå·": "Product Model", |
| | | "æ¥è¯¢æ¥æ": "Query Date", |
| | | "宿¶æ¨¡å¼ï¼å®æ¶æ¯åéå·æ°å½æ¥æ°æ®ï¼": "Real-time mode (refresh )", |
| | | "导åºåææ¥å": "Export Report", |
| | | "产åä¸åæ ¼æ°": "Number of Unqualified Products", |
| | | "产åä¸åæ ¼ç": "Unqualified Rate of Products", |
| | | "产å主è¦ä¸åæ ¼åå ": "Main Unqualified Reasons for Products", |
| | | "å·¥åº": "Process", |
| | | "å·¥ä½": "Workstation", |
| | | "çæ¬¡": "Shift", |
| | | "å¾è¡¨": "Chart", |
| | | "æ±å½¢å¾": "Bar Chart", |
| | | "æçº¿å¾": "Line Chart", |
| | | "æ±å½¢æçº¿å¾": "Bar-Line Chart", |
| | | "è¿å": "Back", |
| | | "ä¸åæ ¼åå åå¸": "Distribution of Unqualified Reasons", |
| | | "å
¨é¨": "All" |
| | | }, |
| | | "LabelManagement": { |
| | | "产ååç§°": "Product Name", |
| | | "产åID": "Product ID", |
| | | "产ååå·": "Product Model", |
| | | "å·¥åº": "Process", |
| | | "å·¥ä½": "Workstation", |
| | | "åºå·": "Serial Number", |
| | | "æ ç¾åç§°": "Label Name", |
| | | "éåºäº§ååç§°": "Product Name", |
| | | "æä½ç¨æ·": "Operating user", |
| | | "夿³¨": "Remark", |
| | | "æ·»å ": "Add", |
| | | "ç¼è¾": "Edit", |
| | | "åå»ºå¯æ¬": "Create a copy", |
| | | "å é¤": "Delete", |
| | | "请è¾å
¥å
³é®å": "Please Enter Keywords", |
| | | "使ç¨äº§å": "Use Product", |
| | | "éæ°æå°": "Reload Print", |
| | | "æ¶é´èå´": "Time Range", |
| | | "å¼å§æ¶é´": "Start Time", |
| | | "ç»ææ¶é´": "End Time", |
| | | "æå°æ¶é´": "Print Time", |
| | | "æå°æ¨¡æ¿": "Print Template", |
| | | "æå°ç»æ": "Print Result", |
| | | "æ·»å æ ç¾": "Add Label", |
| | | "æ°æ®æ å°": "Data Mapping", |
| | | "卿忮µ": "Dynamic Field", |
| | | "æ°æ®ç±»å": "Data Type", |
| | | "æ°æ®æº": "Data Source", |
| | | "å·¥ä½åç§°": "Workstation Name", |
| | | "æ ç¾æ¨¡æ¿": "Label Template", |
| | | "æå°æ¬¡æ°": "Print Count", |
| | | "éæ©": "Select", |
| | | "éç¨äº§å": "Product Name", |
| | | "éç¨å·¥ä½": "Work Station", |
| | | "è¯·éæ©": "Please Select", |
| | | "è¯·éæ©éç¨äº§å": "Please Product", |
| | | "请è¾å
¥æ ç¾åç§°": "Please Enter Label Name", |
| | | "å·¥ä½éæ©": "Station Selection", |
| | | "è¯·éæ©æ ç¾æ¨¡æ¿": "Please Select Label Template", |
| | | "åé": "Variable", |
| | | "åæ®µ": "Field", |
| | | "æ¡ç çæè§å": "Barcode generation rules", |
| | | "æµç¨ä¸ä¸æ": "Flow Context", |
| | | "æ è¯": "FLag", |
| | | "çæè§å": "generation rules", |
| | | "ä¸ååé": "Issue Variable", |
| | | "è§åç±»å": "Rule type", |
| | | "æ¡ç æ®µç»æ": "Barcode Segment Composition", |
| | | "æ¡ç 示ä¾": "Barcode example", |
| | | "æ´æ°æ¶é´": "Update Time", |
| | | "éç¨äº§ååç§°": "Product Name", |
| | | "请è¾å
¥å¤æ³¨": "Please enter the remarks", |
| | | "è¯·éæ©æå°æº": "Please Select Print", |
| | | "æå°æ¨¡ç": "Print Template", |
| | | "è¯·éæ©æå°è®°å½": "Please Select Print Record", |
| | | "éç¨å·¥ä½ä¸è½ä¸ºç©º": "The applicable workstation cannot be empty", |
| | | "éç¨å·¥ä½å
许为空": "The applicable workstation cannot be empty", |
| | | "æ°æ®æ å°ä¸è½ä¸ºç©º": "Data mapping cannot be empty", |
| | | "è¯·éæ©éç¨å·¥ä½": "Please select the applicable workstation", |
| | | "å¤å¶": "Copy", |
| | | "å 餿°æ®": "Delete Data", |
| | | "è¯·éæ©æ ç¾": "Please Select Label", |
| | | "ç¼è¾æ ç¾": "Edit Label", |
| | | "éç¨äº§åä¸å
许为空": "The applicable product cannot be empty", |
| | | "æ ç¾åç§°ä¸å
许为空": "The label name cannot be empty", |
| | | "éç¨å·¥ä½ä¸å
许为空": "The applicable workstation cannot be empty", |
| | | "æå°æº": "Printer", |
| | | "åå»ºå¯æ¬æå": "Copy creation successful", |
| | | "确认å é¤é䏿 ç¾ï¼": "Confirm deletion of selected label?", |
| | | "æå°æå": "Print successful", |
| | | "请è¾å
¥æå°æ¬¡æ°": "Please enter the number of prints", |
| | | "ä»
æ¯ææä½åæ¡æ°æ®": "Only single data operations are supported", |
| | | "ä¿åæå": "Save successful", |
| | | "å 餿å": "Delete successful" |
| | | }, |
| | | "WMS-WMSMissionManagement": { |
| | | "ä»»å¡ç®¡ç": "Mission Management", |
| | | "å建æ¶é´": "CreateTime", |
| | | "çé": "Filter", |
| | | "导åº": "Export", |
| | | "请è¾å
¥å
³é®å": "Please Enter Keywords", |
| | | "å
¥åº": "Inbound", |
| | | "åºåº": "Outbound", |
| | | "ç§»ä½": "Transposing", |
| | | "æ®éå
¥åº": "Ordinary storage", |
| | | "æ®éåºåº": "Ordinary outbound", |
| | | "空æå
¥åº": "Empty pallet storage", |
| | | "空æåºåº": "Empty palletized outbound", |
| | | "éåé
": "redistribution", |
| | | "æ®éç§»ä½": "Ordinary shift" |
| | | }, |
| | | "PalletManagement": { |
| | | "导å
¥æå": "Import successful", |
| | | "è§£ç»æå": "Unbinding successful", |
| | | "ç»å®æå": "Binding successful", |
| | | "ä¿åæå": "Save successful", |
| | | "æç": "Pallet", |
| | | "å¯¼åºæç": "Export Pallet", |
| | | "导åº": "Export", |
| | | "导å
¥å¤±è´¥": "Import Fail", |
| | | "导å
¥æä»¶æ ¼å¼ä¸æ£ç¡®ï¼è¯·å¯¼å
¥.xlsx/.xlsä¸.csvæ ¼å¼çæä»¶": "Import file format is incorrect, please import .xlsx/.xls and .csv format files", |
| | | "è¯·éæ©æç": "Please Select Pallet", |
| | | "确认å é¤é䏿çï¼": "Confirm deletion of selected pallet?", |
| | | "å 餿å": "Delete successful", |
| | | "å é¤å¤±è´¥": "Delete failed", |
| | | "å é¤ä¸": "Deleting", |
| | | "å 餿ç": "Delete Pallet", |
| | | "æç管ç": "Pallet Management", |
| | | "æçç¼å·": "Pallet Number", |
| | | "æçç±»å": "Pallet Type", |
| | | "æä½": "Operation", |
| | | "ç¶æ": "Status", |
| | | "å建æ¶é´": "Creation Time", |
| | | "æ´æ°æ¶é´": "Update Time", |
| | | "ä»
æ¯ææä½åæ¡æ°æ®": "Only single data operations are supported", |
| | | "ç¼è¾æç": "Edit Pallet", |
| | | "æç已使ç¨ï¼è¯·éæ°éæ©": "Pallet has been used, please select again", |
| | | "æçç»å®": "Pallet Binding", |
| | | "æçæªä½¿ç¨ï¼è¯·éæ°éæ©": "Pallet has not been used, please select again", |
| | | "æ¯å¦ç¡®è®¤è§£é¤ç»å®ï¼": "Confirm pallet binding?", |
| | | "è§£é¤ç»å®æå": "Pallet binding released successfully", |
| | | "使ç¨ä¸": "In Use", |
| | | "æªä½¿ç¨": "Not Used", |
| | | "æ·»å ": "Add", |
| | | "ç»å®": "Bind", |
| | | "è§£ç»": "Unbind", |
| | | "èªå¨ç»å®": "Auto Bind", |
| | | "èªå¨è§£ç»": "Auto Unbind", |
| | | "æå¨ç»å®": "Manual Bind", |
| | | "æå¨è§£ç»": "Manual Unbind", |
| | | "å é¤": "Delete", |
| | | "æçç»å®è®°å½": "Pallet Binding Record", |
| | | "请è¾å
¥å
³é®å": "Please Enter Keywords", |
| | | "åºå·": "Serial Number", |
| | | "æçç ": "Pallet Code", |
| | | "å½åç»å®äº§åç ": "Current Binding Product Code", |
| | | "夿³¨": "Remark", |
| | | "æ·»å æ¡ä»¶": "Add Condition", |
| | | "æ¶é´èå´": "Time Range", |
| | | "å¼å§æ¶é´": "Start Time", |
| | | "ç»ææ¶é´": "End Time", |
| | | "çé": "Filter", |
| | | "æ¶é´èå´æå¤§è·¨åº¦ä¸º60天": "The maximum time range span is 60 days", |
| | | "æçç»å®è®°å½.xlsx": "Pallet Binding Record.xlsx", |
| | | "产åç ": "Product Code", |
| | | "å¨ä½": "Action", |
| | | "å·¥åº": "Process", |
| | | "æ¶é´": "Time", |
| | | "è¯·éæ©å¨ä½": "Please Select Action", |
| | | "请è¾å
¥å·¥åº": "Please Enter Process", |
| | | "请è¾å
¥": "Please Enter", |
| | | "è¯·éæ©": "Please Select", |
| | | "导å
¥": "Import", |
| | | "ç¼è¾": "Edit", |
| | | "æ·»å æç": "Add Pallet", |
| | | "请è¾å
¥æçç ": "Please Enter Pallet Code", |
| | | "请è¾å
¥å¤æ³¨ä¿¡æ¯": "Please Enter Remark Information", |
| | | "请è¾å
¥äº§åç ": "Please Enter Product Code", |
| | | "产åç ä¸å
许为空": "Product code cannot be empty", |
| | | "æçç ä¸å
许为空": "Tray code cannot be empty", |
| | | "è¯·éæ©ç¶æ": "Please select Status" |
| | | } |
| | | } |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | { |
| | | "MesSuite": { |
| | | "å䏿·»å ä¸è¡": "Add a row above", |
| | | "å䏿·»å ä¸è¡": "Add a row below", |
| | | "å é¤": "Delete", |
| | | "ä¸è½ä¸ºç©º": "Cannot be empty", |
| | | "ææ æ°æ®": "No data", |
| | | "ç¡®å®": "Confirm", |
| | | "æ¥è¯¢": "search", |
| | | "确认": "Confirm", |
| | | "åæ¶": "Cancel", |
| | | "追溯æ¥è¡¨": "Traceability report", |
| | | "æ¥è¡¨é
ç½®": "Report configuration", |
| | | "å
±": "Total", |
| | | "页": "Pages", |
| | | "å½å第": "Current", |
| | | "æ¯é¡µ": "Per Page", |
| | | "æ¡è®°å½": "Records", |
| | | "第": "th", |
| | | "è¯·éæ©": "Please select" |
| | | } |
| | | } |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | { |
| | | "ProcessManagement": { |
| | | "ææ æ°æ®": "No data", |
| | | "è¯·éæ©": "Please select", |
| | | "å·¥åºå表": "WorkSection Report", |
| | | "å·¥ä½å表": "Workstations Report", |
| | | "详æ
": "details", |
| | | "çé": "Filter", |
| | | "æ·»å æ¡ä»¶": "Add Condition", |
| | | "æ·»å å·¥åº": "Add WorkSection", |
| | | "å·¥åºè®¾ç½®": "WorkSection Settings", |
| | | "åç»æ¡ä»¶": "Group Condition", |
| | | "æå±äº§çº¿æ®µ": "Belonging production line segment", |
| | | "è¯·éæ©æå±äº§çº¿æ®µ": "Please select Belonging production line segment", |
| | | "å
³èæµç¨": "Associated Flow", |
| | | "è¯·éæ©å
³èæµç¨": "Please select Associated Flow", |
| | | "åç»": "Group", |
| | | "导å
¥": "Import", |
| | | "导åº": "Export", |
| | | "请è¾å
¥": "Please enter", |
| | | "请è¾å
¥å
³é®å": "Please enter keywords", |
| | | "åºå·": "Number", |
| | | "å·¥åºåç§°": "WorkSection Name", |
| | | "å·¥åºç¼å·": "WorkSection Number", |
| | | "å·¥ä½åç§°": "Workstation Name", |
| | | "æå±å·¥åº": "Belonging WorkSection", |
| | | "è¯·éæ©æå±å·¥åº": "Please select Belonging WorkSection", |
| | | "çæ¿IP": "Dashboard IP", |
| | | "SOPä¿¡å·": "SOP Signal", |
| | | "æ´æ°ç åé": "Update code variable", |
| | | "夿³¨": "Remark", |
| | | "æ¹éé
ç½®": "Batch configuration", |
| | | "åæ°é
ç½®": "Parameter configuration", |
| | | "æ¯æé
ç½®äº§çº¿äº§åæ¡ç ä¸å¯ä¸æçè£
é
ç»å®å
³ç³»": "Support configuration production line product barcode and unique material assembly binding relationship", |
| | | "ç©æäº§åå
³èå·¥åº": "Material product assembly work section", |
| | | "è¿ç«ç»æå¼é
ç½®": "Entry station result value configuration", |
| | | "å·¥åºç»æå¼é
ç½®": "WorkSection result value configuration", |
| | | "è¡¥å
è¯´ææ å°": "Supplementary description mapping relationship", |
| | | "å
³èæ¡ç çæè§å": "Associated barcode generation rule", |
| | | "æ¡ç åç§°": "Barcode name", |
| | | "æµç¨åç§°": "Flow name", |
| | | "éæ©": "Select", |
| | | "å
³èç©æ": "Associated material", |
| | | "å
³é®å": "Keyword", |
| | | "åæ°ä¿¡å·é
ç½®": "Parameter signal configuration", |
| | | "导å
¥æå": "Import success", |
| | | "å¯¼åºæå": "Export success", |
| | | "åè½é
ç½®": "Function configuration", |
| | | "ééåæ°": "Collection parameter", |
| | | "é
æ¹åæ°": "Formula parameter", |
| | | "ä¸è¯åå ": "Defect reason", |
| | | "ç©æåæ°": "Material parameter", |
| | | "å±å¼å·¥åºè¯¦æ
": "Expand work section details", |
| | | "å䏿·»å å·¥åº": "Add work section upwards", |
| | | "å䏿·»å å·¥åº": "Add work section downwards", |
| | | "å建工åºå¯æ¬": "Create work section copy", |
| | | "åå»ºå¯æ¬æå": "Create copy success", |
| | | "å é¤å·¥åº": "Delete work section", |
| | | "æ¯å¦å é¤": "Are you sure to delete", |
| | | "å 餿å": "Delete success", |
| | | "å·¥åº": "WorkSection", |
| | | "导å
¥å¤±è´¥": "Import fail", |
| | | "导å
¥æä»¶æ ¼å¼ä¸æ£ç¡®ï¼è¯·å¯¼å
¥.xlsx/.xlsä¸.csvæ ¼å¼çæä»¶": "Import file format is incorrect, please import .xlsx/.xls and .csv format files", |
| | | "请è¾å
¥å·¥åºåç§°": "Please enter workSection name", |
| | | "è¯·éæ©äº§çº¿æ®µ": "Please select production line segment", |
| | | "ç©æåç§°": "Material name", |
| | | "ç©æç±»å": "Material type", |
| | | "åæ°å": "Parameter name", |
| | | "åæ°æè¿°": "Parameter description", |
| | | "å½åå·¥åºæ°æ®æªä¿åï¼æ¯å¦ç¡®è®¤å
³éï¼": "Current work section data has not been saved, do you want to close?", |
| | | "ä¿åæåï¼æ³¨æé坿µç¨æå¡ï¼": "Save success, please restart the flow service!", |
| | | "产线段": "Production line segment", |
| | | "ç»å®å¯ä¸æ": "Binding unique material", |
| | | "è¿ç«ç»æ": "Entry station result", |
| | | "ä¸åå¼": "Issued value", |
| | | "åå§å¼": "Original value", |
| | | "æ å°å¼": "Mapping value", |
| | | "ä¿åæå": "Save success", |
| | | "å±å¼å·¥ä½è¯¦æ
": "Expand workstation details", |
| | | "å䏿·»å å·¥ä½": "Add workstation upwards", |
| | | "å䏿·»å å·¥ä½": "Add workstation downwards", |
| | | "æ·»å å·¥ä½": "Add Workstation", |
| | | "å建工ä½å¯æ¬": "Create workstation copy", |
| | | "å建工ä½å¯æ¬æå": "Create workstation copy success", |
| | | "å é¤å·¥ä½": "Delete workstation", |
| | | "å·¥ä½": "Workstation", |
| | | "å½å工使°æ®æªä¿åï¼æ¯å¦ç¡®è®¤å
³éï¼": "Current workstation data has not been saved, do you want to close?", |
| | | "请è¾å
¥å·¥ä½åç§°": "Please enter workstation name", |
| | | "请è¾å
¥å·¥åºç¼å·": "Please enter workSection Number", |
| | | "ä¸è½ä¸ºç©ºæç©ºç½å符ï¼": "Cannot be empty or blank characters!", |
| | | "çæ¿IPå°å": "Dashboard IP address", |
| | | "请è¾å
¥çæ¿IPå°å": "Please enter dashboard IP address", |
| | | "è¯·éæ©æ´æ°ç ": "Please select update code", |
| | | "æ´æ°ç ": "Update code", |
| | | "è¯·éæ©SOPä¿¡å·": "Please select SOP signal", |
| | | "ç©ææ£éªä¿¡å·": "Material inspection signal", |
| | | "ç©ææ¡ç åé": "Material barcode variable", |
| | | "ç©ææ ¡éªç»æ": "Material check result", |
| | | "ç»å®ç©æ": "Binding material", |
| | | "ç©ææ¡ç ä¿¡æ¯ç¼ååé": "Material barcode information cache variable", |
| | | "ä¸è¯ååå åç§°": "Defect reason name", |
| | | "夿å¼": "Judgment value", |
| | | "ä¸è¯ååå åé": "Defect reason variable", |
| | | "åè½åç§°": "Function name", |
| | | "æå±æµç¨": "Belonging flow", |
| | | "åè½æè¿°": "Function description", |
| | | "åè½é项": "Function option", |
| | | "ééåé": "Collection variable", |
| | | "ä¸åå
³èåé": "Issued related variable", |
| | | "çå¬å
³èåé": "Listen related variable", |
| | | "åè½å段": "Function field", |
| | | "æè¿°": "Description", |
| | | "åéè§å": "Variable rule", |
| | | "ç©æç¼å·": "Material number", |
| | | "å
³èå·¥åº": "Related workSection", |
| | | "åä½": "Unit", |
| | | "è§åç±»å": "Rule type", |
| | | "æ¡ç æ®µç»æ": "Barcode segment composition", |
| | | "æ¡ç 示ä¾": "Barcode example", |
| | | "æ´æ°æ¶é´": "Update time", |
| | | "æ ¡éªç±»å": "Check type", |
| | | "æ ¡éªæ¡ç ": "Check barcode", |
| | | "交äºç±»å": "Interaction type", |
| | | "åè½é¡¹": "Function item", |
| | | "å·¥åºå表-å表": "WorkSection Report-List", |
| | | "å·¥ä½-å表": "Workstations Report-List", |
| | | "å·¥åºå表-æ·»å ": "WorkSection Report-Add", |
| | | "å·¥åºå表-设置": "WorkSection Report-Settings", |
| | | "å·¥åºå表-è¿æ»¤": "WorkSection Report-Filter", |
| | | "å·¥åºå表-åç»": "WorkSection Report-Group", |
| | | "å·¥åºå表-导å
¥": "WorkSection Report-Import", |
| | | "å·¥åºå表-è¾åº": "WorkSection Report-Export", |
| | | "å·¥ä½å表-æ·»å ": "Workstations Report-Add", |
| | | "å·¥ä½å表-æ¹éé
ç½®": "Workstations Report-Batch Settings", |
| | | "å·¥ä½å表-è¿æ»¤": "Workstations Report-Filter", |
| | | "å·¥ä½å表-åç»": "Workstations Report-Group", |
| | | "å·¥ä½å表-导å
¥": "Workstations Report-Import", |
| | | "å·¥ä½å表-è¾åº": "Workstations Report-Export", |
| | | "ç¡®å®": "Confirm", |
| | | "æ¥è¯¢": "search", |
| | | "确认": "Confirm", |
| | | "åæ¶": "Cancel", |
| | | "追溯æ¥è¡¨": "Traceability report", |
| | | "æ¥è¡¨é
ç½®": "Report configuration", |
| | | "å
±": "Total", |
| | | "页": "Pages", |
| | | "å½å第": "Current", |
| | | "æ¯é¡µ": "Per Page", |
| | | "æ¡è®°å½": "Records", |
| | | "第": "th", |
| | | "æä½": "Operation", |
| | | "å¼å¸¸åå ": "Abnormal reason" |
| | | } |
| | | } |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | { |
| | | "ProductManagement": { |
| | | "ææ æ°æ®": "No data", |
| | | "产å管ç": "Product management", |
| | | "æ·»å ": "Add", |
| | | "ç¼è¾": "Edit", |
| | | "导å
¥": "Import", |
| | | "导åº": "Export", |
| | | "SOP管ç": "SOP management", |
| | | "SOPé
ç½®": "SOP configuration", |
| | | "å é¤": "Delete", |
| | | "请è¾å
¥äº§ååç§°ã产ååå·ãå产åç®ç ": "Enter product name,model,code", |
| | | "åºå·": "Serial number", |
| | | "产ååç§°": "Product name", |
| | | "产ååå·": "Product model", |
| | | "产åç®å·": "Product code", |
| | | "é
æ¹åç§°": "Recipe name", |
| | | "å·¥èºè·¯çº¿": "Process route", |
| | | "夿³¨": "Remark", |
| | | "é¢è§": "Preview", |
| | | "æ·»å æ¬å°æä»¶": "Add local file", |
| | | "ææ½è³è¿éä¸ä¼ ": "Drag and drop here to upload", |
| | | "å·¥åºæ®µ": "Process segment", |
| | | "è¯·éæ©å·¥åºæ®µ": "Please select a process segment", |
| | | "å
¨é¨": "All", |
| | | "å·¥åº": "Process", |
| | | "请è¾å
¥å·¥åºåç§°": "Enter process name", |
| | | "å·¥æ¥ç®¡ç": "Workstep management", |
| | | "æ°å¢": "Add", |
| | | "éä»¶": "Attachment", |
| | | "å·¥æ¥åå·¥æ¥æè¿°ä¸ºå¿
å¡«": "Workstep and description are required", |
| | | "å·¥æ¥åç§°ä¸å¯ä»¥éå¤": "Workstep name cannot be repeated", |
| | | "å·¥æ¥": "Workstep", |
| | | "æä½æè¿°": "Operation description", |
| | | "è¯·éæ©å·¥åº": "Please select a process", |
| | | "è¯·éæ©éè¦å é¤çå·¥æ¥": "Please select the workstep to be deleted", |
| | | "å·¥åºç¼å·": "Process number", |
| | | "å·¥åºåç§°": "Process name", |
| | | "å·¥åºæ®µåç§°": "Process segment name", |
| | | "æä½æå": "Operation successful", |
| | | "产ååç§°ä¸å
许为空ï¼": "Product name cannot be empty!", |
| | | "请è¾å
¥äº§ååç§°": "Please enter product name", |
| | | "产ååå·ä¸å
许为空ï¼": "Product model cannot be empty!", |
| | | "请è¾å
¥äº§ååå·": "Please enter product model", |
| | | "请è¾å
¥äº§åç®å·": "Please enter product code", |
| | | "å建æå": "Creation successful", |
| | | "ä¿®æ¹æå": "Modification successful", |
| | | "å 餿å": "Deletion successful", |
| | | "è¯·éæ©äº§åè¿è¡å é¤!": "Please select a product to delete!", |
| | | "产åå é¤åï¼ç¸å
³çäº§æ°æ®æ æ³æ¢å¤ï¼æ¯å¦ç¡®è®¤å é¤ï¼": "Product deletion cannot be recovered, are you sure to delete?", |
| | | "æ°å»ºäº§å": "New product", |
| | | "è¯·éæ©ä¸ä¸ªäº§åè¿è¡ç¼è¾": "Please select a product to edit", |
| | | "è¯·éæ©ä¸ä¸ªäº§åè¿è¡æä½!": "Please select a product to operate!", |
| | | "ä»
æ¯æç¼è¾å个产å": "Only support editing a single product", |
| | | "该产ååå·æ£å¨ç产ä¸ï¼ä¸å¯æä½ï¼": "The product model is in production, cannot be operated!", |
| | | "ä»
æ¯æå¯¹ä¸ä¸ªäº§ååå·è¿è¡æä½!": "Only support operating on a single product model!", |
| | | "äº§åæ£å¨ç产ä¸ï¼ä¸å
许ç¼è¾!": "Product is in production, cannot be edited!", |
| | | "ç¼è¾äº§å": "Edit product", |
| | | "ç¡®å®": "Confirm", |
| | | "æ¥è¯¢": "search", |
| | | "确认": "Confirm", |
| | | "åæ¶": "Cancel", |
| | | "追溯æ¥è¡¨": "Traceability report", |
| | | "æ¥è¡¨é
ç½®": "Report configuration", |
| | | "å
±": "Total", |
| | | "页": "Pages", |
| | | "å½å第": "Current", |
| | | "æ¯é¡µ": "Per Page", |
| | | "æ¡è®°å½": "Records", |
| | | "第": "th" |
| | | } |
| | | } |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | { |
| | | "trace": { |
| | | "追溯æ¥è¡¨": "Traceability Report", |
| | | "æ¥è¡¨é
ç½®": "Report Configuration", |
| | | "请è¾å
¥èªç¶æ°ï¼": "Please enter a natural number!", |
| | | "è¾å
¥æ°é大äºåæ°æ°éï¼è¯·éæ°è¾å
¥": "The input quantity is greater than the parameter quantity. Please enter again.", |
| | | "å»ç»åæ°ä¸è½å
å«å¤çº§è¡¨å¤´ï¼è¯·éæ°è¾å
¥": "The frozen column count cannot include multi-level headers. Please enter again.", |
| | | "ä¸å¡å段é
ç½®": "Business Field Configuration", |
| | | "å±ç¤ºé
ç½®": "Display Configuration", |
| | | "æ»è¡¨é
ç½®": "Overall Table Configuration", |
| | | "ä¿åæåï¼": "Saved successfully!", |
| | | "ä¿å失败ï¼": "Failed to save!", |
| | | "æç¤º": "Tip", |
| | | "æ¯å¦å é¤": "Do you want to delete?", |
| | | "æ¯": "Yes", |
| | | "å¦": "No", |
| | | "åºå·": "Serial Number", |
| | | "产ååç§°": "Product Name", |
| | | "产ååå·": "Product Model", |
| | | "夿³¨": "Remarks", |
| | | "ææ æ°æ®": "No data available", |
| | | "请å¾éå¤éæ¡ï¼": "Please check the checkbox!", |
| | | "è¯·éæ©å·¥åºï¼": "Please select a process!", |
| | | "è¯·éæ©åæ°ï¼": "Please select parameters!", |
| | | "ä¸é": "Upper Limit", |
| | | "æä½": "Operation", |
| | | "ä¿®æ¹": "Modify", |
| | | "æ»è¡¨åç§°": "Overall Table Name", |
| | | "ç»åå·¥åº": "Combined Process", |
| | | "æä½æ¶é´": "Operation Time", |
| | | "æä½äºº": "Operator", |
| | | "æ¥ç": "View", |
| | | "æ°å»º": "New", |
| | | "å·¥åºæ®µ": "Process Segment", |
| | | "å·¥åºåç§°": "Process Name", |
| | | "éæ©": "Select", |
| | | "å é¤": "Delete", |
| | | "æ°å»ºæ»è¡¨": "New Overall Table", |
| | | "ä¿®æ¹æ»è¡¨": "Modify Overall Table", |
| | | "å
±": "Total", |
| | | "页": "Pages", |
| | | "å½å第": "Current", |
| | | "æ¯é¡µ": "Per Page", |
| | | "æ¡è®°å½": "Records", |
| | | "å¯¼åºæ¶é´èå´": "Export Time Range", |
| | | "å·¥åº": "Process", |
| | | "åæ°": "Parameter", |
| | | "ä¸éå¼": "Upper Limit Value", |
| | | "ä¸éå¼": "Lower Limit Value", |
| | | "è¿å": "Restore", |
| | | "å·¥åºåæ°ç±»å": "Process Parameter Type", |
| | | "å·¥åºåæ°": "Process Parameter", |
| | | "产线段åç§°": "Production Line Segment Name", |
| | | "å·¥åºç¼å·": "Process Number", |
| | | "åæ°ç±»å": "Parameter Type", |
| | | "åæ°åç§°": "Parameter Name", |
| | | "ééåæ°": "Collected Parameters", |
| | | "ä¸ååæ°": "Issued Parameters" |
| | | }, |
| | | "lmes": { |
| | | "ç¡®å®": "Confirm", |
| | | "确认": "Confirm", |
| | | "åæ¶": "Cancel" |
| | | } |
| | | } |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | <!-- |
| | | mitm.html is the lite "man in the middle" |
| | | |
| | | This is only meant to signal the opener's messageChannel to |
| | | the service worker - when that is done this mitm can be closed |
| | | but it's better to keep it alive since this also stops the sw |
| | | from restarting |
| | | |
| | | The service worker is capable of intercepting all request and fork their |
| | | own "fake" response - wish we are going to craft |
| | | when the worker then receives a stream then the worker will tell the opener |
| | | to open up a link that will start the download |
| | | --> |
| | | <script> |
| | | // This will prevent the sw from restarting |
| | | let keepAlive = () => { |
| | | keepAlive = () => {} |
| | | var ping = location.href.substr(0, location.href.lastIndexOf('/')) + '/ping' |
| | | var interval = setInterval(() => { |
| | | if (sw) { |
| | | sw.postMessage('ping') |
| | | } else { |
| | | fetch(ping).then(res => res.text(!res.ok && clearInterval(interval))) |
| | | } |
| | | }, 10000) |
| | | } |
| | | |
| | | // message event is the first thing we need to setup a listner for |
| | | // don't want the opener to do a random timeout - instead they can listen for |
| | | // the ready event |
| | | // but since we need to wait for the Service Worker registration, we store the |
| | | // message for later |
| | | let messages = [] |
| | | window.onmessage = evt => messages.push(evt) |
| | | |
| | | let sw = null |
| | | let scope = '' |
| | | |
| | | function registerWorker() { |
| | | return navigator.serviceWorker.getRegistration('./').then(swReg => { |
| | | return swReg || navigator.serviceWorker.register('sw.js', { scope: './' }) |
| | | }).then(swReg => { |
| | | const swRegTmp = swReg.installing || swReg.waiting |
| | | |
| | | scope = swReg.scope |
| | | |
| | | return (sw = swReg.active) || new Promise(resolve => { |
| | | swRegTmp.addEventListener('statechange', fn = () => { |
| | | if (swRegTmp.state === 'activated') { |
| | | swRegTmp.removeEventListener('statechange', fn) |
| | | sw = swReg.active |
| | | resolve() |
| | | } |
| | | }) |
| | | }) |
| | | }) |
| | | } |
| | | |
| | | // Now that we have the Service Worker registered we can process messages |
| | | function onMessage (event) { |
| | | let { data, ports, origin } = event |
| | | |
| | | // It's important to have a messageChannel, don't want to interfere |
| | | // with other simultaneous downloads |
| | | if (!ports || !ports.length) { |
| | | throw new TypeError("[StreamSaver] You didn't send a messageChannel") |
| | | } |
| | | |
| | | if (typeof data !== 'object') { |
| | | throw new TypeError("[StreamSaver] You didn't send a object") |
| | | } |
| | | |
| | | // the default public service worker for StreamSaver is shared among others. |
| | | // so all download links needs to be prefixed to avoid any other conflict |
| | | data.origin = origin |
| | | |
| | | // if we ever (in some feature versoin of streamsaver) would like to |
| | | // redirect back to the page of who initiated a http request |
| | | data.referrer = data.referrer || document.referrer || origin |
| | | |
| | | // pass along version for possible backwards compatibility in sw.js |
| | | data.streamSaverVersion = new URLSearchParams(location.search).get('version') |
| | | |
| | | if (data.streamSaverVersion === '1.2.0') { |
| | | console.warn('[StreamSaver] please update streamsaver') |
| | | } |
| | | |
| | | /** @since v2.0.0 */ |
| | | if (!data.headers) { |
| | | console.warn("[StreamSaver] pass `data.headers` that you would like to pass along to the service worker\nit should be a 2D array or a key/val object that fetch's Headers api accepts") |
| | | } else { |
| | | // test if it's correct |
| | | // should thorw a typeError if not |
| | | new Headers(data.headers) |
| | | } |
| | | |
| | | /** @since v2.0.0 */ |
| | | if (typeof data.filename === 'string') { |
| | | console.warn("[StreamSaver] You shouldn't send `data.filename` anymore. It should be included in the Content-Disposition header option") |
| | | // Do what File constructor do with fileNames |
| | | data.filename = data.filename.replace(/\//g, ':') |
| | | } |
| | | |
| | | /** @since v2.0.0 */ |
| | | if (data.size) { |
| | | console.warn("[StreamSaver] You shouldn't send `data.size` anymore. It should be included in the content-length header option") |
| | | } |
| | | |
| | | /** @since v2.0.0 */ |
| | | if (data.readableStream) { |
| | | console.warn("[StreamSaver] You should send the readableStream in the messageChannel, not throught mitm") |
| | | } |
| | | |
| | | /** @since v2.0.0 */ |
| | | if (!data.pathname) { |
| | | console.warn("[StreamSaver] Please send `data.pathname` (eg: /pictures/summer.jpg)") |
| | | data.pathname = Math.random().toString().slice(-6) + '/' + data.filename |
| | | } |
| | | |
| | | // remove all leading slashes |
| | | data.pathname = data.pathname.replace(/^\/+/g, '') |
| | | |
| | | // remove protocol |
| | | let org = origin.replace(/(^\w+:|^)\/\//, '') |
| | | |
| | | // set the absolute pathname to the download url. |
| | | data.url = new URL(`${scope + org}/${data.pathname}`).toString() |
| | | |
| | | if (!data.url.startsWith(`${scope + org}/`)) { |
| | | throw new TypeError('[StreamSaver] bad `data.pathname`') |
| | | } |
| | | |
| | | // This sends the message data as well as transferring |
| | | // messageChannel.port2 to the service worker. The service worker can |
| | | // then use the transferred port to reply via postMessage(), which |
| | | // will in turn trigger the onmessage handler on messageChannel.port1. |
| | | |
| | | const transferable = data.readableStream |
| | | ? [ ports[0], data.readableStream ] |
| | | : [ ports[0] ] |
| | | |
| | | if (!(data.readableStream || data.transferringReadable)) { |
| | | keepAlive() |
| | | } |
| | | |
| | | return sw.postMessage(data, transferable) |
| | | } |
| | | |
| | | if (window.opener) { |
| | | // The opener can't listen to onload event, so we need to help em out! |
| | | // (telling them that we are ready to accept postMessage's) |
| | | window.opener.postMessage('StreamSaver::loadedPopup', '*') |
| | | } |
| | | |
| | | if (navigator.serviceWorker) { |
| | | registerWorker().then(() => { |
| | | window.onmessage = onMessage |
| | | messages.forEach(window.onmessage) |
| | | }) |
| | | } |
| | | |
| | | // FF v102 just started to supports transferable streams, but still needs to ping sw.js |
| | | // even tough the service worker dose not have to do any kind of work and listen to any |
| | | // messages... #305 |
| | | keepAlive() |
| | | |
| | | </script> |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | /* global self ReadableStream Response */ |
| | | |
| | | self.addEventListener('install', () => { |
| | | self.skipWaiting() |
| | | }) |
| | | |
| | | self.addEventListener('activate', event => { |
| | | event.waitUntil(self.clients.claim()) |
| | | }) |
| | | |
| | | const map = new Map() |
| | | |
| | | // This should be called once per download |
| | | // Each event has a dataChannel that the data will be piped through |
| | | self.onmessage = event => { |
| | | // We send a heartbeat every x second to keep the |
| | | // service worker alive if a transferable stream is not sent |
| | | if (event.data === 'ping') { |
| | | return |
| | | } |
| | | |
| | | const data = event.data |
| | | const downloadUrl = data.url || self.registration.scope + Math.random() + '/' + (typeof data === 'string' ? data : data.filename) |
| | | const port = event.ports[0] |
| | | const metadata = new Array(3) // [stream, data, port] |
| | | |
| | | metadata[1] = data |
| | | metadata[2] = port |
| | | |
| | | // Note to self: |
| | | // old streamsaver v1.2.0 might still use `readableStream`... |
| | | // but v2.0.0 will always transfer the stream through MessageChannel #94 |
| | | if (event.data.readableStream) { |
| | | metadata[0] = event.data.readableStream |
| | | } else if (event.data.transferringReadable) { |
| | | port.onmessage = evt => { |
| | | port.onmessage = null |
| | | metadata[0] = evt.data.readableStream |
| | | } |
| | | } else { |
| | | metadata[0] = createStream(port) |
| | | } |
| | | |
| | | map.set(downloadUrl, metadata) |
| | | port.postMessage({ download: downloadUrl }) |
| | | } |
| | | |
| | | function createStream (port) { |
| | | // ReadableStream is only supported by chrome 52 |
| | | return new ReadableStream({ |
| | | start (controller) { |
| | | // When we receive data on the messageChannel, we write |
| | | port.onmessage = ({ data }) => { |
| | | if (data === 'end') { |
| | | return controller.close() |
| | | } |
| | | |
| | | if (data === 'abort') { |
| | | controller.error('Aborted the download') |
| | | return |
| | | } |
| | | |
| | | controller.enqueue(data) |
| | | } |
| | | }, |
| | | cancel (reason) { |
| | | console.log('user aborted', reason) |
| | | port.postMessage({ abort: true }) |
| | | } |
| | | }) |
| | | } |
| | | |
| | | self.onfetch = event => { |
| | | const url = event.request.url |
| | | |
| | | // this only works for Firefox |
| | | if (url.endsWith('/ping')) { |
| | | return event.respondWith(new Response('pong')) |
| | | } |
| | | |
| | | const hijacke = map.get(url) |
| | | |
| | | if (!hijacke) return null |
| | | |
| | | const [ stream, data, port ] = hijacke |
| | | |
| | | map.delete(url) |
| | | |
| | | // Not comfortable letting any user control all headers |
| | | // so we only copy over the length & disposition |
| | | const responseHeaders = new Headers({ |
| | | 'Content-Type': 'application/octet-stream; charset=utf-8', |
| | | |
| | | // To be on the safe side, The link can be opened in a iframe. |
| | | // but octet-stream should stop it. |
| | | 'Content-Security-Policy': "default-src 'none'", |
| | | 'X-Content-Security-Policy': "default-src 'none'", |
| | | 'X-WebKit-CSP': "default-src 'none'", |
| | | 'X-XSS-Protection': '1; mode=block', |
| | | 'Cross-Origin-Embedder-Policy': 'require-corp' |
| | | }) |
| | | |
| | | let headers = new Headers(data.headers || {}) |
| | | |
| | | if (headers.has('Content-Length')) { |
| | | responseHeaders.set('Content-Length', headers.get('Content-Length')) |
| | | } |
| | | |
| | | if (headers.has('Content-Disposition')) { |
| | | responseHeaders.set('Content-Disposition', headers.get('Content-Disposition')) |
| | | } |
| | | |
| | | // data, data.filename and size should not be used anymore |
| | | if (data.size) { |
| | | console.warn('Depricated') |
| | | responseHeaders.set('Content-Length', data.size) |
| | | } |
| | | |
| | | let fileName = typeof data === 'string' ? data : data.filename |
| | | if (fileName) { |
| | | console.warn('Depricated') |
| | | // Make filename RFC5987 compatible |
| | | fileName = encodeURIComponent(fileName).replace(/['()]/g, escape).replace(/\*/g, '%2A') |
| | | responseHeaders.set('Content-Disposition', "attachment; filename*=UTF-8''" + fileName) |
| | | } |
| | | |
| | | event.respondWith(new Response(stream, { headers: responseHeaders })) |
| | | |
| | | port.postMessage({ debug: 'Download started' }) |
| | | } |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | #!/bin/bash |
| | | |
| | | # å®ä¹é»è®¤ç»ä»¶æ°ç» |
| | | default_widget_Array=() |
| | | |
| | | # 读å .build.prod æä»¶å
容 |
| | | if [[ -f ./.build.prod ]]; then |
| | | while IFS= read -r line || [ -n "$line" ]; do |
| | | default_widget_Array+=("$line") |
| | | done < ./.build.prod |
| | | fi |
| | | # ä» .build æä»¶è¯»åå
容 |
| | | buildFile="./.build" |
| | | |
| | | build_widget_Array=() |
| | | if [ -f "$buildFile" ]; then |
| | | while IFS= read -r line || [ -n "$line" ]; do |
| | | build_widget_Array+=("$line") |
| | | done < "$buildFile" |
| | | fi |
| | | if [ -f "$buildFile.local" ]; then |
| | | while IFS= read -r line || [ -n "$line" ]; do |
| | | build_widget_Array+=("$line") |
| | | done < "$buildFile.local" |
| | | fi |
| | | |
| | | # æ£æ¥å¹¶å建 src/widgets ç®å½ |
| | | basePath="src/widgets" |
| | | if [ ! -d "$basePath" ]; then |
| | | echo "ç®å½ $basePath ä¸åå¨ãæ£å¨å建..." |
| | | mkdir -p "$basePath" |
| | | fi |
| | | |
| | | # å®ä¹ä¸ä¸ªå½æ°æ¥å¤çç»ä»¶ |
| | | process_widget() { |
| | | local widgetName=$1 |
| | | local gitUrl=$2 |
| | | local widgetPath="$basePath/$widgetName" |
| | | |
| | | if [ -d "$widgetPath" ]; then |
| | | # 妿æä»¶å¤¹åå¨ï¼è¿å
¥è¯¥æä»¶å¤¹å¹¶æ§è¡ git pull |
| | | echo "ç®å½ $widgetPath å·²åå¨ãæ£å¨æåææ°æ´æ¹..." |
| | | cd "$widgetPath" || exit |
| | | |
| | | # æ£æ¥æ¯å¦è®¾ç½®äºè·è¸ªåæ¯ |
| | | branch_name=$(git rev-parse --abbrev-ref HEAD) |
| | | upstream_branch=$(git rev-parse --abbrev-ref --symbolic-full-name @{u} 2>/dev/null) |
| | | |
| | | if [ -z "$upstream_branch" ]; then |
| | | echo "å½å忝 $branch_name 没æè®¾ç½®ä¸æ¸¸åæ¯ãæ£å¨è®¾ç½®ä¸æ¸¸åæ¯ä¸º origin/$branch_name..." |
| | | git branch --set-upstream-to=origin/$branch_name |
| | | fi |
| | | |
| | | # æ£æ¥æ¯å¦ææªæäº¤çæ´æ¹ |
| | | stash_result=1 |
| | | if [ -n "$(git status --porcelain)" ]; then |
| | | echo "æ£æµå°æªæäº¤çæ´æ¹ãæ£å¨æåæ´æ¹..." |
| | | git stash push -m "卿å $widgetName æ´æ¹ä¹åèªå¨æå" |
| | | stash_result=$? |
| | | fi |
| | | |
| | | # å°è¯æ§è¡ git pull |
| | | git pull --ff-only |
| | | pull_result=$? |
| | | |
| | | # 妿æ stashï¼åå°è¯æ¢å¤ |
| | | if [ "$stash_result" -eq 0 ]; then |
| | | echo "æ£å¨æ¢å¤æåçæ´æ¹..." |
| | | git stash pop |
| | | fi |
| | | |
| | | cd - || exit |
| | | |
| | | # æ£æ¥ pull çç»æ |
| | | if [ "$pull_result" -ne 0 ]; then |
| | | echo "$widgetName ç git pull 失败ã请æå¨è§£å³å²çªã" |
| | | fi |
| | | else |
| | | # 妿æä»¶å¤¹ä¸åå¨ï¼æ§è¡ git clone |
| | | echo "ç®å½ $widgetPath ä¸åå¨ãæ£å¨å
éä»åº..." |
| | | git clone "$gitUrl" "$widgetPath" |
| | | fi |
| | | } |
| | | |
| | | # å¤çé»è®¤ç»ä»¶æ°ç» |
| | | for widgetName in "${default_widget_Array[@]}"; do |
| | | gitUrl="https://gitlab.syc-cms.com/lmes-plugin/web/$widgetName.git" |
| | | process_widget "$widgetName" "$gitUrl" |
| | | done |
| | | |
| | | # å¤ç .build æä»¶ä¸çç»ä»¶æ°ç» |
| | | for widgetName in "${build_widget_Array[@]}"; do |
| | | gitUrl="https://gitlab.syc-cms.com/lmes-plugin/web/business/$widgetName.git" |
| | | process_widget "$widgetName" "$gitUrl" |
| | | done |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | #!/bin/bash |
| | | |
| | | # é»è®¤ç»ä»¶æ°ç» |
| | | widget_Array=() |
| | | |
| | | # æå®åæ¯åä½ä¸ºåæ°ä¼ å
¥ |
| | | target_branch=$1 |
| | | |
| | | if [[ -z "$target_branch" ]]; then |
| | | echo "请æå®ç®æ 忝ï¼ä¾å¦: bash $0 feature/wg/test" |
| | | exit 1 |
| | | fi |
| | | # 读å .build.prod æä»¶å
容 |
| | | if [[ -f ./.build.prod ]]; then |
| | | while IFS= read -r line || [ -n "$line" ]; do |
| | | widget_Array+=("$line") |
| | | done < ./.build.prod |
| | | fi |
| | | |
| | | # 读å .build æä»¶å
容 |
| | | if [[ -f ./.build ]]; then |
| | | while IFS= read -r line || [ -n "$line" ]; do |
| | | widget_Array+=("$line") |
| | | done < ./.build |
| | | fi |
| | | |
| | | # 读å .build æä»¶å
容 |
| | | if [[ -f ./.build.local ]]; then |
| | | while IFS= read -r line || [ -n "$line" ]; do |
| | | widget_Array+=("$line") |
| | | done < ./.build.local |
| | | fi |
| | | |
| | | # å»é |
| | | widget_Array=($(echo "${widget_Array[@]}" | tr ' ' '\n' | sort -u | tr '\n' ' ')) |
| | | |
| | | # åå¨åæ¢ä¿¡æ¯çæ°ç» |
| | | declare -a switch_info |
| | | |
| | | # 循ç¯éåç»ä»¶æ°ç» |
| | | for widgetName in "${widget_Array[@]}"; do |
| | | # æ£æ¥ç»ä»¶ç®å½æ¯å¦åå¨ |
| | | if [[ -d "src/widgets/$widgetName" ]]; then |
| | | # è¿å
¥ç»ä»¶ç®å½ |
| | | cd "src/widgets/$widgetName" || { echo "æ æ³è¿å
¥ç®å½ src/widgets/$widgetName"; continue; } |
| | | |
| | | # è·åå½å忝å |
| | | current_branch=$(git symbolic-ref --short HEAD) |
| | | |
| | | # 妿å½ååæ¯ä»£ç æåå¨ï¼æäº¤åæ´ |
| | | if [[ -n "$(git status --porcelain)" ]]; then |
| | | git add . |
| | | git commit -m 'merge' |
| | | fi |
| | | |
| | | # å建ä¸ä¸ªtag |
| | | git tag "$target_branch" |
| | | git push origin "$target_branch" |
| | | # è·å忢åç忝å |
| | | new_branch=$(git symbolic-ref --short HEAD) |
| | | |
| | | # æ¨éæå®åæ¯å°è¿ç¨ |
| | | # git push --set-upstream origin "$target_branch" |
| | | |
| | | # æ·»å åæ¢ä¿¡æ¯å°æ°ç» |
| | | switch_info+=("$widgetName: $current_branch -> $new_branch") |
| | | |
| | | # è¿åå°ä¸ä¸çº§ç®å½ |
| | | cd - > /dev/null || exit |
| | | else |
| | | echo "ç®å½ src/widgets/$widgetName ä¸åå¨" |
| | | fi |
| | | done |
| | | |
| | | # ç»ä¸è¾åºåæ¢ä¿¡æ¯ |
| | | echo "åæ¢ä¿¡æ¯ï¼" |
| | | for info in "${switch_info[@]}"; do |
| | | echo "$info" |
| | | done |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | 'use strict' |
| | | Object.defineProperty(exports, '__esModule', { value: true }) |
| | | exports.tar = |
| | | exports.zip = |
| | | exports.ZipAFolder = |
| | | exports.COMPRESSION_LEVEL = |
| | | void 0 |
| | | const tslib_1 = require('tslib') |
| | | const fs_1 = require('fs') |
| | | const path_1 = tslib_1.__importDefault(require('path')) |
| | | const archiver_1 = tslib_1.__importDefault(require('archiver')) |
| | | const promises_1 = tslib_1.__importDefault(require('fs/promises')) |
| | | const is_glob_1 = tslib_1.__importDefault(require('is-glob')) |
| | | const glob_1 = require('glob') |
| | | var COMPRESSION_LEVEL |
| | | ;(function (COMPRESSION_LEVEL) { |
| | | COMPRESSION_LEVEL[(COMPRESSION_LEVEL['uncompressed'] = 0)] = 'uncompressed' |
| | | COMPRESSION_LEVEL[(COMPRESSION_LEVEL['medium'] = 5)] = 'medium' |
| | | COMPRESSION_LEVEL[(COMPRESSION_LEVEL['high'] = 9)] = 'high' |
| | | })(COMPRESSION_LEVEL || (exports.COMPRESSION_LEVEL = COMPRESSION_LEVEL = {})) |
| | | class ZipAFolder { |
| | | static tar(src, tarFilePath, zipAFolderOptions) { |
| | | return tslib_1.__awaiter(this, void 0, void 0, function* () { |
| | | const o = zipAFolderOptions || { |
| | | compression: COMPRESSION_LEVEL.high, |
| | | } |
| | | if (o.compression === COMPRESSION_LEVEL.uncompressed) { |
| | | yield ZipAFolder.compress({ |
| | | src, |
| | | targetFilePath: tarFilePath, |
| | | format: 'tar', |
| | | zipAFolderOptions, |
| | | }) |
| | | } else { |
| | | yield ZipAFolder.compress({ |
| | | src, |
| | | targetFilePath: tarFilePath, |
| | | format: 'tar', |
| | | zipAFolderOptions, |
| | | archiverOptions: { |
| | | gzip: true, |
| | | gzipOptions: { |
| | | level: o.compression, |
| | | }, |
| | | }, |
| | | }) |
| | | } |
| | | }) |
| | | } |
| | | static zip(src, zipFilePath, zipAFolderOptions) { |
| | | return tslib_1.__awaiter(this, void 0, void 0, function* () { |
| | | const o = zipAFolderOptions || { |
| | | compression: COMPRESSION_LEVEL.high, |
| | | } |
| | | if (o.compression === COMPRESSION_LEVEL.uncompressed) { |
| | | yield ZipAFolder.compress({ |
| | | src, |
| | | targetFilePath: zipFilePath, |
| | | format: 'zip', |
| | | zipAFolderOptions, |
| | | archiverOptions: { |
| | | store: true, |
| | | }, |
| | | }) |
| | | } else { |
| | | yield ZipAFolder.compress({ |
| | | src, |
| | | targetFilePath: zipFilePath, |
| | | format: 'zip', |
| | | zipAFolderOptions, |
| | | archiverOptions: { |
| | | zlib: { |
| | | level: o.compression, |
| | | }, |
| | | }, |
| | | }) |
| | | } |
| | | }) |
| | | } |
| | | static compress(_a) { |
| | | return tslib_1.__awaiter( |
| | | this, |
| | | arguments, |
| | | void 0, |
| | | function* ({ |
| | | src, |
| | | targetFilePath, |
| | | format, |
| | | zipAFolderOptions, |
| | | archiverOptions, |
| | | }) { |
| | | let output |
| | | const globList = [] |
| | | if ( |
| | | !(zipAFolderOptions === null || zipAFolderOptions === void 0 |
| | | ? void 0 |
| | | : zipAFolderOptions.customWriteStream) && |
| | | targetFilePath |
| | | ) { |
| | | const targetBasePath = path_1.default.dirname(targetFilePath) |
| | | if (targetBasePath === src) { |
| | | throw new Error('Source and target folder must be different.') |
| | | } |
| | | try { |
| | | if (!(0, is_glob_1.default)(src)) { |
| | | yield promises_1.default.access( |
| | | src, |
| | | promises_1.default.constants.R_OK |
| | | ) |
| | | } |
| | | yield promises_1.default.access( |
| | | targetBasePath, |
| | | promises_1.default.constants.R_OK | |
| | | promises_1.default.constants.W_OK |
| | | ) |
| | | } catch (e) { |
| | | throw new Error(`Permission error: ${e.message}`) |
| | | } |
| | | if ((0, is_glob_1.default)(src)) { |
| | | for (const globPart of src.split(',')) { |
| | | globList.push(...(yield (0, glob_1.glob)(globPart.trim()))) |
| | | } |
| | | if (globList.length === 0) { |
| | | throw new Error(`No glob match found for "${src}".`) |
| | | } |
| | | } |
| | | output = (0, fs_1.createWriteStream)(targetFilePath) |
| | | } else if (zipAFolderOptions && zipAFolderOptions.customWriteStream) { |
| | | output = zipAFolderOptions.customWriteStream |
| | | } else { |
| | | throw new Error( |
| | | 'You must either provide a target file path or a custom write stream to write to.' |
| | | ) |
| | | } |
| | | const zipArchive = (0, archiver_1.default)( |
| | | format, |
| | | archiverOptions || {} |
| | | ) |
| | | return new Promise((resolve, reject) => |
| | | tslib_1.__awaiter(this, void 0, void 0, function* () { |
| | | output.on('close', resolve) |
| | | output.on('error', reject) |
| | | zipArchive.pipe(output) |
| | | if ((0, is_glob_1.default)(src)) { |
| | | for (const file of globList) { |
| | | if ((yield promises_1.default.lstat(file)).isFile()) { |
| | | const content = yield promises_1.default.readFile(file) |
| | | zipArchive.append(content, { |
| | | name: file, |
| | | }) |
| | | } |
| | | } |
| | | } else { |
| | | zipArchive.directory( |
| | | src, |
| | | (zipAFolderOptions === null || zipAFolderOptions === void 0 |
| | | ? void 0 |
| | | : zipAFolderOptions.destPath) || false, |
| | | { |
| | | date: new Date(Date.now() + 8 * 60 * 60 * 1000), |
| | | } |
| | | ) |
| | | } |
| | | yield zipArchive.finalize() |
| | | }) |
| | | ) |
| | | } |
| | | ) |
| | | } |
| | | } |
| | | exports.ZipAFolder = ZipAFolder |
| | | exports.zip = ZipAFolder.zip |
| | | exports.tar = ZipAFolder.tar |
| | | //# sourceMappingURL=ZipAFolder.js.map |
| | |
| | | const crossSpawn = require('cross-spawn') |
| | | const slash = require('slash') |
| | | const tag = require('./tag.js') |
| | | const { writeFileSync, rmSync, ensureFileSync } = require('fs-extra') |
| | | const { spawn } = require('node:child_process') |
| | | const { globSync } = require('glob') |
| | | const path = require('path') |
| | | const fs = require('fs-extra') |
| | | const slash = require('slash') |
| | | const crossSpawn = require('cross-spawn') |
| | | const { zip } = require('./ZipAFolder.js') |
| | | const os = require('os') |
| | | const chalk = require('chalk') |
| | | |
| | | const assetsUrl = |
| | | 'https://lmes:gldt-ocw4NMSiDHD461ZoDvyK@gitlab.syc-cms.com:8443/lmes-plugin/web/assets.git' |
| | | const baseDir = './node_modules/.cache/wwwroot' |
| | | const baseBuildFile = './node_modules/.cache/widgets.json' |
| | | let isSingleBuild = false |
| | | const isWin = process.platform === 'win32' |
| | | const argvPath = './script/.argv' |
| | | const widgetName = process.argv[process.argv.length - 1] |
| | | const widgetsPath = globSync(`./src/widgets/*/index.ts`) |
| | | const getWidgetNames = widgetsPath.map((file) => { |
| | | const parts = isWin |
| | | ? path.resolve(file).split('\\') |
| | | : path.resolve(file).split('/') |
| | | return parts[parts.length - 2] |
| | | }) |
| | | |
| | | if (getWidgetNames.includes(widgetName)) { |
| | | isSingleBuild = true |
| | | writeFileSync(argvPath, widgetName) |
| | | } |
| | | |
| | | const hostPath = slash(path.resolve(process.cwd(), baseDir)) |
| | | const hostZipPath = slash(path.resolve(process.cwd(), './wwwroot.zip')) |
| | | let isSingleBuild = false |
| | | let isDebugMode = false |
| | | // ç¼è¯ç»ææ°é |
| | | let buildCount = 0 |
| | | // ç¼è¯è¿ç¨æ»æ°é |
| | | let buildSumCount = 0 |
| | | let startTime = Date.now() |
| | | removeHostPackage() |
| | | buildWidgets() |
| | | |
| | | /** |
| | | * ç¼è¯ç»ä»¶ |
| | | */ |
| | | function buildWidgets() { |
| | | const isWin = process.platform === 'win32' |
| | | const argv = process.argv || [] |
| | | |
| | | // å½debug模å¼ä¸ï¼å°æ¬å°205ç¯å¢ä¸çå¾çå°åæ å°å°ä»£ç ä¸ï¼å¯ä»¥å°.envç¯å¢è¿è¡è®¾ç½®VITE_STATIC_URL |
| | | if (argv.includes('debug')) { |
| | | isDebugMode = true |
| | | argv.splice(argv.indexOf('debug'), 1) |
| | | } |
| | | const widgetName = argv[argv.length - 1] |
| | | |
| | | const widgetsPath = globSync(`./src/widgets/*/index.ts`) |
| | |
| | | ? path.resolve(file).split('\\') |
| | | : path.resolve(file).split('/') |
| | | return parts[parts.length - 2] |
| | | }) // æå
ä¸ä¸ªç»ä»¶ |
| | | }) |
| | | |
| | | try { |
| | | fs.removeSync('./dist') |
| | | } catch (error) { |
| | | console.error('distä¸åå¨ï¼ç»§ç»æ§è¡æå
ä»»å¡') |
| | | } |
| | | |
| | | // æå
ä¸ä¸ªç»ä»¶ |
| | | if (widgetName && widgetNames.includes(widgetName)) { |
| | | isSingleBuild = true |
| | | writeFileSync(argvPath, widgetName) |
| | |
| | | */ |
| | | function divideArray(widgets) { |
| | | // 彿å
æ¶ï¼æä½çµèå¯è½ä¼å¡ |
| | | const cpus = os.availableParallelism() > 1 ? os.availableParallelism() - 1 : 1 |
| | | const cpus = os.availableParallelism() |
| | | let result = {} |
| | | let dataPerKey = Math.floor(widgets.length / cpus) |
| | | let remainingData = widgets.length |
| | |
| | | */ |
| | | function runBuild(nodeIndex) { |
| | | const cmdParams = ['run', 'build-lib'] |
| | | const run = crossSpawn( |
| | | cmdParams.push(isDebugMode ? 'development' : 'production') |
| | | const run = spawn( |
| | | process.platform === 'win32' ? 'npm.cmd' : 'npm', |
| | | cmdParams, |
| | | { |
| | |
| | | }, |
| | | } |
| | | ) |
| | | run.on('close', (code) => { |
| | | |
| | | run.on('close', async (code) => { |
| | | if (code == 0 && isSingleBuild) rmSync(argvPath) |
| | | // æ·»å æå
hash |
| | | buildCount++ |
| | | await tag() |
| | | if (!isSingleBuild) { |
| | | if (buildCount >= buildSumCount) { |
| | | console.log(chalk.green(`å·²ç»ç¼è¯å®ææç»ä»¶ï¼æ·»å çæ¬tagï¼è¯·ç¨å...`)) |
| | | console.log(chalk.green(`å¼å§æå
wwwroot.zipå
`)) |
| | | getHostPackage() |
| | | } |
| | | } |
| | | }) |
| | | } |
| | | /** |
| | | * è·åhostå
zipå
|
| | | * @param {*} |
| | | */ |
| | | function getHostPackage() { |
| | | const resourcesPath = slash( |
| | | path.resolve(process.cwd(), `${baseDir}/resources`) |
| | | ) |
| | | const widgetsPath = slash(path.resolve(process.cwd(), `${baseDir}/widgets`)) |
| | | const currentDistPath = slash(path.resolve(process.cwd(), './dist')) |
| | | const isResources = fs.existsSync(resourcesPath) |
| | | const isWidgets = fs.existsSync(widgetsPath) |
| | | if (!isResources) { |
| | | fs.mkdirpSync(resourcesPath) |
| | | } |
| | | if (!isWidgets) { |
| | | fs.mkdirpSync(widgetsPath) |
| | | } |
| | | |
| | | const git = crossSpawn.sync('git', ['clone', assetsUrl, '-b', 'develop'], { |
| | | stdio: 'inherit', |
| | | cwd: resourcesPath, |
| | | shell: true, |
| | | }) |
| | | |
| | | if (git.status === 0) { |
| | | fs.rmSync(slash(path.resolve(resourcesPath, './assets/.git')), { |
| | | recursive: true, |
| | | }) |
| | | const dirs = globSync(slash(path.resolve(currentDistPath, './**/*.js'))) |
| | | dirs.forEach((dir) => { |
| | | const widgetName = slash(dir).replace(currentDistPath, '.') |
| | | const widgetPath = slash(path.resolve(widgetsPath, widgetName)) |
| | | |
| | | fs.copySync(slash(dir), widgetPath) |
| | | }) |
| | | zipDir(hostPath, hostZipPath) |
| | | .then(() => { |
| | | console.log(chalk.green(`${hostZipPath} å缩æå`)) |
| | | fs.rmSync(hostPath, { |
| | | recursive: true, |
| | | }) |
| | | console.log( |
| | | chalk.green(`ç¼è¯æ»æ¶é´: ${(Date.now() - startTime) / 1000}ç§`) |
| | | ) |
| | | }) |
| | | .catch((error) => { |
| | | console.log(error) |
| | | }) |
| | | } |
| | | } |
| | | /** |
| | | * å缩zipå
|
| | | * @param {*} dir |
| | | * @param {*} zipPath |
| | | * @returns |
| | | */ |
| | | function zipDir(dir, zipPath) { |
| | | return new Promise(async (resolve, reject) => { |
| | | try { |
| | | await zip(slash(dir), slash(zipPath)) |
| | | resolve() |
| | | } catch (error) { |
| | | reject(error) |
| | | } |
| | | }) |
| | | } |
| | | /** |
| | | * å é¤hostå
|
| | | * @param {*} |
| | | */ |
| | | function removeHostPackage() { |
| | | if (fs.existsSync(hostPath)) { |
| | | fs.rmSync(hostPath, { |
| | | recursive: true, |
| | | }) |
| | | } |
| | | if (fs.existsSync(hostZipPath)) { |
| | | fs.rmSync(hostZipPath, { |
| | | recursive: true, |
| | | }) |
| | | } |
| | | } |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | export const external = [ |
| | | 'vue', |
| | | 'sdk', |
| | | 'element-plus', |
| | | 'lodash', |
| | | 'sortablejs', |
| | | '@vueuse/core', |
| | | 'dayjs', |
| | | 'vxe-table', |
| | | '@element-plus/icons-vue', |
| | | '@element-plus', |
| | | /node_modules/, |
| | | 'koa-compose', |
| | | 'lodash', |
| | | 'lodash/add', |
| | | 'lodash/after', |
| | | 'lodash/ary', |
| | | 'lodash/assign', |
| | | 'lodash/assignIn', |
| | | 'lodash/assignInWith', |
| | | 'lodash/assignWith', |
| | | 'lodash/at', |
| | | 'lodash/attempt', |
| | | 'lodash/before', |
| | | 'lodash/bind', |
| | | 'lodash/bindAll', |
| | | 'lodash/bindKey', |
| | | 'lodash/camelCase', |
| | | 'lodash/capitalize', |
| | | 'lodash/castArray', |
| | | 'lodash/ceil', |
| | | 'lodash/chain', |
| | | 'lodash/chunk', |
| | | 'lodash/clamp', |
| | | 'lodash/clone', |
| | | 'lodash/cloneDeep', |
| | | 'lodash/cloneDeepWith', |
| | | 'lodash/cloneWith', |
| | | 'lodash/commit', |
| | | 'lodash/compact', |
| | | 'lodash/concat', |
| | | 'lodash/cond', |
| | | 'lodash/conforms', |
| | | 'lodash/conformsTo', |
| | | 'lodash/constant', |
| | | 'lodash/countBy', |
| | | 'lodash/create', |
| | | 'lodash/curry', |
| | | 'lodash/curryRight', |
| | | 'lodash/debounce', |
| | | 'lodash/deburr', |
| | | 'lodash/defaults', |
| | | 'lodash/defaultsDeep', |
| | | 'lodash/defaultTo', |
| | | 'lodash/defer', |
| | | 'lodash/delay', |
| | | 'lodash/difference', |
| | | 'lodash/differenceBy', |
| | | 'lodash/differenceWith', |
| | | 'lodash/divide', |
| | | 'lodash/drop', |
| | | 'lodash/dropRight', |
| | | 'lodash/dropRightWhile', |
| | | 'lodash/dropWhile', |
| | | 'lodash/each', |
| | | 'lodash/eachRight', |
| | | 'lodash/endsWith', |
| | | 'lodash/entries', |
| | | 'lodash/entriesIn', |
| | | 'lodash/eq', |
| | | 'lodash/escape', |
| | | 'lodash/escapeRegExp', |
| | | 'lodash/every', |
| | | 'lodash/extend', |
| | | 'lodash/extendWith', |
| | | 'lodash/fill', |
| | | 'lodash/filter', |
| | | 'lodash/find', |
| | | 'lodash/findIndex', |
| | | 'lodash/findKey', |
| | | 'lodash/findLast', |
| | | 'lodash/findLastIndex', |
| | | 'lodash/findLastKey', |
| | | 'lodash/first', |
| | | 'lodash/flatMap', |
| | | 'lodash/flatMapDeep', |
| | | 'lodash/flatMapDepth', |
| | | 'lodash/flatten', |
| | | 'lodash/flattenDeep', |
| | | 'lodash/flattenDepth', |
| | | 'lodash/flip', |
| | | 'lodash/floor', |
| | | 'lodash/flow', |
| | | 'lodash/flowRight', |
| | | 'lodash/forEach', |
| | | 'lodash/forEachRight', |
| | | 'lodash/forIn', |
| | | 'lodash/forInRight', |
| | | 'lodash/forOwn', |
| | | 'lodash/forOwnRight', |
| | | 'lodash/fromPairs', |
| | | 'lodash/functions', |
| | | 'lodash/functionsIn', |
| | | 'lodash/get', |
| | | 'lodash/groupBy', |
| | | 'lodash/gt', |
| | | 'lodash/gte', |
| | | 'lodash/has', |
| | | 'lodash/hasIn', |
| | | 'lodash/head', |
| | | 'lodash/identity', |
| | | 'lodash/includes', |
| | | 'lodash/indexOf', |
| | | 'lodash/initial', |
| | | 'lodash/inRange', |
| | | 'lodash/intersection', |
| | | 'lodash/intersectionBy', |
| | | 'lodash/intersectionWith', |
| | | 'lodash/invert', |
| | | 'lodash/invertBy', |
| | | 'lodash/invoke', |
| | | 'lodash/invokeMap', |
| | | 'lodash/isArguments', |
| | | 'lodash/isArray', |
| | | 'lodash/isArrayBuffer', |
| | | 'lodash/isArrayLike', |
| | | 'lodash/isArrayLikeObject', |
| | | 'lodash/isBoolean', |
| | | 'lodash/isBuffer', |
| | | 'lodash/isDate', |
| | | 'lodash/isElement', |
| | | 'lodash/isEmpty', |
| | | 'lodash/isEqual', |
| | | 'lodash/isEqualWith', |
| | | 'lodash/isError', |
| | | 'lodash/isFinite', |
| | | 'lodash/isFunction', |
| | | 'lodash/isInteger', |
| | | 'lodash/isLength', |
| | | 'lodash/isMap', |
| | | 'lodash/isMatch', |
| | | 'lodash/isMatchWith', |
| | | 'lodash/isNaN', |
| | | 'lodash/isNative', |
| | | 'lodash/isNil', |
| | | 'lodash/isNull', |
| | | 'lodash/isNumber', |
| | | 'lodash/isObject', |
| | | 'lodash/isObjectLike', |
| | | 'lodash/isPlainObject', |
| | | 'lodash/isRegExp', |
| | | 'lodash/isSafeInteger', |
| | | 'lodash/isSet', |
| | | 'lodash/isString', |
| | | 'lodash/isSymbol', |
| | | 'lodash/isTypedArray', |
| | | 'lodash/isUndefined', |
| | | 'lodash/isWeakMap', |
| | | 'lodash/isWeakSet', |
| | | 'lodash/join', |
| | | 'lodash/kebabCase', |
| | | 'lodash/keyBy', |
| | | 'lodash/keys', |
| | | 'lodash/keysIn', |
| | | 'lodash/last', |
| | | 'lodash/lastIndexOf', |
| | | 'lodash/lowerCase', |
| | | 'lodash/lowerFirst', |
| | | 'lodash/lt', |
| | | 'lodash/lte', |
| | | 'lodash/map', |
| | | 'lodash/mapKeys', |
| | | 'lodash/mapValues', |
| | | 'lodash/matches', |
| | | 'lodash/matchesProperty', |
| | | 'lodash/max', |
| | | 'lodash/maxBy', |
| | | 'lodash/mean', |
| | | 'lodash/meanBy', |
| | | 'lodash/memoize', |
| | | 'lodash/merge', |
| | | 'lodash/mergeWith', |
| | | 'lodash/method', |
| | | 'lodash/methodOf', |
| | | 'lodash/min', |
| | | 'lodash/minBy', |
| | | 'lodash/mixin', |
| | | 'lodash/multiply', |
| | | 'lodash/negate', |
| | | 'lodash/noConflict', |
| | | 'lodash/noop', |
| | | 'lodash/now', |
| | | 'lodash/nth', |
| | | 'lodash/nthArg', |
| | | 'lodash/once', |
| | | 'lodash/orderBy', |
| | | 'lodash/over', |
| | | 'lodash/overArgs', |
| | | 'lodash/overEvery', |
| | | 'lodash/overSome', |
| | | 'lodash/pad', |
| | | 'lodash/padEnd', |
| | | 'lodash/padStart', |
| | | 'lodash/parseInt', |
| | | 'lodash/partial', |
| | | 'lodash/partialRight', |
| | | 'lodash/partition', |
| | | 'lodash/pick', |
| | | 'lodash/pickBy', |
| | | 'lodash/property', |
| | | 'lodash/propertyOf', |
| | | 'lodash/pull', |
| | | 'lodash/pullAll', |
| | | 'lodash/pullAllBy', |
| | | 'lodash/pullAllWith', |
| | | 'lodash/pullAt', |
| | | 'lodash/random', |
| | | 'lodash/range', |
| | | 'lodash/rangeRight', |
| | | 'lodash/rearg', |
| | | 'lodash/reduce', |
| | | 'lodash/reduceRight', |
| | | 'lodash/reject', |
| | | 'lodash/remove', |
| | | 'lodash/repeat', |
| | | 'lodash/replace', |
| | | 'lodash/result', |
| | | 'lodash/reverse', |
| | | 'lodash/round', |
| | | 'lodash/sample', |
| | | 'lodash/sampleSize', |
| | | 'lodash/set', |
| | | 'lodash/setWith', |
| | | 'lodash/shuffle', |
| | | 'lodash/size', |
| | | 'lodash/slice', |
| | | 'lodash/snakeCase', |
| | | 'lodash/some', |
| | | 'lodash/sortBy', |
| | | 'lodash/sortedIndex', |
| | | 'lodash/sortedIndexBy', |
| | | 'lodash/sortedIndexOf', |
| | | 'lodash/sortedLastIndex', |
| | | 'lodash/sortedLastIndexBy', |
| | | 'lodash/sortedLastIndexOf', |
| | | 'lodash/sortedUniq', |
| | | 'lodash/sortedUniqBy', |
| | | 'lodash/split', |
| | | 'lodash/spread', |
| | | 'lodash/startCase', |
| | | 'lodash/startsWith', |
| | | 'lodash/stubArray', |
| | | 'lodash/stubFalse', |
| | | 'lodash/stubObject', |
| | | 'lodash/stubString', |
| | | 'lodash/stubTrue', |
| | | 'lodash/subtract', |
| | | 'lodash/sum', |
| | | 'lodash/sumBy', |
| | | 'lodash/tail', |
| | | 'lodash/take', |
| | | 'lodash/takeRight', |
| | | 'lodash/takeRightWhile', |
| | | 'lodash/takeWhile', |
| | | 'lodash/tap', |
| | | 'lodash/template', |
| | | 'lodash/throttle', |
| | | 'lodash/thru', |
| | | 'lodash/times', |
| | | 'lodash/toArray', |
| | | 'lodash/toFinite', |
| | | 'lodash/toInteger', |
| | | 'lodash/toLength', |
| | | 'lodash/toLower', |
| | | 'lodash/toNumber', |
| | | 'lodash/toPairs', |
| | | 'lodash/toPairsIn', |
| | | 'lodash/toPath', |
| | | 'lodash/toPlainObject', |
| | | 'lodash/toSafeInteger', |
| | | 'lodash/toString', |
| | | 'lodash/toUpper', |
| | | 'lodash/transform', |
| | | 'lodash/trim', |
| | | 'lodash/trimEnd', |
| | | 'lodash/trimStart', |
| | | 'lodash/truncate', |
| | | 'lodash/unary', |
| | | 'lodash/unescape', |
| | | 'lodash/union', |
| | | 'lodash/unionBy', |
| | | 'lodash/unionWith', |
| | | 'lodash/uniq', |
| | | 'lodash/uniqBy', |
| | | 'lodash/uniqWith', |
| | | 'lodash/uniqueId', |
| | | 'lodash/unset', |
| | | 'lodash/unzip', |
| | | 'lodash/unzipWith', |
| | | 'lodash/update', |
| | | 'lodash/updateWith', |
| | | 'lodash/upperCase', |
| | | 'lodash/upperFirst', |
| | | 'lodash/value', |
| | | 'lodash/valueOf', |
| | | 'lodash/values', |
| | | 'lodash/valuesIn', |
| | | 'lodash/without', |
| | | 'lodash/words', |
| | | 'lodash/wrap', |
| | | 'lodash/xor', |
| | | 'lodash/xorBy', |
| | | 'lodash/xorWith', |
| | | 'lodash/zip', |
| | | 'lodash/zipObject', |
| | | 'lodash/zipObjectDeep', |
| | | 'lodash/zipWith', |
| | | ] |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | const { glob } = require('glob') |
| | | const { readFileSync, writeFileSync, ensureDirSync } = require('fs-extra') |
| | | const { resolve } = require('path') |
| | | const regExp = /export default [\s\S]*?;/ |
| | | const regExpObj = /\{[\s\S]*?;/ |
| | | const babel = require('@babel/core') |
| | | const pkg = require('../package.json') |
| | | const isWin = process.platform === 'win32' |
| | | |
| | | /** |
| | | * æ ¹æ®widgetsä¸çç»ä»¶ï¼èªå¨çæèåæ°æ®ï¼ç¨äºå¯¹å¤å¼ç¨ |
| | | */ |
| | | async function start() { |
| | | const tsFiles = await glob(resolve(process.cwd(), 'src/widgets/*/index.ts'), { |
| | | ignore: 'node_modules/**', |
| | | windowsPathsNoEscape: true, |
| | | }) |
| | | |
| | | const menu = [] |
| | | const menuMap = {} |
| | | const errorKey = ' is not defined' |
| | | |
| | | tsFiles.forEach((filePath) => { |
| | | const spl = !isWin ? filePath.split('/') : filePath.split('\\') |
| | | |
| | | const patchName = spl[spl.length - 2] |
| | | const file = readFileSync(filePath, { encoding: 'utf8' }) |
| | | const { code } = babel.transformSync(file) |
| | | const exportDefaultRegion = code.match(regExp) |
| | | const exportDefaultContent = exportDefaultRegion[0] |
| | | if (exportDefaultContent) { |
| | | const v = exportDefaultContent.match(regExpObj) |
| | | const canvasView = exportDefaultContent.match(/canvasView: ([^,]+),/) |
| | | let canvasViewValue = canvasView ? canvasView[0] : '' |
| | | canvasViewValue = !canvasViewValue.includes(')') |
| | | ? canvasViewValue.replace(',', '),') |
| | | : canvasViewValue |
| | | |
| | | const c = v[0].replace(canvasViewValue, '') |
| | | let setViewMatch = c.match(/settingsView:\s*(.*?)(?=\s*[,}])/) |
| | | let newCode = '' |
| | | if (setViewMatch[0]) { |
| | | newCode = c.replace(setViewMatch[0], '').replace(';', '') |
| | | } |
| | | if (newCode.includes('canvasView')) { |
| | | newCode = newCode.replace( |
| | | /canvasView\s*:\s*.*?(\{.*?\}|\(.*?\)|[^\s,]+)\s*,?\s*(?=\n|$)/gs, |
| | | '' |
| | | ) |
| | | } |
| | | |
| | | const codeRun = (code) => { |
| | | const fn = new Function(`return ${code}`) |
| | | const widgetInfo = fn() |
| | | const row = { |
| | | name: widgetInfo.name, |
| | | path: `/${pkg.name}/` + patchName, |
| | | patchName: patchName, |
| | | |
| | | icon: widgetInfo.icon, |
| | | notPage: !!widgetInfo.notPage, |
| | | } |
| | | menu.push(row) |
| | | menuMap[patchName] = row |
| | | } |
| | | try { |
| | | codeRun(newCode) |
| | | } catch (error) { |
| | | if (error.message.includes(errorKey)) { |
| | | const iconKey = error.message.split(errorKey) |
| | | if (iconKey.length > 1) { |
| | | const iconName = iconKey[0] |
| | | const code = newCode.replaceAll(iconName, `"${iconName}"`) |
| | | codeRun(code) |
| | | } |
| | | } else { |
| | | console.error(error.message) |
| | | } |
| | | } |
| | | } |
| | | }) |
| | | const data = `export const menu: Record<string,any>[] = ${JSON.stringify( |
| | | menu, |
| | | null, |
| | | 2 |
| | | )};\nexport const menuMap: Record<string,any> = ${JSON.stringify( |
| | | menuMap, |
| | | null, |
| | | 2 |
| | | )};` |
| | | // çæmenu JSON å°build.prod |
| | | // const buildInfo = readFileSync(resolve(process.cwd(), '.build'), { |
| | | // encoding: 'utf-8', |
| | | // }) |
| | | // const recoveryWidget = buildInfo.split('\n') |
| | | ensureDirSync(resolve(process.cwd(), './src/config/')) |
| | | writeFileSync(resolve(process.cwd(), './src/config/menu.ts'), data, { |
| | | encoding: 'utf-8', |
| | | }) |
| | | |
| | | // const widgets = menu |
| | | // .map((item) => item.patchName) |
| | | // .filter((name) => !recoveryWidget.includes(name)) |
| | | // writeFileSync(resolve(process.cwd(), '.build.prod'), widgets.join('\n'), { |
| | | // encoding: 'utf-8', |
| | | // }) |
| | | } |
| | | const startTime = performance.now() |
| | | |
| | | start() |
| | | |
| | | console.log('æ§è¡æ¶é´: ', Math.ceil(performance.now() - startTime), 'ms') |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | // @ts-nocheck |
| | | |
| | | /** |
| | | * å¢å debuggerç»ä»¶ |
| | | * @param option |
| | | * @returns |
| | | */ |
| | | export default function VitePluginDevelopmentFilter(option: { |
| | | tag: string |
| | | prodTag: string |
| | | }): any { |
| | | return { |
| | | name: 'vite-plugin-development-filter', |
| | | transform(code, id) { |
| | | const { tag, prodTag } = option |
| | | const regexWithCapture = new RegExp( |
| | | `<${tag}>([\\s\\S]*?)<\\/${tag}>`, |
| | | 'g' |
| | | ) |
| | | const regexWithCaptureProd = new RegExp( |
| | | `<${prodTag}>([\\s\\S]*?)<\\/${prodTag}>`, |
| | | 'g' |
| | | ) |
| | | if (regexWithCapture.test(code)) { |
| | | if (process.env.NODE_ENV === 'production') { |
| | | const newCode = code.replaceAll(regexWithCapture, '') |
| | | return newCode |
| | | .replaceAll(`<${prodTag}>`, '') |
| | | .replaceAll(`</${prodTag}>`, '') |
| | | } |
| | | } |
| | | if (regexWithCaptureProd.test(code)) { |
| | | if (process.env.NODE_ENV === 'development') { |
| | | const newCode = code.replaceAll(regexWithCaptureProd, '') |
| | | return newCode |
| | | } |
| | | } |
| | | return code |
| | | }, |
| | | } |
| | | } |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | /** |
| | | * å¢å debuggerç»ä»¶ |
| | | * @param option |
| | | * @returns |
| | | */ |
| | | export default function VitePluginDevelopmentFilter(): any { |
| | | return { |
| | | name: 'vite-plugin-image-filter', |
| | | apply: 'build', |
| | | |
| | | transform(code, id) { |
| | | if (code.includes('createVNode(Icon')) { |
| | | console.info('code', code) |
| | | } |
| | | // const tag = 'Icon' |
| | | // const regexWithCapture = new RegExp( |
| | | // `<${tag}>([\\s\\S]*?)<\\/${tag}>`, |
| | | // 'g' |
| | | // ) |
| | | |
| | | // if (regexWithCapture.test(code)) { |
| | | // if (process.env.NODE_ENV === 'production') { |
| | | // const newCode = code.replaceAll(regexWithCapture, '') |
| | | // return newCode |
| | | // } |
| | | // } |
| | | return code |
| | | }, |
| | | } |
| | | } |
| | |
| | | // @ts-ignore |
| | | const filePath = isWin ? basePath.replaceAll('\\', '/') : basePath |
| | | const regex = new RegExp(`${filePath}/([^/]*)/index.ts`) |
| | | const NOT_PAGE = 'notPage:true' |
| | | /** |
| | | * æåå
³é®å符 |
| | | * @param {*} code |
| | |
| | | if (regex.test(id)) { |
| | | const codeData = parseCode(code) |
| | | const transformCode = mergeCodeString(codeData, code) |
| | | // const emptyCode = code.replaceAll(' ', '') |
| | | |
| | | const newCode = transformCode |
| | | // const newCode = emptyCode.includes(NOT_PAGE) ? code : transformCode |
| | | return { |
| | | code: transformCode, |
| | | code: newCode, |
| | | map: null, // 妿å¯è¡å°æä¾ source map |
| | | } |
| | | } |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | /** |
| | | * éè¿element plusèªå¨çnamespaceè¿è¡æ ·å¼å离 |
| | | * ç±äºç®åelement plusèªå¨çnamespaceï¼æ æ³æ¯ætreeshaking |
| | | * å æ¤æå
ä¹åï¼åéådistæä»¶å¤¹ï¼æ¿æ¢æå
ä¹åçjsãcsså¼ï¼å®ç°namespaceæç»ææ |
| | | */ |
| | | /* eslint-disable no-undef */ |
| | | const fs = require('fs') |
| | | const path = require('path') |
| | | |
| | | const distPath = path.resolve(__dirname, '../dist/information-ui/es') |
| | | |
| | | fs.readdir(distPath, function (err, files) { |
| | | if (err) return console.error('Error:(spec)', err) |
| | | for (const filename of files) { |
| | | if (!filename.endsWith('js') && !filename.endsWith('.css')) continue |
| | | const filePath = distPath + '/' + filename |
| | | |
| | | fs.readFile(filePath, function (err, data) { |
| | | if (err) { |
| | | return err |
| | | } |
| | | let str = data.toString() |
| | | |
| | | // jsä»
æ¿æ¢namespace keyå¼å³å¯ |
| | | if (filename.endsWith('js')) { |
| | | str = str.replace('"el"', '"cs"') |
| | | } |
| | | // csséè¦æ¿æ¢ææçel- |
| | | if (filename.endsWith('.css')) { |
| | | str = str.replace(/el-/g, 'cs-') |
| | | } |
| | | |
| | | fs.writeFile(filePath, str, function (err) { |
| | | if (err) return err |
| | | }) |
| | | }) |
| | | } |
| | | }) |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | const { globSync } = require('glob') |
| | | const execa = require('execa') |
| | | const slash = require('slash') |
| | | const path = require('path') |
| | | const fs = require('fs-extra') |
| | | |
| | | const getWidgetsPath = async () => { |
| | | const widgetsPath = globSync(`./src/widgets/*/`) |
| | | for (let index = 0; index < widgetsPath.length; index++) { |
| | | const widgetPath = slash(widgetsPath[index]) |
| | | const slashCwd = slash(process.cwd()) |
| | | const cwd = slash(path.resolve(slashCwd, widgetPath)) |
| | | const gitInfo = await getGitInfo(cwd) |
| | | const wPaths = widgetPath.split('/') |
| | | const widgetName = wPaths[wPaths.length - 1] |
| | | if (widgetName) { |
| | | const tag = { |
| | | commit: gitInfo.commit?.stdout, |
| | | branch: gitInfo.branch?.stdout, |
| | | userName: gitInfo.userName?.stdout, |
| | | } |
| | | const widgetTagFile = slash( |
| | | path.resolve(slashCwd, `dist/${widgetName}/version.tag`) |
| | | ) |
| | | const widgetFile = slash( |
| | | path.resolve(slashCwd, `dist/${widgetName}/index.js`) |
| | | ) |
| | | |
| | | const isExist = fs.existsSync(widgetFile) |
| | | if (isExist) { |
| | | fs.writeJsonSync(widgetTagFile, tag) |
| | | } |
| | | } |
| | | } |
| | | } |
| | | |
| | | /** |
| | | * è·ågitä¿¡æ¯ |
| | | * @returns |
| | | */ |
| | | const getGitInfo = async (cwd) => { |
| | | const option = { |
| | | cwd, |
| | | } |
| | | async function getGitHash() { |
| | | return await execa('git', ['rev-parse', '--short', 'HEAD'], option) |
| | | } |
| | | |
| | | async function getGitBranch() { |
| | | return execa('git', ['rev-parse', '--abbrev-ref', 'HEAD'], option) |
| | | } |
| | | |
| | | async function getGitUserName() { |
| | | return execa('git', ['config', 'user.name'], option) |
| | | } |
| | | try { |
| | | const commit = await getGitHash() |
| | | const branch = await getGitBranch() |
| | | const userName = await getGitUserName() |
| | | return { |
| | | commit, |
| | | branch, |
| | | userName, |
| | | } |
| | | } catch (error) { |
| | | console.error(error) |
| | | return {} |
| | | } |
| | | } |
| | | |
| | | const start = getWidgetsPath |
| | | |
| | | module.exports = start |
| | |
| | | try { |
| | | await fn('.tsx') |
| | | } catch (error) { |
| | | console.log(error, 'error') |
| | | await fn('.vue') |
| | | } |
| | | } |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | import sdk from 'sdk' |
| | | import { ConfigureCodeMap } from '@/libs/system-enum' |
| | | // import { getSettings } from '@/widgets/SystemManagement/Models/Service/Service' |
| | | const { utils } = sdk |
| | | const { request } = utils |
| | | /** |
| | | * 夿æ¯å¦ä¸ºå¯¹è±¡ |
| | | * @param str |
| | | * @returns |
| | | */ |
| | | const isStringAnObject = (str: string) => { |
| | | try { |
| | | const obj = JSON.parse(str) |
| | | return typeof obj === 'object' && obj !== null |
| | | } catch (e) { |
| | | return false |
| | | } |
| | | } |
| | | |
| | | /** |
| | | * è·å设置 |
| | | * @returns |
| | | */ |
| | | export const getSettings = () => { |
| | | return request.get( |
| | | `/api/v1/settingmanagement/setting/G?namePrefix=SCMS.AppSettings` |
| | | ) |
| | | } |
| | | |
| | | /** |
| | | * æä¸¾è·åæ¥å£ |
| | | * @param type æä¸¾å¼ |
| | | * @returns |
| | | */ |
| | | export const getEnumList = (type: string): Promise<any> => { |
| | | return request({ |
| | | url: `/api/v1/messuite/query/enumeration/${type}`, |
| | | method: 'get', |
| | | }) |
| | | } |
| | | |
| | | /** |
| | | * è·åå·¥åºæ¥å£ |
| | | * @param filter çé |
| | | * @returns |
| | | */ |
| | | export const getWorkSectionApi = ( |
| | | filter?: any |
| | | ): Promise<{ items: any[]; totalCount: number }> => { |
| | | const str = new URLSearchParams( |
| | | filter as unknown as URLSearchParams |
| | | ).toString() |
| | | return request.get(`/api/v1/messuite/query/worksection?` + str) |
| | | } |
| | | |
| | | /** |
| | | * è·åå·¥ä½ |
| | | * @param filter çé |
| | | * @returns |
| | | */ |
| | | export const getWorkStationApi = ( |
| | | filter?: any |
| | | ): Promise<{ items: any[]; totalCount: number }> => { |
| | | const str = new URLSearchParams( |
| | | filter as unknown as URLSearchParams |
| | | ).toString() |
| | | return request.get(`/api/v1/messuite/query/workstation?` + str) |
| | | } |
| | | |
| | | export const getFormDataBySettings = async () => { |
| | | const { settings } = (await getSettings()) || { |
| | | settings: [], |
| | | } |
| | | const formData: any = {} |
| | | |
| | | settings.forEach((item: any) => { |
| | | const keys = item.name.split('.') |
| | | const key = keys[keys.length - 1] |
| | | if (key) { |
| | | if (typeof item.name === ConfigureCodeMap.ProductionLineSegment) { |
| | | try { |
| | | item.value = JSON.parse(item.value) |
| | | formData[key] = item.value |
| | | } catch (error) { |
| | | item.value = [] |
| | | } |
| | | } else { |
| | | try { |
| | | if (isStringAnObject(item.value)) { |
| | | formData[key] = JSON.parse(item.value) |
| | | } else { |
| | | formData[key] = item.value |
| | | } |
| | | } catch (error) { |
| | | formData[key] = [] |
| | | console.error(error) |
| | | } |
| | | } |
| | | } |
| | | }) |
| | | |
| | | return formData |
| | | } |
| | | |
| | | /** |
| | | * è·åæµç¨å表 |
| | | * @returns |
| | | */ |
| | | export const getFlowData = () => { |
| | | return request.get( |
| | | `/api/v1/messuite/query/flowdefinition?MaxResultCount=9999&SkipCount=0` |
| | | ) |
| | | } |
| | | // è·åç©æç±»å |
| | | export const getMaterialTypes = () => { |
| | | return request.get(`/api/v1/materialmanagement/material/types`) |
| | | } |
| | | |
| | | /** |
| | | * è·åç©æç±»å |
| | | * @returns |
| | | */ |
| | | export const getMaterialTypesEnum = async () => { |
| | | return request.get(`/api/v1/messuite/query/enumeration/MaterialType`) |
| | | } |
| | | |
| | | // çæ¬åè½å表 |
| | | export const getFeatureListData = (providerKey: string = 'Basic') => { |
| | | if (providerKey) { |
| | | return request.get( |
| | | `/api/v1/featuremanagement/feature/E?providerKey=${providerKey}` |
| | | ) |
| | | } |
| | | return Promise.resolve({ |
| | | group: [], |
| | | }) |
| | | } |
| | |
| | | responseType: 'blob', |
| | | }) |
| | | } |
| | | /** |
| | | * å¯¼åº post è¯·æ± |
| | | * @param data |
| | | * @returns |
| | | */ |
| | | export const postExportFileToClient = ( |
| | | url: string, |
| | | params: Record<string, any> |
| | | ) => { |
| | | return request.post(url, params, { |
| | | responseType: 'blob', |
| | | }) |
| | | } |
| | |
| | | import { ElMessage } from 'element-plus' |
| | | const { request } = sdk.utils |
| | | |
| | | // !éå¿
è¦ï¼ä¸è¦å¨æ¤å 彿°ï¼è¯·å¨å¯¹åºçapiæä»¶ä¸æ·»å ï¼ç»ä»¶apiï¼è¯·å¨ç»ä»¶ä¸æ·»å api.tsä¸æä»¶æ·»å |
| | | |
| | | function getProject(tree: any[]) { |
| | | // æ¹ä¾¿è°è¯ |
| | | const projectId = import.meta.env.VITE_APP_PROJECT_ID |
| | | const target = tree.find((e: any) => e.id === projectId) |
| | | const target = tree.find((e: any) => e.id == projectId) |
| | | if (target) return target |
| | | for (let i = 0; i < tree.length; i++) { |
| | | const item = tree[i] |
| | |
| | | } |
| | | } |
| | | } |
| | | export const getXProject = async () => { |
| | | const tree: any = await request.get('/api/v1/project/node/tree') |
| | | return tree |
| | | } |
| | | |
| | | const projectInfo = async (id: string | number = 0) => { |
| | | const info: Record<string, any> = await request.get( |
| | | `/api/v1/project/${id}/info` |
| | |
| | | sessionStorage.setItem('X-Project', info.identifier) |
| | | sessionStorage.setItem('X-Project-Name', info.name) |
| | | } |
| | | |
| | | export const getXProject = async () => { |
| | | const tree: any = await request.get('/api/v1/project/node/tree') |
| | | return tree |
| | | } |
| | | |
| | | export const setXProject = async () => { |
| | | try { |
| | | const tree: any = await request.get('/api/v1/project/node/tree') |
| | | const tree: any = await getXProject() |
| | | if (tree.length) { |
| | | const project = getProject(tree) |
| | | await projectInfo(project.id) |
| | |
| | | } |
| | | } |
| | | |
| | | let provider = { ConfigName: '' } |
| | | export const setProvider = (computed: any) => { |
| | | provider = computed |
| | | } |
| | | export const postImport = (file: FormData) => { |
| | | return request({ |
| | | url: `/api/v1/zc/productsop/uploadsop`, |
| | |
| | | data: file, |
| | | }) |
| | | } |
| | | |
| | | //产å |
| | | function getproductList(data: any, hasFormula: boolean = true) { |
| | | const url = `api/v1/messuite/query/product?filter=${data.filter}&hasFormula=${hasFormula}` |
| | | const method = 'get' |
| | | return import.meta.env.PROD |
| | | ? sdk.request({ url, method }) |
| | | : request({ url, method }) |
| | | } |
| | | |
| | | // å·¥åºå表 |
| | | function getWorksectionList(data: any) { |
| | | const url = `api/v1/messuite/query/worksection?filter=${data.filter}&abilityType=${data.abilityType}&includeDetails=${data.includeDetails}` |
| | | const method = 'get' |
| | | return import.meta.env.PROD |
| | | ? sdk.request({ url, method }) |
| | | : request({ url, method }) |
| | | } |
| | | |
| | | function getTableheader(data: any) { |
| | | const url = `api/v1/tracemanagement/trace/tableheader?productId=${data.productId}` |
| | | const method = 'get' |
| | | return import.meta.env.PROD |
| | | ? sdk.request({ url, method, params: { ...provider } }) |
| | | : request({ url, method, params: { ...provider } }) |
| | | } |
| | | |
| | | function getTablelayout(data: any) { |
| | | const url = `api/v1/tracemanagement/trace/tablelayout?productId=${encodeURIComponent( |
| | | data.productId |
| | | )}&tableId=${data.tableId}&isSummary=${data.isSummary}&onlyIncludeParameter=${ |
| | | data.onlyIncludeParameter || false |
| | | }` |
| | | const method = 'get' |
| | | return import.meta.env.PROD |
| | | ? sdk.request({ url, method, params: { ...provider } }) |
| | | : request({ url, method, params: { ...provider } }) |
| | | } |
| | | |
| | | function getTraceList(data: any) { |
| | | const url = `api/v1/tracemanagement/trace?SerialNumber=${encodeURIComponent( |
| | | data.SerialNumber |
| | | )}&SearchMode=${data.SearchMode}&From=${data.From}&To=${ |
| | | data.To |
| | | }&IsQualified=${data.IsQualified}&TableId=${data.TableId}&IsSummary=${ |
| | | data.IsSummary |
| | | }&SkipCount=${data.SkipCount}&MaxResultCount=${ |
| | | data.MaxResultCount |
| | | }&ProductModel=${encodeURIComponent( |
| | | data.ProductModel |
| | | )}&Updatecode=${encodeURIComponent( |
| | | data.Updatecode |
| | | )}&MaterialCode=${encodeURIComponent(data.MaterialCode)}&OrderCode=${ |
| | | data.OrderCode |
| | | }&IsAsc=${data.IsAsc || false}` |
| | | const method = 'get' |
| | | return import.meta.env.PROD |
| | | ? sdk.request({ url, method, params: { ...provider } }) |
| | | : request({ url, method, params: { ...provider } }) |
| | | } |
| | | |
| | | function getCurve(data: any) { |
| | | const url = `api/v1/tracemanagement/trace/curve?WorkSectionId=${data.WorkSectionId}&ParamId=${data.ParamId}&From=${data.From}&To=${data.To}&ProductModel=${data.ProductModel}` |
| | | const method = 'get' |
| | | return import.meta.env.PROD |
| | | ? sdk.request({ url, method, params: { ...provider } }) |
| | | : request({ url, method, params: { ...provider } }) |
| | | } |
| | | |
| | | function getStatistics(data: any) { |
| | | const url = `api/v1/tracemanagement/trace/statistics?SerialNumber=${encodeURIComponent( |
| | | data.SerialNumber |
| | | )}&SearchMode=${data.SearchMode}&From=${data.From}&To=${ |
| | | data.To |
| | | }&IsQualified=${data.IsQualified}&TableId=${data.TableId}&IsSummary=${ |
| | | data.IsSummary |
| | | }&ProductModel=${encodeURIComponent(data.ProductModel)}&Updatecode=${ |
| | | data.Updatecode |
| | | }&MaterialCode=${data.MaterialCode}&OrderCode=${data.OrderCode}` |
| | | const method = 'get' |
| | | return import.meta.env.PROD |
| | | ? sdk.request({ url, method, params: { ...provider } }) |
| | | : request({ url, method, params: { ...provider } }) |
| | | } |
| | | |
| | | function getSetting(data: any) { |
| | | const providerName = provider.ConfigName ? 'U' : 'G' |
| | | // const url = `api/v1/settingmanagement/setting?namePrefix=${data.namePrefix}` |
| | | const url = `api/v1/settingmanagement/setting/${providerName}?namePrefix=${ |
| | | data.namePrefix |
| | | }&providerKey=${provider.ConfigName || ''}` |
| | | const method = 'get' |
| | | return import.meta.env.PROD |
| | | ? sdk.request({ url, method, params: provider }) |
| | | : request({ url, method, params: provider }) |
| | | } |
| | | function saveSetting(data: any, providerKey?: string) { |
| | | const providerName = provider.ConfigName ? 'U' : 'G' |
| | | // const url = `api/v1/settingmanagement/setting` |
| | | let _providerKey = providerKey |
| | | ? `?providerKey=${provider.ConfigName || ''}` |
| | | : '' |
| | | const url = `api/v1/settingmanagement/setting/${providerName}${_providerKey}` |
| | | const method = 'post' |
| | | return import.meta.env.PROD |
| | | ? sdk.request({ url, method, data, params: provider }) |
| | | : request({ url, method, data, params: provider }) |
| | | } |
| | | |
| | | function getTraceproductmodelconfig(data: any) { |
| | | const url = `api/v1/tracemanagement/traceproductmodelconfig?ProductId=${ |
| | | data.ProductId |
| | | }&GetIfEmppty=${data.GetIfEmppty || false}&Filter=${data.Filter || ''}` |
| | | const method = 'get' |
| | | return import.meta.env.PROD |
| | | ? sdk.request({ url, method, params: { ...provider } }) |
| | | : request({ url, method, params: { ...provider } }) |
| | | } |
| | | |
| | | function getTracesummarytable(data: any) { |
| | | const url = `api/v1/tracemanagement/tracesummarytable?Filter=${data.Filter}&ProductId=${data.ProductId}&includeAll=true` |
| | | const method = 'get' |
| | | return import.meta.env.PROD |
| | | ? sdk.request({ url, method, params: { ...provider } }) |
| | | : request({ url, method, params: { ...provider } }) |
| | | } |
| | | |
| | | function creatTracesummarytable(data: any) { |
| | | const url = `api/v1/tracemanagement/tracesummarytable` |
| | | const method = 'post' |
| | | return import.meta.env.PROD |
| | | ? sdk.request({ url, method, data: { ...data, ...provider } }) |
| | | : request({ url, method, data: { ...data, ...provider } }) |
| | | } |
| | | |
| | | function updateTracesummarytable(data: any) { |
| | | const url = `api/v1/tracemanagement/tracesummarytable/${data.id}` |
| | | const method = 'put' |
| | | return import.meta.env.PROD |
| | | ? sdk.request({ url, method, data: { ...data, ...provider } }) |
| | | : request({ url, method, data: { ...data, ...provider } }) |
| | | } |
| | | |
| | | function delTracesummarytable(data: any) { |
| | | const url = `api/v1/tracemanagement/tracesummarytable` |
| | | const method = 'delete' |
| | | return import.meta.env.PROD |
| | | ? sdk.request({ url, method, data, params: { ...provider } }) |
| | | : request({ url, method, data, params: { ...provider } }) |
| | | } |
| | | |
| | | function getProcessroutebyproductmodel(data: any) { |
| | | const url = `api/v1/messuite/query/processroutebyproductmodel?productModel=${ |
| | | data.productModel || '' |
| | | }&includeDetails=${data.includeDetails || true}&includeFormulaDetails=${ |
| | | data.includeFormulaDetails || true |
| | | }` |
| | | const method = 'get' |
| | | return import.meta.env.PROD |
| | | ? sdk.request({ url, method }) |
| | | : request({ url, method }) |
| | | } |
| | | |
| | | function getProcessroute(data: any) { |
| | | const url = `api/v1/messuite/query/processroutes?productId=${ |
| | | data.productId || '' |
| | | }&includeDetails=${data.includeDetails || true}&includeFormulaDetails=${ |
| | | data.includeFormulaDetails || true |
| | | }` |
| | | const method = 'get' |
| | | return import.meta.env.PROD |
| | | ? sdk.request({ url, method }) |
| | | : request({ url, method }) |
| | | } |
| | | |
| | | function traceproductmodelconfig(data: any) { |
| | | const url = `api/v1/tracemanagement/traceproductmodelconfig` |
| | | const method = 'put' |
| | | return import.meta.env.PROD |
| | | ? sdk.request({ url, method, data: { ...data, ...provider } }) |
| | | : request({ url, method, data: { ...data, ...provider } }) |
| | | } |
| | | |
| | | function exportTrace(data: any) { |
| | | const url = `api/v1/tracemanagement/trace/export?SerialNumber=${data.SerialNumber}&SearchMode=${data.SearchMode}&ProductModel=${data.ProductModel}&From=${data.From}&To=${data.To}&IsQualified=${data.IsQualified}&TableId=${data.TableId}&IsSummary=${data.IsSummary}&Updatecode=${data.Updatecode}&MaterialCode=${data.MaterialCode}&OrderCode=${data.OrderCode}` |
| | | const method = 'get' |
| | | return import.meta.env.PROD |
| | | ? sdk.request({ url, method, data, params: provider, responseType: 'blob' }) |
| | | : request({ url, method, data, params: provider, responseType: 'blob' }) |
| | | } |
| | | |
| | | function saveTraceBackFieldWidth(data: any, tableName: string) { |
| | | const url = `/api/v1/messuite/setting/SCMS.TraceManagement.TraceTableSettings/${tableName}` |
| | | const method = 'post' |
| | | return sdk.request({ url, method, data }) |
| | | } |
| | | |
| | | export { |
| | | getproductList, |
| | | getWorksectionList, |
| | | getTraceList, |
| | | getSetting, |
| | | getTraceproductmodelconfig, |
| | | saveSetting, |
| | | getTracesummarytable, |
| | | delTracesummarytable, |
| | | creatTracesummarytable, |
| | | getProcessroutebyproductmodel, |
| | | getProcessroute, |
| | | updateTracesummarytable, |
| | | getTableheader, |
| | | getTablelayout, |
| | | getCurve, |
| | | getStatistics, |
| | | traceproductmodelconfig, |
| | | exportTrace, |
| | | saveTraceBackFieldWidth, |
| | | } |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | import sdk from 'sdk' |
| | | const { utils } = sdk |
| | | const { request } = utils |
| | | const isDev = process.env.NODE_ENV === 'development' |
| | | /** |
| | | * è·åæµç¨å¾xml |
| | | * @returns |
| | | */ |
| | | export const getFlowXml = async (flowType: string | number) => { |
| | | const res = await request.get( |
| | | `/api/v1/flowmanagement/flowdesign/define?flowType=${flowType}` |
| | | ) |
| | | return res |
| | | } |
| | | |
| | | export const getFlowData = (category: string) => { |
| | | return request.get( |
| | | `/api/v1/flowmanagement/flowdesign/type?category=${category}` |
| | | ) |
| | | } |
| | | |
| | | export const getFlowDetail = (type: string, flowType?: number) => { |
| | | const flowTypeStr = flowType ? `&flowType=${flowType}` : '' |
| | | return request.get( |
| | | `/api/v1/flowmanagement/flowdesign/attribute?type=${type}${flowTypeStr}` |
| | | ) |
| | | } |
| | | |
| | | export const saveFlowData = (data: any, isTemp: boolean) => { |
| | | return request.post( |
| | | `/api/v1/flowmanagement/flowdesign/define?isTemp=${isTemp}`, |
| | | data |
| | | ) |
| | | } |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | // @ts-ignore |
| | | import sdk from 'sdk' |
| | | const { utils } = sdk |
| | | const { request } = utils |
| | | |
| | | import type { |
| | | IVariables, |
| | | IPeriod, |
| | | IPeriodSetting, |
| | | } from '@/api/period-setting.type' |
| | | |
| | | interface MyResponse<T> { |
| | | data: { |
| | | variables: IVariables[] |
| | | periods: IPeriod[] |
| | | [key: string]: any |
| | | } |
| | | status: number |
| | | statusText: string |
| | | headers: any |
| | | config: any |
| | | } |
| | | |
| | | // 设å¤å°è´¦Table |
| | | export default { |
| | | getPeriodConfigs: (): Promise<MyResponse<IPeriodSetting>> => { |
| | | return request({ |
| | | url: `/api/v1/periodmanagement/periodsetting`, |
| | | method: 'get', |
| | | }) |
| | | }, |
| | | postPeriodConfigs: (data: any) => { |
| | | return request({ |
| | | url: `/api/v1/periodmanagement/periodsetting`, |
| | | method: 'post', |
| | | data, |
| | | }) |
| | | }, |
| | | } |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | export interface IVariables { |
| | | UUID?: string |
| | | displayName: string |
| | | name: string |
| | | value: string |
| | | } |
| | | |
| | | export interface IPeriod { |
| | | name: string |
| | | type: string |
| | | startTime: string |
| | | endTime: string |
| | | } |
| | | |
| | | export interface IPeriodSetting { |
| | | variables: IVariables[] |
| | | periods: IPeriod[] |
| | | } |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | registry=https://registry.npmjs.org/ |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | .barContent { |
| | | width: 100%; |
| | | height: 600px; |
| | | display: flex; |
| | | justify-content: flex-start; |
| | | align-items: flex-start; |
| | | flex-direction: column; |
| | | .barHeader { |
| | | display: flex; |
| | | /* justify-content: space-between; */ |
| | | align-items: center; |
| | | width: 100%; |
| | | margin-bottom: 10px; |
| | | .search { |
| | | margin-left: auto; |
| | | } |
| | | } |
| | | .barSearch { |
| | | width: 300px; |
| | | display: flex; |
| | | justify-content: space-between; |
| | | align-items: center; |
| | | column-gap: 6px; |
| | | .searchBtn { |
| | | color: #fff; |
| | | height: 26px !important; |
| | | } |
| | | } |
| | | .tableContent { |
| | | width: 100%; |
| | | height: calc(100% - 90px); |
| | | .withoutBtn { |
| | | color: #000; |
| | | } |
| | | } |
| | | .add { |
| | | width: 22px; |
| | | height: 22px; |
| | | background-image: url(@/assets/svg/add.svg); |
| | | background-size: 20px 20px; |
| | | background-position: center; |
| | | background-color: #8b9ca4; |
| | | border-radius: 4px; |
| | | margin-right: 2px; |
| | | cursor: pointer; |
| | | } |
| | | } |
| | | |
| | | // .without-picker-popper_content.is-light { |
| | | // background-color: var(--el-color-white) !important; |
| | | // border: 1px solid var(--el-datepicker-border-color) !important; |
| | | // box-shadow: var(--el-box-shadow-light) !important; |
| | | // padding: 0 !important; |
| | | // max-width: inherit !important; |
| | | |
| | | // .cs-popper__arrow:before { |
| | | // background: var(--el-color-white) !important; |
| | | // } |
| | | // } |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | import { defineComponent, ref, computed } from 'vue' |
| | | import BaseTable from '@/components/Table/Table' |
| | | import { |
| | | BarcodeAnalysisColumns, |
| | | BarcodeAnalysisType, |
| | | BarcodeAnalysisRow, |
| | | BarcodeAnalysisCurrent, |
| | | } from '@/widgets/BarcodeManagement/state' |
| | | import dayjs from 'dayjs' |
| | | import Search from '@/components/Search/Search' |
| | | import { ElMessage, ElTooltip } from 'element-plus' |
| | | import { _t } from '@/libs/Language/Language' |
| | | import BaseDialog from '../BaseDialog/BaseDialog' |
| | | import { useVModel } from '@vueuse/core' |
| | | import styles from './BarcodeAnalysisDialog.module.scss' |
| | | |
| | | export default defineComponent({ |
| | | name: 'BarcodeAnalysis', |
| | | props: { |
| | | visible: { |
| | | type: Boolean, |
| | | default: false, |
| | | }, |
| | | selections: { |
| | | type: Array, |
| | | default: () => [], |
| | | }, |
| | | radio: { |
| | | type: Boolean, |
| | | default: false, |
| | | }, |
| | | }, |
| | | emits: ['confirm'], |
| | | setup(props, { emit }) { |
| | | const tableRef = ref() |
| | | const visible = useVModel(props, 'visible', emit) |
| | | const dataSource = ref<BarcodeAnalysisRow[]>([]) |
| | | const searchInner = ref('') |
| | | const checkedList = ref<BarcodeAnalysisRow[]>([]) |
| | | |
| | | const onSearch = () => { |
| | | tableRef.value?.getList() |
| | | tableRef.value?.clearSelectEvent() |
| | | } |
| | | |
| | | const onCheck = (records: BarcodeAnalysisRow[]) => { |
| | | checkedList.value = records |
| | | } |
| | | |
| | | const onConfirm = () => { |
| | | if (checkedList.value.length === 0) { |
| | | ElMessage.warning(_t('è¯·éæ©è§£æè§å')) |
| | | return |
| | | } |
| | | if (checkedList.value.length > 1) { |
| | | ElMessage.warning(_t('è¯·éæ©ä¸æ¡è§£æè§å')) |
| | | return |
| | | } |
| | | console.log(checkedList.value[0], 'checkedList.value[0]') |
| | | emit('confirm', checkedList.value[0]) |
| | | visible.value = false |
| | | } |
| | | |
| | | const onClose = () => { |
| | | visible.value = false |
| | | console.log('onClose') |
| | | } |
| | | return () => |
| | | visible.value ? ( |
| | | <BaseDialog |
| | | title={_t('æ¡ç è§£æè§å')} |
| | | v-model={visible.value} |
| | | width="1200" |
| | | height="800" |
| | | onClose={onClose} |
| | | onConfirm={onConfirm} |
| | | > |
| | | <div class={styles.barContent}> |
| | | <div class={styles.barHeader}> |
| | | <Search |
| | | class={styles.search} |
| | | onConfirm={onSearch} |
| | | placeholder={_t('请è¾å
¥è§£æè§ååç§°')} |
| | | v-model={searchInner.value} |
| | | /> |
| | | </div> |
| | | <div class={styles.tableContent}> |
| | | <BaseTable |
| | | ref={tableRef} |
| | | url="/api/v1/barcodemanagement/barcodeanalysis" |
| | | params={{ Filter: searchInner.value }} |
| | | v-model:dataSource={dataSource.value} |
| | | selections={props.selections} |
| | | columns={BarcodeAnalysisColumns.value} |
| | | isChecked={true} |
| | | isFooter={false} |
| | | radio={props.radio} |
| | | onCheck={onCheck} |
| | | v-slots={{ |
| | | type: ({ row }) => BarcodeAnalysisType[row.type], |
| | | barcodeSegmentComposition: ({ row }) => ( |
| | | <ElTooltip |
| | | effect="dark" |
| | | content={row.barcodeAnalysisDetails |
| | | .map((e: any) => e.name) |
| | | .join('/')} |
| | | placement="top" |
| | | > |
| | | {row.barcodeAnalysisDetails |
| | | .map((e: any) => e.name) |
| | | .join('/')} |
| | | </ElTooltip> |
| | | ), |
| | | ruleByType: ({ row }) => { |
| | | switch (row.type) { |
| | | case 0: |
| | | return row.symbol |
| | | case 1: |
| | | return row.startSymbol + row.endSymbol |
| | | case 2: |
| | | return row.fixedLength |
| | | default: |
| | | return '-' |
| | | } |
| | | }, |
| | | isUsed: ({ row }) => |
| | | row.isUsed ? _t('使ç¨ä¸') : _t('æªä½¿ç¨'), |
| | | lastModificationTime: ({ row }) => |
| | | row.lastModificationTime |
| | | ? dayjs(row.lastModificationTime).format( |
| | | 'YYYY-MM-DD HH:mm:ss' |
| | | ) |
| | | : '-', |
| | | }} |
| | | /> |
| | | </div> |
| | | </div> |
| | | </BaseDialog> |
| | | ) : null |
| | | }, |
| | | }) |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | .relationDialog { |
| | | width: 100%; |
| | | } |
| | | .select { |
| | | font-size: 14px; |
| | | font-family: PingFang SC, PingFang SC; |
| | | font-weight: 400; |
| | | color: #5a84ff; |
| | | cursor: pointer; |
| | | } |
| | | |
| | | .header { |
| | | width: 100%; |
| | | height: 35px; |
| | | display: flex; |
| | | justify-content: flex-start; |
| | | align-items: center; |
| | | margin-bottom: 10px; |
| | | .key { |
| | | font-size: 12px; |
| | | font-family: PingFang SC, PingFang SC; |
| | | font-weight: 400; |
| | | color: #35363b; |
| | | margin-right: 10px; |
| | | } |
| | | } |
| | | .table { |
| | | width: 100%; |
| | | height: calc(100% - 50px); |
| | | } |
| | | .selected { |
| | | cursor: pointer; |
| | | font-size: 14px; |
| | | font-family: PingFang SC, PingFang SC; |
| | | font-weight: 400; |
| | | color: #5a84ff; |
| | | &:hover { |
| | | color: #5a84ff; |
| | | opacity: 0.6; |
| | | } |
| | | } |
| | | |
| | | .selectVariable { |
| | | :global(.cs-input__inner) { |
| | | padding-right: 10px; |
| | | } |
| | | } |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | import Dialog from '@/components/BaseDialog/index.vue' |
| | | const BaseDialog: any = Dialog |
| | | import { defineComponent, SetupContext } from 'vue' |
| | | import styles from './BarcodeGenerateDialog.module.scss' |
| | | import { useRelationGenerate } from '@/hooks/Dialog' |
| | | import Text from '@/components/Text/Text' |
| | | import BaseTable from '@/components/Table/Table' |
| | | |
| | | import Search from '@/components/Search/Search' |
| | | import DyForm from '@/components/DyForm/DyForm' |
| | | import { _t } from '@/libs/Language/Language' |
| | | import dayjs from 'dayjs' |
| | | |
| | | export default defineComponent({ |
| | | name: 'å
³èæ¡ç çæè§å', |
| | | props: { |
| | | // æ§å¶å¼¹çªæ¾ç¤ºéè |
| | | modelValue: { |
| | | type: [Object, Number, String], |
| | | default: () => ({}), |
| | | }, |
| | | visible: { |
| | | type: Boolean, |
| | | default: null, |
| | | }, |
| | | title: { |
| | | type: String, |
| | | default: _t('å
³èæ¡ç çæè§å'), |
| | | }, |
| | | mode: { |
| | | type: String, |
| | | default: 'select', |
| | | }, |
| | | type: { |
| | | type: String, |
| | | default: 'select', |
| | | }, |
| | | ruleType: { |
| | | type: String, |
| | | default: 'barcodegeneration', |
| | | }, |
| | | }, |
| | | emits: ['update:modelValue', 'update:visible', 'close', 'confirm'], |
| | | setup(props, ctx: SetupContext) { |
| | | const { |
| | | visible, |
| | | data, |
| | | modelValue, |
| | | search, |
| | | tableRef, |
| | | columns, |
| | | url, |
| | | formData, |
| | | barcodeVisible, |
| | | formRef, |
| | | onBarcodeConfirm, |
| | | onClose, |
| | | onConfirm, |
| | | onSelect, |
| | | onRowClick, |
| | | onSearch, |
| | | } = useRelationGenerate(props, ctx) |
| | | return () => { |
| | | const { description } = modelValue.value |
| | | return ( |
| | | <div class={styles.relationDialog}> |
| | | {props.type === 'select' ? ( |
| | | <el-input |
| | | modelValue={formData.value.input} |
| | | {...ctx.attrs} |
| | | class={styles.selectVariable} |
| | | placeholder={_t('è¯·éæ©')} |
| | | suffix-icon={ |
| | | <el-button |
| | | link |
| | | type="primary" |
| | | size="small" |
| | | style="margin-right: 10px;" |
| | | onClick={onSelect} |
| | | > |
| | | {_t('éæ©')} |
| | | </el-button> |
| | | } |
| | | ></el-input> |
| | | ) : null} |
| | | {props.mode === 'select' && |
| | | (description ? ( |
| | | <span class={styles.selected} onClick={onSelect}> |
| | | {description} |
| | | </span> |
| | | ) : ( |
| | | <span onClick={onSelect} class={styles.select}> |
| | | {_t('è¯·éæ©')} |
| | | </span> |
| | | ))} |
| | | <BaseDialog |
| | | width="400px" |
| | | destroy-on-close |
| | | append-to-body={true} |
| | | v-model={visible.value} |
| | | title={_t(props.title)} |
| | | onClose={onClose} |
| | | onConfirm={onConfirm} |
| | | > |
| | | <div class={styles.table}> |
| | | <DyForm |
| | | v-model:formData={formData.value} |
| | | ref={formRef} |
| | | formItemProps={[ |
| | | { |
| | | prop: 'barcode', |
| | | label: _t('çæè§å'), |
| | | placeholder: _t('è¯·éæ©'), |
| | | el: 'input', |
| | | suffixIcon: ( |
| | | <el-button |
| | | link |
| | | type="primary" |
| | | size="small" |
| | | style="margin-right: 10px;" |
| | | onClick={() => (barcodeVisible.value = true)} |
| | | > |
| | | {_t('éæ©')} |
| | | </el-button> |
| | | ), |
| | | rules: [ |
| | | { |
| | | message: 'è¯·éæ©çæè§å', |
| | | required: true, |
| | | trigger: 'change', |
| | | }, |
| | | ], |
| | | }, |
| | | { |
| | | prop: 'dataVariable', |
| | | label: _t('ä¸ååé'), |
| | | el: 'variable', |
| | | placeholder: _t('è¯·éæ©'), |
| | | type: 'select', |
| | | }, |
| | | ]} |
| | | /> |
| | | </div> |
| | | </BaseDialog> |
| | | <BaseDialog |
| | | width="954px" |
| | | height="536px" |
| | | destroy-on-close |
| | | append-to-body={true} |
| | | v-model={barcodeVisible.value} |
| | | title={_t(props.title)} |
| | | onClose={() => (barcodeVisible.value = false)} |
| | | onConfirm={onBarcodeConfirm} |
| | | > |
| | | <div class={styles.header}> |
| | | <label class={styles.key}>{_t('æ¡ç åç§°')}</label> |
| | | <Search v-model={search.value} onConfirm={onSearch} /> |
| | | </div> |
| | | <div class={styles.table}> |
| | | <BaseTable |
| | | ref={tableRef} |
| | | url={url.value} |
| | | columns={columns.value} |
| | | size="mini" |
| | | v-model:dataSource={data.value} |
| | | isHidePagination={true} |
| | | pageSize={999} |
| | | isVScroll |
| | | onRowClick={onRowClick} |
| | | v-slots={{ |
| | | lastModificationTime: ({ row }: any) => ( |
| | | <Text |
| | | tip={dayjs(row.lastModificationTime).format( |
| | | 'YYYY-MM-DD HH:MM:ss' |
| | | )} |
| | | > |
| | | {dayjs(row.lastModificationTime).format( |
| | | 'YYYY-MM-DD HH:MM:ss' |
| | | )} |
| | | </Text> |
| | | ), |
| | | }} |
| | | /> |
| | | </div> |
| | | </BaseDialog> |
| | | </div> |
| | | ) |
| | | } |
| | | }, |
| | | }) |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | import { defineComponent } from 'vue' |
| | | |
| | | export default defineComponent({ |
| | | setup(props, { attrs, slots }) { |
| | | const namespace = import.meta.env.VITE_APP_NAMESPACE |
| | | |
| | | return () => { |
| | | return ( |
| | | <el-config-provider {...attrs} namespace={namespace}> |
| | | {slots.default?.()} |
| | | </el-config-provider> |
| | | ) |
| | | } |
| | | }, |
| | | }) |
| | |
| | | height: 100%; |
| | | border: 1px solid #dbdbdb; |
| | | font-family: PingFang SC, PingFang SC; |
| | | padding: 0 12px; |
| | | // padding: 0 12px; |
| | | position: relative; |
| | | overflow: hidden; |
| | | |
| | | .title { |
| | | font-size: 16px; |
| | |
| | | position: absolute; |
| | | bottom: 0; |
| | | left: 0; |
| | | background-color: #fff; |
| | | z-index: 0; |
| | | } |
| | | } |
| | | .content { |
| | | padding: 15px 20px 0; |
| | | height: calc(100% - 46px); |
| | | .scrollContent { |
| | | height: calc(100% - 94px); |
| | | box-sizing: border-box; |
| | | background: #fff; |
| | | overflow: hidden; |
| | | // padding: 0 12px; |
| | | // padding-right: 4px; |
| | | } |
| | | .content { |
| | | height: auto; |
| | | background: #f7f8fa; |
| | | border-radius: 5px 5px 5px 5px; |
| | | padding: 14px 14px 20px 14px; |
| | | border-radius: 5px 5px 5px 5px; |
| | | |
| | | .header { |
| | | margin-bottom: 12px; |
| | |
| | | type: String, |
| | | default: '', |
| | | }, |
| | | customClass: { |
| | | type: String, |
| | | default: '', |
| | | }, |
| | | }, |
| | | setup(props, { slots }) { |
| | | setup(props, { slots, attrs }) { |
| | | return () => ( |
| | | <div class={styles.container}> |
| | | <div class={styles.header}> |
| | | <Icon width={22} height={22} icon={props.icon} /> |
| | | <div class={styles.title}>{props.title}</div> |
| | | </div> |
| | | <div class={styles.content}>{slots.default?.()}</div> |
| | | <div class={styles.scrollContent}> |
| | | <div class={[styles.content, props.customClass]}> |
| | | {slots.default?.()} |
| | | </div> |
| | | </div> |
| | | <footer class={styles.footer}>{slots.footer?.()}</footer> |
| | | </div> |
| | | ) |
| | |
| | | .cs-dialog__footer { |
| | | padding: 0; |
| | | padding-top: 10px; |
| | | padding-bottom: 10px; |
| | | } |
| | | .cs-dialog-footer { |
| | | padding: 0 18px; |
| | | padding-bottom: 10px; |
| | | |
| | | .cs-base-btn { |
| | | width: 98px; |
| | | height: 26px; |
| | |
| | | .cs-dialog__footer { |
| | | padding: 0; |
| | | padding-top: 10px; |
| | | padding-bottom: 10px; |
| | | } |
| | | .cs-dialog-footer { |
| | | padding: 0 18px; |
| | | padding-bottom: 10px; |
| | | |
| | | .cs-base-btn { |
| | | width: 98px; |
| | | height: 26px; |
| | |
| | | import { computed, defineComponent, onMounted, ref } from 'vue' |
| | | import { Component, computed, defineComponent, onMounted, ref } from 'vue' |
| | | import styles from './BaseDrawer.module.scss' |
| | | import Icon from '../Icon/Icon' |
| | | import { _t } from '@/libs/Language/Language' |
| | | |
| | | //@ts-ignore |
| | | export default defineComponent<{ |
| | | [key: string]: any |
| | |
| | | type: String, |
| | | default: '', |
| | | }, |
| | | submitDisabled: { |
| | | type: Boolean, |
| | | default: false, |
| | | }, |
| | | appendToBody: { |
| | | type: Boolean, |
| | | default: true, |
| | | }, |
| | | |
| | | // modelValue: { |
| | | // type: Boolean, |
| | | // default: false, |
| | |
| | | // }) |
| | | |
| | | return () => { |
| | | const vSlots: { |
| | | footer: () => Component |
| | | title?: () => Component |
| | | } = { |
| | | footer() { |
| | | return ( |
| | | <div class={styles.csDialogFooter}> |
| | | <el-button |
| | | onClick={() => emit('close')} |
| | | type="info" |
| | | plain |
| | | class={{ |
| | | [styles.dialogBtn]: true, |
| | | [styles.csBaseBtn]: true, |
| | | }} |
| | | > |
| | | {_t('åæ¶')} |
| | | </el-button> |
| | | <el-button |
| | | onClick={() => emit('confirm')} |
| | | type="primary" |
| | | disabled={props.submitDisabled} |
| | | class={{ |
| | | [styles.csBaseBtn]: true, |
| | | }} |
| | | > |
| | | {_t('确认')} |
| | | </el-button> |
| | | </div> |
| | | ) |
| | | }, |
| | | } |
| | | if (slots.title) { |
| | | vSlots.title = () => { |
| | | return slots.title?.() |
| | | } |
| | | } |
| | | return ( |
| | | <div |
| | | class={styles.drawContent} |
| | |
| | | }} |
| | | onOpen={() => emit('open')} |
| | | onClose={() => emit('close')} |
| | | v-slots={{ |
| | | footer() { |
| | | return ( |
| | | <div class={styles.csDialogFooter}> |
| | | <el-button |
| | | onClick={() => emit('close')} |
| | | type="info" |
| | | plain |
| | | class={{ |
| | | [styles.dialogBtn]: true, |
| | | [styles.csBaseBtn]: true, |
| | | }} |
| | | > |
| | | åæ¶ |
| | | </el-button> |
| | | <el-button |
| | | onClick={() => emit('confirm')} |
| | | type="primary" |
| | | class={{ |
| | | [styles.csBaseBtn]: true, |
| | | }} |
| | | > |
| | | 确认 |
| | | </el-button> |
| | | </div> |
| | | ) |
| | | }, |
| | | }} |
| | | v-slots={vSlots} |
| | | append-to-body={props.appendToBody} |
| | | {...attrs} |
| | | title={props.title} |
| | | size={props.width || attrs.size} |
| | |
| | | display: flex; |
| | | justify-content: flex-start; |
| | | align-items: center; |
| | | |
| | | .input { |
| | | border-radius: 4px; |
| | | padding: 0 6px; |
| | | height: calc(100% - 6px); |
| | | border: 1px solid transparent; |
| | | padding: 0 6px; |
| | | transition: all 0.1s ease-in; |
| | | &:focus { |
| | | border: 1px solid #5a84ff; |
| | | } |
| | | } |
| | | } |
| | | |
| | | :global( |
| | | .arco-table-hover:not(.arco-table-dragging) |
| | | .arco-table-tr:not(.arco-table-tr-empty):not(.arco-table-tr-summary):hover |
| | | .arco-table-td:not(.arco-table-col-fixed-left):not( |
| | | .arco-table-col-fixed-right |
| | | ) |
| | | ) { |
| | | .hover { |
| | | display: block; |
| | | } |
| | | .hasHover { |
| | | // display: none; |
| | | } |
| | | .baseInput { |
| | | .input { |
| | | border-radius: 4px; |
| | | padding: 0 6px; |
| | | background: #fff; |
| | | border: 1px solid #d9d9d9; |
| | | &:focus { |
| | | border: 1px solid #5a84ff; |
| | | } |
| | | } |
| | | } |
| | | } |
| | | :global(.arco-table) { |
| | | .baseInput { |
| | | .input { |
| | | height: 30px; |
| | | } |
| | | } |
| | | } |
| | | |
| | | :global(.information-table) { |
| | |
| | | .hasHover { |
| | | // display: none; |
| | | } |
| | | .baseInput { |
| | | .input { |
| | | border-radius: 4px; |
| | | padding: 0 6px; |
| | | background: #fff; |
| | | height: calc(100% - 6px); |
| | | border: 1px solid #d9d9d9; |
| | | &:focus { |
| | | border: 1px solid #5a84ff; |
| | | } |
| | | } |
| | | } |
| | | } |
| | |
| | | import { defineComponent, SetupContext, ref, computed } from 'vue' |
| | | import styles from './BaseInput.module.scss' |
| | | import { getScopeT, Language } from '@/libs/Language/Language' |
| | | |
| | | export default defineComponent({ |
| | | name: 'BaseInput', |
| | | emits: ['update:modelValue', 'click'], |
| | | emits: ['update:modelValue', 'click', 'change', 'enter'], |
| | | props: { |
| | | modelValue: { |
| | | type: [String, Number], |
| | |
| | | type: String, |
| | | default: '请è¾å
¥', |
| | | }, |
| | | readOnly: { |
| | | type: Boolean, |
| | | default: false, |
| | | }, |
| | | LanguageScopeKey: { |
| | | type: String, |
| | | default: '', |
| | | }, |
| | | onChange: { |
| | | type: Function, |
| | | }, |
| | | onEnter: { |
| | | type: Function, |
| | | }, |
| | | }, |
| | | setup(props, { attrs, slots, emit }: SetupContext) { |
| | | const _t = getScopeT(props.LanguageScopeKey) |
| | | |
| | | const input = computed({ |
| | | get() { |
| | | return props.modelValue |
| | |
| | | evt?.stopPropagation() |
| | | emit('click', evt) |
| | | } |
| | | const onKeypress = (event: KeyboardEvent) => { |
| | | if (event.keyCode === 13) { |
| | | emit('enter') |
| | | } |
| | | } |
| | | return () => { |
| | | return ( |
| | | <div class={styles.baseInput} onClick={onClick}> |
| | | <input |
| | | placeholder={props.placeholder} |
| | | {...attrs} |
| | | placeholder={_t(props.placeholder)} |
| | | class={{ |
| | | [styles.input]: true, |
| | | [styles.hover]: true, |
| | | }} |
| | | v-model={input.value} |
| | | onInput={() => emit('change')} |
| | | onKeypress={onKeypress} |
| | | /> |
| | | {/* <span class={styles.hasHover}> |
| | | {input.value ? ( |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | /** |
| | | * @author: zhengbolin |
| | | * |
| | | * AutoTooltip ç»ä»¶ - ç¨äºèªå¨å¤æææ¬æ¯å¦æº¢åºï¼å¹¶å¨æº¢åºæ¶å±ç¤ºå·¥å
·æç¤ºã |
| | | * |
| | | * åçï¼ |
| | | * 该ç»ä»¶éè¿æ£æµææ¬å®¹å¨ç `scrollWidth` å `clientWidth` æ¥å¤æææ¬æ¯å¦æº¢åºï¼ |
| | | * å¦ææº¢åºï¼åä½¿ç¨ Arco Design ç `Tooltip` ç»ä»¶æ¥å±ç¤ºå·¥å
·æç¤ºã |
| | | * |
| | | * ä½¿ç¨ææ¡£ï¼ |
| | | * 1. ä¼ å
¥ `text` 屿§ï¼ç»ä»¶ä¼å¤æè¯¥ææ¬æ¯å¦æº¢åºï¼ |
| | | * 2. è¥ææ¬æº¢åºï¼æ¾ç¤ºå·¥å
·æç¤ºï¼è¥ä¸æº¢åºï¼ç´æ¥å±ç¤ºææ¬ï¼ |
| | | * 3. å¨çªå£å¤§å°ååæ¶èªå¨éæ°è®¡ç®ææ¬æ¯å¦æº¢åºã |
| | | * |
| | | */ |
| | | import { defineComponent, ref, onMounted, onBeforeUnmount } from 'vue' |
| | | import { Tooltip } from '@arco-design/web-vue' |
| | | |
| | | interface AutoTooltipProps { |
| | | text: string // è¦å±ç¤ºçææ¬å
容 |
| | | } |
| | | |
| | | const AutoTooltip = defineComponent({ |
| | | name: 'AutoTooltip', |
| | | |
| | | props: { |
| | | text: { |
| | | type: String, |
| | | required: true |
| | | } |
| | | }, |
| | | |
| | | setup(props: AutoTooltipProps) { |
| | | const containerRef = ref<HTMLElement | null>(null) // å¼ç¨å®¹å¨å
ç´ |
| | | const isOverflow = ref(false) |
| | | |
| | | // æ£æ¥ææ¬æ¯å¦æº¢åº |
| | | const checkOverflow = () => { |
| | | if (containerRef.value) { |
| | | isOverflow.value = containerRef.value.scrollWidth > containerRef.value.clientWidth |
| | | } |
| | | } |
| | | |
| | | // å¨ç»ä»¶æè½½åè¿è¡ä¸æ¬¡æº¢åºæ£æ¥ï¼å¹¶çå¬çªå£ç resize äºä»¶ |
| | | onMounted(() => { |
| | | checkOverflow() |
| | | window.addEventListener('resize', checkOverflow) |
| | | }) |
| | | |
| | | // å¨ç»ä»¶å¸è½½åæ¸
é¤äºä»¶çå¬å¨ |
| | | onBeforeUnmount(() => { |
| | | window.removeEventListener('resize', checkOverflow) |
| | | }) |
| | | |
| | | // 渲æå½æ° |
| | | return () => ( |
| | | <div |
| | | ref={containerRef} |
| | | style={{ |
| | | display: 'inline-block', // 设置容å¨ä¸ºè¡å
å级å
ç´ |
| | | maxWidth: '100%', // æå¤§å®½åº¦ä¸º 100% |
| | | whiteSpace: 'nowrap', // 鲿¢ææ¬æ¢è¡ |
| | | overflow: 'hidden', // è¶
åºçææ¬éè |
| | | textOverflow: 'ellipsis', // 使ç¨çç¥å·è¡¨ç¤ºæº¢åºçææ¬ |
| | | }} |
| | | > |
| | | {isOverflow.value ? ( |
| | | // å¦ææº¢åºï¼ä½¿ç¨ Tooltip å±ç¤ºæº¢åºçå
容 |
| | | <Tooltip content={props.text}> |
| | | <span>{props.text}</span> |
| | | </Tooltip> |
| | | ) : ( |
| | | // å¦åç´æ¥å±ç¤ºææ¬ |
| | | <span>{props.text}</span> |
| | | )} |
| | | </div> |
| | | ) |
| | | }, |
| | | }) |
| | | |
| | | export default AutoTooltip |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | import { TableData, ClassName } from '@arco-design/web-vue' |
| | | import { CSSProperties } from 'vue' |
| | | export interface ParamsItem { |
| | | Sorting?: string |
| | | SkipCount?: string | number |
| | | MaxResultCount?: number |
| | | [key: string]: any |
| | | } |
| | | |
| | | export interface ColumnType { |
| | | title?: string |
| | | field: string |
| | | width?: string | number |
| | | sortable?: boolean |
| | | required?: boolean |
| | | type?: string |
| | | cellStyle?: ((record: TableData) => ClassName) | CSSProperties |
| | | [key: string]: any |
| | | } |
| | | |
| | | export interface TablePropsItemType { |
| | | cellStyle?: Function |
| | | rowStyle?: () => any |
| | | rowClassName?: string | Function |
| | | headBorder?: boolean |
| | | emptyText?: string |
| | | selections?: string[] |
| | | autoFirstClickRow?: boolean |
| | | // åæ° |
| | | params?: ParamsItem |
| | | // æ°æ®æº |
| | | dataSource: any[] |
| | | // å |
| | | columns: ColumnType[] |
| | | // å½åé¡µå¤§å° |
| | | pageSize?: number |
| | | // æ»æ° |
| | | total?: number |
| | | // æ¯å¦éèå页 |
| | | isHidePagination?: boolean |
| | | // æ¯å¦å¤é |
| | | isChecked?: boolean | Function |
| | | // æ¯å¦æ¾ç¤ºåºå· |
| | | isSeq?: boolean |
| | | // æ¯å¦æåº |
| | | isSort?: boolean |
| | | // id.. |
| | | id?: string |
| | | // æ¯å¦åºç°ææ½ï¼åºå¼ |
| | | showDarg?: boolean | string |
| | | // æ¯å¦ææ½ |
| | | isDrag?: boolean | string |
| | | // æ¯å¦ç¦ç¨ææ½ ï¼çéçæ¶åä¸è¬ç¦ç¨ææ½ï¼ |
| | | disabledDrag?: boolean |
| | | // æ¯å¦èªå¨é«åº¦ |
| | | height?: string |
| | | maxHeight?: string |
| | | // æ¯å¦å¼å¯èææ»å¨ |
| | | isVScroll?: boolean |
| | | // è¾¹æ¡ |
| | | border?: string | any |
| | | // 请æ±å°å |
| | | url?: string |
| | | // æåºå°å模ç |
| | | sortUrlTpl?: string |
| | | //æ¾ç¤ºåºé¨ |
| | | isFooter?: boolean |
| | | gt?: number |
| | | // å³é®èå |
| | | contextMenu?: Array<{ |
| | | label: string |
| | | fn: (item: any) => void |
| | | [key: string]: any |
| | | }> |
| | | rowConfig?: any |
| | | size?: SizeType | undefined |
| | | // 黿¢å泡 |
| | | isStop?: boolean |
| | | LanguageScopeKey?: string |
| | | style?: CSSProperties |
| | | hightLightRow?: string |
| | | columnResizable?: boolean |
| | | columnResize?: Function |
| | | // [key: string]: any |
| | | } |
| | | |
| | | export interface MenuOptionType { |
| | | zIndex?: number |
| | | minWidth?: number |
| | | x?: number |
| | | y?: number |
| | | } |
| | | |
| | | export interface contextMenuItemType { |
| | | show: boolean |
| | | current: Record<string, any> | null |
| | | options: any |
| | | } |
| | | |
| | | export interface ScopeType { |
| | | rowIndex: number |
| | | record: Record<string, TableData> |
| | | column: ColumnType |
| | | } |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | .baseTable { |
| | | width: 100%; |
| | | height: 100%; |
| | | min-height: 100px; |
| | | --color-neutral-2: #dbdfe7; |
| | | --base-row-background: #e6f7ff; |
| | | // :global(.arco-table-th) { |
| | | // background-color: var(--color-neutral-2); |
| | | // } |
| | | // background-color: red; |
| | | .baseTableRow { |
| | | :global(.arco-table-td) { |
| | | background-color: var(--base-row-background); |
| | | } |
| | | } |
| | | :global(.arco-table .arco-table-body .arco-table-cell) { |
| | | padding: 0; |
| | | height: 42px; |
| | | } |
| | | .nullData { |
| | | width: 100%; |
| | | height: 23px; |
| | | display: flex; |
| | | justify-content: center; |
| | | align-content: center; |
| | | color: rgb(96, 98, 102); |
| | | font-size: 13px; |
| | | } |
| | | .bodyCell { |
| | | padding: 0 16px; |
| | | height: 42px; |
| | | display: flex; |
| | | align-items: center; |
| | | } |
| | | } |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | import { ConfigProvider } from '@arco-design/web-vue' |
| | | import { |
| | | defineComponent, |
| | | DefineComponent, |
| | | PropType, |
| | | reactive, |
| | | defineProps, |
| | | inject, |
| | | SetupContext, |
| | | computed, |
| | | onMounted, |
| | | } from 'vue' |
| | | import { TablePropsItemType } from './BaseTable.d' |
| | | import { useVModels } from '@vueuse/core' |
| | | import { tableEmits, tableProps } from './Props' |
| | | import { _t, getScopeT, globalT } from '@/libs/Language/Language' |
| | | import { useUtils } from './useUtils' |
| | | import styles from './BaseTable.module.scss' |
| | | import { ColumnSlots } from './useColumns' |
| | | import { useEvent } from './useEvent' |
| | | import { createState } from './useState' |
| | | import { useHook } from './useHook' |
| | | import { debounce } from 'lodash' |
| | | |
| | | const PropsDefineWrapper = { |
| | | ...tableProps, |
| | | ...tableEmits, |
| | | } as const |
| | | const emits = Object.keys(tableEmits).map((eventName: string) => { |
| | | const name = eventName.split('on')?.[1] |
| | | return name.replace(name[0], name[0].toLowerCase()) |
| | | }) |
| | | type BaseTablePropsDefine = DefineComponent<typeof PropsDefineWrapper> |
| | | |
| | | const BaseTable: BaseTablePropsDefine = defineComponent({ |
| | | name: 'BaseTable', |
| | | props: tableProps, |
| | | emits, |
| | | setup(props, ctx: SetupContext) { |
| | | const { columns, columnSeq, dataSource, rowId, baseTableRef } = createState( |
| | | props, |
| | | ctx |
| | | ) |
| | | const events = useEvent(props, ctx) |
| | | const { getRowClassName, getTableStyle, autoHeight } = useHook(props, ctx) |
| | | const slots = ColumnSlots(props, columns) |
| | | const slotMap = { |
| | | ...columnSeq.value, |
| | | ...slots, |
| | | empty: () => { |
| | | return <div class={styles.nullData}>{_t('ææ æ°æ®')}</div> |
| | | }, |
| | | } |
| | | return () => { |
| | | const style = getTableStyle() |
| | | |
| | | return ( |
| | | <div class={styles.baseTable} style={style} ref={baseTableRef}> |
| | | <a-table |
| | | {...props} |
| | | columns={columns.value} |
| | | data={dataSource.value} |
| | | rowKey={rowId.value} |
| | | bordered={{ wrapper: true, cell: true }} |
| | | pagination={!props.isHidePagination} |
| | | v-slots={slotMap} |
| | | row-class={getRowClassName} |
| | | columnResizable={props.columnResizable} |
| | | headerCellClass="selector-ignore" |
| | | scroll={{ x: props.width, y: autoHeight.value }} |
| | | virtual-list-props={ |
| | | props.isVScroll ? { height: '100%' } : undefined |
| | | } |
| | | {...events} |
| | | ></a-table> |
| | | </div> |
| | | ) |
| | | } |
| | | }, |
| | | }) |
| | | export default BaseTable |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | import { CSSProperties, PropType } from 'vue' |
| | | import { TablePropsItemType } from './BaseTable.d' |
| | | |
| | | export const tableProps = { |
| | | columns: { |
| | | type: Array as PropType<TablePropsItemType['columns']>, |
| | | default: () => [], |
| | | }, |
| | | dataSource: { |
| | | type: Array as PropType<TablePropsItemType['dataSource']>, |
| | | default: () => [], |
| | | }, |
| | | LanguageScopeKey: { |
| | | type: String as PropType<TablePropsItemType['LanguageScopeKey']>, |
| | | default: '', |
| | | }, |
| | | id: { |
| | | type: String as PropType<TablePropsItemType['id']>, |
| | | default: 'id', |
| | | }, |
| | | isSeq: { |
| | | type: Boolean as PropType<TablePropsItemType['isSeq']>, |
| | | default: true, |
| | | }, |
| | | isHidePagination: { |
| | | type: Boolean as PropType<TablePropsItemType['isHidePagination']>, |
| | | default: false, |
| | | }, |
| | | cellStyle: { |
| | | type: [Function, Object] as [ |
| | | PropType<TablePropsItemType['cellStyle']>, |
| | | any |
| | | ], |
| | | }, |
| | | hightLightRow: { |
| | | type: String, |
| | | default: '', |
| | | }, |
| | | style: { |
| | | type: Object, |
| | | default: () => {}, |
| | | }, |
| | | columnResizable: { |
| | | type: Boolean as PropType<TablePropsItemType['columnResizable']>, |
| | | default: false, |
| | | }, |
| | | /** |
| | | * 宽度 |
| | | */ |
| | | width: { |
| | | type: Number, |
| | | }, |
| | | isVScroll: { |
| | | type: Boolean as PropType<TablePropsItemType['isVScroll']>, |
| | | default: false, |
| | | }, |
| | | } as const |
| | | |
| | | export const tableEmits = { |
| | | onColumnResize: Function, |
| | | onRowClick: Function, |
| | | } |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | import { defineComponent, PropType, Ref } from 'vue' |
| | | import { ColumnType, ScopeType, TablePropsItemType } from './BaseTable.d' |
| | | import styles from './BaseTable.module.scss' |
| | | import { isFunction, isNil } from 'lodash' |
| | | import AutoTooltip from './AutoTooltip' |
| | | |
| | | export const ColumnSlots: ( |
| | | props: TablePropsItemType, |
| | | columns: Ref<ColumnType[]> |
| | | ) => Record<string, Function> = (props, columns: Ref<ColumnType[]>) => { |
| | | const slots: Record<string, Function> = {} |
| | | const columnsData = columns.value.filter((column) => column.field !== 'seq') |
| | | const getCellStyle = (data: ScopeType) => |
| | | isFunction(props.cellStyle) |
| | | ? props.cellStyle({ ...data, row: data.record }) |
| | | : {} |
| | | |
| | | const RenderSlot = ({ column, record, rowIndex }: ScopeType) => { |
| | | const cellStyle = getCellStyle({ column, record, rowIndex }) |
| | | const text = isNil(record[column.field]) ? '-' : record[column.field] |
| | | const render = column.customRender ? column.customRender : () => <AutoTooltip text={text as string}/> |
| | | |
| | | return ( |
| | | <div class={styles.bodyCell} style={cellStyle}> |
| | | {render({ column, record, rowIndex })} |
| | | </div> |
| | | ) |
| | | } |
| | | /** |
| | | * èªå®ä¹å |
| | | */ |
| | | columnsData.map((column) => { |
| | | slots[column.field] = RenderSlot |
| | | // if (isFunction(column.customRender)) { |
| | | |
| | | // // slots[column.field] = ({ column, record, rowIndex }: ScopeType) => { |
| | | // // const cellStyle = getCellStyle({ column, record, rowIndex }) |
| | | // // return ( |
| | | // // <div class={styles.bodyCell} style={cellStyle}> |
| | | // // {render({ column, record, rowIndex })} |
| | | // // </div> |
| | | // // ) |
| | | // // } |
| | | // delete column.customRender |
| | | // } else { |
| | | // slots[column.field] = ({ column, record, rowIndex }: ScopeType) => { |
| | | // const cellStyle = getCellStyle({ column, record, rowIndex }) |
| | | |
| | | // return ( |
| | | // <div class={styles.bodyCell} style={cellStyle}> |
| | | // {isNil(record[column.field]) ? '-' : record[column.field]} |
| | | // </div> |
| | | // ) |
| | | // } |
| | | // } |
| | | }) |
| | | return slots |
| | | } |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | import { TableData } from '@arco-design/web-vue' |
| | | import { debounce } from 'lodash' |
| | | import { onMounted, SetupContext } from 'vue' |
| | | import { TablePropsItemType } from './BaseTable.d' |
| | | import { useHook } from './useHook' |
| | | import { injectState } from './useState' |
| | | // import { currentRow } from './useState' |
| | | |
| | | export const useEvent = (props: TablePropsItemType, ctx: SetupContext) => { |
| | | const { emit } = ctx |
| | | // const { boxRef, isResize } = injectState() |
| | | const onRowClick = (record: TableData) => { |
| | | // currentRow.value = record |
| | | } |
| | | const onColumnResize = debounce((dataIndex: string, width: number) => { |
| | | emit('columnResize', dataIndex, width) |
| | | }, 200) |
| | | |
| | | // onMounted(() => { |
| | | // boxRef.value?.addEventListener('mousedown', (event: MouseEvent) => { |
| | | // if (isResize.value) { |
| | | |
| | | // } |
| | | // }) |
| | | // boxRef.value?.addEventListener('mouseup', (event: MouseEvent) => { |
| | | // isResize.value = false |
| | | // }) |
| | | // }) |
| | | |
| | | return { |
| | | onRowClick, |
| | | onColumnResize, |
| | | } |
| | | } |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | import { TableData } from '@arco-design/web-vue' |
| | | import { computed, nextTick, onMounted, SetupContext } from 'vue' |
| | | import styles from './BaseTable.module.scss' |
| | | import { injectState } from './useState' |
| | | import { ColumnType, ScopeType, TablePropsItemType } from './BaseTable.d' |
| | | import { debounce, isFunction } from 'lodash' |
| | | |
| | | export const useHook = (props: TablePropsItemType, ctx: SetupContext) => { |
| | | const { currentRow, dataSource, rowId, currentHeight, baseTableRef } = |
| | | injectState() |
| | | |
| | | /** |
| | | * è·åè¡çæ ·å¼åç§° |
| | | * @param record |
| | | * @param rowIndex |
| | | * @returns |
| | | */ |
| | | const getRowClassName = (record: TableData, rowIndex: number) => { |
| | | if (record === currentRow.value) { |
| | | return styles.baseTableRow |
| | | } |
| | | } |
| | | /** |
| | | * è·åstyle |
| | | */ |
| | | const getTableStyle = () => { |
| | | return { |
| | | ...props.style, |
| | | '--base-row-background': props.hightLightRow, |
| | | } |
| | | } |
| | | /** |
| | | * 设置å½åè¡é«äº® |
| | | * @param key id |
| | | */ |
| | | const setCurrentRow = (key: string) => { |
| | | const row = dataSource.value.find((item) => item[rowId.value] === key) |
| | | if (row) { |
| | | currentRow.value = row |
| | | } |
| | | } |
| | | |
| | | onMounted(() => { |
| | | if (baseTableRef.value) { |
| | | const fn = debounce((entries: any) => { |
| | | const entry = entries[0] |
| | | const borderBoxSize = entry.borderBoxSize[0] || {} |
| | | currentHeight.value = borderBoxSize.blockSize |
| | | }, 150) |
| | | const resizeObserver = new ResizeObserver(fn) |
| | | resizeObserver.observe(baseTableRef.value) |
| | | } |
| | | }) |
| | | |
| | | const autoHeight = computed(() => { |
| | | const height = currentHeight.value |
| | | if (baseTableRef.value) { |
| | | const rect = baseTableRef.value.getBoundingClientRect() |
| | | const rectHeight = height || rect.height |
| | | return rectHeight > 42 ? rectHeight - 42 : rectHeight |
| | | } |
| | | }) |
| | | |
| | | ctx.expose({ |
| | | setCurrentRow, |
| | | }) |
| | | return { |
| | | getRowClassName, |
| | | getTableStyle, |
| | | autoHeight, |
| | | } |
| | | } |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | import { TableData } from '@arco-design/web-vue' |
| | | import { useVModels } from '@vueuse/core' |
| | | import { computed, inject, provide, ref, SetupContext } from 'vue' |
| | | import { useUtils } from './useUtils' |
| | | import { TablePropsItemType } from './BaseTable.d' |
| | | |
| | | const KEY = Symbol('BaseTable') |
| | | |
| | | const useStore = (props: TablePropsItemType, ctx: SetupContext) => { |
| | | const currentRow = ref<TableData>() |
| | | |
| | | const { dataSource } = useVModels(props, ctx.emit) |
| | | const { columns, columnSeq } = useUtils(props, ctx) |
| | | const rowId = computed(() => props.id || 'id') |
| | | const baseTableRef = ref() |
| | | const currentHeight = ref<number>(0) |
| | | |
| | | const store = { |
| | | currentRow, |
| | | dataSource, |
| | | columns, |
| | | columnSeq, |
| | | rowId, |
| | | baseTableRef, |
| | | currentHeight, |
| | | } |
| | | return store |
| | | } |
| | | |
| | | export type StoreType = ReturnType<typeof useStore> |
| | | |
| | | let store = {} |
| | | |
| | | export const createState = (props: TablePropsItemType, ctx: SetupContext) => { |
| | | store = useStore(props, ctx) |
| | | provide(KEY, store) |
| | | return store as StoreType |
| | | } |
| | | |
| | | export const injectState = () => { |
| | | const injectStore = inject(KEY, '') |
| | | if (!injectStore) { |
| | | return store as StoreType |
| | | } |
| | | return inject(KEY) as StoreType |
| | | } |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | import { getScopeT, globalT } from '@/libs/Language/Language' |
| | | import { computed, h, inject, SetupContext } from 'vue' |
| | | import { ScopeType, TablePropsItemType } from './BaseTable.d' |
| | | import styles from './BaseTable.module.scss' |
| | | import { useVModels } from '@vueuse/core' |
| | | import { TableData } from '@arco-design/web-vue' |
| | | import { isFunction } from 'lodash' |
| | | |
| | | export const useUtils = (props: TablePropsItemType, { emit }: SetupContext) => { |
| | | const LanguageScopeKey = |
| | | props.LanguageScopeKey || inject('LanguageScopeKey', '') |
| | | const _t = LanguageScopeKey ? getScopeT(LanguageScopeKey) : globalT |
| | | |
| | | const getCellStyle = (data: ScopeType) => |
| | | isFunction(props.cellStyle) |
| | | ? props.cellStyle({ ...data, row: data.record }) |
| | | : {} |
| | | |
| | | const columns = computed(() => { |
| | | return props.columns.map((item) => { |
| | | const render = item.render |
| | | delete item.render |
| | | const column = { |
| | | tooltip: true, |
| | | ellipsis: true, |
| | | ...item, |
| | | // èªå®ä¹render |
| | | customRender: render, |
| | | title: _t(item.title), |
| | | dataIndex: item.field, |
| | | slotName: item.field || item.slotName, |
| | | headerCellClass: 'selector-ignore', |
| | | width: item.width ? parseInt(String(item.width)) : item.width, |
| | | } |
| | | return column |
| | | }) |
| | | }) |
| | | /** |
| | | * 设置åºå· |
| | | */ |
| | | const columnSeq = computed(() => { |
| | | const seq = columns.value.find((column) => column.type === 'seq') |
| | | if (seq && props.isSeq) { |
| | | return { |
| | | ...seq, |
| | | seq: ({ column, record, rowIndex }: TableData) => { |
| | | const cellStyle = getCellStyle({ column, record, rowIndex }) |
| | | return h( |
| | | 'div', |
| | | { |
| | | class: styles.bodyCell, |
| | | style: cellStyle, |
| | | }, |
| | | rowIndex + 1 |
| | | ) |
| | | }, |
| | | } |
| | | } |
| | | return {} |
| | | }) |
| | | |
| | | return { |
| | | _t, |
| | | LanguageScopeKey, |
| | | columns, |
| | | columnSeq, |
| | | // slotsMap, |
| | | } |
| | | } |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | <!-- eslint-disable vue/no-mutating-props --> |
| | | <template> |
| | | <button @click="emit('click')" class="custom-btn" v-bind="attrs"> |
| | | <slot></slot> |
| | | </button> |
| | | </template> |
| | | |
| | | <script setup lang="ts"> |
| | | import { useAttrs, useSlots } from 'vue' |
| | | |
| | | const attrs = useAttrs() |
| | | |
| | | const emit = defineEmits(['click']) |
| | | </script> |
| | | |
| | | <style scoped lang="scss"> |
| | | .custom-btn { |
| | | --el-button-text-color: var(--el-color-white); |
| | | --el-button-bg-color: var(--el-color-primary); |
| | | --el-button-border-color: var(--el-color-primary); |
| | | --el-button-outline-color: var(--el-color-primary-light-5); |
| | | --el-button-active-color: var(--el-color-primary-dark-2); |
| | | --el-button-hover-text-color: var(--el-color-white); |
| | | --el-button-hover-link-text-color: var(--el-color-primary-light-5); |
| | | --el-button-hover-bg-color: var(--el-color-primary-light-3); |
| | | --el-button-hover-border-color: var(--el-color-primary-light-3); |
| | | --el-button-active-bg-color: var(--el-color-primary-dark-2); |
| | | --el-button-active-border-color: var(--el-color-primary-dark-2); |
| | | --el-button-disabled-text-color: var(--el-color-white); |
| | | --el-button-disabled-bg-color: var(--el-color-primary-light-5); |
| | | --el-button-disabled-border-color: var(--el-color-primary-light-5); |
| | | display: inline-flex; |
| | | justify-content: center; |
| | | align-items: center; |
| | | line-height: 1; |
| | | min-height: 32px; |
| | | white-space: nowrap; |
| | | cursor: pointer; |
| | | color: #fff; |
| | | text-align: center; |
| | | box-sizing: border-box; |
| | | outline: none; |
| | | transition: 0.1s; |
| | | font-weight: var(--el-button-font-weight); |
| | | user-select: none; |
| | | vertical-align: middle; |
| | | -webkit-appearance: none; |
| | | background-color: var(--el-button-bg-color); |
| | | border: var(--el-border); |
| | | border-color: var(--el-button-border-color); |
| | | padding: 8px 15px; |
| | | font-size: var(--el-font-size-base); |
| | | border-radius: var(--el-border-radius-base); |
| | | opacity: 1; |
| | | &:hover { |
| | | border-color: var(--el-button-hover-border-color); |
| | | background-color: var(--el-button-hover-bg-color); |
| | | outline: none; |
| | | } |
| | | &:focus { |
| | | border-color: var(--el-button-hover-border-color); |
| | | background-color: var(--el-button-hover-bg-color); |
| | | outline: none; |
| | | } |
| | | &:active { |
| | | border-color: var(--el-button-active-border-color); |
| | | background-color: var(--el-button-active-bg-color); |
| | | outline: none; |
| | | } |
| | | } |
| | | </style> |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | .extendedSummaryTable { |
| | | width: calc(100% - 20px); |
| | | height: calc(100% - 160px); |
| | | min-height: 100px; |
| | | margin: 10px; |
| | | margin-bottom: 0; |
| | | margin-top: 0; |
| | | overflow: hidden; |
| | | .exclamation { |
| | | display: flex; |
| | | align-items: center; |
| | | justify-content: center; |
| | | img { |
| | | margin-left: 5px; |
| | | } |
| | | } |
| | | :global(.vxe-table .vxe-cell--sort) { |
| | | width: 1.5em; |
| | | height: 9px; |
| | | text-align: center; |
| | | display: inline-block; |
| | | position: relative; |
| | | } |
| | | :global(.vxe-table--render-default .vxe-table--body-wrapper) { |
| | | transform: translate3d(0, 0, 0); |
| | | } |
| | | } |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | import { defineComponent, ref, reactive, computed, onMounted, watch } from 'vue' |
| | | import type { PropType } from 'vue' |
| | | import styles from './CanvasTableS2.module.scss' |
| | | import { PivotSheet, S2DataConfig, TableSheet, type S2Options } from '@antv/s2' |
| | | import { _t } from '@/libs/Language/Language' |
| | | |
| | | export default defineComponent({ |
| | | name: 'CanvasTableS2', |
| | | props: { |
| | | tableHeader: { |
| | | type: Array as PropType<any[]>, |
| | | required: true, |
| | | }, |
| | | dataList: { |
| | | type: Array as PropType<any[]>, |
| | | required: true, |
| | | }, |
| | | fixedColumn: { |
| | | type: Number, |
| | | default: 0, |
| | | }, |
| | | saveConfig: { |
| | | type: Function, |
| | | default: () => {}, |
| | | }, |
| | | isExtendedSummaryTable: { |
| | | type: Boolean, |
| | | default: false, |
| | | }, |
| | | summaryDataStructure: { |
| | | type: Array as PropType<any[]>, |
| | | default: () => [], |
| | | }, |
| | | tableColumns: { |
| | | type: Array as PropType<any[]>, |
| | | default: () => [], |
| | | }, |
| | | onSortChange: { |
| | | type: Function, |
| | | default: () => {}, |
| | | }, |
| | | }, |
| | | setup(props, { emit, slots, expose }) { |
| | | const tableRef = ref<HTMLDivElement>() |
| | | const tableHeight = ref(0) |
| | | const tableWidth = ref(0) |
| | | |
| | | /** |
| | | * å¤çæ©å±æ»è¡¨åæ»è¡¨ååæ°æ® |
| | | */ |
| | | const data = computed(() => { |
| | | return props.dataList |
| | | }) |
| | | |
| | | const findSeq = (structure: any[], seq: string) => { |
| | | return structure.find((item) => { |
| | | return Object.entries(item).find(([key, value]) => { |
| | | if (key === 'Seq' && value[0].data) { |
| | | return value[0].data == seq |
| | | } |
| | | }) |
| | | }) |
| | | } |
| | | |
| | | const summaryDataStructureComputed = computed(() => { |
| | | const structure = props.summaryDataStructure |
| | | const data = props.dataList |
| | | const result = [] |
| | | data.forEach((item, index: number) => { |
| | | if (!Object.keys(structure).length) return |
| | | const findSeqItem = findSeq(structure, item.Seq) |
| | | // éè¦å¤æseqæ¯å¦åå¨ï¼å¦æåå¨ï¼å°item设置为{} |
| | | if (findSeqItem) { |
| | | if (result.find((resultItem) => resultItem.seq == item.Seq)) { |
| | | result.push({ |
| | | item: {}, |
| | | seq: item.Seq, |
| | | }) |
| | | } else { |
| | | result.push({ |
| | | item: findSeqItem, |
| | | seq: item.Seq, |
| | | }) |
| | | } |
| | | } |
| | | }) |
| | | |
| | | return result.map((item) => { |
| | | if (item.item) { |
| | | return item.item |
| | | } else { |
| | | return {} |
| | | } |
| | | }) |
| | | }) |
| | | |
| | | /** |
| | | * åå¹¶åå
æ ¼ |
| | | */ |
| | | const mergeCells = computed<any>(() => { |
| | | const mergeCells = [] |
| | | // if (!props.isExtendedSummaryTable) { |
| | | // return mergeCells |
| | | // } |
| | | const mergeCellsMap = {} |
| | | const mergeCellArr = [] |
| | | summaryDataStructureComputed.value.forEach((item, index: number) => { |
| | | Object.entries(item).forEach(([key, arr]: [string, any[]]) => { |
| | | const column = columnMap.value[key] |
| | | arr.forEach((row, i) => { |
| | | // mergeCellsMap[column?.index] = mergeCellsMap[column?.index] || [] |
| | | // mergeCellsMap[column?.index].push({ |
| | | // colIndex: column?.index, |
| | | // rowIndex: index + row.rowSpan, |
| | | // showText: false, |
| | | // }) |
| | | mergeCells.push({ |
| | | row: index, |
| | | col: column?.index, |
| | | rowspan: row.rowSpan, |
| | | colspan: 1, |
| | | key: key, |
| | | name: column?.name, |
| | | }) |
| | | }) |
| | | }) |
| | | }) |
| | | const filterMergeCells = mergeCells.filter( |
| | | (item) => |
| | | (item.rowspan > 1 || item.colspan > 1) && item.col !== undefined |
| | | ) |
| | | filterMergeCells.forEach((item) => { |
| | | const cells = [] |
| | | if (item.rowspan > 1) { |
| | | for (let index = 0; index < item.rowspan; index++) { |
| | | cells.push({ |
| | | colIndex: item.col, |
| | | rowIndex: item.row + index, |
| | | showText: index == 0 ? true : false, |
| | | }) |
| | | } |
| | | } |
| | | if (cells.length) { |
| | | mergeCellArr.push(cells) |
| | | } |
| | | }) |
| | | // console.log(mergeCellArr, 'mergeCellArr') |
| | | // Object.values(mergeCellsMap).forEach((arr: any[]) => { |
| | | // arr.forEach((item,index) => { |
| | | // if(index == 0) { |
| | | // item.showText = true |
| | | // item. |
| | | // } else { |
| | | |
| | | // } |
| | | // }) |
| | | // }) |
| | | |
| | | return mergeCellArr |
| | | }) |
| | | |
| | | const columnMap = computed(() => { |
| | | const map = {} |
| | | props.tableColumns.forEach((item, index) => { |
| | | map[item.key] = { |
| | | ...item, |
| | | index: index, |
| | | } |
| | | }) |
| | | return map |
| | | }) |
| | | /** |
| | | * è¡¨å¤´æ°æ® |
| | | */ |
| | | const columns = computed(() => { |
| | | return props.tableHeader.map((item) => { |
| | | return { |
| | | title: item.name, |
| | | field: item.key, |
| | | name: item.name, |
| | | width: item.width, |
| | | children: item.childs.map((child) => { |
| | | return { |
| | | title: child.name, |
| | | name: child.name, |
| | | field: child.key, |
| | | width: child.width, |
| | | } |
| | | }), |
| | | } |
| | | }) |
| | | }) |
| | | |
| | | watch( |
| | | () => props.dataList, |
| | | () => { |
| | | if (Array.isArray(props.dataList) && data.value.length) { |
| | | tableHeight.value = tableRef.value?.clientHeight |
| | | tableWidth.value = tableRef.value?.clientWidth |
| | | if (tableWidth.value && tableHeight.value) { |
| | | render(tableWidth.value, tableHeight.value) |
| | | } |
| | | } |
| | | } |
| | | ) |
| | | |
| | | const render = async (width, height) => { |
| | | const filedWidthMap = {} |
| | | props.tableColumns.forEach((column) => { |
| | | filedWidthMap[column.key] = column.width || 200 |
| | | }) |
| | | const s2Options: S2Options = { |
| | | width, |
| | | height, |
| | | hierarchyType: 'grid', |
| | | mergedCellsInfo: mergeCells.value, |
| | | style: { |
| | | colCell: { |
| | | widthByField: filedWidthMap, |
| | | }, |
| | | }, |
| | | // æé«æ»å¨æ§è½ |
| | | transformCanvasConfig(renderer) { |
| | | renderer.setConfig({ |
| | | enableCulling: true, |
| | | enableRenderingOptimization: true, |
| | | }) |
| | | }, |
| | | } |
| | | const s2DataConfig: S2DataConfig = { |
| | | fields: { |
| | | columns: columns.value, |
| | | }, |
| | | data: data.value, |
| | | } |
| | | const container = document.querySelector('#s2_table') |
| | | |
| | | const s2 = new TableSheet(container, s2DataConfig, s2Options) |
| | | s2.setTheme({ |
| | | dataCell: { |
| | | bolderText: { |
| | | textAlign: 'center', |
| | | textBaseline: 'middle', |
| | | }, |
| | | text: { |
| | | textAlign: 'center', |
| | | textBaseline: 'middle', |
| | | }, |
| | | }, |
| | | }) |
| | | await s2.render() |
| | | } |
| | | // onMounted(async () => { |
| | | // // è·åè¡¨æ ¼çé«åº¦ |
| | | // const t = setTimeout(() => { |
| | | // tableHeight.value = tableRef.value?.clientHeight |
| | | // tableWidth.value = tableRef.value?.clientWidth |
| | | // render(tableWidth.value, tableHeight.value) |
| | | // clearTimeout(t) |
| | | // }, 0) |
| | | // }) |
| | | return () => { |
| | | return ( |
| | | <div |
| | | class={styles.extendedSummaryTable} |
| | | id="s2_table" |
| | | ref={tableRef} |
| | | ></div> |
| | | ) |
| | | } |
| | | }, |
| | | }) |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | .CommonTable { |
| | | width: 100%; |
| | | max-height: 490px; |
| | | overflow: auto; |
| | | } |
| | | |
| | | .table { |
| | | :global(.custom-td-action) { |
| | | margin-top: -3px !important; |
| | | } |
| | | } |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | import { |
| | | computed, |
| | | ref, |
| | | defineComponent, |
| | | SetupContext, |
| | | onMounted, |
| | | reactive, |
| | | Fragment, |
| | | DefineComponent, |
| | | Component, |
| | | nextTick, |
| | | } from 'vue' |
| | | import BaseTable from '@/components/Table/Table' |
| | | import styles from './CommonTable.module.scss' |
| | | import { Create } from '@/libs/Create/Create' |
| | | import BaseInput from '@/components/BaseInput/BaseInput' |
| | | import Variable from '@/components/Variable/Variable' |
| | | import Tag from '@/components/Tag/Tag' |
| | | import Icon from '@/components/Icon/Icon' |
| | | import { useVModels } from '@vueuse/core' |
| | | import RelationMaterielDialog from '@/widgets/ProcessManagement/Views/Pages/Dialog/RelationMaterielDialog/RelationMaterielDialog' |
| | | import RelationBarcodeGenerateDialog from '@/widgets/ProcessManagement/Views/Pages/Dialog/RelationBarcodeGenerateDialog/RelationBarcodeGenerateDialog' |
| | | import cloneDeep from 'lodash/cloneDeep' |
| | | import omit from 'lodash/omit' |
| | | import { ElMessage } from 'element-plus' |
| | | import { ConfirmBox } from '@/components/ConfirmBox/ConfirmBox' |
| | | // @ts-ignore |
| | | import { v4 as uuidv4 } from 'uuid' |
| | | import get from 'lodash/get' |
| | | import Text from '@/components/Text/Text' |
| | | import isNil from 'lodash/isNil' |
| | | import set from 'lodash/set' |
| | | import Select from '../Select/Select' |
| | | import { clone, has, isFunction } from 'lodash' |
| | | import { _t } from '@/libs/Language/Language' |
| | | import ElInputNumber from 'element-plus/es/components/input-number/index' |
| | | import ElSwitch from 'element-plus/es/components/switch/index' |
| | | import FlowContextDialog from '@/components/FlowContextDialog/FlowContextDialog' |
| | | import { emit } from 'process' |
| | | |
| | | const WidgetMap: Record<string, Component> = { |
| | | tag: Tag, |
| | | input: BaseInput, |
| | | variable: Variable, |
| | | constant: BaseInput, |
| | | generateBarcode: RelationBarcodeGenerateDialog, |
| | | parsingBarcode: RelationBarcodeGenerateDialog, |
| | | relationMateriel: RelationMaterielDialog, |
| | | select: Select, |
| | | inputNumber: ElInputNumber, |
| | | switch: ElSwitch, |
| | | flowItemKey: FlowContextDialog, |
| | | } |
| | | |
| | | export interface CurrentType { |
| | | row: any |
| | | index: number |
| | | } |
| | | |
| | | export default defineComponent({ |
| | | name: 'åæ°è¡¨æ ¼', |
| | | props: { |
| | | dataSource: { |
| | | type: Array, |
| | | default: [], |
| | | }, |
| | | columns: { |
| | | type: Array, |
| | | default: [], |
| | | }, |
| | | isFooter: { |
| | | type: Boolean, |
| | | default: true, |
| | | }, |
| | | isDrag: { |
| | | type: Boolean, |
| | | default: true, |
| | | }, |
| | | isChecked: { |
| | | type: Boolean, |
| | | default: true, |
| | | }, |
| | | isStop: { |
| | | type: Boolean, |
| | | default: false, |
| | | }, |
| | | isContextMenu: { |
| | | type: Boolean, |
| | | default: false, |
| | | }, |
| | | contextMenu: { |
| | | type: Array, |
| | | default: [], |
| | | }, |
| | | mergeContextMenu: { |
| | | type: Array, |
| | | default: [], |
| | | }, |
| | | height: { |
| | | type: String, |
| | | default: '', |
| | | }, |
| | | style: { |
| | | type: Object, |
| | | default: () => ({}), |
| | | }, |
| | | delConfig: { |
| | | type: Object, |
| | | default: () => ({ |
| | | tip: '', |
| | | }), |
| | | }, |
| | | uuid: { |
| | | type: Boolean, |
| | | default: false, |
| | | }, |
| | | create: { |
| | | type: Function, |
| | | default: null, |
| | | }, |
| | | isSeq: { |
| | | type: Boolean, |
| | | default: true, |
| | | }, |
| | | autoHeight: { |
| | | type: String, |
| | | default: '', |
| | | }, |
| | | maxHeight: { |
| | | type: String, |
| | | default: '', |
| | | }, |
| | | LanguageScopeKey: { |
| | | type: String, |
| | | default: '', |
| | | }, |
| | | customWidgetMap: { |
| | | type: Object, |
| | | default: () => ({}), |
| | | }, |
| | | id: { |
| | | type: String, |
| | | default: 'id', |
| | | }, |
| | | onRowClick: { |
| | | type: Function, |
| | | }, |
| | | createCheck: { |
| | | type: Function, |
| | | }, |
| | | onCheck: { |
| | | type: Function, |
| | | }, |
| | | }, |
| | | emits: ['update:dataSource', 'rowClick', 'check'], |
| | | setup(props, ctx: SetupContext) { |
| | | // const { dataSource } = useVModels(props, ctx.emit) |
| | | const dataSource = computed({ |
| | | get() { |
| | | return props.dataSource |
| | | }, |
| | | set(v) { |
| | | ctx.emit('update:dataSource', v) |
| | | }, |
| | | }) |
| | | const fieldRequiredMap = reactive<Record<string, any>>({}) |
| | | const tableRef = ref<any>() |
| | | const selections = ref<any>([]) |
| | | // èå |
| | | const contextMenu = [ |
| | | { |
| | | label: _t('å䏿·»å ä¸è¡'), |
| | | fn: (current: CurrentType) => onUpAdd(current), |
| | | icon: 'up', |
| | | }, |
| | | { |
| | | label: _t('å䏿·»å ä¸è¡'), |
| | | fn: (current: CurrentType) => onDownAdd(current), |
| | | icon: 'down', |
| | | }, |
| | | ...props.mergeContextMenu, |
| | | { |
| | | label: _t('å é¤'), |
| | | fn: ({ index }: CurrentType) => { |
| | | if (selections.value.length) { |
| | | dataSource.value = dataSource.value.filter((item: any) => { |
| | | return !selections.value.includes(item.id) |
| | | }) |
| | | } else { |
| | | dataSource.value.splice(index, 1) |
| | | } |
| | | }, |
| | | icon: 'close', |
| | | }, |
| | | ] |
| | | |
| | | const columns = computed(() => { |
| | | if (props.isSeq) { |
| | | return [ |
| | | { |
| | | type: 'seq', |
| | | width: 40, |
| | | title: _t('åºå·'), |
| | | }, |
| | | ...props.columns, |
| | | ] |
| | | } |
| | | return props.columns |
| | | }) |
| | | |
| | | const onUpAdd = ({ row, index }: CurrentType) => { |
| | | const fn = isFunction(props.createCheck) ? props.createCheck : () => true |
| | | if (!fn()) return |
| | | dataSource.value.splice(index, 0, genData()) |
| | | } |
| | | |
| | | const onDownAdd = ({ row, index }: CurrentType) => { |
| | | const fn = isFunction(props.createCheck) ? props.createCheck : () => true |
| | | if (!fn()) return |
| | | dataSource.value.splice(index + 1, 0, genData()) |
| | | } |
| | | |
| | | const genData = () => { |
| | | let create: Record<string, any> = {} |
| | | if (props.create && typeof props.create === 'function') { |
| | | const fn = props.create |
| | | create = fn() |
| | | } else { |
| | | if (props.uuid) { |
| | | const id = uuidv4() |
| | | create.id = id |
| | | } |
| | | } |
| | | |
| | | return new Create(create) |
| | | } |
| | | |
| | | const getFiled = computed(() => (row: any, field: string, column: any) => { |
| | | if (isNil(row[field])) { |
| | | row[field] = column.defaultValue |
| | | } |
| | | return get(row, field, column.defaultValue) |
| | | }) |
| | | |
| | | const customWidgetFnMap = ( |
| | | key: string, |
| | | { Widget, column, config, field }: any |
| | | ) => { |
| | | const map: Record<string, any> = { |
| | | tag: ( |
| | | <Widget |
| | | key={column.field} |
| | | {...config} |
| | | LanguageScopeKey={props.LanguageScopeKey} |
| | | > |
| | | {field} |
| | | </Widget> |
| | | ), |
| | | } |
| | | return map[key] |
| | | } |
| | | |
| | | /**çæslotsé
ç½® */ |
| | | const generationSlots = computed(() => { |
| | | const slots: Record<string, ({ row, index }: any) => any> = {} |
| | | const columns = props.columns || [] |
| | | const lowerCase = (v: string) => v.charAt(0).toLowerCase() + v.slice(1) |
| | | Object.assign(WidgetMap, props.customWidgetMap) |
| | | let i = 0 |
| | | columns.forEach((column: any) => { |
| | | let el = column.el |
| | | let WidgetEl = null |
| | | if (isFunction(el)) { |
| | | const elStr = el() |
| | | el = typeof elStr === 'string' ? elStr : el |
| | | } else { |
| | | el = el ? lowerCase(el) : el |
| | | } |
| | | |
| | | let Widget: Component | any = WidgetMap[el] || null |
| | | if (column.field !== 'action') { |
| | | const config = column.config || column.props || {} |
| | | const onChange = config.onChange |
| | | delete config.onChange |
| | | slots[column.field] = (scope: any) => { |
| | | const { row, index } = scope |
| | | if (row.el && row.elField === column.field) { |
| | | Widget = WidgetMap[lowerCase(row.el)] || null |
| | | } |
| | | |
| | | const field = get(row, column.field) |
| | | if (!Widget) { |
| | | const msg = get(row, column.field) |
| | | return typeof msg === 'string' ? ( |
| | | <Text tip={msg} LanguageScopeKey={props.LanguageScopeKey}> |
| | | {row.isRequired || column.required ? ( |
| | | <Fragment> |
| | | {column.field !== 'description' ? ( |
| | | <span style="color:#D9001B;">*</span> |
| | | ) : null} |
| | | |
| | | {msg} |
| | | </Fragment> |
| | | ) : ( |
| | | msg |
| | | )} |
| | | </Text> |
| | | ) : ( |
| | | '-' |
| | | ) |
| | | } |
| | | const options = column.options || row.options |
| | | |
| | | const ops = options?.value || options |
| | | const slot = ctx.slots[column.field] |
| | | // æ¯æslots |
| | | if (slot) { |
| | | return slot(Widget, { |
| | | row, |
| | | options: ops, |
| | | config, |
| | | column, |
| | | field: column.field, |
| | | index, |
| | | dataSource: dataSource.value, |
| | | }) |
| | | } |
| | | |
| | | if (!ops) { |
| | | const CurrentWidget = customWidgetFnMap(el, { |
| | | Widget, |
| | | column, |
| | | config, |
| | | field, |
| | | }) |
| | | if (CurrentWidget) return CurrentWidget |
| | | } |
| | | return ( |
| | | <Widget |
| | | key={column.field} |
| | | {...config} |
| | | // 妿åå¨onChangeï¼åè°ç¨onChangeï¼ä¼ érowå¼ |
| | | onChange={(...args) => onChange?.(...args, row)} |
| | | v-model:dataSource={dataSource.value} |
| | | field={column.field} |
| | | index={index} |
| | | options={ops} |
| | | modelValue={getFiled.value(row, column.field, column)} |
| | | onUpdate:modelValue={(val: string | number) => |
| | | onUpdateModelValue(val, row, column) |
| | | } |
| | | LanguageScopeKey={props.LanguageScopeKey} |
| | | /> |
| | | ) |
| | | } |
| | | } else { |
| | | return '-' |
| | | // return get(row, column.field) |
| | | } |
| | | }) |
| | | return slots |
| | | }) |
| | | |
| | | const onUpdateModelValue = ( |
| | | val: string | number, |
| | | row: Record<string, any>, |
| | | column: Record<string, any> |
| | | ) => { |
| | | set(row, column.field, val) |
| | | column.format && column.format(val, row) |
| | | } |
| | | |
| | | const onCheck = (records: any[]) => { |
| | | selections.value = records.map((item) => item.id) |
| | | ctx.emit('check', records) |
| | | } |
| | | |
| | | const onAdd = () => { |
| | | const fn = isFunction(props.createCheck) ? props.createCheck : () => true |
| | | if (!fn()) return |
| | | if (Array.isArray(dataSource.value)) { |
| | | dataSource.value.push(genData()) |
| | | } else { |
| | | dataSource.value = [] |
| | | dataSource.value.push(genData()) |
| | | tableRef.value?.scrollToRowLine() |
| | | } |
| | | tableRef.value?.scrollToRowLine() |
| | | } |
| | | |
| | | const onDelRow = (row: any) => { |
| | | const delFn = () => |
| | | (dataSource.value = dataSource.value.filter((item) => { |
| | | return item !== row |
| | | })) |
| | | if (props.delConfig?.tip && !row?.id?.includes('row_')) { |
| | | ConfirmBox(props.delConfig?.tip).then(() => { |
| | | delFn() |
| | | }) |
| | | } else { |
| | | delFn() |
| | | } |
| | | } |
| | | /** |
| | | * è·ååæ®µRequired |
| | | */ |
| | | const getFieldRequiredMap = () => { |
| | | props.columns.forEach((item: any) => { |
| | | // éèåæ®µä¸éè¦æ ¡éª |
| | | if ((!item.hide && item.required) || item.customRequired) { |
| | | fieldRequiredMap[item.field] = item |
| | | } |
| | | }) |
| | | } |
| | | /** |
| | | * æ ¡éªæ¯å¦æå¿
å¡« |
| | | * @param data |
| | | * @returns |
| | | */ |
| | | const checkRequired = (data: any[]) => { |
| | | const fields = Object.keys(fieldRequiredMap) |
| | | let checked = false |
| | | if (fields.length) { |
| | | for (let index = 0; index < data.length; index++) { |
| | | const item: any = data[index] |
| | | |
| | | if (checked) { |
| | | break |
| | | } else { |
| | | for (let idx = 0; idx < fields.length; idx++) { |
| | | const fieldKey = fields[idx] |
| | | const v = get(item, fieldKey) |
| | | const column = fieldRequiredMap[fieldKey] |
| | | if (isNil(v) || v === '') { |
| | | let msg = '' |
| | | if (item.isRequired) { |
| | | msg = `${item.name} ${_t('ä¸è½ä¸ºç©º')}` |
| | | checked = true |
| | | } else if (column.required) { |
| | | msg = `${column.title} ${_t('ä¸è½ä¸ºç©º')}` |
| | | checked = true |
| | | } |
| | | if (checked && msg) { |
| | | ElMessage.error(msg) |
| | | } |
| | | |
| | | break |
| | | } else { |
| | | if (column.validator && column.validator instanceof Function) { |
| | | const rule = { |
| | | field: fieldKey, |
| | | fullField: column.field, |
| | | type: typeof v, |
| | | pattern: column.pattern, |
| | | message: column.ruleMessage, |
| | | } |
| | | const errorCallBack = (msg: string) => { |
| | | ElMessage.error(msg) |
| | | checked = true |
| | | } |
| | | column.validator(rule, v, errorCallBack) |
| | | if (checked) { |
| | | break |
| | | } |
| | | } |
| | | } |
| | | } |
| | | } |
| | | } |
| | | } |
| | | return !checked |
| | | } |
| | | |
| | | /** |
| | | * è·åæ°æ®ï¼å¹¶æä¾æ ¡éªï¼å é¤å¤ä½å段 |
| | | * @param noCheck |
| | | * @returns |
| | | */ |
| | | const getData = (noCheck = false) => { |
| | | const data: any[] = [] |
| | | dataSource.value.forEach((item: any) => { |
| | | const hasValue = has(item, 'value') |
| | | // å¿å ï¼item.valueä¸å«æå¾ªç¯å¼ç¨._ctxï¼ç®åæªæ¥å°åå |
| | | if (hasValue && has(item.value, '_ctx')) { |
| | | delete item.value._ctx |
| | | } |
| | | const obj = cloneDeep({ |
| | | ...item, |
| | | }) |
| | | data.push(obj) |
| | | }) |
| | | if (noCheck || checkRequired(data)) { |
| | | const newData = data.map((item: any) => { |
| | | if (item.id && String(item.id).includes('row_')) { |
| | | return omit(item, [props.id || 'id']) |
| | | } |
| | | return item |
| | | }) |
| | | return newData |
| | | } |
| | | } |
| | | |
| | | const onRowClick = (record) => { |
| | | ctx.emit('rowClick', record) |
| | | } |
| | | /** |
| | | * é«äº®è¡ |
| | | * @param row |
| | | */ |
| | | const setCurrentRow = (key: string) => { |
| | | nextTick(() => { |
| | | tableRef.value?.setCurrentRow(key) |
| | | }) |
| | | } |
| | | |
| | | const setSelectRow = (keys: string[]) => { |
| | | clearSelectEvent() |
| | | nextTick(() => { |
| | | tableRef.value?.setSelectRow(keys) |
| | | }) |
| | | } |
| | | |
| | | const clearSelectEvent = () => { |
| | | tableRef.value?.clearSelectEvent?.() |
| | | } |
| | | |
| | | onMounted(() => getFieldRequiredMap()) |
| | | |
| | | ctx.expose({ |
| | | getData, |
| | | setCurrentRow, |
| | | clearSelectEvent, |
| | | setSelectRow, |
| | | }) |
| | | |
| | | return () => { |
| | | let contextMenuCustom: boolean | any = [] |
| | | if (props.isContextMenu || props.contextMenu?.length) { |
| | | contextMenuCustom = props.contextMenu?.length |
| | | ? props.contextMenu |
| | | : contextMenu |
| | | } |
| | | return ( |
| | | <div |
| | | class={styles.CommonTable} |
| | | style={{ ...props.style, height: props.height }} |
| | | > |
| | | <BaseTable |
| | | ref={tableRef} |
| | | class={styles.table} |
| | | columns={columns.value} |
| | | id={props.id} |
| | | contextMenu={contextMenuCustom} |
| | | vSlots={{ |
| | | ...generationSlots.value, |
| | | action: ({ row, column }: any) => { |
| | | return ( |
| | | <Icon |
| | | icon={column.icon || 'closeDark'} |
| | | style="cursor: pointer;" |
| | | onClick={() => onDelRow(row)} |
| | | width={16} |
| | | height={16} |
| | | /> |
| | | ) |
| | | }, |
| | | }} |
| | | gt={40} |
| | | size="mini" |
| | | v-model:dataSource={dataSource.value} |
| | | isHidePagination={true} |
| | | isChecked={props.isChecked} |
| | | isDrag={props.isDrag} |
| | | isFooter={props.isFooter} |
| | | isVScroll={true} |
| | | isStop={props.isStop} |
| | | onCheck={onCheck} |
| | | height={props.height} |
| | | maxHeight={props.maxHeight} |
| | | autoHeight={props.autoHeight} |
| | | onClickFooter={onAdd} |
| | | LanguageScopeKey={props.LanguageScopeKey} |
| | | onRowClick={onRowClick} |
| | | /> |
| | | </div> |
| | | ) |
| | | } |
| | | }, |
| | | }) |
| | |
| | | .deleteDialog { |
| | | height: 125px; |
| | | border: 1px solid #dde0e4; |
| | | border-radius: 2px 2px 2px 2px; |
| | | .confirmDialog { |
| | | min-height: 55px; |
| | | // border: 1px solid #dde0e4; |
| | | // border-radius: 2px 2px 2px 2px; |
| | | word-break: break-all; |
| | | font-size: 14px; |
| | | font-size: 16px; |
| | | color: #333; |
| | | display: flex; |
| | | align-items: center; |
| | | justify-content: center; |
| | | padding: 20px; |
| | | padding: 10 0px; |
| | | overflow: auto; |
| | | text-align: center; |
| | | } |
| | | |
| | | |
| | | .ConfirmBox { |
| | | :global(.cs-dialog-content){ |
| | | height: auto !important; |
| | | padding: 0 !important; |
| | | } |
| | | :global(.cs-dialog-footer){ |
| | | padding: 0; |
| | | } |
| | | } |
| | |
| | | import { createApp, h, ref, nextTick } from 'vue' |
| | | import { createApp, h, ref, nextTick, Component } from 'vue' |
| | | import BaseDialog from '@/components/BaseDialog/index.vue' |
| | | import { ElConfigProvider } from 'element-plus' |
| | | import styles from './ConfirmBox.module.scss' |
| | | export const ConfirmBox = (text: string, title = '确认') => { |
| | | import { _t } from '@/libs/Language/Language' |
| | | export const ConfirmBox = ( |
| | | text: string | any, |
| | | title = '确认', |
| | | attrs: any = {} |
| | | ) => { |
| | | return new Promise((resolve, reject) => { |
| | | const mountNode = document.createElement('div') |
| | | document.body.appendChild(mountNode) |
| | | |
| | | const visible = ref(true) |
| | | const RenderProvider = (Widget: any) => { |
| | | return ( |
| | | <el-config-provider namespace="cs"> |
| | | <Widget /> |
| | | </el-config-provider> |
| | | ) |
| | | } |
| | | const app = createApp({ |
| | | render() { |
| | | return h( |
| | | BaseDialog, |
| | | { |
| | | modelValue: visible.value, |
| | | 'onUpdate:modelValue': (value: boolean) => { |
| | | visible.value = value |
| | | return RenderProvider( |
| | | h( |
| | | BaseDialog, |
| | | { |
| | | class: styles.ConfirmBox, |
| | | modelValue: visible.value, |
| | | 'onUpdate:modelValue': (value: boolean) => { |
| | | visible.value = value |
| | | }, |
| | | title: _t(title), |
| | | width: '379px', |
| | | onConfirm: () => { |
| | | resolve(true) |
| | | nextTick(() => { |
| | | mountNode.remove() |
| | | }) |
| | | }, |
| | | onClose: () => { |
| | | reject(false) |
| | | nextTick(() => { |
| | | mountNode.remove() |
| | | }) |
| | | }, |
| | | ...attrs, |
| | | }, |
| | | title: title, |
| | | width: '379px', |
| | | onConfirm: () => { |
| | | resolve(true) |
| | | nextTick(() => { |
| | | mountNode.remove() |
| | | }) |
| | | }, |
| | | onClose: () => { |
| | | reject(false) |
| | | nextTick(() => { |
| | | mountNode.remove() |
| | | }) |
| | | }, |
| | | }, |
| | | h('div', { class: styles.deleteDialog }, text) |
| | | { |
| | | default: h('div', { class: styles.confirmDialog }, text), |
| | | footer: attrs.footer ? attrs.footer : null, |
| | | } |
| | | ) |
| | | ) |
| | | }, |
| | | }) |
| | |
| | | position: relative; |
| | | width: 100%; |
| | | height: 100%; |
| | | background: linear-gradient(93deg, #5a84ff 0%, #c5d4fe 100%); |
| | | background: #5a84ff; |
| | | border-radius: 12px 12px 12px 12px; |
| | | } |
| | | |
| | |
| | | } |
| | | .content { |
| | | // position: relative; |
| | | padding:20px 10px; |
| | | padding: 20px 10px; |
| | | // z-index: 2; |
| | | height: calc(100% - 40px); |
| | | background: linear-gradient(180deg, #f6f9ff 0%, #ffffff 100%); |
| | | box-shadow: 0px 3px 6px 1px rgba(0, 0, 0, 0.16); |
| | | // box-shadow: 0px 3px 6px 1px rgba(0, 0, 0, 0.16); |
| | | box-shadow: 0px 1px 1px 1px #dbdbdb; |
| | | border-radius: 5px 5px 5px 5px; |
| | | overflow: hidden; |
| | | } |
| | |
| | | import Icon from '@/components/Icon/Icon' |
| | | import { useVModel } from '@vueuse/core' |
| | | import { debounce } from 'lodash' |
| | | import { _t } from '@/libs/Language/Language' |
| | | export default defineComponent({ |
| | | name: 'éç¨å¤´é¨', |
| | | props: { |
| | |
| | | class={styles.innerInput} |
| | | onBlur={() => onEventChange(false)} |
| | | onFocus={() => onEventChange(true)} |
| | | placeholder={!isBlur.value ? props.placeholder : ''} |
| | | placeholder={!isBlur.value ? _t(props.placeholder) : ''} |
| | | prefix-icon={ |
| | | <Icon icon="white_search" width={12} height={12} /> |
| | | } |
| | |
| | | type: String, |
| | | default: 'æ é¢', |
| | | }, |
| | | customStyle: { |
| | | type: String, |
| | | }, |
| | | }, |
| | | setup(props, { slots }) { |
| | | return () => ( |
| | | <div class={styles.container}> |
| | | <div class={styles.title}>{props.title}</div> |
| | | <div class={styles.content}>{slots.default?.()}</div> |
| | | <div class={styles.content} style={props.customStyle}> |
| | | {slots.default?.()} |
| | | </div> |
| | | </div> |
| | | ) |
| | | }, |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | .cs-setting-tree_custom_style { |
| | | box-shadow: none; |
| | | height: 28px; |
| | | line-height: 28px; |
| | | font-size: 12px; |
| | | border-radius: 4px; |
| | | color: var(--cms-text-el-input-color); |
| | | border: 1px solid var(--cms-color-bg-4); |
| | | background-color: var(--cms-color-bg-3); |
| | | background-color: #202124; |
| | | outline: none; |
| | | box-sizing: border-box; |
| | | cursor: pointer; |
| | | overflow: hidden; |
| | | |
| | | ::deep(.cs-input__inner) { |
| | | padding-right: 24px !important; |
| | | } |
| | | &:hover { |
| | | border-bottom: 1px solid var(--cms-color-primary-1); |
| | | box-shadow: none !important; |
| | | } |
| | | .cs-select__wrapper { |
| | | outline: none; |
| | | display: flex; |
| | | align-items: center; |
| | | position: relative; |
| | | box-sizing: border-box; |
| | | cursor: pointer; |
| | | text-align: left; |
| | | font-size: 12px; |
| | | gap: 6px; |
| | | min-height: 28px; |
| | | line-height: 24px; |
| | | border-radius: var(--el-border-radius-base); |
| | | transition: var(--el-transition-duration); |
| | | background-color: #141414; |
| | | padding: 0 12px; |
| | | box-shadow: none; |
| | | &:hover { |
| | | box-shadow: none !important; |
| | | } |
| | | } |
| | | .cs-select__wrapper.is-focused { |
| | | box-shadow: none; |
| | | } |
| | | .cs-select__selection { |
| | | position: relative; |
| | | display: flex; |
| | | flex-wrap: wrap; |
| | | align-items: center; |
| | | flex: 1; |
| | | min-width: 0; |
| | | gap: 6px; |
| | | } |
| | | |
| | | .cs-select__input-wrapper.is-hidden { |
| | | position: absolute; |
| | | opacity: 0; |
| | | } |
| | | .cs-select__input-wrapper { |
| | | max-width: 100%; |
| | | } |
| | | .cs-select__selected-item { |
| | | display: flex; |
| | | flex-wrap: wrap; |
| | | user-select: none; |
| | | } |
| | | .cs-select__placeholder.is-transparent { |
| | | user-select: none; |
| | | color: var(--el-text-color-placeholder); |
| | | } |
| | | .cs-select__placeholder { |
| | | position: absolute; |
| | | display: block; |
| | | top: 50%; |
| | | transform: translateY(-50%); |
| | | width: 100%; |
| | | overflow: hidden; |
| | | text-overflow: ellipsis; |
| | | white-space: nowrap; |
| | | } |
| | | .cs-select__input { |
| | | border: none; |
| | | outline: none; |
| | | padding: 0; |
| | | color: var(--el-select-multiple-input-color); |
| | | font-size: inherit; |
| | | font-family: inherit; |
| | | appearance: none; |
| | | height: 24px; |
| | | max-width: 100%; |
| | | background-color: transparent; |
| | | } |
| | | .cs-select__prefix, |
| | | .cs-select__suffix { |
| | | display: flex; |
| | | align-items: center; |
| | | flex-shrink: 0; |
| | | gap: 6px; |
| | | color: var(--el-input-icon-color, var(--el-text-color-placeholder)); |
| | | .cs-select__caret { |
| | | color: var(--el-select-input-color); |
| | | font-size: var(--el-select-input-font-size); |
| | | transition: var(--el-transition-duration); |
| | | transform: rotate(0); |
| | | cursor: pointer; |
| | | } |
| | | .cs-icon { |
| | | --color: inherit; |
| | | height: 1em; |
| | | width: 1em; |
| | | line-height: 1em; |
| | | display: inline-flex; |
| | | justify-content: center; |
| | | align-items: center; |
| | | position: relative; |
| | | fill: currentColor; |
| | | color: var(--color); |
| | | font-size: inherit; |
| | | } |
| | | } |
| | | } |
| | | |
| | | .settings-cs-tree_check { |
| | | box-shadow: 0 1px 6px 1px #0000008f !important; |
| | | background: #202124 !important; |
| | | border: 0 !important; |
| | | .cs-select-dropdown__item:hover { |
| | | background: #383737 !important; |
| | | color: #ccc !important; |
| | | border-radius: 4px; |
| | | } |
| | | .cs-select-dropdown__item.is-hovering, |
| | | .cs-select-dropdown__item.is-selected { |
| | | color: #ccc !important; |
| | | border-radius: 4px; |
| | | } |
| | | .cs-popper__arrow::before { |
| | | border-top: none !important; |
| | | border-left: none !important; |
| | | border-bottom-color: transparent !important; |
| | | border-right-color: transparent !important; |
| | | background: #383737 !important; |
| | | } |
| | | } |
| | | .cs-tree_check-settings { |
| | | .cs-tree { |
| | | height: auto; |
| | | background: #202124; |
| | | .cs-tree-node__content:hover { |
| | | background-color: #383737 !important; |
| | | } |
| | | .cs-tree-node:focus > .cs-tree-node__content { |
| | | background-color: #383737; |
| | | } |
| | | } |
| | | } |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | /** |
| | | * ç¦æ¢å¨éSettingé
ç½®ä¸ä½¿ç¨ |
| | | */ |
| | | |
| | | import { defineComponent, SetupContext } from 'vue' |
| | | import './CsTree.scss' |
| | | |
| | | export default defineComponent<any>({ |
| | | name: 'CsTree', |
| | | setup(props, { attrs }: SetupContext) { |
| | | const namespace = import.meta.env.VITE_APP_NAMESPACE |
| | | |
| | | return () => ( |
| | | <el-config-provider namespace={namespace} z-index={300}> |
| | | <el-tree-select |
| | | class="cs-setting-tree_custom_style" |
| | | popper-class="settings-cs-tree_check cs-tree_check-settings" |
| | | {...attrs} |
| | | /> |
| | | </el-config-provider> |
| | | ) |
| | | }, |
| | | }) |
| | |
| | | import styles from './DateTimePickRange.module.scss' |
| | | import dayjs from 'dayjs' |
| | | import { ElMessage } from 'element-plus' |
| | | import { _t } from '@/libs/Language/Language' |
| | | export default defineComponent({ |
| | | name: 'æ¥æèå´', |
| | | props: { |
| | |
| | | }, |
| | | clearable: { |
| | | type: Boolean, |
| | | default: true |
| | | } |
| | | default: true, |
| | | }, |
| | | }, |
| | | emits: ['change'], |
| | | setup(props, { attrs, slots, emit }) { |
| | |
| | | const onChangeFrom = (val: Date) => { |
| | | console.log(val) |
| | | if (times.To && dayjs(val).isAfter(times.To)) { |
| | | ElMessage.warning('å¼å§æ¶é´å¿
é¡»æ¯ç»ææ¶é´å°') |
| | | ElMessage.warning(_t('å¼å§æ¶é´å¿
é¡»æ¯ç»ææ¶é´å°')) |
| | | return |
| | | } |
| | | emit('change', times) |
| | | } |
| | | |
| | | const onChangeTo = (val: Date) => { |
| | | console.log(val); |
| | | console.log(val) |
| | | if (times.To && dayjs(val).isBefore(times.From)) { |
| | | ElMessage.warning('å¼å§æ¶é´å¿
é¡»æ¯ç»ææ¶é´å°') |
| | | ElMessage.warning(_t('å¼å§æ¶é´å¿
é¡»æ¯ç»ææ¶é´å°')) |
| | | return |
| | | } |
| | | emit('change', times) |
| | |
| | | return () => { |
| | | return ( |
| | | <div class={styles.DateTimePickRange}> |
| | | <span class={styles.label}>{props.label}</span> |
| | | <span class={styles.label}>{_t(props.label)}</span> |
| | | <el-date-picker |
| | | v-model={times.From} |
| | | type="datetime" |
| | | placeholder="è¯·éæ©å¼å§æ¶é´" |
| | | placeholder={_t('è¯·éæ©å¼å§æ¶é´')} |
| | | onChange={onChangeFrom} |
| | | valueFormat={props.valueFormat} |
| | | clearable={props.clearable} |
| | |
| | | <el-date-picker |
| | | v-model={times.To} |
| | | type="datetime" |
| | | placeholder="è¯·éæ©ç»ææ¶é´" |
| | | placeholder={_t('è¯·éæ©ç»ææ¶é´')} |
| | | onChange={onChangeTo} |
| | | valueFormat={props.valueFormat} |
| | | clearable={props.clearable} |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | import { SetupContext, defineComponent, nextTick, onMounted, ref, shallowRef } from 'vue' |
| | | |
| | | import sdk from 'sdk' |
| | | import isEmpty from 'lodash/isEmpty' |
| | | const { packs } = sdk |
| | | const { echarts } = packs |
| | | export default defineComponent({ |
| | | name: 'å¾è¡¨', |
| | | props: { |
| | | chartOptions: { |
| | | type: Object, |
| | | default: () => ({}), |
| | | }, |
| | | }, |
| | | setup(props, { attrs, expose }: SetupContext) { |
| | | const chartDomRef = ref() |
| | | |
| | | const myCharts = shallowRef() |
| | | onMounted(async () => { |
| | | await nextTick() |
| | | if (isEmpty(props.chartOptions)) return |
| | | myCharts.value = (await echarts).init(chartDomRef.value) |
| | | myCharts.value.setOption(props.chartOptions) |
| | | }) |
| | | |
| | | |
| | | const getChartInstance = () => { |
| | | return myCharts.value |
| | | } |
| | | |
| | | const setChartOptions = (options: any) => { |
| | | if (myCharts.value) { |
| | | myCharts.value.setOption(options) |
| | | } |
| | | } |
| | | |
| | | expose({ |
| | | getChartInstance, |
| | | setChartOptions, |
| | | }) |
| | | |
| | | |
| | | return () => <div style="height:100%;width:100%" ref={chartDomRef}></div> |
| | | }, |
| | | }) |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | .container { |
| | | height: 100%; |
| | | } |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | import { PropType, SetupContext, computed, defineComponent, useSlots } from 'vue' |
| | | import BaseDialog from '@/components/BaseDialog/index.vue' |
| | | import styles from './DialogPreView.module.scss' |
| | | import { useVModel } from '@vueuse/core' |
| | | import Chart from './Chart' |
| | | import Picture from './Picture' |
| | | export default defineComponent({ |
| | | name: 'DialogPreView', |
| | | props: { |
| | | title: { |
| | | type: String, |
| | | default: 'é¢è§', |
| | | }, |
| | | isChart: { |
| | | type: Boolean, |
| | | default: false, |
| | | }, |
| | | modelValue: { |
| | | type: Boolean, |
| | | default: false, |
| | | }, |
| | | chartOptions: { |
| | | type: Object, |
| | | default: () => ({}), |
| | | }, |
| | | picList: { |
| | | type: Object as PropType<string[]>, |
| | | default: () => [], |
| | | }, |
| | | }, |
| | | emits: ['update:modelValue', 'close', 'confirm'], |
| | | setup(props, { emit, attrs }: SetupContext) { |
| | | const visible = useVModel(props) |
| | | const slots = useSlots() |
| | | const onClose = () => { |
| | | visible.value = false |
| | | emit('close') |
| | | } |
| | | const onConfirm = () => { |
| | | emit('confirm') |
| | | } |
| | | |
| | | const height = computed(() => { |
| | | return (attrs.height as string) || '578px' |
| | | }) |
| | | |
| | | return () => ( |
| | | <BaseDialog |
| | | destroy-on-close |
| | | class={styles.drawer} |
| | | style="background: #fff" |
| | | width="900px" |
| | | height="578px" |
| | | title={props.title} |
| | | v-model={visible.value} |
| | | onClose={onClose} |
| | | onConfirm={onConfirm} |
| | | v-slots={{ |
| | | footer: () => { |
| | | slots.footer ? slots.footer : null |
| | | }, |
| | | }} |
| | | > |
| | | <div class={styles.container}> |
| | | {props.isChart ? ( |
| | | <Chart chartOptions={props.chartOptions} /> |
| | | ) : ( |
| | | <Picture height={height.value} picList={props.picList} /> |
| | | )} |
| | | </div> |
| | | </BaseDialog> |
| | | ) |
| | | }, |
| | | }) |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | import { |
| | | PropType, |
| | | SetupContext, |
| | | computed, |
| | | defineComponent, |
| | | nextTick, |
| | | onMounted, |
| | | ref, |
| | | } from 'vue' |
| | | export default defineComponent({ |
| | | name: 'å¾ç', |
| | | props: { |
| | | picList: { |
| | | type: Object as PropType<string[]>, |
| | | default: () => [], |
| | | }, |
| | | height: { |
| | | type: String, |
| | | default: '578px', |
| | | }, |
| | | }, |
| | | setup(props, { attrs }: SetupContext) { |
| | | onMounted(async () => {}) |
| | | const arrow = computed(() => { |
| | | return props.picList.length > 2 ? 'always' : 'never' |
| | | }) |
| | | return () => ( |
| | | <el-carousel height={props.height} arrow={arrow.value}> |
| | | {props.picList.map((item) => { |
| | | return ( |
| | | <el-carousel-item> |
| | | <el-image |
| | | style="width: 100%; height: 100%" |
| | | src={item} |
| | | fit="contain" |
| | | /> |
| | | </el-carousel-item> |
| | | ) |
| | | })} |
| | | </el-carousel> |
| | | ) |
| | | }, |
| | | }) |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | import { defineComponent } from 'vue' |
| | | |
| | | export default defineComponent({ |
| | | name: 'DyDatePicker', |
| | | setup(props: any, { attrs }) { |
| | | return () => ( |
| | | <el-date-picker |
| | | {...props} |
| | | {...attrs} |
| | | value-format="YYYY-MM-DD HH:mm:ss" |
| | | /> |
| | | ) |
| | | }, |
| | | }) |
| | |
| | | description?: string |
| | | name?: string |
| | | value: string | number |
| | | tip?: string |
| | | } |
| | | |
| | | export interface FormItemPropType { |
| | |
| | | el?: string | Component | DefineComponent | Ref<string> |
| | | options?: OptionItemType[] | any[] | Ref<any> |
| | | isTitle?: boolean |
| | | title?:string | Component |
| | | title?: string | Component |
| | | [key: string]: any | Ref<string> |
| | | } |
| | | |
| | |
| | | margin-left: 10px; |
| | | } |
| | | } |
| | | :global(.cs-select){ |
| | | :global(.cs-select) { |
| | | width: 100%; |
| | | } |
| | | :global(.cs-form--inline .cs-form-item){ |
| | | width: 46%; |
| | | :global(.cs-form--inline .cs-form-item) { |
| | | width: 46%; |
| | | } |
| | | :global(.cs-form--inline .cs-form-item:nth-last-of-type(2n)){ |
| | | margin-right: 0; |
| | | :global(.cs-form--inline .cs-form-item:nth-last-of-type(2n)) { |
| | | margin-right: 0; |
| | | } |
| | | :global(.cs-date-editor) { |
| | | width: 100%; |
| | | } |
| | | } |
| | | .optionLabel { |
| | | display: flex; |
| | | justify-content: space-between; |
| | | align-items: center; |
| | | } |
| | | .formitemPropsLabel { |
| | | display: flex; |
| | | justify-content: flex-start; |
| | | align-items: center; |
| | | } |
| | | |
| | | .itemDistance { |
| | | margin-bottom: 20px !important; |
| | | } |
| | |
| | | defineComponent, |
| | | PropType, |
| | | ref, |
| | | Ref, |
| | | onMounted, |
| | | SetupContext, |
| | | computed, |
| | | unref, |
| | | markRaw, |
| | | DefineComponent, |
| | | Component, |
| | | watch, |
| | | Fragment, |
| | | useSlots, |
| | | } from 'vue' |
| | | import styles from './DyForm.module.scss' |
| | | import ElInput from 'element-plus/es/components/input/index' |
| | | import DyInput from '../Input/Input' |
| | | import Option from '@/components/Select/Option' |
| | | import Select from '@/components/Select/Select' |
| | | import SelectInput from '@/components/SelectInput/SelectInput' |
| | | import SearchSelect from '@/components/SearchSelect/SearchSelect' |
| | | import type { FormInstance } from 'element-plus' |
| | | import Icon from '../Icon/Icon' |
| | | import { Warning } from '@element-plus/icons-vue' |
| | | import RelationFlowDialog from '@/components/RelationFlowDialog/RelationFlowDialog' |
| | | import { |
| | | FormPropsType, |
| | | FormItemPropType, |
| | |
| | | import TextareaFlow from '../Flow/Flow' |
| | | import get from 'lodash/get' |
| | | import set from 'lodash/set' |
| | | import { has } from 'lodash' |
| | | import Tab from '@/components/Tab/Tab' |
| | | import TabPane from '@/components/Tab/TabPane' |
| | | import ElInputNumber from 'element-plus/es/components/input-number/index' |
| | | import { getCurrentLang, Language } from '@/libs/Language/Language' |
| | | |
| | | const formItemElementMap = markRaw<Record<string, any>>({ |
| | | input: ElInput, |
| | | const formItemElementMap: Record<string, any> = markRaw({ |
| | | input: DyInput, |
| | | inputNumber: ElInputNumber, |
| | | select: Select, |
| | | selectInput: SelectInput, |
| | | flow: RelationFlowDialog, |
| | | variable: Variable, |
| | | textareaFlow: TextareaFlow, |
| | | filterSelect: SearchSelect, |
| | | switch: (props: PropType<any>, { attrs }: SetupContext) => { |
| | | return <el-switch {...attrs} /> |
| | | }, |
| | | dateTime: (props: PropType<any>, { attrs }: SetupContext) => { |
| | | return <el-date-picker |
| | | type="datetime" |
| | | format="YYYY-MM-DD HH:mm:ss" |
| | | {...attrs} |
| | | ></el-date-picker> |
| | | }, |
| | | date: (props: PropType<any>, { attrs }: SetupContext) => { |
| | | return <el-date-picker |
| | | type="date" |
| | | format="YYYY-MM-DD" |
| | | {...attrs} |
| | | ></el-date-picker> |
| | | }, |
| | | }) |
| | | |
| | | const Type: Record<string, any> = { |
| | | select: 'select', |
| | | } |
| | | export default defineComponent<FormPropsType>({ |
| | | export default defineComponent({ |
| | | //@ts-ignore |
| | | name: 'å¨æè¡¨å', |
| | | props: { |
| | |
| | | default: () => ({}), |
| | | }, |
| | | formItemProps: { |
| | | type: Array, |
| | | type: Array as PropType<FormItemPropType[]>, |
| | | default: () => [], |
| | | }, |
| | | inLine: { |
| | | type: Boolean, |
| | | default: false, |
| | | }, |
| | | customWidgetMap: { |
| | | type: Object, |
| | | default: () => ({}), |
| | | }, |
| | | isCategory: { |
| | | type: Boolean, |
| | | default: false, |
| | | }, |
| | | LanguageScopeKey: { |
| | | type: String, |
| | | default: '', |
| | | }, |
| | | }, |
| | | setup(props: PropsType, { attrs, emit, expose }: SetupContext) { |
| | | const formRef = ref<FormInstance>() |
| | | const active = ref('') |
| | | const isZh = ref(true) |
| | | const slots = useSlots() |
| | | const form: any = computed({ |
| | | get() { |
| | | return props.formData |
| | |
| | | emit('update:formData', v) |
| | | }, |
| | | }) |
| | | const formPropsRef = ref<any>({}) |
| | | |
| | | const currentWidgetModel = computed(() => { |
| | | return (path: string) => { |
| | | if (path.includes('.')) { |
| | | const args = path.split('.') |
| | | return get(form.value, args) |
| | | } |
| | | return get(form.value, path) |
| | | } |
| | | }) |
| | |
| | | }) |
| | | }) |
| | | } |
| | | /** |
| | | * è·årefs |
| | | * @returns |
| | | */ |
| | | const getRefByKey = (key: string) => { |
| | | if (key) return formPropsRef.value[key] |
| | | return formPropsRef.value |
| | | } |
| | | |
| | | const resetForm = () => { |
| | | if (!formRef.value) return false |
| | |
| | | } |
| | | |
| | | const formItemProps = computed(() => { |
| | | if (props.isCategory) { |
| | | const tabMap: Record<string, FormItemPropType> = {} |
| | | const tabs: FormItemPropType[] = [] |
| | | if (Array.isArray(props.formItemProps)) { |
| | | props.formItemProps.forEach((item: any) => { |
| | | tabMap[item.category] = tabMap[item.category] || [] |
| | | tabMap[item.category].push(item) |
| | | }) |
| | | Object.keys(tabMap).forEach((key: string) => { |
| | | tabs.push({ |
| | | name: key, |
| | | content: tabMap[key], |
| | | }) |
| | | }) |
| | | } |
| | | return tabs |
| | | } |
| | | |
| | | return props.formItemProps || [] |
| | | }) |
| | | |
| | | expose({ validate, resetForm }) |
| | | |
| | | const FormRender: any = ($props: any) => { |
| | | const item: FormItemPropType = $props.item |
| | |
| | | if (item.el && Type[item.el as string]) { |
| | | return options.map((el: OptionItemType) => ( |
| | | <Option |
| | | label={el.label || el.description || el.name} |
| | | value={el.value} |
| | | ></Option> |
| | | label={el.label || el.description || el.name} |
| | | class={styles.optionLabel} |
| | | key={el.value} |
| | | > |
| | | {el.label || el.description || el.name} |
| | | {el.tip ? ( |
| | | <el-tooltip |
| | | class="box-item" |
| | | effect="dark" |
| | | content={el.tip} |
| | | placement="top" |
| | | key={el.value} |
| | | persistent={false} |
| | | > |
| | | <el-icon> |
| | | <Warning /> |
| | | </el-icon> |
| | | </el-tooltip> |
| | | ) : null} |
| | | </Option> |
| | | )) |
| | | } |
| | | return null |
| | | } |
| | | |
| | | const onUpdateModelValue = (v: string | number, prop: string) => { |
| | | set(form.value, prop, v) |
| | | const onUpdateModelValue = (v: string | number, path: string) => { |
| | | if (path.includes('.')) { |
| | | const args = path.split('.') |
| | | return set(form.value, args, v) |
| | | } |
| | | set(form.value, path, v) |
| | | } |
| | | |
| | | const initFormData = () => { |
| | | formItemProps.value.forEach((item: FormItemPropType) => { |
| | | form.value[item.prop] = form.value[item.prop] || item.defaultValue |
| | | }) |
| | | active.value = formItemProps.value[0].name |
| | | } |
| | | |
| | | const checkZh = (lang: string) => { |
| | | const languageStr = lang.toLowerCase() |
| | | if (languageStr.includes('zh')) return true |
| | | if (languageStr.includes('original')) return true |
| | | return false |
| | | } |
| | | |
| | | const onLanguageChange = () => { |
| | | Language.useChange((language: any) => { |
| | | isZh.value = checkZh(language.lang) |
| | | }) |
| | | } |
| | | |
| | | onMounted(() => { |
| | | isZh.value = checkZh(getCurrentLang()) |
| | | onLanguageChange() |
| | | }) |
| | | |
| | | const RenderItemProps = ($props: any) => { |
| | | const WidgetMap = { |
| | | ...formItemElementMap, |
| | | ...props.customWidgetMap, |
| | | } |
| | | const formItemProps = $props.formItemProps |
| | | |
| | | return ( |
| | | <Fragment> |
| | | {formItemProps.map((item: FormItemPropType, index: number) => { |
| | | if (item.isTitle) { |
| | | if (typeof item.title === 'string') { |
| | | return <Title style="margin-bottom: 10px">{item.title}</Title> |
| | | } |
| | | return item.title |
| | | } |
| | | |
| | | const itemProps: FormItemPropType = {} |
| | | Object.entries(item).forEach(([key, value]) => { |
| | | itemProps[key] = unref(value) |
| | | }) |
| | | const el = |
| | | typeof itemProps.el === 'string' |
| | | ? WidgetMap[itemProps.el] |
| | | : itemProps.el || null |
| | | const hasSlot = itemProps.slot |
| | | const Component = hasSlot ? slots[itemProps.el] : el |
| | | |
| | | const isHide = has(item.isHide, 'value') |
| | | ? item.isHide?.value |
| | | : item.isHide |
| | | return Component && !isHide ? ( |
| | | <el-form-item |
| | | label={itemProps.label} |
| | | prop={itemProps.prop} |
| | | rules={itemProps.rules} |
| | | key={itemProps.prop + index} |
| | | class={styles.itemDistance} |
| | | labelPosition={itemProps.labelPosition} |
| | | labelWidth={isZh.value ? props.labelWidth : 'auto'} |
| | | vSlots={ |
| | | itemProps.icon |
| | | ? { |
| | | label: () => ( |
| | | <label |
| | | key={itemProps.prop} |
| | | class={styles.formitemPropsLabel} |
| | | > |
| | | {itemProps.label} |
| | | {itemProps.icon ? ( |
| | | <el-tooltip |
| | | class="box-item" |
| | | effect="dark" |
| | | content={itemProps.tip} |
| | | placement="top" |
| | | raw-content={itemProps.rawContent} |
| | | persistent={false} |
| | | > |
| | | <Icon |
| | | style="margin-left: 5px" |
| | | icon={itemProps.icon} |
| | | /> |
| | | </el-tooltip> |
| | | ) : null} |
| | | </label> |
| | | ), |
| | | } |
| | | : null |
| | | } |
| | | > |
| | | <Component |
| | | style={{ |
| | | width: itemProps.width, |
| | | height: itemProps.height, |
| | | }} |
| | | {...itemProps} |
| | | placeholder={itemProps.placeholder} |
| | | ref={(ref) => (formPropsRef.value[itemProps.prop] = ref)} |
| | | modelValue={currentWidgetModel.value(itemProps.prop)} |
| | | onUpdate:modelValue={(val: string | number) => |
| | | onUpdateModelValue(val, itemProps.prop) |
| | | } |
| | | > |
| | | <FormRender item={itemProps} /> |
| | | </Component> |
| | | </el-form-item> |
| | | ) : null |
| | | })} |
| | | </Fragment> |
| | | ) |
| | | } |
| | | |
| | | expose({ validate, resetForm, initFormData, getRefByKey }) |
| | | |
| | | return () => { |
| | | return ( |
| | |
| | | <el-form |
| | | labelPosition={props.labelPosition} |
| | | labelWidth={props.labelWidth} |
| | | // labelWidth={isZh.value ? props.labelWidth : 'auto'} |
| | | model={form.value} |
| | | ref={formRef} |
| | | inline={props.inLine} |
| | | > |
| | | {formItemProps.value.map( |
| | | (item: FormItemPropType, index: number) => { |
| | | if (item.isTitle) { |
| | | if (typeof item.title === 'string') { |
| | | return ( |
| | | <Title style="margin-bottom: 10px">{item.title}</Title> |
| | | ) |
| | | } |
| | | return item.title |
| | | } |
| | | |
| | | const itemProps: FormItemPropType = {} |
| | | Object.entries(item).forEach(([key, value]) => { |
| | | itemProps[key] = unref(value) |
| | | }) |
| | | |
| | | const el = |
| | | typeof itemProps.el === 'string' |
| | | ? formItemElementMap[itemProps.el] |
| | | : itemProps.el || null |
| | | const Component = el |
| | | return Component && !item.isHide ? ( |
| | | <el-form-item |
| | | label={itemProps.label} |
| | | prop={itemProps.prop} |
| | | rules={itemProps.rules} |
| | | key={itemProps.prop} |
| | | vSlots={ |
| | | itemProps.labelIcon |
| | | ? { |
| | | label: () => ( |
| | | <label class={styles.formitemPropsLabel}> |
| | | {itemProps.label} |
| | | <Icon icon={itemProps.labelIcon} /> |
| | | </label> |
| | | ), |
| | | } |
| | | : null |
| | | } |
| | | > |
| | | <Component |
| | | style={{ |
| | | width: itemProps.width, |
| | | height: itemProps.height, |
| | | }} |
| | | {...itemProps} |
| | | // v-model={form.value[itemProps.prop as keyof any]} |
| | | modelValue={currentWidgetModel.value(itemProps.prop)} |
| | | onUpdate:modelValue={(val: string | number) => |
| | | onUpdateModelValue(val, itemProps.prop) |
| | | } |
| | | > |
| | | <FormRender item={itemProps} /> |
| | | </Component> |
| | | </el-form-item> |
| | | ) : null |
| | | } |
| | | {props.isCategory ? ( |
| | | <Tab |
| | | active={active.value} |
| | | class={styles.tabContent} |
| | | size="small" |
| | | type="params" |
| | | > |
| | | {formItemProps.value.map((item: any) => { |
| | | return ( |
| | | <TabPane key={item.name} label={item.name} name={item.name}> |
| | | <RenderItemProps formItemProps={item.content} /> |
| | | </TabPane> |
| | | ) |
| | | })} |
| | | </Tab> |
| | | ) : ( |
| | | <RenderItemProps formItemProps={formItemProps.value} /> |
| | | )} |
| | | </el-form> |
| | | </div> |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | <!-- |
| | | <EllipsisTooltipLabel width="100%" :content="content" /> |
| | | |
| | | --> |
| | | <template> |
| | | <div |
| | | class="content" |
| | | :style="{ width: props.width }" |
| | | @mouseover="mouseover" |
| | | @mouseleave="mouseleave" |
| | | :title="props.tooltipContent ? props.tooltipContent : props.content" |
| | | :data-tooltip-disabled="!visible" |
| | | :data-tooltip-effect="props.effect" |
| | | :data-tooltip-placement="props.placement" |
| | | :data-tooltip-popper-class="props.popperClass" |
| | | :data-tooltip-raw-content="props.rawContent" |
| | | > |
| | | <span ref="contentRef"> |
| | | <slot name="content">{{ props.content }}</slot> |
| | | </span> |
| | | </div> |
| | | </template> |
| | | <script setup lang="ts"> |
| | | import { ref } from 'vue' |
| | | interface Props { |
| | | width: string // è¶
åºå®½åº¦æ¶ç¨çç¥å·è¡¨ç¤º |
| | | content: string // æ¾ç¤ºå
容 |
| | | tooltipContent?: string // æç¤ºå
容ï¼è®¾ç½®âæç¤ºå
容âä¸âæ¾ç¤ºå
容âä¸åï¼ |
| | | effect?: string |
| | | placement?: string |
| | | popperClass?: string |
| | | disabled?: boolean |
| | | rawContent?: boolean |
| | | } |
| | | const props = withDefaults(defineProps<Props>(), { |
| | | effect: 'dark', |
| | | placement: 'top-start', |
| | | content: '', |
| | | popperClass: '', |
| | | width: '', |
| | | tooltipContent: '', |
| | | disabled: false, |
| | | rawContent: false, |
| | | }) |
| | | |
| | | let visible = ref(false) |
| | | const contentRef = ref() |
| | | const mouseover = function (): void { |
| | | // 计ç®spanæ ç¾çoffsetWidthä¸ç¶çåå
ç´ çoffsetWidthï¼æ¥å¤ætooltipæ¯å¦æ¾ç¤º |
| | | visible.value = |
| | | contentRef.value.offsetWidth > contentRef.value.parentNode.offsetWidth ? true : false |
| | | } |
| | | const mouseleave = function (): void { |
| | | visible.value = false |
| | | } |
| | | </script> |
| | | <style lang="scss" scoped> |
| | | .content { |
| | | text-overflow: ellipsis; |
| | | word-break: keep-all; |
| | | white-space: nowrap; |
| | | overflow: hidden; |
| | | } |
| | | </style> |
| | |
| | | .flows_pick { |
| | | width: 100%; |
| | | height: 108px; |
| | | height: 66px; |
| | | box-shadow: 0 0 0 1px var(--cs-input-border-color, var(--cs-border-color)) |
| | | inset; |
| | | border-radius: var(--cs-input-border-radius, var(--cs-border-radius-base)); |
| | |
| | | background-color: #fff; |
| | | display: flex; |
| | | justify-content: flex-start; |
| | | padding: 10px 10px; |
| | | padding: 7px; |
| | | overflow: auto; |
| | | flex-wrap: wrap; |
| | | padding-right: 0; |
| | | align-items: flex-start; |
| | | align-content: flex-start; |
| | | padding-bottom: 0px; |
| | | cursor: no-drop; |
| | | > div { |
| | | margin-bottom: 5px; |
| | | } |
| | | |
| | | &:hover { |
| | | box-shadow: 0 0 0 1px #c0c4cc inset; |
| | | } |
| | | } |
| | | .disabled { |
| | | background-color: #f6f7fa; |
| | | background-color: var(--cs-disabled-bg-color); |
| | | } |
| | | .flowTag { |
| | | display: inline; |
| | | color: #b7bac0; |
| | | margin-top: -10px; |
| | | margin-top: -7px; |
| | | margin-left: 4px; |
| | | color: #5c5c5c; |
| | | } |
| | |
| | | import { defineComponent } from 'vue' |
| | | import styles from './Flow.module.scss' |
| | | import Tag from '../Tag/Tag' |
| | | import { scope } from '@/libs/Language/Language' |
| | | |
| | | export default defineComponent({ |
| | | name: 'æµç¨æ¾ç¤ºtag', |
| | | props: { |
| | |
| | | type: Boolean, |
| | | default: false, |
| | | }, |
| | | LanguageScopeKey: { |
| | | type: String, |
| | | default: '', |
| | | }, |
| | | placeholder: { |
| | | type: String, |
| | | default: '', |
| | | }, |
| | | }, |
| | | emits: ['click'], |
| | | setup(props, { attrs, slots, emit }) { |
| | | const _t = scope(props.LanguageScopeKey) |
| | | return () => { |
| | | return ( |
| | | <div |
| | |
| | | }} |
| | | > |
| | | {!props.modelValue?.length ? ( |
| | | <span class={styles.flowTag}>å
³èæµç¨</span> |
| | | <span class={styles.flowTag}>{props.placeholder}</span> |
| | | ) : ( |
| | | props.modelValue.map((item: any) => { |
| | | return ( |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | .relationDialog { |
| | | width: 100%; |
| | | } |
| | | .select { |
| | | font-size: 14px; |
| | | font-family: PingFang SC, PingFang SC; |
| | | font-weight: 400; |
| | | color: #5a84ff; |
| | | cursor: pointer; |
| | | } |
| | | |
| | | .header { |
| | | width: 100%; |
| | | height: 35px; |
| | | display: flex; |
| | | justify-content: flex-start; |
| | | align-items: center; |
| | | margin-bottom: 10px; |
| | | .key { |
| | | font-size: 12px; |
| | | font-family: PingFang SC, PingFang SC; |
| | | font-weight: 400; |
| | | color: #35363b; |
| | | margin-right: 10px; |
| | | } |
| | | } |
| | | |
| | | .table { |
| | | width: 100%; |
| | | height: calc(100% - 50px); |
| | | :global( |
| | | .information-table |
| | | .vxe-table--body |
| | | tbody |
| | | tr |
| | | td:nth-of-type(2) |
| | | .over-ellipsis |
| | | ) { |
| | | white-space: pre; |
| | | } |
| | | } |
| | | |
| | | .selected { |
| | | cursor: pointer; |
| | | font-size: 14px; |
| | | font-family: PingFang SC, PingFang SC; |
| | | font-weight: 400; |
| | | color: #5a84ff; |
| | | &:hover { |
| | | color: #5a84ff; |
| | | opacity: 0.6; |
| | | } |
| | | } |
| | | |
| | | .selectVariable { |
| | | :global(.cs-input__inner) { |
| | | padding-right: 10px; |
| | | } |
| | | } |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | import Dialog from '@/components/BaseDialog/index.vue' |
| | | const BaseDialog: any = Dialog |
| | | import { computed, defineComponent, inject, ref, SetupContext } from 'vue' |
| | | import styles from './FlowContextDialog.module.scss' |
| | | import { useRelationMaterial } from '@/hooks//Dialog' |
| | | import BaseTable from '@/components/Table/Table' |
| | | import { columns } from './config' |
| | | import Search from '@/components/Search/Search' |
| | | import { _t } from '@/libs/Language/Language' |
| | | import { ElMessage } from 'element-plus' |
| | | import { get } from 'lodash' |
| | | |
| | | export default defineComponent({ |
| | | name: 'æµç¨ä¸ä¸æ', |
| | | props: { |
| | | modelValue: { |
| | | type: String, |
| | | default: '', |
| | | }, |
| | | title: { |
| | | type: String, |
| | | default: '', |
| | | }, |
| | | |
| | | readonly: { |
| | | type: Boolean, |
| | | default: false, |
| | | }, |
| | | type: { |
| | | type: String, |
| | | default: 'input', |
| | | }, |
| | | clearable: { |
| | | type: Boolean, |
| | | default: false, |
| | | }, |
| | | flowType: { |
| | | type: String, |
| | | }, |
| | | // ç¨æ¥å®ä¹æ°æ®ç»æ |
| | | dyStruct: { |
| | | type: Boolean, |
| | | default: false, |
| | | }, |
| | | radio: { |
| | | type: Boolean, |
| | | default: false, |
| | | }, |
| | | }, |
| | | emits: ['update:modelValue', 'close', 'confirm'], |
| | | setup(props: any, ctx: SetupContext) { |
| | | const modelValue = computed({ |
| | | get() { |
| | | return props.modelValue |
| | | }, |
| | | set(v) { |
| | | ctx.emit('update:modelValue', v) |
| | | }, |
| | | }) |
| | | const flowType = props.flowType || inject('flowType') |
| | | const data = ref([]) |
| | | const visible = ref(false) |
| | | const tableRef = ref() |
| | | const search = ref('') |
| | | const selected = ref('') |
| | | const originData = ref([]) |
| | | const current = ref() |
| | | const dyModel = computed(() => { |
| | | if (props.dyStruct) { |
| | | return modelValue.value |
| | | } |
| | | return modelValue |
| | | }) |
| | | const onSelect = () => { |
| | | visible.value = true |
| | | } |
| | | const onClose = () => { |
| | | visible.value = false |
| | | } |
| | | const onConfirm = () => { |
| | | visible.value = false |
| | | if (props.dyStruct) { |
| | | modelValue.value = { |
| | | name: current.value?.description, |
| | | value: selected.value, |
| | | } |
| | | } else { |
| | | modelValue.value = selected.value |
| | | } |
| | | } |
| | | const onSearch = (val: string) => { |
| | | if (val) { |
| | | data.value = originData.value.filter((item: any) => { |
| | | return ( |
| | | item.name.includes(val) || |
| | | item.value.includes(val) || |
| | | item.description.includes(val) |
| | | ) |
| | | }) |
| | | } else { |
| | | data.value = originData.value |
| | | } |
| | | } |
| | | const onCheck = (row: any[]) => { |
| | | if (row.length > 1) { |
| | | return ElMessage.warning('ä»
æ¯æå¯¹ä¸æ¡æ°æ®è¿è¡æä½!') |
| | | } |
| | | if (row[0]) { |
| | | selected.value = row[0].value |
| | | current.value = row[0] |
| | | } |
| | | } |
| | | const onOpen = () => { |
| | | if (dyModel.value) { |
| | | tableRef.value?.setSelectRow([dyModel.value?.value]) |
| | | } |
| | | } |
| | | |
| | | const onLoad = () => { |
| | | originData.value = data.value |
| | | } |
| | | |
| | | const Input = () => { |
| | | const readonly = |
| | | typeof props.readonly?.value === 'boolean' |
| | | ? (props.readonly?.value as boolean) |
| | | : (props.readonly as boolean) |
| | | return ( |
| | | <el-input |
| | | v-model={dyModel.value.value} |
| | | clearable={props.clearable} |
| | | class={styles.selectVariable} |
| | | placeholder={_t('è¯·éæ©')} |
| | | readonly={readonly} |
| | | title={props.title} |
| | | suffix-icon={ |
| | | <el-button |
| | | link |
| | | type="primary" |
| | | size="small" |
| | | style="margin-right: 10px;" |
| | | onClick={onSelect} |
| | | > |
| | | {_t('éæ©')} |
| | | </el-button> |
| | | } |
| | | ></el-input> |
| | | ) |
| | | } |
| | | return () => { |
| | | return ( |
| | | <div class={styles.relationDialog}> |
| | | <Input /> |
| | | <BaseDialog |
| | | width="1200px" |
| | | height="536px" |
| | | v-model={visible.value} |
| | | title={_t('æµç¨ä¸ä¸æ')} |
| | | onClose={onClose} |
| | | onConfirm={onConfirm} |
| | | onOpen={onOpen} |
| | | destroy-on-close |
| | | append-to-body |
| | | > |
| | | <div class={styles.header}> |
| | | <label class={styles.key}>{_t('å
³é®å')}</label> |
| | | <Search |
| | | v-model={search.value} |
| | | field="filter" |
| | | onConfirm={onSearch} |
| | | placeholder={_t('请è¾å
¥å
³é®å')} |
| | | /> |
| | | </div> |
| | | <div class={styles.table}> |
| | | <BaseTable |
| | | url={`/api/v1/flowmanagement/flowdesign/flowitemkey`} |
| | | ref={tableRef} |
| | | params={{ |
| | | flowType: flowType, |
| | | }} |
| | | columns={columns} |
| | | size="mini" |
| | | v-model:dataSource={data.value} |
| | | isChecked={true} |
| | | isVScroll |
| | | onCheck={onCheck} |
| | | isStop={true} |
| | | id="value" |
| | | isHidePagination={true} |
| | | onLoad={onLoad} |
| | | radio={props.radio} |
| | | /> |
| | | </div> |
| | | </BaseDialog> |
| | | </div> |
| | | ) |
| | | } |
| | | }, |
| | | }) |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | export const columns = [ |
| | | { |
| | | title: 'åºå·', |
| | | field: 'seq', |
| | | type: 'seq', |
| | | }, |
| | | { |
| | | title: 'åç§°', |
| | | field: 'name', |
| | | }, |
| | | { |
| | | title: 'æ è¯', |
| | | field: 'value', |
| | | }, |
| | | { |
| | | title: 'æè¿°', |
| | | field: 'description', |
| | | }, |
| | | { |
| | | title: 'æ°æ®ç±»å', |
| | | field: 'type', |
| | | }, |
| | | ] |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | .logicFlow { |
| | | width: 100%; |
| | | height: 100%; |
| | | position: relative; |
| | | .beautify { |
| | | position: absolute; |
| | | right: 250px; |
| | | top: 30px; |
| | | z-index: 1; |
| | | } |
| | | .xmlbeautify { |
| | | position: absolute; |
| | | right: 150px; |
| | | top: 30px; |
| | | z-index: 1; |
| | | } |
| | | } |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | import { |
| | | defineComponent, |
| | | SetupContext, |
| | | onMounted, |
| | | reactive, |
| | | ref, |
| | | computed, |
| | | provide, |
| | | } from 'vue' |
| | | import styles from './G6Flow.module.scss' |
| | | import { |
| | | fittingString, |
| | | getFlowDataToXml, |
| | | getJsonByXml, |
| | | getLogicFLowStruct, |
| | | generateFlowXml, |
| | | } from './core/transformHelp' |
| | | import { getFlowXml, getFlowData, saveFlowData } from '@/api/logic-flow' |
| | | import G6Renderer from './components/Renderer/Renderer' |
| | | import Canvas from './components/Canvas/Canvas' |
| | | import { createStore, resetStore } from './core/store' |
| | | import { FlowType } from './type' |
| | | import Tools from './components/Tools/Tools' |
| | | import { cloneDeep, uniqBy } from 'lodash' |
| | | import { v4 as uuidv4 } from 'uuid' |
| | | import NodeDrawer from './components/NodeDrawer/NodeDrawer' |
| | | import EdgeDrawer from './components/EdgeDrawer/EdgeDrawer' |
| | | import { nodeFontSize } from './components/Nodes' |
| | | import { ConditionType } from './core/enum' |
| | | import { ElMessage } from 'element-plus' |
| | | import { baseStore } from './core/store' |
| | | import { _t } from '@/libs/Language/Language' |
| | | |
| | | interface NodeDrawerConfig { |
| | | visible: boolean |
| | | title: string |
| | | model: Record<string, any> |
| | | } |
| | | export default defineComponent({ |
| | | name: 'G6Flow', |
| | | props: { |
| | | flowType: { |
| | | type: [String, Number], |
| | | default: '', |
| | | }, |
| | | height: { |
| | | type: [String, Number], |
| | | default: 750, |
| | | }, |
| | | isEdit: { |
| | | type: Boolean, |
| | | default: false, |
| | | }, |
| | | flowName: { |
| | | type: String, |
| | | }, |
| | | }, |
| | | setup(props, { slots, attrs, expose }: SetupContext) { |
| | | const { |
| | | graphEvent, |
| | | selected, |
| | | flowBaseConfig, |
| | | edgeMap, |
| | | nodeMap, |
| | | flowConfig, |
| | | } = createStore() |
| | | const graphData = ref<FlowType | null>(null) |
| | | const g6RenderRef = ref<any>() |
| | | const selectedEdgeToolType = ref<string>('') |
| | | |
| | | const isEdit = computed(() => { |
| | | return props.isEdit |
| | | }) |
| | | const nodeData = ref<Record<string, any>[]>([]) |
| | | const edgeData = ref<Record<string, any>[]>([]) |
| | | const nodeItem = ref<Record<string, any> | null>(null) |
| | | const nodeDrawerConfig = reactive<NodeDrawerConfig>({ |
| | | visible: false, |
| | | title: _t('èç¹é
ç½®'), |
| | | model: {}, |
| | | }) |
| | | provide('flowType', props.flowType) |
| | | |
| | | const sortNodeDataUniq = (Activities: any[]) => { |
| | | const data = Activities.sort( |
| | | (a: { sort: number }, b: { sort: number }) => { |
| | | return a.sort - b.sort |
| | | } |
| | | ) |
| | | return uniqBy(data, 'type') |
| | | } |
| | | const initData = async () => { |
| | | selected.value = null |
| | | graphData.value = null |
| | | resetStore() |
| | | const res = await getFlowXml(props.flowType) |
| | | const json = getJsonByXml(res.content, props.flowName) |
| | | flowConfig.type = res.type |
| | | flowConfig.version = res.version |
| | | flowBaseConfig.value = { |
| | | type: res.type, |
| | | version: flowConfig.version, |
| | | name: props.flowName, |
| | | } |
| | | graphData.value = getLogicFLowStruct(json) |
| | | |
| | | const data = await Promise.all([ |
| | | getFlowData('Activities'), |
| | | getFlowData('Transitions'), |
| | | ]) |
| | | |
| | | const Activities = sortNodeDataUniq(data[0].Activities) |
| | | const Transitions = sortNodeDataUniq(data[1].Transitions) |
| | | nodeData.value = Activities |
| | | edgeData.value = Transitions |
| | | // edgeMap |
| | | Transitions.forEach((transition) => { |
| | | edgeMap.set(transition.type, transition) |
| | | }) |
| | | // nodeMap |
| | | Activities.forEach((activity) => { |
| | | nodeMap.set(activity.type, activity) |
| | | }) |
| | | } |
| | | |
| | | const onAutoLayout = () => { |
| | | g6RenderRef.value?.autoLayout() |
| | | } |
| | | |
| | | const onDrop = (event: DragEvent) => { |
| | | if (nodeItem.value) { |
| | | g6RenderRef.value?.addNode(nodeItem.value, { |
| | | x: event.x, |
| | | y: event.y, |
| | | }) |
| | | } |
| | | } |
| | | |
| | | const onDragstart = (node: Event) => { |
| | | nodeItem.value = node |
| | | } |
| | | |
| | | const onToolsEdgeClick = (type: string) => { |
| | | selectedEdgeToolType.value = type |
| | | } |
| | | |
| | | const onCopy = (model: any, isShow: any) => { |
| | | if (g6RenderRef.value) { |
| | | const { flowMap, flowNodeMap } = baseStore |
| | | const graph = g6RenderRef.value.getGraph() |
| | | const newModel = cloneDeep(model) |
| | | const label = |
| | | newModel.properties.Name + |
| | | '_' + |
| | | parseInt(String(Math.random() * 10000)) |
| | | newModel.id = uuidv4() |
| | | newModel.x = model.x + 10 |
| | | newModel.y = model.y + 10 |
| | | newModel.name = label |
| | | newModel.properties = { |
| | | ...newModel.properties, |
| | | Name: label, |
| | | label: label, |
| | | name: label, |
| | | oldId: label, |
| | | } |
| | | newModel.label = fittingString(label, 195, nodeFontSize + 2) |
| | | flowMap.set(label, newModel) |
| | | flowNodeMap.set(newModel.id, newModel) |
| | | graph?.addItem('node', newModel) |
| | | } |
| | | isShow.value = false |
| | | } |
| | | |
| | | const onDelete = (model: any, isShow: any) => { |
| | | if (g6RenderRef.value) { |
| | | const graph = g6RenderRef.value.getGraph() |
| | | const item = graph?.findById(model.id) |
| | | graph?.removeItem(item) |
| | | } |
| | | isShow.value = false |
| | | } |
| | | |
| | | const onViewDialog = (model: any, isShow: any) => { |
| | | nodeDrawerConfig.visible = true |
| | | nodeDrawerConfig.model = model |
| | | isShow.value = false |
| | | } |
| | | |
| | | const clear = () => { |
| | | nodeDrawerConfig.model = {} |
| | | graphEvent.clearAllState() |
| | | graphSave(true) |
| | | } |
| | | |
| | | const graphSave = async (isTemp: boolean = false) => { |
| | | const graph = g6RenderRef.value.getGraph() |
| | | const xml = generateFlowXml(graph) |
| | | const data = { |
| | | ...flowConfig, |
| | | content: xml, |
| | | version: flowConfig.version || 1, |
| | | } |
| | | await saveFlowData(data, isTemp) |
| | | !isTemp && ElMessage.success(_t('ä¿åæå')) |
| | | } |
| | | |
| | | expose({ graphSave }) |
| | | onMounted(initData) |
| | | |
| | | return () => { |
| | | if (!graphData.value) return <el-empty description={_t('ææ æ°æ®')} /> |
| | | const Drawer = graphEvent.type.value === 'edge' ? EdgeDrawer : NodeDrawer |
| | | const contextMenu = computed<any[]>(() => { |
| | | const menu: any[] = [ |
| | | { |
| | | type: 'view', |
| | | label: _t('æ¥ç屿§'), |
| | | fn: onViewDialog, |
| | | divided: true, |
| | | disabled: false, |
| | | icon: 'viewProps', |
| | | }, |
| | | ] |
| | | if (isEdit.value) { |
| | | if (graphEvent.type.value === 'node') { |
| | | menu.push({ |
| | | label: _t('å¤å¶'), |
| | | fn: onCopy, |
| | | divided: true, |
| | | icon: 'copy', |
| | | type: 'copy', |
| | | }) |
| | | } |
| | | menu.push({ |
| | | label: _t('å é¤'), |
| | | fn: onDelete, |
| | | type: 'del', |
| | | divided: true, |
| | | disabled: false, |
| | | icon: 'delete-menu', |
| | | }) |
| | | } |
| | | return menu |
| | | }) |
| | | return ( |
| | | <div class={styles.logicFlow}> |
| | | {isEdit.value ? ( |
| | | <Tools |
| | | nodeData={nodeData.value} |
| | | edgeData={edgeData.value} |
| | | onDragstart={onDragstart} |
| | | onEdgeClick={onToolsEdgeClick} |
| | | /> |
| | | ) : null} |
| | | |
| | | <Drawer |
| | | title={nodeDrawerConfig.title} |
| | | v-model={nodeDrawerConfig.visible} |
| | | isEdit={isEdit.value} |
| | | model={ |
| | | nodeDrawerConfig.visible ? nodeDrawerConfig.model : undefined |
| | | } |
| | | onConfirm={clear} |
| | | onClose={clear} |
| | | graph={g6RenderRef.value?.getGraph()} |
| | | type={graphEvent.type.value} |
| | | edgeData={edgeData.value} |
| | | ></Drawer> |
| | | <Canvas |
| | | onDrop={onDrop} |
| | | grid={{ visible: true }} |
| | | minimap={true} |
| | | height={props.height} |
| | | > |
| | | <G6Renderer |
| | | ref={g6RenderRef} |
| | | graphData={graphData.value} |
| | | drag-node={isEdit.value} |
| | | click-select={isEdit.value} |
| | | editing={isEdit.value} |
| | | zoom-canvas |
| | | drag-canvas |
| | | edgeType={!!selectedEdgeToolType.value} |
| | | create-edge={!!selectedEdgeToolType.value} |
| | | edgeContextMenu={contextMenu.value} |
| | | flowName={props.flowName} |
| | | contextMenu={[...contextMenu.value]} |
| | | ></G6Renderer> |
| | | </Canvas> |
| | | </div> |
| | | ) |
| | | } |
| | | }, |
| | | }) |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | import { |
| | | defineComponent, |
| | | Fragment, |
| | | computed, |
| | | Component, |
| | | DefineComponent, |
| | | SetupContext, |
| | | } from 'vue' |
| | | |
| | | export default defineComponent<{ |
| | | grid: Record<string, any> |
| | | minimap: Record<string, any> | boolean |
| | | height?: number |
| | | width?: number |
| | | [key: string]: any |
| | | }>({ |
| | | name: 'Canvas', |
| | | emits: ['drop'], |
| | | setup(props: any, { slots, attrs, emit }: SetupContext) { |
| | | const config = { |
| | | layout: { |
| | | type: 'dagre', |
| | | nodesep: 100, |
| | | ranksep: 40, |
| | | controlPoints: true, |
| | | }, |
| | | fitView: true, |
| | | autoFit: false, |
| | | } |
| | | |
| | | const baseConfig = computed(() => { |
| | | return { |
| | | ...config, |
| | | ...props, |
| | | ...attrs, |
| | | } |
| | | }) |
| | | return () => { |
| | | const Widgets = (slots.default && slots.default()) || [] |
| | | return ( |
| | | <span onDrop={(...arg) => emit('drop', ...arg)}> |
| | | {Widgets.map((Widget: any) => { |
| | | return <Widget {...baseConfig.value} /> |
| | | })} |
| | | </span> |
| | | ) |
| | | } |
| | | }, |
| | | }) |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | .conditionDialog { |
| | | width: 100%; |
| | | display: flex; |
| | | justify-content: space-between; |
| | | align-items: center; |
| | | } |
| | | .dialog { |
| | | width: 100%; |
| | | display: flex; |
| | | justify-content: space-between; |
| | | align-items: center; |
| | | .leftBar { |
| | | width: 208px; |
| | | display: flex; |
| | | justify-content: flex-start; |
| | | align-items: flex-start; |
| | | height: 470px; |
| | | flex-direction: column; |
| | | border: 1px solid #ccc; |
| | | border-radius: 4px; |
| | | overflow-wrap: auto; |
| | | padding: 4px; |
| | | .nodeStyle { |
| | | width: 100%; |
| | | display: flex; |
| | | justify-content: space-between; |
| | | align-items: center; |
| | | font-size: 12px; |
| | | } |
| | | .box { |
| | | margin-left: 0px; |
| | | } |
| | | // .label { |
| | | |
| | | // } |
| | | .tree { |
| | | width: 100%; |
| | | border-radius: 4px; |
| | | } |
| | | } |
| | | |
| | | .content { |
| | | width: calc(100% - 215px); |
| | | height: 470px; |
| | | background-color: #f8f8f8; |
| | | padding: 20px; |
| | | border-radius: 5px; |
| | | position: relative; |
| | | .condition { |
| | | position: absolute; |
| | | left: 0; |
| | | bottom: 0; |
| | | border-top: 1px solid #ddd; |
| | | width: 100%; |
| | | font-size: 13px; |
| | | display: flex; |
| | | align-items: center; |
| | | justify-content: flex-start; |
| | | flex-wrap: wrap; |
| | | padding-left: 10px; |
| | | } |
| | | } |
| | | } |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | import { defineComponent, computed, ref, nextTick } from 'vue' |
| | | import styles from './ConditionDialog.module.scss' |
| | | import BaseDialog from '@/components/BaseDialog/index.vue' |
| | | import DyForm from '@/components/DyForm/DyForm' |
| | | import { CirclePlus, Delete } from '@element-plus/icons-vue' |
| | | import NodeDialog from '../NodeDialog/NodeDialog' |
| | | import { |
| | | ConditionType, |
| | | CompositeCondition, |
| | | ConditionItemType, |
| | | } from '../../core/enum' |
| | | import { Condition } from '../../type' |
| | | import { v4 as uuidv4 } from 'uuid' |
| | | import { cloneDeep } from 'lodash' |
| | | import { _t } from '@/libs/Language/Language' |
| | | interface CompositeCondition { |
| | | Expression: string |
| | | Label: string |
| | | NOT: boolean |
| | | Operator: string |
| | | Property: string |
| | | Value: string |
| | | // Value: { |
| | | // '@_xsi:type': string |
| | | // '#text': string | number // Assuming "#text" can be either string or number |
| | | // } |
| | | } |
| | | export default defineComponent({ |
| | | name: 'æ¡ä»¶é', |
| | | props: { |
| | | formItemProps: { |
| | | type: Array, |
| | | default: [], |
| | | }, |
| | | conditionOptions: { |
| | | type: Array, |
| | | default: [], |
| | | }, |
| | | formData: { |
| | | type: Object, |
| | | default: () => ({}), |
| | | }, |
| | | onConditionChange: { |
| | | type: Function, |
| | | default: () => null, |
| | | }, |
| | | getCondition: { |
| | | type: Function, |
| | | default: () => null, |
| | | }, |
| | | }, |
| | | emits: ['update:modelValue', 'update:formData', 'updateFormData'], |
| | | |
| | | setup(props, ctx) { |
| | | const edgeType = ref('') |
| | | const visible = ref(false) |
| | | const formRef = ref(null) |
| | | const dataSource = ref([]) |
| | | const treeRef = ref() |
| | | const nodeVisible = ref(false) |
| | | const currentFormData = ref({}) |
| | | const formItemProps = ref<any[]>([]) |
| | | const currentNode = ref<{ |
| | | nodeData: { |
| | | children?: any[] |
| | | [key: string]: any |
| | | } | null |
| | | }>({ |
| | | nodeData: null, |
| | | }) |
| | | const formData = ref<Condition | Record<string, any>>({}) |
| | | |
| | | const currentCondition = computed(() => { |
| | | const type = edgeType.value |
| | | return props.getCondition(type, currentFormData.value) |
| | | }) |
| | | /** |
| | | * æ¯å¦æ¯å¤åç±»å |
| | | */ |
| | | const onOpenCondition = () => { |
| | | const nodeId = uuidv4() |
| | | formData.value = cloneDeep(props.formData) |
| | | formData.value.nodeId = nodeId |
| | | formData.value.root = true |
| | | visible.value = true |
| | | nextTick(async () => { |
| | | await handleNodeClick(formData.value as Condition) |
| | | treeRef.value.setCurrentKey(nodeId) |
| | | }) |
| | | } |
| | | |
| | | const onConfirmBtn = () => { |
| | | ctx.emit('updateFormData', formData.value) |
| | | visible.value = false |
| | | } |
| | | |
| | | const onAddNode = (data: Condition) => { |
| | | currentNode.value.nodeData = data |
| | | nodeVisible.value = true |
| | | } |
| | | |
| | | const onDeleteNode = (node: any, data: Condition) => { |
| | | const nodeId = data.nodeId |
| | | if (node.parent) { |
| | | node.parent.data.children = node.parent.data.children.filter( |
| | | (data: Condition) => { |
| | | data.nodeId !== nodeId |
| | | } |
| | | ) |
| | | nextTick(async () => { |
| | | await handleNodeClick(formData.value as Condition) |
| | | }) |
| | | } |
| | | } |
| | | |
| | | const handleNodeClick = async (data: Condition | any) => { |
| | | const formItems = await props.onConditionChange( |
| | | data[ConditionType], |
| | | false |
| | | ) |
| | | formItemProps.value = [ |
| | | { |
| | | label: _t('æ¡ä»¶'), |
| | | prop: ConditionType, |
| | | clearable: true, |
| | | el: 'select', |
| | | placeholder: _t('è¯·éæ©'), |
| | | options: props.conditionOptions, |
| | | disabled: true, |
| | | }, |
| | | ...formItems, |
| | | ] |
| | | currentFormData.value = data |
| | | edgeType.value = data[ConditionType] |
| | | setCurrentKey(data.nodeId) |
| | | } |
| | | // èç¹ç±»åå¼¹çª |
| | | |
| | | const onConditionDialog = async (data: Condition) => { |
| | | const nodeData = currentNode.value.nodeData |
| | | if (nodeData) { |
| | | data.nodeId = uuidv4() |
| | | nodeData.children = nodeData.children || [] |
| | | nodeData.children.push(data) |
| | | await handleNodeClick(data) |
| | | setCurrentKey(data.nodeId) |
| | | } |
| | | } |
| | | |
| | | const setCurrentKey = (nodeId: string) => { |
| | | nextTick(() => { |
| | | treeRef.value.setCurrentKey(nodeId) |
| | | }) |
| | | } |
| | | |
| | | return () => { |
| | | return ( |
| | | <div class={styles.conditionDialog}> |
| | | {/* <el-input |
| | | readonly |
| | | placeholder="è¯·éæ©æ¡ä»¶é" |
| | | v-model={condition.value} |
| | | onClick={onOpenCondition} |
| | | /> */} |
| | | <el-button |
| | | onClick={onOpenCondition} |
| | | style="width: 200px;" |
| | | size="small" |
| | | > |
| | | {_t('éå')} |
| | | </el-button> |
| | | <NodeDialog |
| | | options={props.conditionOptions} |
| | | v-model:visible={nodeVisible.value} |
| | | onConfirm={onConditionDialog} |
| | | ></NodeDialog> |
| | | |
| | | <BaseDialog |
| | | width="800px" |
| | | title={_t('æ¡ä»¶é')} |
| | | v-model={visible.value} |
| | | onClose={() => (visible.value = false)} |
| | | onConfirm={onConfirmBtn} |
| | | destroy-on-close |
| | | > |
| | | {formData.value.nodeId ? ( |
| | | <div class={styles.dialog}> |
| | | <div class={styles.leftBar}> |
| | | <el-tree |
| | | style="max-width: 200px" |
| | | ref={treeRef} |
| | | class={styles.tree} |
| | | data={[formData.value]} |
| | | node-key="nodeId" |
| | | onNodeClick={handleNodeClick} |
| | | default-expand-all |
| | | highlight-current |
| | | expand-on-click-node={false} |
| | | v-slots={{ |
| | | default: ({ node, data }: any) => { |
| | | return ( |
| | | <div class={styles.nodeStyle}> |
| | | <span class={styles.label}> |
| | | {data.Label || data.label || _t('请è¾å
¥æ ç¾å
容')} |
| | | </span> |
| | | <div class={styles.tools}> |
| | | {data[ConditionType] === CompositeCondition ? ( |
| | | <el-button |
| | | onClick={() => onAddNode(data)} |
| | | type="primary" |
| | | link |
| | | > |
| | | <el-icon> |
| | | <CirclePlus /> |
| | | </el-icon> |
| | | </el-button> |
| | | ) : null} |
| | | <el-button |
| | | onClick={() => onDeleteNode(node, data)} |
| | | class={styles.box} |
| | | type="primary" |
| | | link |
| | | disabled={data.root} |
| | | > |
| | | <el-icon> |
| | | <Delete /> |
| | | </el-icon> |
| | | </el-button> |
| | | </div> |
| | | </div> |
| | | ) |
| | | }, |
| | | }} |
| | | ></el-tree> |
| | | </div> |
| | | <div class={styles.content}> |
| | | <DyForm |
| | | // ref={formConditionRef} |
| | | isLine={true} |
| | | formItemProps={formItemProps.value} |
| | | v-model:formData={currentFormData.value} |
| | | labelWidth="140px" |
| | | ></DyForm> |
| | | <div class={styles.condition}>{currentCondition.value}</div> |
| | | </div> |
| | | </div> |
| | | ) : null} |
| | | </BaseDialog> |
| | | </div> |
| | | ) |
| | | } |
| | | }, |
| | | }) |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | .formDrawer { |
| | | margin-left: 40px; |
| | | } |
| | | .drawContent { |
| | | position: relative; |
| | | width: 100%; |
| | | height: 100%; |
| | | .condition { |
| | | position: absolute; |
| | | left: 0; |
| | | bottom: 0; |
| | | border-top: 1px solid #ddd; |
| | | width: 100%; |
| | | height: 40px; |
| | | padding: 10px; |
| | | color: #333; |
| | | font-size: 13px; |
| | | display: flex; |
| | | align-items: center; |
| | | justify-content: flex-start; |
| | | flex-wrap: wrap; |
| | | } |
| | | } |
| | | .edgeDialogTitle { |
| | | font-size: 18px; |
| | | font-family: Source Han Sans CN, Source Han Sans CN; |
| | | font-weight: bold; |
| | | color: #464e54; |
| | | line-height: 0px; |
| | | > img { |
| | | margin-left: 10px; |
| | | } |
| | | } |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | import { |
| | | computed, |
| | | defineComponent, |
| | | ref, |
| | | onMounted, |
| | | watch, |
| | | SetupContext, |
| | | PropType, |
| | | nextTick, |
| | | } from 'vue' |
| | | import BaseDrawer from '@/components/BaseDrawer/BaseDrawer' |
| | | import DyForm from '@/components/DyForm/DyForm' |
| | | import { getFlowDetail, getFlowData } from '@/api/logic-flow' |
| | | import { FormItemPropType } from '@/components/DyForm/DyForm.d' |
| | | import ElInputNumber from 'element-plus/es/components/input-number/index' |
| | | import { cloneDeep, debounce, isFunction, sortBy, throttle } from 'lodash' |
| | | import styles from './EdgeDrawer.module.scss' |
| | | import { fittingString } from '../../core/transformHelp' |
| | | import { width, fontSize } from '../Nodes' |
| | | import ConditionDialog from '../ConditionDialog/ConditionDialog' |
| | | import { ConditionType, ValueText, CompositeCondition } from '../../core/enum' |
| | | import { Condition } from '../../type' |
| | | import { injectStore } from '../../core/store' |
| | | import Icon from '@/components/Icon/Icon' |
| | | import FlowContextDialog from '@/components/FlowContextDialog/FlowContextDialog' |
| | | import { WidgetNameType } from '../Models/WidgetTypeByEnum' |
| | | import { _t } from '@/libs/Language/Language' |
| | | |
| | | export default defineComponent({ |
| | | name: 'NodeDrawer', |
| | | props: { |
| | | title: { |
| | | type: String, |
| | | }, |
| | | model: { |
| | | type: Object, |
| | | default: () => ({}), |
| | | }, |
| | | modelValue: { |
| | | type: Boolean, |
| | | }, |
| | | graph: { |
| | | type: Object, |
| | | default: null, |
| | | }, |
| | | type: { |
| | | type: String, |
| | | default: '', |
| | | }, |
| | | edgeData: { |
| | | type: Array, |
| | | default: [], |
| | | }, |
| | | isEdit: { |
| | | type: Boolean, |
| | | default: false, |
| | | }, |
| | | }, |
| | | emits: ['update:modelValue', 'close', 'confirm', 'update:title'], |
| | | setup(props, { slots, emit }) { |
| | | const { flowMap, flowNodeMap, edgeMap } = injectStore() |
| | | const isOpen = ref(false) |
| | | const edgeType = ref('') |
| | | const title = ref(props.title) |
| | | const formRef = ref<any>(null) |
| | | const formConditionRef = ref<any>(null) |
| | | const conditionFormItemProps = ref<FormItemPropType>([]) |
| | | const formDataCondition = ref({}) |
| | | const conditionConfig = ref<Record<string, any>>({ |
| | | has: false, |
| | | item: {}, |
| | | }) |
| | | |
| | | const conditionOptions = ref< |
| | | { |
| | | label: string |
| | | value: string |
| | | }[] |
| | | >([]) |
| | | |
| | | const visible = computed({ |
| | | get: () => props.modelValue, |
| | | set: (value) => { |
| | | emit('update:modelValue', value) |
| | | }, |
| | | }) |
| | | const model = computed(() => props.model) |
| | | |
| | | const currentCondition = computed(() => { |
| | | const data = formData.value?.Condition || {} |
| | | |
| | | return getCondition(edgeType.value, data) |
| | | }) |
| | | |
| | | const currentTip = computed(() => { |
| | | const type = model.value?.properties?.[ConditionType] |
| | | return edgeMap.get(type)?.description |
| | | }) |
| | | |
| | | const formData: Record<string, any> = ref() |
| | | |
| | | const formItemProps = ref<FormItemPropType>([]) |
| | | |
| | | const customWidgetMap = { |
| | | inputNumber: ElInputNumber, |
| | | flowItemKey: FlowContextDialog, |
| | | |
| | | condition: (props: any, { attrs }: SetupContext) => ( |
| | | <ConditionDialog |
| | | formItemProps={conditionFormItemProps.value} |
| | | conditionOptions={conditionOptions.value} |
| | | onConditionChange={onConditionChange} |
| | | onUpdateFormData={onUpdateFormData} |
| | | getCondition={getCondition} |
| | | v-model:formData={formData.value.Condition} |
| | | {...props} |
| | | {...attrs} |
| | | /> |
| | | ), |
| | | } |
| | | |
| | | const onClose = () => { |
| | | visible.value = false |
| | | isOpen.value = false |
| | | emit('close') |
| | | } |
| | | |
| | | const onUpdateFormData = (data: Condition) => { |
| | | formData.value.Condition = data |
| | | } |
| | | |
| | | const onConfirm = () => { |
| | | const graph = props.graph |
| | | const item = graph.findById(model.value.id) |
| | | const modelData = cloneDeep(model.value) |
| | | modelData.properties = formData.value |
| | | modelData.label = formData.value?.Condition?.Label || formData.value.Label |
| | | |
| | | item.update(modelData) |
| | | visible.value = false |
| | | emit('confirm') |
| | | } |
| | | |
| | | const formItemSort = (formItems: FormItemPropType[]) => { |
| | | return sortBy(formItems, ['sort']) |
| | | } |
| | | |
| | | const getConditionsItems = async (type: string) => { |
| | | const data = await getFlowDetail(type) |
| | | return generateFormItems(data.attributes || []) |
| | | } |
| | | |
| | | const getConditions = async () => { |
| | | const data = await getFlowData('Conditions') |
| | | const conditions: Record<string, any> = data.Conditions || [] |
| | | conditionOptions.value = conditions.map((item: any) => { |
| | | let name = item.type === CompositeCondition ? _t('å¤åæ¡ä»¶') : item.name |
| | | return { |
| | | ...item, |
| | | label: name, |
| | | value: item.type, |
| | | tip: item.description, |
| | | } |
| | | }) |
| | | } |
| | | |
| | | const onClearCondition = (val: string) => { |
| | | if (!val) { |
| | | formData.value.Condition = {} |
| | | } |
| | | } |
| | | |
| | | const onConditionChange = async ( |
| | | val: string, |
| | | isNative: boolean = true, |
| | | isSelectChange?: boolean |
| | | ) => { |
| | | const data = await getConditionsItems(val) |
| | | if (isSelectChange) { |
| | | formData.value.Condition.Operator = '' |
| | | } |
| | | if (isNative) { |
| | | edgeType.value = val |
| | | conditionFormItemProps.value = data |
| | | } |
| | | return data |
| | | } |
| | | const getRules = (item: any) => { |
| | | return item.required |
| | | ? [ |
| | | { |
| | | required: true, |
| | | message: item.name, |
| | | trigger: 'blur', |
| | | }, |
| | | ] |
| | | : [] |
| | | } |
| | | const generateFormItems = (attributes: any[]) => { |
| | | const formItems: any[] = [] |
| | | |
| | | attributes?.forEach((item: FormItemPropType) => { |
| | | const placeholder = WidgetNameType[item.propertyType]?.placeholder |
| | | const el = |
| | | WidgetNameType[item.propertyType]?.el || |
| | | WidgetNameType[item.propertyType]?.type |
| | | const type = WidgetNameType[item.propertyType]?.el |
| | | ? WidgetNameType[item.propertyType]?.type |
| | | : undefined |
| | | if (item.propertyType !== 'Condition') { |
| | | const formItem: FormItemPropType = { |
| | | label: item.name, |
| | | // prop: |
| | | // item.propertyType === 'Object' |
| | | // ? `${item.propertyKey}.${ValueText}` |
| | | // : item.propertyKey, |
| | | prop: item.propertyKey, |
| | | readonly: item.readonly, |
| | | el, |
| | | rules: getRules(item), |
| | | tip: item.description || item.name, |
| | | icon: 'wen', |
| | | options: item.propertyData?.map((item: any) => { |
| | | return { |
| | | label: item.name, |
| | | tip: item.description, |
| | | value: item.value, |
| | | } |
| | | }), |
| | | disabled: ['Source', 'Sink'].includes(item.propertyKey), |
| | | defaultValue: item.propertyValue, |
| | | clearable: !item.nullable ? false : true, |
| | | controlsPosition: 'right', |
| | | step: 1, |
| | | min: WidgetNameType[item.propertyType]?.type?.min ?? undefined, |
| | | nullable: item.nullable ? undefined : item.propertyValue, |
| | | valueOnClear: item.nullable ? undefined : item.propertyValue, |
| | | type, |
| | | rows: WidgetNameType[item.propertyType]?.rows || 10, |
| | | } |
| | | |
| | | if (item.pattern) { |
| | | formItem.rules.push({ |
| | | pattern: new RegExp(item.pattern), |
| | | message: item.ruleMessage || _t('æ ¼å¼é误'), |
| | | trigger: 'blur', |
| | | }) |
| | | } |
| | | if (placeholder) { |
| | | formItem.placeholder = placeholder + item.name |
| | | } |
| | | if (item.visible) { |
| | | formItems.push(formItem) |
| | | } |
| | | } else { |
| | | conditionConfig.value.has = true |
| | | conditionConfig.value.item = item |
| | | } |
| | | }) |
| | | |
| | | return formItems |
| | | } |
| | | |
| | | const onOpen = async () => { |
| | | const type = |
| | | model.value?.properties?.[ConditionType] || 'BusinessTransition' |
| | | if (!props.model && type) return |
| | | isOpen.value = true |
| | | getConditions() |
| | | const data = await getFlowDetail(type) |
| | | const attributes = data.attributes || [] |
| | | const formItems: FormItemPropType[] = generateFormItems(attributes) |
| | | if (conditionConfig.value.has) { |
| | | formItems.push({ |
| | | label: conditionConfig.value.item.name, |
| | | clearable: conditionConfig.value.item.nullable ? true : false, |
| | | prop: `Condition.${ConditionType}`, |
| | | el: 'select', |
| | | placeholder: _t('è¯·éæ©'), |
| | | icon: 'wen', |
| | | defaultValue: '', |
| | | rules: getRules(conditionConfig.value.item), |
| | | options: conditionOptions.value, |
| | | tip: conditionConfig.value.item.description, |
| | | onClear: onClearCondition, |
| | | onChange: (val: string, isNative: boolean) => |
| | | onConditionChange(val, isNative, true), |
| | | }) |
| | | } |
| | | title.value = data.name |
| | | formItemProps.value = formItemSort(formItems) |
| | | nextTick(() => { |
| | | formRef.value?.initFormData() |
| | | initEdgeFormData() |
| | | }) |
| | | } |
| | | const initEdgeFormData = () => { |
| | | formData.value = {} |
| | | nextTick(() => { |
| | | const properties = cloneDeep(model.value?.properties) |
| | | const Condition = properties?.Condition || {} |
| | | formData.value = { |
| | | ...formData.value, |
| | | ...properties, |
| | | } |
| | | onConditionChange(Condition[ConditionType]) |
| | | const { oldSourceId, oldTargetId } = formData.value |
| | | |
| | | if (oldSourceId && oldTargetId) { |
| | | const sourceName = flowMap.get(oldSourceId).name |
| | | const sinkName = flowMap.get(oldTargetId).name |
| | | formData.value.Source = sourceName |
| | | formData.value.Sink = sinkName |
| | | } else { |
| | | const sourceName = flowNodeMap.get(model.value?.source)?.name |
| | | const sinkName = flowNodeMap.get(model.value?.target)?.name |
| | | formData.value.Source = sourceName |
| | | formData.value.Sink = sinkName |
| | | } |
| | | }) |
| | | } |
| | | const OperatorType: Record<string, string> = { |
| | | RelOpEqual: '=', |
| | | RelOpLess: '<', |
| | | RelOpLarge: '>', |
| | | RelOpLessEq: '<=', |
| | | RelOpLargeEq: '>=', |
| | | RelOpNotEqual: '!=', |
| | | RelOpContain: 'Contains', |
| | | } |
| | | /** |
| | | * è·åæ¡ä»¶ |
| | | * @returns |
| | | */ |
| | | const getCondition = (type: string, data: Record<string, any>) => { |
| | | const not = data.NOT ? '!' : '' |
| | | const typeMap: Record<string, Function> = { |
| | | PropertyCondition() { |
| | | // PropertyToCompareéè¦æ¯è¾çå¼ |
| | | // Property 屿§ |
| | | // Operator æ¯è¾ç¬¦ |
| | | // Value 常é |
| | | // Parameter åæ°å |
| | | const result = data.PropertyToCompare || data.Value |
| | | const property = |
| | | data.Parameter && data.Property |
| | | ? `${data.Parameter}.${data.Property}` |
| | | : data.Property || data.Parameter |
| | | if (property && OperatorType[data.Operator] && result) { |
| | | return `${not} ${property} ${OperatorType[data.Operator]} ${result}` |
| | | } |
| | | }, |
| | | CompositeCondition() { |
| | | const treeToString: any = (tree: any[]) => { |
| | | if (!Array.isArray(tree) || tree.length === 0) { |
| | | return '' |
| | | } |
| | | |
| | | return tree |
| | | .map((node) => { |
| | | if (node.children && node.children.length > 0) { |
| | | // éå½å¤çåèç¹ |
| | | return `(${treeToString(node.children)})` |
| | | } else { |
| | | // å¤çå½åèç¹ |
| | | return node.condition?.trim() |
| | | } |
| | | }) |
| | | .join(` ${tree[0].operator?.trim()} `) |
| | | } |
| | | const fn = (data: any[], root: boolean = false) => { |
| | | let sumArray: any[] = [] |
| | | data.forEach((item) => { |
| | | const operator = item.Operator |
| | | if (Array.isArray(item.children)) { |
| | | item.children.forEach((composition: any) => { |
| | | const type = composition[ConditionType] |
| | | |
| | | if (type === CompositeCondition) { |
| | | if (composition.children) { |
| | | sumArray.push({ |
| | | children: fn([composition]), |
| | | operator, |
| | | }) |
| | | } |
| | | } else { |
| | | const condition = getCondition(type, composition) |
| | | sumArray.push({ |
| | | condition, |
| | | operator, |
| | | }) |
| | | } |
| | | }) |
| | | } |
| | | }) |
| | | return sumArray |
| | | } |
| | | const condition = treeToString(fn([data])) |
| | | return `${not} ${condition}` |
| | | }, |
| | | ChoiceCondition() { |
| | | const name = data.ActivityRowName |
| | | const choice = data.Choice |
| | | if (name && choice) { |
| | | return `${not} ${name}.Choice = ${choice}` |
| | | } |
| | | }, |
| | | TableCondition() { |
| | | const name = data.PropertyName |
| | | const operator = OperatorType[data.Operator] |
| | | const value = data.Value |
| | | if (name && operator && value) { |
| | | return `${not} ${name} ${operator} ${value}` |
| | | } |
| | | }, |
| | | XMLCondition() { |
| | | const parameter = data.Parameter |
| | | const prefix = data.Prefix |
| | | const xPath = data.XPath |
| | | if (parameter && prefix && xPath) { |
| | | return `${not} ${parameter}[${prefix}:${xPath}].Result>0` |
| | | } |
| | | }, |
| | | } |
| | | const fn = typeMap[type] |
| | | return isFunction(fn) && fn() |
| | | } |
| | | |
| | | onMounted(() => { |
| | | if (!isOpen.value) { |
| | | onOpen() |
| | | } |
| | | }) |
| | | |
| | | return () => { |
| | | return ( |
| | | <BaseDrawer |
| | | onClose={onClose} |
| | | onConfirm={onConfirm} |
| | | onOpen={onOpen} |
| | | width="700px" |
| | | v-model={visible.value} |
| | | submitDisabled={!formItemProps.value.length || !props.isEdit} |
| | | destroy-on-close |
| | | v-slots={{ |
| | | title: () => { |
| | | return ( |
| | | <div class={styles.edgeDialogTitle}> |
| | | {title.value || model.value.label} |
| | | <el-tooltip |
| | | effect="dark" |
| | | content={currentTip.value} |
| | | placement="top" |
| | | > |
| | | <Icon icon="wen" /> |
| | | </el-tooltip> |
| | | </div> |
| | | ) |
| | | }, |
| | | }} |
| | | > |
| | | <div class={styles.drawContent}> |
| | | {formItemProps.value.length ? ( |
| | | <DyForm |
| | | ref={formRef} |
| | | customWidgetMap={customWidgetMap} |
| | | formItemProps={formItemProps.value} |
| | | v-model:formData={formData.value} |
| | | labelWidth="140px" |
| | | ></DyForm> |
| | | ) : ( |
| | | <el-empty image-size={200} description={_t('ææ æ°æ®')} /> |
| | | )} |
| | | {conditionConfig.value.has ? ( |
| | | <div class={styles.formDrawer}> |
| | | <DyForm |
| | | ref={formConditionRef} |
| | | customWidgetMap={customWidgetMap} |
| | | formItemProps={conditionFormItemProps.value} |
| | | v-model:formData={formData.value.Condition} |
| | | labelWidth="140px" |
| | | ></DyForm> |
| | | </div> |
| | | ) : null} |
| | | |
| | | <div class={styles.condition}>{currentCondition.value}</div> |
| | | </div> |
| | | </BaseDrawer> |
| | | ) |
| | | } |
| | | }, |
| | | }) |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | .contextMenuItemC { |
| | | width: 100%; |
| | | height: 100%; |
| | | display: flex; |
| | | justify-content: flex-start; |
| | | align-items: center; |
| | | padding: 6px 0 6px 11px; |
| | | |
| | | .iconBox { |
| | | width: auto; |
| | | } |
| | | |
| | | .labelC { |
| | | font-size: 14px; |
| | | font-family: PingFang SC, PingFang SC; |
| | | font-weight: 400; |
| | | color: #333333; |
| | | } |
| | | } |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | import { defineComponent, ref, computed } from 'vue' |
| | | import Icon from '@/components/Icon/Icon' |
| | | import styles from './Menu.module.scss' |
| | | import './index.scss' |
| | | import { isNil } from 'lodash' |
| | | |
| | | interface contextMenuItemType { |
| | | current: Record<string, any> | null |
| | | options: any |
| | | } |
| | | interface CurrentType { |
| | | row: any |
| | | index: number |
| | | } |
| | | |
| | | interface ItemType { |
| | | label: string |
| | | icon: string |
| | | fn: (c: CurrentType) => void |
| | | disabled?: boolean |
| | | divided?: boolean |
| | | } |
| | | |
| | | export default defineComponent({ |
| | | name: 'å³é®èå', |
| | | props: { |
| | | contextMenu: { |
| | | type: Array, |
| | | }, |
| | | graph: { |
| | | type: Object, |
| | | }, |
| | | visible: { |
| | | type: Boolean, |
| | | default: false, |
| | | }, |
| | | options: { |
| | | type: Object, |
| | | default: () => {}, |
| | | }, |
| | | model: { |
| | | type: Object, |
| | | default: () => {}, |
| | | }, |
| | | isShow: { |
| | | type: Boolean, |
| | | default: false, |
| | | }, |
| | | }, |
| | | setup(props, { emit }) { |
| | | const menuRef = ref<any>() |
| | | // const contextMenu: ItemType[] | unknown[] = props.contextMenu || [] |
| | | const contextMenu = computed(() => { |
| | | return props.contextMenu || [] |
| | | }) |
| | | // [ |
| | | // { |
| | | // label: 'å¤å¶', |
| | | // fn: (c: CurrentType) => {}, |
| | | // divided: true, |
| | | // icon: 'o', |
| | | // }, |
| | | // { |
| | | // label: 'å é¤', |
| | | // fn: (c: CurrentType) => {}, |
| | | // divided: true, |
| | | // disabled: false, |
| | | // icon: 'up', |
| | | // }, |
| | | // { |
| | | // label: 'æ¥ç屿§', |
| | | // fn: (c: CurrentType) => {}, |
| | | // divided: true, |
| | | // disabled: false, |
| | | // icon: 'up', |
| | | // }, |
| | | // ] |
| | | |
| | | const visible = computed({ |
| | | get: () => { |
| | | return props.visible |
| | | }, |
| | | set(value) { |
| | | emit('update:visible', value) |
| | | }, |
| | | }) |
| | | |
| | | const isShow = computed({ |
| | | get: () => { |
| | | return props.isShow |
| | | }, |
| | | set(value) { |
| | | emit('update:isShow', value) |
| | | }, |
| | | }) |
| | | |
| | | const contextMenuConfig = computed(() => { |
| | | return { |
| | | options: { |
| | | zIndex: 2000, |
| | | minWidth: 132, |
| | | x: 0, |
| | | y: 0, |
| | | ...props.options, |
| | | }, |
| | | } |
| | | }) |
| | | |
| | | const contextDisabled: any = computed(() => { |
| | | return (item: any) => { |
| | | if (item.disabled !== undefined) { |
| | | if (!isNil(item.disabled?.value)) { |
| | | return item.disabled?.value |
| | | } else { |
| | | return item.disabled |
| | | } |
| | | } |
| | | return false |
| | | } |
| | | }) |
| | | /** |
| | | * èå |
| | | * @param item |
| | | */ |
| | | const onHandleMenuItem = (event: TouchEvent | MouseEvent, item: any) => { |
| | | event?.stopPropagation() |
| | | item.fn && item.fn(props.model, isShow) |
| | | } |
| | | return () => { |
| | | return isShow.value ? ( |
| | | <context-menu |
| | | // v-if="contextMenu?.length > 0" |
| | | ref={menuRef} |
| | | v-model:show={visible.value} |
| | | options={contextMenuConfig.value.options} |
| | | > |
| | | { |
| | | // @ts-ignore |
| | | contextMenu.value.map((item: ItemType, index: number) => { |
| | | return ( |
| | | <span |
| | | onTouchstart={(event) => onHandleMenuItem(event, item)} |
| | | onClick={(event) => onHandleMenuItem(event, item)} |
| | | > |
| | | <context-menu-item |
| | | key={index} |
| | | label={item.label} |
| | | disabled={!!contextDisabled.value(item)} |
| | | style={{ |
| | | filter: contextDisabled.value(item) |
| | | ? 'opacity(0.4)' |
| | | : 'none', |
| | | }} |
| | | > |
| | | <div |
| | | style={{ |
| | | cursor: !contextDisabled.value(item) |
| | | ? 'pointer' |
| | | : 'not-allowed', |
| | | }} |
| | | class={styles.contextMenuItemC} |
| | | > |
| | | <div style="width: 16px; margin-right: 7px"> |
| | | <Icon |
| | | height={16} |
| | | class={styles.iconBox} |
| | | icon={item.icon} |
| | | /> |
| | | </div> |
| | | <div class={styles.labelC}>{item.label}</div> |
| | | </div> |
| | | </context-menu-item> |
| | | </span> |
| | | ) |
| | | }) |
| | | } |
| | | </context-menu> |
| | | ) : null |
| | | } |
| | | }, |
| | | }) |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | // å³ä¾§èå |
| | | .mx-context-menu { |
| | | width: 132px; |
| | | background: #ffffff; |
| | | box-shadow: 0px 0px 6px 1px rgba(0, 0, 0, 0.16); |
| | | padding: 0px; |
| | | |
| | | .mx-context-menu-item-wrapper { |
| | | padding: 4px; |
| | | height: 40px; |
| | | border-bottom: 1px solid #e3e6ed; |
| | | |
| | | .mx-context-menu-item { |
| | | cursor: pointer; |
| | | border-radius: 6px; |
| | | width: 100%; |
| | | padding: 0; |
| | | height: 100%; |
| | | } |
| | | } |
| | | |
| | | .mx-context-menu-item-wrapper:last-child { |
| | | border-bottom: none; |
| | | } |
| | | |
| | | .table-context-menu-item-c { |
| | | width: 100%; |
| | | height: 100%; |
| | | display: flex; |
| | | justify-content: flex-start; |
| | | align-items: center; |
| | | padding: 6px 0 6px 11px; |
| | | |
| | | .icon-box { |
| | | width: auto; |
| | | } |
| | | |
| | | .label-c { |
| | | font-size: 14px; |
| | | font-family: PingFang SC, PingFang SC; |
| | | font-weight: 400; |
| | | color: #333333; |
| | | } |
| | | } |
| | | } |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | import { _t } from '@/libs/Language/Language' |
| | | import { injectStore } from '../../core/store' |
| | | import { WidgetNameType } from './WidgetTypeByEnum' |
| | | |
| | | const { flowMap } = injectStore() |
| | | |
| | | export class CreateFormItem { |
| | | category: string = '' |
| | | label: string = '' |
| | | prop: string = '' |
| | | el: any |
| | | rules: any |
| | | readonly: boolean = false |
| | | tip: string = '' |
| | | icon: string = '' |
| | | options: any |
| | | defaultValue: any |
| | | clearable: boolean = true |
| | | controlsPosition: string = '' |
| | | step: number = 1 |
| | | min: number = 0 |
| | | propertyType: string = '' |
| | | elementAttributes: any |
| | | elementType: any |
| | | type: string = '' |
| | | placeholder: string = '' |
| | | valueOnClear: number | any |
| | | nullable: boolean = false |
| | | pattern: string = '' |
| | | rows: string | number = 10 |
| | | constructor(item: any, currentNode: string) { |
| | | this.init(item, currentNode) |
| | | } |
| | | |
| | | init(item: any, currentNode: string) { |
| | | const el = |
| | | WidgetNameType[item.propertyType]?.el || |
| | | WidgetNameType[item.propertyType]?.type |
| | | this.category = item.category |
| | | this.label = item.name |
| | | this.prop = item.propertyKey |
| | | this.el = el |
| | | this.readonly = item.readonly |
| | | this.tip = item.description |
| | | this.icon = 'wen' |
| | | this.options = item.options |
| | | this.defaultValue = item.propertyValue |
| | | this.clearable = item.nullable ? true : false |
| | | this.controlsPosition = 'right' |
| | | this.valueOnClear = item.nullable ? undefined : item.propertyValue |
| | | this.step = 1 |
| | | this.nullable = item.nullable |
| | | this.min = WidgetNameType[item.propertyType]?.type?.min ?? undefined |
| | | this.propertyType = item.propertyType |
| | | this.elementAttributes = item?.elementAttributes |
| | | this.elementType = item.elementType |
| | | this.placeholder = item.placeholder |
| | | this.type = WidgetNameType[item.propertyType]?.el |
| | | ? WidgetNameType[item.propertyType]?.type |
| | | : 'select' |
| | | this.rules = this.getRules(item.propertyKey, currentNode) |
| | | this.rows = item.rows || WidgetNameType[item.propertyType]?.rows |
| | | |
| | | const requiredRule = { |
| | | required: true, |
| | | message: this.options.length ? _t('è¯·éæ©') : _t('请è¾å
¥') + item.name, |
| | | trigger: 'change', |
| | | } |
| | | if (item.required && !this.rules) { |
| | | this.rules = [requiredRule] |
| | | } |
| | | if (item.pattern) { |
| | | this.rules.push({ |
| | | pattern: new RegExp(item.pattern), |
| | | message: item.ruleMessage || _t('æ ¼å¼é误'), |
| | | trigger: 'change', |
| | | }) |
| | | } |
| | | } |
| | | |
| | | getRules(key: string, currentNode: string) { |
| | | // æ ¹æ®å®é
æ
åµå®ç°è·åè§åçé»è¾ |
| | | const ruleMap: Record<string, any> = { |
| | | Name: [ |
| | | { |
| | | required: true, |
| | | message: _t('请è¾å
¥æ¥éª¤åç§°'), |
| | | trigger: 'change', |
| | | }, |
| | | |
| | | { |
| | | validator: (rule: any, value: string, callback: any) => { |
| | | let count = 0 |
| | | let isSameValue = false |
| | | flowMap.forEach((item: any) => { |
| | | if (item?.properties?.name === value) { |
| | | if (currentNode !== item.id) { |
| | | count++ |
| | | if (count >= 1) { |
| | | return (isSameValue = true) |
| | | } |
| | | } |
| | | } |
| | | }) |
| | | |
| | | if (isSameValue) { |
| | | callback(_t('èç¹åç§°éå¤ï¼è¯·æ£æ¥åéè¯')) |
| | | } else { |
| | | callback() |
| | | } |
| | | }, |
| | | trigger: 'blur', |
| | | }, |
| | | ], |
| | | } |
| | | return ruleMap[key] |
| | | } |
| | | } |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | import { _t } from '@/libs/Language/Language' |
| | | |
| | | export const WidgetNameType: Record<string, any> = { |
| | | String: { |
| | | type: 'input', |
| | | placeholder: _t('请è¾å
¥'), |
| | | }, |
| | | Textarea: { |
| | | el: 'input', |
| | | type: 'textarea', |
| | | placeholder: _t('请è¾å
¥'), |
| | | rows: 10, |
| | | }, |
| | | Boolean: { |
| | | type: 'switch', |
| | | }, |
| | | Enum: { |
| | | type: 'select', |
| | | placeholder: _t('è¯·éæ©'), |
| | | }, |
| | | Int32: { |
| | | type: 'inputNumber', |
| | | placeholder: _t('请è¾å
¥'), |
| | | }, |
| | | Int64: { |
| | | type: 'inputNumber', |
| | | placeholder: _t('请è¾å
¥'), |
| | | }, |
| | | |
| | | UInt32: { |
| | | type: 'inputNumber', |
| | | placeholder: _t('请è¾å
¥'), |
| | | min: 0, |
| | | }, |
| | | ArrayList: { |
| | | type: 'tableArray', |
| | | placeholder: '', |
| | | }, |
| | | Object: { |
| | | type: 'tableArray', |
| | | placeholder: '', |
| | | }, |
| | | Variable: { |
| | | type: 'variable', |
| | | placeholder: _t('è¯·éæ©'), |
| | | }, |
| | | FlowItemKey: { |
| | | type: 'flowItemKey', |
| | | placeholder: _t('è¯·éæ©'), |
| | | }, |
| | | ConditionCollection: { |
| | | type: 'condition', |
| | | }, |
| | | Decimal: { |
| | | type: 'inputNumber', |
| | | placeholder: _t('请è¾å
¥'), |
| | | precision: 6, |
| | | }, |
| | | Double: { |
| | | type: 'inputNumber', |
| | | placeholder: _t('请è¾å
¥'), |
| | | precision: 6, |
| | | }, |
| | | Single: { |
| | | type: 'inputNumber', |
| | | placeholder: _t('请è¾å
¥'), |
| | | precision: 6, |
| | | }, |
| | | } |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | import { computed, defineComponent, ref } from 'vue' |
| | | import BaseDialog from '@/components/BaseDialog/index.vue' |
| | | import DyForm from '@/components/DyForm/DyForm' |
| | | import { ConditionType } from '../../core/enum' |
| | | import { _t } from '@/libs/Language/Language' |
| | | |
| | | export default defineComponent({ |
| | | props: ['visible', 'options'], |
| | | emits: ['confirm', 'update:visible'], |
| | | setup(props, { emit }) { |
| | | const formData = ref({}) |
| | | const formRef = ref() |
| | | const visible = computed({ |
| | | get() { |
| | | return props.visible |
| | | }, |
| | | set(v) { |
| | | emit('update:visible', v) |
| | | }, |
| | | }) |
| | | |
| | | const onConfirm = async () => { |
| | | await formRef.value.validate() |
| | | visible.value = false |
| | | emit('confirm', { ...formData.value }) |
| | | } |
| | | return () => { |
| | | return ( |
| | | <BaseDialog |
| | | width="400px" |
| | | title={_t('æ¡ä»¶ç±»å')} |
| | | v-model={visible.value} |
| | | onClose={() => (visible.value = false)} |
| | | onConfirm={onConfirm} |
| | | > |
| | | <DyForm |
| | | ref={formRef} |
| | | isLine={true} |
| | | formItemProps={[ |
| | | { |
| | | label: 'æ¡ä»¶ç±»å', |
| | | prop: ConditionType, |
| | | el: 'select', |
| | | options: props.options || [], |
| | | rules: [ |
| | | { |
| | | required: true, |
| | | message: _t('è¯·éæ©æ¡ä»¶ç±»å'), |
| | | trigger: 'blur', |
| | | }, |
| | | ], |
| | | }, |
| | | ]} |
| | | v-model:formData={formData.value} |
| | | labelWidth="80px" |
| | | ></DyForm> |
| | | </BaseDialog> |
| | | ) |
| | | } |
| | | }, |
| | | }) |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | .formDrawer { |
| | | margin-left: 40px; |
| | | } |
| | | .drawContent { |
| | | position: relative; |
| | | width: 100%; |
| | | height: 100%; |
| | | .condition { |
| | | position: absolute; |
| | | left: 0; |
| | | bottom: 0; |
| | | border-top: 1px solid #ddd; |
| | | width: 100%; |
| | | height: 40px; |
| | | padding: 10px; |
| | | color: #333; |
| | | font-size: 13px; |
| | | display: flex; |
| | | align-items: center; |
| | | justify-content: flex-start; |
| | | flex-wrap: wrap; |
| | | } |
| | | } |
| | | .edgeDialogTitle { |
| | | font-size: 18px; |
| | | font-family: Source Han Sans CN, Source Han Sans CN; |
| | | font-weight: bold; |
| | | color: #464e54; |
| | | line-height: 0px; |
| | | > img { |
| | | margin-left: 10px; |
| | | } |
| | | } |
| | | .tip { |
| | | font-size: 12px; |
| | | color: #8a8a8a; |
| | | position: absolute; |
| | | left: 20px; |
| | | top: 60px; |
| | | } |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | import { |
| | | computed, |
| | | defineComponent, |
| | | ref, |
| | | onMounted, |
| | | watch, |
| | | SetupContext, |
| | | PropType, |
| | | nextTick, |
| | | inject, |
| | | } from 'vue' |
| | | import BaseDrawer from '@/components/BaseDrawer/BaseDrawer' |
| | | import DyForm from '@/components/DyForm/DyForm' |
| | | import { injectStore } from '../../core/store' |
| | | import { StoreKey } from '../../type/index.d' |
| | | import { getFlowDetail } from '@/api/logic-flow' |
| | | import { FormItemPropType } from '@/components/DyForm/DyForm.d' |
| | | import ElInputNumber from 'element-plus/es/components/input-number/index' |
| | | import { cloneDeep, get, isNil, isNull, omitBy, remove, sortBy } from 'lodash' |
| | | import { fittingString } from '../../core/transformHelp' |
| | | import { width, nodeFontSize } from '../Nodes' |
| | | import TableArray from '@/components/TableArray/TableArray' |
| | | import { CreateFormItem } from '../Models/CreateFormItem' |
| | | import { WidgetNameType } from '../Models/WidgetTypeByEnum' |
| | | import { ConditionType } from '../../core/enum' |
| | | import FlowContextDialog from '@/components/FlowContextDialog/FlowContextDialog' |
| | | import styles from './NodeDrawer.module.scss' |
| | | import Icon from '@/components/Icon/Icon' |
| | | import { _t } from '@/libs/Language/Language' |
| | | |
| | | export default defineComponent({ |
| | | name: 'NodeDrawer', |
| | | props: { |
| | | title: { |
| | | type: String, |
| | | }, |
| | | model: { |
| | | type: Object, |
| | | default: () => ({}), |
| | | }, |
| | | modelValue: { |
| | | type: Boolean, |
| | | }, |
| | | graph: { |
| | | type: Object, |
| | | default: null, |
| | | }, |
| | | type: { |
| | | type: String, |
| | | default: '', |
| | | }, |
| | | isEdit: { |
| | | type: Boolean, |
| | | default: false, |
| | | }, |
| | | }, |
| | | emits: ['update:modelValue', 'close', 'confirm', 'update:title'], |
| | | setup(props, { slots, emit }) { |
| | | const isOpen = ref(false) |
| | | const title = ref(props.title) |
| | | const formRef = ref<any>(null) |
| | | const flowType = inject('flowType', '') |
| | | const { nodeMap } = injectStore() |
| | | |
| | | const customWidgetMap = { |
| | | inputNumber: ElInputNumber, |
| | | switch: (props: PropType<any>, { attrs }: SetupContext) => { |
| | | return <el-switch {...attrs} /> |
| | | }, |
| | | tableArray: TableArray, |
| | | flowItemKey: FlowContextDialog, |
| | | } |
| | | |
| | | const visible = computed({ |
| | | get: () => props.modelValue, |
| | | set: (value) => { |
| | | emit('update:modelValue', value) |
| | | }, |
| | | }) |
| | | const model = computed(() => props.model) |
| | | |
| | | const formData: Record<string, any> = ref({}) |
| | | |
| | | const formItemProps = ref<FormItemPropType>([]) |
| | | const formItemPropMap = ref<Record<string, FormItemPropType>>({}) |
| | | |
| | | const currentNode = computed(() => { |
| | | return model.value?.properties |
| | | }) |
| | | const onClose = () => { |
| | | visible.value = false |
| | | isOpen.value = false |
| | | } |
| | | /** |
| | | * è¿æ»¤id |
| | | */ |
| | | const filterDataId = () => { |
| | | formItemProps.value.forEach((formItem: FormItemPropType) => { |
| | | if (formItem.propertyType === 'ArrayList') { |
| | | const data = get( |
| | | formData.value, |
| | | `[${formItem.prop}][${formItem.elementType}]`, |
| | | [] |
| | | ) |
| | | data.forEach((item: any) => { |
| | | delete item.id |
| | | }) |
| | | } |
| | | }) |
| | | } |
| | | |
| | | const onConfirm = async () => { |
| | | const refs: Record<string, any> = {} |
| | | const valid = await formRef.value?.validate() |
| | | |
| | | let validField = true |
| | | |
| | | formItemProps.value.forEach((formItem: FormItemPropType) => { |
| | | if (formItem.propertyType === 'ArrayList') { |
| | | refs[formItem.prop] = formRef.value?.getRefByKey(formItem.prop) |
| | | } |
| | | }) |
| | | Object.keys(refs).forEach((key: string) => { |
| | | const ref = refs[key] |
| | | const valid = ref?.valid() |
| | | if (!valid) { |
| | | return (validField = false) |
| | | } |
| | | }) |
| | | |
| | | if (!validField) return |
| | | if (!valid) return |
| | | const graph = props.graph |
| | | const item = graph.findById(model.value.id) |
| | | const modelData = cloneDeep(model.value) |
| | | const label = formData.value.Name |
| | | filterDataId() |
| | | modelData.properties = formData.value |
| | | modelData.name = label |
| | | modelData.label = fittingString(label, width - 5, nodeFontSize + 2) |
| | | item.update(modelData) |
| | | visible.value = false |
| | | emit('confirm', formData.value) |
| | | } |
| | | |
| | | const formItemSort = (formItems: FormItemPropType[]) => { |
| | | return sortBy(formItems, ['sort']) |
| | | } |
| | | |
| | | const updateFormData = () => { |
| | | const properties = model.value?.properties |
| | | formData.value = { |
| | | ...formData.value, |
| | | ...properties, |
| | | } |
| | | const type = currentNode.value?.type |
| | | if (!formData.value[ConditionType] && type) { |
| | | formData.value[ConditionType] = type |
| | | } |
| | | |
| | | formItemProps.value.forEach((formItem: FormItemPropType) => { |
| | | const data = formData.value[formItem.prop] |
| | | |
| | | if (formItem.propertyType === 'ArrayList') { |
| | | if (Array.isArray(data) || !data) { |
| | | formData.value[formItem.prop] = {} |
| | | } |
| | | if (!data?.[formItem.elementType]) { |
| | | formData.value[formItem.prop][formItem.elementType] = [] |
| | | } |
| | | const childData = formData.value[formItem.prop][formItem.elementType] |
| | | if (!Array.isArray(childData) && childData) { |
| | | formData.value[formItem.prop][formItem.elementType] = [childData] |
| | | } |
| | | } else { |
| | | if (isNil(data)) { |
| | | formData.value[formItem.prop] = formItem.defaultValue |
| | | } |
| | | if (formItem.propertyType === 'Enum') { |
| | | const v = formData.value[formItem.prop] |
| | | formData.value[formItem.prop] = |
| | | v !== null ? String(formData.value[formItem.prop]) : v |
| | | } |
| | | } |
| | | }) |
| | | } |
| | | |
| | | const onOpen = async () => { |
| | | formItemProps.value = {} |
| | | formItemPropMap.value = {} |
| | | formData.value = {} |
| | | if (!currentNode.value?.type) return |
| | | isOpen.value = true |
| | | const data = await getFlowDetail( |
| | | model.value?.properties?.type, |
| | | flowType !== '' ? Number(flowType) : undefined |
| | | ) |
| | | const attributes = data.attributes || [] |
| | | const formItems: FormItemPropType[] = [] |
| | | attributes?.forEach((item: FormItemPropType) => { |
| | | const placeholder = WidgetNameType[item.propertyType]?.placeholder |
| | | const options = |
| | | item.propertyData?.map((item: any) => { |
| | | return { |
| | | label: item.name, |
| | | tip: item.description, |
| | | value: item.value, |
| | | } |
| | | }) || [] |
| | | |
| | | const option = { |
| | | ...item, |
| | | options, |
| | | placeholder: placeholder && placeholder + item.name, |
| | | } |
| | | const formItem: FormItemPropType = new CreateFormItem( |
| | | option, |
| | | model.value.id |
| | | ) |
| | | if (item.visible) { |
| | | formItems.push(formItem) |
| | | } |
| | | }) |
| | | formItemProps.value = formItemSort(formItems) |
| | | formItemProps.value.forEach((formItem: FormItemPropType) => { |
| | | formItemPropMap.value[formItem.prop] = formItem |
| | | }) |
| | | title.value = data.name |
| | | nextTick(() => { |
| | | formRef.value?.initFormData() |
| | | |
| | | updateFormData() |
| | | }) |
| | | } |
| | | |
| | | onMounted(() => { |
| | | if (!isOpen.value) { |
| | | onOpen() |
| | | } |
| | | }) |
| | | |
| | | return () => { |
| | | const type = model.value?.properties?.type |
| | | const nodeInfo = type ? nodeMap.get(type) : {} |
| | | |
| | | return ( |
| | | <BaseDrawer |
| | | onClose={onClose} |
| | | onConfirm={onConfirm} |
| | | onOpen={onOpen} |
| | | // title={title.value || model.value.label} |
| | | width="60%" |
| | | v-model={visible.value} |
| | | submitDisabled={!formItemProps.value.length || !props.isEdit} |
| | | destroy-on-close |
| | | v-slots={{ |
| | | title: () => { |
| | | return ( |
| | | <div class={styles.edgeDialogTitle}> |
| | | {title.value || model.value.label} |
| | | <div class={styles.tip}>{nodeInfo?.description}</div> |
| | | </div> |
| | | ) |
| | | }, |
| | | }} |
| | | > |
| | | {formItemProps.value.length ? ( |
| | | <DyForm |
| | | isCategory={true} |
| | | ref={formRef} |
| | | customWidgetMap={customWidgetMap} |
| | | formItemProps={formItemProps.value} |
| | | v-model:formData={formData.value} |
| | | labelWidth="140px" |
| | | ></DyForm> |
| | | ) : ( |
| | | <el-empty image-size={200} description={_t('ææ æ°æ®')} /> |
| | | )} |
| | | </BaseDrawer> |
| | | ) |
| | | } |
| | | }, |
| | | }) |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | import { NODES } from '../../core/enum' |
| | | import { width, height, x, y } from './index' |
| | | |
| | | const EndNode: { |
| | | type: string |
| | | options: Record<string, any> |
| | | } = { |
| | | type: NODES.END_ACTIVITY, |
| | | options: { |
| | | drawShape(cfg: Record<string, any>, group: any) { |
| | | const rect = group.addShape('rect', { |
| | | attrs: { |
| | | x: -75 - x, |
| | | y: -25 - y, |
| | | width, |
| | | height, |
| | | radius: 10, |
| | | stroke: '#5B8FF9', |
| | | fill: '#C6E5FF', |
| | | lineWidth: 3, |
| | | }, |
| | | name: 'rect-shape', |
| | | }) |
| | | return rect |
| | | }, |
| | | }, |
| | | } |
| | | |
| | | export default EndNode |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | import { defineComponent } from 'vue' |
| | | import styles from './index.module.scss' |
| | | |
| | | export default defineComponent({ |
| | | name: 'Node', |
| | | props: { |
| | | cfg: { |
| | | type: Object, |
| | | required: true, |
| | | }, |
| | | }, |
| | | setup() { |
| | | return () => { |
| | | return <div class={styles.nodeContent}>Node</div> |
| | | } |
| | | }, |
| | | }) |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | import { NODES } from '../../core/enum' |
| | | import { width, height, x, y } from './index' |
| | | |
| | | // const pngMap = import.meta.glob('../../../../assets/images/*.png', { |
| | | // eager: true, |
| | | // }) |
| | | // const iconMap: Record<string, any> = Object.entries(pngMap).reduce( |
| | | // (acc, [key, value]: any[]) => { |
| | | // const name = key |
| | | // .replace('../../../../assets/images/', '') |
| | | // .replace('.png', '') |
| | | // return { |
| | | // ...acc, |
| | | // [name]: value.default, |
| | | // } |
| | | // }, |
| | | // {} |
| | | // ) |
| | | const OrdinaryNode: { |
| | | type: string |
| | | options: Record<string, any> |
| | | } = { |
| | | type: NODES.ACTIVITIES, |
| | | options: { |
| | | drawShape(cfg: Record<string, any>, group: any) { |
| | | const type = cfg?.properties?.type |
| | | const isRoot = cfg?.isRoot |
| | | const rect = group.addShape('rect', { |
| | | zIndex: 1, |
| | | attrs: { |
| | | x: -width / 2, |
| | | y: -height / 2, |
| | | width, |
| | | height, |
| | | radius: 1, |
| | | stroke: '#5B8FF9', |
| | | fill: '#C6E5FF', |
| | | lineWidth: 2, |
| | | }, |
| | | name: 'rect-shape', |
| | | }) |
| | | group.addShape('image', { |
| | | zIndex: 100, |
| | | draggable: false, |
| | | attrs: { |
| | | x: -width / 2 + 1, |
| | | y: -height / 2 + 1, |
| | | radius: 1, |
| | | width: 20, |
| | | height: 20, |
| | | // img: isRoot ? iconMap[NODES.ACTIVITY] : iconMap[type], |
| | | img: `/resources/assets/images/${isRoot ? NODES.ACTIVITY : type}.png`, |
| | | }, |
| | | name: 'node-icon', |
| | | }) |
| | | return rect |
| | | }, |
| | | }, |
| | | } |
| | | |
| | | export default OrdinaryNode |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | import { NODES } from '../../core/enum' |
| | | import { width, height, x, y } from './index' |
| | | |
| | | const StartNode: { |
| | | type: string |
| | | options: Record<string, any> |
| | | } = { |
| | | type: NODES.ACTIVITY, |
| | | options: { |
| | | drawShape(cfg: Record<string, any>, group: any) { |
| | | const rect = group.addShape('rect', { |
| | | attrs: { |
| | | x: -75 - x, |
| | | y: -25 - y, |
| | | width, |
| | | height, |
| | | radius: 10, |
| | | stroke: '#5B8FF9', |
| | | fill: '#C6E5FF', |
| | | lineWidth: 3, |
| | | }, |
| | | name: 'rect-shape', |
| | | }) |
| | | return rect |
| | | }, |
| | | }, |
| | | } |
| | | export default StartNode |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | .nodeContent { |
| | | width: 100%; |
| | | height: 100%; |
| | | background-color: red; |
| | | } |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | const w = 50 |
| | | const h = 10 |
| | | export const x = w / 2 |
| | | export const y = h / 2 |
| | | export const width = 150 + w |
| | | export const height = 50 + h |
| | | export const fontSize = 16 |
| | | export const nodeFontSize = fontSize + 2 |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | .renderer { |
| | | position: relative; |
| | | // overflow: hidden; |
| | | padding: 10px; |
| | | } |
| | | .miniMap { |
| | | width: 200px; |
| | | height: 120px; |
| | | position: absolute; |
| | | left: calc(100% - 215px); |
| | | bottom: calc(100% - 130px); |
| | | border: 1px solid #ccc; |
| | | z-index: 99; |
| | | background-color: #fff; |
| | | } |
| | | |
| | | .toolBar { |
| | | width: 46px; |
| | | > div { |
| | | width: 46px; |
| | | display: flex; |
| | | justify-content: space-between; |
| | | align-items: center; |
| | | flex-direction: column; |
| | | border: none !important; |
| | | padding: 0; |
| | | } |
| | | } |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | import { |
| | | defineComponent, |
| | | onMounted, |
| | | ref, |
| | | nextTick, |
| | | watch, |
| | | computed, |
| | | SetupContext, |
| | | Fragment, |
| | | onUnmounted, |
| | | } from 'vue' |
| | | import styles from './Renderer.module.scss' |
| | | import { ConditionType, NODES } from '../../core/enum' |
| | | import G6, { Graph } from '@antv/g6' |
| | | import { behaviorMap } from '../../core/behavior' |
| | | import StartNode from '../Nodes/StartNode' |
| | | import EndNode from '../Nodes/EndNode' |
| | | import OrdinaryNode from '../Nodes/OrdinaryNode' |
| | | import Core from '../../core/Core' |
| | | import { injectStore } from '../../core/store' |
| | | import { fontSize, nodeFontSize } from '../Nodes' |
| | | import Menu from '../Menu/Menu' |
| | | import { cloneDeep } from 'lodash' |
| | | import ToolBar from '../ToolBar/ToolBarDefine' |
| | | import Tooltip from '../Tooltip/Tooltip' |
| | | |
| | | interface PropsType { |
| | | graphData: Record<string, any> |
| | | [key: string]: any |
| | | style: Record<string, any> |
| | | } |
| | | |
| | | export default defineComponent<PropsType>({ |
| | | // @ts-ignore |
| | | name: 'G6FlowRenderer', |
| | | props: { |
| | | graphData: { |
| | | type: Object, |
| | | required: true, |
| | | }, |
| | | style: { type: Object, default: () => ({}) }, |
| | | minimap: { type: [Boolean, Object], default: false }, |
| | | isEdgeAnimation: { type: Boolean, default: false }, |
| | | dragCanvas: { type: Boolean, default: false }, |
| | | dragNode: { type: Boolean, default: false }, |
| | | activateRelations: { type: Boolean, default: false }, |
| | | zoomCanvas: { type: Boolean, default: false }, |
| | | clickSelect: { type: Boolean, default: false }, |
| | | createEdge: { type: Boolean, default: false }, |
| | | flowName: { type: String, default: 'æµç¨å¾' }, |
| | | editing: { |
| | | type: Boolean, |
| | | default: false, |
| | | }, |
| | | contextMenu: { |
| | | type: Array, |
| | | }, |
| | | edgeContextMenu: { |
| | | type: Array, |
| | | }, |
| | | }, |
| | | // emits: Object.keys(behaviorMap), |
| | | emits: [], |
| | | setup(props: PropsType, { expose, attrs, slots, emit }: SetupContext) { |
| | | const { graphEvent, flowMap, flowNodeMap } = injectStore() |
| | | const core = new Core() |
| | | |
| | | const canvasConfig = computed(() => { |
| | | return { |
| | | ...attrs, |
| | | } |
| | | }) |
| | | let graph: Graph | null = null |
| | | const graphConfig = { |
| | | width: 0, |
| | | height: 0, |
| | | } |
| | | /** |
| | | * 注åè¾¹ä¸èç¹ |
| | | */ |
| | | const batchRegister = () => { |
| | | G6.registerNode(NODES.END_ACTIVITY, EndNode.options, 'single-node') |
| | | G6.registerNode(NODES.ACTIVITIES, OrdinaryNode.options, 'single-node') |
| | | } |
| | | /** |
| | | * èªå¨å¸å± |
| | | */ |
| | | const autoLayout = () => { |
| | | if (graph) { |
| | | const layout = canvasConfig.value?.layout || {} |
| | | graph.updateLayout({ ...layout }) |
| | | } |
| | | } |
| | | |
| | | /** |
| | | * èªå¨å¸å± |
| | | */ |
| | | const render = () => { |
| | | if (graph) { |
| | | if (!props.graphData?.nodes?.length) return |
| | | const isEdit = props.graphData?.nodes?.[0]?.isEdit |
| | | if (isEdit) { |
| | | graph.destroyLayout() |
| | | graph.changeData(props.graphData) |
| | | } |
| | | graph.render() |
| | | |
| | | setTimeout(zoomCanvas) |
| | | } |
| | | } |
| | | /** |
| | | * 缩æ¾å°ä¸é´ |
| | | */ |
| | | const zoomCanvas = (x?: number, y?: number) => { |
| | | if (graph) { |
| | | const { width, height } = graphConfig |
| | | graph?.zoomTo(0.7, { |
| | | x: x || width / 2 - 33, |
| | | y: y || 0, |
| | | // duration: 1000, |
| | | }) |
| | | } |
| | | } |
| | | |
| | | const getTools = () => { |
| | | const toolBarInstance = new ToolBar({ |
| | | className: styles.toolBar, |
| | | format: autoLayout, |
| | | downName: props.flowName, |
| | | }) |
| | | const g6ToolInstance = toolBarInstance.instanceToolBar() |
| | | return g6ToolInstance |
| | | } |
| | | |
| | | const getMiniMap = () => { |
| | | const container = document.querySelector( |
| | | `.${styles.miniMap}` |
| | | ) as HTMLDivElement |
| | | if (!container) return |
| | | const minimap = new G6.Minimap({ |
| | | container, |
| | | }) |
| | | return minimap |
| | | } |
| | | /** |
| | | * 渲æé»è¾æµ |
| | | * @param graphData |
| | | */ |
| | | const renderG6Graph = () => { |
| | | if (!Object.keys(props.graphData).length) return |
| | | if (graph) { |
| | | graph.data(props.graphData) |
| | | } |
| | | render() |
| | | } |
| | | /** |
| | | * è·ååè½äºä»¶é
ç½® |
| | | * @returns |
| | | */ |
| | | const getBaseBehaviorConfig = () => { |
| | | const events: string[] = [] |
| | | Object.entries(props || {}).forEach(([key, value]: any[]) => { |
| | | if (behaviorMap[key] && value) { |
| | | events.push(behaviorMap[key]) |
| | | } |
| | | }) |
| | | return events |
| | | } |
| | | /** |
| | | * åå§å渲æ |
| | | */ |
| | | const initializeRenderer = async () => { |
| | | batchRegister() |
| | | await renderG6Graph() |
| | | } |
| | | /** |
| | | * å®ä¾åLogicFlow |
| | | */ |
| | | const instanceG6Graph = () => { |
| | | const container = document.querySelector( |
| | | `.${styles.renderer}` |
| | | ) as HTMLElement |
| | | if (!container) return |
| | | const width = container.scrollWidth |
| | | const height = container.scrollHeight || 500 |
| | | graphConfig.width = width |
| | | graphConfig.height = height |
| | | const defaultProps = core.setDefaultProps() |
| | | const behavior = getBaseBehaviorConfig() |
| | | const minimap = getMiniMap() |
| | | const toolBar = props.editing ? getTools() : null |
| | | const toolTip = Tooltip() |
| | | const plugins = [minimap, toolBar, toolTip].filter((v) => v) |
| | | graph = new G6.Graph({ |
| | | container, |
| | | width, |
| | | height, |
| | | modes: { |
| | | default: [...behavior], |
| | | }, |
| | | // 设置为trueï¼å¯ç¨ redo & undo æ åè½ |
| | | enabledStack: true, |
| | | plugins, |
| | | ...defaultProps, |
| | | ...canvasConfig.value, |
| | | }) |
| | | |
| | | graphEvent.init(graph, canvasConfig.value.layout) |
| | | initializeRenderer() |
| | | } |
| | | /** |
| | | * è·åå½åLogicFlowå®ä¾ |
| | | * @returns |
| | | */ |
| | | const getCurrentInstance = () => { |
| | | return graph |
| | | } |
| | | |
| | | const currentHeight = computed(() => { |
| | | const height = canvasConfig.value?.height |
| | | if (height) { |
| | | return height + 'px' |
| | | } |
| | | return window.innerHeight + 'px' |
| | | }) |
| | | |
| | | const addNode = (node: any, position: any) => { |
| | | if (!graph) return |
| | | const point = graph?.getPointByClient(position.x, position.y) |
| | | const config = { |
| | | label: node.name, |
| | | type: node.category, |
| | | } |
| | | const model = core.createNode(config, { |
| | | x: point.x, |
| | | y: point.y, |
| | | properties: { |
| | | Name: node.name, |
| | | type: node.type, |
| | | [ConditionType]: node.type, |
| | | }, |
| | | }) |
| | | if (flowMap.get(model.Name)) { |
| | | const v = parseInt(String(Math.random() * 10000)) |
| | | const newName = model.Name + '_' + v |
| | | model.Name = newName |
| | | model.label = newName |
| | | model.name = newName |
| | | model.properties.Name = newName |
| | | } |
| | | flowNodeMap.set(model.id, model) |
| | | flowMap.set(model.name, model) |
| | | graph?.addItem('node', model) |
| | | } |
| | | |
| | | const getGraph = () => { |
| | | return graph |
| | | } |
| | | |
| | | watch( |
| | | () => props.graphData, |
| | | (v, oldV) => { |
| | | if (v !== oldV && v) { |
| | | instanceG6Graph() |
| | | } |
| | | } |
| | | ) |
| | | |
| | | watch( |
| | | () => props.createEdge, |
| | | () => { |
| | | if (!props.createEdge) { |
| | | graph?.removeBehaviors('create-edge', 'default') |
| | | } else { |
| | | graph?.addBehaviors('create-edge', 'default') |
| | | } |
| | | } |
| | | ) |
| | | |
| | | onMounted(() => { |
| | | instanceG6Graph() |
| | | }) |
| | | |
| | | onUnmounted(() => { |
| | | graph?.destroy() |
| | | graphEvent?.onUnmounted() |
| | | }) |
| | | |
| | | expose({ |
| | | getGraph, |
| | | render, |
| | | autoLayout, |
| | | getCurrentInstance, |
| | | zoomCanvas, |
| | | addNode, |
| | | }) |
| | | return () => { |
| | | let contextMenu = |
| | | graphEvent.type.value === 'edge' |
| | | ? props.edgeContextMenu |
| | | : props.contextMenu |
| | | if (graphEvent.model.value?.isRoot) { |
| | | contextMenu = contextMenu.filter( |
| | | (item: any) => !['copy', 'del'].includes(item.type) |
| | | ) |
| | | } |
| | | return ( |
| | | <div |
| | | class={styles.renderer} |
| | | // onClick={(event: Event) => onCancelSelect(event)} |
| | | style={{ |
| | | width: '100%', |
| | | height: currentHeight.value, |
| | | ...props.style, |
| | | }} |
| | | > |
| | | <div class={styles.miniMap}></div> |
| | | <div class={styles.toolBar}></div> |
| | | {contextMenu && contextMenu.length > 0 && ( |
| | | <Menu |
| | | contextMenu={contextMenu} |
| | | visible={true} |
| | | v-model:isShow={graphEvent.isShow.value} |
| | | options={graphEvent.position.value} |
| | | model={graphEvent.model.value} |
| | | /> |
| | | )} |
| | | </div> |
| | | ) |
| | | } |
| | | }, |
| | | }) |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | .toolBarContent { |
| | | width: auto; |
| | | height: fit-content; |
| | | display: flex; |
| | | justify-content: flex-start; |
| | | align-items: center; |
| | | flex-direction: column; |
| | | width: 46px; |
| | | display: flex; |
| | | justify-content: space-between; |
| | | align-items: center; |
| | | flex-direction: column; |
| | | border: none !important; |
| | | box-shadow: 0 3px 6px -4px rgba(0, 0, 0, 0.12), |
| | | 0 6px 16px 0 rgba(0, 0, 0, 0.08), 0 9px 28px 8px rgba(0, 0, 0, 0.05); |
| | | padding-left: 0; |
| | | margin: 0; |
| | | user-select: none; |
| | | } |
| | | |
| | | .toolBarItem { |
| | | width: 20px; |
| | | height: 40px !important; |
| | | cursor: pointer; |
| | | display: flex; |
| | | justify-content: center; |
| | | align-items: center; |
| | | &:hover { |
| | | filter: invert(50%) sepia(45%) saturate(3890%) hue-rotate(208deg) |
| | | brightness(102%) contrast(106%); |
| | | } |
| | | } |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | import { defineComponent } from 'vue' |
| | | import styles from './ToolBar.module.scss' |
| | | import BaseConfigProvider from '@/components/BaseConfigProvider/BaseConfigProvider' |
| | | import { _t } from '@/libs/Language/Language' |
| | | |
| | | export default defineComponent({ |
| | | name: 'ToolBar', |
| | | components: { |
| | | BaseConfigProvider, |
| | | }, |
| | | setup() { |
| | | const namespace = import.meta.env.VITE_APP_NAMESPACE |
| | | |
| | | const toolBar = [ |
| | | { |
| | | code: 'undo', |
| | | name: _t('æ¤é'), |
| | | icon: 'undo.svg', |
| | | }, |
| | | { |
| | | code: 'redo', |
| | | name: _t('æ¢å¤'), |
| | | icon: 'redo.svg', |
| | | }, |
| | | { |
| | | code: 'enlarge', |
| | | name: _t('æ¾å¤§'), |
| | | icon: 'enlarge.svg', |
| | | }, |
| | | { |
| | | code: 'reduce', |
| | | name: _t('缩å°'), |
| | | icon: 'reduce.svg', |
| | | }, |
| | | { |
| | | code: 'format', |
| | | name: _t('ç¾å'), |
| | | icon: 'format1.svg', |
| | | }, |
| | | { |
| | | code: 'download', |
| | | name: _t('ä¸è½½'), |
| | | icon: 'download.svg', |
| | | }, |
| | | { |
| | | code: 'import', |
| | | name: _t('导å
¥'), |
| | | icon: 'import.svg', |
| | | }, |
| | | { |
| | | code: 'export', |
| | | name: _t('导åº'), |
| | | icon: 'export.png', |
| | | }, |
| | | ] |
| | | return () => { |
| | | return ( |
| | | <ul class={styles.toolBarContent}> |
| | | {toolBar.map((item: any) => { |
| | | const imgUrl = new URL( |
| | | `../../../../assets/images/${item.icon}`, |
| | | import.meta.url |
| | | ).href |
| | | return ( |
| | | <el-config-provider namespace={namespace}> |
| | | <el-tooltip |
| | | class="box-item" |
| | | effect="dark" |
| | | content={item.name} |
| | | placement="right" |
| | | > |
| | | <li |
| | | class={styles.toolBarItem} |
| | | key={item.code} |
| | | // @ts-ignore |
| | | code={item.code} |
| | | > |
| | | <img |
| | | src={imgUrl} |
| | | width={20} |
| | | height={20} |
| | | // @ts-ignore |
| | | code={item.code} |
| | | /> |
| | | </li> |
| | | </el-tooltip> |
| | | </el-config-provider> |
| | | ) |
| | | })} |
| | | </ul> |
| | | ) |
| | | } |
| | | }, |
| | | }) |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | import G6, { Graph } from '@antv/g6' |
| | | import styles from './ToolBar.module.scss' |
| | | import { h, createApp } from 'vue' |
| | | import ToolBar from './ToolBar' |
| | | import { generateFlowXml, importXmlInit } from '../../core/transformHelp' |
| | | import { ElMessage } from 'element-plus' |
| | | import { injectStore } from '../../core/store' |
| | | import { _t } from '@/libs/Language/Language' |
| | | |
| | | export default class ToolBarDefine { |
| | | #className: string |
| | | #toolBarInstance: any |
| | | #downName: string | undefined |
| | | #format?: () => void |
| | | #animateCfg = { duration: 200, easing: 'easeCubic' } |
| | | constructor({ className, format, downName }: any) { |
| | | this.#className = className |
| | | this.#format = format |
| | | this.#downName = downName |
| | | } |
| | | get container() { |
| | | return document.querySelector(`.${this.#className}`) |
| | | } |
| | | get getContent() { |
| | | return () => { |
| | | const div = document.createElement('div') |
| | | |
| | | const app = createApp(() => { |
| | | return <ToolBar /> |
| | | }) |
| | | app.mount(div) |
| | | return div |
| | | } |
| | | } |
| | | |
| | | removeNode(dom: HTMLElement | HTMLInputElement) { |
| | | const t = setTimeout(() => { |
| | | dom.remove() |
| | | clearTimeout(t) |
| | | }, 2000) |
| | | } |
| | | handleClick(code: string, graph: Graph) { |
| | | const { flowBaseConfig } = injectStore() |
| | | if (this.#toolBarInstance) { |
| | | const toolBar: typeof G6.ToolBar | any = this.#toolBarInstance |
| | | |
| | | const fnMap: Record<string, () => void> = { |
| | | redo: () => { |
| | | toolBar.redo() |
| | | }, |
| | | undo: () => { |
| | | toolBar.undo() |
| | | }, |
| | | enlarge: () => { |
| | | graph.zoom(1.1, { x: 0, y: 0 }, true, this.#animateCfg) |
| | | }, |
| | | reduce: () => { |
| | | graph.zoom(0.9, { x: 0, y: 0 }, true, this.#animateCfg) |
| | | }, |
| | | format: () => { |
| | | this.#format && this.#format() |
| | | }, |
| | | export: () => { |
| | | const xml = generateFlowXml(graph) |
| | | const blob = new Blob([xml], { type: 'text/xml' }) |
| | | const url = URL.createObjectURL(blob) |
| | | const a = document.createElement('a') |
| | | a.href = url |
| | | const { name, type, version } = flowBaseConfig.value |
| | | const flowName = `${name}_${type}_${version}` |
| | | a.download = flowName + '.pfd' |
| | | a.click() |
| | | ElMessage.success(_t('å¯¼åºæå')) |
| | | URL.revokeObjectURL(url) |
| | | this.removeNode(a) |
| | | }, |
| | | import: () => { |
| | | const fileInput = document.createElement('input') |
| | | fileInput.type = 'file' |
| | | fileInput.accept = 'application/pfd' |
| | | fileInput.click() |
| | | fileInput.onchange = (e: any) => { |
| | | const file = e.target.files[0] |
| | | const reader = new FileReader() |
| | | reader.readAsText(file) |
| | | reader.onload = (e: any) => { |
| | | const xml = e.target.result |
| | | importXmlInit(graph, xml) |
| | | ElMessage.success(_t('导å
¥æå')) |
| | | this.removeNode(fileInput) |
| | | } |
| | | } |
| | | }, |
| | | download: () => { |
| | | const oldRatio = window.devicePixelRatio |
| | | window.devicePixelRatio = 3 |
| | | graph.downloadFullImage(this.#downName, 'image/png', { |
| | | backgroundColor: '#fff', |
| | | padding: 10, |
| | | }) |
| | | setTimeout(() => { |
| | | window.devicePixelRatio = oldRatio |
| | | }, 0) |
| | | }, |
| | | } |
| | | const fn = fnMap[code] |
| | | fn && fn() |
| | | } |
| | | } |
| | | instanceToolBar() { |
| | | this.#toolBarInstance = new G6.ToolBar({ |
| | | container: this.container as any, |
| | | getContent: this.getContent, |
| | | handleClick: this.handleClick.bind(this) as () => void, |
| | | }) |
| | | return this.#toolBarInstance |
| | | } |
| | | } |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | .tools { |
| | | display: flex; |
| | | justify-content: flex-start; |
| | | align-items: center; |
| | | flex-direction: column; |
| | | width: 46px; |
| | | position: absolute; |
| | | left: 0px; |
| | | top: 340px; |
| | | z-index: 99; |
| | | border-radius: 5px; |
| | | height: auto; |
| | | background-color: #fff; |
| | | user-select: none; |
| | | |
| | | box-shadow: 0 3px 6px -4px rgba(0, 0, 0, 0.12), |
| | | 0 6px 16px 0 rgba(0, 0, 0, 0.08), 0 9px 28px 8px rgba(0, 0, 0, 0.05); |
| | | // border: 1px solid #e2e2e2; |
| | | // box-shadow: 0px 1px 5px #aaa; |
| | | .box { |
| | | width: 39px; |
| | | height: 39px; |
| | | flex-shrink: 0; |
| | | display: flex; |
| | | flex-shrink: 1; |
| | | justify-content: center; |
| | | align-items: center; |
| | | cursor: pointer; |
| | | |
| | | &:hover { |
| | | color: #5a84ff; |
| | | } |
| | | &:active { |
| | | opacity: 0.7; |
| | | } |
| | | > span { |
| | | font-size: 10px; |
| | | } |
| | | .icon { |
| | | width: 26px; |
| | | height: 26px; |
| | | padding: 4px; |
| | | border-radius: 4px; |
| | | display: flex; |
| | | justify-content: center; |
| | | align-items: center; |
| | | |
| | | &:hover { |
| | | .img { |
| | | filter: invert(50%) sepia(45%) saturate(3890%) hue-rotate(208deg) |
| | | brightness(102%) contrast(106%); |
| | | } |
| | | } |
| | | } |
| | | .selectNode { |
| | | background-color: rgba(90, 132, 255, 0.9); |
| | | .img { |
| | | filter: invert(100%) sepia(6%) saturate(7478%) hue-rotate(180deg) |
| | | brightness(101%) contrast(106%); |
| | | } |
| | | &:hover { |
| | | background-color: rgba(90, 132, 255, 0.9); |
| | | .img { |
| | | filter: invert(100%) sepia(6%) saturate(7478%) hue-rotate(180deg) |
| | | brightness(101%) contrast(106%); |
| | | } |
| | | } |
| | | } |
| | | } |
| | | .nodeBox { |
| | | width: 100%; |
| | | height: 45px; |
| | | flex-direction: column; |
| | | } |
| | | .boxLi { |
| | | width: 100%; |
| | | height: 45px; |
| | | font-size: 10px; |
| | | display: flex; |
| | | justify-content: center; |
| | | align-items: center; |
| | | flex-direction: column; |
| | | > span { |
| | | margin-top: 2px; |
| | | } |
| | | } |
| | | } |
| | | .popover { |
| | | padding-right: 0 !important; |
| | | } |
| | | .nodes { |
| | | width: 100%; |
| | | max-height: 350px; |
| | | min-height: 170px; |
| | | display: flex; |
| | | align-items: center; |
| | | justify-content: flex-start; |
| | | flex-direction: column; |
| | | // border-radius: 5px; |
| | | // position: absolute; |
| | | // border: 1px solid #e2e2e2; |
| | | // left: 85px; |
| | | // top: 56px; |
| | | z-index: 9; |
| | | overflow: auto; |
| | | background-color: #fff; |
| | | |
| | | .ul { |
| | | width: 100%; |
| | | display: flex; |
| | | align-items: flex-start; |
| | | justify-content: flex-start; |
| | | padding: 0; |
| | | margin: 0; |
| | | flex-wrap: wrap; |
| | | flex: 1; |
| | | |
| | | .li { |
| | | width: 154px; |
| | | height: 30px; |
| | | list-style-type: none; |
| | | font-size: 12px; |
| | | color: #333; |
| | | display: flex; |
| | | align-items: center; |
| | | padding: 5px 10px; |
| | | border: 1px solid #ddd; |
| | | border-radius: 5px; |
| | | // box-shadow: 0px 1px 3px #ccc; |
| | | cursor: pointer; |
| | | margin: 0 5px; |
| | | margin-top: 5px; |
| | | cursor: move; |
| | | |
| | | .icon { |
| | | margin-right: 10px; |
| | | } |
| | | &:hover { |
| | | color: #5a84ff; |
| | | border: 1px solid #5b8ff9; |
| | | } |
| | | } |
| | | } |
| | | } |
| | | .hoverEdge { |
| | | filter: brightness(2.5); |
| | | } |
| | | .hide { |
| | | display: none; |
| | | } |
| | | .boxShow { |
| | | color: rgba(90, 132, 255); |
| | | .icon { |
| | | background-color: rgba(90, 132, 255); |
| | | } |
| | | .img { |
| | | filter: brightness(2.5); |
| | | } |
| | | } |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | import { |
| | | computed, |
| | | ref, |
| | | defineComponent, |
| | | onUnmounted, |
| | | watch, |
| | | onMounted, |
| | | } from 'vue' |
| | | import styles from './Tools.module.scss' |
| | | import Icon from '@/components/Icon/Icon' |
| | | import { injectStore } from '../../core/store' |
| | | import { _t } from '@/libs/Language/Language' |
| | | |
| | | export default defineComponent({ |
| | | props: { |
| | | nodeData: { |
| | | type: Array, |
| | | default: () => [], |
| | | }, |
| | | edgeData: { |
| | | type: Array, |
| | | default: () => [], |
| | | }, |
| | | }, |
| | | emits: ['dragstart', 'edgeClick'], |
| | | setup(props, ctx) { |
| | | const visible = ref(false) |
| | | const { selected } = injectStore() |
| | | let flag = false |
| | | const activeNames = ref<string[]>([]) |
| | | const onClickBox = (event: MouseEvent | TouchEvent) => { |
| | | nodeData.value.forEach((item: any) => { |
| | | if (!activeNames.value.includes(item.group)) { |
| | | activeNames.value.push(item.group) |
| | | } |
| | | }) |
| | | if (!flag) { |
| | | event.stopPropagation() |
| | | visible.value = !visible.value |
| | | } |
| | | } |
| | | const onTouchstart = (event: TouchEvent) => { |
| | | flag = true |
| | | visible.value = !visible.value |
| | | event.stopPropagation() |
| | | } |
| | | const onTouchstartBox = (event: TouchEvent) => { |
| | | event.stopPropagation() |
| | | } |
| | | const onClickEdge = (item: any) => { |
| | | selected.value = item.type === selected.value ? null : item.type |
| | | ctx.emit('edgeClick', selected.value) |
| | | } |
| | | const nodeData = computed(() => { |
| | | return props.nodeData || [] |
| | | }) |
| | | |
| | | const nodeMap = computed(() => { |
| | | const nodeData = props.nodeData || [] |
| | | const map: Record<string, any[]> = {} |
| | | nodeData.forEach((item: any) => { |
| | | map[item.group] = map[item.group] || [] |
| | | map[item.group].push(item) |
| | | }) |
| | | return map |
| | | }) |
| | | |
| | | const edgeData = computed(() => { |
| | | return props.edgeData || [] |
| | | }) |
| | | |
| | | const onDragstart = (item: Record<string, any>, event: DragEvent) => { |
| | | ctx.emit('dragstart', item) |
| | | } |
| | | |
| | | const onCollapseChange = (v: string) => {} |
| | | |
| | | document.addEventListener('click', () => { |
| | | if (visible.value && !flag) { |
| | | visible.value = false |
| | | } |
| | | }) |
| | | document.addEventListener('touchstart', () => { |
| | | if (visible.value) { |
| | | visible.value = false |
| | | } |
| | | }) |
| | | |
| | | onUnmounted(() => { |
| | | selected.value = null |
| | | }) |
| | | |
| | | // watch(nodeData, (data: any[]) => { |
| | | |
| | | // }) |
| | | |
| | | return () => { |
| | | return ( |
| | | <div> |
| | | {/* å·¥å
·ç®± */} |
| | | <div class={[styles.tools]}> |
| | | <el-popover |
| | | placement="right-end" |
| | | width={365} |
| | | trigger="click" |
| | | popper-class={styles.popover} |
| | | visible={visible.value} |
| | | v-slots={{ |
| | | reference: () => { |
| | | return ( |
| | | <div |
| | | onClick={onClickBox} |
| | | onTouchstart={onTouchstart} |
| | | class={{ |
| | | [styles.box]: true, |
| | | [styles.nodeBox]: true, |
| | | [styles.boxShow]: visible.value, |
| | | }} |
| | | > |
| | | <el-tooltip |
| | | class="box-item" |
| | | effect="dark" |
| | | content={_t('æ´»å¨èç¹')} |
| | | placement="right" |
| | | > |
| | | <div |
| | | class={{ |
| | | [styles.icon]: true, |
| | | [styles.selectNode]: visible.value, |
| | | }} |
| | | > |
| | | <Icon |
| | | class={styles.img} |
| | | icon="node1" |
| | | width={20} |
| | | height={20} |
| | | draggable={false} |
| | | ></Icon> |
| | | </div> |
| | | </el-tooltip> |
| | | </div> |
| | | ) |
| | | }, |
| | | }} |
| | | > |
| | | <div |
| | | class={{ |
| | | [styles.nodes]: true, |
| | | }} |
| | | onTouchstart={onTouchstartBox} |
| | | > |
| | | <el-collapse |
| | | v-model={activeNames.value} |
| | | onChange={onCollapseChange} |
| | | onClick={(event: Event) => event?.stopPropagation()} |
| | | style={{ width: 'calc(100% - 10px)', marginRight: '10px' }} |
| | | > |
| | | {Object.keys(nodeMap.value).map((key) => { |
| | | const nodes = nodeMap.value[key] |
| | | return ( |
| | | <el-collapse-item title={key} name={key}> |
| | | <ul class={styles.ul}> |
| | | {nodes.map((item: any) => { |
| | | return ( |
| | | <el-tooltip |
| | | class="box-item" |
| | | effect="dark" |
| | | content={item.description} |
| | | key={item.type} |
| | | placement="top" |
| | | > |
| | | <li |
| | | onDragstart={(event) => |
| | | onDragstart(item, event) |
| | | } |
| | | draggable |
| | | class={styles.li} |
| | | > |
| | | {item.imageRef ? ( |
| | | <Icon |
| | | class={styles.icon} |
| | | icon={item.imageRef} |
| | | width={15} |
| | | height={15} |
| | | ></Icon> |
| | | ) : null} |
| | | |
| | | {item.name} |
| | | </li> |
| | | </el-tooltip> |
| | | ) |
| | | })} |
| | | </ul> |
| | | </el-collapse-item> |
| | | ) |
| | | })} |
| | | </el-collapse> |
| | | </div> |
| | | </el-popover> |
| | | |
| | | {edgeData.value.map((item: any, index: number) => { |
| | | return ( |
| | | <div |
| | | key={item.type} |
| | | onClick={() => onClickEdge(item)} |
| | | class={{ |
| | | [styles.box]: true, |
| | | [styles.boxLi]: true, |
| | | [styles.boxShow]: selected.value === item.type, |
| | | }} |
| | | > |
| | | <el-tooltip |
| | | class="box-item" |
| | | effect="dark" |
| | | content={item.name} |
| | | placement="right" |
| | | > |
| | | <div |
| | | class={{ |
| | | [styles.icon]: true, |
| | | [styles.selectNode]: selected.value === item.type, |
| | | }} |
| | | > |
| | | <Icon |
| | | // @ts-ignore |
| | | class={{ |
| | | [styles.img]: true, |
| | | }} |
| | | draggable={false} |
| | | icon={item.imageRef} |
| | | width={20} |
| | | height={20} |
| | | ></Icon> |
| | | </div> |
| | | </el-tooltip> |
| | | |
| | | {/* <span>{item.name}</span> */} |
| | | </div> |
| | | ) |
| | | })} |
| | | </div> |
| | | {/* èç¹ */} |
| | | </div> |
| | | ) |
| | | } |
| | | }, |
| | | }) |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | .g6-tooltip { |
| | | border-radius: 6px; |
| | | font-size: 12px; |
| | | color: #fff; |
| | | background-color: #000; |
| | | padding: 2px 8px; |
| | | text-align: center; |
| | | } |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | import G6 from '@antv/g6' |
| | | import './Tooltip.scss' |
| | | export default () => |
| | | new G6.Tooltip({ |
| | | offsetX: 35, |
| | | offsetY: 30, |
| | | itemTypes: ['node'], |
| | | getContent: (e: any) => { |
| | | return `<span>${e?.item.getModel().name}</span>` |
| | | }, |
| | | }) |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | import { NODES, TYPE, ConditionType } from './enum' |
| | | import { Create } from '@/libs/Create/Create' |
| | | import { v4 as uuidv4 } from 'uuid' |
| | | import { fontSize, nodeFontSize } from '../components/Nodes' |
| | | |
| | | interface NodeItem { |
| | | type: TYPE.NODE | TYPE.EDGE |
| | | label: string |
| | | } |
| | | |
| | | interface PointType { |
| | | x: number |
| | | y: number |
| | | properties: any |
| | | } |
| | | export default class Core { |
| | | createNode({ label, type }: NodeItem, { x, y, properties }: PointType) { |
| | | const id = uuidv4() |
| | | return new Create({ |
| | | id, |
| | | type, |
| | | label, |
| | | x, |
| | | y, |
| | | properties, |
| | | Name: label, |
| | | name: label, |
| | | }) |
| | | } |
| | | setDefaultProps() { |
| | | return { |
| | | fitCenter: true, |
| | | animate: true, |
| | | minZoom: 0.2, |
| | | maxZoom: 1.4, |
| | | defaultNode: { |
| | | type: NODES.ACTIVITIES, |
| | | labelCfg: { |
| | | style: { |
| | | fill: '#333', |
| | | fontSize: nodeFontSize, |
| | | textAlign: 'center', |
| | | textBaseline: 'middle', |
| | | fontWeight: 'bold', |
| | | }, |
| | | }, |
| | | }, |
| | | defaultEdge: { |
| | | type: 'polyline', |
| | | |
| | | labelCfg: { |
| | | // refX: 10, |
| | | // refY: -5, |
| | | style: { |
| | | fill: '#333', |
| | | stroke: '#aaa', |
| | | fontSize: fontSize - 2, |
| | | }, |
| | | }, |
| | | style: { |
| | | radius: 20, |
| | | offset: 45, |
| | | endArrow: true, |
| | | lineWidth: 3, |
| | | stroke: '#aaa', |
| | | // router: true, |
| | | }, |
| | | }, |
| | | edgeStateStyles: { |
| | | active: { |
| | | stroke: '#5a84ff', |
| | | lineWidth: 6, |
| | | 'text-shape': { |
| | | fontSize: fontSize, |
| | | }, |
| | | }, |
| | | hover: { |
| | | stroke: '#5a84ff', |
| | | lineWidth: 6, |
| | | 'text-shape': { |
| | | fontSize: fontSize, |
| | | }, |
| | | }, |
| | | }, |
| | | nodeStateStyles: { |
| | | hover: { |
| | | stroke: '#d9d9d9', |
| | | fill: '#8ca9ff', |
| | | 'text-shape': { |
| | | fill: '#fff', |
| | | }, |
| | | }, |
| | | active: { |
| | | stroke: 'rgb(104 53 255 / 50%)', |
| | | shadowColor: '#5b8ff9', |
| | | shadowBlur: 7, |
| | | 'text-shape': { |
| | | fill: '#333', |
| | | }, |
| | | }, |
| | | selected: { |
| | | stroke: 'rgb(104 53 255 / 50%)', |
| | | fill: '#8ca9ff', |
| | | 'text-shape': { |
| | | fill: '#fff', |
| | | }, |
| | | }, |
| | | }, |
| | | } |
| | | } |
| | | static createRoot() { |
| | | return new Create({ |
| | | id: 'å¯å¨', |
| | | type: NODES.ACTIVITIES, |
| | | isRoot: true, |
| | | text: { |
| | | x: 0, |
| | | y: 0, |
| | | }, |
| | | label: 'å¯å¨', |
| | | properties: { |
| | | Alias: 'å¯å¨', |
| | | Name: 'å¯å¨', |
| | | Description: '', |
| | | EnterMode: '', |
| | | ExitMode: '', |
| | | JoinType: '', |
| | | SplitType: '', |
| | | ExtendedProperty: '', |
| | | [ConditionType]: '', |
| | | type: NODES.ACTIVITIES, |
| | | id: 'å¯å¨', |
| | | name: 'å¯å¨', |
| | | label: 'å¯å¨', |
| | | }, |
| | | isEdit: true, |
| | | }) |
| | | } |
| | | |
| | | static createBaseXml(name?: string) { |
| | | name = name || '' |
| | | return `<ProcessflowDefine Version="1"> |
| | | <Define> |
| | | <ProcessflowBuilder xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema"> |
| | | <Parameters></Parameters> |
| | | <Name>${name}</Name> |
| | | <Description></Description> |
| | | <Root xsi:type=""> |
| | | <Alias>å¯å¨</Alias> |
| | | <Name>å¯å¨</Name> |
| | | <Description></Description> |
| | | <EnterMode></EnterMode> |
| | | <ExitMode></ExitMode> |
| | | <JoinType></JoinType> |
| | | <SplitType></SplitType> |
| | | <ExtendedProperty></ExtendedProperty> |
| | | </Root> |
| | | <Activities></Activities> |
| | | <Transitions></Transitions> |
| | | </ProcessflowBuilder> |
| | | </Define> |
| | | <Appearance> |
| | | <ProcessflowAppearance> |
| | | <å¯å¨> |
| | | <x>74.55000000000001</x> |
| | | <y>56.25</y> |
| | | </å¯å¨> |
| | | </ProcessflowAppearance> |
| | | </Appearance> |
| | | </ProcessflowDefine>` |
| | | } |
| | | } |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | import G6, { Edge, Graph } from '@antv/g6' |
| | | import {} from './store' |
| | | import { onUnmounted, ref } from 'vue' |
| | | import { cloneDeep } from 'lodash' |
| | | import { fontSize } from '../components/Nodes' |
| | | import type { Store, StoreKey } from '../type/index' |
| | | import { ConditionType } from './enum' |
| | | |
| | | export default class GraphEvent { |
| | | store: Store |
| | | graph: Graph | null = null |
| | | position = ref<{ x: number; y: number }>({ x: 0, y: 0 }) |
| | | visible = ref<boolean>(false) |
| | | isShow = ref<boolean>(false) |
| | | model = ref<any>(null) |
| | | item = ref<any>(null) |
| | | type = ref<string>('') |
| | | isContextMenu = ref<boolean>(false) |
| | | layout = {} |
| | | isChange = false |
| | | touchTime = 0 |
| | | touchMoveTime = 0 |
| | | currentTouchTime = 0 |
| | | touchEvent = {} as any |
| | | currentPosition: null | { |
| | | x: number |
| | | y: number |
| | | controlPointsMap?: Record< |
| | | string | number, |
| | | Array<{ |
| | | x: number |
| | | y: number |
| | | }> |
| | | > |
| | | } = null |
| | | constructor(store: Store) { |
| | | this.store = store |
| | | this.nodeContextMenu = this.nodeContextMenu.bind(this) |
| | | this.edgeContextMenu = this.edgeContextMenu.bind(this) |
| | | this.edgeMouseOver = this.edgeMouseOver.bind(this) |
| | | this.edgeClick = this.edgeClick.bind(this) |
| | | this.onNodeMouseMove = this.onNodeMouseMove.bind(this) |
| | | this.onNodeTouchStart = this.onNodeTouchStart.bind(this) |
| | | this.onNodeTouchEnd = this.onNodeTouchEnd.bind(this) |
| | | this.onNodeTouchmove = this.onNodeTouchmove.bind(this) |
| | | this.cancelEvent = this.cancelEvent.bind(this) |
| | | this.onAfterCreateEdge = this.onAfterCreateEdge.bind(this) |
| | | this.onCanvasContextMenu = this.onCanvasContextMenu.bind(this) |
| | | |
| | | document.addEventListener('touchstart', this.cancelEvent, true) |
| | | document.addEventListener( |
| | | 'click', |
| | | (...arg) => this.cancelEvent(...arg, 'click'), |
| | | true |
| | | ) |
| | | } |
| | | cancelEvent(e?: Event, type?: string) { |
| | | this.touchMoveTime = 0 |
| | | if (!type) { |
| | | const t = setTimeout(() => { |
| | | this.isShow.value = false |
| | | clearTimeout(t) |
| | | }, 200) |
| | | } else { |
| | | this.isShow.value = false |
| | | } |
| | | } |
| | | |
| | | onUnmounted() { |
| | | document.removeEventListener('touchstart', this.cancelEvent, true) |
| | | document.removeEventListener('click', this.cancelEvent, true) |
| | | } |
| | | |
| | | init(graph: Graph, layout: Record<string, any>) { |
| | | this.touchMoveTime = 0 |
| | | this.touchTime = 0 |
| | | this.currentTouchTime = 0 |
| | | this.graph = graph |
| | | this.layout = layout |
| | | |
| | | this.graph.on('canvas:contextmenu', this.onCanvasContextMenu) |
| | | this.graph.on('canvas:touchmove', this.onNodeTouchmove) |
| | | this.graph.on('node:touchstart', this.onNodeTouchStart) |
| | | this.graph.on('edge:touchstart', this.onNodeTouchStart) |
| | | this.graph.on('touchend', this.onNodeTouchEnd) |
| | | this.graph.on('node:contextmenu', this.nodeContextMenu) |
| | | this.graph.on('edge:contextmenu', this.edgeContextMenu) |
| | | this.graph.on('node:mouseenter', (...arg) => { |
| | | this.currentPosition = null |
| | | this.nodeMouseOver(...arg, true) |
| | | }) |
| | | this.graph.on('node:mouseleave', (...arg) => |
| | | this.nodeMouseOver(...arg, false) |
| | | ) |
| | | |
| | | this.graph.on('edge:mouseenter', (...arg) => |
| | | this.edgeMouseOver(...arg, true) |
| | | ) |
| | | this.graph.on('edge:mouseleave', (...arg) => |
| | | this.edgeMouseOver(...arg, false) |
| | | ) |
| | | this.graph.on('edge:click', (...arg) => this.edgeClick(...arg)) |
| | | |
| | | this.graph.on('aftercreateedge', this.onAfterCreateEdge) |
| | | } |
| | | onCanvasContextMenu(event: Event) { |
| | | event?.preventDefault() |
| | | } |
| | | onAfterCreateEdge({ edge }: { edge: Edge }) { |
| | | const model: any = edge.getModel() |
| | | if (!model.properties) { |
| | | model.properties = {} |
| | | } |
| | | if (!model.properties[ConditionType]) { |
| | | model.properties[ConditionType] = this.store.selected.value |
| | | } |
| | | edge.update(model) |
| | | } |
| | | onNodeTouchmove(event: TouchEvent) { |
| | | this.touchTime = 0 |
| | | this.touchMoveTime++ |
| | | if (this.touchMoveTime < 20) { |
| | | this.touchTime = this.currentTouchTime |
| | | } |
| | | } |
| | | onNodeTouchEnd(event: Event | any) { |
| | | event.stopPropagation() |
| | | if (this.touchTime !== 0) { |
| | | const now = Date.now() |
| | | const time = now - this.touchTime |
| | | if (time > 300) { |
| | | this.nodeContextMenu(this.touchEvent) |
| | | } |
| | | } |
| | | this.touchTime = 0 |
| | | this.currentTouchTime = 0 |
| | | } |
| | | onNodeTouchStart(event: Event | any) { |
| | | this.touchEvent = event |
| | | this.touchTime = Date.now() |
| | | this.currentTouchTime = Date.now() |
| | | event.stopPropagation() |
| | | } |
| | | contextMenuSetting(event: any | Event) { |
| | | event?.preventDefault() |
| | | this.model.value = event.item?.getModel() |
| | | this.position.value = { |
| | | x: event.clientX, |
| | | y: event.clientY, |
| | | } |
| | | this.visible.value = true |
| | | this.isShow.value = true |
| | | this.item.value = event.item |
| | | this.type.value = event.item?._cfg.type |
| | | } |
| | | nodeContextMenu(event: any | Event) { |
| | | this.item.value = event.item |
| | | this.contextMenuSetting(event) |
| | | } |
| | | edgeContextMenu(event: any | Event) { |
| | | this.item.value = event.item |
| | | this.isContextMenu.value = true |
| | | this.graph?.setItemState(event.item, 'hover', true) |
| | | this.contextMenuSetting(event) |
| | | } |
| | | edgeMouseOver(event: any | Event, type: boolean) { |
| | | const { item } = event |
| | | this.item.value = event.item |
| | | if (!this.isContextMenu.value) { |
| | | const model = item.getModel() || {} |
| | | const style = model.style || {} |
| | | if (!style['text-shape']) { |
| | | style['text-shape'] = { |
| | | fontSize: fontSize, |
| | | } |
| | | } |
| | | this.graph?.setItemState(item, 'hover', type) |
| | | } |
| | | } |
| | | nodeMouseOver(event: any | Event, type: boolean) { |
| | | this.graph?.setItemState(event.item, 'active', type) |
| | | } |
| | | edgeClick(event: any | Event) { |
| | | const { item } = event |
| | | this.item.value = event.item |
| | | this.graph?.setItemState(item, 'selected', true) |
| | | } |
| | | clearAllState() { |
| | | // æ¸
é¤ 'active' ä¸ 'hover' ç¶æ |
| | | this.isContextMenu.value = false |
| | | this.item.value?.clearStates(['actived', 'hover', 'selected']) |
| | | this.item.value = null |
| | | } |
| | | onNodeMouseMove(nodeData: any) { |
| | | if (nodeData.name !== 'drag' && !this.currentPosition) { |
| | | const model = nodeData.item.getModel() || {} |
| | | return (this.currentPosition = { |
| | | x: model.x, |
| | | y: model.y, |
| | | }) |
| | | } |
| | | if (this.currentPosition && nodeData.name === 'drag') { |
| | | const edges = nodeData.item.getEdges() |
| | | const model = nodeData.item.getModel() || {} |
| | | const { x, y } = model |
| | | const diffX = x - this.currentPosition.x |
| | | const diffY = y - this.currentPosition.y |
| | | edges.forEach((edge: any, index: number) => { |
| | | const edgeModel = cloneDeep(edge.getModel() || {}) |
| | | |
| | | if ( |
| | | this.currentPosition && |
| | | !this.currentPosition?.controlPointsMap?.[index] |
| | | ) { |
| | | const controlPointsMap = this.currentPosition.controlPointsMap || {} |
| | | controlPointsMap[index] = edgeModel.controlPoints || [] |
| | | this.currentPosition.controlPointsMap = controlPointsMap |
| | | } |
| | | const controlPoints = cloneDeep( |
| | | this.currentPosition?.controlPointsMap?.[index] || [] |
| | | ) |
| | | |
| | | controlPoints.forEach((point: { x: number; y: number }) => { |
| | | point.x = point.x + diffX |
| | | point.y = point.y + diffY |
| | | }) |
| | | edgeModel.controlPoints = controlPoints |
| | | this.graph?.updateItem(edge, edgeModel) |
| | | // edgeModel.controlPoints = [] |
| | | }) |
| | | } |
| | | // this.graph?.refreshPositions() |
| | | // console.log(edges, this.currentPosition, 'node:mousedown1-2-2-2-11-2210210') |
| | | } |
| | | } |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | export const behaviorMap: { |
| | | [key: string]: string |
| | | } = { |
| | | dragCanvas: 'drag-canvas', |
| | | dragNode: 'drag-node', |
| | | zoomCanvas: 'zoom-canvas', |
| | | clickSelect: 'click-select', |
| | | createEdge: 'create-edge', |
| | | } |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | export const CURVE = 'curve' |
| | | |
| | | export const NODES = { |
| | | ACTIVITIES: 'Activities', |
| | | ACTIVITY: 'StartActivity', |
| | | VARIABLE_MONITOR_ACTIVITY: 'VariableMonitorActivity', |
| | | VARIABLE_READ_ACTIVITY: 'VariableReadActivity', |
| | | MATERIAL_ASSOCIATION_ACTIVITY: 'MaterialAssociationActivity', |
| | | TRAY_ASSOCIATION_ACTIVITY: '"TrayAssociationActivity"', |
| | | VARIABLE_WRITE_ACTIVITY: 'VariableWriteActivity', |
| | | INBOUND_INITIALIZE_ACTIVITY: 'InboundInitializeActivity', |
| | | DETERMINE_PROCESS_ACTIVITY: 'DetermineProcessActivity', |
| | | BUSINESS_ACTIVITY: 'BusinessActivity', |
| | | PRODUCT_STATEDETECTION_ACTIVITY: 'ProductStateDetectionActivity', |
| | | DUPLICATE_CODE_DETECTION_ACTIVITY: 'DuplicateCodeDetectionActivity', |
| | | MISSING_PROCESS_DETECTION_ACTIVITY: 'MissingProcessDetectionActivity', |
| | | OUTBOUND_INITIALIZE_ACTIVITY: 'OutboundInitializeActivity', |
| | | PARAMETER_COLLECT_ACTIVITY: 'ParameterCollectActivity', |
| | | PLC_QUALIFICATION_JUDGMENT_ACTIVITY: 'PLCQualificationJudgmentActivity', |
| | | LOCAL_QUALIFICATION_JUDGMENT_ACTIVITY: 'LocalQualificationJudgmentActivity', |
| | | PARAMETER_SAVE_ACTIVITY: 'ParameterSaveActivity', |
| | | END_ACTIVITY: 'EndActivity', |
| | | ORDINARY_NODE: 'OrdinaryNode', //æ®éèç¹ |
| | | } |
| | | |
| | | export const ActivityKey = [ |
| | | 'Alias', |
| | | 'Name', |
| | | 'EnterMode', |
| | | 'ExitMode', |
| | | 'JoinType', |
| | | 'SplitType', |
| | | 'NeedTagChange', |
| | | 'TaskDelay', |
| | | 'MonitorVariableName', |
| | | 'CompareVariableValue', |
| | | 'ExtendedProperty', |
| | | '@_xsi:type', |
| | | ] |
| | | |
| | | export const TransitionKey = ['Label', 'Condition', 'Sink', 'Source'] |
| | | |
| | | export const ConditionKey = [ |
| | | 'Label', |
| | | 'Expression', |
| | | 'NOT', |
| | | 'Operator', |
| | | 'Property', |
| | | 'Value', |
| | | '@_xsi:type', |
| | | ] |
| | | |
| | | export const ConditionType = '@_xsi:type' |
| | | export const ValueText = '#text' |
| | | |
| | | export enum TYPE { |
| | | NODE = 'node', |
| | | EDGE = 'edge', |
| | | } |
| | | |
| | | /** |
| | | * å¤åç±»å |
| | | */ |
| | | export const CompositeCondition = 'CompositeCondition' |
| | | |
| | | export interface ConditionItemType { |
| | | [ConditionType]: string |
| | | } |
| | | export enum OpType { |
| | | RelOpEqual = '=', |
| | | RelOpLess = '<', |
| | | RelOpLarge = '>', |
| | | RelOpLessEq = '<=', |
| | | RelOpLargeEq = '>=', |
| | | RelOpNotEqual = '!=', |
| | | RelOpContain = 'Contains', |
| | | } |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | import { provide, inject, ref, isRef, Ref, reactive, toRaw } from 'vue' |
| | | import mitt from 'mitt' |
| | | import type { Store, StoreKey } from '../type/index' |
| | | import GraphEvent from './GraphEvent' |
| | | |
| | | const selected = ref(null) |
| | | const lf = ref() |
| | | const theme = ref({}) |
| | | const lastLines = ref<any[]>([]) |
| | | /** |
| | | * Name,value |
| | | */ |
| | | const flowMap: Map<string, any> = new Map() |
| | | /** |
| | | * id,value |
| | | */ |
| | | const flowNodeMap: Map<string, any> = new Map() |
| | | const xmlData = ref(null) |
| | | /** |
| | | * ä¿åæ¶é
ç½® |
| | | */ |
| | | const flowBaseConfig = ref<{ |
| | | type?: number |
| | | version?: number |
| | | content?: string |
| | | }>({}) |
| | | const edgeMap = new Map() |
| | | const nodeMap = new Map() |
| | | const flowConfig: { |
| | | type?: number |
| | | version?: number |
| | | } = {} |
| | | export const baseStore: any = { |
| | | lf, |
| | | theme, |
| | | xmlData, |
| | | flowNodeMap, |
| | | edgeMap, |
| | | flowMap, |
| | | selected, |
| | | lastLines, |
| | | flowBaseConfig, |
| | | nodeMap, |
| | | flowConfig, |
| | | } |
| | | const graphEvent = new GraphEvent(baseStore) |
| | | const store = { |
| | | ...baseStore, |
| | | graphEvent, |
| | | } as Store |
| | | |
| | | export const resetStore = () => { |
| | | flowMap.clear() |
| | | flowNodeMap.clear() |
| | | flowBaseConfig.value = {} |
| | | xmlData.value = null |
| | | lastLines.value = [] |
| | | edgeMap.clear() |
| | | nodeMap.clear() |
| | | } |
| | | export const createStore = () => { |
| | | return store |
| | | } |
| | | |
| | | export const injectStore = (key?: StoreKey) => { |
| | | if (key) { |
| | | return store[key] |
| | | } |
| | | return store as Store |
| | | } |
| | | |
| | | export const emitter = mitt() |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | import { XMLParser, XMLBuilder } from 'fast-xml-parser' |
| | | import { |
| | | CURVE, |
| | | NODES, |
| | | ActivityKey, |
| | | TransitionKey, |
| | | ConditionKey, |
| | | ConditionType, |
| | | ValueText, |
| | | } from './enum' |
| | | import { v4 as uuidv4 } from 'uuid' |
| | | import { injectStore, resetStore } from './store' |
| | | import { Condition, FlowType } from '../type' |
| | | import { cloneDeep, isNil, set, get, isNull, omitBy } from 'lodash' |
| | | import { nodeFontSize } from '../components/Nodes' |
| | | import { _t } from '@/libs/Language/Language' |
| | | const { flowMap, xmlData, flowNodeMap } = injectStore() |
| | | import G6 from '@antv/g6' |
| | | import Core from './Core' |
| | | import { ElMessage } from 'element-plus' |
| | | |
| | | export const isFirstLetterUpperCase = (str: string) => { |
| | | // ä½¿ç¨æ£åè¡¨è¾¾å¼æ£æ¥é¦åæ¯æ¯å¦ä¸ºå¤§å |
| | | return /^[A-Z]/.test(str) || str === ConditionType |
| | | } |
| | | |
| | | export const fittingString = ( |
| | | str: string, |
| | | maxWidth: number, |
| | | fontSize: number |
| | | ) => { |
| | | const ellipsis = '...' |
| | | const ellipsisLength = G6.Util.getTextSize(ellipsis, fontSize)[0] |
| | | let currentWidth = 0 |
| | | let res = str |
| | | const pattern = new RegExp('[\u4E00-\u9FA5]+') // distinguish the Chinese charactors and letters |
| | | str.split('').forEach((letter, i) => { |
| | | if (currentWidth > maxWidth - ellipsisLength) return |
| | | if (pattern.test(letter)) { |
| | | // Chinese charactors |
| | | currentWidth += fontSize |
| | | } else { |
| | | // get the width of single letter according to the fontSize |
| | | currentWidth += G6.Util.getLetterWidth(letter, fontSize) |
| | | } |
| | | if (currentWidth > maxWidth - ellipsisLength) { |
| | | res = `${str.substr(0, i)}${ellipsis}` |
| | | } |
| | | }) |
| | | return res |
| | | } |
| | | |
| | | /** |
| | | * è·åxmlå符串çjson对象 |
| | | * @param xml |
| | | * @returns |
| | | */ |
| | | export const getJsonByXml = (xml: string, name?: string) => { |
| | | const options = { |
| | | ignoreAttributes: false, |
| | | attributeNamePrefix: '@_', |
| | | } |
| | | const parser = new XMLParser(options) |
| | | |
| | | try { |
| | | const json = parser.parse(xml) |
| | | xmlData.value = json |
| | | return json |
| | | } catch (error) { |
| | | const newXml = Core.createBaseXml(name) |
| | | const json = parser.parse(newXml) |
| | | xmlData.value = json |
| | | return json |
| | | } |
| | | } |
| | | |
| | | /** |
| | | * è½¬æ¢æµç¨å¾æ°æ®ä¸ºxml |
| | | * @param flowData |
| | | */ |
| | | export const getFlowDataToXml = ({ nodes, edges }: FlowType) => { |
| | | const Activity: any[] = [] |
| | | const Transition: any[] = [] |
| | | const nodeMap: Record<string, any> = {} |
| | | |
| | | nodes.forEach((item) => { |
| | | const obj: Record<string, any> = {} |
| | | Object.keys(item.properties || {}).forEach((key) => { |
| | | if (isFirstLetterUpperCase(key)) { |
| | | obj[key] = item.properties[key] |
| | | } |
| | | }) |
| | | const oldId = item?.properties?.oldId |
| | | const flow = flowMap.get(oldId) |
| | | obj.Name = flow?.properties?.Name || item.properties.Name || '' |
| | | nodeMap[obj.Name] = { |
| | | x: item.x, |
| | | y: item.y, |
| | | } |
| | | Activity.push(obj) |
| | | }) |
| | | |
| | | edges.forEach((item) => { |
| | | const obj: Record<string, any> = {} |
| | | Object.keys(item?.properties || {}).forEach((key) => { |
| | | if (isFirstLetterUpperCase(key)) { |
| | | obj[key] = item.properties[key] |
| | | } |
| | | const condition = item.properties?.Condition || {} |
| | | Object.keys(condition || {}).forEach((key) => { |
| | | obj.Condition = obj.Condition || {} |
| | | if (isFirstLetterUpperCase(key)) { |
| | | obj.Condition[key] = condition[key] |
| | | } |
| | | }) |
| | | }) |
| | | obj.Condition = handleConditionChildren(obj.Condition) |
| | | |
| | | if (!Object.keys(obj.Condition).length) { |
| | | delete obj.Condition |
| | | } |
| | | const oldSourceId = item.properties?.oldSourceId |
| | | const oldTargetId = item.properties?.oldTargetId |
| | | const flowSource = flowMap.get(oldSourceId) |
| | | const flowTarget = flowMap.get(oldTargetId) |
| | | if (oldSourceId && oldTargetId) { |
| | | obj.Source = flowSource?.properties?.Name || '' |
| | | obj.Sink = flowTarget?.properties?.Name || '' |
| | | } else { |
| | | const sourceName = flowNodeMap.get(item?.source)?.name |
| | | const sinkName = flowNodeMap.get(item?.target)?.name |
| | | obj.Source = sourceName |
| | | obj.Sink = sinkName |
| | | } |
| | | nodeMap[`${obj.Source}_${obj.Sink}`] = { |
| | | controlPoints: item.controlPoints, |
| | | endPoint: item.endPoint, |
| | | startPoint: item.startPoint, |
| | | } |
| | | Transition.push(obj) |
| | | }) |
| | | |
| | | // æµç¨å¾ç»æ |
| | | return getXmlByJson(Activity, Transition, nodeMap) |
| | | } |
| | | /** |
| | | * 转æ¢å¯¹è±¡ï¼å°åå大åçåæµ |
| | | */ |
| | | export const translationObj = (obj: Record<string, any>) => { |
| | | const up: Record<string, any> = {} |
| | | const low: Record<string, any> = {} |
| | | if (isNil(obj)) return null |
| | | Object.entries(obj).forEach(([key, value]) => { |
| | | if (isFirstLetterUpperCase(key)) { |
| | | up[key] = value |
| | | } else { |
| | | low[key] = value |
| | | } |
| | | }) |
| | | return { |
| | | up, |
| | | low, |
| | | } |
| | | } |
| | | /** |
| | | * å¤ç夿æ¡ä»¶çåé |
| | | */ |
| | | const handleConditionChildren = (condition: Condition) => { |
| | | const newCondition = cloneDeep(condition) |
| | | const deepConditionFn = (condition: Condition) => { |
| | | let conditionObj: any = {} |
| | | const obj = translationObj(condition) |
| | | |
| | | if (Array.isArray(condition?.children) && condition?.children?.length > 0) { |
| | | const Condition: any[] = [] |
| | | condition?.children.forEach((item) => { |
| | | Condition.push(deepConditionFn(item)) |
| | | }) |
| | | conditionObj = { |
| | | Conditions: { |
| | | Condition, |
| | | }, |
| | | } |
| | | } |
| | | if (obj) { |
| | | Object.assign(conditionObj, obj.up) |
| | | } |
| | | return conditionObj |
| | | } |
| | | return deepConditionFn(newCondition) |
| | | } |
| | | |
| | | /** |
| | | * å¤çName为Idçæ
åµï¼ä¸ºå¯æ¹å¨ |
| | | * æ°æ®è½¬æ¢ï¼å°Idæ¢æUUID |
| | | */ |
| | | export const transformFlowStructByNodeId = ({ |
| | | nodes, |
| | | edges, |
| | | }: { |
| | | nodes: any[] |
| | | edges: any[] |
| | | }) => { |
| | | const newNodes = nodes.map((item) => { |
| | | const { id } = item.properties |
| | | const uuid = uuidv4() |
| | | const node = { |
| | | ...item, |
| | | id: uuid, |
| | | name: id, |
| | | type: NODES.ACTIVITIES, |
| | | properties: { |
| | | ...item.properties, |
| | | name: id, |
| | | id: uuid, |
| | | oldId: id, |
| | | }, |
| | | } |
| | | flowMap.set(id, node) |
| | | flowNodeMap.set(uuid, node) |
| | | return node |
| | | }) |
| | | |
| | | const newEdges = edges.map((item) => { |
| | | const { sourceNodeId, targetNodeId } = item |
| | | const id = uuidv4() |
| | | return { |
| | | ...item, |
| | | id, |
| | | label: item.label || item.properties?.Label, |
| | | type: 'polyline', |
| | | targetNodeId: flowMap.get(targetNodeId)?.id || '', |
| | | target: flowMap.get(targetNodeId)?.id || '', |
| | | source: flowMap.get(sourceNodeId)?.id || '', |
| | | sourceNodeId: flowMap.get(sourceNodeId)?.id || '', |
| | | properties: { |
| | | ...item.properties, |
| | | }, |
| | | controlPoints: |
| | | item.controlPoints && !Array.isArray(item.controlPoints) |
| | | ? [item.controlPoints] |
| | | : item.controlPoints, |
| | | } |
| | | }) |
| | | return { |
| | | nodes: newNodes, |
| | | edges: newEdges, |
| | | } |
| | | } |
| | | /** |
| | | * è·åå¹¶è§£ææµç¨å¾ç»æ |
| | | * @param data |
| | | * @returns |
| | | */ |
| | | export const getLogicFLowStruct = (data: Record<string, any>) => { |
| | | try { |
| | | if (Object.keys(data).length === 0) return null |
| | | // è¾¹ |
| | | let Transition = |
| | | data?.ProcessflowDefine?.Define?.ProcessflowBuilder?.Transitions |
| | | .Transition || [] |
| | | // èç¹ |
| | | let Activities = |
| | | data?.ProcessflowDefine?.Define?.ProcessflowBuilder?.Activities |
| | | .Activity || [] |
| | | Activities = Array.isArray(Activities) ? Activities : [Activities] |
| | | Transition = Array.isArray(Transition) ? Transition : [Transition] |
| | | const nodeMap = |
| | | data?.ProcessflowDefine?.Appearance.ProcessflowAppearance || {} |
| | | const Root = data?.ProcessflowDefine.Define.ProcessflowBuilder.Root |
| | | const nodes = Activities.map((item: Record<string, any>) => { |
| | | const type = item[ConditionType] |
| | | const isEnd = type === NODES.END_ACTIVITY |
| | | const { x, y } = nodeMap[item.Name] || {} |
| | | return { |
| | | id: item.Name, |
| | | type: isEnd ? NODES.END_ACTIVITY : NODES.ACTIVITIES, |
| | | x: x || item.x || 0, |
| | | y: y || item.y || 0, |
| | | text: { |
| | | x: item.x || 0, |
| | | y: item.y || 0, |
| | | }, |
| | | label: fittingString(item.Name, 195, nodeFontSize + 2), |
| | | properties: { |
| | | ...item, |
| | | name: item.Alias, |
| | | type: item[ConditionType], |
| | | id: item.Name, |
| | | label: item.Name, |
| | | }, |
| | | } |
| | | }) |
| | | if (Root) { |
| | | const { x, y } = nodeMap[Root.Name] || {} |
| | | nodes.unshift({ |
| | | id: Root.Name, |
| | | type: NODES.ACTIVITIES, |
| | | x: x || 0, |
| | | y: y || 0, |
| | | isRoot: true, |
| | | text: { |
| | | x: 0, |
| | | y: 0, |
| | | }, |
| | | label: fittingString(Root.Name, 195, nodeFontSize + 2), |
| | | properties: { |
| | | ...Root, |
| | | type: Root[ConditionType], |
| | | id: Root.Name, |
| | | name: Root.Alias, |
| | | label: Root.Name, |
| | | }, |
| | | }) |
| | | nodes[0].isEdit = !!(x + y) |
| | | } |
| | | |
| | | // 夿æ¯å¦éè¦èªå®ä¹å¸å± |
| | | const edges = Transition.map((item: Record<string, any>, index: number) => { |
| | | const Condition = item?.Condition |
| | | ? handlerConditionToChildren(item?.Condition) |
| | | : {} |
| | | const edgeItem = nodeMap[`${item.Source}_${item.Sink}`] || {} |
| | | return { |
| | | id: index + 1, |
| | | type: CURVE, |
| | | targetNodeId: item.Sink, |
| | | sourceNodeId: item.Source, |
| | | // text: { |
| | | // x: 0, |
| | | // y: 0, |
| | | // value: item?.Condition?.Label, |
| | | // }, |
| | | label: item?.Condition?.Label || '', |
| | | properties: { |
| | | ...item, |
| | | Condition, |
| | | oldSourceId: item.Source, |
| | | oldTargetId: item.Sink, |
| | | name: item?.Label, |
| | | }, |
| | | ...edgeItem, |
| | | } |
| | | }) |
| | | const flows = { nodes, edges } |
| | | return transformFlowStructByNodeId(flows) |
| | | } catch (error) { |
| | | const data = { |
| | | nodes: [Core.createRoot()], |
| | | edges: [], |
| | | } |
| | | return transformFlowStructByNodeId(data) |
| | | } |
| | | } |
| | | |
| | | /** |
| | | * å°Conditionå¤çætreeç»æ |
| | | */ |
| | | const handlerConditionToChildren = (c: any) => { |
| | | const condition = cloneDeep(c) |
| | | const getConditionTree = (condition: any) => { |
| | | let newCondition: any = {} |
| | | // å¤åæ¡ä»¶-> Condition |
| | | |
| | | if (condition?.Conditions) { |
| | | const Condition = condition.Conditions?.Condition |
| | | const children = [] |
| | | |
| | | if (!Array.isArray(Condition) && Condition[ConditionType]) { |
| | | children.push(Condition) |
| | | } else { |
| | | children.push(...Condition) |
| | | } |
| | | if (Array.isArray(children) && children?.length > 0) { |
| | | const newChildren: any[] = [] |
| | | children.forEach((child) => { |
| | | newChildren.push(getConditionTree(child)) |
| | | }) |
| | | newCondition.children = newChildren |
| | | } |
| | | delete condition.Conditions |
| | | } |
| | | // const Value = |
| | | // typeof condition.Value === 'object' |
| | | // ? condition.Value |
| | | // : { |
| | | // [ValueText]: condition.Value, |
| | | // } |
| | | const currentCondition = { |
| | | ...condition, |
| | | } |
| | | |
| | | Object.assign(newCondition, { |
| | | ...currentCondition, |
| | | }) |
| | | return newCondition |
| | | } |
| | | return getConditionTree(condition) |
| | | } |
| | | |
| | | /** |
| | | * è·åjsonçxmlå符串 |
| | | * @param json |
| | | * @returns |
| | | */ |
| | | export const getXmlByJson = ( |
| | | Activity: any[], |
| | | Transition: any[], |
| | | ProcessflowAppearance?: any |
| | | ) => { |
| | | const json = cloneDeep(xmlData.value) |
| | | const Root = Activity.shift() |
| | | const flowAppearance = get( |
| | | json, |
| | | 'ProcessflowDefine.Appearance.ProcessflowAppearance', |
| | | { |
| | | å¯å¨: {}, |
| | | } |
| | | ) |
| | | set( |
| | | json, |
| | | 'ProcessflowDefine.Define.ProcessflowBuilder.Transitions.Transition', |
| | | Transition |
| | | ) |
| | | set( |
| | | json, |
| | | 'ProcessflowDefine.Define.ProcessflowBuilder.Activities.Activity', |
| | | Activity |
| | | ) |
| | | |
| | | set(json, 'ProcessflowDefine.Define.ProcessflowBuilder.Root', Root) |
| | | set(json, 'ProcessflowDefine.Appearance.ProcessflowAppearance', { |
| | | '@_xmlns:xsi': flowAppearance['@_xmlns:xsi'], |
| | | '@_xmlns:xsd': flowAppearance['@_xmlns:xsd'], |
| | | ...ProcessflowAppearance, |
| | | }) |
| | | |
| | | const builder = new XMLBuilder({ |
| | | ignoreAttributes: false, |
| | | attributeNamePrefix: '@_', |
| | | format: true, |
| | | }) |
| | | const xml = builder.build(json) |
| | | return xml |
| | | } |
| | | /** |
| | | * é¦åæ¯å°å |
| | | * @param str |
| | | * @returns |
| | | */ |
| | | export const toLowerCaseFirstLetter = (str: string) => { |
| | | return str.charAt(0).toLowerCase() + str.slice(1) |
| | | } |
| | | |
| | | /** |
| | | * çéèç¹çtargetçº¿æ¡æåªäºï¼ç¨æ¥å¼å¯å¨ç» |
| | | * @param nodeId |
| | | * @param edges |
| | | * @returns |
| | | */ |
| | | export const getNodeTargetLines = ( |
| | | nodeId: string, |
| | | edges: Record<string, any>[] |
| | | ) => { |
| | | const lines = edges.filter((item: Record<string, any>) => { |
| | | return item.targetNodeId === nodeId |
| | | }) |
| | | return lines |
| | | } |
| | | const removeNullFields: any = (data: any) => { |
| | | if (Array.isArray(data)) { |
| | | return data |
| | | .map((item) => removeNullFields(item)) |
| | | .filter( |
| | | (item) => |
| | | !( |
| | | item === null || |
| | | (Array.isArray(item) && |
| | | item.length === 0 && |
| | | !removeNullFields(item).length) || |
| | | item === '' |
| | | ) |
| | | ) |
| | | } else if (typeof data === 'object' && data !== null) { |
| | | const newObj: any = {} |
| | | for (const key in data) { |
| | | const value = data[key] |
| | | if ( |
| | | (value !== null && value !== '') || |
| | | (Array.isArray(value) && value.length > 0) |
| | | ) { |
| | | newObj[key] = removeNullFields(value) |
| | | } |
| | | } |
| | | return newObj |
| | | } else { |
| | | return data |
| | | } |
| | | } |
| | | /** |
| | | * è¾åºxml |
| | | * @param graph |
| | | * @returns |
| | | */ |
| | | export const generateFlowXml = (graph: any) => { |
| | | const graphData = graph.save() |
| | | const data: any = removeNullFields(graphData) |
| | | return getFlowDataToXml(data) |
| | | } |
| | | |
| | | /** |
| | | * è¾åºxml |
| | | * @param graph |
| | | * @returns |
| | | */ |
| | | export const importXmlInit = (graph: any, xml: string) => { |
| | | try { |
| | | resetStore() |
| | | const json = getJsonByXml(xml) |
| | | const graphData = getLogicFLowStruct(json) |
| | | // graph.destroy() |
| | | graph.data(graphData) |
| | | graph.render() |
| | | } catch (error) { |
| | | ElMessage.error(_t('导å
¥å¤±è´¥')) |
| | | } |
| | | } |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | // export interface |
| | | import GraphEvent from '../core/GraphEvent' |
| | | |
| | | export interface Store { |
| | | lf: any |
| | | xmlData: Ref<any> |
| | | theme: Ref<any> |
| | | flowMap: Map<string, any> |
| | | selected: Ref<any> |
| | | lastLines: Ref<any[]> |
| | | graphEvent: GraphEvent |
| | | flowBaseConfig: Ref<any> |
| | | edgeMap: Map<string, any> |
| | | nodeMap: Map<string, any> |
| | | flowConfig: Ref<any> |
| | | } |
| | | |
| | | export enum StoreKey { |
| | | LF = 'lf', |
| | | THEME = 'theme', |
| | | FLOW_MAP = 'flowMap', |
| | | SELECTED = 'selected', |
| | | LAST_LINES = 'lastLines', |
| | | XML_DATA = 'xmlData', |
| | | } |
| | | |
| | | export interface FlowType { |
| | | edges: any[] |
| | | nodes: any[] |
| | | } |
| | | |
| | | interface Condition { |
| | | '@_xsi:type': string |
| | | _xsiType: string // å¯¹åº "_xsi:type" |
| | | Expression: string |
| | | Label: string |
| | | Not: boolean |
| | | Operator: string |
| | | Property: string |
| | | root: boolean |
| | | Value: string |
| | | // Value: { |
| | | // _xsiType: string // å¯¹åº "@_xsi:type" |
| | | // Text: string | number // å¯¹åº "#text" |
| | | // } |
| | | nodeId: string |
| | | children: Condition[] |
| | | } |
| | |
| | | import { computed, defineComponent } from 'vue' |
| | | import { computed, defineComponent, ref } from 'vue' |
| | | import parse from 'style-to-object' |
| | | export default defineComponent({ |
| | | name: '徿 ', |
| | | props: { |
| | |
| | | type: Number, |
| | | default: 12, |
| | | }, |
| | | draggable: { |
| | | type: Boolean, |
| | | default: false, |
| | | }, |
| | | cursor: { |
| | | type: String, |
| | | default: '', |
| | | }, |
| | | class: { |
| | | type: String, |
| | | default: '', |
| | | }, |
| | | style: { |
| | | type: [Object, String], |
| | | default: () => ({}), |
| | | }, |
| | | }, |
| | | emits: ['click'], |
| | | setup(props, { attrs, slots, emit }) { |
| | | const VITE_STATIC_URL = process.env.VITE_STATIC_URL || '' |
| | | const imgUrl = computed(() => { |
| | | const imgName = props.icon |
| | | return new URL(`../../assets/images/${imgName}.png`, import.meta.url).href |
| | | let imgName = props.icon |
| | | if (!imgName) return '' |
| | | let baseDir = 'images' |
| | | if (imgName.includes('files/')) { |
| | | baseDir = 'files' |
| | | imgName = imgName.split('/')[1] |
| | | } |
| | | return `${VITE_STATIC_URL}/resources/assets/${baseDir}/${imgName}.png` |
| | | }) |
| | | const style = computed(() => { |
| | | if (typeof props.style === 'string') { |
| | | return parse(props.style) |
| | | } |
| | | return props.style |
| | | }) |
| | | |
| | | return () => { |
| | | if (imgUrl.value.includes('undefined')) return null |
| | | |
| | | return ( |
| | | <img |
| | | onClick={(evt: Event) => emit('click', evt)} |
| | | width={props.width} |
| | | height={props.height} |
| | | src={imgUrl.value} |
| | | style={{ cursor: props.cursor, ...style.value }} |
| | | class={props.class} |
| | | {...attrs} |
| | | /> |
| | | ) |
| | |
| | | border-radius: 6px 6px 6px 6px; |
| | | padding: 5px; |
| | | padding: 5px 10px; |
| | | color: #464E54!important; |
| | | color: #464e54 !important; |
| | | margin-left: 0 !important; |
| | | |
| | | >span { |
| | | > span { |
| | | font-size: 14px; |
| | | font-family: PingFang SC, PingFang SC; |
| | | font-weight: 400; |
| | |
| | | :global(.cs-button) { |
| | | color: #464e54; |
| | | } |
| | | |
| | | } |
| | | |
| | | .btn:hover { |
| | | background-color: #ECECEC!important; |
| | | background-color: transparent !important; |
| | | opacity: 1 !important; |
| | | } |
| | | .btn:active { |
| | | background-color: #dbdbdb!important; |
| | | background-color: transparent !important; |
| | | } |
| | | .img { |
| | | width: 16px; |
| | | margin-right: 4px; |
| | | } |
| | | .status { |
| | | &:hover { |
| | | .img { |
| | | filter: invert(49%) sepia(100%) saturate(6281%) hue-rotate(222deg) |
| | | brightness(99%) contrast(99%); |
| | | opacity: 1; |
| | | } |
| | | > span { |
| | | color: #265cfb !important; |
| | | } |
| | | } |
| | | color: #464e54; |
| | | } |
| | | .add { |
| | | .iconFont { |
| | | font-size: 19px; |
| | | color: #5a84ff; |
| | | } |
| | | |
| | | &:hover { |
| | | .iconFont { |
| | | font-size: 19px; |
| | | color: #265cfb; |
| | | } |
| | | > span { |
| | | color: #265cfb !important; |
| | | } |
| | | } |
| | | color: #464e54; |
| | | } |
| | |
| | | emits: ['click'], |
| | | setup(props: IconButtonProps, { attrs, slots, emit }: SetupContext) { |
| | | const imgName = computed(() => props.icon) |
| | | const imgUrl = () => |
| | | new URL(`../../assets/images/${imgName.value}.png`, import.meta.url).href |
| | | const VITE_STATIC_URL = process.env.VITE_STATIC_URL || '' |
| | | |
| | | let status = attrs.status === undefined ? true : attrs.status |
| | | let isAdd = attrs.status === 'add' |
| | | const imgUrl = () => { |
| | | let baseDir = 'images' |
| | | let name = imgName.value |
| | | if (imgName.value) { |
| | | if (imgName.value.includes('files/')) { |
| | | baseDir = 'files' |
| | | name = imgName.value.split('/')[1] |
| | | } |
| | | } |
| | | |
| | | return `${VITE_STATIC_URL}/resources/assets/${baseDir}/${name}.png` |
| | | } |
| | | const BtnRender = () => { |
| | | return ( |
| | | <el-button |
| | | {...attrs} |
| | | type={props.type} |
| | | text |
| | | class={styles.btn} |
| | | class={{ |
| | | [styles.btn]: true, |
| | | [styles.status]: attrs.disabled ? false : status, |
| | | }} |
| | | onClick={(evt: Event) => emit('click', evt)} |
| | | > |
| | | {imgName.value ? <img src={imgUrl()} class={styles.img} /> : null} |
| | | <span style={props.type === 'primary' ? { color: '#5a84ff' } : {}}> |
| | | {slots.default && slots.default()} |
| | | {slots.default?.()} |
| | | </span> |
| | | </el-button> |
| | | ) |
| | |
| | | persistent={false} |
| | | popper-style={{ |
| | | marginTop: '-7px', |
| | | padding: '8px', |
| | | padding: '10px', |
| | | }} |
| | | trigger="click" |
| | | vSlots={{ |
| | | reference: BtnRender, |
| | | }} |
| | | > |
| | | {slots.default && slots.default()} |
| | | {slots.default?.()} |
| | | </el-popover> |
| | | ) |
| | | } |
| | |
| | | </span> |
| | | ) |
| | | } |
| | | return <BtnRender /> |
| | | return BtnRender() |
| | | } |
| | | }, |
| | | }) |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | import { computed, defineComponent } from 'vue' |
| | | import parse from 'style-to-object' |
| | | export default defineComponent({ |
| | | name: 'å¾ç', |
| | | props: { |
| | | src: { |
| | | type: String, |
| | | default: '', |
| | | }, |
| | | draggable: { |
| | | type: Boolean, |
| | | default: false, |
| | | }, |
| | | cursor: { |
| | | type: String, |
| | | default: '', |
| | | }, |
| | | class: { |
| | | type: String, |
| | | default: '', |
| | | }, |
| | | style: { |
| | | type: [Object, String], |
| | | default: () => ({}), |
| | | }, |
| | | alt: { |
| | | type: String, |
| | | }, |
| | | }, |
| | | emits: ['click'], |
| | | setup(props, { attrs, slots, emit }) { |
| | | const VITE_STATIC_URL = process.env.VITE_STATIC_URL || '' |
| | | const imgUrl = computed(() => { |
| | | if (props.src.includes('/')) { |
| | | return props.src |
| | | } |
| | | const imgName = props.src |
| | | if (!imgName) return '' |
| | | return `${VITE_STATIC_URL}/resources/assets/files/${imgName}.png` |
| | | }) |
| | | const style = computed(() => { |
| | | if (typeof props.style === 'string') { |
| | | return parse(props.style) |
| | | } |
| | | return props.style |
| | | }) |
| | | return () => { |
| | | if (imgUrl.value.includes('undefined')) return null |
| | | return ( |
| | | <img |
| | | onClick={(evt: Event) => emit('click', evt)} |
| | | src={imgUrl.value} |
| | | style={{ cursor: props.cursor, ...style.value }} |
| | | class={props.class} |
| | | alt={props.alt} |
| | | {...attrs} |
| | | /> |
| | | ) |
| | | } |
| | | }, |
| | | }) |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | .content { |
| | | padding: 20px; |
| | | display: flex; |
| | | justify-content: space-between; |
| | | align-items: center; |
| | | } |
| | | |
| | | .timeItem { |
| | | margin-bottom: 16px; |
| | | display: flex; |
| | | align-items: center; |
| | | |
| | | &:last-child { |
| | | margin-bottom: 0; |
| | | } |
| | | } |
| | | |
| | | .label { |
| | | color: #666; |
| | | margin-right: 8px; |
| | | } |
| | | |
| | | .time { |
| | | font-size: 16px; |
| | | color: #333; |
| | | } |
| | | |
| | | .processContent { |
| | | display: flex; |
| | | justify-content: space-between; |
| | | align-items: center; |
| | | width: 100%; |
| | | height: 10px; |
| | | margin: 10px 0; |
| | | margin-top: 20px; |
| | | } |
| | | |
| | | .processItem { |
| | | display: flex; |
| | | justify-content: flex-start; |
| | | align-items: center; |
| | | height: 20px; |
| | | border-radius: 15px; |
| | | background-color: #f0f0f0; |
| | | margin: 10px 0; |
| | | width: calc(100% - 70px); |
| | | } |
| | | |
| | | .process { |
| | | height: 20px; |
| | | width: 0%; |
| | | border-radius: 5px; |
| | | background-color: #5a97ff; |
| | | transition: width 0.3s ease-in-out; |
| | | position: relative; |
| | | border-radius: 15px; |
| | | overflow: hidden; |
| | | |
| | | &::after { |
| | | content: ''; |
| | | position: absolute; |
| | | top: 0; |
| | | left: 0; |
| | | width: 100%; |
| | | height: 100%; |
| | | background: linear-gradient( |
| | | 90deg, |
| | | rgba(255, 255, 255, 0) 0%, |
| | | rgba(255, 255, 255, 0.3) 50%, |
| | | rgba(255, 255, 255, 0) 100% |
| | | ); |
| | | animation: shimmer 1.5s infinite; |
| | | } |
| | | } |
| | | |
| | | @keyframes shimmer { |
| | | 0% { |
| | | transform: translateX(-100%); |
| | | } |
| | | 100% { |
| | | transform: translateX(100%); |
| | | } |
| | | } |
| | | |
| | | .processTitle { |
| | | font-size: 14px; |
| | | color: #333; |
| | | } |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | import { computed, defineComponent, Fragment, ref } from 'vue' |
| | | import styles from './ImportProcessDialog.module.scss' |
| | | import BaseDialog from '@/components/BaseDialog/BaseDialog' |
| | | import { ElMessage } from 'element-plus' |
| | | import { _t, Language } from '@/libs/Language/Language' |
| | | import IconButton from '../IconButton/IconButton' |
| | | import { Socket } from '@/libs/Socket/index' |
| | | import dayjs from 'dayjs' |
| | | import { ConfirmBox } from '@/components/ConfirmBox/ConfirmBox' |
| | | const ReceiveProgress = 'ReceiveProgress' |
| | | const Cancel = 'Cancel' |
| | | export default defineComponent({ |
| | | name: 'ImportProcessDialog', |
| | | props: { |
| | | visible: { |
| | | type: Boolean, |
| | | default: false, |
| | | }, |
| | | elapsedTime: { |
| | | type: String, |
| | | default: '00:00:00', |
| | | }, |
| | | remainingTime: { |
| | | type: String, |
| | | default: '00:00:00', |
| | | }, |
| | | IsInspectionPointTask: { |
| | | type: Boolean, |
| | | default: false, |
| | | }, |
| | | }, |
| | | setup(props, { emit }) { |
| | | const timeText = computed(() => _t('计ç®ä¸...')) |
| | | const visible = ref(false) |
| | | const connectionId = ref('') |
| | | const dtoJson = ref('') |
| | | const progress = ref(0) |
| | | const remainingTime = ref('00:00:00') |
| | | const elapsedTime = ref(timeText.value) |
| | | const clearTime = ref(null) |
| | | const startTime = ref<dayjs.Dayjs>() |
| | | const isCancel = ref(false) |
| | | let socket: Socket | null = null |
| | | const handleClose = () => { |
| | | visible.value = false |
| | | clearTime.value && clearTime.value() |
| | | } |
| | | /** |
| | | * 头é¨é
ç½® |
| | | */ |
| | | const headers = computed(() => { |
| | | return { |
| | | Authorization: `Bearer ${sessionStorage.getItem('Token')}`, |
| | | 'X-Project': sessionStorage.getItem('X-Project'), |
| | | 'Accept-Language': Language.getLangReqHeader(), |
| | | } |
| | | }) |
| | | /** |
| | | * ä¸ä¼ æå |
| | | */ |
| | | const onSuccess = () => { |
| | | if (!isCancel.value) { |
| | | ElMessage.success(_t('导å
¥æå')) |
| | | handleClose() |
| | | } |
| | | } |
| | | /** |
| | | * 失败 |
| | | * @param err |
| | | */ |
| | | const onError = (err: any) => { |
| | | try { |
| | | const message = JSON.parse(err.message) |
| | | ElMessage.error(message.msg) |
| | | } catch (error) { |
| | | ElMessage.error(_t('导å
¥å¤±è´¥')) |
| | | } |
| | | handleClose() |
| | | } |
| | | |
| | | const initSocket = () => { |
| | | return new Promise((resolve, reject) => { |
| | | socket = new Socket({ |
| | | url: '/hubs/v1/traceImportProgress', |
| | | name: '追溯导å
¥è¿åº¦', |
| | | }) |
| | | |
| | | socket?.connection?.start().then((data: any) => { |
| | | if (socket) { |
| | | connectionId.value = socket!.connection!.connectionId |
| | | dtoJson.value = JSON.stringify({ |
| | | key: connectionId.value, |
| | | IsInspectionPointTask: props.IsInspectionPointTask, |
| | | }) |
| | | socket.on(ReceiveProgress, onReceiveProgress) |
| | | resolve(true) |
| | | } else { |
| | | reject(false) |
| | | } |
| | | }) |
| | | }) |
| | | } |
| | | |
| | | const onReceiveProgress = (data: any) => { |
| | | progress.value = data |
| | | if (progress.value === 0) { |
| | | remainingTime.value = timeText.value |
| | | } else if (progress.value > 0 && progress.value < 100) { |
| | | const elapsed = dayjs().diff(startTime.value, 'second') |
| | | const totalEstimatedSeconds = Math.ceil( |
| | | (elapsed * 100) / progress.value |
| | | ) |
| | | const remainingSeconds = Math.max(totalEstimatedSeconds - elapsed, 0) |
| | | |
| | | remainingTime.value = dayjs() |
| | | .startOf('day') |
| | | .add(remainingSeconds, 'second') |
| | | .format('HH:mm:ss') |
| | | } else if (progress.value >= 100) { |
| | | remainingTime.value = '00:00:00' |
| | | clearTime.value && clearTime.value() |
| | | } |
| | | } |
| | | /** |
| | | * ä¸ä¼ é©å |
| | | */ |
| | | const onBeforeUpload = async (file: File) => { |
| | | const result = await initSocket() |
| | | if (!result) { |
| | | return false |
| | | } |
| | | const format = ['xlsx', 'xls', 'csv'] |
| | | if (!format.includes(file.name.split('.')[1])) { |
| | | ElMessage.error( |
| | | _t('导å
¥æä»¶æ ¼å¼ä¸æ£ç¡®ï¼è¯·å¯¼å
¥.xlsx/.xlsä¸.csvæ ¼å¼çæä»¶') |
| | | ) |
| | | return false |
| | | } |
| | | |
| | | visible.value = true |
| | | clearTime.value = updateTime() |
| | | return true |
| | | } |
| | | |
| | | const updateTime = () => { |
| | | startTime.value = dayjs() |
| | | const t = setInterval(() => { |
| | | elapsedTime.value = dayjs() |
| | | .startOf('day') |
| | | .add(dayjs().diff(startTime.value, 'second'), 'second') |
| | | .format('HH:mm:ss') |
| | | }, 1000) |
| | | return () => clearInterval(t) |
| | | } |
| | | |
| | | const onOpen = () => { |
| | | elapsedTime.value = '00:00:00' |
| | | remainingTime.value = timeText.value |
| | | progress.value = 0 |
| | | } |
| | | |
| | | const onCancelImport = async () => { |
| | | try { |
| | | await ConfirmBox(_t('æ¯å¦åæ¶å¯¼å
¥')) |
| | | isCancel.value = true |
| | | socket?.call(Cancel, connectionId.value).then((res: any) => { |
| | | visible.value = false |
| | | clearTime.value && clearTime.value() |
| | | elapsedTime.value = '00:00:00' |
| | | remainingTime.value = timeText.value |
| | | ElMessage.success(_t('忶坼å
¥æå')) |
| | | }) |
| | | } catch (error) { |
| | | isCancel.value = false |
| | | } |
| | | } |
| | | |
| | | return () => ( |
| | | <Fragment> |
| | | <el-upload |
| | | name="file" |
| | | accept=".xlsx,.xls,.csv" |
| | | show-file-list={false} |
| | | data={{ dtoJson: dtoJson.value }} |
| | | onError={onError} |
| | | onSuccess={onSuccess} |
| | | before-upload={onBeforeUpload} |
| | | headers={headers.value} |
| | | action="/api/v1/tracemanagement/trace/import" |
| | | > |
| | | <IconButton icon="in"></IconButton> |
| | | </el-upload> |
| | | <BaseDialog |
| | | v-model={visible.value} |
| | | title={_t('导å
¥è¿åº¦')} |
| | | onOpen={onOpen} |
| | | onClose={handleClose} |
| | | hideClose={true} |
| | | showFooter={false} |
| | | v-slots={{ |
| | | footer: () => ( |
| | | <el-button onClick={onCancelImport}>{_t('忶坼å
¥')}</el-button> |
| | | ), |
| | | }} |
| | | > |
| | | <div class={styles.processContent}> |
| | | <div class={styles.processTitle}>{_t('导å
¥è¿åº¦')}</div> |
| | | <div class={styles.processItem}> |
| | | <div |
| | | class={styles.process} |
| | | style={{ width: `${progress.value}%` }} |
| | | ></div> |
| | | </div> |
| | | </div> |
| | | <div class={styles.content}> |
| | | <div class={styles.timeItem}> |
| | | <span class={styles.label}>{_t('å·²ç¨æ¶é´')}</span> |
| | | <span class={styles.time}>{elapsedTime.value}</span> |
| | | </div> |
| | | <div class={styles.timeItem}> |
| | | <span class={styles.label}>{_t('å©ä½æ¶é´')}</span> |
| | | <span class={styles.time}>{remainingTime.value}</span> |
| | | </div> |
| | | </div> |
| | | </BaseDialog> |
| | | </Fragment> |
| | | ) |
| | | }, |
| | | }) |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | import { defineComponent } from 'vue' |
| | | |
| | | export default defineComponent({ |
| | | name: 'DyFormInput', |
| | | setup(props, { attrs, slots }) { |
| | | return () => <el-input {...props} {...attrs} /> |
| | | }, |
| | | }) |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | .container { |
| | | height: 560px; |
| | | } |
| | | .mainTable { |
| | | height: calc(100% - 90px); |
| | | } |
| | | .tools { |
| | | margin-top: 15px; |
| | | display: flex; |
| | | width: 270px; |
| | | align-items: center; |
| | | .name { |
| | | margin-right: 10px; |
| | | } |
| | | } |
| | | .box { |
| | | width: 100%; |
| | | display: flex; |
| | | justify-content: space-between; |
| | | align-items: center; |
| | | } |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | import { defineComponent } from 'vue' |
| | | import BaseDialog from '@/components/BaseDialog/index.vue' |
| | | import { useSelectDialog } from './hook' |
| | | import styles from './LabelDialog.module.scss' |
| | | import Search from '@/components/Search/Search' |
| | | import BaseTable from '@/components/Table/Table' |
| | | import { _t } from '@/libs/Language/Language' |
| | | import Text from '../Text/Text' |
| | | export default defineComponent({ |
| | | name: 'LabelDialog', |
| | | props: { |
| | | modelValue: { |
| | | type: Boolean, |
| | | default: false, |
| | | }, |
| | | title: { |
| | | type: String, |
| | | default: '', |
| | | }, |
| | | data: { |
| | | type: Array, |
| | | default: () => [], |
| | | }, |
| | | printerName: { |
| | | type: String, |
| | | }, |
| | | radio: { |
| | | type: Boolean, |
| | | default: false, |
| | | }, |
| | | }, |
| | | emits: ['update:modelValue', 'close', 'confirm'], |
| | | setup(props, ctx) { |
| | | const { |
| | | onClose, |
| | | onConfirm, |
| | | onCheck, |
| | | onOpen, |
| | | onSearch, |
| | | printName, |
| | | printVisible, |
| | | url, |
| | | visible, |
| | | innerValue, |
| | | tableRef, |
| | | dataSource, |
| | | columns, |
| | | selections, |
| | | onPreview, |
| | | } = useSelectDialog(props, ctx) |
| | | return () => ( |
| | | <BaseDialog |
| | | destroy-on-close |
| | | class={styles.drawer} |
| | | style="background: #fff" |
| | | width="664px" |
| | | height="578px" |
| | | title={_t('æ ç¾ç®¡ç')} |
| | | v-model={visible.value} |
| | | onClose={onClose} |
| | | onConfirm={onConfirm} |
| | | onOpen={onOpen} |
| | | > |
| | | <div class={styles.container}> |
| | | <BaseDialog |
| | | title={printName.value} |
| | | v-model={printVisible.value} |
| | | width="664px" |
| | | height="500px" |
| | | onClose={() => (printVisible.value = false)} |
| | | onConfirm={() => (printVisible.value = false)} |
| | | > |
| | | <el-image |
| | | style="width: 100%;" |
| | | src={url.value} |
| | | zoom-rate={1.2} |
| | | max-scale={7} |
| | | min-scale={0.2} |
| | | preview-src-list={[url.value]} |
| | | fit="cover" |
| | | /> |
| | | </BaseDialog> |
| | | <div class={styles.tools}> |
| | | <span class={styles.name}>{_t('æ¥è¯¢')}</span> |
| | | <Search v-model={innerValue.value} onConfirm={onSearch} /> |
| | | </div> |
| | | <div class={styles.mainTable}> |
| | | <BaseTable |
| | | params={{ |
| | | // Filter: innerValue.value, |
| | | printerName: props.printerName, |
| | | }} |
| | | selections={selections.value} |
| | | pageSize={50} |
| | | ref={tableRef} |
| | | url="/api/v1/labelmanagement/label/template" |
| | | style="margin-top:10px" |
| | | v-model:dataSource={dataSource.value} |
| | | columns={columns.value} |
| | | isChecked={true} |
| | | isHidePagination={true} |
| | | id="templateName" |
| | | onCheck={onCheck} |
| | | radio={props.radio} |
| | | v-slots={{ |
| | | templateName: ({ row }) => { |
| | | return ( |
| | | <div class={styles.box}> |
| | | <Text tip={row.templateName} truncated={true}> |
| | | {row.templateName} |
| | | </Text> |
| | | <el-button |
| | | type="primary" |
| | | link |
| | | onClick={() => onPreview(row)} |
| | | > |
| | | {_t('é¢è§')} |
| | | </el-button> |
| | | </div> |
| | | ) |
| | | }, |
| | | }} |
| | | /> |
| | | </div> |
| | | </div> |
| | | </BaseDialog> |
| | | ) |
| | | }, |
| | | }) |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | import { ref, onMounted, reactive, computed, watch, nextTick } from 'vue' |
| | | import { _t } from '@/libs/Language/Language' |
| | | |
| | | export const useSelectDialog = (props: any, ctx: any) => { |
| | | const visible = computed({ |
| | | get() { |
| | | return props.modelValue |
| | | }, |
| | | set(val) { |
| | | ctx.emit('update:modelValue', val) |
| | | }, |
| | | }) |
| | | |
| | | const url = ref('') |
| | | |
| | | const dataSource = ref<any[]>([]) |
| | | |
| | | const innerValue = ref('') |
| | | |
| | | const tableRef = ref() |
| | | |
| | | const checkedList = ref<any[]>([]) |
| | | |
| | | const imageRef = ref() |
| | | |
| | | const printName = ref('') |
| | | |
| | | const printVisible = ref(false) |
| | | |
| | | const columns = computed(() => [ |
| | | { |
| | | title: _t('åºå·'), |
| | | type: 'seq', |
| | | width: '60', |
| | | }, |
| | | { |
| | | field: 'templateName', |
| | | title: _t('模æ¿åç§°'), |
| | | }, |
| | | { |
| | | field: 'remark', |
| | | title: _t('夿³¨'), |
| | | }, |
| | | ]) |
| | | |
| | | const onClose = () => { |
| | | visible.value = false |
| | | } |
| | | |
| | | const onConfirm = async () => { |
| | | ctx.emit('confirm', checkedList.value) |
| | | } |
| | | |
| | | const onSearch = async () => { |
| | | const data: any[] = await tableRef.value?.getList() |
| | | dataSource.value = data.filter((item: any) => |
| | | item.templateName.includes(innerValue.value) |
| | | ) |
| | | } |
| | | |
| | | const onCheck = (list: any) => { |
| | | checkedList.value = list |
| | | } |
| | | |
| | | const selections = computed(() => { |
| | | return props.data?.map((item: any) => item.templateName) ?? [] |
| | | }) |
| | | |
| | | const onOpen = () => { |
| | | // console.log(dataSource.value, selections, props.data) |
| | | } |
| | | |
| | | const onPreview = (row: any) => { |
| | | url.value = `/api/v1/labelmanagement/label/preview?printerName=${row.printerName}&templateName=${row.templateName}` |
| | | printName.value = row.printerName |
| | | printVisible.value = true |
| | | } |
| | | |
| | | return { |
| | | selections, |
| | | columns, |
| | | dataSource, |
| | | tableRef, |
| | | innerValue, |
| | | visible, |
| | | url, |
| | | imageRef, |
| | | printName, |
| | | printVisible, |
| | | onPreview, |
| | | onSearch, |
| | | onCheck, |
| | | onOpen, |
| | | onClose, |
| | | onConfirm, |
| | | } |
| | | } |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | .logicFlow { |
| | | width: 100%; |
| | | height: 100%; |
| | | position: relative; |
| | | .beautify { |
| | | position: absolute; |
| | | right: 30px; |
| | | top: 30px; |
| | | z-index: 1; |
| | | } |
| | | .xmlbeautify { |
| | | position: absolute; |
| | | right: 150px; |
| | | top: 30px; |
| | | z-index: 1; |
| | | } |
| | | } |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | import { defineComponent, SetupContext, onMounted, reactive, ref } from 'vue' |
| | | import styles from './LogicFlow.module.scss' |
| | | import { |
| | | getFlowDataToXml, |
| | | getJsonByXml, |
| | | getLogicFLowStruct, |
| | | } from './core/transformHelp' |
| | | import { getFlowXml } from '@/api/logic-flow' |
| | | import LogicRenderer from './components/Renderer/Renderer' |
| | | import Canvas from './components/Canvas/Canvas' |
| | | import Theme from './components/Theme/Theme' |
| | | import NodeDrawer from './components/NodeDrawer/NodeDrawer' |
| | | import EdgeDrawer from './components/EdgeDrawer/EdgeDrawer' |
| | | import { injectStore } from './core/store' |
| | | import Empty from '../Empty/Empty' |
| | | import { FlowType } from './type' |
| | | interface NodeDrawerConfig { |
| | | visible: boolean |
| | | title: string |
| | | node: Record<string, any> |
| | | } |
| | | export default defineComponent({ |
| | | name: 'LogicFlow', |
| | | props: { |
| | | flowType: { |
| | | type: [String, Number], |
| | | default: '', |
| | | }, |
| | | }, |
| | | setup(props, { slots, attrs }: SetupContext) { |
| | | const { lf } = injectStore() |
| | | const graphData = ref<FlowType | null>(null) |
| | | const logicRenderRef = ref<any>() |
| | | |
| | | const nodeDrawerConfig = reactive<NodeDrawerConfig>({ |
| | | visible: false, |
| | | title: 'èç¹é
ç½®', |
| | | node: {}, |
| | | }) |
| | | const edgeDrawerConfig = reactive<NodeDrawerConfig>({ |
| | | visible: false, |
| | | title: 'æ¡ä»¶é
ç½®', |
| | | node: {}, |
| | | }) |
| | | const initData = async () => { |
| | | const res = await getFlowXml(props.flowType) |
| | | const json = getJsonByXml(res) |
| | | graphData.value = getLogicFLowStruct(json) |
| | | } |
| | | |
| | | const onAutoLayout = () => { |
| | | logicRenderRef.value?.autoLayout() |
| | | } |
| | | /** |
| | | * èç¹åå» |
| | | * @param data |
| | | */ |
| | | const onNodeDbClick = ({ data }: Record<string, any>) => { |
| | | nodeDrawerConfig.visible = true |
| | | nodeDrawerConfig.node = data |
| | | nodeDrawerConfig.title = data.properties?.name || data.id || 'èç¹é
ç½®' |
| | | } |
| | | |
| | | const onEdgeDbClick = ({ data }: Record<string, any>) => { |
| | | edgeDrawerConfig.visible = true |
| | | edgeDrawerConfig.node = data |
| | | edgeDrawerConfig.title = data.properties?.name || data.id || 'æ¡ä»¶é
ç½®' |
| | | } |
| | | |
| | | const onView = (properties: Record<string, any>) => { |
| | | onNodeDbClick({ |
| | | data: { |
| | | id: properties.id, |
| | | properties, |
| | | }, |
| | | }) |
| | | } |
| | | |
| | | const onTransformXml = () => { |
| | | if (graphData.value !== null) { |
| | | getFlowDataToXml(graphData.value) |
| | | } |
| | | } |
| | | |
| | | onMounted(initData) |
| | | |
| | | return () => { |
| | | if (!graphData.value) return <el-empty description="ææ æ°æ®" /> |
| | | |
| | | return ( |
| | | <div class={styles.logicFlow}> |
| | | <NodeDrawer |
| | | lf={lf} |
| | | title={nodeDrawerConfig.title} |
| | | v-model={nodeDrawerConfig.visible} |
| | | node={nodeDrawerConfig.node} |
| | | ></NodeDrawer> |
| | | <EdgeDrawer |
| | | title={edgeDrawerConfig.title} |
| | | v-model={edgeDrawerConfig.visible} |
| | | node={edgeDrawerConfig.node} |
| | | ></EdgeDrawer> |
| | | <el-button |
| | | onClick={onTransformXml} |
| | | class={styles.xmlbeautify} |
| | | size="small" |
| | | type="primary" |
| | | > |
| | | xml |
| | | </el-button> |
| | | <el-button |
| | | onClick={onAutoLayout} |
| | | class={styles.beautify} |
| | | size="small" |
| | | type="primary" |
| | | > |
| | | ä¸é®ç¾å |
| | | </el-button> |
| | | <Canvas grid={{ visible: true }} minimap={true}> |
| | | <Theme |
| | | snapline={{ |
| | | stroke: '#ff0000', // 对é½çº¿é¢è² |
| | | strokeWidth: 0.5, // 对é½çº¿å®½åº¦ |
| | | }} |
| | | /> |
| | | <LogicRenderer |
| | | ref={logicRenderRef} |
| | | graphData={graphData.value} |
| | | onNodeDbClick={onNodeDbClick} |
| | | onEdgeDbClick={onEdgeDbClick} |
| | | onView={onView} |
| | | // adjustEdge={true} |
| | | isEdgeAnimation={true} |
| | | // isSilentMode={true} |
| | | // adjustNodePosition={true} |
| | | // hideAnchors={true} |
| | | // edgeTextEdit={false} |
| | | // nodeTextEdit={false} |
| | | ></LogicRenderer> |
| | | </Canvas> |
| | | </div> |
| | | ) |
| | | } |
| | | }, |
| | | }) |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | import { |
| | | defineComponent, |
| | | Fragment, |
| | | computed, |
| | | Component, |
| | | DefineComponent, |
| | | SetupContext, |
| | | } from 'vue' |
| | | |
| | | export default defineComponent<{ |
| | | grid: Record<string, any> |
| | | minimap: Record<string, any> | boolean |
| | | }>({ |
| | | name: 'LogicFlowCanvas', |
| | | setup(props: any, { slots, attrs }: SetupContext) { |
| | | const logicFlowConfig = { |
| | | grid: { |
| | | size: 20, |
| | | visible: true, |
| | | type: 'dot', |
| | | config: { |
| | | color: '#ababab', |
| | | thickness: 1, |
| | | }, |
| | | }, |
| | | } |
| | | |
| | | const baseConfig = computed(() => { |
| | | return { |
| | | ...logicFlowConfig, |
| | | ...props, |
| | | ...attrs, |
| | | } |
| | | }) |
| | | return () => { |
| | | const Widgets = (slots.default && slots.default()) || [] |
| | | return ( |
| | | <span> |
| | | {Widgets.map((Widget: any) => { |
| | | return <Widget {...baseConfig.value} /> |
| | | })} |
| | | </span> |
| | | ) |
| | | } |
| | | }, |
| | | }) |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | import { computed, defineComponent, ref, onMounted, watch } from 'vue' |
| | | import BaseDrawer from '@/components/BaseDrawer/BaseDrawer' |
| | | import DyForm from '@/components/DyForm/DyForm' |
| | | import { injectStore } from '../../core/store' |
| | | import { StoreKey } from '../../type/index.d' |
| | | import { BaseEdgeModel } from '@logicflow/core' |
| | | export default defineComponent({ |
| | | name: 'NodeDrawer', |
| | | props: { |
| | | modelValue: { |
| | | type: Boolean, |
| | | default: false, |
| | | }, |
| | | title: { |
| | | type: String, |
| | | default: '', |
| | | }, |
| | | node: { |
| | | type: Object, |
| | | default: () => ({}), |
| | | }, |
| | | }, |
| | | emits: ['update:modelValue', 'close', 'confirm'], |
| | | setup(props, { slots, emit }) { |
| | | const lf = injectStore(StoreKey.LF) |
| | | const visible = computed({ |
| | | get: () => props.modelValue, |
| | | set: (value) => { |
| | | emit('update:modelValue', value) |
| | | }, |
| | | }) |
| | | const node = computed(() => props.node) |
| | | |
| | | const formData = ref<any>({}) |
| | | |
| | | const formItemProps = [ |
| | | { |
| | | label: 'åç§°', |
| | | prop: 'Name', |
| | | el: 'input', |
| | | placeholder: '请è¾å
¥åç§°', |
| | | rules: [{ required: true, message: '请è¾å
¥åç§°', trigger: 'blur' }], |
| | | }, |
| | | { |
| | | label: 'ç®æ ç¯è', |
| | | prop: 'Sink', |
| | | el: 'input', |
| | | placeholder: '请è¾å
¥ç®æ ç¯è', |
| | | disabled: true, |
| | | }, |
| | | { |
| | | label: 'æºç¯è', |
| | | prop: 'Source', |
| | | el: 'input', |
| | | placeholder: '请è¾å
¥æºç¯è', |
| | | disabled: true, |
| | | }, |
| | | { |
| | | label: 'æ¯è¾ç¬¦', |
| | | prop: 'Operator', |
| | | el: 'select', |
| | | placeholder: '请è¾å
¥æ¯è¾ç¬¦', |
| | | options: [ |
| | | { |
| | | label: 'ç¸ç', |
| | | value: 'RelOpEqual', |
| | | }, |
| | | { |
| | | label: 'æè
', |
| | | value: 'Or', |
| | | }, |
| | | { |
| | | label: 'å¹¶ä¸', |
| | | value: 'And', |
| | | }, |
| | | ], |
| | | }, |
| | | { |
| | | label: 'æ ç¾', |
| | | prop: 'Label', |
| | | el: 'input', |
| | | placeholder: '请è¾å
¥æ ç¾', |
| | | }, |
| | | { |
| | | label: '常éå¼', |
| | | prop: 'Value', |
| | | el: 'input', |
| | | placeholder: '请è¾å
¥å¸¸éå¼', |
| | | }, |
| | | { |
| | | label: 'æ±å', |
| | | prop: 'NOT', |
| | | el: 'select', |
| | | placeholder: '请è¾å
¥æ±å', |
| | | options: [ |
| | | { |
| | | label: 'å¦', |
| | | value: 'false', |
| | | }, |
| | | { |
| | | label: 'æ¯', |
| | | value: 'true', |
| | | }, |
| | | ], |
| | | }, |
| | | { |
| | | label: '屿§å', |
| | | prop: 'Property', |
| | | el: 'input', |
| | | placeholder: '请è¾å
¥å±æ§å', |
| | | }, |
| | | { |
| | | label: 'åæ°å', |
| | | prop: 'Parameter', |
| | | el: 'input', |
| | | placeholder: '请è¾å
¥åæ°å', |
| | | }, |
| | | ] |
| | | const onClose = () => { |
| | | visible.value = false |
| | | } |
| | | |
| | | const onConfirm = () => { |
| | | const edgeModel: BaseEdgeModel = lf.value.getEdgeModelById(node.value.id) |
| | | edgeModel.setProperties({ |
| | | Label: formData.value.Name, |
| | | Sink: formData.value.Sink, |
| | | Source: formData.value.Source, |
| | | Condition: { |
| | | Expression: formData.value.Label, |
| | | Operator: formData.value.Operator, |
| | | Property: formData.value.Property, |
| | | Value: formData.value.Value, |
| | | NOT: formData.value.NOT, |
| | | Parameter: formData.value.Parameter, |
| | | }, |
| | | }) |
| | | edgeModel.updateText(formData.value.Name) |
| | | visible.value = false |
| | | } |
| | | |
| | | const initData = () => { |
| | | const { properties } = node.value |
| | | const Value = |
| | | typeof properties.Condition?.Value === 'string' |
| | | ? String(properties.Condition?.Value) |
| | | : '' |
| | | formData.value = { |
| | | Name: properties?.Label, |
| | | Sink: properties.Sink, |
| | | Source: properties.Source, |
| | | Label: properties.Condition?.Expression, //æ ç¾ |
| | | Operator: properties.Condition?.Operator, //æ¯è¾ç¬¦å· |
| | | Property: properties.Condition?.Property, //屿§å |
| | | Value, //常éå¼ |
| | | NOT: String(properties.Condition?.NOT), //æ±å |
| | | Parameter: properties.Condition?.Parameter, //åæ°å |
| | | } |
| | | } |
| | | |
| | | watch(node, (v, oldV) => { |
| | | if (v !== oldV) { |
| | | initData() |
| | | } |
| | | }) |
| | | |
| | | return () => { |
| | | return ( |
| | | <BaseDrawer |
| | | onClose={onClose} |
| | | onConfirm={onConfirm} |
| | | title={props.title} |
| | | width="600px" |
| | | v-model={visible.value} |
| | | destroy-on-close |
| | | > |
| | | <DyForm |
| | | formItemProps={formItemProps} |
| | | v-model:formData={formData.value} |
| | | ></DyForm> |
| | | </BaseDrawer> |
| | | ) |
| | | } |
| | | }, |
| | | }) |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | // è´å¡å°æ²çº¿ |
| | | import { BezierEdge, BezierEdgeModel } from '@logicflow/core' |
| | | import { CURVE } from '../../core/enum' // æçº¿ |
| | | import { PolylineEdge, PolylineEdgeModel } from '@logicflow/core' |
| | | import { CurvedEdge, CurvedEdgeModel } from '@logicflow/extension' |
| | | |
| | | class CurveModel extends BezierEdgeModel { |
| | | initEdgeData(data: any) { |
| | | super.initEdgeData(data) |
| | | this.radius = 500 |
| | | } |
| | | setAttributes() { |
| | | this.isAnimation = true |
| | | this.text.editable = false |
| | | this.offset = 20 |
| | | const t = setTimeout(() => { |
| | | this.isAnimation = false |
| | | clearTimeout(t) |
| | | }, 3000) |
| | | } |
| | | getEdgeAnimationStyle() { |
| | | const style = super.getEdgeAnimationStyle() |
| | | style.strokeDasharray = '15 2' |
| | | style.animationDuration = '30s' |
| | | style.stroke = '#5a84ff' |
| | | // #9265f3 |
| | | return style |
| | | } |
| | | getEdgeStyle() { |
| | | const style = super.getEdgeStyle() |
| | | const { properties } = this |
| | | if (properties.isActived) { |
| | | style.strokeDasharray = '2 2' |
| | | } |
| | | if (this.isSelected || this.isHovered) { |
| | | style.stroke = '#5a84ff' |
| | | } else { |
| | | style.stroke = '#c4c8d5' |
| | | } |
| | | return style |
| | | } |
| | | getTextStyle() { |
| | | const style: Record<string, any> = super.getTextStyle() |
| | | style.color = '#444' |
| | | style.fontSize = 13 |
| | | if (this.isSelected || this.isHovered) { |
| | | style.color = '#5a84ff' |
| | | } else { |
| | | style.color = '#444' |
| | | } |
| | | return style |
| | | } |
| | | |
| | | getOutlineStyle() { |
| | | const style: Record<string, any> = super.getOutlineStyle() |
| | | style.stroke = '#5a84ff' |
| | | style.hover.stroke = '#5a84ff' |
| | | return style |
| | | } |
| | | getAdjustStart() {} |
| | | } |
| | | |
| | | export default { |
| | | type: CURVE, |
| | | view: BezierEdge, |
| | | model: CurveModel, |
| | | } |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | import { computed, defineComponent, ref, onMounted, watch } from 'vue' |
| | | import BaseDrawer from '@/components/BaseDrawer/BaseDrawer' |
| | | import DyForm from '@/components/DyForm/DyForm' |
| | | import { injectStore } from '../../core/store' |
| | | import { StoreKey } from '../../type/index.d' |
| | | |
| | | export default defineComponent({ |
| | | name: 'NodeDrawer', |
| | | props: { |
| | | modelValue: { |
| | | type: Boolean, |
| | | default: false, |
| | | }, |
| | | title: { |
| | | type: String, |
| | | default: '', |
| | | }, |
| | | node: { |
| | | type: Object, |
| | | default: () => ({}), |
| | | }, |
| | | lf: { |
| | | type: Object, |
| | | default: () => ({}), |
| | | }, |
| | | }, |
| | | emits: ['update:modelValue', 'close', 'confirm'], |
| | | setup(props, { slots, emit }) { |
| | | const lf = injectStore(StoreKey.LF) |
| | | const visible = computed({ |
| | | get: () => props.modelValue, |
| | | set: (value) => { |
| | | emit('update:modelValue', value) |
| | | }, |
| | | }) |
| | | const node = computed(() => props.node) |
| | | |
| | | const formData = ref({}) |
| | | |
| | | const formItemProps = [ |
| | | { |
| | | label: 'åç§°', |
| | | prop: 'Name', |
| | | el: 'input', |
| | | placeholder: '请è¾å
¥åç§°', |
| | | rules: [{ required: true, message: 'èç¹åç§°', trigger: 'blur' }], |
| | | }, |
| | | { |
| | | label: 'è¿åºæ¨¡å¼', |
| | | prop: 'SplitType', |
| | | el: 'input', |
| | | placeholder: '请è¾å
¥è¿åºæ¨¡å¼', |
| | | rules: [{ required: true, message: 'è¿åºæ¨¡å¼', trigger: 'blur' }], |
| | | }, |
| | | |
| | | { |
| | | label: 'è¿å
¥æ¨¡å¼', |
| | | prop: 'JoinType', |
| | | el: 'input', |
| | | placeholder: '请è¾å
¥è¿å
¥æ¨¡å¼', |
| | | rules: [{ required: true, message: 'è¿å
¥æ¨¡å¼', trigger: 'blur' }], |
| | | }, |
| | | { |
| | | label: 'éåºæ¨¡å¼', |
| | | prop: 'ExitMode', |
| | | el: 'input', |
| | | placeholder: '请è¾å
¥éåºæ¨¡å¼', |
| | | rules: [{ required: true, message: 'éåºæ¨¡å¼', trigger: 'blur' }], |
| | | }, |
| | | { |
| | | label: 'è¿å
¥æ¨¡å¼', |
| | | prop: 'EnterMode', |
| | | el: 'input', |
| | | placeholder: '请è¾å
¥è¿å
¥æ¨¡å¼', |
| | | rules: [{ required: true, message: 'è¿å
¥æ¨¡å¼', trigger: 'blur' }], |
| | | }, |
| | | ] |
| | | const onClose = () => { |
| | | visible.value = false |
| | | } |
| | | |
| | | const onConfirm = () => { |
| | | lf.value.getNodeModelById(node.value.id).setProperties({ |
| | | ...formData.value, |
| | | }) |
| | | visible.value = false |
| | | } |
| | | |
| | | const initData = () => { |
| | | const { properties } = node.value |
| | | formData.value = { |
| | | Name: properties.Name, |
| | | SplitType: properties.SplitType, |
| | | JoinType: properties.JoinType, |
| | | ExitMode: properties.ExitMode, |
| | | EnterMode: properties.EnterMode, |
| | | } |
| | | } |
| | | |
| | | watch(node, (v, oldV) => { |
| | | if (v !== oldV) { |
| | | initData() |
| | | } |
| | | }) |
| | | |
| | | return () => { |
| | | return ( |
| | | <BaseDrawer |
| | | onClose={onClose} |
| | | onConfirm={onConfirm} |
| | | title={props.title} |
| | | width="600px" |
| | | v-model={visible.value} |
| | | destroy-on-close |
| | | > |
| | | <DyForm |
| | | formItemProps={formItemProps} |
| | | v-model:formData={formData.value} |
| | | ></DyForm> |
| | | </BaseDrawer> |
| | | ) |
| | | } |
| | | }, |
| | | }) |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | import { HtmlNodeModel, HtmlNode } from '@logicflow/core' |
| | | import { h, createApp, defineComponent } from 'vue' |
| | | import styles from './index.module.scss' |
| | | import Icon from '@/components/Icon/Icon' |
| | | import { injectStore, emitter } from '../../core/store' |
| | | |
| | | export default defineComponent({ |
| | | name: 'BaseNode', |
| | | props: { |
| | | node: { |
| | | type: Object, |
| | | default: () => ({}), |
| | | }, |
| | | color: { |
| | | type: String, |
| | | default: '#000', |
| | | }, |
| | | background: { |
| | | type: String, |
| | | default: '#fff', |
| | | }, |
| | | icon: { |
| | | type: String, |
| | | }, |
| | | width: { |
| | | type: [String, Number], |
| | | default: '101px', |
| | | }, |
| | | height: { |
| | | type: [String, Number], |
| | | default: '33px', |
| | | }, |
| | | borderColor: { |
| | | type: String, |
| | | default: '#ccc', |
| | | }, |
| | | type: { |
| | | type: String, |
| | | default: 'base', |
| | | }, |
| | | }, |
| | | emits: ['view'], |
| | | setup(props, { emit }) { |
| | | const { selected, onSelectNode } = injectStore() |
| | | const onClickDetail = () => { |
| | | emitter.emit('view', props.node) |
| | | } |
| | | return () => { |
| | | const style = { |
| | | background: props.background, |
| | | color: props.color, |
| | | width: props.width, |
| | | height: props.height, |
| | | borderColor: props.borderColor, |
| | | } |
| | | const node = props.node |
| | | return ( |
| | | <div |
| | | onClick={(event: Event) => onSelectNode(node, event)} |
| | | class={styles.baseNodeContent} |
| | | > |
| | | <div |
| | | class={{ |
| | | [styles.baseNode]: true, |
| | | [styles.baseNodeSelected]: node.id === selected.value, |
| | | }} |
| | | style={style} |
| | | > |
| | | {props.type === 'node' ? ( |
| | | <Icon |
| | | class={styles.detail} |
| | | icon="detail" |
| | | width={15} |
| | | height={15} |
| | | onClick={onClickDetail} |
| | | /> |
| | | ) : null} |
| | | <Icon icon={props.icon} width={25} height={25} /> |
| | | <div class={styles.nodeText}>{node?.Name}</div> |
| | | </div> |
| | | </div> |
| | | ) |
| | | } |
| | | }, |
| | | }) |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | import { HtmlNodeModel, HtmlNode } from '@logicflow/core' |
| | | import { h, createApp } from 'vue' |
| | | import BaseNode from './BaseNode' |
| | | import { NODES } from '../../core/enum' |
| | | |
| | | class StartModel extends HtmlNodeModel { |
| | | setAttributes() { |
| | | this.text.editable = false |
| | | const width = 120 |
| | | const height = 36 |
| | | this.width = width |
| | | this.height = height |
| | | this.anchorsOffset = [ |
| | | // [width / 2, 0],//å³è¾¹ |
| | | // [0, height / 2], //ä¸è¾¹ |
| | | // [-width / 2, 0], |
| | | [0, -height / 2], //ä¸è¾¹ |
| | | ] |
| | | } |
| | | } |
| | | |
| | | class StartNode extends HtmlNode { |
| | | [key: string]: any |
| | | constructor(props: any) { |
| | | super(props) |
| | | this.app = createApp(() => { |
| | | const { properties } = this.props.model |
| | | return ( |
| | | <BaseNode |
| | | width="116px" |
| | | height="30px" |
| | | borderColor="rgb(146, 101, 243)" |
| | | icon="end" |
| | | node={properties} |
| | | background="#fff" |
| | | color="#333" |
| | | /> |
| | | ) |
| | | }) |
| | | } |
| | | |
| | | setHtml(rootEl: HTMLElement) { |
| | | const dom = document.createElement('div') |
| | | rootEl.appendChild(dom) |
| | | this.app.mount(dom) |
| | | } |
| | | } |
| | | |
| | | export default { |
| | | type: NODES.END_ACTIVITY, |
| | | view: StartNode, |
| | | model: StartModel, |
| | | } |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | import { HtmlNodeModel, HtmlNode } from '@logicflow/core' |
| | | import { h, createApp, defineComponent, computed } from 'vue' |
| | | import styles from './index.module.scss' |
| | | import Icon from '@/components/Icon/Icon' |
| | | import { injectStore } from '../../core/store' |
| | | |
| | | interface NodeType { |
| | | name: string |
| | | value: string |
| | | color?: string |
| | | } |
| | | export default defineComponent({ |
| | | name: 'BaseNode', |
| | | props: { |
| | | node: { |
| | | type: Object, |
| | | default: () => ({}), |
| | | }, |
| | | color: { |
| | | type: String, |
| | | default: '#000', |
| | | }, |
| | | background: { |
| | | type: String, |
| | | default: '#fff', |
| | | }, |
| | | icon: { |
| | | type: String, |
| | | }, |
| | | width: { |
| | | type: [String, Number], |
| | | default: '206', |
| | | }, |
| | | height: { |
| | | type: [String, Number], |
| | | default: '65px', |
| | | }, |
| | | }, |
| | | setup(props) { |
| | | const { selected, onSelectNode } = injectStore() |
| | | |
| | | const nodeFlows = computed(() => { |
| | | const node = props.node?.source || {} |
| | | |
| | | const nodeBusiness: NodeType[] = [] |
| | | if (node.SplitType) { |
| | | nodeBusiness.push({ |
| | | name: 'è¿åºæ¨¡å¼', |
| | | value: node.SplitType, |
| | | color: '#000', |
| | | }) |
| | | } |
| | | if (node.JoinType) { |
| | | nodeBusiness.push({ |
| | | name: 'è¿å
¥æ¨¡å¼', |
| | | value: node.JoinType, |
| | | color: '#000', |
| | | }) |
| | | } |
| | | |
| | | if (node.ExitMode) { |
| | | nodeBusiness.push({ |
| | | name: 'éåºæ¨¡å¼', |
| | | value: node.ExitMode, |
| | | color: '#000', |
| | | }) |
| | | } |
| | | if (node.EnterMode) { |
| | | nodeBusiness.push({ |
| | | name: 'è¿å
¥æ¨¡å¼', |
| | | value: node.EnterMode, |
| | | color: '#000', |
| | | }) |
| | | } |
| | | return nodeBusiness |
| | | }) |
| | | |
| | | return () => { |
| | | const style = { |
| | | background: props.background, |
| | | color: props.color, |
| | | width: props.width, |
| | | height: props.height, |
| | | } |
| | | const node = props.node |
| | | return ( |
| | | <div onClick={() => onSelectNode(node)} class={styles.flowNodeContent}> |
| | | <div |
| | | class={{ |
| | | [styles.flowNode]: true, |
| | | [styles.flowNodeSelected]: node.id === selected.value, |
| | | }} |
| | | > |
| | | <header style={style} class={styles.flowHeader}> |
| | | <Icon icon={props.icon} width={20} height={20} /> |
| | | {node.name} |
| | | </header> |
| | | <main class={styles.flowNodeMain}> |
| | | {nodeFlows.value.map((node: NodeType) => { |
| | | return ( |
| | | <div class={styles.flowInfo} style={{ color: node.color }}> |
| | | <label class={styles.label}>{node.name}ï¼</label> |
| | | <span class={styles.info}>{node.value}</span> |
| | | </div> |
| | | ) |
| | | })} |
| | | </main> |
| | | </div> |
| | | </div> |
| | | ) |
| | | } |
| | | }, |
| | | }) |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | import { HtmlNodeModel, HtmlNode } from '@logicflow/core' |
| | | import { h, createApp } from 'vue' |
| | | import BaseNode from './BaseNode' |
| | | import styles from './index.module.scss' |
| | | import { NODES } from '../../core/enum' |
| | | |
| | | interface NodeOptionType { |
| | | icon?: string |
| | | background?: string |
| | | color?: string |
| | | width?: string |
| | | height?: string |
| | | } |
| | | |
| | | export class NodeModel extends HtmlNodeModel { |
| | | setAttributes() { |
| | | this.text.editable = false |
| | | const width = 206 |
| | | const height = 136 |
| | | |
| | | this.width = width |
| | | this.height = height |
| | | this.anchorsOffset = [ |
| | | // [width / 2, 0], //å³è¾¹ |
| | | [0, height / 2], //ä¸è¾¹ |
| | | // [-width / 2, 0], //左边 |
| | | [0, -height / 2], //ä¸è¾¹ |
| | | ] |
| | | } |
| | | } |
| | | |
| | | export class Node extends HtmlNode { |
| | | [key: string]: any |
| | | constructor(props: any, option: NodeOptionType) { |
| | | super(props) |
| | | const nodeProps: NodeOptionType = { |
| | | icon: 'lightsetting', |
| | | background: '#fff', |
| | | color: '#000000a6', |
| | | ...option, |
| | | } |
| | | this.isMounted = false |
| | | this.app = createApp(() => { |
| | | const { properties } = this.props.model |
| | | return <BaseNode node={properties} {...nodeProps} type="node" /> |
| | | }) |
| | | } |
| | | |
| | | setHtml(rootEl: HTMLElement) { |
| | | const dom = document.createElement('div') |
| | | rootEl.appendChild(dom) |
| | | if (!this.isMounted) { |
| | | this.app.mount(dom) |
| | | } |
| | | |
| | | this.isMounted = true |
| | | } |
| | | } |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | import { HtmlNodeModel, HtmlNode } from '@logicflow/core' |
| | | import { h, createApp } from 'vue' |
| | | import { NODES } from '../../core/enum' |
| | | import { Node, NodeModel } from './Node' |
| | | |
| | | const style = { |
| | | width: 165, |
| | | height: 50, |
| | | } |
| | | |
| | | class OrdinaryNodeNodeModel extends NodeModel { |
| | | setAttributes() { |
| | | this.text.editable = false |
| | | this.width = style.width |
| | | this.height = style.height |
| | | this.anchorsOffset = [ |
| | | // [style.width / 2, 0], //å³è¾¹ |
| | | [0, style.height / 2], //ä¸è¾¹ |
| | | // [-style.width / 2, 0], //左边 |
| | | [0, -style.height / 2], //ä¸è¾¹ |
| | | ] |
| | | } |
| | | } |
| | | |
| | | class OrdinaryNodeNodeNode extends Node { |
| | | [key: string]: any |
| | | constructor(props: any) { |
| | | const option = { |
| | | color: 'rgba(0, 0, 0, 0.85)', |
| | | background: '#fff', |
| | | height: `${style.height - 6}px`, |
| | | width: `${style.width - 6}px`, |
| | | icon: 'varsetting', |
| | | borderColor: '#9265f3', |
| | | } |
| | | super(props, option) |
| | | } |
| | | } |
| | | |
| | | export default { |
| | | type: NODES.ORDINARY_NODE, |
| | | view: OrdinaryNodeNodeNode, |
| | | model: OrdinaryNodeNodeModel, |
| | | } |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | import { HtmlNodeModel, HtmlNode } from '@logicflow/core' |
| | | import { h, createApp } from 'vue' |
| | | import BaseNode from './BaseNode' |
| | | import { NODES } from '../../core/enum' |
| | | |
| | | class StartModel extends HtmlNodeModel { |
| | | setAttributes() { |
| | | this.text.editable = false |
| | | const width = 120 |
| | | const height = 36 |
| | | this.width = width |
| | | this.height = height |
| | | this.anchorsOffset = [ |
| | | // [width / 2, 0],//å³è¾¹ |
| | | [0, height / 2], //ä¸è¾¹ |
| | | // [-width / 2, 0], |
| | | // [0, -height / 2], //ä¸è¾¹ |
| | | ] |
| | | } |
| | | } |
| | | |
| | | class StartNode extends HtmlNode { |
| | | [key: string]: any |
| | | constructor(props: any) { |
| | | super(props) |
| | | this.app = createApp(() => { |
| | | const { properties } = this.props.model |
| | | return ( |
| | | <BaseNode |
| | | width="116px" |
| | | height="30px" |
| | | borderColor="rgb(146, 101, 243)" |
| | | icon="start" |
| | | node={properties} |
| | | background="#fff" |
| | | color="#333" |
| | | /> |
| | | ) |
| | | }) |
| | | } |
| | | |
| | | setHtml(rootEl: HTMLElement) { |
| | | const dom = document.createElement('div') |
| | | rootEl.appendChild(dom) |
| | | this.app.mount(dom) |
| | | } |
| | | } |
| | | |
| | | export default { |
| | | type: NODES.ACTIVITY, |
| | | view: StartNode, |
| | | model: StartModel, |
| | | } |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | import { HtmlNodeModel, HtmlNode } from '@logicflow/core' |
| | | import { h, createApp } from 'vue' |
| | | import { NODES } from '../../../core/enum' |
| | | import { Node, NodeModel } from '../Node' |
| | | |
| | | class BusinessModel extends NodeModel {} |
| | | |
| | | class BusinessNode extends Node { |
| | | [key: string]: any |
| | | constructor(props: any) { |
| | | const option = { |
| | | color: '#ab47bc', |
| | | background: '#fff', |
| | | height: '36px', |
| | | icon: 'varsetting', |
| | | } |
| | | super(props, option) |
| | | } |
| | | } |
| | | |
| | | export default { |
| | | type: NODES.BUSINESS_ACTIVITY, |
| | | view: BusinessNode, |
| | | model: BusinessModel, |
| | | } |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | import { HtmlNodeModel, HtmlNode } from '@logicflow/core' |
| | | import { h, createApp } from 'vue' |
| | | import { NODES } from '../../../core/enum' |
| | | import { Node, NodeModel } from '../Node' |
| | | |
| | | class DetermineProcessModel extends NodeModel {} |
| | | |
| | | class DetermineProcessNode extends Node { |
| | | [key: string]: any |
| | | constructor(props: any) { |
| | | const option = { |
| | | color: '#ab47bc', |
| | | background: '#fff', |
| | | height: '36px', |
| | | icon: 'varsetting', |
| | | } |
| | | super(props, option) |
| | | } |
| | | } |
| | | |
| | | export default { |
| | | type: NODES.DETERMINE_PROCESS_ACTIVITY, |
| | | view: DetermineProcessNode, |
| | | model: DetermineProcessModel, |
| | | } |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | import { HtmlNodeModel, HtmlNode } from '@logicflow/core' |
| | | import { h, createApp } from 'vue' |
| | | import { NODES } from '../../../core/enum' |
| | | import { Node, NodeModel } from '../Node' |
| | | |
| | | class DuplicateCodeDetectionModel extends NodeModel {} |
| | | |
| | | class DuplicateCodeDetectionNode extends Node { |
| | | [key: string]: any |
| | | constructor(props: any) { |
| | | const option = { |
| | | color: '#ab47bc', |
| | | background: '#fff', |
| | | height: '36px', |
| | | icon: 'varsetting', |
| | | } |
| | | super(props, option) |
| | | } |
| | | } |
| | | |
| | | export default { |
| | | type: NODES.DUPLICATE_CODE_DETECTION_ACTIVITY, |
| | | view: DuplicateCodeDetectionNode, |
| | | model: DuplicateCodeDetectionModel, |
| | | } |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | import { HtmlNodeModel, HtmlNode } from '@logicflow/core' |
| | | import { h, createApp } from 'vue' |
| | | import { NODES } from '../../../core/enum' |
| | | import { Node, NodeModel } from '../Node' |
| | | |
| | | class InboundInitializeModel extends NodeModel {} |
| | | |
| | | class InboundInitializeNode extends Node { |
| | | [key: string]: any |
| | | constructor(props: any) { |
| | | const option = { |
| | | color: '#ab47bc', |
| | | background: '#fff', |
| | | height: '36px', |
| | | icon: 'varsetting', |
| | | } |
| | | super(props, option) |
| | | } |
| | | } |
| | | |
| | | export default { |
| | | type: NODES.VARIABLE_MONITOR_ACTIVITY, |
| | | view: InboundInitializeNode, |
| | | model: InboundInitializeModel, |
| | | } |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | import { HtmlNodeModel, HtmlNode } from '@logicflow/core' |
| | | import { h, createApp } from 'vue' |
| | | import { NODES } from '../../../core/enum' |
| | | import { Node, NodeModel } from '../Node' |
| | | |
| | | class LocalQualificationJudgmentModel extends NodeModel {} |
| | | |
| | | class LocalQualificationJudgmentNode extends Node { |
| | | [key: string]: any |
| | | constructor(props: any) { |
| | | const option = { |
| | | color: '#ab47bc', |
| | | background: '#fff', |
| | | height: '36px', |
| | | icon: 'varsetting', |
| | | } |
| | | super(props, option) |
| | | } |
| | | } |
| | | |
| | | export default { |
| | | type: NODES.LOCAL_QUALIFICATION_JUDGMENT_ACTIVITY, |
| | | view: LocalQualificationJudgmentNode, |
| | | model: LocalQualificationJudgmentModel, |
| | | } |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | import { HtmlNodeModel, HtmlNode } from '@logicflow/core' |
| | | import { h, createApp } from 'vue' |
| | | import { NODES } from '../../../core/enum' |
| | | import { Node, NodeModel } from '../Node' |
| | | |
| | | class MaterialAssociationModel extends NodeModel {} |
| | | |
| | | class MaterialAssociationNode extends Node { |
| | | [key: string]: any |
| | | constructor(props: any) { |
| | | const option = { |
| | | color: '#ab47bc', |
| | | background: '#fff', |
| | | height: '36px', |
| | | icon: 'varsetting', |
| | | } |
| | | super(props, option) |
| | | } |
| | | } |
| | | |
| | | export default { |
| | | type: NODES.MATERIAL_ASSOCIATION_ACTIVITY, |
| | | view: MaterialAssociationNode, |
| | | model: MaterialAssociationModel, |
| | | } |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | import { HtmlNodeModel, HtmlNode } from '@logicflow/core' |
| | | import { h, createApp } from 'vue' |
| | | import { NODES } from '../../../core/enum' |
| | | import { Node, NodeModel } from '../Node' |
| | | |
| | | class MissingProcessDetectionModel extends NodeModel {} |
| | | |
| | | class MissingProcessDetectionNode extends Node { |
| | | [key: string]: any |
| | | constructor(props: any) { |
| | | const option = { |
| | | color: '#ab47bc', |
| | | background: '#fff', |
| | | height: '36px', |
| | | icon: 'varsetting', |
| | | } |
| | | super(props, option) |
| | | } |
| | | } |
| | | |
| | | export default { |
| | | type: NODES.MISSING_PROCESS_DETECTION_ACTIVITY, |
| | | view: MissingProcessDetectionNode, |
| | | model: MissingProcessDetectionModel, |
| | | } |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | import { HtmlNodeModel, HtmlNode } from '@logicflow/core' |
| | | import { h, createApp } from 'vue' |
| | | import { NODES } from '../../../core/enum' |
| | | import { Node, NodeModel } from '../Node' |
| | | |
| | | class OutboundInitializeModel extends NodeModel {} |
| | | |
| | | class OutboundInitializeNode extends Node { |
| | | [key: string]: any |
| | | constructor(props: any) { |
| | | const option = { |
| | | color: '#ab47bc', |
| | | background: '#fff', |
| | | height: '36px', |
| | | icon: 'varsetting', |
| | | } |
| | | super(props, option) |
| | | } |
| | | } |
| | | |
| | | export default { |
| | | type: NODES.OUTBOUND_INITIALIZE_ACTIVITY, |
| | | view: OutboundInitializeNode, |
| | | model: OutboundInitializeModel, |
| | | } |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | import { HtmlNodeModel, HtmlNode } from '@logicflow/core' |
| | | import { h, createApp } from 'vue' |
| | | import { NODES } from '../../../core/enum' |
| | | import { Node, NodeModel } from '../Node' |
| | | |
| | | class PLCQualificationJudgmentModel extends NodeModel {} |
| | | |
| | | class PLCQualificationJudgmentNode extends Node { |
| | | [key: string]: any |
| | | constructor(props: any) { |
| | | const option = { |
| | | color: '#ab47bc', |
| | | background: '#fff', |
| | | height: '36px', |
| | | icon: 'varsetting', |
| | | } |
| | | super(props, option) |
| | | } |
| | | } |
| | | |
| | | export default { |
| | | type: NODES.PLC_QUALIFICATION_JUDGMENT_ACTIVITY, |
| | | view: PLCQualificationJudgmentNode, |
| | | model: PLCQualificationJudgmentModel, |
| | | } |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | import { HtmlNodeModel, HtmlNode } from '@logicflow/core' |
| | | import { h, createApp } from 'vue' |
| | | import { NODES } from '../../../core/enum' |
| | | import { Node, NodeModel } from '../Node' |
| | | |
| | | class ParameterCollectModel extends NodeModel {} |
| | | |
| | | class ParameterCollectNode extends Node { |
| | | [key: string]: any |
| | | constructor(props: any) { |
| | | const option = { |
| | | color: '#ab47bc', |
| | | background: '#fff', |
| | | height: '36px', |
| | | icon: 'varsetting', |
| | | } |
| | | super(props, option) |
| | | } |
| | | } |
| | | |
| | | export default { |
| | | type: NODES.PARAMETER_COLLECT_ACTIVITY, |
| | | view: ParameterCollectNode, |
| | | model: ParameterCollectModel, |
| | | } |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | import { HtmlNodeModel, HtmlNode } from '@logicflow/core' |
| | | import { h, createApp } from 'vue' |
| | | import { NODES } from '../../../core/enum' |
| | | import { Node, NodeModel } from '../Node' |
| | | |
| | | class ParameterSaveModel extends NodeModel {} |
| | | |
| | | class ParameterSaveNode extends Node { |
| | | [key: string]: any |
| | | constructor(props: any) { |
| | | const option = { |
| | | color: '#ab47bc', |
| | | background: '#fff', |
| | | height: '36px', |
| | | icon: 'varsetting', |
| | | } |
| | | super(props, option) |
| | | } |
| | | } |
| | | |
| | | export default { |
| | | type: NODES.PARAMETER_SAVE_ACTIVITY, |
| | | view: ParameterSaveNode, |
| | | model: ParameterSaveModel, |
| | | } |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | import { HtmlNodeModel, HtmlNode } from '@logicflow/core' |
| | | import { h, createApp } from 'vue' |
| | | import { NODES } from '../../../core/enum' |
| | | import { Node, NodeModel } from '../Node' |
| | | |
| | | class ProductStateDetectionModel extends NodeModel {} |
| | | |
| | | class ProductStateDetectionNode extends Node { |
| | | [key: string]: any |
| | | constructor(props: any) { |
| | | const option = { |
| | | color: '#ab47bc', |
| | | background: '#fff', |
| | | height: '36px', |
| | | icon: 'varsetting', |
| | | } |
| | | super(props, option) |
| | | } |
| | | } |
| | | |
| | | export default { |
| | | type: NODES.PRODUCT_STATEDETECTION_ACTIVITY, |
| | | view: ProductStateDetectionNode, |
| | | model: ProductStateDetectionModel, |
| | | } |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | import { HtmlNodeModel, HtmlNode } from '@logicflow/core' |
| | | import { h, createApp } from 'vue' |
| | | import { NODES } from '../../../core/enum' |
| | | import { Node, NodeModel } from '../Node' |
| | | |
| | | class TrayAssociationModel extends NodeModel {} |
| | | |
| | | class TrayAssociationNode extends Node { |
| | | [key: string]: any |
| | | constructor(props: any) { |
| | | const option = { |
| | | color: '#ab47bc', |
| | | background: '#fff', |
| | | height: '36px', |
| | | icon: 'varsetting', |
| | | } |
| | | super(props, option) |
| | | } |
| | | } |
| | | |
| | | export default { |
| | | type: NODES.TRAY_ASSOCIATION_ACTIVITY, |
| | | view: TrayAssociationNode, |
| | | model: TrayAssociationModel, |
| | | } |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | import { HtmlNodeModel, HtmlNode } from '@logicflow/core' |
| | | import { h, createApp } from 'vue' |
| | | import { NODES } from '../../../core/enum' |
| | | import { Node, NodeModel } from '../Node' |
| | | |
| | | class VariableMonitorModel extends NodeModel {} |
| | | |
| | | class VariableMonitorNode extends Node { |
| | | [key: string]: any |
| | | constructor(props: any) { |
| | | const option = { |
| | | color: '#ab47bc', |
| | | background: '#fff', |
| | | height: '36px', |
| | | icon: 'varsetting', |
| | | } |
| | | super(props, option) |
| | | } |
| | | } |
| | | |
| | | export default { |
| | | type: NODES.VARIABLE_MONITOR_ACTIVITY, |
| | | view: VariableMonitorNode, |
| | | model: VariableMonitorModel, |
| | | } |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | import { HtmlNodeModel, HtmlNode } from '@logicflow/core' |
| | | import { h, createApp } from 'vue' |
| | | import { NODES } from '../../../core/enum' |
| | | import { Node, NodeModel } from '../Node' |
| | | |
| | | class VariableReadNodeModel extends NodeModel {} |
| | | |
| | | class VariableReadNodeNode extends Node { |
| | | [key: string]: any |
| | | constructor(props: any) { |
| | | const option = { |
| | | color: '#ab47bc', |
| | | background: '#fff', |
| | | height: '36px', |
| | | icon: 'varsetting', |
| | | } |
| | | super(props, option) |
| | | } |
| | | } |
| | | |
| | | export default { |
| | | type: NODES.VARIABLE_READ_ACTIVITY, |
| | | view: VariableReadNodeNode, |
| | | model: VariableReadNodeModel, |
| | | } |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | import { HtmlNodeModel, HtmlNode } from '@logicflow/core' |
| | | import { h, createApp } from 'vue' |
| | | import { NODES } from '../../../core/enum' |
| | | import { Node, NodeModel } from '../Node' |
| | | |
| | | class VariableWriteNodeModel extends NodeModel {} |
| | | |
| | | class VariableWriteNodeNode extends Node { |
| | | [key: string]: any |
| | | constructor(props: any) { |
| | | const option = { |
| | | color: '#ab47bc', |
| | | background: '#fff', |
| | | height: '36px', |
| | | icon: 'varsetting', |
| | | } |
| | | super(props, option) |
| | | } |
| | | } |
| | | |
| | | export default { |
| | | type: NODES.VARIABLE_WRITE_ACTIVITY, |
| | | view: VariableWriteNodeNode, |
| | | model: VariableWriteNodeModel, |
| | | } |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | // å¼å§èç¹ä¸ç»æèç¹ |
| | | .baseNodeContent { |
| | | padding: 2px; |
| | | .baseNode { |
| | | width: 101px; |
| | | height: 33px; |
| | | border: 1px solid #ccc; |
| | | border-radius: 5px; |
| | | font-size: 12px; |
| | | display: flex; |
| | | justify-content: space-between; |
| | | align-items: center; |
| | | box-shadow: 0 -1px 4px 0 rgba(247, 140, 227, 0.5), |
| | | 1px 1px 4px 0 rgba(230, 174, 220, 0.5); |
| | | padding: 0 16px; |
| | | position: relative; |
| | | .detail { |
| | | display: none; |
| | | } |
| | | &:hover { |
| | | .detail { |
| | | display: block; |
| | | } |
| | | } |
| | | .nodeText { |
| | | width: calc(100% - 20px); |
| | | margin-left: 10px; |
| | | } |
| | | } |
| | | |
| | | .baseNodeSelected { |
| | | border-color: #5a84ff !important; |
| | | box-shadow: 0 0 0 3px #c8d3f2; |
| | | background-color: #e7ecfd !important; |
| | | } |
| | | .detail { |
| | | position: absolute; |
| | | right: 3px; |
| | | top: 3px; |
| | | cursor: pointer; |
| | | &:hover { |
| | | filter: invert(48%) sepia(64%) saturate(2590%) hue-rotate(206deg) |
| | | brightness(100%) contrast(102%); |
| | | } |
| | | } |
| | | } |
| | | // æµç¨èç¹ |
| | | .flowNodeContent { |
| | | padding: 2px; |
| | | .flowNode { |
| | | width: 200px; |
| | | height: 130px; |
| | | border: 1px solid #ccc; |
| | | background-color: #fff; |
| | | border-radius: 5px; |
| | | font-size: 12px; |
| | | display: flex; |
| | | justify-content: flex-start; |
| | | flex-direction: column; |
| | | align-items: center; |
| | | box-shadow: 0 -1px 4px 0 rgba(209, 209, 209, 50%), |
| | | 1px 1px 4px 0 rgba(217, 217, 217, 50%); |
| | | } |
| | | .flowNodeSelected { |
| | | border-color: #5a84ff; |
| | | box-shadow: 0 0 0 3px #c8d3f2; |
| | | } |
| | | .flowHeader { |
| | | width: 100%; |
| | | height: 36px; |
| | | border-bottom: 1px solid #ccc; |
| | | display: flex; |
| | | justify-content: space-between; |
| | | align-items: center; |
| | | padding: 0 5px; |
| | | color: #fff; |
| | | background: #fff; |
| | | font-weight: 500; |
| | | font-size: 14px; |
| | | border-top-left-radius: 5px; |
| | | border-top-right-radius: 5px; |
| | | flex-shrink: 0; |
| | | } |
| | | .flowNodeMain { |
| | | width: 100%; |
| | | padding: 5px; |
| | | display: flex; |
| | | justify-content: space-between; |
| | | align-items: center; |
| | | flex-direction: column; |
| | | .flowInfo { |
| | | display: flex; |
| | | justify-content: space-between; |
| | | align-items: center; |
| | | width: 100%; |
| | | margin-bottom: 4px; |
| | | |
| | | .label { |
| | | font-size: 12px; |
| | | } |
| | | .info { |
| | | font-size: 12px; |
| | | } |
| | | } |
| | | } |
| | | } |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | import StartNode from './StartNode' |
| | | import EndNode from './EndNode' |
| | | // import Node from './Node' |
| | | |
| | | export default { |
| | | StartNode, |
| | | EndNode, |
| | | // Node, |
| | | } |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | .renderer { |
| | | :global(.lf-mini-map-header) { |
| | | display: none; |
| | | } |
| | | :global(.lf-mini-map) { |
| | | border: 1px solid #ccc; |
| | | background-color: #fff; |
| | | } |
| | | } |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | import { |
| | | defineComponent, |
| | | onMounted, |
| | | ref, |
| | | nextTick, |
| | | watch, |
| | | computed, |
| | | getCurrentInstance, |
| | | SetupContext, |
| | | } from 'vue' |
| | | import LogicFlow, { BaseEdgeModel } from '@logicflow/core' |
| | | import '@logicflow/core/dist/style/index.css' |
| | | import Dagre from '../../core/dagre' |
| | | import { createStore } from '../../core/store' |
| | | import { MiniMap } from '@logicflow/extension' |
| | | import Curve from '../Edges/Curve' |
| | | import StartNode from '../Nodes/StartNode' |
| | | import EndNode from '../Nodes/EndNode' |
| | | import OrdinaryNode from '../Nodes/OrdinaryNode' |
| | | import { eventMap } from '../../core/event' |
| | | import { |
| | | toLowerCaseFirstLetter, |
| | | getNodeTargetLines, |
| | | } from '../../core/transformHelp' |
| | | import { isFunction } from 'lodash' |
| | | import styles from './Renderer.module.scss' |
| | | import { emitter } from '../../core/store' |
| | | import Empty from '@/components/Empty/Empty' |
| | | |
| | | interface PropsType { |
| | | graphData: Record<string, any> |
| | | [key: string]: any |
| | | style: Record<string, any> |
| | | } |
| | | |
| | | export default defineComponent<PropsType>({ |
| | | // @ts-ignore |
| | | name: 'LogicFlowRenderer', |
| | | props: { |
| | | graphData: { |
| | | type: Object, |
| | | required: true, |
| | | }, |
| | | style: { type: Object, default: () => ({}) }, |
| | | minimap: { type: [Boolean, Object], default: false }, |
| | | isEdgeAnimation: { type: Boolean, default: false }, |
| | | }, |
| | | // emits: Object.keys(eventMap), |
| | | setup(props: PropsType, { expose, attrs, slots, emit }: SetupContext) { |
| | | const lfRef = ref() |
| | | const lf = ref() |
| | | const store = createStore() |
| | | const { onCancelSelect, showEdgeAnimation } = store |
| | | const logicFlowConfig = computed(() => { |
| | | return { |
| | | ...attrs, |
| | | } |
| | | }) |
| | | /** |
| | | * 注åè¾¹ä¸èç¹ |
| | | */ |
| | | const batchRegister = () => { |
| | | lf.value.batchRegister([Curve, StartNode, EndNode, OrdinaryNode]) |
| | | } |
| | | /** |
| | | * 主é¢è®¾ç½® |
| | | */ |
| | | const setTheme = () => { |
| | | const theme = store.theme |
| | | lf.value.setTheme(theme.value) |
| | | } |
| | | /** |
| | | * èªå¨å¸å± |
| | | */ |
| | | const autoLayout = () => { |
| | | if (lf.value?.extension?.dagre) { |
| | | lf.value.extension.dagre.layout({ |
| | | nodesep: 40, |
| | | ranksep: 30, |
| | | // radial: true, |
| | | // controlPoints: true, |
| | | }) |
| | | } |
| | | } |
| | | |
| | | const showMiniMap = () => { |
| | | if (!props.minimap) return |
| | | |
| | | let params: { |
| | | leftPosition?: number | string |
| | | topPosition?: number | string |
| | | } = { |
| | | leftPosition: 20, |
| | | topPosition: 20, |
| | | } |
| | | if (typeof props.minimap === 'object') { |
| | | params = props.minimap |
| | | } |
| | | lf.value?.extension.miniMap.show(params.leftPosition, params.topPosition) |
| | | } |
| | | /** |
| | | * 渲æé»è¾æµ |
| | | * @param graphData |
| | | */ |
| | | const renderLogicFlow = () => { |
| | | if (!Object.keys(props.graphData).length) return |
| | | lf.value.render(props.graphData) |
| | | |
| | | return nextTick(autoLayout) |
| | | } |
| | | /** |
| | | * åå§å渲æ |
| | | */ |
| | | const initializeRenderer = async () => { |
| | | batchRegister() |
| | | setTheme() |
| | | await renderLogicFlow() |
| | | showMiniMap() |
| | | |
| | | initializeEvent() |
| | | } |
| | | /** |
| | | * å®ä¾åLogicFlow |
| | | */ |
| | | const instanceLogicFlow = () => { |
| | | if (!Object.keys(props.graphData).length) return |
| | | lf.value = new LogicFlow({ |
| | | container: lfRef.value, |
| | | plugins: [Dagre, MiniMap], |
| | | ...logicFlowConfig.value, |
| | | }) |
| | | store.lf.value = lf.value |
| | | initializeRenderer() |
| | | } |
| | | |
| | | /** |
| | | * 注åäºä»¶ |
| | | */ |
| | | const initializeEvent = () => { |
| | | const eventBox: string[] = [] |
| | | const eventNameMap: Record<string, any> = {} |
| | | // 注åèç¹äºä»¶ |
| | | emitter.on('view', (node: any) => emit('view', node)) |
| | | // clickäºä»¶åç¬åå¤ç |
| | | lf.value?.on(eventMap.nodeClick, (...arg: any) => { |
| | | const { data } = arg[0] |
| | | emit(eventMap.nodeClick, ...arg) |
| | | if (props.isEdgeAnimation) { |
| | | showEdgeAnimation(data) |
| | | } |
| | | }) |
| | | Object.entries(attrs).forEach(([eventName, fn]) => { |
| | | if (eventName.includes('on')) { |
| | | const name = toLowerCaseFirstLetter(eventName.replace('on', '')) |
| | | eventNameMap[name] = fn |
| | | if (eventMap.nodeClick !== name) { |
| | | eventBox.push(name) |
| | | } |
| | | } |
| | | }) |
| | | |
| | | Object.entries(eventMap).forEach(([key, eventName]: string[]) => { |
| | | if (eventBox.includes(key)) { |
| | | lf.value?.on(eventName, (...arg: any) => { |
| | | emit(key, ...arg) |
| | | }) |
| | | } |
| | | }) |
| | | } |
| | | /** |
| | | * è·åå½åLogicFlowå®ä¾ |
| | | * @returns |
| | | */ |
| | | const getCurrentInstance = () => { |
| | | return lf.value |
| | | } |
| | | |
| | | watch( |
| | | () => props.graphData, |
| | | (v, oldV) => { |
| | | if (v !== oldV && v) { |
| | | instanceLogicFlow() |
| | | } |
| | | } |
| | | ) |
| | | |
| | | onMounted(() => { |
| | | instanceLogicFlow() |
| | | }) |
| | | |
| | | expose({ |
| | | autoLayout, |
| | | getCurrentInstance, |
| | | }) |
| | | return () => { |
| | | return ( |
| | | <div |
| | | class={styles.renderer} |
| | | onClick={(event: Event) => onCancelSelect(event)} |
| | | ref={lfRef} |
| | | style={{ width: '100%', height: '100%', ...props.style }} |
| | | > |
| | | {slots.default?.()} |
| | | </div> |
| | | ) |
| | | } |
| | | }, |
| | | }) |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | import { defineComponent } from 'vue' |
| | | import { injectStore } from '../../core/store' |
| | | |
| | | export default defineComponent({ |
| | | name: 'Theme', |
| | | props: [ |
| | | 'ellipse', |
| | | 'polygon', |
| | | 'outline', |
| | | 'edgeAdjust', |
| | | 'text', |
| | | 'snapline', |
| | | 'line', |
| | | 'anchorLine', |
| | | 'arrow', |
| | | 'edgeText', |
| | | 'bezier', |
| | | 'polyline', |
| | | 'baseEdge', |
| | | 'nodeText', |
| | | 'anchor', |
| | | ], |
| | | setup(props, { attrs }) { |
| | | const { theme } = injectStore() |
| | | theme.value = { ...theme.value, ...attrs, ...props } |
| | | return () => null |
| | | }, |
| | | }) |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | // @ts-nocheck |
| | | import { DagreLayout, DagreLayoutOptions } from '@antv/layout' |
| | | import * as d3 from 'd3' |
| | | import * as d3Hierarchy from 'd3-hierarchy' |
| | | import { CURVE, NODES, ActivityKey, TransitionKey, ConditionKey } from './enum' |
| | | |
| | | function convertToTree(nodes, edges, rootId) { |
| | | // å建ä¸ä¸ªç©ºå¯¹è±¡ï¼ç¨äºå°èç¹IDæ å°å°å
¶èªèº«å¯¹è±¡ |
| | | const nodeMap = {} |
| | | |
| | | // éåèç¹å表ï¼å°æ¯ä¸ªèç¹IDæ å°å°å
¶èªèº«å¯¹è±¡ï¼å¹¶åå§åchildren屿§ä¸ºç©ºæ°ç» |
| | | nodes.forEach((node) => { |
| | | nodeMap[node.id] = { ...node, children: [] } |
| | | }) |
| | | |
| | | // éåè¾¹å表ï¼å°æ¯ä¸ªè¾¹çæºèç¹è¿æ¥å°ç®æ èç¹ |
| | | edges.forEach((edge) => { |
| | | const sourceNode = nodeMap[edge.source] |
| | | const targetNode = nodeMap[edge.target] |
| | | sourceNode.children.push(targetNode) |
| | | }) |
| | | // è¿åæ ¹èç¹å¯¹è±¡ |
| | | return nodeMap[rootId] |
| | | } |
| | | export default class Dagre { |
| | | static pluginName = 'dagre' |
| | | lf: any |
| | | option: DagreLayoutOptions |
| | | render(lf: any) { |
| | | this.lf = lf |
| | | } |
| | | getBytesLength(word: string): number { |
| | | if (!word) { |
| | | return 0 |
| | | } |
| | | let totalLength = 0 |
| | | for (let i = 0; i < word.length; i++) { |
| | | const c = word.charCodeAt(i) |
| | | if (word.match(/[A-Z]/)) { |
| | | totalLength += 1.5 |
| | | } else if ((c >= 0x0001 && c <= 0x007e) || (c >= 0xff60 && c <= 0xff9f)) { |
| | | totalLength += 1 |
| | | } else { |
| | | totalLength += 2 |
| | | } |
| | | } |
| | | return totalLength |
| | | } |
| | | /** |
| | | * option: { |
| | | * rankdir: "TB", // layout æ¹å, å¯é TB, BT, LR, RL |
| | | * align: undefined, // èç¹å¯¹é½æ¹å¼ï¼å¯é UL, UR, DL, DR |
| | | * nodeSize: undefined, // èç¹å¤§å° |
| | | * nodesepFunc: undefined, // èç¹æ°´å¹³é´è·(px) |
| | | * ranksepFunc: undefined, // æ¯ä¸å±èç¹ä¹é´é´è· |
| | | * nodesep: 40, // èç¹æ°´å¹³é´è·(px) 注æï¼å¦æægridï¼éè¦ä¿è¯nodesep为gridçå¶æ°å |
| | | * ranksep: 40, // æ¯ä¸å±èç¹ä¹é´é´è· 注æï¼å¦æægridï¼éè¦ä¿è¯ranksep为gridçå¶æ°å |
| | | * controlPoints: false, // æ¯å¦ä¿çå¸å±è¿çº¿çæ§å¶ç¹ |
| | | * radial: false, // æ¯å¦åºäº dagre è¿è¡è¾å°å¸å± |
| | | * focusNode: null, // radial 为 true æ¶çæï¼å
³æ³¨çèç¹ |
| | | * }; |
| | | */ |
| | | layout(option = {}) { |
| | | const { nodes, edges, gridSize } = this.lf.graphModel |
| | | // 为äºä¿è¯çæçèç¹å¨girdSizeä¸ï¼éè¦å¤çä¸ä¸ã |
| | | let nodesep = 40 |
| | | let ranksep = 40 |
| | | if (gridSize > 20) { |
| | | nodesep = gridSize * 2 |
| | | ranksep = gridSize * 2 |
| | | } |
| | | this.option = { |
| | | type: 'dagre', |
| | | rankdir: 'TB', |
| | | // align: 'UL', |
| | | // align: 'UR', |
| | | align: 'DR', |
| | | nodesep, |
| | | ranksep, |
| | | begin: [120, 120], |
| | | controlPoints: true, |
| | | ...option, |
| | | } |
| | | const layoutInstance = new DagreLayout(this.option) |
| | | const nodes1 = nodes.map((node) => ({ |
| | | id: node.id, |
| | | type: node.type, |
| | | model: node, |
| | | |
| | | size: { |
| | | width: node.width, |
| | | height: node.height, |
| | | }, |
| | | })) |
| | | |
| | | const edges1 = edges.map((edge) => ({ |
| | | source: edge.sourceNodeId, |
| | | target: edge.targetNodeId, |
| | | model: edge, |
| | | })) |
| | | const rootId = nodes.find((node) => node.type === 'Activity')?.id |
| | | const treeData = convertToTree(nodes1, edges1, rootId) |
| | | var treemap = d3.tree().size([1066, 1145]) |
| | | const root = d3.hierarchy(treeData, function (d) { |
| | | return d.children |
| | | }) |
| | | treemap(root) |
| | | function treeToMap(root) { |
| | | const map = new Map() |
| | | |
| | | root.each((node) => { |
| | | map.set(node.data.id, node) |
| | | }) |
| | | return map |
| | | } |
| | | function getFlowLayout(nodeMap) { |
| | | let edges = [] |
| | | const nodes = [] |
| | | nodeMap.forEach((node) => { |
| | | nodes.push({ |
| | | id: node.data.id, |
| | | type: node.data.type, |
| | | model: node.data.model, |
| | | x: node.x, |
| | | y: node.y, |
| | | properties: node.data.model?.properties, |
| | | size: { |
| | | width: node.data.model.width, |
| | | height: node.data.model.height, |
| | | }, |
| | | }) |
| | | const childData = [] |
| | | if (node?.children) { |
| | | node?.children?.forEach((nodeChild) => { |
| | | childData.push({ |
| | | properties: nodeChild.data.model?.properties, |
| | | sourceNodeId: node?.parent?.data?.id, |
| | | targetNodeId: nodeChild.data?.id, |
| | | model: nodeChild.data.model, |
| | | id: nodeChild.data.model?.id, |
| | | type: CURVE, |
| | | }) |
| | | }) |
| | | } else { |
| | | childData.push({ |
| | | sourceNodeId: node?.parent?.data?.id, |
| | | model: node.data.model, |
| | | id: node.data.model?.id, |
| | | properties: node.data.model?.properties, |
| | | |
| | | type: CURVE, |
| | | }) |
| | | } |
| | | edges = edges.concat(childData) |
| | | }) |
| | | return { |
| | | nodes, |
| | | edges, |
| | | } |
| | | } |
| | | const nodeMap = treeToMap(root) |
| | | const v = getFlowLayout(nodeMap) |
| | | |
| | | const layoutData = layoutInstance.layout({ |
| | | nodes: nodes.map((node) => ({ |
| | | id: node.id, |
| | | size: { |
| | | width: node.width, |
| | | height: node.height, |
| | | }, |
| | | model: node, |
| | | })), |
| | | edges: edges.map((edge) => ({ |
| | | source: edge.sourceNodeId, |
| | | target: edge.targetNodeId, |
| | | model: edge, |
| | | })), |
| | | }) |
| | | const newGraphData = { |
| | | nodes: [], |
| | | edges: [], |
| | | } |
| | | layoutData.nodes.forEach((node) => { |
| | | // @ts-ignore: pass node data |
| | | const { model } = node |
| | | const data = model.getData() |
| | | // @ts-ignore: pass node data |
| | | data.x = node.x |
| | | // @ts-ignore: pass node data |
| | | data.y = node.y |
| | | |
| | | if (data.text) { |
| | | data.text = { |
| | | x: node.x + 10, |
| | | y: node.y - this.getBytesLength(data.text) * 6 - 10, |
| | | value: data.text.value, |
| | | } |
| | | } |
| | | newGraphData.nodes.push(data) |
| | | }) |
| | | layoutData.edges.forEach((edge) => { |
| | | // @ts-ignore: pass edge data |
| | | const { model } = edge |
| | | const data = model.getData() |
| | | data.pointsList = this.calcPointsList(model, newGraphData.nodes) |
| | | if (data.pointsList) { |
| | | const first = data.pointsList[0] |
| | | const last = data.pointsList[data.pointsList.length - 1] |
| | | data.startPoint = { x: first.x, y: first.y } |
| | | data.endPoint = { x: last.x, y: last.y } |
| | | if (data.text && data.text.value) { |
| | | data.text = { |
| | | x: last.x, |
| | | y: last.y - this.getBytesLength(data.text.value) * 8, |
| | | value: data.text.value, |
| | | } |
| | | } |
| | | } else { |
| | | data.startPoint = undefined |
| | | data.endPoint = undefined |
| | | if (data.text && data.text.value) { |
| | | data.text = data.text.value |
| | | } |
| | | } |
| | | newGraphData.edges.push(data) |
| | | }) |
| | | // console.log(v, newGraphData, '000---') |
| | | |
| | | this.lf.render(newGraphData) |
| | | } |
| | | pointFilter(points) { |
| | | const allPoints = points |
| | | let i = 1 |
| | | while (i < allPoints.length - 1) { |
| | | const pre = allPoints[i - 1] |
| | | const current = allPoints[i] |
| | | const next = allPoints[i + 1] |
| | | if ( |
| | | (pre.x === current.x && current.x === next.x) || |
| | | (pre.y === current.y && current.y === next.y) |
| | | ) { |
| | | allPoints.splice(i, 1) |
| | | } else { |
| | | i++ |
| | | } |
| | | } |
| | | return allPoints |
| | | } |
| | | calcPointsList(model, nodes) { |
| | | // å¨èç¹ç¡®è®¤ä»å·¦åå³åï¼éè¿è®¡ç®æ¥ä¿è¯èç¹è¿çº¿æ¸
æ°ã |
| | | // TODO: é¿é |
| | | const pointsList = [] |
| | | if (this.option.rankdir === 'LR') { |
| | | const sourceNodeModel = this.lf.getNodeModelById(model.sourceNodeId) |
| | | const targetNodeModel = this.lf.getNodeModelById(model.targetNodeId) |
| | | const newSourceNodeData = nodes.find( |
| | | (node) => node.id === model.sourceNodeId |
| | | ) |
| | | const newTargetNodeData = nodes.find( |
| | | (node) => node.id === model.targetNodeId |
| | | ) |
| | | if (newSourceNodeData.x < newTargetNodeData.x) { |
| | | pointsList.push({ |
| | | x: newSourceNodeData.x + sourceNodeModel.width / 2, |
| | | y: newSourceNodeData.y, |
| | | }) |
| | | pointsList.push({ |
| | | x: |
| | | newSourceNodeData.x + |
| | | sourceNodeModel.width / 2 + |
| | | (model.offset || 50), |
| | | y: newSourceNodeData.y, |
| | | }) |
| | | pointsList.push({ |
| | | x: |
| | | newSourceNodeData.x + |
| | | sourceNodeModel.width / 2 + |
| | | (model.offset || 50), |
| | | y: newTargetNodeData.y, |
| | | }) |
| | | pointsList.push({ |
| | | x: newTargetNodeData.x - targetNodeModel.width / 2, |
| | | y: newTargetNodeData.y, |
| | | }) |
| | | return this.pointFilter(pointsList) |
| | | } |
| | | // ååè¿çº¿ |
| | | if (newSourceNodeData.x > newTargetNodeData.x) { |
| | | if (newSourceNodeData.y >= newTargetNodeData.y) { |
| | | pointsList.push({ |
| | | x: newSourceNodeData.x, |
| | | y: newSourceNodeData.y + sourceNodeModel.height / 2, |
| | | }) |
| | | pointsList.push({ |
| | | x: newSourceNodeData.x, |
| | | y: |
| | | newSourceNodeData.y + |
| | | sourceNodeModel.height / 2 + |
| | | (model.offset || 50), |
| | | }) |
| | | pointsList.push({ |
| | | x: newTargetNodeData.x, |
| | | y: |
| | | newSourceNodeData.y + |
| | | sourceNodeModel.height / 2 + |
| | | (model.offset || 50), |
| | | }) |
| | | pointsList.push({ |
| | | x: newTargetNodeData.x, |
| | | y: newTargetNodeData.y + targetNodeModel.height / 2, |
| | | }) |
| | | } else { |
| | | pointsList.push({ |
| | | x: newSourceNodeData.x, |
| | | y: newSourceNodeData.y - sourceNodeModel.height / 2, |
| | | }) |
| | | pointsList.push({ |
| | | x: newSourceNodeData.x, |
| | | y: |
| | | newSourceNodeData.y - |
| | | sourceNodeModel.height / 2 - |
| | | (model.offset || 50), |
| | | }) |
| | | pointsList.push({ |
| | | x: newTargetNodeData.x, |
| | | y: |
| | | newSourceNodeData.y - |
| | | sourceNodeModel.height / 2 - |
| | | (model.offset || 50), |
| | | }) |
| | | pointsList.push({ |
| | | x: newTargetNodeData.x, |
| | | y: newTargetNodeData.y - targetNodeModel.height / 2, |
| | | }) |
| | | } |
| | | console.log(pointsList, 'pointsList') |
| | | return this.pointFilter(pointsList) |
| | | } |
| | | } |
| | | return undefined |
| | | } |
| | | } |
| PipeLineLems/web/src/components/LogicFlow/core/dagre.ts
PipeLineLems/web/src/components/LogicFlow/core/enum.ts
PipeLineLems/web/src/components/LogicFlow/core/event.ts
PipeLineLems/web/src/components/LogicFlow/core/layout.ts
PipeLineLems/web/src/components/LogicFlow/core/store.ts
PipeLineLems/web/src/components/LogicFlow/core/transformHelp.ts
PipeLineLems/web/src/components/LogicFlow/type/index.d.ts
PipeLineLems/web/src/components/Menu/index.vue
PipeLineLems/web/src/components/MyPages/index.vue
PipeLineLems/web/src/components/Pdf/index.vue
PipeLineLems/web/src/components/PrintDialog/PrintDialog.module.scss
PipeLineLems/web/src/components/PrintDialog/PrintDialog.tsx
PipeLineLems/web/src/components/ProcessRouterDialog/ProcessRouterDialog.module.scss
PipeLineLems/web/src/components/ProcessRouterDialog/ProcessRouterDialog.tsx
PipeLineLems/web/src/components/ProcessRouterDialog/api.ts
PipeLineLems/web/src/components/ProcessRouterDialog/hook.ts
PipeLineLems/web/src/components/ProcessRoutes/ProcessRoutes.module.scss
PipeLineLems/web/src/components/ProcessRoutes/ProcessRoutes.tsx
PipeLineLems/web/src/components/ProductSelectDialog/ProductSelectDialog.module.scss
PipeLineLems/web/src/components/ProductSelectDialog/ProductSelectDialog.tsx
PipeLineLems/web/src/components/ProductSelectDialog/hook.ts
PipeLineLems/web/src/components/ProjectConfig/ProjectConfig.module.scss
PipeLineLems/web/src/components/ProjectConfig/ProjectConfig.tsx
PipeLineLems/web/src/components/Radio/Radio.module.scss
PipeLineLems/web/src/components/Radio/Radio.tsx
PipeLineLems/web/src/components/RelationFlowDialog/RelationFlowDialog.module.scss
PipeLineLems/web/src/components/RelationFlowDialog/RelationFlowDialog.tsx
PipeLineLems/web/src/components/RelationFlowDialog/app.ts
PipeLineLems/web/src/components/RelationFlowDialog/enum.ts
PipeLineLems/web/src/components/Search/Search.tsx
PipeLineLems/web/src/components/SearchSelect/Option.tsx
PipeLineLems/web/src/components/SearchSelect/SearchSelect.tsx
PipeLineLems/web/src/components/SearchSelect/Select.module.scss
PipeLineLems/web/src/components/Segment/segment.module.scss
PipeLineLems/web/src/components/Segment/segment.tsx
PipeLineLems/web/src/components/Select/Option.tsx
PipeLineLems/web/src/components/Select/Select.module.scss
PipeLineLems/web/src/components/Select/Select.tsx
PipeLineLems/web/src/components/Select/Select1.tsx
PipeLineLems/web/src/components/SelectInput/SelectInput.tsx
PipeLineLems/web/src/components/Setting/Setting.tsx
PipeLineLems/web/src/components/SvgIcon/SvgIcon.module.scss
PipeLineLems/web/src/components/SvgIcon/SvgIcon.tsx
PipeLineLems/web/src/components/Tab/Tab.tsx
PipeLineLems/web/src/components/Tab/TabPane.tsx
PipeLineLems/web/src/components/Table/index.module.scss
PipeLineLems/web/src/components/TableArray/TableArray.module.scss
PipeLineLems/web/src/components/TableArray/TableArray.tsx
PipeLineLems/web/src/components/TableFilter/TableFilter.module.scss
PipeLineLems/web/src/components/TableFilter/TableFilter.tsx
PipeLineLems/web/src/components/Tag/Tag.tsx
PipeLineLems/web/src/components/TdButton/TdButton.module.scss
PipeLineLems/web/src/components/TdButton/TdButton.tsx
PipeLineLems/web/src/components/Text/Text.module.scss
PipeLineLems/web/src/components/Text/Text.tsx
PipeLineLems/web/src/components/Title/Title.module.scss
PipeLineLems/web/src/components/Title/Title.tsx
PipeLineLems/web/src/components/Variable/Variable.module.scss
PipeLineLems/web/src/components/Variable/Variable.tsx
PipeLineLems/web/src/components/WorkSectionDialog/WorkSectionDialog.module.scss
PipeLineLems/web/src/components/WorkSectionDialog/WorkSectionDialog.tsx
PipeLineLems/web/src/components/WorkSectionDialog/hook.ts
PipeLineLems/web/src/components/WorkSectionParams/WorkSectionParams.module.scss
PipeLineLems/web/src/components/WorkSectionParams/WorkSectionParams.tsx
PipeLineLems/web/src/components/WorkSectionParams/api.ts
PipeLineLems/web/src/components/WorkStationDialog/WorkStationDialog.module.scss
PipeLineLems/web/src/components/WorkStationDialog/WorkStationDialog.tsx
PipeLineLems/web/src/components/WorkStationDialog/hook.ts
PipeLineLems/web/src/components/index.d.ts
PipeLineLems/web/src/components/index.ts
PipeLineLems/web/src/components/package.json
PipeLineLems/web/src/components/vue3-context-menu/ContextMenuItem.vue
PipeLineLems/web/src/hooks/Dialog.ts
PipeLineLems/web/src/hooks/File.ts
PipeLineLems/web/src/hooks/drawer.ts
PipeLineLems/web/src/index.d.ts
PipeLineLems/web/src/libs/Base/Base.ts
PipeLineLems/web/src/libs/DownloadFile/DownLoadFile.ts
PipeLineLems/web/src/libs/Permission/Permission.d.ts
PipeLineLems/web/src/libs/Permission/Permission.ts
PipeLineLems/web/src/libs/Provider/Provider.ts
PipeLineLems/web/src/libs/Socket/Socket.ts
PipeLineLems/web/src/libs/Socket/index.ts
PipeLineLems/web/src/libs/Socket/toast.ts
PipeLineLems/web/src/libs/Store/Store.d.ts
PipeLineLems/web/src/libs/Store/Store.ts
PipeLineLems/web/src/libs/Store/globalState.ts
PipeLineLems/web/src/libs/system-enum.ts
PipeLineLems/web/src/main.ts
PipeLineLems/web/src/provider/index.vue
PipeLineLems/web/src/utils/client.ts
PipeLineLems/web/src/utils/columnConfig.ts
PipeLineLems/web/src/utils/index.ts
PipeLineLems/web/src/utils/request.ts
PipeLineLems/web/src/utils/storage.ts
PipeLineLems/web/src/utils/util.ts
PipeLineLems/web/src/widgets/MyPluginName/Views/MyPluginName.tsx
PipeLineLems/web/src/widgets/MyPluginName/index.ts
PipeLineLems/web/vite.build.config.ts
PipeLineLems/web/vite.config.ts
PipeLineLems/web/vite.lib.config.ts
PipeLineLems/web/yarn.lock |