index.vue 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434
  1. <template>
  2. <z-paging ref="paging" v-model="list" bgColor="#f7f7f7" @query="query" hide-no-more-inside hide-empty-view>
  3. <template #top>
  4. <ut-navbar title="加工任务详情" :fixed="false"> </ut-navbar>
  5. </template>
  6. <view class="pd-24">
  7. <view class="bg-#fff pd-24 pt-16 b-radius p-rtv" @click="gotoDetail">
  8. <!-- 任务类型标签 -->
  9. <view v-if="+taskDetail?.processType == 1 && +taskDetail?.processMedType == 1" class="bg-#91C747 c-#fff f-w-5 pd-10 pt-4 pb-4 f-s-20" style="border-radius: 16rpx 0 16rpx 0; width: max-content; position: absolute; top: 0rpx; left: 0rpx">种子初加工</view>
  10. <view v-if="+taskDetail?.processType == 1 && +taskDetail?.processMedType == 2" class="bg-#C7A962 c-#fff f-w-5 pd-10 pt-4 pb-4 f-s-20" style="border-radius: 16rpx 0 16rpx 0; width: max-content; position: absolute; top: 0rpx; left: 0rpx">药材初加工</view>
  11. <view v-if="+taskDetail?.processType == 2" class="bg-#37A954 c-#fff f-w-5 pd-10 pt-4 pb-4 f-s-20" style="border-radius: 16rpx 0 16rpx 0; width: max-content; position: absolute; top: 0rpx; left: 0rpx">趁鲜切制</view>
  12. <!-- 日期范围 -->
  13. <view v-if="taskDetail?.processingDate || taskDetail?.processingDateEnd" class="d-flex a-c j-ed">
  14. <view class="c-#999 f-s-24">{{ taskDetail?.processingDate }} 至 {{ taskDetail?.processingDateEnd }}</view>
  15. </view>
  16. <!-- 药材名称 -->
  17. <view class="d-flex a-c mb-10">
  18. <view class="f-s-34 f-w-5 c-#333 mr-10">{{ taskDetail?.variety || taskDetail?.medicineName }}</view>
  19. <view v-if="+taskDetail?.processMedType == 1" class="f-s-24 c-#666">{{ selectDictLabel(pt_stock_type, taskDetail?.processMedType) }}</view>
  20. </view>
  21. <!-- 加工批号 -->
  22. <view class="d-flex f-s-28 pd2-4-0">
  23. <view class="c-#666">加工批号:</view>
  24. <view class="c-#333 f-w-5 flex1">{{ taskDetail?.processCode }}</view>
  25. </view>
  26. <!-- 执行标准 -->
  27. <view class="d-flex f-s-28 pd2-4-0">
  28. <view class="c-#666">执行标准:</view>
  29. <view class="c-#333 f-w-5 flex1">
  30. <span>{{ selectDictLabel(pt_standard_type, taskDetail?.standardType) }}</span>
  31. <span v-if="taskDetail?.standardDetailName" class="c-#666">({{ taskDetail?.standardDetailName }})</span>
  32. </view>
  33. </view>
  34. <!-- 加工工艺 -->
  35. <view class="d-flex f-s-28 pd2-4-0">
  36. <view class="c-#666">加工工艺:</view>
  37. <view class="c-#333 f-w-5 flex1 d-flex a-c" style="justify-content: flex-start">
  38. <template v-for="(item, index) in (taskDetail?.ptech || '').split(',')" :key="index">
  39. <span v-if="+index > 0 && item" class="c-#999 ml-10 mr-10">→</span>
  40. <span v-if="item">{{ item }}</span>
  41. </template>
  42. <span v-if="!taskDetail?.ptech" class="c-#999">-</span>
  43. </view>
  44. </view>
  45. <view class="d-flex j-sb">
  46. <!-- 加工负责人 -->
  47. <view class="d-flex f-s-28 pd2-4-0">
  48. <view class="c-#666">加工负责人:</view>
  49. <view class="c-#333 f-w-5 flex1">{{ taskDetail?.contactName || '-' }}</view>
  50. </view>
  51. <!-- 去修改按钮 -->
  52. <view class="d-flex a-c j-ed pd2-4-0">
  53. <view class="c-primary f-s-28 d-flex a-c" @click.stop="goEdit">
  54. <span>去修改</span>
  55. <up-icon name="arrow-right" size="24rpx" class="ml-5"></up-icon>
  56. </view>
  57. </view>
  58. </view>
  59. </view>
  60. <!-- Tab 切换 -->
  61. <view class="d-flex a-c bg-#f7f7f7 mb-16">
  62. <up-tabs :list="tabs" @change="onTabChange" :current="activeTab" lineWidth="60"></up-tabs>
  63. </view>
  64. <!-- 原料信息列表 -->
  65. <view v-if="+activeTab == 0">
  66. <view v-if="list.length === 0 && +activeTab == 0" class="d-flex flex-cln a-c pd-40">
  67. <ut-empty color="#ccc" size="28rpx" image=" https://ta.zycpzs.cn/oss-file/smart-trace/szyy/images-plt/plant/noEmpty.png">暂无加工原料信息</ut-empty>
  68. <up-button type="primary" @click="goAssociate">去关联原料信息</up-button>
  69. </view>
  70. <view v-else class="d-flex a-c mb-16">
  71. <view class="c-#999 f-s-28">使用的加工原料批次</view>
  72. <view class="flex1"></view>
  73. <up-button type="error" style="width: 160rpx; height: 60rpx" @click="withdraw">撤回用料</up-button>
  74. </view>
  75. <view v-for="(item, index) in list" :key="index" class="bg-#fff b-radius pd-24">
  76. <!-- 类型标签 -->
  77. <view class="d-flex j-sb a-c li-item-head mb-16">
  78. <view class="li-left-tag" :class="{ [`bg-instore-${item?.storageInfo?.instoreType}`]: true }">{{ selectDictLabel(pt_fresh_instore_type, item?.storageInfo?.instoreType) }}</view>
  79. <view class="f-s-22 c-#666 pt-10">{{ item?.updateTime || item?.createTime }}</view>
  80. </view>
  81. <view class="d-flex a-c j-sb mb-10">
  82. <!-- 物料名称 -->
  83. <view class="d-flex" style="align-items: flex-end">
  84. <view class="f-s-32 f-w-5 c-#333 mr-10">{{ item?.materialName }}</view>
  85. <view class="f-s-24 c-#999">{{ item?.storageInfo?.partName }}</view>
  86. </view>
  87. <!-- 状态 -->
  88. <view class="d-flex a-c" v-if="item?.storageInfo?.examinReport">
  89. <view class="c-#37A954 f-s-24 bg-#EDF7F0 pd-8 radius-8">已检验</view>
  90. </view>
  91. </view>
  92. <!-- 溯源入库 -->
  93. <template v-if="+item?.storageInfo?.instoreType == 1">
  94. <!-- 采收批号 -->
  95. <view class="d-flex pd2-4-0 f-s-28">
  96. <view class="c-#666">入库批号:</view>
  97. <view class="c-#333 f-w-5 flex1">{{ item?.storageInfo?.batchCode }}</view>
  98. </view>
  99. <view class="d-flex pd2-4-0 f-s-28">
  100. <view class="c-#666">供应商:</view>
  101. <view class="c-#333 f-w-5 flex1">{{ item?.storageInfo?.supplier || '-' }}</view>
  102. </view>
  103. </template>
  104. <!-- 非溯源入库 -->
  105. <template v-if="+item?.storageInfo?.instoreType == 2">
  106. <!-- 采收批号 -->
  107. <view class="d-flex pd2-4-0 f-s-28">
  108. <view class="c-#666">入库批号:</view>
  109. <view class="c-#333 f-w-5 flex1">{{ item?.storageInfo?.batchCode }}</view>
  110. </view>
  111. <view class="d-flex pd2-4-0 f-s-28">
  112. <view class="c-#666">供应商:</view>
  113. <view class="c-#333 f-w-5 flex1">{{ item?.storageInfo?.supplier || '-' }}</view>
  114. </view>
  115. <view class="d-flex pd2-4-0 f-s-28">
  116. <view class="c-#666">存放库房:</view>
  117. <view class="c-#333 f-w-5 flex1">
  118. {{ getStorageRoomNames(item?.storageInfo?.warehouses) || '-' }}
  119. </view>
  120. </view>
  121. </template>
  122. <!-- 采收入库 -->
  123. <template v-if="+item?.storageInfo?.instoreType == 3">
  124. <!-- 采收批号 -->
  125. <view class="d-flex pd2-4-0 f-s-28">
  126. <view class="c-#666">采收批号:</view>
  127. <view class="c-#333 f-w-5 flex1">{{ item?.storageInfo?.batchCode }}</view>
  128. </view>
  129. <view class="d-flex pd2-4-0 f-s-28">
  130. <view class="c-#666">采收基地:</view>
  131. <view class="c-#333 f-w-5 flex1">{{ item?.storageInfo?.baseName || '-' }}</view>
  132. </view>
  133. </template>
  134. <!-- 本次使用量 -->
  135. <view class="d-flex pd2-4-0 f-s-28">
  136. <view class="c-#666">本次使用量:</view>
  137. <view class="c-#333 f-w-5 flex1">{{ item?.quantity || 0 }}{{ item?.unit }}</view>
  138. </view>
  139. </view>
  140. </view>
  141. <!-- 产出信息列表 -->
  142. <view v-else>
  143. <view v-if="outputList?.length === 0" class="d-flex flex-cln a-c pd-40">
  144. <ut-empty color="#ccc" size="28rpx" image="https://ta.zycpzs.cn/oss-file/smart-trace/szyy/images-plt/plant/noEmpty.png">暂无产出信息</ut-empty>
  145. <up-button type="primary" @click="handleShowOutputModel">去添加产出信息</up-button>
  146. </view>
  147. <view v-else class="d-flex a-c mb-16">
  148. <view class="c-#999 f-s-28">产出物:</view>
  149. <view class="c-#999 f-s-28">{{ outputList.length }}个</view>
  150. <view class="flex1"></view>
  151. <up-button v-if="+taskDetail?.processType == 1 && +taskDetail?.processMedType == 1" color="#18BECA" style="width: 210rpx; height: 60rpx; margin-right: 20rpx" @click="goToBatchInstore">单个/批量入库</up-button>
  152. <up-button type="primary" style="width: 160rpx; height: 60rpx" @click="handleShowOutputModel">添加产出</up-button>
  153. </view>
  154. <up-swipe-action>
  155. <up-swipe-action-item v-for="(item, index) in outputList" :key="index" :name="item?.id" :options="swipeOptions" class="mb-16" @click="handleSwipeClick">
  156. <ProcessingOutputItem :item="item" :index="index" :selectable="false" @click="handleOutputItemClick" />
  157. </up-swipe-action-item>
  158. </up-swipe-action>
  159. </view>
  160. </view>
  161. </z-paging>
  162. <!-- 添加/修改产出信息弹框 -->
  163. <OutputInfo v-if="showOutputModel" v-model:show="showOutputModel" :type="taskDetail?.processType" :processId="taskId" :isEdit="isEditOutput" :editData="editOutputData" @confirm="handleOutputConfirm" />
  164. </template>
  165. <script setup lang="ts">
  166. import { getStorageRoomNames } from '@/utils/common';
  167. import { useClientRequest } from '@/utils/request';
  168. import OutputInfo from './models/outputInfo.vue';
  169. import ProcessingOutputItem from './models/processing-output-item.vue';
  170. const { proxy } = getCurrentInstance() as ComponentInternalInstance;
  171. const { pt_stock_type, pt_standard_type, pt_fresh_instore_type, pt_final_form_type } = toRefs<any>(proxy?.useDict('pt_stock_type', 'pt_standard_type', 'pt_fresh_instore_type', 'pt_final_form_type'));
  172. const paging = ref();
  173. const list = ref<any[]>([]);
  174. const taskId = ref('');
  175. const taskDetail = ref<any>({});
  176. const outputList = ref<any[]>([]);
  177. const activeTab = ref(0);
  178. const tabs = [
  179. {
  180. name: '原料信息',
  181. value: 0,
  182. },
  183. {
  184. name: '产出信息',
  185. value: 1,
  186. },
  187. ];
  188. // 加载任务详情
  189. const loadTaskDetail = async () => {
  190. try {
  191. const res = await useClientRequest.get(`/plt-api/app/processe/getInfoById/${taskId.value}`);
  192. if (res && res.data) {
  193. taskDetail.value = res.data;
  194. }
  195. } catch (error) {
  196. console.error('加载任务详情失败:', error);
  197. }
  198. };
  199. // z-paging 查询原料列表
  200. const query = async (pageNum: number, pageSize: number) => {
  201. try {
  202. const res = await useClientRequest.get('/plt-api/app/processInputMaterial/pageList', {
  203. pageNum,
  204. pageSize,
  205. processId: taskId.value,
  206. });
  207. if (res) {
  208. const { rows } = res;
  209. paging.value.complete(rows);
  210. }
  211. getOutputList();
  212. } catch (error) {
  213. console.error('加载原料列表失败:', error);
  214. paging.value.complete([]);
  215. }
  216. };
  217. const goAssociate = () => {
  218. uni.$once(`updatesupervise-${taskDetail?.value?.id}`, function (data) {
  219. paging.value?.reload();
  220. });
  221. uni.$u.route({
  222. type: 'navigateTo',
  223. url: '/tools/species-info-process/index',
  224. params: { id: taskDetail?.value?.id, processMedType: taskDetail?.value?.processMedType },
  225. });
  226. };
  227. // Tab 切换
  228. const onTabChange = (tabItem: any) => {
  229. activeTab.value = tabItem?.value;
  230. if (+activeTab.value === 1) {
  231. // 切换到产出信息,加载产出信息列表
  232. getOutputList();
  233. } else {
  234. // 切换回原料信息,重新加载
  235. paging.value?.reload();
  236. }
  237. };
  238. // 获取产出信息列表
  239. const getOutputList = async () => {
  240. try {
  241. const res: any = await useClientRequest.get('/plt-api/app/processOutPut/pageList', {
  242. processId: taskId.value,
  243. });
  244. if (res && res.rows) {
  245. outputList.value = res.rows;
  246. }
  247. return res;
  248. } catch (error) {
  249. console.error('加载产出信息失败:', error);
  250. outputList.value = [];
  251. }
  252. };
  253. // 去修改
  254. const goEdit = () => {
  255. uni.$u.route({
  256. type: 'navigateTo',
  257. url: '/plant/processing/processing-create/index',
  258. params: { id: taskId.value, edit: 1 },
  259. });
  260. };
  261. // 跳转到详情页
  262. const gotoDetail = () => {
  263. uni.$u.route({
  264. type: 'navigateTo',
  265. url: '/plant/processing/processing-detail/index',
  266. params: { id: taskId.value },
  267. });
  268. };
  269. // 监听修改成功事件,重新加载任务详情
  270. const handleUpdateTaskDetail = () => {
  271. loadTaskDetail(); // 重新加载任务详情
  272. if (+activeTab.value === 0) {
  273. paging.value?.reload(); // 刷新原料列表
  274. } else {
  275. getOutputList(); // 刷新产出列表
  276. }
  277. };
  278. onLoad((options: any) => {
  279. taskId.value = options?.id || '';
  280. // 监听修改成功事件
  281. uni.$on('updateprocesstasklist', handleUpdateTaskDetail);
  282. if (taskId.value) {
  283. loadTaskDetail();
  284. }
  285. if (options?.output) {
  286. activeTab.value = 1;
  287. getOutputList();
  288. }
  289. });
  290. // 离开页面时卸载事件监听
  291. onUnload(() => {
  292. uni.$off('updateprocesstasklist');
  293. });
  294. const withdraw = async () => {
  295. // 删除
  296. const res = await uni.showModal({
  297. title: '撤回提示',
  298. content: '撤回后不可恢复,请谨慎操作!',
  299. confirmColor: '#F74C30',
  300. });
  301. console.log(res);
  302. if (res.confirm) {
  303. const delRes = await useClientRequest.get(`/plt-api/app/processInputMaterial/callbackInput/${list.value?.[0]?.id}`);
  304. if (delRes && delRes.code === 200) {
  305. uni.showToast({ title: '删除成功', icon: 'none' });
  306. uni.$emit(`updatesupervise-${taskId.value}`, []);
  307. paging.value?.reload();
  308. }
  309. }
  310. };
  311. // 显示添加产出信息弹框
  312. const showOutputModel = ref(false);
  313. const isEditOutput = ref(false); // 是否编辑模式
  314. const editOutputData = ref<any>({}); // 编辑的数据
  315. const handleShowOutputModel = () => {
  316. isEditOutput.value = false;
  317. editOutputData.value = {};
  318. showOutputModel.value = true;
  319. };
  320. // 处理添加/修改成功
  321. const handleOutputConfirm = async () => {
  322. const res: any = await getOutputList();
  323. console.log(res, 'res˝');
  324. uni.$emit(`updateoutList-${taskId.value}`, res?.rows || []);
  325. };
  326. // 处理产出项点击
  327. const handleOutputItemClick = (item: any) => {
  328. console.log('点击产出项:', item);
  329. };
  330. // 滑动操作选项
  331. const swipeOptions = reactive([
  332. {
  333. text: '修改',
  334. style: {
  335. backgroundColor: '#18BECA',
  336. width: '100rpx',
  337. fontSize: '28rpx',
  338. },
  339. },
  340. {
  341. text: '删除',
  342. style: {
  343. backgroundColor: '#F74C30',
  344. width: '100rpx',
  345. fontSize: '28rpx',
  346. },
  347. },
  348. ]);
  349. // 处理滑动按钮点击
  350. const handleSwipeClick = async (event: any) => {
  351. const { name, index } = event;
  352. const item = outputList.value[index];
  353. if (index === 0) {
  354. // 点击修改
  355. handleEditOutput(item);
  356. } else if (index === 1) {
  357. // 点击删除
  358. handleDeleteOutput(name, item);
  359. }
  360. };
  361. // 处理修改产出
  362. const handleEditOutput = (item: any) => {
  363. isEditOutput.value = true;
  364. editOutputData.value = item;
  365. showOutputModel.value = true;
  366. };
  367. // 处理删除产出
  368. const handleDeleteOutput = async (outPutId: string | number, item: any) => {
  369. try {
  370. const res = await uni.showModal({
  371. title: '删除提示',
  372. content: '删除后不可恢复,请谨慎操作!',
  373. confirmColor: '#F74C30',
  374. });
  375. if (!res.confirm) return;
  376. const delRes = await useClientRequest.get(`/plt-api/app/processOutPut/removeOutPut/${outPutId}`);
  377. if (delRes && delRes.code === 200) {
  378. uni.showToast({ title: '删除成功', icon: 'none' });
  379. const data = await getOutputList();
  380. uni.$emit(`updateoutList-${taskId.value}`, data?.rows || []);
  381. }
  382. } catch (error) {
  383. console.error('删除失败:', error);
  384. }
  385. };
  386. // 跳转到单个/批量入库页面
  387. const goToBatchInstore = () => {
  388. uni.$u.route({
  389. type: 'navigateTo',
  390. url: '/plant/processing/processing-depstock/index',
  391. params: {
  392. processId: taskId.value,
  393. },
  394. });
  395. };
  396. </script>
  397. <style scoped lang="scss">
  398. .li-left-tag {
  399. padding: 6rpx 16rpx;
  400. color: #fff;
  401. border-radius: 16rpx 0 16rpx 0;
  402. font-size: 20rpx;
  403. font-weight: 500;
  404. }
  405. .li-item-head {
  406. margin-left: -24rpx;
  407. margin-top: -24rpx;
  408. }
  409. </style>