DefaultForm.vue 30 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462
  1. <script setup lang="tsx">
  2. import { Form } from '@/components/Form'
  3. import { reactive, ref, onMounted, computed } from 'vue'
  4. import { useI18n } from '@/hooks/web/useI18n'
  5. import { useIcon } from '@/hooks/web/useIcon'
  6. import { ContentWrap } from '@/components/ContentWrap'
  7. import { useAppStore } from '@/store/modules/app'
  8. import { SelectOption, RadioOption, CheckboxOption, FormSchema } from '@/components/Form'
  9. import { useForm } from '@/hooks/web/useForm'
  10. import {
  11. ElOption,
  12. ElOptionGroup,
  13. ElButton,
  14. ElRadio,
  15. ElRadioButton,
  16. ElCheckbox,
  17. ElCheckboxButton
  18. } from 'element-plus'
  19. import { getDictOneApi } from '@/api/common'
  20. const appStore = useAppStore()
  21. const { t } = useI18n()
  22. const isMobile = computed(() => appStore.getMobile)
  23. const restaurants = ref<Recordable[]>([])
  24. const querySearch = (queryString: string, cb: Fn) => {
  25. const results = queryString
  26. ? restaurants.value.filter(createFilter(queryString))
  27. : restaurants.value
  28. // call callback function to return suggestions
  29. cb(results)
  30. }
  31. let timeout: NodeJS.Timeout
  32. const querySearchAsync = (queryString: string, cb: (arg: any) => void) => {
  33. const results = queryString
  34. ? restaurants.value.filter(createFilter(queryString))
  35. : restaurants.value
  36. clearTimeout(timeout)
  37. timeout = setTimeout(() => {
  38. cb(results)
  39. }, 3000 * Math.random())
  40. }
  41. const createFilter = (queryString: string) => {
  42. return (restaurant: Recordable) => {
  43. return restaurant.value.toLowerCase().indexOf(queryString.toLowerCase()) === 0
  44. }
  45. }
  46. const loadAll = () => {
  47. return [
  48. { value: 'vue', link: 'https://github.com/vuejs/vue' },
  49. { value: 'element', link: 'https://github.com/ElemeFE/element' },
  50. { value: 'cooking', link: 'https://github.com/ElemeFE/cooking' },
  51. { value: 'mint-ui', link: 'https://github.com/ElemeFE/mint-ui' },
  52. { value: 'vuex', link: 'https://github.com/vuejs/vuex' },
  53. { value: 'vue-router', link: 'https://github.com/vuejs/vue-router' },
  54. { value: 'babel', link: 'https://github.com/babel/babel' }
  55. ]
  56. }
  57. const handleSelect = (item: Recordable) => {
  58. console.log(item)
  59. }
  60. onMounted(() => {
  61. restaurants.value = loadAll()
  62. })
  63. const initials = ['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j']
  64. const options = ref(
  65. Array.from({ length: 1000 }).map((_, idx) => ({
  66. value: `Option ${idx + 1}`,
  67. label: `${initials[idx % 10]}${idx}`
  68. }))
  69. )
  70. const options2 = ref(
  71. Array.from({ length: 10 }).map((_, idx) => {
  72. const label = idx + 1
  73. return {
  74. value: `Group ${label}`,
  75. label: `Group ${label}`,
  76. options: Array.from({ length: 10 }).map((_, idx) => ({
  77. value: `Option ${idx + 1 + 10 * label}`,
  78. label: `${initials[idx % 10]}${idx + 1 + 10 * label}`
  79. }))
  80. }
  81. })
  82. )
  83. const options3 = [
  84. {
  85. value: 'guide',
  86. label: 'Guide',
  87. children: [
  88. {
  89. value: 'disciplines',
  90. label: 'Disciplines',
  91. children: [
  92. {
  93. value: 'consistency',
  94. label: 'Consistency'
  95. },
  96. {
  97. value: 'feedback',
  98. label: 'Feedback'
  99. },
  100. {
  101. value: 'efficiency',
  102. label: 'Efficiency'
  103. },
  104. {
  105. value: 'controllability',
  106. label: 'Controllability'
  107. }
  108. ]
  109. },
  110. {
  111. value: 'navigation',
  112. label: 'Navigation',
  113. children: [
  114. {
  115. value: 'side nav',
  116. label: 'Side Navigation'
  117. },
  118. {
  119. value: 'top nav',
  120. label: 'Top Navigation'
  121. }
  122. ]
  123. }
  124. ]
  125. },
  126. {
  127. value: 'component',
  128. label: 'Component',
  129. children: [
  130. {
  131. value: 'basic',
  132. label: 'Basic',
  133. children: [
  134. {
  135. value: 'layout',
  136. label: 'Layout'
  137. },
  138. {
  139. value: 'color',
  140. label: 'Color'
  141. },
  142. {
  143. value: 'typography',
  144. label: 'Typography'
  145. },
  146. {
  147. value: 'icon',
  148. label: 'Icon'
  149. },
  150. {
  151. value: 'button',
  152. label: 'Button'
  153. }
  154. ]
  155. },
  156. {
  157. value: 'form',
  158. label: 'Form',
  159. children: [
  160. {
  161. value: 'radio',
  162. label: 'Radio'
  163. },
  164. {
  165. value: 'checkbox',
  166. label: 'Checkbox'
  167. },
  168. {
  169. value: 'input',
  170. label: 'Input'
  171. },
  172. {
  173. value: 'input-number',
  174. label: 'InputNumber'
  175. },
  176. {
  177. value: 'select',
  178. label: 'Select'
  179. },
  180. {
  181. value: 'cascader',
  182. label: 'Cascader'
  183. },
  184. {
  185. value: 'switch',
  186. label: 'Switch'
  187. },
  188. {
  189. value: 'slider',
  190. label: 'Slider'
  191. },
  192. {
  193. value: 'time-picker',
  194. label: 'TimePicker'
  195. },
  196. {
  197. value: 'date-picker',
  198. label: 'DatePicker'
  199. },
  200. {
  201. value: 'datetime-picker',
  202. label: 'DateTimePicker'
  203. },
  204. {
  205. value: 'upload',
  206. label: 'Upload'
  207. },
  208. {
  209. value: 'rate',
  210. label: 'Rate'
  211. },
  212. {
  213. value: 'form',
  214. label: 'Form'
  215. }
  216. ]
  217. },
  218. {
  219. value: 'data',
  220. label: 'Data',
  221. children: [
  222. {
  223. value: 'table',
  224. label: 'Table'
  225. },
  226. {
  227. value: 'tag',
  228. label: 'Tag'
  229. },
  230. {
  231. value: 'progress',
  232. label: 'Progress'
  233. },
  234. {
  235. value: 'tree',
  236. label: 'Tree'
  237. },
  238. {
  239. value: 'pagination',
  240. label: 'Pagination'
  241. },
  242. {
  243. value: 'badge',
  244. label: 'Badge'
  245. }
  246. ]
  247. },
  248. {
  249. value: 'notice',
  250. label: 'Notice',
  251. children: [
  252. {
  253. value: 'alert',
  254. label: 'Alert'
  255. },
  256. {
  257. value: 'loading',
  258. label: 'Loading'
  259. },
  260. {
  261. value: 'message',
  262. label: 'Message'
  263. },
  264. {
  265. value: 'message-box',
  266. label: 'MessageBox'
  267. },
  268. {
  269. value: 'notification',
  270. label: 'Notification'
  271. }
  272. ]
  273. },
  274. {
  275. value: 'navigation',
  276. label: 'Navigation',
  277. children: [
  278. {
  279. value: 'menu',
  280. label: 'Menu'
  281. },
  282. {
  283. value: 'tabs',
  284. label: 'Tabs'
  285. },
  286. {
  287. value: 'breadcrumb',
  288. label: 'Breadcrumb'
  289. },
  290. {
  291. value: 'dropdown',
  292. label: 'Dropdown'
  293. },
  294. {
  295. value: 'steps',
  296. label: 'Steps'
  297. }
  298. ]
  299. },
  300. {
  301. value: 'others',
  302. label: 'Others',
  303. children: [
  304. {
  305. value: 'dialog',
  306. label: 'Dialog'
  307. },
  308. {
  309. value: 'tooltip',
  310. label: 'Tooltip'
  311. },
  312. {
  313. value: 'popover',
  314. label: 'Popover'
  315. },
  316. {
  317. value: 'card',
  318. label: 'Card'
  319. },
  320. {
  321. value: 'carousel',
  322. label: 'Carousel'
  323. },
  324. {
  325. value: 'collapse',
  326. label: 'Collapse'
  327. }
  328. ]
  329. }
  330. ]
  331. }
  332. ]
  333. const generateData = () => {
  334. const data: {
  335. value: number
  336. desc: string
  337. disabled: boolean
  338. }[] = []
  339. for (let i = 1; i <= 15; i++) {
  340. data.push({
  341. value: i,
  342. desc: `Option ${i}`,
  343. disabled: i % 4 === 0
  344. })
  345. }
  346. return data
  347. }
  348. const holidays = [
  349. '2021-10-01',
  350. '2021-10-02',
  351. '2021-10-03',
  352. '2021-10-04',
  353. '2021-10-05',
  354. '2021-10-06',
  355. '2021-10-07'
  356. ]
  357. const isHoliday = ({ dayjs }) => {
  358. return holidays.includes(dayjs.format('YYYY-MM-DD'))
  359. }
  360. const schema = reactive<FormSchema[]>([
  361. {
  362. field: 'field1',
  363. label: t('formDemo.input'),
  364. component: 'Divider'
  365. },
  366. {
  367. field: 'field2',
  368. label: t('formDemo.default'),
  369. component: 'Input',
  370. componentProps: {
  371. formatter: (value) => `$ ${value}`.replace(/\B(?=(\d{3})+(?!\d))/g, ','),
  372. parser: (value) => value.replace(/\$\s?|(,*)/g, '')
  373. }
  374. },
  375. {
  376. field: 'field3',
  377. label: `${t('formDemo.icon')}1`,
  378. component: 'Input',
  379. componentProps: {
  380. suffixIcon: useIcon({ icon: 'ep:calendar' }),
  381. prefixIcon: useIcon({ icon: 'ep:share' })
  382. }
  383. },
  384. {
  385. field: 'field4',
  386. label: `${t('formDemo.icon')}2`,
  387. component: 'Input',
  388. componentProps: {
  389. slots: {
  390. suffix: () => {
  391. return useIcon({ icon: 'ep:share' })
  392. },
  393. prefix: () => useIcon({ icon: 'ep:calendar' })
  394. }
  395. }
  396. },
  397. {
  398. field: 'field5',
  399. label: t('formDemo.mixed'),
  400. component: 'Input',
  401. componentProps: {
  402. slots: {
  403. prepend: () => useIcon({ icon: 'ep:calendar' }),
  404. append: () => useIcon({ icon: 'ep:share' })
  405. }
  406. }
  407. },
  408. {
  409. field: 'input-field7',
  410. label: t('formDemo.password'),
  411. component: 'Input',
  412. componentProps: {
  413. showPassword: true
  414. }
  415. },
  416. {
  417. field: 'field6',
  418. label: t('formDemo.textarea'),
  419. component: 'Input',
  420. componentProps: {
  421. type: 'textarea',
  422. rows: 2
  423. }
  424. },
  425. {
  426. field: 'field7',
  427. label: t('formDemo.autocomplete'),
  428. component: 'Divider'
  429. },
  430. {
  431. field: 'field8',
  432. label: t('formDemo.default'),
  433. component: 'Autocomplete',
  434. componentProps: {
  435. fetchSuggestions: querySearch,
  436. on: {
  437. select: handleSelect
  438. }
  439. }
  440. },
  441. {
  442. field: 'field9',
  443. label: t('formDemo.slot'),
  444. component: 'Autocomplete',
  445. componentProps: {
  446. fetchSuggestions: querySearch,
  447. on: {
  448. select: handleSelect
  449. },
  450. slots: {
  451. default: ({ item }) => {
  452. return (
  453. <>
  454. <div class="value">{item?.value}</div>
  455. <span class="link">{item?.link}</span>
  456. </>
  457. )
  458. }
  459. }
  460. }
  461. },
  462. {
  463. field: 'autocomplete-field10',
  464. label: t('formDemo.remoteSearch'),
  465. component: 'Autocomplete',
  466. componentProps: {
  467. fetchSuggestions: querySearchAsync,
  468. on: {
  469. select: handleSelect
  470. }
  471. }
  472. },
  473. {
  474. field: 'field10',
  475. component: 'Divider',
  476. label: t('formDemo.inputNumber')
  477. },
  478. {
  479. field: 'field11',
  480. label: t('formDemo.default'),
  481. component: 'InputNumber',
  482. value: 0
  483. },
  484. {
  485. field: 'field12',
  486. label: t('formDemo.position'),
  487. component: 'InputNumber',
  488. componentProps: {
  489. controlsPosition: 'right'
  490. },
  491. value: 10
  492. },
  493. {
  494. field: 'field13',
  495. label: t('formDemo.select'),
  496. component: 'Divider'
  497. },
  498. {
  499. field: 'field14',
  500. label: t('formDemo.default'),
  501. component: 'Select',
  502. componentProps: {
  503. options: [
  504. {
  505. disabled: true,
  506. label: 'option1',
  507. value: '1'
  508. },
  509. {
  510. label: 'option2',
  511. value: '2'
  512. }
  513. ]
  514. }
  515. },
  516. {
  517. field: 'field15',
  518. label: t('formDemo.slot'),
  519. component: 'Select',
  520. componentProps: {
  521. options: [
  522. {
  523. label: 'option1',
  524. value: '1'
  525. },
  526. {
  527. label: 'option2',
  528. value: '2'
  529. }
  530. ],
  531. slots: {
  532. default: (options: SelectOption[]) => {
  533. if (options.length) {
  534. return options?.map((v) => {
  535. return <ElOption key={v.value} label={v.label} value={v.value} />
  536. })
  537. } else {
  538. return null
  539. }
  540. },
  541. prefix: () => useIcon({ icon: 'ep:calendar' }),
  542. empty: () => {
  543. return useIcon({ icon: 'ep:share' })
  544. }
  545. }
  546. }
  547. },
  548. {
  549. field: 'select-field18',
  550. label: t('formDemo.optionSlot'),
  551. component: 'Select',
  552. componentProps: {
  553. options: [
  554. {
  555. value: 'Beijing',
  556. label: 'Beijing'
  557. },
  558. {
  559. value: 'Shanghai',
  560. label: 'Shanghai'
  561. },
  562. {
  563. value: 'Nanjing',
  564. label: 'Nanjing'
  565. },
  566. {
  567. value: 'Chengdu',
  568. label: 'Chengdu'
  569. },
  570. {
  571. value: 'Shenzhen',
  572. label: 'Shenzhen'
  573. },
  574. {
  575. value: 'Guangzhou',
  576. label: 'Guangzhou'
  577. }
  578. ],
  579. slots: {
  580. optionDefault: (option: SelectOption) => {
  581. return (
  582. <>
  583. <span style="float: left">{option.label}</span>
  584. <span style="float: right; color: var(--el-text-color-secondary); font-size: 13px;">
  585. {option.value}
  586. </span>
  587. </>
  588. )
  589. }
  590. }
  591. }
  592. },
  593. {
  594. field: 'field16',
  595. label: t('formDemo.selectGroup'),
  596. component: 'Select',
  597. componentProps: {
  598. options: [
  599. {
  600. label: 'option1',
  601. options: [
  602. {
  603. disabled: true,
  604. label: 'option1-1',
  605. value: '1-1'
  606. },
  607. {
  608. label: 'option1-2',
  609. value: '1-2'
  610. }
  611. ]
  612. },
  613. {
  614. label: 'option2',
  615. options: [
  616. {
  617. label: 'option2-1',
  618. value: '2-1'
  619. },
  620. {
  621. label: 'option2-2',
  622. value: '2-2'
  623. }
  624. ]
  625. }
  626. ]
  627. }
  628. },
  629. {
  630. field: 'field17',
  631. label: `${t('formDemo.selectGroup')} ${t('formDemo.slot')}`,
  632. component: 'Select',
  633. componentProps: {
  634. options: [
  635. {
  636. label: 'option1',
  637. options: [
  638. {
  639. label: 'option1-1',
  640. value: '1-1'
  641. },
  642. {
  643. label: 'option1-2',
  644. value: '1-2'
  645. }
  646. ]
  647. },
  648. {
  649. label: 'option2',
  650. options: [
  651. {
  652. label: 'option2-1',
  653. value: '2-1'
  654. },
  655. {
  656. label: 'option2-2',
  657. value: '2-2'
  658. }
  659. ]
  660. }
  661. ],
  662. slots: {
  663. optionGroupDefault: (option: SelectOption) => {
  664. return (
  665. <ElOptionGroup key={option.label} label={`${option.label} ${option.label}`}>
  666. {option?.options?.map((v) => {
  667. return <ElOption key={v.value} label={v.label} value={v.value} />
  668. })}
  669. </ElOptionGroup>
  670. )
  671. }
  672. }
  673. }
  674. },
  675. {
  676. field: 'field18',
  677. label: `${t('formDemo.selectV2')}`,
  678. component: 'Divider'
  679. },
  680. {
  681. field: 'field19',
  682. label: t('formDemo.default'),
  683. component: 'SelectV2',
  684. componentProps: {
  685. value: undefined,
  686. options: options.value
  687. }
  688. },
  689. {
  690. field: 'field20',
  691. label: t('formDemo.slot'),
  692. component: 'SelectV2',
  693. componentProps: {
  694. options: options.value,
  695. slots: {
  696. default: (option: SelectOption) => {
  697. return (
  698. <>
  699. <span style="margin-right: 8px">{option?.label}</span>
  700. <span style="color: var(--el-text-color-secondary); font-size: 13px">
  701. {option?.value}
  702. </span>
  703. </>
  704. )
  705. }
  706. }
  707. }
  708. },
  709. {
  710. field: 'field21',
  711. label: t('formDemo.selectGroup'),
  712. component: 'SelectV2',
  713. componentProps: {
  714. options: options2.value
  715. }
  716. },
  717. {
  718. field: 'field22',
  719. label: `${t('formDemo.selectGroup')} ${t('formDemo.slot')}`,
  720. component: 'SelectV2',
  721. componentProps: {
  722. options: options2.value,
  723. slots: {
  724. default: (option: SelectOption) => {
  725. return (
  726. <>
  727. <span style="margin-right: 8px">{option?.label}</span>
  728. <span style="color: var(--el-text-color-secondary); font-size: 13px">
  729. {option?.value}
  730. </span>
  731. </>
  732. )
  733. }
  734. }
  735. }
  736. },
  737. {
  738. field: 'field23',
  739. label: t('formDemo.cascader'),
  740. component: 'Divider'
  741. },
  742. {
  743. field: 'field24',
  744. label: t('formDemo.default'),
  745. component: 'Cascader',
  746. componentProps: {
  747. options: options3,
  748. props: {
  749. multiple: true
  750. }
  751. }
  752. },
  753. {
  754. field: 'field25',
  755. label: t('formDemo.slot'),
  756. component: 'Cascader',
  757. componentProps: {
  758. options: options3,
  759. slots: {
  760. default: ({ data, node }) => {
  761. return (
  762. <>
  763. <span>{data.label}</span>
  764. {!node.isLeaf ? <span> ({data.children.length}) </span> : null}
  765. </>
  766. )
  767. }
  768. }
  769. }
  770. },
  771. {
  772. field: 'field26',
  773. label: t('formDemo.switch'),
  774. component: 'Divider'
  775. },
  776. {
  777. field: 'field27',
  778. label: t('formDemo.default'),
  779. component: 'Switch',
  780. value: false
  781. },
  782. {
  783. field: 'field28',
  784. label: t('formDemo.icon'),
  785. component: 'Switch',
  786. value: false,
  787. componentProps: {
  788. activeIcon: useIcon({ icon: 'ep:check' }),
  789. inactiveIcon: useIcon({ icon: 'ep:close' })
  790. }
  791. },
  792. {
  793. field: 'field29',
  794. label: t('formDemo.rate'),
  795. component: 'Divider'
  796. },
  797. {
  798. field: 'field30',
  799. label: t('formDemo.default'),
  800. component: 'Rate',
  801. value: 0
  802. },
  803. {
  804. field: 'field31',
  805. label: t('formDemo.icon'),
  806. component: 'Rate',
  807. value: null,
  808. componentProps: {
  809. voidIcon: useIcon({ icon: 'ep:chat-round' }),
  810. icons: [
  811. useIcon({ icon: 'ep:chat-round' }),
  812. useIcon({ icon: 'ep:chat-line-round' }),
  813. useIcon({ icon: 'ep:chat-dot-round' })
  814. ]
  815. }
  816. },
  817. {
  818. field: 'field32',
  819. label: t('formDemo.colorPicker'),
  820. component: 'Divider'
  821. },
  822. {
  823. field: 'field33',
  824. label: t('formDemo.default'),
  825. component: 'ColorPicker'
  826. },
  827. {
  828. field: 'field34',
  829. label: t('formDemo.transfer'),
  830. component: 'Divider'
  831. },
  832. {
  833. field: 'field35',
  834. label: t('formDemo.default'),
  835. component: 'Transfer',
  836. componentProps: {
  837. props: {
  838. key: 'value',
  839. label: 'desc'
  840. },
  841. data: generateData()
  842. },
  843. value: [],
  844. colProps: {
  845. span: 24
  846. }
  847. },
  848. {
  849. field: 'field36',
  850. label: t('formDemo.slot'),
  851. component: 'Transfer',
  852. componentProps: {
  853. props: {
  854. key: 'value',
  855. label: 'desc'
  856. },
  857. filterable: true,
  858. leftDefaultChecked: [2, 3],
  859. rightDefaultChecked: [1],
  860. titles: ['Source', 'Target'],
  861. buttonTexts: ['To Left', 'To Right'],
  862. format: {
  863. noChecked: '${total}',
  864. hasChecked: '${checked}/${total}'
  865. },
  866. data: generateData(),
  867. slots: {
  868. default: ({ option }) => {
  869. return (
  870. <span>
  871. {option.value} - {option.desc}
  872. </span>
  873. )
  874. },
  875. leftFooter: () => {
  876. return (
  877. <ElButton class="transfer-footer" size="small">
  878. Operation
  879. </ElButton>
  880. )
  881. },
  882. rightFooter: () => {
  883. return (
  884. <ElButton class="transfer-footer" size="small">
  885. Operation
  886. </ElButton>
  887. )
  888. }
  889. }
  890. },
  891. value: [1],
  892. colProps: {
  893. span: 24
  894. }
  895. },
  896. {
  897. field: 'field37',
  898. label: `${t('formDemo.render')}`,
  899. component: 'Transfer',
  900. componentProps: {
  901. props: {
  902. key: 'value',
  903. label: 'desc',
  904. disabled: 'disabled'
  905. },
  906. leftDefaultChecked: [2, 3],
  907. rightDefaultChecked: [1],
  908. data: generateData(),
  909. renderContent: (h, option) => {
  910. return h('span', null, `${option.value} - ${option.desc}`)
  911. }
  912. },
  913. value: [1],
  914. colProps: {
  915. span: 24
  916. }
  917. },
  918. {
  919. field: 'field38',
  920. label: t('formDemo.radio'),
  921. component: 'Divider'
  922. },
  923. {
  924. field: 'field39-2',
  925. label: t('formDemo.radioGroup'),
  926. component: 'RadioGroup',
  927. componentProps: {
  928. options: [
  929. {
  930. // disabled: true,
  931. label: 'option-1',
  932. value: '1'
  933. },
  934. {
  935. label: 'option-2',
  936. value: '2'
  937. }
  938. ]
  939. }
  940. },
  941. {
  942. field: 'field39-3',
  943. label: `${t('formDemo.radioGroup')} ${t('formDemo.slot')}`,
  944. component: 'RadioGroup',
  945. componentProps: {
  946. options: [
  947. {
  948. // disabled: true,
  949. label: 'option-1',
  950. value: '1'
  951. },
  952. {
  953. label: 'option-2',
  954. value: '2'
  955. }
  956. ],
  957. slots: {
  958. default: (options: RadioOption[]) => {
  959. return options?.map((v) => {
  960. return (
  961. <ElRadio label={v.value}>
  962. {v.label}({v.value})
  963. </ElRadio>
  964. )
  965. })
  966. }
  967. }
  968. }
  969. },
  970. {
  971. field: 'field40',
  972. label: t('formDemo.button'),
  973. component: 'RadioButton',
  974. componentProps: {
  975. options: [
  976. {
  977. label: 'option-1',
  978. value: '1'
  979. },
  980. {
  981. label: 'option-2',
  982. value: '2'
  983. }
  984. ]
  985. }
  986. },
  987. {
  988. field: 'field40-1',
  989. label: `${t('formDemo.button')} ${t('formDemo.slot')}`,
  990. component: 'RadioButton',
  991. componentProps: {
  992. options: [
  993. {
  994. label: 'option-1',
  995. value: '1'
  996. },
  997. {
  998. label: 'option-2',
  999. value: '2'
  1000. }
  1001. ],
  1002. slots: {
  1003. default: (options: RadioOption[]) => {
  1004. return options?.map((v) => {
  1005. return (
  1006. <ElRadioButton label={v.value}>
  1007. {v.label}({v.value})
  1008. </ElRadioButton>
  1009. )
  1010. })
  1011. }
  1012. }
  1013. }
  1014. },
  1015. {
  1016. field: 'field41',
  1017. label: t('formDemo.checkbox'),
  1018. component: 'Divider'
  1019. },
  1020. {
  1021. field: 'field42-2',
  1022. label: t('formDemo.checkboxGroup'),
  1023. component: 'CheckboxGroup',
  1024. value: [],
  1025. componentProps: {
  1026. options: [
  1027. {
  1028. label: 'option-1',
  1029. value: '1'
  1030. },
  1031. {
  1032. label: 'option-2',
  1033. value: '2'
  1034. },
  1035. {
  1036. label: 'option-3',
  1037. value: '3'
  1038. }
  1039. ]
  1040. }
  1041. },
  1042. {
  1043. field: 'field42-3',
  1044. label: `${t('formDemo.checkboxGroup')} ${t('formDemo.slot')}`,
  1045. component: 'CheckboxGroup',
  1046. value: [],
  1047. componentProps: {
  1048. options: [
  1049. {
  1050. label: 'option-1',
  1051. value: '1'
  1052. },
  1053. {
  1054. label: 'option-2',
  1055. value: '2'
  1056. },
  1057. {
  1058. label: 'option-3',
  1059. value: '3'
  1060. }
  1061. ],
  1062. slots: {
  1063. default: (options: CheckboxOption[]) => {
  1064. return options?.map((v) => {
  1065. return (
  1066. <ElCheckbox label={v.value}>
  1067. {v.label}({v.value})
  1068. </ElCheckbox>
  1069. )
  1070. })
  1071. }
  1072. }
  1073. }
  1074. },
  1075. {
  1076. field: 'field43',
  1077. label: t('formDemo.button'),
  1078. component: 'CheckboxButton',
  1079. value: [],
  1080. componentProps: {
  1081. options: [
  1082. {
  1083. disabled: true,
  1084. label: 'option-1',
  1085. value: '1'
  1086. },
  1087. {
  1088. label: 'option-2',
  1089. value: '2'
  1090. },
  1091. {
  1092. label: 'option-3',
  1093. value: '23'
  1094. }
  1095. ]
  1096. }
  1097. },
  1098. {
  1099. field: 'field43-1',
  1100. label: `${t('formDemo.button')} ${t('formDemo.slot')}`,
  1101. component: 'CheckboxButton',
  1102. value: [],
  1103. componentProps: {
  1104. options: [
  1105. {
  1106. disabled: true,
  1107. label: 'option-1',
  1108. value: '1'
  1109. },
  1110. {
  1111. label: 'option-2',
  1112. value: '2'
  1113. },
  1114. {
  1115. label: 'option-3',
  1116. value: '23'
  1117. }
  1118. ],
  1119. slots: {
  1120. default: (options: CheckboxOption[]) => {
  1121. return options?.map((v) => {
  1122. return (
  1123. <ElCheckboxButton label={v.value}>
  1124. {v.label}({v.value})
  1125. </ElCheckboxButton>
  1126. )
  1127. })
  1128. }
  1129. }
  1130. }
  1131. },
  1132. {
  1133. field: 'field44',
  1134. component: 'Divider',
  1135. label: t('formDemo.slider')
  1136. },
  1137. {
  1138. field: 'field45',
  1139. component: 'Slider',
  1140. label: t('formDemo.default'),
  1141. value: 0
  1142. },
  1143. {
  1144. field: 'field46',
  1145. component: 'Divider',
  1146. label: t('formDemo.datePicker')
  1147. },
  1148. {
  1149. field: 'field47',
  1150. component: 'DatePicker',
  1151. label: t('formDemo.default'),
  1152. componentProps: {
  1153. type: 'date'
  1154. }
  1155. },
  1156. {
  1157. field: 'field48',
  1158. component: 'DatePicker',
  1159. label: t('formDemo.shortcuts'),
  1160. componentProps: {
  1161. type: 'date',
  1162. disabledDate: (time: Date) => {
  1163. return time.getTime() > Date.now()
  1164. },
  1165. shortcuts: [
  1166. {
  1167. text: t('formDemo.today'),
  1168. value: new Date()
  1169. },
  1170. {
  1171. text: t('formDemo.yesterday'),
  1172. value: () => {
  1173. const date = new Date()
  1174. date.setTime(date.getTime() - 3600 * 1000 * 24)
  1175. return date
  1176. }
  1177. },
  1178. {
  1179. text: t('formDemo.aWeekAgo'),
  1180. value: () => {
  1181. const date = new Date()
  1182. date.setTime(date.getTime() - 3600 * 1000 * 24 * 7)
  1183. return date
  1184. }
  1185. }
  1186. ]
  1187. }
  1188. },
  1189. {
  1190. field: 'field47-1',
  1191. component: 'DatePicker',
  1192. label: t('formDemo.slot'),
  1193. value: '2021-10-29',
  1194. componentProps: {
  1195. type: 'date',
  1196. slots: {
  1197. default: (cell: any) => {
  1198. return (
  1199. <div class={{ cell: true, current: cell.isCurrent }}>
  1200. <span class="text">{cell.text}</span>
  1201. {isHoliday(cell) ? <span class="holiday" /> : null}
  1202. </div>
  1203. )
  1204. }
  1205. }
  1206. }
  1207. },
  1208. {
  1209. field: 'field49',
  1210. component: 'DatePicker',
  1211. label: t('formDemo.week'),
  1212. componentProps: {
  1213. type: 'week',
  1214. format: `[${t('formDemo.week')}]`
  1215. }
  1216. },
  1217. {
  1218. field: 'field50',
  1219. component: 'DatePicker',
  1220. label: t('formDemo.year'),
  1221. componentProps: {
  1222. type: 'year'
  1223. }
  1224. },
  1225. {
  1226. field: 'field51',
  1227. component: 'DatePicker',
  1228. label: t('formDemo.month'),
  1229. componentProps: {
  1230. type: 'month'
  1231. }
  1232. },
  1233. {
  1234. field: 'field52',
  1235. component: 'DatePicker',
  1236. label: t('formDemo.dates'),
  1237. componentProps: {
  1238. type: 'dates'
  1239. }
  1240. },
  1241. {
  1242. field: 'field53',
  1243. component: 'DatePicker',
  1244. label: t('formDemo.daterange'),
  1245. componentProps: {
  1246. type: 'daterange'
  1247. }
  1248. },
  1249. {
  1250. field: 'field54',
  1251. component: 'DatePicker',
  1252. label: t('formDemo.monthrange'),
  1253. componentProps: {
  1254. type: 'monthrange'
  1255. }
  1256. },
  1257. {
  1258. field: 'field56',
  1259. component: 'Divider',
  1260. label: t('formDemo.dateTimePicker')
  1261. },
  1262. {
  1263. field: 'field57',
  1264. component: 'DatePicker',
  1265. label: t('formDemo.default'),
  1266. componentProps: {
  1267. type: 'datetime'
  1268. }
  1269. },
  1270. {
  1271. field: 'field58',
  1272. component: 'DatePicker',
  1273. label: t('formDemo.shortcuts'),
  1274. componentProps: {
  1275. type: 'datetime',
  1276. shortcuts: [
  1277. {
  1278. text: t('formDemo.today'),
  1279. value: new Date()
  1280. },
  1281. {
  1282. text: t('formDemo.yesterday'),
  1283. value: () => {
  1284. const date = new Date()
  1285. date.setTime(date.getTime() - 3600 * 1000 * 24)
  1286. return date
  1287. }
  1288. },
  1289. {
  1290. text: t('formDemo.aWeekAgo'),
  1291. value: () => {
  1292. const date = new Date()
  1293. date.setTime(date.getTime() - 3600 * 1000 * 24 * 7)
  1294. return date
  1295. }
  1296. }
  1297. ]
  1298. }
  1299. },
  1300. {
  1301. field: 'field59',
  1302. component: 'DatePicker',
  1303. label: t('formDemo.dateTimerange'),
  1304. componentProps: {
  1305. type: 'datetimerange'
  1306. }
  1307. },
  1308. {
  1309. field: 'field60',
  1310. component: 'Divider',
  1311. label: t('formDemo.timePicker')
  1312. },
  1313. {
  1314. field: 'field61',
  1315. component: 'TimePicker',
  1316. label: t('formDemo.default')
  1317. },
  1318. {
  1319. field: 'field62',
  1320. component: 'Divider',
  1321. label: t('formDemo.timeSelect')
  1322. },
  1323. {
  1324. field: 'field63',
  1325. component: 'TimeSelect',
  1326. label: t('formDemo.default')
  1327. },
  1328. {
  1329. field: 'field64',
  1330. component: 'Divider',
  1331. label: t('formDemo.richText')
  1332. },
  1333. {
  1334. field: 'field65',
  1335. component: 'Editor',
  1336. value: 'hello world',
  1337. label: t('formDemo.default'),
  1338. colProps: {
  1339. span: 24
  1340. }
  1341. },
  1342. {
  1343. field: 'field66',
  1344. component: 'Divider',
  1345. label: t('formDemo.inputPassword')
  1346. },
  1347. {
  1348. field: 'field67',
  1349. component: 'InputPassword',
  1350. label: t('formDemo.default'),
  1351. componentProps: {
  1352. strength: true
  1353. }
  1354. },
  1355. {
  1356. field: 'field68',
  1357. component: 'Divider',
  1358. label: `${t('formDemo.form')} ${t('formDemo.slot')}`
  1359. },
  1360. {
  1361. field: 'field69',
  1362. component: 'Input',
  1363. label: `label`,
  1364. formItemProps: {
  1365. slots: {
  1366. label: ({ label }) => {
  1367. return (
  1368. <div class="custom-label">
  1369. <span class="label-text">custom {label}</span>
  1370. </div>
  1371. )
  1372. }
  1373. }
  1374. }
  1375. },
  1376. {
  1377. field: 'field70',
  1378. component: 'Divider',
  1379. label: `${t('formDemo.remoteLoading')}`
  1380. },
  1381. {
  1382. field: 'field71',
  1383. label: `${t('formDemo.select')}`,
  1384. component: 'Select',
  1385. componentProps: {
  1386. options: []
  1387. },
  1388. // 远程加载option
  1389. optionApi: async () => {
  1390. const res = await getDictOneApi()
  1391. return res.data
  1392. }
  1393. }
  1394. ])
  1395. const { register, formRef, methods } = useForm()
  1396. </script>
  1397. <template>
  1398. <ContentWrap :title="t('formDemo.defaultForm')" :message="t('formDemo.formDes')">
  1399. <Form
  1400. @register="register"
  1401. :schema="schema"
  1402. label-width="auto"
  1403. :label-position="isMobile ? 'top' : 'right'"
  1404. />
  1405. </ContentWrap>
  1406. </template>
  1407. <style lang="less">
  1408. .cell {
  1409. height: 30px;
  1410. padding: 3px 0;
  1411. box-sizing: border-box;
  1412. .text {
  1413. width: 24px;
  1414. height: 24px;
  1415. display: block;
  1416. margin: 0 auto;
  1417. line-height: 24px;
  1418. position: absolute;
  1419. left: 50%;
  1420. transform: translateX(-50%);
  1421. border-radius: 50%;
  1422. }
  1423. &.current {
  1424. .text {
  1425. color: #fff;
  1426. background: #626aef;
  1427. }
  1428. }
  1429. .holiday {
  1430. position: absolute;
  1431. width: 6px;
  1432. height: 6px;
  1433. background: var(--el-color-danger);
  1434. border-radius: 50%;
  1435. bottom: 0px;
  1436. left: 50%;
  1437. transform: translateX(-50%);
  1438. }
  1439. }
  1440. .transfer-footer {
  1441. margin-left: 15px;
  1442. padding: 6px 5px;
  1443. }
  1444. </style>