Files
MedicineManagerSystem/frontend/src/views/stockOut/StockOutList.vue
KiriAky 107 258bae75b2 添加后端基础架构和API功能
- 配置.env文件支持环境变量管理
- 集成MyBatis Plus ORM框架并配置数据库连接
- 实现JWT认证和Spring Security安全配置
- 添加全局异常处理机制和统一响应结果封装
- 配置CORS跨域资源共享支持
- 实现用户认证API包括登录、注册、刷新token功能
- 开发完整的药品管理系统包含分类、药品、库存管理
- 实现出入库管理功能包括供应商、客户管理
- 添加角色权限管理和菜单配置
- 实现仪表盘统计和过期预警功能
- 配置分页查询和数据验证功能
```
2026-07-06 20:04:44 +08:00

131 lines
6.0 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>
import { ref, reactive, onMounted } from 'vue'
import { useRouter } from 'vue-router'
import { getStockOutList, getStockOutById, auditStockOut } from '@/api/stockOut'
import { Search, Refresh, Plus } from '@element-plus/icons-vue'
import { ElMessage, ElMessageBox } from 'element-plus'
const router = useRouter()
const query = reactive({ page: 1, size: 10, recordNo: '' })
const tableData = ref([])
const total = ref(0)
const loading = ref(false)
const detailVisible = ref(false)
const detailRecord = ref({})
const detailItems = ref([])
const statusMap = { 0: { type: 'warning', text: '待审核' }, 1: { type: 'success', text: '已出库' }, 2: { type: 'info', text: '已取消' } }
const typeMap = { 1: '销售出库', 2: '领用出库', 3: '报损出库', 4: '退货出库' }
async function loadData() {
loading.value = true
try {
const r = await getStockOutList(query)
tableData.value = r.data?.records || []
total.value = r.data?.total || 0
} finally { loading.value = false }
}
function handleCreate() { router.push('/stock-out/add') }
async function handleView(row) {
try {
const r = await getStockOutById(row.id)
detailRecord.value = r.data || row
detailItems.value = r.data?.details || []
detailVisible.value = true
} catch { ElMessage.error('获取详情失败') }
}
async function handleAudit(row) {
await ElMessageBox.confirm(`确认审核通过出库单 ${row.recordNo}?审核后库存将自动扣减。`, '审核确认', { type: 'success' })
await auditStockOut(row.id, { status: 1 })
ElMessage.success('审核通过,库存已扣减')
loadData()
}
async function handleReject(row) {
await ElMessageBox.confirm(`确认驳回出库单 ${row.recordNo}`, '驳回确认', { type: 'warning' })
await auditStockOut(row.id, { status: 2 })
ElMessage.success('已驳回')
loadData()
}
onMounted(loadData)
</script>
<template>
<div class="page-container">
<div class="search-bar">
<el-input v-model="query.recordNo" placeholder="出库单号" clearable style="width:200px" @keyup.enter="loadData" />
<el-button type="primary" :icon="Search" @click="loadData">搜索</el-button>
<el-button :icon="Refresh" @click="query.recordNo='';loadData()">重置</el-button>
</div>
<div class="tool-bar">
<el-button type="primary" v-permission="'stock-out:add'" :icon="Plus" @click="handleCreate">新建出库单</el-button>
</div>
<el-table :data="tableData" border stripe v-loading="loading">
<el-table-column prop="recordNo" label="出库单号" width="160" />
<el-table-column prop="customerName" label="客户" min-width="160">
<template #default="{ row }">{{ row.customerName || '-' }}</template>
</el-table-column>
<el-table-column prop="outType" label="类型" width="110">
<template #default="{ row }">{{ typeMap[row.outType] || '未知' }}</template>
</el-table-column>
<el-table-column prop="totalAmount" label="总金额" width="120">
<template #default="{ row }">¥{{ row.totalAmount }}</template>
</el-table-column>
<el-table-column prop="outDate" label="出库日期" width="120" />
<el-table-column prop="status" label="状态" width="100" align="center">
<template #default="{ row }">
<el-tag :type="statusMap[row.status]?.type || 'info'" size="small">
{{ statusMap[row.status]?.text || '未知' }}
</el-tag>
</template>
</el-table-column>
<el-table-column prop="remark" label="备注" min-width="150" show-overflow-tooltip />
<el-table-column label="操作" width="220" fixed="right">
<template #default="{ row }">
<div class="table-actions">
<el-button size="small" @click="handleView(row)">查看</el-button>
<template v-if="row.status === 0">
<el-button size="small" type="success" v-permission="'stock-out:audit'" @click="handleAudit(row)">通过</el-button>
<el-button size="small" type="danger" @click="handleReject(row)">驳回</el-button>
</template>
</div>
</template>
</el-table-column>
</el-table>
<div style="display:flex;justify-content:flex-end;margin-top:16px">
<el-pagination
v-model:current-page="query.page" v-model:page-size="query.size"
:total="total" :page-sizes="[10,20,50]"
layout="total,sizes,prev,pager,next"
@current-change="loadData" @size-change="query.page=1;loadData()"
/>
</div>
<el-dialog v-model="detailVisible" title="出库单详情" width="750px">
<el-descriptions :column="3" border>
<el-descriptions-item label="出库单号">{{ detailRecord.recordNo }}</el-descriptions-item>
<el-descriptions-item label="客户">{{ detailRecord.customerName || '-' }}</el-descriptions-item>
<el-descriptions-item label="出库日期">{{ detailRecord.outDate }}</el-descriptions-item>
<el-descriptions-item label="类型">{{ typeMap[detailRecord.outType] }}</el-descriptions-item>
<el-descriptions-item label="总金额">¥{{ detailRecord.totalAmount }}</el-descriptions-item>
<el-descriptions-item label="状态">
<el-tag :type="statusMap[detailRecord.status]?.type" size="small">{{ statusMap[detailRecord.status]?.text }}</el-tag>
</el-descriptions-item>
</el-descriptions>
<h4 style="margin:16px 0 8px">药品明细</h4>
<el-table :data="detailItems" border size="small" max-height="300">
<el-table-column prop="medicineName" label="药品" min-width="160" />
<el-table-column prop="batchNo" label="批号" width="120" />
<el-table-column prop="quantity" label="数量" width="80" />
<el-table-column prop="unitPrice" label="单价" width="90"><template #default="{row}">¥{{row.unitPrice}}</template></el-table-column>
<el-table-column prop="totalPrice" label="小计" width="100"><template #default="{row}">¥{{row.totalPrice}}</template></el-table-column>
</el-table>
</el-dialog>
</div>
</template>