DocGeneratorGrid.vue 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519
  1. <template>
  2. <div class="flex-container-1">
  3. <div class="flex-content-1 table-fix-head">
  4. <table
  5. class="fixed-table table-striped table-bordered"
  6. :width="tableWidth"
  7. height="40px"
  8. >
  9. <thead>
  10. <tr height="40px">
  11. <th
  12. width="50px"
  13. class="fixed-cell"
  14. >
  15. <input autocomplete="off"
  16. :checked="allSelected"
  17. type="checkbox"
  18. @click="selectAll($event)"
  19. />
  20. </th>
  21. <th
  22. v-for="infoGridField in infoGridFields"
  23. v-show="infoGridField.isShow"
  24. :key="infoGridField.fieldName"
  25. :width="infoGridField.width + 'px'"
  26. @dragover="ondragover($event, infoGridField)"
  27. @click="onSort(infoGridField)"
  28. >
  29. <div
  30. :id="'infoGridFieldId_' + infoGridField.fieldName"
  31. class="rz-handle"
  32. draggable="true"
  33. @dragstart="ondragstart($event, infoGridField)"
  34. @drag="ondrag($event, infoGridField)"
  35. @dragend="ondragend($event, infoGridField)"
  36. />
  37. <div class="td-max">
  38. {{ infoGridField.name }}
  39. </div>
  40. </th>
  41. </tr>
  42. </thead>
  43. <tbody>
  44. <tr
  45. v-for="rowData in dataList"
  46. :key="rowData.id"
  47. height="40px"
  48. >
  49. <td class="fixed-cell">
  50. <input autocomplete="off"
  51. v-model="rowData.checked"
  52. type="checkbox"
  53. :value="rowData.id"
  54. />
  55. </td>
  56. <td
  57. v-for="infoGridField in infoGridFields"
  58. :key="infoGridField.fieldName + '_' + rowData.id"
  59. >
  60. <input autocomplete="off"
  61. v-if="infoGridField.simpleDisplayType == 'TextEditor'"
  62. type="text"
  63. class="form-control"
  64. :value="getDisplayValue(rowData, infoGridField)"
  65. @keyup="valueChange($event, rowData, infoGridField)"
  66. />
  67. <input autocomplete="off"
  68. v-if="infoGridField.simpleDisplayType == 'NumberEditor'"
  69. type="number"
  70. class="form-control"
  71. :value="getDisplayValue(rowData,infoGridField)"
  72. @keyup="valueChange($event, rowData, infoGridField)"
  73. />
  74. <span v-if="infoGridField.simpleDisplayType == null || infoGridField.simpleDisplayType == '' || infoGridField.simpleDisplayType == 'NONE'">
  75. {{ rowData.data[infoGridField.fieldName] == undefined ? "" : rowData.data[infoGridField.fieldName].displayValue[0] }}
  76. </span>
  77. </td>
  78. </tr>
  79. </tbody>
  80. </table>
  81. </div>
  82. <div
  83. class="flex-footer-1"
  84. style="margin-top: 10px;"
  85. >
  86. <div class="pull-left">
  87. <span>
  88. {{ (pagination.current_page-1)*pagination.per_page+1 }}
  89. -
  90. {{ pagination.current_page*pagination.per_page }}
  91. 条,共计
  92. {{ pagination.total }}
  93. 条,每页
  94. </span>
  95. <PageSizeSelect @page-size-changed="gridSizeSelect" />
  96. <span>条</span>
  97. </div>
  98. <div class="pull-right">
  99. <Pagination
  100. :pagination="pagination"
  101. :callback="refreshSearch"
  102. />
  103. </div>
  104. </div>
  105. </div>
  106. </template>
  107. <script>
  108. var Common = require('../../common/Common.js').default;
  109. var InfoUtil = require('./InfoUtil.js').default;
  110. var Pagination = require('../../vue-bootstrap-pagination/src/vue-bootstrap-pagination.vue').default;
  111. var PageSizeSelect = require('../../page-size-select/src/PageSizeSelect.vue').default;
  112. export default {
  113. components: {
  114. Pagination,
  115. PageSizeSelect,
  116. },
  117. props: {
  118. // 查询窗口编号
  119. infoWindowNo : {
  120. type: String,
  121. default: null,
  122. },
  123. // 表格字段
  124. infoGridFields: {
  125. type: Array,
  126. default: null,
  127. },
  128. // 渲染的数据
  129. infoWindowData: {
  130. type: Object,
  131. default: null,
  132. },
  133. // 方法:根据id判断数据是否被选中
  134. isSelectedById: {
  135. type: Function,
  136. default: null,
  137. },
  138. },
  139. emits: ['selectChanged', 'refreshSearch'],
  140. data: function () {
  141. return {
  142. dataList: [],
  143. pagination: {
  144. total: 0,
  145. per_page: Common.pageSize, // required
  146. current_page: 1, // required
  147. last_page: 10, // required
  148. },
  149. sortStyle: '',
  150. sortClause: '',
  151. };
  152. },
  153. computed: {
  154. /**
  155. * 自动计算表格的宽度
  156. * @author YangZhiJie 20210909
  157. */
  158. tableWidth: function () {
  159. var totalWidth = 50;
  160. if (this.infoGridFields !== undefined) {
  161. this.infoGridFields.forEach(function (infoGridField) {
  162. if (infoGridField.width !== undefined
  163. && infoGridField.width !== null
  164. && infoGridField.width !== '') {
  165. totalWidth += Number(infoGridField.width);
  166. }
  167. });
  168. }
  169. return totalWidth + 'px';
  170. },
  171. /**
  172. * 是否选择了全部的数据
  173. * @author YangZhiJie 20210909
  174. */
  175. allSelected: function () {
  176. var _self = this;
  177. if (this.dataList === undefined || this.dataList === null || this.dataList.length == 0) {
  178. return false;
  179. }
  180. for (let index = 0, length = this.dataList.length; index < length; index++) {
  181. if (this.dataList[index].checked === false) {
  182. return false;
  183. }
  184. }
  185. return true;
  186. },
  187. },
  188. watch: {
  189. infoWindowData: function (newValue, oldValue) {
  190. this.setDataList(newValue);
  191. },
  192. dataList: {
  193. handler: function(newValue, oldValue){
  194. // 清除延迟执行
  195. if(this.selectChangedTimeout !== undefined && this.selectChangedTimeout !== null){
  196. window.clearTimeout(this.selectChangedTimeout);
  197. }
  198. // 设置延迟执行
  199. this.selectChangedTimeout = setTimeout(()=>{
  200. console.log('selectChanged');
  201. this.$emit('selectChanged', this.dataList);
  202. }, 500);
  203. },
  204. deep: true,
  205. },
  206. },
  207. methods: {
  208. /**
  209. * 重新设置分页
  210. * 供外部组件调用
  211. * @author YangZhiJie 20210909
  212. */
  213. resetPagination: function () {
  214. this.pagination.current_page = 1;
  215. this.pagination.last_page = 10;
  216. this.pagination.total = 0;
  217. },
  218. /**
  219. * 设置分页
  220. * @author YangZhiJie 20210909
  221. */
  222. setPagination: function (total, lastPage) {
  223. this.pagination.last_page = lastPage;
  224. this.pagination.total = total;
  225. },
  226. /**
  227. * 获取查询参数
  228. * 供外部组件调用
  229. * @author YangZhiJie 20210909
  230. */
  231. getQueryParam: function () {
  232. return {
  233. infoWindowNo: this.infoWindowNo,
  234. start: (this.pagination.current_page - 1) * this.pagination.per_page,
  235. length: this.pagination.per_page,
  236. sortClause: this.sortClause,
  237. };
  238. },
  239. /**
  240. * 页码数量改变
  241. * @author YangZhiJie 20210909
  242. */
  243. gridSizeSelect: function (newPageSize) {
  244. this.pagination.per_page = newPageSize;
  245. this.pagination.current_page = 1;
  246. },
  247. /**
  248. * 列开始拖动
  249. * @author YangZhiJie 20210909
  250. */
  251. ondragstart: function (event, gridFieldItem) {
  252. var _self = this;
  253. _self.startX = event.pageX;
  254. _self.startWidth = Number(gridFieldItem.width);
  255. event.dataTransfer.setDragImage(event.target, 0, 20);
  256. event.dataTransfer.effectAllowed = 'move';
  257. },
  258. /**
  259. * 列拖动
  260. * @author YangZhiJie 20210909
  261. */
  262. ondrag: function (event, gridFieldItem) {
  263. var _self = this;
  264. gridFieldItem.width = _self.startWidth + (event.pageX - _self.startX);
  265. },
  266. /**
  267. * 列结束拖动
  268. * @author YangZhiJie 20210909
  269. */
  270. ondragend: function (event, gridFieldItem, index) {
  271. var _self = this;
  272. let newWidth = _self.startWidth + (event.pageX - _self.startX);
  273. if (newWidth < 50) {
  274. newWidth = 50;
  275. }
  276. gridFieldItem.width = newWidth;
  277. //gridFieldItem.width = gridFieldItemClone.width;
  278. InfoUtil.saveInfoGridFields(_self.infoWindowDto.no, _self.infoGridFields);
  279. },
  280. ondragover: function (event, gridFieldItem) {
  281. event.preventDefault();
  282. event.dataTransfer.dropEffect = 'move';
  283. },
  284. /**
  285. * 排序
  286. * @author YangZhiJie 20210909
  287. */
  288. onSort: function (infoGridField) {
  289. var _self = this;
  290. var fieldName = null;
  291. if (infoGridField.sortFieldName != undefined && infoGridField.sortFieldName != '') {
  292. fieldName = infoGridField.sortFieldName;
  293. } else {
  294. fieldName = infoGridField.fieldName;
  295. }
  296. _self.sortClause = fieldName + _self.sortStyle;
  297. this.$emit('refreshSearch');
  298. _self.sortStyle = ((_self.sortStyle === ' ASC') ? ' DESC' : ' ASC');
  299. },
  300. /**
  301. * 发送查询请求
  302. * @author YangZhiJie 20210909
  303. */
  304. refreshSearch: function(){
  305. this.$emit('refreshSearch');
  306. },
  307. /**
  308. * 冻结表头
  309. * @author YangZhiJie 20210909
  310. */
  311. fixedTableHeader: function () {
  312. let _self = this;
  313. _self.$nextTick(function () {
  314. var $th = $('.table-fix-head').find('thead');
  315. var $fixedCell = $('.table-fix-head').find('.fixed-cell');
  316. $('.table-fix-head').on('scroll', function () {
  317. $th.css('transform', 'translateY(' + this.scrollTop + 'px)');
  318. $fixedCell.css('transform', 'translateX(' + this.scrollLeft + 'px)');
  319. });
  320. });
  321. },
  322. /**
  323. * 表格中填写的值发生了改变
  324. * @author YangZhiJie 20210909
  325. */
  326. valueChange: function (event, rowData, infoGridField) {
  327. var _self = this;
  328. var value = event.target.value;
  329. const fieldName = infoGridField.fieldName;
  330. if (rowData.data[fieldName] == undefined) {
  331. var tempFieldValue = {
  332. displayValue: [value],
  333. };
  334. rowData.data[fieldName]=tempFieldValue;
  335. } else {
  336. rowData.data[fieldName].displayValue[0]=value;
  337. }
  338. rowData.checked = true;
  339. },
  340. /**
  341. * 获取显示的值
  342. * @author YangZhiJie 20210909
  343. */
  344. getDisplayValue(rowData, infoGridField) {
  345. let fieldValue = rowData.data[infoGridField.fieldName];
  346. if (fieldValue === undefined || fieldValue === null) {
  347. return '';
  348. } else {
  349. return fieldValue.displayValue[0];
  350. }
  351. },
  352. /**
  353. * 选择所有/取消选择的数据
  354. * @author YangZhiJie 20210909
  355. */
  356. selectAll: function (event) {
  357. var isChecked = event.currentTarget.checked;
  358. if (this.dataList === undefined || this.dataList === null || this.dataList.length == 0) {
  359. return;
  360. }
  361. for (let index = 0, length = this.dataList.length; index < length; index++) {
  362. this.dataList[index].checked = isChecked;
  363. }
  364. },
  365. /**
  366. * 设置dataList数据
  367. * @author YangZhiJie 20210908
  368. */
  369. setDataList: function (dataList) {
  370. let _self = this;
  371. if (dataList === null || dataList === undefined) {
  372. this.dataList.splice(0, this.dataList.length);
  373. return;
  374. }
  375. if (!Array.isArray(dataList)) {
  376. console.error('参数异常,参数不是数组类型。');
  377. console.error(dataList);
  378. return;
  379. }
  380. const tempDataList = JSON.parse(JSON.stringify(dataList));
  381. for (let index = 0, length = tempDataList.length; index < length; index++) {
  382. if(this.isSelectedById != null){
  383. tempDataList[index].checked = this.isSelectedById(tempDataList[index].id);
  384. }else{
  385. tempDataList[index].checked = false;
  386. }
  387. }
  388. this.dataList = tempDataList;
  389. this.$nextTick(function(){
  390. _self.fixedTableHeader();
  391. });
  392. },
  393. },
  394. };
  395. </script>
  396. <style scoped>
  397. .flex-container-1 {
  398. display: flex;
  399. flex-direction: column;
  400. width: 100%;
  401. height: calc(100% - 10px);
  402. }
  403. .flex-content-1 {
  404. flex: 1;
  405. overflow: auto;
  406. width: 100%;
  407. margin-top: 5px;
  408. }
  409. .flex-footer-1 {
  410. height: 35px;
  411. /*放大缩小比例为0 */
  412. flex: 0 0 35px;
  413. }
  414. </style>
  415. <style scoped>
  416. .fixed-table {
  417. table-layout: fixed;
  418. }
  419. table.fixed-table th {
  420. position: relative;
  421. min-width: 10px;
  422. }
  423. table.fixed-table tr td:first-child,
  424. table.fixed-table tr th:first-child {
  425. text-align: center;
  426. }
  427. table.fixed-table th,
  428. table.fixed-table td {
  429. text-align: left;
  430. overflow: hidden;
  431. white-space: nowrap;
  432. text-overflow: ellipsis;
  433. padding: 0.1em;
  434. border-right: 1px solid rgba(0, 0, 0, 0.05);
  435. background-color: white;
  436. }
  437. table.fixed-table th .rz-handle {
  438. width: 10px;
  439. height: 100%;
  440. position: absolute;
  441. top: 0;
  442. right: 0;
  443. background: repeating-linear-gradient(
  444. 45deg,
  445. transparent,
  446. transparent 2px,
  447. rgba(0, 0, 0, 0.05) 2px,
  448. rgba(0, 0, 0, 0.05) 4px
  449. );
  450. cursor: ew-resize !important;
  451. }
  452. table.fixed-table th .rz-handle.rz-handle-active {
  453. border-right: 2px solid #000;
  454. transform: scaleX(100);
  455. background: rgba(0, 0, 0, 0.05) 2px;
  456. }
  457. .rz-handle:hover {
  458. background: rgba(0, 0, 0, 0.2) 4px;
  459. }
  460. </style>