Commit cd3ab983 by chengming

修改bug

parent 57206161
......@@ -21,4 +21,5 @@ chrome-user-data
dll
dist
src\util\request.js
package-lock.json
\ No newline at end of file
package-lock.json
build/config.js
\ No newline at end of file
// 1.计算加载时间
function getPerformanceTiming() {
var performance = window.performance;
if (!performance) {
// 当前浏览器不支持
console.log('你的浏览器不支持 performance 接口');
return;
}
var t = performance.timing;
var times = {};
//【重要】页面加载完成的时间
//【原因】这几乎代表了用户等待页面可用的时间
times.loadPage = t.loadEventEnd - t.navigationStart;
//【重要】解析 DOM 树结构的时间
//【原因】反省下你的 DOM 树嵌套是不是太多了!
times.domReady = t.domComplete - t.responseEnd;
//【重要】重定向的时间
//【原因】拒绝重定向!比如,http://example.com/ 就不该写成 http://example.com
times.redirect = t.redirectEnd - t.redirectStart;
//【重要】DNS 查询时间
//【原因】DNS 预加载做了么?页面内是不是使用了太多不同的域名导致域名查询的时间太长?
// 可使用 HTML5 Prefetch 预查询 DNS ,见:[HTML5 prefetch](http://segmentfault.com/a/1190000000633364)
times.lookupDomain = t.domainLookupEnd - t.domainLookupStart;
//【重要】读取页面第一个字节的时间
//【原因】这可以理解为用户拿到你的资源占用的时间,加异地机房了么,加CDN 处理了么?加带宽了么?加 CPU 运算速度了么?
// TTFB 即 Time To First Byte 的意思
// 维基百科:https://en.wikipedia.org/wiki/Time_To_First_Byte
times.ttfb = t.responseStart - t.navigationStart;
//【重要】内容加载完成的时间
//【原因】页面内容经过 gzip 压缩了么,静态资源 css/js 等压缩了么?
times.request = t.responseEnd - t.requestStart;
//【重要】执行 onload 回调函数的时间
//【原因】是否太多不必要的操作都放到 onload 回调函数里执行了,考虑过延迟加载、按需加载的策略么?
times.loadEvent = t.loadEventEnd - t.loadEventStart;
// DNS 缓存时间
times.appcache = t.domainLookupStart - t.fetchStart;
// 卸载页面的时间
times.unloadEvent = t.unloadEventEnd - t.unloadEventStart;
// TCP 建立连接完成握手的时间
times.connect = t.connectEnd - t.connectStart;
return times;
}
// 2.计算加载时间
function getEntryTiming(entry) {
function getEntryTiming(entry) {
var t = entry;
var times = {};
// 重定向的时间
times.redirect = t.redirectEnd - t.redirectStart;
// DNS 查询时间
times.lookupDomain = t.domainLookupEnd - t.domainLookupStart;
// 内容加载完成的时间
times.request = t.responseEnd - t.requestStart;
// TCP 建立连接完成握手的时间
times.connect = t.connectEnd - t.connectStart;
// 挂载 entry 返回
times.name = entry.name;
times.entryType = entry.entryType;
times.initiatorType = entry.initiatorType;
times.duration = entry.duration;
return times;
}
// 例如:
function entriesTimes() {
function entriesTimes() {
var entries = window.performance.getEntries();//这个函数返回的将是一个数组,包含了页面中所有的 HTTP 请求
entries.forEach(function (entry) {
var times = getEntryTiming(entry);
......@@ -99,93 +98,118 @@ function getPerformanceTiming() {
}
entriesTimes()
$(function() {
let comGetLocation={
//hash parm
getUrlParam() {
$(function () {
let comGetLocation = {
//hash parm
getUrlParam() {
var search = location.search;
if (location.search.indexOf("?") == -1) {
return '';
}
var queryString = search.split("?")[1];
if (queryString.indexOf("&") != -1) {
var data={};
if (queryString.indexOf("&") != -1) {
var data = {};
var arr = queryString.split("&"); // split
arr.map((item)=>{
data[item.split("=")[0]]=item.substring(item.indexOf("=")+1)
})
return data;
arr.map((item) => {
data[item.split("=")[0]] = item.substring(item.indexOf("=") + 1)
})
return data;
}else {
} else {
return '';
}
}
};
function getAuthorization(parms,href_url) {
if(!parms.md5nm){
function getAuthorization(parms, href_url) {
if (!parms.md5nm) {
alert("login_name没有找到")
return;
}
console.log(href_url,"url")
let {appId,mp,companyCode,siteCode,md5nm,token,salt,sign}= parms;
console.log(appId,'appid');
console.log(mp,'mp');
console.log(appId,'appid');
console.log(companyCode,'companyCode');
console.log(siteCode,'siteCode');
console.log(md5nm,'md5nm');
console.log(token,'token');
console.log(salt,'salt');
console.log(sign,'sign');
console.log(href_url, "url")
let { appId, mp, companyCode, siteCode, md5nm, token, salt, sign } = parms;
console.log(appId, 'appid');
console.log(mp, 'mp');
console.log(appId, 'appid');
console.log(companyCode, 'companyCode');
console.log(siteCode, 'siteCode');
console.log(md5nm, 'md5nm');
console.log(token, 'token');
console.log(salt, 'salt');
console.log(sign, 'sign');
// md5nm -->name ,mp -> terminalType,hrefUrl
var data={appId,name:md5nm,token,salt,sign,hrefUrl:href_url,type:parms.authType?parms.authType:1};
if(parms.mp==1||parms.mp==0){
data.terminalType=3;
}else{
data.terminalType=parms.mp;
var data = { appId, name: md5nm, token, salt, sign, hrefUrl: href_url, type: parms.authType ? parms.authType : 1 };
if (parms.mp == 1 || parms.mp == 0) {
data.terminalType = 3;
} else {
data.terminalType = parms.mp;
}
var origin= location.origin;
var origin = location.origin;
$.ajax({
type: "post",
url: origin+"/system/public/api/plus/getAccount?companyCode=" + companyCode + "&siteCode=" + siteCode,
url: origin + "/system/public/api/plus/getAccount?companyCode=" + companyCode + "&siteCode=" + siteCode,
async: true,
dataType: "json",
contentType: 'application/json;charset=UTF-8',
data:JSON.stringify(data),
data: JSON.stringify(data),
success: function (res) {
if (res.code == 1000) {
sessionStorage.setItem("mgtk",res.data.Authorization)
if (res.code == 1000) {
sessionStorage.setItem("mgtk", res.data.Authorization)
sessionStorage.setItem("userName", res.data.userInfo.name);
sessionStorage.setItem("dev", res.data.userInfo.dev);
href_url=decodeURIComponent(href_url);
// 新增:设置用户权限到localStorage
if (res.data.authRole && Array.isArray(res.data.authRole)) {
const permissionsArray = res.data.authRole.map(role => role.code);
localStorage.setItem("userPermissions", JSON.stringify(permissionsArray));
// 触发权限更新事件 - 使用更可靠的方式
setTimeout(() => {
const event = new CustomEvent("permissionsUpdate", {
detail: { permissions: permissionsArray }
});
window.dispatchEvent(event);
console.log('RJump: 权限更新事件已触发:', permissionsArray);
}, 100);
} else {
localStorage.setItem("userPermissions", "[]");
setTimeout(() => {
const event = new CustomEvent("permissionsUpdate", {
detail: { permissions: [] }
});
window.dispatchEvent(event);
console.log('RJump: 权限更新事件已触发: []');
}, 100);
}
href_url = decodeURIComponent(href_url);
location.replace(href_url);
}else {
$("#body").html("<span style='color: red'>错误信息:</span>"+JSON.stringify(res))
}
} else {
$("#body").html("<span style='color: red'>错误信息:</span>" + JSON.stringify(res))
}
},
error:function (err) {
error: function (err) {
$("#body").html(`<span style='color: red'>错误信息:${JSON.stringify(err)}</span>`)
}
});
};
let datas= comGetLocation.getUrlParam();
console.log('集合',datas);
let datas = comGetLocation.getUrlParam();
console.log('集合', datas);
var parms = datas;
let {appId,mp,companyCode,siteCode,md5nm,token,salt,sign}= parms;
if(appId&&companyCode&&siteCode&&md5nm&&token&&salt&&sign){
let { appId, mp, companyCode, siteCode, md5nm, token, salt, sign } = parms;
if (appId && companyCode && siteCode && md5nm && token && salt && sign) {
}else{
} else {
alert("参数不全,不发请求跳转");
return;
}
getAuthorization(parms,datas.href_url);
getAuthorization(parms, datas.href_url);
});
\ No newline at end of file
var os = require('os'), IP = "http://10.10.12.94:8090", ifaces = os.networkInterfaces() // 获取本机IP
var os = require('os');
// 修改为指向项目根目录的config.js
const config = require('./config');
let IP = config.IP;
const ifaces = os.networkInterfaces();
out:
for (var i in ifaces) {
for (var j in ifaces[i]) {
......@@ -9,22 +15,5 @@ for (var i in ifaces) {
}
}
};
const host = {
prod: {
BASE_URL: "https://mg.kmelearning.com",
},
deve: {
BASE_URL: "https://mg.fairyclass.cn",
},
sit: {
BASE_URL: "https://mg.fairyclass.cn/",
},
uat: {
BASE_URL: "https://uat.mg.kmelearning.com",
},
other: {
BASE_URL: "",
},
};
module.exports = {IP,host};
\ No newline at end of file
module.exports = {IP, host: config.host};
\ No newline at end of file
......@@ -12,21 +12,66 @@
* <App />
* </AuthProvider>
*/
import React, { createContext, useState, useEffect } from "react";
import React, { createContext, useState, useEffect, useCallback } from "react";
export const AuthContext = createContext();
export const AuthProvider = ({ children }) => {
const [userPermissions, setUserPermissions] = useState([]);
// 使用useCallback优化更新函数,避免不必要的重新渲染
const updatePermissions = useCallback((newPermissions) => {
const permissionsArray = Array.isArray(newPermissions) ? newPermissions : [];
console.log('AuthContext: 更新权限:', permissionsArray);
// 更新状态
setUserPermissions(permissionsArray);
// 更新localStorage
localStorage.setItem("userPermissions", JSON.stringify(permissionsArray));
// 触发自定义事件,确保当前窗口能收到权限更新
window.dispatchEvent(new CustomEvent("permissionsUpdate", {
detail: { permissions: permissionsArray }
}));
}, []);
useEffect(() => {
// 初始化权限
const perms = JSON.parse(localStorage.getItem("userPermissions") || "[]");
console.log('AuthContext: 初始化权限:', perms);
setUserPermissions(perms);
}, []);
// 监听 localStorage 变化(其他标签页修改时触发)
const handleStorageChange = (e) => {
if (e.key === "userPermissions") {
console.log('AuthContext: storage事件触发,权限更新:', e.newValue);
const newPerms = JSON.parse(e.newValue || "[]");
setUserPermissions(newPerms);
}
};
// 监听自定义权限更新事件(当前标签页修改时触发)
const handlePermissionsUpdate = (e) => {
if (e.detail && Array.isArray(e.detail.permissions)) {
console.log('AuthContext: 自定义权限更新事件触发:', e.detail.permissions);
setUserPermissions(e.detail.permissions);
}
};
// 添加事件监听器
window.addEventListener("storage", handleStorageChange);
window.addEventListener("permissionsUpdate", handlePermissionsUpdate);
return () => {
window.removeEventListener("storage", handleStorageChange);
window.removeEventListener("permissionsUpdate", handlePermissionsUpdate);
};
}, []); // 空依赖数组,只在组件挂载时执行一次
return (
<AuthContext.Provider value={{ userPermissions }}>
<AuthContext.Provider value={{ userPermissions, updatePermissions }}>
{children}
</AuthContext.Provider>
);
};
};
\ No newline at end of file
import React, { useContext, useEffect, useState } from "react";
import { AuthContext } from "./AuthContext";
/**
* @file @/common/permissions/Permission.jsx
* @description 控制组件渲染权限
* 权限控制组件
* @param {Object} props - 组件属性
* @param {React.ReactNode} props.children - 需要权限控制的子组件
* @param {string|string[]} props.permission - 所需权限字符串或数组
* @param {'or' | 'and'} [props.mode='or'] - 权限匹配模式,'or' 表示满足任一权限即可,'and' 表示需满足所有权限
* @param {React.ReactNode} [props.fallback=null] - 无权限时显示的替代组件,默认为 null(不显示)
* @returns {React.ReactNode} - 根据权限渲染子组件或替代组件
* @author Lichen
* @date 2025/09/28
* @example
* import Permission from '@/common/permissions/Permission';
* <Permission permission="edu_site_admin">
* <button>用户管理</button>
* </Permission>
*
* <Permission permission={['edu_site_admin']} mode="and" fallback={<span>无权限</span>}>
* <button>删除用户</button>
* </Permission> // mode="and" 表示权限全部满足时才显示组件,否则显示 fallback
*
* <Permission permission={['edu_site_admin']} mode="or">
* <button>修改用户</button>
* </Permission> // mode="or" 表示权限满足其一时显示组件,否则显示 fallback
* @param {string|string[]} props.permission - 需要的权限
* @param {string} props.mode - 权限检查模式:'and' | 'or',默认 'and'
* @param {React.ReactNode} props.children - 子组件
* @param {React.ReactNode} props.fallback - 无权限时显示的组件
* @returns {React.ReactNode} - 根据权限条件渲染的组件
*/
import usePermission from "./usePermission";
const Permission = ({ permission, mode = "and", children, fallback = null }) => {
const { userPermissions } = useContext(AuthContext);
const [forceUpdate, setForceUpdate] = useState(0);
// 监听权限更新事件,强制重新渲染
useEffect(() => {
const handlePermissionsUpdate = () => {
console.log('Permission组件: 收到权限更新事件,强制重新渲染');
setForceUpdate(prev => prev + 1);
};
window.addEventListener("permissionsUpdate", handlePermissionsUpdate);
return () => {
window.removeEventListener("permissionsUpdate", handlePermissionsUpdate);
};
}, []);
// 权限检查函数
const checkPermission = () => {
if (!userPermissions || !Array.isArray(userPermissions)) return false;
if (typeof permission === "string") {
return userPermissions.includes(permission);
}
if (Array.isArray(permission)) {
if (mode === "and") {
return permission.every(p => userPermissions.includes(p));
} else {
return permission.some(p => userPermissions.includes(p));
}
}
return false;
};
const Permission = ({ children, permission, mode = "or", fallback = null }) => {
const hasPermission = usePermission();
return hasPermission(permission, mode) ? children : fallback;
// 使用forceUpdate确保权限更新后重新渲染
return checkPermission() ? children : fallback;
};
export default Permission;
export default Permission;
\ No newline at end of file
/**
* @file @/common/permissions/permissionUtils.js
* @description 权限工具函数
* @author Lichen
* @date 2025/09/28
*/
/**
* 更新用户权限并触发更新事件
* @param {string[]} permissions - 新的权限数组
*/
export const updateUserPermissions = (permissions) => {
const permissionsArray = Array.isArray(permissions) ? permissions : [];
console.log('权限工具函数:更新权限为:', permissionsArray);
// 更新localStorage
localStorage.setItem("userPermissions", JSON.stringify(permissionsArray));
// 触发自定义事件,通知所有权限组件更新
const event = new CustomEvent("permissionsUpdate", {
detail: { permissions: permissionsArray }
});
window.dispatchEvent(event);
// 为了确保兼容性,也触发storage事件(主要给其他标签页使用)
try {
window.dispatchEvent(new StorageEvent("storage", {
key: "userPermissions",
newValue: JSON.stringify(permissionsArray),
oldValue: localStorage.getItem("userPermissions"),
url: window.location.href
}));
} catch (e) {
// 在某些浏览器中,手动创建StorageEvent可能不支持,忽略错误
console.log('StorageEvent创建失败,使用自定义事件:', e);
}
};
/**
* 触发权限更新事件
* @param {string[]} permissions - 新的权限数组
*/
export const triggerPermissionsUpdate = (permissions) => {
updateUserPermissions(permissions);
};
/**
* 获取当前用户权限
* @returns {string[]} 权限数组
*/
export const getCurrentPermissions = () => {
return JSON.parse(localStorage.getItem("userPermissions") || "[]");
};
/**
* 清除用户权限
*/
export const clearPermissions = () => {
updateUserPermissions([]);
};
\ No newline at end of file
......@@ -536,7 +536,7 @@ class homePage extends Component {
// 使用 formatter 来显示百分比
return `${params.marker}${params.name}${parseFloat(
params.value
)}%`; // 使用计算后的百分比值
).toFixed(2)}%`; // 使用计算后的百分比值
},
},
type: "bar",
......@@ -549,7 +549,9 @@ class homePage extends Component {
position: "top",
formatter: function (params) {
// 使用 formatter 来显示百分比
return `${params.value}%`;
return `${parseFloat(
params.value
).toFixed(2)}%`;
},
textStyle: {
//数值样式
......
......@@ -40,7 +40,6 @@ export function exfetchR(data, cb, check) {
// 校验token
if (check) {
url = checkToken;
// let authorization = cookie.load("token");
let authorization = sessionStorage.getItem("mgtk");
data = { authorization, terminalType: "1" };
}
......@@ -55,19 +54,21 @@ export function exfetchR(data, cb, check) {
const authRole = res?.data?.authRole || [];
if (authRole.length > 0) {
userPermissions = JSON.stringify(authRole.map(role => role.code));
window.localStorage.setItem("userPermissions", userPermissions);
}else{
window.localStorage.setItem("userPermissions", userPermissions);
}
// 确保userPermissions先写入localStorage
window.localStorage.setItem("userPermissions", userPermissions);
// 触发权限更新事件,确保权限上下文能收到更新
window.dispatchEvent(new CustomEvent("permissionsUpdate", {
detail: { permissions: JSON.parse(userPermissions || "[]") }
}));
//只有社群的话直接滚走去社群
// 只有社群的话直接滚走去社群
if (res.data.isOnlyCommunity) {
sessionStorage.setItem("mgtk", res.data.Authorization);
return cb(res);
} else {
if (cb) {
cb(res);
}
// 登录
if (!check) {
// 临时设置语言,后期需要根据选择语言更改
......@@ -76,20 +77,21 @@ export function exfetchR(data, cb, check) {
setGlobalData("companyCode", location.pathname.split("/")[1]);
setGlobalData("siteCode", location.pathname.split("/")[2]);
// 存储token
// cookie.save("token", res.data.Authorization);
sessionStorage.setItem("mgtk", res.data.Authorization);
// cookie.save("token", res.data.Authorization);
}
// 任意进入
// 临时设置语言,后期需要根据选择语言更改
setGlobalData("language", "zh-CN");
// cookie.save("userName", res.data.userInfo.fullName);//bug-12952-cwj
sessionStorage.setItem("userName", res.data.userInfo.fullName);
// 站点code
setGlobalData("companyCode", location.pathname.split("/")[1]);
setGlobalData("siteCode", location.pathname.split("/")[2]);
// 更新菜单和用户信息
dispatch({ type: Types.SIGN_FORM, userLogin: res.data });
// 最后执行回调函数,确保所有数据都已保存
if (cb) {
cb(res);
}
}
}
});
......@@ -160,4 +162,4 @@ export function setCollapsedFlag(data, cb) {
cb();
}
};
}
}
\ No newline at end of file
......@@ -24,6 +24,9 @@ import intl from "react-intl-universal";
import func from "@/common/commonFunc";
import { locales } from "@/locales/api";
import { publicLanguageGet } from "@/common/Layout/Header/redux/actions";
// 导入权限上下文
import { AuthProvider } from "@/common/permissions/AuthContext";
// end
const zh_CN = require("@/locales/zh-CN.json")
const en_US = require("@/locales/en-US.json")
......@@ -92,62 +95,54 @@ class Routes extends React.Component {
render() {
let cache = sessionStorage.getItem('lang') || 'zh_CN';
// intl.init({
// // currentLocale: localStorage.getItem("lang") || "zh_CN",
// currentLocale: cache,
// locales: { [cache]: this.props.languageType },
// fallbackLocale: null
// });
intl.init({
// currentLocale: localStorage.getItem("lang") || "zh_CN",
currentLocale: 'zh_CN',
locales: { zh_CN: zh_CN},
fallbackLocale: null
});
let languageBag = sessionStorage.getItem('lang') || 'zh_CN'
// antd 语言包
// let localeLangage = require("antd/es/locale/" + this.props.langage + ".js");
let localeLangage = require("antd/es/locale/" + languageBag + ".js");
return (
<ConfigProvider
csp={{ nonce: "d3ne7uWP43Bhr0e" }}
locale={localeLangage.default}
>
<Router history={history}>
<Suspense fallback={<div style={{ paddingTop: '50%', textAlign: 'center' }}><Spin tip="加载中..." /></div>}>
<Switch>
<Route
path={"/:companyCode"}
render={({ match }) => {
return (
<Switch>
<Route
path={`${match.url}/:sitCode`}
render={({ match }) => {
return (
<Switch>
<Route
path={`${match.url}/login`}
component={Login}
/>
<Route render={() => <Main match={match} />} />
</Switch>
);
}}
/>
<Route render={() => <ParamError text={"站点"} />} />
</Switch>
);
}}
/>
<Route render={() => <ParamError text={"企业"} />} />
</Switch>
</Suspense>
</Router>
{/* 添加权限上下文包装 */}
<AuthProvider>
<Router history={history}>
<Suspense fallback={<div style={{ paddingTop: '50%', textAlign: 'center' }}><Spin tip="加载中..." /></div>}>
<Switch>
<Route
path={"/:companyCode"}
render={({ match }) => {
return (
<Switch>
<Route
path={`${match.url}/:sitCode`}
render={({ match }) => {
return (
<Switch>
<Route
path={`${match.url}/login`}
component={Login}
/>
<Route render={() => <Main match={match} />} />
</Switch>
);
}}
/>
<Route render={() => <ParamError text={"站点"} />} />
</Switch>
);
}}
/>
<Route render={() => <ParamError text={"企业"} />} />
</Switch>
</Suspense>
</Router>
</AuthProvider>
</ConfigProvider>
);
}
......@@ -166,4 +161,4 @@ function mapDispatchToProps(dispatch) {
};
}
export default connect(mapStateToProps, mapDispatchToProps)(Routes);
export default connect(mapStateToProps, mapDispatchToProps)(Routes);
\ No newline at end of file
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment