setPlan.vue 20 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700
  1. <template>
  2. <div class="project-setPlan" v-loading="loading">
  3. <div class="project-setPlan-main">
  4. <div class="project-setPlan-title">商品要求</div>
  5. <div class="project-setPlan-ask-table">
  6. <template v-if="ladder">
  7. <el-table
  8. :data="ladder"
  9. :size="'mini'"
  10. border
  11. stripe
  12. style="width: 100%"
  13. >
  14. <el-table-column label="要求编码" prop="pgNo" width="155px" />
  15. <el-table-column prop="good_type" label="商品类型" width="80px">
  16. <template slot-scope="scope">
  17. <el-tag
  18. :size="'mini'"
  19. v-text="
  20. (
  21. statusOptions.find(
  22. (item) => item.value == scope.row.good_type
  23. ) || {}
  24. ).label || '--'
  25. "
  26. ></el-tag
  27. ></template>
  28. </el-table-column>
  29. <el-table-column prop="budget_price" label="预算单价" width="110" />
  30. <el-table-column prop="num" label="购买数量" width="110" />
  31. <el-table-column prop="cat_name" label="商品分类" />
  32. <el-table-column prop="good_img" label="图片" width="50">
  33. <template slot-scope="scope">
  34. <div
  35. v-if="scope.row.good_img"
  36. style="width: 20px; height: 20px"
  37. class="hover"
  38. v-viewer
  39. >
  40. <img
  41. :src="scope.row.good_img"
  42. style="display: inline-block; width: 100%; height: 100%"
  43. alt=""
  44. />
  45. </div>
  46. </template>
  47. </el-table-column>
  48. <el-table-column prop="good_name" label="商品名称" />
  49. </el-table>
  50. </template>
  51. </div>
  52. <div class="project-setPlan-title">客户意向商品</div>
  53. <div class="project-setPlan-backGood-table">
  54. <el-table
  55. :data="tableData"
  56. :size="'mini'"
  57. border
  58. stripe
  59. ref="multipleTable"
  60. style="width: 100%"
  61. @selection-change="handleSelectionChange"
  62. >
  63. <el-table-column
  64. type="selection"
  65. width="40"
  66. v-if="table_type === 'add'"
  67. >
  68. </el-table-column>
  69. <el-table-column
  70. prop="pgNo"
  71. label="要求编码"
  72. width="155px"
  73. show-overflow-tooltip
  74. />
  75. <el-table-column
  76. prop="origin_price"
  77. label="销售单价"
  78. width="110"
  79. show-overflow-tooltip
  80. />
  81. <el-table-column
  82. prop="num"
  83. label="购买数量"
  84. width="110"
  85. show-overflow-tooltip
  86. />
  87. <el-table-column
  88. prop="good_img"
  89. label="图片"
  90. width="50"
  91. show-overflow-tooltip
  92. >
  93. <template slot-scope="scope">
  94. <div
  95. v-if="scope.row.good_img"
  96. style="width: 20px; height: 20px"
  97. class="hover"
  98. v-viewer
  99. >
  100. <img
  101. :src="scope.row.good_img"
  102. style="display: inline-block; width: 100%; height: 100%"
  103. alt=""
  104. />
  105. </div>
  106. </template>
  107. </el-table-column>
  108. <el-table-column
  109. prop="good_name"
  110. label="商品名称"
  111. show-overflow-tooltip
  112. />
  113. <el-table-column
  114. prop="class_cat"
  115. label="商品分类"
  116. show-overflow-tooltip
  117. />
  118. <el-table-column prop="model" label="规格" show-overflow-tooltip />
  119. <el-table-column
  120. prop="expiry_day"
  121. label="信息有效期"
  122. width="85"
  123. show-overflow-tooltip
  124. />
  125. <el-table-column
  126. prop="work_day"
  127. label="制作工期"
  128. width="70"
  129. show-overflow-tooltip
  130. />
  131. <el-table-column
  132. prop="delivery_day"
  133. label="物流时间"
  134. width="70"
  135. show-overflow-tooltip
  136. />
  137. </el-table>
  138. </div>
  139. <div class="project-setPlan-title">
  140. 项目方案
  141. <span v-if="total !== 0 && table_type === 'list'"
  142. >{{ plan_show.status === "1" ? "已选定" : "" }}方案总金额:{{
  143. plan_show.sale_total
  144. }}元</span
  145. >
  146. <el-button-group
  147. :size="'mini'"
  148. class="fr"
  149. v-if="table_type === 'list'"
  150. style="margin: 8px 0 0 0"
  151. >
  152. <el-button
  153. type="primary"
  154. class="fr"
  155. v-if="
  156. powers &&
  157. powers.length > 0 &&
  158. powers.some((item) => item == '064') &&
  159. (status == '3' || status == '4')
  160. "
  161. @click="add_plan"
  162. icon="el-icon-circle-plus-outline"
  163. :size="'mini'"
  164. >添加方案
  165. </el-button>
  166. <el-button
  167. type="primary"
  168. class="fr"
  169. v-if="plan_show.status === '1'"
  170. @click="place_order"
  171. :size="'mini'"
  172. >项目下单<i class="el-icon-shopping-cart-2 el-icon--right"></i>
  173. </el-button>
  174. <el-button
  175. class="fr"
  176. type="primary"
  177. :size="'mini'"
  178. :disabled="index === 0"
  179. v-if="total !== 0"
  180. icon="el-icon-arrow-left"
  181. @click="index--, change_plan()"
  182. ></el-button>
  183. <el-button
  184. type="primary"
  185. class="fr"
  186. v-if="total !== 0"
  187. :size="'mini'"
  188. style="height: 29px"
  189. >方案共{{ index + 1 }}/{{ total }}</el-button
  190. >
  191. <el-button
  192. type="primary"
  193. class="fr"
  194. :disabled="index + 1 === total"
  195. v-if="total !== 0"
  196. @click="index++, change_plan()"
  197. :size="'mini'"
  198. ><i class="el-icon-arrow-right el-icon--right" :size="'mini'"></i
  199. ></el-button>
  200. </el-button-group>
  201. <el-button-group
  202. :size="'mini'"
  203. class="fr"
  204. v-else-if="table_type === 'add'"
  205. style="margin: 8px 0 0 0"
  206. >
  207. <el-button
  208. class="fr"
  209. type="primary"
  210. :size="'mini'"
  211. icon="el-icon-arrow-left"
  212. @click="back_list"
  213. >返回列表</el-button
  214. >
  215. <el-button type="primary" class="fr" @click="save_plan" :size="'mini'"
  216. >保存方案<i class="el-icon-upload el-icon--right"></i>
  217. </el-button>
  218. </el-button-group>
  219. </div>
  220. <div class="project-setPlan-backGood-table">
  221. <el-table
  222. :data="plan_show.feedback"
  223. :size="'mini'"
  224. border
  225. stripe
  226. :ref="'multipleTable' + index"
  227. style="width: 100%"
  228. >
  229. <el-table-column
  230. prop="pgNo"
  231. label="要求编码"
  232. width="155px"
  233. show-overflow-tooltip
  234. />
  235. <el-table-column
  236. prop="origin_price"
  237. label="系统售价单价"
  238. width="110"
  239. show-overflow-tooltip
  240. />
  241. <el-table-column
  242. prop="new_sale_price"
  243. label="当前销售单价"
  244. width="110"
  245. show-overflow-tooltip
  246. >
  247. <template slot-scope="scope">
  248. <digital-input
  249. v-if="table_type === 'add'"
  250. :values="scope.row.new_sale_price"
  251. :placeholder="'售价'"
  252. :min="scope.row.origin_price"
  253. :max="100000000000"
  254. :position="'right'"
  255. :precision="0"
  256. :size="'mini'"
  257. :controls="false"
  258. :append="''"
  259. @reschange="
  260. moq_num_change($event, scope.$index, 'new_sale_price')
  261. "
  262. />
  263. <span v-else>{{ scope.row.sale_price }}元</span>
  264. </template>
  265. </el-table-column>
  266. <el-table-column
  267. prop="origin_num"
  268. label="咨询数量"
  269. width="110"
  270. show-overflow-tooltip
  271. />
  272. <el-table-column
  273. prop="num"
  274. label="购买数量"
  275. width="110"
  276. show-overflow-tooltip
  277. >
  278. <template slot-scope="scope">
  279. <digital-input
  280. v-if="table_type === 'add'"
  281. :values="scope.row.origin_num"
  282. :placeholder="'购买数量'"
  283. :min="scope.row.origin_num"
  284. :max="100000000000"
  285. :position="'right'"
  286. :precision="0"
  287. :size="'mini'"
  288. :controls="false"
  289. :append="''"
  290. @reschange="moq_num_change($event, scope.$index, 'num')"
  291. />
  292. <span v-else>{{ scope.row.num }}</span>
  293. </template>
  294. </el-table-column>
  295. <el-table-column
  296. prop="good_img"
  297. label="图片"
  298. width="50"
  299. show-overflow-tooltip
  300. >
  301. <template slot-scope="scope">
  302. <div
  303. v-if="scope.row.good_img"
  304. style="width: 20px; height: 20px"
  305. class="hover"
  306. v-viewer
  307. >
  308. <img
  309. :src="scope.row.good_img"
  310. style="display: inline-block; width: 100%; height: 100%"
  311. alt=""
  312. />
  313. </div>
  314. </template>
  315. </el-table-column>
  316. <el-table-column
  317. prop="good_name"
  318. label="商品名称"
  319. show-overflow-tooltip
  320. />
  321. <el-table-column
  322. prop="class_cat"
  323. label="商品分类"
  324. show-overflow-tooltip
  325. />
  326. <el-table-column prop="model" label="规格" show-overflow-tooltip />
  327. <el-table-column
  328. prop="expiry_day"
  329. label="信息有效期"
  330. width="85"
  331. show-overflow-tooltip
  332. />
  333. <el-table-column
  334. prop="work_day"
  335. label="制作工期"
  336. width="70"
  337. show-overflow-tooltip
  338. />
  339. <el-table-column
  340. prop="delivery_day"
  341. label="物流时间"
  342. width="70"
  343. show-overflow-tooltip
  344. />
  345. </el-table>
  346. </div>
  347. <buy-good-modal
  348. :showModel="bayGoodShowModel"
  349. :sitem="bayGoodItem"
  350. @cancel="bayGoodShowModel = false"
  351. @refresh="(bayGoodShowModel = false), $emit('resGoodOk')"
  352. />
  353. </div>
  354. </div>
  355. </template>
  356. <script>
  357. import asyncRequest from "@/apis/service/sellOut/project";
  358. import resToken from "@/mixins/resToken";
  359. import columnsForm from "./columnsForm";
  360. import buyGoodModal from "./buyGoodModal";
  361. export default {
  362. name: "setPlan",
  363. props: ["showModel", "sitem", "id", "type"],
  364. mixins: [resToken],
  365. components: {
  366. buyGoodModal,
  367. },
  368. computed: {
  369. powers() {
  370. let tran =
  371. this.$store.getters.btnList.find(
  372. (item) => item.menu_route == "projectDetail"
  373. ) || {};
  374. if (tran && tran.action && tran.action.length > 0) {
  375. return tran.action;
  376. } else {
  377. return [];
  378. }
  379. },
  380. },
  381. watch: {
  382. // showModel: function (val) {
  383. // this.showModelThis = val;
  384. // if (val) {
  385. // this.initForm();
  386. // }
  387. // },
  388. // showModelThis(val) {
  389. // if (!val) {
  390. // this.$emit("cancel");
  391. // }
  392. // },
  393. },
  394. data() {
  395. return {
  396. showModel: false,
  397. searchItem: {},
  398. loading: false,
  399. allPlanList: [],
  400. bayGoodItem: {},
  401. bayGoodShowModel: false,
  402. ladder: [],
  403. index: 0,
  404. total: 0,
  405. table_type: "list",
  406. // allList: [],
  407. projectNo: "",
  408. status: "",
  409. statusOptions: [
  410. { value: "1", label: "竞品" },
  411. { value: "2", label: "竞聘" },
  412. ],
  413. table: {
  414. stripe: true,
  415. border: true,
  416. // _defaultHeader_: ["setcol"],
  417. },
  418. // 表格 - 列参数
  419. columns: columnsForm,
  420. tableData: [],
  421. multipleSelection: [],
  422. plan_show: {
  423. sale_total: "0",
  424. feedback: [],
  425. },
  426. };
  427. },
  428. mounted() {
  429. this.initForm();
  430. },
  431. methods: {
  432. //初始化整个组件
  433. async initForm() {
  434. this.loading = true;
  435. await this.initListData();
  436. await this.back_list();
  437. this.loading = false;
  438. },
  439. //项目下单
  440. place_order() {
  441. const { company, khName, platform_name, arrtime, project_name } =
  442. this.sitem;
  443. this.bayGoodItem = JSON.parse(
  444. JSON.stringify(this.allPlanList[this.index])
  445. );
  446. this.bayGoodItem.in_company = company;
  447. this.bayGoodItem.in_khname = khName;
  448. this.bayGoodItem.in_platform_name = platform_name;
  449. this.bayGoodItem.in_arrival_time = arrtime;
  450. this.bayGoodItem.in_project_name = project_name;
  451. this.bayGoodShowModel = true;
  452. },
  453. async resetFormData() {
  454. this.pageInfo = {
  455. size: 15,
  456. curr: 1,
  457. total: 0,
  458. };
  459. this.loading = true;
  460. this.tableData = [];
  461. await this.searchList();
  462. },
  463. async back_list() {
  464. this.table_type = "list";
  465. await this.get_plan("1");
  466. },
  467. add_plan() {
  468. const { low_rate } = this.sitem;
  469. let r = low_rate ? low_rate : "0";
  470. if (r === 0) {
  471. this.$message.warning("暂无项目毛利率,不能制定方案!");
  472. return;
  473. }
  474. this.table_type = "add";
  475. this.plan_show = {
  476. sale_total: "0",
  477. feedback: [],
  478. };
  479. },
  480. moq_num_change(e, index, key) {
  481. this.plan_show.feedback[index][key] = e + "";
  482. this.$set(
  483. this.plan_show.feedback[index],
  484. index,
  485. this.plan_show.feedback[index]
  486. );
  487. },
  488. //初始化整个组件
  489. async initListData() {
  490. console.log(this.sitem);
  491. const { projectNo, ladder, status } = this.sitem;
  492. this.status = status;
  493. this.projectNo = projectNo;
  494. this.ladder = JSON.parse(JSON.stringify(ladder));
  495. this.pageInfo = {
  496. size: 100,
  497. curr: 1,
  498. total: 0,
  499. };
  500. this.tableData = [];
  501. await this.searchList();
  502. },
  503. handleSelectionChange(val) {
  504. this.multipleSelection = val;
  505. let list = JSON.parse(JSON.stringify(this.plan_show.feedback));
  506. this.plan_show = {
  507. sale_total: "0",
  508. feedback: [],
  509. };
  510. this.multipleSelection.forEach((a, i) => {
  511. let fi = list.findIndex((b) => a.id === b.id && b.pgNo === a.pgNo);
  512. if (fi !== -1) {
  513. this.plan_show.feedback.push(JSON.parse(JSON.stringify(list[fi])));
  514. } else {
  515. this.plan_show.feedback.push(
  516. JSON.parse(JSON.stringify(this.multipleSelection[i]))
  517. );
  518. }
  519. });
  520. this.plan_show.feedback.map((e) => {
  521. console.log(e.sale_price);
  522. e.new_sale_price = e.sale_price;
  523. e.origin_num = e.num;
  524. return e;
  525. });
  526. },
  527. async searchList() {
  528. const { size, curr } = this.pageInfo;
  529. // this.loading = true;
  530. let model = {
  531. page: curr,
  532. size: size,
  533. zxNo: "",
  534. infoNo: "",
  535. bidNo: "",
  536. status: "1",
  537. pgNo: "",
  538. projectNo: this.projectNo,
  539. };
  540. const { code, data } = await asyncRequest.back_good_list(model);
  541. if (code === 0) {
  542. const { list, count } = data;
  543. this.tableData = list;
  544. this.tableData.map((v) => {
  545. v.class_cat = "";
  546. if (v.can && v.can.length > 0) {
  547. v.can.forEach((x, i) => {
  548. v.class_cat += i === 0 ? x.name : "/" + x.name;
  549. });
  550. }
  551. return v;
  552. });
  553. this.pageInfo.total = Number(count);
  554. } else if (code >= 100 && code <= 104) {
  555. await this.logout();
  556. } else {
  557. this.tableData = [];
  558. this.pageInfo.total = 0;
  559. }
  560. // this.loading = false;
  561. },
  562. //保存方案
  563. async save_plan() {
  564. if (!this.loading) {
  565. const { feedback } = this.plan_show;
  566. let list = feedback;
  567. let isok = true;
  568. list.forEach((a) => {
  569. let findex = list.findIndex(
  570. (b) => b.pgNo === a.pgNo && a.id !== b.id
  571. );
  572. if (findex !== -1) {
  573. isok = false;
  574. }
  575. });
  576. if (!isok) {
  577. this.$message.warning("一种商品要求只能选择一种商品!");
  578. return;
  579. }
  580. let isall = true;
  581. this.ladder.forEach((a) => {
  582. let to = 0;
  583. list.forEach((b) => {
  584. if (a.pgNo === b.pgNo) {
  585. to++;
  586. }
  587. });
  588. if (to !== 1) {
  589. isall = false;
  590. }
  591. });
  592. if (!isall) {
  593. this.$message.warning("方案必须涵盖全部商品要求!");
  594. return;
  595. }
  596. this.loading = true;
  597. let model = {
  598. feedback: [],
  599. projectNo: this.projectNo,
  600. };
  601. list.forEach((e) => {
  602. let si = {
  603. feedid: e.id,
  604. sale_price: e.new_sale_price,
  605. good_num: e.num,
  606. };
  607. model.feedback.push(si);
  608. });
  609. const { code, data, message } = await asyncRequest.project_make_plan(
  610. model
  611. );
  612. if (code === 0) {
  613. await this.back_list();
  614. } else if (code >= 100 && code <= 104) {
  615. await this.logout();
  616. } else {
  617. this.$message.warning(message);
  618. }
  619. this.loading = false;
  620. }
  621. },
  622. //获取全部方案
  623. async get_plan(type) {
  624. let model = {
  625. projectNo: this.projectNo,
  626. };
  627. const { code, data, message } = await asyncRequest.get_project_plan(
  628. model
  629. );
  630. if (code === 0) {
  631. this.allPlanList = JSON.parse(JSON.stringify(data));
  632. this.total = this.allPlanList.length;
  633. if (type && this.allPlanList.length > 0) {
  634. await this.change_plan("1");
  635. }
  636. } else if (code >= 100 && code <= 104) {
  637. await this.logout();
  638. } else {
  639. this.$message.warning(message);
  640. }
  641. },
  642. //切换当前展示的方案
  643. async change_plan(type) {
  644. this.table_type = "list";
  645. this.plan_show = {
  646. sale_total: "0",
  647. status: "0",
  648. feedback: [],
  649. };
  650. if (type) {
  651. this.index = 0;
  652. }
  653. if (this.status === "4") {
  654. this.allPlanList.forEach((a, ai) => {
  655. if (a.status === "1") {
  656. this.index = ai;
  657. }
  658. });
  659. }
  660. const { sale_total, feedback, status } = JSON.parse(
  661. JSON.stringify(this.allPlanList[this.index])
  662. );
  663. this.plan_show = {
  664. sale_total: sale_total,
  665. status: status,
  666. feedback: JSON.parse(JSON.stringify(feedback)),
  667. };
  668. console.log(this.plan_show);
  669. for (let i = 0; i < this.plan_show.feedback.length; i++) {
  670. this.$set(this.plan_show.feedback[i], i, this.plan_show.feedback[i]);
  671. }
  672. },
  673. },
  674. };
  675. </script>
  676. <style lang="scss" scoped>
  677. .project-setPlan {
  678. box-sizing: border-box;
  679. width: 100%;
  680. .project-setPlan-main {
  681. padding: 2px 16px 16px 16px;
  682. // background: #fefefe;
  683. border-radius: 5px;
  684. overflow: hidden;
  685. border: 1px solid #f0f0f0;
  686. margin: 0 0 16px 0;
  687. .project-setPlan-title {
  688. height: 48px;
  689. line-height: 48px;
  690. color: #676767;
  691. }
  692. }
  693. }
  694. </style>