DefaultForm.vue 30 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452
  1. <script setup lang="tsx">
  2. import { Form } from '@/components/Form'
  3. import { reactive, ref, onMounted, computed, unref } 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. const appStore = useAppStore()
  20. const { t } = useI18n()
  21. const isMobile = computed(() => appStore.getMobile)
  22. const toggle = ref(false)
  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 (
  668. <ElOption
  669. key={v.value}
  670. disabled={unref(toggle)}
  671. label={v.label}
  672. value={v.value}
  673. />
  674. )
  675. })}
  676. </ElOptionGroup>
  677. )
  678. }
  679. }
  680. }
  681. },
  682. {
  683. field: 'field18',
  684. label: `${t('formDemo.selectV2')}`,
  685. component: 'Divider'
  686. },
  687. {
  688. field: 'field19',
  689. label: t('formDemo.default'),
  690. component: 'SelectV2',
  691. componentProps: {
  692. value: undefined,
  693. options: options.value
  694. }
  695. },
  696. {
  697. field: 'field20',
  698. label: t('formDemo.slot'),
  699. component: 'SelectV2',
  700. componentProps: {
  701. options: options.value,
  702. slots: {
  703. default: (option: SelectOption) => {
  704. return (
  705. <>
  706. <span style="margin-right: 8px">{option?.label}</span>
  707. <span style="color: var(--el-text-color-secondary); font-size: 13px">
  708. {option?.value}
  709. </span>
  710. </>
  711. )
  712. }
  713. }
  714. }
  715. },
  716. {
  717. field: 'field21',
  718. label: t('formDemo.selectGroup'),
  719. component: 'SelectV2',
  720. componentProps: {
  721. options: options2.value
  722. }
  723. },
  724. {
  725. field: 'field22',
  726. label: `${t('formDemo.selectGroup')}${t('formDemo.slot')}`,
  727. component: 'SelectV2',
  728. componentProps: {
  729. options: options2.value,
  730. slots: {
  731. default: (option: SelectOption) => {
  732. return (
  733. <>
  734. <span style="margin-right: 8px">{option?.label}</span>
  735. <span style="color: var(--el-text-color-secondary); font-size: 13px">
  736. {option?.value}
  737. </span>
  738. </>
  739. )
  740. }
  741. }
  742. }
  743. },
  744. {
  745. field: 'field23',
  746. label: t('formDemo.cascader'),
  747. component: 'Divider'
  748. },
  749. {
  750. field: 'field24',
  751. label: t('formDemo.default'),
  752. component: 'Cascader',
  753. componentProps: {
  754. options: options3,
  755. props: {
  756. multiple: true
  757. }
  758. }
  759. },
  760. {
  761. field: 'field25',
  762. label: t('formDemo.slot'),
  763. component: 'Cascader',
  764. componentProps: {
  765. options: options3,
  766. slots: {
  767. default: ({ data, node }) => {
  768. return (
  769. <>
  770. <span>{data.label}</span>
  771. {!node.isLeaf ? <span> ({data.children.length}) </span> : null}
  772. </>
  773. )
  774. }
  775. }
  776. }
  777. },
  778. {
  779. field: 'field26',
  780. label: t('formDemo.switch'),
  781. component: 'Divider'
  782. },
  783. {
  784. field: 'field27',
  785. label: t('formDemo.default'),
  786. component: 'Switch',
  787. value: false
  788. },
  789. {
  790. field: 'field28',
  791. label: t('formDemo.icon'),
  792. component: 'Switch',
  793. value: false,
  794. componentProps: {
  795. activeIcon: useIcon({ icon: 'ep:check' }),
  796. inactiveIcon: useIcon({ icon: 'ep:close' })
  797. }
  798. },
  799. {
  800. field: 'field29',
  801. label: t('formDemo.rate'),
  802. component: 'Divider'
  803. },
  804. {
  805. field: 'field30',
  806. label: t('formDemo.default'),
  807. component: 'Rate',
  808. value: 0
  809. },
  810. {
  811. field: 'field31',
  812. label: t('formDemo.icon'),
  813. component: 'Rate',
  814. value: null,
  815. componentProps: {
  816. voidIcon: useIcon({ icon: 'ep:chat-round' }),
  817. icons: [
  818. useIcon({ icon: 'ep:chat-round' }),
  819. useIcon({ icon: 'ep:chat-line-round' }),
  820. useIcon({ icon: 'ep:chat-dot-round' })
  821. ]
  822. }
  823. },
  824. {
  825. field: 'field32',
  826. label: t('formDemo.colorPicker'),
  827. component: 'Divider'
  828. },
  829. {
  830. field: 'field33',
  831. label: t('formDemo.default'),
  832. component: 'ColorPicker'
  833. },
  834. {
  835. field: 'field34',
  836. label: t('formDemo.transfer'),
  837. component: 'Divider'
  838. },
  839. {
  840. field: 'field35',
  841. label: t('formDemo.default'),
  842. component: 'Transfer',
  843. componentProps: {
  844. props: {
  845. key: 'value',
  846. label: 'desc'
  847. },
  848. data: generateData()
  849. },
  850. value: [],
  851. colProps: {
  852. span: 24
  853. }
  854. },
  855. {
  856. field: 'field36',
  857. label: t('formDemo.slot'),
  858. component: 'Transfer',
  859. componentProps: {
  860. props: {
  861. key: 'value',
  862. label: 'desc'
  863. },
  864. filterable: true,
  865. leftDefaultChecked: [2, 3],
  866. rightDefaultChecked: [1],
  867. titles: ['Source', 'Target'],
  868. buttonTexts: ['To Left', 'To Right'],
  869. format: {
  870. noChecked: '${total}',
  871. hasChecked: '${checked}/${total}'
  872. },
  873. data: generateData(),
  874. slots: {
  875. default: ({ option }) => {
  876. return (
  877. <span>
  878. {option.value} - {option.desc}
  879. </span>
  880. )
  881. },
  882. leftFooter: () => {
  883. return (
  884. <ElButton class="transfer-footer" size="small">
  885. Operation
  886. </ElButton>
  887. )
  888. },
  889. rightFooter: () => {
  890. return (
  891. <ElButton class="transfer-footer" size="small">
  892. Operation
  893. </ElButton>
  894. )
  895. }
  896. }
  897. },
  898. value: [1],
  899. colProps: {
  900. span: 24
  901. }
  902. },
  903. {
  904. field: 'field37',
  905. label: `${t('formDemo.render')}`,
  906. component: 'Transfer',
  907. componentProps: {
  908. props: {
  909. key: 'value',
  910. label: 'desc',
  911. disabled: 'disabled'
  912. },
  913. leftDefaultChecked: [2, 3],
  914. rightDefaultChecked: [1],
  915. data: generateData(),
  916. renderContent: (h, option) => {
  917. return h('span', null, `${option.value} - ${option.desc}`)
  918. }
  919. },
  920. value: [1],
  921. colProps: {
  922. span: 24
  923. }
  924. },
  925. {
  926. field: 'field38',
  927. label: t('formDemo.radio'),
  928. component: 'Divider'
  929. },
  930. {
  931. field: 'field39-2',
  932. label: t('formDemo.radioGroup'),
  933. component: 'RadioGroup',
  934. componentProps: {
  935. options: [
  936. {
  937. // disabled: true,
  938. label: 'option-1',
  939. value: '1'
  940. },
  941. {
  942. label: 'option-2',
  943. value: '2'
  944. }
  945. ]
  946. }
  947. },
  948. {
  949. field: 'field39-3',
  950. label: `${t('formDemo.radioGroup')} ${t('formDemo.slot')}`,
  951. component: 'RadioGroup',
  952. componentProps: {
  953. options: [
  954. {
  955. // disabled: true,
  956. label: 'option-1',
  957. value: '1'
  958. },
  959. {
  960. label: 'option-2',
  961. value: '2'
  962. }
  963. ],
  964. slots: {
  965. default: (options: RadioOption[]) => {
  966. return options?.map((v) => {
  967. return (
  968. <ElRadio label={v.value}>
  969. {v.label}({v.value})
  970. </ElRadio>
  971. )
  972. })
  973. }
  974. }
  975. }
  976. },
  977. {
  978. field: 'field40',
  979. label: t('formDemo.button'),
  980. component: 'RadioButton',
  981. componentProps: {
  982. options: [
  983. {
  984. label: 'option-1',
  985. value: '1'
  986. },
  987. {
  988. label: 'option-2',
  989. value: '2'
  990. }
  991. ]
  992. }
  993. },
  994. {
  995. field: 'field40-1',
  996. label: `${t('formDemo.button')} ${t('formDemo.slot')}`,
  997. component: 'RadioButton',
  998. componentProps: {
  999. options: [
  1000. {
  1001. label: 'option-1',
  1002. value: '1'
  1003. },
  1004. {
  1005. label: 'option-2',
  1006. value: '2'
  1007. }
  1008. ],
  1009. slots: {
  1010. default: (options: RadioOption[]) => {
  1011. return options?.map((v) => {
  1012. return (
  1013. <ElRadioButton label={v.value}>
  1014. {v.label}({v.value})
  1015. </ElRadioButton>
  1016. )
  1017. })
  1018. }
  1019. }
  1020. }
  1021. },
  1022. {
  1023. field: 'field41',
  1024. label: t('formDemo.checkbox'),
  1025. component: 'Divider'
  1026. },
  1027. {
  1028. field: 'field42-2',
  1029. label: t('formDemo.checkboxGroup'),
  1030. component: 'CheckboxGroup',
  1031. value: [],
  1032. componentProps: {
  1033. options: [
  1034. {
  1035. label: 'option-1',
  1036. value: '1'
  1037. },
  1038. {
  1039. label: 'option-2',
  1040. value: '2'
  1041. },
  1042. {
  1043. label: 'option-3',
  1044. value: '3'
  1045. }
  1046. ]
  1047. }
  1048. },
  1049. {
  1050. field: 'field42-3',
  1051. label: `${t('formDemo.checkboxGroup')} ${t('formDemo.slot')}`,
  1052. component: 'CheckboxGroup',
  1053. value: [],
  1054. componentProps: {
  1055. options: [
  1056. {
  1057. label: 'option-1',
  1058. value: '1'
  1059. },
  1060. {
  1061. label: 'option-2',
  1062. value: '2'
  1063. },
  1064. {
  1065. label: 'option-3',
  1066. value: '3'
  1067. }
  1068. ],
  1069. slots: {
  1070. default: (options: CheckboxOption[]) => {
  1071. return options?.map((v) => {
  1072. return (
  1073. <ElCheckbox label={v.value}>
  1074. {v.label}({v.value})
  1075. </ElCheckbox>
  1076. )
  1077. })
  1078. }
  1079. }
  1080. }
  1081. },
  1082. {
  1083. field: 'field43',
  1084. label: t('formDemo.button'),
  1085. component: 'CheckboxButton',
  1086. value: [],
  1087. componentProps: {
  1088. options: [
  1089. {
  1090. disabled: true,
  1091. label: 'option-1',
  1092. value: '1'
  1093. },
  1094. {
  1095. label: 'option-2',
  1096. value: '2'
  1097. },
  1098. {
  1099. label: 'option-3',
  1100. value: '23'
  1101. }
  1102. ]
  1103. }
  1104. },
  1105. {
  1106. field: 'field43-1',
  1107. label: `${t('formDemo.button')} ${t('formDemo.slot')}`,
  1108. component: 'CheckboxButton',
  1109. value: [],
  1110. componentProps: {
  1111. options: [
  1112. {
  1113. disabled: true,
  1114. label: 'option-1',
  1115. value: '1'
  1116. },
  1117. {
  1118. label: 'option-2',
  1119. value: '2'
  1120. },
  1121. {
  1122. label: 'option-3',
  1123. value: '23'
  1124. }
  1125. ],
  1126. slots: {
  1127. default: (options: CheckboxOption[]) => {
  1128. return options?.map((v) => {
  1129. return (
  1130. <ElCheckboxButton label={v.value}>
  1131. {v.label}({v.value})
  1132. </ElCheckboxButton>
  1133. )
  1134. })
  1135. }
  1136. }
  1137. }
  1138. },
  1139. {
  1140. field: 'field44',
  1141. component: 'Divider',
  1142. label: t('formDemo.slider')
  1143. },
  1144. {
  1145. field: 'field45',
  1146. component: 'Slider',
  1147. label: t('formDemo.default'),
  1148. value: 0
  1149. },
  1150. {
  1151. field: 'field46',
  1152. component: 'Divider',
  1153. label: t('formDemo.datePicker')
  1154. },
  1155. {
  1156. field: 'field47',
  1157. component: 'DatePicker',
  1158. label: t('formDemo.default'),
  1159. componentProps: {
  1160. type: 'date'
  1161. }
  1162. },
  1163. {
  1164. field: 'field48',
  1165. component: 'DatePicker',
  1166. label: t('formDemo.shortcuts'),
  1167. componentProps: {
  1168. type: 'date',
  1169. disabledDate: (time: Date) => {
  1170. return time.getTime() > Date.now()
  1171. },
  1172. shortcuts: [
  1173. {
  1174. text: t('formDemo.today'),
  1175. value: new Date()
  1176. },
  1177. {
  1178. text: t('formDemo.yesterday'),
  1179. value: () => {
  1180. const date = new Date()
  1181. date.setTime(date.getTime() - 3600 * 1000 * 24)
  1182. return date
  1183. }
  1184. },
  1185. {
  1186. text: t('formDemo.aWeekAgo'),
  1187. value: () => {
  1188. const date = new Date()
  1189. date.setTime(date.getTime() - 3600 * 1000 * 24 * 7)
  1190. return date
  1191. }
  1192. }
  1193. ]
  1194. }
  1195. },
  1196. {
  1197. field: 'field47-1',
  1198. component: 'DatePicker',
  1199. label: t('formDemo.slot'),
  1200. value: '2021-10-29',
  1201. componentProps: {
  1202. type: 'date',
  1203. slots: {
  1204. default: (cell: any) => {
  1205. return (
  1206. <div class={{ cell: true, current: cell.isCurrent }}>
  1207. <span class="text">{cell.text}</span>
  1208. {isHoliday(cell) ? <span class="holiday" /> : null}
  1209. </div>
  1210. )
  1211. }
  1212. }
  1213. }
  1214. },
  1215. {
  1216. field: 'field49',
  1217. component: 'DatePicker',
  1218. label: t('formDemo.week'),
  1219. componentProps: {
  1220. type: 'week',
  1221. format: `[${t('formDemo.week')}]`
  1222. }
  1223. },
  1224. {
  1225. field: 'field50',
  1226. component: 'DatePicker',
  1227. label: t('formDemo.year'),
  1228. componentProps: {
  1229. type: 'year'
  1230. }
  1231. },
  1232. {
  1233. field: 'field51',
  1234. component: 'DatePicker',
  1235. label: t('formDemo.month'),
  1236. componentProps: {
  1237. type: 'month'
  1238. }
  1239. },
  1240. {
  1241. field: 'field52',
  1242. component: 'DatePicker',
  1243. label: t('formDemo.dates'),
  1244. componentProps: {
  1245. type: 'dates'
  1246. }
  1247. },
  1248. {
  1249. field: 'field53',
  1250. component: 'DatePicker',
  1251. label: t('formDemo.daterange'),
  1252. componentProps: {
  1253. type: 'daterange'
  1254. }
  1255. },
  1256. {
  1257. field: 'field54',
  1258. component: 'DatePicker',
  1259. label: t('formDemo.monthrange'),
  1260. componentProps: {
  1261. type: 'monthrange'
  1262. }
  1263. },
  1264. {
  1265. field: 'field56',
  1266. component: 'Divider',
  1267. label: t('formDemo.dateTimePicker')
  1268. },
  1269. {
  1270. field: 'field57',
  1271. component: 'DatePicker',
  1272. label: t('formDemo.default'),
  1273. componentProps: {
  1274. type: 'datetime'
  1275. }
  1276. },
  1277. {
  1278. field: 'field58',
  1279. component: 'DatePicker',
  1280. label: t('formDemo.shortcuts'),
  1281. componentProps: {
  1282. type: 'datetime',
  1283. shortcuts: [
  1284. {
  1285. text: t('formDemo.today'),
  1286. value: new Date()
  1287. },
  1288. {
  1289. text: t('formDemo.yesterday'),
  1290. value: () => {
  1291. const date = new Date()
  1292. date.setTime(date.getTime() - 3600 * 1000 * 24)
  1293. return date
  1294. }
  1295. },
  1296. {
  1297. text: t('formDemo.aWeekAgo'),
  1298. value: () => {
  1299. const date = new Date()
  1300. date.setTime(date.getTime() - 3600 * 1000 * 24 * 7)
  1301. return date
  1302. }
  1303. }
  1304. ]
  1305. }
  1306. },
  1307. {
  1308. field: 'field59',
  1309. component: 'DatePicker',
  1310. label: t('formDemo.dateTimerange'),
  1311. componentProps: {
  1312. type: 'datetimerange'
  1313. }
  1314. },
  1315. {
  1316. field: 'field60',
  1317. component: 'Divider',
  1318. label: t('formDemo.timePicker')
  1319. },
  1320. {
  1321. field: 'field61',
  1322. component: 'TimePicker',
  1323. label: t('formDemo.default')
  1324. },
  1325. {
  1326. field: 'field62',
  1327. component: 'Divider',
  1328. label: t('formDemo.timeSelect')
  1329. },
  1330. {
  1331. field: 'field63',
  1332. component: 'TimeSelect',
  1333. label: t('formDemo.default')
  1334. },
  1335. {
  1336. field: 'field64',
  1337. component: 'Divider',
  1338. label: t('formDemo.richText')
  1339. },
  1340. {
  1341. field: 'field65',
  1342. component: 'Editor',
  1343. value: 'hello world',
  1344. label: t('formDemo.default'),
  1345. componentProps: {
  1346. editorConfig: {
  1347. placeholder: '请输入内容...'
  1348. }
  1349. },
  1350. colProps: {
  1351. span: 24
  1352. }
  1353. },
  1354. {
  1355. field: 'field66',
  1356. component: 'Divider',
  1357. label: t('formDemo.inputPassword')
  1358. },
  1359. {
  1360. field: 'field67',
  1361. component: 'InputPassword',
  1362. label: t('formDemo.default'),
  1363. componentProps: {
  1364. strength: true
  1365. }
  1366. },
  1367. {
  1368. field: 'field68',
  1369. component: 'Divider',
  1370. label: `${t('formDemo.form')} t('formDemo.slot')}`,
  1371. },
  1372. {
  1373. field: 'field69',
  1374. component: 'Input',
  1375. value: 'test',
  1376. label: `default`,
  1377. },
  1378. ])
  1379. const { register, formRef, methods } = useForm({
  1380. schema,
  1381. labelWidth: 'auto',
  1382. labelPosition: isMobile.value ? 'top' : 'right'
  1383. })
  1384. const changeToggle = () => {
  1385. toggle.value = !unref(toggle)
  1386. }
  1387. </script>
  1388. <template>
  1389. <button @click="changeToggle">测试</button>
  1390. <ContentWrap :title="t('formDemo.defaultForm')" :message="t('formDemo.formDes')">
  1391. <Form @register="register" label-width="auto" :label-position="isMobile ? 'top' : 'right'">
  1392. </Form>
  1393. </ContentWrap>
  1394. </template>
  1395. <style lang="less">
  1396. .cell {
  1397. height: 30px;
  1398. padding: 3px 0;
  1399. box-sizing: border-box;
  1400. .text {
  1401. width: 24px;
  1402. height: 24px;
  1403. display: block;
  1404. margin: 0 auto;
  1405. line-height: 24px;
  1406. position: absolute;
  1407. left: 50%;
  1408. transform: translateX(-50%);
  1409. border-radius: 50%;
  1410. }
  1411. &.current {
  1412. .text {
  1413. color: #fff;
  1414. background: #626aef;
  1415. }
  1416. }
  1417. .holiday {
  1418. position: absolute;
  1419. width: 6px;
  1420. height: 6px;
  1421. background: var(--el-color-danger);
  1422. border-radius: 50%;
  1423. bottom: 0px;
  1424. left: 50%;
  1425. transform: translateX(-50%);
  1426. }
  1427. }
  1428. .transfer-footer {
  1429. margin-left: 15px;
  1430. padding: 6px 5px;
  1431. }
  1432. </style>