c0828fb1fdde559e68573e7b475258f27097b39d.svn-base 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352
  1. <template>
  2. <a-modal
  3. :title="title"
  4. :width="1000"
  5. :visible="visible"
  6. :confirmLoading="confirmLoading"
  7. @ok="handleOk"
  8. @cancel="handleCancel"
  9. cancelText="关闭">
  10. <a-spin :spinning="confirmLoading">
  11. <a-form-model ref="form" :model="model" :rules="validatorRules">
  12. <a-form-model-item :labelCol="labelCol" :wrapperCol="wrapperCol" label="规则名称" prop="ruleName" >
  13. <a-input placeholder="请输入规则名称" v-model="model.ruleName"/>
  14. </a-form-model-item>
  15. <a-form-model-item :labelCol="labelCol" :wrapperCol="wrapperCol" label="规则Code" prop="ruleCode">
  16. <a-input placeholder="请输入规则Code" v-model="model.ruleCode"/>
  17. </a-form-model-item>
  18. <a-form-model-item :labelCol="labelCol" :wrapperCol="wrapperCol" label="规则描述" prop="ruleDescription">
  19. <a-textarea placeholder="请输入规则描述" v-model="model.ruleDescription"/>
  20. </a-form-model-item>
  21. </a-form-model>
  22. <!-- 规则设计 -->
  23. <a-tabs v-model="tabs.activeKey">
  24. <a-tab-pane tab="局部规则" :key="tabs.design.key" forceRender>
  25. <a-alert type="info" showIcon message="局部规则按照你输入的位数有序的校验。"/>
  26. <j-editable-table ref="designTable" dragSort rowNumber :maxHeight="240" :columns="tabs.design.columns" :dataSource="tabs.design.dataSource" style="margin-top: 8px;">
  27. <template #action="props">
  28. <my-action-button :rowEvent="props"/>
  29. </template>
  30. </j-editable-table>
  31. </a-tab-pane>
  32. <a-tab-pane tab="全局规则" :key="tabs.global.key" forceRender>
  33. <j-editable-table ref="globalTable" dragSort rowNumber actionButton :maxHeight="240" :columns="tabs.global.columns" :dataSource="tabs.global.dataSource">
  34. <template #actionButtonAfter>
  35. <a-alert type="info" showIcon message="全局规则可校验用户输入的所有字符;全局规则的优先级比局部规则的要高。" style="margin-bottom: 8px;"/>
  36. </template>
  37. <template #action="props">
  38. <my-action-button :rowEvent="props" allowEmpty/>
  39. </template>
  40. </j-editable-table>
  41. </a-tab-pane>
  42. </a-tabs>
  43. </a-spin>
  44. </a-modal>
  45. </template>
  46. <script>
  47. import pick from 'lodash.pick'
  48. import { httpAction } from '@/api/manage'
  49. import { validateDuplicateValue, alwaysResolve, failedSymbol } from '@/utils/util'
  50. import { FormTypes } from '@/utils/JEditableTableUtil'
  51. import JEditableTable from '@comp/jeecg/JEditableTable'
  52. export default {
  53. name: 'SysCheckRuleModal',
  54. components: {
  55. JEditableTable,
  56. 'my-action-button': {
  57. props: { rowEvent: Object, allowEmpty: Boolean },
  58. methods: {
  59. confirmIsShow() {
  60. const { index, allValues: { inputValues } } = this.rowEvent
  61. let value = inputValues[index]
  62. return value.digits || value.pattern
  63. },
  64. handleLineAdd() {
  65. const { target } = this.rowEvent
  66. target.add()
  67. },
  68. handleLineDelete() {
  69. const { rowId, target } = this.rowEvent
  70. target.removeRows(rowId)
  71. },
  72. renderDeleteButton() {
  73. if (this.allowEmpty || this.rowEvent.index > 0) {
  74. if (this.confirmIsShow()) {
  75. return (
  76. <a-popconfirm title="确定要删除吗?" onConfirm={this.handleLineDelete}>
  77. <a-button icon="minus"/>
  78. </a-popconfirm>
  79. )
  80. } else {
  81. return (
  82. <a-button icon="minus" onClick={this.handleLineDelete}/>
  83. )
  84. }
  85. }
  86. return ''
  87. },
  88. },
  89. render() {
  90. return (
  91. <div>
  92. <a-button onClick={this.handleLineAdd} icon="plus"/>
  93. &nbsp;
  94. {this.renderDeleteButton()}
  95. </div>
  96. )
  97. }
  98. }
  99. },
  100. data() {
  101. return {
  102. title: '操作',
  103. visible: false,
  104. model: {},
  105. labelCol: {
  106. xs: { span: 24 },
  107. sm: { span: 5 },
  108. },
  109. wrapperCol: {
  110. xs: { span: 24 },
  111. sm: { span: 16 },
  112. },
  113. confirmLoading: false,
  114. validatorRules: {
  115. ruleName: [{required: true, message: '请输入规则名称!'}],
  116. ruleCode: [
  117. {required: true, message: '请输入规则Code!'},
  118. {validator: (rule, value, callback) => validateDuplicateValue('sys_check_rule', 'rule_code', value, this.model.id, callback)}
  119. ],
  120. },
  121. tabs: {
  122. activeKey: 'design',
  123. global: {
  124. key: 'global',
  125. columns: [
  126. {
  127. title: '优先级',
  128. key: 'priority',
  129. width: '15%',
  130. type: FormTypes.select,
  131. defaultValue: '1',
  132. options: [
  133. { title: '优先运行', value: '1' },
  134. { title: '最后运行', value: '0' },
  135. ],
  136. validateRules: []
  137. },
  138. {
  139. title: '规则(正则表达式)',
  140. key: 'pattern',
  141. width: '50%',
  142. type: FormTypes.input,
  143. validateRules: [
  144. { required: true, message: '规则不能为空' },
  145. { handler: this.validatePatternHandler },
  146. ]
  147. },
  148. {
  149. title: '提示文本',
  150. key: 'message',
  151. width: '20%',
  152. type: FormTypes.input,
  153. validateRules: [
  154. { required: true, message: '${title}不能为空' },
  155. ]
  156. },
  157. {
  158. title: '操作',
  159. key: 'action',
  160. width: '15%',
  161. slotName: 'action',
  162. type: FormTypes.slot
  163. }
  164. ],
  165. dataSource: [],
  166. },
  167. design: {
  168. key: 'design',
  169. columns: [
  170. {
  171. title: '位数',
  172. key: 'digits',
  173. width: '15%',
  174. type: FormTypes.inputNumber,
  175. validateRules: [
  176. { required: true, message: '${title}不能为空' },
  177. { pattern: /^[1-9]\d*$/, message: '请输入零以上的正整数' },
  178. ]
  179. },
  180. {
  181. title: '规则(正则表达式)',
  182. key: 'pattern',
  183. width: '50%',
  184. type: FormTypes.input,
  185. validateRules: [
  186. { required: true, message: '规则不能为空' },
  187. { handler: this.validatePatternHandler }
  188. ]
  189. },
  190. {
  191. title: '提示文本',
  192. key: 'message',
  193. width: '20%',
  194. type: FormTypes.input,
  195. validateRules: [
  196. { required: true, message: '${title}不能为空' },
  197. ]
  198. },
  199. {
  200. title: '操作',
  201. key: 'action',
  202. width: '15%',
  203. slotName: 'action',
  204. type: FormTypes.slot
  205. },
  206. ],
  207. dataSource: [],
  208. }
  209. },
  210. url: {
  211. add: '/sys/checkRule/add',
  212. edit: '/sys/checkRule/edit',
  213. },
  214. }
  215. },
  216. created() {
  217. },
  218. methods: {
  219. validatePatternHandler(type, value, row, column, callback, target) {
  220. if (type === 'blur' || type === 'getValues') {
  221. try {
  222. new RegExp(value)
  223. callback(true)
  224. } catch (e) {
  225. callback(false, '请输入正确的正则表达式')
  226. }
  227. } else {
  228. callback(true) // 不填写或者填写 null 代表不进行任何操作
  229. }
  230. },
  231. add() {
  232. this.edit({})
  233. },
  234. edit(record) {
  235. this.tabs.activeKey = this.tabs.design.key
  236. this.tabs.global.dataSource = []
  237. this.tabs.design.dataSource = [{ digits: '', pattern: '', message: '' }]
  238. this.visible = true
  239. this.$nextTick(() => {
  240. this.$refs.form.resetFields()
  241. this.model = Object.assign({}, record)
  242. // 子表数据
  243. let ruleJson = this.model.ruleJson
  244. if (ruleJson) {
  245. let ruleList = JSON.parse(ruleJson)
  246. // 筛选出全局规则和局部规则
  247. let global = [], design = [], priority = '1'
  248. ruleList.forEach(rule => {
  249. if (rule.digits === '*') {
  250. global.push(Object.assign(rule, { priority }))
  251. } else {
  252. priority = '0'
  253. design.push(rule)
  254. }
  255. })
  256. this.tabs.global.dataSource = global
  257. this.tabs.design.dataSource = design
  258. }
  259. })
  260. },
  261. close() {
  262. this.$emit('close')
  263. this.visible = false
  264. },
  265. handleOk() {
  266. Promise.all([
  267. // 主表单校验
  268. alwaysResolve(new Promise((resolve, reject) => {
  269. this.$refs.form.validate((ok, err) => ok ? resolve(this.model) : reject(err))
  270. })),
  271. // 局部规则子表校验
  272. alwaysResolve(this.$refs.designTable.getValuesPromise),
  273. // 全局规则子表校验
  274. alwaysResolve(this.$refs.globalTable.getValuesPromise),
  275. ]).then(results => {
  276. let [mainResult, designResult, globalResult] = results
  277. if (mainResult.type === failedSymbol) {
  278. return Promise.reject('主表校验未通过')
  279. } else if (designResult.type === failedSymbol) {
  280. this.tabs.activeKey = this.tabs.design.key
  281. return Promise.reject('局部规则子表校验未通过')
  282. } else if (globalResult.type === failedSymbol) {
  283. this.tabs.activeKey = this.tabs.global.key
  284. return Promise.reject('全局规则子表校验未通过')
  285. } else {
  286. // 所有校验已通过,这一步是整合数据
  287. let mainValues = mainResult.data, globalValues = globalResult.data, designValues = designResult.data
  288. // 整合两个子表的数据
  289. let firstGlobal = [], afterGlobal = []
  290. globalValues.forEach(v => {
  291. v.digits = '*'
  292. if (v.priority === '1') {
  293. firstGlobal.push(v)
  294. } else {
  295. afterGlobal.push(v)
  296. }
  297. })
  298. let concatValues = firstGlobal.concat(designValues).concat(afterGlobal)
  299. let subValues = concatValues.map(i => pick(i, 'digits', 'pattern', 'message'))
  300. // 生成 formData,用于传入后台
  301. let ruleJson = JSON.stringify(subValues)
  302. let formData = Object.assign(this.model, mainValues, { ruleJson })
  303. // 判断请求方式和请求地址,并发送请求
  304. let method = 'post', httpUrl = this.url.add
  305. if (this.model.id) {
  306. //method = 'put'
  307. httpUrl = this.url.edit
  308. }
  309. this.confirmLoading = true
  310. return httpAction(httpUrl, formData, method)
  311. }
  312. }).then((res) => {
  313. if (res.success) {
  314. this.$message.success(res.message)
  315. this.$emit('ok')
  316. this.close()
  317. } else {
  318. this.$message.warning(res.message)
  319. }
  320. }).catch(e => {
  321. console.error(e)
  322. }).finally(() => {
  323. this.confirmLoading = false
  324. })
  325. },
  326. handleCancel() {
  327. this.close()
  328. },
  329. }
  330. }
  331. </script>
  332. <style lang="less" scoped></style>