systemLib.ts 27 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963
  1. import _ from 'lodash'
  2. import {Lib, lookupScope} from './lib'
  3. import {ajax} from "./config";
  4. import {msg, showErrorDialog} from "../message";
  5. export const SIMPLE_RE = /^(?:\{(?:(\d+)|([a-z_][\w\.]*))\})$/i
  6. /**
  7. * 对某个表达式进行求值
  8. * a:{query.a},b:{query.b} -> a:aValue,b:bValue
  9. *
  10. * @example
  11. * calcExpress(cc.viewModel.data, "WH_ID:{query.WH_ID},C:{theGrid.selection.data.WH_ID}")
  12. * 计算出来的值是: "WH_ID:queryWhId,C:JH000000001"
  13. *
  14. * @param data 数据环境对象
  15. * @param express 表达式对象
  16. */
  17. export function calcExpress(data, express) {
  18. let result = express
  19. if (SIMPLE_RE.test(express)) {
  20. // '{foo}' 简单表达式
  21. const path = express.substring(1, express.length - 1);
  22. const ret = _.get(data, path)
  23. return ret.isModel ? ret.data : ret
  24. }
  25. while (true) {
  26. const mlist = result.match(/{(.*?)}/)
  27. if (!mlist) {
  28. break
  29. }
  30. const pathC = mlist[0] // {query.a}
  31. const path = mlist[1] // query.a
  32. let value = _.get(data, path)
  33. result = result.replaceAll(pathC, value || '')
  34. }
  35. return result
  36. }
  37. /**
  38. * 对个对象进行表达式求值,不用回调
  39. * @example
  40. * calcObjectFlat({query:{a:'aValue',b1:'b1Value',b2:'b2Value',d1:1,d2:2}}, { a:'{query.a}', b:{b1:'{query.b1}', b2:'{query.b2}'},c:'aa',d:['{query.d1}','{query.d2}'] })
  41. *
  42. * {
  43. * a: '{query.a}',
  44. * b: {
  45. * b1: '{query.b1}',
  46. * b2: '{query.b2}',
  47. * },
  48. * c: 'aa',
  49. * d: [
  50. * '{query.d1}',
  51. * '{query.d2}'
  52. * ]
  53. * }
  54. *
  55. * 计算结果为
  56. * {
  57. * a: 'aValue',
  58. * b: {
  59. * b1: 'b1Value',
  60. * b2: 'b2Value'
  61. * },
  62. * c: 'aa'
  63. * d: [
  64. * '1',
  65. * '2'
  66. * ]
  67. * }
  68. *
  69. * @param data
  70. * @param paramObject
  71. */
  72. export function calcObjectFlat(data, paramObject) {
  73. const result = _.cloneDeep(paramObject)
  74. const trav = (param) => {
  75. _.forOwn(param, (value, key) => {
  76. if (_.isPlainObject(value)) {
  77. // 深度递归,对子对象进行求解
  78. trav(value)
  79. } else if (_.isString(value)) {
  80. // 字符串直接用 calcExpress 表达式求解
  81. param[key] = calcExpress(data, param[key])
  82. } else if (_.isArray(value)) {
  83. // 数组求解
  84. _.each(value, (v, idx) => {
  85. value[idx] = calcExpress(data, v)
  86. })
  87. }
  88. })
  89. }
  90. trav(result)
  91. return result
  92. }
  93. /**
  94. * 根据表达式进入写值
  95. * express="{query.a}" 写值就是 viewModel.set('query.a', value)
  96. * express="test-{query.a}" 写值就会失败
  97. *
  98. * @example
  99. * tryWriteByExpress(cc.viewModel, "{query.WH_ID}", "111")
  100. * 写值成功
  101. *
  102. * tryWriteByExpress(cc.viewModel, "test-{query.WH_ID}", "111")
  103. * 写值失败
  104. *
  105. * @param viewModel VM对象
  106. * @param express 表达式对象
  107. * @param value 目标值
  108. */
  109. export function tryWriteByExpress(viewModel, express, value) {
  110. if (SIMPLE_RE.test(express)) {
  111. // '{foo}' 简单表达式
  112. express = express.substring(1, express.length - 1);
  113. viewModel.set(express, value)
  114. }
  115. }
  116. /**
  117. * 尝试根据含表达式的对象回写, calcObjectFlat 的逆向方法
  118. * @example
  119. * tryWriteObject({ a:'{query.a}', b:{b1:'{query.b1}', b2:'{query.b2}'},c:'aa',d:['{query.d1}','{query.d2}']}, {a:'aValue', b:{b1:'b1Value', b2:'b2Value'}, c:'aa', d:[1,2]})
  120. *
  121. * expressObject:
  122. * {
  123. * a: '{query.a}',
  124. * b: {
  125. * b1: '{query.b1}',
  126. * b2: '{query.b2}',
  127. * },
  128. * c: 'aa',
  129. * d: [
  130. * '{query.a}',
  131. * '{query.b2}'
  132. * ]
  133. * }
  134. *
  135. * valueObject:
  136. * {
  137. * a: 'aValue',
  138. * b: {
  139. * b1: 'b1Value',
  140. * b2: 'b2Value'
  141. * },
  142. * c: 'aa'
  143. * c: [
  144. * 'aValue',
  145. * 'b2Value'
  146. * ]
  147. * }
  148. *
  149. * 系统会尝试回写
  150. * viewModel.set('query.a', 'aValue')
  151. * viewModel.set('query.b1', 'b1Value')
  152. * viewModel.set('query.b2', 'b2Value')
  153. *
  154. * @param expressObject 含表达式的对象
  155. * @param valueObject 表达式计算完成之后的结果对象
  156. * @param writeFn 写入的方法 (path, value)=>void
  157. */
  158. export function tryWriteObject(expressObject, valueObject, writeFn) {
  159. const trav = (pathPrefix) => {
  160. let parent = expressObject
  161. if (_.size(pathPrefix) > 1) {
  162. parent = _.get(parent, pathPrefix.substring(1))
  163. }
  164. _.forOwn(parent, (value, key) => {
  165. if (_.isPlainObject(value)) {
  166. // 深度递归,对子对象进行求解
  167. trav(pathPrefix + "." + key)
  168. } else if (_.isString(value)) {
  169. // 字符串直接用 calcExpress 表达式求解
  170. if (SIMPLE_RE.test(value)) {
  171. // If we have '{foo}' alone it is a literal 简单表达式
  172. const targetPath = value.substring(1, value.length - 1);
  173. const targetValue = _.get(valueObject, (pathPrefix + "." + key).substr(1))
  174. if (!writeFn) {
  175. console.log(`viewModel.set('${targetPath}', '${targetValue}')`)
  176. } else {
  177. writeFn(targetPath, targetValue)
  178. }
  179. }
  180. } else if (_.isArray(value)) {
  181. _.each(value, (v, idx) => {
  182. if (SIMPLE_RE.test(v)) {
  183. const targetPath = (pathPrefix + "." + key).substr(1) + "[" + idx + "]";
  184. const targetValue = _.get(valueObject, (pathPrefix + "." + key).substr(1) + "[" + idx + "]")
  185. if (!writeFn) {
  186. console.log(`viewModel.set('${targetPath}', '${targetValue}')`)
  187. } else {
  188. writeFn(targetPath, targetValue)
  189. }
  190. }
  191. })
  192. }
  193. })
  194. }
  195. trav("")
  196. }
  197. /**
  198. * 对多个表达式进行求值. 异步回调的方式返回
  199. * {
  200. * a: 1,
  201. * b: '{someBind}',
  202. * c: ['a', 'b', 'c'],
  203. * d: ['a', 'b', '{someBind}'],
  204. * e: {
  205. * y: 1,
  206. * z: 2
  207. * },
  208. * f: {
  209. * y: 1,
  210. * z: '{someBind}'
  211. * }
  212. * }
  213. *
  214. * // Will produce
  215. * {
  216. * b: value,
  217. * d: ['a', 'b', value],
  218. * f: {
  219. * y: 1,
  220. * z: value
  221. * }
  222. * }
  223. * @param viewModel scope.viewModel对象
  224. * @param paramObject 求值对象
  225. */
  226. export function calcObject(viewModel, paramObject) {
  227. // new Ext.app.bind.Multi({a:'1',b:'ddd{query.WH_ID}'},currentScope.viewModel,function(v){console.log(v)},currentScope, {single: true})
  228. return new Promise(resolve => {
  229. const schedule = new Ext.app.bind.Multi(
  230. paramObject,
  231. viewModel,
  232. (ret) => {
  233. schedule.destroy()
  234. // 从 Ext.data.Model 对象转换为 js-object 对象
  235. ret = toPlainObject(ret)
  236. resolve(ret)
  237. },
  238. viewModel,
  239. {single: true})
  240. })
  241. }
  242. /**
  243. * 用于任意组件 Ext.Component 构造时,获取当前组件对应的表格(如果不是 grid.columns 对象就会返回 undefined)
  244. * @param config 组件构造函数传入的 config 配置文件
  245. */
  246. export function getParentGrid(config) {
  247. return config.$initParent?.grid
  248. }
  249. /**
  250. * 动态的为 combo 或 columns.combo 设置下拉框的值
  251. * @param sender 目标对象
  252. * @param config 目标对象的配置(在构造函数之前也可以)
  253. * @param getDictFn 获取字典的方法
  254. * @param bizKey 传入字典的参数
  255. */
  256. export function setComboStore(sender, config, getDictFn, bizKey) {
  257. if (sender.$className === 'Ext.form.field.ComboBox') {
  258. getDictFn(bizKey, (r) => {
  259. if (sender.el?.dom) {
  260. // 异步回传
  261. sender.setStore(new Ext.data.Store(r))
  262. } else {
  263. // 同步回传
  264. config.store = new Ext.data.Store(r)
  265. }
  266. })
  267. return
  268. } else if (sender.xtype === 'gridcolumn') {
  269. const grid = getParentGrid(config)
  270. const {editor, renderer} = config
  271. getDictFn(bizKey, (r) => {
  272. if (sender.rendered) {
  273. // 已经渲染出来了, 用方法进行修改
  274. const editor = sender.getEditor()
  275. if (editor && editor.xtype === 'combo') {
  276. const valueField = r.field[0]
  277. const displayField = r.field[1]
  278. editor.valueField = valueField
  279. editor.setDisplayField(displayField)
  280. editor.setStore(new Ext.data.Store({
  281. field: ['id', 'text'],
  282. data: [
  283. {id: "Y", text: "启用"},
  284. {id: "N", text: "禁用"},
  285. {id: "D", text: "删除"},
  286. ]
  287. }))
  288. }
  289. } else {
  290. // 没有渲染之前,修改 config 即可
  291. if (editor && editor.xtype === 'combo') {
  292. // 带编辑模式
  293. editor.store = new Ext.data.Store(r)
  294. }
  295. }
  296. const renderer = (value, metaData) => {
  297. const valueField = r.field[0]
  298. const displayField = r.field[1]
  299. _.each(r.data, row => {
  300. // 从 valueField 找到要显示的 displayField
  301. if (row[valueField] == value) {
  302. value = row[displayField]
  303. return false
  304. }
  305. })
  306. return value
  307. }
  308. if (sender.rendered) {
  309. // 已经渲染出来了, 对列进行渲染
  310. sender.renderer = renderer
  311. sender.getView().refresh()
  312. } else {
  313. config.renderer = renderer
  314. }
  315. })
  316. return
  317. }
  318. throw new TypeError("无法识别的组件类型")
  319. }
  320. /**
  321. * 调用服务器 Ajax
  322. */
  323. export function invokeServer(url: string, ...args: any[]) {
  324. // @ts-ignore
  325. return ajax.func({
  326. url: url,
  327. method: 'invoke',
  328. args: args
  329. })
  330. }
  331. export function clearViewModelValues(viewModel, propertyName) {
  332. const dd = _.get(viewModel.getData(), propertyName)
  333. _.forOwn(dd, (value, key) => {
  334. viewModel.set(propertyName + '.' + key, '')
  335. })
  336. }
  337. export function reloadGrid(scope, gridRefName) {
  338. scope.refs[gridRefName]?.reload()
  339. }
  340. /**
  341. * 将 Ext.data.Model 对象 (及子属性) 转换为 js.object 对象
  342. */
  343. export function toPlainObject(obj) {
  344. if (obj.isModel) {
  345. obj = obj.data
  346. }
  347. _.forOwn(obj, (v, k) => {
  348. // Ext.data.Model.constructor
  349. if (!v) {
  350. return
  351. }
  352. if (v.isModel) {
  353. v = v.data
  354. }
  355. if (typeof v === 'object') {
  356. obj[k] = toPlainObject(v)
  357. } else {
  358. obj[k] = v
  359. }
  360. })
  361. return obj
  362. }
  363. export function confirm(msg, sender?): Promise<void> {
  364. return new Promise<void>(resolve => {
  365. const scope = lookupScope(sender)
  366. const config: any = {
  367. title: '请确认',
  368. icon: Ext.Msg.QUESTION,
  369. modal: true,
  370. animateTarget: sender,
  371. // constrainHeader: true,
  372. // constrain: true,
  373. // constrainTo: scope._handle?.el?.dom || Ext.getBody(),
  374. items: [
  375. {
  376. html: _.escape(msg)
  377. }
  378. ],
  379. buttons: [
  380. {
  381. xtype: 'button', text: '确定', iconCls: 'x-fa fa-check',
  382. handler() {
  383. resolve()
  384. win.close()
  385. }
  386. },
  387. {
  388. xtype: 'button', text: '取消', iconCls: 'x-fa fa-times',
  389. handler() {
  390. win.close()
  391. }
  392. }
  393. ]
  394. }
  395. if (scope?._handle) {
  396. config.constrain = true
  397. }
  398. const win = new Ext.Window(config);
  399. if (scope?._handle) {
  400. scope?._handle?.add(win)
  401. }
  402. win.show()
  403. })
  404. }
  405. class SystemEventFu {
  406. @Lib({
  407. title: '弹出确认对话框,回答 YES 之后调用某方法',
  408. author: '罗一帆',
  409. createAt: '2021-07-06',
  410. updateAt: '2021-07-06',
  411. type: 'system',
  412. category: '对话框',
  413. args: [
  414. {
  415. type: 'string',
  416. title: '对话框的确认文字',
  417. name: 'text',
  418. },
  419. {
  420. type: 'event',
  421. title: '确认之后调用的方法',
  422. name: 'fn',
  423. allowEmpty: true,
  424. }
  425. ]
  426. })
  427. confirm(text, fn) {
  428. return function (sender) {
  429. const scope = lookupScope(sender)
  430. const msg = calcExpress(scope.viewModel.data, text)
  431. confirm(msg, sender).then(() => {
  432. fn.call(scope, sender)
  433. })
  434. }
  435. }
  436. @Lib({
  437. title: '查询表单,如果 url 为空值,就取消查询',
  438. author: '罗一帆',
  439. createAt: '2021-07-06',
  440. updateAt: '2021-07-06',
  441. type: 'system',
  442. category: '表单',
  443. args: [
  444. {
  445. type: 'string',
  446. title: 'groovy 服务路径',
  447. name: 'invokeUrl',
  448. },
  449. {
  450. type: 'object',
  451. title: 'invoke 参数的 lookup 表达式, 如果不填 默认提交所有的 viewModel.data',
  452. name: 'invokeParam',
  453. allowEmpty: true,
  454. },
  455. {
  456. type: 'string',
  457. title: '服务读取后,数据的回写位置,可以是 scope.XX / system.XX / string / lookup表达式',
  458. name: 'writeTarget',
  459. allowEmpty: true,
  460. }
  461. ]
  462. })
  463. loadForm(invokeUrl: string, invokeParam: any, writeTarget: any) {
  464. return function (sender) {
  465. if (!invokeUrl) {
  466. return
  467. }
  468. const scope = lookupScope(sender)
  469. scope.setLoading(true)
  470. let data = scope.viewModel.data
  471. if (invokeParam) {
  472. data = calcObjectFlat(data, invokeParam)
  473. }
  474. invokeServer(invokeUrl, data).then(res => {
  475. if (res.success) {
  476. if (typeof writeTarget === "string") {
  477. _.forOwn(res.data, (v, k) => {
  478. scope.viewModel.set(writeTarget + "." + k, v)
  479. })
  480. } else if (typeof writeTarget === 'function') {
  481. writeTarget.call(scope, res.data)
  482. } else if (typeof writeTarget === 'object') {
  483. const ret = calcObjectFlat(res.data, writeTarget)
  484. _.forOwn(ret, (v, k) => {
  485. scope.viewModel.set(k, v)
  486. })
  487. }
  488. } else {
  489. showErrorDialog(res.msg || '未知错误', sender)
  490. }
  491. }).catch((e) => {
  492. const msg = e.response?.data?.msg
  493. showErrorDialog(msg || e.toString(), sender)
  494. }).finally(() => {
  495. scope.setLoading(false)
  496. })
  497. }
  498. }
  499. @Lib({
  500. title: '提交(不做校验、不关闭窗体)',
  501. author: '罗一帆',
  502. createAt: '2021-07-02',
  503. updateAt: '2021-07-02',
  504. type: 'system',
  505. category: '表单',
  506. args: [
  507. {
  508. type: 'string',
  509. title: 'groovy 服务路径',
  510. name: 'groovyUrl',
  511. },
  512. {
  513. type: 'object',
  514. title: '参数的 lookup 表达式, 如果不填 默认提交所有的 viewModel.data',
  515. name: 'arg0',
  516. allowEmpty: true,
  517. },
  518. {
  519. type: 'event',
  520. title: '成功后的回调',
  521. name: 'successCallback',
  522. allowEmpty: true,
  523. }
  524. ]
  525. })
  526. commit(groovyUrl: string, arg0: any, successCallback) {
  527. return function (sender) {
  528. const scope = lookupScope(sender)
  529. scope.setLoading(true)
  530. let data = scope.viewModel.data
  531. if (arg0) {
  532. data = calcObjectFlat(data, arg0)
  533. }
  534. invokeServer(groovyUrl, data).then(res => {
  535. if (res.success) {
  536. if (res.msg) {
  537. msg(res.msg)
  538. }
  539. if (typeof successCallback === 'function') {
  540. successCallback.call(scope, sender, res.data)
  541. }
  542. } else {
  543. showErrorDialog(res.msg || '未知错误', sender)
  544. }
  545. }).catch((e) => {
  546. const msg = e.response?.data?.msg
  547. showErrorDialog(msg || e.toString(), sender)
  548. }).finally(() => {
  549. scope.setLoading(false)
  550. })
  551. }
  552. }
  553. @Lib({
  554. title: '提交表单',
  555. author: '罗一帆',
  556. createAt: '2021-07-02',
  557. updateAt: '2021-07-02',
  558. type: 'system',
  559. category: '表单',
  560. args: [
  561. {
  562. type: 'string',
  563. title: 'groovy 服务路径',
  564. name: 'groovyUrl',
  565. },
  566. {
  567. type: 'object',
  568. title: '参数的 lookup 表达式, 如果不填 默认提交所有的 viewModel.data',
  569. name: 'arg0',
  570. allowEmpty: true,
  571. }
  572. ]
  573. })
  574. formCommit(groovyUrl: string, arg0: any) {
  575. return function (sender) {
  576. const scope = lookupScope(sender)
  577. const form = scope.down('form')
  578. if (form) {
  579. // 如果下级有表单,就做表单校验
  580. const valid = form.isValid()
  581. if (!valid) {
  582. return
  583. }
  584. }
  585. scope.setLoading(true)
  586. let data = scope.viewModel.data
  587. if (arg0) {
  588. data = calcObjectFlat(data, arg0)
  589. }
  590. invokeServer(groovyUrl, data).then(res => {
  591. if (res.success) {
  592. if (res.msg) {
  593. msg(res.msg)
  594. }
  595. scope.dialogSuccess(res)
  596. } else {
  597. showErrorDialog(res.msg || '未知错误', sender)
  598. }
  599. }).catch((e) => {
  600. const msg = e.response?.data?.msg
  601. showErrorDialog(msg || e.toString(), sender)
  602. }).finally(() => {
  603. scope.setLoading(false)
  604. })
  605. }
  606. }
  607. @Lib({
  608. title: '对话框成功回调',
  609. author: '罗一帆',
  610. createAt: '2021-07-02',
  611. updateAt: '2021-07-02',
  612. type: 'system',
  613. category: '对话框',
  614. args: []
  615. })
  616. dialogSuccess() {
  617. debugger
  618. }
  619. @Lib({
  620. title: '清空 viewModel 某个属性',
  621. author: '罗一帆',
  622. createAt: '2021-07-02',
  623. updateAt: '2021-07-02',
  624. type: 'system',
  625. category: '表单',
  626. args: [
  627. {
  628. type: 'viewModel',
  629. title: 'propertyName 属性路径',
  630. name: 'propertyName',
  631. }
  632. ]
  633. })
  634. clearViewModelValues(propertyName: string) {
  635. return function (sender) {
  636. const scope = lookupScope(sender)
  637. clearViewModelValues(scope.viewModel, propertyName)
  638. }
  639. }
  640. @Lib({
  641. title: '清空 viewModel 某个属性,并刷新表格',
  642. author: '罗一帆',
  643. createAt: '2021-07-02',
  644. updateAt: '2021-07-02',
  645. type: 'system',
  646. category: '表单',
  647. args: [
  648. {
  649. type: 'viewModel',
  650. title: 'propertyName 属性路径',
  651. name: 'propertyName',
  652. },
  653. {
  654. type: 'refs',
  655. title: 'gridRef 表格引用名',
  656. allowEmpty: true,
  657. name: 'gridRefName',
  658. }
  659. ]
  660. })
  661. clearViewModelReloadGrid(propertyName: string, gridRefName?: string) {
  662. return function (sender) {
  663. const scope = lookupScope(sender)
  664. clearViewModelValues(scope.viewModel, propertyName)
  665. if (!gridRefName) {
  666. scope.down('grid')?.reload()
  667. } else {
  668. scope.refs[gridRefName]?.reload()
  669. }
  670. }
  671. }
  672. @Lib({
  673. title: '刷新表格',
  674. author: '罗一帆',
  675. createAt: '2021-07-02',
  676. updateAt: '2021-07-02',
  677. type: 'system',
  678. category: '表单',
  679. args: [
  680. {
  681. type: 'refs',
  682. title: 'gridRef 表格引用名, 不填写的情况下刷新所有',
  683. allowEmpty: true,
  684. name: 'gridRefName',
  685. }
  686. ]
  687. })
  688. reloadGrid(gridRefName: string) {
  689. return function (sender) {
  690. const scope = lookupScope(sender)
  691. if (!gridRefName) {
  692. scope.down('grid')?.reload()
  693. } else {
  694. scope.refs[gridRefName]?.reload()
  695. }
  696. }
  697. }
  698. @Lib({
  699. title: '显示对话框',
  700. author: '罗一帆',
  701. createAt: '2021-07-02',
  702. updateAt: '2021-07-02',
  703. type: 'system',
  704. category: '对话框',
  705. args: [
  706. {
  707. type: 'module',
  708. title: '业务模块名',
  709. name: 'url',
  710. },
  711. {
  712. type: 'object',
  713. title: '参数数据 lookup 表达式',
  714. name: 'lookupForData',
  715. allowEmpty: true,
  716. },
  717. {
  718. type: 'event',
  719. title: '成功回调',
  720. name: 'successCallback',
  721. allowEmpty: true,
  722. }
  723. ]
  724. })
  725. showDialog(url: string, lookupForData: any, successCallback) {
  726. return function (sender) {
  727. const scope = lookupScope(sender)
  728. const data = scope.viewModel.data
  729. const param = calcObjectFlat(data, lookupForData)
  730. // @ts-ignore
  731. require([url], (module) => {
  732. const ScopeClass = module.default
  733. const scope = new ScopeClass()
  734. scope.success = successCallback
  735. scope.showDialog(sender, {}, {data: param})
  736. })
  737. }
  738. }
  739. @Lib({
  740. title: '弹出查找框(不借助 search)',
  741. author: '罗一帆',
  742. createAt: '2021-07-02',
  743. updateAt: '2021-07-02',
  744. type: 'system',
  745. category: '对话框',
  746. args: [
  747. {
  748. type: 'module',
  749. title: '模块名 (WidgetDialog)',
  750. name: 'widgetUrl',
  751. },
  752. {
  753. type: 'object',
  754. title: 'lookup 映射关系',
  755. name: 'lookupSetting',
  756. allowEmpty: true,
  757. }
  758. ]
  759. })
  760. showWidget(widgetUrl, lookup) {
  761. return function (sender, queryValue) {
  762. showWidget(widgetUrl, lookup, sender, queryValue)
  763. }
  764. }
  765. @Lib({
  766. title: '根据 lookup 清空 viewModel',
  767. author: '罗一帆',
  768. createAt: '2021-07-05',
  769. updateAt: '2021-07-05',
  770. type: 'system',
  771. category: '表单',
  772. args: [
  773. {
  774. type: 'viewModel',
  775. title: 'lookup 设值',
  776. name: 'lookup',
  777. },
  778. ]
  779. })
  780. clearViewModelByLookup(lookup) {
  781. return function (sender) {
  782. clearViewModelByLookup(sender, lookup)
  783. }
  784. }
  785. @Lib({
  786. title: '关闭对话框',
  787. author: '罗一帆',
  788. createAt: '2021-07-05',
  789. updateAt: '2021-07-05',
  790. type: 'system',
  791. category: '对话框',
  792. args: [
  793. {
  794. type: 'event',
  795. title: '对话框的返回值回调',
  796. name: 'callBack',
  797. },
  798. ]
  799. })
  800. closeMe(callBack) {
  801. return function (sender) {
  802. const scope = lookupScope(sender)
  803. scope.close()
  804. if (callBack) {
  805. callBack.call(sender)
  806. }
  807. }
  808. }
  809. }
  810. export function clearViewModelByLookup(sender, lookup) {
  811. if (_.isPlainObject(lookup)) {
  812. const parentScope = lookupScope(sender)
  813. _.forOwn(lookup, (value, key) => {
  814. if (SIMPLE_RE.test(value)) {
  815. // '{foo}' 简单表达式
  816. const path = value.substring(1, value.length - 1);
  817. if (path !== 'queryValue') {
  818. parentScope.viewModel.set(path, '')
  819. }
  820. }
  821. })
  822. }
  823. }
  824. export function showWidget(widgetUrl, lookup, sender, queryValue, vjson = {}) {
  825. const parentScope = lookupScope(sender)
  826. const me = sender
  827. // @ts-ignore
  828. require([widgetUrl], (widgetScope) => {
  829. const WidgetScopeClass = widgetScope.default
  830. widgetScope = new WidgetScopeClass()
  831. // 传递进 widget.model 的数据
  832. const widgetDialogData = calcObjectFlat({
  833. queryValue: queryValue,
  834. ...parentScope.viewModel.data
  835. }, lookup)
  836. widgetScope.parentScope = parentScope
  837. widgetScope.searchWidgetSuccess = (data) => {
  838. if (typeof lookup === 'string') {
  839. // lookup 是字符串的情况下,就是取某个列作为 value 值
  840. me.setValue(data[lookup])
  841. return
  842. }
  843. /**
  844. * lookup: {
  845. * // 扩展到 viewModel 的值做更改
  846. * WH_CODE: "{queryValue}",
  847. * WH_NAME: "{query.WH_NAME}",
  848. * }
  849. */
  850. if (_.isPlainObject(lookup)) {
  851. const parentScope = lookupScope(sender)
  852. tryWriteObject(lookup, data, (path, value) => {
  853. if (path === 'queryValue') {
  854. me.setValue(value)
  855. } else {
  856. parentScope.viewModel.set(path, value)
  857. }
  858. }
  859. )
  860. }
  861. return true
  862. }
  863. widgetScope.showDialog(sender, vjson, {data: widgetDialogData})
  864. })
  865. }
  866. /**
  867. * 停止事件的默认行为
  868. * @param e
  869. */
  870. export function stopEvent(e) {
  871. e.preventDefault()
  872. e.stopPropagation()
  873. // @ts-ignore
  874. window.event.cancelBubble = true
  875. e.returnValue = false;
  876. e.cancelBubble = true;
  877. }