feat(transaction/attendance): 实现待改派工单列表与免密策略运营区域联动
- 待改派工单页面替换 mock 数据为真实接口,增加状态筛选和日期格式化
- 免密策略新增页面添加根据城市获取电子围栏列表功能,实现运营区域动态加载
- 统一 API 请求参数格式,修复接口路径和参数拼接方式
| | |
| | | |
| | | /** 打卡地址管理 */ |
| | | |
| | | |
| | | // 获取打卡地址列表 |
| | | export function getCheckLocationList(params: any) { |
| | | return request.Post<Service.ResponseResult<any>>('/maintenance/api/v1/check-location/pageList', params) |
| | |
| | | |
| | | // 删除打卡地址 |
| | | export function deleteCheckLocation(id: any) { |
| | | return request.Delete<Service.ResponseResult<any>>('/maintenance/api/v1/check-location/deleteById?id=' + id) |
| | | return request.Delete<Service.ResponseResult<any>>(`/maintenance/api/v1/check-location/deleteById?id=${id}`) |
| | | } |
| | | |
| | | // 启用禁用打卡地址 |
| | | export function updateCheckLocationStatus(params: any) { |
| | | return request.Post<Service.ResponseResult<any>>('/maintenance/api/v1/check-location/updateStatus', params) |
| | | } |
| | | |
| | | |
| | | /** 班次管理 */ |
| | | |
| | |
| | | |
| | | // 删除班次 |
| | | export function deleteShift(id: any) { |
| | | return request.Delete<Service.ResponseResult<any>>('/maintenance/xp-shift/api/v1/shift/deleteById?id=' + id) |
| | | return request.Delete<Service.ResponseResult<any>>(`/maintenance/xp-shift/api/v1/shift/deleteById?id=${id}`) |
| | | } |
| | | |
| | | |
| | | /** 消息通知管理 */ |
| | | |
| | | |
| | | // 获取消息通知列表 |
| | | export function getNoticeList() { |
| | |
| | | return request.Post<Service.ResponseResult<any>>('/operation/api/v1/notification/update', params) |
| | | } |
| | | |
| | | |
| | | /** 打卡统计 */ |
| | | |
| | | |
| | | // 获取打卡统计列表 |
| | | export function getClockInStatisticsList(params: any) { |
| | |
| | | |
| | | // 导出排班 |
| | | export function exportScheduling(params: any) { |
| | | const method = request.Get<Service.ResponseResult<any>>('/maintenance/api/v1/scheduling/exportExcel?month=' + params.month, {}, { responseType: 'blob' }) |
| | | const method = request.Get<Service.ResponseResult<any>>(`/maintenance/api/v1/scheduling/exportExcel?month=${params.month}`, {}, { responseType: 'blob' }) |
| | | method.meta = { ...method.meta, isBlob: true } |
| | | return method |
| | | } |
| | |
| | | export function saveScheduling(params: any) { |
| | | return request.Post<Service.ResponseResult<any>>('/maintenance/api/v1/scheduling/saveSchedulingDetail', params) |
| | | } |
| | | |
| | | |
| | | // 获取班次不分页列表 |
| | | export function getShiftListNoPage() { |
| | |
| | | |
| | | // 获取运维人员详情 |
| | | export function getOperationsUserDetail(id: any) { |
| | | return request.Get<Service.ResponseResult<any>>('/account/api/v1/operationsUser/detailById?id=' + id) |
| | | return request.Get<Service.ResponseResult<any>>(`/account/api/v1/operationsUser/detailById?id=${id}`) |
| | | } |
| | | |
| | | // 新增运维人员 |
| | |
| | | |
| | | // 删除运维人员 |
| | | export function deleteOperationsUser(id: any) { |
| | | return request.Delete<Service.ResponseResult<any>>('/account/api/v1/operationsUser/deleteById?id=' + id) |
| | | return request.Delete<Service.ResponseResult<any>>(`/account/api/v1/operationsUser/deleteById?id=${id}`) |
| | | } |
| | | |
| | | // 启用禁用运维人员 |
| | |
| | | return request.Post<Service.ResponseResult<any>>('/account/api/v1/operationsUser/importOperationsUser', formData) |
| | | } |
| | | |
| | | |
| | | /** 任务工单 */ |
| | | |
| | | // 任务中心列表 |
| | |
| | | |
| | | // 获取任务详情 |
| | | export function getTaskOrderDetail(id: any) { |
| | | return request.Get<Service.ResponseResult<any>>('/maintenance/api/v1/taskManagement/taskDetail?id=' + id) |
| | | return request.Get<Service.ResponseResult<any>>(`/maintenance/api/v1/taskManagement/taskDetail?id=${id}`) |
| | | } |
| | | |
| | | // 任务分配 |
| | | export function assignTaskOrder(params: any) { |
| | | return request.Get<Service.ResponseResult<any>>('/maintenance/api/v1/taskManagement/assigneeTask?id=' + params.id + '&handlerUserId=' + params.handlerUserId) |
| | | return request.Get<Service.ResponseResult<any>>(`/maintenance/api/v1/taskManagement/assigneeTask?id=${params.id}&handlerUserId=${params.handlerUserId}`) |
| | | } |
| | | |
| | | // 删除任务 |
| | | export function deleteTaskOrder(id: any) { |
| | | return request.Delete<Service.ResponseResult<any>>('/maintenance/api/v1/taskManagement/deleteTaskById?id=' + id) |
| | | return request.Delete<Service.ResponseResult<any>>(`/maintenance/api/v1/taskManagement/deleteTaskById?id=${id}`) |
| | | } |
| | | |
| | | // 事故类型列表 |
| | |
| | | export function getVehicleListNoPage() { |
| | | return request.Post<Service.ResponseResult<any>>('/maintenance/api/v1/taskManagement/listVehicle') |
| | | } |
| | | |
| | | // 待改派工单列表 |
| | | export function getTaskOrderReassignList(params: any) { |
| | | return request.Post<Service.ResponseResult<any>>('/maintenance/api/v1/task/reassign/pageList', params) |
| | | } |
| | | |
| | | // 待改派工单详情 |
| | | export function getTaskOrderReassignDetail(id: any) { |
| | | return request.Get<Service.ResponseResult<any>>(`/maintenance/api/v1/task/reassign/detail?taskId =${id}`) |
| | | } |
| | | |
| | | // 可改派的运维人员列表 |
| | | export function getTaskOrderReassignOperationsUserList(params: any) { |
| | | return request.Post<Service.ResponseResult<any>>('/maintenance/api/v1/task/reassign/availableUsers', params) |
| | | } |
| | |
| | | |
| | | // 获取免密支付策略详情 |
| | | export function getPasswordFreePolicyDetail(id: any) { |
| | | return request.Get<Service.ResponseResult<any>>(`/operation/api/v1/passwordFreePolicy/queryById?id=${id}`) |
| | | return request.Get<Service.ResponseResult<any>>(`/operation/api/v1/passwordFreePolicy/getById/${id}`) |
| | | } |
| | | |
| | | // 通过城市获取围栏列表 |
| | | export function getFenceListByCityId(params: any) { |
| | | return request.Post<Service.ResponseResult<any>>(`/map/api/v1/electronicFence/list`, params) |
| | | } |
| | |
| | | import { computed, onMounted, ref } from 'vue' |
| | | import { useBoolean } from '@/hooks' |
| | | import { NButton, NTag, useMessage } from 'naive-ui' |
| | | import { getTaskAccidentTypeList } from '@/service/api/attendance' |
| | | import { getTaskAccidentTypeList, getTaskOrderReassignList } from '@/service/api/attendance' |
| | | import SearchPanel from '@/components/custom/SearchPanel.vue' |
| | | import Pagination from '@/components/common/Pagination.vue' |
| | | import ReassignModal from './components/ReassignModal.vue' |
| | | import ReassignDetailModal from './components/ReassignDetailModal.vue' |
| | | import dayjs from 'dayjs' |
| | | |
| | | const { bool: loading, setTrue: startLoading, setFalse: endLoading } = useBoolean(false) |
| | | const message = useMessage() |
| | |
| | | // 获取列表数据 |
| | | async function getList() { |
| | | startLoading() |
| | | // Mock data simulation |
| | | setTimeout(() => { |
| | | const mockData = Array.from({ length: 10 }).map((_, index) => { |
| | | const isPending = index < 5 // 前5条待处理,后5条已处理 |
| | | |
| | | const levels = [ |
| | | 0, // 1 |
| | | 0, // 2 |
| | | 2, // 3 |
| | | 1, // 4 |
| | | 2, // 5 |
| | | 3, // 6 |
| | | 1, // 7 |
| | | 2, // 8 |
| | | 1, // 9 |
| | | 3, // 10 |
| | | ] |
| | | |
| | | const types = [ |
| | | '车辆整备', |
| | | '车辆技术故障>关键传感器故障', |
| | | '车辆整备', |
| | | '车辆整备', |
| | | '车辆整备', |
| | | '车辆整备', |
| | | '车辆整备', |
| | | '车辆技术故障>关键传感器故障', |
| | | '车辆技术故障>关键传感器故障', |
| | | '车辆技术故障>关键传感器故障', |
| | | ] |
| | | |
| | | return { |
| | | id: `mock-id-${pageParams.value.page}-${index}`, |
| | | vehicle: '皖PXV7029', |
| | | taskCategory: '事故', |
| | | type: types[index], |
| | | level: levels[index], |
| | | description: '任务描述内容任务描述内容', |
| | | applyTime: '2025-05-07 14:53', |
| | | reason: '任务分派冲突', |
| | | status: isPending ? 'pending' : 'processed', |
| | | } |
| | | }) |
| | | |
| | | count.value = 1000 // Mock total count |
| | | listData.value = mockData |
| | | try { |
| | | const params = { |
| | | pageNum: pageParams.value.page, |
| | | pageSize: pageParams.value.size, |
| | | plateNumber: model.value.plateNumber || undefined, |
| | | taskCategory: model.value.taskCategory ?? undefined, |
| | | taskGeneralId: model.value.taskGeneralId ?? undefined, |
| | | taskErrorId: model.value.taskErrorId ?? undefined, |
| | | taskUrgencyLevel: model.value.taskUrgencyLevel ?? undefined, |
| | | status: model.value.status ?? undefined, |
| | | } |
| | | const res = await getTaskOrderReassignList(params) |
| | | if (res.code === 200) { |
| | | const records = res.data?.records || [] |
| | | listData.value = records |
| | | count.value = res.data?.total || records.length || 0 |
| | | return |
| | | } |
| | | listData.value = [] |
| | | count.value = 0 |
| | | } |
| | | catch (error) { |
| | | console.error('获取待改派工单列表失败:', error) |
| | | listData.value = [] |
| | | count.value = 0 |
| | | } |
| | | finally { |
| | | endLoading() |
| | | }, 500) |
| | | } |
| | | } |
| | | |
| | | // 分页变化 |
| | |
| | | key: 'taskCategory', |
| | | width: 100, |
| | | resizable: true, |
| | | render: row => options.find(item => item.value === row.taskCategory)?.label || row.taskCategory || '-', |
| | | }, |
| | | { |
| | | title: '类型', |
| | |
| | | key: 'applyTime', |
| | | width: 160, |
| | | resizable: true, |
| | | render: row => row.applyTime ? dayjs(row.applyTime).format('YYYY/MM/DD HH:mm') : '-', |
| | | }, |
| | | { |
| | | title: '改派原因', |
| | |
| | | width: 100, |
| | | resizable: true, |
| | | render: (row) => { |
| | | const isPending = row.status === 'pending' |
| | | const isPending = !!row._pending |
| | | return ( |
| | | <NTag |
| | | bordered={false} |
| | |
| | | width: 90, |
| | | fixed: 'right', |
| | | render: (row) => { |
| | | const isPending = row.status === 'pending' |
| | | const isPending = !!row._pending |
| | | if (isPending) { |
| | | return ( |
| | | <div class="flex items-center justify-start gap-2"> |
| | |
| | | import { NButton, NCheckbox, NDatePicker, NForm, NInputNumber, NSelect, NSpace, NSwitch, useMessage } from 'naive-ui' |
| | | import type { FormItemRule } from 'naive-ui' |
| | | import dayjs from 'dayjs' |
| | | import { addPasswordFreePolicy, editPasswordFreePolicy, getCityList, getPasswordFreePolicyDetail } from '@/service/api/transaction' |
| | | import { addPasswordFreePolicy, editPasswordFreePolicy, getCityList, getFenceListByCityId, getPasswordFreePolicyDetail } from '@/service/api/transaction' |
| | | import { useTabStore } from '@/store' |
| | | |
| | | const tabStore = useTabStore() |
| | |
| | | const isOperationAreaOpen = ref(false) |
| | | |
| | | const formModel = ref({ |
| | | city: null as string | null, |
| | | operationArea: null as string | null, |
| | | city: null as string | number | null, |
| | | operationArea: null as string | number | null, |
| | | status: 1, |
| | | validTimeStart: null as number | null, |
| | | validTimeEnd: null as number | null, |
| | |
| | | const formRef = ref<any>(null) |
| | | const validTimeStartPicker = ref<any>(null) |
| | | const validTimeEndPicker = ref<any>(null) |
| | | const operationAreaOptions = ref<any[]>([]) |
| | | |
| | | async function getOperationAreaOptions(cityCode: string | number) { |
| | | try { |
| | | const res = await getFenceListByCityId({ cityCode }) |
| | | if (res.code === 200) { |
| | | const rawList = res.data?.records || res.data?.list || res.data || [] |
| | | const list = Array.isArray(rawList) ? rawList : [] |
| | | operationAreaOptions.value = list.map((item: any) => ({ |
| | | label: item.electronicName || item.fenceName || item.name || '-', |
| | | value: item.id ?? item.electronicId ?? item.code, |
| | | })) |
| | | return |
| | | } |
| | | operationAreaOptions.value = [] |
| | | message.warning(res.msg || '获取运营区域失败') |
| | | } |
| | | catch (error) { |
| | | console.error('获取运营区域失败:', error) |
| | | operationAreaOptions.value = [] |
| | | message.error('请求运营区域失败') |
| | | } |
| | | } |
| | | |
| | | async function fetchDetail() { |
| | | if (!id.value) |
| | |
| | | if (res.code === 200 && res.data) { |
| | | const data = res.data |
| | | formModel.value = { |
| | | city: data.city ?? data.cityId ?? null, |
| | | city: data.cityCode ?? data.city ?? data.cityId ?? null, |
| | | operationArea: data.operationArea ?? data.operationAreaId ?? null, |
| | | status: Number(data.status ?? 1), |
| | | validTimeStart: data.validTimeStart ? dayjs(data.validTimeStart).valueOf() : null, |
| | |
| | | sendNotification: data.sendNotification === 1 || data.sendNotification === true ? 1 : 0, |
| | | differenceRatio: data.differenceRatio ?? null, |
| | | } |
| | | if (formModel.value.city !== null && formModel.value.city !== undefined) |
| | | await getOperationAreaOptions(formModel.value.city) |
| | | return |
| | | } |
| | | message.warning(res.msg || '获取策略详情失败') |
| | |
| | | function getCityListData() { |
| | | getCityList({ type: 0 }).then((res) => { |
| | | if (res.code === 200) { |
| | | cityList.value = res.data || [] |
| | | cityList.value.forEach((item) => { |
| | | item.label = item.name |
| | | item.value = item.id |
| | | }) |
| | | const list = Array.isArray(res.data) ? res.data : [] |
| | | cityList.value = list.map((item: any) => ({ |
| | | ...item, |
| | | label: item.name, |
| | | value: item.cityCode ?? item.code ?? item.id, |
| | | })) |
| | | } |
| | | }) |
| | | } |
| | | |
| | | watch(() => formModel.value.city, async (cityCode) => { |
| | | formModel.value.operationArea = null |
| | | operationAreaOptions.value = [] |
| | | if (cityCode === null || cityCode === undefined || cityCode === '') |
| | | return |
| | | await getOperationAreaOptions(cityCode) |
| | | }) |
| | | |
| | | onMounted(() => { |
| | | getCityListData() |
| | |
| | | alt="arrow" |
| | | > |
| | | </template> |
| | | l <template #empty> |
| | | <template #empty> |
| | | <div class="flex-center"> |
| | | <img |
| | | src="/src/assets/element-img/no-data.png" |
| | |
| | | <NSelect |
| | | v-model:value="formModel.operationArea" |
| | | placeholder="请选择" |
| | | :options="[]" |
| | | :options="operationAreaOptions" |
| | | class="w-300px" |
| | | @update:show="(val: boolean) => isOperationAreaOpen = val" |
| | | > |