DefaultForm.vue 32 KB

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