feat 财务中心
This commit is contained in:
@@ -284,3 +284,5 @@
|
|||||||
@finance-entry-export-bg: #e6f6ec;
|
@finance-entry-export-bg: #e6f6ec;
|
||||||
@finance-entry-badge-bg: #f53f3f;
|
@finance-entry-badge-bg: #f53f3f;
|
||||||
@finance-chart-switch-active: #024fff;
|
@finance-chart-switch-active: #024fff;
|
||||||
|
@finance-switch-active-bg: #e8f0ff;
|
||||||
|
@finance-switch-idle-bg: #f2f4f7;
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import { computed, ref } from 'vue'
|
import { computed, ref } from 'vue'
|
||||||
import { ElRadioGroup, ElRadioButton } from 'element-plus'
|
import { ElButton } from 'element-plus'
|
||||||
|
|
||||||
interface DistributionItem {
|
interface DistributionItem {
|
||||||
name: string
|
name: string
|
||||||
@@ -31,9 +31,23 @@ const AXIS = [250, 200, 150, 100, 50]
|
|||||||
const AXIS_MAX = AXIS[0]
|
const AXIS_MAX = AXIS[0]
|
||||||
const MONTHS = ['1月', '2月', '3月', '4月', '5月']
|
const MONTHS = ['1月', '2月', '3月', '4月', '5月']
|
||||||
|
|
||||||
|
interface PeriodOption {
|
||||||
|
label: string
|
||||||
|
value: 'month' | 'half'
|
||||||
|
}
|
||||||
|
|
||||||
// 设计稿 #20 右上角切换:月度账单(激活)/ 上半
|
// 设计稿 #20 右上角切换:月度账单(激活)/ 上半
|
||||||
|
const PERIODS: PeriodOption[] = [
|
||||||
|
{ label: '月度账单', value: 'month' },
|
||||||
|
{ label: '上半', value: 'half' },
|
||||||
|
]
|
||||||
|
|
||||||
const period = ref<'month' | 'half'>('month')
|
const period = ref<'month' | 'half'>('month')
|
||||||
|
|
||||||
|
function onPeriodChange(value: 'month' | 'half'): void {
|
||||||
|
period.value = value
|
||||||
|
}
|
||||||
|
|
||||||
// 柱高按 Y 轴量程绝对值换算(设计稿 #20:Y 轴 250 为满量程),非占比
|
// 柱高按 Y 轴量程绝对值换算(设计稿 #20:Y 轴 250 为满量程),非占比
|
||||||
function heightPercentOf(value: number): number {
|
function heightPercentOf(value: number): number {
|
||||||
if (value <= 0) return 0
|
if (value <= 0) return 0
|
||||||
@@ -47,14 +61,17 @@ function heightPercentOf(value: number): number {
|
|||||||
业务类型分布
|
业务类型分布
|
||||||
</h3>
|
</h3>
|
||||||
|
|
||||||
<el-radio-group v-model="period" class="finance-chart__switch">
|
<div class="finance-chart__switch">
|
||||||
<el-radio-button value="month">
|
<el-button
|
||||||
月度账单
|
v-for="item in PERIODS"
|
||||||
</el-radio-button>
|
:key="item.value"
|
||||||
<el-radio-button value="half">
|
class="finance-chart__switch-btn"
|
||||||
上半
|
:class="{ 'is-active': period === item.value }"
|
||||||
</el-radio-button>
|
@click="onPeriodChange(item.value)"
|
||||||
</el-radio-group>
|
>
|
||||||
|
{{ item.label }}
|
||||||
|
</el-button>
|
||||||
|
</div>
|
||||||
|
|
||||||
<div class="finance-chart__body">
|
<div class="finance-chart__body">
|
||||||
<ul class="finance-chart__axis" aria-hidden="true">
|
<ul class="finance-chart__axis" aria-hidden="true">
|
||||||
@@ -136,30 +153,38 @@ function heightPercentOf(value: number): number {
|
|||||||
}
|
}
|
||||||
|
|
||||||
&__switch {
|
&__switch {
|
||||||
|
.flex(row, flex-end, center);
|
||||||
|
gap: 8px;
|
||||||
position: absolute;
|
position: absolute;
|
||||||
top: 25px;
|
top: 25px;
|
||||||
right: 23px;
|
right: 23px;
|
||||||
|
|
||||||
:deep(.el-radio-button__inner) {
|
:deep(.el-button + .el-button) {
|
||||||
border: none;
|
margin-left: 0;
|
||||||
border-radius: 0;
|
}
|
||||||
padding: 0;
|
|
||||||
background: transparent;
|
|
||||||
box-shadow: none;
|
|
||||||
font-size: 11px;
|
|
||||||
font-weight: 500;
|
|
||||||
line-height: 15px;
|
|
||||||
color: @finance-muted-text;
|
|
||||||
transition: color 0.2s;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
:deep(.el-radio-button.is-active .el-radio-button__inner) {
|
&__switch-btn {
|
||||||
background: transparent;
|
height: 24px;
|
||||||
|
margin-left: 0;
|
||||||
|
padding: 0 12px;
|
||||||
|
border: none;
|
||||||
|
border-radius: @radius-round;
|
||||||
|
background: @finance-switch-idle-bg;
|
||||||
|
font-size: 11px;
|
||||||
|
font-weight: 500;
|
||||||
|
line-height: 24px;
|
||||||
|
color: @finance-muted-text;
|
||||||
|
transition: color 0.2s, background 0.2s;
|
||||||
|
|
||||||
|
&:hover {
|
||||||
|
background: @finance-switch-idle-bg;
|
||||||
color: @finance-chart-switch-active;
|
color: @finance-chart-switch-active;
|
||||||
}
|
}
|
||||||
|
|
||||||
:deep(.el-radio-button + .el-radio-button) {
|
&.is-active {
|
||||||
margin-left: 14px;
|
background: @finance-switch-active-bg;
|
||||||
|
color: @finance-chart-switch-active;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -2,7 +2,7 @@
|
|||||||
import { computed, onMounted, ref } from 'vue'
|
import { computed, onMounted, ref } from 'vue'
|
||||||
import { storeToRefs } from 'pinia'
|
import { storeToRefs } from 'pinia'
|
||||||
import { RouterLink } from 'vue-router'
|
import { RouterLink } from 'vue-router'
|
||||||
import { ElMessage, ElButton, ElRadioGroup, ElRadioButton, ElTable, ElTableColumn } from 'element-plus'
|
import { ElMessage, ElButton, ElTable, ElTableColumn } from 'element-plus'
|
||||||
import { FilterPanel, PaginationBar, StatusTag } from '@/components'
|
import { FilterPanel, PaginationBar, StatusTag } from '@/components'
|
||||||
import { useFinanceStore } from '@/stores/modules/finance'
|
import { useFinanceStore } from '@/stores/modules/finance'
|
||||||
import type { Invoice, InvoiceStatus } from '@/types/business/finance'
|
import type { Invoice, InvoiceStatus } from '@/types/business/finance'
|
||||||
@@ -36,10 +36,6 @@ function onTab(value: InvoiceStatus | 'all'): void {
|
|||||||
void financeStore.searchInvoices()
|
void financeStore.searchInvoices()
|
||||||
}
|
}
|
||||||
|
|
||||||
function onTabChange(val: string | number | boolean | undefined): void {
|
|
||||||
onTab(val as InvoiceStatus | 'all')
|
|
||||||
}
|
|
||||||
|
|
||||||
function onSearch(): void {
|
function onSearch(): void {
|
||||||
financeStore.setInvoiceQuery({ ...invoiceQuery.value, keyword: keyword.value })
|
financeStore.setInvoiceQuery({ ...invoiceQuery.value, keyword: keyword.value })
|
||||||
void financeStore.searchInvoices()
|
void financeStore.searchInvoices()
|
||||||
@@ -112,19 +108,17 @@ onMounted(() => {
|
|||||||
</RouterLink>
|
</RouterLink>
|
||||||
</section>
|
</section>
|
||||||
|
|
||||||
<el-radio-group
|
<div class="invoices__tabs">
|
||||||
class="invoices__tabs"
|
<el-button
|
||||||
:model-value="invoiceQuery.status"
|
|
||||||
@change="onTabChange"
|
|
||||||
>
|
|
||||||
<el-radio-button
|
|
||||||
v-for="tab in STATUS_TABS"
|
v-for="tab in STATUS_TABS"
|
||||||
:key="tab.value"
|
:key="tab.value"
|
||||||
:value="tab.value"
|
class="invoices__tab"
|
||||||
|
:class="{ 'is-active': invoiceQuery.status === tab.value }"
|
||||||
|
@click="onTab(tab.value)"
|
||||||
>
|
>
|
||||||
{{ tab.label }}
|
{{ tab.label }}
|
||||||
</el-radio-button>
|
</el-button>
|
||||||
</el-radio-group>
|
</div>
|
||||||
|
|
||||||
<FilterPanel
|
<FilterPanel
|
||||||
v-model:keyword="keyword"
|
v-model:keyword="keyword"
|
||||||
@@ -326,26 +320,40 @@ onMounted(() => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
&__tabs {
|
&__tabs {
|
||||||
:deep(.el-radio-button__inner) {
|
display: flex;
|
||||||
|
flex-direction: row;
|
||||||
|
align-items: flex-start;
|
||||||
|
gap: @spacing-sm;
|
||||||
|
}
|
||||||
|
|
||||||
|
&__tab {
|
||||||
height: 34px;
|
height: 34px;
|
||||||
|
margin: 0;
|
||||||
padding: 0 @spacing-base;
|
padding: 0 @spacing-base;
|
||||||
border: 1px solid @border-color;
|
border: 1px solid @border-color;
|
||||||
border-radius: @radius-base;
|
border-radius: @radius-base;
|
||||||
background: @white;
|
background: @white;
|
||||||
color: @text-color;
|
color: @text-color;
|
||||||
font-size: @font-size-base;
|
font-size: @font-size-base;
|
||||||
box-shadow: none;
|
font-weight: 400;
|
||||||
|
transition: all 0.2s;
|
||||||
|
|
||||||
|
&:hover {
|
||||||
|
border-color: @primary-color;
|
||||||
|
background: @white;
|
||||||
|
color: @primary-color;
|
||||||
}
|
}
|
||||||
|
|
||||||
:deep(.el-radio-button + .el-radio-button) {
|
&.is-active {
|
||||||
margin-left: @spacing-sm;
|
|
||||||
}
|
|
||||||
|
|
||||||
:deep(.el-radio-button.is-active .el-radio-button__inner) {
|
|
||||||
border-color: @primary-color;
|
border-color: @primary-color;
|
||||||
background: @primary-color;
|
background: @primary-color;
|
||||||
color: @white;
|
color: @white;
|
||||||
box-shadow: -1px 0 0 0 @primary-color;
|
|
||||||
|
&:hover {
|
||||||
|
border-color: @primary-color;
|
||||||
|
background: @primary-color;
|
||||||
|
color: @white;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user