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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

@ -1,8 +1,8 @@
<!--
* @Description: 工具栏
-->
<script lang="ts">
import { defineComponent, inject, reactive, toRefs } from 'vue'
<script lang="ts" setup>
import { inject, reactive } from 'vue'
import type { UseRefHistoryReturn } from '@vueuse/core'
import { Divider, Tooltip } from 'ant-design-vue'
import type { IFormConfig } from '../../../typings/v-form-component'
@ -15,17 +15,9 @@ interface IToolbarsConfig {
event: string
}
export default defineComponent({
name: 'OperatingArea',
components: {
Tooltip,
Icon,
Divider,
},
setup() {
const state = reactive<{
const state = reactive<{
toolbarsConfigs: IToolbarsConfig[]
}>({
}>({
toolbarsConfigs: [
{
title: '预览-支持布局',
@ -64,13 +56,10 @@ export default defineComponent({
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>
<template>
@ -78,7 +67,7 @@ export default defineComponent({
<!-- 头部操作按钮区域 start -->
<!-- 操作左侧区域 start -->
<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)">
<Icon :icon="item.icon" />
</a>

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

@ -1,7 +1,6 @@
<script lang="ts" setup>
import { computed } from 'vue'
import { useI18n } from '@/hooks/web/useI18n'
import { useDesign } from '@/hooks/web/useDesign'
import { BasicForm, useForm } from '@/components/Form'
import { BasicModal, useModalInner } from '@/components/Modal'
import { useUserStore } from '@/store/modules/user'
@ -11,7 +10,6 @@ import headerImg from '@/assets/images/header.jpg'
defineOptions({ name: 'LockModal' })
const { t } = useI18n()
const { prefixCls } = useDesign('header-lock-modal')
const userStore = useUserStore()
const lockStore = useLockStore()
@ -52,18 +50,18 @@ const avatar = computed(() => {
</script>
<template>
<BasicModal :footer="null" width="25%" :title="t('layout.header.lockScreen')" v-bind="$attrs" :class="prefixCls" @register="register">
<div :class="`${prefixCls}__entry`">
<div :class="`${prefixCls}__header`">
<img :src="avatar" :class="`${prefixCls}__header-img`">
<p :class="`${prefixCls}__header-name`">
<BasicModal :footer="null" width="25%" :title="t('layout.header.lockScreen')" v-bind="$attrs" @register="register">
<div class="relative rounded-10 px-8 pb-8 pt-30">
<div class="absolute left-[calc(50%-45px)] top-0 w-auto text-center">
<img :src="avatar" class="w-18 rounded-50%">
<p class="mt-2">
{{ getRealName }}
</p>
</div>
<BasicForm @register="registerForm" />
<div :class="`${prefixCls}__footer`">
<div class="mt-4 text-center">
<a-button type="primary" block class="mt-2" @click="handleLock">
{{ t('layout.header.lockScreenBtn') }}
</a-button>
@ -71,38 +69,3 @@ const avatar = computed(() => {
</div>
</BasicModal>
</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 { computed, defineComponent, onMounted, ref, unref, watch } from 'vue'
import { computed, onMounted, ref, unref, watch } from 'vue'
import type { RouteLocationNormalized } from 'vue-router'
import { onClickOutside } from '@vueuse/core'
import LayoutTrigger from '../trigger/index.vue'
import { useDragLine } from './useLayoutSider'
import type { Menu } from '@/router/types'
@ -16,36 +17,22 @@ import { useDesign } from '@/hooks/web/useDesign'
import { useI18n } from '@/hooks/web/useI18n'
import { useGo } from '@/hooks/web/usePage'
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 { listenerRouteChange } from '@/logics/mitt/routeChange'
export default defineComponent({
name: 'LayoutMixSider',
components: {
ScrollContainer,
AppLogo,
SimpleMenu,
Icon,
LayoutTrigger,
SimpleMenuTag,
},
directives: {
clickOutside,
},
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 {
const wrap = ref(null)
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,
getCanDrag,
getCloseMixSidebarOnChange,
@ -57,22 +44,22 @@ export default defineComponent({
setMenuSetting,
getIsMixSidebar,
getCollapsed,
} = useMenuSetting()
} = useMenuSetting()
const { title } = useGlobSetting()
const permissionStore = usePermissionStore()
const { title } = useGlobSetting()
const permissionStore = usePermissionStore()
useDragLine(sideRef, dragBarRef, true)
useDragLine(sideRef, dragBarRef, true)
const getMenuStyle = computed((): CSSProperties => {
const getMenuStyle = computed((): CSSProperties => {
return {
width: unref(openMenu) ? `${unref(getMenuWidth)}px` : 0,
// eslint-disable-next-line @typescript-eslint/no-use-before-define
left: `${unref(getMixSideWidth)}px`,
}
})
})
const getIsFixed = computed(() => {
const getIsFixed = computed(() => {
// eslint-disable-next-line vue/no-side-effects-in-computed-properties
mixSideHasChildren.value = unref(childrenMenus).length > 0
const isFixed = unref(getMixSideFixed) && unref(mixSideHasChildren)
@ -81,24 +68,24 @@ export default defineComponent({
openMenu.value = true
return isFixed
})
})
const getMixSideWidth = computed(() => {
const getMixSideWidth = computed(() => {
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 width = `${unref(getMixSideWidth) + fixedWidth}px`
return getWrapCommonStyle(width)
})
})
const getWrapStyle = computed((): CSSProperties => {
const getWrapStyle = computed((): CSSProperties => {
const width = `${unref(getMixSideWidth)}px`
return getWrapCommonStyle(width)
})
})
const getMenuEvents = computed(() => {
const getMenuEvents = computed(() => {
return !unref(getMixSideFixed)
? {
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()
})
})
// Menu changes
watch(
// Menu changes
watch(
[() => permissionStore.getLastBuildMenuTime, () => permissionStore.getBackMenuList],
async () => {
menuModules.value = await getShallowMenus()
@ -124,26 +111,26 @@ export default defineComponent({
{
immediate: true,
},
)
)
listenerRouteChange((route) => {
listenerRouteChange((route) => {
currentRoute.value = route
setActive(true)
if (unref(getCloseMixSidebarOnChange))
closeMenu()
})
})
function getWrapCommonStyle(width: string): CSSProperties {
function getWrapCommonStyle(width: string): CSSProperties {
return {
width,
maxWidth: width,
minWidth: width,
flex: `0 0 ${width}`,
}
}
}
// Process module menu click
async function handleModuleClick(path: string, hover = false) {
// Process module menu click
async function handleModuleClick(path: string, hover = false) {
const children = await getChildrenMenus(path)
if (unref(activePath) === path) {
if (!hover) {
@ -172,10 +159,10 @@ export default defineComponent({
return
}
childrenMenus.value = children
}
}
// Set the currently active menu and submenu
async function setActive(setChildren = false) {
// Set the currently active menu and submenu
async function setActive(setChildren = false) {
const path = currentRoute.value?.path
if (!path)
return
@ -196,18 +183,18 @@ export default defineComponent({
childrenMenus.value = []
}
}
}
}
function handleMenuClick(path: string) {
function handleMenuClick(path: string) {
go(path)
}
}
function handleClickOutside() {
function handleClickOutside() {
setActive(true)
closeMenu()
}
}
function getItemEvents(item: Menu) {
function getItemEvents(item: Menu) {
if (unref(getMixSideTrigger) === 'hover') {
return {
onMouseenter: () => handleModuleClick(item.path, true),
@ -221,52 +208,29 @@ export default defineComponent({
return {
onClick: () => handleModuleClick(item.path),
}
}
}
function handleFixedMenu() {
function handleFixedMenu() {
setMenuSetting({
mixSideFixed: !unref(getIsFixed),
})
}
}
// Close menu
function closeMenu() {
// Close menu
function closeMenu() {
if (!unref(getIsFixed))
openMenu.value = false
}
}
return {
t,
prefixCls,
menuModules,
handleModuleClick,
activePath,
childrenMenus,
getShowDragBar,
handleMenuClick,
getMenuStyle,
handleClickOutside,
sideRef,
dragBarRef,
title,
openMenu,
getMenuTheme,
getItemEvents,
getMenuEvents,
getDomStyle,
handleFixedMenu,
getMixSideFixed,
getWrapStyle,
getCollapsed,
}
},
onClickOutside(wrap, () => {
handleClickOutside()
})
</script>
<template>
<div :class="`${prefixCls}-dom`" :style="getDomStyle" />
<div
v-click-outside="handleClickOutside"
ref="wrap"
:style="getWrapStyle"
:class="[
prefixCls,