智慧农业后台管理页面
tangzy
2022-05-30 cd70224e0a8d45c76bfc93ae18ac04765a92c3c1
农资管理
6 files modified
5 files added
1655 ■■■■■ changed files
public/img/stock/exit.png patch | view | raw | blame | history
src/api/soldr/soldr.js 62 ●●●●● patch | view | raw | blame | history
src/api/soldrecord/soldrecord.js 12 ●●●●● patch | view | raw | blame | history
src/router/views/index.js 16 ●●●●● patch | view | raw | blame | history
src/views/land/cs.vue 130 ●●●●● patch | view | raw | blame | history
src/views/land/landAdd.vue 155 ●●●●● patch | view | raw | blame | history
src/views/soldr/soldr.vue 263 ●●●●● patch | view | raw | blame | history
src/views/soldrecord/soldrecord.vue 17 ●●●●● patch | view | raw | blame | history
src/views/stock/stockmanage.vue 315 ●●●● patch | view | raw | blame | history
src/views/stock/stockout.vue 680 ●●●●● patch | view | raw | blame | history
src/views/stockrecord/stockrecord.vue 5 ●●●●● patch | view | raw | blame | history
public/img/stock/exit.png
src/api/soldr/soldr.js
New file
@@ -0,0 +1,62 @@
import request from '@/router/axios';
export const getList = (current, size, params) => {
  return request({
    url: '/api/soldr/soldr/page',
    method: 'get',
    params: {
      ...params,
      current,
      size,
    }
  })
}
export const getDetail = (id) => {
  return request({
    url: '/api/soldr/soldr/detail',
    method: 'get',
    params: {
      id
    }
  })
}
export const remove = (ids) => {
  return request({
    url: '/api/soldr/soldr/remove',
    method: 'post',
    params: {
      ids,
    }
  })
}
export const add = (row) => {
  return request({
    url: '/api/soldr/soldr/submit',
    method: 'post',
    data: row
  })
}
export const update = (row) => {
  return request({
    url: '/api/soldr/soldr/submit',
    method: 'post',
    data: row
  })
}
export const Updateout = (num,id,type) => {
  return request({
    url: '/api/soldr/soldr/out',
    method: 'post',
    params: {
      num,
      id,
      type
    }
  })
}
src/api/soldrecord/soldrecord.js
@@ -12,6 +12,18 @@
  })
}
export const getListbg = (current, size, params) => {
  return request({
    url: '/api/soldrecord/soldrecord/pagebg',
    method: 'get',
    params: {
      ...params,
      current,
      size,
    }
  })
}
export const getDetail = (id) => {
  return request({
    url: '/api/soldrecord/soldrecord/detail',
src/router/views/index.js
@@ -121,6 +121,20 @@
    }]
  },
  {
    path: '/stockout',
    redirect: '/stock/stockout',
    component: Layout,
    children: [{
      path: '/stockout',
      name: '已出资待使用农资',
      meta: {
        i18n: 'index',
      },
      component: () =>
        import ( /* webpackChunkName: "views" */ '@/views/stock/stockout')
    }]
  },
  {
    path: '/landMap',
    redirect: '/land/landMap',
    component: Layout,
@@ -186,7 +200,7 @@
        i18n: 'land'
      },
      component: () =>
        import ( /* webpackChunkName: "views" */ '@/views/land/land')
        import ( /* webpackChunkName: "views" */ '@/views/land/cs')
    }]
  },
  {
src/views/land/cs.vue
@@ -1,5 +1,52 @@
<template>
  <div class="wraaper-box">
    <div class="search">
      <div style="float: left">
        <div style="float: left">
          <el-select
            v-model="formInline.stype"
            placeholder="全部分类"
            size="small"
            @change="stypeChange"
          >
            <el-option label="全部分类" value=""></el-option>
            <el-option label="大田" value="0"></el-option>
            <el-option label="大棚" value="1"></el-option>
            <el-option label="果园" value="2"></el-option>
            <el-option label="鱼塘" value="3"></el-option>
            <el-option label="山地" value="4"></el-option>
            <el-option label="养殖区" value="4"></el-option>
          </el-select>
        </div>
<!--        <div style="float: left; margin-left: 15px">-->
<!--          <el-select-->
<!--            v-model="formInline.state"-->
<!--            size="small"-->
<!--            placeholder="有库存"-->
<!--            @change="stateChange"-->
<!--          >-->
<!--            <el-option label="全部" value=""></el-option>-->
<!--            <el-option label="有库存" value="0"></el-option>-->
<!--            <el-option label="无库存" value="1"></el-option>-->
<!--          </el-select>-->
<!--        </div>-->
        <div style="float: left; margin-left: 15px">
          <el-input
            v-model="formInline.keyword"
            size="small"
            placeholder="请输入名称"
            @input="keywordChange"
            clearable
          ></el-input>
        </div>
      </div>
      <div>
        <el-button size="small"
        ><span style="color: #5abf78" @click="out(row)">进入地图模式</span></el-button
        >
        <el-button type="success" size="small" @click="land" style="margin-right: 50px;width: 80px;">圈地</el-button>
      </div>
    </div>
    <div class="landhome">
      <div class="land" v-for="(item, index) in farmPlanList" :key="index"  @click="landInfo(item)">
        <div class="land-img" >
@@ -14,21 +61,48 @@
        </div>
      </div>
    </div>
    <div class="el-page">
      <el-pagination
        @size-change="handleSizeChange"
        @current-change="handleCurrentChange"
        :current-page="page.currentPage"
        :hide-on-single-page="value"
        :page-size="page.pageSize"
        background
        layout="total, prev, pager, next"
        :total="page.total"
      >
      </el-pagination>
    </div>
    <landAdd v-if="landVisible" ref="land"></landAdd>
  </div>
</template>
<script>
import { mapGetters } from "vuex";
import {getList} from "@/api/land/land";
import landAdd from "./landAdd";
export default {
  components: {
    landAdd,
  },
  name: "wel",
  data() {
    return {
      formInline: {
        stype: "0",
        state: "0",
        keyword: "",
      },
      query: {},
      farmingCount:0,
      landVisible: false,
      farmPlanList: [],
      page: {
        pageSize: 4,
        currentPage: 1,
        total: 0,
      },
      option: {
        labelWidth: 80,
        span:6,
@@ -49,6 +123,38 @@
    this.onLoad();
  },
  methods: {
    //圈地
    land() {
      this.landVisible = true;
      this.$nextTick(() => {
        this.$refs.land.init();
      });
    },
    //农资类型select 改变事件
    stypeChange(value) {
      this.query["landType"] = value;
      this.onLoad(this.page, this.query);
    },
    //库存 select 改变事件
    stateChange(value) {
      this.query["state"] = value;
      this.onLoad(this.page, this.query);
    },
    //keywordChange 输入事件
    keywordChange(value) {
      this.query["landName"] = value;
      this.onLoad(this.page, this.query);
    },
    //分页
    handleSizeChange(val) {
      this.page.pageSize = val;
      this.onLoad(this.page);
    },
    //改变页码
    handleCurrentChange(val) {
      this.page.currentPage = val;
      this.onLoad(this.page);
    },
    landInfo(item){
      this.$router.push({
        path: `/LandDetail`,
@@ -68,6 +174,15 @@
<style lang="scss" scope>
.el-font-size {
  font-size: 14px;
}
.search {
  padding-top: 40px;
  width: 98%;
  margin: 0 auto;
  display: flex;
  flex-flow: row nowrap;
  justify-content: space-between;
}
.wraaper-box {
@@ -100,7 +215,6 @@
      height: 280px;
      margin: 0 auto;
      text-align: center;
      background: green;
      .landimg {
        width: 100%;
@@ -149,6 +263,18 @@
  }
  .search {
    padding-top: 40px;
    width: 98%;
    margin: 0 auto;
    display: flex;
    flex-flow: row nowrap;
    justify-content: space-between;
    margin-top: -25px;
  }
  .el-page {
    background-color: black;
    text-align: center;
  }
}
</style>
src/views/land/landAdd.vue
New file
@@ -0,0 +1,155 @@
<template>
  <el-dialog
    :title="title"
    :modal-append-to-body="false"
    :append-to-body="true"
    :close-on-click-modal="false"
    width="60%"
    :visible.sync="visible"
  >
    <avue-form ref="form" v-model="form" :option="option" @submit="submit">
      <!-- 地图插入 -->
      <template slot-scope="{ type, disabled }" slot="line">
        <getMapDataInThere
          ref="getMapData"
          id="getMapData"
          @setMapData="setMapData"
        ></getMapDataInThere>
      </template>
    </avue-form>
  </el-dialog>
</template>
<script>
import {mapGetters} from "vuex";
import { getLandList } from "@/api/land/land";
import { getStrainList } from "@/api/farmplant/strain";
import {add} from "@/api/land/land";
import getMapDataInThere from "./getMapDataInThere.vue";
export default {
  components: {
    getMapDataInThere
  },
  data() {
    return {
      title:"新增地块",
      form: {},
      option: {
        emptyBtn: false,
        submitText: "保存",
        gutter: 30,
        column: [
          {
            label: "地块名称",
            prop: "landName",
            rules: [{
              required: true,
              message: "请输入地块名称",
              trigger: "blur"
            }]
          },
          {
            label: "地块类型",
            type: "select",
            prop: "landType",
            dicUrl: "/api/blade-system/dict-biz/dictionary?code=land",
            props: {
              label: "dictValue",
              value: "dictKey"
            },
            dataType: "number",
            rules: [{
              required: true,
              message: "请选择地块类型",
              trigger: "blur"
            }]
          },
          {
            label: "面积单位",
            prop: "landUnit",
            type: "select",
            dicUrl: "/api/blade-system/dict-biz/dictionary?code=landunit",
            props: {
              label: "dictValue",
              value: "dictKey"
            },
            dataType: "number",
            span: 6,
          },
          {
            label: "地块展示",
            labelWidth: "0",
            prop: "line",
            className: "mapClass",
            span: 24,
            formslot: true,
          }
        ],
      },
      visible: false,
    };
  },
  computed: {
    ...mapGetters(["userInfo", "permission", "polygons"]),
  },
  methods: {
    //初始化
    init() {
      //计算当前时间
      this.visible = true;
    },
    // 表单提交
    submit(row,loading) {
      var that = this;
      if (this.polygons.length == 0) {
        //没有面的数据
        this.$refs.getMapData.isCheck = true;
        loading();
      } else {
        //如果有值,空间坐标转换
        let pol = this.polygons;
        let polLength = this.polygons.length - 1;
        let usePolygons = "";
        for (let k in pol) {
          usePolygons += pol[k].lng + "," + pol[k].lat;
          if (k != polLength) {
            usePolygons += ";";
          }
        }
        //设置坐标点
        row.userId = this.userInfo.user_id;
        row.landRange = usePolygons;
      }
      add(row).then(() => {
        that.$refs.form.resetFields();
        that.visible = false;
        this.$message({
          type: "success",
          message: "操作成功!"
        });
      }, error => {
        loading();
        window.console.log(error);
      });
    },
    setMapData(val) {
      this.LineData = val[0];
      this.PointData = val[1];
    },
  },
};
</script>
<style lang="scss" scoped>
.mapClass div label {
  display: none;
}
#getMapData {
  width: 90%;
  position: relative;
  height: 400px;
  top: 10px;
  left: 90px;
}
</style>
src/views/soldr/soldr.vue
New file
@@ -0,0 +1,263 @@
<template>
  <basic-container>
    <avue-crud :option="option"
               :table-loading="loading"
               :data="data"
               :page.sync="page"
               :permission="permissionList"
               :before-open="beforeOpen"
               v-model="form"
               ref="crud"
               @row-update="rowUpdate"
               @row-save="rowSave"
               @row-del="rowDel"
               @search-change="searchChange"
               @search-reset="searchReset"
               @selection-change="selectionChange"
               @current-change="currentChange"
               @size-change="sizeChange"
               @refresh-change="refreshChange"
               @on-load="onLoad">
      <template slot="menuLeft">
        <el-button type="danger"
                   size="small"
                   icon="el-icon-delete"
                   plain
                   v-if="permission.soldr_delete"
                   @click="handleDelete">删 除
        </el-button>
      </template>
    </avue-crud>
  </basic-container>
</template>
<script>
  import {getList, getDetail, add, update, remove} from "@/api/soldr/soldr";
  import {mapGetters} from "vuex";
  export default {
    data() {
      return {
        form: {},
        query: {},
        loading: true,
        page: {
          pageSize: 10,
          currentPage: 1,
          total: 0
        },
        selectionList: [],
        option: {
          height:'auto',
          calcHeight: 30,
          tip: false,
          searchShow: true,
          searchMenuSpan: 6,
          border: true,
          index: true,
          viewBtn: true,
          selection: true,
          dialogClickModal: false,
          column: [
            {
              label: "农资id",
              prop: "stockId1",
              rules: [{
                required: true,
                message: "请输入农资id",
                trigger: "blur"
              }]
            },
            {
              label: "数量",
              prop: "amount1",
              rules: [{
                required: true,
                message: "请输入数量",
                trigger: "blur"
              }]
            },
            {
              label: "",
              prop: "tenantId1",
              rules: [{
                required: true,
                message: "请输入",
                trigger: "blur"
              }]
            },
            {
              label: "规格",
              prop: "specs1",
              rules: [{
                required: true,
                message: "请输入规格",
                trigger: "blur"
              }]
            },
            {
              label: "规格值(0:克 1:斤 2:公斤 3:吨 4:毫升 5:升 )",
              prop: "specsVal1",
              rules: [{
                required: true,
                message: "请输入规格值(0:克 1:斤 2:公斤 3:吨 4:毫升 5:升 )",
                trigger: "blur"
              }]
            },
            {
              label: "规格值2( 0:袋 1:包 2:瓶 3:盒 4:箱 5:桶 6:支)",
              prop: "specsVal2",
              rules: [{
                required: true,
                message: "请输入规格值2( 0:袋 1:包 2:瓶 3:盒 4:箱 5:桶 6:支)",
                trigger: "blur"
              }]
            },
            {
              label: "出库类型",
              prop: "type",
              rules: [{
                required: true,
                message: "请输入出库类型",
                trigger: "blur"
              }]
            },
          ]
        },
        data: []
      };
    },
    computed: {
      ...mapGetters(["permission"]),
      permissionList() {
        return {
          addBtn: this.vaildData(this.permission.soldr_add, false),
          viewBtn: this.vaildData(this.permission.soldr_view, false),
          delBtn: this.vaildData(this.permission.soldr_delete, false),
          editBtn: this.vaildData(this.permission.soldr_edit, false)
        };
      },
      ids() {
        let ids = [];
        this.selectionList.forEach(ele => {
          ids.push(ele.id);
        });
        return ids.join(",");
      }
    },
    methods: {
      rowSave(row, done, loading) {
        add(row).then(() => {
          this.onLoad(this.page);
          this.$message({
            type: "success",
            message: "操作成功!"
          });
          done();
        }, error => {
          loading();
          window.console.log(error);
        });
      },
      rowUpdate(row, index, done, loading) {
        update(row).then(() => {
          this.onLoad(this.page);
          this.$message({
            type: "success",
            message: "操作成功!"
          });
          done();
        }, error => {
          loading();
          console.log(error);
        });
      },
      rowDel(row) {
        this.$confirm("确定将选择数据删除?", {
          confirmButtonText: "确定",
          cancelButtonText: "取消",
          type: "warning"
        })
          .then(() => {
            return remove(row.id);
          })
          .then(() => {
            this.onLoad(this.page);
            this.$message({
              type: "success",
              message: "操作成功!"
            });
          });
      },
      handleDelete() {
        if (this.selectionList.length === 0) {
          this.$message.warning("请选择至少一条数据");
          return;
        }
        this.$confirm("确定将选择数据删除?", {
          confirmButtonText: "确定",
          cancelButtonText: "取消",
          type: "warning"
        })
          .then(() => {
            return remove(this.ids);
          })
          .then(() => {
            this.onLoad(this.page);
            this.$message({
              type: "success",
              message: "操作成功!"
            });
            this.$refs.crud.toggleSelection();
          });
      },
      beforeOpen(done, type) {
        if (["edit", "view"].includes(type)) {
          getDetail(this.form.id).then(res => {
            this.form = res.data.data;
          });
        }
        done();
      },
      searchReset() {
        this.query = {};
        this.onLoad(this.page);
      },
      searchChange(params, done) {
        this.query = params;
        this.page.currentPage = 1;
        this.onLoad(this.page, params);
        done();
      },
      selectionChange(list) {
        this.selectionList = list;
      },
      selectionClear() {
        this.selectionList = [];
        this.$refs.crud.toggleSelection();
      },
      currentChange(currentPage){
        this.page.currentPage = currentPage;
      },
      sizeChange(pageSize){
        this.page.pageSize = pageSize;
      },
      refreshChange() {
        this.onLoad(this.page, this.query);
      },
      onLoad(page, params = {}) {
        this.loading = true;
        getList(page.currentPage, page.pageSize, Object.assign(params, this.query)).then(res => {
          const data = res.data.data;
          this.page.total = data.total;
          this.data = data.records;
          this.loading = false;
          this.selectionClear();
        });
      }
    }
  };
</script>
<style>
</style>
src/views/soldrecord/soldrecord.vue
@@ -32,7 +32,7 @@
</template>
<script>
  import {getList, getDetail, add, update, remove} from "@/api/soldrecord/soldrecord";
  import {getList, getDetail, add, update, remove,getListbg} from "@/api/soldrecord/soldrecord";
  import {mapGetters} from "vuex";
  export default {
@@ -80,9 +80,7 @@
            {
              label: "农资类型",
              prop: "stype",
              addDisplay: false,
              searchLabelWidth: 80,
              searchSpan: 4,
              type: "select",
              dicUrl: "/api/blade-system/dict-biz/dictionary?code=stockType",
              props: {
@@ -90,11 +88,15 @@
                value: "dictKey"
              },
              dataType: "number",
              search: true,
            },
            {
              label: "厂家名称",
              prop: "factoryName",
              addDisplay: false,
            },
            {
              label: "出库类型",
              prop: "dic3",
              addDisplay: false,
            },
            {
@@ -235,9 +237,10 @@
      },
      onLoad(page, params = {}) {
        this.loading = true;
        var datas = this.$route.query.stockId;
        params.stockId1=datas;
        getList(page.currentPage, page.pageSize, Object.assign(params, this.query)).then(res => {
        var datas = this.$route.query;
        console.log(datas)
        params.stockId1=datas.stockId1;
        getListbg(page.currentPage, page.pageSize, Object.assign(params, this.query)).then(res => {
          const data = res.data.data;
          this.page.total = data.total;
          this.data = data.records;
src/views/stock/stockmanage.vue
@@ -9,8 +9,12 @@
            size="small"
            @change="stypeChange"
          >
            <el-option label="全部分类" value="0"></el-option>
            <el-option label="" value="1"></el-option>
            <el-option label="全部分类" value=""></el-option>
            <el-option label="化肥" value="0"></el-option>
            <el-option label="有机肥" value="1"></el-option>
            <el-option label="杀虫剂" value="2"></el-option>
            <el-option label="杀菌剂" value="3"></el-option>
            <el-option label="饲料" value="4"></el-option>
          </el-select>
        </div>
        <div style="float: left; margin-left: 15px">
@@ -20,7 +24,7 @@
            placeholder="有库存"
            @change="stateChange"
          >
            <el-option label="全部" value="2"></el-option>
            <el-option label="全部" value=""></el-option>
            <el-option label="有库存" value="0"></el-option>
            <el-option label="无库存" value="1"></el-option>
          </el-select>
@@ -37,12 +41,12 @@
      </div>
      <div>
        <el-button size="small"
          ><span style="color: #5abf78">已出库待使用的农资</span></el-button
        ><span style="color: #5abf78" @click="out(row)">已出库待使用的农资</span></el-button
        >
        <el-button size="small"
          ><span style="color: #5abf78">出入库记录</span></el-button
        ><span style="color: #5abf78" @click="start(row)">出入库记录</span></el-button
        >
        <el-button type="success" size="small">农资入库</el-button>
        <el-button type="success" size="small" @click="mod(item)">农资入库</el-button>
      </div>
    </div>
    <div class="table">
@@ -51,38 +55,38 @@
          <!-- <div class="farm"> -->
          <div class="left">
            <div class="farm-img">
              <img src="../../../public/img/stock/fei.png" class="img" />
              <img src="../../../public/img/stock/fei.png" class="img"/>
            </div>
            <div class="farm-param">
              <div class="param-spec">
                <div class="spec-1"><span>肥料</span></div>
                <div class="spec-2"><span>有机肥</span></div>
                <div class="spec-1"><span>{{ item.stype }}</span></div>
                <div class="spec-3">
                  <span>{{ item.spn }}</span>
                </div>
              </div>
              <div class="param-cen">有机肥</div>
              <div class="param-cen">{{ item.agrname }}</div>
              <div class="param-cen1">{{ item.factoryName }}</div>
              <div class="param-detail">
                <img src="../../../public/img/stock/edit.png" />
                <div class="detail-text">查看库存明细</div>
                <img src="../../../public/img/stock/edit.png"/>
                <div class="detail-text" @click="kc(item)">查看库存明细</div>
              </div>
            </div>
          </div>
          <div class="right">
            <div class="spec">
              <span class="num">{{ item.amount }}</span
              >袋<span class="num1">(共940公斤)</span>
              >{{ item.dic2 }}<span class="num1">&nbsp;&nbsp;&nbsp;(共{{ item.cnum }}{{ item.dic1 }})</span>
            </div>
            <div class="btn">
              <div class="in" @click="modifiedGrades(item)">
                <img src="../../../public/img/stock/luku.png" /><span
                  >入库</span
                >
                <img src="../../../public/img/stock/luku.png"/><span
              >入库</span
              >
              </div>
              <div class="out" @click="modifiedGrades1(item)">
                <img src="../../../public/img/stock/chuku.png" /><span
                  >出库</span
                >
                <img src="../../../public/img/stock/chuku.png"/><span
              >出库</span
              >
              </div>
            </div>
          </div>
@@ -146,13 +150,36 @@
        </avue-form>
      </div>
    </el-dialog>
    <el-dialog
      title="农资入库"
      :visible.sync="gradec"
      width="width"
      :modal="true"
      :modal-append-to-body="true"
      :append-to-body="true"
      :close-on-click-modal="false"
      :close-on-press-escape="false"
      :before-close="dialogBeforeClose"
    >
      <div>
        <avue-form
          v-if="gradec"
          ref="formK"
          :option="option"
          v-model="formK"
          @reset-change="emptytChange"
          @submit="submitK"
        >
        </avue-form>
      </div>
    </el-dialog>
  </div>
</template>
<script>
import { getList, getDetail, add, update, remove } from "@/api/stock/stock";
import { add1 } from "@/api/stockrecord/stockrecord";
import { mapGetters } from "vuex";
import {getList, getDetail, add, update, remove} from "@/api/stock/stock";
import {add1} from "@/api/stockrecord/stockrecord";
import {mapGetters} from "vuex";
export default {
  data() {
@@ -165,15 +192,158 @@
      form: {},
      formC: {},
      formR: {},
      formK: {},
      specsValue1: "",
      query: {},
      loading: true,
      page: {
        pageSize: 10,
        pageSize: 4,
        currentPage: 1,
        total: 0,
      },
      selectionList: [],
      option: {
        height: 'auto',
        calcHeight: 30,
        tip: false,
        searchShow: true,
        searchMenuSpan: 3,
        border: true,
        index: true,
        align: "center",
        viewBtn: true,
        selection: true,
        dialogClickModal: false,
        column: [
          {
            label: "农资",
            prop: "stockId",
            span: 24,
            type: "select",
            dicUrl: "/api/stockfactory/stockfactory/selectStockFa",
            props: {
              label: "dictValue",
              value: "dictKey"
            },
            rules: [{
              required: true,
              message: "请输入农资",
              trigger: "blur"
            }]
          },
          {
            label: "规格",
            type: "number",
            prop: "specs",
            span: 7,
            rules: [{
              required: true,
              message: "请输入规格",
              trigger: "blur"
            }]
          },
          {
            label: "规格值1",
            value:"0",
            hide: true,
            prop: "specsValue1",
            searchSpan: 4,
            span: 5,
            type: "select",
            dicUrl: "/api/blade-system/dict-biz/dictionary?code=stockSpecs1",
            props: {
              label: "dictValue",
              value: "dictKey"
            },
            dataType: "number",
          },
          {
            label: "规格值2",
            value:"0",
            hide: true,
            prop: "specsValue2",
            searchSpan: 4,
            span: 5,
            type: "select",
            dicUrl: "/api/blade-system/dict-biz/dictionary?code=stockSpecs2",
            props: {
              label: "dictValue",
              value: "dictKey"
            },
            dataType: "number",
          },
          {
            label: "入库数量",
            span: 7,
            type: "number",
            prop: "amount",
            rules: [{
              required: true,
              message: "请输入入库数量",
              trigger: "blur"
            }]
          },
          {
            label: "入库类型",
            value:"0",
            prop: "type",
            type: "select",
            span: 12,
            searchSpan: 4,
            dicUrl: "/api/blade-system/dict-biz/dictionary?code=stockPurchase",
            props: {
              label: "dictValue",
              value: "dictKey"
            },
            dataType: "number",
            search: true,
            rules: [{
              required: true,
              message: "请输入入库类型",
              trigger: "blur"
            }]
          },
          {
            label: "入库时间",
            prop: "time",
            type: "date",
            format: "yyyy-MM-dd",
            valueFormat: "yyyy-MM-dd",
            span: 12,
            rules: [{
              required: true,
              message: "请输入入库时间",
              trigger: "blur"
            }]
          },
          {
            label: "单据、凭证照片",
            prop: "picture",
            type: "upload",
            labelWidth: 145,
            dataType: "string",
            span: 24,
            limit: 5,
            listType: "picture-card",
            tip: "建议上传手机横屏拍摄的照片,宽高比16:9,最多上传5张",
            canvasOption: {
              text: "",
              ratio: 1.0,
            },
            propsHttp: {
              res: "data",
              url: "url"
            },
            action: "/api/blade-resource/oss/endpoint/put-files"
          },
          {
            label: "备注",
            type: "textarea",
            prop: "remarks",
            span: 23,
          },
        ]
      },
      option1: {
        height: "auto",
        calcHeight: 30,
@@ -446,6 +616,7 @@
          },
          {
            label: "出库类型",
            value:"0",
            prop: "type1",
            type: "select",
            span: 12,
@@ -509,6 +680,7 @@
        ],
      },
      gradeBoxVisible: false,
      gradec: false,
      gradeBoxVisible1: false,
      data: [],
    };
@@ -536,6 +708,16 @@
    this.onLoad(this.page);
  },
  methods: {
    //库存明细
    kc(item) {
      const data = {
        stockId: item.stockId,
      };
      this.$router.push({
        path: `/stockrecord`,
        query: data
      });
    },
    //农资类型select 改变事件
    stypeChange(value) {
      this.query["stype"] = value;
@@ -548,7 +730,7 @@
    },
    //keywordChange 输入事件
    keywordChange(value) {
      this.query["keyword"] = value;
      this.query["agrname"] = value;
      this.onLoad(this.page, this.query);
    },
    //分页
@@ -561,7 +743,23 @@
      this.page.currentPage = val;
      this.onLoad(this.page);
    },
    //入库
    //农资入库按钮
    submitK(row, done, loading) {
      add(row).then(() => {
        this.onLoad(this.page);
        this.$message({
          type: "success",
          message: "操作成功!"
        });
        this.$refs.formK.resetFields();
        this.gradec = false;
        done();
      }, error => {
        loading();
        window.console.log(error);
      });
    },
//入库
    submitR(row, done, loading) {
      var that = this;
      add1(row).then(
@@ -573,7 +771,6 @@
            message: "操作成功!",
          });
          that.gradeBoxVisible = false;
          done();
        },
        (error) => {
@@ -581,8 +778,9 @@
          done();
        }
      );
    },
    //出库
    }
    ,
//出库
    submitC(row, done, loading) {
      var that = this;
      add1(row).then(
@@ -602,8 +800,9 @@
          done();
        }
      );
    },
    // 往入库页面填充数据
    }
    ,
// 往入库页面填充数据
    modifiedGrades(row) {
      this.formR = {
        id: null,
@@ -618,7 +817,12 @@
        stockType1: 1,
      };
      this.gradeBoxVisible = true;
    },
    }
    ,
    mod(row) {
      this.gradec = true;
    }
    ,
    modifiedGrades1(row) {
      this.formC = {
        id: null,
@@ -633,7 +837,8 @@
        stockType1: 0,
      };
      this.gradeBoxVisible1 = true;
    },
    }
    ,
    rowSave(row, done, loading) {
      add(row).then(
        () => {
@@ -649,7 +854,8 @@
          window.console.log(error);
        }
      );
    },
    }
    ,
    rowUpdate(row, index, done, loading) {
      update(row).then(
        () => {
@@ -665,7 +871,8 @@
          console.log(error);
        }
      );
    },
    }
    ,
    rowDel(row) {
      this.$confirm("确定将选择数据删除?", {
        confirmButtonText: "确定",
@@ -682,7 +889,8 @@
            message: "操作成功!",
          });
        });
    },
    }
    ,
    handleDelete() {
      if (this.selectionList.length === 0) {
        this.$message.warning("请选择至少一条数据");
@@ -704,7 +912,8 @@
          });
          this.$refs.crud.toggleSelection();
        });
    },
    }
    ,
    beforeOpen(done, type) {
      if (["edit", "view"].includes(type)) {
        getDetail(this.form.id).then((res) => {
@@ -712,11 +921,20 @@
        });
      }
      done();
    },
    //农事操作
    }
    ,
//农事操作
    start(row) {
      this.$router.push({
        path: `/stockrecord`,
        query: row,
      });
    }
    ,
    //已出库待使用农资
    out(row) {
      this.$router.push({
        path: `/stockout`,
        query: row,
      });
    },
@@ -726,7 +944,8 @@
        path: `/soldrecord`,
        query: row,
      });
    },
    }
    ,
    onLoad(page, params = {}) {
      this.loading = true;
      getList(
@@ -740,9 +959,11 @@
        this.loading = false;
        this.selectionClear();
      });
    },
    }
    ,
  },
};
}
;
</script>
<style lang="scss" scoped>
@@ -777,7 +998,7 @@
      .left {
        width: 78%;
        height: 151xp;
        height: 151 xp;
        float: left;
        .farm-img {
@@ -869,6 +1090,14 @@
            line-height: 60px;
          }
          .param-cen1 {
            font-size: 12px;
            font-weight: bold;
            color: #b2b2b2;
            margin-top: -6px;
          }
          .param-detail {
            height: 28px;
            display: flex;
@@ -923,7 +1152,7 @@
          display: flex;
          flex-direction: column;
          justify-content: center;
          padding-left: 25px;
          padding-left: 100px;
          .in {
            width: 67px;
src/views/stock/stockout.vue
New file
@@ -0,0 +1,680 @@
<template>
  <div class="body">
    <div class="search">
      <div style="float: left">
        <div style="float: left">
          <el-select
            v-model="formInline.stype"
            placeholder="全部分类"
            size="small"
            @change="stypeChange"
          >
            <el-option label="全部分类" value=""></el-option>
            <el-option label="化肥" value="0"></el-option>
            <el-option label="有机肥" value="1"></el-option>
            <el-option label="杀虫剂" value="2"></el-option>
            <el-option label="杀菌剂" value="3"></el-option>
            <el-option label="饲料" value="4"></el-option>
          </el-select>
        </div>
      </div>
    </div>
    <div class="table">
      <div class="content">
        <div class="farm" v-for="(item, index) in data" :key="index">
          <!-- <div class="farm"> -->
          <div class="left">
            <div class="farm-img">
              <img src="../../../public/img/stock/fei.png" class="img"/>
            </div>
            <div class="farm-param">
              <div class="param-spec">
                <div class="spec-1"><span>{{ item.stype }}</span></div>
                <div class="spec-3">
                  <span>{{ item.spn }}</span>
                </div>
              </div>
              <div class="param-cen">{{ item.agrname }}</div>
              <div class="param-cen1">{{ item.factoryName }}</div>
            </div>
          </div>
          <div class="right">
            <div class="spec">
              <span class="num">{{ item.amount1 }}</span
              ><span class="num2">{{ item.dic2 }}</span><span class="num1">&nbsp;&nbsp;共计&nbsp;{{
                item.cnum
              }}{{ item.dic1 }}</span>
            </div>
            <div class="btn">
              <div class="in" @click="kc(item)">
                <img src="../../../public/img/stock/edit.png"/><span
              >查看变更明细</span
              >
              </div>
              <div class="out" @click="out(item)">
                <img src="../../../public/img/stock/exit.png"/><span
              >退回</span
              >
              </div>
            </div>
          </div>
        </div>
      </div>
    </div>
    <div class="el-page">
      <el-pagination
        @size-change="handleSizeChange"
        @current-change="handleCurrentChange"
        :current-page="page.currentPage"
        :hide-on-single-page="value"
        :page-size="page.pageSize"
        background
        layout="total, prev, pager, next"
        :total="page.total"
      >
      </el-pagination>
    </div>
    <el-dialog
      title="退回农资"
      :visible.sync="outScoke"
      width="25%"
      :modal="true"
      :modal-append-to-body="true"
      :append-to-body="true"
      :close-on-click-modal="false"
      :close-on-press-escape="false"
      :before-close="dialogBeforeClose"
    >
      <div>
        <avue-form
          v-if="outScoke"
          ref="formO"
          :option="option2"
          v-model="formO"
          @reset-change="emptytChange"
          @submit="submitO"
        >
        </avue-form>
      </div>
    </el-dialog>
  </div>
</template>
<script>
import {getList, getDetail, add, update, remove,Updateout} from "@/api/soldr/soldr";
import {mapGetters} from "vuex";
export default {
  data() {
    return {
      formInline: {
        stype: "0",
        state: "0",
        keyword: "",
      },
      specsValue1: "",
      query: {},
      loading: true,
      option2: {
        height: 50,
        calcHeight: 30,
        tip: false,
        searchShow: true,
        searchMenuSpan: 6,
        border: true,
        index: true,
        viewBtn: true,
        selection: true,
        dialogClickModal: false,
        column: [
          {
            label: "农资",
            span: 20,
            display: true,
            prop: "stockid",
          },
          {
            label: "库存数量",
            span: 20,
            display: true,
            prop: "num",
          },
          {
            label: "退回数量",
            span: 20,
            type: "number",
            prop: "spn",
          }
        ],
      },
      page: {
        pageSize: 10,
        currentPage: 1,
        total: 0,
      },
      outScoke: false,
      selectionList: [],
      data: [],
    };
  },
  computed: {
    ...mapGetters(["permission"]),
    permissionList() {
      return {
        addBtn: this.vaildData(this.permission.stock_add, false),
        viewBtn: this.vaildData(this.permission.stock_view, false),
        delBtn: this.vaildData(this.permission.stock_delete, true),
        editBtn: this.vaildData(this.permission.stock_edit, false),
      };
    },
    ids() {
      let ids = [];
      this.selectionList.forEach((ele) => {
        ids.push(ele.id);
      });
      return ids.join(",");
    },
  },
  created() {
    //初始化页面数据
    this.onLoad(this.page);
  },
  methods: {
    kc(item) {
      this.$router.push({
        path: `/soldrecord`,
        query: item
      });
    },
    //退回提交
    submitO(row, done, loading) {
      //退回数量大于入库数量
      if (row.spn > row.num) {
        this.$message.warning("退回失败! 退回数量不可大于剩余数量");
        this.outScoke = false
        done();
      }
      //退回数量等于入库数量
      if (row.spn == row.num) {
        Updateout(row.spn,row.stockid,0).then(
          () => {
            this.onLoad(this.page);
            this.$message({
              type: "success",
              message: "操作成功!",
            });
            this.outScoke = false
            done();
          },
          (error) => {
            loading();
            window.console.log(error);
          }
        );
      }
        //退回数量小于入库数量
      if (row.spn < row.num) {
        Updateout(row.spn,row.stockid,1).then(
          () => {
            this.onLoad(this.page);
            this.$message({
              type: "success",
              message: "操作成功!",
            });
            this.outScoke = false
            done();
          },
          (error) => {
            loading();
            window.console.log(error);
          }
        );
      }
    },
    //农资类型select 改变事件
    stypeChange(value) {
      this.query["stype"] = value;
      this.onLoad(this.page, this.query);
    },
    //库存 select 改变事件
    stateChange(value) {
      this.query["state"] = value;
      this.onLoad(this.page, this.query);
    },
    //keywordChange 输入事件
    keywordChange(value) {
      this.query["keyword"] = value;
      this.onLoad(this.page, this.query);
    },
    //分页
    handleSizeChange(val) {
      this.page.pageSize = val;
      this.onLoad(this.page);
    },
    //改变页码
    handleCurrentChange(val) {
      this.page.currentPage = val;
      this.onLoad(this.page);
    },
    //农资入库按钮
    submitK(row, done, loading) {
      add(row).then(() => {
        this.onLoad(this.page);
        this.$message({
          type: "success",
          message: "操作成功!"
        });
        that.gradec = false;
        done();
      }, error => {
        loading();
        window.console.log(error);
      });
    },
// 往入库页面填充数据
    modifiedGrades(row) {
      this.formR = {
        id: null,
        stockId1: row.stockId,
        spn: row.spn,
        num: row.amount,
        type1: row.type,
        time1: row.time,
        specs1: row.specs,
        specsVal1: row.specsValue1,
        specsVal2: row.specsValue1,
        stockType1: 1,
      };
      this.gradeBoxVisible = true;
    },
    //退回
    out(row) {
      this.formO = {
        num: row.amount1,
        stockid: row.stockId1,
      };
      this.outScoke = true
    }
    ,
    mod(row) {
      this.gradec = true;
    }
    ,
    modifiedGrades1(row) {
      this.formC = {
        id: null,
        stockId1: row.stockId,
        spn: row.spn,
        num: row.amount,
        type1: row.type,
        time1: row.time,
        specs1: row.specs,
        specsVal1: row.specsValue1,
        specsVal2: row.specsValue1,
        stockType1: 0,
      };
      this.gradeBoxVisible1 = true;
    }
    ,
    rowSave(row, done, loading) {
      add(row).then(
        () => {
          this.onLoad(this.page);
          this.$message({
            type: "success",
            message: "操作成功!",
          });
          done();
        },
        (error) => {
          loading();
          window.console.log(error);
        }
      );
    }
    ,
    rowUpdate(row, index, done, loading) {
      update(row).then(
        () => {
          this.onLoad(this.page);
          this.$message({
            type: "success",
            message: "操作成功!",
          });
          done();
        },
        (error) => {
          loading();
          console.log(error);
        }
      );
    }
    ,
    rowDel(row) {
      this.$confirm("确定将选择数据删除?", {
        confirmButtonText: "确定",
        cancelButtonText: "取消",
        type: "warning",
      })
        .then(() => {
          return remove(row.id);
        })
        .then(() => {
          this.onLoad(this.page);
          this.$message({
            type: "success",
            message: "操作成功!",
          });
        });
    }
    ,
    handleDelete() {
      if (this.selectionList.length === 0) {
        this.$message.warning("请选择至少一条数据");
        return;
      }
      this.$confirm("确定将选择数据删除?", {
        confirmButtonText: "确定",
        cancelButtonText: "取消",
        type: "warning",
      })
        .then(() => {
          return remove(this.ids);
        })
        .then(() => {
          this.onLoad(this.page);
          this.$message({
            type: "success",
            message: "操作成功!",
          });
          this.$refs.crud.toggleSelection();
        });
    }
    ,
    beforeOpen(done, type) {
      if (["edit", "view"].includes(type)) {
        getDetail(this.form.id).then((res) => {
          this.form = res.data.data;
        });
      }
      done();
    },
    onLoad(page, params = {}) {
      this.loading = true;
      getList(
        page.currentPage,
        page.pageSize,
        Object.assign(params, this.query)
      ).then((res) => {
        const data = res.data.data;
        this.page.total = data.total;
        this.data = data.records;
        this.loading = false;
        this.selectionClear();
      });
    }
    ,
  },
}
;
</script>
<style lang="scss" scoped>
.body {
  background-color: #fff;
  width: 98%;
  height: 95%;
  margin: 0 auto;
  .search {
    padding-top: 40px;
    width: 98%;
    margin: 0 auto;
    display: flex;
    flex-flow: row nowrap;
    justify-content: space-between;
  }
  .content {
    padding-top: 20px;
    width: 98%;
    height: auto;
    min-height: 630px;
    margin: 0 auto;
    .farm {
      border: 1px solid #f3f3f3;
      border-radius: 8px;
      box-shadow: 0px 0px 6px 1px rgba(0, 0, 0, 0.05);
      opacity: 1;
      height: 151px;
      .left {
        width: 78%;
        height: 151px;
        float: left;
        .farm-img {
          width: 115px;
          height: 115px;
          line-height: 151px;
          background: #f3f3f3;
          border-radius: 8px 8px 8px 8px;
          opacity: 1;
          text-align: center;
          margin-left: 20px;
          margin-top: 19px;
          float: left;
          img {
            width: 100%;
            height: 100%;
          }
        }
        .farm-param {
          height: 100%;
          position: relative;
          left: 20px;
          top: 20px;
          .param-spec {
            height: 30px;
            .spec-1 {
              width: 42px;
              height: 21px;
              background: #fdf2e9;
              border-radius: 11px 11px 11px 11px;
              opacity: 1;
              text-align: center;
              float: left;
              span {
                font-size: 12px;
                font-weight: 400;
                color: #ef8a3c;
                font-family: Microsoft YaHei-Regular, Microsoft YaHei;
              }
            }
            .spec-2 {
              width: 53px;
              height: 21px;
              background: #fdf2e9;
              border-radius: 11px 11px 11px 11px;
              opacity: 1;
              text-align: center;
              float: left;
              margin-left: 10px;
              span {
                font-size: 12px;
                font-weight: 400;
                color: #ef8a3c;
                font-family: Microsoft YaHei-Regular, Microsoft YaHei;
              }
            }
            .spec-3 {
              width: 72px;
              height: 21px;
              background: #f4f4f4;
              border-radius: 11px 11px 11px 11px;
              opacity: 1;
              text-align: center;
              margin-left: 10px;
              float: left;
              span {
                font-size: 12px;
                font-weight: 400;
                color: #999999;
                font-family: Microsoft YaHei-Regular, Microsoft YaHei;
              }
            }
          }
          .param-cen {
            font-size: 20px;
            font-weight: bold;
            color: #333333;
            height: 60px;
            line-height: 60px;
          }
          .param-cen1 {
            font-size: 12px;
            font-weight: bold;
            color: #b2b2b2;
            margin-top: -8px;
          }
          .param-detail {
            height: 28px;
            display: flex;
            align-items: center;
            padding-top: 0px;
            cursor: pointer;
            img {
              width: 11.6px;
              height: 13.06px;
              float: left;
            }
            .detail-text {
              font-size: 12px;
              font-family: Microsoft YaHei-Regular, Microsoft YaHei;
              font-weight: 400;
              color: #5abf78;
              margin-left: 5px;
            }
          }
        }
      }
      .right {
        height: 100%;
        .spec {
          height: 151px;
          line-height: 151px;
          font-size: 26px;
          color: #5abf78;
          float: left;
          .num {
            font-size: 16px;
            font-family: DIN-Bold, DIN;
            font-weight: bold;
            color: #5abf78;
          }
          .num1 {
            font-size: 16px;
            font-family: Microsoft YaHei-Regular, Microsoft YaHei;
            font-weight: bold;
            color: #5abf78;
          }
          .num2 {
            font-size: 16px;
            font-family: Microsoft YaHei-Regular, Microsoft YaHei;
            font-weight: bold;
            color: #5abf78;
          }
        }
        .btn {
          height: 151px;
          display: flex;
          flex-direction: column;
          justify-content: center;
          padding-left: 100px;
          .in {
            width: 100px;
            height: 25px;
            line-height: 25px;
            //background: rgba(90, 191, 120, 0.1);
            //border-radius: 13px;
            //border: 1px solid #5abf78;
            text-align: center;
            cursor: pointer;
            img {
              width: 11.38px;
              height: 11.35px;
            }
            span {
              font-size: 12px;
              font-family: Microsoft YaHei-Regular, Microsoft YaHei;
              font-weight: 400;
              color: #64c3a4;
              position: relative;
              top: -2px;
              left: 3px;
            }
          }
          .out {
            margin-top: 10px;
            width: 100px;
            height: 25px;
            line-height: 25px;
            //background: rgba(90, 191, 120, 0.1);
            //border-radius: 13px;
            //border: 1px solid #5abf78;
            text-align: center;
            cursor: pointer;
            img {
              width: 11.38px;
              height: 11.35px;
            }
            span {
              font-size: 12px;
              font-family: Microsoft YaHei-Regular, Microsoft YaHei;
              font-weight: 400;
              color: #64c3a4;
              position: relative;
              top: -2px;
              left: 3px;
            }
          }
        }
      }
    }
  }
  .el-page {
    padding-top: 30px;
    text-align: center;
  }
}
</style>
src/views/stockrecord/stockrecord.vue
@@ -57,6 +57,7 @@
          index: true,
          viewBtn: true,
          align: "center",
          excelBtn:true,
          selection: true,
          dialogClickModal: false,
          column: [
@@ -108,8 +109,8 @@
              prop: "count",
            },
            {
              label: "时间",
              prop: "time1",
              label: "操作时间",
              prop: "createTime",
            },
            {
              label: "操作人",