| src/components/operationWorkbench/PointNameConflictDialog.vue | ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史 | |
| src/service/api/point.ts | ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史 | |
| src/service/api/testOperationWorkbench.ts | ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史 | |
| src/views/businessOperations/operationWorkbench/map.vue | ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史 | |
| src/views/testDemo/operationWorkbench/list.vue | ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史 | |
| src/views/testDemo/operationWorkbench/map.vue | ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史 | |
| src/views/testDemo/testPlanManagement/detail.vue | ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史 |
src/components/operationWorkbench/PointNameConflictDialog.vue
@@ -17,9 +17,12 @@ pointNumber?: string; } | null; type PointIdentity = number | string | null | undefined; const props = defineProps<{ validateNameConflict?: ( name: string name: string, pointId?: number | string ) => Promise<DuplicateNameCheckResult> | DuplicateNameCheckResult; }>(); @@ -31,6 +34,8 @@ const legacyPointName = ref(""); const currentPointNameError = ref(""); const legacyPointNameError = ref(""); const currentPointId = ref<PointIdentity>(undefined); const legacyPointId = ref<PointIdentity>(undefined); let dialogSettled = false; let dialogResolver: @@ -45,6 +50,8 @@ legacyPointName.value = ""; currentPointNameError.value = ""; legacyPointNameError.value = ""; currentPointId.value = undefined; legacyPointId.value = undefined; } function finalizeDialog(result: PointNameConflictDialogResult | null) { @@ -88,7 +95,11 @@ clearFieldError(field); return false; } const duplicatePoint = await props.validateNameConflict(normalizedName); const pointId = field === "current" ? currentPointId.value : legacyPointId.value; const duplicatePoint = await props.validateNameConflict( normalizedName, pointId ?? undefined ); if (!duplicatePoint) { clearFieldError(field); return false; @@ -164,12 +175,18 @@ if (action === "rename-legacy-point") legacyPointName.value = ""; }); function open(options?: { duplicateName?: string }) { function open(options?: { duplicateName?: string; currentPointId?: PointIdentity; legacyPointId?: PointIdentity; }) { dialogSettled = false; duplicateName.value = String(options?.duplicateName || "").trim(); selectedAction.value = "rename-current-point"; currentPointName.value = ""; legacyPointName.value = ""; currentPointId.value = options?.currentPointId; legacyPointId.value = options?.legacyPointId; visible.value = true; return new Promise<PointNameConflictDialogResult | null>((resolve) => { dialogResolver = resolve; src/service/api/point.ts
@@ -7,9 +7,12 @@ return request.Post<Service.ResponseResult<Entity.Point[]>>('/map/api/v1/point/list', params) } export function checkPointNameDuplicate(pointName: string) { export function checkPointNameDuplicate(params: { pointName: string id?: number | string }) { return request.Get<Service.ResponseResult<any>>('/map/api/v1/point/checkNameDuplicate', { params: { pointName }, params, }) } src/service/api/testOperationWorkbench.ts
@@ -49,9 +49,12 @@ return request.Post<Service.ResponseResult<Entity.Point[]>>('/map/api/v1/point/listDemo', params) } export function checkPointNameDuplicate(pointName: string) { export function checkPointNameDuplicate(params: { pointName: string id?: number | string }) { return request.Get<Service.ResponseResult<any>>('/map/api/v1/point/checkNameDuplicate', { params: { pointName }, params, }) } src/views/businessOperations/operationWorkbench/map.vue
@@ -5385,6 +5385,8 @@ interface PointNameConflictDialogExposed { open: (options?: { duplicateName?: string currentPointId?: number | string legacyPointId?: number | string }) => Promise<PointNameConflictDialogResult | null> } @@ -5414,12 +5416,19 @@ } } async function findDuplicatePointByName(pointName: string) { async function findDuplicatePointByName( pointName: string, id?: number | string, ) { const normalizedName = String(pointName || '').trim() if (!normalizedName) return null const normalizedId = String(id || '').trim() try { const res = await checkPointNameDuplicate(normalizedName) const res = await checkPointNameDuplicate({ pointName: normalizedName, id: normalizedId || undefined, }) if (res.code !== 200) return null return normalizeDuplicatePointInfo(res.data, normalizedName) @@ -5460,7 +5469,11 @@ async function preparePointSavePayloadForConflict<T extends Record<string, any>>( payload: T, ) { const duplicatePoint = await findDuplicatePointByName(payload.pointName || '') const currentPointId = payload.id const duplicatePoint = await findDuplicatePointByName( payload.pointName || '', currentPointId, ) if (!duplicatePoint) { return { shouldContinue: true, @@ -5470,6 +5483,8 @@ const resolvePayload = await pointNameConflictDialogRef.value?.open({ duplicateName: duplicatePoint.pointName, currentPointId, legacyPointId: duplicatePoint.id, }) if (!resolvePayload) { return { src/views/testDemo/operationWorkbench/list.vue
@@ -2,7 +2,7 @@ import noDataImg from '@/assets/element-img/no-data.png' import downIcon from '@/assets/element-img/down.png' import type { DataTableColumns, FormInst } from 'naive-ui' import { NButton, NDataTable, NDatePicker, NInput, NSelect, NSpace, NTag, NTooltip } from 'naive-ui' import { NButton, NDataTable, NDatePicker, NInput, NSelect, NSpace, NTag, NTimePicker, NTooltip } from 'naive-ui' import { computed, onActivated, onMounted, reactive, ref, watch } from 'vue' import { onBeforeRouteLeave, useRoute, useRouter } from 'vue-router' import dayjs from 'dayjs' @@ -95,6 +95,13 @@ { label: '20以上禁行区域', value: '20' }, ] const fenceStrategyTypeOptions = [ { label: '工作日', value: 0 }, { label: '法定节假日', value: 1 }, { label: '非工作日', value: 2 }, { label: '自定义时间', value: 3 }, ] const stationStatusOptions = [ { label: '草稿', value: 0 }, { label: '待生效', value: 1 }, @@ -117,6 +124,11 @@ electronicNumberOrName: '', electronicAreaId: null as string | null, statusList: null as number[] | null, type: null as number | null, typeStr: null as number[] | null, lifecycleRange: null as [number, number] | null, startTime: '', endTime: '', updateBy: '', updateTime: null as [number, number] | null, createBy: '', @@ -202,6 +214,8 @@ const isPointAreaSelectOpen = ref(false) const isFenceStatusListOpen = ref(false) const isFenceElectronicAreaIdOpen = ref(false) const isFenceStrategyTypeOpen = ref(false) const isFenceStrategyWeekOpen = ref(false) const isStationStatusOpen = ref(false) const isStationPointNumOpen = ref(false) const isFenceCityOpen = ref(false) @@ -328,6 +342,28 @@ return fenceStrategyDateTypeOptions.find(option => option.value === Number(item?.type))?.label || '-' } function normalizeFenceStrategyWeekFilter(value: Array<number | string> | null | undefined) { const normalized = (Array.isArray(value) ? value : []) .map(item => Number(item)) .filter(item => Number.isFinite(item)) if (normalized.includes(0)) return [0] return Array.from(new Set(normalized)).sort((a, b) => a - b) } function handleFenceStrategyTypeFilterChange(value: number | null) { fenceModel.value.type = value if (value !== 3) fenceModel.value.typeStr = null } function handleFenceStrategyWeekFilterChange(value: Array<number | string> | null) { const normalized = normalizeFenceStrategyWeekFilter(value) fenceModel.value.typeStr = normalized.length ? normalized : null } function formatFenceStrategyTimeList(item: Record<string, any>) { const times = Array.isArray(item?.time) ? item.time : [] return times @@ -422,6 +458,18 @@ function getDateRangeEnd(value: [number, number] | null | undefined) { return value ? dayjs(value[1]).endOf('day').format('YYYY-MM-DD HH:mm:ss') : undefined } function parseTimePickerValue(value?: string | null) { const normalizedValue = String(value || '').trim() if (!normalizedValue) return null const parsed = dayjs(`2000-01-01 ${normalizedValue}`) return parsed.isValid() ? parsed.valueOf() : null } function formatTimePickerValue(value: number | null) { return typeof value === 'number' ? dayjs(value).format('HH:mm') : '' } function getCurrentTabModel() { @@ -632,6 +680,12 @@ pageSize: pagination.pageSize, electronicNumberOrName: fenceModel.value.electronicNumberOrName, statusList: fenceModel.value.statusList, type: fenceModel.value.type, typeStr: fenceModel.value.type === 3 ? fenceModel.value.typeStr : null, effectTime: fenceModel.value.lifecycleRange ? dayjs(fenceModel.value.lifecycleRange[0]).startOf('day').format('YYYY-MM-DD HH:mm:ss') : null, failureTime: fenceModel.value.lifecycleRange ? dayjs(fenceModel.value.lifecycleRange[1]).endOf('day').format('YYYY-MM-DD HH:mm:ss') : null, startTime: fenceModel.value.startTime || null, endTime: fenceModel.value.endTime || null, createBy: fenceModel.value.createBy, updateBy: fenceModel.value.updateBy, updateStartTime: fenceModel.value.updateTime ? dayjs(fenceModel.value.updateTime[0]).format('YYYY-MM-DD HH:mm:ss') : null, @@ -1573,6 +1627,94 @@ ), }, { label: '运营策略', path: 'type', render: () => ( <NSelect value={fenceModel.value.type} options={fenceStrategyTypeOptions} placeholder="请选择" clearable onUpdate:value={handleFenceStrategyTypeFilterChange} onUpdate:show={(val: boolean) => isFenceStrategyTypeOpen.value = val} > {{ arrow: () => ( <img src="https://huishou-1323682843.cos.ap-nanjing.myqcloud.com/images/e120f81c-9f15-4e1a-9938-22252898edf9.png" class={`arrow-icon ${isFenceStrategyTypeOpen.value ? 'arrow-icon--open' : ''}`} style={{ width: '16px', height: '16px' }} alt="arrow" /> ), }} </NSelect> ), }, { label: '生命周期', path: 'lifecycleRange', render: () => ( <NDatePicker v-model:value={fenceModel.value.lifecycleRange} type="daterange" clearable actions={[]} close-on-select={true} format="yyyy/MM/dd" /> ), }, ...(fenceModel.value.type === 3 ? [{ label: '自定义周', path: 'typeStr', render: () => ( <NSelect value={fenceModel.value.typeStr} options={fenceStrategyWeekOptions} placeholder="请选择自定义周" clearable multiple max-tag-count={1} onUpdate:show={(val: boolean) => isFenceStrategyWeekOpen.value = val} onUpdate:value={handleFenceStrategyWeekFilterChange} > {{ arrow: () => ( <img src="https://huishou-1323682843.cos.ap-nanjing.myqcloud.com/images/e120f81c-9f15-4e1a-9938-22252898edf9.png" class={`arrow-icon ${isFenceStrategyWeekOpen.value ? 'arrow-icon--open' : ''}`} style={{ width: '16px', height: '16px' }} alt="arrow" /> ), }} </NSelect> ), }] : []), { label: '运营时间', path: 'operationTime', render: () => ( <div style={{ display: 'flex', alignItems: 'center', gap: '8px', width: '100%' }}> <NTimePicker value={parseTimePickerValue(fenceModel.value.startTime)} format="HH:mm" placeholder="开始时间" clearable actions={['now']} style={{ width: 'calc(50% - 12px)' }} onUpdate:value={value => fenceModel.value.startTime = formatTimePickerValue(value)} /> <span>至</span> <NTimePicker value={parseTimePickerValue(fenceModel.value.endTime)} format="HH:mm" placeholder="结束时间" clearable actions={['now']} style={{ width: 'calc(50% - 12px)' }} onUpdate:value={value => fenceModel.value.endTime = formatTimePickerValue(value)} /> </div> ), }, { label: '更新人', path: 'updateBy', render: () => <NInput v-model:value={fenceModel.value.updateBy} />, src/views/testDemo/operationWorkbench/map.vue
@@ -6979,6 +6979,8 @@ interface PointNameConflictDialogExposed { open: (options?: { duplicateName?: string currentPointId?: number | string legacyPointId?: number | string }) => Promise<PointNameConflictDialogResult | null> } @@ -7008,12 +7010,19 @@ } } async function findDuplicatePointByName(pointName: string) { async function findDuplicatePointByName( pointName: string, id?: number | string, ) { const normalizedName = String(pointName || '').trim() if (!normalizedName) return null const normalizedId = String(id || '').trim() try { const res = await checkPointNameDuplicate(normalizedName) const res = await checkPointNameDuplicate({ pointName: normalizedName, id: normalizedId || undefined, }) if (res.code !== 200) return null return normalizeDuplicatePointInfo(res.data, normalizedName) @@ -7054,7 +7063,11 @@ async function preparePointSavePayloadForConflict<T extends Record<string, any>>( payload: T, ) { const duplicatePoint = await findDuplicatePointByName(payload.pointName || '') const currentPointId = payload.id const duplicatePoint = await findDuplicatePointByName( payload.pointName || '', currentPointId, ) if (!duplicatePoint) { return { shouldContinue: true, @@ -7064,6 +7077,8 @@ const resolvePayload = await pointNameConflictDialogRef.value?.open({ duplicateName: duplicatePoint.pointName, currentPointId, legacyPointId: duplicatePoint.id, }) if (!resolvePayload) { return { src/views/testDemo/testPlanManagement/detail.vue
@@ -178,7 +178,7 @@ const filterItems = computed(() => [ { label: '订单号', label: '订单编号', path: 'orderNo', render: () => <n-input v-model:value={searchModel.value.orderNo} placeholder="请输入" clearable allow-input={onlyAllowNumberAndLetter} />, }, @@ -219,7 +219,7 @@ ), }, { label: '车辆', label: '接单车辆', path: 'plateNumber', render: () => ( <n-select @@ -237,7 +237,7 @@ ), }, { label: '订单状态', label: '状态', path: 'status', render: () => ( <n-select