flat: 暂存

This commit is contained in:
Apcallover
2025-12-30 15:40:46 +08:00
parent 634610ca7e
commit 6641e07b8a
3 changed files with 582 additions and 723 deletions

View File

@@ -18,6 +18,7 @@
"postinstall": "electron-builder install-app-deps",
"build:unpack": "npm run build && electron-builder --dir",
"build:win": "npm run build && electron-builder --win",
"build:win:x64": "npm run build && electron-builder --win --x64",
"build:mac": "npm run build && electron-builder --mac",
"build:linux": "npm run build && electron-builder --linux"
},

View File

@@ -34,7 +34,7 @@ function createWindow(): void {
mainWindow.show();
});
mainWindow.webContents.openDevTools();
// mainWindow.webContents.openDevTools();
mainWindow.webContents.setWindowOpenHandler((details) => {
shell.openExternal(details.url);

View File

@@ -1,13 +1,15 @@
<template><a-layout class="app-container">
<template>
<a-layout class="app-container">
<a-layout-header class="header">
<a-flex justify="space-between" align="center" style="height: 100%">
<div class="logo-title">
<!-- <WifiOutlined />
直播中台控制系统 -->
<!-- <WifiOutlined v-if="isLiveOn" style="color: #52c41a" /> -->
<!-- 直播中台控制系统 -->
</div>
<a-space :size="20">
<a-badge :dot="isConnected">
<SettingOutlined class="action-icon" />
</a-badge>
<a-avatar size="default" style="background-color: #1677ff">
<template #icon>
<UserOutlined />
@@ -17,334 +19,183 @@
</a-flex>
</a-layout-header>
<a-layout>
<a-layout-sider resizable width="300" :min-width="250" :max-width="500" class="sider">
<div class="sider-top" style="overflow-y: auto;flex: 2;border-bottom: 1px solid #e8e8e8;max-height: calc(100% * 2 / 5);min-height: calc(100% * 2 / 5);">
<a-flex justify="space-between" align="center" style="margin-bottom: 16px">
<a-space align="left" >
<a-typography-title :level="5">
岗位列表
</a-typography-title>
</a-space>
<a-space align="right" >
<a-button type="primary" @click="handleShow" :loading="modelLoading" >
添加岗位
<a-layout class="sub-layout">
<a-layout-sider resizable :width="300" :min-width="250" :max-width="500" class="sider">
<div class="sider-container">
<div class="sider-section top-panel">
<div class="section-header">
<a-typography-title :level="5" style="margin: 0">岗位列表</a-typography-title>
<a-button type="primary" size="small" @click="handleShow" :loading="modelLoading">
<template #icon>
<PlusOutlined />
</template>添加
</a-button>
</a-space>
</a-flex>
<a-list :data-source="positions" item-layout="horizontal">
<template #renderItem="{ item, index }" >
<a-list-item class="position-item" >
<DeleteOutlined title="删除此项" @click.stop="deletedGw(index)"
style="color: #1677ff; margin-right: 5px;margin-bottom: 3px;" />
<a-list-item-meta :title="item.title" @click="setGwDetail(index)" >
</a-list-item-meta>
<RightOutlined @click="sendMessageGwAll(index)" />
</a-list-item>
</template>
</a-list>
<a-divider />
</div>
<div ref="listScrollRef" class="sider-bottom" style="overflow-y: auto;flex: 3;max-height: calc(100% * 3 / 5);">
<a-typography-title :level="5">岗位详情</a-typography-title>
<a-list :data-source="dutyList" item-layout="horizontal">
<div class="section-content">
<a-list :data-source="positions" item-layout="horizontal" size="small">
<template #renderItem="{ item, index }">
<a-list-item @click="resetSayin" :ref="($el) => insertItemList($el)" class="position-item" :class="{ 'highlight-item': index === scrollIndex }">
<h6 class="details-title" v-if="item.length === 5 " >
<StarFilled style="color: #1677ff; margin-left:-20px;margin-right:5px;" />{{ item }}
</h6>
<a-list-item-meta v-else :title="item" >
</a-list-item-meta>
<a-list-item class="position-item" @click="setGwDetail(index)">
<div class="item-main">
<span class="item-title">{{ item.title }}</span>
</div>
<template #actions>
<a-space>
<DeleteOutlined class="delete-btn" @click.stop="deletedGw(index)" />
<RightOutlined class="play-btn" @click.stop="sendMessageGwAll(index)" />
</a-space>
</template>
</a-list-item>
</template>
</a-list>
</div>
</div>
<div class="sider-section bottom-panel">
<div class="section-header sticky-header">
<a-typography-title :level="5" style="margin: 0">岗位详情</a-typography-title>
</div>
<div ref="listScrollRef" class="section-content">
<a-list :data-source="dutyList" item-layout="horizontal" size="small">
<template #renderItem="{ item, index }">
<a-list-item @click="resetSayin" :ref="($el) => insertItemList($el)"
class="detail-item" :class="{ 'highlight-item': index === scrollIndex }">
<div v-if="item.length === 5" class="special-duty">
<StarFilled class="star-icon" />
<span class="bold-text">{{ item }}</span>
</div>
<span v-else class="normal-duty">{{ item }}</span>
</a-list-item>
</template>
</a-list>
<a-empty v-if="dutyList.length === 0" :image="aEmpty.PRESENTED_IMAGE_SIMPLE"
description="暂无详情" />
</div>
</div>
</div>
</a-layout-sider>
<a-layout class="main-content-layout">
<a-layout-content class="content-scroll-area">
<a-card title="直播控制" size="small">
<a-row :gutter="[16, 16]">
<a-col :xs="24" :sm="12" :md="8">
<a-space direction="vertical" size="middle" style="display: flex">
<a-card title="直播控制" size="small" :bordered="false" class="custom-card">
<a-row :gutter="[12, 12]">
<a-col :span="8">
<a-button type="primary" block @click="startLive" :loading="loading || isLiveOn">
<template #icon>
<PlayCircleOutlined />
</template>
开始直播
</template>开始直播
</a-button>
</a-col>
<a-col :xs="24" :sm="12" :md="8">
<a-button type="danger" block @click="stopLive" :loading="loading"
:disabled="!isLiveOn">
<a-col :span="8">
<a-button danger block @click="stopLive" :loading="loading" :disabled="!isLiveOn">
<template #icon>
<StopOutlined />
</template>
结束直播
</template>结束直播
</a-button>
</a-col>
<a-col :xs="24" :sm="12" :md="8">
<a-button block @click="fullScreenInsert" :disabled="!isLiveOn">
<template #icon>
<DesktopOutlined />
</template>
全屏插播
</a-button>
</a-col>
<a-col :xs="24" :sm="12" :md="8">
<a-button block @click="windowInsert" :disabled="!isLiveOn">
<template #icon>
<FullscreenOutlined />
</template>
窗口插播
</a-button>
</a-col>
<a-col :xs="24" :sm="12" :md="8">
<a-button block @click="audioInsert" :disabled="!isLiveOn">
<template #icon>
<HighlightOutlined />
</template>
音频插入
</a-button>
</a-col>
<a-col :xs="24" :sm="12" :md="8">
<a-button block @click="forceClose">
<a-col :span="8">
<a-button danger ghost block @click="forceClose">
<template #icon>
<VideoCameraOutlined />
</template>
强制关闭
</template>强制关闭
</a-button>
</a-col>
<a-col :span="8"><a-button block @click="fullScreenInsert"
:disabled="!isLiveOn">全屏插播</a-button></a-col>
<a-col :span="8"><a-button block @click="windowInsert"
:disabled="!isLiveOn">窗口插播</a-button></a-col>
<a-col :span="8"><a-button block @click="audioInsert"
:disabled="!isLiveOn">音频插入</a-button></a-col>
</a-row>
</a-card>
<a-card title="讲解输出" size="small">
<div class="placeholder-box">
</div>
</a-card>
<a-card title="AI模型管理" size="small">
<a-card title="AI模型管理" size="small" :bordered="false" class="custom-card">
<template #extra>
<a-button type="link" size="small" @click="refreshModelStatus">
<ReloadOutlined />刷新
</a-button>
</template>
<a-flex justify="space-between" align="center" style="margin-bottom: 16px">
<a-space>
<a-typography-text>当前模型:</a-typography-text>
<a-tag :color="modelStatus.exists ? 'green' : 'orange'">
{{ modelStatus.modelName }}
<template v-if="modelStatus.exists">
<CheckCircleOutlined />
</template>
<template v-else>
<ClockCircleOutlined />
</template>
</a-tag>
<a-tag :color="modelStatus.ollamaRunning ? 'green' : 'red'">
{{ modelStatus.ollamaRunning ? 'Ollama运行中' : 'Ollama未运行' }}
</a-tag>
</a-space>
<a-space>
<a-button type="primary" @click="loadModel" :loading="modelLoading"
:disabled="modelLoading">
<template #icon>
<DownloadOutlined />
</template>
{{ modelLoading ? '加载中...' : '加载模型' }}
</a-button>
<a-button @click="refreshModelStatus" :disabled="modelLoading">
<template #icon>
<ReloadOutlined />
</template>
刷新状态
</a-button>
<a-tag :color="modelStatus.exists ? 'green' : 'orange'">{{ modelStatus.modelName
}}</a-tag>
<a-badge :status="modelStatus.ollamaRunning ? 'processing' : 'default'"
:text="modelStatus.ollamaRunning ? 'Ollama运行中' : '服务未就绪'" />
</a-space>
<a-button type="primary" size="small" @click="loadModel"
:loading="modelLoading">加载模型</a-button>
</a-flex>
<!-- 文件拖拽区域 -->
<div class="file-drop-zone" @drop="handleFileDrop" @dragover.prevent @dragenter.prevent
<div class="file-drop-zone" @drop="handleFileDrop" @dragover.prevent
:class="{ 'is-dragging': fileUploadLoading }">
<p class="file-drop-icon">
<InboxOutlined />
</p>
<p class="file-drop-text">拖拽图片拖拽视频文件自动展示</p>
<p class="file-drop-hint">支持图片视频格式</p>
<InboxOutlined class="drop-icon" />
<p class="drop-text">拖拽图片或视频至此处自动展示</p>
</div>
<!-- 已上传文件列表 -->
<div v-if="uploadedFiles.length > 0" class="uploaded-files-list">
<div v-for="(file, index) in uploadedFiles" :key="index" class="file-item">
<div v-if="uploadedFiles.length > 0" class="file-list-container">
<div v-for="(file, index) in uploadedFiles" :key="index" class="file-item-row">
<div class="file-info">
<FileOutlined class="file-icon" />
<span class="file-name">{{ file.name }}</span>
<a-tag :color="getFileTagColor(file.type)" size="small">{{
<FileOutlined /> <span class="file-name">{{ file.name }}</span>
<a-tag size="small" :color="getFileTagColor(file.type)">{{
getFileTypeText(file.type)
}}</a-tag>
</div>
<a-button size="small" danger @click="removeFile(index)">
<template #icon>
<a-button type="text" danger size="small" @click="removeFile(index)">
<DeleteOutlined />
</template>
删除
</a-button>
</div>
</div>
<a-space style="margin-top: 12px;">
<a-button @click="clearAllFiles" :disabled="uploadedFiles.length === 0">
<template #icon>
<DeleteOutlined />
</template>
清空文件
</a-button>
<a-button @click="showFilesInLive" :disabled="uploadedFiles.length === 0 || !isLiveOn">
<template #icon>
<EyeOutlined />
</template>
在直播中展示
</a-button>
<a-space style="margin-top: 12px">
<a-button size="small" @click="clearAllFiles"
:disabled="uploadedFiles.length === 0">清空</a-button>
<a-button size="small" type="primary" ghost @click="showFilesInLive"
:disabled="uploadedFiles.length === 0 || !isLiveOn">在直播中展示</a-button>
</a-space>
</a-card>
</a-space>
</a-layout-content>
<a-layout-footer class="input-footer">
<a-space>
<a-button danger size="small" block @click="polishText('inputValue')" :loading="polishLoading"
:disabled="!inputValue.trim()">
润色
</a-button>
</a-space>
<a-space-compact block style="display: flex; margin-bottom: 8px; margin-top: 8px;">
<a-textarea v-model:value="inputValue" placeholder="输入指令..."
<div class="footer-inner">
<a-flex gap="small" vertical>
<div class="quick-commands">
<span class="label">快捷指令:</span>
<a-button v-for="cmd in ['欢迎新观众', '感谢陪伴', '互动提问', '行业分享']" :key="cmd" size="small"
class="cmd-btn" @click="setQuickCommand(cmd)">{{ cmd }}</a-button>
</div>
<a-space-compact block>
<a-textarea v-model:value="inputValue" placeholder="输入指令或内容..."
:auto-size="{ minRows: 1, maxRows: 3 }" @press-enter="sendMessage" />
<a-button type="primary" @click="sendMessage" :disabled="!isLiveOn">发送</a-button>
<a-button type="primary" @click="sendMessage" :disabled="!isLiveOn"
style="height: auto">发送</a-button>
</a-space-compact>
<a-space>
<a-typography-text type="secondary">快捷指令:</a-typography-text>
<a-button type="dashed" size="small" @click="setQuickCommand('欢迎新观众')">欢迎新观众</a-button>
<a-button type="dashed" size="small" @click="setQuickCommand('感谢大家的陪伴')">感谢陪伴</a-button>
<a-button type="dashed" size="small" @click="setQuickCommand('有什么问题可以随时提问')">互动提问</a-button>
<a-button type="dashed" size="small"
@click="setQuickCommand('今天给大家分享一些有趣的行业资讯')">行业分享</a-button>
</a-space>
<a-button size="small" class="polish-btn" @click="polishText('inputValue')"
:loading="polishLoading">
<RotateRightOutlined /> 智能润色
</a-button>
</a-flex>
</div>
</a-layout-footer>
</a-layout>
</a-layout>
</a-layout>
<!-- 可输入内容的模态框 -->
<a-modal
v-model:open="showModal"
width="800px"
ok-text="提交"
cancel-text="取消"
@ok="handleOk"
@cancel="handleCancel"
:maskClosable="false"
:destroyOnClose="true"
:confirmLoading="confirmLoading"
>
<template #title>
<div class="modal-title-wrapper">
<!-- 标题栏右侧按钮组 -->
<div class="title-button-group">
<a-row>
<a-col :span="10">
<!-- 原标题文字 -->
<a-label style="font-weight: bolder;" >新增岗位信息</a-label>
<!-- 暂时没有其他格式得默认就是text
<a-button
:type="btn1Type"
size="small"
@click="typeChange('btn1')"
style="margin-left:10px;"
>
文本
</a-button>
<a-button
:type="btn2Type"
size="small"
@click="typeChange('btn2')"
style="margin-left:5px;"
>
JSON
</a-button>
-->
</a-col>
<a-col :span="14">
<!-- 在提交得时候自动进行转换 仅保留文字润色功能
<a-button
type="default"
size="small"
@click="transText"
style="margin-left:13px;"
>
转换
</a-button>
-->
<a-button
type="default"
size="small"
@click="polishText('gangwei')"
style="margin-left:5px;"
>
润色
</a-button>
</a-col>
</a-row>
</div>
</div>
</template>
<!-- 表单区域 -->
<a-form
ref="formRef"
:model="formData"
:rules="formRules"
:label-col="{ span: 6 }"
:wrapper-col="{ span: 50 }"
layout="horizontal"
>
<a-row :gutter="16">
<a-col :span="24">
<!-- 单行输入框 -->
<a-form-item label="" name="infoin">
<a-textarea
v-model:value="formData.infoin"
placeholder="请输岗位信息"
:rows="15"
maxlength="2000"
/>
<a-modal v-model:open="showModal" title="新增岗位信息" width="600px" @ok="handleOk">
<a-form ref="formRef" :model="formData" :rules="formRules" layout="vertical">
<a-form-item label="详细信息" name="infoin">
<a-textarea v-model:value="formData.infoin" :rows="10" placeholder="请输入岗位描述,系统将自动切分段落..." />
</a-form-item>
</a-col>
<a-col :span="0">
<div style="width: 375px;height: 340px;overflow-y: scroll;">
<!-- 多行文本框 -->
<div v-for="(item, index) in formData.infoDetail"
:key="index"
>
<textarea style="overflow: hidden;border: none;line-height: 1.1;height: auto;min-height: 10px;outline: none;width: 100%;flex: none;resize: none;margin: 0px;padding: 0px 5px;word-wrap: break-word;word-break: break-all;"
v-model="formData.infoDetail[index]"
readonly="true" class="auto-wrap-textarea" wrap="soft"
/>
</div>
</div>
</a-col>
</a-row>
<a-button size="small" @click="polishText('gangwei')" :loading="polishLoading">
<RotateRightOutlined />润色内容
</a-button>
</a-form>
</a-modal>
</a-layout>
</template>
<script setup>
import { ref, onMounted, onUnmounted, computed, reactive, nextTick, watch } from 'vue';
import { message, Modal, } from 'ant-design-vue';
import { message, Modal, Empty as aEmpty } from 'ant-design-vue';
import SocketClient from '@renderer/utils/socket';
import {
WifiOutlined,
@@ -367,6 +218,8 @@ import {
ClockCircleOutlined,
FileOutlined,
EyeOutlined,
RotateRightOutlined,
PlusOutlined
} from '@ant-design/icons-vue';
import { useUserStore } from '@renderer/stores/useUserStore';
@@ -1012,6 +865,7 @@ const polishTextBackStr = async (_inputStr) => {
// const originalText = _inputStr+123;
// console.log("originalText",originalText)
// return originalText;
const originalText = _inputStr;
try {
console.log('开始润色文本:', originalText);
@@ -1374,239 +1228,243 @@ onMounted(() => {
});
</script>
<style scoped>
/* 根容器:
使用 100vh 充满窗口,并禁止窗口级别滚动。
内部的 <a-layout> 会自动继承这个高度。
*/
<style scoped lang="scss">
/* 布局基座 */
.app-container {
height: 100vh;
overflow: hidden;
/* 关键:禁止最外层滚动 */
}
/* 顶部导航栏 */
.header {
background: #fff;
border-bottom: 1px solid #f0f0f0;
padding: 0 20px;
height: 60px;
/* 缩小顶部栏高度 */
line-height: 60px;
flex-shrink: 0;
/* 防止顶部栏被压缩 */
height: 56px;
line-height: 56px;
z-index: 100;
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.04);
-webkit-app-region: drag;
}
.logo-title {
font-size: 18px;
/* 缩小字体 */
font-weight: 600;
display: flex;
align-items: center;
gap: 8px;
.sub-layout {
height: calc(100vh - 56px);
}
.action-icon {
font-size: 16px;
cursor: pointer;
}
/* 左侧边栏:
- ant-layout-sider 默认有 100% 高度
- 我们需要让 *内部* 的内容可滚动
*/
/* 侧边栏结构优化 */
.sider {
background: #fff;
background: #fff !important;
border-right: 1px solid #f0f0f0;
/* 关键Sider 本身高度 100%
但内部内容可能溢出,所以用一个 wrapper 来滚动
*/
height: 100%;
}
.sider-scroll-content {
height: 100%;
overflow-y: auto;
padding: 16px;
/* 缩小内边距 */
}
.position-item {
padding: 10px 8px;
/* 缩小列表项间距 */
border-radius: 6px;
cursor: pointer;
transition: background-color 0.3s;
}
.position-item:hover {
background-color: #f7f7f7;
}
/* 岗位详情 */
.details-title {
font-size: 14px;
font-weight: 600;
margin-top: 16px;
margin-bottom: 8px;
:deep(.ant-layout-sider-children) {
display: flex;
align-items: center;
flex-direction: column;
}
}
.details-list {
padding-left: 24px;
/* 缩小缩进 */
margin: 0;
color: #555;
line-height: 1.7;
}
/* 右侧主布局:
- 默认就是 flex: 1自动撑满
- 背景色放在这里,而不是 content-scroll-area
*/
.main-content-layout {
background: #f0f2f5;
/* 关键:确保内部的 content 和 footer 垂直排列 */
.sider-container {
display: flex;
flex-direction: column;
height: 100%;
/* 继承父级高度 */
}
/* 右侧可滚动内容区:
- flex: 1: 自动撑满所有可用空间
- overflow-y: auto: 独立滚动
*/
.content-scroll-area {
overflow-y: auto;
padding: 16px;
/* 缩小内边距 */
flex: 1;
/* 关键:撑满除 footer 外的空间 */
.sider-section {
display: flex;
flex-direction: column;
overflow: hidden;
&.top-panel {
flex: 4; // 岗位列表占 40%
border-bottom: 1px solid #f0f0f0;
}
/* 讲解输出占位符 */
.placeholder-box {
min-height: 120px;
/* 缩小高度 */
background: #fafafa;
border: 1px dashed #d9d9d9;
border-radius: 8px;
&.bottom-panel {
flex: 6; // 岗位详情占 60%
background-color: #fafafa;
}
}
/* 底部输入框:
- flex-shrink: 0: 确保不会被压缩
- height: auto: 高度自适应
*/
.input-footer {
background: #fff;
.section-header {
padding: 12px 16px;
/* 缩小内边距 */
border-top: 1px solid #f0f0f0;
box-shadow: 0 -2px 8px rgba(0, 0, 0, 0.05);
height: auto;
/* 关键:高度自适应 */
flex-shrink: 0;
/* 关键:防止被压缩 */
display: flex;
justify-content: space-between;
align-items: center;
background: #fff;
}
/* 文件拖拽区域样式 */
.section-content {
flex: 1;
overflow-y: auto;
padding: 0 12px 12px;
&::-webkit-scrollbar {
width: 4px;
}
&::-webkit-scrollbar-thumb {
background: #e8e8e8;
border-radius: 2px;
}
}
/* 列表项交互样式 */
.position-item {
padding: 8px 12px !important;
border-radius: 6px;
margin-bottom: 4px;
cursor: pointer;
transition: all 0.2s;
border: 1px solid transparent !important;
&:hover {
background-color: #f0f7ff;
border-color: #e6f4ff !important;
}
.play-btn {
color: #1677ff;
&:hover {
opacity: 0.8;
}
}
.delete-btn {
color: #bfbfbf;
&:hover {
color: #ff4d4f;
}
}
}
.detail-item {
padding: 10px 12px !important;
border-radius: 4px;
margin-bottom: 2px;
background: #fff;
border-left: 3px solid transparent !important;
&.highlight-item {
background-color: #e6f4ff !important;
border-left-color: #1677ff !important;
box-shadow: 0 2px 4px rgba(0, 0, 0, 0.05);
}
}
.special-duty {
display: flex;
align-items: center;
color: #1677ff;
.star-icon {
margin-right: 8px;
}
.bold-text {
font-weight: 600;
}
}
/* 主内容与卡片 */
.main-content-layout {
background: #f5f7fa;
}
.content-scroll-area {
padding: 16px;
overflow-y: auto;
}
.custom-card {
border-radius: 8px;
box-shadow: 0 1px 2px rgba(0, 0, 0, 0.03);
:deep(.ant-card-head) {
border-bottom: 1px solid #f0f0f0;
min-height: 40px;
}
}
/* 文件上传区 */
.file-drop-zone {
border: 2px dashed #d9d9d9;
border: 1px dashed #d9d9d9;
border-radius: 8px;
padding: 24px;
text-align: center;
background-color: #fafafa;
transition: all 0.3s ease;
cursor: pointer;
margin-bottom: 16px;
}
background: #fff;
transition: all 0.3s;
.file-drop-zone:hover,
.file-drop-zone.is-dragging {
&.is-dragging,
&:hover {
border-color: #1677ff;
background-color: #f0f8ff;
background: #f0f7ff;
}
.file-drop-icon {
font-size: 48px;
.drop-icon {
font-size: 32px;
color: #1677ff;
margin-bottom: 8px;
}
.file-drop-text {
font-size: 16px;
color: #262626;
margin-bottom: 4px;
font-weight: 500;
}
.file-drop-hint {
font-size: 14px;
.drop-text {
color: #8c8c8c;
margin: 0;
font-size: 13px;
}
}
/* 文件列表样式 */
.uploaded-files-list {
max-height: 200px;
overflow-y: auto;
.file-list-container {
margin-top: 12px;
border: 1px solid #f0f0f0;
border-radius: 6px;
margin-bottom: 12px;
max-height: 150px;
overflow-y: auto;
}
.file-item {
.file-item-row {
display: flex;
justify-content: space-between;
align-items: center;
padding: 8px 12px;
border-bottom: 1px solid #f0f0f0;
}
padding: 6px 12px;
background: #fff;
border-bottom: 1px solid #f9f9f9;
.file-item:last-child {
&:last-child {
border-bottom: none;
}
.file-item:hover {
background-color: #f5f5f5;
}
.file-info {
/* 底部区域 */
.input-footer {
background: #fff;
padding: 12px 20px;
border-top: 1px solid #f0f0f0;
height: auto;
}
.quick-commands {
display: flex;
align-items: center;
flex: 1;
min-width: 0;
gap: 8px;
.label {
color: #8c8c8c;
font-size: 12px;
}
.file-icon {
margin-right: 8px;
color: #1677ff;
flex-shrink: 0;
.cmd-btn {
font-size: 12px;
border-radius: 10px;
background: #f5f5f5;
border: none;
}
}
.file-name {
font-size: 14px;
color: #262626;
margin-right: 8px;
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
flex: 1;
}
.polish-btn {
align-self: flex-start;
color: #722ed1;
border-color: #d3adf7;
/* 确保卡片之间有间距 */
.ant-card {
margin-bottom: 16px;
&:hover {
background: #f9f0ff;
}
/* 新增index=5 时的高亮样式(可根据需求自定义) */
.highlight-item {
background-color: #e6f7ff; /* 浅蓝色背景 */
border-left: 3px solid #1677ff; /* 蓝色左侧边框强调 */
padding-left: 15px !important; /* 调整内边距 */
color: #1677ff; /* 文字变蓝 */
}
</style>