| | |
| | | --- |
| | | |
| | | 先检查页面的表单,并对表单做以下优化: |
| | | 1,下拉框-如果有下拉框,需要优化下拉框的插槽arrow。 |
| | | 1,下拉框-如果有下拉框,需要优化下拉框的插槽arrow。 |
| | | 2,如果有参考的图片,需要先参考 图片的布局来调整。 |
| | | 3,一般的页面,都是padding:12px 。如果有块状元素,使用ncard。 |
| | | 4,如果有页面的title,title的样式这些可以参考:src\views\system\config\index.vue。 |
| | | 5,如果页面有保存这些操作,可以结合 src\views\system\config\index.vue 页面,看一下保存的样式这些。 |
| | |
| | | }) { |
| | | return request.Post<Service.ResponseResult<any>>('/order/api/v1/cruise-order/pageList', data) |
| | | } |
| | | |
| | | export function deleteCruiseOrder(id: number | string) { |
| | | return request.Delete<Service.ResponseResult<any>>(`/order/api/v1/cruise-order/deleteById?id=${id}`) |
| | | } |
| | |
| | | |
| | | // 计算弹窗标题 |
| | | const modalTitle = computed(() => { |
| | | return props.type === 'complete' ? '完善车辆信息' : '更新信息' |
| | | return props.type === 'complete' ? '完善车辆信息' : '更新车辆信息' |
| | | }) |
| | | </script> |
| | | |
| | |
| | | import { useBoolean } from '@/hooks' |
| | | import SelectPointModal from '../patrol-points/components/SelectPointModal.vue' |
| | | import VehicleSelectModal from '@/views/assetManagement/fleetManagement/components/VehicleSelectModal.vue' |
| | | import { editCruisePlan, fetchCruiseOrderPageList, fetchCruisePlanDetail } from '@/service/api/cruise' |
| | | import { deleteCruiseOrder, editCruisePlan, fetchCruiseOrderPageList, fetchCruisePlanDetail } from '@/service/api/cruise' |
| | | |
| | | const router = useRouter() |
| | | const route = useRoute() |
| | | const message = useMessage() |
| | | const dialog = useDialog() |
| | | |
| | | interface Point { |
| | | id: number |
| | |
| | | const selectedRecords = ref<number[]>([]) |
| | | const { bool: recordLoading, setTrue: startRecordLoading, setFalse: endRecordLoading } = useBoolean(false) |
| | | |
| | | const isStatusSelectOpen = ref(false) |
| | | |
| | | const statusTextMap: Record<number, string> = { |
| | | 1: '进行中', |
| | | 2: '已停止', |
| | |
| | | |
| | | const handleRecordDetail = (record: CruiseOrderRow) => { |
| | | message.info(`订单 ${record.id} 详情暂未接入`) |
| | | router.push({ name: 'orderDetail', params: { id: record.id } }) |
| | | } |
| | | |
| | | const handleDeleteRecord = (record: CruiseOrderRow) => { |
| | | dialog.create({ |
| | | title: '是否确认删除该巡游订单?', |
| | | content: '删除后数据不可恢复,请谨慎操作', |
| | | positiveText: '确认', |
| | | negativeText: '取消', |
| | | draggable: true, |
| | | onPositiveClick: async () => { |
| | | const res = await deleteCruiseOrder(record.id) |
| | | if (res.code === 200) { |
| | | message.success('删除成功') |
| | | getRecordList() |
| | | } |
| | | } |
| | | }) |
| | | } |
| | | |
| | | const recordColumns = computed<DataTableColumns<CruiseOrderRow>>(() => [ |
| | | { type: 'selection', width: 50 }, |
| | | { title: '订单号', key: 'id', width: 100 }, |
| | | { title: '下单时间', key: 'createTime', width: 180 }, |
| | | { title: '起点', key: 'startPointName', minWidth: 150 }, |
| | | { title: '终点', key: 'endPointName', minWidth: 150 }, |
| | | { title: '接单车辆', key: 'plateNumber', width: 140 }, |
| | | { title: '归属车队', key: 'fleetName', width: 140 }, |
| | | { type: 'selection', width: 50, fixed: 'left' }, |
| | | { title: '订单号', key: 'id', width: 200, align: 'left', resizable: true }, |
| | | { title: '下单时间', key: 'createTime', width: 180, align: 'left', resizable: true, render: row => row.createTime ? dayjs(row.createTime).format('YYYY/MM/DD HH:mm') : '-' }, |
| | | { title: '订单来源', key: 'orderSource', width: 120, align: 'left', resizable: true, render: () => '系统自动创建' }, |
| | | { title: '起点', key: 'startPointName', width: 200, align: 'left', resizable: true, ellipsis: { tooltip: true } }, |
| | | { title: '终点', key: 'endPointName', width: 200, align: 'left', resizable: true, ellipsis: { tooltip: true } }, |
| | | { title: '接单车辆', key: 'plateNumber', width: 140, align: 'left', resizable: true }, |
| | | { title: '归属车队', key: 'fleetName', width: 140, align: 'left', resizable: true }, |
| | | { |
| | | title: '状态', |
| | | key: 'status', |
| | | width: 100, |
| | | align: 'left', |
| | | resizable: true, |
| | | render: row => <span>{row.status ? statusTextMap[row.status] || row.status : '-'}</span>, |
| | | }, |
| | | { |
| | | title: '操作', |
| | | key: 'actions', |
| | | width: 100, |
| | | width: 120, |
| | | fixed: 'right', |
| | | align: 'left', |
| | | render: row => ( |
| | | <div class="flex gap-3"> |
| | | <a style={{ color: '#0068FF', cursor: 'pointer' }} onClick={() => handleRecordDetail(row)}>详情</a> |
| | | <a style={{ color: '#FF4D4F', cursor: 'pointer' }} onClick={() => handleDeleteRecord(row)}>删除</a> |
| | | </div> |
| | | ), |
| | | }, |
| | |
| | | { |
| | | label: '订单状态', |
| | | path: 'status', |
| | | render: () => <n-select v-model:value={recordSearch.value.status} options={statusOptions} placeholder="请选择" clearable />, |
| | | render: () => ( |
| | | <n-select |
| | | v-model:value={recordSearch.value.status} |
| | | options={statusOptions} |
| | | placeholder="请选择" |
| | | clearable |
| | | onUpdate:show={(val: boolean) => (isStatusSelectOpen.value = val)} |
| | | > |
| | | {{ |
| | | arrow: () => ( |
| | | <img |
| | | src="https://huishou-1323682843.cos.ap-nanjing.myqcloud.com/images/e120f81c-9f15-4e1a-9938-22252898edf9.png" |
| | | class={`arrow-icon ${isStatusSelectOpen.value ? 'arrow-icon--open' : ''}`} |
| | | style={{ width: '16px', height: '16px' }} |
| | | alt="arrow" |
| | | /> |
| | | ), |
| | | }} |
| | | </n-select> |
| | | ), |
| | | }, |
| | | { |
| | | label: '下单时间', |
| | | path: 'dateRange', |
| | | render: () => <n-date-picker v-model:value={recordSearch.value.dateRange} type="datetimerange" clearable style={{ width: '100%' }} />, |
| | | render: () => ( |
| | | <n-date-picker |
| | | v-model:value={recordSearch.value.dateRange} |
| | | type="datetimerange" |
| | | clearable |
| | | style={{ width: '100%' }} |
| | | actions={[]} |
| | | close-on-select={true} |
| | | start-placeholder="开始时间" |
| | | end-placeholder="结束时间" |
| | | /> |
| | | ), |
| | | }, |
| | | ]) |
| | | |
| | |
| | | </div> |
| | | </n-card> |
| | | </n-tab-pane> |
| | | <n-tab-pane name="record" tab="巡游计划记录"> |
| | | <n-tab-pane name="record" tab="巡游订单记录"> |
| | | <n-card style="border-radius: 6px; margin-bottom: 16px"> |
| | | <n-form :model="recordSearch" label-placement="left" inline :show-feedback="false"> |
| | | <SearchPanel> |
| | |
| | | :data="records" |
| | | :loading="recordLoading" |
| | | :row-key="(row: CruiseOrderRow) => row.id" |
| | | :scroll-x="1450" |
| | | :pagination="{ |
| | | page: recordCurrentPage, |
| | | pageSize: recordPageSize, |
| | |
| | | <script setup lang="ts"> |
| | | import { ref } from 'vue' |
| | | import { ref, onMounted } from 'vue' |
| | | import { useTabStore } from '@/store' |
| | | import { useRouter, useRoute } from 'vue-router' |
| | | import { getOperationsUserDetail } from '@/service/api/attendance' |
| | | import { getOperationsUserDetail, editOperationsUser } from '@/service/api/attendance' |
| | | import { fetchRoleList } from '@/service/api/fleet' |
| | | import PersonnelFormModal from './components/PersonnelFormModal.vue' |
| | | |
| | | const router = useRouter() |
| | | const route = useRoute() |
| | | const tabStore = useTabStore() |
| | | |
| | | const personnelInfo = ref() |
| | | const showFormModal = ref(false) |
| | | const modalRef = ref() |
| | | const roleOptions = ref<any[]>([]) |
| | | |
| | | const getDetail = async () => { |
| | | const res = await getOperationsUserDetail(route.params.id) |
| | | if (res.code === 200) { |
| | | personnelInfo.value = res.data |
| | | } |
| | | } |
| | | |
| | | const getRoleList = async () => { |
| | | const res = await fetchRoleList() |
| | | if (res.code === 200) { |
| | | roleOptions.value = res.data.map((item: any) => ({ |
| | | label: item.roleName, |
| | | value: item.id, |
| | | })) |
| | | } |
| | | } |
| | | |
| | | const handleBack = () => { |
| | | tabStore.closeTab(route.fullPath) |
| | | router.back() |
| | | } |
| | | |
| | | onMounted(async () => { |
| | | const res = await getOperationsUserDetail(route.params.id) |
| | | if (res.code === 200) { |
| | | personnelInfo.value = res.data |
| | | } |
| | | const handleEdit = () => { |
| | | showFormModal.value = true |
| | | modalRef.value?.openModal(personnelInfo.value) |
| | | } |
| | | |
| | | const handleConfirmForm = (data: any) => { |
| | | editOperationsUser(data).then(res => { |
| | | if (res.code === 200) { |
| | | showFormModal.value = false |
| | | window.$message.success('编辑成功') |
| | | getDetail() |
| | | } |
| | | }) |
| | | } |
| | | |
| | | onMounted(() => { |
| | | getDetail() |
| | | getRoleList() |
| | | }) |
| | | </script> |
| | | |
| | | <template> |
| | | <div class="h-full flex flex-col" style="gap: 12px" v-if="personnelInfo?.nickName"> |
| | | <n-card style="border-radius: 6px" content-style="padding: 12px"> |
| | | <div class="flex items-center justify-between mb-4"> |
| | | <div class="text-lg font-bold">员工详情</div> |
| | | <n-button style="width: 84px; height: 32px" @click="handleBack">返回</n-button> |
| | | <div class="h-full flex flex-col p-12px overflow-y-auto" v-if="personnelInfo?.nickName"> |
| | | <n-card :bordered="false" class="rounded-6px" content-style="padding: 24px"> |
| | | <div class="flex items-center justify-between mb-24px"> |
| | | <div class="head">员工详情</div> |
| | | <n-button type="primary" ghost class="w-84px h-32px" @click="handleEdit">编辑</n-button> |
| | | </div> |
| | | |
| | | <div class="flex items-start gap-4"> |
| | | <n-avatar |
| | | round |
| | | :size="64" |
| | | v-if="personnelInfo.avatar" |
| | | :src="JSON.parse(personnelInfo.avatar).url" |
| | | /> |
| | | <div class="flex-1"> |
| | | <div class="flex items-center gap-3 mb-2"> |
| | | <span class="text-lg font-medium">{{ personnelInfo.nickName }}</span> |
| | | </div> |
| | | <div class="text-sm mb-2"> |
| | | <span class="text-gray-600">编号:</span> |
| | | <span>{{ personnelInfo.uniqueNumber }}</span> |
| | | </div> |
| | | <div class="grid grid-cols-3 gap-4 text-sm"> |
| | | <div> |
| | | <span class="text-gray-600">电话:</span> |
| | | <span>{{ personnelInfo.phoneNumber }}</span> |
| | | </div> |
| | | <div> |
| | | <span class="text-gray-600">性别:</span> |
| | | <span>{{ personnelInfo.sex === 1 ? '男' : '女' }}</span> |
| | | </div> |
| | | <div> |
| | | <span class="text-gray-600">角色:</span> |
| | | <span class="gap-2 inline-flex"> |
| | | <n-tag type="info" size="small" v-for="item in personnelInfo.sysRoles">{{ item.roleName }}</n-tag> |
| | | </span> |
| | | </div> |
| | | <div> |
| | | <span class="text-gray-600">备注:</span> |
| | | <span>{{ personnelInfo.remarks || '-' }}</span> |
| | | </div> |
| | | <div class="flex items-center gap-8px mb-16px"> |
| | | <div class="relative w-40px h-40px"> |
| | | <n-avatar |
| | | round |
| | | :size="40" |
| | | v-if="JSON.parse(personnelInfo.avatar).url" |
| | | :src="JSON.parse(personnelInfo.avatar).url" |
| | | /> |
| | | <img src="/src/assets/element-img/avatar.png" style="width:40px;height:40px" v-else-if="!JSON.parse(personnelInfo.avatar).url && personnelInfo.sex === 1" /> |
| | | <img src="/src/assets/element-img/acatar-woman.png" style="width:40px;height:40px" v-else /> |
| | | <img src="/src/assets/element-img/man.png" class="sex-icon" v-if="personnelInfo.sex === 1"/> |
| | | <img src="/src/assets/element-img/woman.png" class="sex-icon" v-else/> |
| | | |
| | | </div> |
| | | <div class="flex flex-col gap-4px"> |
| | | <span class="text-16px text-[#171F26]">{{ personnelInfo.nickName }}</span> |
| | | <div class="text-14px text-[#919191]"> |
| | | 编号:{{ personnelInfo.uniqueNumber }} |
| | | </div> |
| | | </div> |
| | | </div> |
| | | </n-card> |
| | | |
| | | <n-card style="border-radius: 6px" content-style="padding: 12px"> |
| | | <div class="mb-4"> |
| | | <div class="text-sm font-medium">身份证:</div> |
| | | <div class="flex gap-4" v-if="personnelInfo.idCardFront || personnelInfo.idCardBack"> |
| | | <div class="grid grid-cols-3 gap-24px mb-16px line-bottom"> |
| | | <div class="flex items-center"> |
| | | <span class="text-14px label-color w-42px">电话:</span> |
| | | <span class="text-14px text-[#171F26]">{{ personnelInfo.phoneNumber }}</span> |
| | | </div> |
| | | <div class="flex items-center"> |
| | | <span class="text-14px label-color w-42px">角色:</span> |
| | | <div class="flex gap-8px"> |
| | | <span v-for="item in personnelInfo.sysRoles" :key="item.roleId" class="text-14px text-[#171F26]">{{ item.roleName }}</span> |
| | | </div> |
| | | </div> |
| | | <div class="flex items-center"> |
| | | <span class="text-14px label-color w-42px">备注:</span> |
| | | <span class="text-14px text-[#171F26]">{{ personnelInfo.remarks || '-' }}</span> |
| | | </div> |
| | | </div> |
| | | |
| | | |
| | | <div class="mb-16px"> |
| | | <div class="text-14px font-600 text-[#171F26] mb-12px">身份证:</div> |
| | | <div class="flex gap-16px" v-if="personnelInfo.idCardFront || personnelInfo.idCardBack"> |
| | | <n-image |
| | | width="128" |
| | | height="80" |
| | | width="213" |
| | | height="120" |
| | | v-if="personnelInfo.idCardFront" |
| | | :src="JSON.parse(personnelInfo.idCardFront).url" |
| | | object-fit="cover" |
| | | style="border-radius: 4px" |
| | | class="rounded-4px border border-[#E5E5E5]" |
| | | /> |
| | | <n-image |
| | | width="128" |
| | | height="80" |
| | | width="213" |
| | | height="120" |
| | | v-if="personnelInfo.idCardBack" |
| | | :src="JSON.parse(personnelInfo.idCardBack).url" |
| | | object-fit="cover" |
| | | style="border-radius: 4px" |
| | | class="rounded-4px border border-[#E5E5E5]" |
| | | /> |
| | | </div> |
| | | <div v-else> |
| | | <span>-</span> |
| | | </div> |
| | | <div v-else class="text-14px text-[#919191]">-</div> |
| | | </div> |
| | | |
| | | <div class="mb-4"> |
| | | <div class="text-sm font-medium">驾驶证:</div> |
| | | <div class="mb-16px"> |
| | | <div class="text-14px font-600 text-[#171F26] mb-12px">驾驶证:</div> |
| | | <n-image |
| | | width="128" |
| | | height="80" |
| | | width="213" |
| | | height="120" |
| | | v-if="personnelInfo.driverLicense" |
| | | :src="JSON.parse(personnelInfo.driverLicense).url" |
| | | object-fit="cover" |
| | | style="border-radius: 4px" |
| | | class="rounded-4px border border-[#E5E5E5]" |
| | | /> |
| | | <div v-else> |
| | | <span>-</span> |
| | | </div> |
| | | <div v-else class="text-14px text-[#919191]">-</div> |
| | | </div> |
| | | |
| | | <div> |
| | | <div class="text-sm font-medium">无犯罪记录证明:</div> |
| | | <div class="text-14px font-600 text-[#171F26] mb-12px">无犯罪记录证明:</div> |
| | | <n-image |
| | | width="128" |
| | | height="80" |
| | | width="213" |
| | | height="120" |
| | | v-if="personnelInfo.certificateOfNoCriminalRecord" |
| | | :src="JSON.parse(personnelInfo.certificateOfNoCriminalRecord).url" |
| | | object-fit="cover" |
| | | style="border-radius: 4px" |
| | | class="rounded-4px border border-[#E5E5E5]" |
| | | /> |
| | | <div v-else> |
| | | <span>-</span> |
| | | </div> |
| | | <div v-else class="text-14px text-[#919191]">-</div> |
| | | </div> |
| | | </n-card> |
| | | |
| | | <PersonnelFormModal |
| | | v-model:show="showFormModal" |
| | | ref="modalRef" |
| | | mode="edit" |
| | | :roleOptions="roleOptions" |
| | | @confirm="handleConfirmForm" |
| | | /> |
| | | </div> |
| | | </template> |
| | | |
| | | <style scoped></style> |
| | | <style scoped lang="scss"> |
| | | .p-12px { |
| | | padding: 12px; |
| | | } |
| | | |
| | | .rounded-6px { |
| | | border-radius: 6px; |
| | | } |
| | | |
| | | .rounded-4px { |
| | | border-radius: 4px; |
| | | } |
| | | |
| | | |
| | | .mb-12px { |
| | | margin-bottom: 12px; |
| | | } |
| | | |
| | | .w-84px { |
| | | width: 84px; |
| | | } |
| | | |
| | | .h-32px { |
| | | height: 32px; |
| | | } |
| | | |
| | | .w-42px { |
| | | width: 42px; |
| | | } |
| | | |
| | | .text-16px { |
| | | font-size: 16px; |
| | | line-height: 18px; |
| | | font-weight: bold; |
| | | } |
| | | |
| | | .sex-icon{ |
| | | position: absolute; |
| | | bottom: 0; |
| | | right: 0; |
| | | // transform: translate(-50%, -50%); |
| | | width: 12px; |
| | | height: 12px; |
| | | } |
| | | .text-14px { |
| | | font-size: 14px; |
| | | line-height: 18px; |
| | | color: #171F26; |
| | | } |
| | | .line-bottom { |
| | | border-bottom: 1px solid #E5E5E5; |
| | | padding-bottom: 16px; |
| | | } |
| | | .label-color{ |
| | | color: rgba(23, 31, 38, 0.6); |
| | | } |
| | | |
| | | |
| | | .head { |
| | | font-family: PingFang SC; |
| | | font-size: 16px; |
| | | font-weight: 600; |
| | | line-height: 24px; |
| | | letter-spacing: normal; |
| | | color: #171F26; |
| | | position: relative; |
| | | text-indent: 11px; |
| | | |
| | | &::before { |
| | | content: ''; |
| | | position: absolute; |
| | | top: 50%; |
| | | left: 0; |
| | | transform: translateY(-50%); |
| | | width: 3px; |
| | | height: 14px; |
| | | z-index: 0; |
| | | border-radius: 3px; |
| | | background: #0068FF; |
| | | } |
| | | } |
| | | </style> |
| | |
| | | const roleOptions = ref<any[]>([]) |
| | | const modalRef = ref() |
| | | |
| | | const isRoleSelectOpen = ref(false) |
| | | const isStatusSelectOpen = ref(false) |
| | | |
| | | const statusOptions = [ |
| | | { label: '启用', value: true }, |
| | | { label: '禁用', value: false } |
| | |
| | | showFormModal.value = true |
| | | } |
| | | |
| | | const handleEdit = (row: any) => { |
| | | // router.push(`/operations/personnel/personnelManagement/detail/${row.id}`) |
| | | formMode.value = 'edit' |
| | | showFormModal.value = true |
| | | modalRef.value?.openModal(row) |
| | | } |
| | | |
| | | const handleConfirmForm = (data: any) => { |
| | | if (data.id) { |
| | | editOperationsUser(data).then(res => { |
| | |
| | | } |
| | | |
| | | const moreOptions = (row: any) => [ |
| | | { |
| | | label: '编辑', |
| | | key: 'edit', |
| | | show: hasPermission(70115), |
| | | props: { |
| | | onClick: () => handleEdit(row) |
| | | } |
| | | }, |
| | | { |
| | | label: row.status ? '禁用' : '启用', |
| | | key: 'toggle', |
| | |
| | | { |
| | | label: '角色', |
| | | path: 'roleId', |
| | | render: () => <n-select v-model:value={searchModel.value.roleId} options={roleOptions.value} placeholder="请选择" clearable /> |
| | | render: () => ( |
| | | <n-select |
| | | v-model:value={searchModel.value.roleId} |
| | | options={roleOptions.value} |
| | | placeholder="请选择" |
| | | clearable |
| | | onUpdate:show={(val: boolean) => isRoleSelectOpen.value = val} |
| | | > |
| | | {{ |
| | | arrow: () => ( |
| | | <img |
| | | src="https://huishou-1323682843.cos.ap-nanjing.myqcloud.com/images/e120f81c-9f15-4e1a-9938-22252898edf9.png" |
| | | class={`arrow-icon ${isRoleSelectOpen.value ? 'arrow-icon--open' : ''}`} |
| | | style={{ width: '16px', height: '16px' }} |
| | | alt="arrow" |
| | | /> |
| | | ), |
| | | }} |
| | | </n-select> |
| | | ) |
| | | }, |
| | | { |
| | | label: '账号状态', |
| | | path: 'status', |
| | | render: () => <n-select v-model:value={searchModel.value.status} options={statusOptions} placeholder="请选择" clearable /> |
| | | render: () => ( |
| | | <n-select |
| | | v-model:value={searchModel.value.status} |
| | | options={statusOptions} |
| | | placeholder="请选择" |
| | | clearable |
| | | onUpdate:show={(val: boolean) => isStatusSelectOpen.value = val} |
| | | > |
| | | {{ |
| | | arrow: () => ( |
| | | <img |
| | | src="https://huishou-1323682843.cos.ap-nanjing.myqcloud.com/images/e120f81c-9f15-4e1a-9938-22252898edf9.png" |
| | | class={`arrow-icon ${isStatusSelectOpen.value ? 'arrow-icon--open' : ''}`} |
| | | style={{ width: '16px', height: '16px' }} |
| | | alt="arrow" |
| | | /> |
| | | ), |
| | | }} |
| | | </n-select> |
| | | ) |
| | | }, |
| | | ]) |
| | | |
| | | const columns = computed<DataTableColumns<any>>(() => [ |
| | | { title: '序号', key: 'serialNumber', width: 80, resizable: true }, |
| | | { title: '序号', key: 'serialNumber', width: 80, resizable: true, align: 'left' }, |
| | | { |
| | | title: '姓名', |
| | | key: 'nickName', |
| | | width: 150, |
| | | resizable: true, |
| | | align: 'left', |
| | | render: (row) => { |
| | | return ( |
| | | <div class="flex items-center gap-2"> |
| | |
| | | ) |
| | | }, |
| | | }, |
| | | { title: '编号', key: 'uniqueNumber', width: 120, resizable: true }, |
| | | { title: '联系电话', key: 'phoneNumber', width: 150, resizable: true }, |
| | | { title: '编号', key: 'uniqueNumber', width: 120, resizable: true, align: 'left' }, |
| | | { title: '联系电话', key: 'phoneNumber', width: 150, resizable: true, align: 'left' }, |
| | | { |
| | | title: '角色', |
| | | key: 'sysRoles', |
| | | width: 150, |
| | | resizable: true, |
| | | align: 'left', |
| | | render: (row) => ( |
| | | <div class="flex items-center gap-1"> |
| | | { |
| | |
| | | key: 'status', |
| | | width: 100, |
| | | resizable: true, |
| | | align: 'left', |
| | | render: (row) => ( |
| | | row.status ? <NTag type="primary" size="small" style={{ borderRadius: '4px' }} >启用</NTag> : <NTag type="error" size="small" style={{ borderRadius: '4px' }} >禁用</NTag> |
| | | ) |
| | | }, |
| | | { title: '创建时间', key: 'createTime', width: 180 , resizable: true, render: (row) => dayjs(row.createTime).format('YYYY-MM-DD HH:mm') }, |
| | | { title: '备注', key: 'remarks', width: 150, resizable: true, ellipsis: { tooltip: true }, render: (row) => row.remarks || '-' }, |
| | | { title: '创建时间', key: 'createTime', width: 180 , resizable: true, align: 'left', render: (row) => row.createTime ? dayjs(row.createTime).format('YYYY/MM/DD HH:mm') : '-' }, |
| | | { title: '备注', key: 'remarks', width: 150, resizable: true, align: 'left', ellipsis: { tooltip: true }, render: (row) => row.remarks || '-' }, |
| | | { |
| | | title: '操作', |
| | | key: 'actions', |
| | | width: 120, |
| | | fixed: 'right', |
| | | align: 'left', |
| | | render: (row) => ( |
| | | <div class="flex gap-3"> |
| | | <a v-permission="70111" style={{ color: '#0068FF', cursor: 'pointer' }} onClick={() => router.push(`/operations/personnel/personnelManagement/detail/${row.id}`)}>详情</a> |
| | |
| | | |
| | | <template> |
| | | <div class="roboTaxi"> |
| | | <n-card style="border-radius: 6px" content-style="padding: 12px"> |
| | | <div class="roboTaxi-form-card mb-12px"> |
| | | <n-form :model="searchModel" label-placement="left" inline :show-feedback="false"> |
| | | <SearchPanel> |
| | | <n-gi v-for="item in filterItems" :key="item.path"> |
| | |
| | | </template> |
| | | </SearchPanel> |
| | | </n-form> |
| | | </n-card> |
| | | </div> |
| | | |
| | | <n-card class="flex-1 mt-12px"> |
| | | <n-card class="flex-1 robotaxi-table-card"> |
| | | <template #header> |
| | | <n-flex justify="flex-end"> |
| | | <n-button v-permission="70112" @click="handleExport" style="width: 84px; height: 32px">导出</n-button> |
| | |
| | | @click="handleAdd">新增</n-button> |
| | | </n-flex> |
| | | </template> |
| | | <NSpace vertical> |
| | | <n-data-table :columns="columns" :data="personnelList" :loading="loading" :bordered="false" :header-height="18" |
| | | :row-height="18" /> |
| | | <Pagination :count="total" :page="pageParams.pageNum" :page-size="pageParams.pageSize" @change="changePage" /> |
| | | </NSpace> |
| | | <div class="flex-1 flex flex-col h-full"> |
| | | <n-data-table |
| | | :columns="columns" |
| | | :data="personnelList" |
| | | :loading="loading" |
| | | :bordered="false" |
| | | :scroll-x="1200" |
| | | :header-height="18" |
| | | class="flex-1" |
| | | :row-height="18" |
| | | /> |
| | | <Pagination :count="total" class="robotaxi-pagination mt-12px" :page="pageParams.pageNum" :page-size="pageParams.pageSize" @change="changePage" /> |
| | | </div> |
| | | </n-card> |
| | | |
| | | <PersonnelFormModal v-model:show="showFormModal" ref="modalRef" :mode="formMode" :roleOptions="roleOptions" |