Merge remote-tracking branch 'origin/ai-hub' into ai-hub

This commit is contained in:
ccnetcore
2026-01-04 00:08:24 +08:00
12 changed files with 735 additions and 47 deletions

View File

@@ -445,4 +445,119 @@ function getProgressColor(task: DailyTaskItem): string {
font-size: 13px;
color: #606266;
}
/* 移动端响应式优化 */
@media (max-width: 768px) {
.daily-task-container {
padding: 12px;
}
.task-header h2 {
font-size: 20px;
}
.task-desc {
font-size: 13px;
}
/* 消耗统计卡片 */
.consumption-card {
padding: 16px;
flex-direction: column;
text-align: center;
}
.consumption-icon {
font-size: 40px;
margin-right: 0;
margin-bottom: 12px;
}
.consumption-value {
font-size: 28px;
}
/* 任务列表 */
.task-item {
flex-direction: column;
padding: 16px;
gap: 12px;
}
.task-icon {
font-size: 40px;
margin-right: 0;
margin-bottom: 8px;
justify-content: center;
}
.task-main {
gap: 10px;
}
.task-title {
flex-direction: column;
align-items: flex-start;
gap: 8px;
}
.task-name {
font-size: 16px;
}
.task-description {
font-size: 13px;
}
.task-action {
margin-left: 0;
width: 100%;
}
.task-action .el-button {
width: 100%;
}
.task-tips ul {
padding-left: 16px;
}
.task-tips li {
font-size: 12px;
}
}
@media (max-width: 480px) {
.daily-task-container {
padding: 8px;
}
.task-header h2 {
font-size: 18px;
}
.consumption-card {
padding: 12px;
}
.consumption-icon {
font-size: 36px;
}
.consumption-value {
font-size: 24px;
}
.task-item {
padding: 12px;
}
.task-name {
font-size: 15px;
}
.reward-value {
font-size: 15px;
}
}
</style>

View File

@@ -1100,11 +1100,20 @@ onBeforeUnmount(() => {
/* 响应式布局 */
@media (max-width: 768px) {
.premium-package-info {
padding: 0;
}
.header {
flex-direction: column;
align-items: flex-start;
gap: 16px;
padding-bottom: 16px;
gap: 12px;
padding-bottom: 12px;
margin-bottom: 16px;
}
.header-left {
gap: 12px;
}
.header-main-icon {
@@ -1120,18 +1129,47 @@ onBeforeUnmount(() => {
font-size: 12px;
}
.header .el-button {
width: 100%;
}
.package-card {
border-radius: 12px;
}
.stats-grid {
grid-template-columns: 1fr;
gap: 12px;
}
.stat-item {
padding: 16px;
}
.stat-value {
font-size: 24px;
}
.stat-label {
font-size: 13px;
}
.progress-section {
padding: 16px;
}
.progress-label {
font-size: 14px;
}
.progress-percent {
font-size: 18px;
}
.progress-legend {
flex-direction: column;
gap: 8px;
align-items: flex-start;
}
.warning-content {
@@ -1139,6 +1177,18 @@ onBeforeUnmount(() => {
text-align: center;
}
.warning-icon {
font-size: 32px;
}
.warning-text h3 {
font-size: 16px;
}
.warning-text p {
font-size: 13px;
}
.card-header-left {
gap: 10px;
}
@@ -1155,5 +1205,66 @@ onBeforeUnmount(() => {
.header-subtitle {
font-size: 12px;
}
.token-pie-chart {
height: 300px;
}
.chart-container-wrapper {
padding: 12px;
}
.token-stat-item {
padding: 12px;
}
.token-name {
font-size: 14px;
}
.stat-tokens .value {
font-size: 18px;
}
.tips-content li {
font-size: 12px;
}
.token-usage-card {
margin-top: 16px;
}
}
@media (max-width: 480px) {
.header-main-icon {
font-size: 24px;
padding: 8px;
}
.main-title {
font-size: 18px;
}
.stat-item {
padding: 12px;
}
.stat-value {
font-size: 20px;
}
.header-title {
font-size: 15px;
}
.token-pie-chart {
height: 280px;
}
.rank-badge {
width: 28px;
height: 28px;
font-size: 12px;
}
}
</style>

View File

@@ -525,4 +525,120 @@ onUnmounted(() => {
:deep(.el-pagination.is-background .el-pager li:not(.is-disabled):hover) {
color: #409eff;
}
/* 移动端响应式优化 */
@media (max-width: 768px) {
.recharge-log-container {
padding: 12px;
}
.log-header {
flex-direction: column;
align-items: stretch;
gap: 12px;
margin-bottom: 16px;
padding-bottom: 12px;
}
.log-title {
font-size: 18px;
}
.log-title .el-icon {
font-size: 20px;
}
.header-actions {
flex-wrap: wrap;
width: 100%;
}
.header-actions .el-input {
width: 100% !important;
margin-left: 0 !important;
margin-top: 8px;
}
/* 表格移动端优化 */
:deep(.el-table) {
font-size: 12px;
}
:deep(.el-table th) {
font-size: 12px;
padding: 6px 0;
}
:deep(.el-table .cell) {
padding: 8px 6px;
}
:deep(.el-table__body-wrapper) {
overflow-x: auto;
}
.amount-cell {
font-size: 13px;
}
.log-footer {
flex-direction: column;
gap: 12px;
align-items: stretch;
margin-top: 16px;
padding-top: 12px;
}
.summary {
font-size: 14px;
text-align: center;
}
:deep(.el-pagination) {
justify-content: center;
}
/* 对话框移动端优化 */
:deep(.el-dialog) {
width: 90% !important;
margin: 5vh auto !important;
}
:deep(.el-dialog__body) {
padding: 15px;
}
.fullscreen-image {
max-width: 95%;
max-height: 95%;
border: 4px solid white;
border-radius: 12px;
}
}
@media (max-width: 480px) {
.recharge-log-container {
padding: 8px;
}
.log-title {
font-size: 16px;
}
:deep(.el-table) {
font-size: 11px;
}
:deep(.el-table th) {
font-size: 11px;
}
:deep(.el-table .cell) {
padding: 6px 4px;
}
.header-actions .el-button {
padding: 8px;
}
}
</style>

View File

@@ -147,10 +147,19 @@ function updateLineChart() {
const tokens = usageData.value.map(item => item.tokens);
const isMobile = window.innerWidth < 768;
const option = {
tooltip: {
trigger: 'axis',
formatter: '{b}<br/>用量: {c} ',
confine: true,
position(point: any, params: any, dom: any, rect: any, size: any) {
if (isMobile) {
return ['50%', '10%'];
}
return null;
},
},
grid: {
left: '3%',
@@ -265,12 +274,31 @@ function updatePieChart() {
const isManyItems = data.length > 8;
const isSmallContainer = pieContainerSize.width.value < 600;
const isMobile = window.innerWidth < 768;
const option = {
graphic: [], // 清空graphic配置
tooltip: {
trigger: 'item',
formatter: '{a} <br/>{b}: {c} tokens ({d}%)',
formatter: isMobile
? (params: any) => {
// 移动端简化显示
return `${params.name}<br/>占比: ${params.percent}%`;
}
: '{a} <br/>{b}: {c} tokens ({d}%)',
confine: true,
textStyle: {
fontSize: isMobile ? 11 : 14,
},
padding: isMobile ? [5, 8] : [10, 15],
position(point: any, params: any, dom: any, rect: any, size: any) {
if (isMobile) {
// 移动端固定在顶部中央
return ['50%', '10%'];
}
// 桌面端自动定位
return null;
},
},
legend: {
show: false, // 隐藏图例,使用标签线代替
@@ -279,7 +307,7 @@ function updatePieChart() {
{
name: '模型用量',
type: 'pie',
radius: ['50%', '70%'],
radius: isMobile ? ['40%', '60%'] : ['50%', '70%'],
center: ['50%', '50%'],
avoidLabelOverlap: true,
itemStyle: {
@@ -289,16 +317,16 @@ function updatePieChart() {
},
label: {
show: true,
position: 'outside',
formatter: '{b}: {d}%',
fontSize: 13,
position: isMobile ? 'inside' : 'outside',
formatter: isMobile ? '{d}%' : '{b}: {d}%',
fontSize: isMobile ? 11 : 13,
fontWeight: 600,
color: '#333',
color: isMobile ? '#fff' : '#333',
},
emphasis: {
label: {
show: true,
fontSize: 16,
fontSize: isMobile ? 13 : 16,
fontWeight: 'bold',
},
itemStyle: {
@@ -308,7 +336,7 @@ function updatePieChart() {
},
},
labelLine: {
show: true,
show: !isMobile,
length: 15,
length2: 10,
lineStyle: {
@@ -395,6 +423,7 @@ function updateBarChart() {
const isManyItems = models.length > 10;
const isSmallContainer = barContainerSize.width.value < 600;
const isMobile = window.innerWidth < 768;
const option = {
graphic: [], // 清空graphic配置
@@ -404,27 +433,43 @@ function updateBarChart() {
type: 'shadow',
},
formatter: '{b}<br/>用量: {c} tokens',
confine: true,
position(point: any, params: any, dom: any, rect: any, size: any) {
if (isMobile) {
// 移动端固定在顶部中央
return ['50%', '10%'];
}
// 桌面端自动定位
return null;
},
},
grid: {
left: '3%',
right: '4%',
left: isMobile ? '5%' : '3%',
right: isMobile ? '5%' : '4%',
bottom: '3%',
top: '3%',
containLabel: true,
},
xAxis: {
type: 'value',
name: 'Token用量',
name: isMobile ? '' : 'Token用量',
nameTextStyle: {
fontSize: isMobile ? 11 : 12,
},
axisLabel: {
fontSize: isMobile ? 10 : 12,
},
},
yAxis: {
type: 'category',
data: models,
axisLabel: {
interval: 0,
fontSize: Math.max(10, 14 - Math.floor(models.length / 10)),
fontSize: isMobile ? 10 : Math.max(10, 14 - Math.floor(models.length / 10)),
formatter(value: string) {
if (isSmallContainer && value.length > 10) {
return `${value.substring(0, 8)}...`;
const maxLength = isMobile ? 8 : (isSmallContainer ? 10 : 20);
if (value.length > maxLength) {
return `${value.substring(0, maxLength - 2)}...`;
}
return value;
},
@@ -455,9 +500,10 @@ function updateBarChart() {
borderRadius: [0, 4, 4, 0],
},
label: {
show: true,
show: !isMobile,
position: 'right',
formatter: '{c} ',
fontSize: isMobile ? 10 : 12,
},
},
],
@@ -569,7 +615,7 @@ onBeforeUnmount(() => {
</div>
</template>
<div class="chart-container">
<div ref="lineChart" class="chart" style="height: 350px;" />
<div ref="lineChart" class="chart line-chart" />
</div>
</el-card>
@@ -580,7 +626,7 @@ onBeforeUnmount(() => {
</div>
</template>
<div class="chart-container">
<div ref="pieChart" class="chart" style="height: 400px;" />
<div ref="pieChart" class="chart pie-chart" />
</div>
</el-card>
@@ -591,7 +637,7 @@ onBeforeUnmount(() => {
</div>
</template>
<div class="chart-container">
<div ref="barChart" class="chart" style="height: 450px;" />
<div ref="barChart" class="chart bar-chart" />
</div>
</el-card>
</div>
@@ -738,36 +784,129 @@ onBeforeUnmount(() => {
transition: all 0.3s ease;
}
/* 不同图表类型的默认高度 */
.line-chart {
height: 350px;
}
.pie-chart {
height: 400px;
}
.bar-chart {
height: 450px;
}
@media (max-width: 768px) {
.usage-statistics {
padding: 15px;
padding: 12px;
}
.header {
flex-direction: column;
align-items: flex-start;
gap: 12px;
margin-bottom: 20px;
margin-bottom: 16px;
padding-bottom: 12px;
}
.header h2 {
font-size: 18px;
}
.header .el-icon {
font-size: 20px;
}
.header-actions {
width: 100%;
flex-direction: column;
gap: 8px;
}
.token-selector {
width: 100% !important;
}
.chart-card {
margin-bottom: 20px;
}
.chart {
height: 350px !important;
}
.usage-statistics.fullscreen-mode {
padding: 15px;
margin-bottom: 16px;
border-radius: 12px;
}
.card-header {
flex-direction: column;
align-items: flex-start;
gap: 8px;
font-size: 14px;
}
.card-title {
font-size: 14px;
word-break: break-word;
}
.chart-container {
padding: 8px;
overflow: hidden;
}
/* 移动端图表高度优化 */
.line-chart {
height: 280px !important;
}
.pie-chart {
height: 350px !important;
}
.bar-chart {
height: 400px !important;
}
.usage-statistics.fullscreen-mode {
padding: 12px;
}
/* Tag 样式优化 */
:deep(.el-tag) {
font-size: 11px;
padding: 2px 6px;
height: auto;
}
}
@media (max-width: 480px) {
.usage-statistics {
padding: 8px;
}
.header h2 {
font-size: 16px;
}
.card-title {
font-size: 13px;
}
/* 超小屏幕图表高度 */
.line-chart {
height: 250px !important;
}
.pie-chart {
height: 320px !important;
}
.bar-chart {
height: 380px !important;
}
.chart-card {
margin-bottom: 12px;
}
.chart-container {
padding: 6px;
}
}
</style>

View File

@@ -752,14 +752,17 @@ function toggleSidebar() {
.aside-container {
position: fixed;
left: 0;
top: 0;
top: var(--header-container-default-height, 64px);
bottom: 0;
z-index: 1000;
width: 280px !important;
max-width: 80vw;
transform: translateX(-100%);
transition: transform 0.3s cubic-bezier(0.4, 0, 0.2, 1);
box-shadow: 2px 0 8px rgba(0, 0, 0, 0.15);
background: #fff;
overflow-y: auto;
overflow-x: hidden;
&.aside-collapsed {
transform: translateX(-100%);
@@ -773,6 +776,7 @@ function toggleSidebar() {
.aside-wrapper {
width: 280px !important;
max-width: 80vw;
.aside-collapsed & {
width: 100px !important;
@@ -782,7 +786,7 @@ function toggleSidebar() {
// 移动端遮罩层
.aside-overlay {
position: fixed;
top: 0;
top: var(--header-container-default-height, 64px);
left: 0;
right: 0;
bottom: 0;

View File

@@ -195,6 +195,8 @@ function toggleMobileMenu() {
direction="rtl"
:size="280"
:close-on-click-modal="true"
:lock-scroll="true"
:modal-class="'mobile-drawer-modal'"
class="mobile-drawer"
>
<template #header>

View File

@@ -31,7 +31,6 @@ const sessionId = computed(() => route.params?.id);
display: flex;
width: 100%;
height: calc(100vh - var(--header-container-default-height));
overflow: hidden;
}
@@ -41,4 +40,18 @@ const sessionId = computed(() => route.params?.id);
flex-direction: column;
overflow: hidden;
}
/* 移动端优化 */
@media (max-width: 768px) {
.conversation-page {
position: relative;
overflow: hidden;
}
.chat-content {
width: 100%;
overflow-y: auto;
overflow-x: hidden;
}
}
</style>

View File

@@ -90,12 +90,12 @@ window.addEventListener('resize', checkIsMobile);
<!-- 主内容区 -->
<div class="content-main">
<div v-if="isMobile" class="content-header">
<div class="mobile-toggle" @click="isCollapsed = false">
<el-icon><Expand /></el-icon>
<span>AI应用</span>
</div>
</div>
<!-- <div v-if="isMobile" class="content-header"> -->
<!-- <div class="mobile-toggle" @click="isCollapsed = false"> -->
<!-- <el-icon><Expand /></el-icon> -->
<!-- <span>AI应用</span> -->
<!-- </div> -->
<!-- </div> -->
<router-view v-slot="{ Component }">
<keep-alive>
<component :is="Component" />

View File

@@ -746,4 +746,128 @@ function handleImagePreview(url: string) {
display: inline-block;
margin-left: 8px;
}
/* 移动端响应式优化 */
@media (max-width: 768px) {
.chat-with-id-container {
padding: 0 12px;
.chat-header {
height: 50px;
.left-box {
padding-left: 8px;
gap: 8px;
}
.middle-box {
margin-left: 8px;
}
}
.chat-warp {
height: calc(100vh - 110px);
.thinking-chain-warp {
margin-bottom: 8px;
}
}
/* 气泡列表优化 */
:deep(.el-bubble-list) {
padding-top: 16px;
}
:deep(.el-bubble) {
padding: 0 8px;
padding-bottom: 16px;
}
/* 用户图片优化 */
:deep(.user-image) {
max-width: 150px;
max-height: 150px;
}
/* 文件项优化 */
:deep(.user-file-item) {
padding: 6px 10px;
font-size: 12px;
.file-icon {
font-size: 14px;
}
}
/* Sender 输入框优化 */
.chat-defaul-sender {
margin-bottom: 16px;
}
/* Footer 优化 */
.footer-wrapper {
flex-wrap: wrap;
gap: 6px;
}
.footer-time {
font-size: 11px;
.footer-token {
padding: 0 3px;
font-size: 11px;
}
}
}
}
/* 超小屏幕优化 */
@media (max-width: 480px) {
.chat-with-id-container {
padding: 0 8px;
.chat-header {
height: 48px;
.left-box {
padding-left: 4px;
gap: 6px;
}
.middle-box {
margin-left: 6px;
}
}
.chat-warp {
height: calc(100vh - 100px);
}
:deep(.el-bubble-list) {
padding-top: 12px;
}
:deep(.el-bubble) {
padding: 0 6px;
padding-bottom: 12px;
}
:deep(.user-image) {
max-width: 120px;
max-height: 120px;
}
.chat-defaul-sender {
margin-bottom: 12px;
}
.footer-time {
font-size: 10px;
.footer-token {
font-size: 10px;
}
}
}
}
</style>

View File

@@ -113,12 +113,12 @@ window.addEventListener('resize', checkIsMobile);
<!-- 主内容区 -->
<div class="content-main">
<div v-if="isMobile" class="content-header">
<div class="mobile-toggle" @click="isCollapsed = false">
<el-icon><Expand /></el-icon>
<span>控制台</span>
</div>
</div>
<!-- <div v-if="isMobile" class="content-header"> -->
<!-- <div class="mobile-toggle" @click="isCollapsed = false"> -->
<!-- <el-icon><Expand /></el-icon> -->
<!-- <span>控制台</span> -->
<!-- </div> -->
<!-- </div> -->
<router-view v-slot="{ Component }">
<keep-alive>
<component :is="Component" :external-invite-code="inviteCodeFromUrl" />

View File

@@ -9,7 +9,21 @@
// el 弹框不知道为啥宽度会变大
.el-popup-parent--hidden {
width: 100% !important;
overflow: hidden;
overflow: hidden !important;
}
// 移动端 Drawer 遮罩层样式修复
.mobile-drawer-modal {
z-index: 2000;
}
// 防止移动端 drawer 打开时页面溢出
@media (max-width: 768px) {
body.el-popup-parent--hidden {
position: fixed;
width: 100%;
height: 100%;
}
}

View File

@@ -1,6 +1,8 @@
//需要重写的样式放这里
.elx-xmarkdown-container {
padding: 0 ;
max-width: 100%;
overflow-x: auto;
}
.el-bubble-content p{
margin: 0 !important;
@@ -11,6 +13,9 @@
font-size: 16px !important;
font-weight: 400 !important;
line-height: 28px !important;
max-width: 100%;
overflow-wrap: break-word;
word-break: break-word;
}
.chat-with-id-container{
//待定
@@ -18,7 +23,52 @@
}
.el-bubble-content-wrapper {
--bubble-content-max-width: 800px;
max-width: 100%;
}
.markdown-language-header-div{
z-index: 0 !important;
}
/* 移动端 markdown 优化 */
@media (max-width: 768px) {
.el-bubble-content-wrapper {
--bubble-content-max-width: 100%;
max-width: calc(100vw - 80px);
}
.el-bubble-content {
font-size: 14px !important;
line-height: 24px !important;
padding: 8px !important;
}
.elx-xmarkdown-container {
max-width: 100%;
overflow-x: auto;
}
/* markdown 内容元素优化 */
.markdown-body {
font-size: 14px !important;
pre {
max-width: 100%;
overflow-x: auto;
}
code {
word-break: break-all;
}
table {
display: block;
max-width: 100%;
overflow-x: auto;
}
img {
max-width: 100%;
height: auto;
}
}
}