feat(odf-uniapp): Add mileage correction editing and export enhancements
Some checks are pending
continuous-integration/drone/push Build is running
Some checks are pending
continuous-integration/drone/push Build is running
- Add inline editing UI for mileage correction field in fault detail page - Implement save/cancel buttons for mileage correction updates - Add updateMileageCorrection API endpoint and service method - Update App.vue global styles with page background color - Enhance pages.json with backgroundColorTop and backgroundColorBottom - Add MileageCorrectionDto for request validation - Implement batch fault times retrieval for export functionality - Add fault frequency time concatenation in export data - Improve export data structure with complete fault history information
This commit is contained in:
parent
1bd5bc74ee
commit
837ff4d4cc
|
|
@ -14,4 +14,7 @@
|
|||
|
||||
<style>
|
||||
/*每个页面公共css */
|
||||
page {
|
||||
background-color: #F5F5F5;
|
||||
}
|
||||
</style>
|
||||
|
|
|
|||
|
|
@ -140,6 +140,8 @@
|
|||
"navigationBarTextStyle": "white",
|
||||
"navigationBarTitleText": "绥时录",
|
||||
"navigationBarBackgroundColor": "#1A73EC",
|
||||
"backgroundColor": "#F5F5F5"
|
||||
"backgroundColor": "#F5F5F5",
|
||||
"backgroundColorTop": "#F5F5F5",
|
||||
"backgroundColorBottom": "#F5F5F5"
|
||||
}
|
||||
}
|
||||
|
|
@ -73,9 +73,29 @@
|
|||
<text class="info-label">表显故障里程</text>
|
||||
<text class="info-value">{{ displayMileage }}</text>
|
||||
</view>
|
||||
<view class="info-row" v-if="detail.mileageCorrection">
|
||||
<view class="info-row">
|
||||
<text class="info-label">表显里程矫正</text>
|
||||
<text class="info-value">{{ detail.mileageCorrection }}</text>
|
||||
<view class="info-value correction-row" v-if="editingCorrection">
|
||||
<input
|
||||
class="correction-input"
|
||||
v-model="correctionInput"
|
||||
type="text"
|
||||
placeholder="请输入"
|
||||
placeholder-class="input-placeholder"
|
||||
/>
|
||||
<view class="correction-btn save-btn" @click="saveCorrection">
|
||||
<text class="correction-btn-text">保存</text>
|
||||
</view>
|
||||
<view class="correction-btn cancel-btn" @click="cancelEditCorrection">
|
||||
<text class="correction-btn-text cancel-text">取消</text>
|
||||
</view>
|
||||
</view>
|
||||
<view class="info-value correction-row" v-else>
|
||||
<text>{{ detail.mileageCorrection || '未填写' }}</text>
|
||||
<view class="correction-btn edit-btn" @click="startEditCorrection">
|
||||
<text class="correction-btn-text">修改</text>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
<view class="info-row">
|
||||
<text class="info-label">所属光缆</text>
|
||||
|
|
@ -104,7 +124,7 @@
|
|||
<script setup>
|
||||
import { ref, reactive, computed } from 'vue'
|
||||
import { onLoad } from '@dcloudio/uni-app'
|
||||
import { getFaultDetail, incrementFaultCount } from '@/services/trunk'
|
||||
import { getFaultDetail, incrementFaultCount, updateMileageCorrection } from '@/services/trunk'
|
||||
import { BASE_URL } from '@/services/api'
|
||||
import { openNavigation } from '@/utils/navigation'
|
||||
|
||||
|
|
@ -128,6 +148,9 @@ const detail = reactive({
|
|||
faultTimes: []
|
||||
})
|
||||
const incrementing = ref(false)
|
||||
const editingCorrection = ref(false)
|
||||
const correctionInput = ref('')
|
||||
const savingCorrection = ref(false)
|
||||
|
||||
const allFaultTimes = computed(() => {
|
||||
const times = []
|
||||
|
|
@ -228,6 +251,34 @@ async function handleIncrement() {
|
|||
}
|
||||
}
|
||||
|
||||
function startEditCorrection() {
|
||||
correctionInput.value = detail.mileageCorrection || ''
|
||||
editingCorrection.value = true
|
||||
}
|
||||
|
||||
function cancelEditCorrection() {
|
||||
editingCorrection.value = false
|
||||
}
|
||||
|
||||
async function saveCorrection() {
|
||||
if (savingCorrection.value) return
|
||||
savingCorrection.value = true
|
||||
try {
|
||||
const res = await updateMileageCorrection(faultId.value, correctionInput.value)
|
||||
if (res.code === 200) {
|
||||
detail.mileageCorrection = correctionInput.value
|
||||
editingCorrection.value = false
|
||||
uni.showToast({ title: '保存成功', icon: 'success' })
|
||||
} else {
|
||||
uni.showToast({ title: res.msg || '保存失败', icon: 'none' })
|
||||
}
|
||||
} catch (err) {
|
||||
uni.showToast({ title: '网络异常', icon: 'none' })
|
||||
} finally {
|
||||
savingCorrection.value = false
|
||||
}
|
||||
}
|
||||
|
||||
function handleNavigate() {
|
||||
openNavigation(detail.latitude, detail.longitude, detail.location || '故障地点')
|
||||
}
|
||||
|
|
@ -407,6 +458,55 @@ onLoad((options) => {
|
|||
font-size: 24rpx;
|
||||
}
|
||||
|
||||
.correction-row {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 12rpx;
|
||||
}
|
||||
|
||||
.correction-input {
|
||||
flex: 1;
|
||||
height: 56rpx;
|
||||
padding: 0 16rpx;
|
||||
background: #F5F5F5;
|
||||
border-radius: 8rpx;
|
||||
border: 1rpx solid #E8E8E8;
|
||||
font-size: 26rpx;
|
||||
color: #333;
|
||||
}
|
||||
|
||||
.input-placeholder {
|
||||
color: #999;
|
||||
}
|
||||
|
||||
.correction-btn {
|
||||
border-radius: 8rpx;
|
||||
padding: 6rpx 20rpx;
|
||||
flex-shrink: 0;
|
||||
}
|
||||
|
||||
.edit-btn {
|
||||
background: #1A73EC;
|
||||
}
|
||||
|
||||
.save-btn {
|
||||
background: #1A73EC;
|
||||
}
|
||||
|
||||
.cancel-btn {
|
||||
background: #fff;
|
||||
border: 1rpx solid #ccc;
|
||||
}
|
||||
|
||||
.correction-btn-text {
|
||||
color: #fff;
|
||||
font-size: 24rpx;
|
||||
}
|
||||
|
||||
.cancel-text {
|
||||
color: #666;
|
||||
}
|
||||
|
||||
.bottom-bar {
|
||||
position: fixed;
|
||||
bottom: 0;
|
||||
|
|
|
|||
|
|
@ -45,5 +45,8 @@ export function addFault(formData) {
|
|||
export const incrementFaultCount = (id) =>
|
||||
post(`/business/OdfCableFaults/incrementFaultCount/${id}`)
|
||||
|
||||
export const updateMileageCorrection = (id, mileageCorrection) =>
|
||||
post(`/business/OdfCableFaults/updateMileageCorrection/${id}`, { mileageCorrection })
|
||||
|
||||
export const searchCablesAndFaults = (deptId, keyword) =>
|
||||
get('/business/OdfCables/search', { deptId, keyword })
|
||||
|
|
|
|||
|
|
@ -74,6 +74,18 @@ namespace ZR.Admin.WebApi.Controllers.Business
|
|||
return SUCCESS(response);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 更新表显里程矫正
|
||||
/// </summary>
|
||||
[HttpPost("updateMileageCorrection/{id}")]
|
||||
[ActionPermissionFilter(Permission = "odfcablefaults:list")]
|
||||
[Log(Title = "干线故障", BusinessType = BusinessType.UPDATE)]
|
||||
public IActionResult UpdateMileageCorrection(int id, [FromBody] MileageCorrectionDto dto)
|
||||
{
|
||||
var response = _OdfCableFaultsService.UpdateMileageCorrection(id, dto.MileageCorrection);
|
||||
return ToResponse(response);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 删除故障并级联删除图片
|
||||
/// </summary>
|
||||
|
|
@ -102,6 +114,10 @@ namespace ZR.Admin.WebApi.Controllers.Business
|
|||
return ToResponse(ResultCode.FAIL, "没有要导出的数据");
|
||||
}
|
||||
|
||||
// 收集所有故障ID,批量查询频次时间记录
|
||||
var faultIds = list.Result.Select(item => (int)((dynamic)item).Id).ToList();
|
||||
var allFaultTimes = _OdfCableFaultsService.GetFaultTimesByFaultIds(faultIds);
|
||||
|
||||
// 将英文属性名转换为中文列头
|
||||
var exportList = new List<Dictionary<string, object>>();
|
||||
foreach (var item in list.Result)
|
||||
|
|
@ -109,14 +125,29 @@ namespace ZR.Admin.WebApi.Controllers.Business
|
|||
var obj = (object)item;
|
||||
var props = obj.GetType().GetProperties();
|
||||
var dict = props.ToDictionary(p => p.Name, p => p.GetValue(obj));
|
||||
var faultId = (int)dict.GetValueOrDefault("Id");
|
||||
var faultCount = dict.ContainsKey("FaultCount") ? dict["FaultCount"] : 1;
|
||||
|
||||
// 拼接所有故障时间(首次 + 增加的频次时间)
|
||||
var times = new List<string>();
|
||||
var firstTime = dict.GetValueOrDefault("FaultTime");
|
||||
if (firstTime != null) times.Add(firstTime.ToString());
|
||||
if (allFaultTimes.ContainsKey(faultId))
|
||||
{
|
||||
times.AddRange(allFaultTimes[faultId].Select(t => t.ToString()));
|
||||
}
|
||||
times.Sort();
|
||||
|
||||
var row = new Dictionary<string, object>
|
||||
{
|
||||
["编号"] = dict.GetValueOrDefault("Id"),
|
||||
["光缆编号"] = dict.GetValueOrDefault("CableId"),
|
||||
["故障时间"] = dict.GetValueOrDefault("FaultTime"),
|
||||
["故障时间"] = string.Join("\n", times),
|
||||
["故障发生频次"] = faultCount,
|
||||
["人员"] = dict.GetValueOrDefault("Personnel"),
|
||||
["故障原因"] = dict.GetValueOrDefault("FaultReason"),
|
||||
["表显故障里程"] = dict.GetValueOrDefault("Mileage"),
|
||||
["表显里程矫正"] = dict.GetValueOrDefault("MileageCorrection"),
|
||||
["地点"] = dict.GetValueOrDefault("Location"),
|
||||
["纬度"] = dict.GetValueOrDefault("Latitude"),
|
||||
["经度"] = dict.GetValueOrDefault("Longitude"),
|
||||
|
|
|
|||
|
|
@ -76,6 +76,9 @@ namespace ZR.Model.Business.Dto
|
|||
[ExcelColumnName("表显故障里程")]
|
||||
public string Mileage { get; set; }
|
||||
|
||||
[ExcelColumnName("表显里程矫正")]
|
||||
public string MileageCorrection { get; set; }
|
||||
|
||||
[ExcelColumnName("地点")]
|
||||
public string Location { get; set; }
|
||||
|
||||
|
|
@ -93,5 +96,16 @@ namespace ZR.Model.Business.Dto
|
|||
|
||||
[ExcelColumnName("所属光缆")]
|
||||
public string CableName { get; set; }
|
||||
|
||||
[ExcelColumnName("故障发生频次")]
|
||||
public int? FaultCount { get; set; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 更新表显里程矫正
|
||||
/// </summary>
|
||||
public class MileageCorrectionDto
|
||||
{
|
||||
public string MileageCorrection { get; set; }
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -43,5 +43,15 @@ namespace ZR.Service.Business.IBusinessService
|
|||
/// 增加故障频次
|
||||
/// </summary>
|
||||
object IncrementFaultCount(int id);
|
||||
|
||||
/// <summary>
|
||||
/// 批量查询故障频次时间记录
|
||||
/// </summary>
|
||||
Dictionary<int, List<DateTime>> GetFaultTimesByFaultIds(List<int> faultIds);
|
||||
|
||||
/// <summary>
|
||||
/// 更新表显里程矫正
|
||||
/// </summary>
|
||||
int UpdateMileageCorrection(int id, string mileageCorrection);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -42,6 +42,7 @@ namespace ZR.Service.Business
|
|||
f.Longitude,
|
||||
f.Remark,
|
||||
f.CreatedAt,
|
||||
f.FaultCount,
|
||||
CableName = c.CableName
|
||||
})
|
||||
.MergeTable()
|
||||
|
|
@ -269,6 +270,24 @@ namespace ZR.Service.Business
|
|||
};
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 批量查询故障频次时间记录,按故障ID分组
|
||||
/// </summary>
|
||||
public Dictionary<int, List<DateTime>> GetFaultTimesByFaultIds(List<int> faultIds)
|
||||
{
|
||||
if (faultIds == null || faultIds.Count == 0)
|
||||
return new Dictionary<int, List<DateTime>>();
|
||||
|
||||
var records = Context.Queryable<OdfCableFaultTimes>()
|
||||
.Where(t => faultIds.Contains(t.FaultId))
|
||||
.OrderBy(t => t.FaultTime)
|
||||
.ToList();
|
||||
|
||||
return records
|
||||
.GroupBy(t => t.FaultId)
|
||||
.ToDictionary(g => g.Key, g => g.Select(t => t.FaultTime).ToList());
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 查询表达式
|
||||
/// </summary>
|
||||
|
|
@ -327,10 +346,12 @@ namespace ZR.Service.Business
|
|||
Personnel = item.Personnel,
|
||||
FaultReason = item.FaultReason,
|
||||
Mileage = item.Mileage,
|
||||
MileageCorrection = item.MileageCorrection,
|
||||
Location = item.Location,
|
||||
Latitude = item.Latitude ?? 0,
|
||||
Longitude = item.Longitude ?? 0,
|
||||
Remark = item.Remark,
|
||||
FaultCount = item.FaultCount ?? 1,
|
||||
CreatedAt = DateTime.Now,
|
||||
UpdatedAt = DateTime.Now
|
||||
};
|
||||
|
|
@ -348,5 +369,21 @@ namespace ZR.Service.Business
|
|||
string errorMsg = errorMsgs.Count > 0 ? string.Join(";", errorMsgs.Take(10)) : "";
|
||||
return (successCount, errorCount, errorMsg);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 更新表显里程矫正
|
||||
/// </summary>
|
||||
public int UpdateMileageCorrection(int id, string mileageCorrection)
|
||||
{
|
||||
var fault = GetFirst(f => f.Id == id);
|
||||
if (fault == null)
|
||||
{
|
||||
throw new CustomException("故障记录不存在");
|
||||
}
|
||||
|
||||
fault.MileageCorrection = mileageCorrection;
|
||||
fault.UpdatedAt = DateTime.Now;
|
||||
return Update(fault, true);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -39,3 +39,14 @@ export function delOdfCableFaults(pid) {
|
|||
export async function exportOdfCableFaults(query) {
|
||||
await downFile('business/OdfCableFaults/export', { ...query })
|
||||
}
|
||||
|
||||
/**
|
||||
* 更新表显里程矫正
|
||||
*/
|
||||
export function updateMileageCorrection(id, mileageCorrection) {
|
||||
return request({
|
||||
url: 'business/OdfCableFaults/updateMileageCorrection/' + id,
|
||||
method: 'POST',
|
||||
data: { mileageCorrection }
|
||||
})
|
||||
}
|
||||
|
|
|
|||
|
|
@ -83,7 +83,9 @@
|
|||
<el-table-column prop="personnel" label="人员" align="center" :show-overflow-tooltip="true" v-if="columns.showColumn('personnel')" />
|
||||
<el-table-column prop="faultReason" label="故障原因" align="center" :show-overflow-tooltip="true" v-if="columns.showColumn('faultReason')" />
|
||||
<el-table-column prop="mileage" label="表显故障里程" align="center" :show-overflow-tooltip="true" v-if="columns.showColumn('mileage')" />
|
||||
<el-table-column prop="mileageCorrection" label="表显里程矫正" align="center" :show-overflow-tooltip="true" v-if="columns.showColumn('mileageCorrection')" />
|
||||
<el-table-column prop="cableName" label="所属光缆" align="center" :show-overflow-tooltip="true" v-if="columns.showColumn('cableName')" />
|
||||
<el-table-column prop="faultCount" label="故障频次" align="center" v-if="columns.showColumn('faultCount')" />
|
||||
<el-table-column label="地点" align="center" :show-overflow-tooltip="true" v-if="columns.showColumn('location')">
|
||||
<template #default="scope">
|
||||
<span v-if="scope.row.latitude || scope.row.longitude">{{ scope.row.longitude }}, {{ scope.row.latitude }}</span>
|
||||
|
|
@ -109,9 +111,29 @@
|
|||
<el-dialog v-model="detailVisible" title="故障详情" width="700px" destroy-on-close>
|
||||
<el-descriptions :column="2" border v-if="detailData">
|
||||
<el-descriptions-item label="Id">{{ detailData.id }}</el-descriptions-item>
|
||||
<el-descriptions-item label="故障时间">{{ detailData.faultTime }}</el-descriptions-item>
|
||||
<el-descriptions-item label="故障发生频次">{{ detailData.faultCount || 1 }}</el-descriptions-item>
|
||||
<el-descriptions-item label="故障时间" :span="2">
|
||||
<div v-if="allDetailFaultTimes.length > 0">
|
||||
<div v-for="(t, i) in allDetailFaultTimes" :key="i">{{ t }}</div>
|
||||
</div>
|
||||
<span v-else>{{ detailData.faultTime }}</span>
|
||||
</el-descriptions-item>
|
||||
<el-descriptions-item label="人员">{{ detailData.personnel }}</el-descriptions-item>
|
||||
<el-descriptions-item label="表显故障里程">{{ detailData.mileage }}</el-descriptions-item>
|
||||
<el-descriptions-item label="表显故障里程">{{ detailDisplayMileage }}</el-descriptions-item>
|
||||
<el-descriptions-item label="表显里程矫正">
|
||||
<div style="display: flex; align-items: center; gap: 8px;">
|
||||
<el-input
|
||||
v-if="editingDetailCorrection"
|
||||
v-model="detailCorrectionInput"
|
||||
size="small"
|
||||
style="width: 150px;"
|
||||
placeholder="请输入" />
|
||||
<span v-else>{{ detailData.mileageCorrection || '未填写' }}</span>
|
||||
<el-button v-if="editingDetailCorrection" type="primary" size="small" @click="saveDetailCorrection" :loading="savingDetailCorrection">保存</el-button>
|
||||
<el-button v-if="editingDetailCorrection" size="small" @click="editingDetailCorrection = false">取消</el-button>
|
||||
<el-button v-if="!editingDetailCorrection" type="primary" size="small" link @click="startEditDetailCorrection">修改</el-button>
|
||||
</div>
|
||||
</el-descriptions-item>
|
||||
<el-descriptions-item label="所属光缆">{{ detailData.cableName }}</el-descriptions-item>
|
||||
<el-descriptions-item label="地点">{{ detailData.location }}</el-descriptions-item>
|
||||
<el-descriptions-item label="纬度">{{ detailData.latitude }}</el-descriptions-item>
|
||||
|
|
@ -142,7 +164,7 @@
|
|||
</template>
|
||||
|
||||
<script setup name="odfcablefaults">
|
||||
import { listOdfCableFaults, getOdfCableFaults, delOdfCableFaults } from '@/api/business/odfcablefaults.js'
|
||||
import { listOdfCableFaults, getOdfCableFaults, delOdfCableFaults, updateMileageCorrection } from '@/api/business/odfcablefaults.js'
|
||||
import { listOdfCables } from '@/api/business/odfcables.js'
|
||||
import importData from '@/components/ImportData'
|
||||
|
||||
|
|
@ -156,6 +178,9 @@ const detailLoading = ref(false)
|
|||
const cableOptions = ref([])
|
||||
const cableSearchLoading = ref(false)
|
||||
const faultTimeRange = ref(null)
|
||||
const editingDetailCorrection = ref(false)
|
||||
const detailCorrectionInput = ref('')
|
||||
const savingDetailCorrection = ref(false)
|
||||
|
||||
const queryParams = reactive({
|
||||
pageNum: 1,
|
||||
|
|
@ -174,7 +199,9 @@ const columns = ref([
|
|||
{ visible: true, align: 'center', type: '', prop: 'personnel', label: '人员', showOverflowTooltip: true },
|
||||
{ visible: true, align: 'center', type: '', prop: 'faultReason', label: '故障原因', showOverflowTooltip: true },
|
||||
{ visible: true, align: 'center', type: '', prop: 'mileage', label: '表显故障里程', showOverflowTooltip: true },
|
||||
{ visible: true, align: 'center', type: '', prop: 'mileageCorrection', label: '表显里程矫正', showOverflowTooltip: true },
|
||||
{ visible: true, align: 'center', type: '', prop: 'cableName', label: '所属光缆', showOverflowTooltip: true },
|
||||
{ visible: true, align: 'center', type: '', prop: 'faultCount', label: '故障频次' },
|
||||
{ visible: true, align: 'center', type: '', prop: 'location', label: '地点', showOverflowTooltip: true },
|
||||
{ visible: false, align: 'center', type: '', prop: 'latitude', label: '纬度' },
|
||||
{ visible: false, align: 'center', type: '', prop: 'longitude', label: '经度' },
|
||||
|
|
@ -192,6 +219,33 @@ const state = reactive({
|
|||
|
||||
const { single, multiple } = toRefs(state)
|
||||
|
||||
// 详情弹窗中所有故障时间(含首次+增加的频次时间),按时间升序
|
||||
const allDetailFaultTimes = computed(() => {
|
||||
if (!detailData.value) return []
|
||||
const times = []
|
||||
if (detailData.value.faultTime) {
|
||||
times.push(detailData.value.faultTime)
|
||||
}
|
||||
if (detailData.value.faultTimes && detailData.value.faultTimes.length > 0) {
|
||||
detailData.value.faultTimes.forEach(t => {
|
||||
times.push(t.faultTime || t.FaultTime || '')
|
||||
})
|
||||
}
|
||||
times.sort()
|
||||
return times
|
||||
})
|
||||
|
||||
// 详情弹窗中表显故障里程 = 表显故障里程 + 表显里程矫正
|
||||
const detailDisplayMileage = computed(() => {
|
||||
if (!detailData.value) return ''
|
||||
const m = parseFloat(detailData.value.mileage)
|
||||
const c = parseFloat(detailData.value.mileageCorrection)
|
||||
if (!isNaN(m) && !isNaN(c)) {
|
||||
return String(Math.round((m + c) * 10000) / 10000)
|
||||
}
|
||||
return detailData.value.mileage || ''
|
||||
})
|
||||
|
||||
// 远程搜索光缆
|
||||
function remoteCableSearch(query) {
|
||||
if (query) {
|
||||
|
|
@ -232,6 +286,26 @@ function getList() {
|
|||
})
|
||||
}
|
||||
|
||||
function startEditDetailCorrection() {
|
||||
detailCorrectionInput.value = detailData.value?.mileageCorrection || ''
|
||||
editingDetailCorrection.value = true
|
||||
}
|
||||
|
||||
function saveDetailCorrection() {
|
||||
savingDetailCorrection.value = true
|
||||
updateMileageCorrection(detailData.value.id, detailCorrectionInput.value).then((res) => {
|
||||
if (res.code == 200) {
|
||||
detailData.value.mileageCorrection = detailCorrectionInput.value
|
||||
editingDetailCorrection.value = false
|
||||
proxy.$modal.msgSuccess('保存成功')
|
||||
getList()
|
||||
}
|
||||
savingDetailCorrection.value = false
|
||||
}).catch(() => {
|
||||
savingDetailCorrection.value = false
|
||||
})
|
||||
}
|
||||
|
||||
// 查询
|
||||
function handleQuery() {
|
||||
queryParams.pageNum = 1
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user