UNPKG

tps-ui-components

Version:

TPS UI组件库 - 基于Vue 2和Element UI的企业级组件库

1,310 lines (1,204 loc) 136 kB
'use strict'; Object.defineProperty(exports, '__esModule', { value: true }); var axios = require('axios'); function _interopDefaultLegacy (e) { return e && typeof e === 'object' && 'default' in e ? e : { 'default': e }; } var axios__default = /*#__PURE__*/_interopDefaultLegacy(axios); function _classCallCheck(a, n) { if (!(a instanceof n)) throw new TypeError("Cannot call a class as a function"); } function _defineProperties(e, r) { for (var t = 0; t < r.length; t++) { var o = r[t]; o.enumerable = o.enumerable || !1, o.configurable = !0, "value" in o && (o.writable = !0), Object.defineProperty(e, _toPropertyKey(o.key), o); } } function _createClass(e, r, t) { return r && _defineProperties(e.prototype, r), t && _defineProperties(e, t), Object.defineProperty(e, "prototype", { writable: !1 }), e; } function _defineProperty(e, r, t) { return (r = _toPropertyKey(r)) in e ? Object.defineProperty(e, r, { value: t, enumerable: !0, configurable: !0, writable: !0 }) : e[r] = t, e; } function ownKeys(e, r) { var t = Object.keys(e); if (Object.getOwnPropertySymbols) { var o = Object.getOwnPropertySymbols(e); r && (o = o.filter(function (r) { return Object.getOwnPropertyDescriptor(e, r).enumerable; })), t.push.apply(t, o); } return t; } function _objectSpread2(e) { for (var r = 1; r < arguments.length; r++) { var t = null != arguments[r] ? arguments[r] : {}; r % 2 ? ownKeys(Object(t), !0).forEach(function (r) { _defineProperty(e, r, t[r]); }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(e, Object.getOwnPropertyDescriptors(t)) : ownKeys(Object(t)).forEach(function (r) { Object.defineProperty(e, r, Object.getOwnPropertyDescriptor(t, r)); }); } return e; } function _toPrimitive(t, r) { if ("object" != typeof t || !t) return t; var e = t[Symbol.toPrimitive]; if (void 0 !== e) { var i = e.call(t, r || "default"); if ("object" != typeof i) return i; throw new TypeError("@@toPrimitive must return a primitive value."); } return ("string" === r ? String : Number)(t); } function _toPropertyKey(t) { var i = _toPrimitive(t, "string"); return "symbol" == typeof i ? i : i + ""; } /** * TPS主题管理器 * 用于实现一键换肤功能,支持多种主题切换 * @version 1.0.0 * @author TPS Team */ var ThemeManager = /*#__PURE__*/function () { function ThemeManager() { _classCallCheck(this, ThemeManager); // 预定义主题配置 this.themes = { "default": { name: '默认主题', primaryColor: '#4d9bd5', backgroundColor: '#F5F5F5', textColor: '#303133', borderColor: '#DCDFE6', successColor: '#67C23A', warningColor: '#E6A23C', dangerColor: '#F56C6C', infoColor: '#909399' }, dark: { name: '暗黑主题', primaryColor: '#4d9bd5', backgroundColor: '#303133', textColor: '#E5EAF3', borderColor: '#434343', successColor: '#67C23A', warningColor: '#E6A23C', dangerColor: '#F56C6C', infoColor: '#909399' }, blue: { name: '蓝色主题', primaryColor: '#1890ff', backgroundColor: '#f0f9ff', textColor: '#0d1a26', borderColor: '#91d5ff', successColor: '#52c41a', warningColor: '#faad14', dangerColor: '#ff4d4f', infoColor: '#1890ff' }, red: { name: '红色主题', primaryColor: '#FF4D4F', backgroundColor: '#F5F5F5', textColor: '#303133', borderColor: '#DCDFE6', successColor: '#67C23A', warningColor: '#E6A23C', dangerColor: '#FF4D4F', infoColor: '#909399' }, green: { name: '绿色主题', primaryColor: '#52c41a', backgroundColor: '#f6ffed', textColor: '#000000', borderColor: '#b7eb8f', successColor: '#52c41a', warningColor: '#faad14', dangerColor: '#ff4d4f', infoColor: '#1890ff' } }; // 当前主题 this.currentTheme = 'default'; // 创建样式标签 this.styleElement = document.createElement('style'); this.styleElement.id = 'tps-theme-variables'; document.head.appendChild(this.styleElement); // 初始化主题 this.init(); } /** * 初始化主题管理器 */ return _createClass(ThemeManager, [{ key: "init", value: function init() { // 从localStorage读取保存的主题 var savedTheme = localStorage.getItem('tps-theme'); if (savedTheme && this.themes[savedTheme]) { this.changeTheme(savedTheme); } else { this.changeTheme('default'); } // 监听系统主题变化 if (window.matchMedia) { var mediaQuery = window.matchMedia('(prefers-color-scheme: dark)'); mediaQuery.addListener(this.handleSystemThemeChange.bind(this)); } } /** * 切换主题 * @param {string} themeName - 主题名称 * @param {boolean} saveToStorage - 是否保存到localStorage */ }, { key: "changeTheme", value: function changeTheme(themeName) { var saveToStorage = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : true; if (!this.themes[themeName]) { console.error("\u4E3B\u9898 ".concat(themeName, " \u4E0D\u5B58\u5728")); return false; } var theme = this.themes[themeName]; this.currentTheme = themeName; // 更新CSS变量 this.updateCSSVariables(theme); // 更新Element UI主题 this.updateElementTheme(theme); // 触发主题变化事件 this.emitThemeChange(themeName, theme); // 保存到localStorage if (saveToStorage) { localStorage.setItem('tps-theme', themeName); } return true; } /** * 更新CSS变量 * @param {Object} theme - 主题配置 */ }, { key: "updateCSSVariables", value: function updateCSSVariables(theme) { var cssVariables = Object.keys(theme).filter(function (key) { return key !== 'name'; }).map(function (key) { var cssVarName = "--tps-".concat(key.replace(/([A-Z])/g, '-$1').toLowerCase()); return "".concat(cssVarName, ": ").concat(theme[key], ";"); }).join('\n'); var cssContent = ":root {\n".concat(cssVariables, "\n}"); this.styleElement.textContent = cssContent; } /** * 更新Element UI主题 * @param {Object} theme - 主题配置 */ }, { key: "updateElementTheme", value: function updateElementTheme(theme) { // 更新Element UI的CSS变量 var elementVariables = { '--el-color-primary': theme.primaryColor, '--el-color-success': theme.successColor, '--el-color-warning': theme.warningColor, '--el-color-danger': theme.dangerColor, '--el-color-info': theme.infoColor, '--el-border-color-base': theme.borderColor, '--el-text-color-primary': theme.textColor, '--el-background-color-base': theme.backgroundColor }; Object.keys(elementVariables).forEach(function (key) { document.documentElement.style.setProperty(key, elementVariables[key]); }); } /** * 处理系统主题变化 * @param {MediaQueryListEvent} e - 媒体查询事件 */ }, { key: "handleSystemThemeChange", value: function handleSystemThemeChange(e) { if (e.matches) { // 系统切换到暗色模式 this.changeTheme('dark', false); } else { // 系统切换到亮色模式 this.changeTheme('default', false); } } /** * 触发主题变化事件 * @param {string} themeName - 主题名称 * @param {Object} theme - 主题配置 */ }, { key: "emitThemeChange", value: function emitThemeChange(themeName, theme) { var event = new CustomEvent('themeChange', { detail: { themeName: themeName, theme: theme } }); window.dispatchEvent(event); } /** * 获取当前主题 * @returns {string} 当前主题名称 */ }, { key: "getCurrentTheme", value: function getCurrentTheme() { return this.currentTheme; } /** * 获取所有可用主题 * @returns {Object} 主题列表 */ }, { key: "getAvailableThemes", value: function getAvailableThemes() { var _this = this; return Object.keys(this.themes).map(function (key) { return { key: key, name: _this.themes[key].name, colors: _this.themes[key] }; }); } /** * 添加自定义主题 * @param {string} themeName - 主题名称 * @param {Object} themeConfig - 主题配置 */ }, { key: "addTheme", value: function addTheme(themeName, themeConfig) { this.themes[themeName] = themeConfig; } /** * 移除主题 * @param {string} themeName - 主题名称 */ }, { key: "removeTheme", value: function removeTheme(themeName) { if (themeName === 'default') { console.warn('不能删除默认主题'); return false; } delete this.themes[themeName]; return true; } }]); }(); // 创建单例实例 var themeManager = new ThemeManager(); // Vue插件导出 var ThemeManager$1 = { install: function install(Vue) { Vue.prototype.$themeManager = themeManager; // 添加全局方法 Vue.prototype.$changeTheme = function (themeName) { return themeManager.changeTheme(themeName); }; Vue.prototype.$getCurrentTheme = function () { return themeManager.getCurrentTheme(); }; Vue.prototype.$getAvailableThemes = function () { return themeManager.getAvailableThemes(); }; }, // 直接调用方法 changeTheme: function changeTheme(themeName) { return themeManager.changeTheme(themeName); }, getCurrentTheme: function getCurrentTheme() { return themeManager.getCurrentTheme(); }, getAvailableThemes: function getAvailableThemes() { return themeManager.getAvailableThemes(); }, addTheme: function addTheme(themeName, themeConfig) { return themeManager.addTheme(themeName, themeConfig); }, removeTheme: function removeTheme(themeName) { return themeManager.removeTheme(themeName); } }; // 默认配置 var DEFAULT_CONFIG = { baseURL: process.env.VUE_APP_BASE_API || '/api', timeout: 10000, headers: { 'Content-Type': 'application/json;charset=UTF-8' } }; /** * 创建axios实例 * @param {Object} config - 自定义配置 * @returns {Object} axios实例 */ function createRequest() { var config = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {}; var instance = axios__default["default"].create(_objectSpread2(_objectSpread2({}, DEFAULT_CONFIG), config)); // 请求拦截器 instance.interceptors.request.use(function (config) { // 添加认证token var token = getToken(); if (token) { config.headers.Authorization = "Bearer ".concat(token); } // 添加请求时间戳(防止缓存) if (config.method === 'get') { config.params = _objectSpread2(_objectSpread2({}, config.params), {}, { _t: Date.now() }); } // 请求日志 if (process.env.NODE_ENV === 'development') { console.log('🚀 Request:', { url: config.url, method: config.method, params: config.params, data: config.data }); } return config; }, function (error) { console.error('❌ Request Error:', error); return Promise.reject(error); }); // 响应拦截器 instance.interceptors.response.use(function (response) { var data = response.data, config = response.config; // 响应日志 if (process.env.NODE_ENV === 'development') { console.log('✅ Response:', { url: config.url, data: data }); } // 检查业务状态码 if (data.code !== undefined && data.code !== 200) { var errorMessage = data.message || data.msg || '请求失败'; // 显示错误信息 showErrorMessage(errorMessage); // 特殊状态码处理 handleSpecialStatusCode(data.code, errorMessage); return Promise.reject(new Error(errorMessage)); } // 返回数据 return data.data !== undefined ? data.data : data; }, function (error) { console.error('❌ Response Error:', error); var errorMessage = '网络请求失败'; if (error.response) { var _error$response = error.response, status = _error$response.status, data = _error$response.data; // HTTP状态码错误处理 switch (status) { case 400: errorMessage = data.message || '请求参数错误'; break; case 401: errorMessage = '未授权,请重新登录'; handleUnauthorized(); break; case 403: errorMessage = '拒绝访问'; break; case 404: errorMessage = '请求的资源不存在'; break; case 408: errorMessage = '请求超时'; break; case 500: errorMessage = '服务器内部错误'; break; case 502: errorMessage = '网关错误'; break; case 503: errorMessage = '服务不可用'; break; case 504: errorMessage = '网关超时'; break; default: errorMessage = data.message || "\u8FDE\u63A5\u9519\u8BEF".concat(status); } } else if (error.request) { errorMessage = '网络连接失败,请检查网络设置'; } else { errorMessage = error.message || '请求配置错误'; } // 显示错误信息 showErrorMessage(errorMessage); return Promise.reject(error); }); return instance; } /** * 获取认证token * @returns {string|null} token */ function getToken() { return localStorage.getItem('token') || sessionStorage.getItem('token'); } /** * 显示错误信息 * @param {string} message - 错误信息 */ function showErrorMessage(message) { // 尝试使用Element UI的Message组件 if (typeof window !== 'undefined' && window.Vue && window.Vue.prototype.$message) { window.Vue.prototype.$message({ message: message, type: 'error', duration: 3000, showClose: true }); } else { // 降级到console.error console.error('API Error:', message); } } /** * 处理特殊状态码 * @param {number} code - 状态码 * @param {string} message - 错误信息 */ function handleSpecialStatusCode(code, message) { switch (code) { case 401: case 403: handleUnauthorized(); break; case 1001: // 自定义业务状态码处理 console.warn('业务警告:', message); break; } } /** * 处理未授权情况 */ function handleUnauthorized() { // 清除token localStorage.removeItem('token'); sessionStorage.removeItem('token'); // 跳转到登录页 if (typeof window !== 'undefined' && window.Vue && window.Vue.prototype.$router) { window.Vue.prototype.$router.push('/login'); } } // 创建默认实例 var request = createRequest(); /** * GET请求 * @param {string} url - 请求地址 * @param {Object} params - 请求参数 * @param {Object} config - 请求配置 * @returns {Promise} 请求Promise */ var get = function get(url) { var params = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {}; var config = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : {}; return request(_objectSpread2({ method: 'get', url: url, params: params }, config)); }; /** * POST请求 * @param {string} url - 请求地址 * @param {Object} data - 请求数据 * @param {Object} config - 请求配置 * @returns {Promise} 请求Promise */ var post = function post(url) { var data = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {}; var config = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : {}; return request(_objectSpread2({ method: 'post', url: url, data: data }, config)); }; /** * PUT请求 * @param {string} url - 请求地址 * @param {Object} data - 请求数据 * @param {Object} config - 请求配置 * @returns {Promise} 请求Promise */ var put = function put(url) { var data = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {}; var config = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : {}; return request(_objectSpread2({ method: 'put', url: url, data: data }, config)); }; /** * DELETE请求 * @param {string} url - 请求地址 * @param {Object} params - 请求参数 * @param {Object} config - 请求配置 * @returns {Promise} 请求Promise */ var del = function del(url) { var params = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {}; var config = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : {}; return request(_objectSpread2({ method: 'delete', url: url, params: params }, config)); }; /** * 文件上传 * @param {string} url - 上传地址 * @param {FormData} formData - 文件数据 * @param {Object} config - 请求配置 * @returns {Promise} 请求Promise */ var upload = function upload(url, formData) { var config = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : {}; return request(_objectSpread2({ method: 'post', url: url, data: formData, headers: { 'Content-Type': 'multipart/form-data' } }, config)); }; // // // // // // // // // // // // // // // // // // // // // /** * TpsButton 按钮组件 * 基于Element UI Button组件封装,提供统一的样式和交互 * @displayName TpsButton */ var script$5 = { name: 'TpsButton', props: { /** * 按钮类型 * @values primary, success, warning, danger, info, text */ type: { type: String, default: 'default', validator: value => { return ['default', 'primary', 'success', 'warning', 'danger', 'info', 'text'].includes(value) } }, /** * 按钮尺寸 * @values medium, small, mini */ size: { type: String, default: 'medium', validator: value => { return ['medium', 'small', 'mini'].includes(value) } }, /** * 是否朴素按钮 */ plain: { type: Boolean, default: false }, /** * 是否圆角按钮 */ round: { type: Boolean, default: false }, /** * 是否圆形按钮 */ circle: { type: Boolean, default: false }, /** * 是否加载中状态 */ loading: { type: Boolean, default: false }, /** * 是否禁用状态 */ disabled: { type: Boolean, default: false }, /** * 图标类名 */ icon: { type: String, default: '' }, /** * 是否默认聚焦 */ autofocus: { type: Boolean, default: false }, /** * 原生type属性 * @values button, submit, reset */ nativeType: { type: String, default: 'button', validator: value => { return ['button', 'submit', 'reset'].includes(value) } }, /** * 自定义主题色 */ color: { type: String, default: '' }, /** * 按钮变体 * @values default, gradient, shadow */ variant: { type: String, default: 'default', validator: value => { return ['default', 'gradient', 'shadow'].includes(value) } } }, computed: { /** * 计算按钮类型 */ computedType() { return this.type === 'default' ? '' : this.type }, /** * 按钮样式类 */ buttonClass() { return [ 'tps-button', { [`tps-button--${this.variant}`]: this.variant !== 'default', 'tps-button--custom-color': this.color } ] } }, methods: { /** * 点击事件处理 * @param {Event} event - 点击事件 */ handleClick(event) { if (this.loading || this.disabled) { return } /** * 按钮点击事件 * @event click * @param {Event} event - 原生点击事件 */ this.$emit('click', event); }, /** * 聚焦事件处理 * @param {Event} event - 聚焦事件 */ handleFocus(event) { /** * 按钮聚焦事件 * @event focus * @param {Event} event - 原生聚焦事件 */ this.$emit('focus', event); }, /** * 失焦事件处理 * @param {Event} event - 失焦事件 */ handleBlur(event) { /** * 按钮失焦事件 * @event blur * @param {Event} event - 原生失焦事件 */ this.$emit('blur', event); } }, mounted() { // 应用自定义颜色 if (this.color) { this.$el.style.setProperty('--tps-button-color', this.color); } } }; function normalizeComponent(template, style, script, scopeId, isFunctionalTemplate, moduleIdentifier /* server only */, shadowMode, createInjector, createInjectorSSR, createInjectorShadow) { if (typeof shadowMode !== 'boolean') { createInjectorSSR = createInjector; createInjector = shadowMode; shadowMode = false; } // Vue.extend constructor export interop. const options = typeof script === 'function' ? script.options : script; // render functions if (template && template.render) { options.render = template.render; options.staticRenderFns = template.staticRenderFns; options._compiled = true; // functional template if (isFunctionalTemplate) { options.functional = true; } } // scopedId if (scopeId) { options._scopeId = scopeId; } let hook; if (moduleIdentifier) { // server build hook = function (context) { // 2.3 injection context = context || // cached call (this.$vnode && this.$vnode.ssrContext) || // stateful (this.parent && this.parent.$vnode && this.parent.$vnode.ssrContext); // functional // 2.2 with runInNewContext: true if (!context && typeof __VUE_SSR_CONTEXT__ !== 'undefined') { context = __VUE_SSR_CONTEXT__; } // inject component styles if (style) { style.call(this, createInjectorSSR(context)); } // register component module identifier for async chunk inference if (context && context._registeredComponents) { context._registeredComponents.add(moduleIdentifier); } }; // used by ssr in case component is cached and beforeCreate // never gets called options._ssrRegister = hook; } else if (style) { hook = shadowMode ? function (context) { style.call(this, createInjectorShadow(context, this.$root.$options.shadowRoot)); } : function (context) { style.call(this, createInjector(context)); }; } if (hook) { if (options.functional) { // register for functional component in vue file const originalRender = options.render; options.render = function renderWithStyleInjection(h, context) { hook.call(context); return originalRender(h, context); }; } else { // inject component registration as beforeCreate hook const existing = options.beforeCreate; options.beforeCreate = existing ? [].concat(existing, hook) : [hook]; } } return script; } const isOldIE = typeof navigator !== 'undefined' && /msie [6-9]\\b/.test(navigator.userAgent.toLowerCase()); function createInjector(context) { return (id, style) => addStyle(id, style); } let HEAD; const styles = {}; function addStyle(id, css) { const group = isOldIE ? css.media || 'default' : id; const style = styles[group] || (styles[group] = { ids: new Set(), styles: [] }); if (!style.ids.has(id)) { style.ids.add(id); let code = css.source; if (css.map) { // https://developer.chrome.com/devtools/docs/javascript-debugging // this makes source maps inside style tags work properly in Chrome code += '\n/*# sourceURL=' + css.map.sources[0] + ' */'; // http://stackoverflow.com/a/26603875 code += '\n/*# sourceMappingURL=data:application/json;base64,' + btoa(unescape(encodeURIComponent(JSON.stringify(css.map)))) + ' */'; } if (!style.element) { style.element = document.createElement('style'); style.element.type = 'text/css'; if (css.media) style.element.setAttribute('media', css.media); if (HEAD === undefined) { HEAD = document.head || document.getElementsByTagName('head')[0]; } HEAD.appendChild(style.element); } if ('styleSheet' in style.element) { style.styles.push(code); style.element.styleSheet.cssText = style.styles .filter(Boolean) .join('\n'); } else { const index = style.ids.size - 1; const textNode = document.createTextNode(code); const nodes = style.element.childNodes; if (nodes[index]) style.element.removeChild(nodes[index]); if (nodes.length) style.element.insertBefore(textNode, nodes[index]); else style.element.appendChild(textNode); } } } /* script */ const __vue_script__$5 = script$5; /* template */ var __vue_render__$5 = function () { var _vm = this; var _h = _vm.$createElement; var _c = _vm._self._c || _h; return _c( "el-button", { class: _vm.buttonClass, attrs: { type: _vm.computedType, size: _vm.size, plain: _vm.plain, round: _vm.round, circle: _vm.circle, loading: _vm.loading, disabled: _vm.disabled, icon: _vm.icon, autofocus: _vm.autofocus, "native-type": _vm.nativeType, }, on: { click: _vm.handleClick, focus: _vm.handleFocus, blur: _vm.handleBlur, }, }, [_vm._t("default")], 2 ) }; var __vue_staticRenderFns__$5 = []; __vue_render__$5._withStripped = true; /* style */ const __vue_inject_styles__$5 = function (inject) { if (!inject) return inject("data-v-09be781e_0", { source: "\n.tps-button[data-v-09be781e] {\n /* 基础样式 */\n transition: all 0.3s ease;\n border-radius: var(--tps-border-radius, 4px);\n font-weight: 500;\n letter-spacing: 0.5px;\n}\n\n/* 渐变变体 */\n.tps-button--gradient.el-button--primary[data-v-09be781e] {\n background: linear-gradient(135deg, var(--tps-primary-color, #4d9bd5) 0%, #357abd 100%);\n border: none;\n box-shadow: 0 4px 12px rgba(77, 155, 213, 0.3);\n}\n.tps-button--gradient.el-button--primary[data-v-09be781e]:hover {\n background: linear-gradient(135deg, #357abd 0%, #2968a3 100%);\n box-shadow: 0 6px 16px rgba(77, 155, 213, 0.4);\n transform: translateY(-2px);\n}\n\n/* 阴影变体 */\n.tps-button--shadow[data-v-09be781e] {\n box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1);\n}\n.tps-button--shadow[data-v-09be781e]:hover {\n box-shadow: 0 4px 16px rgba(0, 0, 0, 0.15);\n transform: translateY(-1px);\n}\n\n/* 自定义颜色 */\n.tps-button--custom-color.el-button--primary[data-v-09be781e] {\n background-color: var(--tps-button-color);\n border-color: var(--tps-button-color);\n}\n.tps-button--custom-color.el-button--primary[data-v-09be781e]:hover {\n background-color: var(--tps-button-color);\n border-color: var(--tps-button-color);\n opacity: 0.8;\n}\n\n/* 响应式设计 */\n@media (max-width: 768px) {\n.tps-button[data-v-09be781e] {\n padding: 8px 16px;\n font-size: 14px;\n}\n}\n\n/* 主题适配 */\n.tps-button[data-v-09be781e] {\n color: var(--tps-text-color, #303133);\n border-color: var(--tps-border-color, #DCDFE6);\n}\n\n/* 加载状态优化 */\n.tps-button.is-loading[data-v-09be781e] {\n pointer-events: none;\n}\n\n/* 禁用状态优化 */\n.tps-button.is-disabled[data-v-09be781e] {\n opacity: 0.6;\n cursor: not-allowed;\n}\n\n/* 聚焦状态 */\n.tps-button[data-v-09be781e]:focus {\n outline: 2px solid var(--tps-primary-color, #4d9bd5);\n outline-offset: 2px;\n}\n", map: {"version":3,"sources":["E:\\新建文件夹\\tps-ui-components\\src\\components\\TpsButton\\index.vue"],"names":[],"mappings":";AA6NA;EACA,SAAA;EACA,yBAAA;EACA,4CAAA;EACA,gBAAA;EACA,qBAAA;AACA;;AAEA,SAAA;AACA;EACA,uFAAA;EACA,YAAA;EACA,8CAAA;AACA;AAEA;EACA,6DAAA;EACA,8CAAA;EACA,2BAAA;AACA;;AAEA,SAAA;AACA;EACA,wCAAA;AACA;AAEA;EACA,0CAAA;EACA,2BAAA;AACA;;AAEA,UAAA;AACA;EACA,yCAAA;EACA,qCAAA;AACA;AAEA;EACA,yCAAA;EACA,qCAAA;EACA,YAAA;AACA;;AAEA,UAAA;AACA;AACA;IACA,iBAAA;IACA,eAAA;AACA;AACA;;AAEA,SAAA;AACA;EACA,qCAAA;EACA,8CAAA;AACA;;AAEA,WAAA;AACA;EACA,oBAAA;AACA;;AAEA,WAAA;AACA;EACA,YAAA;EACA,mBAAA;AACA;;AAEA,SAAA;AACA;EACA,oDAAA;EACA,mBAAA;AACA","file":"index.vue","sourcesContent":["<template>\n <el-button\n :class=\"buttonClass\"\n :type=\"computedType\"\n :size=\"size\"\n :plain=\"plain\"\n :round=\"round\"\n :circle=\"circle\"\n :loading=\"loading\"\n :disabled=\"disabled\"\n :icon=\"icon\"\n :autofocus=\"autofocus\"\n :native-type=\"nativeType\"\n @click=\"handleClick\"\n @focus=\"handleFocus\"\n @blur=\"handleBlur\"\n >\n <slot></slot>\n </el-button>\n</template>\n\n<script>\n/**\n * TpsButton 按钮组件\n * 基于Element UI Button组件封装,提供统一的样式和交互\n * @displayName TpsButton\n */\nexport default {\n name: 'TpsButton',\n \n props: {\n /**\n * 按钮类型\n * @values primary, success, warning, danger, info, text\n */\n type: {\n type: String,\n default: 'default',\n validator: value => {\n return ['default', 'primary', 'success', 'warning', 'danger', 'info', 'text'].includes(value)\n }\n },\n \n /**\n * 按钮尺寸\n * @values medium, small, mini\n */\n size: {\n type: String,\n default: 'medium',\n validator: value => {\n return ['medium', 'small', 'mini'].includes(value)\n }\n },\n \n /**\n * 是否朴素按钮\n */\n plain: {\n type: Boolean,\n default: false\n },\n \n /**\n * 是否圆角按钮\n */\n round: {\n type: Boolean,\n default: false\n },\n \n /**\n * 是否圆形按钮\n */\n circle: {\n type: Boolean,\n default: false\n },\n \n /**\n * 是否加载中状态\n */\n loading: {\n type: Boolean,\n default: false\n },\n \n /**\n * 是否禁用状态\n */\n disabled: {\n type: Boolean,\n default: false\n },\n \n /**\n * 图标类名\n */\n icon: {\n type: String,\n default: ''\n },\n \n /**\n * 是否默认聚焦\n */\n autofocus: {\n type: Boolean,\n default: false\n },\n \n /**\n * 原生type属性\n * @values button, submit, reset\n */\n nativeType: {\n type: String,\n default: 'button',\n validator: value => {\n return ['button', 'submit', 'reset'].includes(value)\n }\n },\n \n /**\n * 自定义主题色\n */\n color: {\n type: String,\n default: ''\n },\n \n /**\n * 按钮变体\n * @values default, gradient, shadow\n */\n variant: {\n type: String,\n default: 'default',\n validator: value => {\n return ['default', 'gradient', 'shadow'].includes(value)\n }\n }\n },\n \n computed: {\n /**\n * 计算按钮类型\n */\n computedType() {\n return this.type === 'default' ? '' : this.type\n },\n \n /**\n * 按钮样式类\n */\n buttonClass() {\n return [\n 'tps-button',\n {\n [`tps-button--${this.variant}`]: this.variant !== 'default',\n 'tps-button--custom-color': this.color\n }\n ]\n }\n },\n \n methods: {\n /**\n * 点击事件处理\n * @param {Event} event - 点击事件\n */\n handleClick(event) {\n if (this.loading || this.disabled) {\n return\n }\n \n /**\n * 按钮点击事件\n * @event click\n * @param {Event} event - 原生点击事件\n */\n this.$emit('click', event)\n },\n \n /**\n * 聚焦事件处理\n * @param {Event} event - 聚焦事件\n */\n handleFocus(event) {\n /**\n * 按钮聚焦事件\n * @event focus\n * @param {Event} event - 原生聚焦事件\n */\n this.$emit('focus', event)\n },\n \n /**\n * 失焦事件处理\n * @param {Event} event - 失焦事件\n */\n handleBlur(event) {\n /**\n * 按钮失焦事件\n * @event blur\n * @param {Event} event - 原生失焦事件\n */\n this.$emit('blur', event)\n }\n },\n \n mounted() {\n // 应用自定义颜色\n if (this.color) {\n this.$el.style.setProperty('--tps-button-color', this.color)\n }\n }\n}\n</script>\n\n<style scoped>\n.tps-button {\n /* 基础样式 */\n transition: all 0.3s ease;\n border-radius: var(--tps-border-radius, 4px);\n font-weight: 500;\n letter-spacing: 0.5px;\n}\n\n/* 渐变变体 */\n.tps-button--gradient.el-button--primary {\n background: linear-gradient(135deg, var(--tps-primary-color, #4d9bd5) 0%, #357abd 100%);\n border: none;\n box-shadow: 0 4px 12px rgba(77, 155, 213, 0.3);\n}\n\n.tps-button--gradient.el-button--primary:hover {\n background: linear-gradient(135deg, #357abd 0%, #2968a3 100%);\n box-shadow: 0 6px 16px rgba(77, 155, 213, 0.4);\n transform: translateY(-2px);\n}\n\n/* 阴影变体 */\n.tps-button--shadow {\n box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1);\n}\n\n.tps-button--shadow:hover {\n box-shadow: 0 4px 16px rgba(0, 0, 0, 0.15);\n transform: translateY(-1px);\n}\n\n/* 自定义颜色 */\n.tps-button--custom-color.el-button--primary {\n background-color: var(--tps-button-color);\n border-color: var(--tps-button-color);\n}\n\n.tps-button--custom-color.el-button--primary:hover {\n background-color: var(--tps-button-color);\n border-color: var(--tps-button-color);\n opacity: 0.8;\n}\n\n/* 响应式设计 */\n@media (max-width: 768px) {\n .tps-button {\n padding: 8px 16px;\n font-size: 14px;\n }\n}\n\n/* 主题适配 */\n.tps-button {\n color: var(--tps-text-color, #303133);\n border-color: var(--tps-border-color, #DCDFE6);\n}\n\n/* 加载状态优化 */\n.tps-button.is-loading {\n pointer-events: none;\n}\n\n/* 禁用状态优化 */\n.tps-button.is-disabled {\n opacity: 0.6;\n cursor: not-allowed;\n}\n\n/* 聚焦状态 */\n.tps-button:focus {\n outline: 2px solid var(--tps-primary-color, #4d9bd5);\n outline-offset: 2px;\n}\n</style>"]}, media: undefined }); }; /* scoped */ const __vue_scope_id__$5 = "data-v-09be781e"; /* module identifier */ const __vue_module_identifier__$5 = undefined; /* functional template */ const __vue_is_functional_template__$5 = false; /* style inject SSR */ /* style inject shadow dom */ const __vue_component__$5 = /*#__PURE__*/normalizeComponent( { render: __vue_render__$5, staticRenderFns: __vue_staticRenderFns__$5 }, __vue_inject_styles__$5, __vue_script__$5, __vue_scope_id__$5, __vue_is_functional_template__$5, __vue_module_identifier__$5, false, createInjector, undefined, undefined ); // 为组件提供install方法,供按需引入 __vue_component__$5.install = function (Vue) { Vue.component(__vue_component__$5.name, __vue_component__$5); }; // // // // // // // // // // // // // // // // // // // // // // // // // // // /** * TpsCard 卡片组件 * 提供统一的卡片容器,支持多种样式和布局 * @displayName TpsCard */ var script$4 = { name: 'TpsCard', props: { /** * 卡片标题 */ title: { type: String, default: '' }, /** * 标题图标 */ icon: { type: String, default: '' }, /** * 卡片阴影 * @values always, hover, never */ shadow: { type: String, default: 'always', validator: value => { return ['always', 'hover', 'never'].includes(value) } }, /** * 卡片内边距 */ padding: { type: [String, Number], default: '20px' }, /** * 卡片圆角 */ radius: { type: [String, Number], default: '8px' }, /** * 是否有边框 */ bordered: { type: Boolean, default: true }, /** * 卡片类型 * @values default, primary, success, warning, danger, info */ type: { type: String, default: 'default', validator: value => { return ['default', 'primary', 'success', 'warning', 'danger', 'info'].includes(value) } }, /** * 是否可悬浮 */ hoverable: { type: Boolean, default: false }, /** * 是否加载中 */ loading: { type: Boolean, default: false }, /** * 自定义背景色 */ backgroundColor: { type: String, default: '' }, /** * 卡片尺寸 * @values small, medium, large */ size: { type: String, default: 'medium', validator: value => { return ['small', 'medium', 'large'].includes(value) } } }, computed: { /** * 卡片样式类 */ cardClass() { return [ 'tps-card', `tps-card--${this.shadow}`, `tps-card--${this.size}`, { [`tps-card--${this.type}`]: this.type !== 'default', 'tps-card--bordered': this.bordered, 'tps-card--hoverable': this.hoverable, 'tps-card--loading': this.loading } ] }, /** * 卡片样式 */ cardStyle() { const style = {}; if (this.radius) { style.borderRadius = typeof this.radius === 'number' ? `${this.radius}px` : this.radius; } if (this.backgroundColor) { style.backgroundColor = this.backgroundColor; } return style }, /** * 卡片内容样式 */ bodyStyle() { const style = {}; if (this.padding) { style.padding = typeof this.padding === 'number' ? `${this.padding}px` : this.padding; } return style } } }; /* script */ const __vue_script__$4 = script$4; /* template */ var __vue_render__$4 = function () { var _vm = this; var _h = _vm.$createElement; var _c = _vm._self._c || _h; return _c("div", { class: _vm.cardClass, style: _vm.cardStyle }, [ _vm.$slots.header || _vm.title ? _c( "div", { staticClass: "tps-card__header" }, [ _vm._t("header", function () { return [ _c("div", { staticClass: "tps-card__title" }, [ _vm.icon ? _c("i", { staticClass: "tps-card__icon", class: _vm.icon, }) : _vm._e(), _vm._v("\n " + _vm._s(_vm.title) + "\n "), ]), _vm._v(" "), _vm.$slots.extra ? _c( "div", { staticClass: "tps-card__extra" }, [_vm._t("extra")], 2 ) : _vm._e(), ] }), ], 2 ) : _vm._e(), _vm._v(" "), _c( "div", { staticClass: "tps-card__body", style: _vm.bodyStyle }, [_vm._t("default")], 2 ), _vm._v(" "), _vm.$slots.footer ? _c("div", { staticClass: "tps-card__footer" }, [_vm._t("footer")], 2) : _vm._e(), ]) }; var __vue_staticRenderFns__$4 = []; __vue_render__$4._withStripped = true; /* style */ const __vue_inject_styles__$4 = function (inject) { if (!inject) return inject("data-v-0f58e5b7_0", { source: "\n.tps-card[data-v-0f58e5b7] {\n background-color: var(--tps-background-color, #ffffff);\n border: 1px solid var(--tps-border-color, #EBEEF5);\n border-radius: 8px;\n overflow: hidden;\n transition: all 0.3s ease;\n position: relative;\n}\n\n/* 阴影样式 */\n.tps-card--always[data-v-0f58e5b7] {\n box-shadow: 0 2px 12px 0 rgba(0, 0, 0, 0.1);\n}\n.tps-card--hover[data-v-0f58e5b7] {\n box-shadow: none;\n}\n.tps-card--hover[data-v-0f58e5b7]:hover {\n box-shadow: 0 2px 12px 0 rgba(0, 0, 0, 0.1);\n}\n.tps-card--never[data-v-0f58e5b7] {\n box-shadow: none;\n}\n\n/* 边框样式 */\n.tps-card--bordered[data-v-0f58e5b7] {\n border: 1px solid var(--tps-border-color, #EBEEF5);\n}\n.tps-card[data-v-0f58e5b7]:not(.tps-card--bordered) {\n border: none;\n}\n\n/* 悬浮效果 */\n.tps-card--hoverable[data-v-0f58e5b7]:hover {\n transform: translateY(-2px);\n box-shadow: 0 4px 20px 0 rgba(0, 0, 0, 0.15);\n}\n\n/* 尺寸样式 */\n.tps-card--small .tps-card__header[data-v-0f58e5b7] {\n padding: 12px 16px;\n}\n.tps-card--small .tps-card__body[data-v-0f58e5b7] {\n padding: 12px 16px;\n}\n.tps-card--small .tps-card__footer[data-v-0f58e5b7] {\n padding: 12px 16px;\n}\n.tps-card--medium .tps-card__header[data-v-0f58e5b7] {\n padding: 16px 20px;\n}\n.tps-card--medium .tps-card__body[data-v-0f58e5b7] {\n padding: 20px;\n}\n.tps-card--medium .tps-card__footer[data-v-0f58e5b7] {\n padding: 16px 20px;\n}\n.tps-card--large .tps-card__header[data-v-0f58e5b7] {\n padding: 20px 24px;\n}\n.tps-card--large .tps-card__body[data-v-0f58e5b7] {\n padding: 24px;\n}\n.tps-card--large .tps-card__footer[data-v-0f58e5b7] {\n padding: 20px 24px;\n}\n\n/* 类型样式 */\n.tps-card--primary[data-v-0f58e5b7] {\n border-color: var(--tps-primary-color, #4d9bd5);\n}\n.tps-card--primary .tps-card__header[data-v-0f58e5b7] {\n background-color: var(--tps-primary-color, #4d9bd5);\n color: #ffffff;\n}\n.tps-card--success[data-v-0f58e5b7] {\n border-color: var(--tps-success-color, #67C23A);\n}\n.tps-card--success .tps-card__header[data-v-0f58e5b7] {\n background-color: var(--tps-success-color, #67C23A);\n color: #ffffff;\n}\n.tps-card--warning[data-v-0f58e5b7] {\n border-color: var(--tps-warning-color, #E6A23C);\n}\n.tps-card--warning .tps-card__header[data-v-0f58e5b7] {\n background-color: var(--tps-warning-color, #E6A23C);\n color: #ffffff;\n}\n.tps-card--danger[data-v-0f58e5b7] {\n border-color: var(--tps-danger-color, #F56C6C);\n}\n.tps-card--danger .tps-card__header[data-v-0f58e5b7] {\n background-color: var(--tps-danger-color, #F56C6C);\n color: #ffffff;\n}\n.tps-card--info[data-v-0f58e5b7] {\n border-color: var(--tps-info-color, #909399);\n}\n.tps-card--info .tps-card__header[data-v-0f58e5b7] {\n background-color: var(--tps-info-color, #909399);\n color: #ffffff;\n}\n\n/* 头部样式 */\n.tps-card__header[data-v-0f58e5b7] {\n background-color: var(--tps-background-color, #ffffff);\n border-bottom: 1px solid var(--tps-border-color, #EBEEF5);\n display: flex;\n justify-content: space-between;\n align-items: center;\n font-weight: 500;\n}\n.tps-card__title[data-v-0f58e5b7] {\n display: flex;\n align-items: center;\n font-size: 16px;\n color: var(--tps-text-color, #303133);\n}\n.tps-card__icon[data-v-0f58e5b7] {\n margin-right: 8px;\n font-size: 18px;\n}\n.tps-card__extra[data-v-0f58e5b7] {\n color: var(--tps-text-color, #606266);\n}\n\n/* 内容样式 */\n.tps-card__body[data-v-0f58e5b7] {\n color: var(--tps-text-color, #606266);\n line-height: 1.6;\n}\n\n/* 底部样式 */\n.tps-card__footer[data-v-0f58e5b7] {\n background-color: var(--tps-background-color, #fafafa);\n border-top: 1px solid var(--tps-border-color, #EBEEF5);\n color: var(--tps-text-color, #606266);\n}\n\n/* 加载状态 */\n.tps-card--loading[data-v-0f58e5b7] {\n position: relative;\n overflow: hidden;\n}\n.tps-card--loading[data-v-0f58e5b7]::before {\n content: '';\n position: absolute;\n top: 0;\n left: -100%;\n width: 100%;\n height: 100%;\n background: linear-gradient(\n 90deg,\n transparent,\n rgba(255, 255, 255, 0.4),\n transparent\n );\n animation: loading-data-v-0f58e5b7 1.5s infinite;\n z-index: 1;\n}\n@keyframes loading-data-v-0f58e5b7 {\n0% {\n left: -100%;\n}\n100% {\n left: 100%;\n}\n}\n\n/* 响应式设计 */\n@media (max-width: 768px) {\n.tps-card[data-v-0f58e5b7] {\n margin: 8px;\n}\n.tps-card__header[data-v-0f58e5b7] {\n padding: 12px 16px;\n}\n.tps-card__body[data-v-0f58e5b7] {\n padding: 16px;\n}\n.tps-card__footer[data-v-0f58e5b7] {\n padding: 12px 16px;\n}\n}\n", map: {"version":3,"sources":["E:\\新建文件夹\\tps-ui-components\\src\\components\\TpsCard\\index.vue"],"names":[],"mappings":";AA8LA;EACA,sDAAA;EACA,kDAAA;EACA,kBAAA;EACA,gBAAA;EACA,yBAAA;EACA,kBAAA;AACA;;AAEA,SAAA;AACA;EACA,2CAAA;AACA;AAEA;EACA,gBAAA;AACA;AAEA;EACA,2CAAA;AACA;AAEA;EACA,gBAAA;AACA;;AAEA,SAAA;AACA;EACA,kDAAA;AACA;AAEA;EACA,YAAA;AACA;;AAEA,SAAA;AACA;EACA,2BAAA;EACA,4CAAA;AACA;;AAEA,SAAA;AACA;EACA,kBAAA;AACA;AAEA;EACA,kBAAA;AACA;AAEA;EACA,kBAAA;AACA;AAEA;EACA,kBAAA;AACA;AAEA;EACA,aAAA;AACA;AAEA;EACA,kBAAA;AACA;AAEA;EACA,kBAAA;AACA;AAEA;EACA,aAAA;AACA;AAEA;EACA,kBAAA;AACA;;AAEA,SAAA;AACA;EACA,+CAAA;AACA;AAEA;EACA,mDAAA;EACA,cAAA;AACA;AAEA;EACA,+CAAA;AACA;AAEA;EACA,mDAAA;EACA,cAAA;AACA;AAEA;EACA,+CAAA;AACA;AAEA;EACA,mDAAA;EACA,cAAA;AACA;AAEA;EACA,8CAAA;AACA;AAEA;EACA,kDAAA;EACA,cAAA;AACA;AAEA;EACA,4CAAA;AACA;AAEA;EACA,gDAAA;EACA,cAAA;AACA;;AAEA,SAAA;AACA;EACA,sDAAA;EACA,yDAAA;EACA,aAAA;EACA,8BAAA;EACA,mBAAA;EACA,gBAAA;AACA;AAEA;EACA,aAAA;EACA,mBAAA;EACA,eAAA;EACA,qCAAA;AACA;AAEA;EACA,iBAAA;EACA,eAAA;AACA;AAEA;EACA,qCAAA;AACA;;AAEA,SAAA;AACA;EACA,qCAAA;EACA,gBAAA;AACA;;AAEA,SAAA;AACA;EACA,sDAAA;EACA,sDAAA;EACA,qCAAA;AACA;;AAEA,SAAA;AACA;EACA,kBAAA;EACA,gBAAA;AACA;AAEA;EACA,WAAA;EACA,kBAAA;EACA,MAAA;EACA,WAAA;EACA,WAAA;EACA,YAAA;EACA;;;;;GAKA;EACA,gDAAA;EACA,UAAA;AACA;AAEA;AACA;IACA,WAAA;AACA;AACA;IACA,UAAA;AACA;AACA;;AAEA,UAAA;AACA;AACA;IACA,WAAA;AACA;AAEA;IACA,kBAAA;AACA;AAEA;IACA,aAAA;AACA;AAEA;IACA,kBAAA;AACA;AACA","file":"index.vue","sourcesContent":["<template>\n <div :class=\"cardClass\" :style=\"cardStyle\">\n <!-- 卡片头部 -->\n <div v-if=\"$slots.header || title\" class=\"tps-card__header\">\n <slot name=\"header\">\n <div class=\"tps-card__title\">\n <i v-if=\"icon\" :class=\"icon\" class=\"tps-card__icon\"></i>\n {{ title }}\n </div>\n <div v-if=\"$slots.extra\" class=\"tps-card__extra\">\n <slot name=\"extra\"></slot>\n </div>\n </slot>\n </div>\n \n <!-- 卡片内容 -->\n <div class=\"tps-card__body\" :style=\"bodyStyle\">\n <slot></slot>\n </div>\n \n <!-- 卡片底部 -->\n <div v-if=\"$slots.footer\" class=\"tps-card__footer\">\n <slot name=\"footer\"></slot>\n </div>\n </div>\n</template>\n\n<script>\n/**\n * TpsCard 卡片组件\n * 提供统一的卡片容器,支持多种样式和布局\n * @displayName TpsCard\n */\nexport default {\n name: 'TpsCard',\n \n props: {\n /**\n * 卡片标题\n */\n title: {\n type: String,\n default: ''\n },\n \n /**\n * 标题图标\n */\n icon: {\n type: String,\n default: ''\n },\n \n /**\n * 卡片阴影\n * @values always, hover, never\n */\n shadow: {\n type: String,\n default: 'always',\n validator: value => {\n return ['always', 'hover', 'never'].includes(value)\n }\n },\n \n /**\n * 卡片内边距\n */\n padding: {\n type: [String, Number],\n default: '20px'\n },\n \n /**\n * 卡片圆角\n */\n radius: {\n type: [String, Number],\n default: '8px'\n },\n \n /**\n * 是否有边框\n */\n bordered: {\n type: Boolean,\n default: true\n },\n \n /**\n * 卡片类型\n * @values default, primary, success, warning, danger, info\n */\n type: {\n type: String,\n default: 'default',\n validator: value => {\n return ['default', 'primary', 'success', 'warning', 'danger', 'info'].includes(value)\n }\n },\n \n /**\n * 是否可悬浮\n */\n hoverable: {\n type: Boolean,\n default: false\n },\n \n /**\n * 是否加载中\n */\n loading: {\n type: Boolean,\n default: false\n },\n \n /**\n * 自定义背景色\n */\n backgroundColor: {\n type: String,\n default: ''\n },\n \n /**\n * 卡片尺寸\n * @values small, medium, large\n */\n size: {\n type: String,\n default: 'medium',\n validator: value => {\n return ['small', 'medium', 'large'].includes(value)\n }\n }\n },\n \n computed: {\n /**\n * 卡片样式类\n */\n cardClass() {\n return [\n 'tps-card',\n `tps-card--${this.shadow}`,\n `tps-card--${this.size}`,\n {\n [`tps-card--${this.type}`]: this.type !== 'default',\n 'tps-card--bordered': this.bordered,\n 'tps-card--hoverable': this.hoverable,\n 'tps-card--loading': this.loading\n }\n ]\n },\n \n /**\n * 卡片样式\n */\n cardStyle() {\n const style = {}\n \n if (this.radius) {\n style.borderRadius = typeof this.radius === 'number' ? `${this.radius}px` : this.radius\n }\n \n if (this.backgroundColor) {\n style.backgroundColor = this.backgroundColor\n }\n \n return style\n },\n \n /**\n * 卡片内容样式\n */\n bodyStyle() {\n const style = {}\n \n if (this.padding) {\n style.padding = typeof this.padding === 'number' ? `${this.padding}px` : this.padding\n }\n \n return style\n }\n }\n}\n</script>\n\n<style scoped>\n.tps-card {\n background-color: var(--tps-background-color, #ffffff);\n border: 1px solid var(--tps-border-color, #EBEEF5);\n border-radius: 8px;\n overflow: hidden;\n transition: all 0.3s ease;\n position: relative;\n}\n\n/* 阴影样式 */\n.tps-card--always {\n box-shadow: 0 2px 12px 0 rgba(0, 0, 0, 0.1);\n}\n\n.tps-card--hover {\n box-shadow: none;\n}\n\n.tps-card--hover:hover {\n box-shadow: 0 2px 12px 0 rgba(0, 0, 0, 0.1);\n}\n\n.tps-card--never {\n box-shadow: none;\n}\n\n/* 边框样式 */\n.tps-card--bordered {\n border: 1px solid var(--tps-border-color, #EBEEF5);\n}\n\n.tps-card:not(.tps-card--bordered) {\n border: none;\n}\n\n/* 悬浮效果 */\n.tps-card--hoverable:hover {\n transform: translateY(-2px);\n box-shadow: 0 4px 20px 0 rgba(0, 0, 0, 0.15);\n}\n\n/* 尺寸样式 */\n.tps-card--small .tps-card__header {\n padding: 12px 16px;\n}\n\n.tps-card--small .tps-card__body {\n padding: 12px 16px;\n}\n\n.tps-card--small .tps-card__footer {\n padding: 12px 16px;\n}\n\n.tps-card--medium .tps-card__header {\n padding: 16px 20px;\n}\n\n.tps-card--medium .tps-card__body {\n padding: 20px;\n}\n\n.tps-card--medium .tps-card__footer {\n padding: 16px 20px;\n}\n\n.tps-card--large .tps-card__header {\