Files
art-design/src/views/admin/vehicle/port.vue
T

363 lines
11 KiB
Vue
Raw Normal View History

2025-09-18 10:57:17 +08:00
<template>
<div class="port-page">
<div class="port-toolbar boxshadow">
<div class="toolbar-left">
<ElButton @click="showDialog('add')" v-ripple v-if="hasAuth('port@add')" type="primary"
>创建港口</ElButton
>
</div>
<div class="toolbar-right">
<el-input
v-model="keyword"
placeholder="请输入客户名称"
clearable
style="width: 260px"
@keyup.enter="getPortList"
>
<template #suffix>
<el-icon class="clickable" @click="getPortList"><Search /></el-icon>
</template>
</el-input>
</div>
</div>
<div class="boxshadow">
<ArtTable
ref="tableRef"
row-key="id"
:loading="loading"
:data="tableData"
:currentPage="pagination.currentPage"
:pageSize="pagination.pageSize"
:total="pagination.total"
@size-change="handleSizeChange"
@current-change="handleCurrentChange"
>
<template #default>
2025-10-10 10:14:26 +08:00
<!-- <ElTableColumn label="港口代码" prop="port_code" min-width="120" /> -->
2025-09-18 10:57:17 +08:00
<ElTableColumn label="港口名称" prop="port_name" min-width="150" />
2025-10-10 10:14:26 +08:00
<ElTableColumn label="英文名称" prop="port_name_en" min-width="150" />
2025-09-18 10:57:17 +08:00
<ElTableColumn label="国家" prop="country_id" min-width="140">
<template #default="scope">
<span>{{ scope.row.country_name }}</span>
</template>
</ElTableColumn>
<!-- <ElTableColumn label="纬度" prop="lat" min-width="100" /> -->
<!-- <ElTableColumn label="经度" prop="lng" min-width="100" /> -->
<ElTableColumn label="排序" prop="sort" width="80" />
<ElTableColumn label="状态" prop="status" width="100">
<template #default="scope">
<ElTag :type="scope.row.status ? 'success' : 'info'">{{
scope.row.status ? '启用' : '停用'
}}</ElTag>
</template>
</ElTableColumn>
<ElTableColumn label="创建时间" prop="created_at" min-width="160" />
<ElTableColumn fixed="right" label="操作" width="200px">
<template #default="scope">
<ElRow>
<el-button link @click="showDialog('edit', scope.row)" v-if="hasAuth('port@update')"
>编辑</el-button
>
<el-button
type="danger"
link
@click="deletePort(scope.row)"
v-if="hasAuth('port@destroy')"
>删除</el-button
>
</ElRow>
</template>
</ElTableColumn>
</template>
</ArtTable>
</div>
<ElDialog
v-model="dialogVisible"
:title="dialogType === 'add' ? '新增港口' : '编辑港口'"
align-center
width="720px"
>
<ElForm ref="formRef" :model="form" :rules="rules" label-width="110px" class="form">
<ElFormItem label="港口代码" prop="port_code">
<ElInput v-model="form.port_code" placeholder="请输入港口代码" />
</ElFormItem>
<ElFormItem label="港口名称" prop="port_name">
<ElInput v-model="form.port_name" placeholder="请输入港口名称" />
</ElFormItem>
2025-10-10 10:14:26 +08:00
<ElFormItem label="英文名称" prop="port_name_en">
<ElInput v-model="form.port_name_en" placeholder="请输入港口英文名称" />
</ElFormItem>
2025-09-18 10:57:17 +08:00
<ElFormItem label="国家" prop="country_id">
<el-select
v-model="form.country_id"
filterable
placeholder="请选择国家"
style="width: 100%"
>
<el-option
v-for="item in countryOptions"
:key="item.id"
:label="item.cn_addr"
:value="item.id"
/>
</el-select>
</ElFormItem>
<!-- <ElFormItem label="纬度" prop="lat">
<ElInput v-model="form.lat" placeholder="请输入纬度" />
</ElFormItem>
<ElFormItem label="经度" prop="lng">
<ElInput v-model="form.lng" placeholder="请输入经度" />
</ElFormItem> -->
<ElFormItem label="排序" prop="sort">
<ElInputNumber v-model="form.sort" :min="0" :max="9999" style="width: 100%" />
</ElFormItem>
<ElFormItem label="港口描述" prop="description">
<ElInput
v-model="form.description"
type="textarea"
:rows="3"
maxlength="300"
show-word-limit
placeholder="请输入港口描述"
/>
</ElFormItem>
<ElFormItem label="状态">
<ElSwitch v-model="form.status" :active-value="1" :inactive-value="0" />
</ElFormItem>
</ElForm>
<template #footer>
<div class="dialog-footer">
<ElButton @click="dialogVisible = false">取消</ElButton>
<ElButton type="primary" @click="handleSubmit(formRef)">提交</ElButton>
</div>
</template>
</ElDialog>
</div>
</template>
<script setup lang="ts">
import { ElMessage, ElMessageBox } from 'element-plus'
import type { FormInstance, FormRules } from 'element-plus'
import { vehicleService } from '@/api/vehicleApi'
import { commonService } from '@/api/commonApi'
import { useAuth } from '@/composables/useAuth'
const { hasAuth } = useAuth()
defineOptions({ name: 'AdminVehiclePort' })
const loading = ref(false)
const dialogVisible = ref(false)
const dialogType = ref<'add' | 'edit'>('add')
const formRef = ref<FormInstance>()
const keyword = ref<string>('')
const countryFilter = ref<number | undefined>(undefined)
const statusFilter = ref<number | undefined>(undefined)
const countryOptions = ref<any[]>([])
const loadCountryOptions = async () => {
try {
const res = await commonService.getCountrySelect()
countryOptions.value = res || []
} catch (e) {
countryOptions.value = []
}
}
const form = reactive<any>({
id: '',
status: 1,
sort: 0,
port_code: '',
port_name: '',
2025-10-10 10:14:26 +08:00
port_name_en: '',
2025-09-18 10:57:17 +08:00
lat: '',
lng: '',
description: '',
country_id: undefined
})
const rules = reactive<FormRules>({
port_code: [{ required: true, message: '请输入港口代码', trigger: 'blur' }],
port_name: [{ required: true, message: '请输入港口名称', trigger: 'blur' }],
country_id: [{ required: true, message: '请选择国家', trigger: 'change' }]
})
const pagination = reactive({
currentPage: 1,
pageSize: 10,
total: 0
})
const tableData = ref<any[]>([])
const tableRef = ref()
onMounted(() => {
loadCountryOptions()
getPortList()
})
watch([keyword, countryFilter, statusFilter], () => {
pagination.currentPage = 1
getPortList()
})
const getPortList = async () => {
loading.value = true
try {
const { currentPage, pageSize } = pagination
const params = {
current: currentPage,
size: pageSize,
keyword: keyword.value
}
const { records, current, size, total } = await vehicleService.getPortList(params)
tableData.value = records || []
Object.assign(pagination, { currentPage: current, pageSize: size, total })
} catch (error) {
console.error('获取港口列表失败:', error)
ElMessage.error('获取港口列表失败')
} finally {
loading.value = false
}
}
const handleSizeChange = (newPageSize: number) => {
pagination.pageSize = newPageSize
getPortList()
}
const handleCurrentChange = (newCurrentPage: number) => {
pagination.currentPage = newCurrentPage
getPortList()
}
const showDialog = (type: 'add' | 'edit', row?: any) => {
dialogVisible.value = true
dialogType.value = type
if (type === 'edit' && row) {
Object.assign(form, {
id: row.id,
status: row.status,
sort: row.sort ?? 0,
port_code: row.port_code,
port_name: row.port_name,
2025-10-10 10:14:26 +08:00
port_name_en: row.port_name_en,
2025-09-18 10:57:17 +08:00
lat: row.lat,
lng: row.lng,
description: row.description,
country_id: row.country_id
})
} else {
Object.assign(form, {
id: '',
status: 1,
sort: 0,
port_code: '',
port_name: '',
2025-10-10 10:14:26 +08:00
port_name_en: '',
2025-09-18 10:57:17 +08:00
lat: '',
lng: '',
description: '',
country_id: undefined
})
}
}
const deletePort = (row: any) => {
ElMessageBox.confirm('确定删除该港口吗?', '删除确认', {
confirmButtonText: '确定',
cancelButtonText: '取消',
type: 'error'
}).then(async () => {
try {
const { message } = await vehicleService.portDelete({ id: row.id })
ElMessage.success(message)
getPortList()
} catch (error) {
console.error('删除失败:', error)
ElMessage.error('删除失败')
}
})
}
const handleSubmit = async (formEl: FormInstance | undefined) => {
if (!formEl) return
await formEl.validate(async (valid) => {
if (!valid) return
try {
if (dialogType.value === 'add') {
const { message } = await vehicleService.portAdd({
status: form.status,
sort: form.sort,
port_code: form.port_code,
port_name: form.port_name,
2025-10-10 10:14:26 +08:00
port_name_en: form.port_name_en,
2025-09-18 10:57:17 +08:00
lat: form.lat,
lng: form.lng,
description: form.description,
country_id: form.country_id
})
ElMessage.success(message)
} else {
const { message } = await vehicleService.portEdit({
id: form.id,
status: form.status,
sort: form.sort,
port_code: form.port_code,
port_name: form.port_name,
2025-10-10 10:14:26 +08:00
port_name_en: form.port_name_en,
2025-09-18 10:57:17 +08:00
lat: form.lat,
lng: form.lng,
description: form.description,
country_id: form.country_id
})
ElMessage.success(message)
}
dialogVisible.value = false
getPortList()
} catch (error) {
console.error('操作失败:', error)
ElMessage.error('操作失败')
}
})
}
const getCountryLabel = (id: number | undefined) => {
if (!id) return '-'
const found = countryOptions.value.find((c: any) => c.id === id)
return found ? found.name : id
}
</script>
<style lang="scss" scoped>
:deep(.el-table__empty-block) {
height: 100% !important;
min-height: 200px;
display: flex;
align-items: center;
justify-content: center;
}
.port-page {
background: var(--art-main-bg-color);
min-height: 100vh;
}
.port-toolbar {
display: flex;
justify-content: space-between;
align-items: center;
margin-bottom: 16px;
padding: 20px 20px;
background: var(--art-main-bg-color);
}
.port-search-group {
display: flex;
gap: 12px;
align-items: center;
}
.form {
padding: 20px 0;
}
.dialog-footer {
text-align: right;
}
.el-col2 {
margin-bottom: 16px;
}
</style>