index.vue 23 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775
  1. <template>
  2. <div>
  3. <FullPage
  4. :title="$route.query.title"
  5. :list="list"
  6. @init="init"
  7. :loading="loading"
  8. @searchData="init"
  9. @changePage="changePage"
  10. @changeSize="changeSize"
  11. :tableColums="tableColums"
  12. :tableData="tableData"
  13. :pageIndex="pageIndex"
  14. :total="total"
  15. >
  16. <div slot="titleButton" style="display:flex;">
  17. <Upload
  18. v-if="persimissionData['批量导入'] || persimissionData.all"
  19. name="your_file"
  20. :show-upload-list="false"
  21. :headers="headers"
  22. :on-error="uploadError"
  23. :on-success="uploadSuccess"
  24. :action="$store.state.ip + '/api/product_import'"
  25. >
  26. <Button type="success" ghost icon="md-exit" style="margin-right:10px;"
  27. >批量导入</Button
  28. >
  29. </Upload>
  30. <Button
  31. v-if="persimissionData['批量导出'] || persimissionData.all"
  32. @click="exportData"
  33. type="warning"
  34. ghost
  35. icon="md-return-left"
  36. style="margin-right:10px;"
  37. >批量导出</Button
  38. >
  39. <!-- v-if="persimissionData['批改替换项'] || persimissionData.all" -->
  40. <Button
  41. type="primary"
  42. ghost
  43. @click="showModal = true"
  44. style="margin-right:10px;"
  45. >批改替换项</Button
  46. >
  47. <Button
  48. v-if="persimissionData['新增产品'] || persimissionData.all"
  49. type="primary"
  50. ghost
  51. icon="md-add"
  52. @click="goPage(1)"
  53. >新增产品</Button
  54. >
  55. </div>
  56. <div slot="navButton"></div>
  57. <template slot="set" slot-scope="{ row }">
  58. <div class="table-set">
  59. <svg
  60. style="font-size:20px"
  61. color="#3764FF"
  62. @click="goPage(4, row)"
  63. class="icon icon-nav"
  64. aria-hidden="true"
  65. >
  66. <use xlink:href="#iconcopy-01"></use>
  67. </svg>
  68. <svg
  69. v-if="persimissionData['编辑'] || persimissionData.all"
  70. style="font-size:20px"
  71. color="#3764FF"
  72. @click="goPage(2, row)"
  73. class="icon icon-nav"
  74. aria-hidden="true"
  75. >
  76. <use xlink:href="#iconbianji"></use>
  77. </svg>
  78. <svg
  79. style="font-size:20px"
  80. color="green"
  81. @click="goPage(3, row)"
  82. class="icon icon-nav"
  83. aria-hidden="true"
  84. >
  85. <use xlink:href="#iconxiangqing"></use>
  86. </svg>
  87. <svg
  88. v-if="persimissionData['删除'] || persimissionData.all"
  89. @click="delItems(row)"
  90. class="icon icon-nav"
  91. style="font-size:20px"
  92. color="red"
  93. aria-hidden="true"
  94. >
  95. <use xlink:href="#iconshanchu"></use>
  96. </svg>
  97. </div>
  98. </template>
  99. </FullPage>
  100. <Modal
  101. v-model="showModal"
  102. :title="'批改替换项:' + $route.query.title"
  103. width="1300"
  104. >
  105. <div class="show_modal_content">
  106. <div class="show_modal_content_left">
  107. <div class="show_modal_content_left_item">
  108. <div class="show_modal_content_left_item_title">
  109. <Button
  110. type="primary"
  111. style="cursor:default;border-radius:0"
  112. :ghost="!isSelectAll"
  113. @click="handleProductAllClick(tableData)"
  114. >产品名称</Button
  115. >
  116. </div>
  117. <div class="show_modal_content_left_item_detail_warp">
  118. <div
  119. class="show_modal_content_left_item_detail"
  120. v-for="product in tableData"
  121. :key="product.id"
  122. >
  123. <Button
  124. type="primary"
  125. :ghost="!product.isSelect"
  126. style="border-radius:10px"
  127. @click="handleProductClick(product, 2)"
  128. >{{ product.title }}</Button
  129. >
  130. </div>
  131. </div>
  132. </div>
  133. <div class="show_modal_content_left_item">
  134. <div class="show_modal_content_left_item_title">
  135. <Button
  136. type="primary"
  137. style="cursor:default;border-radius:0"
  138. ghost
  139. >部件名称</Button
  140. >
  141. </div>
  142. <div v-if="productPartList.length < 1">
  143. <Button type="primary" ghost style="border-radius:10px"
  144. >无</Button
  145. >
  146. </div>
  147. <div v-else class="show_modal_content_left_item_detail_warp">
  148. <div
  149. class="show_modal_content_left_item_detail"
  150. v-for="part in productPartList"
  151. :key="part.id"
  152. >
  153. <Button
  154. type="primary"
  155. :ghost="!part.isSelect"
  156. style="border-radius:10px"
  157. @click="handlePartClick(part, 3)"
  158. >{{ part.title }}</Button
  159. >
  160. </div>
  161. </div>
  162. </div>
  163. </div>
  164. <div class="show_modal_content_right">
  165. <div class="show_modal_content_right_top">
  166. <Button type="primary" @click="handleAddChangeable"
  167. >新增替换部件</Button
  168. >
  169. </div>
  170. <div class="show_modal_content_right_body">
  171. <Table
  172. border
  173. max-height="500"
  174. :columns="changeableColumns"
  175. :data="changeableTableData"
  176. ></Table>
  177. </div>
  178. </div>
  179. </div>
  180. <div slot="footer">
  181. <Button
  182. type="primary"
  183. style="margin-right:10px;"
  184. @click="showModal = false"
  185. >取消</Button
  186. >
  187. <Button
  188. type="primary"
  189. style="margin-right:10px;"
  190. @click="handleChangeableConfirm"
  191. >确定</Button
  192. >
  193. </div>
  194. </Modal>
  195. <Modal
  196. v-model="showKey"
  197. :width="1250"
  198. :mask-closable="false"
  199. :closable="false"
  200. >
  201. <div>
  202. <KeyBoard
  203. :rightData="measureList"
  204. @cancel="cancelKey"
  205. @success="successKey"
  206. class="key-co"
  207. />
  208. </div>
  209. <div slot="footer"></div>
  210. </Modal>
  211. </div>
  212. </template>
  213. <script>
  214. import { mapState } from "vuex";
  215. import KeyBoard from "../../components/keyboard/index";
  216. export default {
  217. components: { KeyBoard },
  218. data() {
  219. return {
  220. list: [
  221. {
  222. title: "产品名称",
  223. name: "Input",
  224. value: "",
  225. serverName: "title",
  226. placeholder: "请输入产品名称",
  227. },
  228. {
  229. title: "产品型号",
  230. name: "Input",
  231. value: "",
  232. serverName: "model",
  233. placeholder: "请输入产品型号",
  234. },
  235. {
  236. title: "图号",
  237. name: "Input",
  238. value: "",
  239. serverName: "url_number",
  240. placeholder: "请输入图号",
  241. },
  242. ],
  243. tableColums: [
  244. {
  245. title: "序号",
  246. type: "index",
  247. align: "center",
  248. key: "",
  249. width: "100",
  250. },
  251. { title: "分类名称", align: "center", key: "type_name" },
  252. { title: "产品名称", align: "center", key: "title" },
  253. { title: "计量单位", align: "center", key: "unit" },
  254. { title: "型号", align: "center", key: "model" },
  255. { title: "图号", align: "center", key: "url_number" },
  256. {
  257. title: "产品图片",
  258. align: "center",
  259. key: "company",
  260. render: (h, params) => {
  261. const { row } = params;
  262. return h("img", {
  263. attrs: {
  264. src: this.$store.state.ip + params.row.img_url,
  265. style:
  266. "max-width:50px;max-height:50px;position:relative;top:3px;",
  267. },
  268. on: {
  269. click: (e) => {
  270. this.axios("/api/orders_img", {
  271. params: { id: row.id, type: 0 },
  272. }).then((res) => {
  273. console.log(
  274. "this.$store.state.ip :>> ",
  275. this.$store.state.ip
  276. );
  277. if (res.code == 200) {
  278. row.imgs = res.data;
  279. this.$previewImg({
  280. list: res.data,
  281. baseUrl: this.$store.state.ip,
  282. baseImgField: "img_url",
  283. baseTitleField: "",
  284. });
  285. }
  286. });
  287. // if(row.imgs&&row.imgs.length>0){//优化处理考虑到图纸我就暂时不处理了
  288. // this.$previewImg({
  289. // list:row.imgs,
  290. // baseUrl:this.$store.state.ip,
  291. // baseImgField:'img_url',
  292. // baseTitleField:''
  293. // })
  294. // }else{
  295. // this.axios('/api/orders_img',{params:{id:row.id,type:0}}).then(res=>{
  296. // if(res.code == 200){
  297. // row.imgs = res.data
  298. // this.$previewImg({
  299. // list:row.imgs,
  300. // baseUrl:this.$store.state.ip,
  301. // baseImgField:'img_url',
  302. // baseTitleField:''
  303. // })
  304. // }
  305. // })
  306. // }
  307. },
  308. },
  309. });
  310. },
  311. },
  312. {
  313. title: "图纸",
  314. align: "center",
  315. key: "url",
  316. render: (h, params) => {
  317. const { row } = params;
  318. return h("img", {
  319. attrs: {
  320. src: this.$store.state.ip + params.row.url,
  321. style:
  322. "max-width:50px;max-height:50px;position:relative;top:3px;",
  323. },
  324. on: {
  325. click: (e) => {
  326. this.axios("/api/orders_img", {
  327. params: { id: row.id, type: 1 },
  328. }).then((res) => {
  329. if (res.code == 200) {
  330. row.imgs = res.data;
  331. this.$previewImg({
  332. list: row.imgs,
  333. baseUrl: this.$store.state.ip,
  334. baseImgField: "img_url",
  335. baseTitleField: "",
  336. });
  337. }
  338. });
  339. },
  340. },
  341. });
  342. },
  343. },
  344. { title: "操作", align: "center", slot: "set", width: "150" },
  345. ],
  346. tableData: [],
  347. pageIndex: 1,
  348. total: 0,
  349. pageSize: 10,
  350. proxyObj: {},
  351. loading: false,
  352. headers: { Authorization: localStorage.getItem("token") },
  353. showModal: false,
  354. productPartList: [],
  355. currentProductList: [],
  356. changeableColumns: [
  357. {
  358. title: "替换部件",
  359. align: "center",
  360. key: "part_id",
  361. render: (h, params) => {
  362. const { index } = params;
  363. const currencyRow = this.changeableTableData[index];
  364. return h(
  365. "Select",
  366. {
  367. props: {
  368. value: currencyRow.part_id,
  369. size: "small",
  370. transfer: true,
  371. clearable: true,
  372. filterable: true,
  373. },
  374. on: {
  375. "on-change": (e) => {
  376. currencyRow.part_id = e;
  377. },
  378. },
  379. },
  380. [
  381. this.partsList.map((item) => {
  382. return h("Option", {
  383. props: { label: item.title, value: item.id },
  384. });
  385. }),
  386. ]
  387. );
  388. },
  389. },
  390. {
  391. title: "高",
  392. align: "center",
  393. key: "formula_l",
  394. width: "100px",
  395. render: (h, params) => {
  396. const { index } = params;
  397. const currencyRow = this.changeableTableData[index];
  398. return h("Input", {
  399. props: {
  400. placeholder: "请输入高",
  401. value: currencyRow.formula_l,
  402. disabled: this.isChecked,
  403. },
  404. on: {
  405. "on-focus": () => {
  406. this.openKey(index, "formula_l", currencyRow);
  407. },
  408. },
  409. });
  410. },
  411. },
  412. {
  413. title: "宽",
  414. align: "center",
  415. key: "formula_w",
  416. width: "100px",
  417. render: (h, params) => {
  418. const { index } = params;
  419. const currencyRow = this.changeableTableData[index];
  420. return h("Input", {
  421. props: {
  422. placeholder: "请输入宽",
  423. value: currencyRow.formula_w,
  424. },
  425. on: {
  426. "on-focus": () => {
  427. this.openKey(index, "formula_w", currencyRow);
  428. },
  429. },
  430. });
  431. },
  432. },
  433. {
  434. title: "厚",
  435. align: "center",
  436. key: "formula_h",
  437. width: "100px",
  438. render: (h, params) => {
  439. const { index } = params;
  440. const currencyRow = this.changeableTableData[index];
  441. return h("Input", {
  442. props: {
  443. placeholder: "请输入厚",
  444. value: currencyRow.formula_h,
  445. },
  446. on: {
  447. "on-focus": () => {
  448. this.openKey(index, "formula_h", currencyRow);
  449. },
  450. },
  451. });
  452. },
  453. },
  454. {
  455. title: "操作",
  456. align: "center",
  457. key: "set",
  458. width: "100px",
  459. render: (h, params) => {
  460. const { index } = params;
  461. // const currencyRow = this.changeableTableData[index];
  462. return h(
  463. "a",
  464. {
  465. on: {
  466. click: () => {
  467. this.changeableTableData.splice(index, 1);
  468. },
  469. },
  470. },
  471. "删除"
  472. );
  473. },
  474. },
  475. ],
  476. changeableTableData: [],
  477. partsList: [],
  478. showKey: false,
  479. measureList: [],
  480. currencyChoose: {},
  481. attrindex: null,
  482. attrName: "",
  483. isSelectAll: false,
  484. };
  485. },
  486. beforeRouteLeave(to, from, next) {
  487. if (to.path == "/cms/product/edit") {
  488. this.$route.meta.keepAlive = true;
  489. } else {
  490. this.$route.meta.keepAlive = false;
  491. }
  492. next();
  493. },
  494. beforeRouteEnter(to, from, next) {
  495. next((vm) => {
  496. vm.getData(vm.proxyObj);
  497. });
  498. },
  499. created() {
  500. // 获取部件列表
  501. this.axios("/api/parts_index").then((res) => {
  502. this.partsList = res.data.data;
  503. });
  504. // 获取产品分类测量字段
  505. this.axios("/api/basics_product_list", {
  506. params: { id: this.$route.query.id },
  507. }).then((res) => {
  508. if (res.code == 200) {
  509. const { data } = res;
  510. const result = data.filter((rows) => rows.id == this.$route.query.id);
  511. this.measureList = result[0].measure;
  512. }
  513. });
  514. },
  515. mounted() {
  516. this.proxyObj.type_id = this.$route.query.id;
  517. this.getData(this.proxyObj);
  518. },
  519. computed: {
  520. ...mapState(["persimissionData"]),
  521. },
  522. watch: {
  523. "$route.query.title": {
  524. handler() {
  525. this.proxyObj.type_id = this.$route.query.id;
  526. this.list.forEach((element) => {
  527. element.value = "";
  528. });
  529. this.proxyObj.model = "";
  530. this.proxyObj.title = "";
  531. this.getData(this.proxyObj);
  532. },
  533. },
  534. },
  535. methods: {
  536. init(row) {
  537. this.pageIndex = 1;
  538. row.page_index = this.pageIndex;
  539. row.page_size = this.pageSize;
  540. row.type_id = this.$route.query.id; //产品管理因为无法使用id 所以用type_id替代
  541. this.proxyObj = row;
  542. this.getData(row);
  543. },
  544. getData(row) {
  545. this.loading = true;
  546. this.axios("/api/product", { params: row }).then((res) => {
  547. this.loading = false;
  548. this.tableData = res.data.data;
  549. this.total = res.data.total;
  550. this.tableData.map((item) => (item.isSelect = false));
  551. });
  552. },
  553. delItems(row) {
  554. this.confirmDelete({
  555. content: "确认删除么?",
  556. then: () => {
  557. this.axios
  558. .post("/api/product", { id: row.id, state: 0 })
  559. .then((res) => {
  560. if (res.code == 200) {
  561. this.$Message.success(res.msg);
  562. this.getData(this.proxyObj);
  563. }
  564. });
  565. },
  566. });
  567. },
  568. handleProductAllClick(product) {
  569. this.isSelectAll = !this.isSelectAll;
  570. // let flag
  571. product.map((item) => {
  572. item.isSelect = this.isSelectAll;
  573. });
  574. let ids = product.map((item) => item.id);
  575. this.isSelectAll &&
  576. this.axios
  577. .post("/api/support_product_get_part", {
  578. type: 2,
  579. basic_product_id: [this.$route.query.id],
  580. product_id: ids,
  581. part_id: [],
  582. })
  583. .then((res) => {
  584. console.log(res);
  585. this.productPartList = res.data;
  586. this.productPartList.map((item) => (item.isSelect = false));
  587. });
  588. },
  589. handleProductClick(product, type) {
  590. product.isSelect = !product.isSelect;
  591. this.currentProductList = product;
  592. const temp_product = this.tableData.filter((item) => item.isSelect);
  593. const product_id = temp_product.map((item) => item.id);
  594. // 判断是否全选,全选标题选中
  595. let flag = true
  596. this.tableData.map(item=>{
  597. if (!item.isSelect) {
  598. flag = false
  599. }
  600. })
  601. this.isSelectAll = flag
  602. this.axios
  603. .post("/api/support_product_get_part", {
  604. type,
  605. basic_product_id: [this.$route.query.id],
  606. product_id,
  607. part_id: [],
  608. })
  609. .then((res) => {
  610. console.log(res);
  611. this.productPartList = res.data;
  612. this.productPartList.map((item) => (item.isSelect = false));
  613. });
  614. this.$forceUpdate();
  615. },
  616. handlePartClick(part, type) {
  617. // 部件单选
  618. this.productPartList.map((item) => (item.isSelect = false));
  619. part.isSelect = !part.isSelect;
  620. const temp_product = this.tableData.filter((item) => item.isSelect);
  621. const product_id = temp_product.map((item) => item.id);
  622. const temp_part = this.productPartList.filter((item) => item.isSelect);
  623. const part_id = temp_part.map((item) => item.id);
  624. this.axios
  625. .post("/api/support_product_get_part", {
  626. type,
  627. basic_product_id: [this.$route.query.id],
  628. product_id,
  629. part_id,
  630. })
  631. .then((res) => {
  632. console.log(res);
  633. this.changeableTableData = res.data;
  634. });
  635. this.$forceUpdate();
  636. },
  637. handleAddChangeable() {
  638. const temp = this.productPartList.filter((item) => item.isSelect);
  639. if (temp.length > 0) {
  640. this.changeableTableData.push({
  641. id: "",
  642. formula_h: "",
  643. formula_l: "",
  644. formula_w: "",
  645. });
  646. } else {
  647. this.$Message.warning("请选择部件名称");
  648. }
  649. },
  650. handleChangeableConfirm() {
  651. const temp_product = this.tableData.filter((item) => item.isSelect);
  652. const product_id = temp_product.map((item) => item.id);
  653. const temp_part = this.productPartList.filter((item) => item.isSelect);
  654. const part_id = temp_part.map((item) => item.id);
  655. this.axios
  656. .post("/api/support_product_batch", {
  657. type: 3,
  658. basic_product_id: [this.$route.query.id],
  659. product_id,
  660. part_id,
  661. change: this.changeableTableData,
  662. })
  663. .then((res) => {
  664. if (res.code == 200) {
  665. this.$Message.success(res.msg);
  666. this.tableData.map((item) => (item.isSelect = false));
  667. this.productPartList = [];
  668. this.changeableTableData = [];
  669. this.showModal = false;
  670. }
  671. });
  672. },
  673. openKey(row, attr, cur) {
  674. this.showKey = true;
  675. this.attrindex = row;
  676. this.attrName = attr;
  677. this.currencyChoose = cur;
  678. },
  679. successKey(str) {
  680. // this.info.part[this.attrindex][this.attrName] = str;
  681. this.currencyChoose[this.attrName] = str;
  682. this.showKey = false;
  683. },
  684. cancelKey() {
  685. this.showKey = false;
  686. },
  687. changePage(e) {
  688. this.pageIndex = e;
  689. this.proxyObj.page_index = this.pageIndex;
  690. this.getData(this.proxyObj);
  691. },
  692. changeSize(e) {
  693. this.pageSize = e;
  694. this.proxyObj.page_size = this.pageSize;
  695. this.getData(this.proxyObj);
  696. },
  697. goPage(n, row) {
  698. //n = 1 新增 2 编辑 3 查看
  699. let id = row ? row.id : "";
  700. this.$router.push({
  701. path: "/cms/product/edit",
  702. query: {
  703. type: n,
  704. id: id,
  705. back_id: this.$route.query.id,
  706. title: this.$route.query.title,
  707. },
  708. });
  709. },
  710. async exportData() {
  711. const res = await this.axios("/api/product_export", {
  712. params: { ...this.proxyObj },
  713. });
  714. if (res.code == 200) {
  715. let url = `${this.$store.state.ip}/api/storage/${res.data.file}`;
  716. location.href = url;
  717. }
  718. },
  719. uploadSuccess(res) {
  720. if (res.code == 200) {
  721. this.$Message.success(res.msg || "上传成功");
  722. } else {
  723. this.$Message.warning(res.msg || "上传失败");
  724. }
  725. this.getData(this.proxyObj);
  726. },
  727. uploadError(err) {
  728. this.$Message.error(err.msg || "上传失败");
  729. },
  730. },
  731. };
  732. </script>
  733. <style lang="scss" scoped>
  734. .show_modal_content {
  735. display: flex;
  736. .show_modal_content_left {
  737. width: 50%;
  738. min-height: 500px;
  739. overflow: hidden;
  740. overflow-y: auto;
  741. border-right: 1px solid #e8eaec;
  742. padding-top: 20px;
  743. .show_modal_content_left_item {
  744. width: 100%;
  745. display: flex;
  746. .show_modal_content_left_item_title,
  747. .show_modal_content_left_item_detail {
  748. margin-bottom: 10px;
  749. margin-right: 20px;
  750. }
  751. .show_modal_content_left_item_detail_warp {
  752. display: flex;
  753. justify-content: flex-start;
  754. align-items: flex-start;
  755. flex-wrap: wrap;
  756. .show_modal_content_left_item_detail {
  757. }
  758. }
  759. }
  760. }
  761. .show_modal_content_right {
  762. width: 50%;
  763. padding-left: 20px;
  764. .show_modal_content_right_top {
  765. display: flex;
  766. justify-content: flex-end;
  767. margin-top: 50px;
  768. margin-bottom: 10px;
  769. }
  770. }
  771. }
  772. </style>