|
|
|
|
@ -0,0 +1,296 @@
|
|
|
|
|
poetizepoetize-im-uisrcmain.js
|
|
|
|
|
// 引入Vue 3的createApp方法,用于创建Vue应用实例
|
|
|
|
|
import { createApp } from 'vue';
|
|
|
|
|
|
|
|
|
|
// 引入应用的根组件
|
|
|
|
|
import App from './App.vue';
|
|
|
|
|
|
|
|
|
|
// 引入Vue Router实例,用于管理前端路由
|
|
|
|
|
import router from './router';
|
|
|
|
|
|
|
|
|
|
// 引入Vuex或Pinia实例,用于状态管理
|
|
|
|
|
import store from './store';
|
|
|
|
|
|
|
|
|
|
// 从naive-ui库中引入多个UI组件,并使用create方法创建一个Naive UI插件实例
|
|
|
|
|
import {
|
|
|
|
|
create,
|
|
|
|
|
NAvatar,
|
|
|
|
|
NInput,
|
|
|
|
|
NIcon,
|
|
|
|
|
NTag,
|
|
|
|
|
NDivider,
|
|
|
|
|
NButton,
|
|
|
|
|
NDrawer,
|
|
|
|
|
NCard,
|
|
|
|
|
NTabs,
|
|
|
|
|
NTabPane,
|
|
|
|
|
NSwitch,
|
|
|
|
|
NModal,
|
|
|
|
|
NBadge,
|
|
|
|
|
NPopover,
|
|
|
|
|
NImage,
|
|
|
|
|
NPopconfirm
|
|
|
|
|
} from 'naive-ui';
|
|
|
|
|
|
|
|
|
|
poetizepoetize-im-uisrcApp.vue
|
|
|
|
|
// 从element-plus库中引入特定组件,并引入其样式文件
|
|
|
|
|
import {
|
|
|
|
|
ElUpload,
|
|
|
|
|
ElButton,
|
|
|
|
|
ElRadioGroup,
|
|
|
|
|
ElRadioButton
|
|
|
|
|
} from 'element-plus';
|
|
|
|
|
import 'element-plus/dist/index.css';
|
|
|
|
|
|
|
|
|
|
// 引入自定义的HTTP请求工具、通用方法和常量
|
|
|
|
|
import http from './utils/request';
|
|
|
|
|
import common from './utils/common';
|
|
|
|
|
import constant from './utils/constant';
|
|
|
|
|
|
|
|
|
|
// 引入自定义字体和样式文件
|
|
|
|
|
import 'vfonts/FiraCode.css';
|
|
|
|
|
import './assets/css/index.css';
|
|
|
|
|
import './assets/css/color.css';
|
|
|
|
|
import './assets/css/animation.css';
|
|
|
|
|
|
|
|
|
|
// 创建一个Naive UI插件实例,并注册所有需要的组件
|
|
|
|
|
const naive = create({
|
|
|
|
|
components: [
|
|
|
|
|
NAvatar, NInput, NIcon, NTag, NDivider, NButton,
|
|
|
|
|
NDrawer, NCard, NTabs, NTabPane, NSwitch, NModal,
|
|
|
|
|
NBadge, NPopover, NImage, NPopconfirm
|
|
|
|
|
]
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
// 创建Vue应用实例
|
|
|
|
|
const app = createApp(App);
|
|
|
|
|
|
|
|
|
|
// 使用Vue Router和状态管理实例
|
|
|
|
|
app.use(router);
|
|
|
|
|
app.use(store);
|
|
|
|
|
|
|
|
|
|
// 使用Naive UI插件
|
|
|
|
|
app.use(naive);
|
|
|
|
|
|
|
|
|
|
// 单独注册Element Plus的组件,使它们可以在应用的全局范围内使用
|
|
|
|
|
app.component(ElUpload.name, ElUpload);
|
|
|
|
|
app.component(ElButton.name, ElButton);
|
|
|
|
|
app.component(ElRadioGroup.name, ElRadioGroup);
|
|
|
|
|
app.component(ElRadioButton.name, ElRadioButton);
|
|
|
|
|
|
|
|
|
|
// 添加全局属性,用于HTTP请求、通用方法和常量
|
|
|
|
|
app.config.globalProperties.$http = http;
|
|
|
|
|
app.config.globalProperties.$common = common;
|
|
|
|
|
app.config.globalProperties.$constant = constant;
|
|
|
|
|
|
|
|
|
|
// 添加全局前置路由守卫
|
|
|
|
|
router.beforeEach((to, from, next) => {
|
|
|
|
|
// 检查目标路由是否需要认证
|
|
|
|
|
if (to.meta.requiresAuth) {
|
|
|
|
|
// 如果是根路径,则检查URL查询参数
|
|
|
|
|
if (to.path === "/") {
|
|
|
|
|
// 如果存在defaultStoreType查询参数,则存储到localStorage
|
|
|
|
|
if (typeof to.query.defaultStoreType !== "undefined") {
|
|
|
|
|
localStorage.setItem("defaultStoreType", to.query.defaultStoreType);
|
|
|
|
|
}
|
|
|
|
|
// 如果存在userToken查询参数,则验证token
|
|
|
|
|
if (typeof to.query.userToken !== "undefined") {
|
|
|
|
|
let userToken = to.query.userToken;
|
|
|
|
|
const xhr = new XMLHttpRequest();
|
|
|
|
|
xhr.open('post', constant.baseURL + "/user/token", false); // 同步请求,不推荐在生产环境中使用
|
|
|
|
|
xhr.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded');
|
|
|
|
|
xhr.send("userToken=" + userToken);
|
|
|
|
|
let result = JSON.parse(xhr.responseText);
|
|
|
|
|
// 如果token验证通过,则加载用户信息并重定向到应用主页面
|
|
|
|
|
if (!common.isEmpty(result) && result.code === 200) {
|
|
|
|
|
store.commit("loadCurrentUser", result.data);
|
|
|
|
|
localStorage.setItem("userToken", result.data.accessToken);
|
|
|
|
|
window.location.href = constant.imURL;
|
|
|
|
|
next();
|
|
|
|
|
} else {
|
|
|
|
|
// 如果token验证失败,则重定向到登录页面
|
|
|
|
|
window.location.href = constant.webBaseURL;
|
|
|
|
|
}
|
|
|
|
|
} else if (Boolean(localStorage.getItem("userToken"))) {
|
|
|
|
|
// 如果已存储userToken,则允许路由变化
|
|
|
|
|
next();
|
|
|
|
|
} else {
|
|
|
|
|
// 如果没有userToken,则重定向到登录页面
|
|
|
|
|
window.location.href = constant.webBaseURL;
|
|
|
|
|
}
|
|
|
|
|
} else {
|
|
|
|
|
// 如果不是根路径,则检查是否已存储userToken
|
|
|
|
|
if (Boolean(localStorage.getItem("userToken"))) {
|
|
|
|
|
// 如果已存储userToken,则允许路由变化
|
|
|
|
|
next();
|
|
|
|
|
} else {
|
|
|
|
|
// 如果没有userToken,则重定向到登录页面
|
|
|
|
|
window.location.href = constant.webBaseURL;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
} else {
|
|
|
|
|
// 如果目标路由不需要认证,则直接允许路由变化
|
|
|
|
|
next();
|
|
|
|
|
}
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
// 将Vue应用挂载到HTML中的#app元素上
|
|
|
|
|
app.mount('#app');
|
|
|
|
|
|
|
|
|
|
poetizepoetize-im-uisrcutilsajaxUpload.js
|
|
|
|
|
<template>
|
|
|
|
|
<!-- 使用naive-ui的NConfigProvider组件来提供全局配置 -->
|
|
|
|
|
<!-- :theme="null" 表示不应用任何预设主题,允许使用默认或自定义样式 -->
|
|
|
|
|
<!-- :locale="zhCN" 设置应用的语言环境为简体中文 -->
|
|
|
|
|
<!-- :date-locale="dateZhCN" 设置日期和时间的相关格式为简体中文 -->
|
|
|
|
|
<n-config-provider :theme="null" :locale="zhCN" :date-locale="dateZhCN">
|
|
|
|
|
<!-- 使用NDialogProvider组件来管理对话框的全局状态 -->
|
|
|
|
|
<!-- 这有助于在应用的任何位置控制对话框的显示和隐藏 -->
|
|
|
|
|
<n-dialog-provider>
|
|
|
|
|
<!-- router-view是Vue Router的一个组件,用于显示当前路由匹配的组件 -->
|
|
|
|
|
<!-- 它根据URL的变化来动态渲染不同的组件 -->
|
|
|
|
|
<router-view/>
|
|
|
|
|
</n-dialog-provider>
|
|
|
|
|
</n-config-provider>
|
|
|
|
|
</template>
|
|
|
|
|
|
|
|
|
|
<script>
|
|
|
|
|
// 从naive-ui库中导入所需的组件和语言/日期配置
|
|
|
|
|
import { NConfigProvider, NDialogProvider, zhCN, dateZhCN, darkTheme } from 'naive-ui';
|
|
|
|
|
|
|
|
|
|
export default {
|
|
|
|
|
// 注册在模板中使用的组件
|
|
|
|
|
components: {
|
|
|
|
|
NConfigProvider,
|
|
|
|
|
NDialogProvider
|
|
|
|
|
},
|
|
|
|
|
setup() {
|
|
|
|
|
// setup函数是Vue 3 Composition API的一部分,用于定义组件的响应式状态、计算属性和方法等
|
|
|
|
|
// 这里返回的对象中的属性可以在模板中直接使用
|
|
|
|
|
return {
|
|
|
|
|
// darkTheme是从naive-ui导入的,但在这个组件中没有被直接使用
|
|
|
|
|
// 它可能用于其他目的,比如根据条件动态切换主题
|
|
|
|
|
darkTheme,
|
|
|
|
|
// zhCN是简体中文的语言配置,用于NConfigProvider的locale属性
|
|
|
|
|
zhCN,
|
|
|
|
|
// dateZhCN是简体中文的日期和时间格式配置,用于NConfigProvider的date-locale属性
|
|
|
|
|
dateZhCN
|
|
|
|
|
// 注意:虽然zhCN和dateZhCN在setup函数中返回了,但在模板中它们是通过NConfigProvider的props直接使用的
|
|
|
|
|
// 因此,在模板中并不需要直接使用这些变量,但它们必须被导入并在setup中返回,以确保NConfigProvider能够接收到正确的props
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
</script>
|
|
|
|
|
|
|
|
|
|
<style scoped>
|
|
|
|
|
/* scoped样式意味着这里的CSS只会应用于当前组件,不会影响到其他组件 */
|
|
|
|
|
/* 当前组件没有定义任何样式,所以这里保持为空 */
|
|
|
|
|
</style>
|
|
|
|
|
|
|
|
|
|
// 从当前目录下的common.js文件中导入common模块(可能包含一些工具函数或配置)
|
|
|
|
|
import common from './common';
|
|
|
|
|
|
|
|
|
|
// 定义一个函数,用于根据XMLHttpRequest对象生成一个错误对象
|
|
|
|
|
function getError(action, option, xhr) {
|
|
|
|
|
let msg; // 定义一个变量用于存储错误信息
|
|
|
|
|
|
|
|
|
|
// 如果xhr对象有response属性(通常用于处理响应体为JSON的情况)
|
|
|
|
|
if (xhr.response) {
|
|
|
|
|
// 使用xhr.response.error(如果存在)或xhr.response作为错误信息
|
|
|
|
|
msg = `${xhr.response.error || xhr.response}`;
|
|
|
|
|
}
|
|
|
|
|
// 如果xhr对象有responseText属性(用于处理文本响应)
|
|
|
|
|
else if (xhr.responseText) {
|
|
|
|
|
// 直接使用xhr.responseText作为错误信息
|
|
|
|
|
msg = `${xhr.responseText}`;
|
|
|
|
|
}
|
|
|
|
|
// 如果以上两种情况都不满足
|
|
|
|
|
else {
|
|
|
|
|
// 使用一个通用的错误信息,包括失败的动作和HTTP状态码
|
|
|
|
|
msg = `fail to ${action} ${xhr.status}`;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 返回一个包含错误信息的Error对象
|
|
|
|
|
return new Error(msg);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 定义一个函数,用于获取XMLHttpRequest对象的响应体
|
|
|
|
|
function getBody(xhr) {
|
|
|
|
|
const text = xhr.responseText || xhr.response; // 尝试获取responseText或response属性
|
|
|
|
|
|
|
|
|
|
// 如果没有响应文本,则直接返回
|
|
|
|
|
if (!text) {
|
|
|
|
|
return text;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 尝试将文本解析为JSON对象
|
|
|
|
|
try {
|
|
|
|
|
return JSON.parse(text);
|
|
|
|
|
} catch {
|
|
|
|
|
// 如果解析失败,则返回原始的文本
|
|
|
|
|
return text;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 导出默认函数,该函数用于发送一个XMLHttpRequest请求
|
|
|
|
|
export default function (option) {
|
|
|
|
|
const xhr = new XMLHttpRequest(); // 创建一个新的XMLHttpRequest对象
|
|
|
|
|
const action = option.action; // 从option对象中获取请求的URL
|
|
|
|
|
|
|
|
|
|
const formData = new FormData(); // 创建一个FormData对象用于存储要发送的数据
|
|
|
|
|
|
|
|
|
|
// 如果option对象中有data属性,则遍历其键值对并添加到formData中
|
|
|
|
|
if (option.data) {
|
|
|
|
|
for (const [key, value] of Object.entries(option.data)) {
|
|
|
|
|
// 如果值是数组,则使用...操作符将其展开为多个参数传递给append方法
|
|
|
|
|
if (Array.isArray(value)) formData.append(key, ...value);
|
|
|
|
|
else formData.append(key, value);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 添加文件数据到formData中,文件名和文件对象从option中获取
|
|
|
|
|
formData.append(option.filename, option.file, option.file.name);
|
|
|
|
|
|
|
|
|
|
// 监听错误事件,并在错误发生时调用option.onError函数,传入一个Error对象
|
|
|
|
|
xhr.addEventListener('error', () => {
|
|
|
|
|
option.onError(getError(action, option, xhr));
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
// 监听加载完成事件,并根据响应状态码调用相应的回调函数
|
|
|
|
|
xhr.addEventListener('load', () => {
|
|
|
|
|
// 如果响应状态码表示错误(不是2xx)
|
|
|
|
|
if (xhr.status < 200 || xhr.status >= 300) {
|
|
|
|
|
// 调用option.onError函数,传入一个Error对象
|
|
|
|
|
return option.onError(getError(action, option, xhr));
|
|
|
|
|
}
|
|
|
|
|
// 如果响应成功,则调用option.onSuccess函数,并传入响应体
|
|
|
|
|
option.onSuccess(getBody(xhr));
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
// 打开请求,指定方法(如GET、POST)、URL和是否异步
|
|
|
|
|
xhr.open(option.method, action, true);
|
|
|
|
|
|
|
|
|
|
// 如果option对象中有withCredentials属性且xhr对象支持该属性,则设置withCredentials为true
|
|
|
|
|
if (option.withCredentials && 'withCredentials' in xhr) {
|
|
|
|
|
xhr.withCredentials = true;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 设置请求头,如果option对象中有headers属性
|
|
|
|
|
const headers = option.headers || {};
|
|
|
|
|
if (headers instanceof Headers) {
|
|
|
|
|
// 如果headers是一个Headers对象,则遍历其键值对并设置到xhr中
|
|
|
|
|
headers.forEach((value, key) => xhr.setRequestHeader(key, value));
|
|
|
|
|
} else {
|
|
|
|
|
// 否则,遍历一个普通的对象并设置请求头,跳过空值
|
|
|
|
|
for (const [key, value] of Object.entries(headers)) {
|
|
|
|
|
if (common.isEmpty(value)) continue; // 使用common模块的isEmpty函数检查值是否为空
|
|
|
|
|
xhr.setRequestHeader(key, value);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 发送请求,并传入formData作为请求体
|
|
|
|
|
xhr.send(formData);
|
|
|
|
|
|
|
|
|
|
// 返回xhr对象,允许调用者进一步操作(如取消请求)
|
|
|
|
|
return xhr;
|
|
|
|
|
}
|