completepage: 🍻 多语言添加页面完成
This commit is contained in:
parent
7efa04759c
commit
d373c138fb
|
@ -1,82 +0,0 @@
|
||||||
// 模拟后端动态生成路由
|
|
||||||
import { defineFakeRoute } from 'vite-plugin-fake-server/client';
|
|
||||||
|
|
||||||
/**
|
|
||||||
* roles:页面级别权限,这里模拟二种 "admin"、"common"
|
|
||||||
* admin:管理员角色
|
|
||||||
* common:普通角色
|
|
||||||
*/
|
|
||||||
const permissionRouter = {
|
|
||||||
path: '/permission',
|
|
||||||
meta: {
|
|
||||||
title: 'menus.purePermission',
|
|
||||||
icon: 'ep:lollipop',
|
|
||||||
rank: 10,
|
|
||||||
},
|
|
||||||
children: [
|
|
||||||
{
|
|
||||||
path: '/permission/page/index',
|
|
||||||
name: 'PermissionPage',
|
|
||||||
meta: {
|
|
||||||
title: 'menus.purePermissionPage',
|
|
||||||
roles: ['admin', 'common'],
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
path: '/permission/button/router',
|
|
||||||
component: 'permission/button/index',
|
|
||||||
name: 'PermissionButtonRouter',
|
|
||||||
meta: {
|
|
||||||
title: 'menus.purePermissionButtonRouter',
|
|
||||||
auths: ['permission:btn:add', 'permission:btn:edit', 'permission:btn:delete'],
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
path: '/permission/button/login',
|
|
||||||
component: 'permission/button/perms',
|
|
||||||
name: 'PermissionButtonLogin',
|
|
||||||
meta: {
|
|
||||||
title: 'menus.purePermissionButtonLogin',
|
|
||||||
},
|
|
||||||
},
|
|
||||||
],
|
|
||||||
};
|
|
||||||
|
|
||||||
const user = {
|
|
||||||
path: '/user',
|
|
||||||
meta: {
|
|
||||||
icon: 'ep:lollipop',
|
|
||||||
title: '用户',
|
|
||||||
rank: 1,
|
|
||||||
},
|
|
||||||
children: [
|
|
||||||
{
|
|
||||||
path: '/user/index',
|
|
||||||
meta: {
|
|
||||||
icon: null,
|
|
||||||
title: '用户index',
|
|
||||||
rank: 2,
|
|
||||||
roles: ['admin', 'common'],
|
|
||||||
auths: ['*', '*::*', '*::*::*', '*', '*::*', '::*::*'],
|
|
||||||
},
|
|
||||||
id: '2',
|
|
||||||
parentId: '1',
|
|
||||||
name: '用户index',
|
|
||||||
children: [],
|
|
||||||
},
|
|
||||||
],
|
|
||||||
};
|
|
||||||
|
|
||||||
// 获取系统路由
|
|
||||||
export default defineFakeRoute([
|
|
||||||
{
|
|
||||||
url: '/mock/get-async-routes',
|
|
||||||
method: 'get',
|
|
||||||
response: () => {
|
|
||||||
return {
|
|
||||||
success: true,
|
|
||||||
data: [permissionRouter, user],
|
|
||||||
};
|
|
||||||
},
|
|
||||||
},
|
|
||||||
]);
|
|
16
mock/i18n.ts
16
mock/i18n.ts
|
@ -1,16 +0,0 @@
|
||||||
import { defineFakeRoute } from 'vite-plugin-fake-server/client';
|
|
||||||
import en from './i18n/en';
|
|
||||||
import zh from './i18n/zh';
|
|
||||||
|
|
||||||
export default defineFakeRoute([
|
|
||||||
{
|
|
||||||
url: '/mock/getI18n',
|
|
||||||
method: 'get',
|
|
||||||
response: () => {
|
|
||||||
return {
|
|
||||||
code: 200,
|
|
||||||
data: { zh, en, local: 'zh' },
|
|
||||||
};
|
|
||||||
},
|
|
||||||
},
|
|
||||||
]);
|
|
|
@ -1,20 +0,0 @@
|
||||||
import { buttons } from "./en/buttons";
|
|
||||||
import { search } from "./en/search";
|
|
||||||
import { panel } from "./en/panel";
|
|
||||||
import { menus } from "./en/menus";
|
|
||||||
import { status } from "./en/status";
|
|
||||||
import { login } from "./en/login";
|
|
||||||
import { style } from "./en/style";
|
|
||||||
import { system } from "./en/system";
|
|
||||||
|
|
||||||
export default {
|
|
||||||
name: "en",
|
|
||||||
buttons,
|
|
||||||
search,
|
|
||||||
panel,
|
|
||||||
menus,
|
|
||||||
status,
|
|
||||||
login,
|
|
||||||
style,
|
|
||||||
system
|
|
||||||
};
|
|
|
@ -1,25 +0,0 @@
|
||||||
export const buttons = {
|
|
||||||
openSystemSet: "Open System Configs",
|
|
||||||
pureOpenSystemSet: "pureOpenSystemSet",
|
|
||||||
|
|
||||||
pureAccountSettings: "Account",
|
|
||||||
pureLoginOut: "LoginOut",
|
|
||||||
pureLogin: "Login",
|
|
||||||
pureReload: "Reload",
|
|
||||||
pureCloseCurrentTab: "Close CurrentTab",
|
|
||||||
pureCloseLeftTabs: "Close LeftTabs",
|
|
||||||
pureCloseRightTabs: "Close RightTabs",
|
|
||||||
pureCloseOtherTabs: "Close OtherTabs",
|
|
||||||
pureCloseAllTabs: "Close AllTabs",
|
|
||||||
pureContentFullScreen: "Content FullScreen",
|
|
||||||
pureContentExitFullScreen: "Content ExitFullScreen",
|
|
||||||
pureClickCollapse: "Collapse",
|
|
||||||
pureClickExpand: "Expand",
|
|
||||||
confirm: "Confirm",
|
|
||||||
pureSwitch: "Switch",
|
|
||||||
close: "Close",
|
|
||||||
pureBackTop: "BackTop",
|
|
||||||
pureOpenText: "Open",
|
|
||||||
pureCloseText: "Close",
|
|
||||||
rest: "Rest"
|
|
||||||
};
|
|
|
@ -1,40 +0,0 @@
|
||||||
export const login = {
|
|
||||||
loginSuccess: "Login Success",
|
|
||||||
loginFail: "Login Fail",
|
|
||||||
usernameRegex: "please input username",
|
|
||||||
username: "input username",
|
|
||||||
password: "input password",
|
|
||||||
login: "Login",
|
|
||||||
|
|
||||||
email: "email",
|
|
||||||
repeatPassword: "Sure Password",
|
|
||||||
emailCode: "input email code",
|
|
||||||
verifyCode: "verify code",
|
|
||||||
emailRegex: "please input email",
|
|
||||||
passwordRegex: "please input password",
|
|
||||||
passwordSureRegex: "Please entr confirm password",
|
|
||||||
passwordDifferentRegex: "The two passwords do not match!",
|
|
||||||
emailCodeRegex: "please input email code",
|
|
||||||
getEmailCode: "get email code",
|
|
||||||
rememberMe: "days no need to login",
|
|
||||||
rememberInfo:
|
|
||||||
"After checking and logging in, will automatically log in to the system without entering your username and password within the specified number of days.",
|
|
||||||
forgetPassword: "Forget Password?",
|
|
||||||
getCodeInfo: "Seconds",
|
|
||||||
getVerifyCode: "Get VerifyCode",
|
|
||||||
definite: "definite",
|
|
||||||
back: "back",
|
|
||||||
passWordUpdateReg: "Password has been updated",
|
|
||||||
pureTip: 'After scanning the code, click "Confirm" to complete the login',
|
|
||||||
pureRegisterSuccess: "Regist Success",
|
|
||||||
pureTickPrivacy: "Please tick Privacy Policy",
|
|
||||||
pureReadAccept: "I have read it carefully and accept",
|
|
||||||
purePrivacyPolicy: "Privacy Policy",
|
|
||||||
pureVerifyCodeReg: "Please enter verify code",
|
|
||||||
pureVerifyCodeCorrectReg: "Please enter correct verify code",
|
|
||||||
pureVerifyCodeSixReg: "Please enter a 6-digit verify code",
|
|
||||||
purePhoneReg: "Please enter the phone",
|
|
||||||
purePhoneCorrectReg: "Please enter the correct phone number format",
|
|
||||||
purePassWordRuleReg:
|
|
||||||
"The password format should be any combination of 8-18 digits"
|
|
||||||
};
|
|
|
@ -1,120 +0,0 @@
|
||||||
export const menus = {
|
|
||||||
home: "Home",
|
|
||||||
purePermissionButtonRouter: "PermissionButtonRouter",
|
|
||||||
purePermissionButtonLogin: "purePermissionButtonLogin",
|
|
||||||
pureLogin: "Login",
|
|
||||||
pureEmpty: "Empty Page",
|
|
||||||
pureTable: "Table",
|
|
||||||
pureSysManagement: "System Manage",
|
|
||||||
pureUser: "User Manage",
|
|
||||||
pureRole: "Role Manage",
|
|
||||||
pureSystemMenu: "Menu Manage",
|
|
||||||
pureDept: "Dept Manage",
|
|
||||||
pureSysMonitor: "System Monitor",
|
|
||||||
pureOnlineUser: "Online User",
|
|
||||||
pureLoginLog: "Login Log",
|
|
||||||
pureOperationLog: "Operation Log",
|
|
||||||
pureSystemLog: "System Log",
|
|
||||||
pureEditor: "Editor",
|
|
||||||
pureAbnormal: "Abnormal Page",
|
|
||||||
pureFourZeroFour: "404",
|
|
||||||
pureFourZeroOne: "403",
|
|
||||||
pureFive: "500",
|
|
||||||
pureComponents: "Components",
|
|
||||||
pureDialog: "Dialog",
|
|
||||||
pureMessage: "Message Tips",
|
|
||||||
pureVideo: "Video",
|
|
||||||
pureSegmented: "Segmented",
|
|
||||||
pureWaterfall: "Waterfall",
|
|
||||||
pureMap: "Map",
|
|
||||||
pureDraggable: "Draggable",
|
|
||||||
pureSplitPane: "Split Pane",
|
|
||||||
pureText: "Text Ellipsis",
|
|
||||||
pureElButton: "Button",
|
|
||||||
pureButton: "Button Animation",
|
|
||||||
pureCheckButton: "Check Button",
|
|
||||||
pureCropping: "Picture Cropping",
|
|
||||||
pureAnimatecss: "AnimateCss Selector",
|
|
||||||
pureCountTo: "Digital Animation",
|
|
||||||
pureSelector: "Scope Selector",
|
|
||||||
pureFlowChart: "Flow Chart",
|
|
||||||
pureSeamless: "Seamless Scroll",
|
|
||||||
pureContextmenu: "Context Menu",
|
|
||||||
pureTypeit: "Typeit",
|
|
||||||
pureJsonEditor: "JSON Editor",
|
|
||||||
pureColorPicker: "Color Picker",
|
|
||||||
pureDatePicker: "Date Picker",
|
|
||||||
pureDateTimePicker: "DateTimePicker",
|
|
||||||
pureTimePicker: "TimePicker",
|
|
||||||
pureTag: "Tag",
|
|
||||||
pureStatistic: "Statistic",
|
|
||||||
pureCollapse: "Collapse",
|
|
||||||
pureGanttastic: "Gantt Chart",
|
|
||||||
pureProgress: "Progress",
|
|
||||||
pureUpload: "File Upload",
|
|
||||||
pureCheckCard: "CheckCard",
|
|
||||||
pureMenus: "MultiLevel Menu",
|
|
||||||
pureMenu1: "Menu1",
|
|
||||||
pureMenu2: "Menu2",
|
|
||||||
purePermission: "Permission Manage",
|
|
||||||
purePermissionPage: "Page Permission",
|
|
||||||
purePermissionButton: "Button Permission",
|
|
||||||
pureTabs: "Tabs Operate",
|
|
||||||
pureGuide: "Guide",
|
|
||||||
pureAble: "Able",
|
|
||||||
pureMenuTree: "Menu Tree",
|
|
||||||
pureVideoFrame: "Video Frame Capture",
|
|
||||||
pureWavesurfer: "Audio Visualization",
|
|
||||||
pureRipple: "Ripple",
|
|
||||||
pureMqtt: "Mqtt Client",
|
|
||||||
pureOptimize: "Debounce、Throttle、Copy、Longpress Directives",
|
|
||||||
pureVerify: "Captcha",
|
|
||||||
pureWatermark: "Water Mark",
|
|
||||||
purePrint: "Print",
|
|
||||||
pureDownload: "Download",
|
|
||||||
pureExternalPage: "External Page",
|
|
||||||
pureExternalDoc: "Docs External",
|
|
||||||
pureEmbeddedDoc: "Docs Embedded",
|
|
||||||
pureExternalLink: "Vue-Pure-Admin",
|
|
||||||
pureUtilsLink: "Pure-Admin-Utils",
|
|
||||||
pureColorHuntDoc: "ColorHunt",
|
|
||||||
pureUiGradients: "UiGradients",
|
|
||||||
pureEpDoc: "Element-Plus",
|
|
||||||
pureTailwindcssDoc: "Tailwindcss",
|
|
||||||
pureVueDoc: "Vue3",
|
|
||||||
pureViteDoc: "Vite",
|
|
||||||
purePiniaDoc: "Pinia",
|
|
||||||
pureRouterDoc: "Vue-Router",
|
|
||||||
pureAbout: "About",
|
|
||||||
pureResult: "Result Page",
|
|
||||||
pureSuccess: "Success Page",
|
|
||||||
pureFail: "Fail Page",
|
|
||||||
pureIconSelect: "Icon Select",
|
|
||||||
pureTimeline: "Time Line",
|
|
||||||
pureLineTree: "LineTree",
|
|
||||||
pureList: "List Page",
|
|
||||||
pureCardList: "Card List Page",
|
|
||||||
pureDebounce: "Debounce & Throttle",
|
|
||||||
pureFormDesign: "Form Design",
|
|
||||||
pureBarcode: "Barcode",
|
|
||||||
pureQrcode: "Qrcode",
|
|
||||||
pureCascader: "Area Cascader",
|
|
||||||
pureSwiper: "Swiper Plugin",
|
|
||||||
pureVirtualList: "Virtual List",
|
|
||||||
purePdf: "PDF Preview",
|
|
||||||
pureExcel: "Export Excel",
|
|
||||||
pureInfiniteScroll: "Table Infinite Scroll",
|
|
||||||
pureSensitive: "Sensitive Filter",
|
|
||||||
purePinyin: "PinYin",
|
|
||||||
pureDanmaku: "Danmaku",
|
|
||||||
pureSchemaForm: "Form",
|
|
||||||
pureTableBase: "Base Usage",
|
|
||||||
pureTableHigh: "High Usage",
|
|
||||||
pureTableEdit: "Edit Usage",
|
|
||||||
pureVxeTable: "Virtual Usage",
|
|
||||||
pureBoard: "Paint Board",
|
|
||||||
pureMindMap: "Mind Map",
|
|
||||||
pureMenuOverflow: "Menu Overflow Show Tooltip Text",
|
|
||||||
pureChildMenuOverflow: "Child Menu Overflow Show Tooltip Text",
|
|
||||||
systemctlTest: "Systemctl lTest"
|
|
||||||
};
|
|
|
@ -1,38 +0,0 @@
|
||||||
export const panel = {
|
|
||||||
pureSystemSet: "System Configs",
|
|
||||||
pureCloseSystemSet: "Close System Configs",
|
|
||||||
pureClearCacheAndToLogin: "Clear cache and return to login page",
|
|
||||||
pureClearCache: "Clear Cache",
|
|
||||||
pureOverallStyle: "Overall Style",
|
|
||||||
pureOverallStyleLight: "Light",
|
|
||||||
pureOverallStyleLightTip:
|
|
||||||
"Set sail freshly and light up the comfortable work interface",
|
|
||||||
pureOverallStyleDark: "Dark",
|
|
||||||
pureOverallStyleDarkTip:
|
|
||||||
"Moonlight Overture, indulge in the tranquility and elegance of the night",
|
|
||||||
pureOverallStyleSystem: "Auto",
|
|
||||||
pureOverallStyleSystemTip:
|
|
||||||
"Synchronize time, the interface naturally responds to morning and dusk",
|
|
||||||
pureThemeColor: "Theme Color",
|
|
||||||
pureLayoutModel: "Layout Model",
|
|
||||||
pureVerticalTip: "The menu on the left is familiar and friendly",
|
|
||||||
pureHorizontalTip: "Top menu, concise overview",
|
|
||||||
pureMixTip: "Mixed menu, flexible",
|
|
||||||
pureStretch: "Stretch Page",
|
|
||||||
pureStretchFixed: "Fixed",
|
|
||||||
pureStretchFixedTip:
|
|
||||||
"Compact pages make it easy to find the information you need",
|
|
||||||
pureStretchCustom: "Custom",
|
|
||||||
pureStretchCustomTip: "Minimum 1280, maximum 1600",
|
|
||||||
pureTagsStyle: "Tags Style",
|
|
||||||
pureTagsStyleSmart: "Smart",
|
|
||||||
pureTagsStyleSmartTip: "Smart tags add fun and brilliance",
|
|
||||||
pureTagsStyleCard: "Card",
|
|
||||||
pureTagsStyleCardTip: "Card tags for efficient browsing",
|
|
||||||
pureInterfaceDisplay: "Interface Display",
|
|
||||||
pureGreyModel: "Grey Model",
|
|
||||||
pureWeakModel: "Weak Model",
|
|
||||||
pureHiddenTags: "Hidden Tags",
|
|
||||||
pureHiddenFooter: "Hidden Footer",
|
|
||||||
pureMultiTagsCache: "MultiTags Cache"
|
|
||||||
};
|
|
|
@ -1,8 +0,0 @@
|
||||||
export const search = {
|
|
||||||
pureTotal: "Total",
|
|
||||||
pureHistory: "History",
|
|
||||||
pureCollect: "Collect",
|
|
||||||
pureDragSort: "(Drag Sort)",
|
|
||||||
pureEmpty: "Empty",
|
|
||||||
purePlaceholder: "Search Menu"
|
|
||||||
};
|
|
|
@ -1,11 +0,0 @@
|
||||||
export const status = {
|
|
||||||
pureLoad: "Loading...",
|
|
||||||
pureMessage: "Message",
|
|
||||||
pureNotify: "Notify",
|
|
||||||
pureTodo: "Todo",
|
|
||||||
pureNoMessage: "No Message",
|
|
||||||
pureNoNotify: "No Notify",
|
|
||||||
pureNoTodo: "No Todo",
|
|
||||||
enable: "enable",
|
|
||||||
disable: "disable"
|
|
||||||
};
|
|
|
@ -1,5 +0,0 @@
|
||||||
export const style = {
|
|
||||||
larger: "Larger",
|
|
||||||
default: "Default",
|
|
||||||
small: "Small"
|
|
||||||
};
|
|
|
@ -1,8 +0,0 @@
|
||||||
export const system = {
|
|
||||||
carousel: "carousel setting",
|
|
||||||
config: "system config",
|
|
||||||
favicon: "system favicon",
|
|
||||||
feedback: "system feedback",
|
|
||||||
emailUsers: "email users",
|
|
||||||
log: "system log"
|
|
||||||
};
|
|
|
@ -1,20 +0,0 @@
|
||||||
import { buttons } from "./zh/buttons";
|
|
||||||
import { search } from "./zh/search";
|
|
||||||
import { panel } from "./zh/panel";
|
|
||||||
import { menus } from "./zh/menus";
|
|
||||||
import { status } from "./zh/status";
|
|
||||||
import { login } from "./zh/login";
|
|
||||||
import { style } from "./zh/style";
|
|
||||||
import { system } from "./zh/system";
|
|
||||||
|
|
||||||
export default {
|
|
||||||
name: "zh",
|
|
||||||
buttons,
|
|
||||||
search,
|
|
||||||
panel,
|
|
||||||
menus,
|
|
||||||
status,
|
|
||||||
login,
|
|
||||||
style,
|
|
||||||
system
|
|
||||||
};
|
|
|
@ -1,26 +0,0 @@
|
||||||
export const buttons = {
|
|
||||||
openSystemSet: "打开系统配置",
|
|
||||||
pureOpenSystemSet: "权限设定",
|
|
||||||
|
|
||||||
pureAccountSettings: "账户设置",
|
|
||||||
pureLoginOut: "退出系统",
|
|
||||||
pureLogin: "登录",
|
|
||||||
pureReload: "重新加载",
|
|
||||||
pureCloseCurrentTab: "关闭当前标签页",
|
|
||||||
pureCloseLeftTabs: "关闭左侧标签页",
|
|
||||||
pureCloseRightTabs: "关闭右侧标签页",
|
|
||||||
pureCloseOtherTabs: "关闭其他标签页",
|
|
||||||
pureCloseAllTabs: "关闭全部标签页",
|
|
||||||
pureContentFullScreen: "内容区全屏",
|
|
||||||
pureContentExitFullScreen: "内容区退出全屏",
|
|
||||||
pureClickCollapse: "点击折叠",
|
|
||||||
pureClickExpand: "点击展开",
|
|
||||||
confirm: "确认",
|
|
||||||
pureSwitch: "切换",
|
|
||||||
close: "关闭",
|
|
||||||
pureBackTop: "回到顶部",
|
|
||||||
pureOpenText: "开",
|
|
||||||
pureCloseText: "关",
|
|
||||||
rest: "重置",
|
|
||||||
search: "搜索"
|
|
||||||
};
|
|
|
@ -1,38 +0,0 @@
|
||||||
export const login = {
|
|
||||||
loginSuccess: "登录成功",
|
|
||||||
loginFail: "登录失败",
|
|
||||||
usernameRegex: "请输入账号",
|
|
||||||
username: "输入用户名",
|
|
||||||
password: "输入密码",
|
|
||||||
login: "登录",
|
|
||||||
|
|
||||||
email: "输入邮箱",
|
|
||||||
repeatPassword: "确认密码",
|
|
||||||
emailCode: "邮箱验证码",
|
|
||||||
verifyCode: "图形验证码",
|
|
||||||
emailRegex: "输入邮箱",
|
|
||||||
passwordRegex: "请输入密码",
|
|
||||||
passwordSureRegex: "请输入确认密码",
|
|
||||||
repeatPasswordRegex: "请输入确认密码",
|
|
||||||
passwordDifferentRegex: "两次密码不一致!",
|
|
||||||
emailCodeRegex: "请输入邮箱验证码",
|
|
||||||
verifyCodeRegex: "输入验证码",
|
|
||||||
getEmailCode: "获取邮箱验证码",
|
|
||||||
rememberMe: "天内免登录",
|
|
||||||
rememberInfo: "勾选并登录后,规定天数内无需输入用户名和密码会自动登入系统",
|
|
||||||
forgetPassword: "忘记密码?",
|
|
||||||
getVerifyCode: "获取验证码",
|
|
||||||
definite: "确定",
|
|
||||||
back: "返回",
|
|
||||||
getCodeInfo: "秒后重新获取",
|
|
||||||
passWordUpdateReg: "修改密码成功",
|
|
||||||
pureRegisterSuccess: "注册成功",
|
|
||||||
pureTickPrivacy: "请勾选隐私政策",
|
|
||||||
pureReadAccept: "我已仔细阅读并接受",
|
|
||||||
purePrivacyPolicy: "《隐私政策》",
|
|
||||||
pureVerifyCodeCorrectReg: "请输入正确的验证码",
|
|
||||||
pureVerifyCodeSixReg: "请输入6位数字验证码",
|
|
||||||
purePhoneReg: "请输入手机号码",
|
|
||||||
purePhoneCorrectReg: "请输入正确的手机号码格式",
|
|
||||||
purePassWordRuleReg: "密码格式应为8-18位数字、字母、符号的任意两种组合"
|
|
||||||
};
|
|
|
@ -1,120 +0,0 @@
|
||||||
export const menus = {
|
|
||||||
home: "首页",
|
|
||||||
purePermissionButtonRouter: "权限1",
|
|
||||||
purePermissionButtonLogin: "权限2",
|
|
||||||
pureLogin: "登录",
|
|
||||||
pureEmpty: "无Layout页",
|
|
||||||
pureTable: "表格",
|
|
||||||
pureSysManagement: "系统管理",
|
|
||||||
pureUser: "用户管理",
|
|
||||||
pureRole: "角色管理",
|
|
||||||
pureSystemMenu: "菜单管理",
|
|
||||||
pureDept: "部门管理",
|
|
||||||
pureSysMonitor: "系统监控",
|
|
||||||
pureOnlineUser: "在线用户",
|
|
||||||
pureLoginLog: "登录日志",
|
|
||||||
pureOperationLog: "操作日志",
|
|
||||||
pureSystemLog: "系统日志",
|
|
||||||
pureEditor: "编辑器",
|
|
||||||
pureAbnormal: "异常页面",
|
|
||||||
pureFourZeroFour: "404",
|
|
||||||
pureFourZeroOne: "403",
|
|
||||||
pureFive: "500",
|
|
||||||
pureComponents: "组件",
|
|
||||||
pureDialog: "函数式弹框",
|
|
||||||
pureMessage: "消息提示",
|
|
||||||
pureVideo: "视频",
|
|
||||||
pureSegmented: "分段控制器",
|
|
||||||
pureWaterfall: "瀑布流无限滚动",
|
|
||||||
pureMap: "地图",
|
|
||||||
pureDraggable: "拖拽",
|
|
||||||
pureSplitPane: "切割面板",
|
|
||||||
pureText: "文本省略",
|
|
||||||
pureElButton: "按钮",
|
|
||||||
pureCheckButton: "可选按钮",
|
|
||||||
pureButton: "按钮动效",
|
|
||||||
pureCropping: "图片裁剪",
|
|
||||||
pureAnimatecss: "animate.css选择器",
|
|
||||||
pureCountTo: "数字动画",
|
|
||||||
pureSelector: "范围选择器",
|
|
||||||
pureFlowChart: "流程图",
|
|
||||||
pureSeamless: "无缝滚动",
|
|
||||||
pureContextmenu: "右键菜单",
|
|
||||||
pureTypeit: "打字机",
|
|
||||||
pureJsonEditor: "JSON编辑器",
|
|
||||||
pureColorPicker: "颜色选择器",
|
|
||||||
pureDatePicker: "日期选择器",
|
|
||||||
pureDateTimePicker: "日期时间选择器",
|
|
||||||
pureTimePicker: "时间选择器",
|
|
||||||
pureTag: "标签",
|
|
||||||
pureStatistic: "统计组件",
|
|
||||||
pureCollapse: "折叠面板",
|
|
||||||
pureGanttastic: "甘特图",
|
|
||||||
pureProgress: "进度条",
|
|
||||||
pureUpload: "文件上传",
|
|
||||||
pureCheckCard: "多选卡片",
|
|
||||||
pureMenus: "多级菜单",
|
|
||||||
pureMenu1: "菜单1",
|
|
||||||
pureMenu2: "菜单2",
|
|
||||||
purePermission: "权限管理",
|
|
||||||
purePermissionPage: "页面权限",
|
|
||||||
purePermissionButton: "按钮权限",
|
|
||||||
pureTabs: "标签页操作",
|
|
||||||
pureGuide: "引导页",
|
|
||||||
pureAble: "功能",
|
|
||||||
pureMenuTree: "菜单树结构",
|
|
||||||
pureVideoFrame: "视频帧截取-wasm版",
|
|
||||||
pureWavesurfer: "音频可视化",
|
|
||||||
pureRipple: "波纹(Ripple)",
|
|
||||||
pureMqtt: "MQTT客户端(mqtt)",
|
|
||||||
pureOptimize: "防抖、截流、复制、长按指令",
|
|
||||||
pureVerify: "图形验证码",
|
|
||||||
pureWatermark: "水印",
|
|
||||||
purePrint: "打印",
|
|
||||||
pureDownload: "下载",
|
|
||||||
pureExternalPage: "外部页面",
|
|
||||||
pureExternalDoc: "文档外链",
|
|
||||||
pureEmbeddedDoc: "文档内嵌",
|
|
||||||
pureExternalLink: "vue-pure-admin",
|
|
||||||
pureUtilsLink: "pure-admin-utils",
|
|
||||||
pureColorHuntDoc: "调色板",
|
|
||||||
pureUiGradients: "渐变色",
|
|
||||||
pureEpDoc: "element-plus",
|
|
||||||
pureTailwindcssDoc: "tailwindcss",
|
|
||||||
pureVueDoc: "vue3",
|
|
||||||
pureViteDoc: "vite",
|
|
||||||
purePiniaDoc: "pinia",
|
|
||||||
pureRouterDoc: "vue-router",
|
|
||||||
pureAbout: "关于",
|
|
||||||
pureResult: "结果页面",
|
|
||||||
pureSuccess: "成功页面",
|
|
||||||
pureFail: "失败页面",
|
|
||||||
pureIconSelect: "图标选择器",
|
|
||||||
pureTimeline: "时间线",
|
|
||||||
pureLineTree: "树形连接线",
|
|
||||||
pureList: "列表页面",
|
|
||||||
pureCardList: "卡片列表页",
|
|
||||||
pureDebounce: "防抖节流",
|
|
||||||
pureFormDesign: "表单设计器",
|
|
||||||
pureBarcode: "条形码",
|
|
||||||
pureQrcode: "二维码",
|
|
||||||
pureCascader: "区域级联选择器",
|
|
||||||
pureSwiper: "Swiper插件",
|
|
||||||
pureVirtualList: "虚拟列表",
|
|
||||||
purePdf: "PDF预览",
|
|
||||||
pureExcel: "导出Excel",
|
|
||||||
pureInfiniteScroll: "表格无限滚动",
|
|
||||||
pureSensitive: "敏感词过滤",
|
|
||||||
purePinyin: "汉语拼音",
|
|
||||||
pureDanmaku: "弹幕",
|
|
||||||
pureSchemaForm: "表单",
|
|
||||||
pureTableBase: "基础用法",
|
|
||||||
pureTableHigh: "高级用法",
|
|
||||||
pureTableEdit: "可编辑用法",
|
|
||||||
pureVxeTable: "虚拟滚动",
|
|
||||||
pureBoard: "艺术画板",
|
|
||||||
pureMindMap: "思维导图",
|
|
||||||
pureMenuOverflow: "目录超出显示 Tooltip 文字提示",
|
|
||||||
pureChildMenuOverflow: "菜单超出显示 Tooltip 文字提示",
|
|
||||||
systemctlTest: "系统测试"
|
|
||||||
};
|
|
|
@ -1,34 +0,0 @@
|
||||||
export const panel = {
|
|
||||||
pureSystemSet: "系统配置",
|
|
||||||
pureCloseSystemSet: "关闭配置",
|
|
||||||
pureClearCacheAndToLogin: "清空缓存并返回登录页",
|
|
||||||
pureClearCache: "清空缓存",
|
|
||||||
pureOverallStyle: "整体风格",
|
|
||||||
pureOverallStyleLight: "浅色",
|
|
||||||
pureOverallStyleLightTip: "清新启航,点亮舒适的工作界面",
|
|
||||||
pureOverallStyleDark: "深色",
|
|
||||||
pureOverallStyleDarkTip: "月光序曲,沉醉于夜的静谧雅致",
|
|
||||||
pureOverallStyleSystem: "自动",
|
|
||||||
pureOverallStyleSystemTip: "同步时光,界面随晨昏自然呼应",
|
|
||||||
pureThemeColor: "主题色",
|
|
||||||
pureLayoutModel: "导航模式",
|
|
||||||
pureVerticalTip: "左侧菜单,亲切熟悉",
|
|
||||||
pureHorizontalTip: "顶部菜单,简洁概览",
|
|
||||||
pureMixTip: "混合菜单,灵活多变",
|
|
||||||
pureStretch: "页宽",
|
|
||||||
pureStretchFixed: "固定",
|
|
||||||
pureStretchFixedTip: "紧凑页面,轻松找到所需信息",
|
|
||||||
pureStretchCustom: "自定义",
|
|
||||||
pureStretchCustomTip: "最小1280、最大1600",
|
|
||||||
pureTagsStyle: "页签风格",
|
|
||||||
pureTagsStyleSmart: "灵动",
|
|
||||||
pureTagsStyleSmartTip: "灵动标签,添趣生辉",
|
|
||||||
pureTagsStyleCard: "卡片",
|
|
||||||
pureTagsStyleCardTip: "卡片标签,高效浏览",
|
|
||||||
pureInterfaceDisplay: "界面显示",
|
|
||||||
pureGreyModel: "灰色模式",
|
|
||||||
pureWeakModel: "色弱模式",
|
|
||||||
pureHiddenTags: "隐藏标签页",
|
|
||||||
pureHiddenFooter: "隐藏页脚",
|
|
||||||
pureMultiTagsCache: "页签持久化"
|
|
||||||
};
|
|
|
@ -1,10 +0,0 @@
|
||||||
export const search = {
|
|
||||||
search: {
|
|
||||||
pureTotal: "共",
|
|
||||||
pureHistory: "搜索历史",
|
|
||||||
pureCollect: "收藏",
|
|
||||||
pureDragSort: "(可拖拽排序)",
|
|
||||||
pureEmpty: "暂无搜索结果",
|
|
||||||
purePlaceholder: "搜索菜单(支持拼音搜索)"
|
|
||||||
}
|
|
||||||
};
|
|
|
@ -1,11 +0,0 @@
|
||||||
export const status = {
|
|
||||||
pureLoad: "加载中...",
|
|
||||||
pureMessage: "消息",
|
|
||||||
pureNotify: "通知",
|
|
||||||
pureTodo: "待办",
|
|
||||||
pureNoMessage: "暂无消息",
|
|
||||||
pureNoNotify: "暂无通知",
|
|
||||||
pureNoTodo: "暂无待办",
|
|
||||||
enable: "启用",
|
|
||||||
disable: "不启用"
|
|
||||||
};
|
|
|
@ -1,5 +0,0 @@
|
||||||
export const style = {
|
|
||||||
larger: "宽松",
|
|
||||||
default: "默认",
|
|
||||||
small: "紧凑"
|
|
||||||
};
|
|
|
@ -1,8 +0,0 @@
|
||||||
export const system = {
|
|
||||||
config: "系统设置",
|
|
||||||
carousel: "轮播图设置",
|
|
||||||
favicon: "图标设置",
|
|
||||||
feedback: "用户反馈",
|
|
||||||
emailUsers: "邮件用户",
|
|
||||||
log: "系统日志"
|
|
||||||
};
|
|
|
@ -1,42 +0,0 @@
|
||||||
// 根据角色动态生成路由
|
|
||||||
import { defineFakeRoute } from "vite-plugin-fake-server/client";
|
|
||||||
|
|
||||||
export default defineFakeRoute([
|
|
||||||
{
|
|
||||||
url: "/mock/login",
|
|
||||||
method: "post",
|
|
||||||
response: ({ body }) => {
|
|
||||||
if (body.username === "admin") {
|
|
||||||
return {
|
|
||||||
success: true,
|
|
||||||
data: {
|
|
||||||
avatar: "https://avatars.githubusercontent.com/u/44761321",
|
|
||||||
username: "admin",
|
|
||||||
nickname: "小铭",
|
|
||||||
// 一个用户可能有多个角色
|
|
||||||
roles: ["admin"],
|
|
||||||
// 按钮级别权限
|
|
||||||
permissions: ["*:*:*"],
|
|
||||||
accessToken: "eyJhbGciOiJIUzUxMiJ9.admin",
|
|
||||||
refreshToken: "eyJhbGciOiJIUzUxMiJ9.adminRefresh",
|
|
||||||
expires: "2030/10/30 00:00:00"
|
|
||||||
}
|
|
||||||
};
|
|
||||||
} else {
|
|
||||||
return {
|
|
||||||
success: true,
|
|
||||||
data: {
|
|
||||||
avatar: "https://avatars.githubusercontent.com/u/52823142",
|
|
||||||
username: "common",
|
|
||||||
nickname: "小林",
|
|
||||||
roles: ["common"],
|
|
||||||
permissions: ["permission:btn:add", "permission:btn:edit"],
|
|
||||||
accessToken: "eyJhbGciOiJIUzUxMiJ9.common",
|
|
||||||
refreshToken: "eyJhbGciOiJIUzUxMiJ9.commonRefresh",
|
|
||||||
expires: "2030/10/30 00:00:00"
|
|
||||||
}
|
|
||||||
};
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
]);
|
|
|
@ -82,7 +82,7 @@ class PureHttp {
|
||||||
return whiteList.some(url => config.url.endsWith(url))
|
return whiteList.some(url => config.url.endsWith(url))
|
||||||
? config
|
? config
|
||||||
: new Promise(resolve => {
|
: new Promise(resolve => {
|
||||||
const data = getToken();
|
const data: any = getToken();
|
||||||
if (data) {
|
if (data) {
|
||||||
const now = new Date().getTime();
|
const now = new Date().getTime();
|
||||||
const expired = parseInt(data.expires) - now <= 0;
|
const expired = parseInt(data.expires) - now <= 0;
|
||||||
|
|
|
@ -154,8 +154,6 @@ class PureHttp {
|
||||||
|
|
||||||
// 关闭进度条动画
|
// 关闭进度条动画
|
||||||
NProgress.done();
|
NProgress.done();
|
||||||
message(error.message, { type: 'error' });
|
|
||||||
|
|
||||||
return error;
|
return error;
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
|
|
|
@ -12,7 +12,7 @@ export const fetchGetI18n = () => {
|
||||||
* 多语言管理---获取多语言列表
|
* 多语言管理---获取多语言列表
|
||||||
*/
|
*/
|
||||||
export const fetchGetI18nList = (data: any) => {
|
export const fetchGetI18nList = (data: any) => {
|
||||||
return http.request<BaseResult<ResultTable>>('get', `i18n/getI18nList/${data.currentPage}/${data.pageSize}`, { data });
|
return http.request<BaseResult<ResultTable>>('get', `i18n/getI18nList/${data.currentPage}/${data.pageSize}`, { params: data });
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -1,114 +1,114 @@
|
||||||
export const animates = [
|
export const animates = [
|
||||||
/* Attention seekers */
|
/* Attention seekers */
|
||||||
"bounce",
|
'bounce',
|
||||||
"flash",
|
'flash',
|
||||||
"pulse",
|
'pulse',
|
||||||
"rubberBand",
|
'rubberBand',
|
||||||
"shakeX",
|
'shakeX',
|
||||||
"headShake",
|
'headShake',
|
||||||
"swing",
|
'swing',
|
||||||
"tada",
|
'tada',
|
||||||
"wobble",
|
'wobble',
|
||||||
"jello",
|
'jello',
|
||||||
"heartBeat",
|
'heartBeat',
|
||||||
/* Back entrances */
|
/* Back entrances */
|
||||||
"backInDown",
|
'backInDown',
|
||||||
"backInLeft",
|
'backInLeft',
|
||||||
"backInRight",
|
'backInRight',
|
||||||
"backInUp",
|
'backInUp',
|
||||||
/* Back exits */
|
/* Back exits */
|
||||||
"backOutDown",
|
'backOutDown',
|
||||||
"backOutLeft",
|
'backOutLeft',
|
||||||
"backOutRight",
|
'backOutRight',
|
||||||
"backOutUp",
|
'backOutUp',
|
||||||
/* Bouncing entrances */
|
/* Bouncing entrances */
|
||||||
"bounceIn",
|
'bounceIn',
|
||||||
"bounceInDown",
|
'bounceInDown',
|
||||||
"bounceInLeft",
|
'bounceInLeft',
|
||||||
"bounceInRight",
|
'bounceInRight',
|
||||||
"bounceInUp",
|
'bounceInUp',
|
||||||
/* Bouncing exits */
|
/* Bouncing exits */
|
||||||
"bounceOut",
|
'bounceOut',
|
||||||
"bounceOutDown",
|
'bounceOutDown',
|
||||||
"bounceOutLeft",
|
'bounceOutLeft',
|
||||||
"bounceOutRight",
|
'bounceOutRight',
|
||||||
"bounceOutUp",
|
'bounceOutUp',
|
||||||
/* Fading entrances */
|
/* Fading entrances */
|
||||||
"fadeIn",
|
'fadeIn',
|
||||||
"fadeInDown",
|
'fadeInDown',
|
||||||
"fadeInDownBig",
|
'fadeInDownBig',
|
||||||
"fadeInLeft",
|
'fadeInLeft',
|
||||||
"fadeInLeftBig",
|
'fadeInLeftBig',
|
||||||
"fadeInRight",
|
'fadeInRight',
|
||||||
"fadeInRightBig",
|
'fadeInRightBig',
|
||||||
"fadeInUp",
|
'fadeInUp',
|
||||||
"fadeInUpBig",
|
'fadeInUpBig',
|
||||||
"fadeInTopLeft",
|
'fadeInTopLeft',
|
||||||
"fadeInTopRight",
|
'fadeInTopRight',
|
||||||
"fadeInBottomLeft",
|
'fadeInBottomLeft',
|
||||||
"fadeInBottomRight",
|
'fadeInBottomRight',
|
||||||
/* Fading exits */
|
/* Fading exits */
|
||||||
"fadeOut",
|
'fadeOut',
|
||||||
"fadeOutDown",
|
'fadeOutDown',
|
||||||
"fadeOutDownBig",
|
'fadeOutDownBig',
|
||||||
"fadeOutLeft",
|
'fadeOutLeft',
|
||||||
"fadeOutLeftBig",
|
'fadeOutLeftBig',
|
||||||
"fadeOutRight",
|
'fadeOutRight',
|
||||||
"fadeOutRightBig",
|
'fadeOutRightBig',
|
||||||
"fadeOutUp",
|
'fadeOutUp',
|
||||||
"fadeOutUpBig",
|
'fadeOutUpBig',
|
||||||
"fadeOutTopLeft",
|
'fadeOutTopLeft',
|
||||||
"fadeOutTopRight",
|
'fadeOutTopRight',
|
||||||
"fadeOutBottomRight",
|
'fadeOutBottomRight',
|
||||||
"fadeOutBottomLeft",
|
'fadeOutBottomLeft',
|
||||||
/* Flippers */
|
/* Flippers */
|
||||||
"flip",
|
'flip',
|
||||||
"flipInX",
|
'flipInX',
|
||||||
"flipInY",
|
'flipInY',
|
||||||
"flipOutX",
|
'flipOutX',
|
||||||
"flipOutY",
|
'flipOutY',
|
||||||
/* Lightspeed */
|
/* Lightspeed */
|
||||||
"lightSpeedInRight",
|
'lightSpeedInRight',
|
||||||
"lightSpeedInLeft",
|
'lightSpeedInLeft',
|
||||||
"lightSpeedOutRight",
|
'lightSpeedOutRight',
|
||||||
"lightSpeedOutLeft",
|
'lightSpeedOutLeft',
|
||||||
/* Rotating entrances */
|
/* Rotating entrances */
|
||||||
"rotateIn",
|
'rotateIn',
|
||||||
"rotateInDownLeft",
|
'rotateInDownLeft',
|
||||||
"rotateInDownRight",
|
'rotateInDownRight',
|
||||||
"rotateInUpLeft",
|
'rotateInUpLeft',
|
||||||
"rotateInUpRight",
|
'rotateInUpRight',
|
||||||
/* Rotating exits */
|
/* Rotating exits */
|
||||||
"rotateOut",
|
'rotateOut',
|
||||||
"rotateOutDownLeft",
|
'rotateOutDownLeft',
|
||||||
"rotateOutDownRight",
|
'rotateOutDownRight',
|
||||||
"rotateOutUpLeft",
|
'rotateOutUpLeft',
|
||||||
"rotateOutUpRight",
|
'rotateOutUpRight',
|
||||||
/* Specials */
|
/* Specials */
|
||||||
"hinge",
|
'hinge',
|
||||||
"jackInTheBox",
|
'jackInTheBox',
|
||||||
"rollIn",
|
'rollIn',
|
||||||
"rollOut",
|
'rollOut',
|
||||||
/* Zooming entrances */
|
/* Zooming entrances */
|
||||||
"zoomIn",
|
'zoomIn',
|
||||||
"zoomInDown",
|
'zoomInDown',
|
||||||
"zoomInLeft",
|
'zoomInLeft',
|
||||||
"zoomInRight",
|
'zoomInRight',
|
||||||
"zoomInUp",
|
'zoomInUp',
|
||||||
/* Zooming exits */
|
/* Zooming exits */
|
||||||
"zoomOut",
|
'zoomOut',
|
||||||
"zoomOutDown",
|
'zoomOutDown',
|
||||||
"zoomOutLeft",
|
'zoomOutLeft',
|
||||||
"zoomOutRight",
|
'zoomOutRight',
|
||||||
"zoomOutUp",
|
'zoomOutUp',
|
||||||
/* Sliding entrances */
|
/* Sliding entrances */
|
||||||
"slideInDown",
|
'slideInDown',
|
||||||
"slideInLeft",
|
'slideInLeft',
|
||||||
"slideInRight",
|
'slideInRight',
|
||||||
"slideInUp",
|
'slideInUp',
|
||||||
/* Sliding exits */
|
/* Sliding exits */
|
||||||
"slideOutDown",
|
'slideOutDown',
|
||||||
"slideOutLeft",
|
'slideOutLeft',
|
||||||
"slideOutRight",
|
'slideOutRight',
|
||||||
"slideOutUp"
|
'slideOutUp',
|
||||||
];
|
];
|
||||||
|
|
|
@ -1,17 +1,18 @@
|
||||||
<script setup lang="ts">
|
<script lang="ts" setup>
|
||||||
import { ref, computed } from "vue";
|
import { computed, ref } from 'vue';
|
||||||
import { animates } from "./animate";
|
import { animates } from './animate';
|
||||||
import { cloneDeep } from "@pureadmin/utils";
|
import { cloneDeep } from '@pureadmin/utils';
|
||||||
|
import { $t } from '@/plugins/i18n';
|
||||||
|
|
||||||
defineOptions({
|
defineOptions({
|
||||||
name: "ReAnimateSelector"
|
name: 'ReAnimateSelector',
|
||||||
});
|
});
|
||||||
|
|
||||||
defineProps({
|
defineProps({
|
||||||
placeholder: {
|
placeholder: {
|
||||||
type: String,
|
type: String,
|
||||||
default: "请选择动画"
|
default: $t('please_select_animation'),
|
||||||
}
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
const inputValue = defineModel({ type: String });
|
const inputValue = defineModel({ type: String });
|
||||||
|
@ -21,116 +22,78 @@ const animatesList = ref(animates);
|
||||||
const copyAnimatesList = cloneDeep(animatesList);
|
const copyAnimatesList = cloneDeep(animatesList);
|
||||||
|
|
||||||
const animateClass = computed(() => {
|
const animateClass = computed(() => {
|
||||||
return [
|
return ['mt-1', 'flex', 'border', 'w-[130px]', 'h-[100px]', 'items-center', 'cursor-pointer', 'transition-all', 'justify-center', 'border-[#e5e7eb]', 'hover:text-primary', 'hover:duration-[700ms]'];
|
||||||
"mt-1",
|
|
||||||
"flex",
|
|
||||||
"border",
|
|
||||||
"w-[130px]",
|
|
||||||
"h-[100px]",
|
|
||||||
"items-center",
|
|
||||||
"cursor-pointer",
|
|
||||||
"transition-all",
|
|
||||||
"justify-center",
|
|
||||||
"border-[#e5e7eb]",
|
|
||||||
"hover:text-primary",
|
|
||||||
"hover:duration-[700ms]"
|
|
||||||
];
|
|
||||||
});
|
});
|
||||||
|
|
||||||
const animateStyle = computed(
|
const animateStyle = computed(
|
||||||
() => (i: string) =>
|
() => (i: string) =>
|
||||||
inputValue.value === i
|
inputValue.value === i
|
||||||
? {
|
? {
|
||||||
borderColor: "var(--el-color-primary)",
|
borderColor: 'var(--el-color-primary)',
|
||||||
color: "var(--el-color-primary)"
|
color: 'var(--el-color-primary)',
|
||||||
}
|
}
|
||||||
: ""
|
: '',
|
||||||
);
|
);
|
||||||
|
|
||||||
function onChangeIcon(animate: string) {
|
function onChangeIcon(animate: string) {
|
||||||
inputValue.value = animate;
|
inputValue.value = animate;
|
||||||
}
|
}
|
||||||
|
|
||||||
function onClear() {
|
function onClear() {
|
||||||
inputValue.value = "";
|
inputValue.value = '';
|
||||||
}
|
}
|
||||||
|
|
||||||
function filterMethod(value: any) {
|
function filterMethod(value: any) {
|
||||||
searchVal.value = value;
|
searchVal.value = value;
|
||||||
animatesList.value = copyAnimatesList.value.filter((i: string | any[]) =>
|
animatesList.value = copyAnimatesList.value.filter((i: string | any[]) => i.includes(value));
|
||||||
i.includes(value)
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const animateMap = ref({});
|
const animateMap = ref({});
|
||||||
|
|
||||||
function onMouseEnter(index: string | number) {
|
function onMouseEnter(index: string | number) {
|
||||||
animateMap.value[index] = animateMap.value[index]?.loading
|
animateMap.value[index] = animateMap.value[index]?.loading
|
||||||
? Object.assign({}, animateMap.value[index], {
|
? Object.assign({}, animateMap.value[index], {
|
||||||
loading: false
|
loading: false,
|
||||||
})
|
})
|
||||||
: Object.assign({}, animateMap.value[index], {
|
: Object.assign({}, animateMap.value[index], {
|
||||||
loading: true
|
loading: true,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
function onMouseleave() {
|
function onMouseleave() {
|
||||||
animateMap.value = {};
|
animateMap.value = {};
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<el-select
|
<el-select :filter-method="filterMethod" :model-value="inputValue" :placeholder="placeholder" clearable filterable popper-class="pure-animate-popper" @clear="onClear">
|
||||||
clearable
|
<template #empty>
|
||||||
filterable
|
<div class="w-[280px]">
|
||||||
:placeholder="placeholder"
|
<el-scrollbar :view-style="{ overflow: 'hidden' }" class="border-t border-[#e5e7eb]" height="212px" noresize>
|
||||||
popper-class="pure-animate-popper"
|
<ul class="flex flex-wrap justify-around mb-1">
|
||||||
:model-value="inputValue"
|
<li
|
||||||
:filter-method="filterMethod"
|
v-for="(animate, index) in animatesList"
|
||||||
@clear="onClear"
|
:key="index"
|
||||||
>
|
:class="animateClass"
|
||||||
<template #empty>
|
:style="animateStyle(animate)"
|
||||||
<div class="w-[280px]">
|
@click="onChangeIcon(animate)"
|
||||||
<el-scrollbar
|
@mouseenter.prevent="onMouseEnter(index)"
|
||||||
noresize
|
@mouseleave.prevent="onMouseleave"
|
||||||
height="212px"
|
>
|
||||||
:view-style="{ overflow: 'hidden' }"
|
<h4 :class="[`animate__animated animate__${animateMap[index]?.loading ? animate + ' animate__infinite' : ''} `]">
|
||||||
class="border-t border-[#e5e7eb]"
|
{{ animate }}
|
||||||
>
|
</h4>
|
||||||
<ul class="flex flex-wrap justify-around mb-1">
|
</li>
|
||||||
<li
|
</ul>
|
||||||
v-for="(animate, index) in animatesList"
|
<el-empty v-show="animatesList.length === 0" :description="`${searchVal} ${$t('animation_not_exist')}`" :image-size="60" />
|
||||||
:key="index"
|
</el-scrollbar>
|
||||||
:class="animateClass"
|
</div>
|
||||||
:style="animateStyle(animate)"
|
</template>
|
||||||
@mouseenter.prevent="onMouseEnter(index)"
|
</el-select>
|
||||||
@mouseleave.prevent="onMouseleave"
|
|
||||||
@click="onChangeIcon(animate)"
|
|
||||||
>
|
|
||||||
<h4
|
|
||||||
:class="[
|
|
||||||
`animate__animated animate__${
|
|
||||||
animateMap[index]?.loading
|
|
||||||
? animate + ' animate__infinite'
|
|
||||||
: ''
|
|
||||||
} `
|
|
||||||
]"
|
|
||||||
>
|
|
||||||
{{ animate }}
|
|
||||||
</h4>
|
|
||||||
</li>
|
|
||||||
</ul>
|
|
||||||
<el-empty
|
|
||||||
v-show="animatesList.length === 0"
|
|
||||||
:description="`${searchVal} 动画不存在`"
|
|
||||||
:image-size="60"
|
|
||||||
/>
|
|
||||||
</el-scrollbar>
|
|
||||||
</div>
|
|
||||||
</template>
|
|
||||||
</el-select>
|
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<style>
|
<style>
|
||||||
.pure-animate-popper {
|
.pure-animate-popper {
|
||||||
min-width: 0 !important;
|
min-width: 0 !important;
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|
|
@ -1,20 +1,18 @@
|
||||||
import { defineComponent, Fragment } from "vue";
|
import { defineComponent, Fragment } from 'vue';
|
||||||
import { hasAuth } from "@/router/utils";
|
import { hasAuth } from '@/router/utils';
|
||||||
|
|
||||||
export default defineComponent({
|
export default defineComponent({
|
||||||
name: "Auth",
|
name: 'Auth',
|
||||||
props: {
|
props: {
|
||||||
value: {
|
value: {
|
||||||
type: undefined,
|
type: undefined,
|
||||||
default: []
|
default: [],
|
||||||
}
|
},
|
||||||
},
|
},
|
||||||
setup(props, { slots }) {
|
setup(props, { slots }) {
|
||||||
return () => {
|
return () => {
|
||||||
if (!slots) return null;
|
if (!slots) return null;
|
||||||
return hasAuth(props.value) ? (
|
return hasAuth(props.value) ? <Fragment>{slots.default?.()}</Fragment> : null;
|
||||||
<Fragment>{slots.default?.()}</Fragment>
|
};
|
||||||
) : null;
|
},
|
||||||
};
|
|
||||||
}
|
|
||||||
});
|
});
|
||||||
|
|
|
@ -1,39 +1,32 @@
|
||||||
import { ref } from "vue";
|
import { ref } from 'vue';
|
||||||
import reDialog from "./index.vue";
|
import reDialog from './index.vue';
|
||||||
import { useTimeoutFn } from "@vueuse/core";
|
import { useTimeoutFn } from '@vueuse/core';
|
||||||
import { withInstall } from "@pureadmin/utils";
|
import { withInstall } from '@pureadmin/utils';
|
||||||
import type {
|
import type { ArgsType, ButtonProps, DialogOptions, DialogProps, EventType } from './type';
|
||||||
EventType,
|
|
||||||
ArgsType,
|
|
||||||
DialogProps,
|
|
||||||
ButtonProps,
|
|
||||||
DialogOptions
|
|
||||||
} from "./type";
|
|
||||||
|
|
||||||
const dialogStore = ref<Array<DialogOptions>>([]);
|
const dialogStore = ref<Array<DialogOptions>>([]);
|
||||||
|
|
||||||
/** 打开弹框 */
|
/** 打开弹框 */
|
||||||
const addDialog = (options: DialogOptions) => {
|
const addDialog = (options: DialogOptions) => {
|
||||||
const open = () =>
|
const open = () => dialogStore.value.push(Object.assign(options, { visible: true }));
|
||||||
dialogStore.value.push(Object.assign(options, { visible: true }));
|
if (options?.openDelay) {
|
||||||
if (options?.openDelay) {
|
useTimeoutFn(() => {
|
||||||
useTimeoutFn(() => {
|
open();
|
||||||
open();
|
}, options.openDelay);
|
||||||
}, options.openDelay);
|
} else {
|
||||||
} else {
|
open();
|
||||||
open();
|
}
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
/** 关闭弹框 */
|
/** 关闭弹框 */
|
||||||
const closeDialog = (options: DialogOptions, index: number, args?: any) => {
|
const closeDialog = (options: DialogOptions, index: number, args?: any) => {
|
||||||
dialogStore.value[index].visible = false;
|
dialogStore.value[index].visible = false;
|
||||||
options.closeCallBack && options.closeCallBack({ options, index, args });
|
options.closeCallBack && options.closeCallBack({ options, index, args });
|
||||||
|
|
||||||
const closeDelay = options?.closeDelay ?? 200;
|
const closeDelay = options?.closeDelay ?? 200;
|
||||||
useTimeoutFn(() => {
|
useTimeoutFn(() => {
|
||||||
dialogStore.value.splice(index, 1);
|
dialogStore.value.splice(index, 1);
|
||||||
}, closeDelay);
|
}, closeDelay);
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -42,13 +35,13 @@ const closeDialog = (options: DialogOptions, index: number, args?: any) => {
|
||||||
* @param key 属性,默认`title`
|
* @param key 属性,默认`title`
|
||||||
* @param index 弹框索引(默认`0`,代表只有一个弹框,对于嵌套弹框要改哪个弹框的属性值就把该弹框索引赋给`index`)
|
* @param index 弹框索引(默认`0`,代表只有一个弹框,对于嵌套弹框要改哪个弹框的属性值就把该弹框索引赋给`index`)
|
||||||
*/
|
*/
|
||||||
const updateDialog = (value: any, key = "title", index = 0) => {
|
const updateDialog = (value: any, key = 'title', index = 0) => {
|
||||||
dialogStore.value[index][key] = value;
|
dialogStore.value[index][key] = value;
|
||||||
};
|
};
|
||||||
|
|
||||||
/** 关闭所有弹框 */
|
/** 关闭所有弹框 */
|
||||||
const closeAllDialog = () => {
|
const closeAllDialog = () => {
|
||||||
dialogStore.value = [];
|
dialogStore.value = [];
|
||||||
};
|
};
|
||||||
|
|
||||||
/** 千万别忘了在下面这三处引入并注册下,放心注册,不使用`addDialog`调用就不会被挂载
|
/** 千万别忘了在下面这三处引入并注册下,放心注册,不使用`addDialog`调用就不会被挂载
|
||||||
|
@ -59,11 +52,4 @@ const closeAllDialog = () => {
|
||||||
const ReDialog = withInstall(reDialog);
|
const ReDialog = withInstall(reDialog);
|
||||||
|
|
||||||
export type { EventType, ArgsType, DialogProps, ButtonProps, DialogOptions };
|
export type { EventType, ArgsType, DialogProps, ButtonProps, DialogOptions };
|
||||||
export {
|
export { ReDialog, dialogStore, addDialog, closeDialog, updateDialog, closeAllDialog };
|
||||||
ReDialog,
|
|
||||||
dialogStore,
|
|
||||||
addDialog,
|
|
||||||
closeDialog,
|
|
||||||
updateDialog,
|
|
||||||
closeAllDialog
|
|
||||||
};
|
|
||||||
|
|
|
@ -1,206 +1,154 @@
|
||||||
<script setup lang="ts">
|
<script lang="ts" setup>
|
||||||
import {
|
import { type ButtonProps, closeDialog, type DialogOptions, dialogStore, type EventType } from './index';
|
||||||
type EventType,
|
import { computed, ref } from 'vue';
|
||||||
type ButtonProps,
|
import { isFunction } from '@pureadmin/utils';
|
||||||
type DialogOptions,
|
import Fullscreen from '@iconify-icons/ri/fullscreen-fill';
|
||||||
closeDialog,
|
import ExitFullscreen from '@iconify-icons/ri/fullscreen-exit-fill';
|
||||||
dialogStore
|
import { $t } from '@/plugins/i18n';
|
||||||
} from "./index";
|
|
||||||
import { ref, computed } from "vue";
|
|
||||||
import { isFunction } from "@pureadmin/utils";
|
|
||||||
import Fullscreen from "@iconify-icons/ri/fullscreen-fill";
|
|
||||||
import ExitFullscreen from "@iconify-icons/ri/fullscreen-exit-fill";
|
|
||||||
|
|
||||||
defineOptions({
|
defineOptions({
|
||||||
name: "ReDialog"
|
name: 'ReDialog',
|
||||||
});
|
});
|
||||||
|
|
||||||
const sureBtnMap = ref({});
|
const sureBtnMap = ref({});
|
||||||
const fullscreen = ref(false);
|
const fullscreen = ref(false);
|
||||||
|
|
||||||
const footerButtons = computed(() => {
|
const footerButtons = computed(() => {
|
||||||
return (options: DialogOptions) => {
|
return (options: DialogOptions) => {
|
||||||
return options?.footerButtons?.length > 0
|
return options?.footerButtons?.length > 0
|
||||||
? options.footerButtons
|
? options.footerButtons
|
||||||
: ([
|
: ([
|
||||||
{
|
{
|
||||||
label: "取消",
|
label: $t('cancel'),
|
||||||
text: true,
|
text: true,
|
||||||
bg: true,
|
bg: true,
|
||||||
btnClick: ({ dialog: { options, index } }) => {
|
btnClick: ({ dialog: { options, index } }) => {
|
||||||
const done = () =>
|
const done = () => closeDialog(options, index, { command: 'cancel' });
|
||||||
closeDialog(options, index, { command: "cancel" });
|
if (options?.beforeCancel && isFunction(options?.beforeCancel)) {
|
||||||
if (options?.beforeCancel && isFunction(options?.beforeCancel)) {
|
options.beforeCancel(done, { options, index });
|
||||||
options.beforeCancel(done, { options, index });
|
} else {
|
||||||
} else {
|
done();
|
||||||
done();
|
}
|
||||||
}
|
},
|
||||||
}
|
},
|
||||||
},
|
{
|
||||||
{
|
label: $t('confirm'),
|
||||||
label: "确定",
|
type: 'primary',
|
||||||
type: "primary",
|
text: true,
|
||||||
text: true,
|
bg: true,
|
||||||
bg: true,
|
popconfirm: options?.popconfirm,
|
||||||
popconfirm: options?.popconfirm,
|
btnClick: ({ dialog: { options, index } }) => {
|
||||||
btnClick: ({ dialog: { options, index } }) => {
|
if (options?.sureBtnLoading) {
|
||||||
if (options?.sureBtnLoading) {
|
sureBtnMap.value[index] = Object.assign({}, sureBtnMap.value[index], {
|
||||||
sureBtnMap.value[index] = Object.assign(
|
loading: true,
|
||||||
{},
|
});
|
||||||
sureBtnMap.value[index],
|
}
|
||||||
{
|
const closeLoading = () => {
|
||||||
loading: true
|
if (options?.sureBtnLoading) {
|
||||||
}
|
sureBtnMap.value[index].loading = false;
|
||||||
);
|
}
|
||||||
}
|
};
|
||||||
const closeLoading = () => {
|
const done = () => {
|
||||||
if (options?.sureBtnLoading) {
|
closeLoading();
|
||||||
sureBtnMap.value[index].loading = false;
|
closeDialog(options, index, { command: 'sure' });
|
||||||
}
|
};
|
||||||
};
|
if (options?.beforeSure && isFunction(options?.beforeSure)) {
|
||||||
const done = () => {
|
options.beforeSure(done, { options, index, closeLoading });
|
||||||
closeLoading();
|
} else {
|
||||||
closeDialog(options, index, { command: "sure" });
|
done();
|
||||||
};
|
}
|
||||||
if (options?.beforeSure && isFunction(options?.beforeSure)) {
|
},
|
||||||
options.beforeSure(done, { options, index, closeLoading });
|
},
|
||||||
} else {
|
] as Array<ButtonProps>);
|
||||||
done();
|
};
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
] as Array<ButtonProps>);
|
|
||||||
};
|
|
||||||
});
|
});
|
||||||
|
|
||||||
const fullscreenClass = computed(() => {
|
const fullscreenClass = computed(() => {
|
||||||
return [
|
return ['el-icon', 'el-dialog__close', '-translate-x-2', 'cursor-pointer', 'hover:!text-[red]'];
|
||||||
"el-icon",
|
|
||||||
"el-dialog__close",
|
|
||||||
"-translate-x-2",
|
|
||||||
"cursor-pointer",
|
|
||||||
"hover:!text-[red]"
|
|
||||||
];
|
|
||||||
});
|
});
|
||||||
|
|
||||||
function eventsCallBack(
|
function eventsCallBack(event: EventType, options: DialogOptions, index: number, isClickFullScreen = false) {
|
||||||
event: EventType,
|
if (!isClickFullScreen) fullscreen.value = options?.fullscreen ?? false;
|
||||||
options: DialogOptions,
|
if (options?.[event] && isFunction(options?.[event])) {
|
||||||
index: number,
|
return options?.[event]({ options, index });
|
||||||
isClickFullScreen = false
|
}
|
||||||
) {
|
|
||||||
if (!isClickFullScreen) fullscreen.value = options?.fullscreen ?? false;
|
|
||||||
if (options?.[event] && isFunction(options?.[event])) {
|
|
||||||
return options?.[event]({ options, index });
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function handleClose(
|
function handleClose(options: DialogOptions, index: number, args = { command: 'close' }) {
|
||||||
options: DialogOptions,
|
closeDialog(options, index, args);
|
||||||
index: number,
|
eventsCallBack('close', options, index);
|
||||||
args = { command: "close" }
|
|
||||||
) {
|
|
||||||
closeDialog(options, index, args);
|
|
||||||
eventsCallBack("close", options, index);
|
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<el-dialog
|
<el-dialog
|
||||||
v-for="(options, index) in dialogStore"
|
v-for="(options, index) in dialogStore"
|
||||||
:key="index"
|
:key="index"
|
||||||
v-bind="options"
|
v-model="options.visible"
|
||||||
v-model="options.visible"
|
:fullscreen="fullscreen ? true : options?.fullscreen ? true : false"
|
||||||
class="pure-dialog"
|
class="pure-dialog"
|
||||||
:fullscreen="fullscreen ? true : options?.fullscreen ? true : false"
|
v-bind="options"
|
||||||
@closed="handleClose(options, index)"
|
@closeAutoFocus="eventsCallBack('closeAutoFocus', options, index)"
|
||||||
@opened="eventsCallBack('open', options, index)"
|
@closed="handleClose(options, index)"
|
||||||
@openAutoFocus="eventsCallBack('openAutoFocus', options, index)"
|
@openAutoFocus="eventsCallBack('openAutoFocus', options, index)"
|
||||||
@closeAutoFocus="eventsCallBack('closeAutoFocus', options, index)"
|
@opened="eventsCallBack('open', options, index)"
|
||||||
>
|
>
|
||||||
<!-- header -->
|
<!-- header -->
|
||||||
<template
|
<template v-if="options?.fullscreenIcon || options?.headerRenderer" #header="{ close, titleId, titleClass }">
|
||||||
v-if="options?.fullscreenIcon || options?.headerRenderer"
|
<div v-if="options?.fullscreenIcon" class="flex items-center justify-between">
|
||||||
#header="{ close, titleId, titleClass }"
|
<span :id="titleId" :class="titleClass">{{ options?.title }}</span>
|
||||||
>
|
<i
|
||||||
<div
|
v-if="!options?.fullscreen"
|
||||||
v-if="options?.fullscreenIcon"
|
:class="fullscreenClass"
|
||||||
class="flex items-center justify-between"
|
@click="
|
||||||
>
|
() => {
|
||||||
<span :id="titleId" :class="titleClass">{{ options?.title }}</span>
|
fullscreen = !fullscreen;
|
||||||
<i
|
eventsCallBack('fullscreenCallBack', { ...options, fullscreen }, index, true);
|
||||||
v-if="!options?.fullscreen"
|
}
|
||||||
:class="fullscreenClass"
|
"
|
||||||
@click="
|
>
|
||||||
() => {
|
<IconifyIconOffline :icon="options?.fullscreen ? ExitFullscreen : fullscreen ? ExitFullscreen : Fullscreen" class="pure-dialog-svg" />
|
||||||
fullscreen = !fullscreen;
|
</i>
|
||||||
eventsCallBack(
|
</div>
|
||||||
'fullscreenCallBack',
|
<component :is="options?.headerRenderer({ close, titleId, titleClass })" v-else />
|
||||||
{ ...options, fullscreen },
|
</template>
|
||||||
index,
|
<component :is="options.contentRenderer({ options, index })" v-bind="options?.props" @close="args => handleClose(options, index, args)" />
|
||||||
true
|
<!-- footer -->
|
||||||
);
|
<template v-if="!options?.hideFooter" #footer>
|
||||||
}
|
<template v-if="options?.footerRenderer">
|
||||||
"
|
<component :is="options?.footerRenderer({ options, index })" />
|
||||||
>
|
</template>
|
||||||
<IconifyIconOffline
|
<span v-else>
|
||||||
class="pure-dialog-svg"
|
<template v-for="(btn, key) in footerButtons(options)" :key="key">
|
||||||
:icon="
|
<el-popconfirm
|
||||||
options?.fullscreen
|
v-if="btn.popconfirm"
|
||||||
? ExitFullscreen
|
v-bind="btn.popconfirm"
|
||||||
: fullscreen
|
@confirm="
|
||||||
? ExitFullscreen
|
btn.btnClick({
|
||||||
: Fullscreen
|
dialog: { options, index },
|
||||||
"
|
button: { btn, index: key },
|
||||||
/>
|
})
|
||||||
</i>
|
"
|
||||||
</div>
|
>
|
||||||
<component
|
<template #reference>
|
||||||
:is="options?.headerRenderer({ close, titleId, titleClass })"
|
<el-button v-bind="btn">{{ btn?.label }}</el-button>
|
||||||
v-else
|
</template>
|
||||||
/>
|
</el-popconfirm>
|
||||||
</template>
|
<el-button
|
||||||
<component
|
v-else
|
||||||
v-bind="options?.props"
|
:loading="key === 1 && sureBtnMap[index]?.loading"
|
||||||
:is="options.contentRenderer({ options, index })"
|
v-bind="btn"
|
||||||
@close="args => handleClose(options, index, args)"
|
@click="
|
||||||
/>
|
btn.btnClick({
|
||||||
<!-- footer -->
|
dialog: { options, index },
|
||||||
<template v-if="!options?.hideFooter" #footer>
|
button: { btn, index: key },
|
||||||
<template v-if="options?.footerRenderer">
|
})
|
||||||
<component :is="options?.footerRenderer({ options, index })" />
|
"
|
||||||
</template>
|
>
|
||||||
<span v-else>
|
{{ btn?.label }}
|
||||||
<template v-for="(btn, key) in footerButtons(options)" :key="key">
|
</el-button>
|
||||||
<el-popconfirm
|
</template>
|
||||||
v-if="btn.popconfirm"
|
</span>
|
||||||
v-bind="btn.popconfirm"
|
</template>
|
||||||
@confirm="
|
</el-dialog>
|
||||||
btn.btnClick({
|
|
||||||
dialog: { options, index },
|
|
||||||
button: { btn, index: key }
|
|
||||||
})
|
|
||||||
"
|
|
||||||
>
|
|
||||||
<template #reference>
|
|
||||||
<el-button v-bind="btn">{{ btn?.label }}</el-button>
|
|
||||||
</template>
|
|
||||||
</el-popconfirm>
|
|
||||||
<el-button
|
|
||||||
v-else
|
|
||||||
v-bind="btn"
|
|
||||||
:loading="key === 1 && sureBtnMap[index]?.loading"
|
|
||||||
@click="
|
|
||||||
btn.btnClick({
|
|
||||||
dialog: { options, index },
|
|
||||||
button: { btn, index: key }
|
|
||||||
})
|
|
||||||
"
|
|
||||||
>
|
|
||||||
{{ btn?.label }}
|
|
||||||
</el-button>
|
|
||||||
</template>
|
|
||||||
</span>
|
|
||||||
</template>
|
|
||||||
</el-dialog>
|
|
||||||
</template>
|
</template>
|
||||||
|
|
|
@ -1,275 +1,206 @@
|
||||||
import type { CSSProperties, VNode, Component } from "vue";
|
import type { Component, CSSProperties, VNode } from 'vue';
|
||||||
|
|
||||||
type DoneFn = (cancel?: boolean) => void;
|
type DoneFn = (cancel?: boolean) => void;
|
||||||
type EventType =
|
type EventType = 'open' | 'close' | 'openAutoFocus' | 'closeAutoFocus' | 'fullscreenCallBack';
|
||||||
| "open"
|
|
||||||
| "close"
|
|
||||||
| "openAutoFocus"
|
|
||||||
| "closeAutoFocus"
|
|
||||||
| "fullscreenCallBack";
|
|
||||||
type ArgsType = {
|
type ArgsType = {
|
||||||
/** `cancel` 点击取消按钮、`sure` 点击确定按钮、`close` 点击右上角关闭按钮或空白页或按下了esc键 */
|
/** `cancel` 点击取消按钮、`sure` 点击确定按钮、`close` 点击右上角关闭按钮或空白页或按下了esc键 */
|
||||||
command: "cancel" | "sure" | "close";
|
command: 'cancel' | 'sure' | 'close';
|
||||||
};
|
};
|
||||||
type ButtonType =
|
type ButtonType = 'primary' | 'success' | 'warning' | 'danger' | 'info' | 'text';
|
||||||
| "primary"
|
|
||||||
| "success"
|
|
||||||
| "warning"
|
|
||||||
| "danger"
|
|
||||||
| "info"
|
|
||||||
| "text";
|
|
||||||
|
|
||||||
/** https://element-plus.org/zh-CN/component/dialog.html#attributes */
|
/** https://element-plus.org/zh-CN/component/dialog.html#attributes */
|
||||||
type DialogProps = {
|
type DialogProps = {
|
||||||
/** `Dialog` 的显示与隐藏 */
|
/** `Dialog` 的显示与隐藏 */
|
||||||
visible?: boolean;
|
visible?: boolean;
|
||||||
/** `Dialog` 的标题 */
|
/** `Dialog` 的标题 */
|
||||||
title?: string;
|
title?: string;
|
||||||
/** `Dialog` 的宽度,默认 `50%` */
|
/** `Dialog` 的宽度,默认 `50%` */
|
||||||
width?: string | number;
|
width?: string | number;
|
||||||
/** 是否为全屏 `Dialog`(会一直处于全屏状态,除非弹框关闭),默认 `false`,`fullscreen` 和 `fullscreenIcon` 都传时只有 `fullscreen` 会生效 */
|
/** 是否为全屏 `Dialog`(会一直处于全屏状态,除非弹框关闭),默认 `false`,`fullscreen` 和 `fullscreenIcon` 都传时只有 `fullscreen` 会生效 */
|
||||||
fullscreen?: boolean;
|
fullscreen?: boolean;
|
||||||
/** 是否显示全屏操作图标,默认 `false`,`fullscreen` 和 `fullscreenIcon` 都传时只有 `fullscreen` 会生效 */
|
/** 是否显示全屏操作图标,默认 `false`,`fullscreen` 和 `fullscreenIcon` 都传时只有 `fullscreen` 会生效 */
|
||||||
fullscreenIcon?: boolean;
|
fullscreenIcon?: boolean;
|
||||||
/** `Dialog CSS` 中的 `margin-top` 值,默认 `15vh` */
|
/** `Dialog CSS` 中的 `margin-top` 值,默认 `15vh` */
|
||||||
top?: string;
|
top?: string;
|
||||||
/** 是否需要遮罩层,默认 `true` */
|
/** 是否需要遮罩层,默认 `true` */
|
||||||
modal?: boolean;
|
modal?: boolean;
|
||||||
/** `Dialog` 自身是否插入至 `body` 元素上。嵌套的 `Dialog` 必须指定该属性并赋值为 `true`,默认 `false` */
|
/** `Dialog` 自身是否插入至 `body` 元素上。嵌套的 `Dialog` 必须指定该属性并赋值为 `true`,默认 `false` */
|
||||||
appendToBody?: boolean;
|
appendToBody?: boolean;
|
||||||
/** 是否在 `Dialog` 出现时将 `body` 滚动锁定,默认 `true` */
|
/** 是否在 `Dialog` 出现时将 `body` 滚动锁定,默认 `true` */
|
||||||
lockScroll?: boolean;
|
lockScroll?: boolean;
|
||||||
/** `Dialog` 的自定义类名 */
|
/** `Dialog` 的自定义类名 */
|
||||||
class?: string;
|
class?: string;
|
||||||
/** `Dialog` 的自定义样式 */
|
/** `Dialog` 的自定义样式 */
|
||||||
style?: CSSProperties;
|
style?: CSSProperties;
|
||||||
/** `Dialog` 打开的延时时间,单位毫秒,默认 `0` */
|
/** `Dialog` 打开的延时时间,单位毫秒,默认 `0` */
|
||||||
openDelay?: number;
|
openDelay?: number;
|
||||||
/** `Dialog` 关闭的延时时间,单位毫秒,默认 `0` */
|
/** `Dialog` 关闭的延时时间,单位毫秒,默认 `0` */
|
||||||
closeDelay?: number;
|
closeDelay?: number;
|
||||||
/** 是否可以通过点击 `modal` 关闭 `Dialog`,默认 `true` */
|
/** 是否可以通过点击 `modal` 关闭 `Dialog`,默认 `true` */
|
||||||
closeOnClickModal?: boolean;
|
closeOnClickModal?: boolean;
|
||||||
/** 是否可以通过按下 `ESC` 关闭 `Dialog`,默认 `true` */
|
/** 是否可以通过按下 `ESC` 关闭 `Dialog`,默认 `true` */
|
||||||
closeOnPressEscape?: boolean;
|
closeOnPressEscape?: boolean;
|
||||||
/** 是否显示关闭按钮,默认 `true` */
|
/** 是否显示关闭按钮,默认 `true` */
|
||||||
showClose?: boolean;
|
showClose?: boolean;
|
||||||
/** 关闭前的回调,会暂停 `Dialog` 的关闭. 回调函数内执行 `done` 参数方法的时候才是真正关闭对话框的时候 */
|
/** 关闭前的回调,会暂停 `Dialog` 的关闭. 回调函数内执行 `done` 参数方法的时候才是真正关闭对话框的时候 */
|
||||||
beforeClose?: (done: DoneFn) => void;
|
beforeClose?: (done: DoneFn) => void;
|
||||||
/** 为 `Dialog` 启用可拖拽功能,默认 `false` */
|
/** 为 `Dialog` 启用可拖拽功能,默认 `false` */
|
||||||
draggable?: boolean;
|
draggable?: boolean;
|
||||||
/** 是否让 `Dialog` 的 `header` 和 `footer` 部分居中排列,默认 `false` */
|
/** 是否让 `Dialog` 的 `header` 和 `footer` 部分居中排列,默认 `false` */
|
||||||
center?: boolean;
|
center?: boolean;
|
||||||
/** 是否水平垂直对齐对话框,默认 `false` */
|
/** 是否水平垂直对齐对话框,默认 `false` */
|
||||||
alignCenter?: boolean;
|
alignCenter?: boolean;
|
||||||
/** 当关闭 `Dialog` 时,销毁其中的元素,默认 `false` */
|
/** 当关闭 `Dialog` 时,销毁其中的元素,默认 `false` */
|
||||||
destroyOnClose?: boolean;
|
destroyOnClose?: boolean;
|
||||||
};
|
};
|
||||||
|
|
||||||
//element-plus.org/zh-CN/component/popconfirm.html#attributes
|
//element-plus.org/zh-CN/component/popconfirm.html#attributes
|
||||||
type Popconfirm = {
|
type Popconfirm = {
|
||||||
/** 标题 */
|
/** 标题 */
|
||||||
title?: string;
|
title?: string;
|
||||||
/** 确定按钮文字 */
|
/** 确定按钮文字 */
|
||||||
confirmButtonText?: string;
|
confirmButtonText?: string;
|
||||||
/** 取消按钮文字 */
|
/** 取消按钮文字 */
|
||||||
cancelButtonText?: string;
|
cancelButtonText?: string;
|
||||||
/** 确定按钮类型,默认 `primary` */
|
/** 确定按钮类型,默认 `primary` */
|
||||||
confirmButtonType?: ButtonType;
|
confirmButtonType?: ButtonType;
|
||||||
/** 取消按钮类型,默认 `text` */
|
/** 取消按钮类型,默认 `text` */
|
||||||
cancelButtonType?: ButtonType;
|
cancelButtonType?: ButtonType;
|
||||||
/** 自定义图标,默认 `QuestionFilled` */
|
/** 自定义图标,默认 `QuestionFilled` */
|
||||||
icon?: string | Component;
|
icon?: string | Component;
|
||||||
/** `Icon` 颜色,默认 `#f90` */
|
/** `Icon` 颜色,默认 `#f90` */
|
||||||
iconColor?: string;
|
iconColor?: string;
|
||||||
/** 是否隐藏 `Icon`,默认 `false` */
|
/** 是否隐藏 `Icon`,默认 `false` */
|
||||||
hideIcon?: boolean;
|
hideIcon?: boolean;
|
||||||
/** 关闭时的延迟,默认 `200` */
|
/** 关闭时的延迟,默认 `200` */
|
||||||
hideAfter?: number;
|
hideAfter?: number;
|
||||||
/** 是否将 `popover` 的下拉列表插入至 `body` 元素,默认 `true` */
|
/** 是否将 `popover` 的下拉列表插入至 `body` 元素,默认 `true` */
|
||||||
teleported?: boolean;
|
teleported?: boolean;
|
||||||
/** 当 `popover` 组件长时间不触发且 `persistent` 属性设置为 `false` 时, `popover` 将会被删除,默认 `false` */
|
/** 当 `popover` 组件长时间不触发且 `persistent` 属性设置为 `false` 时, `popover` 将会被删除,默认 `false` */
|
||||||
persistent?: boolean;
|
persistent?: boolean;
|
||||||
/** 弹层宽度,最小宽度 `150px`,默认 `150` */
|
/** 弹层宽度,最小宽度 `150px`,默认 `150` */
|
||||||
width?: string | number;
|
width?: string | number;
|
||||||
};
|
};
|
||||||
|
|
||||||
type BtnClickDialog = {
|
type BtnClickDialog = {
|
||||||
options?: DialogOptions;
|
options?: DialogOptions;
|
||||||
index?: number;
|
index?: number;
|
||||||
};
|
};
|
||||||
type BtnClickButton = {
|
type BtnClickButton = {
|
||||||
btn?: ButtonProps;
|
btn?: ButtonProps;
|
||||||
index?: number;
|
index?: number;
|
||||||
};
|
};
|
||||||
/** https://element-plus.org/zh-CN/component/button.html#button-attributes */
|
/** https://element-plus.org/zh-CN/component/button.html#button-attributes */
|
||||||
type ButtonProps = {
|
type ButtonProps = {
|
||||||
/** 按钮文字 */
|
/** 按钮文字 */
|
||||||
label: string;
|
label: string;
|
||||||
/** 按钮尺寸 */
|
/** 按钮尺寸 */
|
||||||
size?: "large" | "default" | "small";
|
size?: 'large' | 'default' | 'small';
|
||||||
/** 按钮类型 */
|
/** 按钮类型 */
|
||||||
type?: "primary" | "success" | "warning" | "danger" | "info";
|
type?: 'primary' | 'success' | 'warning' | 'danger' | 'info';
|
||||||
/** 是否为朴素按钮,默认 `false` */
|
/** 是否为朴素按钮,默认 `false` */
|
||||||
plain?: boolean;
|
plain?: boolean;
|
||||||
/** 是否为文字按钮,默认 `false` */
|
/** 是否为文字按钮,默认 `false` */
|
||||||
text?: boolean;
|
text?: boolean;
|
||||||
/** 是否显示文字按钮背景颜色,默认 `false` */
|
/** 是否显示文字按钮背景颜色,默认 `false` */
|
||||||
bg?: boolean;
|
bg?: boolean;
|
||||||
/** 是否为链接按钮,默认 `false` */
|
/** 是否为链接按钮,默认 `false` */
|
||||||
link?: boolean;
|
link?: boolean;
|
||||||
/** 是否为圆角按钮,默认 `false` */
|
/** 是否为圆角按钮,默认 `false` */
|
||||||
round?: boolean;
|
round?: boolean;
|
||||||
/** 是否为圆形按钮,默认 `false` */
|
/** 是否为圆形按钮,默认 `false` */
|
||||||
circle?: boolean;
|
circle?: boolean;
|
||||||
/** 确定按钮的 `Popconfirm` 气泡确认框相关配置 */
|
/** 确定按钮的 `Popconfirm` 气泡确认框相关配置 */
|
||||||
popconfirm?: Popconfirm;
|
popconfirm?: Popconfirm;
|
||||||
/** 是否为加载中状态,默认 `false` */
|
/** 是否为加载中状态,默认 `false` */
|
||||||
loading?: boolean;
|
loading?: boolean;
|
||||||
/** 自定义加载中状态图标组件 */
|
/** 自定义加载中状态图标组件 */
|
||||||
loadingIcon?: string | Component;
|
loadingIcon?: string | Component;
|
||||||
/** 按钮是否为禁用状态,默认 `false` */
|
/** 按钮是否为禁用状态,默认 `false` */
|
||||||
disabled?: boolean;
|
disabled?: boolean;
|
||||||
/** 图标组件 */
|
/** 图标组件 */
|
||||||
icon?: string | Component;
|
icon?: string | Component;
|
||||||
/** 是否开启原生 `autofocus` 属性,默认 `false` */
|
/** 是否开启原生 `autofocus` 属性,默认 `false` */
|
||||||
autofocus?: boolean;
|
autofocus?: boolean;
|
||||||
/** 原生 `type` 属性,默认 `button` */
|
/** 原生 `type` 属性,默认 `button` */
|
||||||
nativeType?: "button" | "submit" | "reset";
|
nativeType?: 'button' | 'submit' | 'reset';
|
||||||
/** 自动在两个中文字符之间插入空格 */
|
/** 自动在两个中文字符之间插入空格 */
|
||||||
autoInsertSpace?: boolean;
|
autoInsertSpace?: boolean;
|
||||||
/** 自定义按钮颜色, 并自动计算 `hover` 和 `active` 触发后的颜色 */
|
/** 自定义按钮颜色, 并自动计算 `hover` 和 `active` 触发后的颜色 */
|
||||||
color?: string;
|
color?: string;
|
||||||
/** `dark` 模式, 意味着自动设置 `color` 为 `dark` 模式的颜色,默认 `false` */
|
/** `dark` 模式, 意味着自动设置 `color` 为 `dark` 模式的颜色,默认 `false` */
|
||||||
dark?: boolean;
|
dark?: boolean;
|
||||||
/** 自定义元素标签 */
|
/** 自定义元素标签 */
|
||||||
tag?: string | Component;
|
tag?: string | Component;
|
||||||
/** 点击按钮后触发的回调 */
|
/** 点击按钮后触发的回调 */
|
||||||
btnClick?: ({
|
btnClick?: ({
|
||||||
dialog,
|
dialog,
|
||||||
button
|
button,
|
||||||
}: {
|
}: {
|
||||||
/** 当前 `Dialog` 信息 */
|
/** 当前 `Dialog` 信息 */
|
||||||
dialog: BtnClickDialog;
|
dialog: BtnClickDialog;
|
||||||
/** 当前 `button` 信息 */
|
/** 当前 `button` 信息 */
|
||||||
button: BtnClickButton;
|
button: BtnClickButton;
|
||||||
}) => void;
|
}) => void;
|
||||||
};
|
};
|
||||||
|
|
||||||
interface DialogOptions extends DialogProps {
|
interface DialogOptions extends DialogProps {
|
||||||
/** 内容区组件的 `props`,可通过 `defineProps` 接收 */
|
/** 内容区组件的 `props`,可通过 `defineProps` 接收 */
|
||||||
props?: any;
|
props?: any;
|
||||||
/** 是否隐藏 `Dialog` 按钮操作区的内容 */
|
/** 是否隐藏 `Dialog` 按钮操作区的内容 */
|
||||||
hideFooter?: boolean;
|
hideFooter?: boolean;
|
||||||
/** 确定按钮的 `Popconfirm` 气泡确认框相关配置 */
|
/** 确定按钮的 `Popconfirm` 气泡确认框相关配置 */
|
||||||
popconfirm?: Popconfirm;
|
popconfirm?: Popconfirm;
|
||||||
/** 点击确定按钮后是否开启 `loading` 加载动画 */
|
/** 点击确定按钮后是否开启 `loading` 加载动画 */
|
||||||
sureBtnLoading?: boolean;
|
sureBtnLoading?: boolean;
|
||||||
/**
|
/**
|
||||||
* @description 自定义对话框标题的内容渲染器
|
* @description 自定义对话框标题的内容渲染器
|
||||||
* @see {@link https://element-plus.org/zh-CN/component/dialog.html#%E8%87%AA%E5%AE%9A%E4%B9%89%E5%A4%B4%E9%83%A8}
|
* @see {@link https://element-plus.org/zh-CN/component/dialog.html#%E8%87%AA%E5%AE%9A%E4%B9%89%E5%A4%B4%E9%83%A8}
|
||||||
*/
|
*/
|
||||||
headerRenderer?: ({
|
headerRenderer?: ({ close, titleId, titleClass }: { close: Function; titleId: string; titleClass: string }) => VNode | Component;
|
||||||
close,
|
/** 自定义内容渲染器 */
|
||||||
titleId,
|
contentRenderer?: ({ options, index }: { options: DialogOptions; index: number }) => VNode | Component;
|
||||||
titleClass
|
/** 自定义按钮操作区的内容渲染器,会覆盖`footerButtons`以及默认的 `取消` 和 `确定` 按钮 */
|
||||||
}: {
|
footerRenderer?: ({ options, index }: { options: DialogOptions; index: number }) => VNode | Component;
|
||||||
close: Function;
|
/** 自定义底部按钮操作 */
|
||||||
titleId: string;
|
footerButtons?: Array<ButtonProps>;
|
||||||
titleClass: string;
|
/** `Dialog` 打开后的回调 */
|
||||||
}) => VNode | Component;
|
open?: ({ options, index }: { options: DialogOptions; index: number }) => void;
|
||||||
/** 自定义内容渲染器 */
|
/** `Dialog` 关闭后的回调(只有点击右上角关闭按钮或空白页或按下了esc键关闭页面时才会触发) */
|
||||||
contentRenderer?: ({
|
close?: ({ options, index }: { options: DialogOptions; index: number }) => void;
|
||||||
options,
|
/** `Dialog` 关闭后的回调。 `args` 返回的 `command` 值解析:`cancel` 点击取消按钮、`sure` 点击确定按钮、`close` 点击右上角关闭按钮或空白页或按下了esc键 */
|
||||||
index
|
closeCallBack?: ({ options, index, args }: { options: DialogOptions; index: number; args: any }) => void;
|
||||||
}: {
|
/** 点击全屏按钮时的回调 */
|
||||||
options: DialogOptions;
|
fullscreenCallBack?: ({ options, index }: { options: DialogOptions; index: number }) => void;
|
||||||
index: number;
|
/** 输入焦点聚焦在 `Dialog` 内容时的回调 */
|
||||||
}) => VNode | Component;
|
openAutoFocus?: ({ options, index }: { options: DialogOptions; index: number }) => void;
|
||||||
/** 自定义按钮操作区的内容渲染器,会覆盖`footerButtons`以及默认的 `取消` 和 `确定` 按钮 */
|
/** 输入焦点从 `Dialog` 内容失焦时的回调 */
|
||||||
footerRenderer?: ({
|
closeAutoFocus?: ({ options, index }: { options: DialogOptions; index: number }) => void;
|
||||||
options,
|
/** 点击底部取消按钮的回调,会暂停 `Dialog` 的关闭. 回调函数内执行 `done` 参数方法的时候才是真正关闭对话框的时候 */
|
||||||
index
|
beforeCancel?: (
|
||||||
}: {
|
done: Function,
|
||||||
options: DialogOptions;
|
{
|
||||||
index: number;
|
options,
|
||||||
}) => VNode | Component;
|
index,
|
||||||
/** 自定义底部按钮操作 */
|
}: {
|
||||||
footerButtons?: Array<ButtonProps>;
|
options: DialogOptions;
|
||||||
/** `Dialog` 打开后的回调 */
|
index: number;
|
||||||
open?: ({
|
},
|
||||||
options,
|
) => void;
|
||||||
index
|
/** 点击底部确定按钮的回调,会暂停 `Dialog` 的关闭. 回调函数内执行 `done` 参数方法的时候才是真正关闭对话框的时候 */
|
||||||
}: {
|
beforeSure?: (
|
||||||
options: DialogOptions;
|
done: Function,
|
||||||
index: number;
|
{
|
||||||
}) => void;
|
options,
|
||||||
/** `Dialog` 关闭后的回调(只有点击右上角关闭按钮或空白页或按下了esc键关闭页面时才会触发) */
|
index,
|
||||||
close?: ({
|
closeLoading,
|
||||||
options,
|
}: {
|
||||||
index
|
options: DialogOptions;
|
||||||
}: {
|
index: number;
|
||||||
options: DialogOptions;
|
/** 关闭确定按钮的 `loading` 加载动画 */
|
||||||
index: number;
|
closeLoading: Function;
|
||||||
}) => void;
|
},
|
||||||
/** `Dialog` 关闭后的回调。 `args` 返回的 `command` 值解析:`cancel` 点击取消按钮、`sure` 点击确定按钮、`close` 点击右上角关闭按钮或空白页或按下了esc键 */
|
) => void;
|
||||||
closeCallBack?: ({
|
|
||||||
options,
|
|
||||||
index,
|
|
||||||
args
|
|
||||||
}: {
|
|
||||||
options: DialogOptions;
|
|
||||||
index: number;
|
|
||||||
args: any;
|
|
||||||
}) => void;
|
|
||||||
/** 点击全屏按钮时的回调 */
|
|
||||||
fullscreenCallBack?: ({
|
|
||||||
options,
|
|
||||||
index
|
|
||||||
}: {
|
|
||||||
options: DialogOptions;
|
|
||||||
index: number;
|
|
||||||
}) => void;
|
|
||||||
/** 输入焦点聚焦在 `Dialog` 内容时的回调 */
|
|
||||||
openAutoFocus?: ({
|
|
||||||
options,
|
|
||||||
index
|
|
||||||
}: {
|
|
||||||
options: DialogOptions;
|
|
||||||
index: number;
|
|
||||||
}) => void;
|
|
||||||
/** 输入焦点从 `Dialog` 内容失焦时的回调 */
|
|
||||||
closeAutoFocus?: ({
|
|
||||||
options,
|
|
||||||
index
|
|
||||||
}: {
|
|
||||||
options: DialogOptions;
|
|
||||||
index: number;
|
|
||||||
}) => void;
|
|
||||||
/** 点击底部取消按钮的回调,会暂停 `Dialog` 的关闭. 回调函数内执行 `done` 参数方法的时候才是真正关闭对话框的时候 */
|
|
||||||
beforeCancel?: (
|
|
||||||
done: Function,
|
|
||||||
{
|
|
||||||
options,
|
|
||||||
index
|
|
||||||
}: {
|
|
||||||
options: DialogOptions;
|
|
||||||
index: number;
|
|
||||||
}
|
|
||||||
) => void;
|
|
||||||
/** 点击底部确定按钮的回调,会暂停 `Dialog` 的关闭. 回调函数内执行 `done` 参数方法的时候才是真正关闭对话框的时候 */
|
|
||||||
beforeSure?: (
|
|
||||||
done: Function,
|
|
||||||
{
|
|
||||||
options,
|
|
||||||
index,
|
|
||||||
closeLoading
|
|
||||||
}: {
|
|
||||||
options: DialogOptions;
|
|
||||||
index: number;
|
|
||||||
/** 关闭确定按钮的 `loading` 加载动画 */
|
|
||||||
closeLoading: Function;
|
|
||||||
}
|
|
||||||
) => void;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export type { EventType, ArgsType, DialogProps, ButtonProps, DialogOptions };
|
export type { EventType, ArgsType, DialogProps, ButtonProps, DialogOptions };
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
import iconifyIconOffline from "./src/iconifyIconOffline";
|
import iconifyIconOffline from './src/iconifyIconOffline';
|
||||||
import iconifyIconOnline from "./src/iconifyIconOnline";
|
import iconifyIconOnline from './src/iconifyIconOnline';
|
||||||
import fontIcon from "./src/iconfont";
|
import fontIcon from './src/iconfont';
|
||||||
|
|
||||||
/** 本地图标组件 */
|
/** 本地图标组件 */
|
||||||
const IconifyIconOffline = iconifyIconOffline;
|
const IconifyIconOffline = iconifyIconOffline;
|
||||||
|
|
|
@ -1,48 +1,45 @@
|
||||||
import { h, defineComponent } from "vue";
|
import { defineComponent, h } from 'vue';
|
||||||
|
|
||||||
// 封装iconfont组件,默认`font-class`引用模式,支持`unicode`引用、`font-class`引用、`symbol`引用 (https://www.iconfont.cn/help/detail?spm=a313x.7781069.1998910419.20&helptype=code)
|
// 封装iconfont组件,默认`font-class`引用模式,支持`unicode`引用、`font-class`引用、`symbol`引用 (https://www.iconfont.cn/help/detail?spm=a313x.7781069.1998910419.20&helptype=code)
|
||||||
export default defineComponent({
|
export default defineComponent({
|
||||||
name: "FontIcon",
|
name: 'FontIcon',
|
||||||
props: {
|
props: {
|
||||||
icon: {
|
icon: {
|
||||||
type: String,
|
type: String,
|
||||||
default: ""
|
default: '',
|
||||||
}
|
},
|
||||||
},
|
},
|
||||||
render() {
|
render() {
|
||||||
const attrs = this.$attrs;
|
const attrs = this.$attrs;
|
||||||
if (Object.keys(attrs).includes("uni") || attrs?.iconType === "uni") {
|
if (Object.keys(attrs).includes('uni') || attrs?.iconType === 'uni') {
|
||||||
return h(
|
return h(
|
||||||
"i",
|
'i',
|
||||||
{
|
{
|
||||||
class: "iconfont",
|
class: 'iconfont',
|
||||||
...attrs
|
...attrs,
|
||||||
},
|
},
|
||||||
this.icon
|
this.icon,
|
||||||
);
|
);
|
||||||
} else if (
|
} else if (Object.keys(attrs).includes('svg') || attrs?.iconType === 'svg') {
|
||||||
Object.keys(attrs).includes("svg") ||
|
return h(
|
||||||
attrs?.iconType === "svg"
|
'svg',
|
||||||
) {
|
{
|
||||||
return h(
|
class: 'icon-svg',
|
||||||
"svg",
|
'aria-hidden': true,
|
||||||
{
|
},
|
||||||
class: "icon-svg",
|
{
|
||||||
"aria-hidden": true
|
default: () => [
|
||||||
},
|
h('use', {
|
||||||
{
|
'xlink:href': `#${this.icon}`,
|
||||||
default: () => [
|
}),
|
||||||
h("use", {
|
],
|
||||||
"xlink:href": `#${this.icon}`
|
},
|
||||||
})
|
);
|
||||||
]
|
} else {
|
||||||
}
|
return h('i', {
|
||||||
);
|
class: `iconfont ${this.icon}`,
|
||||||
} else {
|
...attrs,
|
||||||
return h("i", {
|
});
|
||||||
class: `iconfont ${this.icon}`,
|
}
|
||||||
...attrs
|
},
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
});
|
||||||
|
|
|
@ -1,30 +1,28 @@
|
||||||
import { h, defineComponent } from "vue";
|
import { defineComponent, h } from 'vue';
|
||||||
import { Icon as IconifyIcon, addIcon } from "@iconify/vue/dist/offline";
|
import { addIcon, Icon as IconifyIcon } from '@iconify/vue/dist/offline';
|
||||||
|
|
||||||
// Iconify Icon在Vue里本地使用(用于内网环境)
|
// Iconify Icon在Vue里本地使用(用于内网环境)
|
||||||
export default defineComponent({
|
export default defineComponent({
|
||||||
name: "IconifyIconOffline",
|
name: 'IconifyIconOffline',
|
||||||
components: { IconifyIcon },
|
components: { IconifyIcon },
|
||||||
props: {
|
props: {
|
||||||
icon: {
|
icon: {
|
||||||
default: null
|
default: null,
|
||||||
}
|
},
|
||||||
},
|
},
|
||||||
render() {
|
render() {
|
||||||
if (typeof this.icon === "object") addIcon(this.icon, this.icon);
|
if (typeof this.icon === 'object') addIcon(this.icon, this.icon);
|
||||||
const attrs = this.$attrs;
|
const attrs = this.$attrs;
|
||||||
return h(
|
return h(
|
||||||
IconifyIcon,
|
IconifyIcon,
|
||||||
{
|
{
|
||||||
icon: this.icon,
|
icon: this.icon,
|
||||||
style: attrs?.style
|
style: attrs?.style ? Object.assign(attrs.style, { outline: 'none' }) : { outline: 'none' },
|
||||||
? Object.assign(attrs.style, { outline: "none" })
|
...attrs,
|
||||||
: { outline: "none" },
|
},
|
||||||
...attrs
|
{
|
||||||
},
|
default: () => [],
|
||||||
{
|
},
|
||||||
default: () => []
|
);
|
||||||
}
|
},
|
||||||
);
|
|
||||||
}
|
|
||||||
});
|
});
|
||||||
|
|
|
@ -1,30 +1,28 @@
|
||||||
import { h, defineComponent } from "vue";
|
import { defineComponent, h } from 'vue';
|
||||||
import { Icon as IconifyIcon } from "@iconify/vue";
|
import { Icon as IconifyIcon } from '@iconify/vue';
|
||||||
|
|
||||||
// Iconify Icon在Vue里在线使用(用于外网环境)
|
// Iconify Icon在Vue里在线使用(用于外网环境)
|
||||||
export default defineComponent({
|
export default defineComponent({
|
||||||
name: "IconifyIconOnline",
|
name: 'IconifyIconOnline',
|
||||||
components: { IconifyIcon },
|
components: { IconifyIcon },
|
||||||
props: {
|
props: {
|
||||||
icon: {
|
icon: {
|
||||||
type: String,
|
type: String,
|
||||||
default: ""
|
default: '',
|
||||||
}
|
},
|
||||||
},
|
},
|
||||||
render() {
|
render() {
|
||||||
const attrs = this.$attrs;
|
const attrs = this.$attrs;
|
||||||
return h(
|
return h(
|
||||||
IconifyIcon,
|
IconifyIcon,
|
||||||
{
|
{
|
||||||
icon: `${this.icon}`,
|
icon: `${this.icon}`,
|
||||||
style: attrs?.style
|
style: attrs?.style ? Object.assign(attrs.style, { outline: 'none' }) : { outline: 'none' },
|
||||||
? Object.assign(attrs.style, { outline: "none" })
|
...attrs,
|
||||||
: { outline: "none" },
|
},
|
||||||
...attrs
|
{
|
||||||
},
|
default: () => [],
|
||||||
{
|
},
|
||||||
default: () => []
|
);
|
||||||
}
|
},
|
||||||
);
|
|
||||||
}
|
|
||||||
});
|
});
|
||||||
|
|
|
@ -1,14 +1,16 @@
|
||||||
// 这里存放本地图标,在 src/layout/index.vue 文件中加载,避免在首启动加载
|
// 这里存放本地图标,在 src/layout/index.vue 文件中加载,避免在首启动加载
|
||||||
import { addIcon } from "@iconify/vue/dist/offline";
|
import { addIcon } from '@iconify/vue/dist/offline';
|
||||||
|
|
||||||
// 本地菜单图标,后端在路由的 icon 中返回对应的图标字符串并且前端在此处使用 addIcon 添加即可渲染菜单图标
|
// 本地菜单图标,后端在路由的 icon 中返回对应的图标字符串并且前端在此处使用 addIcon 添加即可渲染菜单图标
|
||||||
// @iconify-icons/ep
|
// @iconify-icons/ep
|
||||||
import Lollipop from "@iconify-icons/ep/lollipop";
|
import Lollipop from '@iconify-icons/ep/lollipop';
|
||||||
import HomeFilled from "@iconify-icons/ep/home-filled";
|
import HomeFilled from '@iconify-icons/ep/home-filled';
|
||||||
addIcon("ep:lollipop", Lollipop);
|
|
||||||
addIcon("ep:home-filled", HomeFilled);
|
|
||||||
// @iconify-icons/ri
|
// @iconify-icons/ri
|
||||||
import Search from "@iconify-icons/ri/search-line";
|
import Search from '@iconify-icons/ri/search-line';
|
||||||
import InformationLine from "@iconify-icons/ri/information-line";
|
import InformationLine from '@iconify-icons/ri/information-line';
|
||||||
addIcon("ri:search-line", Search);
|
|
||||||
addIcon("ri:information-line", InformationLine);
|
addIcon('ep:lollipop', Lollipop);
|
||||||
|
addIcon('ep:home-filled', HomeFilled);
|
||||||
|
|
||||||
|
addIcon('ri:search-line', Search);
|
||||||
|
addIcon('ri:information-line', InformationLine);
|
||||||
|
|
|
@ -1,20 +1,20 @@
|
||||||
export interface iconType {
|
export interface iconType {
|
||||||
// iconify (https://docs.iconify.design/icon-components/vue/#properties)
|
// iconify (https://docs.iconify.design/icon-components/vue/#properties)
|
||||||
inline?: boolean;
|
inline?: boolean;
|
||||||
width?: string | number;
|
width?: string | number;
|
||||||
height?: string | number;
|
height?: string | number;
|
||||||
horizontalFlip?: boolean;
|
horizontalFlip?: boolean;
|
||||||
verticalFlip?: boolean;
|
verticalFlip?: boolean;
|
||||||
flip?: string;
|
flip?: string;
|
||||||
rotate?: number | string;
|
rotate?: number | string;
|
||||||
color?: string;
|
color?: string;
|
||||||
horizontalAlign?: boolean;
|
horizontalAlign?: boolean;
|
||||||
verticalAlign?: boolean;
|
verticalAlign?: boolean;
|
||||||
align?: string;
|
align?: string;
|
||||||
onLoad?: Function;
|
onLoad?: Function;
|
||||||
includes?: Function;
|
includes?: Function;
|
||||||
// svg 需要什么SVG属性自行添加
|
// svg 需要什么SVG属性自行添加
|
||||||
fill?: string;
|
fill?: string;
|
||||||
// all icon
|
// all icon
|
||||||
style?: object;
|
style?: object;
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,2 +0,0 @@
|
||||||
normal 普通数字动画组件
|
|
||||||
rebound 回弹式数字动画组件
|
|
|
@ -1,216 +1,175 @@
|
||||||
import { useRenderIcon } from "@/components/CommonIcon/src/hooks";
|
import { useRenderIcon } from '@/components/CommonIcon/src/hooks';
|
||||||
import {
|
import { isFunction, isNumber, useDark, useResizeObserver } from '@pureadmin/utils';
|
||||||
isFunction,
|
import { defineComponent, getCurrentInstance, h, nextTick, type PropType, ref, toRef, watch } from 'vue';
|
||||||
isNumber,
|
import './index.css';
|
||||||
useDark,
|
import type { OptionsType } from './type';
|
||||||
useResizeObserver
|
|
||||||
} from "@pureadmin/utils";
|
|
||||||
import {
|
|
||||||
type PropType,
|
|
||||||
defineComponent,
|
|
||||||
getCurrentInstance,
|
|
||||||
h,
|
|
||||||
nextTick,
|
|
||||||
ref,
|
|
||||||
toRef,
|
|
||||||
watch
|
|
||||||
} from "vue";
|
|
||||||
import "./index.css";
|
|
||||||
import type { OptionsType } from "./type";
|
|
||||||
|
|
||||||
const props = {
|
const props = {
|
||||||
options: {
|
options: {
|
||||||
type: Array<OptionsType>,
|
type: Array<OptionsType>,
|
||||||
default: () => []
|
default: () => [],
|
||||||
},
|
},
|
||||||
/** 默认选中,按照第一个索引为 `0` 的模式,可选(`modelValue`只有传`number`类型时才为响应式) */
|
/** 默认选中,按照第一个索引为 `0` 的模式,可选(`modelValue`只有传`number`类型时才为响应式) */
|
||||||
modelValue: {
|
modelValue: {
|
||||||
type: undefined,
|
type: undefined,
|
||||||
require: false,
|
require: false,
|
||||||
default: "0"
|
default: '0',
|
||||||
},
|
},
|
||||||
/** 将宽度调整为父元素宽度 */
|
/** 将宽度调整为父元素宽度 */
|
||||||
block: {
|
block: {
|
||||||
type: Boolean,
|
type: Boolean,
|
||||||
default: false
|
default: false,
|
||||||
},
|
},
|
||||||
/** 控件尺寸 */
|
/** 控件尺寸 */
|
||||||
size: {
|
size: {
|
||||||
type: String as PropType<"small" | "default" | "large">
|
type: String as PropType<'small' | 'default' | 'large'>,
|
||||||
},
|
},
|
||||||
/** 是否全局禁用,默认 `false` */
|
/** 是否全局禁用,默认 `false` */
|
||||||
disabled: {
|
disabled: {
|
||||||
type: Boolean,
|
type: Boolean,
|
||||||
default: false
|
default: false,
|
||||||
},
|
},
|
||||||
/** 当内容发生变化时,设置 `resize` 可使其自适应容器位置 */
|
/** 当内容发生变化时,设置 `resize` 可使其自适应容器位置 */
|
||||||
resize: {
|
resize: {
|
||||||
type: Boolean,
|
type: Boolean,
|
||||||
default: false
|
default: false,
|
||||||
}
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
export default defineComponent({
|
export default defineComponent({
|
||||||
name: "ReSegmented",
|
name: 'ReSegmented',
|
||||||
props,
|
props,
|
||||||
emits: ["change", "update:modelValue"],
|
emits: ['change', 'update:modelValue'],
|
||||||
setup(props, { emit }) {
|
setup(props, { emit }) {
|
||||||
const width = ref(0);
|
const width = ref(0);
|
||||||
const translateX = ref(0);
|
const translateX = ref(0);
|
||||||
const { isDark } = useDark();
|
const { isDark } = useDark();
|
||||||
const initStatus = ref(false);
|
const initStatus = ref(false);
|
||||||
const curMouseActive = ref(-1);
|
const curMouseActive = ref(-1);
|
||||||
const segmentedItembg = ref("");
|
const segmentedItembg = ref('');
|
||||||
const instance = getCurrentInstance()!;
|
const instance = getCurrentInstance()!;
|
||||||
const curIndex = isNumber(props.modelValue)
|
const curIndex = isNumber(props.modelValue) ? toRef(props, 'modelValue') : ref(0);
|
||||||
? toRef(props, "modelValue")
|
|
||||||
: ref(0);
|
|
||||||
|
|
||||||
function handleChange({ option, index }, event: Event) {
|
function handleChange({ option, index }, event: Event) {
|
||||||
if (props.disabled || option.disabled) return;
|
if (props.disabled || option.disabled) return;
|
||||||
event.preventDefault();
|
event.preventDefault();
|
||||||
isNumber(props.modelValue)
|
isNumber(props.modelValue) ? emit('update:modelValue', index) : (curIndex.value = index);
|
||||||
? emit("update:modelValue", index)
|
segmentedItembg.value = '';
|
||||||
: (curIndex.value = index);
|
emit('change', { index, option });
|
||||||
segmentedItembg.value = "";
|
}
|
||||||
emit("change", { index, option });
|
|
||||||
}
|
|
||||||
|
|
||||||
function handleMouseenter({ option, index }, event: Event) {
|
function handleMouseenter({ option, index }, event: Event) {
|
||||||
if (props.disabled) return;
|
if (props.disabled) return;
|
||||||
event.preventDefault();
|
event.preventDefault();
|
||||||
curMouseActive.value = index;
|
curMouseActive.value = index;
|
||||||
if (option.disabled || curIndex.value === index) {
|
if (option.disabled || curIndex.value === index) {
|
||||||
segmentedItembg.value = "";
|
segmentedItembg.value = '';
|
||||||
} else {
|
} else {
|
||||||
segmentedItembg.value = isDark.value
|
segmentedItembg.value = isDark.value ? '#1f1f1f' : 'rgba(0, 0, 0, 0.06)';
|
||||||
? "#1f1f1f"
|
}
|
||||||
: "rgba(0, 0, 0, 0.06)";
|
}
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
function handleMouseleave(_, event: Event) {
|
function handleMouseleave(_, event: Event) {
|
||||||
if (props.disabled) return;
|
if (props.disabled) return;
|
||||||
event.preventDefault();
|
event.preventDefault();
|
||||||
curMouseActive.value = -1;
|
curMouseActive.value = -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
function handleInit(index = curIndex.value) {
|
function handleInit(index = curIndex.value) {
|
||||||
nextTick(() => {
|
nextTick(() => {
|
||||||
const curLabelRef = instance?.proxy?.$refs[`labelRef${index}`] as ElRef;
|
const curLabelRef = instance?.proxy?.$refs[`labelRef${index}`] as ElRef;
|
||||||
if (!curLabelRef) return;
|
if (!curLabelRef) return;
|
||||||
width.value = curLabelRef.clientWidth;
|
width.value = curLabelRef.clientWidth;
|
||||||
translateX.value = curLabelRef.offsetLeft;
|
translateX.value = curLabelRef.offsetLeft;
|
||||||
initStatus.value = true;
|
initStatus.value = true;
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
function handleResizeInit() {
|
function handleResizeInit() {
|
||||||
useResizeObserver(".pure-segmented", () => {
|
useResizeObserver('.pure-segmented', () => {
|
||||||
nextTick(() => {
|
nextTick(() => {
|
||||||
handleInit(curIndex.value);
|
handleInit(curIndex.value);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
(props.block || props.resize) && handleResizeInit();
|
(props.block || props.resize) && handleResizeInit();
|
||||||
|
|
||||||
watch(
|
watch(
|
||||||
() => curIndex.value,
|
() => curIndex.value,
|
||||||
index => {
|
index => {
|
||||||
nextTick(() => {
|
nextTick(() => {
|
||||||
handleInit(index);
|
handleInit(index);
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
immediate: true
|
immediate: true,
|
||||||
}
|
},
|
||||||
);
|
);
|
||||||
|
|
||||||
watch(() => props.size, handleResizeInit, {
|
watch(() => props.size, handleResizeInit, {
|
||||||
immediate: true
|
immediate: true,
|
||||||
});
|
});
|
||||||
|
|
||||||
const rendLabel = () => {
|
const rendLabel = () => {
|
||||||
return props.options.map((option, index) => {
|
return props.options.map((option, index) => {
|
||||||
return (
|
return (
|
||||||
<label
|
<label
|
||||||
ref={`labelRef${index}`}
|
ref={`labelRef${index}`}
|
||||||
class={[
|
class={['pure-segmented-item', (props.disabled || option?.disabled) && 'pure-segmented-item-disabled']}
|
||||||
"pure-segmented-item",
|
style={{
|
||||||
(props.disabled || option?.disabled) &&
|
background: curMouseActive.value === index ? segmentedItembg.value : '',
|
||||||
"pure-segmented-item-disabled"
|
color: props.disabled ? null : !option.disabled && (curIndex.value === index || curMouseActive.value === index) ? (isDark.value ? 'rgba(255, 255, 255, 0.85)' : 'rgba(0,0,0,.88)') : '',
|
||||||
]}
|
}}
|
||||||
style={{
|
onMouseenter={event => handleMouseenter({ option, index }, event)}
|
||||||
background:
|
onMouseleave={event => handleMouseleave({ option, index }, event)}
|
||||||
curMouseActive.value === index ? segmentedItembg.value : "",
|
onClick={event => handleChange({ option, index }, event)}
|
||||||
color: props.disabled
|
>
|
||||||
? null
|
<input type='radio' name='segmented' />
|
||||||
: !option.disabled &&
|
<div
|
||||||
(curIndex.value === index || curMouseActive.value === index)
|
class='pure-segmented-item-label'
|
||||||
? isDark.value
|
v-tippy={{
|
||||||
? "rgba(255, 255, 255, 0.85)"
|
content: option?.tip,
|
||||||
: "rgba(0,0,0,.88)"
|
zIndex: 41000,
|
||||||
: ""
|
}}
|
||||||
}}
|
>
|
||||||
onMouseenter={event => handleMouseenter({ option, index }, event)}
|
{option.icon && !isFunction(option.label) ? (
|
||||||
onMouseleave={event => handleMouseleave({ option, index }, event)}
|
<span class='pure-segmented-item-icon' style={{ marginRight: option.label ? '6px' : 0 }}>
|
||||||
onClick={event => handleChange({ option, index }, event)}
|
{h(
|
||||||
>
|
useRenderIcon(option.icon, {
|
||||||
<input type="radio" name="segmented" />
|
...option?.iconAttrs,
|
||||||
<div
|
}),
|
||||||
class="pure-segmented-item-label"
|
)}
|
||||||
v-tippy={{
|
</span>
|
||||||
content: option?.tip,
|
) : null}
|
||||||
zIndex: 41000
|
{option.label ? isFunction(option.label) ? h(option.label) : <span>{option.label}</span> : null}
|
||||||
}}
|
</div>
|
||||||
>
|
</label>
|
||||||
{option.icon && !isFunction(option.label) ? (
|
);
|
||||||
<span
|
});
|
||||||
class="pure-segmented-item-icon"
|
};
|
||||||
style={{ marginRight: option.label ? "6px" : 0 }}
|
|
||||||
>
|
|
||||||
{h(
|
|
||||||
useRenderIcon(option.icon, {
|
|
||||||
...option?.iconAttrs
|
|
||||||
})
|
|
||||||
)}
|
|
||||||
</span>
|
|
||||||
) : null}
|
|
||||||
{option.label ? (
|
|
||||||
isFunction(option.label) ? (
|
|
||||||
h(option.label)
|
|
||||||
) : (
|
|
||||||
<span>{option.label}</span>
|
|
||||||
)
|
|
||||||
) : null}
|
|
||||||
</div>
|
|
||||||
</label>
|
|
||||||
);
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
return () => (
|
return () => (
|
||||||
<div
|
<div
|
||||||
class={{
|
class={{
|
||||||
"pure-segmented": true,
|
'pure-segmented': true,
|
||||||
"pure-segmented-block": props.block,
|
'pure-segmented-block': props.block,
|
||||||
"pure-segmented--large": props.size === "large",
|
'pure-segmented--large': props.size === 'large',
|
||||||
"pure-segmented--small": props.size === "small"
|
'pure-segmented--small': props.size === 'small',
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<div class="pure-segmented-group">
|
<div class='pure-segmented-group'>
|
||||||
<div
|
<div
|
||||||
class="pure-segmented-item-selected"
|
class='pure-segmented-item-selected'
|
||||||
style={{
|
style={{
|
||||||
width: `${width.value}px`,
|
width: `${width.value}px`,
|
||||||
transform: `translateX(${translateX.value}px)`,
|
transform: `translateX(${translateX.value}px)`,
|
||||||
display: initStatus.value ? "block" : "none"
|
display: initStatus.value ? 'block' : 'none',
|
||||||
}}
|
}}
|
||||||
></div>
|
></div>
|
||||||
{rendLabel()}
|
{rendLabel()}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
},
|
||||||
});
|
});
|
||||||
|
|
|
@ -169,7 +169,7 @@ export default defineComponent({
|
||||||
};
|
};
|
||||||
|
|
||||||
const isFixedColumn = (label: string) => {
|
const isFixedColumn = (label: string) => {
|
||||||
return !!dynamicColumns.value.filter(item => $t(item.label) === $t(label))[0].fixed;
|
return !!dynamicColumns.value.filter(item => item.label === label)[0].fixed;
|
||||||
};
|
};
|
||||||
|
|
||||||
const rendTippyProps = (content: string) => ({
|
const rendTippyProps = (content: string) => ({
|
||||||
|
@ -213,7 +213,7 @@ export default defineComponent({
|
||||||
<div class={[topClass.value]}>
|
<div class={[topClass.value]}>
|
||||||
<el-checkbox class='!-mr-1' label='列展示' v-model={checkAll.value} indeterminate={isIndeterminate.value} onChange={value => handleCheckAllChange(value)} />
|
<el-checkbox class='!-mr-1' label='列展示' v-model={checkAll.value} indeterminate={isIndeterminate.value} onChange={value => handleCheckAllChange(value)} />
|
||||||
<el-button type='primary' link onClick={() => onReset()}>
|
<el-button type='primary' link onClick={() => onReset()}>
|
||||||
重置
|
{$t('buttons.reset')}
|
||||||
</el-button>
|
</el-button>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
@ -226,8 +226,8 @@ export default defineComponent({
|
||||||
<div class='flex items-center'>
|
<div class='flex items-center'>
|
||||||
<DragIcon class={['drag-btn w-[16px] mr-2', isFixedColumn(item) ? '!cursor-no-drop' : '!cursor-grab']} onMouseenter={(event: { preventDefault: () => void }) => rowDrop(event)} />
|
<DragIcon class={['drag-btn w-[16px] mr-2', isFixedColumn(item) ? '!cursor-no-drop' : '!cursor-grab']} onMouseenter={(event: { preventDefault: () => void }) => rowDrop(event)} />
|
||||||
<el-checkbox key={index} label={item} value={item} onChange={value => handleCheckColumnListChange(value, item)}>
|
<el-checkbox key={index} label={item} value={item} onChange={value => handleCheckColumnListChange(value, item)}>
|
||||||
<span title={$t(item)} class='inline-block w-[120px] truncate hover:text-text_color_primary'>
|
<span title={item} class='inline-block w-[120px] truncate hover:text-text_color_primary'>
|
||||||
{$t(item)}
|
{item}
|
||||||
</span>
|
</span>
|
||||||
</el-checkbox>
|
</el-checkbox>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -1,70 +1,71 @@
|
||||||
<script setup lang="ts">
|
<script lang="ts" setup>
|
||||||
import { useRouter } from "vue-router";
|
import { useRouter } from 'vue-router';
|
||||||
import noAccess from "@/assets/status/403.svg?component";
|
import noAccess from '@/assets/status/403.svg?component';
|
||||||
|
import { $t } from '@/plugins/i18n';
|
||||||
|
|
||||||
defineOptions({
|
defineOptions({
|
||||||
name: "403"
|
name: '403',
|
||||||
});
|
});
|
||||||
|
|
||||||
const router = useRouter();
|
const router = useRouter();
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<div class="flex justify-center items-center h-[640px]">
|
<div class="flex justify-center items-center h-[640px]">
|
||||||
<noAccess />
|
<noAccess />
|
||||||
<div class="ml-12">
|
<div class="ml-12">
|
||||||
<p
|
<p
|
||||||
v-motion
|
v-motion
|
||||||
class="font-medium text-4xl mb-4 dark:text-white"
|
:enter="{
|
||||||
:initial="{
|
opacity: 1,
|
||||||
opacity: 0,
|
y: 0,
|
||||||
y: 100
|
transition: {
|
||||||
}"
|
delay: 80,
|
||||||
:enter="{
|
},
|
||||||
opacity: 1,
|
}"
|
||||||
y: 0,
|
:initial="{
|
||||||
transition: {
|
opacity: 0,
|
||||||
delay: 80
|
y: 100,
|
||||||
}
|
}"
|
||||||
}"
|
class="font-medium text-4xl mb-4 dark:text-white"
|
||||||
>
|
>
|
||||||
403
|
403
|
||||||
</p>
|
</p>
|
||||||
<p
|
<p
|
||||||
v-motion
|
v-motion
|
||||||
class="mb-4 text-gray-500"
|
:enter="{
|
||||||
:initial="{
|
opacity: 1,
|
||||||
opacity: 0,
|
y: 0,
|
||||||
y: 100
|
transition: {
|
||||||
}"
|
delay: 120,
|
||||||
:enter="{
|
},
|
||||||
opacity: 1,
|
}"
|
||||||
y: 0,
|
:initial="{
|
||||||
transition: {
|
opacity: 0,
|
||||||
delay: 120
|
y: 100,
|
||||||
}
|
}"
|
||||||
}"
|
class="mb-4 text-gray-500"
|
||||||
>
|
>
|
||||||
抱歉,你无权访问该页面
|
{{ $t('sorry_no_access') }}
|
||||||
</p>
|
</p>
|
||||||
<el-button
|
<el-button
|
||||||
v-motion
|
v-motion
|
||||||
type="primary"
|
:enter="{
|
||||||
:initial="{
|
opacity: 1,
|
||||||
opacity: 0,
|
y: 0,
|
||||||
y: 100
|
transition: {
|
||||||
}"
|
delay: 160,
|
||||||
:enter="{
|
},
|
||||||
opacity: 1,
|
}"
|
||||||
y: 0,
|
:initial="{
|
||||||
transition: {
|
opacity: 0,
|
||||||
delay: 160
|
y: 100,
|
||||||
}
|
}"
|
||||||
}"
|
type="primary"
|
||||||
@click="router.push('/')"
|
@click="router.push('/')"
|
||||||
>
|
>
|
||||||
返回首页
|
{{ $t('return_to_homepage') }}
|
||||||
</el-button>
|
</el-button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
|
@ -1,70 +1,71 @@
|
||||||
<script setup lang="ts">
|
<script lang="ts" setup>
|
||||||
import { useRouter } from "vue-router";
|
import { useRouter } from 'vue-router';
|
||||||
import noExist from "@/assets/status/404.svg?component";
|
import noExist from '@/assets/status/404.svg?component';
|
||||||
|
import { $t } from '@/plugins/i18n';
|
||||||
|
|
||||||
defineOptions({
|
defineOptions({
|
||||||
name: "404"
|
name: '404',
|
||||||
});
|
});
|
||||||
|
|
||||||
const router = useRouter();
|
const router = useRouter();
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<div class="flex justify-center items-center h-[640px]">
|
<div class="flex justify-center items-center h-[640px]">
|
||||||
<noExist />
|
<noExist />
|
||||||
<div class="ml-12">
|
<div class="ml-12">
|
||||||
<p
|
<p
|
||||||
v-motion
|
v-motion
|
||||||
class="font-medium text-4xl mb-4 dark:text-white"
|
:enter="{
|
||||||
:initial="{
|
opacity: 1,
|
||||||
opacity: 0,
|
y: 0,
|
||||||
y: 100
|
transition: {
|
||||||
}"
|
delay: 80,
|
||||||
:enter="{
|
},
|
||||||
opacity: 1,
|
}"
|
||||||
y: 0,
|
:initial="{
|
||||||
transition: {
|
opacity: 0,
|
||||||
delay: 80
|
y: 100,
|
||||||
}
|
}"
|
||||||
}"
|
class="font-medium text-4xl mb-4 dark:text-white"
|
||||||
>
|
>
|
||||||
404
|
404
|
||||||
</p>
|
</p>
|
||||||
<p
|
<p
|
||||||
v-motion
|
v-motion
|
||||||
class="mb-4 text-gray-500"
|
:enter="{
|
||||||
:initial="{
|
opacity: 1,
|
||||||
opacity: 0,
|
y: 0,
|
||||||
y: 100
|
transition: {
|
||||||
}"
|
delay: 120,
|
||||||
:enter="{
|
},
|
||||||
opacity: 1,
|
}"
|
||||||
y: 0,
|
:initial="{
|
||||||
transition: {
|
opacity: 0,
|
||||||
delay: 120
|
y: 100,
|
||||||
}
|
}"
|
||||||
}"
|
class="mb-4 text-gray-500"
|
||||||
>
|
>
|
||||||
抱歉,你访问的页面不存在
|
{{ $t('sorry_page_not_found') }}
|
||||||
</p>
|
</p>
|
||||||
<el-button
|
<el-button
|
||||||
v-motion
|
v-motion
|
||||||
type="primary"
|
:enter="{
|
||||||
:initial="{
|
opacity: 1,
|
||||||
opacity: 0,
|
y: 0,
|
||||||
y: 100
|
transition: {
|
||||||
}"
|
delay: 160,
|
||||||
:enter="{
|
},
|
||||||
opacity: 1,
|
}"
|
||||||
y: 0,
|
:initial="{
|
||||||
transition: {
|
opacity: 0,
|
||||||
delay: 160
|
y: 100,
|
||||||
}
|
}"
|
||||||
}"
|
type="primary"
|
||||||
@click="router.push('/')"
|
@click="router.push('/')"
|
||||||
>
|
>
|
||||||
返回首页
|
{{ $t('return_to_homepage') }}
|
||||||
</el-button>
|
</el-button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
|
@ -1,70 +1,71 @@
|
||||||
<script setup lang="ts">
|
<script lang="ts" setup>
|
||||||
import { useRouter } from "vue-router";
|
import { useRouter } from 'vue-router';
|
||||||
import noServer from "@/assets/status/500.svg?component";
|
import noServer from '@/assets/status/500.svg?component';
|
||||||
|
import { $t } from '@/plugins/i18n';
|
||||||
|
|
||||||
defineOptions({
|
defineOptions({
|
||||||
name: "500"
|
name: '500',
|
||||||
});
|
});
|
||||||
|
|
||||||
const router = useRouter();
|
const router = useRouter();
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<div class="flex justify-center items-center h-[640px]">
|
<div class="flex justify-center items-center h-[640px]">
|
||||||
<noServer />
|
<noServer />
|
||||||
<div class="ml-12">
|
<div class="ml-12">
|
||||||
<p
|
<p
|
||||||
v-motion
|
v-motion
|
||||||
class="font-medium text-4xl mb-4 dark:text-white"
|
:enter="{
|
||||||
:initial="{
|
opacity: 1,
|
||||||
opacity: 0,
|
y: 0,
|
||||||
y: 100
|
transition: {
|
||||||
}"
|
delay: 80,
|
||||||
:enter="{
|
},
|
||||||
opacity: 1,
|
}"
|
||||||
y: 0,
|
:initial="{
|
||||||
transition: {
|
opacity: 0,
|
||||||
delay: 80
|
y: 100,
|
||||||
}
|
}"
|
||||||
}"
|
class="font-medium text-4xl mb-4 dark:text-white"
|
||||||
>
|
>
|
||||||
500
|
500
|
||||||
</p>
|
</p>
|
||||||
<p
|
<p
|
||||||
v-motion
|
v-motion
|
||||||
class="mb-4 text-gray-500"
|
:enter="{
|
||||||
:initial="{
|
opacity: 1,
|
||||||
opacity: 0,
|
y: 0,
|
||||||
y: 100
|
transition: {
|
||||||
}"
|
delay: 120,
|
||||||
:enter="{
|
},
|
||||||
opacity: 1,
|
}"
|
||||||
y: 0,
|
:initial="{
|
||||||
transition: {
|
opacity: 0,
|
||||||
delay: 120
|
y: 100,
|
||||||
}
|
}"
|
||||||
}"
|
class="mb-4 text-gray-500"
|
||||||
>
|
>
|
||||||
抱歉,服务器出错了
|
{{ $t('sorry_server_error') }}
|
||||||
</p>
|
</p>
|
||||||
<el-button
|
<el-button
|
||||||
v-motion
|
v-motion
|
||||||
type="primary"
|
:enter="{
|
||||||
:initial="{
|
opacity: 1,
|
||||||
opacity: 0,
|
y: 0,
|
||||||
y: 100
|
transition: {
|
||||||
}"
|
delay: 160,
|
||||||
:enter="{
|
},
|
||||||
opacity: 1,
|
}"
|
||||||
y: 0,
|
:initial="{
|
||||||
transition: {
|
opacity: 0,
|
||||||
delay: 160
|
y: 100,
|
||||||
}
|
}"
|
||||||
}"
|
type="primary"
|
||||||
@click="router.push('/')"
|
@click="router.push('/')"
|
||||||
>
|
>
|
||||||
返回首页
|
{{ $t('return_to_homepage') }}
|
||||||
</el-button>
|
</el-button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
|
@ -209,8 +209,8 @@ const markOptions = computed<Array<OptionsType>>(() => {
|
||||||
value: 'card',
|
value: 'card',
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
label: 'panel.pureTagsStyleChrome',
|
label: t('panel.pureTagsStyleChrome'),
|
||||||
tip: 'panel.pureTagsStyleChromeTip',
|
tip: t('panel.pureTagsStyleChrome'),
|
||||||
value: 'chrome',
|
value: 'chrome',
|
||||||
},
|
},
|
||||||
];
|
];
|
||||||
|
|
|
@ -545,7 +545,7 @@ onBeforeUnmount(() => {
|
||||||
<TagChrome />
|
<TagChrome />
|
||||||
</div>
|
</div>
|
||||||
<span class="tag-title">
|
<span class="tag-title">
|
||||||
{{ transformI18n(item.meta.title) }}
|
{{ $t(item.meta.title) }}
|
||||||
</span>
|
</span>
|
||||||
<span v-if="isFixedTag(item) ? false : index !== 0" class="chrome-close-btn" @click.stop="deleteMenu(item)">
|
<span v-if="isFixedTag(item) ? false : index !== 0" class="chrome-close-btn" @click.stop="deleteMenu(item)">
|
||||||
<IconifyIconOffline :icon="Close" />
|
<IconifyIconOffline :icon="Close" />
|
||||||
|
|
88
src/main.ts
88
src/main.ts
|
@ -1,68 +1,64 @@
|
||||||
import { useI18n } from "@/plugins/i18n";
|
import { useI18n } from '@/plugins/i18n';
|
||||||
import { setupStore } from "@/store";
|
import { setupStore } from '@/store';
|
||||||
import { MotionPlugin } from "@vueuse/motion";
|
import { MotionPlugin } from '@vueuse/motion';
|
||||||
import App from "./App.vue";
|
import App from './App.vue';
|
||||||
import { getPlatformConfig } from "./config";
|
import { getPlatformConfig } from './config';
|
||||||
import router from "./router";
|
import router from './router';
|
||||||
// import { useEcharts } from "@/plugins/echarts";
|
// import { useEcharts } from "@/plugins/echarts";
|
||||||
import { useElementPlus } from "@/plugins/elementPlus";
|
import { useElementPlus } from '@/plugins/elementPlus';
|
||||||
import { injectResponsiveStorage } from "@/utils/responsive";
|
import { injectResponsiveStorage } from '@/utils/responsive';
|
||||||
import { createApp, type Directive } from "vue";
|
import { createApp, type Directive } from 'vue';
|
||||||
|
|
||||||
import Table from "@pureadmin/table";
|
import Table from '@pureadmin/table';
|
||||||
// import PureDescriptions from "@pureadmin/descriptions";
|
// import PureDescriptions from "@pureadmin/descriptions";
|
||||||
// 引入重置样式
|
// 引入重置样式
|
||||||
import "./style/reset.scss";
|
import './style/reset.scss';
|
||||||
// 导入公共样式
|
// 导入公共样式
|
||||||
import "./style/index.scss";
|
import './style/index.scss';
|
||||||
// 一定要在main.ts中导入tailwind.css,防止vite每次hmr都会请求src/style/index.scss整体css文件导致热更新慢的问题
|
// 一定要在main.ts中导入tailwind.css,防止vite每次hmr都会请求src/style/index.scss整体css文件导致热更新慢的问题
|
||||||
import "element-plus/dist/index.css";
|
import 'element-plus/dist/index.css';
|
||||||
import "./style/tailwind.css";
|
import './style/tailwind.css';
|
||||||
// 导入字体图标
|
// 导入字体图标
|
||||||
import "./assets/iconfont/iconfont.css";
|
import './assets/iconfont/iconfont.css';
|
||||||
import "./assets/iconfont/iconfont.js";
|
import './assets/iconfont/iconfont.js';
|
||||||
// 自定义指令
|
// 自定义指令
|
||||||
import * as directives from "@/directives";
|
import * as directives from '@/directives';
|
||||||
// 全局注册@iconify/vue图标库
|
// 全局注册@iconify/vue图标库
|
||||||
import {
|
import { FontIcon, IconifyIconOffline, IconifyIconOnline } from './components/CommonIcon';
|
||||||
FontIcon,
|
|
||||||
IconifyIconOffline,
|
|
||||||
IconifyIconOnline
|
|
||||||
} from "./components/CommonIcon";
|
|
||||||
// 全局注册按钮级别权限组件
|
// 全局注册按钮级别权限组件
|
||||||
import { Auth } from "@/components/Auth";
|
import { Auth } from '@/components/Auth';
|
||||||
import { Perms } from "@/components/Perms";
|
import { Perms } from '@/components/Perms';
|
||||||
// 全局注册vue-tippy
|
// 全局注册vue-tippy
|
||||||
import "tippy.js/dist/tippy.css";
|
import 'tippy.js/dist/tippy.css';
|
||||||
import "tippy.js/themes/light.css";
|
import 'tippy.js/themes/light.css';
|
||||||
import VueTippy from "vue-tippy";
|
import VueTippy from 'vue-tippy';
|
||||||
import { useEcharts } from "@/plugins/echarts";
|
import { useEcharts } from '@/plugins/echarts';
|
||||||
|
|
||||||
const app = createApp(App);
|
const app = createApp(App);
|
||||||
|
|
||||||
Object.keys(directives).forEach(key => {
|
Object.keys(directives).forEach(key => {
|
||||||
app.directive(key, (directives as { [key: string]: Directive })[key]);
|
app.directive(key, (directives as { [key: string]: Directive })[key]);
|
||||||
});
|
});
|
||||||
|
|
||||||
app.component("IconifyIconOffline", IconifyIconOffline);
|
app.component('IconifyIconOffline', IconifyIconOffline);
|
||||||
app.component("IconifyIconOnline", IconifyIconOnline);
|
app.component('IconifyIconOnline', IconifyIconOnline);
|
||||||
app.component("FontIcon", FontIcon);
|
app.component('FontIcon', FontIcon);
|
||||||
app.component("Auth", Auth);
|
app.component('Auth', Auth);
|
||||||
app.component("Perms", Perms);
|
app.component('Perms', Perms);
|
||||||
|
|
||||||
app.use(VueTippy);
|
app.use(VueTippy);
|
||||||
|
|
||||||
getPlatformConfig(app).then(async config => {
|
getPlatformConfig(app).then(async config => {
|
||||||
setupStore(app);
|
setupStore(app);
|
||||||
app.use(router);
|
app.use(router);
|
||||||
await router.isReady();
|
await router.isReady();
|
||||||
injectResponsiveStorage(app, config);
|
injectResponsiveStorage(app, config);
|
||||||
app
|
app
|
||||||
.use(MotionPlugin)
|
.use(MotionPlugin)
|
||||||
.use(useI18n)
|
.use(useI18n)
|
||||||
.use(useElementPlus)
|
.use(useElementPlus)
|
||||||
.use(Table)
|
.use(Table)
|
||||||
// .use(PureDescriptions)
|
// .use(PureDescriptions)
|
||||||
.use(useEcharts);
|
.use(useEcharts);
|
||||||
app.mount("#app");
|
app.mount('#app');
|
||||||
});
|
});
|
||||||
|
|
|
@ -1,24 +1,24 @@
|
||||||
// 多组件库的国际化和本地项目国际化兼容
|
// 多组件库的国际化和本地项目国际化兼容
|
||||||
import { createI18n } from "vue-i18n";
|
import { createI18n } from 'vue-i18n';
|
||||||
import type { App } from "vue";
|
import type { App } from 'vue';
|
||||||
|
|
||||||
// ? 从本地存储中获取数据
|
// ? 从本地存储中获取数据
|
||||||
const languageData = localStorage.getItem("i18nStore");
|
const languageData = localStorage.getItem('i18nStore');
|
||||||
|
|
||||||
// 配置多语言
|
// 配置多语言
|
||||||
export const i18n = createI18n({
|
export const i18n = createI18n({
|
||||||
// 如果要支持 compositionAPI,此项必须设置为 false
|
// 如果要支持 compositionAPI,此项必须设置为 false
|
||||||
legacy: false,
|
legacy: false,
|
||||||
// locale: 'zh',
|
// locale: 'zh',
|
||||||
fallbackLocale: "en",
|
fallbackLocale: 'en',
|
||||||
// ? 全局注册$t方法
|
// ? 全局注册$t方法
|
||||||
globalInjection: true,
|
globalInjection: true,
|
||||||
// 本地内容存在时,首次加载如果本地存储没有多语言需要再刷新
|
// 本地内容存在时,首次加载如果本地存储没有多语言需要再刷新
|
||||||
messages: languageData ? JSON.parse(languageData).i18n : {}
|
messages: languageData ? JSON.parse(languageData).i18n : {},
|
||||||
});
|
});
|
||||||
|
|
||||||
export const $t: any = (i18n.global as any).t as any;
|
export const $t: any = (i18n.global as any).t as any;
|
||||||
|
|
||||||
export function useI18n(app: App) {
|
export function useI18n(app: App) {
|
||||||
app.use(i18n);
|
app.use(i18n);
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
import { defineStore } from 'pinia';
|
import { defineStore } from 'pinia';
|
||||||
import { fetchAddI18n, fetchDeleteI18n, fetchGetI18n, fetchGetI18nList, fetchUpdateI18n } from '@/api/v1/i18n';
|
import { fetchAddI18n, fetchDeleteI18n, fetchGetI18n, fetchGetI18nList, fetchUpdateI18n } from '@/api/v1/i18n';
|
||||||
import { pageSizes } from '@/enums/baseConstant';
|
import { pageSizes } from '@/enums/baseConstant';
|
||||||
import { message, storeMessage } from '@/utils/message';
|
import { storeMessage } from '@/utils/message';
|
||||||
|
|
||||||
export const userI18nStore = defineStore('i18nStore', {
|
export const userI18nStore = defineStore('i18nStore', {
|
||||||
persist: true,
|
persist: true,
|
||||||
|
@ -12,7 +12,7 @@ export const userI18nStore = defineStore('i18nStore', {
|
||||||
// 多语言列表
|
// 多语言列表
|
||||||
datalist: [],
|
datalist: [],
|
||||||
// 查询表单
|
// 查询表单
|
||||||
form: { keyName: undefined, translation: undefined },
|
form: { keyName: '', translation: '', typeName: '' },
|
||||||
isAddShown: false,
|
isAddShown: false,
|
||||||
// ? 分页查询结果
|
// ? 分页查询结果
|
||||||
pagination: {
|
pagination: {
|
||||||
|
@ -50,6 +50,9 @@ export const userI18nStore = defineStore('i18nStore', {
|
||||||
*/
|
*/
|
||||||
async getI18nMangeList() {
|
async getI18nMangeList() {
|
||||||
const data = { ...this.pagination, ...this.form };
|
const data = { ...this.pagination, ...this.form };
|
||||||
|
delete data.pageSizes;
|
||||||
|
delete data.total;
|
||||||
|
delete data.background;
|
||||||
const result = await fetchGetI18nList(data);
|
const result = await fetchGetI18nList(data);
|
||||||
|
|
||||||
// 如果成功赋值内容
|
// 如果成功赋值内容
|
||||||
|
@ -61,7 +64,6 @@ export const userI18nStore = defineStore('i18nStore', {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
message(result.message, { type: 'error' });
|
|
||||||
return false;
|
return false;
|
||||||
},
|
},
|
||||||
|
|
||||||
|
|
|
@ -95,6 +95,7 @@ export const closeAllMessage = (): void => ElMessage.closeAll();
|
||||||
*/
|
*/
|
||||||
export const storeMessage = (result: BaseResult<any>) => {
|
export const storeMessage = (result: BaseResult<any>) => {
|
||||||
if (result.code !== 200) {
|
if (result.code !== 200) {
|
||||||
|
message(result.message, { type: 'warning' });
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
message(result.message, { type: 'success' });
|
message(result.message, { type: 'success' });
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
<script lang="ts" setup>
|
<script lang="ts" setup>
|
||||||
import { ref } from 'vue';
|
import { onMounted, ref } from 'vue';
|
||||||
import { FormInstance } from 'element-plus';
|
import { FormInstance } from 'element-plus';
|
||||||
import { rules } from '@/views/i18n/i18n-setting/utils/columns';
|
import { rules } from '@/views/i18n/i18n-setting/utils/columns';
|
||||||
import { FormProps } from '@/views/i18n/i18n-setting/utils/types';
|
import { FormProps } from '@/views/i18n/i18n-setting/utils/types';
|
||||||
|
@ -9,7 +9,7 @@ const props = withDefaults(defineProps<FormProps>(), {
|
||||||
formInline: () => ({
|
formInline: () => ({
|
||||||
keyName: '',
|
keyName: '',
|
||||||
translation: '',
|
translation: '',
|
||||||
typeId: '',
|
typeName: '',
|
||||||
}),
|
}),
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -17,14 +17,17 @@ const ruleFormRef = ref<FormInstance>();
|
||||||
const form = ref(props.formInline);
|
const form = ref(props.formInline);
|
||||||
const i18nTypeStore = userI18nTypeStore();
|
const i18nTypeStore = userI18nTypeStore();
|
||||||
|
|
||||||
|
onMounted(() => {
|
||||||
|
i18nTypeStore.getI18nTypeList();
|
||||||
|
});
|
||||||
defineExpose({ ruleFormRef });
|
defineExpose({ ruleFormRef });
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<el-form ref="ruleFormRef" :model="form" :rules="rules" isDefault-icon label-position="left" label-width="135px">
|
<el-form ref="ruleFormRef" :model="form" :rules="rules" isDefault-icon label-position="left" label-width="135px">
|
||||||
<el-form-item label="选择添加语言分类" prop="typeId">
|
<el-form-item label="选择添加语言分类" prop="typeName">
|
||||||
<el-select v-model="form.typeId" filterable placeholder="选择添加语言分类">
|
<el-select v-model="form.typeName" filterable placeholder="选择添加语言分类">
|
||||||
<el-option v-for="item in i18nTypeStore.datalist" :key="item.id" :label="item.typeName" :value="item.id" />
|
<el-option v-for="item in i18nTypeStore.datalist" :key="item.typeName" :label="item.typeName" :value="item.typeName" />
|
||||||
</el-select>
|
</el-select>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
|
|
||||||
|
|
|
@ -10,17 +10,17 @@ import PureTableBar from '@/components/TableBar/src/bar';
|
||||||
import PureTable from '@pureadmin/table';
|
import PureTable from '@pureadmin/table';
|
||||||
import { columns } from '@/views/i18n/i18n-setting/utils/columns';
|
import { columns } from '@/views/i18n/i18n-setting/utils/columns';
|
||||||
import Refresh from '@iconify-icons/ep/refresh';
|
import Refresh from '@iconify-icons/ep/refresh';
|
||||||
import { resetForm } from '@/views/menu/utils/hook';
|
import { $t } from '@/plugins/i18n';
|
||||||
|
|
||||||
const tableRef = ref();
|
const tableRef = ref();
|
||||||
const formRef = ref();
|
const pageFormRef = ref();
|
||||||
const i18nStore = userI18nStore();
|
const i18nStore = userI18nStore();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 重置表单
|
* 重置表单
|
||||||
* @param formEl
|
* @param formEl
|
||||||
*/
|
*/
|
||||||
const resetForm = async formEl => {
|
const resetForm = async (formEl: any) => {
|
||||||
if (!formEl) return;
|
if (!formEl) return;
|
||||||
formEl.resetFields();
|
formEl.resetFields();
|
||||||
await onSearch();
|
await onSearch();
|
||||||
|
@ -58,22 +58,25 @@ onMounted(() => {
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<div class="main">
|
<div class="main">
|
||||||
<el-form ref="formRef" :inline="true" :model="i18nStore.form" class="search-form bg-bg_color w-[99/100] pl-8 pt-[12px] overflow-auto">
|
<el-form ref="pageFormRef" :inline="true" :model="i18nStore.form" class="search-form bg-bg_color w-[99/100] pl-8 pt-[12px] overflow-auto">
|
||||||
<el-form-item label="多语言key" prop="keyName">
|
<el-form-item :label="$t('i18n.keyName')" prop="keyName">
|
||||||
<el-input v-model="i18nStore.form.keyName" class="!w-[180px]" clearable placeholder="输入多语言key" />
|
<el-input v-model="i18nStore.form.keyName" :placeholder="`${$t('input')}${$t('i18n.keyName')}`" class="!w-[180px]" clearable />
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
<el-form-item label="多语言翻译" prop="translation">
|
<el-form-item :label="$t('i18n.translation')" prop="translation">
|
||||||
<el-input v-model="i18nStore.form.translation" class="!w-[180px]" clearable placeholder="输入多语言翻译" />
|
<el-input v-model="i18nStore.form.translation" :placeholder="`${$t('input')}${$t('i18n.translation')}`" class="!w-[180px]" clearable />
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item :label="$t('i18n.typeName')" prop="typeName">
|
||||||
|
<el-input v-model="i18nStore.form.typeName" :placeholder="`${$t('input')}${$t('i18n.typeName')}`" class="!w-[180px]" clearable />
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
<el-form-item>
|
<el-form-item>
|
||||||
<el-button :icon="useRenderIcon('ri:search-line')" :loading="i18nStore.loading" type="primary" @click="onSearch"> 搜索 </el-button>
|
<el-button :icon="useRenderIcon('ri:search-line')" :loading="i18nStore.loading" type="primary" @click="onSearch"> {{ $t('search') }} </el-button>
|
||||||
<el-button :icon="useRenderIcon(Refresh)" @click="resetForm(formRef)"> 重置</el-button>
|
<el-button :icon="useRenderIcon(Refresh)" @click="resetForm(pageFormRef)"> {{ $t('buttons.reset') }}</el-button>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
</el-form>
|
</el-form>
|
||||||
|
|
||||||
<PureTableBar :columns="columns" :tableRef="tableRef?.getTableRef()" title="多语言管理" @fullscreen="tableRef.setAdaptive()" @refresh="onSearch">
|
<PureTableBar :columns="columns" :tableRef="tableRef?.getTableRef()" :title="$t('multilingual_management')" @fullscreen="tableRef.setAdaptive()" @refresh="onSearch">
|
||||||
<template #buttons>
|
<template #buttons>
|
||||||
<el-button :icon="useRenderIcon(AddFill)" type="primary" @click="onAdd"> 添加多语言</el-button>
|
<el-button :icon="useRenderIcon(AddFill)" type="primary" @click="onAdd"> {{ $t('add_multilingual') }} </el-button>
|
||||||
</template>
|
</template>
|
||||||
<template v-slot="{ size, dynamicColumns }">
|
<template v-slot="{ size, dynamicColumns }">
|
||||||
<pure-table
|
<pure-table
|
||||||
|
@ -87,6 +90,8 @@ onMounted(() => {
|
||||||
:size="size"
|
:size="size"
|
||||||
adaptive
|
adaptive
|
||||||
align-whole="center"
|
align-whole="center"
|
||||||
|
border
|
||||||
|
highlight-current-row
|
||||||
row-key="id"
|
row-key="id"
|
||||||
showOverflowTooltip
|
showOverflowTooltip
|
||||||
table-layout="auto"
|
table-layout="auto"
|
||||||
|
@ -95,11 +100,13 @@ onMounted(() => {
|
||||||
@page-current-change="onCurrentPageChange"
|
@page-current-change="onCurrentPageChange"
|
||||||
>
|
>
|
||||||
<template #operation="{ row }">
|
<template #operation="{ row }">
|
||||||
<el-button :icon="useRenderIcon(EditPen)" :size="size" class="reset-margin" link type="primary" @click="onUpdate(row)"> 修改 </el-button>
|
<el-button :icon="useRenderIcon(EditPen)" :size="size" class="reset-margin" link type="primary" @click="onUpdate(row)"> {{ $t('modify') }} </el-button>
|
||||||
<el-button v-show="row.menuType !== 3" :icon="useRenderIcon(AddFill)" :size="size" class="reset-margin" link type="primary"> 新增 </el-button>
|
<el-button v-show="row.menuType !== 3" :icon="useRenderIcon(AddFill)" :size="size" class="reset-margin" link type="primary"> {{ $t('add_new') }} </el-button>
|
||||||
<el-popconfirm :title="`是否确认删除 ${row.translation}数据`" @confirm="onDelete(row)">
|
<el-popconfirm :title="`${$t('confirm_delete')} ${row.translation}`" @confirm="onDelete(row)">
|
||||||
<template #reference>
|
<template #reference>
|
||||||
<el-button :icon="useRenderIcon(Delete)" :size="size" class="reset-margin" link type="primary"> 删除 </el-button>
|
<el-button :icon="useRenderIcon(Delete)" :size="size" class="reset-margin" link type="primary">
|
||||||
|
{{ $t('delete') }}
|
||||||
|
</el-button>
|
||||||
</template>
|
</template>
|
||||||
</el-popconfirm>
|
</el-popconfirm>
|
||||||
</template>
|
</template>
|
||||||
|
|
|
@ -1,22 +1,23 @@
|
||||||
// 多语言表格列字段
|
// 多语言表格列字段
|
||||||
import { reactive } from 'vue';
|
import { reactive } from 'vue';
|
||||||
import type { FormRules } from 'element-plus';
|
import type { FormRules } from 'element-plus';
|
||||||
|
import { $t } from '@/plugins/i18n';
|
||||||
|
|
||||||
export const columns: TableColumnList = [
|
export const columns: TableColumnList = [
|
||||||
{ label: 'id', prop: 'id' },
|
{ label: $t('id'), prop: 'id' },
|
||||||
{ label: 'i18n_keyName', prop: 'keyName' },
|
{ label: $t('i18n.keyName'), prop: 'keyName' },
|
||||||
{ label: 'i18n_translation', prop: 'translation' },
|
{ label: $t('i18n.translation'), prop: 'translation' },
|
||||||
{ label: 'i18n_typeId', prop: 'typeId' },
|
{ label: $t('i18n.typeName'), prop: 'typeName' },
|
||||||
{ label: 'updateTime', prop: 'updateTime' },
|
{ label: $t('table.updateTime'), prop: 'updateTime' },
|
||||||
{ label: 'createTime', prop: 'createTime' },
|
{ label: $t('table.createTime'), prop: 'createTime' },
|
||||||
{ label: 'createUser', prop: 'createUser' },
|
{ label: $t('table.createUser'), prop: 'createUser' },
|
||||||
{ label: 'updateUser', prop: 'updateUser' },
|
{ label: $t('table.updateUser'), prop: 'updateUser' },
|
||||||
{ label: 'operation', fixed: 'right', width: 210, slot: 'operation' },
|
{ label: $t('table.operation'), fixed: 'right', width: 210, slot: 'operation' },
|
||||||
];
|
];
|
||||||
|
|
||||||
// 添加多语言表单规则
|
// 添加多语言表单规则
|
||||||
export const rules = reactive<FormRules>({
|
export const rules = reactive<FormRules>({
|
||||||
keyName: [{ required: true, message: '输入多语言key', trigger: 'blur' }],
|
keyName: [{ required: true, message: `${$t('input')}${$t('i18n.keyName')}`, trigger: 'blur' }],
|
||||||
translation: [{ required: true, message: '输入多语言翻译', trigger: 'blur' }],
|
translation: [{ required: true, message: `${$t('input')}${$t('i18n.translation')}`, trigger: 'blur' }],
|
||||||
typeId: [{ required: true, message: '选择添加语言分类', trigger: 'blur' }],
|
typeName: [{ required: true, message: `${$t('input')}${$t('i18n.typeName')}`, trigger: 'blur' }],
|
||||||
});
|
});
|
||||||
|
|
|
@ -1,23 +1,15 @@
|
||||||
import { h, reactive, ref } from 'vue';
|
import { h, ref } from 'vue';
|
||||||
import { userI18nStore } from '@/store/i18n/i18n';
|
import { userI18nStore } from '@/store/i18n/i18n';
|
||||||
import { messageBox } from '@/utils/message';
|
import { messageBox } from '@/utils/message';
|
||||||
import { addDialog } from '@/components/BaseDialog/index';
|
import { addDialog, closeDialog } from '@/components/BaseDialog/index';
|
||||||
import { deviceDetection } from '@pureadmin/utils';
|
import { deviceDetection } from '@pureadmin/utils';
|
||||||
import I18nDialog from '@/views/i18n/i18n-setting/i18n-dialog.vue';
|
import I18nDialog from '@/views/i18n/i18n-setting/i18n-dialog.vue';
|
||||||
import type { FormProps } from '@/views/i18n/i18n-setting/utils/types';
|
import type { FormProps } from '@/views/i18n/i18n-setting/utils/types';
|
||||||
|
import { $t } from '@/plugins/i18n';
|
||||||
|
|
||||||
export const formRef = ref();
|
export const formRef = ref();
|
||||||
const i18nStore = userI18nStore();
|
const i18nStore = userI18nStore();
|
||||||
const ids = ref<string[]>([]);
|
export const ids = ref<string[]>([]);
|
||||||
|
|
||||||
// 更新表单数据
|
|
||||||
export const updateForm = reactive({
|
|
||||||
id: '',
|
|
||||||
languageId: '',
|
|
||||||
keyName: '',
|
|
||||||
translate: '',
|
|
||||||
parentId: '',
|
|
||||||
});
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* * 查询内容
|
* * 查询内容
|
||||||
|
@ -34,25 +26,56 @@ export const onSearch = async () => {
|
||||||
*/
|
*/
|
||||||
export const onAdd = () => {
|
export const onAdd = () => {
|
||||||
addDialog({
|
addDialog({
|
||||||
title: `添加多语言`,
|
title: `${$t('add_multilingual')}`,
|
||||||
width: '30%',
|
width: '30%',
|
||||||
props: { formInline: { keyName: '', translation: '', typeId: '' } },
|
props: { formInline: { keyName: '', translation: '', typeName: '' } },
|
||||||
draggable: true,
|
draggable: true,
|
||||||
fullscreen: deviceDetection(),
|
fullscreen: deviceDetection(),
|
||||||
fullscreenIcon: true,
|
fullscreenIcon: true,
|
||||||
closeOnClickModal: false,
|
closeOnClickModal: false,
|
||||||
contentRenderer: () => h(I18nDialog, { ref: formRef }),
|
contentRenderer: () => h(I18nDialog, { ref: formRef }),
|
||||||
beforeSure: (done, { options }) => {
|
footerButtons: [
|
||||||
const form = options.props.formInline as FormProps;
|
{
|
||||||
formRef.value.ruleFormRef.validate(async (valid: any) => {
|
label: '取消',
|
||||||
if (!valid) return;
|
text: true,
|
||||||
|
bg: true,
|
||||||
|
btnClick: ({ dialog: { options, index } }) => {
|
||||||
|
closeDialog(options, index);
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: $t('buttons.pureConfirm'),
|
||||||
|
type: 'primary',
|
||||||
|
text: true,
|
||||||
|
bg: true,
|
||||||
|
btnClick: ({ dialog: { options, index } }) => {
|
||||||
|
const form = options.props.formInline as FormProps;
|
||||||
|
formRef.value.ruleFormRef.validate(async (valid: any) => {
|
||||||
|
if (!valid) return;
|
||||||
|
|
||||||
const result = await i18nStore.addI18n(form);
|
const result = await i18nStore.addI18n(form);
|
||||||
if (!result) return;
|
if (!result) return;
|
||||||
done();
|
closeDialog(options, index);
|
||||||
await onSearch();
|
await onSearch();
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: '继续添加',
|
||||||
|
type: 'success',
|
||||||
|
text: true,
|
||||||
|
bg: true,
|
||||||
|
btnClick: ({ dialog: { options } }) => {
|
||||||
|
const form = options.props.formInline as FormProps;
|
||||||
|
formRef.value.ruleFormRef.validate(async (valid: any) => {
|
||||||
|
if (!valid) return;
|
||||||
|
const result = await i18nStore.addI18n(form);
|
||||||
|
if (!result) return;
|
||||||
|
await onSearch();
|
||||||
|
});
|
||||||
|
},
|
||||||
|
},
|
||||||
|
],
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
|
@ -2,7 +2,7 @@
|
||||||
export interface FormItemProps {
|
export interface FormItemProps {
|
||||||
keyName: string;
|
keyName: string;
|
||||||
translation: string;
|
translation: string;
|
||||||
typeId: string;
|
typeName: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
// 添加或修改表单Props
|
// 添加或修改表单Props
|
||||||
|
|
|
@ -10,7 +10,7 @@ import { onAdd, onDelete, onSearch, onUpdate } from '@/views/i18n/i18n-type-sett
|
||||||
import Delete from '@iconify-icons/ep/delete';
|
import Delete from '@iconify-icons/ep/delete';
|
||||||
import EditPen from '@iconify-icons/ep/edit-pen';
|
import EditPen from '@iconify-icons/ep/edit-pen';
|
||||||
import TableIsDefaultTag from '@/components/TableBar/src/TableIsDefaultTag.vue';
|
import TableIsDefaultTag from '@/components/TableBar/src/TableIsDefaultTag.vue';
|
||||||
import { resetForm } from '@/views/menu/utils/hook';
|
import { resetForm } from '@/views/system/menu/utils/hook';
|
||||||
import Refresh from '@iconify-icons/ep/refresh';
|
import Refresh from '@iconify-icons/ep/refresh';
|
||||||
|
|
||||||
const tableRef = ref();
|
const tableRef = ref();
|
||||||
|
|
|
@ -1,8 +1,8 @@
|
||||||
<script lang="ts" setup>
|
<script lang="ts" setup>
|
||||||
import { onMounted, ref } from 'vue';
|
import { onMounted, ref } from 'vue';
|
||||||
import ReCol from '@/components/MyCol';
|
import ReCol from '@/components/MyCol';
|
||||||
import { formRules } from './utils/rule';
|
import { formRules } from '@/views/system/menu/utils/rule';
|
||||||
import { FormProps } from './utils/types';
|
import { FormProps } from '@/views/system/menu/utils/types';
|
||||||
import { IconSelect } from '@/components/ReIcon';
|
import { IconSelect } from '@/components/ReIcon';
|
||||||
import Segmented from '@/components/ReSegmented';
|
import Segmented from '@/components/ReSegmented';
|
||||||
import ReAnimateSelector from '@/components/AnimateSelector';
|
import ReAnimateSelector from '@/components/AnimateSelector';
|
|
@ -7,10 +7,10 @@ import Delete from '@iconify-icons/ep/delete';
|
||||||
import EditPen from '@iconify-icons/ep/edit-pen';
|
import EditPen from '@iconify-icons/ep/edit-pen';
|
||||||
import Refresh from '@iconify-icons/ep/refresh';
|
import Refresh from '@iconify-icons/ep/refresh';
|
||||||
import AddFill from '@iconify-icons/ri/add-circle-line';
|
import AddFill from '@iconify-icons/ri/add-circle-line';
|
||||||
import { dataList, handleDelete, loading, onSearch, openDialog, resetForm } from '@/views/menu/utils/hook';
|
import { dataList, handleDelete, loading, onSearch, openDialog, resetForm } from '@/views/system/menu/utils/hook';
|
||||||
import form from '@/views/role/form.vue';
|
import form from '@/views/role/form.vue';
|
||||||
import PureTable from '@pureadmin/table';
|
import PureTable from '@pureadmin/table';
|
||||||
import { columns } from '@/views/menu/utils/rule';
|
import { columns } from '@/views/system/menu/utils/rule';
|
||||||
|
|
||||||
defineOptions({
|
defineOptions({
|
||||||
name: 'SystemMenu',
|
name: 'SystemMenu',
|
|
@ -3,9 +3,9 @@ import { handleTree } from '@/utils/tree';
|
||||||
import { message } from '@/utils/message';
|
import { message } from '@/utils/message';
|
||||||
import { getMenuList } from '@/api/v1/system';
|
import { getMenuList } from '@/api/v1/system';
|
||||||
import { $t } from '@/plugins/i18n';
|
import { $t } from '@/plugins/i18n';
|
||||||
import { addDialog } from '@/components/BaseDialog';
|
import { addDialog } from '@/components/BaseDialog/index';
|
||||||
import { h, reactive, ref } from 'vue';
|
import { h, reactive, ref } from 'vue';
|
||||||
import type { FormItemProps } from '../utils/types';
|
import type { FormItemProps } from './types';
|
||||||
|
|
||||||
import { cloneDeep, deviceDetection, isAllEmpty } from '@pureadmin/utils';
|
import { cloneDeep, deviceDetection, isAllEmpty } from '@pureadmin/utils';
|
||||||
import { userRouterStore } from '@/store/modules/router';
|
import { userRouterStore } from '@/store/modules/router';
|
|
@ -3,7 +3,7 @@ import type { FormRules } from 'element-plus';
|
||||||
import { useRenderIcon } from '@/components/ReIcon/src/hooks';
|
import { useRenderIcon } from '@/components/ReIcon/src/hooks';
|
||||||
import { $t } from '@/plugins/i18n';
|
import { $t } from '@/plugins/i18n';
|
||||||
import { isAllEmpty } from '@pureadmin/utils';
|
import { isAllEmpty } from '@pureadmin/utils';
|
||||||
import { getMenuType } from '@/views/menu/utils/hook';
|
import { getMenuType } from '@/views/system/menu/utils/hook';
|
||||||
|
|
||||||
export const columns: TableColumnList = [
|
export const columns: TableColumnList = [
|
||||||
{
|
{
|
Loading…
Reference in New Issue