feat: 完善平台总后台模块
This commit is contained in:
@@ -1,6 +1,6 @@
|
||||
<script setup lang="ts">
|
||||
import { computed, onMounted, reactive, ref } from 'vue';
|
||||
import { platformAPI, type DashboardOverview, type IdnAccount, type OrgDeliveryPoint, type OrgGasStation, type OrgServicePerson, type Profile, type SafEvent } from './api/platform';
|
||||
import { platformAPI, type DashboardOverview, type OrgDeliveryPoint, type OrgGasStation, type OrgServicePerson, type PlatfromAccount, type Profile, type SafEvent } from './api/platform';
|
||||
|
||||
type Tab = 'dashboard' | 'station' | 'delivery' | 'person' | 'user' | 'safety' | 'trade' | 'finance' | 'content' | 'track' | 'operation' | 'audit';
|
||||
type CatalogItem = { title: string; description: string; operations: string[] };
|
||||
@@ -13,12 +13,11 @@ const overview = ref<DashboardOverview>({});
|
||||
const stations = ref<OrgGasStation[]>([]);
|
||||
const deliveryPoints = ref<OrgDeliveryPoint[]>([]);
|
||||
const servicePeople = ref<OrgServicePerson[]>([]);
|
||||
const users = ref<IdnAccount[]>([]);
|
||||
const users = ref<PlatfromAccount[]>([]);
|
||||
const safetyEvents = ref<SafEvent[]>([]);
|
||||
const profile = ref<Profile>();
|
||||
const loginForm = reactive({ username: 'root', password: '' });
|
||||
const stationForm = reactive({ stationCode: '', name: '', principal: '', serviceArea: '' });
|
||||
const passwordForm = reactive({ currentPassword: '', newPassword: '', confirmPassword: '' });
|
||||
|
||||
const tabs: Array<{ key: Tab; label: string }> = [
|
||||
{ key: 'dashboard', label: '运营总览' }, { key: 'station', label: '气站管理' }, { key: 'delivery', label: '配送点管理' },
|
||||
@@ -49,7 +48,7 @@ async function loadData() {
|
||||
try {
|
||||
[profile.value, overview.value, stations.value, deliveryPoints.value, servicePeople.value, users.value, safetyEvents.value] = await Promise.all([
|
||||
platformAPI.getProfile(), platformAPI.getDashboard(), platformAPI.listOrgGasStation(), platformAPI.listOrgDeliveryPoint(),
|
||||
platformAPI.listOrgServicePerson(), platformAPI.listIdnAccount(), platformAPI.listSafEvent(),
|
||||
platformAPI.listOrgServicePerson(), platformAPI.listPlatfromAccount(), platformAPI.listSafEvent(),
|
||||
]);
|
||||
} catch (error) {
|
||||
errorMessage.value = error instanceof Error ? error.message : '加载数据失败';
|
||||
@@ -75,14 +74,6 @@ async function createStation() {
|
||||
finally { loading.value = false; }
|
||||
}
|
||||
|
||||
async function changePassword() {
|
||||
if (passwordForm.newPassword !== passwordForm.confirmPassword) { errorMessage.value = '两次输入的新密码不一致'; return; }
|
||||
loading.value = true;
|
||||
try { await platformAPI.changePassword(passwordForm.currentPassword, passwordForm.newPassword); Object.assign(passwordForm, { currentPassword: '', newPassword: '', confirmPassword: '' }); await loadData(); }
|
||||
catch (error) { errorMessage.value = error instanceof Error ? error.message : '修改密码失败'; }
|
||||
finally { loading.value = false; }
|
||||
}
|
||||
|
||||
onMounted(loadData);
|
||||
</script>
|
||||
|
||||
@@ -90,7 +81,7 @@ onMounted(loadData);
|
||||
<main v-if="!loggedIn" class="login-page">
|
||||
<form class="login-card" @submit.prevent="login">
|
||||
<span class="brand-mark">阀</span><p class="eyebrow">HEQI PLATFORM</p><h1>可燃气体平台总后台</h1>
|
||||
<p>使用平台管理员账号登录。首次登录后必须修改初始密码。</p>
|
||||
<p>使用平台管理员账号登录。</p>
|
||||
<input v-model.trim="loginForm.username" autocomplete="username" placeholder="账号" required />
|
||||
<input v-model="loginForm.password" type="password" autocomplete="current-password" placeholder="密码" required />
|
||||
<p v-if="errorMessage" class="error">{{ errorMessage }}</p><button :disabled="loading" type="submit">{{ loading ? '登录中…' : '登录' }}</button>
|
||||
@@ -99,7 +90,7 @@ onMounted(loadData);
|
||||
|
||||
<main v-else class="shell">
|
||||
<aside class="sidebar">
|
||||
<div class="brand"><span class="brand-mark">阀</span><div><strong>可燃气体平台</strong><small>平台总后台</small></div></div>
|
||||
<div class="brand"><img v-if="profile?.avatar" class="avatar" :src="profile.avatar" :alt="profile.displayName" /><span v-else class="brand-mark">阀</span><div><strong>可燃气体平台</strong><small>平台总后台</small></div></div>
|
||||
<nav><button v-for="tab in tabs" :key="tab.key" :class="{ active: currentTab === tab.key }" @click="currentTab = tab.key">{{ tab.label }}</button></nav>
|
||||
<div class="account"><strong>{{ profile?.displayName || '平台管理员' }}</strong><small>{{ profile?.roleCode || '加载中' }}</small><button class="link-button" @click="logout">退出登录</button></div>
|
||||
</aside>
|
||||
@@ -107,13 +98,11 @@ onMounted(loadData);
|
||||
<section class="content">
|
||||
<header><div><p class="eyebrow">PLATFORM ADMIN</p><h1>{{ activeLabel }}</h1></div><button class="secondary" :disabled="loading" @click="loadData">{{ loading ? '同步中…' : '刷新数据' }}</button></header>
|
||||
<p v-if="errorMessage" class="error">{{ errorMessage }}</p>
|
||||
<article v-if="profile?.mustChangePassword" class="panel warning"><h2>首次登录安全设置</h2><p>root 初始密码仅可用于首次进入,请立即设置不少于 12 位的新密码。</p><form class="password-form" @submit.prevent="changePassword"><input v-model="passwordForm.currentPassword" type="password" placeholder="当前密码" required /><input v-model="passwordForm.newPassword" type="password" placeholder="新密码(至少 12 位)" required /><input v-model="passwordForm.confirmPassword" type="password" placeholder="确认新密码" required /><button :disabled="loading">修改密码</button></form></article>
|
||||
|
||||
<template v-if="currentTab === 'dashboard'"><div class="cards"><article v-for="([label, value]) in overviewCards" :key="label"><span>{{ label }}</span><strong>{{ value }}</strong></article></div><article class="panel"><h2>平台职责边界</h2><p>统一管理所有气站、配送点、服务人员和用户,并对可燃气体业务的安全、订单配送轨迹、资金结算、邀请二维码和高风险操作保留审计闭环。</p></article></template>
|
||||
<template v-if="currentTab === 'station'"><article class="panel"><h2>创建气站</h2><form @submit.prevent="createStation"><input v-model.trim="stationForm.stationCode" placeholder="气站编码,例如 GS-1002" /><input v-model.trim="stationForm.name" placeholder="气站名称" /><input v-model.trim="stationForm.principal" placeholder="负责人" /><input v-model.trim="stationForm.serviceArea" placeholder="服务区域" /><button :disabled="loading">提交审核</button></form><p>气站可继续管理其配送点、服务人员、用户及专属邀请注册二维码。</p></article><DataTable :headers="['编码', '名称', '负责人', '服务区域', '状态']" :rows="stations.map((item) => [item.stationCode, item.name, item.principal, item.serviceArea, item.status])" /></template>
|
||||
<template v-if="currentTab === 'delivery'"><article class="panel"><h2>配送点管理边界</h2><p>配送点归属气站,负责管理服务人员、用户、配送班次、订单交付与配送轨迹;平台可跨组织查看、审核、冻结和迁移。</p></article><DataTable :headers="['编码', '配送点', '归属气站', '服务区域', '状态']" :rows="deliveryPoints.map((item) => [item.deliveryCode, item.name, item.gasStationName, item.serviceArea, item.status])" /></template>
|
||||
<template v-if="currentTab === 'person'"><article class="panel"><h2>服务人员生命周期</h2><p>覆盖安装维修、安检、配送角色、资质、登录设备、接单状态、任务绩效及停用留档。</p></article><DataTable :headers="['姓名', '手机号', '角色', '工作状态', '资质状态']" :rows="servicePeople.map((item) => [item.name, item.phoneMasked, item.roles, item.workStatus, item.credentialStatus])" /></template>
|
||||
<template v-if="currentTab === 'user'"><article class="panel"><h2>用户 360° 管理</h2><p>统一查看用户资料、地址、智能瓶阀、订单、权益、投诉与风险处置;敏感信息按最小化原则展示。</p></article><DataTable :headers="['手机号', '账户类型', '状态', '服务区域']" :rows="users.map((item) => [item.phoneMasked, item.accountType, item.status, item.serviceArea])" /></template>
|
||||
<template v-if="currentTab === 'user'"><article class="panel"><h2>平台账户管理</h2><p>统一查看平台账户资料、角色、头像、手机号、状态与操作记录;敏感信息按最小化原则展示。</p></article><DataTable :headers="['账号', '名称', '头像', '手机号', '角色', '状态']" :rows="users.map((item) => [item.username, item.displayName, item.avatar || '未设置', item.phoneMasked, item.roleCode, item.status])" /></template>
|
||||
<template v-if="currentTab === 'safety'"><article class="panel"><h2>安全运营中心</h2><p>对智能瓶阀告警、安检异常、可燃气体风险、资质临期与订单异常进行分级、派发、升级和复盘。</p></article><DataTable :headers="['事件编码', '等级', '事件说明', '状态', '创建时间']" :rows="safetyEvents.map((item) => [item.eventCode, `${item.level} 级`, item.title, item.status, new Date(item.createdAt).toLocaleString()])" /></template>
|
||||
<template v-if="catalog[currentTab]"><div class="catalog"><article v-for="item in catalog[currentTab]" :key="item.title" class="panel"><h2>{{ item.title }}</h2><p>{{ item.description }}</p><div class="tags"><span v-for="operation in item.operations" :key="operation">{{ operation }}</span></div></article></div></template>
|
||||
</section>
|
||||
|
||||
Reference in New Issue
Block a user