outputInfo.vue 19 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384
  1. <template>
  2. <up-popup :show="show" mode="bottom" @close="handleClose" :round="20" closeable safeAreaInsetBottom>
  3. <view class="d-flex flex-cln">
  4. <view class="f-s-34 f-w-5 pd-24 pb-16">{{ getTitle() }}</view>
  5. <scroll-view scroll-y class="flex1" style="max-height: 70vh">
  6. <view class="pd-24">
  7. <up-form ref="formRef" :model="formData" :rules="rules" labelPosition="top" labelWidth="auto">
  8. <template v-if="+type == 1">
  9. <!-- 规格等级 -->
  10. <up-form-item label="规格等级" required prop="specnLevel">
  11. <view class="flex1" @click="goToSpecLevel">
  12. <up-input readonly v-model="formData.specnLevel" type="number" placeholder="请选择规格等级"
  13. style="padding-left: 0; padding-right: 0" border="bottom" clearable
  14. suffixIcon="arrow-down-fill" suffixIconStyle="color: #2A6D52;font-size: 22rpx">
  15. </up-input>
  16. </view>
  17. <view class="ml-20">
  18. <up-checkbox :customStyle="{ marginBottom: '8px' }" label="统货" name="agree"
  19. usedAlone :checked="formData.specnLevel == '统货'"
  20. @change="handleSpecnLevelChange"> </up-checkbox>
  21. </view>
  22. </up-form-item>
  23. <!-- 产量 -->
  24. <up-form-item label="产量" prop="capacity" required>
  25. <view class="flex1 d-flex">
  26. <view class="flex1 ov-hd" id="capacitypppp">
  27. <up-form-item border-bottom prop="capacity" class="form-item-top-padding-0">
  28. <up-input v-model="formData.capacity" type="number" placeholder="请输入产量"
  29. border="none" clearable></up-input>
  30. </up-form-item>
  31. </view>
  32. <view class="pd-5"></view>
  33. <view class="min-w-100">
  34. <ut-action-sheet v-model="formData.unit" :tabs="pt_out_put_unit" title="选择单位">
  35. <up-form-item border-bottom prop="unit" class="form-item-top-padding-0">
  36. <view class="flex1" style="line-height: 24px">
  37. <view v-if="formData?.unit" class="f-s-30 c-#333 f-w-5 flex1">{{
  38. formData?.unit }}</view>
  39. <view v-else class="f-s-30 c-ccc f-w-4 flex1">单位</view>
  40. </view>
  41. <template #right>
  42. <up-icon size="22rpx" color="#2A6D52"
  43. name="arrow-down-fill"></up-icon>
  44. </template>
  45. </up-form-item>
  46. </ut-action-sheet>
  47. </view>
  48. </view>
  49. </up-form-item>
  50. <!-- 产出物图片 -->
  51. <up-form-item borderBottom label="产出物图片">
  52. <ut-upload v-model="formData.imgs" :max-count="6" valueType="array" accept="image"
  53. width="210rpx" height="210rpx" style="card"></ut-upload>
  54. </up-form-item>
  55. <!-- 检验报告 -->
  56. <up-form-item borderBottom label="加工检验报告">
  57. <ut-upload v-model="formData.examinReport" :max-count="50" valueType="array"
  58. accept="image,file" width="210rpx" height="210rpx" style="card"></ut-upload>
  59. </up-form-item>
  60. </template>
  61. <!-- 类型 2 特有字段 -->
  62. <template v-else>
  63. <!-- 规格等级 -->
  64. <up-form-item label="规格等级" required prop="specnLevel">
  65. <view class="flex1" @click="goToSpecLevel">
  66. <up-input readonly v-model="formData.specnLevel" type="number" placeholder="请选择规格等级"
  67. style="padding-left: 0; padding-right: 0" border="bottom" clearable
  68. suffixIcon="arrow-down-fill" suffixIconStyle="color: #2A6D52;font-size: 22rpx">
  69. </up-input>
  70. </view>
  71. <view class="ml-20">
  72. <up-checkbox :customStyle="{ marginBottom: '8px' }" label="统货" name="agree"
  73. usedAlone :checked="formData.specnLevel == '统货'"
  74. @change="handleSpecnLevelChange"> </up-checkbox>
  75. </view>
  76. </up-form-item>
  77. <!-- 产量 -->
  78. <up-form-item label="产量" prop="capacity" required>
  79. <view class="flex1 d-flex">
  80. <view class="flex1 ov-hd" id="capacitypppp">
  81. <up-form-item border-bottom prop="capacity" class="form-item-top-padding-0">
  82. <up-input v-model="formData.capacity" type="number" placeholder="请输入产量"
  83. border="none" clearable></up-input>
  84. </up-form-item>
  85. </view>
  86. <view class="pd-5"></view>
  87. <view class="min-w-100">
  88. <ut-action-sheet v-model="formData.unit" :tabs="pt_out_put_unit" title="选择单位">
  89. <up-form-item border-bottom prop="unit" class="form-item-top-padding-0">
  90. <view class="flex1" style="line-height: 24px">
  91. <view v-if="formData?.unit" class="f-s-30 c-#333 f-w-5 flex1">{{
  92. formData?.unit }}</view>
  93. <view v-else class="f-s-30 c-ccc f-w-4 flex1">单位</view>
  94. </view>
  95. <template #right>
  96. <up-icon size="22rpx" color="#37A954"
  97. name="arrow-down-fill"></up-icon>
  98. </template>
  99. </up-form-item>
  100. </ut-action-sheet>
  101. </view>
  102. </view>
  103. </up-form-item>
  104. <!-- 切制形态 -->
  105. <ut-action-sheet v-model="formData.finalFormType" :tabs="pt_final_form_type" title="选择切制形态">
  106. <up-form-item borderBottom label="切制形态" prop="finalFormType" required>
  107. <view v-if="formData?.finalFormType" class="f-s-30 c-#333 f-w-5 flex1">{{
  108. selectDictLabel(pt_final_form_type,
  109. formData?.finalFormType) }}</view>
  110. <view v-else class="f-s-30 c-ccc f-w-4 flex1">请选择切制形态</view>
  111. <template #right>
  112. <up-icon size="22rpx" color="#37A954" name="arrow-down-fill"></up-icon>
  113. </template>
  114. </up-form-item>
  115. </ut-action-sheet>
  116. <!-- 具体切制形态 -->
  117. <up-form-item borderBottom label="具体切制形态" prop="finalFormOther" required>
  118. <up-input v-model="formData.finalFormOther" placeholder="请输入具体切制形态" border="none"
  119. clearable></up-input>
  120. </up-form-item>
  121. <!-- 切制尺寸 -->
  122. <up-form-item label="切制尺寸" required>
  123. <view class="flex1 d-flex">
  124. <view class="flex1 ov-hd" id="finalSpecnpppp">
  125. <up-form-item border-bottom prop="finalSpecn" class="form-item-top-padding-0">
  126. <up-input v-model="formData.finalSpecn" type="number" placeholder="请输入切制尺寸"
  127. border="none" clearable></up-input>
  128. </up-form-item>
  129. </view>
  130. <view class="pd-5"></view>
  131. <view class="min-w-100">
  132. <ut-action-sheet v-model="formData.finalUnit" :tabs="pt_final_unit"
  133. title="选择切制单位">
  134. <up-form-item border-bottom prop="finalUnit"
  135. class="form-item-top-padding-0">
  136. <view class="flex1" style="line-height: 24px">
  137. <view v-if="formData?.finalUnit" class="f-s-30 c-#333 f-w-5 flex1">
  138. {{
  139. selectDictLabel(pt_final_unit, formData?.finalUnit) }}</view>
  140. <view v-else class="f-s-30 c-ccc f-w-4 flex1">单位</view>
  141. </view>
  142. <template #right>
  143. <up-icon size="22rpx" color="#37A954"
  144. name="arrow-down-fill"></up-icon>
  145. </template>
  146. </up-form-item>
  147. </ut-action-sheet>
  148. </view>
  149. </view>
  150. </up-form-item>
  151. <!-- 产出物图片 -->
  152. <up-form-item borderBottom label="产出物图片">
  153. <ut-upload v-model="formData.imgs" :max-count="6" valueType="array" accept="image"
  154. width="210rpx" height="210rpx" style="card"></ut-upload>
  155. </up-form-item>
  156. <!-- 检验报告 -->
  157. <up-form-item borderBottom label="加工检验报告">
  158. <ut-upload v-model="formData.examinReport" :max-count="50" valueType="array"
  159. accept="image,file" width="210rpx" height="210rpx" style="card"></ut-upload>
  160. </up-form-item>
  161. </template>
  162. </up-form>
  163. </view>
  164. <!-- 底部按钮 -->
  165. </scroll-view>
  166. <template #bottom>
  167. <view class="d-flex gap-20 pd-24">
  168. <up-button plain type="info" @click="handleClose">取消</up-button>
  169. <up-button type="primary" @click="handleSubmit">确认</up-button>
  170. </view>
  171. </template>
  172. </view>
  173. </up-popup>
  174. </template>
  175. <script setup lang="ts">
  176. import { useClientRequest } from '@/utils/request';
  177. const { proxy } = getCurrentInstance() as ComponentInternalInstance;
  178. const { pt_final_form_type, pt_final_unit, pt_out_put_unit } = toRefs<any>(proxy?.useDict('pt_final_form_type', 'pt_final_unit', 'pt_out_put_unit'));
  179. // 字典标签选择函数
  180. const selectDictLabel = (dict: any[], value: string | number) => {
  181. const item = dict.find((item) => item.value == value);
  182. return item ? item.label : '';
  183. };
  184. const props = defineProps<{
  185. show: boolean;
  186. type: number; // 1: 初加工,2: 趁鲜切制
  187. processId: string | number; // 加工任务 ID
  188. isEdit: boolean; // 是否编辑模式
  189. editData: any; // 要编辑的数据
  190. }>();
  191. const emit = defineEmits<{
  192. 'update:show': [value: boolean];
  193. confirm: [data: any];
  194. }>();
  195. const formRef = ref();
  196. // 表单数据
  197. const formData = ref({
  198. specnLevel: '',
  199. capacity: '',
  200. unit: '',
  201. imgs: [] as any[],
  202. examinReport: [] as any[],
  203. finalFormType: '',
  204. finalFormOther: '',
  205. finalSpecn: '',
  206. finalUnit: '',
  207. id: '', // 编辑模式需要 id
  208. });
  209. // 监听 editData 变化,初始化表单数据
  210. watch(
  211. () => props.editData,
  212. (newVal) => {
  213. if (newVal && props.isEdit) {
  214. formData.value = {
  215. specnLevel: newVal?.specnLevel || '',
  216. capacity: newVal?.capacity || '',
  217. unit: newVal?.unit || '',
  218. imgs: newVal?.imgs ? newVal.imgs.split(',').map((url: string) => ({ url })) : [],
  219. examinReport: newVal?.examinReport || [],
  220. finalFormType: newVal?.finalFormType || '',
  221. finalFormOther: newVal?.finalFormOther || '',
  222. finalSpecn: newVal?.finalSpecn || '',
  223. finalUnit: newVal?.finalUnit || '',
  224. id: newVal?.id || '',
  225. };
  226. }
  227. },
  228. { immediate: true },
  229. );
  230. // 动态生成校验规则
  231. const getRules = () => {
  232. const baseRules = {
  233. specnLevel: [{ required: true, message: '请选择规格等级', trigger: 'change' }],
  234. capacity: [
  235. { required: true, message: '请输入产量', trigger: 'blur' },
  236. { type: 'number', message: '产量必须为数字', trigger: 'blur' },
  237. ],
  238. unit: [{ required: true, message: '请选择单位', trigger: 'change' }],
  239. };
  240. if (type.value === 2) {
  241. // 类型 2(趁鲜切制)所有字段必填
  242. return {
  243. ...baseRules,
  244. finalFormType: [{ required: true, message: '请选择切制形态', trigger: 'change' }],
  245. finalFormOther: [{ required: true, message: '请输入具体切制形态', trigger: 'blur' }],
  246. finalSpecn: [{ required: true, message: '请输入切制尺寸', trigger: 'blur' }],
  247. finalUnit: [{ required: true, message: '请选择切制单位', trigger: 'change' }],
  248. };
  249. } else {
  250. // 类型 1(初加工)只有前三个必填
  251. return baseRules;
  252. }
  253. };
  254. // 根据 type 动态设置校验规则
  255. const type = ref(+props.type);
  256. const rules = ref(getRules());
  257. // 监听 type 变化,重新生成规则
  258. watch(
  259. () => props.type,
  260. (newVal) => {
  261. type.value = newVal;
  262. rules.value = getRules();
  263. },
  264. );
  265. // 关闭弹框
  266. const handleClose = () => {
  267. emit('update:show', false);
  268. resetForm();
  269. };
  270. // 获取标题
  271. const getTitle = () => {
  272. return props.isEdit ? '修改产出信息' : '添加产出信息';
  273. };
  274. // 重置表单
  275. const resetForm = () => {
  276. formData.value = {
  277. specnLevel: '',
  278. capacity: '',
  279. unit: '',
  280. imgs: [],
  281. examinReport: [],
  282. finalFormType: '',
  283. finalFormOther: '',
  284. finalSpecn: '',
  285. finalUnit: '',
  286. id: '',
  287. };
  288. formRef.value?.clearValidate();
  289. };
  290. // 处理统货 checkbox 点击事件
  291. const handleSpecnLevelChange = (checked: boolean) => {
  292. if (checked) {
  293. formData.value.specnLevel = '统货';
  294. } else {
  295. formData.value.specnLevel = '';
  296. }
  297. };
  298. // 跳转到规格等级选择页面
  299. const goToSpecLevel = () => {
  300. uni.$once('updateSpecificationLevel', (res) => {
  301. if (res?.data) {
  302. formData.value.specnLevel = res.data;
  303. }
  304. });
  305. uni.navigateTo({
  306. url: '/tools/specification-level/index',
  307. });
  308. };
  309. // 提交表单
  310. const handleSubmit = async () => {
  311. try {
  312. const valid = await formRef.value?.validate();
  313. if (!valid) return;
  314. // 准备提交数据
  315. const submitData = {
  316. processId: props.processId,
  317. specnLevel: formData.value.specnLevel,
  318. capacity: Number(formData.value.capacity),
  319. unit: formData.value.unit,
  320. imgs: formData.value.imgs.map((item: any) => item.url).join(','),
  321. examinReport: formData.value.examinReport.map((item: any) => ({
  322. fileName: item.fileName || '',
  323. url: item.url || '',
  324. fileSize: item.fileSize || 0,
  325. })),
  326. finalFormType: formData.value.finalFormType,
  327. finalFormOther: formData.value.finalFormOther,
  328. finalSpecn: formData.value.finalSpecn,
  329. finalUnit: formData.value.finalUnit,
  330. };
  331. let res: any;
  332. // 编辑模式调用修改接口
  333. if (props.isEdit && formData.value.id) {
  334. (submitData as any).id = formData.value.id;
  335. res = await useClientRequest.post('/plt-api/app/processOutPut/outputEdit', submitData);
  336. } else {
  337. // 新增模式调用新增接口
  338. res = await useClientRequest.post('/plt-api/app/processOutPut/output', submitData);
  339. }
  340. if (res && res.code === 200) {
  341. uni.showToast({ title: props.isEdit ? '修改成功' : '添加成功', icon: 'success' });
  342. handleClose();
  343. emit('confirm', res.data);
  344. }
  345. } catch (error) {
  346. console.error('提交失败:', error);
  347. }
  348. };
  349. </script>
  350. <style scoped lang="scss">
  351. .search-select-item {
  352. height: 86rpx;
  353. background-color: #fff;
  354. border-radius: 10rpx;
  355. box-sizing: border-box;
  356. padding-left: 16rpx;
  357. padding-right: 16rpx;
  358. padding-top: 14rpx;
  359. padding-bottom: 14rpx;
  360. }
  361. </style>