Files
KCGL/inventory-web/src/views/outbound/index.vue
dxc 5065410662 feat: add RBAC control for outbound list module
Co-authored-by: aider (openai/DeepSeek-V3.2-Thinking) <aider@aider.chat>
2026-02-27 13:57:59 +08:00

235 lines
8.1 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.

<template>
<div class="app-container">
<div class="filter-container">
<el-input
v-model="listQuery.keyword"
placeholder="单号/姓名/SKU"
style="width: 200px;"
class="filter-item"
clearable
@keyup.enter="fetchData"
/>
<el-date-picker
v-model="listQuery.dateRange"
type="daterange"
range-separator=""
start-placeholder="开始日期"
end-placeholder="结束日期"
class="filter-item"
style="margin-left: 10px;"
value-format="YYYY-MM-DD"
/>
<el-button type="primary" class="filter-item" style="margin-left: 10px;" @click="fetchData">查询</el-button>
<el-button v-if="userStore.hasPermission('outbound_create:operation')" type="success" class="filter-item" @click="$router.push('/outbound/create')">新建出库</el-button>
</div>
<el-table
:data="list"
v-loading="loading"
border
style="width: 100%; margin-top: 20px;"
:header-cell-style="{ background: '#f5f7fa', color: '#606266' }"
>
<el-table-column type="expand">
<template #default="props">
<div style="padding: 10px 40px; background: #fafafa;">
<h4 style="margin: 0 0 10px 0; color: #409EFF;">商品明细 (按单价降序)</h4>
<el-table :data="props.row.items" border size="small">
<el-table-column v-if="hasColumnPermission('sku')" prop="sku" label="SKU" width="150" />
<el-table-column v-if="hasColumnPermission('name')" prop="name" label="名称" min-width="150" show-overflow-tooltip />
<el-table-column v-if="hasColumnPermission('material_type')" prop="material_type" label="类型" width="120" show-overflow-tooltip />
<el-table-column v-if="hasColumnPermission('category')" prop="category" label="类别" width="120" show-overflow-tooltip />
<el-table-column v-if="hasColumnPermission('spec_model')" prop="spec_model" label="规格型号" min-width="150" show-overflow-tooltip />
<el-table-column v-if="hasColumnPermission('quantity')" prop="quantity" label="数量" width="100" />
<el-table-column v-if="hasColumnPermission('unit_price')" prop="unit_price" label="单价" width="120">
<template #default="{row}">¥{{ row.unit_price }}</template>
</el-table-column>
<el-table-column v-if="hasColumnPermission('subtotal')" prop="subtotal" label="小计">
<template #default="{row}">
<span style="color: #F56C6C; font-weight: bold;">¥{{ row.subtotal.toFixed(2) }}</span>
</template>
</el-table-column>
</el-table>
</div>
</template>
</el-table-column>
<el-table-column v-if="hasColumnPermission('outbound_no')" prop="outbound_no" label="出库单号" min-width="200" show-overflow-tooltip />
<el-table-column v-if="hasColumnPermission('outbound_time')" prop="outbound_time" label="出库时间" width="170" align="center">
<template #default="{ row }">
<span>{{ row.outbound_time ? row.outbound_time.substring(0, 16) : '' }}</span>
</template>
</el-table-column>
<el-table-column v-if="hasColumnPermission('outbound_type')" prop="outbound_type" label="类型" width="100" align="center">
<template #default="{ row }">
<el-tag :type="getTagType(row.outbound_type)">{{ formatType(row.outbound_type) }}</el-tag>
</template>
</el-table-column>
<el-table-column v-if="hasColumnPermission('total_amount')" prop="total_amount" label="总金额" width="120" align="right">
<template #default="{ row }">
<span style="color: #F56C6C; font-weight: bold; font-size: 15px;">¥{{ row.total_amount }}</span>
</template>
</el-table-column>
<el-table-column v-if="hasColumnPermission('consumer_name')" prop="consumer_name" label="领用/客户" min-width="120" show-overflow-tooltip />
<el-table-column v-if="hasColumnPermission('operator_name')" prop="operator_name" label="操作员" min-width="100" show-overflow-tooltip />
<el-table-column v-if="hasColumnPermission('remark')" prop="remark" label="备注" min-width="150" show-overflow-tooltip />
<el-table-column v-if="hasColumnPermission('signature_path')" label="签名" width="120" align="center">
<template #default="{ row }">
<div v-if="row.signature_path" class="signature-cell">
<el-image
style="width: 80px; height: 40px; border-radius: 4px; border: 1px solid #dcdfe6;"
:src="row.signature_path"
:preview-src-list="[row.signature_path]"
preview-teleported
fit="contain"
hide-on-click-modal
>
<template #error>
<div class="image-slot">
<el-icon><Picture /></el-icon>
</div>
</template>
</el-image>
</div>
<span v-else style="color: #909399; font-size: 12px;">未签名</span>
</template>
</el-table-column>
</el-table>
<div style="margin-top: 20px; text-align: right;">
<el-pagination
background
layout="prev, pager, next"
:total="total"
:page-size="listQuery.limit"
@current-change="handlePageChange"
/>
</div>
</div>
</template>
<script setup lang="ts">
import { ref, onMounted, reactive } from 'vue'
import { getOutboundList } from '@/api/outbound'
import { Picture } from '@element-plus/icons-vue'
import { useUserStore } from '@/stores/user'
const userStore = useUserStore()
// 列与权限Code的映射关系数据库中的code
const permissionMap: Record<string, string> = {
outbound_no: 'outbound_list:outbound_no',
outbound_time: 'outbound_list:outbound_time',
outbound_type: 'outbound_list:outbound_type',
total_amount: 'outbound_list:total_amount',
consumer_name: 'outbound_list:consumer_name',
operator_name: 'outbound_list:operator_name',
remark: 'outbound_list:remark',
signature_path: 'outbound_list:signature_path',
// 明细列
sku: 'outbound_list:sku',
name: 'outbound_list:name',
material_type: 'outbound_list:material_type',
category: 'outbound_list:category',
spec_model: 'outbound_list:spec_model',
quantity: 'outbound_list:quantity',
unit_price: 'outbound_list:unit_price',
subtotal: 'outbound_list:subtotal',
}
// 检查列权限
const hasColumnPermission = (prop: string) => {
if (userStore.role === 'SUPER_ADMIN' || userStore.username === 'IRIS') {
return true
}
const code = permissionMap[prop]
return code ? userStore.hasPermission(code) : false
}
const list = ref([])
const total = ref(0)
const loading = ref(false)
const listQuery = reactive({
page: 1,
limit: 10,
keyword: '',
dateRange: []
})
const fetchData = async () => {
loading.value = true
try {
const params = {
...listQuery,
start_date: listQuery.dateRange && listQuery.dateRange[0] ? listQuery.dateRange[0] : null,
end_date: listQuery.dateRange && listQuery.dateRange[1] ? listQuery.dateRange[1] : null
}
const res = await getOutboundList(params)
list.value = res.data.items || []
total.value = res.data.total || 0
} catch (e) {
console.error(e)
} finally {
loading.value = false
}
}
const handlePageChange = (val: number) => {
listQuery.page = val
fetchData()
}
const formatType = (type: string) => {
const map: any = {
'SALES': '销售出库',
'USE': '内部领用',
'TRANSFER': '调拨',
'SCRAP': '报废'
}
return map[type] || type
}
const getTagType = (type: string) => {
const map: any = {
'SALES': 'success',
'USE': 'warning',
'TRANSFER': 'info',
'SCRAP': 'danger'
}
return map[type] || ''
}
onMounted(() => {
fetchData()
})
</script>
<style scoped>
.signature-cell {
display: flex;
justify-content: center;
align-items: center;
padding: 2px 0;
}
.image-slot {
display: flex;
justify-content: center;
align-items: center;
width: 100%;
height: 100%;
background: #f5f7fa;
color: #909399;
}
</style>