Files
erp_sb/electron-vue-template/src/renderer/components/common/AccountManager.vue
2025-09-25 16:04:00 +08:00

132 lines
5.6 KiB
Vue
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<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'])
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 : []
}
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()
}
</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>