first commit

This commit is contained in:
wang_yp 2025-01-17 17:00:30 +08:00
parent 50c95399ae
commit 484e918229
25 changed files with 694 additions and 597 deletions

449
org.html
View File

@ -1,449 +0,0 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<title>Title</title>
</head>
<style>
@media screen and(-ms-high-contrast:active),(-ms-high-contrast:none) {
.ie_display{
display: flex;
flex-direction: column;
align-items: center;
}
.ie_margin{
margin-left: -10px!important;
}
}
</style>
<body style="overflow-y: scroll;">
<div id="depart" style="display: flex;justify-content: center;padding: 30px"></div>
</body>
<script src="http://libs.baidu.com/jquery/2.0.0/jquery.min.js"></script>
<script>
var isCompany = false;
//配置公司背景色,部门背景色,用户所在部门背景色
var comBackground = 'linear-gradient(#2196f3,#4c6cca)';
var depBackground = 'linear-gradient(#673ab7,#4c6cca)';
var userBackground = 'linear-gradient(#4CAF50,#4c6cca)';
//获取用户所在部门和id
var userDepName = '技术部';
var userDepId = '7';
var isHasTopCom = false;//是否需要另设顶层公司
var topCompany = 'XXX集团有限公司';//顶层公司名称
//1.接口返回原始数据结构
var depArr = [
{departmentname: 'CEO', subcompanyid1: '2', supdepid: '0', id: '1'},
{departmentname: '销售与市场', subcompanyid1: '3', supdepid: '1', id: '2'},
{departmentname: '生产', subcompanyid1: '2', supdepid: '1', id: '3'},
{departmentname: '人力资源部', subcompanyid1: '2', supdepid: '2', id: '4'},
{departmentname: '物流&客服部', subcompanyid1: '3', supdepid: '3', id: '5'},
{departmentname: '计划&采购部', subcompanyid1: '3', supdepid: '3', id: '6'},
{departmentname: '技术部', subcompanyid1: '2', supdepid: '4', id: '7'},
{departmentname: '采购部', subcompanyid1: '2', supdepid: '5', id: '8'},
{departmentname: '销售部', subcompanyid1: '2', supdepid: '6', id: '9'},
];
var comArr = [
{subcompanyname: 'XXX有限公司', supsubcomid: '0', id: '1'},
{subcompanyname: 'XXX有限公司华中分公司', supsubcomid: '1', id: '2'},
{subcompanyname: 'XXX有限公司华南分公司', supsubcomid: '1', id: '3'},
];
//2.将接口返回的数据拼接成链表结构
function findDep(depArr, str, arrNew) {
var arr = arrNew || [];
depArr.map(function(item, index){
if (item.departmentname == str) {
depArr.map(function(item1, index){
if (item1.id == item.supdepid) {
arr.push(item1);
if (item.supdepid == '0') {
return;
}
findDep(depArr, item1.departmentname, arr);
}
})
}
})
return arr;
}
var newComArr = [];
if(isHasTopCom){
newComArr.push({
departmentname: topCompany,
supdepid: '0',
id: '8888',
});
}
comArr.map(function(item, index){
if(isHasTopCom){
if (item.supsubcomid === '0') {
item.supsubcomid = '8888';
};
}
newComArr.push({
departmentname: item.subcompanyname,
supdepid: item.supsubcomid,
id: item.id,
});
});
function bibao(obj, s, m, str) {
var x1 = m || [];
for (var i = 0; i < obj.length; i++) {
if (obj[i].supdepid == s) {
x1.push(obj[i]);
x1.map(function (item, index) {
if (item.subcompanyid1 && isCompany) {
} else {
x1[index].child = [];
}
if (str) {
isCompany = true;
for (var i = 0; i < str.length; i++) {
if (item.id == str[i].subcompanyid1 && !item.subcompanyid1) {
x1[index].child.push(str[i]);
}
}
}
return bibao(obj, item.id, x1[index].child, str);
})
}
}
return x1;
};
var arr = bibao(depArr, '0');
var gData = bibao(newComArr,'0', [], arr);
//3.界面和样式的处理
function generate(obj, num, cb) {
if (obj && obj[0]) {
obj.map(function (item, index) {
var html = '';
var str = item.departmentname;
if (item.departmentname.indexOf(" ") > -1) {
item.departmentname = item.departmentname.replace(/\s*/g, "");
}
var str1 = '';
if (item.departmentname.indexOf('-') > -1) {
str1 = item.departmentname.replace(/-/g, '')
}else if (item.departmentname.indexOf('&') > -1) {
str1 = item.departmentname.replace(/&/g, '')
}else if (item.departmentname.indexOf('—') > -1) {
str1 = item.departmentname.replace(/—/g, '')
} else if (item.departmentname.indexOf('.') > -1) {
str1 = item.departmentname.replace(/./g, '')
} else if (item.departmentname.indexOf('') > -1) {
str1 = item.departmentname.replace(//g, '')
} else if (item.departmentname.indexOf('') > -1) {
str1 = item.departmentname.replace(//g, '')
} else if (item.departmentname.indexOf('') > -1 && item.departmentname.indexOf('') > -1) {
str1 = item.departmentname.replace(//g, '').replace(//g, '');
} else if (item.departmentname.indexOf('(') > -1 && item.departmentname.indexOf(')') > -1) {
str1 = item.departmentname.replace('(', '').replace(')', '');
} else if (item.departmentname.indexOf('-') > -1 && item.departmentname.indexOf('(') > -1 && item.departmentname.indexOf(')') > -1) {
str1 = item.departmentname.replace(/-/g, '').replace('(', '').replace(')', '');
} else if (item.departmentname.indexOf('-') > -1 && item.departmentname.indexOf('') > -1 && item.departmentname.indexOf('') > -1) {
str1 = item.departmentname.replace(/-/g, '').replace(//g, '').replace(//g, '');
} else {
str1 = item.departmentname;
}
var idStr = str1 + item.id;
var idStrSpan = item.departmentname + item.id + 'span';
var child = item.child;
var spanBar = num != 1 ? "<div style='background: #4c6cca;display: block;width: 3px;height: 20px;margin: auto;'></div>" : "<span></span>";
var background = item.subcompanyid1 ? depBackground : comBackground;
if (item.departmentname == userDepName && item.id== userDepId) {
background = userBackground;
}
var span = child && child.length > 0 ? "<div id=" + idStrSpan + " style='color:#fff;cursor:pointer;font-size: 25px;margin-top: -10px' onclick='display(" + JSON.stringify(item) + ",$(this)," + index + ")'>+</div>" : "<span></span>";
html += "<div class='ie_display' style='text-align: center;font-size:14px;color:#fff;width: 200px'><div style='display:flex;align-items: center'><div>" + spanBar + "<div style='background: " + background + ";box-shadow:5px 5px 5px #6A48D7;width: 150px;margin: auto;text-align: center;border-radius: 5px;display: flex;align-items:center;justify-content:space-between;height: 60px'><div style='width: 20px'></div><div>" + str + "</div><div style='display: flex;flex-direction: column;height: 100%;justify-content: space-between'>" + span + "<div style='align-self: flex-end;width: 20px;border-radius: 50%;background: #fff;color: #4c6cca'>" + child.length + "</div></div></div></div></div><div id=" + "'" + idStr + "'" + " style='display: flex;justify-content: center;'></div></div>";
if (cb) {
cb(html)
}
})
}
};
generate(gData, 1, function (html) {
$('#depart').append(html)
});
//4.点击触发generate方法挂载界面(点击右上角的+或-按钮)
function display(item, that, index) {
var str1 = '';
if (item.departmentname.indexOf('-') > -1) {
str1 = item.departmentname.replace(/-/g, '')
} else if (item.departmentname.indexOf('&') > -1) {
str1 = item.departmentname.replace(/&/g, '')
}else if (item.departmentname.indexOf('—') > -1) {
str1 = item.departmentname.replace(/—/g, '')
} else if (item.departmentname.indexOf('.') > -1) {
str1 = item.departmentname.replace(/./g, '')
} else if (item.departmentname.indexOf('') > -1) {
str1 = item.departmentname.replace(//g, '')
} else if (item.departmentname.indexOf('') > -1) {
str1 = item.departmentname.replace(//g, '')
} else if (item.departmentname.indexOf('') > -1 && item.departmentname.indexOf('') > -1) {
str1 = item.departmentname.replace(//g, '').replace(//g, '');
} else if (item.departmentname.indexOf('(') > -1 && item.departmentname.indexOf(')') > -1) {
str1 = item.departmentname.replace('(', '').replace(')', '');
} else if (item.departmentname.indexOf('-') > -1 && item.departmentname.indexOf('(') > -1 && item.departmentname.indexOf(')') > -1) {
str1 = item.departmentname.replace(/-/g, '').replace('(', '').replace(')', '');
} else if (item.departmentname.indexOf('-') > -1 && item.departmentname.indexOf('') > -1 && item.departmentname.indexOf('') > -1) {
str1 = item.departmentname.replace(/-/g, '').replace(//g, '').replace(//g, '');
} else {
str1 = item.departmentname;
}
var str = str1 + item.id;
var child = item.child;
var spanLeftImg = child[0].subcompanyid1 ? './leftDep.png' : './leftCom.png';
var spanRightImg = child[0].subcompanyid1 ? './rightDep.png' : './rightCom.png';
if(Number($('#depart')[0].style.left.replace('px',''))>0){
}else {
$('#depart').css({
'position': 'relative',
'left': "0px",
'transition-property': 'all',
'transition-duration': '1.5s'
});
}
if (child) {
if ($('#' + str).children('div').length > 0) {
that.html('+');
$('#' + str + '>div').remove();
if (child.length !== 1) {
$('#' + str).prev().remove();
}
} else {
var firstChild = 0;
var divLeft = 0;
var lineWidth = 0;
that.html('-');
$('#' + str).before('<div style="width: 150px"><div style="background: #4c6cca;display: block;width: 3px;height: 20px;margin: auto;"></div><div style="height: 3px;background: #4c6cca;margin-left: -26px"></div></div>');
generate(child, '', function (html) {
$('#' + str).append("<div style=''>" + html + "</div>");
$('#' + str).css('margin-bottom', '20px');
var childNum = $('#' + str).children('div').length;
var maxNum = parseInt((window.innerWidth-5)/200);
var siblings = ($('#' + str).parent().parent().siblings());
var windowWidth = window.innerWidth;
//右边越界
if ($('#' + str) && $('#' + str).children('div:first-child')[0] && ($('#' + str).children('div:last-child')[0].offsetLeft > windowWidth - 200) && child.length < maxNum) {
$('#depart').css({
position: 'relative',
'left': -($('#' + str).children('div:last-child')[0].offsetLeft + 200 - windowWidth) + 'px',
'transition-property': 'all',
'transition-duration': '1s'
});
}
for (var i = 0; i < siblings.length; i++) {
if ($(siblings[i])[0].childElementCount > 0 && $(siblings[i])[0].id!='span1'&& $(siblings[i])[0].id!='span2') {
if ($(siblings[i]).children().children('div:last-child').children().length > 0) {
if ($(siblings[i]).children().children('div:last-child').children().length > 1) {
$(siblings[i]).children().children('div:last-child').prev().remove();
}
$(siblings[i]).children().children('div:first-child').children('div:last-child').children('div:last-child').children('div:last-child').children('div:first-child').html('+');
$(siblings[i]).children().children('div:last-child').children().remove();
}
}
}
if (200 * (childNum + 1) - 197 >= window.innerWidth) {
if (isIE()) {
console.log(isIE())
$('#' + str).css({position: 'absolute', left: '-28px', right: 0});
} else {
$('#' + str).css({position: 'absolute', left: 0, right: 0});
}
$('#' + str).css({position: 'absolute', left: 0, right: 0});
$('#' + str).children("div:nth-child(" + childNum + ")").css('display', 'none');
if ($('#' + str).children("div:first-child")[0]&&$('#' + str).children("div:first-child")[0].id != 'span1') {
$('#' + str).children("div:first-child").before('<div id="span1" class="ie_positon_span1" style="margin-top: 23px;cursor: pointer" onclick="leftDir(' + str + ')"><img src=' + spanLeftImg + ' alt="" style="width:40px;height: 50px"/></div>');
}
$('#' + str).children('#span1').css('visibility', 'hidden');
if ($('#' + str).children('#span2').length == 0) {
$('#' + str).children("div:nth-child(" + Number(maxNum + 1) + ")").after('<div id="span2" class="ie_margin" style="margin-top: 23px;cursor: pointer;margin-left: -40px" onclick="rightDir(' + str + ')"><img src=' + spanRightImg + ' alt="" style="width:40px;height: 50px"/></div>');
}
divLeft = $('#' + str).children("div:nth-child(2)").children("div:first-child").children("div:first-child").children("div:first-child").children("div:first-child")[0].offsetLeft+1.5;
lineWidth = 200 * (maxNum - 1);
firstChild = $('#' + str).children('#span1')&&$('#' + str).children('#span1')[0].offsetLeft;
} else {
divLeft = $('#' + str).children("div:first-child").children("div:first-child").children("div:first-child").children("div:first-child").children("div:first-child")[0].offsetLeft;
lineWidth = 200 * (childNum - 1) + 3 ;
firstChild = $('#' + str).children("div:first-child")[0].offsetLeft;
}
//左边越界
if (firstChild+Number($('#depart')[0].offsetLeft)<=0) {
$('#depart').css({
'position': 'relative',
'left': -firstChild + 'px',
'transition-property': 'all',
'transition-duration': '1s'
});
}
$('#' + str).prev().children("div:last-child").css({
'width': lineWidth + 'px',
'margin-left': '0px',
'position': 'absolute',
'left': divLeft+ 'px',
});
if (child.length == 1) {
$('#' + str).prev().remove();
}
});
}
}
}
//5.创建用户所属的组织链条
var count = 0;
function findDep(depArr, str, id, arrNew) {
var arr = arrNew || [{child: []}];
count++;
for (var n = 0; n < depArr.length; n++) {
var item = depArr[n];
if (item.departmentname == str && item.id == id) {
for (var m = 0; m < depArr.length; m++) {
var item1 = depArr[m];
if (item1.id == item.supdepid) {
var itemStr = item1.child;
for (var i = 0; i < itemStr.length; i++) {
if (item.departmentname == itemStr[i].departmentname) {
if (count % 2 == 0) {
arr[0].name = item1.departmentname;
arr[0].no = i;
}
if (count % 2 != 0) {
arr[0].child.push({name: item1.departmentname, no: i});
}
}
}
var arrNew = arr;
if (arr[0].name != undefined && arr[0].child.length > 0) {
arrNew = [{child: arr}];
count--;
}
if (item1.supdepid == '0' && item1.subcompanyid1 == undefined) {
return arr;
} else if (item1.supdepid == '0') {
for (var i = 0; i < newComArr.length; i++) {
if (newComArr[i].id == item1.subcompanyid1) {
var itemStr1 = newComArr[i].child;
for (var j = 0; j < itemStr1.length; j++) {
if (item1.departmentname == itemStr1[j].departmentname) {
arrNew[0].name = newComArr[i].departmentname;
arrNew[0].no = j;
return findDep(newComArr, newComArr[i].departmentname, newComArr[i].id, [{child: arrNew}]);
break;
}
}
}
}
} else {
return findDep(depArr, item1.departmentname, item1.id, arrNew);
}
break;
}else if(item.supdepid == '0'){
var arrNew = arr;
if (arr[0].name != undefined && arr[0].child.length > 0) {
arrNew = [{child: arr}];
count--;
}
for (var i = 0; i < newComArr.length; i++) {
if (newComArr[i].id == item.subcompanyid1) {
var itemStr1 = newComArr[i].child;
for (var j = 0; j < itemStr1.length; j++) {
if (item.departmentname == itemStr1[j].departmentname) {
arrNew[0].name = newComArr[i].departmentname;
arrNew[0].no = j;
return findDep(newComArr, newComArr[i].departmentname, newComArr[i].id, [{child: arrNew}]);
break;
}
}
}
}
}
}
break;
}
}
}
var depChain = findDep(depArr, userDepName, userDepId);
function displayDep(obj, objN, index) {
var objM = obj[index];
var idStrSpan = objM.departmentname + objM.id + 'span';
display(objM, $('#' + idStrSpan));
if (objN && objN.length > 0) {
if (objM.departmentname == objN[0].name) {
if (objN[0].child && objN[0].child.length > 0) {
displayDep(objM.child, objN[0].child, objN[0].no);
}
}
}
}
;
displayDep(gData, depChain, 0);
//点击右边箭头
function rightDir(str) {
if ($(str).children('#span1')[0].style.visibility == 'hidden') {
$(str).children('#span1').css('visibility', 'visible');
}
$(str).children('#span1').next().css('display', 'none');
$(str).children('#span1').insertAfter($(str).children('#span1').next());
$(str).children('#span2').next().css('display', 'block');
$(str).children('#span2').insertAfter($(str).children('#span2').next());
if ($(str).children('#span2').next().length == 0) {
$(str).children('#span2').css('visibility', 'hidden');
}
removeChild(str);
}
//点击左边箭头
function leftDir(str) {
if ($(str).children('#span2')[0].style.visibility == 'hidden') {
$(str).children('#span2').css('visibility', 'visible');
}
$(str).children('#span1').prev().css('display', 'block');
$(str).children('#span1').insertBefore($(str).children('#span1').prev());
$(str).children('#span2').prev().css('display', 'none');
$(str).children('#span2').insertBefore($(str).children('#span2').prev());
if ($(str).children('#span1').prev().length == 0) {
$(str).children('#span1').css('visibility', 'hidden');
}
removeChild(str);
}
//公共方法-点击箭头之后删掉下面的所属机构
function removeChild(father) {
$('#depart').css({
position: 'relative',
'left': "0px",
'transition-property': 'all',
'transition-duration': '1.5s'
});
var siblings = $(father).children();
for (var i = 0; i < siblings.length; i++) {
if ($(siblings[i])[0].childElementCount > 0) {
if ($(siblings[i]).children().children('div:last-child').children().length > 0) {
if ($(siblings[i]).children().children('div:last-child').children().length > 1) {
$(siblings[i]).children().children('div:last-child').prev().remove();
}
$(siblings[i]).children().children('div:last-child').children().remove();
$(siblings[i]).children().children('div:first-child').children('div:last-child').children('div:last-child').children('div:last-child').children('div:first-child').html('+');
}
}
}
}
//判断是否是ie浏览器
function isIE() {
if (!!window.ActiveXObject || "ActiveXObject" in window) {
return true;
} else {
return false;
}
}
</script>
</html>

View File

@ -1,5 +1,5 @@
{ {
"name": "ball_admin", "name": "store",
"version": "0.1.0", "version": "0.1.0",
"private": true, "private": true,
"dependencies": { "dependencies": {

View File

@ -1,7 +1,7 @@
import { Form, Select } from "antd"; import { Form, Select } from "antd";
import { FormDatas } from "./interface"; import { FormDatas } from "./interface";
import { useEffect, useState } from "react"; import { useEffect, useState } from "react";
import baseHttp from "@/service/base"; import { base } from "@/service/base";
const { Option } = Select; const { Option } = Select;
export const FormSelect = (v: FormDatas) => { export const FormSelect = (v: FormDatas) => {
const [list, setList] = useState<any>([]); const [list, setList] = useState<any>([]);
@ -9,7 +9,7 @@ export const FormSelect = (v: FormDatas) => {
if (v.selectList && v.selectList.length > 0) { if (v.selectList && v.selectList.length > 0) {
setList(v.selectList); setList(v.selectList);
} else { } else {
baseHttp.get(`${v.selectUrl}/?size=50&offset=1`, "").then((res) => { base.get(`${v.selectUrl}/?size=50&offset=1`, "").then((res) => {
setList(res.data.record ?? []); setList(res.data.record ?? []);
}); });
} }

View File

@ -11,10 +11,10 @@ export const items = [
], ],
}, },
{ {
key: "/data", key: "/source",
label: `数据管理`, label: `数据管理`,
children: [ children: [
{ label: "数据管理", key: "/data/list" }, { label: "数据管理", key: "/source/list" },
], ],
}, },
{ {

View File

@ -13,10 +13,9 @@ const Login = (props) => {
userName: values.account, userName: values.account,
passWord: values.password, passWord: values.password,
}); });
await usrStore.loginVideo()
if (status) { if (status) {
usrStore.closeLoginDilog(); usrStore.closeLoginDilog();
navigate("/admin/user", { replace: true }); navigate("/user/list", { replace: true });
} }
}; };
const onFinishFailed = () => {}; const onFinishFailed = () => {};

8
src/pages/menu/menu.less Normal file
View File

@ -0,0 +1,8 @@
.contentBox{
overflow-y: auto;
height: 100%;
.tableName{
height: 100%;
overflow-y: auto;
}
}

50
src/pages/menu/menu.tsx Normal file
View File

@ -0,0 +1,50 @@
import { Button, Space, Modal, FormInstance } from "antd";
import { inject, observer } from "mobx-react";
import BTable from "@/components/b_table";
import { useEffect, useState } from "react";
import { Store } from "antd/lib/form/interface";
import React from "react";
import { columns } from "./menu_config";
import "./menu.less";
const Menu = (props: Store) => {
const { usrStore } = props;
const [isModalOpen, setIsModalOpen] = useState<boolean>(false);
const formRef = React.useRef<FormInstance>(null);
const [userId, setId] = useState<Number | null>(null);
useEffect(() => {}, []);
const addHandler = () => {};
return (
<div className="contentBox">
<Space direction="vertical" size="middle" style={{ display: "flex" }}>
<Button type="default" onClick={() => addHandler()}>
</Button>
<BTable
store={usrStore}
scroll={{ x: "max-content" }}
columns={columns}
dataSource={usrStore.list}
/>
<Modal
title={!userId ? "添加菜单" : "编辑菜单"}
width={800}
open={isModalOpen}
afterClose={() => formRef.current?.resetFields()}
onOk={() => formRef.current?.submit()}
okText="确定"
cancelText="取消"
onCancel={() => {
setId(null);
setIsModalOpen(false);
}}
></Modal>
</Space>
</div>
);
};
export default inject("usrStore")(observer(Menu));

View File

@ -0,0 +1,97 @@
import { FormType } from "@/components/form/interface";
import { UserDataType } from "@/model/userModel";
import { ColumnsType } from "antd/lib/table";
import { Image } from "antd";
import { getBirthDateAndGender } from "@/util/util";
export const defaultConfig = (team, per) => [
{
type: FormType.input,
label: "用户名",
name: "user_name",
value: "",
rules: [{ required: true, message: "请输入用户名称!" }],
},
{
type: FormType.inputNumber,
label: "年龄",
name: "age",
value: "",
rules: [{ required: true, message: "请输入年龄" }],
},
{
type: FormType.input,
label: "身份证",
name: "id_card",
value: "",
rules: [{ required: true, message: "请输入身份证" }],
},
{
type: FormType.input,
label: "登录账号",
name: "account",
value: "",
rules: [{ required: true, message: "请输入登录账号" }],
},
{
type: FormType.input,
label: "联系电话",
name: "tel",
value: "",
},
{
type: FormType.input,
label: "邮箱",
name: "email",
value: "",
},
{
type: FormType.upload,
label: "头像",
name: "head_img",
value: [],
},
];
export const columns: ColumnsType<UserDataType> = [
{
title: "用户名",
dataIndex: "user_name",
width: 200,
fixed: "left",
},
{
title: "性别",
width: 150,
render: (render) => (
<span>{getBirthDateAndGender(render.id_card)?.gender}</span>
),
},
{
title: "头像",
dataIndex: "head_img",
width: 150,
render: (head_img) => {
return <Image src={head_img}></Image>;
},
},
{
title: "登录账号",
width: 150,
dataIndex: "account",
},
{
title: "身份证",
width: 150,
dataIndex: "id_card",
},
{
title: "联系电话",
width: 150,
dataIndex: "tel",
},
];

View File

@ -0,0 +1,8 @@
.contentBox{
overflow-y: auto;
height: 100%;
.tableName{
height: 100%;
overflow-y: auto;
}
}

View File

@ -0,0 +1,50 @@
import { Button, Space, Modal, FormInstance } from "antd";
import { inject, observer } from "mobx-react";
import BTable from "@/components/b_table";
import { useEffect, useState } from "react";
import { Store } from "antd/lib/form/interface";
import React from "react";
import { columns } from "./permission_config";
import "./permission.less";
const Permission = (props: Store) => {
const { usrStore } = props;
const [isModalOpen, setIsModalOpen] = useState<boolean>(false);
const formRef = React.useRef<FormInstance>(null);
const [userId, setId] = useState<Number | null>(null);
useEffect(() => {}, []);
const addHandler = () => {};
return (
<div className="contentBox">
<Space direction="vertical" size="middle" style={{ display: "flex" }}>
<Button type="default" onClick={() => addHandler()}>
</Button>
<BTable
store={usrStore}
scroll={{ x: "max-content" }}
columns={columns}
dataSource={usrStore.list}
/>
<Modal
title={!userId ? "添加权限" : "编辑权限"}
width={800}
open={isModalOpen}
afterClose={() => formRef.current?.resetFields()}
onOk={() => formRef.current?.submit()}
okText="确定"
cancelText="取消"
onCancel={() => {
setId(null);
setIsModalOpen(false);
}}
></Modal>
</Space>
</div>
);
};
export default inject("usrStore")(observer(Permission));

View File

@ -0,0 +1,97 @@
import { FormType } from "@/components/form/interface";
import { UserDataType } from "@/model/userModel";
import { ColumnsType } from "antd/lib/table";
import { Image } from "antd";
import { getBirthDateAndGender } from "@/util/util";
export const defaultConfig = (team, per) => [
{
type: FormType.input,
label: "用户名",
name: "user_name",
value: "",
rules: [{ required: true, message: "请输入用户名称!" }],
},
{
type: FormType.inputNumber,
label: "年龄",
name: "age",
value: "",
rules: [{ required: true, message: "请输入年龄" }],
},
{
type: FormType.input,
label: "身份证",
name: "id_card",
value: "",
rules: [{ required: true, message: "请输入身份证" }],
},
{
type: FormType.input,
label: "登录账号",
name: "account",
value: "",
rules: [{ required: true, message: "请输入登录账号" }],
},
{
type: FormType.input,
label: "联系电话",
name: "tel",
value: "",
},
{
type: FormType.input,
label: "邮箱",
name: "email",
value: "",
},
{
type: FormType.upload,
label: "头像",
name: "head_img",
value: [],
},
];
export const columns: ColumnsType<UserDataType> = [
{
title: "用户名",
dataIndex: "user_name",
width: 200,
fixed: "left",
},
{
title: "性别",
width: 150,
render: (render) => (
<span>{getBirthDateAndGender(render.id_card)?.gender}</span>
),
},
{
title: "头像",
dataIndex: "head_img",
width: 150,
render: (head_img) => {
return <Image src={head_img}></Image>;
},
},
{
title: "登录账号",
width: 150,
dataIndex: "account",
},
{
title: "身份证",
width: 150,
dataIndex: "id_card",
},
{
title: "联系电话",
width: 150,
dataIndex: "tel",
},
];

8
src/pages/role/role.less Normal file
View File

@ -0,0 +1,8 @@
.contentBox{
overflow-y: auto;
height: 100%;
.tableName{
height: 100%;
overflow-y: auto;
}
}

50
src/pages/role/role.tsx Normal file
View File

@ -0,0 +1,50 @@
import { Button, Space, Modal, FormInstance } from "antd";
import { inject, observer } from "mobx-react";
import BTable from "@/components/b_table";
import { useEffect, useState } from "react";
import { Store } from "antd/lib/form/interface";
import React from "react";
import { columns } from "./role_config";
import "./role.less";
const Role = (props: Store) => {
const { usrStore } = props;
const [isModalOpen, setIsModalOpen] = useState<boolean>(false);
const formRef = React.useRef<FormInstance>(null);
const [userId, setId] = useState<Number | null>(null);
useEffect(() => {}, []);
const addHandler = () => {};
return (
<div className="contentBox">
<Space direction="vertical" size="middle" style={{ display: "flex" }}>
<Button type="default" onClick={() => addHandler()}>
</Button>
<BTable
store={usrStore}
scroll={{ x: "max-content" }}
columns={columns}
dataSource={usrStore.list}
/>
<Modal
title={!userId ? "添加角色" : "编辑角色"}
width={800}
open={isModalOpen}
afterClose={() => formRef.current?.resetFields()}
onOk={() => formRef.current?.submit()}
okText="确定"
cancelText="取消"
onCancel={() => {
setId(null);
setIsModalOpen(false);
}}
></Modal>
</Space>
</div>
);
};
export default inject("usrStore")(observer(Role));

View File

@ -0,0 +1,97 @@
import { FormType } from "@/components/form/interface";
import { UserDataType } from "@/model/userModel";
import { ColumnsType } from "antd/lib/table";
import { Image } from "antd";
import { getBirthDateAndGender } from "@/util/util";
export const defaultConfig = (team, per) => [
{
type: FormType.input,
label: "用户名",
name: "user_name",
value: "",
rules: [{ required: true, message: "请输入用户名称!" }],
},
{
type: FormType.inputNumber,
label: "年龄",
name: "age",
value: "",
rules: [{ required: true, message: "请输入年龄" }],
},
{
type: FormType.input,
label: "身份证",
name: "id_card",
value: "",
rules: [{ required: true, message: "请输入身份证" }],
},
{
type: FormType.input,
label: "登录账号",
name: "account",
value: "",
rules: [{ required: true, message: "请输入登录账号" }],
},
{
type: FormType.input,
label: "联系电话",
name: "tel",
value: "",
},
{
type: FormType.input,
label: "邮箱",
name: "email",
value: "",
},
{
type: FormType.upload,
label: "头像",
name: "head_img",
value: [],
},
];
export const columns: ColumnsType<UserDataType> = [
{
title: "用户名",
dataIndex: "user_name",
width: 200,
fixed: "left",
},
{
title: "性别",
width: 150,
render: (render) => (
<span>{getBirthDateAndGender(render.id_card)?.gender}</span>
),
},
{
title: "头像",
dataIndex: "head_img",
width: 150,
render: (head_img) => {
return <Image src={head_img}></Image>;
},
},
{
title: "登录账号",
width: 150,
dataIndex: "account",
},
{
title: "身份证",
width: 150,
dataIndex: "id_card",
},
{
title: "联系电话",
width: 150,
dataIndex: "tel",
},
];

View File

@ -0,0 +1,8 @@
.contentBox{
overflow-y: auto;
height: 100%;
.tableName{
height: 100%;
overflow-y: auto;
}
}

View File

@ -0,0 +1,50 @@
import { Button, Space, Modal, FormInstance } from "antd";
import { inject, observer } from "mobx-react";
import BTable from "@/components/b_table";
import { useEffect, useState } from "react";
import { Store } from "antd/lib/form/interface";
import React from "react";
import { columns } from "./source_config";
import "./source.less";
const Source = (props: Store) => {
const { usrStore } = props;
const [isModalOpen, setIsModalOpen] = useState<boolean>(false);
const formRef = React.useRef<FormInstance>(null);
const [userId, setId] = useState<Number | null>(null);
useEffect(() => {}, []);
const addHandler = () => {};
return (
<div className="contentBox">
<Space direction="vertical" size="middle" style={{ display: "flex" }}>
<Button type="default" onClick={() => addHandler()}>
</Button>
<BTable
store={usrStore}
scroll={{ x: "max-content" }}
columns={columns}
dataSource={usrStore.list}
/>
<Modal
title={!userId ? "添加用户" : "编辑用户"}
width={800}
open={isModalOpen}
afterClose={() => formRef.current?.resetFields()}
onOk={() => formRef.current?.submit()}
okText="确定"
cancelText="取消"
onCancel={() => {
setId(null);
setIsModalOpen(false);
}}
></Modal>
</Space>
</div>
);
};
export default inject("usrStore")(observer(Source));

View File

@ -0,0 +1,97 @@
import { FormType } from "@/components/form/interface";
import { UserDataType } from "@/model/userModel";
import { ColumnsType } from "antd/lib/table";
import { Image } from "antd";
import { getBirthDateAndGender } from "@/util/util";
export const defaultConfig = (team, per) => [
{
type: FormType.input,
label: "用户名",
name: "user_name",
value: "",
rules: [{ required: true, message: "请输入用户名称!" }],
},
{
type: FormType.inputNumber,
label: "年龄",
name: "age",
value: "",
rules: [{ required: true, message: "请输入年龄" }],
},
{
type: FormType.input,
label: "身份证",
name: "id_card",
value: "",
rules: [{ required: true, message: "请输入身份证" }],
},
{
type: FormType.input,
label: "登录账号",
name: "account",
value: "",
rules: [{ required: true, message: "请输入登录账号" }],
},
{
type: FormType.input,
label: "联系电话",
name: "tel",
value: "",
},
{
type: FormType.input,
label: "邮箱",
name: "email",
value: "",
},
{
type: FormType.upload,
label: "头像",
name: "head_img",
value: [],
},
];
export const columns: ColumnsType<UserDataType> = [
{
title: "用户名",
dataIndex: "user_name",
width: 200,
fixed: "left",
},
{
title: "性别",
width: 150,
render: (render) => (
<span>{getBirthDateAndGender(render.id_card)?.gender}</span>
),
},
{
title: "头像",
dataIndex: "head_img",
width: 150,
render: (head_img) => {
return <Image src={head_img}></Image>;
},
},
{
title: "登录账号",
width: 150,
dataIndex: "account",
},
{
title: "身份证",
width: 150,
dataIndex: "id_card",
},
{
title: "联系电话",
width: 150,
dataIndex: "tel",
},
];

View File

@ -1,67 +0,0 @@
import MapContainer from "@/components/map/MapComponent";
import MapUtl from "@/components/map/mapUtil";
import { Button, message, Modal } from "antd";
import { inject, observer } from "mobx-react";
import { useState } from "react";
const Move = (props) => {
const { usrStore, id } = props;
const [isOpen, setOpen] = useState<boolean>(false);
return (
<>
<Button
type="dashed"
size="small"
onClick={() => {
setOpen(true);
}}
>
</Button>
<Modal
title={"轨迹回放"}
width={"80%"}
open={isOpen}
centered
okText="确定"
cancelText="取消"
footer={null}
destroyOnClose={true}
onCancel={() => {
setOpen(false);
}}
>
<div>
<Button
type="dashed"
size="small"
onClick={() => {
usrStore.getSite(id).then((res) => {
let data: any = [];
if (res.data && res.data.record) {
res.data.record.forEach((element) => {
data.push([element.long, element.lat]);
});
if (data.length === 0) {
message.info("暂无轨迹数据");
return;
}
if (data.length > 0) {
MapUtl.polyline(data);
}
}
});
}}
>
</Button>
<div style={{ height: "10px" }}></div>
<MapContainer />
</div>
</Modal>
</>
);
};
// getSite
export default inject("usrStore")(observer(Move));

View File

@ -12,8 +12,11 @@ const User = (props: Store) => {
const [isModalOpen, setIsModalOpen] = useState<boolean>(false); const [isModalOpen, setIsModalOpen] = useState<boolean>(false);
const formRef = React.useRef<FormInstance>(null); const formRef = React.useRef<FormInstance>(null);
const [userId, setId] = useState<Number | null>(null); const [userId, setId] = useState<Number | null>(null);
useEffect(() => {}, [usrStore]); // 获取列表数据
useEffect(() => {
usrStore.getlist();
}, [usrStore]);
const addHandler = () => {}; const addHandler = () => {};
return ( return (

View File

@ -3,6 +3,9 @@ import LayOut from "@/components/layout/layout";
import Login from "@/pages/login/login"; import Login from "@/pages/login/login";
import User from "@/pages/user/user"; import User from "@/pages/user/user";
import Dashbord from "@/pages/dashbord"; import Dashbord from "@/pages/dashbord";
import Source from "@/pages/source/source";
import Menu from "@/pages/menu/menu";
import Role from "@/pages/role/role";
const routers = createHashRouter([ const routers = createHashRouter([
{ {
@ -19,6 +22,21 @@ const routers = createHashRouter([
index: true, index: true,
element: <User />, element: <User />,
}, },
{
path: "/source/list",
index: true,
element: <Source />,
},
{
path: "/permission/menu",
index: true,
element: <Menu />,
},
{
path: "/permission/role",
index: true,
element: <Role />,
},
], ],
}, },
{ {

View File

@ -1,6 +1,7 @@
import store from "@/store"; import store from "@/store";
import Config from "@/util/config"; import Config from "@/util/config";
import axios, { AxiosResponse } from "axios"; import axios, { AxiosResponse } from "axios";
// import { baseHttp } from '@/service/base';
// 添加请求拦截器 // 添加请求拦截器
axios.defaults.headers.common["Content-Type"] = "application/json; charset=utf8"; axios.defaults.headers.common["Content-Type"] = "application/json; charset=utf8";
axios.defaults.headers.common["X-Requested-With"] = "XMLHttpRequest"; axios.defaults.headers.common["X-Requested-With"] = "XMLHttpRequest";
@ -31,7 +32,7 @@ axios.interceptors.response.use((res: AxiosResponse) => {
} }
return Promise.reject(err); return Promise.reject(err);
}); });
class BaseHttp { class BaseHttps {
async gets(url: string, params: any) { async gets(url: string, params: any) {
let res = await axios({ let res = await axios({
method: 'get', method: 'get',
@ -48,7 +49,6 @@ class BaseHttp {
let res = await axios({ let res = await axios({
method: 'get', method: 'get',
url: url, url: url,
params params
}); });
return res.data; return res.data;
@ -96,5 +96,5 @@ class BaseHttp {
}; };
} }
// eslint-disable-next-line import/no-anonymous-default-export const base = new BaseHttps();
export default new BaseHttp() export { base };

25
src/service/user.ts Normal file
View File

@ -0,0 +1,25 @@
import { base } from '@/service/base';
class UserService {
static configAdd: string = "/user";
static configEdit: string = "/user";
static configList: string = "/user/list";
static configDelete: string = "/user";
static async add(params) {
return await base.post(UserService.configAdd, params);
}
static async edit(identity: string, params: any) {
return await base.put(UserService.configEdit + "/" + identity, params);
}
static async remove(identity) {
return await base.delete(UserService.configEdit + "/" + identity, {});
}
static async list(params) {
return await base.get(UserService.configList, params);
}
}
export default UserService ;

View File

@ -1,4 +1,5 @@
import baseHttp from "@/service/base"; import { base } from "@/service/base";
import userService from "@/service/user";
import { Pages } from "@/util/model/interface"; import { Pages } from "@/util/model/interface";
import { message } from "antd"; import { message } from "antd";
import { action, makeObservable, observable, runInAction } from "mobx"; import { action, makeObservable, observable, runInAction } from "mobx";
@ -36,7 +37,7 @@ class BaseStore<B> implements BaseStoreInterface<B> {
// 删除 // 删除
async deleteItem(id: number) { async deleteItem(id: number) {
try { try {
await baseHttp.delete(this.urlConfig.DELETE + "/" + id, {}) await base.delete(this.urlConfig.DELETE + "/" + id, {})
this.getlist() this.getlist()
} catch (error) { } catch (error) {
console.log(error); console.log(error);
@ -50,7 +51,7 @@ class BaseStore<B> implements BaseStoreInterface<B> {
// 添加 // 添加
async add(param: any, listParam?: any) { async add(param: any, listParam?: any) {
try { try {
let res = await baseHttp.post(this.urlConfig.ADD, param) let res = await userService.add(param);
if (res.code !== 200) { if (res.code !== 200) {
message.error(res.msg) message.error(res.msg)
return false return false
@ -65,7 +66,7 @@ class BaseStore<B> implements BaseStoreInterface<B> {
// 更新 // 更新
async putItem(id: string, param: any, listParam?: any) { async putItem(id: string, param: any, listParam?: any) {
try { try {
let res = await baseHttp.put(this.urlConfig.EDIT + "/" + id, param) let res = await userService.edit(id, param)
if (res.code !== 200) { if (res.code !== 200) {
message.error(res.msg) message.error(res.msg)
return false return false
@ -81,23 +82,23 @@ class BaseStore<B> implements BaseStoreInterface<B> {
async getlist(params?: any) { async getlist(params?: any) {
this.listStatus = true; this.listStatus = true;
try { try {
let res = await baseHttp.get(this.urlConfig.LIST, { let res = await userService.list({
size: this.page?.Size ?? 20, size: this.page?.Size ?? 20,
offset: this.page?.Offset ?? 1, offset: this.page?.Offset ?? 1,
...params ...params
}); });
this.listStatus = false;
let data: Array<B> = [] let data: Array<B> = []
if (!res?.data?.record) { if (!res?.data) {
runInAction(() => { runInAction(() => {
this.list = data; this.list = data;
}) })
this.listStatus = false;
return; return;
} }
for (let i = 0; i < res.data.record.length; i++) { for (let i = 0; i < res.data.length; i++) {
data.push({ data.push({
key: res.data.record[i].id, key: res.data[i].id,
...res.data.record[i] ...res.data[i]
}) })
} }
runInAction(() => { runInAction(() => {

View File

@ -1,22 +1,11 @@
import { action, computed, makeObservable, observable } from "mobx"; import { action, computed, makeObservable, observable } from "mobx";
// 用户信息 // 用户信息
import baseHttp from "@/service/base"; import { base } from "@/service/base";
import BaseStore from "./baseStore"; import BaseStore from "./baseStore";
import { UserDataType, UserInfos } from "@/model/userModel"; import { UserDataType, UserInfos } from "@/model/userModel";
import { message } from "antd"; import { message } from "antd";
class UserConfig { class UserConfig {
static LOGINURI: string = "/v1/anth/login/pc" static LOGINURI: string = "/anth/login/pc"
static LIST: string = "/v1/user/list"
static ADD: string = "/v1/user"
static DELETE: string = "/v1/user"
static EDIT: string = "/v1/user"
static pover: string = "/v1/user/userPower"
static team: string = "/v1/team/list"
static per: string = "/v1/persMgmt/list"
static serch: string = "/v1/user/serch"
static getPatrol: string = "/v1/user/getPatrol"
static videoLogin: string = "api/v1/login"
static siteList: string = "/v1/user/site"
} }
class UserStore extends BaseStore<UserDataType> { class UserStore extends BaseStore<UserDataType> {
@ -30,13 +19,6 @@ class UserStore extends BaseStore<UserDataType> {
makeObservable(this, { makeObservable(this, {
logOut: action, logOut: action,
login: action, login: action,
getTeam: action,
getPer: action,
serchUser: action,
setPoverDe: action,
setUserDetaul: action,
getPatrol: action,
getSite: action,
_userinfo: observable, _userinfo: observable,
isNeedLogin: observable, isNeedLogin: observable,
poverDetail: observable, poverDetail: observable,
@ -45,27 +27,6 @@ class UserStore extends BaseStore<UserDataType> {
userInfo: computed, userInfo: computed,
}) })
} }
async getTeam() {
return await baseHttp.get(UserConfig.team, null)
}
async getPer() {
return await baseHttp.get(UserConfig.per, null)
}
async getPover() {
return await baseHttp.get(UserConfig.pover, null)
}
async serchUser(params: any) {
return await baseHttp.get(UserConfig.serch, { user_name: params })
}
async getPatrol() {
return await baseHttp.get(UserConfig.getPatrol, {})
}
async getSite(id) {
return await baseHttp.get(UserConfig.siteList + "/" + id, {})
}
get userInfo(): UserInfos { get userInfo(): UserInfos {
if (!this._userinfo.token) { if (!this._userinfo.token) {
@ -88,12 +49,11 @@ class UserStore extends BaseStore<UserDataType> {
genre: 1 genre: 1
} }
try { try {
let data = await baseHttp.post(UserConfig.LOGINURI, param) let data = await base.post(UserConfig.LOGINURI, param)
if (data.code !== 200) { if (data.code !== 0) {
message.error(data.msg) message.error(data.msg)
return false return false
} }
window.localStorage.setItem("token", data.data.token ?? ""); window.localStorage.setItem("token", data.data.token ?? "");
return true return true
} catch (error) { } catch (error) {
@ -102,19 +62,6 @@ class UserStore extends BaseStore<UserDataType> {
} }
} }
async loginVideo() {
try {
let data = await baseHttp.get(UserConfig.videoLogin, {
username: "easycvr",
password: "4092c09db0af030641a977d76044de4f",
})
window.localStorage.setItem("video-token", data.EasyDarwin.Body.Token ?? "");
return true
} catch (error) {
console.log(error)
return false
}
}
openLoginDilog() { openLoginDilog() {
this.isNeedLogin = true; this.isNeedLogin = true;
} }

View File

@ -1,4 +1,4 @@
class Config { class Config {
static baseUrl = "http://127.0.0.1:12016"; static baseUrl = "http://127.0.0.1:12214/v1";
} }
export default Config; export default Config;