Browse Source

refactor: use setup

main
xingyu 2 years ago
parent
commit
b808fceb5f
  1. 117
      src/components/FormDesign/src/components/VFormDesign/components/ComponentProps.vue
  2. 42
      src/components/FormDesign/src/components/VFormDesign/components/FormItemColumnProps.vue
  3. 48
      src/components/FormDesign/src/components/VFormDesign/components/FormItemProps.vue
  4. 33
      src/components/FormDesign/src/components/VFormDesign/components/FormNode.vue
  5. 58
      src/components/FormDesign/src/components/VFormDesign/components/LayoutItem.vue
  6. 46
      src/components/FormDesign/src/components/VFormDesign/components/PreviewCode.vue
  7. 42
      src/components/FormDesign/src/components/VFormDesign/modules/CollapseItem.vue
  8. 47
      src/components/FormDesign/src/components/VFormDesign/modules/FormComponentPanel.vue
  9. 22
      src/components/FormDesign/src/components/VFormDesign/modules/PropsPanel.vue
  10. 27
      src/components/FormDesign/src/components/VFormDesign/modules/Toolbar.vue
  11. 49
      src/layouts/default/header/components/lock/LockModal.vue
  12. 160
      src/layouts/default/sider/MixSider.vue

117
src/components/FormDesign/src/components/VFormDesign/components/ComponentProps.vue

@ -1,22 +1,9 @@
<!-- <!--
* @Description: 组件属性控件 * @Description: 组件属性控件
--> -->
<script lang="ts"> <script lang="ts" setup>
import { import { Checkbox, Col, Empty, Form, FormItem, Select } from 'ant-design-vue'
Checkbox, import { computed, ref, watch } from 'vue'
Col,
Empty,
Form,
FormItem,
Input,
InputNumber,
RadioGroup,
Row,
Select,
Switch,
} from 'ant-design-vue'
import RadioButtonGroup from '/@/components/Form/src/components/RadioButtonGroup.vue'
import { computed, defineComponent, ref, watch } from 'vue'
import { useFormDesignState } from '../../../hooks/useFormDesignState' import { useFormDesignState } from '../../../hooks/useFormDesignState'
import { import {
baseComponentAttrs, baseComponentAttrs,
@ -28,41 +15,21 @@ import { formItemsForEach, remove } from '../../../utils'
import type { IBaseFormAttrs } from '../config/formItemPropsConfig' import type { IBaseFormAttrs } from '../config/formItemPropsConfig'
import FormOptions from './FormOptions.vue' import FormOptions from './FormOptions.vue'
export default defineComponent({ const { formConfig } = useFormDesignState()
name: 'ComponentProps', // compuated
components: { const allOptions = ref([] as Omit<IBaseFormAttrs, 'tag'>[])
FormOptions, function showControlAttrs(includes: string[] | undefined) {
Empty,
Input,
Form,
FormItem,
Switch,
Checkbox,
Select,
InputNumber,
RadioGroup,
RadioButtonGroup,
Col,
Row,
},
setup() {
// compuated
const allOptions = ref([] as Omit<IBaseFormAttrs, 'tag'>[])
const showControlAttrs = (includes: string[] | undefined) => {
if (!includes) if (!includes)
return true return true
return includes.includes(formConfig.value.currentItem!.component) return includes.includes(formConfig.value.currentItem!.component)
} }
const { formConfig } = useFormDesignState()
if (formConfig.value.currentItem) { if (formConfig.value.currentItem) {
formConfig.value.currentItem.componentProps formConfig.value.currentItem.componentProps
= formConfig.value.currentItem.componentProps || {} = formConfig.value.currentItem.componentProps || {}
} }
watch( watch(
() => formConfig.value.currentItem?.field, () => formConfig.value.currentItem?.field,
(_newValue, oldValue) => { (_newValue, oldValue) => {
formConfig.value.schemas formConfig.value.schemas
@ -73,9 +40,9 @@ export default defineComponent({
} }
}) })
}, },
) )
watch( watch(
() => formConfig.value.currentItem && formConfig.value.currentItem.component, () => formConfig.value.currentItem && formConfig.value.currentItem.component,
() => { () => {
allOptions.value = [] allOptions.value = []
@ -124,22 +91,22 @@ export default defineComponent({
{ {
immediate: true, immediate: true,
}, },
) )
// //
const controlOptions = computed(() => { const controlOptions = computed(() => {
return allOptions.value.filter((item) => { return allOptions.value.filter((item) => {
return item.category === 'control' return item.category === 'control'
}) })
}) })
// //
const inputOptions = computed(() => { const inputOptions = computed(() => {
return allOptions.value.filter((item) => { return allOptions.value.filter((item) => {
return item.category === 'input' return item.category === 'input'
}) })
}) })
watch( watch(
() => formConfig.value.currentItem!.componentProps, () => formConfig.value.currentItem!.componentProps,
() => { () => {
const func = componentPropsFuncs[formConfig.value.currentItem!.component] const func = componentPropsFuncs[formConfig.value.currentItem!.component]
@ -150,23 +117,14 @@ export default defineComponent({
immediate: true, immediate: true,
deep: true, deep: true,
}, },
) )
const linkOptions = computed(() => { const linkOptions = computed(() => {
return ( return (
formConfig.value.schemas formConfig.value.schemas
&& formConfig.value.schemas && formConfig.value.schemas
.filter(item => item.key !== formConfig.value.currentItem!.key) .filter(item => item.key !== formConfig.value.currentItem!.key)
.map(({ label, field }) => ({ label: `${label}/${field}`, value: field })) .map(({ label, field }) => ({ label: `${label}/${field}`, value: field }))
) )
})
return {
formConfig,
showControlAttrs,
linkOptions,
controlOptions,
inputOptions,
}
},
}) })
</script> </script>
@ -184,27 +142,20 @@ export default defineComponent({
<div v-if="item.children"> <div v-if="item.children">
<component <component
v-bind="child.componentProps" v-bind="child.componentProps" :is="child.component" v-for="(child, index) of item.children"
:is="child.component" :key="index" v-model:value="formConfig.currentItem.componentProps[item.name][index]"
v-for="(child, index) of item.children"
:key="index"
v-model:value="formConfig.currentItem.componentProps[item.name][index]"
/> />
</div> </div>
<!-- 如果不是数组则正常处理属性值 --> <!-- 如果不是数组则正常处理属性值 -->
<component <component
v-bind="item.componentProps" v-bind="item.componentProps" :is="item.component" v-else
:is="item.component" v-model:value="formConfig.currentItem.componentProps[item.name]" class="component-prop"
v-else
v-model:value="formConfig.currentItem.componentProps[item.name]"
class="component-prop"
/> />
</FormItem> </FormItem>
<FormItem label="控制属性"> <FormItem label="控制属性">
<Col v-for="item in controlOptions" :key="item.name"> <Col v-for="item in controlOptions" :key="item.name">
<Checkbox <Checkbox
v-if="showControlAttrs(item.includes)" v-if="showControlAttrs(item.includes)" v-bind="item.componentProps"
v-bind="item.componentProps"
v-model:checked="formConfig.currentItem.componentProps[item.name]" v-model:checked="formConfig.currentItem.componentProps[item.name]"
> >
{{ item.label }} {{ item.label }}
@ -213,16 +164,11 @@ export default defineComponent({
</FormItem> </FormItem>
</div> </div>
<FormItem label="关联字段"> <FormItem label="关联字段">
<Select <Select v-model:value="formConfig.currentItem.link" mode="multiple" :options="linkOptions" />
v-model:value="formConfig.currentItem.link"
mode="multiple"
:options="linkOptions"
/>
</FormItem> </FormItem>
<FormItem <FormItem
v-if=" v-if="[
[
'Select', 'Select',
'CheckboxGroup', 'CheckboxGroup',
'RadioGroup', 'RadioGroup',
@ -230,8 +176,7 @@ export default defineComponent({
'Cascader', 'Cascader',
'AutoComplete', 'AutoComplete',
].includes(formConfig.currentItem.component) ].includes(formConfig.currentItem.component)
" " label="选项"
label="选项"
> >
<FormOptions /> <FormOptions />
</FormItem> </FormItem>

42
src/components/FormDesign/src/components/VFormDesign/components/FormItemColumnProps.vue

@ -1,45 +1,20 @@
<!-- <!--
* @Description: 表单项属性 * @Description: 表单项属性
--> -->
<script lang="ts"> <script lang="ts" setup>
import { defineComponent } from 'vue' import { Empty, Form, FormItem } from 'ant-design-vue'
import { Checkbox, Empty, Form, FormItem, Input, Select, Slider, Switch } from 'ant-design-vue'
import { isArray } from 'lodash-es' import { isArray } from 'lodash-es'
import { baseItemColumnProps } from '../config/formItemPropsConfig' import { baseItemColumnProps } from '../config/formItemPropsConfig'
import { useFormDesignState } from '../../../hooks/useFormDesignState' import { useFormDesignState } from '../../../hooks/useFormDesignState'
import RuleProps from './RuleProps.vue'
export default defineComponent({ const { formConfig } = useFormDesignState()
name: 'FormItemProps', function showProps(exclude: string[] | undefined) {
components: {
RuleProps,
Empty,
Input,
Form,
FormItem,
Switch,
Checkbox,
Select,
Slider,
},
// props: {} as PropsOptions,
setup() {
const { formConfig } = useFormDesignState()
const showProps = (exclude: string[] | undefined) => {
if (!exclude) if (!exclude)
return true return true
return isArray(exclude) ? !exclude.includes(formConfig.value.currentItem!.component) : true return isArray(exclude) ? !exclude.includes(formConfig.value.currentItem!.component) : true
} }
return {
baseItemColumnProps,
formConfig,
showProps,
}
},
})
</script> </script>
<template> <template>
@ -50,11 +25,8 @@ export default defineComponent({
<div v-for="item of baseItemColumnProps" :key="item.name"> <div v-for="item of baseItemColumnProps" :key="item.name">
<FormItem v-if="showProps(item.exclude)" :label="item.label"> <FormItem v-if="showProps(item.exclude)" :label="item.label">
<component <component
v-bind="item.componentProps" v-bind="item.componentProps" :is="item.component" v-if="formConfig.currentItem.colProps"
:is="item.component" v-model:value="formConfig.currentItem.colProps[item.name]" class="component-props"
v-if="formConfig.currentItem.colProps"
v-model:value="formConfig.currentItem.colProps[item.name]"
class="component-props"
/> />
</FormItem> </FormItem>
</div> </div>

48
src/components/FormDesign/src/components/VFormDesign/components/FormItemProps.vue

@ -1,8 +1,8 @@
<!-- <!--
* @Description: 表单项属性控件属性面板 * @Description: 表单项属性控件属性面板
--> -->
<script lang="ts"> <script lang="ts" setup>
import { computed, defineComponent, watch } from 'vue' import { computed, watch } from 'vue'
import { import {
Checkbox, Checkbox,
Col, Col,
@ -10,9 +10,6 @@ import {
Form, Form,
FormItem, FormItem,
Input, Input,
RadioGroup,
Select,
Slider,
Switch, Switch,
} from 'ant-design-vue' } from 'ant-design-vue'
import { isArray } from 'lodash-es' import { isArray } from 'lodash-es'
@ -26,27 +23,9 @@ import {
import { useFormDesignState } from '../../../hooks/useFormDesignState' import { useFormDesignState } from '../../../hooks/useFormDesignState'
import RuleProps from './RuleProps.vue' import RuleProps from './RuleProps.vue'
export default defineComponent({ const { formConfig } = useFormDesignState()
name: 'FormItemProps',
components: {
RuleProps,
Empty,
Input,
Form,
FormItem,
Switch,
Checkbox,
Select,
Slider,
Col,
RadioGroup,
},
// props: {} as PropsOptions,
setup() {
const { formConfig } = useFormDesignState()
watch( watch(
() => formConfig.value, () => formConfig.value,
() => { () => {
if (formConfig.value.currentItem) { if (formConfig.value.currentItem) {
@ -58,29 +37,18 @@ export default defineComponent({
} }
}, },
{ deep: true, immediate: true }, { deep: true, immediate: true },
) )
const showProps = (exclude: string[] | undefined) => { function showProps(exclude: string[] | undefined) {
if (!exclude) if (!exclude)
return true return true
return isArray(exclude) ? !exclude.includes(formConfig.value.currentItem!.component) : true return isArray(exclude) ? !exclude.includes(formConfig.value.currentItem!.component) : true
} }
const controlPropsList = computed(() => { const controlPropsList = computed(() => {
return baseFormItemControlAttrs.filter((item) => { return baseFormItemControlAttrs.filter((item) => {
return showProps(item.exclude) return showProps(item.exclude)
}) })
})
return {
baseFormItemProps,
advanceFormItemProps,
advanceFormItemColProps,
formConfig,
controlPropsList,
showProps,
}
},
}) })
</script> </script>

33
src/components/FormDesign/src/components/VFormDesign/components/FormNode.vue

@ -1,42 +1,29 @@
<!-- <!--
* @Description: 拖拽节点控件 * @Description: 拖拽节点控件
--> -->
<script lang="ts"> <script lang="ts" setup>
import type { PropType } from 'vue' import type { PropType } from 'vue'
import { defineComponent, reactive, toRefs } from 'vue'
import type { IVFormComponent } from '../../../typings/v-form-component' import type { IVFormComponent } from '../../../typings/v-form-component'
import { useFormDesignState } from '../../../hooks/useFormDesignState' import { useFormDesignState } from '../../../hooks/useFormDesignState'
import VFormItem from '../../VFormItem/index.vue' import VFormItem from '../../VFormItem/index.vue'
import FormNodeOperate from './FormNodeOperate.vue' import FormNodeOperate from './FormNodeOperate.vue'
// import VFormItem from '../../VFormItem/vFormItem.vue'; const props = defineProps(
export default defineComponent({ {
name: 'FormNode',
components: {
VFormItem,
FormNodeOperate,
},
props: {
schema: { schema: {
type: Object as PropType<IVFormComponent>, type: Object as PropType<IVFormComponent>,
required: true, required: true,
}, },
}, },
setup(props) {
const { formConfig, formDesignMethods } = useFormDesignState() )
const state = reactive({})
// formDesignMethods const { formConfig, formDesignMethods } = useFormDesignState()
const handleSelectItem = () => { // formDesignMethods
function handleSelectItem() {
// formDesignMethods // formDesignMethods
formDesignMethods.handleSetSelectItem(props.schema) formDesignMethods.handleSetSelectItem(props.schema)
} }
return {
...toRefs(state),
handleSelectItem,
formConfig,
}
},
})
</script> </script>
<template> <template>

58
src/components/FormDesign/src/components/VFormDesign/components/LayoutItem.vue

@ -3,9 +3,9 @@
* 千万不要在template下面的第一行加注释因为这里拖动的第一个元素 * 千万不要在template下面的第一行加注释因为这里拖动的第一个元素
--> -->
<script lang="ts"> <script lang="ts" setup>
import type { PropType } from 'vue' import type { PropType } from 'vue'
import { computed, defineComponent, reactive, toRefs } from 'vue' import { computed } from 'vue'
import draggable from 'vuedraggable' import draggable from 'vuedraggable'
import { Col, Row } from 'ant-design-vue' import { Col, Row } from 'ant-design-vue'
import { useFormDesignState } from '../../../hooks/useFormDesignState' import { useFormDesignState } from '../../../hooks/useFormDesignState'
@ -13,16 +13,8 @@ import type { IVFormComponent } from '../../../typings/v-form-component'
import FormNode from './FormNode.vue' import FormNode from './FormNode.vue'
import FormNodeOperate from './FormNodeOperate.vue' import FormNodeOperate from './FormNodeOperate.vue'
export default defineComponent({ const props = defineProps(
name: 'LayoutItem', {
components: {
FormNode,
FormNodeOperate,
Draggable: draggable,
Row,
Col,
},
props: {
schema: { schema: {
type: Object as PropType<IVFormComponent>, type: Object as PropType<IVFormComponent>,
required: true, required: true,
@ -32,33 +24,23 @@ export default defineComponent({
required: true, required: true,
}, },
}, },
emits: ['dragStart', 'handleColAdd', 'handle-copy', 'handle-delete'], )
setup(props) {
const { const emit = defineEmits(['dragStart', 'handleColAdd', 'handle-copy', 'handle-delete'])
formDesignMethods: { handleSetSelectItem },
formConfig, const Draggable = draggable
} = useFormDesignState()
const state = reactive({}) const { formDesignMethods: { handleSetSelectItem }, formConfig } = useFormDesignState()
const colPropsComputed = computed(() => { const colPropsComputed = computed(() => {
const { colProps = {} } = props.schema const { colProps = {} } = props.schema
return colProps return colProps
}) })
const list1 = computed(() => props.schema.columns) const list1 = computed(() => props.schema.columns)
// AColdiv // AColdiv
const layoutTag = computed(() => { const layoutTag = computed(() => {
return formConfig.value.layout === 'horizontal' ? 'Col' : 'div' return formConfig.value.layout === 'horizontal' ? 'Col' : 'div'
})
return {
...toRefs(state),
colPropsComputed,
handleSetSelectItem,
layoutTag,
list1,
}
},
}) })
</script> </script>
@ -87,8 +69,8 @@ export default defineComponent({
class="drag-move" class="drag-move"
:schema="element" :schema="element"
:current-item="currentItem" :current-item="currentItem"
@handle-copy="$emit('handle-copy')" @handle-copy="emit('handle-copy')"
@handle-delete="$emit('handle-delete')" @handle-delete="emit('handle-delete')"
/> />
</template> </template>
</Draggable> </Draggable>
@ -102,8 +84,8 @@ export default defineComponent({
:key="schema.key" :key="schema.key"
:schema="schema" :schema="schema"
:current-item="currentItem" :current-item="currentItem"
@handle-copy="$emit('handle-copy')" @handle-copy="emit('handle-copy')"
@handle-delete="$emit('handle-delete')" @handle-delete="emit('handle-delete')"
/> />
</Col> </Col>
</template> </template>

46
src/components/FormDesign/src/components/VFormDesign/components/PreviewCode.vue

@ -1,16 +1,12 @@
<script lang="ts"> <script lang="ts" setup>
import { defineComponent, reactive, ref, toRefs, unref } from 'vue' import { ref, unref } from 'vue'
import { CodeEditor, MODE } from '@/components/CodeEditor' import { CodeEditor, MODE } from '@/components/CodeEditor'
import { useCopyToClipboard } from '@/hooks/web/useCopyToClipboard' import { useCopyToClipboard } from '@/hooks/web/useCopyToClipboard'
import { useMessage } from '@/hooks/web/useMessage' import { useMessage } from '@/hooks/web/useMessage'
export default defineComponent({ const props = defineProps(
name: 'PreviewCode', {
components: {
CodeEditor,
},
props: {
fileFormat: { fileFormat: {
type: String, type: String,
default: 'json', default: 'json',
@ -20,14 +16,11 @@ export default defineComponent({
default: '', default: '',
}, },
}, },
setup(props) { )
const state = reactive({
open: false,
})
const myEditor = ref(null) const myEditor = ref(null)
const exportData = (data: string, fileName = `file.${props.fileFormat}`) => { function exportData(data: string, fileName = `file.${props.fileFormat}`) {
let content = 'data:text/csv;charset=utf-8,' let content = 'data:text/csv;charset=utf-8,'
content += data content += data
const encodedUri = encodeURI(content) const encodedUri = encodeURI(content)
@ -35,15 +28,15 @@ export default defineComponent({
actions.setAttribute('href', encodedUri) actions.setAttribute('href', encodedUri)
actions.setAttribute('download', fileName) actions.setAttribute('download', fileName)
actions.click() actions.click()
} }
const handleExportJson = () => { function handleExportJson() {
exportData(props.editorJson) exportData(props.editorJson)
} }
const { clipboardRef, copiedRef } = useCopyToClipboard() const { clipboardRef, copiedRef } = useCopyToClipboard()
const { createMessage } = useMessage() const { createMessage } = useMessage()
const handleCopyJson = () => { function handleCopyJson() {
// //
const value = props.editorJson const value = props.editorJson
if (!value) { if (!value) {
@ -53,18 +46,7 @@ export default defineComponent({
clipboardRef.value = value clipboardRef.value = value
if (unref(copiedRef)) if (unref(copiedRef))
createMessage.warning('复制成功!') createMessage.warning('复制成功!')
} }
return {
...toRefs(state),
myEditor,
exportData,
handleCopyJson,
handleExportJson,
MODE,
}
},
})
</script> </script>
<template> <template>

42
src/components/FormDesign/src/components/VFormDesign/modules/CollapseItem.vue

@ -1,16 +1,13 @@
<script lang="ts"> <script lang="ts" setup>
import { defineComponent, reactive } from 'vue'
import draggable from 'vuedraggable' import draggable from 'vuedraggable'
import type { IVFormComponent } from '../../../typings/v-form-component' import type { IVFormComponent } from '../../../typings/v-form-component'
import { Icon } from '@/components/Icon' import { Icon } from '@/components/Icon'
import { useDesign } from '@/hooks/web/useDesign' import { useDesign } from '@/hooks/web/useDesign'
export default defineComponent({ const props = defineProps(
name: 'CollapseItem', {
components: { Draggable: draggable, Icon },
props: {
list: { list: {
type: [Array], type: Array as unknown as any[],
default: () => [], default: () => [],
}, },
handleListPush: { handleListPush: {
@ -18,24 +15,23 @@ export default defineComponent({
default: null, default: null,
}, },
}, },
setup(props, { emit }) { )
const { prefixCls } = useDesign('form-design-collapse-item') const emit = defineEmits(['start', 'add-attrs', 'handle-list-push'])
const Draggable = draggable
const state = reactive({}) const { prefixCls } = useDesign('form-design-collapse-item')
const handleStart = (e: any, list1: IVFormComponent[]) => {
function handleStart(e: any, list1: IVFormComponent[]) {
emit('start', list1[e.oldIndex].component) emit('start', list1[e.oldIndex].component)
} }
const handleAdd = (e: any) => { function handleAdd(e: any) {
console.log(e) console.log(e)
} }
// https://github.com/SortableJS/vue.draggable.next // https://github.com/SortableJS/vue.draggable.next
// https://github.com/SortableJS/vue.draggable.next/blob/master/example/components/custom-clone.vue // https://github.com/SortableJS/vue.draggable.next/blob/master/example/components/custom-clone.vue
const cloneItem = (one) => { function cloneItem(one) {
return props.handleListPush(one) return props.handleListPush(one)
} }
return { prefixCls, state, handleStart, handleAdd, cloneItem }
},
})
</script> </script>
<template> <template>
@ -57,8 +53,8 @@ export default defineComponent({
<template #item="{ element, index }"> <template #item="{ element, index }">
<li <li
class="bs-box text-ellipsis" class="bs-box text-ellipsis"
@dragstart="$emit('add-attrs', list, index)" @dragstart="emit('add-attrs', list, index)"
@click="$emit('handle-list-push', element)" @click="emit('handle-list-push', element)"
> >
<!-- <svg v-if="element.icon.indexOf('icon-') > -1" class="icon" aria-hidden="true"> <!-- <svg v-if="element.icon.indexOf('icon-') > -1" class="icon" aria-hidden="true">
<use :xlink:href="`#${element.icon}`" /> <use :xlink:href="`#${element.icon}`" />

47
src/components/FormDesign/src/components/VFormDesign/modules/FormComponentPanel.vue

@ -2,7 +2,7 @@
* @Description: 中间表单布局面板 * @Description: 中间表单布局面板
* https://github.com/SortableJS/vue.draggable.next/issues/138 * https://github.com/SortableJS/vue.draggable.next/issues/138
--> -->
<script lang="ts"> <script lang="ts" setup>
import draggable from 'vuedraggable' import draggable from 'vuedraggable'
import { computed, defineComponent } from 'vue' import { computed, defineComponent } from 'vue'
import { cloneDeep } from 'lodash-es' import { cloneDeep } from 'lodash-es'
@ -10,52 +10,37 @@ import { Empty, Form } from 'ant-design-vue'
import { useFormDesignState } from '../../../hooks/useFormDesignState' import { useFormDesignState } from '../../../hooks/useFormDesignState'
import LayoutItem from '../components/LayoutItem.vue' import LayoutItem from '../components/LayoutItem.vue'
export default defineComponent({ const emit = defineEmits(['handleSetSelectItem'])
name: 'FormComponentPanel',
components: { const Draggable = draggable
LayoutItem,
Draggable: draggable, const { formConfig } = useFormDesignState()
Form,
Empty, /**
},
emits: ['handleSetSelectItem'],
setup(_, { emit }) {
const { formConfig } = useFormDesignState()
/**
* 拖拽完成事件 * 拖拽完成事件
* @param newIndex * @param newIndex
*/ */
const addItem = ({ newIndex }: any) => { function addItem({ newIndex }: any) {
formConfig.value.schemas = formConfig.value.schemas || [] formConfig.value.schemas = formConfig.value.schemas || []
const schemas = formConfig.value.schemas const schemas = formConfig.value.schemas
schemas[newIndex] = cloneDeep(schemas[newIndex]) schemas[newIndex] = cloneDeep(schemas[newIndex])
emit('handleSetSelectItem', schemas[newIndex]) emit('handleSetSelectItem', schemas[newIndex])
} }
/** /**
* 拖拽开始事件 * 拖拽开始事件
* @param e {Object} 事件对象 * @param e {Object} 事件对象
*/ */
const handleDragStart = (e: any) => { function handleDragStart(e: any) {
emit('handleSetSelectItem', formConfig.value.schemas[e.oldIndex]) emit('handleSetSelectItem', formConfig.value.schemas[e.oldIndex])
} }
// currentItem // currentItem
// AColdiv // AColdiv
const layoutTag = computed(() => { const layoutTag = computed(() => {
return formConfig.value.layout === 'horizontal' ? 'Col' : 'div' return formConfig.value.layout === 'horizontal' ? 'Col' : 'div'
})
return {
addItem,
handleDragStart,
formConfig,
layoutTag,
}
},
}) })
</script> </script>

22
src/components/FormDesign/src/components/VFormDesign/modules/PropsPanel.vue

@ -1,8 +1,8 @@
<!-- <!--
* @Description: 右侧属性配置面板 * @Description: 右侧属性配置面板
--> -->
<script lang="ts"> <script lang="ts" setup>
import { computed, defineComponent } from 'vue' import { computed } from 'vue'
import { TabPane, Tabs } from 'ant-design-vue' import { TabPane, Tabs } from 'ant-design-vue'
import FormProps from '../components/FormProps.vue' import FormProps from '../components/FormProps.vue'
import FormItemProps from '../components/FormItemProps.vue' import FormItemProps from '../components/FormItemProps.vue'
@ -15,25 +15,11 @@ type ChangeTabKey = 1 | 2
export interface IPropsPanel { export interface IPropsPanel {
changeTab: (key: ChangeTabKey) => void changeTab: (key: ChangeTabKey) => void
} }
export default defineComponent({ const { formConfig } = useFormDesignState()
name: 'PropsPanel', const slotProps = computed(() => {
components: {
FormProps,
FormItemProps,
ComponentProps,
ComponentColumnProps,
Tabs,
TabPane,
},
setup() {
const { formConfig } = useFormDesignState()
const slotProps = computed(() => {
return customComponents.find( return customComponents.find(
item => item.component === formConfig.value.currentItem?.component, item => item.component === formConfig.value.currentItem?.component,
) )
})
return { formConfig, customComponents, slotProps }
},
}) })
</script> </script>

27
src/components/FormDesign/src/components/VFormDesign/modules/Toolbar.vue

@ -1,8 +1,8 @@
<!-- <!--
* @Description: 工具栏 * @Description: 工具栏
--> -->
<script lang="ts"> <script lang="ts" setup>
import { defineComponent, inject, reactive, toRefs } from 'vue' import { inject, reactive } from 'vue'
import type { UseRefHistoryReturn } from '@vueuse/core' import type { UseRefHistoryReturn } from '@vueuse/core'
import { Divider, Tooltip } from 'ant-design-vue' import { Divider, Tooltip } from 'ant-design-vue'
import type { IFormConfig } from '../../../typings/v-form-component' import type { IFormConfig } from '../../../typings/v-form-component'
@ -15,17 +15,9 @@ interface IToolbarsConfig {
event: string event: string
} }
export default defineComponent({ const state = reactive<{
name: 'OperatingArea',
components: {
Tooltip,
Icon,
Divider,
},
setup() {
const state = reactive<{
toolbarsConfigs: IToolbarsConfig[] toolbarsConfigs: IToolbarsConfig[]
}>({ }>({
toolbarsConfigs: [ toolbarsConfigs: [
{ {
title: '预览-支持布局', title: '预览-支持布局',
@ -64,13 +56,10 @@ export default defineComponent({
icon: 'ant-design:clear-outlined', icon: 'ant-design:clear-outlined',
}, },
], ],
})
const historyRef = inject('historyReturn') as UseRefHistoryReturn<IFormConfig, IFormConfig>
const { undo, redo, canUndo, canRedo } = historyRef
return { ...toRefs(state), undo, redo, canUndo, canRedo }
},
}) })
const historyRef = inject('historyReturn') as UseRefHistoryReturn<IFormConfig, IFormConfig>
const { undo, redo, canUndo, canRedo } = historyRef
</script> </script>
<template> <template>
@ -78,7 +67,7 @@ export default defineComponent({
<!-- 头部操作按钮区域 start --> <!-- 头部操作按钮区域 start -->
<!-- 操作左侧区域 start --> <!-- 操作左侧区域 start -->
<div class="left-btn-box"> <div class="left-btn-box">
<Tooltip v-for="item in toolbarsConfigs" :key="item.icon" :title="item.title"> <Tooltip v-for="item in state.toolbarsConfigs" :key="item.icon" :title="item.title">
<a class="toolbar-text" @click="$emit(item.event)"> <a class="toolbar-text" @click="$emit(item.event)">
<Icon :icon="item.icon" /> <Icon :icon="item.icon" />
</a> </a>

49
src/layouts/default/header/components/lock/LockModal.vue

@ -1,7 +1,6 @@
<script lang="ts" setup> <script lang="ts" setup>
import { computed } from 'vue' import { computed } from 'vue'
import { useI18n } from '@/hooks/web/useI18n' import { useI18n } from '@/hooks/web/useI18n'
import { useDesign } from '@/hooks/web/useDesign'
import { BasicForm, useForm } from '@/components/Form' import { BasicForm, useForm } from '@/components/Form'
import { BasicModal, useModalInner } from '@/components/Modal' import { BasicModal, useModalInner } from '@/components/Modal'
import { useUserStore } from '@/store/modules/user' import { useUserStore } from '@/store/modules/user'
@ -11,7 +10,6 @@ import headerImg from '@/assets/images/header.jpg'
defineOptions({ name: 'LockModal' }) defineOptions({ name: 'LockModal' })
const { t } = useI18n() const { t } = useI18n()
const { prefixCls } = useDesign('header-lock-modal')
const userStore = useUserStore() const userStore = useUserStore()
const lockStore = useLockStore() const lockStore = useLockStore()
@ -52,18 +50,18 @@ const avatar = computed(() => {
</script> </script>
<template> <template>
<BasicModal :footer="null" width="25%" :title="t('layout.header.lockScreen')" v-bind="$attrs" :class="prefixCls" @register="register"> <BasicModal :footer="null" width="25%" :title="t('layout.header.lockScreen')" v-bind="$attrs" @register="register">
<div :class="`${prefixCls}__entry`"> <div class="relative rounded-10 px-8 pb-8 pt-30">
<div :class="`${prefixCls}__header`"> <div class="absolute left-[calc(50%-45px)] top-0 w-auto text-center">
<img :src="avatar" :class="`${prefixCls}__header-img`"> <img :src="avatar" class="w-18 rounded-50%">
<p :class="`${prefixCls}__header-name`"> <p class="mt-2">
{{ getRealName }} {{ getRealName }}
</p> </p>
</div> </div>
<BasicForm @register="registerForm" /> <BasicForm @register="registerForm" />
<div :class="`${prefixCls}__footer`"> <div class="mt-4 text-center">
<a-button type="primary" block class="mt-2" @click="handleLock"> <a-button type="primary" block class="mt-2" @click="handleLock">
{{ t('layout.header.lockScreenBtn') }} {{ t('layout.header.lockScreenBtn') }}
</a-button> </a-button>
@ -71,38 +69,3 @@ const avatar = computed(() => {
</div> </div>
</BasicModal> </BasicModal>
</template> </template>
<style lang="less">
@prefix-cls: ~'@{namespace}-header-lock-modal';
.@{prefix-cls} {
&__entry {
position: relative;
//height: 240px;
padding: 130px 30px 30px;
border-radius: 10px;
}
&__header {
position: absolute;
top: 0;
left: calc(50% - 45px);
width: auto;
text-align: center;
&-img {
width: 70px;
border-radius: 50%;
}
&-name {
margin-top: 5px;
}
}
&__footer {
margin-top: 16px;
text-align: center;
}
}
</style>

160
src/layouts/default/sider/MixSider.vue

@ -1,7 +1,8 @@
<script lang="ts"> <script lang="ts" setup>
import type { CSSProperties } from 'vue' import type { CSSProperties } from 'vue'
import { computed, defineComponent, onMounted, ref, unref, watch } from 'vue' import { computed, onMounted, ref, unref, watch } from 'vue'
import type { RouteLocationNormalized } from 'vue-router' import type { RouteLocationNormalized } from 'vue-router'
import { onClickOutside } from '@vueuse/core'
import LayoutTrigger from '../trigger/index.vue' import LayoutTrigger from '../trigger/index.vue'
import { useDragLine } from './useLayoutSider' import { useDragLine } from './useLayoutSider'
import type { Menu } from '@/router/types' import type { Menu } from '@/router/types'
@ -16,36 +17,22 @@ import { useDesign } from '@/hooks/web/useDesign'
import { useI18n } from '@/hooks/web/useI18n' import { useI18n } from '@/hooks/web/useI18n'
import { useGo } from '@/hooks/web/usePage' import { useGo } from '@/hooks/web/usePage'
import { SIDE_BAR_MINI_WIDTH, SIDE_BAR_SHOW_TIT_MINI_WIDTH } from '@/enums/appEnum' import { SIDE_BAR_MINI_WIDTH, SIDE_BAR_SHOW_TIT_MINI_WIDTH } from '@/enums/appEnum'
import clickOutside from '@/directives/clickOutside'
import { getChildrenMenus, getCurrentParentPath, getShallowMenus } from '@/router/menus' import { getChildrenMenus, getCurrentParentPath, getShallowMenus } from '@/router/menus'
import { listenerRouteChange } from '@/logics/mitt/routeChange' import { listenerRouteChange } from '@/logics/mitt/routeChange'
export default defineComponent({ const wrap = ref(null)
name: 'LayoutMixSider', const menuModules = ref<Menu[]>([])
components: { const activePath = ref('')
ScrollContainer, const childrenMenus = ref<Menu[]>([])
AppLogo, const openMenu = ref(false)
SimpleMenu, const dragBarRef = ref<ElRef>(null)
Icon, const sideRef = ref<ElRef>(null)
LayoutTrigger, const currentRoute = ref<Nullable<RouteLocationNormalized>>(null)
SimpleMenuTag,
}, const { prefixCls } = useDesign('layout-mix-sider')
directives: { const go = useGo()
clickOutside, const { t } = useI18n()
}, const {
setup() {
const menuModules = ref<Menu[]>([])
const activePath = ref('')
const childrenMenus = ref<Menu[]>([])
const openMenu = ref(false)
const dragBarRef = ref<ElRef>(null)
const sideRef = ref<ElRef>(null)
const currentRoute = ref<Nullable<RouteLocationNormalized>>(null)
const { prefixCls } = useDesign('layout-mix-sider')
const go = useGo()
const { t } = useI18n()
const {
getMenuWidth, getMenuWidth,
getCanDrag, getCanDrag,
getCloseMixSidebarOnChange, getCloseMixSidebarOnChange,
@ -57,22 +44,22 @@ export default defineComponent({
setMenuSetting, setMenuSetting,
getIsMixSidebar, getIsMixSidebar,
getCollapsed, getCollapsed,
} = useMenuSetting() } = useMenuSetting()
const { title } = useGlobSetting() const { title } = useGlobSetting()
const permissionStore = usePermissionStore() const permissionStore = usePermissionStore()
useDragLine(sideRef, dragBarRef, true) useDragLine(sideRef, dragBarRef, true)
const getMenuStyle = computed((): CSSProperties => { const getMenuStyle = computed((): CSSProperties => {
return { return {
width: unref(openMenu) ? `${unref(getMenuWidth)}px` : 0, width: unref(openMenu) ? `${unref(getMenuWidth)}px` : 0,
// eslint-disable-next-line @typescript-eslint/no-use-before-define // eslint-disable-next-line @typescript-eslint/no-use-before-define
left: `${unref(getMixSideWidth)}px`, left: `${unref(getMixSideWidth)}px`,
} }
}) })
const getIsFixed = computed(() => { const getIsFixed = computed(() => {
// eslint-disable-next-line vue/no-side-effects-in-computed-properties // eslint-disable-next-line vue/no-side-effects-in-computed-properties
mixSideHasChildren.value = unref(childrenMenus).length > 0 mixSideHasChildren.value = unref(childrenMenus).length > 0
const isFixed = unref(getMixSideFixed) && unref(mixSideHasChildren) const isFixed = unref(getMixSideFixed) && unref(mixSideHasChildren)
@ -81,24 +68,24 @@ export default defineComponent({
openMenu.value = true openMenu.value = true
return isFixed return isFixed
}) })
const getMixSideWidth = computed(() => { const getMixSideWidth = computed(() => {
return unref(getCollapsed) ? SIDE_BAR_MINI_WIDTH : SIDE_BAR_SHOW_TIT_MINI_WIDTH return unref(getCollapsed) ? SIDE_BAR_MINI_WIDTH : SIDE_BAR_SHOW_TIT_MINI_WIDTH
}) })
const getDomStyle = computed((): CSSProperties => { const getDomStyle = computed((): CSSProperties => {
const fixedWidth = unref(getIsFixed) ? unref(getRealWidth) : 0 const fixedWidth = unref(getIsFixed) ? unref(getRealWidth) : 0
const width = `${unref(getMixSideWidth) + fixedWidth}px` const width = `${unref(getMixSideWidth) + fixedWidth}px`
return getWrapCommonStyle(width) return getWrapCommonStyle(width)
}) })
const getWrapStyle = computed((): CSSProperties => { const getWrapStyle = computed((): CSSProperties => {
const width = `${unref(getMixSideWidth)}px` const width = `${unref(getMixSideWidth)}px`
return getWrapCommonStyle(width) return getWrapCommonStyle(width)
}) })
const getMenuEvents = computed(() => { const getMenuEvents = computed(() => {
return !unref(getMixSideFixed) return !unref(getMixSideFixed)
? { ? {
onMouseleave: () => { onMouseleave: () => {
@ -107,16 +94,16 @@ export default defineComponent({
}, },
} }
: {} : {}
}) })
const getShowDragBar = computed(() => unref(getCanDrag)) const getShowDragBar = computed(() => unref(getCanDrag))
onMounted(async () => { onMounted(async () => {
menuModules.value = await getShallowMenus() menuModules.value = await getShallowMenus()
}) })
// Menu changes // Menu changes
watch( watch(
[() => permissionStore.getLastBuildMenuTime, () => permissionStore.getBackMenuList], [() => permissionStore.getLastBuildMenuTime, () => permissionStore.getBackMenuList],
async () => { async () => {
menuModules.value = await getShallowMenus() menuModules.value = await getShallowMenus()
@ -124,26 +111,26 @@ export default defineComponent({
{ {
immediate: true, immediate: true,
}, },
) )
listenerRouteChange((route) => { listenerRouteChange((route) => {
currentRoute.value = route currentRoute.value = route
setActive(true) setActive(true)
if (unref(getCloseMixSidebarOnChange)) if (unref(getCloseMixSidebarOnChange))
closeMenu() closeMenu()
}) })
function getWrapCommonStyle(width: string): CSSProperties { function getWrapCommonStyle(width: string): CSSProperties {
return { return {
width, width,
maxWidth: width, maxWidth: width,
minWidth: width, minWidth: width,
flex: `0 0 ${width}`, flex: `0 0 ${width}`,
} }
} }
// Process module menu click // Process module menu click
async function handleModuleClick(path: string, hover = false) { async function handleModuleClick(path: string, hover = false) {
const children = await getChildrenMenus(path) const children = await getChildrenMenus(path)
if (unref(activePath) === path) { if (unref(activePath) === path) {
if (!hover) { if (!hover) {
@ -172,10 +159,10 @@ export default defineComponent({
return return
} }
childrenMenus.value = children childrenMenus.value = children
} }
// Set the currently active menu and submenu // Set the currently active menu and submenu
async function setActive(setChildren = false) { async function setActive(setChildren = false) {
const path = currentRoute.value?.path const path = currentRoute.value?.path
if (!path) if (!path)
return return
@ -196,18 +183,18 @@ export default defineComponent({
childrenMenus.value = [] childrenMenus.value = []
} }
} }
} }
function handleMenuClick(path: string) { function handleMenuClick(path: string) {
go(path) go(path)
} }
function handleClickOutside() { function handleClickOutside() {
setActive(true) setActive(true)
closeMenu() closeMenu()
} }
function getItemEvents(item: Menu) { function getItemEvents(item: Menu) {
if (unref(getMixSideTrigger) === 'hover') { if (unref(getMixSideTrigger) === 'hover') {
return { return {
onMouseenter: () => handleModuleClick(item.path, true), onMouseenter: () => handleModuleClick(item.path, true),
@ -221,52 +208,29 @@ export default defineComponent({
return { return {
onClick: () => handleModuleClick(item.path), onClick: () => handleModuleClick(item.path),
} }
} }
function handleFixedMenu() { function handleFixedMenu() {
setMenuSetting({ setMenuSetting({
mixSideFixed: !unref(getIsFixed), mixSideFixed: !unref(getIsFixed),
}) })
} }
// Close menu // Close menu
function closeMenu() { function closeMenu() {
if (!unref(getIsFixed)) if (!unref(getIsFixed))
openMenu.value = false openMenu.value = false
} }
return { onClickOutside(wrap, () => {
t, handleClickOutside()
prefixCls,
menuModules,
handleModuleClick,
activePath,
childrenMenus,
getShowDragBar,
handleMenuClick,
getMenuStyle,
handleClickOutside,
sideRef,
dragBarRef,
title,
openMenu,
getMenuTheme,
getItemEvents,
getMenuEvents,
getDomStyle,
handleFixedMenu,
getMixSideFixed,
getWrapStyle,
getCollapsed,
}
},
}) })
</script> </script>
<template> <template>
<div :class="`${prefixCls}-dom`" :style="getDomStyle" /> <div :class="`${prefixCls}-dom`" :style="getDomStyle" />
<div <div
v-click-outside="handleClickOutside" ref="wrap"
:style="getWrapStyle" :style="getWrapStyle"
:class="[ :class="[
prefixCls, prefixCls,