style: 全局 UI 主题皮肤重构与样式模块化

引入 Element Plus 主题定制和主题皮肤 composable,将全局
样式拆分为组件级独立 CSS 文件(侧边栏、顶栏、工作台等),
统一色彩变量和间距规范,重构所有视图和组件样式以适配新
主题系统,优化图表和知识图谱组件视觉表现,提取审计和差
旅报销相关子组件。
This commit is contained in:
caoxiaozhu
2026-05-27 09:17:57 +08:00
parent df49103f23
commit 2dcc72102d
112 changed files with 10983 additions and 8996 deletions

View File

@@ -1,4 +1,4 @@
import { computed, onBeforeUnmount, onMounted, ref } from 'vue'
import { computed, ref } from 'vue'
import TableLoadingState from '../../components/shared/TableLoadingState.vue'
import TableEmptyState from '../../components/shared/TableEmptyState.vue'
@@ -102,7 +102,6 @@ export default {
const activeTypeFilter = ref(ARCHIVE_FILTER_ALL)
const activeDepartmentFilter = ref(ARCHIVE_FILTER_ALL)
const activeArchiveMonthFilter = ref(ARCHIVE_FILTER_ALL)
const openFilterKey = ref('')
const selectedClaimId = ref('')
const listKeyword = ref('')
const rows = ref([])
@@ -118,7 +117,7 @@ export default {
const departmentFilterLabel = computed(() => resolveFilterLabel(departmentFilterOptions.value, activeDepartmentFilter.value, '所属部门'))
const archiveMonthFilterLabel = computed(() => resolveFilterLabel(archiveMonthFilterOptions.value, activeArchiveMonthFilter.value, '归档月份'))
const filterDropdowns = computed(() => [
const filterMenus = computed(() => [
{
key: 'risk',
label: riskFilterLabel.value,
@@ -210,7 +209,6 @@ export default {
activeDepartmentFilter.value = ARCHIVE_FILTER_ALL
activeArchiveMonthFilter.value = ARCHIVE_FILTER_ALL
listKeyword.value = ''
openFilterKey.value = ''
}
function handleEmptyAction() {
@@ -222,10 +220,6 @@ export default {
resetListFilters()
}
function toggleFilterDropdown(key) {
openFilterKey.value = openFilterKey.value === key ? '' : key
}
function selectFilterValue(key, value) {
if (key === 'risk') {
activeRiskFilter.value = value
@@ -237,18 +231,6 @@ export default {
activeArchiveMonthFilter.value = value
}
openFilterKey.value = ''
}
function handleDocumentClick(event) {
const target = event.target
if (!(target instanceof Element)) {
return
}
if (!target.closest('.archive-dropdown-filter')) {
openFilterKey.value = ''
}
}
function closeSelectedDetail() {
@@ -278,14 +260,6 @@ export default {
}
}
onMounted(() => {
document.addEventListener('click', handleDocumentClick)
})
onBeforeUnmount(() => {
document.removeEventListener('click', handleDocumentClick)
})
void reload()
return {
@@ -293,11 +267,10 @@ export default {
archiveEmptyState,
closeSelectedDetail,
error,
filterDropdowns,
filterMenus,
handleEmptyAction,
listKeyword,
loading,
openFilterKey,
reload,
resetListFilters,
rows,
@@ -305,7 +278,6 @@ export default {
selectedRow,
showEmpty,
tabs,
toggleFilterDropdown,
visibleRows
}
}

View File

@@ -1,11 +1,13 @@
import { computed, nextTick, onBeforeUnmount, onMounted, ref, watch } from 'vue'
import ConfirmDialog from '../../components/shared/ConfirmDialog.vue'
import AuditAssetList from '../../components/audit/AuditAssetList.vue'
import AuditJsonRiskRuleDetail from '../../components/audit/AuditJsonRiskRuleDetail.vue'
import AuditRuleDialogs from '../../components/audit/AuditRuleDialogs.vue'
import AuditSpreadsheetChangeDrawer from '../../components/audit/AuditSpreadsheetChangeDrawer.vue'
import AuditSpreadsheetRuleDetail from '../../components/audit/AuditSpreadsheetRuleDetail.vue'
import AuditVersionTimelineDrawer from '../../components/audit/AuditVersionTimelineDrawer.vue'
import { fetchEmployees } from '../../services/employees.js'
import RiskRuleFlowDiagram from '../../components/shared/RiskRuleFlowDiagram.vue'
import RiskRuleTestDialog from '../../components/shared/RiskRuleTestDialog.vue'
import TableLoadingState from '../../components/shared/TableLoadingState.vue'
import TableEmptyState from '../../components/shared/TableEmptyState.vue'
import { useSystemState } from '../../composables/useSystemState.js'
import { useToast } from '../../composables/useToast.js'
import {
@@ -77,11 +79,13 @@ import {
export default {
name: 'AuditView',
components: {
ConfirmDialog,
RiskRuleFlowDiagram,
RiskRuleTestDialog,
TableLoadingState,
TableEmptyState
AuditAssetList,
AuditJsonRiskRuleDetail,
AuditRuleDialogs,
AuditSpreadsheetChangeDrawer,
AuditSpreadsheetRuleDetail,
AuditVersionTimelineDrawer,
TableLoadingState
},
emits: ['detail-open-change'],
setup(_, { emit }) {
@@ -115,6 +119,10 @@ export default {
const reviewSubmitReviewer = ref('')
const reviewSubmitReviewerLoading = ref(false)
const reviewSubmitReviewerOptions = ref([])
const riskRuleAttachmentOptions = [
{ label: '是', value: true },
{ label: '否', value: false }
]
const riskRuleCreateOpen = ref(false)
const riskRuleCreateForm = ref(createDefaultRiskRuleForm())
const riskRuleTestOpen = ref(false)
@@ -466,7 +474,7 @@ export default {
icon: hasFilters ? 'mdi mdi-tune-variant' : 'mdi mdi-view-grid-outline',
actionLabel: hasFilters ? '清空筛选' : '',
actionIcon: hasFilters ? 'mdi mdi-filter-remove-outline' : '',
tone: hasFilters ? 'emerald' : 'slate',
tone: hasFilters ? 'primary' : 'slate',
artLabel: hasFilters ? 'FILTER' : 'QUEUE',
tips: hasFilters
? [
@@ -956,7 +964,7 @@ export default {
if (!canUploadSpreadsheet.value) {
return
}
spreadsheetUploadInput.value?.click()
spreadsheetUploadInput.value?.click?.()
}
async function downloadSpreadsheetFile() {
@@ -1003,9 +1011,7 @@ export default {
toast(error?.message || '规则表内容导入失败,请稍后重试。')
} finally {
actionState.value = ''
if (spreadsheetUploadInput.value) {
spreadsheetUploadInput.value.value = ''
}
spreadsheetUploadInput.value?.reset?.()
}
}
@@ -1916,6 +1922,7 @@ export default {
reviewSubmitReviewer,
reviewSubmitReviewerLoading,
reviewSubmitReviewerOptions,
riskRuleAttachmentOptions,
riskRuleCreateOpen,
riskRuleCreateForm,
riskRuleCreateBusy,

View File

@@ -2,6 +2,7 @@ import { computed, onMounted, ref, watch } from 'vue'
import BudgetTrendChart from '../../components/charts/BudgetTrendChart.vue'
import ConfirmDialog from '../../components/shared/ConfirmDialog.vue'
import EnterpriseSelect from '../../components/shared/EnterpriseSelect.vue'
import { createBudgetAllocation, fetchBudgetSummary } from '../../services/budgets.js'
import { fetchEmployeeMeta } from '../../services/employees.js'
import {
@@ -177,7 +178,8 @@ export default {
},
components: {
BudgetTrendChart,
ConfirmDialog
ConfirmDialog,
EnterpriseSelect
},
setup(props) {
const departments = ref(FALLBACK_DEPARTMENTS)
@@ -215,6 +217,14 @@ export default {
const isDepartmentBudgetMonitor = computed(
() => isBudgetMonitorUser(props.currentUser) && !canSwitchDepartments.value && !isExecutiveUser(props.currentUser)
)
const yearOptions = BUDGET_YEAR_OPTIONS.map((year) => ({ label: `${year}年度`, value: year }))
const budgetPageSizeOptions = BUDGET_PAGE_SIZE_OPTIONS.map((size) => ({ label: `${size} 条/页`, value: size }))
const departmentOptions = computed(() =>
departments.value.map((department) => ({
label: department.name,
value: department.code
}))
)
const activeDepartment = computed(() =>
departments.value.find((item) => item.code === activeDepartmentCode.value) || departments.value[0]
@@ -273,7 +283,7 @@ export default {
value: `¥${currency(totals.value.total)}`,
yoy: comparison('+8.42%', 'up'),
mom: comparison('+2.16%', 'up'),
tone: 'green',
tone: 'primary',
icon: 'mdi mdi-wallet-outline'
},
{
@@ -281,7 +291,7 @@ export default {
value: `¥${currency(totals.value.used)}`,
yoy: comparison('+12.68%', 'up'),
mom: comparison('+4.35%', 'up'),
tone: 'blue',
tone: 'info',
icon: 'mdi mdi-chart-line'
},
{
@@ -289,7 +299,7 @@ export default {
value: `¥${currency(totals.value.occupied)}`,
yoy: comparison('+6.37%', 'up'),
mom: comparison('-1.84%', 'down'),
tone: 'orange',
tone: 'warning',
icon: 'mdi mdi-briefcase-check-outline'
},
{
@@ -297,7 +307,7 @@ export default {
value: `¥${currency(totals.value.left)}`,
yoy: comparison('-3.26%', 'down'),
mom: comparison('-2.08%', 'down'),
tone: 'green',
tone: 'primary',
icon: 'mdi mdi-cash'
}
])
@@ -612,7 +622,7 @@ export default {
budgetPage: currentBudgetPage,
budgetPageNumbers,
budgetPageSize,
budgetPageSizeOptions: BUDGET_PAGE_SIZE_OPTIONS,
budgetPageSizeOptions,
canEditBudget,
canSwitchDepartments,
closeBudgetEditDialog,
@@ -633,6 +643,7 @@ export default {
confirmDeleteRow,
cancelDeleteRow,
cancelSaveBudget,
departmentOptions,
requestSaveBudget,
statusOptions: BUDGET_STATUS_OPTIONS,
statuses: ['全部', '正常', '预警', '管控'],
@@ -645,6 +656,7 @@ export default {
visibleDepartments,
warningOptions: BUDGET_WARNING_OPTIONS,
warnings,
yearOptions,
years: BUDGET_YEAR_OPTIONS
}
}

View File

@@ -1,6 +1,7 @@
import { computed, onBeforeUnmount, onMounted, ref, watch } from 'vue'
import ConfirmDialog from '../../components/shared/ConfirmDialog.vue'
import EnterpriseSelect from '../../components/shared/EnterpriseSelect.vue'
import TableLoadingState from '../../components/shared/TableLoadingState.vue'
import TableEmptyState from '../../components/shared/TableEmptyState.vue'
import { useToast } from '../../composables/useToast.js'
@@ -438,6 +439,7 @@ export default {
name: 'EmployeeManagementView',
components: {
ConfirmDialog,
EnterpriseSelect,
TableLoadingState,
TableEmptyState
},
@@ -457,7 +459,7 @@ export default {
const currentPage = ref(1)
const pageSize = ref(10)
const pageSizes = [10, 20, 50]
const pageSizeOpen = ref(false)
const pageSizeOptions = pageSizes.map((size) => ({ label: `${size} 条/页`, value: size }))
const actionState = ref('')
const loading = ref(false)
const errorMessage = ref('')
@@ -713,7 +715,7 @@ export default {
icon: hasEmployeeFilters.value ? 'mdi mdi-account-search-outline' : 'mdi mdi-badge-account-horizontal-outline',
actionLabel: hasEmployeeFilters.value ? '清空筛选' : '查看全部员工',
actionIcon: hasEmployeeFilters.value ? 'mdi mdi-filter-remove-outline' : 'mdi mdi-format-list-bulleted',
tone: hasEmployeeFilters.value ? 'emerald' : 'slate',
tone: hasEmployeeFilters.value ? 'primary' : 'slate',
artLabel: hasEmployeeFilters.value ? 'FILTER' : 'STATUS',
tips: hasEmployeeFilters.value
? ['关键词、部门、职级和角色条件会叠加生效', '也可以直接搜索姓名、工号或岗位']
@@ -791,7 +793,6 @@ export default {
watch(filteredEmployees, () => {
currentPage.value = 1
pageSizeOpen.value = false
})
function resetFilters() {
@@ -801,7 +802,6 @@ export default {
selectedRole.value = ''
activeTab.value = DEFAULT_STATUS_TABS[0]
activeFilterPopover.value = ''
pageSizeOpen.value = false
}
function handleEmployeeEmptyAction() {
@@ -815,14 +815,9 @@ export default {
function changePageSize(size) {
pageSize.value = size
pageSizeOpen.value = false
currentPage.value = 1
}
function togglePageSizeOpen() {
pageSizeOpen.value = !pageSizeOpen.value
}
function toggleFilterPopover(name) {
activeFilterPopover.value = activeFilterPopover.value === name ? '' : name
}
@@ -852,7 +847,6 @@ export default {
if (!(target instanceof Element)) {
closeFilterPopover()
pageSizeOpen.value = false
return
}
@@ -868,13 +862,8 @@ export default {
closeDepartmentPicker()
}
if (!target.closest('.page-size-wrap')) {
pageSizeOpen.value = false
}
if (
target.closest('.picker-filter') ||
target.closest('.page-size-wrap') ||
target.closest('.manager-picker') ||
target.closest('.department-picker')
) {
@@ -1437,7 +1426,7 @@ export default {
currentPage,
pageSize,
pageSizes,
pageSizeOpen,
pageSizeOptions,
departmentOptions,
gradeOptions,
roleFilterOptions,
@@ -1475,7 +1464,6 @@ export default {
disableDialogOpen,
disableEmployeeAccount,
changePageSize,
togglePageSizeOpen,
toggleFilterPopover,
closeFilterPopover,
selectFilter,

View File

@@ -1,6 +1,7 @@
import { ref } from 'vue'
import { testModelConnectivity } from '../../services/settings.js'
import { useToast } from '../../composables/useToast.js'
import EnterpriseSelect from '../../components/shared/EnterpriseSelect.vue'
const MODEL_SECRET_MASK = '********'
@@ -101,6 +102,9 @@ function isModelSecretMask(value) {
export default {
name: 'LlmSettingsPanel',
components: {
EnterpriseSelect
},
props: {
llmForm: {
type: Object,

View File

@@ -11,7 +11,7 @@ export default {
const showPassword = ref(false)
const features = [
{ title: '智能审单', desc: 'AI 自动识别票据与规则,提升准确率与效率', icon: 'mdi mdi-file-document-outline', tone: 'green' },
{ title: '智能审单', desc: 'AI 自动识别票据与规则,提升准确率与效率', icon: 'mdi mdi-file-document-outline', tone: 'primary' },
{ title: '异常预警', desc: '多维风险识别与预警,主动防控风险', icon: 'mdi mdi-bell-outline', tone: 'red' },
{ title: 'SLA 监控', desc: '实时监控服务水平协议,保障审批及时性', icon: 'mdi mdi-sync', tone: 'blue' }
]

View File

@@ -3,6 +3,7 @@ import { useRouter } from 'vue-router'
import LogTrendChart from '../../components/charts/LogTrendChart.vue'
import DonutChart from '../../components/charts/DonutChart.vue'
import EnterpriseSelect from '../../components/shared/EnterpriseSelect.vue'
import TableLoadingState from '../../components/shared/TableLoadingState.vue'
import { fetchAgentRuns } from '../../services/agentAssets.js'
import { fetchSystemLogEntries } from '../../services/systemLogs.js'
@@ -221,6 +222,7 @@ export default {
components: {
LogTrendChart,
DonutChart,
EnterpriseSelect,
TableLoadingState
},
emits: ['summary-change'],
@@ -237,20 +239,28 @@ export default {
const systemLevelFilter = ref('')
const systemEventTypeFilter = ref('')
const systemLogEntries = ref([])
const currentPage = ref(1)
const pageSize = ref(10)
const pageSizes = [10, 20, 50]
const pageSizeOpen = ref(false)
const currentPage = ref(1)
const pageSize = ref(10)
const pageSizes = [10, 20, 50]
const pageSizeOptions = pageSizes.map((size) => ({ label: `${size} 条/页`, value: size }))
let pollTimer = 0
const isAdmin = computed(() => isManagerUser(currentUser.value))
const filteredHermesRuns = computed(() => hermesRuns.value)
const systemLevelOptions = computed(() =>
Array.from(new Set(systemLogEntries.value.map((entry) => entry.level).filter(Boolean)))
)
const systemEventTypeOptions = computed(() =>
Array.from(new Set(systemLogEntries.value.map((entry) => entry.event_type).filter(Boolean)))
)
const systemLevelOptions = computed(() =>
Array.from(new Set(systemLogEntries.value.map((entry) => entry.level).filter(Boolean)))
)
const systemEventTypeOptions = computed(() =>
Array.from(new Set(systemLogEntries.value.map((entry) => entry.event_type).filter(Boolean)))
)
const systemLevelFilterOptions = computed(() => [
{ label: '全部', value: '' },
...systemLevelOptions.value
])
const systemEventTypeFilterOptions = computed(() => [
{ label: '全部', value: '' },
...systemEventTypeOptions.value
])
const filteredSystemLogEntries = computed(() => {
const keyword = systemSearchKeyword.value.trim().toLowerCase()
return systemLogEntries.value.filter((entry) => {
@@ -330,11 +340,10 @@ export default {
return filteredSystemLogEntries.value.slice(start, start + pageSize.value)
})
function changePageSize(size) {
pageSize.value = size
pageSizeOpen.value = false
currentPage.value = 1
}
function changePageSize(size) {
pageSize.value = size
currentPage.value = 1
}
async function loadHermesRuns() {
if (!isAdmin.value) {
@@ -456,8 +465,8 @@ export default {
loadSystemLogs,
currentPage,
pageSize,
pageSizeOpen,
pageSizes,
pageSizes,
pageSizeOptions,
resolveLevelTone,
resolveRunLevel,
resolveRunModuleLabel,
@@ -472,10 +481,12 @@ export default {
runningRunCount,
selectRun,
selectSystemLog,
systemEventTypeFilter,
systemEventTypeOptions,
systemLevelFilter,
systemLevelOptions,
systemEventTypeFilter,
systemEventTypeFilterOptions,
systemEventTypeOptions,
systemLevelFilter,
systemLevelFilterOptions,
systemLevelOptions,
systemLogEntries,
systemLogLoading,
systemSearchKeyword,

View File

@@ -1,5 +1,10 @@
import EnterpriseSelect from '../../components/shared/EnterpriseSelect.vue'
export default {
name: 'MailSettingsPanel',
components: {
EnterpriseSelect
},
props: {
mailForm: {
type: Object,
@@ -7,6 +12,12 @@ export default {
}
},
setup(props) {
const encryptionOptions = [
{ label: 'SSL/TLS', value: 'SSL/TLS' },
{ label: 'STARTTLS', value: 'STARTTLS' },
{ label: '无', value: 'None' }
]
function toggleField(field) {
if (props.mailForm) {
props.mailForm[field] = !props.mailForm[field]
@@ -14,6 +25,7 @@ export default {
}
return {
encryptionOptions,
toggleField
}
}

View File

@@ -36,11 +36,11 @@ export default {
}
const demoDepartments = [
{ name: '销售部', amount: 182000, color: '#10b981' },
{ name: '研发中心', amount: 146000, color: '#3b82f6' },
{ name: '市场部', amount: 96000, color: '#f59e0b' },
{ name: '运营部', amount: 68600, color: '#8b5cf6' },
{ name: '行政部', amount: 48300, color: '#3b82f6' }
{ name: '销售部', amount: 182000, color: 'var(--theme-primary)' },
{ name: '研发中心', amount: 146000, color: 'var(--chart-blue)' },
{ name: '市场部', amount: 96000, color: 'var(--chart-amber)' },
{ name: '运营部', amount: 68600, color: 'var(--chart-purple)' },
{ name: '行政部', amount: 48300, color: 'var(--chart-blue)' }
]
const formatCompact = (value) => {

View File

@@ -1,6 +1,7 @@
import { computed, nextTick, onBeforeUnmount, onMounted, ref, watch } from 'vue'
import ConfirmDialog from '../../components/shared/ConfirmDialog.vue'
import EnterpriseSelect from '../../components/shared/EnterpriseSelect.vue'
import TableLoadingState from '../../components/shared/TableLoadingState.vue'
import { useSystemState } from '../../composables/useSystemState.js'
import { useToast } from '../../composables/useToast.js'
@@ -86,6 +87,7 @@ export default {
name: 'PoliciesView',
components: {
ConfirmDialog,
EnterpriseSelect,
TableLoadingState
},
emits: ['summary-change'],
@@ -95,13 +97,13 @@ export default {
const documentSearch = ref('')
const activeFolder = ref('')
const folders = ref([])
const documents = ref([])
const selectedDocument = ref(null)
const pageSizeOpen = ref(false)
const currentPage = ref(1)
const pageSize = ref(10)
const pageSizes = [10, 20, 50]
const folders = ref([])
const documents = ref([])
const selectedDocument = ref(null)
const currentPage = ref(1)
const pageSize = ref(10)
const pageSizes = [10, 20, 50]
const pageSizeOptions = pageSizes.map((size) => ({ label: `${size} 条/页`, value: size }))
const loading = ref(false)
const uploadInput = ref(null)
const uploading = ref(false)
@@ -558,11 +560,10 @@ export default {
}
}
function changePageSize(size) {
pageSize.value = size
pageSizeOpen.value = false
currentPage.value = 1
}
function changePageSize(size) {
pageSize.value = size
currentPage.value = 1
}
function closePreview() {
selectedDocument.value = null
@@ -586,12 +587,11 @@ export default {
currentPreviewPageIndex.value = index
}
watch(filteredDocuments, () => {
currentPage.value = 1
pageSizeOpen.value = false
if (selectedDocument.value && !filteredDocuments.value.some((doc) => doc.id === selectedDocument.value.id)) {
closePreview()
watch(filteredDocuments, () => {
currentPage.value = 1
if (selectedDocument.value && !filteredDocuments.value.some((doc) => doc.id === selectedDocument.value.id)) {
closePreview()
}
})
@@ -650,9 +650,9 @@ export default {
knowledgeSyncButtonLabel,
knowledgeSyncHint,
loading,
pageSize,
pageSizeOpen,
pageSizes,
pageSize,
pageSizeOptions,
pageSizes,
onlyOfficeError,
onlyOfficeHostId,
onlyOfficeLoading,

View File

@@ -1,5 +1,6 @@
import { computed, ref, watch } from 'vue'
import EnterpriseSelect from '../../components/shared/EnterpriseSelect.vue'
import TableLoadingState from '../../components/shared/TableLoadingState.vue'
import TableEmptyState from '../../components/shared/TableEmptyState.vue'
import { normalizeRequestForUi } from '../../utils/requestViewModel.js'
@@ -12,6 +13,7 @@ function extractRowDate(value) {
export default {
name: 'RequestsView',
components: {
EnterpriseSelect,
TableLoadingState,
TableEmptyState
},
@@ -61,11 +63,10 @@ export default {
const currentPage = ref(1)
const pageSize = ref(10)
const pageSizes = [10, 20, 50]
const pageSizeOpen = ref(false)
const pageSizeOptions = pageSizes.map((size) => ({ label: `${size} 条/页`, value: size }))
function changePageSize(size) {
pageSize.value = size
pageSizeOpen.value = false
currentPage.value = 1
}
@@ -132,7 +133,7 @@ export default {
icon: 'mdi mdi-receipt-text-plus-outline',
actionLabel: '',
actionIcon: '',
tone: 'emerald',
tone: 'theme',
artLabel: 'CLAIM',
tips: ['保存草稿后会自动回到这里', '支持草稿、待提交、审批中和已完成全流程管理']
}
@@ -163,7 +164,6 @@ export default {
rangeEnd.value = ''
appliedStart.value = ''
appliedEnd.value = ''
pageSizeOpen.value = false
currentPage.value = 1
}
@@ -197,7 +197,7 @@ export default {
currentPage,
pageSize,
pageSizes,
pageSizeOpen,
pageSizeOptions,
changePageSize,
filteredRows,
totalCount,

View File

@@ -1,12 +1,14 @@
import HermesEmployeeSettingsPanel from '../HermesEmployeeSettingsPanel.vue'
import LlmSettingsPanel from '../LlmSettingsPanel.vue'
import MailSettingsPanel from '../MailSettingsPanel.vue'
import EnterpriseSelect from '../../components/shared/EnterpriseSelect.vue'
import { useSettings } from '../../composables/useSettings.js'
export default {
name: 'SettingsView',
components: {
HermesEmployeeSettingsPanel,
EnterpriseSelect,
LlmSettingsPanel,
MailSettingsPanel
},
@@ -18,4 +20,3 @@ export default {
}
}
}

View File

@@ -2,6 +2,8 @@ import { computed, nextTick, onBeforeUnmount, onMounted, ref, watch } from 'vue'
import { useRouter } from 'vue-router'
import ConfirmDialog from '../../components/shared/ConfirmDialog.vue'
import TravelReimbursementInsightPanel from '../../components/travel/TravelReimbursementInsightPanel.vue'
import TravelReimbursementMessageItem from '../../components/travel/TravelReimbursementMessageItem.vue'
import { useSystemState } from '../../composables/useSystemState.js'
import { useToast } from '../../composables/useToast.js'
import { useTravelReimbursementFlow } from './useTravelReimbursementFlow.js'
@@ -501,7 +503,9 @@ function buildReviewMainMessageText(message) {
export default {
name: 'TravelReimbursementCreateView',
components: {
ConfirmDialog
ConfirmDialog,
TravelReimbursementInsightPanel,
TravelReimbursementMessageItem
},
props: {
initialPrompt: {
@@ -2109,8 +2113,126 @@ export default {
await handleSaveDraftDirectly(message, 'save_draft')
}
const messageItemUi = computed(() => ({
ASSISTANT_DISPLAY_NAME,
aiAvatar,
userAvatar,
submitting: submitting.value,
reviewActionBusy: reviewActionBusy.value,
sessionSwitchBusy: sessionSwitchBusy.value,
applicationPreviewEditor: applicationPreviewEditor.value,
buildMessageBubbleClass,
buildReviewMainMessageText,
renderMarkdown,
handleAssistantMarkdownClick,
resolveApplicationPreviewRows,
resolveApplicationPreviewEditorControl,
resolveApplicationPreviewEditorOptions,
isApplicationPreviewEditing,
openApplicationPreviewEditor,
commitApplicationPreviewEditor,
handleApplicationPreviewEditorKeydown,
buildApplicationPreviewFooterText,
runWelcomeQuickAction: runShortcut,
handleSuggestedAction,
isSuggestedActionSelected,
buildExpenseQueryWindowLabel,
buildExpenseQueryHint,
getExpenseQueryActivePage,
getExpenseQueryTotalPages,
getExpenseQueryVisibleRecords,
handleExpenseQueryRecordClick,
appendExpenseQueryRiskToConversation,
shiftExpenseQueryPage,
setExpenseQueryPage,
buildReviewPlainFollowupForMessage,
canUseInlineSaveDraft,
handleInlineSaveDraft,
buildReviewNextStepRichCopyForMessage,
resolveReviewFooterActions,
handleReviewAction,
buildReviewPrimaryButtonLabel
}))
const insightPanelUi = computed(() => ({
showInsightPanel: showInsightPanel.value,
isKnowledgeSession: isKnowledgeSession.value,
activeReviewPayload: activeReviewPayload.value,
isReviewFlowDrawer: isReviewFlowDrawer.value,
currentInsight: currentInsight.value,
currentIntentLabel: currentIntentLabel.value,
reviewDrawerTitle: reviewDrawerTitle.value,
reviewOverviewDrawerAvailable: reviewOverviewDrawerAvailable.value,
isReviewOverviewDrawer: isReviewOverviewDrawer.value,
submitting: submitting.value,
reviewActionBusy: reviewActionBusy.value,
switchToReviewOverviewDrawer,
reviewDocumentDrawerAvailable: reviewDocumentDrawerAvailable.value,
isReviewDocumentDrawer: isReviewDocumentDrawer.value,
toggleReviewDocumentDrawer,
reviewDocumentDrawerIcon: reviewDocumentDrawerIcon.value,
reviewRiskDrawerAvailable: reviewRiskDrawerAvailable.value,
isReviewRiskDrawer: isReviewRiskDrawer.value,
toggleReviewRiskDrawer,
reviewRiskDrawerIcon: reviewRiskDrawerIcon.value,
reviewFlowDrawerAvailable: reviewFlowDrawerAvailable.value,
flowOverallStatusTone: flowOverallStatusTone.value,
toggleReviewFlowDrawer,
reviewFlowDrawerIcon: reviewFlowDrawerIcon.value,
activeSessionType: activeSessionType.value,
reviewDrawerMode: reviewDrawerMode.value,
hotKnowledgeQuestions,
deleteSessionBusy: deleteSessionBusy.value,
sessionSwitchBusy: sessionSwitchBusy.value,
askHotKnowledgeQuestion,
resolveKnowledgeRankTone,
resolveKnowledgeRankLabel,
flowOverallStatusText: flowOverallStatusText.value,
flowTotalDurationText: flowTotalDurationText.value,
flowRunId: flowRunId.value,
flowRefreshBusy: flowRefreshBusy.value,
refreshFlowRunDetail,
flowSteps: flowSteps.value,
resolveFlowStepStatusLabel,
formatFlowStepDuration,
resolveFlowStepDetail,
reviewIntentText: reviewIntentText.value,
reviewFactCards: reviewFactCards.value,
reviewInlineEditorKey: reviewInlineEditorKey.value,
reviewInlineErrors: reviewInlineErrors.value,
reviewInlineForm: reviewInlineForm.value,
DATE_INPUT_FORMAT,
REVIEW_SCENE_OPTIONS,
REVIEW_SCENE_OTHER_OPTION,
clearInlineReviewFieldError,
commitInlineReviewEditor,
selectInlineScene,
reviewInlinePendingFiles: reviewInlinePendingFiles.value,
openInlineReviewEditor,
reviewPanelConfidence: reviewPanelConfidence.value,
reviewCategoryOptions: reviewCategoryOptions.value,
selectReviewCategory,
reviewSelectedOtherCategory: reviewSelectedOtherCategory.value,
reviewOtherCategoryOpen: reviewOtherCategoryOpen.value,
reviewOtherCategoryOptions: reviewOtherCategoryOptions.value,
selectReviewOtherCategory,
activeReviewDocumentIndex: activeReviewDocumentIndex.value,
reviewDocumentCount: reviewDocumentCount.value,
goReviewDocument,
activeReviewDocument: activeReviewDocument.value,
activeReviewDocumentPreview: activeReviewDocumentPreview.value,
canPreviewActiveReviewDocument: canPreviewActiveReviewDocument.value,
openActiveReviewDocumentPreview,
reviewRiskSummary: reviewRiskSummary.value,
reviewRiskItems: reviewRiskItems.value,
appendReviewRiskBriefToConversation,
reviewRiskEmpty: reviewRiskEmpty.value,
reviewHasUnsavedChanges: reviewHasUnsavedChanges.value,
saveInlineReviewChanges
}))
return {
emit, ASSISTANT_DISPLAY_NAME, aiAvatar, userAvatar, fileInputRef, composerTextareaRef, messageListRef, composerDraft, composerDatePickerOpen, composerDateMode, composerSingleDate, composerRangeStartDate, composerRangeEndDate, composerBusinessTimeTags, composerCanApplyDateSelection,
emit, messageItemUi, insightPanelUi, ASSISTANT_DISPLAY_NAME, aiAvatar, userAvatar, fileInputRef, composerTextareaRef, messageListRef, composerDraft, composerDatePickerOpen, composerDateMode, composerSingleDate, composerRangeStartDate, composerRangeEndDate, composerBusinessTimeTags, composerCanApplyDateSelection,
toggleComposerDatePicker, closeComposerDatePicker, setComposerDateMode, handleComposerDateInputChange, removeComposerBusinessTimeTag, flowSteps, flowRunId, flowRefreshBusy, completedFlowStepCount, flowOverallStatusTone, flowOverallStatusText, flowTotalDurationText,
attachedFiles, composerFilesExpanded, visibleAttachedFiles, hiddenAttachedFileCount, submitting, sessionSwitchBusy, messages, currentInsight, linkedRequest, canSubmit, activeSessionType, isKnowledgeSession, hotKnowledgeQuestions,
hasInsightPanelContent, showInsightPanel, insightPanelToggleLabel, assistantHeaderTitle, assistantHeaderDescription, composerPlaceholder, currentIntentLabel, canDeleteCurrentSession, latestReviewMessage, activeReviewPayload, activeReviewPanelScope, activeReviewFilePreviews, reviewDrawerMode, isReviewOverviewDrawer, isReviewDocumentDrawer, isReviewRiskDrawer, isReviewFlowDrawer,

View File

@@ -2,8 +2,11 @@ import { computed, onBeforeUnmount, reactive, ref, watch } from 'vue'
import { useSystemState } from '../../composables/useSystemState.js'
import { useToast } from '../../composables/useToast.js'
import EnterpriseSelect from '../../components/shared/EnterpriseSelect.vue'
import ConfirmDialog from '../../components/shared/ConfirmDialog.vue'
import ReturnReasonDialog from '../../components/shared/ReturnReasonDialog.vue'
import TravelRequestApprovalDialog from '../../components/travel/TravelRequestApprovalDialog.vue'
import TravelRequestDeleteDialog from '../../components/travel/TravelRequestDeleteDialog.vue'
import TravelRequestReturnDialog from '../../components/travel/TravelRequestReturnDialog.vue'
import {
approveExpenseClaim,
createExpenseClaimItem,
@@ -358,7 +361,10 @@ export default {
name: 'TravelRequestDetailView',
components: {
ConfirmDialog,
ReturnReasonDialog
EnterpriseSelect,
TravelRequestApprovalDialog,
TravelRequestDeleteDialog,
TravelRequestReturnDialog
},
props: {
request: {

View File

@@ -71,7 +71,7 @@ export const TAB_META = {
tableColumns: RULE_TABLE_COLUMNS,
showRuntimeColumn: false,
showStatusColumn: false,
badgeTone: 'emerald'
badgeTone: 'primary'
},
riskRules: {
assetType: 'rule',

View File

@@ -346,7 +346,7 @@ export function resolveTabMeta(tabId, typeKey) {
return {
...TYPE_META.rules,
typeKey: 'rules',
badgeTone: 'emerald'
badgeTone: 'primary'
}
}
return TAB_META[typeKey]