整合前端
This commit is contained in:
568
ruoyi-ui/src/views/oa/oaWarehouse/addTask.vue
Normal file
568
ruoyi-ui/src/views/oa/oaWarehouse/addTask.vue
Normal file
@@ -0,0 +1,568 @@
|
||||
<template>
|
||||
<el-card style="margin: 10px" v-loading="loading">
|
||||
<el-form
|
||||
:model="queryParams"
|
||||
ref="queryForm"
|
||||
size="small"
|
||||
:inline="true"
|
||||
v-show="showSearch"
|
||||
label-width="68px"
|
||||
>
|
||||
<el-form-item label="任意搜索" prop="name">
|
||||
<el-input
|
||||
v-model="queryParams.name"
|
||||
placeholder="请输入物料名/型号/品牌"
|
||||
clearable
|
||||
@keyup.enter.native="handleQuery"
|
||||
/>
|
||||
</el-form-item>
|
||||
<el-form-item label="型号" prop="model">
|
||||
<el-input
|
||||
v-model="queryParams.model"
|
||||
placeholder="请输入型号"
|
||||
clearable
|
||||
@keyup.enter.native="handleQuery"
|
||||
/>
|
||||
</el-form-item>
|
||||
|
||||
<el-form-item label="品牌" prop="brand">
|
||||
<el-input
|
||||
v-model="queryParams.brand"
|
||||
placeholder="请输入品牌"
|
||||
clearable
|
||||
@keyup.enter.native="handleQuery"
|
||||
/>
|
||||
</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>
|
||||
<div class="transfer-box-container">
|
||||
<el-row>
|
||||
<!-- 左侧区域 -->
|
||||
<el-col :span="8">
|
||||
<el-tabs v-model="activeName">
|
||||
<el-tab-pane label="低于阈值" name="first">
|
||||
<!-- 低于阈值表格 -->
|
||||
<el-table
|
||||
:data="thresholdData"
|
||||
border
|
||||
:loading="loading"
|
||||
highlight-current-row
|
||||
@row-click="handleThresholdRowClick"
|
||||
:row-class-name="thresholdRowClassName"
|
||||
style="width: 100%; margin-bottom: 20px"
|
||||
>
|
||||
<el-table-column
|
||||
prop="name"
|
||||
label="物料名"
|
||||
align="center"
|
||||
></el-table-column>
|
||||
<el-table-column
|
||||
prop="model"
|
||||
label="型号"
|
||||
align="center"
|
||||
></el-table-column>
|
||||
<el-table-column
|
||||
prop="brand"
|
||||
label="品牌"
|
||||
align="center"
|
||||
></el-table-column>
|
||||
<el-table-column
|
||||
prop="unit"
|
||||
label="单位"
|
||||
align="center"
|
||||
></el-table-column>
|
||||
<el-table-column prop="inventory" label="库存量" align="center">
|
||||
<template slot-scope="scope">
|
||||
<span class="inventory-value">{{ scope.row.inventory }}</span>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column prop="taskInventory" label="在途料" align="center">
|
||||
<template slot-scope="scope">
|
||||
<span class="task-inventory-value">{{ scope.row.taskInventory || 0 }}</span>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
<pagination
|
||||
v-show="total1 > 0"
|
||||
:total="total1"
|
||||
:page.sync="queryParams1.pageNum"
|
||||
:limit.sync="queryParams1.pageSize"
|
||||
@pagination="getList"
|
||||
/>
|
||||
</el-tab-pane>
|
||||
<el-tab-pane label="未低于阈值" name="second">
|
||||
<!-- 未低于阈值表格 -->
|
||||
<el-table
|
||||
:data="notThresholdData"
|
||||
border
|
||||
:loading="loading"
|
||||
highlight-current-row
|
||||
@row-click="handleNotThresholdRowClick"
|
||||
:row-class-name="notThresholdRowClassName"
|
||||
style="width: 100%; margin-bottom: 10px"
|
||||
>
|
||||
<el-table-column
|
||||
prop="name"
|
||||
label="物料名"
|
||||
align="center"
|
||||
></el-table-column>
|
||||
<el-table-column
|
||||
prop="model"
|
||||
label="型号"
|
||||
align="center"
|
||||
></el-table-column>
|
||||
<el-table-column
|
||||
prop="brand"
|
||||
label="品牌"
|
||||
align="center"
|
||||
></el-table-column>
|
||||
<el-table-column
|
||||
prop="unit"
|
||||
label="单位"
|
||||
align="center"
|
||||
></el-table-column>
|
||||
<el-table-column prop="inventory" label="库存量" align="center">
|
||||
<template slot-scope="scope">
|
||||
<span class="inventory-value">{{ scope.row.inventory }}</span>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column prop="taskInventory" label="在途料" align="center">
|
||||
<template slot-scope="scope">
|
||||
<span class="task-inventory-value">{{ scope.row.taskInventory || 0 }}</span>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
<pagination
|
||||
v-show="total2 > 0"
|
||||
:total="total2"
|
||||
:page.sync="queryParams2.pageNum"
|
||||
:limit.sync="queryParams2.pageSize"
|
||||
@pagination="getList"
|
||||
/>
|
||||
</el-tab-pane>
|
||||
</el-tabs>
|
||||
</el-col>
|
||||
|
||||
<!-- 中间操作按钮 -->
|
||||
<el-col :span="4" style="text-align: center; margin-top: 120px">
|
||||
<el-button
|
||||
type="primary"
|
||||
@click="moveToRight"
|
||||
style="margin-bottom: 20px"
|
||||
>
|
||||
加入采购单 >>
|
||||
</el-button>
|
||||
<br />
|
||||
<el-button type="primary" @click="moveToLeft"> << 撤销 </el-button>
|
||||
</el-col>
|
||||
|
||||
<!-- 右侧列表 -->
|
||||
<el-col :span="12">
|
||||
<div class="table-title">
|
||||
补充库存
|
||||
<el-button
|
||||
type="text"
|
||||
@click="addCustomItem"
|
||||
style="margin-left: 10px"
|
||||
>
|
||||
新增
|
||||
</el-button>
|
||||
</div>
|
||||
<el-table
|
||||
:data="rightData"
|
||||
border
|
||||
highlight-current-row
|
||||
@row-click="handleRightRowClick"
|
||||
:row-class-name="rightRowClassName"
|
||||
style="width: 100%"
|
||||
>
|
||||
<!-- 物料名 -->
|
||||
<el-table-column label="物料名" align="center">
|
||||
<template slot-scope="{ row }">
|
||||
<!-- 如果是来自左侧的数据,就显示纯文本;否则可以输入 -->
|
||||
<el-input
|
||||
v-if="!row.fromLeft"
|
||||
v-model="row.name"
|
||||
size="small"
|
||||
placeholder="请输入物料名"
|
||||
/>
|
||||
<span v-else>{{ row.name }}</span>
|
||||
</template>
|
||||
</el-table-column>
|
||||
|
||||
<!-- 型号 -->
|
||||
<el-table-column label="型号" align="center">
|
||||
<template slot-scope="{ row }">
|
||||
<el-input
|
||||
v-if="!row.fromLeft"
|
||||
v-model="row.model"
|
||||
size="small"
|
||||
placeholder="请输入型号"
|
||||
/>
|
||||
<span v-else>{{ row.model }}</span>
|
||||
</template>
|
||||
</el-table-column>
|
||||
|
||||
<!-- 品牌 -->
|
||||
<el-table-column label="品牌" align="center">
|
||||
<template slot-scope="{ row }">
|
||||
<el-input
|
||||
v-if="!row.fromLeft"
|
||||
v-model="row.brand"
|
||||
size="small"
|
||||
placeholder="请输入品牌"
|
||||
/>
|
||||
<span v-else>{{ row.brand }}</span>
|
||||
</template>
|
||||
</el-table-column>
|
||||
|
||||
<el-table-column label="规格" align="center">
|
||||
<template slot-scope="{ row }">
|
||||
<el-input
|
||||
v-if="!row.fromLeft"
|
||||
v-model="row.specifications"
|
||||
size="small"
|
||||
placeholder="请输入规格"
|
||||
/>
|
||||
<span v-else>{{ row.specifications }}</span>
|
||||
</template>
|
||||
</el-table-column>
|
||||
|
||||
<el-table-column label="单位" align="center">
|
||||
<template slot-scope="{ row }">
|
||||
<el-input
|
||||
v-if="!row.fromLeft"
|
||||
v-model="row.unit"
|
||||
size="small"
|
||||
placeholder="请输入单位"
|
||||
/>
|
||||
<span v-else>{{ row.unit }}</span>
|
||||
</template>
|
||||
</el-table-column>
|
||||
|
||||
<!-- 补充库存量 -->
|
||||
<el-table-column label="补充库存量" align="center">
|
||||
<template slot-scope="{ row }">
|
||||
<el-input
|
||||
v-model="row.taskInventory"
|
||||
size="small"
|
||||
type="number"
|
||||
placeholder="请输入补充库存量"
|
||||
/>
|
||||
</template>
|
||||
</el-table-column>
|
||||
|
||||
<el-table-column label="截止日期" align="center">
|
||||
<template slot-scope="{ row }">
|
||||
<el-date-picker
|
||||
v-model="row.endTime"
|
||||
align="right"
|
||||
type="date"
|
||||
placeholder="选择日期"
|
||||
value-format="yyyy-MM-dd"
|
||||
>
|
||||
</el-date-picker>
|
||||
</template>
|
||||
</el-table-column>
|
||||
|
||||
<!-- 操作列:只能删除自定义新增的行,来自左侧的只能移回 -->
|
||||
<el-table-column label="操作" align="center">
|
||||
<template slot-scope="{ row }">
|
||||
<el-button
|
||||
v-if="!row.fromLeft"
|
||||
type="text"
|
||||
@click.stop="removeRightItem(row)"
|
||||
>
|
||||
删除
|
||||
</el-button>
|
||||
<el-button v-else type="text" @click.stop="moveRowBack(row)">
|
||||
移回左侧
|
||||
</el-button>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
</el-col>
|
||||
</el-row>
|
||||
<div style="display: flex; justify-content: flex-end; margin-top: 40px">
|
||||
<el-button type="primary" @click="submitForm">提交采购单</el-button>
|
||||
<el-button @click="cancel">取 消</el-button>
|
||||
</div>
|
||||
</div>
|
||||
</el-card>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { listNotThreshold, listThreshold } from "@/api/oa/warehouse/oaWarehouse";
|
||||
import { addOaWarehouseTaskBatch } from "@/api/oa/warehouse/warehouseTask";
|
||||
|
||||
export default {
|
||||
name: "TransferBox",
|
||||
data() {
|
||||
return {
|
||||
loading: false,
|
||||
thresholdData: [],
|
||||
// 显示搜索条件
|
||||
showSearch: true,
|
||||
notThresholdData: [],
|
||||
// 右侧列表
|
||||
rightData: [],
|
||||
total1: 0,
|
||||
total2: 0,
|
||||
// 左侧选中项:为了区分两个表格,各自记录
|
||||
thresholdSelection: null,
|
||||
notThresholdSelection: null,
|
||||
// 右侧选中项
|
||||
rightSelection: null,
|
||||
wareList: [],
|
||||
queryParams1: {
|
||||
pageSize: 10,
|
||||
pageNum: 1,
|
||||
},
|
||||
queryParams2: {
|
||||
pageSize: 10,
|
||||
pageNum: 1,
|
||||
},
|
||||
queryParams: {
|
||||
pageSize: 10,
|
||||
pageNum: 1,
|
||||
},
|
||||
activeName: "first",
|
||||
};
|
||||
},
|
||||
|
||||
created() {
|
||||
this.getList();
|
||||
},
|
||||
methods: {
|
||||
submitForm() {
|
||||
addOaWarehouseTaskBatch(this.rightData).then((res) => {
|
||||
this.goBack();
|
||||
});
|
||||
},
|
||||
/** 返回页面 */
|
||||
goBack() {
|
||||
// 关闭当前标签页并返回上个页面
|
||||
this.$tab.closePage(this.$route);
|
||||
this.$router.back();
|
||||
},
|
||||
cancel() {
|
||||
this.resetQuery();
|
||||
this.rightData = [];
|
||||
},
|
||||
/** 搜索按钮操作 */
|
||||
handleQuery() {
|
||||
this.queryParams1 = this.queryParams;
|
||||
this.queryParams2 = this.queryParams;
|
||||
this.queryParams1.pageNum = 1;
|
||||
this.queryParams2.pageNum = 1;
|
||||
this.getList();
|
||||
},
|
||||
/** 重置按钮操作 */
|
||||
resetQuery() {
|
||||
this.resetForm("queryForm1");
|
||||
this.resetForm("queryForm2");
|
||||
this.resetForm("queryForm");
|
||||
this.handleQuery();
|
||||
},
|
||||
/** 查询库存管理列表 */
|
||||
getList() {
|
||||
this.loading = true;
|
||||
listThreshold(this.queryParams1).then((response) => {
|
||||
this.thresholdData = response.rows;
|
||||
this.total1 = response.total;
|
||||
listNotThreshold(this.queryParams2).then((response) => {
|
||||
this.notThresholdData = response.rows;
|
||||
this.total2 = response.total;
|
||||
this.loading = false;
|
||||
});
|
||||
});
|
||||
},
|
||||
// ========= 左侧:低于阈值表格,选中处理 =========
|
||||
handleThresholdRowClick(row) {
|
||||
this.thresholdSelection = row;
|
||||
// 若点击了低阈值表格,则清空另一个表格以及右侧选中的状态
|
||||
this.notThresholdSelection = null;
|
||||
this.rightSelection = null;
|
||||
},
|
||||
|
||||
// ========= 左侧:未低于阈值表格,选中处理 =========
|
||||
handleNotThresholdRowClick(row) {
|
||||
this.notThresholdSelection = row;
|
||||
// 若点击了未阈值表格,则清空另一个表格以及右侧选中的状态
|
||||
this.thresholdSelection = null;
|
||||
this.rightSelection = null;
|
||||
},
|
||||
|
||||
// ========= 右侧表格,选中处理 =========
|
||||
handleRightRowClick(row) {
|
||||
this.rightSelection = row;
|
||||
// 点击右侧时,可以把左侧两个表格的选中都清掉
|
||||
this.thresholdSelection = null;
|
||||
this.notThresholdSelection = null;
|
||||
},
|
||||
|
||||
// ========= 移到右侧 =========
|
||||
moveToRight() {
|
||||
// 优先判断是否选中"低阈值"表格的行
|
||||
if (this.thresholdSelection) {
|
||||
// 1. 从 thresholdData 移除
|
||||
this.thresholdData = this.thresholdData.filter(
|
||||
(item) => item.id !== this.thresholdSelection.id
|
||||
);
|
||||
// 2. push到右侧
|
||||
this.thresholdSelection.fromLeft = true;
|
||||
this.thresholdSelection.taskInventory = 0;
|
||||
this.thresholdSelection.origin = "threshold";
|
||||
if (
|
||||
this.rightData.find(
|
||||
(item) => item.id === this.thresholdSelection.id
|
||||
) === undefined
|
||||
) {
|
||||
this.rightData.push({ ...this.thresholdSelection });
|
||||
}
|
||||
|
||||
// 3. 清除选中
|
||||
this.thresholdSelection = null;
|
||||
return;
|
||||
}
|
||||
|
||||
// 再判断是否选中"未低阈值"表格的行
|
||||
if (this.notThresholdSelection) {
|
||||
// 1. 从 notThresholdData 移除
|
||||
|
||||
this.notThresholdData = this.notThresholdData.filter(
|
||||
(item) => item.id !== this.notThresholdSelection.id
|
||||
);
|
||||
// 2. push到右侧
|
||||
this.notThresholdSelection.fromLeft = true;
|
||||
this.notThresholdSelection.taskInventory = 0;
|
||||
this.notThresholdSelection.origin = "notThreshold";
|
||||
if (
|
||||
this.rightData.find(
|
||||
(item) => item.id === this.notThresholdSelection.id
|
||||
) === undefined
|
||||
) {
|
||||
this.rightData.push({ ...this.notThresholdSelection });
|
||||
}
|
||||
|
||||
// 3. 清除选中
|
||||
this.notThresholdSelection = null;
|
||||
return;
|
||||
}
|
||||
|
||||
// 若都没有选中,提示
|
||||
this.$message.warning("请先选择左侧的一条数据!");
|
||||
},
|
||||
|
||||
// ========= 从右侧移回左侧 =========
|
||||
moveToLeft() {
|
||||
if (!this.rightSelection) {
|
||||
this.$message.warning("请先选择右侧的一条数据!");
|
||||
return;
|
||||
}
|
||||
// 若选中的行是用户自定义的(fromLeft=false),则无法移回
|
||||
if (!this.rightSelection.fromLeft) {
|
||||
this.$message.warning("该数据是新增的,无法移回左侧!");
|
||||
return;
|
||||
}
|
||||
|
||||
// 如果是来自左侧,则看它 origin 是哪个
|
||||
const row = { ...this.rightSelection };
|
||||
this.rightData = this.rightData.filter((item) => item.id !== row.id);
|
||||
|
||||
// 按 origin 放回对应数组
|
||||
if (row.origin === "threshold") {
|
||||
this.thresholdData.push(row);
|
||||
} else if (row.origin === "notThreshold") {
|
||||
this.notThresholdData.push(row);
|
||||
}
|
||||
|
||||
// 清空选中
|
||||
this.rightSelection = null;
|
||||
},
|
||||
|
||||
// ========= 右侧操作列:移回 =========
|
||||
moveRowBack(row) {
|
||||
// 同理,把这个 row 从右侧移除,并放回对应左侧表格
|
||||
this.rightData = this.rightData.filter((item) => item.id !== row.id);
|
||||
if (row.origin === "threshold") {
|
||||
this.thresholdData.push({ ...row });
|
||||
} else if (row.origin === "notThreshold") {
|
||||
this.notThresholdData.push({ ...row });
|
||||
}
|
||||
},
|
||||
|
||||
// ========= 新增一条自定义行到右侧 =========
|
||||
addCustomItem() {
|
||||
const newId = new Date().getTime(); // 简单生成唯一id
|
||||
this.rightData.push({
|
||||
id: newId,
|
||||
name: "",
|
||||
model: "",
|
||||
brand: "",
|
||||
inventory: "",
|
||||
fromLeft: false, // 标识为手动新增
|
||||
});
|
||||
},
|
||||
|
||||
// ========= 删除右侧的自定义行 =========
|
||||
removeRightItem(row) {
|
||||
this.rightData = this.rightData.filter((item) => item.id !== row.id);
|
||||
},
|
||||
|
||||
// ========= 行样式控制(高亮) =========
|
||||
thresholdRowClassName({ row }) {
|
||||
return this.thresholdSelection && this.thresholdSelection.id === row.id
|
||||
? "selected-row"
|
||||
: "";
|
||||
},
|
||||
notThresholdRowClassName({ row }) {
|
||||
return this.notThresholdSelection &&
|
||||
this.notThresholdSelection.id === row.id
|
||||
? "selected-row"
|
||||
: "";
|
||||
},
|
||||
rightRowClassName({ row }) {
|
||||
return this.rightSelection && this.rightSelection.id === row.id
|
||||
? "selected-row"
|
||||
: "";
|
||||
},
|
||||
},
|
||||
};
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
.transfer-box-container {
|
||||
padding: 20px;
|
||||
}
|
||||
|
||||
.table-title {
|
||||
font-weight: bold;
|
||||
margin-bottom: 10px;
|
||||
}
|
||||
|
||||
.selected-row {
|
||||
background-color: #f0f9eb !important;
|
||||
}
|
||||
|
||||
.inventory-value {
|
||||
color: #409EFF;
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
.task-inventory-value {
|
||||
color: #67C23A;
|
||||
margin-left: 5px;
|
||||
}
|
||||
</style>
|
||||
160
ruoyi-ui/src/views/oa/oaWarehouse/data.vue
Normal file
160
ruoyi-ui/src/views/oa/oaWarehouse/data.vue
Normal file
@@ -0,0 +1,160 @@
|
||||
<template>
|
||||
<div class="app-container">
|
||||
<!-- 返回按钮 -->
|
||||
<el-row class="mb8">
|
||||
<el-col>
|
||||
<el-card class="box-card" style="display: flex; align-items: center;">
|
||||
<el-button
|
||||
icon="el-icon-arrow-left"
|
||||
@click="goBack"
|
||||
circle
|
||||
>
|
||||
</el-button>
|
||||
<span class="text item">
|
||||
物料:<strong>{{ warehouse.name }}</strong> 的出/入库详情
|
||||
</span>
|
||||
</el-card>
|
||||
</el-col>
|
||||
</el-row>
|
||||
|
||||
<el-row class="mb8">
|
||||
<el-col>
|
||||
<el-tabs v-model="activeTab" @tab-click="handleTabClick">
|
||||
<el-tab-pane label="全部" name="all" />
|
||||
<el-tab-pane label="出库" name="out" />
|
||||
<el-tab-pane label="入库" name="in" />
|
||||
</el-tabs>
|
||||
</el-col>
|
||||
</el-row>
|
||||
|
||||
|
||||
<right-toolbar :showSearch.sync="showSearch" @queryTable="getList" />
|
||||
|
||||
<el-table v-loading="loading" :data="outWarehouseList">
|
||||
<!-- 全部 -->
|
||||
<template v-if="activeTab === 'all'">
|
||||
<el-table-column type="selection" width="55" align="center" />
|
||||
<el-table-column label="序号" align="center" type="index" />
|
||||
<el-table-column label="类型" align="center" >
|
||||
<template slot-scope="scope">
|
||||
<el-tag :type="scope.row.type===0?'success':'warning'">{{scope.row.type===0?'出库':'入库'}}</el-tag>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="单据号" align="center" prop="masterNum" />
|
||||
<el-table-column :label="`数量(${warehouse.unit})`" align="center" prop="amount" />
|
||||
<el-table-column label="价格快照" align="center" prop="signPrice" />
|
||||
<el-table-column label="操作时间" align="center" prop="createTime" />
|
||||
<el-table-column label="关联项目" align="center" prop="projectName" />
|
||||
<el-table-column label="备注" align="center" prop="remark" />
|
||||
</template>
|
||||
|
||||
<!-- 出库 -->
|
||||
<template v-else-if="activeTab === 'out'">
|
||||
<el-table-column type="selection" width="55" align="center" />
|
||||
<el-table-column label="序号" align="center" type="index" />
|
||||
<el-table-column label="出库单" align="center" prop="masterNum" />
|
||||
<el-table-column :label="`出库数量(${warehouse.unit})`" align="center" prop="amount" />
|
||||
<el-table-column label="出库价格快照" align="center" prop="signPrice" />
|
||||
<el-table-column label="操作时间" align="center" prop="createTime" />
|
||||
<el-table-column label="关联项目" align="center" prop="projectName" />
|
||||
<el-table-column label="备注" align="center" prop="remark" />
|
||||
</template>
|
||||
|
||||
<!-- 入库 -->
|
||||
<template v-else>
|
||||
<el-table-column type="selection" width="55" align="center" />
|
||||
<el-table-column label="序号" align="center" type="index" />
|
||||
<el-table-column label="入库单" align="center" prop="masterNum" />
|
||||
<el-table-column :label="`入库数量(${warehouse.unit})`" align="center" prop="amount" />
|
||||
<el-table-column label="入库价格快照" align="center" prop="signPrice" />
|
||||
<el-table-column label="操作时间" align="center" prop="createTime" />
|
||||
<el-table-column label="关联项目" align="center" prop="projectName" />
|
||||
<el-table-column label="备注" align="center" prop="remark" />
|
||||
</template>
|
||||
</el-table>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { listOaOutWarehouse } from "@/api/oa/warehouse/oaOutWarehouse";
|
||||
import { getOaWarehouse } from "@/api/oa/warehouse/oaWarehouse";
|
||||
|
||||
export default {
|
||||
name: "Data",
|
||||
data() {
|
||||
return {
|
||||
// Tab 控制:'all' | 'out' | 'in'
|
||||
activeTab: "all",
|
||||
|
||||
showSearch: true,
|
||||
// 出/入库列表
|
||||
outWarehouseList: [],
|
||||
// 查询参数:初始 type 为 null(全部)
|
||||
queryParams: {
|
||||
pageNum: 1,
|
||||
pageSize: 9999,
|
||||
warehouseId: this.$route.params.warehouseId,
|
||||
type: null,
|
||||
},
|
||||
// 物料信息
|
||||
warehouse: {},
|
||||
|
||||
// 加载状态
|
||||
loading: false,
|
||||
};
|
||||
},
|
||||
created() {
|
||||
this.getWarehouse();
|
||||
this.getList();
|
||||
},
|
||||
methods: {
|
||||
// Tab 切换
|
||||
handleTabClick(tab) {
|
||||
switch (tab.name) {
|
||||
case "out":
|
||||
this.queryParams.type = 0;
|
||||
break;
|
||||
case "in":
|
||||
this.queryParams.type = 1;
|
||||
break;
|
||||
default:
|
||||
this.queryParams.type = null;
|
||||
}
|
||||
this.queryParams.pageNum = 1;
|
||||
this.getList();
|
||||
},
|
||||
// 获取物料详情
|
||||
getWarehouse() {
|
||||
getOaWarehouse(this.queryParams.warehouseId).then((res) => {
|
||||
this.warehouse = res.data;
|
||||
});
|
||||
},
|
||||
// 获取列表
|
||||
getList() {
|
||||
this.loading = true;
|
||||
listOaOutWarehouse(this.queryParams)
|
||||
.then((res) => {
|
||||
this.outWarehouseList = res.rows;
|
||||
this.total = res.total;
|
||||
})
|
||||
.finally(() => {
|
||||
this.loading = false;
|
||||
});
|
||||
},
|
||||
|
||||
/** 返回页面 */
|
||||
goBack() {
|
||||
this.$tab.closePage(this.$route);
|
||||
this.$router.back();
|
||||
}
|
||||
|
||||
},
|
||||
};
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss">
|
||||
/* 根据需要补充自定义样式 */
|
||||
.mb8 {
|
||||
margin-bottom: 8px;
|
||||
}
|
||||
</style>
|
||||
@@ -0,0 +1,77 @@
|
||||
<template>
|
||||
<el-card shadow="hover" class="chart-card">
|
||||
<div slot="header" class="clearfix">
|
||||
<span>{{ title }}</span>
|
||||
<el-date-picker
|
||||
v-model="selectedYear"
|
||||
type="month"
|
||||
placeholder="选择时间"
|
||||
size="mini"
|
||||
class="float-right"
|
||||
value-format="yyyy-MM"
|
||||
@change="onYearChange"
|
||||
/>
|
||||
</div>
|
||||
<div ref="chart" class="chart-container"></div>
|
||||
</el-card>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import * as echarts from 'echarts'
|
||||
|
||||
export default {
|
||||
name: 'ChartContainer',
|
||||
props: {
|
||||
title: String,
|
||||
ranges: Array,
|
||||
range: String,
|
||||
option: Object
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
localRange: this.range,
|
||||
selectedYear: null,
|
||||
}
|
||||
},
|
||||
watch: {
|
||||
localRange(val) {
|
||||
this.$emit('update:range', val)
|
||||
this.renderChart()
|
||||
},
|
||||
// 只要 parent 更新了 option,就重绘
|
||||
option: {
|
||||
deep: true,
|
||||
immediate: true,
|
||||
handler() {
|
||||
this.renderChart()
|
||||
}
|
||||
}
|
||||
},
|
||||
mounted() {
|
||||
this.renderChart()
|
||||
},
|
||||
methods: {
|
||||
onYearChange(val) {
|
||||
// year: Date 对象,或者 Number(部分版本 ElementUI 会直接返回年)
|
||||
const year = val instanceof Date ? val.getFullYear() : val;
|
||||
this.selectedYear = year;
|
||||
this.$emit('year-change', year);
|
||||
},
|
||||
renderChart() {
|
||||
const chart = echarts.init(this.$refs.chart)
|
||||
chart.setOption(this.option)
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
.chart-card {
|
||||
height: 360px;
|
||||
}
|
||||
|
||||
.chart-container {
|
||||
width: 100%;
|
||||
height: 300px;
|
||||
}
|
||||
</style>
|
||||
@@ -0,0 +1,53 @@
|
||||
<template>
|
||||
<chart-container
|
||||
title="出入库对比"
|
||||
:option="chartOption"
|
||||
@year-change="onChildYearChange"
|
||||
/>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { monthDataAnalysis } from "@/api/oa/warehouse/oaWarehouse";
|
||||
import ChartContainer from './ChartContainer.vue';
|
||||
|
||||
export default {
|
||||
name: 'InOutCompare',
|
||||
components: {ChartContainer},
|
||||
props: {},
|
||||
data() {
|
||||
return {
|
||||
year: undefined,
|
||||
chartOption: {}
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
|
||||
},
|
||||
mounted() {
|
||||
this.getData()
|
||||
},
|
||||
methods: {
|
||||
onChildYearChange(year) {
|
||||
this.year = year;
|
||||
this.getData()
|
||||
},
|
||||
getData() {
|
||||
monthDataAnalysis({month:this.year}).then(res => {
|
||||
this.chartOption = {
|
||||
legend: {},
|
||||
xAxis: {
|
||||
type: 'category',
|
||||
data: ['1月', '2月', '3月', '4月', '5月', '6月', '7月', '8月', '9月', '10月', '11月', '12月']
|
||||
},
|
||||
yAxis: {type: 'value'},
|
||||
series: [
|
||||
{name: '入库量', type: 'bar', data: res.data.inData["月"]},
|
||||
{name: '出库量', type: 'bar', data: res.data.outData["月"]}
|
||||
]
|
||||
}
|
||||
})
|
||||
}
|
||||
},
|
||||
|
||||
}
|
||||
</script>
|
||||
@@ -0,0 +1,60 @@
|
||||
<template>
|
||||
<chart-container
|
||||
title="库存趋势分析"
|
||||
@year-change="onChildYearChange"
|
||||
:option="dataMap"
|
||||
/>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { monthDataAnalysis } from "@/api/oa/warehouse/oaWarehouse";
|
||||
import ChartContainer from './ChartContainer.vue';
|
||||
|
||||
export default {
|
||||
name: 'InventoryTrend',
|
||||
components: {ChartContainer},
|
||||
props: {},
|
||||
data() {
|
||||
return {
|
||||
year: undefined,
|
||||
dataMap:{}
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
},
|
||||
mounted() {
|
||||
this.getData()
|
||||
},
|
||||
methods: {
|
||||
onChildYearChange(year) {
|
||||
this.year = year;
|
||||
this.getData()
|
||||
},
|
||||
getData() {
|
||||
|
||||
monthDataAnalysis({month:this.year}).then(res => {
|
||||
console.log(res.data)
|
||||
const today = new Date();
|
||||
|
||||
// 2. 拿到“本月已过天数”
|
||||
const daysSoFar = today.getDate(); // 1–31
|
||||
|
||||
// 3. 生成一个长度为 daysSoFar 的数组,内容是 “1日”、“2日”…“N日”
|
||||
const dayCategories = Array.from(
|
||||
{ length: daysSoFar },
|
||||
(_, i) => `${i + 1}日`
|
||||
);
|
||||
|
||||
this.dataMap = {
|
||||
xAxis: {
|
||||
type: 'category',
|
||||
data: dayCategories
|
||||
},
|
||||
yAxis: {type: 'value'},
|
||||
series: [{data: res.data.dataMap["日"], type: 'line'}]
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
309
ruoyi-ui/src/views/oa/oaWarehouse/data/index.vue
Normal file
309
ruoyi-ui/src/views/oa/oaWarehouse/data/index.vue
Normal file
@@ -0,0 +1,309 @@
|
||||
<template>
|
||||
<div class="dashboard">
|
||||
|
||||
<el-row>
|
||||
<el-col span="24">
|
||||
<el-form :inline="true" :model="filters" class="filter-form" size="mini">
|
||||
<el-form-item label="时间范围:">
|
||||
<el-date-picker
|
||||
v-model="filters.dateRange"
|
||||
type="daterange"
|
||||
range-separator="至"
|
||||
start-placeholder="开始日期"
|
||||
end-placeholder="结束日期"
|
||||
value-format="yyyy-MM-dd"
|
||||
></el-date-picker>
|
||||
</el-form-item>
|
||||
<el-form-item label="物料分类:">
|
||||
<el-select v-model="filters.category" placeholder="全部分类" clearable>
|
||||
<el-option v-for="opt in categoryOptions" :key="opt.value" :label="opt.label" :value="opt.value"/>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item label="仓库位置:">
|
||||
<el-select v-model="filters.warehouse" placeholder="全部仓库" clearable disabled="">
|
||||
<el-option v-for="opt in warehouseOptions" :key="opt.value" :label="opt.label" :value="opt.value"/>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item label="供应商:">
|
||||
<el-select v-model="filters.supplier" placeholder="全部供应商" clearable disabled="">
|
||||
<el-option v-for="opt in supplierOptions" :key="opt.value" :label="opt.label" :value="opt.value"/>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item>
|
||||
<el-button type="primary" @click="fetchData">查询</el-button>
|
||||
<el-button type="success" icon="el-icon-download" @click="exportReport">导出报表</el-button>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
</el-col>
|
||||
</el-row>
|
||||
<el-row
|
||||
type="flex"
|
||||
class="card-row"
|
||||
:gutter="20"
|
||||
justify="space-between"
|
||||
>
|
||||
<el-col
|
||||
v-for="card in summaryCards"
|
||||
:key="card.title"
|
||||
:style="{ flex: `0 0 ${cardWidth}` }"
|
||||
>
|
||||
<el-card shadow="hover" class="summary-card">
|
||||
<div class="card-content">
|
||||
<div class="card-title">{{ card.title }}</div>
|
||||
<div class="card-value">{{ card.value }}</div>
|
||||
<div
|
||||
class="card-desc"
|
||||
:class="card.trend > 0 ? 'trend-up' : 'trend-down'"
|
||||
>
|
||||
<i
|
||||
:class="
|
||||
card.trend > 0
|
||||
? 'el-icon-caret-top'
|
||||
: 'el-icon-caret-bottom'
|
||||
"
|
||||
></i>
|
||||
{{ Math.abs(card.trend) }}%
|
||||
{{ card.trend > 0 ? '环比上月' : '环比昨日' }}
|
||||
</div>
|
||||
</div>
|
||||
</el-card>
|
||||
</el-col>
|
||||
</el-row>
|
||||
|
||||
<!-- Encapsulated Charts -->
|
||||
<el-row :gutter="20" class="chart-row">
|
||||
<el-col :span="12">
|
||||
<inventory-trend :range.sync="chartRange.inventory"/>
|
||||
</el-col>
|
||||
<el-col :span="12">
|
||||
<in-out-compare :range.sync="chartRange.movements"/>
|
||||
</el-col>
|
||||
</el-row>
|
||||
|
||||
<!-- Table -->
|
||||
<el-card shadow="hover" class="table-card">
|
||||
<div slot="header" class="clearfix">
|
||||
<span>最近记录</span>
|
||||
</div>
|
||||
<el-table
|
||||
:data="tableData"
|
||||
border
|
||||
size="small"
|
||||
style="width: 100%"
|
||||
>
|
||||
<el-table-column prop="name" label="物料名称"/>
|
||||
<el-table-column prop="model" label="型号"/>
|
||||
<el-table-column prop="brand" label="品牌"/>
|
||||
<el-table-column prop="specifications" label="规格型号"/>
|
||||
<el-table-column prop="inventory" label="当前库存"/>
|
||||
<el-table-column prop="threshold" label="安全库存"/>
|
||||
<el-table-column prop="taskInventory" label="在途数量"/>
|
||||
<el-table-column prop="lastInbound" label="最近入库"/>
|
||||
<el-table-column prop="lastOutbound" label="最近出库"/>
|
||||
<el-table-column label="库存状态">
|
||||
<template #default="{ row }">
|
||||
<el-tag
|
||||
:type="calcInventoryStatus(row.inventory, row.taskInventory,row.threshold).type"
|
||||
>
|
||||
{{ calcInventoryStatus(row.inventory, row.taskInventory,row.threshold).status }}
|
||||
</el-tag>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
|
||||
</el-card>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { CardDataAnalysis, recentWarehouse } from "@/api/oa/warehouse/oaWarehouse";
|
||||
import InOutCompare from "@/views/oa/oaWarehouse/data/components/InOutCompare.vue";
|
||||
import InventoryTrend from "@/views/oa/oaWarehouse/data/components/InventoryTrend.vue";
|
||||
|
||||
export default {
|
||||
name: 'Dashboard',
|
||||
components: {InventoryTrend, InOutCompare},
|
||||
data() {
|
||||
return {
|
||||
filters: {
|
||||
dateRange: [],
|
||||
category: null,
|
||||
warehouse: null,
|
||||
supplier: null,
|
||||
},
|
||||
categoryOptions: [
|
||||
{label: '全部分类', value: null},
|
||||
{label: '全部分类', value: 'hardware'},
|
||||
{label: '全部分类', value: 'pipe'},
|
||||
// ...
|
||||
],
|
||||
warehouseOptions: [
|
||||
{label: '全部仓库', value: null},
|
||||
{label: '全部仓库', value: 'main'},
|
||||
{label: '全部仓库', value: 'A'},
|
||||
// ...
|
||||
],
|
||||
supplierOptions: [
|
||||
{label: '全部供应商', value: null},
|
||||
{label: '全部供应商', value: 'A'},
|
||||
{label: '全部供应商', value: 'B'},
|
||||
// ...
|
||||
],
|
||||
summaryCards: [
|
||||
{title: '当前总库存量', value: 238526, trend: 8.5},
|
||||
{title: '在途物料数量', value: 12385, trend: -3.2},
|
||||
{title: '今日入库量', value: 1856, trend: 12.8},
|
||||
{title: '今日出库量', value: 2156, trend: 5.6},
|
||||
{title: '预警信息', value: 15, trend: 0},
|
||||
],
|
||||
chartRange: {
|
||||
inventory: '月',
|
||||
movements: '月',
|
||||
},
|
||||
loading:false,
|
||||
tableData: [],
|
||||
tableFilter: {keyword: ''},
|
||||
queryParams: {
|
||||
|
||||
},
|
||||
queryWarehouse:{
|
||||
limit:10
|
||||
}
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
// 自动计算卡片宽度:(100% - 总间距) / 卡片数
|
||||
cardWidth() {
|
||||
const n = this.summaryCards.length;
|
||||
const totalGutter = (n - 1) * 20; // gutter 20px * (n-1)
|
||||
return `calc((100% - ${totalGutter}px) / ${n})`;
|
||||
},
|
||||
filteredTableData() {
|
||||
const kw = this.tableFilter.keyword && this.tableFilter.keyword.toLowerCase()
|
||||
let data = this.tableData
|
||||
if (kw) {
|
||||
data = data.filter(r => r.name.toLowerCase().includes(kw))
|
||||
}
|
||||
const start = (this.currentPage - 1) * this.pageSize
|
||||
return data.slice(start, start + this.pageSize)
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
|
||||
calcInventoryStatus(inventory, inTransit, threshold) {
|
||||
const total = inventory + inTransit;
|
||||
|
||||
if (total > threshold+10) {
|
||||
return { status: '库存积压', type: 'warning' };
|
||||
}else
|
||||
if (total > threshold) {
|
||||
return { status: '正常', type: 'success' };
|
||||
}else
|
||||
if (total < threshold-2 && total > threshold) {
|
||||
return { status: '库存预警', type: 'danger' };
|
||||
}
|
||||
return { status: '库存不足', type: 'info' };
|
||||
},
|
||||
fetchData() {
|
||||
this.loading = true
|
||||
// TODO: 调用后端接口,获取 summaryCards, tableData,以及图表数据
|
||||
if (this.filters.dateRange.length > 0) {
|
||||
this.queryParams["beginTime"] = this.filters.dateRange[0]+" 00:00:00";
|
||||
this.queryParams["endTime"] = this.filters.dateRange[1]+" 23:59:59";
|
||||
}
|
||||
|
||||
CardDataAnalysis(this.queryParams).then(res => {
|
||||
this.summaryCards = res.data
|
||||
this.initCharts()
|
||||
})
|
||||
recentWarehouse(this.queryWarehouse).then(response => {
|
||||
|
||||
this.tableData = response.data;
|
||||
this.loading = false;
|
||||
});
|
||||
|
||||
|
||||
},
|
||||
exportReport() {
|
||||
// TODO: 导出报表逻辑
|
||||
},
|
||||
|
||||
},
|
||||
mounted() {
|
||||
this.fetchData()
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
.dashboard {
|
||||
padding: 20px;
|
||||
}
|
||||
|
||||
.filter-form {
|
||||
margin-bottom: 20px;
|
||||
}
|
||||
|
||||
.card-row {
|
||||
margin-bottom: 20px;
|
||||
}
|
||||
|
||||
.summary-card {
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.card-content {
|
||||
padding: 10px 0;
|
||||
}
|
||||
|
||||
.card-title {
|
||||
font-size: 14px;
|
||||
color: #666;
|
||||
margin-bottom: 8px;
|
||||
}
|
||||
|
||||
.card-value {
|
||||
font-size: 24px;
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
.card-desc {
|
||||
margin-top: 4px;
|
||||
font-size: 12px;
|
||||
}
|
||||
|
||||
.trend-up {
|
||||
color: #67c23a;
|
||||
}
|
||||
|
||||
.trend-down {
|
||||
color: #f56c6c;
|
||||
}
|
||||
|
||||
.chart-row {
|
||||
margin-bottom: 20px;
|
||||
}
|
||||
|
||||
.chart-card {
|
||||
height: 360px;
|
||||
}
|
||||
|
||||
.chart-container {
|
||||
width: 100%;
|
||||
height: 300px;
|
||||
}
|
||||
|
||||
.table-card {
|
||||
margin-bottom: 20px;
|
||||
}
|
||||
|
||||
.filter-input {
|
||||
width: 200px;
|
||||
margin-left: 16px;
|
||||
}
|
||||
|
||||
.pagination {
|
||||
margin-top: 16px;
|
||||
text-align: right;
|
||||
}
|
||||
</style>
|
||||
483
ruoyi-ui/src/views/oa/oaWarehouse/index.vue
Normal file
483
ruoyi-ui/src/views/oa/oaWarehouse/index.vue
Normal file
@@ -0,0 +1,483 @@
|
||||
<template>
|
||||
<div class="app-container" v-loading="loading">
|
||||
<el-form :model="queryParams" ref="queryForm" size="small" :inline="true" v-show="showSearch" label-width="68px">
|
||||
<el-form-item label="型号" prop="model">
|
||||
<el-input
|
||||
v-model="queryParams.model"
|
||||
placeholder="请输入型号"
|
||||
clearable
|
||||
@keyup.enter.native="handleQuery"
|
||||
/>
|
||||
</el-form-item>
|
||||
<el-form-item label="物料名称" prop="name">
|
||||
<el-input
|
||||
v-model="queryParams.name"
|
||||
placeholder="请输入物料名称"
|
||||
clearable
|
||||
@keyup.enter.native="handleQuery"
|
||||
/>
|
||||
</el-form-item>
|
||||
<el-form-item label="品牌" prop="brand">
|
||||
<el-input
|
||||
v-model="queryParams.brand"
|
||||
placeholder="请输入品牌"
|
||||
clearable
|
||||
@keyup.enter.native="handleQuery"
|
||||
/>
|
||||
</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="primary"
|
||||
plain
|
||||
icon="el-icon-plus"
|
||||
size="mini"
|
||||
@click="handleAdd"
|
||||
v-hasPermi="['oa:oaWarehouse:add']"
|
||||
>新增</el-button>
|
||||
</el-col>
|
||||
<el-col :span="1.5">
|
||||
<el-button
|
||||
type="success"
|
||||
plain
|
||||
icon="el-icon-edit"
|
||||
size="mini"
|
||||
:disabled="single"
|
||||
@click="handleUpdate"
|
||||
v-hasPermi="['oa:oaWarehouse:edit']"
|
||||
>修改</el-button>
|
||||
</el-col>
|
||||
<el-col :span="1.5">
|
||||
<el-button
|
||||
type="danger"
|
||||
plain
|
||||
icon="el-icon-delete"
|
||||
size="mini"
|
||||
:disabled="multiple"
|
||||
@click="handleDelete"
|
||||
v-hasPermi="['oa:oaWarehouse: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:oaWarehouse:export']"
|
||||
>导出</el-button>
|
||||
</el-col>
|
||||
|
||||
<el-col :span="1.5">
|
||||
<el-button
|
||||
type="info"
|
||||
plain
|
||||
icon="el-icon-upload2"
|
||||
size="mini"
|
||||
@click="handleImport"
|
||||
>导入</el-button>
|
||||
</el-col>
|
||||
|
||||
<el-col :span="1.5">
|
||||
<el-button
|
||||
|
||||
plain
|
||||
icon="el-icon-upload"
|
||||
size="mini"
|
||||
@click="addWarehouseTask"
|
||||
>添加采购计划</el-button>
|
||||
</el-col>
|
||||
<right-toolbar :showSearch.sync="showSearch" @queryTable="getList"></right-toolbar>
|
||||
</el-row>
|
||||
|
||||
<el-table v-loading="loading" :data="oaWarehouseList" @selection-change="handleSelectionChange" :row-class-name="tableRowClassName">
|
||||
<el-table-column type="selection" width="55" align="center" />
|
||||
<el-table-column label="序号" align="center" type="index"/>
|
||||
<el-table-column label="物料" align="center" prop="name" :show-overflow-tooltip="true">
|
||||
<template slot-scope="scope">
|
||||
<router-link :to="'/oa/warehouse-data/index/' + scope.row.id" class="link-type">
|
||||
<i class="el-icon-warning" v-if="scope.row.inventory<scope.row.threshold" style="color: red"></i>
|
||||
<span>{{ scope.row.name }}</span>
|
||||
</router-link>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="型号" align="center" prop="model" />
|
||||
<el-table-column label="单价" align="center" prop="price" />
|
||||
<el-table-column label="库存数量" align="center" prop="inventory">
|
||||
<template slot-scope="scope">
|
||||
<span>{{scope.row.inventory}}
|
||||
<span v-if="scope.row.taskInventory!==null">
|
||||
({{scope.row.taskInventory}})
|
||||
</span>
|
||||
|
||||
</span>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="单位" align="center" prop="unit" />
|
||||
<el-table-column label="品牌" align="center" prop="brand" />
|
||||
<el-table-column label="规格" align="center" prop="specifications" />
|
||||
<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-edit"
|
||||
@click="handleUpdate(scope.row)"
|
||||
v-hasPermi="['oa:oaWarehouse:edit']"
|
||||
>修改</el-button>
|
||||
<el-button
|
||||
size="mini"
|
||||
type="text"
|
||||
icon="el-icon-delete"
|
||||
@click="handleDelete(scope.row)"
|
||||
v-hasPermi="['oa:oaWarehouse:remove']"
|
||||
>删除</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="title" :visible.sync="open" width="500px" append-to-body>
|
||||
<el-form ref="form" :model="form" :rules="rules" label-width="80px">
|
||||
|
||||
<el-form-item label="物料名称" prop="name">
|
||||
<el-input v-model="form.name" placeholder="请输入物料名称" />
|
||||
</el-form-item>
|
||||
|
||||
<el-form-item label="告警阈值" prop="threshold">
|
||||
<el-input v-model="form.threshold" type="number" placeholder="请输入告警阈值" />
|
||||
</el-form-item>
|
||||
<el-form-item label="型号" prop="model">
|
||||
<el-input v-model="form.model" placeholder="请输入型号" />
|
||||
</el-form-item>
|
||||
|
||||
<el-form-item label="单价" prop="price">
|
||||
<el-input v-model="form.price" placeholder="请输入单价" />
|
||||
</el-form-item>
|
||||
<el-form-item label="库存数量" prop="inventory">
|
||||
<el-input v-model="form.inventory" placeholder="请输入库存数量" />
|
||||
</el-form-item>
|
||||
<el-form-item label="单位" prop="unit">
|
||||
<el-input v-model="form.unit" placeholder="请输入单位" />
|
||||
</el-form-item>
|
||||
<el-form-item label="品牌" prop="brand">
|
||||
<el-input v-model="form.brand" placeholder="请输入品牌" />
|
||||
</el-form-item>
|
||||
<el-form-item label="规格" prop="specifications">
|
||||
<el-input v-model="form.specifications" placeholder="请输入规格" />
|
||||
</el-form-item>
|
||||
<el-form-item label="备注" prop="remark">
|
||||
<el-input v-model="form.remark" type="textarea" placeholder="请输入内容" />
|
||||
</el-form-item>
|
||||
</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-dialog :title="upload.title" :visible.sync="upload.open" width="400px" append-to-body>
|
||||
<el-upload
|
||||
ref="upload"
|
||||
:limit="1"
|
||||
accept=".xlsx, .xls"
|
||||
:headers="upload.headers"
|
||||
:action="upload.url + '?updateSupport=' + upload.updateSupport"
|
||||
:disabled="upload.isUploading"
|
||||
:on-progress="handleFileUploadProgress"
|
||||
:on-success="handleFileSuccess"
|
||||
:on-error="handleFileError"
|
||||
:auto-upload="false"
|
||||
drag
|
||||
>
|
||||
<i class="el-icon-upload"></i>
|
||||
<div class="el-upload__text">将文件拖到此处,或<em>点击上传</em></div>
|
||||
<div class="el-upload__tip text-center" slot="tip">
|
||||
|
||||
<span>仅允许导入xls、xlsx格式文件。</span>
|
||||
<el-link type="primary" :underline="false" style="font-size:12px;vertical-align: baseline;" @click="importTemplate">下载模板</el-link>
|
||||
</div>
|
||||
</el-upload>
|
||||
<div slot="footer" class="dialog-footer">
|
||||
<el-button type="primary" @click="submitFileForm">确 定</el-button>
|
||||
<el-button @click="upload.open = false">取 消</el-button>
|
||||
</div>
|
||||
</el-dialog>
|
||||
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { delOaWarehouse, getOaWarehouse, listOaWarehouse, updateOaWarehouse } from "@/api/oa/warehouse/oaWarehouse";
|
||||
import { addOaWarehouseMasterToIn } from "@/api/oa/warehouse/warehouseMaster";
|
||||
import { getToken } from "@/utils/auth";
|
||||
export default {
|
||||
name: "OaWarehouse",
|
||||
data() {
|
||||
return {
|
||||
// 用户导入参数
|
||||
upload: {
|
||||
// 是否显示弹出层(用户导入)
|
||||
open: false,
|
||||
// 弹出层标题(用户导入)
|
||||
title: "",
|
||||
// 是否禁用上传
|
||||
isUploading: false,
|
||||
// 是否更新已经存在的用户数据
|
||||
updateSupport: 0,
|
||||
// 设置上传的请求头部
|
||||
headers: { Authorization: "Bearer " + getToken() },
|
||||
// 上传的地址
|
||||
url: process.env.VUE_APP_BASE_API + "/oa/oaWarehouse/importData"
|
||||
},
|
||||
// 按钮loading
|
||||
buttonLoading: false,
|
||||
// 遮罩层
|
||||
loading: true,
|
||||
// 选中数组
|
||||
ids: [],
|
||||
// 非单个禁用
|
||||
single: true,
|
||||
// 非多个禁用
|
||||
multiple: true,
|
||||
// 显示搜索条件
|
||||
showSearch: true,
|
||||
// 总条数
|
||||
total: 0,
|
||||
// 库存管理表格数据
|
||||
oaWarehouseList: [],
|
||||
// 弹出层标题
|
||||
title: "",
|
||||
// 是否显示弹出层
|
||||
open: false,
|
||||
loadingInstance: null, // 全屏 Loading 句柄
|
||||
// 查询参数
|
||||
queryParams: {
|
||||
pageNum: 1,
|
||||
pageSize: 10,
|
||||
inventory: undefined,
|
||||
model: undefined,
|
||||
unit: undefined,
|
||||
name: undefined,
|
||||
brand: undefined,
|
||||
specifications: undefined,
|
||||
},
|
||||
// 表单参数
|
||||
form: {},
|
||||
// 表单校验
|
||||
rules: {
|
||||
inventory: [
|
||||
{ required: true, message: "库存数量不能为空", trigger: "blur" }
|
||||
],
|
||||
name: [
|
||||
{ required: true, message: "物料名称不能为空", trigger: "blur" }
|
||||
],
|
||||
}
|
||||
};
|
||||
},
|
||||
created() {
|
||||
this.getList();
|
||||
},
|
||||
methods: {
|
||||
tableRowClassName({row, rowIndex}){
|
||||
if (row.inventory+row.taskInventory<row.threshold) {
|
||||
return 'warning-row';
|
||||
}
|
||||
return '';
|
||||
},
|
||||
/** 查询库存管理列表 */
|
||||
getList() {
|
||||
this.loading = true;
|
||||
listOaWarehouse(this.queryParams).then(response => {
|
||||
this.oaWarehouseList = response.rows;
|
||||
this.total = response.total;
|
||||
this.loading = false;
|
||||
});
|
||||
},
|
||||
// 取消按钮
|
||||
cancel() {
|
||||
this.open = false;
|
||||
this.reset();
|
||||
},
|
||||
// 表单重置
|
||||
reset() {
|
||||
this.form = {
|
||||
id: undefined,
|
||||
inventory: undefined,
|
||||
model: undefined,
|
||||
unit: undefined,
|
||||
name: undefined,
|
||||
brand: undefined,
|
||||
specifications: undefined,
|
||||
remark: undefined,
|
||||
createTime: undefined,
|
||||
createBy: undefined,
|
||||
updateTime: undefined,
|
||||
updateBy: undefined,
|
||||
delFlag: undefined
|
||||
};
|
||||
this.resetForm("form");
|
||||
},
|
||||
/** 搜索按钮操作 */
|
||||
handleQuery() {
|
||||
this.queryParams.pageNum = 1;
|
||||
this.getList();
|
||||
},
|
||||
/** 重置按钮操作 */
|
||||
resetQuery() {
|
||||
this.resetForm("queryForm");
|
||||
this.handleQuery();
|
||||
},
|
||||
// 多选框选中数据
|
||||
handleSelectionChange(selection) {
|
||||
this.ids = selection.map(item => item.id)
|
||||
this.single = selection.length!==1
|
||||
this.multiple = !selection.length
|
||||
},
|
||||
/** 新增按钮操作 */
|
||||
handleAdd() {
|
||||
this.reset();
|
||||
this.open = true;
|
||||
this.title = "添加库存管理";
|
||||
},
|
||||
/** 修改按钮操作 */
|
||||
handleUpdate(row) {
|
||||
this.loading = true;
|
||||
this.reset();
|
||||
const id = row.id || this.ids
|
||||
getOaWarehouse(id).then(response => {
|
||||
this.loading = false;
|
||||
this.form = response.data;
|
||||
this.open = true;
|
||||
this.title = "修改库存管理";
|
||||
});
|
||||
},
|
||||
/** 提交按钮 */
|
||||
submitForm() {
|
||||
this.$refs["form"].validate(valid => {
|
||||
if (valid) {
|
||||
this.buttonLoading = true;
|
||||
if (this.form.id != null) {
|
||||
updateOaWarehouse(this.form).then(response => {
|
||||
this.$modal.msgSuccess("修改成功");
|
||||
this.open = false;
|
||||
this.getList();
|
||||
}).finally(() => {
|
||||
this.buttonLoading = false;
|
||||
});
|
||||
} else {
|
||||
addOaWarehouseMasterToIn(this.form).then(response => {
|
||||
this.$modal.msgSuccess("新增成功");
|
||||
this.open = false;
|
||||
this.getList();
|
||||
}).finally(() => {
|
||||
this.buttonLoading = false;
|
||||
});
|
||||
}
|
||||
}
|
||||
});
|
||||
},
|
||||
/** 删除按钮操作 */
|
||||
handleDelete(row) {
|
||||
const ids = row.id || this.ids;
|
||||
this.$modal.confirm('是否确认删除库存管理编号为"' + ids + '"的数据项?').then(() => {
|
||||
this.loading = true;
|
||||
return delOaWarehouse(ids);
|
||||
}).then(() => {
|
||||
this.loading = false;
|
||||
this.getList();
|
||||
this.$modal.msgSuccess("删除成功");
|
||||
}).catch(() => {
|
||||
}).finally(() => {
|
||||
this.loading = false;
|
||||
});
|
||||
},
|
||||
/** 导出按钮操作 */
|
||||
handleExport() {
|
||||
this.download('oa/oaWarehouse/export', {
|
||||
...this.queryParams
|
||||
}, `oaWarehouse_${new Date().getTime()}.xlsx`)
|
||||
},
|
||||
|
||||
/** 导入按钮操作 */
|
||||
handleImport() {
|
||||
this.upload.title = "用户导入";
|
||||
this.upload.open = true;
|
||||
},
|
||||
/** 下载模板操作 */
|
||||
importTemplate() {
|
||||
this.download('oa/oaWarehouse/importTemplate', {
|
||||
}, `ware_template_${new Date().getTime()}.xlsx`)
|
||||
},
|
||||
// 文件上传中处理
|
||||
handleFileUploadProgress(event, file, fileList) {
|
||||
this.upload.isUploading = true;
|
||||
},
|
||||
// 文件上传成功处理
|
||||
handleFileSuccess(response, file, fileList) {
|
||||
if (this.loadingInstance) {
|
||||
this.loadingInstance.close();
|
||||
this.loadingInstance = null;
|
||||
}
|
||||
this.upload.open = false;
|
||||
this.upload.isUploading = false;
|
||||
this.$refs.upload.clearFiles();
|
||||
this.$alert("<div style='overflow: auto;overflow-x: hidden;max-height: 70vh;padding: 10px 20px 0;'>" + response.msg + "</div>", "导入结果", { dangerouslyUseHTMLString: true });
|
||||
this.getList();
|
||||
},
|
||||
|
||||
handleFileError(err) {
|
||||
if (this.loadingInstance) {
|
||||
this.loadingInstance.close();
|
||||
this.loadingInstance = null;
|
||||
}
|
||||
this.upload.isUploading = false;
|
||||
this.loading = false;
|
||||
this.$message.error('导入失败,请重试');
|
||||
},
|
||||
|
||||
// 提交上传文件
|
||||
submitFileForm() {
|
||||
/* 1. 打开全屏加载遮罩 */
|
||||
this.loadingInstance = this.$loading({
|
||||
lock: true,
|
||||
fullscreen: true, // 覆盖整页
|
||||
text: '正在导入中,请稍候…',
|
||||
spinner: 'el-icon-loading',
|
||||
background: 'rgba(0, 0, 0, 0.4)'
|
||||
});
|
||||
this.$refs.upload.submit();
|
||||
},
|
||||
|
||||
/** 路由 添加采购计划 */
|
||||
addWarehouseTask(){
|
||||
this.$router.push("/oa/warehouse-data/addTask");
|
||||
}
|
||||
}
|
||||
};
|
||||
</script>
|
||||
<style>
|
||||
.el-table .warning-row {
|
||||
background: oldlace;
|
||||
}
|
||||
|
||||
.el-table .success-row {
|
||||
background: #f0f9eb;
|
||||
}
|
||||
</style>
|
||||
641
ruoyi-ui/src/views/oa/oaWarehouse/task.vue
Normal file
641
ruoyi-ui/src/views/oa/oaWarehouse/task.vue
Normal file
@@ -0,0 +1,641 @@
|
||||
<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>
|
||||
<right-toolbar :showSearch.sync="showSearch" @queryTable="getList"></right-toolbar>
|
||||
</el-row>
|
||||
|
||||
<el-table v-loading="loading" :data="TaskList" @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="masterNum">
|
||||
<template slot-scope="scope">
|
||||
<el-input v-model="scope.row.masterNum" size="mini" placeholder="请输入采购单编号"
|
||||
@blur="updateMasterRemark(scope.row)" />
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="状态" align="center" prop="status">
|
||||
<template slot-scope="scope">
|
||||
<el-tag :type="scope.row.status === 1 ? 'success' : 'warning'">{{
|
||||
scope.row.status === 1 ? "完成" : "未完成"
|
||||
}}
|
||||
</el-tag>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="最近截止日期" align="center" prop="nearestEndTime">
|
||||
<template slot-scope="scope" v-if="scope.row.nearestEndTime != null && scope.row.status !== 1">
|
||||
<template v-if="dayDiff(scope.row.nearestEndTime) > 3">
|
||||
<!-- 超过 3 天,正常显示 -->
|
||||
<span>{{ parseTime(scope.row.nearestEndTime, '{y}-{m}-{d}') }}</span>
|
||||
|
||||
</template><template v-else-if="dayDiff(scope.row.nearestEndTime) > 0">
|
||||
<!-- 未来 1–3 天 -->
|
||||
<el-tag type="warning" effect="plain">
|
||||
剩余{{ dayDiff(scope.row.nearestEndTime) }}天
|
||||
</el-tag>
|
||||
|
||||
</template><template v-else-if="dayDiff(scope.row.nearestEndTime) === 0">
|
||||
<!-- 今天到期 -->
|
||||
<el-tag type="danger" effect="plain">
|
||||
<i class="el-icon-warning-outline"></i> 今日过期!
|
||||
</el-tag>
|
||||
|
||||
</template><template v-else>
|
||||
<!-- 已过期 -->
|
||||
<el-tag type="danger" effect="plain">
|
||||
逾期{{ Math.abs(dayDiff(scope.row.endTime)) }}天
|
||||
</el-tag>
|
||||
</template>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="操作时间" align="center" prop="signTime">
|
||||
<template slot-scope="scope">
|
||||
<span>{{ parseTime(scope.row.signTime, "{y}-{m}-{d}") }}</span>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="操作人" align="center" prop="signUser" />
|
||||
<el-table-column label="备注" align="center" prop="remark">
|
||||
<template slot-scope="scope">
|
||||
<el-input v-model="scope.row.remark" size="mini" type="textarea" placeholder="请输入备注"
|
||||
@blur="updateMasterRemark(scope.row)" />
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="需求编号" align="center" prop="requirementNum">
|
||||
<template slot-scope="scope">
|
||||
<el-select v-model="scope.row.requirementId" placeholder="请选择需求编号" filterable clearable
|
||||
@change="updateMasterRemark(scope.row)">
|
||||
<el-option v-for="item in requirementList" :key="item.requirementId" :label="item.title"
|
||||
:value="item.requirementId" />
|
||||
</el-select>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<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-search" @click="showDetail(scope.row)">查看
|
||||
</el-button>
|
||||
|
||||
<el-button size="mini" type="text" icon="el-icon-finished" v-if="scope.row.status === 0"
|
||||
@click="handleIn(scope.row)">执行入库
|
||||
</el-button>
|
||||
|
||||
<el-button size="mini" type="text" icon="el-icon-check" v-if="scope.row.status === 0"
|
||||
@click="handComplete(scope.row)">完成
|
||||
</el-button>
|
||||
|
||||
<el-button size="mini" type="text" icon="el-icon-download" @click="handleExport(scope.row)">导出
|
||||
</el-button>
|
||||
|
||||
<el-button size="mini" type="text" icon="el-icon-remove" @click="handleDelete(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-drawer size="70%" :title="parseTime(searchItem.signTime) + '-采购单'" :visible.sync="drawer">
|
||||
<el-table v-loading="loading" :data="warehouseTaskList">
|
||||
<el-table-column type="selection" width="55" align="center" />
|
||||
<el-table-column label="序号" align="center" type="index" />
|
||||
<el-table-column label="物料名" align="center" prop="name" />
|
||||
<el-table-column label="采购数量" align="center" prop="taskInventory" />
|
||||
<el-table-column label="单位" align="center" prop="unit" />
|
||||
<el-table-column label="品牌" align="center" prop="brand" />
|
||||
<el-table-column label="型号" align="center" prop="model" />
|
||||
<el-table-column label="规格" align="center" prop="specifications" />
|
||||
<el-table-column label="操作" align="center" prop="remark">
|
||||
<template slot-scope="scope">
|
||||
<el-button type="text" icon="el-icon-edit" @click="handleRemoveTask(scope.row)">删除</el-button>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
</el-drawer>
|
||||
|
||||
<el-drawer size="70%" :title="parseTime(searchItem.signTime, '{y}_{m}_{d}') + '_采购单'"
|
||||
:visible.sync="completeDrawer">
|
||||
<!-- 工具栏 -->
|
||||
<div style="display:flex;justify-content:space-between;margin-bottom:10px">
|
||||
<!-- 模式切换 -->
|
||||
<el-radio-group v-model="mode" size="mini">
|
||||
<el-radio-button label="single">单个入库</el-radio-button>
|
||||
<el-radio-button label="batch">批量操作</el-radio-button>
|
||||
</el-radio-group>
|
||||
</div>
|
||||
|
||||
<el-table v-loading="loading" :data="warehouseTaskList" ref="warehouseTable">
|
||||
<el-table-column type="selection" width="55" align="center" />
|
||||
<el-table-column label="序号" align="center" type="index" />
|
||||
<el-table-column label="物料名" align="center" prop="name" />
|
||||
<el-table-column label="截止日期" align="center" prop="endTime">
|
||||
<template slot-scope="scope" v-if="scope.row.endTime != null">
|
||||
<template v-if="dayDiff(scope.row.endTime) > 3">
|
||||
<!-- 超过 3 天,正常显示 -->
|
||||
<span>{{ parseTime(scope.row.endTime, '{y}-{m}-{d}') }}</span>
|
||||
|
||||
</template><template v-else-if="dayDiff(scope.row.endTime) > 0">
|
||||
<!-- 未来 1–3 天 -->
|
||||
<el-tag type="warning" effect="plain">
|
||||
剩余{{ dayDiff(scope.row.endTime) }}天
|
||||
</el-tag>
|
||||
|
||||
</template><template v-else-if="dayDiff(scope.row.endTime) === 0">
|
||||
<!-- 今天到期 -->
|
||||
<el-tag type="danger" effect="plain">
|
||||
<i class="el-icon-warning-outline"></i> 今日过期!
|
||||
</el-tag>
|
||||
|
||||
</template><template v-else>
|
||||
<!-- 已过期 -->
|
||||
<el-tag type="danger" effect="plain">
|
||||
逾期{{ Math.abs(dayDiff(scope.row.endTime)) }}天
|
||||
</el-tag>
|
||||
</template>
|
||||
</template>
|
||||
</el-table-column>
|
||||
|
||||
<el-table-column label="采购数量" align="center" prop="taskInventory" />
|
||||
<el-table-column label="采购价格" align="center" prop="price">
|
||||
<template slot-scope="scope">
|
||||
<el-input v-model="scope.row.price" v-if="scope.row.taskStatus !== 2" type="number"></el-input>
|
||||
<span v-else>
|
||||
已经操作入库,录入价格请前往入库明细查看
|
||||
</span>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="品牌" align="center" prop="brand" />
|
||||
<el-table-column label="规格" align="center" prop="specifications" />
|
||||
<el-table-column label="备注" align="center" prop="remark">
|
||||
<template slot-scope="scope">
|
||||
<el-input v-model="scope.row.remark" size="mini" placeholder="请输入备注" :disabled="scope.row.taskStatus === 2"
|
||||
@blur="updateRemark(scope.row)" />
|
||||
</template>
|
||||
</el-table-column>
|
||||
<!-- ⇩⇩⇩ ③ 操作列(单行按钮) ⇩⇩⇩ -->
|
||||
<!-- ★ 新增状态列 ★ -->
|
||||
<el-table-column label="状态" prop="taskStatus" width="140" align="center">
|
||||
<template slot-scope="scope">
|
||||
<!-- 单个模式:可编辑 -->
|
||||
<el-tag type="success" v-if="scope.row.taskStatus === 2">完成</el-tag>
|
||||
<!-- 单个模式下可编辑,动态过滤选项 -->
|
||||
<el-select v-else-if="mode === 'single'" v-model="scope.row.taskStatus" size="mini" placeholder="状态"
|
||||
@change="handleUpdateTask(scope.row)">
|
||||
<el-option v-for="s in filteredStatusOptions(scope.row)" :key="s.value" :value="s.value"
|
||||
:label="s.label" />
|
||||
</el-select>
|
||||
|
||||
<!-- 批量模式:只显示 -->
|
||||
<span v-else>{{ statusLabel(scope.row.taskStatus) }}</span>
|
||||
</template>
|
||||
</el-table-column>
|
||||
|
||||
<el-table-column label="操作" align="center">
|
||||
<template slot-scope="scope">
|
||||
|
||||
<el-button size="mini" type="danger" v-if="scope.row.taskStatus !== 2"
|
||||
@click="handleBatchDelete(scope.row)">删除</el-button>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
<div style="display: flex; justify-content: flex-end; margin: 20px">
|
||||
<!-- 批量模式下才显示 -->
|
||||
<div v-if="mode === 'batch'">
|
||||
<el-select v-model="batchStatus" size="mini" placeholder="选择批量状态">
|
||||
<el-option v-for="s in statusOptions" :key="s.value" :value="s.value" :label="s.label" />
|
||||
</el-select>
|
||||
</div>
|
||||
<el-button @click="submitComplete" v-if="mode === 'batch'" size="mini" type="success">执行入库</el-button>
|
||||
<el-button @click="completeDrawer = false" size="mini">关闭</el-button>
|
||||
|
||||
</div>
|
||||
</el-drawer>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { listRequirements } from "@/api/oa/requirement";
|
||||
import {
|
||||
addOaWarehouseMaster,
|
||||
delOaWarehouseMaster, listOaWarehouseMaster,
|
||||
updateOaWarehouseMaster,
|
||||
} from "@/api/oa/warehouse/warehouseMaster";
|
||||
import {
|
||||
delOaWarehouseTask,
|
||||
getOaWarehouseTaskByMasterId,
|
||||
updateOaWarehouseTask,
|
||||
updateOaWarehouseTaskBatch,
|
||||
updateOaWarehouseTaskStatus,
|
||||
updateTaskRemark
|
||||
} from "@/api/oa/warehouse/warehouseTask";
|
||||
|
||||
|
||||
export default {
|
||||
name: "OaOutWarehouse",
|
||||
data () {
|
||||
return {
|
||||
completeDrawer: false,
|
||||
mode: 'single',
|
||||
batchStatus: null, // 批量入库时选择的状态
|
||||
searchTime: [], // 搜索时间范围
|
||||
// 细节数据
|
||||
detailData: {},
|
||||
// 抽屉
|
||||
drawer: false,
|
||||
// 选中项目名称
|
||||
selectedProject: "",
|
||||
// 查看详情弹窗
|
||||
outDetail: {},
|
||||
// 弹窗标志
|
||||
detail: false,
|
||||
// 绑定项目详情
|
||||
projectDetail: {},
|
||||
// 物料信息详情
|
||||
warehouseDetail: {},
|
||||
// 入库列表
|
||||
TaskList: [],
|
||||
// 按钮loading
|
||||
buttonLoading: false,
|
||||
// 遮罩层
|
||||
loading: true,
|
||||
// 选中数组
|
||||
ids: [],
|
||||
// 非单个禁用
|
||||
single: true,
|
||||
selectedRows: [],
|
||||
// 非多个禁用
|
||||
multiple: true,
|
||||
// 显示搜索条件
|
||||
showSearch: true,
|
||||
// 总条数
|
||||
total: 0,
|
||||
// 弹出层标题
|
||||
title: "",
|
||||
// 选择对象
|
||||
searchItem: {},
|
||||
// 是否显示弹出层
|
||||
open: false,
|
||||
warehouseTaskList: [],
|
||||
// 查询参数
|
||||
queryParams: {
|
||||
pageNum: 1,
|
||||
pageSize: 50,
|
||||
type: 2,
|
||||
},
|
||||
// 导出参数
|
||||
exportParams: {
|
||||
pageNum: 1,
|
||||
pageSize: 10,
|
||||
},
|
||||
statusOptions: [
|
||||
{ value: 0, label: '未采购' },
|
||||
{ value: 1, label: '在途' },
|
||||
{ value: 2, label: '完成' },
|
||||
{ value: 3, label: '作废' }
|
||||
],
|
||||
// 表单参数
|
||||
form: {},
|
||||
currentMasterId: null,
|
||||
requirementList: [],
|
||||
};
|
||||
},
|
||||
created () {
|
||||
this.getList();
|
||||
this.getRequirementList();
|
||||
},
|
||||
methods: {
|
||||
// 获取需求列表
|
||||
getRequirementList () {
|
||||
listRequirements({
|
||||
pageNum: 1,
|
||||
pageSize: 1000,
|
||||
}).then((res) => {
|
||||
this.requirementList = res.rows;
|
||||
});
|
||||
},
|
||||
// 返回 endTime 与今天(不含时分秒)的差值(单位:天)
|
||||
dayDiff (endTime) {
|
||||
const end = new Date(endTime)
|
||||
const now = new Date()
|
||||
end.setHours(0, 0, 0, 0)
|
||||
now.setHours(0, 0, 0, 0)
|
||||
// 正数 = future days; 0 = today; 负数 = past days
|
||||
return Math.floor((end - now) / (1000 * 60 * 60 * 24))
|
||||
},
|
||||
// 根据 price 动态过滤:如果行 price 为空,就干掉 value===2
|
||||
filteredStatusOptions (row) {
|
||||
if (row.price == null || row.price === '') {
|
||||
return this.statusOptions.filter(opt => opt.value !== 2);
|
||||
}
|
||||
return this.statusOptions;
|
||||
},
|
||||
|
||||
|
||||
/** 单个入库接口 */
|
||||
handleUpdateTask (row) {
|
||||
this.loading = true;
|
||||
// 这里如果用户选了“完成”但 price 还是空,你也可以额外做下兜底校验
|
||||
if (row.taskStatus === 2 && (row.price == null || row.price === '')) {
|
||||
this.$message.error('请先填写价格,才能标记为完成');
|
||||
row.taskStatus = 0; // 或者恢复到之前的状态
|
||||
return;
|
||||
}
|
||||
updateOaWarehouseTaskStatus(row).then(response => {
|
||||
getOaWarehouseTaskByMasterId(row.masterId).then((res) => {
|
||||
this.currentMasterId = row.masterId;
|
||||
this.warehouseTaskList = res.data;
|
||||
this.loading = false;
|
||||
this.$modal.msgSuccess("操作成功")
|
||||
this.getList();
|
||||
});
|
||||
})
|
||||
},
|
||||
/** 状态值 → 文字 */
|
||||
statusLabel (val) {
|
||||
const item = this.statusOptions.find(s => s.value === val)
|
||||
return item ? item.label : ''
|
||||
},
|
||||
|
||||
|
||||
handleRemoveTask (row) {
|
||||
this.$confirm('确定删除该物料吗?', '提示', {
|
||||
confirmButtonText: '确定',
|
||||
cancelButtonText: '取消',
|
||||
type: 'warning'
|
||||
}).then(() => {
|
||||
this.loading = true;
|
||||
delOaWarehouseTask(row.taskId).then((res) => {
|
||||
getOaWarehouseTaskByMasterId(this.currentMasterId).then((res) => {
|
||||
this.warehouseTaskList = res.data;
|
||||
this.$message.success('删除成功')
|
||||
})
|
||||
})
|
||||
.finally(() => {
|
||||
this.loading = false;
|
||||
})
|
||||
})
|
||||
},
|
||||
|
||||
/** 批量删除 */
|
||||
handleBatchDelete (row) {
|
||||
let rows = this.$refs.warehouseTable.selection
|
||||
|
||||
if (!rows.length) {
|
||||
rows = [row]
|
||||
}
|
||||
if (!rows.length) return this.$message.warning('请先勾选物料')
|
||||
|
||||
const taskIds = rows.map(row => row.taskId)
|
||||
this.$confirm(`确认删除 ${rows.length} 条记录?`, '提示',
|
||||
{
|
||||
confirmButtonText: '确定',
|
||||
cancelButtonText: '取消',
|
||||
type: 'warning'
|
||||
}
|
||||
).then(() => {
|
||||
delOaWarehouseTask(taskIds).then((res) => {
|
||||
this.getList();
|
||||
this.drawer = false;
|
||||
this.$message.success('删除成功')
|
||||
})
|
||||
|
||||
})
|
||||
},
|
||||
|
||||
/** 单行删除 */
|
||||
handleDeleteTask (index) {
|
||||
this.warehouseTaskList.splice(index, 1)
|
||||
this.$message.success('删除成功')
|
||||
},
|
||||
submitComplete () {
|
||||
const rows = this.$refs.warehouseTable.selection || []
|
||||
if (!rows.length) {
|
||||
return this.$message.warning('请先勾选物料')
|
||||
}
|
||||
if (this.batchStatus === null) {
|
||||
return this.$message.warning('请选择批量状态')
|
||||
}
|
||||
|
||||
// 前端直接设值(实际项目可调用接口)
|
||||
rows.forEach(r => { r.taskStatus = this.batchStatus })
|
||||
|
||||
// 批量入库采购单
|
||||
updateOaWarehouseTaskBatch(rows).then(res => {
|
||||
this.getList();
|
||||
this.drawer = false;
|
||||
this.$message.success(`已批量入库 ${rows.length} 条`)
|
||||
|
||||
})
|
||||
|
||||
},
|
||||
/** 执行入库操作 */
|
||||
handleIn (row) {
|
||||
// 更新采购单情况
|
||||
this.completeDrawer = true;
|
||||
this.searchItem = row;
|
||||
this.form = row;
|
||||
this.loading = true;
|
||||
this.currentMasterId = row.masterId;
|
||||
getOaWarehouseTaskByMasterId(row.masterId).then((res) => {
|
||||
this.currentMasterId = row.masterId;
|
||||
this.warehouseTaskList = res.data;
|
||||
this.loading = false;
|
||||
});
|
||||
},
|
||||
/** 执行完成操作, 这里只是把状态改为1 */
|
||||
handComplete (row) {
|
||||
this.form = row;
|
||||
this.form.status = 1;
|
||||
updateOaWarehouseMaster(this.form).then((res) => {
|
||||
this.$modal.msgSuccess("操作成功");
|
||||
this.getList();
|
||||
});
|
||||
},
|
||||
|
||||
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 {
|
||||
this.queryParams.startTime = '';
|
||||
this.queryParams.endTime = '';
|
||||
}
|
||||
listOaWarehouseMaster(this.queryParams).then((res) => {
|
||||
this.TaskList = res.rows;
|
||||
this.total = res.total;
|
||||
this.loading = false;
|
||||
});
|
||||
},
|
||||
// 取消按钮
|
||||
cancel () {
|
||||
this.open = false;
|
||||
this.reset();
|
||||
},
|
||||
// 表单重置
|
||||
reset () {
|
||||
this.form = {
|
||||
projectId: undefined,
|
||||
warehouseList: [],
|
||||
remark: ''
|
||||
};
|
||||
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;
|
||||
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 = "添加仓库入库";
|
||||
this.form.remark = '';
|
||||
},
|
||||
/** 修改按钮操作 */
|
||||
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 (row) {
|
||||
this.exportParams.masterId = row.masterId;
|
||||
this.download(
|
||||
"oa/oaWarehouseTask/export",
|
||||
{
|
||||
...this.exportParams,
|
||||
},
|
||||
`采购单_${new Date().getTime()}.xlsx`
|
||||
);
|
||||
},
|
||||
|
||||
// 查看入库单独条目详情
|
||||
showDetail (row) {
|
||||
this.drawer = true;
|
||||
this.searchItem = row;
|
||||
this.loading = true;
|
||||
getOaWarehouseTaskByMasterId(row.masterId).then((res) => {
|
||||
this.currentMasterId = row.masterId;
|
||||
this.warehouseTaskList = res.data;
|
||||
this.loading = false;
|
||||
});
|
||||
},
|
||||
// 修改采购单详情的备注
|
||||
updateRemark (row) {
|
||||
// 只提交remark字段,避免无关字段被覆盖
|
||||
updateOaWarehouseTask({
|
||||
taskId: row.taskId,
|
||||
remark: row.remark
|
||||
}).then(() => {
|
||||
this.$message.success('备注已保存');
|
||||
});
|
||||
},
|
||||
// 修改采购单据的备注
|
||||
updateMasterRemark (row) {
|
||||
updateTaskRemark({
|
||||
masterId: row.masterId,
|
||||
remark: row.remark,
|
||||
masterNum: row.masterNum,
|
||||
requirementId: row.requirementId ? row.requirementId : 0,
|
||||
}).then(() => {
|
||||
this.$message.success('已保存');
|
||||
});
|
||||
},
|
||||
},
|
||||
};
|
||||
</script>
|
||||
Reference in New Issue
Block a user