refactor: rewrite comments in English
This commit is contained in:
parent
4a0c3c6231
commit
e3202ade12
1
.gitignore
vendored
1
.gitignore
vendored
@ -181,4 +181,3 @@ workspace/
|
|||||||
|
|
||||||
# Private Config
|
# Private Config
|
||||||
config/config.toml
|
config/config.toml
|
||||||
|
|
||||||
|
@ -69,7 +69,3 @@ To build the application:
|
|||||||
wails build
|
wails build
|
||||||
|
|
||||||
The built application will be located in the project’s dist directory.
|
The built application will be located in the project’s dist directory.
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
@ -69,7 +69,3 @@ nodejs官网安装: https://nodejs.org/en
|
|||||||
wails build
|
wails build
|
||||||
|
|
||||||
构建好的应用在项目dist目录下
|
构建好的应用在项目dist目录下
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
@ -35,7 +35,7 @@ func (a *App) Greet(name string) string {
|
|||||||
|
|
||||||
// ReadAll reads file content
|
// ReadAll reads file content
|
||||||
func (a *App) ReadAll(filePath string) string {
|
func (a *App) ReadAll(filePath string) string {
|
||||||
// 读取文件内容,得到一个含文件内容和callbackid的json字符串
|
// Read the file content, resulting in a JSON string containing file content and callback ID
|
||||||
data := string(utils.ReadAll(filePath))
|
data := string(utils.ReadAll(filePath))
|
||||||
utils.Log("ReadAll data: ", data)
|
utils.Log("ReadAll data: ", data)
|
||||||
return data
|
return data
|
||||||
|
@ -10,4 +10,3 @@
|
|||||||
<script src="./src/main.js" type="module"></script>
|
<script src="./src/main.js" type="module"></script>
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
|
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
<template>
|
<template>
|
||||||
<!-- 全局配置 -->
|
<!-- Global Configuration -->
|
||||||
<el-config-provider :size="size" :z-index="zIndex" :locale="locale" :button="config" :message="config"
|
<el-config-provider :size="size" :z-index="zIndex" :locale="locale" :button="config" :message="config"
|
||||||
:value-on-clear="null" :empty-values="[undefined, null]">
|
:value-on-clear="null" :empty-values="[undefined, null]">
|
||||||
<RouterView />
|
<RouterView />
|
||||||
@ -10,7 +10,7 @@
|
|||||||
import { ref, reactive, onMounted, watch } from 'vue'
|
import { ref, reactive, onMounted, watch } from 'vue'
|
||||||
import en from 'element-plus/es/locale/lang/en'
|
import en from 'element-plus/es/locale/lang/en'
|
||||||
import zhCn from 'element-plus/es/locale/lang/zh-cn'
|
import zhCn from 'element-plus/es/locale/lang/zh-cn'
|
||||||
/** 暗黑主题 */
|
/** Dark Theme */
|
||||||
import { useDark, useStorage } from '@vueuse/core'
|
import { useDark, useStorage } from '@vueuse/core'
|
||||||
|
|
||||||
const size = 'default'
|
const size = 'default'
|
||||||
@ -22,11 +22,11 @@ const localeStr = localConfig.selectedLang ? localConfig.selectedLang.code : 'en
|
|||||||
const locale = localeStr == 'en' ? en : zhCn
|
const locale = localeStr == 'en' ? en : zhCn
|
||||||
|
|
||||||
const isDark = useDark()
|
const isDark = useDark()
|
||||||
// 存储用户的喜好
|
// Store user preferences
|
||||||
const userPrefersDark = ref(null)
|
const userPrefersDark = ref(null)
|
||||||
onMounted(() => {
|
onMounted(() => {
|
||||||
|
|
||||||
// 使用 useStorage 钩子来同步 isDark 和本地存储
|
// Use useStorage hook to sync isDark and local storage
|
||||||
useStorage(
|
useStorage(
|
||||||
'user-prefers-dark',
|
'user-prefers-dark',
|
||||||
userPrefersDark,
|
userPrefersDark,
|
||||||
@ -35,17 +35,17 @@ onMounted(() => {
|
|||||||
)
|
)
|
||||||
})
|
})
|
||||||
|
|
||||||
// 监听 isDark 变化,并更新本地存储
|
// Watch isDark changes and update local storage
|
||||||
watch(isDark, (newValue) => {
|
watch(isDark, (newValue) => {
|
||||||
userPrefersDark.value = newValue ? 'dark' : 'light'
|
userPrefersDark.value = newValue ? 'dark' : 'light'
|
||||||
})
|
})
|
||||||
|
|
||||||
|
|
||||||
/* 全局配置 */
|
/* Global Configuration */
|
||||||
const config = reactive({
|
const config = reactive({
|
||||||
// 按钮-中文字符中间自动插入空格
|
// Button - Automatically insert space between Chinese characters
|
||||||
autoInsertSpace: true,
|
autoInsertSpace: true,
|
||||||
// 消息-可同时显示的消息最大数量
|
// Message - Maximum number of messages that can be displayed simultaneously
|
||||||
max: 3,
|
max: 3,
|
||||||
})
|
})
|
||||||
</script>
|
</script>
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
:root {
|
:root {
|
||||||
--el-menu-base-level-padding: 10px !important;
|
--el-menu-base-level-padding: 10px !important;
|
||||||
/** 子菜单缩进 */
|
/** Indents for submenu items */
|
||||||
--el-menu-level-padding: 20px !important;
|
--el-menu-level-padding: 20px !important;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -13,7 +13,7 @@
|
|||||||
margin: 0;
|
margin: 0;
|
||||||
padding: 0;
|
padding: 0;
|
||||||
font-family: inherit;
|
font-family: inherit;
|
||||||
/* 让broder不占用宽度 */
|
/* Ensure borders don't take up space */
|
||||||
box-sizing: border-box;
|
box-sizing: border-box;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -34,7 +34,7 @@ body {
|
|||||||
padding: 0;
|
padding: 0;
|
||||||
line-height: 1.5;
|
line-height: 1.5;
|
||||||
touch-action: none;
|
touch-action: none;
|
||||||
/* 不使用原生滚动条 */
|
/* Don't use native scroll bars */
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -69,7 +69,7 @@ a {
|
|||||||
text-decoration: none;
|
text-decoration: none;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* 防止双击选中 */
|
/* Avoid double-click selection */
|
||||||
a.no-select {
|
a.no-select {
|
||||||
-webkit-user-select: none;
|
-webkit-user-select: none;
|
||||||
-moz-user-select: none;
|
-moz-user-select: none;
|
||||||
@ -114,12 +114,12 @@ fieldset {
|
|||||||
text-align: right;
|
text-align: right;
|
||||||
}
|
}
|
||||||
|
|
||||||
/** 文本缩进默认值,2个字符 */
|
/** Default indent for text, 2 characters */
|
||||||
.text-indent {
|
.text-indent {
|
||||||
text-indent: 2em;
|
text-indent: 2em;
|
||||||
}
|
}
|
||||||
|
|
||||||
/** \n 换行 */
|
/** Multiline text preset */
|
||||||
.multiline-text {
|
.multiline-text {
|
||||||
white-space: pre-wrap;
|
white-space: pre-wrap;
|
||||||
word-wrap: break-word;
|
word-wrap: break-word;
|
||||||
@ -130,7 +130,7 @@ input:-webkit-autofill,
|
|||||||
textarea:-webkit-autofill,
|
textarea:-webkit-autofill,
|
||||||
select:-webkit-autofill {
|
select:-webkit-autofill {
|
||||||
-webkit-text-fill-color: var(--el-text-color);
|
-webkit-text-fill-color: var(--el-text-color);
|
||||||
/* transparent 背景透明 */
|
/* transparent background */
|
||||||
-webkit-box-shadow: 0 0 0px 1000px transparent inset;
|
-webkit-box-shadow: 0 0 0px 1000px transparent inset;
|
||||||
transition: background-color 5000s ease-in-out 0s;
|
transition: background-color 5000s ease-in-out 0s;
|
||||||
}
|
}
|
||||||
@ -151,32 +151,32 @@ input::selection,
|
|||||||
input:-webkit-autofill::selection,
|
input:-webkit-autofill::selection,
|
||||||
input:-webkit-autofill:hover::selection,
|
input:-webkit-autofill:hover::selection,
|
||||||
input:-webkit-autofill:focus::selection {
|
input:-webkit-autofill:focus::selection {
|
||||||
/* 设置自动填充时选中文本的样式 */
|
/* Style for autocompleted text */
|
||||||
/* 文字颜色 */
|
/* Color for text */
|
||||||
-webkit-text-fill-color: rgb(255, 255, 255);
|
-webkit-text-fill-color: rgb(255, 255, 255);
|
||||||
/* 背景颜色 */
|
/* Color for background */
|
||||||
background-color: rgb(0, 0, 255);
|
background-color: rgb(0, 0, 255);
|
||||||
-webkit-box-shadow: 0 0 0px 1000px rgb(255, 255, 255) inset;
|
-webkit-box-shadow: 0 0 0px 1000px rgb(255, 255, 255) inset;
|
||||||
box-shadow: 0 0 0px 1000px rgb(255, 255, 255) inset;
|
box-shadow: 0 0 0px 1000px rgb(255, 255, 255) inset;
|
||||||
/* 防止背景颜色变化 */
|
/* Avoid color changes for background */
|
||||||
transition: background-color 5000s ease-in-out 0s;
|
transition: background-color 5000s ease-in-out 0s;
|
||||||
}
|
}
|
||||||
|
|
||||||
img {
|
img {
|
||||||
/* 添加渐变效果 */
|
/* Add transition */
|
||||||
transition: opacity 0.4s ease;
|
transition: opacity 0.4s ease;
|
||||||
/* 默认透明度为1(不透明) */
|
/* No transparency by default */
|
||||||
opacity: 1;
|
opacity: 1;
|
||||||
/* 添加圆角 */
|
/* Add rounded corners */
|
||||||
border-radius: 6px;
|
border-radius: 6px;
|
||||||
}
|
}
|
||||||
|
|
||||||
img.edit:hover {
|
img.edit:hover {
|
||||||
/* 鼠标悬停时透明度降为0.5 */
|
/* Degrade transparency by 0.5 on hover */
|
||||||
opacity: 0.5;
|
opacity: 0.5;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* 渐变边框 */
|
/* Gradient border */
|
||||||
.gradient-border {
|
.gradient-border {
|
||||||
border: 12px solid transparent;
|
border: 12px solid transparent;
|
||||||
border-radius: 6px;
|
border-radius: 6px;
|
||||||
@ -196,7 +196,7 @@ img.edit:hover {
|
|||||||
|
|
||||||
/** Element Plus Start */
|
/** Element Plus Start */
|
||||||
|
|
||||||
/* 移除全局 el-link 组件的下划线 */
|
/* Remove underlines globally for el-link */
|
||||||
.el-link::after {
|
.el-link::after {
|
||||||
display: none;
|
display: none;
|
||||||
}
|
}
|
||||||
@ -232,7 +232,7 @@ img.edit:hover {
|
|||||||
}
|
}
|
||||||
|
|
||||||
.el-textarea__inner::-webkit-scrollbar {
|
.el-textarea__inner::-webkit-scrollbar {
|
||||||
/* 隐藏滚动条 */
|
/* Hide scrollbar */
|
||||||
width: 0 !important;
|
width: 0 !important;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -253,14 +253,14 @@ button>span.el-button__text--expand {
|
|||||||
--el-font-size-base: 11px;
|
--el-font-size-base: 11px;
|
||||||
}
|
}
|
||||||
|
|
||||||
/** 菜单样式,菜单组件部分样式必须定义在主类中,
|
/** Menu styles - Some of the styles are intended to be defined in main classes. */
|
||||||
|
|
||||||
/* 覆盖el-menu的默认高度 */
|
/* Override the default height for el-menu */
|
||||||
.el-menu--horizontal {
|
.el-menu--horizontal {
|
||||||
--el-menu-horizontal-height: 36px;
|
--el-menu-horizontal-height: 36px;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* 弹出菜单样式 */
|
/* Styles for pop-up menus */
|
||||||
.el-menu--collapse .el-menu .el-submenu,
|
.el-menu--collapse .el-menu .el-submenu,
|
||||||
.el-menu--popup {
|
.el-menu--popup {
|
||||||
min-width: 120px !important;
|
min-width: 120px !important;
|
||||||
@ -268,7 +268,7 @@ button>span.el-button__text--expand {
|
|||||||
margin: 0px 0px !important;
|
margin: 0px 0px !important;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* 如果在AsideMenu定义, 关联的菜单组件可能读取不到某些覆盖的样式 */
|
/* If defined in AsideMenu, menu components associated may not read some overridden styles */
|
||||||
.el-sub-menu__title {
|
.el-sub-menu__title {
|
||||||
padding: 0px 10px !important;
|
padding: 0px 10px !important;
|
||||||
border-radius: 6px;
|
border-radius: 6px;
|
||||||
@ -280,7 +280,7 @@ button>span.el-button__text--expand {
|
|||||||
color: var(--el-color-primary);
|
color: var(--el-color-primary);
|
||||||
}
|
}
|
||||||
|
|
||||||
/** 菜单折叠时hover菜单项高度这里必须再定义一次 */
|
/* When menu is collapsed, hover menu item height must be redefined */
|
||||||
.el-menu-item {
|
.el-menu-item {
|
||||||
border-radius: 6px;
|
border-radius: 6px;
|
||||||
height: 32px !important;
|
height: 32px !important;
|
||||||
@ -301,7 +301,7 @@ button>span.el-button__text--expand {
|
|||||||
background-color: rgba(var(--el-color-primary-rgb), .1);
|
background-color: rgba(var(--el-color-primary-rgb), .1);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* 分割线样式 */
|
/* Divider styles */
|
||||||
div.el-divider {
|
div.el-divider {
|
||||||
margin: 18px auto;
|
margin: 18px auto;
|
||||||
}
|
}
|
||||||
@ -415,7 +415,7 @@ div.el-divider {
|
|||||||
align-items: center;
|
align-items: center;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* 全屏居中 */
|
/* Fullscreen center */
|
||||||
.full-center {
|
.full-center {
|
||||||
width: 100%;
|
width: 100%;
|
||||||
height: 100%;
|
height: 100%;
|
||||||
@ -563,7 +563,7 @@ div.el-divider {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 可换行的弹性布局
|
* Flex layout with multiline support
|
||||||
*/
|
*/
|
||||||
.card-row-wrap {
|
.card-row-wrap {
|
||||||
display: flex;
|
display: flex;
|
||||||
@ -572,31 +572,31 @@ div.el-divider {
|
|||||||
flex-wrap: wrap;
|
flex-wrap: wrap;
|
||||||
}
|
}
|
||||||
|
|
||||||
/** 卡片行内独占一行, 不能取代card-row-item wp-100 */
|
/** Exclusive line in a card, doesn't replace card-row-item wp-100 */
|
||||||
.card-row-aline {
|
.card-row-aline {
|
||||||
width: 100%;
|
width: 100%;
|
||||||
/*防止撑开父元素, 要用flex布局*/
|
/* Prevent parent element to be affected, need a flex display */
|
||||||
min-width: 0;
|
min-width: 0;
|
||||||
margin: 8px 14px;
|
margin: 8px 14px;
|
||||||
/** 为子元素预留margin空间 */
|
/* Reserve margin space for child elements in flex container */
|
||||||
/* padding: 0px 10px; */
|
/* padding: 0px 10px; */
|
||||||
display: flex;
|
display: flex;
|
||||||
justify-content: start;
|
justify-content: start;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
}
|
}
|
||||||
|
|
||||||
/** 卡片行普通元素, 有固定宽度,自适应排版 */
|
/* Card row item with fixed width and adaptive layout */
|
||||||
.card-row-item {
|
.card-row-item {
|
||||||
/*防止撑开父元素*/
|
/* Prevent item from expanding parent container */
|
||||||
min-width: 0;
|
min-width: 0;
|
||||||
margin: 8px 14px;
|
margin: 8px 14px;
|
||||||
/** 不自动换行,可设置高度 */
|
/* Flex layout without wrapping */
|
||||||
display: flex;
|
display: flex;
|
||||||
justify-content: start;
|
justify-content: start;
|
||||||
align-items: start;
|
align-items: start;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* 元素水平居中 */
|
/* Horizontal centering utility class */
|
||||||
.item-h-center {
|
.item-h-center {
|
||||||
margin: 0 auto;
|
margin: 0 auto;
|
||||||
}
|
}
|
||||||
@ -606,30 +606,30 @@ div.el-divider {
|
|||||||
line-height: 32px;
|
line-height: 32px;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* 第一个子元素 */
|
/* First child element styling in card rows */
|
||||||
.card-row-item>span:first-child,
|
.card-row-item>span:first-child,
|
||||||
.card-row-item>label:first-child {
|
.card-row-item>label:first-child {
|
||||||
align-self: start;
|
align-self: start;
|
||||||
width: 100px;
|
width: 100px;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* 第二个子元素是span时 */
|
/* Second child span element styling */
|
||||||
.card-row-item>span:nth-child(2) {
|
.card-row-item>span:nth-child(2) {
|
||||||
width: 240px;
|
width: 240px;
|
||||||
padding-left: 12px;
|
padding-left: 12px;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* 第二个子元素是p时 */
|
/* Second child paragraph element styling */
|
||||||
.card-row-item>p:nth-child(2) {
|
.card-row-item>p:nth-child(2) {
|
||||||
padding: 5px 12px;
|
padding: 5px 12px;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* 第二个子元素 */
|
/* General second child element styling */
|
||||||
.card-row-item>*:nth-child(2) {
|
.card-row-item>*:nth-child(2) {
|
||||||
width: 240px;
|
width: 240px;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* 第二个子元素 独占一行时 */
|
/* Full-width modifier for second child elements */
|
||||||
.card-row-item.wp-100>*:nth-child(2) {
|
.card-row-item.wp-100>*:nth-child(2) {
|
||||||
width: calc(100% - 100px);
|
width: calc(100% - 100px);
|
||||||
}
|
}
|
||||||
@ -639,7 +639,7 @@ div.el-divider {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* card行-无数据
|
* No data placeholder styling
|
||||||
*/
|
*/
|
||||||
.card-item-no-data {
|
.card-item-no-data {
|
||||||
width: 100%;
|
width: 100%;
|
||||||
@ -666,17 +666,17 @@ div.el-divider {
|
|||||||
margin: -8px -14px;
|
margin: -8px -14px;
|
||||||
}
|
}
|
||||||
|
|
||||||
/** 全屏视频背景包装模块 */
|
/** Full-screen video background container */
|
||||||
.video-bg-wrap {
|
.video-bg-wrap {
|
||||||
position: relative;
|
position: relative;
|
||||||
width: 100%;
|
width: 100%;
|
||||||
height: 100vh;
|
height: 100vh;
|
||||||
/** 可设置背景在视频加载前或失败时做显示 设置为深色 */
|
/* Fallback background for video */
|
||||||
background: #000 url('') no-repeat fixed center center / cover;
|
background: #000 url('') no-repeat fixed center center / cover;
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
}
|
}
|
||||||
|
|
||||||
/** 全屏视频背景包装模块-视频样式 */
|
/** Video element styling */
|
||||||
.video-bg-wrap video {
|
.video-bg-wrap video {
|
||||||
z-index: 0;
|
z-index: 0;
|
||||||
position: absolute;
|
position: absolute;
|
||||||
@ -687,26 +687,24 @@ div.el-divider {
|
|||||||
object-fit: fill;
|
object-fit: fill;
|
||||||
}
|
}
|
||||||
|
|
||||||
/** 全屏视频背景包装模块-前台内容样式 */
|
/** Front content overlay for video background */
|
||||||
.video-bg-wrap .front {
|
.video-bg-wrap .front {
|
||||||
z-index: 1;
|
z-index: 1;
|
||||||
/* 设置子元素为绝对定位 */
|
/* Set children to be absolute positioned */
|
||||||
position: absolute;
|
position: absolute;
|
||||||
/* 子元素顶部距离父元素顶部的距离为50% */
|
/* Center content */
|
||||||
top: 50%;
|
top: 50%;
|
||||||
/* 子元素左侧距离父元素左侧的距离为50% */
|
|
||||||
left: 50%;
|
left: 50%;
|
||||||
/* 使用transform进行微调,将子元素居中 */
|
|
||||||
transform: translate(-50%, -50%);
|
transform: translate(-50%, -50%);
|
||||||
/* background-color: rgb(255, 255, 255, 0.9); */
|
/* background-color: rgb(255, 255, 255, 0.9); */
|
||||||
/* 背景模糊 */
|
/* Blur background */
|
||||||
backdrop-filter: blur(10px);
|
backdrop-filter: blur(10px);
|
||||||
/* opacity: 0.8; */
|
/* opacity: 0.8; */
|
||||||
border-radius: 6px;
|
border-radius: 6px;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 色彩标签
|
* Color labels
|
||||||
*/
|
*/
|
||||||
.color-label {
|
.color-label {
|
||||||
padding: 2px 6px;
|
padding: 2px 6px;
|
||||||
@ -714,7 +712,7 @@ div.el-divider {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 布局管理器遮挡层
|
* Modal layer for layout manager
|
||||||
*/
|
*/
|
||||||
.layout-shade {
|
.layout-shade {
|
||||||
position: fixed;
|
position: fixed;
|
||||||
@ -751,7 +749,7 @@ div.el-divider {
|
|||||||
}
|
}
|
||||||
|
|
||||||
.adv-search {
|
.adv-search {
|
||||||
/** 自动高度过渡动画 */
|
/** Height transitions for height */
|
||||||
display: grid;
|
display: grid;
|
||||||
grid-template-rows: 0fr;
|
grid-template-rows: 0fr;
|
||||||
transition: grid-template-rows 0.3s ease-in-out;
|
transition: grid-template-rows 0.3s ease-in-out;
|
||||||
@ -766,7 +764,7 @@ div.el-divider {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 背景颜色
|
* Background colors
|
||||||
*/
|
*/
|
||||||
.bg-primary {
|
.bg-primary {
|
||||||
background-color: var(--el-color-primary);
|
background-color: var(--el-color-primary);
|
||||||
@ -789,43 +787,43 @@ div.el-divider {
|
|||||||
color: transparent;
|
color: transparent;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* 定义文字渐变色动画 */
|
/* Color cycling animation for text */
|
||||||
@keyframes text-color-change {
|
@keyframes text-color-change {
|
||||||
0% {
|
0% {
|
||||||
color: #ff3334;
|
color: #ff3334;
|
||||||
/* 动画开始时的颜色 */
|
/* Color for beginning of animation */
|
||||||
}
|
}
|
||||||
|
|
||||||
20% {
|
20% {
|
||||||
color: #ffcf00;
|
color: #ffcf00;
|
||||||
/* 动画中间时的颜色 */
|
/* Color for middle of animation */
|
||||||
}
|
}
|
||||||
|
|
||||||
40% {
|
40% {
|
||||||
color: #66ccff;
|
color: #66ccff;
|
||||||
/* 动画中间时的颜色 */
|
/* Color for middle of animation */
|
||||||
}
|
}
|
||||||
|
|
||||||
60% {
|
60% {
|
||||||
color: #ff3399;
|
color: #ff3399;
|
||||||
/* 动画中间时的颜色 */
|
/* Color for middle of animation */
|
||||||
}
|
}
|
||||||
|
|
||||||
80% {
|
80% {
|
||||||
color: #9933ff;
|
color: #9933ff;
|
||||||
/* 动画中间时的颜色 */
|
/* Color for middle of animation */
|
||||||
}
|
}
|
||||||
|
|
||||||
100% {
|
100% {
|
||||||
color: #19e713;
|
color: #19e713;
|
||||||
/* 动画结束时的颜色 */
|
/* Color for ending of animation */
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* 应用动画到元素 */
|
/* Animated text element */
|
||||||
.animated-text {
|
.animated-text {
|
||||||
animation: text-color-change 2s infinite alternate;
|
animation: text-color-change 2s infinite alternate;
|
||||||
/* 动画名称,持续时间,循环次数,方向 */
|
/* Animation name, duration, iteration count, direction */
|
||||||
}
|
}
|
||||||
|
|
||||||
@keyframes hue {
|
@keyframes hue {
|
||||||
|
@ -1,16 +1,14 @@
|
|||||||
import utils from '@/assets/js/utils'
|
|
||||||
import { ReadAll } from '@/../wailsjs/go/main/App.js'
|
import { ReadAll } from '@/../wailsjs/go/main/App.js'
|
||||||
|
import utils from '@/assets/js/utils'
|
||||||
|
|
||||||
// 临时缓存文件信息
|
// Temporary cache for file information
|
||||||
function cache(fileObj, $event) {
|
function cache(fileObj, $event) {
|
||||||
console.log('cache fileObj start:', fileObj, $event.target, $event.dataTransfer)
|
console.log('Caching fileObj start:', fileObj, $event.target, $event.dataTransfer)
|
||||||
console.log('typeof fileObj:', Array.isArray(fileObj))
|
console.log('typeof fileObj:', Array.isArray(fileObj))
|
||||||
// 如果fileObj是数组,创建一个新的元素,追加到数组
|
// If fileObj is an array, create new element and append to array
|
||||||
// event.target.files和event.dataTransfer.files是JavaScript中与文件上传和拖放相关的事件属性。
|
// event.target.files and event.dataTransfer.files are properties related to file upload and drag-drop events
|
||||||
// event.target.files:这个属性是在HTML的文件输入元素(<input type="file">)上使用时,
|
// event.target.files: Used with <input type="file"> elements, contains list of files selected via change event
|
||||||
// 当用户选择文件并触发change事件时,可以通过event.target.files获取到用户选择的文件列表。
|
// event.dataTransfer.files: Contains list of files dropped onto an element via drag-drop event
|
||||||
// event.dataTransfer.files:这个属性是在用户拖放文件到一个元素上时,
|
|
||||||
// 可以通过event.dataTransfer.files获取到拖放的文件列表。
|
|
||||||
console.log('$event:', $event, $event.type)
|
console.log('$event:', $event, $event.type)
|
||||||
let files
|
let files
|
||||||
if ($event.type == 'change') {
|
if ($event.type == 'change') {
|
||||||
@ -18,36 +16,36 @@ function cache(fileObj, $event) {
|
|||||||
} else if ($event.type == 'drop') {
|
} else if ($event.type == 'drop') {
|
||||||
files = $event.dataTransfer.files
|
files = $event.dataTransfer.files
|
||||||
} else {
|
} else {
|
||||||
console.error("无法识别的事件")
|
console.error("Unrecognized event type")
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
const file = files[0]
|
const file = files[0]
|
||||||
console.log("file:", file)
|
console.log("Selected file:", file)
|
||||||
const fileInfo = Array.isArray(fileObj) ? new Object() : fileObj
|
const fileInfo = Array.isArray(fileObj) ? new Object() : fileObj
|
||||||
fileInfo.file = file
|
fileInfo.file = file
|
||||||
let URL = window.URL || window.webkitURL
|
let URL = window.URL || window.webkitURL
|
||||||
fileInfo.fileUrl = URL.createObjectURL(file)
|
fileInfo.fileUrl = URL.createObjectURL(file)
|
||||||
const fileType = file.type
|
const fileType = file.type
|
||||||
console.log(fileType, typeof (fileType))
|
console.log("File type:", fileType, typeof (fileType))
|
||||||
if (utils.notNull(fileType) && fileType.startsWith("image")) {
|
if (utils.notNull(fileType) && fileType.startsWith("image")) {
|
||||||
fileInfo.imgUrl = fileInfo.fileUrl
|
fileInfo.imgUrl = fileInfo.fileUrl
|
||||||
}
|
}
|
||||||
fileInfo.fileName = file.name
|
fileInfo.fileName = file.name
|
||||||
console.log('cache fileObj end:', fileInfo)
|
console.log('Caching fileObj completed:', fileInfo)
|
||||||
if (Array.isArray(fileObj)) {
|
if (Array.isArray(fileObj)) {
|
||||||
// 操作成功后追加到数组末尾
|
// Append to array after successful operation
|
||||||
fileObj.push(fileInfo)
|
fileObj.push(fileInfo)
|
||||||
}
|
}
|
||||||
if ($event.type == 'change') {
|
if ($event.type == 'change') {
|
||||||
// 解决选择相同的文件 不触发change事件的问题,放在最后清理
|
// Clear input to allow reselecting same file
|
||||||
$event.target.value = null
|
$event.target.value = null
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// 上传文件
|
// Upload file
|
||||||
async function upload(fileObj) {
|
async function upload(fileObj) {
|
||||||
console.log("准备开始上传文件!", fileObj, fileObj.file, fileObj.fileId)
|
console.log("Preparing to upload file...", fileObj, fileObj.file, fileObj.fileId)
|
||||||
// 当前地址
|
// Current location handling
|
||||||
if (utils.isNull(fileObj.file)) {
|
if (utils.isNull(fileObj.file)) {
|
||||||
if (utils.notNull(fileObj.fileId) && fileObj.remark != fileObj.remarkUpd) {
|
if (utils.notNull(fileObj.fileId) && fileObj.remark != fileObj.remarkUpd) {
|
||||||
let remark = null
|
let remark = null
|
||||||
@ -58,7 +56,7 @@ async function upload(fileObj) {
|
|||||||
}
|
}
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
console.log("开始上传文件!", fileObj, fileObj.file, fileObj.fileId)
|
console.log("Starting file upload...", fileObj, fileObj.file, fileObj.fileId)
|
||||||
const url = '/common/file/upload'
|
const url = '/common/file/upload'
|
||||||
const formData = new FormData()
|
const formData = new FormData()
|
||||||
formData.append('file', fileObj.file)
|
formData.append('file', fileObj.file)
|
||||||
@ -73,38 +71,38 @@ async function upload(fileObj) {
|
|||||||
}
|
}
|
||||||
})
|
})
|
||||||
Object.assign(fileObj, data)
|
Object.assign(fileObj, data)
|
||||||
console.log("文件同步上传处理完毕", fileObj)
|
console.log("File upload processed successfully", fileObj)
|
||||||
return fileObj
|
return fileObj
|
||||||
}
|
}
|
||||||
|
|
||||||
// 更新文件备注
|
// Update file remark
|
||||||
async function updRemark(fileId, remarkUpd) {
|
async function updRemark(fileId, remarkUpd) {
|
||||||
const param = {
|
const param = {
|
||||||
fileId: fileId,
|
fileId: fileId,
|
||||||
remark: remarkUpd
|
remark: remarkUpd
|
||||||
}
|
}
|
||||||
await utils.awaitPost('/common/file/updRemark', param)
|
await utils.awaitPost('/common/file/updRemark', param)
|
||||||
console.log("更新文件备注成功")
|
console.log("File remark updated successfully")
|
||||||
}
|
}
|
||||||
|
|
||||||
// 批量上传文件
|
// Batch upload files
|
||||||
async function uploads(fileObjs) {
|
async function uploads(fileObjs) {
|
||||||
if (utils.isEmpty(fileObjs)) {
|
if (utils.isEmpty(fileObjs)) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
for (let index in fileObjs) {
|
for (let index in fileObjs) {
|
||||||
console.log('fileObjs[index]:', fileObjs, index, fileObjs.length, fileObjs[index])
|
console.log('Processing file object:', fileObjs, index, fileObjs.length, fileObjs[index])
|
||||||
await upload(fileObjs[index])
|
await upload(fileObjs[index])
|
||||||
console.log("uploads index:", index, "上传文件完毕", fileObjs[index])
|
console.log("Upload completed for index:", index, fileObjs[index])
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// 上传文件(onChange时)
|
// Handle file upload (onChange event)
|
||||||
function upOnChg(fileObj, $event) {
|
function upOnChg(fileObj, $event) {
|
||||||
const file = $event.target.files[0] || $event.dataTransfer.files[0]
|
const file = $event.target.files[0] || $event.dataTransfer.files[0]
|
||||||
// 当前地址
|
// Current location
|
||||||
let URL = window.URL || window.webkitURL
|
let URL = window.URL || window.webkitURL
|
||||||
// 转成 blob地址
|
// Convert to blob URL
|
||||||
fileObj.fileUrl = URL.createObjectURL(file)
|
fileObj.fileUrl = URL.createObjectURL(file)
|
||||||
const url = '/common/file/upload'
|
const url = '/common/file/upload'
|
||||||
const formData = new FormData()
|
const formData = new FormData()
|
||||||
@ -115,12 +113,13 @@ function upOnChg(fileObj, $event) {
|
|||||||
'Content-Type': 'multipart/form-data'
|
'Content-Type': 'multipart/form-data'
|
||||||
}
|
}
|
||||||
}).then((data) => {
|
}).then((data) => {
|
||||||
console.log("文件上传结果:", data)
|
console.log("File upload result:", data)
|
||||||
Object.assign(fileObj, data)
|
Object.assign(fileObj, data)
|
||||||
fileObj.remarkUpd = data.remark
|
fileObj.remarkUpd = data.remark
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Add to component list
|
||||||
function add(fileList) {
|
function add(fileList) {
|
||||||
const comp = {
|
const comp = {
|
||||||
index: fileList.length,
|
index: fileList.length,
|
||||||
@ -134,8 +133,9 @@ function add(fileList) {
|
|||||||
fileList.push(comp)
|
fileList.push(comp)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Remove component from list
|
||||||
function del(fileObj, index) {
|
function del(fileObj, index) {
|
||||||
console.log("fileObj,index:", fileObj, index)
|
console.log("Deleting file object:", fileObj, index)
|
||||||
if (Array.isArray(fileObj)) {
|
if (Array.isArray(fileObj)) {
|
||||||
fileObj.splice(index, 1)
|
fileObj.splice(index, 1)
|
||||||
} else {
|
} else {
|
||||||
@ -143,11 +143,12 @@ function del(fileObj, index) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Convert between Java and JS file objects
|
||||||
function trans(javaFile, jsFile) {
|
function trans(javaFile, jsFile) {
|
||||||
if (jsFile == undefined || jsFile == null) {
|
if (jsFile == undefined || jsFile == null) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
// 如果是数组,先清空数组
|
// Clear array if present
|
||||||
if (jsFile instanceof Array) {
|
if (jsFile instanceof Array) {
|
||||||
jsFile.splice(0, jsFile.length)
|
jsFile.splice(0, jsFile.length)
|
||||||
} else {
|
} else {
|
||||||
@ -157,7 +158,7 @@ function trans(javaFile, jsFile) {
|
|||||||
if (javaFile == undefined || javaFile == null) {
|
if (javaFile == undefined || javaFile == null) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
// 数组类型
|
// Handle array type
|
||||||
if (jsFile instanceof Array) {
|
if (jsFile instanceof Array) {
|
||||||
for (let java of javaFile) {
|
for (let java of javaFile) {
|
||||||
const js = {}
|
const js = {}
|
||||||
@ -166,41 +167,40 @@ function trans(javaFile, jsFile) {
|
|||||||
jsFile.push(js)
|
jsFile.push(js)
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
// 对象类型
|
// Handle object type
|
||||||
console.log("对象类型", jsFile instanceof Array)
|
console.log("Object type conversion", jsFile instanceof Array)
|
||||||
javaFile.remarkUpd = javaFile.remark
|
javaFile.remarkUpd = javaFile.remark
|
||||||
Object.assign(jsFile, javaFile)
|
Object.assign(jsFile, javaFile)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// 从Comps中收集fileId
|
// Collect file IDs from components
|
||||||
function fileIds(fileList) {
|
function fileIds(fileList) {
|
||||||
return fileList.map(comp => comp.fileId).join(',')
|
return fileList.map(comp => comp.fileId).join(',')
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Read file contents
|
||||||
function readAll(filePath) {
|
function readAll(filePath) {
|
||||||
return ReadAll(filePath)
|
return ReadAll(filePath)
|
||||||
}
|
}
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
// onChange时缓存
|
// Cache on change event
|
||||||
cache,
|
cache,
|
||||||
// 上传文件
|
// Single file upload
|
||||||
upload,
|
upload,
|
||||||
// 上传文件
|
// Batch file upload
|
||||||
uploads,
|
uploads,
|
||||||
// 上传文件
|
// Immediate upload on change
|
||||||
upOnChg,
|
upOnChg,
|
||||||
// onChange时上传
|
// Add component
|
||||||
upOnChg,
|
|
||||||
// 添加到组件列表
|
|
||||||
add,
|
add,
|
||||||
// 从组件列表中删除组件
|
// Remove component
|
||||||
del,
|
del,
|
||||||
// 文件Java对象与js对象转换
|
// Object conversion
|
||||||
trans,
|
trans,
|
||||||
// 从Comps中收集fileId
|
// Collect file IDs
|
||||||
fileIds,
|
fileIds,
|
||||||
// 读取文件
|
// Read file
|
||||||
readAll
|
readAll
|
||||||
}
|
}
|
@ -1,7 +1,7 @@
|
|||||||
import { useEventListener } from '@vueuse/core'
|
import { useEventListener } from '@vueuse/core'
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* 显示页面遮罩
|
* Show page shade
|
||||||
*/
|
*/
|
||||||
export const showShade = function (closeCallBack) {
|
export const showShade = function (closeCallBack) {
|
||||||
const className = 'shade'
|
const className = 'shade'
|
||||||
@ -13,7 +13,7 @@ export const showShade = function (closeCallBack) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* 隐藏页面遮罩
|
* Hide page shade
|
||||||
*/
|
*/
|
||||||
export const closeShade = function (closeCallBack = () => { }) {
|
export const closeShade = function (closeCallBack = () => { }) {
|
||||||
const shadeEl = document.querySelector('.layout-shade')
|
const shadeEl = document.querySelector('.layout-shade')
|
||||||
|
@ -1,15 +1,15 @@
|
|||||||
|
import { Greet } from '@/../wailsjs/go/main/App.js'
|
||||||
import axios from "axios"
|
import axios from "axios"
|
||||||
import { ElMessage } from 'element-plus'
|
import { ElMessage } from 'element-plus'
|
||||||
import { Greet } from '@/../wailsjs/go/main/App.js'
|
|
||||||
|
|
||||||
/** axios start */
|
/** axios start */
|
||||||
// 创建 axios 实例
|
// Create a new axios instance
|
||||||
const $axios = axios.create({
|
const $axios = axios.create({
|
||||||
baseURL: "api",
|
baseURL: "api",
|
||||||
timeout: 12000
|
timeout: 12000
|
||||||
})
|
})
|
||||||
|
|
||||||
// 请求拦截器
|
// Request interceptors
|
||||||
$axios.interceptors.request.use(
|
$axios.interceptors.request.use(
|
||||||
(config) => {
|
(config) => {
|
||||||
config.headers["token"] = ''
|
config.headers["token"] = ''
|
||||||
@ -27,24 +27,24 @@ $axios.interceptors.request.use(
|
|||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|
||||||
// 响应拦截器
|
// Response interceptors
|
||||||
$axios.interceptors.response.use(
|
$axios.interceptors.response.use(
|
||||||
(response) => {
|
(response) => {
|
||||||
// console.log("response:", response)
|
// console.log("response:", response)
|
||||||
if (response.status == 200) {
|
if (response.status == 200) {
|
||||||
return response.data
|
return response.data
|
||||||
} else {
|
} else {
|
||||||
pop("请求错误:" + response.status)
|
pop("Exception occurred in response:" + response.status)
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
(error) => {
|
(error) => {
|
||||||
console.log("error:" + JSON.stringify(error))
|
console.log("error:" + JSON.stringify(error))
|
||||||
if (error.response == undefined || error.response == null) {
|
if (error.response == undefined || error.response == null) {
|
||||||
pop("未知请求错误!")
|
pop("Unknown request error!")
|
||||||
} else if (error.response.status == 500) {
|
} else if (error.response.status == 500) {
|
||||||
pop("请求后台服务异常,请稍后重试!")
|
pop("Unable to communicate with backend, please retry later!")
|
||||||
} else {
|
} else {
|
||||||
pop("请求错误:" + error)
|
pop("Request error:" + error)
|
||||||
}
|
}
|
||||||
return Promise.reject(error)
|
return Promise.reject(error)
|
||||||
}
|
}
|
||||||
@ -75,7 +75,7 @@ async function awaitDel(url, param) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* demo 调用 go 接口
|
* demo call Go interfaces
|
||||||
*/
|
*/
|
||||||
function greet(name) {
|
function greet(name) {
|
||||||
return Greet(name).then(resp => {
|
return Greet(name).then(resp => {
|
||||||
@ -85,78 +85,80 @@ function greet(name) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 判断对象为空
|
* Identify whether the object is null
|
||||||
*/
|
*/
|
||||||
function isNull(obj) {
|
function isNull(obj) {
|
||||||
return obj == undefined || obj == null
|
return obj == undefined || obj == null
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 判断对象非空
|
* Identify whether the object is not null
|
||||||
*/
|
*/
|
||||||
function notNull(obj) {
|
function notNull(obj) {
|
||||||
return obj != undefined && obj != null
|
return obj != undefined && obj != null
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 判断空字符串
|
* Identify an empty string
|
||||||
*/
|
*/
|
||||||
function isBlank(str) {
|
function isBlank(str) {
|
||||||
return str == undefined || str == null || /^s*$/.test(str)
|
return str == undefined || str == null || /^s*$/.test(str)
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 判断不为空字符串
|
* Identify a non-empty string
|
||||||
*/
|
*/
|
||||||
function notBlank(str) {
|
function notBlank(str) {
|
||||||
return !isBlank(str)
|
return !isBlank(str)
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 判断数组为空
|
* Identify an empty array
|
||||||
*/
|
*/
|
||||||
function isEmpty(arr) {
|
function isEmpty(arr) {
|
||||||
return arr == undefined || arr == null || (arr instanceof Array && arr.length == 0)
|
return arr == undefined || arr == null || (arr instanceof Array && arr.length == 0)
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 判断数组非空
|
* Identify a non-empty array
|
||||||
*/
|
*/
|
||||||
function notEmpty(arr) {
|
function notEmpty(arr) {
|
||||||
return arr != undefined && arr != null && arr instanceof Array && arr.length > 0
|
return arr != undefined && arr != null && arr instanceof Array && arr.length > 0
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 判断对象为true
|
* Identify true
|
||||||
*/
|
*/
|
||||||
function isTrue(obj) {
|
function isTrue(obj) {
|
||||||
return obj == true || obj == 'true'
|
return obj == true || obj == 'true'
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 判断对象为false
|
* Identify false
|
||||||
*/
|
*/
|
||||||
function isFalse(obj) {
|
function isFalse(obj) {
|
||||||
return !isTrue(obj)
|
return !isTrue(obj)
|
||||||
}
|
}
|
||||||
|
/**
|
||||||
/** 获取字符串中某字符的个数
|
* Get count of a specific character in a string
|
||||||
* @param {string} str - 要搜索的字符串
|
* @param {string} str - String to search
|
||||||
* @param {string} char - 要查找的字符
|
* @param {string} char - Character to find
|
||||||
* @returns {number} - 字符在字符串中出现的次数
|
* @returns {number} - Occurrence count
|
||||||
*/
|
*/
|
||||||
function getCharCount(str, char) {
|
function getCharCount(str, char) {
|
||||||
// 使用g表示整个字符串都要匹配
|
// g=match globally
|
||||||
var regex = new RegExp(char, 'g')
|
var regex = new RegExp(char, 'g')
|
||||||
// match方法可在字符串内检索指定的值,或找到一个或多个正则表达式的匹配
|
// Search for all occurrences of the character in the string
|
||||||
var result = str.match(regex)
|
var result = str.match(regex)
|
||||||
var count = !result ? 0 : result.length
|
var count = !result ? 0 : result.length
|
||||||
return count
|
return count
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 日期格式化
|
* Format date with specified pattern
|
||||||
* 默认格式为yyyy-MM-dd HH:mm:ss
|
* @param {Date|string} date - Date object or date string
|
||||||
|
* @param {string} format - Target format pattern
|
||||||
|
* @returns {string} - Formatted date string
|
||||||
*/
|
*/
|
||||||
function dateFormat(date, format) {
|
function dateFormat(date, format) {
|
||||||
if (date == undefined || date == null || date == '') {
|
if (date == undefined || date == null || date == '') {
|
||||||
@ -187,27 +189,28 @@ function dateFormat(date, format) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 遍历对象中的日期,并进行格式化
|
* Recursively format Date properties in objects/arrays
|
||||||
|
* @param {Object} obj - Target object to process
|
||||||
*/
|
*/
|
||||||
function fomateDateProperty(obj) {
|
function fomateDateProperty(obj) {
|
||||||
for (let i in obj) {
|
for (let i in obj) {
|
||||||
//遍历对象中的属性
|
// Iterate through all properties of the object
|
||||||
if (obj[i] == null) {
|
if (obj[i] == null) {
|
||||||
continue
|
continue
|
||||||
} else if (obj[i] instanceof Date) {
|
} else if (obj[i] instanceof Date) {
|
||||||
// 格式化为yyyy-MM-dd HH:mm:ss
|
// Format as `yyyy-MM-dd HH:mm:ss`
|
||||||
obj[i] = dateFormat(obj[i])
|
obj[i] = dateFormat(obj[i])
|
||||||
} else if (obj[i].constructor === Object) {
|
} else if (obj[i].constructor === Object) {
|
||||||
//如果发现该属性的值还是一个对象,再判空后进行迭代调用
|
// Recursively format nested objects
|
||||||
if (Object.keys(obj[i]).length > 0) {
|
if (Object.keys(obj[i]).length > 0) {
|
||||||
//判断对象上是否存在属性,如果为空对象则删除
|
// Delete empty properties
|
||||||
fomateDateProperty(obj[i])
|
fomateDateProperty(obj[i])
|
||||||
}
|
}
|
||||||
} else if (obj[i].constructor === Array) {
|
} else if (obj[i].constructor === Array) {
|
||||||
//对象值如果是数组,判断是否为空数组后进入数据遍历判空逻辑
|
// Recursively clean nested arrays
|
||||||
if (obj[i].length > 0) {
|
if (obj[i].length > 0) {
|
||||||
for (let j = 0; j < obj[i].length; j++) {
|
for (let j = 0; j < obj[i].length; j++) {
|
||||||
//遍历数组
|
// Iterate through all array items
|
||||||
fomateDateProperty(obj[i][j])
|
fomateDateProperty(obj[i][j])
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -215,35 +218,37 @@ function fomateDateProperty(obj) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
// 遍历删除对象中的空值属性
|
* Remove null/empty properties recursively
|
||||||
|
* @param {Object} obj - Target object to clean
|
||||||
|
*/
|
||||||
function delNullProperty(obj) {
|
function delNullProperty(obj) {
|
||||||
for (let i in obj) {
|
for (let i in obj) {
|
||||||
//遍历对象中的属性
|
// Iterate through all properties of the object
|
||||||
if (obj[i] === undefined || obj[i] === null || obj[i] === "") {
|
if (obj[i] === undefined || obj[i] === null || obj[i] === "") {
|
||||||
//首先除去常规空数据,用delete关键字
|
// Delete general null/empty properties
|
||||||
delete obj[i]
|
delete obj[i]
|
||||||
} else if (obj[i].constructor === Object) {
|
} else if (obj[i].constructor === Object) {
|
||||||
//如果发现该属性的值还是一个对象,再判空后进行迭代调用
|
// Recursively clean nested objects
|
||||||
if (Object.keys(obj[i]).length === 0) delete obj[i]
|
if (Object.keys(obj[i]).length === 0) delete obj[i]
|
||||||
//判断对象上是否存在属性,如果为空对象则删除
|
// Delete empty properties
|
||||||
delNullProperty(obj[i])
|
delNullProperty(obj[i])
|
||||||
} else if (obj[i].constructor === Array) {
|
} else if (obj[i].constructor === Array) {
|
||||||
//对象值如果是数组,判断是否为空数组后进入数据遍历判空逻辑
|
// Recursively clean arrays
|
||||||
if (obj[i].length === 0) {
|
if (obj[i].length === 0) {
|
||||||
//如果数组为空则删除
|
// Delete empty arrays
|
||||||
delete obj[i]
|
delete obj[i]
|
||||||
} else {
|
} else {
|
||||||
for (let index = 0; index < obj[i].length; index++) {
|
for (let index = 0; index < obj[i].length; index++) {
|
||||||
//遍历数组
|
// Iterate through all array items
|
||||||
if (obj[i][index] === undefined || obj[i][index] === null || obj[i][index] === "" || JSON.stringify(obj[i][index]) === "{}") {
|
if (obj[i][index] === undefined || obj[i][index] === null || obj[i][index] === "" || JSON.stringify(obj[i][index]) === "{}") {
|
||||||
obj[i].splice(index, 1)
|
obj[i].splice(index, 1)
|
||||||
//如果数组值为以上空值则修改数组长度,移除空值下标后续值依次提前
|
// Delete null/empty array items
|
||||||
index--
|
index--
|
||||||
//由于数组当前下标内容已经被替换成下一个值,所以计数器需要自减以抵消之后的自增
|
// Do decrement to avoid skipping next item (index is now pointing to the next item)
|
||||||
}
|
}
|
||||||
if (obj[i].constructor === Object) {
|
if (obj[i].constructor === Object) {
|
||||||
//如果发现数组值中有对象,则再次进入迭代
|
// Recursively clean nested objects in array items
|
||||||
delNullProperty(obj[i])
|
delNullProperty(obj[i])
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -253,22 +258,27 @@ function delNullProperty(obj) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 弹出消息框
|
* Display message notification
|
||||||
* @param msg 消息内容
|
* @param {string} msg - Message content
|
||||||
* @param type
|
* @param {string} type - Message type (success/warning/error/etc)
|
||||||
*/
|
*/
|
||||||
function pop(msg, type) {
|
function pop(msg, type) {
|
||||||
ElMessage({ message: msg, type: type })
|
ElMessage({ message: msg, type: type })
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Show default message when no data available
|
||||||
|
* @param {*} data - Data to check
|
||||||
|
*/
|
||||||
function popNoData(data) {
|
function popNoData(data) {
|
||||||
if (data == undefined || data == null || (data instanceof Array && data.length == 0)) {
|
if (data == undefined || data == null || (data instanceof Array && data.length == 0)) {
|
||||||
ElMessage("暂无数据!")
|
ElMessage("No data available!")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 当前时间字符串
|
* Get current datetime as formatted string
|
||||||
|
* @returns {string} Current datetime in yyyy-MM-dd HH:mm format
|
||||||
*/
|
*/
|
||||||
function nowDatetimeStr() {
|
function nowDatetimeStr() {
|
||||||
const date = new Date()
|
const date = new Date()
|
||||||
@ -277,7 +287,9 @@ function nowDatetimeStr() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 构建分页
|
* Pagination structure builder
|
||||||
|
* @param {Object} source - Source pagination data
|
||||||
|
* @param {Object} target - Target pagination object
|
||||||
*/
|
*/
|
||||||
function buildPage(source, target) {
|
function buildPage(source, target) {
|
||||||
target.pageNum = source.pageNum
|
target.pageNum = source.pageNum
|
||||||
@ -287,7 +299,8 @@ function buildPage(source, target) {
|
|||||||
copyArray(source.list, target.list)
|
copyArray(source.list, target.list)
|
||||||
}
|
}
|
||||||
/**
|
/**
|
||||||
* 清空数组
|
* Clear array contents
|
||||||
|
* @param {Array} arr - Array to clear
|
||||||
*/
|
*/
|
||||||
function clearArray(arr) {
|
function clearArray(arr) {
|
||||||
if (arr == undefined || arr == null || arr.length == 0) {
|
if (arr == undefined || arr == null || arr.length == 0) {
|
||||||
@ -295,8 +308,10 @@ function clearArray(arr) {
|
|||||||
}
|
}
|
||||||
arr.splice(0, arr.length)
|
arr.splice(0, arr.length)
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 清空属性
|
* Reset object properties to null
|
||||||
|
* @param {Object} obj - Target object
|
||||||
*/
|
*/
|
||||||
function clearProps(obj) {
|
function clearProps(obj) {
|
||||||
if (obj == undefined || obj == null) {
|
if (obj == undefined || obj == null) {
|
||||||
@ -308,9 +323,11 @@ function clearProps(obj) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 复制对象属性
|
* Copy properties between objects
|
||||||
|
* @param {Object} source - Source object
|
||||||
|
* @param {Object} target - Target object
|
||||||
*/
|
*/
|
||||||
function copyProps(source, target) {
|
function copyProps(source, target = {}) {
|
||||||
if (target == undefined || target == null) {
|
if (target == undefined || target == null) {
|
||||||
target = {}
|
target = {}
|
||||||
}
|
}
|
||||||
@ -322,13 +339,15 @@ function copyProps(source, target) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
/**
|
/**
|
||||||
* 复制数组
|
* Clone array contents
|
||||||
|
* @param {Array} source - Source array
|
||||||
|
* @param {Array} target - Target array
|
||||||
*/
|
*/
|
||||||
function copyArray(source, target) {
|
function copyArray(source, target) {
|
||||||
if (target == undefined || target == null) {
|
if (target == undefined || target == null) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
// 先清空数组
|
// Clear the array first
|
||||||
if (target.length > 0) {
|
if (target.length > 0) {
|
||||||
target.splice(0, target.length)
|
target.splice(0, target.length)
|
||||||
/* while (target.length > 0) {
|
/* while (target.length > 0) {
|
||||||
@ -344,7 +363,10 @@ function copyArray(source, target) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 发生变更的属性
|
* Find changed properties between objects
|
||||||
|
* @param {Object} origin - Original object
|
||||||
|
* @param {Object} target - Modified object
|
||||||
|
* @returns {Object} Changed properties
|
||||||
*/
|
*/
|
||||||
function dfProps(origin, target) {
|
function dfProps(origin, target) {
|
||||||
if (origin == undefined || origin == null || target == undefined || target == null) {
|
if (origin == undefined || origin == null || target == undefined || target == null) {
|
||||||
@ -359,9 +381,11 @@ function dfProps(origin, target) {
|
|||||||
return dfObj
|
return dfObj
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 是否存在不同属性
|
* Check for property differences
|
||||||
|
* @param {Object} origin - Original object
|
||||||
|
* @param {Object} target - Modified object
|
||||||
|
* @returns {boolean} True if differences exist
|
||||||
*/
|
*/
|
||||||
function hasDfProps(origin, target) {
|
function hasDfProps(origin, target) {
|
||||||
const df = dfProps(origin, target)
|
const df = dfProps(origin, target)
|
||||||
@ -374,7 +398,9 @@ function hasDfProps(origin, target) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 所有字段为空
|
* Check if all object properties are null
|
||||||
|
* @param {Object} target - Object to check
|
||||||
|
* @returns {boolean} True if all properties are null
|
||||||
*/
|
*/
|
||||||
function isAllPropsNull(target) {
|
function isAllPropsNull(target) {
|
||||||
if (target == undefined || target == null) {
|
if (target == undefined || target == null) {
|
||||||
@ -437,7 +463,9 @@ function descByLabel(label) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 重试调用
|
* Retry calls
|
||||||
|
* @param {Function} method - Method to call
|
||||||
|
* @param {any} params - Method parameters that are passed to the method
|
||||||
*/
|
*/
|
||||||
function retry(method) {
|
function retry(method) {
|
||||||
const params = []
|
const params = []
|
||||||
@ -450,7 +478,10 @@ function retry(method) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 根据opts编码匹配中文
|
* Resolve label from options
|
||||||
|
* @param {string|number} keyOrVal - Key or value to resolve
|
||||||
|
* @param {Array} opts - Options array
|
||||||
|
* @returns {string} Resolved label if found, or original keyOrVal if not found
|
||||||
*/
|
*/
|
||||||
function resolveLabelFromOpts(keyOrVal, opts) {
|
function resolveLabelFromOpts(keyOrVal, opts) {
|
||||||
if (isEmpty(opts)) {
|
if (isEmpty(opts)) {
|
||||||
@ -464,7 +495,11 @@ function resolveLabelFromOpts(keyOrVal, opts) {
|
|||||||
return keyOrVal
|
return keyOrVal
|
||||||
}
|
}
|
||||||
|
|
||||||
/** 下划线转首字母小写驼峰 */
|
/**
|
||||||
|
* Underscored string to camel case string
|
||||||
|
* @param {String} underscore Underscored string
|
||||||
|
* @returns Camel case string
|
||||||
|
*/
|
||||||
function underScoreToCamelCase(underscore) {
|
function underScoreToCamelCase(underscore) {
|
||||||
if (isNull(underscore) || !underscore.includes('_')) {
|
if (isNull(underscore) || !underscore.includes('_')) {
|
||||||
return underscore
|
return underscore
|
||||||
@ -480,7 +515,12 @@ function underScoreToCamelCase(underscore) {
|
|||||||
return words.join("")
|
return words.join("")
|
||||||
}
|
}
|
||||||
|
|
||||||
/** 防抖函数 */
|
/**
|
||||||
|
* Debounce a function call
|
||||||
|
* @param {Function} func Function to debounce
|
||||||
|
* @param {Number} delay Delay in milliseconds
|
||||||
|
* @returns Debounced function
|
||||||
|
*/
|
||||||
function debounce(func, delay) {
|
function debounce(func, delay) {
|
||||||
let timer
|
let timer
|
||||||
return function () {
|
return function () {
|
||||||
@ -500,45 +540,44 @@ function stringToLines(str) {
|
|||||||
}
|
}
|
||||||
return str.split('\n')
|
return str.split('\n')
|
||||||
}
|
}
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
/**
|
/**
|
||||||
* http请求 GET请求
|
* Synchronous GET HTTP request
|
||||||
*/
|
*/
|
||||||
get,
|
get,
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* http请求, 异步等待 GET请求
|
* Asynchronous GET HTTP request (async/await)
|
||||||
*/
|
*/
|
||||||
awaitGet,
|
awaitGet,
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* http请求 POST请求
|
* Synchronous POST HTTP request
|
||||||
*/
|
*/
|
||||||
post,
|
post,
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* http请求, 异步等待 POST请求
|
* Asynchronous POST HTTP request (async/await)
|
||||||
*/
|
*/
|
||||||
awaitPost,
|
awaitPost,
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* http请求 DELETE请求
|
* Synchronous DELETE HTTP request
|
||||||
*/
|
*/
|
||||||
del,
|
del,
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* http请求, 异步等待 DELETE请求
|
* Asynchronous DELETE HTTP request (async/await)
|
||||||
*/
|
*/
|
||||||
awaitDel,
|
awaitDel,
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 判断对象为空
|
* Checks if a value is null/undefined
|
||||||
*/
|
*/
|
||||||
isNull,
|
isNull,
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 判断对象非空
|
* Verifies a value is not null/undefined
|
||||||
*/
|
*/
|
||||||
notNull,
|
notNull,
|
||||||
|
|
||||||
@ -547,12 +586,12 @@ export default {
|
|||||||
notBlank,
|
notBlank,
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 判断数组为空
|
* Checks if an array is empty
|
||||||
*/
|
*/
|
||||||
isEmpty,
|
isEmpty,
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 判断数组非空
|
* Verifies an array contains elements
|
||||||
*/
|
*/
|
||||||
notEmpty,
|
notEmpty,
|
||||||
|
|
||||||
@ -563,64 +602,62 @@ export default {
|
|||||||
getCharCount,
|
getCharCount,
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 弹出消息提示
|
* Displays a toast notification
|
||||||
*/
|
*/
|
||||||
pop,
|
pop,
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 判定数据是否为空, 如果为空则提示暂无数据
|
* Shows "No data" notification for empty datasets
|
||||||
*/
|
*/
|
||||||
popNoData,
|
popNoData,
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 遍历删除对象中的空值属性
|
* Removes null/undefined properties from an object
|
||||||
*/
|
*/
|
||||||
delNullProperty,
|
delNullProperty,
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
* Gets current datetime as formatted string (YYYY-MM-DD HH:mm:ss)
|
||||||
* 当前时间字符串
|
|
||||||
*/
|
*/
|
||||||
nowDatetimeStr,
|
nowDatetimeStr,
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 构建分页
|
* Constructs pagination parameters
|
||||||
*/
|
*/
|
||||||
buildPage,
|
buildPage,
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 清空数组
|
* Clears all elements from an array
|
||||||
*/
|
*/
|
||||||
clearArray,
|
clearArray,
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 清空属性
|
* Resets object properties to null/undefined
|
||||||
*/
|
*/
|
||||||
clearProps,
|
clearProps,
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 复制对象属性
|
* Copies properties between objects
|
||||||
*/
|
*/
|
||||||
copyProps,
|
copyProps,
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 复制数组
|
* Creates a shallow array copy
|
||||||
*/
|
*/
|
||||||
copyArray,
|
copyArray,
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 日期格式化
|
* Formats Date object to string (customizable format)
|
||||||
* 默认格式为yyyy-MM-dd HH:mm:ss
|
|
||||||
*/
|
*/
|
||||||
dateFormat,
|
dateFormat,
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 遍历对象中的日期,并进行格式化
|
* Formats Date properties in objects to strings
|
||||||
*/
|
*/
|
||||||
fomateDateProperty,
|
fomateDateProperty,
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 发生变更的属性
|
* Tracks changed properties between object states
|
||||||
*/
|
*/
|
||||||
dfProps,
|
dfProps,
|
||||||
|
|
||||||
@ -633,7 +670,7 @@ export default {
|
|||||||
descByLabel,
|
descByLabel,
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 重试调用
|
* Retries failed operations with attempts
|
||||||
*/
|
*/
|
||||||
retry,
|
retry,
|
||||||
|
|
||||||
|
@ -1,15 +1,15 @@
|
|||||||
import utils from '@/assets/js/utils'
|
import utils from '@/assets/js/utils'
|
||||||
|
|
||||||
/** 英文编码正则 */
|
/** Regex for English letters, numbers, and underscores */
|
||||||
const codeReg = /^[A-Za-z0-9_\-\.]+$/
|
const codeReg = /^[A-Za-z0-9_\-\.]+$/
|
||||||
|
|
||||||
/** 手机号正则 */
|
/** Regex for mobile phone number in China (Mainland) */
|
||||||
const mobileReg = /^1[3456789]\d{9}$/
|
const mobileReg = /^1[3456789]\d{9}$/
|
||||||
|
|
||||||
/** 大陆身份证正则 */
|
/** Regex for ID card number in China (Mainland) */
|
||||||
const idNoReg = /^(^[1-9]\d{7}((0\d)|(1[0-2]))(([0|1|2]\d)|3[0-1])\d{3}$)|(^[1-9]\d{5}[1-9]\d{3}((0\d)|(1[0-2]))(([0|1|2]\d)|3[0-1])((\d{4})|\d{3}[Xx])$)$/
|
const idNoReg = /^(^[1-9]\d{7}((0\d)|(1[0-2]))(([0|1|2]\d)|3[0-1])\d{3}$)|(^[1-9]\d{5}[1-9]\d{3}((0\d)|(1[0-2]))(([0|1|2]\d)|3[0-1])((\d{4})|\d{3}[Xx])$)$/
|
||||||
|
|
||||||
/** email正则 */
|
/** Regex for email */
|
||||||
const emailReg = /^[a-zA-Z0-9_-]+@[a-zA-Z0-9_-]+(\.[a-zA-Z0-9_-]+)+$/
|
const emailReg = /^[a-zA-Z0-9_-]+@[a-zA-Z0-9_-]+(\.[a-zA-Z0-9_-]+)+$/
|
||||||
|
|
||||||
const commonValidator = (rule, value, callback) => {
|
const commonValidator = (rule, value, callback) => {
|
||||||
@ -22,7 +22,7 @@ const commonValidator = (rule, value, callback) => {
|
|||||||
|
|
||||||
const notBlankValidator = (rule, value, callback) => {
|
const notBlankValidator = (rule, value, callback) => {
|
||||||
if (utils.isBlank(value)) {
|
if (utils.isBlank(value)) {
|
||||||
callback(new Error('输入不能为空'))
|
callback(new Error('Input cannot be blank'))
|
||||||
} else {
|
} else {
|
||||||
callback()
|
callback()
|
||||||
}
|
}
|
||||||
@ -32,7 +32,7 @@ const nameValidator = (rule, value, callback) => {
|
|||||||
if (utils.isBlank(value)) {
|
if (utils.isBlank(value)) {
|
||||||
callback()
|
callback()
|
||||||
} else if (value.length > 50) {
|
} else if (value.length > 50) {
|
||||||
callback(new Error('字符数不能超过50'))
|
callback(new Error('Name too long (max 50 characters)'))
|
||||||
} else {
|
} else {
|
||||||
callback()
|
callback()
|
||||||
}
|
}
|
||||||
@ -42,7 +42,7 @@ const mobileValidator = (rule, value, callback) => {
|
|||||||
if (utils.isNull(value)) {
|
if (utils.isNull(value)) {
|
||||||
callback()
|
callback()
|
||||||
} else if (!mobileReg.test(value)) {
|
} else if (!mobileReg.test(value)) {
|
||||||
callback(new Error('手机号格式错误'))
|
callback(new Error('Invalid mobile number'))
|
||||||
} else {
|
} else {
|
||||||
callback()
|
callback()
|
||||||
}
|
}
|
||||||
@ -52,7 +52,7 @@ const idNoValidator = (rule, value, callback) => {
|
|||||||
if (utils.isNull(value)) {
|
if (utils.isNull(value)) {
|
||||||
callback()
|
callback()
|
||||||
} else if (!idNoReg.test(value)) {
|
} else if (!idNoReg.test(value)) {
|
||||||
callback(new Error('手机号格式错误'))
|
callback(new Error('Invalid ID card number'))
|
||||||
} else {
|
} else {
|
||||||
callback()
|
callback()
|
||||||
}
|
}
|
||||||
@ -62,7 +62,7 @@ const emailValidator = (rule, value, callback) => {
|
|||||||
if (utils.isNull(value)) {
|
if (utils.isNull(value)) {
|
||||||
callback()
|
callback()
|
||||||
} else if (!emailReg.test(value)) {
|
} else if (!emailReg.test(value)) {
|
||||||
callback(new Error('手机号格式错误'))
|
callback(new Error('Invalid email address'))
|
||||||
} else {
|
} else {
|
||||||
callback()
|
callback()
|
||||||
}
|
}
|
||||||
@ -72,7 +72,7 @@ const codeValidator = (rule, value, callback) => {
|
|||||||
if (utils.isBlank(value)) {
|
if (utils.isBlank(value)) {
|
||||||
callback()
|
callback()
|
||||||
} else if (!codeReg.test(value)) {
|
} else if (!codeReg.test(value)) {
|
||||||
callback(new Error('编码格式错误'))
|
callback(new Error('Invalid code format'))
|
||||||
} else {
|
} else {
|
||||||
callback()
|
callback()
|
||||||
}
|
}
|
||||||
@ -82,7 +82,7 @@ const intValidator = (rule, value, callback) => {
|
|||||||
if (utils.isBlank(value)) {
|
if (utils.isBlank(value)) {
|
||||||
callback()
|
callback()
|
||||||
} else if (!Number.isInteger(value)) {
|
} else if (!Number.isInteger(value)) {
|
||||||
callback(new Error('请输入整数'))
|
callback(new Error('Input must be an integer'))
|
||||||
} else {
|
} else {
|
||||||
callback()
|
callback()
|
||||||
}
|
}
|
||||||
@ -92,7 +92,7 @@ function validator() {
|
|||||||
console.log("arguments:", arguments)
|
console.log("arguments:", arguments)
|
||||||
if (arguments.length <= 1) {
|
if (arguments.length <= 1) {
|
||||||
const type = arguments[0]
|
const type = arguments[0]
|
||||||
// 默认校验逻辑, 不含有特殊字符
|
// Generic validators
|
||||||
if (utils.isBlank(type)) {
|
if (utils.isBlank(type)) {
|
||||||
return commonValidator
|
return commonValidator
|
||||||
} else if (type == 'notBlank') {
|
} else if (type == 'notBlank') {
|
||||||
@ -113,22 +113,22 @@ function validator() {
|
|||||||
return commonValidator
|
return commonValidator
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// 复合校验器
|
// Complex validators
|
||||||
const complexValidator = (rule, value, callback) => {
|
const complexValidator = (rule, value, callback) => {
|
||||||
for (let i = 0; i < arguments.length; i++) {
|
for (let i = 0; i < arguments.length; i++) {
|
||||||
const typeStr = arguments[i]
|
const typeStr = arguments[i]
|
||||||
if (typeStr == 'notBlank' && utils.isBlank(value)) {
|
if (typeStr == 'notBlank' && utils.isBlank(value)) {
|
||||||
callback(new Error('输入不能为空'))
|
callback(new Error('Input cannot be blank'))
|
||||||
break
|
break
|
||||||
} else if (typeStr == 'code' && !codeReg.test(value)) {
|
} else if (typeStr == 'code' && !codeReg.test(value)) {
|
||||||
callback(new Error('编码格式错误'))
|
callback(new Error('Invalid code format'))
|
||||||
break
|
break
|
||||||
} else if (typeStr == 'int' && Number.isInteger(value)) {
|
} else if (typeStr == 'int' && Number.isInteger(value)) {
|
||||||
callback(new Error('请输入整数'))
|
callback(new Error('In'))
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// 兜底callback()只会触发一次
|
// Ensure callback is called at least once
|
||||||
callback()
|
callback()
|
||||||
}
|
}
|
||||||
return complexValidator
|
return complexValidator
|
||||||
@ -138,62 +138,62 @@ export default {
|
|||||||
|
|
||||||
username: (username) => {
|
username: (username) => {
|
||||||
if (typeof (username) == "undefined" || username == null) {
|
if (typeof (username) == "undefined" || username == null) {
|
||||||
return "账号不能为空"
|
return "Username cannot be blank"
|
||||||
}
|
}
|
||||||
username = username.trim()
|
username = username.trim()
|
||||||
if (username.length < 4) {
|
if (username.length < 4) {
|
||||||
return "账号字符不能小于4位"
|
return "Username must be at least 4 characters long"
|
||||||
}
|
}
|
||||||
if (username.length > 20) {
|
if (username.length > 20) {
|
||||||
return "账号字符不能大于20位"
|
return "Username must be at most 20 characters long"
|
||||||
}
|
}
|
||||||
const reg = /^[A-Za-z0-9]+$/
|
const reg = /^[A-Za-z0-9]+$/
|
||||||
if (!reg.test(username)) {
|
if (!reg.test(username)) {
|
||||||
return "账号为必须为字母和数字"
|
return "Username must be letters and numbers only"
|
||||||
}
|
}
|
||||||
return null
|
return null
|
||||||
},
|
},
|
||||||
|
|
||||||
password: (password) => {
|
password: (password) => {
|
||||||
if (typeof (password) == "undefined" || password == null) {
|
if (typeof (password) == "undefined" || password == null) {
|
||||||
return "密码不能为空"
|
return "Password cannot be blank"
|
||||||
}
|
}
|
||||||
password = password.trim()
|
password = password.trim()
|
||||||
if (password.length < 4) {
|
if (password.length < 4) {
|
||||||
return "密码字符不能小于4位"
|
return "Password must be at least 4 characters long"
|
||||||
}
|
}
|
||||||
if (password.length > 20) {
|
if (password.length > 20) {
|
||||||
return "密码字符不能大于20位"
|
return "Password must be at most 20 characters long"
|
||||||
}
|
}
|
||||||
const reg = /^[A-Za-z0-9\.\-\_\+]+$/
|
const reg = /^[A-Za-z0-9\.\-\_\+]+$/
|
||||||
if (!reg.test(password)) {
|
if (!reg.test(password)) {
|
||||||
return "密码为必须为字母和数字或.-+_"
|
return "Password must be letters, numbers, and special characters (.-_+) only"
|
||||||
}
|
}
|
||||||
return null
|
return null
|
||||||
},
|
},
|
||||||
|
|
||||||
email: (email) => {
|
email: (email) => {
|
||||||
if (typeof (email) == "undefined" || email == null) {
|
if (typeof (email) == "undefined" || email == null) {
|
||||||
return "邮箱不能为空"
|
return "Email cannot be blank"
|
||||||
}
|
}
|
||||||
const reg = /^[A-Za-z0-9._%-]+@([A-Za-z0-9-]+\.)+[A-Za-z]{2,4}$/
|
const reg = /^[A-Za-z0-9._%-]+@([A-Za-z0-9-]+\.)+[A-Za-z]{2,4}$/
|
||||||
if (!reg.test(email)) {
|
if (!reg.test(email)) {
|
||||||
return "邮箱格式不正确"
|
return "Invalid email address"
|
||||||
}
|
}
|
||||||
return null
|
return null
|
||||||
},
|
},
|
||||||
|
|
||||||
validCode: (validCode) => {
|
validCode: (validCode) => {
|
||||||
if (typeof (validCode) == "undefined" || validCode == null) {
|
if (typeof (validCode) == "undefined" || validCode == null) {
|
||||||
return "验证码不能为空"
|
return "Verification code cannot be blank"
|
||||||
}
|
}
|
||||||
validCode = validCode.trim()
|
validCode = validCode.trim()
|
||||||
if (validCode.length != 6) {
|
if (validCode.length != 6) {
|
||||||
return "验证码必须为6位"
|
return "Verification code must be 6 characters long"
|
||||||
}
|
}
|
||||||
const reg = /^[A-Za-z0-9]{6}$/
|
const reg = /^[A-Za-z0-9]{6}$/
|
||||||
if (!reg.test(validCode)) {
|
if (!reg.test(validCode)) {
|
||||||
return "验证码格式不正确"
|
return "Invalid verification code format"
|
||||||
}
|
}
|
||||||
return null
|
return null
|
||||||
},
|
},
|
||||||
|
@ -1,12 +1,12 @@
|
|||||||
import { fileURLToPath, URL } from 'node:url'
|
import { fileURLToPath, URL } from 'node:url'
|
||||||
|
|
||||||
import { defineConfig } from 'vite'
|
|
||||||
import vue from '@vitejs/plugin-vue'
|
import vue from '@vitejs/plugin-vue'
|
||||||
|
import { defineConfig } from 'vite'
|
||||||
|
|
||||||
import AutoImport from 'unplugin-auto-import/vite'
|
|
||||||
import Components from 'unplugin-vue-components/vite'
|
|
||||||
import { ElementPlusResolver } from 'unplugin-vue-components/resolvers'
|
|
||||||
import { terser } from 'rollup-plugin-terser'
|
import { terser } from 'rollup-plugin-terser'
|
||||||
|
import AutoImport from 'unplugin-auto-import/vite'
|
||||||
|
import { ElementPlusResolver } from 'unplugin-vue-components/resolvers'
|
||||||
|
import Components from 'unplugin-vue-components/vite'
|
||||||
|
|
||||||
// https://vitejs.dev/config/
|
// https://vitejs.dev/config/
|
||||||
export default defineConfig({
|
export default defineConfig({
|
||||||
@ -37,16 +37,16 @@ export default defineConfig({
|
|||||||
},
|
},
|
||||||
build: {
|
build: {
|
||||||
chunkSizeWarningLimit: 1500,
|
chunkSizeWarningLimit: 1500,
|
||||||
// 分解块,将大块分解成更小的块
|
// Split into chunks
|
||||||
rollupOptions: {
|
rollupOptions: {
|
||||||
output: {
|
output: {
|
||||||
manualChunks(id) {
|
manualChunks(id) {
|
||||||
if (id.includes('node_modules')) {
|
if (id.includes('node_modules')) {
|
||||||
// 让每个插件都打包成独立的文件
|
// Pack each package into a separate chunk
|
||||||
return id.toString().split('node_modules/')[1].split('/')[0].toString();
|
return id.toString().split('node_modules/')[1].split('/')[0].toString()
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
// 单位b, 合并较小模块
|
// In bytes, merge small modules
|
||||||
experimentalMinChunkSize: 10 * 1024,
|
experimentalMinChunkSize: 10 * 1024,
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
@ -52,7 +52,7 @@ const handleClose = (key, keyPath) => {
|
|||||||
// console.log(key, keyPath)
|
// console.log(key, keyPath)
|
||||||
}
|
}
|
||||||
|
|
||||||
// 菜单
|
// Menu List
|
||||||
const menuList = [
|
const menuList = [
|
||||||
{
|
{
|
||||||
index: "M02",
|
index: "M02",
|
||||||
@ -89,7 +89,7 @@ const menuList = [
|
|||||||
]
|
]
|
||||||
|
|
||||||
onMounted(() => {
|
onMounted(() => {
|
||||||
// 页面刷新后,检查菜单定位
|
// Check menu position after refresh
|
||||||
// activeMenu()
|
// activeMenu()
|
||||||
})
|
})
|
||||||
|
|
||||||
@ -107,11 +107,11 @@ function listSubMenu(menuCode) {
|
|||||||
|
|
||||||
watch(() => router.currentRoute.value.path, (newValue, oldValue) => {
|
watch(() => router.currentRoute.value.path, (newValue, oldValue) => {
|
||||||
// console.log('LeftMenu侦听到router.currentRoute.value.path发生更新', newValue, oldValue)
|
// console.log('LeftMenu侦听到router.currentRoute.value.path发生更新', newValue, oldValue)
|
||||||
// 路由发生变更后,检查菜单定位
|
// Check menu position after route change
|
||||||
activeMenu()
|
activeMenu()
|
||||||
})
|
})
|
||||||
|
|
||||||
// 检查激活的菜单
|
// Check activated menu position
|
||||||
function activeMenu() {
|
function activeMenu() {
|
||||||
const currRoute = router.currentRoute
|
const currRoute = router.currentRoute
|
||||||
const path = currRoute.value.path
|
const path = currRoute.value.path
|
||||||
@ -121,13 +121,13 @@ function activeMenu() {
|
|||||||
if (utils.notNull(index)) {
|
if (utils.notNull(index)) {
|
||||||
return index
|
return index
|
||||||
}
|
}
|
||||||
// 没有匹配上,截取掉path最后一级,再匹配一次
|
// No match, try to find menu for parent path
|
||||||
const lastIndex = path.lastIndexOf('/')
|
const lastIndex = path.lastIndexOf('/')
|
||||||
if (lastIndex != -1) {
|
if (lastIndex != -1) {
|
||||||
const newPath = path.substring(0, lastIndex)
|
const newPath = path.substring(0, lastIndex)
|
||||||
console.log("截取后newPath:", newPath)
|
console.log("newPath from parent path:", newPath)
|
||||||
index = getIndexByPath(newPath)
|
index = getIndexByPath(newPath)
|
||||||
console.log("截取后index:", index)
|
console.log("index from parent path:", index)
|
||||||
if (utils.notNull(index)) {
|
if (utils.notNull(index)) {
|
||||||
return index
|
return index
|
||||||
}
|
}
|
||||||
@ -135,7 +135,7 @@ function activeMenu() {
|
|||||||
return "1"
|
return "1"
|
||||||
}
|
}
|
||||||
|
|
||||||
// 根据路径查询菜单index
|
// Query menu index by path
|
||||||
function getIndexByPath(path) {
|
function getIndexByPath(path) {
|
||||||
for (let fstMenu of menuList) {
|
for (let fstMenu of menuList) {
|
||||||
// console.log(fstMenu.index, fstMenu.href == path)
|
// console.log(fstMenu.index, fstMenu.href == path)
|
||||||
@ -157,7 +157,7 @@ function getIndexByPath(path) {
|
|||||||
return thdMenu.index
|
return thdMenu.index
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// 三级菜单path都没匹配上,取路由配置中的to进行匹配
|
// If no third-level menu path matches, use the 'to' from the route configuration to find a match
|
||||||
for (let thdMenu of thdMenuList) {
|
for (let thdMenu of thdMenuList) {
|
||||||
const nodeList = routeMap.get(path)
|
const nodeList = routeMap.get(path)
|
||||||
if (utils.isEmpty(nodeList)) {
|
if (utils.isEmpty(nodeList)) {
|
||||||
@ -165,14 +165,14 @@ function getIndexByPath(path) {
|
|||||||
}
|
}
|
||||||
for (let node of nodeList) {
|
for (let node of nodeList) {
|
||||||
if (node.to == thdMenu.href) {
|
if (node.to == thdMenu.href) {
|
||||||
// console.log("匹配上node.to:", node.to)
|
// console.log("A match was found for node.to:", node.to)
|
||||||
return thdMenu.index
|
return thdMenu.index
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// 二级菜单都没匹配上,取路由配置中的to进行匹配
|
// Iterate through each secondary menu item in the secMenuList
|
||||||
for (let secMenu of secMenuList) {
|
for (let secMenu of secMenuList) {
|
||||||
// console.log(secMenu.index, secMenu.href == path)
|
// console.log(secMenu.index, secMenu.href == path)
|
||||||
const nodeList = routeMap.get(path)
|
const nodeList = routeMap.get(path)
|
||||||
@ -187,13 +187,13 @@ function getIndexByPath(path) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// 一级菜单都没匹配上,取路由配置中的to进行匹配
|
// None of the menu items match the path, try to find a match for the 'to' from the route configuration
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// 获取routes配置
|
// get routes configuration
|
||||||
const routes = router.options.routes;
|
const routes = router.options.routes
|
||||||
// console.log("routes:", routes)
|
// console.log("routes:", routes)
|
||||||
const routeMap = new Map()
|
const routeMap = new Map()
|
||||||
routes.forEach(lv1 => {
|
routes.forEach(lv1 => {
|
||||||
@ -261,7 +261,7 @@ function getMenuNameByCode(code) {
|
|||||||
|
|
||||||
<style scoped>
|
<style scoped>
|
||||||
span {
|
span {
|
||||||
/* 防止双击选中 */
|
/* Prevent text selection from double-clicking */
|
||||||
-webkit-user-select: none;
|
-webkit-user-select: none;
|
||||||
-moz-user-select: none;
|
-moz-user-select: none;
|
||||||
-ms-user-select: none;
|
-ms-user-select: none;
|
||||||
@ -269,16 +269,16 @@ span {
|
|||||||
}
|
}
|
||||||
|
|
||||||
span {
|
span {
|
||||||
/* 字体大小 */
|
/* Font size */
|
||||||
font-size: 16px;
|
font-size: 16px;
|
||||||
}
|
}
|
||||||
|
|
||||||
li {
|
li {
|
||||||
/* 字体大小 */
|
/* Font size */
|
||||||
font-size: 15px;
|
font-size: 15px;
|
||||||
}
|
}
|
||||||
|
|
||||||
/** 菜单折叠时hover菜单项高度这里必须再定义一次 */
|
/** When the menu is collapsed, redefine the hover menu height */
|
||||||
.el-menu-item {
|
.el-menu-item {
|
||||||
min-width: 44px;
|
min-width: 44px;
|
||||||
height: 36px;
|
height: 36px;
|
||||||
|
@ -25,17 +25,18 @@
|
|||||||
</el-header>
|
</el-header>
|
||||||
<el-main>
|
<el-main>
|
||||||
<el-scrollbar style="width: 100%;">
|
<el-scrollbar style="width: 100%;">
|
||||||
<!-- 路由展示区 -->
|
<!-- Router View Container -->
|
||||||
<!-- { Component }指当前路由所对应的组件 -->
|
<!-- { Component } = currently matched route component -->
|
||||||
<RouterView v-slot="{ Component }">
|
<RouterView v-slot="{ Component }">
|
||||||
<!-- 添加过渡动画 需要确保插入的component元素只有一个根节点, 否则报错. component中的根元素的transition会覆盖transitionName的样式
|
<!-- Cached Route Transition: Only keeps alive components with keepAlive meta flag
|
||||||
而且需要保证component中根元素的宽度相同所以最好是统一给component添加一个根元素 -->
|
Transition animation requires single root element in component Key ensures proper re-rendering on route path changes -->
|
||||||
<transition :name="transitionName">
|
<transition :name="transitionName">
|
||||||
<KeepAlive>
|
<KeepAlive>
|
||||||
<Component :is="Component" v-if="keepAlive" :key="$route.path" />
|
<Component :is="Component" v-if="keepAlive" :key="$route.path" />
|
||||||
</KeepAlive>
|
</KeepAlive>
|
||||||
</transition>
|
</transition>
|
||||||
<!-- 添加过渡动画 需要确保插入的component元素只有一个根节点 -->
|
<!-- Non-cached Route Transition: Fresh instance for other components
|
||||||
|
Separate transition to prevent animation conflicts -->
|
||||||
<transition :name="transitionName">
|
<transition :name="transitionName">
|
||||||
<Component :is="Component" v-if="!keepAlive" :key="$route.path" />
|
<Component :is="Component" v-if="!keepAlive" :key="$route.path" />
|
||||||
</transition>
|
</transition>
|
||||||
@ -66,46 +67,49 @@ const config = useConfig()
|
|||||||
const { shrink, menuCollapse } = storeToRefs(config)
|
const { shrink, menuCollapse } = storeToRefs(config)
|
||||||
const currentRoute = reactive(router.currentRoute)
|
const currentRoute = reactive(router.currentRoute)
|
||||||
|
|
||||||
// 默认动画效果, 向左滑动
|
// Default transition effect, slide to the left
|
||||||
let transitionName = 'slide-left'
|
let transitionName = 'slide-left'
|
||||||
|
|
||||||
const keepAlive = computed(() => {
|
const keepAlive = computed(() => {
|
||||||
return currentRoute.value.meta.keepAlive
|
return currentRoute.value.meta.keepAlive
|
||||||
})
|
})
|
||||||
|
|
||||||
/** 固定菜单头展开折叠动画时间 刷新页面时菜单不会展开或折叠, 设置持续时间为0, 不产生动画 */
|
/**
|
||||||
|
* Set the menu animation duration to 0ms on page refresh to prevent the menu from expanding or collapsing
|
||||||
|
* with an animation. This ensures that the menu state remains consistent after a page reload.
|
||||||
|
*/
|
||||||
const menuAnimationDuration = ref(0)
|
const menuAnimationDuration = ref(0)
|
||||||
|
|
||||||
// 菜单折叠展开切换
|
// Function to toggle the menu between expanded and collapsed states
|
||||||
function menuToggle() {
|
function menuToggle() {
|
||||||
menuAnimationDuration.value = '300ms'
|
menuAnimationDuration.value = '300ms'
|
||||||
|
|
||||||
if (menuCollapse.value) {
|
if (menuCollapse.value) {
|
||||||
// console.log("折叠状态下, 进行展开菜单")
|
// console.log("Extend menu")
|
||||||
if (shrink.value) {
|
if (shrink.value) {
|
||||||
// 收缩时, 展开遮罩
|
// Expend the shade if menu is collapsing
|
||||||
showShade(() => {
|
showShade(() => {
|
||||||
// console.log("这里定义关闭遮罩回调函数, 关闭遮罩后, 折叠菜单")
|
// Callback function to close the shade after the menu has collapsed
|
||||||
config.setMenuCollapse(true)
|
config.setMenuCollapse(true)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
// console.log("展开状态下, 进行折叠菜单, 关闭掉侧栏遮罩")
|
// If the menu is in an expanded state, close the shade
|
||||||
closeShade()
|
closeShade()
|
||||||
}
|
}
|
||||||
// 切换菜单折叠状态
|
// Toggle the menu state
|
||||||
config.setMenuCollapse(!menuCollapse.value)
|
config.setMenuCollapse(!menuCollapse.value)
|
||||||
}
|
}
|
||||||
|
|
||||||
function onAdaptiveLayout() {
|
function onAdaptiveLayout() {
|
||||||
// 获取当前窗口宽度
|
// Get the current window width
|
||||||
const clientWidth = document.body.clientWidth
|
const clientWidth = document.body.clientWidth
|
||||||
// console.log("menuCollapse:", menuCollapse.value, config.getMenuCollapse(), "clientWidth:", clientWidth)
|
// console.log("menuCollapse:", menuCollapse.value, config.getMenuCollapse(), "clientWidth:", clientWidth)
|
||||||
// 设定aside是否收缩
|
// Determine if the aside menu should be shrunk based on the window width
|
||||||
if (clientWidth < 800) {
|
if (clientWidth < 800) {
|
||||||
config.setShrink(true)
|
config.setShrink(true)
|
||||||
if (!menuCollapse.value) {
|
if (!menuCollapse.value) {
|
||||||
// 展开状态下, 收起菜单
|
// Collapse the menu if it is not already collapsed
|
||||||
menuToggle()
|
menuToggle()
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
@ -119,16 +123,15 @@ onBeforeMount(() => {
|
|||||||
})
|
})
|
||||||
|
|
||||||
watch(() => router.currentRoute.value.path, (newValue, oldValue) => {
|
watch(() => router.currentRoute.value.path, (newValue, oldValue) => {
|
||||||
// console.log("路由变化,如果是收缩状态,则收起菜单:", newValue, oldValue)
|
// If the layout is shrunk and the menu is expanded, collapse the menu
|
||||||
if (shrink.value && !menuCollapse.value) {
|
if (shrink.value && !menuCollapse.value) {
|
||||||
// console.log("收缩状态下, 且菜单展开时, 收起菜单")
|
|
||||||
menuToggle()
|
menuToggle()
|
||||||
}
|
}
|
||||||
|
|
||||||
})
|
})
|
||||||
|
|
||||||
function refresh() {
|
function refresh() {
|
||||||
// console.log("刷新页面")
|
// Reload the page
|
||||||
location.reload()
|
location.reload()
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -182,7 +185,7 @@ main {
|
|||||||
white-space: nowrap;
|
white-space: nowrap;
|
||||||
}
|
}
|
||||||
|
|
||||||
/** 菜单折叠 */
|
/* Keyframes for the menu collapse animation */
|
||||||
@keyframes menuCollapse {
|
@keyframes menuCollapse {
|
||||||
0% {
|
0% {
|
||||||
width: 200px;
|
width: 200px;
|
||||||
@ -193,7 +196,7 @@ main {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/** 菜单展开 */
|
/* Keyframes for the menu expand animation */
|
||||||
@keyframes menuExpand {
|
@keyframes menuExpand {
|
||||||
0% {
|
0% {
|
||||||
width: 44px;
|
width: 44px;
|
||||||
@ -209,9 +212,9 @@ main {
|
|||||||
z-index: 9999;
|
z-index: 9999;
|
||||||
height: 44px;
|
height: 44px;
|
||||||
width: 44px;
|
width: 44px;
|
||||||
/* 引用上面定义的@keyframes名称 */
|
/* Reference to the keyframes */
|
||||||
animation-name: menuCollapse;
|
animation-name: menuCollapse;
|
||||||
/* 动画持续时间 */
|
/* Duration of the animation */
|
||||||
animation-duration: v-bind('menuAnimationDuration');
|
animation-duration: v-bind('menuAnimationDuration');
|
||||||
animation-timing-function: ease-in-out;
|
animation-timing-function: ease-in-out;
|
||||||
background-color: var(--el-fg-color);
|
background-color: var(--el-fg-color);
|
||||||
@ -222,13 +225,13 @@ main {
|
|||||||
z-index: 9999;
|
z-index: 9999;
|
||||||
height: 44px;
|
height: 44px;
|
||||||
width: 200px;
|
width: 200px;
|
||||||
/* 引用上面定义的@keyframes名称 */
|
/* Reference to the keyframes */
|
||||||
animation-name: menuExpand;
|
animation-name: menuExpand;
|
||||||
/* 动画持续时间 */
|
/* Duration of the animation */
|
||||||
animation-duration: v-bind('menuAnimationDuration');
|
animation-duration: v-bind('menuAnimationDuration');
|
||||||
animation-timing-function: ease-in-out;
|
animation-timing-function: ease-in-out;
|
||||||
background-color: var(--el-fg-color);
|
background-color: var(--el-fg-color);
|
||||||
z-index: 9999999
|
z-index: 9999999;
|
||||||
}
|
}
|
||||||
|
|
||||||
.scrollbar-menu-wrapper {
|
.scrollbar-menu-wrapper {
|
||||||
@ -240,6 +243,6 @@ main {
|
|||||||
.scrollbar-menu-wrapper.shrink {
|
.scrollbar-menu-wrapper.shrink {
|
||||||
position: fixed;
|
position: fixed;
|
||||||
left: 0;
|
left: 0;
|
||||||
z-index: 9999999
|
z-index: 9999999;
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
|
@ -1,25 +1,25 @@
|
|||||||
import './assets/css/main.css'
|
import './assets/css/main.css'
|
||||||
|
|
||||||
|
import files from '@/assets/js/files'
|
||||||
import utils from '@/assets/js/utils'
|
import utils from '@/assets/js/utils'
|
||||||
|
import verify from '@/assets/js/verify'
|
||||||
import { createPinia } from 'pinia'
|
import { createPinia } from 'pinia'
|
||||||
import piniaPluginPersistedstate from 'pinia-plugin-persistedstate'
|
import piniaPluginPersistedstate from 'pinia-plugin-persistedstate'
|
||||||
import files from '@/assets/js/files'
|
|
||||||
import verify from '@/assets/js/verify'
|
|
||||||
import { createApp } from 'vue'
|
import { createApp } from 'vue'
|
||||||
import App from './App.vue'
|
import App from './App.vue'
|
||||||
import router from './router'
|
|
||||||
import i18n from './locales/i18n'
|
import i18n from './locales/i18n'
|
||||||
|
import router from './router'
|
||||||
|
|
||||||
// import ElementPlus from 'element-plus'
|
// import ElementPlus from 'element-plus'
|
||||||
import { ElMessage } from 'element-plus'
|
import { ElMessage } from 'element-plus'
|
||||||
import 'element-plus/dist/index.css'
|
import 'element-plus/dist/index.css'
|
||||||
/* 暗黑主题模式 */
|
/* Dark theme configuration */
|
||||||
import 'element-plus/theme-chalk/dark/css-vars.css'
|
|
||||||
import '@/assets/less/light.css'
|
|
||||||
import '@/assets/less/dark.css'
|
import '@/assets/less/dark.css'
|
||||||
// 定义特性标志
|
import '@/assets/less/light.css'
|
||||||
window.__VUE_PROD_DEVTOOLS__ = false;
|
import 'element-plus/theme-chalk/dark/css-vars.css'
|
||||||
window.__VUE_PROD_HYDRATION_MISMATCH_DETAILS__ = false;
|
// Configure Vue production flags
|
||||||
|
window.__VUE_PROD_DEVTOOLS__ = false
|
||||||
|
window.__VUE_PROD_HYDRATION_MISMATCH_DETAILS__ = false
|
||||||
|
|
||||||
const pinia = createPinia()
|
const pinia = createPinia()
|
||||||
pinia.use(piniaPluginPersistedstate)
|
pinia.use(piniaPluginPersistedstate)
|
||||||
@ -28,21 +28,21 @@ const app = createApp(App)
|
|||||||
|
|
||||||
app.use(pinia)
|
app.use(pinia)
|
||||||
|
|
||||||
// 全局引用router
|
// Globally reference router
|
||||||
app.use(router)
|
app.use(router)
|
||||||
|
|
||||||
app.use(i18n)
|
app.use(i18n)
|
||||||
|
|
||||||
// ElMessage需要在utils中使用,这里单独引入
|
// Register Element Plus Message component globally (required for use in utils)
|
||||||
app.use(ElMessage)
|
app.use(ElMessage)
|
||||||
|
|
||||||
// 全局使用
|
// Global configuration of ElementPlus
|
||||||
// ElSelect.props.placeholder.default = '请选择'
|
// ElSelect.props.placeholder.default = '请选择'
|
||||||
// 在引入 ElementPlus 时,可以传入一个包含 size 和 zIndex 属性的全局配置对象。
|
// When ElementPlus is imported, a global configuration object can be passed in which contains size and zIndex properties
|
||||||
// size 用于设置表单组件的默认尺寸,zIndex 用于设置弹出组件的层级,zIndex 的默认值为 2000。
|
// size is used to set the default size of form components, and zIndex is used to set the layer level of pop-up components.
|
||||||
// app.use(ElementPlus, { locale, size: 'default', zIndex: 2000 })
|
// app.use(ElementPlus, { locale, size: 'default', zIndex: 2000 })
|
||||||
|
|
||||||
// 使用vue3 provide注册
|
// Configure global providers for shared utilities
|
||||||
app.provide('utils', utils)
|
app.provide('utils', utils)
|
||||||
|
|
||||||
|
|
||||||
@ -52,4 +52,3 @@ app.provide('verify', verify)
|
|||||||
/* app.provide('uuid', uuidv4) */
|
/* app.provide('uuid', uuidv4) */
|
||||||
|
|
||||||
app.mount('#app')
|
app.mount('#app')
|
||||||
|
|
||||||
|
@ -1,12 +1,12 @@
|
|||||||
import { fileURLToPath, URL } from 'node:url'
|
import { fileURLToPath, URL } from 'node:url'
|
||||||
|
|
||||||
import { defineConfig } from 'vite'
|
|
||||||
import vue from '@vitejs/plugin-vue'
|
import vue from '@vitejs/plugin-vue'
|
||||||
|
import { defineConfig } from 'vite'
|
||||||
|
|
||||||
import AutoImport from 'unplugin-auto-import/vite'
|
|
||||||
import Components from 'unplugin-vue-components/vite'
|
|
||||||
import { ElementPlusResolver } from 'unplugin-vue-components/resolvers'
|
|
||||||
import { terser } from 'rollup-plugin-terser'
|
import { terser } from 'rollup-plugin-terser'
|
||||||
|
import AutoImport from 'unplugin-auto-import/vite'
|
||||||
|
import { ElementPlusResolver } from 'unplugin-vue-components/resolvers'
|
||||||
|
import Components from 'unplugin-vue-components/vite'
|
||||||
|
|
||||||
// https://vitejs.dev/config/
|
// https://vitejs.dev/config/
|
||||||
export default defineConfig({
|
export default defineConfig({
|
||||||
@ -37,16 +37,16 @@ export default defineConfig({
|
|||||||
},
|
},
|
||||||
build: {
|
build: {
|
||||||
chunkSizeWarningLimit: 1500,
|
chunkSizeWarningLimit: 1500,
|
||||||
// 分解块,将大块分解成更小的块
|
// Fine-tune bundling strategy
|
||||||
rollupOptions: {
|
rollupOptions: {
|
||||||
output: {
|
output: {
|
||||||
manualChunks(id) {
|
manualChunks(id) {
|
||||||
if (id.includes('node_modules')) {
|
if (id.includes('node_modules')) {
|
||||||
// 让每个插件都打包成独立的文件
|
// Extract package name from module path to create separate chunks
|
||||||
return id.toString().split('node_modules/')[1].split('/')[0].toString();
|
return id.toString().split('node_modules/')[1].split('/')[0].toString()
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
// 单位b, 合并较小模块
|
// Attempt to merge chunks smaller than 10KB (in bytes)
|
||||||
experimentalMinChunkSize: 10 * 1024,
|
experimentalMinChunkSize: 10 * 1024,
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
@ -31,4 +31,3 @@ wails build
|
|||||||
npm install axios
|
npm install axios
|
||||||
npm install qs
|
npm install qs
|
||||||
npm i --save-dev @types/qs
|
npm i --save-dev @types/qs
|
||||||
|
|
||||||
|
@ -1,8 +0,0 @@
|
|||||||
def factorial(n):
|
|
||||||
if n == 0 or n == 1:
|
|
||||||
return 1
|
|
||||||
else:
|
|
||||||
return n * factorial(n - 1)
|
|
||||||
|
|
||||||
# Example usage
|
|
||||||
print(factorial(5))
|
|
@ -1,2 +0,0 @@
|
|||||||
Hello, World!
|
|
||||||
This is a sample text file.
|
|
Loading…
x
Reference in New Issue
Block a user