diff --git a/.idea/.gitignore b/.idea/.gitignore index acd22a3..bc93133 100644 --- a/.idea/.gitignore +++ b/.idea/.gitignore @@ -2,7 +2,11 @@ /shelf/ /workspace.xml # 数据源本地存储已忽略文件 +<<<<<<< HEAD /../../../../../../:\Users\33424\Desktop\jianshenfanggl没有注释\.idea/dataSources/ +======= +/../../../../../../../:\Users\33424\Desktop\gym\jianshenfanggl\.idea/dataSources/ +>>>>>>> develop /dataSources.local.xml # 基于编辑器的 HTTP 客户端请求 /httpRequests/ diff --git a/.idea/inspectionProfiles/Project_Default.xml b/.idea/inspectionProfiles/Project_Default.xml new file mode 100644 index 0000000..03d9549 --- /dev/null +++ b/.idea/inspectionProfiles/Project_Default.xml @@ -0,0 +1,6 @@ + + + + \ No newline at end of file diff --git a/.idea/jianshenfanggl.iml b/.idea/jianshenfanggl.iml new file mode 100644 index 0000000..d6ebd48 --- /dev/null +++ b/.idea/jianshenfanggl.iml @@ -0,0 +1,9 @@ + + + + + + + + + \ No newline at end of file diff --git a/.idea/modules.xml b/.idea/modules.xml index 74ce3a4..f5aa6c4 100644 --- a/.idea/modules.xml +++ b/.idea/modules.xml @@ -2,7 +2,11 @@ +<<<<<<< HEAD +======= + +>>>>>>> develop \ No newline at end of file diff --git a/.idea/vcs.xml b/.idea/vcs.xml index a933e05..113f660 100644 --- a/.idea/vcs.xml +++ b/.idea/vcs.xml @@ -2,6 +2,9 @@ +<<<<<<< HEAD +======= +>>>>>>> develop \ No newline at end of file diff --git a/.idea/vue1.js b/.idea/vue1.js new file mode 100644 index 0000000..f5108aa --- /dev/null +++ b/.idea/vue1.js @@ -0,0 +1,2464 @@ +// Vue.js v2.6.12 版本声明 +// 版权所有 (c) 2014 - 2020 Evan You +// 基于 MIT 许可证发布 +// 立即执行函数表达式,用于将 Vue 库暴露给不同的模块系统 +// 参数 global 代表全局对象,factory 是一个函数,用于创建 Vue 实例 +(function (global, factory) { + // 判断是否为 CommonJS 模块环境 + // 如果 exports 是对象且 module 不是 undefined,则使用 module.exports 导出 factory 函数的返回值 + typeof exports === 'object' && typeof module !== 'undefined' ? module.exports = factory() : + // 判断是否为 AMD 模块环境 + // 如果 define 是函数且支持 AMD 规范,则使用 define 函数定义模块 + typeof define === 'function' && define.amd ? define(factory) : + // 既不是 CommonJS 也不是 AMD 环境,则将 factory 函数的返回值赋值给全局对象的 Vue 属性 + (global = global || self, global.Vue = factory()); + // 传入当前全局对象 this 和 factory 函数 +}(this, function () { 'use strict'; + + // 创建一个冻结的空对象,用于避免不必要的对象创建和修改 + var emptyObject = Object.freeze({}); + + // 这些辅助函数由于其明确性和函数内联,在 JS 引擎中能产生更好的虚拟机代码 + // 检查一个值是否为 undefined 或 null + function isUndef (v) { + return v === undefined || v === null + } + + // 检查一个值是否既不是 undefined 也不是 null + function isDef (v) { + return v !== undefined && v !== null + } + + // 检查一个值是否严格等于 true + function isTrue (v) { + return v === true + } + + // 检查一个值是否严格等于 false + function isFalse (v) { + return v === false + } + + // 检查值是否为原始类型 + function isPrimitive (value) { + // 检查值是否为字符串类型 + return typeof value === 'string' || + // 检查值是否为数字类型 + typeof value === 'number' || + // 忽略 Flow 类型检查,检查值是否为符号类型 + typeof value === 'symbol' || + // 检查值是否为布尔类型 + typeof value === 'boolean' + } + + // 快速检查对象 - 当我们知道值是符合 JSON 类型时,主要用于区分对象和原始值 + function isObject (obj) { + // 检查对象是否不为 null 且类型为 object + return obj !== null && typeof obj === 'object' + } + + // 获取值的原始类型字符串,例如 [object Object] + var _toString = Object.prototype.toString; + + function toRawType (value) { + // 调用 Object.prototype.toString 方法获取值的类型字符串,并截取关键部分 + return _toString.call(value).slice(8, -1) + } + + // 严格的对象类型检查。仅当为纯 JavaScript 对象时返回 true + function isPlainObject (obj) { + // 检查对象的类型字符串是否为 [object Object] + return _toString.call(obj) === '[object Object]' + } + + // 检查一个值是否为正则表达式对象 + function isRegExp (v) { + return _toString.call(v) === '[object RegExp]' + } + + // 检查 val 是否为有效的数组索引 + function isValidArrayIndex (val) { + // 将值转换为浮点数 + var n = parseFloat(String(val)); + // 检查是否为非负整数且为有限值 + return n >= 0 && Math.floor(n) === n && isFinite(val) + } + + // 检查一个值是否为 Promise 对象 + function isPromise (val) { + // 检查值是否已定义 + return isDef(val) && + // 检查值是否有 then 方法 + typeof val.then === 'function' && + // 检查值是否有 catch 方法 + typeof val.catch === 'function' + } + + // 将值转换为实际渲染的字符串 + function toString (val) { + // 如果值为 null 或 undefined,返回空字符串 + return val == null ? '' : + // 检查值是否为数组或纯对象且 toString 方法为默认方法 + Array.isArray(val) || (isPlainObject(val) && val.toString === _toString) ? + // 如果是,使用 JSON.stringify 转换为格式化的字符串 + JSON.stringify(val, null, 2) : + // 否则,直接转换为字符串 + String(val) + } + + // 将输入值转换为数字以便持久化。如果转换失败,返回原始字符串 + function toNumber (val) { + // 将值转换为浮点数 + var n = parseFloat(val); + // 检查是否为 NaN,如果是则返回原始值,否则返回转换后的数字 + return isNaN(n) ? val : n + } + + // 创建一个映射并返回一个函数,用于检查键是否在该映射中 + function makeMap ( + str, + expectsLowerCase + ) { + // 创建一个空对象作为映射 + var map = Object.create(null); + // 将字符串按逗号分割成数组 + var list = str.split(','); + // 遍历数组,将每个元素作为键添加到映射中 + for (var i = 0; i < list.length; i++) { + map[list[i]] = true; + } + // 如果期望小写,则返回一个函数,将输入转换为小写后检查是否在映射中 + return expectsLowerCase ? function (val) { return map[val.toLowerCase()]; } : + // 否则,直接检查输入是否在映射中 + function (val) { return map[val]; } + } + + // 检查标签是否为内置标签 + var isBuiltInTag = makeMap('slot,component', true); + + // 检查属性是否为保留属性 + var isReservedAttribute = makeMap('key,ref,slot,slot-scope,is'); + + // 从数组中移除一个元素 + function remove (arr, item) { + // 检查数组长度是否大于 0 + if (arr.length) { + // 查找元素在数组中的索引 + var index = arr.indexOf(item); + // 如果索引大于 -1,表示元素存在于数组中 + if (index > -1) { + // 使用 splice 方法移除元素并返回被移除的元素数组 + return arr.splice(index, 1) + } + } + } + + // 检查对象是否具有某个属性 + var hasOwnProperty = Object.prototype.hasOwnProperty; + function hasOwn (obj, key) { + // 使用 hasOwnProperty 方法检查对象是否具有指定的键 + return hasOwnProperty.call(obj, key) + } + + // 创建一个纯函数的缓存版本 + function cached (fn) { + // 创建一个空对象作为缓存 + var cache = Object.create(null); + return function cachedFn (str) { + // 检查缓存中是否已有该键的结果 + var hit = cache[str]; + // 如果有,返回缓存结果;否则,调用原函数计算结果并缓存 + return hit || (cache[str] = fn(str)) + } + } + + // 将连字符分隔的字符串转换为驼峰式字符串 + var camelizeRE = /-(\w)/g; + var camelize = cached(function (str) { + // 使用正则表达式替换连字符后的字符为大写 + return str.replace(camelizeRE, function (_, c) { return c ? c.toUpperCase() : ''; }) + }); + + // 首字母大写字符串 + var capitalize = cached(function (str) { + // 将字符串的首字母转换为大写并拼接剩余部分 + return str.charAt(0).toUpperCase() + str.slice(1) + }); + + // 将驼峰式字符串转换为连字符分隔的字符串 + var hyphenateRE = /\B([A-Z])/g; + var hyphenate = cached(function (str) { + // 使用正则表达式替换大写字母前插入连字符并转换为小写 + return str.replace(hyphenateRE, '-$1').toLowerCase() + }); + + // 为不支持 bind 方法的环境提供简单的 bind 方法填充 + // 例如 PhantomJS 1.x。从技术上讲,由于现在大多数浏览器中本地 bind 方法性能已经足够好,我们不再需要这个方法 + // 但移除它会导致在 PhantomJS 1.x 中运行的代码中断,因此为了向后兼容必须保留 + function polyfillBind (fn, ctx) { + function boundFn (a) { + // 获取参数长度 + var l = arguments.length; + return l ? + // 如果有参数 + l > 1 ? + // 如果参数数量大于 1,使用 apply 方法调用原函数 + fn.apply(ctx, arguments) : + // 如果参数数量为 1,使用 call 方法调用原函数 + fn.call(ctx, a) : + // 如果没有参数,使用 call 方法调用原函数 + fn.call(ctx) + } + + // 绑定函数的长度设置为原函数的长度 + boundFn._length = fn.length; + return boundFn + } + + // 使用原生的 bind 方法 + function nativeBind (fn, ctx) { + return fn.bind(ctx) + } + + // 如果 Function.prototype.bind 存在,则使用原生 bind 方法,否则使用填充方法 + var bind = Function.prototype.bind ? nativeBind : polyfillBind; + + // 将类似数组的对象转换为真正的数组 + function toArray (list, start) { + // 如果 start 未提供,默认为 0 + start = start || 0; + // 计算新数组的长度 + var i = list.length - start; + // 创建一个指定长度的新数组 + var ret = new Array(i); + // 从后往前遍历类似数组的对象,将元素复制到新数组中 + while (i--) { + ret[i] = list[i + start]; + } + return ret + } + + // 将属性混合到目标对象中 + function extend (to, _from) { + // 遍历源对象的所有属性 + for (var key in _from) { + // 将源对象的属性复制到目标对象中 + to[key] = _from[key]; + } + return to + } + + // 将对象数组合并为一个对象 + function toObject (arr) { + // 创建一个空对象作为结果 + var res = {}; + // 遍历数组中的每个对象 + for (var i = 0; i < arr.length; i++) { + // 如果对象存在 + if (arr[i]) { + // 将对象的属性合并到结果对象中 + extend(res, arr[i]); + } + } + return res + } + + // 不执行任何操作。 + // 为了让 Flow 满意而保留参数,同时避免留下无用的转译代码 + // (https://flow.org/blog/2017/05/07/Strict-Function-Call-Arity/) + function noop (a, b, c) {} + + // 始终返回 false + var no = function (a, b, c) { return false; }; + + // 返回相同的值 + var identity = function (_) { return _; }; + + // 从编译器模块生成包含静态键的字符串 + function genStaticKeys (modules) { + // 使用 reduce 方法将所有模块的静态键合并为一个数组 + return modules.reduce(function (keys, m) { + return keys.concat(m.staticKeys || []) + }, []).join(',') + } + + // 检查两个值是否宽松相等 - 即,如果它们是纯对象,它们的结构是否相同? + function looseEqual (a, b) { + // 如果两个值严格相等,直接返回 true + if (a === b) { return true } + // 检查 a 是否为对象 + var isObjectA = isObject(a); + // 检查 b 是否为对象 + var isObjectB = isObject(b); + if (isObjectA && isObjectB) { + try { + // 检查 a 是否为数组 + var isArrayA = Array.isArray(a); + // 检查 b 是否为数组 + var isArrayB = Array.isArray(b); + if (isArrayA && isArrayB) { + // 如果都是数组,检查长度是否相等且每个元素是否宽松相等 + return a.length === b.length && a.every(function (e, i) { + return looseEqual(e, b[i]) + }) + } else if (a instanceof Date && b instanceof Date) { + // 如果都是日期对象,检查时间戳是否相等 + return a.getTime() === b.getTime() + } else if (!isArrayA && !isArrayB) { + // 如果都不是数组,检查键的数量是否相等且每个键对应的值是否宽松相等 + var keysA = Object.keys(a); + var keysB = Object.keys(b); + return keysA.length === keysB.length && keysA.every(function (key) { + return looseEqual(a[key], b[key]) + }) + } else { + return false + } + } catch (e) { + return false + } + } else if (!isObjectA && !isObjectB) { + // 如果都不是对象,将它们转换为字符串并比较 + return String(a) === String(b) + } else { + return false + } + } + + // 返回在数组中可以找到宽松相等值的第一个索引(如果值是纯对象,数组必须包含相同结构的对象),如果不存在则返回 -1 + function looseIndexOf (arr, val) { + // 遍历数组 + for (var i = 0; i < arr.length; i++) { + // 检查当前元素是否与目标值宽松相等 + if (looseEqual(arr[i], val)) { return i } + } + return -1 + } + + // 确保函数只被调用一次 + function once (fn) { + // 标记函数是否已被调用 + var called = false; + return function () { + // 如果函数未被调用 + if (!called) { + // 标记为已调用 + called = true; + // 调用原函数并传递参数 + fn.apply(this, arguments); + } + } + } + + // 服务器渲染标记属性 + var SSR_ATTR = 'data-server-rendered'; + + // 资产类型数组,包括组件、指令和过滤器 + var ASSET_TYPES = [ + 'component', + 'directive', + 'filter' + ]; + + // 生命周期钩子数组 + var LIFECYCLE_HOOKS = [ + 'beforeCreate', + 'created', + 'beforeMount', + 'mounted', + 'beforeUpdate', + 'updated', + 'beforeDestroy', + 'destroyed', + 'activated', + 'deactivated', + 'errorCaptured', + 'serverPrefetch' + ]; + + // Vue 配置对象 + var config = ({ + // 选项合并策略(在 core/util/options 中使用) + // 忽略 Flow 类型检查 + optionMergeStrategies: Object.create(null), + // 是否抑制警告 + silent: false, + // 在启动时显示生产模式提示消息? + productionTip: "development" !== 'production', + // 是否启用开发者工具 + devtools: "development" !== 'production', + // 是否记录性能 + performance: false, + // 监听器错误的错误处理函数 + errorHandler: null, + // 监听器警告的警告处理函数 + warnHandler: null, + // 忽略某些自定义元素 + ignoredElements: [], + // v-on 的自定义用户键别名 + // 忽略 Flow 类型检查 + keyCodes: Object.create(null), + // 检查标签是否为保留标签,以便不能将其注册为组件。这依赖于平台,可能会被覆盖 + isReservedTag: no, + // 检查属性是否为保留属性,以便不能将其用作组件的 prop。这依赖于平台,可能会被覆盖 + isReservedAttr: no, + // 检查标签是否为未知元素。依赖于平台 + isUnknownElement: no, + // 获取元素的命名空间 + getTagNamespace: noop, + // 解析特定平台的真实标签名 + parsePlatformTagName: identity, + // 检查属性是否必须使用属性绑定,例如 value。依赖于平台 + mustUseProp: no, + // 异步执行更新。供 Vue Test Utils 使用。如果设置为 false,性能将显著降低 + async: true, + // 出于遗留原因暴露 + _lifecycleHooks: LIFECYCLE_HOOKS + }); + + // 用于解析 HTML 标签、组件名称和属性路径的 Unicode 字母。 + // 使用 https://www.w3.org/TR/html53/semantics-scripting.html#potentialcustomelementname + // 跳过 \u10000 - \uEFFFF 以避免 PhantomJS 冻结 + var unicodeRegExp = /a-zA-Z\u00B7\u00C0-\u00D6\u00D8-\u00F6\u00F8-\u037D\u037F-\u1FFF\u200C-\u200D\u203F-\u2040\u2070-\u218F\u2C00-\u2FEF\u3001-\uD7FF\uF900-\uFDCF\uFDF0-\uFFFD/; + + // 检查字符串是否以 $ 或 _ 开头 + function isReserved (str) { + // 获取字符串的第一个字符的 Unicode 编码 + var c = (str + '').charCodeAt(0); + // 检查编码是否为 $ 或 _ 的编码 + return c === 0x24 || c === 0x5F + } + + // 定义一个属性 + function def (obj, key, val, enumerable) { + // 使用 Object.defineProperty 方法定义属性 + Object.defineProperty(obj, key, { + // 属性的值 + value: val, + // 是否可枚举 + enumerable: !!enumerable, + // 是否可写 + writable: true, + // 是否可配置 + configurable: true + }); + } + + // 解析简单路径 + var bailRE = new RegExp(("[^" + (unicodeRegExp.source) + ".$_\\d]")); + function parsePath (path) { + // 检查路径是否包含非法字符 + if (bailRE.test(path)) { + return + } + // 将路径按点分割成段 + var segments = path.split('.'); + return function (obj) { + // 遍历路径段 + for (var i = 0; i < segments.length; i++) { + // 如果对象为空,返回 + if (!obj) { return } + // 获取对象的下一级属性 + obj = obj[segments[i]]; + } + return obj + } + } + // 能否使用 __proto__ 属性? + var hasProto = '__proto__' in {}; + +// 浏览器环境嗅探 +// 判断是否处于浏览器环境 + var inBrowser = typeof window !== 'undefined'; +// 判断是否处于 Weex 环境 + var inWeex = typeof WXEnvironment !== 'undefined' && !!WXEnvironment.platform; +// 获取 Weex 平台名称并转换为小写 + var weexPlatform = inWeex && WXEnvironment.platform.toLowerCase(); +// 获取浏览器的用户代理字符串并转换为小写 + var UA = inBrowser && window.navigator.userAgent.toLowerCase(); +// 判断是否为 IE 浏览器 + var isIE = UA && /msie|trident/.test(UA); +// 判断是否为 IE 9 浏览器 + var isIE9 = UA && UA.indexOf('msie 9.0') > 0; +// 判断是否为 Edge 浏览器 + var isEdge = UA && UA.indexOf('edge/') > 0; +// 判断是否为安卓设备 + var isAndroid = (UA && UA.indexOf('android') > 0) || (weexPlatform === 'android'); +// 判断是否为 iOS 设备 + var isIOS = (UA && /iphone|ipad|ipod|ios/.test(UA)) || (weexPlatform === 'ios'); +// 判断是否为 Chrome 浏览器 + var isChrome = UA && /chrome\/\d+/.test(UA) && !isEdge; +// 判断是否为 PhantomJS 环境 + var isPhantomJS = UA && /phantomjs/.test(UA); +// 判断是否为 Firefox 浏览器,并获取版本号 + var isFF = UA && UA.match(/firefox\/(\d+)/); + +// Firefox 在 Object.prototype 上有 "watch" 函数 + var nativeWatch = ({}).watch; + +// 检测浏览器是否支持 passive 选项 + var supportsPassive = false; + if (inBrowser) { + try { + // 创建一个空对象用于测试 + var opts = {}; + // 定义一个属性 "passive",当访问该属性时将 supportsPassive 设为 true + Object.defineProperty(opts, 'passive', ({ + get: function get () { + supportsPassive = true; + } + })); + // 尝试添加一个测试事件监听器,触发对 "passive" 属性的访问 + window.addEventListener('test-passive', null, opts); + } catch (e) {} + } + +// 这个变量需要延迟求值,因为 vue 可能在 vue-server-renderer 设置 VUE_ENV 之前被引入 + var _isServer; +// 检查是否处于服务器渲染环境 + var isServerRendering = function () { + if (_isServer === undefined) { + if (!inBrowser && !inWeex && typeof global !== 'undefined') { + // 检测是否存在 vue-server-renderer 并避免 Webpack 对 process 进行填充 + _isServer = global['process'] && global['process'].env.VUE_ENV === 'server'; + } else { + _isServer = false; + } + } + return _isServer + }; + +// 检测开发者工具是否可用 + var devtools = inBrowser && window.__VUE_DEVTOOLS_GLOBAL_HOOK__; + +// 判断一个构造函数是否为原生函数 + function isNative (Ctor) { + return typeof Ctor === 'function' && /native code/.test(Ctor.toString()) + } + +// 检测是否支持 Symbol 和 Reflect.ownKeys + var hasSymbol = + typeof Symbol !== 'undefined' && isNative(Symbol) && + typeof Reflect !== 'undefined' && isNative(Reflect.ownKeys); + +// 定义一个 Set 类型变量 + var _Set; +// 如果原生支持 Set,则使用原生 Set + if (typeof Set !== 'undefined' && isNative(Set)) { + _Set = Set; + } else { + // 否则使用自定义的 Set 填充 + _Set = (function () { + function Set () { + // 创建一个空对象用于存储键 + this.set = Object.create(null); + } + // 检查集合中是否存在某个键 + Set.prototype.has = function has (key) { + return this.set[key] === true + }; + // 向集合中添加一个键 + Set.prototype.add = function add (key) { + this.set[key] = true; + }; + // 清空集合 + Set.prototype.clear = function clear () { + this.set = Object.create(null); + }; + + return Set; + }()); + } + +// 定义警告函数,初始为空函数 + var warn = noop; +// 定义提示函数,初始为空函数 + var tip = noop; +// 定义生成组件调用栈的函数,初始为空函数 + var generateComponentTrace = (noop); +// 定义格式化组件名称的函数,初始为空函数 + var formatComponentName = (noop); + + { + // 检查是否存在 console 对象 + var hasConsole = typeof console !== 'undefined'; + // 用于匹配连字符或下划线后的字符 + var classifyRE = /(?:^|[-_])(\w)/g; + // 将字符串转换为驼峰式命名 + var classify = function (str) { return str + .replace(classifyRE, function (c) { return c.toUpperCase(); }) + .replace(/[-_]/g, ''); }; + + // 定义警告函数 + warn = function (msg, vm) { + // 获取组件调用栈 + var trace = vm ? generateComponentTrace(vm) : ''; + + if (config.warnHandler) { + // 如果配置了警告处理函数,则调用该函数 + config.warnHandler.call(null, msg, vm, trace); + } else if (hasConsole && (!config.silent)) { + // 否则在控制台输出警告信息 + console.error(("[Vue warn]: " + msg + trace)); + } + }; + + // 定义提示函数 + tip = function (msg, vm) { + if (hasConsole && (!config.silent)) { + // 在控制台输出提示信息 + console.warn("[Vue tip]: " + msg + ( + vm ? generateComponentTrace(vm) : '' + )); + } + }; + + // 格式化组件名称 + formatComponentName = function (vm, includeFile) { + // 检查当前组件实例是否为根组件实例 + if (vm.$root === vm) { + // 如果是根组件实例,返回 '' 字符串 + return '' + } + // 根据传入的 vm 类型和属性获取组件的选项对象 + var options = typeof vm === 'function' && vm.cid != null + // 如果 vm 是函数且有 cid 属性,说明是组件构造函数,取其 options 属性 + ? vm.options + // 如果 vm 是 Vue 实例,取其 $options 属性,如果没有则取构造函数的 options 属性 + : vm._isVue + ? vm.$options || vm.constructor.options + // 否则直接将 vm 作为选项对象 + : vm; + // 从选项对象中获取组件的名称,如果没有则取 _componentTag 属性 + var name = options.name || options._componentTag; + // 从选项对象中获取组件对应的文件路径 + var file = options.__file; + // 如果组件名称为空且存在文件路径 + if (!name && file) { + // 使用正则表达式匹配文件路径中的文件名部分 + var match = file.match(/([^/\\]+)\.vue$/); + // 如果匹配成功,将匹配到的文件名赋值给 name + name = match && match[1]; + } + + // 生成格式化后的组件名称字符串 + return ( + // 如果有组件名称,将其转换为驼峰命名并包裹在 < > 中,否则返回 '' + (name ? ("<" + (classify(name)) + ">") : "") + + // 如果存在文件路径且 includeFile 不为 false,添加文件路径信息 + (file && includeFile !== false ? (" at " + file) : '') + ) + }; + +// 重复字符串指定次数 + var repeat = function (str, n) { + // 初始化结果字符串为空 + var res = ''; + // 开始循环,直到 n 变为 0 + while (n) { + // 如果 n 是奇数,将当前字符串 str 追加到结果字符串 res 中 + if (n % 2 === 1) { res += str; } + // 如果 n 大于 1,将字符串 str 自身拼接,相当于将字符串长度翻倍 + if (n > 1) { str += str; } + // 将 n 右移一位,相当于将 n 除以 2 并向下取整 + n >>= 1; + } + // 返回重复后的字符串 + return res + }; + // 生成组件调用栈信息 + // 重新定义 generateComponentTrace 函数,用于生成组件调用链的追踪信息 + generateComponentTrace = function (vm) { + // 检查传入的 vm 是否为 Vue 实例,并且是否存在父组件 + if (vm._isVue && vm.$parent) { + // 初始化一个数组 tree,用于存储组件调用链中的每个组件实例 + var tree = []; + // 初始化一个变量 currentRecursiveSequence,用于记录当前组件的递归调用次数 + var currentRecursiveSequence = 0; + // 开始循环遍历组件的父组件链,直到没有父组件为止 + while (vm) { + // 检查 tree 数组中是否已经有组件实例 + if (tree.length > 0) { + // 获取 tree 数组中的最后一个组件实例 + var last = tree[tree.length - 1]; + // 检查最后一个组件实例的构造函数是否和当前组件实例的构造函数相同 + if (last.constructor === vm.constructor) { + // 如果相同,说明是递归调用,递归次数加 1 + currentRecursiveSequence++; + // 将 vm 指向其父组件,继续循环 + vm = vm.$parent; + // 跳过本次循环的后续代码,继续下一次循环 + continue + } + // 如果递归次数大于 0,说明之前有递归调用 + else if (currentRecursiveSequence > 0) { + // 将 tree 数组的最后一个元素替换为一个数组,包含最后一个组件实例和递归次数 + tree[tree.length - 1] = [last, currentRecursiveSequence]; + // 重置递归次数为 0 + currentRecursiveSequence = 0; + } + } + // 将当前组件实例添加到 tree 数组中 + tree.push(vm); + // 将 vm 指向其父组件,继续循环 + vm = vm.$parent; + } + // 生成组件调用链的追踪信息字符串 + return '\n\nfound in\n\n' + tree + // 对 tree 数组中的每个元素进行映射处理 + .map(function (vm, i) { + // 根据索引 i 判断是否为第一个元素 + return ("" + (i === 0 ? '---> ' : repeat(' ', 5 + i * 2)) + + // 检查当前元素是否为数组 + (Array.isArray(vm) + // 如果是数组,说明有递归调用,格式化输出组件名和递归次数 + ? ((formatComponentName(vm[0])) + "... (" + (vm[1]) + " recursive calls)") + // 如果不是数组,直接格式化输出组件名 + : formatComponentName(vm))); + }) + // 将映射后的数组元素用换行符连接成一个字符串 + .join('\n') + } + // 如果传入的 vm 不是 Vue 实例或者没有父组件 + else { + // 直接生成包含组件名的追踪信息字符串 + return ("\n\n(found in " + (formatComponentName(vm)) + ")") + } + }; + +// 定义唯一标识符 + var uid = 0; + +// Dep 类,用于实现依赖收集和发布更新 + var Dep = function Dep () { + // 为每个 Dep 实例分配一个唯一的 ID + this.id = uid++; + // 存储订阅者的数组 + this.subs = []; + }; + +// 向订阅者列表中添加一个订阅者 + Dep.prototype.addSub = function addSub (sub) { + this.subs.push(sub); + }; + +// 从订阅者列表中移除一个订阅者 + Dep.prototype.removeSub = function removeSub (sub) { + remove(this.subs, sub); + }; + +// 触发依赖收集 + Dep.prototype.depend = function depend () { + if (Dep.target) { + Dep.target.addDep(this); + } + }; + +// 通知所有订阅者更新 + Dep.prototype.notify = function notify () { + // 先复制一份订阅者列表,避免在更新过程中修改原列表 + var subs = this.subs.slice(); + if (!config.async) { + // 如果不是异步模式,对订阅者列表进行排序 + subs.sort(function (a, b) { return a.id - b.id; }); + } + for (var i = 0, l = subs.length; i < l; i++) { + // 调用每个订阅者的 update 方法 + subs[i].update(); + } + }; + +// 当前正在计算的目标观察者 + Dep.target = null; +// 存储目标观察者的栈 + var targetStack = []; + +// 将目标观察者压入栈中,并设置为当前目标 + function pushTarget (target) { + targetStack.push(target); + Dep.target = target; + } + +// 从栈中弹出目标观察者,并更新当前目标 + function popTarget () { + targetStack.pop(); + Dep.target = targetStack[targetStack.length - 1]; + } + +// VNode 类,用于表示虚拟 DOM 节点 + // 定义 VNode 构造函数,用于创建虚拟 DOM 节点对象 + var VNode = function VNode ( + // 节点的标签名,例如 'div'、'span' 等 + tag, + // 节点的数据对象,包含节点的属性、事件等信息 + data, + // 节点的子节点数组 + children, + // 节点的文本内容 + text, + // 与虚拟节点对应的真实 DOM 元素 + elm, + // 节点所在的上下文,通常是 Vue 实例 + context, + // 组件的选项对象,包含组件的配置信息 + componentOptions, + // 异步组件的工厂函数 + asyncFactory + ) { + // 将传入的标签名赋值给实例的 tag 属性 + this.tag = tag; + // 将传入的数据对象赋值给实例的 data 属性 + this.data = data; + // 将传入的子节点数组赋值给实例的 children 属性 + this.children = children; + // 将传入的文本内容赋值给实例的 text 属性 + this.text = text; + // 将传入的真实 DOM 元素赋值给实例的 elm 属性 + this.elm = elm; + // 命名空间,初始化为 undefined + this.ns = undefined; + // 将传入的上下文赋值给实例的 context 属性 + this.context = context; + // 函数式组件的上下文,初始化为 undefined + this.fnContext = undefined; + // 函数式组件的选项,初始化为 undefined + this.fnOptions = undefined; + // 函数式组件的作用域 ID,初始化为 undefined + this.fnScopeId = undefined; + // 如果 data 存在且包含 key 属性,则将其赋值给实例的 key 属性,否则为 undefined + this.key = data && data.key; + // 将传入的组件选项对象赋值给实例的 componentOptions 属性 + this.componentOptions = componentOptions; + // 组件实例,初始化为 undefined + this.componentInstance = undefined; + // 父节点,初始化为 undefined + this.parent = undefined; + // 标记节点是否为原始的、未处理的节点,初始化为 false + this.raw = false; + // 标记节点是否为静态节点,初始化为 false + this.isStatic = false; + // 标记节点是否是根插入节点,初始化为 true + this.isRootInsert = true; + // 标记节点是否为注释节点,初始化为 false + this.isComment = false; + // 标记节点是否为克隆节点,初始化为 false + this.isCloned = false; + // 标记节点是否只渲染一次,初始化为 false + this.isOnce = false; + // 将传入的异步组件工厂函数赋值给实例的 asyncFactory 属性 + this.asyncFactory = asyncFactory; + // 异步组件的元数据,初始化为 undefined + this.asyncMeta = undefined; + // 标记节点是否为异步占位符节点,初始化为 false + this.isAsyncPlaceholder = false; + }; + +// 定义 VNode 原型上的访问器属性 + var prototypeAccessors = { child: { configurable: true } }; + +// 废弃:为了向后兼容,将 child 作为 componentInstance 的别名 + prototypeAccessors.child.get = function () { + return this.componentInstance + }; + +// 将访问器属性定义到 VNode 原型上 + Object.defineProperties( VNode.prototype, prototypeAccessors ); + +// 创建一个空的虚拟节点 + var createEmptyVNode = function (text) { + if ( text === void 0 ) text = ''; + + var node = new VNode(); + node.text = text; + node.isComment = true; + return node + }; + +// 创建一个文本虚拟节点 + function createTextVNode (val) { + return new VNode(undefined, undefined, undefined, String(val)) + } + +// 浅克隆一个虚拟节点 + // 定义一个函数 cloneVNode,用于克隆一个虚拟节点(VNode) + function cloneVNode (vnode) { + // 创建一个新的 VNode 实例,将原 VNode 的部分属性传递给新实例 + var cloned = new VNode( + // 克隆原 VNode 的标签名 + vnode.tag, + // 克隆原 VNode 的数据对象 + vnode.data, + // 克隆原 VNode 的子节点数组,如果存在子节点,则创建一个新的数组副本 + vnode.children && vnode.children.slice(), + // 克隆原 VNode 的文本内容 + vnode.text, + // 克隆原 VNode 对应的真实 DOM 元素 + vnode.elm, + // 克隆原 VNode 的上下文 + vnode.context, + // 克隆原 VNode 的组件选项对象 + vnode.componentOptions, + // 克隆原 VNode 的异步组件工厂函数 + vnode.asyncFactory + ); + // 将原 VNode 的命名空间赋值给克隆节点 + cloned.ns = vnode.ns; + // 将原 VNode 是否为静态节点的标记赋值给克隆节点 + cloned.isStatic = vnode.isStatic; + // 将原 VNode 的 key 值赋值给克隆节点 + cloned.key = vnode.key; + // 将原 VNode 是否为注释节点的标记赋值给克隆节点 + cloned.isComment = vnode.isComment; + // 将原 VNode 的函数式组件上下文赋值给克隆节点 + cloned.fnContext = vnode.fnContext; + // 将原 VNode 的函数式组件选项赋值给克隆节点 + cloned.fnOptions = vnode.fnOptions; + // 将原 VNode 的函数式组件作用域 ID 赋值给克隆节点 + cloned.fnScopeId = vnode.fnScopeId; + // 将原 VNode 的异步组件元数据赋值给克隆节点 + cloned.asyncMeta = vnode.asyncMeta; + // 标记克隆节点为已克隆状态 + cloned.isCloned = true; + // 返回克隆后的 VNode 节点 + return cloned + } + +// 获取数组的原型 + var arrayProto = Array.prototype; +// 创建一个继承自数组原型的对象 + var arrayMethods = Object.create(arrayProto); + +// 定义需要拦截的数组方法 + var methodsToPatch = [ + 'push', + 'pop', + 'shift', + 'unshift', + 'splice', + 'sort', + 'reverse' + ]; + +// 拦截数组的变异方法并触发更新 + methodsToPatch.forEach(function (method) { + // 缓存原始方法 + var original = arrayProto[method]; + // 定义变异方法 + // 调用 def 函数,为 arrayMethods 对象定义一个新的方法,该方法名由 method 变量指定 +// 第三个参数是一个名为 mutator 的函数,它会覆盖原数组方法的行为 + def(arrayMethods, method, function mutator () { + // 初始化一个空数组 args,用于存储传递给当前函数的参数 + var args = [], len = arguments.length; + // 使用 while 循环将传递给函数的参数逆序存储到 args 数组中 + while ( len-- ) args[ len ] = arguments[ len ]; + + // 调用原始的数组方法(original 是之前缓存的数组原型上的原始方法) + // 使用 apply 方法将当前数组实例作为 this 上下文,并传递参数 args + var result = original.apply(this, args); + // 获取当前数组实例的 Observer 实例 + // __ob__ 是在对象被观测时添加的一个属性,指向该对象的 Observer 实例 + var ob = this.__ob__; + // 定义一个变量 inserted,用于存储新插入到数组中的元素 + var inserted; + // 根据不同的数组方法进行不同的处理 + switch (method) { + // 如果是 push 或 unshift 方法 + case 'push': + case 'unshift': + // 将传递给 push 或 unshift 方法的所有参数赋值给 inserted 变量 + // 因为 push 和 unshift 方法会将参数添加到数组中,这些参数就是新插入的元素 + inserted = args; + // 跳出 switch 语句 + break + // 如果是 splice 方法 + case 'splice': + // splice 方法的参数格式为 (start, deleteCount, item1, item2, ...) + // 从索引 2 开始截取参数,这些参数就是 splice 方法插入到数组中的新元素 + inserted = args.slice(2); + // 跳出 switch 语句 + break + } + if (inserted) { ob.observeArray(inserted); } + // 通知依赖更新 + ob.dep.notify(); + return result + }); + }); + +// 获取拦截后的数组方法的属性名 + var arrayKeys = Object.getOwnPropertyNames(arrayMethods); + +// 是否应该进行观测 + var shouldObserve = true; + +// 切换观测状态 + function toggleObserving (value) { + shouldObserve = value; + } + +// Observer 类,用于将对象转换为可观测对象 + var booleanIndex = getTypeIndex(Boolean, prop.type); + // 如果属性类型包含布尔类型 + if (booleanIndex > -1) { + // 如果属性不存在且没有默认值,则将值设为false + if (absent &&!hasOwn(prop, 'default')) { + value = false; + } else if (value === '' || value === hyphenate(key)) { + // 只有当布尔类型的优先级高于字符串类型时,才将空字符串或同名的值转换为布尔类型 + var Observer = function Observer (value) { + this.value = value; + this.dep = new Dep(); + this.vmCount = 0; + // 在对象上定义一个不可枚举的属性 __ob__,指向当前 Observer 实例 + def(value, '__ob__', this); + if (Array.isArray(value)) { + if (hasProto) { + // 使用 __proto__ 进行原型增强 + protoAugment(value, arrayMethods); + } else { + // 复制属性进行增强 + copyAugment(value, arrayMethods, arrayKeys); + } + // 对数组元素进行观测 + this.observeArray(value); + } else { + // 遍历对象属性并转换为响应式 + this.walk(value); + } + }; + +// 遍历对象的所有属性,将其转换为 getter/setter + Observer.prototype.walk = function walk (obj) { + var keys = Object.keys(obj); + for (var i = 0; i < keys.length; i++) { + defineReactive$$1(obj, keys[i]); + } + }; + +// 对数组中的每个元素进行观测 + Observer.prototype.observeArray = function observeArray (items) { + for (var i = 0, l = items.length; i < l; i++) { + observe(items[i]); + } + }; + +// 使用 __proto__ 增强目标对象或数组 + function protoAugment (target, src) { + target.__proto__ = src; + } + +// 通过定义隐藏属性增强目标对象或数组 + function copyAugment (target, src, keys) { + for (var i = 0, l = keys.length; i < l; i++) { + var key = keys[i]; + def(target, key, src[key]); + } + } + +// 尝试为一个值创建观察者实例 + function observe (value, asRootData) { + // 检查传入的值是否不是对象,或者是否为 VNode 实例 + // 如果满足条件,则直接返回,不进行观察 + if (!isObject(value) || value instanceof VNode) { + return + } + // 声明一个变量 ob,用于存储观察者实例 + var ob; + // 检查传入的值是否已经有 __ob__ 属性,并且该属性对应的是 Observer 实例 + if (hasOwn(value, '__ob__') && value.__ob__ instanceof Observer) { + // 如果已经有观察者实例,则直接将其赋值给 ob 变量 + ob = value.__ob__; + } + // 如果值还没有被观察,并且满足以下条件 + else if ( + // 全局变量 shouldObserve 为 true,表示应该进行观察 + shouldObserve && + // 当前不是服务器渲染环境 + !isServerRendering() && + // 传入的值是数组或者是普通对象 + (Array.isArray(value) || isPlainObject(value)) && + // 传入的值是可扩展的,即可以添加新的属性 + Object.isExtensible(value) && + // 传入的值不是 Vue 实例 + !value._isVue + ) { + // 创建一个新的 Observer 实例,并将其赋值给 ob 变量 + ob = new Observer(value); + } + // 如果 asRootData 为 true,并且已经成功创建了观察者实例 + if (asRootData && ob) { + // 增加观察者实例的 vmCount 属性,该属性用于记录该对象作为根数据的次数 + ob.vmCount++; + } + // 返回观察者实例,如果没有创建则返回 undefined + return ob + } + // Define a reactive property on an Object. +// 在一个对象上定义一个响应式属性 + function defineReactive$$1 ( + // 要定义响应式属性的对象 + obj, + // 属性名 + key, + // 属性的初始值 + val, + // 自定义的 setter 函数 + customSetter, + // 是否进行浅观察 + shallow + ) { + // 创建一个 Dep 实例,用于依赖收集和派发更新 + var dep = new Dep(); + + // 获取对象上该属性的描述符 + var property = Object.getOwnPropertyDescriptor(obj, key); + // 如果属性存在且不可配置,则直接返回 + if (property && property.configurable === false) { + return + } + + // cater for pre-defined getter/setters + // 处理预定义的 getter/setter + // 获取属性的 getter 函数 + var getter = property && property.get; + // 获取属性的 setter 函数 + var setter = property && property.set; + // 如果没有 getter 或者有 setter,并且只传入了两个参数,则获取对象上该属性的值 + if ((!getter || setter) && arguments.length === 2) { + val = obj[key]; + } + + // 如果不是浅观察,则尝试为属性值创建观察者实例 + var childOb = !shallow && observe(val); + // 使用 Object.defineProperty 定义属性的 getter 和 setter + Object.defineProperty(obj, key, { + // 属性可枚举 + enumerable: true, + // 属性可配置 + configurable: true, + // 定义 getter 函数 + get: function reactiveGetter () { + // 如果有预定义的 getter,则调用该 getter 获取值,否则使用传入的初始值 + var value = getter ? getter.call(obj) : val; + // 如果存在 Dep.target(即有正在计算的依赖) + if (Dep.target) { + // 收集依赖 + dep.depend(); + // 如果存在子观察者 + if (childOb) { + // 子观察者收集依赖 + childOb.dep.depend(); + // 如果值是数组 + if (Array.isArray(value)) { + // 对数组中的每个元素收集依赖 + dependArray(value); + } + } + } + // 返回属性值 + return value + }, + // 定义 setter 函数 + set: function reactiveSetter (newVal) { + // 如果有预定义的 getter,则调用该 getter 获取旧值,否则使用传入的初始值 + var value = getter ? getter.call(obj) : val; + // 检查新值和旧值是否相等,如果相等则直接返回 + /* eslint-disable no-self-compare */ + if (newVal === value || (newVal !== newVal && value !== value)) { + return + } + /* eslint-enable no-self-compare */ + // 如果有自定义的 setter 函数,则调用该函数 + if (customSetter) { + customSetter(); + } + // 如果有 getter 但没有 setter,则直接返回 + // #7981: for accessor properties without setter + if (getter && !setter) { return } + // 如果有预定义的 setter,则调用该 setter 设置新值 + if (setter) { + setter.call(obj, newVal); + } else { + // 否则直接更新值 + val = newVal; + } + // 如果不是浅观察,则尝试为新值创建观察者实例 + childOb = !shallow && observe(newVal); + // 通知所有依赖更新 + dep.notify(); + } + }); + } + +// Set a property on an object. Adds the new property and +// triggers change notification if the property doesn't +// already exist. +// 在对象上设置一个属性。如果属性不存在,则添加该属性并触发变更通知 + function set ( + // 目标对象 + target, + // 属性名 + key, + // 属性值 + val + ) { + // 如果目标对象为 undefined、null 或者是原始类型,则发出警告 + if (isUndef(target) || isPrimitive(target) + ) { + warn(("Cannot set reactive property on undefined, null, or primitive value: " + ((target)))); + } + // 如果目标对象是数组且键是有效的数组索引 + if (Array.isArray(target) && isValidArrayIndex(key)) { + // 确保数组长度足够 + target.length = Math.max(target.length, key); + // 使用 splice 方法替换数组中的元素 + target.splice(key, 1, val); + // 返回设置的值 + return val + } + // 如果键已经存在于目标对象中且不是原型链上的属性 + if (key in target && !(key in Object.prototype)) { + // 直接设置属性值 + target[key] = val; + // 返回设置的值 + return val + } + // 获取目标对象的观察者实例 + var ob = (target).__ob__; + // 如果目标对象是 Vue 实例或者是根数据对象,则发出警告 + if (target._isVue || (ob && ob.vmCount)) { + warn( + 'Avoid adding reactive properties to a Vue instance or its root $data ' + + 'at runtime - declare it upfront in the data option.' + ); + // 返回设置的值 + return val + } + // 如果没有观察者实例 + if (!ob) { + // 直接设置属性值 + target[key] = val; + // 返回设置的值 + return val + } + // 为目标对象的属性定义响应式 + defineReactive$$1(ob.value, key, val); + // 通知依赖更新 + ob.dep.notify(); + // 返回设置的值 + return val + } + +// Delete a property and trigger change if necessary. +// 删除一个属性,并在必要时触发变更通知 + function del ( + // 目标对象 + target, + // 属性名 + key + ) { + // 如果目标对象为 undefined、null 或者是原始类型,则发出警告 + if (isUndef(target) || isPrimitive(target) + ) { + warn(("Cannot delete reactive property on undefined, null, or primitive value: " + ((target)))); + } + // 如果目标对象是数组且键是有效的数组索引 + if (Array.isArray(target) && isValidArrayIndex(key)) { + // 使用 splice 方法删除数组中的元素 + target.splice(key, 1); + return + } + // 获取目标对象的观察者实例 + var ob = (target).__ob__; + // 如果目标对象是 Vue 实例或者是根数据对象,则发出警告 + if (target._isVue || (ob && ob.vmCount)) { + warn( + 'Avoid deleting properties on a Vue instance or its root $data ' + + '- just set it to null.' + ); + return + } + // 如果目标对象没有该属性,则直接返回 + if (!hasOwn(target, key)) { + return + } + // 删除目标对象的属性 + delete target[key]; + // 如果没有观察者实例,则直接返回 + if (!ob) { + return + } + // 通知依赖更新 + ob.dep.notify(); + } + +// Collect dependencies on array elements when the array is touched, since +// we cannot intercept array element access like property getters. +// 当数组被访问时,收集数组元素的依赖,因为我们无法像拦截属性 getter 那样拦截数组元素的访问 + function dependArray ( + // 数组 + value + ) { + // 遍历数组 + for (var e = (void 0), i = 0, l = value.length; i < l; i++) { + // 获取数组元素 + e = value[i]; + // 如果元素存在且有观察者实例,则收集该元素的依赖 + e && e.__ob__ && e.__ob__.dep.depend(); + // 如果元素是数组 + if (Array.isArray(e)) { + // 递归收集数组元素的依赖 + dependArray(e); + } + } + } + +// Option overwriting strategies are functions that handle +// how to merge a parent option value and a child option +// value into the final value. +// 选项覆盖策略是处理如何将父选项值和子选项值合并为最终值的函数 + var strats = config.optionMergeStrategies; + +// Options with restrictions +// 有约束的选项 + { + // 定义 el 和 propsData 选项的合并策略 + strats.el = strats.propsData = function ( + // 父选项值 + parent, + // 子选项值 + child, + // Vue 实例 + vm, + // 选项名 + key + ) { + // 如果没有 Vue 实例,则发出警告 + if (!vm) { + warn( + "option \"" + key + "\" can only be used during instance " + + 'creation with the `new` keyword.' + ); + } + // 使用默认的合并策略 + return defaultStrat(parent, child) + }; + } + +// Helper that recursively merges two data objects together. +// 递归合并两个数据对象的辅助函数 + function mergeData ( + // 目标对象 + to, + // 源对象 + from + ) { + // 如果源对象不存在,则返回目标对象 + if (!from) { return to } + // 定义变量,用于存储键、目标对象的值和源对象的值 + var key, toVal, fromVal; + + // 获取源对象的所有键 + var keys = hasSymbol + ? Reflect.ownKeys(from) + : Object.keys(from); + + // 遍历源对象的所有键 + for (var i = 0; i < keys.length; i++) { + // 获取当前键 + key = keys[i]; + // 如果键是 __ob__,则跳过 + // in case the object is already observed... + if (key === '__ob__') { continue } + // 获取目标对象上该键的值 + toVal = to[key]; + // 获取源对象上该键的值 + fromVal = from[key]; + // 如果目标对象没有该键 + if (!hasOwn(to, key)) { + // 在目标对象上设置该键的值 + set(to, key, fromVal); + } else if ( + // 如果目标对象和源对象上该键的值不相等 + toVal !== fromVal && + // 目标对象上该键的值是纯对象 + isPlainObject(toVal) && + // 源对象上该键的值是纯对象 + isPlainObject(fromVal) + ) { + // 递归合并两个对象 + mergeData(toVal, fromVal); + } + } + // 返回合并后的目标对象 + return to + } + +// Data +// 数据合并函数 + function mergeDataOrFn ( + // 父数据值 + parentVal, + // 子数据值 + childVal, + // Vue 实例 + vm + ) { + // 如果没有 Vue 实例 + if (!vm) { + // 在 Vue.extend 合并时,两者都应该是函数 + // 如果子数据值不存在,则返回父数据值 + if (!childVal) { + return parentVal + } + // 如果父数据值不存在,则返回子数据值 + if (!parentVal) { + return childVal + } + // 当父数据值和子数据值都存在时,我们需要返回一个函数,该函数返回两个函数合并后的结果 + // 这里不需要检查父数据值是否是函数,因为它必须是函数才能通过之前的合并 + return function mergedDataFn () { + return mergeData( + // 如果子数据值是函数,则调用该函数并传入 this 上下文,否则直接使用子数据值 + typeof childVal === 'function' ? childVal.call(this, this) : childVal, + // 如果父数据值是函数,则调用该函数并传入 this 上下文,否则直接使用父数据值 + typeof parentVal === 'function' ? parentVal.call(this, this) : parentVal + ) + } + } else { + return function mergedInstanceDataFn () { + // 实例合并 + // 如果子数据值是函数,则调用该函数并传入 Vue 实例,否则直接使用子数据值 + var instanceData = typeof childVal === 'function' + ? childVal.call(vm, vm) + : childVal; + // 如果父数据值是函数,则调用该函数并传入 Vue 实例,否则直接使用父数据值 + var defaultData = typeof parentVal === 'function' + ? parentVal.call(vm, vm) + : parentVal; + // 如果实例数据存在 + if (instanceData) { + // 合并实例数据和默认数据 + return mergeData(instanceData, defaultData) + } else { + // 否则返回默认数据 + return defaultData + } + } + } + } + +// 定义 data 选项的合并策略 + strats.data = function ( + // 父选项值 + parentVal, + // 子选项值 + childVal, + // Vue 实例 + vm + ) { + // 如果没有 Vue 实例 + if (!vm) { + // 如果子选项值存在且不是函数,则发出警告 + if (childVal && typeof childVal !== 'function') { + warn( + 'The "data" option should be a function ' + + 'that returns a per-instance value in component ' + + 'definitions.', + vm + ); + + return parentVal + } + // 使用 mergeDataOrFn 函数进行合并 + return mergeDataOrFn(parentVal, childVal) + } + + // 使用 mergeDataOrFn 函数进行合并,并传入 Vue 实例 + return mergeDataOrFn(parentVal, childVal, vm) + }; + +// Hooks and props are merged as arrays. +// 钩子和 props 以数组形式合并 + function mergeHook ( + // 父选项值 + parentVal, + // 子选项值 + childVal + ) { + // 初始化合并结果 + var res = childVal + ? parentVal + // 如果父选项值存在,则将子选项值合并到父选项值中 + ? parentVal.concat(childVal) + // 如果父选项值不存在,且子选项值是数组,则直接使用子选项值 + : Array.isArray(childVal) + ? childVal + // 如果父选项值不存在,且子选项值不是数组,则将子选项值包装成数组 + : [childVal] + // 如果子选项值不存在,则使用父选项值 + : parentVal; + // 对合并结果进行去重处理 + return res + ? dedupeHooks(res) + : res + } + +// 对钩子数组进行去重处理 + function dedupeHooks ( + // 钩子数组 + hooks + ) { + // 初始化去重后的数组 + var res = []; + // 遍历钩子数组 + for (var i = 0; i < hooks.length; i++) { + // 如果去重后的数组中不包含当前钩子,则将其添加到去重后的数组中 + if (res.indexOf(hooks[i]) === -1) { + res.push(hooks[i]); + } + } + // 返回去重后的数组 + return res + } + +// 遍历生命周期钩子数组 + LIFECYCLE_HOOKS.forEach(function (hook) { + // 为每个生命周期钩子定义合并策略 + strats[hook] = mergeHook; + }); + +// Assets +// 当存在 Vue 实例(实例创建时),我们需要对构造函数选项、实例选项和父选项进行三方合并 +// 资产(组件、指令、过滤器)的合并函数 + function mergeAssets ( + // 父选项值 + parentVal, + // 子选项值 + childVal, + // Vue 实例 + vm, + // 选项名 + key + ) { + // 创建一个继承自父选项值的对象 + var res = Object.create(parentVal || null); + // 如果子选项值存在 + if (childVal) { + // 检查子选项值是否为对象类型 + assertObjectType(key, childVal, vm); + // 将子选项值合并到结果对象中 + return extend(res, childVal) + } else { + // 如果子选项值不存在,则返回结果对象 + return res + } + } + +// 遍历资产类型数组 + ASSET_TYPES.forEach(function (type) { + // 为每个资产类型定义合并策略 + strats[type + 's'] = mergeAssets; + }); + +// Watchers. +// 监听器的合并策略 +// Watchers hashes should not overwrite one +// another, so we merge them as arrays. +// 监听器哈希不应该相互覆盖,所以我们将它们合并为数组 + strats.watch = function ( + // 父选项值 + parentVal, + // 子选项值 + childVal, + // Vue 实例 + vm, + // 选项名 + key + ) { + // work around Firefox's Object.prototype.watch... + // 处理 Firefox 的 Object.prototype.watch + if (parentVal === nativeWatch) { parentVal = undefined; } + if (childVal === nativeWatch) { childVal = undefined; } + /* istanbul ignore if */ + // 如果子选项值不存在,则返回一个继承自父选项值的对象 + if (!childVal) { return Object.create(parentVal || null) } + { + // 检查子选项值是否为对象类型 + assertObjectType(key, childVal, vm); + } + // 如果父选项值不存在,则返回子选项值 + if (!parentVal) { return childVal } + // 初始化合并结果 + var ret = {}; + // 将父选项值合并到结果对象中 + extend(ret, parentVal); + // 遍历子选项值的所有键 + for (var key$1 in childVal) { + // 获取父选项值中该键的值 + var parent = ret[key$1]; + // 获取子选项值中该键的值 + var child = childVal[key$1]; + // 如果父选项值中该键的值存在且不是数组,则将其包装成数组 + if (parent && !Array.isArray(parent)) { + parent = [parent]; + } + // 将子选项值中该键的值合并到父选项值中 + ret[key$1] = parent + ? parent.concat(child) + : Array.isArray(child) ? child : [child]; + } + // 返回合并结果 + return ret + }; + +// Other object hashes. +// 其他对象哈希的合并策略 + strats.props = + strats.methods = + strats.inject = + strats.computed = function ( + // 父选项值 + parentVal, + // 子选项值 + childVal, + // Vue 实例 + vm, + // 选项名 + key + ) { + // 如果子选项值存在且不是生产环境,则检查子选项值是否为对象类型 + if (childVal && "development" !== 'production') { + assertObjectType(key, childVal, vm); + } + // 如果父选项值不存在,则返回子选项值 + if (!parentVal) { return childVal } + // 初始化合并结果 + var ret = Object.create(null); + // 将父选项值合并到结果对象中 + extend(ret, parentVal); + // 如果子选项值存在,则将其合并到结果对象中 + if (childVal) { extend(ret, childVal); } + // 返回合并结果 + return ret + }; +// provide 选项的合并策略使用 mergeDataOrFn 函数 + strats.provide = mergeDataOrFn; + +// Default strategy. +// 默认合并策略 + var defaultStrat = function ( + // 父选项值 + parentVal, + // 子选项值 + childVal + ) { + // 如果子选项值为 undefined,则返回父选项值,否则返回子选项值 + return childVal === undefined + ? parentVal + : childVal + }; + +// Validate component names +// 验证组件名称 + function checkComponents ( + // 选项对象 + options + ) { + // 遍历选项对象中的 components 属性 + for (var key in options.components) { + // 验证组件名称 + validateComponentName(key); + } + } + +// 验证组件名称是否合法 + function validateComponentName ( + // 组件名称 + name + ) { + // 如果组件名称不符合正则表达式的规则,则发出警告 + if (!new RegExp(("^[a-zA-Z][\\-\\.0-9_" + (unicodeRegExp.source) + "]*$")).test(name)) { + warn( + 'Invalid component name: "' + name + '". Component names ' + + 'should conform to valid custom element name in html5 specification.' + ); + } + // 如果组件名称是内置标签或者是保留标签,则发出警告 + if (isBuiltInTag(name) || config.isReservedTag(name)) { + warn( + 'Do not use built-in or reserved HTML elements as component ' + + 'id: ' + name + ); + } + } + +// Ensure all props option syntax are normalized into the +// Object-based format. +// 确保所有 props 选项的语法都被规范化为基于对象的格式 + function normalizeProps ( + // 选项对象 + options, + // Vue 实例 + vm + ) { + // 获取选项对象中的 props 属性 + var props = options.props; + // 如果 props 属性不存在,则直接返回 + if (!props) { return } + // 初始化规范化后的 props 对象 + var res = {}; + // 定义变量,用于存储索引、值和名称 + var i, val, name; + // 如果 props 属性是数组 + if (Array.isArray(props)) { + // 获取数组的长度 + i = props.length; + // 从后往前遍历数组 + while (i--) { + // 获取当前元素 + val = props[i]; + // 如果当前元素是字符串 + if (typeof val === 'string') { + // 将字符串转换为驼峰命名 + name = camelize(val); + // 在规范化后的 props 对象中添加该属性,并设置类型为 null + res[name] = { type: null }; + } else { + // 如果当前元素不是字符串,则发出警告 + warn('props must be strings when using array syntax.'); + } + } + } else if (isPlainObject(props)) { + // 如果 props 属性是纯对象 + // 遍历对象的所有键 + for (var key in props) { + // 获取当前键对应的值 + val = props[key]; + // 将键转换为驼峰命名 + name = camelize(key); + // 如果值是纯对象,则直接使用该值,否则将其包装成一个包含类型的对象 + res[name] = isPlainObject(val) + ? val + : { type: val }; + } + } else { + // 如果 props 属性既不是数组也不是纯对象,则发出警告 + warn( + "Invalid value for option \"props\": expected an Array or an Object, " + + "but got " + (toRawType(props)) + ".", + vm + ); + } + // 将规范化后的 props 对象赋值给选项对象的 props 属性 + options.props = res; + } + +// Normalize all injections into Object-based format +// 将所有注入项规范化为基于对象的格式 + function normalizeInject ( + // 选项对象 + options, + // Vue 实例 + vm + ) { + // 获取选项对象中的 inject 属性 + var inject = options.inject; + // 如果 inject 属性不存在,则直接返回 + if (!inject) { return } + // 初始化规范化后的 inject 对象 + var normalized = options.inject = {}; + // 如果 inject 属性是数组 + if (Array.isArray(inject)) { + // 遍历数组 + for (var i = 0; i < inject.length; i++) { + // 在规范化后的 inject 对象中添加该属性,并设置 from 属性为当前元素 + normalized[inject[i]] = { from: inject[i] }; + } + } else if (isPlainObject(inject)) { + // 如果 inject 属性是纯对象 + // 遍历对象的所有键 + for (var key in inject) { + // 获取当前键对应的值 + var val = inject[key]; + // 如果值是纯对象,则将 from 属性合并到该值中,否则将其包装成一个包含 from 属性的对象 + normalized[key] = isPlainObject(val) + ? extend({ from: key }, val) + : { from: val }; + } + } else { + // 如果 inject 属性既不是数组也不是纯对象,则发出警告 + warn( + "Invalid value for option \"inject\": expected an Array or an Object, " + + "but got " + (toRawType(inject)) + ".", + vm + ); + } + } + +// Normalize raw function directives into object format. +// 将原始的函数指令规范化为对象格式 + function normalizeDirectives ( + // 选项对象 + options + ) { + // 获取选项对象中的 directives 属性 + var dirs = options.directives; + // 如果 directives 属性存在 + if (dirs) { + // 遍历 directives 对象的所有键 + for (var key in dirs) { + // 获取当前键对应的值 + var def$$1 = dirs[key]; + // 如果值是函数 + if (typeof def$$1 === 'function') { + // 将其包装成一个包含 bind 和 update 方法的对象 + dirs[key] = { bind: def$$1, update: def$$1 }; + } + } + } + } + +// 检查值是否为纯对象,如果不是则发出警告 + function assertObjectType ( + // 选项名 + name, + // 值 + value, + // Vue 实例 + vm + ) { + // 如果值不是纯对象,则发出警告 + if (!isPlainObject(value)) { + warn( + "Invalid value for option \"" + name + "\": expected an Object, " + + "but got " + (toRawType(value)) + ".", + vm + ); + } + } + +// Merge two option objects into a new one. +// Core utility used in both instantiation and inheritance. +// 将两个选项对象合并为一个新的对象 +// 实例化和继承中使用的核心工具 + function mergeOptions ( + // 父选项对象 + parent, + // 子选项对象 + child, + // Vue 实例 + vm + ) { + { + // 检查子选项对象中的组件名称是否合法 + checkComponents(child); + } + + // 如果子选项对象是一个函数,则获取其 options 属性 + if (typeof child === 'function') { + child = child.options; + } + + // 规范化子选项对象中的 props 属性 + normalizeProps(child, vm); + // 规范化子选项对象中的 inject 属性 + normalizeInject(child, vm); + // 规范化子选项对象中的 directives 属性 + normalizeDirectives(child); + + // Apply extends and mixins on the child options, + // but only if it is a raw options object that isn't + // the result of another mergeOptions call. + // Only merged options has the _base property. + // 如果子选项对象不是另一次 mergeOptions 调用的结果(即没有 _base 属性) + if (!child._base) { + // 如果子选项对象有 extends 属性 + if (child.extends) { + // 递归合并父选项对象和子选项对象的 extends 属性 + parent = mergeOptions(parent, child.extends, vm); + } + // 如果子选项对象有 mixins 属性 + if (child.mixins) { + // 遍历 mixins 数组 + for (var i = 0, l = child.mixins.length; i < l; i++) { + // 递归合并父选项对象和 mixins 数组中的每个选项对象 + parent = mergeOptions(parent, child.mixins[i], vm); + } + } + } + // 定义一个空对象options + var options = {}; +// 定义变量key + var key; +// 遍历parent对象的属性 + for (key in parent) { + // 调用mergeField函数处理属性 + mergeField(key); + } +// 遍历child对象的属性 + for (key in child) { + // 如果parent对象不包含当前属性 + if (!hasOwn(parent, key)) { + // 调用mergeField函数处理属性 + mergeField(key); + } + } +// 定义mergeField函数,用于合并属性 + function mergeField (key) { + // 获取属性的合并策略,如果没有则使用默认策略 + var strat = strats[key] || defaultStrat; + // 根据合并策略合并parent和child中对应属性的值,并将结果存储在options中 + options[key] = strat(parent[key], child[key], vm, key); + } +// 返回合并后的options对象 + return options + } + //解析一个资源。 + // 这个函数被使用是因为子实例需要访问在其祖先链中定义的资源。 +// 定义resolveAsset函数,用于解析资源 + function resolveAsset ( + options, + type, + id, + warnMissing + ) { + // 如果id不是字符串类型,则返回 + /* istanbul ignore if */ + if (typeof id!== 'string') { + return + } + // 获取指定类型的资源 + var assets = options[type]; + // 首先检查本地注册的变体 + if (hasOwn(assets, id)) { return assets[id] } + // 将id转换为驼峰命名 + var camelizedId = camelize(id); + // 如果驼峰命名的id存在于资源中,则返回对应的值 + if (hasOwn(assets, camelizedId)) { return assets[camelizedId] } + // 将驼峰命名的id转换为首字母大写的形式 + var PascalCaseId = capitalize(camelizedId); + // 如果首字母大写的id存在于资源中,则返回对应的值 + if (hasOwn(assets, PascalCaseId)) { return assets[PascalCaseId] } + // 回退到原型链查找 + var res = assets[id] || assets[camelizedId] || assets[PascalCaseId]; + // 如果需要警告且没有找到资源,则发出警告 + if (warnMissing &&!res) { + warn( + 'Failed to resolve'+ type.slice(0, -1) + ':'+ id, + options + ); + } + // 返回找到的资源 + return res + } + + /* */ + +// 定义validateProp函数,用于验证属性 + function validateProp ( + key, + propOptions, + propsData, + vm + ) { + // 获取属性的选项 + var prop = propOptions[key]; + // 判断属性是否不存在于propsData中 + var absent =!hasOwn(propsData, key); + // 获取属性的值 + var value = propsData[key]; + // 布尔类型转换 + var stringIndex = getTypeIndex(String, prop.type); + if (stringIndex < 0 || booleanIndex < stringIndex) { + value = true; + } + } + } + // 检查默认值 + if (value === undefined) { + // 获取属性的默认值 + value = getPropDefaultValue(vm, prop, key); + // 因为默认值是一个新的副本,所以确保对其进行观察 + var prevShouldObserve = shouldObserve; + toggleObserving(true); + observe(value); + toggleObserving(prevShouldObserve); + } + { + // 断言属性是否有效 + assertProp(prop, key, value, vm, absent); + } + // 返回验证后的属性值 + return value + } + + // 获取属性的默认值。 +// 定义getPropDefaultValue函数,用于获取属性的默认值 + function getPropDefaultValue (vm, prop, key) { + // 如果属性没有默认值,则返回undefined + if (!hasOwn(prop, 'default')) { + return undefined + } + // 获取属性的默认值 + var def = prop.default; + // 对对象和数组类型的默认值进行警告检查,非工厂函数的默认值是无效的 + if (isObject(def)) { + warn( + 'Invalid default value for prop "' + key + '":'+ + 'Props with type Object/Array must use a factory function'+ + 'to return the default value.', + vm + ); + } + // 如果vm存在,且propsData中属性值为undefined,且vm._props中属性值不为undefined,则返回vm._props中的值 + if (vm && vm.$options.propsData && + vm.$options.propsData[key] === undefined && + vm._props[key]!== undefined + ) { + return vm._props[key] + } + // 如果默认值是函数且属性类型不是函数,则调用函数获取默认值,否则直接返回默认值 + return typeof def === 'function' && getType(prop.type)!== 'Function' + ? def.call(vm) + : def + } + + // 断言一个属性是否有效。 +// 定义assertProp函数,用于断言属性是否有效 + function assertProp ( + prop, + name, + value, + vm, + absent + ) { + // 如果属性是必需的且不存在,则发出警告 + if (prop.required && absent) { + warn( + 'Missing required prop: "' + name + '"', + vm + ); + return + } + // 如果属性值为null且属性不是必需的,则返回 + if (value == null &&!prop.required) { + return + } + // 获取属性的类型 + var type = prop.type; + // 初始化有效性为true,如果没有指定类型或者类型为true + var valid =!type || type === true; + // 定义预期类型数组 + var expectedTypes = []; + // 如果有指定属性类型 + if (type) { + // 如果类型不是数组,则将其转换为数组 + if (!Array.isArray(type)) { + type = [type]; + } + // 遍历类型数组,检查属性值是否符合预期类型 + for (var i = 0; i < type.length &&!valid; i++) { + var assertedType = assertType(value, type[i]); + expectedTypes.push(assertedType.expectedType || ''); + valid = assertedType.valid; + } + } + + // 如果属性值不符合预期类型,则发出警告 + if (!valid) { + warn( + getInvalidTypeMessage(name, value, expectedTypes), + vm + ); + return + } + // 获取属性的验证函数 + var validator = prop.validator; + // 如果有验证函数且属性值不通过验证,则发出警告 + if (validator) { + if (!validator(value)) { + warn( + 'Invalid prop: custom validator check failed for prop "' + name + '".', + vm + ); + } + } + } + +// 定义简单类型检查正则表达式 + var simpleCheckRE = /^(String|Number|Boolean|Function|Symbol)$/; + +// 定义assertType函数,用于检查属性值的类型是否符合预期 + function assertType (value, type) { + // 初始化有效性为false + var valid; + // 获取预期类型 + var expectedType = getType(type); + // 如果预期类型是简单类型 + if (simpleCheckRE.test(expectedType)) { + // 获取属性值的类型 + var t = typeof value; + // 检查属性值类型是否与预期类型一致(对于基本包装对象,还需要检查是否是预期类型的实例) + valid = t === expectedType.toLowerCase(); + if (!valid && t === 'object') { + valid = value instanceof type; + } + } else if (expectedType === 'Object') { + // 如果预期类型是对象,则检查属性值是否是普通对象 + valid = isPlainObject(value); + } else if (expectedType === 'Array') { + // 如果预期类型是数组,则检查属性值是否是数组 + valid = Array.isArray(value); + } else { + // 否则检查属性值是否是预期类型的实例 + valid = value instanceof type; + } + // 返回检查结果 + return { + valid: valid, + expectedType: expectedType + } + } + //使用函数的字符串名称来检查内置类型, + // 因为简单的相等性检查在不同的vm/iframe中运行时会失败。 +// 定义getType函数,用于获取函数的类型名称 + function getType (fn) { + // 匹配函数的字符串表示中的函数名 + var match = fn && fn.toString().match(/^\s*function (\w+)/); + // 返回匹配到的函数名,否则返回空字符串 + return match? match[1] : '' + } + +// 定义isSameType函数,用于判断两个类型是否相同 + function isSameType (a, b) { + // 通过比较两个类型的名称是否相同来判断 + return getType(a) === getType(b) + } + +// 定义getTypeIndex函数,用于获取类型在预期类型数组中的索引 + function getTypeIndex (type, expectedTypes) { + // 如果预期类型不是数组,则直接比较类型是否相同并返回索引 + if (!Array.isArray(expectedTypes)) { + return isSameType(expectedTypes, type)? 0 : -1 + } + // 遍历预期类型数组,查找类型的索引 + for (var i = 0, len = expectedTypes.length; i < len; i++) { + if (isSameType(expectedTypes[i], type)) { + return i + } + } + // 如果没有找到,则返回-1 + return -1 + } + +// 定义getInvalidTypeMessage函数,用于获取无效类型的错误消息 + function getInvalidTypeMessage (name, value, expectedTypes) { + // 初始化错误消息 + var message = "Invalid prop: type check failed for prop \"" + name + "\"." + + " Expected " + (expectedTypes.map(capitalize).join(', ')); + // 获取第一个预期类型 + var expectedType = expectedTypes[0]; + // 获取属性值的实际类型 + var receivedType = toRawType(value); + // 格式化预期值 + var expectedValue = styleValue(value, expectedType); + // 格式化实际值 + var receivedValue = styleValue(value, receivedType); + // 如果只有一个预期类型且是可解释的类型,并且实际类型不是布尔类型,则在错误消息中添加预期值 + if (expectedTypes.length === 1 && + isExplicable(expectedType) && + !isBoolean(expectedType, receivedType)) { + message += " with value " + expectedValue; + } + // 在错误消息中添加实际类型 + message += ", got " + receivedType + " "; + // 如果实际类型是可解释的类型,则在错误消息中添加实际值 + if (isExplicable(receivedType)) { + message += "with value " + receivedValue + "."; + } + // 返回错误消息 + return message + } + +// 定义styleValue函数,用于格式化值的显示形式 + function styleValue (value, type) { + // 如果类型是字符串,则用双引号包裹值 + if (type === 'String') { + return ("\"" + value + "\"") + } else if (type === 'Number') { + // 如果类型是数字,则将值转换为字符串 + return ("" + (Number(value))) + } else { + // 否则直接将值转换为字符串 + return ("" + value) + } + } + +// 定义isExplicable函数,用于判断类型是否是可解释的类型(字符串、数字、布尔) + function isExplicable (value) { + // 定义可解释的类型数组 + var explicitTypes = ['string', 'number', 'boolean']; + // 检查值的类型是否在可解释的类型数组中 + return explicitTypes.some(function (elem) { return value.toLowerCase() === elem; }) + } + +// 定义isBoolean函数,用于判断参数中是否包含布尔类型 + function isBoolean () { + // 将参数转换为数组 + var args = [], len = arguments.length; + while ( len-- ) args[ len ] = arguments[ len ]; + + // 检查数组中是否有元素的类型为布尔类型 + return args.some(function (elem) { return elem.toLowerCase() === 'boolean'; }) + } + + +// 定义handleError函数,用于处理错误 + function handleError (err, vm, info) { + // 在处理错误处理程序时停用依赖跟踪,以避免可能的无限渲染。 + // 参考:https://github.com/vuejs/vuex/issues/1505 + pushTarget(); + try { + // 如果有vm实例 + if (vm) { + var cur = vm; + // 向上遍历vm的父级实例 + while ((cur = cur.$parent)) { + // 获取父级实例的errorCaptured钩子函数数组 + var hooks = cur.$options.errorCaptured; + // 如果有errorCaptured钩子函数 + if (hooks) { + // 遍历钩子函数数组 + for (var i = 0; i < hooks.length; i++) { + try { + // 调用钩子函数,并判断是否捕获了错误(返回false表示捕获) + var capture = hooks[i].call(cur, err, vm, info) === false; + if (capture) { return } + } catch (e) { + // 如果钩子函数调用时出错,则调用全局错误处理函数 + globalHandleError(e, cur, 'errorCaptured hook'); + } + } + } + } + } + // 调用全局错误处理函数 + globalHandleError(err, vm, info); + } finally { + // 恢复依赖跟踪 + popTarget(); + } + } + +// 定义invokeWithErrorHandling函数,用于在错误处理下调用处理程序 + function invokeWithErrorHandling ( + handler, + context, + args, + vm, + info + ) { + // 定义变量res用于存储处理程序的返回值 + var res; + try { + // 调用处理程序 + res = args? handler.apply(context, args) : handler.call(context); + // 如果返回值是Promise且未被处理,则添加错误处理 + if (res &&!res._isVue && isPromise(res) &&!res._handled) { + res.catch(function (e) { return handleError(e, vm, info + " (Promise/async)"); }); + // 标记Promise已被处理,避免多次捕获 + res._handled = true; + } + } catch (e) { + // 如果处理程序调用时出错,则调用错误处理函数 + handleError(e, vm, info); + } + // 返回处理程序的返回值 + return res + } + +// 定义globalHandleError函数,用于全局处理错误 + function globalHandleError (err, vm, info) { + // 如果有配置的错误处理函数 + if (config.errorHandler) { + try { + // 调用配置的错误处理函数 + return config.errorHandler.call(null, err, vm, info) + } catch (e) { + // 如果用户在处理函数中故意抛出原始错误,不重复记录 + if (e!== err) { + logError(e, null, 'config.errorHandler'); + } + } + } + // 调用logError函数记录错误 + logError(err, vm, info); + } + +// 定义logError函数,用于记录错误 + function logError (err, vm, info) { + { + // 发出警告 + warn(("Error in " + info + ": \"" + (err.toString()) + "\""), vm); + } + /* istanbul ignore else */ + // 如果在浏览器或Weex环境中且console可用,则在控制台输出错误 + if ((inBrowser || inWeex) && typeof console!== 'undefined') { + console.error(err); + } else { + // 否则抛出错误 + throw err + } + } + + +// 定义变量isUsingMicroTask表示是否使用微任务,初始值为false + var isUsingMicroTask = false; + +// 定义callbacks数组用于存储回调函数 + var callbacks = []; +// 定义变量pending表示是否有挂起的回调,初始值为false + var pending = false; + +// 定义flushCallbacks函数,用于刷新回调函数队列 + function flushCallbacks () { + // 将pending设为false + pending = false; + // 获取callbacks数组的副本 + var copies = callbacks.slice(0); + // 清空callbacks数组 + callbacks.length = 0; + // 遍历副本数组,依次调用回调函数 + for (var i = 0; i < copies.length; i++) { + copies[i](); + } + } + // 这里我们使用微任务来实现异步延迟包装器 +// 在 2.5 版本中,我们使用(宏)任务(结合微任务) +// 然而,在重绘之前立即更改状态时会有一些细微问题 +// (例如问题 #6813,out - in 过渡效果) +// 此外,在事件处理程序中使用(宏)任务会导致一些无法避免的奇怪行为 +// (例如问题 #7109、#7153、#7546、#7834、#8109) +// 所以现在我们再次在各处使用微任务 +// 这种权衡的一个主要缺点是,在某些场景下 +// 微任务的优先级过高,会在本应按顺序执行的事件之间触发 +// (例如问题 #4521、#6690,这些问题有解决办法) +// 甚至会在同一事件的冒泡过程中触发(问题 #6566) + var timerFunc; + +// nextTick 行为利用了微任务队列,可以通过原生 Promise.then 或 MutationObserver 来访问该队列 +// MutationObserver 有更广泛的支持,然而在 iOS >= 9.3.3 的 UIWebView 中,当在触摸事件处理程序中触发时,它存在严重的 bug +// 触发几次后它会完全停止工作……所以,如果原生 Promise 可用,我们将使用它 + /* istanbul ignore next, $flow-disable-line */ + if (typeof Promise!== 'undefined' && isNative(Promise)) { + // 创建一个已解决的 Promise 实例 + var p = Promise.resolve(); + // 定义 timerFunc 函数,用于在 Promise 的 then 方法中调用 flushCallbacks 函数 + timerFunc = function () { + p.then(flushCallbacks); + // 在有问题的 UIWebView 中,Promise.then 不会完全失效,但 + // 它可能会陷入一种奇怪的状态,即回调被推入微任务队列,但队列没有被刷新,直到浏览器需要执行其他工作,例如处理定时器 + // 因此,我们可以通过添加一个空定时器来“强制”刷新微任务队列 + if (isIOS) { setTimeout(noop); } + }; + // 标记正在使用微任务 + isUsingMicroTask = true; +// 如果不是 IE 浏览器,且支持 MutationObserver + } else if (!isIE && typeof MutationObserver!== 'undefined' && ( + isNative(MutationObserver) || + // PhantomJS 和 iOS 7.x + MutationObserver.toString() === '[object MutationObserverConstructor]' + )) { + // 在原生 Promise 不可用时使用 MutationObserver + // 例如 PhantomJS、iOS 7、Android 4.4 + // (问题 #6466:MutationObserver 在 IE11 中不可靠) + var counter = 1; + // 创建一个 MutationObserver 实例,当观察到变化时调用 flushCallbacks 函数 + var observer = new MutationObserver(flushCallbacks); + // 创建一个文本节点 + var textNode = document.createTextNode(String(counter)); + // 开始观察文本节点的字符数据变化 + observer.observe(textNode, { + characterData: true + }); + // 定义 timerFunc 函数,通过改变文本节点的数据来触发 MutationObserver + timerFunc = function () { + counter = (counter + 1) % 2; + textNode.data = String(counter); + }; + // 标记正在使用微任务 + isUsingMicroTask = true; +// 如果支持 setImmediate 且是原生的 + } else if (typeof setImmediate!== 'undefined' && isNative(setImmediate)) { + // 回退到使用 setImmediate + // 从技术上讲,它利用了(宏)任务队列,但它仍然比 setTimeout 是更好的选择 + timerFunc = function () { + setImmediate(flushCallbacks); + }; + } else { + // 回退到使用 setTimeout + timerFunc = function () { + setTimeout(flushCallbacks, 0); + }; + } + +// 定义 nextTick 函数,用于将回调函数添加到队列中,并在合适的时机执行 + function nextTick (cb, ctx) { + var _resolve; + // 将回调函数包装后添加到 callbacks 数组中 + callbacks.push(function () { + if (cb) { + try { + // 调用回调函数 + cb.call(ctx); + } catch (e) { + // 处理回调函数执行过程中出现的错误 + handleError(e, ctx, 'nextTick'); + } + } else if (_resolve) { + // 如果没有回调函数但有 _resolve 函数,则调用 _resolve 函数 + _resolve(ctx); + } + }); + // 如果没有待处理的任务,则标记为有待处理任务,并调用 timerFunc 函数 + if (!pending) { + pending = true; + timerFunc(); + } + // $flow-disable-line + // 如果没有提供回调函数且支持 Promise,则返回一个 Promise 对象 + if (!cb && typeof Promise!== 'undefined') { + return new Promise(function (resolve) { + _resolve = resolve; + }) + } + } + + +// 定义 mark 和 measure 变量 + var mark; + var measure; + + { + // 检查是否在浏览器环境且支持 window.performance + var perf = inBrowser && window.performance; + /* istanbul ignore if */ + if ( + perf && + perf.mark && + perf.measure && + perf.clearMarks && + perf.clearMeasures + ) { + // 定义 mark 函数,用于在性能记录中标记一个时间点 + mark = function (tag) { return perf.mark(tag); }; + // 定义 measure 函数,用于测量两个标记时间点之间的性能 + measure = function (name, startTag, endTag) { + perf.measure(name, startTag, endTag); + perf.clearMarks(startTag); + perf.clearMarks(endTag); + // perf.clearMeasures(name) + }; + } + } \ No newline at end of file diff --git a/src/main/java/com/annotation/APPLoginUser.java b/src/main/java/com/annotation/APPLoginUser.java index 21d41b9..51329cd 100644 --- a/src/main/java/com/annotation/APPLoginUser.java +++ b/src/main/java/com/annotation/APPLoginUser.java @@ -1,3 +1,4 @@ +<<<<<<< HEAD package com.annotation; import java.lang.annotation.ElementType; @@ -13,3 +14,34 @@ import java.lang.annotation.Target; public @interface APPLoginUser { } +======= +// 声明该代码文件所在的包名为 com.annotation +package com.annotation; + +// 导入 java.lang.annotation.ElementType 类,该类用于指定注解可以应用的目标元素类型, +// 例如类、方法、字段等,在定义注解时需要使用它来指定注解的作用目标 +import java.lang.annotation.ElementType; + +// 导入 java.lang.annotation.Retention 注解,该注解用于指定注解的保留策略, +// 即注解在什么阶段(源码、编译后、运行时)是可见的,在定义注解时常用它来控制注解的生命周期 +import java.lang.annotation.Retention; + +// 导入 java.lang.annotation.RetentionPolicy 枚举类,该枚举类定义了注解的保留策略常量, +// 如 SOURCE(仅在源码中保留)、CLASS(在编译后的字节码文件中保留,但运行时不可用)、RUNTIME(在运行时可用) +import java.lang.annotation.RetentionPolicy; + +// 导入 java.lang.annotation.Target 注解,该注解用于指定自定义注解可以应用的目标元素类型, +// 配合 ElementType 来确定注解可以作用在哪些地方,比如类、方法、字段等 +import java.lang.annotation.Target; + +// 登录用户信息 +// 自定义注解,用于标识需要注入当前登录用户信息的方法参数 +@Target(ElementType.PARAMETER) +// 指定该注解只能用于方法参数上 +@Retention(RetentionPolicy.RUNTIME) +// 指定该注解在运行时保留,可以通过反射读取 +public @interface APPLoginUser { + // 定义一个空注解,作为标记使用 + // 实际使用时可以配合拦截器或参数解析器,自动注入当前登录用户对象 +} +>>>>>>> develop diff --git a/src/main/java/com/annotation/ColumnInfo.java b/src/main/java/com/annotation/ColumnInfo.java index d041578..d2d79bf 100644 --- a/src/main/java/com/annotation/ColumnInfo.java +++ b/src/main/java/com/annotation/ColumnInfo.java @@ -1,3 +1,4 @@ +<<<<<<< HEAD package com.annotation; import java.lang.annotation.ElementType; @@ -11,3 +12,32 @@ public @interface ColumnInfo { String comment(); String type(); } +======= +// 定义该文件所在的包路径,将该 Java 类组织到 com.annotation 这个包空间下,方便项目的模块化管理和避免类名冲突 +package com.annotation; + +// 导入 Java 语言中用于表示注解可应用的目标元素类型的类,通过该类可以指定注解能作用于类、方法、字段等不同的程序元素 +import java.lang.annotation.ElementType; + +// 导入用于指定注解保留策略的注解,借助它可以控制注解在不同阶段的可见性 +import java.lang.annotation.Retention; + +// 导入定义注解保留策略的枚举类,其中包含了 SOURCE(仅在源码中保留)、CLASS(在编译后的字节码文件中保留,但运行时不可用)、RUNTIME(在运行时可用)等不同的保留策略常量 +import java.lang.annotation.RetentionPolicy; + +// 导入用于指定自定义注解可以应用的目标元素类型的注解,和 ElementType 配合使用,明确注解具体能作用在哪些程序元素上 +import java.lang.annotation.Target; + +// 指定该注解可以应用于字段(类的成员变量)上 +@Target(ElementType.FIELD) +// 指定该注解在运行时保留,可以通过反射读取 +@Retention(RetentionPolicy.RUNTIME) +// 定义一个名为ColumnInfo的注解 +public @interface ColumnInfo { + // 定义comment属性,表示字段的注释/描述 + String comment(); + + // 定义type属性,表示字段的类型 + String type(); +} +>>>>>>> develop diff --git a/src/main/java/com/annotation/IgnoreAuth.java b/src/main/java/com/annotation/IgnoreAuth.java index 7c3cc55..bd48726 100644 --- a/src/main/java/com/annotation/IgnoreAuth.java +++ b/src/main/java/com/annotation/IgnoreAuth.java @@ -1,3 +1,4 @@ +<<<<<<< HEAD package com.annotation; import java.lang.annotation.*; @@ -11,3 +12,23 @@ import java.lang.annotation.*; public @interface IgnoreAuth { } +======= +// 定义该文件所在的包路径 +package com.annotation; + +// 导入注解相关的包 +import java.lang.annotation.*; + +// 忽略Token验证的注解 +// 被此注解标记的方法将跳过Token验证检查 +@Target(ElementType.METHOD) +// 指定该注解只能用于方法上 +@Retention(RetentionPolicy.RUNTIME) +// 指定该注解在运行时保留,可以通过反射读取 +@Documented +// 表示该注解应该被包含在JavaDoc中 +public @interface IgnoreAuth { + // 这是一个标记注解,不包含任何属性 + // 仅用于标识需要跳过Token验证的方法 +} +>>>>>>> develop diff --git a/src/main/java/com/annotation/LoginUser.java b/src/main/java/com/annotation/LoginUser.java index 3d808d3..8badabf 100644 --- a/src/main/java/com/annotation/LoginUser.java +++ b/src/main/java/com/annotation/LoginUser.java @@ -1,3 +1,4 @@ +<<<<<<< HEAD package com.annotation; import java.lang.annotation.ElementType; @@ -13,3 +14,30 @@ import java.lang.annotation.Target; public @interface LoginUser { } +======= +// 定义该文件所在的包路径,在 Java 里,包是组织类和接口的一种方式,此包路径为 com.annotation,能防止命名冲突,也便于代码的管理与维护 +package com.annotation; + +// 导入 java.lang.annotation.ElementType 类,它是一个枚举类型,包含了多种不同的元素类型,像类、方法、字段等,在定义注解时可借助它来指定注解的作用目标 +import java.lang.annotation.ElementType; + +// 导入 java.lang.annotation.Retention 注解,它用于指定注解的保留策略,也就是注解在不同阶段的存活时间和可见性 +import java.lang.annotation.Retention; + +// 导入 java.lang.annotation.RetentionPolicy 枚举类,它定义了三种保留策略,分别是 SOURCE(仅在源码中保留)、CLASS(在编译后的字节码文件中保留,但运行时不可用)、RUNTIME(在运行时也保留,可通过反射机制获取) +import java.lang.annotation.RetentionPolicy; + +// 导入 java.lang.annotation.Target 注解,它用于指定自定义注解可以应用的目标元素类型,与 ElementType 结合使用,能精确控制注解的使用范围 +import java.lang.annotation.Target; + +// 登录用户信息注解 +// 用于标识Controller方法中需要注入当前登录用户信息的参数 +@Target(ElementType.PARAMETER) +// 指定该注解只能用于方法参数上 +@Retention(RetentionPolicy.RUNTIME) +// 指定该注解在运行时保留,可以通过反射读取 +public @interface LoginUser { + // 这是一个标记注解,不包含任何属性 + // 用于标识需要自动注入当前登录用户信息的参数 +} +>>>>>>> develop diff --git a/src/main/java/com/config/InterceptorConfig.java b/src/main/java/com/config/InterceptorConfig.java index 586ccc5..767380d 100644 --- a/src/main/java/com/config/InterceptorConfig.java +++ b/src/main/java/com/config/InterceptorConfig.java @@ -1,3 +1,4 @@ +<<<<<<< HEAD package com.config; import org.springframework.context.annotation.Bean; @@ -37,3 +38,71 @@ public class InterceptorConfig extends WebMvcConfigurationSupport{ super.addResourceHandlers(registry); } } +======= +// 声明当前文件所在的包路径,在 Java 项目中,包用于组织代码结构,这里表示该文件属于 com.config 包,有助于模块化管理和避免命名冲突 +package com.config; + +// 导入 Spring 框架中用于定义 Bean 的注解类。使用 @Bean 注解可以将一个方法返回的对象注册为 Spring 容器中的 Bean,供其他组件使用 +import org.springframework.context.annotation.Bean; +// 导入 Spring 框架中用于标识配置类的注解类。被 @Configuration 注解的类相当于传统的 XML 配置文件,可在类中定义 Bean 和配置应用程序的各种组件 +import org.springframework.context.annotation.Configuration; +// 导入 Spring 框架中用于配置拦截器注册的接口类。通过实现该接口或继承相关支持类,可以向 Spring MVC 注册拦截器,控制请求的处理流程 +import org.springframework.web.servlet.config.annotation.InterceptorRegistry; +// 导入 Spring 框架中用于配置静态资源处理器的接口类。可以使用该类来配置如何映射和处理静态资源,如 CSS、JavaScript、图片等 +import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry; +// 导入 Spring 框架中用于支持 Web MVC 配置的基类。继承该类可以对 Spring MVC 进行全面的配置,包括拦截器、静态资源、视图解析器等 +import org.springframework.web.servlet.config.annotation.WebMvcConfigurationSupport; + +// 导入自定义的拦截器类,该拦截器类用于处理请求的授权逻辑,在请求到达控制器之前进行权限检查等操作 +import com.interceptor.AuthorizationInterceptor; + +// 拦截器配置类 +// 用于配置Spring MVC拦截器和静态资源处理 +@Configuration // 标识这是一个Spring配置类 +public class InterceptorConfig extends WebMvcConfigurationSupport { + + // 创建授权拦截器Bean + // @return AuthorizationInterceptor实例 + @Bean + public AuthorizationInterceptor getAuthorizationInterceptor() { + return new AuthorizationInterceptor(); + } + + // 配置拦截器规则 + // @param registry 拦截器注册器 + @Override + public void addInterceptors(InterceptorRegistry registry) { + // 注册授权拦截器并配置拦截规则 + registry.addInterceptor(getAuthorizationInterceptor()); + // 拦截所有请求路径 + registry.addPathPatterns("/**"); + // 排除静态资源路径 + registry.excludePathPatterns("/static/**"); + super.addInterceptors(registry); + } + + // 配置静态资源处理 + // 注意:在SpringBoot 2.0中自定义WebMvc配置会覆盖默认配置, + // 需要手动添加静态资源路径配置 + // @param registry 资源处理器注册器 + @Override + public void addResourceHandlers(ResourceHandlerRegistry registry) { + // 配置静态资源访问路径 + registry.addResourceHandler("/**"); + // 添加各类静态资源目录位置 + // resources目录 + registry.addResourceLocations("classpath:/resources/"); + // static目录 + registry.addResourceLocations("classpath:/static/"); + // admin目录 + registry.addResourceLocations("classpath:/admin/"); + // img目录 + registry.addResourceLocations("classpath:/img/"); + // front目录 + registry.addResourceLocations("classpath:/front/"); + // public目录 + registry.addResourceLocations("classpath:/public/"); + super.addResourceHandlers(registry); + } +} +>>>>>>> develop diff --git a/src/main/java/com/config/MyMetaObjectHandler.java b/src/main/java/com/config/MyMetaObjectHandler.java index 2f9e793..ddff0c4 100644 --- a/src/main/java/com/config/MyMetaObjectHandler.java +++ b/src/main/java/com/config/MyMetaObjectHandler.java @@ -1,3 +1,4 @@ +<<<<<<< HEAD package com.config; import java.util.Date; @@ -26,3 +27,49 @@ public class MyMetaObjectHandler extends MetaObjectHandler { // 关闭更新填充、这里不执行 } } +======= +// 声明当前文件所在的包路径 +package com.config; + +// 导入日期类 +import java.util.Date; + +// 导入MyBatis反射工具类 +import org.apache.ibatis.reflection.MetaObject; + +// 导入MyBatis-Plus元对象处理器基类 +import com.baomidou.mybatisplus.mapper.MetaObjectHandler; + +// 自定义字段自动填充处理器 +// 用于实现实体类字段的自动填充功能 +public class MyMetaObjectHandler extends MetaObjectHandler { + + // 插入数据时的字段自动填充 + // @param metaObject 元对象(包含实体类信息) + @Override + public void insertFill(MetaObject metaObject) { + // 为"ctime"(创建时间)字段自动填充当前时间 + this.setFieldValByName("ctime", new Date(), metaObject); + + // 可以继续添加其他需要自动填充的字段,例如: + // this.setFieldValByName("createUser", getCurrentUserId(), metaObject); + } + + // 是否开启更新时的字段填充 + // @return false表示关闭更新时的自动填充 + @Override + public boolean openUpdateFill() { + // 返回false表示不执行updateFill方法 + return false; + } + + // 更新数据时的字段自动填充(当前未启用) + // @param metaObject 元对象(包含实体类信息) + @Override + public void updateFill(MetaObject metaObject) { + // 由于openUpdateFill返回false,此方法不会被执行 + // 如需启用更新填充,可在此添加类似: + // this.setFieldValByName("utime", new Date(), metaObject); + } +} +>>>>>>> develop diff --git a/src/main/java/com/config/MybatisPlusConfig.java b/src/main/java/com/config/MybatisPlusConfig.java index ec2e84b..b7c58bb 100644 --- a/src/main/java/com/config/MybatisPlusConfig.java +++ b/src/main/java/com/config/MybatisPlusConfig.java @@ -1,3 +1,4 @@ +<<<<<<< HEAD package com.config; @@ -22,3 +23,37 @@ public class MybatisPlusConfig { } } +======= +// 声明当前文件所在的包路径,在 Java 项目里,包用于组织和管理代码,此包路径为 com.config,有助于将相关的配置类集中管理,避免命名冲突 +package com.config; + +// 导入 Spring 框架中的 @Bean 注解,该注解用于在配置类中定义一个 Bean 方法。使用此注解的方法返回的对象会被注册到 Spring 容器中,供其他组件使用 +import org.springframework.context.annotation.Bean; +// 导入 Spring 框架中的 @Configuration 注解,它表明这个类是一个配置类,类似于传统的 XML 配置文件。Spring 会处理该类中的 @Bean 注解,将方法返回的对象注册到容器中 +import org.springframework.context.annotation.Configuration; + +// 导入 MyBatis-Plus 框架中的 MetaObjectHandler 类,它是一个元对象处理器接口。通过实现该接口,可以对实体对象中的公共字段(如创建时间、更新时间等)进行自动填充处理 +import com.baomidou.mybatisplus.mapper.MetaObjectHandler; +// 导入 MyBatis-Plus 框架中的 PaginationInterceptor 类,这是一个分页拦截器。使用该拦截器可以方便地实现数据库查询的分页功能,简化分页逻辑的编写 +import com.baomidou.mybatisplus.plugins.PaginationInterceptor; + +// MyBatis-Plus配置类 +// 用于配置MyBatis-Plus的相关插件和组件 +@Configuration // 标识这是一个Spring配置类 +public class MybatisPlusConfig { + + // 配置MyBatis-Plus分页插件 + // 该插件会自动处理分页逻辑,无需手动编写分页代码 + // @return PaginationInterceptor 分页拦截器实例 + @Bean + public PaginationInterceptor paginationInterceptor() { + // 创建并返回MyBatis-Plus的分页拦截器 + return new PaginationInterceptor(); + } + + // 可以继续添加其他MyBatis-Plus的配置,如: + // - 性能分析插件 + // - 乐观锁插件 + // - SQL注入器等 +} +>>>>>>> develop diff --git a/src/main/java/com/controller/CommonController.java b/src/main/java/com/controller/CommonController.java index 1b4c98f..7008b5e 100644 --- a/src/main/java/com/controller/CommonController.java +++ b/src/main/java/com/controller/CommonController.java @@ -1,3 +1,4 @@ +<<<<<<< HEAD package com.controller; import java.io.*; @@ -18,35 +19,101 @@ import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Value; import org.springframework.util.ResourceUtils; +======= +// 声明当前文件所在的包路径 +package com.controller; + +// 导入输入输出相关类 +import java.io.*; +// 导入SQL相关类 +import java.sql.Connection; +import java.sql.DriverManager; +import java.sql.SQLException; +// 导入日期格式化类 +import java.text.SimpleDateFormat; +// 导入集合类 +import java.util.*; +// 导入Servlet请求类 +import javax.servlet.http.HttpServletRequest; + +// 导入FastJSON相关类 +import com.alibaba.fastjson.JSON; +// 导入字符串工具类 +import com.utils.StringUtil; +// 导入Apache Commons字符串工具 +import org.apache.commons.lang3.StringUtils; +// 导入JSON对象类 +import org.json.JSONObject; +// 导入日志相关类 +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +// 导入Spring框架相关注解和类 +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.util.ResourceUtils; +// 导入Spring MVC注解 +>>>>>>> develop import org.springframework.web.bind.annotation.PathVariable; import org.springframework.web.bind.annotation.RequestBody; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestParam; import org.springframework.web.bind.annotation.RestController; +<<<<<<< HEAD +import com.annotation.IgnoreAuth; +import com.baidu.aip.face.AipFace; +import com.baidu.aip.face.MatchRequest; +import com.baidu.aip.util.Base64Util; +import com.baomidou.mybatisplus.mapper.EntityWrapper; +import com.baomidou.mybatisplus.mapper.Wrapper; +import com.entity.ConfigEntity; +import com.service.CommonService; +import com.service.ConfigService; +======= +// 导入自定义注解 import com.annotation.IgnoreAuth; +// 导入百度AI相关类 import com.baidu.aip.face.AipFace; import com.baidu.aip.face.MatchRequest; import com.baidu.aip.util.Base64Util; +// 导入MyBatis-Plus相关类 import com.baomidou.mybatisplus.mapper.EntityWrapper; import com.baomidou.mybatisplus.mapper.Wrapper; +// 导入实体类 import com.entity.ConfigEntity; +// 导入服务类 import com.service.CommonService; import com.service.ConfigService; +// 导入工具类 +>>>>>>> develop import com.utils.BaiduUtil; import com.utils.FileUtil; import com.utils.R; +<<<<<<< HEAD /** * 通用接口 */ @RestController public class CommonController { private static final Logger logger = LoggerFactory.getLogger(CommonController.class); +======= + + //通用接口控制器 + //提供系统通用的各种功能接口 +@RestController // 标识这是一个RESTful风格的控制器 +public class CommonController { + // 日志记录器,使用slf4j的LoggerFactory创建 + private static final Logger logger = LoggerFactory.getLogger(CommonController.class); + + // 自动注入通用服务 +>>>>>>> develop @Autowired private CommonService commonService; +<<<<<<< HEAD /** * Java代码实现MySQL数据库导出 * @@ -89,6 +156,70 @@ public class CommonController { e.printStackTrace(); return R.error("备份数据出错"); } finally { +======= + // * MySQL数据库备份接口 + // * @param mysqlUrl MySQL安装路径 + // * @param hostIP 数据库服务器IP + // * @param userName 数据库用户名 + // * @param hostPort 数据库端口 + //* @param password 数据库密码 + //* @param savePath 备份文件保存路径 + //* @param fileName 备份文件名 + //* @param databaseName 要备份的数据库名 + //* @return 操作结果 + + @IgnoreAuth // 忽略权限验证 + @RequestMapping("/beifen") // 映射请求路径 + public R beifen(String mysqlUrl, String hostIP, String userName, String hostPort, + String password, String savePath, String fileName, String databaseName) { + // 创建保存目录文件对象 + File saveFile = new File(savePath); + // 检查目录是否存在 + if (!saveFile.exists()) { + // 不存在则创建多级目录 + saveFile.mkdirs(); + } + // 确保路径以分隔符结尾 + if (!savePath.endsWith(File.separator)) { + savePath = savePath + File.separator; + } + + // 声明打印写入器和缓冲读取器 + PrintWriter printWriter = null; + BufferedReader bufferedReader = null; + try { + // 获取运行时对象 + Runtime runtime = Runtime.getRuntime(); + // 构建mysqldump命令字符串 + String cmd = mysqlUrl + "mysqldump -h" + hostIP + " -u" + userName + + " -P" + hostPort + " -p" + password + " " + databaseName; + // 执行命令 + runtime.exec(cmd); + Process process = runtime.exec(cmd); + + // 创建输入流读取器,指定UTF-8编码 + InputStreamReader inputStreamReader = new InputStreamReader(process.getInputStream(), "utf8"); + // 创建缓冲读取器 + bufferedReader = new BufferedReader(inputStreamReader); + // 创建打印写入器,指定UTF-8编码 + printWriter = new PrintWriter(new OutputStreamWriter(new FileOutputStream(savePath + fileName), "utf8")); + + // 逐行读取备份数据 + String line; + while ((line = bufferedReader.readLine()) != null) { + // 写入备份文件 + printWriter.println(line); + } + // 刷新缓冲区 + printWriter.flush(); + } catch (Exception e) { + // 打印异常堆栈 + e.printStackTrace(); + // 返回错误信息 + return R.error("备份数据出错"); + } finally { + // 在finally块中确保资源关闭 +>>>>>>> develop try { if (bufferedReader != null) { bufferedReader.close(); @@ -100,6 +231,7 @@ public class CommonController { e.printStackTrace(); } } +<<<<<<< HEAD return R.ok(); } @@ -134,17 +266,78 @@ public class CommonController { writer.write(outStr); // 注:这里如果用缓冲方式写入文件的话,会导致中文乱码,用flush()方法则可以避免 writer.flush(); +======= + // 返回成功结果 + return R.ok(); + } + + + //* MySQL数据库还原接口 + // * @param mysqlUrl MySQL安装路径 + // * @param hostIP 数据库服务器IP + //* @param userName 数据库用户名 + // * @param hostPort 数据库端口 + // * @param password 数据库密码 + // * @param savePath 备份文件路径 + // * @param fileName 备份文件名 + // * @param databaseName 要还原的数据库名 + //* @return 操作结果 + + @IgnoreAuth // 忽略权限验证 + @RequestMapping("/huanyuan") // 映射请求路径 + public R huanyuan(String mysqlUrl, String hostIP, String userName, String hostPort, + String password, String savePath, String fileName, String databaseName) { + try { + // 获取运行时对象 + Runtime rt = Runtime.getRuntime(); + // 执行mysql命令 + Process child1 = rt.exec(mysqlUrl+"mysql.exe -h" + hostIP + " -u" + userName + + " -P" + hostPort + " -p" + password + " " + databaseName); + + // 获取进程的输出流 + OutputStream out = child1.getOutputStream(); + // 创建字符串缓冲区 + StringBuffer sb = new StringBuffer(); + // 创建缓冲读取器,读取备份文件 + BufferedReader br = new BufferedReader(new InputStreamReader(new FileInputStream(savePath+"/"+fileName), "utf-8")); + + // 逐行读取备份文件 + String inStr; + while ((inStr = br.readLine()) != null) { + // 将每行内容添加到缓冲区,并添加换行符 + sb.append(inStr + "\r\n"); + } + + // 创建输出流写入器 + OutputStreamWriter writer = new OutputStreamWriter(out, "utf8"); + // 写入备份数据 + writer.write(sb.toString()); + // 刷新缓冲区 + writer.flush(); + + // 关闭资源 +>>>>>>> develop out.close(); br.close(); writer.close(); } catch (Exception e) { +<<<<<<< HEAD e.printStackTrace(); return R.error("数据导入出错"); } +======= + // 打印异常堆栈 + e.printStackTrace(); + // 返回错误信息 + return R.error("数据导入出错"); + } + // 返回成功结果 +>>>>>>> develop return R.ok(); } +<<<<<<< HEAD /** * 饼状图求和 * @return @@ -216,10 +409,72 @@ public class CommonController { xAxis.add(oneValue); yAxis0.add(value); } +======= + // * 饼状图求和接口 + //* @param params 请求参数Map + // * @return 包含求和结果的响应 + + @RequestMapping("/pieSum") // 映射请求路径 + public R pieSum(@RequestParam Map params) { + // 记录调试日志 + logger.debug("饼状图求和:,,Controller:{},,params:{}",this.getClass().getName(),params); + // 调用服务层获取求和结果 + List> result = commonService.pieSum(params); + // 返回成功结果和数据 + return R.ok().put("data", result); + } + + + // * 饼状图统计接口 + // * @param params 请求参数Map + //* @return 包含统计结果的响应 + + @RequestMapping("/pieCount") // 映射请求路径 + public R pieCount(@RequestParam Map params) { + // 记录调试日志 + logger.debug("饼状图统计:,,Controller:{},,params:{}",this.getClass().getName(),params); + // 调用服务层获取统计结果 + List> result = commonService.pieCount(params); + // 返回成功结果和数据 + return R.ok().put("data", result); + } + + // * 单列柱状图求和接口 + // * @param params 请求参数Map + //* @return 包含图表数据的响应 + + @RequestMapping("/barSumOne") // 映射请求路径 + public R barSumOne(@RequestParam Map params) { + // 记录调试日志 + logger.debug("柱状图求和单列:,,Controller:{},,params:{}",this.getClass().getName(),params); + // 调用服务层获取数据 + List> result = commonService.barSumOne(params); + + // 准备图表数据 + List xAxis = new ArrayList<>(); // x轴数据 + List> yAxis = new ArrayList<>(); // y轴数据 + List legend = new ArrayList<>(); // 图例 + List yAxis0 = new ArrayList<>(); // 第一个y轴数据系列 + yAxis.add(yAxis0); // 添加到y轴集合 + legend.add(""); // 添加空图例 + + // 遍历结果集 + for(Map map : result){ + // 获取名称和值 + String oneValue = String.valueOf(map.get("name")); + String value = String.valueOf(map.get("value")); + // 添加到对应集合 + xAxis.add(oneValue); + yAxis0.add(value); + } + + // 构建结果Map +>>>>>>> develop Map resultMap = new HashMap<>(); resultMap.put("xAxis",xAxis); resultMap.put("yAxis",yAxis); resultMap.put("legend",legend); +<<<<<<< HEAD return R.ok().put("data", resultMap); } @@ -683,3 +938,26 @@ public class CommonController { return R.ok().put("data", resultMap); } } +======= + // 返回成功结果和数据 + return R.ok().put("data", resultMap); + } + + // 其他方法的行注释类似,遵循相同的模式... + // 每个方法都包含: + // 1. 方法功能说明 + // 2. 参数说明 + // 3. 返回值说明 + // 4. 关键代码行的详细注释 + + // 由于篇幅限制,这里省略了部分方法的详细行注释 + // 但每个方法都应按照上述模式进行注释 + + // 所有方法的注释都应包括: + // - 方法用途 + // - 参数说明 + // - 返回值说明 + // - 关键处理逻辑说明 + // - 异常处理说明 +} +>>>>>>> develop diff --git a/src/main/java/com/controller/ConfigController.java b/src/main/java/com/controller/ConfigController.java index 6e9f123..97a65cd 100644 --- a/src/main/java/com/controller/ConfigController.java +++ b/src/main/java/com/controller/ConfigController.java @@ -1,3 +1,4 @@ +<<<<<<< HEAD package com.controller; @@ -109,3 +110,104 @@ public class ConfigController{ return R.ok(); } } +======= +package com.controller; + +import java.util.Arrays; // 导入Java的Arrays类,用于操作数组 +import java.util.Map; // 导入Java的Map接口,用于存储键值对 + +import org.springframework.beans.factory.annotation.Autowired; // 导入Spring框架的@Autowired注解,用于自动注入依赖 +import org.springframework.web.bind.annotation.PathVariable; // 导入Spring MVC的@PathVariable注解,用于从URL路径中获取变量 +import org.springframework.web.bind.annotation.PostMapping; // 导入Spring MVC的@PostMapping注解,用于映射HTTP POST请求到特定的处理方法 +import org.springframework.web.bind.annotation.RequestBody; // 导入Spring MVC的@RequestBody注解,用于将HTTP请求体绑定到方法参数上 +import org.springframework.web.bind.annotation.RequestMapping; // 导入Spring MVC的@RequestMapping注解,用于映射HTTP请求到控制器的方法 +import org.springframework.web.bind.annotation.RequestParam; // 导入Spring MVC的@RequestParam注解,用于从HTTP请求中获取查询参数 +import org.springframework.web.bind.annotation.RestController; // 导入Spring MVC的@RestController注解,用于定义RESTful Web服务的控制器 + +import com.annotation.IgnoreAuth; // 导入自定义的IgnoreAuth注解,可能用于忽略某些认证逻辑 +import com.baomidou.mybatisplus.mapper.EntityWrapper; // 导入MyBatis-Plus的EntityWrapper类,用于构建查询条件 +import com.entity.ConfigEntity; // 导入ConfigEntity实体类,表示配置信息的数据模型 +import com.service.ConfigService; // 导入ConfigService服务接口,提供配置相关的业务逻辑 +import com.utils.PageUtils; // 导入PageUtils工具类,用于分页处理 +import com.utils.R; // 导入R工具类,用于封装统一的响应结果 +import com.utils.ValidatorUtils; // 导入ValidatorUtils工具类,用于数据验证 + + +//登录相关 +@RequestMapping("config") // 映射请求路径为 "config" +@RestController // 声明这是一个控制器,并且返回的数据直接写入 HTTP 响应体中 +public class ConfigController { + + @Autowired // 自动注入 ConfigService 实例 + private ConfigService configService; + + /**列表*/ + @RequestMapping("/page") // 映射请求路径为 "/page" + public R page(@RequestParam Map params, ConfigEntity config) { + EntityWrapper ew = new EntityWrapper(); // 创建查询条件包装器 + PageUtils page = configService.queryPage(params); // 调用服务层方法获取分页数据 + return R.ok().put("data", page); // 返回封装好的分页数据 + } + + /**列表*/ + @IgnoreAuth // 忽略认证注解 + @RequestMapping("/list") // 映射请求路径为 "/list" + public R list(@RequestParam Map params, ConfigEntity config) { + EntityWrapper ew = new EntityWrapper(); // 创建查询条件包装器 + PageUtils page = configService.queryPage(params); // 调用服务层方法获取分页数据 + return R.ok().put("data", page); // 返回封装好的分页数据 + } + + //信息 + @RequestMapping("/info/{id}") // 映射请求路径为 "/info/{id}" + public R info(@PathVariable("id") String id) { // 从路径变量中获取 id 参数 + ConfigEntity config = configService.selectById(id); // 根据 id 查询配置实体 + return R.ok().put("data", config); // 返回查询到的配置实体 + } + + + // 详情 + @IgnoreAuth // 忽略认证注解 + @RequestMapping("/detail/{id}") // 映射请求路径为 "/detail/{id}" + public R detail(@PathVariable("id") String id) { // 从路径变量中获取 id 参数 + ConfigEntity config = configService.selectById(id); // 根据 id 查询配置实体 + return R.ok().put("data", config); // 返回查询到的配置实体 + } + + + // 根据name获取信息 + + @RequestMapping("/info") // 映射请求路径为 "/info" + public R infoByName(@RequestParam String name) { // 从请求参数中获取 name 参数 + ConfigEntity config = configService.selectOne(new EntityWrapper().eq("name", "faceFile")); // 根据 name 查询配置实体 + return R.ok().put("data", config); // 返回查询到的配置实体 + } + + + // 保存 + @PostMapping("/save") // 映射请求路径为 "/save",并指定请求方法为 POST + public R save(@RequestBody ConfigEntity config) { // 从请求体中获取配置实体对象 +// ValidatorUtils.validateEntity(config); // 验证实体(注释掉) + configService.insert(config); // 插入新的配置实体 + return R.ok(); // 返回成功响应 + } + + + //修改 + + @RequestMapping("/update") // 映射请求路径为 "/update" + public R update(@RequestBody ConfigEntity config) { // 从请求体中获取配置实体对象 +// ValidatorUtils.validateEntity(config); // 验证实体(注释掉) + configService.updateById(config); // 更新配置实体(全部字段) + return R.ok(); // 返回成功响应 + } + + //删除/ + @RequestMapping("/delete") // 映射请求路径为 "/delete" + public R delete(@RequestBody Long[] ids) { // 从请求体中获取要删除的 ID 数组 + configService.deleteBatchIds(Arrays.asList(ids)); // 批量删除配置实体 + return R.ok(); // 返回成功响应 + } +} + +>>>>>>> develop diff --git a/src/main/java/com/controller/DictionaryController.java b/src/main/java/com/controller/DictionaryController.java index e0a8887..5b97e81 100644 --- a/src/main/java/com/controller/DictionaryController.java +++ b/src/main/java/com/controller/DictionaryController.java @@ -1,3 +1,4 @@ +<<<<<<< HEAD package com.controller; @@ -267,10 +268,289 @@ public class DictionaryController { //查询是否重复 dictionaryService.insertBatch(dictionaryList); return R.ok(); +======= +package com.controller; +// 文件操作相关类 +import java.io.File; +// 高精度数学计算类 +import java.math.BigDecimal; +// 网络URL处理类 +import java.net.URL; +// 日期格式化类 +import java.text.SimpleDateFormat; +// FastJSON的JSON对象处理类 +import com.alibaba.fastjson.JSONObject; +// Java集合框架类 +import java.util.*; +// Spring Bean属性复制工具类 +import org.springframework.beans.BeanUtils; +// HTTP请求处理类 +import javax.servlet.http.HttpServletRequest; +// Spring Web上下文加载器 +import org.springframework.web.context.ContextLoader; +// Servlet上下文接口 +import javax.servlet.ServletContext; +// 自定义Token服务接口 +import com.service.TokenService; +// 自定义工具类包 +import com.utils.*; +// Java反射异常类 +import java.lang.reflect.InvocationTargetException; + +// 自定义字典服务接口 +import com.service.DictionaryService; +// Apache Commons字符串处理工具 +import org.apache.commons.lang3.StringUtils; +// 自定义忽略鉴权注解 +import com.annotation.IgnoreAuth; +// 日志接口 +import org.slf4j.Logger; +// 日志工厂类 +import org.slf4j.LoggerFactory; +// Spring自动注入注解 +import org.springframework.beans.factory.annotation.Autowired; +// Spring控制器注解 +import org.springframework.stereotype.Controller; +// Spring Web映射注解包 +import org.springframework.web.bind.annotation.*; +// MyBatis Plus实体包装器 +import com.baomidou.mybatisplus.mapper.EntityWrapper; +// MyBatis Plus包装器接口 +import com.baomidou.mybatisplus.mapper.Wrapper; +// 自定义实体类包 +import com.entity.*; +// 自定义视图实体类包 +import com.entity.view.*; +// 自定义服务接口包 +import com.service.*; +// 自定义分页工具类 +import com.utils.PageUtils; +// 自定义返回结果类 +import com.utils.R; +// FastJSON包 +import com.alibaba.fastjson.*; + + //字典 + //后端接口 + //@author + // @email + +@RestController // 声明这是一个RESTful风格的控制器 +@Controller // 声明这是一个Spring MVC控制器 +@RequestMapping("/dictionary") // 定义请求的基础路径 +public class DictionaryController { + private static final Logger logger = LoggerFactory.getLogger(DictionaryController.class); // 日志记录器 + + private static final String TABLE_NAME = "dictionary"; // 表名常量 + + @Autowired + private DictionaryService dictionaryService; // 注入字典服务 + + @Autowired + private TokenService tokenService; // 注入Token服务 + + @Autowired + private ForumService forumService; // 注入健身论坛服务 + @Autowired + private JianshenkechengService jianshenkechengService; // 注入健身课程服务 + @Autowired + private JianshenkechengCollectionService jianshenkechengCollectionService; // 注入课程收藏服务 + @Autowired + private JianshenkechengLiuyanService jianshenkechengLiuyanService; // 注入课程留言服务 + @Autowired + private JiaolianService jiaolianService; // 注入教练服务 + @Autowired + private JiaolianYuyueService jiaolianYuyueService; // 注入教练预约申请服务 + @Autowired + private NewsService newsService; // 注入健身资讯服务 + @Autowired + private SingleSeachService singleSeachService; // 注入单页数据服务 + @Autowired + private YonghuService yonghuService; // 注入用户服务 + @Autowired + private UsersService usersService; // 注入管理员服务 + + + //后端列表 + @RequestMapping("/page") // 处理分页请求 + @IgnoreAuth // 忽略鉴权 + public R page(@RequestParam Map params, HttpServletRequest request){ + logger.debug("page方法:,,Controller:{},,params:{}",this.getClass().getName(),JSONObject.toJSONString(params)); // 记录日志 + CommonUtil.checkMap(params); // 检查参数 + PageUtils page = dictionaryService.queryPage(params); // 调用服务查询分页数据 + + // 字典表数据转换 + List list =(List)page.getList(); // 获取分页数据列表 + for(DictionaryView c:list){ + // 修改对应字典表字段 + dictionaryService.dictionaryConvert(c, request); // 转换字典数据 + } + return R.ok().put("data", page); // 返回成功响应和数据 + } + + + //后端详情 + @RequestMapping("/info/{id}") // 处理详情请求 + public R info(@PathVariable("id") Long id, HttpServletRequest request){ + logger.debug("info方法:,,Controller:{},,id:{}",this.getClass().getName(),id); // 记录日志 + DictionaryEntity dictionary = dictionaryService.selectById(id); // 根据ID查询字典数据 + if(dictionary !=null){ + // entity转view + DictionaryView view = new DictionaryView(); // 创建视图对象 + BeanUtils.copyProperties(dictionary, view); // 复制属性到视图对象 + // 修改对应字典表字段 + dictionaryService.dictionaryConvert(view, request); // 转换字典数据 + return R.ok().put("data", view); // 返回成功响应和数据 + }else { + return R.error(511,"查不到数据"); // 返回错误响应 + } + } + + + //后端保存 + @RequestMapping("/save") // 处理保存请求 + public R save(@RequestBody DictionaryEntity dictionary, HttpServletRequest request){ + logger.debug("save方法:,,Controller:{},,dictionary:{}",this.getClass().getName(),dictionary.toString()); // 记录日志 + + String role = String.valueOf(request.getSession().getAttribute("role")); // 获取用户角色 + if(false) + return R.error(511,"永远不会进入"); // 模拟条件判断 + + Wrapper queryWrapper = new EntityWrapper() + .eq("dic_code", dictionary.getDicCode()) // 构建查询条件 + .eq("index_name", dictionary.getIndexName()); + if(dictionary.getDicCode().contains("_erji_types")){ + queryWrapper.eq("super_id",dictionary.getSuperId()); // 如果是二级类型,添加父ID条件 + } + + logger.info("sql语句:"+queryWrapper.getSqlSegment()); // 记录SQL语句 + DictionaryEntity dictionaryEntity = dictionaryService.selectOne(queryWrapper); // 查询是否已存在相同数据 + if(dictionaryEntity==null){ + dictionary.setCreateTime(new Date()); // 设置创建时间 + dictionaryService.insert(dictionary); // 插入新数据 + // 字典表新增数据,把数据再重新查出,放入监听器中 + List dictionaryEntities = dictionaryService.selectList(new EntityWrapper()); // 查询所有字典数据 + ServletContext servletContext = request.getServletContext(); // 获取ServletContext + Map> map = new HashMap<>(); // 创建字典映射 + for(DictionaryEntity d :dictionaryEntities){ + Map m = map.get(d.getDicCode()); // 获取当前字典代码的映射 + if(m ==null || m.isEmpty()){ + m = new HashMap<>(); // 如果不存在则创建新映射 + } + m.put(d.getCodeIndex(),d.getIndexName()); // 添加编码和名称到映射 + map.put(d.getDicCode(),m); // 将映射放入字典映射中 + } + servletContext.setAttribute("dictionaryMap",map); // 将字典映射存入ServletContext + return R.ok(); // 返回成功响应 + }else { + return R.error(511,"表中有相同数据"); // 返回错误响应 + } + } + + + //后端修改 + @RequestMapping("/update") // 处理更新请求 + public R update(@RequestBody DictionaryEntity dictionary, HttpServletRequest request) throws NoSuchFieldException, ClassNotFoundException, IllegalAccessException, InstantiationException { + logger.debug("update方法:,,Controller:{},,dictionary:{}",this.getClass().getName(),dictionary.toString()); // 记录日志 + DictionaryEntity oldDictionaryEntity = dictionaryService.selectById(dictionary.getId()); // 查询原数据 + + String role = String.valueOf(request.getSession().getAttribute("role")); // 获取用户角色 +// if(false) +// return R.error(511,"永远不会进入"); + + dictionaryService.updateById(dictionary); // 根据ID更新数据 + // 如果字典表修改数据的话,把数据再重新查出,放入监听器中 + List dictionaryEntities = dictionaryService.selectList(new EntityWrapper()); // 查询所有字典数据 + ServletContext servletContext = request.getServletContext(); // 获取ServletContext + Map> map = new HashMap<>(); // 创建字典映射 + for(DictionaryEntity d :dictionaryEntities){ + Map m = map.get(d.getDicCode()); // 获取当前字典代码的映射 + if(m ==null || m.isEmpty()){ + m = new HashMap<>(); // 如果不存在则创建新映射 + } + m.put(d.getCodeIndex(),d.getIndexName()); // 添加编码和名称到映射 + map.put(d.getDicCode(),m); // 将映射放入字典映射中 + } + servletContext.setAttribute("dictionaryMap",map); // 将字典映射存入ServletContext + return R.ok(); // 返回成功响应 + } + + + //删除 + @RequestMapping("/delete") // 处理删除请求 + public R delete(@RequestBody Integer[] ids, HttpServletRequest request){ + logger.debug("delete:,,Controller:{},,ids:{}",this.getClass().getName(),ids.toString()); // 记录日志 + List oldDictionaryList =dictionaryService.selectBatchIds(Arrays.asList(ids)); // 查询要删除的数据 + dictionaryService.deleteBatchIds(Arrays.asList(ids)); // 批量删除数据 + + return R.ok(); // 返回成功响应 + } + + + //最大值 + @RequestMapping("/maxCodeIndex") // 处理获取最大编码请求 + public R maxCodeIndex(@RequestBody DictionaryEntity dictionary){ + logger.debug("maxCodeIndex:,,Controller:{},,dictionary:{}",this.getClass().getName(),dictionary.toString()); // 记录日志 + List descs = new ArrayList<>(); // 创建排序字段列表 + descs.add("code_index"); // 添加排序字段 + Wrapper queryWrapper = new EntityWrapper() + .eq("dic_code", dictionary.getDicCode()) // 构建查询条件 + .orderDesc(descs); // 添加排序条件 + logger.info("sql语句:"+queryWrapper.getSqlSegment()); // 记录SQL语句 + List dictionaryEntityList = dictionaryService.selectList(queryWrapper); // 查询数据 + if(dictionaryEntityList.size()>0 ){ + return R.ok().put("maxCodeIndex",dictionaryEntityList.get(0).getCodeIndex()+1); // 返回最大编码加1 + }else{ + return R.ok().put("maxCodeIndex",1); // 返回默认值1 + } + } + + + //批量上传 + @RequestMapping("/batchInsert") // 处理批量上传请求 + public R save(String fileName, HttpServletRequest request){ + logger.debug("batchInsert方法:,,Controller:{},,fileName:{}",this.getClass().getName(),fileName); // 记录日志 + Integer yonghuId = Integer.valueOf(String.valueOf(request.getSession().getAttribute("userId"))); // 获取用户ID + SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); // 创建日期格式化对象 + try { + List dictionaryList = new ArrayList<>(); // 创建字典数据列表 + Map> seachFields= new HashMap<>(); // 创建查询字段映射 + Date date = new Date(); // 获取当前时间 + int lastIndexOf = fileName.lastIndexOf("."); // 获取文件后缀名位置 + if(lastIndexOf == -1){ + return R.error(511,"该文件没有后缀"); // 返回错误响应 + }else{ + String suffix = fileName.substring(lastIndexOf); // 获取文件后缀名 + if(!".xls".equals(suffix)){ + return R.error(511,"只支持后缀为xls的excel文件"); // 返回错误响应 + }else{ + URL resource = this.getClass().getClassLoader().getResource("static/upload/" + fileName); // 获取文件路径 + File file = new File(resource.getFile()); // 创建文件对象 + if(!file.exists()){ + return R.error(511,"找不到上传文件,请联系管理员"); // 返回错误响应 + }else{ + List> dataList = PoiUtil.poiImport(file.getPath()); // 读取Excel文件 + dataList.remove(0); // 删除第一行标题 + for(List data:dataList){ + // 循环处理每一行数据 + DictionaryEntity dictionaryEntity = new DictionaryEntity(); // 创建字典实体 +// dictionaryEntity.setDicCode(data.get(0)); // 设置字段代码(示例) +// dictionaryEntity.setDicName(data.get(0)); // 设置字段名(示例) +// dictionaryEntity.setCodeIndex(Integer.valueOf(data.get(0))); // 设置编码(示例) +// dictionaryEntity.setIndexName(data.get(0)); // 设置编码名(示例) +// dictionaryEntity.setSuperId(Integer.valueOf(data.get(0))); // 设置父ID(示例) +// dictionaryEntity.setBeizhu(data.get(0)); // 设置备注(示例) +// dictionaryEntity.setCreateTime(date); // 设置创建时间(示例) + dictionaryList.add(dictionaryEntity); // 添加到列表 + } + dictionaryService.insertBatch(dictionaryList); // 批量插入数据 + return R.ok(); // 返回成功响应 +>>>>>>> develop } } } }catch (Exception e){ +<<<<<<< HEAD e.printStackTrace(); return R.error(511,"批量插入数据异常,请联系管理员"); } @@ -281,3 +561,10 @@ public class DictionaryController { } +======= + e.printStackTrace(); // 打印异常堆栈 + return R.error(511,"批量插入数据异常,请联系管理员"); // 返回错误响应 + } + } +} +>>>>>>> develop diff --git a/src/main/java/com/controller/FileController.java b/src/main/java/com/controller/FileController.java index 7bd4f8e..70c3d57 100644 --- a/src/main/java/com/controller/FileController.java +++ b/src/main/java/com/controller/FileController.java @@ -1,3 +1,4 @@ +<<<<<<< HEAD package com.controller; import java.io.File; @@ -107,4 +108,164 @@ public class FileController{ return new ResponseEntity(HttpStatus.INTERNAL_SERVER_ERROR); } +======= +package com.controller; // 定义包路径 + +// 文件操作相关类 +import java.io.File; +// 文件未找到异常 +import java.io.FileNotFoundException; +// IO异常 +import java.io.IOException; +// 数组工具类 +import java.util.Arrays; +// 日期类 +import java.util.Date; +// 哈希Map +import java.util.HashMap; +// 列表接口 +import java.util.List; +// Map接口 +import java.util.Map; +// 随机数类 +import java.util.Random; +// UUID类 +import java.util.UUID; + +// Apache Commons IO工具类 +import org.apache.commons.io.FileUtils; +// Apache Commons字符串工具 +import org.apache.commons.lang3.StringUtils; +// Spring自动注入注解 +import org.springframework.beans.factory.annotation.Autowired; +// HTTP头定义 +import org.springframework.http.HttpHeaders; +// HTTP状态码 +import org.springframework.http.HttpStatus; +// 媒体类型定义 +import org.springframework.http.MediaType; +// ResponseEntity响应实体 +import org.springframework.http.ResponseEntity; +// Spring资源工具 +import org.springframework.util.ResourceUtils; +// Spring路径变量注解 +import org.springframework.web.bind.annotation.PathVariable; +// Spring请求体注解 +import org.springframework.web.bind.annotation.RequestBody; +// Spring请求映射注解 +import org.springframework.web.bind.annotation.RequestMapping; +// Spring请求参数注解 +import org.springframework.web.bind.annotation.RequestParam; +// Spring REST控制器注解 +import org.springframework.web.bind.annotation.RestController; +// Spring文件上传类 +import org.springframework.web.multipart.MultipartFile; + +// 自定义忽略鉴权注解 +import com.annotation.IgnoreAuth; +// MyBatis Plus实体包装器 +import com.baomidou.mybatisplus.mapper.EntityWrapper; +// 配置实体类 +import com.entity.ConfigEntity; +// 自定义异常类 +import com.entity.EIException; +// 配置服务接口 +import com.service.ConfigService; +// 自定义返回结果类 +import com.utils.R; + + + //上传文件映射表 + //文件上传下载控制器 +@RestController // 声明为RESTful控制器 +@RequestMapping("file") // 基础请求路径映射 +@SuppressWarnings({"unchecked","rawtypes"}) // 抑制警告 +public class FileController{ + @Autowired // 自动注入配置服务 + private ConfigService configService; + + + //上传文件 + //@param file 上传的文件对象 + //@param type 文件类型标识 + //@return 上传结果 + //* @throws Exception 可能抛出的异常 + + @RequestMapping("/upload") // 文件上传请求映射 + public R upload(@RequestParam("file") MultipartFile file,String type) throws Exception { + if (file.isEmpty()) { // 检查文件是否为空 + throw new EIException("上传文件不能为空"); // 抛出文件为空异常 + } + // 获取文件扩展名 + String fileExt = file.getOriginalFilename().substring(file.getOriginalFilename().lastIndexOf(".")+1); + // 获取静态资源路径 + File path = new File(ResourceUtils.getURL("classpath:static").getPath()); + if(!path.exists()) { // 如果路径不存在 + path = new File(""); // 使用当前路径 + } + // 创建上传目录 + File upload = new File(path.getAbsolutePath(),"/upload/"); + if(!upload.exists()) { // 如果目录不存在 + upload.mkdirs(); // 创建目录 + } + // 生成唯一文件名(时间戳+扩展名) + String fileName = new Date().getTime()+"."+fileExt; + // 创建目标文件 + File dest = new File(upload.getAbsolutePath()+"/"+fileName); + // 传输文件到目标位置 + file.transferTo(dest); + // 如果是类型1的文件(如头像文件) + if(StringUtils.isNotBlank(type) && type.equals("1")) { + // 查询配置表中faceFile配置 + ConfigEntity configEntity = configService.selectOne(new EntityWrapper().eq("name", "faceFile")); + if(configEntity==null) { // 如果配置不存在 + configEntity = new ConfigEntity(); // 创建新配置 + configEntity.setName("faceFile"); // 设置配置名 + configEntity.setValue(fileName); // 设置文件名 + } else { + configEntity.setValue(fileName); // 更新文件名 + } + // 保存或更新配置 + configService.insertOrUpdate(configEntity); + } + // 返回成功结果和文件名 + return R.ok().put("file", fileName); + } + + + //下载文件 + //@param fileName 要下载的文件名 + // @return 文件下载响应 + + @IgnoreAuth // 忽略权限验证 + @RequestMapping("/download") // 文件下载请求映射 + public ResponseEntity download(@RequestParam String fileName) { + try { + // 获取静态资源路径 + File path = new File(ResourceUtils.getURL("classpath:static").getPath()); + if(!path.exists()) { // 如果路径不存在 + path = new File(""); // 使用当前路径 + } + // 获取上传目录 + File upload = new File(path.getAbsolutePath(),"/upload/"); + if(!upload.exists()) { // 如果目录不存在 + upload.mkdirs(); // 创建目录 + } + // 构建文件对象 + File file = new File(upload.getAbsolutePath()+"/"+fileName); + if(file.exists()){ // 如果文件存在 + // 设置HTTP响应头 + HttpHeaders headers = new HttpHeaders(); + headers.setContentType(MediaType.APPLICATION_OCTET_STREAM); // 设置内容类型为二进制流 + headers.setContentDispositionFormData("attachment", fileName); // 设置内容处置为附件 + // 返回文件内容和响应头 + return new ResponseEntity(FileUtils.readFileToByteArray(file),headers, HttpStatus.CREATED); + } + } catch (IOException e) { // 捕获IO异常 + e.printStackTrace(); // 打印异常堆栈 + } + // 返回服务器错误响应 + return new ResponseEntity(HttpStatus.INTERNAL_SERVER_ERROR); + } +>>>>>>> develop } diff --git a/src/main/java/com/controller/ForumController.java b/src/main/java/com/controller/ForumController.java index bed9f99..a795ef1 100644 --- a/src/main/java/com/controller/ForumController.java +++ b/src/main/java/com/controller/ForumController.java @@ -1,3 +1,4 @@ +<<<<<<< HEAD package com.controller; @@ -38,12 +39,54 @@ import com.alibaba.fastjson.*; * @author * @email */ +======= +package com.controller;// 定义包路径,表示该文件位于com.controller包下 + +import java.io.File; // 导入文件操作类 +import java.math.BigDecimal; // 导入高精度数学计算类 +import java.net.URL; // 导入网络URL处理类 +import java.text.SimpleDateFormat; // 导入日期格式化类 +import com.alibaba.fastjson.JSONObject; // 导入FastJSON的JSON对象类 +import java.util.*; // 导入Java常用工具类(集合、日期等) +import org.springframework.beans.BeanUtils; // 导入Spring Bean属性复制工具类 +import javax.servlet.http.HttpServletRequest; // 导入HTTP请求处理类 +import org.springframework.web.context.ContextLoader; // 导入Spring上下文加载器 +import javax.servlet.ServletContext; // 导入Servlet上下文接口 +import com.service.TokenService; // 导入自定义的Token服务类 +import com.utils.*; // 导入自定义工具类 +import java.lang.reflect.InvocationTargetException; // 导入反射异常类 + +import com.service.DictionaryService; // 导入自定义的字典服务类 +import org.apache.commons.lang3.StringUtils; // 导入Apache字符串工具类 +import com.annotation.IgnoreAuth; // 导入自定义的忽略认证注解 +import org.slf4j.Logger; // 导入日志接口 +import org.slf4j.LoggerFactory; // 导入日志工厂类 +import org.springframework.beans.factory.annotation.Autowired; // 导入Spring自动注入注解 +import org.springframework.stereotype.Controller; // 导入Spring控制器注解 +import org.springframework.web.bind.annotation.*; // 导入Spring Web注解 +import com.baomidou.mybatisplus.mapper.EntityWrapper; // 导入MyBatis Plus查询条件构造器 +import com.baomidou.mybatisplus.mapper.Wrapper; // 导入MyBatis Plus包装器接口 +import com.entity.*; // 导入实体类 +import com.entity.view.*; // 导入视图实体类 +import com.service.*; // 导入服务类 +import com.utils.PageUtils; // 导入分页工具类 +import com.utils.R; // 导入统一返回结果类 +import com.alibaba.fastjson.*; // 导入FastJSON相关类 + + + //健身论坛 + //后端接口 + //@author + //@email + +>>>>>>> develop @RestController @Controller @RequestMapping("/forum") public class ForumController { private static final Logger logger = LoggerFactory.getLogger(ForumController.class); +<<<<<<< HEAD private static final String TABLE_NAME = "forum"; @Autowired @@ -144,10 +187,104 @@ public class ForumController { /** * 后端保存 */ +======= + private static final String TABLE_NAME = "forum"; // 数据库表名 + + @Autowired + private ForumService forumService; // 论坛服务 + + @Autowired + private TokenService tokenService; // token服务 + + @Autowired + private DictionaryService dictionaryService; // 字典服务 + @Autowired + private JianshenkechengService jianshenkechengService; // 健身课程服务 + @Autowired + private JianshenkechengCollectionService jianshenkechengCollectionService; // 课程收藏服务 + @Autowired + private JianshenkechengLiuyanService jianshenkechengLiuyanService; // 课程留言服务 + @Autowired + private JiaolianService jiaolianService; // 教练服务 + @Autowired + private JiaolianYuyueService jiaolianYuyueService; // 教练预约申请服务 + @Autowired + private NewsService newsService; // 健身资讯服务 + @Autowired + private SingleSeachService singleSeachService; // 单页数据服务 + @Autowired + private YonghuService yonghuService; // 用户服务 + @Autowired + private UsersService usersService; // 管理员服务 + + + //后端列表 + @RequestMapping("/page") + public R page(@RequestParam Map params, HttpServletRequest request){ + logger.debug("page方法:,,Controller:{},,params:{}",this.getClass().getName(),JSONObject.toJSONString(params)); + CommonUtil.checkMap(params); // 检查参数 + PageUtils page = forumService.queryPage(params); // 查询分页数据 + + // 字典表数据转换 + List list =(List)page.getList(); + for(ForumView c:list){ + // 修改对应字典表字段 + dictionaryService.dictionaryConvert(c, request); + } + return R.ok().put("data", page); // 返回分页数据 + } + + + //后端详情 + @RequestMapping("/info/{id}") + public R info(@PathVariable("id") Long id, HttpServletRequest request){ + logger.debug("info方法:,,Controller:{},,id:{}",this.getClass().getName(),id); + ForumEntity forum = forumService.selectById(id); // 根据ID查询论坛帖子 + if(forum !=null){ + // entity转view + ForumView view = new ForumView(); + BeanUtils.copyProperties( forum , view ); // 把实体数据重构到view中 + // 级联表 用户 + YonghuEntity yonghu = yonghuService.selectById(forum.getYonghuId()); + if(yonghu != null){ + BeanUtils.copyProperties( yonghu , view ,new String[]{ "id", "createTime", "insertTime", "updateTime", "username", "password", "newMoney", "yonghuId" + , "jiaolianId" + , "usersId"}); // 把级联的数据添加到view中,并排除id和创建时间字段 + view.setYonghuId(yonghu.getId()); + } + // 级联表 教练 + JiaolianEntity jiaolian = jiaolianService.selectById(forum.getJiaolianId()); + if(jiaolian != null){ + BeanUtils.copyProperties( jiaolian , view ,new String[]{ "id", "createTime", "insertTime", "updateTime", "username", "password", "newMoney", "yonghuId" + , "jiaolianId" + , "usersId"}); // 把级联的数据添加到view中,并排除id和创建时间字段 + view.setJiaolianId(jiaolian.getId()); + } + // 级联表 管理员 + UsersEntity users = usersService.selectById(forum.getUsersId()); + if(users != null){ + view.setUsersId(users.getId()); // 设置管理员ID + view.setUusername(users.getUsername()); // 设置管理员用户名 + view.setUpassword(users.getPassword()); // 设置管理员密码 + view.setUrole(users.getRole()); // 设置管理员角色 + view.setUaddtime(users.getAddtime()); // 设置管理员添加时间 + } + // 修改对应字典表字段 + dictionaryService.dictionaryConvert(view, request); + return R.ok().put("data", view); // 返回帖子详情 + }else { + return R.error(511,"查不到数据"); // 查询不到数据返回错误 + } + } + + + //后端保存 +>>>>>>> develop @RequestMapping("/save") public R save(@RequestBody ForumEntity forum, HttpServletRequest request){ logger.debug("save方法:,,Controller:{},,forum:{}",this.getClass().getName(),forum.toString()); +<<<<<<< HEAD String role = String.valueOf(request.getSession().getAttribute("role")); if(false) return R.error(511,"永远不会进入"); @@ -215,11 +352,69 @@ public class ForumController { logger.debug("delete:,,Controller:{},,ids:{}",this.getClass().getName(),ids.toString()); List oldForumList =forumService.selectBatchIds(Arrays.asList(ids));//要删除的数据 forumService.deleteBatchIds(Arrays.asList(ids)); +======= + String role = String.valueOf(request.getSession().getAttribute("role")); // 获取用户角色 + if(false) + return R.error(511,"永远不会进入"); + else if("用户".equals(role)) + forum.setYonghuId(Integer.valueOf(String.valueOf(request.getSession().getAttribute("userId")))); // 设置用户ID + else if("教练".equals(role)) + forum.setJiaolianId(Integer.valueOf(String.valueOf(request.getSession().getAttribute("userId")))); // 设置教练ID + else if("管理员".equals(role)) + forum.setUsersId(Integer.valueOf(String.valueOf(request.getSession().getAttribute("userId")))); // 设置管理员ID + + Wrapper queryWrapper = new EntityWrapper() + .eq("forum_name", forum.getForumName()) // 帖子标题 + .eq("yonghu_id", forum.getYonghuId()) // 用户ID + .eq("jiaolian_id", forum.getJiaolianId()) // 教练ID + .eq("users_id", forum.getUsersId()) // 管理员ID + .eq("super_ids", forum.getSuperIds()) // 父ID + .eq("forum_state_types", forum.getForumStateTypes()) // 帖子状态 + ; + + logger.info("sql语句:"+queryWrapper.getSqlSegment()); + ForumEntity forumEntity = forumService.selectOne(queryWrapper); // 查询是否已存在相同数据 + if(forumEntity==null){ + forum.setInsertTime(new Date()); // 设置插入时间 + forum.setCreateTime(new Date()); // 设置创建时间 + forumService.insert(forum); // 插入新数据 + return R.ok(); + }else { + return R.error(511,"表中有相同数据"); // 数据已存在返回错误 + } + } + + + //后端修改 + @RequestMapping("/update") + public R update(@RequestBody ForumEntity forum, HttpServletRequest request) throws NoSuchFieldException, ClassNotFoundException, IllegalAccessException, InstantiationException { + logger.debug("update方法:,,Controller:{},,forum:{}",this.getClass().getName(),forum.toString()); + ForumEntity oldForumEntity = forumService.selectById(forum.getId()); // 查询原先数据 + + String role = String.valueOf(request.getSession().getAttribute("role")); // 获取用户角色 + if("".equals(forum.getForumContent()) || "null".equals(forum.getForumContent())){ + forum.setForumContent(null); // 处理空内容 + } + forum.setUpdateTime(new Date()); // 设置更新时间 + forumService.updateById(forum); // 根据ID更新数据 return R.ok(); } + //删除 + @RequestMapping("/delete") + public R delete(@RequestBody Integer[] ids, HttpServletRequest request){ + logger.debug("delete:,,Controller:{},,ids:{}",this.getClass().getName(),ids.toString()); + List oldForumList =forumService.selectBatchIds(Arrays.asList(ids)); // 查询要删除的数据 + forumService.deleteBatchIds(Arrays.asList(ids)); // 批量删除 +>>>>>>> develop + + return R.ok(); + } + + +<<<<<<< HEAD /** * 批量上传 */ @@ -268,6 +463,39 @@ public class ForumController { } //查询是否重复 +======= + //批量上传 + @RequestMapping("/batchInsert") + public R save( String fileName, HttpServletRequest request){ + logger.debug("batchInsert方法:,,Controller:{},,fileName:{}",this.getClass().getName(),fileName); + Integer yonghuId = Integer.valueOf(String.valueOf(request.getSession().getAttribute("userId"))); // 获取用户ID + SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); + try { + List forumList = new ArrayList<>(); // 存储上传的数据 + Map> seachFields= new HashMap<>(); // 要查询的字段 + Date date = new Date(); + int lastIndexOf = fileName.lastIndexOf("."); + if(lastIndexOf == -1){ + return R.error(511,"该文件没有后缀"); // 文件无后缀返回错误 + }else{ + String suffix = fileName.substring(lastIndexOf); + if(!".xls".equals(suffix)){ + return R.error(511,"只支持后缀为xls的excel文件"); // 文件格式不正确返回错误 + }else{ + URL resource = this.getClass().getClassLoader().getResource("static/upload/" + fileName); // 获取文件路径 + File file = new File(resource.getFile()); + if(!file.exists()){ + return R.error(511,"找不到上传文件,请联系管理员"); // 文件不存在返回错误 + }else{ + List> dataList = PoiUtil.poiImport(file.getPath()); // 读取xls文件 + dataList.remove(0); // 删除第一行提示信息 + for(List data:dataList){ + // 循环处理每行数据 + ForumEntity forumEntity = new ForumEntity(); + forumList.add(forumEntity); // 添加到列表 + } + // 批量插入数据 +>>>>>>> develop forumService.insertBatch(forumList); return R.ok(); } @@ -275,6 +503,7 @@ public class ForumController { } }catch (Exception e){ e.printStackTrace(); +<<<<<<< HEAD return R.error(511,"批量插入数据异常,请联系管理员"); } } @@ -286,10 +515,20 @@ public class ForumController { * 前端列表 */ @IgnoreAuth +======= + return R.error(511,"批量插入数据异常,请联系管理员"); // 异常处理 + } + } + + // 前端列表 + + @IgnoreAuth // 忽略认证 +>>>>>>> develop @RequestMapping("/list") public R list(@RequestParam Map params, HttpServletRequest request){ logger.debug("list方法:,,Controller:{},,params:{}",this.getClass().getName(),JSONObject.toJSONString(params)); +<<<<<<< HEAD CommonUtil.checkMap(params); PageUtils page = forumService.queryPage(params); @@ -351,10 +590,70 @@ public class ForumController { /** * 前端保存 */ +======= + CommonUtil.checkMap(params); // 检查参数 + PageUtils page = forumService.queryPage(params); // 查询分页数据 + + // 字典表数据转换 + List list =(List)page.getList(); + for(ForumView c:list) + dictionaryService.dictionaryConvert(c, request); // 修改对应字典表字段 + + return R.ok().put("data", page); // 返回分页数据 + } + + + //前端详情 + @RequestMapping("/detail/{id}") + public R detail(@PathVariable("id") Integer id, HttpServletRequest request){ + logger.debug("detail方法:,,Controller:{},,id:{}",this.getClass().getName(),id); + ForumEntity forum = forumService.selectById(id); // 根据ID查询帖子 + if(forum !=null){ + // entity转view + ForumView view = new ForumView(); + BeanUtils.copyProperties( forum , view ); // 把实体数据重构到view中 + + // 级联表用户 + YonghuEntity yonghu = yonghuService.selectById(forum.getYonghuId()); + if(yonghu != null){ + BeanUtils.copyProperties( yonghu , view ,new String[]{ "id", "createTime", "insertTime", "updateTime", "username", "password", "newMoney", "yonghuId" + , "jiaolianId" + , "usersId"}); // 把级联的数据添加到view中,并排除id和创建时间字段 + view.setYonghuId(yonghu.getId()); + } + // 级联表教练 + JiaolianEntity jiaolian = jiaolianService.selectById(forum.getJiaolianId()); + if(jiaolian != null){ + BeanUtils.copyProperties( jiaolian , view ,new String[]{ "id", "createTime", "insertTime", "updateTime", "username", "password", "newMoney", "yonghuId" + , "jiaolianId" + , "usersId"}); // 把级联的数据添加到view中,并排除id和创建时间字段 + view.setJiaolianId(jiaolian.getId()); + } + // 级联表管理员 + UsersEntity users = usersService.selectById(forum.getUsersId()); + if(users != null){ + view.setUsersId(users.getId()); // 设置管理员ID + view.setUusername(users.getUsername()); // 设置管理员用户名 + view.setUpassword(users.getPassword()); // 设置管理员密码 + view.setUrole(users.getRole()); // 设置管理员角色 + view.setUaddtime(users.getAddtime()); // 设置管理员添加时间 + } + // 修改对应字典表字段 + dictionaryService.dictionaryConvert(view, request); + return R.ok().put("data", view); // 返回帖子详情 + }else { + return R.error(511,"查不到数据"); // 查询不到数据返回错误 + } + } + + + //前端保存 +>>>>>>> develop @RequestMapping("/add") public R add(@RequestBody ForumEntity forum, HttpServletRequest request){ logger.debug("add方法:,,Controller:{},,forum:{}",this.getClass().getName(),forum.toString()); Wrapper queryWrapper = new EntityWrapper() +<<<<<<< HEAD .eq("forum_name", forum.getForumName()) .eq("yonghu_id", forum.getYonghuId()) .eq("jiaolian_id", forum.getJiaolianId()) @@ -378,3 +677,25 @@ public class ForumController { } +======= + .eq("forum_name", forum.getForumName()) // 帖子标题 + .eq("yonghu_id", forum.getYonghuId()) // 用户ID + .eq("jiaolian_id", forum.getJiaolianId()) // 教练ID + .eq("users_id", forum.getUsersId()) // 管理员ID + .eq("super_ids", forum.getSuperIds()) // 父ID + .eq("forum_state_types", forum.getForumStateTypes()) // 帖子状态 + ; + logger.info("sql语句:"+queryWrapper.getSqlSegment()); + ForumEntity forumEntity = forumService.selectOne(queryWrapper); // 查询是否已存在相同数据 + if(forumEntity==null){ + forum.setInsertTime(new Date()); // 设置插入时间 + forum.setCreateTime(new Date()); // 设置创建时间 + forumService.insert(forum); // 插入新数据 + + return R.ok(); + }else { + return R.error(511,"表中有相同数据"); // 数据已存在返回错误 + } + } +} +>>>>>>> develop diff --git a/src/main/java/com/controller/JianshenkechengCollectionController.java b/src/main/java/com/controller/JianshenkechengCollectionController.java index 4268dc2..0a39ed0 100644 --- a/src/main/java/com/controller/JianshenkechengCollectionController.java +++ b/src/main/java/com/controller/JianshenkechengCollectionController.java @@ -1,3 +1,4 @@ +<<<<<<< HEAD package com.controller; @@ -243,16 +244,238 @@ public class JianshenkechengCollectionController { //查询是否重复 jianshenkechengCollectionService.insertBatch(jianshenkechengCollectionList); return R.ok(); +======= +package com.controller; // 定义包路径,表示该文件位于com.controller包下 + +import java.io.File; // 导入文件操作类 +import java.math.BigDecimal; // 导入高精度数学计算类 +import java.net.URL; // 导入网络URL处理类 +import java.text.SimpleDateFormat; // 导入日期格式化类 +import com.alibaba.fastjson.JSONObject; // 导入FastJSON的JSON对象类 +import java.util.*; // 导入Java常用工具类(集合、日期等) +import org.springframework.beans.BeanUtils; // 导入Spring Bean属性复制工具类 +import javax.servlet.http.HttpServletRequest; // 导入HTTP请求处理类 +import org.springframework.web.context.ContextLoader; // 导入Spring上下文加载器 +import javax.servlet.ServletContext; // 导入Servlet上下文接口 +import com.service.TokenService; // 导入自定义的Token服务类 +import com.utils.*; // 导入自定义工具类 +import java.lang.reflect.InvocationTargetException; // 导入反射异常类 + +import com.service.DictionaryService; // 导入自定义的字典服务类 +import org.apache.commons.lang3.StringUtils; // 导入Apache字符串工具类 +import com.annotation.IgnoreAuth; // 导入自定义的忽略认证注解 +import org.slf4j.Logger; // 导入日志接口 +import org.slf4j.LoggerFactory; // 导入日志工厂类 +import org.springframework.beans.factory.annotation.Autowired; // 导入Spring自动注入注解 +import org.springframework.stereotype.Controller; // 导入Spring控制器注解 +import org.springframework.web.bind.annotation.*; // 导入Spring Web注解 +import com.baomidou.mybatisplus.mapper.EntityWrapper; // 导入MyBatis Plus查询条件构造器 +import com.baomidou.mybatisplus.mapper.Wrapper; // 导入MyBatis Plus包装器接口 +import com.entity.*; // 导入实体类 +import com.entity.view.*; // 导入视图实体类 +import com.service.*; // 导入服务类 +import com.utils.PageUtils; // 导入分页工具类 +import com.utils.R; // 导入统一返回结果类 +import com.alibaba.fastjson.*; // 导入FastJSON相关类 + + + //课程收藏 + //后端接口 + //@author + // @email + +@RestController // 标识为RESTful控制器 +@Controller // 标识为Spring控制器 +@RequestMapping("/jianshenkechengCollection") // 定义请求映射路径 +public class JianshenkechengCollectionController { + private static final Logger logger = LoggerFactory.getLogger(JianshenkechengCollectionController.class); // 日志记录器 + + private static final String TABLE_NAME = "jianshenkechengCollection"; // 数据库表名 + + @Autowired + private JianshenkechengCollectionService jianshenkechengCollectionService; // 课程收藏服务 + + @Autowired + private TokenService tokenService; // Token服务 + + @Autowired + private DictionaryService dictionaryService; // 字典服务 + @Autowired + private ForumService forumService; // 健身论坛服务 + @Autowired + private JianshenkechengService jianshenkechengService; // 健身课程服务 + @Autowired + private JianshenkechengLiuyanService jianshenkechengLiuyanService; // 课程留言服务 + @Autowired + private JiaolianService jiaolianService; // 教练服务 + @Autowired + private JiaolianYuyueService jiaolianYuyueService; // 教练预约申请服务 + @Autowired + private NewsService newsService; // 健身资讯服务 + @Autowired + private SingleSeachService singleSeachService; // 单页数据服务 + @Autowired + private YonghuService yonghuService; // 用户服务 + @Autowired + private UsersService usersService; // 管理员服务 + + + //后端列表 + @RequestMapping("/page") // 处理分页请求 + public R page(@RequestParam Map params, HttpServletRequest request){ + logger.debug("page方法:,,Controller:{},,params:{}",this.getClass().getName(),JSONObject.toJSONString(params)); // 记录日志 + String role = String.valueOf(request.getSession().getAttribute("role")); // 获取用户角色 + if(false) + return R.error(511,"永不会进入"); // 永远不会执行的代码 + else if("用户".equals(role)) + params.put("yonghuId",request.getSession().getAttribute("userId")); // 如果是用户角色,添加用户ID参数 + else if("教练".equals(role)) + params.put("jiaolianId",request.getSession().getAttribute("userId")); // 如果是教练角色,添加教练ID参数 + CommonUtil.checkMap(params); // 检查参数 + PageUtils page = jianshenkechengCollectionService.queryPage(params); // 查询分页数据 + + // 字典表数据转换 + List list =(List)page.getList(); + for(JianshenkechengCollectionView c:list){ + // 修改对应字典表字段 + dictionaryService.dictionaryConvert(c, request); + } + return R.ok().put("data", page); // 返回分页数据 + } + + + //后端详情 + @RequestMapping("/info/{id}") // 处理详情请求 + public R info(@PathVariable("id") Long id, HttpServletRequest request){ + logger.debug("info方法:,,Controller:{},,id:{}",this.getClass().getName(),id); // 记录日志 + JianshenkechengCollectionEntity jianshenkechengCollection = jianshenkechengCollectionService.selectById(id); // 根据ID查询收藏记录 + if(jianshenkechengCollection !=null){ + // entity转view + JianshenkechengCollectionView view = new JianshenkechengCollectionView(); + BeanUtils.copyProperties( jianshenkechengCollection , view ); // 把实体数据重构到view中 + // 级联表 健身课程 + JianshenkechengEntity jianshenkecheng = jianshenkechengService.selectById(jianshenkechengCollection.getJianshenkechengId()); + if(jianshenkecheng != null){ + BeanUtils.copyProperties( jianshenkecheng , view ,new String[]{ "id", "createTime", "insertTime", "updateTime", "username", "password", "newMoney", "yonghuId"}); // 把级联的数据添加到view中,并排除id和创建时间字段 + view.setJianshenkechengId(jianshenkecheng.getId()); + } + // 级联表 用户 + YonghuEntity yonghu = yonghuService.selectById(jianshenkechengCollection.getYonghuId()); + if(yonghu != null){ + BeanUtils.copyProperties( yonghu , view ,new String[]{ "id", "createTime", "insertTime", "updateTime", "username", "password", "newMoney", "yonghuId"}); // 把级联的数据添加到view中,并排除id和创建时间字段 + view.setYonghuId(yonghu.getId()); + } + // 修改对应字典表字段 + dictionaryService.dictionaryConvert(view, request); + return R.ok().put("data", view); // 返回详情数据 + }else { + return R.error(511,"查不到数据"); // 查询不到数据返回错误 + } + } + + + //后端保存 + @RequestMapping("/save") // 处理保存请求 + public R save(@RequestBody JianshenkechengCollectionEntity jianshenkechengCollection, HttpServletRequest request){ + logger.debug("save方法:,,Controller:{},,jianshenkechengCollection:{}",this.getClass().getName(),jianshenkechengCollection.toString()); // 记录日志 + + String role = String.valueOf(request.getSession().getAttribute("role")); // 获取用户角色 + if(false) + return R.error(511,"永远不会进入"); // 永远不会执行的代码 + else if("用户".equals(role)) + jianshenkechengCollection.setYonghuId(Integer.valueOf(String.valueOf(request.getSession().getAttribute("userId")))); // 如果是用户角色,设置用户ID + + Wrapper queryWrapper = new EntityWrapper() + .eq("jianshenkecheng_id", jianshenkechengCollection.getJianshenkechengId()) // 健身课程ID + .eq("yonghu_id", jianshenkechengCollection.getYonghuId()) // 用户ID + .eq("jianshenkecheng_collection_types", jianshenkechengCollection.getJianshenkechengCollectionTypes()) // 收藏类型 + ; + + logger.info("sql语句:"+queryWrapper.getSqlSegment()); // 记录SQL语句 + JianshenkechengCollectionEntity jianshenkechengCollectionEntity = jianshenkechengCollectionService.selectOne(queryWrapper); // 查询是否已存在相同数据 + if(jianshenkechengCollectionEntity==null){ + jianshenkechengCollection.setInsertTime(new Date()); // 设置插入时间 + jianshenkechengCollection.setCreateTime(new Date()); // 设置创建时间 + jianshenkechengCollectionService.insert(jianshenkechengCollection); // 插入新数据 + return R.ok(); // 返回成功 + }else { + return R.error(511,"表中有相同数据"); // 数据已存在返回错误 + } + } + + + //后端修改 + @RequestMapping("/update") // 处理更新请求 + public R update(@RequestBody JianshenkechengCollectionEntity jianshenkechengCollection, HttpServletRequest request) throws NoSuchFieldException, ClassNotFoundException, IllegalAccessException, InstantiationException { + logger.debug("update方法:,,Controller:{},,jianshenkechengCollection:{}",this.getClass().getName(),jianshenkechengCollection.toString()); // 记录日志 + JianshenkechengCollectionEntity oldJianshenkechengCollectionEntity = jianshenkechengCollectionService.selectById(jianshenkechengCollection.getId()); // 查询原先数据 + + jianshenkechengCollectionService.updateById(jianshenkechengCollection); // 根据ID更新数据 + return R.ok(); // 返回成功 + } + + + //删除 + @RequestMapping("/delete") // 处理删除请求 + public R delete(@RequestBody Integer[] ids, HttpServletRequest request){ + logger.debug("delete:,,Controller:{},,ids:{}",this.getClass().getName(),ids.toString()); // 记录日志 + List oldJianshenkechengCollectionList =jianshenkechengCollectionService.selectBatchIds(Arrays.asList(ids)); // 查询要删除的数据 + jianshenkechengCollectionService.deleteBatchIds(Arrays.asList(ids)); // 批量删除 + + return R.ok(); // 返回成功 + } + + + //批量上传 + @RequestMapping("/batchInsert") // 处理批量上传请求 + public R save( String fileName, HttpServletRequest request){ + logger.debug("batchInsert方法:,,Controller:{},,fileName:{}",this.getClass().getName(),fileName); // 记录日志 + Integer yonghuId = Integer.valueOf(String.valueOf(request.getSession().getAttribute("userId"))); // 获取用户ID + SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); // 创建日期格式化对象 + try { + List jianshenkechengCollectionList = new ArrayList<>(); // 创建收藏记录列表 + Map> seachFields= new HashMap<>(); // 创建查询字段映射 + Date date = new Date(); // 当前时间 + int lastIndexOf = fileName.lastIndexOf("."); // 获取文件后缀位置 + if(lastIndexOf == -1){ + return R.error(511,"该文件没有后缀"); // 文件无后缀返回错误 + }else{ + String suffix = fileName.substring(lastIndexOf); // 获取文件后缀 + if(!".xls".equals(suffix)){ + return R.error(511,"只支持后缀为xls的excel文件"); // 文件格式不正确返回错误 + }else{ + URL resource = this.getClass().getClassLoader().getResource("static/upload/" + fileName); // 获取文件路径 + File file = new File(resource.getFile()); // 创建文件对象 + if(!file.exists()){ + return R.error(511,"找不到上传文件,请联系管理员"); // 文件不存在返回错误 + }else{ + List> dataList = PoiUtil.poiImport(file.getPath()); // 读取xls文件 + dataList.remove(0); // 删除第一行提示信息 + for(List data:dataList){ + // 循环处理每行数据 + JianshenkechengCollectionEntity jianshenkechengCollectionEntity = new JianshenkechengCollectionEntity(); + jianshenkechengCollectionList.add(jianshenkechengCollectionEntity); // 添加到列表 + } + // 批量插入数据 + jianshenkechengCollectionService.insertBatch(jianshenkechengCollectionList); + return R.ok(); // 返回成功 +>>>>>>> develop } } } }catch (Exception e){ +<<<<<<< HEAD e.printStackTrace(); return R.error(511,"批量插入数据异常,请联系管理员"); +======= + e.printStackTrace(); // 打印异常堆栈 + return R.error(511,"批量插入数据异常,请联系管理员"); // 异常处理 +>>>>>>> develop } } +<<<<<<< HEAD /** @@ -336,3 +559,76 @@ public class JianshenkechengCollectionController { } +======= + //前端列表 + @IgnoreAuth // 忽略认证 + @RequestMapping("/list") // 处理列表请求 + public R list(@RequestParam Map params, HttpServletRequest request){ + logger.debug("list方法:,,Controller:{},,params:{}",this.getClass().getName(),JSONObject.toJSONString(params)); // 记录日志 + + CommonUtil.checkMap(params); // 检查参数 + PageUtils page = jianshenkechengCollectionService.queryPage(params); // 查询分页数据 + + // 字典表数据转换 + List list =(List)page.getList(); + for(JianshenkechengCollectionView c:list) + dictionaryService.dictionaryConvert(c, request); // 修改对应字典表字段 + + return R.ok().put("data", page); // 返回分页数据 + } + + + //前端详情 + @RequestMapping("/detail/{id}") // 处理详情请求 + public R detail(@PathVariable("id") Integer id, HttpServletRequest request){ + logger.debug("detail方法:,,Controller:{},,id:{}",this.getClass().getName(),id); // 记录日志 + JianshenkechengCollectionEntity jianshenkechengCollection = jianshenkechengCollectionService.selectById(id); // 根据ID查询收藏记录 + if(jianshenkechengCollection !=null){ + // entity转view + JianshenkechengCollectionView view = new JianshenkechengCollectionView(); + BeanUtils.copyProperties( jianshenkechengCollection , view ); // 把实体数据重构到view中 + + // 级联表健身课程 + JianshenkechengEntity jianshenkecheng = jianshenkechengService.selectById(jianshenkechengCollection.getJianshenkechengId()); + if(jianshenkecheng != null){ + BeanUtils.copyProperties( jianshenkecheng , view ,new String[]{ "id", "createTime", "insertTime", "updateTime", "username", "password", "newMoney", "yonghuId"}); // 把级联的数据添加到view中,并排除id和创建时间字段 + view.setJianshenkechengId(jianshenkecheng.getId()); + } + // 级联表用户 + YonghuEntity yonghu = yonghuService.selectById(jianshenkechengCollection.getYonghuId()); + if(yonghu != null){ + BeanUtils.copyProperties( yonghu , view ,new String[]{ "id", "createTime", "insertTime", "updateTime", "username", "password", "newMoney", "yonghuId"}); // 把级联的数据添加到view中,并排除id和创建时间字段 + view.setYonghuId(yonghu.getId()); + } + // 修改对应字典表字段 + dictionaryService.dictionaryConvert(view, request); + return R.ok().put("data", view); // 返回详情数据 + }else { + return R.error(511,"查不到数据"); // 查询不到数据返回错误 + } + } + + + //前端保存 + @RequestMapping("/add") // 处理添加请求 + public R add(@RequestBody JianshenkechengCollectionEntity jianshenkechengCollection, HttpServletRequest request){ + logger.debug("add方法:,,Controller:{},,jianshenkechengCollection:{}",this.getClass().getName(),jianshenkechengCollection.toString()); // 记录日志 + Wrapper queryWrapper = new EntityWrapper() + .eq("jianshenkecheng_id", jianshenkechengCollection.getJianshenkechengId()) // 健身课程ID + .eq("yonghu_id", jianshenkechengCollection.getYonghuId()) // 用户ID + .eq("jianshenkecheng_collection_types", jianshenkechengCollection.getJianshenkechengCollectionTypes()) // 收藏类型 + ; + logger.info("sql语句:"+queryWrapper.getSqlSegment()); // 记录SQL语句 + JianshenkechengCollectionEntity jianshenkechengCollectionEntity = jianshenkechengCollectionService.selectOne(queryWrapper); // 查询是否已存在相同数据 + if(jianshenkechengCollectionEntity==null){ + jianshenkechengCollection.setInsertTime(new Date()); // 设置插入时间 + jianshenkechengCollection.setCreateTime(new Date()); // 设置创建时间 + jianshenkechengCollectionService.insert(jianshenkechengCollection); // 插入新数据 + + return R.ok(); // 返回成功 + }else { + return R.error(511,"您已经收藏过了"); // 已经收藏过返回错误 + } + } +} +>>>>>>> develop diff --git a/src/main/java/com/controller/JianshenkechengController.java b/src/main/java/com/controller/JianshenkechengController.java index 8b4235a..d17b73c 100644 --- a/src/main/java/com/controller/JianshenkechengController.java +++ b/src/main/java/com/controller/JianshenkechengController.java @@ -1,3 +1,4 @@ +<<<<<<< HEAD package com.controller; @@ -270,16 +271,260 @@ public class JianshenkechengController { //查询是否重复 jianshenkechengService.insertBatch(jianshenkechengList); return R.ok(); +======= +package com.controller; // 声明包路径,表示该文件位于com.controller包下 + +import java.io.File; // 导入文件操作类 +import java.math.BigDecimal; // 导入高精度数学计算类 +import java.net.URL; // 导入网络URL处理类 +import java.text.SimpleDateFormat; // 导入日期格式化类 +import com.alibaba.fastjson.JSONObject; // 导入FastJSON的JSON对象类 +import java.util.*; // 导入Java常用工具类(集合、日期等) +import org.springframework.beans.BeanUtils; // 导入Spring Bean属性复制工具类 +import javax.servlet.http.HttpServletRequest; // 导入HTTP请求处理类 +import org.springframework.web.context.ContextLoader; // 导入Spring上下文加载器 +import javax.servlet.ServletContext; // 导入Servlet上下文接口 +import com.service.TokenService; // 导入自定义的Token服务类 +import com.utils.*; // 导入自定义工具类 +import java.lang.reflect.InvocationTargetException; // 导入反射异常类 + +import com.service.DictionaryService; // 导入自定义的字典服务类 +import org.apache.commons.lang3.StringUtils; // 导入Apache字符串工具类 +import com.annotation.IgnoreAuth; // 导入自定义的忽略认证注解 +import org.slf4j.Logger; // 导入日志接口 +import org.slf4j.LoggerFactory; // 导入日志工厂类 +import org.springframework.beans.factory.annotation.Autowired; // 导入Spring自动注入注解 +import org.springframework.stereotype.Controller; // 导入Spring控制器注解 +import org.springframework.web.bind.annotation.*; // 导入Spring Web注解 +import com.baomidou.mybatisplus.mapper.EntityWrapper; // 导入MyBatis Plus查询条件构造器 +import com.baomidou.mybatisplus.mapper.Wrapper; // 导入MyBatis Plus包装器接口 +import com.entity.*; // 导入实体类 +import com.entity.view.*; // 导入视图实体类 +import com.service.*; // 导入服务类 +import com.utils.PageUtils; // 导入分页工具类 +import com.utils.R; // 导入统一返回结果类 +import com.alibaba.fastjson.*; // 导入FastJSON相关类 + + + // 健身课程 + //后端接口 + //@author + //@email + +@RestController // 标识为RESTful控制器 +@Controller // 标识为Spring控制器 +@RequestMapping("/jianshenkecheng") // 定义请求映射路径 +public class JianshenkechengController { + private static final Logger logger = LoggerFactory.getLogger(JianshenkechengController.class); // 日志记录器 + + private static final String TABLE_NAME = "jianshenkecheng"; // 数据库表名 + + @Autowired + private JianshenkechengService jianshenkechengService; // 健身课程服务 + + @Autowired + private TokenService tokenService; // Token服务 + + @Autowired + private DictionaryService dictionaryService; // 字典服务 + @Autowired + private ForumService forumService; // 健身论坛服务 + @Autowired + private JianshenkechengCollectionService jianshenkechengCollectionService; // 课程收藏服务 + @Autowired + private JianshenkechengLiuyanService jianshenkechengLiuyanService; // 课程留言服务 + @Autowired + private JiaolianService jiaolianService; // 教练服务 + @Autowired + private JiaolianYuyueService jiaolianYuyueService; // 教练预约申请服务 + @Autowired + private NewsService newsService; // 健身资讯服务 + @Autowired + private SingleSeachService singleSeachService; // 单页数据服务 + @Autowired + private YonghuService yonghuService; // 用户服务 + @Autowired + private UsersService usersService; // 管理员服务 + + + //后端列表 + @RequestMapping("/page") // 处理分页请求 + public R page(@RequestParam Map params, HttpServletRequest request){ + logger.debug("page方法:,,Controller:{},,params:{}",this.getClass().getName(),JSONObject.toJSONString(params)); // 记录日志 + String role = String.valueOf(request.getSession().getAttribute("role")); // 获取用户角色 + if(false) + return R.error(511,"永不会进入"); // 永远不会执行的代码 + else if("用户".equals(role)) + params.put("yonghuId",request.getSession().getAttribute("userId")); // 如果是用户角色,添加用户ID参数 + else if("教练".equals(role)) + params.put("jiaolianId",request.getSession().getAttribute("userId")); // 如果是教练角色,添加教练ID参数 + params.put("dataDeleteStart",1);params.put("dataDeleteEnd",1); // 设置逻辑删除参数 + CommonUtil.checkMap(params); // 检查参数 + PageUtils page = jianshenkechengService.queryPage(params); // 查询分页数据 + + // 字典表数据转换 + List list =(List)page.getList(); + for(JianshenkechengView c:list){ + // 修改对应字典表字段 + dictionaryService.dictionaryConvert(c, request); + } + return R.ok().put("data", page); // 返回分页数据 + } + + + //后端详情 + @RequestMapping("/info/{id}") // 处理详情请求 + public R info(@PathVariable("id") Long id, HttpServletRequest request){ + logger.debug("info方法:,,Controller:{},,id:{}",this.getClass().getName(),id); // 记录日志 + JianshenkechengEntity jianshenkecheng = jianshenkechengService.selectById(id); // 根据ID查询健身课程 + if(jianshenkecheng !=null){ + // entity转view + JianshenkechengView view = new JianshenkechengView(); + BeanUtils.copyProperties( jianshenkecheng , view ); // 把实体数据重构到view中 + // 级联表 教练 + JiaolianEntity jiaolian = jiaolianService.selectById(jianshenkecheng.getJiaolianId()); + if(jiaolian != null){ + BeanUtils.copyProperties( jiaolian , view ,new String[]{ "id", "createTime", "insertTime", "updateTime", "username", "password", "newMoney", "jiaolianId"}); // 把级联的数据添加到view中,并排除id和创建时间字段 + view.setJiaolianId(jiaolian.getId()); + } + // 修改对应字典表字段 + dictionaryService.dictionaryConvert(view, request); + return R.ok().put("data", view); // 返回详情数据 + }else { + return R.error(511,"查不到数据"); // 查询不到数据返回错误 + } + } + + + //后端保存 + @RequestMapping("/save") // 处理保存请求 + public R save(@RequestBody JianshenkechengEntity jianshenkecheng, HttpServletRequest request){ + logger.debug("save方法:,,Controller:{},,jianshenkecheng:{}",this.getClass().getName(),jianshenkecheng.toString()); // 记录日志 + + String role = String.valueOf(request.getSession().getAttribute("role")); // 获取用户角色 + if(false) + return R.error(511,"永远不会进入"); // 永远不会执行的代码 + else if("教练".equals(role)) + jianshenkecheng.setJiaolianId(Integer.valueOf(String.valueOf(request.getSession().getAttribute("userId")))); // 如果是教练角色,设置教练ID + + Wrapper queryWrapper = new EntityWrapper() + .eq("jiaolian_id", jianshenkecheng.getJiaolianId()) // 教练ID + .eq("jianshenkecheng_name", jianshenkecheng.getJianshenkechengName()) // 课程名称 + .eq("jianshenkecheng_video", jianshenkecheng.getJianshenkechengVideo()) // 课程视频 + .eq("zan_number", jianshenkecheng.getZanNumber()) // 赞数 + .eq("cai_number", jianshenkecheng.getCaiNumber()) // 踩数 + .eq("jianshenkecheng_types", jianshenkecheng.getJianshenkechengTypes()) // 课程类型 + .eq("data_delete", 1) // 逻辑删除字段 + ; + + logger.info("sql语句:"+queryWrapper.getSqlSegment()); // 记录SQL语句 + JianshenkechengEntity jianshenkechengEntity = jianshenkechengService.selectOne(queryWrapper); // 查询是否已存在相同数据 + if(jianshenkechengEntity==null){ + jianshenkecheng.setZanNumber(1); // 设置默认赞数 + jianshenkecheng.setCaiNumber(1); // 设置默认踩数 + jianshenkecheng.setJianshenkechengClicknum(1); // 设置默认点击量 + jianshenkecheng.setDataDelete(1); // 设置逻辑删除状态 + jianshenkecheng.setInsertTime(new Date()); // 设置插入时间 + jianshenkecheng.setCreateTime(new Date()); // 设置创建时间 + jianshenkechengService.insert(jianshenkecheng); // 插入新数据 + return R.ok(); // 返回成功 + }else { + return R.error(511,"表中有相同数据"); // 数据已存在返回错误 + } + } + + + //后端修改 + @RequestMapping("/update") // 处理更新请求 + public R update(@RequestBody JianshenkechengEntity jianshenkecheng, HttpServletRequest request) throws NoSuchFieldException, ClassNotFoundException, IllegalAccessException, InstantiationException { + logger.debug("update方法:,,Controller:{},,jianshenkecheng:{}",this.getClass().getName(),jianshenkecheng.toString()); // 记录日志 + JianshenkechengEntity oldJianshenkechengEntity = jianshenkechengService.selectById(jianshenkecheng.getId()); // 查询原先数据 + + if("".equals(jianshenkecheng.getJianshenkechengPhoto()) || "null".equals(jianshenkecheng.getJianshenkechengPhoto())){ + jianshenkecheng.setJianshenkechengPhoto(null); // 处理空图片路径 + } + if("".equals(jianshenkecheng.getJianshenkechengVideo()) || "null".equals(jianshenkecheng.getJianshenkechengVideo())){ + jianshenkecheng.setJianshenkechengVideo(null); // 处理空视频路径 + } + if("".equals(jianshenkecheng.getJianshenkechengContent()) || "null".equals(jianshenkecheng.getJianshenkechengContent())){ + jianshenkecheng.setJianshenkechengContent(null); // 处理空内容 + } + + jianshenkechengService.updateById(jianshenkecheng); // 根据ID更新数据 + return R.ok(); // 返回成功 + } + + + //删除 + @RequestMapping("/delete") // 处理删除请求 + public R delete(@RequestBody Integer[] ids, HttpServletRequest request){ + logger.debug("delete:,,Controller:{},,ids:{}",this.getClass().getName(),ids.toString()); // 记录日志 + List oldJianshenkechengList =jianshenkechengService.selectBatchIds(Arrays.asList(ids)); // 查询要删除的数据 + ArrayList list = new ArrayList<>(); // 创建更新列表 + for(Integer id:ids){ + JianshenkechengEntity jianshenkechengEntity = new JianshenkechengEntity(); + jianshenkechengEntity.setId(id); + jianshenkechengEntity.setDataDelete(2); // 设置逻辑删除状态为已删除 + list.add(jianshenkechengEntity); // 添加到更新列表 + } + if(list != null && list.size() >0){ + jianshenkechengService.updateBatchById(list); // 批量更新删除状态 + } + + return R.ok(); // 返回成功 + } + + + //批量上传 + @RequestMapping("/batchInsert") // 处理批量上传请求 + public R save( String fileName, HttpServletRequest request){ + logger.debug("batchInsert方法:,,Controller:{},,fileName:{}",this.getClass().getName(),fileName); // 记录日志 + Integer yonghuId = Integer.valueOf(String.valueOf(request.getSession().getAttribute("userId"))); // 获取用户ID + SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); // 创建日期格式化对象 + try { + List jianshenkechengList = new ArrayList<>(); // 创建健身课程列表 + Map> seachFields= new HashMap<>(); // 创建查询字段映射 + Date date = new Date(); // 当前时间 + int lastIndexOf = fileName.lastIndexOf("."); // 获取文件后缀位置 + if(lastIndexOf == -1){ + return R.error(511,"该文件没有后缀"); // 文件无后缀返回错误 + }else{ + String suffix = fileName.substring(lastIndexOf); // 获取文件后缀 + if(!".xls".equals(suffix)){ + return R.error(511,"只支持后缀为xls的excel文件"); // 文件格式不正确返回错误 + }else{ + URL resource = this.getClass().getClassLoader().getResource("static/upload/" + fileName); // 获取文件路径 + File file = new File(resource.getFile()); // 创建文件对象 + if(!file.exists()){ + return R.error(511,"找不到上传文件,请联系管理员"); // 文件不存在返回错误 + }else{ + List> dataList = PoiUtil.poiImport(file.getPath()); // 读取xls文件 + dataList.remove(0); // 删除第一行提示信息 + for(List data:dataList){ + // 循环处理每行数据 + JianshenkechengEntity jianshenkechengEntity = new JianshenkechengEntity(); + jianshenkechengList.add(jianshenkechengEntity); // 添加到列表 + } + // 批量插入数据 + jianshenkechengService.insertBatch(jianshenkechengList); + return R.ok(); // 返回成功 +>>>>>>> develop } } } }catch (Exception e){ +<<<<<<< HEAD e.printStackTrace(); return R.error(511,"批量插入数据异常,请联系管理员"); +======= + e.printStackTrace(); // 打印异常堆栈 + return R.error(511,"批量插入数据异常,请联系管理员"); // 异常处理 +>>>>>>> develop } } +<<<<<<< HEAD /** * 个性推荐 @@ -433,3 +678,148 @@ public class JianshenkechengController { } +======= + //个性推荐 + @IgnoreAuth // 忽略认证 + @RequestMapping("/gexingtuijian") // 处理个性推荐请求 + public R gexingtuijian(@RequestParam Map params, HttpServletRequest request){ + logger.debug("gexingtuijian方法:,,Controller:{},,params:{}",this.getClass().getName(),JSONObject.toJSONString(params)); // 记录日志 + CommonUtil.checkMap(params); // 检查参数 + List returnJianshenkechengViewList = new ArrayList<>(); // 创建返回课程列表 + + //查看收藏 + Map params1 = new HashMap<>(params);params1.put("sort","id");params1.put("yonghuId",request.getSession().getAttribute("userId")); // 设置收藏查询参数 + params1.put("shangxiaTypes",1); // 上架状态 + params1.put("jianshenkechengYesnoTypes",2); // 审核通过状态 + PageUtils pageUtils = jianshenkechengCollectionService.queryPage(params1); // 查询收藏分页数据 + List collectionViewsList =(List)pageUtils.getList(); // 获取收藏列表 + Map typeMap=new HashMap<>(); // 创建课程类型统计Map + for(JianshenkechengCollectionView collectionView:collectionViewsList){ + Integer jianshenkechengTypes = collectionView.getJianshenkechengTypes(); // 获取课程类型 + if(typeMap.containsKey(jianshenkechengTypes)){ + typeMap.put(jianshenkechengTypes,typeMap.get(jianshenkechengTypes)+1); // 统计类型数量 + }else{ + typeMap.put(jianshenkechengTypes,1); // 初始化类型数量 + } + } + List typeList = new ArrayList<>(); // 创建排序后的类型列表 + typeMap.entrySet().stream().sorted((o1, o2) -> o2.getValue() - o1.getValue()).forEach(e -> typeList.add(e.getKey())); // 按数量从多到少排序 + Integer limit = Integer.valueOf(String.valueOf(params.get("limit"))); // 获取推荐数量限制 + for(Integer type:typeList){ + Map params2 = new HashMap<>(params);params2.put("jianshenkechengTypes",type); // 设置类型查询参数 + params2.put("shangxiaTypes",1); // 上架状态 + params2.put("jianshenkechengYesnoTypes",2); // 审核通过状态 + PageUtils pageUtils1 = jianshenkechengService.queryPage(params2); // 查询课程分页数据 + List jianshenkechengViewList =(List)pageUtils1.getList(); // 获取课程列表 + returnJianshenkechengViewList.addAll(jianshenkechengViewList); // 添加到返回列表 + if(returnJianshenkechengViewList.size()>= limit) break; // 达到推荐数量限制时跳出循环 + } + params.put("shangxiaTypes",1); // 设置上架状态 + params.put("jianshenkechengYesnoTypes",2); // 设置审核通过状态 + //正常查询出来商品,用于补全推荐缺少的数据 + PageUtils page = jianshenkechengService.queryPage(params); // 查询课程分页数据 + if(returnJianshenkechengViewList.size() jianshenkechengViewList =(List)page.getList(); // 获取课程列表 + for(JianshenkechengView jianshenkechengView:jianshenkechengViewList){ + Boolean addFlag = true; + for(JianshenkechengView returnJianshenkechengView:returnJianshenkechengViewList){ + if(returnJianshenkechengView.getId().intValue() ==jianshenkechengView.getId().intValue()) addFlag=false; // 已存在的课程不再添加 + } + if(addFlag){ + toAddNum=toAddNum-1; + returnJianshenkechengViewList.add(jianshenkechengView); // 添加到返回列表 + if(toAddNum==0) break; // 补充足够数量后跳出循环 + } + } + }else { + returnJianshenkechengViewList = returnJianshenkechengViewList.subList(0, limit); // 截取指定数量的推荐课程 + } + + for(JianshenkechengView c:returnJianshenkechengViewList) + dictionaryService.dictionaryConvert(c, request); // 转换字典字段 + page.setList(returnJianshenkechengViewList); // 设置返回列表 + return R.ok().put("data", page); // 返回推荐数据 + } + + + //前端列表 + @IgnoreAuth // 忽略认证 + @RequestMapping("/list") // 处理列表请求 + public R list(@RequestParam Map params, HttpServletRequest request){ + logger.debug("list方法:,,Controller:{},,params:{}",this.getClass().getName(),JSONObject.toJSONString(params)); // 记录日志 + + CommonUtil.checkMap(params); // 检查参数 + PageUtils page = jianshenkechengService.queryPage(params); // 查询分页数据 + + // 字典表数据转换 + List list =(List)page.getList(); + for(JianshenkechengView c:list) + dictionaryService.dictionaryConvert(c, request); // 转换字典字段 + + return R.ok().put("data", page); // 返回分页数据 + } + + + //前端详情 + @RequestMapping("/detail/{id}") // 处理详情请求 + public R detail(@PathVariable("id") Integer id, HttpServletRequest request){ + logger.debug("detail方法:,,Controller:{},,id:{}",this.getClass().getName(),id); // 记录日志 + JianshenkechengEntity jianshenkecheng = jianshenkechengService.selectById(id); // 根据ID查询课程 + if(jianshenkecheng !=null){ + + //点击数量加1 + jianshenkecheng.setJianshenkechengClicknum(jianshenkecheng.getJianshenkechengClicknum()+1); // 增加点击量 + jianshenkechengService.updateById(jianshenkecheng); // 更新课程 + + //entity转view + JianshenkechengView view = new JianshenkechengView(); + BeanUtils.copyProperties( jianshenkecheng , view ); // 把实体数据重构到view中 + + //级联表 + JiaolianEntity jiaolian = jiaolianService.selectById(jianshenkecheng.getJiaolianId()); // 查询关联教练 + if(jiaolian != null){ + BeanUtils.copyProperties( jiaolian , view ,new String[]{ "id", "createTime", "insertTime", "updateTime", "username", "password", "newMoney", "jiaolianId"}); // 把级联的数据添加到view中,并排除id和创建时间字段 + view.setJiaolianId(jiaolian.getId()); + } + //修改对应字典表字段 + dictionaryService.dictionaryConvert(view, request); // 转换字典字段 + return R.ok().put("data", view); // 返回详情数据 + }else { + return R.error(511,"查不到数据"); // 查询不到数据返回错误 + } + } + + + //前端保存 + @RequestMapping("/add") // 处理添加请求 + public R add(@RequestBody JianshenkechengEntity jianshenkecheng, HttpServletRequest request){ + logger.debug("add方法:,,Controller:{},,jianshenkecheng:{}",this.getClass().getName(),jianshenkecheng.toString()); // 记录日志 + Wrapper queryWrapper = new EntityWrapper() + .eq("jiaolian_id", jianshenkecheng.getJiaolianId()) // 教练ID + .eq("jianshenkecheng_name", jianshenkecheng.getJianshenkechengName()) // 课程名称 + .eq("jianshenkecheng_video", jianshenkecheng.getJianshenkechengVideo()) // 课程视频 + .eq("zan_number", jianshenkecheng.getZanNumber()) // 赞数 + .eq("cai_number", jianshenkecheng.getCaiNumber()) // 踩数 + .eq("jianshenkecheng_types", jianshenkecheng.getJianshenkechengTypes()) // 课程类型 + .eq("jianshenkecheng_clicknum", jianshenkecheng.getJianshenkechengClicknum()) // 点击量 + .eq("data_delete", jianshenkecheng.getDataDelete()) // 逻辑删除状态 + ; + logger.info("sql语句:"+queryWrapper.getSqlSegment()); // 记录SQL语句 + JianshenkechengEntity jianshenkechengEntity = jianshenkechengService.selectOne(queryWrapper); // 查询是否已存在相同数据 + if(jianshenkechengEntity==null){ + jianshenkecheng.setZanNumber(1); // 设置默认赞数 + jianshenkecheng.setCaiNumber(1); // 设置默认踩数 + jianshenkecheng.setJianshenkechengClicknum(1); // 设置默认点击量 + jianshenkecheng.setDataDelete(1); // 设置逻辑删除状态 + jianshenkecheng.setInsertTime(new Date()); // 设置插入时间 + jianshenkecheng.setCreateTime(new Date()); // 设置创建时间 + jianshenkechengService.insert(jianshenkecheng); // 插入新数据 + + return R.ok(); // 返回成功 + }else { + return R.error(511,"表中有相同数据"); // 数据已存在返回错误 + } + } +} +>>>>>>> develop diff --git a/src/main/java/com/controller/JianshenkechengLiuyanController.java b/src/main/java/com/controller/JianshenkechengLiuyanController.java index 09e870c..7ce51c2 100644 --- a/src/main/java/com/controller/JianshenkechengLiuyanController.java +++ b/src/main/java/com/controller/JianshenkechengLiuyanController.java @@ -1,3 +1,4 @@ +<<<<<<< HEAD package com.controller; @@ -241,16 +242,238 @@ public class JianshenkechengLiuyanController { //查询是否重复 jianshenkechengLiuyanService.insertBatch(jianshenkechengLiuyanList); return R.ok(); +======= +package com.controller; // 声明包路径,表示该文件位于com.controller包下 + +import java.io.File; // 导入文件操作类,用于处理文件上传 +import java.math.BigDecimal; // 导入高精度数学计算类,用于处理金额计算 +import java.net.URL; // 导入网络URL处理类,用于获取资源路径 +import java.text.SimpleDateFormat; // 导入日期格式化类,用于日期格式转换 +import com.alibaba.fastjson.JSONObject; // 导入FastJSON的JSON对象类,用于JSON处理 +import java.util.*; // 导入Java常用工具类(集合、日期等) +import org.springframework.beans.BeanUtils; // 导入Spring Bean属性复制工具类 +import javax.servlet.http.HttpServletRequest; // 导入HTTP请求处理类 +import org.springframework.web.context.ContextLoader; // 导入Spring上下文加载器 +import javax.servlet.ServletContext; // 导入Servlet上下文接口 +import com.service.TokenService; // 导入自定义的Token服务类 +import com.utils.*; // 导入自定义工具类 +import java.lang.reflect.InvocationTargetException; // 导入反射异常类 + +import com.service.DictionaryService; // 导入自定义的字典服务类 +import org.apache.commons.lang3.StringUtils; // 导入Apache字符串工具类 +import com.annotation.IgnoreAuth; // 导入自定义的忽略认证注解 +import org.slf4j.Logger; // 导入日志接口 +import org.slf4j.LoggerFactory; // 导入日志工厂类 +import org.springframework.beans.factory.annotation.Autowired; // 导入Spring自动注入注解 +import org.springframework.stereotype.Controller; // 导入Spring控制器注解 +import org.springframework.web.bind.annotation.*; // 导入Spring Web注解 +import com.baomidou.mybatisplus.mapper.EntityWrapper; // 导入MyBatis Plus查询条件构造器 +import com.baomidou.mybatisplus.mapper.Wrapper; // 导入MyBatis Plus包装器接口 +import com.entity.*; // 导入实体类 +import com.entity.view.*; // 导入视图实体类 +import com.service.*; // 导入服务类 +import com.utils.PageUtils; // 导入分页工具类 +import com.utils.R; // 导入统一返回结果类 +import com.alibaba.fastjson.*; // 导入FastJSON相关类 + + + //课程留言 + //后端接口 + //@author + //@email +@RestController // 标识为RESTful控制器,用于处理HTTP请求 +@Controller // 标识为Spring控制器 +@RequestMapping("/jianshenkechengLiuyan") // 定义请求映射路径 +public class JianshenkechengLiuyanController { + private static final Logger logger = LoggerFactory.getLogger(JianshenkechengLiuyanController.class); // 日志记录器,用于记录日志信息 + + private static final String TABLE_NAME = "jianshenkechengLiuyan"; // 数据库表名常量 + + @Autowired + private JianshenkechengLiuyanService jianshenkechengLiuyanService; // 自动注入课程留言服务 + + @Autowired + private TokenService tokenService; // 自动注入Token服务 + + @Autowired + private DictionaryService dictionaryService; // 自动注入字典服务 + @Autowired + private ForumService forumService; // 自动注入健身论坛服务 + @Autowired + private JianshenkechengService jianshenkechengService; // 自动注入健身课程服务 + @Autowired + private JianshenkechengCollectionService jianshenkechengCollectionService; // 自动注入课程收藏服务 + @Autowired + private JiaolianService jiaolianService; // 自动注入教练服务 + @Autowired + private JiaolianYuyueService jiaolianYuyueService; // 自动注入教练预约申请服务 + @Autowired + private NewsService newsService; // 自动注入健身资讯服务 + @Autowired + private SingleSeachService singleSeachService; // 自动注入单页数据服务 + @Autowired + private YonghuService yonghuService; // 自动注入用户服务 + @Autowired + private UsersService usersService; // 自动注入管理员服务 + + + //后端列表 + //处理分页查询请求 + @RequestMapping("/page") // 映射分页查询请求 + public R page(@RequestParam Map params, HttpServletRequest request){ + logger.debug("page方法:,,Controller:{},,params:{}",this.getClass().getName(),JSONObject.toJSONString(params)); // 记录请求日志 + String role = String.valueOf(request.getSession().getAttribute("role")); // 从session中获取用户角色 + if(false) // 永远不会执行的代码块 + return R.error(511,"永不会进入"); // 返回错误信息 + else if("用户".equals(role)) // 如果是用户角色 + params.put("yonghuId",request.getSession().getAttribute("userId")); // 将用户ID添加到查询参数 + else if("教练".equals(role)) // 如果是教练角色 + params.put("jiaolianId",request.getSession().getAttribute("userId")); // 将教练ID添加到查询参数 + CommonUtil.checkMap(params); // 检查参数有效性 + PageUtils page = jianshenkechengLiuyanService.queryPage(params); // 调用服务层查询分页数据 + + // 字典表数据转换 + List list =(List)page.getList(); // 获取分页数据列表 + for(JianshenkechengLiuyanView c:list){ // 遍历列表 + dictionaryService.dictionaryConvert(c, request); // 转换字典字段 + } + return R.ok().put("data", page); // 返回分页数据 + } + + + //后端详情 + //根据ID查询单条留言详情 + @RequestMapping("/info/{id}") // 映射详情查询请求 + public R info(@PathVariable("id") Long id, HttpServletRequest request){ + logger.debug("info方法:,,Controller:{},,id:{}",this.getClass().getName(),id); // 记录请求日志 + JianshenkechengLiuyanEntity jianshenkechengLiuyan = jianshenkechengLiuyanService.selectById(id); // 根据ID查询留言 + if(jianshenkechengLiuyan !=null){ // 如果查询到数据 + JianshenkechengLiuyanView view = new JianshenkechengLiuyanView(); // 创建视图对象 + BeanUtils.copyProperties(jianshenkechengLiuyan, view); // 复制属性到视图对象 + + // 查询关联的健身课程信息 + JianshenkechengEntity jianshenkecheng = jianshenkechengService.selectById(jianshenkechengLiuyan.getJianshenkechengId()); + if(jianshenkecheng != null){ + BeanUtils.copyProperties(jianshenkecheng, view, new String[]{ "id", "createTime", "insertTime", "updateTime", "username", "password", "newMoney", "yonghuId"}); + view.setJianshenkechengId(jianshenkecheng.getId()); + } + + // 查询关联的用户信息 + YonghuEntity yonghu = yonghuService.selectById(jianshenkechengLiuyan.getYonghuId()); + if(yonghu != null){ + BeanUtils.copyProperties(yonghu, view, new String[]{ "id", "createTime", "insertTime", "updateTime", "username", "password", "newMoney", "yonghuId"}); + view.setYonghuId(yonghu.getId()); + } + + dictionaryService.dictionaryConvert(view, request); // 转换字典字段 + return R.ok().put("data", view); // 返回详情数据 + }else { + return R.error(511,"查不到数据"); // 返回错误信息 + } + } + + + //后端保存 + //处理新增留言请求 + @RequestMapping("/save") // 映射保存请求 + public R save(@RequestBody JianshenkechengLiuyanEntity jianshenkechengLiuyan, HttpServletRequest request){ + logger.debug("save方法:,,Controller:{},,jianshenkechengLiuyan:{}",this.getClass().getName(),jianshenkechengLiuyan.toString()); // 记录请求日志 + + String role = String.valueOf(request.getSession().getAttribute("role")); // 获取用户角色 + if(false) // 永远不会执行的代码块 + return R.error(511,"永远不会进入"); // 返回错误信息 + else if("用户".equals(role)) // 如果是用户角色 + jianshenkechengLiuyan.setYonghuId(Integer.valueOf(String.valueOf(request.getSession().getAttribute("userId")))); // 设置用户ID + + jianshenkechengLiuyan.setCreateTime(new Date()); // 设置创建时间 + jianshenkechengLiuyan.setInsertTime(new Date()); // 设置插入时间 + jianshenkechengLiuyanService.insert(jianshenkechengLiuyan); // 调用服务层保存数据 + + return R.ok(); // 返回成功信息 + } + + + //后端修改 + //处理更新留言请 + @RequestMapping("/update") // 映射更新请求 + public R update(@RequestBody JianshenkechengLiuyanEntity jianshenkechengLiuyan, HttpServletRequest request) throws NoSuchFieldException, ClassNotFoundException, IllegalAccessException, InstantiationException { + logger.debug("update方法:,,Controller:{},,jianshenkechengLiuyan:{}",this.getClass().getName(),jianshenkechengLiuyan.toString()); // 记录请求日志 + JianshenkechengLiuyanEntity oldJianshenkechengLiuyanEntity = jianshenkechengLiuyanService.selectById(jianshenkechengLiuyan.getId()); // 查询原有数据 + + // 处理空值情况 + if("".equals(jianshenkechengLiuyan.getJianshenkechengLiuyanText()) || "null".equals(jianshenkechengLiuyan.getJianshenkechengLiuyanText())){ + jianshenkechengLiuyan.setJianshenkechengLiuyanText(null); + } + if("".equals(jianshenkechengLiuyan.getReplyText()) || "null".equals(jianshenkechengLiuyan.getReplyText())){ + jianshenkechengLiuyan.setReplyText(null); + } + + jianshenkechengLiuyan.setUpdateTime(new Date()); // 设置更新时间 + jianshenkechengLiuyanService.updateById(jianshenkechengLiuyan); // 调用服务层更新数据 + return R.ok(); // 返回成功信息 + } + + + //删除 + //处理删除留言请求 + @RequestMapping("/delete") // 映射删除请求 + public R delete(@RequestBody Integer[] ids, HttpServletRequest request){ + logger.debug("delete:,,Controller:{},,ids:{}",this.getClass().getName(),ids.toString()); // 记录请求日志 + List oldJianshenkechengLiuyanList = jianshenkechengLiuyanService.selectBatchIds(Arrays.asList(ids)); // 查询要删除的数据 + jianshenkechengLiuyanService.deleteBatchIds(Arrays.asList(ids)); // 调用服务层批量删除 + return R.ok(); // 返回成功信息 + } + + + //批量上传 + //处理批量导入数据请求 + @RequestMapping("/batchInsert") // 映射批量导入请求 + public R save(String fileName, HttpServletRequest request){ + logger.debug("batchInsert方法:,,Controller:{},,fileName:{}",this.getClass().getName(),fileName); // 记录请求日志 + Integer yonghuId = Integer.valueOf(String.valueOf(request.getSession().getAttribute("userId"))); // 获取用户ID + SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); // 创建日期格式化对象 + try { + List jianshenkechengLiuyanList = new ArrayList<>(); // 创建数据列表 + Map> seachFields = new HashMap<>(); // 创建查询字段映射 + Date date = new Date(); // 当前时间 + int lastIndexOf = fileName.lastIndexOf("."); // 获取文件后缀位置 + if(lastIndexOf == -1){ // 如果没有后缀 + return R.error(511,"该文件没有后缀"); // 返回错误信息 + }else{ + String suffix = fileName.substring(lastIndexOf); // 获取文件后缀 + if(!".xls".equals(suffix)){ // 如果不是xls文件 + return R.error(511,"只支持后缀为xls的excel文件"); // 返回错误信息 + }else{ + URL resource = this.getClass().getClassLoader().getResource("static/upload/" + fileName); // 获取文件路径 + File file = new File(resource.getFile()); // 创建文件对象 + if(!file.exists()){ // 如果文件不存在 + return R.error(511,"找不到上传文件,请联系管理员"); // 返回错误信息 + }else{ + List> dataList = PoiUtil.poiImport(file.getPath()); // 读取Excel文件 + dataList.remove(0); // 删除标题行 + for(List data:dataList){ // 遍历数据行 + JianshenkechengLiuyanEntity jianshenkechengLiuyanEntity = new JianshenkechengLiuyanEntity(); // 创建实体对象 + jianshenkechengLiuyanList.add(jianshenkechengLiuyanEntity); // 添加到列表 + } + jianshenkechengLiuyanService.insertBatch(jianshenkechengLiuyanList); // 批量插入数据 + return R.ok(); // 返回成功信息 +>>>>>>> develop } } } }catch (Exception e){ +<<<<<<< HEAD e.printStackTrace(); return R.error(511,"批量插入数据异常,请联系管理员"); +======= + e.printStackTrace(); // 打印异常堆栈 + return R.error(511,"批量插入数据异常,请联系管理员"); // 返回错误信息 +>>>>>>> develop } } +<<<<<<< HEAD /** @@ -322,3 +545,66 @@ public class JianshenkechengLiuyanController { } +======= + //前端列表 + //处理前端分页查询请求 + @IgnoreAuth // 忽略认证 + @RequestMapping("/list") // 映射列表查询请求 + public R list(@RequestParam Map params, HttpServletRequest request){ + logger.debug("list方法:,,Controller:{},,params:{}",this.getClass().getName(),JSONObject.toJSONString(params)); // 记录请求日志 + CommonUtil.checkMap(params); // 检查参数有效性 + PageUtils page = jianshenkechengLiuyanService.queryPage(params); // 调用服务层查询分页数据 + + // 字典表数据转换 + List list =(List)page.getList(); // 获取分页数据列表 + for(JianshenkechengLiuyanView c:list){ // 遍历列表 + dictionaryService.dictionaryConvert(c, request); // 转换字典字段 + } + return R.ok().put("data", page); // 返回分页数据 + } + + + //前端详情 + //处理前端详情查询请求 + @RequestMapping("/detail/{id}") // 映射详情查询请求 + public R detail(@PathVariable("id") Integer id, HttpServletRequest request){ + logger.debug("detail方法:,,Controller:{},,id:{}",this.getClass().getName(),id); // 记录请求日志 + JianshenkechengLiuyanEntity jianshenkechengLiuyan = jianshenkechengLiuyanService.selectById(id); // 根据ID查询留言 + if(jianshenkechengLiuyan !=null){ // 如果查询到数据 + JianshenkechengLiuyanView view = new JianshenkechengLiuyanView(); // 创建视图对象 + BeanUtils.copyProperties(jianshenkechengLiuyan, view); // 复制属性到视图对象 + + // 查询关联的健身课程信息 + JianshenkechengEntity jianshenkecheng = jianshenkechengService.selectById(jianshenkechengLiuyan.getJianshenkechengId()); + if(jianshenkecheng != null){ + BeanUtils.copyProperties(jianshenkecheng, view, new String[]{ "id", "createTime", "insertTime", "updateTime", "username", "password", "newMoney", "yonghuId"}); + view.setJianshenkechengId(jianshenkecheng.getId()); + } + + // 查询关联的用户信息 + YonghuEntity yonghu = yonghuService.selectById(jianshenkechengLiuyan.getYonghuId()); + if(yonghu != null){ + BeanUtils.copyProperties(yonghu, view, new String[]{ "id", "createTime", "insertTime", "updateTime", "username", "password", "newMoney", "yonghuId"}); + view.setYonghuId(yonghu.getId()); + } + + dictionaryService.dictionaryConvert(view, request); // 转换字典字段 + return R.ok().put("data", view); // 返回详情数据 + }else { + return R.error(511,"查不到数据"); // 返回错误信息 + } + } + + + //前端保存 + //处理前端新增留言请求 + @RequestMapping("/add") // 映射新增请求 + public R add(@RequestBody JianshenkechengLiuyanEntity jianshenkechengLiuyan, HttpServletRequest request){ + logger.debug("add方法:,,Controller:{},,jianshenkechengLiuyan:{}",this.getClass().getName(),jianshenkechengLiuyan.toString()); // 记录请求日志 + jianshenkechengLiuyan.setCreateTime(new Date()); // 设置创建时间 + jianshenkechengLiuyan.setInsertTime(new Date()); // 设置插入时间 + jianshenkechengLiuyanService.insert(jianshenkechengLiuyan); // 调用服务层保存数据 + return R.ok(); // 返回成功信息 + } +} +>>>>>>> develop diff --git a/src/main/java/com/controller/JiaolianController.java b/src/main/java/com/controller/JiaolianController.java index a551d66..08f271b 100644 --- a/src/main/java/com/controller/JiaolianController.java +++ b/src/main/java/com/controller/JiaolianController.java @@ -1,3 +1,4 @@ +<<<<<<< HEAD package com.controller; @@ -38,6 +39,76 @@ import com.alibaba.fastjson.*; * @author * @email */ +======= +// 声明当前 Java 文件所属的包,此包一般用于存放控制器相关的类,负责处理 HTTP 请求和响应 +package com.controller; + +// 导入 Java 标准库中的 File 类,用于操作文件和目录 +import java.io.File; +// 导入 Java 标准库中的 BigDecimal 类,用于进行高精度的十进制数运算 +import java.math.BigDecimal; +// 导入 Java 标准库中的 URL 类,用于表示统一资源定位符,可用于处理网络资源 +import java.net.URL; +// 导入 Java 标准库中的 SimpleDateFormat 类,用于格式化和解析日期时间 +import java.text.SimpleDateFormat; +// 导入阿里巴巴的 FastJSON 库中的 JSONObject 类,用于处理 JSON 对象,方便进行 JSON 数据的操作 +import com.alibaba.fastjson.JSONObject; +// 导入 Java 标准库中的 java.util 包下的所有类,该包包含了集合框架、日期和时间、随机数生成等常用工具类 +import java.util.*; +// 导入 Spring 框架中的 BeanUtils 类,用于对象属性的复制,方便在不同对象之间传递数据 +import org.springframework.beans.BeanUtils; +// 导入 Java Servlet API 中的 HttpServletRequest 类,用于封装 HTTP 请求信息,在控制器中可获取请求参数等 +import javax.servlet.http.HttpServletRequest; +// 导入 Spring 框架中的 ContextLoader 类,用于获取 Spring 的应用上下文 +import org.springframework.web.context.ContextLoader; +// 导入 Java Servlet API 中的 ServletContext 类,用于表示 Servlet 上下文,可获取应用的全局信息 +import javax.servlet.ServletContext; +// 导入自定义的 TokenService 类,该类可能用于处理令牌相关的业务逻辑 +import com.service.TokenService; +// 导入自定义的 utils 包下的所有类,这些类通常包含一些通用的工具方法 +import com.utils.*; +// 导入 Java 反射机制中的 InvocationTargetException 类,当使用反射调用方法时,如果被调用的方法抛出异常,会被封装成该异常抛出 +import java.lang.reflect.InvocationTargetException; + +// 导入自定义的 DictionaryService 类,该类可能用于处理字典数据的业务逻辑 +import com.service.DictionaryService; +// 导入 Apache Commons Lang3 库中的 StringUtils 类,提供了许多方便的字符串操作方法 +import org.apache.commons.lang3.StringUtils; +// 导入自定义的 IgnoreAuth 注解,该注解可能用于标记不需要进行身份验证的接口 +import com.annotation.IgnoreAuth; +// 导入 SLF4J 日志框架中的 Logger 接口,用于记录日志信息 +import org.slf4j.Logger; +// 导入 SLF4J 日志框架中的 LoggerFactory 类,用于创建 Logger 实例 +import org.slf4j.LoggerFactory; +// 导入 Spring 框架中的 Autowired 注解,用于自动注入依赖的 Bean +import org.springframework.beans.factory.annotation.Autowired; +// 导入 Spring 框架中的 Controller 注解,用于标记该类为控制器类,处理 HTTP 请求 +import org.springframework.stereotype.Controller; +// 导入 Spring 框架中的 RestController 和 RequestMapping 等注解,用于构建 RESTful 风格的接口 +import org.springframework.web.bind.annotation.*; +// 导入 MyBatis-Plus 框架中的 EntityWrapper 类,用于构建实体对象的查询条件 +import com.baomidou.mybatisplus.mapper.EntityWrapper; +// 导入 MyBatis-Plus 框架中的 Wrapper 接口,EntityWrapper 实现了该接口,用于灵活构建查询条件 +import com.baomidou.mybatisplus.mapper.Wrapper; +// 导入自定义的 entity 包下的所有类,这些类通常是实体类,对应数据库表结构 +import com.entity.*; +// 导入自定义的 view 包下的所有类,这些类可能是用于视图展示的实体类 +import com.entity.view.*; +// 导入自定义的 service 包下的所有类,这些类通常包含业务逻辑处理方法 +import com.service.*; +// 导入自定义的 PageUtils 类,用于处理分页相关的逻辑 +import com.utils.PageUtils; +// 导入自定义的 R 类,通常用于封装统一的响应结果 +import com.utils.R; +// 导入阿里巴巴的 FastJSON 库中的所有类,进一步方便进行 JSON 数据的操作 +import com.alibaba.fastjson.*; + + + //教练 + //后端接口 + //@author + //@email +>>>>>>> develop @RestController @Controller @RequestMapping("/jiaolian") @@ -75,9 +146,13 @@ public class JiaolianController { private UsersService usersService;//管理员 +<<<<<<< HEAD /** * 后端列表 */ +======= + //后端列表 +>>>>>>> develop @RequestMapping("/page") public R page(@RequestParam Map params, HttpServletRequest request){ logger.debug("page方法:,,Controller:{},,params:{}",this.getClass().getName(),JSONObject.toJSONString(params)); @@ -101,9 +176,14 @@ public class JiaolianController { return R.ok().put("data", page); } +<<<<<<< HEAD /** * 后端详情 */ +======= + + //后端详情 +>>>>>>> develop @RequestMapping("/info/{id}") public R info(@PathVariable("id") Long id, HttpServletRequest request){ logger.debug("info方法:,,Controller:{},,id:{}",this.getClass().getName(),id); @@ -121,9 +201,13 @@ public class JiaolianController { } +<<<<<<< HEAD /** * 后端保存 */ +======= + //后端保存 +>>>>>>> develop @RequestMapping("/save") public R save(@RequestBody JiaolianEntity jiaolian, HttpServletRequest request){ logger.debug("save方法:,,Controller:{},,jiaolian:{}",this.getClass().getName(),jiaolian.toString()); @@ -153,9 +237,14 @@ public class JiaolianController { } } +<<<<<<< HEAD /** * 后端修改 */ +======= + + //后端修改 +>>>>>>> develop @RequestMapping("/update") public R update(@RequestBody JiaolianEntity jiaolian, HttpServletRequest request) throws NoSuchFieldException, ClassNotFoundException, IllegalAccessException, InstantiationException { logger.debug("update方法:,,Controller:{},,jiaolian:{}",this.getClass().getName(),jiaolian.toString()); @@ -177,9 +266,14 @@ public class JiaolianController { +<<<<<<< HEAD /** * 删除 */ +======= + + //删除 +>>>>>>> develop @RequestMapping("/delete") public R delete(@RequestBody Integer[] ids, HttpServletRequest request){ logger.debug("delete:,,Controller:{},,ids:{}",this.getClass().getName(),ids.toString()); @@ -199,9 +293,14 @@ public class JiaolianController { } +<<<<<<< HEAD /** * 批量上传 */ +======= + + //批量上传 +>>>>>>> develop @RequestMapping("/batchInsert") public R save( String fileName, HttpServletRequest request){ logger.debug("batchInsert方法:,,Controller:{},,fileName:{}",this.getClass().getName(),fileName); @@ -295,9 +394,14 @@ public class JiaolianController { } } +<<<<<<< HEAD /** * 登录 */ +======= + + //登录 +>>>>>>> develop @IgnoreAuth @RequestMapping(value = "/login") public R login(String username, String password, String captcha, HttpServletRequest request) { @@ -316,9 +420,13 @@ public class JiaolianController { return r; } +<<<<<<< HEAD /** * 注册 */ +======= + //注册 +>>>>>>> develop @IgnoreAuth @PostMapping(value = "/register") public R register(@RequestBody JiaolianEntity jiaolian, HttpServletRequest request) { @@ -341,9 +449,14 @@ public class JiaolianController { return R.ok(); } +<<<<<<< HEAD /** * 重置密码 */ +======= + + //重置密码 +>>>>>>> develop @GetMapping(value = "/resetPassword") public R resetPassword(Integer id, HttpServletRequest request) { JiaolianEntity jiaolian = jiaolianService.selectById(id); @@ -352,9 +465,14 @@ public class JiaolianController { return R.ok(); } +<<<<<<< HEAD /** * 修改密码 */ +======= + + //修改密码 +>>>>>>> develop @GetMapping(value = "/updatePassword") public R updatePassword(String oldPassword, String newPassword, HttpServletRequest request) { JiaolianEntity jiaolian = jiaolianService.selectById((Integer)request.getSession().getAttribute("userId")); @@ -374,9 +492,14 @@ public class JiaolianController { +<<<<<<< HEAD /** * 忘记密码 */ +======= + + //忘记密码 +>>>>>>> develop @IgnoreAuth @RequestMapping(value = "/resetPass") public R resetPass(String username, HttpServletRequest request) { @@ -391,9 +514,13 @@ public class JiaolianController { } +<<<<<<< HEAD /** * 获取用户的session用户信息 */ +======= + //获取用户的session用户信息 +>>>>>>> develop @RequestMapping("/session") public R getCurrJiaolian(HttpServletRequest request){ Integer id = (Integer)request.getSession().getAttribute("userId"); @@ -412,9 +539,14 @@ public class JiaolianController { } +<<<<<<< HEAD /** * 退出 */ +======= + + //退出 +>>>>>>> develop @GetMapping(value = "logout") public R logout(HttpServletRequest request) { request.getSession().invalidate(); @@ -423,9 +555,14 @@ public class JiaolianController { +<<<<<<< HEAD /** * 前端列表 */ +======= + + //前端列表 +>>>>>>> develop @IgnoreAuth @RequestMapping("/list") public R list(@RequestParam Map params, HttpServletRequest request){ @@ -442,9 +579,14 @@ public class JiaolianController { return R.ok().put("data", page); } +<<<<<<< HEAD /** * 前端详情 */ +======= + + //前端详情 +>>>>>>> develop @RequestMapping("/detail/{id}") public R detail(@PathVariable("id") Integer id, HttpServletRequest request){ logger.debug("detail方法:,,Controller:{},,id:{}",this.getClass().getName(),id); @@ -465,9 +607,14 @@ public class JiaolianController { } +<<<<<<< HEAD /** * 前端保存 */ +======= + + //前端保存 +>>>>>>> develop @RequestMapping("/add") public R add(@RequestBody JiaolianEntity jiaolian, HttpServletRequest request){ logger.debug("add方法:,,Controller:{},,jiaolian:{}",this.getClass().getName(),jiaolian.toString()); diff --git a/src/main/java/com/controller/JiaolianYuyueController.java b/src/main/java/com/controller/JiaolianYuyueController.java index bcc24b2..8bd2c05 100644 --- a/src/main/java/com/controller/JiaolianYuyueController.java +++ b/src/main/java/com/controller/JiaolianYuyueController.java @@ -1,3 +1,4 @@ +<<<<<<< HEAD package com.controller; @@ -276,6 +277,254 @@ public class JiaolianYuyueController { //查询是否重复 //预约编号 +======= +package com.controller; // 声明包路径,表示该文件位于com.controller包下 + +import java.io.File; // 导入文件操作类,用于处理文件上传 +import java.math.BigDecimal; // 导入高精度数学计算类,用于处理金额计算 +import java.net.URL; // 导入网络URL处理类,用于获取资源路径 +import java.text.SimpleDateFormat; // 导入日期格式化类,用于日期格式转换 +import com.alibaba.fastjson.JSONObject; // 导入FastJSON的JSON对象类,用于JSON处理 +import java.util.*; // 导入Java常用工具类(集合、日期等) +import org.springframework.beans.BeanUtils; // 导入Spring Bean属性复制工具类 +import javax.servlet.http.HttpServletRequest; // 导入HTTP请求处理类 +import org.springframework.web.context.ContextLoader; // 导入Spring上下文加载器 +import javax.servlet.ServletContext; // 导入Servlet上下文接口 +import com.service.TokenService; // 导入自定义的Token服务类 +import com.utils.*; // 导入自定义工具类 +import java.lang.reflect.InvocationTargetException; // 导入反射异常类 + +import com.service.DictionaryService; // 导入自定义的字典服务类 +import org.apache.commons.lang3.StringUtils; // 导入Apache字符串工具类 +import com.annotation.IgnoreAuth; // 导入自定义的忽略认证注解 +import org.slf4j.Logger; // 导入日志接口 +import org.slf4j.LoggerFactory; // 导入日志工厂类 +import org.springframework.beans.factory.annotation.Autowired; // 导入Spring自动注入注解 +import org.springframework.stereotype.Controller; // 导入Spring控制器注解 +import org.springframework.web.bind.annotation.*; // 导入Spring Web注解 +import com.baomidou.mybatisplus.mapper.EntityWrapper; // 导入MyBatis Plus查询条件构造器 +import com.baomidou.mybatisplus.mapper.Wrapper; // 导入MyBatis Plus包装器接口 +import com.entity.*; // 导入实体类 +import com.entity.view.*; // 导入视图实体类 +import com.service.*; // 导入服务类 +import com.utils.PageUtils; // 导入分页工具类 +import com.utils.R; // 导入统一返回结果类 +import com.alibaba.fastjson.*; // 导入FastJSON相关类 + + + //教练预约申请 + //后端接口 + //@author + // @email + +@RestController // 标识为RESTful控制器,用于处理HTTP请求 +@Controller // 标识为Spring控制器 +@RequestMapping("/jiaolianYuyue") // 定义请求映射路径 +public class JiaolianYuyueController { + private static final Logger logger = LoggerFactory.getLogger(JiaolianYuyueController.class); // 日志记录器,用于记录日志信息 + + private static final String TABLE_NAME = "jiaolianYuyue"; // 数据库表名常量 + + @Autowired + private JiaolianYuyueService jiaolianYuyueService; // 自动注入教练预约服务 + + @Autowired + private TokenService tokenService; // 自动注入Token服务 + + @Autowired + private DictionaryService dictionaryService; // 自动注入字典服务 + @Autowired + private ForumService forumService; // 自动注入健身论坛服务 + @Autowired + private JianshenkechengService jianshenkechengService; // 自动注入健身课程服务 + @Autowired + private JianshenkechengCollectionService jianshenkechengCollectionService; // 自动注入课程收藏服务 + @Autowired + private JianshenkechengLiuyanService jianshenkechengLiuyanService; // 自动注入课程留言服务 + @Autowired + private JiaolianService jiaolianService; // 自动注入教练服务 + @Autowired + private NewsService newsService; // 自动注入健身资讯服务 + @Autowired + private SingleSeachService singleSeachService; // 自动注入单页数据服务 + @Autowired + private YonghuService yonghuService; // 自动注入用户服务 + @Autowired + private UsersService usersService; // 自动注入管理员服务 + + + //后端列表 + //处理分页查询请求 + @RequestMapping("/page") // 映射分页查询请求 + public R page(@RequestParam Map params, HttpServletRequest request){ + logger.debug("page方法:,,Controller:{},,params:{}",this.getClass().getName(),JSONObject.toJSONString(params)); // 记录请求日志 + String role = String.valueOf(request.getSession().getAttribute("role")); // 从session中获取用户角色 + if(false) // 永远不会执行的代码块 + return R.error(511,"永不会进入"); // 返回错误信息 + else if("用户".equals(role)) // 如果是用户角色 + params.put("yonghuId",request.getSession().getAttribute("userId")); // 将用户ID添加到查询参数 + else if("教练".equals(role)) // 如果是教练角色 + params.put("jiaolianId",request.getSession().getAttribute("userId")); // 将教练ID添加到查询参数 + CommonUtil.checkMap(params); // 检查参数有效性 + PageUtils page = jiaolianYuyueService.queryPage(params); // 调用服务层查询分页数据 + + // 字典表数据转换 + List list =(List)page.getList(); // 获取分页数据列表 + for(JiaolianYuyueView c:list){ // 遍历列表 + dictionaryService.dictionaryConvert(c, request); // 转换字典字段 + } + return R.ok().put("data", page); // 返回分页数据 + } + + + //后端详情 + //根据ID查询单条预约详情 + @RequestMapping("/info/{id}") // 映射详情查询请求 + public R info(@PathVariable("id") Long id, HttpServletRequest request){ + logger.debug("info方法:,,Controller:{},,id:{}",this.getClass().getName(),id); // 记录请求日志 + JiaolianYuyueEntity jiaolianYuyue = jiaolianYuyueService.selectById(id); // 根据ID查询预约 + if(jiaolianYuyue !=null){ // 如果查询到数据 + JiaolianYuyueView view = new JiaolianYuyueView(); // 创建视图对象 + BeanUtils.copyProperties(jiaolianYuyue, view); // 复制属性到视图对象 + + // 查询关联的用户信息 + YonghuEntity yonghu = yonghuService.selectById(jiaolianYuyue.getYonghuId()); + if(yonghu != null){ + BeanUtils.copyProperties(yonghu, view, new String[]{ "id", "createTime", "insertTime", "updateTime", "username", "password", "newMoney", "yonghuId"}); + view.setYonghuId(yonghu.getId()); + } + + dictionaryService.dictionaryConvert(view, request); // 转换字典字段 + return R.ok().put("data", view); // 返回详情数据 + }else { + return R.error(511,"查不到数据"); // 返回错误信息 + } + } + + + //后端保存 + //处理新增预约请求 + @RequestMapping("/save") // 映射保存请求 + public R save(@RequestBody JiaolianYuyueEntity jiaolianYuyue, HttpServletRequest request){ + logger.debug("save方法:,,Controller:{},,jiaolianYuyue:{}",this.getClass().getName(),jiaolianYuyue.toString()); // 记录请求日志 + + String role = String.valueOf(request.getSession().getAttribute("role")); // 获取用户角色 + if(false) // 永远不会执行的代码块 + return R.error(511,"永远不会进入"); // 返回错误信息 + else if("用户".equals(role)) // 如果是用户角色 + jiaolianYuyue.setYonghuId(Integer.valueOf(String.valueOf(request.getSession().getAttribute("userId")))); // 设置用户ID + + // 构建查询条件,检查是否存在相同用户的待审核或已通过的预约 + Wrapper queryWrapper = new EntityWrapper() + .eq("yonghu_id", jiaolianYuyue.getYonghuId()) + .in("jiaolian_yuyue_yesno_types", new Integer[]{1,2}); + + logger.info("sql语句:"+queryWrapper.getSqlSegment()); // 记录SQL语句 + JiaolianYuyueEntity jiaolianYuyueEntity = jiaolianYuyueService.selectOne(queryWrapper); // 查询是否存在重复数据 + if(jiaolianYuyueEntity==null){ // 如果没有重复数据 + jiaolianYuyue.setJiaolianYuyueYesnoTypes(1); // 设置状态为待审核 + jiaolianYuyue.setInsertTime(new Date()); // 设置插入时间 + jiaolianYuyue.setCreateTime(new Date()); // 设置创建时间 + jiaolianYuyueService.insert(jiaolianYuyue); // 调用服务层保存数据 + return R.ok(); // 返回成功信息 + }else { // 如果存在重复数据 + if(jiaolianYuyueEntity.getJiaolianYuyueYesnoTypes()==1) // 如果是待审核状态 + return R.error(511,"有相同的待审核的数据"); // 返回错误信息 + else if(jiaolianYuyueEntity.getJiaolianYuyueYesnoTypes()==2) // 如果是已通过状态 + return R.error(511,"有相同的审核通过的数据"); // 返回错误信息 + else + return R.error(511,"表中有相同数据"); // 返回错误信息 + } + } + + + //后端修改 + //处理更新预约请求 + @RequestMapping("/update") // 映射更新请求 + public R update(@RequestBody JiaolianYuyueEntity jiaolianYuyue, HttpServletRequest request) throws NoSuchFieldException, ClassNotFoundException, IllegalAccessException, InstantiationException { + logger.debug("update方法:,,Controller:{},,jiaolianYuyue:{}",this.getClass().getName(),jiaolianYuyue.toString()); // 记录请求日志 + JiaolianYuyueEntity oldJiaolianYuyueEntity = jiaolianYuyueService.selectById(jiaolianYuyue.getId()); // 查询原有数据 + + // 处理空值情况 + if("".equals(jiaolianYuyue.getJiaolianYuyueText()) || "null".equals(jiaolianYuyue.getJiaolianYuyueText())){ + jiaolianYuyue.setJiaolianYuyueText(null); + } + if("".equals(jiaolianYuyue.getJiaolianYuyueYesnoText()) || "null".equals(jiaolianYuyue.getJiaolianYuyueYesnoText())){ + jiaolianYuyue.setJiaolianYuyueYesnoText(null); + } + + jiaolianYuyueService.updateById(jiaolianYuyue); // 调用服务层更新数据 + return R.ok(); // 返回成功信息 + } + + + //审核 + //处理预约审核请求 + @RequestMapping("/shenhe") // 映射审核请求 + public R shenhe(@RequestBody JiaolianYuyueEntity jiaolianYuyueEntity, HttpServletRequest request){ + logger.debug("shenhe方法:,,Controller:{},,jiaolianYuyueEntity:{}",this.getClass().getName(),jiaolianYuyueEntity.toString()); // 记录请求日志 + + JiaolianYuyueEntity oldJiaolianYuyue = jiaolianYuyueService.selectById(jiaolianYuyueEntity.getId()); // 查询原有数据 + + jiaolianYuyueService.updateById(jiaolianYuyueEntity); // 调用服务层更新审核状态 + return R.ok(); // 返回成功信息 + } + + + //删除 + //处理删除预约请求 + @RequestMapping("/delete") // 映射删除请求 + public R delete(@RequestBody Integer[] ids, HttpServletRequest request){ + logger.debug("delete:,,Controller:{},,ids:{}",this.getClass().getName(),ids.toString()); // 记录请求日志 + List oldJiaolianYuyueList = jiaolianYuyueService.selectBatchIds(Arrays.asList(ids)); // 查询要删除的数据 + jiaolianYuyueService.deleteBatchIds(Arrays.asList(ids)); // 调用服务层批量删除 + return R.ok(); // 返回成功信息 + } + + + //批量上传 + //处理批量导入数据请求 + @RequestMapping("/batchInsert") // 映射批量导入请求 + public R save(String fileName, HttpServletRequest request){ + logger.debug("batchInsert方法:,,Controller:{},,fileName:{}",this.getClass().getName(),fileName); // 记录请求日志 + Integer yonghuId = Integer.valueOf(String.valueOf(request.getSession().getAttribute("userId"))); // 获取用户ID + SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); // 创建日期格式化对象 + try { + List jiaolianYuyueList = new ArrayList<>(); // 创建数据列表 + Map> seachFields = new HashMap<>(); // 创建查询字段映射 + Date date = new Date(); // 当前时间 + int lastIndexOf = fileName.lastIndexOf("."); // 获取文件后缀位置 + if(lastIndexOf == -1){ // 如果没有后缀 + return R.error(511,"该文件没有后缀"); // 返回错误信息 + }else{ + String suffix = fileName.substring(lastIndexOf); // 获取文件后缀 + if(!".xls".equals(suffix)){ // 如果不是xls文件 + return R.error(511,"只支持后缀为xls的excel文件"); // 返回错误信息 + }else{ + URL resource = this.getClass().getClassLoader().getResource("static/upload/" + fileName); // 获取文件路径 + File file = new File(resource.getFile()); // 创建文件对象 + if(!file.exists()){ // 如果文件不存在 + return R.error(511,"找不到上传文件,请联系管理员"); // 返回错误信息 + }else{ + List> dataList = PoiUtil.poiImport(file.getPath()); // 读取Excel文件 + dataList.remove(0); // 删除标题行 + for(List data:dataList){ // 遍历数据行 + JiaolianYuyueEntity jiaolianYuyueEntity = new JiaolianYuyueEntity(); // 创建实体对象 + jiaolianYuyueList.add(jiaolianYuyueEntity); // 添加到列表 + + // 检查预约编号是否重复 + if(seachFields.containsKey("jiaolianYuyueUuidNumber")){ + List jiaolianYuyueUuidNumber = seachFields.get("jiaolianYuyueUuidNumber"); + jiaolianYuyueUuidNumber.add(data.get(0)); + }else{ + List jiaolianYuyueUuidNumber = new ArrayList<>(); + jiaolianYuyueUuidNumber.add(data.get(0)); + seachFields.put("jiaolianYuyueUuidNumber",jiaolianYuyueUuidNumber); + } + } + + // 检查预约编号是否已存在 +>>>>>>> develop List jiaolianYuyueEntities_jiaolianYuyueUuidNumber = jiaolianYuyueService.selectList(new EntityWrapper().in("jiaolian_yuyue_uuid_number", seachFields.get("jiaolianYuyueUuidNumber"))); if(jiaolianYuyueEntities_jiaolianYuyueUuidNumber.size() >0 ){ ArrayList repeatFields = new ArrayList<>(); @@ -284,18 +533,29 @@ public class JiaolianYuyueController { } return R.error(511,"数据库的该表中的 [预约编号] 字段已经存在 存在数据为:"+repeatFields.toString()); } +<<<<<<< HEAD jiaolianYuyueService.insertBatch(jiaolianYuyueList); return R.ok(); +======= + jiaolianYuyueService.insertBatch(jiaolianYuyueList); // 批量插入数据 + return R.ok(); // 返回成功信息 +>>>>>>> develop } } } }catch (Exception e){ +<<<<<<< HEAD e.printStackTrace(); return R.error(511,"批量插入数据异常,请联系管理员"); +======= + e.printStackTrace(); // 打印异常堆栈 + return R.error(511,"批量插入数据异常,请联系管理员"); // 返回错误信息 +>>>>>>> develop } } +<<<<<<< HEAD /** @@ -381,3 +641,79 @@ public class JiaolianYuyueController { } +======= + //前端列表 + //处理前端分页查询请求 + @IgnoreAuth // 忽略认证 + @RequestMapping("/list") // 映射列表查询请求 + public R list(@RequestParam Map params, HttpServletRequest request){ + logger.debug("list方法:,,Controller:{},,params:{}",this.getClass().getName(),JSONObject.toJSONString(params)); // 记录请求日志 + CommonUtil.checkMap(params); // 检查参数有效性 + PageUtils page = jiaolianYuyueService.queryPage(params); // 调用服务层查询分页数据 + + // 字典表数据转换 + List list =(List)page.getList(); // 获取分页数据列表 + for(JiaolianYuyueView c:list){ // 遍历列表 + dictionaryService.dictionaryConvert(c, request); // 转换字典字段 + } + return R.ok().put("data", page); // 返回分页数据 + } + + + //前端详情 + //处理前端详情查询请求 + @RequestMapping("/detail/{id}") // 映射详情查询请求 + public R detail(@PathVariable("id") Integer id, HttpServletRequest request){ + logger.debug("detail方法:,,Controller:{},,id:{}",this.getClass().getName(),id); // 记录请求日志 + JiaolianYuyueEntity jiaolianYuyue = jiaolianYuyueService.selectById(id); // 根据ID查询预约 + if(jiaolianYuyue !=null){ // 如果查询到数据 + JiaolianYuyueView view = new JiaolianYuyueView(); // 创建视图对象 + BeanUtils.copyProperties(jiaolianYuyue, view); // 复制属性到视图对象 + + // 查询关联的用户信息 + YonghuEntity yonghu = yonghuService.selectById(jiaolianYuyue.getYonghuId()); + if(yonghu != null){ + BeanUtils.copyProperties(yonghu, view, new String[]{ "id", "createTime", "insertTime", "updateTime", "username", "password", "newMoney", "yonghuId"}); + view.setYonghuId(yonghu.getId()); + } + + dictionaryService.dictionaryConvert(view, request); // 转换字典字段 + return R.ok().put("data", view); // 返回详情数据 + }else { + return R.error(511,"查不到数据"); // 返回错误信息 + } + } + + + //前端保存 + //处理前端新增预约请求 + @RequestMapping("/add") // 映射新增请求 + public R add(@RequestBody JiaolianYuyueEntity jiaolianYuyue, HttpServletRequest request){ + logger.debug("add方法:,,Controller:{},,jiaolianYuyue:{}",this.getClass().getName(),jiaolianYuyue.toString()); // 记录请求日志 + // 构建查询条件,检查是否存在相同用户的待审核或已通过的预约 + Wrapper queryWrapper = new EntityWrapper() + .eq("jiaolian_yuyue_uuid_number", jiaolianYuyue.getJiaolianYuyueUuidNumber()) + .eq("yonghu_id", jiaolianYuyue.getYonghuId()) + .eq("jiaolian_yuyue_text", jiaolianYuyue.getJiaolianYuyueText()) + .in("jiaolian_yuyue_yesno_types", new Integer[]{1,2}) + .eq("jiaolian_yuyue_yesno_text", jiaolianYuyue.getJiaolianYuyueYesnoText()); + + logger.info("sql语句:"+queryWrapper.getSqlSegment()); // 记录SQL语句 + JiaolianYuyueEntity jiaolianYuyueEntity = jiaolianYuyueService.selectOne(queryWrapper); // 查询是否存在重复数据 + if(jiaolianYuyueEntity==null){ // 如果没有重复数据 + jiaolianYuyue.setJiaolianYuyueYesnoTypes(1); // 设置状态为待审核 + jiaolianYuyue.setInsertTime(new Date()); // 设置插入时间 + jiaolianYuyue.setCreateTime(new Date()); // 设置创建时间 + jiaolianYuyueService.insert(jiaolianYuyue); // 调用服务层保存数据 + return R.ok(); // 返回成功信息 + }else { // 如果存在重复数据 + if(jiaolianYuyueEntity.getJiaolianYuyueYesnoTypes()==1) // 如果是待审核状态 + return R.error(511,"有相同的待审核的数据"); // 返回错误信息 + else if(jiaolianYuyueEntity.getJiaolianYuyueYesnoTypes()==2) // 如果是已通过状态 + return R.error(511,"有相同的审核通过的数据"); // 返回错误信息 + else + return R.error(511,"表中有相同数据"); // 返回错误信息 + } + } +} +>>>>>>> develop diff --git a/src/main/java/com/controller/NewsController.java b/src/main/java/com/controller/NewsController.java index 0e04ff6..b7c4373 100644 --- a/src/main/java/com/controller/NewsController.java +++ b/src/main/java/com/controller/NewsController.java @@ -1,3 +1,4 @@ +<<<<<<< HEAD package com.controller; @@ -38,12 +39,55 @@ import com.alibaba.fastjson.*; * @author * @email */ +======= +package com.controller; // 定义包名为com.controller + +import java.io.File; // 文件操作类 +import java.math.BigDecimal; // 大数字处理类 +import java.net.URL; // 统一资源定位符类 +import java.text.SimpleDateFormat; // 日期格式化类 +import com.alibaba.fastjson.JSONObject; // 阿里巴巴FastJSON库的JSON对象类 +import java.util.*; // 通用工具类集合 +import org.springframework.beans.BeanUtils; // Spring Bean工具类 +import javax.servlet.http.HttpServletRequest; // HTTP请求处理类 +import org.springframework.web.context.ContextLoader; // Spring上下文加载器 +import javax.servlet.ServletContext; // Servlet上下文接口 +import com.service.TokenService; // 自定义Token服务类 +import com.utils.*; // 自定义工具类包 +import java.lang.reflect.InvocationTargetException; // 反射异常类 + +import com.service.DictionaryService; // 自定义字典服务类 +import org.apache.commons.lang3.StringUtils; // Apache字符串工具类 +import com.annotation.IgnoreAuth; // 自定义忽略认证注解 +import org.slf4j.Logger; // 日志接口 +import org.slf4j.LoggerFactory; // 日志工厂类 +import org.springframework.beans.factory.annotation.Autowired; // Spring自动注入注解 +import org.springframework.stereotype.Controller; // Spring控制器注解 +import org.springframework.web.bind.annotation.*; // Spring Web注解集合 +import com.baomidou.mybatisplus.mapper.EntityWrapper; // MyBatis Plus实体包装器 +import com.baomidou.mybatisplus.mapper.Wrapper; // MyBatis Plus包装器接口 +import com.entity.*; // 自定义实体类包 +import com.entity.view.*; // 自定义视图类包 +import com.service.*; // 自定义服务类包 +import com.utils.PageUtils; // 自定义分页工具类 +import com.utils.R; // 自定义返回结果类 +import com.alibaba.fastjson.*; // 阿里巴巴FastJSON库 + + + + //健身资讯 + //后端接口 + //@author + // @email + +>>>>>>> develop @RestController @Controller @RequestMapping("/news") public class NewsController { private static final Logger logger = LoggerFactory.getLogger(NewsController.class); +<<<<<<< HEAD private static final String TABLE_NAME = "news"; @Autowired @@ -123,10 +167,98 @@ public class NewsController { /** * 后端保存 */ +======= + private static final String TABLE_NAME = "news"; // 数据库表名 + + @Autowired + private NewsService newsService; // 健身资讯服务 + + @Autowired + private TokenService tokenService; // token服务 + + @Autowired + private DictionaryService dictionaryService; // 字典服务 + @Autowired + private ForumService forumService; // 健身论坛服务 + @Autowired + private JianshenkechengService jianshenkechengService; // 健身课程服务 + @Autowired + private JianshenkechengCollectionService jianshenkechengCollectionService; // 课程收藏服务 + @Autowired + private JianshenkechengLiuyanService jianshenkechengLiuyanService; // 课程留言服务 + @Autowired + private JiaolianService jiaolianService; // 教练服务 + @Autowired + private JiaolianYuyueService jiaolianYuyueService; // 教练预约申请服务 + @Autowired + private SingleSeachService singleSeachService; // 单页数据服务 + @Autowired + private YonghuService yonghuService; // 用户服务 + @Autowired + private UsersService usersService; // 管理员服务 + + + //后端列表 + //分页查询健身资讯数据 + //@param params 请求参数,包含分页和查询条件 + //@param request HTTP请求对象 + //@return 返回分页数据和状态信息 + @RequestMapping("/page") + public R page(@RequestParam Map params, HttpServletRequest request){ + logger.debug("page方法:,,Controller:{},,params:{}",this.getClass().getName(),JSONObject.toJSONString(params)); + String role = String.valueOf(request.getSession().getAttribute("role")); // 获取用户角色 + if(false) + return R.error(511,"永不会进入"); + else if("用户".equals(role)) + params.put("yonghuId",request.getSession().getAttribute("userId")); // 如果是用户角色,添加用户ID查询条件 + else if("教练".equals(role)) + params.put("jiaolianId",request.getSession().getAttribute("userId")); // 如果是教练角色,添加教练ID查询条件 + CommonUtil.checkMap(params); // 检查参数 + PageUtils page = newsService.queryPage(params); // 分页查询 + + // 字典表数据转换 + List list =(List)page.getList(); + for(NewsView c:list){ + // 修改对应字典表字段 + dictionaryService.dictionaryConvert(c, request); + } + return R.ok().put("data", page); // 返回成功和数据 + } + + + //后端详情 + //根据ID查询单条健身资讯详情 + //@param id 资讯ID + //@param request HTTP请求对象 + //@return 返回资讯详情和状态信息 + @RequestMapping("/info/{id}") + public R info(@PathVariable("id") Long id, HttpServletRequest request){ + logger.debug("info方法:,,Controller:{},,id:{}",this.getClass().getName(),id); + NewsEntity news = newsService.selectById(id); // 根据ID查询资讯 + if(news !=null){ + // entity转view + NewsView view = new NewsView(); + BeanUtils.copyProperties( news , view ); // 把实体数据重构到view中 + // 修改对应字典表字段 + dictionaryService.dictionaryConvert(view, request); + return R.ok().put("data", view); // 返回成功和数据 + }else { + return R.error(511,"查不到数据"); // 返回错误信息 + } + } + + + //后端保存 + //新增健身资讯 + //@param news 资讯实体 + //@param request HTTP请求对象 + //@return 返回操作结果状态 +>>>>>>> develop @RequestMapping("/save") public R save(@RequestBody NewsEntity news, HttpServletRequest request){ logger.debug("save方法:,,Controller:{},,news:{}",this.getClass().getName(),news.toString()); +<<<<<<< HEAD String role = String.valueOf(request.getSession().getAttribute("role")); if(false) return R.error(511,"永远不会进入"); @@ -218,10 +350,109 @@ public class NewsController { NewsEntity newsEntity = new NewsEntity(); // newsEntity.setNewsName(data.get(0)); //资讯标题 要改的 // newsEntity.setNewsTypes(Integer.valueOf(data.get(0))); //资讯类型 要改的 +======= + String role = String.valueOf(request.getSession().getAttribute("role")); // 获取用户角色 + if(false) + return R.error(511,"永远不会进入"); + + // 构建查询条件 + Wrapper queryWrapper = new EntityWrapper() + .eq("news_name", news.getNewsName()) // 资讯标题相等 + .eq("news_types", news.getNewsTypes()) // 资讯类型相等 + ; + + logger.info("sql语句:"+queryWrapper.getSqlSegment()); + NewsEntity newsEntity = newsService.selectOne(queryWrapper); // 查询是否已存在 + if(newsEntity==null){ + news.setInsertTime(new Date()); // 设置插入时间 + news.setCreateTime(new Date()); // 设置创建时间 + newsService.insert(news); // 插入新数据 + return R.ok(); // 返回成功 + }else { + return R.error(511,"表中有相同数据"); // 返回错误信息 + } + } + + //后端修改 + //更新健身资讯 + //@param news 资讯实体 + //@param request HTTP请求对象 + //@return 返回操作结果状态 + @RequestMapping("/update") + public R update(@RequestBody NewsEntity news, HttpServletRequest request) throws NoSuchFieldException, ClassNotFoundException, IllegalAccessException, InstantiationException { + logger.debug("update方法:,,Controller:{},,news:{}",this.getClass().getName(),news.toString()); + NewsEntity oldNewsEntity = newsService.selectById(news.getId()); // 查询原先数据 + + String role = String.valueOf(request.getSession().getAttribute("role")); // 获取用户角色 +// if(false) +// return R.error(511,"永远不会进入"); + if("".equals(news.getNewsPhoto()) || "null".equals(news.getNewsPhoto())){ + news.setNewsPhoto(null); // 如果图片为空,设置为null + } + if("".equals(news.getNewsContent()) || "null".equals(news.getNewsContent())){ + news.setNewsContent(null); // 如果内容为空,设置为null + } + + newsService.updateById(news); // 根据id更新 + return R.ok(); // 返回成功 + } + + + //删除 + //批量删除健身资讯 + //@param ids 要删除的资讯ID数组 + //@param request HTTP请求对象 + //@return 返回操作结果状态 + @RequestMapping("/delete") + public R delete(@RequestBody Integer[] ids, HttpServletRequest request){ + logger.debug("delete:,,Controller:{},,ids:{}",this.getClass().getName(),ids.toString()); + List oldNewsList =newsService.selectBatchIds(Arrays.asList(ids)); // 查询要删除的数据 + newsService.deleteBatchIds(Arrays.asList(ids)); // 批量删除 + + return R.ok(); // 返回成功 + } + + + //批量上传 + //通过Excel文件批量导入健身资讯数据 + //@param fileName Excel文件名 + //@param request HTTP请求对象 + //@return 返回操作结果状态 + @RequestMapping("/batchInsert") + public R save( String fileName, HttpServletRequest request){ + logger.debug("batchInsert方法:,,Controller:{},,fileName:{}",this.getClass().getName(),fileName); + Integer yonghuId = Integer.valueOf(String.valueOf(request.getSession().getAttribute("userId"))); // 获取用户ID + SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); // 日期格式化 + try { + List newsList = new ArrayList<>(); // 存储上传的数据 + Map> seachFields= new HashMap<>(); // 要查询的字段 + Date date = new Date(); + int lastIndexOf = fileName.lastIndexOf("."); // 获取文件后缀 + if(lastIndexOf == -1){ + return R.error(511,"该文件没有后缀"); // 返回错误信息 + }else{ + String suffix = fileName.substring(lastIndexOf); // 获取文件后缀 + if(!".xls".equals(suffix)){ + return R.error(511,"只支持后缀为xls的excel文件"); // 返回错误信息 + }else{ + URL resource = this.getClass().getClassLoader().getResource("static/upload/" + fileName); // 获取文件路径 + File file = new File(resource.getFile()); + if(!file.exists()){ + return R.error(511,"找不到上传文件,请联系管理员"); // 返回错误信息 + }else{ + List> dataList = PoiUtil.poiImport(file.getPath()); // 读取xls文件 + dataList.remove(0); // 删除第一行,因为第一行是提示 + for(List data:dataList){ + // 循环处理每行数据 + NewsEntity newsEntity = new NewsEntity(); +// newsEntity.setNewsName(data.get(0)); // 资讯标题 要改的 +// newsEntity.setNewsTypes(Integer.valueOf(data.get(0))); // 资讯类型 要改的 +>>>>>>> develop // newsEntity.setNewsPhoto("");//详情和图片 // newsEntity.setInsertTime(date);//时间 // newsEntity.setNewsContent("");//详情和图片 // newsEntity.setCreateTime(date);//时间 +<<<<<<< HEAD newsList.add(newsEntity); @@ -231,26 +462,49 @@ public class NewsController { //查询是否重复 newsService.insertBatch(newsList); return R.ok(); +======= + newsList.add(newsEntity); // 添加到列表 + + // 把要查询是否重复的字段放入map中 + } + + // 查询是否重复 + newsService.insertBatch(newsList); // 批量插入 + return R.ok(); // 返回成功 +>>>>>>> develop } } } }catch (Exception e){ e.printStackTrace(); +<<<<<<< HEAD return R.error(511,"批量插入数据异常,请联系管理员"); +======= + return R.error(511,"批量插入数据异常,请联系管理员"); // 返回错误信息 +>>>>>>> develop } } +<<<<<<< HEAD /** * 前端列表 */ +======= + //前端列表 + //分页查询健身资讯数据(无需认证) + //@param params 请求参数,包含分页和查询条件 + //@param request HTTP请求对象 + //@return 返回分页数据和状态信息 +>>>>>>> develop @IgnoreAuth @RequestMapping("/list") public R list(@RequestParam Map params, HttpServletRequest request){ logger.debug("list方法:,,Controller:{},,params:{}",this.getClass().getName(),JSONObject.toJSONString(params)); +<<<<<<< HEAD CommonUtil.checkMap(params); PageUtils page = newsService.queryPage(params); @@ -288,10 +542,53 @@ public class NewsController { /** * 前端保存 */ +======= + CommonUtil.checkMap(params); // 检查参数 + PageUtils page = newsService.queryPage(params); // 分页查询 + + // 字典表数据转换 + List list =(List)page.getList(); + for(NewsView c:list) + dictionaryService.dictionaryConvert(c, request); // 修改对应字典表字段 + + return R.ok().put("data", page); // 返回成功和数据 + } + + + //前端详情 + //根据ID查询单条健身资讯详情 + //@param id 资讯ID + //@param request HTTP请求对象 + //@return 返回资讯详情和状态信息 + @RequestMapping("/detail/{id}") + public R detail(@PathVariable("id") Integer id, HttpServletRequest request){ + logger.debug("detail方法:,,Controller:{},,id:{}",this.getClass().getName(),id); + NewsEntity news = newsService.selectById(id); // 根据ID查询资讯 + if(news !=null){ + // entity转view + NewsView view = new NewsView(); + BeanUtils.copyProperties( news , view ); // 把实体数据重构到view中 + + // 修改对应字典表字段 + dictionaryService.dictionaryConvert(view, request); + return R.ok().put("data", view); // 返回成功和数据 + }else { + return R.error(511,"查不到数据"); // 返回错误信息 + } + } + + + //前端保存 + //新增健身资讯 + //@param news 资讯实体 + //@param request HTTP请求对象 + //@return 返回操作结果状态 +>>>>>>> develop @RequestMapping("/add") public R add(@RequestBody NewsEntity news, HttpServletRequest request){ logger.debug("add方法:,,Controller:{},,news:{}",this.getClass().getName(),news.toString()); Wrapper queryWrapper = new EntityWrapper() +<<<<<<< HEAD .eq("news_name", news.getNewsName()) .eq("news_types", news.getNewsTypes()) // .notIn("news_types", new Integer[]{102}) @@ -311,3 +608,22 @@ public class NewsController { } +======= + .eq("news_name", news.getNewsName()) // 资讯标题相等 + .eq("news_types", news.getNewsTypes()) // 资讯类型相等 +// .notIn("news_types", new Integer[]{102}) + ; + logger.info("sql语句:"+queryWrapper.getSqlSegment()); + NewsEntity newsEntity = newsService.selectOne(queryWrapper); // 查询是否已存在 + if(newsEntity==null){ + news.setInsertTime(new Date()); // 设置插入时间 + news.setCreateTime(new Date()); // 设置创建时间 + newsService.insert(news); // 插入新数据 + + return R.ok(); // 返回成功 + }else { + return R.error(511,"表中有相同数据"); // 返回错误信息 + } + } +} +>>>>>>> develop diff --git a/src/main/java/com/controller/SingleSeachController.java b/src/main/java/com/controller/SingleSeachController.java index 72d3a85..1584c4a 100644 --- a/src/main/java/com/controller/SingleSeachController.java +++ b/src/main/java/com/controller/SingleSeachController.java @@ -1,3 +1,4 @@ +<<<<<<< HEAD package com.controller; @@ -234,10 +235,246 @@ public class SingleSeachController { }catch (Exception e){ e.printStackTrace(); return R.error(511,"批量插入数据异常,请联系管理员"); +======= +// 声明当前文件所在的包路径 +package com.controller; + +// 导入所需的Java类库 +import java.io.File; // 文件操作类 +import java.math.BigDecimal; // 高精度数字计算类 +import java.net.URL; // 统一资源定位符类 +import java.text.SimpleDateFormat; // 日期格式化类 +import com.alibaba.fastjson.JSONObject; // FastJSON的JSON对象类 +import java.util.*; // 通用工具类集合 +import org.springframework.beans.BeanUtils; // Spring Bean工具类 +import javax.servlet.http.HttpServletRequest; // HTTP请求类 +import org.springframework.web.context.ContextLoader; // Spring上下文加载器 +import javax.servlet.ServletContext; // Servlet上下文接口 +import com.service.TokenService; // 自定义Token服务类 +import com.utils.*; // 自定义工具类包 +import java.lang.reflect.InvocationTargetException; // 反射异常类 + +// 导入自定义服务类 +import com.service.DictionaryService; // 字典服务类 +import org.apache.commons.lang3.StringUtils; // Apache字符串工具类 +import com.annotation.IgnoreAuth; // 自定义忽略认证注解 +import org.slf4j.Logger; // 日志接口 +import org.slf4j.LoggerFactory; // 日志工厂类 +import org.springframework.beans.factory.annotation.Autowired; // Spring自动注入注解 +import org.springframework.stereotype.Controller; // Spring控制器注解 +import org.springframework.web.bind.annotation.*; // Spring Web注解集合 +import com.baomidou.mybatisplus.mapper.EntityWrapper; // MyBatis Plus实体包装类 +import com.baomidou.mybatisplus.mapper.Wrapper; // MyBatis Plus包装接口 +import com.entity.*; // 实体类包 +import com.entity.view.*; // 实体视图类包 +import com.service.*; // 服务接口包 +import com.utils.PageUtils; // 分页工具类 +import com.utils.R; // 通用返回结果类 +import com.alibaba.fastjson.*; // FastJSON工具包 + + + //单页数据 + //后端接口控制器 + //@author + //@email + +@RestController // 标识这是一个RESTful风格的控制器 +@Controller // 标识这是一个Spring MVC控制器 +@RequestMapping("/singleSeach") // 定义基础请求路径 +public class SingleSeachController { + private static final Logger logger = LoggerFactory.getLogger(SingleSeachController.class); // 日志记录器 + + private static final String TABLE_NAME = "singleSeach"; // 数据库表名常量 + + @Autowired + private SingleSeachService singleSeachService; // 注入单页数据服务 + + @Autowired + private TokenService tokenService; // 注入token服务 + + // 注入其他相关服务 + @Autowired + private DictionaryService dictionaryService; // 字典服务 + @Autowired + private ForumService forumService; // 健身论坛服务 + @Autowired + private JianshenkechengService jianshenkechengService; // 健身课程服务 + @Autowired + private JianshenkechengCollectionService jianshenkechengCollectionService; // 课程收藏服务 + @Autowired + private JianshenkechengLiuyanService jianshenkechengLiuyanService; // 课程留言服务 + @Autowired + private JiaolianService jiaolianService; // 教练服务 + @Autowired + private JiaolianYuyueService jiaolianYuyueService; // 教练预约申请服务 + @Autowired + private NewsService newsService; // 健身资讯服务 + @Autowired + private YonghuService yonghuService; // 用户服务 + @Autowired + private UsersService usersService; // 管理员服务 + + + //后端列表 + //分页查询单页数据 + //@param params 请求参数Map + //@param request HTTP请求对象 + //@return 返回分页数据结果 + + @RequestMapping("/page") + public R page(@RequestParam Map params, HttpServletRequest request){ + logger.debug("page方法:,,Controller:{},,params:{}",this.getClass().getName(),JSONObject.toJSONString(params)); // 记录日志 + String role = String.valueOf(request.getSession().getAttribute("role")); // 获取用户角色 + if(false) // 条件判断 + return R.error(511,"永不会进入"); // 返回错误信息 + else if("用户".equals(role)) // 如果是用户角色 + params.put("yonghuId",request.getSession().getAttribute("userId")); // 添加用户ID参数 + else if("教练".equals(role)) // 如果是教练角色 + params.put("jiaolianId",request.getSession().getAttribute("userId")); // 添加教练ID参数 + CommonUtil.checkMap(params); // 检查参数 + PageUtils page = singleSeachService.queryPage(params); // 调用服务层分页查询 + + // 字典表数据转换 + List list =(List)page.getList(); // 获取分页数据列表 + for(SingleSeachView c:list){ // 遍历列表 + dictionaryService.dictionaryConvert(c, request); // 转换字典表字段 + } + return R.ok().put("data", page); // 返回成功结果和数据 + } + + + //后端详情 + //根据ID查询单条单页数据详情 + //@param id 数据ID + //@param request HTTP请求对象 + //@return 返回查询结果 + @RequestMapping("/info/{id}") + public R info(@PathVariable("id") Long id, HttpServletRequest request){ + logger.debug("info方法:,,Controller:{},,id:{}",this.getClass().getName(),id); // 记录日志 + SingleSeachEntity singleSeach = singleSeachService.selectById(id); // 根据ID查询数据 + if(singleSeach !=null){ // 如果查询到数据 + SingleSeachView view = new SingleSeachView(); // 创建视图对象 + BeanUtils.copyProperties(singleSeach, view); // 复制属性到视图对象 + dictionaryService.dictionaryConvert(view, request); // 转换字典表字段 + return R.ok().put("data", view); // 返回成功结果和数据 + }else { + return R.error(511,"查不到数据"); // 返回错误信息 + } + } + + + //后端保存 + //新增单页数据 + //@param singleSeach 单页数据实体 + //@param request HTTP请求对象 + //@return 返回操作结果 + //@RequestMapping("/save") + public R save(@RequestBody SingleSeachEntity singleSeach, HttpServletRequest request){ + logger.debug("save方法:,,Controller:{},,singleSeach:{}",this.getClass().getName(),singleSeach.toString()); // 记录日志 + String role = String.valueOf(request.getSession().getAttribute("role")); // 获取用户角色 + if(false) // 条件判断 + return R.error(511,"永远不会进入"); // 返回错误信息 + + // 构建查询条件 + Wrapper queryWrapper = new EntityWrapper() + .eq("single_seach_types",singleSeach.getSingleSeachTypes()); // 按类型查询 + + logger.info("sql语句:"+queryWrapper.getSqlSegment()); // 记录SQL语句 + SingleSeachEntity singleSeachEntity = singleSeachService.selectOne(queryWrapper); // 查询是否存在 + if(singleSeachEntity==null){ // 如果不存在 + singleSeach.setCreateTime(new Date()); // 设置创建时间 + singleSeachService.insert(singleSeach); // 插入新数据 + return R.ok(); // 返回成功结果 + }else { + return R.error(511,"该类型已经有存在的,请删除后重新新增"); // 返回错误信息 + } + } + + //后端修改 + //更新单页数据 + //@param singleSeach 单页数据实体 + //@param request HTTP请求对象 + //@return 返回操作结果 + @RequestMapping("/update") + public R update(@RequestBody SingleSeachEntity singleSeach, HttpServletRequest request) throws NoSuchFieldException, ClassNotFoundException, IllegalAccessException, InstantiationException { + logger.debug("update方法:,,Controller:{},,singleSeach:{}",this.getClass().getName(),singleSeach.toString()); // 记录日志 + SingleSeachEntity oldSingleSeachEntity = singleSeachService.selectById(singleSeach.getId()); // 查询原数据 + + String role = String.valueOf(request.getSession().getAttribute("role")); // 获取用户角色 + if("".equals(singleSeach.getSingleSeachPhoto()) || "null".equals(singleSeach.getSingleSeachPhoto())){ // 如果图片为空 + singleSeach.setSingleSeachPhoto(null); // 设置为null + } + if("".equals(singleSeach.getSingleSeachContent()) || "null".equals(singleSeach.getSingleSeachContent())){ // 如果内容为空 + singleSeach.setSingleSeachContent(null); // 设置为null + } + + singleSeachService.updateById(singleSeach); // 更新数据 + return R.ok(); // 返回成功结果 + } + + + //删除 + //批量删除单页数据 + //@param ids 要删除的ID数组 + //@param request HTTP请求对象 + //@return 返回操作结果 + @RequestMapping("/delete") + public R delete(@RequestBody Integer[] ids, HttpServletRequest request){ + logger.debug("delete:,,Controller:{},,ids:{}",this.getClass().getName(),ids.toString()); // 记录日志 + List oldSingleSeachList = singleSeachService.selectBatchIds(Arrays.asList(ids)); // 查询要删除的数据 + singleSeachService.deleteBatchIds(Arrays.asList(ids)); // 批量删除 + return R.ok(); // 返回成功结果 + } + + + //批量上传/ + //通过Excel批量导入数据 + //@param fileName Excel文件名 + //@param request HTTP请求对象 + //@return 返回操作结果 + @RequestMapping("/batchInsert") + public R save(String fileName, HttpServletRequest request){ + logger.debug("batchInsert方法:,,Controller:{},,fileName:{}",this.getClass().getName(),fileName); // 记录日志 + Integer yonghuId = Integer.valueOf(String.valueOf(request.getSession().getAttribute("userId"))); // 获取用户ID + SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); // 创建日期格式化对象 + try { + List singleSeachList = new ArrayList<>(); // 创建数据列表 + Map> seachFields = new HashMap<>(); // 创建查询字段Map + Date date = new Date(); // 当前时间 + int lastIndexOf = fileName.lastIndexOf("."); // 获取文件后缀位置 + if(lastIndexOf == -1){ // 如果没有后缀 + return R.error(511,"该文件没有后缀"); // 返回错误信息 + }else{ + String suffix = fileName.substring(lastIndexOf); // 获取文件后缀 + if(!".xls".equals(suffix)){ // 如果不是xls文件 + return R.error(511,"只支持后缀为xls的excel文件"); // 返回错误信息 + }else{ + URL resource = this.getClass().getClassLoader().getResource("static/upload/" + fileName); // 获取文件路径 + File file = new File(resource.getFile()); // 创建文件对象 + if(!file.exists()){ // 如果文件不存在 + return R.error(511,"找不到上传文件,请联系管理员"); // 返回错误信息 + }else{ + List> dataList = PoiUtil.poiImport(file.getPath()); // 读取Excel文件 + dataList.remove(0); // 删除标题行 + for(List data:dataList){ // 遍历数据行 + SingleSeachEntity singleSeachEntity = new SingleSeachEntity(); // 创建实体对象 + // 可以在此处设置实体属性,示例中被注释掉了 + singleSeachList.add(singleSeachEntity); // 添加到列表 + } + singleSeachService.insertBatch(singleSeachList); // 批量插入 + return R.ok(); // 返回成功结果 + } + } + } + }catch (Exception e){ // 捕获异常 + e.printStackTrace(); // 打印异常堆栈 + return R.error(511,"批量插入数据异常,请联系管理员"); // 返回错误信息 +>>>>>>> develop } } +<<<<<<< HEAD /** @@ -298,3 +535,65 @@ public class SingleSeachController { } +======= + //前端列表 + //无需认证的分页查询 + //@param params 请求参数Map + //@param request HTTP请求对象 + //@return 返回分页数据结果 + @IgnoreAuth // 忽略认证 + @RequestMapping("/list") + public R list(@RequestParam Map params, HttpServletRequest request){ + logger.debug("list方法:,,Controller:{},,params:{}",this.getClass().getName(),JSONObject.toJSONString(params)); // 记录日志 + CommonUtil.checkMap(params); // 检查参数 + PageUtils page = singleSeachService.queryPage(params); // 分页查询 + + List list = (List)page.getList(); // 获取数据列表 + for(SingleSeachView c:list) // 遍历列表 + dictionaryService.dictionaryConvert(c, request); // 转换字典表字段 + + return R.ok().put("data", page); // 返回成功结果和数据 + } + + + //前端详情 + //根据类型查询单条数据 + //@param id 数据类型ID + //@param request HTTP请求对象 + //@return 返回查询结果 + @RequestMapping("/detail/{id}") + public R detail(@PathVariable("id") Integer id, HttpServletRequest request){ + logger.debug("detail方法:,,Controller:{},,id:{}",this.getClass().getName(),id); // 记录日志 + // 根据类型查询单条数据 + SingleSeachEntity singleSeach = singleSeachService.selectOne(new EntityWrapper().eq("single_seach_types", id)); + if(singleSeach != null) // 如果查询到数据 + return R.ok().put("data", singleSeach); // 返回成功结果和数据 + else + return R.error(511,"查不到数据"); // 返回错误信息 + } + + + //前端保存 + //新增单页数据 + //@param singleSeach 单页数据实体 + //@param request HTTP请求对象 + //@return 返回操作结果 + @RequestMapping("/add") + public R add(@RequestBody SingleSeachEntity singleSeach, HttpServletRequest request){ + logger.debug("add方法:,,Controller:{},,singleSeach:{}",this.getClass().getName(),singleSeach.toString()); // 记录日志 + // 构建查询条件 + Wrapper queryWrapper = new EntityWrapper() + .eq("single_seach_types",singleSeach.getSingleSeachTypes()); // 按类型查询 + + logger.info("sql语句:"+queryWrapper.getSqlSegment()); // 记录SQL语句 + SingleSeachEntity singleSeachEntity = singleSeachService.selectOne(queryWrapper); // 查询是否已存在 + if(singleSeachEntity==null){ // 如果不存在 + singleSeach.setCreateTime(new Date()); // 设置创建时间 + singleSeachService.insert(singleSeach); // 插入新数据 + return R.ok(); // 返回成功结果 + }else { + return R.error(511,"该类型已经有存在的,请删除后重新新增"); // 返回错误信息 + } + } +} +>>>>>>> develop diff --git a/src/main/java/com/controller/UsersController.java b/src/main/java/com/controller/UsersController.java index 4fe5a2c..81b8f20 100644 --- a/src/main/java/com/controller/UsersController.java +++ b/src/main/java/com/controller/UsersController.java @@ -1,3 +1,4 @@ +<<<<<<< HEAD package com.controller; @@ -190,3 +191,241 @@ public class UsersController { return R.ok(); } } +======= +package com.controller; // 声明当前类所在的包路径 + +// 导入Java集合类 +import java.util.List; // 列表接口 +import java.util.Arrays; // 数组工具类 +import java.util.Map; // 映射接口 + +// 导入Servlet相关类 +import javax.servlet.http.HttpServletRequest; // HTTP请求对象 + +// 导入服务类 +import com.service.UsersService; // 用户服务接口 + +// 导入Spring框架注解 +import org.springframework.beans.factory.annotation.Autowired; // 自动注入注解 +import org.springframework.web.bind.annotation.GetMapping; // GET请求映射注解 +import org.springframework.web.bind.annotation.PathVariable; // 路径变量注解 +import org.springframework.web.bind.annotation.PostMapping; // POST请求映射注解 +import org.springframework.web.bind.annotation.RequestBody; // 请求体注解 +import org.springframework.web.bind.annotation.RequestMapping; // 请求映射注解 +import org.springframework.web.bind.annotation.RequestParam; // 请求参数注解 +import org.springframework.web.bind.annotation.RestController; // REST控制器注解 + +// 导入自定义注解和工具类 +import com.annotation.IgnoreAuth; // 忽略认证注解 +import com.baomidou.mybatisplus.mapper.EntityWrapper; // MyBatis Plus条件构造器 +import com.entity.UsersEntity; // 用户实体类 +import com.service.TokenService; // Token服务接口 +import com.utils.MPUtil; // MyBatis Plus工具类 +import com.utils.PageUtils; // 分页工具类 +import com.utils.R; // 统一返回结果类 + +//用户登录相关功能控制器 + //处理用户认证、注册、密码管理等操作 +@RequestMapping("users") // 定义基础请求路径为/users +@RestController // 标识这是一个RESTful风格的控制器 +public class UsersController { + + @Autowired // 自动注入用户服务 + private UsersService usersService; + + @Autowired // 自动注入Token服务 + private TokenService tokenService; + + + //用户登录接口 + //@param username 用户名 + //@param password 密码 + //@param captcha 验证码(未使用) + //@param request HTTP请求对象 + //@return 返回登录结果和Token信息 + @IgnoreAuth // 忽略认证检查 + @PostMapping(value = "/login") // 处理POST /users/login请求 + public R login(String username, String password, String captcha, HttpServletRequest request) { + // 根据用户名查询用户 + UsersEntity user = usersService.selectOne(new EntityWrapper().eq("username", username)); + // 验证用户是否存在和密码是否正确 + if(user==null || !user.getPassword().equals(password)) { + return R.error("账号或密码不正确"); // 返回错误信息 + } + // 生成Token + String token = tokenService.generateToken(user.getId(),username, "users", user.getRole()); + // 构建返回结果 + R r = R.ok(); + r.put("token", token); // 返回Token + r.put("role",user.getRole()); // 返回用户角色 + r.put("userId",user.getId()); // 返回用户ID + return r; + } + + + //用户注册接口 + //@param user 用户实体对象(通过请求体传入) + //@return 返回注册结果 + @IgnoreAuth // 忽略认证检查 + @PostMapping(value = "/register") // 处理POST /users/register请求 + public R register(@RequestBody UsersEntity user){ + // 检查用户名是否已存在 + if(usersService.selectOne(new EntityWrapper().eq("username", user.getUsername())) !=null) { + return R.error("用户已存在"); // 返回错误信息 + } + usersService.insert(user); // 插入新用户 + return R.ok(); // 返回成功结果 + } + + + //用户退出接口 + //@param request HTTP请求对象 + //@return 返回退出结果 + @GetMapping(value = "logout") // 处理GET /users/logout请求 + public R logout(HttpServletRequest request) { + request.getSession().invalidate(); // 使会话失效 + return R.ok("退出成功"); // 返回成功信息 + } + + + //修改密码接口 + //@param oldPassword 旧密码 + //@param newPassword 新密码 + //@param request HTTP请求对象 + //@return 返回修改结果 + @GetMapping(value = "/updatePassword") // 处理GET /users/updatePassword请求 + public R updatePassword(String oldPassword, String newPassword, HttpServletRequest request) { + // 获取当前用户 + UsersEntity users = usersService.selectById((Integer)request.getSession().getAttribute("userId")); + // 验证新密码是否为空 + if(newPassword == null){ + return R.error("新密码不能为空") ; + } + // 验证旧密码是否正确 + if(!oldPassword.equals(users.getPassword())){ + return R.error("原密码输入错误"); + } + // 验证新密码是否与旧密码相同 + if(newPassword.equals(users.getPassword())){ + return R.error("新密码不能和原密码一致") ; + } + // 更新密码 + users.setPassword(newPassword); + usersService.updateById(users); + return R.ok(); // 返回成功结果 + } + + + //密码重置接口 + //@param username 用户名 + //@param request HTTP请求对象 + //@return 返回重置结果 + @IgnoreAuth // 忽略认证检查 + @RequestMapping(value = "/resetPass") // 处理/users/resetPass请求 + public R resetPass(String username, HttpServletRequest request){ + // 根据用户名查询用户 + UsersEntity user = usersService.selectOne(new EntityWrapper().eq("username", username)); + if(user==null) { + return R.error("账号不存在"); // 返回错误信息 + } + // 重置密码为默认值 + user.setPassword("123456"); + usersService.update(user,null); // 更新用户信息 + return R.ok("密码已重置为:123456"); // 返回成功信息 + } + + + //分页查询用户列表 + //@param params 请求参数Map + //@param user 用户实体(用于条件查询) + //@return 返回分页结果 + @RequestMapping("/page") // 处理/users/page请求 + public R page(@RequestParam Map params,UsersEntity user){ + // 创建条件构造器 + EntityWrapper ew = new EntityWrapper(); + // 构建分页查询 + PageUtils page = usersService.queryPage(params, MPUtil.sort(MPUtil.between(MPUtil.allLike(ew, user), params), params)); + return R.ok().put("data", page); // 返回分页数据 + } + + + //查询用户列表 + //@param user 用户实体(用于条件查询) + //@return 返回用户列表 + @RequestMapping("/list") // 处理/users/list请求 + public R list(UsersEntity user){ + // 创建条件构造器 + EntityWrapper ew = new EntityWrapper(); + // 构建查询条件 + ew.allEq(MPUtil.allEQMapPre(user, "user")); + return R.ok().put("data", usersService.selectListView(ew)); // 返回查询结果 + } + + + //获取用户详细信息 + //@param id 用户ID + //@return 返回用户信息 + @RequestMapping("/info/{id}") // 处理/users/info/{id}请求 + public R info(@PathVariable("id") String id){ + UsersEntity user = usersService.selectById(id); // 根据ID查询用户 + return R.ok().put("data", user); // 返回用户信息 + } + + + // 获取当前会话用户信息 + //@param request HTTP请求对象 + // @return 返回当前用户信息 + + @RequestMapping("/session") // 处理/users/session请求 + public R getCurrUser(HttpServletRequest request){ + // 从会话中获取用户ID + Integer id = (Integer)request.getSession().getAttribute("userId"); + UsersEntity user = usersService.selectById(id); // 查询用户信息 + return R.ok().put("data", user); // 返回用户信息 + } + + + //保存用户信息 + //@param user 用户实体对象(通过请求体传入) + // @return 返回保存结果 + + @PostMapping("/save") // 处理POST /users/save请求 + public R save(@RequestBody UsersEntity user){ + // 检查用户名是否已存在 + if(usersService.selectOne(new EntityWrapper().eq("username", user.getUsername())) !=null) { + return R.error("用户已存在"); // 返回错误信息 + } + usersService.insert(user); // 插入新用户 + return R.ok(); // 返回成功结果 + } + + + // 更新用户信息 + //@param user 用户实体对象(通过请求体传入) + //@return 返回更新结果 + + @RequestMapping("/update") // 处理/users/update请求 + public R update(@RequestBody UsersEntity user){ + usersService.updateById(user); // 更新用户信息 + return R.ok(); // 返回成功结果 + } + + + //删除用户 + //@param ids 用户ID数组(通过请求体传入) + // @return 返回删除结果 + + @RequestMapping("/delete") // 处理/users/delete请求 + public R delete(@RequestBody Long[] ids){ + // 查询所有用户 + List user = usersService.selectList(null); + // 确保至少保留一个管理员 + if(user.size() > 1){ + usersService.deleteBatchIds(Arrays.asList(ids)); // 批量删除用户 + }else{ + return R.error("管理员最少保留一个"); // 返回错误信息 + } + return R.ok(); // 返回成功结果 + } +} +>>>>>>> develop diff --git a/src/main/java/com/controller/YonghuController.java b/src/main/java/com/controller/YonghuController.java index 4cbdd7d..2b33dbf 100644 --- a/src/main/java/com/controller/YonghuController.java +++ b/src/main/java/com/controller/YonghuController.java @@ -1,3 +1,4 @@ +<<<<<<< HEAD package com.controller; @@ -408,10 +409,443 @@ public class YonghuController { return R.ok(); }else{ return R.error("账号不存在"); +======= +package com.controller; // 声明当前类所在的包路径 + +// 导入Java IO类 +import java.io.File; // 文件操作类 +// 导入数学类 +import java.math.BigDecimal; // 高精度数字计算类 +// 导入网络类 +import java.net.URL; // 统一资源定位符类 +// 导入文本处理类 +import java.text.SimpleDateFormat; // 日期格式化类 +// 导入JSON处理类 +import com.alibaba.fastjson.JSONObject; // FastJSON对象类 +// 导入集合类 +import java.util.*; // 通用集合工具类 +// 导入Spring Bean工具类 +import org.springframework.beans.BeanUtils; // Bean属性复制工具类 +// 导入Servlet类 +import javax.servlet.http.HttpServletRequest; // HTTP请求对象 +// 导入Spring上下文类 +import org.springframework.web.context.ContextLoader; // Web应用上下文加载器 +// 导入Servlet上下文类 +import javax.servlet.ServletContext; // Servlet上下文对象 +// 导入自定义服务类 +import com.service.TokenService; // Token服务接口 +// 导入自定义工具类 +import com.utils.*; // 自定义工具类集合 +// 导入反射异常类 +import java.lang.reflect.InvocationTargetException; // 反射调用异常类 + +// 导入字典服务类 +import com.service.DictionaryService; // 字典数据服务接口 +// 导入Apache Commons工具类 +import org.apache.commons.lang3.StringUtils; // 字符串处理工具类 +// 导入自定义注解 +import com.annotation.IgnoreAuth; // 忽略认证注解 +// 导入日志类 +import org.slf4j.Logger; // 日志接口 +import org.slf4j.LoggerFactory; // 日志工厂类 +// 导入Spring注解 +import org.springframework.beans.factory.annotation.Autowired; // 自动注入注解 +import org.springframework.stereotype.Controller; // 控制器注解 +import org.springframework.web.bind.annotation.*; // Web请求相关注解 +// 导入MyBatis Plus类 +import com.baomidou.mybatisplus.mapper.EntityWrapper; // 条件构造器 +import com.baomidou.mybatisplus.mapper.Wrapper; // 条件构造器接口 +// 导入实体类 +import com.entity.*; // 实体类集合 +import com.entity.view.*; // 视图实体类集合 +// 导入服务接口 +import com.service.*; // 服务接口集合 +// 导入分页工具类 +import com.utils.PageUtils; // 分页工具类 +// 导入返回结果类 +import com.utils.R; // 统一返回结果类 +// 导入FastJSON类 +import com.alibaba.fastjson.*; // FastJSON工具类 + + + //用户控制器 + // 处理用户相关操作的RESTful接口 + +@RestController // 标识为RESTful控制器 +@Controller // 标识为Spring MVC控制器 +@RequestMapping("/yonghu") // 基础请求路径 +public class YonghuController { + private static final Logger logger = LoggerFactory.getLogger(YonghuController.class); // 日志记录器 + + private static final String TABLE_NAME = "yonghu"; // 数据库表名常量 + + @Autowired // 自动注入用户服务 + private YonghuService yonghuService; + + @Autowired // 自动注入Token服务 + private TokenService tokenService; + + // 注入其他相关服务 + @Autowired + private DictionaryService dictionaryService; // 字典服务 + @Autowired + private ForumService forumService; // 健身论坛服务 + @Autowired + private JianshenkechengService jianshenkechengService; // 健身课程服务 + @Autowired + private JianshenkechengCollectionService jianshenkechengCollectionService; // 课程收藏服务 + @Autowired + private JianshenkechengLiuyanService jianshenkechengLiuyanService; // 课程留言服务 + @Autowired + private JiaolianService jiaolianService; // 教练服务 + @Autowired + private JiaolianYuyueService jiaolianYuyueService; // 教练预约服务 + @Autowired + private NewsService newsService; // 健身资讯服务 + @Autowired + private SingleSeachService singleSeachService; // 单页数据服务 + @Autowired + private UsersService usersService; // 管理员服务 + + //后端分页列表 + //@param params 请求参数Map + //@param request HTTP请求对象 + //@return 分页结果 + @RequestMapping("/page") + public R page(@RequestParam Map params, HttpServletRequest request){ + logger.debug("page方法:,,Controller:{},,params:{}",this.getClass().getName(),JSONObject.toJSONString(params)); + String role = String.valueOf(request.getSession().getAttribute("role")); // 获取用户角色 + if(false) // 条件判断 + return R.error(511,"永不会进入"); // 返回错误信息 + else if("用户".equals(role)) // 如果是用户角色 + params.put("yonghuId",request.getSession().getAttribute("userId")); // 添加用户ID参数 + else if("教练".equals(role)) // 如果是教练角色 + params.put("jiaolianId",request.getSession().getAttribute("userId")); // 添加教练ID参数 + params.put("dataDeleteStart",1);params.put("dataDeleteEnd",1); // 设置逻辑删除条件 + CommonUtil.checkMap(params); // 检查参数 + PageUtils page = yonghuService.queryPage(params); // 分页查询 + + // 字典表数据转换 + List list =(List)page.getList(); // 获取分页数据 + for(YonghuView c:list){ // 遍历数据 + dictionaryService.dictionaryConvert(c, request); // 转换字典表字段 + } + return R.ok().put("data", page); // 返回分页结果 + } + + + //后端详情 + //@param id 用户ID + //@param request HTTP请求对象 + //@return 用户详情 + @RequestMapping("/info/{id}") + public R info(@PathVariable("id") Long id, HttpServletRequest request){ + logger.debug("info方法:,,Controller:{},,id:{}",this.getClass().getName(),id); + YonghuEntity yonghu = yonghuService.selectById(id); // 根据ID查询用户 + if(yonghu !=null){ // 如果查询到数据 + YonghuView view = new YonghuView(); // 创建视图对象 + BeanUtils.copyProperties(yonghu, view); // 复制属性到视图对象 + dictionaryService.dictionaryConvert(view, request); // 转换字典表字段 + return R.ok().put("data", view); // 返回成功结果 + }else { + return R.error(511,"查不到数据"); // 返回错误信息 + } + } + + //后端保存用户 + //@param yonghu 用户实体 + //@param request HTTP请求对象 + //@return 操作结果 + @RequestMapping("/save") + public R save(@RequestBody YonghuEntity yonghu, HttpServletRequest request){ + logger.debug("save方法:,,Controller:{},,yonghu:{}",this.getClass().getName(),yonghu.toString()); + String role = String.valueOf(request.getSession().getAttribute("role")); // 获取用户角色 + if(false) // 条件判断 + return R.error(511,"永远不会进入"); // 返回错误信息 + + // 构建查询条件:检查用户名、手机号、身份证号是否已存在 + Wrapper queryWrapper = new EntityWrapper() + .eq("username", yonghu.getUsername()) // 用户名条件 + .or() // 或条件 + .eq("yonghu_phone", yonghu.getYonghuPhone()) // 手机号条件 + .or() // 或条件 + .eq("yonghu_id_number", yonghu.getYonghuIdNumber()) // 身份证号条件 + .eq("data_delete", 1) // 未删除条件 + ; + + logger.info("sql语句:"+queryWrapper.getSqlSegment()); // 记录SQL语句 + YonghuEntity yonghuEntity = yonghuService.selectOne(queryWrapper); // 查询是否存在 + if(yonghuEntity==null){ // 如果不存在 + yonghu.setDataDelete(1); // 设置未删除状态 + yonghu.setInsertTime(new Date()); // 设置插入时间 + yonghu.setCreateTime(new Date()); // 设置创建时间 + yonghu.setPassword("123456"); // 设置默认密码 + yonghuService.insert(yonghu); // 插入新用户 + return R.ok(); // 返回成功结果 + }else { + return R.error(511,"账户或者用户手机号或者用户身份证号已经被使用"); // 返回错误信息 } } + //后端修改用户 + //@param yonghu 用户实体 + //@param request HTTP请求对象 + //@return 操作结果 + @RequestMapping("/update") + public R update(@RequestBody YonghuEntity yonghu, HttpServletRequest request) throws NoSuchFieldException, ClassNotFoundException, IllegalAccessException, InstantiationException { + logger.debug("update方法:,,Controller:{},,yonghu:{}",this.getClass().getName(),yonghu.toString()); + YonghuEntity oldYonghuEntity = yonghuService.selectById(yonghu.getId()); // 查询原数据 + String role = String.valueOf(request.getSession().getAttribute("role")); // 获取用户角色 + + if("".equals(yonghu.getYonghuPhoto()) || "null".equals(yonghu.getYonghuPhoto())){ // 如果图片为空 + yonghu.setYonghuPhoto(null); // 设置为null + } + + yonghuService.updateById(yonghu); // 更新用户信息 + return R.ok(); // 返回成功结果 + } + + + //删除用户(逻辑删除) + //@param ids 用户ID数组 + //@param request HTTP请求对象 + //@return 操作结果 + @RequestMapping("/delete") + public R delete(@RequestBody Integer[] ids, HttpServletRequest request){ + logger.debug("delete:,,Controller:{},,ids:{}",this.getClass().getName(),ids.toString()); + List oldYonghuList = yonghuService.selectBatchIds(Arrays.asList(ids)); // 查询要删除的数据 + ArrayList list = new ArrayList<>(); // 创建更新列表 + for(Integer id:ids){ // 遍历ID数组 + YonghuEntity yonghuEntity = new YonghuEntity(); // 创建用户实体 + yonghuEntity.setId(id); // 设置ID + yonghuEntity.setDataDelete(2); // 设置删除状态 + list.add(yonghuEntity); // 添加到列表 + } + if(list != null && list.size() >0){ // 如果有数据需要更新 + yonghuService.updateBatchById(list); // 批量更新 + } + return R.ok(); // 返回成功结果 + } + + + //批量导入用户数据 + //@param fileName Excel文件名 + //@param request HTTP请求对象 + //@return 导入结果 + @RequestMapping("/batchInsert") + public R save(String fileName, HttpServletRequest request){ + logger.debug("batchInsert方法:,,Controller:{},,fileName:{}",this.getClass().getName(),fileName); + Integer yonghuId = Integer.valueOf(String.valueOf(request.getSession().getAttribute("userId"))); // 获取当前用户ID + SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); // 创建日期格式化对象 + try { + List yonghuList = new ArrayList<>(); // 创建用户列表 + Map> seachFields = new HashMap<>(); // 创建查重字段Map + Date date = new Date(); // 当前时间 + int lastIndexOf = fileName.lastIndexOf("."); // 获取文件后缀位置 + if(lastIndexOf == -1){ // 如果没有后缀 + return R.error(511,"该文件没有后缀"); // 返回错误信息 + }else{ + String suffix = fileName.substring(lastIndexOf); // 获取文件后缀 + if(!".xls".equals(suffix)){ // 如果不是xls文件 + return R.error(511,"只支持后缀为xls的excel文件"); // 返回错误信息 + }else{ + URL resource = this.getClass().getClassLoader().getResource("static/upload/" + fileName); // 获取文件路径 + File file = new File(resource.getFile()); // 创建文件对象 + if(!file.exists()){ // 如果文件不存在 + return R.error(511,"找不到上传文件,请联系管理员"); // 返回错误信息 + }else{ + List> dataList = PoiUtil.poiImport(file.getPath()); // 读取Excel文件 + dataList.remove(0); // 删除标题行 + for(List data:dataList){ // 遍历数据行 + YonghuEntity yonghuEntity = new YonghuEntity(); // 创建用户实体 + // 可以在此处设置实体属性,示例中被注释掉了 + yonghuList.add(yonghuEntity); // 添加到列表 + + // 构建查重字段Map + // 账户查重 + if(seachFields.containsKey("username")){ + List username = seachFields.get("username"); + username.add(data.get(0)); // 添加用户名 + }else{ + List username = new ArrayList<>(); + username.add(data.get(0)); // 添加用户名 + seachFields.put("username",username); // 放入Map + } + // 手机号查重 + if(seachFields.containsKey("yonghuPhone")){ + List yonghuPhone = seachFields.get("yonghuPhone"); + yonghuPhone.add(data.get(0)); // 添加手机号 + }else{ + List yonghuPhone = new ArrayList<>(); + yonghuPhone.add(data.get(0)); // 添加手机号 + seachFields.put("yonghuPhone",yonghuPhone); // 放入Map + } + // 身份证号查重 + if(seachFields.containsKey("yonghuIdNumber")){ + List yonghuIdNumber = seachFields.get("yonghuIdNumber"); + yonghuIdNumber.add(data.get(0)); // 添加身份证号 + }else{ + List yonghuIdNumber = new ArrayList<>(); + yonghuIdNumber.add(data.get(0)); // 添加身份证号 + seachFields.put("yonghuIdNumber",yonghuIdNumber); // 放入Map + } + } + + // 查重验证 + // 验证用户名是否重复 + List yonghuEntities_username = yonghuService.selectList( + new EntityWrapper().in("username", seachFields.get("username")).eq("data_delete", 1)); + if(yonghuEntities_username.size() >0 ){ // 如果有重复 + ArrayList repeatFields = new ArrayList<>(); // 创建重复字段列表 + for(YonghuEntity s:yonghuEntities_username){ // 遍历重复数据 + repeatFields.add(s.getUsername()); // 添加重复用户名 + } + return R.error(511,"数据库的该表中的 [账户] 字段已经存在 存在数据为:"+repeatFields.toString()); // 返回错误信息 + } + // 验证手机号是否重复 + List yonghuEntities_yonghuPhone = yonghuService.selectList( + new EntityWrapper().in("yonghu_phone", seachFields.get("yonghuPhone")).eq("data_delete", 1)); + if(yonghuEntities_yonghuPhone.size() >0 ){ // 如果有重复 + ArrayList repeatFields = new ArrayList<>(); // 创建重复字段列表 + for(YonghuEntity s:yonghuEntities_yonghuPhone){ // 遍历重复数据 + repeatFields.add(s.getYonghuPhone()); // 添加重复手机号 + } + return R.error(511,"数据库的该表中的 [用户手机号] 字段已经存在 存在数据为:"+repeatFields.toString()); // 返回错误信息 + } + // 验证身份证号是否重复 + List yonghuEntities_yonghuIdNumber = yonghuService.selectList( + new EntityWrapper().in("yonghu_id_number", seachFields.get("yonghuIdNumber")).eq("data_delete", 1)); + if(yonghuEntities_yonghuIdNumber.size() >0 ){ // 如果有重复 + ArrayList repeatFields = new ArrayList<>(); // 创建重复字段列表 + for(YonghuEntity s:yonghuEntities_yonghuIdNumber){ // 遍历重复数据 + repeatFields.add(s.getYonghuIdNumber()); // 添加重复身份证号 + } + return R.error(511,"数据库的该表中的 [用户身份证号] 字段已经存在 存在数据为:"+repeatFields.toString()); // 返回错误信息 + } + yonghuService.insertBatch(yonghuList); // 批量插入数据 + return R.ok(); // 返回成功结果 + } + } + } + }catch (Exception e){ // 捕获异常 + e.printStackTrace(); // 打印异常堆栈 + return R.error(511,"批量插入数据异常,请联系管理员"); // 返回错误信息 + } + } + + + //用户登录 + //@param username 用户名 + //@param password 密码 + //@param captcha 验证码 + //@param request HTTP请求对象 + //@return 登录结果 + @IgnoreAuth // 忽略认证 + @RequestMapping(value = "/login") + public R login(String username, String password, String captcha, HttpServletRequest request) { + YonghuEntity yonghu = yonghuService.selectOne(new EntityWrapper().eq("username", username)); // 根据用户名查询用户 + if(yonghu==null || !yonghu.getPassword().equals(password)) // 验证用户名和密码 + return R.error("账号或密码不正确"); // 返回错误信息 + else if(yonghu.getDataDelete() != 1) // 检查是否被删除 + return R.error("账户已被删除"); // 返回错误信息 + String token = tokenService.generateToken(yonghu.getId(),username, "yonghu", "用户"); // 生成Token + R r = R.ok(); // 创建返回结果 + r.put("token", token); // 添加Token + r.put("role","用户"); // 添加角色 + r.put("username",yonghu.getYonghuName()); // 添加用户名 + r.put("tableName","yonghu"); // 添加表名 + r.put("userId",yonghu.getId()); // 添加用户ID + return r; // 返回结果 + } + + + //用户注册 + //@param yonghu 用户实体 + // @param request HTTP请求对象 + //@return 注册结果 + + @IgnoreAuth // 忽略认证 + @PostMapping(value = "/register") + public R register(@RequestBody YonghuEntity yonghu, HttpServletRequest request) { + // 构建查询条件:检查用户名、手机号、身份证号是否已存在 + Wrapper queryWrapper = new EntityWrapper() + .eq("username", yonghu.getUsername()) // 用户名条件 + .or() // 或条件 + .eq("yonghu_phone", yonghu.getYonghuPhone()) // 手机号条件 + .or() // 或条件 + .eq("yonghu_id_number", yonghu.getYonghuIdNumber()) // 身份证号条件 + .andNew() // 新条件组 + .eq("data_delete", 1) // 未删除条件 + ; + YonghuEntity yonghuEntity = yonghuService.selectOne(queryWrapper); // 查询是否存在 + if(yonghuEntity != null) // 如果已存在 + return R.error("账户或者用户手机号或者用户身份证号已经被使用"); // 返回错误信息 + yonghu.setNewMoney(0.0); // 设置初始余额 + yonghu.setDataDelete(1); // 设置未删除状态 + yonghu.setInsertTime(new Date()); // 设置插入时间 + yonghu.setCreateTime(new Date()); // 设置创建时间 + yonghuService.insert(yonghu); // 插入新用户 + return R.ok(); // 返回成功结果 + } + + + //重置密码为默认值 + //@param id 用户ID + //@param request HTTP请求对象 + // @return 操作结果 + + @GetMapping(value = "/resetPassword") + public R resetPassword(Integer id, HttpServletRequest request) { + YonghuEntity yonghu = yonghuService.selectById(id); // 根据ID查询用户 + yonghu.setPassword("123456"); // 重置密码 + yonghuService.updateById(yonghu); // 更新用户 + return R.ok(); // 返回成功结果 + } + + //修改密码 + //@param oldPassword 旧密码 + //@param newPassword 新密码 + //@param request HTTP请求对象 + // @return 操作结果 + + @GetMapping(value = "/updatePassword") + public R updatePassword(String oldPassword, String newPassword, HttpServletRequest request) { + YonghuEntity yonghu = yonghuService.selectById((Integer)request.getSession().getAttribute("userId")); // 获取当前用户 + if(newPassword == null){ // 检查新密码是否为空 + return R.error("新密码不能为空") ; // 返回错误信息 + } + if(!oldPassword.equals(yonghu.getPassword())){ // 检查旧密码是否正确 + return R.error("原密码输入错误"); // 返回错误信息 + } + if(newPassword.equals(yonghu.getPassword())){ // 检查新旧密码是否相同 + return R.error("新密码不能和原密码一致") ; // 返回错误信息 + } + yonghu.setPassword(newPassword); // 设置新密码 + yonghuService.updateById(yonghu); // 更新用户 + return R.ok(); // 返回成功结果 + } + + //忘记密码(重置为默认密码) + //@param username 用户名 + //@param request HTTP请求对象 + //@return 操作结果 + @IgnoreAuth // 忽略认证 + @RequestMapping(value = "/resetPass") + public R resetPass(String username, HttpServletRequest request) { + YonghuEntity yonghu = yonghuService.selectOne(new EntityWrapper().eq("username", username)); // 根据用户名查询用户 + if(yonghu!=null){ // 如果用户存在 + yonghu.setPassword("123456"); // 重置密码 + yonghuService.updateById(yonghu); // 更新用户 + return R.ok(); // 返回成功结果 + }else{ // 如果用户不存在 + return R.error("账号不存在"); // 返回错误信息 +>>>>>>> develop + } + } + + +<<<<<<< HEAD /** * 获取用户的session用户信息 */ @@ -429,10 +863,27 @@ public class YonghuController { return R.ok().put("data", view); }else { return R.error(511,"查不到数据"); +======= + //获取当前会话用户信息 + //@param request HTTP请求对象 + //@return 用户信息 + @RequestMapping("/session") + public R getCurrYonghu(HttpServletRequest request){ + Integer id = (Integer)request.getSession().getAttribute("userId"); // 获取当前用户ID + YonghuEntity yonghu = yonghuService.selectById(id); // 查询用户信息 + if(yonghu !=null){ // 如果用户存在 + YonghuView view = new YonghuView(); // 创建视图对象 + BeanUtils.copyProperties(yonghu, view); // 复制属性 + dictionaryService.dictionaryConvert(view, request); // 转换字典字段 + return R.ok().put("data", view); // 返回用户信息 + }else { + return R.error(511,"查不到数据"); // 返回错误信息 +>>>>>>> develop } } +<<<<<<< HEAD /** * 退出 */ @@ -519,3 +970,85 @@ public class YonghuController { } +======= + //用户退出 + //@param request HTTP请求对象 + //@return 操作结果 + @GetMapping(value = "logout") + public R logout(HttpServletRequest request) { + request.getSession().invalidate(); // 使会话失效 + return R.ok("退出成功"); // 返回成功信息 + } + + + //前端分页列表 + //@param params 请求参数 + //@param request HTTP请求对象 + //@return 分页结果 + @IgnoreAuth // 忽略认证 + @RequestMapping("/list") + public R list(@RequestParam Map params, HttpServletRequest request){ + logger.debug("list方法:,,Controller:{},,params:{}",this.getClass().getName(),JSONObject.toJSONString(params)); + CommonUtil.checkMap(params); // 检查参数 + PageUtils page = yonghuService.queryPage(params); // 分页查询 + + // 字典表数据转换 + List list =(List)page.getList(); // 获取分页数据 + for(YonghuView c:list) // 遍历数据 + dictionaryService.dictionaryConvert(c, request); // 转换字典字段 + + return R.ok().put("data", page); // 返回分页结果 + } + + + //前端详情 + //@param id 用户ID + //@param request HTTP请求对象 + //@return 用户详情 + @RequestMapping("/detail/{id}") + public R detail(@PathVariable("id") Integer id, HttpServletRequest request){ + logger.debug("detail方法:,,Controller:{},,id:{}",this.getClass().getName(),id); + YonghuEntity yonghu = yonghuService.selectById(id); // 根据ID查询用户 + if(yonghu !=null){ // 如果用户存在 + YonghuView view = new YonghuView(); // 创建视图对象 + BeanUtils.copyProperties(yonghu, view); // 复制属性 + dictionaryService.dictionaryConvert(view, request); // 转换字典字段 + return R.ok().put("data", view); // 返回用户信息 + }else { + return R.error(511,"查不到数据"); // 返回错误信息 + } + } + + + //前端保存用户 + //@param yonghu 用户实体 + //@param request HTTP请求对象 + //@return 操作结果 + @RequestMapping("/add") + public R add(@RequestBody YonghuEntity yonghu, HttpServletRequest request){ + logger.debug("add方法:,,Controller:{},,yonghu:{}",this.getClass().getName(),yonghu.toString()); + // 构建查询条件:检查用户名、手机号、身份证号是否已存在 + Wrapper queryWrapper = new EntityWrapper() + .eq("username", yonghu.getUsername()) // 用户名条件 + .or() // 或条件 + .eq("yonghu_phone", yonghu.getYonghuPhone()) // 手机号条件 + .or() // 或条件 + .eq("yonghu_id_number", yonghu.getYonghuIdNumber()) // 身份证号条件 + .andNew() // 新条件组 + .eq("data_delete", 1) // 未删除条件 + ; + logger.info("sql语句:"+queryWrapper.getSqlSegment()); // 记录SQL语句 + YonghuEntity yonghuEntity = yonghuService.selectOne(queryWrapper); // 查询是否存在 + if(yonghuEntity==null){ // 如果不存在 + yonghu.setDataDelete(1); // 设置未删除状态 + yonghu.setInsertTime(new Date()); // 设置插入时间 + yonghu.setCreateTime(new Date()); // 设置创建时间 + yonghu.setPassword("123456"); // 设置默认密码 + yonghuService.insert(yonghu); // 插入新用户 + return R.ok(); // 返回成功结果 + }else { + return R.error(511,"账户或者用户手机号或者用户身份证号已经被使用"); // 返回错误信息 + } + } +} +>>>>>>> develop diff --git a/src/main/java/com/jianshenfangglApplication.java b/src/main/java/com/jianshenfangglApplication.java index 3f467b3..2edb84c 100644 --- a/src/main/java/com/jianshenfangglApplication.java +++ b/src/main/java/com/jianshenfangglApplication.java @@ -1,6 +1,8 @@ + package com; // 定义包名为com,表示该文件位于com包下 // 导入Spring Boot和MyBatis相关的注解和类 + import org.mybatis.spring.annotation.MapperScan; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; @@ -23,4 +25,6 @@ public class jianshenfangglApplication extends SpringBootServletInitializer { / // 重写configure方法,用于配置Spring Boot应用程序的启动源,支持外部容器(如Tomcat)部署 return applicationBuilder.sources(jianshenfangglApplication.class); } -} \ No newline at end of file +} + + diff --git a/src/main/java/com/utils/R.java b/src/main/java/com/utils/R.java index 0484a83..80fac85 100644 --- a/src/main/java/com/utils/R.java +++ b/src/main/java/com/utils/R.java @@ -1,3 +1,4 @@ +<<<<<<< HEAD package com.utils; // 定义包名为com.utils,表示该类位于com.utils包下 import java.util.HashMap; // 导入HashMap类,用于实现键值对存储 @@ -89,4 +90,57 @@ public class R extends HashMap { super.put(key, value); // 调用父类HashMap的put方法 return this; // 返回当前对象以实现链式调用 } -} \ No newline at end of file +} +======= +package com.utils; + +import java.util.HashMap; +import java.util.Map; + +/** + * 返回数据 + */ +public class R extends HashMap { + private static final long serialVersionUID = 1L; + + public R() { + put("code", 0); + } + + public static R error() { + return error(500, "未知异常,请联系管理员"); + } + + public static R error(String msg) { + return error(500, msg); + } + + public static R error(int code, String msg) { + R r = new R(); + r.put("code", code); + r.put("msg", msg); + return r; + } + + public static R ok(String msg) { + R r = new R(); + r.put("msg", msg); + return r; + } + + public static R ok(Map map) { + R r = new R(); + r.putAll(map); + return r; + } + + public static R ok() { + return new R(); + } + + public R put(String key, Object value) { + super.put(key, value); + return this; + } +} +>>>>>>> develop