tps-ui-components
Version:
TPS UI组件库 - 基于Vue 2和Element UI的企业级组件库
1,310 lines (1,204 loc) • 136 kB
JavaScript
'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 {\