Commit 51151952 by wangchunyang

样式按标准调整,去除多去的文件

parent 0bcd26da
<template>
<div class="key-dm-inbound-wrapper">
<Tabs v-model="activeTab" @on-click="handleTabChange">
<TabPane label="办公用品入库" name="inbound">
<div class="search-div">
<Row type="flex" :gutter="16">
<Col span="18">
<span>入库单号:</span>
<Input
v-model="filters.inbound.inbound_no"
placeholder="请输入入库单号:"
class="mr10"
style="width: 200px"
/>
<span>批次号:</span>
<Input
v-model="filters.inbound.batch_no"
placeholder="请输入批次号:"
class="mr10"
style="width: 200px"
/>
<span>开始时间:</span>
<DatePicker
v-model="filters.inbound.startDate"
type="date"
format="yyyy-MM-dd"
value-format="yyyy-MM-dd"
placeholder="请选择开始时间"
class="mr10"
style="width: 150px"
/>
<span>结束时间:</span>
<DatePicker
v-model="filters.inbound.endDate"
type="date"
format="yyyy-MM-dd"
value-format="yyyy-MM-dd"
placeholder="请选择结束时间"
class="mr10"
style="width: 150px"
/>
<br>
<div class="mt8">
<span>入库类型:</span>
<Select
v-model="filters.inbound.inbound_type"
placeholder="请选择入库类型"
class="mr10"
style="width: 200px"
clearable
>
<Option :value='1'>手工入库</Option>
<Option :value='2'>归还入库</Option>
</Select>
<span>入库状态:</span>
<Select
v-model="filters.inbound.inbound_status"
placeholder="请选择入库状态"
class="mr10"
style="width: 200px"
clearable
>
<Option :value='0'>待入库</Option>
<Option :value='1'>已入库</Option>
</Select>
</div>
</Col>
<Col span="6" class="text-right">
<Button type="primary" class="mr10" @click="handleSearch('inbound')">搜索</Button>
<Button type="primary" class="mr10" @click="handleReset('inbound')">重置</Button>
<Button type="primary" class="mr10" @click="openInboundModal">新增入库</Button>
<Button type="primary" class="mr10" v-if="showImport()" @click="importShow = true">导入</Button>
</Col>
</Row>
</div>
<Table :data="tables.inbound" :loading="loading.inbound" :columns="inboundColumns" border>
<template slot="action" slot-scope="{ row }">
<Poptip confirm title="确认执行入库?" transfer @on-ok="doInbound(row)" v-if="canEdit(row)">
<Button size="small" type="success" class="mr5">入库</Button>
</Poptip>
<Button size="small" @click="openDetail(row)" class="mr5">详细</Button>
<Button size="small" type="primary" @click="openEdit(row)" v-if="canEdit(row)" class="mr5">修改</Button>
<Poptip confirm title="确认删除?" transfer @on-ok="deleteInbound(row)" v-if="canEdit(row)">
<Button size="small" type="error">删除</Button>
</Poptip>
</template>
</Table>
<Page class="page_style" :total="pagers.inbound.totalRecord" :current="pagers.inbound.pageNo" :page-size="pagers.inbound.pageSize"
show-total show-sizer @on-change="pageChange('inbound', $event)" @on-page-size-change="sizeChange('inbound', $event)" />
</TabPane>
<TabPane label="办公用品归还" name="return">
<div class="search-div">
<Row type="flex" :gutter="16">
<Col span="18">
<span>部门:</span>
<Input
v-model="filters.return.department_name"
placeholder="请输入部门"
class="mr10"
style="width: 200px"
/>
<span>申领人:</span>
<Input
v-model="filters.return.applicant_name"
placeholder="请输入申请人"
class="mr10"
style="width: 200px"
/>
</Col>
<Col span="6" class="action-col">
<Button type="primary" class="mr10" @click="handleSearch('return')">搜索</Button>
<Button type="primary" class="mr10" @click="handleReset('return')" >重置</Button>
</Col>
</Row>
</div>
<Table :data="tables.return" :loading="loading.return" :columns="returnColumns" border>
<template slot="action" slot-scope="{ row }">
<Button size="small" type="primary" @click="openReturnModal(row)">归还</Button>
</template>
</Table>
<Page class="page_style" :total="pagers.return.totalRecord" :current="pagers.return.pageNo" :page-size="pagers.return.pageSize"
show-total show-sizer @on-change="pageChange('return', $event)" @on-page-size-change="sizeChange('return', $event)" />
</TabPane>
<TabPane label="库存查询" name="inventory">
<div class="search-div">
<Row type="flex" :gutter="16">
<Col span="18">
<span>用品编码:</span>
<Input
v-model="filters.inventory.material_code"
placeholder="请输入用品编码"
class="mr10"
style="width: 200px"
/>
<span>用品名称:</span>
<Input
v-model="filters.inventory.material_name"
placeholder="请输入用品名称"
class="mr10"
style="width: 200px"
/>
</Col>
<Col span="6" class="action-col">
<Button type="primary" class="mr10" @click="handleSearch('inventory')">搜索</Button>
<Button type="primary" class="mr10" @click="handleReset('inventory')">重置</Button>
</Col>
</Row>
</div>
<Table :data="tables.inventory" :loading="loading.inventory" :columns="inventoryColumns" border />
</TabPane>
</Tabs>
<!-- 入库弹窗 -->
<Modal v-model="inboundModal.visible" :title="inboundModal.isEdit ? '修改入库' : '新增入库'" width="800">
<Form :model="inboundModal.form" :rules="inboundRules" :label-width="120" ref="inboundForm">
<FormItem label="入库单号" prop="inbound_no">
<Input v-model="inboundModal.form.inbound_no" />
</FormItem>
<FormItem label="批次号" prop="batch_no">
<Input v-model="inboundModal.form.batch_no" />
</FormItem>
<FormItem label="入库日期" prop="inbound_date">
<DatePicker
v-model="inboundModal.form.inbound_date"
type="date"
format="yyyy-MM-dd"
value-format="yyyy-MM-dd"
placeholder="请选择入库日期"
/>
</FormItem>
<FormItem label="存放位置">
<Input v-model="inboundModal.form.storage_location" />
</FormItem>
<FormItem label="备注">
<Input type="textarea" v-model="inboundModal.form.remark" :rows="2" />
</FormItem>
<h4>明细(从用品库选择)
<div style="float: right;">
<Button size="small" class="mr5" type="primary" @click="showMaterialSelector = true">添加</Button>
<Button size="small" type="error" @click="deleteSelectedInboundDetails">删除</Button>
</div>
</h4>
<Table :data="inboundModal.details" :columns="inboundDetailColumns" size="small" border @on-selection-change="onInboundDetailSelectionChange" style="width: 100%" />
<MaterialSelector v-model="showMaterialSelector" :selected="[]" @on-ok="handleInboundMaterialSelectorOk" @cancel="showMaterialSelector = false" />
</Form>
<div slot="footer">
<Button @click="inboundModal.visible=false">取消</Button>
<Button type="primary" :loading="inboundModal.saving" @click="saveInbound">保存</Button>
</div>
</Modal>
<!-- 归还弹窗 -->
<Modal v-model="returnModal.visible" title="归还物品" width="700">
<Form :model="returnModal.record" :label-width="120">
<FormItem label="申请单号"><span>{{ returnModal.record.application_no }}</span></FormItem>
<FormItem label="申请人"><span>{{ returnModal.record.applicant_name }}</span></FormItem>
<FormItem label="归还明细">
<Table :data="returnModal.details" :columns="returnDetailColumns" size="small" border />
</FormItem>
</Form>
<div slot="footer">
<Button @click="returnModal.visible=false">取消</Button>
<Button type="primary" :loading="returnModal.saving" @click="confirmReturn">归还</Button>
</div>
</Modal>
<!-- 详情弹窗 -->
<Modal v-model="detailModal.visible" title="入库/归还详情" width="720">
<Spin fix v-if="detailModal.loading"></Spin>
<div v-else>
<Row :gutter="16"><Col span="12"><p><strong>单号:</strong>{{ detailModal.data.inbound_no || detailModal.data.application_no }}</p></Col></Row>
<Row class="mt8"><Col span="24"><h4>明细</h4></Col></Row>
<Table :data="detailModal.details" :columns="detailDetailColumns" size="small" border />
<!-- <Row class="mt8"><Col span="24"><h4>操作日志</h4></Col></Row>
<Table :data="detailModal.logs" :columns="detailLogsColumns" size="small" border /> -->
</div>
<div slot="footer"><Button type="primary" @click="detailModal.visible=false">关闭</Button></div>
</Modal>
<!-- 导入用品弹窗 -->
<Modal v-model="importShow" title="入库导入" width="360">
<Row type="flex" justify="center" align="middle">
<Col span="10">
<div style="text-align: center;">
<Upload
action="#"
:show-upload-list="false"
:before-upload="handleBeforeUpload"
:format="['xls','xlsx']"
accept=".xls,.xlsx"
:max-size="4096">
<Button icon="ios-cloud-upload-outline" type="primary" :loading="impBtnDisabled">导入</Button>
</Upload>
</div>
</Col>
<Col span="12">
<div style="text-align: center;">
<Button type="primary" @click="tplDownload" style="margin-right: 10px;">下载模板</Button>
</div>
</Col>
</Row>
<div slot="footer">
<Button size="large" type="text" @click="importShow = false">关闭</Button>
</div>
</Modal>
</div>
</template>
<script>
import {
getInboundList,
saveInbound,
deleteInbound,
doInbound,
getPendingReturnList,
processReturn,
getInventoryList,
getInboundById,
getPendingReturnById,
importInbound
} from '@/api/key-dm'
import MaterialSelector from '@/view/key-person/key_dm_conf/materialSelector.vue'
import { normalizeVisitTimeValue } from '@/view/key-person/key_dm_conf/dates.js'
import axios from 'axios'
export default {
name: 'key-dm-inbound-index',
components: { MaterialSelector },
data () {
return {
importShow: false,
impBtnDisabled: false,
// 时间范围数组
inboundDateRange: null,
// 入库状态映射字典
inboundTypeMap: { '1': '手工', '2': '归还' },
inboundStatusMap: { '0': '待入库', '1': '已入库' },
opTypeMap: { '1': '入库', '2': '出库' },
issueStatusType: { '0': '待发放', '1': '已发放' },
activeTab: 'inbound',
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 },
inboundColumns: [
{ type: 'index', title: '序号', width: 60, align: 'center' },
{ title: '入库单号', key: 'inbound_no', align: 'center' },
{ title: '批次号', key: 'batch_no', align: 'center' },
{
title: '入库日期',
key: 'inbound_date',
align: 'center',
render: (h, { row }) => {
return h('span', this.formatDate(row.inbound_date) || row.inbound_date || '')
}
},
{
title: '类型',
key: 'inbound_type',
align: 'center',
render: (h, { row }) => {
return h('span', this.inboundTypeMap[row.inbound_type] || row.inbound_type || '-')
}
},
{
title: '状态',
key: 'inbound_status',
align: 'center',
render: (h, { row }) => {
return h('span', this.inboundStatusMap[row.inbound_status] || row.inbound_status || '-')
}
},
{ title: '操作', slot: 'action', width: 260, align: 'center' }
],
returnColumns: [
{ type: 'index', title: '序号', width: 60, align: 'center' },
{ title: '部门', key: 'department_name', align: 'center' },
// { title: '申请单号', key: 'application_no', align: 'center' },
{ title: '申领人', key: 'applicant_name', align: 'center' },
{ title: '申领用途', key: 'borrow_purpose', align: 'center' },
{
title: '提交审批时间',
key: 'submit_time',
align: 'center',
render: (h, { row }) => {
return h('span', this.formatDateTime(row.submit_time) || '-')
}
},
{
title: '审批通过时间',
key: 'approval_time',
align: 'center',
render: (h, { row }) => {
return h('span', this.formatDateTime(row.approval_time) || '-')
}
},
{
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: [
{ type: 'index', title: '序号', width: 60, align: 'center' },
{ title: '用品编码', key: 'material_code', align: 'center' },
{ title: '用品名称', key: 'material_name', align: 'center' },
{ title: '总量', key: 'total_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)
}
}
],
// 模态窗口内表格列定义
inboundDetailColumns: [
{ type: 'selection', width: 60 },
{ title: '用品编码', key: 'material_code', minWidth: 120 },
{ title: '用品名称', key: 'material_name', minWidth: 150 },
{ title: '入库数量',
key: 'inbound_quantity',
minWidth: 120,
render: (h, params) => {
return h('InputNumber', {
props: {
value: params.row.inbound_quantity || 0,
min: 0,
precision: 0
},
style: { width: '100px' },
on: {
'on-change': (val) => {
// 使用Vue.set确保响应式更新
this.$set(this.inboundModal.details[params.index], 'inbound_quantity', Number(val) || 0)
// 计算并更新总金额
const quantity = Number(val) || 0
const unitPrice = this.inboundModal.details[params.index].unit_price || 0
this.$set(this.inboundModal.details[params.index], 'total_amount', (quantity * unitPrice).toFixed(2))
}
}
})
}
},
{ title: '单价',
key: 'unit_price',
minWidth: 120,
render: (h, params) => {
return h('InputNumber', {
props: {
value: params.row.unit_price || 0,
min: 0,
precision: 2
},
style: { width: '100px' },
on: {
'on-change': (val) => {
// 使用Vue.set确保响应式更新
this.$set(this.inboundModal.details[params.index], 'unit_price', Number(val) || 0)
// 计算并更新总金额
const quantity = this.inboundModal.details[params.index].inbound_quantity || 0
const unitPrice = Number(val) || 0
this.$set(this.inboundModal.details[params.index], 'total_amount', (quantity * unitPrice).toFixed(2))
}
}
})
}
},
{
title: '总金额',
key: 'total_amount',
minWidth: 120,
render: (h, params) => {
const quantity = Number(params.row.inbound_quantity) || 0
const unitPrice = Number(params.row.unit_price) || 0
const total = (quantity * unitPrice).toFixed(2)
this.$set(params.row, 'total_amount', total)
return h('span', total)
}
}
],
returnDetailColumns: [
{ title: '用品名称', key: 'material_name' },
{ title: '申请数量', key: 'apply_quantity' },
{ title: '归还数量', key: 'returned_quantity' }
],
detailDetailColumns: [
{ title: '用品编码', key: 'material_code' },
{ title: '用品名称', key: 'material_name' },
{ title: '数量', key: 'inbound_quantity' },
{ title: '单价', key: 'unit_price' }
],
detailLogsColumns: [
{
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: '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,
inboundSelectedDetails: [],
inboundModal: { visible: false, isEdit: false, saving: false, form: {}, details: [] },
returnModal: { visible: false, record: {}, details: [], saving: false },
detailModal: { visible: false, loading: false, data: {}, details: [], logs: [] },
// 表单验证规则
inboundRules: {
inbound_no: [
{ required: true, message: '请填写入库单号', trigger: 'blur' }
],
batch_no: [
{ required: true, message: '请选择批次号', trigger: 'blur' }
],
inbound_date: [
{ required: true, message: '请选择入库日期' }
]
}
}
},
watch: {},
created () { this.fetchList('inbound') },
methods: {
showImport () {
// // 简单权限控制:可根据需要替换
// const info = this.$store.state.user.otherUserInfo || {}
// const areaId = info.area_id || ''
// if (areaId && areaId.startsWith('2201')) return true
// return false
return true
},
async tplDownload () {
// 下载入库导入模板
try {
const response = await axios.post(
'/api/ac/jilinsscgsdp/keyDmInbound/templateDownload',
{},
{
responseType: 'blob'
}
)
const url = window.URL.createObjectURL(new Blob([response.data]))
// 创建隐藏的a标签并设置属性
const link = document.createElement('a')
link.href = url
link.download = '入库导入模板.xlsx' // 自定义下载文件名和扩展名
link.style.display = 'none'
document.body.appendChild(link)
// 触发点击下载
link.click()
// 清理
document.body.removeChild(link)
window.URL.revokeObjectURL(url)
} catch (error) {
console.error('下载失败:', error)
// 可以在这里添加错误提示
}
},
handleBeforeUpload (file) {
const fileExt = file.name.split('.').pop().toLocaleLowerCase()
if (fileExt === 'xlsx' || fileExt === 'xls') {
this.readFile(file)
} else {
this.$Notice.warning({
title: '文件类型错误',
desc: '文件:' + file.name + '不是EXCEL文件,请选择后缀为.xlsx或者.xls的EXCEL文件。'
})
}
return false
},
async readFile (file) {
this.impBtnDisabled = true
const formdata = new FormData()
formdata.append('file', file)
formdata.append('fileName', file.name)
const ret = await importInbound(formdata)
if (ret && ret.data) {
this.importShow = false
this.impBtnDisabled = false
const mobj = ret.data.data || {}
let msg = '添加' + (mobj.insert || 0) + '条, 更新' + (mobj.update || 0) + '条'
if (mobj.error) {
msg += ', 缺少关键信息未能导入' + mobj.error + '条'
}
if (mobj.errInfo && mobj.errInfo !== '') {
msg += ', 以下记录导入失败:' + mobj.errInfo
}
if (ret.data.errmsg && ret.data.errmsg !== 'success') {
msg += ret.data.errmsg
}
if ((mobj.insert || 0) + (mobj.update || 0) > 0) {
this.fetchList('inbound')
}
this.$Notice.success({
title: '导入完成!',
desc: msg
})
} else {
this.impBtnDisabled = false
this.$Notice.warning({
title: '未导入数据!',
desc: ret && ret.data && ret.data.errmsg
})
}
},
// 获取当天日期,格式为 yyyy-MM-dd
getTodayDate () {
const today = new Date()
const year = today.getFullYear()
const month = String(today.getMonth() + 1).padStart(2, '0')
const day = String(today.getDate()).padStart(2, '0')
return `${year}-${month}-${day}`
},
handleTabChange (name) {
this.activeTab = name
if (name === 'return') this.fetchList('return')
if (name === 'inventory') this.fetchList('inventory')
},
fetchList (tab) {
const apiMap = { inbound: getInboundList, return: getPendingReturnList, inventory: getInventoryList }
const api = apiMap[tab]; if (!api) return
this.loading[tab] = true
// 清理空值,防止参数传递问题
const cleanParams = (obj) => {
obj.startDate = normalizeVisitTimeValue(obj.startDate)
obj.endDate = normalizeVisitTimeValue(obj.endDate)
const cleaned = {}
for (let key in obj) {
const value = obj[key]
if (value !== null && value !== undefined && value !== '') {
cleaned[key] = value
}
}
return cleaned
}
const payload = Object.assign({}, this.pagers[tab] || {}, { params: cleanParams(this.filters[tab]) || {} })
api(payload).then(ret => {
if (ret.data && ret.data.errcode === 0) {
const data = ret.data.data || {}
this.tables[tab] = data.results || []
if (data.totalRecord !== undefined) (this.pagers[tab] || {}).totalRecord = data.totalRecord
} 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.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) },
openInboundModal () {
this.inboundModal.isEdit = false
this.inboundModal.form = { inbound_no: '', batch_no: '', inbound_date: this.getTodayDate(), inbound_type: 1, storage_location: '', remark: '' }
this.inboundModal.details = []
this.inboundModal.visible = true
},
onInboundDetailSelectionChange (list) {
this.inboundSelectedDetails = list || []
},
handleInboundMaterialSelectorOk (selectedRows) {
console.log('选择的用品信息' + selectedRows)
if (!Array.isArray(selectedRows) || selectedRows.length === 0) {
this.$Message.warning('未选择用品')
return
}
selectedRows.forEach(sel => {
const code = sel.material_code
const exist = this.inboundModal.details.find(d => d.material_code === code)
if (exist) {
exist.inbound_quantity = Number(exist.inbound_quantity || 0) + 1
} else {
this.inboundModal.details.push({
material_id: sel.id,
material_code: sel.material_code,
material_name: sel.material_name,
inbound_quantity: 0,
unit_price: 0,
total_amount: 0
})
}
})
this.showMaterialSelector = false
},
// 转换时间戳为yyyy-MM-dd
formatDate (timestamp) {
if (!timestamp || isNaN(Number(timestamp))) return ''
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('请先选择要删除的明细行')
return
}
const toRemoveCodes = this.inboundSelectedDetails.map(r => r.material_code)
this.inboundModal.details = this.inboundModal.details.filter(d => !toRemoveCodes.includes(d.material_code))
this.inboundSelectedDetails = []
},
openEdit (row) {
this.inboundModal.isEdit = true
getInboundById({ id: row.id }).then(ret => {
if (ret.data && ret.data.errcode === 0) {
this.inboundModal.form = ret.data.data || {}
if (this.inboundModal.form.inbound_date) {
this.inboundModal.form.inbound_date = this.formatDate(this.inboundModal.form.inbound_date) || ''
} else {
this.inboundModal.form.inbound_date = this.getTodayDate()
}
this.inboundModal.details = ret.data.data.details || []
}
})
this.inboundModal.visible = true
},
saveInbound () {
// 1. 验证明细数据
this.inboundModal.saving = true
// 1. 验证主表必填项
const { inbound_no, batch_no, inbound_date } = this.inboundModal.form
if (!inbound_no || !batch_no || !inbound_date) {
this.$Message.warning('入库单号、批次号、入库日期为必填项')
this.inboundModal.saving = false
return
}
if (this.inboundModal.details === null || this.inboundModal.details.length < 1) {
this.$Message.warning('请至少入库一条用品')
return
}
// 2. 验证明细数据
const invalidDetails = this.inboundModal.details.filter(detail => {
return !detail.inbound_quantity || detail.inbound_quantity <= 0
})
if (invalidDetails.length > 0) {
this.$Message.warning('请填写有效的入库数量(必须大于0)')
this.inboundModal.saving = false
return
}
// 2. 转换数据类型
const details = this.inboundModal.details.map(detail => {
return {
material_id: detail.material_id,
material_code: detail.material_code,
material_name: detail.material_name,
inbound_quantity: Number(detail.inbound_quantity) || 0,
unit_price: Number(detail.unit_price) || 0,
total_amount: Number(detail.total_amount) || 0
}
})
// 3. 发送请求
const payload = {
...this.inboundModal.form,
details: details
}
console.log('发送的数据:', payload) // 添加日志,查看发送的数据
saveInbound(payload).then(ret => {
if (ret.data && ret.data.errcode === 0) {
this.$Message.success('保存成功')
this.inboundModal.visible = false
this.fetchList('inbound')
} else {
this.$Notice.error({
title: '保存失败',
desc: ret.data & ret.data.errmsg || '未知错误'
})
}
}).catch(error => {
console.error('保存出错:', error)
this.$Notice.error({ title: '保存出错', desc: error.message })
}).finally(() => {
this.inboundModal.saving = false
})
},
canEdit (row) {
const userId = this.$store.state.user.userId
return row.inbound_status === 0 && row.create_by === userId
},
deleteInbound (row) {
deleteInbound({ id: row.id }).then(ret => {
if (ret.data && ret.data.errcode === 0) {
this.$Message.success('删除成功'); this.fetchList('inbound')
} else {
this.$Notice.error({
title: '删除失败', desc: ret.data && ret.data.errmsg
})
}
})
},
doInbound (row) {
doInbound({ id: row.id }).then(ret => {
if (ret.data && ret.data.errcode === 0) {
this.$Message.success('入库成功')
this.fetchList('inbound')
this.fetchList('inventory')
} else {
this.$Notice.error({ title: '入库失败', desc: ret.data && ret.data.errmsg })
}
})
},
openReturnModal (row) {
this.returnModal.record = Object.assign({}, row)
this.returnModal.details = []
getPendingReturnById({ id: row.id }).then(ret => {
if (ret.data && ret.data.errcode === 0) this.returnModal.details = ret.data.data.details || []
})
this.returnModal.visible = true
},
confirmReturn () {
this.returnModal.saving = true
processReturn({ id: this.returnModal.record.id }).then(ret => {
if (ret.data && ret.data.errcode === 0) { this.$Message.success('归还已入库并更新库存'); this.returnModal.visible = false; this.fetchList('return'); this.fetchList('inventory') } else this.$Notice.error({ title: '归还失败', desc: ret.data && ret.data.errmsg })
}).finally(() => { this.returnModal.saving = false })
},
openDetail (row) {
this.detailModal.visible = true
this.detailModal.loading = true
getInboundById({ id: row.id }).then(ret => {
if (ret.data && ret.data.errcode === 0) {
console.log(ret.data)
this.detailModal.data = ret.data.data || {}
this.detailModal.details = ret.data.data.details || []
this.detailModal.logs = ret.data.data.logs || []
} else this.$Notice.error({ title: '查询失败', desc: ret.data && ret.data.errmsg })
}).finally(() => { this.detailModal.loading = false })
}
}
}
</script>
<style scoped>
.key-dm-inbound-wrapper { padding: 10px; }
.search-div { border: 1px solid #dce1e7; padding: 12px; margin-bottom: 12px; background-color: #f8fbff; }
.mr10 { margin-right: 10px; }
.text-right { text-align: right; }
.page_style { margin-top: 12px; text-align: right; }
.mt8 { margin-top: 8px; }
.mr5 {
margin-right: 5px;
}
/* 搜索区域外层盒:统一间距+背景 */
.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>
......@@ -345,27 +345,32 @@ export default {
{ title: '请假类型', key: 'leave_type_name', align: 'center' },
{ title: '起止时间', key: 'start_time', align: 'center', render: (h, { row }) => h('span', `${row.start_time || '-'} ~ ${row.end_time || '-'}`) },
{ title: '审批完成时间', key: 'approval_complete_time', align: 'center' },
{ title: '结果', key: 'op_result', align: 'center', render: (h, { row }) => {
let statusText = '';
let statusClass = '';
{
title: '结果',
key: 'op_result',
align: 'center',
render: (h, { row }) => {
let statusText = ''
let statusClass = ''
switch (row.op_result) {
case 0:
statusText = '未通过';
statusClass = 'text-orange';
break;
statusText = '未通过'
statusClass = 'text-orange'
break
case 1:
statusText = '通过';
statusClass = 'text-green';
break;
statusText = '通过'
statusClass = 'text-green'
break
case -1:
statusText = '驳回';
statusClass = 'text-red';
break;
statusText = '驳回'
statusClass = 'text-red'
break
default:
statusText = '-';
statusText = '-'
}
return h('span', { class: statusClass }, statusText);
} },
return h('span', { class: statusClass }, statusText)
}
},
{ title: '操作', slot: 'action', align: 'center', width: 100 }
],
queryColumns: [
......@@ -457,7 +462,6 @@ export default {
// 加载待审批计数,用于页面顶部/选项卡徽章显示
this.loadPendingCount()
this.getUserDmPermission()
},
watch: {
// 当弹窗关闭时清理选择的审批人,确保下次打开时下拉框能正确刷新显示
......@@ -1079,22 +1083,22 @@ export default {
openHistoryDetail (row) { this.openDetail(row) },
renderApproveResult (h, { row }) { return row.approver_result === 1 ? '通过' : (row.approver_result === -1 ? '驳回' : '未处理') },
formatDatetime (val) {
if (!val) return '-';
if (!val) return '-'
try {
// 处理ISO格式时间字符串,如 "2023-12-31T10:30:00.000Z"
if (typeof val === 'string' && val.includes('T')) {
// 移除时区信息和毫秒,转换为本地时间格式
const date = new Date(val);
const date = new Date(val)
if (!isNaN(date.getTime())) {
const pad = (n) => (n < 10 ? '0' + n : String(n));
const pad = (n) => (n < 10 ? '0' + n : String(n))
return date.getFullYear() + '-' + pad(date.getMonth() + 1) + '-' + pad(date.getDate()) + ' ' +
pad(date.getHours()) + ':' + pad(date.getMinutes()) + ':' + pad(date.getSeconds());
pad(date.getHours()) + ':' + pad(date.getMinutes()) + ':' + pad(date.getSeconds())
}
}
// 如果不是ISO格式或解析失败,返回原值的T替换版本
return String(val).replace('T', ' ');
return String(val).replace('T', ' ')
} catch (e) {
return String(val).replace('T', ' ');
return String(val).replace('T', ' ')
}
},
loadStats () {
......@@ -1119,7 +1123,6 @@ export default {
this.loadStats()
},
deleteApply (row) {
deleteLeaveById({ id: row.id, leave_id: row.leave_id }).then(ret => {
if (ret.data && ret.data.errcode === 0) {
this.$Message.success('删除成功')
......
Markdown 格式
0%
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论