优化
This commit is contained in:
@@ -1,11 +1,11 @@
|
||||
import { http, unwrapApiResponse, type ApiEnvelope } from '@/api/http'
|
||||
|
||||
export interface PlatformPermissionResource {
|
||||
id: number
|
||||
tenantId: number
|
||||
id: number | string
|
||||
tenantId: number | string
|
||||
appCode: 'PLATFORM'
|
||||
permissionType: 'MENU' | 'BUTTON'
|
||||
parentId: number
|
||||
parentId: number | string
|
||||
permissionCode: string
|
||||
permissionName: string
|
||||
routePath: string | null
|
||||
@@ -64,7 +64,7 @@ export interface CreatePlatformPermissionRequest {
|
||||
type: 'MENU' | 'BUTTON'
|
||||
code: string
|
||||
name: string
|
||||
parentId: number
|
||||
parentId: number | string
|
||||
routePath: string | null
|
||||
httpMethod: null
|
||||
sortNo: number
|
||||
|
||||
@@ -0,0 +1,36 @@
|
||||
import { describe, expect, it } from 'vitest'
|
||||
import { mapPlatformPermission } from '@/utils/platformPermission'
|
||||
|
||||
describe('mapPlatformPermission', () => {
|
||||
it('treats the string root parent as a root node and preserves long ids', () => {
|
||||
expect(mapPlatformPermission({
|
||||
id: '2082813911786024961',
|
||||
tenantId: '0',
|
||||
appCode: 'PLATFORM',
|
||||
permissionType: 'MENU',
|
||||
parentId: '0',
|
||||
permissionCode: 'platform:audit',
|
||||
permissionName: '审计管理',
|
||||
routePath: '/audit',
|
||||
httpMethod: null,
|
||||
sortNo: 50,
|
||||
status: 'ACTIVE',
|
||||
})).toMatchObject({ id: '2082813911786024961', parentId: null, code: 'platform:audit' })
|
||||
})
|
||||
|
||||
it('preserves a long string parent id for child resources', () => {
|
||||
expect(mapPlatformPermission({
|
||||
id: '2082813911786024962',
|
||||
tenantId: '0',
|
||||
appCode: 'PLATFORM',
|
||||
permissionType: 'BUTTON',
|
||||
parentId: '2082813911786024961',
|
||||
permissionCode: 'platform:audit:list',
|
||||
permissionName: '操作日志',
|
||||
routePath: null,
|
||||
httpMethod: null,
|
||||
sortNo: 10,
|
||||
status: 'ACTIVE',
|
||||
})).toMatchObject({ id: '2082813911786024962', parentId: '2082813911786024961', type: '按钮' })
|
||||
})
|
||||
})
|
||||
@@ -0,0 +1,17 @@
|
||||
import type { PlatformPermissionResource } from '@/api/platformIam'
|
||||
import type { Permission } from '@/types/admin'
|
||||
|
||||
export function mapPlatformPermission(item: PlatformPermissionResource): Permission {
|
||||
const parentId = String(item.parentId)
|
||||
return {
|
||||
id: String(item.id),
|
||||
parentId: parentId === '0' ? null : parentId,
|
||||
name: item.permissionName,
|
||||
code: item.permissionCode,
|
||||
type: item.permissionType === 'BUTTON' ? '按钮' : '菜单',
|
||||
path: item.routePath ?? '',
|
||||
method: item.httpMethod ?? '-',
|
||||
status: item.status === 'ACTIVE' ? '启用' : '停用',
|
||||
sort: item.sortNo,
|
||||
}
|
||||
}
|
||||
@@ -120,12 +120,12 @@ function addressText(item: Counterparty) {
|
||||
<section class="surface-panel table-panel">
|
||||
<header class="panel-heading"><div><h2>往来单位档案</h2><p>平台维护完整主数据;企业客户端仅可只读选择已启用的发货单位和收货单位。</p></div></header>
|
||||
<el-table :data="pagedRows" row-key="id" empty-text="没有符合条件的往来单位">
|
||||
<el-table-column label="操作" width="220" fixed="left"><template #default="{ row }"><div class="table-actions"><el-button link type="primary" @click="openDetail(row as Counterparty)"><Eye :size="15" />详情</el-button><el-button v-if="access.can('counterparty:write')" link type="primary" @click="openEdit(row as Counterparty)"><Pencil :size="15" />编辑</el-button><el-button v-if="access.can('counterparty:write')" link :type="(row as Counterparty).status === '启用' ? 'danger' : 'success'" @click="toggleStatus(row as Counterparty)">{{ (row as Counterparty).status === '启用' ? '停用' : '启用' }}</el-button></div></template></el-table-column>
|
||||
<el-table-column label="单位" min-width="230"><template #default="{ row }"><div class="counterparty-cell"><span><Building2 :size="17" /></span><div><strong>{{ (row as Counterparty).name }}</strong><small>{{ (row as Counterparty).code }}</small></div></div></template></el-table-column>
|
||||
<el-table-column label="类型" min-width="220"><template #default="{ row }"><div class="type-tags"><el-tag v-for="type in (row as Counterparty).types" :key="type" size="small" effect="plain">{{ type }}</el-tag></div></template></el-table-column>
|
||||
<el-table-column label="主要联系人" min-width="170"><template #default="{ row }"><div class="primary-cell"><strong>{{ (row as Counterparty).contactName }}</strong><span>{{ (row as Counterparty).contactPhone }}</span></div></template></el-table-column>
|
||||
<el-table-column label="城市 / 地址" min-width="210"><template #default="{ row }"><div class="primary-cell"><strong>{{ (row as Counterparty).country }} · {{ (row as Counterparty).city }}</strong><span>{{ (row as Counterparty).address }}</span></div></template></el-table-column>
|
||||
<el-table-column label="状态" width="90"><template #default="{ row }"><StatusBadge :status="(row as Counterparty).status" /></template></el-table-column>
|
||||
<el-table-column label="操作" width="220" fixed="right"><template #default="{ row }"><div class="table-actions"><el-button link type="primary" @click="openDetail(row as Counterparty)"><Eye :size="15" />详情</el-button><el-button v-if="access.can('counterparty:write')" link type="primary" @click="openEdit(row as Counterparty)"><Pencil :size="15" />编辑</el-button><el-button v-if="access.can('counterparty:write')" link :type="(row as Counterparty).status === '启用' ? 'danger' : 'success'" @click="toggleStatus(row as Counterparty)">{{ (row as Counterparty).status === '启用' ? '停用' : '启用' }}</el-button></div></template></el-table-column>
|
||||
</el-table>
|
||||
<footer class="table-footer"><span>显示 {{ pagedRows.length }} 条,共 {{ filteredRows.length }} 条</span><el-pagination v-model:current-page="page" :page-size="pageSize" :total="filteredRows.length" layout="prev, pager, next" /></footer>
|
||||
</section>
|
||||
|
||||
@@ -135,6 +135,15 @@ function exportCustomers() {
|
||||
<div><h2>客户档案</h2><p>共 {{ filteredRows.length }} 家企业,客户资料与注册审核统一管理。</p></div>
|
||||
</header>
|
||||
<el-table :data="pagedRows" row-key="id" empty-text="没有符合条件的客户">
|
||||
<el-table-column label="操作" width="246" fixed="left">
|
||||
<template #default="{ row }">
|
||||
<div class="table-actions">
|
||||
<el-button link type="primary" @click="openDetail(row as Customer)"><Eye :size="15" />详情</el-button>
|
||||
<el-button v-if="!access.usesServerPermissions" link type="primary" @click="openEdit(row as Customer)"><Pencil :size="15" />编辑</el-button>
|
||||
<el-button v-if="!access.usesServerPermissions && row.status !== '待审核'" link :type="row.status === '停用' ? 'success' : 'danger'" @click="toggleStatus(row as Customer)">{{ row.status === '停用' ? '启用' : '停用' }}</el-button>
|
||||
</div>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column prop="id" label="客户编号" width="96" />
|
||||
<el-table-column label="企业信息" min-width="250">
|
||||
<template #default="{ row }"><div class="primary-cell"><strong>{{ row.name }}</strong><span>{{ row.creditCode }}</span></div></template>
|
||||
@@ -144,15 +153,6 @@ function exportCustomers() {
|
||||
<el-table-column label="套餐/账期" width="130"><template #default="{ row }"><div class="primary-cell"><strong>{{ row.packageName }}</strong><span>{{ row.period }} 天账期</span></div></template></el-table-column>
|
||||
<el-table-column prop="orders" label="订单数" width="86" align="right" />
|
||||
<el-table-column label="状态" width="96"><template #default="{ row }"><StatusBadge :status="row.status" /></template></el-table-column>
|
||||
<el-table-column label="操作" width="246" fixed="right">
|
||||
<template #default="{ row }">
|
||||
<div class="table-actions">
|
||||
<el-button link type="primary" @click="openDetail(row as Customer)"><Eye :size="15" />详情</el-button>
|
||||
<el-button v-if="!access.usesServerPermissions" link type="primary" @click="openEdit(row as Customer)"><Pencil :size="15" />编辑</el-button>
|
||||
<el-button v-if="!access.usesServerPermissions && row.status !== '待审核'" link :type="row.status === '停用' ? 'success' : 'danger'" @click="toggleStatus(row as Customer)">{{ row.status === '停用' ? '启用' : '停用' }}</el-button>
|
||||
</div>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
<footer class="table-footer"><span>显示 {{ pagedRows.length }} 条,共 {{ filteredRows.length }} 条</span><el-pagination v-model:current-page="page" :page-size="pageSize" :total="filteredRows.length" layout="prev, pager, next" /></footer>
|
||||
</section>
|
||||
|
||||
@@ -216,6 +216,15 @@ onBeforeUnmount(clearPreviewUrl)
|
||||
<div><h2>企业资料审核</h2><p>仅展示后端返回的待审核记录,提交审核时使用审核单 ID。</p></div>
|
||||
</header>
|
||||
<el-table v-loading="loading" :data="filteredReviews" row-key="id" empty-text="暂无待审核企业">
|
||||
<el-table-column label="操作" width="250" fixed="left">
|
||||
<template #default="{ row }">
|
||||
<div class="table-actions">
|
||||
<el-button link type="primary" @click="openDetail(row as EnterpriseReview)"><Eye :size="15" />详情</el-button>
|
||||
<el-button v-if="access.can('platform:customer:approve')" link type="success" @click="openDecision(row as EnterpriseReview, 'approve')"><ShieldCheck :size="15" />通过</el-button>
|
||||
<el-button v-if="access.can('platform:customer:reject')" link type="danger" @click="openDecision(row as EnterpriseReview, 'reject')"><ShieldX :size="15" />驳回</el-button>
|
||||
</div>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="企业" min-width="230">
|
||||
<template #default="{ row }">
|
||||
<div class="primary-cell"><strong>{{ displayText((row as EnterpriseReview).tenantName) }}</strong><span>{{ displayText((row as EnterpriseReview).tenantCode) }} · 租户 {{ (row as EnterpriseReview).tenantId }}</span></div>
|
||||
@@ -233,15 +242,6 @@ onBeforeUnmount(clearPreviewUrl)
|
||||
</el-table-column>
|
||||
<el-table-column label="提交时间" min-width="175"><template #default="{ row }">{{ formatDate((row as EnterpriseReview).submittedAt ?? (row as EnterpriseReview).createdAt) }}</template></el-table-column>
|
||||
<el-table-column label="状态" width="110"><template #default><span class="status-badge is-warning"><i />待审核</span></template></el-table-column>
|
||||
<el-table-column label="操作" width="250" fixed="right">
|
||||
<template #default="{ row }">
|
||||
<div class="table-actions">
|
||||
<el-button link type="primary" @click="openDetail(row as EnterpriseReview)"><Eye :size="15" />详情</el-button>
|
||||
<el-button v-if="access.can('platform:customer:approve')" link type="success" @click="openDecision(row as EnterpriseReview, 'approve')"><ShieldCheck :size="15" />通过</el-button>
|
||||
<el-button v-if="access.can('platform:customer:reject')" link type="danger" @click="openDecision(row as EnterpriseReview, 'reject')"><ShieldX :size="15" />驳回</el-button>
|
||||
</div>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
<footer class="table-footer"><span>共 {{ filteredReviews.length }} 条待审记录</span><span v-if="keyword">已按关键词筛选</span></footer>
|
||||
</section>
|
||||
|
||||
@@ -104,12 +104,12 @@ async function toggleStatus(company: ExpressCompany) {
|
||||
<section class="surface-panel table-panel">
|
||||
<div class="panel-heading"><div><h2>快递公司名录</h2><p>编码和名称必须唯一;停用后不允许新增引用,历史订单快照不受影响。</p></div></div>
|
||||
<el-table :data="pagedRows" row-key="id" empty-text="没有符合条件的快递公司">
|
||||
<el-table-column label="操作" width="220" fixed="left"><template #default="{ row }"><div class="table-actions"><el-button link type="primary" @click="openDetail(row as ExpressCompany)">详情</el-button><el-button v-if="access.can('express-company:write')" link type="primary" @click="openEdit(row as ExpressCompany)"><Pencil :size="15" />编辑</el-button><el-button v-if="access.can('express-company:write')" link :type="(row as ExpressCompany).status === '合作中' ? 'danger' : 'success'" @click="toggleStatus(row as ExpressCompany)">{{ (row as ExpressCompany).status === '合作中' ? '停用' : '启用' }}</el-button></div></template></el-table-column>
|
||||
<el-table-column label="公司名称" min-width="190"><template #default="{ row }"><div class="express-company-cell"><span><Truck :size="18" /></span><div><strong>{{ (row as ExpressCompany).name }}</strong><small>{{ (row as ExpressCompany).id }} · {{ (row as ExpressCompany).updatedAt }}</small></div></div></template></el-table-column>
|
||||
<el-table-column label="编码" min-width="110"><template #default="{ row }"><code class="code-value">{{ (row as ExpressCompany).code }}</code></template></el-table-column>
|
||||
<el-table-column label="官网" min-width="220"><template #default="{ row }"><a v-if="(row as ExpressCompany).website" class="company-link" :href="websiteUrl(row as ExpressCompany)" target="_blank" rel="noopener noreferrer">{{ (row as ExpressCompany).website }}<ExternalLink :size="14" /></a><span v-else>—</span></template></el-table-column>
|
||||
<el-table-column label="客服电话" min-width="150"><template #default="{ row }"><span class="phone-value"><Phone :size="14" />{{ (row as ExpressCompany).phone || '—' }}</span></template></el-table-column>
|
||||
<el-table-column label="状态" width="100"><template #default="{ row }"><StatusBadge :status="(row as ExpressCompany).status" /></template></el-table-column>
|
||||
<el-table-column label="操作" width="220" fixed="right"><template #default="{ row }"><div class="table-actions"><el-button link type="primary" @click="openDetail(row as ExpressCompany)">详情</el-button><el-button v-if="access.can('express-company:write')" link type="primary" @click="openEdit(row as ExpressCompany)"><Pencil :size="15" />编辑</el-button><el-button v-if="access.can('express-company:write')" link :type="(row as ExpressCompany).status === '合作中' ? 'danger' : 'success'" @click="toggleStatus(row as ExpressCompany)">{{ (row as ExpressCompany).status === '合作中' ? '停用' : '启用' }}</el-button></div></template></el-table-column>
|
||||
</el-table>
|
||||
<div class="table-footer"><span>显示 {{ pagedRows.length }} 条,共 {{ filteredRows.length }} 条</span><el-pagination v-model:current-page="page" :page-size="pageSize" :total="filteredRows.length" layout="prev, pager, next" /></div>
|
||||
</section>
|
||||
|
||||
@@ -188,6 +188,7 @@ function exportOrders() { ElMessage.success(`已生成 ${filteredRows.value.leng
|
||||
<section class="surface-panel table-panel">
|
||||
<header class="panel-heading"><div><h2>头程订单</h2><p>从审核、受理、订舱到运输完成,统一跟进订单状态与负责人。</p></div><span v-if="selectedRows.length" class="selection-note">已选择 {{ selectedRows.length }} 笔</span></header>
|
||||
<el-table :data="pagedRows" row-key="id" empty-text="没有符合条件的头程订单" @selection-change="selectedRows = $event">
|
||||
<el-table-column label="操作" width="290" fixed="left"><template #default="{ row }"><div class="table-actions"><el-button link type="primary" @click="openDetail(row as FirstLegOrder)"><Eye :size="15" />详情</el-button><el-button v-if="canEditOrder(row as FirstLegOrder)" link type="primary" @click="openEdit(row as FirstLegOrder)"><Pencil :size="15" />编辑</el-button><el-button v-if="access.can('first-leg:delivery')" link type="primary" @click="openDeliveryDialog(row as FirstLegOrder)"><PackageCheck :size="15" />快递</el-button><el-button v-if="access.can('first-leg:status')" link type="success" @click="openStatusDialog([row as FirstLegOrder])"><UserRoundCheck :size="15" />处理</el-button></div></template></el-table-column>
|
||||
<el-table-column type="selection" width="44" />
|
||||
<el-table-column label="订单信息" min-width="210"><template #default="{ row }"><div class="primary-cell"><strong class="order-no">{{ row.no }}</strong><span>{{ row.referenceNo || '无客户参考号' }} · {{ row.createdAt }}</span></div></template></el-table-column>
|
||||
<el-table-column label="客户" min-width="185" show-overflow-tooltip><template #default="{ row }"><div class="primary-cell"><strong>{{ row.customerName }}</strong><span>{{ row.businessType }} · {{ row.priority }}</span></div></template></el-table-column>
|
||||
@@ -198,7 +199,6 @@ function exportOrders() { ElMessage.success(`已生成 ${filteredRows.value.leng
|
||||
<el-table-column label="应收" width="118" align="right"><template #default="{ row }"><strong>{{ row.currency === 'CNY' ? '¥' : '$' }}{{ row.amount.toLocaleString() }}</strong></template></el-table-column>
|
||||
<el-table-column label="负责人" width="100"><template #default="{ row }"><span :class="{ 'muted-value': row.operator === '未分配' }">{{ row.operator }}</span></template></el-table-column>
|
||||
<el-table-column label="状态" width="96"><template #default="{ row }"><StatusBadge :status="row.status" /></template></el-table-column>
|
||||
<el-table-column label="操作" width="290" fixed="right"><template #default="{ row }"><div class="table-actions"><el-button link type="primary" @click="openDetail(row as FirstLegOrder)"><Eye :size="15" />详情</el-button><el-button v-if="canEditOrder(row as FirstLegOrder)" link type="primary" @click="openEdit(row as FirstLegOrder)"><Pencil :size="15" />编辑</el-button><el-button v-if="access.can('first-leg:delivery')" link type="primary" @click="openDeliveryDialog(row as FirstLegOrder)"><PackageCheck :size="15" />快递</el-button><el-button v-if="access.can('first-leg:status')" link type="success" @click="openStatusDialog([row as FirstLegOrder])"><UserRoundCheck :size="15" />处理</el-button></div></template></el-table-column>
|
||||
</el-table>
|
||||
<footer class="table-footer"><span>显示 {{ pagedRows.length }} 条,共 {{ filteredRows.length }} 条</span><el-pagination v-model:current-page="page" :page-size="pageSize" :total="filteredRows.length" layout="prev, pager, next" /></footer>
|
||||
</section>
|
||||
|
||||
@@ -100,13 +100,13 @@ async function toggleStatus(row: InternalUser) {
|
||||
<section class="surface-panel table-panel">
|
||||
<header class="panel-heading"><div><h2>内部用户</h2><p>维护平台员工账号,并通过角色控制菜单和操作权限。</p></div></header>
|
||||
<el-table :data="pagedRows" row-key="id" empty-text="没有符合条件的内部用户">
|
||||
<el-table-column label="操作" width="250" fixed="left"><template #default="{ row }"><div v-if="access.can('system:user:write')" class="table-actions"><el-button link type="primary" @click="openEdit(row as InternalUser)"><Pencil :size="15" />编辑</el-button><el-button link type="primary" @click="resetPassword(row as InternalUser)"><KeyRound :size="15" />重置密码</el-button><el-button link :type="row.status === '正常' ? 'danger' : 'success'" :disabled="row.account === 'admin'" @click="toggleStatus(row as InternalUser)">{{ row.status === '正常' ? '停用' : '启用' }}</el-button></div></template></el-table-column>
|
||||
<el-table-column label="用户" min-width="190"><template #default="{ row }"><div class="user-cell"><span>{{ row.name.slice(0,1) }}</span><div><strong>{{ row.name }}</strong><small>{{ row.account }}</small></div></div></template></el-table-column>
|
||||
<el-table-column prop="department" label="部门" width="110" />
|
||||
<el-table-column label="角色" min-width="190"><template #default="{ row }"><div class="tag-list"><el-tag v-for="roleId in row.roleIds" :key="roleId" effect="plain" size="small">{{ roleName(roleId) }}</el-tag></div></template></el-table-column>
|
||||
<el-table-column label="联系方式" min-width="190"><template #default="{ row }"><div class="primary-cell"><strong>{{ row.phone }}</strong><span>{{ row.email }}</span></div></template></el-table-column>
|
||||
<el-table-column prop="lastLogin" label="最后登录" width="150" />
|
||||
<el-table-column label="状态" width="88"><template #default="{ row }"><StatusBadge :status="row.status" /></template></el-table-column>
|
||||
<el-table-column label="操作" width="250" fixed="right"><template #default="{ row }"><div v-if="access.can('system:user:write')" class="table-actions"><el-button link type="primary" @click="openEdit(row as InternalUser)"><Pencil :size="15" />编辑</el-button><el-button link type="primary" @click="resetPassword(row as InternalUser)"><KeyRound :size="15" />重置密码</el-button><el-button link :type="row.status === '正常' ? 'danger' : 'success'" :disabled="row.account === 'admin'" @click="toggleStatus(row as InternalUser)">{{ row.status === '正常' ? '停用' : '启用' }}</el-button></div></template></el-table-column>
|
||||
</el-table>
|
||||
<footer class="table-footer"><span>显示 {{ pagedRows.length }} 条,共 {{ filteredRows.length }} 条</span><el-pagination v-model:current-page="page" :page-size="pageSize" :total="filteredRows.length" layout="prev, pager, next" /></footer>
|
||||
</section>
|
||||
|
||||
@@ -4,7 +4,7 @@ import { ElMessage, ElMessageBox } from 'element-plus'
|
||||
import { Braces, FolderTree, Pencil, Plus, Search, ShieldCheck } from '@lucide/vue'
|
||||
import MetricStrip from '@/components/MetricStrip.vue'
|
||||
import StatusBadge from '@/components/StatusBadge.vue'
|
||||
import { createPlatformPermission, listPlatformPermissions, type PlatformPermissionResource } from '@/api/platformIam'
|
||||
import { createPlatformPermission, listPlatformPermissions } from '@/api/platformIam'
|
||||
import { getApiErrorDetails, getApiErrorMessage, type ApiErrorDetails } from '@/api/http'
|
||||
import ApiErrorMeta from '@/components/ApiErrorMeta.vue'
|
||||
import { useUnsavedWorkRegistration } from '@/composables/useUnsavedWorkRegistration'
|
||||
@@ -12,6 +12,7 @@ import { useAccessPreviewStore } from '@/stores/accessPreview'
|
||||
import { useAdminDataStore } from '@/stores/adminData'
|
||||
import type { Permission, PermissionType } from '@/types/admin'
|
||||
import { buildPermissionTree, getDescendantIds } from '@/utils/permissionTree'
|
||||
import { mapPlatformPermission } from '@/utils/platformPermission'
|
||||
|
||||
const store = useAdminDataStore()
|
||||
const access = useAccessPreviewStore()
|
||||
@@ -55,20 +56,6 @@ const metrics = computed(() => [
|
||||
{ label: '停用资源', value: permissions.value.filter((item) => item.status === '停用').length, note: '当前不可分配' },
|
||||
])
|
||||
|
||||
function mapPlatformPermission(item: PlatformPermissionResource): Permission {
|
||||
return {
|
||||
id: String(item.id),
|
||||
parentId: item.parentId === 0 ? null : String(item.parentId),
|
||||
name: item.permissionName,
|
||||
code: item.permissionCode,
|
||||
type: item.permissionType === 'BUTTON' ? '按钮' : '菜单',
|
||||
path: item.routePath ?? '',
|
||||
method: item.httpMethod ?? '-',
|
||||
status: item.status === 'ACTIVE' ? '启用' : '停用',
|
||||
sort: item.sortNo,
|
||||
}
|
||||
}
|
||||
|
||||
async function loadPermissions() {
|
||||
if (!access.usesServerPermissions) return
|
||||
loading.value = true
|
||||
@@ -97,7 +84,7 @@ async function savePermission() {
|
||||
type: form.type === '按钮' ? 'BUTTON' : 'MENU',
|
||||
code: form.code.trim(),
|
||||
name: form.name.trim(),
|
||||
parentId: form.parentId ? Number(form.parentId) : 0,
|
||||
parentId: form.parentId || '0',
|
||||
routePath: form.type === '菜单' ? form.path.trim() : null,
|
||||
httpMethod: null,
|
||||
sortNo: form.sort,
|
||||
@@ -147,13 +134,13 @@ onMounted(loadPermissions)
|
||||
<section class="surface-panel table-panel">
|
||||
<header class="panel-heading"><div><h2>权限资源树</h2><p>目录组织菜单,按钮控制页面操作;接口权限将在服务端契约确定后补充。</p></div><div class="legend-list"><span><i class="is-menu" />目录 / 菜单</span><span><i class="is-action" />操作</span><span><i class="is-api" />接口预留</span></div></header>
|
||||
<el-table v-loading="loading" :data="treeRows" row-key="id" default-expand-all :tree-props="{ children: 'children' }" empty-text="没有符合条件的权限资源">
|
||||
<el-table-column label="操作" width="235" fixed="left"><template #default="{ row }"><div v-if="access.usesServerPermissions && canCreate" class="table-actions"><el-button v-if="row.type === '菜单'" link type="primary" @click="openCreate(row.id)"><Plus :size="15" />添加下级</el-button><span class="secondary-text">编辑接口待补齐</span></div><div v-else-if="access.can('system:permission:write')" class="table-actions"><el-button link type="primary" @click="openEdit(row as Permission)"><Pencil :size="15" />编辑</el-button><el-button v-if="row.type === '目录' || row.type === '菜单'" link type="primary" @click="openCreate(row.id)"><Plus :size="15" />添加下级</el-button><el-button link :type="row.status === '启用' ? 'danger' : 'success'" @click="toggleStatus(row as Permission)">{{ row.status === '启用' ? '停用' : '启用' }}</el-button></div></template></el-table-column>
|
||||
<el-table-column label="权限名称" min-width="260"><template #default="{ row }"><div class="permission-name"><span :class="`is-${typeClass(row.type)}`"><FolderTree v-if="row.type === '目录' || row.type === '菜单'" :size="16" /><ShieldCheck v-else-if="row.type === '按钮'" :size="16" /><Braces v-else :size="16" /></span><strong>{{ row.name }}</strong></div></template></el-table-column>
|
||||
<el-table-column label="权限编码" min-width="220"><template #default="{ row }"><code class="code-value">{{ row.code }}</code></template></el-table-column>
|
||||
<el-table-column prop="type" label="类型" width="80" />
|
||||
<el-table-column label="路由 / 接口" min-width="260"><template #default="{ row }"><div class="endpoint-cell"><span v-if="row.method !== '-'">{{ row.method }}</span><code>{{ row.path || '-' }}</code></div></template></el-table-column>
|
||||
<el-table-column prop="sort" label="排序" width="72" align="right" />
|
||||
<el-table-column label="状态" width="88"><template #default="{ row }"><StatusBadge :status="row.status" /></template></el-table-column>
|
||||
<el-table-column label="操作" width="235" fixed="right"><template #default="{ row }"><div v-if="access.usesServerPermissions && canCreate" class="table-actions"><el-button v-if="row.type === '菜单'" link type="primary" @click="openCreate(row.id)"><Plus :size="15" />添加下级</el-button><span class="secondary-text">编辑接口待补齐</span></div><div v-else-if="access.can('system:permission:write')" class="table-actions"><el-button link type="primary" @click="openEdit(row as Permission)"><Pencil :size="15" />编辑</el-button><el-button v-if="row.type === '目录' || row.type === '菜单'" link type="primary" @click="openCreate(row.id)"><Plus :size="15" />添加下级</el-button><el-button link :type="row.status === '启用' ? 'danger' : 'success'" @click="toggleStatus(row as Permission)">{{ row.status === '启用' ? '停用' : '启用' }}</el-button></div></template></el-table-column>
|
||||
</el-table>
|
||||
</section>
|
||||
|
||||
|
||||
@@ -186,13 +186,13 @@ onMounted(loadRoles)
|
||||
<section class="surface-panel table-panel">
|
||||
<header class="panel-heading"><div><h2>角色与授权</h2><p>角色负责聚合菜单、操作和数据范围,内部用户可分配多个角色。</p></div></header>
|
||||
<el-table v-loading="loading" :data="filteredRows" row-key="id" empty-text="没有符合条件的角色">
|
||||
<el-table-column label="操作" width="235" fixed="left"><template #default="{ row }"><span v-if="access.usesServerPermissions" class="secondary-text">接口待补齐</span><div v-else-if="access.can('system:role:grant')" class="table-actions"><el-button link type="primary" @click="openEdit(row as Role)"><Pencil :size="15" />配置</el-button><el-button link :type="row.status === '启用' ? 'danger' : 'success'" :disabled="row.builtIn" @click="toggleStatus(row as Role)">{{ row.status === '启用' ? '停用' : '启用' }}</el-button><el-button link type="danger" :disabled="row.builtIn || row.userCount > 0" @click="removeRole(row as Role)"><Trash2 :size="15" />删除</el-button></div></template></el-table-column>
|
||||
<el-table-column label="角色" min-width="210"><template #default="{ row }"><div class="role-cell"><span><ShieldCheck :size="18" /></span><div><strong>{{ row.name }}</strong><small>{{ row.code }}</small></div></div></template></el-table-column>
|
||||
<el-table-column prop="description" label="说明" min-width="240" show-overflow-tooltip />
|
||||
<el-table-column label="授权范围" min-width="170"><template #default="{ row }"><div class="primary-cell"><strong>{{ permissionSummary(row as Role) }}</strong><span>{{ access.usesServerPermissions ? '数据范围待接口提供' : row.dataScope }}</span></div></template></el-table-column>
|
||||
<el-table-column label="用户数" width="86" align="right"><template #default="{ row }">{{ access.usesServerPermissions ? '—' : row.userCount }}</template></el-table-column>
|
||||
<el-table-column label="类型" width="95"><template #default="{ row }"><el-tag :type="row.builtIn ? 'warning' : 'info'" effect="plain" size="small">{{ row.builtIn ? '系统内置' : '自定义' }}</el-tag></template></el-table-column>
|
||||
<el-table-column label="状态" width="88"><template #default="{ row }"><StatusBadge :status="row.status" /></template></el-table-column>
|
||||
<el-table-column label="操作" width="235" fixed="right"><template #default="{ row }"><span v-if="access.usesServerPermissions" class="secondary-text">接口待补齐</span><div v-else-if="access.can('system:role:grant')" class="table-actions"><el-button link type="primary" @click="openEdit(row as Role)"><Pencil :size="15" />配置</el-button><el-button link :type="row.status === '启用' ? 'danger' : 'success'" :disabled="row.builtIn" @click="toggleStatus(row as Role)">{{ row.status === '启用' ? '停用' : '启用' }}</el-button><el-button link type="danger" :disabled="row.builtIn || row.userCount > 0" @click="removeRole(row as Role)"><Trash2 :size="15" />删除</el-button></div></template></el-table-column>
|
||||
</el-table>
|
||||
</section>
|
||||
|
||||
|
||||
@@ -128,6 +128,9 @@ async function toggleStatus(warehouse: Warehouse) {
|
||||
<section class="surface-panel table-panel">
|
||||
<div class="panel-heading"><div><h2>平台收货仓</h2><p>仅启用仓库会进入客户头程下单选项</p></div></div>
|
||||
<el-table v-if="pagedRows.length" :data="pagedRows" row-key="id">
|
||||
<el-table-column label="操作" width="180" fixed="left">
|
||||
<template #default="{ row }"><div v-if="access.can('warehouse:write')" class="table-actions"><el-button link type="primary" @click="openEdit(row as Warehouse)"><Pencil :size="15" />编辑</el-button><el-button link :type="(row as Warehouse).status === 'ACTIVE' ? 'danger' : 'success'" @click="toggleStatus(row as Warehouse)"><Power :size="15" />{{ (row as Warehouse).status === 'ACTIVE' ? '停用' : '启用' }}</el-button></div><span v-else class="warehouse-subline">仅查看</span></template>
|
||||
</el-table-column>
|
||||
<el-table-column label="仓库" min-width="200">
|
||||
<template #default="{ row }"><div class="warehouse-cell"><span><WarehouseIcon :size="18" /></span><div><strong>{{ (row as Warehouse).name }}</strong><small>{{ (row as Warehouse).code }}</small></div></div></template>
|
||||
</el-table-column>
|
||||
@@ -136,9 +139,6 @@ async function toggleStatus(warehouse: Warehouse) {
|
||||
<el-table-column label="联系人" min-width="150"><template #default="{ row }"><strong>{{ (row as Warehouse).contactName || '-' }}</strong><span class="warehouse-subline">{{ (row as Warehouse).contactPhone || '-' }}</span></template></el-table-column>
|
||||
<el-table-column label="收货时间" prop="businessHours" min-width="190" />
|
||||
<el-table-column label="状态" width="100"><template #default="{ row }"><el-tag :type="(row as Warehouse).status === 'ACTIVE' ? 'success' : 'info'" effect="light">{{ (row as Warehouse).status === 'ACTIVE' ? '启用' : '停用' }}</el-tag></template></el-table-column>
|
||||
<el-table-column label="操作" width="180">
|
||||
<template #default="{ row }"><div v-if="access.can('warehouse:write')" class="table-actions"><el-button link type="primary" @click="openEdit(row as Warehouse)"><Pencil :size="15" />编辑</el-button><el-button link :type="(row as Warehouse).status === 'ACTIVE' ? 'danger' : 'success'" @click="toggleStatus(row as Warehouse)"><Power :size="15" />{{ (row as Warehouse).status === 'ACTIVE' ? '停用' : '启用' }}</el-button></div><span v-else class="warehouse-subline">仅查看</span></template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
<el-empty v-else description="没有符合条件的仓库" />
|
||||
<div class="table-footer"><span>共 {{ filteredRows.length }} 个收货仓</span><el-pagination v-model:current-page="page" :page-size="pageSize" :total="filteredRows.length" layout="prev, pager, next" /></div>
|
||||
|
||||
Reference in New Issue
Block a user