<template>
<div class="address-container">
<!-- 功能操作区 -->
<div class="action-bar">
<el-button type="primary" round icon="el-icon-plus" @click="add">新增地址</el-button>
<el-button type="danger" round icon="el-icon-delete" @click="deleteAllClick">删除全部</el-button>
</div>
<!-- 表格区域 -->
<el-table
:data="tableData"
v-loading="loading"
stripe
border
class="address-table"
height="500"
>
<el-table-column prop="name" label="收货人" align="center" width="120"></el-table-column>
<el-table-column prop="address" label="所在地区" width="180"></el-table-column>
<el-table-column prop="addDetail" label="详细地址" min-width="250" show-overflow-tooltip></el-table-column>
<el-table-column prop="phone" label="手机号" width="130"></el-table-column>
<!-- 操作列 -->
<el-table-column fixed="right" label="操作" width="240" align="center">
<template #default="scope">
<el-button size="small" type="primary" @click="editeClick(scope.row)">
编辑
</el-button>
<el-popconfirm
title="确定要删除该地址吗?"
@confirm="deleteClick(scope.row.id)"
style="margin-left: 10px"
>
<template #reference>
<el-button size="small" type="danger">删除</el-button>
</template>
</el-popconfirm>
<el-button
size="small"
type="success"
:disabled="scope.row.status === 1"
style="margin-left: 10px"
@click="changeStatus(scope.row.id)"
>
{{ scope.row.status === 1 ? '已选中' : '选择' }}
</el-button>
</template>
</el-table-column>
</el-table>
<!-- 分页 + 弹窗 -->
<div class="pagination-and-dialog">
<!-- 分页 -->
<el-pagination
@size-change="handleSizeChange"
@current-change="handleCurrentChange"
:current-page.sync="currentPage"
:page-sizes="[5, 10, 20]"
:page-size.sync="pageSize"
layout="total, sizes, prev, pager, next, jumper"
:total="totalNumber"
background
/>
<!-- 新增/编辑弹窗 -->
<el-dialog title="📍 新增或修改地址" :visible.sync="dialogVisible" width="50%" center>
<el-form :model="form" :rules="rules" ref="addressForm" label-width="100px" class="address-form">
<el-form-item label="所在地区" prop="address">
<el-cascader
filterable
clearable
:options="options"
v-model="form.address"
placeholder="请选择省/市/区"
@change="addressChoose"
style="width: 100%"
/>
</el-form-item>
<el-form-item label="详细地址" prop="addDetail">
<el-input
v-model="form.addDetail"
type="textarea"
:rows="3"
placeholder="请输入街道、门牌号、小区、楼栋等信息"
/>
</el-form-item>
<el-form-item label="收货人" prop="name">
<el-input v-model="form.name" placeholder="请输入真实姓名" maxlength="25" show-word-limit />
</el-form-item>
<el-form-item label="手机号" prop="phone">
<el-input v-model="form.phone" placeholder="请输入11位手机号" maxlength="11" />
</el-form-item>
</el-form>
<template #footer>
<div class="dialog-footer">
<el-button @click="dialogVisible = false">取 消</el-button>
<el-button type="primary" @click="save">确 定</el-button>
</div>
</template>
</el-dialog>
</div>
</div>
</template>
<script>
import request from "@/utils/request";
import { pcaTextArr } from "element-china-area-data";
export default {
name: "AddressManage",
created() {
document.title = "地址管理";
let str = sessionStorage.getItem("user") || "{}";
this.user = JSON.parse(str);
this.loadData();
},
data() {
return {
options: pcaTextArr,
loading: true,
form: {},
dialogVisible: false,
totalNumber: 0,
currentPage: 1,
pageSize: 5,
search: "",
tableData: [],
user: {},
rules: {
address: [{ required: true, message: "请选择所在地区", trigger: "change" }],
addDetail: [{ required: true, message: "请填写详细地址", trigger: "blur" }],
name: [{ required: true, message: "请输入收货人姓名", trigger: "blur" }],
phone: [
{ required: true, message: "请输入手机号", trigger: "blur" },
{ pattern: /^1[3-9]\d{9}$/, message: "请输入正确的11位手机号", trigger: "blur" }
]
}
};
},
methods: {
loadData() {
this.loading = true;
request
.get("/address", {
params: {
pageNum: this.currentPage,
pageSize: this.pageSize,
userId: this.user.id
}
})
.then(res => {
this.tableData = res.data.records;
this.totalNumber = res.data.total;
this.loading = false;
});
},
add() {
this.form = {};
this.dialogVisible = true;
},
save() {
// 校验手机号
if (!/^1[3-9]\d{9}$/.test(this.form.phone)) {
this.$message.error("请输入合法的11位手机号");
return;
}
// 处理地址拼接
if (Array.isArray(this.form.address) && this.form.address.length === 3) {
this.form.address = this.form.address.join(" ");
}
this.form.userId = this.user.id;
const req = this.form.id ? request.put("/address", this.form) : request.post("/address", this.form);
req.then(res => {
if (res.code === "0") {
this.$message.success(this.form.id ? "更新成功" : "新增成功");
this.dialogVisible = false;
this.loadData();
} else {
this.$message.error(res.msg || "操作失败");
}
});
},
deleteClick(id) {
request.delete("/address", { params: { id } }).then(res => {
if (res.code === "0") {
this.$message.success("删除成功");
this.loadData();
} else {
this.$message.error(res.msg || "删除失败");
}
});
},
deleteAllClick() {
this.$confirm("此操作将删除所有地址,是否继续?", "警告", {
confirmButtonText: "确定",
cancelButtonText: "取消",
type: "warning"
}).then(() => {
request.delete("/address/all").then(res => {
if (res.code === "0") {
this.$message.success("全部删除成功");
this.loadData();
} else {
this.$message.error(res.msg || "删除失败");
}
});
}).catch(() => {
this.$message.info("已取消删除");
});
},
editeClick(row) {
this.form = JSON.parse(JSON.stringify(row));
// 将字符串地址转为数组用于 Cascader 显示
if (typeof this.form.address === 'string') {
this.form.address = this.form.address.split(' ').filter(Boolean);
}
this.dialogVisible = true;
},
addressChoose(value) {
console.log("选中的地区:", value);
},
handleSizeChange() {
this.loadData();
},
handleCurrentChange() {
this.loadData();
},
changeStatus(id) {
request.get("/address/update", {
params: { id, userId: this.user.id }
}).then(() => {
this.$message.success("默认地址设置成功");
this.loadData();
}).catch(() => {
this.$message.error("设置失败");
});
}
}
};
</script>
<style scoped>
/* 整体容器 */
.address-container {
width: 900px;
margin: 25px auto;
padding: 20px;
background-color: #ffffff;
border-radius: 16px;
box-shadow: 0 6px 20px rgba(0, 0, 0, 0.08);
font-family: 'Helvetica Neue', Arial, sans-serif;
}
/* 操作栏 */
.action-bar {
display: flex;
gap: 16px;
margin-bottom: 24px;
}
/* 表格美化 */
.address-table ::v-deep(th) {
background-color: #f5f7fa;
color: #1a1a1a;
font-weight: 600;
}
.address-table ::v-deep(.cell) {
text-align: center;
}
.address-table ::v-deep(tr:hover) {
background-color: #f9fafc !important;
}
/* 分页与弹窗区域 */
.pagination-and-dialog {
margin-top: 24px;
}
/* 弹窗内表单 */
.address-form ::v-deep(.el-form-item__label) {
font-weight: 500;
color: #333;
}
/* 对话框底部按钮 */
.dialog-footer {
text-align: center;
padding: 10px 0;
}
.dialog-footer .el-button {
width: 100px;
font-weight: 500;
}
/* 响应式适配 */
@media (max-width: 920px) {
.address-container {
width: 100%;
margin: 15px;
padding: 15px;
}
.action-bar {
flex-direction: column;
align-items: flex-start;
}
.address-table ::v-deep(.el-table-column--selection) {
width: 40px !important;
}
}
</style>