This commit is contained in:
aaron 2025-03-12 12:41:02 +08:00
parent 04758174f0
commit a9ed11754c
2 changed files with 320 additions and 2 deletions

View File

@ -64,6 +64,17 @@
</div>
<a-tag v-else color="orange">未设置</a-tag>
</template>
<template v-if="column.key === 'admin'">
<div v-if="record.admin" class="admin-info-table">
<div class="admin-info-row">
<span class="admin-name">{{ record.admin.nickname || '未知' }}</span>
</div>
<div class="admin-info-row">
<span class="admin-phone">{{ record.admin.phone || '-' }}</span>
</div>
</div>
<a-tag v-else color="orange">未设置</a-tag>
</template>
<template v-if="column.key === 'action'">
<div class="action-buttons">
<a @click="handleEdit(record)">编辑</a>
@ -71,6 +82,8 @@
<a @click="handleEditDeliveryPrice(record)">配送定价</a>
<a-divider type="vertical" />
<a @click="handleEditProfitSharing(record)">设置分润</a>
<a-divider type="vertical" />
<a @click="handleSetAdmin(record)">设置服务商</a>
</div>
</template>
</template>
@ -316,6 +329,69 @@
<span v-if="!isRateValid" class="rate-error-message">总比例必须等于100%</span>
</div>
</a-modal>
<!-- 设置服务商模态框 -->
<a-modal
v-model:visible="adminModalVisible"
title="设置服务商"
@ok="handleAdminSave"
@cancel="handleAdminCancel"
:confirmLoading="adminSaving"
width="480px"
>
<div class="admin-search-form">
<a-form layout="vertical">
<a-form-item label="搜索用户">
<a-input
v-model:value="adminSearchPhone"
placeholder="请输入手机号搜索,按回车键搜索"
:loading="adminSearching"
@pressEnter="handleSearchAdmin"
/>
</a-form-item>
</a-form>
<div v-if="adminSearchResult" class="admin-search-result">
<a-card :class="{ 'admin-card-selected': adminSearchResult.selected }" @click="selectSearchResult(adminSearchResult)">
<div class="admin-info">
<div class="admin-info-item">
<span class="admin-info-label">用户ID:</span>
<span class="admin-info-value">{{ adminSearchResult.userid }}</span>
</div>
<div class="admin-info-item">
<span class="admin-info-label">姓名:</span>
<span class="admin-info-value">{{ adminSearchResult.nickname }}</span>
</div>
<div class="admin-info-item">
<span class="admin-info-label">手机号:</span>
<span class="admin-info-value">{{ adminSearchResult.phone }}</span>
</div>
</div>
</a-card>
</div>
<div v-if="currentCommunity" class="current-admin-info">
<div class="current-admin-title">当前服务商信息</div>
<div v-if="currentCommunity.admin_id" class="admin-info">
<div class="admin-info-item">
<span class="admin-info-label">用户ID:</span>
<span class="admin-info-value">{{ currentCommunity.admin_id }}</span>
</div>
<div class="admin-info-item" v-if="currentCommunity.admin_name">
<span class="admin-info-label">姓名:</span>
<span class="admin-info-value">{{ currentCommunity.admin_name }}</span>
</div>
<div class="admin-info-item" v-if="currentCommunity.admin_phone">
<span class="admin-info-label">手机号:</span>
<span class="admin-info-value">{{ currentCommunity.admin_phone }}</span>
</div>
</div>
<div v-else class="no-admin-info">
<a-empty description="暂无服务商" />
</div>
</div>
</div>
</a-modal>
</div>
<!-- 二维码预览模态框 -->
@ -416,6 +492,11 @@ export default defineComponent({
key: 'profit_sharing',
width: 220,
},
{
title: '服务商',
key: 'admin',
width: 150,
},
{
title: '位置',
key: 'location',
@ -972,6 +1053,104 @@ export default defineComponent({
currentCommunityName.value = ''
}
//
const adminModalVisible = ref(false)
const adminSaving = ref(false)
const adminSearching = ref(false)
const adminSearchPhone = ref('')
const adminSearchResult = ref(null)
const currentCommunity = ref(null)
//
const handleSetAdmin = (record) => {
currentCommunity.value = { ...record }
adminSearchPhone.value = ''
adminSearchResult.value = null
adminModalVisible.value = true
}
//
const handleSearchAdmin = async () => {
if (!adminSearchPhone.value || adminSearchPhone.value.length < 5) {
message.warning('请输入有效的手机号')
return
}
try {
adminSearching.value = true
const res = await request.get(`/api/user/search_by_phone/${adminSearchPhone.value}`)
if (res.code === 200) {
if (res.data) {
adminSearchResult.value = {
...res.data,
selected: false
}
} else {
adminSearchResult.value = null
message.warning('未找到该用户')
}
} else {
message.error(res.message || '搜索失败')
}
} catch (error) {
console.error('搜索用户失败:', error)
message.error('搜索失败')
} finally {
adminSearching.value = false
}
}
//
const selectSearchResult = (result) => {
if (adminSearchResult.value) {
adminSearchResult.value.selected = !adminSearchResult.value.selected
}
}
//
const handleAdminSave = async () => {
if (!adminSearchResult.value) {
message.warning('请先搜索并选择服务商')
return
}
if (!adminSearchResult.value.selected) {
message.warning('请先选择搜索结果中的用户作为服务商')
return
}
try {
adminSaving.value = true
const params = {
admin_id: adminSearchResult.value.userid
}
const res = await request.put(`/api/community/${currentCommunity.value.id}`, params)
if (res.code === 200) {
message.success('服务商设置成功')
adminModalVisible.value = false
//
fetchData()
} else {
message.error(res.message || '设置失败')
}
} catch (error) {
console.error('设置服务商失败:', error)
message.error('设置失败')
} finally {
adminSaving.value = false
}
}
//
const handleAdminCancel = () => {
adminModalVisible.value = false
adminSearchPhone.value = ''
adminSearchResult.value = null
currentCommunity.value = null
}
onMounted(() => {
fetchData()
})
@ -1023,7 +1202,18 @@ export default defineComponent({
handleProfitSharingCancel,
getTotalRate,
validateTotalRate,
calculatePlatformRate
calculatePlatformRate,
adminModalVisible,
adminSaving,
adminSearching,
adminSearchPhone,
adminSearchResult,
currentCommunity,
handleSetAdmin,
handleSearchAdmin,
handleAdminSave,
handleAdminCancel,
selectSearchResult
}
}
})
@ -1436,6 +1626,7 @@ export default defineComponent({
.action-buttons a {
white-space: nowrap;
padding: 0 4px;
}
:deep(.ant-divider-vertical) {
@ -1484,4 +1675,93 @@ export default defineComponent({
color: rgba(0, 0, 0, 0.45);
line-height: 1.2;
}
/* 服务商设置相关样式 */
.admin-search-form {
margin-bottom: 16px;
}
.admin-search-result {
margin-top: 16px;
margin-bottom: 16px;
}
.admin-card-selected {
border: 2px solid #1890ff;
cursor: pointer;
}
.admin-search-result :deep(.ant-card) {
cursor: pointer;
transition: all 0.3s;
}
.admin-search-result :deep(.ant-card:hover) {
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.15);
}
.current-admin-info {
margin-top: 24px;
border-top: 1px dashed #e8e8e8;
padding-top: 16px;
}
.current-admin-title {
font-size: 14px;
font-weight: 500;
color: rgba(0, 0, 0, 0.85);
margin-bottom: 12px;
}
.admin-info {
background-color: #f9f9f9;
padding: 12px;
border-radius: 4px;
}
.admin-info-item {
margin-bottom: 8px;
display: flex;
}
.admin-info-item:last-child {
margin-bottom: 0;
}
.admin-info-label {
width: 70px;
color: rgba(0, 0, 0, 0.65);
}
.admin-info-value {
flex: 1;
color: rgba(0, 0, 0, 0.85);
font-weight: 500;
}
.no-admin-info {
padding: 16px 0;
}
/* 表格中服务商信息显示样式 */
.admin-info-table {
display: flex;
flex-direction: column;
gap: 4px;
font-size: 12px;
padding: 4px 0;
}
.admin-info-row {
line-height: 1.5;
}
.admin-name {
font-weight: 500;
color: rgba(0, 0, 0, 0.85);
}
.admin-phone {
color: rgba(0, 0, 0, 0.65);
}
</style>

View File

@ -67,6 +67,15 @@
>
恢复
</a-button>
<a-button
type="primary"
ghost
size="small"
:loading="record.runLoading"
@click="runJob(record)"
>
执行
</a-button>
</a-space>
</template>
</template>
@ -178,7 +187,8 @@ export default defineComponent({
// loading
tableData.value = (res.data || []).map(item => ({
...item,
loading: false
loading: false,
runLoading: false
}))
pagination.value.total = tableData.value.length
} else {
@ -271,6 +281,33 @@ export default defineComponent({
}
}
//
const runJob = async (record) => {
try {
// runLoading
const index = tableData.value.findIndex(item => item.id === record.id)
if (index !== -1) {
tableData.value[index].runLoading = true
}
const res = await request.post(`/api/scheduler/jobs/${record.id}/run`)
if (res.code === 200) {
message.success('任务已触发执行')
} else {
message.error(res.message || '操作失败')
}
} catch (error) {
console.error('执行任务失败:', error)
message.error('操作失败')
} finally {
// runLoading
const index = tableData.value.findIndex(item => item.id === record.id)
if (index !== -1) {
tableData.value[index].runLoading = false
}
}
}
onMounted(() => {
refreshData()
})
@ -285,6 +322,7 @@ export default defineComponent({
handleTableChange,
pauseJob,
resumeJob,
runJob,
refreshData
}
}