Commit 56bce0bb by zhangtw

入库

parent 4a8990bf
......@@ -71,3 +71,12 @@ export const getInboundById = (param) => {
data: param
})
}
// 归还详情
export const getPendingReturnById = (param) => {
return axios.request({
url: '/api/ac/jilinsscgsdp/keyDmInbound/getPendingReturnById',
method: 'post',
data: param
})
}
......@@ -4,12 +4,63 @@
<TabPane label="办公用品入库" name="inbound">
<div class="search-div">
<Row type="flex" :gutter="16">
<Col span="8">
<Input v-model="filters.inbound.inbound_no" placeholder="单号/批次号" style="width:60%" />
<Button type="primary" class="mr10" @click="handleSearch('inbound')">搜索</Button>
<Button @click="handleReset('inbound')">重置</Button>
<Col span="20">
<div class="search-form">
<Form :inline="true" :model="filters.return" class="form-inline">
<FormItem label="入库单号:" class="form-item">
<Input
v-model="filters.inbound.inbound_no"
placeholder="请输入入库单号:"
class="form-input"
/>
</FormItem>
<FormItem label="批次号:" class="form-item">
<Input
v-model="filters.inbound.batch_no"
placeholder="请输入批次号:"
class="form-input"
/>
</FormItem>
<FormItem label="入库日期" class="form-item">
<DatePicker
v-model="inboundDateRange"
type="daterange"
range-separator="至"
start-placeholder="开始日期"
end-placeholder="结束日期"
format="yyyy-MM-dd"
value-format="yyyy-MM-dd"
clearable
/>
</FormItem>
<FormItem label="入库类型:" class="form-item">
<Select
v-model="filters.inbound.inbound_type"
placeholder="请选择入库类型"
class="form-input"
>
<Option :value='1'>手工入库</Option>
<Option :value='2'>归还入库</Option>
</Select>
</FormItem>
<FormItem label="入库类型:" class="form-item">
<Select
v-model="filters.inbound.inbound_status"
placeholder="请选择入库类型"
class="form-input"
>
<Option :value='0'>待入库</Option>
<Option :value='1'>已入库</Option>
</Select>
</FormItem>
<FormItem class="form-item-actions">
<Button type="primary" @click="handleSearch('inbound')">搜索</Button>
<Button @click="handleReset('inbound')" style="margin-left: 8px;">重置</Button>
</FormItem>
</Form>
</div>
</Col>
<Col span="16" class="text-right">
<Col span="4" class="text-right">
<Button type="success" @click="openInboundModal">新增入库</Button>
</Col>
</Row>
......@@ -34,9 +85,28 @@
<div class="search-div">
<Row type="flex" :gutter="16">
<Col span="10">
<Input v-model="filters.return.key" placeholder="申请单号/申请人" style="width:60%" />
<Button type="primary" class="mr10" @click="handleSearch('return')">搜索</Button>
<Button @click="handleReset('return')">重置</Button>
<div class="search-form">
<Form :inline="true" :model="filters.return" class="form-inline">
<FormItem label="申请单号:" class="form-item">
<Input
v-model="filters.return.application_no"
placeholder="请输入申请单号"
class="form-input"
/>
</FormItem>
<FormItem label="申请人:" class="form-item">
<Input
v-model="filters.return.applicant_name"
placeholder="请输入申请人"
class="form-input"
/>
</FormItem>
<FormItem class="form-item-actions">
<Button type="primary" @click="handleSearch('return')">搜索</Button>
<Button @click="handleReset('return')" style="margin-left: 8px;">重置</Button>
</FormItem>
</Form>
</div>
</Col>
</Row>
</div>
......@@ -142,20 +212,42 @@ import {
getPendingReturnList,
processReturn,
getInventoryList,
getInboundById
getInboundById,
getPendingReturnById
} from '@/api/key-dm-inbound'
import MaterialSelector from '@/view/key-person/key_dm_conf/materialSelector.vue'
import { normalizeVisitTimeValue } from '@/view/key-person/key_dm_conf/dates.js'
export default {
name: 'key-dm-inbound-index',
components: { MaterialSelector },
data () {
return {
// 时间范围数组
inboundDateRange: null,
// 入库状态映射字典
inboundTypeMap: { '1': '手工', '2': '归还' },
inboundStatusMap: { '0': '待入库', '1': '已入库' },
opTypeMap: { '1': '入库', '2': '出库' },
issueStatusType: { '0': '待发放', '1': '已发放' },
activeTab: 'inbound',
filters: { inbound: { inbound_no: '' }, return: { key: '' }, inventory: { material_name: '' } },
filters: {
inbound: {
inbound_no: null,
batch_no: null,
startDate: null,
endDate: null,
inbound_type: null,
inbound_status: null
},
return: {
application_no: '',
applicant_name: ''
},
inventory: {
material_name: ''
}
},
tables: { inbound: [], return: [], inventory: [] },
pagers: { inbound: { pageNo: 1, pageSize: 10, totalRecord: 0 }, return: { pageNo: 1, pageSize: 10, totalRecord: 0 }, inventory: { pageNo: 1, pageSize: 10, totalRecord: 0 } },
loading: { inbound: false, return: false, inventory: false },
......@@ -168,7 +260,7 @@ export default {
key: 'inbound_date',
align: 'center',
render: (h, { row }) => {
return h('span', this.formatDate(row.inbound_date) || row.inbound_date || '-')
return h('span', this.formatDate(row.inbound_date) || row.inbound_date || '')
}
},
{
......@@ -194,7 +286,14 @@ export default {
{ title: '申请单号', key: 'application_no', align: 'center' },
{ title: '申请人', key: 'applicant_name', align: 'center' },
{ title: '部门', key: 'department_name', align: 'center' },
{ title: '发放状态', key: 'issue_status', align: 'center' },
{
title: '发放状态',
key: 'issue_status',
align: 'center',
render: (h, { row }) => {
return h('span', this.issueStatusType[row.issue_status] || row.issue_status || '-')
}
},
{ title: '操作', slot: 'action', width: 140, align: 'center' }
],
inventoryColumns: [
......@@ -202,8 +301,16 @@ export default {
{ title: '物料编码', key: 'material_code', align: 'center' },
{ title: '物料名称', key: 'material_name', align: 'center' },
{ title: '总量', key: 'total_quantity', align: 'center' },
{ title: '可用', key: 'available_quantity', align: 'center' },
{ title: '借出', key: 'borrowed_quantity', align: 'center' }
{
title: '可用',
key: 'available_quantity',
align: 'center',
render: (h, { row }) => {
return h('span', (row.total_quantity - row.borrowed_quantity - row.damaged_quantity) || 0)
}
},
{ title: '借出', key: 'borrowed_quantity', align: 'center' },
{ title: '损坏', key: 'damaged_quantity', align: 'center' }
],
// 模态窗口内表格列定义
inboundDetailColumns: [
......@@ -283,9 +390,32 @@ export default {
{ title: '单价', key: 'unit_price' }
],
detailLogsColumns: [
{ title: '操作类型', key: 'op_type' },
{
title: '物料名称',
key: 'material_name'
},
{
title: '操作类型',
key: 'op_type',
render: (h, { row }) => {
return h('span', this.opTypeMap[row.op_type] || row.op_type || '-')
}
},
{ title: '数量', key: 'quantity' },
{ title: '时间', key: 'create_time' }
{
title: '操作人',
key: 'userName',
render: (h, { row }) => {
return h('span', row.userName || row.create_by || '-')
}
},
{
title: '时间',
key: 'create_time',
render: (h, { row }) => {
return h('span', this.formatDateTime(row.create_time) || row.create_time || '-')
}
}
],
// 选择器控制与已选明细
showMaterialSelector: false,
......@@ -295,6 +425,17 @@ export default {
detailModal: { visible: false, loading: false, data: {}, details: [], logs: [] }
}
},
watch: {
inboundDateRange (newVal) {
if (newVal && Array.isArray(newVal)) {
this.filters.inbound.startDate = normalizeVisitTimeValue(newVal[0])
this.filters.inbound.endDate = normalizeVisitTimeValue(newVal[1])
} else {
this.filters.inbound.startDate = null
this.filters.inbound.endDate = null
}
}
},
created () { this.fetchList('inbound') },
methods: {
// 获取当天日期,格式为 yyyy-MM-dd
......@@ -323,8 +464,11 @@ export default {
} else this.$Notice.error({ title: '查询失败', desc: ret.data && ret.data.errmsg })
}).finally(() => { this.loading[tab] = false })
},
handleSearch (tab) { (this.pagers[tab] || {}).pageNo = 1; this.fetchList(tab) },
handleReset (tab) { this.filters[tab] = {}; (this.pagers[tab] || {}).pageNo = 1; this.fetchList(tab) },
handleSearch (tab) {
(this.pagers[tab] || {}).pageNo = 1
this.fetchList(tab)
},
handleReset (tab) { this.inboundDateRange = null; this.filters[tab] = {}; (this.pagers[tab] || {}).pageNo = 1; this.fetchList(tab) },
pageChange (tab, pageNo) { (this.pagers[tab] || {}).pageNo = pageNo; this.fetchList(tab) },
sizeChange (tab, size) { (this.pagers[tab] || {}).pageSize = size; (this.pagers[tab] || {}).pageNo = 1; this.fetchList(tab) },
......@@ -367,6 +511,26 @@ export default {
const d = new Date(Number(timestamp))
return `${d.getFullYear()}-${String(d.getMonth() + 1).padStart(2, '0')}-${String(d.getDate()).padStart(2, '0')}`
},
// 转换时间戳为yyyy-MM-dd hh-mm-ss
formatDateTime (timestamp) {
// 空值/非数字处理:返回空字符串
if (!timestamp || isNaN(Number(timestamp))) return ''
const d = new Date(Number(timestamp))
// 年
const year = d.getFullYear()
// 月(补0)
const month = String(d.getMonth() + 1).padStart(2, '0')
// 日(补0)
const day = String(d.getDate()).padStart(2, '0')
// 时(24小时制,补0)
const hour = String(d.getHours()).padStart(2, '0')
// 分(补0)
const minute = String(d.getMinutes()).padStart(2, '0')
// 秒(补0)
const second = String(d.getSeconds()).padStart(2, '0')
// 拼接为 yyyy-MM-dd HH:mm:ss
return `${year}-${month}-${day} ${hour}:${minute}:${second}`
},
deleteSelectedInboundDetails () {
if (!this.inboundSelectedDetails || this.inboundSelectedDetails.length === 0) {
this.$Message.warning('请先选择要删除的明细行')
......@@ -461,7 +625,7 @@ export default {
openReturnModal (row) {
this.returnModal.record = Object.assign({}, row)
this.returnModal.details = []
getInboundById({ id: row.id }).then(ret => {
getPendingReturnById({ id: row.id }).then(ret => {
if (ret.data && ret.data.errcode === 0) this.returnModal.details = ret.data.data.details || []
})
this.returnModal.visible = true
......@@ -496,4 +660,67 @@ export default {
.text-right { text-align: right; }
.page_style { margin-top: 12px; text-align: right; }
.mt8 { margin-top: 8px; }
/* 搜索区域外层盒:统一间距+背景 */
.search-container {
padding: 16px;
background: #fff;
border-radius: 4px;
margin-bottom: 16px;
}
/* 行容器:垂直居中+间距 */
.search-row {
margin: 0 !important;
}
/* 内联表单:消除默认间距 */
.form-inline {
display: flex;
align-items: center;
flex-wrap: wrap;
margin: 0;
}
/* 表单项:统一间距+对齐 */
.form-item {
margin: 0 8px 0 0 !important;
display: flex;
align-items: center;
}
/* 输入框/下拉框:统一宽度 */
.form-input {
width: 180px !important;
}
/* 按钮组:单独样式 */
.form-item-actions {
margin-left: 16px !important;
}
/* 右侧操作列:居右+内边距 */
.action-col {
text-align: right;
padding-right: 16px;
}
/* 响应式适配:小屏幕自动换行 */
@media (max-width: 768px) {
.form-inline {
flex-direction: column;
align-items: flex-start;
}
.form-item {
margin: 8px 0 !important;
width: 100%;
}
.form-input {
width: 100% !important;
}
.action-col {
text-align: left;
padding: 16px 0 0 0;
}
}
</style>
......@@ -27,10 +27,10 @@
placeholder="请选择审批状态"
class="form-input"
>
<Option :value= "0">待提交</Option>
<Option :value= "1">审核中</Option>
<Option :value= "9">审核通过</Option>
<Option :value= "-1">驳回</Option>
<Option :value='0'>待提交</Option>
<Option :value='1'>审核中</Option>
<Option :value='9'>审核通过</Option>
<Option :value='-1'>驳回</Option>
</Select>
</FormItem>
<FormItem class="form-item-actions">
......@@ -220,6 +220,7 @@ export default {
editingCellField: '',
// 审批状态映射字典
approvalStatusMap: { '0': '待提交', '1': '审核中', '9': '审核通过', '-1': '驳回' },
opTypeMap: { '1': '入库', '2': '出库' },
activeTab: 'apply',
filters: {
apply: { application_no: '', applicant_name: '', approval_status: null },
......@@ -234,8 +235,32 @@ export default {
{ title: '申请人', key: 'applicant_name', align: 'center' },
{ title: '部门', key: 'department_name', align: 'center' },
{ title: '审评用途', key: 'borrow_purpose', align: 'center' },
{ title: '起止时间', key: 'start_time', align: 'center' },
{ title: '时长', key: 'duration', align: 'center' },
{
title: '起止时间',
key: 'start_time',
align: 'center',
width: '300px',
render: (h, { row }) => {
return h('span', (this.formatDateTime(row.create_time) || row.create_time || '-') + '--' + (this.formatDateTime(row.approval_time) || row.approval_time || '-'))
}
},
{
title: '时长',
key: 'duration',
align: 'center',
render: (h, { row }) => {
const createTime = Number(row.create_time) || 0
const approvalTime = Number(row.approval_time) || 0
let duration = null
if (createTime !== 0 && approvalTime !== 0) {
const diffMs = Math.abs(approvalTime - createTime)
duration = this.formatDuration(diffMs)
} else {
duration = this.formatDuration('')
}
return h('span', duration)
}
},
{
title: '状态',
key: 'approval_status',
......@@ -273,7 +298,14 @@ export default {
return h('span', this.approvalStatusMap[row.approval_status + ''] || row.approval_status || '-')
}
},
{ title: '审批完成时间', key: 'approval_complete_time', align: 'center' },
{
title: '审批完成时间',
key: 'approval_time',
align: 'center',
render: (h, { row }) => {
return h('span', this.formatDateTime(row.approval_time) || row.approval_time || '-')
}
},
{ title: '操作', slot: 'action', width: 100, align: 'center' }
],
// 模态窗口内表格列定义
......@@ -369,9 +401,23 @@ export default {
{ title: '已归还', key: 'returned_quantity' }
],
detailLogsColumns: [
{ title: '操作类型', key: 'op_type' },
{ title: '物料名称', key: 'material_name' },
{
title: '操作类型',
key: 'op_type',
render: (h, { row }) => {
return h('span', this.opTypeMap[row.op_type] || row.op_type || '-')
}
},
{ title: '数量', key: 'quantity' },
{ title: '时间', key: 'create_time' },
{
title: '时间',
key: 'create_time',
width: '150px',
render: (h, { row }) => {
return h('span', this.formatDateTime(row.create_time) || row.create_time || '-')
}
},
{ title: '操作人', key: 'create_by' }
],
// 选择器控制与已选明细
......@@ -392,6 +438,28 @@ export default {
const day = String(today.getDate()).padStart(2, '0')
return `${year}-${month}-${day}`
},
// 格式化毫秒差值为易读的时长
formatDuration (diffMs) {
// 无有效差值时返回兜底值
if (diffMs <= 0) return '--'
// 时间单位换算(毫秒)
const oneSecond = 1000
const oneMinute = oneSecond * 60
const oneHour = oneMinute * 60
const oneDay = oneHour * 24
// 计算各单位的数值
const days = Math.floor(diffMs / oneDay)
const hours = Math.floor((diffMs % oneDay) / oneHour)
const minutes = Math.floor((diffMs % oneHour) / oneMinute)
const seconds = Math.floor((diffMs % oneMinute) / oneSecond)
// 拼接时长字符串(按需显示非零单位,避免冗余)
let duration = ''
if (days > 0) duration += `${days}天`
if (hours > 0 || duration) duration += `${hours}时`
if (minutes > 0 || duration) duration += `${minutes}分`
duration += `${seconds}秒`
return duration
},
// 处理单元格点击编辑
handleCellEdit (row, column, index, field) {
if (field === 'apply_quantity') {
......@@ -415,6 +483,26 @@ export default {
const d = new Date(Number(timestamp))
return `${d.getFullYear()}-${String(d.getMonth() + 1).padStart(2, '0')}-${String(d.getDate()).padStart(2, '0')}`
},
// 转换时间戳为yyyy-MM-dd hh-mm-ss
formatDateTime (timestamp) {
// 空值/非数字处理:返回空字符串
if (!timestamp || isNaN(Number(timestamp))) return ''
const d = new Date(Number(timestamp))
// 年
const year = d.getFullYear()
// 月(补0)
const month = String(d.getMonth() + 1).padStart(2, '0')
// 日(补0)
const day = String(d.getDate()).padStart(2, '0')
// 时(24小时制,补0)
const hour = String(d.getHours()).padStart(2, '0')
// 分(补0)
const minute = String(d.getMinutes()).padStart(2, '0')
// 秒(补0)
const second = String(d.getSeconds()).padStart(2, '0')
// 拼接为 yyyy-MM-dd HH:mm:ss
return `${year}-${month}-${day} ${hour}:${minute}:${second}`
},
handleTabChange (name) {
this.activeTab = name
if (name === 'pending') this.fetchList('pending')
......@@ -495,6 +583,7 @@ export default {
exist.apply_quantity = Number(exist.apply_quantity || 0) + 1
} else {
this.applyModal.details.push({
material_id: sel.id,
material_code: sel.material_code,
material_name: sel.material_name,
apply_quantity: 1,
......
......@@ -103,7 +103,7 @@ export default {
visible: false,
saving: false,
form: {}
},
}
// leader / office state 已移除
}
},
......
Markdown 格式
0%
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论