fix: 彻底解耦出库/借库权限联动 + 路由去硬编码roles + 补API权限保护
根因: 借库选单页面14处硬编码outbound_selection:operation, 导致两模块权限联动 修复: - borrow/apply: 14处outbound_selection:operation→op_borrow_apply:operation - stock.py: 拆分_do_get_stock_list裸逻辑, 出库/借库各绑独立权限码 - transactions: 新增/borrow/stock-list端点(@permission(op_borrow_apply)) - transaction.ts: 新增getBorrowStockList前端API函数 - outbound.py: 出库审批4端点改用独立outbound_approval权限码 - transactions.py: 借库审批3端点补@permission(op_borrow_approval) - purchase.py: 采购管理7端点补@permission(inbound_buy) - audit.py: 审计日志补@permission(system_audit) - router: 清除全部6处硬编码roles, 交由动态权限树控制
This commit is contained in:
@ -174,6 +174,17 @@ export function approveBorrowRequest(id: number, data: { action: 'approve' | 're
|
||||
})
|
||||
}
|
||||
|
||||
/**
|
||||
* 借库选单专用库存列表(独立权限 op_borrow_apply)
|
||||
*/
|
||||
export function getBorrowStockList(params: { page?: number; pageSize?: number; keyword?: string }) {
|
||||
return request({
|
||||
url: '/v1/transactions/borrow/stock-list',
|
||||
method: 'get',
|
||||
params
|
||||
})
|
||||
}
|
||||
|
||||
/**
|
||||
* 执行借库扣减(审批通过后调用)
|
||||
* @param data approval_id + 扫码选中的物品 + 借用人信息 + 签名
|
||||
|
||||
@ -164,8 +164,7 @@ const routes: Array<RouteRecordRaw> = [
|
||||
component: () => import('@/views/outbound/approval/index.vue'),
|
||||
meta: {
|
||||
title: '出库审批',
|
||||
icon: 'Stamp',
|
||||
roles: ['SUPER_ADMIN', 'SUPERVISOR']
|
||||
icon: 'Stamp'
|
||||
}
|
||||
}
|
||||
]
|
||||
@ -239,8 +238,7 @@ const routes: Array<RouteRecordRaw> = [
|
||||
component: () => import('@/views/borrow/approval/index.vue'),
|
||||
meta: {
|
||||
title: '借库审批',
|
||||
icon: 'Stamp',
|
||||
roles: ['SUPER_ADMIN', 'SUPERVISOR']
|
||||
icon: 'Stamp'
|
||||
}
|
||||
}
|
||||
]
|
||||
@ -276,9 +274,7 @@ const routes: Array<RouteRecordRaw> = [
|
||||
redirect: '/system/user-create',
|
||||
meta: {
|
||||
title: '系统管理',
|
||||
icon: 'Setting',
|
||||
// [修复] 使用大写角色名,匹配后端常量
|
||||
roles: ['SUPER_ADMIN', 'SUPERVISOR']
|
||||
icon: 'Setting'
|
||||
},
|
||||
children: [
|
||||
{
|
||||
@ -287,8 +283,7 @@ const routes: Array<RouteRecordRaw> = [
|
||||
component: () => import('@/views/system/UserCreate.vue'),
|
||||
meta: {
|
||||
title: '账号开通',
|
||||
icon: 'User',
|
||||
roles: ['SUPER_ADMIN', 'SUPERVISOR']
|
||||
icon: 'User'
|
||||
}
|
||||
},
|
||||
// [新增] 权限分配页面,只有超级管理员可进
|
||||
@ -298,8 +293,7 @@ const routes: Array<RouteRecordRaw> = [
|
||||
component: () => import('@/views/system/PermissionConfig.vue'),
|
||||
meta: {
|
||||
title: '权限分配',
|
||||
icon: 'Lock',
|
||||
roles: ['SUPER_ADMIN', 'SUPERVISOR']
|
||||
icon: 'Lock'
|
||||
}
|
||||
},
|
||||
{
|
||||
@ -308,8 +302,7 @@ const routes: Array<RouteRecordRaw> = [
|
||||
component: () => import('@/views/system/AuditLog.vue'),
|
||||
meta: {
|
||||
title: '审计日志',
|
||||
icon: 'Document',
|
||||
roles: ['SUPER_ADMIN', 'SUPERVISOR']
|
||||
icon: 'Document'
|
||||
}
|
||||
}
|
||||
]
|
||||
|
||||
@ -19,25 +19,25 @@
|
||||
</template>
|
||||
<!-- 普通模式 -->
|
||||
<template v-else>
|
||||
<el-button v-if="userStore.hasPermission('outbound_selection:operation')" type="warning" plain :disabled="selectedItems.length === 0" @click="isBulkMode = true">
|
||||
<el-button v-if="userStore.hasPermission('op_borrow_apply:operation')" type="warning" plain :disabled="selectedItems.length === 0" @click="isBulkMode = true">
|
||||
批量操作
|
||||
</el-button>
|
||||
<el-button v-if="userStore.hasPermission('outbound_selection:operation')" type="danger" :disabled="selectedItems.length === 0" @click="clearAll">
|
||||
<el-button v-if="userStore.hasPermission('op_borrow_apply:operation')" type="danger" :disabled="selectedItems.length === 0" @click="clearAll">
|
||||
清空列表
|
||||
</el-button>
|
||||
<el-divider direction="vertical" />
|
||||
<el-button v-if="userStore.hasPermission('outbound_selection:operation')" type="primary" :icon="Plus" @click="openManualSelect">
|
||||
<el-button v-if="userStore.hasPermission('op_borrow_apply:operation')" type="primary" :icon="Plus" @click="openManualSelect">
|
||||
手动添加库存
|
||||
</el-button>
|
||||
<el-button v-if="userStore.hasPermission('outbound_selection:operation')" type="warning" :icon="List" @click="openBomSelect">
|
||||
<el-button v-if="userStore.hasPermission('op_borrow_apply:operation')" type="warning" :icon="List" @click="openBomSelect">
|
||||
按 BOM 套餐添加
|
||||
</el-button>
|
||||
</template>
|
||||
<el-divider direction="vertical" />
|
||||
<el-button v-if="userStore.hasPermission('outbound_selection:operation')" type="success" :icon="Printer" :disabled="selectedItems.length === 0" @click="handlePreview">
|
||||
<el-button v-if="userStore.hasPermission('op_borrow_apply:operation')" type="success" :icon="Printer" :disabled="selectedItems.length === 0" @click="handlePreview">
|
||||
生成预览 & 打印
|
||||
</el-button>
|
||||
<el-button v-if="userStore.hasPermission('outbound_selection:operation')" type="primary" :icon="Plus" :disabled="selectedItems.length === 0" @click="openRequestDialog">
|
||||
<el-button v-if="userStore.hasPermission('op_borrow_apply:operation')" type="primary" :icon="Plus" :disabled="selectedItems.length === 0" @click="openRequestDialog">
|
||||
提交借库申请
|
||||
</el-button>
|
||||
</div>
|
||||
@ -98,7 +98,7 @@
|
||||
size="small"
|
||||
style="width: 100%"
|
||||
controls-position="right"
|
||||
:disabled="!userStore.hasPermission('outbound_selection:operation')"
|
||||
:disabled="!userStore.hasPermission('op_borrow_apply:operation')"
|
||||
@change="(val) => handleMainQuantityChange(val, row)"
|
||||
/>
|
||||
</template>
|
||||
@ -106,7 +106,7 @@
|
||||
|
||||
<el-table-column label="操作" width="80" align="center" fixed="right">
|
||||
<template #default="{ $index }">
|
||||
<el-button v-if="!isBulkMode && userStore.hasPermission('outbound_selection:operation')" type="danger" link @click="removeRow($index)">移除</el-button>
|
||||
<el-button v-if="!isBulkMode && userStore.hasPermission('op_borrow_apply:operation')" type="danger" link @click="removeRow($index)">移除</el-button>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
@ -162,7 +162,7 @@
|
||||
size="small"
|
||||
style="width: 100%"
|
||||
placeholder="0"
|
||||
:disabled="!userStore.hasPermission('outbound_selection:operation')"
|
||||
:disabled="!userStore.hasPermission('op_borrow_apply:operation')"
|
||||
@click.stop
|
||||
@change="(val) => handleManualQuantityChange(val, row)"
|
||||
/>
|
||||
@ -185,7 +185,7 @@
|
||||
已勾选 {{ tempSelection.length }} 项
|
||||
</span>
|
||||
<el-button @click="manualDialogVisible = false">取消</el-button>
|
||||
<el-button v-if="userStore.hasPermission('outbound_selection:operation')" type="primary" @click="confirmManualAdd">确认添加</el-button>
|
||||
<el-button v-if="userStore.hasPermission('op_borrow_apply:operation')" type="primary" @click="confirmManualAdd">确认添加</el-button>
|
||||
</template>
|
||||
</el-dialog>
|
||||
|
||||
@ -202,7 +202,7 @@
|
||||
/>
|
||||
</el-form-item>
|
||||
<el-form-item label="借库套数">
|
||||
<el-input-number v-model="bomSets" :min="1" label="套" style="width: 200px;" :disabled="!userStore.hasPermission('outbound_selection:operation')" />
|
||||
<el-input-number v-model="bomSets" :min="1" label="套" style="width: 200px;" :disabled="!userStore.hasPermission('op_borrow_apply:operation')" />
|
||||
<el-tag v-if="selectedBomNo && maxBuildableSets >= 0" type="success" style="margin-left: 16px;">
|
||||
当前库存最多可成套借库: {{ maxBuildableSets }} 套
|
||||
</el-tag>
|
||||
@ -248,7 +248,7 @@
|
||||
<template #footer>
|
||||
<el-button @click="bomSelectVisible = false">取消</el-button>
|
||||
<el-button
|
||||
v-if="userStore.hasPermission('outbound_selection:operation')"
|
||||
v-if="userStore.hasPermission('op_borrow_apply:operation')"
|
||||
type="primary"
|
||||
@click="confirmBomAdd"
|
||||
>
|
||||
@ -288,11 +288,11 @@
|
||||
<span class="dialog-footer">
|
||||
<el-button @click="previewVisible = false">取消</el-button>
|
||||
|
||||
<el-button v-if="userStore.hasPermission('outbound_selection:operation')" type="warning" :icon="Download" :loading="exportLoading" @click="confirmExport">
|
||||
<el-button v-if="userStore.hasPermission('op_borrow_apply:operation')" type="warning" :icon="Download" :loading="exportLoading" @click="confirmExport">
|
||||
导出 Excel
|
||||
</el-button>
|
||||
|
||||
<el-button v-if="userStore.hasPermission('outbound_selection:operation')" type="primary" :icon="Printer" :loading="printLoading" @click="confirmPrint">
|
||||
<el-button v-if="userStore.hasPermission('op_borrow_apply:operation')" type="primary" :icon="Printer" :loading="printLoading" @click="confirmPrint">
|
||||
确认打印 (A4)
|
||||
</el-button>
|
||||
</span>
|
||||
@ -440,9 +440,9 @@
|
||||
import { ref, computed, watch } from 'vue'
|
||||
import { Printer, Search, Plus, Download, List } from '@element-plus/icons-vue'
|
||||
import { ElMessage, ElTable, ElMessageBox } from 'element-plus'
|
||||
import { getStockList, printSelectionList } from '@/api/inbound/stock'
|
||||
import { printSelectionList } from '@/api/inbound/stock'
|
||||
import { useUserStore } from '@/stores/user'
|
||||
import { submitBorrowRequest } from '@/api/transaction'
|
||||
import { submitBorrowRequest, getBorrowStockList } from '@/api/transaction'
|
||||
import { getApproversList } from '@/api/auth'
|
||||
import { getBomList, getBomDetail, getBomWithStock } from '@/api/bom'
|
||||
|
||||
@ -583,7 +583,7 @@ const getTypeTag = (type: string) => {
|
||||
const loadStockList = async () => {
|
||||
stockLoading.value = true
|
||||
try {
|
||||
const res: any = await getStockList({
|
||||
const res: any = await getBorrowStockList({
|
||||
page: stockPage.value,
|
||||
pageSize: stockPageSize.value,
|
||||
keyword: searchKeyword.value.trim(),
|
||||
@ -610,7 +610,7 @@ const loadAllStockForBom = async () => {
|
||||
let page = 1
|
||||
const pageSize = 200
|
||||
while (true) {
|
||||
const res: any = await getStockList({
|
||||
const res: any = await getBorrowStockList({
|
||||
page,
|
||||
pageSize,
|
||||
is_aggregated: true
|
||||
|
||||
Reference in New Issue
Block a user