瀏覽代碼

add:采购管理添加导出按钮

zoie 2 天之前
父節點
當前提交
bb297f8381

+ 4 - 1
src/api/purchase/index.ts

@@ -14,4 +14,7 @@ export const Purchase_Add = (params: any) => $http.post('/storage/Purchase/Add',
 export const Purchase_Edit = (params: any) => $http.post('/storage/Purchase/Edit', params)
 // 删除
 export const Purchase_Del = (params: any) => $http.post('/storage/Purchase/Del', params)
-
+export const Purchase_Audit_List = (params: any) => $http.post('/storage/Purchase/Audit_List', params)
+export const Purchase_Excel = (params: any) => $http.post('/storage/Purchase/Excel', params)
+export const Purchase_Stat_Excel = (params: any) => $http.post('/storage/Purchase/Stat_Excel', params, { responseType: 'blob' })
+export const Purchase_Apply_User_List = (params: any) => $http.post('/storage/Purchase/User/list', params, { responseType: 'blob' })

+ 216 - 191
src/hooks/useTablePublic.ts

@@ -1,252 +1,277 @@
-import type { FormInstance } from 'element-plus'
-import { GlobalStore } from '@/stores/index'
+import type {FormInstance} from 'element-plus'
+import {GlobalStore} from '@/stores/index'
+import {reactive} from "vue";
 
 export interface LeaveUserInfoIn {
-  T_user_name: string
-  T_dept: string
-  T_post: string
-  T_type_name: string
-  T_start_time: string
-  T_end_time: string
-  T_text: string
-  Id: string
-  T_duration: number
+	T_user_name: string
+	T_dept: string
+	T_post: string
+	T_type_name: string
+	T_start_time: string
+	T_end_time: string
+	T_text: string
+	Id: string
+	T_duration: number
 }
 
 export interface OvertimeUserInfoIn {
-  T_uid: string
-  T_user_name: string
-  T_dept: string
-  T_post: string
-  T_type_name: string
-  T_start_time: string
-  T_end_time: string
-  T_text: string
-  Id: string
-  T_duration: string
-  T_prove_img: any
+	T_uid: string
+	T_user_name: string
+	T_dept: string
+	T_post: string
+	T_type_name: string
+	T_start_time: string
+	T_end_time: string
+	T_text: string
+	Id: string
+	T_duration: string
+	T_prove_img: any
 }
 
 export interface ContractFormType {
-  T_uuid: string
-  T_number: string
-  T_task_id: string
-  T_product: any
-  T_type: any 
-  T_money: string
-  T_uuid_name:string
-  T_discount?: string
-  T_customer?: string
-  T_start_date?: string
-  T_end_date?: string
-  T_date: string
-  T_project?: string
-  T_remark: string
-  T_pdf: string
-  T_submit: string
-  T_recoveries: string
-  T_invoice: string
-  T_submit_name?: string
-  T_remit:any,
-  T_approval_money: any
-  T_approval_opinion: any
-  T_State: any
+	T_uuid: string
+	T_number: string
+	T_task_id: string
+	T_product: any
+	T_type: any
+	T_money: string
+	T_uuid_name: string
+	T_discount?: string
+	T_customer?: string
+	T_start_date?: string
+	T_end_date?: string
+	T_date: string
+	T_project?: string
+	T_remark: string
+	T_pdf: string
+	T_submit: string
+	T_recoveries: string
+	T_invoice: string
+	T_submit_name?: string
+	T_remit: any,
+	T_approval_money: any
+	T_approval_opinion: any
+	T_State: any
 }
+
 export interface MyPercentageFormType {
-  T_id: string
-  T_device_type: string
-  T_verify_type: string
-  T_company_uuid: string
-  T_verifyCompany_name: string
-  T_money: any
-  T_type: any
+	T_id: string
+	T_device_type: string
+	T_verify_type: string
+	T_company_uuid: string
+	T_verifyCompany_name: string
+	T_money: any
+	T_type: any
 }
+
 export interface MyPercentageFormTypeFrom {
-  T_id: string
-  // T_number: string
-  T_type: any 
-  // T_item: any
-  T_money:string
-  T_task_id:string
-  T_device_type:string
-  T_uuid_name:string
-  T_verify_type:string
-  T_verifyCompany?:any
-  T_uuid?: string
-  T_submit?: string
-  T_product?:any
-  T_state?:any
-  T_approval_money?:any
-  T_approval_opinion?:any
+	T_id: string
+	// T_number: string
+	T_type: any
+	// T_item: any
+	T_money: string
+	T_task_id: string
+	T_device_type: string
+	T_uuid_name: string
+	T_verify_type: string
+	T_verifyCompany?: any
+	T_uuid?: string
+	T_submit?: string
+	T_product?: any
+	T_state?: any
+	T_approval_money?: any
+	T_approval_opinion?: any
 }
+
 export interface royaltyType {
-  T_name: string
-  T_num:number
-  T_price:number
-  T_priceNum:number
+	T_name: string
+	T_num: number
+	T_price: number
+	T_priceNum: number
+}
+
+export interface PurchaseApproverInfoIn {
+	T_date: string
+	T_dept: string
+	T_uuid_name: string
+	T_State: number
+	T_submit_name: string
+	T_approver_name: string
+	T_remark: string
+	T_Detail: any
 }
 
 export const Project_State = [
-  { id: 1, name: '待审核' },
-  { id: 2, name: '进行中' },
-  { id: 3, name: '已完成' }
+	{id: 1, name: '待审核'},
+	{id: 2, name: '进行中'},
+	{id: 3, name: '已完成'}
 ]
 
 export const Project_F_State = [
-  { id: 3, name: '已完成' },
-  { id: 4, name: '已发绩效' }
+	{id: 3, name: '已完成'},
+	{id: 4, name: '已发绩效'}
 ]
 export const ReimburseFrom_F_State = [
-  { T_State: 2, name: '待审核' },
-  { T_State: 3, name: '审核通过' },
-  { T_State: 4, name: '审核不通过' },
+	{T_State: 2, name: '待审核'},
+	{T_State: 3, name: '审核通过'},
+	{T_State: 4, name: '审核不通过'},
 ]
 export const columns = [
-  { 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: '是否关联SN', prop: 'T_relation_sn', align: 'center ', width: 120, name: 'T_relation_sn' },
-  { label: '*数量', prop: 'count', align: 'center ', name: 'count' },
-  { label: '*已出库数量', prop: 'T_product_out', align: 'center ', name: 'T_product_out' },
-  { prop: 'operation', label: '操作', width: 80, fixed: 'right' }
+	{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: '是否关联SN', prop: 'T_relation_sn', align: 'center ', width: 120, name: 'T_relation_sn'},
+	{label: '*数量', prop: 'count', align: 'center ', name: 'count'},
+	{label: '*已出库数量', prop: 'T_product_out', align: 'center ', name: 'T_product_out'},
+	{prop: 'operation', label: '操作', width: 80, fixed: 'right'}
 ]
 export const Mycolumns = [
-  { type: 'index', label: '序号', width: 80, align: 'center ' },
-  { label: '项目', prop: 'T_name', align: 'center '},
-  { label: '*数量', prop: 'T_num', align: 'center ', name: 'T_num', width: 120 },
-  { label: '单价', prop: 'T_price', align: 'center '},
-  { label: '总价', prop: 'T_priceNum', align: 'center ', name: 'T_priceNum' },
-  { prop: 'operation', label: '操作', width: 80, fixed: 'right' }
+	{type: 'index', label: '序号', width: 80, align: 'center '},
+	{label: '项目', prop: 'T_name', align: 'center '},
+	{label: '*数量', prop: 'T_num', align: 'center ', name: 'T_num', width: 120},
+	{label: '单价', prop: 'T_price', align: 'center '},
+	{label: '总价', prop: 'T_priceNum', align: 'center ', name: 'T_priceNum'},
+	{prop: 'operation', label: '操作', width: 80, fixed: 'right'}
 ]
 /**
  * 提成明细
  */
 export const royalty = [
-  { type: 'index', label: '序号', width: 80, align: 'center ' },
-  { label: '项目', prop: 'T_name', align: 'center ', name: 'T_name' },
-  { label: '*数量', prop: 'T_num', align: 'center ' },
-  { label: '单价', prop: 'T_price', align: 'center ' },
-  { label: '总价', prop: 'T_priceNum', align: 'center ', name: 'T_priceNum' },
+	{type: 'index', label: '序号', width: 80, align: 'center '},
+	{label: '项目', prop: 'T_name', align: 'center ', name: 'T_name'},
+	{label: '*数量', prop: 'T_num', align: 'center '},
+	{label: '单价', prop: 'T_price', align: 'center '},
+	{label: '总价', prop: 'T_priceNum', align: 'center ', name: 'T_priceNum'},
 ]
 
 export const columnsRecoveries = [
-  { type: 'index', label: '序号', width: 80, align: 'center ' },
-  { label: '回款时间', prop: 'T_date', align: 'center ' },
-  { label: '回款金额', prop: 'T_money', align: 'center ' },
-  { prop: 'operation', label: '操作', width: 150, fixed: 'right' }
+	{type: 'index', label: '序号', width: 80, align: 'center '},
+	{label: '回款时间', prop: 'T_date', align: 'center '},
+	{label: '回款金额', prop: 'T_money', align: 'center '},
+	{prop: 'operation', label: '操作', width: 150, fixed: 'right'}
 ]
 export const labelsRecoveries = {
-  date: '回款时间',
-  money: '回款金额'
+	date: '回款时间',
+	money: '回款金额'
 }
 export const columnsInvoice = [
-  { type: 'index', label: '序号', width: 80, align: 'center ' },
-  { label: '开票时间', prop: 'T_date', align: 'center ' },
-  { label: '开票金额', prop: 'T_money', align: 'center ' },
-  { prop: 'operation', label: '操作', width: 150, fixed: 'right' }
+	{type: 'index', label: '序号', width: 80, align: 'center '},
+	{label: '开票时间', prop: 'T_date', align: 'center '},
+	{label: '开票金额', prop: 'T_money', align: 'center '},
+	{prop: 'operation', label: '操作', width: 150, fixed: 'right'}
 ]
 //打款明细
 export const columnsRemit = [
-  { type: 'index', label: '序号', width: 80, align: 'center ' },
-  { label: '打款时间', prop: 'T_date', align: 'center ' },
-  { label: '打款金额', prop: 'T_money', align: 'center ' },
-  { prop: 'operation', label: '操作', width: 150, fixed: 'right' }
+	{type: 'index', label: '序号', width: 80, align: 'center '},
+	{label: '打款时间', prop: 'T_date', align: 'center '},
+	{label: '打款金额', prop: 'T_money', align: 'center '},
+	{prop: 'operation', label: '操作', width: 150, fixed: 'right'}
 ]
 export const labelsInvoice = {
-  date: '开票时间',
-  money: '开票金额'
+	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',  name: 'T_price',align: 'center ', sortable: true },
-  { label: '总价', prop: 'T_total', align: 'center ', sortable: true },
-  { prop: 'operation', label: '操作', width: 80, fixed: 'right' }
+	{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', name: 'T_price', align: 'center ', sortable: true},
+	{label: '总价', prop: 'T_total', align: 'center ', sortable: true},
+	{prop: 'operation', label: '操作', width: 80, fixed: 'right'}
 ]
 
 export const options = [
-  { name: '已通过', id: 1 },
-  { name: '未通过', id: 2 },
-  { name: '待审核', id: 3 }
+	{name: '已通过', id: 1},
+	{name: '未通过', id: 2},
+	{name: '待审核', id: 3}
 ]
 export const options1 = [
-  { name: '待审核', id: 1 },
-  { name: '审核通过', id: 2 },
-  { name: '审核不通过', id: 3 },
-  { name: '已部分打款', id: 4 },
-  { name: '已全部打款', id: 5 }
+	{name: '待审核', id: 1},
+	{name: '审核通过', id: 2},
+	{name: '审核不通过', id: 3},
+	{name: '已部分打款', id: 4},
+	{name: '已全部打款', id: 5}
 ]
 export const options2 = [
-  { name: '待审核', id: 1 },
-  { name: '审核通过', id: 2 },
-  { name: '审核不通过', id: 3 },
-  // { name: '已部分打款', id: 4 },
-  { name: '已打款', id: 5 },
-  { name: '未提交审核', id: 6 }
+	{name: '待审核', id: 1},
+	{name: '审核通过', id: 2},
+	{name: '审核不通过', id: 3},
+	// { name: '已部分打款', id: 4 },
+	{name: '已打款', id: 5},
+	{name: '未提交审核', id: 6}
 ]
 export const options3 = [
-  { name: '验证实施', id: 1 },
-  { name: '报告编写', id: 2 },
+	{name: '验证实施', id: 1},
+	{name: '报告编写', id: 2},
 ]
 export const options4 = [
-	{ name: '未回款', id: 1 },
-	{ name: '已回款', id: 2 },
+	{name: '未回款', id: 1},
+	{name: '已回款', id: 2},
+]
+export const deptOptions = [
+	{name: '研发部', id: '研发部'},
+	{name: '生产部', id: '生产部'},
+	{name: '报告部', id: '报告部'},
+	{name: '实施部', id: '实施部'},
+	{name: '财务人事部', id: '财务人事部'},
+	{name: '销售部', id: '销售部'},
 ]
-export function useStapublicFun(data:any){
-  const a = options2.find((item:any)=>item.id == data)
-  return a?.name
+
+export function useStapublicFun(data: any) {
+	const a = options2.find((item: any) => item.id == data)
+	return a?.name
 
 }
+
 export function useTablePublic() {
-  const globalStore = GlobalStore()
-  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 tableRowClassName = (T_uuid: string, T_uuid2: string): any => {
-    let user: any = undefined
-    if (T_uuid === T_uuid2) {
-      user = T_uuid2
-    }
-    if (user !== undefined) {
-      let rowBackground = {
-        background: '#e3eefd',
-        color: '#0d7bff'
-      }
-      return rowBackground
-    } else {
-      return ''
-    }
-  }
-  const resetForm = (formEl: FormInstance | undefined) => {
-    if (!formEl) return
-    formEl.resetFields()
-  }
-
-  const searchOnTableList = (TableRef: any) => TableRef?.searchTable()
-  const updateOnTableList = (TableRef: any) => TableRef?.getTableList()
-
-  return {
-    validate_T_product,
-    resetForm,
-    globalStore,
-    tableRowClassName,
-    searchOnTableList,
-    updateOnTableList
-  }
+	const globalStore = GlobalStore()
+	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 tableRowClassName = (T_uuid: string, T_uuid2: string): any => {
+		let user: any = undefined
+		if (T_uuid === T_uuid2) {
+			user = T_uuid2
+		}
+		if (user !== undefined) {
+			let rowBackground = {
+				background: '#e3eefd',
+				color: '#0d7bff'
+			}
+			return rowBackground
+		} else {
+			return ''
+		}
+	}
+	const resetForm = (formEl: FormInstance | undefined) => {
+		if (!formEl) return
+		formEl.resetFields()
+	}
+
+	const searchOnTableList = (TableRef: any) => TableRef?.searchTable()
+	const updateOnTableList = (TableRef: any) => TableRef?.getTableList()
+
+	return {
+		validate_T_product,
+		resetForm,
+		globalStore,
+		tableRowClassName,
+		searchOnTableList,
+		updateOnTableList
+	}
 }

+ 28 - 4
src/views/purchase/MyPurchase.vue

@@ -3,9 +3,10 @@ import {defineAsyncComponent, nextTick, reactive, ref} from 'vue'
 import {ElMessage, ElMessageBox} from 'element-plus'
 import TableBase from '@/components/TableBase/index.vue'
 import {useTablePublic} from '@/hooks/useTablePublic'
-import {Delete, Edit, View} from '@element-plus/icons-vue'
+import {Delete, Edit, Finished, View} from '@element-plus/icons-vue'
 import {ColumnProps} from '@/components/TableBase/interface/index'
 import {Purchase_Del, Purchase_User_list} from '@/api/purchase/index'
+import {Purchase_Excel} from "@/api/purchase";
 
 const TableRef = ref<InstanceType<typeof TableBase> | null>(null)
 const {globalStore, updateOnTableList} = useTablePublic()
@@ -15,11 +16,13 @@ const PurchaseForm = defineAsyncComponent(() => import(/*webpackChunkName: 'Purc
 const columns: ColumnProps[] = [
 	{type: 'index', label: '序号', width: 80},
 	{prop: 'T_date', label: '申请时间'},
+	{prop: 'T_dept', label: '申请部门'},
 	{prop: 'T_uuid_name', label: '申请人'},
 	{prop: 'T_State', label: '状态', name: 'T_State'},
 	{prop: 'T_submit_name', label: '提交人'},
+	{prop: 'T_approver_name', label: '审批人'},
 	{prop: 'T_remark', label: '备注', width: 125},
-	{prop: 'operation', label: '操作', width: 200, fixed: 'right'}
+	{prop: 'operation', label: '操作', width: 260, fixed: 'right'}
 ]
 // 搜索
 const options = reactive([
@@ -57,6 +60,18 @@ const DeletePurchase = (Id: number) => {
 			ElMessage.warning('取消成功!')
 		})
 }
+const exportExcel = async (Id: number) => {
+
+	const result:any = await Purchase_Excel({
+		User_tokey: globalStore.GET_User_tokey,
+		T_id: Id,
+	})
+	if (result.Code === 200) {
+		window.open(result.Data)
+	}
+
+}
+
 const openPurchaseDrawer = (type: string, row?: any) => purchaseFormRef.value?.purchaseFromOpen(type, row)
 </script>
 <template>
@@ -97,8 +112,10 @@ const openPurchaseDrawer = (type: string, row?: any) => purchaseFormRef.value?.p
 			</template>
 
 			<template #T_State="{ row }">
-				<el-tag v-if="row.T_State === 1" effect="dark">待采购</el-tag>
-				<el-tag v-else type="success" effect="dark">已采购</el-tag>
+				<el-tag v-if="row.T_State === 1" type="primary" effect="dark">待采购</el-tag>
+				<el-tag v-else-if="row.T_State === 2" type="success" effect="dark">已采购</el-tag>
+				<el-tag v-else-if="row.T_State === 3" type="warning" effect="dark">待审批</el-tag>
+				<el-tag v-else type="danger" effect="dark">未通过</el-tag>
 			</template>
 			<template #right="{ row }">
 				<el-button link type="success" size="small" :icon="View" @click="openPurchaseDrawer('view', row)"
@@ -106,6 +123,13 @@ const openPurchaseDrawer = (type: string, row?: any) => purchaseFormRef.value?.p
 				</el-button>
 				<el-button
 					link
+					type="success"
+					size="small"
+					:icon="Finished"
+					@click="exportExcel(row.Id)"
+				>导出</el-button>
+				<el-button
+					link
 					type="primary"
 					size="small"
 					:icon="Edit"

+ 106 - 11
src/views/purchase/Purchase.vue

@@ -1,12 +1,19 @@
 <script setup lang="ts">
-import {defineAsyncComponent, nextTick, reactive, ref} from 'vue'
+import {defineAsyncComponent, nextTick, onMounted, reactive, ref} from 'vue'
 import {ElMessage, ElMessageBox} from 'element-plus'
-import {Delete, Edit, View} from '@element-plus/icons-vue'
+import {Delete, Edit, Finished, View} from '@element-plus/icons-vue'
 import TableBase from '@/components/TableBase/index.vue'
 import {useTablePublic} from '@/hooks/useTablePublic'
 import {ColumnProps} from '@/components/TableBase/interface/index'
-import {Purchase_Approval, Purchase_Del, Purchase_List} from '@/api/purchase/index'
-
+import {
+	Purchase_Apply_User_List,
+	Purchase_Del,
+	Purchase_Excel,
+	Purchase_List,
+	Purchase_Stat_Excel
+} from '@/api/purchase/index'
+import { deptOptions } from '@/hooks/useTablePublic'
+import {stockInexcel, Storehouse_VerifyContract_Recover_User_List} from "@/api/storehouse";
 interface UserInfoIn {
 	T_name: string
 	T_type_name: string
@@ -19,11 +26,13 @@ interface UserInfoIn {
 const columns: ColumnProps[] = [
 	{type: 'index', label: '序号', width: 80},
 	{prop: 'T_date', label: '申请时间'},
+	{prop: 'T_dept', label: '申请部门'},
 	{prop: 'T_uuid_name', label: '申请人'},
 	{prop: 'T_State', label: '状态', name: 'T_State'},
 	{prop: 'T_submit_name', label: '提交人'},
+	{prop: 'T_approver_name', label: '审批人'},
 	{prop: 'T_remark', label: '备注', width: 125},
-	{prop: 'operation', label: '操作', width: 200, fixed: 'right'}
+	{prop: 'operation', label: '操作', width: 260, fixed: 'right'}
 ]
 // 搜索
 const options = reactive([
@@ -41,6 +50,8 @@ const PurchaseForm = defineAsyncComponent(() => import(/*webpackChunkName: 'Purc
 const T_date = ref<string[]>([])
 const initParam = reactive({
 	User_tokey: globalStore.GET_User_tokey,
+	T_uuid: '',
+	T_dept: '',
 	T_state: '',
 	T_end_date: '',
 	T_start_date: ''
@@ -68,6 +79,66 @@ const DeletePurchase = (Id: number) => {
 			ElMessage.warning('取消成功!')
 		})
 }
+
+const exportExcel = async (Id: number) => {
+
+	const result:any = await Purchase_Excel({
+		User_tokey: globalStore.GET_User_tokey,
+		T_id: Id,
+	})
+	if (result.Code === 200) {
+		window.open(result.Data)
+	}
+
+}
+
+const exportStatExcel = async () => {
+
+	const result:any = await Purchase_Stat_Excel({
+		User_tokey: globalStore.GET_User_tokey,
+		T_uuid: initParam.T_uuid,
+		T_dept: initParam.T_dept,
+		T_state: initParam.T_state,
+		T_end_date: initParam.T_end_date,
+		T_start_date: initParam.T_start_date
+	})
+	if (result.Code === 200) {
+		window.open(result.Data)
+	}
+}
+
+interface ListItem {
+	value: string
+	label: string
+}
+const loading = ref(false)
+const list = ref<ListItem[]>([])
+const optionsData = ref<ListItem[]>([])
+const remoteMethod = async (query: string) => {
+	if (query) {
+		loading.value = true
+		setTimeout(() => {
+			loading.value = false
+			optionsData.value = list.value.filter((item: any) => {
+				return item.label.toLowerCase().includes(query.toLowerCase())
+			})
+		}, 200)
+	} else {
+		optionsData.value = list.value
+	}
+}
+const click2 = async () => { optionsData.value = list.value }
+onMounted(async () => {
+	const result: any = await Purchase_Apply_User_List({})
+	let arr =  []
+	if (result?.Data !== null) {
+		arr = result.Data.Data
+	}
+
+	list.value = arr.map((item: any) => {
+		return { value: item.T_uuid, label: item.T_name }
+	})
+})
 </script>
 <template>
 	<div class="purchase">
@@ -80,7 +151,7 @@ const DeletePurchase = (Id: number) => {
 			<template #table-header>
 				<div class="input-suffix">
 					<el-row :gutter="20" style="margin-bottom: 0">
-						<el-col :xl="6" :lg="6" :md="5" style="display: flex">
+						<el-col :xl="6" :lg="6" :md="6" style="display: flex">
 							<span class="inline-flex items-center">申请日期:</span>
 							<el-date-picker
 								v-model="T_date"
@@ -92,32 +163,56 @@ const DeletePurchase = (Id: number) => {
 								value-format="YYYY-MM-DD"
 							/>
 						</el-col>
-						<el-col :xl="10" :md="12">
+						<el-col :xl="6" :md="6">
+							<span class="inline-flex items-center">部门:</span>
+							<el-select v-model="initParam.T_dept" class="w-50 m-2" clearable placeholder="请选择部门~">
+								<el-option v-for="item in deptOptions" :key="item.id" :label="item.name" :value="item.id"/>
+							</el-select>
+						</el-col>
+						<el-col :xl="6" :lg="6"  :md="6" class="d-flex">
+							<span class="inline-flex items-center">申请人:</span>
+							<el-select v-model="initParam.T_uuid" filterable remote reserve-keyword placeholder="申请人"
+									   :remote-method="remoteMethod" :loading="loading" @click="click2" clearable style="width: 150px;">
+								<el-option v-for="item in optionsData" :key="item.value" :label="item.label" :value="item.value" />
+							</el-select>
+						</el-col>
+						<el-col :xl="6" :md="6">
 							<span class="inline-flex items-center">状态:</span>
 							<el-select v-model="initParam.T_state" class="w-50 m-2" 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-button type="success" @click="exportStatExcel">导出</el-button>
 						</el-col>
 					</el-row>
 				</div>
 			</template>
 			<template #T_State="{ row }">
-				<el-tag v-if="row.T_State === 1" effect="dark">待采购</el-tag>
-				<el-tag v-else type="success" effect="dark">已采购</el-tag>
+				<el-tag v-if="row.T_State === 1" type="primary" effect="dark">待采购</el-tag>
+				<el-tag v-else-if="row.T_State === 2" type="success" effect="dark">已采购</el-tag>
+				<el-tag v-else-if="row.T_State === 3" type="warning" effect="dark">待审批</el-tag>
+				<el-tag v-else type="danger" effect="dark">未通过</el-tag>
 			</template>
 			<template #right="{ row }">
 				<el-button link type="success" size="small" :icon="View" @click="openPurchaseDrawer('view', row)">详情
 				</el-button>
 				<el-button
 					link
+					type="success"
+					size="small"
+					:icon="Finished"
+					@click="exportExcel(row.Id)"
+				>导出
+				</el-button>
+				<el-button
+					link
 					type="primary"
 					size="small"
 					:icon="Edit"
 					@click="openPurchaseDrawer('edit', row)"
 				>编辑
-				</el-button
-				>
+				</el-button>
+
 				<el-button
 					link
 					type="danger"

+ 229 - 0
src/views/purchase/PurchaseApprover.vue

@@ -0,0 +1,229 @@
+<script setup lang="ts">
+import {nextTick, ref} from 'vue'
+import {ElMessage} from 'element-plus'
+import {GlobalStore} from '@/stores/index'
+import TableBase from '@/components/TableBase/index.vue'
+import {ColumnProps} from '@/components/TableBase/interface/index'
+import {Purchase_Approval, Purchase_Audit_List, Purchase_Get} from '@/api/purchase/index'
+import {PurchaseApproverInfoIn, useTablePublic} from '@/hooks/useTablePublic'
+
+const TableRef = ref()
+const globalStore = GlobalStore()
+const initParam = {User_tokey: globalStore.GET_User_tokey}
+const columns: ColumnProps[] = [{prop: 'T_uuid_name', label: '姓名'}]
+const {tableRowClassName} = useTablePublic()
+const tableRowClassNameHandle = (data: any): any => tableRowClassName(data.row.Id, userInfo.value.Id)
+const gridData: any = ref([])
+const userInfo: any = ref<PurchaseApproverInfoIn>({
+	T_date: '',
+	T_dept: '',
+	T_uuid_name: '',
+	T_State: 0,
+	T_submit_name: '',
+	T_approver_name: '',
+	T_remark: '',
+	T_Detail: '',
+})
+
+
+const getApproveParams = (row: any) => {
+	userInfo.value.Id = ''
+	// setTimeout(() => {
+	//   userInfo.value = { ...row }
+	// }, 100)
+
+	nextTick(async () => {
+
+		userInfo.value = {...row}
+		// form.value.T_approver = row.T_approver_name
+		// form.value.T_uuid = row.T_uuid_name
+		const res: any = await Purchase_Get({T_id: row.Id})
+		if (res.Code === 200) {
+			userInfo.value = {...res.Data}
+			// purchaseDetailRef.value?.setDetailData(res.Data.T_Detail)
+		}
+
+	})
+
+}
+
+const ApprovalPurchase = async (T_State: number) => {
+	if (!userInfo.value.Id) return
+	const params = {
+		User_tokey: globalStore.GET_User_tokey,
+		T_id: userInfo.value.Id,
+		T_State
+	}
+	const res: any = await Purchase_Approval(params)
+	if (res.Code === 200) {
+		if (T_State) {
+			ElMessage.success('审核通过!')
+		} else {
+			ElMessage.warning('审核不通过!')
+		}
+		nextTick(() => {
+			TableRef.value.getTableList()
+			userInfo.value = {} as PurchaseApproverInfoIn
+		})
+	}
+}
+</script>
+
+<template>
+	<div class="Overtime">
+		<div style="width: 290px" class="Overtime-table">
+			<TableBase
+				ref="TableRef"
+				:columns="columns"
+				:requestApi="Purchase_Audit_List"
+				:initParam="initParam"
+				layout="prev, pager, next"
+				:rowClick="getApproveParams"
+				:tableRowClassName="tableRowClassNameHandle"
+			>
+				<template #table-header>
+					<h3 class="title">待处理</h3>
+				</template>
+			</TableBase>
+		</div>
+		<transition
+			leave-active-class="animate__animated animate__fadeOutRight"
+			enter-active-class="animate__animated animate__fadeInLeft"
+		>
+			<el-row class="h-100 f-1 margin-left-3 Approver-container" v-if="userInfo.Id">
+				<el-col :span="24" class="h-100" style="overflow: auto">
+					<el-card class="m-b-3">
+						<div class="Approver-content">
+							<div>申请日期:{{ userInfo.T_date }}</div>
+							<div>申请部门:{{ userInfo.T_dept }}</div>
+							<div>申请人: {{ userInfo.T_uuid_name }}</div>
+							<div>提交人: {{ userInfo.T_submit_name }}</div>
+							<div>审批人: {{ userInfo.T_approver_name }}</div>
+							<div>
+								<span class="ml-3 w-35 text-gray-600 inline-flex items-center">备注:</span>
+								{{ userInfo.T_remark }}
+							</div>
+							<div>采购明细:</div>
+
+							<div>
+
+								<el-table :data="userInfo.T_Detail" border max-height="100%">
+									<el-table-column type="index" label="序号" width="100"/>
+									<el-table-column property="T_name" label="名称"/>
+									<el-table-column property="T_model" label="型号"/>
+									<el-table-column property="T_spec" label="规格"/>
+									<el-table-column property="T_quantity" label="数量"/>
+									<el-table-column property="T_reference_site" label="参考网址"/>
+									<el-table-column property="T_demand" label="需求"/>
+									<el-table-column property="T_remark" label="备注"/>
+									<el-table-column property="T_unit_price" label="采购单价"/>
+								</el-table>
+							</div>
+
+						</div>
+					</el-card>
+					<div class="btn">
+						<el-button type="primary" @click="ApprovalPurchase(1)">通过</el-button>
+						<el-button type="danger" @click="ApprovalPurchase(4)">不通过</el-button>
+					</div>
+				</el-col>
+			</el-row>
+		</transition>
+	</div>
+</template>
+
+<style scoped lang="scss">
+@import '@/styles/var.scss';
+
+.Approver-container {
+	z-index: 0;
+	width: 100%;
+	height: 100%;
+	display: flex;
+	justify-content: center;
+	.Approver-content {
+		flex: 1;
+		display: flex;
+		flex-direction: column;
+		overflow: auto;
+		// justify-content: space-between;
+		margin-top: 20px;
+		font-size: 16px;
+		color: #8B8E94FF;
+		div {
+			margin-bottom: 10px;
+		}
+	}
+}
+
+.Overtime {
+	display: flex;
+	height: 100%;
+
+	.Overtime-table {
+		@include f-direction;
+		z-index: 1;
+
+		:deep(.table-header) {
+			margin-bottom: 0;
+		}
+	}
+
+	overflow: hidden;
+
+	.img {
+		width: 200px;
+	}
+
+	.b-show-0 {
+		box-shadow: none;
+		font-size: 16px;
+		font-weight: 500;
+
+		.el-row {
+			margin-bottom: 10px;
+
+			.el-col {
+				padding: 15px;
+			}
+		}
+	}
+
+	:deep(.el-card .el-card__body) {
+		font-weight: bold;
+		// color: var(--el-text-color-secondary);
+	}
+
+	.f-1 {
+		flex: 1;
+	}
+
+	.title {
+		width: 100%;
+		text-align: center;
+	}
+
+	.btn {
+		margin-top: 1rem;
+		display: flex;
+		justify-content: center;
+
+	}
+
+	.info-content {
+		display: flex;
+		// color: #606266;
+
+		.info-name {
+			display: flex;
+			// flex-direction: column;
+			align-items: center;
+			padding-left: 0.75rem;
+
+			span:first-child {
+				margin-right: 2rem;
+			}
+		}
+	}
+}
+</style>

+ 1 - 1
src/views/purchase/PurchaseDetail.vue

@@ -159,7 +159,7 @@ const typeTip = ref(props.typeTip)
       <el-form-item label="规格:" :label-width="formLabelWidth" prop="T_spec">
         <el-input v-model="form.T_spec" type="text" autocomplete="off" placeholder="请输入规格" />
       </el-form-item>
-		<el-form-item label="数量:" :label-width="formLabelWidth" prop="T_spec">
+		<el-form-item label="数量:" :label-width="formLabelWidth" prop="T_quantity">
 			<el-input v-model="form.T_quantity" type="text" autocomplete="off" placeholder="请输入数量" />
 		</el-form-item>
 		<el-form-item label="参考网址:" :label-width="formLabelWidth" prop="T_reference_site">

+ 52 - 14
src/views/purchase/PurchaseForm.vue

@@ -7,6 +7,7 @@ import Drawer from '@/components/Drawer/index.vue'
 import type { FormInstance, FormRules } from 'element-plus'
 import { Purchase_Get, Purchase_Edit, Purchase_Add } from '@/api/purchase/index'
 import receiveUser from '@/views/storehouse/outStock/receiveUser.vue'
+import { deptOptions } from '@/hooks/useTablePublic'
 
 const typeTip = ref('')
 const formLabelWidth = ref('120px')
@@ -16,9 +17,12 @@ const ruleFormRef = ref<FormInstance>()
 const drawerRef = ref<InstanceType<typeof Drawer> | null>(null)
 const purchaseDetailRef = ref<InstanceType<typeof PurchaseDetail> | null>(null)
 const userDrawerRef = ref<InstanceType<typeof receiveUser> | null>(null)
+const approverDrawerRef = ref<InstanceType<typeof receiveUser> | null>(null)
+
 const form = ref({
   Id: '',
   T_date: '',
+  T_dept: '',
   T_uuid: '',
   T_uuid_name: '',
   T_detail: '',
@@ -26,8 +30,8 @@ const form = ref({
   T_State: '',
   T_approver: '',
   T_approver_name: '',
-
 })
+
 const rules = reactive<FormRules>({
   T_name: [{ required: true, message: '请输入采购申请名称', trigger: 'blur' }]
 })
@@ -53,7 +57,6 @@ const addPurchase = (formEl: FormInstance | undefined) => {
         User_tokey,
         ...form.value,
         T_detail: detail,
-        T_approver: form.value.T_uuid
       }
       if (typeTip.value === 'new') {
         res = await Purchase_Add(params)
@@ -73,19 +76,26 @@ const addPurchase = (formEl: FormInstance | undefined) => {
   })
 }
 
+const selectUser = () => userDrawerRef.value?.openDrawer()
 const getPurchaseInfo = ({ T_uuid, T_name }: { T_uuid: string; T_name: string }) => {
-	form.value.T_uuid_name = T_name
 	form.value.T_uuid = T_uuid
+	form.value.T_uuid_name = T_name
+}
+
+const selectApprover = () => approverDrawerRef.value?.openDrawer()
+
+const getApproverInfo = ({ T_uuid, T_name }: { T_uuid: string; T_name: string }) => {
+	form.value.T_approver = T_uuid
+	form.value.T_approver_name = T_name
 }
-const selectUser = () => userDrawerRef.value?.openDrawer()
 
 const purchaseFromOpen = (type: string, row?: any) => {
   typeTip.value = type
   nextTick(async () => {
     if (typeTip.value !== 'new') {
       form.value = { ...row }
-      form.value.T_approver = row.T_approver_name
-      form.value.T_uuid = row.T_approver
+      // form.value.T_approver = row.T_approver_name
+      // form.value.T_uuid = row.T_uuid_name
       const res: any = await Purchase_Get({ T_id: row.Id })
       if (res.Code === 200) {
         purchaseDetailRef.value?.setDetailData(res.Data.T_Detail)
@@ -111,6 +121,8 @@ const getTitle = (type: string) => {
 
 const emit = defineEmits<{ (event: 'onTableList'): void }>()
 
+
+
 defineExpose({
   purchaseFromOpen
 })
@@ -127,17 +139,24 @@ defineExpose({
           style="flex: 0 0 50%"
           class="my-date-picker"
           v-model="form.T_date"
-		  :disabled="purchaseName !=='myPurchase'"
+		  :disabled="! (typeTip === 'new' || typeTip === 'edit')"
           type="date"
           placeholder="申请日期"
           format="YYYY-MM-DD"
           value-format="YYYY-MM-DD"
         />
       </el-form-item>
-      <el-form-item  label="申请人:" :label-width="formLabelWidth" prop="T_uuid">
+		<el-form-item  label="申请部门:" :label-width="formLabelWidth" prop="T_dept">
+			<el-select 	:disabled="! (typeTip === 'new' || typeTip === 'edit')" v-model="form.T_dept" class="w-50" clearable placeholder="请选择申请部门">
+				<el-option v-for="item in deptOptions" :key="item.id" :label="item.name" :value="item.id"/>
+			</el-select>
+		</el-form-item>
+
+		<el-form-item  label="申请人:" :label-width="formLabelWidth" prop="T_uuid_name">
 			<el-input
+				:key="Math.random()"
 				v-model="form.T_uuid_name"
-				:disabled="purchaseName !=='myPurchase'"
+				:disabled="! (typeTip === 'new' || typeTip === 'edit')"
 				placeholder="请选择申请人"
 				class="w-50"
 				@focus="selectUser"
@@ -152,6 +171,16 @@ defineExpose({
           :typeTip="typeTip"
         ></PurchaseDetail>
       </el-form-item>
+		<el-form-item label="审批人:" :label-width="formLabelWidth" prop="T_approver_name">
+			<el-input
+				:key="Math.random()"
+				:disabled="! (typeTip === 'new' || typeTip === 'edit')"
+				v-model="form.T_approver_name"
+				autocomplete="off"
+				placeholder="审请选择批人"
+				class="w-50"
+				@focus="selectApprover" />
+		</el-form-item>
 	<el-form-item v-if="purchaseName !== 'myPurchase'"  label="状态:" :label-width="formLabelWidth" prop="T_state">
 		<el-radio-group v-model="form.T_State" :disabled="! (typeTip === 'new' || typeTip === 'edit')">
 			<el-radio :label="1">待采购</el-radio>
@@ -178,12 +207,21 @@ defineExpose({
         >
       </el-form-item>
     </el-form>
-	  <receiveUser
-		  ref="userDrawerRef"
-		  @onUserInfo="getPurchaseInfo"
-		  title="选择申请人"
-	  ></receiveUser>
+
   </Drawer>
+	<receiveUser
+		ref="userDrawerRef"
+		:key="Math.random()"
+		@onUserInfo="getPurchaseInfo"
+		title="选择申请人"
+	></receiveUser>
+	<receiveUser
+		:dept_leader="1"
+		ref="approverDrawerRef"
+		:key="Math.random()"
+		@onUserInfo="getApproverInfo"
+		title="选择审批人"
+	></receiveUser>
 </template>
 <style scoped lang="scss">
 .btn {

+ 56 - 15
src/views/storehouse/ValidationTool/validation.vue

@@ -89,17 +89,20 @@ const recordColumns: ColumnProps[] = [
 ]
 const operationColumns: ColumnProps[] = [
 	{type: 'index', label: '序号', width: 80},
-	{prop: 'BatchNumber', label: '操作时间',  width: 190},
-	{prop: 'T_state', label: '操作', name: 'T_state'},
+	{prop: 'BatchNumber', label: '操作时间', width: 190},
+	{prop: 'T_state', label: '操作', name: 'T_state', width: 80},
 	{prop: 'LendUser', label: '借出(归还)人', ellipsis: true},
-	{prop: 'T_project', label: '关联项目', ellipsis: true},
+	{prop: 'T_project', label: '关联项目', name:'T_project',  ellipsis: true,  width: 300},
 	{prop: 'T_remark', label: '备注',  ellipsis: true},
+	{prop: 'T_sn_quantity', label: '设备数量'},
 	{prop: 'operation', label: 'SN', width: 100, fixed: 'right', align: 'center' }
 
 ]
 const snColumns = [
 	{ type: 'index', label: '序号', width: 80, align: 'center ' },
-	{ label: 'SN', prop: 'sn', align: 'center ' }
+	{ label: '关联项目', prop: 'T_project', align: 'center ' },
+	{ label: '数量', prop: 'T_number', align: 'center ' },
+	{ label: 'SN', prop: 'T_sn', align: 'center ' }
 ]
 // 搜索
 const options = reactive([
@@ -470,7 +473,7 @@ const operationPreview = () => {
 	operationTableRef.value?.searchTable()
 }
 const tableSnData = ref<any[]>([])
-const previewSn = (devicelist: string[]) => {
+const previewSn = (devicelist: any[]) => {
 	drawerSnRef.value?.openDrawer()
 	if (!devicelist) return
 	tableSnData.value = devicelist.map((item: string) => {
@@ -887,23 +890,23 @@ onMounted(() => {
 								</el-select>
 							</el-col>
 							<el-col :xl="4" :lg="4" :md="4">
-								<span class="inline-flex items-center">借出人</span>
+								<span class="inline-flex items-center">借出(归还)人</span>
 								<el-input
 									class="w-50 m-2"
 									v-model="recordInitParam.LendUser"
 									type="text"
-									placeholder="按借出人搜索"
+									placeholder="按借出(归还)人搜索"
 									clearable
 									@change="recordSearchHandle"
 								/>
 							</el-col>
 							<el-col :xl="4" :lg="4" :md="4">
-								<span class="inline-flex items-center">借出项目</span>
+								<span class="inline-flex items-center">关联项目</span>
 								<el-input
 									class="w-50 m-2"
 									v-model="recordInitParam.T_project"
 									type="text"
-									placeholder="按借出项目搜索"
+									placeholder="按关联项目搜索"
 									clearable
 									@change="recordSearchHandle"
 								/>
@@ -925,6 +928,7 @@ onMounted(() => {
 						</el-row>
 					</div>
 				</template>
+
 				<template #T_state="{ row }">
 					<el-tag v-if="row.T_state == 1" type="success" effect="dark"> 已出库</el-tag>
 					<el-tag v-if="row.T_state == 2" effect="dark">未出库</el-tag>
@@ -972,7 +976,7 @@ onMounted(() => {
 									class="w-50 m-2"
 									v-model="operationInitParam.LendUser"
 									type="text"
-									placeholder="按借出人搜索"
+									placeholder="按借出(归还)人搜索"
 									clearable
 									@change="operationSearchHandle"
 								/>
@@ -983,7 +987,7 @@ onMounted(() => {
 									class="w-50 m-2"
 									v-model="operationInitParam.T_project"
 									type="text"
-									placeholder="按借出项目搜索"
+									placeholder="按关联项目搜索"
 									clearable
 									@change="operationSearchHandle"
 								/>
@@ -1002,13 +1006,15 @@ onMounted(() => {
 					<el-tag v-if="row.T_state == 4" effect="dark" type="danger">报废</el-tag>
 					<el-tag v-if="row.T_state == 5" effect="dark" type="info">损坏</el-tag>
 				</template>
+				<template #T_project="{ row }">
+					<div v-for="(item, index) in row.T_project" :key="index"> {{ item }} </div>
+				</template>
 				<template #right="{ row }">
 					<el-button type="primary"  @click="previewSn(row.T_sn_List)">查看</el-button>
-
 				</template>
 			</TableBase>
 		</el-dialog>
-		<Drawer ref="drawerSnRef" :handleClose="callbackSnDrawer" size="30%">
+		<Drawer ref="drawerSnRef" :handleClose="callbackSnDrawer" size="40%">
 			<el-table
 				:data="tableSnData"
 				style="width: 100%; height: 99%"
@@ -1017,11 +1023,46 @@ onMounted(() => {
           height: '50px'
         }"
 			>
-				<template v-for="item in snColumns" :key="item">
+				<template v-for="item in snColumns" :key="item.prop">
 					<el-table-column show-overflow-tooltip v-if="item.type === 'index'" v-bind="item" />
-					<el-table-column show-overflow-tooltip v-if="item.prop" v-bind="item" />
+					<el-table-column
+						show-overflow-tooltip
+						v-else-if="item.prop === 'T_project'"
+						:label="item.label"
+						:width="item.width"
+						align="center"
+					>
+						<template #default="scope">
+							{{scope.row.sn.T_project}}
+						</template>
+					</el-table-column>
+					<el-table-column
+						show-overflow-tooltip
+						v-else-if="item.prop === 'T_number'"
+						:label="item.label"
+						:width="item.width"
+						align="center"
+					>
+						<template #default="scope">
+							{{ scope.row.sn.T_sn.length }}
+						</template>
+					</el-table-column>
+					<el-table-column
+						show-overflow-tooltip
+						v-else-if="item.prop === 'T_sn'"
+						:label="item.label"
+						:width="item.width"
+						align="center"
+					>
+						<template #default="scope">
+							<div v-for="(item, index) in scope.row.sn.T_sn" :key="index"> {{ item }} </div>
+						</template>
+					</el-table-column>
+
+
 				</template>
 			</el-table>
+
 		</Drawer>
 		<snAdd ref="btnRef" @successFun="successFun"></snAdd>