feat: 优化后台界面与报表样式
This commit is contained in:
@@ -256,35 +256,41 @@ const getPlaceholder = (placeholder: string | string[] | undefined, key = 0, def
|
||||
width: 100%;
|
||||
max-width: 100%;
|
||||
background-color: var(--ba-bg-color-overlay);
|
||||
border: 1px solid var(--ba-border-color);
|
||||
border: 1px solid var(--ba-border-color-soft);
|
||||
border-bottom: none;
|
||||
padding: 13px 15px;
|
||||
padding: 16px;
|
||||
font-size: 14px;
|
||||
border-radius: var(--ba-radius-panel) var(--ba-radius-panel) 0 0;
|
||||
.com-search-col {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
min-height: 40px;
|
||||
padding-top: 8px;
|
||||
color: var(--el-text-color-regular);
|
||||
font-size: 13px;
|
||||
}
|
||||
.com-search-col-label {
|
||||
width: 33.33%;
|
||||
padding: 0 15px;
|
||||
padding: 0 12px;
|
||||
text-align: right;
|
||||
overflow: hidden;
|
||||
white-space: nowrap;
|
||||
color: var(--el-text-color-secondary);
|
||||
font-weight: 600;
|
||||
}
|
||||
.com-search-col-input {
|
||||
padding: 0 15px;
|
||||
padding: 0 12px;
|
||||
width: 66.66%;
|
||||
}
|
||||
.com-search-col-input-range {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
padding: 0 15px;
|
||||
padding: 0 12px;
|
||||
width: 66.66%;
|
||||
.range-separator {
|
||||
padding: 0 5px;
|
||||
padding: 0 8px;
|
||||
color: var(--el-text-color-secondary);
|
||||
font-size: 12px;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -297,4 +303,28 @@ const getPlaceholder = (placeholder: string | string[] | undefined, key = 0, def
|
||||
.w83 {
|
||||
width: 83.5% !important;
|
||||
}
|
||||
|
||||
@media screen and (max-width: 768px) {
|
||||
.table-com-search {
|
||||
padding: 12px;
|
||||
.com-search-col {
|
||||
display: block;
|
||||
}
|
||||
.com-search-col-label,
|
||||
.com-search-col-input,
|
||||
.com-search-col-input-range,
|
||||
.w16,
|
||||
.w83 {
|
||||
width: 100% !important;
|
||||
padding: 0;
|
||||
text-align: left;
|
||||
}
|
||||
.com-search-col-label {
|
||||
margin-bottom: 6px;
|
||||
}
|
||||
}
|
||||
.pl-20 {
|
||||
padding-left: 0;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
||||
@@ -176,42 +176,51 @@ const onChangeShowColumn = (value: string | number | boolean, field: string) =>
|
||||
box-sizing: border-box;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 10px;
|
||||
width: 100%;
|
||||
max-width: 100%;
|
||||
background-color: var(--ba-bg-color-overlay);
|
||||
border: 1px solid var(--ba-border-color);
|
||||
border: 1px solid var(--ba-border-color-soft);
|
||||
border-bottom: none;
|
||||
padding: 13px 15px;
|
||||
padding: 14px 16px;
|
||||
font-size: 14px;
|
||||
border-radius: var(--ba-radius-panel) var(--ba-radius-panel) 0 0;
|
||||
.table-header-operate-text {
|
||||
margin-left: 6px;
|
||||
}
|
||||
:deep(.el-button) {
|
||||
min-height: 32px;
|
||||
}
|
||||
}
|
||||
.btns-ml-12 + .btns-ml-12 {
|
||||
margin-left: 12px;
|
||||
margin-left: 0;
|
||||
}
|
||||
.table-search {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 10px;
|
||||
margin-left: auto;
|
||||
.quick-search {
|
||||
width: auto;
|
||||
width: 240px;
|
||||
}
|
||||
}
|
||||
.table-search-button-group {
|
||||
display: flex;
|
||||
margin-left: 12px;
|
||||
border: 1px solid var(--el-border-color);
|
||||
border-radius: var(--el-border-radius-base);
|
||||
margin-left: 0;
|
||||
border: 1px solid var(--ba-border-color-soft);
|
||||
border-radius: var(--ba-radius-control);
|
||||
overflow: hidden;
|
||||
background: var(--ba-bg-color-soft);
|
||||
button:focus,
|
||||
button:active {
|
||||
background-color: var(--ba-bg-color-overlay);
|
||||
}
|
||||
button:hover {
|
||||
background-color: var(--el-color-info-light-7);
|
||||
background-color: var(--el-color-primary-light-9);
|
||||
}
|
||||
.table-search-button-item {
|
||||
height: 30px;
|
||||
height: 32px;
|
||||
width: 34px;
|
||||
border: none;
|
||||
border-radius: 0;
|
||||
}
|
||||
@@ -219,7 +228,7 @@ const onChangeShowColumn = (value: string | number | boolean, field: string) =>
|
||||
margin: 0;
|
||||
}
|
||||
.right-border {
|
||||
border-right: 1px solid var(--el-border-color);
|
||||
border-right: 1px solid var(--ba-border-color-soft);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -240,4 +249,19 @@ html.dark {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@media screen and (max-width: 768px) {
|
||||
.table-header {
|
||||
flex-wrap: wrap;
|
||||
align-items: stretch;
|
||||
padding: 12px;
|
||||
}
|
||||
.table-search {
|
||||
width: 100%;
|
||||
margin-left: 0;
|
||||
.quick-search {
|
||||
width: 100%;
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
||||
@@ -230,17 +230,42 @@ defineExpose({
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss">
|
||||
.ba-data-table {
|
||||
border-radius: 0 0 var(--ba-radius-panel) var(--ba-radius-panel);
|
||||
overflow: hidden;
|
||||
}
|
||||
.ba-data-table :deep(.table-header-cell) .cell {
|
||||
color: var(--el-text-color-primary);
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
white-space: nowrap;
|
||||
font-weight: 700;
|
||||
}
|
||||
.ba-data-table :deep(.cell) {
|
||||
line-height: 1.45;
|
||||
}
|
||||
.ba-data-table :deep(.el-table__empty-text) {
|
||||
padding: 18px 0;
|
||||
color: var(--el-text-color-secondary);
|
||||
font-weight: 500;
|
||||
}
|
||||
.table-pagination {
|
||||
box-sizing: border-box;
|
||||
width: 100%;
|
||||
max-width: 100%;
|
||||
background-color: var(--ba-bg-color-overlay);
|
||||
padding: 13px 15px;
|
||||
padding: 14px 16px;
|
||||
border: 1px solid var(--ba-border-color-soft);
|
||||
border-top: none;
|
||||
border-radius: 0 0 var(--ba-radius-panel) var(--ba-radius-panel);
|
||||
display: flex;
|
||||
justify-content: flex-end;
|
||||
}
|
||||
|
||||
@media screen and (max-width: 768px) {
|
||||
.table-pagination {
|
||||
justify-content: center;
|
||||
padding: 12px;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
||||
@@ -41,6 +41,9 @@ export default {
|
||||
'Current Balance': 'Current Balance',
|
||||
'Transaction Breakdown': 'Transaction Breakdown',
|
||||
'Safe Alert': 'Safe Alert',
|
||||
'Fast Calculation': 'Fast Calculation',
|
||||
'Calculation placeholder': 'e.g. +10+50-20',
|
||||
'Fast Calculation Support': 'Fast Calculation Support',
|
||||
Transfer: 'Transfer',
|
||||
'No Alert': 'No Alert',
|
||||
'No bank data': 'No bank data',
|
||||
|
||||
@@ -41,6 +41,9 @@ export default {
|
||||
'Current Balance': '当前余额',
|
||||
'Transaction Breakdown': '交易明细',
|
||||
'Safe Alert': '安全提醒',
|
||||
'Fast Calculation': '快速计算',
|
||||
'Calculation placeholder': 'e.g. +10+50-20',
|
||||
'Fast Calculation Support': 'Fast Calculation Support',
|
||||
Transfer: '转账',
|
||||
'No Alert': '无提醒',
|
||||
'No bank data': '暂无银行数据',
|
||||
|
||||
@@ -28,12 +28,15 @@ const menuWidth = computed(() => config.menuWidth())
|
||||
<style scoped lang="scss">
|
||||
.layout-aside-Default:not(.shrink) {
|
||||
background: var(--ba-bg-color-overlay);
|
||||
margin: 16px 0 16px 16px;
|
||||
height: calc(100% - 32px);
|
||||
box-shadow: var(--el-box-shadow-light);
|
||||
border-radius: var(--el-border-radius-base);
|
||||
margin: var(--ba-main-space) 0 var(--ba-main-space) var(--ba-main-space);
|
||||
height: calc(100% - (var(--ba-main-space) * 2));
|
||||
border: 1px solid var(--ba-border-color-soft);
|
||||
box-shadow: var(--ba-shadow-card);
|
||||
border-radius: var(--ba-radius-panel);
|
||||
overflow: hidden;
|
||||
transition: width 0.3s ease;
|
||||
transition:
|
||||
width 0.26s ease,
|
||||
box-shadow 0.26s ease;
|
||||
width: v-bind(menuWidth);
|
||||
}
|
||||
.layout-aside-Default.shrink,
|
||||
@@ -43,7 +46,8 @@ const menuWidth = computed(() => config.menuWidth())
|
||||
margin: 0;
|
||||
height: 100%;
|
||||
overflow: hidden;
|
||||
transition: width 0.3s ease;
|
||||
border-right: 1px solid var(--ba-border-color-soft);
|
||||
transition: width 0.26s ease;
|
||||
width: v-bind(menuWidth);
|
||||
}
|
||||
.shrink {
|
||||
|
||||
@@ -49,29 +49,47 @@ const onMenuCollapse = function () {
|
||||
<style scoped lang="scss">
|
||||
.layout-logo {
|
||||
width: 100%;
|
||||
height: 50px;
|
||||
height: 56px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
box-sizing: border-box;
|
||||
padding: 10px;
|
||||
padding: 10px 12px;
|
||||
background: v-bind('config.layout.layoutMode != "Streamline" ? config.getColorVal("menuTopBarBackground"):"transparent"');
|
||||
border-bottom: 1px solid var(--ba-border-color-soft);
|
||||
}
|
||||
.logo-img {
|
||||
width: 28px;
|
||||
width: 30px;
|
||||
height: 30px;
|
||||
object-fit: contain;
|
||||
}
|
||||
.website-name {
|
||||
display: block;
|
||||
width: 180px;
|
||||
padding-left: 4px;
|
||||
font-size: var(--el-font-size-extra-large);
|
||||
font-weight: 600;
|
||||
padding-left: 8px;
|
||||
font-size: 17px;
|
||||
font-weight: 700;
|
||||
letter-spacing: 0;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
white-space: nowrap;
|
||||
}
|
||||
.fold {
|
||||
margin-left: auto;
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
width: 30px;
|
||||
height: 30px;
|
||||
border-radius: var(--ba-radius-control);
|
||||
cursor: pointer;
|
||||
transition:
|
||||
background-color 0.2s ease,
|
||||
transform 0.2s ease;
|
||||
&:hover {
|
||||
background: var(--el-color-primary-light-9);
|
||||
transform: translateX(-1px);
|
||||
}
|
||||
}
|
||||
.unfold {
|
||||
margin: 0 auto;
|
||||
|
||||
@@ -53,11 +53,11 @@ const menuTitle = (menu: RouteRecordRaw) => {
|
||||
|
||||
const reportMenuPaths: Record<string, string> = {
|
||||
'Annual Report': '/user/moneyLog/annualReport',
|
||||
'年度报表': '/user/moneyLog/annualReport',
|
||||
年度报表: '/user/moneyLog/annualReport',
|
||||
'Daily Report': '/user/moneyLog/dailyReport',
|
||||
'日报表': '/user/moneyLog/dailyReport',
|
||||
日报表: '/user/moneyLog/dailyReport',
|
||||
'Customer Report': '/user/moneyLog/customerReport',
|
||||
'客户报表': '/user/moneyLog/customerReport',
|
||||
客户报表: '/user/moneyLog/customerReport',
|
||||
}
|
||||
|
||||
const onClickMenuItem = (menu: RouteRecordRaw) => {
|
||||
@@ -96,8 +96,8 @@ const onClickSubMenu = (menu: RouteRecordRaw) => {
|
||||
.el-sub-menu .icon,
|
||||
.el-menu-item .icon {
|
||||
vertical-align: middle;
|
||||
margin-right: 5px;
|
||||
width: 24px;
|
||||
margin-right: 8px;
|
||||
width: 22px;
|
||||
text-align: center;
|
||||
flex-shrink: 0;
|
||||
}
|
||||
@@ -106,5 +106,6 @@ const onClickSubMenu = (menu: RouteRecordRaw) => {
|
||||
}
|
||||
.el-menu-item.is-active {
|
||||
background-color: v-bind('config.getColorVal("menuActiveBackground")');
|
||||
box-shadow: inset 3px 0 0 v-bind('config.getColorVal("menuActiveColor")');
|
||||
}
|
||||
</style>
|
||||
|
||||
@@ -71,6 +71,7 @@ onBeforeRouteUpdate((to) => {
|
||||
.vertical-menus-scrollbar {
|
||||
height: v-bind(verticalMenusScrollbarHeight);
|
||||
background-color: v-bind('config.getColorVal("menuBackground")');
|
||||
padding: 4px 0 10px;
|
||||
}
|
||||
.layouts-menu-vertical {
|
||||
border: 0;
|
||||
|
||||
@@ -29,46 +29,63 @@ const onMenuCollapse = () => {
|
||||
<style lang="scss" scoped>
|
||||
.nav-bar {
|
||||
display: flex;
|
||||
height: 50px;
|
||||
margin: 20px var(--ba-main-space) 0 var(--ba-main-space);
|
||||
height: 52px;
|
||||
margin: var(--ba-main-space) var(--ba-main-space) 0 var(--ba-main-space);
|
||||
gap: 12px;
|
||||
:deep(.nav-tabs) {
|
||||
display: flex;
|
||||
height: 100%;
|
||||
position: relative;
|
||||
min-width: 0;
|
||||
.ba-nav-tab {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
padding: 0 20px;
|
||||
padding: 0 18px;
|
||||
cursor: pointer;
|
||||
z-index: 1;
|
||||
user-select: none;
|
||||
opacity: 0.7;
|
||||
opacity: 0.78;
|
||||
color: v-bind('config.getColorVal("headerBarTabColor")');
|
||||
border-radius: var(--ba-radius-control);
|
||||
transition:
|
||||
opacity 0.2s ease,
|
||||
color 0.2s ease,
|
||||
background-color 0.2s ease;
|
||||
.close-icon {
|
||||
padding: 2px;
|
||||
margin: 2px 0 0 4px;
|
||||
}
|
||||
.close-icon:hover {
|
||||
background: var(--ba-color-primary-light);
|
||||
color: var(--el-border-color) !important;
|
||||
background: var(--el-color-primary-light-8);
|
||||
color: var(--el-color-primary) !important;
|
||||
border-radius: 50%;
|
||||
}
|
||||
&.active {
|
||||
color: v-bind('config.getColorVal("headerBarTabActiveColor")');
|
||||
font-weight: 600;
|
||||
}
|
||||
&:hover {
|
||||
opacity: 1;
|
||||
background: v-bind('config.getColorVal("headerBarHoverBackground")');
|
||||
}
|
||||
}
|
||||
.nav-tabs-active-box {
|
||||
position: absolute;
|
||||
height: 40px;
|
||||
border-radius: var(--el-border-radius-base);
|
||||
height: 38px;
|
||||
top: 7px;
|
||||
border-radius: var(--ba-radius-control);
|
||||
background-color: v-bind('config.getColorVal("headerBarTabActiveBackground")');
|
||||
box-shadow: var(--el-box-shadow-light);
|
||||
transition: all 0.2s;
|
||||
-webkit-transition: all 0.2s;
|
||||
border: 1px solid var(--ba-border-color-soft);
|
||||
box-shadow: var(--ba-shadow-card);
|
||||
transition:
|
||||
transform 0.2s ease,
|
||||
width 0.2s ease,
|
||||
left 0.2s ease;
|
||||
-webkit-transition:
|
||||
transform 0.2s ease,
|
||||
width 0.2s ease,
|
||||
left 0.2s ease;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -76,6 +93,7 @@ const onMenuCollapse = () => {
|
||||
width: 100%;
|
||||
background-color: v-bind('config.getColorVal("headerBarBackground")');
|
||||
margin: 0;
|
||||
border-bottom: 1px solid var(--ba-border-color-soft);
|
||||
.unfold {
|
||||
align-self: center;
|
||||
padding-left: var(--ba-main-space);
|
||||
|
||||
@@ -231,8 +231,9 @@ const onClearCache = (type: string) => {
|
||||
|
||||
<style scoped lang="scss">
|
||||
.nav-menus.Default:not(.shrink) {
|
||||
border-radius: var(--el-border-radius-base);
|
||||
box-shadow: var(--el-box-shadow-light);
|
||||
border: 1px solid var(--ba-border-color-soft);
|
||||
border-radius: var(--ba-radius-panel);
|
||||
box-shadow: var(--ba-shadow-card);
|
||||
}
|
||||
.reload-hot-server-content {
|
||||
font-size: var(--el-font-size-small);
|
||||
@@ -250,35 +251,52 @@ const onClearCache = (type: string) => {
|
||||
height: 100%;
|
||||
margin-left: auto;
|
||||
background-color: v-bind('configStore.getColorVal("headerBarBackground")');
|
||||
overflow: hidden;
|
||||
.nav-menu-item {
|
||||
height: 100%;
|
||||
width: 40px;
|
||||
width: 44px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
cursor: pointer;
|
||||
transition:
|
||||
background-color 0.2s ease,
|
||||
transform 0.18s ease;
|
||||
.nav-menu-icon {
|
||||
box-sizing: content-box;
|
||||
color: v-bind('configStore.getColorVal("headerBarTabColor")');
|
||||
}
|
||||
&:hover {
|
||||
transform: translateY(-1px);
|
||||
.icon {
|
||||
animation: twinkle 0.3s ease-in-out;
|
||||
animation: twinkle 0.24s ease-in-out;
|
||||
}
|
||||
}
|
||||
&:active {
|
||||
transform: translateY(0);
|
||||
}
|
||||
}
|
||||
.admin-info {
|
||||
display: flex;
|
||||
height: 100%;
|
||||
padding: 0 10px;
|
||||
padding: 0 14px 0 10px;
|
||||
align-items: center;
|
||||
cursor: pointer;
|
||||
user-select: none;
|
||||
color: v-bind('configStore.getColorVal("headerBarTabColor")');
|
||||
transition: background-color 0.2s ease;
|
||||
:deep(.el-avatar) {
|
||||
border: 2px solid var(--ba-border-color-soft);
|
||||
background: var(--ba-bg-color-soft);
|
||||
}
|
||||
}
|
||||
.admin-name {
|
||||
padding-left: 6px;
|
||||
max-width: 128px;
|
||||
padding-left: 8px;
|
||||
white-space: nowrap;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
font-weight: 600;
|
||||
}
|
||||
.nav-menu-item:hover,
|
||||
.admin-info:hover,
|
||||
@@ -294,22 +312,34 @@ const onClearCache = (type: string) => {
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
flex-wrap: wrap;
|
||||
padding-top: 10px;
|
||||
padding-top: 12px;
|
||||
:deep(.el-avatar) {
|
||||
border: 3px solid var(--ba-border-color-soft);
|
||||
}
|
||||
.admin-info-other {
|
||||
display: block;
|
||||
width: 100%;
|
||||
text-align: center;
|
||||
padding: 10px 0;
|
||||
padding: 12px 0 8px;
|
||||
.admin-info-name {
|
||||
font-size: var(--el-font-size-large);
|
||||
font-weight: 700;
|
||||
}
|
||||
.admin-info-lasttime {
|
||||
margin-top: 4px;
|
||||
color: var(--el-text-color-secondary);
|
||||
font-size: var(--el-font-size-small);
|
||||
}
|
||||
}
|
||||
}
|
||||
.admin-info-footer {
|
||||
padding: 10px 0;
|
||||
padding: 12px;
|
||||
margin: 0 -12px -12px -12px;
|
||||
display: flex;
|
||||
justify-content: space-around;
|
||||
justify-content: flex-end;
|
||||
gap: 8px;
|
||||
border-top: 1px solid var(--ba-border-color-soft);
|
||||
background: var(--ba-bg-color-soft);
|
||||
}
|
||||
.pt2 {
|
||||
padding-top: 2px;
|
||||
|
||||
@@ -101,5 +101,6 @@ watch(
|
||||
width: 100%;
|
||||
position: relative;
|
||||
overflow: hidden;
|
||||
background: linear-gradient(180deg, rgba(255, 255, 255, 0.58), rgba(255, 255, 255, 0) 220px), var(--ba-bg-color);
|
||||
}
|
||||
</style>
|
||||
|
||||
@@ -55,10 +55,15 @@ onUnmounted(() => {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
border: 1px solid var(--ba-border-color-soft);
|
||||
border-radius: var(--ba-radius-panel);
|
||||
background: linear-gradient(90deg, transparent, rgba(37, 99, 235, 0.05), transparent), var(--ba-bg-color-overlay);
|
||||
box-shadow: var(--ba-shadow-card);
|
||||
}
|
||||
.loading-footer {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
margin-top: 16px;
|
||||
}
|
||||
</style>
|
||||
|
||||
@@ -15,11 +15,11 @@ export const useConfig = defineStore(
|
||||
isDark: false,
|
||||
|
||||
// 侧边栏
|
||||
menuBackground: ['#ffffff', '#1d1e1f'],
|
||||
menuColor: ['#303133', '#CFD3DC'],
|
||||
menuActiveBackground: ['#ffffff', '#1d1e1f'],
|
||||
menuActiveColor: ['#409eff', '#3375b9'],
|
||||
menuTopBarBackground: ['#fcfcfc', '#1d1e1f'],
|
||||
menuBackground: ['#ffffff', '#182131'],
|
||||
menuColor: ['#334155', '#cbd5e1'],
|
||||
menuActiveBackground: ['#eef4ff', '#162846'],
|
||||
menuActiveColor: ['#2563eb', '#8eadf5'],
|
||||
menuTopBarBackground: ['#ffffff', '#182131'],
|
||||
menuWidth: 260,
|
||||
menuDefaultIcon: 'fa fa-circle-o',
|
||||
menuCollapse: false,
|
||||
@@ -27,11 +27,11 @@ export const useConfig = defineStore(
|
||||
menuShowTopBar: true,
|
||||
|
||||
// 顶栏
|
||||
headerBarTabColor: ['#000000', '#CFD3DC'],
|
||||
headerBarTabActiveBackground: ['#ffffff', '#1d1e1f'],
|
||||
headerBarTabActiveColor: ['#000000', '#409EFF'],
|
||||
headerBarBackground: ['#ffffff', '#1d1e1f'],
|
||||
headerBarHoverBackground: ['#f5f5f5', '#18222c'],
|
||||
headerBarTabColor: ['#475569', '#cbd5e1'],
|
||||
headerBarTabActiveBackground: ['#ffffff', '#182131'],
|
||||
headerBarTabActiveColor: ['#172033', '#8eadf5'],
|
||||
headerBarBackground: ['#ffffff', '#182131'],
|
||||
headerBarHoverBackground: ['#eef4ff', '#162846'],
|
||||
})
|
||||
|
||||
const lang: Lang = reactive({
|
||||
|
||||
@@ -3,7 +3,6 @@
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
box-sizing: border-box;
|
||||
outline: none !important;
|
||||
}
|
||||
|
||||
html,
|
||||
@@ -14,14 +13,17 @@ body,
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
font-family:
|
||||
Helvetica Neue,
|
||||
Helvetica,
|
||||
ui-sans-serif,
|
||||
system-ui,
|
||||
-apple-system,
|
||||
BlinkMacSystemFont,
|
||||
Segoe UI,
|
||||
PingFang SC,
|
||||
Hiragino Sans GB,
|
||||
Microsoft YaHei,
|
||||
SimSun,
|
||||
sans-serif;
|
||||
font-weight: 400;
|
||||
line-height: 1.5;
|
||||
-webkit-font-smoothing: antialiased;
|
||||
-webkit-tap-highlight-color: transparent;
|
||||
background-color: var(--ba-bg-color);
|
||||
@@ -29,6 +31,36 @@ body,
|
||||
font-size: var(--el-font-size-base);
|
||||
}
|
||||
|
||||
html {
|
||||
text-rendering: optimizeLegibility;
|
||||
}
|
||||
|
||||
html,
|
||||
body {
|
||||
overscroll-behavior: none;
|
||||
}
|
||||
|
||||
button,
|
||||
input,
|
||||
textarea,
|
||||
select {
|
||||
font: inherit;
|
||||
}
|
||||
|
||||
a {
|
||||
color: inherit;
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
:focus-visible {
|
||||
outline: 2px solid rgba(37, 99, 235, 0.38);
|
||||
outline-offset: 2px;
|
||||
}
|
||||
|
||||
::selection {
|
||||
background: rgba(37, 99, 235, 0.18);
|
||||
}
|
||||
|
||||
// 阿里 iconfont Symbol引用css
|
||||
.iconfont-icon {
|
||||
width: 1em;
|
||||
@@ -51,7 +83,7 @@ body,
|
||||
}
|
||||
|
||||
.default-main {
|
||||
margin: var(--ba-main-space) var(--ba-main-space) 60px var(--ba-main-space);
|
||||
margin: var(--ba-main-space) var(--ba-main-space) 64px var(--ba-main-space);
|
||||
}
|
||||
.zoom-handle {
|
||||
position: absolute;
|
||||
@@ -64,10 +96,10 @@ body,
|
||||
.block-help {
|
||||
display: block;
|
||||
width: 100%;
|
||||
color: #909399;
|
||||
color: var(--ba-text-muted);
|
||||
font-size: 13px;
|
||||
line-height: 16px;
|
||||
padding-top: 5px;
|
||||
line-height: 1.45;
|
||||
padding-top: 6px;
|
||||
}
|
||||
|
||||
/* 表格顶部菜单-s */
|
||||
@@ -84,7 +116,9 @@ body,
|
||||
|
||||
/* 鼠标置入浮动效果-s */
|
||||
.suspension {
|
||||
transition: all 0.3s ease;
|
||||
transition:
|
||||
transform 0.24s ease,
|
||||
box-shadow 0.24s ease;
|
||||
}
|
||||
.suspension:hover {
|
||||
-webkit-transform: translateY(-4px) scale(1.02);
|
||||
@@ -92,20 +126,23 @@ body,
|
||||
-ms-transform: translateY(-4px) scale(1.02);
|
||||
-o-transform: translateY(-4px) scale(1.02);
|
||||
transform: translateY(-4px) scale(1.02);
|
||||
-webkit-box-shadow: 0 14px 24px rgba(0, 0, 0, 0.2);
|
||||
box-shadow: 0 14px 24px rgba(0, 0, 0, 0.2);
|
||||
-webkit-box-shadow: 0 16px 34px rgba(15, 23, 42, 0.14);
|
||||
box-shadow: 0 16px 34px rgba(15, 23, 42, 0.14);
|
||||
z-index: 2147483600;
|
||||
border-radius: 6px;
|
||||
border-radius: var(--ba-radius-panel);
|
||||
}
|
||||
/* 鼠标置入浮动效果-e */
|
||||
|
||||
/* 表格-s */
|
||||
.ba-table-box {
|
||||
border-radius: var(--el-border-radius-round);
|
||||
border-radius: var(--ba-radius-panel);
|
||||
overflow: hidden;
|
||||
background: var(--ba-bg-color-overlay);
|
||||
box-shadow: var(--ba-shadow-card);
|
||||
}
|
||||
.ba-table-alert {
|
||||
background-color: var(--el-fill-color-darker) !important;
|
||||
border: 1px solid var(--ba-boder-color);
|
||||
background-color: var(--ba-bg-color-soft) !important;
|
||||
border: 1px solid var(--ba-border-color);
|
||||
border-bottom: 0;
|
||||
border-bottom-left-radius: 0;
|
||||
border-bottom-right-radius: 0;
|
||||
@@ -115,28 +152,31 @@ body,
|
||||
/* 新增/编辑表单-s */
|
||||
.ba-operate-dialog {
|
||||
overflow: hidden;
|
||||
border-radius: var(--el-border-radius-base);
|
||||
padding-bottom: 52px;
|
||||
border-radius: var(--ba-radius-panel);
|
||||
padding-bottom: 58px;
|
||||
}
|
||||
.ba-operate-dialog .el-dialog__header {
|
||||
border-bottom: 1px solid var(--ba-bg-color);
|
||||
border-bottom: 1px solid var(--ba-border-color-soft);
|
||||
padding: 18px 22px;
|
||||
.el-dialog__headerbtn {
|
||||
top: 4px;
|
||||
top: 8px;
|
||||
}
|
||||
}
|
||||
.ba-operate-dialog .el-dialog__body {
|
||||
height: 58vh;
|
||||
padding: 20px 22px;
|
||||
}
|
||||
.ba-operate-dialog .el-dialog__footer {
|
||||
padding: 10px var(--el-dialog-padding-primary);
|
||||
box-shadow: var(--el-box-shadow);
|
||||
padding: 12px 22px;
|
||||
box-shadow: 0 -10px 24px rgba(15, 23, 42, 0.06);
|
||||
position: absolute;
|
||||
width: 100%;
|
||||
bottom: 0;
|
||||
left: 0;
|
||||
background: var(--ba-bg-color-overlay);
|
||||
}
|
||||
.ba-operate-form {
|
||||
padding-top: 20px;
|
||||
padding-top: 16px;
|
||||
}
|
||||
/* 新增/编辑表单-e */
|
||||
|
||||
@@ -145,9 +185,10 @@ body,
|
||||
position: fixed;
|
||||
top: 0;
|
||||
left: 0;
|
||||
height: 100vh;
|
||||
height: 100dvh;
|
||||
width: 100vw;
|
||||
background-color: rgba(0, 0, 0, 0.5);
|
||||
background-color: rgba(15, 23, 42, 0.48);
|
||||
backdrop-filter: blur(2px);
|
||||
z-index: 2147483599;
|
||||
}
|
||||
/* 全局遮罩-e */
|
||||
@@ -169,7 +210,9 @@ body,
|
||||
.slide-left-enter-active,
|
||||
.slide-left-leave-active {
|
||||
will-change: transform;
|
||||
transition: all 0.3s ease;
|
||||
transition:
|
||||
transform 0.22s ease,
|
||||
opacity 0.22s ease;
|
||||
}
|
||||
// slide-right
|
||||
.slide-right-enter-from {
|
||||
@@ -194,9 +237,9 @@ body,
|
||||
min-height: calc(100vh - 120px);
|
||||
}
|
||||
.user-views {
|
||||
padding-left: 15px;
|
||||
padding-left: var(--ba-main-space);
|
||||
.user-views-card {
|
||||
margin-bottom: 15px;
|
||||
margin-bottom: var(--ba-main-space);
|
||||
}
|
||||
}
|
||||
.ba-aside-drawer {
|
||||
@@ -226,6 +269,9 @@ body,
|
||||
.xs-hidden {
|
||||
display: none;
|
||||
}
|
||||
.default-main {
|
||||
margin: 12px 12px 48px 12px;
|
||||
}
|
||||
}
|
||||
@media screen and (max-width: 1024px) {
|
||||
.ba-operate-dialog {
|
||||
|
||||
@@ -6,8 +6,10 @@
|
||||
$bg-color: () !default;
|
||||
$bg-color: map.merge(
|
||||
(
|
||||
'': #141414,
|
||||
'overlay': #1d1e1f,
|
||||
'': #101722,
|
||||
'overlay': #182131,
|
||||
'soft': #111c2a,
|
||||
'muted': #0d1420,
|
||||
),
|
||||
$bg-color
|
||||
);
|
||||
@@ -16,7 +18,9 @@ $bg-color: map.merge(
|
||||
$border-color: () !default;
|
||||
$border-color: map.merge(
|
||||
(
|
||||
'': #4c4d4f,
|
||||
'': #2d3a4c,
|
||||
'soft': #263244,
|
||||
'strong': #3a4a61,
|
||||
),
|
||||
$border-color
|
||||
);
|
||||
@@ -24,4 +28,22 @@ $border-color: map.merge(
|
||||
html.dark {
|
||||
@include set-component-css-var('bg-color', $bg-color);
|
||||
@include set-component-css-var('border-color', $border-color);
|
||||
|
||||
--ba-surface-soft: #111c2a;
|
||||
--ba-surface-muted: #0d1420;
|
||||
--ba-text-muted: #94a3b8;
|
||||
--ba-shadow-soft: 0 18px 44px rgba(0, 0, 0, 0.34);
|
||||
--ba-shadow-card: 0 12px 30px rgba(0, 0, 0, 0.28);
|
||||
--el-color-primary: #5b86f0;
|
||||
--el-color-primary-light-3: #406fcf;
|
||||
--el-color-primary-light-5: #2e4f93;
|
||||
--el-color-primary-light-7: #203b6f;
|
||||
--el-color-primary-light-8: #1b315a;
|
||||
--el-color-primary-light-9: #162846;
|
||||
--el-color-primary-dark-2: #8eadf5;
|
||||
--el-text-color-primary: #e5edf7;
|
||||
--el-text-color-regular: #cbd5e1;
|
||||
--el-text-color-secondary: #94a3b8;
|
||||
--el-fill-color-light: #111c2a;
|
||||
--el-fill-color-lighter: #0d1420;
|
||||
}
|
||||
|
||||
@@ -1,19 +1,189 @@
|
||||
.el-menu {
|
||||
user-select: none;
|
||||
padding: 8px;
|
||||
background: transparent;
|
||||
.el-sub-menu__title:hover {
|
||||
background-color: var(--el-color-primary-light-9) !important;
|
||||
}
|
||||
.el-menu-item,
|
||||
.el-sub-menu__title {
|
||||
height: 42px;
|
||||
margin: 3px 0;
|
||||
border-radius: var(--ba-radius-control);
|
||||
line-height: 42px;
|
||||
transition:
|
||||
background-color 0.2s ease,
|
||||
color 0.2s ease,
|
||||
transform 0.2s ease;
|
||||
}
|
||||
.el-menu-item:hover,
|
||||
.el-sub-menu__title:hover {
|
||||
transform: translateX(2px);
|
||||
}
|
||||
.el-menu-item.is-active {
|
||||
background: var(--el-color-primary-light-9);
|
||||
color: var(--el-color-primary);
|
||||
font-weight: 600;
|
||||
}
|
||||
}
|
||||
|
||||
.el-table {
|
||||
--el-table-border-color: var(--ba-border-color);
|
||||
--el-table-header-bg-color: var(--ba-bg-color-soft);
|
||||
--el-table-header-text-color: var(--el-text-color-primary);
|
||||
--el-table-row-hover-bg-color: var(--el-color-primary-light-9);
|
||||
color: var(--el-text-color-regular);
|
||||
font-variant-numeric: tabular-nums;
|
||||
.el-table__cell {
|
||||
padding: 9px 0;
|
||||
}
|
||||
.el-table__header th {
|
||||
font-weight: 600;
|
||||
letter-spacing: 0.01em;
|
||||
}
|
||||
.el-table__empty-block {
|
||||
min-height: 180px;
|
||||
}
|
||||
.el-table__empty-text {
|
||||
color: var(--el-text-color-secondary);
|
||||
}
|
||||
}
|
||||
|
||||
.el-card {
|
||||
border: none;
|
||||
border-radius: var(--ba-radius-panel);
|
||||
box-shadow: var(--ba-shadow-card);
|
||||
.el-card__header {
|
||||
border-bottom: 1px solid var(--el-border-color-extra-light);
|
||||
border-bottom: 1px solid var(--ba-border-color-soft);
|
||||
padding: 14px 18px;
|
||||
font-weight: 600;
|
||||
}
|
||||
.el-card__body {
|
||||
padding: 18px;
|
||||
}
|
||||
}
|
||||
|
||||
.el-button {
|
||||
border-radius: var(--ba-radius-control);
|
||||
font-weight: 600;
|
||||
transition:
|
||||
transform 0.18s ease,
|
||||
box-shadow 0.18s ease,
|
||||
background-color 0.18s ease,
|
||||
border-color 0.18s ease;
|
||||
&:hover {
|
||||
transform: translateY(-1px);
|
||||
}
|
||||
&:active {
|
||||
transform: translateY(0);
|
||||
}
|
||||
&.is-link:hover,
|
||||
&.is-text:hover,
|
||||
&.is-circle:hover {
|
||||
transform: none;
|
||||
}
|
||||
}
|
||||
|
||||
.el-button--primary:not(.is-link, .is-text, .is-plain) {
|
||||
box-shadow: 0 8px 18px rgba(37, 99, 235, 0.18);
|
||||
}
|
||||
|
||||
.el-button--danger:not(.is-link, .is-text, .is-plain) {
|
||||
box-shadow: 0 8px 18px rgba(220, 63, 77, 0.14);
|
||||
}
|
||||
|
||||
.el-input__wrapper,
|
||||
.el-textarea__inner,
|
||||
.el-select__wrapper {
|
||||
border-radius: var(--ba-radius-control);
|
||||
box-shadow: 0 0 0 1px var(--ba-border-color-soft) inset;
|
||||
transition:
|
||||
box-shadow 0.2s ease,
|
||||
background-color 0.2s ease;
|
||||
}
|
||||
|
||||
.el-input__wrapper:hover,
|
||||
.el-textarea__inner:hover,
|
||||
.el-select__wrapper:hover {
|
||||
box-shadow: 0 0 0 1px var(--ba-border-color-strong) inset;
|
||||
}
|
||||
|
||||
.el-input__wrapper.is-focus,
|
||||
.el-textarea__inner:focus,
|
||||
.el-select__wrapper.is-focused {
|
||||
box-shadow:
|
||||
0 0 0 1px var(--el-color-primary) inset,
|
||||
0 0 0 3px rgba(37, 99, 235, 0.12);
|
||||
}
|
||||
|
||||
.el-date-editor.el-input__wrapper {
|
||||
border-radius: var(--ba-radius-control);
|
||||
}
|
||||
|
||||
.el-dialog {
|
||||
border-radius: var(--ba-radius-panel);
|
||||
box-shadow: 0 24px 70px rgba(15, 23, 42, 0.2);
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.el-dialog__header {
|
||||
margin-right: 0;
|
||||
padding: 18px 22px;
|
||||
border-bottom: 1px solid var(--ba-border-color-soft);
|
||||
}
|
||||
|
||||
.el-dialog__title {
|
||||
color: var(--el-text-color-primary);
|
||||
font-weight: 700;
|
||||
}
|
||||
|
||||
.el-dialog__body {
|
||||
padding: 20px 22px;
|
||||
}
|
||||
|
||||
.el-dialog__footer {
|
||||
padding: 14px 22px 18px;
|
||||
background: var(--ba-bg-color-soft);
|
||||
border-top: 1px solid var(--ba-border-color-soft);
|
||||
}
|
||||
|
||||
.el-overlay {
|
||||
backdrop-filter: blur(2px);
|
||||
}
|
||||
|
||||
.el-popper,
|
||||
.el-dropdown__popper,
|
||||
.el-popover.el-popper {
|
||||
border: 1px solid var(--ba-border-color-soft);
|
||||
border-radius: var(--ba-radius-panel);
|
||||
box-shadow: var(--ba-shadow-soft);
|
||||
}
|
||||
|
||||
.el-dropdown-menu {
|
||||
padding: 6px;
|
||||
}
|
||||
|
||||
.el-dropdown-menu__item {
|
||||
border-radius: 6px;
|
||||
}
|
||||
|
||||
.el-pagination {
|
||||
font-variant-numeric: tabular-nums;
|
||||
}
|
||||
|
||||
.el-pagination.is-background .el-pager li,
|
||||
.el-pagination.is-background .btn-prev,
|
||||
.el-pagination.is-background .btn-next {
|
||||
border-radius: 7px;
|
||||
}
|
||||
|
||||
.el-tag {
|
||||
border-radius: 6px;
|
||||
font-weight: 600;
|
||||
}
|
||||
|
||||
.el-alert {
|
||||
border-radius: var(--ba-radius-panel);
|
||||
}
|
||||
|
||||
.el-divider__text.is-center {
|
||||
@@ -38,7 +208,7 @@
|
||||
}
|
||||
}
|
||||
.el-textarea__inner {
|
||||
padding: 5px 11px;
|
||||
padding: 7px 11px;
|
||||
}
|
||||
.datetime-picker {
|
||||
height: 32px;
|
||||
@@ -55,14 +225,14 @@
|
||||
height: 5px;
|
||||
}
|
||||
&::-webkit-scrollbar-thumb {
|
||||
background: #eaeaea;
|
||||
background: #d5dde8;
|
||||
border-radius: var(--el-border-radius-base);
|
||||
box-shadow: none;
|
||||
-webkit-box-shadow: none;
|
||||
}
|
||||
&:hover {
|
||||
&::-webkit-scrollbar-thumb:hover {
|
||||
background: #c8c9cc;
|
||||
background: #aeb9c8;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -70,7 +240,7 @@
|
||||
.el-overlay-dialog,
|
||||
.ba-scroll-style {
|
||||
scrollbar-width: thin;
|
||||
scrollbar-color: #c8c9cc #eaeaea;
|
||||
scrollbar-color: #aeb9c8 #d5dde8;
|
||||
}
|
||||
}
|
||||
/* dialog 滚动条样式优化结束 >>> */
|
||||
|
||||
@@ -2,4 +2,5 @@
|
||||
@use '/@/styles/element';
|
||||
@use '/@/styles/var';
|
||||
@use '/@/styles/dark';
|
||||
@use '/@/styles/report-table';
|
||||
@use '/@/styles/markdown';
|
||||
|
||||
276
web/src/styles/report-table.scss
Normal file
276
web/src/styles/report-table.scss
Normal file
@@ -0,0 +1,276 @@
|
||||
.admin-report-page {
|
||||
color: var(--el-text-color-primary);
|
||||
font-size: 14px;
|
||||
font-variant-numeric: tabular-nums;
|
||||
}
|
||||
|
||||
.admin-report-tabs {
|
||||
display: flex;
|
||||
width: fit-content;
|
||||
max-width: 100%;
|
||||
gap: 4px;
|
||||
margin-bottom: var(--ba-main-space);
|
||||
padding: 4px;
|
||||
overflow-x: auto;
|
||||
border: 1px solid var(--ba-border-color-soft);
|
||||
border-radius: var(--ba-radius-panel);
|
||||
background: var(--ba-bg-color-overlay);
|
||||
box-shadow: var(--ba-shadow-card);
|
||||
|
||||
button {
|
||||
min-height: 34px;
|
||||
padding: 0 18px;
|
||||
border: 0;
|
||||
border-radius: var(--ba-radius-control);
|
||||
background: transparent;
|
||||
color: var(--el-text-color-regular);
|
||||
font-weight: 600;
|
||||
white-space: nowrap;
|
||||
cursor: pointer;
|
||||
transition:
|
||||
color 0.18s ease,
|
||||
background-color 0.18s ease,
|
||||
box-shadow 0.18s ease;
|
||||
|
||||
&:hover {
|
||||
background: var(--el-color-primary-light-9);
|
||||
color: var(--el-color-primary);
|
||||
}
|
||||
|
||||
&.active {
|
||||
background: var(--el-color-primary);
|
||||
color: var(--el-color-white);
|
||||
box-shadow: 0 8px 18px rgba(37, 99, 235, 0.18);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.admin-report-filter {
|
||||
margin-bottom: var(--ba-main-space);
|
||||
overflow: hidden;
|
||||
border: 1px solid var(--ba-border-color-soft);
|
||||
border-radius: var(--ba-radius-panel);
|
||||
background: var(--ba-bg-color-overlay);
|
||||
box-shadow: var(--ba-shadow-card);
|
||||
}
|
||||
|
||||
.admin-report-heading {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
gap: 12px;
|
||||
min-height: 46px;
|
||||
padding: 13px 16px;
|
||||
border-bottom: 1px solid var(--ba-border-color-soft);
|
||||
background: var(--ba-bg-color-soft);
|
||||
color: var(--el-text-color-primary);
|
||||
font-weight: 700;
|
||||
|
||||
strong {
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
min-height: 24px;
|
||||
padding: 0 10px;
|
||||
border-radius: 999px;
|
||||
background: var(--el-color-success-light-9);
|
||||
color: var(--el-color-success);
|
||||
font-size: 12px;
|
||||
font-weight: 700;
|
||||
}
|
||||
}
|
||||
|
||||
.admin-report-filter-content {
|
||||
padding: 16px;
|
||||
background: var(--ba-bg-color-overlay);
|
||||
}
|
||||
|
||||
.admin-report-filter-content .filter-item,
|
||||
.admin-report-filter-content .date-fields {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 8px;
|
||||
}
|
||||
|
||||
.admin-report-filter-content label {
|
||||
color: var(--el-text-color-secondary);
|
||||
font-weight: 600;
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
.admin-report-filter-content .el-date-editor,
|
||||
.admin-report-filter-content .el-input,
|
||||
.admin-report-filter-content .el-select {
|
||||
width: 200px;
|
||||
}
|
||||
|
||||
.admin-report-actions {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 8px;
|
||||
|
||||
.el-button {
|
||||
min-width: 92px;
|
||||
margin: 0;
|
||||
}
|
||||
}
|
||||
|
||||
.admin-report-summary {
|
||||
margin: 0 0 10px;
|
||||
color: var(--el-text-color-regular);
|
||||
font-size: 13px;
|
||||
|
||||
strong {
|
||||
color: var(--el-text-color-primary);
|
||||
font-weight: 700;
|
||||
}
|
||||
}
|
||||
|
||||
.admin-report-table-wrap {
|
||||
overflow-x: auto;
|
||||
border: 1px solid var(--ba-border-color-soft);
|
||||
border-radius: var(--ba-radius-panel);
|
||||
background: var(--ba-bg-color-overlay);
|
||||
box-shadow: var(--ba-shadow-card);
|
||||
}
|
||||
|
||||
.admin-report-table {
|
||||
width: 100%;
|
||||
border-collapse: separate;
|
||||
border-spacing: 0;
|
||||
color: var(--el-text-color-regular);
|
||||
font-size: 13px;
|
||||
line-height: 1.45;
|
||||
font-variant-numeric: tabular-nums;
|
||||
|
||||
th,
|
||||
td {
|
||||
height: 42px;
|
||||
padding: 10px 12px;
|
||||
border-right: 1px solid var(--ba-border-color-soft);
|
||||
border-bottom: 1px solid var(--ba-border-color-soft);
|
||||
background: var(--ba-bg-color-overlay);
|
||||
text-align: left;
|
||||
vertical-align: middle;
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
th:last-child,
|
||||
td:last-child {
|
||||
border-right: 0;
|
||||
}
|
||||
|
||||
thead th {
|
||||
border-bottom-color: var(--ba-border-color-strong);
|
||||
background: var(--ba-bg-color-soft);
|
||||
color: var(--el-text-color-primary);
|
||||
font-weight: 700;
|
||||
|
||||
small {
|
||||
display: block;
|
||||
margin-top: 2px;
|
||||
color: var(--el-text-color-secondary);
|
||||
font-size: 11px;
|
||||
font-weight: 500;
|
||||
}
|
||||
}
|
||||
|
||||
tbody tr:last-child td {
|
||||
border-bottom: 0;
|
||||
}
|
||||
|
||||
tbody tr:hover td {
|
||||
background: var(--el-color-primary-light-9);
|
||||
}
|
||||
|
||||
.date-cell,
|
||||
.reward-cell {
|
||||
background: var(--ba-bg-color-soft);
|
||||
}
|
||||
|
||||
.deposit-value,
|
||||
.positive-value {
|
||||
color: var(--el-color-success);
|
||||
font-weight: 700;
|
||||
}
|
||||
|
||||
.withdraw-value,
|
||||
.negative-value {
|
||||
color: var(--el-color-danger);
|
||||
font-weight: 700;
|
||||
}
|
||||
|
||||
.unclaim-value {
|
||||
color: var(--el-color-primary);
|
||||
font-weight: 700;
|
||||
}
|
||||
|
||||
.empty-row {
|
||||
height: 150px;
|
||||
color: var(--el-text-color-secondary);
|
||||
text-align: center;
|
||||
}
|
||||
}
|
||||
|
||||
.admin-report-footer {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
gap: 12px;
|
||||
margin-top: 12px;
|
||||
padding: 12px 16px;
|
||||
border: 1px solid var(--ba-border-color-soft);
|
||||
border-radius: var(--ba-radius-panel);
|
||||
background: var(--ba-bg-color-overlay);
|
||||
box-shadow: var(--ba-shadow-card);
|
||||
color: var(--el-text-color-secondary);
|
||||
font-size: 13px;
|
||||
}
|
||||
|
||||
.admin-report-page-size {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 8px;
|
||||
|
||||
.el-select {
|
||||
width: 96px;
|
||||
}
|
||||
}
|
||||
|
||||
html.dark {
|
||||
.admin-report-heading strong {
|
||||
background: rgba(22, 138, 91, 0.18);
|
||||
}
|
||||
}
|
||||
|
||||
@media (max-width: 768px) {
|
||||
.admin-report-tabs {
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.admin-report-filter-content {
|
||||
padding: 12px;
|
||||
}
|
||||
|
||||
.admin-report-filter-content .filter-item,
|
||||
.admin-report-filter-content .date-fields {
|
||||
align-items: flex-start;
|
||||
flex-direction: column;
|
||||
}
|
||||
|
||||
.admin-report-filter-content .el-date-editor,
|
||||
.admin-report-filter-content .el-input,
|
||||
.admin-report-filter-content .el-select {
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.admin-report-actions,
|
||||
.admin-report-footer {
|
||||
align-items: stretch;
|
||||
flex-direction: column;
|
||||
}
|
||||
|
||||
.admin-report-actions .el-button,
|
||||
.admin-report-footer .el-pagination {
|
||||
width: 100%;
|
||||
}
|
||||
}
|
||||
@@ -2,15 +2,24 @@
|
||||
@use 'mixins' as *;
|
||||
|
||||
// 后台主体窗口左右间距
|
||||
$main-space: 16px;
|
||||
$primary-light: #3f6ad8;
|
||||
$main-space: 18px;
|
||||
$primary-light: #2563eb;
|
||||
$surface-soft: #eef3f8;
|
||||
$surface-muted: #f7f9fc;
|
||||
$text-muted: #64748b;
|
||||
$shadow-soft: 0 14px 34px rgba(15, 23, 42, 0.08);
|
||||
$shadow-card: 0 10px 24px rgba(15, 23, 42, 0.06);
|
||||
$radius-panel: 10px;
|
||||
$radius-control: 7px;
|
||||
|
||||
// --ba-background
|
||||
$bg-color: () !default;
|
||||
$bg-color: map.merge(
|
||||
(
|
||||
'': #f5f5f5,
|
||||
'': #eef3f8,
|
||||
'overlay': #ffffff,
|
||||
'soft': $surface-muted,
|
||||
'muted': $surface-soft,
|
||||
),
|
||||
$bg-color
|
||||
);
|
||||
@@ -19,7 +28,9 @@ $bg-color: map.merge(
|
||||
$border-color: () !default;
|
||||
$border-color: map.merge(
|
||||
(
|
||||
'': #f6f6f6,
|
||||
'': #d8e0ea,
|
||||
'soft': #e8eef5,
|
||||
'strong': #c7d2de,
|
||||
),
|
||||
$border-color
|
||||
);
|
||||
@@ -27,6 +38,38 @@ $border-color: map.merge(
|
||||
:root {
|
||||
@include set-css-var-value('main-space', $main-space);
|
||||
@include set-css-var-value('color-primary-light', $primary-light);
|
||||
@include set-css-var-value('surface-soft', $surface-soft);
|
||||
@include set-css-var-value('surface-muted', $surface-muted);
|
||||
@include set-css-var-value('text-muted', $text-muted);
|
||||
@include set-css-var-value('shadow-soft', $shadow-soft);
|
||||
@include set-css-var-value('shadow-card', $shadow-card);
|
||||
@include set-css-var-value('radius-panel', $radius-panel);
|
||||
@include set-css-var-value('radius-control', $radius-control);
|
||||
@include set-component-css-var('bg-color', $bg-color);
|
||||
@include set-component-css-var('border-color', $border-color);
|
||||
|
||||
--el-color-primary: #2563eb;
|
||||
--el-color-primary-light-3: #5b86f0;
|
||||
--el-color-primary-light-5: #8eadf5;
|
||||
--el-color-primary-light-7: #c7d7fb;
|
||||
--el-color-primary-light-8: #dbe6fd;
|
||||
--el-color-primary-light-9: #eef4ff;
|
||||
--el-color-primary-dark-2: #1d4ed8;
|
||||
--el-color-success: #168a5b;
|
||||
--el-color-success-light-9: #ecfdf5;
|
||||
--el-color-warning: #b7791f;
|
||||
--el-color-warning-light-9: #fff7ed;
|
||||
--el-color-danger: #dc3f4d;
|
||||
--el-color-danger-light-9: #fff1f2;
|
||||
--el-color-info: #64748b;
|
||||
--el-border-radius-base: #{$radius-control};
|
||||
--el-border-radius-small: 5px;
|
||||
--el-border-radius-round: #{$radius-panel};
|
||||
--el-box-shadow-light: #{$shadow-card};
|
||||
--el-box-shadow: #{$shadow-soft};
|
||||
--el-text-color-primary: #172033;
|
||||
--el-text-color-regular: #334155;
|
||||
--el-text-color-secondary: #64748b;
|
||||
--el-fill-color-light: #f7f9fc;
|
||||
--el-fill-color-lighter: #fbfcfe;
|
||||
}
|
||||
|
||||
@@ -14,7 +14,12 @@
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr v-for="bank in visibleBanks" :key="bank.id" :class="bank.rowClass" :style="{ backgroundColor: bank.labelColor }">
|
||||
<tr
|
||||
v-for="bank in visibleBanks"
|
||||
:key="bank.id"
|
||||
:class="[bank.rowClass, { 'bank-colored': bank.labelColor }]"
|
||||
:style="bankRowStyle(bank)"
|
||||
>
|
||||
<td>
|
||||
<strong>{{ bank.name }}</strong>
|
||||
<small>{{ bank.account }}</small>
|
||||
@@ -22,11 +27,50 @@
|
||||
<td class="balance">AUD {{ money(bank.balance) }}</td>
|
||||
<td>
|
||||
<div class="bank-operate">
|
||||
<el-button size="small" :icon="Coin" circle />
|
||||
<el-button size="small" :icon="Switch" @click="openTransfer(bank)">{{ t('dashboard.Transfer') }}</el-button>
|
||||
<div class="breakdown">
|
||||
<span><i class="dot income">↓</i> ({{ bank.depositCount }}) {{ money(bank.deposit) }}</span>
|
||||
<span><i class="dot outcome">↑</i> ({{ bank.withdrawCount }}) {{ money(bank.withdraw) }}</span>
|
||||
<input :id="calculatorToggleId(bank)" class="calculator-toggle" type="checkbox" />
|
||||
<div class="bank-operate-main">
|
||||
<label
|
||||
class="calculator-button"
|
||||
:for="calculatorToggleId(bank)"
|
||||
:aria-label="t('dashboard.Fast Calculation')"
|
||||
:title="t('dashboard.Fast Calculation')"
|
||||
>
|
||||
<Icon name="fa fa-calculator" size="13" color="currentColor" />
|
||||
</label>
|
||||
<el-button size="small" :icon="Switch" @click="openTransfer(bank)">
|
||||
{{ t('dashboard.Transfer') }}
|
||||
</el-button>
|
||||
<div class="breakdown">
|
||||
<div class="breakdown-row breakdown-in">
|
||||
<span class="breakdown-label">入</span>
|
||||
<span class="breakdown-count">({{ bank.depositCount }})</span>
|
||||
<strong>{{ money(bank.deposit) }}</strong>
|
||||
</div>
|
||||
<div class="breakdown-row breakdown-out">
|
||||
<span class="breakdown-label">出</span>
|
||||
<span class="breakdown-count">({{ bank.withdrawCount }})</span>
|
||||
<strong>{{ money(bank.withdraw) }}</strong>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="bank-calculator">
|
||||
<div class="calculator-formula">
|
||||
<el-input
|
||||
v-model="calculatorFormulas[calculatorKey(bank)]"
|
||||
class="calculator-input"
|
||||
size="small"
|
||||
:placeholder="t('dashboard.Calculation placeholder')"
|
||||
clearable
|
||||
/>
|
||||
<span class="calculator-equals">=</span>
|
||||
<strong class="calculator-result" :class="{ 'is-invalid': isCalculatorInvalid(bank) }">
|
||||
{{ calculatorResultText(bank) }}
|
||||
</strong>
|
||||
</div>
|
||||
<div class="calculator-hint">
|
||||
{{ t('dashboard.Fast Calculation Support') }}
|
||||
<span>+ − × ÷</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</td>
|
||||
@@ -240,7 +284,7 @@
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { Coin, Switch } from '@element-plus/icons-vue'
|
||||
import { Switch } from '@element-plus/icons-vue'
|
||||
import { computed, onMounted, reactive, ref } from 'vue'
|
||||
import { useI18n } from 'vue-i18n'
|
||||
import { bankTransact, delTransact, editTransact, index as getDashboard, logHistory, newTransact } from '/@/api/backend/dashboard'
|
||||
@@ -357,6 +401,11 @@ interface HistoryRow {
|
||||
bankAfter: string
|
||||
}
|
||||
|
||||
interface CalculationResult {
|
||||
valid: boolean
|
||||
value: number
|
||||
}
|
||||
|
||||
const today = () => {
|
||||
const date = new Date()
|
||||
const pad = (value: number) => value.toString().padStart(2, '0')
|
||||
@@ -374,6 +423,249 @@ const toNumber = (value: unknown) => {
|
||||
return Number.isFinite(number) ? number : 0
|
||||
}
|
||||
|
||||
const normalizeCalculationFormula = (value: string) =>
|
||||
value
|
||||
.replace(/,/g, '')
|
||||
.replace(/乘以/g, '*')
|
||||
.replace(/除以/g, '/')
|
||||
.replace(/加/g, '+')
|
||||
.replace(/减/g, '-')
|
||||
.replace(/[+]/g, '+')
|
||||
.replace(/[-–—]/g, '-')
|
||||
.replace(/[×*xX]/g, '*')
|
||||
.replace(/[÷/]/g, '/')
|
||||
.replace(/\s+/g, '')
|
||||
.replace(/^=/, '')
|
||||
|
||||
const evaluateExpression = (expression: string) => {
|
||||
let index = 0
|
||||
|
||||
const parseNumber = () => {
|
||||
const matched = expression.slice(index).match(/^(?:\d+(?:\.\d*)?|\.\d+)/)
|
||||
if (!matched) return null
|
||||
|
||||
index += matched[0].length
|
||||
return Number(matched[0])
|
||||
}
|
||||
|
||||
const parseFactor = (): number | null => {
|
||||
const char = expression[index]
|
||||
|
||||
if (char === '+') {
|
||||
index += 1
|
||||
return parseFactor()
|
||||
}
|
||||
|
||||
if (char === '-') {
|
||||
index += 1
|
||||
const value = parseFactor()
|
||||
return value === null ? null : -value
|
||||
}
|
||||
|
||||
if (char === '(') {
|
||||
index += 1
|
||||
const value = parseExpression()
|
||||
|
||||
if (value === null || expression[index] !== ')') return null
|
||||
|
||||
index += 1
|
||||
return value
|
||||
}
|
||||
|
||||
return parseNumber()
|
||||
}
|
||||
|
||||
const parseTerm = (): number | null => {
|
||||
let value = parseFactor()
|
||||
if (value === null) return null
|
||||
|
||||
while (expression[index] === '*' || expression[index] === '/') {
|
||||
const operator = expression[index]
|
||||
index += 1
|
||||
const right = parseFactor()
|
||||
|
||||
if (right === null) return null
|
||||
|
||||
value = operator === '*' ? value * right : right === 0 ? Number.NaN : value / right
|
||||
}
|
||||
|
||||
return value
|
||||
}
|
||||
|
||||
function parseExpression(): number | null {
|
||||
let value = parseTerm()
|
||||
if (value === null) return null
|
||||
|
||||
while (expression[index] === '+' || expression[index] === '-') {
|
||||
const operator = expression[index]
|
||||
index += 1
|
||||
const right = parseTerm()
|
||||
|
||||
if (right === null) return null
|
||||
|
||||
value = operator === '+' ? value + right : value - right
|
||||
}
|
||||
|
||||
return value
|
||||
}
|
||||
|
||||
const result = parseExpression()
|
||||
|
||||
return result !== null && index === expression.length && Number.isFinite(result) ? result : null
|
||||
}
|
||||
|
||||
const calculateBalancePreview = (balance: number, formula: string): CalculationResult => {
|
||||
const normalized = normalizeCalculationFormula(formula)
|
||||
|
||||
if (!normalized) {
|
||||
return { valid: true, value: balance }
|
||||
}
|
||||
|
||||
if (!/^[\d+\-*/().]+$/.test(normalized)) {
|
||||
return { valid: false, value: balance }
|
||||
}
|
||||
|
||||
const expression = /^[+\-*/]/.test(normalized) ? `${balance}${normalized}` : `${balance}+${normalized}`
|
||||
const value = evaluateExpression(expression)
|
||||
|
||||
return value === null ? { valid: false, value: balance } : { valid: true, value }
|
||||
}
|
||||
|
||||
const clampRgbChannel = (value: number) => Math.min(255, Math.max(0, Math.round(value)))
|
||||
|
||||
const parseColorChannel = (value: string) => {
|
||||
const number = Number(value)
|
||||
return Number.isFinite(number) ? clampRgbChannel(number) : 0
|
||||
}
|
||||
|
||||
const parseAlphaChannel = (value?: string) => {
|
||||
if (value === undefined) return 1
|
||||
|
||||
const number = Number(value)
|
||||
return Number.isFinite(number) ? Math.min(1, Math.max(0, number)) : 1
|
||||
}
|
||||
|
||||
const parseColorToRgb = (value: string) => {
|
||||
const color = value.trim()
|
||||
const hex = color.match(/^#([0-9a-f]{3}|[0-9a-f]{6}|[0-9a-f]{8})$/i)
|
||||
|
||||
if (hex) {
|
||||
const raw = hex[1]
|
||||
const full =
|
||||
raw.length === 3
|
||||
? raw
|
||||
.split('')
|
||||
.map((char) => char + char)
|
||||
.join('')
|
||||
: raw
|
||||
|
||||
return {
|
||||
r: Number.parseInt(full.slice(0, 2), 16),
|
||||
g: Number.parseInt(full.slice(2, 4), 16),
|
||||
b: Number.parseInt(full.slice(4, 6), 16),
|
||||
a: full.length === 8 ? Number.parseInt(full.slice(6, 8), 16) / 255 : 1,
|
||||
}
|
||||
}
|
||||
|
||||
const rgb = color.match(/^rgba?\(\s*([\d.]+)\s*,\s*([\d.]+)\s*,\s*([\d.]+)(?:\s*,\s*([\d.]+))?\s*\)$/i)
|
||||
|
||||
if (!rgb) return null
|
||||
|
||||
return {
|
||||
r: parseColorChannel(rgb[1]),
|
||||
g: parseColorChannel(rgb[2]),
|
||||
b: parseColorChannel(rgb[3]),
|
||||
a: parseAlphaChannel(rgb[4]),
|
||||
}
|
||||
}
|
||||
|
||||
const rgbToCss = (rgb: { r: number; g: number; b: number }) => `rgb(${clampRgbChannel(rgb.r)}, ${clampRgbChannel(rgb.g)}, ${clampRgbChannel(rgb.b)})`
|
||||
|
||||
const mixRgb = (source: { r: number; g: number; b: number }, target: { r: number; g: number; b: number }, targetWeight: number) => ({
|
||||
r: source.r * (1 - targetWeight) + target.r * targetWeight,
|
||||
g: source.g * (1 - targetWeight) + target.g * targetWeight,
|
||||
b: source.b * (1 - targetWeight) + target.b * targetWeight,
|
||||
})
|
||||
|
||||
const polishedBankRowColor = (backgroundColor: string) => {
|
||||
const rgb = parseColorToRgb(backgroundColor)
|
||||
if (!rgb) return backgroundColor
|
||||
|
||||
const blended = {
|
||||
r: rgb.r * rgb.a + 255 * (1 - rgb.a),
|
||||
g: rgb.g * rgb.a + 255 * (1 - rgb.a),
|
||||
b: rgb.b * rgb.a + 255 * (1 - rgb.a),
|
||||
}
|
||||
const max = Math.max(blended.r, blended.g, blended.b)
|
||||
const min = Math.min(blended.r, blended.g, blended.b)
|
||||
|
||||
if (max - min < 18) {
|
||||
return rgbToCss(mixRgb(blended, { r: 241, g: 245, b: 249 }, 0.72))
|
||||
}
|
||||
|
||||
if (blended.g >= blended.r && blended.g >= blended.b) {
|
||||
return '#d9f3e5'
|
||||
}
|
||||
|
||||
if (blended.r >= blended.g && blended.r >= blended.b) {
|
||||
return '#f8dde2'
|
||||
}
|
||||
|
||||
return '#dbeafe'
|
||||
}
|
||||
|
||||
const srgbToLinear = (channel: number) => {
|
||||
const value = channel / 255
|
||||
return value <= 0.03928 ? value / 12.92 : Math.pow((value + 0.055) / 1.055, 2.4)
|
||||
}
|
||||
|
||||
const relativeLuminance = (rgb: { r: number; g: number; b: number }) =>
|
||||
0.2126 * srgbToLinear(rgb.r) + 0.7152 * srgbToLinear(rgb.g) + 0.0722 * srgbToLinear(rgb.b)
|
||||
|
||||
const contrastRatio = (first: number, second: number) => {
|
||||
const lighter = Math.max(first, second)
|
||||
const darker = Math.min(first, second)
|
||||
return (lighter + 0.05) / (darker + 0.05)
|
||||
}
|
||||
|
||||
const readableTextColor = (backgroundColor: string) => {
|
||||
const rgb = parseColorToRgb(backgroundColor)
|
||||
if (!rgb) return '#172033'
|
||||
|
||||
const blended = {
|
||||
r: rgb.r * rgb.a + 255 * (1 - rgb.a),
|
||||
g: rgb.g * rgb.a + 255 * (1 - rgb.a),
|
||||
b: rgb.b * rgb.a + 255 * (1 - rgb.a),
|
||||
}
|
||||
const luminance = relativeLuminance(blended)
|
||||
const slateContrast = contrastRatio(luminance, relativeLuminance({ r: 23, g: 32, b: 51 }))
|
||||
const whiteContrast = contrastRatio(luminance, 1)
|
||||
const darkContrast = contrastRatio(luminance, 0)
|
||||
|
||||
if (slateContrast >= 4.5 || slateContrast >= whiteContrast) {
|
||||
return '#172033'
|
||||
}
|
||||
|
||||
return whiteContrast >= darkContrast ? '#ffffff' : '#000000'
|
||||
}
|
||||
|
||||
const bankRowStyle = (bank: Bank): Record<string, string> => {
|
||||
if (!bank.labelColor) return {}
|
||||
|
||||
const backgroundColor = polishedBankRowColor(bank.labelColor)
|
||||
const textColor = readableTextColor(backgroundColor)
|
||||
const isLightText = textColor === '#ffffff'
|
||||
|
||||
return {
|
||||
backgroundColor,
|
||||
'--bank-row-text-color': textColor,
|
||||
'--bank-row-muted-color': isLightText ? 'rgba(255, 255, 255, 0.82)' : 'rgba(0, 0, 0, 0.72)',
|
||||
'--bank-row-border-color': isLightText ? 'rgba(255, 255, 255, 0.24)' : 'rgba(0, 0, 0, 0.16)',
|
||||
'--bank-row-control-bg': isLightText ? 'rgba(255, 255, 255, 0.16)' : 'rgba(255, 255, 255, 0.72)',
|
||||
'--bank-row-control-hover-bg': isLightText ? 'rgba(255, 255, 255, 0.26)' : 'rgba(255, 255, 255, 0.88)',
|
||||
}
|
||||
}
|
||||
|
||||
const formatDateTime = (value: unknown) => {
|
||||
if (typeof value === 'string' && value.trim() && !Number.isFinite(Number(value))) {
|
||||
return value
|
||||
@@ -435,6 +727,7 @@ const transactionPage = reactive({
|
||||
pageSize: 10,
|
||||
})
|
||||
const showAllBanks = ref(false)
|
||||
const calculatorFormulas = reactive<Record<string, string>>({})
|
||||
const visibleBanks = computed(() => (showAllBanks.value ? banks.value : banks.value.slice(0, 4)))
|
||||
const totalDeposit = computed(() => transactionTotals.totalDeposit)
|
||||
const totalWithdraw = computed(() => transactionTotals.totalWithdraw)
|
||||
@@ -460,6 +753,19 @@ const summary = computed(() => [
|
||||
{ label: t('dashboard.Unclaimed Receipt'), value: customerSummary.unclaimReceipt },
|
||||
])
|
||||
|
||||
const calculatorKey = (bank: Bank) => String(bank.id)
|
||||
|
||||
const calculatorToggleId = (bank: Bank) => `bank-calculator-${calculatorKey(bank).replace(/[^a-zA-Z0-9_-]/g, '-')}`
|
||||
|
||||
const calculatorResult = (bank: Bank) => calculateBalancePreview(bank.balance, calculatorFormulas[calculatorKey(bank)] || '')
|
||||
|
||||
const isCalculatorInvalid = (bank: Bank) => !calculatorResult(bank).valid
|
||||
|
||||
const calculatorResultText = (bank: Bank) => {
|
||||
const result = calculatorResult(bank)
|
||||
return result.valid ? `AUD ${money(result.value)}` : 'AUD --'
|
||||
}
|
||||
|
||||
const transactionDialog = reactive<{ visible: boolean; loading: boolean; mode: 'create' | 'edit'; editId: number | string | '' }>({
|
||||
visible: false,
|
||||
loading: false,
|
||||
@@ -753,25 +1059,29 @@ onMounted(() => {
|
||||
.bookkeeping-dashboard {
|
||||
color: var(--el-text-color-primary);
|
||||
font-size: 13px;
|
||||
font-variant-numeric: tabular-nums;
|
||||
}
|
||||
.dashboard-grid {
|
||||
display: grid;
|
||||
grid-template-columns: minmax(0, 1fr) 310px;
|
||||
gap: 16px;
|
||||
gap: var(--ba-main-space);
|
||||
}
|
||||
.dashboard-panel,
|
||||
.transaction-section {
|
||||
border: 1px solid var(--el-border-color);
|
||||
border-radius: 4px;
|
||||
background: var(--el-bg-color);
|
||||
border: 1px solid var(--ba-border-color-soft);
|
||||
border-radius: var(--ba-radius-panel);
|
||||
background: var(--ba-bg-color-overlay);
|
||||
box-shadow: var(--ba-shadow-card);
|
||||
overflow: hidden;
|
||||
}
|
||||
.panel-title {
|
||||
padding: 11px 14px;
|
||||
border-bottom: 1px solid var(--el-border-color);
|
||||
background: var(--el-fill-color-light);
|
||||
padding: 13px 16px;
|
||||
border-bottom: 1px solid var(--ba-border-color-soft);
|
||||
background: var(--ba-bg-color-soft);
|
||||
color: var(--el-text-color-primary);
|
||||
font-size: 15px;
|
||||
font-weight: 700;
|
||||
line-height: 1.4;
|
||||
}
|
||||
.table-scroll {
|
||||
overflow-x: auto;
|
||||
@@ -781,16 +1091,68 @@ onMounted(() => {
|
||||
border-collapse: collapse;
|
||||
th,
|
||||
td {
|
||||
padding: 9px 12px;
|
||||
border-bottom: 1px solid var(--el-border-color-lighter);
|
||||
padding: 11px 14px;
|
||||
border-bottom: 1px solid var(--ba-border-color-soft);
|
||||
text-align: left;
|
||||
vertical-align: middle;
|
||||
}
|
||||
th {
|
||||
color: var(--el-text-color-secondary);
|
||||
font-size: 12px;
|
||||
font-weight: 700;
|
||||
background: var(--ba-bg-color-soft);
|
||||
white-space: nowrap;
|
||||
}
|
||||
tbody tr {
|
||||
transition: background-color 0.18s ease;
|
||||
}
|
||||
tbody tr:hover:not(.bank-colored) {
|
||||
background: var(--el-color-primary-light-9);
|
||||
}
|
||||
tbody tr.bank-colored {
|
||||
color: var(--bank-row-text-color);
|
||||
text-shadow: none;
|
||||
|
||||
td {
|
||||
border-bottom-color: var(--bank-row-border-color);
|
||||
}
|
||||
|
||||
small {
|
||||
color: var(--bank-row-muted-color);
|
||||
}
|
||||
|
||||
.balance {
|
||||
color: inherit;
|
||||
}
|
||||
|
||||
:deep(.el-button) {
|
||||
--el-button-text-color: var(--bank-row-text-color);
|
||||
--el-button-bg-color: var(--bank-row-control-bg);
|
||||
--el-button-border-color: var(--bank-row-border-color);
|
||||
--el-button-hover-text-color: var(--bank-row-text-color);
|
||||
--el-button-hover-bg-color: var(--bank-row-control-hover-bg);
|
||||
--el-button-hover-border-color: var(--bank-row-border-color);
|
||||
--el-button-active-text-color: var(--bank-row-text-color);
|
||||
--el-button-active-bg-color: var(--bank-row-control-hover-bg);
|
||||
--el-button-active-border-color: var(--bank-row-border-color);
|
||||
}
|
||||
|
||||
.calculator-button {
|
||||
color: var(--bank-row-text-color);
|
||||
border-color: var(--bank-row-border-color);
|
||||
background: var(--bank-row-control-bg);
|
||||
&:hover,
|
||||
&:focus-visible {
|
||||
background: var(--bank-row-control-hover-bg);
|
||||
}
|
||||
}
|
||||
|
||||
:deep(.el-tag) {
|
||||
color: var(--bank-row-text-color);
|
||||
border-color: var(--bank-row-border-color);
|
||||
background: var(--bank-row-control-bg);
|
||||
}
|
||||
}
|
||||
strong,
|
||||
small {
|
||||
display: block;
|
||||
@@ -815,15 +1177,164 @@ onMounted(() => {
|
||||
}
|
||||
.bank-operate {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 7px;
|
||||
flex-direction: column;
|
||||
align-items: flex-start;
|
||||
gap: 8px;
|
||||
:deep(.el-button.is-circle) {
|
||||
width: 30px;
|
||||
height: 30px;
|
||||
}
|
||||
}
|
||||
.breakdown {
|
||||
.bank-operate-main {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
flex-wrap: wrap;
|
||||
gap: 8px;
|
||||
}
|
||||
.calculator-toggle {
|
||||
position: absolute;
|
||||
width: 1px;
|
||||
height: 1px;
|
||||
opacity: 0;
|
||||
pointer-events: none;
|
||||
}
|
||||
.calculator-toggle:not(:checked) ~ .bank-calculator {
|
||||
display: none;
|
||||
}
|
||||
.calculator-toggle:checked + .bank-operate-main .calculator-button {
|
||||
border-color: var(--el-color-primary);
|
||||
background: var(--el-color-primary-light-9);
|
||||
color: var(--el-color-primary);
|
||||
}
|
||||
.calculator-toggle:focus-visible + .bank-operate-main .calculator-button {
|
||||
outline: 2px solid var(--el-color-primary-light-5);
|
||||
outline-offset: 2px;
|
||||
}
|
||||
.calculator-button {
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
width: 30px;
|
||||
height: 30px;
|
||||
padding: 0;
|
||||
border: 1px solid var(--el-border-color);
|
||||
border-radius: 50%;
|
||||
background: var(--el-bg-color);
|
||||
color: var(--el-text-color-regular);
|
||||
cursor: pointer;
|
||||
line-height: 1;
|
||||
transition:
|
||||
background-color 0.18s ease,
|
||||
border-color 0.18s ease,
|
||||
color 0.18s ease;
|
||||
&:hover,
|
||||
&:focus-visible {
|
||||
border-color: var(--el-color-primary);
|
||||
color: var(--el-color-primary);
|
||||
background: var(--el-color-primary-light-9);
|
||||
outline: none;
|
||||
}
|
||||
}
|
||||
.bank-calculator {
|
||||
width: min(300px, 100%);
|
||||
padding: 6px 8px 5px;
|
||||
border: 1px solid var(--ba-border-color-soft);
|
||||
border-radius: 2px;
|
||||
background: rgba(255, 255, 255, 0.94);
|
||||
box-shadow: 0 6px 14px rgba(15, 23, 42, 0.08);
|
||||
color: var(--el-text-color-primary);
|
||||
}
|
||||
.calculator-formula {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 5px;
|
||||
}
|
||||
.calculator-input {
|
||||
flex: 1 1 125px;
|
||||
min-width: 112px;
|
||||
:deep(.el-input__wrapper) {
|
||||
min-height: 28px;
|
||||
border-radius: 0;
|
||||
box-shadow: 0 0 0 1px rgba(148, 163, 184, 0.72) inset;
|
||||
}
|
||||
}
|
||||
.calculator-equals {
|
||||
color: var(--el-text-color-primary);
|
||||
font-size: 15px;
|
||||
font-weight: 700;
|
||||
line-height: 1;
|
||||
}
|
||||
.calculator-result {
|
||||
min-width: 92px;
|
||||
color: var(--el-text-color-primary);
|
||||
font-size: 15px;
|
||||
font-weight: 700;
|
||||
line-height: 1;
|
||||
white-space: nowrap;
|
||||
&.is-invalid {
|
||||
color: var(--el-color-danger);
|
||||
}
|
||||
}
|
||||
.calculator-hint {
|
||||
margin-top: 3px;
|
||||
color: var(--el-text-color-regular);
|
||||
font-size: 11px;
|
||||
line-height: 1.2;
|
||||
span {
|
||||
margin-left: 4px;
|
||||
font-size: 12px;
|
||||
font-weight: 700;
|
||||
letter-spacing: 1px;
|
||||
}
|
||||
}
|
||||
.breakdown {
|
||||
display: inline-flex;
|
||||
flex-direction: column;
|
||||
gap: 4px;
|
||||
min-width: 118px;
|
||||
padding: 5px 8px;
|
||||
border: 1px solid rgba(148, 163, 184, 0.28);
|
||||
border-radius: 4px;
|
||||
background: rgba(248, 250, 252, 0.94);
|
||||
color: var(--el-text-color-regular);
|
||||
box-shadow: 0 1px 0 rgba(15, 23, 42, 0.04);
|
||||
}
|
||||
.breakdown-row {
|
||||
display: grid;
|
||||
grid-template-columns: 18px auto minmax(0, 1fr);
|
||||
align-items: center;
|
||||
gap: 4px;
|
||||
font-size: 12px;
|
||||
font-weight: 700;
|
||||
line-height: 1.15;
|
||||
white-space: nowrap;
|
||||
}
|
||||
.breakdown-label {
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
width: 18px;
|
||||
height: 18px;
|
||||
border-radius: 3px;
|
||||
color: #ffffff;
|
||||
font-size: 11px;
|
||||
font-weight: 700;
|
||||
}
|
||||
.breakdown-count {
|
||||
color: var(--el-text-color-secondary);
|
||||
font-weight: 600;
|
||||
}
|
||||
.breakdown-in {
|
||||
color: var(--el-color-success);
|
||||
.breakdown-label {
|
||||
background: var(--el-color-success);
|
||||
}
|
||||
}
|
||||
.breakdown-out {
|
||||
color: var(--el-color-danger);
|
||||
.breakdown-label {
|
||||
background: var(--el-color-danger);
|
||||
}
|
||||
}
|
||||
.dot {
|
||||
font-style: normal;
|
||||
@@ -840,16 +1351,22 @@ onMounted(() => {
|
||||
.more-info {
|
||||
display: block;
|
||||
width: 100%;
|
||||
padding: 9px;
|
||||
padding: 11px;
|
||||
border: 0;
|
||||
background: transparent;
|
||||
border-top: 1px solid var(--ba-border-color-soft);
|
||||
background: var(--ba-bg-color-soft);
|
||||
color: var(--el-color-primary);
|
||||
cursor: pointer;
|
||||
font-weight: 700;
|
||||
transition: background-color 0.18s ease;
|
||||
&:hover {
|
||||
background: var(--el-color-primary-light-9);
|
||||
}
|
||||
}
|
||||
.summary-side {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 14px;
|
||||
gap: var(--ba-main-space);
|
||||
}
|
||||
.summary-panel dl {
|
||||
display: grid;
|
||||
@@ -860,8 +1377,12 @@ onMounted(() => {
|
||||
.summary-panel dt,
|
||||
.summary-panel dd {
|
||||
margin: 0;
|
||||
padding: 8px 12px;
|
||||
border-bottom: 1px solid var(--el-border-color-lighter);
|
||||
padding: 10px 14px;
|
||||
border-bottom: 1px solid var(--ba-border-color-soft);
|
||||
}
|
||||
.summary-panel dt {
|
||||
color: var(--el-text-color-secondary);
|
||||
font-weight: 600;
|
||||
}
|
||||
.summary-panel dd {
|
||||
color: var(--el-color-primary);
|
||||
@@ -870,11 +1391,12 @@ onMounted(() => {
|
||||
}
|
||||
.create-button {
|
||||
width: 100%;
|
||||
min-height: 44px;
|
||||
min-height: 46px;
|
||||
font-weight: 700;
|
||||
}
|
||||
.webhook-alert {
|
||||
margin: 16px 0;
|
||||
margin: var(--ba-main-space) 0;
|
||||
border: 1px solid rgba(183, 121, 31, 0.24);
|
||||
p {
|
||||
margin: 6px 0 0;
|
||||
line-height: 1.5;
|
||||
@@ -883,9 +1405,10 @@ onMounted(() => {
|
||||
.filter-row {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
gap: 16px;
|
||||
padding: 12px;
|
||||
border-bottom: 1px solid var(--el-border-color);
|
||||
gap: 14px;
|
||||
padding: 14px 16px;
|
||||
border-bottom: 1px solid var(--ba-border-color-soft);
|
||||
background: var(--ba-bg-color-soft);
|
||||
}
|
||||
.date-filter,
|
||||
.totals {
|
||||
@@ -895,10 +1418,18 @@ onMounted(() => {
|
||||
gap: 8px;
|
||||
}
|
||||
.date-filter :deep(.el-date-editor) {
|
||||
width: 145px;
|
||||
width: 150px;
|
||||
}
|
||||
.date-filter label {
|
||||
color: var(--el-text-color-secondary);
|
||||
font-weight: 600;
|
||||
}
|
||||
.totals {
|
||||
justify-content: flex-end;
|
||||
color: var(--el-text-color-regular);
|
||||
b {
|
||||
font-weight: 700;
|
||||
}
|
||||
em {
|
||||
color: var(--el-color-primary);
|
||||
font-style: normal;
|
||||
@@ -913,7 +1444,9 @@ onMounted(() => {
|
||||
.pagination {
|
||||
display: flex;
|
||||
justify-content: flex-end;
|
||||
padding: 12px;
|
||||
padding: 14px 16px;
|
||||
border-top: 1px solid var(--ba-border-color-soft);
|
||||
background: var(--ba-bg-color-soft);
|
||||
}
|
||||
.inline-mode {
|
||||
margin-left: 12px;
|
||||
@@ -923,7 +1456,7 @@ onMounted(() => {
|
||||
color: var(--el-text-color-secondary);
|
||||
}
|
||||
:deep(.el-dialog__body) {
|
||||
padding-top: 12px;
|
||||
padding-top: 16px;
|
||||
}
|
||||
:deep(.el-form-item .el-select),
|
||||
:deep(.el-form-item .el-input) {
|
||||
@@ -938,11 +1471,24 @@ onMounted(() => {
|
||||
.filter-row {
|
||||
flex-direction: column;
|
||||
}
|
||||
.date-filter {
|
||||
align-items: stretch;
|
||||
label {
|
||||
width: 100%;
|
||||
}
|
||||
:deep(.el-date-editor),
|
||||
:deep(.el-button) {
|
||||
width: 100%;
|
||||
}
|
||||
}
|
||||
.totals {
|
||||
justify-content: flex-start;
|
||||
}
|
||||
.bank-table {
|
||||
min-width: 760px;
|
||||
}
|
||||
.pagination {
|
||||
justify-content: center;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
||||
@@ -18,10 +18,10 @@
|
||||
<div class="login">
|
||||
<div class="login-box">
|
||||
<div class="head">
|
||||
<img src="~assets/login-header.png" alt="" />
|
||||
<img src="~assets/login-header.png" alt="login" />
|
||||
</div>
|
||||
<div class="form">
|
||||
<img class="profile-avatar" :src="fullUrl('/static/images/avatar.png')" alt="" />
|
||||
<img class="profile-avatar" :src="fullUrl('/static/images/avatar.png')" alt="avatar" />
|
||||
<div class="content">
|
||||
<el-form @keyup.enter="onSubmitPre()" ref="formRef" :rules="rules" size="large" :model="form">
|
||||
<el-form-item prop="username">
|
||||
@@ -52,14 +52,7 @@
|
||||
</el-form-item>
|
||||
<el-checkbox v-model="form.keep" :label="t('login.Hold session')" size="default"></el-checkbox>
|
||||
<el-form-item>
|
||||
<el-button
|
||||
:loading="state.submitLoading"
|
||||
class="submit-button"
|
||||
round
|
||||
type="primary"
|
||||
size="large"
|
||||
@click="onSubmitPre()"
|
||||
>
|
||||
<el-button :loading="state.submitLoading" class="submit-button" type="primary" size="large" @click="onSubmitPre()">
|
||||
{{ t('login.Sign in') }}
|
||||
</el-button>
|
||||
</el-form-item>
|
||||
@@ -173,13 +166,26 @@ const onSubmit = (captchaInfo = '') => {
|
||||
<style scoped lang="scss">
|
||||
.switch-language {
|
||||
position: fixed;
|
||||
top: 20px;
|
||||
right: 20px;
|
||||
z-index: 1;
|
||||
top: 22px;
|
||||
right: 22px;
|
||||
z-index: 2;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
width: 42px;
|
||||
height: 42px;
|
||||
border: 1px solid rgba(148, 163, 184, 0.28);
|
||||
border-radius: var(--ba-radius-panel);
|
||||
background: rgba(255, 255, 255, 0.76);
|
||||
box-shadow: var(--ba-shadow-card);
|
||||
backdrop-filter: blur(10px);
|
||||
}
|
||||
.bubble {
|
||||
overflow: hidden;
|
||||
background: url(/@/assets/bg.jpg) repeat;
|
||||
background:
|
||||
linear-gradient(135deg, rgba(238, 243, 248, 0.94), rgba(226, 232, 240, 0.9)),
|
||||
url(/@/assets/bg.jpg) repeat;
|
||||
background-blend-mode: screen;
|
||||
}
|
||||
.form-item-icon {
|
||||
height: auto;
|
||||
@@ -189,21 +195,25 @@ const onSubmit = (captchaInfo = '') => {
|
||||
top: 0;
|
||||
display: flex;
|
||||
width: 100vw;
|
||||
height: 100vh;
|
||||
min-height: 100dvh;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
.login-box {
|
||||
overflow: hidden;
|
||||
width: 430px;
|
||||
width: min(430px, calc(100vw - 32px));
|
||||
padding: 0;
|
||||
background: var(--ba-bg-color-overlay);
|
||||
margin-bottom: 80px;
|
||||
margin-bottom: 64px;
|
||||
border: 1px solid rgba(216, 224, 234, 0.8);
|
||||
border-radius: 16px;
|
||||
box-shadow: 0 26px 72px rgba(15, 23, 42, 0.18);
|
||||
}
|
||||
.head {
|
||||
background: #ccccff;
|
||||
background: linear-gradient(135deg, rgba(37, 99, 235, 0.16), rgba(15, 23, 42, 0.02)), var(--ba-bg-color-soft);
|
||||
border-bottom: 1px solid var(--ba-border-color-soft);
|
||||
img {
|
||||
display: block;
|
||||
width: 430px;
|
||||
width: 100%;
|
||||
margin: 0 auto;
|
||||
user-select: none;
|
||||
}
|
||||
@@ -213,22 +223,27 @@ const onSubmit = (captchaInfo = '') => {
|
||||
.profile-avatar {
|
||||
display: block;
|
||||
position: absolute;
|
||||
height: 100px;
|
||||
width: 100px;
|
||||
border-radius: 50%;
|
||||
border: 4px solid var(--ba-bg-color-overlay);
|
||||
top: -50px;
|
||||
right: calc(50% - 50px);
|
||||
height: 92px;
|
||||
width: 92px;
|
||||
border-radius: 18px;
|
||||
border: 5px solid var(--ba-bg-color-overlay);
|
||||
top: -46px;
|
||||
right: calc(50% - 46px);
|
||||
z-index: 2;
|
||||
user-select: none;
|
||||
box-shadow: 0 12px 30px rgba(15, 23, 42, 0.16);
|
||||
}
|
||||
.content {
|
||||
padding: 100px 40px 40px 40px;
|
||||
padding: 92px 40px 40px 40px;
|
||||
:deep(.el-form-item) {
|
||||
margin-bottom: 20px;
|
||||
}
|
||||
}
|
||||
.submit-button {
|
||||
width: 100%;
|
||||
letter-spacing: 2px;
|
||||
font-weight: 300;
|
||||
min-height: 44px;
|
||||
letter-spacing: 0;
|
||||
font-weight: 700;
|
||||
margin-top: 15px;
|
||||
--el-button-bg-color: var(--el-color-primary);
|
||||
}
|
||||
@@ -241,9 +256,17 @@ const onSubmit = (captchaInfo = '') => {
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
.login-box {
|
||||
width: 340px;
|
||||
width: calc(100vw - 28px);
|
||||
margin-top: 0;
|
||||
margin-bottom: 0;
|
||||
}
|
||||
.form .content {
|
||||
padding: 86px 24px 28px 24px;
|
||||
}
|
||||
}
|
||||
.switch-language {
|
||||
top: 14px;
|
||||
right: 14px;
|
||||
}
|
||||
}
|
||||
.chang-lang :deep(.el-dropdown-menu__item) {
|
||||
@@ -257,15 +280,24 @@ const onSubmit = (captchaInfo = '') => {
|
||||
// 暗黑样式
|
||||
@at-root .dark {
|
||||
.bubble {
|
||||
background: url(/@/assets/bg-dark.jpg) repeat;
|
||||
background:
|
||||
linear-gradient(135deg, rgba(16, 23, 34, 0.92), rgba(24, 33, 49, 0.88)),
|
||||
url(/@/assets/bg-dark.jpg) repeat;
|
||||
background-blend-mode: multiply;
|
||||
}
|
||||
.switch-language {
|
||||
background: rgba(24, 33, 49, 0.76);
|
||||
border-color: rgba(58, 74, 97, 0.85);
|
||||
}
|
||||
.login {
|
||||
.login-box {
|
||||
background: #161b22;
|
||||
background: #182131;
|
||||
border-color: rgba(58, 74, 97, 0.86);
|
||||
}
|
||||
.head {
|
||||
background: linear-gradient(135deg, rgba(91, 134, 240, 0.14), rgba(13, 20, 32, 0.18)), #111c2a;
|
||||
img {
|
||||
filter: brightness(61%);
|
||||
filter: brightness(72%);
|
||||
}
|
||||
}
|
||||
.form {
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
<template>
|
||||
<div class="default-main customer-report">
|
||||
<section class="report-filter">
|
||||
<header>{{ t('user.moneyLog.customerReport.title') }}</header>
|
||||
<div class="filter-content">
|
||||
<div class="default-main admin-report-page customer-report">
|
||||
<section class="admin-report-filter report-filter">
|
||||
<header class="admin-report-heading">{{ t('user.moneyLog.customerReport.title') }}</header>
|
||||
<div class="admin-report-filter-content filter-content">
|
||||
<div class="filter-item">
|
||||
<label>{{ t('user.moneyLog.customerReport.startDate') }}:</label>
|
||||
<el-date-picker v-model="filters.start" type="date" value-format="YYYY-MM-DD" clearable />
|
||||
@@ -17,26 +17,22 @@
|
||||
</div>
|
||||
<div class="filter-item">
|
||||
<label>{{ t('user.moneyLog.customerReport.loseRebate') }}:</label>
|
||||
<el-input
|
||||
v-model="filters.loseRebate"
|
||||
:placeholder="t('user.moneyLog.customerReport.rebatePlaceholder')"
|
||||
clearable
|
||||
/>
|
||||
<el-input v-model="filters.loseRebate" :placeholder="t('user.moneyLog.customerReport.rebatePlaceholder')" clearable />
|
||||
</div>
|
||||
<div class="filter-actions">
|
||||
<div class="admin-report-actions filter-actions">
|
||||
<el-button type="primary" @click="search">{{ t('user.moneyLog.customerReport.search') }}</el-button>
|
||||
<el-button @click="clear">{{ t('user.moneyLog.customerReport.clear') }}</el-button>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<div class="date-summary">
|
||||
<div class="admin-report-summary date-summary">
|
||||
<strong>{{ t('user.moneyLog.customerReport.dateOfData') }}:</strong>
|
||||
{{ dateSummary }}
|
||||
</div>
|
||||
|
||||
<div v-loading="loading" class="report-table-wrap">
|
||||
<table class="report-table" :style="{ minWidth: `${tableMinWidth}px` }">
|
||||
<div v-loading="loading" class="admin-report-table-wrap report-table-wrap">
|
||||
<table class="admin-report-table report-table" :style="{ minWidth: `${tableMinWidth}px` }">
|
||||
<thead>
|
||||
<tr>
|
||||
<th rowspan="2" class="date-column">{{ t('user.moneyLog.customerReport.registerDate') }} ↓</th>
|
||||
@@ -83,7 +79,7 @@
|
||||
</table>
|
||||
</div>
|
||||
|
||||
<div class="table-footer">
|
||||
<div class="admin-report-footer table-footer">
|
||||
<div>{{ t('user.moneyLog.customerReport.totalRecords', { total }) }}</div>
|
||||
<el-pagination
|
||||
v-model:current-page="currentPage"
|
||||
@@ -94,7 +90,7 @@
|
||||
:page-count="lastPage"
|
||||
@current-change="loadReport"
|
||||
/>
|
||||
<div class="page-size">
|
||||
<div class="admin-report-page-size page-size">
|
||||
<span>{{ t('user.moneyLog.customerReport.show') }}</span>
|
||||
<el-select v-model="pageSize" @change="changePageSize">
|
||||
<el-option v-for="size in pageSizes" :key="size" :label="size" :value="size" />
|
||||
@@ -269,48 +265,20 @@ onMounted(loadReport)
|
||||
|
||||
<style scoped lang="scss">
|
||||
.customer-report {
|
||||
--report-dark: #333;
|
||||
--report-border: #d8d8d8;
|
||||
--report-reward: #e5e5e5;
|
||||
--report-surface: var(--el-bg-color);
|
||||
padding: 20px;
|
||||
color: var(--el-text-color-primary);
|
||||
font-size: 14px;
|
||||
}
|
||||
|
||||
.report-filter {
|
||||
margin-bottom: 20px;
|
||||
border: 1px solid var(--report-border);
|
||||
background: var(--report-surface);
|
||||
|
||||
header {
|
||||
min-height: 37px;
|
||||
padding: 9px 8px;
|
||||
background: var(--report-dark);
|
||||
color: #fff;
|
||||
font-weight: 700;
|
||||
}
|
||||
padding: var(--ba-main-space);
|
||||
}
|
||||
|
||||
.filter-content {
|
||||
display: grid;
|
||||
grid-template-columns: 335px 335px;
|
||||
gap: 6px 18px;
|
||||
min-height: 120px;
|
||||
padding: 13px 20px;
|
||||
grid-template-columns: repeat(2, minmax(280px, 350px));
|
||||
gap: 12px 18px;
|
||||
}
|
||||
|
||||
.filter-item {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 8px;
|
||||
|
||||
label {
|
||||
width: 115px;
|
||||
width: 118px;
|
||||
flex-shrink: 0;
|
||||
font-weight: 700;
|
||||
text-align: right;
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
:deep(.el-date-editor),
|
||||
@@ -321,53 +289,11 @@ onMounted(loadReport)
|
||||
|
||||
.filter-actions {
|
||||
grid-column: 2;
|
||||
display: flex;
|
||||
gap: 16px;
|
||||
|
||||
.el-button {
|
||||
width: 160px;
|
||||
margin: 0;
|
||||
}
|
||||
}
|
||||
|
||||
.date-summary {
|
||||
margin-bottom: 8px;
|
||||
}
|
||||
|
||||
.report-table-wrap {
|
||||
overflow-x: auto;
|
||||
justify-content: flex-start;
|
||||
}
|
||||
|
||||
.report-table {
|
||||
width: 100%;
|
||||
min-width: 2500px;
|
||||
border-collapse: collapse;
|
||||
|
||||
th,
|
||||
td {
|
||||
height: 38px;
|
||||
padding: 8px;
|
||||
border: 1px solid var(--report-border);
|
||||
text-align: left;
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
thead th {
|
||||
border-color: #eee;
|
||||
background: var(--report-dark);
|
||||
color: #fff;
|
||||
font-weight: 700;
|
||||
vertical-align: middle;
|
||||
|
||||
small {
|
||||
display: block;
|
||||
font-size: 11px;
|
||||
}
|
||||
}
|
||||
|
||||
tbody td {
|
||||
background: var(--report-surface);
|
||||
}
|
||||
|
||||
.date-column {
|
||||
width: 225px;
|
||||
@@ -381,10 +307,6 @@ onMounted(loadReport)
|
||||
min-width: 250px;
|
||||
}
|
||||
|
||||
.reward-cell {
|
||||
background: var(--report-reward);
|
||||
}
|
||||
|
||||
.username-cell {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
@@ -392,55 +314,19 @@ onMounted(loadReport)
|
||||
}
|
||||
|
||||
.user-icon {
|
||||
color: var(--el-text-color-primary);
|
||||
}
|
||||
|
||||
.deposit-value,
|
||||
.positive-value {
|
||||
color: #35ad78;
|
||||
}
|
||||
|
||||
.withdraw-value,
|
||||
.negative-value {
|
||||
color: #e05a55;
|
||||
}
|
||||
|
||||
.empty-row {
|
||||
height: 150px;
|
||||
color: var(--el-text-color-secondary);
|
||||
text-align: center;
|
||||
}
|
||||
}
|
||||
|
||||
.table-footer {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: flex-start;
|
||||
gap: 8px;
|
||||
margin-top: 18px;
|
||||
}
|
||||
|
||||
.page-size {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 8px;
|
||||
|
||||
.el-select {
|
||||
width: 90px;
|
||||
}
|
||||
}
|
||||
|
||||
@at-root html.dark {
|
||||
.customer-report {
|
||||
--report-dark: #2b2b2b;
|
||||
--report-border: var(--el-border-color);
|
||||
--report-reward: #333;
|
||||
:deep(.el-pagination) {
|
||||
margin-left: auto;
|
||||
}
|
||||
}
|
||||
|
||||
@media (max-width: 768px) {
|
||||
.customer-report {
|
||||
padding: 14px;
|
||||
padding: 12px;
|
||||
}
|
||||
|
||||
.filter-content {
|
||||
@@ -449,8 +335,7 @@ onMounted(loadReport)
|
||||
}
|
||||
|
||||
.filter-item {
|
||||
align-items: flex-start;
|
||||
flex-direction: column;
|
||||
display: flex;
|
||||
|
||||
label {
|
||||
width: auto;
|
||||
@@ -459,6 +344,7 @@ onMounted(loadReport)
|
||||
}
|
||||
|
||||
.filter-actions {
|
||||
grid-column: auto;
|
||||
width: 100%;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,27 +1,15 @@
|
||||
<template>
|
||||
<div class="default-main daily-report">
|
||||
<section class="report-filter">
|
||||
<header>{{ t('user.moneyLog.dailyReport.title') }}</header>
|
||||
<div class="filter-content">
|
||||
<div class="default-main admin-report-page daily-report">
|
||||
<section class="admin-report-filter report-filter">
|
||||
<header class="admin-report-heading">{{ t('user.moneyLog.dailyReport.title') }}</header>
|
||||
<div class="admin-report-filter-content filter-content">
|
||||
<div class="date-fields">
|
||||
<label>{{ t('user.moneyLog.dailyReport.startDate') }}:</label>
|
||||
<el-date-picker
|
||||
v-model="filters.start"
|
||||
type="date"
|
||||
value-format="YYYY-MM-DD"
|
||||
:clearable="false"
|
||||
@change="loadReport"
|
||||
/>
|
||||
<el-date-picker v-model="filters.start" type="date" value-format="YYYY-MM-DD" :clearable="false" @change="loadReport" />
|
||||
<label>{{ t('user.moneyLog.dailyReport.endDate') }}:</label>
|
||||
<el-date-picker
|
||||
v-model="filters.end"
|
||||
type="date"
|
||||
value-format="YYYY-MM-DD"
|
||||
:clearable="false"
|
||||
@change="loadReport"
|
||||
/>
|
||||
<el-date-picker v-model="filters.end" type="date" value-format="YYYY-MM-DD" :clearable="false" @change="loadReport" />
|
||||
</div>
|
||||
<div class="period-tabs">
|
||||
<div class="admin-report-tabs period-tabs">
|
||||
<button
|
||||
v-for="period in periods"
|
||||
:key="period.value"
|
||||
@@ -35,8 +23,8 @@
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<div v-loading="loading" class="report-table-wrap">
|
||||
<table class="report-table" :style="{ minWidth: `${tableMinWidth}px` }">
|
||||
<div v-loading="loading" class="admin-report-table-wrap report-table-wrap">
|
||||
<table class="admin-report-table report-table" :style="{ minWidth: `${tableMinWidth}px` }">
|
||||
<thead>
|
||||
<tr>
|
||||
<th rowspan="2" class="date-column">{{ t('user.moneyLog.dailyReport.date') }}</th>
|
||||
@@ -233,117 +221,33 @@ onMounted(loadReport)
|
||||
|
||||
<style scoped lang="scss">
|
||||
.daily-report {
|
||||
--report-dark: #333;
|
||||
--report-border: #ddd;
|
||||
--report-strong-border: #999;
|
||||
--report-muted: #ddd;
|
||||
--report-surface: var(--el-bg-color);
|
||||
padding: 20px;
|
||||
color: var(--el-text-color-primary);
|
||||
font-size: 14px;
|
||||
}
|
||||
|
||||
.report-filter {
|
||||
margin-bottom: 20px;
|
||||
border: 1px solid var(--report-border);
|
||||
background: var(--report-surface);
|
||||
|
||||
header {
|
||||
min-height: 37px;
|
||||
padding: 9px 8px;
|
||||
background: var(--report-dark);
|
||||
color: #fff;
|
||||
font-weight: 700;
|
||||
}
|
||||
padding: var(--ba-main-space);
|
||||
}
|
||||
|
||||
.filter-content {
|
||||
min-height: 92px;
|
||||
padding: 13px;
|
||||
display: flex;
|
||||
align-items: flex-start;
|
||||
flex-direction: column;
|
||||
gap: 12px;
|
||||
}
|
||||
|
||||
.date-fields {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 8px;
|
||||
margin-bottom: 5px;
|
||||
|
||||
label {
|
||||
font-weight: 700;
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
:deep(.el-date-editor) {
|
||||
width: 200px;
|
||||
margin-right: 0;
|
||||
}
|
||||
}
|
||||
|
||||
.period-tabs {
|
||||
display: flex;
|
||||
width: fit-content;
|
||||
overflow: hidden;
|
||||
border: 1px solid #999;
|
||||
border-radius: 3px;
|
||||
margin-bottom: 0;
|
||||
box-shadow: none;
|
||||
|
||||
button {
|
||||
width: 100px;
|
||||
height: 32px;
|
||||
border: 0;
|
||||
border-right: 1px solid #999;
|
||||
background: var(--el-fill-color-light);
|
||||
color: var(--el-text-color-primary);
|
||||
cursor: pointer;
|
||||
|
||||
&:last-child {
|
||||
border-right: 0;
|
||||
}
|
||||
|
||||
&:hover {
|
||||
background: var(--el-fill-color);
|
||||
}
|
||||
|
||||
&.active {
|
||||
background: #bbb;
|
||||
color: #000;
|
||||
}
|
||||
min-width: 96px;
|
||||
}
|
||||
}
|
||||
|
||||
.report-table-wrap {
|
||||
overflow-x: auto;
|
||||
}
|
||||
|
||||
.report-table {
|
||||
width: 100%;
|
||||
min-width: 2516px;
|
||||
border-collapse: collapse;
|
||||
|
||||
th,
|
||||
td {
|
||||
height: 38px;
|
||||
padding: 8px;
|
||||
border: 1px solid var(--report-border);
|
||||
text-align: left;
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
thead {
|
||||
background: var(--report-dark);
|
||||
color: #fff;
|
||||
|
||||
th {
|
||||
border-color: #eee;
|
||||
background: var(--report-dark);
|
||||
font-weight: 700;
|
||||
vertical-align: middle;
|
||||
}
|
||||
}
|
||||
|
||||
tbody td {
|
||||
background: var(--report-surface);
|
||||
color: var(--el-text-color-primary);
|
||||
}
|
||||
|
||||
.date-column,
|
||||
.date-cell {
|
||||
@@ -352,9 +256,7 @@ onMounted(loadReport)
|
||||
|
||||
.date-cell,
|
||||
.reward-cell {
|
||||
border-color: var(--report-strong-border);
|
||||
background: var(--report-muted);
|
||||
color: #333;
|
||||
font-weight: 600;
|
||||
}
|
||||
|
||||
.single-column {
|
||||
@@ -372,56 +274,15 @@ onMounted(loadReport)
|
||||
.reward-heading {
|
||||
min-width: 230px;
|
||||
}
|
||||
|
||||
.deposit-value,
|
||||
.positive-value {
|
||||
color: #3cb371;
|
||||
}
|
||||
|
||||
.withdraw-value,
|
||||
.negative-value {
|
||||
color: #ff5349;
|
||||
}
|
||||
|
||||
.unclaim-value {
|
||||
color: #9457c5;
|
||||
}
|
||||
|
||||
.empty-row {
|
||||
height: 150px;
|
||||
background: var(--report-surface);
|
||||
color: var(--el-text-color-secondary);
|
||||
text-align: center;
|
||||
}
|
||||
}
|
||||
|
||||
@at-root html.dark {
|
||||
.daily-report {
|
||||
--report-dark: #2b2b2b;
|
||||
--report-border: var(--el-border-color);
|
||||
--report-strong-border: #606266;
|
||||
--report-muted: #333;
|
||||
}
|
||||
|
||||
.period-tabs button.active {
|
||||
background: #555;
|
||||
color: #fff;
|
||||
}
|
||||
|
||||
.report-table .date-cell,
|
||||
.report-table .reward-cell {
|
||||
color: var(--el-text-color-primary);
|
||||
}
|
||||
}
|
||||
|
||||
@media (max-width: 768px) {
|
||||
.daily-report {
|
||||
padding: 14px;
|
||||
padding: 12px;
|
||||
}
|
||||
|
||||
.date-fields {
|
||||
align-items: flex-start;
|
||||
flex-direction: column;
|
||||
width: 100%;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
<template>
|
||||
<div class="default-main submitted-rewards">
|
||||
<nav class="reward-tabs" :aria-label="t('user.submittedReward.Promotion type')">
|
||||
<div class="default-main admin-report-page submitted-rewards">
|
||||
<nav class="admin-report-tabs reward-tabs" :aria-label="t('user.submittedReward.Promotion type')">
|
||||
<button
|
||||
v-for="tab in promotionTabs"
|
||||
:key="tab.value"
|
||||
@@ -12,13 +12,13 @@
|
||||
</button>
|
||||
</nav>
|
||||
|
||||
<section class="reward-panel">
|
||||
<header class="panel-heading">
|
||||
<section class="admin-report-filter reward-panel">
|
||||
<header class="admin-report-heading panel-heading">
|
||||
<span>{{ t('user.submittedReward.Submitted Rewards') }} ({{ activePromotionLabel }})</span>
|
||||
<strong>{{ t('user.submittedReward.Running') }}</strong>
|
||||
</header>
|
||||
|
||||
<div class="filter-panel">
|
||||
<div class="admin-report-filter-content filter-panel">
|
||||
<div class="filter-item">
|
||||
<label>{{ t('user.submittedReward.Start Date') }}:</label>
|
||||
<el-date-picker v-model="filters.start" type="date" value-format="YYYY-MM-DD" :clearable="false" />
|
||||
@@ -45,20 +45,20 @@
|
||||
@keyup.enter="search"
|
||||
/>
|
||||
</div>
|
||||
<div class="filter-actions">
|
||||
<el-button @click="search">{{ t('Search') }}</el-button>
|
||||
<div class="admin-report-actions filter-actions">
|
||||
<el-button type="primary" @click="search">{{ t('Search') }}</el-button>
|
||||
<el-button @click="clearFilters">{{ t('user.submittedReward.Clear') }}</el-button>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<div class="date-summary">
|
||||
<div class="admin-report-summary date-summary">
|
||||
<strong>{{ t('user.submittedReward.Date of data') }}:</strong>
|
||||
{{ dateRangeText }}
|
||||
</div>
|
||||
|
||||
<div v-loading="loading" class="reward-table-wrap">
|
||||
<table class="reward-table">
|
||||
<div v-loading="loading" class="admin-report-table-wrap reward-table-wrap">
|
||||
<table class="admin-report-table reward-table">
|
||||
<thead>
|
||||
<tr>
|
||||
<th class="submitted-time">{{ t('user.submittedReward.Submitted Time') }}</th>
|
||||
@@ -76,20 +76,10 @@
|
||||
<td>{{ row.status }}</td>
|
||||
<td>
|
||||
<div v-if="row.statusCode === 0" class="action-buttons">
|
||||
<el-button
|
||||
type="success"
|
||||
size="small"
|
||||
:loading="actionLoadingId === row.id"
|
||||
@click="confirmReward(row, 1)"
|
||||
>
|
||||
<el-button type="success" size="small" :loading="actionLoadingId === row.id" @click="confirmReward(row, 1)">
|
||||
{{ t('user.submittedReward.Agree') }}
|
||||
</el-button>
|
||||
<el-button
|
||||
type="danger"
|
||||
size="small"
|
||||
:loading="actionLoadingId === row.id"
|
||||
@click="confirmReward(row, 2)"
|
||||
>
|
||||
<el-button type="danger" size="small" :loading="actionLoadingId === row.id" @click="confirmReward(row, 2)">
|
||||
{{ t('user.submittedReward.Reject') }}
|
||||
</el-button>
|
||||
</div>
|
||||
@@ -102,7 +92,7 @@
|
||||
</table>
|
||||
</div>
|
||||
|
||||
<div class="table-footer">
|
||||
<div class="admin-report-footer table-footer">
|
||||
<span>{{ t('user.submittedReward.Total records', { total: pagination.total }) }}</span>
|
||||
<el-pagination
|
||||
v-if="pagination.total > 0"
|
||||
@@ -295,87 +285,38 @@ onMounted(() => {
|
||||
|
||||
<style scoped lang="scss">
|
||||
.submitted-rewards {
|
||||
--reward-dark: #333;
|
||||
--reward-border: #ddd;
|
||||
--reward-approved: #dcfbc9;
|
||||
padding: 20px;
|
||||
color: var(--el-text-color-primary);
|
||||
font-size: 14px;
|
||||
padding: var(--ba-main-space);
|
||||
}
|
||||
|
||||
.reward-tabs {
|
||||
display: flex;
|
||||
width: fit-content;
|
||||
margin-bottom: 20px;
|
||||
overflow: hidden;
|
||||
border: 1px solid #999;
|
||||
border-radius: 4px;
|
||||
|
||||
button {
|
||||
min-width: 136px;
|
||||
height: 31px;
|
||||
padding: 5px 30px;
|
||||
border: 0;
|
||||
border-right: 1px solid #999;
|
||||
background: var(--el-fill-color-light);
|
||||
color: var(--el-text-color-primary);
|
||||
cursor: pointer;
|
||||
|
||||
&:last-child {
|
||||
min-width: 99px;
|
||||
border-right: 0;
|
||||
}
|
||||
|
||||
&:hover {
|
||||
background: var(--el-fill-color);
|
||||
}
|
||||
|
||||
&.active {
|
||||
background: #bbb;
|
||||
color: #000;
|
||||
min-width: 112px;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.reward-panel {
|
||||
border: 1px solid var(--reward-border);
|
||||
}
|
||||
|
||||
.panel-heading {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 12px;
|
||||
min-height: 40px;
|
||||
padding: 10px;
|
||||
background: var(--reward-dark);
|
||||
color: #fff;
|
||||
font-weight: 700;
|
||||
justify-content: flex-start;
|
||||
|
||||
strong {
|
||||
color: #57e31a;
|
||||
margin-left: 4px;
|
||||
}
|
||||
}
|
||||
|
||||
.filter-panel {
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
align-items: center;
|
||||
gap: 8px 28px;
|
||||
min-height: 88px;
|
||||
padding: 14px 40px;
|
||||
background: var(--el-bg-color);
|
||||
flex-wrap: wrap;
|
||||
gap: 12px 24px;
|
||||
}
|
||||
|
||||
.filter-item {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 12px;
|
||||
|
||||
label {
|
||||
min-width: 76px;
|
||||
text-align: right;
|
||||
font-weight: 700;
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
:deep(.el-date-editor),
|
||||
@@ -386,48 +327,13 @@ onMounted(() => {
|
||||
}
|
||||
|
||||
.filter-actions {
|
||||
display: flex;
|
||||
gap: 8px;
|
||||
|
||||
.el-button {
|
||||
width: 100px;
|
||||
margin: 0;
|
||||
min-width: 92px;
|
||||
}
|
||||
}
|
||||
|
||||
.date-summary {
|
||||
margin: 20px 0 8px;
|
||||
}
|
||||
|
||||
.reward-table-wrap {
|
||||
min-height: 120px;
|
||||
overflow-x: auto;
|
||||
}
|
||||
|
||||
.reward-table {
|
||||
width: 100%;
|
||||
min-width: 850px;
|
||||
border-collapse: collapse;
|
||||
|
||||
th,
|
||||
td {
|
||||
height: 37px;
|
||||
padding: 8px;
|
||||
border: 1px solid var(--reward-border);
|
||||
text-align: left;
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
th {
|
||||
background: var(--reward-dark);
|
||||
color: #fff;
|
||||
font-weight: 700;
|
||||
}
|
||||
|
||||
tbody tr {
|
||||
background: var(--reward-approved);
|
||||
color: #333;
|
||||
}
|
||||
|
||||
.submitted-time {
|
||||
width: 150px;
|
||||
@@ -444,13 +350,6 @@ onMounted(() => {
|
||||
.action {
|
||||
width: 180px;
|
||||
}
|
||||
|
||||
.empty-row {
|
||||
height: 90px;
|
||||
background: var(--el-bg-color);
|
||||
color: var(--el-text-color-secondary);
|
||||
text-align: center;
|
||||
}
|
||||
}
|
||||
|
||||
.action-buttons {
|
||||
@@ -462,34 +361,9 @@ onMounted(() => {
|
||||
}
|
||||
}
|
||||
|
||||
.table-footer {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: flex-start;
|
||||
gap: 8px;
|
||||
margin-top: 18px;
|
||||
}
|
||||
|
||||
@at-root html.dark {
|
||||
.submitted-rewards {
|
||||
--reward-dark: #2b2b2b;
|
||||
--reward-border: var(--el-border-color);
|
||||
--reward-approved: #29482b;
|
||||
}
|
||||
|
||||
.reward-tabs button.active {
|
||||
background: #555;
|
||||
color: #fff;
|
||||
}
|
||||
|
||||
.reward-table tbody tr {
|
||||
color: var(--el-text-color-primary);
|
||||
}
|
||||
}
|
||||
|
||||
@media (max-width: 900px) {
|
||||
.submitted-rewards {
|
||||
padding: 14px;
|
||||
padding: 12px;
|
||||
}
|
||||
|
||||
.reward-tabs {
|
||||
@@ -502,7 +376,8 @@ onMounted(() => {
|
||||
}
|
||||
|
||||
.filter-panel {
|
||||
padding: 14px;
|
||||
align-items: flex-start;
|
||||
flex-direction: column;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
||||
Reference in New Issue
Block a user