From bc59731083cc9ba3a103cf5e076f80ad92017b4e Mon Sep 17 00:00:00 2001 From: JaguarJack <82664165@qq.com> Date: Tue, 23 Apr 2024 13:12:02 +0800 Subject: [PATCH] =?UTF-8?q?feat:=E6=96=B0=E5=A2=9E=20form=20=E7=BB=84?= =?UTF-8?q?=E4=BB=B6?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../admin/components/catchForm/CatchForm.vue | 158 ++++++++++++++ .../admin/components/catchForm/Disabled.vue | 30 +++ .../admin/components/catchForm/FormItem.vue | 193 ++++++++++++++++++ .../admin/components/catchForm/FormRender.vue | 13 ++ .../catchForm/components/Alert/index.ts | 6 + .../catchForm/components/Button/Button.vue | 41 ++++ .../catchForm/components/Button/index.ts | 7 + .../catchForm/components/Card/Card.vue | 24 +++ .../catchForm/components/Card/index.ts | 7 + .../components/Cascader/Cascader.vue | 55 +++++ .../catchForm/components/Cascader/index.ts | 7 + .../components/Checkbox/Checkbox.vue | 71 +++++++ .../catchForm/components/Checkbox/index.ts | 7 + .../components/Collapse/Collapse.vue | 34 +++ .../catchForm/components/Collapse/index.ts | 7 + .../components/ColorPicker/ColorPicker.vue | 24 +++ .../catchForm/components/ColorPicker/index.ts | 6 + .../catchForm/components/Custom/Custom.vue | 30 +++ .../catchForm/components/Custom/index.ts | 11 + .../catchForm/components/DatePicker/index.ts | 7 + .../catchForm/components/Divider/Divider.vue | 13 ++ .../catchForm/components/Divider/index.ts | 7 + .../components/FormList/FormList.vue | 161 +++++++++++++++ .../catchForm/components/FormList/index.ts | 7 + .../catchForm/components/Gird/Grid.vue | 36 ++++ .../catchForm/components/Gird/index.ts | 7 + .../components/IconSelect/IconSelect.vue | 21 ++ .../catchForm/components/IconSelect/index.ts | 7 + .../catchForm/components/Inline/Inline.vue | 20 ++ .../catchForm/components/Inline/index.ts | 7 + .../catchForm/components/Input/index.ts | 8 + .../components/InputNumber/InputNumber.vue | 39 ++++ .../catchForm/components/InputNumber/index.ts | 7 + .../catchForm/components/Password/index.ts | 8 + .../catchForm/components/Radio/Radio.vue | 68 ++++++ .../catchForm/components/Radio/index.ts | 7 + .../catchForm/components/Rate/index.ts | 7 + .../catchForm/components/Select/Select.vue | 84 ++++++++ .../catchForm/components/Select/index.ts | 7 + .../catchForm/components/Slider/index.ts | 7 + .../catchForm/components/Switch/index.ts | 7 + .../catchForm/components/Switch/index.vue | 28 +++ .../catchForm/components/TextArea/index.ts | 8 + .../catchForm/components/Title/Title.vue | 23 +++ .../catchForm/components/Title/index.ts | 7 + .../components/Transfer/Transfer.vue | 38 ++++ .../catchForm/components/Transfer/index.ts | 7 + .../catchForm/components/Tree/Tree.vue | 86 ++++++++ .../catchForm/components/Tree/index.ts | 7 + .../catchForm/components/Upload/Upload.vue | 79 +++++++ .../catchForm/components/Upload/index.ts | 7 + .../components/UploadFile/UploadFile.vue | 78 +++++++ .../catchForm/components/UploadFile/index.ts | 7 + .../components/UploadFiles/UploadFiles.vue | 93 +++++++++ .../catchForm/components/UploadFiles/index.ts | 7 + .../components/UploadImage/UploadImage.vue | 73 +++++++ .../catchForm/components/UploadImage/index.ts | 7 + .../components/UploadImages/UploadImages.vue | 95 +++++++++ .../components/UploadImages/index.ts | 7 + .../components/catchForm/components/index.ts | 12 ++ .../catchForm/config/commonAttr/apiAttr.js | 64 ++++++ .../catchForm/config/commonAttr/basicAttr.js | 47 +++++ .../catchForm/config/commonAttr/highAttr.js | 18 ++ .../catchForm/config/commonAttr/index.js | 6 + .../config/commonAttr/linkageAttr.js | 36 ++++ .../catchForm/config/commonAttr/mergeAttr.js | 32 +++ .../catchForm/config/commonAttr/optionAttr.js | 91 +++++++++ .../components/catchForm/config/commonType.ts | 70 +++++++ .../components/catchForm/config/symbol.ts | 10 + .../components/catchForm/directive/index.js | 2 + .../catchForm/directive/selectLoadMore.js | 23 +++ .../catchForm/directive/tableLoadMore.js | 20 ++ .../components/catchForm/hooks/useRequest.js | 49 +++++ .../components/catchForm/hooks/useSelect.js | 151 ++++++++++++++ resources/admin/components/catchForm/index.ts | 69 +++++++ .../components/catchForm/support/index.ts | 163 +++++++++++++++ 76 files changed, 2793 insertions(+) create mode 100644 resources/admin/components/catchForm/CatchForm.vue create mode 100644 resources/admin/components/catchForm/Disabled.vue create mode 100644 resources/admin/components/catchForm/FormItem.vue create mode 100644 resources/admin/components/catchForm/FormRender.vue create mode 100644 resources/admin/components/catchForm/components/Alert/index.ts create mode 100644 resources/admin/components/catchForm/components/Button/Button.vue create mode 100644 resources/admin/components/catchForm/components/Button/index.ts create mode 100644 resources/admin/components/catchForm/components/Card/Card.vue create mode 100644 resources/admin/components/catchForm/components/Card/index.ts create mode 100644 resources/admin/components/catchForm/components/Cascader/Cascader.vue create mode 100644 resources/admin/components/catchForm/components/Cascader/index.ts create mode 100644 resources/admin/components/catchForm/components/Checkbox/Checkbox.vue create mode 100644 resources/admin/components/catchForm/components/Checkbox/index.ts create mode 100644 resources/admin/components/catchForm/components/Collapse/Collapse.vue create mode 100644 resources/admin/components/catchForm/components/Collapse/index.ts create mode 100644 resources/admin/components/catchForm/components/ColorPicker/ColorPicker.vue create mode 100644 resources/admin/components/catchForm/components/ColorPicker/index.ts create mode 100644 resources/admin/components/catchForm/components/Custom/Custom.vue create mode 100644 resources/admin/components/catchForm/components/Custom/index.ts create mode 100644 resources/admin/components/catchForm/components/DatePicker/index.ts create mode 100644 resources/admin/components/catchForm/components/Divider/Divider.vue create mode 100644 resources/admin/components/catchForm/components/Divider/index.ts create mode 100644 resources/admin/components/catchForm/components/FormList/FormList.vue create mode 100644 resources/admin/components/catchForm/components/FormList/index.ts create mode 100644 resources/admin/components/catchForm/components/Gird/Grid.vue create mode 100644 resources/admin/components/catchForm/components/Gird/index.ts create mode 100644 resources/admin/components/catchForm/components/IconSelect/IconSelect.vue create mode 100644 resources/admin/components/catchForm/components/IconSelect/index.ts create mode 100644 resources/admin/components/catchForm/components/Inline/Inline.vue create mode 100644 resources/admin/components/catchForm/components/Inline/index.ts create mode 100644 resources/admin/components/catchForm/components/Input/index.ts create mode 100644 resources/admin/components/catchForm/components/InputNumber/InputNumber.vue create mode 100644 resources/admin/components/catchForm/components/InputNumber/index.ts create mode 100644 resources/admin/components/catchForm/components/Password/index.ts create mode 100644 resources/admin/components/catchForm/components/Radio/Radio.vue create mode 100644 resources/admin/components/catchForm/components/Radio/index.ts create mode 100644 resources/admin/components/catchForm/components/Rate/index.ts create mode 100644 resources/admin/components/catchForm/components/Select/Select.vue create mode 100644 resources/admin/components/catchForm/components/Select/index.ts create mode 100644 resources/admin/components/catchForm/components/Slider/index.ts create mode 100644 resources/admin/components/catchForm/components/Switch/index.ts create mode 100644 resources/admin/components/catchForm/components/Switch/index.vue create mode 100644 resources/admin/components/catchForm/components/TextArea/index.ts create mode 100644 resources/admin/components/catchForm/components/Title/Title.vue create mode 100644 resources/admin/components/catchForm/components/Title/index.ts create mode 100644 resources/admin/components/catchForm/components/Transfer/Transfer.vue create mode 100644 resources/admin/components/catchForm/components/Transfer/index.ts create mode 100644 resources/admin/components/catchForm/components/Tree/Tree.vue create mode 100644 resources/admin/components/catchForm/components/Tree/index.ts create mode 100644 resources/admin/components/catchForm/components/Upload/Upload.vue create mode 100644 resources/admin/components/catchForm/components/Upload/index.ts create mode 100644 resources/admin/components/catchForm/components/UploadFile/UploadFile.vue create mode 100644 resources/admin/components/catchForm/components/UploadFile/index.ts create mode 100644 resources/admin/components/catchForm/components/UploadFiles/UploadFiles.vue create mode 100644 resources/admin/components/catchForm/components/UploadFiles/index.ts create mode 100644 resources/admin/components/catchForm/components/UploadImage/UploadImage.vue create mode 100644 resources/admin/components/catchForm/components/UploadImage/index.ts create mode 100644 resources/admin/components/catchForm/components/UploadImages/UploadImages.vue create mode 100644 resources/admin/components/catchForm/components/UploadImages/index.ts create mode 100644 resources/admin/components/catchForm/components/index.ts create mode 100644 resources/admin/components/catchForm/config/commonAttr/apiAttr.js create mode 100644 resources/admin/components/catchForm/config/commonAttr/basicAttr.js create mode 100644 resources/admin/components/catchForm/config/commonAttr/highAttr.js create mode 100644 resources/admin/components/catchForm/config/commonAttr/index.js create mode 100644 resources/admin/components/catchForm/config/commonAttr/linkageAttr.js create mode 100644 resources/admin/components/catchForm/config/commonAttr/mergeAttr.js create mode 100644 resources/admin/components/catchForm/config/commonAttr/optionAttr.js create mode 100644 resources/admin/components/catchForm/config/commonType.ts create mode 100644 resources/admin/components/catchForm/config/symbol.ts create mode 100644 resources/admin/components/catchForm/directive/index.js create mode 100644 resources/admin/components/catchForm/directive/selectLoadMore.js create mode 100644 resources/admin/components/catchForm/directive/tableLoadMore.js create mode 100644 resources/admin/components/catchForm/hooks/useRequest.js create mode 100644 resources/admin/components/catchForm/hooks/useSelect.js create mode 100644 resources/admin/components/catchForm/index.ts create mode 100644 resources/admin/components/catchForm/support/index.ts diff --git a/resources/admin/components/catchForm/CatchForm.vue b/resources/admin/components/catchForm/CatchForm.vue new file mode 100644 index 0000000..023a529 --- /dev/null +++ b/resources/admin/components/catchForm/CatchForm.vue @@ -0,0 +1,158 @@ + + + + + + + + + + diff --git a/resources/admin/components/catchForm/Disabled.vue b/resources/admin/components/catchForm/Disabled.vue new file mode 100644 index 0000000..78a9da7 --- /dev/null +++ b/resources/admin/components/catchForm/Disabled.vue @@ -0,0 +1,30 @@ + + + + + + + + + + + + diff --git a/resources/admin/components/catchForm/FormItem.vue b/resources/admin/components/catchForm/FormItem.vue new file mode 100644 index 0000000..85868e8 --- /dev/null +++ b/resources/admin/components/catchForm/FormItem.vue @@ -0,0 +1,193 @@ + + + + + + + + + + + + + + + + + + + + + diff --git a/resources/admin/components/catchForm/FormRender.vue b/resources/admin/components/catchForm/FormRender.vue new file mode 100644 index 0000000..1bf9ed6 --- /dev/null +++ b/resources/admin/components/catchForm/FormRender.vue @@ -0,0 +1,13 @@ + + + + + + diff --git a/resources/admin/components/catchForm/components/Alert/index.ts b/resources/admin/components/catchForm/components/Alert/index.ts new file mode 100644 index 0000000..804629a --- /dev/null +++ b/resources/admin/components/catchForm/components/Alert/index.ts @@ -0,0 +1,6 @@ +import { ElAlert } from 'element-plus' +export default { + name: 'alert', + component: ElAlert, + type: 'assist' +} diff --git a/resources/admin/components/catchForm/components/Button/Button.vue b/resources/admin/components/catchForm/components/Button/Button.vue new file mode 100644 index 0000000..2c24f7a --- /dev/null +++ b/resources/admin/components/catchForm/components/Button/Button.vue @@ -0,0 +1,41 @@ + + {{ name }} + + + + + diff --git a/resources/admin/components/catchForm/components/Button/index.ts b/resources/admin/components/catchForm/components/Button/index.ts new file mode 100644 index 0000000..ed2ac51 --- /dev/null +++ b/resources/admin/components/catchForm/components/Button/index.ts @@ -0,0 +1,7 @@ +import Button from './Button.vue' + +export default { + name: 'button', + component: Button, + type: 'assist' +} diff --git a/resources/admin/components/catchForm/components/Card/Card.vue b/resources/admin/components/catchForm/components/Card/Card.vue new file mode 100644 index 0000000..57afa13 --- /dev/null +++ b/resources/admin/components/catchForm/components/Card/Card.vue @@ -0,0 +1,24 @@ + + + + + + + + + diff --git a/resources/admin/components/catchForm/components/Card/index.ts b/resources/admin/components/catchForm/components/Card/index.ts new file mode 100644 index 0000000..ddc4d95 --- /dev/null +++ b/resources/admin/components/catchForm/components/Card/index.ts @@ -0,0 +1,7 @@ +import Card from './Card.vue' + +export default { + name: 'card', + component: Card, + type: 'layout' +} diff --git a/resources/admin/components/catchForm/components/Cascader/Cascader.vue b/resources/admin/components/catchForm/components/Cascader/Cascader.vue new file mode 100644 index 0000000..d48abd6 --- /dev/null +++ b/resources/admin/components/catchForm/components/Cascader/Cascader.vue @@ -0,0 +1,55 @@ + + + + + diff --git a/resources/admin/components/catchForm/components/Cascader/index.ts b/resources/admin/components/catchForm/components/Cascader/index.ts new file mode 100644 index 0000000..6dd517c --- /dev/null +++ b/resources/admin/components/catchForm/components/Cascader/index.ts @@ -0,0 +1,7 @@ +import Cascader from './Cascader.vue' + +export default { + name: 'cascader', + type: 'basic', + component: Cascader +} diff --git a/resources/admin/components/catchForm/components/Checkbox/Checkbox.vue b/resources/admin/components/catchForm/components/Checkbox/Checkbox.vue new file mode 100644 index 0000000..50a470b --- /dev/null +++ b/resources/admin/components/catchForm/components/Checkbox/Checkbox.vue @@ -0,0 +1,71 @@ + + 暂无选项 + + + + {{ item[label] }} + + + + {{ item[label] }} + + + + + + + diff --git a/resources/admin/components/catchForm/components/Checkbox/index.ts b/resources/admin/components/catchForm/components/Checkbox/index.ts new file mode 100644 index 0000000..1089fbb --- /dev/null +++ b/resources/admin/components/catchForm/components/Checkbox/index.ts @@ -0,0 +1,7 @@ +import Checkbox from './Checkbox.vue' + +export default { + name: 'checkbox', + type: 'basic', + component: Checkbox +} diff --git a/resources/admin/components/catchForm/components/Collapse/Collapse.vue b/resources/admin/components/catchForm/components/Collapse/Collapse.vue new file mode 100644 index 0000000..db7743b --- /dev/null +++ b/resources/admin/components/catchForm/components/Collapse/Collapse.vue @@ -0,0 +1,34 @@ + + + + + + + + + + + + + + diff --git a/resources/admin/components/catchForm/components/Collapse/index.ts b/resources/admin/components/catchForm/components/Collapse/index.ts new file mode 100644 index 0000000..4c65eea --- /dev/null +++ b/resources/admin/components/catchForm/components/Collapse/index.ts @@ -0,0 +1,7 @@ +import Collapse from './Collapse.vue' + +export default { + name: 'collapse', + component: Collapse, + type: 'layout' +} diff --git a/resources/admin/components/catchForm/components/ColorPicker/ColorPicker.vue b/resources/admin/components/catchForm/components/ColorPicker/ColorPicker.vue new file mode 100644 index 0000000..1ecb9e2 --- /dev/null +++ b/resources/admin/components/catchForm/components/ColorPicker/ColorPicker.vue @@ -0,0 +1,24 @@ + + + + + + + diff --git a/resources/admin/components/catchForm/components/ColorPicker/index.ts b/resources/admin/components/catchForm/components/ColorPicker/index.ts new file mode 100644 index 0000000..f27309a --- /dev/null +++ b/resources/admin/components/catchForm/components/ColorPicker/index.ts @@ -0,0 +1,6 @@ +import { ElColorPicker } from 'element-plus' +export default { + name: 'color_picker', + component: ElColorPicker, + type: 'basic' +} diff --git a/resources/admin/components/catchForm/components/Custom/Custom.vue b/resources/admin/components/catchForm/components/Custom/Custom.vue new file mode 100644 index 0000000..d2e9cf4 --- /dev/null +++ b/resources/admin/components/catchForm/components/Custom/Custom.vue @@ -0,0 +1,30 @@ + + 请输入全局注册得组件名 + + + + + + diff --git a/resources/admin/components/catchForm/components/Custom/index.ts b/resources/admin/components/catchForm/components/Custom/index.ts new file mode 100644 index 0000000..dfb8aa0 --- /dev/null +++ b/resources/admin/components/catchForm/components/Custom/index.ts @@ -0,0 +1,11 @@ +import Custom from './Custom.vue' + +export default { + name: 'custom', + component: Custom, + initialValues: { + label: '自定义组件', + component: 'Custom', + props: {} + } +} diff --git a/resources/admin/components/catchForm/components/DatePicker/index.ts b/resources/admin/components/catchForm/components/DatePicker/index.ts new file mode 100644 index 0000000..b6cc3e9 --- /dev/null +++ b/resources/admin/components/catchForm/components/DatePicker/index.ts @@ -0,0 +1,7 @@ +import { ElDatePicker } from 'element-plus' + +export default { + name: 'date_picker', + component: ElDatePicker, + type: 'basic' +} diff --git a/resources/admin/components/catchForm/components/Divider/Divider.vue b/resources/admin/components/catchForm/components/Divider/Divider.vue new file mode 100644 index 0000000..3a9a6fd --- /dev/null +++ b/resources/admin/components/catchForm/components/Divider/Divider.vue @@ -0,0 +1,13 @@ + + {{ title }} + + + + + diff --git a/resources/admin/components/catchForm/components/Divider/index.ts b/resources/admin/components/catchForm/components/Divider/index.ts new file mode 100644 index 0000000..acc2ae0 --- /dev/null +++ b/resources/admin/components/catchForm/components/Divider/index.ts @@ -0,0 +1,7 @@ +import Divider from './Divider.vue' + +export default { + name: 'divider', + component: Divider, + type: 'assist' +} diff --git a/resources/admin/components/catchForm/components/FormList/FormList.vue b/resources/admin/components/catchForm/components/FormList/FormList.vue new file mode 100644 index 0000000..c074936 --- /dev/null +++ b/resources/admin/components/catchForm/components/FormList/FormList.vue @@ -0,0 +1,161 @@ + + + + + + + + + + + + + + + + + + + + + + {{ title + (index + 1) }} + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/resources/admin/components/catchForm/components/FormList/index.ts b/resources/admin/components/catchForm/components/FormList/index.ts new file mode 100644 index 0000000..62df07b --- /dev/null +++ b/resources/admin/components/catchForm/components/FormList/index.ts @@ -0,0 +1,7 @@ +import FormList from './FormList.vue' + +export default { + name: 'form_list', + component: FormList, + type: 'high' +} diff --git a/resources/admin/components/catchForm/components/Gird/Grid.vue b/resources/admin/components/catchForm/components/Gird/Grid.vue new file mode 100644 index 0000000..2e0be19 --- /dev/null +++ b/resources/admin/components/catchForm/components/Gird/Grid.vue @@ -0,0 +1,36 @@ + + + + + + + + + + + diff --git a/resources/admin/components/catchForm/components/Gird/index.ts b/resources/admin/components/catchForm/components/Gird/index.ts new file mode 100644 index 0000000..f637e9a --- /dev/null +++ b/resources/admin/components/catchForm/components/Gird/index.ts @@ -0,0 +1,7 @@ +import Grid from './Grid.vue' + +export default { + name: 'grid', + type: 'layout', + component: Grid +} diff --git a/resources/admin/components/catchForm/components/IconSelect/IconSelect.vue b/resources/admin/components/catchForm/components/IconSelect/IconSelect.vue new file mode 100644 index 0000000..05ae59e --- /dev/null +++ b/resources/admin/components/catchForm/components/IconSelect/IconSelect.vue @@ -0,0 +1,21 @@ + + + + + + + + + + + + diff --git a/resources/admin/components/catchForm/components/IconSelect/index.ts b/resources/admin/components/catchForm/components/IconSelect/index.ts new file mode 100644 index 0000000..4196d7d --- /dev/null +++ b/resources/admin/components/catchForm/components/IconSelect/index.ts @@ -0,0 +1,7 @@ +import IconSelect from './IconSelect.vue' + +export default { + name: 'icon_select', + type: 'basic', + component: IconSelect +} diff --git a/resources/admin/components/catchForm/components/Inline/Inline.vue b/resources/admin/components/catchForm/components/Inline/Inline.vue new file mode 100644 index 0000000..3174c3d --- /dev/null +++ b/resources/admin/components/catchForm/components/Inline/Inline.vue @@ -0,0 +1,20 @@ + + + + + + + + + diff --git a/resources/admin/components/catchForm/components/Inline/index.ts b/resources/admin/components/catchForm/components/Inline/index.ts new file mode 100644 index 0000000..aab6b9c --- /dev/null +++ b/resources/admin/components/catchForm/components/Inline/index.ts @@ -0,0 +1,7 @@ +import Inline from './Inline.vue' + +export default { + name: 'inline', + type: 'layout', + component: Inline +} diff --git a/resources/admin/components/catchForm/components/Input/index.ts b/resources/admin/components/catchForm/components/Input/index.ts new file mode 100644 index 0000000..bbb5157 --- /dev/null +++ b/resources/admin/components/catchForm/components/Input/index.ts @@ -0,0 +1,8 @@ +import { ElInput } from 'element-plus' +import { h } from 'vue' + +export default { + name: 'input', + component: h(ElInput, { showWordLimit: true, autocomplete: 'off' }), + type: 'basic' +} diff --git a/resources/admin/components/catchForm/components/InputNumber/InputNumber.vue b/resources/admin/components/catchForm/components/InputNumber/InputNumber.vue new file mode 100644 index 0000000..7336521 --- /dev/null +++ b/resources/admin/components/catchForm/components/InputNumber/InputNumber.vue @@ -0,0 +1,39 @@ + + + + {{ unit }} + + + + + + diff --git a/resources/admin/components/catchForm/components/InputNumber/index.ts b/resources/admin/components/catchForm/components/InputNumber/index.ts new file mode 100644 index 0000000..ff822b6 --- /dev/null +++ b/resources/admin/components/catchForm/components/InputNumber/index.ts @@ -0,0 +1,7 @@ +import InputNumber from './InputNumber.vue' + +export default { + name: 'input_number', + type: 'basic', + component: InputNumber +} diff --git a/resources/admin/components/catchForm/components/Password/index.ts b/resources/admin/components/catchForm/components/Password/index.ts new file mode 100644 index 0000000..00a1278 --- /dev/null +++ b/resources/admin/components/catchForm/components/Password/index.ts @@ -0,0 +1,8 @@ +import { ElInput } from 'element-plus' +import { h } from 'vue' + +export default { + name: 'password', + component: h(ElInput, { type: 'password', showWordLimit: true, autocomplete: 'off' }), + type: 'basic' +} diff --git a/resources/admin/components/catchForm/components/Radio/Radio.vue b/resources/admin/components/catchForm/components/Radio/Radio.vue new file mode 100644 index 0000000..72e5bac --- /dev/null +++ b/resources/admin/components/catchForm/components/Radio/Radio.vue @@ -0,0 +1,68 @@ + + + 暂无选项 + + + + {{ item[label] }} + + + + {{ item[label] }} + + + + + {{ item[label] }} + + + + {{ item[label] }} + + + + + + diff --git a/resources/admin/components/catchForm/components/Radio/index.ts b/resources/admin/components/catchForm/components/Radio/index.ts new file mode 100644 index 0000000..1c2a11c --- /dev/null +++ b/resources/admin/components/catchForm/components/Radio/index.ts @@ -0,0 +1,7 @@ +import Radio from './Radio.vue' + +export default { + name: 'radio', + type: 'basic', + component: Radio +} diff --git a/resources/admin/components/catchForm/components/Rate/index.ts b/resources/admin/components/catchForm/components/Rate/index.ts new file mode 100644 index 0000000..29f26f5 --- /dev/null +++ b/resources/admin/components/catchForm/components/Rate/index.ts @@ -0,0 +1,7 @@ +import { ElRate } from 'element-plus' + +export default { + name: 'rate', + component: ElRate, + type: 'basic' +} diff --git a/resources/admin/components/catchForm/components/Select/Select.vue b/resources/admin/components/catchForm/components/Select/Select.vue new file mode 100644 index 0000000..711556f --- /dev/null +++ b/resources/admin/components/catchForm/components/Select/Select.vue @@ -0,0 +1,84 @@ + + + + + + + + + + + + + + diff --git a/resources/admin/components/catchForm/components/Select/index.ts b/resources/admin/components/catchForm/components/Select/index.ts new file mode 100644 index 0000000..0f01d06 --- /dev/null +++ b/resources/admin/components/catchForm/components/Select/index.ts @@ -0,0 +1,7 @@ +import Select from './Select.vue' + +export default { + name: 'select', + type: 'basic', + component: Select +} diff --git a/resources/admin/components/catchForm/components/Slider/index.ts b/resources/admin/components/catchForm/components/Slider/index.ts new file mode 100644 index 0000000..04cc978 --- /dev/null +++ b/resources/admin/components/catchForm/components/Slider/index.ts @@ -0,0 +1,7 @@ +import { ElSlider } from 'element-plus' + +export default { + name: 'slider', + component: ElSlider, + type: 'basic' +} diff --git a/resources/admin/components/catchForm/components/Switch/index.ts b/resources/admin/components/catchForm/components/Switch/index.ts new file mode 100644 index 0000000..cc87c9f --- /dev/null +++ b/resources/admin/components/catchForm/components/Switch/index.ts @@ -0,0 +1,7 @@ +import { ElSwitch } from 'element-plus' +import cswitch from './index.vue' +export default { + name: 'switch', + component: cswitch, + type: 'basic' +} diff --git a/resources/admin/components/catchForm/components/Switch/index.vue b/resources/admin/components/catchForm/components/Switch/index.vue new file mode 100644 index 0000000..72cbf3f --- /dev/null +++ b/resources/admin/components/catchForm/components/Switch/index.vue @@ -0,0 +1,28 @@ + + + + + diff --git a/resources/admin/components/catchForm/components/TextArea/index.ts b/resources/admin/components/catchForm/components/TextArea/index.ts new file mode 100644 index 0000000..f2a4548 --- /dev/null +++ b/resources/admin/components/catchForm/components/TextArea/index.ts @@ -0,0 +1,8 @@ +import { ElInput } from 'element-plus' +import { h } from 'vue' + +export default { + name: 'textarea', + component: h(ElInput, { type: 'textarea', showWordLimit: true, autocomplete: 'off' }), + type: 'basic' +} diff --git a/resources/admin/components/catchForm/components/Title/Title.vue b/resources/admin/components/catchForm/components/Title/Title.vue new file mode 100644 index 0000000..878505d --- /dev/null +++ b/resources/admin/components/catchForm/components/Title/Title.vue @@ -0,0 +1,23 @@ + + {{ + title + }} + + + diff --git a/resources/admin/components/catchForm/components/Title/index.ts b/resources/admin/components/catchForm/components/Title/index.ts new file mode 100644 index 0000000..ba6041b --- /dev/null +++ b/resources/admin/components/catchForm/components/Title/index.ts @@ -0,0 +1,7 @@ +import Title from './Title.vue' + +export default { + name: 'title', + component: Title, + type: 'assist' +} diff --git a/resources/admin/components/catchForm/components/Transfer/Transfer.vue b/resources/admin/components/catchForm/components/Transfer/Transfer.vue new file mode 100644 index 0000000..a45e5f9 --- /dev/null +++ b/resources/admin/components/catchForm/components/Transfer/Transfer.vue @@ -0,0 +1,38 @@ + + + + + diff --git a/resources/admin/components/catchForm/components/Transfer/index.ts b/resources/admin/components/catchForm/components/Transfer/index.ts new file mode 100644 index 0000000..36416d2 --- /dev/null +++ b/resources/admin/components/catchForm/components/Transfer/index.ts @@ -0,0 +1,7 @@ +import Transfer from './Transfer.vue' + +export default { + name: 'transfer', + type: 'basic', + component: Transfer +} diff --git a/resources/admin/components/catchForm/components/Tree/Tree.vue b/resources/admin/components/catchForm/components/Tree/Tree.vue new file mode 100644 index 0000000..5997c37 --- /dev/null +++ b/resources/admin/components/catchForm/components/Tree/Tree.vue @@ -0,0 +1,86 @@ + + + + + diff --git a/resources/admin/components/catchForm/components/Tree/index.ts b/resources/admin/components/catchForm/components/Tree/index.ts new file mode 100644 index 0000000..dfeb021 --- /dev/null +++ b/resources/admin/components/catchForm/components/Tree/index.ts @@ -0,0 +1,7 @@ +import Tree from './Tree.vue' + +export default { + name: 'tree', + type: 'basic', + component: Tree +} diff --git a/resources/admin/components/catchForm/components/Upload/Upload.vue b/resources/admin/components/catchForm/components/Upload/Upload.vue new file mode 100644 index 0000000..ff235c5 --- /dev/null +++ b/resources/admin/components/catchForm/components/Upload/Upload.vue @@ -0,0 +1,79 @@ + + + + + {{ buttonText }} + + + + + diff --git a/resources/admin/components/catchForm/components/Upload/index.ts b/resources/admin/components/catchForm/components/Upload/index.ts new file mode 100644 index 0000000..8b6c20b --- /dev/null +++ b/resources/admin/components/catchForm/components/Upload/index.ts @@ -0,0 +1,7 @@ +import Upload from './Upload.vue' + +export default { + name: 'upload', + component: Upload, + type: 'basic' +} diff --git a/resources/admin/components/catchForm/components/UploadFile/UploadFile.vue b/resources/admin/components/catchForm/components/UploadFile/UploadFile.vue new file mode 100644 index 0000000..70ddb12 --- /dev/null +++ b/resources/admin/components/catchForm/components/UploadFile/UploadFile.vue @@ -0,0 +1,78 @@ + + + + + {{ filename }} + + + + 点击上传文件 + + + + + + diff --git a/resources/admin/components/catchForm/components/UploadFile/index.ts b/resources/admin/components/catchForm/components/UploadFile/index.ts new file mode 100644 index 0000000..0d6c194 --- /dev/null +++ b/resources/admin/components/catchForm/components/UploadFile/index.ts @@ -0,0 +1,7 @@ +import UploadFile from './UploadFile.vue' + +export default { + name: 'upload_file', + component: UploadFile, + type: 'basic' +} diff --git a/resources/admin/components/catchForm/components/UploadFiles/UploadFiles.vue b/resources/admin/components/catchForm/components/UploadFiles/UploadFiles.vue new file mode 100644 index 0000000..156c5a6 --- /dev/null +++ b/resources/admin/components/catchForm/components/UploadFiles/UploadFiles.vue @@ -0,0 +1,93 @@ + + + + + + + 点击上传文件 + + + + + {{ getFilename(item) }} + + + + + + + diff --git a/resources/admin/components/catchForm/components/UploadFiles/index.ts b/resources/admin/components/catchForm/components/UploadFiles/index.ts new file mode 100644 index 0000000..4a37de9 --- /dev/null +++ b/resources/admin/components/catchForm/components/UploadFiles/index.ts @@ -0,0 +1,7 @@ +import UploadFiles from './UploadFiles.vue' + +export default { + name: 'upload_files', + component: UploadFiles, + type: 'basic' +} diff --git a/resources/admin/components/catchForm/components/UploadImage/UploadImage.vue b/resources/admin/components/catchForm/components/UploadImage/UploadImage.vue new file mode 100644 index 0000000..9ad3022 --- /dev/null +++ b/resources/admin/components/catchForm/components/UploadImage/UploadImage.vue @@ -0,0 +1,73 @@ + + + + + + + + + + + diff --git a/resources/admin/components/catchForm/components/UploadImage/index.ts b/resources/admin/components/catchForm/components/UploadImage/index.ts new file mode 100644 index 0000000..a028e75 --- /dev/null +++ b/resources/admin/components/catchForm/components/UploadImage/index.ts @@ -0,0 +1,7 @@ +import UploadImage from './UploadImage.vue' + +export default { + name: 'upload_image', + component: UploadImage, + type: 'basic' +} diff --git a/resources/admin/components/catchForm/components/UploadImages/UploadImages.vue b/resources/admin/components/catchForm/components/UploadImages/UploadImages.vue new file mode 100644 index 0000000..3e1c5ac --- /dev/null +++ b/resources/admin/components/catchForm/components/UploadImages/UploadImages.vue @@ -0,0 +1,95 @@ + + + + + + + + + + + + + + + + + + + + + diff --git a/resources/admin/components/catchForm/components/UploadImages/index.ts b/resources/admin/components/catchForm/components/UploadImages/index.ts new file mode 100644 index 0000000..e69a2e5 --- /dev/null +++ b/resources/admin/components/catchForm/components/UploadImages/index.ts @@ -0,0 +1,7 @@ +import UploadImages from './UploadImages.vue' + +export default { + name: 'upload_images', + component: UploadImages, + type: 'basic' +} diff --git a/resources/admin/components/catchForm/components/index.ts b/resources/admin/components/catchForm/components/index.ts new file mode 100644 index 0000000..01fdd42 --- /dev/null +++ b/resources/admin/components/catchForm/components/index.ts @@ -0,0 +1,12 @@ +import type { formElement } from '/admin/components/catchForm/config/commonType' + +const modules = import.meta.glob('./*/index.ts', { eager: true }) +const components: { [component: string]: formElement } = {} + +for (const path in modules) { + const data = (modules[path] as { default: formElement }).default + if (data) { + components[data.name] = data + } +} +export default components diff --git a/resources/admin/components/catchForm/config/commonAttr/apiAttr.js b/resources/admin/components/catchForm/config/commonAttr/apiAttr.js new file mode 100644 index 0000000..4969347 --- /dev/null +++ b/resources/admin/components/catchForm/config/commonAttr/apiAttr.js @@ -0,0 +1,64 @@ +export default [ + { + label: 'url', + component: 'Input', + name: 'props.api.url', + initialValue: '/current/query/article', + designKey: 'form-UrE8' + }, + { + label: '请求方式', + component: 'Radio', + name: 'props.api.method', + props: { + mode: 'static', + autoSelectedFirst: true, + options: [ + { + label: 'GET', + value: 'GET' + }, + { + label: 'POST', + value: 'POST' + }, + { + label: 'PUT', + value: 'PUT' + }, + { + label: 'DELETE', + value: 'DELETE' + } + ] + }, + designKey: 'form-nOpD' + }, + { + label: '请求参数', + component: 'JsonEdit', + name: 'props.api.params', + hidden: '{{ ["POST","PUT"].includes($values.props.api.method) }}', + initialValue: {}, + props: { + mode: 'dialog' + } + }, + { + label: '请求参数', + component: 'JsonEdit', + name: 'props.api.data', + hidden: '{{ ["GET","DELETE"].includes($values.props.api.method) }}', + initialValue: {}, + props: { + mode: 'dialog' + } + }, + { + label: '数据路径', + component: 'Input', + name: 'props.api.dataPath', + initialValue: 'data', + designKey: 'form-UrE8' + } +] diff --git a/resources/admin/components/catchForm/config/commonAttr/basicAttr.js b/resources/admin/components/catchForm/config/commonAttr/basicAttr.js new file mode 100644 index 0000000..591b464 --- /dev/null +++ b/resources/admin/components/catchForm/config/commonAttr/basicAttr.js @@ -0,0 +1,47 @@ +import { recursionDelete } from '/admin/components/catchForm/support' + +const basicAttr = (omit = [], moreAttrs = []) => { + const attr = [ + { label: '标签', component: 'Input', name: 'label' }, + { + label: '唯一标识', + component: 'Input', + name: 'name', + help: "既是唯一标识,也是数据路径。比如输入【props.name】,数据就会保存为 { props: { name:'xxx' } }" + }, + { label: '字段说明', component: 'Textarea', name: 'help' }, + { + label: '占位提示', + component: 'Input', + name: 'props.placeholder', + designKey: 'form-ekRL' + }, + { label: '初始值', component: 'Input', name: 'initialValue' }, + { + component: 'Grid', + children: [ + { label: '是否必填', component: 'Switch', name: 'required' }, + { label: '是否只读', component: 'Switch', name: 'props.readonly' }, + { label: '是否禁用', component: 'Switch', name: 'props.disabled' }, + { label: '隐藏字段', component: 'Switch', name: 'hidden' }, + { label: '隐藏标签', component: 'Switch', name: 'hideLabel' } + ], + props: { + columns: 3, + 'row-gap': 0, + 'column-gap': 20 + }, + designKey: 'form-R003', + name: 'cNmCuu', + style: { + marginBottom: 0 + } + } + ] + + const omitAttrs = recursionDelete(attr, (item) => !omit.includes(item.name)) + + return [...omitAttrs, ...moreAttrs] +} + +export default basicAttr diff --git a/resources/admin/components/catchForm/config/commonAttr/highAttr.js b/resources/admin/components/catchForm/config/commonAttr/highAttr.js new file mode 100644 index 0000000..3e0a55b --- /dev/null +++ b/resources/admin/components/catchForm/config/commonAttr/highAttr.js @@ -0,0 +1,18 @@ +const basicAttr = (omit = []) => { + const attr = [ + { label: '自定义class', component: 'Input', name: 'props.class' }, + { + label: '自定义style', + component: 'JsonEdit', + name: 'props.style', + help: '与vue的style对象格式一样', + props: { + mode: 'dialog' + } + } + ] + + return attr.filter((item) => !omit.includes(item.name)) +} + +export default basicAttr diff --git a/resources/admin/components/catchForm/config/commonAttr/index.js b/resources/admin/components/catchForm/config/commonAttr/index.js new file mode 100644 index 0000000..3c4884e --- /dev/null +++ b/resources/admin/components/catchForm/config/commonAttr/index.js @@ -0,0 +1,6 @@ +export { default as basicAttr } from './basicAttr' +export { default as highAttr } from './highAttr' +export { default as apiAttr } from './apiAttr' +export { default as linkageAttr } from './linkageAttr' +export { default as optionAttr } from './optionAttr' +export { default as mergeAttr } from './mergeAttr' diff --git a/resources/admin/components/catchForm/config/commonAttr/linkageAttr.js b/resources/admin/components/catchForm/config/commonAttr/linkageAttr.js new file mode 100644 index 0000000..1d49f91 --- /dev/null +++ b/resources/admin/components/catchForm/config/commonAttr/linkageAttr.js @@ -0,0 +1,36 @@ +export default [ + { + component: 'Alert', + props: { + type: 'success', + description: '对于配置级的联动,请直接点击下方按钮【编辑配置文本】,通过插值表达式实现', + closable: true, + 'show-icon': true + }, + designKey: 'design-MQPU', + name: 'form-Oqi5' + }, + { + label: '值联动', + help: '本字段值改变时,修改其他字段的值', + name: 'change', + component: 'FormList', + children: [ + { + label: '目标字段', + name: 'target', + component: 'Input', + props: {} + }, + { + label: '值', + name: 'value', + component: 'Input', + props: {} + } + ], + props: { + mode: 'card' + } + } +] diff --git a/resources/admin/components/catchForm/config/commonAttr/mergeAttr.js b/resources/admin/components/catchForm/config/commonAttr/mergeAttr.js new file mode 100644 index 0000000..4f70ea6 --- /dev/null +++ b/resources/admin/components/catchForm/config/commonAttr/mergeAttr.js @@ -0,0 +1,32 @@ +const mergeAttr = (attrConfig) => { + const { basic = [], high = [], linkage = [] } = attrConfig + + const attrs = [ + { + component: 'Collapse', + name: 'mergeAttr', + children: [ + { + title: '常用属性', + name: 'basic', + checked: true, + children: basic + }, + { + title: '高级属性', + name: 'high', + children: high + }, + { + title: '联动规则', + name: 'linkage', + children: linkage + } + ] + } + ] + + return attrs +} + +export default mergeAttr diff --git a/resources/admin/components/catchForm/config/commonAttr/optionAttr.js b/resources/admin/components/catchForm/config/commonAttr/optionAttr.js new file mode 100644 index 0000000..ae69304 --- /dev/null +++ b/resources/admin/components/catchForm/config/commonAttr/optionAttr.js @@ -0,0 +1,91 @@ +import apiAttr from './apiAttr' + +export default [ + { + component: 'Divider', + props: { + title: '选项设置', + contentPosition: 'center' + }, + designKey: 'design-gSnX', + name: 'form-xDEe', + style: { + marginTop: '40px' + } + }, + { + label: '标签key', + component: 'Input', + name: 'props.labelKey', + designKey: 'form-X6hs' + }, + { + label: '值Key', + component: 'Input', + name: 'props.valueKey', + designKey: 'form-STkl' + }, + { + label: '数据模式', + component: 'Radio', + name: 'props.mode', + props: { + mode: 'static', + options: [ + { + label: '静态', + value: 'static' + }, + { + label: '远程', + value: 'remote' + } + ], + optionType: 'button', + space: 0 + }, + designKey: 'form-PLpj' + }, + { + label: '静态选项', + name: 'props.options', + component: 'FormList', + hidden: '{{$values.props.mode!=="static"}}', + children: [ + { + label: '选项名', + name: '{{$values.props.labelKey}}', + component: 'Input', + props: { + placeholder: '请输入...' + }, + designKey: 'form-LnGh' + // initialValue: "{{ '选项' + ($index+1) }}" + }, + { + label: '选项值', + name: '{{$values.props.valueKey}}', + component: 'Input', + props: {}, + designKey: 'form-HYtW' + // initialValue: "{{ 'value' + ($index+1) }}" + } + ], + designKey: 'form-Iwpd', + props: { + mode: 'table', + newItemDefaults: + '{{ (index) => ({ [$values.props.labelKey]: `选项${index + 1}`, [$values.props.valueKey]: `value${index + 1}` }) }}' + } + }, + { + component: 'Card', + props: { + // header: '远程数据' + }, + designKey: 'id-pGeN', + name: 'form-6vzT', + hidden: '{{$values.props.mode==="static"}}', + children: apiAttr + } +] diff --git a/resources/admin/components/catchForm/config/commonType.ts b/resources/admin/components/catchForm/config/commonType.ts new file mode 100644 index 0000000..e97fbcb --- /dev/null +++ b/resources/admin/components/catchForm/config/commonType.ts @@ -0,0 +1,70 @@ +type anyObject = { [key: string]: any } + +type formValuesType = anyObject + +type contextType = { + $values: formValuesType + $selectData: formValuesType + $initialValues: formValuesType + [key: string]: any +} + +type changeItemType = { + target: string + value: any +} + +interface formItemType { + label?: string + name: string + component: string + required?: boolean + props?: object + default?: any + help?: string + children?: formItemType[] + hidden?: boolean | string + hideLabel?: boolean + rules?: any[] + class?: string + style?: any + change?: changeItemType[] + footer: formItemType +} + +type formItemsType = formItemType[] + +type schemaType = { + labelWidth: number + labelAlign: string + size: string + footer: Object + class?: string + disabled?: boolean + hideRequiredAsterisk?: boolean + labelBold?: boolean + items: formItemsType +} + +type formElement = { + name: string + component: any + icon: string + type: 'assist' | 'layout' | 'basic' | 'high' + order: number + attr: formItemsType + initialValues: formItemType + modelName: string +} + +type iconSelectConfigType = { component?: any; propKey?: string; iconList?: string[] } + +type $globalType = { + http?: any + getSchema?: (schemaId: string) => Promise + elements?: { [key: string]: formElement } + iconSelectConfig?: iconSelectConfigType + customElements?: { [key: string]: formElement } +} + +export type { anyObject, schemaType, formValuesType, contextType, formItemType, formItemsType, formElement, changeItemType, $globalType, iconSelectConfigType } diff --git a/resources/admin/components/catchForm/config/symbol.ts b/resources/admin/components/catchForm/config/symbol.ts new file mode 100644 index 0000000..b5e11df --- /dev/null +++ b/resources/admin/components/catchForm/config/symbol.ts @@ -0,0 +1,10 @@ +/* eslint-disable symbol-description */ +export const $global = Symbol() +export const $schema = Symbol() +export const $formValues = Symbol() +export const $selectData = Symbol() +export const $formEvents = Symbol() +export const $initialValues = Symbol() +export const $current = Symbol() +export const $methods = Symbol() +export const $hoverKey = Symbol() diff --git a/resources/admin/components/catchForm/directive/index.js b/resources/admin/components/catchForm/directive/index.js new file mode 100644 index 0000000..a13cf80 --- /dev/null +++ b/resources/admin/components/catchForm/directive/index.js @@ -0,0 +1,2 @@ +export { default as selectLoadMore } from './selectLoadMore' +export { default as tableLoadMore } from './tableLoadMore' diff --git a/resources/admin/components/catchForm/directive/selectLoadMore.js b/resources/admin/components/catchForm/directive/selectLoadMore.js new file mode 100644 index 0000000..f7feb58 --- /dev/null +++ b/resources/admin/components/catchForm/directive/selectLoadMore.js @@ -0,0 +1,23 @@ +import { nextTick } from 'vue' + +const loadMore = (app) => { + app.directive('selectLoadMore', { + mounted: function (el, binding) { + nextTick(() => { + const dropdown = document.querySelector(`.${binding.arg} .el-select-dropdown__wrap`) // 获取下拉框元素 + + if (dropdown) { + dropdown.addEventListener('scroll', function () { + // 监听元素触底 + const condition = this.scrollHeight - this.scrollTop - 5 <= this.clientHeight + if (condition) { + binding.value() + } + }) + } + }) + } + }) +} + +export default loadMore diff --git a/resources/admin/components/catchForm/directive/tableLoadMore.js b/resources/admin/components/catchForm/directive/tableLoadMore.js new file mode 100644 index 0000000..ad8a00d --- /dev/null +++ b/resources/admin/components/catchForm/directive/tableLoadMore.js @@ -0,0 +1,20 @@ +import { nextTick } from 'vue' + +const loadMore = app => { + app.directive('tableLoadMore', { + mounted: function (el, binding) { + nextTick(() => { + const dom = el.querySelector('.el-scrollbar__wrap') // 获取下拉框元素 + dom.addEventListener('scroll', function () { + // 监听元素触底 + const condition = this.scrollHeight - this.scrollTop - 5 <= this.clientHeight + if (condition) { + binding.value() + } + }) + }) + } + }) +} + +export default loadMore diff --git a/resources/admin/components/catchForm/hooks/useRequest.js b/resources/admin/components/catchForm/hooks/useRequest.js new file mode 100644 index 0000000..ee67395 --- /dev/null +++ b/resources/admin/components/catchForm/hooks/useRequest.js @@ -0,0 +1,49 @@ +import { ref, watch, inject } from 'vue' +import { isEqual, debounce, throttle } from 'lodash' +import { getDataByPath } from '/admin/components/catchForm/support' + +const useRequest = ({ api, debounceTime, throttleTime }) => { + const $request = inject('$request') + + const data = ref([]) + const loading = ref(false) + + const fetchData = async () => { + loading.value = true + + const res = await $request.get(api) + + const resData = getDataByPath(res, api.dataPath) + + data.value = resData + + loading.value = false + } + + const debounceRemote = debounce(fetchData, debounceTime) + const throttleRemote = throttle(fetchData, throttleTime) + + const run = () => { + if (debounceTime) { + return debounceRemote() + } + if (throttleTime) { + return throttleRemote() + } + + return fetchData() + } + + watch( + () => api, + (newVal, oldVal) => { + if (!isEqual(newVal, oldVal)) { + run() + } + } + ) + + return { data, loading } +} + +export default useRequest diff --git a/resources/admin/components/catchForm/hooks/useSelect.js b/resources/admin/components/catchForm/hooks/useSelect.js new file mode 100644 index 0000000..af8ed9d --- /dev/null +++ b/resources/admin/components/catchForm/hooks/useSelect.js @@ -0,0 +1,151 @@ +import { ref, reactive, computed, watch, onMounted, inject } from 'vue' +import { isEqual, isPlainObject, debounce } from 'lodash' +import { getDataByPath } from '/admin/components/catchForm/support' +import { $selectData, $global } from '/admin/components/catchForm/config/symbol' + +const useSelect = (props, emits) => { + const selectData = inject($selectData) + + const { request } = inject($global) + + const selectVal = computed({ + get() { + return props.modelValue + }, + set(val) { + emits('update:modelValue', val) + } + }) + + const currentOptions = ref([]) + + const loading = ref(false) + + const isMax = ref(false) + + const stateParams = reactive({ + pageNum: 1, + pageSize: 10 + // filters: {}, + }) + + const fetchData = debounce(async () => { + if (isMax.value || !props.api) return + + const { url, method, data, dataPath } = props.api + + loading.value = true + + let res = null + if (method === 'get') { + res = await request.get(url, data) + } else { + res = await request.post(url, data) + } + + const resData = getDataByPath(res, dataPath) + + if (resData.length !== stateParams.pageSize) { + isMax.value = true + } + + const resDataParse = resData.map(item => { + if (isPlainObject(item)) { + return item + } + return { label: item, value: item } + }) + + currentOptions.value = [...currentOptions.value, ...resDataParse] + + stateParams.pageNum++ + + loading.value = false + }, 300) + + onMounted(() => { + const { mode, options } = props + if (mode === 'static') { + currentOptions.value = options + isMax.value = true + } + if (mode === 'remote') { + fetchData() + } + }) + + watch( + () => props.api, + (newVal, oldVal) => { + // bug:这里发生只api内存地址变化,实际api无变化也会触发监听。暂时使用深层对比解决 + if (!isEqual(newVal, oldVal)) { + currentOptions.value = [] + isMax.value = false + stateParams.pageNum = 1 + fetchData() + } + } + ) + + watch(currentOptions, newVal => { + const { autoSelectedFirst, modelValue, valueKey, multiple, sort } = props + // 自动选中第一项 + if (autoSelectedFirst && newVal.length && !modelValue?.length) { + const firstValue = multiple ? [newVal[0][valueKey]] : newVal[0][valueKey] + emits('update:modelValue', firstValue) + selectChange(firstValue) + } + + if (sort) { + currentOptions.value = currentOptions.value.sort((a, b) => a.value - b.value) + } + }) + + watch( + () => props.options, + newVal => { + if (props.mode === 'static') { + currentOptions.value = newVal + } + } + ) + + watch( + () => props.mode, + newVal => { + if (newVal === 'static') { + currentOptions.value = props.options + } + if (newVal === 'remote') { + currentOptions.value = [] + fetchData() + } + } + ) + + const selectChange = val => { + const { valueKey, multiple, name } = props + + let valueData = {} + + if (multiple) { + // 多选就过滤出vals对应的源数据 + valueData = currentOptions.value.filter(item => { + return val.includes(item[valueKey]) + }) + } else { + // 单选找到单项对应的源数据 + valueData = currentOptions.value.find(item => item[valueKey] === val) + } + + // 如果接到了selectData,给顶级组件保存当前值对应得数据源 + if (selectData) { + selectData[name] = valueData + } + emits('onChangeSelect', selectData) + } + + return { selectVal, selectChange, currentOptions, loading, fetchData, isMax } +} + +export default useSelect diff --git a/resources/admin/components/catchForm/index.ts b/resources/admin/components/catchForm/index.ts new file mode 100644 index 0000000..ee13d67 --- /dev/null +++ b/resources/admin/components/catchForm/index.ts @@ -0,0 +1,69 @@ +import type { App } from 'vue' +import CatchForm from './CatchForm.vue' +import { $global } from '/admin/components/catchForm/config/symbol' +import * as Directives from '/admin/components/catchForm/directive' + +import type { + anyObject, + schemaType, + formValuesType, + contextType, + formItemType, + formItemsType, + formElement, + changeItemType, + $globalType +} from '/admin/components/catchForm/config/commonType' +import components from '/admin/components/catchForm/components' + +/** + * 合并 custom elements + * @param customElements + * @returns + */ +const handleMergeElements = (customElements: { [key: string]: formElement }) => { + const mergeElements: { [key: string]: formElement } = {} + + Object.entries(components).forEach(([key, value]) => { + const customData = customElements[key] + if (customData) { + return (mergeElements[key] = { + ...value, + component: customData.component, + modelName: customData.modelName || 'modelValue', + attr: customData.attr || value.attr + }) + } + + return (mergeElements[key] = { ...value, modelName: 'modelValue' }) + }) + + return mergeElements +} + +type $optionsType = { + http?: any + // elements?: { [key: string]: formElement } + // iconSelectConfig?: iconSelectConfigType + customElements?: { [key: string]: formElement } +} + +const install = function (app: App, options: $optionsType = {}) { + const { http, customElements = {} } = options + + app.provide($global, { + http: http, + elements: handleMergeElements(customElements) + }) + // 注册指令 + Object.values(Directives).forEach(fn => fn(app)) +} + +export { CatchForm } + +export type { anyObject, schemaType, formValuesType, contextType, formItemType, formItemsType, formElement, changeItemType, $globalType } + +export function bootstrapCatchForm(app: App, options:Object = {}) { + install(app, options) + app.component('CatchForm', CatchForm) +} diff --git a/resources/admin/components/catchForm/support/index.ts b/resources/admin/components/catchForm/support/index.ts new file mode 100644 index 0000000..9ccc630 --- /dev/null +++ b/resources/admin/components/catchForm/support/index.ts @@ -0,0 +1,163 @@ +/* eslint-disable no-new-func */ +import { cloneDeep, isString, isPlainObject, isArray } from 'lodash' +import type { formValuesType } from '/admin/components/catchForm/config/commonType' +import type { formItemType, formItemsType } from '/admin/components/catchForm/config/commonType' +import { isEqual } from 'lodash' +import type { anyObject, contextType} from '/admin/components/catchForm/config/commonType' + +type handleLinkagesType = (obj: { newVal: Object; oldVal: Object; formValues: anyObject; formItems: formItemsType }) => void + +// 模板转换函数,将一个由双大括号包裹的字符串,转化为js表达式并返回结果(context限制变量范围) +const templateParse = (str: string, context: contextType) => { + if (!str) return str + if (typeof str !== 'string') return str + + const template = str.match(/{{(.+?)}}/) + if (template) { + try { + const parse = new Function(Object.keys(context).join(','), 'return ' + template[1]) + + return parse(...Object.values(context)) + } catch (e) { + // console.log(str, '模板转换错误:', e) + return str + } + } else { + return str + } +} + +const deepParse = (prop: any, context: contextType): any => { + const $values = context.$values + + if (isString(prop)) { + return templateParse(prop, context) + } + + if (isPlainObject(prop)) { + return Object.keys(prop).reduce((all, key) => { + const itemContext = { ...context } + + if (prop.name && $values) { + itemContext.$val = getDataByPath($values, prop.name) + itemContext.$select = context.$selectData[prop.name] + } + + return { ...all, [key]: deepParse(prop[key], itemContext) } + }, {}) + } + if (isArray(prop)) { + return prop.map(item => { + return deepParse(item, context) + }) + } + + return prop +} + +const handleLinkages: handleLinkagesType = ({ newVal, oldVal, formValues, formItems }) => { + for (const item of formItems) { + const newValue = getDataByPath(newVal, item.name) + const oldValue = getDataByPath(oldVal, item.name) + + if (item.change && !isEqual(newValue, oldValue)) { + let temp = cloneDeep(formValues.value) + item.change.forEach(({ target, value }) => { + temp = setDataByPath(temp, target, value) + }) + formValues.value = temp + } + + if (item.children && item.component !== 'FormList') { + handleLinkages({ + newVal, + oldVal, + formValues, + formItems: item.children + }) + } + } +} + +const recursionDelete = (items: formItemsType, callback: (item: formItemType) => boolean): formItemsType => { + const data = items.filter(callback) + return data.map(item => { + if (item.children) { + return { + ...item, + children: recursionDelete(item.children, callback) + } + } + return item + }) +} +const setDataByPath = (object: formValuesType, path: string, value: any) => { + const cloneObj = cloneDeep(object) + // 将路径字符串分割成路径数组 + const pathArray = path.split('.') + // 递归函数,用于在对象的深层级找到要修改的位置并更新其值 + function update(obj: formValuesType, pathArray: string[], value: any) { + // 如果路径数组为空,表示已经到达了最后一级,更新值并返回 + if (pathArray.length === 1) { + obj[pathArray[0]] = value + return + } + + // 获取当前路径的第一个部分 + const currentKey = pathArray.shift() + + if (currentKey) { + // 如果当前键不存在,则创建一个空对象 + if (!obj[currentKey]) { + obj[currentKey] = {} + } + + // 递归调用更新函数 + update(obj[currentKey], pathArray, value) + } + } + + // 调用递归函数 + update(cloneObj, pathArray, value) + + // 返回更新后的对象 + return cloneObj +} + +const isRegexString = (str: string) => { + const regexMetaCharacters = /[.*+?^${}()|[\]\\]/ + + return regexMetaCharacters.test(str) +} + +const getRandomId = (length: number) => { + const characters = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789' + let randomId = '' + + for (let i = 0; i < length; i++) { + const randomIndex = Math.floor(Math.random() * characters.length) + randomId += characters.charAt(randomIndex) + } + + return randomId +} + +const getDataByPath = (obj: anyObject, path: string) => { + // 使用正则表达式分割路径字符串 + const keys = path.split('.') + + // 遍历路径,逐层深入对象 + let result = obj + for (const key of keys) { + if (result && typeof result === 'object' && key in result) { + result = result[key] + } else { + // 如果路径无效,返回 undefined 或者其他默认值 + return undefined + } + } + + return result +} + +export { setDataByPath, recursionDelete, isRegexString, getRandomId, handleLinkages, getDataByPath, deepParse}