| | |
| | | ellipsis: true, |
| | | resizable: true, |
| | | }, |
| | | { |
| | | { |
| | | title: '车辆颜色', |
| | | align: 'left', |
| | | key: 'vehicleColor', |
| | | ellipsis: true, |
| | | resizable: true, |
| | | }, |
| | | // { |
| | | // title: '采购来源', |
| | | // align: 'left', |
| | | // key: 'procurementSource', |
| | | // ellipsis: true, |
| | | // resizable: true, |
| | | // render: (row) => <span>{row.procurementSource || '-'}</span>, |
| | | // }, |
| | | // { |
| | | // title: '运营区域', |
| | | // align: 'left', |
| | | // key: 'locationName', |
| | | // ellipsis: true, |
| | | // resizable: true, |
| | | // render: (row) => <span>{row.locationName || '-'}</span>, |
| | | // }, |
| | | { |
| | | title: '采购来源', |
| | | align: 'left', |
| | | key: 'procurementSource', |
| | | ellipsis: true, |
| | | resizable: true, |
| | | render: row => <span>{row.procurementSource || '-'}</span>, |
| | | }, |
| | | { |
| | | title: '运营区域', |
| | | align: 'left', |
| | | key: 'locationName', |
| | | ellipsis: true, |
| | | resizable: true, |
| | | render: row => <span>{row.locationName || '-'}</span>, |
| | | }, |
| | | { |
| | | title: '状态', |
| | | align: 'left', |
| | |
| | | fleetName: row.fleetName, |
| | | operationsUserName: row.operationsUserName, |
| | | phoneNumber: row.phoneNumber, |
| | | |
| | | electronicName: row.electronicName |
| | | } |
| | | fleetFormModalVisible.value = true |
| | |
| | | <!-- Footer Actions (Fixed at Bottom via Flexbox Layout) --> |
| | | <div class=" bg-white px-6 py-4 flex justify-end gap-3 border-t border-gray-100 flex-shrink-0 z-50"> |
| | | <n-button>取消</n-button> |
| | | <n-button type="primary" @click="handleSave">保存</n-button> |
| | | <n-button type="primary" @click="handleSave" v-permission="5031">保存</n-button> |
| | | </div> |
| | | </div> |
| | | </template> |
| | |
| | | <NSpace> |
| | | <NButton |
| | | text |
| | | v-permission="70212" |
| | | type='primary' |
| | | onClick={() => handleEdit(row)} |
| | | > |
| | |
| | | </NButton> |
| | | <NButton |
| | | text |
| | | v-permission="70214" |
| | | type='primary' |
| | | onClick={() => { |
| | | dialog.create({ |
| | |
| | | > |
| | | { row.status === 1 ? '禁用' : '启用' } |
| | | </NButton> |
| | | <NPopconfirm onPositiveClick={() => delteteUser(row.id!)}> |
| | | <NPopconfirm v-permission="70213" onPositiveClick={() => delteteUser(row.id!)}> |
| | | {{ |
| | | default: () => '确认删除', |
| | | trigger: () => <NButton text type="error">删除</NButton>, |
| | |
| | | |
| | | <n-card class="flex-1"> |
| | | <template #header> |
| | | <n-flex justify="flex-end"> |
| | | <n-flex justify="flex-end" v-permission="70211"> |
| | | <NButton type="primary" secondary @click="handleAdd"> |
| | | 新增打卡地 |
| | | </NButton> |
| | |
| | | <n-date-picker v-model:value="selectedMonth" placeholder="选择月份" type="month" style="width: 260px" |
| | | @update:value="handleMonthChange" /> |
| | | <div class="flex gap-2"> |
| | | <n-button style="width: 84px;height: 32px;background-color: #E6F4FF;color: #0068FF;border: 1px solid #7ABDFF;" |
| | | <n-button v-permission="70252" style="width: 84px;height: 32px;background-color: #E6F4FF;color: #0068FF;border: 1px solid #7ABDFF;" |
| | | @click="handleCopy">复制</n-button> |
| | | <n-button style="width: 84px;height: 32px;background-color: #E6F4FF;color: #0068FF;border: 1px solid #7ABDFF;" |
| | | <n-button v-permission="70253" style="width: 84px;height: 32px;background-color: #E6F4FF;color: #0068FF;border: 1px solid #7ABDFF;" |
| | | @click="handleDownload">下载表</n-button> |
| | | <n-button type="primary" style="width: 84px; height: 32px" @click="handleEdit">编辑</n-button> |
| | | <n-button v-permission="70251" type="primary" style="width: 84px; height: 32px" @click="handleEdit">编辑</n-button> |
| | | </div> |
| | | </div> |
| | | |
| | |
| | | <NSpace> |
| | | <NButton |
| | | text |
| | | v-permission="70242" |
| | | type='primary' |
| | | onClick={() => handleEdit(row)} |
| | | > |
| | | 编辑 |
| | | </NButton> |
| | | <NPopconfirm onPositiveClick={() => handleDelete(row.id!)}> |
| | | <NPopconfirm v-permission="70243" onPositiveClick={() => handleDelete(row.id!)}> |
| | | {{ |
| | | default: () => '确认删除', |
| | | trigger: () => <NButton text type="error">删除</NButton>, |
| | |
| | | |
| | | <n-card class="flex-1"> |
| | | <template #header> |
| | | <n-flex justify="flex-end"> |
| | | <n-flex justify="flex-end" v-permission="70241"> |
| | | <NButton type="primary" secondary @click="handleAdd"> |
| | | 新增班次 |
| | | </NButton> |
| | |
| | | width: 134, |
| | | fixed: 'right', |
| | | render: (row) => ( |
| | | <NButton text type="primary" onClick={() => handleViewDetail(row)}> |
| | | <NButton v-permission="70222" text type="primary" onClick={() => handleViewDetail(row)}> |
| | | 打卡明细 |
| | | </NButton> |
| | | ) |
| | |
| | | |
| | | <n-card style="border-radius: 6px; margin-top: 12px" content-style="padding: 12px"> |
| | | <template #header> |
| | | <n-flex justify="flex-end"> |
| | | <n-flex justify="flex-end" v-permission="70221"> |
| | | <NButton type="primary" secondary @click="handleExport"> |
| | | 导出 |
| | | </NButton> |
| | |
| | | <script setup lang="ts"> |
| | | import { ref, h } from 'vue' |
| | | import { useBoolean } from '@/hooks' |
| | | import type { DataTableColumns } from 'naive-ui' |
| | | import { NCheckbox } from 'naive-ui' |
| | | import { getNoticeList, updateNoticeConfig } from '@/service/api/attendance' |
| | | import { ref, h } from "vue"; |
| | | import { useBoolean } from "@/hooks"; |
| | | import type { DataTableColumns } from "naive-ui"; |
| | | import { NCheckbox } from "naive-ui"; |
| | | import { getNoticeList, updateNoticeConfig } from "@/service/api/attendance"; |
| | | |
| | | const { bool: loading, setTrue: startLoading, setFalse: endLoading } = useBoolean(false) |
| | | const { |
| | | bool: loading, |
| | | setTrue: startLoading, |
| | | setFalse: endLoading, |
| | | } = useBoolean(false); |
| | | |
| | | const tableData = ref<any[]>([]) |
| | | const tableData = ref<any[]>([]); |
| | | |
| | | const columns: DataTableColumns<any> = [ |
| | | { |
| | | title: '序号', |
| | | key: 'serialNumber', |
| | | title: "序号", |
| | | key: "serialNumber", |
| | | width: 80, |
| | | }, |
| | | { |
| | | title: '通知类型', |
| | | key: 'notificationType', |
| | | title: "通知类型", |
| | | key: "notificationType", |
| | | render: (row) => { |
| | | switch (row.notificationType) { |
| | | //通知类型 1=新增事故,2=事故即将超时提示,3=事故超时提示,4=排班信息变动,5=事故状态变更,6=新增任务,7=任务过期提示,8=版本更新提示,9=变更协议政策内容,10=变更协议内容并需用户授权,11=打卡成功通知 |
| | | case 1: |
| | | return '新增事故' |
| | | return "新增事故"; |
| | | case 2: |
| | | return '事故即将超时提示' |
| | | return "事故即将超时提示"; |
| | | case 3: |
| | | return '事故超时提示' |
| | | return "事故超时提示"; |
| | | case 4: |
| | | return '排班信息变动' |
| | | return "排班信息变动"; |
| | | case 5: |
| | | return '事故状态变更' |
| | | return "事故状态变更"; |
| | | case 6: |
| | | return '新增任务' |
| | | return "新增任务"; |
| | | case 7: |
| | | return '任务过期提示' |
| | | return "任务过期提示"; |
| | | case 8: |
| | | return '版本更新提示' |
| | | return "版本更新提示"; |
| | | case 9: |
| | | return '变更协议政策内容' |
| | | return "变更协议政策内容"; |
| | | case 10: |
| | | return '变更协议内容并需用户授权' |
| | | return "变更协议内容并需用户授权"; |
| | | case 11: |
| | | return '打卡成功通知' |
| | | return "打卡成功通知"; |
| | | default: |
| | | return row.notificationType |
| | | return row.notificationType; |
| | | } |
| | | } |
| | | }, |
| | | }, |
| | | { |
| | | title: '通知方式', |
| | | key: 'method', |
| | | title: "通知方式", |
| | | key: "method", |
| | | render: (row) => { |
| | | return h('div', { class: 'flex items-center gap-4' }, [ |
| | | h(NCheckbox, { |
| | | checked: row.isPush, |
| | | onUpdateChecked: (value: boolean) => { |
| | | row.isPush = value |
| | | } |
| | | }, { default: () => 'PUSH推送' }), |
| | | h(NCheckbox, { |
| | | checked: row.isMessage, |
| | | onUpdateChecked: (value: boolean) => { |
| | | row.isMessage = value |
| | | } |
| | | }, { default: () => '短信通知' }) |
| | | ]) |
| | | } |
| | | return h("div", { class: "flex items-center gap-4" }, [ |
| | | h( |
| | | NCheckbox, |
| | | { |
| | | checked: row.isPush, |
| | | onUpdateChecked: (value: boolean) => { |
| | | row.isPush = value; |
| | | }, |
| | | }, |
| | | { default: () => "PUSH推送" } |
| | | ), |
| | | h( |
| | | NCheckbox, |
| | | { |
| | | checked: row.isMessage, |
| | | onUpdateChecked: (value: boolean) => { |
| | | row.isMessage = value; |
| | | }, |
| | | }, |
| | | { default: () => "短信通知" } |
| | | ), |
| | | ]); |
| | | }, |
| | | }, |
| | | { |
| | | title: '更新时间', |
| | | key: 'updateTime', |
| | | } |
| | | ] |
| | | title: "更新时间", |
| | | key: "updateTime", |
| | | }, |
| | | ]; |
| | | |
| | | const handleSave = () => { |
| | | console.log('保存', tableData.value) |
| | | startLoading() |
| | | updateNoticeConfig({ notifications: tableData.value }).then((res) => { |
| | | if (res.code === 200) { |
| | | window.$message.success('保存成功') |
| | | } |
| | | }).finally(() => { |
| | | getList() |
| | | endLoading() |
| | | }) |
| | | } |
| | | console.log("保存", tableData.value); |
| | | startLoading(); |
| | | updateNoticeConfig({ notifications: tableData.value }) |
| | | .then((res) => { |
| | | if (res.code === 200) { |
| | | window.$message.success("保存成功"); |
| | | } |
| | | }) |
| | | .finally(() => { |
| | | getList(); |
| | | endLoading(); |
| | | }); |
| | | }; |
| | | |
| | | async function getList() { |
| | | startLoading() |
| | | getNoticeList().then((res) => { |
| | | tableData.value = res.data || [] |
| | | tableData.value.forEach((item: any, index: number) => { |
| | | item.serialNumber = (pageParams.value.pageNum - 1) * pageParams.value.pageSize + index + 1 |
| | | startLoading(); |
| | | getNoticeList() |
| | | .then((res) => { |
| | | tableData.value = res.data || []; |
| | | tableData.value.forEach((item: any, index: number) => { |
| | | item.serialNumber = |
| | | (pageParams.value.pageNum - 1) * pageParams.value.pageSize + |
| | | index + |
| | | 1; |
| | | }); |
| | | }) |
| | | }).finally(() => { |
| | | endLoading() |
| | | }) |
| | | .finally(() => { |
| | | endLoading(); |
| | | }); |
| | | } |
| | | |
| | | onMounted(() => { |
| | | getList() |
| | | }) |
| | | getList(); |
| | | }); |
| | | </script> |
| | | |
| | | <template> |
| | | <div class="h-full flex-col"> |
| | | <n-card style="border-radius: 6px; overflow: hidden;" |
| | | content-style="padding: 12px; height: 100%; display: flex; flex-direction: column;"> |
| | | <div style="flex: 1; overflow: auto;"> |
| | | <n-data-table :columns="columns" :data="tableData" :loading="loading" :bordered="false" :header-height="18" |
| | | :row-height="18" /> |
| | | <n-card |
| | | style="border-radius: 6px; overflow: hidden" |
| | | content-style="padding: 12px; height: 100%; display: flex; flex-direction: column;" |
| | | > |
| | | <div style="flex: 1; overflow: auto"> |
| | | <n-data-table |
| | | :columns="columns" |
| | | :data="tableData" |
| | | :loading="loading" |
| | | :bordered="false" |
| | | :header-height="18" |
| | | :row-height="18" |
| | | /> |
| | | </div> |
| | | </n-card> |
| | | |
| | | <div class="flex justify-end absolute bottom-0 left-0 right-0" |
| | | style="background-color: white; padding: 16px 24px; border-radius: 6px;"> |
| | | <n-button type="primary" style="width: 84px; height: 32px" @click="handleSave">保存</n-button> |
| | | <div |
| | | class="flex justify-end absolute bottom-0 left-0 right-0" |
| | | style="background-color: white; padding: 16px 24px; border-radius: 6px" |
| | | > |
| | | <n-button |
| | | v-permission="7041" |
| | | type="primary" |
| | | style="width: 84px; height: 32px" |
| | | @click="handleSave" |
| | | >保存</n-button |
| | | > |
| | | </div> |
| | | </div> |
| | | </template> |
| | | |
| | | <style scoped> |
| | | :deep(.n-data-table-th) { |
| | | background-color: #F4F6F8; |
| | | background-color: #f4f6f8; |
| | | } |
| | | </style> |
| | |
| | | import { useRouter } from 'vue-router' |
| | | import type { DataTableColumns } from 'naive-ui' |
| | | import { NButton, NTag, NDropdown } from 'naive-ui' |
| | | import { usePermission } from '@/hooks' |
| | | import { getOperationsUserList, exportOperationsUserTemplate, exportOperationsUser, importOperationsUser, |
| | | addOperationsUser, editOperationsUser, updateOperationsUserStatus, deleteOperationsUser } from '@/service/api/attendance' |
| | | import { fetchRoleList } from '@/service/api/fleet' |
| | |
| | | const router = useRouter() |
| | | const dialog = useDialog() |
| | | const { bool: loading, setTrue: startLoading, setFalse: endLoading } = useBoolean(false) |
| | | const { hasPermission } = usePermission() |
| | | |
| | | const searchModel = ref({ |
| | | nickName: '', |
| | |
| | | { |
| | | label: '编辑', |
| | | key: 'edit', |
| | | show: hasPermission(70115), |
| | | props: { |
| | | onClick: () => handleEdit(row) |
| | | } |
| | |
| | | { |
| | | label: row.status ? '禁用' : '启用', |
| | | key: 'toggle', |
| | | show: hasPermission(70116), |
| | | props: { |
| | | onClick: () => { |
| | | updateOperationsUserStatus({ |
| | |
| | | { |
| | | label: '重置密码', |
| | | key: 'password', |
| | | show: hasPermission(70117), |
| | | props: { |
| | | onClick: () => { |
| | | handleResetPassword(row) |
| | |
| | | { |
| | | label: '删除', |
| | | key: 'delete', |
| | | show: hasPermission(70118), |
| | | props: { |
| | | onClick: () => { |
| | | dialog.create({ |
| | |
| | | fixed: 'right', |
| | | render: (row) => ( |
| | | <div class="flex gap-3"> |
| | | <a style={{ color: '#0068FF', cursor: 'pointer' }} onClick={() => router.push(`/operations/personnel/personnelManagement/detail/${row.id}`)}>详情</a> |
| | | <a v-permission="70111" style={{ color: '#0068FF', cursor: 'pointer' }} onClick={() => router.push(`/operations/personnel/personnelManagement/detail/${row.id}`)}>详情</a> |
| | | <NDropdown options={moreOptions(row)} trigger="click"> |
| | | <a style={{ color: '#0068FF', cursor: 'pointer' }}>更多</a> |
| | | </NDropdown> |
| | |
| | | <n-card class="flex-1 mt-12px"> |
| | | <template #header> |
| | | <n-flex justify="flex-end"> |
| | | <n-button @click="handleExport" style="width: 84px; height: 32px">导出</n-button> |
| | | <n-button @click="handleImport" style="width: 84px; height: 32px">导入</n-button> |
| | | <n-button @click="handleDownloadTemplate" style="width: 84px; height: 32px">下载模板</n-button> |
| | | <n-button style="width: 84px;height: 32px;background-color: #E6F4FF;color: #0068FF;border: 1px solid #7ABDFF;" |
| | | <n-button v-permission="70112" @click="handleExport" style="width: 84px; height: 32px">导出</n-button> |
| | | <n-button v-permission="70113" @click="handleImport" style="width: 84px; height: 32px">导入</n-button> |
| | | <n-button v-permission="70112" @click="handleDownloadTemplate" style="width: 84px; height: 32px">下载模板</n-button> |
| | | <n-button v-permission="70114" style="width: 84px;height: 32px;background-color: #E6F4FF;color: #0068FF;border: 1px solid #7ABDFF;" |
| | | @click="handleAdd">新增</n-button> |
| | | </n-flex> |
| | | </template> |
| | |
| | | <NSpace> |
| | | {(row.status === 0 || row.status === 1) && <NButton |
| | | text |
| | | v-permission="7053" |
| | | type='primary' |
| | | onClick={() => modalRef.value.openModal(row.id)} |
| | | > |
| | |
| | | </NButton>} |
| | | <NButton |
| | | text |
| | | v-permission="7054" |
| | | type='primary' |
| | | onClick={() => detailModalRef.value.openModal(row.id)} |
| | | > |
| | | 详情 |
| | | </NButton> |
| | | <NPopconfirm onPositiveClick={() => handleDeltete(row.id!)}> |
| | | <NPopconfirm v-permission="7055" onPositiveClick={() => handleDeltete(row.id!)}> |
| | | {{ |
| | | default: () => '确认删除', |
| | | trigger: () => <NButton text type="error">删除</NButton>, |
| | |
| | | <n-card style="border-radius: 6px; margin-top: 12px" content-style="padding: 12px"> |
| | | <template #header> |
| | | <n-flex justify="flex-end"> |
| | | <n-button @click="handleExport" style="width: 84px; height: 32px">导出</n-button> |
| | | <NButton type="primary" secondary @click="handleAdd"> |
| | | <n-button v-permission="7051" @click="handleExport" style="width: 84px; height: 32px">导出</n-button> |
| | | <NButton v-permission="7052" type="primary" secondary @click="handleAdd"> |
| | | 新增任务 |
| | | </NButton> |
| | | </n-flex> |
| | |
| | | <script setup lang="ts"> |
| | | import { ref, h, onMounted } from "vue"; |
| | | <script setup lang="tsx"> |
| | | import { ref, onMounted } from "vue"; |
| | | import type { DataTableColumns } from "naive-ui"; |
| | | import { NButton, NTag, NAvatar, NImage } from "naive-ui"; |
| | | import { useBoolean } from "@/hooks"; |
| | |
| | | align: "center", |
| | | render: (row) => { |
| | | const displayName = row.nickName || "-"; |
| | | return h("div", { class: "flex items-center justify-center gap-2" }, [ |
| | | h( |
| | | NAvatar, |
| | | { |
| | | round: true, |
| | | size: 32, |
| | | style: { backgroundColor: "#e0e0e0" }, |
| | | src: row.avatar || undefined, |
| | | }, |
| | | { default: () => displayName.charAt(0) } |
| | | ), |
| | | h("span", displayName), |
| | | ]); |
| | | return ( |
| | | <div class="flex items-center justify-center gap-2"> |
| | | <NAvatar |
| | | round |
| | | size={32} |
| | | style={{ backgroundColor: "#e0e0e0" }} |
| | | src={row.avatar || undefined} |
| | | > |
| | | {displayName.charAt(0)} |
| | | </NAvatar> |
| | | <span>{displayName}</span> |
| | | </div> |
| | | ); |
| | | }, |
| | | }, |
| | | { |
| | |
| | | const roleName = Array.isArray(row.roleNames) |
| | | ? row.roleNames.join("、") |
| | | : row.roleNames || "-"; |
| | | return h( |
| | | NTag, |
| | | { type: "info", size: "small" }, |
| | | { |
| | | default: () => roleName, |
| | | } |
| | | return ( |
| | | <NTag type="info" size="small"> |
| | | {roleName} |
| | | </NTag> |
| | | ); |
| | | }, |
| | | }, |
| | |
| | | render: (row) => { |
| | | const statusText = auditStatusLabelMap[row.auditStatus]; |
| | | const tagType = auditStatusTagTypeMap[row.auditStatus]; |
| | | return h( |
| | | NTag, |
| | | { type: tagType as any, size: "small" }, |
| | | { |
| | | default: () => statusText, |
| | | } |
| | | return ( |
| | | <NTag type={tagType as any} size="small"> |
| | | {statusText} |
| | | </NTag> |
| | | ); |
| | | }, |
| | | }, |
| | |
| | | if (row.idCardFront && row.idCardBack) { |
| | | const idCardFront = JSON.parse(row.idCardFront).url; |
| | | const idCardBack = JSON.parse(row.idCardBack).url; |
| | | return h("div", { class: "flex gap-1 justify-center" }, [ |
| | | h(NImage, { |
| | | width: 60, |
| | | height: 40, |
| | | src: idCardFront, |
| | | objectFit: "cover", |
| | | style: { borderRadius: "4px" }, |
| | | previewSrc: idCardFront, |
| | | }), |
| | | h(NImage, { |
| | | width: 60, |
| | | height: 40, |
| | | src: idCardBack, |
| | | objectFit: "cover", |
| | | style: { borderRadius: "4px" }, |
| | | previewSrc: idCardBack, |
| | | }), |
| | | ]); |
| | | return ( |
| | | <div class="flex gap-1 justify-center"> |
| | | <NImage |
| | | width={60} |
| | | height={40} |
| | | src={idCardFront} |
| | | objectFit="cover" |
| | | style={{ borderRadius: "4px" }} |
| | | previewSrc={idCardFront} |
| | | /> |
| | | <NImage |
| | | width={60} |
| | | height={40} |
| | | src={idCardBack} |
| | | objectFit="cover" |
| | | style={{ borderRadius: "4px" }} |
| | | previewSrc={idCardBack} |
| | | /> |
| | | </div> |
| | | ); |
| | | } |
| | | return h( |
| | | "div", |
| | | { |
| | | class: "flex gap-1 justify-center", |
| | | }, |
| | | [ |
| | | h( |
| | | "div", |
| | | { |
| | | style: { |
| | | width: "60px", |
| | | height: "40px", |
| | | backgroundColor: "#f0f0f0", |
| | | borderRadius: "4px", |
| | | display: "flex", |
| | | alignItems: "center", |
| | | justifyContent: "center", |
| | | }, |
| | | }, |
| | | "📷" |
| | | ), |
| | | h( |
| | | "div", |
| | | { |
| | | style: { |
| | | width: "60px", |
| | | height: "40px", |
| | | backgroundColor: "#f0f0f0", |
| | | borderRadius: "4px", |
| | | display: "flex", |
| | | alignItems: "center", |
| | | justifyContent: "center", |
| | | }, |
| | | }, |
| | | "📷" |
| | | ), |
| | | ] |
| | | return ( |
| | | <div class="flex gap-1 justify-center"> |
| | | <div |
| | | style={{ |
| | | width: "60px", |
| | | height: "40px", |
| | | backgroundColor: "#f0f0f0", |
| | | borderRadius: "4px", |
| | | display: "flex", |
| | | alignItems: "center", |
| | | justifyContent: "center", |
| | | }} |
| | | > |
| | | 📷 |
| | | </div> |
| | | <div |
| | | style={{ |
| | | width: "60px", |
| | | height: "40px", |
| | | backgroundColor: "#f0f0f0", |
| | | borderRadius: "4px", |
| | | display: "flex", |
| | | alignItems: "center", |
| | | justifyContent: "center", |
| | | }} |
| | | > |
| | | 📷 |
| | | </div> |
| | | </div> |
| | | ); |
| | | }, |
| | | }, |
| | |
| | | render: (row) => { |
| | | if (row.driverLicense) { |
| | | const driverLicense = JSON.parse(row.driverLicense).url; |
| | | return h(NImage, { |
| | | width: 60, |
| | | height: 40, |
| | | src: driverLicense, |
| | | objectFit: "cover", |
| | | style: { borderRadius: "4px" }, |
| | | previewSrc: driverLicense, |
| | | }); |
| | | return ( |
| | | <NImage |
| | | width={60} |
| | | height={40} |
| | | src={driverLicense} |
| | | objectFit="cover" |
| | | style={{ borderRadius: "4px" }} |
| | | previewSrc={driverLicense} |
| | | /> |
| | | ); |
| | | } |
| | | return h( |
| | | "div", |
| | | { |
| | | style: { |
| | | return ( |
| | | <div |
| | | style={{ |
| | | width: "60px", |
| | | height: "40px", |
| | | backgroundColor: "#f0f0f0", |
| | |
| | | alignItems: "center", |
| | | justifyContent: "center", |
| | | margin: "0 auto", |
| | | }, |
| | | }, |
| | | "📷" |
| | | }} |
| | | > |
| | | 📷 |
| | | </div> |
| | | ); |
| | | }, |
| | | }, |
| | |
| | | const certificateOfNoCriminalRecord = JSON.parse( |
| | | row.certificateOfNoCriminalRecord |
| | | ).url; |
| | | return h(NImage, { |
| | | width: 60, |
| | | height: 40, |
| | | src: certificateOfNoCriminalRecord, |
| | | objectFit: "cover", |
| | | style: { borderRadius: "4px" }, |
| | | previewSrc: certificateOfNoCriminalRecord, |
| | | }); |
| | | return ( |
| | | <NImage |
| | | width={60} |
| | | height={40} |
| | | src={certificateOfNoCriminalRecord} |
| | | objectFit="cover" |
| | | style={{ borderRadius: "4px" }} |
| | | previewSrc={certificateOfNoCriminalRecord} |
| | | /> |
| | | ); |
| | | } |
| | | return h( |
| | | "div", |
| | | { |
| | | style: { |
| | | return ( |
| | | <div |
| | | style={{ |
| | | width: "60px", |
| | | height: "40px", |
| | | backgroundColor: "#f0f0f0", |
| | |
| | | alignItems: "center", |
| | | justifyContent: "center", |
| | | margin: "0 auto", |
| | | }, |
| | | }, |
| | | "📷" |
| | | }} |
| | | > |
| | | 📷 |
| | | </div> |
| | | ); |
| | | }, |
| | | }, |
| | |
| | | align: "center", |
| | | fixed: "right", |
| | | render: (row) => { |
| | | return h("div", { class: "flex items-center justify-center gap-2" }, [ |
| | | row.auditStatus === 1 |
| | | ? h( |
| | | NButton, |
| | | { |
| | | text: true, |
| | | type: "primary", |
| | | onClick: () => handleApprove(row.id), |
| | | }, |
| | | { default: () => "审核" } |
| | | ) |
| | | : null, |
| | | h( |
| | | NButton, |
| | | { |
| | | text: true, |
| | | type: "error", |
| | | onClick: () => handleDelete(row.id), |
| | | }, |
| | | { default: () => "删除" } |
| | | ), |
| | | ]); |
| | | return ( |
| | | <div class="flex items-center justify-center gap-2"> |
| | | {row.auditStatus === 1 ? ( |
| | | <NButton |
| | | v-permission="80112" |
| | | text |
| | | type="primary" |
| | | onClick={() => handleApprove(row.id)} |
| | | > |
| | | 审核 |
| | | </NButton> |
| | | ) : null} |
| | | <NButton |
| | | v-permission="80113" |
| | | text |
| | | type="error" |
| | | onClick={() => handleDelete(row.id)} |
| | | > |
| | | 删除 |
| | | </NButton> |
| | | </div> |
| | | ); |
| | | }, |
| | | }, |
| | | ]; |
| | |
| | | > |
| | | <div class="mb-4 flex justify-end gap-2"> |
| | | <n-button |
| | | v-permission="80111" |
| | | style=" |
| | | width: 84px; |
| | | height: 32px; |
| | |
| | | <script setup lang="ts"> |
| | | <script setup lang="tsx"> |
| | | import { ref, h, onMounted } from "vue"; |
| | | import type { DataTableColumns } from "naive-ui"; |
| | | import { NButton, NTag, NTooltip } from "naive-ui"; |
| | |
| | | align: "center", |
| | | fixed: "right", |
| | | render: (row) => { |
| | | return h("div", { class: "flex items-center justify-center gap-2" }, [ |
| | | row.auditStatus === 1 |
| | | ? h( |
| | | NButton, |
| | | { |
| | | text: true, |
| | | type: "primary", |
| | | onClick: () => handleApprove(row.id), |
| | | }, |
| | | { default: () => "审核" } |
| | | ) |
| | | : null, |
| | | h( |
| | | NButton, |
| | | { |
| | | text: true, |
| | | type: "error", |
| | | onClick: () => handleDelete(row.id), |
| | | }, |
| | | { default: () => "删除" } |
| | | ), |
| | | ]); |
| | | return ( |
| | | <div class="flex items-center justify-center gap-2"> |
| | | {row.auditStatus === 1 ? ( |
| | | <NButton |
| | | v-permission="80122" |
| | | text |
| | | type="primary" |
| | | onClick={() => handleApprove(row.id)} |
| | | > |
| | | 审核 |
| | | </NButton> |
| | | ) : null} |
| | | <NButton |
| | | v-permission="80123" |
| | | text |
| | | type="error" |
| | | onClick={() => handleDelete(row.id)} |
| | | > |
| | | 删除 |
| | | </NButton> |
| | | </div> |
| | | ); |
| | | }, |
| | | }, |
| | | ]; |
| | |
| | | positiveText: "确定", |
| | | negativeText: "取消", |
| | | onPositiveClick: async () => { |
| | | const { error } = await deletePolicyApplicationById(id); |
| | | if (!error) { |
| | | const res = await deletePolicyApplicationById(id); |
| | | if (res.code === 200) { |
| | | window.$message?.success("删除成功"); |
| | | getPolicyApplicationList(); |
| | | } else { |
| | |
| | | |
| | | const handleConfirmReview = async (data: any) => { |
| | | const auditStatus = data?.result === "pass" ? 2 : 3; |
| | | const { error } = await batchAuditPolicyApplication({ |
| | | const res = await batchAuditPolicyApplication({ |
| | | auditStatus, |
| | | ids: selectedIds.value, |
| | | auditRemarks: data?.auditRemarks || "", |
| | | }); |
| | | if (!error) { |
| | | if (res.code === 200) { |
| | | window.$message?.success("审核成功"); |
| | | selectedIds.value = []; |
| | | getPolicyApplicationList(); |
| | |
| | | > |
| | | <div class="mb-4 flex justify-end gap-2"> |
| | | <n-button |
| | | v-permission="80121" |
| | | style=" |
| | | width: 84px; |
| | | height: 32px; |
| | |
| | | :data="tableData" |
| | | :loading="loading" |
| | | :scroll-x="1500" |
| | | :row-key="(row: PolicyApplicationItem) => row.id" |
| | | :row-key="(row: any) => row.id" |
| | | @update:checked-row-keys="handleCheck" |
| | | /> |
| | | <Pagination :count="count" @change="changePage" /> |
| | |
| | | <script setup lang="ts"> |
| | | <script setup lang="tsx"> |
| | | import { ref, h, computed, onMounted } from "vue"; |
| | | import type { DataTableColumns, FormInst, FormRules } from "naive-ui"; |
| | | import { NButton } from "naive-ui"; |
| | |
| | | key: "actions", |
| | | width: 160, |
| | | align: "center", |
| | | render: (row) => |
| | | h("div", { class: "flex items-center justify-center gap-2" }, [ |
| | | h( |
| | | NButton, |
| | | { |
| | | text: true, |
| | | type: "primary", |
| | | onClick: () => handleEdit(row), |
| | | }, |
| | | { default: () => "编辑" } |
| | | ), |
| | | h( |
| | | NButton, |
| | | { |
| | | text: true, |
| | | type: "error", |
| | | onClick: () => handleDelete(row), |
| | | }, |
| | | { default: () => "删除" } |
| | | ), |
| | | ]), |
| | | render: (row) => { |
| | | return ( |
| | | <div class="flex items-center justify-center gap-2"> |
| | | <NButton |
| | | v-permission="80232" |
| | | text |
| | | type="primary" |
| | | onClick={() => handleEdit(row)} |
| | | > |
| | | 编辑 |
| | | </NButton> |
| | | <NButton |
| | | v-permission="8023" |
| | | text |
| | | type="error" |
| | | onClick={() => handleDelete(row)} |
| | | > |
| | | 删除 |
| | | </NButton> |
| | | </div> |
| | | ); |
| | | }, |
| | | }, |
| | | ]; |
| | | |
| | |
| | | await formRef.value?.validate(); |
| | | const payload = { feedbackType: formModel.value.feedbackType }; |
| | | if (modalMode.value === "add") { |
| | | const { error } = await saveFeedbackType(payload); |
| | | if (!error) { |
| | | const res = await saveFeedbackType(payload); |
| | | if (res.code === 200) { |
| | | window.$message?.success("新增成功"); |
| | | modalVisible.value = false; |
| | | getFeedbackTypeList(); |
| | |
| | | } |
| | | return; |
| | | } |
| | | const { error } = await updateFeedbackType({ |
| | | const res = await updateFeedbackType({ |
| | | id: formModel.value.id as number, |
| | | ...payload, |
| | | }); |
| | | if (!error) { |
| | | if (res.code === 200) { |
| | | window.$message?.success("编辑成功"); |
| | | modalVisible.value = false; |
| | | getFeedbackTypeList(); |
| | |
| | | positiveText: "确定", |
| | | negativeText: "取消", |
| | | onPositiveClick: async () => { |
| | | const { error } = await deleteFeedbackType(row.id); |
| | | if (!error) { |
| | | const res = await deleteFeedbackType(row.id); |
| | | if (res.code === 200) { |
| | | window.$message?.success("删除成功"); |
| | | getFeedbackTypeList(); |
| | | } else { |
| | |
| | | > |
| | | <div class="mb-4 flex justify-end gap-2"> |
| | | <n-button |
| | | v-permission="80221" |
| | | style=" |
| | | width: 84px; |
| | | height: 32px; |
| | |
| | | <script setup lang="ts"> |
| | | <script setup lang="tsx"> |
| | | import { ref, h, onMounted } from "vue"; |
| | | import type { DataTableColumns } from "naive-ui"; |
| | | import { NButton } from "naive-ui"; |
| | |
| | | width: 260, |
| | | align: "center", |
| | | render: (row) => { |
| | | const buttons = [ |
| | | h( |
| | | NButton, |
| | | { text: true, type: "primary", onClick: () => handleView(row) }, |
| | | { default: () => "详情" } |
| | | ), |
| | | ]; |
| | | if ([1,2].includes(row.handleStatus)) { |
| | | buttons.push( |
| | | h( |
| | | NButton, |
| | | { text: true, type: "primary", onClick: () => handleStart(row) }, |
| | | { default: () => "处理" } |
| | | ) |
| | | ); |
| | | } |
| | | buttons.push( |
| | | h( |
| | | NButton, |
| | | { text: true, type: "primary", onClick: () => handleEdit(row) }, |
| | | { default: () => "编辑" } |
| | | ), |
| | | h( |
| | | NButton, |
| | | { text: true, type: "error", onClick: () => handleDelete(row) }, |
| | | { default: () => "删除" } |
| | | ) |
| | | ); |
| | | return h( |
| | | "div", |
| | | { class: "flex items-center justify-center gap-2" }, |
| | | buttons |
| | | return ( |
| | | <div class="flex items-center justify-center gap-2"> |
| | | <NButton |
| | | v-permission="80212" |
| | | text |
| | | type="primary" |
| | | onClick={() => handleView(row)} |
| | | > |
| | | 详情 |
| | | </NButton> |
| | | {[1, 2].includes(row.handleStatus || 0) ? ( |
| | | <NButton |
| | | v-permission="80213" |
| | | text |
| | | type="primary" |
| | | onClick={() => handleStart(row)} |
| | | > |
| | | 处理 |
| | | </NButton> |
| | | ) : null} |
| | | <NButton |
| | | v-permission="80215" |
| | | text |
| | | type="primary" |
| | | onClick={() => handleEdit(row)} |
| | | > |
| | | 编辑 |
| | | </NButton> |
| | | <NButton |
| | | v-permission="80216" |
| | | text |
| | | type="error" |
| | | onClick={() => handleDelete(row)} |
| | | > |
| | | 删除 |
| | | </NButton> |
| | | </div> |
| | | ); |
| | | }, |
| | | }, |
| | |
| | | } |
| | | |
| | | function handleStart(row: WorkOrderItem) { |
| | | handleRow.value = row; |
| | | handleModalVisible.value = true; |
| | | } |
| | | |
| | | function handleProcess(row: WorkOrderItem) { |
| | | handleRow.value = row; |
| | | handleModalVisible.value = true; |
| | | } |
| | |
| | | positiveText: "确定", |
| | | negativeText: "取消", |
| | | onPositiveClick: async () => { |
| | | const { error } = await deleteWorkOrder(row.id); |
| | | if (!error) { |
| | | const res = await deleteWorkOrder(row.id); |
| | | if (res.code === 200) { |
| | | window.$message?.success("删除成功"); |
| | | getWorkOrderList(); |
| | | } else { |
| | |
| | | > |
| | | <div class="mb-4 flex justify-end gap-2"> |
| | | <n-button |
| | | v-permission="80211" |
| | | style=" |
| | | width: 96px; |
| | | height: 32px; |