search.mdc 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743
  1. ---
  2. description: cl-search 组件示例
  3. globs: *.tsx, *.ts, *.vue
  4. ---
  5. ## 起步 示例
  6. ```vue
  7. <template>
  8. <div class="scope">
  9. <div class="h">
  10. <el-tag size="small" effect="dark" disable-transitions>base</el-tag>
  11. <span>起步</span>
  12. </div>
  13. <div class="c">
  14. <el-button @click="open">预览</el-button>
  15. <demo-code :files="['search/base.vue']" />
  16. <!-- 自定义表格组件 -->
  17. <cl-dialog v-model="visible" title="起步" width="80%">
  18. <cl-crud ref="Crud">
  19. <cl-row>
  20. <!--【很重要】搜索组件 -->
  21. <cl-search ref="Search" />
  22. </cl-row>
  23. <cl-row>
  24. <cl-table ref="Table" />
  25. </cl-row>
  26. <cl-row>
  27. <cl-flex1 />
  28. <cl-pagination />
  29. </cl-row>
  30. </cl-crud>
  31. </cl-dialog>
  32. </div>
  33. <div class="f">
  34. <span class="date">2024-01-01</span>
  35. </div>
  36. </div>
  37. </template>
  38. <script setup lang="ts">
  39. import { useCrud, useSearch, useTable } from '@cool-vue/crud';
  40. import { ref } from 'vue';
  41. import { useDict } from '/$/dict';
  42. const { dict } = useDict();
  43. // cl-crud 配置
  44. const Crud = useCrud(
  45. {
  46. service: 'test'
  47. },
  48. app => {
  49. app.refresh();
  50. }
  51. );
  52. // cl-table 配置
  53. const Table = useTable({
  54. autoHeight: false,
  55. contextMenu: ['refresh'],
  56. columns: [
  57. {
  58. label: '姓名',
  59. prop: 'name',
  60. minWidth: 140
  61. },
  62. {
  63. label: '手机号',
  64. prop: 'phone',
  65. minWidth: 140
  66. },
  67. {
  68. label: '工作',
  69. prop: 'occupation',
  70. dict: dict.get('occupation'),
  71. minWidth: 140
  72. },
  73. {
  74. label: '创建时间',
  75. prop: 'createTime',
  76. minWidth: 170,
  77. sortable: 'desc'
  78. }
  79. ]
  80. });
  81. // cl-search 配置
  82. //【很重要】该组件基于 cl-form 故很多示例都可复用
  83. const Search = useSearch({
  84. // 配置如 cl-form 一样
  85. items: [
  86. {
  87. label: '姓名',
  88. prop: 'name',
  89. component: {
  90. name: 'el-input',
  91. props: {
  92. clearable: true,
  93. // 值改变的时候刷新列表
  94. onChange(val: string) {
  95. refresh({
  96. name: val,
  97. page: 1
  98. });
  99. }
  100. }
  101. }
  102. },
  103. {
  104. label: '手机号',
  105. prop: 'phone',
  106. component: {
  107. name: 'el-input',
  108. props: {
  109. clearable: true
  110. }
  111. }
  112. },
  113. {
  114. label: '工作',
  115. prop: 'occupation',
  116. component: {
  117. name: 'cl-select',
  118. props: {
  119. tree: true,
  120. checkStrictly: true,
  121. options: dict.get('occupation')
  122. }
  123. }
  124. }
  125. ],
  126. onChange(data, prop) {
  127. console.log(data, prop);
  128. }
  129. });
  130. function refresh(params?: any) {
  131. Crud.value?.refresh(params);
  132. }
  133. const visible = ref(false);
  134. function open() {
  135. visible.value = true;
  136. }
  137. </script>
  138. ```
  139. ## 折叠 示例
  140. ```vue
  141. <template>
  142. <div class="scope">
  143. <div class="h">
  144. <el-tag size="small" effect="dark" disable-transitions>collapse</el-tag>
  145. <span>折叠</span>
  146. </div>
  147. <div class="c">
  148. <el-button @click="open">预览</el-button>
  149. <demo-code :files="['search/collapse.vue']" />
  150. <!-- 折叠表格组件 -->
  151. <cl-dialog v-model="visible" title="折叠" width="80%">
  152. <cl-crud ref="Crud">
  153. <!--【collapse】折叠参数,【inline】是否行内 -->
  154. <cl-search ref="Search" reset-btn collapse :inline="false" />
  155. <cl-row>
  156. <cl-table ref="Table" />
  157. </cl-row>
  158. <cl-row>
  159. <cl-flex1 />
  160. <cl-pagination />
  161. </cl-row>
  162. </cl-crud>
  163. </cl-dialog>
  164. </div>
  165. <div class="f">
  166. <span class="date">2024-12-26</span>
  167. </div>
  168. </div>
  169. </template>
  170. <script setup lang="ts">
  171. import { useCrud, useSearch, useTable } from '@cool-vue/crud';
  172. import { ref } from 'vue';
  173. import { useDict } from '/$/dict';
  174. import { range } from 'lodash-es';
  175. const { dict } = useDict();
  176. // cl-crud 配置
  177. const Crud = useCrud(
  178. {
  179. service: 'test'
  180. },
  181. app => {
  182. app.refresh();
  183. }
  184. );
  185. // cl-table 配置
  186. const Table = useTable({
  187. autoHeight: false,
  188. contextMenu: ['refresh'],
  189. columns: [
  190. {
  191. label: '姓名',
  192. prop: 'name',
  193. minWidth: 140
  194. },
  195. {
  196. label: '手机号',
  197. prop: 'phone',
  198. minWidth: 140
  199. },
  200. {
  201. label: '工作',
  202. prop: 'occupation',
  203. dict: dict.get('occupation'),
  204. minWidth: 140
  205. },
  206. {
  207. label: '创建时间',
  208. prop: 'createTime',
  209. minWidth: 170,
  210. sortable: 'desc'
  211. }
  212. ]
  213. });
  214. // cl-search 配置
  215. const Search = useSearch({
  216. items: [
  217. ...range(20).map(i => {
  218. return {
  219. label: '输入框',
  220. prop: `T${i + 1}`,
  221. component: {
  222. name: 'el-input'
  223. }
  224. };
  225. })
  226. ]
  227. });
  228. function refresh(params?: any) {
  229. Crud.value?.refresh(params);
  230. }
  231. const visible = ref(false);
  232. function open() {
  233. visible.value = true;
  234. }
  235. </script>
  236. x
  237. ```
  238. ## 自定义 示例
  239. ```vue
  240. <template>
  241. <div class="scope">
  242. <div class="h">
  243. <el-tag size="small" effect="dark" disable-transitions>custom</el-tag>
  244. <span>自定义</span>
  245. </div>
  246. <div class="c">
  247. <el-button @click="open">预览</el-button>
  248. <demo-code :files="['search/custom.vue']" />
  249. <!-- 自定义表格组件 -->
  250. <cl-dialog v-model="visible" title="自定义" width="80%">
  251. <cl-crud ref="Crud">
  252. <cl-row>
  253. <!--【很重要】搜索组件 -->
  254. <cl-search
  255. ref="Search"
  256. :reset-btn="true"
  257. :on-load="onLoad"
  258. :on-search="onSearch"
  259. >
  260. <!-- 自定义按钮 -->
  261. <template #buttons="scope">
  262. <el-button @click="toSearch(scope)">自定义按钮</el-button>
  263. </template>
  264. </cl-search>
  265. </cl-row>
  266. <cl-row>
  267. <cl-table ref="Table" />
  268. </cl-row>
  269. <cl-row>
  270. <cl-flex1 />
  271. <cl-pagination />
  272. </cl-row>
  273. </cl-crud>
  274. </cl-dialog>
  275. </div>
  276. <div class="f">
  277. <span class="date">2024-01-01</span>
  278. </div>
  279. </div>
  280. </template>
  281. <script setup lang="ts">
  282. import { useCrud, useSearch, useTable } from '@cool-vue/crud';
  283. import { ref } from 'vue';
  284. import { useDict } from '/$/dict';
  285. import { ElMessage } from 'element-plus';
  286. const { dict } = useDict();
  287. // cl-crud 配置
  288. const Crud = useCrud(
  289. {
  290. service: 'test'
  291. },
  292. app => {
  293. app.refresh();
  294. }
  295. );
  296. // cl-table 配置
  297. const Table = useTable({
  298. autoHeight: false,
  299. contextMenu: ['refresh'],
  300. columns: [
  301. {
  302. label: '姓名',
  303. prop: 'name',
  304. minWidth: 140
  305. },
  306. {
  307. label: '手机号',
  308. prop: 'phone',
  309. minWidth: 140
  310. },
  311. {
  312. label: '工作',
  313. prop: 'occupation',
  314. dict: dict.get('occupation'),
  315. minWidth: 140
  316. },
  317. {
  318. label: '创建时间',
  319. prop: 'createTime',
  320. minWidth: 170,
  321. sortable: 'desc'
  322. }
  323. ]
  324. });
  325. // cl-search 配置
  326. //【很重要】该组件基于 cl-form 故很多示例都可复用
  327. const Search = useSearch({
  328. // 配置如 cl-form 一样
  329. items: [
  330. {
  331. label: '姓名',
  332. prop: 'name',
  333. component: {
  334. name: 'el-input',
  335. props: {
  336. clearable: true,
  337. // 值改变的时候刷新列表
  338. onChange(val: string) {
  339. refresh({
  340. name: val,
  341. page: 1
  342. });
  343. }
  344. }
  345. }
  346. },
  347. {
  348. label: '手机号',
  349. prop: 'phone',
  350. component: {
  351. name: 'el-input',
  352. props: {
  353. clearable: true
  354. }
  355. }
  356. },
  357. {
  358. label: '工作',
  359. prop: 'occupation',
  360. component: {
  361. name: 'cl-select',
  362. props: {
  363. tree: true,
  364. checkStrictly: true,
  365. options: dict.get('occupation')
  366. }
  367. }
  368. }
  369. ]
  370. });
  371. function refresh(params?: any) {
  372. Crud.value?.refresh(params);
  373. }
  374. // cl-search 初始化
  375. function onLoad(data: any) {
  376. data.name = '白小纯';
  377. }
  378. // cl-search 配置 onSearch 后,必须使用 next 方法继续请求
  379. function onSearch(data: any, { next }: { next: (data: any) => void }) {
  380. ElMessage.info('开始搜索');
  381. // 这边可以处理其他事务
  382. next(data);
  383. }
  384. // 自定义搜索,data 为表单数据
  385. function toSearch(data: any) {
  386. ElMessage.info('自定义搜索');
  387. refresh({
  388. page: 1,
  389. ...data
  390. });
  391. }
  392. const visible = ref(false);
  393. function open() {
  394. visible.value = true;
  395. }
  396. </script>
  397. ```
  398. ## 布局 示例
  399. ```vue
  400. <template>
  401. <div class="scope">
  402. <div class="h">
  403. <el-tag size="small" effect="dark" disable-transitions>layout</el-tag>
  404. <span>布局</span>
  405. </div>
  406. <div class="c">
  407. <el-button @click="open">预览</el-button>
  408. <demo-code :files="['search/layout.vue']" />
  409. <!-- 自定义表格组件 -->
  410. <cl-dialog v-model="visible" title="布局" width="80%">
  411. <cl-crud ref="Crud">
  412. <!--【很重要】搜索组件 -->
  413. <cl-search ref="Search" :reset-btn="true" />
  414. <cl-row>
  415. <cl-table ref="Table" />
  416. </cl-row>
  417. <cl-row>
  418. <cl-flex1 />
  419. <cl-pagination />
  420. </cl-row>
  421. </cl-crud>
  422. </cl-dialog>
  423. </div>
  424. <div class="f">
  425. <span class="date">2024-01-01</span>
  426. </div>
  427. </div>
  428. </template>
  429. <script setup lang="ts">
  430. import { useCrud, useSearch, useTable } from '@cool-vue/crud';
  431. import { ref } from 'vue';
  432. import { useDict } from '/$/dict';
  433. const { dict } = useDict();
  434. // cl-crud 配置
  435. const Crud = useCrud(
  436. {
  437. service: 'test'
  438. },
  439. app => {
  440. app.refresh();
  441. }
  442. );
  443. // cl-table 配置
  444. const Table = useTable({
  445. autoHeight: false,
  446. contextMenu: ['refresh'],
  447. columns: [
  448. {
  449. label: '姓名',
  450. prop: 'name',
  451. minWidth: 140
  452. },
  453. {
  454. label: '手机号',
  455. prop: 'phone',
  456. minWidth: 140
  457. },
  458. {
  459. label: '工作',
  460. prop: 'occupation',
  461. dict: dict.get('occupation'),
  462. minWidth: 140
  463. },
  464. {
  465. label: '创建时间',
  466. prop: 'createTime',
  467. minWidth: 170,
  468. sortable: 'desc'
  469. }
  470. ]
  471. });
  472. // cl-search 配置
  473. //【很重要】该组件基于 cl-form 故很多示例都可复用
  474. const Search = useSearch({
  475. // 取消行内表单模式
  476. inline: false,
  477. // 表单参数
  478. props: {
  479. labelPosition: 'top'
  480. },
  481. // 配置如 cl-form 一样
  482. items: [
  483. {
  484. label: '姓名',
  485. prop: 'name',
  486. component: {
  487. name: 'el-input',
  488. props: {
  489. clearable: true,
  490. // 值改变的时候刷新列表
  491. onChange(val: string) {
  492. refresh({
  493. name: val,
  494. page: 1
  495. });
  496. }
  497. }
  498. }
  499. },
  500. {
  501. label: '手机号',
  502. prop: 'phone',
  503. component: {
  504. name: 'el-input',
  505. props: {
  506. clearable: true
  507. }
  508. }
  509. },
  510. {
  511. label: '工作',
  512. prop: 'occupation',
  513. component: {
  514. name: 'cl-select',
  515. props: {
  516. tree: true,
  517. checkStrictly: true,
  518. options: dict.get('occupation')
  519. }
  520. }
  521. }
  522. ]
  523. });
  524. function refresh(params?: any) {
  525. Crud.value?.refresh(params);
  526. }
  527. const visible = ref(false);
  528. function open() {
  529. visible.value = true;
  530. }
  531. </script>
  532. ```
  533. ## 使用插件 示例
  534. ```vue
  535. <template>
  536. <div class="scope">
  537. <div class="h">
  538. <el-tag size="small" effect="dark" disable-transitions>plugin</el-tag>
  539. <span>使用插件</span>
  540. </div>
  541. <div class="c">
  542. <el-button @click="open">预览</el-button>
  543. <demo-code :files="['search/layout.vue']" />
  544. <!-- 自定义表格组件 -->
  545. <cl-dialog v-model="visible" title="使用插件" width="80%">
  546. <cl-crud ref="Crud">
  547. <cl-row>
  548. <cl-flex1 />
  549. <!--【很重要】搜索组件 -->
  550. <cl-search ref="Search" />
  551. </cl-row>
  552. <cl-row>
  553. <cl-table ref="Table" />
  554. </cl-row>
  555. <cl-row>
  556. <cl-flex1 />
  557. <cl-pagination />
  558. </cl-row>
  559. </cl-crud>
  560. </cl-dialog>
  561. </div>
  562. <div class="f">
  563. <span class="date">2024-01-01</span>
  564. </div>
  565. </div>
  566. </template>
  567. <script setup lang="ts">
  568. import { useCrud, useSearch, useTable } from '@cool-vue/crud';
  569. import { ref } from 'vue';
  570. import { useDict } from '/$/dict';
  571. import { Plugins } from '/#/crud';
  572. const { dict } = useDict();
  573. // cl-crud 配置
  574. const Crud = useCrud(
  575. {
  576. service: 'test'
  577. },
  578. app => {
  579. app.refresh();
  580. }
  581. );
  582. // cl-table 配置
  583. const Table = useTable({
  584. autoHeight: false,
  585. contextMenu: ['refresh'],
  586. columns: [
  587. {
  588. label: '姓名',
  589. prop: 'name',
  590. minWidth: 140
  591. },
  592. {
  593. label: '手机号',
  594. prop: 'phone',
  595. minWidth: 140
  596. },
  597. {
  598. label: '工作',
  599. prop: 'occupation',
  600. dict: dict.get('occupation'),
  601. minWidth: 140
  602. },
  603. {
  604. label: '创建时间',
  605. prop: 'createTime',
  606. minWidth: 170,
  607. sortable: 'desc'
  608. }
  609. ]
  610. });
  611. // cl-search 配置
  612. const Search = useSearch({
  613. // 【很重要】自动读取 service 下的 search 数据
  614. plugins: [
  615. Plugins.Search.setAuto({
  616. customComponent(field) {
  617. if (field.propertyName == 'name') {
  618. return {
  619. name: 'cl-select',
  620. props: {
  621. options: [
  622. {
  623. label: '张三',
  624. value: '1'
  625. },
  626. {
  627. label: '李四',
  628. value: '2'
  629. }
  630. ]
  631. }
  632. };
  633. }
  634. // null 则不操作,按系统默认操作
  635. return null;
  636. }
  637. })
  638. ]
  639. });
  640. function refresh(params?: any) {
  641. Crud.value?.refresh(params);
  642. }
  643. const visible = ref(false);
  644. function open() {
  645. visible.value = true;
  646. }
  647. </script>
  648. ```