136 lines
5.7 KiB
Vue
136 lines
5.7 KiB
Vue
<script setup lang="ts">
|
||
import { ref, onMounted, computed } from 'vue'
|
||
import { zebraApi, type BanmaAccount } from '../../api/zebra'
|
||
import { ElMessageBox, ElMessage } from 'element-plus'
|
||
|
||
type PlatformKey = 'zebra' | 'shopee' | 'rakuten' | 'amazon'
|
||
|
||
const props = defineProps<{ modelValue: boolean; platform?: PlatformKey }>()
|
||
const emit = defineEmits(['update:modelValue', 'add', 'refresh'])
|
||
const visible = computed({ get: () => props.modelValue, set: v => emit('update:modelValue', v) })
|
||
const curPlatform = ref<PlatformKey>(props.platform || 'zebra')
|
||
const PLATFORM_LABEL: Record<PlatformKey, string> = {
|
||
zebra: '斑马 ERP',
|
||
shopee: 'Shopee 虾皮购物',
|
||
rakuten: 'Rakuten 乐天购物',
|
||
amazon: 'Amazon 亚马逊'
|
||
}
|
||
|
||
const accounts = ref<BanmaAccount[]>([])
|
||
async function load() {
|
||
// 目前后端只有斑马接口,其它平台先共用此接口占位
|
||
const res = await zebraApi.getAccounts()
|
||
const list = (res as any)?.data ?? res
|
||
accounts.value = Array.isArray(list) ? list : []
|
||
}
|
||
|
||
// 暴露方法供父组件调用
|
||
defineExpose({ load })
|
||
onMounted(load)
|
||
|
||
function switchPlatform(p: PlatformKey) {
|
||
curPlatform.value = p
|
||
load()
|
||
}
|
||
|
||
function formatDate(a: any) {
|
||
const v = a?.updateTime || a?.createTime
|
||
return v ? String(v) : '-'
|
||
}
|
||
|
||
async function onDelete(a: any) {
|
||
const id = a?.id
|
||
try {
|
||
await ElMessageBox.confirm(`确定删除账号 "${a?.name || a?.username || id}" 吗?`, '提示', { type: 'warning' })
|
||
} catch { return }
|
||
await zebraApi.removeAccount(id)
|
||
ElMessage({ message: '删除成功', type: 'success' })
|
||
await load()
|
||
emit('refresh') // 通知外层组件刷新账号列表
|
||
}
|
||
</script>
|
||
|
||
<script lang="ts">
|
||
import { defineComponent } from 'vue'
|
||
export default defineComponent({ name: 'AccountManager' })
|
||
</script>
|
||
|
||
<template>
|
||
<el-dialog v-model="visible" width="550px" class="acc-manager" :show-close="true">
|
||
<template #header>
|
||
<div class="dlg-header"></div>
|
||
</template>
|
||
|
||
<div class="layout">
|
||
<aside class="sider">
|
||
<div class="sider-title">全账号管理</div>
|
||
<div class="nav only-zebra">
|
||
<div :class="['nav-item', {active: curPlatform==='zebra'}]" @click="switchPlatform('zebra')">斑马 ERP</div>
|
||
</div>
|
||
</aside>
|
||
<section class="content">
|
||
<div class="platform-bar">{{ PLATFORM_LABEL[curPlatform] }}</div>
|
||
<div class="top">
|
||
<img src="/icon/image.png" class="hero" alt="logo" />
|
||
<div class="head-main">
|
||
<div class="main-title">在线账号管理(3/3)</div>
|
||
<div class="main-sub">
|
||
您当前订阅可同时托管3家 Shopee 店铺<br>
|
||
如需扩增同时托管店铺数,请 <span class="upgrade">升级订阅</span>。
|
||
</div>
|
||
</div>
|
||
</div>
|
||
<div class="list" :class="{ compact: accounts.length <= 1 }">
|
||
<div v-for="a in accounts" :key="a.id" class="row">
|
||
<span :class="['dot', a.status === 1 ? 'on' : 'off']"></span>
|
||
<div class="user-info">
|
||
<img class="avatar" src="/image/img_v3_02qd_052605f0-4be3-44db-9691-35ee5ff6201g.jpg" />
|
||
<span class="name">{{ a.name || a.username }}</span>
|
||
</div>
|
||
<span class="date">{{ formatDate(a) }}</span>
|
||
<el-button link type="danger" @click="onDelete(a)">删除</el-button>
|
||
</div>
|
||
</div>
|
||
<div class="footer">
|
||
<el-button type="primary" class="btn" @click="$emit('add')">添加账号</el-button>
|
||
</div>
|
||
</section>
|
||
</div>
|
||
</el-dialog>
|
||
</template>
|
||
|
||
<style scoped>
|
||
.acc-manager :deep(.el-dialog__header) { text-align:center; }
|
||
.layout { display:grid; grid-template-columns: 160px 1fr; gap: 12px; min-height: 340px; }
|
||
.sider { border-right: 1px solid #ebeef5; padding-right: 10px; }
|
||
.sider-title { color:#303133; font-size:13px; font-weight: 600; margin-bottom: 10px; text-align: left; }
|
||
.nav { display:flex; flex-direction: column; gap: 4px; }
|
||
.nav-item { padding: 6px 8px; border-radius: 4px; cursor: pointer; color:#606266; font-size: 12px; transition: all 0.2s; text-align: left; }
|
||
.nav-item:hover { background:#f0f2f5; }
|
||
.nav-item.active { background:#e6f4ff; color:#409EFF; font-weight: 600; }
|
||
.platform-bar { font-weight: 600; color:#303133; margin: 0 0 12px 0; text-align: left; font-size: 14px; padding-bottom: 8px; border-bottom: 1px solid #ebeef5; }
|
||
.content { display:flex; flex-direction: column; min-width: 0; }
|
||
.top { display:flex; flex-direction: column; align-items:center; gap: 6px; margin-bottom: 12px; }
|
||
.hero { width: 160px; height: auto; }
|
||
.head-main { text-align:center; }
|
||
.main-title { font-size: 16px; font-weight: 600; color:#303133; margin-bottom: 4px; }
|
||
.main-sub { color:#909399; font-size: 11px; line-height: 1.4; }
|
||
.upgrade { color:#409EFF; cursor: pointer; }
|
||
.list { border:1px solid #ebeef5; border-radius: 6px; background: #fff; flex: 0 0 auto; width: 100%; max-height: 160px; overflow-y: auto; }
|
||
.list.compact { max-height: 48px; }
|
||
.row { display:grid; grid-template-columns: 8px 1fr 120px 60px; gap: 8px; align-items:center; padding: 4px 8px; border-bottom: 1px solid #f5f5f5; height: 28px; }
|
||
.row:last-child { border-bottom:none; }
|
||
.row:hover { background:#fafafa; }
|
||
.dot { width:6px; height:6px; border-radius:50%; justify-self: center; }
|
||
.dot.on { background:#52c41a; }
|
||
.dot.off { background:#ff4d4f; }
|
||
.user-info { display: flex; align-items: center; gap: 8px; min-width: 0; }
|
||
.avatar { width:22px; height:22px; border-radius:50%; object-fit: cover; }
|
||
.name { font-weight:500; font-size: 13px; color:#303133; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
|
||
.date { color:#999; font-size:11px; text-align: center; }
|
||
.footer { display:flex; justify-content:center; padding-top: 10px; }
|
||
.btn { width: 180px; height: 32px; font-size: 13px; }
|
||
</style>
|
||
|
||
|