Files
fad_oa/ruoyi-ui/src/views/oa/oaInWarehouse/index.vue
2026-05-30 15:32:57 +08:00

627 lines
22 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">
<el-form :model="queryParams" ref="queryForm" size="small" :inline="true" v-show="showSearch" label-width="68px">
<el-form-item label="操作时间" prop="signTime">
<el-date-picker v-model="searchTime" type="daterange" start-placeholder="开始日期" end-placeholder="结束日期"
:default-time="['00:00:00', '23:59:59']">
</el-date-picker>
</el-form-item>
<el-form-item>
<el-button type="primary" icon="el-icon-search" size="mini" @click="handleQuery">搜索</el-button>
<el-button icon="el-icon-refresh" size="mini" @click="resetQuery">重置</el-button>
</el-form-item>
</el-form>
<el-row :gutter="10" class="mb8">
<el-col :span="1.5">
<el-button type="danger" plain icon="el-icon-delete" size="mini" :disabled="multiple" @click="handleDelete"
v-hasPermi="['oa:oaOutWarehouse:remove']">删除
</el-button>
</el-col>
<el-col :span="1.5">
<el-button type="warning" plain icon="el-icon-download" size="mini" @click="handleExport"
v-hasPermi="['oa:oaOutWarehouse:export']">导出
</el-button>
</el-col>
<right-toolbar :showSearch.sync="showSearch" @queryTable="getList"></right-toolbar>
</el-row>
<el-table v-loading="loading" :data="outWareHouseList" @selection-change="handleSelectionChange" stripe size="small">
<el-table-column type="selection" width="40" align="center" />
<el-table-column label="入库时间" prop="signTime" width="100">
<template slot-scope="scope">{{ parseTime(scope.row.signTime, '{y}-{m}-{d}') }}</template>
</el-table-column>
<el-table-column label="入库人" prop="signUser" width="80" />
<el-table-column label="关联需求" min-width="160" show-overflow-tooltip>
<template slot-scope="scope">
<span v-if="scope.row.requirementName">{{ scope.row.requirementName }}</span>
<span v-else style="color:#c0c4cc;">无关联</span>
</template>
</el-table-column>
<el-table-column label="关联项目" prop="projectName" min-width="160" show-overflow-tooltip>
<template slot-scope="scope">
<span v-if="scope.row.projectName">{{ scope.row.projectName }}</span>
<span v-else style="color:#c0c4cc;"></span>
</template>
</el-table-column>
<el-table-column label="物料概览" prop="itemsSummary" min-width="220" show-overflow-tooltip>
<template slot-scope="scope">
<span v-if="scope.row.itemsSummary">{{ scope.row.itemsSummary }}</span>
<el-button v-else type="text" size="mini" @click="showDetail(scope.row)">查看</el-button>
</template>
</el-table-column>
<el-table-column label="物料种类" prop="itemCount" width="80" align="right" />
<el-table-column label="入库总数" prop="totalQty" width="80" align="right" />
<el-table-column label="备注" prop="remark" min-width="120" show-overflow-tooltip />
<el-table-column label="操作" align="center" width="100" class-name="small-padding fixed-width">
<template slot-scope="scope">
<el-button size="mini" type="text" icon="el-icon-search" @click="showDetail(scope.row)">详情</el-button>
</template>
</el-table-column>
</el-table>
<pagination v-show="total > 0" :total="total" :page.sync="queryParams.pageNum" :limit.sync="queryParams.pageSize"
@pagination="getList" />
<!-- 详情描述弹窗 -->
<el-dialog title="入库物料详情" :visible.sync="detail" width="950px" append-to-body>
<!-- 物料数据 -->
<el-descriptions class="margin-top" title="物料数据" :column="3" border>
<el-descriptions-item>
<template slot="label">
<i class="el-icon-s-order"></i>
入库单
</template>
{{ detailData.masterNum }}
</el-descriptions-item>
<el-descriptions-item>
<template slot="label">
<i class="el-icon-user"></i>
操作人
</template>
{{ detailData.signUser }}
</el-descriptions-item>
<el-descriptions-item>
<template slot="label">
<i class="el-icon-date"></i>
入库时间
</template>
{{ detailData.signTime }}
</el-descriptions-item>
<el-descriptions-item>
<template slot="label">
<i class="el-icon-tickets"></i>
备注
</template>
{{ detailData.remark == null ? '空' : detailData.remark }}
</el-descriptions-item>
<el-descriptions-item :span="3">
<template slot="label">
<i class="el-icon-paperclip"></i>
收货单
</template>
<template v-if="detailData.receiptFiles">
<a v-for="f in parseReceiptFiles(detailData.receiptFiles)" :key="f.ossId"
:href="f.url" target="_blank" download
style="color:#409eff; margin-right:10px; font-size:12px;">
<i class="el-icon-paperclip"></i>{{ f.name }}
</a>
</template>
<span v-else style="color:#c0c4cc;"></span>
</el-descriptions-item>
</el-descriptions>
<el-table v-loading="loading" :data="oaOutWarehouseList" @selection-change="handleSelectionChange">
<el-table-column type="selection" width="55" align="center" />
<el-table-column label="序号" align="center" type="index" />
<el-table-column label="物料名" align="center" prop="warehouseName" />
<el-table-column label="入库数量" align="center" prop="amount" />
<el-table-column label="型号" align="center" prop="model" />
<el-table-column label="规格" align="center" prop="specifications" />
<el-table-column label="入库价格" align="center" prop="signPrice" />
<el-table-column label="备注" align="center" prop="remark" />
</el-table>
<div slot="footer" class="dialog-footer">
<el-button @click="detail = false">关闭</el-button>
</div>
</el-dialog>
<!-- 添加或修改仓库入库对话框 -->
<el-dialog :title="title" :visible.sync="open" width="800px" append-to-body>
<el-form ref="form" :model="form" :rules="rules" label-width="80px">
<el-form-item label="采购需求" prop="requirementId" required>
<el-select v-model="form.requirementId" filterable remote
:remote-method="loadRequirementOptions" :loading="requirementLoading"
placeholder="按需求标题搜索(必选)" style="width: 100%"
@change="onRequirementChange">
<el-option v-for="r in requirementOptions" :key="r.requirementId"
:label="r.title" :value="r.requirementId">
<span style="float: left">{{ r.title }}</span>
<span style="float: right; color: #8492a6; font-size: 12px">
{{ r.projectName || '无项目' }}
</span>
</el-option>
</el-select>
</el-form-item>
<el-form-item label="绑定项目">
<el-radio-group v-model="projectFlag" :disabled="drawer">
<el-radio :label="true"></el-radio>
<el-radio :label="false"></el-radio>
</el-radio-group>
</el-form-item>
<el-form-item v-if="projectFlag && !drawer" prop="projectId" label="项目名">
<ProjectSelect v-model="form.projectId" placeholder="请选择项目" />
</el-form-item>
<el-form-item prop="masterNum" label="编号">
<el-input placeholder="请输入编号" v-model="form.masterNum">
</el-input>
</el-form-item>
<el-form-item label="收货单" prop="receiptDoc">
<file-upload v-model="form.receiptDoc" />
</el-form-item>
<el-form-item v-if="drawer" label="项目名">
<el-input :value="form.projectName" disabled></el-input>
</el-form-item>
<el-form-item v-else prop="remark" label="备注">
<el-input type="textarea" :autosize="{ minRows: 2, maxRows: 4 }" placeholder="请输入内容" v-model="form.remark">
</el-input>
</el-form-item>
<el-divider> 入库详情</el-divider>
<div>
<div style="margin-bottom: 10px">
<el-button @click="addRow" type="primary">添加</el-button>
<el-button @click="deleteRows" type="danger" :disabled="selectedRows.length === 0">删除</el-button>
</div>
<el-table :data="form.warehouseList" style="width: 100%" border stripe v-loading="loading"
highlight-current-row @selection-change="handleSelectionFormChange">
<el-table-column type="selection" width="55"></el-table-column>
<el-table-column label="序号" width="80" type="index"></el-table-column>
<el-table-column label="物料名" width="200">
<template slot-scope="scope">
<el-select v-model="scope.row.warehouseId" placeholder="请输入关键字" filterable remote reserve-keyword
@change="(e) => handleGetInventory(e, scope.$index)" :remote-method="remoteMethod" :loading="loading">
<el-option v-for="(item, index) in oaWarehouseList" :key="item.id" :label="item.name"
:value="item.id">
<span style="float: left">{{ item.name }}</span>
<span style="float: right; color: #8492a6; font-size: 13px">{{ item.model }}</span>
</el-option>
</el-select>
</template>
</el-table-column>
<el-table-column label="当前库存">
<template slot-scope="scope">
<div>{{ scope.row.inventory === "" ? '请选择物料' : scope.row.inventory }}</div>
</template>
</el-table-column>
<el-table-column label="规格">
<template slot-scope="scope">
<div>{{ scope.row.model === "" ? '请选择物料' : scope.row.model }}</div>
</template>
</el-table-column>
<el-table-column label="品牌">
<template slot-scope="scope">
<div>{{ scope.row.brand === "" ? '请选择物料' : scope.row.brand }}</div>
</template>
</el-table-column>
<el-table-column label="入库数量">
<template slot-scope="scope">
<el-input type="number" v-model="scope.row.amount" :min="0" :max="scope.row.inventory"></el-input>
</template>
</el-table-column>
</el-table>
</div>
</el-form>
<div slot="footer" class="dialog-footer">
<el-button :loading="buttonLoading" type="primary" @click="submitForm"> </el-button>
<el-button @click="cancel"> </el-button>
</div>
</el-dialog>
<el-drawer size="70%" :title="searchItem.projectName + '-入库单'" :visible.sync="drawer">
<el-button style="margin: 25px" type="primary" plain icon="el-icon-plus" size="mini" @click="handleAdd"
v-hasPermi="['oa:oaOutWarehouse:add']">新增
</el-button>
<el-table v-loading="loading" :data="oaOutWarehouseList" @selection-change="handleSelectionChange">
<el-table-column type="selection" width="55" align="center" />
<el-table-column label="序号" align="center" type="index" />
<el-table-column label="物料名" align="center" prop="warehouseName" />
<el-table-column label="入库数量" align="center" prop="amount" />
<el-table-column label="入库价格" align="center" prop="signPrice" />
<el-table-column label="操作" align="center" class-name="small-padding fixed-width">
<template slot-scope="scope">
<el-button size="mini" type="text" icon="el-icon-delete" @click="handleDelete(scope.row)"
v-hasPermi="['oa:oaOutWarehouse:remove']">删除
</el-button>
</template>
</el-table-column>
</el-table>
</el-drawer>
</div>
</template>
<script>
import { listByMultiQuery, listOaWarehouse } from "@/api/oa/warehouse/oaWarehouse";
import {
addOaWarehouseMaster,
delOaWarehouseMaster,
listOaWarehouseMaster,
updateOaWarehouseMaster
} from "@/api/oa/warehouse/warehouseMaster";
import { listRequirements } from "@/api/oa/requirement";
import FileUpload from "@/components/FileUpload";
import ProjectSelect from "@/components/fad-service/ProjectSelect";
export default {
name: "OaOutWarehouse",
components: {
ProjectSelect,
FileUpload
},
data () {
return {
// 细节数据
detailData: {},
searchTime: [],
// 抽屉
drawer: false,
// 选中项目名称
selectedProject: "",
// 查看详情弹窗
outDetail: {},
// 弹窗标志
detail: false,
// 绑定项目详情
projectDetail: {},
// 物料信息详情
warehouseDetail: {},
// 入库列表
outWareHouseList: [],
// 按钮loading
buttonLoading: false,
// 遮罩层
loading: true,
// 选中数组
ids: [],
// 非单个禁用
single: true,
selectedRows: [],
// 非多个禁用
multiple: true,
// 显示搜索条件
showSearch: true,
// 总条数
total: 0,
// 仓库入库表格数据
oaOutWarehouseList: [],
// 库存数据
oaWarehouseList: [],
// 弹出层标题
title: "",
// 选择对象
searchItem: {},
// 是否显示弹出层
open: false,
// 是否绑定项目
projectFlag: false,
// 采购需求下拉
requirementOptions: [],
requirementLoading: false,
// 库存查询参数
warehouseParams: {
pageSize: 999,
pageNum: 1
},
// 查询参数
queryParams: {
pageNum: 1,
pageSize: 30,
type: 1,
},
// 表单参数
form: {
projectId: '',
warehouseList: []
},
// 表单校验
rules: {
amount: [
{ required: true, message: "入库数量不能为空", trigger: "blur" }
],
masterNum: [
{ required: true, message: "编号不能为空", trigger: "blur" }
],
warehouseId: [
{ required: true, message: "入库对象id不能为空", trigger: "blur" }
],
requirementId: [
{ required: true, message: "入库必须关联采购需求", trigger: "change" }
],
}
};
},
created () {
this.getList();
// 路由带 requirementId 进来时自动打开新增入库表单并预填
const q = this.$route && this.$route.query;
if (q && q.requirementId) {
this.$nextTick(() => {
this.handleAdd();
this.form.requirementId = Number(q.requirementId) || q.requirementId;
// 顺手把预填项推到选项列表,让 select 能显示
if (q.requirementTitle) {
this.requirementOptions = [{
requirementId: this.form.requirementId,
title: q.requirementTitle
}];
}
});
}
},
methods: {
// 后端联查的收货单文件解析("ossId|name|url,,..."
parseReceiptFiles (raw) {
if (!raw) return []
return String(raw).split(',,').map(s => {
const [ossId, name, url] = s.split('|')
return { ossId, name: name || '收货单', url: url || '' }
}).filter(f => f.ossId)
},
// 远程搜索采购需求
loadRequirementOptions (keyword) {
this.requirementLoading = true
listRequirements({ pageNum: 1, pageSize: 20, title: keyword || undefined, status: 1 })
.then(res => { this.requirementOptions = res.rows || [] })
.finally(() => { this.requirementLoading = false })
},
onRequirementChange (id) {
const r = this.requirementOptions.find(x => x.requirementId === id)
if (r && r.projectId) {
this.projectFlag = true
this.form.projectId = r.projectId
}
},
// 添加新的一行
addRow () {
console.log(this.form)
this.form.warehouseList.push({
name: '',
warehouseId: '',
inventory: '',
amount: '',
});
},
// 删除勾选的行
deleteRows () {
this.form.warehouseList = this.form.warehouseList.filter(row => !this.selectedRows.includes(row));
this.selectedRows = []; // 清空选中的行
},
// 处理表格选择变化,更新选中的行
handleSelectionFormChange (val) {
this.selectedRows = val;
},
getDateStr (date) {
if (!date) {
return ''
}
return this.parseTime(date, '{y}-{m}-{d} {h}:{i}:{s}')
},
/** 查询仓库入库列表 */
getList () {
this.loading = true;
// 处理搜索时间
if (this.searchTime && this.searchTime.length === 2) {
this.queryParams.startTime = this.getDateStr(this.searchTime[0])
this.queryParams.endTime = this.getDateStr(this.searchTime[1])
} else {
delete this.queryParams.startTime
delete this.queryParams.endTime
}
listOaWarehouseMaster(this.queryParams).then(res => {
this.outWareHouseList = res.rows
this.total = res.total
this.loading = false
})
},
// 取消按钮
cancel () {
this.open = false;
this.reset();
},
// 表单重置
reset () {
this.form = {
projectId: undefined,
requirementId: undefined,
receiptDoc: undefined,
warehouseList: [],
};
this.resetForm("form");
},
/** 搜索按钮操作 */
handleQuery () {
this.queryParams.pageNum = 1;
this.getList();
},
/** 重置按钮操作 */
resetQuery () {
this.resetForm("queryForm");
this.handleQuery();
},
// 多选框选中数据
handleSelectionChange (selection) {
this.ids = selection.map(item => item.masterId)
this.single = selection.length !== 1
this.multiple = !selection.length
},
/** 新增按钮操作 */
handleAdd () {
this.reset();
this.open = true;
this.loadRequirementOptions();
if (this.drawer) {
// 如果抽屉是打开的说明是从项目处进入的新增从而加入projectId
this.projectFlag = true;
this.form.projectId = this.selectedProject.projectId;
this.form.masterId = this.searchItem.masterId;
this.form.projectName = this.searchItem.projectName;
this.form.masterNum = this.searchItem.masterNum;
}
this.title = "添加仓库入库";
},
/** 修改按钮操作 */
handleUpdate (row) {
this.loading = true;
this.reset();
const id = row.masterId || this.ids
},
/** 提交按钮 */
submitForm () {
this.$refs["form"].validate(valid => {
if (valid) {
this.buttonLoading = true;
if (this.form.masterId != null) {
updateOaWarehouseMaster(this.form).then(response => {
this.$modal.msgSuccess("修改成功");
this.open = false;
this.drawer = false;
this.getList();
}).finally(() => {
this.buttonLoading = false;
});
} else {
this.form.type = 1
addOaWarehouseMaster(this.form).then(response => {
this.$modal.msgSuccess("新增成功");
this.open = false;
// this.getList();
}).finally(() => {
this.buttonLoading = false;
});
}
}
});
},
/** 删除按钮操作 */
handleDelete (row) {
const ids = row.masterId || this.ids;
this.$modal.confirm('是否确认删除仓库入库编号为"' + ids + '"的数据项?').then(() => {
this.loading = true;
return delOaWarehouseMaster(ids);
}).then(() => {
this.getList();
this.$modal.msgSuccess("删除成功");
this.open = false;
this.drawer = false;
}).catch(() => {
}).finally(() => {
this.loading = false;
});
},
/** 导出按钮操作 */
handleExport () {
this.download('oa/oaOutWarehouse/export', {
...this.queryParams
}, `oaOutWarehouse_${new Date().getTime()}.xlsx`)
},
addDomain () {
this.form.outWareHouseList.push({
value: '',
warehouseId: '',
key: Date.now()
});
},
removeDomain (item) {
var index = this.form.outWareHouseList.indexOf(item)
if (index !== -1) {
this.form.outWareHouseList.splice(index, 1)
}
},
// 获取对应的库存 后续添加品牌型号
handleGetInventory (e, index) {
let obj = this.oaWarehouseList[this.oaWarehouseList.findIndex(item => item.id === e)]
this.form.warehouseList[index].inventory = obj.inventory
this.form.warehouseList[index].model = obj.model
this.form.warehouseList[index].brand = obj.brand
this.form.warehouseList[index].amount = 0
this.form.warehouseList[index].signPrice = obj.price
},
querySearch (queryString, cb) {
var oaWarehouseList = this.oaWarehouseList;
var results = queryString ? oaWarehouseList.filter(this.createFilter(queryString)) : oaWarehouseList;
// 调用 callback 返回建议列表的数据
cb(results);
},
createFilter (queryString) {
return (restaurant) => {
// console.log(restaurant)
// console.log(restaurant.name.toLowerCase().indexOf(queryString.toLowerCase()))
return (restaurant.value.toLowerCase().indexOf(queryString.toLowerCase()) === 0);
};
},
getOaOutWarehouseList () {
listOaWarehouse(this.warehouseParams).then(res => {
this.oaWarehouseList = res.rows
})
},
remoteMethod (query) {
this.warehouseParams.name = query
this.selectLoading = true;
listByMultiQuery(this.warehouseParams).then(res => {
this.oaWarehouseList = res.rows.filter(item => {
const queryLower = query.toLowerCase();
return item.name.toLowerCase().indexOf(queryLower) > -1 ||
item.model.toLowerCase().indexOf(queryLower) > -1 ||
item.brand.toLowerCase().indexOf(queryLower) > -1;
});
this.selectLoading = false;
})
},
// 查看入库详情
handleSearch (item) {
this.loading = true
this.searchItem = item;
this.oaOutWarehouseList = item.warehouseList;
this.drawer = true;
this.loading = false;
},
// 查看入库单独条目详情
showDetail (row) {
this.detailData = row;
this.detail = true;
this.oaOutWarehouseList = row.warehouseList;
}
}
};
</script>