grid.js 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360
  1. import _ from 'lodash'
  2. import {grid} from '../Defaults'
  3. import {baseConfig} from "./base";
  4. import {lookupFn, lookupScope} from "../lib/lib";
  5. import {serverInvokeUrlTransform} from "../lib/config";
  6. import {calcObject} from "../lib/systemLib";
  7. import {
  8. disabled,
  9. fieldLabel,
  10. gravity, height, metaId,
  11. PropertyDescriptionTable,
  12. tooltip,
  13. value, width,
  14. YvBase
  15. } from "../PropertyDescriptionTable";
  16. import {PropertyDescription} from "../PropertyDescription";
  17. export default function () {
  18. Ext.define('Yvan.Grid', {
  19. extend: 'Ext.grid.Panel',
  20. xtype: 'yvgrid',
  21. constructor(config) {
  22. const me = this
  23. const {dataSource} = config
  24. const newConfig = _.defaultsDeep({
  25. // 强制性属性
  26. }, baseConfig(config, 'row-item'), config, grid)
  27. const buttons = [
  28. {
  29. xtype: 'button',
  30. tooltip: '导出Excel',
  31. iconCls: 'x-fa fa-download'
  32. },
  33. {
  34. xtype: 'button',
  35. iconCls: 'x-fa fa-text-width',
  36. tooltip: '自适应宽度',
  37. listeners: {
  38. click: this.autoSizeColumns
  39. }
  40. },
  41. {
  42. xtype: 'button',
  43. tooltip: '清空筛选',
  44. iconCls: 'x-fa fa-filter',
  45. handler: this.clearFilter
  46. },
  47. {
  48. xtype: 'button',
  49. tooltip: '清空筛选',
  50. iconCls: 'x-fa fa-cube',
  51. handler: this.test
  52. }
  53. ]
  54. if (newConfig.pagination) {
  55. newConfig.bbar = new Ext.PagingToolbar({
  56. pageSize: 50,
  57. displayInfo: true,
  58. store: this.store,
  59. emptyMsg: '没有记录',
  60. items: [
  61. {
  62. xtype: 'combobox',
  63. tooltip: '分页',
  64. queryMode: 'local',
  65. editable: false,
  66. allowBlank: true,
  67. labelAlign: 'right',
  68. width: 90,
  69. // labelWidth: 30,
  70. listConfig: {
  71. minWidth: null
  72. },
  73. value: 50,
  74. valueField: undefined,
  75. displayField: undefined,
  76. hideClear: true,
  77. store: ['20', '50', '100', '200', '300'],
  78. listeners: {
  79. change: (sender, nv, ov) => {
  80. this.store.pageSize = nv;
  81. this.store.loadPage(1);
  82. }
  83. }
  84. },
  85. ...buttons
  86. ]
  87. })
  88. } else {
  89. newConfig.bbar = {
  90. xtype: 'toolbar', overflowHandler: 'menu',
  91. items: [
  92. ...buttons
  93. ]
  94. }
  95. }
  96. this.superclass.constructor.call(this, newConfig)
  97. },
  98. _setDataReal(value) {
  99. const me = this
  100. me.setStore(new Ext.data.Store({
  101. fields: getFileds(this),
  102. data: value
  103. }))
  104. },
  105. /**
  106. * 轻量级刷新
  107. */
  108. refreshData() {
  109. const store = this.getStore()
  110. if (store) {
  111. store.reload()
  112. }
  113. },
  114. /**
  115. * 为表格强制设置焦点
  116. * @param seq 顺序号
  117. */
  118. focusRow(seq) {
  119. this.setSelection(this.store.getAt(seq))
  120. this.getView().focusRow(seq)
  121. },
  122. /**
  123. * 重新载入数据(重新计算参数)
  124. */
  125. reload(reloadParams = {}) {
  126. const me = this
  127. const {config} = me
  128. if (config.dataSourceCallbackFn) {
  129. // 函数请求刷新
  130. const scope = lookupScope(this)
  131. // me.setLoading(true)
  132. config.dataSourceCallbackFn.call(scope, me, {
  133. successCallback(value) {
  134. me._setDataReal(value)
  135. // me.setLoading(false)
  136. me.fireEvent('dataLoadComplete', me, true, value);
  137. },
  138. failCallback(error) {
  139. // me.setLoading(false)
  140. me.fireEvent('dataLoadComplete', me, false, error);
  141. }
  142. })
  143. return
  144. }
  145. // if (this.store) {
  146. // this.store.reload({aaaa: 1, bbbb: 2})
  147. // }
  148. const {dataSource} = config
  149. if (_.isPlainObject(dataSource) && dataSource.method === 'invoke' && !window["IS_DESIGN_MODE"]) {
  150. const scope = lookupScope(me)
  151. calcObject(scope.viewModel, dataSource.params).then(params => {
  152. me.setStore(new Ext.data.Store({
  153. remoteSort: config.remoteSort,
  154. remoteFilter: config.remoteFilter,
  155. proxy: {
  156. type: 'jsonAjax',
  157. $owner: me,
  158. url: serverInvokeUrlTransform(dataSource.url),
  159. extraParams: _.defaultsDeep({}, reloadParams, params),
  160. reader: {
  161. type: 'json',
  162. rootProperty: 'data',
  163. totalProperty: 'pagination.total',
  164. successProperty: 'success',
  165. messageProperty: 'msg'
  166. }
  167. },
  168. listeners: {
  169. load: function (store, records, successful, operation) {
  170. me.fireEvent('dataLoadComplete', me, successful, records);
  171. }
  172. }
  173. }))
  174. })
  175. }
  176. },
  177. initComponent() {
  178. const me = this
  179. const {config} = me
  180. const scope = lookupScope(this)
  181. if (!window["IS_DESIGN_MODE"]) {
  182. // 转换 dataSource 属性
  183. convertDataSource(me, scope, config)
  184. }
  185. this.on({
  186. afterrender(sender) {
  187. const me = this
  188. const {config} = this
  189. const {dataSource} = config
  190. if (config.autoLoad) {
  191. if (config.dataSourceCallbackFn) {
  192. me.reload()
  193. ``
  194. } else if (_.isPlainObject(dataSource) && dataSource.method === 'invoke') {
  195. me.reload()
  196. }
  197. }
  198. if (config.contextMenu) {
  199. this.contextMenu = this.add(config.contextMenu)
  200. }
  201. const $dom = $(sender.el.dom)
  202. $dom.on('keydown', (e) => {
  203. me.fireEvent('keydown', me, e,)
  204. }).on('keyup', (e) => {
  205. me.fireEvent('keyup', me, e,)
  206. })
  207. },
  208. itemcontextmenu(view, rec, node, index, e) {
  209. if (this.contextMenu) {
  210. e.stopEvent();
  211. this.contextMenu.show().setLocalXY(e.getXY());
  212. return false;
  213. }
  214. },
  215. destory() {
  216. },
  217. })
  218. if (this.store?.proxy) {
  219. // 为 stores.proxy.buildRequest 做准备
  220. this.store.proxy.$owner = this
  221. }
  222. this.superclass.initComponent.call(this)
  223. },
  224. autoSizeColumns(sender) {
  225. const grid = sender.up('grid')
  226. // const columns = grid.columns;
  227. // for (let i = 0; i < columns.length; i++) {
  228. // const column = columns[i];
  229. // grid.getView().autoSizeColumn(column);
  230. // column.setWidth(column.getWidth() + 5);
  231. // }
  232. for (let i = 1; i < grid.headerCt.getColumnCount(); i++) {
  233. grid.headerCt.getGridColumns()[i].autoSize(i);
  234. grid.headerCt.getGridColumns()[i].setWidth(grid.headerCt.getGridColumns()[i].getWidth() + 15);
  235. }
  236. },
  237. clearFilter(sender) {
  238. sender.up('grid').filters.clearFilters();
  239. },
  240. test(sender) {
  241. const grid = sender.up('grid')
  242. // grid.refreshData()
  243. // console.log('grid', grid)
  244. },
  245. setLoading(value) {
  246. if (value) {
  247. this.mask('读取中')
  248. } else {
  249. this.unmask()
  250. }
  251. },
  252. // reload() {
  253. // dataSourceReload(this)
  254. // },
  255. })
  256. PropertyDescriptionTable.set(
  257. 'yvgrid',
  258. new PropertyDescription(YvBase, {
  259. props: [
  260. fieldLabel, value, disabled,
  261. gravity, tooltip, metaId, width, height
  262. ],
  263. })
  264. )
  265. }
  266. /**
  267. * 获取 columns 中所有的 dataIndex
  268. */
  269. function getFileds(newConfig) {
  270. const fields = []
  271. _.forEach(newConfig.columns, c => {
  272. if (c.dataIndex) {
  273. fields.push(c.dataIndex)
  274. }
  275. })
  276. return fields
  277. }
  278. function convertDataSource(sender, scope, newConfig) {
  279. if (typeof newConfig.store !== 'undefined') {
  280. // 有 store 属性的情况下,不做任何事
  281. return
  282. }
  283. if (typeof newConfig.dataSource === 'undefined') {
  284. // 没有定义 dataSource 的情况下,不做任何事
  285. return
  286. }
  287. if (_.isArray(newConfig.data)) {
  288. // 有 data 属性赋值的情况下
  289. newConfig.store = {
  290. fields: getFileds(newConfig),
  291. data: newConfig.data
  292. }
  293. delete newConfig.data
  294. return
  295. }
  296. let {dataSource} = newConfig
  297. if (typeof dataSource === 'string') {
  298. // dataSource 是字符串的情况下,找到成员函数
  299. dataSource = lookupFn(scope, dataSource)
  300. }
  301. if (typeof dataSource === 'function') {
  302. // dataSource 是函数的情况下,在 afterrender 之后进行回调
  303. newConfig.store = new Ext.data.Store({
  304. fields: getFileds(newConfig),
  305. // data: [],
  306. autoLoad: true,
  307. proxy: {
  308. type: 'memory',
  309. data: [],
  310. // reader: {
  311. // type: 'json',
  312. // rootProperty: 'users'
  313. // }
  314. }
  315. })
  316. newConfig.dataSourceCallbackFn = dataSource
  317. return
  318. }
  319. // throw new TypeError('无法识别的调用方法')
  320. }