diff --git a/src/App.vue b/src/App.vue index 23cdb0b0..b6593853 100644 --- a/src/App.vue +++ b/src/App.vue @@ -1,33 +1,48 @@ diff --git a/src/main.js b/src/main.js index 304e5839..905c110b 100644 --- a/src/main.js +++ b/src/main.js @@ -1,32 +1,68 @@ -import Vue from 'vue' -import App from './App.vue' -import router from './router' -import store from './store' -import VueCookie from 'vue-cookie' +// 导入Vue框架 +import Vue from 'vue'; + +// 导入根组件 +import App from './App.vue'; + +// 导入Vue Router实例,用于页面路由管理 +import router from './router'; + +// 导入Vuex状态管理实例 +import store from './store'; + +// 导入vue-cookie插件,用于处理cookie +import VueCookie from 'vue-cookie'; + +// 导入Element UI组件库 import ElementUI from 'element-ui'; -import moment from 'moment' +// 导入moment.js库,用于日期和时间处理 +import moment from 'moment'; + +// 导入Element UI的CSS样式 import 'element-ui/lib/theme-chalk/index.css'; -import './assets/css/common.css' -import './assets/scss/index.scss' -import httpRequest from '@/utils/httpRequest' // api: https://github.com/axios/axios -import { isAuth } from '@/utils' -import VueClipboard from 'vue-clipboard2' +// 导入全局CSS样式 +import './assets/css/common.css'; + +// 导入全局SCSS样式 +import './assets/scss/index.scss'; + +// 导入自定义的httpRequest工具,基于axios的封装(注意:这里注释的api链接可能不准确,因为httpRequest的具体实现未在代码中给出) +import httpRequest from '@/utils/httpRequest'; + +// 导入自定义的权限验证工具 +import { isAuth } from '@/utils'; + +// 导入vue-clipboard2插件,用于复制文本到剪贴板 +import VueClipboard from 'vue-clipboard2'; + +// 使用Element UI组件库 Vue.use(ElementUI); -Vue.use(VueClipboard) -Vue.use(VueCookie) -Vue.config.productionTip = false -// 挂载全局 -Vue.prototype.$http = httpRequest // ajax请求方法 -Vue.prototype.isAuth = isAuth // 权限方法 +// 使用vue-clipboard2插件 +Vue.use(VueClipboard); + +// 使用vue-cookie插件 +Vue.use(VueCookie); + +// 禁止Vue在启动时生成生产提示 +Vue.config.productionTip = false; + +// 挂载全局属性和方法 +// 全局ajax请求方法 +Vue.prototype.$http = httpRequest; +// 全局权限验证方法 +Vue.prototype.isAuth = isAuth; +// 设置moment.js的语言环境为中文 moment.locale('zh-cn'); -Vue.prototype.$moment = moment; //时间处理 +// 将moment挂载到Vue原型上,作为全局的时间处理方法 +Vue.prototype.$moment = moment; +// 创建Vue实例,并挂载到#app元素上 new Vue({ - router, - store, - render: h => h(App) -}).$mount('#app') + router, // 注入路由,使得我们可以通过this.$router访问路由实例 + store, // 注入store,使得我们可以通过this.$store访问状态管理实例 + render: h => h(App) // 渲染App组件 +}).$mount('#app'); // 挂载到DOM上的#app元素 \ No newline at end of file diff --git a/src/store/index.js b/src/store/index.js index 1c9d94b3..ebf0d802 100644 --- a/src/store/index.js +++ b/src/store/index.js @@ -1,5 +1,7 @@ import Vue from 'vue' import Vuex from 'vuex' + +// 引入各个模块的 Vuex 状态管理文件 import common from './modules/common' import user from './modules/user' import article from './modules/article' @@ -7,18 +9,26 @@ import message from './modules/message' import wxUserTags from './modules/wxUserTags' import wxAccount from './modules/wxAccount' +// 注册 Vuex 插件,使其可用于 Vue 中 Vue.use(Vuex) export default new Vuex.Store({ - modules: { - common, - user, - article, - message, - wxUserTags, - wxAccount - }, - mutations: { - }, - strict: true +// 使用 modules 来组织不同的子模块 +modules: { +// 引入并注册各个模块 +common, // 公共模块,可能用于存储一些通用的状态 +user, // 用户模块,存储用户信息相关的状态 +article, // 文章模块,存储与文章相关的状态 +message, // 消息模块,存储消息相关的状态 +wxUserTags, // 微信用户标签模块,管理微信用户标签的状态 +wxAccount // 微信账号模块,管理微信账号相关的状态 +}, + +// mutations 用于同步修改状态,这里没有定义任何 mutations(可根据需求进行扩展) +mutations: { +// 这里可以添加全局的 mutation,但目前没有定义 +}, + +// 启用严格模式,开发环境下会对状态的修改进行检查,确保只能通过 mutation 修改状态 +strict: true }) diff --git a/src/store/modules/wxAccount.js b/src/store/modules/wxAccount.js index 19d1c8b5..78903d08 100644 --- a/src/store/modules/wxAccount.js +++ b/src/store/modules/wxAccount.js @@ -1,32 +1,59 @@ -import Vue from 'vue' +import Vue from 'vue'; + export default { - namespaced: true, - state: { - ACCOUNT_TYPES:{ - 1:'订阅号', - 2:'服务号' - }, - accountList:[], - selectedAppid:'' - }, - mutations: { - updateAccountList (state, list) { - state.accountList = list - if(!list.length)return - if(!state.selectedAppid){ - let appidCookie = Vue.cookie.get('appid') - let selectedAppid = appidCookie?appidCookie:list[0].appid - this.commit('wxAccount/selectAccount',selectedAppid) - } - }, - selectAccount (state, appid) { - Vue.cookie.set('appid',appid) - let oldAppid = state.selectedAppid - state.selectedAppid = appid - if(oldAppid){//切换账号时刷新网页 - location.reload(); - } - }, - } - } - \ No newline at end of file +// Vuex模块启用命名空间 +namespaced: true, + +// Vuex的state,用来存储应用状态 +state: { +// 账户类型,映射数字ID到账户类型名称 +ACCOUNT_TYPES: { +1: '订阅号', +2: '服务号' +}, + +// 存储账户列表 +accountList: [], + +// 当前选中的Appid,用来标识选择的账号 +selectedAppid: '' +}, + +// Vuex的mutations,用来修改state +mutations: { +// 更新账户列表 +updateAccountList (state, list) { +// 更新state中的accountList +state.accountList = list; + +// 如果列表为空,直接返回 +if (!list.length) return; + +// 如果当前没有选中的Appid,则从cookie或列表中选择一个默认Appid +if (!state.selectedAppid) { +let appidCookie = Vue.cookie.get('appid'); +// 获取cookie中的appid,如果有则使用cookie中的appid,否则使用列表中的第一个Appid +let selectedAppid = appidCookie ? appidCookie : list[0].appid; +// 通过commit调用mutation更新选中的账号 +this.commit('wxAccount/selectAccount', selectedAppid); +} +}, + +// 选择某个账号(切换Appid) +selectAccount (state, appid) { +// 更新cookie中的appid,保存选中的Appid +Vue.cookie.set('appid', appid); + +// 记录上一个选中的Appid +let oldAppid = state.selectedAppid; + +// 更新当前选中的Appid +state.selectedAppid = appid; + +// 如果选中的Appid发生变化,则刷新页面 +if (oldAppid) { +location.reload(); +} +} +} +}; diff --git a/src/store/modules/wxUserTags.js b/src/store/modules/wxUserTags.js index ce78e9a6..6cb02ef4 100644 --- a/src/store/modules/wxUserTags.js +++ b/src/store/modules/wxUserTags.js @@ -1,12 +1,20 @@ export default { - namespaced: true, - state: { - tags:[] - }, - mutations: { - updateTags (state, tags) { - state.tags = tags - } - } + // 启用 Vuex 模块的命名空间,避免命名冲突 + namespaced: true, + + // state 存储模块的状态 + state: { + // tags 用来存储标签数据的数组 + tags: [] + }, + + // mutations 用来修改 state 中的状态 + mutations: { + // 更新 tags 数组的内容 + updateTags (state, tags) { + // 将传入的 tags 更新到 state 中 + state.tags = tags; } + } + }; \ No newline at end of file diff --git a/src/utils/httpRequest.js b/src/utils/httpRequest.js index 4112705b..9a5ad605 100644 --- a/src/utils/httpRequest.js +++ b/src/utils/httpRequest.js @@ -4,74 +4,81 @@ import router from '@/router' import qs from 'qs' import merge from 'lodash/merge' import { clearLoginInfo } from '@/utils' -const baseUrl = '/wx' +const baseUrl = '/wx' // 设置请求的基础路径 + +// 创建axios实例 const http = axios.create({ - timeout: 1000 * 30, - withCredentials: true, - headers: { - 'Content-Type': 'application/json; charset=utf-8' - } +timeout: 1000 * 30, // 设置请求超时为30秒 +withCredentials: true, // 允许携带跨域请求的cookie +headers: { +'Content-Type': 'application/json; charset=utf-8' // 默认请求头为json格式 +} }) /** - * 请求拦截 - */ +* 请求拦截器 +* 在每个请求发送之前,加入token(从cookie中获取) +*/ http.interceptors.request.use(config => { - config.headers['token'] = Vue.cookie.get('token') // 请求头带上token - return config +config.headers['token'] = Vue.cookie.get('token') // 在请求头中加入token +return config // 返回请求配置 }, error => { - return Promise.reject(error) +return Promise.reject(error) // 请求出错时,返回Promise拒绝 }) /** - * 响应拦截 - */ +* 响应拦截器 +* 对响应数据进行拦截处理 +* 如果返回的状态码为401(未授权),则清除登录信息并跳转到登录页 +*/ http.interceptors.response.use(response => { - if (response.data && response.data.code === 401) { // 401, token失效 - clearLoginInfo() - router.push({ name: 'login' }) - } - return response +if (response.data && response.data.code === 401) { // 判断返回的code是否为401,代表token失效 +clearLoginInfo() // 清除登录信息 +router.push({ name: 'login' }) // 跳转到登录页面 +} +return response // 返回响应数据 }, error => { - return Promise.reject(error) +return Promise.reject(error) // 响应出错时,返回Promise拒绝 }) /** - * 请求地址处理 - * @param {*} actionName action方法名称 - */ +* 请求地址处理函数 +* @param {*} actionName 接口的名称,拼接成完整的URL +* @returns {string} 拼接后的完整URL +*/ http.adornUrl = (actionName) => { - // 非生产环境 && 开启代理, 接口前缀统一使用[/proxyApi/]前缀做代理拦截! - return baseUrl + actionName +// 在开发环境下,如果开启了代理,则请求路径会带上代理前缀 +return baseUrl + actionName // 返回完整的请求URL } /** - * get请求参数处理 - * @param {*} params 参数对象 - * @param {*} openDefultParams 是否开启默认参数? - */ +* get请求的参数处理 +* @param {*} params 请求的参数对象 +* @param {*} openDefultParams 是否开启默认参数 +* @returns {object} 处理后的参数对象 +*/ http.adornParams = (params = {}, openDefultParams = true) => { - var defaults = { - 't': new Date().getTime() - } - return openDefultParams ? merge(defaults, params) : params +const defaults = { +'t': new Date().getTime() // 添加时间戳参数,防止缓存 +} +return openDefultParams ? merge(defaults, params) : params // 合并默认参数和传入的参数 } /** - * post请求数据处理 - * @param {*} data 数据对象 - * @param {*} openDefultdata 是否开启默认数据? - * @param {*} contentType 数据格式 - * json: 'application/json; charset=utf-8' - * form: 'application/x-www-form-urlencoded; charset=utf-8' - */ +* post请求的数据处理 +* @param {*} data 请求的数据对象 +* @param {*} openDefultdata 是否开启默认数据 +* @param {*} contentType 数据格式类型('json'或'form') +* @returns {string} 处理后的数据 +*/ http.adornData = (data = {}, openDefultdata = true, contentType = 'json') => { - var defaults = { - 't': new Date().getTime() - } - data = openDefultdata ? merge(defaults, data) : data - return contentType === 'json' ? JSON.stringify(data) : qs.stringify(data) +const defaults = { +'t': new Date().getTime() // 添加时间戳参数,防止缓存 +} +data = openDefultdata ? merge(defaults, data) : data // 合并默认数据和传入的数据 +// 根据不同的contentType,处理数据格式 +return contentType === 'json' ? JSON.stringify(data) : qs.stringify(data) } -export default http +export default http // 导出axios实例,供其他模块使用 diff --git a/src/utils/index.js b/src/utils/index.js index facd0660..aa52b209 100644 --- a/src/utils/index.js +++ b/src/utils/index.js @@ -3,56 +3,76 @@ import router from '@/router' import store from '@/store' /** - * 获取uuid - */ +* 获取UUID +* 生成一个标准的UUID(例如:xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx) +* 使用随机数和指定格式的规则生成UUID +*/ export function getUUID() { - return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, c => { - return (c === 'x' ? (Math.random() * 16 | 0) : ('r&0x3' | '0x8')).toString(16) - }) +return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, c => { +return (c === 'x' ? (Math.random() * 16 | 0) : ('r&0x3' | '0x8')).toString(16) +}) } /** - * 是否有权限 - * @param {*} key - */ +* 检查是否有某个权限 +* @param {*} key 权限的标识符 +* @returns {boolean} 如果权限列表中包含该权限返回true,否则返回false +*/ export function isAuth(key) { - return JSON.parse(sessionStorage.getItem('permissions') || '[]').indexOf(key) !== -1 || false +// 从 sessionStorage 中获取权限列表,并转换为数组,如果没有权限列表,默认返回空数组 +return JSON.parse(sessionStorage.getItem('permissions') || '[]').indexOf(key) !== -1 || false } /** - * 树形数据转换 - * @param {*} data - * @param {*} id - * @param {*} pid - */ +* 将平面数据转换为树形数据 +* @param {*} data 原始平面数据 +* @param {*} id 唯一标识符字段,默认为'id' +* @param {*} pid 父级标识符字段,默认为'parentId' +* @returns {Array} 转换后的树形数据 +*/ export function treeDataTranslate(data, id = 'id', pid = 'parentId') { - var res = [] - var temp = {} - for (var i = 0; i < data.length; i++) { - temp[data[i][id]] = data[i] - } - for (var k = 0; k < data.length; k++) { - if (temp[data[k][pid]] && data[k][id] !== data[k][pid]) { - if (!temp[data[k][pid]]['children']) { - temp[data[k][pid]]['children'] = [] - } - if (!temp[data[k][pid]]['_level']) { - temp[data[k][pid]]['_level'] = 1 - } - data[k]['_level'] = temp[data[k][pid]]._level + 1 - temp[data[k][pid]]['children'].push(data[k]) - } else { - res.push(data[k]) - } - } - return res +var res = [] // 存储最终的树形结构 +var temp = {} // 临时存储每个节点,以便快速查找父节点 + +// 将数据转换为临时对象,key为节点的id,值为节点本身 +for (var i = 0; i < data.length; i++) { +temp[data[i][id]] = data[i] +} + +// 遍历数据,根据pid将节点组织成树形结构 +for (var k = 0; k < data.length; k++) { +// 如果节点的父节点存在,并且当前节点的id不等于父节点的id +if (temp[data[k][pid]] && data[k][id] !== data[k][pid]) { +// 如果父节点没有'children'属性,则初始化为数组 +if (!temp[data[k][pid]]['children']) { +temp[data[k][pid]]['children'] = [] +} +// 如果父节点没有'_level'属性,则设置为1 +if (!temp[data[k][pid]]['_level']) { +temp[data[k][pid]]['_level'] = 1 +} +// 当前节点的级别为父节点的级别+1 +data[k]['_level'] = temp[data[k][pid]]._level + 1 +// 将当前节点推送到父节点的children数组中 +temp[data[k][pid]]['children'].push(data[k]) +} else { +// 如果当前节点是根节点,直接推送到结果数组中 +res.push(data[k]) +} +} + +return res // 返回转换后的树形数据 } /** - * 清除登录信息 - */ +* 清除登录信息 +* 用于用户退出时,清理本地存储的登录信息 +*/ export function clearLoginInfo() { - Vue.cookie.delete('token') - //store.commit('resetStore') - router.options.isAddDynamicMenuRoutes = false +// 删除cookie中的'token' +Vue.cookie.delete('token') +// 目前注释掉了重置store的操作,若需要可以解除注释 +// store.commit('resetStore') +// 重置动态菜单路由标志 +router.options.isAddDynamicMenuRoutes = false } diff --git a/src/utils/validate.js b/src/utils/validate.js index be7357aa..c25e3f44 100644 --- a/src/utils/validate.js +++ b/src/utils/validate.js @@ -1,31 +1,36 @@ /** - * 邮箱 - * @param {*} s - */ +* 验证邮箱格式 +* @param {*} s - 需要验证的邮箱地址 +* @returns {boolean} - 返回是否是有效的邮箱地址 +*/ export function isEmail(s) { - return /^([a-zA-Z0-9_-])+@([a-zA-Z0-9_-])+((.[a-zA-Z0-9_-]{2,3}){1,2})$/.test(s) -} - -/** - * 手机号码 - * @param {*} s - */ -export function isMobile(s) { + return /^([a-zA-Z0-9_-])+@([a-zA-Z0-9_-])+((\.[a-zA-Z0-9_-]{2,3}){1,2})$/.test(s) + } + + /** + * 验证手机号码格式(中国手机号) + * @param {*} s - 需要验证的手机号 + * @returns {boolean} - 返回是否是有效的手机号码 + */ + export function isMobile(s) { return /^1[0-9]{10}$/.test(s) -} - -/** - * 电话号码 - * @param {*} s - */ -export function isPhone(s) { + } + + /** + * 验证固定电话号码格式 + * @param {*} s - 需要验证的电话号码 + * @returns {boolean} - 返回是否是有效的电话号码(包括区号和本地号码) + */ + export function isPhone(s) { return /^([0-9]{3,4}-)?[0-9]{7,8}$/.test(s) -} - -/** - * URL地址 - * @param {*} s - */ -export function isURL(s) { + } + + /** + * 验证URL地址格式 + * @param {*} s - 需要验证的URL地址 + * @returns {boolean} - 返回是否是有效的URL地址(包括http或https协议) + */ + export function isURL(s) { return /^http[s]?:\/\/.*/.test(s) -} + } + \ No newline at end of file diff --git a/src/views/common/404.vue b/src/views/common/404.vue index 38589071..c96b106e 100644 --- a/src/views/common/404.vue +++ b/src/views/common/404.vue @@ -1,61 +1,81 @@ - - - - + + \ No newline at end of file diff --git a/src/views/common/home.vue b/src/views/common/home.vue index 948980de..fe655f7e 100644 --- a/src/views/common/home.vue +++ b/src/views/common/home.vue @@ -1,12 +1,18 @@ - - + } + + \ No newline at end of file diff --git a/src/views/common/login.vue b/src/views/common/login.vue index a43ddb05..1914a120 100644 --- a/src/views/common/login.vue +++ b/src/views/common/login.vue @@ -1,184 +1,220 @@ - + + +
+

管理员登录

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + - + \ No newline at end of file diff --git a/src/views/common/theme.vue b/src/views/common/theme.vue index 1aeccbcb..388b2ff6 100644 --- a/src/views/common/theme.vue +++ b/src/views/common/theme.vue @@ -1,33 +1,53 @@ - + - + \ No newline at end of file diff --git a/src/views/main-content.vue b/src/views/main-content.vue index 987dcd84..050dc5e3 100644 --- a/src/views/main-content.vue +++ b/src/views/main-content.vue @@ -1,7 +1,9 @@ - + \ No newline at end of file diff --git a/src/views/main-navbar-update-password.vue b/src/views/main-navbar-update-password.vue index 4c2cd4a7..8cf0b223 100644 --- a/src/views/main-navbar-update-password.vue +++ b/src/views/main-navbar-update-password.vue @@ -1,19 +1,26 @@ - + \ No newline at end of file diff --git a/src/views/main-navbar.vue b/src/views/main-navbar.vue index 75364b13..6d67fd9a 100644 --- a/src/views/main-navbar.vue +++ b/src/views/main-navbar.vue @@ -1,60 +1,76 @@ + \ No newline at end of file diff --git a/src/views/main-sidebar-sub-menu.vue b/src/views/main-sidebar-sub-menu.vue index b45b1b61..9c5cf325 100644 --- a/src/views/main-sidebar-sub-menu.vue +++ b/src/views/main-sidebar-sub-menu.vue @@ -1,50 +1,38 @@ - - + \ No newline at end of file diff --git a/src/views/main-sidebar.vue b/src/views/main-sidebar.vue index 795a07d0..9e8a962e 100644 --- a/src/views/main-sidebar.vue +++ b/src/views/main-sidebar.vue @@ -1,69 +1,78 @@ + \ No newline at end of file diff --git a/src/views/main.vue b/src/views/main.vue index 2b044f4b..3f6a31f4 100644 --- a/src/views/main.vue +++ b/src/views/main.vue @@ -1,9 +1,16 @@ + \ No newline at end of file diff --git a/src/views/modules/oss/oss-config.vue b/src/views/modules/oss/oss-config.vue index 484f90d5..ae429ca5 100644 --- a/src/views/modules/oss/oss-config.vue +++ b/src/views/modules/oss/oss-config.vue @@ -1,127 +1,150 @@ - + - + \ No newline at end of file diff --git a/src/views/modules/oss/oss-uploader-tencent.vue b/src/views/modules/oss/oss-uploader-tencent.vue index d3dac232..81e3ddb2 100644 --- a/src/views/modules/oss/oss-uploader-tencent.vue +++ b/src/views/modules/oss/oss-uploader-tencent.vue @@ -1,87 +1,105 @@ - - + +
+ + + +
{{uploading ? infoText : '上传文件'}}
+
+ + + - - + }, + mounted() { + // 组件加载完毕后,发起请求获取 COS 配置数据 + this.$http({ + url: this.$http.adornUrl('/sys/oss/config'), + method: 'get', + params: this.$http.adornParams() // 传递请求参数 + }).then(({ data }) => { + if (data && data.code === 200) { + // 如果获取成功,保存配置数据 + this.cosConfig = data.config; + // 初始化腾讯云 COS 实例 + cos = new COS({ + SecretId: data.config.qcloudSecretId, + SecretKey: data.config.qcloudSecretKey, + }); + } else { + // 配置获取失败,提示错误信息 + this.$message.error('请先配置云存储相关信息!'); + } + }) + }, + methods: { + // 选择文件的方法 + selectFile() { + // 如果当前没有文件正在上传,点击触发文件选择框 + if (!this.uploading) { + this.$refs.fileInput.click(); + } + }, + // 文件选择后触发的回调方法 + onFileChange() { + let file = this.$refs.fileInput.files[0]; // 获取选中的文件 + this.uploading = true; // 设置上传状态为 true + let now = new Date(); + // 生成上传文件的存储路径(包括日期和时间戳确保路径唯一) + let path = now.toISOString().slice(0, 10) + '/' + now.getTime() + file.name.substr(file.name.lastIndexOf('.')); + + // 调用腾讯云 COS 上传文件方法 + cos.putObject({ + Bucket: this.cosConfig.qcloudBucketName, // 必须指定的桶名称 + Region: this.cosConfig.qcloudRegion, // 必须指定的区域 + Key: path, // 文件存储路径(文件名) + Body: file, // 上传的文件对象 + onProgress: (progressData) => { // 上传进度回调 + // 更新上传进度提示文本 + this.infoText = '上传中:' + (progressData.percent * 100).toFixed(2) + '%'; + } + }, (err, data) => { + // 上传完成后回调,处理成功和失败的情况 + console.log(err || data); + this.uploading = false; // 上传状态恢复为 false + if (data) { + // 上传成功,更新提示文本 + this.infoText = '上传文件'; + // 生成文件访问的 URL + let fileUrl = 'https://' + this.cosConfig.qcloudBucketName + '.cos.' + this.cosConfig.qcloudRegion + '.myqcloud.com/' + path; + this.saveUploadResult(fileUrl); // 保存上传结果 + } else { + // 上传失败,显示错误消息 + this.$message.error('文件上传失败', err); + } + }); + }, + // 保存上传结果(上传成功后调用,传入文件的访问 URL) + saveUploadResult(url) { + this.$http({ + url: this.$http.adornUrl('/sys/oss/upload'), + method: 'post', + data: { url: url } // 将上传的文件 URL 传给服务器 + }).then(({ data }) => { + // 上传成功后,触发 `uploaded` 事件,将文件 URL 传递给父组件 + this.$emit('uploaded', url); + }) + } + } + } + + + + \ No newline at end of file diff --git a/src/views/modules/oss/oss-uploader.vue b/src/views/modules/oss/oss-uploader.vue index e013aace..64bc5914 100644 --- a/src/views/modules/oss/oss-uploader.vue +++ b/src/views/modules/oss/oss-uploader.vue @@ -1,59 +1,73 @@ - - + + \ No newline at end of file diff --git a/src/views/modules/oss/oss.vue b/src/views/modules/oss/oss.vue index 35fdcbeb..4c403ce3 100644 --- a/src/views/modules/oss/oss.vue +++ b/src/views/modules/oss/oss.vue @@ -39,108 +39,79 @@ diff --git a/src/views/modules/sys/config-add-or-update.vue b/src/views/modules/sys/config-add-or-update.vue index 26b6aa1a..898bfb61 100644 --- a/src/views/modules/sys/config-add-or-update.vue +++ b/src/views/modules/sys/config-add-or-update.vue @@ -1,96 +1,117 @@ diff --git a/src/views/modules/sys/config.vue b/src/views/modules/sys/config.vue index 6a7517b5..b20162c1 100644 --- a/src/views/modules/sys/config.vue +++ b/src/views/modules/sys/config.vue @@ -1,134 +1,172 @@ diff --git a/src/views/modules/sys/log.vue b/src/views/modules/sys/log.vue index 117b2ac8..5223704c 100644 --- a/src/views/modules/sys/log.vue +++ b/src/views/modules/sys/log.vue @@ -1,90 +1,107 @@ diff --git a/src/views/modules/sys/menu-add-or-update.vue b/src/views/modules/sys/menu-add-or-update.vue index 2d49a09f..ccee5e29 100644 --- a/src/views/modules/sys/menu-add-or-update.vue +++ b/src/views/modules/sys/menu-add-or-update.vue @@ -1,218 +1,253 @@ - - - - + + \ No newline at end of file diff --git a/src/views/modules/sys/menu.vue b/src/views/modules/sys/menu.vue index ad3fb1bc..bcdbd004 100644 --- a/src/views/modules/sys/menu.vue +++ b/src/views/modules/sys/menu.vue @@ -1,109 +1,148 @@ - - + + \ No newline at end of file diff --git a/src/views/modules/sys/role-add-or-update.vue b/src/views/modules/sys/role-add-or-update.vue index 641f01c2..c02f64e5 100644 --- a/src/views/modules/sys/role-add-or-update.vue +++ b/src/views/modules/sys/role-add-or-update.vue @@ -1,111 +1,148 @@ - - + + \ No newline at end of file diff --git a/src/views/modules/sys/role.vue b/src/views/modules/sys/role.vue index 000c3188..c02f64e5 100644 --- a/src/views/modules/sys/role.vue +++ b/src/views/modules/sys/role.vue @@ -1,132 +1,148 @@ - - + + \ No newline at end of file diff --git a/src/views/modules/wx/wx-menu.vue b/src/views/modules/wx/wx-menu.vue index cc7d8dd8..2d3a00bd 100644 --- a/src/views/modules/wx/wx-menu.vue +++ b/src/views/modules/wx/wx-menu.vue @@ -6,37 +6,54 @@
公众号菜单
-
+
+
发布 - 清空 + 清空 + +
@@ -56,6 +73,7 @@ export default { } }, mounted() { + // 获取当前微信菜单配置 this.getWxMenu(); }, methods: { @@ -88,7 +106,7 @@ export default { this.selectedSubMenuIndex = i2 this.selectedButton = this.menu.buttons[i].subButtons[i2] }, - //添加菜单 + // 添加菜单项(主菜单或子菜单) addMenu(level,i) { if (level == 1 && this.menu.buttons.length < 3) { this.menu.buttons.push({ @@ -108,7 +126,7 @@ export default { this.selectSubMenu(i,this.menu.buttons[i].subButtons.length - 1) } }, - //删除菜单 + // 删除选中的菜单项(主菜单或子菜单) delMenu() { if (this.selectedMenuLevel == 1 && confirm('删除后菜单下设置的内容将被删除')) { this.menu.buttons.splice(this.selectedMenuIndex, 1); @@ -118,12 +136,13 @@ export default { this.unSelectMenu() } }, - unSelectMenu(){//不选中任何菜单 + unSelectMenu(){// 取消选中任何菜单项 this.selectedMenuLevel = 0 this.selectedMenuIndex = '' this.selectedSubMenuIndex = '' this.selectedButton = '' }, + // 更新微信菜单配置 updateWxMenu() { this.$http({ url: this.$http.adornUrl('/manage/wxMenu/updateMenu'), @@ -138,7 +157,7 @@ export default { }); }, - onDrop(i,i2){//拖拽移动位置 + onDrop(i,i2){// 拖拽放置菜单项(用于排序) this.onDragOverMenu=''; if(i==this.selectedMenuIndex && i2==this.selectedSubMenuIndex) //拖拽到了原位置 return diff --git a/src/views/modules/wx/wx-msg-reply.vue b/src/views/modules/wx/wx-msg-reply.vue index 7721aeb3..cd93fa38 100644 --- a/src/views/modules/wx/wx-msg-reply.vue +++ b/src/views/modules/wx/wx-msg-reply.vue @@ -1,14 +1,22 @@ @@ -17,68 +25,83 @@ export default { data() { return { + // 控制对话框显示状态 visible: false, + // 控制发送按钮状态及文本 uploading: false, + // 表单数据模型 dataForm: { - openid:'', - replyType:'text', - replyContent:'' + // 用户唯一标识 + openid: '', + // 回复类型,默认为文本 + replyType: 'text', + // 回复内容 + replyContent: '' }, + // 表单验证规则 dataRule: { + // 回复内容必填验证 replyContent: [ { required: true, message: "回复内容不能为空", trigger: "blur" } ] } } }, - components:{ - WxMsgPreview:()=>import('@/components/wx-msg-preview') + // 局部注册组件(但在此组件模板中未使用) + components: { + WxMsgPreview: () => import('@/components/wx-msg-preview') }, methods: { + // 初始化方法,接收openid并显示对话框 init(openid) { - if(!openid)throw '参数异常' - this.dataForm.openid=openid - this.visible = true + if (!openid) throw '参数异常'; // 校验openid是否存在 + this.dataForm.openid = openid; // 设置openid + this.visible = true; // 显示对话框 }, - // 表单提交 + // 表单提交方法 dataFormSubmit() { - if(this.uploading)return - this.uploading=true - this.$refs['dataForm'].validate((valid) => { - if (valid) { + if (this.uploading) return; // 如果正在上传,则直接返回 + this.uploading = true; // 设置上传状态为true + this.$refs['dataForm'].validate((valid) => { // 验证表单 + if (valid) { // 如果验证通过 + // 发送请求(注意:这里假设存在一个自定义的$http方法) this.$http({ - url: this.$http.adornUrl(`/manage/wxMsg/reply`), - method: 'post', - data: this.$http.adornData(this.dataForm) - }).then(({ data }) => { - if (data && data.code === 200) { + url: this.$http.adornUrl(`/manage/wxMsg/reply`), // 请求地址(可能经过某种处理) + method: 'post', // 请求方法 + data: this.$http.adornData(this.dataForm) // 请求数据(可能经过某种处理) + }).then(({ data }) => { // 请求成功回调 + if (data && data.code === 200) { // 如果请求成功且返回码为200 + // 显示成功消息,并关闭对话框,清空回复内容 this.$message({ message: '回复成功', type: 'success', duration: 1500, onClose: () => { - this.visible = false - + this.visible = false; } - }) - this.$emit("success",{...this.dataForm}); - this.dataForm.replyContent='' - } else { - this.$message.error(data.msg) + }); + this.$emit("success", { ...this.dataForm }); // 触发success事件,传递表单数据 + this.dataForm.replyContent = ''; // 清空回复内容 + } else { // 如果请求失败 + // 显示错误消息 + this.$message.error(data.msg); } - this.uploading=false - }) + this.uploading = false; // 无论成功或失败,都重置上传状态 + }); } - }) + }); }, + // 插入链接方法,向回复内容中添加链接文本(注意:链接地址未动态设置) addLink() { - this.dataForm.replyContent += '链接文字' + this.dataForm.replyContent += '链接文字'; } } } + \ No newline at end of file diff --git a/src/views/modules/wx/wx-msg.vue b/src/views/modules/wx/wx-msg.vue index eec873d2..f4e2fe3a 100644 --- a/src/views/modules/wx/wx-msg.vue +++ b/src/views/modules/wx/wx-msg.vue @@ -1,12 +1,16 @@ + - + + \ No newline at end of file diff --git a/src/views/modules/wx/wx-qrcode.vue b/src/views/modules/wx/wx-qrcode.vue index 38ce9fa9..46e2512d 100644 --- a/src/views/modules/wx/wx-qrcode.vue +++ b/src/views/modules/wx/wx-qrcode.vue @@ -1,67 +1,86 @@ + \ No newline at end of file diff --git a/src/views/modules/wx/wx-user-tagging.vue b/src/views/modules/wx/wx-user-tagging.vue index ff4b2664..7856db12 100644 --- a/src/views/modules/wx/wx-user-tagging.vue +++ b/src/views/modules/wx/wx-user-tagging.vue @@ -1,101 +1,120 @@ + \ No newline at end of file