提交 5636555f authored 作者: ziwencao's avatar ziwencao

build: build更新.

上级 8f396e34
/* eslint-env node */ /* eslint-env node */
require("@rushstack/eslint-patch/modern-module-resolution"); require("@rushstack/eslint-patch/modern-module-resolution");
module.exports = { module.exports = {
root: true, root: true,
extends: [ extends: [
"plugin:vue/vue3-essential", "plugin:vue/vue3-essential",
"airbnb-base", "airbnb-base",
"eslint:recommended", "eslint:recommended",
"@vue/eslint-config-typescript", "@vue/eslint-config-typescript",
"@vue/eslint-config-prettier", "@vue/eslint-config-prettier",
"vue-global-api", "vue-global-api",
], ],
overrides: [ overrides: [
{ {
files: ["cypress/e2e/**.{cy,spec}.{js,ts,jsx,tsx}"], files: ["cypress/e2e/**.{cy,spec}.{js,ts,jsx,tsx}"],
extends: ["plugin:cypress/recommended"], extends: ["plugin:cypress/recommended"],
}, },
], ],
parserOptions: { parserOptions: {
ecmaVersion: "latest", ecmaVersion: "latest",
parser: "@typescript-eslint/parser", parser: "@typescript-eslint/parser",
sourceType: "module", sourceType: "module",
}, },
plugins: ["vue", "@typescript-eslint"], plugins: ["vue", "@typescript-eslint"],
rules: { rules: {
// 关闭名称校验 // 关闭名称校验
"vue/multi-word-component-names": "off", "vue/multi-word-component-names": "off",
"import/no-unresolved": "off", "import/no-unresolved": "off",
"import/extensions": "off", "import/extensions": "off",
"import/no-absolute-path": "off", "import/no-absolute-path": "off",
"import/no-extraneous-dependencies": "off", "import/no-extraneous-dependencies": "off",
"vue/no-multiple-template-root": "off", "vue/no-multiple-template-root": "off",
"no-param-reassign": [ "no-param-reassign": [
"error", "error",
{ {
props: true, props: true,
ignorePropertyModificationsFor: ["state", "config"], ignorePropertyModificationsFor: ["state", "config"],
}, },
], ],
}, },
}; };
{} {
\ No newline at end of file "prettier/prettier": [
"error",
{
"endOfLine": "auto"
}
]
}
\ No newline at end of file
import { defineConfig } from "cypress"; import { defineConfig } from "cypress";
export default defineConfig({ export default defineConfig({
e2e: { e2e: {
specPattern: "cypress/e2e/**/*.{cy,spec}.{js,jsx,ts,tsx}", specPattern: "cypress/e2e/**/*.{cy,spec}.{js,jsx,ts,tsx}",
baseUrl: "http://localhost:4173", baseUrl: "http://localhost:4173",
}, },
}); });
// https://docs.cypress.io/api/introduction/api.html // https://docs.cypress.io/api/introduction/api.html
describe("My First Test", () => { describe("My First Test", () => {
it("visits the app root url", () => { it("visits the app root url", () => {
cy.visit("/"); cy.visit("/");
cy.contains("h1", "You did it!"); cy.contains("h1", "You did it!");
}); });
}); });
/// <reference types="cypress" /> /// <reference types="cypress" />
// *********************************************** // ***********************************************
// This example commands.ts shows you how to // This example commands.ts shows you how to
// create various custom commands and overwrite // create various custom commands and overwrite
// existing commands. // existing commands.
// //
// For more comprehensive examples of custom // For more comprehensive examples of custom
// commands please read more here: // commands please read more here:
// https://on.cypress.io/custom-commands // https://on.cypress.io/custom-commands
// *********************************************** // ***********************************************
// //
// //
// -- This is a parent command -- // -- This is a parent command --
// Cypress.Commands.add('login', (email, password) => { ... }) // Cypress.Commands.add('login', (email, password) => { ... })
// //
// //
// -- This is a child command -- // -- This is a child command --
// Cypress.Commands.add('drag', { prevSubject: 'element'}, (subject, options) => { ... }) // Cypress.Commands.add('drag', { prevSubject: 'element'}, (subject, options) => { ... })
// //
// //
// -- This is a dual command -- // -- This is a dual command --
// Cypress.Commands.add('dismiss', { prevSubject: 'optional'}, (subject, options) => { ... }) // Cypress.Commands.add('dismiss', { prevSubject: 'optional'}, (subject, options) => { ... })
// //
// //
// -- This will overwrite an existing command -- // -- This will overwrite an existing command --
// Cypress.Commands.overwrite('visit', (originalFn, url, options) => { ... }) // Cypress.Commands.overwrite('visit', (originalFn, url, options) => { ... })
// //
// declare global { // declare global {
// namespace Cypress { // namespace Cypress {
// interface Chainable { // interface Chainable {
// login(email: string, password: string): Chainable<void> // login(email: string, password: string): Chainable<void>
// drag(subject: string, options?: Partial<TypeOptions>): Chainable<Element> // drag(subject: string, options?: Partial<TypeOptions>): Chainable<Element>
// dismiss(subject: string, options?: Partial<TypeOptions>): Chainable<Element> // dismiss(subject: string, options?: Partial<TypeOptions>): Chainable<Element>
// visit(originalFn: CommandOriginalFn, url: string, options: Partial<VisitOptions>): Chainable<Element> // visit(originalFn: CommandOriginalFn, url: string, options: Partial<VisitOptions>): Chainable<Element>
// } // }
// } // }
// } // }
export {}; export {};
// *********************************************************** // ***********************************************************
// This example support/index.js is processed and // This example support/index.js is processed and
// loaded automatically before your test files. // loaded automatically before your test files.
// //
// This is a great place to put global configuration and // This is a great place to put global configuration and
// behavior that modifies Cypress. // behavior that modifies Cypress.
// //
// You can change the location of this file or turn off // You can change the location of this file or turn off
// automatically serving support files with the // automatically serving support files with the
// 'supportFile' configuration option. // 'supportFile' configuration option.
// //
// You can read more here: // You can read more here:
// https://on.cypress.io/configuration // https://on.cypress.io/configuration
// *********************************************************** // ***********************************************************
// Import commands.js using ES2015 syntax: // Import commands.js using ES2015 syntax:
import "./commands"; import "./commands";
// Alternatively you can use CommonJS syntax: // Alternatively you can use CommonJS syntax:
// require('./commands') // require('./commands')
/// <reference types="vite/client" /> /// <reference types="vite/client" />
declare module "*.vue" { declare module "*.vue" {
import { ComponentOptions } from "vue"; import { ComponentOptions } from "vue";
const componentOptions: ComponentOptions; const componentOptions: ComponentOptions;
export default componentOptions; export default componentOptions;
} }
...@@ -4,7 +4,7 @@ ...@@ -4,7 +4,7 @@
<meta charset="UTF-8" /> <meta charset="UTF-8" />
<link rel="icon" href="/favicon.ico" /> <link rel="icon" href="/favicon.ico" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" /> <meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Vite App</title> <title></title>
</head> </head>
<body> <body>
<div id="app"></div> <div id="app"></div>
......
// eslint-disable-next-line no-undef // eslint-disable-next-line no-undef
module.exports = { module.exports = {
plugins: { plugins: {
tailwindcss: {}, tailwindcss: {},
autoprefixer: {}, autoprefixer: {},
}, },
}; };
import type { AxiosRequestConfig } from "axios"; import type { AxiosRequestConfig } from "axios";
import request, { useRequest } from "@/libs/request"; import request, { useRequest } from "@/libs/request";
type ResponseType<T> = { type ResponseType<T> = {
code: number; code: number;
data: T; data: T;
msg: string; msg: string;
pageNum: number; pageNum: number;
total: number; total: number;
}; };
export default function requestAxios() { export default function requestAxios() {
return request<any>({ return request<any>({
method: "get", method: "get",
url: "/api", url: "/api",
}); });
} }
class Ajax { class Ajax {
static get<T>( static get<T>(
url: string, url: string,
data: { [args: string]: any }, data: { [args: string]: any },
axiosConfig: AxiosRequestConfig = {} axiosConfig: AxiosRequestConfig = {}
) { ) {
return useRequest<ResponseType<T>>({ return useRequest<ResponseType<T>>({
method: "get", method: "get",
url, url,
data, data,
...axiosConfig, ...axiosConfig,
}).content; }).content;
} }
static post<T>( static post<T>(
url: string, url: string,
data: { [args: string]: any }, data: { [args: string]: any },
axiosConfig: AxiosRequestConfig = {} axiosConfig: AxiosRequestConfig = {}
) { ) {
return useRequest<ResponseType<T>>({ return useRequest<ResponseType<T>>({
method: "post", method: "post",
url, url,
data, data,
...axiosConfig, ...axiosConfig,
}).content; }).content;
} }
static put<T>( static put<T>(
url: string, url: string,
data: { [args: string]: any }, data: { [args: string]: any },
axiosConfig: AxiosRequestConfig = {} axiosConfig: AxiosRequestConfig = {}
) { ) {
return useRequest<ResponseType<T>>({ return useRequest<ResponseType<T>>({
method: "put", method: "put",
url, url,
data, data,
...axiosConfig, ...axiosConfig,
}).content; }).content;
} }
static delete<T>( static delete<T>(
url: string, url: string,
data: { [args: string]: any }, data: { [args: string]: any },
axiosConfig: AxiosRequestConfig = {} axiosConfig: AxiosRequestConfig = {}
) { ) {
return useRequest<ResponseType<T>>({ return useRequest<ResponseType<T>>({
method: "delete", method: "delete",
url, url,
data, data,
...axiosConfig, ...axiosConfig,
}).content; }).content;
} }
} }
export const clxAjax = Ajax; export const clxAjax = Ajax;
import type { UserInfo } from "@/stores/user"; import type { UserInfo } from "@/stores/user";
import { clxAjax } from "."; import { clxAjax } from ".";
/** 登录接口 */ /** 登录接口 */
export const loginRequset = () => { export const loginRequset = () => {
return clxAjax.post<UserInfo>("user-service/owner/user/login", { return clxAjax.post<UserInfo>("user-service/owner/user/login", {
captcha: "11", captcha: "11",
mobile: "12222222222", mobile: "12222222222",
platform: 6, platform: 6,
pwd: "e10adc3949ba59abbe56e057f20f883e", pwd: "e10adc3949ba59abbe56e057f20f883e",
}); });
}; };
export default { export default {
loginRequset, loginRequset,
}; };
import SvgIcon from "@/components/sys/SvgIcon.vue"; import SvgIcon from "@/components/sys/SvgIcon.vue";
export const components = [SvgIcon]; export const components = [SvgIcon];
export const plugins = []; export const plugins = [];
<script setup lang="ts"> <script setup lang="ts">
import { computed, withDefaults } from "vue"; import { computed, withDefaults } from "vue";
type SvgProps = { type SvgProps = {
prefix?: string; prefix?: string;
name?: string; name?: string;
color?: string; color?: string;
}; };
const props = withDefaults(defineProps<SvgProps>(), { const props = withDefaults(defineProps<SvgProps>(), {
prefix: "icon", prefix: "icon",
name: "", name: "",
color: "#000", color: "#000",
}); });
const symbolId = computed(() => `#${props.prefix}-${props.name}`); const symbolId = computed(() => `#${props.prefix}-${props.name}`);
</script> </script>
<template> <template>
<svg aria-hidden="true"> <svg aria-hidden="true">
<use :xlink:href="symbolId" :fill="color" /> <use :xlink:href="symbolId" :fill="color" />
</svg> </svg>
</template> </template>
<template> <template>
<footer>底部</footer> <footer>底部</footer>
</template> </template>
<script lang="ts" setup name="DefaultFooter"></script> <script lang="ts" setup name="DefaultFooter"></script>
<style scoped> <style scoped>
footer { footer {
background-color: antiquewhite; background-color: antiquewhite;
} }
</style> </style>
import mitt, { type Emitter } from "mitt"; import mitt, { type Emitter } from "mitt";
const emitter: Emitter<any> = mitt(); const emitter: Emitter<any> = mitt();
export default emitter; export default emitter;
import { ref, type Ref } from "vue"; import { ref, type Ref } from "vue";
import axios, { import axios, {
AxiosError, AxiosError,
type AxiosResponse, type AxiosResponse,
type AxiosRequestConfig, type AxiosRequestConfig,
} from "axios"; } from "axios";
import storage from "store"; import storage from "store";
// import { ElMessage } from "element-plus"; // import { ElMessage } from "element-plus";
import { useUserStore, USER_INFO, type UserInfo } from "@/stores/user"; import { useUserStore, USER_INFO, type UserInfo } from "@/stores/user";
const { VITE_APP_BASE_URL } = import.meta.env; const { VITE_APP_BASE_URL } = import.meta.env;
const request = axios.create({ const request = axios.create({
// API 请求的默认前缀 // API 请求的默认前缀
baseURL: VITE_APP_BASE_URL as string, baseURL: VITE_APP_BASE_URL as string,
timeout: 10000, // 请求超时时间 timeout: 10000, // 请求超时时间
}); });
// 异常拦截处理器 // 异常拦截处理器
const errorHandler = (error: AxiosError) => { const errorHandler = (error: AxiosError) => {
const status = error.response?.status; const status = error.response?.status;
const useStore = useUserStore(); const useStore = useUserStore();
switch (status) { switch (status) {
/* eslint-disable no-param-reassign */ /* eslint-disable no-param-reassign */
case 400: case 400:
error.message = "请求错误"; error.message = "请求错误";
break; break;
case 401: case 401:
useStore.logout(); useStore.logout();
error.message = "未授权,请登录"; error.message = "未授权,请登录";
break; break;
case 403: case 403:
error.message = "拒绝访问"; error.message = "拒绝访问";
break; break;
case 404: case 404:
error.message = `请求地址出错: ${error.response?.config.url}`; error.message = `请求地址出错: ${error.response?.config.url}`;
break; break;
case 408: case 408:
error.message = "请求超时"; error.message = "请求超时";
break; break;
case 500: case 500:
error.message = "服务器内部错误"; error.message = "服务器内部错误";
break; break;
case 501: case 501:
error.message = "服务未实现"; error.message = "服务未实现";
break; break;
case 502: case 502:
error.message = "网关错误"; error.message = "网关错误";
break; break;
case 503: case 503:
error.message = "服务不可用"; error.message = "服务不可用";
break; break;
case 504: case 504:
error.message = "网关超时"; error.message = "网关超时";
break; break;
case 505: case 505:
error.message = "HTTP版本不受支持"; error.message = "HTTP版本不受支持";
break; break;
default: default:
break; break;
} }
return Promise.reject(error); return Promise.reject(error);
}; };
request.interceptors.request.use((config) => { request.interceptors.request.use((config) => {
// 如果 token 存在 // 如果 token 存在
// 让每个请求携带自定义 token 请根据实际情况自行修改 // 让每个请求携带自定义 token 请根据实际情况自行修改
// config.headers.Authorization = `Bearer ${storage.get(ACCESS_TOKEN)}`; // config.headers.Authorization = `Bearer ${storage.get(ACCESS_TOKEN)}`;
const userInfo = (storage.get(USER_INFO) as UserInfo) || {}; const userInfo = (storage.get(USER_INFO) as UserInfo) || {};
config.headers = { config.headers = {
...config.headers, ...config.headers,
Authorization: `Bearer ${userInfo?.accessToken}`, Authorization: `Bearer ${userInfo?.accessToken}`,
userId: userInfo?.userId, userId: userInfo?.userId,
childId: userInfo?.childId, childId: userInfo?.childId,
userMin: "vip", userMin: "vip",
accessToken: userInfo?.accessToken, accessToken: userInfo?.accessToken,
}; };
return config; return config;
}, errorHandler); }, errorHandler);
// response interceptor // response interceptor
request.interceptors.response.use((response: AxiosResponse) => { request.interceptors.response.use((response: AxiosResponse) => {
const dataAxios = response.data; const dataAxios = response.data;
const useStore = useUserStore(); const useStore = useUserStore();
// 这个状态码是和后端约定的 // 这个状态码是和后端约定的
const { code, msg } = dataAxios; const { code, msg } = dataAxios;
// 根据 code 进行判断 // 根据 code 进行判断
if (code === undefined) { if (code === undefined) {
// 如果没有 code 代表这不是项目后端开发的接口 // 如果没有 code 代表这不是项目后端开发的接口
return dataAxios; return dataAxios;
} }
// 有 code 代表这是一个后端接口 可以进行进一步的判断 // 有 code 代表这是一个后端接口 可以进行进一步的判断
// if (code) ElMessage.error(msg); // if (code) ElMessage.error(msg);
if (code) alert(msg); if (code) alert(msg);
switch (code) { switch (code) {
case 0: case 0:
// code === 0 代表没有错误 // code === 0 代表没有错误
return dataAxios; return dataAxios;
case 1: case 1:
// code === 1 代表请求错误 // code === 1 代表请求错误
throw Error(msg); throw Error(msg);
case 401: case 401:
useStore.logout(); useStore.logout();
throw Error(msg); throw Error(msg);
default: default:
// 不是正确的 code // 不是正确的 code
return dataAxios; return dataAxios;
} }
}, errorHandler); }, errorHandler);
export default request; export default request;
export interface RequestConfig { export interface RequestConfig {
successMessage?: string; successMessage?: string;
errorMessage?: string; errorMessage?: string;
/** 立即发送请求 */ /** 立即发送请求 */
immediate?: boolean; immediate?: boolean;
} }
export function useRequest<T>( export function useRequest<T>(
axiosConfig: AxiosRequestConfig, axiosConfig: AxiosRequestConfig,
requestConfig?: RequestConfig requestConfig?: RequestConfig
) { ) {
// 最终返回的数据 // 最终返回的数据
const data = ref<T>(); const data = ref<T>();
// 请求失败返回的 Error 对象 // 请求失败返回的 Error 对象
const error = ref<Error>(); const error = ref<Error>();
// 请求状态 // 请求状态
const loading = ref(false); const loading = ref(false);
// 立即发送请求 // 立即发送请求
const immediate = requestConfig?.immediate !== false; const immediate = requestConfig?.immediate !== false;
// 终止请求 // 终止请求
const { CancelToken } = axios; const { CancelToken } = axios;
const { token, cancel } = CancelToken.source(); const { token, cancel } = CancelToken.source();
// 合并求情配置 // 合并求情配置
const config = { ...axiosConfig, cancelToken: token }; const config = { ...axiosConfig, cancelToken: token };
// 请求 Promise // 请求 Promise
function run() { function run() {
loading.value = true; loading.value = true;
return new Promise<Ref<T | undefined>>((resolve, reject) => { return new Promise<Ref<T | undefined>>((resolve, reject) => {
request<T>(config) request<T>(config)
.then((res: T) => { .then((res: T) => {
data.value = res; data.value = res;
resolve(data); resolve(data);
}) })
.catch((err: Error) => { .catch((err: Error) => {
error.value = err; error.value = err;
reject(err); reject(err);
if (requestConfig?.errorMessage) { if (requestConfig?.errorMessage) {
throw Error(requestConfig.errorMessage); throw Error(requestConfig.errorMessage);
} }
}) })
.finally(() => { .finally(() => {
loading.value = false; loading.value = false;
}); });
}); });
} }
const content = new Promise<Ref<T | undefined>>((resolve, reject) => { const content = new Promise<Ref<T | undefined>>((resolve, reject) => {
if (immediate) { if (immediate) {
run() run()
.then((res) => { .then((res) => {
resolve(res); resolve(res);
}) })
.catch((err) => { .catch((err) => {
reject(err); reject(err);
}); });
} }
}); });
return { data, error, loading, content, run, cancel }; return { data, error, loading, content, run, cancel };
} }
import { AxiosRequestConfig } from "axios"; import { AxiosRequestConfig } from "axios";
declare module "axios" { declare module "axios" {
export interface AxiosInstance { export interface AxiosInstance {
/* eslint-disable no-unused-vars */ /* eslint-disable no-unused-vars */
<T = any>(config: AxiosRequestConfig): Promise<T>; <T = any>(config: AxiosRequestConfig): Promise<T>;
request<T = any>(config: AxiosRequestConfig): Promise<T>; request<T = any>(config: AxiosRequestConfig): Promise<T>;
get<T = any>(url: string, config?: AxiosRequestConfig): Promise<T>; get<T = any>(url: string, config?: AxiosRequestConfig): Promise<T>;
delete<T = any>(url: string, config?: AxiosRequestConfig): Promise<T>; delete<T = any>(url: string, config?: AxiosRequestConfig): Promise<T>;
head<T = any>(url: string, config?: AxiosRequestConfig): Promise<T>; head<T = any>(url: string, config?: AxiosRequestConfig): Promise<T>;
post<T = any>( post<T = any>(
url: string, url: string,
data?: any, data?: any,
config?: AxiosRequestConfig config?: AxiosRequestConfig
): Promise<T>; ): Promise<T>;
put<T = any>( put<T = any>(
url: string, url: string,
data?: any, data?: any,
config?: AxiosRequestConfig config?: AxiosRequestConfig
): Promise<T>; ): Promise<T>;
patch<T = any>( patch<T = any>(
url: string, url: string,
data?: any, data?: any,
config?: AxiosRequestConfig config?: AxiosRequestConfig
): Promise<T>; ): Promise<T>;
} }
} }
export default function baseApiUrl(port?: number) { export default function baseApiUrl(port?: number) {
const { VITE_APP_BASE_URL } = import.meta.env; const { VITE_APP_BASE_URL } = import.meta.env;
if (port) { if (port) {
return `${VITE_APP_BASE_URL}:${port}`; return `${VITE_APP_BASE_URL}:${port}`;
} }
return VITE_APP_BASE_URL; return VITE_APP_BASE_URL;
} }
// 处理静态资源链接 // 处理静态资源链接
export default function baseStaticUrl(src = "") { export default function baseStaticUrl(src = "") {
const { VITE_APP_STATIC_URL } = import.meta.env; const { VITE_APP_STATIC_URL } = import.meta.env;
if (src) { if (src) {
return `${VITE_APP_STATIC_URL}${src}`; return `${VITE_APP_STATIC_URL}${src}`;
} }
return VITE_APP_STATIC_URL as string; return VITE_APP_STATIC_URL as string;
} }
export { default as baseStaticUrl } from "./baseStaticUrl"; export { default as baseStaticUrl } from "./baseStaticUrl";
export { default as baseApiUrl } from "./baseApiUrl"; export { default as baseApiUrl } from "./baseApiUrl";
export { default as setTitle } from "./setTitle"; export { default as setTitle } from "./setTitle";
export default function setTitle(title?: string) { export default function setTitle(title?: string) {
const { VITE_APP_TITLE } = import.meta.env; const { VITE_APP_TITLE } = import.meta.env;
const processTitle = VITE_APP_TITLE || "CLX"; const processTitle = VITE_APP_TITLE || "CLX";
window.document.title = `${title ? `${title} | ` : ""} ${processTitle}`; window.document.title = `${title ? `${title} | ` : ""} ${processTitle}`;
} }
<script lang="ts" setup name="404"> <script lang="ts" setup name="404">
import { ref } from "vue"; import { ref } from "vue";
import router from "@/router"; import router from "@/router";
const countdown = ref(3); const countdown = ref(3);
const countdownInterval = setInterval(() => { const countdownInterval = setInterval(() => {
countdown.value -= 1; countdown.value -= 1;
if (countdown.value === 0) { if (countdown.value === 0) {
router.push("/"); router.push("/");
clearInterval(countdownInterval); clearInterval(countdownInterval);
} }
}, 1000); }, 1000);
</script> </script>
<template> <template>
<div class="h-screen flex flex-col justify-center items-center"> <div class="h-screen flex flex-col justify-center items-center">
<h1 class="text-3xl">404</h1> <h1 class="text-3xl">404</h1>
<p>{{ countdown }} seconds after the jump...</p> <p>{{ countdown }} seconds after the jump...</p>
</div> </div>
</template> </template>
<route lang="yaml"> <route lang="yaml">
name: home name: home
meta: meta:
auth: true auth: true
</route> </route>
<script lang="ts" setup name="PageHome"> <script lang="ts" setup name="PageHome">
import { useRouter } from "vue-router"; import { useRouter } from "vue-router";
const router = useRouter(); const router = useRouter();
function regist() { function regist() {
router.push({ router.push({
path: "/user/regist", path: "/user/regist",
query: { query: {
id: 123, id: 123,
}, },
}); });
} }
</script> </script>
<template> <template>
<div> <div>
<div class="page-example">home</div> <div class="page-example">home</div>
<router-link to="/user/login"><button>登錄</button></router-link> <router-link to="/user/login"><button>登錄</button></router-link>
<button type="primary" @click="regist()">注册</button> <button type="primary" @click="regist()">注册</button>
<div <div
class="p-6 max-w-sm mx-auto bg-white rounded-xl shadow-md flex items-center space-x-4" class="p-6 max-w-sm mx-auto bg-white rounded-xl shadow-md flex items-center space-x-4"
> >
<div class="flex-shrink-0"> <div class="flex-shrink-0">
<svg-icon class="h-12 w-12" name="tooling"></svg-icon> <svg-icon class="h-12 w-12" name="tooling"></svg-icon>
</div> </div>
<div> <div>
<div class="text-xl font-medium text-black">ChitChat</div> <div class="text-xl font-medium text-black">ChitChat</div>
<p class="text-gray-500">You have a new message!</p> <p class="text-gray-500">You have a new message!</p>
</div> </div>
</div> </div>
</div> </div>
</template> </template>
<style scoped> <style scoped>
.login-icon { .login-icon {
width: 20px; width: 20px;
height: 20px; height: 20px;
} }
</style> </style>
...@@ -2,4 +2,4 @@ ...@@ -2,4 +2,4 @@
redirect: redirect:
name: home name: home
</route> </route>
<template></template> <!-- <template></template> -->
<route lang="yaml"> <route lang="yaml">
name: user name: user
meta: meta:
auth: false auth: false
title: 用户 title: 用户
layout: BlankLayout layout: BlankLayout
</route> </route>
<route lang="yaml"> <route lang="yaml">
name: login name: login
meta: meta:
auth: false auth: false
title: 登录 title: 登录
layout: BlankLayout layout: BlankLayout
</route> </route>
<template> <template>
<div> <div>
<div class="page-example">login</div> <div class="page-example">login</div>
<div <div
class="p-6 max-w-sm mx-auto bg-white rounded-xl shadow-md flex items-center space-x-4" class="p-6 max-w-sm mx-auto bg-white rounded-xl shadow-md flex items-center space-x-4"
> >
<div class="flex-shrink-0"> <div class="flex-shrink-0">
<svg-icon class="h-12 w-12" name="tooling"></svg-icon> <svg-icon class="h-12 w-12" name="tooling"></svg-icon>
</div> </div>
<div> <div>
<div class="text-xl font-medium text-black"> <div class="text-xl font-medium text-black">
<button type="link" @click="login()">登錄</button> <button type="link" @click="login()">登錄</button>
</div> </div>
<p class="text-gray-500">点击登录!</p> <p class="text-gray-500">点击登录!</p>
</div> </div>
</div> </div>
</div> </div>
</template> </template>
<script lang="ts" setup name="PageLogin"> <script lang="ts" setup name="PageLogin">
import { useRoute, useRouter } from "vue-router"; import { useRoute, useRouter } from "vue-router";
// import { ElMessage } from "element-plus"; // import { ElMessage } from "element-plus";
import { loginRequset } from "@/api/user"; import { loginRequset } from "@/api/user";
import { useUserStore } from "@/stores/user"; import { useUserStore } from "@/stores/user";
import { baseStaticUrl } from "@/libs/utils"; import { baseStaticUrl } from "@/libs/utils";
const router = useRouter(); const router = useRouter();
const route = useRoute(); const route = useRoute();
function GetRequest(urlStr: string) { function GetRequest(urlStr: string) {
if (!urlStr.includes("?")) return {}; if (!urlStr.includes("?")) return {};
const url = urlStr.split("?")[1].split("&"); // 获取url中"?"符后的字串 const url = urlStr.split("?")[1].split("&"); // 获取url中"?"符后的字串
const query: { [args: string]: any } = {}; const query: { [args: string]: any } = {};
url.forEach((item: string) => { url.forEach((item: string) => {
query[item.split("=")[0]] = decodeURIComponent(item.split("=")[1]); // 转码 query[item.split("=")[0]] = decodeURIComponent(item.split("=")[1]); // 转码
}); });
return query; return query;
} }
console.log(import.meta.env); console.log(import.meta.env);
function login() { function login() {
loginRequset() loginRequset()
.then((res) => { .then((res) => {
console.log(res); console.log(res);
const data = res?.value?.data; const data = res?.value?.data;
if (!data) return; if (!data) return;
const user = useUserStore(); const user = useUserStore();
user.setUserInfo({ user.setUserInfo({
...data, ...data,
}); });
const queryRedirect = route.query?.redirect as string; const queryRedirect = route.query?.redirect as string;
router.push({ router.push({
path: queryRedirect || "/", path: queryRedirect || "/",
query: GetRequest(queryRedirect || ""), query: GetRequest(queryRedirect || ""),
}); });
}) })
.catch((error) => { .catch((error) => {
// ElMessage.error(error); // ElMessage.error(error);
alert(error); alert(error);
}); });
} }
</script> </script>
<style scoped> <style scoped>
.login-icon { .login-icon {
width: 20px; width: 20px;
height: 20px; height: 20px;
} }
</style> </style>
<route lang="yaml"> <route lang="yaml">
name: regist name: regist
meta: meta:
auth: true auth: true
title: 注册 title: 注册
layout: BlankLayout layout: BlankLayout
</route> </route>
<script lang="ts" setup name="PageRegist"> <script lang="ts" setup name="PageRegist">
import { useRoute } from "vue-router"; import { useRoute } from "vue-router";
const route = useRoute(); const route = useRoute();
console.log(route.query); console.log(route.query);
</script> </script>
<template> <template>
<div> <div>
<div class="page-example">注册</div> <div class="page-example">注册</div>
</div> </div>
</template> </template>
<style scoped></style> <style scoped></style>
import storage from "store"; import storage from "store";
import NProgress from "nprogress"; import NProgress from "nprogress";
import router from "@/router"; import router from "@/router";
import { USER_INFO, useUserStore, type UserInfo } from "@/stores/user"; import { USER_INFO, useUserStore, type UserInfo } from "@/stores/user";
import { setTitle } from "@/libs/utils"; import { setTitle } from "@/libs/utils";
// 进度条 // 进度条
import "nprogress/nprogress.css"; import "nprogress/nprogress.css";
const loginRoutePath = "/user/login"; const loginRoutePath = "/user/login";
const defaultRoutePath = "/home"; const defaultRoutePath = "/home";
/** /**
* 路由拦截 * 路由拦截
* 权限验证 * 权限验证
*/ */
router.beforeEach(async (to, from, next) => { router.beforeEach(async (to, from, next) => {
const userStore = useUserStore(); const userStore = useUserStore();
const userInfo = (storage.get(USER_INFO) as UserInfo) || {}; const userInfo = (storage.get(USER_INFO) as UserInfo) || {};
const token = userInfo?.accessToken; const token = userInfo?.accessToken;
// 进度条 // 进度条
NProgress.start(); NProgress.start();
// 验证当前路由所有的匹配中是否需要有登录验证的 // 验证当前路由所有的匹配中是否需要有登录验证的
if (to.matched.some((r) => r.meta.auth)) { if (to.matched.some((r) => r.meta.auth)) {
// 是否存有token作为验证是否登录的条件 // 是否存有token作为验证是否登录的条件
if (token && token !== "undefined") { if (token && token !== "undefined") {
if (to.path === loginRoutePath) { if (to.path === loginRoutePath) {
next({ path: defaultRoutePath }); next({ path: defaultRoutePath });
} else { } else {
next(); next();
} }
} else { } else {
// 没有登录的时候跳转到登录界面 // 没有登录的时候跳转到登录界面
// 携带上登录成功之后需要跳转的页面完整路径 // 携带上登录成功之后需要跳转的页面完整路径
next({ next({
name: "login", name: "login",
query: { query: {
redirect: to.fullPath, redirect: to.fullPath,
}, },
}); });
NProgress.done(); NProgress.done();
} }
} else { } else {
// 不需要身份校验 直接通过 // 不需要身份校验 直接通过
next(); next();
} }
}); });
router.afterEach((to) => { router.afterEach((to) => {
// 进度条 // 进度条
NProgress.done(); NProgress.done();
setTitle(to.meta.title as string); setTitle(to.meta.title as string);
}); });
import { ref, computed } from "vue"; import { ref, computed } from "vue";
import { defineStore } from "pinia"; import { defineStore } from "pinia";
export const useCounterStore = defineStore("counter", () => { export const useCounterStore = defineStore("counter", () => {
const count = ref(0); const count = ref(0);
const doubleCount = computed(() => count.value * 2); const doubleCount = computed(() => count.value * 2);
function increment() { function increment() {
count.value += 1; count.value += 1;
} }
return { count, doubleCount, increment }; return { count, doubleCount, increment };
}); });
export default { export default {
useCounterStore, useCounterStore,
}; };
import { defineStore } from "pinia"; import { defineStore } from "pinia";
import storage from "store"; import storage from "store";
import UaParser from "ua-parser-js"; import UaParser from "ua-parser-js";
import type { IResult as UaResult } from "ua-parser-js"; import type { IResult as UaResult } from "ua-parser-js";
import router from "@/router"; import router from "@/router";
/** /**
* 用户信息-类型 * 用户信息-类型
*/ */
export interface UserInfo { export interface UserInfo {
accessToken: string; accessToken: string;
authed: number; authed: number;
childId: number; childId: number;
company: string; company: string;
domain: string; domain: string;
equipmentFlag: number; equipmentFlag: number;
headImg: string; headImg: string;
logo: string; logo: string;
mobile: string; mobile: string;
name: string; name: string;
openid: string; openid: string;
placeId: number; placeId: number;
placeName: string; placeName: string;
role: number; role: number;
shortName: string; shortName: string;
tradeAuth: number; tradeAuth: number;
truckNo: number; truckNo: number;
userId: number; userId: number;
walletCode: number; walletCode: number;
} }
export interface UserState { export interface UserState {
userInfo: UserInfo; userInfo: UserInfo;
ua: UaResult; ua: UaResult;
} }
/** userInfo 存储信息 字段名 */ /** userInfo 存储信息 字段名 */
export const USER_INFO: "USER_INFO" = "USER_INFO"; export const USER_INFO: "USER_INFO" = "USER_INFO";
/** token 字段名 */ /** token 字段名 */
export const ACCESS_TOKEN: "accessToken" = "accessToken"; export const ACCESS_TOKEN: "accessToken" = "accessToken";
/** userId 字段名 */ /** userId 字段名 */
export const USER_ID: "userId" = "userId"; export const USER_ID: "userId" = "userId";
const defaultUserInfo = { const defaultUserInfo = {
accessToken: "", accessToken: "",
authed: 0, authed: 0,
childId: 0, childId: 0,
company: "", company: "",
domain: "", domain: "",
equipmentFlag: 0, equipmentFlag: 0,
headImg: "", headImg: "",
logo: "", logo: "",
mobile: "", mobile: "",
name: "", name: "",
openid: "", openid: "",
placeId: 0, placeId: 0,
placeName: "", placeName: "",
role: 0, role: 0,
shortName: "", shortName: "",
tradeAuth: 0, tradeAuth: 0,
truckNo: 0, truckNo: 0,
userId: 0, userId: 0,
walletCode: 0, walletCode: 0,
}; };
export const useUserStore = defineStore({ export const useUserStore = defineStore({
id: "clxUser", id: "clxUser",
state: (): UserState => ({ state: (): UserState => ({
userInfo: { ...defaultUserInfo }, userInfo: { ...defaultUserInfo },
ua: new UaParser().getResult(), ua: new UaParser().getResult(),
}), }),
actions: { actions: {
setUserInfo(payload: UserInfo) { setUserInfo(payload: UserInfo) {
this.userInfo = payload; this.userInfo = payload;
storage.set(USER_INFO, this.userInfo || {}); storage.set(USER_INFO, this.userInfo || {});
}, },
resetUserInfo() { resetUserInfo() {
this.userInfo = { ...defaultUserInfo }; this.userInfo = { ...defaultUserInfo };
}, },
async getUserInfo() { async getUserInfo() {
const userInfo = (storage.get(USER_INFO) as UserInfo) || {}; const userInfo = (storage.get(USER_INFO) as UserInfo) || {};
const userID = userInfo?.userId; const userID = userInfo?.userId;
if (!userID) { if (!userID) {
// 异步调用查询用户信息接口 // 异步调用查询用户信息接口
} }
}, },
async login() { async login() {
// 调用登陆接口 // 调用登陆接口
// this.setUserInfo(payload); // this.setUserInfo(payload);
// router.push({ path: '/' }); // router.push({ path: '/' });
}, },
async logout() { async logout() {
// 调用退出登陆接口 // 调用退出登陆接口
this.resetUserInfo(); this.resetUserInfo();
router.push({ name: "login" }); router.push({ name: "login" });
}, },
async verification(token: string) { async verification(token: string) {
// 调用 token 验证接口 // 调用 token 验证接口
return Promise.resolve(token); return Promise.resolve(token);
}, },
}, },
}); });
Markdown 格式
0%
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论