Browse Source

进销存模块

cz 2 years ago
parent
commit
65b3ad7fe8

+ 30 - 6
src/router/index.js

@@ -19,8 +19,7 @@ const routes = [{
 		name: 'main',
 		component: main,
 		redirect: '/main/equipment',
-		children: [
-			{
+		children: [{
 				path: 'equipment',
 				name: '设备列表',
 				component: () => import('../views/equipment/index.vue')
@@ -53,18 +52,43 @@ const routes = [{
 				component: () => import('../views/purchase-sales/inbound-outbound/manualOutbound/index.vue')
 			},
 			{
+				path: 'manualOutboundAdd',
+				name: '手动出库新增',
+				component: () => import('../views/purchase-sales/inbound-outbound/manualOutbound/add.vue')
+			},
+			{
 				path: 'manualInbound',
 				name: '手动入库',
 				component: () => import('../views/purchase-sales/inbound-outbound/manualInbound/index.vue')
 			},
 			{
-				path: 'addDetails',
-				name: '手动入12312312库',
-				component: () => import('../views/purchase-sales/inbound-outbound/addDetails.vue')
+				path: 'manualInboundAdd',
+				name: '手动入库新增',
+				component: () => import('../views/purchase-sales/inbound-outbound/manualInbound/add.vue')
+			},
+			{
+				path: 'transferWarehouse',
+				name: '调仓',
+				component: () => import('../views/purchase-sales/inbound-outbound/transferWarehouse/index.vue')
+			},
+			{
+				path: 'sendTransferWarehouse',
+				name: '发起调仓',
+				component: () => import('../views/purchase-sales/inbound-outbound/transferWarehouse/add.vue')
+			},
+			{
+				path: 'inventoryQuery',
+				name: '库存查询',
+				component: () => import('../views/purchase-sales/inventory-management/inventoryQuery/index.vue')
+			},
+			{
+				path: 'outInList',
+				name: '出入库流水',
+				component: () => import('../views/purchase-sales/inventory-management/outInList/index.vue')
 			},
 		]
 	},
-	
+
 ]
 
 const router = createRouter({

+ 0 - 101
src/views/purchase-sales/inbound-outbound/addDetails.vue

@@ -1,101 +0,0 @@
-<template>
-  <div>
-    <van-form @submit="onSubmit" label-align="top">
-      <van-field
-        v-model="result"
-        is-link
-        readonly
-        name="picker"
-        label="仓库名称"
-        placeholder="请选择"
-        @click="formStatus.isShowWarehouse = true"
-        :rules="[
-          { required: true, message: '请选择仓库名称', trigger: 'onChange' },
-        ]"
-      />
-
-      <div>
-        出库明细1
-        <van-field
-          v-model="result"
-          is-link
-          readonly
-          name="picker"
-          label="物品名称"
-          placeholder="请选择"
-          :rules="[
-            { required: true, message: '请选择物品名称', trigger: 'onChange' },
-          ]"
-          @click="formStatus.isShowProduct = true"
-        />
-        <van-field
-          v-model="username"
-          name="出库数量"
-          label="出库数量"
-          placeholder="请输入"
-          :rules="[
-            { required: true, message: '请输入出库数量', trigger: 'onBlur' },
-          ]"
-        />
-      </div>
-      <div style="margin: 16px">
-        <van-button round block type="primary" native-type="submit">
-          提交
-        </van-button>
-      </div>
-    </van-form>
-    <!-- 仓库弹窗选择 -->
-    <van-popup v-model:show="formStatus.isShowWarehouse" position="bottom">
-      <van-picker
-        :columns="formStatus.warehouseColumns"
-        :columns-field-names="{
-          text: 'name',
-          value: 'id',
-        }"
-        @confirm="onConfirm"
-        @cancel="formStatus.isShowWarehouse = false"
-      />
-    </van-popup>
-    <!-- 产品弹窗选择 -->
-    <van-popup v-model:show="formStatus.isShowProduct" position="bottom">
-      <van-picker
-        :columns="formStatus.productColumns"
-        :columns-field-names="{
-          text: 'name',
-          value: 'id',
-        }"
-        @confirm="onConfirm"
-        @cancel="formStatus.isShowProduct = false"
-      />
-    </van-popup>
-  </div>
-</template>
-
-<script setup>
-import { ref, reactive, getCurrentInstance } from "vue";
-const { proxy } = getCurrentInstance();
-const submitForm = reactive({});
-const formStatus = reactive({
-  isShowWarehouse: false,
-  isShowProduct: false,
-  warehouseColumns: [],
-  productColumns: [],
-});
-const getSelectData = async () => {
-  const res = await proxy.post("/warehouse/page", {
-    pageNum: 1,
-    pageSize: 9999,
-  });
-  formStatus.warehouseColumns = res.data.rows;
-  const res1 = await proxy.post("/productInfo/page", {
-    pageNum: 1,
-    pageSize: 9999,
-    definition: "1",
-  });
-  formStatus.productColumns = res1.data.rows;
-};
-getSelectData();
-</script>
-
-<style lang="scss" scoped>
-</style>

+ 218 - 0
src/views/purchase-sales/inbound-outbound/manualInbound/add.vue

@@ -0,0 +1,218 @@
+<template>
+  <div class="form">
+    <van-nav-bar
+      title="手动入库"
+      left-text="返回"
+      left-arrow
+      @click-left="onClickLeft"
+    >
+    </van-nav-bar>
+    <van-form @submit="onSubmit" label-align="top" style="margin-top: 20px">
+      <van-cell-group inset>
+        <van-field
+          v-model="formData.warehouseName"
+          is-link
+          readonly
+          label="仓库名称"
+          placeholder="选择仓库名称"
+          @click="typeModal = true"
+          :rules="[{ required: true, message: '仓库名称不能为空' }]"
+          required
+        />
+        <van-popup v-model:show="typeModal" round position="bottom">
+          <van-picker
+            :columns="columns"
+            @cancel="typeModal = false"
+            @confirm="onConfirm"
+          />
+        </van-popup>
+        <!-- 明细列表 -->
+        <div v-for="(item, index) in list" :key="index">
+          <div class="row">
+            <div class="title">明细{{ index + 1 }}</div>
+            <div
+              class="delete"
+              @click.native="handleDel(index)"
+              v-if="!route.query.id"
+            >
+              <van-icon name="cross" />
+            </div>
+          </div>
+          <van-field
+            v-model="list[index].productName"
+            is-link
+            readonly
+            label="物品名称"
+            placeholder="选择物品名称"
+            @click="handleSelect(index)"
+            :rules="[{ required: true, message: '物品名称不能为空' }]"
+            required
+          />
+
+          <van-field
+            v-model="list[index].quantity"
+            label="入库数量"
+            placeholder="请输入入库数量"
+            :rules="[{ required: true, message: '入库数量不能为空' }]"
+            required
+          />
+        </div>
+        <van-popup v-model:show="typeModalOne" round position="bottom">
+          <van-picker
+            :columns="columnsOne"
+            @cancel="typeModalOne = false"
+            @confirm="(data) => onConfirmOne(data, index)"
+          />
+        </van-popup>
+      </van-cell-group>
+
+      <div style="text-align: center; line-height: 28px" v-if="!route.query.id">
+        <van-button
+          icon="plus"
+          type="primary"
+          plain
+          size="mini"
+          style="margin-top: 10px"
+          @click="handleAddRow"
+          >添加明细</van-button
+        >
+      </div>
+
+      <div style="margin: 16px" v-if="!route.query.id">
+        <van-button round block type="primary" native-type="submit">
+          提交
+        </van-button>
+      </div>
+    </van-form>
+  </div>
+</template>
+
+<script setup>
+import { ref, getCurrentInstance, onMounted } from "vue";
+import { showSuccessToast, showFailToast } from "vant";
+import { useRoute } from "vue-router";
+
+const proxy = getCurrentInstance().proxy;
+const route = useRoute();
+const showPicker = ref(false);
+const typeModal = ref(false);
+const typeModalOne = ref(false);
+let selectIndex = ref(null);
+const formData = ref({
+  warehouseId: "",
+  type: "1",
+  warehouseName: "",
+});
+const list = ref([]);
+const handleAddRow = () => {
+  list.value.push({
+    productId: "",
+    productName: "",
+    quantity: "",
+  });
+};
+const getDict = () => {
+  proxy.post("/warehouse/page", { pageNum: 1, pageSize: 9999 }).then((res) => {
+    columns.value = res.data.rows.map((item) => {
+      return {
+        text: item.name,
+        value: item.id,
+      };
+    });
+    // formData.value.warehouseName = formData.value.warehouseId
+    //   ? columns.value.find((item) => item.value == formData.value.warehouseId).name
+    //   : null;
+  });
+
+  proxy
+    .post("/productInfo/page", { pageNum: 1, pageSize: 9999, definition: "1" })
+    .then((res) => {
+      columnsOne.value = res.data.rows.map((item) => {
+        return {
+          text: item.name,
+          value: item.id,
+        };
+      });
+      // formData.value.warehouseName = formData.value.warehouseId
+      //   ? columns.value.find((item) => item.value == formData.value.warehouseId).name
+      //   : null;
+    });
+};
+
+const getDetails = (id) => {
+  proxy.post("/stockJournal/detail", { id }).then((res) => {
+    formData.value = res.data;
+    list.value = res.data.list.map((x) => ({
+      productId: x.productId,
+      productName: x.productName,
+      quantity: x.quantity,
+    }));
+  });
+};
+
+const columns = ref([]);
+const columnsOne = ref([]);
+
+const onConfirm = ({ selectedOptions }) => {
+  formData.value.warehouseId = selectedOptions[0].value;
+  formData.value.warehouseName = selectedOptions[0].text;
+  typeModal.value = false;
+};
+
+const onConfirmOne = ({ selectedOptions }, index) => {
+  list.value[selectIndex.value].productId = selectedOptions[0].value;
+  list.value[selectIndex.value].productName = selectedOptions[0].text;
+  typeModalOne.value = false;
+};
+
+const handleSelect = (index) => {
+  selectIndex.value = index;
+  typeModalOne.value = true;
+};
+
+const handleDel = (index) => {
+  list.value.splice(index, 1);
+};
+
+const onClickLeft = () => history.back();
+
+const onSubmit = () => {
+  if (!list.value.length > 0) return showFailToast("请添加明细!");
+  formData.value.list = list.value.map((x) => ({
+    productId: x.productId,
+    quantity: x.quantity,
+  }));
+  formData.value.type = "1";
+  proxy.post("/stock/add", formData.value).then(
+    (res) => {
+      setTimeout(() => {
+        showSuccessToast("入库成功");
+        proxy.$router.push("/main/manualInbound");
+      }, 500);
+    },
+    (err) => {
+      return showFailToast(err.message);
+    }
+  );
+};
+onMounted(() => {
+  getDetails(route.query.id);
+  getDict();
+});
+</script>
+<style lang="scss" scoped>
+.row {
+  display: flex;
+  padding: 5px 10px 0 10px;
+  justify-content: space-between;
+  align-items: center;
+  .title {
+    flex: 1;
+  }
+  .delete {
+    width: 20px;
+    cursor: pointer;
+    text-align: center;
+  }
+}
+</style>

+ 92 - 80
src/views/purchase-sales/inbound-outbound/manualInbound/index.vue

@@ -1,102 +1,114 @@
 <template>
-	<van-nav-bar
-		title="仓库维护"
-		left-text=""
-		left-arrow
-		@click-left="onClickLeft"
-		@click-right="onClickRight"
-	>
-		<template #right>
-			添加
-		</template>
-	</van-nav-bar>
-	<van-search v-model="req.keyword"  placeholder="请输入搜索关键词" @search="onRefresh" />
-	<van-pull-refresh v-model="loading" @refresh="onRefresh" >
-		
-		<div class="list">
-			<van-list
-				v-model:loading="loading"
-				:finished="finished"
-				finished-text="没有更多了"
-				@load="onLoad"
-				style="margin-bottom:60px"
-			>
-				<commonList :data="listData" @onClick="toDtl" :config="listConfig"></commonList>
-			</van-list>
-		</div>
-	</van-pull-refresh>
+  <van-nav-bar
+    title="手动入库"
+    left-text=""
+    left-arrow
+    @click-left="onClickLeft"
+    @click-right="onClickRight"
+  >
+    <template #right> 添加 </template>
+  </van-nav-bar>
+  <van-search
+    v-model="req.keyword"
+    placeholder="请输入搜索关键词"
+    @search="onRefresh"
+  />
+  <van-pull-refresh v-model="loading" @refresh="onRefresh">
+    <div class="list">
+      <van-list
+        v-model:loading="loading"
+        :finished="finished"
+        finished-text="没有更多了"
+        @load="onLoad"
+        style="margin-bottom: 60px"
+      >
+        <commonList
+          :data="listData"
+          @onClick="toDtl"
+          :config="listConfig"
+        ></commonList>
+      </van-list>
+    </div>
+  </van-pull-refresh>
 </template>
 <script setup>
-import { ref, getCurrentInstance, onMounted } from 'vue'
-import commonList from '@/components/common-list.vue'
-import { useRoute } from 'vue-router'
-const loading = ref(false)
-const router = useRoute()
+import { ref, getCurrentInstance, onMounted } from "vue";
+import commonList from "@/components/common-list.vue";
+import { useRoute } from "vue-router";
+const loading = ref(false);
+const router = useRoute();
 const req = ref({
-	pageNum:1,
-	keyword:null
-})
+  pageNum: 1,
+  type: "1",
+  keyword: null,
+});
 const finished = ref(false);
-const proxy = getCurrentInstance().proxy
-const listData = ref([])
-
+const proxy = getCurrentInstance().proxy;
+const listData = ref([]);
 
 const listConfig = ref([
-	{
-		label: '仓库名称',
-		prop: 'name',
-	},
-	{
-		label: '仓库类型',
-		prop: 'type',
-	}
-])
+  {
+    label: "仓库名称",
+    prop: "warehouseName",
+  },
+  {
+    label: "入库时间",
+    prop: "createTime",
+  },
+  {
+    label: "操作人",
+    prop: "userName",
+  },
+]);
 const onRefresh = () => {
-	req.value.pageNum = 1
-	finished.value = false
-	getList('refresh')
-}
+  req.value.pageNum = 1;
+  finished.value = false;
+  getList("refresh");
+};
 const onLoad = () => {
-    getList()
-}
+  getList();
+};
 
-const onClickLeft = () => proxy.$router.push('/main/working')
+const onClickLeft = () => proxy.$router.push("/main/working");
 
 const onClickRight = () => {
-	proxy.$router.push('/main/warehouseConfigAdd')
-}
+  proxy.$router.push("/main/manualInboundAdd");
+};
 
 const toDtl = (row) => {
-	console.log(row)
-	proxy.$router.push({
-        path: 'warehouseConfigAdd',
-		query: row
-      })
-}
+  proxy.$router.push({
+    path: "manualInboundAdd",
+    query: {
+      id: row.id,
+    },
+  });
+};
 
 const getList = (type) => {
-	loading.value = true
-	proxy.post('/warehouse/page',req.value).then(res => {	
-		
-		console.log(req.value)
-		listData.value = type === 'refresh' ? res.data.rows : listData.value.concat(res.data.rows)
-		if(req.value.pageNum * 10 >= res.data.total) {
-			finished.value = true
-		}
-		req.value.pageNum++	
-		loading.value = false
-		
-		
-		
-	}).catch(err => {
-		loading.value = false
-	})
-}
-getList()
+  loading.value = true;
+  proxy
+    .post("/stockJournal/page", req.value)
+    .then((res) => {
+      console.log(req.value);
+      listData.value =
+        type === "refresh"
+          ? res.data.rows
+          : listData.value.concat(res.data.rows);
+      if (req.value.pageNum * 10 >= res.data.total) {
+        finished.value = true;
+      }
+      req.value.pageNum++;
+      loading.value = false;
+    })
+    .catch((err) => {
+      loading.value = false;
+    });
+};
+getList();
 </script>
 
 <style lang="scss" scoped>
 .list {
-	min-height: 70vh;
+  min-height: 70vh;
 }
 </style>

+ 0 - 0
src/views/purchase-sales/inbound-outbound/manualInbound/outbound.vue


+ 219 - 0
src/views/purchase-sales/inbound-outbound/manualOutbound/add.vue

@@ -0,0 +1,219 @@
+<template>
+  <div class="form">
+    <van-nav-bar
+      title="手动出库"
+      left-text="返回"
+      left-arrow
+      @click-left="onClickLeft"
+    >
+    </van-nav-bar>
+    <van-form @submit="onSubmit" label-align="top" style="margin-top: 20px">
+      <van-cell-group inset>
+        <van-field
+          v-model="formData.warehouseName"
+          is-link
+          readonly
+          label="仓库名称"
+          placeholder="选择仓库名称"
+          @click="typeModal = true"
+          :rules="[{ required: true, message: '仓库名称不能为空' }]"
+          required
+        />
+        <van-popup v-model:show="typeModal" round position="bottom">
+          <van-picker
+            :columns="columns"
+            @cancel="typeModal = false"
+            @confirm="onConfirm"
+          />
+        </van-popup>
+        <!-- 明细列表 -->
+        <div v-for="(item, index) in list" :key="index">
+          <div class="row">
+            <div class="title">明细{{ index + 1 }}</div>
+            <div
+              class="delete"
+              @click.native="handleDel(index)"
+              v-if="!route.query.id"
+            >
+              <van-icon name="cross" />
+            </div>
+          </div>
+          <van-field
+            v-model="list[index].productName"
+            is-link
+            readonly
+            label="物品名称"
+            placeholder="选择物品名称"
+            @click="handleSelect(index)"
+            :rules="[{ required: true, message: '物品名称不能为空' }]"
+            required
+          />
+
+          <van-field
+            v-model="list[index].quantity"
+            label="出库数量"
+            placeholder="请输入出库数量"
+            :rules="[{ required: true, message: '出库数量不能为空' }]"
+            required
+          />
+        </div>
+        <van-popup v-model:show="typeModalOne" round position="bottom">
+          <van-picker
+            :columns="columnsOne"
+            @cancel="typeModalOne = false"
+            @confirm="(data) => onConfirmOne(data, index)"
+          />
+        </van-popup>
+      </van-cell-group>
+
+      <div style="text-align: center; line-height: 28px" v-if="!route.query.id">
+        <van-button
+          icon="plus"
+          type="primary"
+          plain
+          size="mini"
+          style="margin-top: 10px"
+          @click="handleAddRow"
+          >添加明细</van-button
+        >
+      </div>
+
+      <div style="margin: 16px" v-if="!route.query.id">
+        <van-button round block type="primary" native-type="submit">
+          提交
+        </van-button>
+      </div>
+    </van-form>
+  </div>
+</template>
+
+<script setup>
+import { ref, getCurrentInstance, onMounted } from "vue";
+import { showSuccessToast, showFailToast } from "vant";
+import { useRoute } from "vue-router";
+
+const proxy = getCurrentInstance().proxy;
+const route = useRoute();
+const showPicker = ref(false);
+const typeModal = ref(false);
+const typeModalOne = ref(false);
+let selectIndex = ref(null);
+const formData = ref({
+  warehouseId: "",
+  type: "2",
+  warehouseName: "",
+});
+const list = ref([]);
+const handleAddRow = () => {
+  list.value.push({
+    productId: "",
+    productName: "",
+    quantity: "",
+  });
+};
+const getDetails = (id) => {
+  proxy.post("/stockJournal/detail", { id }).then((res) => {
+    console.log(res, "www");
+    formData.value = res.data;
+    list.value = res.data.list.map((x) => ({
+      productId: x.productId,
+      productName: x.productName,
+      quantity: x.quantity,
+    }));
+  });
+};
+
+const getDict = () => {
+  proxy.post("/warehouse/page", { pageNum: 1, pageSize: 9999 }).then((res) => {
+    columns.value = res.data.rows.map((item) => {
+      return {
+        text: item.name,
+        value: item.id,
+      };
+    });
+    // formData.value.warehouseName = formData.value.warehouseId
+    //   ? columns.value.find((item) => item.value == formData.value.warehouseId).name
+    //   : null;
+  });
+
+  proxy
+    .post("/productInfo/page", { pageNum: 1, pageSize: 9999, definition: "1" })
+    .then((res) => {
+      columnsOne.value = res.data.rows.map((item) => {
+        return {
+          text: item.name,
+          value: item.id,
+        };
+      });
+      // formData.value.warehouseName = formData.value.warehouseId
+      //   ? columns.value.find((item) => item.value == formData.value.warehouseId).name
+      //   : null;
+    });
+};
+
+const columns = ref([]);
+const columnsOne = ref([]);
+
+const onConfirm = ({ selectedOptions }) => {
+  formData.value.warehouseId = selectedOptions[0].value;
+  formData.value.warehouseName = selectedOptions[0].text;
+  typeModal.value = false;
+};
+
+const onConfirmOne = ({ selectedOptions }, index) => {
+  list.value[selectIndex.value].productId = selectedOptions[0].value;
+  list.value[selectIndex.value].productName = selectedOptions[0].text;
+  typeModalOne.value = false;
+};
+
+const handleSelect = (index) => {
+  selectIndex.value = index;
+  typeModalOne.value = true;
+};
+
+const handleDel = (index) => {
+  list.value.splice(index, 1);
+};
+
+const onClickLeft = () => history.back();
+
+const onSubmit = () => {
+  if (!list.value.length > 0) return showFailToast("请添加明细!");
+  formData.value.list = list.value.map((x) => ({
+    productId: x.productId,
+    quantity: x.quantity,
+  }));
+  formData.value.type = "2";
+  proxy.post("/stock/edit", formData.value).then(
+    (res) => {
+      setTimeout(() => {
+        showSuccessToast("出库成功");
+        proxy.$router.push("/main/manualOutbound");
+      }, 500);
+    },
+    (err) => {
+      return showFailToast(err.message);
+    }
+  );
+};
+onMounted(() => {
+  getDetails(route.query.id);
+  getDict();
+});
+</script>
+<style lang="scss" scoped>
+.row {
+  display: flex;
+  padding: 5px 10px 0 10px;
+  justify-content: space-between;
+  align-items: center;
+  .title {
+    flex: 1;
+  }
+  .delete {
+    width: 20px;
+    cursor: pointer;
+    text-align: center;
+  }
+}
+</style>

+ 92 - 85
src/views/purchase-sales/inbound-outbound/manualOutbound/index.vue

@@ -1,108 +1,115 @@
 <template>
-  <van-button type="primary" @click="handleAdd">添加</van-button>
-  <van-pull-refresh v-model="pageStatus.refreshing" @refresh="onRefresh">
-    <van-list
-      v-model:loading="pageStatus.loading"
-      :loading-text="pageStatus.loadingText"
-      :finished="pageStatus.finished"
-      finished-text="没有更多了"
-      @load="onLoad"
-    >
-      <div class="list">
-        <div v-for="item in pageStatus.list" :key="item.id" class="list-item">
-          <div class="row">
-            <div class="title">仓库名称</div>
-            <div class="value">{{ item.warehouseName }}</div>
-          </div>
-          <div class="row">
-            <div class="title">出库时间</div>
-            <div class="value">{{ item.createTime }}</div>
-            <div class="icon"></div>
-          </div>
-          <div class="row">
-            <div class="title">操作人</div>
-            <div class="value">{{ item.userName }}</div>
-          </div>
-        </div>
-      </div>
-    </van-list>
+  <van-nav-bar
+    title="手动出库"
+    left-text=""
+    left-arrow
+    @click-left="onClickLeft"
+    @click-right="onClickRight"
+  >
+    <template #right> 添加 </template>
+  </van-nav-bar>
+  <van-search
+    v-model="req.keyword"
+    placeholder="请输入搜索关键词"
+    @search="onRefresh"
+  />
+  <van-pull-refresh v-model="loading" @refresh="onRefresh">
+    <div class="list">
+      <van-list
+        v-model:loading="loading"
+        :finished="finished"
+        finished-text="没有更多了"
+        @load="onLoad"
+        style="margin-bottom: 60px"
+      >
+        <commonList
+          :data="listData"
+          @onClick="toDtl"
+          :config="listConfig"
+        ></commonList>
+      </van-list>
+    </div>
   </van-pull-refresh>
 </template>
-
 <script setup>
-import { ref, reactive, getCurrentInstance } from "vue";
-const { proxy } = getCurrentInstance();
-const pageStatus = reactive({
-  refreshing: false,
-  loading: false,
-  loadingText: "数据加载中,请稍后!",
-  finished: false,
-  finishedText: "",
-  list: [],
-});
-
-const queryData = reactive({
+import { ref, getCurrentInstance, onMounted } from "vue";
+import commonList from "@/components/common-list.vue";
+import { useRoute } from "vue-router";
+const loading = ref(false);
+const router = useRoute();
+const req = ref({
   pageNum: 1,
-  pageSize: 10,
-  keyword: "",
-  type: "2", // 2为手动出库
+  type: "2",
+  keyword: null,
 });
-// 请求列表事件
-const getList = async () => {
-  pageStatus.loading = true;
-  pageStatus.finished = false;
-  const { data } = await proxy.post("/stockJournal/page", queryData);
-  pageStatus.list = [...pageStatus.list, ...data.rows];
-  pageStatus.loading = false;
-  pageStatus.finished = true;
-  if (pageStatus.refreshing) {
-    pageStatus.refreshing = false;
-  }
-};
-// 监听下拉刷新事件
+const finished = ref(false);
+const proxy = getCurrentInstance().proxy;
+const listData = ref([]);
+
+const listConfig = ref([
+  {
+    label: "仓库名称",
+    prop: "warehouseName",
+  },
+  {
+    label: "出库时间",
+    prop: "createTime",
+  },
+  {
+    label: "操作人",
+    prop: "userName",
+  },
+]);
 const onRefresh = () => {
-  pageStatus.refreshing = true;
-  queryData.pageNum = 1;
-  queryData.pageSize = 10;
-  queryData.keyword = "";
-  pageStatus.list = [];
-  getList();
+  req.value.pageNum = 1;
+  finished.value = false;
+  getList("refresh");
 };
-// 监听上拉加载事件
 const onLoad = () => {
-  queryData.pageNum += 1;
   getList();
 };
 
-const handleAdd = () => {
+const onClickLeft = () => proxy.$router.push("/main/working");
+
+const onClickRight = () => {
+  proxy.$router.push("/main/manualOutboundAdd");
+};
+
+const toDtl = (row) => {
+  console.log(row);
   proxy.$router.push({
-    path: "/purchase-sales/addDetails",
+    path: "manualOutboundAdd",
+    query: {
+      id: row.id,
+    },
   });
 };
 
+const getList = (type) => {
+  loading.value = true;
+  proxy
+    .post("/stockJournal/page", req.value)
+    .then((res) => {
+      console.log(req.value);
+      listData.value =
+        type === "refresh"
+          ? res.data.rows
+          : listData.value.concat(res.data.rows);
+      if (req.value.pageNum * 10 >= res.data.total) {
+        finished.value = true;
+      }
+      req.value.pageNum++;
+      loading.value = false;
+    })
+    .catch((err) => {
+      loading.value = false;
+    });
+};
 getList();
 </script>
 
 <style lang="scss" scoped>
 .list {
-  padding: 10px 10px 0 10px;
-  .list-item {
-    .row {
-      display: flex;
-      align-items: center;
-      margin-bottom: 5px;
-      .title {
-        min-width: 70px;
-        color: #999999;
-      }
-      .value {
-        flex: 1;
-      }
-      .icon {
-        width: 40px;
-        text-align: center;
-      }
-    }
-  }
+  min-height: 70vh;
 }
 </style>

+ 253 - 0
src/views/purchase-sales/inbound-outbound/transferWarehouse/add.vue

@@ -0,0 +1,253 @@
+<template>
+  <div class="form">
+    <van-nav-bar
+      title="调仓"
+      left-text="返回"
+      left-arrow
+      @click-left="onClickLeft"
+    >
+    </van-nav-bar>
+    <van-form @submit="onSubmit" label-align="top" style="margin-top: 20px">
+      <van-cell-group inset>
+        <van-field
+          v-model="formData.warehouseName"
+          is-link
+          readonly
+          label="调出仓库"
+          placeholder="选择调出仓库"
+          @click="handleOpen(false)"
+          :rules="[{ required: true, message: '调出仓库不能为空' }]"
+          required
+        />
+        <van-field
+          v-model="formData.toWarehouseName"
+          is-link
+          readonly
+          label="调入仓库"
+          placeholder="选择调入仓库"
+          @click="handleOpen(true)"
+          :rules="[{ required: true, message: '调入仓库不能为空' }]"
+          required
+        />
+        <van-popup v-model:show="typeModal" round position="bottom">
+          <van-picker
+            :columns="columns"
+            @cancel="typeModal = false"
+            @confirm="onConfirm"
+          />
+        </van-popup>
+        <!-- 明细列表 -->
+        <div v-for="(item, index) in list" :key="index">
+          <div class="row">
+            <div class="title">明细{{ index + 1 }}</div>
+            <div
+              class="delete"
+              @click.native="handleDel(index)"
+              v-if="!route.query.id"
+            >
+              <van-icon name="cross" />
+            </div>
+          </div>
+          <van-field
+            v-model="list[index].productName"
+            is-link
+            readonly
+            label="物品名称"
+            placeholder="选择物品名称"
+            @click="handleSelect(index)"
+            :rules="[{ required: true, message: '物品名称不能为空' }]"
+            required
+          />
+
+          <van-field
+            v-model="list[index].quantity"
+            label="出库数量"
+            placeholder="请输入出库数量"
+            :rules="[{ required: true, message: '出库数量不能为空' }]"
+            required
+          />
+        </div>
+        <van-popup v-model:show="typeModalOne" round position="bottom">
+          <van-picker
+            :columns="columnsOne"
+            @cancel="typeModalOne = false"
+            @confirm="(data) => onConfirmOne(data, index)"
+          />
+        </van-popup>
+      </van-cell-group>
+
+      <div style="text-align: center; line-height: 28px" v-if="!route.query.id">
+        <van-button
+          icon="plus"
+          type="primary"
+          plain
+          size="mini"
+          style="margin-top: 10px"
+          @click="handleAddRow"
+          >添加明细</van-button
+        >
+      </div>
+
+      <div style="margin: 16px" v-if="!route.query.id">
+        <van-button round block type="primary" native-type="submit">
+          提交
+        </van-button>
+      </div>
+    </van-form>
+  </div>
+</template>
+
+<script setup>
+import { ref, getCurrentInstance, onMounted } from "vue";
+import { showSuccessToast, showFailToast } from "vant";
+import { useRoute } from "vue-router";
+
+const proxy = getCurrentInstance().proxy;
+const route = useRoute();
+const showPicker = ref(false);
+const typeModal = ref(false);
+const typeModalOne = ref(false);
+let selectIndex = ref(null);
+let isTo = ref(false);
+
+const formData = ref({
+  warehouseId: "",
+  warehouseName: "",
+  toWarehouseId: "",
+  toWarehouseName: "",
+});
+const list = ref([]);
+const handleAddRow = () => {
+  list.value.push({
+    productId: "",
+    productName: "",
+    quantity: "",
+  });
+};
+const getDetails = (id) => {
+  proxy.post("/stockJournal/detail", { id }).then((res) => {
+    console.log(res, "www");
+    formData.value = res.data;
+    list.value = res.data.list.map((x) => ({
+      productId: x.productId,
+      productName: x.productName,
+      quantity: x.quantity,
+    }));
+  });
+};
+
+const getDict = () => {
+  proxy.post("/warehouse/page", { pageNum: 1, pageSize: 9999 }).then((res) => {
+    columns.value = res.data.rows.map((item) => {
+      return {
+        text: item.name,
+        value: item.id,
+      };
+    });
+    // formData.value.warehouseName = formData.value.warehouseId
+    //   ? columns.value.find((item) => item.value == formData.value.warehouseId).name
+    //   : null;
+  });
+
+  proxy
+    .post("/productInfo/page", { pageNum: 1, pageSize: 9999, definition: "1" })
+    .then((res) => {
+      columnsOne.value = res.data.rows.map((item) => {
+        return {
+          text: item.name,
+          value: item.id,
+        };
+      });
+      // formData.value.warehouseName = formData.value.warehouseId
+      //   ? columns.value.find((item) => item.value == formData.value.warehouseId).name
+      //   : null;
+    });
+};
+
+const columns = ref([]);
+const columnsOne = ref([]);
+
+const onConfirm = ({ selectedOptions }) => {
+  if (isTo.value) {
+    formData.value.toWarehouseId = selectedOptions[0].value;
+    formData.value.toWarehouseName = selectedOptions[0].text;
+    if (formData.value.toWarehouseId === formData.value.warehouseId) {
+      formData.value.toWarehouseId = "";
+      formData.value.toWarehouseName = "";
+      return showFailToast("仓库不可相同!");
+    }
+  } else {
+    formData.value.warehouseId = selectedOptions[0].value;
+    formData.value.warehouseName = selectedOptions[0].text;
+    if (formData.value.toWarehouseId === formData.value.warehouseId) {
+      formData.value.warehouseId = "";
+      formData.value.warehouseName = "";
+      return showFailToast("仓库不可相同!");
+    }
+  }
+
+  typeModal.value = false;
+};
+
+const onConfirmOne = ({ selectedOptions }, index) => {
+  list.value[selectIndex.value].productId = selectedOptions[0].value;
+  list.value[selectIndex.value].productName = selectedOptions[0].text;
+  typeModalOne.value = false;
+};
+
+const handleSelect = (index) => {
+  selectIndex.value = index;
+  typeModalOne.value = true;
+};
+
+const handleOpen = (flag) => {
+  isTo.value = flag;
+  typeModal.value = true;
+};
+
+const handleDel = (index) => {
+  list.value.splice(index, 1);
+};
+
+const onClickLeft = () => history.back();
+
+const onSubmit = () => {
+  if (!list.value.length > 0) return showFailToast("请添加明细!");
+  formData.value.list = list.value.map((x) => ({
+    productId: x.productId,
+    quantity: x.quantity,
+  }));
+  // formData.value.type = "2";
+  proxy.post("/stock/stockTransfer", formData.value).then(
+    (res) => {
+      setTimeout(() => {
+        showSuccessToast("调仓成功");
+        proxy.$router.push("/main/transferWarehouse");
+      }, 500);
+    },
+    (err) => {
+      return showFailToast(err.message);
+    }
+  );
+};
+onMounted(() => {
+  getDetails(route.query.id);
+  getDict();
+});
+</script>
+<style lang="scss" scoped>
+.row {
+  display: flex;
+  padding: 5px 10px 0 10px;
+  justify-content: space-between;
+  align-items: center;
+  .title {
+    flex: 1;
+  }
+  .delete {
+    width: 20px;
+    cursor: pointer;
+    text-align: center;
+  }
+}
+</style>

+ 115 - 0
src/views/purchase-sales/inbound-outbound/transferWarehouse/index.vue

@@ -0,0 +1,115 @@
+<template>
+  <van-nav-bar
+    title="调仓"
+    left-text=""
+    left-arrow
+    @click-left="onClickLeft"
+    @click-right="onClickRight"
+  >
+    <template #right> 添加 </template>
+  </van-nav-bar>
+  <van-search
+    v-model="req.keyword"
+    placeholder="请输入搜索关键词"
+    @search="onRefresh"
+  />
+  <van-pull-refresh v-model="loading" @refresh="onRefresh">
+    <div class="list">
+      <van-list
+        v-model:loading="loading"
+        :finished="finished"
+        finished-text="没有更多了"
+        @load="onLoad"
+        style="margin-bottom: 60px"
+      >
+        <commonList
+          :data="listData"
+          @onClick="toDtl"
+          :config="listConfig"
+        ></commonList>
+      </van-list>
+    </div>
+  </van-pull-refresh>
+</template>
+<script setup>
+import { ref, getCurrentInstance, onMounted } from "vue";
+import commonList from "@/components/common-list.vue";
+import { useRoute } from "vue-router";
+const loading = ref(false);
+const router = useRoute();
+const req = ref({
+  pageNum: 1,
+  type: "3",
+  keyword: null,
+});
+const finished = ref(false);
+const proxy = getCurrentInstance().proxy;
+const listData = ref([]);
+
+const listConfig = ref([
+  {
+    label: "调出仓库",
+    prop: "warehouseName",
+  },
+  {
+    label: "调入仓库",
+    prop: "toWarehouseName",
+  },
+  {
+    label: "操作人",
+    prop: "userName",
+  },
+]);
+const onRefresh = () => {
+  req.value.pageNum = 1;
+  finished.value = false;
+  getList("refresh");
+};
+const onLoad = () => {
+  getList();
+};
+
+const onClickLeft = () => proxy.$router.push("/main/working");
+
+const onClickRight = () => {
+  proxy.$router.push("/main/sendTransferWarehouse");
+};
+
+const toDtl = (row) => {
+  console.log(row);
+  proxy.$router.push({
+    path: "sendTransferWarehouse",
+    query: {
+      id: row.id,
+    },
+  });
+};
+
+const getList = (type) => {
+  loading.value = true;
+  proxy
+    .post("/stockJournal/page", req.value)
+    .then((res) => {
+      console.log(req.value);
+      listData.value =
+        type === "refresh"
+          ? res.data.rows
+          : listData.value.concat(res.data.rows);
+      if (req.value.pageNum * 10 >= res.data.total) {
+        finished.value = true;
+      }
+      req.value.pageNum++;
+      loading.value = false;
+    })
+    .catch((err) => {
+      loading.value = false;
+    });
+};
+getList();
+</script>
+
+<style lang="scss" scoped>
+.list {
+  min-height: 70vh;
+}
+</style>

+ 138 - 0
src/views/purchase-sales/inventory-management/inventoryQuery/index.vue

@@ -0,0 +1,138 @@
+<template>
+  <van-nav-bar
+    title="库存查询"
+    left-text=""
+    left-arrow
+    @click-left="onClickLeft"
+  >
+  </van-nav-bar>
+  <van-search
+    v-model="req.keyword"
+    placeholder="请输入搜索关键词"
+    @search="onRefresh"
+  />
+  <van-tabs v-model:active="active" @change="handleChangeTab">
+    <van-tab title="全部" name="all"></van-tab>
+    <van-tab
+      v-for="(item, index) in warehouseData"
+      :title="item.name"
+      :name="item.id"
+    >
+    </van-tab>
+  </van-tabs>
+  <van-pull-refresh v-model="loading" @refresh="onRefresh">
+    <div class="list">
+      <van-list
+        v-model:loading="loading"
+        :finished="finished"
+        finished-text="没有更多了"
+        @load="onLoad"
+        style="margin-bottom: 60px"
+      >
+        <commonList
+          :data="listData"
+          @onClick="toDtl"
+          :config="listConfig"
+        ></commonList>
+      </van-list>
+    </div>
+  </van-pull-refresh>
+</template>
+<script setup>
+import { ref, getCurrentInstance, onMounted } from "vue";
+import commonList from "@/components/common-list.vue";
+import { useRoute } from "vue-router";
+const loading = ref(false);
+const router = useRoute();
+const req = ref({
+  pageNum: 1,
+  id: "",
+  keyword: null,
+});
+const finished = ref(false);
+const proxy = getCurrentInstance().proxy;
+const listData = ref([]);
+const warehouseData = ref([]);
+
+const active = ref("all");
+const listConfig = ref([
+  {
+    label: "物品类型",
+    prop: "type",
+  },
+  {
+    label: "物品名称",
+    prop: "productName",
+  },
+  {
+    label: "库存数量",
+    prop: "quantity",
+  },
+]);
+const onRefresh = () => {
+  req.value.pageNum = 1;
+  finished.value = false;
+  getList("refresh");
+};
+const onLoad = () => {
+  getList();
+};
+
+const onClickLeft = () => proxy.$router.push("/main/working");
+
+const onClickRight = () => {
+  proxy.$router.push("/main/manualInboundAdd");
+};
+
+const toDtl = (row) => {
+  proxy.$router.push({
+    path: "outInList",
+    query: {
+      productId: row.productId,
+      warehouseId: row.warehouseId,
+    },
+  });
+};
+
+const getList = (type) => {
+  loading.value = true;
+  proxy
+    .post("/stock/page", req.value)
+    .then((res) => {
+      listData.value =
+        type === "refresh"
+          ? res.data.rows
+          : listData.value.concat(res.data.rows);
+      if (req.value.pageNum * 10 >= res.data.total) {
+        finished.value = true;
+      }
+      req.value.pageNum++;
+      loading.value = false;
+      console.log(listData.value, "wssa");
+    })
+    .catch((err) => {
+      loading.value = false;
+    });
+};
+
+const getWarehouseData = () => {
+  proxy.post("/warehouse/page", { pageNum: 1, pageSize: 9999 }).then((res) => {
+    warehouseData.value = res.data.rows;
+  });
+};
+
+const handleChangeTab = () => {
+  req.value.id = active.value === "all" ? "" : active.value;
+  req.value.pageNum = 1;
+  listData.value = [];
+  getList();
+};
+getWarehouseData();
+getList();
+</script>
+
+<style lang="scss" scoped>
+.list {
+  min-height: 70vh;
+}
+</style>

+ 202 - 0
src/views/purchase-sales/inventory-management/outInList/index.vue

@@ -0,0 +1,202 @@
+<template>
+  <van-nav-bar
+    title="出入库流水"
+    left-text=""
+    left-arrow
+    @click-left="onClickLeft"
+  >
+  </van-nav-bar>
+  <van-search
+    v-model="req.keyword"
+    placeholder="请输入搜索关键词"
+    @search="onRefresh"
+  />
+  <van-tabs v-model:active="active" @change="handleChangeTab">
+    <van-tab title="全部" name="all"></van-tab>
+    <van-tab title="入库" name="1"></van-tab>
+    <van-tab title="出库" name="2"></van-tab>
+
+    <!-- <van-tab
+      v-for="(item, index) in warehouseData"
+      :title="item.name"
+      :name="item.id"
+    >
+    </van-tab> -->
+  </van-tabs>
+  <van-pull-refresh v-model="loading" @refresh="onRefresh">
+    <div class="list">
+      <van-list
+        v-model:loading="loading"
+        :finished="finished"
+        finished-text="没有更多了"
+        @load="onLoad"
+        style="margin-bottom: 60px"
+      >
+        <div style="margin-top: 10px">
+          <div v-for="(item, index) in listData" :key="item.id" class="item">
+            <div class="row">
+              <div class="left">操作类型</div>
+              <div class="center">
+                {{ item.type }}
+              </div>
+              <div class="right">
+                {{ item.createTime }}
+              </div>
+            </div>
+            <div class="row">
+              <div class="left">仓库名称</div>
+              <div class="center">
+                {{ item.warehouseName }}
+              </div>
+            </div>
+            <div class="row">
+              <div class="left">物品名称</div>
+              <div class="center">
+                {{ item.productName }}
+              </div>
+            </div>
+            <div class="row">
+              <div class="left">操作数量</div>
+              <div class="center">
+                {{ item.quantity }}
+              </div>
+            </div>
+          </div>
+        </div>
+      </van-list>
+    </div>
+  </van-pull-refresh>
+</template>
+<script setup>
+import { ref, getCurrentInstance, onMounted } from "vue";
+import commonList from "@/components/common-list.vue";
+import { useRoute } from "vue-router";
+const loading = ref(false);
+const router = useRoute();
+const route = useRoute();
+const req = ref({
+  pageNum: 1,
+  keyword: null,
+  type: "",
+  warehouseId: "",
+  productId: "",
+});
+const finished = ref(false);
+const proxy = getCurrentInstance().proxy;
+const listData = ref([]);
+const warehouseData = ref([]);
+
+const active = ref("all");
+const listConfig = ref([
+  {
+    label: "物品类型",
+    prop: "type",
+  },
+  {
+    label: "物品名称",
+    prop: "productName",
+  },
+  {
+    label: "库存数量",
+    prop: "quantity",
+  },
+]);
+const onRefresh = () => {
+  req.value.pageNum = 1;
+  finished.value = false;
+  getList("refresh");
+};
+const onLoad = () => {
+  getList();
+};
+
+const onClickLeft = () => {
+  if (route.query.productId || route.query.warehouseId) {
+    history.back();
+  } else {
+    proxy.$router.push("/main/working");
+  }
+};
+
+const onClickRight = () => {
+  proxy.$router.push("/main/manualInboundAdd");
+};
+
+const toDtl = (row) => {
+  proxy.$router.push({
+    path: "manualInboundAdd",
+    query: {
+      id: row.id,
+    },
+  });
+};
+
+const getList = (type) => {
+  loading.value = true;
+  proxy
+    .post("/stockJournalDetails/page", req.value)
+    .then((res) => {
+      listData.value =
+        type === "refresh"
+          ? res.data.rows
+          : listData.value.concat(res.data.rows);
+      if (req.value.pageNum * 10 >= res.data.total) {
+        finished.value = true;
+      }
+      req.value.pageNum++;
+      loading.value = false;
+      console.log(listData.value, "wssa");
+    })
+    .catch((err) => {
+      loading.value = false;
+    });
+};
+
+const getWarehouseData = () => {
+  proxy.post("/warehouse/page", { pageNum: 1, pageSize: 9999 }).then((res) => {
+    warehouseData.value = res.data.rows;
+  });
+};
+
+const handleChangeTab = () => {
+  req.value.type = active.value === "all" ? "" : active.value;
+  req.value.pageNum = 1;
+  listData.value = [];
+  getList();
+};
+// getWarehouseData();
+
+onMounted(() => {
+  req.value.productId = route.query.productId ? route.query.productId : "";
+  req.value.warehouseId = route.query.warehouseId
+    ? route.query.warehouseId
+    : "";
+  listData.value = [];
+  getList();
+});
+</script>
+
+<style lang="scss" scoped>
+.list {
+  min-height: 70vh;
+}
+.item {
+  padding: 10px 10px 0;
+  border-bottom: 1px solid #dddddd;
+  background: #fff;
+  .row {
+    display: flex;
+    margin-bottom: 6px;
+    .left {
+      width: 70px;
+    }
+    .center {
+      flex: 1;
+    }
+    .left,
+    .right {
+      color: #999999;
+    }
+  }
+}
+</style>