Compare commits

36 Commits

Author SHA1 Message Date
xuziqiang
9316629faa fix: 登录校验调整 2024-07-05 18:19:03 +08:00
xuziqiang
c7bbc1f003 fix: 角色新增同级 2024-07-05 17:36:24 +08:00
xuziqiang
da80693704 fix: bug修改 2024-07-05 17:29:34 +08:00
xuziqiang
40d93e74aa fix: bug修改 2024-07-05 17:26:31 +08:00
xuziqiang
b2a200486f fix: hx-op路由调整 2024-07-05 14:12:53 +08:00
xuziqiang
228f420bd4 fix: 项目图标调整 2024-07-05 13:51:28 +08:00
xuziqiang
78d49ff16e fix: 设备联调 2024-07-05 12:04:17 +08:00
xuziqiang
4bbb5c5133 fix: 组件调整 2024-07-04 11:19:38 +08:00
xuziqiang
d294c3f07a feat: 设备台账联调 2024-07-03 18:08:02 +08:00
xuziqiang
fba16c75b9 feat: 设备台账联调 2024-07-03 18:07:52 +08:00
xuziqiang
e5cd75c845 feat: 设备台账联调 2024-07-03 17:58:39 +08:00
xuziqiang
be09e531b9 fix:调整路由 2024-07-03 10:50:16 +08:00
xuziqiang
45908dd5c1 fix: 部门角色编辑调整 2024-07-02 14:52:12 +08:00
xuziqiang
7fd1733872 fix: remove useless console 2024-07-01 16:37:37 +08:00
xuziqiang
2d9fc62d86 feat: 解决批量删除之后选中数据清除问题 2024-07-01 16:04:12 +08:00
xuziqiang
7eb8ba79f8 feat: 树loading样式调整 2024-07-01 15:03:45 +08:00
xuziqiang
ef782e90b6 feat: ns-tree-api补充粘性定位 2024-06-28 16:46:07 +08:00
xuziqiang
46398fda22 fix: 抽离接口异常code 2024-06-28 16:07:37 +08:00
xuziqiang
edfc11825d feat: 补充全局自定义权限指令 2024-06-28 14:49:40 +08:00
xuziqiang
9f1620c9f8 fix: 调整placeholder 2024-06-28 11:45:29 +08:00
xuziqiang
9ddeaa59eb fix: childform 警告调整 2024-06-27 17:08:58 +08:00
xuziqiang
8f25d2293c feat: 分组切换 2024-06-27 15:21:14 +08:00
xuziqiang
7c64a6b231 fix: 修改tag右键操作异常 2024-06-27 14:27:04 +08:00
xuziqiang
d6865544d8 fix: 补充超出滚动 2024-06-27 10:59:05 +08:00
xuziqiang
3d2d777644 fix: bug修复 2024-06-26 16:57:42 +08:00
xuziqiang
613e7feaf4 fix: 样式细节调整 2024-06-26 14:58:23 +08:00
xuziqiang
b55ab2353e feat: 部门样式调整 2024-06-26 10:32:45 +08:00
xuziqiang
d654588e65 feat: 用户管理样式调整 2024-06-25 14:52:13 +08:00
xuziqiang
15fce86265 feat: form 组件样式调整 2024-06-25 11:21:35 +08:00
xuziqiang
cecd3a0325 feat;sider样式补充 2024-06-24 15:24:21 +08:00
xuziqiang
0c291263cd feat: 样式调整 2024-06-21 18:15:32 +08:00
xuziqiang
d4f17c4c02 feat: 树搜索调整 2024-06-21 15:56:21 +08:00
xuziqiang
e16ad610e7 feat: table cancel sticky 2024-06-21 15:45:35 +08:00
xuziqiang
fea7abd476 feat: 样式调整 2024-06-21 15:19:28 +08:00
xuziqiang
2ebe536243 Merge branch 'main' of http://123.60.103.97:3000/xuziqiang/SaaS-lib 2024-06-19 18:23:50 +08:00
xuziqiang
ab3960fff8 fix: bug修复 2024-06-19 18:23:49 +08:00
79 changed files with 5547 additions and 4259 deletions

View File

@@ -2,7 +2,7 @@
<html lang="en">
<head>
<meta charset="UTF-8" />
<link rel="icon" href="/favicon.ico" />
<link rel="icon" href="/projectIcon.svg" />
<meta name="referrer" content="never" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<!-- <script type="text/javascript">

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.5 KiB

View File

@@ -0,0 +1,10 @@
<svg xmlns="http://www.w3.org/2000/svg" width="36" height="36" viewBox="0 0 36 36">
<g id="组_23402" data-name="组 23402" transform="translate(-959.12 -738.12)">
<rect id="矩形_16530" data-name="矩形 16530" width="36" height="36" transform="translate(959.12 738.12)" fill="none"/>
<g id="组_23400" data-name="组 23400" transform="translate(960.956 739.956)">
<path id="路径_30576" data-name="路径 30576" d="M207.674,163.872v-9.284a2.553,2.553,0,0,0-1.179-2.063l-8.056-4.634a2.417,2.417,0,0,0-2.358,0l-8.023,4.65a2.38,2.38,0,0,0-1.179,2.063v9.333A2.553,2.553,0,0,0,188.059,166l8.056,4.585a2.417,2.417,0,0,0,2.358,0l8.056-4.634A2.331,2.331,0,0,0,207.674,163.872Z" transform="translate(-181.117 -142.881)" fill="#4388fb" opacity="0.2"/>
<path id="路径_30577" data-name="路径 30577" d="M265.893,314.283h-2.718l-.884-2.653h-4.224l-.884,2.653h-2.718l4.224-11.625h2.9Zm-4.093-4.617-1.326-4.044a9.365,9.365,0,0,1-.2-1.015h-.065a5.831,5.831,0,0,1-.2,1.015l-1.326,4.044Zm8.072-7.073v11.625h-2.456V302.592Z" transform="translate(-246.539 -292.932)" fill="#4388fb"/>
<path id="路径_30578" data-name="路径 30578" d="M36.685,20.095a.9.9,0,0,0-.884.884v2.472a1.535,1.535,0,0,1-.77,1.294L23.7,31.262a1.422,1.422,0,0,1-1.523,0l-11.33-6.517a1.456,1.456,0,0,1-.77-1.294V20.177a2.409,2.409,0,0,0-1-4.6,2.425,2.425,0,0,0-2.423,2.407,2.391,2.391,0,0,0,1.637,2.276v3.176a3.268,3.268,0,0,0,1.637,2.816l11.33,6.582a3.244,3.244,0,0,0,1.637.409,3.471,3.471,0,0,0,1.637-.475l11.281-6.517a3.268,3.268,0,0,0,1.637-2.816V20.963A.76.76,0,0,0,36.685,20.095Zm.884-6.942V10.287a3.268,3.268,0,0,0-1.637-2.816L24.585.954a3.284,3.284,0,0,0-3.291,0L9.947,7.471A3.268,3.268,0,0,0,8.31,10.287v2.227a.884.884,0,1,0,1.768,0V10.287a1.535,1.535,0,0,1,.77-1.294l11.33-6.517a1.422,1.422,0,0,1,1.523,0L34.982,9.059a1.456,1.456,0,0,1,.77,1.294v2.734a2.4,2.4,0,1,0,1.817.065Z" transform="translate(-6.656 -0.512)" fill="#4388fb"/>
</g>
</g>
</svg>

After

Width:  |  Height:  |  Size: 1.9 KiB

View File

@@ -43,192 +43,160 @@
</script>
<style lang="less" scoped>
:deep(.ns-content) {
padding-top: 80px !important;
}
#app {
width: 100%;
height: 100%;
}
// :deep(.ns-content) {
// // padding-top: 80px !important;
// }
// #app {
// width: 100%;
// height: 100%;
// }
:deep(.ns-left-menu .firstMenuItem-selected .ant-menu-title-content) {
background: unset !important;
}
:deep(.ns-left-menu .ant-menu-item-selected .ant-menu-title-content) {
color: #fff !important;
background: @primary-color;
border-radius: 2px;
height: 40px;
line-height: 40px;
a {
color: #ffffff !important;
}
}
// :deep(.ant-menu-title-content) {
// background: unset !important;
// z-index: 9 !important;
// }
// :deep(.ns-left-menu) {
// .ant-menu-item-selected {
// // color: #fff !important;
// background: @primary-color;
// border-radius: 12px;
// // height: 40px;
// // line-height: 40px;
// padding: 5px @ns-gap;
// position: relative;
// a {
// color: @white !important;
// }
// }
:deep(.ant-menu-light.ant-menu-horizontal > .ant-menu-item:hover) {
background: @primary-color;
}
:deep(.ant-menu-inline .ant-menu-submenu-title) {
color: rgba(255, 255, 255, 0.9) !important;
}
:deep(.ns-left-menu .ant-layout-sider-children .ant-menu-sub.ant-menu-inline) {
position: relative;
&::before {
display: flex;
width: 2px;
height: calc(100% - 40px);
position: absolute;
top: 20px;
left: 20px;
content: '';
background-color: rgba(255, 255, 255, 0.2);
}
}
// .ant-menu-item-active,
// .ant-submenu-item-active {
// // color: rgba(@primary-color, 0.1) !important;
// }
// }
//*************************含tab的 list列表样式 */
:deep(.tabListTable) {
.ns-table-title {
text-align: left;
height: 46px;
line-height: 46px;
font-size: 18px;
font-weight: bold;
user-select: text;
padding-left: 16px;
background: #fff;
width: calc(100% + 32px);
margin-left: -16px;
}
.tabs-list {
overflow: visible !important;
}
.ant-tabs-nav {
width: calc(100% + 32px);
margin-left: -16px !important;
background: #fff;
}
.ant-tabs-nav-wrap {
padding: 0 16px;
}
}
// :deep(.ant-menu-light.ant-menu-horizontal > .ant-menu-item:hover) {
// // background: @primary-color;
// }
// // :deep(.ant-menu-inline .ant-menu-submenu-title) {
// // color: rgba(255, 255, 255, 0.9) !important;
// // }
// :deep(.ns-left-menu .ant-layout-sider-children .ant-menu-sub.ant-menu-inline) {
// // position: relative;
// // &::before {
// // display: flex;
// // width: 2px;
// // height: calc(100% - 40px);
// // position: absolute;
// // top: 20px;
// // left: 20px;
// // content: '';
// // background-color: rgba(255, 255, 255, 0.2);
// // }
// }
//*********************详情页返回修改 */
:deep(.nsDetailView) {
min-height: 100%;
height: 100%;
.ns-detail-content {
padding: 0px 24px;
border-top: 16px solid #e5ebf0;
}
.ant-descriptions-item-label {
color: rgba(0, 0, 0, 0.5);
font-family: PingFang SC;
font-size: 14px;
}
.ant-descriptions-item-content {
color: rgba(0, 0, 0, 0.95);
font-family: PingFang SC;
font-size: 14px;
}
.ant-descriptions-title {
&::after {
content: '';
width: 75px;
height: 7px;
display: block;
background: linear-gradient(90deg, #537fff 0%, #fff 82.67%);
margin-left: 2px;
margin-top: -2px;
}
}
// //*************************含tab的 list列表样式 */
// :deep(.tabListTable) {
// .ns-table-title {
// text-align: left;
// height: 46px;
// line-height: 46px;
// font-size: 18px;
// font-weight: bold;
// user-select: text;
// padding-left: 16px;
// background: #fff;
// width: calc(100% + 32px);
// margin-left: -16px;
// }
// .tabs-list {
// overflow: visible !important;
// }
// .ant-tabs-nav {
// width: calc(100% + 32px);
// margin-left: -16px !important;
// background: #fff;
// }
// .ant-tabs-nav-wrap {
// padding: 0 16px;
// }
// }
.ant-descriptions-row > th,
.ant-descriptions-row > td {
padding-bottom: 8px;
}
.ns-page-header {
margin-bottom: 0 !important;
padding-top: 7px !important;
padding-bottom: 7px !important;
width: calc(100% + 32px);
margin-left: -16px;
.title {
cursor: pointer;
font-size: 18px !important;
}
}
.ant-descriptions-header {
margin: 16px 0 16px 0 !important;
// //*********************详情页返回修改 */
// :deep(.nsDetailView) {
// min-height: 100%;
// height: 100%;
// .ns-detail-content {
// padding: 0px 24px;
// border-top: 16px solid #e5ebf0;
// }
// .ant-descriptions-item-label {
// color: rgba(0, 0, 0, 0.5);
// font-family: PingFang SC;
// font-size: 14px;
// }
// .ant-descriptions-item-content {
// color: rgba(0, 0, 0, 0.95);
// font-family: PingFang SC;
// font-size: 14px;
// }
// .ant-descriptions-title {
// &::after {
// content: '';
// width: 75px;
// height: 7px;
// display: block;
// background: linear-gradient(90deg, #537fff 0%, #fff 82.67%);
// margin-left: 2px;
// margin-top: -2px;
// }
// }
.ant-descriptions-title {
line-height: 16px;
font-size: 16px;
}
}
}
// .ant-descriptions-row > th,
// .ant-descriptions-row > td {
// padding-bottom: 8px;
// }
// .ns-page-header {
// margin-bottom: 0 !important;
// padding-top: 7px !important;
// padding-bottom: 7px !important;
// width: calc(100% + 32px);
// margin-left: -16px;
// .title {
// cursor: pointer;
// font-size: 18px !important;
// }
// }
// .ant-descriptions-header {
// margin: 16px 0 16px 0 !important;
:deep(.ns-detail .ant-descriptions-header .descriptions-title) {
&:after {
content: '';
width: 75px;
height: 7px;
display: block;
background: linear-gradient(90deg, @primary-color 0%, #fff 82.67%);
margin-left: 2px;
margin-top: -2px;
}
}
:deep(.ant-descriptions-header .descriptions-title) {
&:after {
content: '';
width: 75px;
height: 7px;
display: block;
background: linear-gradient(90deg, @primary-color 0%, #fff 82.67%);
margin-left: 2px;
margin-top: -2px;
}
}
</style>
<style lang="less">
// 列表弹框样式修改
.listTableModal .ant-modal-title {
font-weight: 600;
}
.listTableModal .ant-modal-body {
padding: 16px !important;
.ant-tabs-nav-wrap {
padding: 0px;
}
.ns-list-table {
border-left: 16px solid #e5ebf0;
border-right: 16px solid #e5ebf0;
border-bottom: 16px solid #e5ebf0;
}
}
:deep(.ant-menu-submenu-title) {
color: #ffffff !important;
}
</style>
<style lang="less">
//************************修改顶部菜单弹框样式
.ant-menu-submenu-placement-bottomLeft {
.ant-menu-submenu {
background: rgb(3 24 53) !important;
}
.ant-menu-sub {
background: rgb(3 24 53) !important;
}
.ant-menu-title-content {
color: #fff !important;
.ns-icon {
margin-right: 7px;
transform: translateY(2px);
}
}
.ant-menu-submenu-arrow {
color: #fff !important;
}
}
// .ant-descriptions-title {
// line-height: 16px;
// font-size: 16px;
// }
// }
// }
// :deep(.ns-detail .ant-descriptions-header .descriptions-title) {
// &:after {
// content: '';
// width: 75px;
// height: 7px;
// display: block;
// background: linear-gradient(90deg, @primary-color 0%, #fff 82.67%);
// margin-left: 2px;
// margin-top: -2px;
// }
// }
// :deep(.ant-descriptions-header .descriptions-title) {
// &:after {
// content: '';
// width: 75px;
// height: 7px;
// display: block;
// background: linear-gradient(90deg, @primary-color 0%, #fff 82.67%);
// margin-left: 2px;
// margin-top: -2px;
// }
// }
</style>

View File

@@ -0,0 +1,11 @@
import { BASE_URL } from './index';
export enum device {
queryDeviceTree = `${BASE_URL}/deviceInfo/queryDeviceTree`, // 左侧树
queryDevicePage = `${BASE_URL}/deviceInfo/queryDevicePage`, // 列表
dropArea = `${BASE_URL}/deviceInfo/dropArea`, // 查询下拉区域
}
export enum group {
queryDeviceGroupTree = `${BASE_URL}/deviceGroup/queryDeviceGroupTree`, // 左侧树
creatOrUpdate = `${BASE_URL}/deviceGroup/creatOrUpdate`, // 左侧树节点新增编辑
}

View File

@@ -4,3 +4,6 @@
export const apiModule = {
parking: ['User', 'CurrentUser', 'Organizational'],
};
export const BASE_URL = '/carbon-smart';
export const dict = `${BASE_URL}/client/dict/listByKey`;

View File

@@ -1,10 +1,13 @@
const BASE_URL = '/carbon-smart';
import { BASE_URL } from './index';
export enum permission {
add = `${BASE_URL}/admin/permission/save`,
queryOrgPermission = `${BASE_URL}/api/dept/queryOrgPermission`,
queryRolePermission = `${BASE_URL}/api/dept/queryRolePermission`,
queryFilterDeptPermission = `${BASE_URL}/api/dept/queryFilterDeptPermission`,
queryDeptPermission = `${BASE_URL}/api/dept/queryDeptPermission`,
queryDeptPermissionFilter = `${BASE_URL}/api/dept/queryDeptPermissionFilter`,
queryRolePermissionFilter = `${BASE_URL}/api/dept/queryRolePermissionFilter`,
}
export enum origanizemanage {

View File

@@ -0,0 +1,88 @@
<template>
<ns-modal
ref="modalRef"
v-bind="extraModalConfig"
destroyOnClose
v-model:visible="visible"
:title="title"
:okButtonProps="buttonProps"
@ok="handleOk">
<ns-form ref="formRef" :schemas="schemas" :model="formData" formLayout="formVertical" />
</ns-modal>
</template>
<script lang="ts" setup>
import { computed, ref, toRefs, watch } from 'vue';
import { HttpRequestConfig, NsMessage, useApi } from '/nerv-lib/saas';
import { useRoute } from 'vue-router';
type Props = {
title?: string;
schemas: Array<any>;
api: string | object | Function;
data?: object;
extraModalConfig?: object;
};
const route = useRoute();
const { httpRequest } = useApi();
const props = withDefaults(defineProps<Props>(), {
title: '新增',
});
const { schemas } = toRefs(props);
const formData = ref();
watch(
() => props?.data,
(val) => {
formData.value = val;
},
{
immediate: true,
deep: true,
},
);
const modalRef = ref();
const formRef = ref();
const visible = ref(false);
const validateResult = computed(() => {
return !formRef.value?.validateResult;
});
const toggle = () => {
visible.value = !visible.value;
};
const setLoading = (loading = true) => {
buttonProps.value.loading = loading;
};
const handleOk = () => {
setLoading(true);
formRef.value
.triggerSubmit()
.then((data: any) => {
const { api } = props;
const requestConfig: HttpRequestConfig = { method: 'POST' };
const { params } = route;
httpRequest({ api, params: data, pathParams: params, requestConfig })
.then(() => {
NsMessage.success('操作成功', 1, () => {
toggle();
});
})
.finally(() => {
setLoading(false);
});
})
.catch(() => {});
};
const buttonProps = ref({
disabled: validateResult,
loading: false,
});
defineExpose({
toggle,
});
</script>
<style lang="less"></style>

View File

@@ -19,13 +19,14 @@ export const appConfig = {
projectType: 'web',
baseApi: '/api',
projectName: '济阳站_AI智能BAS系统',
enablePermissions: true,
enablePermissions: false,
// themeColor: '#eee',
siderPosition: 'left',
baseHeader: '/parkingManage',
baseRouter: '/parkingManage/parkingLotManage',
themeConfig: {
bgImageUrl: `${import.meta.env.VITE_PUBLIC_PATH}/asset/image/login/background.png`,
logoLessUrl: `${import.meta.env.VITE_PUBLIC_PATH}/asset/image/headerIcon.png`,
},
// userCustomRouterGuard: (to, from, next, whiteNameList, authorizationStore, appConfig) => {
// console.log({ to, from, next, whiteNameList, authorizationStore, appConfig }, 'routeConfig');
@@ -37,8 +38,9 @@ export const appConfig = {
headerSlotConfig: {
component: 'NsSelectApi',
componentProps: {
style: { width: '200px' },
style: { width: '200px', color: '#2778FF', marginRight: '10px' },
api: '/carbon-smart/user/login/logInInfo',
size: 'large',
defaultValue: selectDefaultValue,
// autoSelectFirst: true,
placeholder: '请选择',
@@ -90,6 +92,7 @@ export const appConfig = {
permissionVos: 'permissionVos',
});
sessionStorage.setItem('ORGID', info.orgId);
selectDefaultValue.value = info.orgId;
return { data: { ...trD } };
});
},
@@ -107,15 +110,6 @@ export const appConfig = {
// toRouterName: 'NoticeManageIndex',
// },
resourceInfo: {
// application: {
// version: '1.1.74',
// label: '停车业务平台',
// dataScope: {
// scopeMode: 0,
// scopeType: '',
// dataTips: '',
// },
// },
api: permission.add,
},
};

View File

@@ -0,0 +1,9 @@
/**
* Configure and register global directives
*/
import type { App } from 'vue';
import { setupPermissionDirective } from './permission';
export function setupGlobDirectives(app: App) {
setupPermissionDirective(app);
}

View File

@@ -0,0 +1,46 @@
/**
* Global authority directive
* Used for fine-grained control of component permissions
* @Example v-auth="name"
*/
import type { App, Directive, DirectiveBinding } from 'vue';
import { authorizationService } from '/nerv-lib/saas/store/modules/authorization-service';
function isAuth(el: Element, binding: any) {
const { checkPermission, checkAllPermission, checkPermissionRouter } = authorizationService();
const { value, modifiers } = binding;
if (!value) return;
//操作按钮
if (modifiers.op) {
if (!checkPermission(value)) {
el.parentNode?.removeChild(el);
}
}
// 全部
if (modifiers.all) {
if (!checkAllPermission(value)) {
el.parentNode?.removeChild(el);
}
}
// 路由
if (modifiers.route) {
if (!checkPermissionRouter(value)) {
el.parentNode?.removeChild(el);
}
}
}
const mounted = (el: Element, binding: DirectiveBinding<string | string[]>) => {
isAuth(el, binding);
};
const authDirective: Directive = {
mounted,
};
export function setupPermissionDirective(app: App) {
app.directive('auth', authDirective);
}
export default authDirective;

View File

@@ -1,3 +1,5 @@
import { routerConfig } from '/nerv-lib/saas/config/router.config';
export enum ResultEnum {
SUCCESS = 0,
ERROR = 1,
@@ -20,3 +22,11 @@ export enum ContentTypeEnum {
// form-data upload
FORM_DATA = 'multipart/form-data;charset=UTF-8',
}
export const errCodeMap = new Map<number, any>([
[13, ''],
[1, ''],
[11, ''],
[3005, ''],
[10086, () => routerConfig.logout()],
]);

View File

@@ -0,0 +1,8 @@
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="2.5601806640625" height="11.380615234375" viewBox="0 0 2.5601806640625 11.380615234375" fill="none">
<path d="M1.26462 2.52904C1.72366 2.54024 2.15274 2.30174 2.38556 1.90594C2.61838 1.51015 2.61838 1.01924 2.38556 0.623459C2.15274 0.227661 1.72366 -0.0108337 1.26462 0.00037384C0.578369 0.0171204 0.0307617 0.578232 0.0307617 1.26469C0.0307617 1.95116 0.578369 2.51227 1.26462 2.52904Z" fill="#5A5A68" >
</path>
<path d="M0 5.69049C0 6.38898 0.566193 6.9552 1.26471 6.9552C1.96317 6.9552 2.52936 6.38898 2.52936 5.69049C2.52936 4.99204 1.96317 4.42578 1.26471 4.42578C0.566193 4.42578 0 4.99204 0 5.69049Z" fill="#5A5A68" >
</path>
<path d="M1.26471 11.3805C1.9632 11.3805 2.52942 10.8143 2.52942 10.1158C2.52942 9.4173 1.9632 8.85107 1.26471 8.85107C0.566223 8.85107 0 9.4173 0 10.1158C0 10.8143 0.566223 11.3805 1.26471 11.3805Z" fill="#5A5A68" >
</path>
</svg>

After

Width:  |  Height:  |  Size: 961 B

View File

@@ -0,0 +1,4 @@
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="11.989990234375" height="11.1085205078125" viewBox="0 0 11.989990234375 11.1085205078125" fill="none">
<path d="M11.4607 7.93429L10.704 7.93429L10.704 6.36826C10.704 5.93552 10.3055 5.58339 9.81754 5.58339L6.4082 5.58339L6.4082 3.96776L7.62086 3.96776C7.91499 3.96776 8.15565 3.74458 8.15565 3.47179L8.15565 0.495972C8.15565 0.223183 7.91499 0 7.62086 0L4.41207 0C4.11794 0 3.87727 0.223183 3.87727 0.495972L3.87727 3.47179C3.87727 3.74458 4.11794 3.96776 4.41207 3.96776L5.57927 3.96776L5.57927 5.58339L2.18999 5.58339C1.70065 5.58339 1.30357 5.93552 1.30357 6.36826L1.30357 7.93429L0.534798 7.93429C0.240654 7.93429 0 8.15747 0 8.43025L0 10.6125C0 10.8853 0.240654 11.1085 0.534798 11.1085L2.8879 11.1085C3.18204 11.1085 3.4227 10.8853 3.4227 10.6125L3.4227 8.43025C3.4227 8.15747 3.18204 7.93429 2.8879 7.93429L2.13116 7.93429L2.13116 6.37321C2.13651 6.36578 2.15657 6.35213 2.18865 6.35213L5.57793 6.35213L5.57793 7.93429L4.8252 7.93429C4.53107 7.93429 4.29041 8.15747 4.29041 8.43025L4.29041 10.6125C4.29041 10.8853 4.53107 11.1085 4.8252 11.1085L7.17831 11.1085C7.47245 11.1085 7.7131 10.8853 7.7131 10.6125L7.7131 8.43025C7.7131 8.15747 7.47245 7.93429 7.17831 7.93429L6.40553 7.93429L6.40553 6.35213L9.81352 6.35213C9.84561 6.35213 9.86566 6.36578 9.87102 6.37321L9.87102 7.93429L9.10224 7.93429C8.80811 7.93429 8.56744 8.15747 8.56744 8.43026L8.56744 10.6125C8.56744 10.8853 8.80811 11.1085 9.10224 11.1085L11.4553 11.1085C11.7495 11.1085 11.9901 10.8853 11.9901 10.6125L11.9901 8.43026C11.9955 8.15747 11.7548 7.93429 11.4607 7.93429Z" fill="#4388FB" >
</path>
</svg>

After

Width:  |  Height:  |  Size: 1.6 KiB

View File

@@ -0,0 +1,4 @@
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="11.0960693359375" height="11.361328125" viewBox="0 0 11.0960693359375 11.361328125" fill="none">
<path d="M5.97288 0.0889032L10.8515 3.28616C11.0042 3.38656 11.0961 3.55643 11.0961 3.73899L11.0961 10.8194C11.096 11.1182 10.8536 11.3604 10.5548 11.3604L0.541595 11.3604C0.242524 11.3606 1.90735e-06 11.1182 0 10.8191L0 3.74666C0 3.56014 0.0961657 3.38656 0.254683 3.28776L5.38954 0.0820341C5.56864 -0.0296883 5.79635 -0.02711 5.97288 0.0886391L5.97288 0.0889032ZM7.84865 7.26703L6.76599 7.26703C6.31761 7.26703 5.95412 7.63051 5.95412 8.07889L5.95412 9.18401C5.95412 9.63239 6.31761 9.99588 6.76599 9.99588L7.84838 9.99588C8.29677 9.99588 8.66025 9.63239 8.66025 9.18401L8.66025 8.07916C8.66025 7.63078 8.29677 7.2673 7.84838 7.2673L7.84865 7.26703ZM7.84865 3.71945L6.76599 3.71945C6.31761 3.71945 5.95412 4.08293 5.95412 4.53131L5.95412 5.63643C5.95412 6.08481 6.31761 6.4483 6.76599 6.4483L7.84838 6.4483C8.29677 6.4483 8.66025 6.08481 8.66025 5.63643L8.66025 4.53131C8.66025 4.08293 8.29677 3.71945 7.84838 3.71945L7.84865 3.71945Z" fill="#4388FB" >
</path>
</svg>

After

Width:  |  Height:  |  Size: 1.1 KiB

View File

@@ -0,0 +1,4 @@
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="12.0859375" height="10.474609375" viewBox="0 0 12.0859375 10.474609375" fill="none">
<path d="M11.6831 9.66875L11.2802 9.66875L11.2802 4.02865C11.2802 3.14235 10.5551 2.41719 9.66875 2.41719L7.25156 2.41719L7.25156 9.26588C7.25156 9.49149 7.0743 9.66875 6.8487 9.66875C6.62309 9.66875 6.44583 9.49149 6.44583 9.26588L6.44583 1.61147C6.44583 0.725159 5.72068 0 4.83437 0L2.41719 0C1.53089 0 0.805729 0.725159 0.805729 1.61147L0.805729 9.66875L0.402865 9.66875C0.17726 9.66875 0 9.84601 0 10.0716C0 10.2972 0.17726 10.4745 0.402865 10.4745L11.6831 10.4745C11.9087 10.4745 12.0859 10.2972 12.0859 10.0716C12.0859 9.84601 11.9087 9.66875 11.6831 9.66875ZM4.43151 8.0573L2.82005 8.0573C2.59445 8.0573 2.41719 7.88004 2.41719 7.65443C2.41719 7.42883 2.59445 7.25156 2.82005 7.25156L4.43151 7.25156C4.65711 7.25156 4.83437 7.42883 4.83437 7.65443C4.83437 7.88004 4.65711 8.0573 4.43151 8.0573ZM4.43151 5.64011L2.82005 5.64011C2.59445 5.64011 2.41719 5.46284 2.41719 5.23724C2.41719 5.01164 2.59445 4.83438 2.82005 4.83438L4.43151 4.83438C4.65711 4.83438 4.83437 5.01164 4.83437 5.23724C4.83437 5.46284 4.65711 5.64011 4.43151 5.64011ZM4.43151 3.22292L2.82005 3.22292C2.59445 3.22292 2.41719 3.04565 2.41719 2.82005C2.41719 2.59445 2.59445 2.41719 2.82005 2.41719L4.43151 2.41719C4.65711 2.41719 4.83437 2.59445 4.83437 2.82005C4.83437 3.04565 4.65711 3.22292 4.43151 3.22292ZM10.0716 8.0573L8.46016 8.0573C8.23455 8.0573 8.05729 7.88004 8.05729 7.65443C8.05729 7.42883 8.23455 7.25156 8.46016 7.25156L10.0716 7.25156C10.2972 7.25156 10.4745 7.42883 10.4745 7.65443C10.4745 7.88004 10.2972 8.0573 10.0716 8.0573ZM10.0716 5.64011L8.46016 5.64011C8.23455 5.64011 8.05729 5.46284 8.05729 5.23724C8.05729 5.01164 8.23455 4.83438 8.46016 4.83438L10.0716 4.83438C10.2972 4.83438 10.4745 5.01164 10.4745 5.23724C10.4745 5.46284 10.2972 5.64011 10.0716 5.64011Z" fill="#4388FB" >
</path>
</svg>

After

Width:  |  Height:  |  Size: 1.9 KiB

View File

@@ -0,0 +1,4 @@
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="15.4384765625" height="14.517333984375" viewBox="0 0 15.4384765625 14.517333984375" fill="currentColor">
<path d="M6.32606 8.89293L1.26484 8.89293C0.569183 8.89293 0 8.31818 0 7.61136L0 1.28157C0 0.574753 0.569183 0 1.26484 0L6.32606 0C7.02172 0 7.5909 0.574753 7.5909 1.28157L7.5909 7.61136C7.5909 8.31631 7.02358 8.89293 6.32606 8.89293ZM14.4415 2.05164L11.2533 2.05164C10.7046 2.05164 10.2564 1.59779 10.2564 1.04163L10.2564 1.01001C10.2564 0.453857 10.7046 0 11.2533 0L14.4415 0C14.9902 0 15.4385 0.453857 15.4385 1.01001L15.4385 1.04163C15.4366 1.59779 14.9865 2.05164 14.4415 2.05164ZM14.4415 5.44624L11.2533 5.44624C10.7046 5.44624 10.2564 4.99239 10.2564 4.43623L10.2564 4.40462C10.2564 3.84846 10.7046 3.39459 11.2533 3.39459L14.4415 3.39459C14.9902 3.39459 15.4385 3.84846 15.4385 4.40462L15.4385 4.43623C15.4366 4.99239 14.9865 5.44624 14.4415 5.44624ZM14.4415 8.84457L11.2533 8.84457C10.7046 8.84457 10.2564 8.39072 10.2564 7.83456L10.2564 7.80295C10.2564 7.24678 10.7046 6.79292 11.2533 6.79292L14.4415 6.79292C14.9902 6.79292 15.4385 7.24678 15.4385 7.80295L15.4385 7.83456C15.4366 8.39072 14.9865 8.84457 14.4415 8.84457ZM14.1718 14.5174L1.26484 14.5174C0.569183 14.5174 0 13.9426 0 13.2358L0 11.4018C0 10.6949 0.569183 10.1202 1.26484 10.1202L14.1718 10.1202C14.8674 10.1202 15.4366 10.6949 15.4366 11.4018L15.4366 13.2358C15.4366 13.9426 14.8674 14.5174 14.1718 14.5174Z" fill="currentColor" >
</path>
</svg>

After

Width:  |  Height:  |  Size: 1.5 KiB

View File

@@ -0,0 +1,4 @@
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="13.654296875" height="14.517303466796875" viewBox="0 0 13.654296875 14.517303466796875" fill="none">
<path d="M7.7187 0.222214L12.8503 2.95256C13.345 3.21599 13.6542 3.73064 13.6546 4.29111L13.6546 10.2367C13.6546 10.8 13.3449 11.3159 12.8474 11.5781L7.71483 14.2969C7.15997 14.5908 6.49557 14.5908 5.94072 14.2969L0.80719 11.5791C0.31076 11.3161 0.000213623 10.8004 0 10.2386L0 4.29208C0 3.73071 0.309738 3.21582 0.803329 2.95158L5.93687 0.222214C6.49385 -0.0740738 7.1617 -0.0740738 7.7187 0.222214ZM9.69315 4.92796L6.83699 6.57527L6.81763 6.57527L3.96243 4.92796C3.63583 4.73979 3.21854 4.85202 3.03038 5.17863C2.84222 5.50523 2.95445 5.92252 3.28105 6.11067L6.14592 7.76573L6.14592 10.6712C6.14592 11.0169 6.40453 11.308 6.74785 11.3487L6.82828 11.3536C7.20512 11.3536 7.5106 11.0481 7.5106 10.6712L7.5106 7.76378L10.3755 6.11067C10.7021 5.92197 10.8139 5.50426 10.6252 5.17766C10.4365 4.85106 10.0188 4.73926 9.69217 4.92795L9.69315 4.92796Z" fill="currentColor" >
</path>
</svg>

After

Width:  |  Height:  |  Size: 1.1 KiB

View File

@@ -0,0 +1,4 @@
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="17.279296875" height="14.6025390625" viewBox="0 0 17.279296875 14.6025390625" fill="currentColor">
<path d="M10.007 14.5797L10.007 10.2525L7.28672 10.2525L7.28672 14.5913C7.20171 14.5957 7.13389 14.6022 7.06605 14.6022C5.78165 14.6022 4.49657 14.6029 3.21208 14.6022C2.77071 14.6022 2.47391 14.3191 2.47196 13.8503C2.46304 12.07 2.46575 10.2881 2.47392 8.50777C2.47392 8.41387 2.54524 8.29381 2.6172 8.22973C3.77963 7.20271 4.94816 6.18224 6.11472 5.16097C6.89124 4.48119 7.66712 3.80132 8.44361 3.12223C8.50395 3.0698 8.56569 3.01889 8.64169 2.95401C9.10501 3.35876 9.56628 3.76126 10.0269 4.16451C11.5463 5.49436 13.0638 6.82713 14.5874 8.15192C14.7512 8.2938 14.8211 8.4379 14.8197 8.66717C14.8101 10.3574 14.8128 12.0481 14.8163 13.7375C14.8169 14.0447 14.745 14.3119 14.4893 14.4815C14.3968 14.5432 14.2796 14.5965 14.1734 14.5972C12.8102 14.6044 11.4469 14.6007 10.0845 14.6C10.0646 14.6001 10.0439 14.5906 10.007 14.5797L10.007 14.5797ZM12.0542 2.59968C12.0542 1.88561 12.0536 1.22617 12.0542 0.567406C12.0549 0.146721 12.1494 0.046257 12.5449 0.0455475C13.159 0.0455475 13.7732 0.0448761 14.3873 0.046257C14.7039 0.0470581 14.8135 0.165627 14.8142 0.521568C14.8157 1.93143 14.819 3.34212 14.8101 4.752C14.8087 4.96963 14.8663 5.10934 15.0273 5.24763C15.7004 5.82269 16.3604 6.41369 17.0239 7.00109C17.3494 7.28937 17.3576 7.42977 17.0835 7.77266C16.9177 7.98081 16.7553 8.19265 16.588 8.40011C16.3824 8.65698 16.2124 8.67303 15.9664 8.45463C13.6107 6.36707 11.2551 4.27808 8.89869 2.18983C8.81712 2.11777 8.73353 2.04712 8.6382 1.96411C8.10844 2.43295 7.58274 2.89661 7.05841 3.36166C5.14625 5.05622 3.23403 6.7514 1.32181 8.44586C1.06275 8.67586 0.901754 8.66209 0.683794 8.39129C0.503304 8.16627 0.324193 7.94017 0.146461 7.71297C-0.0605403 7.44801 -0.0522817 7.27692 0.19785 7.05352C1.26495 6.10507 2.33488 5.16026 3.40405 4.21403C4.82891 2.9526 6.25519 1.6927 7.67941 0.4291C8.32567 -0.143761 8.95488 -0.143761 9.60259 0.433456C10.3681 1.11544 11.1358 1.79462 11.9027 2.47441C11.9391 2.50652 11.9775 2.5363 12.0542 2.59968L12.0542 2.59968Z" fill="currentColor" >
</path>
</svg>

After

Width:  |  Height:  |  Size: 2.1 KiB

View File

@@ -1,6 +0,0 @@
<svg width="20" height="9" viewBox="0 0 20 9" fill="none" xmlns="http://www.w3.org/2000/svg">
<g id="Group 6356610" opacity="0.65">
<path id="Vector" d="M6.89084 5.13637L9.85448 8.1L8.95448 9L4.45446 4.49997L8.95448 -8.86233e-07L9.85448 0.899993L6.89091 3.86357L19.0918 3.86351L19.0918 5.13631L6.89084 5.13637Z" fill="white" fill-opacity="0.3"/>
<path id="Vector_2" d="M1.27246 0.0904379L1.27246 9L-0.000335336 9L-0.000334557 0.0904378L1.27246 0.0904379Z" fill="white" fill-opacity="0.65"/>
</g>
</svg>

Before

Width:  |  Height:  |  Size: 503 B

View File

@@ -0,0 +1,4 @@
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="16.21484375" height="13.50872802734375" viewBox="0 0 16.21484375 13.50872802734375" fill="none">
<path d="M8.10415 0C9.84551 0.0632347 11.2034 1.39415 11.1426 2.97804C11.1467 3.44998 11.0312 3.91644 10.805 4.34118L13.2695 6.18327C13.5772 5.96724 13.9542 5.84864 14.343 5.84555C15.4184 5.88545 16.2552 6.70962 16.2133 7.68764C16.2353 8.15778 16.0502 8.61648 15.6992 8.9622C15.3482 9.30793 14.8601 9.51217 14.343 9.52972C13.8259 9.51217 13.3379 9.30793 12.9868 8.9622C12.6358 8.61648 12.4508 8.15778 12.4727 7.68764C12.4714 7.46591 12.5125 7.24566 12.5942 7.03676L10.1298 5.19468C9.72493 5.55505 9.21346 5.80042 8.65782 5.90082L8.65782 8.75605C9.81002 9.04805 10.5971 10.0142 10.5686 11.1016C10.618 12.3849 9.51517 13.462 8.10415 13.5087C6.69582 13.4587 5.59701 12.3826 5.64643 11.1017C5.61473 10.0153 6.39954 9.04848 7.55049 8.75606L7.55049 5.90083C6.99538 5.79909 6.48431 5.55392 6.07856 5.1947L3.62083 7.03678C3.70258 7.24568 3.74371 7.46592 3.74236 7.68765C3.76428 8.15779 3.57925 8.61649 3.22823 8.96222C2.87721 9.30794 2.38914 9.51219 1.87206 9.52974C1.35497 9.51219 0.866907 9.30794 0.515883 8.96222C0.164859 8.61649 -0.020171 8.15779 0.00174713 7.68765C-0.0401125 6.70964 0.796688 5.88547 1.87206 5.84557C2.26084 5.84866 2.63785 5.96725 2.94563 6.18328L5.40335 4.3412C5.1771 3.91646 5.06158 3.44999 5.06575 2.97805C5.0049 1.39416 6.36279 0.0632407 8.10415 0L8.10415 0Z" fill="currentColor" >
</path>
</svg>

After

Width:  |  Height:  |  Size: 1.5 KiB

View File

@@ -5,8 +5,15 @@ import { apiModule } from '/@/api';
import { appConfig } from '/@/config';
import './theme/global.less';
import { LeftOutlined } from '@ant-design/icons-vue';
import { setupGlobDirectives } from '/@/directives';
const app = createApp(App);
app.component('LeftOutlined', LeftOutlined);
// Register global directive
// 注册全局指令
setupGlobDirectives(app);
saasInit({
app,
apiModule,

View File

@@ -2,13 +2,13 @@ const Base = () => import('/nerv-lib/saas/view/system/layout/content.vue');
const equipmentControl = {
path: '/equipmentControl',
name: 'EquipmentControl',
meta: { title: '设备群控', icon: 'dicizhishou', index: 4 },
meta: { title: '设备群控', icon: 'shebeiqunkong', index: 4 },
redirect: { name: 'LightManage' },
children: [
{
path: 'lightManage',
name: 'LightManage',
meta: { title: '智能照明', hideChildren: true, icon: 'dicizhishou' },
meta: { title: '智能照明', hideChildren: true, icon: 'shebeiqunkong' },
component: Base,
redirect: { name: 'lightManageIndex' },
children: [

View File

@@ -2,13 +2,13 @@ const Base = () => import('/nerv-lib/saas/view/system/layout/content.vue');
const equipment = {
path: '/equipmentManage',
name: 'EquipmentManage',
meta: { title: '设备管理', icon: 'dicizhishou', index: 1 },
meta: { title: '设备管理', icon: 'shebeiguanli', index: 1 },
redirect: { name: 'Ledger' },
children: [
{
path: 'ledger',
name: 'Ledger',
meta: { title: '设备台账', hideChildren: true, icon: 'dicizhishou' },
meta: { title: '设备台账', hideChildren: true, icon: 'shebeiguanli' },
component: Base,
redirect: { name: 'LedgerIndex' },
children: [
@@ -28,7 +28,7 @@ const equipment = {
{
path: 'group',
name: 'Group',
meta: { title: '分组管理', hideChildren: true, icon: 'dicizhishou' },
meta: { title: '分组管理', hideChildren: true, icon: 'shebeiguanli' },
component: Base,
redirect: { name: 'GroupIndex' },
children: [
@@ -44,25 +44,25 @@ const equipment = {
},
],
},
{
path: 'energyMapping',
name: 'EnergyMapping',
meta: { title: '能耗映射', hideChildren: true, icon: 'dicizhishou' },
component: Base,
redirect: { name: 'EnergyMappingIndex' },
children: [
{
path: 'index',
name: 'EnergyMappingIndex',
component: () => import('/@/view/equipmentManage/energyMapping/index.vue'),
meta: {
title: '能耗映射',
keepAlive: true,
// backApi: [],
},
},
],
},
// {
// path: 'energyMapping',
// name: 'EnergyMapping',
// meta: { title: '能耗映射', hideChildren: true, icon: 'shebeiguanli' },
// component: Base,
// redirect: { name: 'EnergyMappingIndex' },
// children: [
// {
// path: 'index',
// name: 'EnergyMappingIndex',
// component: () => import('/@/view/equipmentManage/energyMapping/index.vue'),
// meta: {
// title: '能耗映射',
// keepAlive: true,
// // backApi: [],
// },
// },
// ],
// },
],
};
export default equipment;

View File

@@ -2,13 +2,13 @@ const Base = () => import('/nerv-lib/saas/view/system/layout/content.vue');
const home = {
path: '/home',
name: 'home',
meta: { title: '首页', icon: 'dicizhishou', index: 0, hideChildren: true },
meta: { title: '首页', icon: 'shouye', index: 0, hideChildren: true },
redirect: { name: 'homeIndex' },
children: [
{
path: 'index',
name: 'homeIndex',
meta: { title: '首页', hideChildren: true, icon: 'dicizhishou' },
meta: { title: '首页', hideChildren: true, icon: 'shouye' },
component: () => import('/@/view/developing.vue'),
// redirect: { name: 'homeIndex' },
// children: [

View File

@@ -2,61 +2,34 @@ const Base = () => import('/nerv-lib/saas/view/system/layout/content.vue');
const organizationManage = {
path: '/organizationManage',
name: 'organizationManage',
meta: { title: '组织管理', icon: 'dicizhishou', index: 99 },
meta: { title: '组织管理', icon: 'zuzhiguanli', index: 99 },
redirect: { name: 'UserManage' },
children: [
{
path: 'userManage',
name: 'UserManage',
meta: { title: '用户管理', hideChildren: true, icon: 'dicizhishou' },
meta: { title: '用户管理', hideChildren: true, icon: 'zuzhiguanli' },
component: Base,
redirect: { name: 'userManageIndex' },
redirect: { name: 'UserManageIndex' },
children: [
{
path: 'index',
name: 'userManageIndex',
name: 'UserManageIndex',
component: () => import('/@/view/organizationManage/usermanage/index.vue'),
meta: {
title: '用户管理',
keepAlive: true,
operates: [
{ title: '新增', code: 'userAdd' },
{
title: '导入',
code: 'userImport',
},
{
title: '模板下载',
code: 'userTemDownload',
},
{
title: '导出',
code: 'userExports',
},
{
title: '批量删除',
code: 'userBatchDel',
},
{
title: '编辑',
code: 'userEdit',
},
{
title: '冻结',
code: 'userFrozen',
},
{
title: '解冻',
code: 'userUnFrozen',
},
{
title: '重置密码',
code: 'userCodeReset',
},
{
title: '删除',
code: 'userDelete',
},
{ title: '导入', code: 'userImport' },
{ title: '模板下载', code: 'userTemDownload' },
{ title: '导出', code: 'userExports' },
{ title: '批量删除', code: 'userBatchDel' },
{ title: '编辑', code: 'userEdit' },
{ title: '冻结', code: 'userFrozen' },
{ title: '解冻', code: 'userUnFrozen' },
{ title: '重置密码', code: 'userCodeReset' },
{ title: '删除', code: 'userDelete' },
],
// backApi: [],
},
@@ -66,7 +39,7 @@ const organizationManage = {
{
path: 'authorityManage',
name: 'AuthorityManage',
meta: { title: '部门/权限', hideChildren: true, icon: 'dicizhishou' },
meta: { title: '部门/权限', hideChildren: true, icon: 'zuzhiguanli' },
component: Base,
redirect: { name: 'AuthorityManageIndex' },
children: [

View File

@@ -11,10 +11,11 @@
// .ant-menu-dark.ant-menu-horizontal>.ant-menu-item:hover {
// background-color: #43BB79 !important;
// }
.ant-menu-inline .ant-menu-item,
.ant-menu-inline .ant-menu-submenu-title {
width: 100% !important;
max-width: 100% !important;
transition: none !important;
}
.ns-basic-table .ant-btn:hover {
@@ -46,17 +47,17 @@
}
// header菜单字体样式
.ant-menu-dark.ant-menu-horizontal>.ant-menu-item,
.ant-menu-dark.ant-menu-horizontal>.ant-menu-submenu {
color: #fff;
}
// .ant-menu-dark.ant-menu-horizontal>.ant-menu-item,
// .ant-menu-dark.ant-menu-horizontal>.ant-menu-submenu {
// color: #fff;
// }
.ant-menu-dark .ant-menu-item,
.ant-menu-dark .ant-menu-item-group-title,
.ant-menu-dark .ant-menu-item>a,
.ant-menu-dark .ant-menu-item>span>a {
color: #fff;
}
// .ant-menu-dark .ant-menu-item,
// .ant-menu-dark .ant-menu-item-group-title,
// .ant-menu-dark .ant-menu-item>a,
// .ant-menu-dark .ant-menu-item>span>a {
// color: #fff;
// }
@font-face {
/*给字体命名*/
@@ -111,13 +112,13 @@
.ant-menu-title-content {
svg {
color: #A1ABC2;
// color: #A1ABC2;
}
}
.ant-menu-item-selected {
svg {
color: #D0DBF5;
// color: #D0DBF5;
}
}
@@ -181,3 +182,7 @@
background-color: #AEAEAE;
}
}
#app {
min-width: 1200px;
}

View File

@@ -2,6 +2,8 @@ import { dateUtil } from '/nerv-lib/util/date-util';
import data from './mock.json';
import { http } from '/nerv-lib/util';
import { ref } from 'vue';
import { group } from '/@/api/deviceManage';
import { dict } from '/@/api';
const tableKeyMap = [
{
title: '来源企业',
@@ -30,6 +32,22 @@ const tableKeyMap = [
dataIndex: 'position',
},
];
const tableCalKeyMap = [
{
title: '来源企业',
dataIndex: 'id',
},
{
title: '节点编号',
dataIndex: 'deviceName',
textNumber: 8,
textEllipsis: true,
},
{
title: '节点路径',
dataIndex: 'position',
},
];
const doWnload = (url) => {
const a = document.createElement('a');
document.body.appendChild(a);
@@ -41,50 +59,111 @@ const doWnload = (url) => {
};
const mockData = ref(data.listData);
export const formSchema = [
{
field: 'isCreate',
component: 'NsInput',
show: false,
},
{
field: 'orgId',
component: 'NsInput',
show: false,
},
{
field: 'isCreatSon',
component: 'NsInput',
show: false,
},
{
label: '节点名称',
field: 'pointName',
component: 'NsInput',
componentProps: {
placeholder: '请输入节点名称(必填)',
},
rules: [
{
required: true,
message: '请输入节点名称',
},
],
},
{
label: '节点类型',
field: 'pointType',
component: 'NsSelectApi',
componentProps: {
placeholder: '请选择节点类型(必填)',
api: dict,
params: { dicKey: 'COUNT_POINT' },
immediate: true,
resultField: 'data.COUNT_POINT',
labelField: 'cnValue',
valueField: 'cnValue',
},
rules: [
{
required: true,
message: '请输入节点类型',
},
],
},
];
export const treeConfig = (orgId) => {
return {
defaultExpandAll: true,
header: {
icon: 'orgLink',
title: '能耗分组',
},
params: { orgId },
api: group.queryDeviceGroupTree,
// api: () => {
// return new Promise((resolve) => {
// setTimeout(() => {
// resolve({ data: [{ title: '全部', key: 'all', children: data.data }] });
// }, 100);
// });
// },
transform: (data) => {
return [{ title: '全部', key: 'all', selectable: false, children: data }];
},
formConfig: {
schemas: [
{
field: 'energyType',
label: '',
component: 'NsSelectApi',
autoSubmit: true,
componentProps: {
api: dict,
params: { dicKey: 'ENERGY_TYPE' },
immediate: true,
resultField: 'data.ENERGY_TYPE',
labelField: 'cnValue',
valueField: 'cnValue',
placeholder: '请选择能耗种类',
},
},
{
field: 'pointName',
label: '',
component: 'NsInput',
autoSubmit: true,
componentProps: {
placeholder: '请输入节点名称',
},
},
],
},
};
};
export const tableConfig = (el, elGroup, elFormula) => {
return {
title: '设备台账',
title: '点位信息',
// api: '/carbon_emission/device/getDeviceList',
value: mockData.value,
treeConfig: {
defaultExpandAll: true,
api: () => {
return new Promise((resolve) => {
setTimeout(() => {
resolve(data);
}, 100);
});
},
formConfig: {
schemas: [
{
field: 'type',
label: '',
component: 'NsRadioGroup',
autoSubmit: true,
defaultValue: 1,
componentProps: {
options: [
{ label: '碳排', value: 1 },
{ label: '用电量', value: 2 },
{ label: '用水量', value: 3 },
{ label: '燃气量', value: 4 },
{ label: '供热量', value: 5 },
],
},
},
{
field: 'name',
label: '',
component: 'NsInput',
autoSubmit: true,
componentProps: {
placeholder: '请输入',
},
},
],
},
},
headerActions: [
{
@@ -245,11 +324,108 @@ export const tableConfig = (el, elGroup, elFormula) => {
};
};
export const treeConfig = {
defaultExpandAll: true,
defaultSelectedKeys: ['A008'],
resultField: 'insertData',
api: () => {
return Promise.resolve(data);
},
export const tableConfigCal = (el, elGroup, elFormula) => {
return {
title: '点位信息',
// api: '/carbon_emission/device/getDeviceList',
value: mockData.value,
headerActions: [
{
label: '编辑',
name: 'groupEdit',
type: 'primary',
handle: (a, b) => {
el.value.toggle();
},
},
{
label: '批量删除',
name: 'groupTemDownload',
type: 'primary',
dynamicDisabled: (data: any) => {
return data.list.length === 0;
},
handle: () => {
mockData.value.splice(0, 2);
},
},
{
label: '批量导出',
name: 'groupExports',
type: 'primary',
dynamicDisabled: (data: any) => {
return data.list.length === 0;
},
extra: {
xlsxMap: tableKeyMap,
xlsxName: '分组信息YYYY-MM-DD',
},
},
{
label: '批量导入',
name: 'groupImport',
type: 'primary',
extra: {
// api: props.postImportApi, // 导入接口名
title: '设备信息', // 弹窗title
templateName: 'whiteListUser', // 所使用的文件名称
indexName: '设备id', // 匹配类型字段
message: [
{ label: '1、若必填项未填写则不能进行导入操作' },
{ label: `2、当重复时则更新数据。` },
{ label: '3、数据将从模版的第五行进行导入。' },
{ label: '4、文件导入勿超过5MB。' },
],
},
},
{
label: '模板下载',
name: 'groupTemDownload',
type: 'primary',
handle: () => {
// http.get('/asset/file/whiteListUser.xlsx');
doWnload('/hx-ai-intelligent/asset/file/whiteListUser.xlsx');
},
},
],
columns: tableCalKeyMap,
columnActions: {
title: '操作',
actions: [
{
label: '删除',
name: 'FeedBackDetail',
dynamicParams: ['uuid', 'appealType'],
confirm: true,
handle: () => {
mockData.value.splice(0, 1);
},
},
],
},
formConfig: {
schemas: [
{
field: 'name',
label: '设备名称',
component: 'NsInput',
componentProps: {
placeholder: '请选择公司',
},
},
{
field: 'provider',
component: 'NsInput',
componentProps: {
placeholder: '请输入节点编号',
},
},
],
},
// pagination: { pageSizeOptions: false },
rowKey: 'id',
};
};

View File

@@ -2,20 +2,158 @@
<editDrawer ref="editDrawerRef" />
<editGroup ref="editGroupRef" />
<editFormula ref="editFormulaRef" />
<ns-view-list-table v-bind="config" />
<!-- <ns-modal ref="modalRef" title="新增" v-model:visible="visible">
<ns-form ref="formRef" :schemas="formSchema" :model="formData" formLayout="formVertical" />
</ns-modal> -->
<NsModalFrom ref="modalFormRef" v-bind="nsModalFormConfig" />
<div class="groupContainer">
<div class="tree">
<ns-tree-api v-bind="tConfig" @select="handleSelect">
<template #title="data">
<div class="treeRow">
<span>{{ data.title }}</span>
<a-dropdown>
<ns-icon name="actionMore" size="14" class="actionMore" />
<template #overlay>
<a-menu>
<a-menu-item
v-for="(item, index) in actionList"
:key="index"
@click="item.func(data)">
<span>{{ item.title }}</span>
</a-menu-item>
</a-menu>
</template>
</a-dropdown>
</div>
</template>
</ns-tree-api>
</div>
<ns-view-list-table v-show="defaultType" class="table" v-bind="config" />
<ns-view-list-table v-show="!defaultType" class="table" v-bind="configCal" />
</div>
</template>
<script lang="ts" setup>
import { createVNode, onMounted, ref } from 'vue';
import { tableConfig, treeConfig } from './config';
import { createVNode, nextTick, onMounted, ref } from 'vue';
import { tableConfig, treeConfig, tableConfigCal, formSchema } from './config';
import { useParams } from '/nerv-lib/use';
import editDrawer from './edit.vue';
import editGroup from './editGroup.vue';
import editFormula from './editFormula.vue';
import { NsMessage, NsModal } from '/nerv-lib/component';
import NsModalFrom from '/@/components/ns-modal-form.vue';
import { group } from '/@/api/deviceManage';
type opType = 'up' | 'down';
const { getParams } = useParams();
const modalFormRef = ref();
const editDrawerRef = ref();
const editGroupRef = ref();
const editFormulaRef = ref();
const defaultType = ref(true);
const result = JSON.parse(sessionStorage.getItem('ORGID')!);
const config = tableConfig(editDrawerRef, editGroupRef, editFormulaRef);
const configCal = tableConfigCal(editDrawerRef, editGroupRef, editFormulaRef);
const tConfig = treeConfig(result);
const nsModalFormConfig = ref({
api: group.creatOrUpdate,
data: {},
title: '新增',
schemas: formSchema,
extraModalConfig: {
bodyStyle: { paddingBottom: 0 },
},
});
nextTick(() => {
console.log(modalFormRef.value, 'modal');
});
const addNodeSon = (data) => {
console.log(data);
nsModalFormConfig.value.title = '新增';
nsModalFormConfig.value.data = {
pointName: '新增',
isCreate: true,
isCreatSon: false,
orgId: result,
};
modalFormRef.value?.toggle();
};
const editNode = (data) => {
console.log(data);
nsModalFormConfig.value.title = '编辑';
nsModalFormConfig.value.data = { pointName: 123 };
modalFormRef.value?.toggle();
data.value = { pointName: 'qwe' };
};
const moveNode = (data, type: opType) => {
console.log(data);
};
const deleteNode = (a) => {
NsModal.confirm({
content: '确定删除吗?',
onOk: () => {
console.log(a);
},
});
};
const filterAction = (data) => {};
const actionList = [
{ title: '新增子节点', key: 'addNodeSon', func: (data) => addNodeSon(data) },
{ title: '编辑', key: 'editNode', func: (data) => editNode(data) },
{ title: '上移', key: 'moveUp', func: (data) => moveNode(data, 'up') },
{ title: '下移', key: 'moveDown', func: (data) => moveNode(data, 'down') },
{ title: '删除', key: 'deleteNode', func: (data) => deleteNode(data) },
];
const handleSelect = () => {
defaultType.value = !defaultType.value;
};
</script>
<style lang="less" scoped></style>
<style lang="less" scoped>
.groupContainer {
height: 100%;
overflow-y: auto;
background-color: @ns-content-bg;
display: flex;
// gap: @ns-gap;
.tree,
.table {
background-color: @white;
border-radius: @ns-border-radius;
overflow-y: auto;
}
.tree {
margin-right: @ns-gap;
:deep(.ant-spin-nested-loading) {
width: 300px;
background-color: @white;
}
}
.table {
flex: 1;
min-width: 0;
}
}
.actionMore {
display: none;
}
:deep(.ant-tree-node-content-wrapper) {
&:hover {
.actionMore {
display: block;
}
}
}
.treeRow {
display: flex;
justify-content: space-between;
align-items: center;
}
</style>

View File

@@ -1,176 +1,237 @@
import { dateUtil } from '/nerv-lib/util/date-util';
import data from './mock.json';
export const tableConfig = {
title: '设备台账',
// api: '/carbon_emission/device/getDeviceList',
value: data.dataSource,
treeConfig: {
defaultExpandAll: true,
api: () => {
return new Promise((resolve) => {
setTimeout(() => {
resolve(data);
}, 100);
});
import { device } from '/@/api/deviceManage';
import { ref } from 'vue';
import { http } from '/nerv-lib/util';
export const tableConfig = (orgId) => {
return ref({
title: '设备信息',
api: device.queryDevicePage,
params: { orgId },
treeConfig: {
header: {
icon: 'deviceType',
title: '设备类别',
},
params: { orgId },
dynamicParams: 'code',
defaultExpandAll: true,
api: device.queryDeviceTree,
fieldNames: { title: 'deviceType', key: 'code' },
formConfig: {
schemas: [
{
field: 'deviceType',
label: '设备名称',
component: 'NsInput',
autoSubmit: true,
componentProps: {
placeholder: '请输入设备类型',
},
},
],
},
},
rowSelection: null,
columns: [
{
title: '设备名称',
dataIndex: 'deviceName',
},
{
title: '设备型号',
dataIndex: 'deviceModel',
},
{
title: 'SN码',
dataIndex: 'snCode',
textNumber: 5,
textEllipsis: true,
},
{
title: '设备一级区域',
dataIndex: 'device1Area',
textNumber: 5,
textEllipsis: true,
},
{
title: '设备二级区域',
dataIndex: 'device2Area',
textNumber: 5,
textEllipsis: true,
},
{
title: '设备详细位置',
dataIndex: 'deviceAddress',
textNumber: 5,
textEllipsis: true,
},
{
title: '设备规格',
dataIndex: 'deviceTp',
textNumber: 4,
},
{
title: '设备厂商纳税人识别号',
dataIndex: 'deviceRatepay',
textNumber: 8,
textEllipsis: true,
},
{
title: '设备厂商',
textNumber: 4,
dataIndex: 'manufacturer',
},
{
title: '厂商联系人',
dataIndex: 'contactPerson',
},
{
title: '设备描述',
dataIndex: 'deviceDesc',
textNumber: 5,
textEllipsis: true,
},
{
title: 'IP地址',
dataIndex: 'ipAddress',
},
{
title: '生产日期',
dataIndex: 'manufactureDate',
},
{
title: '采购日期',
dataIndex: 'purchaseDate',
},
{
title: '启用日期',
dataIndex: 'startDate',
},
{
title: '设备成本(元)',
dataIndex: 'equipmentCost',
textNumber: 6,
},
{
title: '使用期限',
dataIndex: 'usagePeriod',
textNumber: 4,
customRender: ({ value }) => `${value}`,
},
{
title: '额定功率',
dataIndex: 'ratedPower',
textNumber: 4,
// customRender: ({ value }) => `${value}年`,
},
{
title: '特殊参数',
textNumber: 4,
dataIndex: 'specialParameters',
},
],
formConfig: {
schemas: [
{
field: 'name',
field: 'deviceName',
label: '设备名称',
component: 'NsInput',
autoSubmit: true,
componentProps: {
placeholder: '请输入',
placeholder: '请输入设备名称',
},
},
{
field: 'areas',
label: '设备区域',
component: 'NsCascader',
format: (record) => {
console.log(record);
return record?.reduce(
(pre, cur) => {
const len = cur?.length - 1;
pre[len].push(cur[len]);
return pre;
},
[[], []],
);
},
fieldMap: ['area1', 'area2'],
componentProps: {
placeholder: '请选择设备区域',
multiple: true,
loadData: (selectedOptions, options) => {
const targetOption = selectedOptions[selectedOptions.length - 1];
if (!selectedOptions.length) {
http.post(device.dropArea, { orgId }).then((res) => {
options.value = res.data?.map((item) => {
return { label: item, value: item, children: [], isLeaf: false };
});
});
}
const value = targetOption?.value;
if (targetOption) {
targetOption.loading = true;
http.post(device.dropArea, { device1Area: value, orgId }).then((res) => {
targetOption.loading = false;
targetOption.children = res.data?.map((item) => {
return { label: item, value: item, children: [], isLeaf: true };
});
});
}
},
},
},
{
field: 'manufacturer',
label: '设备厂商',
component: 'NsInput',
componentProps: {
placeholder: '请输入设备厂商',
options: [
{
label: '全部',
value: '',
},
],
},
},
{
field: 'createTime',
label: '生产日期',
component: 'NsRangePicker',
fieldMap: ['manufactureBeginDate', 'manufactureEndDate'],
componentProps: {
valueFormat: 'YYYY-MM-DD',
placeholder: ['设备生产开始日期', '设备生产结束日期'],
},
},
{
field: 'createTime1',
label: '采购日期',
component: 'NsRangePicker',
fieldMap: ['purchaseBeginDate', 'purchaseEndDate'],
componentProps: {
valueFormat: 'YYYY-MM-DD',
placeholder: ['设备采购开始日期', '设备采购结束日期'],
},
},
{
field: 'createTime2',
label: '启用日期',
component: 'NsRangePicker',
fieldMap: ['startBeginDate', 'startEndDate'],
componentProps: {
valueFormat: 'YYYY-MM-DD',
placeholder: ['设备启用开始日期', '设备启用结束日期'],
},
},
],
params: {},
},
},
params: {
page: 0,
pageSize: 10,
},
rowSelection: null,
columns: [
{
title: '设备名称',
dataIndex: 'id',
},
{
title: '设备型号',
dataIndex: 'deviceCode',
},
{
title: 'SN码',
dataIndex: 'deviceName',
textNumber: 8,
textEllipsis: true,
},
{
title: '设备一级区域',
dataIndex: 'position',
},
{
title: '设备二级区域',
dataIndex: 'position',
},
{
title: '设备详细位置',
dataIndex: 'position',
},
{
title: '设备规格',
dataIndex: 'position',
},
{
title: '设备厂商纳税人识别号',
dataIndex: 'position',
},
{
title: '厂商联系人',
dataIndex: 'position',
},
{
title: '设备描述',
dataIndex: 'position',
},
{
title: 'IP地址',
dataIndex: 'position',
},
{
title: '生产日期',
dataIndex: 'position',
},
{
title: '采购日期',
dataIndex: 'position',
},
{
title: '启用日期',
dataIndex: 'position',
},
{
title: '设备成本(元)',
dataIndex: 'position',
},
{
title: '使用期限',
dataIndex: 'position',
},
{
title: '额定功率',
dataIndex: 'position',
},
{
title: '特殊参数',
dataIndex: 'position',
},
],
formConfig: {
schemas: [
{
field: 'name',
label: '设备名称',
component: 'NsInput',
componentProps: {
placeholder: '请输入',
},
},
{
field: 'provider',
label: '设备厂商',
component: 'NsInput',
componentProps: {
placeholder: '请输入',
},
},
{
field: 'payWay',
label: '设备区域',
component: 'NsSelect',
componentProps: {
placeholder: '请选择',
options: [
{
label: '全部',
value: '',
},
],
},
},
{
field: 'createTime',
label: '生产日期',
component: 'NsRangePicker',
fieldMap: ['queryStartDate', 'queryEndDate'],
componentProps: {
valueFormat: 'YYYY-MM-DD',
},
},
{
field: 'createTime1',
label: '采购日期',
component: 'NsRangePicker',
fieldMap: ['queryStartDate', 'queryEndDate'],
componentProps: {
valueFormat: 'YYYY-MM-DD',
},
},
{
field: 'createTime2',
label: '启用日期',
component: 'NsRangePicker',
fieldMap: ['queryStartDate', 'queryEndDate'],
componentProps: {
valueFormat: 'YYYY-MM-DD',
},
},
],
params: {},
},
// pagination: { pageSizeOptions: false },
rowKey: 'uuid',
// pagination: { pageSizeOptions: false },
rowKey: 'uuid',
});
};

View File

@@ -1,8 +1,14 @@
<template>
<ns-view-list-table v-bind="tableConfig" />
<ns-view-list-table v-bind="config" />
</template>
<script lang="ts" setup>
import { tableConfig } from './config';
import { computed, nextTick, ref } from 'vue';
const orgId = ref('');
const result = JSON.parse(sessionStorage.getItem('ORGID')!);
orgId.value = result;
const config = tableConfig(orgId.value);
defineOptions({
name: 'LedgerIndex', // 与页面路由name一致缓存才可生效
});

View File

@@ -131,6 +131,7 @@ export const formConfig2 = (disabled2: Boolean) => {
label: '是否部门领导',
field: 'isLeader',
component: 'NsRadioGroup',
defaultValue: 1,
componentProps: {
disabled: disabled2,
radioType: 'radio',

View File

@@ -3,108 +3,156 @@
<template>
<div class="main">
<div class="left">
<div class="ns-table-title">部门管理</div>
<div class="ns-table-title ns-title-extra-box">部门管理</div>
<a-row>
<a-col :span="12" class="tree">
<ns-button style="margin: 10px" type="primary" @click="pipe(addApartment)">
新增部门
</ns-button>
<ns-button type="primary" @click="pipe(addApartmentSon, true)">新增子部门</ns-button>
<ns-button style="margin: 10px" type="primary" @click="pipe(deleteDept, true)">
删除
</ns-button>
<a-col :span="8" class="tree">
<a-tree
ref="treeRef"
v-if="deptTreeData?.length"
:tree-data="deptTreeData"
:selectedKeys="deptTreeSelectedKeys"
blockNode
defaultExpandAll
@select="SelectApartmentTree">
<template #title="data">
{{ data.deptInfo?.deptName }}
<div style="display: flex; justify-content: space-between; align-items: center">
<span>{{ data.deptInfo?.deptName }}</span>
<a-dropdown>
<ns-icon name="actionMore" size="14" class="actionMore" />
<template #overlay>
<a-menu>
<a-menu-item
v-for="(action, index) in filterAction(data, dropActions)"
:key="index"
@click="action.func(data)">
<span>{{ action.title }}</span>
</a-menu-item>
</a-menu>
</template>
</a-dropdown>
</div>
</template>
</a-tree>
<a-empty style="margin-top: 120px" v-else />
</a-col>
<a-col :span="12" class="list">
<a-tabs v-model:activeKey="activeKey">
<a-tab-pane :key="1" tab="部门信息">
<ns-form
ref="formRef"
:schemas="formSchema"
:wrapperCol="{ span: 18 }"
:model="formData"
formLayout="vertical"
class="form" />
</a-tab-pane>
<a-tab-pane :key="2" :disabled="selectRef?.hasOwnProperty('orgInfo')" tab="部门权限">
<a-tree
:tree-data="deptPermissionTreeData"
:fieldNames="{ children: 'menus', title: 'label', key: 'permissionId' }"
v-model:checkedKeys="deptcheckedKeys"
checkable
:selectable="false"
defaultExpandAll
@check="deptCheck">
<template #title="data"> {{ data.label }}</template>
</a-tree>
</a-tab-pane>
</a-tabs>
<ns-button style="margin: 16px" type="primary" @click="CancelApartment">取消 </ns-button>
<ns-button v-show="disabled" type="primary" @click="pipe(deptEdit, true, false)"
>编辑</ns-button
>
<ns-button v-show="!disabled" type="primary" @click="deptSure">确定</ns-button>
<a-col :span="16" class="list">
<div class="pane">
<a-tabs v-model:activeKey="activeKey">
<a-tab-pane :key="1" tab="部门信息">
<ns-form
ref="formRef"
:schemas="formSchema"
:wrapperCol="{ span: 19 }"
:labelCol="{ span: 5 }"
:model="formData"
formLayout="vertical"
class="form" />
</a-tab-pane>
<a-tab-pane :key="2" :disabled="selectRef?.hasOwnProperty('orgInfo')" tab="部门权限">
<a-tree
v-if="deptPermissionTreeData?.length"
:tree-data="deptPermissionTreeData"
:fieldNames="{ children: 'menus', title: 'label', key: 'permissionId' }"
v-model:checkedKeys="deptcheckedKeys"
checkable
:selectable="false"
defaultExpandAll
@check="deptCheck">
<template #title="data"> {{ data.label }}</template>
</a-tree>
<a-empty style="margin-top: 120px" v-else />
</a-tab-pane>
</a-tabs>
<a-space v-if="activeKey === 1 || deptPermissionTreeData?.length">
<ns-button type="primary" @click="CancelApartment">取消 </ns-button>
<ns-button v-if="disabled" type="primary" @click="pipe(deptEdit, true, false)">
编辑
</ns-button>
<ns-button v-else type="primary" @click="deptSure">确定</ns-button>
</a-space>
</div>
</a-col>
</a-row>
</div>
<div class="right">
<div class="ns-table-title">角色管理</div>
<div class="ns-table-title ns-title-extra-box">角色管理</div>
<a-row>
<a-col :span="12" class="tree">
<ns-button style="margin: 10px" type="primary" @click="rolePipe(addUser, true)">
新增角色
</ns-button>
<ns-button type="primary" @click="rolePipe(addUserSon)">新增子角色</ns-button>
<ns-button style="margin: 10px" type="primary" @click="rolePipe(deleteUser)">
删除
</ns-button>
<a-col :span="8" class="tree">
<a-space wrap style="margin-bottom: 16px; justify-content: flex-start">
<!-- <ns-button v-auth="'userAdd'" type="primary" @click="rolePipe(addUser, true)">
新增角色
</ns-button>
<ns-button type="primary" @click="rolePipe(addUserSon)">新增子角色</ns-button>
<ns-button type="primary" @click="rolePipe(deleteUser)"> 删除 </ns-button> -->
</a-space>
<a-tree
v-if="roleTreeData.length"
:tree-data="roleTreeData"
:selectedKeys="roleTreeSelectedKeys"
blockNode
defaultExpandAll
@select="SelectUserTree">
<template #title="data">
{{ data.zhName }}
<div style="display: flex; justify-content: space-between; align-items: center">
<span> {{ data.zhName }}</span>
<a-dropdown>
<ns-icon name="actionMore" size="14" class="actionMore" />
<template #overlay>
<a-menu>
<a-menu-item
v-for="(action, index) in filterAction(data, dropRoleActions, 'addUser')"
:key="index"
@click="action.func(data)">
<span>{{ action.title }}</span>
</a-menu-item>
</a-menu>
</template>
</a-dropdown>
</div>
</template>
</a-tree>
<a-empty style="margin-top: 120px" v-else />
</a-col>
<a-col :span="12" class="list">
<a-tabs v-model:activeKey="roleActiveKey">
<a-tab-pane :key="1" tab="角色信息">
<ns-form
ref="formRoleRef"
:schemas="formSchema2"
:model="roleFormData"
:wrapperCol="{ span: 18 }"
formLayout="vertical"
class="form" />
</a-tab-pane>
<a-tab-pane :key="2" tab="角色权限">
<a-tree
:tree-data="rolePermissionTreeData"
v-model:checkedKeys="roleCheckedKeys"
defaultExpandAll
:fieldNames="{ children: 'menus', title: 'label', key: 'permissionId' }"
:selectable="false"
checkable
@check="roleCheck" />
</a-tab-pane>
</a-tabs>
<ns-button style="margin: 16px" type="primary" @click="CancelUser">取消</ns-button>
<ns-button v-show="roleDisabled" type="primary" @click="rolePipe(roleEdit, false, false)">
编辑
</ns-button>
<ns-button v-show="!roleDisabled" type="primary" @click="roleSure"> 确定 </ns-button>
<a-col :span="16" class="list">
<div class="pane">
<a-tabs v-model:activeKey="roleActiveKey">
<a-tab-pane :key="1" tab="角色信息">
<ns-form
ref="formRoleRef"
:schemas="formSchema2"
:model="roleFormData"
:labelCol="{ span: 5 }"
:wrapperCol="{ span: 19 }"
formLayout="vertical"
class="form" />
</a-tab-pane>
<a-tab-pane :key="2" tab="角色权限">
<a-tree
v-if="rolePermissionTreeData?.length"
:tree-data="rolePermissionTreeData"
v-model:checkedKeys="roleCheckedKeys"
defaultExpandAll
:fieldNames="{ children: 'menus', title: 'label', key: 'permissionId' }"
:selectable="false"
checkable
@check="roleCheck" />
<a-empty style="margin-top: 120px" v-else />
</a-tab-pane>
</a-tabs>
<a-space v-if="roleActiveKey === 1 || rolePermissionTreeData?.length">
<ns-button type="primary" @click="CancelUser">取消</ns-button>
<ns-button
v-if="roleDisabled"
:disabled="!roleTreeData?.length"
type="primary"
@click="rolePipe(roleEdit, false, false)">
编辑
</ns-button>
<ns-button v-else :disabled="!roleTreeData?.length" type="primary" @click="roleSure">
确定
</ns-button>
</a-space>
</div>
</a-col>
</a-row>
</div>
@@ -115,7 +163,7 @@
import { Modal } from 'ant-design-vue';
import { ExclamationCircleOutlined } from '@ant-design/icons-vue';
import { http } from '/nerv-lib/util/http';
import { cloneDeep, get } from 'lodash-es';
import { cloneDeep, get, isEmpty } from 'lodash-es';
import { formConfig, formConfig2 } from './config';
import { department } from '/@/api/origanizemanage';
import { permission } from '/@/api/origanizemanage';
@@ -128,7 +176,7 @@
const formRef = ref();
const formRoleRef = ref();
let formData = ref({});
let roleFormData = ref({});
let roleFormData = ref({ isLeader: 1 });
const activeKey = ref(1);
const roleActiveKey = ref(1);
const disabled = ref(true);
@@ -172,9 +220,7 @@
/**操作拦截 */
const pipe = (func: Function, flag = false, toggle = true) => {
console.log(selectRef.value);
if (toggle) activeKey.value = 1;
// if (toggle) activeKey.value = 1;
if (flag) {
// 只有部门的操作
if (selectRef.value?.hasOwnProperty('orgInfo') || !selectRef.value?.deptInfo) {
@@ -193,13 +239,15 @@
const rolePipe = (func: Function, linkDept = false, toggle = true) => {
console.log(selectRoleRef.value);
if (toggle) roleActiveKey.value = 1;
// if (toggle) roleActiveKey.value = 1;
// 需要先选择部门
if ((linkDept && !selectRef.value?.deptInfo) || selectRef.value?.hasOwnProperty('own')) {
NsMessage.error('请先选择相关部门');
return;
}
if (!linkDept && !selectRoleRef.value) {
console.log(123);
if (!linkDept && isEmpty(selectRoleRef.value)) {
NsMessage.error('请先选择相关角色');
return;
}
@@ -207,18 +255,42 @@
};
/**操作拦截 */
// 部门权限树
const getPermissionTree = (params) => {
return http.post(permission.queryOrgPermission, params).then((res) => {
deptPermissionTreeData.value = get(res, 'data');
});
};
// 子级部门权限树
const getDeptsonPermissionTree = (params) => {
return http.post(permission.queryDeptPermissionFilter, params).then((res) => {
deptPermissionTreeData.value = get(res, 'data');
});
};
// 角色权限树
const getRolePermissionTree = (params) => {
return http.post(permission.queryFilterDeptPermission, params).then((res) => {
rolePermissionTreeData.value = get(res, 'data');
});
};
// 子级角色权限树
const getRolesonPermissionTree = (params) => {
return http.post(permission.queryRolePermissionFilter, params).then((res) => {
rolePermissionTreeData.value = get(res, 'data');
});
};
getPermissionTree({ projectId, orgId });
// 选中自己的第一个部门
const initDept = () => {
if (!deptTreeData.value?.length || !deptTreeData.value[0]?.children?.length) return;
const info = {
node: { key: '0-0-0', dataRef: { deptInfo: deptTreeData.value[0]?.children[0].deptInfo } },
};
SelectApartmentTree(['0-0-0'], info);
};
// 部门树
const getDepartList = (params) => {
@@ -228,6 +300,7 @@
item['deptInfo'] = item.orgInfo;
item['deptInfo']['deptName'] = item?.orgInfo?.orgName;
item['own'] = !index;
item['selectable'] = false;
item['children'] = item.deptTrees;
return item;
});
@@ -237,6 +310,7 @@
};
getDepartList({ orgId }).then((res) => {
deptTreeData.value = res;
initDept();
});
// 获取部门树
@@ -249,14 +323,23 @@
// 获取角色树
const getUserTree = (params = { deptId: selectRef.value?.deptInfo?.deptId }) => {
http.post(department.queryRoleTree, params).then((res) => {
roleTreeData.value = res.data;
return http.post(department.queryRoleTree, params).then((res) => {
roleTreeData.value = [{ zhName: '全部', selectable: false, orgInfo: {}, children: res.data }];
});
};
// 根据依赖刷新角色树
watchEffect(() => {
if (selectRef.value) {
getUserTree();
getUserTree().then(() => {
if (!roleTreeData.value?.length) {
selectRoleRef.value = {};
roleFormData.value = { isLeader: 1 };
}
const info = {
node: { key: '0-0-0', dataRef: { ...roleTreeData.value[0].children[0] } },
};
SelectUserTree([''], info);
});
}
});
@@ -267,34 +350,42 @@
callback: null,
};
const addApartment = () => {
// 添加部门
const addApartment = (data) => {
const { deptInfo } = data;
activeKey.value = 1;
disabled.value = false;
opMap.type = 'addDept';
formData.value = {};
let sourceOrgId = '';
if (!currentOrgRef.value.own) {
if (deptInfo.orgId !== orgId) {
// 此处为给关联企业加部门
sourceOrgId = orgId;
}
opMap.fuc = (params) => {
return formRef.value.triggerSubmit().then(() => {
return http.post(department.deptSave, {
...params,
orgId: selectRef.value.deptInfo?.orgId,
orgId: deptInfo?.orgId,
sourceOrgId,
projectId,
pdeptId: deptInfo.pdeptId || '',
orgName,
});
});
};
return;
};
const addApartmentSon = () => {
// 添加子部门
const addApartmentSon = (data) => {
const { deptInfo } = data;
activeKey.value = 1;
disabled.value = false;
opMap.type = 'addson';
formData.value = {};
let sourceOrgId = '';
if (!currentOrgRef.value?.own) {
if (deptInfo.orgId !== orgId) {
sourceOrgId = orgId;
}
opMap.fuc = (params) => {
@@ -303,7 +394,7 @@
...params,
orgId,
projectId,
pdeptId: selectRef.value.deptInfo.deptId,
pdeptId: deptInfo.deptId,
sourceOrgId,
// deptName: selectRef.value.deptInfo.deptName,
});
@@ -311,10 +402,11 @@
};
};
const addUser = () => {
const addUser = (data) => {
roleDisabled.value = false;
opMap.type = 'addUser';
roleFormData.value = {};
roleFormData.value = { isLeader: 1 };
roleActiveKey.value = 1;
opMap.fuc = (params) => {
delete params.roleId;
return formRoleRef.value.triggerSubmit().then(() => {
@@ -322,6 +414,7 @@
...params,
orgId,
projectId,
proleId: data.proleId || '',
deptId: selectRef.value.deptInfo.deptId,
deptName: selectRef.value.deptInfo.deptName,
});
@@ -329,10 +422,11 @@
};
};
const addUserSon = () => {
const addUserSon = (data) => {
roleDisabled.value = false;
opMap.type = 'addUserSon';
roleFormData.value = {};
roleActiveKey.value = 1;
roleFormData.value = { isLeader: 1 };
opMap.fuc = (params) => {
delete params.roleId;
return formRoleRef.value.triggerSubmit().then(() => {
@@ -340,24 +434,28 @@
...params,
orgId,
projectId,
proleId: selectRoleRef.value.roleId,
proleId: data.roleId,
deptId: selectRef.value.deptInfo.deptId,
deptName: selectRef.value.deptInfo.deptName,
});
});
};
};
const deleteDept = () => {
const deleteDept = (data) => {
// 删除逻辑
Modal.confirm({
title: '是否确认删除',
onOk() {
http.post(department.deptDel, { deptId: selectRef.value.deptInfo.deptId }).then(() => {
http.post(department.deptDel, { deptId: data.deptInfo.deptId }).then(() => {
getTree();
clearDeptData();
// 清空select树
deptTreeSelectedKeys.value = [];
selectRef.value = '';
if (data.selected) {
// 删除选中的数据需要清空
deptTreeSelectedKeys.value = [];
selectRef.value = '';
roleTreeData.value = [{ zhName: '全部', selectable: false, orgInfo: {}, children: [] }];
}
});
},
onCancel() {
@@ -366,16 +464,20 @@
});
};
const deleteUser = () => {
const deleteUser = (data) => {
Modal.confirm({
title: '是否确认删除',
onOk() {
http.post(department.delRole, { roleId: selectRoleRef.value.roleId }).then(() => {
http.post(department.delRole, { roleId: data.roleId }).then(() => {
getUserTree({ deptId: selectRef.value.deptInfo.deptId });
clearRoleData();
// 清空select树
roleTreeSelectedKeys.value = [];
selectRoleRef.value = '';
if (data.selected) {
// 删除选中的数据需要清空
roleTreeSelectedKeys.value = [];
selectRoleRef.value = '';
}
NsMessage.success('操作成功');
});
},
@@ -453,6 +555,7 @@
};
// 保存角色权限
const rolePermission = () => {
if (!roleTotalCheckedKeys.value?.length) return;
http
.post(department.addRolePermission, {
// deptId: selectRef.value?.deptInfo.deptId,
@@ -512,7 +615,7 @@
// 部门选择
const SelectApartmentTree = (selectedKeys: any, info: any) => {
console.log(info);
console.log(info, 'SelectApartmentTree');
// 部门切换需要调整角色tab
roleActiveKey.value = 1;
@@ -524,15 +627,27 @@
selectRef.value = info.node.dataRef;
// 确定是否是企业
if (!selectRef.value.hasOwnProperty('own')) {
if (!selectRef.value.hasOwnProperty('own') && !selectRef.value.hasOwnProperty('orgInfo')) {
// 部门
formData.value = cloneDeep(info.node.dataRef.deptInfo);
} else {
activeKey.value = 1;
currentOrgRef.value = selectRef.value;
formData.value = {};
}
if (selectRef.value.deptInfo?.pdeptId) {
// 查询子部门
getDeptsonPermissionTree({ deptId: selectRef.value.deptInfo?.pdeptId });
} else {
getPermissionTree({ projectId, orgId });
}
getDeptPermission();
// 切换部门重置逻辑
deptcheckedKeys.value = [];
rolePermissionTreeData.value = [];
roleCheckedKeys.value = [];
roleTreeSelectedKeys.value = [];
roleDisabled.value = true;
};
/**
@@ -559,8 +674,13 @@
selectRoleRef.value = info.node.dataRef;
roleFormData.value = cloneDeep(info.node.dataRef);
roleCheckedKeys.value = [];
if (selectRoleRef.value?.proleId) {
// 查询子部门
getRolesonPermissionTree({ roleId: selectRoleRef.value?.proleId });
} else {
getRolePermissionTree({ deptId: selectRef.value.deptInfo.deptId });
}
getRolePermission();
getRolePermissionTree({ deptId: selectRef.value.deptInfo.deptId });
};
const CancelApartment = () => {
@@ -613,55 +733,116 @@
rolePermission();
}
};
// 部门区域的dropdown
const dropActions = ref([
{ title: '新增部门', func: addApartment, key: 'addDept' },
{ title: '新增子部门', func: addApartmentSon, key: 'addDeptSon' },
{ title: '删除', func: deleteDept, key: 'deleteDept' },
// { title: '新增角色', func: addUser, key: 'addUser' },
]);
const filterAction = (data, actions, keyV = 'addDept') => {
if (data.hasOwnProperty('orgInfo')) {
// 企业节点
return actions.filter(({ key }) => key === keyV);
}
return actions;
};
// 角色区域的dropdown
const dropRoleActions = ref([
{ title: '新增角色', func: addUser, key: 'addUser' },
{ title: '新增子角色', func: addUserSon, key: 'addUserSon' },
{ title: '删除', func: deleteUser, key: 'deleteUser' },
]);
const treeRef = ref();
console.log(treeRef);
</script>
<style lang="less" scoped>
:deep(.ns-form::after) {
display: none;
}
.actionMore {
display: none;
}
:deep(.ant-row) {
height: calc(100% - 44px);
}
:deep(.ant-tree-node-content-wrapper) {
&:hover {
.actionMore {
display: block;
}
}
}
:deep(.ant-tabs-nav-wrap) {
padding: 0;
}
:deep(.ant-tabs-tabpane) {
padding: 20px;
padding-top: @ns-gap;
.form {
margin: 0 !important;
}
}
:deep(.ant-space) {
justify-content: flex-end;
}
.main {
display: flex;
flex: 1;
height: 100%;
background-color: @ns-content-bg;
> div:first-child {
margin-right: @ns-gap;
}
}
.left {
.left,
.right {
width: 50%;
height: calc(100vh-50px);
border-right: 5px solid rgb(229, 235, 240);
height: 100%;
padding: @ns-gap;
background-color: @white;
border-radius: @ns-border-radius;
// box-shadow: @ns-content-box-shadow;
}
.tree {
width: 400px;
height: 89vh;
border-right: 2px solid rgb(229, 235, 240);
height: 100%;
overflow: hidden;
overflow-y: auto;
border-radius: @ns-border-radius;
border: 1px solid #ebeef5;
padding: 16px;
}
.right {
width: 50%;
}
.top {
height: 50vh;
border-bottom: 5px solid rgb(229, 235, 240);
.list {
padding-left: @ns-gap;
height: 100%;
.pane {
padding-left: @ns-gap;
border-left: 1px solid #ebeef5;
height: 100%;
display: flex;
flex-direction: column;
justify-content: space-between;
:deep(.ant-tabs-content) {
height: 100%;
.ant-tree {
height: 100%;
overflow-y: scroll;
}
}
}
}
.ns-table-title {
text-align: left;
height: 46px;
line-height: 46px;
font-size: 18px;
font-size: 16px;
font-weight: bold;
user-select: text;
padding-left: 16px;
width: 100%;
border-bottom: 2px solid rgb(229, 235, 240);
}
.table {
width: 2000px;
margin-bottom: @ns-gap;
}
.admin {

View File

@@ -44,6 +44,7 @@ export const formConfig = (disabled) => {
label: '性别',
field: 'sex',
component: 'NsRadioGroup',
defaultValue: '男',
componentProps: {
radioType: 'radio',
options: [

View File

@@ -2,7 +2,7 @@
<html lang="en">
<head>
<meta charset="UTF-8" />
<link rel="icon" href="/favicon.ico" />
<link rel="icon" href="/projectIcon.svg" />
<meta name="referrer" content="never" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<!-- <script type="text/javascript">

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.5 KiB

View File

@@ -0,0 +1,10 @@
<svg xmlns="http://www.w3.org/2000/svg" width="36" height="36" viewBox="0 0 36 36">
<g id="组_23402" data-name="组 23402" transform="translate(-959.12 -738.12)">
<rect id="矩形_16530" data-name="矩形 16530" width="36" height="36" transform="translate(959.12 738.12)" fill="none"/>
<g id="组_23400" data-name="组 23400" transform="translate(960.956 739.956)">
<path id="路径_30576" data-name="路径 30576" d="M207.674,163.872v-9.284a2.553,2.553,0,0,0-1.179-2.063l-8.056-4.634a2.417,2.417,0,0,0-2.358,0l-8.023,4.65a2.38,2.38,0,0,0-1.179,2.063v9.333A2.553,2.553,0,0,0,188.059,166l8.056,4.585a2.417,2.417,0,0,0,2.358,0l8.056-4.634A2.331,2.331,0,0,0,207.674,163.872Z" transform="translate(-181.117 -142.881)" fill="#4388fb" opacity="0.2"/>
<path id="路径_30577" data-name="路径 30577" d="M265.893,314.283h-2.718l-.884-2.653h-4.224l-.884,2.653h-2.718l4.224-11.625h2.9Zm-4.093-4.617-1.326-4.044a9.365,9.365,0,0,1-.2-1.015h-.065a5.831,5.831,0,0,1-.2,1.015l-1.326,4.044Zm8.072-7.073v11.625h-2.456V302.592Z" transform="translate(-246.539 -292.932)" fill="#4388fb"/>
<path id="路径_30578" data-name="路径 30578" d="M36.685,20.095a.9.9,0,0,0-.884.884v2.472a1.535,1.535,0,0,1-.77,1.294L23.7,31.262a1.422,1.422,0,0,1-1.523,0l-11.33-6.517a1.456,1.456,0,0,1-.77-1.294V20.177a2.409,2.409,0,0,0-1-4.6,2.425,2.425,0,0,0-2.423,2.407,2.391,2.391,0,0,0,1.637,2.276v3.176a3.268,3.268,0,0,0,1.637,2.816l11.33,6.582a3.244,3.244,0,0,0,1.637.409,3.471,3.471,0,0,0,1.637-.475l11.281-6.517a3.268,3.268,0,0,0,1.637-2.816V20.963A.76.76,0,0,0,36.685,20.095Zm.884-6.942V10.287a3.268,3.268,0,0,0-1.637-2.816L24.585.954a3.284,3.284,0,0,0-3.291,0L9.947,7.471A3.268,3.268,0,0,0,8.31,10.287v2.227a.884.884,0,1,0,1.768,0V10.287a1.535,1.535,0,0,1,.77-1.294l11.33-6.517a1.422,1.422,0,0,1,1.523,0L34.982,9.059a1.456,1.456,0,0,1,.77,1.294v2.734a2.4,2.4,0,1,0,1.817.065Z" transform="translate(-6.656 -0.512)" fill="#4388fb"/>
</g>
</g>
</svg>

After

Width:  |  Height:  |  Size: 1.9 KiB

View File

@@ -23,47 +23,54 @@
});
</script>
<style lang="less" scoped>
<!-- <style lang="less" scoped>
:deep(.ns-content) {
padding-top: 80px !important;
// padding-top: 80px !important;
}
#app {
width: 100%;
height: 100%;
min-width: 1000px;
}
:deep(.ns-left-menu .firstMenuItem-selected .ant-menu-title-content) {
background: unset !important;
}
:deep(.ns-left-menu .ant-menu-item-selected .ant-menu-title-content) {
color: #fff !important;
background: @primary-color;
border-radius: 2px;
height: 40px;
line-height: 40px;
a {
color: #ffffff !important;
:deep(.ns-left-menu) {
.ant-menu-item-active,
.ant-submenu-item-active {
background: #ecf3ff !important;
}
.ant-menu-item-selected .ant-menu-title-content {
// color: #fff !important;
background: @primary-color;
border-radius: 12px;
height: 40px;
line-height: 40px;
a {
color: @white !important;
}
}
}
:deep(.ant-menu-light.ant-menu-horizontal > .ant-menu-item:hover) {
background: @primary-color;
}
:deep(.ant-menu-inline .ant-menu-submenu-title) {
color: rgba(255, 255, 255, 0.9) !important;
}
// :deep(.ant-menu-inline .ant-menu-submenu-title) {
// color: rgba(255, 255, 255, 0.9) !important;
// }
:deep(.ns-left-menu .ant-layout-sider-children .ant-menu-sub.ant-menu-inline) {
position: relative;
&::before {
display: flex;
width: 2px;
height: calc(100% - 40px);
position: absolute;
top: 20px;
left: 20px;
content: '';
background-color: rgba(255, 255, 255, 0.2);
}
// position: relative;
// &::before {
// display: flex;
// width: 2px;
// height: calc(100% - 40px);
// position: absolute;
// top: 20px;
// left: 20px;
// content: '';
// background-color: rgba(255, 255, 255, 0.2);
// }
}
//*************************含tab的 list列表样式 */
@@ -170,46 +177,4 @@
margin-top: -2px;
}
}
</style>
<style lang="less">
// 列表弹框样式修改
.listTableModal .ant-modal-title {
font-weight: 600;
}
.listTableModal .ant-modal-body {
padding: 16px !important;
.ant-tabs-nav-wrap {
padding: 0px;
}
.ns-list-table {
border-left: 16px solid #e5ebf0;
border-right: 16px solid #e5ebf0;
border-bottom: 16px solid #e5ebf0;
}
}
:deep(.ant-menu-submenu-title) {
color: #ffffff !important;
}
</style>
<style lang="less">
//************************修改顶部菜单弹框样式
.ant-menu-submenu-placement-bottomLeft {
.ant-menu-submenu {
background: rgb(3 24 53) !important;
}
.ant-menu-sub {
background: rgb(3 24 53) !important;
}
.ant-menu-title-content {
color: #fff !important;
.ns-icon {
margin-right: 7px;
transform: translateY(2px);
}
}
.ant-menu-submenu-arrow {
color: #fff !important;
}
}
</style>
</style> -->

View File

@@ -20,6 +20,7 @@ export const appConfig = {
baseHeader: '/parkingManage',
baseRouter: '/parkingManage/parkingLotManage',
themeConfig: {
logoLessUrl: `${import.meta.env.VITE_PUBLIC_PATH}/asset/image/headerIcon.png`,
bgImageUrl: `${import.meta.env.VITE_PUBLIC_PATH}/asset/image/login/background.png`,
},
// userCustomRouterGuard: (to, from, next, whiteNameList, authorizationStore, appConfig) => {

View File

@@ -1,3 +1,5 @@
import { routerConfig } from '/nerv-lib/saas/config/router.config';
export enum ResultEnum {
SUCCESS = 0,
ERROR = 1,
@@ -20,3 +22,11 @@ export enum ContentTypeEnum {
// form-data upload
FORM_DATA = 'multipart/form-data;charset=UTF-8',
}
export const errCodeMap = new Map<number, any>([
[13, ''],
[1, ''],
[11, ''],
[3005, ''],
[10086, () => routerConfig.logout()],
]);

View File

@@ -6,23 +6,14 @@ const home = {
redirect: { name: 'homeIndex' },
children: [
{
path: 'homeModule',
name: 'HomeModule',
meta: { title: '首页', hideChildren: true, icon: 'dicizhishou' },
component: Base,
redirect: { name: 'homeIndex' },
children: [
{
path: 'index',
name: 'homeIndex',
component: () => import('/@/view/developing.vue'),
meta: {
title: '首页',
keepAlive: true,
// backApi: [],
},
},
],
path: 'index',
name: 'homeIndex',
component: () => import('/@/view/developing.vue'),
meta: {
title: '首页',
keepAlive: true,
// backApi: [],
},
},
],
};

View File

@@ -1,28 +1,19 @@
const Base = () => import('/nerv-lib/saas/view/system/layout/content.vue');
const organizationManage = {
path: '/organizationManage',
name: 'organizationManage',
name: 'EnterpriseManage',
meta: { title: '企业管理', icon: 'dicizhishou', index: 99, hideChildren: true },
redirect: { name: 'EnterpriseManage' },
redirect: { name: 'EnterpriseManageIndex' },
children: [
{
path: 'enterpriseManage',
name: 'EnterpriseManage',
meta: { title: '企业管理', hideChildren: true, icon: 'dicizhishou' },
component: Base,
redirect: { name: 'EnterpriseManageIndex' },
children: [
{
path: 'index',
name: 'EnterpriseManageIndex',
component: () => import('/@/view/organizationManage/enterpriseManage/index.vue'),
meta: {
title: '企业管理',
keepAlive: true,
// backApi: [],
},
},
],
path: 'index',
name: 'EnterpriseManageIndex',
component: () => import('/@/view/organizationManage/enterpriseManage/index.vue'),
meta: {
title: '企业管理',
keepAlive: true,
// backApi: [],
},
},
],
};

View File

@@ -11,10 +11,11 @@
// .ant-menu-dark.ant-menu-horizontal>.ant-menu-item:hover {
// background-color: #43BB79 !important;
// }
.ant-menu-inline .ant-menu-item,
.ant-menu-inline .ant-menu-submenu-title {
width: 100% !important;
max-width: 100% !important;
transition: none !important;
}
.ns-basic-table .ant-btn:hover {
@@ -46,17 +47,17 @@
}
// header菜单字体样式
.ant-menu-dark.ant-menu-horizontal>.ant-menu-item,
.ant-menu-dark.ant-menu-horizontal>.ant-menu-submenu {
color: #fff;
}
// .ant-menu-dark.ant-menu-horizontal>.ant-menu-item,
// .ant-menu-dark.ant-menu-horizontal>.ant-menu-submenu {
// color: #fff;
// }
.ant-menu-dark .ant-menu-item,
.ant-menu-dark .ant-menu-item-group-title,
.ant-menu-dark .ant-menu-item>a,
.ant-menu-dark .ant-menu-item>span>a {
color: #fff;
}
// .ant-menu-dark .ant-menu-item,
// .ant-menu-dark .ant-menu-item-group-title,
// .ant-menu-dark .ant-menu-item>a,
// .ant-menu-dark .ant-menu-item>span>a {
// color: #fff;
// }
@font-face {
/*给字体命名*/
@@ -111,13 +112,13 @@
.ant-menu-title-content {
svg {
color: #A1ABC2;
// color: #A1ABC2;
}
}
.ant-menu-item-selected {
svg {
color: #D0DBF5;
// color: #D0DBF5;
}
}
@@ -181,3 +182,7 @@
background-color: #AEAEAE;
}
}
#app {
min-width: 1200px;
}

View File

@@ -329,22 +329,26 @@ export const tableConfig = ({
field: 'orgCode',
label: '组织ID',
component: 'NsInput',
componentProps: { placeholder: '请输入组织ID' },
},
{
field: 'cliqueName',
label: '集团名称',
component: 'NsInput',
componentProps: { placeholder: '请输入集团名称' },
},
{
field: 'orgName',
label: '组织名称',
component: 'NsInput',
componentProps: { placeholder: '请输入组织名称' },
},
{
field: 'status',
label: '状态',
component: 'NsSelect',
componentProps: {
placeholder: '请选择状态',
options: [
{
label: '正常',
@@ -363,7 +367,7 @@ export const tableConfig = ({
component: 'NsCascader',
fieldMap: ['province', 'city', 'county'],
componentProps: {
placeholder: '请选择',
placeholder: '请选择省市区',
api: enterPrise.getArea,
fieldNames: { label: 'regionName', value: 'regionName' },
showSearch: true,

View File

@@ -13,7 +13,7 @@ const DATE_TYPE = [
'ARangePicker',
];
const INPUT_TYPE = ['NsInput', 'AInput'];
const INPUT_TYPE = ['NsInput', 'AInput', 'NsTextarea', 'ATextarea'];
/**
* 是否时间组件

View File

@@ -18,7 +18,7 @@
<!-- 占位解决三列中部为空的问题 -->
<a-col :span="formLayout.span" class="ns-form-item ns-form-item-placeholder" />
</a-row>
<a-divider class="ns-child-form-divider" />
<!-- <a-divider class="ns-child-form-divider" /> -->
</template>
<script lang="ts">

View File

@@ -51,6 +51,11 @@
import { isInputType } from '/nerv-lib/component/form/form-util';
import { useParams } from '/nerv-lib/use/use-params';
enum prefix {
'请选择',
'请输入',
}
export default defineComponent({
name: 'NsFormItem',
components: {},
@@ -221,21 +226,28 @@
const {
component,
field,
label,
dynamicParams,
changeEvent = 'change',
valueField,
addModel = [],
autoAddLink = false,
autoSubmit = false,
componentProps,
} = props.schema;
const isCheck =
component && ['NsSwitch', 'NsCheckbox', 'Switch', 'Checkbox'].includes(component);
const eventKey = `on${upperFirst(changeEvent)}`;
const attr: Recordable = {};
if (isInputType(component)) {
const isInput = isInputType(component);
if (isInput) {
attr.allowClear = true;
}
// const { placeholder } = componentProps;
// // 赋予初始提示符
// componentProps['placeholder'] = placeholder || `${prefix[Number(isInput)]}${label}`;
const propsData: Recordable = {
field,
dynamicParams,
@@ -293,8 +305,6 @@
},
onValidateChange: (text: Object | undefined) => {
if (isUndefined(text)) text = {};
console.error(text, 'onValidateChange');
validateRef.value = text;
},
};

View File

@@ -7,7 +7,24 @@
v-bind="getBindValue"
ref="formElRef"
:model="formModel">
<a-row class="ns-form-body" :justify="getFormClass.justify" :gutter="getFormClass.gutter">
<div v-if="showAction && showExpandAll" class="ns-form-title ns-title-extra-box">
<span>查询</span>
<a-button type="link" class="ns-operate-expand" @click="expandAll = !expandAll">
<template v-if="expandAll">
收起筛选
<UpOutlined />
</template>
<template v-else>
展开筛选
<DownOutlined />
</template>
</a-button>
</div>
<a-row
v-show="expandAll"
class="ns-form-body"
:justify="getFormClass.justify"
:gutter="getFormClass.gutter">
<template v-for="(schema, index) in getSchema" :key="schema.field">
<ns-form-item
:show="expandRef || index < splitNumber"
@@ -89,6 +106,7 @@
const { schemas } = toRefs(props);
const isInitDefaultValueRef = ref(false);
const expandRef = ref(props.expand);
const expandAll = ref(props.expandAll);
const formModel = computed(() => {
return props.model;
});
@@ -97,19 +115,13 @@
function addChildForm(form: any) {
childForms.value.push(form);
}
let splitNumber = ref(3);
let splitNumber = ref(4);
const { width: formWidth } = useElementSize(formElRef);
provide('addChildForm', addChildForm);
const getFormClass = computed(() => {
if (props.formLayout === 'flexVertical') {
return formConfig.formLayout.flexVertical;
}
if (props.formLayout === 'flex') {
return formConfig.formLayout.flex;
}
if (props.formLayout === 'flexv2') {
return formConfig.formLayout.flexv2;
if (props.formLayout) {
return formConfig.formLayout[props.formLayout as keyof typeof formConfig.formLayout];
}
return formConfig.formLayout.vertical;
});
@@ -302,17 +314,19 @@
getComponentSpan,
splitNumber,
finish,
expandAll,
};
},
});
</script>
<style lang="less" scoped>
@gap: 16px;
.ns-form {
.ant-row {
flex: 1;
}
.ns-operate {
margin-bottom: 16px;
margin-bottom: @gap;
text-align: right;
margin-left: auto;
@@ -334,5 +348,20 @@
margin-left: 6px;
}
}
.ns-form-title {
text-align: left;
height: 22px;
// line-height: 32px;
//font-size: 16px;
font-weight: bold;
user-select: text;
margin-bottom: calc(@gap - 0px);
display: flex;
justify-content: space-between;
align-items: center;
:deep(.ant-btn) {
padding: 0;
}
}
}
</style>

View File

@@ -15,4 +15,7 @@ export const formProps = {
formLayout: PropTypes.string.def('flex'),
expand: PropTypes.bool.def(true),
showExpand: PropTypes.bool.def(false),
// 收起全部
expandAll: PropTypes.bool.def(true), // 默认是否全部展开
showExpandAll: PropTypes.bool.def(true), // 是否展示右上角的全部收起展开
};

View File

@@ -180,7 +180,6 @@
* 获取数据
*/
const fetch = () => {
console.log('requiredParams', getBindValues.value.checkRequiredParams);
if (getBindValues.value.checkRequiredParams === false) {
options.value = [];
return;

View File

@@ -56,6 +56,9 @@ export const tableProps = {
rowKey: PropTypes.oneOfType([PropTypes.func, PropTypes.string]).def('key'),
refreshTime: PropTypes.number.def(0),
enableTableSession: PropTypes.bool.def(false),
expand: PropTypes.bool.def(true),
showExpand: PropTypes.bool.def(true),
expand: PropTypes.bool.def(true), // 默认是否展开
showExpand: PropTypes.bool.def(false), // 是否展示右下角的收起展开
// 收起全部
expandAll: PropTypes.bool.def(true), // 默认是否全部展开
showExpandAll: PropTypes.bool.def(true), // 是否展示右上角的全部收起展开
};

View File

@@ -72,8 +72,11 @@
},
setup(props) {
const { columnActions, searchData, data } = toRefs(props);
const reload = inject('reload', () => {});
const { filterAction, transformAction } = useAction({ reload });
const clearCheck = inject('clearCheck', () => {});
const { filterAction, transformAction } = useAction({ reload, clearCheck });
const route = useRoute();
const getData = computed(() => {
return {

View File

@@ -1,9 +1,9 @@
<!-- @format -->
<template>
<div class="ns-table-header" v-if="!isEmpty(getActions)">
<!-- <div class="ns-table-title" v-if="tableTitle">{{ tableTitle }}</div> -->
<div class="ns-table-header-action">
<div class="ns-table-header">
<div class="ns-table-title ns-title-extra-box" v-if="tableTitle">{{ tableTitle }}</div>
<div class="ns-table-header-action" v-if="!isEmpty(getActions)">
<slot name="header" :data="data"></slot>
<template v-for="item in getActions" :key="item.name">
<ns-button @click="item.finalHandle()" :disabled="item.dynamicDisabled" :type="item.type">

View File

@@ -3,7 +3,7 @@
<template>
<div class="ns-table" :class="{ 'ns-table-no-search': !(formConfig?.schemas.length > 0) }">
<!-- tabletitle -->
<div
<!-- <div
class="ns-table-title"
@click="
() => {
@@ -12,9 +12,10 @@
"
v-if="tableTitle">
<ns-icon v-if="showBack" class="backIcon" name="left" />{{ tableTitle }}
</div>
</div> -->
<div class="ns-table-container">
<!-- todo drag -->
<div class="ns-part-tree" v-if="!isEmpty(treeConfig)">
<ns-tree-api v-bind="getTreeBindValue" @select="treeSelect" />
</div>
@@ -28,93 +29,44 @@
v-bind="formConfig"
:expand="expand"
:showExpand="showExpand"
:expandAll="expandAll"
:showExpandAll="showExpandAll"
:model="formModel"
@finish="formFinish" />
</div>
<a-row type="flex" class="ns-table-main">
<!-- <a-col :flex="getTreeWidth" v-if="!isEmpty(treeConfig)">
<ns-tree v-if="getTreeData.length" v-bind="getTreeBindValue" @select="treeSelect" />
</a-col> -->
<a-col flex="auto">
<ns-table-header
v-if="!isEmpty(headerActions) || tableTitle"
:headerActions="headerActions"
:searchData="formModel"
:tableTitle="tableTitle"
:data="tableState.selectedRows">
<template #header="data">
<slot name="header" v-bind="data || {}"></slot>
<div class="ns-table-main">
<ns-table-header
v-if="!isEmpty(headerActions) || tableTitle"
:headerActions="headerActions"
:searchData="formModel"
:tableTitle="tableTitle"
:data="tableState.selectedRows">
<template #header="data">
<slot name="header" v-bind="data || {}"></slot>
</template>
</ns-table-header>
<ns-basic-table ref="tableElRef" v-bind="getTableBindValues" :dataSource="tableData">
<template #emptyText>
<template v-if="tableState.loadError">
<div class="ns-table-content">
<div class="fetch-error">
<p>{{ tableState.loadErrorMessage }}</p>
<ns-button type="primary" ghost @click="reload">重新加载</ns-button></div
></div
>
</template>
</ns-table-header>
<ns-basic-table ref="tableElRef" v-bind="getTableBindValues" :dataSource="tableData">
<template #emptyText>
<template v-if="tableState.loadError">
<div class="ns-table-content">
<div class="fetch-error">
<p>{{ tableState.loadErrorMessage }}</p>
<ns-button type="primary" ghost @click="reload">重新加载</ns-button></div
></div
>
</template>
<template v-else-if="tableState.loading"
><div class="ns-table-content"></div
></template>
<template v-else>
<div class="ns-table-content"> <a-empty /> </div>
</template>
<template v-else-if="tableState.loading"
><div class="ns-table-content"></div
></template>
<template v-else>
<div class="ns-table-content"> <a-empty /> </div>
</template>
</template>
<template #[item]="data" v-for="item in Object.keys($slots)" :key="item">
<slot :name="item" v-bind="data || {}"></slot>
<template v-if="item === 'bodyCell'">
<template v-if="data?.column?.textEllipsis">
<span
class="tool-tips"
:style="{ width: `${data.column.textWidth || data.column.width}px` }">
<ns-tooltip
placement="top"
v-if="
data.column.customRender
? data.column.customRender(data)
: data.record[data.column.dataIndex]
">
<template #title>
<span>{{
data.column.customRender
? data.column.customRender(data)
: data.record[data.column.dataIndex] || '-'
}}</span>
</template>
<span class="text-ellipsis">{{
data.column.customRender
? data.column.customRender(data)
: data.record[data.column.dataIndex] || '-'
}}</span>
</ns-tooltip>
<span class="text-ellipsis" v-else> - </span>
</span>
</template>
<template v-if="data.column.dataIndex === 'tableAction'">
<ns-table-action
:data="data.record"
:searchData="formModel"
:columnActions="getColumnActions" />
</template>
<template v-if="data.column.edit">
<ns-table-cell
:value="data.text"
:record="data.record"
:column="data.column"
:index="data.index" />
</template>
</template>
<template v-if="item === 'footer'">
<ns-table-footer :footerActions="footerActions" :data="ediRowData" />
</template>
</template>
<template #bodyCell="data" v-if="!Object.keys($slots).includes('bodyCell')">
<template v-if="data.column.textEllipsis">
<template #[item]="data" v-for="item in Object.keys($slots)" :key="item">
<slot :name="item" v-bind="data || {}"></slot>
<template v-if="item === 'bodyCell'">
<template v-if="data?.column?.textEllipsis">
<span
class="tool-tips"
:style="{ width: `${data.column.textWidth || data.column.width}px` }">
@@ -155,15 +107,61 @@
:index="data.index" />
</template>
</template>
<template
#footer
v-if="!Object.keys($slots).includes('footer') && !isEmpty(footerActions)">
<template v-if="item === 'footer'">
<ns-table-footer :footerActions="footerActions" :data="ediRowData" />
</template>
</ns-basic-table>
</a-col>
</a-row>
</template>
<template #bodyCell="data" v-if="!Object.keys($slots).includes('bodyCell')">
<template v-if="data.column.textEllipsis">
<span
class="tool-tips"
:style="{ width: `${data.column.textWidth || data.column.width}px` }">
<ns-tooltip
placement="top"
v-if="
data.column.customRender
? data.column.customRender(data)
: data.record[data.column.dataIndex]
">
<template #title>
<span>{{
data.column.customRender
? data.column.customRender(data)
: data.record[data.column.dataIndex] || '-'
}}</span>
</template>
<span class="text-ellipsis">{{
data.column.customRender
? data.column.customRender(data)
: data.record[data.column.dataIndex] || '-'
}}</span>
</ns-tooltip>
<span class="text-ellipsis" v-else> - </span>
</span>
</template>
<template v-if="data.column.dataIndex === 'tableAction'">
<ns-table-action
:data="data.record"
:searchData="formModel"
:columnActions="getColumnActions" />
</template>
<template v-if="data.column.edit">
<ns-table-cell
:value="data.text"
:record="data.record"
:column="data.column"
:index="data.index" />
</template>
</template>
<template
#footer
v-if="!Object.keys($slots).includes('footer') && !isEmpty(footerActions)">
<ns-table-footer :footerActions="footerActions" :data="ediRowData" />
</template>
</ns-basic-table>
</div>
</a-spin>
</div>
</div>
@@ -234,6 +232,10 @@
loadErrorMessage: '',
loadinterval: 0,
});
const clearCheck = () => {
tableState.selectedRowKeys = [];
tableState.selectedRows = [];
};
const route = useRoute();
const { getColumnActionWidth } = useTableColumn({
columnActions: Object.assign({}, tableConfig.columnActions, props.columnActions),
@@ -412,8 +414,6 @@
return false;
});
console.log(getPagination.value);
const getTableBindValues = computed(() => {
const { params, dynamicParams } = props;
return {
@@ -513,7 +513,6 @@
tableState.loadError = false;
tableState.loadErrorMessage = '';
dataRef.value = res;
console.log(props.listField);
tableData.value = get(unref(dataRef), props.listField);
//saas项目配置
if (attrs['getPageParams']) {
@@ -619,10 +618,12 @@
}
provide('reload', reload); //提供刷新功能
provide('clearCheck', clearCheck); //提供清空选中功能
return {
navigateBack,
reload,
clearCheck,
formElRef,
tableElRef,
getColumnActions,
@@ -669,7 +670,7 @@
display: flex;
.ns-part-tree {
width: 300px;
padding: 16px;
// padding: 16px;
overflow-y: auto;
}
.ns-part-table {
@@ -677,6 +678,13 @@
min-width: 0;
}
}
:deep(.ant-spin-container) {
display: flex;
flex-direction: column;
.ns-table-main {
height: 100%;
}
}
.ns-table-content {
// background: #e5ebf0;
margin: 16px;

View File

@@ -14,6 +14,7 @@ export const treeProps = {
type: [String, Object, Function] as PropType<string | Function | AxiosRequestConfig>,
default: undefined,
},
treeData: PropTypes.array.def([]),
params: PropTypes.object.def(() => ({})),
dynamicParams: PropTypes.oneOfType([
PropTypes.string,
@@ -38,6 +39,8 @@ export const treeProps = {
blockNode: PropTypes.bool.def(true),
defaultExpandAll: PropTypes.bool.def(true),
resultField: PropTypes.string.def('data'),
header: PropTypes.object,
isSticky: PropTypes.bool.def(true),
transform: {
type: Function,
default: (data: any) => data,

View File

@@ -1,38 +1,62 @@
<template>
<a-spin :spinning="treeState.loading">
<div v-if="!formConfig?.schema">
<ns-form ref="formElRef" v-bind="formConfig" :model="formModel" @finish="formFinish" />
<div class="ns-tree-form">
<div v-show="header" class="ns-tree-title">
<ns-icon :name="header.icon" size="14" />
<span>{{ header.title }}</span>
</div>
<div v-show="!formConfig?.schema">
<ns-form ref="formElRef" v-bind="formConfig" :model="formModel" @finish="formFinish" />
</div>
</div>
<div style="min-height: 300px; overflow-y: scroll">
<ns-tree v-if="treeData?.length" v-bind="getBindValue" v-model:selectedKeys="selectedKeys">
<template #[item]="data" v-for="(item, index) in Object.keys($slots)" :key="index">
<slot :name="item" v-bind="{ ...data, formModel } || {}"></slot>
</template>
</ns-tree>
<!-- <a-empty v-if="!treeData?.length" /> -->
</div>
<ns-tree v-if="treeData?.length" v-bind="getBindValue" v-model:selectedKeys="selectedKeys">
<template #[item]="data" v-for="(item, index) in Object.keys($slots)" :key="index">
<slot :name="item" v-bind="data || {}"></slot>
</template>
</ns-tree>
</a-spin>
</template>
<script lang="ts" setup>
import { computed, reactive, ref, unref, useAttrs } from 'vue';
import { computed, nextTick, reactive, ref, unref, useAttrs, watch } from 'vue';
import { TreeDataItem } from 'ant-design-vue/es/tree/Tree';
import { useApi } from '/nerv-lib/use/use-api';
import { AxiosRequestConfig } from 'axios';
import { get } from 'lodash-es';
import { useRoute } from 'vue-router';
import { isEmpty } from 'lodash-es';
import { debounce } from 'lodash-es';
import { treeProps, treeFormProps } from '/nerv-lib/component/tree/props';
const formElRef = ref();
defineOptions({
name: 'NsTreeApi',
});
const emit = defineEmits(['update:treeData']);
// const model = defineModel('treeData');
const formElRef = ref();
const props = defineProps(treeProps);
const treeData = ref<TreeDataItem[]>([]);
const selectedKeys = ref(props.defaultSelectedKeys || []);
const treeData = ref(props.treeData);
const selectedKeys = ref(props.selectedKeys || []);
const { httpRequest } = useApi();
const requestConfig: AxiosRequestConfig = { method: 'get' };
const route = useRoute();
const attrs = useAttrs();
const formModel = reactive({});
watch(
() => props.treeData,
(val) => {
treeData.value = val;
},
{
deep: true,
},
);
const treeState = reactive({
loading: true,
loading: false,
});
const formConfig = computed(() => {
return {
@@ -40,9 +64,13 @@
...props.formConfig,
};
});
const formFinish = () => {
getData();
};
const isSticky: any = computed(() => {
return props.isSticky ? 'sticky' : 'static';
});
const formFinish = debounce((data: object) => {
selectedKeys.value = [];
getData(data);
}, 200);
const getBindValue = computed(() => ({
...attrs,
...props,
@@ -52,22 +80,24 @@
treeState.loading = loading;
};
const httpPrams = computed(() => {
return { ...route.params, ...route.query, ...props.defaultParams };
return { ...route.params, ...route.query, ...props.params };
});
const getData = () => {
const getData = (params = {}) => {
const { api, transform, resultField } = props;
treeData.value = [];
if (!api) return;
setLoading(true);
httpRequest({
api,
params: httpPrams,
pathParams: { ...route.params, ...route.query },
requestConfig,
params: { ...httpPrams.value, ...params },
pathParams: { ...route.params, ...route.query, ...params },
requestConfig: { ...requestConfig, data: { ...httpPrams.value, ...params } },
})
.then((res) => {
treeData.value = transform(get(res, resultField));
emit('update:treeData', treeData.value);
// model.value = treeData.value;
})
.finally(() => {
setLoading(false);
@@ -76,4 +106,39 @@
getData();
</script>
<style lang="less" scoped></style>
<style lang="less" scoped>
@gap: 16px;
:deep(.ant-form-item) {
margin-bottom: @gap;
}
:deep(.ns-form::after) {
display: none;
}
.ns-tree-form {
position: v-bind(isSticky);
top: 0;
background-color: @white;
z-index: 2;
& ~ div {
padding: 0 @gap !important;
}
}
.ns-tree-title {
font-weight: bold;
user-select: text;
padding: @gap;
margin-bottom: @gap;
padding-bottom: 10px;
border-bottom: 1px solid #e9e9e9;
> span {
padding-left: 6px;
}
& ~ div {
padding: 0 @gap !important;
width: 100%;
}
}
</style>

View File

@@ -0,0 +1,9 @@
<!-- <?xml version="1.0" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg t="1625651626016" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="3205" xmlns:xlink="http://www.w3.org/1999/xlink" width="200" height="200"><defs><style type="text/css"></style></defs><path d="M853.333333 921.6c-20.48 0-34.133333-6.826667-47.786666-20.48l-682.666667-682.666667c-27.306667-27.306667-27.306667-68.266667 0-95.573333s68.266667-27.306667 95.573333 0l682.666667 682.666667c27.306667 27.306667 27.306667 68.266667 0 95.573333-13.653333 13.653333-27.306667 20.48-47.786667 20.48z" p-id="3206"></path><path d="M170.666667 921.6c-20.48 0-34.133333-6.826667-47.786667-20.48-27.306667-27.306667-27.306667-68.266667 0-95.573333l682.666667-682.666667c27.306667-27.306667 68.266667-27.306667 95.573333 0s27.306667 68.266667 0 95.573333l-682.666667 682.666667c-13.653333 13.653333-27.306667 20.48-47.786666 20.48z" p-id="3207"></path></svg> -->
<svg width="14" height="14" viewBox="0 0 14 14" xmlns="http://www.w3.org/2000/svg">
<mask id="mask0" mask-type="alpha" maskUnits="userSpaceOnUse" x="0" y="0" width="14" height="14">
<rect width="14" height="14" />
</mask>
<g mask="url(#mask0)">
<path opacity="0.4611" d="M7.61936 7L10.8767 3.74132C11.0411 3.57683 11.0411 3.30564 10.8767 3.14115L10.8589 3.12337C10.6945 2.95888 10.4234 2.95888 10.259 3.12337L7.00167 6.3865L3.74434 3.12337C3.57992 2.95888 3.30885 2.95888 3.14442 3.12337L3.12665 3.14115C2.95778 3.30564 2.95778 3.57683 3.12665 3.74132L6.38397 7L3.12665 10.2587C2.96223 10.4232 2.96223 10.6944 3.12665 10.8588L3.14442 10.8766C3.30885 11.0411 3.57992 11.0411 3.74434 10.8766L7.00167 7.61795L10.259 10.8766C10.4234 11.0411 10.6945 11.0411 10.8589 10.8766L10.8767 10.8588C11.0411 10.6944 11.0411 10.4232 10.8767 10.2587L7.61936 7Z" />
</g>
</svg>

View File

@@ -0,0 +1,8 @@
<!-- <?xml version="1.0" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg class="icon" width="200px" height="200.00px" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg"><path d="M793.6 329.6L568 491.2c-9.6 8-9.6 22.4 0 30.4l224 172.8c12.8 9.6 30.4 1.6 30.4-14.4V345.6c0-16-17.6-24-28.8-16zM531.2 329.6L305.6 491.2c-9.6 8-9.6 22.4 0 30.4l224 172.8c12.8 9.6 30.4 1.6 30.4-14.4V345.6c0-16-16-24-28.8-16zM267.2 699.2c17.6 0 32-14.4 32-32V356.8c0-17.6-14.4-32-32-32s-32 14.4-32 32v310.4c0 17.6 14.4 32 32 32z" /></svg> -->
<svg width="10" height="7" viewBox="0 0 10 7" fill="none" xmlns="http://www.w3.org/2000/svg">
<g>
<path fill-rule="evenodd" clip-rule="evenodd" d="M5.6001 3.5L9.8001 0V7L5.6001 3.5Z" fill="#909090"/>
<path fill-rule="evenodd" clip-rule="evenodd" d="M1.3999 3.5L5.5999 0V7L1.3999 3.5Z" fill="#909090"/>
<rect width="1.4" height="7" fill="#909090"/>
</g>
</svg>

After

Width:  |  Height:  |  Size: 972 B

File diff suppressed because one or more lines are too long

After

Width:  |  Height:  |  Size: 18 KiB

View File

@@ -1,6 +1,6 @@
<svg width="20" height="9" viewBox="0 0 20 9" fill="none" xmlns="http://www.w3.org/2000/svg">
<svg width="20" height="9" viewBox="0 0 20 9" fill="currentColor" xmlns="http://www.w3.org/2000/svg">
<g id="Group 6356610" opacity="0.65">
<path id="Vector" d="M6.89084 5.13637L9.85448 8.1L8.95448 9L4.45446 4.49997L8.95448 -8.86233e-07L9.85448 0.899993L6.89091 3.86357L19.0918 3.86351L19.0918 5.13631L6.89084 5.13637Z" fill="white" fill-opacity="0.3"/>
<path id="Vector_2" d="M1.27246 0.0904379L1.27246 9L-0.000335336 9L-0.000334557 0.0904378L1.27246 0.0904379Z" fill="white" fill-opacity="0.65"/>
<path id="Vector" d="M6.89084 5.13637L9.85448 8.1L8.95448 9L4.45446 4.49997L8.95448 -8.86233e-07L9.85448 0.899993L6.89091 3.86357L19.0918 3.86351L19.0918 5.13631L6.89084 5.13637Z" fill="currentColor" fill-opacity="0.3"/>
<path id="Vector_2" d="M1.27246 0.0904379L1.27246 9L-0.000335336 9L-0.000334557 0.0904378L1.27246 0.0904379Z" fill="currentColor" fill-opacity="0.65"/>
</g>
</svg>

Before

Width:  |  Height:  |  Size: 503 B

After

Width:  |  Height:  |  Size: 525 B

View File

@@ -11,14 +11,26 @@ export const formConfig = {
gutter: [0, 0],
justify: 'space-around',
},
flex: {
// layout: 'horizontal',
class: 'ns-flex-form ns-flex-form-horizontal',
wrapperCol: { span: 16 },
span: 7,
formVertical: {
layout: 'horizontal',
class: 'ns-vertical-form',
wrapperCol: { span: 24 },
labelCol: { span: 0 },
span: 24,
sm: null, //≥576px <=768
lg: null, //>= 768
gutter: [0, 0],
justify: 'space-around',
},
flex: {
// layout: 'horizontal',
class: 'ns-flex-form ns-flex-form-horizontal',
wrapperCol: { span: 24 },
labelCol: { span: 0 },
span: 6,
sm: null, //≥576px <=768
lg: null, //>= 768
gutter: [20, 0],
justify: 'space-between',
},
flexv2: {

View File

@@ -70,7 +70,6 @@ export const authorizationService = defineStore({
this.dealResourceTree(this.userResourceList);
} else {
const res = await this.appConfig.userResource();
console.log(res, 'hshshhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhh');
this.userResourceList = res.data ? res.data : [];
if (this.appConfig.defaultResource) {
@@ -92,7 +91,6 @@ export const authorizationService = defineStore({
//初始化菜单树
async initMenuResource() {
const res = await this.appConfig.userResource();
console.log(res, 'bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb');
this.initMenus = [];
if (this.appConfig.resourceName && res.data && res.data.length) {

View File

@@ -1,42 +1,63 @@
/**
Ant全局组件样式
*/
.ant-menu-submenu-popup{
.ant-menu-title-content a{
margin-left: 0!important;
.ant-menu-submenu-popup {
.ant-menu-title-content a {
margin-left: 0 !important;
}
.ant-menu-submenu-title .anticon + span{
.ant-menu-submenu-title .anticon + span {
margin-left: 0 !important;
}
.ant-menu-submenu {
height: 40px ;
height: 40px;
margin-top: 4px !important;
margin-bottom: 4px !important;
// display: flex;
// align-items: center;
}
.ant-menu-submenu-title .ant-menu-title-content .anticon{
.ant-menu-submenu-title .ant-menu-title-content .anticon {
margin-left: 0 !important;
margin-right: 6px;
}
li{
li {
display: flex;
align-items: center;
}
}
//侧边栏收缩单个菜单样式
.ant-menu-inline-collapsed-tooltip {
.ant-tooltip-inner,
.ant-tooltip-arrow-content {
background-color: @white;
a {
color: @black !important;
}
}
}
#app .ant-layout-has-sider .ant-menu-vertical .ant-menu-item,#app .ant-menu-vertical-left .ant-menu-item, #app.ant-menu-vertical-right .ant-menu-item,#app .ant-menu-inline .ant-menu-item,#app .ant-menu-vertical .ant-menu-submenu-title,#app .ant-menu-vertical-left .ant-menu-submenu-title,#app .ant-menu-vertical-right .ant-menu-submenu-title,#app .ant-menu-inline .ant-menu-submenu-title {
margin-top: 0px !important;
#app .ant-layout-has-sider .ant-menu-vertical .ant-menu-item,
#app .ant-menu-vertical-left .ant-menu-item,
#app.ant-menu-vertical-right .ant-menu-item,
#app .ant-menu-inline .ant-menu-item,
#app .ant-menu-vertical .ant-menu-submenu-title,
#app .ant-menu-vertical-left .ant-menu-submenu-title,
#app .ant-menu-vertical-right .ant-menu-submenu-title,
#app .ant-menu-inline .ant-menu-submenu-title {
margin-top: 0px !important;
margin-bottom: 0px !important;
height: 40px !important;
// height: 50px !important;
}
.ant-menu-vertical.ant-menu-sub, .ant-menu-vertical-left.ant-menu-sub, .ant-menu-vertical-right.ant-menu-sub{
.ant-menu-vertical.ant-menu-sub,
.ant-menu-vertical-left.ant-menu-sub,
.ant-menu-vertical-right.ant-menu-sub {
min-width: 0 !important;
}
.ant-menu-submenu .ant-menu-sub{
.ant-menu-submenu .ant-menu-sub {
min-width: 0 !important;
}
.ant-layout-sider-children{
.ant-layout-sider-children {
padding-bottom: 40px;
}
@@ -83,56 +104,53 @@
width: 100%;
height: 100%;
position: absolute;
top:0;
left:0;
top: 0;
left: 0;
content: '';
background-color: #37abc4;
opacity: .1;
// background-color:red;
opacity: 0.1;
}
//
//.ant-menu-item:not(.ant-menu-item-selected) a:hover {
// .ant-menu-item:not(.ant-menu-item-selected) a:hover {
// color: @text-color;
//}
// }
//
//.ant-menu-item::after {
// .ant-menu-item::after {
// z-index: 2;
//}
// }
//
//.ant-menu-light .ant-menu-submenu:not(.ant-menu-submenu-selected) .ant-menu-submenu-title:hover {
// color: @text-color;
//}
//
//.ant-layout-sider {
// .ant-layout-sider {
// max-width: @layout-sider-width !important;
// min-width: @layout-sider-width !important;
// width: @layout-sider-width !important;
//}
//
//.ant-menu-submenu:hover > .ant-menu-submenu-title > .ant-menu-submenu-arrow {
// color: @layout-sider-arrow-color;
//}
//
//.ant-menu-submenu-arrow {
// color: @layout-sider-arrow-color;
//}
//
//
// }
// .ant-menu-submenu:hover > .ant-menu-submenu-title > .ant-menu-submenu-arrow {
// color: @layout-sider-arrow-color;
// }
.ant-menu-submenu-arrow {
color: @layout-sider-arrow-color;
}
//
//
// //btn
// .ant-btn:hover {
// border-color: @border-color-base;
// }
//
.ant-btn-primary:hover, .ant-btn-primary:focus {
//
.ant-btn-primary:hover,
.ant-btn-primary:focus {
// color: #fff !important;
color: #fff ;
// color: #fff ;
}
//禁用时鼠标光标
.ant-btn[disabled],
.ant-btn[disabled]:hover,
@@ -153,7 +171,6 @@
box-shadow: none !important;
}
.ant-input-affix-wrapper-focused {
box-shadow: none !important;
}
@@ -194,8 +211,6 @@
}
}
//.ant-btn[disabled],
//.ant-btn[disabled]:hover {
// border: 1px solid transparent;
@@ -265,13 +280,15 @@
// 表头加粗
.ant-table-thead > tr > th {
font-weight: bold;
}
}
//表头不换行
.ant-table-thead > tr > th{
.ant-table-thead > tr > th {
word-break: keep-all;
white-space: nowrap;
}
.ant-menu.ant-menu-dark, .ant-menu-dark .ant-menu-sub, .ant-menu.ant-menu-dark .ant-menu-sub{
.ant-menu.ant-menu-dark,
.ant-menu-dark .ant-menu-sub,
.ant-menu.ant-menu-dark .ant-menu-sub {
background-size: cover;
}

View File

@@ -77,11 +77,11 @@
::-webkit-scrollbar {
width: 6px;
height: 8px;
height: 6px;
}
::-webkit-scrollbar-track {
background-color: rgb(0 0 0 / 5%);
background-color: transparent;
}
::-webkit-scrollbar-thumb {
@@ -137,10 +137,17 @@ body {
height: 100%;
}
a {
transition: color 0.08s;
}
.ant-layout-sider-children {
overflow: auto;
}
.ant-menu.ant-menu-inline-collapsed > .ant-menu-submenu > .ant-menu-submenu-title {
padding: auto;
}
.ns-view-spinning {
position: fixed !important;
width: calc(100% - @ns-content-padding * 2 - @layout-sider-width) !important;
@@ -156,9 +163,35 @@ body {
color: @primary-color;
}
.ant-tabs .ns-table-search {
border-top-left-radius: 0px !important;
border-top-right-radius: 0px !important;
}
.ant-tabs .ns-table-main {
border-bottom-left-radius: 0px !important;
border-bottom-right-radius: 0px !important;
}
// 自定义的title样式
.ns-title-extra-box {
position: relative;
padding-left: 9px;
&::before {
content: '';
position: absolute;
left: 0;
top: 50%;
transform: translateY(-50%);
height: 13px;
width: 3px;
border-radius: 1px;
background-color: @primary-color;
}
}
//状态颜色
.commonStatus {
&::before{
&::before {
content: '';
width: 8px;
height: 8px;
@@ -170,60 +203,60 @@ body {
}
.statusWarn {
&::before{
&::before {
background-color: #fa8214;
}
}
.statusSuccess {
&::before{
background-color: #0D9E3E;
&::before {
background-color: #0d9e3e;
}
}
.statusRunning {
&::before{
background-color: #1C4DDC;
&::before {
background-color: #1c4ddc;
}
}
.statusError {
&::before{
background-color: #D4321C;
&::before {
background-color: #d4321c;
}
}
.statusEmpty {
&::before{
width:0;
&::before {
width: 0;
}
width:0;
width: 0;
}
.statusNotStart {
&::before{
background-color: #8B98AB;
&::before {
background-color: #8b98ab;
}
}
.statusDone{
&::before{
.statusDone {
&::before {
background-color: #697383;
}
}
.statusInvalid{
&::before{
background-color: #AEAEAE;
.statusInvalid {
&::before {
background-color: #aeaeae;
}
}
.statusNull {
&::before{
background-color: #8B98AB;
&::before {
background-color: #8b98ab;
}
// background-color: #8B98AB;
}/* */
.statusNull2{
&::before{
} /* */
.statusNull2 {
&::before {
background-color: #697383;
}
// background-color: #697383;

View File

@@ -12,15 +12,17 @@
@font-size-base: 14px; // 主字号
@layout-body-background: #f0f2f5; //框架背景色
@layout-body-background: #fff; //框架背景色
@layout-header-hover:rgba(0, 0, 0, 0.06);//默认退出hover色
@layout-header-background: #37abc4; // 头部背景色
@layout-header-background: #fff; // 头部背景色
@ant-layout-sider-collapsed-background:rgb(255, 255, 255);//导航栏收缩后背景色
@layout-header-height: 48px;
@layout-header-height: 72px;
@layout-header-padding: 0 50px;
@layout-sider-width: 208px; //侧边导航宽度
@layout-sider-arrow-color: #808d96; //侧边导航箭头颜色
@layout-sider-width: 220px; //侧边导航宽度
@layout-sider-collapsed-width: 60px; //侧边导航收缩宽度
@layout-sider-arrow-color: @black; //侧边导航箭头颜色
// Border color
@border-color-base: hsv(0, 0, 85%); // base border outline a component
@@ -40,7 +42,7 @@
@form-item-margin-bottom: 24px;
//menu
@menu-item-height: 48px;
@menu-item-height: 50px;
@menu-item-active-bg: none;
@menu-item-boundary-margin: 0px;
@@ -53,4 +55,12 @@
//list-table
@ns-content-padding: 24px;
@ns-nav-shutters-height: 31px;
@ns-nav-shutters-height: 48px;
// main-content
@ns-content-bg: #f1f2f6;
@ns-box-shadow: 0px 5px 16px #e4e6e8;
@ns-content-box-shadow: 0px 0px 16px #e4e6e8;
@ns-gap: 20px;
@ns-border-radius: 12px;

View File

@@ -3,7 +3,7 @@
<a-layout class="ns-application" style="height: 100%">
<ns-header class="ns-header-menu" />
<a-layout>
<ns-sider class="ns-left-menu" />
<!-- <ns-sider class="ns-left-menu" /> -->
<a-layout>
<a-layout-content class="content" :style="{ minHeight: '400px', overflow: 'auto' }">
<div>
@@ -43,6 +43,7 @@
display: flex;
align-items: center;
justify-content: center;
padding-top: 200px;
img {
width: 240px;
height: 240px;

View File

@@ -15,8 +15,6 @@
import { tableProps } from '/nerv-lib/component/table/props';
import { PropTypes } from '/nerv-lib/util/type';
import { cloneDeep, get, isArray } from 'lodash-es';
tableProps.expand = PropTypes.bool.def(false);
export default defineComponent({
name: 'NsViewListTable',
props: {
@@ -70,6 +68,7 @@
// }
return formConfig;
});
const getBindValue = computed(() => ({
...attrs,
...props,
@@ -80,7 +79,7 @@
sticky:
props.sticky === false
? false
: { offsetHeader: props.headerActions.length === 0 && !props.title ? 0 : 89 },
: { offsetHeader: props.headerActions.length === 0 && !props.title ? 0 : 0 },
}));
if (formConfig) {
@@ -103,43 +102,63 @@
<style lang="less" scoped>
//关闭 sticky 模式 底部滚动条
@gap: 16px;
@border-gap: @gap solid #e5ebf0;
:deep(.ns-table-container) {
border-top: @border-gap;
}
@border-gap: @gap solid @ns-content-bg;
:deep(.ns-table) {
.ns-part-tree {
border-right: @border-gap;
height: calc(100vh - 158px);
}
.ns-table-main {
padding: 0px @gap;
border-top: @border-gap;
// margin: 16px;
// background-color: #fff;
}
.ns-table-search {
padding: @gap @gap 0;
// margin: 16px;
background: #fff;
// border-width: 16px 0 16px 0px;
// border-color: #e5ebf0;
// border-style: solid;
// border-top: 16px solid #e5ebf0;
}
.ns-table-header {
position: sticky;
z-index: 3;
top: 0;
left: 0;
background-color: @white;
}
.ant-table-sticky-scroll {
display: none !important;
}
.ns-basic-table {
padding-top: @gap;
// 以防样式串
.ns-list-table:not(.ant-drawer-body > *):not(.ant-form > *) {
height: 100%;
background-color: @ns-content-bg;
:deep(.ns-table) {
height: inherit;
.ns-table-container,
.ns-part-tree,
.ant-spin-container {
height: inherit;
}
.ns-part-tree,
.ns-table-search,
.ns-table-main {
background-color: @white;
border-radius: @ns-border-radius;
// box-shadow: @ns-box-shadow;
}
.ns-table-container {
gap: @ns-gap;
}
.ns-part-tree {
}
.ns-part-table {
border-radius: @ns-border-radius;
}
.ns-table-main {
padding: 0px @gap;
margin-top: @ns-gap;
background-color: @white;
overflow-y: auto;
// box-shadow: @ns-content-box-shadow;
// border-top: @border-gap;
// margin: 16px;
// background-color: #fff;
}
.ns-table-search {
padding: @gap @gap 0;
}
.ns-table-header {
// position: sticky;
z-index: 3;
top: 0;
left: 0;
background-color: @white;
}
.ant-table-sticky-scroll {
display: none !important;
}
.ns-basic-table {
padding-top: @gap;
}
}
}

View File

@@ -12,13 +12,15 @@
:menuList="newMenu"
:initSiderKey="selectedSiderKeys"
:initSiderOpenKey="selectedSiderOpenKeys" />
<a-layout>
<a-layout class="ns-application-layout-main">
<newNsTags v-if="configStore.useHistoryTag" />
<ns-tags v-else />
<!-- <NsBreadcrumb v-else :breadcrumbList="breadcrumbList" /> -->
<NsBreadcrumb :breadcrumbList="breadcrumbList" />
<a-layout-content class="ns-content">
<!-- <transition name="fade-slide" mode="out-in"> -->
<!-- <div> -->
<ns-content />
<!-- </div> -->
<!-- </transition> -->
</a-layout-content>
</a-layout>
@@ -73,12 +75,10 @@
authorizationStore.setProjectId(Cookies.get('projectUuid'));
}
const { route: routeModules, routeModuleObject, routeModule } = storeToRefs(useRouteStore());
console.log(routeModules, 'routeModules');
const headers = computed(() => {
const module = cloneDeep(routeModules.value);
const list = [];
console.log('----');
keepAliveStore.clearKeepAlive();
for (let i = 0, j = module.length; i < j; i++) {
const mod = module[i] || {};
@@ -322,21 +322,29 @@
flex-direction: row;
}
}
.ns-application-layout-main {
padding-top: calc(@layout-header-height + @ns-nav-shutters-height * 2);
height: 100vh;
overflow: auto;
}
.ns-content {
position: relative;
flex: 1 1 auto;
padding-top: 80px;
background-color: #e5ebf0;
padding: @ns-gap;
// padding-top: calc(@layout-header-height + @ns-nav-shutters-height);
background-color: @ns-content-bg;
> div {
height: 100%;
background-color: #fff;
margin: 0 16px 16px 16px;
background-color: @white;
border-radius: @ns-border-radius;
overflow-y: auto;
// overflow-x: hidden;
// margin: 0 16px 16px 16px;
}
.ns-content-main {
// margin: @ns-content-padding;
// margin: @ns-gap;
min-height: calc(100% - 48px);
height: calc(100% - 16px);
// height: calc(100% - 16px);
// background-color: @white;
}
.ns-view {

View File

@@ -85,14 +85,14 @@
<style lang="less" scoped>
.NsBreadcrumb {
width: 100%;
padding: 0 16px;
min-height: 42px;
background: #ffffff;
padding: 0 @ns-gap;
min-height: @ns-nav-shutters-height;
background: @white;
display: flex;
align-items: center;
position: fixed;
top: 48px;
z-index: 505;
top: calc(@layout-header-height + @ns-nav-shutters-height);
z-index: 5;
border-bottom: 1px solid rgba(0, 0, 0, 0.05);
}
</style>

View File

@@ -9,11 +9,13 @@
style="width: 192px; height: 48px; object-fit: contain" />
<ns-icon v-else name="headerLogin" class="headerLogin" style="width: auto; height: 48px" />
</div>
<div>
<component v-if="headerSlot" :is="headerSlot.component" v-bind="headerSlot.componentProps" />
</div>
<div class="header-menu">
<a-menu style="width: 100%" mode="horizontal" :selectedKeys="initHeaderKey">
<a-menu
v-if="menuList?.length"
style="width: 100%"
mode="horizontal"
:selectedKeys="initHeaderKey">
<a-menu-item v-for="item in menuList" :key="item.name">
<div @click="tochildren(item)">
<ns-icon :name="item.meta.icon" size="16" /><span>{{ item.meta.title }}</span>
@@ -61,17 +63,17 @@
</template>
</template>
</a-menu>
<div v-else>
<div v-if="configStore.projectName" class="projectTitle">{{ configStore.projectName }}</div>
</div>
</div>
<div class="nsHeader_action">
<div class="projectName action" v-if="showProject">
{{ projectName ? projectName : enterpriseName }}
<div>
<component
v-if="headerSlot"
:is="headerSlot.component"
v-bind="headerSlot.componentProps" />
</div>
<div
class="projectName action"
v-if="['服务管理平台', '报表中心'].includes(configStore.resourceInfo?.application?.label)"
@click="backDoor"
>{{ '返回门户' }}</div
>
<div v-if="bellInfo.isShow" class="bells action" @click="backMessage">
<a-badge :count="messageCount > 99 ? 99 : messageCount">
<ns-icon name="bells" size="32" />
@@ -80,7 +82,7 @@
<a-dropdown :trigger="['hover']">
<div class="userName action">
<!-- <img src="/asset/image/login/adminIcon.png" /> -->
<ns-icon class="headerAdminIcon" name="headerAdminIcon" size="20" />
<!-- <ns-icon class="headerAdminIcon" name="headerAdminIcon" size="20" /> -->
<span
style="
display: block;
@@ -176,7 +178,6 @@
const configStore = appConfigStore();
const { getThemeConfig: themeConfig } = storeToRefs(configStore);
console.log(configStore.headerSlotConfig);
const headerSlot = computed(() => {
return configStore.headerSlotConfig;
});
@@ -424,11 +425,25 @@
}
}
:deep(.ant-menu-submenu-title) {
color: rgba(255, 255, 255, 0.9);
// color: rgba(255, 255, 255, 0.9);
}
.header-menu {
flex: 1;
.projectTitle {
font-size: 28px;
font-weight: 500;
letter-spacing: 2.33px;
line-height: 40px;
color: @primary-color;
text-align: left;
overflow: hidden;
text-wrap: nowrap;
text-overflow: ellipsis;
}
}
:deep(.header-menu .ant-menu-title-content) {
div {
color: rgba(255, 255, 255, 0.9);
// color: rgba(255, 255, 255, 0.9);
.ns-icon {
margin-right: 7px;
transform: translateY(2px);
@@ -436,7 +451,7 @@
}
}
:deep(.ant-menu-submenu-title .ant-menu-title-content) {
color: rgba(255, 255, 255, 0.9);
// color: rgba(255, 255, 255, 0.9);
.ns-icon {
margin-right: 7px;
transform: translateY(2px);
@@ -447,10 +462,13 @@
padding: 0;
position: fixed;
top: 0;
z-index: 5;
z-index: 999;
width: 100%;
background-image: url(/asset/image/header.png);
background-size: 100% 100%;
// background-image: url(/asset/image/header.png);
// background-size: 100% 100%;
box-shadow: @ns-box-shadow;
display: flex;
align-items: center;
}
:deep(.ant-badge-count) {
@@ -504,10 +522,10 @@
}
.nsHeader_action {
color: rgba(255, 255, 255, 0.9);
color: @black;
padding-left: 16px;
padding-right: 16px;
width: 208px;
// width: 208px;
display: flex;
align-items: center;
justify-content: right;

View File

@@ -4,15 +4,16 @@
<div class="ns-left-menu-space" :class="{ 'ns-left-menu-space-collapsed': collapsed }">
<a-layout-sider
class="ns-left-menu"
:width="208"
:collapsedWidth="48"
:collapsedWidth="60"
:width="sideWidth"
:collapsed="collapsed"
breakpoint="lg"
:trigger="null"
v-if="menuList && menuList[0] && menuList[0].children">
{{ $refs.getComputedStyle }}
<a-menu
mode="inline"
:inlineIndent="16"
:inlineIndent="20"
:openKeys="collapsed ? [] : initSiderOpenKey"
:selectedKeys="initSiderKey"
v-for="(item, index) in menuList[0].children"
@@ -21,9 +22,9 @@
v-if="item.children !== undefined && !item.meta.hideChildren && !item.isHide"
:key="item.name">
<template #title>
<span role="img" class="anticon"
><ns-icon :name="item.meta.icon ? item.meta.icon : ''" size="16"
/></span>
<span role="img" class="anticon">
<ns-icon :name="item.meta.icon ? item.meta.icon : ''" size="15" />
</span>
<span>{{ item.meta.title }}</span>
</template>
<!-- 跳转外部链接 -->
@@ -37,27 +38,30 @@
target="_blank"
rel="noopener noreferrer">
{{ newOpen.name }}
</a></a-menu-item
>
</a>
</a-menu-item>
</div>
</div>
<div v-else>
<div v-for="sitem in checkAuthList(item.children)" :key="sitem.name">
<a-menu-item
v-if="(sitem.children === undefined || sitem.meta.hideChildren) && !sitem.isHide"
:key="sitem.name"
><router-link style="margin-left: 8px" :to="{ name: sitem.name }">{{
sitem.meta.title
}}</router-link></a-menu-item
>
:key="sitem.name">
<router-link :to="{ name: sitem.name }">
<span role="img" class="anticon" v-if="sitem.meta.icon">
<ns-icon :name="sitem.meta.icon ? sitem.meta.icon : ''" size="15" />
</span>
<span>{{ sitem?.meta?.title }}</span>
</router-link>
</a-menu-item>
<a-sub-menu
class="threeSubMenu"
v-if="sitem.children !== undefined && !sitem.meta.hideChildren && !sitem.isHide"
:key="sitem.name">
<template #title>
<span role="img" style="margin-left: 8px" class="anticon" v-show="sitem.meta.icon"
><ns-icon :name="sitem.meta.icon" size="16"
/></span>
<span role="img" class="anticon" v-show="sitem.meta.icon">
<ns-icon :name="sitem.meta.icon" size="15" />
</span>
<span>{{ sitem.meta.title }}</span>
</template>
<div v-for="ditem in checkAuthList(sitem.children)" :key="ditem.name">
@@ -66,13 +70,9 @@
v-if="ditem.children !== undefined && !ditem.isHide"
:key="ditem.name">
<template #title>
<span
role="img"
style="margin-left: 8px"
class="anticon"
v-show="ditem.meta.icon"
><ns-icon :name="ditem.meta.icon" size="16"
/></span>
<span role="img" class="anticon" v-show="ditem.meta.icon">
<ns-icon :name="ditem.meta.icon" size="15" />
</span>
<span>{{ ditem.meta.title }}</span>
</template>
<div
@@ -82,19 +82,22 @@
:class="
initSiderKey.includes(fiveFloorItem.name) ? 'ant-menu-item-selected' : ''
"
v-if="fiveFloorItem.meta?.type !== 'op'"
><router-link style="margin-left: 8px" :to="{ name: fiveFloorItem.name }">{{
fiveFloorItem?.meta?.title ? fiveFloorItem?.meta?.title : ''
}}</router-link></a-menu-item
>
v-if="fiveFloorItem.meta?.type !== 'op'">
<router-link :to="{ name: fiveFloorItem.name }">
{{ fiveFloorItem?.meta?.title ? fiveFloorItem?.meta?.title : '' }}123
</router-link>
</a-menu-item>
</div>
</a-sub-menu>
<a-menu-item v-if="ditem.meta?.type !== 'op' && item.children === undefined"
><router-link style="margin-left: 8px" :to="{ name: ditem.name }">{{
ditem?.meta?.title ? ditem?.meta?.title : ''
}}</router-link></a-menu-item
>
<a-menu-item v-if="ditem.meta?.type !== 'op' && item.children === undefined">
<router-link :to="{ name: ditem.name }">
<span role="img" class="anticon" v-if="ditem.meta.icon">
<ns-icon :name="ditem.meta.icon ? ditem.meta.icon : ''" size="15" />
</span>
<span>{{ ditem?.meta?.title }}123</span>
</router-link>
</a-menu-item>
</div>
</a-sub-menu>
</div>
@@ -110,10 +113,9 @@
:key="item.name">
<router-link :to="{ name: item.name }">
<span role="img" class="anticon" v-show="item.meta.icon">
<ns-icon :name="item.meta.icon ? item.meta.icon : ''" size="16" />
<ns-icon :name="item.meta.icon ? item.meta.icon : ''" size="15" />
</span>
<span style="margin-left: 8px">{{ item.meta.title }}</span>
<!-- </span> -->
<span>{{ item.meta.title }}</span>
</router-link>
</a-menu-item>
</a-menu>
@@ -128,7 +130,7 @@
<script lang="ts">
import { MenuUnfoldOutlined, MenuFoldOutlined } from '@ant-design/icons-vue';
import { defineComponent, inject, ref, watchEffect } from 'vue';
import { computed, defineComponent, inject, onMounted, ref, watchEffect } from 'vue';
import { appConfigStore } from '/nerv-lib/saas/store/modules/app-config';
import { authorizationService } from '/nerv-base/store/modules/authorization-service';
import { Emitter } from 'mitt';
@@ -148,6 +150,10 @@
setup: (props) => {
const mittEmit = inject('mittEmit') as Emitter<emitEvents>;
const router = useRouter();
const sideWidth = computed(() => {
return getComputedStyle(document.querySelector('.ns-left-menu-trigger')!).width;
});
const dealRouter = (menuList, routerInfo) => {
menuList?.forEach((item) => {
if (item.name === routerInfo.name) {
@@ -204,70 +210,126 @@
checkOpAuth,
checkAuthList,
checkAuth,
sideWidth,
};
},
});
</script>
<style lang="less" scoped>
@icon-gap: 12px;
// :deep(.ant-layout-sider) {
// width: @layout-sider-width !important;
// max-width: @layout-sider-width !important;
// }
.ns-left-menu {
position: fixed;
top: 0;
left: 0;
height: calc(100% - 40px);
// background-color: @white;
background-image: url(/asset/image/side.png);
background-color: @white;
// background-image: url(/asset/image/side.png);
background-size: cover;
padding-top: 48px;
:deep(.ant-layout-sider-children) {
background-color: transparent;
.ant-menu-root {
background-color: transparent;
padding-top: calc(@layout-header-height + @icon-gap);
.ant-menu-item-selected {
// color: #fff !important;
// background: @primary-color;
border-radius: 12px;
height: 40px;
line-height: 40px;
padding: 5px @ns-gap;
position: relative;
a {
color: @white !important;
}
.ant-menu-submenu-title {
// color: rgba(255, 255, 255, 0.9);
}
.router-link-active::before {
// background-color: @primary-color;
width: 90%;
}
:deep(.ant-layout-sider-children) {
transition: all 0.1s;
padding: 0 @ns-gap;
// background-color: transparent;
.ant-menu-root {
// background-color: transparent;
}
.ant-menu-submenu-title,
.ant-menu-item {
height: @menu-item-height;
border-radius: @ns-border-radius;
// overflow: hidden;
// color: @black;
.ant-menu-submenu-arrow {
// color:inherit
// color: rgba(255, 255, 255, 0.9);
// color: @black;
}
}
.ant-menu {
color: rgba(255, 255, 255, 0.9);
}
.ant-menu-item a {
color: rgba(255, 255, 255, 0.9);
}
.ant-menu-submenu-expand-icon,
.ant-menu-submenu-arrow {
color: rgba(255, 255, 255, 0.9);
color: rgba(@black, 0.85);
}
.ant-menu-sub.ant-menu-inline {
background-color: #001027;
background-color: @white;
// > div {
// margin-inline: 20px;
// }
}
.ant-menu-item-active:not(.ant-menu-item-selected),
.ant-submenu-item-active {
// color: rgba(@primary-color, 0.1) !important;
background-color: rgba(@primary-color, 0.1);
border-radius: 12px;
}
}
}
#iframeApplication .ns-left-menu {
padding-top: 0px;
}
.ant-menu-submenu-title .anticon + span {
margin-left: 8px !important;
.anticon + span {
margin-left: @icon-gap !important;
}
.ns-left-menu-space {
width: 208px;
height: 100%;
background-color: #fff;
width: 100%;
height: auto;
z-index: 9;
box-shadow: @ns-box-shadow;
// background-color: #fff;
overflow: hidden;
transition: all 0.2s;
flex: 0 0 208px;
&.ns-left-menu-space-collapsed {
width: 48px;
flex: 0 0 48px;
flex: 0 0 @layout-sider-width;
// transition: all 0.1s;
// &:not(.ns-left-menu-space-collapsed) :deep(.ant-menu-title-content) {
// padding-left: 8px;
// }
:deep(.ant-menu-item-selected) {
// color: #fff !important;
background: @primary-color;
// border-radius: 12px;
// height: 40px;
// line-height: 40px;
// width: auto;
// margin-inline: @ns-gap;
// padding-left: @ns-gap !important;
position: relative;
a {
color: @white !important;
}
}
}
.ns-left-menu-space-collapsed {
z-index: 11;
width: @layout-sider-collapsed-width;
flex: 0 0 @layout-sider-collapsed-width;
:deep(.ant-layout-sider-children) {
transition: all 0.1s;
padding: 0 calc(@ns-gap / 4) !important;
}
.ns-left-menu-trigger {
width: 48px !important;
width: @layout-sider-collapsed-width !important;
justify-content: center;
padding-left: 0px;
}
@@ -279,14 +341,14 @@
}
.ns-left-menu-trigger {
width: 208px;
width: @layout-sider-width;
height: 40px;
transition: all 0.2s;
border-top: 1px solid rgba(0, 0, 0, 0.06);
position: absolute;
z-index: 999;
cursor: pointer;
background: #163361;
// background: #163361;
bottom: 0px;
display: flex;
align-items: center;
@@ -304,12 +366,12 @@
font-size: 18px;
line-height: 64px;
transform: rotate(0deg);
transition: color 0.3s;
}
.ant-menu-submenu-selected > .ant-menu-submenu-title > .ant-menu-submenu-expand-icon,
.ant-menu-submenu-selected > .ant-menu-submenu-title > .ant-menu-submenu-arrow {
color: red !important;
transition: color 0.2s;
}
// .ant-menu-submenu-selected > .ant-menu-submenu-title > .ant-menu-submenu-expand-icon,
// .ant-menu-submenu-selected > .ant-menu-submenu-title > .ant-menu-submenu-arrow {
// color: red !important;
// }
.ant-menu-submenu-selected .secendIcon {
color: @primary-color !important;
}
@@ -325,42 +387,40 @@
border: unset !important;
content: '';
}
:deep(.ant-menu-sub .ant-menu-item-selected::after) {
position: absolute;
width: 2px;
height: 14px;
background: #fff;
border: unset;
top: 14px;
left: 20px;
right: 0;
bottom: 0;
content: '';
}
:deep(.ant-menu-submenu .ant-menu-submenu .ant-menu-sub .ant-menu-item-selected::after) {
position: absolute;
width: 2px;
height: 14px;
background: #fff;
border: unset;
top: 14px;
left: 40px;
right: 0;
bottom: 0;
content: '';
}
// :deep(.ant-menu-title-content) {
// padding-left: 8px;
// :deep(.ant-menu-sub .ant-menu-item-selected::after) {
// position: absolute;
// width: 2px;
// height: 14px;
// // background: #fff;
// border: unset;
// top: 14px;
// left: 20px;
// right: 0;
// bottom: 0;
// content: '';
// }
// :deep(.ant-menu-submenu .ant-menu-submenu .ant-menu-sub .ant-menu-item-selected::after) {
// position: absolute;
// width: 2px;
// height: 14px;
// // background: #fff;
// border: unset;
// top: 14px;
// left: 40px;
// right: 0;
// bottom: 0;
// content: '';
// }
// :deep(.firstMenuSub .ant-menu-submenu-title) {
// padding-left: 8px !important;
// }
:deep(.firstMenuItem-selected) {
background: @primary-color!important;
border-radius: 4px;
}
:deep(.ns-left-menu .ant-layout-sider-children .ant-menu-submenu-arrow) {
color: rgba(255, 255, 255, 0.5);
// color: rgba(255, 255, 255, 0.5);
}
</style>

View File

@@ -266,7 +266,7 @@
display: flex;
align-items: center;
position: fixed;
top: 48px;
top: @layout-header-height;
z-index: 505;
}
#iframeApplication .ns-tabs {
@@ -281,7 +281,7 @@
display: flex;
align-items: center;
position: fixed;
top: 48px;
top: @layout-header-height;
z-index: 505;
}
:deep(.ant-tabs-nav) {

View File

@@ -1,7 +1,9 @@
<!-- @format -->
<template>
<div :class="leftMenuTrigger ? 'nav-shutters-collapsed' : 'nav-shutters'">
<div
class="nav-shutters-container"
:class="leftMenuTrigger ? 'nav-shutters-collapsed' : 'nav-shutters'">
<div class="shutters-left">
<ns-icon
@click.stop="moveTags('right')"
@@ -12,16 +14,27 @@
<div class="fatherTags">
<ul id="tag-list" ref="tags">
<div v-for="(item, index) in tagList" :key="index" @click="clickTag(item)">
<li
@click.right="openMenu($event, index)"
:id="selectTags.path === item.path ? 'ischoice' : ''">
<span>{{ isdisabledl || isdisabledr ? item.title.substring(0, 4) : item.title }}</span>
<li :id="selectTags.path === item.path ? 'ischoice' : ''">
<a-dropdown :trigger="['contextmenu']" @visibleChange="(v) => visibleChange(v, item)">
<span>
{{ isdisabledl || isdisabledr ? item.title.substring(0, 4) : item.title }}
</span>
<template #overlay>
<a-menu>
<a-menu-item key="1"> <li @click="closeAllMenu">关闭所有标签页</li></a-menu-item>
<a-menu-item key="2">
<li @click="closeOhterMenu">关闭其他标签页</li>
</a-menu-item>
</a-menu>
</template>
</a-dropdown>
<ns-icon
style="min-width: 12px; min-height: 12px; color: rgba(0, 0, 0, 0.45)"
v-if="item.path !== baseHeader.redirect"
name="close"
@click="delTags($event, item)" /> </li
></div>
@click="delTags($event, item)" />
</li>
</div>
</ul>
</div>
<div class="shutters-right">
@@ -31,10 +44,10 @@
name="fastBackward"
class="icon_kt" />
</div>
<ul v-show="visible" :style="{ left: left + 'px', top: top + 'px' }" class="contextmenu">
<!-- <ul v-show="visible" :style="{ left: left + 'px', top: top + 'px' }" class="contextmenu">
<li @click="closeAllMenu">关闭所有标签页</li>
<li @click="closeOhterMenu">关闭其他标签页</li>
</ul>
</ul> -->
</div>
</template>
<script lang="ts">
@@ -52,11 +65,11 @@
const visible = ref<boolean>(false);
const leftMenuTrigger = ref(false);
mittEmit.on('leftMenuTrigger', (val) => {
console.log('leftMenuTrigger', val);
leftMenuTrigger.value = val;
});
// const tagList = ref<tagsClass[]>([]);
const rightNumber = ref<number>(0);
const rightTarget = ref();
const tagsStore = useTags();
const router = useRouter();
const keepAliveStore = useKeepAlive();
@@ -66,16 +79,17 @@
const tagList = computed(() => tagsStore.getTags);
//右键关闭所有标签页
const closeAllMenu = () => {
tagsStore.sliceTags(0);
// tagsStore.sliceTags(0);
tagsStore.clearTags();
};
//右键关闭其他标签页
const closeOhterMenu = () => {
let choicetag = tagList.value[rightNumber.value];
tagsStore.sliceTags(0);
tagsStore.addTags(choicetag);
// let choicetag = tagList.value[rightNumber.value];
tagsStore.clearTags();
tagsStore.addTags(rightTarget.value);
clickTag(rightTarget.value);
};
const selectTags = inject('selectTags');
console.log(selectTags);
const baseHeader = inject('baseHeader');
const closeMenu = () => {
visible.value = false;
@@ -92,7 +106,11 @@
});
}
};
const visibleChange = (visible, target) => {
if (visible) rightTarget.value = target;
};
return {
visibleChange,
leftMenuTrigger,
router,
clickTag,
@@ -173,8 +191,8 @@
if (str !== '') {
offset = str.match(/\d+/)[0];
}
this.left = offsetLeft + menuMinWidth * (i - 1) - 50 - offset;
this.top = offsetTop;
this.left = offsetLeft + menuMinWidth * (i - 1) - 30 - offset;
this.top = offsetTop - 20;
this.visible = true;
}
},
@@ -276,29 +294,34 @@
<style lang="less" scoped>
.nav-shutters {
width: calc(100% - 208px);
width: calc(100% - @layout-sider-width);
// padding: 0 12px;
min-height: 32px;
height: 32px;
background: #ffffff;
min-height: @ns-nav-shutters-height;
height: @ns-nav-shutters-height;
background: @white;
display: flex;
align-items: center;
position: fixed;
top: 48px;
z-index: 2;
top: @layout-header-height;
z-index: 6;
border-bottom: 1px solid rgba(0, 0, 0, 0.05);
}
.nav-shutters-collapsed {
width: calc(100% - 40px);
width: calc(100% - @layout-sider-collapsed-width);
// padding: 0 12px;
min-height: 32px;
height: 32px;
background: #ffffff;
min-height: @ns-nav-shutters-height;
height: @ns-nav-shutters-height;
background: @white;
display: flex;
align-items: center;
position: fixed;
top: 48px;
z-index: 505;
top: @layout-header-height;
z-index: 10;
border-bottom: 1px solid rgba(0, 0, 0, 0.05);
}
.nav-shutters-container {
display: flex;
align-items: center;
}
.shutters-left {
height: @ns-nav-shutters-height;
@@ -312,8 +335,8 @@
.icon_kj {
mix-blend-mode: normal;
cursor: pointer;
width: 12px !important;
height: 12px !important;
// width: 12px !important;
// height: 12px !important;
}
}
.shutters-right {
@@ -327,8 +350,8 @@
justify-content: center;
.icon_kt {
cursor: pointer;
width: 12px !important;
height: 12px !important;
// width: 12px !important;
// height: 12px !important;
transform: rotateY(180deg);
}
}
@@ -339,8 +362,9 @@
}
.fatherTags {
width: calc(100% - 64px);
height: 31px;
flex: 1;
// width: calc(100% - 64px);
height: @ns-nav-shutters-height;
min-width: 400px;
overflow: hidden;
}
@@ -395,10 +419,21 @@
}
}
#ischoice {
background-color: #f5f9fb;
// background-color: #f5f9fb;
position: relative;
&::after {
position: absolute;
content: '';
bottom: 0;
width: 30%;
height: 3px;
background-color: @primary-color;
left: 50%;
transform: translateX(-50%);
}
}
#ischoice span {
color: @text-color !important;
color: @primary-color !important;
}
.checkBox {
height: 200px;
@@ -419,7 +454,7 @@
position: absolute;
list-style-type: none;
padding: 5px 0;
border-radius: 2px;
border-radius: @border-radius-base;
font-size: 12px;
font-weight: 400;
color: #333;

View File

@@ -19,33 +19,51 @@
<h1 class="lg_card_title">{{ configStore.projectName }}</h1>
<p v-show="!errorShow" style="height: 8px"></p>
<p v-show="errorShow" class="lg_card_error">{{ errorMsg }}</p>
<!-- <p class="lg_card_tip">用户名/手机号</p> -->
<a-input class="loginInfo" placeholder="用户名" v-model:value="userName">
<template #prefix>
<ns-icon class="loginIcon" name="userName" size="19" style="margin-right: 20px" />
</template>
</a-input>
<!-- <p class="lg_card_tip">密码</p> -->
<a-input-password class="loginInfo" placeholder="密码" v-model:value="password">
<template #prefix>
<ns-icon class="loginIcon" name="passWord" size="19" style="margin-right: 20px" />
</template>
</a-input-password>
<!-- 验证码 -->
<a-form name="basic" :model="formState" @finish="submit">
<a-form-item name="userName" :rules="[{ required: true, message: '请输入用户名' }]">
<!-- <p class="lg_card_tip">用户名/手机号</p> -->
<a-input class="loginInfo" placeholder="用户名" v-model:value="userName">
<template #prefix>
<ns-icon class="loginIcon" name="userName" size="19" style="margin-right: 20px" />
</template>
</a-input>
</a-form-item>
<a-input v-model:value="code" placeholder="验证码" class="loginInfo">
<template #prefix>
<ns-icon class="loginIcon" name="verifyIcon" size="19" style="margin-right: 20px" />
</template>
<template #addonAfter>
<ns-verify @get-code="onGetCode" />
</template>
</a-input>
<!-- 记住密码 -->
<a-checkbox v-model:checked="isRemember" class="loginInfo">记住密码</a-checkbox>
<a-button @click="submit" :loading="loading" type="primary" class="loginInfo"
>登录</a-button
>
<a-form-item name="password" :rules="[{ required: true, message: '请输入密码' }]">
<!-- <p class="lg_card_tip">密码</p> -->
<a-input-password class="loginInfo" placeholder="密码" v-model:value="password">
<template #prefix>
<ns-icon class="loginIcon" name="passWord" size="19" style="margin-right: 20px" />
</template>
</a-input-password>
</a-form-item>
<a-form-item name="code" :rules="[{ validator }]">
<!-- 验证码 -->
<a-input v-model:value="code" placeholder="验证码" class="loginInfo">
<template #prefix>
<ns-icon
class="loginIcon"
name="verifyIcon"
size="19"
style="margin-right: 20px" />
</template>
<template #addonAfter>
<ns-verify @get-code="onGetCode" />
</template>
</a-input>
</a-form-item>
<!-- <a-form-item name="remember"> -->
<!-- 记住密码 -->
<a-checkbox v-model:checked="isRemember" class="loginInfo">记住密码</a-checkbox>
<!-- </a-form-item> -->
<a-form-item>
<a-button html-type="submit" :loading="loading" type="primary" class="loginInfo">
登录
</a-button>
</a-form-item>
</a-form>
</div>
</a-layout-content>
<!-- <a-layout-footer>Copyright 2021 xu科技 All Rights Reserved</a-layout-footer> -->
@@ -54,7 +72,7 @@
</template>
<script lang="ts">
import { defineComponent, onMounted, ref } from 'vue';
import { defineComponent, onMounted, reactive, ref } from 'vue';
import { useRouter } from 'vue-router';
import { appConfigStore } from '/nerv-lib/saas/store/modules/app-config';
import { authorizationService } from '/nerv-base/store/modules/authorization-service';
@@ -81,11 +99,12 @@
// title.value = appConfig.title ? appConfig.title : '账号登录';
const loading = ref<boolean>(false);
const configStore = appConfigStore();
console.log(configStore);
const formState = reactive({ userName, password, code });
const { getThemeConfig: themeConfig, projectName } = storeToRefs(configStore);
const useAuthorization = authorizationService();
const rememberFunc = (data) => {
console.log(isRemember.value);
if (!isRemember.value) return;
@@ -97,24 +116,28 @@
const { accountNo, password: pwd } = JSON.parse(data);
userName.value = accountNo;
password.value = pwd;
formState.userName = userName.value;
formState.password = password.value;
}
});
const submit = (): void => {
if (password.value === '') {
errorMsg.value = '请输入密码';
errorShow.value = true;
return;
}
if (userName.value === '') {
errorMsg.value = '请输入账号';
errorShow.value = true;
return;
}
// if (!code.value) {
// errorMsg.value = '请输入验证码';
const submit = (value): void => {
console.log(value);
// if (password.value === '') {
// errorMsg.value = '请输入密码';
// errorShow.value = true;
// return;
// }
// if (userName.value === '') {
// errorMsg.value = '请输入账号';
// errorShow.value = true;
// return;
// }
// if (!code.value) {
// // errorMsg.value = '请输入验证码';
// // errorShow.value = true;
// return;
// }
// if (code.value.toLocaleLowerCase() !== verifyCode.value.toLocaleLowerCase()) {
// errorMsg.value = '请输入正确的验证码';
// errorShow.value = true;
@@ -208,7 +231,15 @@
const onGetCode = (res) => {
verifyCode.value = res;
};
const validator = async (rule, value) => {
if (!value) return Promise.reject('请输入验证码');
if (value?.toLocaleLowerCase() !== verifyCode.value.toLocaleLowerCase())
return Promise.reject('请输入正确的验证码');
};
return {
validator,
formState,
projectName,
onGetCode,
code,
@@ -323,7 +354,7 @@
.loginInfo {
height: 48px;
width: 100%;
margin-bottom: 24px;
// margin-bottom: 24px;
font-size: 16px !important;
:deep(.ant-input) {
@@ -340,10 +371,12 @@
}
}
.loginInfo:last-child {
margin-bottom: 16px;
// margin-bottom: 16px;
}
.loginInfo:nth-child(5n + 2) {
margin-bottom: 0px;
.loginInfo:nth-child(4) {
width: fit-content;
// margin-bottom: 0px;
// height: 20px !important;
}
}

View File

@@ -39,6 +39,7 @@ export interface Action {
type?: string; //按钮 primary | ghost | dashed | link | text | default
dynamicDisabled?: boolean | Function;
isReload?: boolean;
isClearCheck?: boolean; // 清空table选中行数据
state?: String; // edit 为编辑态 其他为编辑中
extra?: Recordable;
}
@@ -50,11 +51,12 @@ export interface Action {
*/
interface actionParams {
reload?: Function;
clearCheck?: Function;
}
export function useAction(actionParams: actionParams = {}) {
const router = useRouter();
const route = useRoute();
const { reload } = actionParams;
const { reload, clearCheck } = actionParams;
const { getPath } = usePath();
const { httpRequest } = useApi();
const authService = authorizationService();
@@ -169,6 +171,7 @@ export function useAction(actionParams: actionParams = {}) {
checkDefaultParams,
handle,
isReload = false,
isClearCheck = false,
extra,
} = action;
const { getParams } = useParams();
@@ -239,6 +242,7 @@ export function useAction(actionParams: actionParams = {}) {
api: null,
handle,
isReload,
isClearCheck,
};
let modelInstance: Recordable = {};
if (name && name.toLowerCase().includes('exports')) {
@@ -332,6 +336,9 @@ export function useAction(actionParams: actionParams = {}) {
if (isReload) {
isFunction(reload) && reload();
}
if (isClearCheck) {
isFunction(clearCheck) && clearCheck();
}
setTimeout(() => {
modeUpdate({
okButtonProps: {

View File

@@ -4,7 +4,7 @@ import type { Result } from './axios.d';
import { NsMessage } from '/nerv-lib/component/message';
import { routerConfig } from '/nerv-base/config/router.config';
import { Cookies } from '/nerv-lib/util/cookie';
import { RequestEnum } from '/@/enum/http-enum.ts';
import { RequestEnum, errCodeMap } from '/@/enum/http-enum.ts';
export class NSAxios {
private instance: AxiosInstance;
@@ -75,12 +75,6 @@ export class NSAxios {
return config;
}, undefined);
const errCodeMap = new Map<number, any>([
[13, ''],
[1, ''],
[10086, () => routerConfig.logout()],
]);
// type closeType = (() => void) | undefined;
this.instance.interceptors.response.use(
(res: AxiosResponse) => {
@@ -88,8 +82,6 @@ export class NSAxios {
const code = res?.data?.retcode;
const msg = res?.data?.msg;
if (errCodeMap.has(code)) {
console.log(errCodeMap.get(code));
NsMessage.error({
content: msg,
key: this.errorMsgKey,