QuoteListNew.vue 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512
  1. <template>
  2. <LjDrawer ref="LjDrawerRef" size="50%" :class="prefixCls">
  3. <template #header>
  4. <div class="flx-1">
  5. {{ $t("business.detail.quoteList") }}
  6. <el-button v-if="iforigin" type="primary" size="small" @click="handleOpenOriginQuote">
  7. {{ ifShowOrigin ? "返回新报价清单" : "查看旧报价清单" }}
  8. </el-button>
  9. <el-checkbox
  10. v-if="!ifShowOrigin"
  11. v-model="ifExpandAll"
  12. label="展开明细"
  13. size="small"
  14. style="margin-left: 20px"
  15. @change="toggleRowExpansionAll(tableData2, ifExpandAll)"
  16. ></el-checkbox>
  17. </div>
  18. </template>
  19. <el-descriptions :column="3">
  20. <template #title>
  21. <span class="text-body-b">报价日期:</span>
  22. <span class="text-body-b" v-if="showData.data.createtime">{{ isFilterTime(showData.data.createtime) }}</span>
  23. </template>
  24. <template #extra v-if="ifShowOrigin">
  25. <span class="text-body-b">报价金额:</span>
  26. <span class="text-body-b">{{ isFilterPrice(showData.data.foreign_cost) + isCurrency }}</span>
  27. </template>
  28. <el-descriptions-item v-for="(item, idx) in fields" :key="idx" width="80">
  29. <template #label>
  30. <span class="text-secondary-text"> {{ item.label }}: </span>
  31. </template>
  32. <span class="text-body-m">{{
  33. Object.keys(item).includes("value") ? item.value : isFilterPrice(showData.data[item.field])
  34. }}</span>
  35. </el-descriptions-item>
  36. </el-descriptions>
  37. <template v-if="!ifShowOrigin">
  38. <el-table
  39. :data="tableData"
  40. size="small"
  41. border
  42. style="width: 100%"
  43. :summary-method="getSummaries"
  44. :span-method="objectSpanMethod"
  45. >
  46. <el-table-column prop="level" label="类目" />
  47. <el-table-column prop="group" label="二级项目" />
  48. <template v-if="ifExpandAll">
  49. <el-table-column prop="label" label="项目" />
  50. <el-table-column prop="dscrp" label="内容" width="160" />
  51. <el-table-column prop="qty" label="数量" align="right" />
  52. <el-table-column prop="useqty" label="用量" align="right" />
  53. <el-table-column prop="price" label="单价" align="right" />
  54. </template>
  55. <el-table-column prop="costamt_2" label="标准金额" align="right" />
  56. <el-table-column prop="costamt_1" label="散单金额" align="right" />
  57. <el-table-column prop="costamt_4" label="小单金额" align="right" />
  58. <el-table-column prop="costamt_3" label="大单金额" align="right" />
  59. </el-table>
  60. <!-- <vxe-table
  61. border="full"
  62. ref="tableRef"
  63. :tree-config="treeConfig"
  64. :data="tableData"
  65. @toggle-tree-expand="toggleExpandChangeEvent"
  66. >
  67. <vxe-column field="label" title="项目" tree-node width="120"></vxe-column>
  68. <vxe-column field="dscrp" title="内容" width="160"></vxe-column>
  69. <vxe-column field="qty" title="数量"></vxe-column>
  70. <vxe-column field="costamt" title="数量"></vxe-column>
  71. <template v-if="iforigin && !ifShowOrigin">
  72. <vxe-column field="costamt_1" title="散单金额"></vxe-column>
  73. <vxe-column field="costamt_1" title="标准金额"></vxe-column>
  74. <vxe-column field="costamt_1" title="大单金额"></vxe-column>
  75. <vxe-column field="costamt_1" title="小单金额"></vxe-column>
  76. </template>
  77. <vxe-column field="useqty" title="用量"></vxe-column>
  78. <vxe-column field="price" title="单价"></vxe-column>
  79. </vxe-table> -->
  80. </template>
  81. <template v-else>
  82. <el-table
  83. :data="tableData"
  84. height="100%"
  85. size="small"
  86. border
  87. style="width: 100%"
  88. show-summary
  89. :summary-method="getSummaries"
  90. :span-method="objectSpanMethod"
  91. >
  92. <el-table-column prop="label" label="项目" />
  93. <el-table-column prop="dscrp" label="内容" width="160" />
  94. <el-table-column prop="qty" label="数量" align="right" />
  95. <el-table-column prop="costamt" label="金额" align="right" />
  96. <el-table-column prop="useqty" label="用量" align="right" />
  97. <el-table-column prop="price" label="单价" align="right" />
  98. </el-table>
  99. <!-- <el-table
  100. :data="tableData"
  101. size="small"
  102. border
  103. style="width: 100%"
  104. show-summary
  105. :summary-method="getSummaries"
  106. :span-method="objectSpanMethod"
  107. >
  108. <el-table-column prop="label" label="项目" />
  109. <el-table-column prop="dscrp" label="内容" width="160" />
  110. <el-table-column prop="qty" label="数量" align="right" />
  111. <el-table-column prop="costamt" label="金额" align="right" />
  112. <template v-if="iforigin && !ifShowOrigin">
  113. <el-table-column prop="costamt_1" label="散单金额" align="right" />
  114. <el-table-column prop="costamt_2" label="标准金额" align="right" />
  115. <el-table-column prop="costamt_3" label="大单金额" align="right" />
  116. <el-table-column prop="costamt_4" label="小单金额" align="right" />
  117. </template>
  118. <el-table-column prop="useqty" label="用量" align="right" />
  119. <el-table-column prop="price" label="单价" align="right" />
  120. </el-table> -->
  121. <!-- <el-table
  122. ref="elTableRef"
  123. :data="tableData2"
  124. style="width: 100%; margin-bottom: 20px"
  125. row-key="id"
  126. border
  127. :default-expand-all="ifExpandAll"
  128. :span-method="objectSpanMethod3"
  129. :expand-change="expandChangeFunc"
  130. >
  131. <el-table-column prop="label" label="Date" />
  132. <el-table-column prop="name" label="Name" />
  133. <el-table-column prop="address" label="Address" />
  134. </el-table> -->
  135. </template>
  136. </LjDrawer>
  137. </template>
  138. <script setup lang="tsx" name="mattressQuoteLjDrawerQuoteList">
  139. import { ref, computed, reactive, nextTick } from "vue";
  140. import LjDrawer from "@/components/LjDrawer/index.vue";
  141. import { useDesign } from "@/hooks/useDesign";
  142. import { formatTime, formatAmount3, floatAdd } from "@/utils/index";
  143. import { isFunction } from "@/utils/is";
  144. import { cloneDeep, pick } from "lodash-es";
  145. // import { useUserStore } from "@/stores/modules/user";
  146. import { CommonDynamicSelect } from "@/api/modules/common";
  147. import { useHooksCpQuote } from "../hooks/cpQuote";
  148. import { isFilterPrice, autoMergeCells } from "@/utils/index";
  149. interface WidgetProps {
  150. // data: any;
  151. iforigin: boolean;
  152. }
  153. // interface WidgetTableItem {
  154. // label: string;
  155. // dscrp: any;
  156. // qty?: number | string;
  157. // costamt?: number | string;
  158. // useqty?: number | string;
  159. // price?: number | string;
  160. // [key: string]: any;
  161. // }
  162. const props = withDefaults(defineProps<WidgetProps>(), {
  163. iforigin: false
  164. });
  165. const { prefixCls } = useDesign("ljdrawer-quotelist");
  166. // const { userInfo } = useUserStore();
  167. const { enumMap, tableData, oriTableData, wf_retrieve_qingdan } = useHooksCpQuote();
  168. const LjDrawerRef = ref();
  169. const elTableRef = ref();
  170. const tableRef = ref();
  171. const mainData = ref<any>({});
  172. const showData = ref<any>({});
  173. const ifExpandAll = ref<any>(false);
  174. const isCurrency = computed(() => {
  175. return showData.value.data?.moneyrate != 1 ? "美金" : "人民币";
  176. });
  177. const tableData2: any[] = [
  178. {
  179. id: 1,
  180. label: "2016-05-02",
  181. name: "wangxiaohu",
  182. address: "No. 189, Grove St, Los Angeles"
  183. },
  184. {
  185. id: 2,
  186. label: "2016-05-04",
  187. name: "wangxiaohu",
  188. address: "No. 189, Grove St, Los Angeles"
  189. },
  190. {
  191. id: 3,
  192. label: "2016-05-01",
  193. name: "wangxiaohu",
  194. address: "No. 189, Grove St, Los Angeles",
  195. children: [
  196. {
  197. id: 31,
  198. label: "2016-05-01",
  199. name: "wangxiaohu",
  200. address: "No. 189, Grove St, Los Angeles"
  201. },
  202. {
  203. id: 32,
  204. label: "2016-05-01",
  205. name: "wangxiaohu",
  206. address: "No. 189, Grove St, Los Angeles"
  207. }
  208. ]
  209. },
  210. {
  211. id: 4,
  212. label: "2016-05-03",
  213. name: "wangxiaohu",
  214. address: "No. 189, Grove St, Los Angeles"
  215. }
  216. ];
  217. const treeConfig = reactive<any>({
  218. transform: true,
  219. rowField: "id",
  220. parentField: "parentId"
  221. });
  222. const toggleExpandChangeEvent: any = params => {
  223. const $table = tableRef.value;
  224. if ($table) {
  225. const { row, expanded } = params;
  226. console.log("节点展开事件", expanded, "获取父节点:", $table.getParentRow(row));
  227. }
  228. };
  229. const ifShowOrigin = ref(false);
  230. const originData = ref<any>();
  231. const setOriginData = () => {
  232. let _data = cloneDeep(mainData.value);
  233. if (ifShowOrigin.value) {
  234. // 旧报价
  235. fields.value.map(item => {
  236. let _rp = originData.value.find(itm => itm.label.replace(/【/g, "").replace(/】/g, "") === item.replacelabel);
  237. if (_rp) {
  238. _data.data[item.field] = _rp.value;
  239. }
  240. });
  241. let _rp = originData.value.find(itm => itm.label.replace(/【/g, "").replace(/】/g, "") === "散单金额");
  242. if (_rp) {
  243. _data.data.foreign_cost = _rp.value;
  244. }
  245. }
  246. showData.value = _data;
  247. wf_retrieve_qingdan(_data, !ifShowOrigin.value, ifExpandAll.value);
  248. };
  249. const handleOpenOriginQuote = () => {
  250. ifShowOrigin.value = !ifShowOrigin.value;
  251. console.log("handleOpenOriginQuote>>>>> ", mainData.value);
  252. setOriginData();
  253. };
  254. const toggleRowExpansionAll = (data, isExpansion) => {
  255. wf_retrieve_qingdan(mainData.value, !ifShowOrigin.value, ifExpandAll.value);
  256. // data.forEach(async item => {
  257. // // const elTableRef = await getElTableExpose()
  258. // elTableRef.value?.toggleRowExpansion(item, isExpansion);
  259. // if (item.children !== undefined && item.children !== null) {
  260. // toggleRowExpansionAll(item.children, isExpansion);
  261. // }
  262. // });
  263. };
  264. const objectSpanMethod3 = ({ row, column, rowIndex, columnIndex }: any) => {
  265. // // console.log("objectSpanMethod row,column, rowIndex,columnIndex :>> ", data);
  266. // if (column.property == "label") {
  267. // let rowspan = 1;
  268. // let currentVal = row.label;
  269. // let lastVal = "";
  270. // // 上一个
  271. // if (rowIndex - 1 >= 0) {
  272. // lastVal = tableData2[rowIndex - 1]?.label;
  273. // }
  274. // if (lastVal) {
  275. // if (lastVal != currentVal) {
  276. // // 计算合并行数
  277. // let _span = 0;
  278. // for (let i = rowIndex + 1; i < tableData2.length; i++) {
  279. // if (tableData2[i].label == currentVal) {
  280. // _span++;
  281. // } else {
  282. // break;
  283. // }
  284. // }
  285. // rowspan += _span;
  286. // console.log("rowspan _span :>> ", lastVal, currentVal, rowspan, _span);
  287. // } else {
  288. // rowspan = 0;
  289. // }
  290. // }
  291. // return {
  292. // rowspan,
  293. // colspan: rowspan > 0 ? 1 : 0
  294. // };
  295. // }
  296. // //定义需要合并的列字段,有哪些列需要合并,就自定义添加字段即可
  297. // const fields = ["label"];
  298. // // 当前行的数据
  299. // const cellValue = row[column.property];
  300. // // 判断只合并定义字段的列数据
  301. // if (cellValue && fields.includes(column.property)) {
  302. // const prevRow = tableData2[rowIndex - 1]; //上一行数据
  303. // let nextRow = tableData2[rowIndex + 1]; //下一行数据
  304. // // 当上一行的数据等于当前行数据时,当前行单元格隐藏
  305. // if (prevRow && prevRow[column.property] === cellValue) {
  306. // return { rowspan: 0, colspan: 0 };
  307. // } else {
  308. // // 反之,则循环判断若下一行数据等于当前行数据,则当前行开始进行合并单元格
  309. // let countRowspan = 1; //用于合并计数多少单元格
  310. // while (nextRow && nextRow[column.property] === cellValue) {
  311. // nextRow = tableData2[++countRowspan + rowIndex];
  312. // }
  313. // if (countRowspan > 1) {
  314. // return { rowspan: countRowspan, colspan: 1 };
  315. // }
  316. // }
  317. // }
  318. if (columnIndex === 0) {
  319. if (rowIndex === 2) {
  320. return {
  321. rowspan: 3,
  322. colspan: 1
  323. };
  324. } else if (rowIndex >= 3 && rowIndex < 4) {
  325. return {
  326. rowspan: 0,
  327. colspan: 0
  328. };
  329. }
  330. }
  331. console.log("elTableRef.value :>> ", elTableRef.value);
  332. };
  333. const expandChangeFunc = () => {};
  334. const show = (params: any, originReplace?: any) => {
  335. console.log("show>>>>> ", params, originReplace);
  336. originData.value = [];
  337. if (ifShowOrigin.value) {
  338. setOriginData();
  339. }
  340. mainData.value = cloneDeep(params);
  341. showData.value = cloneDeep(params);
  342. wf_retrieve_qingdan(params, !ifShowOrigin.value, ifExpandAll.value);
  343. LjDrawerRef.value.show();
  344. // nextTick(() => {
  345. // let mergeCells = autoMergeCells(tableRef.value, ["label"]);
  346. // console.log("resetMergeCellsInner autoMergeCells :>> ", mergeCells);
  347. // tableRef.value.setMergeCells(mergeCells);
  348. // });
  349. };
  350. const isFilterTime = time => {
  351. return formatTime(time, "{y}-{m}-{d}", false);
  352. };
  353. const fields = computed(() => {
  354. if (!ifShowOrigin.value) {
  355. const { data } = showData.value;
  356. let _enum = enumMap.value.get("mattresstypeid");
  357. let result = "";
  358. if (_enum) {
  359. result = _enum.find(t => t.value == data.mattresstypeid).label ?? "";
  360. }
  361. let arr = [];
  362. if (Number(data.if_m_chai) == 1) {
  363. arr.push("面拆");
  364. }
  365. if (Number(data.if_z_chai) == 1) {
  366. arr.push("中拆");
  367. }
  368. if (Number(data.if_d_chai) == 1) {
  369. arr.push("底拆");
  370. }
  371. if (Number(data.if_n_butao) == 1) {
  372. arr.push("内布套");
  373. }
  374. if (Number(data.if_w_butao) == 1) {
  375. arr.push("外布套");
  376. }
  377. return [
  378. { label: "核价编码", value: data.mattresscode },
  379. { label: "核价名称", value: data?.mattressname == "" ? "未命名" : data?.mattressname },
  380. { label: "床垫类别", value: result },
  381. { label: "床垫规格", value: `${data.mattress_width} * ${data.mattress_length} * ${data.mattress_height}` },
  382. { label: "拆装、布套", value: arr.join(" ") },
  383. { label: "地区", value: data.area ?? "" },
  384. { label: "柜型", value: data.cabinet_type ?? "" }
  385. ];
  386. } else {
  387. return [
  388. { label: "财务底价", field: "nottax_dept_cost", replacelabel: "部门不含税价" },
  389. { label: "佣金点数", field: "commission", replacelabel: "佣金点数" },
  390. { label: "税率", field: "taxrate", replacelabel: "税率" },
  391. { label: "额外点数", field: "other_rate", replacelabel: "额外点数" },
  392. { label: "额外费用", field: "extras_cost", replacelabel: "额外费用" },
  393. { label: "汇率", field: "moneyrate", replacelabel: "汇率" },
  394. { label: "款式费用", field: "hrcost", replacelabel: "人工费用" },
  395. { label: "边带费用", field: "biandaicost", replacelabel: "边带费用" },
  396. { label: "总成本", field: "total_cost", replacelabel: "车间成本" },
  397. { label: "工厂利润率", field: "profitrate", replacelabel: "工厂利润率" },
  398. { label: "工艺点数", field: "profitrate_point", replacelabel: "工艺点数" },
  399. { label: "不含税出厂价", field: "nottax_factory_cost", replacelabel: "不含税出厂价" },
  400. { label: "部门利润率", field: "dept_profitrate", replacelabel: "部门利润率" },
  401. { label: "FOB费用", field: "fob", replacelabel: "FOB" },
  402. { label: "部门售价", field: "nottax_dept_cost", replacelabel: "部门不含税价" },
  403. { label: "让利点数", field: "dept_profitrate_rangli", replacelabel: "部门让利点数" },
  404. { label: "海绵款扣点", field: "haimian_point", replacelabel: "海绵扣点" }
  405. ];
  406. }
  407. });
  408. const getSummaries = (param: any) => {
  409. const { columns, data } = param;
  410. console.log("getSummaries param :>> ", param);
  411. const sums: any[] = [];
  412. columns.forEach((column, index) => {
  413. if (index === 0) {
  414. sums[index] = <div>材料合计:</div>;
  415. return;
  416. }
  417. const values = data.map(item => Number(item[column.property]?.toString().replace(/,/g, "")));
  418. if (column.property == "costamt" && !values.every(value => Number.isNaN(value))) {
  419. // console.log("values :>> ", values);
  420. sums[index] = `${values.reduce((prev, curr) => {
  421. // console.log("prev,curr :>> ", prev, curr);
  422. const value = Number(curr);
  423. if (!Number.isNaN(value)) {
  424. return floatAdd(prev, curr);
  425. } else {
  426. return prev;
  427. }
  428. }, 0)}`;
  429. } else {
  430. sums[index] = "";
  431. }
  432. });
  433. return sums;
  434. };
  435. const objectSpanMethod = (data: any) => {
  436. const { row, column, rowIndex, columnIndex } = data;
  437. // console.log("objectSpanMethod row,column, rowIndex,columnIndex :>> ", data);
  438. if (["level", "group", "label"].includes(column.property)) {
  439. let rowspan = 1;
  440. let currentVal = row[column.property];
  441. let lastVal = "";
  442. // 上一个
  443. if (rowIndex - 1 >= 0) {
  444. lastVal = tableData.value[rowIndex - 1][column.property];
  445. }
  446. console.log("objectSpanMethod lastVal rowIndex :>> ", lastVal, rowIndex, lastVal || rowIndex == 0);
  447. if (currentVal && (lastVal || rowIndex == 0)) {
  448. if (lastVal != currentVal) {
  449. // 计算合并行数
  450. let _span = 0;
  451. for (let i = rowIndex + 1; i < tableData.value.length; i++) {
  452. console.log("tableData.value[i].label :>> ", tableData.value[i][column.property], currentVal, _span);
  453. if (tableData.value[i][column.property] == currentVal) {
  454. _span++;
  455. } else {
  456. break;
  457. }
  458. }
  459. rowspan += _span;
  460. } else {
  461. rowspan = 0;
  462. }
  463. }
  464. console.log("rowspan _span :>> ", lastVal, currentVal, rowspan);
  465. return {
  466. rowspan,
  467. colspan: rowspan > 0 ? 1 : 0
  468. };
  469. }
  470. };
  471. defineExpose({
  472. show
  473. });
  474. </script>