feat(distribution): 分销站点管理支持完整 CRUD、安全删除保护与管理员密码重置
- 后端支持分销站点编辑(域名唯一性校验、收号压价点位及税率更新) - 后端支持分销站点安全删除校验(阻断存在业务订单、财务流水、结算批次或钱包余额的站点删除;对干净站点连带清理分成规则、展示账号绑定、支付通道配置及专有站长账号) - 后端支持站长账号展示与超级管理员重置站长密码 - 主管理后台与分销后台前端全面支持筛选搜索、编辑模态窗、状态快捷切换、站长密码重置与安全删除确认 - 补充后端 CRUD、删除保护与密码重置覆盖率测试用例
This commit is contained in:
@@ -14,6 +14,10 @@ export interface DistributionSite {
|
||||
listing_qrcode_url?: string
|
||||
receive_ratio_delta?: number
|
||||
receive_cost_delta?: number
|
||||
admin_user_id?: number
|
||||
admin_username?: string
|
||||
admin_nickname?: string
|
||||
member_type?: string
|
||||
created_at: string
|
||||
}
|
||||
|
||||
@@ -166,6 +170,21 @@ export async function updateDistributionSite(
|
||||
return data.data
|
||||
}
|
||||
|
||||
export async function deleteDistributionSite(id: number) {
|
||||
const { data } = await apiClient.delete<ApiResponse<{ deleted: boolean }>>(
|
||||
`/admin/distribution/sites/${id}`
|
||||
)
|
||||
return data.data
|
||||
}
|
||||
|
||||
export async function resetDistributionSiteAdminPassword(id: number, newPassword: string) {
|
||||
const { data } = await apiClient.put<ApiResponse<{ message: string }>>(
|
||||
`/admin/distribution/sites/${id}/admin-password`,
|
||||
{ new_password: newPassword }
|
||||
)
|
||||
return data.data
|
||||
}
|
||||
|
||||
export async function fetchDistributionRules(siteId?: number, mode?: string) {
|
||||
const { data } = await apiClient.get<ApiResponse<{ items: DistributionRule[] }>>(
|
||||
'/admin/distribution/rules',
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
<script setup lang="ts">
|
||||
import { ref, reactive, onMounted, onUnmounted } from 'vue'
|
||||
import { ref, reactive, computed, onMounted, onUnmounted } from 'vue'
|
||||
import { ElMessage, ElMessageBox, type FormInstance, type FormRules } from 'element-plus'
|
||||
import {
|
||||
Plus,
|
||||
@@ -12,6 +12,11 @@ import {
|
||||
Upload,
|
||||
Coin,
|
||||
Message,
|
||||
Edit,
|
||||
Delete,
|
||||
Search,
|
||||
Key,
|
||||
ArrowDown,
|
||||
} from '@element-plus/icons-vue'
|
||||
import {
|
||||
fetchDistributionSites,
|
||||
@@ -19,6 +24,8 @@ import {
|
||||
onboardDistributionSite,
|
||||
syncDistributionSiteAccounts,
|
||||
updateDistributionSite,
|
||||
deleteDistributionSite,
|
||||
resetDistributionSiteAdminPassword,
|
||||
fetchDistributionSiteSMSConfig,
|
||||
updateDistributionSiteSMSConfig,
|
||||
testDistributionSiteSMSConfig,
|
||||
@@ -39,6 +46,47 @@ const loading = ref(false)
|
||||
const sites = ref<DistributionSite[]>([])
|
||||
const defaultSettlementHoldDays = ref(7)
|
||||
|
||||
// 筛选检索状态
|
||||
const searchQuery = ref('')
|
||||
const statusFilter = ref('')
|
||||
const displayAccountFilter = ref('')
|
||||
|
||||
const filteredSites = computed(() => {
|
||||
return sites.value.filter(site => {
|
||||
if (statusFilter.value && site.status !== statusFilter.value) {
|
||||
return false
|
||||
}
|
||||
if (displayAccountFilter.value !== '') {
|
||||
const want = displayAccountFilter.value === 'true'
|
||||
if (site.display_account_enabled !== want) return false
|
||||
}
|
||||
if (searchQuery.value.trim()) {
|
||||
const q = searchQuery.value.trim().toLowerCase()
|
||||
const matchName = site.site_name?.toLowerCase().includes(q)
|
||||
const matchCode = site.site_code?.toLowerCase().includes(q)
|
||||
const matchDomain = site.domain?.toLowerCase().includes(q)
|
||||
const matchAdmin =
|
||||
site.admin_username?.toLowerCase().includes(q) ||
|
||||
site.admin_nickname?.toLowerCase().includes(q)
|
||||
if (!matchName && !matchCode && !matchDomain && !matchAdmin) {
|
||||
return false
|
||||
}
|
||||
}
|
||||
return true
|
||||
})
|
||||
})
|
||||
|
||||
function handleResetFilter() {
|
||||
searchQuery.value = ''
|
||||
statusFilter.value = ''
|
||||
displayAccountFilter.value = ''
|
||||
}
|
||||
|
||||
function copyDomain(domain: string) {
|
||||
navigator.clipboard?.writeText(domain)
|
||||
ElMessage.success('域名已复制到剪贴板')
|
||||
}
|
||||
|
||||
const onboardDialogVisible = ref(false)
|
||||
const submitting = ref(false)
|
||||
const onboardFormRef = ref<FormInstance>()
|
||||
@@ -452,6 +500,160 @@ async function handleSyncAccounts(row: DistributionSite) {
|
||||
}
|
||||
}
|
||||
|
||||
// 站点编辑状态
|
||||
const editDialogVisible = ref(false)
|
||||
const editSubmitting = ref(false)
|
||||
const editFormRef = ref<FormInstance>()
|
||||
const editForm = reactive({
|
||||
id: 0,
|
||||
site_code: '',
|
||||
site_name: '',
|
||||
domain: '',
|
||||
status: 'active',
|
||||
display_account_enabled: true,
|
||||
settlement_hold_days: defaultSettlementHoldDays.value,
|
||||
receive_cost_delta: 0,
|
||||
tax_enabled: false,
|
||||
tax_rate_bps: 100,
|
||||
admin_username: '',
|
||||
})
|
||||
|
||||
const editRules: FormRules = {
|
||||
site_name: [{ required: true, message: '请输入分销站点名称', trigger: 'blur' }],
|
||||
domain: [{ required: true, message: '请输入分销专属域名', trigger: 'blur' }],
|
||||
}
|
||||
|
||||
function handleOpenEdit(row: DistributionSite) {
|
||||
editForm.id = row.id
|
||||
editForm.site_code = row.site_code
|
||||
editForm.site_name = row.site_name
|
||||
editForm.domain = row.domain
|
||||
editForm.status = row.status || 'active'
|
||||
editForm.display_account_enabled = !!row.display_account_enabled
|
||||
editForm.settlement_hold_days = row.settlement_hold_days ?? defaultSettlementHoldDays.value
|
||||
editForm.receive_cost_delta = Number(row.receive_cost_delta || 0)
|
||||
editForm.tax_enabled = !!row.tax_enabled
|
||||
editForm.tax_rate_bps = row.tax_rate_bps ?? 100
|
||||
editForm.admin_username = row.admin_username || ''
|
||||
editDialogVisible.value = true
|
||||
}
|
||||
|
||||
async function handleEditSubmit() {
|
||||
if (!editFormRef.value) return
|
||||
await editFormRef.value.validate(async valid => {
|
||||
if (!valid) return
|
||||
editSubmitting.value = true
|
||||
try {
|
||||
await updateDistributionSite(editForm.id, {
|
||||
site_name: editForm.site_name.trim(),
|
||||
domain: editForm.domain.trim(),
|
||||
status: editForm.status,
|
||||
display_account_enabled: editForm.display_account_enabled,
|
||||
settlement_hold_days: Number(editForm.settlement_hold_days),
|
||||
receive_cost_delta: Number(editForm.receive_cost_delta),
|
||||
tax_enabled: editForm.tax_enabled,
|
||||
tax_rate_bps: editForm.tax_enabled ? Number(editForm.tax_rate_bps) : 0,
|
||||
})
|
||||
ElMessage.success(`【${editForm.site_name}】分销站点信息已更新`)
|
||||
editDialogVisible.value = false
|
||||
await loadSites()
|
||||
} catch (err) {
|
||||
ElMessage.error(readError(err, '更新分销站点信息失败'))
|
||||
} finally {
|
||||
editSubmitting.value = false
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
// 快速启停状态
|
||||
async function handleToggleStatus(row: DistributionSite) {
|
||||
const isCurrentlyActive = row.status === 'active'
|
||||
const newStatus = isCurrentlyActive ? 'disabled' : 'active'
|
||||
const actionText = isCurrentlyActive ? '停用' : '启用'
|
||||
const confirmMsg = isCurrentlyActive
|
||||
? `确认停用分销站点【${row.site_name}】?停用后该站点前台将暂停服务,无法进行租号与收号。`
|
||||
: `确认重新启用分销站点【${row.site_name}】?启用后该站点将恢复正常对外运营。`
|
||||
|
||||
try {
|
||||
await ElMessageBox.confirm(confirmMsg, `确认${actionText}分销站点`, {
|
||||
confirmButtonText: `确认${actionText}`,
|
||||
cancelButtonText: '取消',
|
||||
type: isCurrentlyActive ? 'warning' : 'info',
|
||||
})
|
||||
} catch {
|
||||
return
|
||||
}
|
||||
|
||||
try {
|
||||
await updateDistributionSite(row.id, { status: newStatus })
|
||||
ElMessage.success(`分销站点【${row.site_name}】已${actionText}`)
|
||||
await loadSites()
|
||||
} catch (err) {
|
||||
ElMessage.error(readError(err, `${actionText}分销站点失败`))
|
||||
}
|
||||
}
|
||||
|
||||
// 重置分销商密码状态
|
||||
const resetPwdDialogVisible = ref(false)
|
||||
const resetPwdSubmitting = ref(false)
|
||||
const resetPwdForm = reactive({
|
||||
site_id: 0,
|
||||
site_name: '',
|
||||
admin_username: '',
|
||||
new_password: '',
|
||||
})
|
||||
|
||||
function handleOpenResetPassword(row: DistributionSite) {
|
||||
resetPwdForm.site_id = row.id
|
||||
resetPwdForm.site_name = row.site_name
|
||||
resetPwdForm.admin_username = row.admin_username || '专属管理员'
|
||||
resetPwdForm.new_password = ''
|
||||
resetPwdDialogVisible.value = true
|
||||
}
|
||||
|
||||
async function handleResetPasswordSubmit() {
|
||||
if (!resetPwdForm.new_password || resetPwdForm.new_password.length < 6) {
|
||||
ElMessage.warning('新密码长度不能少于6位')
|
||||
return
|
||||
}
|
||||
resetPwdSubmitting.value = true
|
||||
try {
|
||||
await resetDistributionSiteAdminPassword(resetPwdForm.site_id, resetPwdForm.new_password)
|
||||
ElMessage.success(`【${resetPwdForm.site_name}】管理员密码重置成功!`)
|
||||
resetPwdDialogVisible.value = false
|
||||
} catch (err) {
|
||||
ElMessage.error(readError(err, '重置分销商密码失败'))
|
||||
} finally {
|
||||
resetPwdSubmitting.value = false
|
||||
}
|
||||
}
|
||||
|
||||
// 删除分销站点
|
||||
async function handleDeleteSite(row: DistributionSite) {
|
||||
try {
|
||||
await ElMessageBox.confirm(
|
||||
`确定要删除分销站点【${row.site_name}】(${row.site_code}) 吗?\n此操作将永久清理该分销站及其规则、上架关系与专属管理员账号。\n若该分销站点已产生业务订单或分账流水,系统将予以拦截保护。`,
|
||||
'警告:确认删除分销站点',
|
||||
{
|
||||
confirmButtonText: '确认删除',
|
||||
cancelButtonText: '取消',
|
||||
type: 'error',
|
||||
confirmButtonClass: 'el-button--danger',
|
||||
}
|
||||
)
|
||||
} catch {
|
||||
return
|
||||
}
|
||||
|
||||
try {
|
||||
await deleteDistributionSite(row.id)
|
||||
ElMessage.success(`分销站点【${row.site_name}】已成功删除`)
|
||||
await loadSites()
|
||||
} catch (err) {
|
||||
ElMessage.error(readError(err, '删除分销站点失败'))
|
||||
}
|
||||
}
|
||||
|
||||
onMounted(() => {
|
||||
loadSites()
|
||||
fetchDistributionSiteDefaults()
|
||||
@@ -486,7 +688,38 @@ onMounted(() => {
|
||||
</div>
|
||||
|
||||
<el-card shadow="never">
|
||||
<el-table v-loading="loading" :data="sites" stripe style="width: 100%">
|
||||
<!-- 搜索筛选栏 -->
|
||||
<div class="filter-bar">
|
||||
<el-input
|
||||
v-model="searchQuery"
|
||||
placeholder="搜索站点名称 / 标识 / 域名 / 管理员"
|
||||
clearable
|
||||
:prefix-icon="Search"
|
||||
style="width: 280px"
|
||||
/>
|
||||
<el-select v-model="statusFilter" placeholder="运行状态" clearable style="width: 130px">
|
||||
<el-option label="全部状态" value="" />
|
||||
<el-option label="正常运营" value="active" />
|
||||
<el-option label="已停用" value="disabled" />
|
||||
</el-select>
|
||||
<el-select
|
||||
v-model="displayAccountFilter"
|
||||
placeholder="展示主站账号"
|
||||
clearable
|
||||
style="width: 140px"
|
||||
>
|
||||
<el-option label="全部" value="" />
|
||||
<el-option label="已开启" value="true" />
|
||||
<el-option label="已关闭" value="false" />
|
||||
</el-select>
|
||||
<el-button @click="handleResetFilter">重置筛选</el-button>
|
||||
<el-button :icon="Refresh" @click="loadSites">刷新</el-button>
|
||||
<div class="filter-stats">
|
||||
共 <strong>{{ filteredSites.length }}</strong> 个分销站点
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<el-table v-loading="loading" :data="filteredSites" stripe style="width: 100%">
|
||||
<el-table-column label="站点名称" prop="site_name" min-width="160">
|
||||
<template #default="{ row }">
|
||||
<div class="site-name-cell">
|
||||
@@ -500,22 +733,55 @@ onMounted(() => {
|
||||
<el-tag size="small">{{ row.site_code }}</el-tag>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="绑定域名" prop="domain" min-width="180" />
|
||||
<el-table-column label="运行状态" prop="status" width="100">
|
||||
<el-table-column label="绑定域名" prop="domain" min-width="190">
|
||||
<template #default="{ row }">
|
||||
<el-tag :type="row.status === 'active' ? 'success' : 'info'" size="small">
|
||||
{{ row.status === 'active' ? '正常' : '已停用' }}
|
||||
</el-tag>
|
||||
<div class="domain-cell">
|
||||
<span class="domain-text">{{ row.domain }}</span>
|
||||
<el-button
|
||||
:icon="DocumentCopy"
|
||||
link
|
||||
size="small"
|
||||
title="复制域名"
|
||||
@click="copyDomain(row.domain)"
|
||||
/>
|
||||
</div>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="展示主站账号" prop="display_account_enabled" width="130">
|
||||
<el-table-column label="分销管理员" min-width="140">
|
||||
<template #default="{ row }">
|
||||
<div v-if="row.admin_username" class="admin-cell">
|
||||
<el-tag size="small" type="info">{{ row.admin_username }}</el-tag>
|
||||
<span v-if="row.admin_nickname" class="admin-nickname"
|
||||
>({{ row.admin_nickname }})</span
|
||||
>
|
||||
</div>
|
||||
<span v-else class="text-muted">未关联</span>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="运行状态" prop="status" width="110">
|
||||
<template #default="{ row }">
|
||||
<el-tooltip
|
||||
:content="row.status === 'active' ? '点击可停用分销站点' : '点击可启用分销站点'"
|
||||
placement="top"
|
||||
>
|
||||
<el-switch
|
||||
:model-value="row.status === 'active'"
|
||||
inline-prompt
|
||||
active-text="正常"
|
||||
inactive-text="停用"
|
||||
@click.prevent="handleToggleStatus(row)"
|
||||
/>
|
||||
</el-tooltip>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="展示主站账号" prop="display_account_enabled" width="120">
|
||||
<template #default="{ row }">
|
||||
<el-tag :type="row.display_account_enabled ? 'success' : 'info'" size="small">
|
||||
{{ row.display_account_enabled ? '已开启' : '关闭' }}
|
||||
</el-tag>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="税费设定" width="120">
|
||||
<el-table-column label="税费设定" width="110">
|
||||
<template #default="{ row }">
|
||||
<el-tag v-if="row.tax_enabled" type="warning" size="small">
|
||||
{{ (row.tax_rate_bps / 100).toFixed(1) }}%
|
||||
@@ -561,8 +827,11 @@ onMounted(() => {
|
||||
{{ formatDateTime(row.created_at) }}
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="操作" width="410" fixed="right">
|
||||
<el-table-column label="操作" width="220" fixed="right">
|
||||
<template #default="{ row }">
|
||||
<el-button type="primary" link :icon="Edit" @click="handleOpenEdit(row)">
|
||||
编辑
|
||||
</el-button>
|
||||
<el-button
|
||||
type="primary"
|
||||
link
|
||||
@@ -572,18 +841,38 @@ onMounted(() => {
|
||||
>
|
||||
同步商品
|
||||
</el-button>
|
||||
<el-button type="primary" link :icon="Clock" @click="handleOpenSettlement(row)">
|
||||
结算设置
|
||||
</el-button>
|
||||
<el-button type="primary" link :icon="Coin" @click="handleOpenReceiveRatio(row)">
|
||||
收号比例
|
||||
</el-button>
|
||||
<el-button type="primary" link :icon="Picture" @click="handleOpenQrcode(row)">
|
||||
二维码
|
||||
</el-button>
|
||||
<el-button type="primary" link :icon="Message" @click="handleOpenSMS(row)">
|
||||
短信配置
|
||||
</el-button>
|
||||
<el-dropdown trigger="click">
|
||||
<el-button type="primary" link>
|
||||
更多<el-icon class="el-icon--right"><ArrowDown /></el-icon>
|
||||
</el-button>
|
||||
<template #dropdown>
|
||||
<el-dropdown-menu>
|
||||
<el-dropdown-item :icon="Clock" @click="handleOpenSettlement(row)">
|
||||
结算设置
|
||||
</el-dropdown-item>
|
||||
<el-dropdown-item :icon="Coin" @click="handleOpenReceiveRatio(row)">
|
||||
收号比例
|
||||
</el-dropdown-item>
|
||||
<el-dropdown-item :icon="Picture" @click="handleOpenQrcode(row)">
|
||||
发布二维码
|
||||
</el-dropdown-item>
|
||||
<el-dropdown-item :icon="Message" @click="handleOpenSMS(row)">
|
||||
短信配置
|
||||
</el-dropdown-item>
|
||||
<el-dropdown-item :icon="Key" @click="handleOpenResetPassword(row)">
|
||||
重置管理员密码
|
||||
</el-dropdown-item>
|
||||
<el-dropdown-item
|
||||
divided
|
||||
:icon="Delete"
|
||||
style="color: #f56c6c"
|
||||
@click="handleDeleteSite(row)"
|
||||
>
|
||||
删除站点
|
||||
</el-dropdown-item>
|
||||
</el-dropdown-menu>
|
||||
</template>
|
||||
</el-dropdown>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
@@ -926,6 +1215,144 @@ onMounted(() => {
|
||||
</el-button>
|
||||
</template>
|
||||
</el-dialog>
|
||||
|
||||
<!-- 编辑分销站点对话框 -->
|
||||
<el-dialog v-model="editDialogVisible" title="编辑分销站点" width="620px" destroy-on-close>
|
||||
<el-form ref="editFormRef" :model="editForm" :rules="editRules" label-width="130px">
|
||||
<el-row :gutter="16">
|
||||
<el-col :span="12">
|
||||
<el-form-item label="站点标识">
|
||||
<el-tag size="default" type="info">{{ editForm.site_code }}</el-tag>
|
||||
<span style="margin-left: 8px; font-size: 12px; color: #9ca3af">不可更改</span>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="12">
|
||||
<el-form-item label="分销管理员">
|
||||
<span v-if="editForm.admin_username" style="font-weight: 500">
|
||||
{{ editForm.admin_username }}
|
||||
</span>
|
||||
<span v-else style="color: #9ca3af">未关联</span>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
</el-row>
|
||||
|
||||
<el-form-item label="站点名称" prop="site_name">
|
||||
<el-input v-model="editForm.site_name" placeholder="请输入分销站点名称" />
|
||||
</el-form-item>
|
||||
|
||||
<el-form-item label="分销专属域名" prop="domain">
|
||||
<el-input v-model="editForm.domain" placeholder="请输入绑定的独立域名" />
|
||||
</el-form-item>
|
||||
|
||||
<el-form-item label="运行状态" prop="status">
|
||||
<el-radio-group v-model="editForm.status">
|
||||
<el-radio value="active">正常运营</el-radio>
|
||||
<el-radio value="disabled">暂停服务 (已停用)</el-radio>
|
||||
</el-radio-group>
|
||||
</el-form-item>
|
||||
|
||||
<el-row :gutter="16">
|
||||
<el-col :span="12">
|
||||
<el-form-item label="展示主站账号">
|
||||
<el-switch v-model="editForm.display_account_enabled" />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="12">
|
||||
<el-form-item label="是否征税">
|
||||
<el-switch v-model="editForm.tax_enabled" />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
</el-row>
|
||||
|
||||
<el-row :gutter="16" v-if="editForm.tax_enabled">
|
||||
<el-col :span="24">
|
||||
<el-form-item label="综合税率 (%)">
|
||||
<el-input-number
|
||||
:model-value="editForm.tax_rate_bps / 100"
|
||||
:min="0"
|
||||
:max="50"
|
||||
:step="0.1"
|
||||
:precision="2"
|
||||
@update:model-value="
|
||||
(v: number | undefined) => (editForm.tax_rate_bps = Math.round((v || 0) * 100))
|
||||
"
|
||||
/>
|
||||
<span class="settlement-hint">%(基点折算)</span>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
</el-row>
|
||||
|
||||
<el-row :gutter="16">
|
||||
<el-col :span="12">
|
||||
<el-form-item label="结算冷却期 (天)">
|
||||
<el-input-number
|
||||
v-model="editForm.settlement_hold_days"
|
||||
:min="0"
|
||||
:max="365"
|
||||
:step="1"
|
||||
style="width: 100%"
|
||||
/>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="12">
|
||||
<el-form-item label="收号压价 (点)">
|
||||
<el-input-number
|
||||
v-model="editForm.receive_cost_delta"
|
||||
:min="0"
|
||||
:max="20"
|
||||
:step="0.1"
|
||||
:precision="1"
|
||||
style="width: 100%"
|
||||
/>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
</el-row>
|
||||
</el-form>
|
||||
<template #footer>
|
||||
<el-button @click="editDialogVisible = false">取消</el-button>
|
||||
<el-button type="primary" :loading="editSubmitting" @click="handleEditSubmit">
|
||||
保存修改
|
||||
</el-button>
|
||||
</template>
|
||||
</el-dialog>
|
||||
|
||||
<!-- 重置分销商管理员密码对话框 -->
|
||||
<el-dialog
|
||||
v-model="resetPwdDialogVisible"
|
||||
title="重置分销商管理员密码"
|
||||
width="460px"
|
||||
destroy-on-close
|
||||
>
|
||||
<el-alert
|
||||
type="warning"
|
||||
:closable="false"
|
||||
show-icon
|
||||
title="重置后旧密码将立即失效,分销商管理员需使用新密码重新登录独立分销后台。"
|
||||
style="margin-bottom: 16px"
|
||||
/>
|
||||
<el-form label-width="110px">
|
||||
<el-form-item label="分销站点">
|
||||
<el-input :model-value="resetPwdForm.site_name" disabled />
|
||||
</el-form-item>
|
||||
<el-form-item label="管理员账号">
|
||||
<el-input :model-value="resetPwdForm.admin_username" disabled />
|
||||
</el-form-item>
|
||||
<el-form-item label="新登录密码" required>
|
||||
<el-input
|
||||
v-model="resetPwdForm.new_password"
|
||||
type="password"
|
||||
show-password
|
||||
placeholder="请输入至少6位新登录密码"
|
||||
/>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
<template #footer>
|
||||
<el-button @click="resetPwdDialogVisible = false">取消</el-button>
|
||||
<el-button type="primary" :loading="resetPwdSubmitting" @click="handleResetPasswordSubmit">
|
||||
确认重置密码
|
||||
</el-button>
|
||||
</template>
|
||||
</el-dialog>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
@@ -959,6 +1386,51 @@ onMounted(() => {
|
||||
gap: 12px;
|
||||
}
|
||||
|
||||
.filter-bar {
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
align-items: center;
|
||||
gap: 12px;
|
||||
margin-bottom: 16px;
|
||||
}
|
||||
|
||||
.filter-stats {
|
||||
margin-left: auto;
|
||||
font-size: 13px;
|
||||
color: #6b7280;
|
||||
}
|
||||
|
||||
.filter-stats strong {
|
||||
color: #1f2937;
|
||||
}
|
||||
|
||||
.domain-cell {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 4px;
|
||||
}
|
||||
|
||||
.domain-text {
|
||||
font-family: monospace;
|
||||
font-size: 13px;
|
||||
}
|
||||
|
||||
.admin-cell {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 4px;
|
||||
}
|
||||
|
||||
.admin-nickname {
|
||||
font-size: 12px;
|
||||
color: #6b7280;
|
||||
}
|
||||
|
||||
.text-muted {
|
||||
color: #9ca3af;
|
||||
font-size: 13px;
|
||||
}
|
||||
|
||||
.site-name-cell {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
|
||||
Reference in New Issue
Block a user