menu.data.ts 9.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409
  1. import { BasicColumn } from '/@/components/Table';
  2. import { FormSchema } from '/@/components/Table';
  3. import { h } from 'vue';
  4. import { Icon } from '/@/components/Icon';
  5. import { duplicateCheck } from '../user/user.api';
  6. import { ajaxGetDictItems } from './menu.api';
  7. import { render } from '/@/utils/common/renderUtils';
  8. import { Select } from 'ant-design-vue';
  9. import { rules } from '/@/utils/helper/validator';
  10. const isDir = (type) => type === 0;
  11. const isMenu = (type) => type === 1;
  12. const isButton = (type) => type === 2;
  13. // 定义可选择的组件类型
  14. export enum ComponentTypes {
  15. Default = 'layouts/default/index',
  16. IFrame = 'sys/iframe/FrameBlank',
  17. }
  18. export const columns: BasicColumn[] = [
  19. {
  20. title: '菜单名称',
  21. dataIndex: 'name',
  22. width: 200,
  23. align: 'left',
  24. },
  25. {
  26. title: '菜单类型',
  27. dataIndex: 'menuType',
  28. width: 150,
  29. customRender: ({ text }) => {
  30. return render.renderDict(text, 'menu_type');
  31. },
  32. },
  33. {
  34. title: '图标',
  35. dataIndex: 'icon',
  36. width: 50,
  37. customRender: ({ record }) => {
  38. return h(Icon, { icon: record.icon });
  39. },
  40. },
  41. {
  42. title: '组件',
  43. dataIndex: 'component',
  44. align: 'left',
  45. width: 150,
  46. },
  47. {
  48. title: '路径',
  49. dataIndex: 'url',
  50. align: 'left',
  51. width: 150,
  52. },
  53. {
  54. title: '排序',
  55. dataIndex: 'sortNo',
  56. width: 50,
  57. },
  58. ];
  59. export const searchFormSchema: FormSchema[] = [
  60. {
  61. field: 'name',
  62. label: '菜单名称',
  63. component: 'Input',
  64. colProps: { span: 8 },
  65. },
  66. ];
  67. export const formSchema: FormSchema[] = [
  68. {
  69. label: 'id',
  70. field: 'id',
  71. component: 'Input',
  72. show: false,
  73. },
  74. {
  75. field: 'menuType',
  76. label: '菜单类型',
  77. component: 'RadioButtonGroup',
  78. defaultValue: 0,
  79. componentProps: ({ formActionType }) => {
  80. return {
  81. options: [
  82. { label: '一级菜单', value: 0 },
  83. { label: '子菜单', value: 1 },
  84. { label: '按钮/权限', value: 2 },
  85. ],
  86. onChange: (e) => {
  87. const { updateSchema, clearValidate } = formActionType;
  88. const label = isButton(e) ? '按钮/权限' : '菜单名称';
  89. //清除校验
  90. clearValidate();
  91. updateSchema([
  92. {
  93. field: 'name',
  94. label: label,
  95. },
  96. {
  97. field: 'url',
  98. required: !isButton(e),
  99. },
  100. ]);
  101. },
  102. };
  103. },
  104. },
  105. {
  106. field: 'name',
  107. label: '菜单名称',
  108. component: 'Input',
  109. required: true,
  110. },
  111. {
  112. field: 'parentId',
  113. label: '上级菜单',
  114. component: 'TreeSelect',
  115. required: true,
  116. componentProps: {
  117. replaceFields: {
  118. title: 'name',
  119. key: 'id',
  120. value: 'id',
  121. },
  122. dropdownStyle: {
  123. maxHeight: '50vh',
  124. },
  125. getPopupContainer: (node) => node.parentNode,
  126. },
  127. ifShow: ({ values }) => !isDir(values.menuType),
  128. },
  129. {
  130. field: 'url',
  131. label: '访问路径',
  132. component: 'Input',
  133. required: true,
  134. ifShow: ({ values }) => !(values.component === ComponentTypes.IFrame && values.internalOrExternal) && values.menuType !== 2,
  135. dynamicRules: ({ model, schema }) => {
  136. return rules.duplicateCheckRule('sys_permission', 'url', model, schema, true);
  137. },
  138. },
  139. {
  140. field: 'component',
  141. label: '前端组件',
  142. component: 'Input',
  143. componentProps: {
  144. placeholder: '请输入前端组件',
  145. },
  146. required: true,
  147. ifShow: ({ values }) => !isButton(values.menuType),
  148. },
  149. {
  150. field: 'componentName',
  151. label: '组件名称',
  152. component: 'Input',
  153. componentProps: {
  154. placeholder: '请输入组件名称',
  155. },
  156. helpMessage: [
  157. '此处名称应和vue组件的name属性保持一致。',
  158. '组件名称不能重复,主要用于路由缓存功能。',
  159. '如果组件名称和vue组件的name属性不一致,则会导致路由缓存失效。',
  160. '非必填,留空则会根据访问路径自动生成。',
  161. ],
  162. defaultValue: '',
  163. ifShow: ({ values }) => !isButton(values.menuType),
  164. },
  165. {
  166. field: 'frameSrc',
  167. label: 'Iframe地址',
  168. component: 'Input',
  169. rules: [
  170. { required: true, message: '请输入Iframe地址' },
  171. { type: 'url', message: '请输入正确的url地址' },
  172. ],
  173. ifShow: ({ values }) => !isButton(values.menuType) && values.component === ComponentTypes.IFrame,
  174. },
  175. {
  176. field: 'redirect',
  177. label: '默认跳转地址',
  178. component: 'Input',
  179. ifShow: ({ values }) => isDir(values.menuType),
  180. },
  181. {
  182. field: 'perms',
  183. label: '授权标识',
  184. component: 'Input',
  185. ifShow: ({ values }) => isButton(values.menuType),
  186. dynamicRules: ({ model }) => {
  187. return [
  188. {
  189. required: false,
  190. validator: (_, value) => {
  191. return new Promise((resolve, reject) => {
  192. let params = {
  193. tableName: 'sys_permission',
  194. fieldName: 'perms',
  195. fieldVal: value,
  196. dataId: model.id,
  197. };
  198. duplicateCheck(params)
  199. .then((res) => {
  200. res.success ? resolve() : reject(res.message || '校验失败');
  201. })
  202. .catch((err) => {
  203. reject(err.message || '校验失败');
  204. });
  205. });
  206. },
  207. },
  208. ];
  209. },
  210. },
  211. {
  212. field: 'permsType',
  213. label: '授权策略',
  214. component: 'RadioGroup',
  215. defaultValue: '1',
  216. helpMessage: ['可见/可访问(授权后可见/可访问)', '可编辑(未授权时禁用)'],
  217. componentProps: {
  218. options: [
  219. { label: '可见/可访问', value: '1' },
  220. { label: '可编辑', value: '2' },
  221. ],
  222. },
  223. ifShow: ({ values }) => isButton(values.menuType),
  224. },
  225. {
  226. field: 'status',
  227. label: '状态',
  228. component: 'RadioGroup',
  229. defaultValue: '1',
  230. componentProps: {
  231. options: [
  232. { label: '有效', value: '1' },
  233. { label: '无效', value: '0' },
  234. ],
  235. },
  236. ifShow: ({ values }) => isButton(values.menuType),
  237. },
  238. {
  239. field: 'icon',
  240. label: '菜单图标',
  241. component: 'IconPicker',
  242. ifShow: ({ values }) => !isButton(values.menuType),
  243. },
  244. {
  245. field: 'sortNo',
  246. label: '排序',
  247. component: 'InputNumber',
  248. defaultValue: 1,
  249. ifShow: ({ values }) => !isButton(values.menuType),
  250. },
  251. {
  252. field: 'route',
  253. label: '是否路由菜单',
  254. component: 'Switch',
  255. defaultValue: true,
  256. componentProps: {
  257. checkedChildren: '是',
  258. unCheckedChildren: '否',
  259. },
  260. ifShow: ({ values }) => !isButton(values.menuType),
  261. },
  262. {
  263. field: 'hidden',
  264. label: '隐藏路由',
  265. component: 'Switch',
  266. defaultValue: 0,
  267. componentProps: {
  268. checkedChildren: '是',
  269. unCheckedChildren: '否',
  270. },
  271. ifShow: ({ values }) => !isButton(values.menuType),
  272. },
  273. {
  274. field: 'hideTab',
  275. label: '隐藏Tab',
  276. component: 'Switch',
  277. defaultValue: 0,
  278. componentProps: {
  279. checkedChildren: '是',
  280. unCheckedChildren: '否',
  281. },
  282. ifShow: ({ values }) => !isButton(values.menuType),
  283. },
  284. {
  285. field: 'keepAlive',
  286. label: '是否缓存路由',
  287. component: 'Switch',
  288. defaultValue: false,
  289. componentProps: {
  290. checkedChildren: '是',
  291. unCheckedChildren: '否',
  292. },
  293. ifShow: ({ values }) => !isButton(values.menuType),
  294. },
  295. {
  296. field: 'alwaysShow',
  297. label: '聚合路由',
  298. component: 'Switch',
  299. defaultValue: false,
  300. componentProps: {
  301. checkedChildren: '是',
  302. unCheckedChildren: '否',
  303. },
  304. ifShow: ({ values }) => !isButton(values.menuType),
  305. },
  306. {
  307. field: 'internalOrExternal',
  308. label: '打开方式',
  309. component: 'Switch',
  310. defaultValue: false,
  311. componentProps: {
  312. checkedChildren: '外部',
  313. unCheckedChildren: '内部',
  314. },
  315. ifShow: ({ values }) => !isButton(values.menuType),
  316. },
  317. ];
  318. export const dataRuleColumns: BasicColumn[] = [
  319. {
  320. title: '规则名称',
  321. dataIndex: 'ruleName',
  322. width: 150,
  323. },
  324. {
  325. title: '规则字段',
  326. dataIndex: 'ruleColumn',
  327. width: 100,
  328. },
  329. {
  330. title: '规则值',
  331. dataIndex: 'ruleValue',
  332. width: 100,
  333. },
  334. ];
  335. export const dataRuleSearchFormSchema: FormSchema[] = [
  336. {
  337. field: 'ruleName',
  338. label: '规则名称',
  339. component: 'Input',
  340. colProps: { span: 6 },
  341. },
  342. {
  343. field: 'ruleValue',
  344. label: '规则值',
  345. component: 'Input',
  346. colProps: { span: 6 },
  347. },
  348. ];
  349. export const dataRuleFormSchema: FormSchema[] = [
  350. {
  351. label: 'id',
  352. field: 'id',
  353. component: 'Input',
  354. show: false,
  355. },
  356. {
  357. field: 'ruleName',
  358. label: '规则名称',
  359. component: 'Input',
  360. required: true,
  361. },
  362. {
  363. field: 'ruleColumn',
  364. label: '规则字段',
  365. component: 'Input',
  366. ifShow: ({ values }) => {
  367. return values.ruleConditions !== 'USE_SQL_RULES';
  368. },
  369. },
  370. {
  371. field: 'ruleConditions',
  372. label: '条件规则',
  373. required: true,
  374. component: 'ApiSelect',
  375. componentProps: {
  376. api: ajaxGetDictItems,
  377. params: { code: 'rule_conditions' },
  378. labelField: 'text',
  379. valueField: 'value',
  380. getPopupContainer: (node) => document.body,
  381. },
  382. },
  383. {
  384. field: 'ruleValue',
  385. label: '规则值',
  386. component: 'Input',
  387. required: true,
  388. },
  389. {
  390. field: 'status',
  391. label: '状态',
  392. component: 'RadioButtonGroup',
  393. defaultValue: '1',
  394. componentProps: {
  395. options: [
  396. { label: '无效', value: '0' },
  397. { label: '有效', value: '1' },
  398. ],
  399. },
  400. },
  401. ];