695593266@qq.com 2 месяцев назад
Родитель
Сommit
c3e35c5a57

+ 443 - 243
api/wt/index.js

@@ -1,208 +1,243 @@
-import {
-	get,
-	put,
-	putJ,
-	postJ
-} from "@/utils/request";
+import { get, put, putJ, postJ } from "@/utils/request";
 import Vue from "vue";
 
-
 //获取我的消息列表
 export async function notifyMessagePageAPI(params, loding = true) {
-	const res = await postJ(
-		Vue.prototype.apiUrl + `/sys/notifymessage/page`, params, loding
-	);
-	if (res.code == 0) {
-		return res.data;
-	}
-	return Promise.reject(new Error(res.message));
+  const res = await postJ(
+    Vue.prototype.apiUrl + `/sys/notifymessage/page`,
+    params,
+    loding,
+  );
+  if (res.code == 0) {
+    return res.data;
+  }
+  return Promise.reject(new Error(res.message));
 }
 
 //更新已读-指定消息ID
 export async function updateNotifyMessageReadByIdAPI(params, loding = true) {
-	const res = await postJ(
-		Vue.prototype.apiUrl + `/sys/notifymessage/updateNotifyMessageRead`, params, loding
-	);
-	if (res.code == 0) {
-		return res.data;
-	}
-	return Promise.reject(new Error(res.message));
+  const res = await postJ(
+    Vue.prototype.apiUrl + `/sys/notifymessage/updateNotifyMessageRead`,
+    params,
+    loding,
+  );
+  if (res.code == 0) {
+    return res.data;
+  }
+  return Promise.reject(new Error(res.message));
 }
 //获取某用户的未读消息条数
 export async function getUnreadNotifyMessageCountAPI() {
-	const res = await get(
-		Vue.prototype.apiUrl + `/sys/notifymessage/getUnreadNotifyMessageCount`, '', false
-	);
-	if (res.code == 0) {
-		return res.data;
-	}
-	return Promise.reject(new Error(res.message));
+  const res = await get(
+    Vue.prototype.apiUrl + `/sys/notifymessage/getUnreadNotifyMessageCount`,
+    "",
+    false,
+  );
+  if (res.code == 0) {
+    return res.data;
+  }
+  return Promise.reject(new Error(res.message));
 }
 
 //获取待办事项列表
 export async function getTodoTaskPage(query, loding = true) {
-	const res = await postJ(
-		Vue.prototype.apiUrl + `/bpm/task/todo-page`, query, loding
-	);
-	if (res.code == 0) {
-		return res.data;
-	}
-	return Promise.reject(new Error(res.message));
+  const res = await postJ(
+    Vue.prototype.apiUrl + `/bpm/task/todo-page`,
+    query,
+    loding,
+  );
+  if (res.code == 0) {
+    return res.data;
+  }
+  return Promise.reject(new Error(res.message));
 }
 
 export async function getTodoList(query, loding = true) {
-	const res = await postJ(
-		Vue.prototype.apiUrl + `/bpm/task/todo-page`, query, loding
-	);
-	if (res.code == 0) {
-		return res.data;
-	}
-	return Promise.reject(new Error(res.message));
+  const res = await postJ(
+    Vue.prototype.apiUrl + `/bpm/task/todo-page`,
+    query,
+    loding,
+  );
+  if (res.code == 0) {
+    return res.data;
+  }
+  return Promise.reject(new Error(res.message));
 }
 
-
 export async function rejectTask(data) {
-	const res = await putJ(Vue.prototype.apiUrl + `/bpm/task/reject`, data, true)
-	if (res.code == 0) {
-		return res.data;
-	}
-	return Promise.reject(new Error(res.message));
-
+  const res = await putJ(Vue.prototype.apiUrl + `/bpm/task/reject`, data, true);
+  if (res.code == 0) {
+    return res.data;
+  }
+  return Promise.reject(new Error(res.message));
 }
 
 // 作废
 export async function cancelTask(data) {
-	const res = await postJ(Vue.prototype.apiUrl + `/bpm/process-instance/cancel`, data)
-	if (res.code == 0) {
-		return res.data;
-	}
-	return Promise.reject(new Error(res.message));
-
+  const res = await postJ(
+    Vue.prototype.apiUrl + `/bpm/process-instance/cancel`,
+    data,
+  );
+  if (res.code == 0) {
+    return res.data;
+  }
+  return Promise.reject(new Error(res.message));
 }
 
 //获取已办事项列表
 export async function getDoneTaskPage(query) {
-	const res = await get(
-		Vue.prototype.apiUrl + `/bpm/task/done-page`, query, true
-	);
-	if (res.code == 0) {
-		return res.data;
-	}
-	return Promise.reject(new Error(res.message));
+  const res = await get(
+    Vue.prototype.apiUrl + `/bpm/task/done-page`,
+    query,
+    true,
+  );
+  if (res.code == 0) {
+    return res.data;
+  }
+  return Promise.reject(new Error(res.message));
 }
 
-
 //获取已办事项列表
 export async function getDoneTaskList(query) {
-	const res = await postJ(
-		Vue.prototype.apiUrl + `/bpm/task/done-page`, query, true
-	);
-	if (res.code == 0) {
-		return res.data;
-	}
-	return Promise.reject(new Error(res.message));
+  const res = await postJ(
+    Vue.prototype.apiUrl + `/bpm/task/done-page`,
+    query,
+    true,
+  );
+  if (res.code == 0) {
+    return res.data;
+  }
+  return Promise.reject(new Error(res.message));
 }
 //获取流程详情
 export async function getTaskListByProcessinstanceid(query) {
-	const res = await get(
-		Vue.prototype.apiUrl + `/bpm/task/list-by-process-instance-id`, query, true
-	);
+  const res = await get(
+    Vue.prototype.apiUrl + `/bpm/task/list-by-process-instance-id`,
+    query,
+    true,
+  );
 
-	if (res.code == 0) {
-		return res.data;
-	}
-	return Promise.reject(new Error(res.message));
+  if (res.code == 0) {
+    return res.data;
+  }
+  return Promise.reject(new Error(res.message));
 }
 //获取流程任务实例
 export async function getProcessInstance(id) {
+  const res = await get(
+    Vue.prototype.apiUrl + `/bpm/process-instance/get`,
+    id,
+    true,
+  );
 
-	const res = await get(Vue.prototype.apiUrl + `/bpm/process-instance/get`, id, true)
-
-	if (res.code == 0) {
-		return res.data;
-	}
-	return Promise.reject(new Error(res.message));
+  if (res.code == 0) {
+    return res.data;
+  }
+  return Promise.reject(new Error(res.message));
 }
 
-
 export async function getTaskListByProcessInstanceId(processInstanceId) {
-	const res = await get(Vue.prototype.apiUrl + `/bpm/task/list-by-process-instance-id`, processInstanceId, true)
-	if (res.code == 0) {
-		return res.data;
-	}
-	return Promise.reject(new Error(res.message));
+  const res = await get(
+    Vue.prototype.apiUrl + `/bpm/task/list-by-process-instance-id`,
+    processInstanceId,
+    true,
+  );
+  if (res.code == 0) {
+    return res.data;
+  }
+  return Promise.reject(new Error(res.message));
 }
 // 通用流程审核接口
 export async function approveTaskWithVariables(data) {
-	const res = await putJ(Vue.prototype.apiUrl + `/bpm/task/approveTaskWithVariables`, data, true)
-	if (res.code == 0) {
-		return res.data;
-	}
-	return Promise.reject(new Error(res.message));
+  const res = await putJ(
+    Vue.prototype.apiUrl + `/bpm/task/approveTaskWithVariables`,
+    data,
+    true,
+  );
+  if (res.code == 0) {
+    return res.data;
+  }
+  return Promise.reject(new Error(res.message));
 }
 
-
 /**
  *销售退货审批流程审核接口
  */
 export async function approveTaskSalesOrderReturn(params) {
-	const res = await postJ(Vue.prototype.apiUrl + `/bpm/salesOrderReturnApprove/approve`, params, true)
-	if (res.code == 0) {
-		return res;
-	}
-	return Promise.reject(new Error(res.message));
+  const res = await postJ(
+    Vue.prototype.apiUrl + `/bpm/salesOrderReturnApprove/approve`,
+    params,
+    true,
+  );
+  if (res.code == 0) {
+    return res;
+  }
+  return Promise.reject(new Error(res.message));
 }
 
-
-
 //费用申请
 // 编辑
 export async function feeApplyUpdateAPI(data) {
-	const res = await putJ(Vue.prototype.apiUrl + `/eom/finfeeapply/update`, data, true)
-	if (res.code == 0) {
-		return res.data;
-	}
-	return Promise.reject(new Error(res.message));
+  const res = await putJ(
+    Vue.prototype.apiUrl + `/eom/finfeeapply/update`,
+    data,
+    true,
+  );
+  if (res.code == 0) {
+    return res.data;
+  }
+  return Promise.reject(new Error(res.message));
 }
 
 // 信息
 export async function getFeeApplyInfoAPI(id) {
-	const res = await get(Vue.prototype.apiUrl + `/eom/finfeeapply/getById/${id}`, {}, true)
-	if (res.code == 0) {
-		return res.data;
-	}
-	return Promise.reject(new Error(res.message));
-}
-// 
-// 
-// 
+  const res = await get(
+    Vue.prototype.apiUrl + `/eom/finfeeapply/getById/${id}`,
+    {},
+    true,
+  );
+  if (res.code == 0) {
+    return res.data;
+  }
+  return Promise.reject(new Error(res.message));
+}
+//
+//
+//
 //销售合同
 /**
  * 获取信息详情
  */
 export async function getDetail(id) {
-	const res = await get(Vue.prototype.apiUrl + `/eom/contract/getById/${id}`, {}, true);
-	if (res.code == 0) {
-		return res.data;
-	}
-	return Promise.reject(new Error(res.message));
+  const res = await get(
+    Vue.prototype.apiUrl + `/eom/contract/getById/${id}`,
+    {},
+    true,
+  );
+  if (res.code == 0) {
+    return res.data;
+  }
+  return Promise.reject(new Error(res.message));
 }
 //
 //
 //
 //
 
-
 //客户申请
 /**
  * 客户申请列表
  */
 export async function contactApplyList(id) {
-	const res = await get(Vue.prototype.apiUrl + `/eom/contactlistapply/getById/${id}`, {}, true);
-	if (res.code == 0) {
-		return res.data;
-	}
-	return Promise.reject(new Error(res.message));
+  const res = await get(
+    Vue.prototype.apiUrl + `/eom/contactlistapply/getById/${id}`,
+    {},
+    true,
+  );
+  if (res.code == 0) {
+    return res.data;
+  }
+  return Promise.reject(new Error(res.message));
 }
 //
 //
@@ -214,39 +249,50 @@ export async function contactApplyList(id) {
  * /商机管理-获取信息详情
  */
 export async function getBusinessOpportunityDetailAPI(id) {
-	const res = await get(Vue.prototype.apiUrl + `/eom/businessopportunity/getById/${id}`, {}, true);
-	if (res.code == 0) {
-		return res.data;
-	}
-	return Promise.reject(new Error(res.message));
+  const res = await get(
+    Vue.prototype.apiUrl + `/eom/businessopportunity/getById/${id}`,
+    {},
+    true,
+  );
+  if (res.code == 0) {
+    return res.data;
+  }
+  return Promise.reject(new Error(res.message));
 }
 
 /**
  * 更新信息
  */
 export async function businessOpportunityUpdateAPI(data) {
-	const res = await postJ(Vue.prototype.apiUrl + `/eom/businessopportunity/updateProduct`, data, true);
-	if (res.code == 0) {
-		return res.data;
-	}
-	return Promise.reject(new Error(res.message));
+  const res = await postJ(
+    Vue.prototype.apiUrl + `/eom/businessopportunity/updateProduct`,
+    data,
+    true,
+  );
+  if (res.code == 0) {
+    return res.data;
+  }
+  return Promise.reject(new Error(res.message));
 }
 //
 //
 //
 //
 
-
 //销售订单
 /**
  * /销售订单-获取信息详情
  */
 export async function getSaleOrderDetailAPI(id) {
-	const res = await get(Vue.prototype.apiUrl + `/eom/saleorder/getById/${id}`, {}, true);
-	if (res.code == 0) {
-		return res.data;
-	}
-	return Promise.reject(new Error(res.message));
+  const res = await get(
+    Vue.prototype.apiUrl + `/eom/saleorder/getById/${id}`,
+    {},
+    true,
+  );
+  if (res.code == 0) {
+    return res.data;
+  }
+  return Promise.reject(new Error(res.message));
 }
 //
 //
@@ -257,28 +303,35 @@ export async function getSaleOrderDetailAPI(id) {
  * /销售退货单-获取信息详情
  */
 export async function getSaleOrderReturnGetByIdAPI(id) {
-	const res = await get(Vue.prototype.apiUrl + `/eom/saleorderreturnrecord/getById/${id}`, {}, true);
-	if (res.code == 0) {
-		return res.data;
-	}
-	return Promise.reject(new Error(res.message));
+  const res = await get(
+    Vue.prototype.apiUrl + `/eom/saleorderreturnrecord/getById/${id}`,
+    {},
+    true,
+  );
+  if (res.code == 0) {
+    return res.data;
+  }
+  return Promise.reject(new Error(res.message));
 }
 //
 //
 //
 //
 
-
 //获取发货单
 /**
  * /获取发货单信息详情-获取信息详情
  */
 export async function getSaleOrderSendRecordDetailAPI(id) {
-	const res = await get(Vue.prototype.apiUrl + `/eom/saleordersendrecord/getById/${id}`, {}, true);
-	if (res.code == 0) {
-		return res.data;
-	}
-	return Promise.reject(new Error(res.message));
+  const res = await get(
+    Vue.prototype.apiUrl + `/eom/saleordersendrecord/getById/${id}`,
+    {},
+    true,
+  );
+  if (res.code == 0) {
+    return res.data;
+  }
+  return Promise.reject(new Error(res.message));
 }
 //
 //
@@ -290,11 +343,15 @@ export async function getSaleOrderSendRecordDetailAPI(id) {
  * /获取仓库信息
  */
 export async function getWarehouseListByIdsAPI(data) {
-	const res = await postJ(Vue.prototype.apiUrl + `/wms/warehouse/getWarehouseListByIds`, data, true);
-	if (res.code == 0) {
-		return res.data;
-	}
-	return Promise.reject(new Error(res.message));
+  const res = await postJ(
+    Vue.prototype.apiUrl + `/wms/warehouse/getWarehouseListByIds`,
+    data,
+    true,
+  );
+  if (res.code == 0) {
+    return res.data;
+  }
+  return Promise.reject(new Error(res.message));
 }
 //
 //
@@ -307,32 +364,43 @@ export async function getWarehouseListByIdsAPI(data) {
  * /获取需求单信息
  */
 export async function getPurchaseRequirementByIdsAPI(id) {
-	const res = await get(Vue.prototype.apiUrl + `/eom/purchaserequirement/getById/${id}`, {}, true);
-	if (res.code == 0) {
-		return res.data;
-	}
-	return Promise.reject(new Error(res.message));
+  const res = await get(
+    Vue.prototype.apiUrl + `/eom/purchaserequirement/getById/${id}`,
+    {},
+    true,
+  );
+  if (res.code == 0) {
+    return res.data;
+  }
+  return Promise.reject(new Error(res.message));
 }
 
-
 //获取采购计划单信息
 export async function getPurchasePlanByIdsAPI(id) {
-	const res = await get(Vue.prototype.apiUrl + `/eom/purchaseplan/getById/${id}`, {}, true);
-	if (res.code == 0) {
-		return res.data;
-	}
-	return Promise.reject(new Error(res.message));
+  const res = await get(
+    Vue.prototype.apiUrl + `/eom/purchaseplan/getById/${id}`,
+    {},
+    true,
+  );
+  if (res.code == 0) {
+    return res.data;
+  }
+  return Promise.reject(new Error(res.message));
 }
 
 /**
  * /新增采购需求负责人
  */
 export async function AssignPurchasePlanUserAPI(data) {
-	const res = await postJ(Vue.prototype.apiUrl + `/bpm/purchasePlanApprove/assign`, data, true);
-	if (res.code == 0) {
-		return res.data;
-	}
-	return Promise.reject(new Error(res.message));
+  const res = await postJ(
+    Vue.prototype.apiUrl + `/bpm/purchasePlanApprove/assign`,
+    data,
+    true,
+  );
+  if (res.code == 0) {
+    return res.data;
+  }
+  return Promise.reject(new Error(res.message));
 }
 //
 //
@@ -344,11 +412,15 @@ export async function AssignPurchasePlanUserAPI(data) {
  */
 //获取采购订单信息
 export async function purchaseOrderGetByIdAPI(id) {
-	const res = await get(Vue.prototype.apiUrl + `/eom/purchaseorder/getById/${id}`, {}, true);
-	if (res.code == 0) {
-		return res.data;
-	}
-	return Promise.reject(new Error(res.message));
+  const res = await get(
+    Vue.prototype.apiUrl + `/eom/purchaseorder/getById/${id}`,
+    {},
+    true,
+  );
+  if (res.code == 0) {
+    return res.data;
+  }
+  return Promise.reject(new Error(res.message));
 }
 //
 //
@@ -360,110 +432,238 @@ export async function purchaseOrderGetByIdAPI(id) {
  */
 //获取采购收货单信息
 export async function purchaseOrderReceiveGetByIdAPI(id) {
-	const res = await get(Vue.prototype.apiUrl + `/eom/purchaseorderreceive/getById/${id}`, {}, true);
-	if (res.code == 0) {
-		return res.data;
-	}
-	return Promise.reject(new Error(res.message));
+  const res = await get(
+    Vue.prototype.apiUrl + `/eom/purchaseorderreceive/getById/${id}`,
+    {},
+    true,
+  );
+  if (res.code == 0) {
+    return res.data;
+  }
+  return Promise.reject(new Error(res.message));
 }
 //
 //
 //
 //
 
-
 /**
  * /采购退货
  */
 //获取采购退货单信息
 export async function purchaseOrderReturnGetByIdAPI(id) {
-	const res = await get(Vue.prototype.apiUrl + `/eom/purchaseorderreturn/getById/${id}`, {}, true);
-	if (res.code == 0) {
-		return res.data;
-	}
-	return Promise.reject(new Error(res.message));
+  const res = await get(
+    Vue.prototype.apiUrl + `/eom/purchaseorderreturn/getById/${id}`,
+    {},
+    true,
+  );
+  if (res.code == 0) {
+    return res.data;
+  }
+  return Promise.reject(new Error(res.message));
 }
 //
 //
 //
 //
 
-
 /**
  * /量具送检
  */
 //查询量具送检信息
 export async function processById(params) {
-	const res = await get(Vue.prototype.apiUrl + `/eam/planmaintenance/processById`, params);
-	if (res.code == 0) {
-		return res.data;
-	}
-	return Promise.reject(new Error(res.data.message));
+  const res = await get(
+    Vue.prototype.apiUrl + `/eam/planmaintenance/processById`,
+    params,
+  );
+  if (res.code == 0) {
+    return res.data;
+  }
+  return Promise.reject(new Error(res.data.message));
 }
 //
 // 个人日志列表
 export async function getList(params) {
-	const res = await get('/eom/planToolLog/list', params);
-	if (res.data.code == 0) {
-		return res.data;
-	}
-	return Promise.reject(new Error(res.data.message));
+  const res = await get("/eom/planToolLog/list", params);
+  if (res.data.code == 0) {
+    return res.data;
+  }
+  return Promise.reject(new Error(res.data.message));
 }
 //
 //
 //
 //动态表单 工作流自定义权限过滤表单集合
 export async function getBpmCustomFormList(params) {
-	const res = await get(Vue.prototype.apiUrl + '/flowable/bpmcustomform/list', params);
-	if (res.code == 0) {
-		return res.data;
-	}
-	return Promise.reject(new Error(res.data.message));
-};
+  const res = await get(
+    Vue.prototype.apiUrl + "/flowable/bpmcustomform/list",
+    params,
+  );
+  if (res.code == 0) {
+    return res.data;
+  }
+  return Promise.reject(new Error(res.data.message));
+}
 //动态表单 我发起的申请
 export async function getProcessInstancePage(params) {
-	const res = await postJ(Vue.prototype.apiUrl + '/bpm/process-instance/my-page', params);
-	if (res.code == 0) {
-		return res.data;
-	}
-	return Promise.reject(new Error(res.data.message));
-};
+  const res = await postJ(
+    Vue.prototype.apiUrl + "/bpm/process-instance/my-page",
+    params,
+  );
+  if (res.code == 0) {
+    return res.data;
+  }
+  return Promise.reject(new Error(res.data.message));
+}
 //动态表单 部门发起的申请
 export async function getProcessInstanceDeptPage(query) {
-
-	const res = await get(Vue.prototype.apiUrl + '/bpm/process-instance/my-dept-page', params);
-	if (res.code == 0) {
-		return res.data;
-	}
-	return Promise.reject(new Error(res.data.message));
-};
+  const res = await get(
+    Vue.prototype.apiUrl + "/bpm/process-instance/my-dept-page",
+    params,
+  );
+  if (res.code == 0) {
+    return res.data;
+  }
+  return Promise.reject(new Error(res.data.message));
+}
 //动态表单 通知我的申请
 export async function getProcessInstanceNoticePage(data) {
-
-	const res = await postJ(Vue.prototype.apiUrl + '/bpm/process-instance/my-notice-page', data);
-	if (res.code == 0) {
-		return res.data;
-	}
-	return Promise.reject(new Error(res.data.message));
-};
+  const res = await postJ(
+    Vue.prototype.apiUrl + "/bpm/process-instance/my-notice-page",
+    data,
+  );
+  if (res.code == 0) {
+    return res.data;
+  }
+  return Promise.reject(new Error(res.data.message));
+}
 
 //发起流程通用接口
 export async function processInstanceCreateAPI(params, loding = true) {
-	const res = await postJ(
-		Vue.prototype.apiUrl + `/bpm/process-instance/create`, params, loding
-	);
-	if (res.code == 0) {
-		return res.data;
-	}
-	return Promise.reject(new Error(res.message));
+  const res = await postJ(
+    Vue.prototype.apiUrl + `/bpm/process-instance/create`,
+    params,
+    loding,
+  );
+  if (res.code == 0) {
+    return res.data;
+  }
+  return Promise.reject(new Error(res.message));
 }
 //流程列表
 export async function processInstancePage(params, loding = false) {
-	const res = await get(
-		Vue.prototype.apiUrl + `/bpm/model/page`, params, loding
-	);
-	if (res.code == 0) {
-		return res.data;
-	}
-	return Promise.reject(new Error(res.message));
-}
+  const res = await get(
+    Vue.prototype.apiUrl + `/bpm/model/page`,
+    params,
+    loding,
+  );
+  if (res.code == 0) {
+    return res.data;
+  }
+  return Promise.reject(new Error(res.message));
+}
+
+/**
+ * /获取领料单信息
+ */
+export async function getPickOrderById(id) {
+  const res = await get(
+    Vue.prototype.apiUrl + `/pda/mes/pickorder/getPickOrderById/${id}`,
+    {},
+    true,
+  );
+  if (res.code == 0) {
+    return res.data;
+  }
+  return Promise.reject(new Error(res.message));
+}
+
+/**
+ * 根据来源单号查出库详情
+ */
+export async function getOutInBySourceBizNo(sourceBizNo) {
+  const res = await get(
+    Vue.prototype.apiUrl + `/wms/outintwo/getInfoBySourceBizNo/${sourceBizNo}`,
+    {},
+    true,
+  );
+  if (res.code == 0) {
+    return res.data;
+  }
+  return Promise.reject(new Error(res.message));
+}
+
+/**
+ * 查询所有物品分类
+ */
+export async function allCategoryLevel() {
+  const res = await get(
+    Vue.prototype.apiUrl + `/main/categoryLevel/allCategoryLevel`,
+    {},
+    false,
+  );
+  if (res.code == 0) {
+    return res.data;
+  }
+  return Promise.reject(new Error(res.message));
+}
+
+export async function getLoginUser(data) {
+  const res = await get(
+    Vue.prototype.apiUrl + "/system/account/getLoginUser",
+    data,
+    true,
+  );
+  if (res.code == 0) {
+    return res.data;
+  }
+  if (res.data && res.data.code == 0) {
+    return res.data.data;
+  }
+  return Promise.reject(new Error(res.message || res.data?.message || "获取登录用户数据失败"));
+}
+
+/**
+ * 获取部门列表(树)
+ */
+export async function getGroupList() {
+  const res = await get(
+    Vue.prototype.apiUrl + `/main/group/getGroupList`,
+    {},
+    false,
+  );
+  if (res.code == 0) {
+    return res.data;
+  }
+  return Promise.reject(new Error(res.message));
+}
+
+/**
+ * 根据部门获取员工列表
+ */
+export async function getUserPageByGroupId(params) {
+  const res = await get(
+    Vue.prototype.apiUrl + `/main/user/getUserPage`,
+    params,
+    true,
+  );
+  if (res.code == 0) {
+    return res.data;
+  }
+  return Promise.reject(new Error(res.message));
+}
+
+/**
+ * 根据人员id获取用户信息(含部门)
+ */
+export async function getUserById(id) {
+  const res = await get(
+    Vue.prototype.apiUrl + `/main/user/getById/${id}`,
+    {},
+    true,
+  );
+  if (res.code == 0) {
+    return res.data;
+  }
+  return Promise.reject(new Error(res.message));
+}

+ 51 - 0
enum/dict.js

@@ -179,3 +179,54 @@ export const quoteTypeOp = [
     label: "议价",
   },
 ];
+
+export const warehousingType = [
+  { code: 3, label: "物料", key: "WULIAO" },
+  { code: 4, label: "产品", key: "CHANPIN" },
+  {
+    code: 5,
+    label: "周转车",
+    key: "ZHOUZHUANCHE",
+  },
+  { code: 2, label: "舟皿", key: "ZHOUMIN" },
+  {
+    code: 1,
+    label: "设备",
+    key: "SHENGCHANSHEBEI",
+  },
+  { code: 6, label: "模具", key: "MOJU" },
+  {
+    code: 7,
+    label: "备品备件",
+    key: "BEIPINBEIJIAN",
+  },
+];
+
+export const outputSceneState = [
+  { code: 1, label: "退供出库" },
+  { code: 2, label: "调拨出库" },
+  { code: 3, label: "销售出库" },
+  { code: 4, label: "领用出库" },
+  { code: 5, label: "报废出库" },
+  { code: 6, label: "外协出库" },
+  { code: 7, label: "委外出库" },
+  { code: 8, label: "受托退货出库" },
+  { code: 9, label: "仓库委外出库" },
+  { code: 10, label: "采购退货出库" },
+  { code: 11, label: "自选领用出库" },
+  { code: 12, label: "配料出库" },
+  { code: 13, label: "质检出库" },
+  { code: 14, label: "物料需求清单出库" },
+  { code: 99, label: "其他出库" },
+];
+
+export const emergencyState = [
+  { code: 1, label: "普通", color: "red" },
+  { code: 2, label: "重要", color: "blue" },
+  { code: 3, label: "紧急", color: "red" },
+];
+
+export const materialType = [
+  { code: 1, label: "混炼料" },
+  { code: 2, label: "混合料" },
+];

+ 1 - 1
manifest.json

@@ -10,7 +10,7 @@
             "proxy" : {
                 "/api" : {
                     // "target" : "http://192.168.1.110:18086/",
-                    "target" : "http://192.168.1.251:18086/",
+                    "target" : "http://192.168.1.125:18086/",
                     // "target" : "http://192.168.1.251:18086/",
                     // "target" : "http://192.168.1.251:18086/",
                     // "target" : "http://110.41.182.105/api/",

+ 8 - 0
pages.json

@@ -134,6 +134,14 @@
 				"navigationBarTextStyle": "white"
 			}
 		},
+		{
+			"path": "pages/home/wt/components/materialRequisition/processTask",
+			"style": {
+				"navigationBarTitleText": "仓库自选领用出库审批",
+				"navigationStyle": "custom",
+				"navigationBarTextStyle": "white"
+			}
+		},
 		{
 			"path": "pages/home/wt/components/pricingManage/processTask",
 			"style": {

+ 189 - 0
pages/home/wt/components/materialRequisition/processTask.vue

@@ -0,0 +1,189 @@
+<template>
+  <view class="havedone-container">
+    <uni-nav-bar
+      fixed="true"
+      statusBar="true"
+      left-icon="back"
+      :title="uniNavBarTitle"
+      background-color="#157A2C"
+      color="#fff"
+      @clickLeft="back"
+    ></uni-nav-bar>
+    <!-- <iframe src="http://aiot.zoomwin.com.cn:51001/test/a.html" style="width: 200px;height: 600px" frameborder="0"></iframe> -->
+    <view v-if="processInstance.processDefinition">
+      <taskForm
+        id="async-biz-form-component"
+        :taskId="listData.taskId"
+        :businessId="listData.businessId"
+        :id="listData.id"
+        :taskDefinitionKey="listData.taskDefinitionKey"
+        ref="bziRef"
+      ></taskForm>
+    </view>
+    <view v-for="(item, index) in runningTasks" :key="index">
+      <div v-if="processInstance.processDefinition">
+        <taskSubmit
+          id="async-sub-form-component"
+          :taskId="listData.taskId"
+          :businessId="listData.businessId"
+          :id="listData.id"
+          :taskDefinitionKey="listData.taskDefinitionKey"
+          @handleAudit="handleAudit"
+          @getTableValue="getTableValue"
+          @handleUpdateAssignee="handleUpdateAssignee(item)"
+          @handleBackList="handleBackList(item)"
+          ref="subForm"
+        >
+        </taskSubmit>
+      </div>
+    </view>
+    <u-toast ref="uToast"></u-toast>
+  </view>
+</template>
+
+<script>
+import {
+  getProcessInstance,
+  getTaskListByProcessInstanceId,
+} from "@/api/wt/index.js";
+import Vue from "vue";
+import taskForm from "./taskForm.vue";
+import taskSubmit from "./taskSubmit.vue";
+
+export default {
+  name: "processTask",
+  components: { taskForm, taskSubmit },
+  data() {
+    return {
+      uniNavBarTitle: "",
+      processInstanceLoading: false,
+      listData: {},
+      processInstance: {},
+      runningTasks: [],
+      auditForms: [],
+      activeComp: null,
+    };
+  },
+
+  onLoad(option) {
+    this.listData = option;
+    this.getDetail();
+    this.activeComp = "tab1";
+  },
+  methods: {
+    /** 获得流程实例 */
+    async getDetail() {
+      // 获得流程实例相关
+      this.processInstanceLoading = true;
+      getProcessInstance({
+        id: this.listData.id,
+      }).then(async (response) => {
+        if (!response) {
+          this.$message.error("查询不到流程信息!");
+          return;
+        }
+        // 设置流程信息
+        this.processInstance = response;
+        this.uniNavBarTitle = `${response.name}`;
+
+        this.processInstanceLoading = false;
+      });
+
+      this.runningTasks = [];
+      this.auditForms = [];
+      getTaskListByProcessInstanceId({
+        processInstanceId: this.listData.id,
+      }).then((response) => {
+        console.log(response, "response");
+        // 审批记录
+        this.tasks = [];
+        // 移除已取消的审批
+        response.forEach((task) => {
+          if (task.result !== 4) {
+            this.tasks.push(task);
+          }
+        });
+        // 排序,将未完成的排在前面,已完成的排在后面;
+        this.tasks.sort((a, b) => {
+          // 有已完成的情况,按照完成时间倒序
+          if (a.endTime && b.endTime) {
+            return b.endTime - a.endTime;
+          } else if (a.endTime) {
+            return 1;
+          } else if (b.endTime) {
+            return -1;
+            // 都是未完成,按照创建时间倒序
+          } else {
+            return b.createTime - a.createTime;
+          }
+        });
+
+        // 需要审核的记录
+        let userInfo = wx.getStorageSync("userInfo");
+        this.tasks.forEach((task) => {
+          if (task.result !== 1 && task.result !== 6) {
+            // 只有待处理才需要
+            return;
+          }
+          if (!task.assigneeUser || task.assigneeUser.id !== userInfo.userId) {
+            // 自己不是处理人
+            return;
+          }
+          if (task.taskDefinitionKey !== this.listData.taskDefinitionKey) {
+            // 不是当前流程的
+            return;
+          }
+          this.runningTasks.push({
+            ...task,
+          });
+          console.log(this.runningTasks, " this.runningTasks");
+          this.auditForms.push({
+            reason: "",
+          });
+        });
+      });
+    },
+
+    /** 处理审批通过和不通过的操作 */
+    handleAudit(data) {
+      let text = data.status === 1 ? "通过" : "不通过";
+      this.$refs.uToast.show({
+        type: "success",
+        message: `审批${data.title || text}成功!`,
+        iconUrl: "https://cdn.uviewui.com/uview/demo/toast/success.png",
+      });
+      // 获得最新详情
+      setTimeout(() => {
+        uni.navigateBack();
+      }, 1000);
+
+      // const index = this.runningTasks.indexOf(task);
+      // this.$refs['form' + index][0].validate((valid) => {
+      //   if (!valid) {
+      //     return;
+      //   }
+      //   const data = {
+      //     id: task.id,
+      //     reason: this.auditForms[index].reason
+      //   };
+      //   if (pass) {
+      //     approveTask(data).then((response) => {
+      //       this.$message.success('审批通过成功!');
+      //       this.handleClose(); // 获得最新详情
+      //     });
+      //   } else {
+      //     rejectTask(data).then((response) => {
+      //       this.$message.success('审批不通过成功!');
+      //       this.handleClose(); // 获得最新详情
+      //     });
+      //   }
+      // });
+    },
+    getTableValue(fn) {
+      fn(this.$refs.bziRef.getTableValue());
+    },
+  },
+};
+</script>
+
+<style></style>

+ 1391 - 0
pages/home/wt/components/materialRequisition/taskForm.vue

@@ -0,0 +1,1391 @@
+<template>
+  <view class="">
+    <u-sticky offset-top="50">
+      <view class="subsection-wrap">
+        <u-subsection
+          fontSize="25"
+          mode="subsection"
+          :list="list"
+          :current="curNow"
+          @change="sectionChange"
+          activeColor="#157A2C"
+        ></u-subsection>
+      </view>
+    </u-sticky>
+
+    <view v-show="curNow === 0" class="out-info-wrap">
+      <view class="out-info-title">
+        <text class="out-info-title-bar"></text>
+        <text class="out-info-title-text">领料信息</text>
+      </view>
+      <view class="out-info-divider"></view>
+
+      <view class="out-info-card">
+        <view
+          v-for="(item, index) in pickInfoItems"
+          :key="index"
+          class="out-info-row"
+        >
+          <text class="out-info-label">{{ item.label }}</text>
+          <text class="out-info-value">{{ item.value || "—" }}</text>
+        </view>
+      </view>
+    </view>
+    <view v-show="curNow === 1" class="pick-list-wrap">
+      <view class="out-info-title">
+        <text class="out-info-title-bar"></text>
+        <text class="out-info-title-text">领料清单</text>
+      </view>
+      <view class="out-info-divider"></view>
+
+      <view
+        v-if="!form.detailList || !form.detailList.length"
+        class="pick-list-empty"
+      >
+        暂无领料明细
+      </view>
+
+      <view
+        v-for="(row, idx) in form.detailList"
+        :key="idx"
+        class="pick-list-card"
+      >
+        <view class="pick-list-card-head">
+          <text class="pick-list-index">序号 {{ idx + 1 }}</text>
+        </view>
+        <view class="pick-list-card-body">
+          <view
+            v-for="(field, fieldIdx) in pickListFieldItems"
+            :key="`${idx}-${fieldIdx}`"
+            class="pick-list-row"
+          >
+            <text class="out-info-label">{{ field.label }}</text>
+            <text class="out-info-value">{{
+              formatPickListField(row, field.key)
+            }}</text>
+          </view>
+        </view>
+      </view>
+    </view>
+    <view v-show="curNow === 2" class="out-info-wrap">
+      <view class="out-info-title">
+        <text class="out-info-title-bar"></text>
+        <text class="out-info-title-text">出库信息</text>
+      </view>
+      <view class="out-info-divider"></view>
+
+      <view class="out-info-card">
+        <view
+          v-for="(item, index) in outboundInfoItems"
+          :key="index"
+          class="out-info-row"
+        >
+          <text class="out-info-label">{{ item.label }}</text>
+          <text class="out-info-value">{{ item.value || "—" }}</text>
+        </view>
+      </view>
+    </view>
+    <view v-show="curNow === 3" class="outbound-wrap">
+      <view class="outbound-title">
+        <text class="outbound-title-bar"></text>
+        <text class="outbound-title-text">出库物品清单</text>
+      </view>
+
+      <view class="out-info-divider"></view>
+
+      <view v-if="!outboundItemRows.length" class="outbound-empty">
+        暂无出库物品明细
+      </view>
+
+      <view
+        v-for="(row, index) in outboundItemRows"
+        :key="index"
+        class="outbound-card"
+      >
+        <view class="outbound-card-head">
+          <text class="outbound-index">序号 {{ row.seq }}</text>
+        </view>
+
+        <view
+          v-for="(line, li) in outboundItemGrid"
+          :key="li"
+          class="outbound-grid"
+          :class="{
+            'outbound-grid-last': li === outboundItemGrid.length - 1,
+            'outbound-grid--full': !line.right,
+          }"
+        >
+          <block v-if="line.right">
+            <view class="outbound-col">
+              <text class="outbound-label">{{ line.left[0] }}</text>
+              <text class="outbound-value">{{ dash(row[line.left[1]]) }}</text>
+            </view>
+            <view class="outbound-col outbound-col-right">
+              <text class="outbound-label">{{ line.right[0] }}</text>
+              <text class="outbound-value">{{ dash(row[line.right[1]]) }}</text>
+            </view>
+          </block>
+        </view>
+      </view>
+    </view>
+
+    <view v-show="curNow === 4" class="outbound-wrap">
+      <view class="outbound-title">
+        <text class="outbound-title-bar"></text>
+        <text class="outbound-title-text">包装清单</text>
+      </view>
+
+      <view class="out-info-divider"></view>
+
+      <view v-if="!packingListRows.length" class="outbound-empty">
+        暂无包装明细
+      </view>
+
+      <view
+        v-for="(row, index) in packingListRows"
+        :key="index"
+        class="outbound-card"
+      >
+        <view class="outbound-card-head">
+          <text class="outbound-index">序号 {{ row.seq }}</text>
+        </view>
+
+        <view
+          v-for="(line, li) in packingItemGrid"
+          :key="li"
+          class="outbound-grid"
+          :class="{
+            'outbound-grid-last': li === packingItemGrid.length - 1,
+            'outbound-grid--full': !line.right,
+          }"
+        >
+          <block v-if="line.right">
+            <view class="outbound-col">
+              <text class="outbound-label">{{ line.left[0] }}</text>
+              <text class="outbound-value">{{ dash(row[line.left[1]]) }}</text>
+            </view>
+            <view class="outbound-col outbound-col-right">
+              <text class="outbound-label">{{ line.right[0] }}</text>
+              <text class="outbound-value">{{ dash(row[line.right[1]]) }}</text>
+            </view>
+          </block>
+          <!-- <block v-if="line.right">
+            <view class="outbound-col">
+              <text class="outbound-label">{{ line.left[0] }}</text>
+              <text
+                class="outbound-value"
+                :class="{ 'outbound-value--mono': line.mono }"
+                >{{ dash(row[line.left[1]]) }}</text
+              >
+            </view>
+            <view class="outbound-col outbound-col-right">
+              <text class="outbound-label">{{ line.right[0] }}</text>
+              <text
+                class="outbound-value"
+                :class="{ 'outbound-value--mono': line.mono }"
+                >{{ dash(row[line.right[1]]) }}</text
+              >
+            </view>
+          </block>
+          <view v-else class="outbound-col outbound-col--full">
+            <text class="outbound-label">{{ line.left[0] }}</text>
+            <text class="outbound-value outbound-highlight">{{
+              dash(row[line.left[1]])
+            }}</text>
+          </view> -->
+        </view>
+      </view>
+    </view>
+  </view>
+</template>
+
+<script>
+import {
+  getPickOrderById,
+  getOutInBySourceBizNo,
+  allCategoryLevel,
+  getLoginUser,
+  getGroupList,
+  getUserPageByGroupId,
+  getUserById,
+} from "@/api/wt/index.js";
+import { getHierarchyFifo } from "@/api/warehouseManagement/index.js";
+
+const OUTPUT_SCENE_STATE = [
+  { code: 1, label: "退供出库" },
+  { code: 2, label: "调拨出库" },
+  { code: 3, label: "销售出库" },
+  { code: 4, label: "领用出库" },
+  { code: 5, label: "报废出库" },
+  { code: 6, label: "外协出库" },
+  { code: 7, label: "委外出库" },
+  { code: 8, label: "受托退货出库" },
+  { code: 9, label: "仓库委外出库" },
+  { code: 10, label: "采购退货出库" },
+  { code: 11, label: "自选领用出库" },
+  { code: 12, label: "配料出库" },
+  { code: 13, label: "质检出库" },
+  { code: 14, label: "物料需求清单出库" },
+  { code: 99, label: "其他出库" },
+];
+
+const qualityResults = {
+  0: "无",
+  1: "合格",
+  2: "不合格",
+  3: "让步接收",
+};
+
+const qualityStatus = {
+  0: "未质检",
+  1: "待检",
+  2: "已质检",
+};
+
+/** 出库物品卡片:每行左右两列的字段 key(与 outboundItemRows 一致) */
+const OUTBOUND_ITEM_GRID = [
+  { left: ["名称", "name"], right: ["编码", "code"] },
+  { left: ["批次号", "batchNo"], right: ["型号", "categoryModel"] },
+  { left: ["规格", "specification"], right: ["包装数量", "packQtyDisplay"] },
+  { left: ["计量数量", "countDisplay"], right: ["重量", "weightDisplay"] },
+  { left: ["库存数量", "stockDisplay"], right: ["锁库数", "lockDisplay"] },
+  { left: ["仓库", "warehouse"], right: ["包装规格", "packingSpecification"] },
+  { left: ["供应商", "supplierName"], right: ["供应商编号", "supplierCode"] },
+];
+
+/** 包装清单卡片:字段 key 与 packingListRows 一致 */
+const PACKING_ITEM_GRID = [
+  { left: ["名称", "name"], right: ["编码", "code"] },
+  {
+    left: ["批次号", "batchNo"],
+    right: ["发货条码", "shipBarcode"],
+    mono: true,
+  },
+  {
+    left: ["包装编码", "packageCode"],
+    right: ["客户代号", "customerCode"],
+    mono: true,
+  },
+  {
+    left: ["包装数量", "packageQtyDisplay"],
+    right: ["计量数量", "measureQtyDisplay"],
+  },
+  { left: ["重量", "weightDisplay"], right: ["刻码", "engrave"] },
+  { left: ["质检结果", "resultLabel"], right: ["质检状态", "statusLabel"] },
+  { left: ["生产日期", "productionDate"], right: ["采购日期", "purchaseDate"] },
+  { left: ["供应商", "supplierName"], right: ["供应商代号", "supplierCode"] },
+  // { left: ["物料代号", "materialAlias"], right: ["客户代号", "customerCode"] },
+];
+
+export default {
+  props: {
+    businessId: {
+      default: "",
+    },
+    taskDefinitionKey: {
+      default: "",
+    },
+  },
+  data() {
+    return {
+      form: {},
+      list: ["领料信息", "领料清单", "出库信息", "出库物品", "包装清单"],
+      curNow: 0,
+      isStorage: false,
+      outFormData: {
+        bizType: "",
+        sourceBizNo: "",
+        fromId: "",
+        fromUser: "",
+        fromUserPhone: "",
+        storageTime: "",
+        type: 2,
+        createUserId: "",
+        remark: "",
+        clientName: "",
+        outInDetailList: [],
+        extInfo: {
+          assetType: [],
+          assetTypeName: "",
+          deptCode: "",
+          deptName: "",
+          verifyDeptCode: "",
+          verifyDeptName: "",
+          createUserName: "",
+          createUserId: "",
+          fromUserPhone: "",
+          sourceBizNo: "",
+        },
+      },
+      warehousingMaterialList: [],
+      batchDetailsVOList: [],
+      assetTypeMapping: {},
+      extractedList: [],
+      productList: [],
+      packingList: [],
+      wwType: null,
+      outboundItemGrid: OUTBOUND_ITEM_GRID,
+      packingItemGrid: PACKING_ITEM_GRID,
+    };
+  },
+  computed: {
+    typeOptions() {
+      return [
+        { label: "自建领料", value: 1 },
+        { label: "工单领料", value: 2 },
+        { label: "委外领料", value: 3 },
+      ];
+    },
+    typeLabel() {
+      const current = this.typeOptions.find(
+        (item) => item.value === Number(this.form.type),
+      );
+      return current ? current.label : "";
+    },
+    typeIndex() {
+      const index = this.typeOptions.findIndex(
+        (item) => item.value === Number(this.form.type),
+      );
+      return index > -1 ? index : 0;
+    },
+    pickInfoItems() {
+      return [
+        { label: "领料单名称", value: this.form.name || "" },
+        { label: "领料单号", value: this.form.code || "" },
+        { label: "物品编码", value: this.form.categoryCode || "" },
+        { label: "物品名称", value: this.form.categoryName || "" },
+        { label: "型号", value: this.form.modelType || "" },
+        { label: "规格", value: this.form.specification || "" },
+        { label: "数量", value: this.form.formingNum || "" },
+        { label: "计量单位", value: this.form.unit || "" },
+        { label: "机型", value: this.form.modelKey || "" },
+        { label: "颜色", value: this.form.colorKey || "" },
+        { label: "领料时间", value: this.form.createTime || "" },
+        { label: "领料部门", value: this.form.executorDeptName || "" },
+        { label: "领料人", value: this.form.executorName || "" },
+        { label: "类型", value: this.typeLabel || "" },
+      ];
+    },
+    pickListFieldItems() {
+      return [
+        { label: "工单编号", key: "workOrderCode" },
+        { label: "物品编码", key: "categoryCode" },
+        { label: "物品名称", key: "categoryName" },
+        { label: "数量", key: "demandQuantity" },
+        { label: "领料仓库", key: "warehouseName" },
+      ];
+    },
+    outboundSceneLabel() {
+      const code = Number(this.outFormData.bizType);
+      const item = OUTPUT_SCENE_STATE.find((s) => s.code === code);
+      return item ? item.label : "";
+    },
+    assetTypeLabel() {
+      const assetType = this.outFormData.extInfo.assetType;
+      if (Array.isArray(assetType)) {
+        return assetType
+          .map((id) => this.assetTypeMapping[id] || "")
+          .filter(Boolean)
+          .join("、");
+      }
+      if (typeof assetType === "string" && assetType.includes(",")) {
+        return assetType
+          .split(",")
+          .map((id) => this.assetTypeMapping[id.trim()] || "")
+          .filter(Boolean)
+          .join("、");
+      }
+      return this.assetTypeMapping[assetType] || "";
+    },
+    outboundInfoItems() {
+      const fd = this.outFormData;
+      const ext = fd.extInfo || {};
+      return [
+        { label: "出库场景", value: this.outboundSceneLabel },
+        { label: "领料单", value: fd.sourceBizNo || this.form.code || "" },
+        { label: "出库物品类型", value: this.assetTypeLabel },
+        { label: "出库时间", value: fd.storageTime || "" },
+        { label: "出库登记人", value: ext.createUserName || "" },
+        { label: "领料人部门", value: ext.verifyDeptName || "" },
+        { label: "领料人", value: fd.fromUser || "" },
+        { label: "客户名称", value: fd.clientName || "" },
+        { label: "备注", value: fd.remark || "" },
+      ];
+    },
+    outboundItemRows() {
+      return this.warehousingMaterialList.map((item, i) => {
+        const countUnit = item.measuringUnit || "";
+        const wu = item.weightUnit || "";
+        const packUnit = item.packingUnit || item.minUnit || "";
+        const pb = item.packingCountBase;
+        return {
+          seq: i + 1,
+          code: item.assetCode || item.categoryCode || item.code || "",
+          name: item.assetName || item.name || "",
+          manualBatchNo: item.manualBatchNo || "",
+          batchNo: item.batchNo || "",
+          minPacking:
+            item.minPackingCount != null
+              ? `${item.minPackingCount}${countUnit}/${item.minUnit || ""}`
+              : "",
+          packQtyDisplay: pb != null && pb !== "" ? `${pb}${packUnit}` : "",
+          countDisplay:
+            item.availableCountBase !== "" && item.availableCountBase != null
+              ? `${item.availableCountBase}${countUnit}`
+              : "",
+          weightDisplay:
+            item.weight !== "" && item.weight != null
+              ? `${item.weight}${wu}`
+              : "",
+          stockDisplay:
+            item.stockNum !== "" && item.stockNum != null
+              ? `${item.stockNum}${countUnit}`
+              : "",
+          lockDisplay:
+            item.lockQuantity !== "" && item.lockQuantity != null
+              ? `${item.lockQuantity}${countUnit}`
+              : "",
+          warehouse: item.warehouseName || item.position || "",
+          supplierName: item.supplierName || "",
+          supplierCode: item.supplierCode || "",
+          stockNum: item.stockNum ?? "",
+          categoryModel: item.categoryModel || "",
+          specification: item.specification || "",
+          brandNum: item.brandNum || "",
+          lockQuantity: item.lockQuantity ?? "",
+          packingSpecification: item.packingSpecification || "",
+        };
+      });
+    },
+    packingListRows() {
+      return this.batchDetailsVOList.map((item, i) => {
+        const packUnit = item.packingUnit || item.minUnit || "";
+        const measureUnit = item.measuringUnit || "";
+        const weightUnit = item.weightUnit || "";
+        return {
+          seq: i + 1,
+          code: item.categoryCode || item.onlyCode || "",
+          name: item.name || item.assetName || "",
+          manualBatchNo: item.manualBatchNo || "",
+          batchNo: item.batchNo || "",
+          shipBarcode: item.barcodes || "",
+          packageCode:
+            item.packageNo ||
+            item.code ||
+            item.onlyCode ||
+            item.packageCode ||
+            "",
+          packageQtyDisplay:
+            item.packingCountBase !== "" && item.packingCountBase != null
+              ? `${item.packingCountBase}${packUnit}`
+              : "",
+          measureQtyDisplay:
+            item.availableCountBase !== "" && item.availableCountBase != null
+              ? `${item.availableCountBase}${measureUnit}`
+              : "",
+          materialAlias: item.materielCode || "",
+          customerCode: item.clientCode || "",
+          weightDisplay:
+            item.weight !== "" && item.weight != null
+              ? `${item.weight}${weightUnit}`
+              : "",
+          engrave: item.engrave || "",
+          resultLabel: qualityResults[item.result] || "无",
+          statusLabel: qualityStatus[item.status] || "未质检",
+          productionDate: item.productionDate || "",
+          purchaseDate: item.purchaseDate || "",
+          supplierName: item.supplierName || "",
+          supplierCode: item.supplierCode || "",
+        };
+      });
+    },
+  },
+  async mounted() {
+    await this.loadAssetTypeMapping();
+    await this.getDetailData(this.businessId);
+    await this.getLoginUserData();
+  },
+  methods: {
+    dash(val) {
+      if (val === null || val === undefined) return "—";
+      if (typeof val === "string" && val.trim() === "") return "—";
+      return val;
+    },
+    formatPickListField(row, key) {
+      if (key === "demandQuantity") {
+        const qty = row?.demandQuantity ?? "";
+        const unit = row?.unit ?? "";
+        return qty !== "" || unit !== "" ? `${qty}${unit}` : "";
+      }
+      return row?.[key] ?? "";
+    },
+    async loadAssetTypeMapping() {
+      try {
+        const data = await allCategoryLevel();
+        const list = Array.isArray(data) ? data : data?.data || [];
+        const obj = {};
+        list.forEach((item) => {
+          obj[item.id] = item.name;
+        });
+        this.assetTypeMapping = obj;
+      } catch (e) {
+        console.warn("加载物品分类失败", e);
+      }
+    },
+    async getDetailData(id) {
+      const data = await getPickOrderById(id);
+      this.form = data;
+      this.extractedList = this.form.detailList.map((item) => {
+        return {
+          taskId: item.taskId,
+          workOrderId: item.workOrderId,
+        };
+      });
+      console.log(this.extractedList, "this.extractedList");
+      await this.loadOutboundData(data);
+    },
+    async loadOutboundData(pickData) {
+      const code = pickData.code;
+      if (!code) return;
+      const categoryLevelTopIds = (pickData.detailList || [])
+        .map((item) => item.rootCategoryLevelId)
+        .filter(Boolean);
+      const uniqueAssetTypes = [...new Set(categoryLevelTopIds)];
+      const rootCategoryLevelId =
+        Array.isArray(this.form.detailList) && this.form.detailList[0]
+          ? this.form.detailList[0].rootCategoryLevelId
+          : "";
+      try {
+        const outData = await getOutInBySourceBizNo(code);
+        if (!outData || !outData.id) {
+          throw new Error("No outbound data");
+        }
+        this.isStorage = true;
+        this.outFormData = {
+          bizType: outData.bizType || "11",
+          sourceBizNo:
+            outData.sourceBizNo || outData.extInfo?.sourceBizNo || code,
+          fromId: outData.fromId || "",
+          fromUser: outData.fromUser || "",
+          fromUserPhone: outData.fromUserPhone || "",
+          storageTime: outData.storageTime || "",
+          type: outData.type || 2,
+          createUserId: outData.createUserId || "",
+          clientName: outData.clientName || "",
+          remark: outData.remark || "",
+          outInDetailList: outData.outInDetailVOList || [],
+          extInfo: {
+            ...(outData.extInfo || {}),
+            createUserName:
+              outData.extInfo?.createUserName ||
+              this.outFormData.extInfo?.createUserName ||
+              "",
+            assetType:
+              uniqueAssetTypes.length > 0
+                ? uniqueAssetTypes
+                : rootCategoryLevelId || outData.extInfo?.assetType || "",
+          },
+        };
+        this.parseOutInDetailList(outData.outInDetailVOList || []);
+      } catch (e) {
+        this.isStorage = false;
+        const savedCreateUserName =
+          this.outFormData.extInfo?.createUserName || "";
+        this.outFormData = {
+          bizType: "11",
+          sourceBizNo: code,
+          fromId: "",
+          fromUser: "",
+          fromUserPhone: "",
+          storageTime: "",
+          type: 2,
+          createUserId: "",
+          clientName: "",
+          remark: "",
+          outInDetailList: [],
+          extInfo: {
+            assetType:
+              uniqueAssetTypes.length > 0
+                ? uniqueAssetTypes
+                : rootCategoryLevelId || "",
+            assetTypeName: "",
+            deptCode: "",
+            deptName: "",
+            verifyDeptCode: "",
+            verifyDeptName: "",
+            createUserName: savedCreateUserName,
+            createUserId: "",
+            fromUserPhone: "",
+            sourceBizNo: "",
+          },
+        };
+        this.warehousingMaterialList = [];
+        this.batchDetailsVOList = [];
+
+        if (
+          this.taskDefinitionKey === "storeman" ||
+          this.taskDefinitionKey === "storemanAudit"
+        ) {
+          await this.initOutboundFromHierarchy(pickData);
+        }
+      }
+    },
+    parseOutInDetailList(list) {
+      const materials = [];
+      const packages = [];
+      list.forEach((goodsItem) => {
+        materials.push({
+          ...goodsItem,
+          assetName: goodsItem.name || goodsItem.assetName,
+          assetCode: goodsItem.categoryCode || goodsItem.assetCode,
+          outInNum: goodsItem.packingCount,
+        });
+        const records = goodsItem.outInDetailRecordVOList || [];
+        records.forEach((wrapItem) => {
+          packages.push({
+            ...wrapItem,
+            assetName: goodsItem.name || goodsItem.assetName,
+            assetCode: goodsItem.categoryCode || goodsItem.assetCode,
+          });
+        });
+      });
+      this.warehousingMaterialList = materials;
+      this.batchDetailsVOList = packages;
+    },
+    onTypeChange(e) {
+      const index = e?.detail?.value;
+      const selected = this.typeOptions[index];
+      this.form.type = selected ? selected.value : this.form.type;
+    },
+
+    async getLoginUserData() {
+      try {
+        const data = await getLoginUser();
+        if (!this.outFormData.extInfo) {
+          this.$set(this.outFormData, "extInfo", {});
+        }
+        this.$set(this.outFormData.extInfo, "createUserName", data.name || "");
+      } catch (e) {
+        console.warn("获取登录用户数据失败", e);
+      }
+    },
+    getNowFormatDate() {
+      const now = new Date();
+      const pad = (n) => String(n).padStart(2, "0");
+      this.outFormData.storageTime = `${now.getFullYear()}-${pad(now.getMonth() + 1)}-${pad(now.getDate())} ${pad(now.getHours())}:${pad(now.getMinutes())}:${pad(now.getSeconds())}`;
+    },
+    async getStaffList(groupId) {
+      try {
+        const res = await getUserPageByGroupId({
+          groupId,
+          size: 9999,
+          page: 1,
+        });
+        return res.list || [];
+      } catch (e) {
+        console.warn("获取员工列表失败", e);
+        return [];
+      }
+    },
+    async initOutboundFromHierarchy(pickData) {
+      const code = pickData.code;
+      this.wwType = pickData.type;
+
+      const categoryLevelTopIds = (pickData.detailList || [])
+        .map((item) => item.rootCategoryLevelId)
+        .filter(Boolean);
+      const uniqueAssetTypes = [...new Set(categoryLevelTopIds)];
+
+      this.outFormData.bizType = 11;
+      this.outFormData.sourceBizNo = code;
+      this.outFormData.type = 2;
+      this.outFormData.extInfo.assetType = uniqueAssetTypes;
+      this.outFormData.extInfo.sourceBizNo = code;
+
+      this.getNowFormatDate();
+
+      try {
+        const userData = await getLoginUser();
+        this.outFormData.extInfo.createUserName = userData.name || "";
+        this.outFormData.extInfo.createUserId = userData.userId || "";
+        this.outFormData.createUserId = userData.userId || "";
+      } catch (e) {
+        console.warn("获取登录用户失败", e);
+      }
+
+      if (pickData.executorDeptId) {
+        try {
+          const staffList = await this.getStaffList(pickData.executorDeptId);
+          this.outFormData.fromId = pickData.executorId || "";
+          this.outFormData.fromUser = pickData.executorName || "";
+          this.outFormData.extInfo.verifyDeptCode =
+            pickData.executorDeptId || "";
+          this.outFormData.extInfo.verifyDeptName =
+            pickData.executorDeptName || "";
+        } catch (e) {
+          console.warn("设置领料人信息失败", e);
+        }
+      } else if (pickData.createUserId) {
+        this.outFormData.fromId = pickData.createUserId;
+        try {
+          const userInfo = await getUserById(pickData.createUserId);
+          this.outFormData.fromUser = userInfo.name || "";
+          this.outFormData.extInfo.verifyDeptCode = userInfo.groupId || "";
+          this.outFormData.extInfo.verifyDeptName = userInfo.groupName || "";
+        } catch (e) {
+          console.warn("获取领料人部门信息失败", e);
+        }
+      }
+
+      if (pickData.makerId) {
+        try {
+          const makerInfo = await getUserById(pickData.makerId);
+          this.outFormData.extInfo.verifyDeptCode =
+            this.outFormData.extInfo.verifyDeptCode || makerInfo.groupId || "";
+          this.outFormData.extInfo.verifyDeptName =
+            this.outFormData.extInfo.verifyDeptName ||
+            makerInfo.groupName ||
+            "";
+        } catch (e) {
+          console.warn("获取makerId部门失败", e);
+        }
+      }
+
+      const detailList = pickData.detailList || [];
+      if (!detailList.length) return;
+
+      let requestData;
+      if (Number(this.wwType) === 3) {
+        requestData = {
+          type: this.wwType,
+          deliveryNo: code,
+          taskIds: this.extractedList.map((item) => item.taskId),
+          workOrderIds: this.extractedList.map((item) => item.workOrderId),
+        };
+      } else {
+        requestData = {
+          type: "1",
+          deliveryNo: code,
+          builders: detailList.map((item) => ({
+            categoryId:
+              item.categoryId || item.instanceId || item.productId || "",
+            num: item.demandQuantity || item.measurementCount || 0,
+            warehouseId: item.warehouseId || "",
+            batchNo: item.batchNo || "",
+          })),
+        };
+      }
+
+      try {
+        const data = await getHierarchyFifo(requestData);
+        this.processHierarchyData(data, pickData);
+      } catch (err) {
+        console.warn("获取出库物品数据失败", err);
+      }
+    },
+    processHierarchyData(data, pickData) {
+      if (!Array.isArray(data) || !data.length) return;
+
+      const firstDetail =
+        Array.isArray(pickData?.detailList) && pickData.detailList[0]
+          ? pickData.detailList[0]
+          : {};
+
+      this.productList = data.map((productItem) => ({
+        ...productItem,
+        suspendBatchNo: productItem.batchNo || "",
+        outInDetailRecordRequestList: (
+          productItem.outInDetailRecordRequestList || []
+        ).map((packingItem) => ({
+          ...packingItem,
+          workOrderId: firstDetail.workOrderId || "",
+          pickOrderId: firstDetail.pickOrderId || "",
+          taskId: firstDetail.taskId || "",
+          categoryName: productItem.categoryName || packingItem.categoryName,
+          categoryCode: productItem.categoryCode || packingItem.categoryCode,
+          supplierCode:
+            productItem.supplierCode || packingItem.supplierCode || "",
+          supplierName:
+            productItem.supplierName || packingItem.supplierName || "",
+          materialDetailList: (packingItem.materialDetailList || []).map(
+            (materialItem) => ({
+              ...materialItem,
+              categoryName:
+                productItem.categoryName || materialItem.categoryName,
+              categoryCode:
+                productItem.categoryCode || materialItem.categoryCode,
+              supplierCode:
+                productItem.supplierCode ||
+                packingItem.supplierCode ||
+                materialItem.supplierCode ||
+                "",
+              supplierName:
+                productItem.supplierName ||
+                packingItem.supplierName ||
+                materialItem.supplierName ||
+                "",
+            }),
+          ),
+        })),
+      }));
+
+      console.log(this.productList, "productList");
+      this.productList.sort((a, b) =>
+        (a.categoryCode || "").localeCompare(b.categoryCode || ""),
+      );
+
+      const materials = [];
+      const packages = [];
+
+      console.log(this.productList, "productList1111");
+
+      this.productList.forEach((item) => {
+        materials.push({
+          assetCode: item.categoryCode,
+          assetName: item.categoryName,
+          categoryCode: item.categoryCode,
+          categoryName: item.categoryName,
+          name: item.categoryName,
+          manualBatchNo: item.manualBatchNo || "",
+          batchNo: item.batchNo || "",
+          packingCountBase: item.packingQuantity,
+          minPackingCount: item.minPackingCount,
+          minUnit: item.packingUnit,
+          availableCountBase: item.measureQuantity,
+          measuringUnit: item.measureUnit,
+          weight: item.weight,
+          weightUnit: item.weightUnit,
+          warehouseName: item.warehouseName,
+          warehouseId: item.warehouseId,
+          outInNum: item.packingQuantity,
+          stockNum: item.stockNum,
+          categoryModel: item.categoryModel,
+          specification: item.specification,
+          brandNum: item.brandNum,
+          lockQuantity: item.lockQuantity,
+          packingSpecification: item.extField?.packingSpecification || "",
+          supplierName:
+            item.supplierName ||
+            (item.outInDetailRecordRequestList &&
+              item.outInDetailRecordRequestList[0] &&
+              item.outInDetailRecordRequestList[0].supplierName) ||
+            "",
+          supplierCode:
+            item.supplierCode ||
+            (item.outInDetailRecordRequestList &&
+              item.outInDetailRecordRequestList[0] &&
+              item.outInDetailRecordRequestList[0].supplierCode) ||
+            "",
+        });
+
+        console.log(materials, "materialsmaterialsmaterials");
+
+        const records = item.outInDetailRecordRequestList || [];
+        records.forEach((record) => {
+          packages.push({
+            code: record.packageNo,
+            onlyCode: record.packageNo,
+            assetName: item.categoryName,
+            name: item.categoryName,
+            categoryCode: item.categoryCode,
+            categoryName: item.categoryName,
+            manualBatchNo: record.manualBatchNo || "",
+            batchNo: record.batchNo || "",
+            barcodes: record.barcodes || "",
+            packingCountBase: record.packingQuantity,
+            packingUnit: record.packingUnit,
+            minUnit: record.packingUnit,
+            availableCountBase: record.measureQuantity,
+            measuringUnit: record.measureUnit,
+            materielCode: record.materielDesignation || "",
+            clientCode: record.clientCode || "",
+            weight: record.weight,
+            weightUnit: record.weightUnit,
+            supplierCode: item.supplierCode || record.supplierCode || "",
+            supplierName: item.supplierName || record.supplierName || "",
+            modelKey: record.modelKey || "",
+            colorKey: record.colorKey || "",
+            result: record.result,
+            status: record.status,
+            productionDate: record.productionDate || "",
+            purchaseDate: record.purchaseDate || "",
+            engrave: record.engrave || "",
+          });
+        });
+      });
+
+      this.warehousingMaterialList = materials;
+      this.batchDetailsVOList = packages;
+      this.packingList = packages;
+
+      this.outFormData.outInDetailList = this.productList;
+    },
+    async getReturnStorage() {
+      if (!this.productList || !this.productList.length) {
+        uni.showToast({ title: "请添加出库明细!", icon: "none" });
+        return null;
+      }
+
+      const obj = JSON.parse(JSON.stringify({ ...this.outFormData, type: 2 }));
+      obj.extInfo.sourceBizNo = obj.sourceBizNo;
+      obj.fromType = obj.type;
+
+      if (Array.isArray(obj.extInfo.assetType)) {
+        obj.extInfo.assetType = obj.extInfo.assetType.join(",");
+      }
+
+      const warehouseId = [];
+      const warehouseName = [];
+      this.productList.forEach((item) => {
+        if (item.warehouseId && !warehouseId.includes(item.warehouseId)) {
+          warehouseId.push(item.warehouseId);
+          warehouseName.push(item.warehouseName || "");
+        }
+      });
+      obj.warehouseIds = warehouseId;
+      obj.warehouseNames = warehouseName;
+      obj.outInDetailList = this.productList;
+
+      return obj;
+    },
+    async getTableValue() {
+      const outboundData = {
+        // 原始数据(接口/提交更稳定)
+        warehousingMaterialList: this.warehousingMaterialList || [],
+        batchDetailsVOList: this.batchDetailsVOList || [],
+        // 展示映射数据(便于前端直接渲染)
+        outboundItemRows: this.outboundItemRows || [],
+        packingListRows: this.packingListRows || [],
+      };
+      if (!this.isStorage && this.productList.length > 0) {
+        const returnStorageData = await this.getReturnStorage();
+        return {
+          form: this.form,
+          returnStorageData: returnStorageData || {},
+          ...outboundData,
+        };
+      }
+      return {
+        form: this.form,
+        returnStorageData: {},
+        ...outboundData,
+      };
+    },
+    sectionChange(index) {
+      this.curNow = index;
+    },
+  },
+};
+</script>
+
+<style scoped>
+.btnConcel {
+  margin-top: 20rpx;
+}
+
+.subsection-wrap {
+  background: #f5f7fa;
+  padding: 12rpx 16rpx;
+}
+
+.pick-info-wrap {
+  padding: 0 0 24rpx;
+}
+
+.pick-info-title {
+  display: flex;
+  align-items: center;
+  margin: 20rpx 24rpx 12rpx;
+}
+
+.pick-info-title-bar {
+  width: 8rpx;
+  height: 30rpx;
+  background: #157a2c;
+  border-radius: 4rpx;
+  margin-right: 14rpx;
+  flex-shrink: 0;
+}
+
+.pick-info-title-text {
+  font-size: 30rpx;
+  font-weight: 600;
+  color: #303133;
+}
+
+.pick-info-form {
+  background: #ffffff;
+  border-radius: 16rpx;
+  padding: 6rpx 20rpx;
+  box-sizing: border-box;
+  box-shadow: 0 6rpx 18rpx rgba(0, 0, 0, 0.04);
+}
+
+.pick-info-form :deep(.u-form-item) {
+  padding: 8rpx 0;
+}
+
+.pick-info-form :deep(.u-form-item__body) {
+  min-height: 88rpx;
+}
+
+.pick-info-form :deep(.u-form-item__body__left__content__label) {
+  font-size: 28rpx;
+  color: #303133;
+}
+
+.pick-info-form :deep(.u-border-bottom::after) {
+  border-color: #ebeef5 !important;
+}
+
+.pick-info-form :deep(.u-input) {
+  background: #f6f8fc !important;
+  border: 1rpx solid #e7ebf1 !important;
+  border-radius: 12rpx !important;
+  padding: 12rpx 16rpx !important;
+}
+
+.pick-info-form :deep(.u-input__content__field-wrapper__field) {
+  font-size: 28rpx !important;
+  color: #4a4f57 !important;
+}
+
+.pick-list-wrap {
+  padding: 0 24rpx 32rpx;
+  box-sizing: border-box;
+}
+
+.pick-list-section-title {
+  display: flex;
+  align-items: center;
+  padding: 24rpx 0 16rpx;
+}
+
+.pick-list-section-bar {
+  width: 8rpx;
+  height: 32rpx;
+  background: #1890ff;
+  border-radius: 4rpx;
+  margin-right: 16rpx;
+  flex-shrink: 0;
+}
+
+.pick-list-section-text {
+  font-size: 32rpx;
+  font-weight: 600;
+  color: #303133;
+}
+
+.pick-list-divider {
+  height: 2rpx;
+  background: linear-gradient(
+    90deg,
+    rgba(24, 144, 255, 0.35) 0%,
+    rgba(24, 144, 255, 0.08) 100%
+  );
+  margin-bottom: 8rpx;
+}
+
+.pick-list-empty {
+  text-align: center;
+  color: #909399;
+  font-size: 28rpx;
+  padding: 80rpx 0;
+}
+
+.pick-list-card {
+  background: #fff;
+  border-radius: 16rpx;
+  margin-top: 24rpx;
+  box-shadow: 0 4rpx 24rpx rgba(0, 0, 0, 0.06);
+  border: 1rpx solid #eef0f4;
+  overflow: hidden;
+}
+
+.pick-list-card-head {
+  background: #f5f7fa;
+  padding: 20rpx 24rpx;
+  border-bottom: 1rpx solid #eef0f4;
+}
+
+.pick-list-index {
+  font-size: 26rpx;
+  font-weight: 600;
+  color: #606266;
+}
+
+.pick-list-card-body {
+  padding: 8rpx 24rpx 20rpx;
+}
+
+.pick-list-row {
+  display: flex;
+  align-items: flex-start;
+  justify-content: space-between;
+  padding: 18rpx 0;
+  border-bottom: 1rpx solid #f0f2f5;
+}
+
+.pick-list-row:last-child {
+  border-bottom: none;
+}
+
+.pick-list-row--highlight .pick-list-value {
+  color: #157a2c;
+  font-weight: 600;
+}
+
+.pick-list-row--two {
+  display: flex;
+  gap: 24rpx;
+  align-items: flex-start;
+}
+
+.pick-list-cell {
+  flex: 1;
+  min-width: 0;
+  display: flex;
+  flex-direction: column;
+  gap: 8rpx;
+}
+
+.pick-list-cell--right {
+  align-items: flex-end;
+  text-align: right;
+}
+
+.pick-list-cell--right .pick-list-label,
+.pick-list-cell--right .pick-list-value {
+  text-align: right;
+}
+
+.pick-list-label {
+  font-size: 24rpx;
+  color: #909399;
+  flex-shrink: 0;
+  margin-right: 16rpx;
+  min-width: 140rpx;
+}
+
+.pick-list-row--two .pick-list-label {
+  margin-right: 0;
+  min-width: 0;
+}
+
+.pick-list-value {
+  font-size: 28rpx;
+  color: #303133;
+  word-break: break-all;
+  flex: 1;
+  text-align: right;
+}
+
+.pick-list-row--two .pick-list-value {
+  text-align: left;
+}
+
+.pick-list-cell--right .pick-list-value {
+  text-align: right;
+}
+
+.pick-list-value--mono {
+  font-family: ui-monospace, monospace;
+  font-size: 26rpx;
+}
+
+.out-info-wrap {
+  padding: 0 24rpx 32rpx;
+  box-sizing: border-box;
+}
+
+.out-info-title {
+  display: flex;
+  align-items: center;
+  padding: 24rpx 0 12rpx;
+}
+
+.out-info-title-bar {
+  width: 8rpx;
+  height: 32rpx;
+  background: #1890ff;
+  border-radius: 4rpx;
+  margin-right: 16rpx;
+  flex-shrink: 0;
+}
+
+.out-info-title-text {
+  font-size: 32rpx;
+  font-weight: 600;
+  color: #303133;
+}
+
+.out-info-divider {
+  height: 2rpx;
+  background: linear-gradient(
+    90deg,
+    rgba(24, 144, 255, 0.35) 0%,
+    rgba(24, 144, 255, 0.08) 100%
+  );
+  margin-bottom: 8rpx;
+}
+
+.out-info-card {
+  margin-top: 20rpx;
+  background: #fff;
+  border: 1rpx solid #eef0f4;
+  border-radius: 16rpx;
+  box-shadow: 0 4rpx 20rpx rgba(0, 0, 0, 0.05);
+  overflow: hidden;
+}
+
+.out-info-row {
+  display: flex;
+  align-items: flex-start;
+  justify-content: space-between;
+  padding: 22rpx;
+  border-bottom: 1rpx solid #f0f2f5;
+  gap: 16rpx;
+}
+
+.out-info-row:last-child {
+  border-bottom: none;
+}
+
+.out-info-label {
+  font-size: 28rpx;
+  color: #303133;
+  min-width: 160rpx;
+  word-break: break-all;
+}
+
+.out-info-value {
+  flex: 1;
+  text-align: right;
+  color: #303133;
+  font-size: 28rpx;
+  word-break: break-all;
+}
+
+.outbound-wrap {
+  padding: 0 24rpx 32rpx;
+}
+
+.outbound-title {
+  display: flex;
+  align-items: center;
+  padding: 24rpx 0 14rpx;
+}
+
+.outbound-title-bar {
+  width: 8rpx;
+  height: 32rpx;
+  background: #1890ff;
+  border-radius: 4rpx;
+  margin-right: 14rpx;
+}
+
+.outbound-title-text {
+  font-size: 32rpx;
+  font-weight: 600;
+  color: #303133;
+}
+
+.outbound-empty {
+  text-align: center;
+  color: #909399;
+  font-size: 28rpx;
+  padding: 80rpx 0;
+}
+
+.outbound-card {
+  margin-top: 20rpx;
+  background: #fff;
+  border: 1rpx solid #eef0f4;
+  border-radius: 16rpx;
+  box-shadow: 0 4rpx 20rpx rgba(0, 0, 0, 0.05);
+  overflow: hidden;
+}
+
+.outbound-card-head {
+  background: #f7f9fc;
+  border-bottom: 1rpx solid #eef0f4;
+  padding: 18rpx 22rpx;
+  display: flex;
+  align-items: center;
+  justify-content: space-between;
+}
+
+.outbound-index {
+  font-size: 25rpx;
+  color: #606266;
+  font-weight: 600;
+}
+
+.outbound-code {
+  font-size: 25rpx;
+  color: #303133;
+  font-family: ui-monospace, monospace;
+}
+
+.outbound-grid {
+  padding: 18rpx 22rpx;
+  border-bottom: 1rpx solid #f0f2f5;
+  display: flex;
+  gap: 20rpx;
+}
+
+.outbound-grid-last {
+  border-bottom: none;
+}
+
+.outbound-grid--full {
+  flex-wrap: wrap;
+}
+
+.outbound-col--full {
+  flex: 1;
+  min-width: 0;
+  width: 100%;
+  display: flex;
+  flex-direction: column;
+  gap: 10rpx;
+}
+
+.outbound-col {
+  flex: 1;
+  min-width: 0;
+  display: flex;
+  flex-direction: column;
+  gap: 10rpx;
+}
+
+.outbound-col-right {
+  align-items: flex-end;
+  text-align: right;
+}
+
+.outbound-label {
+  font-size: 24rpx;
+  color: #303133;
+}
+
+.outbound-value {
+  font-size: 28rpx;
+  color: #205dd9;
+  word-break: break-all;
+}
+
+.outbound-col-right .outbound-value {
+  text-align: right;
+}
+
+.outbound-value--mono {
+  font-family: ui-monospace, monospace;
+  font-size: 26rpx;
+}
+
+.outbound-highlight {
+  color: #157a2c;
+  font-weight: 600;
+}
+</style>

+ 269 - 0
pages/home/wt/components/materialRequisition/taskSubmit.vue

@@ -0,0 +1,269 @@
+<template>
+  <view class="">
+    <u--form
+      style="margin: 0 20px"
+      labelPosition="left"
+      :model="form"
+      :rules="rules"
+      ref="uForm"
+      labelWidth="140rpx"
+    >
+      <u-form-item label="审批建议" prop="reason" required>
+        <u--textarea
+          style="width: 100%"
+          height="120"
+          border="surround"
+          placeholder="请输入审批建议"
+          v-model="form.reason"
+        ></u--textarea>
+      </u-form-item>
+    </u--form>
+    <view class="btnList">
+      <u-button
+        style="width: 45%; margin-bottom: 10rpx"
+        :loading="loading"
+        type="success"
+        :text="taskDefinitionKey === 'storeman' ? '申请出库' : '通过'"
+        @click="handleAudit(1)"
+      >
+      </u-button>
+      <u-button
+        style="width: 45%"
+        :loading="loading"
+        type="error"
+        text="驳回"
+        @click="rejectTask(0)"
+      ></u-button>
+    </view>
+    <view class="btnConcel" v-if="taskDefinitionKey !== 'deptLeaderApprove'">
+      <u-button @click="showAction = true">更多</u-button>
+    </view>
+    <u-action-sheet
+      :actions="actionList"
+      :closeOnClickOverlay="true"
+      :closeOnClickAction="true"
+      title="更多操作"
+      :show="showAction"
+      @close="showAction = false"
+      @select="selectActionClick"
+    ></u-action-sheet>
+  </view>
+</template>
+
+<script>
+import {
+  approveTaskWithVariables,
+  rejectTask,
+  cancelTask,
+} from "@/api/wt/index.js";
+import { outStorage } from "@/api/warehouseManagement/index.js";
+
+export default {
+  name: "taskSubmit",
+  props: {
+    businessId: {
+      default: "",
+    },
+    taskId: {
+      default: "",
+    },
+    id: {
+      default: "",
+    },
+    taskDefinitionKey: {
+      default: "",
+    },
+  },
+
+  data() {
+    return {
+      showAction: false,
+      loading: false,
+      taskFormData: {},
+      actionList: [
+        {
+          name: "作废",
+          fontSize: "28",
+          color: "#ffaa7f",
+        },
+      ],
+      form: {
+        technicianId: "",
+        reason: "",
+      },
+      rules: {
+        reason: {
+          type: "string",
+          required: true,
+          message: "请输入审批建议",
+          trigger: "blur",
+        },
+      },
+    };
+  },
+  mounted() {
+    this.$refs.uForm.setRules(this.rules);
+  },
+  methods: {
+    async syncTaskFormData() {
+      try {
+        const data = await this.getTableValue();
+        this.taskFormData = data || {};
+      } catch (e) {
+        console.warn("获取 taskForm 数据失败", e);
+        this.taskFormData = {};
+      }
+      return this.taskFormData;
+    },
+    selectActionClick(item) {
+      if (item.name == "作废") {
+        uni.showModal({
+          title: "提示",
+          content: "是否确认作废?",
+          success: async (modalRes) => {
+            if (modalRes.confirm) {
+              if (!this.form.reason) {
+                return uni.showToast({
+                  title: "审批建议不能为空",
+                  icon: "none",
+                });
+              }
+              this.loading = true;
+              await this.syncTaskFormData();
+              cancelTask({
+                taskId: this.taskId,
+                id: this.id,
+                reason: this.form.reason,
+                businessId: this.businessId,
+                variables: {
+                  taskFormData: this.taskFormData,
+                },
+              })
+                .then(() => {
+                  this.loading = false;
+                  this.$emit("handleAudit", {
+                    title: "作废",
+                  });
+                })
+                .catch(() => {
+                  this.loading = false;
+                  uni.showToast({ title: "流程作废失败", icon: "none" });
+                });
+            }
+          },
+        });
+      }
+    },
+    async handleAudit(status) {
+      if (!!status) {
+        try {
+          await this.$refs.uForm.validate();
+        } catch (e) {
+          return;
+        }
+      }
+      await this.syncTaskFormData();
+
+      let storageData = this.taskFormData.returnStorageData;
+
+      if (!!status) {
+        if (!storageData?.extInfo?.verifyDeptCode) {
+          return uni.showToast({ title: "请选择部门", icon: "none" });
+        }
+        if (!storageData?.fromUser) {
+          return uni.showToast({ title: "请选择领料人", icon: "none" });
+        }
+      }
+      if (!this.form.reason && !!status) {
+        return uni.showToast({ title: "请输入审批意见", icon: "none" });
+      }
+
+      if (this.taskDefinitionKey === "storeman" && !!status) {
+        storageData.isSkip = 1;
+        try {
+          this.loading = true;
+          const res = await outStorage(storageData);
+          if (res.code == 0) {
+            await this._approveTaskWithVariables(status);
+          }
+        } catch (error) {
+          this.loading = false;
+          uni.showToast({ title: "出库失败", icon: "none" });
+        }
+      } else {
+        this.loading = true;
+        await this._approveTaskWithVariables(status);
+      }
+    },
+    async _approveTaskWithVariables(status) {
+      try {
+        let variables = {
+          pass: !!status,
+          taskFormData: this.taskFormData,
+        };
+        let API = !!status ? approveTaskWithVariables : rejectTask;
+        let res = await API({
+          id: this.taskId,
+          reason: this.form.reason,
+          variables,
+        });
+
+        if (res.code != "-1") {
+          this.$emit("handleAudit", {
+            status,
+            title: status === 0 ? "驳回" : "",
+          });
+        }
+      } catch (e) {
+        console.error("审批操作失败", e);
+        uni.showToast({ title: "操作失败", icon: "none" });
+      } finally {
+        this.loading = false;
+      }
+    },
+    async rejectTask(status) {
+      await this.syncTaskFormData();
+      try {
+        this.loading = true;
+        let variables = {
+          pass: !!status,
+          taskFormData: this.taskFormData,
+        };
+        let res = await rejectTask({
+          id: this.taskId,
+          reason: this.form.reason,
+          variables,
+        });
+
+        if (res.code != "-1") {
+          this.$emit("handleAudit", {
+            status,
+            title: status === 0 ? "驳回" : "",
+          });
+        }
+      } catch (e) {
+        console.error("驳回操作失败", e);
+        uni.showToast({ title: "驳回失败", icon: "none" });
+      } finally {
+        this.loading = false;
+      }
+    },
+    getTableValue() {
+      return new Promise((resolve, reject) => {
+        this.$emit("getTableValue", async (data) => {
+          resolve(await data);
+        });
+      });
+    },
+  },
+};
+</script>
+
+<style scoped>
+.btnList {
+  display: flex;
+}
+.btnConcel {
+  margin-top: 20rpx;
+}
+</style>

+ 254 - 237
pages/home/wt/todo/todo.vue

@@ -1,245 +1,262 @@
 <template>
-	<view class="blacklog-container">
-		<uni-nav-bar fixed="true" statusBar="true" left-icon="back" title="我的待办" @clickLeft="back"
-			background-color="#157A2C" color="#fff"></uni-nav-bar>
-
-		<view class="list-container">
-			<u-list @scrolltolower="scrolltolower">
-				<u-list-item v-for="(item, index) in list" :key="index">
-					<view class="kd-card">
-						<view class="card-title">
-							<text>{{ item.processInstance.name }}</text>
-							<text class="card-time">{{ item.createTime }}</text>
-						</view>
-						<view>
-							<view class="card-body">
-								<view class="card-col" v-for="itm in colOptions">
-									<text class="label">{{ itm.label }}</text>
-									<text class="content">{{ item[itm.key] }}</text>
-								</view>
-							</view>
-							<view class="card-footer">
-								<u-button v-if="['0', '2'].includes(item.extensionProperty.taskHandlePlatform)"
-									type="success" @click="handleDetail(item, 'handle')">处理</u-button>
-								<u-button v-else type="error">请在PC端处理</u-button>
-								<u-button type="info" @click="handleDetail(item, 'detail')">流程详情</u-button>
-							</view>
-						</view>
-					</view>
-				</u-list-item>
-			</u-list>
-		</view>
-		<view v-show="list.length === 0" class="no_data">
-			<u-empty mode="data" textSize="30"></u-empty>
-		</view>
-	</view>
+  <view class="blacklog-container">
+    <uni-nav-bar
+      fixed="true"
+      statusBar="true"
+      left-icon="back"
+      title="我的待办"
+      @clickLeft="back"
+      background-color="#157A2C"
+      color="#fff"
+    ></uni-nav-bar>
+
+    <view class="list-container">
+      <u-list @scrolltolower="scrolltolower">
+        <u-list-item v-for="(item, index) in list" :key="index">
+          <view class="kd-card">
+            <view class="card-title">
+              <text>{{ item.processInstance.name }}</text>
+              <text class="card-time">{{ item.createTime }}</text>
+            </view>
+            <view>
+              <view class="card-body">
+                <view class="card-col" v-for="itm in colOptions">
+                  <text class="label">{{ itm.label }}</text>
+                  <text class="content">{{ item[itm.key] }}</text>
+                </view>
+              </view>
+
+              <view class="card-footer">
+                <u-button
+                  type="success"
+                  v-if="
+                    ['0', '2'].includes(
+                      item.extensionProperty.taskHandlePlatform,
+                    )
+                  "
+                  @click="handleDetail(item, 'handle')"
+                  >处理</u-button
+                >
+                <u-button v-else type="error">请在PC端处理</u-button>
+                <u-button type="info" @click="handleDetail(item, 'detail')"
+                  >流程详情</u-button
+                >
+              </view>
+            </view>
+          </view>
+        </u-list-item>
+      </u-list>
+    </view>
+    <view v-show="list.length === 0" class="no_data">
+      <u-empty mode="data" textSize="30"></u-empty>
+    </view>
+  </view>
 </template>
 
 <script>
-	import {
-		getTodoTaskPage
-	} from '@/api/wt/index.js'
-	let [page, size, isEnd] = [1, 10, true]
-
-	export default {
-		computed: {
-			colOptions() {
-				return [{
-						label: '流程节点',
-						key: 'name'
-					},
-					{
-						label: '流程发起人',
-						key: `startUserNickname`
-					}
-				]
-			}
-		},
-		data() {
-			return {
-				list: [],
-				params: {
-					status: '',
-					name: ''
-				}
-			}
-		},
-		onShow() {
-			page = 1
-			this.list = []
-			this.getList()
-		},
-
-		methods: {
-			scrolltolower() {
-				if (isEnd) return
-				page++
-				this.getList()
-			},
-			//miniHandleRouter
-			handleDetail(item, type) {
-				console.log('111~~~', item)
-				//'pages/home' + this.listData.miniHandleRouter
-				///wt/components/feeApplication/taskSubmit
-				if (type == 'handle') {
-					console.log(Object.keys(item.formJson).length)
-					if (Object.keys(item.formJson).length) {
-						
-						let params = JSON.stringify({
-							id: item.id,
-							processInstanceId: item.processInstance.id|| '',
-							type: type
-						})
-						let queryParams = `params=${params}`
-						let url = '/pages/home/wt/components/formParser/routerView'
-            uni.navigateTo({
-							url: `${url}?${queryParams}`
-						})
-					} else {
-						let queryParams =
-							`id=${item.processInstance.id}&businessId=${item.businessId}&taskId=${item.id}&taskDefinitionKey=${item.taskDefinitionKey}&miniHandleRouter=${item.miniHandleRouter}&miniViewRouter=${item.miniViewRouter}`
-						let url = '/pages/home' + item.miniHandleRouter.replace('taskForm', 'processTask')
-						
-						console.log('url~~~',`${url}?${queryParams}`)
-						uni.navigateTo({
-							url: `${url}?${queryParams}`
-						})
-					}			
-
-					//
-				} else {
-					uni.navigateTo({
-						url: `/pages/home/wt/components/detail?processInstanceId=${item.processInstance.id}`
-					})
-				}
-			},
-			async getList() {
-				let paging = {
-					pageNo: page,
-					pageSize: size,
-					processType:0
-				}
-				let par = Object.assign(paging, this.params)
-				isEnd = false
-				const data = await getTodoTaskPage(par)
-				this.list.push(...data.list)
-				this.list.forEach(item => {
-					item.startUserNickname = item.processInstance.startUserNickname
-				})
-				isEnd = this.list.length >= data.count
-			}
-		}
-	}
+import { getTodoTaskPage } from "@/api/wt/index.js";
+let [page, size, isEnd] = [1, 10, true];
+
+export default {
+  computed: {
+    colOptions() {
+      return [
+        {
+          label: "流程节点",
+          key: "name",
+        },
+        {
+          label: "流程发起人",
+          key: `startUserNickname`,
+        },
+      ];
+    },
+  },
+  data() {
+    return {
+      list: [],
+      params: {
+        status: "",
+        name: "",
+      },
+    };
+  },
+  onShow() {
+    page = 1;
+    this.list = [];
+    this.getList();
+  },
+
+  methods: {
+    scrolltolower() {
+      if (isEnd) return;
+      page++;
+      this.getList();
+    },
+    //miniHandleRouter
+    handleDetail(item, type) {
+      console.log("111~~~", item);
+      //'pages/home' + this.listData.miniHandleRouter
+      ///wt/components/feeApplication/taskSubmit
+      if (type == "handle") {
+        console.log(Object.keys(item.formJson).length);
+        if (Object.keys(item.formJson).length) {
+          let params = JSON.stringify({
+            id: item.id,
+            processInstanceId: item.processInstance.id || "",
+            type: type,
+          });
+          let queryParams = `params=${params}`;
+          let url = "/pages/home/wt/components/formParser/routerView";
+          uni.navigateTo({
+            url: `${url}?${queryParams}`,
+          });
+        } else {
+          let queryParams = `id=${item.processInstance.id}&businessId=${item.businessId}&taskId=${item.id}&taskDefinitionKey=${item.taskDefinitionKey}&miniHandleRouter=${item.miniHandleRouter}&miniViewRouter=${item.miniViewRouter}`;
+          let url =
+            "/pages/home" +
+            item.miniHandleRouter.replace("taskForm", "processTask");
+
+          console.log("url~~~", `${url}?${queryParams}`);
+          uni.navigateTo({
+            url: `${url}?${queryParams}`,
+          });
+        }
+
+        //
+      } else {
+        uni.navigateTo({
+          url: `/pages/home/wt/components/detail?processInstanceId=${item.processInstance.id}`,
+        });
+      }
+    },
+    async getList() {
+      let paging = {
+        pageNo: page,
+        pageSize: size,
+        processType: 0,
+      };
+      let par = Object.assign(paging, this.params);
+      isEnd = false;
+      const data = await getTodoTaskPage(par);
+      this.list.push(...data.list);
+      this.list.forEach((item) => {
+        item.startUserNickname = item.processInstance.startUserNickname;
+      });
+      isEnd = this.list.length >= data.count;
+    },
+  },
+};
 </script>
 
 <style lang="scss" scoped>
-	.blacklog-container {
-		height: 100vh;
-		display: flex;
-		flex-direction: column;
-	}
-
-	.list-container {
-		flex: 1;
-		padding: 24rpx;
-		background: $page-bg;
-		flex: 1;
-		overflow: hidden;
-		// position: absolute;
-		// top: 88rpx;
-		// bottom: 0;
-		// left: 0;
-		// right: 0;
-
-		/deep/ .u-list {
-			height: 100% !important;
-		}
-	}
-
-	.no_data {
-		position: fixed;
-		top: 50%;
-		left: 50%;
-		transform: translate(-50%, -50%);
-		color: #999;
-		font-size: 50rpx;
-	}
-
-	.kd-card {
-		font-size: 34rpx;
-		color: #333;
-		background-color: #fff;
-		border-radius: 10rpx;
-		word-break: break-all;
-		margin-bottom: 24rpx;
-
-		.status {
-			font-weight: normal;
-		}
-
-		.card-title {
-			font-size: 1rem;
-			font-weight: bold;
-
-			.card-time {
-				font-weight: normal;
-				color: #bfbfbf;
-				font-size: 0.9rem;
-				align-self: center;
-			}
-		}
-
-		.card-footer,
-		.card-title {
-			display: flex;
-			justify-content: space-between;
-			padding: 30rpx 30rpx;
-		}
-
-		.card-footer {
-			padding: 10rpx 30rpx 18rpx 30rpx;
-			font-size: 0.8rem;
-
-			/deep/ .u-button {
-				width: 48%;
-			}
-		}
-
-		.card-body {
-			padding: 0 28rpx;
-			position: relative;
-			min-height: 150rpx;
-		}
-
-		.card-body:after {
-			content: '';
-			position: absolute;
-			left: auto;
-			top: auto;
-			bottom: 10rpx;
-			right: auto;
-			height: 1rpx;
-			width: 91%;
-			background-color: #f1f1f1;
-		}
-
-		.card-col {
-			padding: 8rpx 0;
-			display: flex;
-
-			// line-height: ;
-
-			.content {
-				flex: 1;
-				overflow: hidden;
-				font-size: 0.9rem;
-			}
-
-			.label {
-				font-size: 0.9rem;
-				color: #999;
-				width: 25%;
-			}
-		}
-	}
+.blacklog-container {
+  height: 100vh;
+  display: flex;
+  flex-direction: column;
+}
+
+.list-container {
+  flex: 1;
+  padding: 24rpx;
+  background: $page-bg;
+  flex: 1;
+  overflow: hidden;
+  // position: absolute;
+  // top: 88rpx;
+  // bottom: 0;
+  // left: 0;
+  // right: 0;
+
+  /deep/ .u-list {
+    height: 100% !important;
+  }
+}
+
+.no_data {
+  position: fixed;
+  top: 50%;
+  left: 50%;
+  transform: translate(-50%, -50%);
+  color: #999;
+  font-size: 50rpx;
+}
+
+.kd-card {
+  font-size: 34rpx;
+  color: #333;
+  background-color: #fff;
+  border-radius: 10rpx;
+  word-break: break-all;
+  margin-bottom: 24rpx;
+
+  .status {
+    font-weight: normal;
+  }
+
+  .card-title {
+    font-size: 1rem;
+    font-weight: bold;
+
+    .card-time {
+      font-weight: normal;
+      color: #bfbfbf;
+      font-size: 0.9rem;
+      align-self: center;
+    }
+  }
+
+  .card-footer,
+  .card-title {
+    display: flex;
+    justify-content: space-between;
+    padding: 30rpx 30rpx;
+  }
+
+  .card-footer {
+    padding: 10rpx 30rpx 18rpx 30rpx;
+    font-size: 0.8rem;
+
+    /deep/ .u-button {
+      width: 48%;
+    }
+  }
+
+  .card-body {
+    padding: 0 28rpx;
+    position: relative;
+    min-height: 150rpx;
+  }
+
+  .card-body:after {
+    content: "";
+    position: absolute;
+    left: auto;
+    top: auto;
+    bottom: 10rpx;
+    right: auto;
+    height: 1rpx;
+    width: 91%;
+    background-color: #f1f1f1;
+  }
+
+  .card-col {
+    padding: 8rpx 0;
+    display: flex;
+
+    // line-height: ;
+
+    .content {
+      flex: 1;
+      overflow: hidden;
+      font-size: 0.9rem;
+    }
+
+    .label {
+      font-size: 0.9rem;
+      color: #999;
+      width: 25%;
+    }
+  }
+}
 </style>