Compare commits

12 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
30 changed files with 818 additions and 458 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">

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

@@ -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,4 +1,5 @@
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`,

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,7 +19,7 @@ export const appConfig = {
projectType: 'web',
baseApi: '/api',
projectName: '济阳站_AI智能BAS系统',
enablePermissions: true,
enablePermissions: false,
// themeColor: '#eee',
siderPosition: 'left',
baseHeader: '/parkingManage',
@@ -92,6 +92,7 @@ export const appConfig = {
permissionVos: 'permissionVos',
});
sessionStorage.setItem('ORGID', info.orgId);
selectDefaultValue.value = info.orgId;
return { data: { ...trD } };
});
},

View File

@@ -7,8 +7,6 @@ import type { App, Directive, DirectiveBinding } from 'vue';
import { authorizationService } from '/nerv-lib/saas/store/modules/authorization-service';
function isAuth(el: Element, binding: any) {
console.log(el, binding);
const { checkPermission, checkAllPermission, checkPermissionRouter } = authorizationService();
const { value, modifiers } = binding;

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

@@ -10,53 +10,26 @@ const organizationManage = {
name: 'UserManage',
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: [],
},

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: '来源企业',
@@ -57,49 +59,105 @@ const doWnload = (url) => {
};
const mockData = ref(data.listData);
export const treeConfig = {
defaultExpandAll: true,
header: {
icon: 'orgLink',
title: '能耗分组',
export const formSchema = [
{
field: 'isCreate',
component: 'NsInput',
show: false,
},
api: () => {
return new Promise((resolve) => {
setTimeout(() => {
resolve(data);
}, 100);
});
{
field: 'orgId',
component: 'NsInput',
show: false,
},
formConfig: {
schemas: [
{
field: 'isCreatSon',
component: 'NsInput',
show: false,
},
{
label: '节点名称',
field: 'pointName',
component: 'NsInput',
componentProps: {
placeholder: '请输入节点名称(必填)',
},
rules: [
{
field: 'type',
label: '',
component: 'NsSelect',
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: '请输入',
},
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 {

View File

@@ -2,29 +2,113 @@
<editDrawer ref="editDrawerRef" />
<editGroup ref="editGroupRef" />
<editFormula ref="editFormulaRef" />
<!-- <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="treeConfig" @select="handleSelect" />
<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, tableConfigCal } 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;
};
@@ -55,4 +139,21 @@
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,180 +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: {
header: {
icon: 'orgLink',
title: '设备类别',
},
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

@@ -65,10 +65,10 @@
</a-tabs>
<a-space v-if="activeKey === 1 || deptPermissionTreeData?.length">
<ns-button type="primary" @click="CancelApartment">取消 </ns-button>
<ns-button v-show="disabled" type="primary" @click="pipe(deptEdit, true, false)">
<ns-button v-if="disabled" type="primary" @click="pipe(deptEdit, true, false)">
编辑
</ns-button>
<ns-button v-show="!disabled" type="primary" @click="deptSure">确定</ns-button>
<ns-button v-else type="primary" @click="deptSure">确定</ns-button>
</a-space>
</div>
</a-col>
@@ -79,11 +79,11 @@
<a-row>
<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 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>
<ns-button type="primary" @click="rolePipe(deleteUser)"> 删除 </ns-button> -->
</a-space>
<a-tree
v-if="roleTreeData.length"
@@ -95,19 +95,19 @@
<template #title="data">
<div style="display: flex; justify-content: space-between; align-items: center">
<span> {{ data.zhName }}</span>
<!-- <a-dropdown>
<a-dropdown>
<ns-icon name="actionMore" size="14" class="actionMore" />
<template #overlay>
<a-menu>
<a-menu-item
v-for="(action, index) in dropRoleActions"
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> -->
</a-dropdown>
</div>
</template>
</a-tree>
@@ -139,20 +139,16 @@
<a-empty style="margin-top: 120px" v-else />
</a-tab-pane>
</a-tabs>
<a-space>
<a-space v-if="roleActiveKey === 1 || rolePermissionTreeData?.length">
<ns-button type="primary" @click="CancelUser">取消</ns-button>
<ns-button
v-show="roleDisabled"
v-if="roleDisabled"
:disabled="!roleTreeData?.length"
type="primary"
@click="rolePipe(roleEdit, false, false)">
编辑
</ns-button>
<ns-button
v-show="!roleDisabled"
:disabled="!roleTreeData?.length"
type="primary"
@click="roleSure">
<ns-button v-else :disabled="!roleTreeData?.length" type="primary" @click="roleSure">
确定
</ns-button>
</a-space>
@@ -167,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';
@@ -180,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);
@@ -224,7 +220,7 @@
/**操作拦截 */
const pipe = (func: Function, flag = false, toggle = true) => {
if (toggle) activeKey.value = 1;
// if (toggle) activeKey.value = 1;
if (flag) {
// 只有部门的操作
if (selectRef.value?.hasOwnProperty('orgInfo') || !selectRef.value?.deptInfo) {
@@ -243,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;
}
@@ -302,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;
});
@@ -325,7 +324,7 @@
// 获取角色树
const getUserTree = (params = { deptId: selectRef.value?.deptInfo?.deptId }) => {
return http.post(department.queryRoleTree, params).then((res) => {
roleTreeData.value = res.data;
roleTreeData.value = [{ zhName: '全部', selectable: false, orgInfo: {}, children: res.data }];
});
};
// 根据依赖刷新角色树
@@ -334,12 +333,12 @@
getUserTree().then(() => {
if (!roleTreeData.value?.length) {
selectRoleRef.value = {};
roleFormData.value = {};
roleFormData.value = { isLeader: 1 };
}
const info = {
node: { key: '0-0', dataRef: { ...roleTreeData.value[0] } },
node: { key: '0-0-0', dataRef: { ...roleTreeData.value[0].children[0] } },
};
SelectUserTree(['0-0'], info);
SelectUserTree([''], info);
});
}
});
@@ -351,8 +350,10 @@
callback: null,
};
// 添加部门
const addApartment = (data) => {
const { deptInfo } = data;
activeKey.value = 1;
disabled.value = false;
opMap.type = 'addDept';
@@ -369,23 +370,17 @@
orgId: deptInfo?.orgId,
sourceOrgId,
projectId,
pdeptId: deptInfo.pdeptId || '',
orgName,
});
});
};
};
const getParent = (data) => {
if (data?.parent) {
getParent(data.parent);
} else {
data;
}
};
// 添加子部门
const addApartmentSon = (data) => {
const { deptInfo } = data;
activeKey.value = 1;
disabled.value = false;
opMap.type = 'addson';
formData.value = {};
@@ -407,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(() => {
@@ -418,6 +414,7 @@
...params,
orgId,
projectId,
proleId: data.proleId || '',
deptId: selectRef.value.deptInfo.deptId,
deptName: selectRef.value.deptInfo.deptName,
});
@@ -425,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(() => {
@@ -436,7 +434,7 @@
...params,
orgId,
projectId,
proleId: selectRoleRef.value.roleId,
proleId: data.roleId,
deptId: selectRef.value.deptInfo.deptId,
deptName: selectRef.value.deptInfo.deptName,
});
@@ -444,8 +442,6 @@
};
};
const deleteDept = (data) => {
console.log(data);
// 删除逻辑
Modal.confirm({
title: '是否确认删除',
@@ -458,6 +454,7 @@
// 删除选中的数据需要清空
deptTreeSelectedKeys.value = [];
selectRef.value = '';
roleTreeData.value = [{ zhName: '全部', selectable: false, orgInfo: {}, children: [] }];
}
});
},
@@ -467,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('操作成功');
});
},
@@ -554,6 +555,7 @@
};
// 保存角色权限
const rolePermission = () => {
if (!roleTotalCheckedKeys.value?.length) return;
http
.post(department.addRolePermission, {
// deptId: selectRef.value?.deptInfo.deptId,
@@ -645,6 +647,7 @@
rolePermissionTreeData.value = [];
roleCheckedKeys.value = [];
roleTreeSelectedKeys.value = [];
roleDisabled.value = true;
};
/**
@@ -739,10 +742,10 @@
// { title: '新增角色', func: addUser, key: 'addUser' },
]);
const filterAction = (data, actions) => {
const filterAction = (data, actions, keyV = 'addDept') => {
if (data.hasOwnProperty('orgInfo')) {
// 企业节点
return actions.filter(({ key }) => key === 'addDept');
return actions.filter(({ key }) => key === keyV);
}
return actions;
};

View File

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

View File

@@ -4,30 +4,17 @@
<div class="main">
<div class="left">
<div class="top">
<ns-tree-api v-bind="orgTreeConfig" @select="handleSelect">
<ns-tree-api v-bind="orgTreeConfig" @select="handleSelect" v-model:treeData="treeData">
<template #title="data">
{{ data.orgInfo?.orgName }}
</template>
</ns-tree-api>
</div>
<div class="top">
<!-- <div class="ns-table-title">关联部门</div>
<a-input-search
v-model:value="searchValue2"
style="margin-bottom: 8px"
placeholder="请输入关联部门"
@search="onSearch2" />
<a-tree
v-if="treeData2?.length"
:tree-data="treeData2"
defaultExpandAll
@select="handleSelect2">
<template #title="data">
{{ data.deptInfo?.deptName }}
</template>
</a-tree> -->
<ns-tree-api v-bind="deptTreeConfig" @select="handleSelect2">
<ns-tree-api
v-bind="deptTreeConfig"
@select="handleSelect2"
v-model:treeData="treeDataDept">
<template #title="data">
{{ data.deptInfo?.deptName }}
</template>
@@ -87,7 +74,7 @@
import { formConfig, formConfig2 } from './config';
import { origanizemanage } from '/@/api/origanizemanage';
defineOptions({ name: 'OrderListIndex' });
defineOptions({ name: 'UserManageIndex' });
const mainRef = ref();
const data = reactive({});
@@ -113,19 +100,21 @@
const casData = ref([]);
const formSchema2 = formConfig2(casData);
const treeData = ref([]);
const treeDataDept = ref([]);
const treeData2 = ref([]);
const userAuthList = ref([]);
const orgId = JSON.parse(sessionStorage.getItem('userInfo')).orgId;
// const orgId = JSON.parse(sessionStorage.getItem('userInfo')).orgId;
const orgId = JSON.parse(sessionStorage.getItem('ORGID')!);
const orgTreeConfig = ref({
selectedKeys: ['0-0'],
defaultExpandAll: true,
api: origanizemanage.queryOrgTree,
defaultParams: { orgId },
params: { orgId },
transform: (data) => {
const otherOrg = data[0].listOrg;
const otherOrg = data[0]?.listOrg;
let treeData = [];
// 特殊处理
if (data[0].orgInfo) {
if (data[0]?.orgInfo) {
treeData = data;
}
otherOrg?.map((item) => {
@@ -153,7 +142,7 @@
const deptTreeConfig = ref({
defaultExpandAll: true,
api: origanizemanage.queryDeptTree,
defaultParams: { orgId },
params: { orgId },
header: {
title: '关联部门',
@@ -192,11 +181,11 @@
});
});
};
getOrgTree();
// getOrgTree();
// 部门树
fetch(origanizemanage.queryDeptTree).then((res) => {
treeData2.value = res.data;
});
// fetch(origanizemanage.queryDeptTree).then((res) => {
// treeData2.value = res.data;
// });
const onSearch = () => {
console.log(searchValue.value);
@@ -225,8 +214,10 @@
};
const handleSelect = (selectedKeys: any, info: any) => {
console.log(info);
fetch(origanizemanage.queryDeptTree, { orgId: info.node?.orgInfo.orgId }).then((res) => {
treeData2.value = res.data;
treeDataDept.value = res.data;
});
tableFetch({ orgId: info.node?.orgInfo.orgId });
};
@@ -298,6 +289,7 @@
opMap.value.type = 'add';
setTimeout(() => {
formData.value = {
sex: '男',
orgName: JSON.parse(sessionStorage.getItem('userInfo')).orgName,
};
userAuthList.value.splice(0);
@@ -350,30 +342,23 @@
customRender: (text: any) => {
return text.index + 1;
},
sorter: {
compare: (a, b) => a.address - b.address,
},
sorter: true,
},
{
title: '账号',
dataIndex: 'accountNo',
sorter: {
compare: (a, b) => a.accountNo - b.accountNo,
},
sorter: true,
},
{
title: '姓名',
dataIndex: 'realName',
sorter: {
compare: (a, b) => a.realName - b.realName,
},
sorter: true,
},
{
title: '性别',
dataIndex: 'sex',
sorter: {
compare: (a, b) => a.name - b.name,
},
sorter: true,
textNumber: 4,
},
{
title: '手机号',
@@ -381,11 +366,15 @@
},
{
title: '邮箱',
textNumber: 5,
textEllipsis: true,
dataIndex: 'email',
},
{
title: '组织关系',
dataIndex: 'orgName',
// textNumber: 9,
// textEllipsis: true,
},
{
title: '部门/角色',

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">

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

@@ -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

@@ -120,14 +120,8 @@
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;
});

View File

@@ -1,9 +1,9 @@
<!-- @format -->
<template>
<div class="ns-table-header" v-if="!isEmpty(getActions)">
<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">
<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

@@ -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,

View File

@@ -1,18 +1,19 @@
<template>
<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>
<a-spin :spinning="treeState.loading">
<div style="min-height: 300px">
<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 || {}"></slot>
<slot :name="item" v-bind="{ ...data, formModel } || {}"></slot>
</template>
</ns-tree>
<!-- <a-empty v-if="!treeData?.length" /> -->
@@ -20,7 +21,7 @@
</a-spin>
</template>
<script lang="ts" setup>
import { computed, nextTick, 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';
@@ -32,16 +33,28 @@
defineOptions({
name: 'NsTreeApi',
});
const emit = defineEmits(['update:treeData']);
// const model = defineModel('treeData');
const formElRef = ref();
const props = defineProps(treeProps);
const treeData = ref<TreeDataItem[]>([]);
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: false,
});
@@ -55,6 +68,7 @@
return props.isSticky ? 'sticky' : 'static';
});
const formFinish = debounce((data: object) => {
selectedKeys.value = [];
getData(data);
}, 200);
const getBindValue = computed(() => ({
@@ -66,7 +80,7 @@
treeState.loading = loading;
};
const httpPrams = computed(() => {
return { ...route.params, ...route.query, ...props.defaultParams };
return { ...route.params, ...route.query, ...props.params };
});
const getData = (params = {}) => {
@@ -82,6 +96,8 @@
})
.then((res) => {
treeData.value = transform(get(res, resultField));
emit('update:treeData', treeData.value);
// model.value = treeData.value;
})
.finally(() => {
setLoading(false);

View File

@@ -11,6 +11,17 @@ export const formConfig = {
gutter: [0, 0],
justify: 'space-around',
},
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',

View File

@@ -431,11 +431,14 @@
flex: 1;
.projectTitle {
font-size: 28px;
font-weight: 900;
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) {

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;
}
}