From 987835ecde9ae6618ea1dc79f32127047a47851c Mon Sep 17 00:00:00 2001
From: wf <2547096351@qq.com>
Date: Tue, 8 Oct 2024 09:45:53 +0800
Subject: [PATCH 1/3] =?UTF-8?q?fix:=20=E4=BF=AE=E5=A4=8D=E5=AD=97=E6=AE=B5?=
=?UTF-8?q?=E6=8B=BC=E5=86=99=E8=A7=84=E8=8C=83?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
src/hooks/{useMneuMethod.ts => useMenuMethod.ts} | 2 +-
src/layout/components/Menu/menu-item.vue | 4 ++--
src/layout/layout-head/index.vue | 4 ++--
src/layout/layout-mixing/index.vue | 4 ++--
4 files changed, 7 insertions(+), 7 deletions(-)
rename src/hooks/{useMneuMethod.ts => useMenuMethod.ts} (92%)
diff --git a/src/hooks/useMneuMethod.ts b/src/hooks/useMenuMethod.ts
similarity index 92%
rename from src/hooks/useMneuMethod.ts
rename to src/hooks/useMenuMethod.ts
index 69f5861..de85910 100644
--- a/src/hooks/useMneuMethod.ts
+++ b/src/hooks/useMenuMethod.ts
@@ -2,7 +2,7 @@
* 菜单处理hooks,内置多种菜单处理场景
* @returns 菜单处理方法
*/
-export const useMneuMethod = () => {
+export const useMenuMethod = () => {
/**
* 多级菜单的显示隐藏
* @param {Menu.MenuOptions} item 菜单的item
diff --git a/src/layout/components/Menu/menu-item.vue b/src/layout/components/Menu/menu-item.vue
index 3d042c6..0a7f351 100644
--- a/src/layout/components/Menu/menu-item.vue
+++ b/src/layout/components/Menu/menu-item.vue
@@ -19,7 +19,7 @@
diff --git a/src/layout/layout-head/index.vue b/src/layout/layout-head/index.vue
index 93e466f..28530ac 100644
--- a/src/layout/layout-head/index.vue
+++ b/src/layout/layout-head/index.vue
@@ -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(true);
watch(language, () => {
diff --git a/src/layout/layout-mixing/index.vue b/src/layout/layout-mixing/index.vue
index b8c79aa..e30e5fc 100644
--- a/src/layout/layout-mixing/index.vue
+++ b/src/layout/layout-mixing/index.vue
@@ -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(true);
watch(language, () => {
From 77aa6c77049b480a9645a50f8679bf27cdec53b4 Mon Sep 17 00:00:00 2001
From: wf <2547096351@qq.com>
Date: Tue, 8 Oct 2024 15:14:10 +0800
Subject: [PATCH 2/3] =?UTF-8?q?feat:=20=E6=8E=A5=E5=8F=A3=E8=AF=B7?=
=?UTF-8?q?=E6=B1=82=E6=B5=8B=E8=AF=95=EF=BC=8C=E6=89=93=E5=8C=85=E8=B7=AF?=
=?UTF-8?q?=E5=BE=84=E3=80=81=E5=BC=80=E5=8F=91=E8=AF=B7=E6=B1=82=E8=B7=AF?=
=?UTF-8?q?=E5=BE=84=E5=AE=8C=E5=96=84?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
.env.development | 5 +++-
.env.production | 3 ++
.env.test | 5 +++-
index.html | 2 +-
src/api/index.ts | 36 ++++++++++++++---------
src/api/modules/home.ts | 4 ---
src/api/modules/login.ts | 10 +++++++
src/assets/logo/snow.svg | 1 +
src/views/login/components/login-form.vue | 16 ++++++----
vite.config.ts | 15 +++++++---
10 files changed, 66 insertions(+), 31 deletions(-)
delete mode 100644 src/api/modules/home.ts
create mode 100644 src/api/modules/login.ts
create mode 100644 src/assets/logo/snow.svg
diff --git a/.env.development b/.env.development
index 3a3adad..5d2653c 100644
--- a/.env.development
+++ b/.env.development
@@ -1,7 +1,10 @@
# 开发环境
VITE_USER_NODE_ENV = development
-# 开发环境地址前缀 (一般 '/' 或 './' 都可以,如果开发环境 '/' 打包预览白屏,请使用 './')
+# 打包路径 开发环境地址前缀 (一般 '/' 或 './' 都可以,如果开发环境 '/' 打包预览白屏,请使用 './')
VITE_PUBLIC_PATH = './'
+# 请求路径 管理系统/开发环境
+VITE_APP_BASE_URL = '/your-request-path'
+
VITE_GLOB_APP_TITLE = SnowAdmin
\ No newline at end of file
diff --git a/.env.production b/.env.production
index bbfa6b5..899679f 100644
--- a/.env.production
+++ b/.env.production
@@ -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
diff --git a/.env.test b/.env.test
index 2075598..3a8c45b 100644
--- a/.env.test
+++ b/.env.test
@@ -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
\ No newline at end of file
diff --git a/index.html b/index.html
index 3b536a6..9c43e06 100644
--- a/index.html
+++ b/index.html
@@ -2,7 +2,7 @@
-
+
<%= title %>
diff --git a/src/api/index.ts b/src/api/index.ts
index ba40802..7c0b478 100644
--- a/src/api/index.ts
+++ b/src/api/index.ts
@@ -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);
diff --git a/src/api/modules/home.ts b/src/api/modules/home.ts
deleted file mode 100644
index 86e8813..0000000
--- a/src/api/modules/home.ts
+++ /dev/null
@@ -1,4 +0,0 @@
-import axios from "@/api";
-
-// 第三板指标
-export const getTargetAPI = () => axios.get("/notice-list");
diff --git a/src/api/modules/login.ts b/src/api/modules/login.ts
new file mode 100644
index 0000000..5e17545
--- /dev/null
+++ b/src/api/modules/login.ts
@@ -0,0 +1,10 @@
+import axios from "@/api";
+
+// 登录
+export const LoginAPI = (data: any) => {
+ return axios({
+ url: "store/store.php?action=Login",
+ method: "post",
+ data
+ });
+};
diff --git a/src/assets/logo/snow.svg b/src/assets/logo/snow.svg
new file mode 100644
index 0000000..3390a7d
--- /dev/null
+++ b/src/assets/logo/snow.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/src/views/login/components/login-form.vue b/src/views/login/components/login-form.vue
index 8cb8a66..dab96eb 100644
--- a/src/views/login/components/login-form.vue
+++ b/src/views/login/components/login-form.vue
@@ -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");
};
diff --git a/vite.config.ts b/vite.config.ts
index 2deb6d1..2343f07 100644
--- a/vite.config.ts
+++ b/vite.config.ts
@@ -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(),
From 7d5a105818d6f627705e1a5000f35fddcca47421 Mon Sep 17 00:00:00 2001
From: wf <2547096351@qq.com>
Date: Tue, 8 Oct 2024 15:41:57 +0800
Subject: [PATCH 3/3] =?UTF-8?q?feat:=20=E6=96=B0=E5=A2=9E=E4=B8=80?=
=?UTF-8?q?=E4=BA=9B=E5=B7=A5=E5=85=B7=E5=87=BD=E6=95=B0=EF=BC=9Apx2px?=
=?UTF-8?q?=E3=80=81=E6=97=B6=E9=97=B4=E6=88=B3=E8=BD=AC=E6=97=B6=E9=97=B4?=
=?UTF-8?q?=E3=80=81formData=E8=87=AA=E5=8A=A8=E5=8A=A0=E5=8F=82?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
src/utils/index.ts | 58 ++++++++++++++++++++++++++++++++++++++++++++++
src/utils/px2px.ts | 15 ++++++++++++
2 files changed, 73 insertions(+)
create mode 100644 src/utils/px2px.ts
diff --git a/src/utils/index.ts b/src/utils/index.ts
index d6c7fa6..4a99f5a 100644
--- a/src/utils/index.ts
+++ b/src/utils/index.ts
@@ -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;
+};
diff --git a/src/utils/px2px.ts b/src/utils/px2px.ts
new file mode 100644
index 0000000..bb71b17
--- /dev/null
+++ b/src/utils/px2px.ts
@@ -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));
+};