goodsLend.vue 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447
  1. <template>
  2. <div>
  3. <en-table-layout :tableData="tableData.data" :loading="loading" @selection-change="handleSelectionChange">
  4. <template #toolbar>
  5. <div class="inner-toolbar w-11/12 flex justify-between">
  6. <div class="toolbar-btns">
  7. <el-button size="mini" v-if="checkPermission(['goodsLend:add'])" type="primary" @click="handleAddGoodsLend">新增</el-button>
  8. <el-button
  9. type="success"
  10. size="mini"
  11. v-if="checkPermission(['goodsLend:confirm'])"
  12. @click="handleConfirmGoodsLend"
  13. :disabled="multipleSelection.length === 0"
  14. >打印</el-button
  15. >
  16. </div>
  17. <div class="toolbar-search">
  18. <en-table-search @search="searchEvent" @advancedSearch="advancedSearchEvent" placeholder="请输入仓库编号" advanced advancedWidth="465">
  19. <template #advanced-content>
  20. <el-form ref="advancedForm" :model="advancedForm" label-width="90px">
  21. <el-form-item label="仓库">
  22. <el-cascader
  23. v-model="advancedForm.dept_id"
  24. :options="warehouseList"
  25. :props="{
  26. label: 'name',
  27. value: 'id',
  28. emitPath: false,
  29. checkStrictly: true,
  30. }"
  31. clearable
  32. ></el-cascader>
  33. </el-form-item>
  34. <el-form-item label="状态">
  35. <el-select v-model="advancedForm.status" clearable>
  36. <el-option key="NEW" label="新创建" value="NEW" />
  37. <el-option key="CONFIRMED" label="已确认" value="CONFIRMED" />
  38. <el-option key="RETURNED" label="已归还" value="RETURNED" />
  39. </el-select>
  40. </el-form-item>
  41. <el-form-item label="时间">
  42. <el-date-picker
  43. v-model="advancedForm.goodsLend_time_range"
  44. type="daterange"
  45. align="center"
  46. :editable="false"
  47. unlink-panels
  48. :clearable="true"
  49. :default-time="['00:00:00', '23:59:59']"
  50. range-separator="-"
  51. start-placeholder="开始日期"
  52. end-placeholder="结束日期"
  53. value-format="timestamp"
  54. :picker-options="{
  55. disabledDate(time) {
  56. return time.getTime() - 1 >= new Date(new Date().getFullYear(), new Date().getMonth(), new Date().getDate()).getTime() + 86400000 - 1;
  57. },
  58. shortcuts: MixinPickerShortcuts,
  59. }"
  60. >
  61. </el-date-picker>
  62. </el-form-item>
  63. </el-form>
  64. </template>
  65. </en-table-search>
  66. </div>
  67. </div>
  68. </template>
  69. <template #table-columns>
  70. <el-table-column type="selection" width="55" />
  71. <el-table-column prop="warehouse.sn" label="仓库编号"></el-table-column>
  72. <el-table-column prop="warehouse.name" label="仓库名称"></el-table-column>
  73. <el-table-column prop="code" label="库位号" />
  74. <el-table-column prop="type" label="库位区域">
  75. <template #default="scope">{{ statusFilter(scope.row.type) }}</template>
  76. </el-table-column>
  77. <el-table-column prop="bind_num" label="已绑定SKU数" />
  78. <el-table-column label="操作" width="250">
  79. <template #default="scope">
  80. <!-- <el-button size="mini" v-if="checkPermission(['inventoryItem'])" @click="introGoodsLend(scope.row)">查看</el-button>
  81. <el-button size="mini" v-if="checkPermission(['bindAreaStock:update'])" @click="AddGoodsLend(scope.row)">绑定商品</el-button> -->
  82. <el-button size="mini" v-if="checkPermission(['goodsLend:edit'])" @click="handleEditGoodsLend(scope.row)">编辑</el-button>
  83. <el-button type="success" size="mini" style="margin-top: 5px" v-if="checkPermission(['goodsLend:del'])" @click="handleReturnGoodsLend(scope.row)"
  84. >删除</el-button
  85. >
  86. <el-button type="primary" size="mini" style="margin-top: 5px" @click="handlePrintGoodsLendDialog(scope.row)">打印</el-button>
  87. </template>
  88. </el-table-column>
  89. </template>
  90. <template #pagination>
  91. <el-pagination
  92. v-if="tableData"
  93. @size-change="handlePageSizeChange"
  94. @current-change="handlePageCurrentChange"
  95. :current-page="tableData.page_no"
  96. :page-sizes="[10, 20, 50, 100]"
  97. :page-size="tableData.page_size"
  98. layout="total, sizes, prev, pager, next, jumper"
  99. :total="tableData.data_total"
  100. >
  101. </el-pagination>
  102. </template>
  103. </en-table-layout>
  104. <el-dialog title="打印预览" v-model:visible="dialogVisible" width="940px" center @close="handleCancle">
  105. <el-button size="mini" type="primary" @click="handlePrintGoodsLend" class="print">打印</el-button>
  106. <div id="deliverySheet" style="width: 900px">
  107. <div class="tips-t" v-for="(item, index) in codeList" :key="index">
  108. <div>
  109. <barcode :value="item" height="20" format="CODE128" fontSize="20"></barcode>
  110. </div>
  111. </div>
  112. </div>
  113. </el-dialog>
  114. <el-dialog :title="title" v-model="dialogVisibleForm" width="940px" center @close="addHandleCancle" style="width: 30%; border-radius: 10px">
  115. <el-form :model="addLendForm" ref="addLendFormRef" :rules="rules" label-width="90px">
  116. <el-form-item label="仓库" prop="warehouse_id">
  117. <el-select v-model="addLendForm.warehouse_id" clearable @change="selWarehouse">
  118. <el-option v-for="item in warehouseList" :key="item.id" :label="item.name" :value="item.id" />
  119. </el-select>
  120. <span style="color: red; margin-left: 20px; cursor: pointer; text-decoration: underline" v-if="warehouseList.length == 0" @click="gowareHouse"
  121. >新增仓库</span
  122. >
  123. </el-form-item>
  124. <el-form-item label="库位区域" prop="type">
  125. <el-select v-model="addLendForm.type" clearable @change="selAreaTableData">
  126. <el-option v-for="item in AreaTableData" :key="item.id" :label="item.name" :value="item.code" />
  127. </el-select>
  128. </el-form-item>
  129. <el-form-item label="库位号" prop="code">
  130. <el-input v-model="addLendForm.code" maxlength="12" placeholder="请输入库位号" style="width: 270px">
  131. <template #prepend>{{ warehouseSn }}-{{ AreaTab }}</template>
  132. </el-input>
  133. </el-form-item>
  134. <el-form-item label="库位说明">
  135. <el-input type="textarea" :autosize="{ minRows: 2, maxRows: 4 }" placeholder="请输入内容" v-model="addLendForm.intro"> </el-input>
  136. </el-form-item>
  137. </el-form>
  138. <template #footer>
  139. <el-button @click="addHandleCancle">取 消</el-button>
  140. <el-button type="primary" @click="lendCommit">确 定</el-button>
  141. </template>
  142. </el-dialog>
  143. </div>
  144. </template>
  145. <script setup>
  146. import { ref, reactive, onMounted, watch } from 'vue';
  147. import * as API_GoodsLend from '@/api/goodsLend';
  148. import Print from 'print-js';
  149. import * as API_Setting from '@/api/setting';
  150. import { useRouter, useRoute } from 'vue-router';
  151. import QRCode from 'qrcode';
  152. /* import EnTableLayout from '@/components/TableLayout/index.vue';
  153. import EnTableSearch from '@/components/TableSearch/index.vue'; */
  154. import { ElMessageBox, ElMessage } from 'element-plus';
  155. import { useStore } from 'vuex';
  156. const store = useStore();
  157. const router = useRouter();
  158. const route = useRoute();
  159. const warehouseSn = ref('');
  160. const warehouseList = ref([]);
  161. const loading = ref(false);
  162. const params = reactive({
  163. page_no: 1,
  164. page_size: 10,
  165. company_id: store.state.companId,
  166. });
  167. const advancedForm = reactive({});
  168. const tableData = ref('');
  169. const dialogVisible = ref(false);
  170. const multipleSelection = ref([]);
  171. const goodsLendForm = reactive({});
  172. const codeList = ref([]);
  173. const title = ref('');
  174. const dialogVisibleForm = ref(false);
  175. const addLendForm = reactive({
  176. warehouse_id: '',
  177. type: '',
  178. code: '',
  179. intro: '',
  180. });
  181. const rules = reactive({
  182. warehouse_id: [{ required: true, message: '请选择仓库', trigger: 'change' }],
  183. name: [{ required: true, message: '请选择输入仓库名称', trigger: 'blur' }],
  184. code: [{ required: true, message: '请选择输入库位号', trigger: 'blur' }],
  185. type: [{ required: true, message: '请选择仓库类型', trigger: 'change' }],
  186. });
  187. const typeList = ref([]);
  188. const AreaTableData = ref([]);
  189. const AreaTab = ref('');
  190. const GET_GoodsLendList = () => {
  191. loading.value = true;
  192. API_GoodsLend.query(params)
  193. .then((response) => {
  194. loading.value = false;
  195. tableData.value = response;
  196. })
  197. .catch(() => {
  198. loading.value = false;
  199. });
  200. };
  201. onMounted(() => {
  202. GET_GoodsLendList();
  203. GET_DeptList();
  204. });
  205. watch(
  206. route,
  207. (newVal) => {
  208. if (newVal.query.status) {
  209. params.status = newVal.query.status;
  210. advancedForm.status = newVal.query.status;
  211. }
  212. params.page_no = 1;
  213. GET_GoodsLendList();
  214. },
  215. { immediate: true }
  216. );
  217. const introGoodsLend = (row) => {
  218. router.push({
  219. name: 'inventoryItem',
  220. params: { id: row.id, type: 'check', code: row.code },
  221. });
  222. };
  223. const AddGoodsLend = (row) => {
  224. router.push({
  225. name: 'bindAreaStock',
  226. params: { id: row.id, warehouse_id: row.warehouse_id, code: row.code },
  227. });
  228. };
  229. const gowareHouse = () => {
  230. dialogVisibleForm.value = false;
  231. router.push({ name: 'warehouseList' });
  232. };
  233. const selWarehouse = (val) => {
  234. const list = warehouseList.value.filter((el) => el.id === val);
  235. let obj = list[0];
  236. warehouseSn.value = obj.sn;
  237. };
  238. const selAreaTableData = (val) => {
  239. const list = AreaTableData.value.filter((el) => el.code === val);
  240. let obj = list[0];
  241. AreaTab.value = obj.code;
  242. };
  243. const lendCommit = () => {
  244. console.log(addLendForm);
  245. addLendForm.code = warehouseSn.value +'-'+ addLendForm.type + '-' + addLendForm.code;
  246. if (title.value === '新增') {
  247. API_GoodsLend.create(addLendForm).then(() => {
  248. ElMessage.success('添加成功!');
  249. dialogVisibleForm.value = false;
  250. warehouseSn.value = '';
  251. addLendForm.value = {};
  252. GET_GoodsLendList();
  253. });
  254. } else if (title.value === '编辑') {
  255. API_GoodsLend.update(addLendForm).then(() => {
  256. ElMessage.success('修改成功!');
  257. dialogVisibleForm.value = false;
  258. addLendForm.value = {};
  259. GET_GoodsLendList();
  260. });
  261. }
  262. };
  263. const addHandleCancle = () => {
  264. dialogVisibleForm.value = false;
  265. };
  266. const handleCancle = () => {
  267. dialogVisible.value = false;
  268. codeList.value = [];
  269. };
  270. const creatQrCode = () => {
  271. nextTick(() => {
  272. codeList.value.forEach((item, index) => {
  273. document.getElementById(`codeItem${index}`).innerHTML = '';
  274. new QRCode(document.getElementById(`codeItem${index}`), {
  275. text: item,
  276. width: 600,
  277. height: 660,
  278. render: 'table',
  279. colorDark: '#333333',
  280. colorLight: '#ffffff',
  281. correctLevel: QRCode.CorrectLevel.H,
  282. });
  283. });
  284. });
  285. };
  286. const handleEditGoodsLend = (row) => {
  287. title.value = '编辑';
  288. const str = row.code;
  289. warehouseSn.value = str.split('-')[0];
  290. AreaTab.value = str.split('-')[1];
  291. // 使用 Object.assign 或者手动赋值来更新 reactive 对象的属性
  292. Object.assign(addLendForm, row);
  293. console.log(warehouseSn.value,AreaTab.value);
  294. addLendForm.code = str.split('-').pop();
  295. dialogVisibleForm.value = true;
  296. };
  297. const handleReturnGoodsLend = (row) => {
  298. ElMessageBox.confirm('确定要删除吗?', '提示', { type: 'warning' })
  299. .then(() => {
  300. API_GoodsLend.deletes({ id: row.id }).then(() => {
  301. ElMessage.success('删除成功!');
  302. GET_GoodsLendList();
  303. });
  304. })
  305. .catch(() => {});
  306. };
  307. const statusFilter = (val) => {
  308. const obj = AreaTableData.value.filter((el) => el.code === val);
  309. return obj.length !== 0 ? obj[0].name : '';
  310. };
  311. const handleConfirmGoodsLend = () => {
  312. if (!multipleSelection.value.length) return ElMessage.error('请先选择!');
  313. const ids = multipleSelection.value.map((item) => item.code);
  314. codeList.value = ids;
  315. dialogVisible.value = true;
  316. creatQrCode();
  317. };
  318. const GET_DeptList = () => {
  319. API_Setting.getListAll().then((response) => {
  320. warehouseList.value = response;
  321. });
  322. API_Setting.getPage({
  323. dictType: 'Warehouse_location_type',
  324. page_no: 1,
  325. page_size: 1,
  326. page_size: 50,
  327. }).then((res) => {
  328. typeList.value = res.data;
  329. });
  330. API_GoodsLend.getListAreaType({ page_no: 1,
  331. page_size: 100,
  332. company_id: store.state.companId,})
  333. .then((response) => {
  334. loading.value = false;
  335. AreaTableData.value = response;
  336. })
  337. .catch(() => {
  338. loading.value = false;
  339. });
  340. };
  341. const handlePrintGoodsLend = () => {
  342. Print({
  343. printable: 'deliverySheet',
  344. type: 'html',
  345. targetStyles: ['*'],
  346. ignoreElements: ['no-logs', 'goods-image', 'no-btn', 'elementToIgnore'],
  347. });
  348. };
  349. const handleDeleteGoodsLend = () => {
  350. if (!multipleSelection.value.length) return ElMessage.error('请先选择!');
  351. ElMessageBox.confirm('确定要删除这些借出单吗?', '提示', { type: 'warning' })
  352. .then(() => {
  353. const ids = multipleSelection.value.map((item) => item.id);
  354. API_GoodsLend.deleteGoodsLend(ids).then(() => {
  355. ElMessage.success('删除成功!');
  356. GET_GoodsLendList();
  357. });
  358. })
  359. .catch(() => {});
  360. };
  361. const handleSelectionChange = (val) => {
  362. multipleSelection.value = val;
  363. };
  364. const handlePageSizeChange = (size) => {
  365. params.page_size = size;
  366. GET_GoodsLendList();
  367. };
  368. const handlePageCurrentChange = (page) => {
  369. params.page_no = page;
  370. GET_GoodsLendList();
  371. };
  372. const handleAddGoodsLend = () => {
  373. title.value = '新增';
  374. dialogVisibleForm.value = true;
  375. };
  376. const handlePrintGoodsLendDialog = (row) => {
  377. dialogVisible.value = true;
  378. codeList.value.push(row.code);
  379. creatQrCode();
  380. };
  381. const GET_GoodsLendDetail = (id) => {
  382. API_GoodsLend.getGoodsLendInfo(id).then((response) => {
  383. goodsLendForm.value = response;
  384. if (response.product_list && response.product_list.length) {
  385. var str = '';
  386. response.product_list.forEach(function (i) {
  387. str += i.product_name + '、';
  388. });
  389. }
  390. goodsLendForm.value.illustrate = str;
  391. });
  392. };
  393. const searchEvent = (data) => {
  394. params.sn = data;
  395. Object.keys(advancedForm).forEach((key) => delete params[key]);
  396. params.page_no = 1;
  397. GET_GoodsLendList();
  398. };
  399. const advancedSearchEvent = () => {
  400. Object.assign(params, advancedForm);
  401. delete params.start_time;
  402. delete params.end_time;
  403. if (advancedForm.goodsLend_time_range) {
  404. params.start_time = parseInt(Number(advancedForm.goodsLend_time_range[0]) / 1000);
  405. params.end_time = parseInt(Number(advancedForm.goodsLend_time_range[1]) / 1000);
  406. }
  407. delete params.goodsLend_time_range;
  408. params.page_no = 1;
  409. GET_GoodsLendList();
  410. };
  411. </script>