添加后端基础架构和API功能
- 配置.env文件支持环境变量管理 - 集成MyBatis Plus ORM框架并配置数据库连接 - 实现JWT认证和Spring Security安全配置 - 添加全局异常处理机制和统一响应结果封装 - 配置CORS跨域资源共享支持 - 实现用户认证API包括登录、注册、刷新token功能 - 开发完整的药品管理系统包含分类、药品、库存管理 - 实现出入库管理功能包括供应商、客户管理 - 添加角色权限管理和菜单配置 - 实现仪表盘统计和过期预警功能 - 配置分页查询和数据验证功能 ```
This commit is contained in:
@@ -1,23 +1,54 @@
|
||||
<script setup>
|
||||
import { ref, reactive, onMounted } from 'vue'
|
||||
import { useRouter } from 'vue-router'
|
||||
import { getStockOutList, auditStockOut } from '@/api/stockOut'
|
||||
import { getStockOutList, getStockOutById, auditStockOut } from '@/api/stockOut'
|
||||
import { Search, Refresh, Plus } from '@element-plus/icons-vue'
|
||||
import { ElMessage } from 'element-plus'
|
||||
import { ElMessage, ElMessageBox } from 'element-plus'
|
||||
|
||||
const router = useRouter()
|
||||
const query = reactive({ page: 1, size: 10 })
|
||||
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([])
|
||||
|
||||
function statusTag(s) { return { 0: 'warning', 1: 'success', 2: 'info' }[s] || 'info' }
|
||||
function statusText(s) { return { 0: '待审核', 1: '已出库', 2: '已取消' }[s] || '未知' }
|
||||
function typeText(s) { return { 1: '销售出库', 2: '领用出库', 3: '报损出库', 4: '退货出库' }[s] || '未知' }
|
||||
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 }
|
||||
}
|
||||
|
||||
async function loadData() { try { const r = await getStockOutList(query); tableData.value = r.data?.records || []; total.value = r.data?.total || 0 } catch { /* */ } }
|
||||
function handleCreate() { router.push('/stock-out/add') }
|
||||
function handleView(row) { ElMessage.info('出库单号: ' + (row.recordNo || row.record_no)) }
|
||||
async function handleAudit(row) { await auditStockOut(row.id, { status: 1 }); ElMessage.success('审核通过,库存已扣减'); loadData() }
|
||||
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>
|
||||
@@ -25,31 +56,75 @@ onMounted(loadData)
|
||||
<template>
|
||||
<div class="page-container">
|
||||
<div class="search-bar">
|
||||
<el-input v-model="query.recordNo" placeholder="出库单号" clearable style="width:180px" />
|
||||
<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="Object.keys(query).forEach(k=>query[k]=k==='page'?1:k==='size'?10:'');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>
|
||||
<el-button type="primary" v-permission="'stock-out:add'" :icon="Plus" @click="handleCreate">新建出库单</el-button>
|
||||
</div>
|
||||
<el-table :data="tableData" border stripe>
|
||||
<el-table-column prop="recordNo" label="出库单号" width="150" />
|
||||
<el-table-column prop="customerName" label="客户" min-width="160" />
|
||||
<el-table-column prop="outType" label="类型" width="100"><template #default="{row}">{{typeText(row.outType)}}</template></el-table-column>
|
||||
<el-table-column prop="totalAmount" label="总金额" width="110"><template #default="{row}">¥{{row.totalAmount}}</template></el-table-column>
|
||||
|
||||
<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="statusTag(row.status)" size="small">{{statusText(row.status)}}</el-tag></template>
|
||||
<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 label="操作" width="200" fixed="right">
|
||||
<template #default="{row}">
|
||||
<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>
|
||||
<el-button v-if="row.status===0" size="small" type="success" v-permission="'stock-out:audit'" @click="handleAudit(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>
|
||||
|
||||
<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>
|
||||
|
||||
Reference in New Issue
Block a user