index.vue 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527
  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: select,
  15. }"
  16. :action-list="[
  17. {
  18. text: '发起盘点',
  19. action: () => openModal('add'),
  20. },
  21. ]"
  22. @get-list="getList"
  23. >
  24. <template #code="{ item }">
  25. <div
  26. style="cursor: pointer; color: #409eff"
  27. @click="handleClickCode(item)"
  28. >
  29. {{ item.code }}
  30. </div>
  31. </template>
  32. </byTable>
  33. </div>
  34. <el-dialog
  35. :title="modalType == 'add' ? '发起盘点' : '盘点详情'"
  36. v-model="dialogVisible"
  37. width="800"
  38. v-loading="loading"
  39. destroy-on-close
  40. >
  41. <byForm
  42. :formConfig="formConfig"
  43. :formOption="formOption"
  44. v-model="formData.data"
  45. :rules="rules"
  46. ref="byform"
  47. >
  48. <template #products>
  49. <div style="width: 100%">
  50. <el-button
  51. type="primary"
  52. @click="openProduct = true"
  53. style="margin-bottom: 10px"
  54. v-if="modalType == 'add'"
  55. :disabled="!formData.data.warehouseId"
  56. >
  57. 添加物品
  58. </el-button>
  59. <el-table :data="formData.data.list" :row-class-name="changeClass">
  60. <el-table-column prop="productCode" label="物品编码" />
  61. <el-table-column prop="productName" label="物品名称" />
  62. <el-table-column prop="productUnit" label="单位" />
  63. <el-table-column prop="quantity" label="库存数量" />
  64. <el-table-column
  65. prop="checkQuantity"
  66. label="盘点数量"
  67. min-width="150"
  68. >
  69. <template #default="{ row, $index }">
  70. <el-form-item
  71. :prop="'list.' + $index + '.checkQuantity'"
  72. :rules="rules.checkQuantity"
  73. :inline-message="true"
  74. >
  75. <el-input-number
  76. v-model="row.checkQuantity"
  77. :precision="4"
  78. :controls="false"
  79. :min="0"
  80. @change="() => handleChange($index)"
  81. />
  82. </el-form-item>
  83. </template>
  84. </el-table-column>
  85. <el-table-column prop="result" label="盘点结果" />
  86. <el-table-column
  87. prop="zip"
  88. label="操作"
  89. width="100"
  90. v-if="modalType == 'add'"
  91. >
  92. <template #default="{ $index }">
  93. <el-button type="primary" link @click="handleRemove($index)"
  94. >删除</el-button
  95. >
  96. </template>
  97. </el-table-column>
  98. </el-table>
  99. </div>
  100. </template>
  101. </byForm>
  102. <template #footer v-if="modalType == 'add'">
  103. <el-button @click="dialogVisible = false" size="large">取 消</el-button>
  104. <el-button
  105. type="primary"
  106. @click="submitForm('byform')"
  107. size="large"
  108. :loading="submitLoading"
  109. >
  110. 确 定
  111. </el-button>
  112. </template>
  113. </el-dialog>
  114. <el-dialog
  115. v-model="openProduct"
  116. title="选择物品"
  117. width="70%"
  118. append-to-body
  119. >
  120. <SelectGoods
  121. @cancel="openProduct = false"
  122. @pushGoods="pushGoods"
  123. ></SelectGoods>
  124. </el-dialog>
  125. </div>
  126. </template>
  127. <script setup>
  128. /* eslint-disable vue/no-unused-components */
  129. import { ElMessage, ElMessageBox } from "element-plus";
  130. import byTable from "@/components/byTable/index";
  131. import byForm from "@/components/byForm/index";
  132. import { computed, defineComponent, ref } from "vue";
  133. import useUserStore from "@/store/modules/user";
  134. import SelectGoods from "@/components/product/SelectGoods";
  135. const loading = ref(false);
  136. const submitLoading = ref(false);
  137. const sourceList = ref({
  138. data: [],
  139. pagination: {
  140. total: 3,
  141. pageNum: 1,
  142. pageSize: 10,
  143. },
  144. });
  145. let dialogVisible = ref(false);
  146. let openProduct = ref(false);
  147. let roomDialogVisible = ref(false);
  148. let modalType = ref("add");
  149. let rules = ref({
  150. checkQuantity: [
  151. { required: true, message: "请输入盘点数量", trigger: "blur" },
  152. ],
  153. warehouseId: [
  154. { required: true, message: "请选择盘点仓库", trigger: "change" },
  155. ],
  156. });
  157. const { proxy } = getCurrentInstance();
  158. const selectConfig = reactive([
  159. {
  160. label: "盘点结论",
  161. prop: "result",
  162. data: [
  163. {
  164. label: "正常",
  165. value: "0",
  166. },
  167. {
  168. label: "异常",
  169. value: "1",
  170. },
  171. ],
  172. },
  173. ]);
  174. const config = computed(() => {
  175. return [
  176. {
  177. attrs: {
  178. label: "盘点单号",
  179. prop: "code",
  180. slot: "code",
  181. },
  182. },
  183. {
  184. attrs: {
  185. label: "仓库名称",
  186. prop: "warehouseName",
  187. },
  188. },
  189. {
  190. attrs: {
  191. label: "盘点时间",
  192. prop: "createTime",
  193. },
  194. },
  195. {
  196. attrs: {
  197. label: "盘点人",
  198. prop: "userName",
  199. },
  200. },
  201. {
  202. attrs: {
  203. label: "盘点结论",
  204. prop: "result",
  205. },
  206. render(result) {
  207. return result == 0 ? "正常" : "异常";
  208. },
  209. },
  210. {
  211. attrs: {
  212. label: "盘点物品数",
  213. prop: "totalNum",
  214. },
  215. },
  216. {
  217. attrs: {
  218. label: "正常物品数",
  219. prop: "normalNum",
  220. },
  221. },
  222. {
  223. attrs: {
  224. label: "异常物品数",
  225. prop: "anomalyNum",
  226. },
  227. },
  228. // {
  229. // attrs: {
  230. // label: "操作",
  231. // width: "200",
  232. // align: "right",
  233. // },
  234. // // 渲染 el-button,一般用在最后一列。
  235. // renderHTML(row) {
  236. // return [
  237. // {
  238. // attrs: {
  239. // label: "接收",
  240. // type: "primary",
  241. // text: true,
  242. // },
  243. // el: "button",
  244. // click() {
  245. // getDtl(row);
  246. // },
  247. // },
  248. // {
  249. // attrs: {
  250. // label: "打印",
  251. // type: "primary",
  252. // text: true,
  253. // },
  254. // el: "button",
  255. // click() {
  256. // getDtl(row);
  257. // },
  258. // },
  259. // ];
  260. // },
  261. // },
  262. ];
  263. });
  264. let formData = reactive({
  265. data: {},
  266. treeData: [],
  267. });
  268. const formOption = reactive({
  269. inline: true,
  270. labelWidth: 100,
  271. itemWidth: 100,
  272. rules: [],
  273. });
  274. const byform = ref(null);
  275. const treeData = ref([]);
  276. const formConfig = reactive([
  277. {
  278. type: "select",
  279. prop: "warehouseId",
  280. label: "仓库名称",
  281. itemWidth: 33,
  282. isLoad: {
  283. url: "/warehouse/page",
  284. req: {
  285. pageNum: 1,
  286. pageSize: 9999,
  287. },
  288. labelKey: "name",
  289. labelVal: "id",
  290. method: "post",
  291. resUrl: "rows",
  292. },
  293. },
  294. {
  295. type: "title",
  296. title: "盘点明细",
  297. },
  298. {
  299. type: "slot",
  300. slotName: "products",
  301. label: "",
  302. },
  303. ]);
  304. const getList = async (req) => {
  305. sourceList.value.pagination = { ...sourceList.value.pagination, ...req };
  306. loading.value = true;
  307. proxy
  308. .post("/stockCheck/page", sourceList.value.pagination)
  309. .then((message) => {
  310. console.log(message);
  311. sourceList.value.data = message.rows;
  312. sourceList.value.pagination.total = message.total;
  313. setTimeout(() => {
  314. loading.value = false;
  315. }, 200);
  316. });
  317. };
  318. const openModal = () => {
  319. dialogVisible.value = true;
  320. modalType.value = "add";
  321. formConfig[0].disabled = false;
  322. formData.data = {
  323. list: [],
  324. };
  325. };
  326. const submitForm = () => {
  327. console.log(byform.value);
  328. byform.value.handleSubmit((valid) => {
  329. // const list = formData.data.list;
  330. // for (let i = 0; i < list.length; i++) {
  331. // const e = list[i];
  332. // if (e.groupNum > e.canSum) {
  333. // return ElMessage({
  334. // message: "组合数量不可大于可组合数量!",
  335. // type: "info",
  336. // });
  337. // }
  338. // }
  339. submitLoading.value = true;
  340. proxy.post("/stockCheck/" + modalType.value, formData.data).then(
  341. (res) => {
  342. ElMessage({
  343. message: modalType.value == "add" ? "添加成功" : "编辑成功",
  344. type: "success",
  345. });
  346. dialogVisible.value = false;
  347. submitLoading.value = false;
  348. getList();
  349. },
  350. (err) => (submitLoading.value = false)
  351. );
  352. });
  353. };
  354. const getDtl = (row) => {
  355. modalType.value = "edit";
  356. proxy.post("/productSpu/detail", { id: row.id }).then((res) => {
  357. res.list = res.productInfoList;
  358. formData.data = res;
  359. dialogVisible.value = true;
  360. });
  361. };
  362. getList();
  363. const handleSelect = (row) => {
  364. const flag = formData.data.list.some((x) => x.id === row.id);
  365. if (flag)
  366. return ElMessage({
  367. message: "该物品已选择",
  368. type: "info",
  369. });
  370. formData.data.list.push({
  371. name: row.name,
  372. code: row.code,
  373. id: row.id,
  374. });
  375. return ElMessage({
  376. message: "选择成功",
  377. type: "success",
  378. });
  379. };
  380. const pushGoods = (goods) => {
  381. const arr = goods.map((x) => ({
  382. productId: x.id,
  383. quantity: "",
  384. checkQuantity: "",
  385. productName: x.name,
  386. productCode: x.code,
  387. productUnit: x.unit,
  388. }));
  389. const ids = arr.map((x) => x.productId);
  390. if (formData.data.warehouseId) {
  391. proxy
  392. .post("/stock/pageByWarehouse", {
  393. id: formData.data.warehouseId,
  394. productIds: ids,
  395. })
  396. .then((res) => {
  397. const productList = res.rows;
  398. for (let i = 0; i < productList.length; i++) {
  399. const e = productList[i];
  400. for (let j = 0; j < arr.length; j++) {
  401. const jele = arr[j];
  402. if (e.productId === jele.productId) {
  403. formData.data.list.push({ ...jele, quantity: e.quantity });
  404. }
  405. }
  406. }
  407. });
  408. }
  409. return ElMessage({
  410. message: "添加成功,已为你自动过滤库存数量为0的数据 !",
  411. type: "success",
  412. });
  413. };
  414. const handleRemove = (index) => {
  415. formData.data.list.splice(index, 1);
  416. return ElMessage({
  417. message: "删除成功",
  418. type: "success",
  419. });
  420. };
  421. // watchEffect(() => {
  422. // const list = formData.data.list;
  423. // if (
  424. // formData.data.warehouseId &&
  425. // list.length > 0 &&
  426. // modalType.value == "add"
  427. // ) {
  428. // proxy
  429. // .post("/stock/pageByWarehouse", {
  430. // id: formData.data.warehouseId,
  431. // productIds: list.map((x) => x.productId),
  432. // })
  433. // .then((res) => {
  434. // const productList = res.rows;
  435. // for (let i = 0; i < list.length; i++) {
  436. // const e = list[i];
  437. // e.quantity = 0;
  438. // for (let j = 0; j < productList.length; j++) {
  439. // if (e.productId == x.productId) {
  440. // e.quantity = x.quantity;
  441. // }
  442. // }
  443. // }
  444. // handleChange();
  445. // });
  446. // }
  447. // });
  448. const handleChange = (index) => {
  449. if (!formData.data.list[index].quantity) return;
  450. if (
  451. formData.data.list[index].quantity > formData.data.list[index].checkQuantity
  452. ) {
  453. formData.data.list[index].result = "盘亏";
  454. }
  455. if (
  456. formData.data.list[index].quantity ==
  457. formData.data.list[index].checkQuantity
  458. ) {
  459. formData.data.list[index].result = "正常";
  460. }
  461. if (
  462. formData.data.list[index].quantity < formData.data.list[index].checkQuantity
  463. ) {
  464. formData.data.list[index].result = "盘盈";
  465. }
  466. };
  467. const changeClass = ({ row }) => {
  468. if (row.result == "盘亏") {
  469. return "redClass";
  470. } else if (row.result == "盘盈") {
  471. return "greenClass";
  472. }
  473. };
  474. const handleClickCode = (row) => {
  475. modalType.value = "edit";
  476. proxy.post("/stockCheck/detail", { id: row.id }).then((res) => {
  477. formConfig[0].disabled = true;
  478. res.list.forEach((x) => {
  479. if (Number(x.checkQuantity) > Number(x.quantity)) {
  480. x.result = "盘盈";
  481. }
  482. if (Number(x.checkQuantity) < Number(x.quantity)) {
  483. x.result = "盘亏";
  484. }
  485. if (Number(x.checkQuantity) == Number(x.quantity)) {
  486. x.result = "正常";
  487. }
  488. });
  489. formData.data = {
  490. warehouseId: row.warehouseId,
  491. list: res.list,
  492. };
  493. dialogVisible.value = true;
  494. });
  495. };
  496. </script>
  497. <style lang="scss" scoped>
  498. .tenant {
  499. padding: 20px;
  500. }
  501. </style>
  502. <style >
  503. .redClass {
  504. color: #f54a45 !important;
  505. }
  506. .greenClass {
  507. color: #39c55a !important;
  508. }
  509. </style>