1404/11/04- first
This commit is contained in:
@@ -0,0 +1,83 @@
|
||||
<template>
|
||||
<ADrawer
|
||||
:class="prefixCls"
|
||||
v-model:visible="settingsStore.showSettingsDrawer"
|
||||
title="تنظیمات"
|
||||
:placement="settingsStore.settingsPlacementDrawer"
|
||||
>
|
||||
<template #closeIcon>
|
||||
<BaseIcon icon="vuesax-linear:add" size="24" class="rotate-45" />
|
||||
</template>
|
||||
|
||||
<div class="flex flex-col gap-4">
|
||||
<div class="flex justify-between">
|
||||
<span class="text-gray-400 text-sm">نوار کناری (Sidebar)</span>
|
||||
<ASwitch :checked="true" size="small" />
|
||||
</div>
|
||||
<div class="flex justify-between">
|
||||
<span class="text-gray-400 text-sm">تب بندی</span>
|
||||
<ASwitch :checked="true" size="small" />
|
||||
</div>
|
||||
<div class="flex justify-between">
|
||||
<span class="text-gray-400 text-sm">سر صفحه (Header)</span>
|
||||
<ASwitch :checked="true" size="small" />
|
||||
</div>
|
||||
<div class="flex justify-between">
|
||||
<span class="text-gray-400 text-sm">مسیر جاری (Breadcrumbs)</span>
|
||||
<ASwitch :checked="true" size="small" />
|
||||
</div>
|
||||
<div class="flex justify-between">
|
||||
<span class="text-gray-400 text-sm">پانویس (Footer)</span>
|
||||
<ASwitch :checked="true" size="small" />
|
||||
</div>
|
||||
</div>
|
||||
<ADivider class="!my-2" />
|
||||
<div class="flex flex-col gap-3">
|
||||
<span class="text-gray-400"> طرح بندی</span>
|
||||
<div class="flex items-center justify-between">
|
||||
<img
|
||||
src="@/core/assets/img/layout/side.png"
|
||||
class="layout-item"
|
||||
:class="[{ active: layoutStore.layout === 'side' }]"
|
||||
/>
|
||||
<img
|
||||
src="@/core/assets/img/layout/mix.png"
|
||||
class="layout-item"
|
||||
:class="[{ active: layoutStore.layout === 'mix' }]"
|
||||
/>
|
||||
<img
|
||||
src="@/core/assets/img/layout/top.png"
|
||||
class="layout-item"
|
||||
:class="[{ active: layoutStore.layout === 'top' }]"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</ADrawer>
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import { usePrefix } from '@core/composable/usePrefix'
|
||||
import { useSettingsStore } from '@core/stores/settings'
|
||||
import { useLayoutStore } from '@core/stores/layout'
|
||||
//const visible = ref<boolean>(false)
|
||||
const { prefixCls } = usePrefix('base-settings')
|
||||
const settingsStore = useSettingsStore()
|
||||
const layoutStore = useLayoutStore()
|
||||
</script>
|
||||
|
||||
<style lang="less">
|
||||
@prefix:~ '@{prefixCls}-base-settings';
|
||||
.@{prefix}{
|
||||
|
||||
.layout-item{
|
||||
cursor: pointer;
|
||||
border:2px solid #eee;
|
||||
padding:5px;
|
||||
&.active{
|
||||
border-color: @primary-color;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
</style>
|
||||
@@ -0,0 +1,139 @@
|
||||
<template>
|
||||
<!-- :class="[, isMobile ? null : 'shadow']"-->
|
||||
<!-- :theme="sideTheme"-->
|
||||
<ALayoutSider
|
||||
theme="light"
|
||||
:class="[prefixCls]"
|
||||
:width="layoutStore.sideMenu.width"
|
||||
:collapsible="layoutStore.sideMenu.collapsible"
|
||||
:collapsedWidth="layoutStore.sideMenu.collapsedWidth"
|
||||
v-model:collapsed="layoutStore.sideMenu.collapsed"
|
||||
:trigger="null"
|
||||
>
|
||||
<div
|
||||
class="flex items-center logo px-4 py-2 gap-3"
|
||||
:style="`height:calc(${layoutStore.header.height} - 1px );min-height:calc(${layoutStore.header.height} - 1px )`"
|
||||
>
|
||||
<img src="@/assets/img/saminLogo_.png" class="object-cover" style="max-height: 32px" alt="" />
|
||||
|
||||
<!-- <img src="@/assets/img/logo.svg" class="object-cover w-full" style="max-height: 32px" />-->
|
||||
<!-- <h1 class="contents">پنل مدیریتی</h1>-->
|
||||
<!-- 11111-->
|
||||
<!-- <router-link to="/myDocuments/workplace">
|
||||
<img src="@/assets/img/logo.png" />
|
||||
<h1>{{ systemName }}</h1>
|
||||
</router-link>-->
|
||||
</div>
|
||||
|
||||
<BasicMenu class="flex-1 overflow-scroll scroll-none" />
|
||||
<!-- <div class="side-version text-center flex flex-col text-xs text-slate-400 items-center">
|
||||
<span>نسخه {{ version() }}</span>
|
||||
<span class="flex text-center gap-1 justify-center">
|
||||
<span>نسخه core</span>
|
||||
<span>{{ coreVersion() }}</span>
|
||||
</span>
|
||||
</div>-->
|
||||
<!-- <i-menu
|
||||
:theme="theme"
|
||||
:collapsed="collapsed"
|
||||
:options="menuData"
|
||||
@select="onSelect"
|
||||
class="menu"
|
||||
/>-->
|
||||
|
||||
<!-- v-model:openKeys="openKeys"
|
||||
v-model:selectedKeys="selectedKeys"
|
||||
mode="inline"
|
||||
theme="dark"-->
|
||||
<!-- <AMenu :inline-collapsed="layoutStore.sideMenu.collapsed" mode="inline" v-if="false">
|
||||
<AMenuItem key="1">
|
||||
<template #icon>
|
||||
<span>111</span>
|
||||
<!– <PieChartOutlined />–>
|
||||
</template>
|
||||
<span>پیشخوان</span>
|
||||
</AMenuItem>
|
||||
<AMenuItem key="2">
|
||||
<template #icon>
|
||||
<span>1111</span>
|
||||
<DesktopOutlined />
|
||||
</template>
|
||||
<span>Option 2</span>
|
||||
</AMenuItem>
|
||||
<AMenuItem key="3">
|
||||
<template #icon>
|
||||
<InboxOutlined />
|
||||
</template>
|
||||
<span>Option 3</span>
|
||||
</AMenuItem>
|
||||
<ASubMenu key="sub1">
|
||||
<template #icon>
|
||||
<MailOutlined />
|
||||
</template>
|
||||
<template #title>Navigation One</template>
|
||||
<AMenuItem key="5">Option 5</AMenuItem>
|
||||
<AMenuItem key="6">Option 6</AMenuItem>
|
||||
<AMenuItem key="7">Option 7</AMenuItem>
|
||||
<AMenuItem key="8">Option 8</AMenuItem>
|
||||
</ASubMenu>
|
||||
<ASubMenu key="sub2">
|
||||
<template #icon>
|
||||
<AppstoreOutlined />
|
||||
</template>
|
||||
<template #title>Navigation Two</template>
|
||||
<AMenuItem key="9">Option 9</AMenuItem>
|
||||
<AMenuItem key="10">Option 10</AMenuItem>
|
||||
<ASubMenu key="sub3" title="Submenu">
|
||||
<AMenuItem key="11">Option 11</AMenuItem>
|
||||
<AMenuItem key="12">Option 12</AMenuItem>
|
||||
</ASubMenu>
|
||||
</ASubMenu>
|
||||
</AMenu>-->
|
||||
</ALayoutSider>
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import { useLayoutStore } from '@core/stores/layout'
|
||||
import { usePrefix } from '@core/composable/usePrefix'
|
||||
import BasicMenu from '@core/layouts/composnts/BasicMenu.vue'
|
||||
//import { coreVersion, version } from '../utils'
|
||||
//import { isDate } from 'lodash'
|
||||
const layoutStore = useLayoutStore()
|
||||
const { prefixCls } = usePrefix('basic-side-menu')
|
||||
</script>
|
||||
|
||||
<style lang="less">
|
||||
@prefix:~ '@{prefixCls}-basic-side-menu';
|
||||
|
||||
.@{prefix}{
|
||||
|
||||
/* & ul{
|
||||
display: none;
|
||||
}*/
|
||||
|
||||
|
||||
/*background-color: antiquewhite;*/
|
||||
position: fixed;
|
||||
height: 100vh;
|
||||
right: 0;
|
||||
top: 0;
|
||||
|
||||
.ant-layout-sider-children{
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
}
|
||||
|
||||
.logo{
|
||||
border-bottom: 1px solid #eee;
|
||||
overflow: hidden;
|
||||
transition: all 0.3s;
|
||||
}
|
||||
|
||||
.side-version{
|
||||
border-top: 1px solid #eee;
|
||||
@apply p-2;
|
||||
max-height: 50px
|
||||
}
|
||||
|
||||
}
|
||||
</style>
|
||||
@@ -0,0 +1,247 @@
|
||||
<template>
|
||||
<ALayoutHeader
|
||||
theme="light"
|
||||
:class="[prefixCls]"
|
||||
:style="`height:${layoutStore.header.height};line-height:${layoutStore.header.height}`"
|
||||
>
|
||||
<!-- :style="`height:${layoutStore.header.height};line-height:${layoutStore.header.height}`"-->
|
||||
<div class="flex items-center">
|
||||
<div class="flex-1 flex">
|
||||
<img :src="getConfigApp('avatar')" style="height: 38px" class="mr-5 mt-1" />
|
||||
<BaseButton
|
||||
type="text"
|
||||
icon="vuesax-linear:menu"
|
||||
@click="handleCollapseSideMenu"
|
||||
v-if="layoutStore.layout == 'side'"
|
||||
/>
|
||||
<!-- justify-center flex-1 -->
|
||||
<!-- <div class="">-->
|
||||
<BasicMenu/>
|
||||
<!-- </div>-->
|
||||
</div>
|
||||
<!-- <BaseButton icon="vuesax-linear:menu" @click="handleCollapseSideMenu"></BaseButton>-->
|
||||
<!-- <div @click="handleCollapseSideMenu">بستن منو</div>-->
|
||||
<div class="flex items-center gap-3 ">
|
||||
<div>
|
||||
<BaseButton size="small" @click="openNewTabBalance">تراز</BaseButton>
|
||||
</div>
|
||||
<ADropdown placement="bottomLeft" class="ml-5">
|
||||
<a class="ant-dropdown-link" @click.prevent>
|
||||
<!-- Hover me-->
|
||||
<div class="flex items-center gap-1 text-gray-400">
|
||||
<AAvatar :src="placeholderM" />
|
||||
<Icon icon="vuesax-linear:arrow-down" size="15" />
|
||||
</div>
|
||||
</a>
|
||||
<template #overlay>
|
||||
<AMenu>
|
||||
<AMenuItem>
|
||||
<div class="flex flex-col">
|
||||
<span class="font-bold">{{ userStore.userInfo?.name }}</span>
|
||||
<span>{{ userStore.userInfo?.post_user }}</span>
|
||||
</div>
|
||||
</AMenuItem>
|
||||
<AMenuDivider />
|
||||
<AMenuItem @click="myInfoVisible = true">
|
||||
<div class="flex items-center gap-1">
|
||||
<Icon icon="vuesax-linear:profile" size="18" />
|
||||
<span>اطلاعات حساب کاربری</span>
|
||||
</div>
|
||||
</AMenuItem>
|
||||
<AMenuItem @click="clearLocalStorage">
|
||||
<div class="flex items-center gap-1">
|
||||
<Icon icon="vuesax-linear:logout" size="18" />
|
||||
<span>خروج</span>
|
||||
</div>
|
||||
</AMenuItem>
|
||||
</AMenu>
|
||||
</template>
|
||||
</ADropdown>
|
||||
<!-- todo remove -->
|
||||
<div class="w-2"></div>
|
||||
<BaseButton
|
||||
iconSize="20"
|
||||
icon="vuesax-linear:setting"
|
||||
type="text"
|
||||
v-if="layoutStore.showSettingsIcon"
|
||||
@click="handleShowSettings"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<BasicModal
|
||||
v-model:visible="myInfoVisible"
|
||||
width="40rem"
|
||||
title="اطلاعات حساب کاربری"
|
||||
@ok="ok"
|
||||
:loading="loading"
|
||||
@close="myInfoVisible = false"
|
||||
>
|
||||
<a-form :model="form" ref="formRef" autocomplete="off">
|
||||
<div class="grid md:grid-cols-2 gap-4">
|
||||
<a-form-item label="نام" name="fname" :rules="inputRules()">
|
||||
<BasicInput v-model:value="form.fname" />
|
||||
</a-form-item>
|
||||
<a-form-item label="نام خانوادگی" name="lname" :rules="inputRules()">
|
||||
<BasicInput v-model:value="form.lname" />
|
||||
</a-form-item>
|
||||
<a-form-item label="شماره موبایل" name="mobile" :rules="inputLenRules(11)">
|
||||
<BasicInput v-model:value="form.mobile" type="number" />
|
||||
</a-form-item>
|
||||
<a-form-item label="رمز کاربری" name="password">
|
||||
<BasicInput type="password" v-model:value="form.password" />
|
||||
</a-form-item>
|
||||
</div>
|
||||
</a-form>
|
||||
</BasicModal>
|
||||
|
||||
<!-- this is admin header-->
|
||||
<!-- <div :class="['admin-header-wide', layout, pageWidth]">
|
||||
<router-link
|
||||
v-if="isMobile || layout === 'head'"
|
||||
to="/"s
|
||||
:class="['logo', isMobile ? null : 'pc', headerTheme]"
|
||||
>
|
||||
<img width="32" src="@/assets/img/logo.png" />
|
||||
<h1 v-if="!isMobile">{{ systemName }}</h1>
|
||||
</router-link>
|
||||
<a-divider v-if="isMobile" type="vertical" />
|
||||
<a-icon
|
||||
v-if="layout !== 'head'"
|
||||
class="trigger"
|
||||
:type="collapsed ? 'menu-unfold' : 'menu-fold'"
|
||||
@click="toggleCollapse"
|
||||
/>
|
||||
<div
|
||||
v-if="layout !== 'side' && !isMobile"
|
||||
class="admin-header-menu"
|
||||
:style="`width: ${menuWidth};`"
|
||||
>
|
||||
<i-menu
|
||||
class="head-menu"
|
||||
:theme="headerTheme"
|
||||
mode="horizontal"
|
||||
:options="menuData"
|
||||
@select="onSelect"
|
||||
/>
|
||||
</div>
|
||||
<div :class="['admin-header-right', headerTheme]">
|
||||
<header-search class="header-item" @active="(val) => (searchActive = val)" />
|
||||
<a-tooltip class="header-item" title="帮助文档" placement="bottom">
|
||||
<a href="https://iczer.gitee.io/vue-antd-admin-docs/" target="_blank">
|
||||
<a-icon type="question-circle-o" />
|
||||
</a>
|
||||
</a-tooltip>
|
||||
<header-notice class="header-item" />
|
||||
<header-avatar class="header-item" />
|
||||
<a-dropdown class="lang header-item">
|
||||
<div><a-icon type="global" /> {{ langAlias }}</div>
|
||||
<a-menu @click="(val) => setLang(val.key)" :selected-keys="[lang]" slot="overlay">
|
||||
<a-menu-item v-for="lang in langList" :key="lang.key">{{
|
||||
lang.key.toLowerCase() + ' ' + lang.name
|
||||
}}</a-menu-item>
|
||||
</a-menu>
|
||||
</a-dropdown>
|
||||
</div>
|
||||
</div>-->
|
||||
</ALayoutHeader>
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import {openNewTabBalance} from '@core/composable/appInfo'
|
||||
import { usePrefix } from '@core/composable/usePrefix'
|
||||
import { useLayoutStore } from '@core/stores/layout'
|
||||
import BasicMenu from '@core/layouts/composnts/BasicMenu.vue'
|
||||
import placeholderM from '@core/assets/img/avatars/placeholder-m.jpg'
|
||||
import Icon from '@core/components/BaseIcon/src/Icon.vue'
|
||||
import { useSettingsStore } from '@core/stores/settings'
|
||||
import { useStaticApiListsStore } from '@/store/staticApisStore'
|
||||
import { useUserStore } from '@/store/userStore'
|
||||
import { inputRules, inputLenRules } from '@/utils/inputRules'
|
||||
import type { User } from '@/model/user'
|
||||
import { createUser, updateMyInformation, updateUser } from '@/api/user'
|
||||
import { message } from 'ant-design-vue/es'
|
||||
import { onMounted, ref } from 'vue'
|
||||
import type { FormInstance } from 'ant-design-vue'
|
||||
import { cloneDeep } from 'lodash'
|
||||
import { useWindowSize } from '@vueuse/core'
|
||||
import {getConfigApp} from "@/utils/config";
|
||||
const { prefixCls } = usePrefix('basic-header')
|
||||
const layoutStore = useLayoutStore()
|
||||
const store = useStaticApiListsStore()
|
||||
const userStore = useUserStore()
|
||||
const settingsStore = useSettingsStore()
|
||||
|
||||
|
||||
const { width } = useWindowSize()
|
||||
//my info modal
|
||||
const loading = ref<boolean>(false)
|
||||
const myInfoVisible = ref<boolean>(false)
|
||||
const formRef = ref<FormInstance>()
|
||||
const form = ref<User>({
|
||||
fname: '',
|
||||
lname: '',
|
||||
mobile: '',
|
||||
post_user: '',
|
||||
manager_id: '',
|
||||
responsible_id: '',
|
||||
section: '',
|
||||
section_id: undefined,
|
||||
process_id: '',
|
||||
qc_id: undefined,
|
||||
user_type: undefined,
|
||||
permission: []
|
||||
})
|
||||
onMounted(() => {
|
||||
form.value = cloneDeep(userStore?.userInfo) as User
|
||||
|
||||
|
||||
})
|
||||
//submit user
|
||||
async function ok() {
|
||||
formRef.value?.validateFields().then(async () => {
|
||||
loading.value = true
|
||||
try {
|
||||
await updateMyInformation(form.value)
|
||||
userStore.getMyInfo()
|
||||
message.success('اطلاعات با موفقیت ویرایش شد')
|
||||
myInfoVisible.value = false
|
||||
} catch (e) {
|
||||
// message.error('خطا در بارگذاری اطلاعات')
|
||||
console.error(e)
|
||||
} finally {
|
||||
loading.value = false
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
//const temp = 12
|
||||
function handleCollapseSideMenu() {
|
||||
layoutStore.sideMenu.collapsed = !layoutStore.sideMenu.collapsed
|
||||
}
|
||||
|
||||
function handleShowSettings() {
|
||||
settingsStore.showSettingsDrawer = !settingsStore.showSettingsDrawer
|
||||
}
|
||||
|
||||
function clearLocalStorage() {
|
||||
localStorage.clear()
|
||||
location.reload()
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="less">
|
||||
@prefix: ~'@{prefixCls}-basic-header';
|
||||
|
||||
.@{prefix} {
|
||||
padding: unset;
|
||||
//height: unset;
|
||||
//@apply flex flex-col justify-center ;
|
||||
//height: 64px;
|
||||
//line-height: unset;
|
||||
border-bottom: 2px solid #eee;
|
||||
// height: @header-height;
|
||||
background-color: #fff;
|
||||
//@apply backdrop-blur bg-red-200;
|
||||
}
|
||||
</style>
|
||||
@@ -0,0 +1,151 @@
|
||||
<template>
|
||||
<!-- 'admin-layout', 'beauty-scroll'-->
|
||||
<ALayout
|
||||
:class="[prefixCls, { 'overflow-y-scroll': !layoutStore.header.fixed }]"
|
||||
class="h-screen"
|
||||
>
|
||||
<!-- v-model="drawerOpen"-->
|
||||
<ADrawer v-if="isMobile">
|
||||
<!-- aside menu
|
||||
<SideMenu
|
||||
:theme="theme.mode"
|
||||
:menuData="menuData"
|
||||
:collapsed="false"
|
||||
:collapsible="false"
|
||||
@menuSelect="onMenuSelect"
|
||||
/>-->
|
||||
</ADrawer>
|
||||
<!-- v-else-if="layout === 'side' || layout === 'mix'"-->
|
||||
<!-- :class="[fixedSideBar ? 'fixed-side' : '']"
|
||||
:theme="theme.mode"
|
||||
:menuData="sideMenuData"
|
||||
:collapsed="collapsed"
|
||||
:collapsible="true"-->
|
||||
<BaseSideMenu v-else-if="layoutStore.layout === 'side'" />
|
||||
<div
|
||||
v-if="layoutStore.sideMenu.fixedSideBar && !isMobile"
|
||||
:style="`width: ${layoutStore.sideMenuWidth}; min-width: ${layoutStore.sideMenuWidth};max-width: ${layoutStore.sideMenuWidth};`"
|
||||
class="virtual-side-menu"
|
||||
></div>
|
||||
<!-- v-if="!hideSetting" v-model="showSetting"-->
|
||||
<ADrawer placement="left">
|
||||
<!-- <div class="setting" slot="handler">
|
||||
<!– <a-icon :type="showSetting ? 'close' : 'setting'" />–>
|
||||
</div>-->
|
||||
this is setting
|
||||
<!-- <setting />-->
|
||||
</ADrawer>
|
||||
<!-- class="admin-layout-main beauty-scroll"-->
|
||||
<ALayout>
|
||||
<!-- 111111 this is header-->
|
||||
<BasicHeader class="hidden md:block"></BasicHeader>
|
||||
<BasicMobileHeader class="md:!hidden"></BasicMobileHeader>
|
||||
<!-- <admin-header
|
||||
:class="[{ 'fixed-tabs': fixedTabs, 'fixed-header': fixedHeader, 'multi-page': multiPage }]"
|
||||
:style="headerStyle"
|
||||
:menuData="headMenuData"
|
||||
:collapsed="collapsed"
|
||||
@toggleCollapse="toggleCollapse"
|
||||
/>-->
|
||||
<!-- <ALayoutHeader
|
||||
:class="[
|
||||
'virtual-header',
|
||||
{ 'fixed-tabs': fixedTabs, 'fixed-header': fixedHeader, 'multi-page': multiPage }
|
||||
]"
|
||||
v-show="fixedHeader"
|
||||
></ALayoutHeader>-->
|
||||
<!-- :style="`min-height: ${minHeight}px;`"-->
|
||||
<ALayoutContent
|
||||
class="admin-layout-content"
|
||||
:class="[{ 'overflow-y-scroll': layoutStore.header.fixed }]"
|
||||
>
|
||||
<!-- :style="{`min-height: ${minHeight}px;`}"-->
|
||||
<!-- this is content-->
|
||||
<!-- <Btn1></Btn1>-->
|
||||
<!-- <BaseButton />-->
|
||||
<!-- <T5></T5>-->
|
||||
<!-- <T6></T6>
|
||||
<BaseIcon />
|
||||
<BaseButton />-->
|
||||
<!-- <T1></T1>
|
||||
<T100 />
|
||||
<T63 />-->
|
||||
<!-- <T78 />-->
|
||||
<!-- <BaseButton />-->
|
||||
<!-- {{ temp. }}-->
|
||||
<!-- {{ temp. }}-->
|
||||
<!-- this is conente
|
||||
<div v-for="i in 30" class="">111111111</div>-->
|
||||
<!-- <div style="position: relative">
|
||||
<slot></slot>
|
||||
</div>-->
|
||||
<RouterView v-slot="{ Component }">
|
||||
<!-- mode="out-in"-->
|
||||
<!-- <transition>-->
|
||||
<component :is="Component" />
|
||||
<!-- </transition>-->
|
||||
</RouterView>
|
||||
</ALayoutContent>
|
||||
<!-- <LayoutFooter style="padding: 0px">
|
||||
footer
|
||||
<!– <page-footer :link-list="footerLinks" :copyright="copyright" />–>
|
||||
</LayoutFooter>-->
|
||||
</ALayout>
|
||||
<BaseSettings />
|
||||
</ALayout>
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import BaseSideMenu from './BaseSideMenu.vue'
|
||||
import BasicHeader from './BasicHeader.vue'
|
||||
import { usePrefix } from '@core/composable/usePrefix'
|
||||
import { useLayoutStore } from '@core/stores/layout'
|
||||
import { isMobile } from '@core/utils/is'
|
||||
import BaseSettings from '@core/layouts/BaseSettings.vue'
|
||||
import BasicMobileheader from "@/components/BasicMobileHeader.vue";
|
||||
const { prefixCls } = usePrefix('basic-layout')
|
||||
const layoutStore = useLayoutStore()
|
||||
</script>
|
||||
|
||||
<style lang="less">
|
||||
@prefix:~'@{prefixCls}-basic-layout';
|
||||
|
||||
.@{prefix}{
|
||||
.virtual-side-menu{
|
||||
transition: all 0.2s;
|
||||
}
|
||||
|
||||
/* .fade-enter-active,
|
||||
.fade-leave-active {
|
||||
transition: opacity 0.5s ease;
|
||||
}
|
||||
|
||||
.fade-enter-from,
|
||||
.fade-leave-to {
|
||||
opacity: 0;
|
||||
}*/
|
||||
|
||||
/*
|
||||
.bounce-enter-active {
|
||||
animation: bounce-in 0.5s;
|
||||
}
|
||||
.bounce-leave-active {
|
||||
animation: bounce-in 0.5s reverse;
|
||||
}
|
||||
@keyframes bounce-in {
|
||||
0% {
|
||||
transform: scale(0);
|
||||
}
|
||||
50% {
|
||||
transform: scale(1.25);
|
||||
}
|
||||
100% {
|
||||
transform: scale(1);
|
||||
}
|
||||
}*/
|
||||
|
||||
|
||||
|
||||
|
||||
}
|
||||
</style>
|
||||
@@ -0,0 +1,32 @@
|
||||
<template>
|
||||
<AMenuItem
|
||||
:disabled="props.item.meta?.disabled ?? false"
|
||||
:key="props.item.name"
|
||||
@click="handleClickMenuItem(item)"
|
||||
>
|
||||
<template #icon>
|
||||
<BaseIcon :size="menuIconSize" v-if="props.item.meta?.icon" :icon="props.item.meta?.icon" />
|
||||
</template>
|
||||
<span>{{ props.item.meta.title ?? props.item.name }}</span>
|
||||
<!-- <template #title>1111</template>-->
|
||||
<!-- <div class="flex"></div>-->
|
||||
</AMenuItem>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { menuIconSize } from '@root/config'
|
||||
import type { RouteRecordRaw } from 'vue-router'
|
||||
|
||||
const router = useRouter()
|
||||
interface Props {
|
||||
item: RouteRecordRaw
|
||||
}
|
||||
|
||||
const props = withDefaults(defineProps<Props>(), {})
|
||||
|
||||
async function handleClickMenuItem(item: RouteRecordRaw) {
|
||||
router.push({ name: item.name })
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped lang="less"></style>
|
||||
@@ -0,0 +1,292 @@
|
||||
<template>
|
||||
|
||||
<div :class="[prefixCls, `${layoutStore.layout}-menu`]">
|
||||
<!-- :selectedKeys="selectedKeys"-->
|
||||
<AMenu :mode="layoutStore.sideMenu.mode" v-model:selectedKeys="selectedKeys" >
|
||||
<template v-for="item in menu">
|
||||
<BasicSubMenu
|
||||
v-if="!item.meta?.hideChildren && item.children && item.children.length > 0"
|
||||
:menu-item="item"
|
||||
:key="item.name"
|
||||
:level="1"
|
||||
/>
|
||||
<!-- <AMenuItem
|
||||
v-else
|
||||
:disabled="item.meta.disabled ?? false"
|
||||
:key="item.name"
|
||||
@click="handleClickMenuItem(item)"
|
||||
>
|
||||
<template #icon>
|
||||
<BaseIcon :size="menuIconSize" v-if="item.meta.icon" :icon="item.meta.icon" />
|
||||
</template>
|
||||
<span>{{ item.meta.title ?? item.name }}</span>
|
||||
<!– <template #title>1111</template>–>
|
||||
<!– <div class="flex"></div>–>
|
||||
</AMenuItem>-->
|
||||
<BaseMenuItem v-else :item="item" :key="item.name"/>
|
||||
</template>
|
||||
|
||||
|
||||
</AMenu >
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import {usePrefix} from '@core/composable/usePrefix'
|
||||
//import { menuIconSize } from '@root/config'
|
||||
import {computed} from 'vue'
|
||||
import type {ComputedRef} from 'vue'
|
||||
import {sortBy} from 'lodash'
|
||||
//import { routes } from '@/core/router/routes'
|
||||
import BasicSubMenu from '@core/layouts/composnts/BasicSubMenu.vue'
|
||||
import {useLayoutStore} from '@core/stores/layout'
|
||||
import BaseMenuItem from '@core/layouts/composnts/BaseMenuItem.vue'
|
||||
import type {RouteRecordName, RouteRecordRaw} from 'vue-router'
|
||||
import {useRouterStore} from '@core/stores/router'
|
||||
|
||||
const {prefixCls} = usePrefix('basic-menu')
|
||||
const layoutStore = useLayoutStore()
|
||||
const currentRoute = useRoute()
|
||||
const selectedKeys = ref<(RouteRecordName | undefined)[]>([])
|
||||
const routerStore = useRouterStore()
|
||||
/*const selectedKeys = computed(() => {
|
||||
const path: (RouteRecordName | undefined)[] = []
|
||||
|
||||
function walkInRoutes(routes: RouteRecordRaw[]) {
|
||||
for (const route of routes) {
|
||||
if (route.name == currentRoute.name) {
|
||||
path.push(route.name)
|
||||
return true
|
||||
}
|
||||
if (route.children && route.children.length > 0) {
|
||||
path.push(route.name)
|
||||
const res = walkInRoutes(route.children)
|
||||
if (!res) {
|
||||
path.pop()
|
||||
} else {
|
||||
return true
|
||||
}
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
walkInRoutes(routes)
|
||||
|
||||
return path
|
||||
})*/
|
||||
|
||||
onMounted(() => {
|
||||
//console.log('aaa')
|
||||
|
||||
const path: (RouteRecordName | undefined)[] = []
|
||||
|
||||
function walkInRoutes(routes: RouteRecordRaw[]) {
|
||||
for (const route of routes) {
|
||||
if (route.name == currentRoute.name) {
|
||||
path.push(route.name)
|
||||
return true
|
||||
}
|
||||
if (route.children && route.children.length > 0) {
|
||||
path.push(route.name)
|
||||
const res = walkInRoutes(route.children)
|
||||
if (!res) {
|
||||
path.pop()
|
||||
} else {
|
||||
return true
|
||||
}
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
walkInRoutes(routerStore.routes)
|
||||
selectedKeys.value = path
|
||||
|
||||
// return path
|
||||
|
||||
})
|
||||
|
||||
const menu: ComputedRef<RouteRecordRaw[]> = computed(() => {
|
||||
return sortBy(routerStore.routes, (item) => {
|
||||
return item.meta?.order
|
||||
}).filter((item) => !item.meta?.hideMenu)
|
||||
})
|
||||
</script>
|
||||
|
||||
<style lang="less">
|
||||
@prefix: ~ '@{prefixCls}-basic-menu';
|
||||
.@{prefix} {
|
||||
|
||||
&.top-menu {
|
||||
@apply pr-5;
|
||||
//display: inline-flex;
|
||||
.ant-menu {
|
||||
// @apply gap-3;
|
||||
//@apply flex-inline;
|
||||
//@apply grid;
|
||||
}
|
||||
|
||||
.ant-menu-horizontal:not(.ant-menu-dark) > .ant-menu-item, .ant-menu-horizontal:not(.ant-menu-dark) > .ant-menu-submenu {
|
||||
padding: 0 5px;
|
||||
}
|
||||
|
||||
/*TODO check for line bottom menu*/
|
||||
|
||||
.ant-menu-horizontal > .ant-menu-item::after, .ant-menu-horizontal > .ant-menu-submenu::after {
|
||||
right: 0 !important;
|
||||
left: 0 !important;
|
||||
}
|
||||
|
||||
.ant-menu-horizontal > .ant-menu-item-selected::after, .ant-menu-horizontal > .ant-menu-submenu-selected::after {
|
||||
position: absolute;
|
||||
bottom: 0;
|
||||
border-bottom: 2px solid @primary-color;
|
||||
transition: border-color 0.3s cubic-bezier(0.645, 0.045, 0.355, 1);
|
||||
content: '';
|
||||
}
|
||||
|
||||
.ant-menu-item-selected {
|
||||
//background-color: red;
|
||||
background-color: lighten(@primary-color, 53%);
|
||||
|
||||
/*.ant-menu-horizontal:not(.ant-menu-dark) > .ant-menu-item:after{
|
||||
border-bottom: 5px solid red;
|
||||
background-color: red;
|
||||
}*/
|
||||
|
||||
/*& > .ant-menu-item::after {
|
||||
position: absolute;
|
||||
right: 20px;
|
||||
bottom: 0;
|
||||
left: 20px;
|
||||
border-bottom: 2px solid #0052d9;
|
||||
transition: border-color 0.3s cubic-bezier(0.645, 0.045, 0.355, 1);
|
||||
content: '';
|
||||
}*/
|
||||
|
||||
|
||||
}
|
||||
|
||||
.ant-menu-item {
|
||||
margin-left: 12px;
|
||||
}
|
||||
|
||||
/*.ant-menu-item:not(.ant-menu-item-disabled):not(.ant-menu-item-selected):hover,
|
||||
.ant-menu-submenu .ant-menu-submenu-title:not(.ant-menu-item-disabled):hover
|
||||
{
|
||||
border-radius:unset !important;
|
||||
}*/
|
||||
|
||||
//display: inline-flex;
|
||||
//justify-content: center;
|
||||
}
|
||||
|
||||
.ant-menu-item, .ant-menu-submenu-title {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
|
||||
& .ant-menu-item-icon {
|
||||
margin-right: unset !important;
|
||||
}
|
||||
}
|
||||
|
||||
/** start style for horizontal menu */
|
||||
|
||||
.ant-menu-horizontal {
|
||||
padding: 0 !important;
|
||||
|
||||
li {
|
||||
padding: 5px;
|
||||
}
|
||||
}
|
||||
|
||||
/** end style for horizontal menu */
|
||||
|
||||
&-side-menu {
|
||||
.ant-menu-item:not(.ant-menu-item-disabled):not(.ant-menu-item-selected):hover,
|
||||
.ant-menu-submenu .ant-menu-submenu-title:not(.ant-menu-item-disabled):hover {
|
||||
transition: background-color 0.9ms linear;
|
||||
border-radius: var(--border-radius-base);
|
||||
color: unset !important;
|
||||
//color: red;
|
||||
background-color: #f3f3f3 !important;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
/* .ant-menu-inline-collapsed{
|
||||
.ant-menu-item,.ant-menu-submenu-title{
|
||||
//display: block;
|
||||
}
|
||||
}*/
|
||||
|
||||
|
||||
.ant-menu {
|
||||
padding: 10px;
|
||||
user-select: none;
|
||||
}
|
||||
|
||||
.ant-menu-title-content {
|
||||
font-size: 15px;
|
||||
}
|
||||
|
||||
.ant-menu-item, .ant-menu-submenu-title {
|
||||
//padding: unset !important;
|
||||
@apply px-2 !important;
|
||||
}
|
||||
|
||||
|
||||
.ant-menu.ant-menu-inline-collapsed > .ant-menu-item .ant-menu-item-icon + span,
|
||||
.ant-menu.ant-menu-inline-collapsed > .ant-menu-submenu .ant-menu-item-icon + span {
|
||||
display: none !important;
|
||||
/*display: flex !important;
|
||||
flex-direction: column !important;
|
||||
justify-content: center !important;*/
|
||||
}
|
||||
|
||||
.ant-menu.ant-menu-inline-collapsed > .ant-menu-submenu > .ant-menu-submenu-title {
|
||||
padding: 0 !important;
|
||||
display: flex !important;
|
||||
align-items: center !important;
|
||||
justify-content: center !important;
|
||||
}
|
||||
|
||||
|
||||
//,.ant-menu.ant-menu-inline-collapsed > .ant-menu-submenu
|
||||
.ant-menu.ant-menu-inline-collapsed > .ant-menu-item {
|
||||
padding: 0 !important;
|
||||
display: flex !important;
|
||||
align-items: center !important;
|
||||
justify-content: center !important;
|
||||
}
|
||||
|
||||
.ant-menu-vertical > .ant-menu-submenu > .ant-menu-submenu-title {
|
||||
height: 36px;
|
||||
}
|
||||
|
||||
|
||||
/*.ant-menu-submenu-title,.ant-menu-submenu-arrow{
|
||||
//color: #f3f3f3 !important;
|
||||
}*/
|
||||
|
||||
|
||||
.ant-menu-item.ant-menu-item-selected {
|
||||
//border-radius: var(--border-radius-base);
|
||||
&::after {
|
||||
content: unset;
|
||||
}
|
||||
}
|
||||
|
||||
.ant-menu.ant-menu-sub.ant-menu-inline {
|
||||
background-color: unset !important;
|
||||
}
|
||||
|
||||
.ant-menu-vertical > .ant-menu-submenu,
|
||||
.ant-menu-vertical > .ant-menu-item {
|
||||
height: 36px;
|
||||
}
|
||||
|
||||
}
|
||||
</style>
|
||||
@@ -0,0 +1,120 @@
|
||||
<template>
|
||||
<!-- <div :class="[prefixCls]">-->
|
||||
<ASubMenu :class="prefixCls" :popupClassName="`${prefixCls}-popup`" :popupOffset="popupOffset">
|
||||
<template #icon>
|
||||
<BaseIcon :size="menuIconSize" v-if="item.meta?.icon" :icon="item.meta.icon" />
|
||||
</template>
|
||||
<template #title>
|
||||
<span>{{ item.meta.title ?? item.name }}</span>
|
||||
</template>
|
||||
<template v-for="childItem in menu">
|
||||
<BasicSubMenu
|
||||
v-if="!childItem.meta?.hideChildren && childItem.children && childItem.children.length > 0"
|
||||
:menu-item="childItem"
|
||||
:key="childItem.name"
|
||||
:level="props.level + 1"
|
||||
/>
|
||||
<!-- <AMenuItem v-else :key="childItem.name" :disabled="childItem.meta.disabled ?? false">
|
||||
<template #icon>
|
||||
<BaseIcon :size="menuIconSize" v-if="childItem.meta.icon" :icon="childItem.meta.icon" />
|
||||
</template>
|
||||
<span>{{ childItem.meta.title ?? childItem.name }}</span>
|
||||
</AMenuItem>-->
|
||||
<BaseMenuItem v-else :item="childItem" :key="childItem.name" />
|
||||
</template>
|
||||
</ASubMenu>
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import { usePrefix } from '@core/composable/usePrefix'
|
||||
import { menuIconSize } from '@root/config'
|
||||
import { computed } from 'vue'
|
||||
import { sortBy } from 'lodash'
|
||||
//import { routes } from '@/core/router/routes'
|
||||
import type { RouteRecordRaw } from 'vue-router'
|
||||
import BaseMenuItem from '@core/layouts/composnts/BaseMenuItem.vue'
|
||||
const { prefixCls } = usePrefix('basic-sub-menu')
|
||||
|
||||
interface Props {
|
||||
menuItem: RouteRecordRaw
|
||||
level: string | number
|
||||
}
|
||||
|
||||
const props = withDefaults(defineProps<Props>(), {
|
||||
level: 1
|
||||
})
|
||||
|
||||
const popupOffset = computed(() => {
|
||||
if (props.level == 1) return [-63, 3]
|
||||
return [-8, -8]
|
||||
})
|
||||
|
||||
const item = computed(() => {
|
||||
return props.menuItem
|
||||
})
|
||||
|
||||
const menu = computed(() => {
|
||||
return sortBy(props.menuItem.children, (item) => {
|
||||
return item.meta?.order
|
||||
}).filter((item) => !item.meta?.hideMenu)
|
||||
})
|
||||
</script>
|
||||
|
||||
<style lang="less">
|
||||
@prefix:~ '@{prefixCls}-basic-sub-menu';
|
||||
.@{prefix}{
|
||||
|
||||
&.ant-menu-submenu-selected{
|
||||
border-radius: var(--border-radius-base);
|
||||
background-color: var(--ant-primary-1);
|
||||
.ant-menu-submenu-arrow{
|
||||
color: var(--ant-primary)
|
||||
}
|
||||
}
|
||||
|
||||
&-popup{
|
||||
|
||||
/*padding-right: 20px;*/
|
||||
ul{
|
||||
//display: none;
|
||||
border-radius: var(--border-radius-base);
|
||||
padding: 5px !important;
|
||||
}
|
||||
|
||||
.ant-menu-vertical.ant-menu-sub > .ant-menu-item{
|
||||
display: flex !important;
|
||||
align-items: center;
|
||||
gap:5px;
|
||||
}
|
||||
|
||||
//background-color: red;
|
||||
.ant-menu-vertical > .ant-menu-submenu > .ant-menu-submenu-title{
|
||||
display: flex;
|
||||
padding: 0 5px;
|
||||
gap:5px;
|
||||
align-items: center;
|
||||
height: 36px;
|
||||
}
|
||||
|
||||
li.ant-menu-item{
|
||||
border-radius: var(--border-radius-base);
|
||||
padding:0 5px;
|
||||
}
|
||||
|
||||
.ant-menu-vertical > .ant-menu-item{
|
||||
height: 36px;
|
||||
}
|
||||
|
||||
/* .ant-menu-submenu.ant-menu-submenu-popup{
|
||||
}*/
|
||||
|
||||
.ant-menu-submenu-arrow{
|
||||
right: unset !important;
|
||||
left: 10px;
|
||||
transform: rotate(180deg);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
</style>
|
||||
Reference in New Issue
Block a user