update
This commit is contained in:
parent
d05216743c
commit
321ff3452b
@ -73,6 +73,9 @@
|
||||
<a-menu-item key="community-time-periods">
|
||||
<router-link to="/community/time-periods">配送时段</router-link>
|
||||
</a-menu-item>
|
||||
<a-menu-item key="community-sets">
|
||||
<router-link to="/community/sets">小区集合</router-link>
|
||||
</a-menu-item>
|
||||
</a-sub-menu>
|
||||
|
||||
<a-sub-menu key="coupon">
|
||||
@ -296,6 +299,11 @@ export default defineComponent({
|
||||
key: 'community-time-periods',
|
||||
title: '配送时段',
|
||||
path: '/community/time-periods'
|
||||
},
|
||||
{
|
||||
key: 'community-sets',
|
||||
title: '小区集合',
|
||||
path: '/community/sets'
|
||||
}
|
||||
]
|
||||
},
|
||||
|
||||
@ -69,6 +69,18 @@ const routes = [
|
||||
name: 'CommunityTimePeriods',
|
||||
component: () => import('../views/community/TimePeriodList.vue'),
|
||||
meta: { title: '小区配送时段' }
|
||||
},
|
||||
{
|
||||
path: 'community/sets',
|
||||
name: 'CommunitySets',
|
||||
component: () => import('../views/community/CommunitySetList.vue'),
|
||||
meta: { title: '小区集合' }
|
||||
},
|
||||
{
|
||||
path: 'community/sets/:id',
|
||||
name: 'CommunitySetDetail',
|
||||
component: () => import('../views/community/CommunitySetDetail.vue'),
|
||||
meta: { title: '小区集合详情' }
|
||||
}
|
||||
]
|
||||
},
|
||||
|
||||
500
src/views/community/CommunitySetDetail.vue
Normal file
500
src/views/community/CommunitySetDetail.vue
Normal file
@ -0,0 +1,500 @@
|
||||
<template>
|
||||
<page-container>
|
||||
<div class="community-set-detail">
|
||||
<div class="detail-header">
|
||||
<div class="header-info">
|
||||
<div class="info-card">
|
||||
<h1 class="set-name">{{ setInfo.set_name || '加载中...' }}</h1>
|
||||
<div class="operator-info" v-if="setInfo.user_name">
|
||||
<span class="label">运营商:</span>
|
||||
<span class="value">{{ setInfo.user_name }}</span>
|
||||
</div>
|
||||
<div class="meta-info" v-if="setInfo.create_time">
|
||||
<span class="label">创建时间:</span>
|
||||
<span class="value">{{ setInfo.create_time }}</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<a-divider />
|
||||
|
||||
<div class="communities-list">
|
||||
<div class="list-header">
|
||||
<h2>关联小区列表</h2>
|
||||
<a-button type="primary" @click="showAddCommunityModal">
|
||||
添加小区
|
||||
</a-button>
|
||||
</div>
|
||||
<a-spin :spinning="loading">
|
||||
<a-empty v-if="communities.length === 0" description="暂无关联小区" />
|
||||
<a-table
|
||||
v-else
|
||||
:columns="columns"
|
||||
:data-source="communities"
|
||||
:pagination="pagination"
|
||||
:loading="loading"
|
||||
@change="handleTableChange"
|
||||
row-key="id"
|
||||
>
|
||||
<template #bodyCell="{ column, record }">
|
||||
<template v-if="column.key === 'action'">
|
||||
<a-button type="link" danger @click="handleRemoveCommunity(record)">
|
||||
移除关联
|
||||
</a-button>
|
||||
</template>
|
||||
</template>
|
||||
</a-table>
|
||||
</a-spin>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- 添加小区模态框 -->
|
||||
<a-modal
|
||||
v-model:visible="addCommunityVisible"
|
||||
title="添加小区"
|
||||
:footer="null"
|
||||
>
|
||||
<div class="search-community">
|
||||
<a-input-search
|
||||
v-model:value="searchValue"
|
||||
placeholder="请输入小区名称搜索"
|
||||
enter-button
|
||||
@search="handleSearchCommunity"
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div v-if="searchLoading" class="search-loading">
|
||||
<a-spin />
|
||||
</div>
|
||||
|
||||
<div v-else-if="searchResults.length > 0" class="search-results">
|
||||
<div class="search-title">搜索结果:</div>
|
||||
<a-radio-group v-model:value="selectedCommunityId">
|
||||
<div v-for="community in searchResults" :key="community.id" class="search-item">
|
||||
<a-radio :value="community.id">
|
||||
<div class="community-info">
|
||||
<div class="community-name">{{ community.name }}</div>
|
||||
<div class="community-address">{{ community.address }}</div>
|
||||
</div>
|
||||
</a-radio>
|
||||
</div>
|
||||
</a-radio-group>
|
||||
|
||||
<div class="search-actions">
|
||||
<a-button type="primary" :disabled="!selectedCommunityId" :loading="submitting" @click="handleAddCommunity">
|
||||
确认添加
|
||||
</a-button>
|
||||
<a-button style="margin-left: 8px;" @click="handleCancelAdd">
|
||||
取消
|
||||
</a-button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div v-else-if="searchValue && !searchLoading" class="no-results">
|
||||
未找到匹配的小区
|
||||
</div>
|
||||
|
||||
<div v-else class="search-tip">
|
||||
请输入小区名称进行搜索
|
||||
</div>
|
||||
</a-modal>
|
||||
</page-container>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { defineComponent, ref, reactive, onMounted } from 'vue'
|
||||
import { useRoute } from 'vue-router'
|
||||
import { message, Modal, Table, Tag, Spin, Empty, Divider } from 'ant-design-vue'
|
||||
import request from '@/utils/request'
|
||||
import PageContainer from '@/components/PageContainer.vue'
|
||||
|
||||
export default defineComponent({
|
||||
components: {
|
||||
PageContainer,
|
||||
ATable: Table,
|
||||
ATag: Tag,
|
||||
ASpin: Spin,
|
||||
AEmpty: Empty,
|
||||
ADivider: Divider
|
||||
},
|
||||
setup() {
|
||||
const route = useRoute()
|
||||
const setId = ref(route.params.id)
|
||||
const loading = ref(false)
|
||||
const setInfo = ref({})
|
||||
const communities = ref([])
|
||||
|
||||
// 分页配置
|
||||
const pagination = ref({
|
||||
current: 1,
|
||||
pageSize: 10,
|
||||
total: 0,
|
||||
showSizeChanger: true,
|
||||
showTotal: (total) => `共 ${total} 条记录`
|
||||
})
|
||||
|
||||
// 表格列定义
|
||||
const columns = [
|
||||
{
|
||||
title: 'ID',
|
||||
dataIndex: 'community_id',
|
||||
key: 'community_id',
|
||||
width: 80
|
||||
},
|
||||
{
|
||||
title: '小区名称',
|
||||
dataIndex: 'community_name',
|
||||
key: 'community_name',
|
||||
width: 200
|
||||
},
|
||||
{
|
||||
title: '地址',
|
||||
dataIndex: 'address',
|
||||
key: 'address',
|
||||
ellipsis: true
|
||||
},
|
||||
{
|
||||
title: '操作',
|
||||
key: 'action',
|
||||
width: 120,
|
||||
fixed: 'right'
|
||||
}
|
||||
]
|
||||
|
||||
// 添加小区相关状态
|
||||
const addCommunityVisible = ref(false)
|
||||
const submitting = ref(false)
|
||||
const searchValue = ref('')
|
||||
const searchLoading = ref(false)
|
||||
const searchResults = ref([])
|
||||
const selectedCommunityId = ref(null)
|
||||
|
||||
// 获取集合详情
|
||||
const fetchSetInfo = async () => {
|
||||
try {
|
||||
loading.value = true
|
||||
const res = await request.get(`/api/community-sets/list/all`)
|
||||
if (res.code === 200 && res.data && res.data.items) {
|
||||
const set = res.data.items.find(item => item.id === Number(setId.value))
|
||||
if (set) {
|
||||
setInfo.value = set
|
||||
} else {
|
||||
message.error('未找到小区集合信息')
|
||||
}
|
||||
} else {
|
||||
message.error(res.message || '获取集合信息失败')
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('获取小区集合信息失败:', error)
|
||||
message.error('获取集合信息失败')
|
||||
} finally {
|
||||
loading.value = false
|
||||
}
|
||||
}
|
||||
|
||||
// 获取关联小区列表
|
||||
const fetchCommunities = async () => {
|
||||
try {
|
||||
loading.value = true
|
||||
const params = {
|
||||
skip: (pagination.value.current - 1) * pagination.value.pageSize,
|
||||
limit: pagination.value.pageSize
|
||||
}
|
||||
|
||||
const res = await request.get(`/api/community-set-mappings/set/${setId.value}/communities`, { params })
|
||||
if (res.code === 200 && res.data) {
|
||||
communities.value = res.data.items || []
|
||||
pagination.value.total = res.data.total || 0
|
||||
} else {
|
||||
message.error(res.message || '获取关联小区失败')
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('获取关联小区失败:', error)
|
||||
message.error('获取关联小区失败')
|
||||
} finally {
|
||||
loading.value = false
|
||||
}
|
||||
}
|
||||
|
||||
// 表格变化处理(分页、排序等)
|
||||
const handleTableChange = (pag) => {
|
||||
pagination.value.current = pag.current
|
||||
pagination.value.pageSize = pag.pageSize
|
||||
fetchCommunities()
|
||||
}
|
||||
|
||||
// 获取小区状态文本
|
||||
const getStatusText = (status) => {
|
||||
const statusMap = {
|
||||
'OPENING': '营业中',
|
||||
'CLOSED': '已关闭',
|
||||
'PREPARING': '筹备中'
|
||||
}
|
||||
return statusMap[status] || status
|
||||
}
|
||||
|
||||
// 获取小区状态颜色
|
||||
const getStatusColor = (status) => {
|
||||
const colorMap = {
|
||||
'OPENING': 'green',
|
||||
'CLOSED': 'red',
|
||||
'PREPARING': 'orange'
|
||||
}
|
||||
return colorMap[status] || 'default'
|
||||
}
|
||||
|
||||
// 显示添加小区模态框
|
||||
const showAddCommunityModal = () => {
|
||||
addCommunityVisible.value = true
|
||||
searchValue.value = ''
|
||||
searchResults.value = []
|
||||
selectedCommunityId.value = null
|
||||
}
|
||||
|
||||
// 搜索小区
|
||||
const handleSearchCommunity = async () => {
|
||||
if (!searchValue.value) {
|
||||
message.warning('请输入小区名称')
|
||||
return
|
||||
}
|
||||
|
||||
try {
|
||||
searchLoading.value = true
|
||||
const res = await request.get(`/api/community/search_by_name/${searchValue.value}`)
|
||||
if (res.code === 200) {
|
||||
searchResults.value = res.data || []
|
||||
if (searchResults.value.length > 0) {
|
||||
selectedCommunityId.value = searchResults.value[0].id
|
||||
}
|
||||
} else {
|
||||
message.warning(res.message || '搜索小区失败')
|
||||
searchResults.value = []
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('搜索小区失败:', error)
|
||||
message.error('搜索小区失败')
|
||||
searchResults.value = []
|
||||
} finally {
|
||||
searchLoading.value = false
|
||||
}
|
||||
}
|
||||
|
||||
// 添加小区
|
||||
const handleAddCommunity = async () => {
|
||||
if (!selectedCommunityId.value) {
|
||||
message.warning('请选择要添加的小区')
|
||||
return
|
||||
}
|
||||
|
||||
try {
|
||||
submitting.value = true
|
||||
const res = await request.post('/api/community-set-mappings/', {
|
||||
set_id: Number(setId.value),
|
||||
community_id: selectedCommunityId.value
|
||||
})
|
||||
|
||||
if (res.code === 200) {
|
||||
message.success('添加小区成功')
|
||||
addCommunityVisible.value = false
|
||||
fetchCommunities() // 刷新列表
|
||||
} else {
|
||||
message.error(res.message || '添加小区失败')
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('添加小区失败:', error)
|
||||
message.error('添加小区失败')
|
||||
} finally {
|
||||
submitting.value = false
|
||||
}
|
||||
}
|
||||
|
||||
// 取消添加
|
||||
const handleCancelAdd = () => {
|
||||
addCommunityVisible.value = false
|
||||
}
|
||||
|
||||
// 移除小区关联
|
||||
const handleRemoveCommunity = (community) => {
|
||||
Modal.confirm({
|
||||
title: '确认移除',
|
||||
content: `确定要移除小区 "${community.community_name}" 的关联吗?`,
|
||||
onOk: async () => {
|
||||
try {
|
||||
const res = await request.delete(`/api/community-set-mappings/${community.id}`)
|
||||
if (res.code === 200) {
|
||||
message.success('移除关联成功')
|
||||
fetchCommunities() // 刷新列表
|
||||
} else {
|
||||
message.error(res.message || '移除关联失败')
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('移除小区关联失败:', error)
|
||||
message.error('移除关联失败')
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
onMounted(() => {
|
||||
fetchSetInfo()
|
||||
fetchCommunities()
|
||||
})
|
||||
|
||||
return {
|
||||
setId,
|
||||
loading,
|
||||
setInfo,
|
||||
communities,
|
||||
columns,
|
||||
pagination,
|
||||
addCommunityVisible,
|
||||
submitting,
|
||||
searchValue,
|
||||
searchLoading,
|
||||
searchResults,
|
||||
selectedCommunityId,
|
||||
getStatusText,
|
||||
getStatusColor,
|
||||
showAddCommunityModal,
|
||||
handleSearchCommunity,
|
||||
handleAddCommunity,
|
||||
handleCancelAdd,
|
||||
handleRemoveCommunity,
|
||||
handleTableChange
|
||||
}
|
||||
}
|
||||
})
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
.detail-header {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: flex-start;
|
||||
margin-bottom: 24px;
|
||||
}
|
||||
|
||||
.header-info {
|
||||
flex: 1;
|
||||
}
|
||||
|
||||
.info-card {
|
||||
background-color: #fafafa;
|
||||
border-radius: 8px;
|
||||
padding: 20px;
|
||||
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.05);
|
||||
border: 1px solid #f0f0f0;
|
||||
}
|
||||
|
||||
.set-name {
|
||||
margin: 0;
|
||||
margin-bottom: 16px;
|
||||
font-size: 24px;
|
||||
color: #1890ff;
|
||||
font-weight: 600;
|
||||
}
|
||||
|
||||
.operator-info, .meta-info {
|
||||
font-size: 14px;
|
||||
margin-bottom: 8px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.operator-info .label, .meta-info .label {
|
||||
color: #666;
|
||||
margin-right: 8px;
|
||||
min-width: 70px;
|
||||
}
|
||||
|
||||
.operator-info .value, .meta-info .value {
|
||||
font-weight: 500;
|
||||
color: #333;
|
||||
}
|
||||
|
||||
.communities-list {
|
||||
margin-top: 24px;
|
||||
}
|
||||
|
||||
.list-header {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
margin-bottom: 16px;
|
||||
}
|
||||
|
||||
.list-header h2 {
|
||||
margin-bottom: 0;
|
||||
}
|
||||
|
||||
:deep(.ant-table-content) {
|
||||
overflow-x: auto;
|
||||
}
|
||||
|
||||
:deep(.ant-table-cell) {
|
||||
vertical-align: middle;
|
||||
}
|
||||
|
||||
.search-community {
|
||||
margin-bottom: 16px;
|
||||
}
|
||||
|
||||
.search-loading {
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
padding: 24px 0;
|
||||
}
|
||||
|
||||
.search-results {
|
||||
max-height: 300px;
|
||||
overflow-y: auto;
|
||||
padding: 8px 0;
|
||||
}
|
||||
|
||||
.search-item {
|
||||
padding: 8px 0;
|
||||
border-bottom: 1px solid #f0f0f0;
|
||||
}
|
||||
|
||||
.search-item:last-child {
|
||||
border-bottom: none;
|
||||
}
|
||||
|
||||
.community-info {
|
||||
margin-left: 8px;
|
||||
}
|
||||
|
||||
.community-name {
|
||||
font-weight: 500;
|
||||
}
|
||||
|
||||
.community-address {
|
||||
font-size: 12px;
|
||||
color: #666;
|
||||
}
|
||||
|
||||
.no-results {
|
||||
text-align: center;
|
||||
color: #999;
|
||||
padding: 24px 0;
|
||||
}
|
||||
|
||||
.search-title {
|
||||
font-weight: bold;
|
||||
margin-bottom: 12px;
|
||||
}
|
||||
|
||||
.search-actions {
|
||||
margin-top: 16px;
|
||||
text-align: right;
|
||||
padding-top: 16px;
|
||||
border-top: 1px solid #f0f0f0;
|
||||
}
|
||||
|
||||
.search-tip {
|
||||
text-align: center;
|
||||
color: #999;
|
||||
padding: 24px 0;
|
||||
}
|
||||
</style>
|
||||
441
src/views/community/CommunitySetList.vue
Normal file
441
src/views/community/CommunitySetList.vue
Normal file
@ -0,0 +1,441 @@
|
||||
<template>
|
||||
<page-container>
|
||||
<div class="community-set-list">
|
||||
<div class="table-header">
|
||||
<h1>小区集合</h1>
|
||||
<a-button type="primary" @click="showCreateModal">
|
||||
创建小区集合
|
||||
</a-button>
|
||||
</div>
|
||||
|
||||
<a-table
|
||||
:columns="columns"
|
||||
:data-source="tableData"
|
||||
:loading="loading"
|
||||
:pagination="pagination"
|
||||
row-key="id"
|
||||
@change="handleTableChange"
|
||||
>
|
||||
<template #bodyCell="{ column, record }">
|
||||
<template v-if="column.key === 'action'">
|
||||
<a-space>
|
||||
<a-button type="link" @click="handleView(record)">
|
||||
查看详情
|
||||
</a-button>
|
||||
</a-space>
|
||||
</template>
|
||||
</template>
|
||||
</a-table>
|
||||
</div>
|
||||
|
||||
<!-- 创建小区集合模态框 -->
|
||||
<a-modal
|
||||
v-model:visible="createModalVisible"
|
||||
title="创建小区集合"
|
||||
@ok="handleCreateSubmit"
|
||||
@cancel="handleCreateCancel"
|
||||
:confirmLoading="submitting"
|
||||
>
|
||||
<a-form :model="createForm" layout="vertical">
|
||||
<a-form-item
|
||||
label="集合名称"
|
||||
name="set_name"
|
||||
:rules="[{ required: true, message: '请输入集合名称' }]"
|
||||
>
|
||||
<a-input v-model:value="createForm.set_name" placeholder="请输入集合名称" />
|
||||
</a-form-item>
|
||||
|
||||
<a-form-item
|
||||
label="运营商"
|
||||
name="user_id"
|
||||
:rules="[{ required: true, message: '运营商必须选择' }]"
|
||||
>
|
||||
<div class="user-search">
|
||||
<a-input-search
|
||||
v-model:value="phoneSearchValue"
|
||||
placeholder="请输入手机号查询"
|
||||
enter-button
|
||||
@search="handlePhoneSearch"
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div v-if="searchedUser" class="user-result">
|
||||
<div class="user-info">
|
||||
<div class="user-name">{{ searchedUser.nickname || '未设置昵称' }}</div>
|
||||
<div class="user-phone">{{ formatPhone(searchedUser.phone) }}</div>
|
||||
<div class="user-roles">
|
||||
<a-tag v-if="hasPartnerRole(searchedUser)" color="green">运营商</a-tag>
|
||||
</div>
|
||||
</div>
|
||||
<div class="user-action">
|
||||
<a-button
|
||||
type="primary"
|
||||
size="small"
|
||||
@click="selectUser(searchedUser)"
|
||||
:disabled="isUserSelected(searchedUser)"
|
||||
>
|
||||
{{ isUserSelected(searchedUser) ? '已选择' : '选择' }}
|
||||
</a-button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div v-if="selectedUser" class="selected-user">
|
||||
<div class="selected-info">
|
||||
<div class="user-name">{{ selectedUser.nickname || '未设置昵称' }}</div>
|
||||
<div class="user-phone">{{ formatPhone(selectedUser.phone) }}</div>
|
||||
<a-button type="link" danger size="small" @click="clearSelectedUser">
|
||||
取消选择
|
||||
</a-button>
|
||||
</div>
|
||||
</div>
|
||||
</a-form-item>
|
||||
</a-form>
|
||||
</a-modal>
|
||||
</page-container>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { defineComponent, ref, reactive, onMounted, computed } from 'vue'
|
||||
import { message } from 'ant-design-vue'
|
||||
import request from '@/utils/request'
|
||||
import PageContainer from '@/components/PageContainer.vue'
|
||||
import { useRouter } from 'vue-router'
|
||||
|
||||
export default defineComponent({
|
||||
components: {
|
||||
PageContainer
|
||||
},
|
||||
setup() {
|
||||
const loading = ref(false)
|
||||
const tableData = ref([])
|
||||
const submitting = ref(false)
|
||||
const router = useRouter()
|
||||
|
||||
// 分页配置
|
||||
const pagination = ref({
|
||||
current: 1,
|
||||
pageSize: 10,
|
||||
total: 0,
|
||||
showSizeChanger: true,
|
||||
showTotal: (total) => `共 ${total} 条记录`
|
||||
})
|
||||
|
||||
// 创建模态框相关状态
|
||||
const createModalVisible = ref(false)
|
||||
const createForm = reactive({
|
||||
set_name: '',
|
||||
user_id: null
|
||||
})
|
||||
|
||||
// 手机号搜索相关状态
|
||||
const phoneSearchValue = ref('')
|
||||
const searchedUser = ref(null)
|
||||
const selectedUser = ref(null)
|
||||
|
||||
// 判断用户是否已选择
|
||||
const isUserSelected = (user) => {
|
||||
return selectedUser.value && selectedUser.value.userid === user.userid
|
||||
}
|
||||
|
||||
// 判断用户是否有运营商角色
|
||||
const hasPartnerRole = (user) => {
|
||||
return user && user.roles && user.roles.includes('partner')
|
||||
}
|
||||
|
||||
// 选择用户
|
||||
const selectUser = (user) => {
|
||||
selectedUser.value = user
|
||||
createForm.user_id = user.userid
|
||||
message.success(`已选择:${user.nickname || user.phone}`)
|
||||
}
|
||||
|
||||
// 清除已选择的用户
|
||||
const clearSelectedUser = () => {
|
||||
selectedUser.value = null
|
||||
createForm.user_id = null
|
||||
}
|
||||
|
||||
// 获取角色名称
|
||||
const getRoleName = (role) => {
|
||||
const roleMap = {
|
||||
'admin': '管理员',
|
||||
'user': '普通用户',
|
||||
'merchant': '商家',
|
||||
'deliveryman': '配送员',
|
||||
'partner': '运营商'
|
||||
}
|
||||
return roleMap[role] || role
|
||||
}
|
||||
|
||||
// 获取角色颜色
|
||||
const getRoleColor = (role) => {
|
||||
const colorMap = {
|
||||
'admin': 'red',
|
||||
'user': 'blue',
|
||||
'merchant': 'orange',
|
||||
'deliveryman': 'purple',
|
||||
'partner': 'green'
|
||||
}
|
||||
return colorMap[role] || 'default'
|
||||
}
|
||||
|
||||
const columns = [
|
||||
{
|
||||
title: 'ID',
|
||||
dataIndex: 'id',
|
||||
key: 'id',
|
||||
width: 80,
|
||||
},
|
||||
{
|
||||
title: '集合名称',
|
||||
dataIndex: 'set_name',
|
||||
key: 'set_name',
|
||||
width: 200,
|
||||
},
|
||||
{
|
||||
title: '运营商',
|
||||
dataIndex: 'user_name',
|
||||
key: 'user_name',
|
||||
width: 150,
|
||||
},
|
||||
{
|
||||
title: '小区数量',
|
||||
dataIndex: 'community_count',
|
||||
key: 'community_count',
|
||||
width: 120,
|
||||
},
|
||||
{
|
||||
title: '创建时间',
|
||||
dataIndex: 'create_time',
|
||||
key: 'create_time',
|
||||
width: 180,
|
||||
},
|
||||
{
|
||||
title: '操作',
|
||||
key: 'action',
|
||||
width: 150,
|
||||
}
|
||||
]
|
||||
|
||||
// 格式化手机号,中间4位显示*
|
||||
const formatPhone = (phone) => {
|
||||
if (!phone) return ''
|
||||
return phone.replace(/(\d{3})\d{4}(\d{4})/, '$1****$2')
|
||||
}
|
||||
|
||||
// 获取小区集合列表
|
||||
const fetchData = async () => {
|
||||
try {
|
||||
loading.value = true
|
||||
const params = {
|
||||
skip: (pagination.value.current - 1) * pagination.value.pageSize,
|
||||
limit: pagination.value.pageSize
|
||||
}
|
||||
|
||||
const res = await request.get('/api/community-sets/list/all', { params })
|
||||
if (res.code === 200 && res.data) {
|
||||
tableData.value = res.data.items || []
|
||||
pagination.value.total = res.data.total || 0
|
||||
} else {
|
||||
message.error(res.message || '获取数据失败')
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('获取小区集合列表失败:', error)
|
||||
message.error('获取数据失败')
|
||||
} finally {
|
||||
loading.value = false
|
||||
}
|
||||
}
|
||||
|
||||
// 显示创建模态框
|
||||
const showCreateModal = () => {
|
||||
createForm.set_name = ''
|
||||
createForm.user_id = null
|
||||
phoneSearchValue.value = ''
|
||||
searchedUser.value = null
|
||||
selectedUser.value = null
|
||||
createModalVisible.value = true
|
||||
}
|
||||
|
||||
// 处理创建提交
|
||||
const handleCreateSubmit = async () => {
|
||||
if (!createForm.set_name) {
|
||||
message.warning('请输入集合名称')
|
||||
return
|
||||
}
|
||||
|
||||
if (!createForm.user_id) {
|
||||
message.warning('请选择运营商')
|
||||
return
|
||||
}
|
||||
|
||||
try {
|
||||
submitting.value = true
|
||||
const res = await request.post('/api/community-sets/', {
|
||||
set_name: createForm.set_name,
|
||||
user_id: createForm.user_id
|
||||
})
|
||||
|
||||
if (res.code === 200) {
|
||||
message.success('创建成功')
|
||||
createModalVisible.value = false
|
||||
fetchData() // 刷新列表
|
||||
} else {
|
||||
message.error(res.message || '创建失败')
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('创建小区集合失败:', error)
|
||||
message.error('创建失败')
|
||||
} finally {
|
||||
submitting.value = false
|
||||
}
|
||||
}
|
||||
|
||||
// 处理创建取消
|
||||
const handleCreateCancel = () => {
|
||||
createModalVisible.value = false
|
||||
}
|
||||
|
||||
// 处理手机号搜索
|
||||
const handlePhoneSearch = async () => {
|
||||
if (!phoneSearchValue.value) {
|
||||
message.warning('请输入手机号')
|
||||
return
|
||||
}
|
||||
|
||||
try {
|
||||
const res = await request.get(`/api/user/search_by_phone/${phoneSearchValue.value}`)
|
||||
if (res.code === 200 && res.data) {
|
||||
searchedUser.value = res.data
|
||||
// 不再自动设置user_id,需要用户手动选择
|
||||
} else {
|
||||
message.warning(res.message || '未找到该用户')
|
||||
searchedUser.value = null
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('搜索用户失败:', error)
|
||||
message.error('搜索失败')
|
||||
searchedUser.value = null
|
||||
}
|
||||
}
|
||||
|
||||
// 查看详情
|
||||
const handleView = (record) => {
|
||||
router.push(`/community/sets/${record.id}`)
|
||||
}
|
||||
|
||||
// 表格变化处理(分页、排序等)
|
||||
const handleTableChange = (pag) => {
|
||||
pagination.value.current = pag.current
|
||||
pagination.value.pageSize = pag.pageSize
|
||||
fetchData()
|
||||
}
|
||||
|
||||
onMounted(() => {
|
||||
fetchData()
|
||||
})
|
||||
|
||||
return {
|
||||
loading,
|
||||
tableData,
|
||||
columns,
|
||||
pagination,
|
||||
createModalVisible,
|
||||
createForm,
|
||||
submitting,
|
||||
phoneSearchValue,
|
||||
searchedUser,
|
||||
selectedUser,
|
||||
formatPhone,
|
||||
getRoleName,
|
||||
getRoleColor,
|
||||
isUserSelected,
|
||||
hasPartnerRole,
|
||||
selectUser,
|
||||
clearSelectedUser,
|
||||
showCreateModal,
|
||||
handleCreateSubmit,
|
||||
handleCreateCancel,
|
||||
handlePhoneSearch,
|
||||
handleView,
|
||||
handleTableChange
|
||||
}
|
||||
}
|
||||
})
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
.table-header {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
margin-bottom: 16px;
|
||||
}
|
||||
|
||||
.table-header h1 {
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
:deep(.ant-table-content) {
|
||||
overflow-x: auto;
|
||||
}
|
||||
|
||||
.user-search {
|
||||
margin-bottom: 16px;
|
||||
}
|
||||
|
||||
.user-result {
|
||||
margin-top: 8px;
|
||||
padding: 12px;
|
||||
background-color: #f5f5f5;
|
||||
border-radius: 4px;
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.user-info {
|
||||
flex: 1;
|
||||
}
|
||||
|
||||
.user-name {
|
||||
font-weight: bold;
|
||||
font-size: 16px;
|
||||
margin-bottom: 4px;
|
||||
}
|
||||
|
||||
.user-phone {
|
||||
color: #666;
|
||||
margin-bottom: 4px;
|
||||
}
|
||||
|
||||
.user-roles {
|
||||
margin-top: 8px;
|
||||
}
|
||||
|
||||
.user-action {
|
||||
margin-left: 16px;
|
||||
}
|
||||
|
||||
.selected-user {
|
||||
margin-top: 16px;
|
||||
padding: 12px;
|
||||
background-color: #e6f7ff;
|
||||
border: 1px solid #91d5ff;
|
||||
border-radius: 4px;
|
||||
}
|
||||
|
||||
.selected-info {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.selected-info .user-name {
|
||||
margin-right: 16px;
|
||||
margin-bottom: 0;
|
||||
}
|
||||
|
||||
.selected-info .user-phone {
|
||||
margin-bottom: 0;
|
||||
}
|
||||
</style>
|
||||
Loading…
Reference in New Issue
Block a user