提交 510f8603 编写于 作者: 查尔斯-BUG万象集's avatar 查尔斯-BUG万象集

新增:新增系统管理/菜单管理(列表、创建、修改、删除、导出)

上级 1319cb32
......@@ -249,6 +249,7 @@ continew-admin
│ │ ├─ monitor # 系统监控模块
│ │ └─ system # 系统管理模块
│ ├─ assets # 静态资源
│ │ ├─ icons # 图标资源
│ │ ├─ images # 图片资源
│ │ └─ style # 样式资源
│ ├─ components # 通用业务组件
......
/*
* Copyright (c) 2022-present Charles7c Authors. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package top.charles7c.cnadmin.common.enums;
import lombok.Getter;
import lombok.RequiredArgsConstructor;
import top.charles7c.cnadmin.common.base.BaseEnum;
/**
* 菜单类型枚举
*
* @author Charles7c
* @since 2023/2/15 20:12
*/
@Getter
@RequiredArgsConstructor
public enum MenuTypeEnum implements BaseEnum<Integer, String> {
/** 目录 */
DIR(1, "目录"),
/** 菜单 */
MENU(2, "菜单"),
/** 按钮 */
BUTTON(3, "按钮"),;
private final Integer value;
private final String description;
}
/*
* Copyright (c) 2022-present Charles7c Authors. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package top.charles7c.cnadmin.system.mapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import top.charles7c.cnadmin.system.model.entity.MenuDO;
/**
* 菜单 Mapper
*
* @author Charles7c
* @since 2023/2/15 20:30
*/
public interface MenuMapper extends BaseMapper<MenuDO> {}
/*
* Copyright (c) 2022-present Charles7c Authors. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package top.charles7c.cnadmin.system.mapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import top.charles7c.cnadmin.system.model.entity.RoleMenuDO;
/**
* 角色和菜单 Mapper
*
* @author Charles7c
* @since 2023/2/15 20:30
*/
public interface RoleMenuMapper extends BaseMapper<RoleMenuDO> {}
/*
* Copyright (c) 2022-present Charles7c Authors. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package top.charles7c.cnadmin.system.model.entity;
import lombok.Data;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import top.charles7c.cnadmin.common.base.BaseDO;
import top.charles7c.cnadmin.common.enums.DisEnableStatusEnum;
import top.charles7c.cnadmin.common.enums.MenuTypeEnum;
/**
* 菜单实体
*
* @author Charles7c
* @since 2023/2/15 20:14
*/
@Data
@TableName("sys_menu")
public class MenuDO extends BaseDO {
private static final long serialVersionUID = 1L;
/**
* 菜单 ID
*/
@TableId
private Long menuId;
/**
* 菜单名称
*/
private String menuName;
/**
* 上级菜单 ID
*/
private Long parentId;
/**
* 菜单类型(1目录 2菜单 3按钮)
*/
private MenuTypeEnum menuType;
/**
* 路由地址
*/
private String path;
/**
* 组件名称
*/
private String name;
/**
* 组件路径
*/
private String component;
/**
* 菜单图标
*/
private String icon;
/**
* 是否外链
*/
private Boolean isExternal;
/**
* 是否缓存
*/
private Boolean isCache;
/**
* 是否隐藏
*/
private Boolean isHidden;
/**
* 权限标识
*/
private String permission;
/**
* 菜单排序
*/
private Integer menuSort;
/**
* 状态(1启用 2禁用)
*/
private DisEnableStatusEnum status;
}
/*
* Copyright (c) 2022-present Charles7c Authors. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package top.charles7c.cnadmin.system.model.entity;
import java.io.Serializable;
import lombok.Data;
import com.baomidou.mybatisplus.annotation.TableName;
/**
* 角色和菜单实体
*
* @author Charles7c
* @since 2023/2/15 20:20
*/
@Data
@TableName("sys_role_menu")
public class RoleMenuDO implements Serializable {
private static final long serialVersionUID = 1L;
/**
* 角色 ID
*/
private Long roleId;
/**
* 菜单 ID
*/
private Long menuId;
}
/*
* Copyright (c) 2022-present Charles7c Authors. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package top.charles7c.cnadmin.system.model.query;
import java.io.Serializable;
import lombok.Data;
import io.swagger.v3.oas.annotations.media.Schema;
import org.springdoc.api.annotations.ParameterObject;
import top.charles7c.cnadmin.common.annotation.Query;
/**
* 菜单查询条件
*
* @author Charles7c
* @since 2023/2/15 20:21
*/
@Data
@ParameterObject
@Schema(description = "菜单查询条件")
public class MenuQuery implements Serializable {
private static final long serialVersionUID = 1L;
/**
* 菜单名称
*/
@Schema(description = "菜单名称")
@Query(type = Query.Type.INNER_LIKE)
private String menuName;
/**
* 状态(1启用 2禁用)
*/
@Schema(description = "状态(1启用 2禁用)")
@Query
private Integer status;
}
/*
* Copyright (c) 2022-present Charles7c Authors. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package top.charles7c.cnadmin.system.model.request;
import javax.validation.constraints.NotBlank;
import javax.validation.constraints.NotNull;
import javax.validation.constraints.Null;
import lombok.Data;
import io.swagger.v3.oas.annotations.media.Schema;
import top.charles7c.cnadmin.common.base.BaseRequest;
import top.charles7c.cnadmin.common.enums.DisEnableStatusEnum;
import top.charles7c.cnadmin.common.enums.MenuTypeEnum;
/**
* 创建或修改菜单信息
*
* @author Charles7c
* @since 2023/2/15 20:21
*/
@Data
@Schema(description = "创建或修改菜单信息")
public class MenuRequest extends BaseRequest {
private static final long serialVersionUID = 1L;
/**
* 菜单 ID
*/
@Schema(description = "菜单 ID")
@Null(message = "新增时,ID 必须为空", groups = Create.class)
@NotNull(message = "修改时,ID 不能为空", groups = Update.class)
private Long menuId;
/**
* 上级菜单 ID
*/
@Schema(description = "上级菜单 ID")
private Long parentId;
/**
* 菜单名称
*/
@Schema(description = "菜单名称")
@NotBlank(message = "菜单名称不能为空")
private String menuName;
/**
* 菜单类型(1目录 2菜单 3按钮)
*/
@Schema(description = "菜单类型(1目录 2菜单 3按钮)", type = "Integer", allowableValues = {"1", "2", "3"})
@NotNull(message = "菜单类型非法")
private MenuTypeEnum menuType;
/**
* 路由地址
*/
@Schema(description = "路由地址")
private String path;
/**
* 组件名称
*/
@Schema(description = "组件名称")
private String name;
/**
* 组件路径
*/
@Schema(description = "组件路径")
private String component;
/**
* 菜单图标
*/
@Schema(description = "菜单图标")
private String icon;
/**
* 是否外链
*/
@Schema(description = "是否外链")
private Boolean isExternal;
/**
* 是否缓存
*/
@Schema(description = "是否缓存")
private Boolean isCache;
/**
* 是否隐藏
*/
@Schema(description = "是否隐藏")
private Boolean isHidden;
/**
* 权限标识
*/
@Schema(description = "权限标识")
private String permission;
/**
* 菜单排序
*/
@Schema(description = "菜单排序")
@NotNull(message = "菜单排序不能为空")
private Integer menuSort;
/**
* 状态(1启用 2禁用)
*/
@Schema(description = "状态(1启用 2禁用)", type = "Integer", allowableValues = {"1", "2"})
private DisEnableStatusEnum status;
}
/*
* Copyright (c) 2022-present Charles7c Authors. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package top.charles7c.cnadmin.system.model.vo;
import java.util.List;
import lombok.Data;
import lombok.experimental.Accessors;
import io.swagger.v3.oas.annotations.media.Schema;
import top.charles7c.cnadmin.common.base.BaseVO;
import top.charles7c.cnadmin.common.enums.DisEnableStatusEnum;
import top.charles7c.cnadmin.common.enums.MenuTypeEnum;
/**
* 菜单信息
*
* @author Charles7c
* @since 2023/2/15 20:23
*/
@Data
@Accessors(chain = true)
@Schema(description = "菜单信息")
public class MenuVO extends BaseVO {
private static final long serialVersionUID = 1L;
/**
* 菜单 ID
*/
@Schema(description = "菜单 ID")
private Long menuId;
/**
* 菜单名称
*/
@Schema(description = "菜单名称")
private String menuName;
/**
* 上级菜单 ID
*/
@Schema(description = "上级菜单 ID")
private Long parentId;
/**
* 菜单类型(1目录 2菜单 3按钮)
*/
@Schema(description = "菜单类型(1目录 2菜单 3按钮)")
private MenuTypeEnum menuType;
/**
* 路由地址
*/
@Schema(description = "路由地址")
private String path;
/**
* 组件名称
*/
@Schema(description = "组件名称")
private String name;
/**
* 组件路径
*/
@Schema(description = "组件路径")
private String component;
/**
* 菜单图标
*/
@Schema(description = "菜单图标")
private String icon;
/**
* 是否外链
*/
@Schema(description = "是否外链")
private Boolean isExternal;
/**
* 是否缓存
*/
@Schema(description = "是否缓存")
private Boolean isCache;
/**
* 是否隐藏
*/
@Schema(description = "是否隐藏")
private Boolean isHidden;
/**
* 权限标识
*/
@Schema(description = "权限标识")
private String permission;
/**
* 菜单排序
*/
@Schema(description = "菜单排序")
private Integer menuSort;
/**
* 状态(1启用 2禁用)
*/
@Schema(description = "状态(1启用 2禁用)")
private DisEnableStatusEnum status;
/**
* 子菜单列表
*/
@Schema(description = "子菜单列表")
private List<MenuVO> children;
}
/*
* Copyright (c) 2022-present Charles7c Authors. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package top.charles7c.cnadmin.system.service;
import java.util.List;
import cn.hutool.core.lang.tree.Tree;
import top.charles7c.cnadmin.common.base.BaseService;
import top.charles7c.cnadmin.system.model.query.MenuQuery;
import top.charles7c.cnadmin.system.model.request.MenuRequest;
import top.charles7c.cnadmin.system.model.vo.MenuVO;
/**
* 菜单业务接口
*
* @author Charles7c
* @since 2023/2/15 20:30
*/
public interface MenuService extends BaseService<MenuVO, MenuVO, MenuQuery, MenuRequest> {
/**
* 构建树
*
* @param list
* 原始列表数据
* @return 树列表
*/
List<MenuVO> buildListTree(List<MenuVO> list);
/**
* 构建树
*
* @param list
* 原始列表数据
* @return 树列表
*/
List<Tree<Long>> buildTree(List<MenuVO> list);
}
/*
* Copyright (c) 2022-present Charles7c Authors. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package top.charles7c.cnadmin.system.service.impl;
import java.util.ArrayList;
import java.util.List;
import java.util.Objects;
import java.util.stream.Collectors;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.lang.tree.Tree;
import top.charles7c.cnadmin.common.base.BaseServiceImpl;
import top.charles7c.cnadmin.common.enums.DisEnableStatusEnum;
import top.charles7c.cnadmin.common.util.TreeUtils;
import top.charles7c.cnadmin.common.util.validate.CheckUtils;
import top.charles7c.cnadmin.system.mapper.MenuMapper;
import top.charles7c.cnadmin.system.model.entity.MenuDO;
import top.charles7c.cnadmin.system.model.query.MenuQuery;
import top.charles7c.cnadmin.system.model.request.MenuRequest;
import top.charles7c.cnadmin.system.model.vo.MenuVO;
import top.charles7c.cnadmin.system.service.MenuService;
/**
* 菜单业务实现类
*
* @author Charles7c
* @since 2023/2/15 20:30
*/
@Service
@RequiredArgsConstructor
public class MenuServiceImpl extends BaseServiceImpl<MenuMapper, MenuDO, MenuVO, MenuVO, MenuQuery, MenuRequest>
implements MenuService {
@Override
@Transactional(rollbackFor = Exception.class)
public Long create(MenuRequest request) {
String menuName = request.getMenuName();
boolean isExists = this.checkNameExists(menuName, request.getParentId(), request.getMenuId());
CheckUtils.throwIf(() -> isExists, String.format("新增失败,'%s'已存在", menuName));
// 保存信息
request.setStatus(DisEnableStatusEnum.ENABLE);
return super.create(request);
}
@Override
@Transactional(rollbackFor = Exception.class)
public void update(MenuRequest request) {
String menuName = request.getMenuName();
boolean isExists = this.checkNameExists(menuName, request.getParentId(), request.getMenuId());
CheckUtils.throwIf(() -> isExists, String.format("修改失败,'%s'已存在", menuName));
super.update(request);
}
@Override
@Transactional(rollbackFor = Exception.class)
public void delete(List<Long> ids) {
super.delete(ids);
super.lambdaUpdate().in(MenuDO::getParentId, ids).remove();
}
@Override
public List<MenuVO> buildListTree(List<MenuVO> list) {
if (CollUtil.isEmpty(list)) {
return new ArrayList<>();
}
// 去除重复子菜单列表
List<MenuVO> deDuplicationList = deDuplication(list);
return deDuplicationList.stream().map(m -> m.setChildren(this.getChildren(m, list)))
.collect(Collectors.toList());
}
/**
* 数据去重(去除重复子菜单列表)
*
* @param list
* 菜单列表
* @return 去重后菜单列表
*/
private List<MenuVO> deDuplication(List<MenuVO> list) {
List<MenuVO> deDuplicationList = new ArrayList<>();
for (MenuVO outer : list) {
boolean flag = true;
for (MenuVO inner : list) {
// 忽略重复子列表
if (inner.getMenuId().equals(outer.getParentId())) {
flag = false;
break;
}
}
if (flag) {
deDuplicationList.add(outer);
}
}
return deDuplicationList;
}
/**
* 获取指定菜单的子菜单列表
*
* @param menuVO
* 指定菜单
* @param list
* 菜单列表
* @return 子菜单列表
*/
private List<MenuVO> getChildren(MenuVO menuVO, List<MenuVO> list) {
return list.stream().filter(m -> Objects.equals(m.getParentId(), menuVO.getMenuId()))
.map(m -> m.setChildren(this.getChildren(m, list))).collect(Collectors.toList());
}
@Override
public List<Tree<Long>> buildTree(List<MenuVO> list) {
return TreeUtils.build(list, (m, tree) -> {
tree.setId(m.getMenuId());
tree.setName(m.getMenuName());
tree.setParentId(m.getParentId());
tree.setWeight(m.getMenuSort());
});
}
/**
* 检查名称是否存在
*
* @param name
* 名称
* @param parentId
* 上级 ID
* @param id
* ID
* @return 是否存在
*/
private boolean checkNameExists(String name, Long parentId, Long id) {
return super.lambdaQuery().eq(MenuDO::getMenuName, name).eq(MenuDO::getParentId, parentId)
.ne(id != null, MenuDO::getMenuId, id).exists();
}
}
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd" >
<mapper namespace="top.charles7c.cnadmin.system.mapper.MenuMapper">
</mapper>
\ No newline at end of file
import { createSvgIconsPlugin } from 'vite-plugin-svg-icons';
import path from 'path';
export default function createSvgIcon(isBuild: boolean) {
return createSvgIconsPlugin({
iconDirs: [path.resolve(process.cwd(), 'src/assets/icons/svg')],
symbolId: 'icon-[dir]-[name]',
svgoOptions: isBuild,
});
}
import { mergeConfig } from 'vite';
import eslint from 'vite-plugin-eslint';
import baseConfig from './vite.config.base';
import createSvgIcon from './plugin/svg-icon';
export default mergeConfig(
{
......@@ -17,6 +18,7 @@ export default mergeConfig(
include: ['src/**/*.ts', 'src/**/*.tsx', 'src/**/*.vue'],
exclude: ['node_modules'],
}),
createSvgIcon(false),
],
},
baseConfig
......
......@@ -5,6 +5,7 @@ import configVisualizerPlugin from './plugin/visualizer';
import configArcoResolverPlugin from './plugin/arcoResolver';
import configStyleImportPlugin from './plugin/styleImport';
import configImageminPlugin from './plugin/imagemin';
import createSvgIcon from './plugin/svg-icon';
export default mergeConfig(
{
......@@ -15,6 +16,7 @@ export default mergeConfig(
configArcoResolverPlugin(),
configStyleImportPlugin(),
configImageminPlugin(),
createSvgIcon(true),
],
build: {
rollupOptions: {
......
......@@ -91,6 +91,7 @@
"vite-plugin-eslint": "^1.8.1",
"vite-plugin-imagemin": "^0.6.1",
"vite-plugin-style-import": "1.4.1",
"vite-plugin-svg-icons": "^2.0.1",
"vite-svg-loader": "^3.6.0",
"vue-tsc": "^1.0.14"
},
......
import axios from 'axios';
import qs from 'query-string';
import { DeptParam } from '@/api/system/dept';
import { MenuParam } from '@/api/system/menu';
import { TreeNodeData } from '@arco-design/web-vue';
export default function listDeptTree(params: DeptParam) {
export function listDeptTree(params: DeptParam) {
return axios.get<TreeNodeData[]>('/common/tree/dept', {
params,
paramsSerializer: (obj) => {
......@@ -11,3 +12,12 @@ export default function listDeptTree(params: DeptParam) {
},
});
}
export function listMenuTree(params: MenuParam) {
return axios.get<TreeNodeData[]>('/common/tree/menu', {
params,
paramsSerializer: (obj) => {
return qs.stringify(obj);
},
});
}
import axios from 'axios';
import qs from 'query-string';
const BASE_URL = '/system/menu';
export interface MenuRecord {
menuId?: number;
menuName: string;
parentId?: number;
menuType: number;
path?: string;
name?: string;
component?: string;
icon?: string;
isExternal: boolean;
isCache: boolean;
isHidden: boolean;
permission?: string;
menuSort: number;
status?: number;
createUserString?: string;
createTime?: string;
updateUserString?: string;
updateTime?: string;
children?: Array<MenuRecord>;
parentName?: string;
}
export interface MenuParam {
menuName?: string;
status?: number;
}
export function listMenu(params: MenuParam) {
return axios.get<MenuRecord[]>(`${BASE_URL}/list`, {
params,
paramsSerializer: (obj) => {
return qs.stringify(obj);
},
});
}
export function getMenu(id: number) {
return axios.get<MenuRecord>(`${BASE_URL}/${id}`);
}
export function createMenu(req: MenuRecord) {
return axios.post(BASE_URL, req);
}
export function updateMenu(req: MenuRecord) {
return axios.put(BASE_URL, req);
}
export function deleteMenu(ids: number | Array<number>) {
return axios.delete(`${BASE_URL}/${ids}`);
}
<svg width="48" height="48" viewBox="0 0 48 48" fill="none"><path d="M44 9H4m38 20H6m28-10H14m20 20H14" stroke="#4E5969" stroke-width="4"/></svg>
\ No newline at end of file
<svg width="48" height="48" viewBox="0 0 48 48" fill="none"><path d="M44 9H4m36 20H4m21-10H4m21 20H4" stroke="#4E5969" stroke-width="4"/></svg>
\ No newline at end of file
<svg width="48" height="48" viewBox="0 0 48 48" fill="none"><path d="M4 9h40M8 29h36M23 19h21M23 39h21" stroke="#4E5969" stroke-width="4"/></svg>
\ No newline at end of file
<svg width="48" height="48" viewBox="0 0 48 48" fill="none"><path stroke="#4E5969" stroke-width="4" stroke-linecap="round" stroke-linejoin="round" d="M7 7h13v13H7zM28 7h13v13H28zM7 28h13v13H7zM28 28h13v13H28z"/></svg>
\ No newline at end of file
<svg width="48" height="48" viewBox="0 0 48 48" fill="none"><rect x="9" y="18" width="30" height="22" rx="1" stroke="#4E5969" stroke-width="4"/><path d="M6 9a1 1 0 011-1h34a1 1 0 011 1v8a1 1 0 01-1 1H7a1 1 0 01-1-1V9zM19 27h10" stroke="#4E5969" stroke-width="4"/></svg>
\ No newline at end of file
<svg width="48" height="48" viewBox="0 0 48 48" fill="none"><path d="M11.27 27.728l12.728 12.728 12.728-12.728M24 5v34.295" stroke="#4E5969" stroke-width="4"/></svg>
\ No newline at end of file
<svg width="48" height="48" viewBox="0 0 48 48" fill="none"><path d="M24.008 41.99a.01.01 0 01-.016 0l-9.978-11.974A.01.01 0 0114.02 30H33.98a.01.01 0 01.007.016l-9.978 11.975z" stroke="#4E5969" stroke-width="4"/><path d="M24 42L14 30h20L24 42z" fill="#4E5969"/><path stroke="#4E5969" stroke-width="4" d="M22 6h4v26h-4z"/><path fill="#4E5969" d="M22 6h4v26h-4z"/></svg>
\ No newline at end of file
<svg width="48" height="48" viewBox="0 0 48 48" fill="none"><path d="M20.272 11.27L7.544 23.998l12.728 12.728M43 24H8.705" stroke="#4E5969" stroke-width="4"/></svg>
\ No newline at end of file
<svg width="48" height="48" viewBox="0 0 48 48" fill="none"><path d="M27.728 11.27l12.728 12.728-12.728 12.728M5 24h34.295" stroke="#4E5969" stroke-width="4"/></svg>
\ No newline at end of file
<svg width="48" height="48" viewBox="0 0 48 48" fill="none"><path d="M23.992 6.01a.01.01 0 01.016 0l9.978 11.974a.01.01 0 01-.007.016H14.02a.01.01 0 01-.007-.016l9.978-11.975z" stroke="#4E5969" stroke-width="4"/><path d="M24 6l10 12H14L24 6z" fill="#4E5969"/><path stroke="#4E5969" stroke-width="4" d="M26 42h-4V16h4z"/><path fill="#4E5969" d="M26 42h-4V16h4z"/></svg>
\ No newline at end of file
<svg width="48" height="48" viewBox="0 0 48 48" fill="none"><path d="M11.27 20.272L23.998 7.544l12.728 12.728M24 43V8.705" stroke="#4E5969" stroke-width="4"/></svg>
\ No newline at end of file
<svg width="48" height="48" viewBox="0 0 48 48" fill="none"><path d="M31 23a7 7 0 11-14 0 7 7 0 0114 0zm0 0c0 3.038 2.462 6.5 5.5 6.5A5.5 5.5 0 0042 24c0-9.941-8.059-18-18-18S6 14.059 6 24s8.059 18 18 18c4.244 0 8.145-1.469 11.222-3.925" stroke="#4E5969" stroke-width="4"/></svg>
\ No newline at end of file
<svg width="48" height="48" viewBox="0 0 48 48" fill="none"><path d="M29.037 15.236s-9.174 9.267-11.48 11.594c-2.305 2.327-1.646 4.987-.329 6.316 1.317 1.33 3.994 1.953 6.258-.332L37.32 18.851c3.623-3.657 2.092-8.492 0-10.639-2.093-2.147-6.916-3.657-10.54 0L11.3 23.838c-3.623 3.657-3.953 10.638.329 14.96 4.282 4.322 11.115 4.105 14.821.333 3.706-3.773 8.74-8.822 11.224-11.33" stroke="#4E5969" stroke-width="4"/></svg>
\ No newline at end of file
<svg width="48" height="48" viewBox="0 0 48 48" fill="none"><path d="M38.293 36.293L26.707 24.707a1 1 0 010-1.414l11.586-11.586c.63-.63 1.707-.184 1.707.707v23.172c0 .89-1.077 1.337-1.707.707zM21 12.414v23.172c0 .89-1.077 1.337-1.707.707L7.707 24.707a1 1 0 010-1.414l11.586-11.586c.63-.63 1.707-.184 1.707.707z" stroke="#4E5969" stroke-width="4"/></svg>
\ No newline at end of file
<svg width="48" height="48" viewBox="0 0 48 48" fill="none"><path d="M19 5.25L22.75 9m0 0l12.043 12.043a1 1 0 010 1.414L32 25.25 21.221 36.029a1 1 0 01-1.428-.014L9.443 25.25l-.763-.793a1 1 0 01.013-1.4L22.75 9zM6 42h36" stroke="#4E5969" stroke-width="4"/><path d="M11.791 25.25c-.881 0-1.332 1.058-.72 1.693l8.722 9.072a1 1 0 001.428.014L32 25.25H11.791z" fill="#4E5969" stroke="#4E5969" stroke-width="4"/><path fill-rule="evenodd" clip-rule="evenodd" d="M40.013 29.812L37.201 27l-2.812 2.812a4 4 0 105.624 0z" fill="#4E5969"/></svg>
\ No newline at end of file
<svg width="48" height="48" viewBox="0 0 48 48" fill="none"><path d="M13 24h12a8 8 0 100-16H13.2a.2.2 0 00-.2.2V24zm0 0h16a8 8 0 110 16H13.2a.2.2 0 01-.2-.2V24z" stroke="#4E5969" stroke-width="4"/></svg>
\ No newline at end of file
<svg width="48" height="48" viewBox="0 0 48 48" fill="none"><path d="M24 13L7 7v28l17 6 17-6V7l-17 6zm0 0v27.5M19 18l-7-2.5M19 25l-7-2.5M19 32l-7-2.5M29 18l7-2.5M29 25l7-2.5M29 32l7-2.5" stroke="#4E5969" stroke-width="4" stroke-linejoin="round"/></svg>
\ No newline at end of file
<svg width="48" height="48" viewBox="0 0 48 48" fill="none"><path d="M19 10a4 4 0 11-8 0 4 4 0 018 0zM38 10a4 4 0 11-8 0 4 4 0 018 0zM19 38a4 4 0 11-8 0 4 4 0 018 0zM15 15v15m0 3.5V30m0 0c0-5 19-7 19-15" stroke="#4E5969" stroke-width="4"/></svg>
\ No newline at end of file
<svg width="48" height="48" viewBox="0 0 48 48" fill="none"><path d="M33 13h7a1 1 0 011 1v12.14a1 1 0 01-.85.99l-21.3 3.24a1 1 0 00-.85.99V43" stroke="#4E5969" stroke-width="4"/><path d="M7 18V8c0-.552.444-1 .997-1H32.01c.552 0 .99.447.99 1v10.002A.998.998 0 0132 19H8a1 1 0 01-1-1z" stroke="#4E5969" stroke-width="4"/></svg>
\ No newline at end of file
<svg width="48" height="48" viewBox="0 0 48 48" fill="none"><path d="M35 27h8M5 27h8m0-9h22v13c0 6.075-4.925 11-11 11s-11-4.925-11-11V18z" stroke="#4E5969" stroke-width="4" stroke-linejoin="round"/><path d="M7 42v-.5a6.5 6.5 0 016.5-6.5M7 42v-.5M41 42v-.5a6.5 6.5 0 00-6.5-6.5M13 18h22M7 14a4 4 0 004 4h26a4 4 0 004-4M24 42V23M17 14a7 7 0 1114 0" stroke="#4E5969" stroke-width="4" stroke-linejoin="round"/></svg>
\ No newline at end of file
<svg width="48" height="48" viewBox="0 0 48 48" fill="none"><path d="M30.8 32.465c.585-2.576 2.231-4.75 3.77-6.897A12.94 12.94 0 0037 18c0-7.18-5.82-13-13-13s-13 5.82-13 13c0 2.823.9 5.437 2.43 7.568 1.539 2.147 3.185 4.32 3.77 6.897l.623 2.756A1 1 0 0018.8 36H29.2a1 1 0 00.976-.779l.624-2.756zM17 42h14" stroke="#4E5969" stroke-width="4"/></svg>
\ No newline at end of file
<svg width="48" height="48" viewBox="0 0 48 48" fill="none"><path d="M7 22h34M8 41h32a1 1 0 001-1V10a1 1 0 00-1-1H8a1 1 0 00-1 1v30a1 1 0 001 1zM34 5v8M14 5v8" stroke="#4E5969" stroke-width="4"/></svg>
\ No newline at end of file
<svg width="48" height="48" viewBox="0 0 48 48" fill="none"><path d="M7 22h34V10a1 1 0 00-1-1H8a1 1 0 00-1 1v30a1 1 0 001 1h18M34 5v8M14 5v8" stroke="#4E5969" stroke-width="4"/><path fill-rule="evenodd" clip-rule="evenodd" d="M36 44a9 9 0 100-18 9 9 0 000 18zm1.5-9.75V29h-3v8.25H42v-3h-4.5z" fill="#4E5969"/></svg>
\ No newline at end of file
<svg width="48" height="48" viewBox="0 0 48 48" fill="none"><path d="M6 13a1 1 0 011-1h34a1 1 0 011 1v26a1 1 0 01-1 1H7a1 1 0 01-1-1V13z" stroke="#4E5969" stroke-width="4"/><path d="M31 26a7 7 0 11-14 0 7 7 0 0114 0zM33 12l-1.862-3.724A.5.5 0 0030.691 8H17.309a.5.5 0 00-.447.276L15 12" stroke="#4E5969" stroke-width="4"/></svg>
\ No newline at end of file
<svg width="48" height="48" viewBox="0 0 48 48" fill="none"><path d="M24.937 34.829a1.2 1.2 0 01-1.874 0L9.56 17.949C8.93 17.165 9.49 16 10.497 16h27.006c1.007 0 1.566 1.164.937 1.95L24.937 34.829z" fill="#4E5969"/></svg>
\ No newline at end of file
<svg width="48" height="48" viewBox="0 0 48 48" fill="none"><path d="M13.171 24.937a1.2 1.2 0 010-1.874L30.051 9.56c.785-.629 1.949-.07 1.949.937v27.006c0 1.007-1.164 1.566-1.95.937L13.171 24.937z" fill="#4E5969"/></svg>
\ No newline at end of file
<svg width="48" height="48" viewBox="0 0 48 48" fill="none"><path d="M34.829 23.063c.6.48.6 1.394 0 1.874L17.949 38.44c-.785.629-1.949.07-1.949-.937V10.497c0-1.006 1.164-1.566 1.95-.937l16.879 13.503z" fill="#4E5969"/></svg>
\ No newline at end of file
<svg width="48" height="48" viewBox="0 0 48 48" fill="none"><path d="M23.063 13.171a1.2 1.2 0 011.874 0l13.503 16.88c.629.785.07 1.949-.937 1.949H10.497c-1.006 0-1.566-1.164-.937-1.95l13.503-16.879z" fill="#4E5969"/></svg>
\ No newline at end of file
<svg width="48" height="48" viewBox="0 0 48 48" fill="none"><path d="M42 24c0 9.941-8.059 18-18 18S6 33.941 6 24 14.059 6 24 6s18 8.059 18 18z" fill="#4E5969" stroke="#4E5969" stroke-width="4"/><path d="M15 22l7 7 11.5-11.5" stroke="#fff" stroke-width="4"/></svg>
\ No newline at end of file
<svg width="48" height="48" viewBox="0 0 48 48" fill="none"><path d="M42 24c0 9.941-8.059 18-18 18S6 33.941 6 24 14.059 6 24 6s18 8.059 18 18z" stroke="#4E5969" stroke-width="4"/><path d="M15 22l7 7 11.5-11.5" stroke="#4E5969" stroke-width="4"/></svg>
\ No newline at end of file
<svg width="48" height="48" viewBox="0 0 48 48" fill="none"><path d="M7 8a1 1 0 011-1h32a1 1 0 011 1v32a1 1 0 01-1 1H8a1 1 0 01-1-1V8z" stroke="#4E5969" stroke-width="4"/><path d="M34.603 16.672L21.168 30.107l-7.778-7.779" stroke="#4E5969" stroke-width="4"/></svg>
\ No newline at end of file
<svg width="48" height="48" viewBox="0 0 48 48" fill="none"><path d="M41.678 11.05L19.05 33.678 6.322 20.95" stroke="#4E5969" stroke-width="4"/></svg>
\ No newline at end of file
<svg width="48" height="48" viewBox="0 0 48 48" fill="none"><path d="M22 21h-5v4.094h5V21zM26 25.094V21h5v4.094h-5z" fill="#4E5969"/><path fill-rule="evenodd" clip-rule="evenodd" d="M24 4C12.954 4 4 12.954 4 24s8.954 20 20 20 20-8.954 20-20S35.046 4 24 4zm2 13v-5h-4v5h-6.5a2.5 2.5 0 00-2.5 2.5v7.094a2.5 2.5 0 002.5 2.5H22V36h4v-6.906h6.5a2.5 2.5 0 002.5-2.5V19.5a2.5 2.5 0 00-2.5-2.5H26z" fill="#4E5969"/></svg>
\ No newline at end of file
<svg width="48" height="48" viewBox="0 0 48 48" fill="none"><path d="M42 24c0 9.941-8.059 18-18 18S6 33.941 6 24 14.059 6 24 6s18 8.059 18 18z" stroke="#4E5969" stroke-width="4"/><path d="M24 14v10h9.5" stroke="#4E5969" stroke-width="4"/></svg>
\ No newline at end of file
<svg width="48" height="48" viewBox="0 0 48 48" fill="none"><path d="M42 24c0 9.941-8.059 18-18 18S6 33.941 6 24 14.059 6 24 6s18 8.059 18 18z" fill="#4E5969" stroke="#4E5969" stroke-width="4"/><path d="M17.643 17.643l6.363 6.364m0 0l6.364 6.364m-6.364-6.364l6.364-6.364m-6.364 6.364l-6.363 6.364" stroke="#fff" stroke-width="4"/></svg>
\ No newline at end of file
<svg width="48" height="48" viewBox="0 0 48 48" fill="none"><path d="M42 24c0 9.941-8.059 18-18 18S6 33.941 6 24 14.059 6 24 6s18 8.059 18 18zM17.643 17.643l6.364 6.364 6.364 6.364" stroke="#4E5969" stroke-width="4"/><path d="M30.37 17.643l-6.363 6.364-6.364 6.364" stroke="#4E5969" stroke-width="4"/></svg>
\ No newline at end of file
<svg width="48" height="48" viewBox="0 0 48 48" fill="none"><path d="M38.142 9.858L24 24 9.858 38.142M9.858 9.858L24 24l14.142 14.142" stroke="#4E5969" stroke-width="4"/></svg>
\ No newline at end of file
<svg width="48" height="48" viewBox="0 0 48 48" fill="none"><path d="M43 22c0-7.732-6.492-14-14.5-14S14 14.268 14 22v.055A9.001 9.001 0 0015 40h13" stroke="#4E5969" stroke-width="4"/><path d="M44.142 34.071l-7.07 7.071L30 34.071M37.07 26v15" stroke="#4E5969" stroke-width="4"/></svg>
\ No newline at end of file
<svg width="48" height="48" viewBox="0 0 48 48" fill="none"><path d="M5 29a9 9 0 009 9h19c5.523 0 10-4.477 10-10 0-5.312-4.142-9.657-9.373-9.98C32.3 12.833 27.598 9 22 9c-6.606 0-11.965 5.338-12 11.935A9 9 0 005 29z" stroke="#4E5969" stroke-width="4"/></svg>
\ No newline at end of file
<svg width="48" height="48" viewBox="0 0 48 48" fill="none"><path d="M29 6h4a3 3 0 013 3v10c0 3 4.343 5 6 5-1.657 0-6 2-6 5v10a3 3 0 01-3 3h-4M19 6h-4a3 3 0 00-3 3v10c0 3-4.343 5-6 5 1.657 0 6 2 6 5v10a3 3 0 003 3h4" stroke="#4E5969" stroke-width="4"/></svg>
\ No newline at end of file
<svg width="48" height="48" viewBox="0 0 48 48" fill="none"><path d="M39 6H9a1 1 0 00-1 1v34a1 1 0 001 1h30a1 1 0 001-1V7a1 1 0 00-1-1z" stroke="#4E5969" stroke-width="4"/><path d="M8 7a1 1 0 011-1h30a1 1 0 011 1v34a1 1 0 01-1 1H9a1 1 0 01-1-1V7zM32.072 16.518l-4.14 15.454" stroke="#4E5969" stroke-width="4"/><path d="M23.071 17L16 24.071l7.071 7.071" stroke="#4E5969" stroke-width="4"/></svg>
\ No newline at end of file
<svg width="48" height="48" viewBox="0 0 48 48" fill="none"><path d="M27.2 6.28l-6.251 35.453M16.734 12.686L5.42 24l11.314 11.314M31.255 12.686L42.57 24 31.255 35.314" stroke="#4E5969" stroke-width="4"/></svg>
\ No newline at end of file
<svg width="48" height="48" viewBox="0 0 48 48" fill="none"><path d="M29 19v10H19V19h10zM13 29a6 6 0 106 6v-6h-6zM35 29a6 6 0 11-6 6v-6h6zM13 19a6 6 0 116-6v6h-6zM35 19a6 6 0 10-6-6v6h6z" stroke="#4E5969" stroke-width="4"/></svg>
\ No newline at end of file
<svg width="48" height="48" viewBox="0 0 48 48" fill="none"><path d="M24 23L7.652 14.345M24 23l16.366-8.664M24 23v19.438M7 14v20l17 9 17-9V14L24 5 7 14z" stroke="#4E5969" stroke-width="4"/></svg>
\ No newline at end of file
<svg width="48" height="48" viewBox="0 0 48 48" fill="none"><path d="M42 24c0 9.941-8.059 18-18 18S6 33.941 6 24 14.059 6 24 6s18 8.059 18 18z" stroke="#4E5969" stroke-width="4"/><path d="M21.177 21.183l10.108-4.717a.2.2 0 01.266.265L26.834 26.84l-10.109 4.717a.2.2 0 01-.266-.266l4.718-10.108z" stroke="#4E5969" stroke-width="4"/></svg>
\ No newline at end of file
<svg viewBox="0 0 48 48" fill="none" stroke="currentColor" xmlns="http://www.w3.org/2000/svg" class="arco-icon arco-icon-computer" style="font-size: 40px;" stroke-width="4" stroke-linecap="butt" stroke-linejoin="miter" filter="" data-v-249840b0=""><path d="M41 7H7v22h34V7Z"></path><path d="M23.778 29v10"></path><path d="M16 39h16"></path><path d="m20.243 14.657 5.657 5.657M15.414 22.314l7.071-7.071M24.485 21.728l7.071-7.071"></path></svg>
\ No newline at end of file
<svg width="48" height="48" viewBox="0 0 48 48" fill="none"><path d="M20 6h18a2 2 0 012 2v22" stroke="#4E5969" stroke-width="4"/><path d="M8 40V16a2 2 0 012-2h20c1.105 0 2 .892 2 1.997v24.011A1.99 1.99 0 0130.003 42H9.996A1.996 1.996 0 018 40z" stroke="#4E5969" stroke-width="4"/></svg>
\ No newline at end of file
<svg width="48" height="48" viewBox="0 0 48 48" fill="none"><path d="M42 24c0 9.941-8.059 18-18 18S6 33.941 6 24 14.059 6 24 6s18 8.059 18 18zM29.292 18a8 8 0 100 12" stroke="#4E5969" stroke-width="4"/></svg>
\ No newline at end of file
<svg width="48" height="48" viewBox="0 0 48 48" fill="none"><path d="M11 31V20c0-7.18 5.82-13 13-13s13 5.82 13 13v8c0 5.784-3.778 10.686-9 12.373" stroke="#4E5969" stroke-width="4"/><path d="M24 41c1.396 0 2.74-.22 4-.627V38a1 1 0 00-1-1h-6a1 1 0 00-1 1v2a1 1 0 001 1h3zM11 21H8a1 1 0 00-1 1v6a1 1 0 001 1h3M37 20v8m0-7h3a1 1 0 011 1v6a1 1 0 01-1 1h-3v-8z" stroke="#4E5969" stroke-width="4"/></svg>
\ No newline at end of file
<svg width="48" height="48" viewBox="0 0 48 48" fill="none"><path d="M36.597 37c3.725-3.667 5.33-8.37 5.211-13-.112-4.38-1.767-8.694-4.627-12C34.07 8.404 29.531 6 24 6c-5.724 0-10.384 2.574-13.5 6.38C6.99 16.662 5.44 22.508 6.53 28c.646 3.258 2.223 6.391 4.873 9M10.5 12.38L17 17.5M6.53 28l8.97-3.5M41.808 24H33.5M37.181 12L31 17.5M24 6v7.5" stroke="#4E5969" stroke-width="4"/><path d="M24 32a5 5 0 100 10 5 5 0 000-10zm0 0V19" stroke="#4E5969" stroke-width="4" stroke-linejoin="round"/></svg>
\ No newline at end of file
<svg width="48" height="48" viewBox="0 0 48 48" fill="none"><path d="M5 11h5.5m0 0v29a1 1 0 001 1h25a1 1 0 001-1V11m-27 0H16m21.5 0H43m-5.5 0H32m-16 0V7h16v4m-16 0h16M20 18v15m8-15v15" stroke="#4E5969" stroke-width="4"/></svg>
\ No newline at end of file
<svg width="48" height="48" viewBox="0 0 48 48" fill="none"><path d="M24 32v8m0 0h-9m9 0h9M7 32h34a1 1 0 001-1V9a1 1 0 00-1-1H7a1 1 0 00-1 1v22a1 1 0 001 1z" stroke="#4E5969" stroke-width="4"/></svg>
\ No newline at end of file
<svg width="48" height="48" viewBox="0 0 48 48" fill="none"><rect x="6.998" y="7" width="34" height="34" rx="1.5" stroke="#4E5969" stroke-width="4"/><circle cx="16" cy="16" r="2" stroke="#4E5969" stroke-width="4"/><circle cx="24" cy="24" r="2" stroke="#4E5969" stroke-width="4"/><circle cx="16" cy="32" r="2" stroke="#4E5969" stroke-width="4"/><circle cx="32" cy="16" r="2" stroke="#4E5969" stroke-width="4"/><circle cx="32" cy="32" r="2" stroke="#4E5969" stroke-width="4"/><circle cx="16" cy="16" r="2" fill="#4E5969"/><circle cx="24" cy="24" r="2" fill="#4E5969"/><circle cx="16" cy="32" r="2" fill="#4E5969"/><circle cx="32" cy="16" r="2" fill="#4E5969"/><circle cx="32" cy="32" r="2" fill="#4E5969"/></svg>
\ No newline at end of file
<svg width="48" height="48" viewBox="0 0 48 48" fill="none"><path d="M9.9 22.456l14.142 14.142 14.142-14.142" stroke="#4E5969" stroke-width="4"/><path d="M9.9 11.142l14.142 14.142 14.142-14.142" stroke="#4E5969" stroke-width="4"/></svg>
\ No newline at end of file
<svg width="48" height="48" viewBox="0 0 48 48" fill="none"><path d="M25.544 9.9L11.402 24.042l14.142 14.142" stroke="#4E5969" stroke-width="4"/><path d="M36.858 9.9L22.716 24.042l14.142 14.142" stroke="#4E5969" stroke-width="4"/></svg>
\ No newline at end of file
<svg width="48" height="48" viewBox="0 0 48 48" fill="none"><path d="M22.456 38.1l14.142-14.142L22.456 9.816" stroke="#4E5969" stroke-width="4"/><path d="M11.142 38.1l14.142-14.142L11.142 9.816" stroke="#4E5969" stroke-width="4"/></svg>
\ No newline at end of file
<svg width="48" height="48" viewBox="0 0 48 48" fill="none"><path d="M38.1 25.544L23.958 11.402 9.816 25.544" stroke="#4E5969" stroke-width="4"/><path d="M38.1 36.858L23.958 22.716 9.816 36.858" stroke="#4E5969" stroke-width="4"/></svg>
\ No newline at end of file
<svg width="48" height="48" viewBox="0 0 48 48" fill="none"><circle cx="24" cy="24" r="18" transform="rotate(-180 24 24)" stroke="#4E5969" stroke-width="4"/><path d="M32.484 20.515L24 29l-8.485-8.485" stroke="#4E5969" stroke-width="4"/></svg>
\ No newline at end of file
<svg width="48" height="48" viewBox="0 0 48 48" fill="none"><path d="M39.6 17.444L24.044 33 8.487 17.444" stroke="#4E5969" stroke-width="4"/></svg>
\ No newline at end of file
<svg width="48" height="48" viewBox="0 0 48 48" fill="none"><path d="M33.072 22.071l-9.07 9.071-9.072-9.071M40 35v6H8v-6M24 5v26" stroke="#4E5969" stroke-width="4"/></svg>
\ No newline at end of file
<svg width="48" height="48" viewBox="0 0 48 48" fill="none"><path d="M7 24h34M24 7v34M30 12l-6-6-6 6M36 30l6-6-6-6M12 30l-6-6 6-6M18 36l6 6 6-6" stroke="#4E5969" stroke-width="4"/></svg>
\ No newline at end of file
<svg width="48" height="48" viewBox="0 0 48 48" fill="none"><path d="M17 8h2v2h-2V8zM17 23h2v2h-2v-2zM17 38h2v2h-2v-2zM29 8h2v2h-2V8zM29 23h2v2h-2v-2zM29 38h2v2h-2v-2z" fill="#4E5969"/><path d="M17 8h2v2h-2V8zM17 23h2v2h-2v-2zM17 38h2v2h-2v-2zM29 8h2v2h-2V8zM29 23h2v2h-2v-2zM29 38h2v2h-2v-2z" stroke="#4E5969" stroke-width="4"/></svg>
\ No newline at end of file
<svg width="48" height="48" viewBox="0 0 48 48" fill="none"><path d="M40 17v2h-2v-2h2zM25 17v2h-2v-2h2zM10 17v2H8v-2h2zM40 29v2h-2v-2h2zM25 29v2h-2v-2h2zM10 29v2H8v-2h2z" fill="#4E5969"/><path d="M40 17v2h-2v-2h2zM25 17v2h-2v-2h2zM10 17v2H8v-2h2zM40 29v2h-2v-2h2zM25 29v2h-2v-2h2zM10 29v2H8v-2h2z" stroke="#4E5969" stroke-width="4"/></svg>
\ No newline at end of file
<svg width="48" height="48" viewBox="0 0 48 48" fill="none"><path d="M10 42h28a1 1 0 001-1V17L28 6H10a1 1 0 00-1 1v34a1 1 0 001 1z" stroke="#4E5969" stroke-width="4"/><path d="M38.5 17H29a1 1 0 01-1-1V6.5" stroke="#4E5969" stroke-width="4"/></svg>
\ No newline at end of file
<svg width="48" height="48" viewBox="0 0 48 48" fill="none"><path d="M13 15.528C14.32 12.386 18.403 6.977 23.556 7c7.944.036 14.514 8.528 10.116 15.71-4.399 7.181-5.718 10.323-6.598 14.363-.82 3.766-9.288 7.143-11.498-1.515" stroke="#4E5969" stroke-width="4"/><path d="M20 18.5c1-3.083 4.5-4.5 6.5-2 2.85 3.562-3.503 8.312-5.5 12.5" stroke="#4E5969" stroke-width="4"/></svg>
\ No newline at end of file
<svg width="48" height="48" viewBox="0 0 48 48" fill="none"><path d="M30.479 19.038l5.734-5.734a1 1 0 000-1.414l-5.586-5.586a1 1 0 00-1.414 0l-5.734 5.734m7 7L15.763 33.754a1 1 0 01-.591.286l-6.047.708a1 1 0 01-1.113-1.069l.477-6.31a1 1 0 01.29-.631l14.7-14.7m7 7l-7-7M5.999 42h36" stroke="#4E5969" stroke-width="4"/></svg>
\ No newline at end of file
<svg width="48" height="48" viewBox="0 0 48 48" fill="none"><rect x="6" y="8" width="36" height="32" rx="1" stroke="#4E5969" stroke-width="4"/><path d="M37 17l-12.43 8.606a1 1 0 01-1.14 0L11 17" stroke="#4E5969" stroke-width="4"/></svg>
\ No newline at end of file
<svg width="48" height="48" viewBox="0 0 48 48" fill="none"><path d="M24 5v6m7 1l4-4m-18 4l-4-4m27 33H8a2 2 0 01-2-2v-8.46a2 2 0 01.272-1.007l6.15-10.54A2 2 0 0114.148 18H33.85a2 2 0 011.728.992l6.149 10.541A2 2 0 0142 30.541V39a2 2 0 01-2 2z" stroke="#4E5969" stroke-width="4"/><path d="M41.5 30H28s-1 3-4 3-4-3-4-3H6.5" stroke="#4E5969" stroke-width="4"/></svg>
\ No newline at end of file
<svg width="48" height="48" viewBox="0 0 48 48" fill="none"><path fill-rule="evenodd" clip-rule="evenodd" d="M23.2 4C12.596 4 4 12.596 4 23.2v1.6C4 35.404 12.596 44 23.2 44h1.6C35.404 44 44 35.404 44 24.8v-1.6C44 12.596 35.404 4 24.8 4h-1.6zm-9.086 10A2.114 2.114 0 0012 16.114v15.772c0 1.167.947 2.114 2.114 2.114H25v-4h-9v-4h7.778v-4H16v-4h9v-4H14.114zM32.4 22a5.4 5.4 0 00-5.4 5.4V34h4v-6.6a1.4 1.4 0 012.801 0V34h4v-6.6a5.4 5.4 0 00-5.4-5.4z" fill="#4E5969"/></svg>
\ No newline at end of file
<svg width="48" height="48" viewBox="0 0 48 48" fill="none"><path d="M25.5 40.503L14.914 40.5a1 1 0 01-.707-.293l-9-9a1 1 0 010-1.414L13.5 21.5 26.793 8.207a1 1 0 011.414 0l14.086 14.086a1 1 0 010 1.414L29 37l-3.5 3.503zm0 0L44 40.5M13.5 21.5L29 37" stroke="#4E5969" stroke-width="4"/></svg>
\ No newline at end of file
<svg width="48" height="48" viewBox="0 0 48 48" fill="none"><path d="M42 24c0 9.941-8.059 18-18 18S6 33.941 6 24 14.059 6 24 6s18 8.059 18 18z" fill="#4E5969" stroke="#4E5969" stroke-width="4"/><path d="M24 28V14M24 30v4" stroke="#fff" stroke-width="4"/></svg>
\ No newline at end of file
<svg width="48" height="48" viewBox="0 0 48 48" fill="none"><path d="M6 24c0-9.941 8.059-18 18-18s18 8.059 18 18-8.059 18-18 18S6 33.941 6 24zM24 28V14M24 30v4" stroke="#4E5969" stroke-width="4"/></svg>
\ No newline at end of file
<svg width="48" height="48" viewBox="0 0 48 48" fill="none"><path d="M16 6h16l10 11v14L32 42H16L6 31V17L16 6z" fill="#4E5969" stroke="#4E5969" stroke-width="4"/><path d="M24 28V14m0 16v4" stroke="#fff" stroke-width="4"/></svg>
\ No newline at end of file
<svg width="48" height="48" viewBox="0 0 48 48" fill="none"><path stroke="#4E5969" stroke-width="4" d="M23 9h2v21h-2z"/><path fill="#4E5969" d="M23 9h2v21h-2z"/><path stroke="#4E5969" stroke-width="4" d="M23 37h2v2h-2z"/><path fill="#4E5969" d="M23 37h2v2h-2z"/></svg>
\ No newline at end of file
<svg width="48" height="48" viewBox="0 0 48 48" fill="none"><path d="M41 22V8c0-.552-.444-1-.996-1H26M7 26v14c0 .552.444 1 .996 1H22" stroke="#4E5969" stroke-width="4"/></svg>
\ No newline at end of file
<svg width="48" height="48" viewBox="0 0 48 48" fill="none"><path d="M10.5 7h6m0 0v10.5l-5.25 14-2.344 6.853A2 2 0 0010.798 41h26.758a2 2 0 001.86-2.737L37 32.167 31.5 17.5V7m-15 0h15m0 0h6M26 22.5v.01" stroke="#4E5969" stroke-width="4"/><path d="M11.25 31.5c1.917 1.833 7.05 4.4 12.25 0s11.167-1.389 13.5.667" stroke="#4E5969" stroke-width="4"/></svg>
\ No newline at end of file
<svg width="48" height="48" viewBox="0 0 48 48" fill="none"><path d="M31 41H7V7h24M32.071 33.142l9.071-9.07L32.071 15M17 24.07h24" stroke="#4E5969" stroke-width="4"/></svg>
\ No newline at end of file
<svg width="48" height="48" viewBox="0 0 48 48" fill="none"><path d="M14 14.5c-2.69 2-5.415 5.33-8 9.5 5.373 8.667 11.373 13 18 13 3.325 0 6.491-1.09 9.5-3.271M17.463 12.5C19 11 21.75 11 24 11c6.627 0 12.627 4.333 18 13-1.766 2.848-3.599 5.228-5.5 7.14" stroke="#4E5969" stroke-width="4"/><path d="M29 24a5 5 0 11-10 0 5 5 0 0110 0zM6.853 7.103l34.294 34.294" stroke="#4E5969" stroke-width="4"/></svg>
\ No newline at end of file
<svg width="48" height="48" viewBox="0 0 48 48" fill="none"><path clip-rule="evenodd" d="M24 37c6.627 0 12.627-4.333 18-13-5.373-8.667-11.373-13-18-13-6.627 0-12.627 4.333-18 13 5.373 8.667 11.373 13 18 13z" stroke="#4E5969" stroke-width="4"/><path d="M29 24a5 5 0 11-10 0 5 5 0 0110 0z" stroke="#4E5969" stroke-width="4"/></svg>
\ No newline at end of file
<svg width="48" height="48" viewBox="0 0 48 48" fill="none"><circle cx="24" cy="24" r="20" fill="#4E5969"/><path d="M18 17v6M30 17v6M16.582 34a8 8 0 0114.837 0" stroke="#fff" stroke-width="4"/></svg>
\ No newline at end of file
<svg width="48" height="48" viewBox="0 0 48 48" fill="none"><circle cx="24" cy="24" r="20" fill="#4E5969"/><path d="M18 17v6M32 32H16M30 17v6" stroke="#fff" stroke-width="4"/></svg>
\ No newline at end of file
<svg width="48" height="48" viewBox="0 0 48 48" fill="none"><circle cx="24" cy="24" r="20" fill="#4E5969"/><path d="M18 17v6M30 17v6M16.582 28.105a8 8 0 0014.837 0" stroke="#fff" stroke-width="4"/></svg>
\ No newline at end of file
<svg width="48" height="48" viewBox="0 0 48 48" fill="none"><path d="M37 42H11a2 2 0 01-2-2V8a2 2 0 012-2h21l7 7v27a2 2 0 01-2 2z" stroke="#4E5969" stroke-width="4"/><path d="M25 30a3 3 0 11-6 0 3 3 0 016 0z" fill="#4E5969"/><path d="M25 30a3 3 0 11-6 0 3 3 0 016 0zm0 0l-.951-12.363a.5.5 0 01.58-.532L30 18" stroke="#4E5969" stroke-width="4"/></svg>
\ No newline at end of file
<svg width="48" height="48" viewBox="0 0 48 48" fill="none"><path d="M26 33l5-6v6h-5zm0 0l-3-4-4 4h7zm11 9H11a2 2 0 01-2-2V8a2 2 0 012-2h21l7 7v27a2 2 0 01-2 2zM17 19h1v1h-1v-1z" stroke="#4E5969" stroke-width="4"/></svg>
\ No newline at end of file
<svg width="48" height="48" viewBox="0 0 48 48" fill="none"><path d="M11 42h26a2 2 0 002-2V13.828a2 2 0 00-.586-1.414l-5.828-5.828A2 2 0 0031.172 6H11a2 2 0 00-2 2v32a2 2 0 002 2z" stroke="#4E5969" stroke-width="4"/><path d="M22.305 21.028c.874 1.939 3.506 6.265 4.903 8.055 1.747 2.237 3.494 2.685 4.368 2.237.873-.447 1.21-4.548-7.425-2.685-7.523 1.623-7.424 3.58-6.988 4.476.728 1.193 2.522 2.627 5.678-6.266C25.699 18.79 24.489 17 23.277 17c-1.409 0-2.538.805-.972 4.028z" stroke="#4E5969" stroke-width="4"/></svg>
\ No newline at end of file
<svg width="48" height="48" viewBox="0 0 48 48" fill="none"><path d="M37 42H11a2 2 0 01-2-2V8a2 2 0 012-2h21l7 7v27a2 2 0 01-2 2z" stroke="#4E5969" stroke-width="4"/><path d="M22 27.796v-6l5 3-5 3z" stroke="#4E5969" stroke-width="4"/></svg>
\ No newline at end of file
<svg width="48" height="48" viewBox="0 0 48 48" fill="none"><path d="M16 21h16m-16 8h10m11 13H11a2 2 0 01-2-2V8a2 2 0 012-2h21l7 7v27a2 2 0 01-2 2z" stroke="#4E5969" stroke-width="4"/></svg>
\ No newline at end of file
<svg width="48" height="48" viewBox="0 0 48 48" fill="none"><path d="M30 42V22.549a1 1 0 01.463-.844l10.074-6.41A1 1 0 0041 14.45V8a1 1 0 00-1-1H8a1 1 0 00-1 1v6.451a1 1 0 00.463.844l10.074 6.41a1 1 0 01.463.844V37" stroke="#4E5969" stroke-width="4"/></svg>
\ No newline at end of file
<svg width="48" height="48" viewBox="0 0 48 48" fill="none"><path d="M42.354 40.854L36.01 34.51m0 0a9 9 0 01-15.364-6.364c0-5 4-9 9-9s9 4 9 9a8.972 8.972 0 01-2.636 6.364zm5.636-26.365h-36m10 16h-10m10 16h-10" stroke="#4E5969" stroke-width="4"/></svg>
\ No newline at end of file
<svg width="48" height="48" viewBox="0 0 48 48" fill="none"><path d="M17.577 27.477C20.022 22.579 17.041 12.98 24.546 6c0 0-1.156 15.55 5.36 17.181 2.145.537 2.68-5.369 4.289-8.59 0 0 .536 4.832 2.68 8.59 3.217 7.517-1 14.117-5.896 17.182-4.289 2.684-14.587 2.807-19.835-5.37-4.824-7.516 0-15.57 0-15.57s4.289 12.35 6.433 8.054z" stroke="#4E5969" stroke-width="4"/></svg>
\ No newline at end of file
<svg width="48" height="48" viewBox="0 0 48 48" fill="none"><path d="M43 40H5M43 28H5M43 19L24 7 5 19" stroke="#4E5969" stroke-width="4"/></svg>
\ No newline at end of file
<svg width="48" height="48" viewBox="0 0 48 48" fill="none"><path d="M24 19v14m-7-7h14M6 13h18l-2.527-3.557a1.077 1.077 0 00-.88-.443H7.06C6.474 9 6 9.448 6 10v3zm0 0h33.882c1.17 0 2.118.895 2.118 2v21c0 1.105-.948 3-2.118 3H8.118C6.948 39 6 38.105 6 37V13z" stroke="#4E5969" stroke-width="4"/></svg>
\ No newline at end of file
<svg width="48" height="48" viewBox="0 0 48 48" fill="none"><path d="M17 26h14M6 13h18l-2.527-3.557a1.077 1.077 0 00-.88-.443H7.06C6.474 9 6 9.448 6 10v3zm0 0h33.882c1.17 0 2.118.895 2.118 2v21c0 1.105-.948 3-2.118 3H8.118C6.948 39 6 38.105 6 37V13z" stroke="#4E5969" stroke-width="4"/></svg>
\ No newline at end of file
<svg width="48" height="48" viewBox="0 0 48 48" fill="none"><path d="M6 13h18l-2.527-3.557a1.077 1.077 0 00-.88-.443H7.06C6.474 9 6 9.448 6 10v3zm0 0h33.882c1.17 0 2.118.895 2.118 2v21c0 1.105-.948 3-2.118 3H8.118C6.948 39 6 38.105 6 37V13z" stroke="#4E5969" stroke-width="4"/></svg>
\ No newline at end of file
<svg width="48" height="48" viewBox="0 0 48 48" fill="none"><path d="M9 41h30M16.467 22L11.5 34m20.032-12L24.998 7h-2l-6.532 15h15.065zm0 0H16.467h15.065zm0 0L36.5 34l-4.968-12z" stroke="#4E5969" stroke-width="4"/></svg>
\ No newline at end of file
<svg width="48" height="48" viewBox="0 0 48 48" fill="none"><path d="M40 8H10a1 1 0 00-1 1v.546a1 1 0 00.341.753L24.17 23.273a1 1 0 01.026 1.482l-.195.183L9.343 37.7a1 1 0 00-.343.754V39a1 1 0 001 1h30" stroke="#4E5969" stroke-width="4"/></svg>
\ No newline at end of file
<svg width="48" height="48" viewBox="0 0 48 48" fill="none"><path d="M9.707 11.707l11.586 11.586a1 1 0 010 1.414L9.707 36.293c-.63.63-1.707.184-1.707-.707V12.414c0-.89 1.077-1.337 1.707-.707zM27 35.586V12.414c0-.89 1.077-1.337 1.707-.707l11.586 11.586a1 1 0 010 1.414L28.707 36.293c-.63.63-1.707.184-1.707-.707z" stroke="#4E5969" stroke-width="4"/></svg>
\ No newline at end of file
<svg width="48" height="48" viewBox="0 0 48 48" fill="none"><path d="M13 42v-8a1 1 0 00-1-1H4M13 6v8a1 1 0 01-1 1H4M35 6v8a1 1 0 001 1h8M35 42v-8a1 1 0 011-1h8" stroke="#4E5969" stroke-width="4"/></svg>
\ No newline at end of file
<svg width="48" height="48" viewBox="0 0 48 48" fill="none"><path d="M6 31v8a1 1 0 001 1h8M6 17V9a1 1 0 011-1h8M42 17V9a1 1 0 00-1-1h-8M42 31v8a1 1 0 01-1 1h-8" stroke="#4E5969" stroke-width="4"/></svg>
\ No newline at end of file
<svg width="48" height="48" viewBox="0 0 48 48" fill="none"><path d="M23 8h2v2h-2V8zM23 23h2v2h-2v-2zM23 38h2v2h-2v-2z" fill="#4E5969"/><path d="M23 8h2v2h-2V8zM23 23h2v2h-2v-2zM23 38h2v2h-2v-2z" stroke="#4E5969" stroke-width="4"/><path d="M37 8h2v2h-2V8zM37 23h2v2h-2v-2zM37 38h2v2h-2v-2z" fill="#4E5969"/><path d="M37 8h2v2h-2V8zM37 23h2v2h-2v-2zM37 38h2v2h-2v-2z" stroke="#4E5969" stroke-width="4"/><path d="M9 8h2v2H9V8zM9 23h2v2H9v-2zM9 38h2v2H9v-2z" fill="#4E5969"/><path d="M9 8h2v2H9V8zM9 23h2v2H9v-2zM9 38h2v2H9v-2z" stroke="#4E5969" stroke-width="4"/></svg>
\ No newline at end of file
<svg width="48" height="48" viewBox="0 0 48 48" fill="none"><path d="M13.45 14.043H8a1 1 0 00-1 1v8a1 1 0 001 1h32a1 1 0 001-1v-8a1 1 0 00-1-1h-4.893m-21.657 0c-1.036-2.833-.615-5.6 1.182-6.637 2.152-1.243 5.464.464 7.397 3.812.539.933.914 1.896 1.127 2.825m-9.706 0h9.706m0 0H25.4m0 0a10.31 10.31 0 011.128-2.825c1.933-3.348 5.244-5.055 7.397-3.812 1.797 1.037 2.217 3.804 1.182 6.637m-9.707 0h9.707M10 26.043a2 2 0 012-2h24a2 2 0 012 2v13a2 2 0 01-2 2H12a2 2 0 01-2-2v-13z" stroke="#4E5969" stroke-width="4"/></svg>
\ No newline at end of file
<svg viewBox="0 0 48 48" fill="none" xmlns="http://www.w3.org/2000/svg" stroke="currentColor" class="arco-icon arco-icon-github" style="font-size: 40px;" stroke-width="4" stroke-linecap="butt" stroke-linejoin="miter" filter="" data-v-249840b0=""><path d="M.056 24.618c0 10.454 6.7 19.344 16.038 22.608 1.259.32 1.067-.582 1.067-1.19v-4.148c-7.265.853-7.553-3.957-8.043-4.758-.987-1.686-3.312-2.112-2.62-2.912 1.654-.853 3.34.213 5.291 3.1 1.413 2.09 4.166 1.738 5.562 1.385a6.777 6.777 0 0 1 1.856-3.253C11.687 34.112 8.55 29.519 8.55 24.057c0-2.646.874-5.082 2.586-7.045-1.088-3.243.102-6.01.26-6.422 3.11-.282 6.337 2.225 6.587 2.421 1.766-.474 3.782-.73 6.038-.73 2.266 0 4.293.26 6.069.74.603-.458 3.6-2.608 6.49-2.345.155.41 1.317 3.12.294 6.315 1.734 1.968 2.62 4.422 2.62 7.077 0 5.472-3.158 10.07-10.699 11.397a6.82 6.82 0 0 1 2.037 4.875v6.02c.042.48 0 .96.806.96 9.477-3.194 16.299-12.15 16.299-22.697C47.938 11.396 37.218.68 23.996.68 10.77.675.055 11.391.055 24.617l.001.001Z" fill="currentColor" stroke="none"></path></svg>
\ No newline at end of file
<svg width="48" height="48" viewBox="0 0 48 48" fill="none"><path d="M6 6v18m0 0v18m0-18h20m0 0V6m0 18v18M40 42V21h-1l-6 3" stroke="#4E5969" stroke-width="4"/></svg>
\ No newline at end of file
<svg width="48" height="48" viewBox="0 0 48 48" fill="none"><path d="M6 6v18m0 0v18m0-18h20m0 0V6m0 18v18M44 40H32v-.5l7.5-9c.914-1.117 2.5-3 2.5-5 0-2.485-2.239-4.5-5-4.5s-5 2.515-5 5M44 40H32" stroke="#4E5969" stroke-width="4"/></svg>
\ No newline at end of file
<svg width="48" height="48" viewBox="0 0 48 48" fill="none"><path d="M6 6v18m0 0v18m0-18h20m0 0V6m0 18v18M37 30a5 5 0 010 10h-.555a4.444 4.444 0 01-4.444-4.444M35 30h2a5 5 0 000-10h-.555a4.444 4.444 0 00-4.444 4.444" stroke="#4E5969" stroke-width="4"/></svg>
\ No newline at end of file
<svg width="48" height="48" viewBox="0 0 48 48" fill="none"><path d="M6 6v18m0 0v18m0-18h20m0 0V6m0 18v18m14.5-6H31v-1l8-15h1.5v16zm0 0H44m-3.5 0v6" stroke="#4E5969" stroke-width="4"/></svg>
\ No newline at end of file
<svg width="48" height="48" viewBox="0 0 48 48" fill="none"><path d="M6 6v18m0 0v18m0-18h20m0 0V6m0 18v18M43 21H32.5v9h.5s1.5-1 4-1a5 5 0 015 5v1a5 5 0 01-5 5c-2.05 0-4.728-1.234-5.5-3" stroke="#4E5969" stroke-width="4"/></svg>
\ No newline at end of file
<svg width="48" height="48" viewBox="0 0 48 48" fill="none"><path d="M6 6v18m0 0v18m0-18h20m0 0V6m0 18v18M32 34.5c0 3.038 2.239 5.5 5 5.5s5-2.462 5-5.5-2.239-5.5-5-5.5-5 2.462-5 5.5zm0 0v-5.73c0-4.444 3.867-7.677 8-7.263.437.044.736.08.952.115" stroke="#4E5969" stroke-width="4"/></svg>
\ No newline at end of file
<svg width="48" height="48" viewBox="0 0 48 48" fill="none"><path d="M6 6v18m0 0v18m0-18h20m0 0V6m0 18v18m4-21h12v1l-4.4 16-1.1 3.5" stroke="#4E5969" stroke-width="4"/></svg>
\ No newline at end of file
<svg width="48" height="48" viewBox="0 0 48 48" fill="none"><path d="M23.64 10.888l.36.375.36-.375c4.171-4.335 10.898-4.593 15.035-.293 4.142 4.305 4.007 10.878.388 16.52-1.999 3.115-5.02 6.612-8.039 9.39-1.508 1.388-3.006 2.588-4.366 3.469-1.341.868-2.5 1.394-3.378 1.522-.878-.128-2.037-.654-3.378-1.522-1.36-.88-2.858-2.08-4.366-3.469-3.018-2.778-6.04-6.275-8.04-9.39-3.618-5.642-3.753-12.215.389-16.52 4.137-4.3 10.863-4.042 15.034.293z" fill="#4E5969" stroke="#4E5969"/></svg>
\ No newline at end of file
<svg width="48" height="48" viewBox="0 0 48 48" fill="none"><path d="M38.083 12.912a9.929 9.929 0 01.177 13.878l-.177.18L25.76 39.273c-.972.97-2.548.97-3.52 0L9.917 26.971l-.177-.181a9.929 9.929 0 01.177-13.878c3.889-3.883 10.194-3.883 14.083 0 3.889-3.883 10.194-3.883 14.083 0z" stroke="#4E5969" stroke-width="4"/></svg>
\ No newline at end of file
<svg width="48" height="48" viewBox="0 0 48 48" fill="none"><path d="M39 43V28a1 1 0 00-1-1h-4v-8a1 1 0 00-1-1H15a1 1 0 00-1 1v8h-4a1 1 0 00-1 1v15M19 9.28V17a1 1 0 001 1h8a1 1 0 001-1V7.28a1 1 0 00-1.242-.97l-8 2a1 1 0 00-.758.97z" stroke="#4E5969" stroke-width="4"/></svg>
\ No newline at end of file
<svg width="48" height="48" viewBox="0 0 48 48" fill="none"><path d="M9 33.953C12.225 38.803 17.74 42 24 42c9.941 0 18-8.059 18-18S33.941 6 24 6C14.313 6 6.413 13.653 6.016 23.243c-.01.25-.016.503-.016.757" stroke="#4E5969" stroke-width="4"/><path d="M32 26h-9v-9M5.5 23.243L6 24l.5-.757h-1z" stroke="#4E5969" stroke-width="4"/></svg>
\ No newline at end of file
<svg width="48" height="48" viewBox="0 0 48 48" fill="none"><path d="M7 17L24 7l17 10v24H7V17z" stroke="#4E5969" stroke-width="4"/><path d="M20 28h8v13h-8V28z" stroke="#4E5969" stroke-width="4"/></svg>
\ No newline at end of file
<svg width="48" height="48" viewBox="0 0 48 48" fill="none"><path d="M11 17h9m-9 7h9m-9 7h5m-8 9h32a2 2 0 002-2V10a2 2 0 00-2-2H8a2 2 0 00-2 2v28a2 2 0 002 2zM36 33a7 7 0 10-14 0" stroke="#4E5969" stroke-width="4"/><circle cx="29" cy="20" r="4" stroke="#4E5969" stroke-width="4"/></svg>
\ No newline at end of file
<svg width="48" height="48" viewBox="0 0 48 48" fill="none"><path d="M41 26V9a2 2 0 00-2-2H9a2 2 0 00-2 2v30a2 2 0 002 2h17" stroke="#4E5969" stroke-width="4" stroke-linecap="square"/><path d="M24 33l9-8.5V27s-2 1-3.5 2.5C27.841 31.159 27 33 27 33h-3zm0 0l-3.5-4.5L17 33h7z" stroke="#4E5969" stroke-width="4" stroke-linecap="square"/><path d="M20.5 28.5L17 33h7l-3.5-4.5zM33 24.5L24 33h3s.841-1.841 2.5-3.5C31 28 33 27 33 27v-2.5zM46 38a8 8 0 11-16 0 8 8 0 0116 0z" fill="#4E5969"/><path d="M41.92 34.088l-3.916 3.916-3.916 3.916M34.088 34.088l3.916 3.916 3.916 3.916" stroke="#fff" stroke-width="2.462"/><path d="M17 15h-2v2h2v-2z" stroke="#4E5969" stroke-width="4" stroke-linecap="square"/></svg>
\ No newline at end of file
<svg width="48" height="48" viewBox="0 0 48 48" fill="none"><path d="M24 33l9-9v9h-9zm0 0l-3.5-4.5L17 33h7zm15 8H9a2 2 0 01-2-2V9a2 2 0 012-2h30a2 2 0 012 2v30a2 2 0 01-2 2zM15 15h2v2h-2v-2z" stroke="#4E5969" stroke-width="4"/><path d="M33 33v-9l-9 9h9zM23.5 33l-3-4-3 4h6zM15 15h2v2h-2z" fill="#4E5969"/></svg>
\ No newline at end of file
<svg width="48" height="48" viewBox="0 0 48 48" fill="none"><path d="M31 41H7V7h24M43 24H19" stroke="#4E5969" stroke-width="4"/><path d="M27.929 33.072l-9.071-9.071 9.07-9.071" stroke="#4E5969" stroke-width="4"/></svg>
\ No newline at end of file
<svg width="48" height="48" viewBox="0 0 48 48" fill="none"><path d="M42 24c0 9.941-8.059 18-18 18S6 33.941 6 24 14.059 6 24 6s18 8.059 18 18z" fill="#4E5969" stroke="#4E5969" stroke-width="4"/><path d="M24 20v14m0-16v-4" stroke="#fff" stroke-width="4"/></svg>
\ No newline at end of file
<svg width="48" height="48" viewBox="0 0 48 48" fill="none"><path d="M42 24c0 9.941-8.059 18-18 18S6 33.941 6 24 14.059 6 24 6s18 8.059 18 18zM24 20v14M24 18v-4" stroke="#4E5969" stroke-width="4"/></svg>
\ No newline at end of file
<svg width="48" height="48" viewBox="0 0 48 48" fill="none"><path stroke="#4E5969" stroke-width="4" d="M25 39h-2V18h2z"/><path fill="#4E5969" d="M25 39h-2V18h2z"/><path stroke="#4E5969" stroke-width="4" d="M25 11h-2V9h2z"/><path fill="#4E5969" d="M25 11h-2V9h2z"/></svg>
\ No newline at end of file
<svg width="48" height="48" viewBox="0 0 48 48" fill="none"><path d="M8 19h16m16 0H24m0 0v23m14 0H10a2 2 0 01-2-2V8a2 2 0 012-2h28a2 2 0 012 2v32a2 2 0 01-2 2z" stroke="#4E5969" stroke-width="4"/></svg>
\ No newline at end of file
<svg width="48" height="48" viewBox="0 0 48 48" fill="none"><path d="M18 8h9m8 0h-8m0 0l-6 32m0 0h-8m8 0h9" stroke="#4E5969" stroke-width="4"/></svg>
\ No newline at end of file
<svg width="48" height="48" viewBox="0 0 48 48" fill="none"><path d="M42 43l-2.385-6M26 43l2.384-6m11.231 0l-.795-2-4.18-10h-1.28l-4.181 10-.795 2m11.231 0h-11.23M17 5l1 5M5 11h26M11 11s1.889 7.826 6.611 12.174C22.333 27.522 30 31 30 31" stroke="#4E5969" stroke-width="4"/><path d="M25 11s-1.889 7.826-6.611 12.174C13.667 27.522 6 31 6 31" stroke="#4E5969" stroke-width="4"/></svg>
\ No newline at end of file
<svg width="48" height="48" viewBox="0 0 48 48" fill="none"><path d="M41 26v14a1 1 0 01-1 1H8a1 1 0 01-1-1V8a1 1 0 011-1h14M19.822 28.178L39.899 8.1M41 20V7H28" stroke="#4E5969" stroke-width="4"/></svg>
\ No newline at end of file
<svg width="48" height="48" viewBox="0 0 48 48" fill="none"><path d="M19 40V8m23 2a2 2 0 00-2-2H8a2 2 0 00-2 2v28a2 2 0 002 2h32a2 2 0 002-2V10z" stroke="#4E5969" stroke-width="4"/></svg>
\ No newline at end of file
<svg width="48" height="48" viewBox="0 0 48 48" fill="none"><circle cx="24" cy="24" r="18" stroke="#4E5969" stroke-width="4"/><path d="M28.485 32.485L20 24l8.485-8.485" stroke="#4E5969" stroke-width="4"/></svg>
\ No newline at end of file
<svg width="48" height="48" viewBox="0 0 48 48" fill="none"><path d="M32 8.4L16.444 23.956 32 39.513" stroke="#4E5969" stroke-width="4"/></svg>
\ No newline at end of file
<svg width="48" height="48" viewBox="0 0 48 48" fill="none"><path d="M4 8h14.5M33 8H18.5m0 0v34" stroke="#4E5969" stroke-width="4"/><path d="M39 9.5L37 13h4l-2-3.5zM39 38.5L37 35h4l-2 3.5z" fill="#4E5969"/><path d="M39 13h2l-2-3.5-2 3.5h2zm0 0v22m0 0h2l-2 3.5-2-3.5h2z" stroke="#4E5969" stroke-width="4"/></svg>
\ No newline at end of file
<svg width="48" height="48" viewBox="0 0 48 48" fill="none"><path d="M14.1 25.414l-4.95 4.95a6 6 0 008.486 8.485l8.485-8.485a6 6 0 000-8.485" stroke="#4E5969" stroke-width="4"/><path d="M21.879 26.121a6 6 0 010-8.485l8.485-8.485a6 6 0 118.485 8.485L33.5 23" stroke="#4E5969" stroke-width="4"/></svg>
\ No newline at end of file
<svg width="48" height="48" viewBox="0 0 48 48" fill="none"><path d="M13 24h30M5 12h4m4 24h30M13 12h30M5 24h4M5 36h4" stroke="#4E5969" stroke-width="4"/></svg>
\ No newline at end of file
<svg width="48" height="48" viewBox="0 0 48 48" fill="none"><path d="M29 16h12a1 1 0 011 1v22a1 1 0 01-1 1H7a1 1 0 01-1-1V17a1 1 0 011-1h12m10 0l8-9m-8 9H19m0 0l-8-9m17.281 21.88l-6.195 4.475a1 1 0 01-1.586-.81v-8.262a1 1 0 011.521-.853l6.196 3.786a1 1 0 01.064 1.664z" stroke="#4E5969" stroke-width="4"/></svg>
\ No newline at end of file
<svg width="48" height="48" viewBox="0 0 48 48" fill="none"><path d="M42 24c0 9.941-8.059 18-18 18S6 33.941 6 24 14.059 6 24 6" stroke="#4E5969" stroke-width="4"/></svg>
\ No newline at end of file
<svg width="48" height="48" viewBox="0 0 48 48" fill="none"><circle cx="24" cy="19" r="5" stroke="#4E5969" stroke-width="4"/><path d="M39 20.405C39 28.914 24 43 24 43S9 28.914 9 20.405C9 11.897 15.716 5 24 5c8.284 0 15 6.897 15 15.405z" stroke="#4E5969" stroke-width="4"/></svg>
\ No newline at end of file
<svg width="48" height="48" viewBox="0 0 48 48" fill="none"><path d="M9 41.5h30a2 2 0 002-2v-20a2 2 0 00-2-2H9a2 2 0 00-2 2v20a2 2 0 002 2zM16 14.5a8 8 0 1116 0v3H16v-3z" stroke="#4E5969" stroke-width="4"/><path d="M28 29.5a4 4 0 11-8 0 4 4 0 018 0z" stroke="#4E5969" stroke-width="4"/></svg>
\ No newline at end of file
<svg width="48" height="48" viewBox="0 0 48 48" fill="none"><path d="M24 10c7.732 0 14 6.268 14 14 0 3.815-1.526 7.273-4 9.798M24 34v6l4-3-4-3zM24 13V7l-4 3 4 3zM24 38c-7.732 0-14-6.268-14-14 0-3.815 1.526-7.273 4-9.798" stroke="#4E5969" stroke-width="4"/></svg>
\ No newline at end of file
<svg width="48" height="48" viewBox="0 0 48 48" fill="none"><path d="M40 8L29.679 18.321" stroke="#4E5969" stroke-width="4" stroke-linecap="round"/><path d="M33 27c0 7.18-5.82 13-13 13S7 34.18 7 27s5.82-13 13-13 13 5.82 13 13zM31 8h9v9" stroke="#4E5969" stroke-width="4" stroke-linecap="square"/></svg>
\ No newline at end of file
<svg width="48" height="48" viewBox="0 0 48 48" fill="none"><path d="M42 11H6M42 24H22M42 37H6M13.66 26.912l-4.82-3.118 4.82-3.118v6.236z" stroke="#4E5969" stroke-width="4"/></svg>
\ No newline at end of file
<svg width="48" height="48" viewBox="0 0 48 48" fill="none"><path d="M6 11h36M22 24h20M6 37h36M8 20.882L12.819 24 8 27.118v-6.236z" stroke="#4E5969" stroke-width="4"/></svg>
\ No newline at end of file
<svg width="48" height="48" viewBox="0 0 48 48" fill="none"><path d="M5 10h38M5 24h38M5 38h38" stroke="#4E5969" stroke-width="4"/></svg>
\ No newline at end of file
<svg width="48" height="48" viewBox="0 0 48 48" fill="none"><path d="M40.527 20C38.727 12.541 32.01 7 24 7 14.611 7 7 14.611 7 24v17h14" stroke="#4E5969" stroke-width="4"/><path d="M40.364 40.364a9 9 0 00-12.728-12.728m12.728 12.728a9 9 0 01-12.728-12.728m12.728 12.728L27.636 27.636M13 20h12M13 29h6" stroke="#4E5969" stroke-width="4"/></svg>
\ No newline at end of file
<svg width="48" height="48" viewBox="0 0 48 48" fill="none"><path d="M15 20h18m-18 9h9M7 41h17.63C33.67 41 41 33.67 41 24.63V24c0-9.389-7.611-17-17-17S7 14.611 7 24v17z" stroke="#4E5969" stroke-width="4"/></svg>
\ No newline at end of file
<svg width="48" height="48" viewBox="0 0 48 48" fill="none"><path d="M20 10h23M20 24h23M20 38h23M9 12v28m0-28a2 2 0 100-4 2 2 0 000 4zm0 26h7M9 24h7" stroke="#4E5969" stroke-width="4"/></svg>
\ No newline at end of file
<svg width="48" height="48" viewBox="0 0 48 48" fill="none"><path d="M42 24c0 9.941-8.059 18-18 18S6 33.941 6 24 14.059 6 24 6s18 8.059 18 18z" fill="#4E5969" stroke="#4E5969" stroke-width="4"/><path d="M32 24H16" stroke="#fff" stroke-width="4"/></svg>
\ No newline at end of file
<svg width="48" height="48" viewBox="0 0 48 48" fill="none"><path d="M42 24c0 9.941-8.059 18-18 18S6 33.941 6 24 14.059 6 24 6s18 8.059 18 18zM32 24H16" stroke="#4E5969" stroke-width="4"/></svg>
\ No newline at end of file
<svg width="48" height="48" viewBox="0 0 48 48" fill="none"><path d="M5 24h38" stroke="#4E5969" stroke-width="4"/></svg>
\ No newline at end of file
<svg width="48" height="48" viewBox="0 0 48 48" fill="none"><path d="M17 14h14m6.125 28h-26.25C9.839 42 9 41.105 9 40V8c0-1.105.84-2 1.875-2h26.25C38.16 6 39 6.895 39 8v32c0 1.105-.84 2-1.875 2zM22 33a2 2 0 114 0 2 2 0 01-4 0z" stroke="#4E5969" stroke-width="4"/><circle cx="24" cy="33" r="2" fill="#4E5969"/></svg>
\ No newline at end of file
<svg width="48" height="48" viewBox="0 0 48 48" fill="none"><path d="M42.108 29.769c.124-.387-.258-.736-.645-.613A17.99 17.99 0 0136 30c-9.941 0-18-8.059-18-18 0-1.905.296-3.74.844-5.463.123-.387-.226-.769-.613-.645C10.558 8.334 5 15.518 5 24c0 10.493 8.507 19 19 19 8.482 0 15.666-5.558 18.108-13.231z" fill="#4E5969"/></svg>
\ No newline at end of file
<svg width="48" height="48" viewBox="0 0 48 48" fill="none"><path d="M39.979 29.241c.11-.344-.23-.654-.574-.544-1.53.487-3.162.75-4.855.75-8.834 0-15.997-7.163-15.997-15.997 0-1.693.263-3.324.75-4.855.11-.344-.2-.684-.544-.574C11.939 10.19 7 16.576 7 24.114 7 33.44 14.56 41 23.886 41c7.538 0 13.923-4.94 16.093-11.759z" stroke="#4E5969" stroke-width="4"/></svg>
\ No newline at end of file
<svg width="48" height="48" viewBox="0 0 48 48" fill="none"><path d="M25 10h-2V8h2v2zM25 25h-2v-2h2v2zM25 40h-2v-2h2v2z" fill="#4E5969"/><path d="M25 10h-2V8h2v2zM25 25h-2v-2h2v2zM25 40h-2v-2h2v2z" stroke="#4E5969" stroke-width="4"/></svg>
\ No newline at end of file
<svg width="48" height="48" viewBox="0 0 48 48" fill="none"><path d="M38 25v-2h2v2h-2zM23 25v-2h2v2h-2zM8 25v-2h2v2H8z" fill="#4E5969"/><path d="M38 25v-2h2v2h-2zM23 25v-2h2v2h-2zM8 25v-2h2v2H8z" stroke="#4E5969" stroke-width="4"/></svg>
\ No newline at end of file
<svg width="48" height="48" viewBox="0 0 48 48" fill="none"><path d="M6 7h4v4H6V7zM6 23h4v4H6v-4zM6 38h4v4H6v-4zM14 15h4v4h-4v-4zM14 31h4v4h-4v-4zM22 7h4v4h-4V7zM22 23h4v4h-4v-4zM22 38h4v4h-4v-4zM30 15h4v4h-4v-4zM30 31h4v4h-4v-4zM38 7h4v4h-4V7zM38 23h4v4h-4v-4zM38 38h4v4h-4v-4z" fill="#4E5969"/><path d="M6 7h4v4H6V7zM6 23h4v4H6v-4zM6 38h4v4H6v-4zM14 15h4v4h-4v-4zM14 31h4v4h-4v-4zM22 7h4v4h-4V7zM22 23h4v4h-4v-4zM22 38h4v4h-4v-4zM30 15h4v4h-4v-4zM30 31h4v4h-4v-4zM38 7h4v4h-4V7zM38 23h4v4h-4v-4zM38 38h4v4h-4v-4z" stroke="#4E5969" stroke-width="4"/></svg>
\ No newline at end of file
<svg width="48" height="48" viewBox="0 0 48 48" fill="none"><path d="M15 37a4 4 0 10-8 0 4 4 0 008 0zm0 0V18.5M41 37a4 4 0 10-8 0 4 4 0 008 0zm0 0V16.5m-26 2V9.926a1 1 0 01.923-.997l24-1.846A1 1 0 0141 8.08v8.42m-26 2l26-2" stroke="#4E5969" stroke-width="4"/></svg>
\ No newline at end of file
<svg width="48" height="48" viewBox="0 0 48 48" fill="none"><path d="M5.931 13.001A2 2 0 004 15v18a2 2 0 002 2h7.37l9.483 6.639A2 2 0 0026 40v-6.93L5.931 13.001zM35.27 28.199l-3.311-3.313a7.985 7.985 0 00-1.96-6.107.525.525 0 01.011-.718l2.122-2.122a.485.485 0 01.7.008c3.125 3.393 3.938 8.15 2.439 12.252zM41.13 34.059l-2.936-2.937c3.07-5.89 2.226-13.288-2.531-18.348a.513.513 0 01.004-.713l2.122-2.122a.492.492 0 01.703.006c6.322 6.64 7.202 16.56 2.639 24.114zM26 18.928l-8.688-8.688 5.541-3.878A2 2 0 0126 8v10.928z" fill="#4E5969"/><path fill-rule="evenodd" clip-rule="evenodd" d="M7.012 4.184l35.272 35.272-2.828 2.828L4.184 7.012l2.828-2.828z" fill="#4E5969"/></svg>
\ No newline at end of file
<svg width="48" height="48" viewBox="0 0 48 48" fill="none"><path d="M35.728 11.272C41.508 17.052 42.5 25 39.123 32M30.071 16.929C32.535 19.393 34 23 32.799 26M19 11.5l4.833-4.35a.1.1 0 01.167.075V17M6.5 6.5l35 35M10 16H7.1a.1.1 0 00-.1.1v15.8a.1.1 0 00.1.1H14l9.833 8.85a.1.1 0 00.167-.075V31" stroke="#4E5969" stroke-width="4"/></svg>
\ No newline at end of file
<svg width="48" height="48" viewBox="0 0 48 48" fill="none"><path d="M6 19h10m0 0h26m-26 0V9m0 10v10m0 0v10m0-10H6m10 0h26M6 9h36v30H6V9z" stroke="#4E5969" stroke-width="4"/></svg>
\ No newline at end of file
<svg width="48" height="48" viewBox="0 0 48 48" fill="none"><path d="M17.5 10.74A12.94 12.94 0 0124 9c7.18 0 13 5.82 13 13v7.5M17 42h14M6 4l36 40M24 9V4M11 35V22c0-1.835.38-3.58 1.066-5.163M11 35H6m5 0h15.5" stroke="#4E5969" stroke-width="4"/></svg>
\ No newline at end of file
<svg width="48" height="48" viewBox="0 0 48 48" fill="none"><path d="M24 9c7.18 0 13 5.82 13 13v13H11V22c0-7.18 5.82-13 13-13zm0 0V4M6 35h36m-25 7h14" stroke="#4E5969" stroke-width="4"/></svg>
\ No newline at end of file
<svg width="48" height="48" viewBox="0 0 48 48" fill="none"><path d="M29.506 6.502L18.494 41.498" stroke="#4E5969" stroke-width="4"/></svg>
\ No newline at end of file
<svg width="48" height="48" viewBox="0 0 48 48" fill="none"><path d="M6 8a1 1 0 011-1h34a1 1 0 011 1v26a1 1 0 01-1 1H7a1 1 0 01-1-1V8zM12 41h24" stroke="#4E5969" stroke-width="4"/><path d="M22.266 27.353l-6.338-6.39 6.389-6.338M16.241 20.965l17.758.07" stroke="#4E5969" stroke-width="4"/></svg>
\ No newline at end of file
<svg width="48" height="48" viewBox="0 0 48 48" fill="none"><path d="M13 24h30M13 37h30M13 11h30" stroke="#4E5969" stroke-width="4"/><path fill-rule="evenodd" clip-rule="evenodd" d="M5.578 13.06v1.694h5.041V13.06H9.164V7.555H7.748L5.256 8.967l.762 1.514 1.114-.637v3.215H5.578zM5.37 26.204v1.491h5.071V26H7.963l.94-.94c.454-.44.784-.86.982-1.258.199-.404.299-.826.299-1.266 0-.686-.225-1.225-.684-1.6-.45-.372-1.092-.55-1.911-.55-.473 0-.934.072-1.38.214a3.63 3.63 0 00-1.133.582l-.067.052.653 1.534.112-.085c.263-.199.524-.345.783-.44.267-.095.525-.141.774-.141.31 0 .52.06.653.164.127.1.198.252.198.478 0 .176-.05.356-.154.54l-.002.002c-.099.186-.273.416-.528.69L5.37 26.205zM10.382 38.344c0-.443-.118-.827-.359-1.145a1.702 1.702 0 00-.712-.56 1.656 1.656 0 00.586-.52 1.73 1.73 0 00.306-1.023c0-.403-.108-.762-.326-1.073a2.076 2.076 0 00-.918-.71c-.386-.166-.834-.247-1.34-.247-.48 0-.953.07-1.418.212-.458.135-.835.319-1.127.555l-.065.053.652 1.486.11-.077c.276-.192.563-.339.863-.44l.002-.002c.3-.108.582-.161.844-.161.267 0 .454.065.58.179l.003.003c.129.107.198.262.198.48 0 .201-.07.33-.197.412-.138.088-.375.141-.733.141h-1.01v1.626H7.51c.37 0 .613.056.75.15.126.085.199.23.199.463 0 .254-.077.411-.21.503l-.002.001c-.135.098-.386.158-.777.158-.594 0-1.194-.2-1.8-.605l-.11-.073-.65 1.483.064.053c.285.236.663.423 1.127.565h.002c.466.135.951.203 1.456.203.852 0 1.538-.178 2.045-.546.517-.378.778-.896.778-1.544z" fill="#4E5969"/></svg>
\ No newline at end of file
<svg width="48" height="48" viewBox="0 0 48 48" fill="none"><path d="M34 11.5L39 9h1v32" stroke="#4E5969" stroke-width="4"/><path d="M24 17h1v1h-1v-1zM24 30h1v1h-1v-1z" fill="#4E5969"/><path d="M24 17h1v1h-1v-1zM24 30h1v1h-1v-1zM5.5 11.5l5-2.5h1v32" stroke="#4E5969" stroke-width="4"/></svg>
\ No newline at end of file
<svg width="48" height="48" viewBox="0 0 48 48" fill="none"><path d="M31.813 12.02C29.73 10.459 27.013 10 24 10c-9.78 0-17.708 6.987-17.708 15.042 0 8.054 8.97 14.583 18.75 14.583 5.277 0 2.485-5.318 5.73-8.333 2.767-2.574 10.937-1.563 10.937-6.25 0-2.792-.521-5.209-2.605-7.617" stroke="#4E5969" stroke-width="4" stroke-linejoin="round"/><path d="M25.042 25.563L42.23 8.375" stroke="#4E5969" stroke-width="4"/><circle cx="22.5" cy="17.5" r="2.5" fill="#4E5969"/><circle cx="15.5" cy="20.5" r="2.5" fill="#4E5969"/><circle cx="14.5" cy="28.5" r="2.5" fill="#4E5969"/></svg>
\ No newline at end of file
<svg width="48" height="48" viewBox="0 0 48 48" fill="none"><rect x="8" y="14" width="24" height="28" rx="1" stroke="#4E5969" stroke-width="4"/><path d="M24 6h.01v.01H24V6zM32 6h.01v.01H32V6zM40 6h.01v.01H40V6zM40 13h.01v.01H40V13zM40 21h.01v.01H40V21z" fill="#4E5969"/><path d="M24 6h.01v.01H24V6zM32 6h.01v.01H32V6zM40 6h.01v.01H40V6zM40 13h.01v.01H40V13zM40 21h.01v.01H40V21z" stroke="#4E5969" stroke-width="4"/></svg>
\ No newline at end of file
<svg width="48" height="48" viewBox="0 0 48 48" fill="none"><path d="M42 24c0 9.941-8.059 18-18 18S6 33.941 6 24 14.059 6 24 6s18 8.059 18 18z" fill="#4E5969"/><path fill-rule="evenodd" clip-rule="evenodd" d="M24 8C15.163 8 8 15.163 8 24s7.163 16 16 16 16-7.163 16-16S32.837 8 24 8zM4 24C4 12.954 12.954 4 24 4s20 8.954 20 20-8.954 20-20 20S4 35.046 4 24z" fill="#4E5969"/><path d="M19 19v10h1V19h-1zM28 19v10h1V19h-1z" stroke="#fff" stroke-width="4"/></svg>
\ No newline at end of file
<svg width="48" height="48" viewBox="0 0 48 48" fill="none"><path d="M42 24c0 9.941-8.059 18-18 18S6 33.941 6 24 14.059 6 24 6s18 8.059 18 18z" stroke="#4E5969" stroke-width="4"/><path d="M19 19v10h1V19h-1zM28 19v10h1V19h-1z" stroke="#4E5969" stroke-width="4"/></svg>
\ No newline at end of file
<svg width="48" height="48" viewBox="0 0 48 48" fill="none"><path stroke="#4E5969" stroke-width="4" d="M14 12h4v24h-4zM30 12h4v24h-4z"/><path fill="#4E5969" d="M14 12h4v24h-4zM30 12h4v24h-4z"/></svg>
\ No newline at end of file
<svg width="48" height="48" viewBox="0 0 48 48" fill="none"><path fill="#4E5969" d="M31.07 8.444l8.486 8.485L19.05 37.435l-8.485-8.485zM33.9 5.615a2 2 0 012.828 0l5.657 5.657a2 2 0 010 2.828l-1.414 1.415-8.486-8.486L33.9 5.615zM17.636 38.85l-8.485-8.486-3.61 10.83a1 1 0 001.264 1.265l10.831-3.61z"/></svg>
\ No newline at end of file
<svg width="48" height="48" viewBox="0 0 48 48" fill="none"><path d="M28.364 11.565l7.071 7.071M7.151 32.778L33.314 6.615l7.07 7.071L14.223 39.85H7.15v-7.07z" stroke="#4E5969" stroke-width="4"/></svg>
\ No newline at end of file
<svg width="48" height="48" viewBox="0 0 48 48" fill="none"><path d="M6.707 34.284a1 1 0 010-1.414l5.657-5.657a1 1 0 011.414 0l4.95 4.95s3.535-1.414 7.778-5.657c4.243-4.243 5.657-7.778 5.657-7.778l-4.95-4.95a1 1 0 010-1.414l5.657-5.657a1 1 0 011.414 0l6.01 6.01s3.183 7.425-8.485 19.092c-11.667 11.668-19.092 8.485-19.092 8.485l-6.01-6.01z" stroke="#4E5969" stroke-width="4"/></svg>
\ No newline at end of file
<svg width="48" height="48" viewBox="0 0 48 48" fill="none"><path d="M17.533 10.974a1 1 0 00-1.537.844v24.357a1 1 0 001.537.843L36.67 24.84a1 1 0 000-1.688L17.533 10.974z" fill="#4E5969"/></svg>
\ No newline at end of file
<svg width="48" height="48" viewBox="0 0 48 48" fill="none"><path d="M12.533 7.965A1 1 0 0011 8.81v30.377a1 1 0 001.533.846L36.656 24.84a1 1 0 000-1.692L12.533 7.965z" stroke="#4E5969" stroke-width="4"/></svg>
\ No newline at end of file
<svg width="48" height="48" viewBox="0 0 48 48" fill="none"><path d="M24 42c9.941 0 18-8.059 18-18S33.941 6 24 6 6 14.059 6 24s8.059 18 18 18z" fill="#4E5969" stroke="#4E5969" stroke-width="4"/><path d="M19 17v14l12-7-12-7z" fill="#fff" stroke="#fff" stroke-width="2" stroke-linejoin="round"/></svg>
\ No newline at end of file
<svg width="48" height="48" viewBox="0 0 48 48" fill="none"><path d="M24 42c9.941 0 18-8.059 18-18S33.941 6 24 6 6 14.059 6 24s8.059 18 18 18z" stroke="#4E5969" stroke-width="4"/><path d="M19 17v14l12-7-12-7z" stroke="#4E5969" stroke-width="4" stroke-linejoin="round"/></svg>
\ No newline at end of file
<svg width="48" height="48" viewBox="0 0 48 48" fill="none"><path d="M42 24c0 9.941-8.059 18-18 18S6 33.941 6 24 14.059 6 24 6s18 8.059 18 18z" fill="#4E5969" stroke="#4E5969" stroke-width="4"/><path d="M32 24h-8m-8 0h8m0 0v8m0-8v-8" stroke="#fff" stroke-width="4"/></svg>
\ No newline at end of file
<svg width="48" height="48" viewBox="0 0 48 48" fill="none"><path d="M42 24c0 9.941-8.059 18-18 18S6 33.941 6 24 14.059 6 24 6s18 8.059 18 18zM24 32V16M32 24H16" stroke="#4E5969" stroke-width="4"/></svg>
\ No newline at end of file
<svg width="48" height="48" viewBox="0 0 48 48" fill="none"><path d="M5 24h38M24 5v38" stroke="#4E5969" stroke-width="4"/></svg>
\ No newline at end of file
<svg width="48" height="48" viewBox="0 0 48 48" fill="none"><path d="M15.5 9.274C10.419 12.214 7 17.708 7 24c0 9.389 7.611 17 17 17s17-7.611 17-17c0-6.292-3.419-11.786-8.5-14.726M24 5v22" stroke="#4E5969" stroke-width="4"/></svg>
\ No newline at end of file
<svg width="48" height="48" viewBox="0 0 48 48" fill="none"><path d="M13 34H7a1 1 0 01-1-1V16a1 1 0 011-1h34a1 1 0 011 1v17a1 1 0 01-1 1h-6M33 7H15a1 1 0 00-1 1v6a1 1 0 001 1h18a1 1 0 001-1V8a1 1 0 00-1-1z" stroke="#4E5969" stroke-width="4"/><path d="M13 29a1 1 0 011-1h20a1 1 0 011 1v11a1 1 0 01-1 1H14a1 1 0 01-1-1V29z" stroke="#4E5969" stroke-width="4"/></svg>
\ No newline at end of file
<svg width="48" height="48" viewBox="0 0 48 48" fill="none"><path d="M42 24c0 9.941-8.059 18-18 18S6 33.941 6 24 14.059 6 24 6s18 8.059 18 18z" stroke="#4E5969" stroke-width="4"/><path d="M6.704 19L15 21.5l6.062-6.994a1 1 0 00.138-1.104L18 7.024M18 40.976l10.918-16.117a1 1 0 00-.298-1.409L21.5 19 15 21.5l4.683 5.152a1 1 0 01.25.814L18 40.976z" stroke="#4E5969" stroke-width="4"/></svg>
\ No newline at end of file
<svg width="48" height="48" viewBox="0 0 48 48" fill="none"><path d="M19.92 28.163L7.192 40.891M19.92 28.163l8.884 8.884c.17.17.447.17.617 0l5.12-5.12a7.862 7.862 0 001.667-8.656.092.092 0 01.02-.102l4.905-4.905a2 2 0 000-2.829L32.648 6.95a2 2 0 00-2.828 0l-4.89 4.89a.126.126 0 01-.139.026 7.828 7.828 0 00-8.618 1.66l-5.027 5.027a.591.591 0 000 .836l8.774 8.774z" stroke="#4E5969" stroke-width="4"/></svg>
\ No newline at end of file
<svg width="48" height="48" viewBox="0 0 48 48" fill="none"><path d="M24 30v4m0 3v6m19-19h-6m-3 0h-4M7 7h17v17H7V7zm0 25h9v9H7v-9zm25 0h9v9h-9v-9zm0-25h9v9h-9V7zm-18 7h3v3h-3v-3z" stroke="#4E5969" stroke-width="4"/></svg>
\ No newline at end of file
<svg width="48" height="48" viewBox="0 0 48 48" fill="none"><path d="M42 24c0 9.941-8.059 18-18 18S6 33.941 6 24 14.059 6 24 6s18 8.059 18 18z" fill="#4E5969" stroke="#4E5969" stroke-width="4"/><path d="M24.006 31v4.008m0-6.008L24 28c0-3 3-4 4.78-6.402C30.558 19.195 28.288 15 23.987 15c-4.014 0-5.382 2.548-5.388 4.514v.465" stroke="#fff" stroke-width="4"/></svg>
\ No newline at end of file
<svg width="48" height="48" viewBox="0 0 48 48" fill="none"><path d="M42 24c0 9.941-8.059 18-18 18S6 33.941 6 24 14.059 6 24 6s18 8.059 18 18z" stroke="#4E5969" stroke-width="4" stroke-linecap="square"/><path d="M24.007 29L24 28c0-3 3-4 4.78-6.402C30.56 19.195 28.29 15 23.988 15c-4.013 0-5.382 2.548-5.388 4.514v.465M24.007 31v4.008" stroke="#4E5969" stroke-width="4"/></svg>
\ No newline at end of file
<svg width="48" height="48" viewBox="0 0 48 48" fill="none"><path d="M13 17c0-5.523 4.925-10 11-10s11 4.477 11 10c0 3.607-2.1 6.767-5.25 8.526C26.857 27.142 24 29.686 24 33v3M24 41h.02v.02H24V41z" stroke="#4E5969" stroke-width="4"/></svg>
\ No newline at end of file
<svg width="48" height="48" viewBox="0 0 48 48" fill="none"><path d="M18.08 33.093a6 6 0 01-12 0c-.212-3.593 2.686-6 6-6a6 6 0 016 6zM39.08 33.093a6 6 0 01-12 0c-.212-3.593 2.686-6 6-6a6 6 0 016 6z" fill="#4E5969"/><path d="M18.08 33.093a6 6 0 01-12 0c-.212-3.593 2.686-6 6-6a6 6 0 016 6zM39.08 33.093a6 6 0 01-12 0c-.212-3.593 2.686-6 6-6a6 6 0 016 6zM27.08 33.093c-.5-8.5 1-25.5 15-24M6.08 33.093c-.5-8.5 1-25.5 15-24" stroke="#4E5969" stroke-width="4"/></svg>
\ No newline at end of file
<svg width="48" height="48" viewBox="0 0 48 48" fill="none"><path clip-rule="evenodd" d="M24 6c9.941 0 18 8.059 18 18s-8.059 18-18 18S6 33.941 6 24 14.059 6 24 6z" stroke="#4E5969" stroke-width="4"/><path d="M19 20a1 1 0 011-1h8a1 1 0 011 1v8a1 1 0 01-1 1h-8a1 1 0 01-1-1v-8z" fill="#4E5969"/><path d="M19 20a1 1 0 011-1h8a1 1 0 011 1v8a1 1 0 01-1 1h-8a1 1 0 01-1-1v-8z" stroke="#4E5969" stroke-width="4"/></svg>
\ No newline at end of file
<svg width="48" height="48" viewBox="0 0 48 48" fill="none"><path clip-rule="evenodd" d="M24 6c9.941 0 18 8.059 18 18s-8.059 18-18 18S6 33.941 6 24 14.059 6 24 6z" stroke="#4E5969" stroke-width="4"/><path d="M30 24a6 6 0 11-12 0 6 6 0 0112 0z" fill="#4E5969"/><path d="M30 24a6 6 0 11-12 0 6 6 0 0112 0z" stroke="#4E5969" stroke-width="4"/></svg>
\ No newline at end of file
<svg width="48" height="48" viewBox="0 0 48 48" fill="none"><path d="M39.19 16H18.5C12.149 16 7 21.149 7 27.5S12.149 39 18.5 39H31" stroke="#4E5969" stroke-width="4"/><path d="M32.678 23.78l7.778-7.778-7.778-7.778" stroke="#4E5969" stroke-width="4"/></svg>
\ No newline at end of file
<svg width="48" height="48" viewBox="0 0 48 48" fill="none"><path d="M38.837 18C36.463 12.136 30.715 8 24 8 15.163 8 8 15.163 8 24s7.163 16 16 16c7.455 0 13.72-5.1 15.496-12" stroke="#4E5969" stroke-width="4"/><path d="M40 8v10H30" stroke="#4E5969" stroke-width="4"/></svg>
\ No newline at end of file
<svg width="48" height="48" viewBox="0 0 48 48" fill="none"><path d="M6.641 24.684L20.654 39.63a.2.2 0 00.346-.137v-8.949A23.078 23.078 0 0126 30c6.207 0 11.84 2.459 15.978 6.456a.01.01 0 00.017-.007c.003-.15.005-.299.005-.45 0-10.493-8.507-19-19-19-.675 0-1.343.036-2 .105V8.506a.2.2 0 00-.346-.137L6.641 23.316a1 1 0 000 1.368z" stroke="#4E5969" stroke-width="4"/></svg>
\ No newline at end of file
<svg width="48" height="48" viewBox="0 0 48 48" fill="none"><circle cx="24" cy="24" r="18" stroke="#4E5969" stroke-width="4"/><path d="M19.485 15.515L27.971 24l-8.486 8.485" stroke="#4E5969" stroke-width="4"/></svg>
\ No newline at end of file
<svg width="48" height="48" viewBox="0 0 48 48" fill="none"><path d="M16 39.513l15.556-15.557L16 8.4" stroke="#4E5969" stroke-width="4"/></svg>
\ No newline at end of file
<svg width="48" height="48" viewBox="0 0 48 48" fill="none"><path d="M24 7v6m0-6h5m-5 0h-5M3 21v11m25 8H9V13h30v11M39 28v14" stroke="#4E5969" stroke-width="4"/><path d="M18 26h1v1h-1v-1zM29 26h1v1h-1v-1zM46 35h-7M39 35h-7" stroke="#4E5969" stroke-width="4"/></svg>
\ No newline at end of file
<svg width="48" height="48" viewBox="0 0 48 48" fill="none"><path d="M18 26h1v1h-1v-1zM29 26h1v1h-1v-1z" fill="#4E5969"/><path d="M24 7v6m0-6h5m-5 0h-5M3 21v11m42-11v11M9 13h30v27H9V13zm9 13h1v1h-1v-1zm11 0h1v1h-1v-1z" stroke="#4E5969" stroke-width="4"/></svg>
\ No newline at end of file
<svg width="48" height="48" viewBox="0 0 48 48" fill="none"><path d="M10 22a1 1 0 011-1h20a1 1 0 011 1v16a1 1 0 01-1 1H11a1 1 0 01-1-1V22zM23 11h11a6 6 0 016 6v6" stroke="#4E5969" stroke-width="4"/><path d="M22.5 12.893L19.587 11 22.5 9.107v3.786z" stroke="#4E5969" stroke-width="5"/></svg>
\ No newline at end of file
<svg width="48" height="48" viewBox="0 0 48 48" fill="none"><path d="M38 22a1 1 0 00-1-1H17a1 1 0 00-1 1v16a1 1 0 001 1h20a1 1 0 001-1V22zM25 11H14a6 6 0 00-6 6v6" stroke="#4E5969" stroke-width="4"/><path d="M25.5 12.893L28.413 11 25.5 9.107v3.786z" stroke="#4E5969" stroke-width="5"/></svg>
\ No newline at end of file
<svg width="48" height="48" viewBox="0 0 48 48" fill="none"><path d="M40 11s-9-1-16-5c-7 4-16 5-16 5v15s2 12 16 16.027C38 38 40 26 40 26V11z" stroke="#4E5969" stroke-width="4"/><path d="M16.825 22.165l6 6 10-10" stroke="#4E5969" stroke-width="4"/></svg>
\ No newline at end of file
<svg width="48" height="48" viewBox="0 0 48 48" fill="none"><path d="M21 13v9m18 20H9a1 1 0 01-1-1V7a1 1 0 011-1h22.55a1 1 0 01.748.336l7.45 8.38a1 1 0 01.252.664V41a1 1 0 01-1 1zM14 6h14v15a1 1 0 01-1 1H15a1 1 0 01-1-1V6z" stroke="#4E5969" stroke-width="4"/></svg>
\ No newline at end of file
<svg width="48" height="48" viewBox="0 0 48 48" fill="none"><path d="M5 24h38M41 17V7H31M7 17V7h10M41 31v10H31M7 31v10h10" stroke="#4E5969" stroke-width="4"/></svg>
\ No newline at end of file
<svg width="48" height="48" viewBox="0 0 48 48" fill="none"><circle cx="24" cy="24" r="18" stroke="#4E5969" stroke-width="4"/><path d="M24 13v10l6.5 7" stroke="#4E5969" stroke-width="4"/></svg>
\ No newline at end of file
<svg width="48" height="48" viewBox="0 0 48 48" fill="none"><path d="M13 29a6 6 0 100 12 6 6 0 000-12zM41 35a6 6 0 10-12 0 6 6 0 0012 0zM40.293 7.707l-23.05 23.05m13.514 0L7.707 7.707" stroke="#4E5969" stroke-width="4"/></svg>
\ No newline at end of file
<svg width="48" height="48" viewBox="0 0 48 48" fill="none"><path d="M33.07 33.071c6.25-6.248 6.25-16.379 0-22.627-6.248-6.249-16.378-6.249-22.627 0-6.248 6.248-6.248 16.379 0 22.627 6.249 6.248 16.38 6.248 22.628 0zm0 0l8.486 8.485" stroke="#4E5969" stroke-width="4"/></svg>
\ No newline at end of file
<svg width="48" height="48" viewBox="0 0 48 48" fill="none"><path d="M17.314 7.243l-7.071 7.07L6 10.072M17.314 20.243l-7.071 7.07L6 23.072M17.314 33.243l-7.071 7.07L6 36.072M21 25h22M21 11h22M21 39h22" stroke="#4E5969" stroke-width="4"/></svg>
\ No newline at end of file
<svg width="48" height="48" viewBox="0 0 48 48" fill="none"><path d="M14 24l-7-5V7l34 17L7 41V29l7-5zm0 0h25" stroke="#4E5969" stroke-width="4" stroke-miterlimit="3.864" stroke-linecap="square"/></svg>
\ No newline at end of file
<svg width="48" height="48" viewBox="0 0 48 48" fill="none"><path d="M18.797 6.732A1 1 0 0119.76 6h8.48a1 1 0 01.963.732l1.286 4.628a1 1 0 001.213.7l4.65-1.2a1 1 0 011.117.468l4.24 7.344a1 1 0 01-.153 1.2L38.192 23.3a1 1 0 000 1.402l3.364 3.427a1 1 0 01.153 1.2l-4.24 7.344a1 1 0 01-1.116.468l-4.65-1.2a1 1 0 00-1.214.7l-1.286 4.628a1 1 0 01-.963.732h-8.48a1 1 0 01-.963-.732L17.51 36.64a1 1 0 00-1.213-.7l-4.65 1.2a1 1 0 01-1.116-.468l-4.24-7.344a1 1 0 01.152-1.2L9.81 24.7a1 1 0 000-1.402l-3.365-3.427a1 1 0 01-.152-1.2l4.24-7.344a1 1 0 011.116-.468l4.65 1.2a1 1 0 001.213-.7l1.286-4.628z" stroke="#4E5969" stroke-width="4"/><path d="M30 24a6 6 0 11-12 0 6 6 0 0112 0z" stroke="#4E5969" stroke-width="4"/></svg>
\ No newline at end of file
<svg width="48" height="48" viewBox="0 0 48 48" fill="none"><path d="M43.092 27.536L31.778 38.849M20.465 4.91L9.15 16.221m9.192 14.85a1 1 0 11-1.414-1.415 1 1 0 011.414 1.414zM6.323 28.95L19.05 41.678a1 1 0 001.415 0l21.213-21.213a1 1 0 000-1.415L28.95 6.323a1 1 0 00-1.414 0L6.323 27.536a1 1 0 000 1.414z" stroke="#4E5969" stroke-width="4"/><circle cx="17.636" cy="30.364" r="1" transform="rotate(45 17.636 30.364)" fill="#4E5969" stroke="#4E5969" stroke-width="4"/></svg>
\ No newline at end of file
<svg width="48" height="48" viewBox="0 0 48 48" fill="none"><path d="M32.442 21.552a4.5 4.5 0 11.065 4.025m-.065-4.025l-16.884-8.104m16.884 8.104A4.483 4.483 0 0032 23.5c0 .75.183 1.455.507 2.077m-16.95-12.13a4.5 4.5 0 11-8.113-3.895 4.5 4.5 0 018.114 3.896zm-.064 20.977A4.5 4.5 0 1011.5 41c3.334-.001 5.503-3.68 3.993-6.578zm0 0l17.014-8.847" stroke="#4E5969" stroke-width="4"/></svg>
\ No newline at end of file
<svg width="48" height="48" viewBox="0 0 48 48" fill="none"><path d="M18 20h-7a1 1 0 00-1 1v20a1 1 0 001 1h26a1 1 0 001-1V21a1 1 0 00-1-1h-7M32.368 14.364L24.004 6l-8.364 8.364M24.003 28V6.604" stroke="#4E5969" stroke-width="4" stroke-miterlimit="16"/></svg>
\ No newline at end of file
<svg width="48" height="48" viewBox="0 0 48 48" fill="none"><path d="M40 36v6H8v-6M30 7l9 9-9 9M9.108 32c1.29-8.868 13.917-15.85 29.392-15.998" stroke="#4E5969" stroke-width="4"/></svg>
\ No newline at end of file
<svg width="48" height="48" viewBox="0 0 48 48" fill="none"><path d="M28 4v15c0 .552.444 1 .996 1H44M20 44V29c0-.552-.444-1-.996-1H4" stroke="#4E5969" stroke-width="4"/></svg>
\ No newline at end of file
<svg width="48" height="48" viewBox="0 0 48 48" fill="none"><path d="M17.936 6H7a1 1 0 00-1 1v17.559a1 1 0 001 1h4V40a1 1 0 001 1h24a1 1 0 001-1V25.559h4a1 1 0 001-1V7a1 1 0 00-1-1H30.064C28.854 7.23 26.59 9.059 24 9.059S19.147 7.23 17.936 6z" stroke="#4E5969" stroke-width="4"/></svg>
\ No newline at end of file
<svg width="48" height="48" viewBox="0 0 48 48" fill="none"><path d="M13.585 12.145a1 1 0 00-1.585.81v22.09a1 1 0 001.585.81L28.878 24.81a1 1 0 000-1.622L13.585 12.145z" fill="#4E5969"/><path fill-rule="evenodd" clip-rule="evenodd" d="M33 36a1 1 0 01-1-1V13a1 1 0 011-1h2a1 1 0 011 1v22a1 1 0 01-1 1h-2z" fill="#4E5969"/></svg>
\ No newline at end of file
<svg width="48" height="48" viewBox="0 0 48 48" fill="none"><path d="M34 24L10 40V8l24 16z" stroke="#4E5969" stroke-width="4" stroke-linecap="round" stroke-linejoin="round"/><path stroke="#4E5969" stroke-width="4" d="M38 6v36"/></svg>
\ No newline at end of file
<svg width="48" height="48" viewBox="0 0 48 48" fill="none"><path d="M34.414 35.855a1 1 0 001.586-.81v-22.09a1 1 0 00-1.586-.81L19.122 23.19a1 1 0 000 1.622l15.292 11.044z" fill="#4E5969"/><path fill-rule="evenodd" clip-rule="evenodd" d="M15 12a1 1 0 011 1v22a1 1 0 01-1 1h-2a1 1 0 01-1-1V13a1 1 0 011-1h2z" fill="#4E5969"/></svg>
\ No newline at end of file
<svg width="48" height="48" viewBox="0 0 48 48" fill="none"><path d="M14 24l24 16V8L14 24z" stroke="#4E5969" stroke-width="4" stroke-linecap="round" stroke-linejoin="round"/><path stroke="#4E5969" stroke-width="4" d="M10 6v36"/></svg>
\ No newline at end of file
<svg width="48" height="48" viewBox="0 0 48 48" fill="none"><path d="M37 21L31.4 8h-.8L25 21M15 6v33.759a.1.1 0 01-.17.07L8 33M25 27h10.4v.65L27 39.35V40h11" stroke="#4E5969" stroke-width="4"/></svg>
\ No newline at end of file
<svg width="48" height="48" viewBox="0 0 48 48" fill="none"><path d="M25 27h10.4v.65L27 39.35V40h11M37 21L31.4 8h-.8L25 21M16.001 42V7.241a.1.1 0 00-.17-.07L9 14" stroke="#4E5969" stroke-width="4"/></svg>
\ No newline at end of file
<svg width="48" height="48" viewBox="0 0 48 48" fill="none"><path d="M43 9H5m0 30h14m15.5-15H5" stroke="#4E5969" stroke-width="4"/></svg>
\ No newline at end of file
<svg width="48" height="48" viewBox="0 0 48 48" fill="none"><path d="M14 15l10-7v32l-10-7H6V15h8z" fill="#4E5969"/><path d="M14 15v2a2 2 0 001.147-.361L14 15zm10-7h2a2 2 0 00-3.147-1.638L24 8zm0 32l-1.147 1.639A2 2 0 0026 40h-2zm-10-7l1.147-1.639A2 2 0 0014 31v2zM6 15v-2a2 2 0 00-2 2h2zm0 18H4a2 2 0 002 2v-2zm9.147-16.361l10-7-2.294-3.277-10 7 2.294 3.277zM22 8v32h4V8h-4zm3.147 30.361l-10-7-2.294 3.277 10 7 2.294-3.276zM6 17h8v-4H6v4zm8 14H6v4h8v-4zm-6 2V15H4v18h4zm21.657-14.586a8 8 0 010 11.314l2.828 2.828c4.687-4.686 4.687-12.284 0-16.97l-2.828 2.828zm5.657-6c6.248 6.249 6.248 16.38 0 22.628l2.828 2.828c7.81-7.81 7.81-20.474 0-28.284l-2.828 2.828z" fill="#4E5969"/></svg>
\ No newline at end of file
<svg width="48" height="48" viewBox="0 0 48 48" fill="none"><path d="M14 16l10-9v34l-10-9H6V16h8z" stroke="#4E5969" stroke-width="4" stroke-linecap="round" stroke-linejoin="round"/><path d="M31.071 16.929c3.905 3.905 3.905 10.237 0 14.142M36.728 11.272c7.03 7.03 7.03 18.427 0 25.456" stroke="#4E5969" stroke-width="4"/></svg>
\ No newline at end of file
<svg width="48" height="48" viewBox="0 0 48 48" fill="none"><path d="M7 33a1 1 0 011-1h32a1 1 0 011 1v7a1 1 0 01-1 1H8a1 1 0 01-1-1v-7zM29.081 21.18a8 8 0 10-10.163 0L14 32h20l-4.919-10.82z" stroke="#4E5969" stroke-width="4"/></svg>
\ No newline at end of file
<svg width="48" height="48" viewBox="0 0 48 48" fill="none"><path d="M22.552 6.908a.5.5 0 01.896 0l5.02 10.17a.5.5 0 00.376.274l11.224 1.631a.5.5 0 01.277.853l-8.122 7.916a.5.5 0 00-.143.443l1.917 11.178a.5.5 0 01-.726.527l-10.038-5.278a.5.5 0 00-.466 0L12.73 39.9a.5.5 0 01-.726-.527l1.918-11.178a.5.5 0 00-.144-.443l-8.122-7.916a.5.5 0 01.278-.853l11.223-1.63a.5.5 0 00.376-.274l5.02-10.17z" fill="#4E5969" stroke="#4E5969" stroke-width="4"/></svg>
\ No newline at end of file
<svg width="48" height="48" viewBox="0 0 48 48" fill="none"><path d="M22.552 6.908a.5.5 0 01.896 0l5.02 10.17a.5.5 0 00.376.274l11.224 1.631a.5.5 0 01.277.853l-8.122 7.916a.5.5 0 00-.143.443l1.917 11.178a.5.5 0 01-.726.527l-10.038-5.278a.5.5 0 00-.466 0L12.73 39.9a.5.5 0 01-.726-.527l1.918-11.178a.5.5 0 00-.144-.443l-8.122-7.916a.5.5 0 01.278-.853l11.223-1.63a.5.5 0 00.376-.274l5.02-10.17z" stroke="#4E5969" stroke-width="4"/></svg>
\ No newline at end of file
<svg width="48" height="48" viewBox="0 0 48 48" fill="none"><path d="M36.728 11.272c7.03 7.03 7.03 18.427 0 25.456-7.03 7.03-18.427 7.03-25.456 0-7.03-7.03-7.03-18.427 0-25.456 7.03-7.03 18.427-7.03 25.456 0zM36.728 36.728L11.272 11.272" stroke="#4E5969" stroke-width="4"/></svg>
\ No newline at end of file
<svg width="48" height="48" viewBox="0 0 48 48" fill="none"><path d="M7 18h34v12H7V18zM40 6H8a1 1 0 00-1 1v11h34V7a1 1 0 00-1-1zM7 30h34v11a1 1 0 01-1 1H8a1 1 0 01-1-1V30z" stroke="#4E5969" stroke-width="4"/><path d="M13.02 36H13v.02h.02V36z" stroke="#4E5969" stroke-width="4"/><path d="M13 12v-2h-2v2h2zm.02 0h2v-2h-2v2zm0 .02v2h2v-2h-2zm-.02 0h-2v2h2v-2zM13 14h.02v-4H13v4zm-1.98-2v.02h4V12h-4zm2-1.98H13v4h.02v-4zm1.98 2V12h-4v.02h4z" fill="#4E5969"/><path d="M13.02 24H13v.02h.02V24z" stroke="#4E5969" stroke-width="4"/></svg>
\ No newline at end of file
<svg width="48" height="48" viewBox="0 0 48 48" fill="none"><path d="M13 32c0 5.247 5.149 9 11.5 9S36 36.747 36 31.5c0-1.707-.5-4.5-3.5-5.695M34 14.5C34 10.358 29.523 7 24 7s-10 3.358-10 7.5c0 1.794 1.6 4.21 3 5.5M43 25.805H5" stroke="#4E5969" stroke-width="4"/></svg>
\ No newline at end of file
<svg width="48" height="48" viewBox="0 0 48 48" fill="none"><path d="M24.53 6.007H9.97c-.535 0-.97.449-.97 1.003V41.8c0 .148.152.245.28.179l15.25-7.881 14.248 7.88c.129.067.28-.03.28-.179V22.06M27.412 11.023h6.794m0 0H41m-6.794 0V4m0 7.023v7.023" stroke="#4E5969" stroke-width="4"/></svg>
\ No newline at end of file
<svg width="48" height="48" viewBox="0 0 48 48" fill="none"><path d="M9 7v34.667a.2.2 0 00.294.176L24 34l14.706 7.843a.2.2 0 00.294-.176V7a1 1 0 00-1-1H10a1 1 0 00-1 1z" stroke="#4E5969" stroke-width="4"/></svg>
\ No newline at end of file
<svg width="48" height="48" viewBox="0 0 48 48" fill="none"><path d="M10 6a1 1 0 00-1 1v34.667a.2.2 0 00.294.176L24 34l14.706 7.843a.2.2 0 00.294-.176V7a1 1 0 00-1-1H10z" stroke="#4E5969" stroke-width="4"/><path d="M31.289 15.596l-9.193 9.193-4.95-4.95" stroke="#4E5969" stroke-width="4"/></svg>
\ No newline at end of file
<svg width="48" height="48" viewBox="0 0 48 48" fill="none"><circle cx="24" cy="24" r="9" fill="#4E5969"/><path d="M21 5.5a.5.5 0 01.5-.5h5a.5.5 0 01.5.5v5a.5.5 0 01-.5.5h-5a.5.5 0 01-.5-.5v-5zM21 37.5a.5.5 0 01.5-.5h5a.5.5 0 01.5.5v5a.5.5 0 01-.5.5h-5a.5.5 0 01-.5-.5v-5zM42.5 21a.5.5 0 01.5.5v5a.5.5 0 01-.5.5h-5a.5.5 0 01-.5-.5v-5a.5.5 0 01.5-.5h5zM10.5 21a.5.5 0 01.5.5v5a.5.5 0 01-.5.5h-5a.5.5 0 01-.5-.5v-5a.5.5 0 01.5-.5h5zM39.203 34.96a.5.5 0 010 .707l-3.536 3.536a.5.5 0 01-.707 0l-3.535-3.536a.5.5 0 010-.707l3.535-3.535a.5.5 0 01.707 0l3.536 3.535zM16.575 12.333a.5.5 0 010 .707l-3.535 3.535a.5.5 0 01-.707 0L8.797 13.04a.5.5 0 010-.707l3.536-3.536a.5.5 0 01.707 0l3.535 3.536zM13.04 39.203a.5.5 0 01-.707 0l-3.536-3.536a.5.5 0 010-.707l3.536-3.535a.5.5 0 01.707 0l3.536 3.535a.5.5 0 010 .707l-3.536 3.536zM35.668 16.575a.5.5 0 01-.708 0l-3.535-3.535a.5.5 0 010-.707l3.535-3.536a.5.5 0 01.708 0l3.535 3.536a.5.5 0 010 .707l-3.535 3.535z" fill="#4E5969"/></svg>
\ No newline at end of file
<svg width="48" height="48" viewBox="0 0 48 48" fill="none"><circle cx="24" cy="24" r="7" stroke="#4E5969" stroke-width="4"/><path stroke="#4E5969" stroke-width="4" d="M23 7h2v2h-2zM23 39h2v2h-2zM41 23v2h-2v-2zM9 23v2H7v-2zM36.728 35.314l-1.415 1.414-1.414-1.414 1.414-1.415zM14.1 12.687L12.686 14.1l-1.414-1.414 1.414-1.414zM12.687 36.728l-1.414-1.414 1.414-1.415 1.414 1.415zM35.315 14.1L33.9 12.686l1.414-1.414 1.414 1.414z"/><path fill="#4E5969" d="M23 7h2v2h-2zM23 39h2v2h-2zM41 23v2h-2v-2zM9 23v2H7v-2zM36.728 35.314l-1.415 1.414-1.414-1.414 1.414-1.415zM14.1 12.687L12.686 14.1l-1.414-1.414 1.414-1.414zM12.687 36.728l-1.414-1.414 1.414-1.415 1.414 1.415zM35.315 14.1L33.9 12.686l1.414-1.414 1.414 1.414z"/></svg>
\ No newline at end of file
<svg width="48" height="48" viewBox="0 0 48 48" fill="none"><path d="M5 17h35.586c.89 0 1.337-1.077.707-1.707L33 7M43 31H7.414c-.89 0-1.337 1.077-.707 1.707L15 41" stroke="#4E5969" stroke-width="4"/></svg>
\ No newline at end of file
<svg width="48" height="48" viewBox="0 0 48 48" fill="none"><path d="M11.98 11.703c-6.64 6.64-6.64 17.403 0 24.042a16.922 16.922 0 008.942 4.7M34.603 37.156l1.414-1.415c6.64-6.639 6.64-17.402 0-24.041A16.922 16.922 0 0027.075 7" stroke="#4E5969" stroke-width="4"/><path d="M14.81 11.982l-1.414-1.414-1.414-1.414h2.829v2.828zM33.192 36.02l1.414 1.414 1.414 1.415h-2.828V36.02z" fill="#C4C4C4" stroke="#4E5969" stroke-width="4"/></svg>
\ No newline at end of file
<svg width="48" height="48" viewBox="0 0 48 48" fill="none"><path d="M24.835 6.035a1 1 0 01.903-.273l12.964 2.592a1 1 0 01.784.785l2.593 12.963a1 1 0 01-.274.904L21.677 43.133a1 1 0 01-1.414 0L4.707 27.577a1 1 0 010-1.414L24.835 6.035z" stroke="#4E5969" stroke-width="4"/><path d="M31.577 17.346a1 1 0 110-2 1 1 0 010 2z" stroke="#4E5969" stroke-width="4"/><path d="M31.581 17.349a1 1 0 110-2 1 1 0 010 2z" fill="#4E5969" stroke="#4E5969" stroke-width="4"/></svg>
\ No newline at end of file
<svg width="48" height="48" viewBox="0 0 48 48" fill="none"><path d="M23.122 7.227a1 1 0 01.765-.29l10.685.628a1 1 0 01.94.94l.629 10.685a1 1 0 01-.292.765L22.025 33.78a1 1 0 01-1.414 0L9.297 22.466a1 1 0 010-1.414L23.122 7.227z" stroke="#4E5969" stroke-width="4"/><path d="M27.698 15.293a1 1 0 111.414-1.414 1 1 0 01-1.414 1.414z" stroke="#4E5969" stroke-width="4"/><path d="M27.698 15.292a1 1 0 111.414-1.414 1 1 0 01-1.414 1.414z" fill="#4E5969" stroke="#4E5969" stroke-width="4"/><path d="M37.581 28.123l-14.849 14.85a1 1 0 01-1.414 0L8.59 30.243" stroke="#4E5969" stroke-width="4"/></svg>
\ No newline at end of file
<svg width="48" height="48" viewBox="0 0 48 48" fill="none"><path d="M11.778 8.697L5.83 27.394A2 2 0 007.735 30l13.133-.075L19.5 33.5c-.964 2.52-3.172 5.9-1 7.5l1.711 1.419a1 1 0 001.386-.196L31 30h3V8H12.731a1 1 0 00-.953.697z" fill="#4E5969"/><path d="M41 32V6M5.83 27.394l5.948-18.697A1 1 0 0112.731 8H34v22h-3l-9.403 12.223a1 1 0 01-1.386.196L18.5 41c-2.172-1.6.036-4.98 1-7.5l1.368-3.575L7.735 30a2 2 0 01-1.906-2.606z" stroke="#4E5969" stroke-width="4"/></svg>
\ No newline at end of file
<svg width="48" height="48" viewBox="0 0 48 48" fill="none"><path d="M41 31V5M5.83 26.393l5.948-18.696A1 1 0 0112.731 7H34v22h-3l-9.403 12.223a1 1 0 01-1.386.196l-2.535-1.87a6 6 0 01-2.044-6.974L17 29H7.735a2 2 0 01-1.906-2.607z" stroke="#4E5969" stroke-width="4"/></svg>
\ No newline at end of file
<svg width="48" height="48" viewBox="0 0 48 48" fill="none"><path d="M36.222 40.303l5.949-18.697A2 2 0 0040.265 19l-13.133.075L28.5 15.5c.964-2.52 3.172-5.9 1-7.5l-1.711-1.419a1 1 0 00-1.386.196L17 19h-3v22h21.269a1 1 0 00.953-.697z" fill="#4E5969"/><path d="M7 17v26m35.17-21.394l-5.948 18.697a1 1 0 01-.953.697H14V19h3l9.403-12.223a1 1 0 011.386-.196L29.5 8c2.172 1.6-.036 4.98-1 7.5l-1.368 3.575L40.265 19a2 2 0 011.906 2.606z" stroke="#4E5969" stroke-width="4"/></svg>
\ No newline at end of file
<svg width="48" height="48" viewBox="0 0 48 48" fill="none"><path d="M7 17v26m35.17-21.394l-5.948 18.697a1 1 0 01-.953.697H14V19h3l9.403-12.223a1 1 0 011.386-.196l2.535 1.87a6 6 0 012.044 6.974L31 19h9.265a2 2 0 011.906 2.606z" stroke="#4E5969" stroke-width="4"/></svg>
\ No newline at end of file
<svg width="48" height="48" viewBox="0 0 48 48" fill="none"><path d="M27.825 5.203a.1.1 0 01.176.066V21h10.781a.1.1 0 01.076.165L20.177 42.797A.1.1 0 0120 42.73V27H9.219a.1.1 0 01-.075-.165L27.825 5.203z" stroke="#4E5969" stroke-width="4"/></svg>
\ No newline at end of file
<svg width="48" height="48" viewBox="0 0 48 48" fill="none"><path d="M5 41h38M24 28V5M30.453 27L24 34.04 17.547 27h12.906z" stroke="#4E5969" stroke-width="4"/><path d="M24 34l6-7H18l6 7z" fill="#4E5969"/></svg>
\ No newline at end of file
<svg width="48" height="48" viewBox="0 0 48 48" fill="none"><path d="M7 5v38M20 24h23M21 30.454L13.96 24 21 17.547v12.907z" stroke="#4E5969" stroke-width="4"/><path d="M14 24l7 6V18l-7 6z" fill="#4E5969"/></svg>
\ No newline at end of file
<svg width="48" height="48" viewBox="0 0 48 48" fill="none"><path d="M41 43V5M28 24H5M27 17.547L34.04 24 27 30.453V17.547z" stroke="#4E5969" stroke-width="4"/><path d="M34 24l-7-6v12l7-6z" fill="#4E5969"/></svg>
\ No newline at end of file
<svg width="48" height="48" viewBox="0 0 48 48" fill="none"><path d="M43 7H5M24 20v23M17.547 21L24 13.96 30.453 21H17.547z" stroke="#4E5969" stroke-width="4"/><path d="M24 14l-6 7h12l-6-7z" fill="#4E5969"/></svg>
\ No newline at end of file
<svg width="48" height="48" viewBox="0 0 48 48" fill="none"><path d="M19.994 11.036c3.66-3.66 9.094-4.462 13.531-2.406a.1.1 0 01.028.16l-6.488 6.488a1 1 0 000 1.414l4.243 4.243a1 1 0 001.414 0l6.488-6.488a.1.1 0 01.16.028c2.056 4.437 1.254 9.872-2.405 13.531-3.695 3.695-9.2 4.477-13.66 2.346L12.923 40.734a1 1 0 01-1.414 0l-4.243-4.243a1 1 0 010-1.414l10.382-10.382c-2.13-4.46-1.349-9.965 2.346-13.66z" stroke="#4E5969" stroke-width="4"/></svg>
\ No newline at end of file
<svg width="48" height="48" viewBox="0 0 48 48" fill="none"><path d="M6 25c0-9.941 8.059-18 18-18 6.867 0 12.836 3.845 15.87 9.5M41 25h2l-1-1-1 1z" stroke="#4E5969" stroke-width="4"/><path d="M31 34l-2.625-7L25 18h-2l-3.375 9L17 34M28.375 27h-8.75M7 25H5l1 1 1-1z" stroke="#4E5969" stroke-width="4"/><path d="M42 25c0 9.941-8.059 18-18 18-6.867 0-12.836-3.845-15.87-9.5" stroke="#4E5969" stroke-width="4"/></svg>
\ No newline at end of file
<svg width="48" height="48" viewBox="0 0 48 48" fill="none"><path d="M13 22V7h22v15m-22 0c0 6.075 4.925 11 11 11s11-4.925 11-11m-22 0V9m22 13V9M35 9h6v7a6 6 0 01-6 6V9zM13 9H7v7a6 6 0 006 6V9zM24 33v8m-12 0h24" stroke="#4E5969" stroke-width="4"/></svg>
\ No newline at end of file
<svg width="48" height="48" viewBox="0 0 48 48" fill="none"><path d="M9 41h30M13 5v17.5C13 27 15.5 33 24 33s11-5 11-10.5V5" stroke="#4E5969" stroke-width="4"/></svg>
\ No newline at end of file
<svg width="48" height="48" viewBox="0 0 48 48" fill="none"><path d="M8.81 16H29.5C35.851 16 41 21.149 41 27.5S35.851 39 29.5 39H17" stroke="#4E5969" stroke-width="4"/><path d="M15.322 23.78l-7.778-7.778 7.778-7.778" stroke="#4E5969" stroke-width="4"/></svg>
\ No newline at end of file
<svg width="48" height="48" viewBox="0 0 48 48" fill="none"><path d="M43 8H5M43 20H5M43 29L24 41 5 29" stroke="#4E5969" stroke-width="4"/></svg>
\ No newline at end of file
<svg width="48" height="48" viewBox="0 0 48 48" fill="none"><rect x="7" y="21" width="34" height="20" rx="1" stroke="#4E5969" stroke-width="4"/><path d="M44 15v0a9 9 0 00-9-9v0a9 9 0 00-9 9v6M24 35v-8" stroke="#4E5969" stroke-width="4"/></svg>
\ No newline at end of file
<svg width="48" height="48" viewBox="0 0 48 48" fill="none"><path d="M13 24h30M5 11h4m4 26h30M13 11h30M5 24h4M5 37h4" stroke="#4E5969" stroke-width="4"/></svg>
\ No newline at end of file
<svg width="48" height="48" viewBox="0 0 48 48" fill="none"><circle cx="24" cy="24" r="18" stroke="#4E5969" stroke-width="4"/><path d="M15.515 28.485L24 20l8.485 8.485" stroke="#4E5969" stroke-width="4"/></svg>
\ No newline at end of file
<svg width="48" height="48" viewBox="0 0 48 48" fill="none"><path d="M39.6 30.556L24.044 15 8.487 30.556" stroke="#4E5969" stroke-width="4"/></svg>
\ No newline at end of file
<svg width="48" height="48" viewBox="0 0 48 48" fill="none"><path d="M40 35v6H8v-6M14.93 17.071L24.001 8l9.071 9.071M24.002 33.142v-25" stroke="#4E5969" stroke-width="4"/></svg>
\ No newline at end of file
<svg width="48" height="48" viewBox="0 0 48 48" fill="none"><path d="M31 14a7 7 0 11-14 0 7 7 0 0114 0zM36 27v8m0 0v8m0-8h8m-8 0h-8M25 27h-8c-5.523 0-10 4.477-10 10v4h18" stroke="#4E5969" stroke-width="4"/></svg>
\ No newline at end of file
<svg width="48" height="48" viewBox="0 0 48 48" fill="none"><circle cx="18" cy="15" r="7" stroke="#4E5969" stroke-width="4"/><circle cx="34" cy="19" r="4" stroke="#4E5969" stroke-width="4"/><path d="M6 34a6 6 0 016-6h12a6 6 0 016 6v6H6v-6zM34 30h4a4 4 0 014 4v4h-8" stroke="#4E5969" stroke-width="4"/></svg>
\ No newline at end of file
<svg width="48" height="48" viewBox="0 0 48 48" fill="none"><path d="M7 37c0-4.97 4.03-8 9-8h16c4.97 0 9 3.03 9 8v3a1 1 0 01-1 1H8a1 1 0 01-1-1v-3z" stroke="#4E5969" stroke-width="4"/><circle cx="24" cy="15" r="8" stroke="#4E5969" stroke-width="4"/></svg>
\ No newline at end of file
<svg width="48" height="48" viewBox="0 0 48 48" fill="none"><path d="M33 18v12m0-12v-6a1 1 0 00-1-1H7a1 1 0 00-1 1v24a1 1 0 001 1h25a1 1 0 001-1v-6m0-12l8.713-2.614a1 1 0 011.287.958v15.312a1 1 0 01-1.287.958L33 30M11 19h6" stroke="#4E5969" stroke-width="4"/></svg>
\ No newline at end of file
<svg width="48" height="48" viewBox="0 0 48 48" fill="none"><path d="M41 21v1c0 8.837-7.163 16-16 16h-2c-8.837 0-16-7.163-16-16v-1" stroke="#4E5969" stroke-width="4"/><path d="M15 15a9 9 0 1118 0v6a9 9 0 11-18 0v-6zM24 38v6" stroke="#4E5969" stroke-width="4"/></svg>
\ No newline at end of file
<svg width="48" height="48" viewBox="0 0 48 48" fill="none"><path d="M31.586 31.485A9.978 9.978 0 0024 28a9.978 9.978 0 00-7.586 3.485M37.256 25.822A17.953 17.953 0 0024 20a17.953 17.953 0 00-13.256 5.822M43.618 19.449C38.696 14.246 31.727 11 24 11c-7.727 0-14.696 3.246-19.618 8.449" stroke="#4E5969" stroke-width="4"/><path d="M27.535 35.465a5 5 0 00-7.07 0L24 39l3.535-3.535z" fill="#4E5969"/></svg>
\ No newline at end of file
<svg width="48" height="48" viewBox="0 0 48 48" fill="none"><path d="M24 29c6.075 0 11-4.925 11-11S30.075 7 24 7s-11 4.925-11 11 4.925 11 11 11zm0 0v15M15 36h18" stroke="#4E5969" stroke-width="4"/></svg>
\ No newline at end of file
<svg width="48" height="48" viewBox="0 0 48 48" fill="none"><path d="M32.607 32.607A14.953 14.953 0 0037 22c0-8.284-6.716-15-15-15-8.284 0-15 6.716-15 15 0 8.284 6.716 15 15 15 4.142 0 7.892-1.679 10.607-4.393zm0 0L41.5 41.5M29 22H15m7 7V15" stroke="#4E5969" stroke-width="4"/></svg>
\ No newline at end of file
<svg width="48" height="48" viewBox="0 0 48 48" fill="none"><path d="M32.607 32.607A14.953 14.953 0 0037 22c0-8.284-6.716-15-15-15-8.284 0-15 6.716-15 15 0 8.284 6.716 15 15 15 4.142 0 7.892-1.679 10.607-4.393zm0 0L41.5 41.5M29 22H15" stroke="#4E5969" stroke-width="4"/></svg>
\ No newline at end of file
......@@ -33,7 +33,7 @@ body {
width: 164px;
height: 32px;
line-height: 32px;
box-shadow: 6px 0px 20px rgba(34, 87, 188, 0.1);
box-shadow: 6px 0 20px rgba(34, 87, 188, 0.1);
border-radius: 4px;
margin-bottom: 4px;
}
......
......@@ -35,37 +35,37 @@
label: '今天',
value: (): Date[] => [
dayjs().startOf('day').toDate(),
dayjs().toDate()
]
dayjs().toDate(),
],
},
{
label: '昨天',
value: (): Date[] => [
dayjs().subtract(1, 'day').startOf('day').toDate(),
dayjs().subtract(1, 'day').endOf('day').toDate()
]
dayjs().subtract(1, 'day').endOf('day').toDate(),
],
},
{
label: '本周',
value: (): Date[] => [
dayjs().startOf('week').add(1, 'day').toDate(),
dayjs().toDate()
]
dayjs().toDate(),
],
},
{
label: '本月',
value: (): Date[] => [
dayjs().startOf('month').toDate(),
dayjs().toDate()
]
dayjs().toDate(),
],
},
{
label: '本年',
value: (): Date[] => [
dayjs().startOf('year').toDate(),
dayjs().toDate()
]
}
dayjs().toDate(),
],
},
];
});
</script>
......@@ -76,4 +76,4 @@
};
</script>
<style scoped lang="less"></style>
\ No newline at end of file
<style scoped lang="less"></style>
<template>
<div class="icon-body">
<a-input-search
v-model="iconName"
placeholder="请输入图标名称"
allow-clear
style="position: relative"
@clear="filterIcons"
@input="filterIcons"
/>
<div class="icon-list">
<div
v-for="(icon, index) in iconList"
:key="index"
@click="handleSelectedIcon(icon)"
>
<svg-icon :icon-class="icon" style="height: 32px; width: 16px" />
<span>{{ icon }}</span>
</div>
</div>
</div>
</template>
<script lang="ts" setup>
import { ref } from 'vue';
import icons from './requireIcons';
const iconName = ref('');
const iconList = ref(icons);
const emits = defineEmits(['selected']);
/**
* 过滤图标
*/
const filterIcons = () => {
iconList.value = icons;
if (iconName.value) {
iconList.value = icons.filter(
(icon) => icon.indexOf(iconName.value) !== -1
);
}
};
/**
* 选中图标
*
* @param name 图标名称
*/
const handleSelectedIcon = (name: string) => {
emits('selected', name);
document.body.click();
};
/**
* 重置
*/
const reset = () => {
iconName.value = '';
iconList.value = icons;
};
defineExpose({
reset,
});
</script>
<script lang="ts">
export default {
name: 'IconSelect',
};
</script>
<style scoped lang="less">
.icon-body {
width: 100%;
padding: 10px;
.icon-list {
height: 200px;
width: 420px;
overflow-y: scroll;
div {
height: 30px;
line-height: 35px;
margin-bottom: -5px;
cursor: pointer;
width: 33%;
float: left;
}
span {
display: inline-block;
margin-left: 10px;
vertical-align: -0.15em;
fill: currentColor;
overflow: hidden;
}
}
}
</style>
const modules = import.meta.glob('./../../assets/icons/svg/*.svg');
const icons = [] as Array<string>;
// eslint-disable-next-line guard-for-in,no-restricted-syntax
for (const path in modules) {
const p = path.split('assets/icons/svg/')[1].split('.svg')[0];
icons.push(p);
}
export default icons;
......@@ -13,6 +13,8 @@ import Chart from './chart/index.vue';
import Breadcrumb from './breadcrumb/index.vue';
import DateRangePicker from './date-range-picker/index.vue';
import RightToolbar from './right-toolbar/index.vue';
import SvgIcon from './svg-icon/index.vue';
import IconSelect from './icon-select/index.vue';
import download from './crud';
// Manually introduce ECharts modules to reduce packing size
......@@ -40,5 +42,7 @@ export default {
Vue.component('Breadcrumb', Breadcrumb);
Vue.component('DateRangePicker', DateRangePicker);
Vue.component('RightToolbar', RightToolbar);
Vue.component('SvgIcon', SvgIcon);
Vue.component('IconSelect', IconSelect);
},
};
......@@ -25,14 +25,14 @@
* 切换搜索栏(显示或隐藏)
*/
const toggleSearch = () => {
emits("update:showQuery", !props.showQuery);
emits('update:showQuery', !props.showQuery);
};
/**
* 刷新
*/
const handleRefresh = () => {
emits("refresh");
emits('refresh');
};
</script>
......
<template>
<svg :class="svgClass" aria-hidden="true">
<use :xlink:href="iconName" :fill="color" />
</svg>
</template>
<script lang="ts" setup>
import { computed } from 'vue';
const props = defineProps({
iconClass: {
type: String,
required: true,
},
className: {
type: String,
default: '',
},
color: {
type: String,
default: '',
},
});
const iconName = computed(() => `#icon-${props.iconClass}`);
const svgClass = computed(() => {
if (props.className) {
return `svg-icon ${props.className}`;
}
return 'svg-icon';
});
</script>
<script lang="ts">
export default {
name: 'SvgIcon',
};
</script>
<style scoped lang="less">
.sub-el-icon,
.nav-icon {
display: inline-block;
font-size: 15px;
margin-right: 12px;
position: relative;
}
.svg-icon {
width: 1em;
height: 1em;
position: relative;
fill: currentColor;
vertical-align: -2px;
}
</style>
import localeMessageBox from '@/components/message-box/locale/en-US';
import localeLogin from '@/views/login/locale/en-US';
import localeWorkplace from '@/views/dashboard/workplace/locale/en-US';
import localeMonitor from '@/views/arco-design/visualization/monitor/locale/en-US';
import localeDataAnalysis from '@/views/arco-design/visualization/data-analysis/locale/en-US';
import localeMultiDAnalysis from '@/views/arco-design/visualization/multi-dimension-data-analysis/locale/en-US';
import localeRole from '@/views/system/role/locale/en-US';
import localeMenu from '@/views/system/menu/locale/en-US';
import localeDept from '@/views/system/dept/locale/en-US';
import localeOnlineUser from '@/views/monitor/online/locale/en-US';
......@@ -18,21 +11,21 @@ import localeSystemLog from '@/views/monitor/log/system/locale/en-US';
import localeSearchTable from '@/views/arco-design/list/search-table/locale/en-US';
import localeCardList from '@/views/arco-design/list/card/locale/en-US';
import localeStepForm from '@/views/arco-design/form/step/locale/en-US';
import localeGroupForm from '@/views/arco-design/form/group/locale/en-US';
import localeBasicProfile from '@/views/arco-design/profile/basic/locale/en-US';
import localeSuccess from '@/views/arco-design/result/success/locale/en-US';
import localeError from '@/views/arco-design/result/error/locale/en-US';
import locale403 from '@/views/arco-design/exception/403/locale/en-US';
import locale404 from '@/views/arco-design/exception/404/locale/en-US';
import locale500 from '@/views/arco-design/exception/500/locale/en-US';
import localeDataAnalysis from '@/views/arco-design/visualization/data-analysis/locale/en-US';
import localeMultiDAnalysis from '@/views/arco-design/visualization/multi-dimension-data-analysis/locale/en-US';
import localeMonitor from '@/views/arco-design/visualization/monitor/locale/en-US';
import localeMessageBox from '@/components/message-box/locale/en-US';
import localeLogin from '@/views/login/locale/en-US';
import localeUserCenter from '@/views/system/user/center/locale/en-US';
import localeSettings from './en-US/settings';
export default {
......@@ -40,34 +33,25 @@ export default {
'menu.dashboard': 'Dashboard',
'menu.server.dashboard': 'Dashboard-Server',
'menu.server.workplace': 'Workplace-Server',
'menu.server.monitor': 'Monitor-Server',
'menu.system': 'System management',
'menu.monitor': 'Monitor',
'menu.list': 'List',
'menu.form': 'Form',
'menu.profile': 'Profile',
'menu.result': 'Result',
'menu.exception': 'Exception',
'menu.visualization': 'Data Visualization',
'menu.user': 'User Center',
'menu.server.monitor': 'Monitor-Server',
'menu.arcoWebsite': 'Arco Design Vue',
'menu.github': 'GitHub',
'menu.user': 'User Center',
'navbar.docs': 'Docs',
'navbar.action.locale': 'Switch to English',
...localeSettings,
...localeMessageBox,
...localeLogin,
...localeWorkplace,
...localeMonitor,
...localeDataAnalysis,
...localeMultiDAnalysis,
...localeRole,
...localeMenu,
...localeDept,
...localeOnlineUser,
......@@ -85,5 +69,12 @@ export default {
...locale403,
...locale404,
...locale500,
...localeDataAnalysis,
...localeMultiDAnalysis,
...localeMonitor,
...localeMessageBox,
...localeLogin,
...localeUserCenter,
...localeSettings,
};
import localeMessageBox from '@/components/message-box/locale/zh-CN';
import localeLogin from '@/views/login/locale/zh-CN';
import localeWorkplace from '@/views/dashboard/workplace/locale/zh-CN';
import localeMonitor from '@/views/arco-design/visualization/monitor/locale/zh-CN';
import localeDataAnalysis from '@/views/arco-design/visualization/data-analysis/locale/zh-CN';
import localeMultiDAnalysis from '@/views/arco-design/visualization/multi-dimension-data-analysis/locale/zh-CN';
import localeRole from '@/views/system/role/locale/zh-CN';
import localeMenu from '@/views/system/menu/locale/zh-CN';
import localeDept from '@/views/system/dept/locale/zh-CN';
import localeOnlineUser from '@/views/monitor/online/locale/zh-CN';
......@@ -18,21 +11,21 @@ import localeSystemLog from '@/views/monitor/log/system/locale/zh-CN';
import localeSearchTable from '@/views/arco-design/list/search-table/locale/zh-CN';
import localeCardList from '@/views/arco-design/list/card/locale/zh-CN';
import localeStepForm from '@/views/arco-design/form/step/locale/zh-CN';
import localeGroupForm from '@/views/arco-design/form/group/locale/zh-CN';
import localeBasicProfile from '@/views/arco-design/profile/basic/locale/zh-CN';
import localeSuccess from '@/views/arco-design/result/success/locale/zh-CN';
import localeError from '@/views/arco-design/result/error/locale/zh-CN';
import locale403 from '@/views/arco-design/exception/403/locale/zh-CN';
import locale404 from '@/views/arco-design/exception/404/locale/zh-CN';
import locale500 from '@/views/arco-design/exception/500/locale/zh-CN';
import localeDataAnalysis from '@/views/arco-design/visualization/data-analysis/locale/zh-CN';
import localeMultiDAnalysis from '@/views/arco-design/visualization/multi-dimension-data-analysis/locale/zh-CN';
import localeMonitor from '@/views/arco-design/visualization/monitor/locale/zh-CN';
import localeMessageBox from '@/components/message-box/locale/zh-CN';
import localeLogin from '@/views/login/locale/zh-CN';
import localeUserCenter from '@/views/system/user/center/locale/zh-CN';
import localeSettings from './zh-CN/settings';
export default {
......@@ -40,34 +33,25 @@ export default {
'menu.dashboard': '仪表盘',
'menu.server.dashboard': '仪表盘-服务端',
'menu.server.workplace': '工作台-服务端',
'menu.server.monitor': '实时监控-服务端',
'menu.system': '系统管理',
'menu.monitor': '系统监控',
'menu.list': '列表页',
'menu.form': '表单页',
'menu.profile': '详情页',
'menu.result': '结果页',
'menu.exception': '异常页',
'menu.visualization': '数据可视化',
'menu.user': '个人中心',
'menu.server.monitor': '实时监控-服务端',
'menu.arcoWebsite': 'Arco Design Vue',
'menu.github': 'GitHub',
'menu.user': '个人中心',
'navbar.docs': '文档中心',
'navbar.action.locale': '切换为中文',
...localeSettings,
...localeMessageBox,
...localeLogin,
...localeWorkplace,
...localeMonitor,
...localeDataAnalysis,
...localeMultiDAnalysis,
...localeRole,
...localeMenu,
...localeDept,
...localeOnlineUser,
......@@ -85,5 +69,12 @@ export default {
...locale403,
...locale404,
...locale500,
...localeDataAnalysis,
...localeMultiDAnalysis,
...localeMonitor,
...localeMessageBox,
...localeLogin,
...localeUserCenter,
...localeSettings,
};
import { createApp } from 'vue';
import ArcoVue from '@arco-design/web-vue';
import ArcoVueIcon from '@arco-design/web-vue/es/icon';
// eslint-disable-next-line import/no-unresolved
import 'virtual:svg-icons-register';
import globalComponents from '@/components';
import router from './router';
import store from './store';
......
export default {
path: 'https://arco.design/vue/docs/start',
name: 'arcoWebsite',
name: 'ArcoWebsite',
meta: {
locale: 'menu.arcoWebsite',
icon: 'icon-link',
......
......@@ -13,7 +13,7 @@ const Monitor: AppRouteRecordRaw = {
},
children: [
{
path: '/online',
path: '/monitor/online',
name: 'OnlineUser',
component: () => import('@/views/monitor/online/index.vue'),
meta: {
......@@ -23,7 +23,7 @@ const Monitor: AppRouteRecordRaw = {
},
},
{
path: 'log/login',
path: '/monitor/log/login',
name: 'LoginLog',
component: () => import('@/views/monitor/log/login/index.vue'),
meta: {
......@@ -33,7 +33,7 @@ const Monitor: AppRouteRecordRaw = {
},
},
{
path: 'log/operation',
path: '/monitor/log/operation',
name: 'OperationLog',
component: () => import('@/views/monitor/log/operation/index.vue'),
meta: {
......@@ -43,7 +43,7 @@ const Monitor: AppRouteRecordRaw = {
},
},
{
path: 'log/system',
path: '/monitor/log/system',
name: 'SystemLog',
component: () => import('@/views/monitor/log/system/index.vue'),
meta: {
......
......@@ -22,6 +22,16 @@ const System: AppRouteRecordRaw = {
roles: ['*'],
},
},
{
path: '/system/menu',
name: 'Menu',
component: () => import('@/views/system/menu/index.vue'),
meta: {
locale: 'menu.system.menu.list',
requiresAuth: true,
roles: ['*'],
},
},
{
path: '/system/dept',
name: 'Dept',
......
......@@ -163,7 +163,6 @@
<a-modal
:title="title"
:visible="visible"
:width="570"
:mask-closable="false"
unmount-on-close
render-to-body
......@@ -297,7 +296,7 @@
updateDept,
deleteDept,
} from '@/api/system/dept';
import listDeptTree from '@/api/common';
import { listDeptTree } from '@/api/common';
const { proxy } = getCurrentInstance() as any;
......
<template>
<div class="app-container">
<Breadcrumb :items="['menu.system', 'menu.system.menu.list']" />
<a-card class="general-card" :title="$t('menu.system.menu.list')">
<!-- 头部区域 -->
<div class="header">
<!-- 搜索栏 -->
<div v-if="showQuery" class="header-query">
<a-form ref="queryRef" :model="queryParams" layout="inline">
<a-form-item field="menuName" hide-label>
<a-input
v-model="queryParams.menuName"
placeholder="输入菜单名称搜索"
allow-clear
style="width: 150px"
@press-enter="handleQuery"
/>
</a-form-item>
<a-form-item field="status" hide-label>
<a-select
v-model="queryParams.status"
:options="statusOptions"
placeholder="状态搜索"
allow-clear
style="width: 150px"
/>
</a-form-item>
<a-form-item hide-label>
<a-space>
<a-button type="primary" @click="handleQuery">
<template #icon><icon-search /></template>查询
</a-button>
<a-button @click="resetQuery">
<template #icon><icon-refresh /></template>重置
</a-button>
</a-space>
</a-form-item>
</a-form>
</div>
<!-- 操作栏 -->
<div class="header-operation">
<a-row>
<a-col :span="12">
<a-space>
<a-button type="primary" @click="toCreate">
<template #icon><icon-plus /></template>新增
</a-button>
<a-button
type="primary"
status="success"
:disabled="single"
:title="single ? '请选择一条要修改的数据' : ''"
@click="toUpdate(ids[0])"
>
<template #icon><icon-edit /></template>修改
</a-button>
<a-button
type="primary"
status="danger"
:disabled="multiple"
:title="multiple ? '请选择要删除的数据' : ''"
@click="handleBatchDelete"
>
<template #icon><icon-delete /></template>删除
</a-button>
<a-button
:loading="exportLoading"
type="primary"
status="warning"
@click="handleExport"
>
<template #icon><icon-download /></template>导出
</a-button>
<a-button type="secondary" @click="handleExpandAll">
<template #icon><icon-swap :rotate="90" /></template>展开/折叠
</a-button>
</a-space>
</a-col>
<a-col :span="12">
<right-toolbar
v-model:show-query="showQuery"
@refresh="getList"
/>
</a-col>
</a-row>
</div>
</div>
<!-- 列表区域 -->
<a-table
ref="tableRef"
:data="menuList"
:row-selection="{
type: 'checkbox',
showCheckedAll: true,
onlyCurrent: false,
}"
:pagination="false"
:default-expand-all-rows="true"
:hide-expand-button-on-empty="true"
row-key="menuId"
:bordered="false"
:stripe="true"
:loading="loading"
size="large"
@select="handleSelect"
@selection-change="handleSelectionChange"
>
<template #columns>
<a-table-column title="菜单名称" data-index="menuName" />
<a-table-column title="图标" align="center">
<template #cell="{ record }">
<svg-icon :icon-class="record.icon ? record.icon : ''" />
</template>
</a-table-column>
<a-table-column title="排序" align="center" data-index="menuSort" />
<a-table-column title="权限标识" data-index="permission" />
<a-table-column title="组件路径" data-index="component" />
<a-table-column title="状态" align="center">
<template #cell="{ record }">
<a-switch
v-model="record.status"
:checked-value="1"
:unchecked-value="2"
@change="handleChangeStatus(record)"
/>
</template>
</a-table-column>
<a-table-column title="外链" align="center">
<template #cell="{ record }">
<a-tag v-if="record.isExternal" color="green"></a-tag>
<a-tag v-else color="red"></a-tag>
</template>
</a-table-column>
<a-table-column title="缓存" align="center">
<template #cell="{ record }">
<a-tag v-if="record.isCache" color="green"></a-tag>
<a-tag v-else color="red"></a-tag>
</template>
</a-table-column>
<a-table-column title="隐藏" align="center">
<template #cell="{ record }">
<a-tag v-if="record.isHidden" color="green"></a-tag>
<a-tag v-else color="red"></a-tag>
</template>
</a-table-column>
<a-table-column title="创建时间" data-index="createTime" />
<a-table-column title="操作" align="center">
<template #cell="{ record }">
<a-button
v-permission="['admin']"
type="text"
size="small"
title="修改"
@click="toUpdate(record.menuId)"
>
<template #icon><icon-edit /></template>修改
</a-button>
<a-popconfirm
content="确定要删除当前选中的数据吗?如果存在下级菜单则一并删除,此操作不能撤销!"
type="warning"
@ok="handleDelete([record.menuId])"
>
<a-button
v-permission="['admin']"
type="text"
size="small"
title="删除"
>
<template #icon><icon-delete /></template>删除
</a-button>
</a-popconfirm>
</template>
</a-table-column>
</template>
</a-table>
<!-- 表单区域 -->
<a-modal
:title="title"
:visible="visible"
:width="625"
:mask-closable="false"
unmount-on-close
render-to-body
@ok="handleOk"
@cancel="handleCancel"
>
<a-form
ref="formRef"
:model="form"
:rules="rules"
layout="inline"
:label-col-style="{ width: '85px' }"
size="large"
>
<a-form-item label="菜单类型" field="menuType" lab>
<a-radio-group v-model="form.menuType" type="button">
<a-radio :value="1" style="width: 57px">目录</a-radio>
<a-radio :value="2" style="width: 57px">菜单</a-radio>
<a-radio :value="3" style="width: 57px">按钮</a-radio>
</a-radio-group>
</a-form-item>
<a-form-item v-if="form.menuType !== 3" label="菜单图标" field="icon">
<a-popover
v-model:popup-visible="showChooseIcon"
position="bottom"
trigger="click"
>
<a-input
v-model="form.icon"
placeholder="点击选择菜单图标"
readonly
allow-clear
style="width: 473px"
>
<template #prefix>
<svg-icon
v-if="form.icon"
:icon-class="form.icon"
style="height: 32px; width: 16px"
/>
<icon-search v-else />
</template>
</a-input>
<template #content>
<icon-select ref="iconSelectRef" @selected="selected" />
</template>
</a-popover>
</a-form-item>
<a-form-item label="菜单名称" field="menuName">
<a-input
v-model="form.menuName"
placeholder="请输入菜单名称"
style="width: 182px"
/>
</a-form-item>
<a-form-item label="菜单排序" field="menuSort">
<a-input-number
v-model="form.menuSort"
placeholder="请输入菜单排序"
:min="1"
mode="button"
style="width: 182px"
/>
</a-form-item>
<a-form-item
v-if="form.menuType !== 1"
label="权限标识"
field="permission"
>
<a-input
v-model="form.permission"
placeholder="请输入权限标识"
style="width: 182px"
/>
</a-form-item>
<a-form-item v-if="form.menuType !== 3" label="路由地址" field="path">
<a-input
v-model="form.path"
placeholder="请输入路由地址"
style="width: 473px"
/>
</a-form-item>
<a-form-item
v-if="!form.isExternal && form.menuType === 2"
label="组件名称"
field="name"
>
<a-input
v-model="form.name"
placeholder="请输入组件名称"
style="width: 182px"
/>
</a-form-item>
<a-form-item
v-if="!form.isExternal && form.menuType === 2"
label="组件路径"
field="component"
>
<a-input
v-model="form.component"
placeholder="请输入组件路径"
style="width: 182px"
/>
</a-form-item>
<br />
<a-form-item
v-if="form.menuType !== 3"
label="是否外链"
field="isExternal"
>
<a-radio-group v-model="form.isExternal" type="button">
<a-radio :value="true"></a-radio>
<a-radio :value="false"></a-radio>
</a-radio-group>
</a-form-item>
<a-form-item
v-if="form.menuType === 2"
label="是否缓存"
field="isCache"
>
<a-radio-group v-model="form.isCache" type="button">
<a-radio :value="true"></a-radio>
<a-radio :value="false"></a-radio>
</a-radio-group>
</a-form-item>
<a-form-item
v-if="form.menuType !== 3"
label="是否隐藏"
field="isHidden"
>
<a-radio-group v-model="form.isHidden" type="button">
<a-radio :value="true"></a-radio>
<a-radio :value="false"></a-radio>
</a-radio-group>
</a-form-item>
<a-form-item label="上级菜单" field="parentId">
<a-tree-select
v-model="form.parentId"
:data="treeData"
placeholder="请选择上级菜单"
allow-clear
allow-search
:filter-tree-node="filterMenuTree"
:fallback-option="false"
style="width: 473px"
/>
</a-form-item>
</a-form>
</a-modal>
</a-card>
</div>
</template>
<script lang="ts" setup>
import { getCurrentInstance, ref, toRefs, reactive } from 'vue';
import {
SelectOptionData,
TreeNodeData,
TableData,
} from '@arco-design/web-vue';
import {
MenuRecord,
MenuParam,
listMenu,
getMenu,
createMenu,
updateMenu,
deleteMenu,
} from '@/api/system/menu';
import { listMenuTree } from '@/api/common';
const { proxy } = getCurrentInstance() as any;
const menuList = ref<MenuRecord[]>([]);
const ids = ref<Array<number>>([]);
const title = ref('');
const single = ref(true);
const multiple = ref(true);
const showQuery = ref(true);
const loading = ref(false);
const exportLoading = ref(false);
const expandAll = ref(false);
const visible = ref(false);
const showChooseIcon = ref(false);
const statusOptions = ref<SelectOptionData[]>([
{ label: '启用', value: 1 },
{ label: '禁用', value: 2 },
]);
const treeData = ref<TreeNodeData[]>();
const data = reactive({
// 查询参数
queryParams: {
menuName: undefined,
status: undefined,
sort: ['parentId,asc', 'menuSort,asc', 'createTime,desc'],
},
// 表单数据
form: {} as MenuRecord,
// 表单验证规则
rules: {
menuName: [{ required: true, message: '请输入菜单名称' }],
path: [{ required: true, message: '请输入路由地址' }],
name: [{ required: true, message: '请输入组件名称' }],
component: [{ required: true, message: '请输入组件路径' }],
permission: [{ required: true, message: '请输入权限标识' }],
menuSort: [{ required: true, message: '请输入菜单排序' }],
},
});
const { queryParams, form, rules } = toRefs(data);
/**
* 查询列表
*
* @param params 查询参数
*/
const getList = (params: MenuParam = { ...queryParams.value }) => {
loading.value = true;
listMenu(params)
.then((res) => {
menuList.value = res.data;
})
.finally(() => {
loading.value = false;
});
};
getList();
/**
* 打开新增对话框
*/
const toCreate = () => {
reset();
listMenuTree({}).then((res) => {
treeData.value = res.data;
});
title.value = '新增菜单';
visible.value = true;
};
/**
* 打开修改对话框
*
* @param id ID
*/
const toUpdate = (id: number) => {
reset();
listMenuTree({}).then((res) => {
treeData.value = res.data;
});
getMenu(id).then((res) => {
form.value = res.data;
title.value = '修改菜单';
visible.value = true;
});
};
/**
* 重置表单
*/
const reset = () => {
form.value = {
menuId: undefined,
menuName: '',
parentId: undefined,
menuType: 1,
path: undefined,
name: undefined,
component: undefined,
icon: undefined,
isExternal: false,
isCache: false,
isHidden: false,
permission: undefined,
menuSort: 999,
status: 1,
};
proxy.$refs.formRef?.resetFields();
};
/**
* 取消
*/
const handleCancel = () => {
visible.value = false;
proxy.$refs.formRef.resetFields();
};
/**
* 确定
*/
const handleOk = () => {
proxy.$refs.formRef.validate((valid: any) => {
if (!valid) {
if (form.value.menuId !== undefined) {
updateMenu(form.value).then((res) => {
handleCancel();
getList();
proxy.$message.success(res.msg);
});
} else {
createMenu(form.value).then((res) => {
handleCancel();
getList();
proxy.$message.success(res.msg);
});
}
}
});
};
/**
* 批量删除
*/
const handleBatchDelete = () => {
if (ids.value.length === 0) {
proxy.$message.info('请选择要删除的数据');
} else {
proxy.$modal.warning({
title: '警告',
titleAlign: 'start',
content:
'确定要删除当前选中的数据吗?如果存在下级菜单则一并删除,此操作不能撤销!',
hideCancel: false,
onOk: () => {
handleDelete(ids.value);
},
});
}
};
/**
* 删除
*
* @param ids ID 列表
*/
const handleDelete = (ids: Array<number>) => {
deleteMenu(ids).then((res) => {
proxy.$message.success(res.msg);
getList();
});
};
/**
* 点击行选择器
*/
const handleSelect = (rowKeys: any, rowKey: any, record: TableData) => {
if (rowKeys.find((key: any) => key === rowKey)) {
if (record.children) {
record.children.forEach((r) => {
proxy.$refs.tableRef.select(r.menuId);
rowKeys.push(r.menuId);
if (r.children) {
handleSelect(rowKeys, rowKey, r);
}
});
}
} else if (record.children) {
record.children.forEach((r) => {
rowKeys.splice(
rowKeys.findIndex((key: number | undefined) => key === r.menuId),
1
);
proxy.$refs.tableRef.select(r.menuId, false);
if (r.children) {
handleSelect(rowKeys, rowKey, r);
}
});
}
};
/**
* 已选择的数据行发生改变
*
* @param rowKeys ID 列表
*/
const handleSelectionChange = (rowKeys: Array<any>) => {
ids.value = rowKeys;
single.value = rowKeys.length !== 1;
multiple.value = !rowKeys.length;
};
/**
* 导出
*/
const handleExport = () => {
if (exportLoading.value) return;
exportLoading.value = true;
proxy
.download('/system/menu/export', { ...queryParams.value }, '菜单数据')
.finally(() => {
exportLoading.value = false;
});
};
/**
* 展开/折叠
*/
const handleExpandAll = () => {
expandAll.value = !expandAll.value;
proxy.$refs.tableRef.expandAll(expandAll.value);
};
/**
* 修改状态
*
* @param record 记录信息
*/
const handleChangeStatus = (record: MenuRecord) => {
const tip = record.status === 1 ? '启用' : '禁用';
updateMenu(record)
.then(() => {
proxy.$message.success(`${tip}成功`);
})
.catch(() => {
record.status = record.status === 1 ? 2 : 1;
});
};
/**
* 过滤菜单树
*
* @param searchValue 搜索值
* @param nodeData 节点值
*/
const filterMenuTree = (searchValue: string, nodeData: TreeNodeData) => {
if (nodeData.title) {
return (
nodeData.title.toLowerCase().indexOf(searchValue.toLowerCase()) > -1
);
}
return false;
};
/**
* 展示下拉图标
*/
const showSelectIcon = () => {
proxy.$refs.iconSelectRef.reset();
showChooseIcon.value = true;
};
/**
* 选择图标
*
* @param name 图标名称
*/
const selected = (name: string) => {
form.value.icon = name;
showChooseIcon.value = false;
};
const hideSelectIcon = () => {
showChooseIcon.value = false;
};
/**
* 查询
*/
const handleQuery = () => {
getList();
};
/**
* 重置
*/
const resetQuery = () => {
proxy.$refs.queryRef.resetFields();
handleQuery();
};
</script>
<script lang="ts">
export default {
// eslint-disable-next-line vue/no-reserved-component-names
name: 'Menu',
};
</script>
<style scoped lang="less"></style>
export default {
'menu.system.menu.list': 'Menu management',
};
export default {
'menu.system.menu.list': '菜单管理',
};
......@@ -181,7 +181,6 @@
<a-modal
:title="title"
:visible="visible"
:width="570"
:mask-closable="false"
unmount-on-close
render-to-body
......@@ -350,7 +349,7 @@
updateRole,
deleteRole,
} from '@/api/system/role';
import listDeptTree from '@/api/common';
import { listDeptTree } from '@/api/common';
const { proxy } = getCurrentInstance() as any;
......
......@@ -1570,6 +1570,11 @@ base@^0.11.1:
mixin-deep "^1.2.0"
pascalcase "^0.1.1"
big.js@^5.2.2:
version "5.2.2"
resolved "https://registry.npmjs.org/big.js/-/big.js-5.2.2.tgz#65f0af382f578bcdc742bd9c281e9cb2d7768328"
integrity sha512-vyL2OymJxmarO8gxMr0mhChsO9QGwhynfuu4+MHTAW6czfq9humCB7rKpUjDd9YUiDPU4mzpyupFSvOClAwbmQ==
bin-build@^3.0.0:
version "3.0.0"
resolved "https://registry.yarnpkg.com/bin-build/-/bin-build-3.0.0.tgz#c5780a25a8a9f966d8244217e6c1f5082a143861"
......@@ -1637,6 +1642,11 @@ bl@^1.0.0:
readable-stream "^2.3.5"
safe-buffer "^5.1.1"
bluebird@^3.5.0:
version "3.7.2"
resolved "https://registry.npmjs.org/bluebird/-/bluebird-3.7.2.tgz#9f229c15be272454ffa973ace0dbee79a1b0c36f"
integrity sha512-XpNj6GDQzdfW+r2Wnn7xiSAd7TM3jzkxGXBGTtWKuSXv1xUV+azxAm8jdWZN06QTQk+2N2XB9jRDkvbmQmcRtg==
boolbase@^1.0.0:
version "1.0.0"
resolved "https://registry.yarnpkg.com/boolbase/-/boolbase-1.0.0.tgz#68dff5fbe60c51eb37725ea9e3ed310dcc1e776e"
......@@ -1657,7 +1667,7 @@ brace-expansion@^2.0.1:
dependencies:
balanced-match "^1.0.0"
braces@^2.3.1:
braces@^2.2.2, braces@^2.3.1:
version "2.3.2"
resolved "https://registry.yarnpkg.com/braces/-/braces-2.3.2.tgz#5979fd3f14cd531565e5fa2df1abfff1dfaee729"
integrity sha512-aNdbnj9P8PjdXU4ybaWLK2IF3jc/EoDYbC7AazW6to3TRsfXxscC9UXOB5iDiEQrkyIbWp2SLQda4+QAa7nc3w==
......@@ -1869,7 +1879,7 @@ ccount@^1.0.0:
resolved "https://registry.yarnpkg.com/ccount/-/ccount-1.1.0.tgz#246687debb6014735131be8abab2d93898f8d043"
integrity sha512-vlNK021QdI7PNeiUh/lKkC/mNHHfV0m/Ad5JoI0TYtlBnJAslM/JIkm/tGC88bkLIwO6OQ5uV6ztS6kVAtCDlg==
chalk@^1.0.0:
chalk@^1.0.0, chalk@^1.1.3:
version "1.1.3"
resolved "https://registry.yarnpkg.com/chalk/-/chalk-1.1.3.tgz#a8115c55e4a702fe4d150abd3872822a7e09fc98"
integrity sha512-U3lRVLMSlsCfjqYPbLyVv11M9CPW4I728d6TCKMAOJueEeB9/8o+eSsMnxPJD+Q+K909sdESg7C+tIkoH6on1A==
......@@ -2012,6 +2022,11 @@ clone-response@1.0.2:
dependencies:
mimic-response "^1.0.0"
clone@^2.1.1:
version "2.1.2"
resolved "https://registry.npmjs.org/clone/-/clone-2.1.2.tgz#1b7f4b9f591f1e8f83670401600345a02887435f"
integrity sha512-3Pe/CF1Nn94hyhIYpjtiLhdCoEoz0DqQ+988E9gmeEdQZlojxnOb74wctFyuwWQHzqyf9X7C7MG8juUpqBJT8w==
collapse-white-space@^1.0.2:
version "1.0.6"
resolved "https://registry.yarnpkg.com/collapse-white-space/-/collapse-white-space-1.0.6.tgz#e63629c0016665792060dbbeb79c42239d2c5287"
......@@ -2203,6 +2218,14 @@ core-util-is@~1.0.0:
resolved "https://registry.yarnpkg.com/core-util-is/-/core-util-is-1.0.3.tgz#a6042d3634c2b27e9328f837b965fac83808db85"
integrity sha512-ZQBvi1DcpJ4GDqanjucZ2Hj3wEO5pZDS89BWbkcrvdxksJorwUDDZamX9ldFkp9aw2lmBDLgkObEA4DWNJ9FYQ==
cors@^2.8.5:
version "2.8.5"
resolved "https://registry.npmjs.org/cors/-/cors-2.8.5.tgz#eac11da51592dd86b9f06f6e7ac293b3df875d29"
integrity sha512-KIHbLJqu73RGr/hnbrO9uBeixNGuvSQjul/jdFvS/KFSIH1hWVd1ng7zOHx+YrEfInLG7q4n6GHQ9cDtxv/P6g==
dependencies:
object-assign "^4"
vary "^1"
cosmiconfig-typescript-loader@^4.0.0:
version "4.3.0"
resolved "https://registry.yarnpkg.com/cosmiconfig-typescript-loader/-/cosmiconfig-typescript-loader-4.3.0.tgz#c4259ce474c9df0f32274ed162c0447c951ef073"
......@@ -2700,6 +2723,11 @@ emoji-regex@^9.2.2:
resolved "https://registry.yarnpkg.com/emoji-regex/-/emoji-regex-9.2.2.tgz#840c8803b0d8047f4ff0cf963176b32d4ef3ed72"
integrity sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==
emojis-list@^3.0.0:
version "3.0.0"
resolved "https://registry.npmjs.org/emojis-list/-/emojis-list-3.0.0.tgz#5570662046ad29e2e916e71aae260abdff4f6a78"
integrity sha512-/kyM18EfinwXZbno9FyUGeFh87KC8HRQBQGildHZbEuRyWFOmv1U10o9BBp8XVZDVNNuQKyIGIu5ZYAAXJ0V2Q==
end-of-stream@^1.0.0, end-of-stream@^1.1.0:
version "1.4.4"
resolved "https://registry.yarnpkg.com/end-of-stream/-/end-of-stream-1.4.4.tgz#5ae64a5f45057baf3626ec14da0ca5e4b2431eb0"
......@@ -3056,7 +3084,7 @@ escalade@^3.1.1:
resolved "https://registry.yarnpkg.com/escalade/-/escalade-3.1.1.tgz#d8cfdc7000965c5a0174b4a82eaa5c0552742e40"
integrity sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw==
escape-string-regexp@^1.0.2, escape-string-regexp@^1.0.5:
escape-string-regexp@1.0.5, escape-string-regexp@^1.0.2, escape-string-regexp@^1.0.5:
version "1.0.5"
resolved "https://registry.yarnpkg.com/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz#1b61c0562190a8dff6ae3bb2cf0200ca130b86d4"
integrity sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==
......@@ -3274,6 +3302,11 @@ esutils@^2.0.2:
resolved "https://registry.yarnpkg.com/esutils/-/esutils-2.0.3.tgz#74d2eb4de0b8da1293711910d50775b9b710ef64"
integrity sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==
etag@^1.8.1:
version "1.8.1"
resolved "https://registry.npmjs.org/etag/-/etag-1.8.1.tgz#41ae2eeb65efa62268aebfea83ac7d79299b0887"
integrity sha512-aIL5Fx7mawVa300al2BnEE4iNvo1qETxLrPI/o05L7z6go7fCw1J6EQmbK4FmJ2AS7kgVF/KEZWufBfdClMcPg==
exec-buffer@^3.0.0:
version "3.2.0"
resolved "https://registry.yarnpkg.com/exec-buffer/-/exec-buffer-3.2.0.tgz#b1686dbd904c7cf982e652c1f5a79b1e5573082b"
......@@ -3418,7 +3451,7 @@ extend@^3.0.0:
resolved "https://registry.yarnpkg.com/extend/-/extend-3.0.2.tgz#f8b1136b4071fbd8eb140aff858b1019ec2915fa"
integrity sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g==
extglob@^2.0.4:
extglob@^2.0.2, extglob@^2.0.4:
version "2.0.4"
resolved "https://registry.yarnpkg.com/extglob/-/extglob-2.0.4.tgz#ad00fe4dc612a9232e8718711dc5cb5ab0285543"
integrity sha512-Nmb6QXkELsuBr24CJSkilo6UHHgbekK5UiZgfE6UHD3Eb27YC6oD+bhcT+tJ6cl8dmsgdQxnWlcry8ksBIBLpw==
......@@ -4059,6 +4092,11 @@ has-bigints@^1.0.1, has-bigints@^1.0.2:
resolved "https://registry.yarnpkg.com/has-bigints/-/has-bigints-1.0.2.tgz#0871bd3e3d51626f6ca0966668ba35d5602d6eaa"
integrity sha512-tSvCKtBr9lkF0Ex0aQiP9N+OpV4zi2r/Nee5VkRDbaqv35RLYMzbwQfFSZZH0kR+Rd6302UJZ2p/bJCEoR3VoQ==
has-flag@^1.0.0:
version "1.0.0"
resolved "https://registry.npmjs.org/has-flag/-/has-flag-1.0.0.tgz#9d9e793165ce017a00f00418c43f942a7b1d11fa"
integrity sha512-DyYHfIYwAJmjAjSSPKANxI8bFY9YtFrgkAfinBojQ8YJTOuOuav64tMUJv584SES4xl74PmuaevIyaLESHdTAA==
has-flag@^3.0.0:
version "3.0.0"
resolved "https://registry.yarnpkg.com/has-flag/-/has-flag-3.0.0.tgz#b5d454dc2199ae225699f3467e5a07f3b955bafd"
......@@ -4138,7 +4176,7 @@ has@^1.0.3:
dependencies:
function-bind "^1.1.1"
he@^1.2.0:
he@^1.1.1, he@^1.2.0:
version "1.2.0"
resolved "https://registry.yarnpkg.com/he/-/he-1.2.0.tgz#84ae65fa7eafb165fddb61566ae14baf05664f0f"
integrity sha512-F/1DnUGPopORZi0ni+CvrCgHQ5FyEAHRLSApuYWMmrbSwoN2Mn/7k+Gl38gJnR7yyDZk6WLXwiGod1JOWNDKGw==
......@@ -4173,7 +4211,7 @@ html-tags@^3.1.0, html-tags@^3.2.0:
resolved "https://registry.yarnpkg.com/html-tags/-/html-tags-3.2.0.tgz#dbb3518d20b726524e4dd43de397eb0a95726961"
integrity sha512-vy7ClnArOZwCnqZgvv+ddgHgJiAFXe3Ge9ML5/mBctVJoUoYPCdxVucOywjDARn6CVoh3dRSFdPHy2sX80L0Wg==
htmlparser2@^3.10.0:
htmlparser2@^3.10.0, htmlparser2@^3.8.3:
version "3.10.1"
resolved "https://registry.yarnpkg.com/htmlparser2/-/htmlparser2-3.10.1.tgz#bd679dc3f59897b6a34bb10749c855bb53a9392f"
integrity sha512-IgieNijUMbkDovyoKObU1DUhm1iwNYE/fuifEoEHfd1oZKZDaONBSkal7Y01shxsM49R4XaMdGez3WnF9UfiCQ==
......@@ -4237,7 +4275,7 @@ ignore@^5.0.4, ignore@^5.1.1, ignore@^5.2.0, ignore@^5.2.1:
resolved "https://registry.yarnpkg.com/ignore/-/ignore-5.2.1.tgz#c2b1f76cb999ede1502f3a226a9310fdfe88d46c"
integrity sha512-d2qQLzTJ9WxQftPAuEQpSPmKqzxePjzVbpAVv62AQ64NTL+wR4JkrVqR/LqFsFEUsHDAiId52mJteHDFuDkElA==
image-size@~0.5.0:
image-size@^0.5.1, image-size@~0.5.0:
version "0.5.5"
resolved "https://registry.yarnpkg.com/image-size/-/image-size-0.5.5.tgz#09dfd4ab9d20e29eb1c3e80b8990378df9e3cb9c"
integrity sha512-6TDAlDPZxUFCv+fuOkIoXT/V/f3Qbq8e37p+YOiYrUv3v9cc3/6x78VdfPgFVaB9dZYeLUfKgHRebpkm/oP2VQ==
......@@ -4666,7 +4704,7 @@ is-path-inside@^3.0.3:
resolved "https://registry.yarnpkg.com/is-path-inside/-/is-path-inside-3.0.3.tgz#d231362e53a07ff2b0e0ea7fed049161ffd16283"
integrity sha512-Fd4gABb+ycGAmKou8eMftCupSir5lRxqf4aD/vd0cD2qc4HL07OjCeuHMr8Ro4CoMaeCKDB0/ECBOVWjTwUvPQ==
is-plain-obj@^1.0.0, is-plain-obj@^1.1.0:
is-plain-obj@^1.0.0, is-plain-obj@^1.1, is-plain-obj@^1.1.0:
version "1.1.0"
resolved "https://registry.yarnpkg.com/is-plain-obj/-/is-plain-obj-1.1.0.tgz#71a50c8429dfca773c92a390a4a03b39fcd51d3e"
integrity sha512-yvkRyxmFKEOQ4pNXCmJG5AEQNlXJS5LaONXo5/cLdTZdWvsZ1ioJEonLGAosKlMWE8lwUy/bJzMjcw8az73+Fg==
......@@ -4810,7 +4848,7 @@ isexe@^2.0.0:
resolved "https://registry.yarnpkg.com/isexe/-/isexe-2.0.0.tgz#e8fbf374dc556ff8947a10dcb0572d633f2cfa10"
integrity sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==
isobject@^2.0.0:
isobject@^2.0.0, isobject@^2.1.0:
version "2.1.0"
resolved "https://registry.yarnpkg.com/isobject/-/isobject-2.1.0.tgz#f065561096a3f1da2ef46272f815c840d87e0c89"
integrity sha512-+OUdGJlgjOBZDfxnDjYYG6zp487z0JGNQq3cYQYg5f5hKR+syHMsaztzGeml/4kGG55CSpKSpWTY+jYGgsHLgA==
......@@ -4847,6 +4885,11 @@ jpegtran-bin@^6.0.1:
bin-build "^3.0.0"
bin-wrapper "^4.0.0"
js-base64@^2.1.9:
version "2.6.4"
resolved "https://registry.npmjs.org/js-base64/-/js-base64-2.6.4.tgz#f4e686c5de1ea1f867dbcad3d46d969428df98c4"
integrity sha512-pZe//GGmwJndub7ZghVHz7vjb2LgC1m8B07Au3eYqeqv9emhESByMXxaEgkUkEqJe87oBbSniGYoQNIBklc7IQ==
js-sdsl@^4.1.4:
version "4.2.0"
resolved "https://registry.yarnpkg.com/js-sdsl/-/js-sdsl-4.2.0.tgz#278e98b7bea589b8baaf048c20aeb19eb7ad09d0"
......@@ -4974,7 +5017,7 @@ kind-of@^4.0.0:
dependencies:
is-buffer "^1.1.5"
kind-of@^5.0.0:
kind-of@^5.0.0, kind-of@^5.0.2:
version "5.1.0"
resolved "https://registry.yarnpkg.com/kind-of/-/kind-of-5.1.0.tgz#729c91e2d857b7a419a1f9aa65685c4c33f5845d"
integrity sha512-NGEErnH6F2vUuXDh+OlbcKW7/wOcfdRHaZ7VWtqCztfHri/++YKmP51OdWeGPuqCOba6kk2OTe5d02VmTB80Pw==
......@@ -5088,6 +5131,15 @@ load-json-file@^4.0.0:
pify "^3.0.0"
strip-bom "^3.0.0"
loader-utils@^1.1.0:
version "1.4.2"
resolved "https://registry.npmjs.org/loader-utils/-/loader-utils-1.4.2.tgz#29a957f3a63973883eb684f10ffd3d151fec01a3"
integrity sha512-I5d00Pd/jwMD2QCduo657+YM/6L3KZu++pmX9VFncxaxvHcru9jx1lBaFft+r4Mt2jK0Yhp41XlRAihzPxHNCg==
dependencies:
big.js "^5.2.2"
emojis-list "^3.0.0"
json5 "^1.0.1"
local-pkg@^0.4.2:
version "0.4.2"
resolved "https://registry.yarnpkg.com/local-pkg/-/local-pkg-0.4.2.tgz#13107310b77e74a0e513147a131a2ba288176c2f"
......@@ -5428,6 +5480,13 @@ meow@^9.0.0:
type-fest "^0.18.0"
yargs-parser "^20.2.3"
merge-options@1.0.1:
version "1.0.1"
resolved "https://registry.npmjs.org/merge-options/-/merge-options-1.0.1.tgz#2a64b24457becd4e4dc608283247e94ce589aa32"
integrity sha512-iuPV41VWKWBIOpBsjoxjDZw8/GbSfZ2mk7N1453bwMrfzdrIk7EzBd+8UVR6rkw67th7xnk9Dytl3J+lHPdxvg==
dependencies:
is-plain-obj "^1.1"
merge-stream@^2.0.0:
version "2.0.0"
resolved "https://registry.yarnpkg.com/merge-stream/-/merge-stream-2.0.0.tgz#52823629a14dd00c9770fb6ad47dc6310f2c1f60"
......@@ -5438,6 +5497,25 @@ merge2@^1.2.3, merge2@^1.3.0, merge2@^1.4.1:
resolved "https://registry.yarnpkg.com/merge2/-/merge2-1.4.1.tgz#4368892f885e907455a6fd7dc55c0c9d404990ae"
integrity sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==
micromatch@3.1.0:
version "3.1.0"
resolved "https://registry.npmjs.org/micromatch/-/micromatch-3.1.0.tgz#5102d4eaf20b6997d6008e3acfe1c44a3fa815e2"
integrity sha512-3StSelAE+hnRvMs8IdVW7Uhk8CVed5tp+kLLGlBP6WiRAXS21GPGu/Nat4WNPXj2Eoc24B02SaeoyozPMfj0/g==
dependencies:
arr-diff "^4.0.0"
array-unique "^0.3.2"
braces "^2.2.2"
define-property "^1.0.0"
extend-shallow "^2.0.1"
extglob "^2.0.2"
fragment-cache "^0.2.1"
kind-of "^5.0.2"
nanomatch "^1.2.1"
object.pick "^1.3.0"
regex-not "^1.0.0"
snapdragon "^0.8.1"
to-regex "^3.0.1"
micromatch@^3.1.10:
version "3.1.10"
resolved "https://registry.yarnpkg.com/micromatch/-/micromatch-3.1.10.tgz#70859bc95c9840952f359a068a3fc49f9ecfac23"
......@@ -5591,7 +5669,7 @@ nanoid@^3.3.4:
resolved "https://registry.yarnpkg.com/nanoid/-/nanoid-3.3.4.tgz#730b67e3cd09e2deacf03c027c81c9d9dbc5e8ab"
integrity sha512-MqBkQh/OHTS2egovRtLk45wEyNXwF+cokD+1YPf9u5VfJiRdAiRwB2froX5Co9Rh20xs4siNPm8naNotSD6RBw==
nanomatch@^1.2.9:
nanomatch@^1.2.1, nanomatch@^1.2.9:
version "1.2.13"
resolved "https://registry.yarnpkg.com/nanomatch/-/nanomatch-1.2.13.tgz#b87a8aa4fc0de8fe6be88895b38983ff265bd119"
integrity sha512-fpoe2T0RbHwBTBUOftAfBPaDEi06ufaUai0mE6Yn1kacc3SnTErfb/h+X94VXzI64rKFHYImXSvdwGGCmwOqCA==
......@@ -5740,7 +5818,7 @@ number-precision@^1.5.0:
resolved "https://registry.yarnpkg.com/number-precision/-/number-precision-1.6.0.tgz#e309d28f80871d36ac9f6ecd974e13afb1ec0de0"
integrity sha512-05OLPgbgmnixJw+VvEh18yNPUo3iyp4BEWJcrLu4X9W05KmMifN7Mu5exYvQXqxxeNWhvIF+j3Rij+HmddM/hQ==
object-assign@^4.0.1, object-assign@^4.1.0:
object-assign@^4, object-assign@^4.0.1, object-assign@^4.1.0:
version "4.1.1"
resolved "https://registry.yarnpkg.com/object-assign/-/object-assign-4.1.1.tgz#2109adc7965887cfc05cbbd442cac8bfbb360863"
integrity sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==
......@@ -6263,6 +6341,11 @@ postcss-media-query-parser@^0.2.3:
resolved "https://registry.yarnpkg.com/postcss-media-query-parser/-/postcss-media-query-parser-0.2.3.tgz#27b39c6f4d94f81b1a73b8f76351c609e5cef244"
integrity sha512-3sOlxmbKcSHMjlUXQZKQ06jOswE7oVkXPxmZdoB1r5l0q6gTFTQSHxNxOrCccElbW7dxNytifNEo8qidX2Vsig==
postcss-prefix-selector@^1.6.0:
version "1.16.0"
resolved "https://registry.npmjs.org/postcss-prefix-selector/-/postcss-prefix-selector-1.16.0.tgz#ad5b56f9a73a2c090ca7161049632c9d89bcb404"
integrity sha512-rdVMIi7Q4B0XbXqNUEI+Z4E+pueiu/CS5E6vRCQommzdQ/sgsS4dK42U7GX8oJR+TJOtT+Qv3GkNo6iijUMp3Q==
postcss-reporter@^6.0.0:
version "6.0.1"
resolved "https://registry.yarnpkg.com/postcss-reporter/-/postcss-reporter-6.0.1.tgz#7c055120060a97c8837b4e48215661aafb74245f"
......@@ -6350,6 +6433,16 @@ postcss-value-parser@^4.1.0, postcss-value-parser@^4.2.0:
resolved "https://registry.yarnpkg.com/postcss-value-parser/-/postcss-value-parser-4.2.0.tgz#723c09920836ba6d3e5af019f92bc0971c02e514"
integrity sha512-1NNCs6uurfkVbeXG4S8JFT9t19m45ICnif8zWLd5oPSZ50QnwMfK+H3jv408d4jw/7Bttv5axS5IiHoLaVNHeQ==
postcss@^5.2.17:
version "5.2.18"
resolved "https://registry.npmjs.org/postcss/-/postcss-5.2.18.tgz#badfa1497d46244f6390f58b319830d9107853c5"
integrity sha512-zrUjRRe1bpXKsX1qAJNJjqZViErVuyEkMTRrwu4ud4sbTtIBRmtaYDrHmcGgmrbsW3MHfmtIf+vJumgQn+PrXg==
dependencies:
chalk "^1.1.3"
js-base64 "^2.1.9"
source-map "^0.5.6"
supports-color "^3.2.3"
postcss@^7.0.0, postcss@^7.0.1, postcss@^7.0.13, postcss@^7.0.14, postcss@^7.0.2, postcss@^7.0.26, postcss@^7.0.32, postcss@^7.0.6, postcss@^7.0.7:
version "7.0.39"
resolved "https://registry.yarnpkg.com/postcss/-/postcss-7.0.39.tgz#9624375d965630e2e1f2c02a935c82a59cb48309"
......@@ -6376,6 +6469,44 @@ postcss@^8.4.0, postcss@^8.4.18:
picocolors "^1.0.0"
source-map-js "^1.0.2"
posthtml-parser@^0.2.0, posthtml-parser@^0.2.1:
version "0.2.1"
resolved "https://registry.npmjs.org/posthtml-parser/-/posthtml-parser-0.2.1.tgz#35d530de386740c2ba24ff2eb2faf39ccdf271dd"
integrity sha512-nPC53YMqJnc/+1x4fRYFfm81KV2V+G9NZY+hTohpYg64Ay7NemWWcV4UWuy/SgMupqQ3kJ88M/iRfZmSnxT+pw==
dependencies:
htmlparser2 "^3.8.3"
isobject "^2.1.0"
posthtml-rename-id@^1.0:
version "1.0.12"
resolved "https://registry.npmjs.org/posthtml-rename-id/-/posthtml-rename-id-1.0.12.tgz#cf7f6eb37146bf1afac31e68f18c6cc19ae61433"
integrity sha512-UKXf9OF/no8WZo9edRzvuMenb6AD5hDLzIepJW+a4oJT+T/Lx7vfMYWT4aWlGNQh0WMhnUx1ipN9OkZ9q+ddEw==
dependencies:
escape-string-regexp "1.0.5"
posthtml-render@^1.0.5, posthtml-render@^1.0.6:
version "1.4.0"
resolved "https://registry.npmjs.org/posthtml-render/-/posthtml-render-1.4.0.tgz#40114070c45881cacb93347dae3eff53afbcff13"
integrity sha512-W1779iVHGfq0Fvh2PROhCe2QhB8mEErgqzo1wpIt36tCgChafP+hbXIhLDOM8ePJrZcFs0vkNEtdibEWVqChqw==
posthtml-svg-mode@^1.0.3:
version "1.0.3"
resolved "https://registry.npmjs.org/posthtml-svg-mode/-/posthtml-svg-mode-1.0.3.tgz#abd554face81223cab0cb367e18e4efd2a4e74b0"
integrity sha512-hEqw9NHZ9YgJ2/0G7CECOeuLQKZi8HjWLkBaSVtOWjygQ9ZD8P7tqeowYs7WrFdKsWEKG7o+IlsPY8jrr0CJpQ==
dependencies:
merge-options "1.0.1"
posthtml "^0.9.2"
posthtml-parser "^0.2.1"
posthtml-render "^1.0.6"
posthtml@^0.9.2:
version "0.9.2"
resolved "https://registry.npmjs.org/posthtml/-/posthtml-0.9.2.tgz#f4c06db9f67b61fd17c4e256e7e3d9515bf726fd"
integrity sha512-spBB5sgC4cv2YcW03f/IAUN1pgDJWNWD8FzkyY4mArLUMJW+KlQhlmUdKAHQuPfb00Jl5xIfImeOsf6YL8QK7Q==
dependencies:
posthtml-parser "^0.2.0"
posthtml-render "^1.0.5"
prelude-ls@^1.2.1:
version "1.2.1"
resolved "https://registry.yarnpkg.com/prelude-ls/-/prelude-ls-1.2.1.tgz#debc6489d7a6e6b0e7611888cec880337d316396"
......@@ -6441,6 +6572,14 @@ q@^1.5.1:
resolved "https://registry.yarnpkg.com/q/-/q-1.5.1.tgz#7e32f75b41381291d04611f1bf14109ac00651d7"
integrity sha512-kV/CThkXo6xyFEZUugw/+pIOywXcDbFYgSct5cT3gqlbkBE1SJdwy6UQoZvodiWF/ckQLZyDE/Bu1M6gVu5lVw==
query-string@^4.3.2:
version "4.3.4"
resolved "https://registry.npmjs.org/query-string/-/query-string-4.3.4.tgz#bbb693b9ca915c232515b228b1a02b609043dbeb"
integrity sha512-O2XLNDBIg1DnTOa+2XrIwSiXEV8h2KImXUnjhhn2+UsvZ+Es2uyd5CCRTNQlDGbzUQOW3aYCBx9rVA6dzsiY7Q==
dependencies:
object-assign "^4.1.0"
strict-uri-encode "^1.0.0"
query-string@^5.0.1:
version "5.1.1"
resolved "https://registry.yarnpkg.com/query-string/-/query-string-5.1.1.tgz#a78c012b71c17e05f2e3fa2319dd330682efb3cb"
......@@ -7557,6 +7696,13 @@ supports-color@^2.0.0:
resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-2.0.0.tgz#535d045ce6b6363fa40117084629995e9df324c7"
integrity sha512-KKNVtd6pCYgPIKU4cp2733HWYCpplQhddZLBUryaAHou723x+FRzQ5Df824Fj+IyyuiQTRoub4SnIFfIcrp70g==
supports-color@^3.2.3:
version "3.2.3"
resolved "https://registry.npmjs.org/supports-color/-/supports-color-3.2.3.tgz#65ac0504b3954171d8a64946b2ae3cbb8a5f54f6"
integrity sha512-Jds2VIYDrlp5ui7t8abHN2bjAu4LV/q4N2KivFPpGH0lrka0BMq/33AmECUXlKPcHigkNaqfXRENFju+rlcy+A==
dependencies:
has-flag "^1.0.0"
supports-color@^5.3.0:
version "5.5.0"
resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-5.5.0.tgz#e2e69a44ac8772f78a1ec0b35b689df6530efc8f"
......@@ -7584,12 +7730,31 @@ supports-preserve-symlinks-flag@^1.0.0:
resolved "https://registry.yarnpkg.com/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz#6eda4bd344a3c94aea376d4cc31bc77311039e09"
integrity sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==
svg-baker@1.7.0:
version "1.7.0"
resolved "https://registry.npmjs.org/svg-baker/-/svg-baker-1.7.0.tgz#8367f78d875550c52fe4756f7303d5c5d7c2e9a7"
integrity sha512-nibslMbkXOIkqKVrfcncwha45f97fGuAOn1G99YwnwTj8kF9YiM6XexPcUso97NxOm6GsP0SIvYVIosBis1xLg==
dependencies:
bluebird "^3.5.0"
clone "^2.1.1"
he "^1.1.1"
image-size "^0.5.1"
loader-utils "^1.1.0"
merge-options "1.0.1"
micromatch "3.1.0"
postcss "^5.2.17"
postcss-prefix-selector "^1.6.0"
posthtml-rename-id "^1.0"
posthtml-svg-mode "^1.0.3"
query-string "^4.3.2"
traverse "^0.6.6"
svg-tags@^1.0.0:
version "1.0.0"
resolved "https://registry.yarnpkg.com/svg-tags/-/svg-tags-1.0.0.tgz#58f71cee3bd519b59d4b2a843b6c7de64ac04764"
integrity sha512-ovssysQTa+luh7A5Weu3Rta6FJlFBBbInjOh722LIt6klpU2/HtdUbszju/G4devcvk8PGt7FCLv5wftu3THUA==
svgo@^2.1.0, svgo@^2.7.0:
svgo@^2.1.0, svgo@^2.7.0, svgo@^2.8.0:
version "2.8.0"
resolved "https://registry.yarnpkg.com/svgo/-/svgo-2.8.0.tgz#4ff80cce6710dc2795f0c7c74101e6764cfccd24"
integrity sha512-+N/Q9kV1+F+UeWYoSiULYo4xYSDQlTgb+ayMobAXPwMnLvop7oxKMo9OzIrX5x3eS4L4f2UHhc9axXwY8DpChg==
......@@ -7739,6 +7904,11 @@ to-regex@^3.0.1, to-regex@^3.0.2:
regex-not "^1.0.2"
safe-regex "^1.1.0"
traverse@^0.6.6:
version "0.6.7"
resolved "https://registry.npmjs.org/traverse/-/traverse-0.6.7.tgz#46961cd2d57dd8706c36664acde06a248f1173fe"
integrity sha512-/y956gpUo9ZNCb99YjxG7OaslxZWHfCHAUUfshwqOXmxUIvqLjVO581BT+gM59+QV9tFe6/CGG53tsA1Y7RSdg==
trim-newlines@^1.0.0:
version "1.0.0"
resolved "https://registry.yarnpkg.com/trim-newlines/-/trim-newlines-1.0.0.tgz#5887966bb582a4503a41eb524f7d35011815a613"
......@@ -8101,6 +8271,11 @@ validate-npm-package-license@^3.0.1:
spdx-correct "^3.0.0"
spdx-expression-parse "^3.0.0"
vary@^1:
version "1.1.2"
resolved "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz#2299f02c6ded30d4a5961b0b9f74524a18f634fc"
integrity sha512-BNGbWLfd0eUPabhkXUVm0j8uuvREyTh5ovRa/dyow/BqAbZJyC+5fU+IzQOzmAKzYqYRAISoRhdQr3eIZ/PXqg==
vfile-location@^2.0.0:
version "2.0.6"
resolved "https://registry.yarnpkg.com/vfile-location/-/vfile-location-2.0.6.tgz#8a274f39411b8719ea5728802e10d9e0dff1519e"
......@@ -8190,6 +8365,20 @@ vite-plugin-style-import@1.4.1:
fs-extra "^10.0.0"
magic-string "^0.25.7"
vite-plugin-svg-icons@^2.0.1:
version "2.0.1"
resolved "https://registry.npmjs.org/vite-plugin-svg-icons/-/vite-plugin-svg-icons-2.0.1.tgz#7269a0962593509f371b9e2bb344d469db2c6df9"
integrity sha512-6ktD+DhV6Rz3VtedYvBKKVA2eXF+sAQVaKkKLDSqGUfnhqXl3bj5PPkVTl3VexfTuZy66PmINi8Q6eFnVfRUmA==
dependencies:
"@types/svgo" "^2.6.1"
cors "^2.8.5"
debug "^4.3.3"
etag "^1.8.1"
fs-extra "^10.0.0"
pathe "^0.2.0"
svg-baker "1.7.0"
svgo "^2.8.0"
vite-svg-loader@^3.6.0:
version "3.6.0"
resolved "https://registry.yarnpkg.com/vite-svg-loader/-/vite-svg-loader-3.6.0.tgz#71d246cba5e808c7f183a2a56a9dde6856bb0c92"
......
......@@ -34,8 +34,11 @@ import top.charles7c.cnadmin.common.model.query.SortQuery;
import top.charles7c.cnadmin.common.model.vo.R;
import top.charles7c.cnadmin.monitor.annotation.Log;
import top.charles7c.cnadmin.system.model.query.DeptQuery;
import top.charles7c.cnadmin.system.model.query.MenuQuery;
import top.charles7c.cnadmin.system.model.vo.DeptVO;
import top.charles7c.cnadmin.system.model.vo.MenuVO;
import top.charles7c.cnadmin.system.service.DeptService;
import top.charles7c.cnadmin.system.service.MenuService;
/**
* 公共 API
......@@ -50,13 +53,23 @@ import top.charles7c.cnadmin.system.service.DeptService;
public class CommonController {
private final DeptService deptService;
private final MenuService menuService;
@Log(ignore = true)
@Operation(summary = "查询部门树", description = "查询树结构的部门列表")
@GetMapping("/tree/dept")
public R<List<Tree<Long>>> listDeptTree(@Validated DeptQuery query, @Validated SortQuery sortQuery) {
List<DeptVO> list = deptService.list(query, sortQuery);
List<Tree<Long>> deptTreeList = deptService.buildTree(list);
return R.ok(deptTreeList);
List<Tree<Long>> treeList = deptService.buildTree(list);
return R.ok(treeList);
}
@Log(ignore = true)
@Operation(summary = "查询菜单树", description = "查询树结构的菜单列表")
@GetMapping("/tree/menu")
public R<List<Tree<Long>>> listMenuTree(@Validated MenuQuery query, @Validated SortQuery sortQuery) {
List<MenuVO> list = menuService.list(query, sortQuery);
List<Tree<Long>> treeList = menuService.buildTree(list);
return R.ok(treeList);
}
}
/*
* Copyright (c) 2022-present Charles7c Authors. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package top.charles7c.cnadmin.webapi.controller.system;
import static top.charles7c.cnadmin.common.annotation.CrudRequestMapping.Api;
import java.util.List;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.RestController;
import top.charles7c.cnadmin.common.annotation.CrudRequestMapping;
import top.charles7c.cnadmin.common.base.BaseController;
import top.charles7c.cnadmin.common.model.query.SortQuery;
import top.charles7c.cnadmin.common.model.vo.R;
import top.charles7c.cnadmin.system.model.query.MenuQuery;
import top.charles7c.cnadmin.system.model.request.MenuRequest;
import top.charles7c.cnadmin.system.model.vo.MenuVO;
import top.charles7c.cnadmin.system.service.MenuService;
/**
* 菜单管理 API
*
* @author Charles7c
* @since 2023/2/15 20:35
*/
@Tag(name = "菜单管理 API")
@RestController
@CrudRequestMapping(value = "/system/menu", api = {Api.LIST, Api.GET, Api.CREATE, Api.UPDATE, Api.DELETE, Api.EXPORT})
public class MenuController extends BaseController<MenuService, MenuVO, MenuVO, MenuQuery, MenuRequest> {
@Override
@Operation(summary = "查询列表树")
public R<List<MenuVO>> list(@Validated MenuQuery query, @Validated SortQuery sortQuery) {
List<MenuVO> list = baseService.list(query, sortQuery);
return R.ok(baseService.buildListTree(list));
}
}
......@@ -22,3 +22,29 @@ INSERT IGNORE INTO `sys_role` VALUES (2, '测试人员', 'test', 4, NULL, '系
-- 初始化默认用户和角色关联数据
INSERT IGNORE INTO `sys_user_role` VALUES (1, 1);
INSERT IGNORE INTO `sys_user_role` VALUES (2, 2);
-- 初始化默认菜单
INSERT IGNORE INTO `sys_menu` VALUES (1000, '系统管理', 0, 1, 'system', NULL, NULL, 'settings', b'0', b'0', b'0', NULL, 1, 1, 1, NOW(), 1, NOW());
INSERT IGNORE INTO `sys_menu` VALUES (1010, '角色管理', 1000, 2, '/system/role', 'Role', 'system/role/index', NULL, b'0', b'0', b'0', 'system:role:list', 2, 1, 1, NOW(), 1, NOW());
INSERT IGNORE INTO `sys_menu` VALUES (1011, '角色新增', 1010, 3, NULL, NULL, NULL, NULL, b'0', b'0', b'0', 'system:role:create', 1, 1, 1, NOW(), 1, NOW());
INSERT IGNORE INTO `sys_menu` VALUES (1012, '角色修改', 1010, 3, NULL, NULL, NULL, NULL, b'0', b'0', b'0', 'system:role:update', 2, 1, 1, NOW(), 1, NOW());
INSERT IGNORE INTO `sys_menu` VALUES (1013, '角色删除', 1010, 3, NULL, NULL, NULL, NULL, b'0', b'0', b'0', 'system:role:delete', 3, 1, 1, NOW(), 1, NOW());
INSERT IGNORE INTO `sys_menu` VALUES (1014, '角色导出', 1010, 3, NULL, NULL, NULL, NULL, b'0', b'0', b'0', 'system:role:export', 4, 1, 1, NOW(), 1, NOW());
INSERT IGNORE INTO `sys_menu` VALUES (1030, '菜单管理', 1000, 2, '/system/menu', 'Menu', 'system/menu/index', NULL, b'0', b'0', b'0', 'system:menu:list', 3, 1, 1, NOW(), 1, NOW());
INSERT IGNORE INTO `sys_menu` VALUES (1031, '菜单新增', 1030, 3, NULL, NULL, NULL, NULL, b'0', b'0', b'0', 'system:menu:create', 1, 1, 1, NOW(), 1, NOW());
INSERT IGNORE INTO `sys_menu` VALUES (1032, '菜单修改', 1030, 3, NULL, NULL, NULL, NULL, b'0', b'0', b'0', 'system:menu:update', 2, 1, 1, NOW(), 1, NOW());
INSERT IGNORE INTO `sys_menu` VALUES (1033, '菜单删除', 1030, 3, NULL, NULL, NULL, NULL, b'0', b'0', b'0', 'system:menu:delete', 3, 1, 1, NOW(), 1, NOW());
INSERT IGNORE INTO `sys_menu` VALUES (1034, '菜单导出', 1030, 3, NULL, NULL, NULL, NULL, b'0', b'0', b'0', 'system:menu:export', 4, 1, 1, NOW(), 1, NOW());
INSERT IGNORE INTO `sys_menu` VALUES (1050, '部门管理', 1000, 2, '/system/dept', 'Dept', 'system/dept/index', NULL, b'0', b'0', b'0', 'system:dept:list', 4, 1, 1, NOW(), 1, NOW());
INSERT IGNORE INTO `sys_menu` VALUES (1051, '部门新增', 1050, 3, NULL, NULL, NULL, NULL, b'0', b'0', b'0', 'system:dept:create', 1, 1, 1, NOW(), 1, NOW());
INSERT IGNORE INTO `sys_menu` VALUES (1052, '部门修改', 1050, 3, NULL, NULL, NULL, NULL, b'0', b'0', b'0', 'system:dept:update', 2, 1, 1, NOW(), 1, NOW());
INSERT IGNORE INTO `sys_menu` VALUES (1053, '部门删除', 1050, 3, NULL, NULL, NULL, NULL, b'0', b'0', b'0', 'system:dept:delete', 3, 1, 1, NOW(), 1, NOW());
INSERT IGNORE INTO `sys_menu` VALUES (1054, '部门导出', 1050, 3, NULL, NULL, NULL, NULL, b'0', b'0', b'0', 'system:dept:export', 4, 1, 1, NOW(), 1, NOW());
INSERT IGNORE INTO `sys_menu` VALUES (2000, '系统监控', 0, 1, 'monitor', NULL, NULL, 'computer', b'0', b'0', b'0', NULL, 2, 1, 1, NOW(), 1, NOW());
INSERT IGNORE INTO `sys_menu` VALUES (2010, '在线用户', 2000, 2, '/monitor/online', 'OnlineUser', 'monitor/online/index', NULL, b'0', b'0', b'0', 'monitor:online:user:list', 1, 1, 1, NOW(), 1, NOW());
INSERT IGNORE INTO `sys_menu` VALUES (2011, '强退用户', 2010, 3, NULL, NULL, NULL, NULL, b'0', b'0', b'0', 'monitor:online:user:delete', 1, 1, 1, NOW(), 1, NOW());
INSERT IGNORE INTO `sys_menu` VALUES (2030, '登录日志', 2000, 2, '/monitor/log/login', 'LoginLog', 'monitor/log/login/index', NULL, b'0', b'0', b'0', 'monitor:log:login:list', 2, 1, 1, NOW(), 1, NOW());
INSERT IGNORE INTO `sys_menu` VALUES (2050, '操作日志', 2000, 2, '/monitor/log/operation', 'OperationLog', 'monitor/log/operation/index', NULL, b'0', b'0', b'0', 'monitor:log:operation:list', 3, 1, 1, NOW(), 1, NOW());
INSERT IGNORE INTO `sys_menu` VALUES (2070, '系统日志', 2000, 2, '/monitor/log/system', 'SystemLog', 'monitor/log/system/index', NULL, b'0', b'0', b'0', 'monitor:log:system:list', 4, 1, 1, NOW(), 1, NOW());
INSERT IGNORE INTO `sys_menu` VALUES (10000, 'Arco Design Vue', 0, 1, 'https://arco.design/vue/docs/start', NULL, NULL, 'link', b'1', b'0', b'0', NULL, 100, 1, 1, NOW(), 1, NOW());
INSERT IGNORE INTO `sys_menu` VALUES (10001, 'GitHub', 0, 1, 'https://github.com/Charles7c/continew-admin', NULL, NULL, 'github', b'1', b'0', b'0', NULL, 101, 1, 1, NOW(), 1, NOW());
......@@ -67,6 +67,37 @@ CREATE TABLE IF NOT EXISTS `sys_user_role` (
PRIMARY KEY (`user_id`,`role_id`) USING BTREE
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='用户和角色关联表';
CREATE TABLE IF NOT EXISTS `sys_menu` (
`menu_id` bigint(20) unsigned AUTO_INCREMENT COMMENT '菜单ID',
`menu_name` varchar(255) NOT NULL COMMENT '菜单名称',
`parent_id` bigint(20) unsigned DEFAULT 0 COMMENT '上级菜单ID',
`menu_type` tinyint(1) unsigned DEFAULT 1 COMMENT '菜单类型(1目录 2菜单 3按钮)',
`path` varchar(512) DEFAULT NULL COMMENT '路由地址',
`name` varchar(255) DEFAULT NULL COMMENT '组件名称',
`component` varchar(255) DEFAULT NULL COMMENT '组件路径',
`icon` varchar(255) DEFAULT NULL COMMENT '菜单图标',
`is_external` bit(1) DEFAULT b'0' COMMENT '是否外链',
`is_cache` bit(1) DEFAULT b'0' COMMENT '是否缓存',
`is_hidden` bit(1) DEFAULT b'0' COMMENT '是否隐藏',
`permission` varchar(255) DEFAULT NULL COMMENT '权限标识',
`menu_sort` int(11) unsigned DEFAULT 999 COMMENT '菜单排序',
`status` tinyint(1) unsigned DEFAULT 1 COMMENT '状态(1启用 2禁用)',
`create_user` bigint(20) unsigned NOT NULL COMMENT '创建人',
`create_time` datetime NOT NULL COMMENT '创建时间',
`update_user` bigint(20) unsigned NOT NULL COMMENT '修改人',
`update_time` datetime NOT NULL COMMENT '修改时间',
PRIMARY KEY (`menu_id`) USING BTREE,
INDEX `idx_parent_id`(`parent_id`) USING BTREE,
INDEX `idx_create_user`(`create_user`) USING BTREE,
INDEX `idx_update_user`(`update_user`) USING BTREE
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='菜单表';
CREATE TABLE IF NOT EXISTS `sys_role_menu` (
`role_id` bigint(20) unsigned NOT NULL COMMENT '角色ID',
`menu_id` bigint(20) unsigned NOT NULL COMMENT '菜单ID',
PRIMARY KEY (`role_id`,`menu_id`) USING BTREE
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='角色和菜单关联表';
CREATE TABLE IF NOT EXISTS `sys_log` (
`log_id` bigint(20) unsigned AUTO_INCREMENT COMMENT '日志ID',
`description` varchar(255) NOT NULL COMMENT '日志描述',
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册