index.vue 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403
  1. // 单据中使用商品表
  2. <template>
  3. <div
  4. :id="'normalTable' + app.name"
  5. class="normalTable"
  6. :style="fullscreen ? 'padding:15px' : ''"
  7. >
  8. <div v-if="props.tableName ? true : false">
  9. <div class="fl-l">
  10. <slot name="operation"></slot>
  11. </div>
  12. <a-space size="middle" class="fl-r mt-10">
  13. <setting-columns
  14. ref="setColumns"
  15. :columns="columns"
  16. :param="props.param"
  17. :tableName="props.tableName"
  18. ></setting-columns>
  19. <fullScreen :domId="'normalTable' + app.name"></fullScreen>
  20. </a-space>
  21. </div>
  22. <a-table
  23. :loading="loading"
  24. class="ant-table-striped ant-table-small"
  25. v-model:expandedRowKeys="expandedRowKeys"
  26. :row-selection="
  27. isSelect
  28. ? {
  29. type: props.filterMultiple ? 'radio' : 'checkbox',
  30. columnWidth: '10px',
  31. selectedRowKeys: selectedRowKeys,
  32. onSelectAll: onSelectAll,
  33. onChange: onSelectChange,
  34. fixed: true,
  35. onSelect: onSelect,
  36. hideSelectAll: false,
  37. preserveSelectedRowKeys: false,
  38. }
  39. : null
  40. "
  41. :rowKey="rowKey"
  42. :keep-selection="true"
  43. :columns="columns"
  44. :defaultExpandAllRows="defaultExpandAllRows"
  45. :data-source="data"
  46. :scroll="
  47. fullscreen ? { x: 'max-content', y: '86vh' } : { x: 'max-content' }
  48. "
  49. :pagination="{
  50. showSizeChanger: true,
  51. defaultPageSize: props.param.content.pageSize,
  52. total: total,
  53. current: props.param.content.pageNumber,
  54. showTotal: (total) => `共 ${total} 条`,
  55. }"
  56. @change="onChange"
  57. :size="size"
  58. :customRow="sequence ? customRow : noRequence"
  59. :bordered="!hideBorder"
  60. :row-class-name="(_record, index) => formatter(_record, index)"
  61. >
  62. <template #headerCell="{ column }">
  63. <div
  64. style="width: 100%"
  65. v-if="column.filter == 1 || column.filter == 2"
  66. >
  67. <!-- <a-input v-model:value="column.value" :placeholder="column.title" @change="setSearchParam(column.dataIndex,column.value)" @pressEnter="listData"></a-input> -->
  68. <a-input
  69. v-model:value="column.value"
  70. :placeholder="column.title"
  71. @change="setSearchParam(column.dataIndex, column.value)"
  72. @pressEnter="listData"
  73. :bordered="true"
  74. >
  75. <template v-if="column.sortable == 1" #suffix>
  76. <sort-ascending-outlined
  77. v-if="column.sort == 0"
  78. @click="setSort(column, 1)"
  79. />
  80. <sort-descending-outlined v-else @click="setSort(column, 0)" />
  81. </template>
  82. </a-input>
  83. </div>
  84. <span v-else style="display: inline-block; padding: 0">
  85. {{ column.title }}
  86. <template v-if="column.sortable == 1">
  87. <sort-ascending-outlined
  88. v-if="column.sort == 0"
  89. @click="setSort(column, 1)"
  90. />
  91. <sort-descending-outlined v-else @click="setSort(column, 0)" />
  92. </template>
  93. </span>
  94. </template>
  95. <template #bodyCell="{ column, record }">
  96. <template v-if="column.fn">
  97. <div style="pointer-events: none">
  98. {{ column.fn(column.fn ? record : "") }}
  99. </div>
  100. </template>
  101. <slot name="tb_cell" :data="{ column, record }"></slot>
  102. </template>
  103. <template #footer v-if="Object.keys($slots).indexOf('footer') != -1">
  104. <slot name="footer"> </slot>
  105. </template>
  106. </a-table>
  107. </div>
  108. </template>
  109. <script setup>
  110. import {
  111. defineEmits,
  112. ref,
  113. defineProps,
  114. defineExpose,
  115. onMounted,
  116. onBeforeUnmount,
  117. computed,
  118. watch,
  119. onActivated,
  120. onDeactivated,
  121. } from "vue";
  122. import settingColumns from "@/components/tableConfiguration/settingColumns.vue";
  123. import fullScreen from "@/components/tableConfiguration/fullScreen.vue";
  124. import Api from "@/api/api";
  125. import utils from "@/utils/utils";
  126. import { useRouter } from "vue-router";
  127. import { storeToRefs } from "pinia";
  128. import { useBaseStore } from "@/stores/modules/base";
  129. import { useColumnsStore } from "@/stores/modules/columns";
  130. import { useAuthStore } from "@/stores/modules/auth";
  131. import {
  132. SortAscendingOutlined,
  133. SortDescendingOutlined,
  134. DownOutlined,
  135. SyncOutlined,
  136. SettingOutlined,
  137. } from "@ant-design/icons-vue";
  138. import { template } from "@antv/g2plot/lib/utils";
  139. const store = useAuthStore();
  140. const colStore = useColumnsStore();
  141. const base = useBaseStore();
  142. let { app } = storeToRefs(store);
  143. let { tableRecord, fullscreen } = storeToRefs(base);
  144. let { selectedColumns } = storeToRefs(colStore);
  145. const router = useRouter();
  146. const props = defineProps({
  147. tableName: String,
  148. columns: Array,
  149. param: Object,
  150. hideBorder: Boolean,
  151. size: String,
  152. tableid: Number,
  153. rowKey: String,
  154. defaultExpandAllRows: {
  155. type: Boolean,
  156. default: () => false,
  157. },
  158. sequence: {
  159. type: Boolean,
  160. default: () => false,
  161. },
  162. filterMultiple: Boolean,
  163. noQuery: false,
  164. tableRowStyle: Function,
  165. isSelect: {
  166. type: Boolean,
  167. default: () => true,
  168. },
  169. });
  170. const formatter = (_record, index) => {
  171. if (props.tableRowStyle) return props.tableRowStyle(_record, index);
  172. if (index % 2 === 1) {
  173. return "table-striped";
  174. } else {
  175. return null;
  176. }
  177. };
  178. let expandedRowKeys = ref([])
  179. const columns = ref(props.columns);
  180. const data = ref([]);
  181. const selectedRowKeys = ref([]);
  182. const total = ref(0);
  183. const emit = defineEmits(["onSelect", "listData", "emitParam"]);
  184. const onSelectChange = (changableRowKeys, selectedRows) => {
  185. selectedRowKeys.value = changableRowKeys;
  186. };
  187. const onChange = (pagination, filters, sorter, { currentDataSource }) => {
  188. selectedRowKeys.value = tableRecord.value.map((e) => e[props.rowKey]);
  189. props.param.content.pageNumber = pagination.current;
  190. props.param.content.pageSize = pagination.pageSize;
  191. listData();
  192. };
  193. const loading = ref(false);
  194. const listData = async (num, size) => {
  195. loading.value = true;
  196. props.param.content.tableid = props.tableid;
  197. emit("emitParam", props.param);
  198. const res = await Api.requested(props.param);
  199. data.value = res.data;
  200. total.value = res.total;
  201. loading.value = false;
  202. emit("listData", data.value, total.value);
  203. };
  204. const onSelect = async (record, selected, selectedRows, nativeEvent) => {
  205. if (!selected) {
  206. tableRecord.value = tableRecord.value.filter(
  207. (e) => e[props.rowKey] !== record[props.rowKey]
  208. );
  209. } else {
  210. tableRecord.value.push(record);
  211. }
  212. emit("onSelect", tableRecord.value);
  213. };
  214. const onSelectAll = (selected, selectedRows, changeRows) => {
  215. if (selected) {
  216. tableRecord.value = [...tableRecord.value, ...changeRows];
  217. } else {
  218. tableRecord.value = tableRecord.value.filter((itemA) => {
  219. return !changeRows.some((itemB) => itemB.itemid === itemA.itemid);
  220. });
  221. }
  222. emit("onSelect", tableRecord.value);
  223. };
  224. const reloadSelect = () => {
  225. selectedRowKeys.value = [];
  226. tableRecord.value = [];
  227. emit("onSelect", tableRecord.value);
  228. };
  229. const setSearchParam = (dataIndex, value) => {
  230. props.param.content.pageNumber = 1;
  231. props.param.content.where.tablefilter = props.param.content.where.tablefilter
  232. ? props.param.content.where.tablefilter
  233. : {};
  234. props.param.content.where.tablefilter[dataIndex] = value;
  235. };
  236. const setSort = (column, sort) => {
  237. props.param.content.simplesort = {};
  238. column.sort = props.param.content.simplesort[column.dataIndex] = sort;
  239. columns.value.forEach((e) => {
  240. if (e.dataIndex !== column.dataIndex) {
  241. e.sort = 0;
  242. }
  243. });
  244. listData();
  245. };
  246. let sourceObj = ref({});
  247. let targetObj = ref({});
  248. let noRequence = () => {};
  249. let customRow = (record, index) => {
  250. return {
  251. style: {
  252. cursor: "move",
  253. },
  254. // 鼠标移入
  255. onMouseenter: (event) => {
  256. // 兼容IE
  257. var ev = event || window.event;
  258. ev.target.draggable = true;
  259. },
  260. // 开始拖拽
  261. onDragstart: (event) => {
  262. // 兼容IE
  263. var ev = event || window.event;
  264. // 阻止冒泡
  265. ev.stopPropagation();
  266. // 得到源目标数据
  267. sourceObj.value = record;
  268. setTimeout(() => {
  269. if (record.parentid == 0) expandedRowKeys.value = []
  270. },100)
  271. console.log(sourceObj,'源数据');
  272. },
  273. // 拖动元素经过的元素
  274. onDragover: (event) => {
  275. // 兼容 IE
  276. var ev = event || window.event;
  277. // 阻止默认行为
  278. let temp = record;
  279. if ((sourceObj.value.parentid!=0 && temp.parentid==0) || sourceObj.value.level != temp.level) return
  280. ev.preventDefault();
  281. },
  282. onDragEnd: (event) => {
  283. },
  284. // 鼠标松开
  285. onDrop: async (event) => {
  286. // 兼容IE
  287. var ev = event || window.event;
  288. // 阻止冒泡
  289. ev.stopPropagation();
  290. // 得到目标数据
  291. targetObj.value = record;
  292. event.preventDefault()
  293. let tempDta = []
  294. if (record.parentid != 0) {
  295. for (let index = 0; index < data.value.length; index++) {
  296. _findParentData(data.value[index],data.value)
  297. }
  298. } else {
  299. tempDta = data.value;
  300. }
  301. function _findParentData (data,all) {
  302. if (data[props.rowKey] == record[props.rowKey]) return tempDta = all
  303. if (data.children && data.children.length) {
  304. data.children.forEach(v => _findParentData(v,data.children))
  305. }
  306. }
  307. tempDta[targetObj.value.weight] = sourceObj.value;
  308. tempDta[sourceObj.value.weight] = targetObj.value;
  309. let source;
  310. let target;
  311. tempDta.forEach((item, index) => {
  312. item.weight = index;
  313. if (sourceObj.value[props.rowKey] == item[props.rowKey]) source = item;
  314. if (targetObj.value[props.rowKey] == item[props.rowKey]) target = item;
  315. });
  316. let res = await Api.requested({
  317. id: "20221201134901",
  318. content: {
  319. ownertable: props.rowKey.substring(0, props.rowKey.indexOf("id")),
  320. sequencesorts: [
  321. {
  322. ownerid: source[props.rowKey],
  323. sequence:
  324. props.param.content.pageSize *
  325. (props.param.content.pageNumber - 1) +
  326. source.weight,
  327. },
  328. {
  329. ownerid: target[props.rowKey],
  330. sequence:
  331. props.param.content.pageSize *
  332. (props.param.content.pageNumber - 1) +
  333. target.weight,
  334. },
  335. ],
  336. },
  337. });
  338. },
  339. };
  340. };
  341. const emitParam = (callback) => {
  342. callback(props.param);
  343. };
  344. onMounted(() => {
  345. props.tableName
  346. ? (columns.value = colStore.loadTableConfig(props.tableName))
  347. : (columns.value = props.columns);
  348. props.noQuery ? "" : listData();
  349. });
  350. onActivated(() => {});
  351. onDeactivated(() => {
  352. reloadSelect();
  353. });
  354. watch(
  355. () => selectedColumns.value,
  356. (n, o) => {
  357. columns.value = colStore.loadTableConfig(props.tableName);
  358. }
  359. );
  360. /**
  361. * 开启缓存后需要拉取新数据
  362. */
  363. defineExpose({
  364. data,
  365. listData,
  366. reloadSelect,
  367. emitParam,
  368. tableRecord,
  369. total,
  370. });
  371. </script>
  372. <style>
  373. </style>
  374. <style scoped>
  375. .ant-table-small :deep(.table-striped) td {
  376. background-color: #f8f9fd;
  377. }
  378. .ant-table-striped :deep td {
  379. font-size: 12px;
  380. }
  381. .normalTable {
  382. background: #fff;
  383. }
  384. .fl-l {
  385. float: left;
  386. }
  387. .fl-r {
  388. float: right;
  389. }
  390. .ant-table-small :deep(.table-striped-red) td {
  391. background: #f1f2f3;
  392. color: #d9363e;
  393. }
  394. .ant-table-small :deep(.table-striped-red) .ant-input-number-input,
  395. .ant-table-small :deep(.table-striped-red) .ant-input {
  396. color: #d9363e !important;
  397. }
  398. </style>