odf_new/server/ZR.Service/Business/OdfMarkerPolesService.cs
zpc 827d7a4367
All checks were successful
continuous-integration/drone/push Build is passing
feat(odf): Add marker pole management and audit logging for v1.2.0
- Add marker pole CRUD functionality with database tables (odf_marker_poles, odf_marker_pole_images)
- Implement marker pole API endpoints and service layer with data isolation by department
- Add UniApp pages for marker pole list, detail, and creation workflows
- Add Vue management backend pages for marker pole and audit log management
- Implement audit logging system via ActionFilter to track all business entity modifications
- Extend search API to include marker poles in results alongside cables and faults
- Add OdfAuditLogsController and service for querying audit trail data
- Update optical box detail page with left-right frame color scheme (green-orange)
- Add cable type page as entry point for marker poles and fault lists
- Create database migration scripts for v1.2.0 schema and permissions
- Add DeptDataScopeHelper for department-based data access control
- Update MCP settings to disable SQL Server connection and fix formatting
- Add marker pole service integration in UniApp with COS image upload support
2026-04-18 22:50:15 +08:00

193 lines
6.3 KiB
C#

using Infrastructure;
using Infrastructure.Attribute;
using ZR.Model;
using ZR.Model.Business;
using ZR.Model.Business.Dto;
using ZR.Model.System;
using ZR.Repository;
using ZR.Service.Business.IBusinessService;
namespace ZR.Service.Business
{
/// <summary>
/// 标石/杆号牌Service业务层处理
/// </summary>
[AppService(ServiceType = typeof(IOdfMarkerPolesService), ServiceLifetime = LifeTime.Transient)]
public class OdfMarkerPolesService : BaseService<OdfMarkerPoles>, IOdfMarkerPolesService
{
/// <summary>
/// 分页查询标石/杆号牌列表,应用部门数据隔离
/// </summary>
public PagedInfo<OdfMarkerPoleListDto> GetList(OdfMarkerPolesQueryDto parm, long deptId)
{
var predicate = Expressionable.Create<OdfMarkerPoles>();
// 部门数据隔离
var visibleDeptIds = DeptDataScopeHelper.GetVisibleDeptIds(Context, deptId);
predicate = predicate.And(it => visibleDeptIds.Contains(it.DeptId));
// 按 CableId 过滤
predicate = predicate.AndIF(parm.CableId != null, it => it.CableId == parm.CableId);
var total = 0;
var list = Queryable()
.Where(predicate.ToExpression())
.OrderByDescending(it => it.RecordTime)
.ToPageList(parm.PageNum, parm.PageSize, ref total);
var result = list.Select(it => new OdfMarkerPoleListDto
{
Id = it.Id,
CableId = it.CableId,
Name = it.Name,
RecordTime = it.RecordTime,
Personnel = it.Personnel,
Latitude = it.Latitude,
Longitude = it.Longitude,
ActualMileage = it.ActualMileage,
DeptName = it.DeptName
}).ToList();
return new PagedInfo<OdfMarkerPoleListDto>
{
Result = result,
TotalNum = total,
PageIndex = parm.PageNum,
PageSize = parm.PageSize
};
}
/// <summary>
/// 查询标石/杆号牌详情,含图片 URL 列表
/// </summary>
public OdfMarkerPoleDetailDto GetDetail(int id)
{
var entity = GetFirst(it => it.Id == id);
if (entity == null)
{
throw new CustomException("标石记录不存在");
}
var images = Context.Queryable<OdfMarkerPoleImages>()
.Where(img => img.MarkerPoleId == id)
.OrderBy(img => img.Id)
.Select(img => img.ImageUrl)
.ToList();
return new OdfMarkerPoleDetailDto
{
Id = entity.Id,
CableId = entity.CableId,
Name = entity.Name,
RecordTime = entity.RecordTime,
Personnel = entity.Personnel,
Latitude = entity.Latitude,
Longitude = entity.Longitude,
ActualMileage = entity.ActualMileage,
DeptId = entity.DeptId,
DeptName = entity.DeptName,
UserId = entity.UserId,
CreatedAt = entity.CreatedAt,
UpdatedAt = entity.UpdatedAt,
ImageUrls = images
};
}
/// <summary>
/// 新增标石/杆号牌,自动填充 DeptId/DeptName
/// </summary>
public int Add(OdfMarkerPoleAddDto dto, long deptId)
{
// 校验 CableId 存在
var cable = Context.Queryable<OdfCables>()
.Where(c => c.Id == dto.CableId)
.First();
if (cable == null)
{
throw new CustomException("光缆不存在");
}
// 校验至少 1 张图片
if (dto.ImageUrls == null || dto.ImageUrls.Length == 0)
{
throw new CustomException("请至少上传一张图片");
}
// 查询部门名称
var dept = Context.Queryable<SysDept>()
.Where(d => d.DeptId == deptId)
.First();
var model = new OdfMarkerPoles
{
CableId = dto.CableId,
Name = dto.Name,
RecordTime = DateTime.Parse(dto.RecordTime),
Personnel = dto.Personnel,
Latitude = dto.Latitude,
Longitude = dto.Longitude,
ActualMileage = dto.ActualMileage,
DeptId = deptId,
DeptName = dept?.DeptName,
UserId = dto.UserId,
CreatedAt = DateTime.Now,
UpdatedAt = DateTime.Now
};
var entity = Insertable(model).ExecuteReturnEntity();
// 插入图片记录
foreach (var imageUrl in dto.ImageUrls)
{
if (string.IsNullOrWhiteSpace(imageUrl)) continue;
var imageRecord = new OdfMarkerPoleImages
{
MarkerPoleId = entity.Id,
ImageUrl = imageUrl,
CreatedAt = DateTime.Now
};
Context.Insertable(imageRecord).ExecuteCommand();
}
return entity.Id;
}
/// <summary>
/// 编辑标石/杆号牌
/// </summary>
public int Update(OdfMarkerPoleEditDto dto)
{
var entity = GetFirst(it => it.Id == dto.Id);
if (entity == null)
{
throw new CustomException("标石记录不存在");
}
entity.Name = dto.Name;
entity.Personnel = dto.Personnel;
entity.Latitude = dto.Latitude;
entity.Longitude = dto.Longitude;
entity.ActualMileage = dto.ActualMileage;
entity.CableId = dto.CableId;
entity.UpdatedAt = DateTime.Now;
return base.Update(entity, true);
}
/// <summary>
/// 删除标石/杆号牌及关联图片
/// </summary>
public int Delete(int id)
{
// 删除关联图片记录
Context.Deleteable<OdfMarkerPoleImages>()
.Where(img => img.MarkerPoleId == id)
.ExecuteCommand();
// 删除标石记录
return base.Delete(id);
}
}
}