feat(web): 更新侧边栏组件和个人工作台组件,增强导航和业务展示功能
This commit is contained in:
@@ -59,11 +59,11 @@
|
|||||||
</div>
|
</div>
|
||||||
</article>
|
</article>
|
||||||
|
|
||||||
<div class="workbench-grid">
|
<div class="workbench-grid" :class="{ 'finance-grid': isFinanceUser }">
|
||||||
<article class="panel list-panel">
|
<article class="panel list-panel">
|
||||||
<div class="section-head">
|
<div class="section-head">
|
||||||
<div class="title-with-badge">
|
<div class="title-with-badge">
|
||||||
<h3>今日待办</h3>
|
<h3>报销待办</h3>
|
||||||
<span class="alert-badge">{{ todoAlertCount }}</span>
|
<span class="alert-badge">{{ todoAlertCount }}</span>
|
||||||
</div>
|
</div>
|
||||||
<button type="button" class="link-action">查看全部 <i class="mdi mdi-chevron-right"></i></button>
|
<button type="button" class="link-action">查看全部 <i class="mdi mdi-chevron-right"></i></button>
|
||||||
@@ -113,6 +113,58 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</article>
|
</article>
|
||||||
|
|
||||||
|
<article v-if="isFinanceUser" class="panel list-panel">
|
||||||
|
<div class="section-head">
|
||||||
|
<div class="title-with-badge">
|
||||||
|
<h3>应收管理</h3>
|
||||||
|
<span class="alert-badge">{{ receivableAlertCount }}</span>
|
||||||
|
</div>
|
||||||
|
<button type="button" class="link-action">查看全部 <i class="mdi mdi-chevron-right"></i></button>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="list-body">
|
||||||
|
<div v-for="item in receivableItems" :key="item.id" class="progress-row">
|
||||||
|
<div class="todo-icon" :style="{ '--icon-color': item.color }">
|
||||||
|
<i :class="item.icon"></i>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="todo-copy progress-copy">
|
||||||
|
<strong>{{ item.title }}</strong>
|
||||||
|
<p>{{ item.date }}</p>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<strong class="progress-amount">{{ item.amount }}</strong>
|
||||||
|
<span class="progress-status" :class="item.tone">{{ item.status }}</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</article>
|
||||||
|
|
||||||
|
<article v-if="isFinanceUser" class="panel list-panel">
|
||||||
|
<div class="section-head">
|
||||||
|
<div class="title-with-badge">
|
||||||
|
<h3>应付管理</h3>
|
||||||
|
<span class="alert-badge">{{ payableAlertCount }}</span>
|
||||||
|
</div>
|
||||||
|
<button type="button" class="link-action">查看全部 <i class="mdi mdi-chevron-right"></i></button>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="list-body">
|
||||||
|
<div v-for="item in payableItems" :key="item.id" class="progress-row">
|
||||||
|
<div class="todo-icon" :style="{ '--icon-color': item.color }">
|
||||||
|
<i :class="item.icon"></i>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="todo-copy progress-copy">
|
||||||
|
<strong>{{ item.title }}</strong>
|
||||||
|
<p>{{ item.date }}</p>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<strong class="progress-amount">{{ item.amount }}</strong>
|
||||||
|
<span class="progress-status" :class="item.tone">{{ item.status }}</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</article>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<article class="panel policy-panel">
|
<article class="panel policy-panel">
|
||||||
@@ -154,6 +206,13 @@ const props = defineProps({
|
|||||||
|
|
||||||
const emit = defineEmits(['openAssistant'])
|
const emit = defineEmits(['openAssistant'])
|
||||||
const { currentUser } = useSystemState()
|
const { currentUser } = useSystemState()
|
||||||
|
|
||||||
|
// 判断是否为财务人员
|
||||||
|
const isFinanceUser = computed(() => {
|
||||||
|
const user = currentUser.value || {}
|
||||||
|
const roleCodes = Array.isArray(user.roleCodes) ? user.roleCodes : []
|
||||||
|
return roleCodes.includes('finance') || roleCodes.includes('accountant') || user.isAdmin
|
||||||
|
})
|
||||||
const { toast } = useToast()
|
const { toast } = useToast()
|
||||||
const assistantDraft = ref('')
|
const assistantDraft = ref('')
|
||||||
const fileInputRef = ref(null)
|
const fileInputRef = ref(null)
|
||||||
@@ -233,7 +292,9 @@ function emitAssistant(payload) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
async function loadLatestConversation() {
|
async function loadLatestConversation() {
|
||||||
const payload = await fetchLatestConversation(resolveCurrentUserId(), SESSION_TYPE_EXPENSE)
|
const payload = await fetchLatestConversation(resolveCurrentUserId(), SESSION_TYPE_EXPENSE, {
|
||||||
|
preferRecoverable: true
|
||||||
|
})
|
||||||
return payload?.found ? payload.conversation || null : null
|
return payload?.found ? payload.conversation || null : null
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -361,6 +422,76 @@ const progressItems = [
|
|||||||
|
|
||||||
const progressAlertCount = progressItems.filter((item) => item.status !== '已到账').length
|
const progressAlertCount = progressItems.filter((item) => item.status !== '已到账').length
|
||||||
|
|
||||||
|
const receivableItems = [
|
||||||
|
{
|
||||||
|
id: 'receivable-1',
|
||||||
|
title: '客户服务费收入',
|
||||||
|
amount: '¥15,800',
|
||||||
|
date: '2026-05-10',
|
||||||
|
status: '待收款',
|
||||||
|
tone: 'info',
|
||||||
|
icon: 'mdi mdi-account-cash-outline',
|
||||||
|
color: '#f59e0b'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: 'receivable-2',
|
||||||
|
title: '项目进度款',
|
||||||
|
amount: '¥42,600',
|
||||||
|
date: '2026-05-08',
|
||||||
|
status: '部分收款',
|
||||||
|
tone: 'success',
|
||||||
|
icon: 'mdi mdi-cash-multiple',
|
||||||
|
color: '#10b981'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: 'receivable-3',
|
||||||
|
title: '咨询服务费',
|
||||||
|
amount: '¥8,900',
|
||||||
|
date: '2026-05-05',
|
||||||
|
status: '逾期提醒',
|
||||||
|
tone: 'info',
|
||||||
|
icon: 'mdi mdi-bell-alert',
|
||||||
|
color: '#ef4444'
|
||||||
|
}
|
||||||
|
]
|
||||||
|
|
||||||
|
const receivableAlertCount = receivableItems.filter((item) => item.status === '逾期提醒' || item.status === '待收款').length
|
||||||
|
|
||||||
|
const payableItems = [
|
||||||
|
{
|
||||||
|
id: 'payable-1',
|
||||||
|
title: '供应商采购款',
|
||||||
|
amount: '¥28,500',
|
||||||
|
date: '2026-05-12',
|
||||||
|
status: '待付款',
|
||||||
|
tone: 'info',
|
||||||
|
icon: 'mdi mdi-truck-outline',
|
||||||
|
color: '#3b82f6'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: 'payable-2',
|
||||||
|
title: '房租物业费',
|
||||||
|
amount: '¥12,800',
|
||||||
|
date: '2026-05-15',
|
||||||
|
status: '待审批',
|
||||||
|
tone: 'success',
|
||||||
|
icon: 'mdi mdi-office-building',
|
||||||
|
color: '#6366f1'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: 'payable-3',
|
||||||
|
title: '软件服务费',
|
||||||
|
amount: '¥3,600',
|
||||||
|
date: '2026-05-01',
|
||||||
|
status: '已付款',
|
||||||
|
tone: 'mint',
|
||||||
|
icon: 'mdi mdi-server',
|
||||||
|
color: '#10b981'
|
||||||
|
}
|
||||||
|
]
|
||||||
|
|
||||||
|
const payableAlertCount = payableItems.filter((item) => item.status === '待付款' || item.status === '待审批').length
|
||||||
|
|
||||||
const policyItems = [
|
const policyItems = [
|
||||||
{
|
{
|
||||||
name: '差旅报销管理办法(2026版)',
|
name: '差旅报销管理办法(2026版)',
|
||||||
@@ -725,6 +856,11 @@ watch(
|
|||||||
gap: 20px;
|
gap: 20px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.workbench-grid.finance-grid {
|
||||||
|
grid-template-columns: repeat(4, 1fr);
|
||||||
|
gap: 16px;
|
||||||
|
}
|
||||||
|
|
||||||
.list-panel,
|
.list-panel,
|
||||||
.policy-panel {
|
.policy-panel {
|
||||||
padding: 20px 22px;
|
padding: 20px 22px;
|
||||||
@@ -974,6 +1110,11 @@ watch(
|
|||||||
.policy-row {
|
.policy-row {
|
||||||
grid-template-columns: 1.8fr 1.8fr 1fr;
|
grid-template-columns: 1.8fr 1.8fr 1fr;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.workbench-grid.finance-grid {
|
||||||
|
grid-template-columns: repeat(2, 1fr);
|
||||||
|
gap: 16px;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@media (max-width: 1440px) {
|
@media (max-width: 1440px) {
|
||||||
@@ -1040,7 +1181,8 @@ watch(
|
|||||||
width: 176px;
|
width: 176px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.workbench-grid {
|
.workbench-grid,
|
||||||
|
.workbench-grid.finance-grid {
|
||||||
grid-template-columns: 1fr;
|
grid-template-columns: 1fr;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1107,6 +1249,14 @@ watch(
|
|||||||
justify-self: start;
|
justify-self: start;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.workbench-grid.finance-grid {
|
||||||
|
gap: 16px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.workbench-grid.finance-grid .list-panel {
|
||||||
|
padding: 16px 18px;
|
||||||
|
}
|
||||||
|
|
||||||
.policy-table {
|
.policy-table {
|
||||||
border: 0;
|
border: 0;
|
||||||
border-radius: 0;
|
border-radius: 0;
|
||||||
@@ -1129,5 +1279,4 @@ watch(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -8,9 +8,6 @@
|
|||||||
</svg>
|
</svg>
|
||||||
</div>
|
</div>
|
||||||
<strong class="brand-name">{{ displayCompanyName }}</strong>
|
<strong class="brand-name">{{ displayCompanyName }}</strong>
|
||||||
<button class="brand-toggle" type="button" aria-label="打开 AI 助手" @click="emit('openChat')">
|
|
||||||
<i class="mdi mdi-chevron-double-left"></i>
|
|
||||||
</button>
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<nav class="rail-nav" aria-label="功能导航">
|
<nav class="rail-nav" aria-label="功能导航">
|
||||||
@@ -115,10 +112,10 @@ const displayCompanyName = computed(() => props.companyName || 'X-Financial')
|
|||||||
|
|
||||||
.rail-brand {
|
.rail-brand {
|
||||||
min-height: 86px;
|
min-height: 86px;
|
||||||
display: grid;
|
display: flex;
|
||||||
grid-template-columns: 32px minmax(0, 1fr) 28px;
|
|
||||||
align-items: center;
|
align-items: center;
|
||||||
gap: 10px;
|
justify-content: center;
|
||||||
|
gap: 12px;
|
||||||
padding: 22px 20px 18px;
|
padding: 22px 20px 18px;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -137,31 +134,11 @@ const displayCompanyName = computed(() => props.companyName || 'X-Financial')
|
|||||||
}
|
}
|
||||||
|
|
||||||
.brand-name {
|
.brand-name {
|
||||||
min-width: 0;
|
|
||||||
color: #0f172a;
|
color: #0f172a;
|
||||||
font-size: 16px;
|
font-size: 16px;
|
||||||
font-weight: 800;
|
font-weight: 800;
|
||||||
letter-spacing: 0;
|
letter-spacing: 0;
|
||||||
white-space: nowrap;
|
white-space: nowrap;
|
||||||
overflow: hidden;
|
|
||||||
text-overflow: ellipsis;
|
|
||||||
}
|
|
||||||
|
|
||||||
.brand-toggle {
|
|
||||||
width: 28px;
|
|
||||||
height: 28px;
|
|
||||||
display: grid;
|
|
||||||
place-items: center;
|
|
||||||
border: 0;
|
|
||||||
border-radius: 7px;
|
|
||||||
background: transparent;
|
|
||||||
color: #718096;
|
|
||||||
transition: background 180ms var(--ease), color 180ms var(--ease);
|
|
||||||
}
|
|
||||||
|
|
||||||
.brand-toggle:hover {
|
|
||||||
background: #eef7f4;
|
|
||||||
color: #07936f;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.rail-nav {
|
.rail-nav {
|
||||||
|
|||||||
Reference in New Issue
Block a user