Skip to content

Commit

Permalink
feat(directive): added draggable sidebar functionality
Browse files Browse the repository at this point in the history
  • Loading branch information
ZhaoJiSen committed Jul 12, 2024
1 parent 55f8492 commit cb97dc9
Show file tree
Hide file tree
Showing 16 changed files with 252 additions and 113 deletions.
2 changes: 1 addition & 1 deletion src/API/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,7 @@ class RequestHttp {
);
}

get<T>(url: string, options?: any): Promise<ResultData<T>> {
get(url: string, options?: any): Promise<any> {
options = setOrgIDToRequestHeader(options);
return this.service.get(url, options);
}
Expand Down
26 changes: 26 additions & 0 deletions src/API/interface/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -26,3 +26,29 @@ export interface GlobalSetting {
CONNECTION_TOKEN_REUSABLE: boolean;
CHAT_AI_ENABLED: boolean;
}

export interface TreeMeta {
type: string;

data: {
id: string;
key: string;
value: string;
};
}

export interface Tree {
id: string;

isParent: Boolean;

name: string;

open: Boolean;

pId: string;

title: string;

meta: TreeMeta;
}
11 changes: 11 additions & 0 deletions src/API/modules/tree.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
import http from '@/API';
import type { Tree } from '@/API/interface';

export const getTreeSource = (async: Boolean): Promise<Tree[]> => {
const syncUrl = '/api/v1/perms/users/self/nodes/all-with-assets/tree/';
const asyncUrl = '/api/v1/perms/users/self/nodes/children-with-assets/tree/';

const url = async ? asyncUrl : syncUrl;

return http.get(url, { observe: 'response' });
};
18 changes: 15 additions & 3 deletions src/ThemeOverrides.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,9 +7,17 @@ export const lightThemeOverrides: GlobalThemeOverrides = {
Spin: {
color: '#1ab394',
textColor: '#292827 '
},
Dropdown: {
optionColorHover: '#48c2a9',
optionTextColorHover: '#fff'
},
Select: {
selectedColor: '#000'
},
Switch: {
// railColor: '#48c2a9'
}

// ...
};

export const darkThemeOverrides: GlobalThemeOverrides = {
Expand All @@ -21,6 +29,10 @@ export const darkThemeOverrides: GlobalThemeOverrides = {
textColor: '#ffffff'
},
Dropdown: {
optionColorHover: '#48c2a9'
optionColorHover: '#48c2a9',
optionTextColorHover: '#101014'
},
Switch: {
railColorActive: '#48c2a9'
}
};
38 changes: 38 additions & 0 deletions src/directive/sidebarDraggable.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
import { DirectiveBinding } from 'vue';

export const draggable = {
beforeMount(el: HTMLElement, binding: DirectiveBinding) {
let startX = 0;
let startWidth = 0;

const mouseMoveHandler = (event: MouseEvent) => {
const newWidth = startWidth + (event.clientX - startX);

// 确保宽度在合理范围内
if (newWidth >= 100 && newWidth <= 600) {
el.style.width = `${newWidth}px`;

// 更新传递的 ref 变量
binding.value = newWidth;
}
};

const mouseUpHandler = () => {
document.removeEventListener('mousemove', mouseMoveHandler);
document.removeEventListener('mouseup', mouseUpHandler);
};

const mouseDownHandler = (event: MouseEvent) => {
const rect = el.getBoundingClientRect();
// 只有在右侧边缘10px范围内拖动才触发
if (event.clientX >= rect.right - 10 && event.clientX <= rect.right) {
startX = event.clientX;
startWidth = el.offsetWidth;
document.addEventListener('mousemove', mouseMoveHandler);
document.addEventListener('mouseup', mouseUpHandler);
}
};

el.addEventListener('mousedown', mouseDownHandler);
}
};
22 changes: 22 additions & 0 deletions src/enums/assetIcon.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
import { h } from 'vue';
import SvgIcon from '@/components/SvgIcon/index.vue';

export enum AssetIconType {
// 数据库类
mysql = 'mysql',
mariadb = 'mariadb',

// 主机
windows = 'windows',
linux = 'linux',
macos = 'macos',
aix = 'aix',
bsd = 'bsd',
gatway = 'gatway',
remoteapphost = 'remoteapphost'
}

export const AssetIconMap = {
[AssetIconType.mysql]: h(SvgIcon, { name: 'mysql' }),
[AssetIconType.mariadb]: h(SvgIcon, { name: 'mariadb' })
};
143 changes: 64 additions & 79 deletions src/layouts/components/FileManagement/index.vue
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,13 @@
<n-tab-pane name="chap1" tab="资产树">
<n-input v-model:value="pattern" placeholder="搜索" />
<n-tree
checkable
block-line
:pattern="pattern"
expand-on-click
:data="data1"
checkbox-placement="left"
:show-line="true"
:pattern="pattern"
:data="testData"
:node-props="nodeProps"
:on-update:expanded-keys="updatePrefixWithExpaned"
/>
Expand All @@ -26,88 +29,22 @@
</template>

<script setup lang="ts">
import { reactive, ref, h } from 'vue';
import { reactive, ref, h, onUnmounted, onMounted } from 'vue';
import { storeToRefs } from 'pinia';
import { getTreeSource } from '@/API/modules/tree';
import { useTreeStore } from '@/stores/modules/tree.ts';
import { useMessage, NIcon, TreeOption } from 'naive-ui';
import { Folder, FolderOpenOutline, FileTrayFullOutline } from '@vicons/ionicons5';
import mittBus from '@/utils/mittBus.ts';
import type { Tree } from '@/API/interface';
const treeStore = useTreeStore();
const { isAsync } = storeToRefs(treeStore);
const message = useMessage();
const pattern = ref('');
const data1 = reactive([
{
key: '收藏夹',
label: '收藏夹',
prefix: () =>
h(NIcon, null, {
default: () => h(Folder)
}),
children: [
{
key: '空的',
label: '空的',
disabled: true,
prefix: () =>
h(NIcon, null, {
default: () => h(Folder)
})
},
{
key: '我的文件',
label: '我的文件',
prefix: () =>
h(NIcon, null, {
default: () => h(Folder)
}),
children: [
{
label: 'template.txt',
key: 'template.txt',
prefix: () =>
h(NIcon, null, {
default: () => h(FileTrayFullOutline)
})
}
]
}
]
},
{
key: 'Default',
label: 'Default',
prefix: () =>
h(NIcon, null, {
default: () => h(Folder)
}),
children: [
{
key: '空的',
label: '空的',
disabled: true,
prefix: () =>
h(NIcon, null, {
default: () => h(Folder)
})
},
{
key: '我的文件',
label: '我的文件',
prefix: () =>
h(NIcon, null, {
default: () => h(Folder)
}),
children: [
{
label: 'template.txt',
key: 'template.txt',
prefix: () =>
h(NIcon, null, {
default: () => h(FileTrayFullOutline)
})
}
]
}
]
}
]);
let testData = ref<TreeOption[]>([]);
const data2 = reactive([
{
key: '所有类型',
Expand Down Expand Up @@ -147,6 +84,7 @@ const data2 = reactive([
]
}
]);
const updatePrefixWithExpaned = (
_keys: Array<string | number>,
_option: Array<TreeOption | null>,
Expand Down Expand Up @@ -180,6 +118,53 @@ const nodeProps = ({ option }: { option: TreeOption }) => {
}
};
};
const loadTree = async (isAsync: Boolean) => {
try {
// 默认异步加载资产树
const res: Tree[] = await getTreeSource(isAsync);
const treeMap: { [key: string]: TreeOption } = {};
res.forEach(node => {
treeMap[node.id] = {
key: node.id,
label: node.name,
prefix: () =>
h(NIcon, null, {
default: () => h(node.isParent ? Folder : FileTrayFullOutline)
}),
children: [],
...node
};
});
res.forEach(node => {
if (node.pId && treeMap[node.pId]) {
treeMap[node.pId]?.children?.push(treeMap[node.id]);
}
});
const data = Object.values(treeMap).filter(node => !node.pId);
testData.value = data;
console.log(res);
console.log(data);
} catch (e) {
console.log(e);
}
};
onMounted(async () => {
await loadTree(isAsync.value);
});
mittBus.on('tree-load', () => {
loadTree(isAsync.value);
});
onUnmounted(() => {
mittBus.off('tree-load');
});
</script>

<style scoped lang="scss"></style>
6 changes: 3 additions & 3 deletions src/layouts/components/Header/headerLeft.vue
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
<n-flex justify="center" align="center" class="top-item">
<logo :logo-image="logoImage || ''" />
<n-flex justify="center" align="center">
<n-button text @click="handleTreeClick">
<n-button text @click="handleTreeIconClick">
<svg-icon class="tree-icon" :name="icon.name" :icon-style="iconStyle" />
</n-button>
</n-flex>
Expand Down Expand Up @@ -40,8 +40,8 @@ const icon = {
component: Profile
};
const handleTreeClick = () => {
mittBus.emit('treeClick');
const handleTreeIconClick = () => {
mittBus.emit('tree-click');
};
const logoImage = globalStore.interface.logo_logout;
Expand Down
2 changes: 1 addition & 1 deletion src/layouts/components/Header/headerRight.vue
Original file line number Diff line number Diff line change
Expand Up @@ -124,7 +124,7 @@ const bottomOptions: HeaderRightOptions[] = [
name: 'setting',
component: Setting,
onClick: () => {
mittBus.emit('openSettingDrawer');
mittBus.emit('open-setting-drawer');
}
}
];
Expand Down
4 changes: 2 additions & 2 deletions src/layouts/components/SettingDrawer/index.vue
Original file line number Diff line number Diff line change
Expand Up @@ -114,12 +114,12 @@ const languageOptions = reactive([
}
]);
mittBus.on('openSettingDrawer', () => {
mittBus.on('open-setting-drawer', () => {
showSettingDrawer.value = true;
});
onBeforeUnmount(() => {
mittBus.off('openSettingDrawer');
mittBus.off('open-setting-drawer');
});
</script>

Expand Down
Loading

0 comments on commit cb97dc9

Please sign in to comment.