search.tsx 3.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177
  1. import { defineComponent, h, inject, mergeProps, nextTick, PropType, reactive, ref } from "vue";
  2. import { Close } from "@element-plus/icons-vue";
  3. import { useBrowser, useConfig, useCore } from "../../hooks";
  4. import { renderNode } from "../../utils/vnode";
  5. import { useApi } from "../form/helper";
  6. export default defineComponent({
  7. name: "cl-adv-search",
  8. components: {
  9. Close
  10. },
  11. props: {
  12. // 表单项
  13. items: {
  14. type: Array as PropType<ClForm.Item[]>,
  15. default: () => []
  16. },
  17. // 标题
  18. title: String,
  19. // 窗体大小
  20. size: {
  21. type: [Number, String],
  22. default: "30%"
  23. },
  24. // 操作按钮
  25. op: {
  26. type: Array,
  27. default: () => ["clear", "reset", "close", "search"]
  28. },
  29. // 搜索钩子
  30. onSearch: Function
  31. },
  32. emits: ["reset", "clear"],
  33. setup(props, { emit, slots, expose }) {
  34. const { crud, mitt } = useCore();
  35. const { style } = useConfig();
  36. const browser = useBrowser();
  37. // 配置
  38. const config = reactive<ClAdvSearch.Config>(
  39. mergeProps(props, inject("useAdvSearch__options") || {})
  40. );
  41. // cl-form
  42. const Form = ref<ClForm.Ref>();
  43. // el-drawer
  44. const Drawer = ref();
  45. // 是否可见
  46. const visible = ref(false);
  47. // 打开
  48. function open() {
  49. visible.value = true;
  50. nextTick(function () {
  51. Form.value?.open({
  52. items: config.items || [],
  53. op: {
  54. hidden: true
  55. },
  56. isReset: false
  57. });
  58. });
  59. }
  60. // 关闭
  61. function close() {
  62. Drawer.value.handleClose();
  63. }
  64. // 重置数据
  65. function reset() {
  66. Form.value?.reset();
  67. emit("reset");
  68. search();
  69. }
  70. // 清空数据
  71. function clear() {
  72. Form.value?.clear();
  73. emit("clear");
  74. }
  75. // 搜素请求
  76. function search() {
  77. Form.value?.submit((data) => {
  78. function next(params: any) {
  79. Form.value?.done();
  80. close();
  81. return crud.refresh({
  82. ...params,
  83. page: 1
  84. });
  85. }
  86. if (config.onSearch) {
  87. config.onSearch(data, { next, close });
  88. } else {
  89. next(data);
  90. }
  91. });
  92. }
  93. // 消息事件
  94. mitt.on("crud.openAdvSearch", open);
  95. // 渲染表单
  96. function renderForm() {
  97. return h(<cl-form ref={Form} inner enable-plugin={false} />, {}, slots);
  98. }
  99. // 渲染底部
  100. function renderFooter() {
  101. const fns = { search, reset, clear, close };
  102. return config.op?.map((e: string) => {
  103. switch (e) {
  104. case "search":
  105. case "reset":
  106. case "clear":
  107. case "close":
  108. return h(
  109. <el-button />,
  110. {
  111. type: e == "search" ? "primary" : null,
  112. size: style.size,
  113. onClick: fns[e]
  114. },
  115. { default: () => crud.dict.label[e] }
  116. );
  117. default:
  118. return renderNode(e, {
  119. scope: Form.value?.getForm(),
  120. slots
  121. });
  122. }
  123. });
  124. }
  125. expose({
  126. open,
  127. close,
  128. clear,
  129. ...useApi({ Form }),
  130. reset
  131. });
  132. return () => {
  133. return (
  134. <el-drawer
  135. ref={Drawer}
  136. modal-class="cl-adv-search"
  137. v-model={visible.value}
  138. direction="rtl"
  139. with-header={false}
  140. size={browser.isMini ? "100%" : config.size}>
  141. <div class="cl-adv-search__header">
  142. <span class="text">{config.title || crud.dict.label.advSearch}</span>
  143. <el-icon size={20} onClick={close}>
  144. <Close />
  145. </el-icon>
  146. </div>
  147. <div class="cl-adv-search__container">{renderForm()}</div>
  148. <div class="cl-adv-search__footer">{renderFooter()}</div>
  149. </el-drawer>
  150. );
  151. };
  152. }
  153. });