index.vue 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443
  1. <template>
  2. <div class="tenant">
  3. <!-- <Banner /> -->
  4. <div class="content">
  5. <byTable
  6. :source="sourceList.data"
  7. :pagination="sourceList.pagination"
  8. :config="config"
  9. :loading="loading"
  10. highlight-current-row
  11. :selectConfig="selectConfig"
  12. :table-events="{
  13. //element talbe事件都能传
  14. select: selectRow,
  15. }"
  16. :action-list="[
  17. {
  18. text: '质检',
  19. disabled: selectData.length === 0,
  20. action: () => start(20),
  21. },
  22. ]"
  23. @get-list="getList"
  24. >
  25. <template #fileSlot="{ item }">
  26. <div
  27. style="cursor: pointer; color: #409eff"
  28. @click="handleClickFile(item)"
  29. >
  30. {{ item.fileName }}
  31. </div>
  32. </template>
  33. </byTable>
  34. </div>
  35. <el-dialog
  36. title="到货质检"
  37. v-model="dialogVisible"
  38. width="800"
  39. v-loading="loading"
  40. >
  41. <el-form
  42. :model="formData.data"
  43. :rules="rules"
  44. ref="formDom"
  45. label-position="top"
  46. >
  47. <div style="margin-bottom: 10px; font-size: 14px">基础信息</div>
  48. <el-row>
  49. <el-col :span="8">
  50. <el-form-item label="供应商" prop="supplyId">
  51. <el-select
  52. v-model="formData.data.supplyId"
  53. placeholder="请选择"
  54. style="width: 100%"
  55. disabled
  56. >
  57. <el-option
  58. v-for="item in supplierData"
  59. :label="item.name"
  60. :value="item.id"
  61. >
  62. </el-option>
  63. </el-select>
  64. </el-form-item>
  65. </el-col>
  66. </el-row>
  67. <el-row>
  68. <el-col :span="6">
  69. <el-form-item label="采购单号" prop="code">
  70. <el-input
  71. v-model="formData.data.code"
  72. placeholder="请输入"
  73. disabled
  74. >
  75. </el-input>
  76. </el-form-item>
  77. </el-col>
  78. </el-row>
  79. <div style="margin-bottom: 10px; font-size: 14px">到货明细</div>
  80. <el-form-item>
  81. <el-table :data="formData.data.qualityDetailList">
  82. <el-table-column
  83. prop="productType"
  84. label="货品类型"
  85. :formatter="(row) => (row.productType == 1 ? '产品' : '物料')"
  86. />
  87. <el-table-column prop="productCode" label="货品编码" />
  88. <el-table-column prop="productName" label="货品名称" />
  89. <el-table-column prop="productSpec" label="规格型号" />
  90. <el-table-column prop="productUnit" label="单位" />
  91. <el-table-column prop="count" label="到货数量" />
  92. <el-table-column prop="sumQualityCount" label="已质检" />
  93. <el-table-column
  94. prop="qualifiedCount"
  95. label="质检合格"
  96. min-width="150"
  97. >
  98. <template #default="{ row, $index }">
  99. <el-form-item
  100. :prop="'qualityDetailList.' + $index + '.qualifiedCount'"
  101. :rules="rules.qualifiedCount"
  102. :inline-message="true"
  103. >
  104. <el-input-number
  105. v-model="row.qualifiedCount"
  106. :precision="4"
  107. :controls="false"
  108. :min="0"
  109. />
  110. </el-form-item>
  111. </template>
  112. </el-table-column>
  113. <el-table-column
  114. prop="noQualifiedCount"
  115. label="质检不合格"
  116. min-width="150"
  117. >
  118. <template #default="{ row, $index }">
  119. <el-form-item
  120. :prop="'qualityDetailList.' + $index + '.noQualifiedCount'"
  121. :rules="rules.noQualifiedCount"
  122. :inline-message="true"
  123. >
  124. <el-input-number
  125. v-model="row.noQualifiedCount"
  126. :precision="4"
  127. :controls="false"
  128. :min="0"
  129. />
  130. </el-form-item>
  131. </template>
  132. </el-table-column>
  133. </el-table>
  134. </el-form-item>
  135. </el-form>
  136. <template #footer>
  137. <el-button @click="dialogVisible = false" size="large">取 消</el-button>
  138. <el-button
  139. type="primary"
  140. @click="submitForm()"
  141. size="large"
  142. :loading="submitLoading"
  143. >
  144. 确 定
  145. </el-button>
  146. </template>
  147. </el-dialog>
  148. </div>
  149. </template>
  150. <script setup>
  151. /* eslint-disable vue/no-unused-components */
  152. import { ElMessage, ElMessageBox } from "element-plus";
  153. import byTable from "@/components/byTable/index";
  154. import byForm from "@/components/byForm/index";
  155. import FileUpload from "@/components/FileUpload/index";
  156. import { computed, defineComponent, ref, watch } from "vue";
  157. import { getToken } from "@/utils/auth";
  158. const uploadFileUrl = ref(import.meta.env.VITE_APP_BASE_API + "/common/upload"); // 上传文件服务器地址
  159. const headers = ref({ Authorization: "Bearer " + getToken() });
  160. const uploadData = ref({});
  161. const loading = ref(false);
  162. const submitLoading = ref(false);
  163. const sourceList = ref({
  164. data: [],
  165. pagination: {
  166. total: 3,
  167. pageNum: 1,
  168. pageSize: 10,
  169. },
  170. });
  171. let dialogVisible = ref(false);
  172. let modalType = ref("add");
  173. let fileList = ref([]);
  174. let rules = ref({
  175. name: [{ required: true, message: "请输入供应商名称", trigger: "blur" }],
  176. qualifiedCount: [
  177. { required: true, message: "请输入质检合格数量", trigger: "blur" },
  178. ],
  179. noQualifiedCount: [
  180. { required: true, message: "请输入质检不合格数量", trigger: "blur" },
  181. ],
  182. });
  183. const { proxy } = getCurrentInstance();
  184. const selectConfig = reactive([
  185. {
  186. label: "质检状态",
  187. prop: "status",
  188. data: [
  189. {
  190. label: "未质检",
  191. value: "0",
  192. },
  193. {
  194. label: "部分质检",
  195. value: "10",
  196. },
  197. {
  198. label: "已质检",
  199. value: "20",
  200. },
  201. ],
  202. },
  203. ]);
  204. const config = computed(() => {
  205. return [
  206. {
  207. type: "selection",
  208. attrs: {
  209. checkAtt: "isCheck",
  210. },
  211. },
  212. {
  213. attrs: {
  214. label: "采购单号",
  215. prop: "code",
  216. },
  217. },
  218. {
  219. attrs: {
  220. label: "供应商",
  221. prop: "supplyName",
  222. },
  223. },
  224. {
  225. attrs: {
  226. label: "物流/快递公司",
  227. prop: "productType",
  228. },
  229. },
  230. {
  231. attrs: {
  232. label: "物流/快递单号",
  233. prop: "productCode",
  234. },
  235. },
  236. {
  237. attrs: {
  238. label: "采购员",
  239. prop: "productName",
  240. },
  241. },
  242. {
  243. attrs: {
  244. label: "采购时间",
  245. prop: "productSpec",
  246. },
  247. },
  248. {
  249. attrs: {
  250. label: "质检状态",
  251. prop: "productUnit",
  252. },
  253. },
  254. {
  255. attrs: {
  256. label: "操作",
  257. width: "100",
  258. align: "right",
  259. },
  260. // 渲染 el-button,一般用在最后一列。
  261. renderHTML(row) {
  262. return [
  263. row.status == 20
  264. ? {
  265. attrs: {
  266. label: "质检",
  267. type: "primary",
  268. text: true,
  269. },
  270. el: "button",
  271. click() {
  272. selectDataOne.value = [row];
  273. start(10);
  274. },
  275. }
  276. : {},
  277. ];
  278. },
  279. },
  280. ];
  281. });
  282. let formData = reactive({
  283. data: {},
  284. });
  285. const formOption = reactive({
  286. inline: true,
  287. labelWidth: 100,
  288. itemWidth: 100,
  289. rules: [],
  290. });
  291. const formConfig = computed(() => {});
  292. const formDom = ref(null);
  293. const getList = async (req) => {
  294. sourceList.value.pagination = { ...sourceList.value.pagination, ...req };
  295. loading.value = true;
  296. proxy
  297. .post("/arrivalDetail/page", sourceList.value.pagination)
  298. .then((message) => {
  299. message.rows.forEach((x) => {
  300. if (x.status < 20) {
  301. x.isCheck = true;
  302. } else {
  303. x.isCheck = false;
  304. }
  305. });
  306. sourceList.value.data = message.rows;
  307. sourceList.value.pagination.total = message.total;
  308. setTimeout(() => {
  309. loading.value = false;
  310. }, 200);
  311. });
  312. };
  313. const submitForm = () => {
  314. formDom.value.validate((valid) => {
  315. const list = formData.data.qualityDetailList;
  316. for (let i = 0; i < list.length; i++) {
  317. const e = list[i];
  318. if (!(e.qualifiedCount + e.noQualifiedCount > 0)) {
  319. return ElMessage({
  320. message: "质检数量不能为0!",
  321. type: "info",
  322. });
  323. }
  324. if (
  325. e.qualifiedCount + e.noQualifiedCount + Number(e.sumQualityCount) >
  326. Number(e.count)
  327. ) {
  328. return ElMessage({
  329. message: "质检数量不能大于到货数量!",
  330. type: "info",
  331. });
  332. }
  333. }
  334. submitLoading.value = true;
  335. proxy.post("/quality/" + modalType.value, formData.data).then(
  336. (res) => {
  337. ElMessage({
  338. message: "质检成功",
  339. type: "success",
  340. });
  341. dialogVisible.value = false;
  342. submitLoading.value = false;
  343. getList();
  344. },
  345. (err) => {
  346. submitLoading.value = false;
  347. }
  348. );
  349. });
  350. };
  351. const getDtl = (row) => {
  352. modalType.value = "edit";
  353. dialogVisible.value = true;
  354. // proxy.post("/productionProcesses/detail", { id: row.id }).then((res) => {
  355. // fileList.value = [
  356. // {
  357. // id: "",
  358. // fileName: res.fileName,
  359. // path: "",
  360. // },
  361. // ];
  362. // formData.data = res;
  363. // dialogVisible.value = true;
  364. // });
  365. };
  366. getList();
  367. const selectData = ref([]);
  368. const selectDataOne = ref([]);
  369. const selectRow = (data) => {
  370. selectData.value = data;
  371. };
  372. const start = (type) => {
  373. modalType.value = "add";
  374. let ids = [];
  375. let row = {};
  376. if (type === 10) {
  377. row = selectDataOne.value[0];
  378. ids = selectDataOne.value.map((x) => x.id);
  379. } else if (type === 20) {
  380. ids = selectData.value.map((x) => x.id);
  381. row = selectData.value[0];
  382. }
  383. proxy.post("/arrivalDetail/detail", { ids }).then((res) => {
  384. formData.data = {
  385. arrivalId: row.arrivalId,
  386. supplyId: row.supplyId,
  387. supplyName: row.supplyName,
  388. code: row.code,
  389. qualityDetailList: res.map((x) => ({
  390. ...x,
  391. arrivalDetailId: x.id,
  392. qualifiedCount: 0,
  393. noQualifiedCount: 0,
  394. })),
  395. };
  396. dialogVisible.value = true;
  397. });
  398. };
  399. watch(selectData, (newVal, oldVal) => {
  400. if (newVal.length == 0) {
  401. sourceList.value.data.forEach((x) => {
  402. if (x.status < 20) {
  403. x.isCheck = true;
  404. } else {
  405. x.isCheck = false;
  406. }
  407. });
  408. } else if (newVal.length == 1) {
  409. const current = newVal[0];
  410. sourceList.value.data.forEach((x) => {
  411. if (x.arrivalId !== current.arrivalId || x.status == 20) {
  412. x.isCheck = false;
  413. }
  414. });
  415. }
  416. });
  417. onMounted(() => {});
  418. </script>
  419. <style lang="scss" scoped>
  420. .tenant {
  421. padding: 20px;
  422. }
  423. .el-checkbox {
  424. display: none;
  425. }
  426. </style>