DefaultForm.vue 31 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469
  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/src/types'
  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. const { register, formRef, methods } = useForm({
  1337. schema,
  1338. labelWidth: 'auto',
  1339. labelPosition: isMobile.value ? 'top' : 'right'
  1340. })
  1341. const changeToggle = () => {
  1342. toggle.value = !unref(toggle)
  1343. }
  1344. </script>
  1345. <template>
  1346. <button @click="changeToggle">测试</button>
  1347. <ContentWrap :title="t('formDemo.defaultForm')" :message="t('formDemo.formDes')">
  1348. <!-- <Form :schema="schema" label-width="auto" :label-position="isMobile ? 'top' : 'right'">
  1349. <template #field4-prefix>
  1350. <Icon icon="ep:calendar" class="el-input__icon" />
  1351. </template>
  1352. <template #field4-suffix>
  1353. <Icon icon="ep:calendar" class="el-input__icon" />
  1354. </template>
  1355. <template #field5-prepend> Http:// </template>
  1356. <template #field5-append> .com </template>
  1357. <template #field9-default="{ item }">
  1358. <div class="value">{{ item.value }}</div>
  1359. <span class="link">{{ item.link }}</span>
  1360. </template>
  1361. <template #field15-option="{ item }">
  1362. <span style="float: left">{{ item.label }}</span>
  1363. <span style="float: right; font-size: 13px; color: var(--el-text-color-secondary)">
  1364. {{ item.value }}
  1365. </span>
  1366. </template>
  1367. <template #field17-option="{ item }">
  1368. <span style="float: left">{{ item.label }}</span>
  1369. <span style="float: right; font-size: 13px; color: var(--el-text-color-secondary)">
  1370. {{ item.value }}
  1371. </span>
  1372. </template>
  1373. <template #field20-default="{ item }">
  1374. <span style="float: left">{{ item.label }}</span>
  1375. <span style="float: right; font-size: 13px; color: var(--el-text-color-secondary)">
  1376. {{ item.value }}
  1377. </span>
  1378. </template>
  1379. <template #field22-default="{ item }">
  1380. <span style="float: left">{{ item.label }}</span>
  1381. <span style="float: right; font-size: 13px; color: var(--el-text-color-secondary)">
  1382. {{ item.value }}
  1383. </span>
  1384. </template>
  1385. <template #field25-default="{ node, data }">
  1386. <span>{{ data.label }}</span>
  1387. <span v-if="!node.isLeaf"> ({{ data.children.length }}) </span>
  1388. </template>
  1389. <template #field36-default="{ option }">
  1390. <span>{{ option.value }} - {{ option.desc }}</span>
  1391. </template>
  1392. <template #field55-default="cell">
  1393. <div class="cell" :class="{ current: cell.isCurrent }">
  1394. <span class="text">{{ cell.text }}</span>
  1395. <span v-if="isHoliday(cell)" class="holiday"></span>
  1396. </div>
  1397. </template>
  1398. </Form> -->
  1399. <Form @register="register" />
  1400. </ContentWrap>
  1401. </template>
  1402. <style lang="less">
  1403. .cell {
  1404. height: 30px;
  1405. padding: 3px 0;
  1406. box-sizing: border-box;
  1407. .text {
  1408. width: 24px;
  1409. height: 24px;
  1410. display: block;
  1411. margin: 0 auto;
  1412. line-height: 24px;
  1413. position: absolute;
  1414. left: 50%;
  1415. transform: translateX(-50%);
  1416. border-radius: 50%;
  1417. }
  1418. &.current {
  1419. .text {
  1420. color: #fff;
  1421. background: #626aef;
  1422. }
  1423. }
  1424. .holiday {
  1425. position: absolute;
  1426. width: 6px;
  1427. height: 6px;
  1428. background: var(--el-color-danger);
  1429. border-radius: 50%;
  1430. bottom: 0px;
  1431. left: 50%;
  1432. transform: translateX(-50%);
  1433. }
  1434. }
  1435. .transfer-footer {
  1436. margin-left: 15px;
  1437. padding: 6px 5px;
  1438. }
  1439. </style>