no message
This commit is contained in:
@@ -0,0 +1,74 @@
|
||||
<template>
|
||||
<div class="page-container">
|
||||
<el-card v-loading="loading">
|
||||
<template #header>
|
||||
<div class="header-row">
|
||||
<span>车主详情</span>
|
||||
<div>
|
||||
<el-button type="warning" @click="handleEdit">编辑</el-button>
|
||||
<el-button @click="handleBack">返回</el-button>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<el-descriptions :column="2" border v-if="detail">
|
||||
<el-descriptions-item label="ID">{{ detail.id }}</el-descriptions-item>
|
||||
<el-descriptions-item label="姓名">{{ detail.name }}</el-descriptions-item>
|
||||
<el-descriptions-item label="身份证号">{{ detail.id_number }}</el-descriptions-item>
|
||||
<el-descriptions-item label="联系电话">{{ detail.phone }}</el-descriptions-item>
|
||||
<el-descriptions-item label="联系地址" :span="2">{{ detail.address || '-' }}</el-descriptions-item>
|
||||
<el-descriptions-item label="创建时间">{{ formatDate(detail.created_at) }}</el-descriptions-item>
|
||||
<el-descriptions-item label="更新时间">{{ formatDate(detail.updated_at) }}</el-descriptions-item>
|
||||
</el-descriptions>
|
||||
</el-card>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { ref, onMounted } from 'vue'
|
||||
import { useRouter, useRoute } from 'vue-router'
|
||||
import { ElMessage } from 'element-plus'
|
||||
import { getCustomer } from '../../api/customer'
|
||||
import type { Customer } from '../../types'
|
||||
|
||||
const router = useRouter()
|
||||
const route = useRoute()
|
||||
const loading = ref(false)
|
||||
const detail = ref<Customer | null>(null)
|
||||
|
||||
function formatDate(dateStr: string) {
|
||||
if (!dateStr) return ''
|
||||
const d = new Date(dateStr)
|
||||
return d.toLocaleString('zh-CN', { hour12: false })
|
||||
}
|
||||
|
||||
async function loadDetail() {
|
||||
loading.value = true
|
||||
try {
|
||||
const res = await getCustomer(Number(route.params.id))
|
||||
detail.value = res.data
|
||||
} catch (e: any) {
|
||||
ElMessage.error(e.message || '获取车主信息失败')
|
||||
} finally {
|
||||
loading.value = false
|
||||
}
|
||||
}
|
||||
|
||||
function handleEdit() {
|
||||
router.push(`/customers/${route.params.id}/edit`)
|
||||
}
|
||||
|
||||
function handleBack() {
|
||||
router.push('/customers')
|
||||
}
|
||||
|
||||
onMounted(loadDetail)
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
.header-row {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
}
|
||||
</style>
|
||||
@@ -0,0 +1,130 @@
|
||||
<template>
|
||||
<div class="page-container">
|
||||
<el-card>
|
||||
<template #header>
|
||||
<span>{{ isEdit ? '编辑车主' : '新增车主' }}</span>
|
||||
</template>
|
||||
|
||||
<el-form
|
||||
ref="formRef"
|
||||
:model="form"
|
||||
:rules="rules"
|
||||
label-width="100px"
|
||||
style="max-width: 600px"
|
||||
>
|
||||
<el-form-item label="姓名" prop="name">
|
||||
<el-input v-model="form.name" placeholder="请输入车主姓名" />
|
||||
</el-form-item>
|
||||
|
||||
<el-form-item label="身份证号" prop="id_number">
|
||||
<el-input v-model="form.id_number" placeholder="请输入18位身份证号" />
|
||||
</el-form-item>
|
||||
|
||||
<el-form-item label="联系电话" prop="phone">
|
||||
<el-input v-model="form.phone" placeholder="请输入11位手机号" />
|
||||
</el-form-item>
|
||||
|
||||
<el-form-item label="联系地址" prop="address">
|
||||
<el-input v-model="form.address" type="textarea" :rows="3" placeholder="请输入联系地址" />
|
||||
</el-form-item>
|
||||
|
||||
<el-form-item>
|
||||
<el-button type="primary" :loading="submitting" @click="handleSubmit">
|
||||
{{ isEdit ? '保存修改' : '新增' }}
|
||||
</el-button>
|
||||
<el-button @click="handleBack">返回</el-button>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
</el-card>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { ref, reactive, computed, onMounted } from 'vue'
|
||||
import { useRouter, useRoute } from 'vue-router'
|
||||
import { ElMessage } from 'element-plus'
|
||||
import type { FormInstance, FormRules } from 'element-plus'
|
||||
import { getCustomer, createCustomer, updateCustomer } from '../../api/customer'
|
||||
|
||||
const router = useRouter()
|
||||
const route = useRoute()
|
||||
const formRef = ref<FormInstance>()
|
||||
|
||||
const isEdit = computed(() => !!route.params.id)
|
||||
|
||||
const form = reactive({
|
||||
name: '',
|
||||
id_number: '',
|
||||
phone: '',
|
||||
address: '',
|
||||
})
|
||||
|
||||
const rules: FormRules = {
|
||||
name: [{ required: true, message: '请输入车主姓名', trigger: 'blur' }],
|
||||
id_number: [
|
||||
{ required: true, message: '请输入身份证号', trigger: 'blur' },
|
||||
{
|
||||
pattern: /^\d{17}[\dXx]$/,
|
||||
message: '身份证号格式不正确',
|
||||
trigger: 'blur',
|
||||
},
|
||||
],
|
||||
phone: [
|
||||
{ required: true, message: '请输入联系电话', trigger: 'blur' },
|
||||
{
|
||||
pattern: /^1[3-9]\d{9}$/,
|
||||
message: '手机号格式不正确',
|
||||
trigger: 'blur',
|
||||
},
|
||||
],
|
||||
}
|
||||
|
||||
const submitting = ref(false)
|
||||
|
||||
async function loadDetail() {
|
||||
const id = Number(route.params.id)
|
||||
try {
|
||||
const res = await getCustomer(id)
|
||||
Object.assign(form, {
|
||||
name: res.data.name,
|
||||
id_number: res.data.id_number,
|
||||
phone: res.data.phone,
|
||||
address: res.data.address || '',
|
||||
})
|
||||
} catch (e: any) {
|
||||
ElMessage.error(e.message || '获取车主信息失败')
|
||||
}
|
||||
}
|
||||
|
||||
async function handleSubmit() {
|
||||
if (!formRef.value) return
|
||||
const valid = await formRef.value.validate().catch(() => false)
|
||||
if (!valid) return
|
||||
|
||||
submitting.value = true
|
||||
try {
|
||||
if (isEdit.value) {
|
||||
await updateCustomer(Number(route.params.id), { ...form })
|
||||
ElMessage.success('保存成功')
|
||||
} else {
|
||||
await createCustomer({ ...form })
|
||||
ElMessage.success('新增成功')
|
||||
}
|
||||
router.push('/customers')
|
||||
} catch (e: any) {
|
||||
ElMessage.error(e.message || '操作失败')
|
||||
} finally {
|
||||
submitting.value = false
|
||||
}
|
||||
}
|
||||
|
||||
function handleBack() {
|
||||
router.push('/customers')
|
||||
}
|
||||
|
||||
onMounted(() => {
|
||||
if (isEdit.value) {
|
||||
loadDetail()
|
||||
}
|
||||
})
|
||||
</script>
|
||||
@@ -0,0 +1,152 @@
|
||||
<template>
|
||||
<div class="page-container">
|
||||
<el-card>
|
||||
<div class="toolbar">
|
||||
<el-input
|
||||
v-model="keyword"
|
||||
placeholder="搜索姓名/身份证号/手机号"
|
||||
clearable
|
||||
style="width: 300px"
|
||||
@keyup.enter="handleSearch"
|
||||
@clear="handleSearch"
|
||||
>
|
||||
<template #prefix>
|
||||
<el-icon><Search /></el-icon>
|
||||
</template>
|
||||
</el-input>
|
||||
<el-button type="primary" @click="handleSearch">
|
||||
<el-icon><Search /></el-icon> 查询
|
||||
</el-button>
|
||||
<el-button type="success" @click="handleCreate">
|
||||
<el-icon><Plus /></el-icon> 新增车主
|
||||
</el-button>
|
||||
</div>
|
||||
|
||||
<el-table :data="tableData" v-loading="loading" stripe border>
|
||||
<el-table-column prop="id" label="ID" width="70" align="center" />
|
||||
<el-table-column prop="name" label="姓名" width="120" />
|
||||
<el-table-column prop="id_number" label="身份证号" width="200" />
|
||||
<el-table-column prop="phone" label="联系电话" width="140" />
|
||||
<el-table-column prop="address" label="联系地址" show-overflow-tooltip />
|
||||
<el-table-column prop="created_at" label="创建时间" width="180">
|
||||
<template #default="{ row }">
|
||||
{{ formatDate(row.created_at) }}
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="操作" width="220" align="center">
|
||||
<template #default="{ row }">
|
||||
<el-button type="primary" link @click="handleDetail(row)">详情</el-button>
|
||||
<el-button type="warning" link @click="handleEdit(row)">编辑</el-button>
|
||||
<el-button type="danger" link @click="handleDelete(row)">删除</el-button>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
|
||||
<el-pagination
|
||||
class="pagination"
|
||||
v-model:current-page="page"
|
||||
v-model:page-size="pageSize"
|
||||
:total="total"
|
||||
:page-sizes="[10, 20, 50]"
|
||||
layout="total, sizes, prev, pager, next, jumper"
|
||||
@current-change="fetchData"
|
||||
@size-change="handleSizeChange"
|
||||
/>
|
||||
</el-card>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { ref, onMounted } from 'vue'
|
||||
import { useRouter } from 'vue-router'
|
||||
import { ElMessage, ElMessageBox } from 'element-plus'
|
||||
import { getCustomers, deleteCustomer } from '../../api/customer'
|
||||
import type { Customer } from '../../types'
|
||||
|
||||
const router = useRouter()
|
||||
const loading = ref(false)
|
||||
const tableData = ref<Customer[]>([])
|
||||
const keyword = ref('')
|
||||
const page = ref(1)
|
||||
const pageSize = ref(10)
|
||||
const total = ref(0)
|
||||
|
||||
function formatDate(dateStr: string) {
|
||||
if (!dateStr) return ''
|
||||
const d = new Date(dateStr)
|
||||
return d.toLocaleString('zh-CN', { hour12: false })
|
||||
}
|
||||
|
||||
async function fetchData() {
|
||||
loading.value = true
|
||||
try {
|
||||
const res = await getCustomers({
|
||||
keyword: keyword.value,
|
||||
page: page.value,
|
||||
pageSize: pageSize.value,
|
||||
})
|
||||
tableData.value = res.data.list
|
||||
total.value = res.data.total
|
||||
} catch (e: any) {
|
||||
ElMessage.error(e.message || '获取车主列表失败')
|
||||
} finally {
|
||||
loading.value = false
|
||||
}
|
||||
}
|
||||
|
||||
function handleSearch() {
|
||||
page.value = 1
|
||||
fetchData()
|
||||
}
|
||||
|
||||
function handleSizeChange() {
|
||||
page.value = 1
|
||||
fetchData()
|
||||
}
|
||||
|
||||
function handleCreate() {
|
||||
router.push('/customers/create')
|
||||
}
|
||||
|
||||
function handleDetail(row: Customer) {
|
||||
router.push(`/customers/${row.id}`)
|
||||
}
|
||||
|
||||
function handleEdit(row: Customer) {
|
||||
router.push(`/customers/${row.id}/edit`)
|
||||
}
|
||||
|
||||
async function handleDelete(row: Customer) {
|
||||
try {
|
||||
await ElMessageBox.confirm(`确定删除车主"${row.name}"吗?`, '删除确认', {
|
||||
type: 'warning',
|
||||
confirmButtonText: '确定',
|
||||
cancelButtonText: '取消',
|
||||
})
|
||||
await deleteCustomer(row.id)
|
||||
ElMessage.success('删除成功')
|
||||
fetchData()
|
||||
} catch (e: any) {
|
||||
if (e !== 'cancel' && e !== 'close') {
|
||||
ElMessage.error(e.message || '删除失败')
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
onMounted(fetchData)
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
.toolbar {
|
||||
display: flex;
|
||||
gap: 12px;
|
||||
margin-bottom: 16px;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.pagination {
|
||||
margin-top: 16px;
|
||||
display: flex;
|
||||
justify-content: flex-end;
|
||||
}
|
||||
</style>
|
||||
Reference in New Issue
Block a user