Sfoglia il codice sorgente

feat: ✨ 完成验证合同

@sun-chaoqun 2 anni fa
parent
commit
d36a022723

+ 24 - 1
src/api/storehouse/index.ts

@@ -33,7 +33,7 @@ export const Storehouse_Product_Name_List = (params: any) => $http.post('/api/st
 export const Storehouse_Product_Model_List = (params: any) => $http.post('/api/storage/Product/Model_List', params)
 // 产品规格
 export const Storehouse_Product_Spec_List = (params: any) => $http.post('/api/storage/Product/Spec_List', params)
-// 产品列表
+// 产品列表  - 验证合同产品列表-不分页
 export const Storehouse_Product_List = (params: any) => $http.post('/api/storage/Product/List', params)
 // 产品添加
 export const Storehouse_Product_Add = (params: any) => $http.post('/api/storage/Product/Add', params)
@@ -119,3 +119,26 @@ export const Storehouse_Stock_Detail_Excel = (params: any) => $http.post('/api/s
 
 // 检查 Sn 号
 export const Storehouse_Device_Check = (params: any) => $http.post('/api/storage/Device/Check', params)
+
+/**
+ * 验证合同
+ */
+// 客户列表
+export const Storehouse_VerifyContract_Customer_List = (params: any) =>
+  $http.post('/api/storage/VerifyContract/Customer_List', params)
+// 添加客户
+export const Storehouse_VerifyContract_Add_Customer = (params: any) =>
+  $http.post('/api/storage/VerifyContract/Add_Customer', params)
+// 编辑客户
+export const Storehouse_VerifyContract_Update_Customer = (params: any) =>
+  $http.post('/api/storage/VerifyContract/Update_Customer', params)
+// 明细列表
+export const Storehouse_VerifyContract_List = (params: any) => $http.post('/api/storage/VerifyContract/List', params)
+// 添加
+export const Storehouse_VerifyContract_Add = (params: any) => $http.post('/api/storage/VerifyContract/Add', params)
+// 编辑
+export const Storehouse_VerifyContract_Edit = (params: any) => $http.post('/api/storage/VerifyContract/Edit', params)
+// 编辑
+export const Storehouse_VerifyContract_Get = (params: any) => $http.post('/api/storage/VerifyContract/Get', params)
+// 编辑
+export const Storehouse_VerifyContract_Del = (params: any) => $http.post('/api/storage/VerifyContract/Del', params)

+ 15 - 0
src/hooks/useTablePublic.ts

@@ -32,6 +32,9 @@ export interface ContractFormType {
   T_customer: string
   T_product: any
   T_money: string
+  T_discount: string
+  T_start_date: string
+  T_end_date: string
   T_date: string
   T_remark: string
   T_pdf: string
@@ -83,6 +86,18 @@ export const labelsInvoice = {
   date: '开票时间',
   money: '开票金额'
 }
+export const verifyFormColumns = [
+  { type: 'index', label: '序号', width: 80, align: 'center ' },
+  { label: '产品图片', prop: 'T_img', align: 'center ', name: 'T_img' },
+  { label: '产品名称', prop: 'T_name', align: 'center ' },
+  { label: '产品分类', prop: 'T_class_name', align: 'center ' },
+  { label: '产品型号', prop: 'T_model', align: 'center ' },
+  { label: '产品规格', prop: 'T_spec', align: 'center ' },
+  { label: '*数量', prop: 'count', align: 'center ', name: 'count', sortable: true },
+  { label: '单价', prop: 'T_price', align: 'center ', sortable: true },
+  { label: '总价', prop: 'T_total', align: 'center ', sortable: true },
+  { prop: 'operation', label: '操作', width: 80, fixed: 'right' }
+]
 
 export function useTablePublic() {
   //判断是否相等,相同时改变背景颜色

+ 16 - 0
src/router/modules/staticRouter.ts

@@ -39,6 +39,22 @@ export const staticRouter: RouteRecordRaw[] = [
             meta: {
               title: '合同详情'
             }
+          },
+          {
+            path: '/verifyContract',
+            name: 'VerifyContract',
+            component: () => import('@/views/storehouse/sales/VerifyContract.vue'),
+            meta: {
+              title: '验证合同'
+            }
+          },
+          {
+            path: '/verifyContractDetail/:id',
+            name: 'VerifyContractDetail',
+            component: () => import('@/views/storehouse/sales/VerifyContractDetail.vue'),
+            meta: {
+              title: '验证合同明细'
+            }
           }
         ]
       },

+ 4 - 0
src/style.scss

@@ -92,6 +92,10 @@ body {
   flex: 1;
 }
 
+.d-flex {
+  display: flex !important;
+}
+
 ::-webkit-scrollbar {
   width: 3px;
   height: 3px;

+ 3 - 9
src/views/storehouse/sales/TableDetail.vue

@@ -28,7 +28,7 @@ const callbackDrawer = (done: () => void) => {
   resetForm(ruleFormRef.value)
 }
 const AddMoneyDetailed = (type: string, row?: any) => {
-  isNew.value = type === 'new' ? true : false
+  isNew.value = type === 'edit' ? false : true
   if (type === 'edit') {
     form.value = { ...row }
   }
@@ -75,13 +75,7 @@ defineExpose({
 </script>
 <template>
   <div class="table-detail">
-    <el-table
-      border
-      stripe
-      :data="tableData"
-      style="width: 100%"
-      :header-cell-style="{ background: '#dedfe0', height: '50px' }"
-    >
+    <el-table border stripe :data="tableData" style="width: 100%" :header-cell-style="{ height: '50px' }">
       <template v-for="item in columns" :key="item.prop">
         <el-table-column v-bind="item" v-if="item.fixed !== 'right'"></el-table-column>
         <el-table-column v-bind="item" v-if="item.fixed === 'right'">
@@ -94,7 +88,7 @@ defineExpose({
         </el-table-column>
       </template>
       <template #append>
-        <slot name="add" :AddDetail="AddMoneyDetailed('new')"></slot>
+        <slot name="add" :AddDetail="AddMoneyDetailed"></slot>
       </template>
     </el-table>
     <Drawer ref="drawerRef" :handleClose="callbackDrawer">

+ 180 - 0
src/views/storehouse/sales/VerifyContract.vue

@@ -0,0 +1,180 @@
+<script setup lang="ts">
+import { GlobalStore } from '@/stores/index'
+import { ref, reactive, nextTick } from 'vue'
+import { useRouter } from 'vue-router'
+import Drawer from '@/components/Drawer/index.vue'
+import { ElMessage } from 'element-plus'
+import TableBase from '@/components/TableBase/index.vue'
+import { Edit, View } from '@element-plus/icons-vue'
+import type { ColumnProps } from '@/components/TableBase/interface/index'
+import type { FormInstance, FormRules } from 'element-plus'
+import {
+  Storehouse_VerifyContract_Add_Customer,
+  Storehouse_VerifyContract_Customer_List,
+  Storehouse_VerifyContract_Update_Customer
+} from '@/api/storehouse/index'
+
+const isNew = ref(true)
+const router = useRouter()
+const globalStore = GlobalStore()
+const ruleFormRef = ref<FormInstance>()
+const drawerRef = ref<InstanceType<typeof Drawer> | null>(null)
+const TableRef = ref<InstanceType<typeof TableBase> | null>(null)
+
+const columns: ColumnProps[] = [
+  { type: 'index', label: '序号', width: 80 },
+  { prop: 'T_customer', label: '客户名称' },
+  { prop: 'T_start_date', label: '起始时间' },
+  { prop: 'T_end_date', label: '终止时间' },
+  { prop: 'T_State', label: '状态', name: 'T_State' },
+  { prop: 'T_sign_times', label: '签约次数' },
+  { prop: 'operation', label: '操作', width: 260, fixed: 'right' }
+]
+const options = reactive([
+  { name: '已签约', id: 3 },
+  { name: '已作废', id: 2 },
+  { name: '未签约', id: 1 },
+  { name: '即将到期', id: 4 }
+])
+const initParam = reactive({
+  User_tokey: globalStore.GET_User_tokey,
+  T_name: '',
+  T_state: ''
+})
+const openContract = (type: string, row?: any) => {
+  isNew.value = type === 'new' ? true : false
+  if (type === 'edit') {
+    form.value = { ...row }
+  }
+  drawerRef.value?.openDrawer()
+}
+const updateOnTableList = () => TableRef.value?.getTableList()
+const processContract = (id: string) => router.push({ name: 'VerifyContractDetail', params: { id } })
+const searchHandle = () => TableRef.value?.searchTable()
+const callbackDrawer = (done: () => void) => {
+  resetForm(ruleFormRef.value)
+  done()
+}
+const form = ref({
+  T_customer: '',
+  T_customer_id: ''
+})
+const rules = reactive<FormRules>({
+  T_customer: [{ required: true, message: '请输入客户名称', trigger: 'blur' }]
+})
+const AddContract = (formEl: FormInstance | undefined) => {
+  if (!formEl) return
+  formEl.validate(async valid => {
+    if (valid) {
+      let res: any = {}
+      if (isNew.value) {
+        res = await Storehouse_VerifyContract_Add_Customer({ User_tokey: globalStore.GET_User_tokey, ...form.value })
+      } else {
+        res = await Storehouse_VerifyContract_Update_Customer({ User_tokey: globalStore.GET_User_tokey, ...form.value })
+      }
+      if (res.Code === 200) {
+        ElMessage.success('添加客户成功!!')
+        nextTick(() => {
+          updateOnTableList()
+          isNew.value = true
+          resetForm(ruleFormRef.value)
+          drawerRef.value?.closeDrawer()
+        })
+      }
+    } else {
+      return false
+    }
+  })
+}
+const resetForm = (formEl: FormInstance | undefined) => {
+  if (!formEl) return
+  formEl.resetFields()
+}
+</script>
+
+<template>
+  <div class="verify-contract">
+    <TableBase
+      ref="TableRef"
+      :columns="columns"
+      :requestApi="Storehouse_VerifyContract_Customer_List"
+      :initParam="initParam"
+    >
+      <template #table-header>
+        <el-row :gutter="20" style="margin-bottom: 0" class="input-suffix">
+          <el-col :xl="6" :lg="8" :md="8" class="d-flex">
+            <span class="inline-flex items-center">客户名称:</span>
+            <el-input
+              v-model="initParam.T_name"
+              type="text"
+              class="w-50 m-2"
+              placeholder="按产品名称搜索"
+              @change="searchHandle"
+            />
+          </el-col>
+          <el-col :xl="6" :md="8" class="d-flex">
+            <span class="inline-flex items-center">状态:</span>
+            <el-select v-model="initParam.T_state" class="w-50" clearable placeholder="请选择状态~">
+              <el-option v-for="item in options" :key="item.id" :label="item.name" :value="item.id" />
+            </el-select>
+            <el-button type="primary" @click="searchHandle">搜索</el-button>
+          </el-col>
+          <el-col :xl="6" :md="2" :offset="4" class="btn"
+            ><el-button type="primary" @click="openContract('new')">添加</el-button></el-col
+          >
+        </el-row>
+      </template>
+      <template #T_State="{ row }">
+        <el-tag v-if="row.T_State === 1" type="warning" effect="dark"> 未签约 </el-tag>
+        <el-tag v-else-if="row.T_State === 2" type="info" effect="dark"> 已作废 </el-tag>
+        <el-tag v-else-if="row.T_State === 3" type="danger" effect="dark"> 已签约 </el-tag>
+        <el-tag v-else type="danger" effect="dark"> 即将到期 </el-tag>
+      </template>
+      <template #right="{ row }">
+        <el-button link type="primary" size="small" :icon="Edit" @click="openContract('edit', row)">编辑</el-button>
+        <el-button link type="success" size="small" :icon="View" @click="processContract(row.T_customer_id)"
+          >明细</el-button
+        >
+      </template>
+    </TableBase>
+    <Drawer ref="drawerRef" :handleClose="callbackDrawer">
+      <template #header="{ params }">
+        <h4 :id="params.titleId" :class="params.titleClass">{{ isNew ? '添加' : '编辑' }} - 客户名称</h4>
+      </template>
+      <el-form ref="ruleFormRef" :model="form" :rules="rules">
+        <el-form-item label="客户名称:" label-width="100px" prop="T_customer">
+          <el-input v-model="form.T_customer" type="text" autocomplete="off" placeholder="请输入仓库名称" />
+        </el-form-item>
+        <el-form-item label-width="100px">
+          <el-button v-if="isNew" color="#626aef" @click="AddContract(ruleFormRef)">提交</el-button>
+          <el-button v-else color="#626aef" @click="AddContract(ruleFormRef)">修改</el-button>
+        </el-form-item>
+      </el-form>
+    </Drawer>
+  </div>
+</template>
+
+<style scoped lang="scss">
+@import '@/styles/var.scss';
+
+.verify-contract {
+  @include f-direction;
+
+  :deep(.el-drawer__header) {
+    margin-bottom: 0;
+  }
+  .input-suffix {
+    width: 100%;
+    .inline-flex {
+      white-space: nowrap;
+    }
+    .btn {
+      display: flex;
+      justify-content: end;
+    }
+    .w-50 {
+      flex: 0 0 50%;
+    }
+  }
+}
+</style>

+ 101 - 0
src/views/storehouse/sales/VerifyContractDetail.vue

@@ -0,0 +1,101 @@
+<script setup lang="ts">
+import { GlobalStore } from '@/stores/index'
+import { ref, reactive, onMounted } from 'vue'
+import VerifyForm from './VerifyForm.vue'
+import { useRouter, useRoute } from 'vue-router'
+
+import TableBase from '@/components/TableBase/index.vue'
+import { Edit, Delete, View } from '@element-plus/icons-vue'
+import type { ColumnProps } from '@/components/TableBase/interface/index'
+import { Storehouse_VerifyContract_List } from '@/api/storehouse/index'
+
+const customer_id = ref('')
+const route = useRoute()
+const router = useRouter()
+const globalStore = GlobalStore()
+const TableRef = ref<InstanceType<typeof TableBase> | null>(null)
+const VerifyFormRef = ref<InstanceType<typeof VerifyForm> | null>(null)
+
+const columns: ColumnProps[] = [
+  { type: 'index', label: '序号', width: 80 },
+  { prop: 'T_number', label: '合同编号' },
+  { prop: 'T_date', label: '签订时间' },
+  { prop: 'T_money', label: '金额' },
+  { prop: 'T_start_date', label: '起始时间' },
+  { prop: 'T_end_date', label: '终止时间' },
+  { prop: 'T_verify_state', label: '是否过期', name: 'T_verify_state' },
+  { prop: 'operation', label: '操作', width: 260, fixed: 'right' }
+]
+const initParam = reactive({
+  User_tokey: globalStore.GET_User_tokey,
+  T_customer_id: route.params.id
+})
+const openContract = (type: string, row?: any) => VerifyFormRef.value?.openDrawer(type, row)
+const updateOnTableList = () => TableRef.value?.getTableList()
+const processContract = (id: string) => router.push({ name: 'VerifyContractDetail', params: { id } })
+onMounted(() => {
+  const { params } = route
+  customer_id.value = params.id as string
+  // initParam.T_customer_id = customer_id.value
+  console.log(initParam)
+})
+</script>
+
+<template>
+  <div class="verify-contract">
+    <TableBase ref="TableRef" :columns="columns" :requestApi="Storehouse_VerifyContract_List" :initParam="initParam">
+      <template #table-header>
+        <el-row :gutter="20" style="margin-bottom: 0" class="input-suffix">
+          <el-col :xl="6" :md="8">
+            <h3 class="inline-flex">合同明细</h3>
+          </el-col>
+          <el-col :xl="6" :md="4" :offset="12" class="btn"
+            ><el-button type="primary" @click="openContract('new')">添加</el-button>
+            <el-button type="primary" @click="router.back()">返回</el-button>
+          </el-col>
+        </el-row>
+      </template>
+      <template #T_verify_state="{ row }">
+        <el-tag v-if="row.T_verify_state === 1" type="warning" effect="dark"> 未签约 </el-tag>
+        <el-tag v-else-if="row.T_verify_state === 2" type="info" effect="dark"> 已作废 </el-tag>
+        <el-tag v-else-if="row.T_verify_state === 3" type="danger" effect="dark"> 已签约 </el-tag>
+        <el-tag v-else type="danger" effect="dark"> 即将到期 </el-tag>
+      </template>
+      <template #right="{ row }">
+        <el-button link type="primary" size="small" :icon="Edit" @click="openContract('edit', row)">编辑</el-button>
+        <el-button link type="success" size="small" :icon="View" @click="processContract(row.T_customer_id)"
+          >明细</el-button
+        >
+        <el-button link type="danger" size="small" :icon="Delete" @click="processContract(row.T_customer_id)"
+          >删除</el-button
+        >
+      </template>
+    </TableBase>
+    <VerifyForm ref="VerifyFormRef" @onTableList="updateOnTableList" :verify_customer_id="customer_id" />
+  </div>
+</template>
+
+<style scoped lang="scss">
+@import '@/styles/var.scss';
+
+.verify-contract {
+  @include f-direction;
+
+  :deep(.el-drawer__header) {
+    margin-bottom: 0;
+  }
+  .input-suffix {
+    width: 100%;
+    .inline-flex {
+      white-space: nowrap;
+    }
+    .btn {
+      display: flex;
+      justify-content: end;
+    }
+    .w-50 {
+      flex: 0 0 50%;
+    }
+  }
+}
+</style>

+ 484 - 0
src/views/storehouse/sales/VerifyForm.vue

@@ -0,0 +1,484 @@
+<script setup lang="ts">
+import {
+  verifyFormColumns,
+  ContractFormType,
+  useTablePublic,
+  columnsRecoveries,
+  labelsRecoveries,
+  columnsInvoice,
+  labelsInvoice
+} from '@/hooks/useTablePublic'
+import {
+  Storehouse_Contract_Get,
+  Storehouse_Contract_Add,
+  Storehouse_Contract_Edit,
+  Storehouse_Contract_Gen_Number
+} from '@/api/storehouse/index'
+
+import { ElMessage } from 'element-plus'
+import TableDetail from './TableDetail.vue'
+import { GlobalStore } from '@/stores/index'
+import { ref, reactive, nextTick } from 'vue'
+import Drawer from '@/components/Drawer/index.vue'
+import { Delete } from '@element-plus/icons-vue'
+import Upload from '@/components/Upload/index.vue'
+import ImageCom from '@/components/Image/index.vue'
+import type { FormInstance, FormRules } from 'element-plus'
+import ContractUser from '@/views/storehouse/outStock/receiveUser.vue'
+import VerifyProject from './VerifyProject.vue'
+
+const isNew = ref(true)
+const isProduct = ref(false)
+const tableData = ref<any[]>([])
+let selectProductData: any[] = []
+const globalStore = GlobalStore()
+const formLabelWidth = ref('120px')
+const { resetForm } = useTablePublic()
+const ruleFormRef = ref<FormInstance>()
+const contractNumberLoading = ref(false)
+const User_tokey = globalStore.GET_User_tokey
+const drawerRef = ref<InstanceType<typeof Drawer> | null>(null)
+const uploadRef = ref<InstanceType<typeof Upload> | null>(null)
+const receiveUserdialog = ref<InstanceType<typeof ContractUser> | null>(null)
+const RecoveriesRef = ref<InstanceType<typeof TableDetail> | null>(null)
+const InvoiceRef = ref<InstanceType<typeof TableDetail> | null>(null)
+
+const validate_T_product = (rule: any, value: any, callback: any) => {
+  if (value === '') {
+    callback(new Error('请选择产品明细'))
+  } else if (value.includes(undefined)) {
+    callback(new Error('请填写产品数量'))
+  } else {
+    callback()
+  }
+}
+
+const rules = reactive<FormRules>({
+  T_number: [{ required: true, message: '请输入合同编号', trigger: 'blur' }],
+  T_customer: [{ required: true, message: '请输入客户名称', trigger: 'blur' }],
+  T_type: [{ required: true, message: '请选择合同类型', trigger: 'blur' }],
+  T_product: [{ validator: validate_T_product, trigger: 'blur' }],
+  T_money: [{ required: true, message: '请输入合同金额', trigger: 'blur' }],
+  T_date: [{ required: true, message: '请选择签订时间', trigger: 'blur' }],
+  T_submit: [{ required: true, message: '请选择合同负责人', trigger: 'change' }],
+  T_submit_name: [{ required: true, message: '请输入项目名称', trigger: 'blur' }]
+})
+
+const callbackDrawer = (done: () => void) => {
+  closeCancle()
+  done()
+}
+
+// 父级方法
+const emit = defineEmits<{ (event: 'onTableList'): void }>()
+
+const form = reactive<ContractFormType>({
+  T_uuid: '',
+  T_number: '',
+  T_customer: '',
+  T_product: '',
+  T_money: '',
+  T_discount: '',
+  T_date: '',
+  T_remark: '',
+  T_pdf: '',
+  T_submit: '',
+  T_recoveries: '',
+  T_invoice: '',
+  T_submit_name: '',
+  T_start_date: '',
+  T_end_date: ''
+})
+
+const openDrawer = (type: string, row?: any) => {
+  isNew.value = type === 'new' ? true : false
+  if (!isNew.value) {
+    nextTick(() => {
+      editDataEcho(row)
+    })
+  }
+  drawerRef.value?.openDrawer()
+}
+// edit data echo
+const editDataEcho = async (row: any) => {
+  form.T_uuid = row.T_submit
+  form.T_pdf = row.T_pdf
+  form.T_date = row.T_date
+  form.T_money = row.T_money
+  form.T_submit = row.T_submit_name
+  form.T_number = row.T_number
+  form.T_customer = row.T_customer
+
+  const res: any = await Storehouse_Contract_Get({
+    User_tokey,
+    T_number: row.T_number
+  })
+  if (res.Code === 200) {
+    const { T_Product, T_invoice, T_recoveries, T_remark } = res.Data
+    form.T_remark = T_remark
+    T_Product &&
+      (tableData.value = T_Product.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
+    T_invoice && InvoiceRef.value?.setMoneyDeatil(T_invoice)
+    T_recoveries && RecoveriesRef.value?.setMoneyDeatil(T_recoveries)
+    blurHandle()
+  }
+}
+
+const blurHandle = () => {
+  // form.T_product
+  form.T_product = []
+  tableData.value = tableData.value.map(item => {
+    if (!item.count) {
+      form.T_product.push(undefined)
+    } else {
+      form.T_product.push(`${item.Id},${item.count}|`)
+      item.T_total = item.count * item.T_price
+    }
+    return item
+  })
+}
+const deleteProduct = (row: any) => {
+  tableData.value = tableData.value.filter(item => item.Id !== row.Id)
+
+  // 设置产品的选中
+  drawerProductRef.value?.selectTableChange(row)
+}
+
+const getMontageStr = (arr: any[], value1: string, value2: string): string => {
+  let str = ''
+  arr.forEach(item => {
+    str += `${item[value1]},${item[value2]}|`
+  })
+  return str
+}
+
+const getFomrParams = () => {
+  const recoveriesData = RecoveriesRef.value?.getMoneyDeatil()
+  const invoiceData = InvoiceRef.value?.getMoneyDeatil()
+  if (recoveriesData?.length) form.T_recoveries = getMontageStr(recoveriesData, 'T_date', 'T_money')
+  if (invoiceData?.length) form.T_invoice = getMontageStr(invoiceData, 'T_date', 'T_money')
+  const product = getMontageStr(tableData.value, 'Id', 'count')
+  const params = {
+    ...form,
+    User_tokey,
+    T_submit: form.T_uuid,
+    T_product: product
+  }
+  return params
+}
+
+const AddContract = (formEl: FormInstance | undefined) => {
+  if (!formEl) return
+  formEl.validate(async valid => {
+    if (valid) {
+      let res: any = {}
+      const params = getFomrParams()
+      if (isNew.value) {
+        res = await Storehouse_Contract_Add({ ...params, T_customer_id: props.verify_customer_id })
+      } else {
+        res = await Storehouse_Contract_Edit({ ...params, T_customer_id: props.verify_customer_id })
+      }
+      if (res.Code === 200) {
+        ElMessage.success(`${isNew.value ? '添加' : '修改'}合同成功!!`)
+        nextTick(() => {
+          closeCancle()
+          emit('onTableList')
+        })
+      }
+    } else false
+  })
+}
+
+const drawerProductRef = ref<InstanceType<typeof VerifyProject> | null>(null)
+/**
+ * 添加产品
+ */
+const AddProductionDetailed = () => {
+  isProduct.value = true
+  nextTick(() => {
+    drawerProductRef.value?.openDrawer()
+  })
+}
+/**
+ * 产品选择 是否
+ */
+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)
+  }
+  getSummaries({ columns: verifyFormColumns, data: tableData.value })
+}
+/**
+ * 全选
+ */
+const ProductSelectionAllChange = (selection: any[]) => (tableData.value = selection)
+/**
+ * 生成合同编号
+ */
+const getContractNumber = async () => {
+  contractNumberLoading.value = true
+  const res: any = await Storehouse_Contract_Gen_Number({ User_tokey }).catch(() => {
+    contractNumberLoading.value = false
+  })
+  if (res.Code === 200) {
+    contractNumberLoading.value = false
+    form.T_number = res.Data
+  }
+}
+
+const getSummaries = (param: any) => {
+  const { columns, data } = param
+  const sums: string[] = []
+  columns.forEach((column: any, index: number) => {
+    if (index === 0) {
+      sums[index] = '合计'
+      return
+    }
+    if (index === 1) {
+      sums[index] = ''
+      return
+    }
+    const values = data.map((item: any) => Number(item[column.property]))
+    if (!values.every((value: any) => Number.isNaN(value))) {
+      sums[index] = values.reduce((prev: any, curr: any) => {
+        const value = Number(curr)
+        if (!Number.isNaN(value)) {
+          return prev + curr
+        } else {
+          return prev
+        }
+      }, 0)
+      if (index === 8) {
+        form.T_money = sums[index]
+      }
+    } else {
+      sums[index] = ''
+    }
+  })
+
+  return sums
+}
+
+/**
+ * 合同负责人
+ */
+const selectApprover = () => receiveUserdialog.value?.openDrawer()
+const getReceiveInfo = ({ T_uuid, T_name }: { T_uuid: string; T_name: string }) => {
+  form.T_submit = T_name
+  form.T_uuid = T_uuid
+}
+const closeCancle = () => {
+  resetForm(ruleFormRef.value)
+  isNew.value = isProduct.value = false
+  tableData.value = []
+  selectProductData = []
+  drawerProductRef.value?.clearSelection()
+  RecoveriesRef.value?.clearDetail()
+  InvoiceRef.value?.clearDetail()
+  drawerRef.value?.closeDrawer()
+}
+
+const props = defineProps<{ verify_customer_id: string }>()
+
+defineExpose({
+  openDrawer
+})
+</script>
+
+<template>
+  <div class="verify-form">
+    <Drawer ref="drawerRef" :handleClose="callbackDrawer" size="80%">
+      <template #header="{ params }">
+        <h4 :id="params.titleId" :class="params.titleClass">{{ isNew ? '添加' : '编辑' }} - 合同</h4>
+      </template>
+      <el-form ref="ruleFormRef" :model="form" :rules="rules">
+        <el-form-item label="合同编号:" :label-width="formLabelWidth" prop="T_number">
+          <div>
+            <el-input v-model="form.T_number" :disabled="!isNew" placeholder="请输入合同编号" class="w-50" />
+            <el-button :loading="contractNumberLoading" :disabled="!isNew" type="primary" @click="getContractNumber"
+              >生成合同编号</el-button
+            >
+            <el-button type="primary" @click="AddProductionDetailed">
+              <el-icon><CirclePlusFilled /></el-icon><span style="margin-left: 6px">验证</span>
+            </el-button>
+          </div>
+        </el-form-item>
+        <el-form-item label="产品明细:" :label-width="formLabelWidth" prop="T_product">
+          <el-table
+            border
+            show-summary
+            :summary-method="getSummaries"
+            :data="tableData"
+            style="width: 100%"
+            :header-cell-style="{ height: '50px' }"
+          >
+            <template v-for="item in verifyFormColumns" :key="item.prop">
+              <el-table-column v-bind="item" v-if="item.fixed !== 'right'">
+                <template #header v-if="item.prop === 'count'">
+                  <span style="color: red">*数量</span>
+                </template>
+                <template #default="{ row }" v-if="item.prop === item.name">
+                  <el-input
+                    v-if="item.prop === 'count'"
+                    v-model.number="row.count"
+                    type="text"
+                    autocomplete="off"
+                    @blur="blurHandle"
+                  />
+                  <ImageCom v-if="item.prop === 'T_img'" :src="row.T_img" />
+                </template>
+              </el-table-column>
+              <el-table-column v-bind="item" v-if="item.fixed === 'right'">
+                <template #default="{ row }">
+                  <el-button link type="danger" size="small" :icon="Delete" @click="deleteProduct(row)">删除</el-button>
+                </template>
+              </el-table-column>
+            </template>
+          </el-table>
+        </el-form-item>
+        <el-form-item label="合同金额:" :label-width="formLabelWidth" prop="T_money">
+          <el-input v-model="form.T_money" type="text" autocomplete="off" placeholder="请输入合同金额" class="w-50" />
+        </el-form-item>
+        <el-form-item label="优惠金额:" :label-width="formLabelWidth" prop="T_discount">
+          <el-input
+            v-model="form.T_discount"
+            type="text"
+            autocomplete="off"
+            placeholder="请输入合同金额"
+            class="w-50"
+          />
+        </el-form-item>
+        <el-form-item label="签订时间:" :label-width="formLabelWidth" prop="T_date">
+          <el-date-picker
+            class="my-date-picker"
+            style="width: 21.5rem"
+            v-model="form.T_date"
+            type="date"
+            placeholder="选择日期"
+            format="YYYY-MM-DD"
+            value-format="YYYY-MM-DD"
+          />
+        </el-form-item>
+        <el-form-item label="起始时间:" :label-width="formLabelWidth" prop="T_start_date">
+          <el-date-picker
+            class="my-date-picker"
+            style="width: 21.5rem"
+            v-model="form.T_start_date"
+            type="date"
+            placeholder="选择日期"
+            format="YYYY-MM-DD"
+            value-format="YYYY-MM-DD"
+          />
+        </el-form-item>
+        <el-form-item label="终止时间:" :label-width="formLabelWidth" prop="T_end_date">
+          <el-date-picker
+            class="my-date-picker"
+            style="width: 21.5rem"
+            v-model="form.T_end_date"
+            type="date"
+            placeholder="选择日期"
+            format="YYYY-MM-DD"
+            value-format="YYYY-MM-DD"
+          />
+        </el-form-item>
+        <el-form-item label="合同负责人:" :label-width="formLabelWidth" prop="T_submit">
+          <el-input v-model="form.T_submit" placeholder="请选择合同负责人" class="w-50" @focus="selectApprover" />
+        </el-form-item>
+        <el-form-item label="项目:" :label-width="formLabelWidth" prop="T_submit_name">
+          <el-input v-model="form.T_submit_name" placeholder="请输入项目名称" class="w-50" />
+        </el-form-item>
+        <el-form-item label="合同备注:" :label-width="formLabelWidth" prop="T_remark">
+          <el-input
+            class="w-50"
+            v-model="form.T_remark"
+            :autosize="{ minRows: 4, maxRows: 6 }"
+            type="textarea"
+            placeholder="请输入备注信息"
+          />
+        </el-form-item>
+        <el-form-item label="上传附件:" :label-width="formLabelWidth" prop="T_pdf">
+          <Upload
+            v-model="form.T_pdf"
+            class="w-50"
+            ref="uploadRef"
+            :limit="1"
+            successText="文件上传成功!!"
+            errorText="文件上传失败"
+            accept=".pdf"
+            listType="text"
+          >
+            <el-button type="primary">上传文件</el-button>
+            <template #tip> 只能上传pdf格式文件!!</template>
+          </Upload>
+        </el-form-item>
+        <el-form-item label="回款明细:" :label-width="formLabelWidth" prop="T_recoveries">
+          <TableDetail ref="RecoveriesRef" :columns="columnsRecoveries" title="回款明细" :labels="labelsRecoveries">
+            <template #add="{ AddDetail }">
+              <el-button type="primary" @click="AddDetail">
+                <el-icon><Plus /></el-icon><span style="margin-left: 6px">添加</span>
+              </el-button>
+            </template>
+          </TableDetail>
+        </el-form-item>
+        <el-form-item label="开票明细:" :label-width="formLabelWidth" prop="T_invoice">
+          <TableDetail ref="InvoiceRef" :columns="columnsInvoice" title="开票明细" :labels="labelsInvoice">
+            <template #add="{ AddDetail }">
+              <el-button type="primary" @click="AddDetail">
+                <el-icon><Plus /></el-icon><span style="margin-left: 6px">添加</span>
+              </el-button>
+            </template>
+          </TableDetail>
+        </el-form-item>
+      </el-form>
+      <template #footer>
+        <div>
+          <el-divider border-style="dashed" />
+          <div class="btn">
+            <el-button @click="closeCancle">取消</el-button>
+            <el-button v-if="isNew" color="#626aef" @click="AddContract(ruleFormRef)">提交</el-button>
+            <el-button v-else color="#626aef" @click="AddContract(ruleFormRef)">修改</el-button>
+          </div>
+        </div>
+      </template>
+    </Drawer>
+    <ContractUser ref="receiveUserdialog" @onUserInfo="getReceiveInfo" title="合同负责人" />
+    <VerifyProject
+      v-if="isProduct"
+      ref="drawerProductRef"
+      :selectProductData="selectProductData"
+      @ontableData="ProductselectionChange"
+      @ontableDataAll="ProductSelectionAllChange"
+    ></VerifyProject>
+  </div>
+</template>
+
+<style scoped lang="scss">
+.verify-form {
+  .btn {
+    margin-top: 32px;
+    display: flex;
+    justify-content: center;
+    .el-button {
+      padding: 0 32px;
+    }
+  }
+  .w-50 {
+    width: 21.5rem;
+  }
+}
+</style>

+ 135 - 0
src/views/storehouse/sales/VerifyProject.vue

@@ -0,0 +1,135 @@
+<script setup lang="ts">
+import { Storehouse_Product_List } from '@/api/storehouse/index'
+import { GlobalStore } from '@/stores/index'
+import Drawer from '@/components/Drawer/index.vue'
+import { ref, reactive, onMounted, nextTick } from 'vue'
+import ImageCom from '@/components/Image/index.vue'
+
+const autoSelect = ref('')
+const selectTable = ref()
+const globalStore = GlobalStore()
+const tableProductData = ref<any[]>([])
+const drawerProductRef = ref<InstanceType<typeof Drawer> | null>(null)
+
+const initParam = reactive({
+  User_tokey: globalStore.GET_User_tokey,
+  page: 1,
+  page_z: 9999,
+  T_VerifyContract: 1
+})
+
+// 获取产品的列表
+const getProductList = async () => {
+  const res: any = await Storehouse_Product_List({ ...initParam, T_name: autoSelect.value })
+  tableProductData.value.push(...res.Data.Data)
+  if (selectProductData.value?.length) {
+    // 设置产品的选中
+    tableProductData.value.forEach((row: any) => {
+      const matchedIndex = selectProductData.value?.findIndex((item: any) => item.Id == row.Id)
+      console.log(matchedIndex)
+      selectTable.value?.toggleRowSelection(row, matchedIndex != -1)
+    })
+  }
+}
+
+onMounted(() => {
+  getProductList()
+})
+
+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 }
+]
+
+// 保存选中的数据id,row-key就是要指定一个key标识这一行的数据
+const getRowKey = (row: any) => row.Id
+const openDrawer = () => drawerProductRef.value?.openDrawer()
+const callbackProductDrawer = (done: () => void) => done()
+// 勾选产品
+const ProductselectionChange = (selection: any[], row: any) => emit('ontableData', row)
+const ProductSelectionAllChange = (selection: any[]) => emit('ontableDataAll', selection)
+const clearSelection = () => {
+  initParam.page = 1
+  tableProductData.value = []
+  selectTable.value?.clearSelection()
+}
+const selectTableChange = (row: any) => {
+  nextTick(() => {
+    selectTable.value?.toggleRowSelection(row, false)
+  })
+}
+
+// props
+const props = defineProps<{ selectProductData?: any[] }>()
+const selectProductData = ref(props.selectProductData)
+const emit = defineEmits<{ (event: 'ontableData', value: any): void; (event: 'ontableDataAll', value: any[]): void }>()
+
+defineExpose({
+  openDrawer,
+  clearSelection,
+  selectTableChange
+})
+</script>
+
+<template>
+  <Drawer ref="drawerProductRef" :handleClose="callbackProductDrawer" size="70%">
+    <template #header="{ params }">
+      <h4 :id="params.titleId" :class="params.titleClass">选择产品</h4>
+    </template>
+    <el-table
+      ref="selectTable"
+      :row-key="getRowKey"
+      :data="tableProductData"
+      style="width: 100%; height: 99%"
+      :header-cell-style="{
+        background: '#dedfe0',
+        height: '50px'
+      }"
+      @select="ProductselectionChange"
+      @select-all="ProductSelectionAllChange"
+    >
+      <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>
+            <ImageCom v-if="item.prop === 'T_img'" :src="row.T_img" />
+          </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>
+  </Drawer>
+</template>
+
+<style scoped lang="scss">
+.tooltip-content {
+  max-width: 500px;
+  overflow-y: auto;
+}
+</style>