using System.Dynamic;
|
using MES.Service.Dto.service;
|
using MES.Service.Modes;
|
using MES.Service.service.QC;
|
using MES.Service.util;
|
using Microsoft.AspNetCore.Mvc;
|
using Newtonsoft.Json.Linq;
|
using System.Web;
|
|
namespace MESApplication.Controllers.QC;
|
|
[Route("api/[controller]")]
|
[ApiController]
|
public class XJController : ControllerBase
|
{
|
[HttpPost("getAll")]
|
public ResponseResult getAll([FromBody] JObject data)
|
{
|
var modify1Flag = Convert.ToInt32(data["modify1Flag"]?.ToString() ?? "0");
|
try
|
{
|
dynamic resultInfos = new ExpandoObject();
|
// var tbBillList =
|
// new XJService().getAll(modify1Flag);
|
// resultInfos.tbBillList = tbBillList;
|
return new ResponseResult
|
{
|
status = 0,
|
message = "OK",
|
data = resultInfos
|
};
|
}
|
catch (Exception ex)
|
{
|
return ResponseResult.ResponseError(ex);
|
}
|
}
|
|
//getMaxReleaseNo
|
[HttpPost("getMaxReleaseNo")]
|
public ResponseResult getMaxReleaseNo()
|
{
|
try
|
{
|
dynamic resultInfos = new ExpandoObject();
|
var tbBillList =
|
new XJService().getMaxReleaseNo();
|
resultInfos.tbBillList = tbBillList;
|
return new ResponseResult
|
{
|
status = 0,
|
message = "OK",
|
data = resultInfos
|
};
|
}
|
catch (Exception ex)
|
{
|
return ResponseResult.ResponseError(ex);
|
}
|
}
|
|
//getLine
|
[HttpPost("getLineAll")]
|
public ResponseResult getLineAll()
|
{
|
try
|
{
|
dynamic resultInfos = new ExpandoObject();
|
var tbBillList =
|
new XJService().getLineAll();
|
resultInfos.tbBillList = tbBillList;
|
return new ResponseResult
|
{
|
status = 0,
|
message = "OK",
|
data = resultInfos
|
};
|
}
|
catch (Exception ex)
|
{
|
return ResponseResult.ResponseError(ex);
|
}
|
}
|
|
|
/// <summary>
|
/// 获取工单
|
/// </summary>
|
[HttpPost("getDaa001")]
|
public ResponseResult getDaa001([FromBody] JObject data)
|
{
|
var daa020 = data["daa020"]?.ToString() ?? "";
|
try
|
{
|
dynamic resultInfos = new ExpandoObject();
|
var tbBillList = new XJService().getDaa001(daa020);
|
resultInfos.tbBillList = tbBillList;
|
return new ResponseResult
|
{
|
status = 0,
|
message = "OK",
|
data = resultInfos
|
};
|
}
|
catch (Exception ex)
|
{
|
return ResponseResult.ResponseError(ex);
|
}
|
}
|
|
/// <summary>
|
/// 获取工单详细信息(包含物料信息)
|
/// </summary>
|
[HttpPost("getWorkOrderWithItem")]
|
public ResponseResult getWorkOrderWithItem([FromBody] JObject data)
|
{
|
var daa020 = data["daa020"]?.ToString() ?? "";
|
try
|
{
|
dynamic resultInfos = new ExpandoObject();
|
var tbBillList = new XJService().getWorkOrderWithItem(daa020);
|
resultInfos.tbBillList = tbBillList;
|
return new ResponseResult
|
{
|
status = 0,
|
message = "OK",
|
data = resultInfos
|
};
|
}
|
catch (Exception ex)
|
{
|
return ResponseResult.ResponseError(ex);
|
}
|
}
|
|
/// <summary>
|
/// 根据产线获取物料编码 lineNo
|
/// </summary>
|
/// <returns></returns>
|
[HttpPost("getBoardItem")]
|
public ResponseResult getBoardItem([FromBody] JObject data)
|
{
|
var lineNo = data["lineNo"]?.ToString() ?? "";
|
try
|
{
|
dynamic resultInfos = new ExpandoObject();
|
var tbBillList =
|
new XJService().getBoardItem(lineNo);
|
// 按 itemNo 去重
|
tbBillList = tbBillList.GroupBy(x => x.ItemNo).Select(g => g.First()).ToList();
|
resultInfos.tbBillList = tbBillList;
|
return new ResponseResult
|
{
|
status = 0,
|
message = "OK",
|
data = resultInfos
|
};
|
}
|
catch (Exception ex)
|
{
|
return ResponseResult.ResponseError(ex);
|
}
|
}
|
|
//getItem
|
[HttpPost("getItem")]
|
public ResponseResult getItem([FromBody] JObject data)
|
{
|
var daa001 = data["daa001"]?.ToString() ?? "";
|
try
|
{
|
dynamic resultInfos = new ExpandoObject();
|
var tbBillList =
|
new XJService().getItem(daa001);
|
resultInfos.tbBillList = tbBillList;
|
return new ResponseResult
|
{
|
status = 0,
|
message = "OK",
|
data = resultInfos
|
};
|
}
|
catch (Exception ex)
|
{
|
return ResponseResult.ResponseError(ex);
|
}
|
}
|
|
//setJYItem
|
[HttpPost("setJYItem")]
|
public ResponseResult setJYItem([FromBody] JObject data)
|
{
|
var itemNo = data["itemNo"]?.ToString() ?? "";
|
try
|
{
|
dynamic resultInfos = new ExpandoObject();
|
var tbBillList =
|
new XJService().setJYItem(itemNo);
|
resultInfos.tbBillList = tbBillList;
|
return new ResponseResult
|
{
|
status = 0,
|
message = "OK",
|
data = resultInfos
|
};
|
}
|
catch (Exception ex)
|
{
|
return ResponseResult.ResponseError(ex);
|
}
|
}
|
|
//save
|
[HttpPost("save")]
|
public ResponseResult save([FromBody] XJDto xjDto)
|
{
|
try
|
{
|
dynamic resultInfos = new ExpandoObject();
|
var result = new XJService().save(xjDto);
|
|
// 返回完整的XJDto对象,包含更新后的items
|
resultInfos.tbBillList = result;
|
resultInfos.xjDto = xjDto; // 包含完整的检验项目信息
|
|
return new ResponseResult
|
{
|
status = 0,
|
message = "OK",
|
data = resultInfos
|
};
|
}
|
catch (Exception ex)
|
{
|
return ResponseResult.ResponseError(ex);
|
}
|
}
|
|
[HttpPost("saveItem")]
|
public ResponseResult saveItem([FromBody] XJDto xjDto)
|
{
|
try
|
{
|
dynamic resultInfos = new ExpandoObject();
|
var tbBillList =
|
new XJService().saveItem(xjDto);
|
resultInfos.tbBillList = tbBillList;
|
return new ResponseResult
|
{
|
status = 0,
|
message = "OK",
|
data = resultInfos
|
};
|
}
|
catch (Exception ex)
|
{
|
return ResponseResult.ResponseError(ex);
|
}
|
}
|
|
//getPage
|
[HttpPost("getPage")]
|
public ResponseResult getPage([FromBody] XJPageResult queryObj)
|
{
|
try
|
{
|
dynamic resultInfos = new ExpandoObject();
|
var (item, totalCount) = new XJService().getPage(queryObj);
|
resultInfos.tbBillList = item;
|
return new ResponseResult
|
{
|
status = 0,
|
message = "OK",
|
data = resultInfos,
|
TotalCount = totalCount
|
};
|
}
|
catch (Exception ex)
|
{
|
return ResponseResult.ResponseError(ex);
|
}
|
}
|
|
//getJYItem
|
[HttpPost("getJYItem")]
|
public ResponseResult getJYItem([FromBody] JObject data)
|
{
|
var pid = data["pid"]?.ToString();
|
var id = data["id"]?.ToString();
|
|
try
|
{
|
dynamic resultInfos = new ExpandoObject();
|
var tbBillList =
|
new XJService().getJYItem(Convert.ToDecimal(pid),
|
Convert.ToDecimal(id));
|
resultInfos.tbBillList = tbBillList;
|
return new ResponseResult
|
{
|
status = 0,
|
message = "OK",
|
data = resultInfos
|
};
|
}
|
catch (Exception ex)
|
{
|
return ResponseResult.ResponseError(ex);
|
}
|
}
|
|
//getXjDetail02ById
|
[HttpPost("getXjDetail02ById")]
|
public ResponseResult getXjDetail02ById([FromBody] JObject data)
|
{
|
var id = data["id"]?.ToString();
|
|
try
|
{
|
dynamic resultInfos = new ExpandoObject();
|
var tbBillList =
|
new XJService().getXjDetail02ById(Convert.ToDecimal(id));
|
resultInfos.tbBillList = tbBillList;
|
return new ResponseResult
|
{
|
status = 0,
|
message = "OK",
|
data = resultInfos
|
};
|
}
|
catch (Exception ex)
|
{
|
return ResponseResult.ResponseError(ex);
|
}
|
}
|
|
[HttpPost("SetQSItemDetail")]
|
public ResponseResult SetQSItemDetail([FromBody] QsQaItemXj02 detail)
|
{
|
try
|
{
|
dynamic resultInfos = new ExpandoObject();
|
var tbBillList = new XJService();
|
var detail021 = tbBillList.SetQSItemDetail(detail);
|
resultInfos.tbBillList = detail021;
|
return new ResponseResult
|
{
|
status = 0,
|
message = "OK",
|
data = resultInfos
|
};
|
}
|
catch (Exception ex)
|
{
|
return ResponseResult.ResponseError(ex);
|
}
|
}
|
|
[HttpPost("UpdateQSItemDetail")]
|
public ResponseResult UpdateQSItemDetail(
|
[FromBody] QsQaItemXj02 detail)
|
{
|
try
|
{
|
dynamic resultInfos = new ExpandoObject();
|
var tbBillList = new XJService();
|
var detail021 = tbBillList.UpdateQSItemDetail(detail);
|
resultInfos.tbBillList = detail021;
|
return new ResponseResult
|
{
|
status = 0,
|
message = "OK",
|
data = resultInfos
|
};
|
}
|
catch (Exception ex)
|
{
|
return ResponseResult.ResponseError(ex);
|
}
|
}
|
|
//removeXJ
|
[HttpPost("removeXJ")]
|
public ResponseResult removeXJ([FromBody] JObject data)
|
{
|
var id = data["id"]?.ToString();
|
try
|
{
|
dynamic resultInfos = new ExpandoObject();
|
var tbBillList =
|
new XJService().removeXJ(Convert.ToDecimal(id));
|
resultInfos.tbBillList = tbBillList;
|
return new ResponseResult
|
{
|
status = 0,
|
message = "OK",
|
data = resultInfos
|
};
|
}
|
catch (Exception ex)
|
{
|
return ResponseResult.ResponseError(ex);
|
}
|
}
|
|
|
//saveRemarksGid
|
[HttpPost("saveRemarksGid")]
|
public ResponseResult saveRemarksGid([FromBody] XJDto rkjDto)
|
{
|
try
|
{
|
dynamic resultInfos = new ExpandoObject();
|
var tbBillList =
|
new XJService().saveRemarksGid(rkjDto);
|
resultInfos.tbBillList = tbBillList;
|
return new ResponseResult
|
{
|
status = 0,
|
message = "OK",
|
data = resultInfos
|
};
|
}
|
catch (Exception ex)
|
{
|
return ResponseResult.ResponseError(ex);
|
}
|
}
|
|
//saveRemarksPid
|
[HttpPost("saveRemarksPid")]
|
public ResponseResult saveRemarksPid([FromBody] XJDto rkjDto)
|
{
|
try
|
{
|
dynamic resultInfos = new ExpandoObject();
|
var tbBillList =
|
new XJService().saveRemarksPid(rkjDto);
|
resultInfos.tbBillList = tbBillList;
|
return new ResponseResult
|
{
|
status = 0,
|
message = "OK",
|
data = resultInfos
|
};
|
}
|
catch (Exception ex)
|
{
|
return ResponseResult.ResponseError(ex);
|
}
|
}
|
|
//saveRemarksById
|
[HttpPost("saveRemarksById")]
|
public ResponseResult saveRemarksById([FromBody] XJDto rkjDto)
|
{
|
try
|
{
|
dynamic resultInfos = new ExpandoObject();
|
var tbBillList =
|
new XJService().saveRemarksById(rkjDto);
|
resultInfos.tbBillList = tbBillList;
|
return new ResponseResult
|
{
|
status = 0,
|
message = "OK",
|
data = resultInfos
|
};
|
}
|
catch (Exception ex)
|
{
|
return ResponseResult.ResponseError(ex);
|
}
|
}
|
|
//刷新检验项目
|
[HttpPost("GenUpdate")]
|
public ResponseResult GenUpdate([FromBody] JObject data)
|
{
|
try
|
{
|
decimal? id = data["id"]?.ToObject<decimal>();
|
string? no = data["no"]?.ToString();
|
string? user = data["user"]?.ToString();
|
|
var (result, message) = new XJService().GenUpdate(id, no, user);
|
|
dynamic resultInfos = new ExpandoObject();
|
resultInfos.result = result;
|
resultInfos.message = message;
|
|
return new ResponseResult
|
{
|
status = 0,
|
message = "OK",
|
data = resultInfos
|
};
|
}
|
catch (Exception ex)
|
{
|
return ResponseResult.ResponseError(ex);
|
}
|
}
|
|
//提交检验
|
[HttpPost("SjSubmit")]
|
public ResponseResult SjSubmit([FromBody] SJDto sjDto)
|
{
|
try
|
{
|
dynamic resultInfos = new ExpandoObject();
|
var tbBillList = new XJService().SjSubmit(sjDto);
|
resultInfos.tbBillList = tbBillList;
|
return new ResponseResult
|
{
|
status = 0,
|
message = "OK",
|
data = resultInfos
|
};
|
}
|
catch (Exception ex)
|
{
|
return ResponseResult.ResponseError(ex);
|
}
|
}
|
|
/// <summary>
|
/// 获取有线体的部门列表
|
/// </summary>
|
[HttpPost("getDepartmentsWithLines")]
|
public ResponseResult GetDepartmentsWithLines()
|
{
|
try
|
{
|
dynamic resultInfos = new ExpandoObject();
|
var tbBillList = new XJService().GetDepartmentsWithLines();
|
resultInfos.tbBillList = tbBillList;
|
return new ResponseResult
|
{
|
status = 0,
|
message = "OK",
|
data = resultInfos
|
};
|
}
|
catch (Exception ex)
|
{
|
return ResponseResult.ResponseError(ex);
|
}
|
}
|
|
/// <summary>
|
/// 保存部门选择
|
/// </summary>
|
[HttpPost("saveDepartmentSelection")]
|
public ResponseResult SaveDepartmentSelection([FromBody] JObject data)
|
{
|
try
|
{
|
var id = Convert.ToDecimal(data["id"]);
|
var departmentId = data["departmentId"]?.ToString() ?? "";
|
var departmentName = data["departmentName"]?.ToString() ?? "";
|
|
dynamic resultInfos = new ExpandoObject();
|
var result = new XJService().SaveDepartmentSelection(id, departmentId, departmentName);
|
resultInfos.tbBillList = result;
|
return new ResponseResult
|
{
|
status = 0,
|
message = "OK",
|
data = resultInfos
|
};
|
}
|
catch (Exception ex)
|
{
|
return ResponseResult.ResponseError(ex);
|
}
|
}
|
|
/// <summary>
|
/// 根据部门ID获取该部门下的线体列表
|
/// </summary>
|
[HttpPost("getLinesByDepartment")]
|
public ResponseResult GetLinesByDepartment([FromBody] JObject data)
|
{
|
try
|
{
|
var departmentId = data["departmentId"]?.ToString() ?? "";
|
|
dynamic resultInfos = new ExpandoObject();
|
var tbBillList = new XJService().GetLinesByDepartment(departmentId);
|
resultInfos.tbBillList = tbBillList;
|
return new ResponseResult
|
{
|
status = 0,
|
message = "OK",
|
data = resultInfos
|
};
|
}
|
catch (Exception ex)
|
{
|
return ResponseResult.ResponseError(ex);
|
}
|
}
|
|
/// <summary>
|
/// 获取附件信息
|
/// </summary>
|
/// <param name="data">包含itemNo的JSON对象</param>
|
/// <returns>附件列表</returns>
|
[HttpPost("getAttachments")]
|
public ResponseResult GetAttachments([FromBody] JObject data)
|
{
|
var itemNo = data["itemNo"]?.ToString();
|
var projName = data["projName"]?.ToString();
|
var fromPage = data["fromPage"]?.ToString(); // 新增参数
|
|
// 调试日志
|
Console.WriteLine($"XJController.GetAttachments 接收参数: itemNo='{itemNo}', projName='{projName}', fromPage='{fromPage}'");
|
|
// 条件过滤逻辑:根据fromPage决定是否过滤
|
string filterProjName = null;
|
if (fromPage == "Detail" && !string.IsNullOrEmpty(projName))
|
{
|
filterProjName = projName; // Detail页面需要过滤
|
}
|
// Add页面不传递filterProjName,显示所有附件
|
|
try
|
{
|
dynamic resultInfos = new System.Dynamic.ExpandoObject();
|
var tbBillList = new XJService().GetAttachments(itemNo, filterProjName);
|
if (tbBillList == null || tbBillList.Count == 0)
|
{
|
return new ResponseResult
|
{
|
status = 1,
|
message = "该检验单未上传附件信息!",
|
data = null
|
};
|
}
|
resultInfos.tbBillList = tbBillList;
|
return new ResponseResult
|
{
|
status = 0,
|
message = "OK",
|
data = resultInfos
|
};
|
}
|
catch (Exception ex)
|
{
|
return ResponseResult.ResponseError(ex);
|
}
|
}
|
|
/// <summary>
|
/// 预览FTP文件
|
/// </summary>
|
/// <param name="itemNo">物料编码</param>
|
/// <param name="fileName">文件名</param>
|
/// <param name="ftpServer">FTP服务器地址</param>
|
/// <param name="projName">项目名称(可选)</param>
|
/// <returns>文件内容</returns>
|
[HttpGet("PreviewFtpFile")]
|
public IActionResult PreviewFtpFile([FromQuery] string itemNo, [FromQuery] string fileName, [FromQuery] string ftpServer, [FromQuery] string projName = null)
|
{
|
try
|
{
|
// 添加CORS响应头
|
Response.Headers.Add("Access-Control-Allow-Origin", "*");
|
Response.Headers.Add("Access-Control-Allow-Methods", "GET, OPTIONS");
|
Response.Headers.Add("Access-Control-Allow-Headers", "Content-Type");
|
Response.Headers.Add("Access-Control-Expose-Headers", "Content-Type, Content-Length");
|
|
var service = new XJService();
|
var fileBytes = service.GetFtpFile(itemNo, fileName, ftpServer, projName);
|
|
if (fileBytes == null || fileBytes.Length == 0)
|
{
|
return NotFound("文件在FTP服务器上不存在");
|
}
|
|
var contentType = service.GetContentType(fileName);
|
fileName = fileName?.Trim().Replace("\r", "").Replace("\n", "");
|
|
return File(fileBytes, contentType);
|
}
|
catch (Exception ex)
|
{
|
return StatusCode(500, $"预览文件失败:{ex.Message}");
|
}
|
}
|
|
/// <summary>
|
/// 下载FTP文件
|
/// </summary>
|
/// <param name="itemNo">物料编码</param>
|
/// <param name="fileName">文件名</param>
|
/// <param name="ftpServer">FTP服务器地址</param>
|
/// <param name="projName">项目名称(可选)</param>
|
/// <returns>文件下载</returns>
|
[HttpGet("DownloadFtpFile")]
|
public IActionResult DownloadFtpFile([FromQuery] string itemNo, [FromQuery] string fileName, [FromQuery] string ftpServer, [FromQuery] string projName = null)
|
{
|
try
|
{
|
// 添加CORS响应头 - 关键配置用于解决跨域问题
|
Response.Headers.Add("Access-Control-Allow-Origin", "*");
|
Response.Headers.Add("Access-Control-Allow-Methods", "GET, OPTIONS");
|
Response.Headers.Add("Access-Control-Allow-Headers", "Content-Type, Authorization");
|
Response.Headers.Add("Access-Control-Expose-Headers", "Content-Disposition, Content-Length, Content-Type");
|
|
var service = new XJService();
|
var fileBytes = service.GetFtpFile(itemNo, fileName, ftpServer, projName);
|
|
if (fileBytes == null || fileBytes.Length == 0)
|
{
|
return NotFound("文件在FTP服务器上不存在");
|
}
|
|
var contentType = service.GetContentType(fileName);
|
fileName = fileName?.Trim().Replace("\r", "").Replace("\n", "");
|
|
// 设置正确的Content-Disposition响应头以支持文件下载
|
var result = File(fileBytes, "application/octet-stream", fileName);
|
|
// 确保Content-Disposition头正确设置,支持中文文件名
|
if (!string.IsNullOrEmpty(fileName))
|
{
|
var encodedFileName = System.Web.HttpUtility.UrlEncode(fileName, System.Text.Encoding.UTF8);
|
Response.Headers.Add("Content-Disposition", $"attachment; filename*=UTF-8''{encodedFileName}");
|
}
|
|
return result;
|
}
|
catch (Exception ex)
|
{
|
return StatusCode(500, $"下载文件失败:{ex.Message}");
|
}
|
}
|
|
[HttpOptions("PreviewFtpFile")]
|
[HttpOptions("DownloadFtpFile")]
|
public IActionResult HandleOptions()
|
{
|
Response.Headers.Add("Access-Control-Allow-Origin", "*");
|
Response.Headers.Add("Access-Control-Allow-Methods", "GET, OPTIONS");
|
Response.Headers.Add("Access-Control-Allow-Headers", "Content-Type, Authorization");
|
Response.Headers.Add("Access-Control-Max-Age", "86400");
|
return Ok();
|
}
|
|
/// <summary>
|
/// 上传图片到检验项目的PICTURE字段
|
/// </summary>
|
/// <param name="file">上传的图片文件</param>
|
/// <param name="id">检验项目ID</param>
|
/// <param name="gid">检验单ID</param>
|
/// <param name="billNo">工单号</param>
|
/// <param name="createBy">创建人</param>
|
/// <returns>上传结果</returns>
|
[HttpPost("UploadImageToPicture")]
|
public ResponseResult UploadImageToPicture(IFormFile file, [FromForm] string id, [FromForm] string gid, [FromForm] string billNo, [FromForm] string createBy)
|
{
|
try
|
{
|
// 参数验证
|
if (file == null || file.Length == 0)
|
{
|
return new ResponseResult
|
{
|
status = 1,
|
message = "请选择要上传的图片文件",
|
data = null
|
};
|
}
|
|
if (string.IsNullOrEmpty(id))
|
{
|
return new ResponseResult
|
{
|
status = 1,
|
message = "检验项目ID不能为空",
|
data = null
|
};
|
}
|
|
if (string.IsNullOrEmpty(createBy))
|
{
|
return new ResponseResult
|
{
|
status = 1,
|
message = "创建人不能为空",
|
data = null
|
};
|
}
|
|
// 读取文件字节数组
|
byte[] imageBytes;
|
using (var memoryStream = new MemoryStream())
|
{
|
file.CopyTo(memoryStream);
|
imageBytes = memoryStream.ToArray();
|
}
|
|
// 调用服务方法保存图片
|
var service = new XJService();
|
var (status, message) = service.UploadImageToPicture(Convert.ToDecimal(id), imageBytes, file.FileName, createBy);
|
|
return new ResponseResult
|
{
|
status = status,
|
message = message,
|
data = null
|
};
|
}
|
catch (Exception ex)
|
{
|
return new ResponseResult
|
{
|
status = 1,
|
message = $"上传图片失败:{ex.Message}",
|
data = null
|
};
|
}
|
}
|
|
/// <summary>
|
/// 删除检验项目的图片
|
/// </summary>
|
/// <param name="data">包含检验项目ID的JSON对象</param>
|
/// <returns>删除结果</returns>
|
[HttpPost("DeleteImageFromPicture")]
|
public ResponseResult DeleteImageFromPicture([FromBody] JObject data)
|
{
|
try
|
{
|
var id = data["id"]?.ToString();
|
|
if (string.IsNullOrEmpty(id))
|
{
|
return new ResponseResult
|
{
|
status = 1,
|
message = "检验项目ID不能为空",
|
data = null
|
};
|
}
|
|
// 调用服务方法删除图片
|
var service = new XJService();
|
var (status, message) = service.DeleteImageFromPicture(Convert.ToDecimal(id));
|
|
return new ResponseResult
|
{
|
status = status,
|
message = message,
|
data = null
|
};
|
}
|
catch (Exception ex)
|
{
|
return new ResponseResult
|
{
|
status = 1,
|
message = $"删除图片失败:{ex.Message}",
|
data = null
|
};
|
}
|
}
|
|
|
}
|