index.vue 20 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729
  1. <!-- 物料信息基础档案 -->
  2. <script src="../../../main.js"></script>
  3. <template>
  4. <div class="material-basic" v-loading="failLoad">
  5. <!-- 主体列表 -->
  6. <el-card
  7. class="material-list"
  8. v-loading="loading"
  9. :body-style="{
  10. height: '100%',
  11. padding: '10px ',
  12. display: 'flex',
  13. 'flex-direction': 'column',
  14. }"
  15. >
  16. <!-- 查询条件 -->
  17. <el-super-search
  18. v-model="params"
  19. :size="size"
  20. :dict="dict"
  21. :columns="SearchColumns"
  22. @reset="handleResetQuery"
  23. @submit="handleQuery"
  24. ></el-super-search>
  25. <!-- 操作栏 -->
  26. <el-row
  27. :gutter="10"
  28. class="mb10"
  29. type="flex"
  30. justify="end"
  31. style="margin: 10px 0"
  32. >
  33. <!-- 新增、修改、删除、复制 -->
  34. <el-col :span="1.5">
  35. <el-button-group>
  36. <el-button :size="size" @click="handleEdit">修改</el-button>
  37. <el-button :size="size" @click="handleRefresh">刷新</el-button>
  38. </el-button-group>
  39. </el-col>
  40. <!-- 启用 -->
  41. <el-col :span="1.5">
  42. <is-using
  43. :size="size"
  44. :select-data="checkedList"
  45. @success="handleQuery"
  46. ></is-using>
  47. </el-col>
  48. <!-- 导入导出 -->
  49. <el-col :span="1.5">
  50. <el-button-group>
  51. <el-button
  52. :size="size"
  53. @click="handleImport"
  54. v-hasPermi="['system:material:import']"
  55. >批量导入</el-button
  56. >
  57. <el-button
  58. :size="size"
  59. @click="handleExport"
  60. v-hasPermi="['system:material:export']"
  61. >批量导出</el-button
  62. >
  63. </el-button-group>
  64. </el-col>
  65. </el-row>
  66. <div
  67. class="el-super-ux-table"
  68. v-resize="resize"
  69. style="
  70. position: relative;
  71. display: flex;
  72. flex: 1;
  73. flex-direction: column;
  74. overflow: auto;
  75. "
  76. >
  77. <ux-grid
  78. v-if="tableHeader.length"
  79. border
  80. use-virtual
  81. keep-source
  82. beautify-table
  83. :size="size"
  84. :data="taskList"
  85. :height="tableHeight"
  86. ref="materialTable"
  87. @cell-dblclick="handledbClick"
  88. @select="handleSelect"
  89. @select-all="handleSelectAll"
  90. :header-row-style="{
  91. color: '#515a6e',
  92. }"
  93. style="flex: 1"
  94. >
  95. <
  96. <!-- 多选 -->
  97. <ux-table-column
  98. fixed="left"
  99. width="60"
  100. align="center"
  101. type="checkbox"
  102. resizable
  103. reserve-selection
  104. :column-key="rowKey"
  105. ></ux-table-column>
  106. <!-- 序号 -->
  107. <ux-table-column
  108. fixed="left"
  109. width="50"
  110. title="序号"
  111. type="index"
  112. align="center"
  113. class="is-index"
  114. resizable
  115. ></ux-table-column>
  116. <!-- <ux-table-column type="selection" width="45" :reserve-selection="true" fixed/>
  117. <ux-table-column type="index" title="序号" width="55" align="center"/> -->
  118. <ux-table-column
  119. width="150"
  120. v-for="h in tableHeader"
  121. v-if="h.show"
  122. :title="h.name"
  123. align="center"
  124. resizable
  125. show-overflow-tooltip
  126. >
  127. <template slot-scope="scope">
  128. <span v-if="h.apiUrl">{{ scope.row[`${h.prop}Name`] }}</span>
  129. <el-checkbox
  130. v-else-if="h.attribute == 'checkbox'"
  131. v-model="scope.row[h.prop]"
  132. disabled
  133. true-label="0"
  134. false-label="2"
  135. ></el-checkbox>
  136. <el-dict-tag
  137. v-else-if="h.dictId"
  138. :value="scope.row[h.prop]"
  139. :options="dict.type[h.dictId]"
  140. ></el-dict-tag>
  141. <span v-else>{{ scope.row[h.prop] || "--" }}</span>
  142. <!-- {{ h.attribute == 'select' ? scope.row[`${h.prop}Name`] :
  143. (h.attribute == 'checkbox' ?
  144. (scope.row[h.prop] == '0' ? '√' : '')
  145. : scope.row[h.prop])
  146. }} -->
  147. </template>
  148. </ux-table-column>
  149. </ux-grid>
  150. <div
  151. style="
  152. height: 50px;
  153. display: flex;
  154. justify-content: space-between;
  155. align-items: center;
  156. "
  157. :style="{
  158. height: '50px',
  159. }"
  160. >
  161. <pagination
  162. :total="total"
  163. :page.sync="queryParams.pageNum"
  164. :limit.sync="queryParams.pageSize"
  165. @pagination="handleQuery"
  166. style="
  167. height: 32px;
  168. padding: 0 !important;
  169. flex: 1;
  170. overflow-x: auto;
  171. "
  172. />
  173. </div>
  174. </div>
  175. </el-card>
  176. <!-- 操作提示 -->
  177. <el-dialog
  178. title="操作提示"
  179. :visible.sync="optionDialog.show"
  180. width="30%"
  181. center
  182. >
  183. <span>是否确认{{ optionDialog.op }}?</span>
  184. <span slot="footer">
  185. <el-button @click="handleOptionShow('option', false)">取 消</el-button>
  186. <el-button type="primary" @click="handleComfirmOption('cancal')"
  187. >确 定</el-button
  188. >
  189. </span>
  190. </el-dialog>
  191. <!-- 导入弹窗 -->
  192. <el-dialog
  193. title="批量导入"
  194. :visible.sync="importData.show"
  195. width="35%"
  196. center
  197. :before-close="handlefileDialogColse"
  198. >
  199. <div class="mb-import">
  200. <el-upload
  201. class="upload-demo"
  202. accept=".xls, .xlsx"
  203. ref="upload"
  204. action="#"
  205. :on-remove="handleFileRemove"
  206. :file-list="importData.list"
  207. :auto-upload="false"
  208. :on-change="handleChangeFile"
  209. :limit="1"
  210. >
  211. <el-button slot="trigger" :size="size" type="primary"
  212. >选取文件</el-button
  213. >
  214. <el-button
  215. style="margin-left: 10px"
  216. :size="size"
  217. type="success"
  218. @click="handleDownTemplate"
  219. >下载模板</el-button
  220. >
  221. <div slot="tip" class="el-upload__tip">只能上传Excel文件</div>
  222. </el-upload>
  223. </div>
  224. <span slot="footer">
  225. <el-button @click="handleImportData('cancal')">取 消</el-button>
  226. <el-button type="primary" @click="handleImportData('confirm')"
  227. >确 定</el-button
  228. >
  229. </span>
  230. </el-dialog>
  231. </div>
  232. </template>
  233. <script>
  234. import "./style/index.scss";
  235. import materialApi from "@/api/material/basic";
  236. import { SearchColumns, OtherDictColumns } from "./columns";
  237. import { initDicts } from "@/utils/init.js";
  238. export default {
  239. name: "material-basic",
  240. dicts: [...initDicts([...SearchColumns, ...OtherDictColumns])],
  241. components: {
  242. ElSuperSearch: () => import("@/components/super-search/index.vue"),
  243. ElDictTag: () => import("@/components/DictTag/index.vue"),
  244. IsUsing: () => import("./isUsing/index.vue"),
  245. },
  246. data() {
  247. const params = this.$init.params(SearchColumns);
  248. return {
  249. failLoad: false,
  250. params: params,
  251. SearchColumns: SearchColumns,
  252. rowKey: "id",
  253. size: "mini",
  254. // 物料基本信息数据
  255. taskList: [],
  256. // 查询表单字段
  257. queryForm: {
  258. name: "",
  259. code: "",
  260. isEnable: "",
  261. },
  262. // 总条数
  263. total: 1,
  264. loading: false,
  265. importData: {
  266. show: false,
  267. list: [],
  268. },
  269. // 查询参数
  270. queryParams: {
  271. pageNum: 1,
  272. pageSize: 50,
  273. code: null,
  274. name: null,
  275. },
  276. // 表头
  277. tableHeader: [],
  278. // 多选数组
  279. checkedList: [],
  280. // 列表选中数据
  281. // checkedList: [],
  282. // 操作弹窗
  283. optionDialog: {
  284. show: false,
  285. op: "",
  286. },
  287. resizeHeight: 0,
  288. };
  289. },
  290. computed: {
  291. tableHeight: {
  292. get() {
  293. return this.resizeHeight;
  294. },
  295. set() {},
  296. },
  297. },
  298. directives: {
  299. // 使用局部注册指令的方式
  300. resize: {
  301. // 指令的名称
  302. bind(el, binding) {
  303. // el为绑定的元素,binding为绑定给指令的对象
  304. let width = "",
  305. height = "";
  306. function isReize() {
  307. const style = document.defaultView.getComputedStyle(el);
  308. if (width !== style.width || height !== style.height) {
  309. binding.value(); // 关键
  310. }
  311. width = style.width;
  312. height = style.height;
  313. }
  314. el.__vueSetInterval__ = setInterval(isReize, 300);
  315. },
  316. unbind(el) {
  317. clearInterval(el.__vueSetInterval__);
  318. },
  319. },
  320. },
  321. methods: {
  322. resize() {
  323. this.resizeHeight =
  324. document.getElementsByClassName("el-super-ux-table")[0].offsetHeight -
  325. 55;
  326. },
  327. // 判读是否启用
  328. handleJudgeIsUsing() {
  329. return (
  330. this.checkedList.length == 1 && this.checkedList[0].isEnable == "已启用"
  331. );
  332. },
  333. // 修改
  334. handleEdit() {
  335. if (this.checkedList.length == 1) {
  336. this.$router.push({
  337. path: `/material/basicFile/detail/${this.checkedList[0].id}`,
  338. query: {
  339. isEdit: true,
  340. },
  341. });
  342. } else {
  343. this.$notify.warning({
  344. message: `${
  345. this.checkedList.length > 1
  346. ? "修改只能选择单个数据!"
  347. : "请选择需要修改的信息!"
  348. }`,
  349. });
  350. }
  351. },
  352. // 删除
  353. handleDel() {
  354. console.log("删除", this.checkedList);
  355. // delMaterial
  356. if (this.checkedList.length) {
  357. let ids = this.checkedList.map((i) => i.id);
  358. materialApi.delMaterial(ids).then((res) => {
  359. if (res.code == 200) {
  360. this.handleRefresh();
  361. // 清空选中数据
  362. this.checkedList = [];
  363. this.$refs.materialTable.clearSelection();
  364. }
  365. });
  366. } else {
  367. this.$notify.warning({
  368. message: `请选择需要删除的数据!`,
  369. });
  370. }
  371. },
  372. //查询
  373. handleQuery() {
  374. // 重新查询后需要清空列表选中的数据
  375. this.checkedList = [];
  376. this.$refs.materialTable.clearSelection();
  377. this.getMaterialList();
  378. },
  379. // 重置查询条件
  380. handleResetQuery() {
  381. this.queryParams.pageNum = 1;
  382. this.queryParams.pageSize = 100;
  383. this.params = this.$init.params(SearchColumns);
  384. this.handleQuery();
  385. },
  386. // 刷新
  387. handleRefresh() {
  388. this.getMaterialList();
  389. // for (const key in this.queryForm) {
  390. // this.queryForm[key] = '';
  391. // }
  392. },
  393. // 批量导入
  394. handleImport() {
  395. this.importData.show = true;
  396. },
  397. // 导入弹窗关闭前
  398. handlefileDialogColse(done) {
  399. this.importData.list = [];
  400. done();
  401. },
  402. // 导入弹窗操作
  403. handleImportData(type) {
  404. switch (type) {
  405. // 取消
  406. case "cancal":
  407. this.importData.list = [];
  408. this.importData.show = false;
  409. break;
  410. // 确认
  411. case "confirm":
  412. if (this.importData.list.length) {
  413. let formData = new FormData();
  414. formData.append("file", this.importData.list[0].raw);
  415. materialApi.fileImport(formData).then((res) => {
  416. if (res.code == 200) {
  417. this.importData.show = false;
  418. this.importData.list = [];
  419. if (res.data.flag) {
  420. this.failLoad = true;
  421. console.log(res.data.datas);
  422. let param = { failDatas: res.data.datas };
  423. if (null != param) {
  424. materialApi.exportMartial(param).then((res) => {
  425. const blob = new Blob([res], {
  426. type: "application/vnd.ms-excel;charset=UTF-8",
  427. }); // 创建一个类文件对象:Blob对象表示一个不可变的、原始数据的类文件对象
  428. const downloadElement = document.createElement("a"); //创建a标签
  429. const href = window.URL.createObjectURL(blob); // 创建下载的链接
  430. downloadElement.href = href; //下载地址
  431. downloadElement.download =
  432. "导入失败的物料基础档案数据.xlsx"; // 下载后文件名
  433. document.body.appendChild(downloadElement);
  434. downloadElement.click(); // 点击下载
  435. document.body.removeChild(downloadElement); // 下载完成移除元素
  436. window.URL.revokeObjectURL(href); // 释放blob对象
  437. this.failLoad = false;
  438. });
  439. }
  440. }
  441. this.$notify({
  442. message: res.data.msg,
  443. type: res.data.flag ? "warning" : "success",
  444. });
  445. } else {
  446. this.$notify({
  447. message: res.msg,
  448. type: res.code == 200 ? "success" : "warning",
  449. });
  450. }
  451. });
  452. } else {
  453. this.$notify({
  454. title: "警告",
  455. message: "请上传文件之后在确认!",
  456. type: "warning",
  457. });
  458. }
  459. break;
  460. }
  461. },
  462. // 删除文件
  463. handleFileRemove(file, fileList) {
  464. // console.log('删除文件', file, 'file', fileList, 'fileList');
  465. this.importData.list = fileList;
  466. },
  467. // 文件发生改变
  468. handleChangeFile(file, fileList) {
  469. this.importData.list = fileList;
  470. },
  471. // 批量导出
  472. handleExport() {
  473. let ids = this.checkedList.length
  474. ? this.checkedList.map((i) => i.id)
  475. : [];
  476. if (ids.length) {
  477. let params = {
  478. // orgId: '1',
  479. ids,
  480. };
  481. this.download(
  482. "/system/material/export",
  483. params,
  484. `物料基本信息${new Date().getTime()}.xlsx`
  485. );
  486. } else {
  487. let params = {
  488. templateCode: "material",
  489. ...this.params,
  490. createTimeBegin:
  491. (this.params.createTimeQueue && this.params.createTimeQueue[0]) ||
  492. "",
  493. createTimeEnd:
  494. (this.params.createTimeQueue && this.params.createTimeQueue[1]) ||
  495. "",
  496. updateTimeBegin:
  497. (this.params.updateTimeQueue && this.params.updateTimeQueue[0]) ||
  498. "",
  499. updateTimeEnd:
  500. (this.params.updateTimeQueue && this.params.updateTimeQueue[1]) ||
  501. "",
  502. };
  503. this.download(
  504. "/system/material/export",
  505. params,
  506. `物料基本信息${new Date().getTime()}.xlsx`
  507. );
  508. }
  509. },
  510. // 下载模板
  511. handleDownTemplate() {
  512. this.download("/system/material/download", {}, `物料基本信息模板.xlsx`);
  513. },
  514. // 操作弹窗显隐
  515. handleOptionShow(type, val) {
  516. switch (type) {
  517. case "option":
  518. this.optionDialog.show = val;
  519. break;
  520. }
  521. },
  522. // 操作弹窗确认按钮
  523. handleComfirmOption(op) {
  524. switch (op) {
  525. case "cancal":
  526. this.handleOptionShow("option", false);
  527. break;
  528. }
  529. },
  530. // 双击行
  531. handledbClick(e) {
  532. this.$router.push({
  533. path: `/material/basicFile/detail/${e.id}`,
  534. });
  535. },
  536. // 绑定row-key
  537. getRowKey(row) {
  538. return row.id;
  539. },
  540. // 对象数组去重
  541. handleUnique(arr, key) {
  542. // arr 需要去重的数组 type:作为去重依据的key
  543. const res = new Map();
  544. return arr.filter((arr) => !res.has(arr[key]) && res.set(arr[key], 1));
  545. },
  546. // 行数据勾选操作
  547. handleSelect(selection, row) {
  548. this.checkedList = selection;
  549. // // true就是选中,0或者false是取消选中
  550. // let selected = selection.length && selection.indexOf(row) !== -1
  551. },
  552. //手动勾选全选
  553. handleSelectAll(selection) {
  554. this.checkedList = selection;
  555. },
  556. // 获取物料列表信息
  557. async getMaterialList() {
  558. try {
  559. this.loading = true;
  560. let page = {
  561. pageNum: this.queryParams.pageNum,
  562. pageSize: this.queryParams.pageSize,
  563. };
  564. let param = {
  565. templateCode: "material",
  566. ...this.params,
  567. createTimeBegin:
  568. (this.params.createTimeQueue && this.params.createTimeQueue[0]) ||
  569. "",
  570. createTimeEnd:
  571. (this.params.createTimeQueue && this.params.createTimeQueue[1]) ||
  572. "",
  573. updateTimeBegin:
  574. (this.params.updateTimeQueue && this.params.updateTimeQueue[0]) ||
  575. "",
  576. updateTimeEnd:
  577. (this.params.updateTimeQueue && this.params.updateTimeQueue[1]) ||
  578. "",
  579. };
  580. console.log(param, "param--------------");
  581. let { code, data } = await materialApi.materialList(param, page);
  582. if (code == 200) {
  583. this.taskList = data.tableBody.rows;
  584. this.total = data.tableBody.total;
  585. }
  586. } catch (error) {
  587. } finally {
  588. this.loading = false;
  589. }
  590. // materialApi.materialList(param, page).then((res) => {
  591. // _this.loading = false;
  592. // console.log(res, '获取物料列表信息以及表头字段');
  593. // let {code, data} = res;
  594. // if (code == 200) {
  595. // _this.taskList = data.tableBody.rows;
  596. // _this.total = data.tableBody.total;
  597. // }
  598. // })
  599. },
  600. // 获取物料列表表头
  601. getTagList(templateCode) {
  602. materialApi.tagList({ templateCode }).then((res) => {
  603. console.log(res, "获取物料列表表头");
  604. if (res.code == 200) {
  605. this.tableHeader = res.data;
  606. }
  607. });
  608. },
  609. },
  610. created() {},
  611. beforeRouteEnter(to, from, next) {
  612. next((vm) => {
  613. if (from.name == "materialDetail") {
  614. // this.$store.getQuery(this.queryForm);
  615. console.log(vm, "queryValue", vm.$store);
  616. vm.queryForm = vm.$store.state.query.queryVlue;
  617. // 清空选中数据
  618. vm.checkedList = [];
  619. vm.$refs.materialTable && vm.$refs.materialTable.clearSelection();
  620. }
  621. vm.getTagList("material_list");
  622. vm.getMaterialList();
  623. });
  624. },
  625. // 进入详情,保留查询条件
  626. beforeRouteLeave(to, from, next) {
  627. if (to.name == "materialDetail") {
  628. this.$store.commit("SET_QUERY", this.queryForm);
  629. } else {
  630. this.$store.commit("SET_QUERY", { name: "", code: "" });
  631. }
  632. next();
  633. },
  634. };
  635. </script>
  636. <style lang="scss">
  637. .material-basic {
  638. height: calc(100vh);
  639. }
  640. .material-list {
  641. // height: calc(100vh - 70px);
  642. height: 100%;
  643. .el-card__body {
  644. height: 100%;
  645. box-sizing: border-box;
  646. padding: 10px;
  647. .el-table {
  648. // overflow: auto;
  649. .el-table__body-wrapper {
  650. overflow-y: auto !important;
  651. overflow-x: auto !important;
  652. }
  653. }
  654. }
  655. .el-pagination {
  656. // margin-top: 8px;
  657. text-align: right;
  658. }
  659. }
  660. .mb-import {
  661. padding: 0 20%;
  662. text-align: center;
  663. display: flex;
  664. align-items: flex-start;
  665. justify-content: space-around;
  666. }
  667. </style>
  668. <style scoped>
  669. .el-dialog__header {
  670. background-color: rgb(244, 244, 244);
  671. }
  672. .mb-query >>> .el-form-item__label {
  673. font-weight: normal;
  674. font-size: 12px;
  675. }
  676. .mb-query >>> .el-form-item {
  677. margin-bottom: 8px;
  678. }
  679. .mb-query >>> .el-select {
  680. width: 90px;
  681. }
  682. .mb-query >>> .el-scrollbar__wrap {
  683. margin-bottom: -18px;
  684. }
  685. ::v-deep.uxbeautifyTableClass
  686. .elx-header--column
  687. .elx-resizable.is--line:before {
  688. height: 100%;
  689. background-color: #dfe6ec;
  690. }
  691. </style>