Merge branch 'main' of gitee.com:wang_fan_w/SnowAdmin into main
This commit is contained in:
commit
e3b60cfa53
@ -1,7 +1,10 @@
|
||||
# 开发环境
|
||||
VITE_USER_NODE_ENV = development
|
||||
|
||||
# 开发环境地址前缀 (一般 '/' 或 './' 都可以,如果开发环境 '/' 打包预览白屏,请使用 './')
|
||||
# 打包路径 开发环境地址前缀 (一般 '/' 或 './' 都可以,如果开发环境 '/' 打包预览白屏,请使用 './')
|
||||
VITE_PUBLIC_PATH = './'
|
||||
|
||||
# 请求路径 管理系统/开发环境
|
||||
VITE_APP_BASE_URL = '/your-request-path'
|
||||
|
||||
VITE_GLOB_APP_TITLE = SnowAdmin
|
||||
@ -4,4 +4,7 @@ VITE_USER_NODE_ENV = production
|
||||
# 打包路径 (就是网站前缀, 例如部署到 http://dcodes.gitee.io/SnowAdmin/ 域名下, 就需要填写 /SnowAdmin/), 一般填一个斜杠 /
|
||||
VITE_PUBLIC_PATH = '/'
|
||||
|
||||
# 请求路径 管理系统/开发环境
|
||||
VITE_APP_BASE_URL = '/'
|
||||
|
||||
VITE_GLOB_APP_TITLE = SnowAdmin
|
||||
|
||||
@ -1,7 +1,10 @@
|
||||
# 开发环境
|
||||
VITE_USER_NODE_ENV = development
|
||||
VITE_USER_NODE_ENV = test
|
||||
|
||||
# 开发环境地址前缀 (一般 '/' 或 './' 都可以)
|
||||
VITE_PUBLIC_PATH = '/test'
|
||||
|
||||
# 请求路径 管理系统/开发环境
|
||||
VITE_APP_BASE_URL = '/'
|
||||
|
||||
VITE_GLOB_APP_TITLE = SnowAdmin
|
||||
@ -2,7 +2,7 @@
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8" />
|
||||
<link rel="icon" type="image/svg+xml" href="/src/assets/svgs/snow.svg" />
|
||||
<link rel="icon" type="image/svg+xml" href="/src/assets/logo/snow.svg" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||
<title><%= title %></title>
|
||||
</head>
|
||||
|
||||
@ -1,17 +1,15 @@
|
||||
import axios from "axios";
|
||||
import { useRouter } from "vue-router";
|
||||
const router = useRouter();
|
||||
import router from "@/router";
|
||||
import { Message } from "@arco-design/web-vue";
|
||||
// 创建axios实例
|
||||
const service = axios.create({
|
||||
baseURL: "https://mock.apifox.com/m1/4457302-4103374-default",
|
||||
timeout: 5000
|
||||
baseURL: "/api"
|
||||
});
|
||||
// 请求拦截器
|
||||
service.interceptors.request.use(
|
||||
function (config: any) {
|
||||
// 发送请求之前做什么
|
||||
// 获取token鉴权
|
||||
console.log("token?", localStorage.getItem("user-info"));
|
||||
let userInfo: any = {};
|
||||
if (localStorage.getItem("user-info")) {
|
||||
userInfo = JSON.parse(localStorage.getItem("user-info") as string);
|
||||
@ -19,12 +17,6 @@ service.interceptors.request.use(
|
||||
if (userInfo.token) {
|
||||
// 有token,在请求头中携带token
|
||||
config.headers.Authorization = userInfo.token;
|
||||
} else {
|
||||
// 如果没有token,则不允许发送请求,并且跳转至登录页要求登录,获取对应的token
|
||||
if (config.url !== "/login") {
|
||||
router.push("/login");
|
||||
Promise.reject("未登录");
|
||||
}
|
||||
}
|
||||
return config;
|
||||
},
|
||||
@ -37,11 +29,27 @@ service.interceptors.request.use(
|
||||
// 响应拦截器
|
||||
service.interceptors.response.use(
|
||||
function (response: any) {
|
||||
return response.data;
|
||||
if (response.status != 200) {
|
||||
Message.error("服务器异常,请联系管理员");
|
||||
return Promise.reject(response.data);
|
||||
}
|
||||
let res = response.data;
|
||||
if (res.code == 401) {
|
||||
Message.error("登录状态已过期");
|
||||
router.push("/login");
|
||||
return Promise.reject(res);
|
||||
} else if (res.code == 404) {
|
||||
Message.error("请求连接超时");
|
||||
return Promise.reject(res);
|
||||
} else if (res.code != 200) {
|
||||
Message.error(res.msg);
|
||||
return Promise.reject(res);
|
||||
} else {
|
||||
// 返回数据
|
||||
return Promise.resolve(res);
|
||||
}
|
||||
},
|
||||
function (error: any) {
|
||||
console.log("响应拦截", error, router);
|
||||
console.log("身份信息过期");
|
||||
localStorage.removeItem("user-info");
|
||||
router.push("/login");
|
||||
return Promise.reject(error);
|
||||
|
||||
@ -1,4 +0,0 @@
|
||||
import axios from "@/api";
|
||||
|
||||
// 第三板指标
|
||||
export const getTargetAPI = () => axios.get("/notice-list");
|
||||
10
src/api/modules/login.ts
Normal file
10
src/api/modules/login.ts
Normal file
@ -0,0 +1,10 @@
|
||||
import axios from "@/api";
|
||||
|
||||
// 登录
|
||||
export const LoginAPI = (data: any) => {
|
||||
return axios({
|
||||
url: "store/store.php?action=Login",
|
||||
method: "post",
|
||||
data
|
||||
});
|
||||
};
|
||||
1
src/assets/logo/snow.svg
Normal file
1
src/assets/logo/snow.svg
Normal file
File diff suppressed because one or more lines are too long
|
After Width: | Height: | Size: 5.5 KiB |
@ -2,7 +2,7 @@
|
||||
* 菜单处理hooks,内置多种菜单处理场景
|
||||
* @returns 菜单处理方法
|
||||
*/
|
||||
export const useMneuMethod = () => {
|
||||
export const useMenuMethod = () => {
|
||||
/**
|
||||
* 多级菜单的显示隐藏
|
||||
* @param {Menu.MenuOptions} item 菜单的item
|
||||
@ -19,7 +19,7 @@
|
||||
<script setup lang="ts">
|
||||
import MenuItem from "@/layout/components/Menu/menu-item.vue";
|
||||
import MenuItemIcon from "@/layout/components/Menu/menu-item-icon.vue";
|
||||
import { useMneuMethod } from "@/hooks/useMneuMethod";
|
||||
import { useMenuMethod } from "@/hooks/useMenuMethod";
|
||||
defineOptions({ name: "MenuItem", inheritAttrs: false });
|
||||
|
||||
interface Props {
|
||||
@ -31,7 +31,7 @@ const props = withDefaults(defineProps<Props>(), {
|
||||
routeTree: () => []
|
||||
});
|
||||
|
||||
const { menuShow, aMenuShow } = useMneuMethod();
|
||||
const { menuShow, aMenuShow } = useMenuMethod();
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped></style>
|
||||
|
||||
@ -50,7 +50,7 @@ import { storeToRefs } from "pinia";
|
||||
import { useRoutesListStore } from "@/store/modules/route-list";
|
||||
import { useRoutingMethod } from "@/hooks/useRoutingMethod";
|
||||
import { useThemeConfig } from "@/store/modules/theme-config";
|
||||
import { useMneuMethod } from "@/hooks/useMneuMethod";
|
||||
import { useMenuMethod } from "@/hooks/useMenuMethod";
|
||||
defineOptions({ name: "LayoutHead" });
|
||||
const router = useRouter();
|
||||
const routerStore = useRoutesListStore();
|
||||
@ -58,7 +58,7 @@ const themeStore = useThemeConfig();
|
||||
const { routeTree, currentRoute } = storeToRefs(routerStore);
|
||||
const { isFooter, language } = storeToRefs(themeStore);
|
||||
|
||||
const { menuShow, aMenuShow } = useMneuMethod();
|
||||
const { menuShow, aMenuShow } = useMenuMethod();
|
||||
|
||||
const drawing = ref<boolean>(true);
|
||||
watch(language, () => {
|
||||
|
||||
@ -53,7 +53,7 @@ import { useRoutesListStore } from "@/store/modules/route-list";
|
||||
import { useRoutingMethod } from "@/hooks/useRoutingMethod";
|
||||
import { storeToRefs } from "pinia";
|
||||
import { useThemeConfig } from "@/store/modules/theme-config";
|
||||
import { useMneuMethod } from "@/hooks/useMneuMethod";
|
||||
import { useMenuMethod } from "@/hooks/useMenuMethod";
|
||||
defineOptions({ name: "LayoutMixing" });
|
||||
const route = useRoute();
|
||||
const router = useRouter();
|
||||
@ -61,7 +61,7 @@ const routerStore = useRoutesListStore();
|
||||
const themeStore = useThemeConfig();
|
||||
const { isFooter, collapsed, asideDark, language } = storeToRefs(themeStore);
|
||||
const { routeTree } = storeToRefs(routerStore);
|
||||
const { aMenuShow } = useMneuMethod();
|
||||
const { aMenuShow } = useMenuMethod();
|
||||
|
||||
const drawing = ref<boolean>(true);
|
||||
watch(language, () => {
|
||||
|
||||
@ -103,3 +103,61 @@ export function webDefaultLanguage() {
|
||||
return "enUS";
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 时间戳转 年月日时分秒
|
||||
* 若timestamp不传则取当前时间
|
||||
* 若type不传则取 年月日时分秒
|
||||
* @param { number } timestamp 时间戳
|
||||
* @return 返回年月日时分秒字符串
|
||||
*/
|
||||
export const getTimestamp = (timestamp: string | number | null, type: string) => {
|
||||
let date = null;
|
||||
if (timestamp) {
|
||||
date = new Date(timestamp);
|
||||
} else {
|
||||
date = new Date();
|
||||
}
|
||||
let Year = String(date.getFullYear());
|
||||
let Moth = String(date.getMonth() + 1).padStart(2, "0");
|
||||
let Day = String(date.getDate()).padStart(2, "0");
|
||||
let Hour = String(date.getHours()).padStart(2, "0");
|
||||
let Minute = String(date.getMinutes()).padStart(2, "0");
|
||||
let Seconds = String(date.getSeconds()).padStart(2, "0");
|
||||
if (type === "yyyy") {
|
||||
return `${Year}`;
|
||||
}
|
||||
if (type === "yyyy-MM") {
|
||||
return `${Year}-${Moth}`;
|
||||
}
|
||||
if (type === "yyyy-MM-dd") {
|
||||
return `${Year}-${Moth}-${Day}`;
|
||||
}
|
||||
return `${Year}-${Moth}-${Day} ${Hour}:${Minute}:${Seconds}`;
|
||||
};
|
||||
|
||||
/**
|
||||
* 给formData循环添加参数,过滤null、undefined、空字符串、NaN
|
||||
* 示例:let data = appendFormData(your-object);
|
||||
* @param { object } obj 参数对象
|
||||
* @return 返回formData对象
|
||||
*/
|
||||
export const appendFormData = (obj: any) => {
|
||||
let formData = new FormData();
|
||||
function deepAppendFormData(formData: any, data: any, parentKey = "") {
|
||||
if (Array.isArray(data) || (typeof data === "object" && data !== null)) {
|
||||
// 如果数据是数组或对象,序列化为 JSON 字符串
|
||||
formData.append(parentKey, JSON.stringify(data));
|
||||
} else if (data !== null && data !== undefined && !Number.isNaN(data) && data !== "") {
|
||||
// 如果数据是基本类型,直接添加
|
||||
formData.append(parentKey, data);
|
||||
}
|
||||
}
|
||||
for (let key in obj) {
|
||||
if (obj.hasOwnProperty(key)) {
|
||||
deepAppendFormData(formData, obj[key], key);
|
||||
}
|
||||
}
|
||||
deepAppendFormData(formData, obj);
|
||||
return formData;
|
||||
};
|
||||
|
||||
15
src/utils/px2px.ts
Normal file
15
src/utils/px2px.ts
Normal file
@ -0,0 +1,15 @@
|
||||
/**
|
||||
* px转响应式px
|
||||
* 示例:$px2px(20, 1920),在1920px的设计稿上元素大小为20px,若在其它窗口大小下,会根据窗口大小自动缩放
|
||||
* @param {number} px 设计稿元素大小
|
||||
* @param {number} viewport 设计稿窗口大小
|
||||
* @returns {number} 响应式px
|
||||
*/
|
||||
export const px2px = (px: number, viewport: number): number => {
|
||||
const viewportWidth: number = (window.innerWidth || document.documentElement.clientWidth) as number;
|
||||
let originalWidth = px;
|
||||
let originalViewport = viewport;
|
||||
// 计算新视口下的宽度
|
||||
let newWidth = (originalWidth / originalViewport) * viewportWidth;
|
||||
return parseInt(String(newWidth));
|
||||
};
|
||||
@ -41,6 +41,7 @@
|
||||
import { Message } from "@arco-design/web-vue";
|
||||
import { useRouter } from "vue-router";
|
||||
import { useUserInfoStore } from "@/store/modules/user-info";
|
||||
|
||||
const router = useRouter();
|
||||
const form = ref({
|
||||
username: "admin",
|
||||
@ -102,16 +103,19 @@ const verify = ref({
|
||||
});
|
||||
const verifyCodeChange = (code: string) => (verify.value.verifyCode = code);
|
||||
|
||||
const onSubmit = ({ errors }: any) => {
|
||||
const onSubmit = async ({ errors }: any) => {
|
||||
if (errors) return;
|
||||
// 存储用户信息
|
||||
// 你的登录请求
|
||||
// ......
|
||||
|
||||
// 登录成功-存储用户信息
|
||||
let stores = useUserInfoStore();
|
||||
let account = {
|
||||
username: form.value.username,
|
||||
roles: ["admin"]
|
||||
username: form.value.username, // 用户名
|
||||
roles: ["admin"] // 角色权限
|
||||
};
|
||||
stores.setAccount(account);
|
||||
stores.setToken("DC-Admin");
|
||||
stores.setAccount(account); // 存储用户信息
|
||||
stores.setToken("Your-Token");
|
||||
Message.success("登录成功");
|
||||
router.replace("/home");
|
||||
};
|
||||
|
||||
@ -18,12 +18,19 @@ export default defineConfig(({ mode }) => {
|
||||
// 获取跟路径对应的文件
|
||||
const env = loadEnv(mode, root);
|
||||
return {
|
||||
// 开发或生产环境服务的公共基础路径
|
||||
// 生产环境服务的公共基础路径-用于生出环境的代理的路径
|
||||
base: env.VITE_PUBLIC_PATH,
|
||||
server: {
|
||||
// host: "0.0.0.0",
|
||||
// open: true,
|
||||
proxy: {}
|
||||
host: "0.0.0.0",
|
||||
open: true,
|
||||
// 为开发服务器配置自定义代理规则-用于开发时的代理
|
||||
proxy: {
|
||||
"/api": {
|
||||
target: env.VITE_APP_BASE_URL,
|
||||
changeOrigin: true,
|
||||
rewrite: path => path.replace(/^\/api/, "")
|
||||
}
|
||||
}
|
||||
},
|
||||
plugins: [
|
||||
vue(),
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user