Browse Source

feat: ✨ 完成入库管理,更新ERP logo

@sun-chaoqun 1 year ago
parent
commit
885d7607c3

+ 2 - 1
index.html

@@ -3,7 +3,8 @@
 
 <head>
   <meta charset="UTF-8" />
-  <link rel="icon" type="image/svg+xml" href="/vite.svg" />
+  <!-- <link rel="icon" type="image/svg+xml" href="/vite.svg" /> -->
+  <link rel="icon" type="image/png" href="/icon.png" />
   <meta name="viewport" content="width=device-width, initial-scale=1.0" />
   <title><%- title %></title>
 </head>

BIN
public/icon.png


+ 9 - 5
src/api/index.ts

@@ -35,12 +35,16 @@ class RequestHttp {
      */
     this.service.interceptors.request.use(
       (config: InternalAxiosRequestConfig) => {
+        const globalStore = GlobalStore()
         // 开始loading
-        loadingInstance = ElLoading.service({
-          lock: true,
-          text: 'Loading',
-          background: 'rgba(0, 0, 0, 0.7)'
-        })
+        if (!globalStore.GET_isloading) {
+          loadingInstance = ElLoading.service({
+            lock: true,
+            text: 'Loading',
+            background: 'rgba(0, 0, 0, 0.7)'
+          })
+        }
+
         // 加入token
         // if (globalStore.GET_User_tokey) {
         //   config.headers['User_tokey'] = globalStore.GET_User_tokey

BIN
src/assets/images/icon.png


BIN
src/assets/images/logo.png


+ 20 - 0
src/layouts/Menu/Logo.vue

@@ -0,0 +1,20 @@
+<template>
+  <div class="logo">
+    <Transition enter-active-class="animate__animated animate__rotateIn" appear mode="out-in">
+      <img src="../../assets/images/logo.png" />
+    </Transition>
+  </div>
+</template>
+
+<script setup lang="ts"></script>
+<!-- animate__rotateIn -->
+<style scoped lang="scss">
+.logo {
+  width: 100%;
+  padding: 5px 15px 5px 20px;
+  transition: width 0.2s;
+  img {
+    width: 100%;
+  }
+}
+</style>

+ 10 - 1
src/router/modules/staticRouter.ts

@@ -1,4 +1,5 @@
 import { RouteRecordRaw } from 'vue-router'
+import { h, defineComponent } from 'vue'
 export const staticRouter: RouteRecordRaw[] = [
   {
     path: '/',
@@ -64,7 +65,7 @@ export const staticRouter: RouteRecordRaw[] = [
             }
           },
           {
-            path: '/contractDetail/:id',
+            path: '/contractDetail/:id/:type',
             name: 'ContractDetail',
             component: () => import('@/views/storehouse/sales/ContractDetail.vue'),
             meta: {
@@ -106,6 +107,14 @@ export const staticRouter: RouteRecordRaw[] = [
             meta: {
               title: '入库管理'
             }
+          },
+          {
+            path: '/inStorageDetail/:id',
+            name: 'InStorageDetail',
+            component: () => import('@/views/storehouse/inventory/InStorageDetail.vue'),
+            meta: {
+              title: '入库详情'
+            }
           }
         ]
       },

+ 7 - 1
src/stores/index.ts

@@ -9,7 +9,7 @@ import { flatMenuListGet, AddRouterMeta, getAllBreadcrumbList } from '@/utils/co
 export const GlobalStore = defineStore({
   id: 'GlobalState',
   state: (): GlobalState => ({
-    loading: false,
+    isloading: false,
     isCollapse: false,
     breadcrumb: [],
     userInfo: JSON.parse(sessionStorage.getItem('User_info') as any) || {},
@@ -23,6 +23,7 @@ export const GlobalStore = defineStore({
     flatMenu: [] // 扁平化的数组
   }),
   getters: {
+    GET_isloading: state => state.isloading,
     GET_User_tokey: state => state.User_tokey,
     GET_Dept_List: state => state.UserDeptList,
     GET_isCollapse: state => state.isCollapse,
@@ -32,6 +33,11 @@ export const GlobalStore = defineStore({
     GET_Flat_Menu: state => state.flatMenu
   },
   actions: {
+    SET_isloading(payload: boolean) {
+      if (typeof payload === 'boolean') {
+        this.isloading = payload
+      }
+    },
     SET_User_Tokey(payload: string) {
       if (typeof payload === 'string') {
         this.User_tokey = payload

+ 1 - 1
src/stores/interface/index.ts

@@ -1,6 +1,6 @@
 /* GlobalState */
 export interface GlobalState {
-  loading: boolean
+  isloading: boolean
   breadcrumb: string[]
   isCollapse: boolean
   User_tokey: string

+ 18 - 12
src/views/Index.vue

@@ -5,6 +5,7 @@ import Main from '@/layouts/Main/index.vue'
 import Header from '@/layouts/Header/index.vue'
 import { GlobalStore } from '@/stores/index'
 import { useRoute } from 'vue-router'
+import Logo from '@/layouts/Menu/Logo.vue'
 
 const globalStore = GlobalStore()
 
@@ -23,17 +24,20 @@ const defaultActive = ref<string>(route.path)
     <el-aside>
       <div class="menu" :style="{ width: globalStore.GET_isCollapse ? '65px' : '210px' }">
         <el-scrollbar>
-          <el-menu
-            :default-active="defaultActive"
-            :collapse="globalStore.GET_isCollapse"
-            :collapse-transition="false"
-            :unique-opened="true"
-            active-text-color="#ffd04b"
-            text-color="#fff"
-            background-color="rgba(18, 21, 39, 0.86)"
-          >
-            <SubMenu :menu-list="routerList"></SubMenu>
-          </el-menu>
+          <div>
+            <Logo />
+            <el-menu
+              :default-active="defaultActive"
+              :collapse="globalStore.GET_isCollapse"
+              :collapse-transition="false"
+              :unique-opened="true"
+              active-text-color="#ffd04b"
+              text-color="#fff"
+              background-color="rgba(18, 21, 39, 0.86)"
+            >
+              <SubMenu :menu-list="routerList"></SubMenu>
+            </el-menu>
+          </div>
         </el-scrollbar>
       </div>
     </el-aside>
@@ -58,7 +62,7 @@ const defaultActive = ref<string>(route.path)
   .el-aside {
     width: auto;
     overflow: inherit;
-    background-color: rgba(18, 21, 39, 0.86);
+    background-color: rgba(18, 21, 39);
     border-right: 1px solid var(--el-border-color);
     transition: all 0.3s ease;
     .menu {
@@ -66,9 +70,11 @@ const defaultActive = ref<string>(route.path)
       flex-direction: column;
       height: 100%;
       transition: all 0.3s ease;
+      // background-color: rgba(18, 21, 39, 0.86);
       .el-menu {
         overflow-x: hidden;
         border-right: none;
+        // background-color: rgba(18, 21, 39, 0.86);
       }
     }
   }

+ 26 - 21
src/views/storehouse/inventory/InStorage.vue

@@ -1,13 +1,15 @@
 <script setup lang="ts">
-import { ref, reactive, onMounted, computed } from 'vue'
+import { useRouter } from 'vue-router'
 import { GlobalStore } from '@/stores/index'
+import { View } from '@element-plus/icons-vue'
+import InStorageForm from './InStorageForm.vue'
+import { ref, reactive, onMounted } from 'vue'
 import Dialog from '@/components/dialog/Dialog.vue'
 import TableBase from '@/components/TableBase/index.vue'
 import type { ColumnProps } from '@/components/TableBase/interface/index'
 import { Storehouse_StockIn_List, Storehouse_Depot_List } from '@/api/storehouse/index'
-import { View } from '@element-plus/icons-vue'
-import InStorageForm from './InStorageForm.vue'
 
+const router = useRouter()
 const globalStore = GlobalStore()
 const TableRef = ref<InstanceType<typeof TableBase> | null>(null)
 
@@ -20,7 +22,9 @@ const columns: ColumnProps[] = [
   { prop: 'operation', label: '操作', width: 260, fixed: 'right' }
 ]
 
-// 查看图片
+/**
+ * 查看图片
+ */
 const url = ref('')
 const srcList = ref<any[]>([])
 const dialog = ref<InstanceType<typeof Dialog> | null>(null)
@@ -30,9 +34,15 @@ const previewImg = (str: string) => {
   url.value = str
   srcList.value.push(str)
 }
+/**
+ * 查看详情
+ */
+const preview = (id: string) => {
+  router.push({ name: 'InStorageDetail', params: { id } })
+}
 
 // 搜索
-const T_date = ref('')
+const T_date = ref<string[]>([])
 
 const initParam = reactive({
   User_tokey: globalStore.GET_User_tokey,
@@ -41,25 +51,20 @@ const initParam = reactive({
   T_depot_id: ''
 })
 
-// const date = computed(()=>{
-//   return { T_end_date: T_date[1] }
-// })
-
 const searchHandle = () => {
-  console.log(initParam)
-  // initParam.T_end_date = initParam.T_date[1]
-  // initParam.T_start_date = initParam.T_date[0]
+  T_date.value && (initParam.T_end_date = T_date.value[1])
+  T_date.value && (initParam.T_start_date = T_date.value[0])
   TableRef.value?.searchTable()
 }
-
-const openInStorageFormDrawer = (type: string, row?: any) => {
-  InStorageFormRef.value?.openDrawer(type, row)
-}
+/**
+ * 添加入库
+ */
+const openInStorageFormDrawer = () => InStorageFormRef.value?.openDrawer()
 
 // 拿到仓库列表
 interface ItemType {
   T_name: string
-  T_State: number
+  Id: number
 }
 const options = ref<ItemType[]>()
 const getDepotList = async () => {
@@ -92,12 +97,12 @@ onMounted(() => {
             <el-col :xl="6" :lg="7" :md="9" style="display: flex">
               <span class="inline-flex items-center">仓库:</span>
               <el-select v-model="initParam.T_depot_id" clearable placeholder="请选择仓库~">
-                <el-option v-for="item in options" :key="item.T_State" :label="item.T_name" :value="item.T_State" />
+                <el-option v-for="item in options" :key="item.Id" :label="item.T_name" :value="item.Id" />
               </el-select>
               <el-button type="primary" @click="searchHandle">搜索</el-button>
             </el-col>
             <el-col :xl="12" :lg="8" :md="4" class="btn"
-              ><el-button type="primary" @click="openInStorageFormDrawer('new')">入库</el-button></el-col
+              ><el-button type="primary" @click="openInStorageFormDrawer">入库</el-button></el-col
             >
           </el-row>
         </div>
@@ -116,13 +121,13 @@ onMounted(() => {
         />
       </template>
       <template #right="{ row }">
-        <el-button link type="success" size="small" :icon="View">详情</el-button>
+        <el-button link type="success" size="small" :icon="View" @click="preview(row.T_number)">详情</el-button>
       </template>
     </TableBase>
     <Dialog ref="dialog" width="50%">
       <el-image :src="url" :zoom-rate="1.2" :preview-src-list="srcList" fit="cover" />
     </Dialog>
-    <InStorageForm ref="InStorageFormRef" :options="options" />
+    <InStorageForm ref="InStorageFormRef" :options="options" @onUpdateList="searchHandle" />
   </div>
 </template>
 

+ 154 - 0
src/views/storehouse/inventory/InStorageDetail.vue

@@ -0,0 +1,154 @@
+<script setup lang="ts">
+import { ref, onMounted } from 'vue'
+import { GlobalStore } from '@/stores/index'
+import { useRoute, useRouter } from 'vue-router'
+import { Storehouse_StockIn_Get } from '@/api/storehouse/index'
+
+interface InfoType {
+  Id: number
+  T_depot_name: string
+  T_date: string
+  T_number: string
+  T_remark: string
+  T_submit: string
+  T_submit_name: string
+}
+
+const info = ref<InfoType | undefined>()
+const globalStore = GlobalStore()
+const route = useRoute()
+const router = useRouter()
+
+const columns = [
+  { type: 'index', label: '序号', width: 80, align: 'center ' },
+  { label: '产品图片', prop: 'T_product_img', align: 'center ', name: 'T_product_img' },
+  { label: '产品名称', prop: 'T_product_name', align: 'center ' },
+  { label: '产品分类', prop: 'T_product_class_name', align: 'center ' },
+  { label: '产品型号', prop: 'T_product_model', align: 'center ', name: 'T_product_model' },
+  { label: '产品规格', prop: 'T_product_spec', align: 'center ' },
+  { label: '是否关联SN', prop: 'T_product_relation_sn', align: 'center ', width: 120, name: 'T_product_relation_sn' },
+  { label: '数量', prop: 'T_num', align: 'center ' },
+  { prop: 'operation', label: '关联设备', width: 100, fixed: 'right', align: 'center ' }
+]
+const getStorehouseContractGet = async () => {
+  const res: any = await Storehouse_StockIn_Get({ User_tokey: globalStore.GET_User_tokey, T_number: route.params.id })
+  if (res.Code === 200) {
+    info.value = res.Data
+    tableData.value = res.Data.T_Product
+  }
+}
+
+const tableData = ref<any[]>([])
+
+onMounted(() => {
+  getStorehouseContractGet()
+})
+</script>
+<template>
+  <div class="contract-detail">
+    <div class="info">
+      <h1>入库详情</h1>
+      <el-divider />
+      <div class="content">
+        <el-row>
+          <el-col :xs="8" :sm="6" :md="4" :lg="3" :xl="2"><span>入库单号:</span></el-col>
+          <el-col :xs="11" :sm="9" :md="7" :lg="6" :xl="5"
+            ><span>{{ info?.T_number! }}</span></el-col
+          >
+        </el-row>
+        <el-row>
+          <el-col :xs="8" :sm="6" :md="4" :lg="3" :xl="2"> <span>入库仓库:</span></el-col>
+          <el-col :xs="11" :sm="9" :md="7" :lg="6" :xl="5"
+            ><span>{{ info?.T_depot_name! }}</span></el-col
+          >
+        </el-row>
+        <el-row>
+          <el-col :xs="8" :sm="6" :md="4" :lg="3" :xl="2"> <span>入库日期:</span></el-col>
+          <el-col :xs="11" :sm="9" :md="7" :lg="6" :xl="5"
+            ><span>{{ info?.T_date! }}</span></el-col
+          >
+        </el-row>
+        <el-row>
+          <el-col :xs="8" :sm="6" :md="4" :lg="3" :xl="2"><span>入库明细:</span></el-col>
+          <el-col :span="21">
+            <el-table
+              :data="tableData"
+              style="width: 100%"
+              border
+              stripe
+              :header-cell-style="{
+                background: '#909399',
+                height: '50px',
+                color: '#fff'
+              }"
+            >
+              <template v-for="item in columns" :key="item.prop">
+                <el-table-column v-bind="item" v-if="item.fixed !== 'right'">
+                  <template #default="{ row }" v-if="item.prop === item.name">
+                    <span v-if="item.prop === 'T_product_relation_sn'">
+                      <el-tag v-if="row.T_product_relation_sn === 1" effect="dark">是</el-tag>
+                      <el-tag v-else type="success" effect="dark">否</el-tag>
+                    </span>
+                    <el-image
+                      v-if="item.prop === 'T_product_img'"
+                      style="height: 50px"
+                      :src="row.T_product_img"
+                      :preview-src-list="srcList"
+                      fit="cover"
+                    />
+                    <el-tooltip
+                      v-if="item.prop === 'T_product_model'"
+                      effect="dark"
+                      :content="row.T_product_model"
+                      placement="bottom"
+                    >
+                      {{ row.T_product_model }}
+                    </el-tooltip>
+                  </template>
+                </el-table-column>
+                <el-table-column v-bind="item" v-if="item.fixed === 'right'">
+                  <template #default="{ row }">
+                    <el-button type="primary" :disabled="!row.T_product_relation_sn">查看</el-button>
+                  </template>
+                </el-table-column>
+              </template>
+            </el-table>
+          </el-col>
+        </el-row>
+        <el-row>
+          <el-col :xs="8" :sm="6" :md="4" :lg="3" :xl="2"><span>备注:</span></el-col>
+          <el-col :xs="11" :sm="9" :md="7" :lg="6" :xl="5"
+            ><span>{{ info?.T_remark! }}</span></el-col
+          >
+        </el-row>
+      </div>
+      <el-divider />
+      <div class="submit">
+        <el-button type="primary" round @click="router.back()">返回</el-button>
+      </div>
+    </div>
+  </div>
+</template>
+
+<style scoped lang="scss">
+.contract-detail {
+  height: 100%;
+  font-weight: bold;
+  color: var(--el-text-color-secondary);
+  .info {
+    height: 100%;
+    padding: 20px;
+    & .content {
+      height: calc(100% - 72px - 25px - 40px);
+      overflow-y: scroll;
+      .el-row {
+        margin-bottom: 16px;
+      }
+    }
+    .submit {
+      display: flex;
+      justify-content: center;
+    }
+  }
+}
+</style>

+ 93 - 289
src/views/storehouse/inventory/InStorageForm.vue

@@ -1,41 +1,14 @@
 <script setup lang="ts">
+import { ElMessage } from 'element-plus'
+import InStorageSn from './InStorageSn.vue'
 import { ref, reactive, nextTick } from 'vue'
-import Drawer from '@/components/Drawer/index.vue'
-import { Delete, CirclePlus } from '@element-plus/icons-vue'
 import { GlobalStore } from '@/stores/index'
-import { ElMessage } from 'element-plus'
-import {
-  Storehouse_StockIn_Add,
-  Storehouse_Product_List,
-  Storehouse_ProductClass_List,
-  Storehouse_Product_Model_List,
-  Storehouse_Product_Name_List,
-  Storehouse_Contract_Product_List
-} from '@/api/storehouse/index'
+import Drawer from '@/components/Drawer/index.vue'
+import InStorageProduct from './InStorageProduct.vue'
 import type { FormInstance, FormRules } from 'element-plus'
-import { default as vElTableInfiniteScroll } from 'el-table-infinite-scroll'
-import InStorageSn from './InStorageSn.vue'
-
-const isNew = ref(true)
-const selectTable = ref()
-let selectProductData: any[] = []
-const globalStore = GlobalStore()
-const formLabelWidth = ref('120px')
-const ruleFormRef = ref<FormInstance>()
-const drawerRef = ref<InstanceType<typeof Drawer> | null>(null)
-const drawerSnRef = ref<InstanceType<typeof InStorageSn> | null>(null)
-const drawerProductRef = ref<InstanceType<typeof Drawer> | null>(null)
+import { Delete, CirclePlus } from '@element-plus/icons-vue'
+import { Storehouse_StockIn_Add, Storehouse_ProductClass_List } from '@/api/storehouse/index'
 
-const classOptions = ref<any[]>([])
-const modelOptions = ref<any[]>([])
-const initParam = reactive({
-  User_tokey: globalStore.GET_User_tokey,
-  T_name: '',
-  T_model: '',
-  T_class: '',
-  page: 0,
-  page_z: 20
-})
 type Fn = () => void
 interface FormType {
   T_number: string
@@ -44,6 +17,16 @@ interface FormType {
   T_date: string
   T_remark: string
 }
+
+const tableData = ref<any[]>([])
+const globalStore = GlobalStore()
+const formLabelWidth = ref('120px')
+const ruleFormRef = ref<FormInstance>()
+const drawerRef = ref<InstanceType<typeof Drawer> | null>(null)
+const drawerSnRef = ref<InstanceType<typeof InStorageSn> | null>(null)
+const drawerProductRef = ref<InstanceType<typeof InStorageProduct> | null>(null)
+const classOptions = ref<any[]>([])
+
 const form = reactive<FormType>({
   T_number: '',
   T_depot_id: '',
@@ -68,7 +51,6 @@ const rules = reactive<FormRules>({
   T_date: [{ required: true, message: '请选择入库日期', trigger: 'blur' }]
 })
 
-const tableData = ref<any[]>([])
 const columns = [
   { type: 'index', label: '序号', width: 80, align: 'center ' },
   { label: '产品图片', prop: 'T_img', align: 'center ', name: 'T_img' },
@@ -82,73 +64,66 @@ const columns = [
   { prop: 'operation', label: '操作', width: 80, fixed: 'right' }
 ]
 
-const productColumns = [
-  { type: 'selection', width: 80 },
-  { prop: 'T_img', label: '产品图片', name: 'T_img' },
-  { prop: 'T_name', label: '产品名称' },
-  { prop: 'T_class_name', label: '产品分类' },
-  { prop: 'T_model', label: '产品型号', ellipsis: true },
-  { prop: 'T_spec', label: '产品规格' },
-  { prop: 'T_relation_sn', label: '关联SN', name: 'T_relation_sn' },
-  { prop: 'T_remark', label: '备注', ellipsis: true }
-]
-
 const countBlurHandle = () => {
   form.T_product = tableData.value.map(item => {
-    if (!item.count) return undefined
-    return `${item.Id},${item.count}`
+    if (!item.count && item.T_relation_sn !== 1) return undefined
+    return `${item.Id},${item.count}|`
   })
 }
 const getDeviceSnToProduct = () => {
   const DeviceSnData: any = drawerSnRef.value?.getDeviceSn()
-  // if (!DeviceSnData.size) {
-  //   const index = tableData.value.findIndex((item: any) => item.T_relation_sn === 1)
-  //   if (index !== -1) return [null]
-  //   else {
-  //     return tableData.value.map(item => {
-  //       if (!item.count) return undefined
-  //       return `${item.Id},${item.count}`
-  //     })
-  //   }
-  // }
-  if (!DeviceSnData.size) return [null]
-  if (!tableData.value.every((item: any) => item.count)) return [undefined]
+  const isEmpty = determineSNorCount(DeviceSnData)
+  if (isEmpty && isEmpty === 'count') return [undefined]
+  if (isEmpty && isEmpty === 'sn') return [null]
+
   return tableData.value.map((item: any) => {
     let product: any = ''
-    DeviceSnData?.forEach((value: any, key: number) => {
-      // T_relation_sn === 1
-      if (item.Id === key) {
-        if (item.T_relation_sn === 1 && value.length > 0) {
+    if (item.T_relation_sn === 1) {
+      DeviceSnData?.forEach((value: any, key: number) => {
+        if (item.Id === key) {
           let str = ''
-          value.forEach((snObj: any) => (str += snObj.sn + ','))
+          value.forEach(
+            (snObj: any, index: number, arr: any[]) => (str += `${snObj.sn}${index === arr.length - 1 ? '' : ','}`)
+          )
           product = `${item.Id}-${item.count}-${str}`
-        } else {
-          product = null
-        }
-      } else {
-        if (item.count) {
-          product = `${item.Id}-${item.count}-`
-        } else {
-          product = undefined
         }
-      }
-    })
+      })
+    } else {
+      product = `${item.Id}-${item.count}-`
+    }
     return product + '|'
   })
 }
+/**
+ * 判断sn or 数量是否为空
+ */
+const determineSNorCount = (DeviceSnData: any) => {
+  for (const item of tableData.value) {
+    if (!item.count && item.T_relation_sn !== 1) return 'count'
+    if (item.T_relation_sn === 1 && !DeviceSnData.get(item.Id) && !DeviceSnData.size) return 'sn'
+  }
+  return false
+}
 
 const AddInStorage = (formEl: FormInstance | undefined) => {
   if (!formEl) return
   form.T_product = getDeviceSnToProduct()
-
   formEl.validate(async valid => {
     if (valid) {
-      const res = await Storehouse_StockIn_Add({
+      const res: any = await Storehouse_StockIn_Add({
         User_tokey: globalStore.GET_User_tokey,
         ...form,
-        T_product: form.T_product.toString()
+        T_product: form.T_product.join('')
       })
-      console.log(res)
+      if (res.Code === 200) {
+        ElMessage.success('入库成功!')
+        drawerProductRef.value?.clearSelection()
+        nextTick(() => {
+          emit('onUpdateList')
+          resetForm(ruleFormRef.value)
+          drawerRef.value?.closeDrawer()
+        })
+      }
     }
   })
 }
@@ -157,150 +132,60 @@ const deleteProduct = (row: any) => {
   tableData.value = tableData.value.filter(item => item.Id !== row.Id)
 
   // 设置产品的选中
-  selectTable.value?.toggleRowSelection(row, false)
+  drawerProductRef.value?.selectTableChange(row)
   // 删除设备得sn
   drawerSnRef.value?.deleteDeviceSn(row.Id)
 }
 
 const callbackDrawer = (done: Fn) => {
   resetForm(ruleFormRef.value)
-  isNew.value = true
   done()
 }
-const callbackProductDrawer = (done: Fn) => done()
-
+/**
+ * 重置表单
+ */
 const resetForm = (formEl: FormInstance | undefined) => {
   if (!formEl) return
   tableData.value = []
   formEl.resetFields()
 }
 
-// 获取产品分类
+/**
+ * 获取产品分类
+ */
 const getProductClassList = async () => {
   const res: any = await Storehouse_ProductClass_List({ page: 1, page_z: 999 })
   classOptions.value = res.Data.Data
 }
+/**
+ * 添加产品
+ */
 const AddProductionDetailed = () => {
   !classOptions.value.length && getProductClassList()
   drawerProductRef.value?.openDrawer()
 }
-const openDrawer = (type: string, row?: any) => {
-  isNew.value = type === 'new' ? true : false
-  if (!isNew.value) {
-    nextTick(() => {
-      editDataEcho(row)
-    })
-  }
-  drawerRef.value?.openDrawer()
-}
-
-const editDataEcho = async (row: any) => {
-  form.T_date = row.T_date
-  form.T_remark = row.T_remark
-  form.T_number = row.T_number
-
-  const res: any = await Storehouse_Contract_Product_List({
-    User_tokey: globalStore.GET_User_tokey,
-    T_number: row.T_number
-  })
-  if (res.Code === 200) {
-    res.Data &&
-      (tableData.value = res.Data.map((item: any) => {
-        item.Id = item.T_product_id
-        item.T_img = item.T_product_img
-        item.T_name = item.T_product_name
-        item.T_class_name = item.T_product_class_name
-        item.T_model = item.T_product_model
-        item.T_spec = item.T_product_spec
-        item.T_relation_sn = item.T_product_relation_sn
-        item.count = item.T_product_total
-        return item
-      }))
-    selectProductData = tableData.value
-  }
-}
-
-// 自动搜索
-const autoSelect = ref('')
-let timeout: NodeJS.Timeout
-const querySearchAsync = async (queryString: string, cb: (arg: any) => void) => {
-  clearTimeout(timeout)
-  timeout = setTimeout(async () => {
-    const results = await getNameAsync(queryString)
-    console.log(autoSelect, queryString)
-    cb(results)
-  }, 2000)
-}
-const getNameAsync = async (str: string): Promise<any> => {
-  const res: any = await Storehouse_Product_Name_List({ T_name: str, T_class: initParam.T_class })
-  if (!res.Data) return
-  return res.Data.map((item: any, index: number) => {
-    return {
-      value: item,
-      index: index
-    }
-  })
-}
-const getProductModelList = async () => {
-  const res: any = await Storehouse_Product_Model_List({ T_name: autoSelect.value })
-  modelOptions.value = res.Data.map((item: any, index: number) => {
-    return {
-      value: item,
-      index: index
-    }
-  })
-}
-const handleSelect = (item: any) => {
-  // initParam.T_name = item.value
-  getProductModelList()
-}
-// 加载第二个抽屉数据
-const load = () => {
-  if (initParam.page && total === tableProductData.value.length) {
-    ElMessage.warning('没有更多数据了!!')
-    return
-  }
-  initParam.page++
-  getProductList()
-}
-let total = 0
-const tableProductData = ref<any[]>([])
-const getProductList = async () => {
-  const res: any = await Storehouse_Product_List({ ...initParam, T_name: autoSelect.value })
-  if (!res.Data.Data) return
-  tableProductData.value.push(...res.Data.Data)
-  total = res.Data.Num
-  if (!isNew.value) {
-    // 设置产品的选中
-    tableProductData.value.forEach((row: any) => {
-      const matchedIndex = selectProductData.findIndex((item: any) => item.Id == row.Id)
-
-      selectTable.value?.toggleRowSelection(row, matchedIndex != -1)
-    })
+/**
+ * 产品选择 是否
+ */
+const ProductselectionChange = (row: any) => {
+  const index = tableData.value.findIndex((item: any) => item.Id === row.Id)
+  if (index === -1) {
+    row.count = ''
+    tableData.value.push(row)
+  } else {
+    tableData.value.splice(index, 1)
   }
 }
-const ProductselectionChange = (row: any[]) => {
-  const newProduct = row.find((product: any) => tableData.value.findIndex((item: any) => item.Id === product.Id) === -1)
-
-  newProduct && tableData.value.push(newProduct)
-}
-
-// 搜索模型
-const searchModelHandle = () => {
-  total = 0
-  initParam.page = 1
-  tableProductData.value = []
-  getProductList()
-}
-// 保存选中的数据id,row-key就是要指定一个key标识这一行的数据
-const getRowKey = (row: any) => {
-  return row.Id
-}
 
-// 添加sn
+/**
+ * 添加sn 号
+ */
 const addDeviceSn = (id: number) => {
   drawerSnRef.value?.addDeviceSn(id)
 }
+/**
+ * 自动计算 count
+ */
 const autoGetCount = (length: number, id: number) => {
   tableData.value.forEach((item: any) => {
     if (item.Id === id) {
@@ -308,16 +193,23 @@ const autoGetCount = (length: number, id: number) => {
     }
   })
 }
+
+// 注册事件
+const emit = defineEmits<{ (event: 'onUpdateList'): void }>()
+
 // 接受props
 interface ItemType {
   T_name: string
-  T_State: number
+  Id: number
 }
 interface PropsType {
   options?: ItemType[]
 }
 const props = defineProps<PropsType>()
-
+/**
+ * 入库调用
+ */
+const openDrawer = () => drawerRef.value?.openDrawer()
 defineExpose({
   openDrawer
 })
@@ -327,7 +219,7 @@ defineExpose({
   <div class="inStorage-form">
     <Drawer ref="drawerRef" :handleClose="callbackDrawer" size="80%">
       <template #header="{ params }">
-        <h4 :id="params.titleId" :class="params.titleClass">{{ isNew ? '入库' : '详情' }}</h4>
+        <h4 :id="params.titleId" :class="params.titleClass">入库</h4>
       </template>
       <el-form ref="ruleFormRef" :model="form" :rules="rules">
         <el-divider border-style="dashed" />
@@ -336,7 +228,7 @@ defineExpose({
         </el-form-item>
         <el-form-item label="入库仓库:" :label-width="formLabelWidth" prop="T_depot_id">
           <el-select v-model="form.T_depot_id" class="w-50" clearable placeholder="请选择入库仓库~">
-            <el-option v-for="item in props.options" :key="item.T_State" :label="item.T_name" :value="item.T_State" />
+            <el-option v-for="item in props.options" :key="item.Id" :label="item.T_name" :value="item.Id" />
           </el-select>
         </el-form-item>
         <el-form-item label="入库日期:" :label-width="formLabelWidth" prop="T_date">
@@ -413,7 +305,7 @@ defineExpose({
             </template>
           </el-table>
         </el-form-item>
-        <el-form-item label="入库仓库:" :label-width="formLabelWidth" prop="T_number">
+        <el-form-item label="入库仓库:" :label-width="formLabelWidth" prop="T_remark">
           <el-input
             v-model="form.T_remark"
             :autosize="{ minRows: 4, maxRows: 6 }"
@@ -424,98 +316,10 @@ defineExpose({
         <div class="btn">
           <el-divider>
             <el-button>取消</el-button>
-            <el-button v-if="isNew" color="#626aef" @click="AddInStorage(ruleFormRef)">提交</el-button>
+            <el-button color="#626aef" @click="AddInStorage(ruleFormRef)">提交</el-button>
           </el-divider>
         </div>
-        <Drawer ref="drawerProductRef" :handleClose="callbackProductDrawer" size="70%">
-          <template #header="{ params }">
-            <h4 :id="params.titleId" :class="params.titleClass">选择产品</h4>
-          </template>
-          <el-card class="box-card" shadow="never">
-            <template #header>
-              <div class="input-suffix">
-                <el-row :gutter="20" style="margin-bottom: 0">
-                  <el-col :xl="5" :lg="8" :md="10" class="d-flex">
-                    <span class="inline-flex items-center">产品分类:</span>
-                    <el-select v-model="initParam.T_class" clearable placeholder="请选择分类~">
-                      <el-option v-for="item in classOptions" :key="item.Id" :label="item.T_name" :value="item.Id" />
-                    </el-select>
-                  </el-col>
-                  <el-col :xl="7" :lg="8" :md="10" class="d-flex">
-                    <span class="inline-flex items-center">产品名称:</span>
-                    <el-autocomplete
-                      v-model="autoSelect"
-                      clearable
-                      :fetch-suggestions="querySearchAsync"
-                      placeholder="按产品名称搜索"
-                      :debounce="2000"
-                      :trigger-on-focus="false"
-                      @select="handleSelect"
-                    />
-                  </el-col>
-                  <el-col :xl="7" :lg="8" :md="12" class="d-flex">
-                    <span class="inline-flex items-center">产品型号:</span>
-                    <el-select v-model="initParam.T_model" clearable placeholder="请选择型号~">
-                      <el-option
-                        v-for="item in modelOptions"
-                        :key="item.index"
-                        :label="item.value"
-                        :value="item.value"
-                      />
-                    </el-select>
-                    <el-button type="primary" @click="searchModelHandle">搜索</el-button>
-                  </el-col>
-                </el-row>
-              </div>
-            </template>
-            <el-table
-              ref="selectTable"
-              :row-key="getRowKey"
-              :data="tableProductData"
-              style="width: 100%; height: 99%"
-              :header-cell-style="{
-                background: '#dedfe0',
-                height: '50px'
-              }"
-              v-el-table-infinite-scroll="load"
-              @selection-change="ProductselectionChange"
-            >
-              <template v-for="item in productColumns" :key="item">
-                <el-table-column
-                  v-if="item.type === 'index' || item.type === 'selection'"
-                  align="center"
-                  v-bind="item"
-                />
-                <el-table-column v-if="!item.ellipsis && item.prop" v-bind="item">
-                  <template #default="{ row }">
-                    <span v-if="item.prop === 'T_relation_sn'">
-                      <el-tag v-if="row.T_relation_sn === 1" effect="dark">是</el-tag>
-                      <el-tag v-else type="success" effect="dark">否</el-tag>
-                    </span>
-                    <el-image v-if="item.prop === 'T_img'" style="height: 50px" :src="row.T_img" fit="cover" />
-                  </template>
-                </el-table-column>
-                <el-table-column v-if="item.ellipsis && item.prop === 'T_model'" align="center" v-bind="item">
-                  <template #default="{ row }">
-                    <el-tooltip effect="dark" :content="row.T_model" placement="bottom">
-                      {{ row.T_model }}
-                    </el-tooltip>
-                  </template>
-                </el-table-column>
-                <el-table-column v-if="item.ellipsis && item.prop === 'T_remark'" align="center" v-bind="item">
-                  <template #default="{ row }">
-                    <el-tooltip effect="customized" placement="left">
-                      <template #content>
-                        <div class="tooltip-content">{{ row.T_remark }}</div>
-                      </template>
-                      {{ row.T_remark }}
-                    </el-tooltip>
-                  </template>
-                </el-table-column>
-              </template>
-            </el-table>
-          </el-card>
-        </Drawer>
+        <InStorageProduct ref="drawerProductRef" @ontableData="ProductselectionChange" />
         <InStorageSn ref="drawerSnRef" @onCount="autoGetCount" />
       </el-form>
     </Drawer>

+ 16 - 40
src/views/storehouse/inventory/InStorageProduct.vue

@@ -1,22 +1,22 @@
 <script setup lang="ts">
-import { ref, reactive, onMounted, computed, nextTick } from 'vue'
-import { GlobalStore } from '@/stores/index'
-import Drawer from '@/components/Drawer/index.vue'
 import {
   Storehouse_Product_List,
   Storehouse_ProductClass_List,
   Storehouse_Product_Model_List,
-  Storehouse_Product_Name_List,
-  Storehouse_Contract_Product_List
+  Storehouse_Product_Name_List
 } from '@/api/storehouse/index'
 import { ElMessage } from 'element-plus'
+import { GlobalStore } from '@/stores/index'
+import Drawer from '@/components/Drawer/index.vue'
+import { ref, reactive, onMounted, nextTick } from 'vue'
 import { default as vElTableInfiniteScroll } from 'el-table-infinite-scroll'
 
 type Fn = () => void
 
 let total = 0
+const autoSelect = ref('')
 const selectTable = ref()
-let selectProductData: any[] = []
+let timeout: NodeJS.Timeout
 const globalStore = GlobalStore()
 const classOptions = ref<any[]>([])
 const modelOptions = ref<any[]>([])
@@ -32,18 +32,18 @@ const initParam = reactive({
   page_z: 20
 })
 const callbackProductDrawer = (done: Fn) => done()
-const autoSelect = ref('')
-let timeout: NodeJS.Timeout
 const querySearchAsync = async (queryString: string, cb: (arg: any) => void) => {
   clearTimeout(timeout)
+  globalStore.SET_isloading(true)
   timeout = setTimeout(async () => {
     const results = await getNameAsync(queryString)
-    console.log(autoSelect, queryString)
     cb(results)
+    globalStore.SET_isloading(false)
   }, 2000)
 }
 
 const getProductModelList = async () => {
+  globalStore.SET_isloading(true)
   const res: any = await Storehouse_Product_Model_List({ T_name: autoSelect.value })
   modelOptions.value = res.Data.map((item: any, index: number) => {
     return {
@@ -51,9 +51,10 @@ const getProductModelList = async () => {
       index: index
     }
   })
+  globalStore.SET_isloading(false)
 }
 const handleSelect = (item: any) => {
-  // initParam.T_name = item.value
+  initParam.T_name = item.value
   getProductModelList()
 }
 // 搜索模型
@@ -79,11 +80,7 @@ const load = () => {
   getProductList()
 }
 // 勾选产品
-const ProductselectionChange = (row: any[]) => {
-  console.log(row, tableData.value)
-  const newProduct = row.find((product: any) => tableData.value.findIndex((item: any) => item.Id === product.Id) === -1)
-  newProduct && emit('ontableData', newProduct)
-}
+const ProductselectionChange = (selection: any[], row: any) => emit('ontableData', row)
 
 const getNameAsync = async (str: string): Promise<any> => {
   const res: any = await Storehouse_Product_Name_List({ T_name: str, T_class: initParam.T_class })
@@ -100,14 +97,6 @@ const getProductList = async () => {
   const res: any = await Storehouse_Product_List({ ...initParam, T_name: autoSelect.value })
   tableProductData.value.push(...res.Data.Data)
   total = res.Data.Num
-  if (!props.isNew) {
-    // 设置产品的选中
-    tableProductData.value.forEach((row: any) => {
-      const matchedIndex = selectProductData.findIndex((item: any) => item.Id == row.Id)
-
-      selectTable.value?.toggleRowSelection(row, matchedIndex != -1)
-    })
-  }
 }
 
 // 获取产品分类
@@ -131,31 +120,18 @@ const productColumns = [
   { prop: 'T_remark', label: '备注', ellipsis: true }
 ]
 
-const openDrawer = () => {
-  drawerProductRef.value?.openDrawer()
-}
-
+const openDrawer = () => drawerProductRef.value?.openDrawer()
+const clearSelection = () => selectTable.value?.clearSelection()
 const selectTableChange = (row: any) => {
-  console.log(row, tableData)
-  // selectTable.value?.clearSelection()
   nextTick(() => {
     selectTable.value?.toggleRowSelection(row, false)
   })
 }
-
-interface PropsType {
-  isNew: boolean
-  tableData: any[]
-}
-
 const emit = defineEmits<{ (event: 'ontableData', value: any): void }>()
 
-const props = defineProps<PropsType>()
-
-const tableData = computed(() => props.tableData)
-
 defineExpose({
   openDrawer,
+  clearSelection,
   selectTableChange
 })
 </script>
@@ -207,7 +183,7 @@ defineExpose({
           height: '50px'
         }"
         v-el-table-infinite-scroll="load"
-        @selection-change="ProductselectionChange"
+        @select="ProductselectionChange"
       >
         <template v-for="item in productColumns" :key="item">
           <el-table-column v-if="item.type === 'index' || item.type === 'selection'" align="center" v-bind="item" />

+ 6 - 0
src/views/storehouse/outStock/OutStock.vue

@@ -0,0 +1,6 @@
+<script setup lang="ts"></script>
+
+<template>
+  <div class="out-stock"></div>
+</template>
+<style scoped></style>

+ 2 - 1
src/views/storehouse/sales/Contract.vue

@@ -3,6 +3,7 @@ import { GlobalStore } from '@/stores/index'
 import { ref, reactive, nextTick } from 'vue'
 import ContractForm from './ContractForm.vue'
 import { useRouter } from 'vue-router'
+import { fnMd5 } from '@/utils/common'
 import { ElMessageBox, ElMessage } from 'element-plus'
 import TableBase from '@/components/TableBase/index.vue'
 import { Edit, Delete, Finished, View } from '@element-plus/icons-vue'
@@ -31,7 +32,7 @@ const openContractFormDrawer = (type: string, row?: any) => {
 const updateOnTableList = () => TableRef.value?.getTableList()
 // 审核
 const processContract = (id: string) => {
-  router.push({ name: 'ContractDetail', params: { id } })
+  router.push({ name: 'ContractDetail', params: { id, type: fnMd5('contract') } })
 }
 // 删除
 const UserDelete = (row: any) => {

+ 12 - 27
src/views/storehouse/sales/ContractDetail.vue

@@ -1,7 +1,8 @@
 <script setup lang="ts">
-import { ref, onMounted } from 'vue'
+import { ref, onMounted, onUnmounted } from 'vue'
 import { useRoute, useRouter } from 'vue-router'
 import { GlobalStore } from '@/stores/index'
+import { fnMd5 } from '@/utils/common'
 import { ElMessage } from 'element-plus'
 import { Storehouse_Contract_Get, Storehouse_Contract_Approval } from '@/api/storehouse/index'
 
@@ -22,6 +23,7 @@ interface InfoType {
   T_type: number
 }
 
+const isSale = ref(false)
 const info = ref<InfoType | undefined>()
 const globalStore = GlobalStore()
 const route = useRoute()
@@ -72,35 +74,16 @@ const getState = (val: number, type: string) => {
 const tableData = ref<any[]>([])
 
 onMounted(() => {
-  console.log(route.params.id)
+  const { params } = route
+  if (params.type === fnMd5('contract')) {
+    isSale.value = true
+  }
   getStorehouseContractGet()
 })
-</script>
-
-<script lang="ts">
-import { defineComponent } from 'vue'
-
-const isSale = ref(false)
-const globalStore = GlobalStore()
-
-export default defineComponent({
-  beforeRouteEnter(to, from, next) {
-    let isRole = globalStore.GET_Flat_Menu.find((item: any) => item.path === 'contract')
-    //需要处理的逻辑
-    if (from.name !== 'ContractSale' && isRole) {
-      isSale.value = true
-    }
-    next()
-  },
-  beforeRouteLeave(to, from, next) {
-    setTimeout(() => {
-      isSale.value = false
-    }, 1000)
-    next()
-  }
+onUnmounted(() => {
+  isSale.value = false
 })
 </script>
-
 <template>
   <div class="contract-detail">
     <div class="info">
@@ -221,7 +204,9 @@ export default defineComponent({
 
       <el-divider />
       <div class="submit">
-        <el-button v-if="isSale" type="danger" round @click="contractApproval(2)">审核不通过</el-button>
+        <el-button v-if="info?.T_State === 3 && isSale" type="danger" round @click="contractApproval(2)"
+          >审核不通过</el-button
+        >
         <el-button v-if="info?.T_State === 3 && isSale" type="success" round @click="contractApproval(1)"
           >审核通过</el-button
         >

+ 2 - 1
src/views/storehouse/sales/ContractSale.vue

@@ -3,6 +3,7 @@ import { GlobalStore } from '@/stores/index'
 import { ref, reactive, nextTick } from 'vue'
 import ContractForm from './ContractForm.vue'
 import { useRouter } from 'vue-router'
+import { fnMd5 } from '@/utils/common'
 import { ElMessageBox, ElMessage } from 'element-plus'
 import TableBase from '@/components/TableBase/index.vue'
 import { Edit, Delete, View } from '@element-plus/icons-vue'
@@ -30,7 +31,7 @@ const openContractFormDrawer = (type: string, row?: any) => {
 const updateOnTableList = () => TableRef.value?.getTableList()
 // 审核
 const processContract = (id: string) => {
-  router.push({ name: 'ContractDetail', params: { id } })
+  router.push({ name: 'ContractDetail', params: { id, type: fnMd5('contractSale') } })
 }
 // 删除
 const UserDelete = (row: any) => {