|
@@ -0,0 +1,504 @@
|
|
|
|
|
+<template>
|
|
|
|
|
+ <!-- 图生图 -->
|
|
|
|
|
+ <div class="number-people">
|
|
|
|
|
+ <div class="content-box">
|
|
|
|
|
+ <!-- AI对话框 -->
|
|
|
|
|
+ <div class="chat-dialog">
|
|
|
|
|
+ <!-- 对话消息列表 -->
|
|
|
|
|
+ <div class="message-list">
|
|
|
|
|
+ <div v-if="imageAllList.length > 0">
|
|
|
|
|
+ <div v-for="(item, index) in imageAllList" :key="index">
|
|
|
|
|
+ <!-- 用户消息 -->
|
|
|
|
|
+ <div class="user-message" v-if="item.type === 'user'">
|
|
|
|
|
+ {{ item.content }}
|
|
|
|
|
+ <div class="user-image-list" v-if="item.imageUrl">
|
|
|
|
|
+ <el-image
|
|
|
|
|
+ style="width: fit-content; height: 180px; margin: 10px;"
|
|
|
|
|
+ :src="item.imageUrl"
|
|
|
|
|
+ :preview-src-list="[item.imageUrl]"
|
|
|
|
|
+ fit="cover"
|
|
|
|
|
+ show-progress
|
|
|
|
|
+ >
|
|
|
|
|
+ <template
|
|
|
|
|
+ #toolbar="{ actions, prev, next, reset, activeIndex, setActiveItem }"
|
|
|
|
|
+ >
|
|
|
|
|
+ <el-icon @click="prev"><Back /></el-icon>
|
|
|
|
|
+ <el-icon @click="next"><Right /></el-icon>
|
|
|
|
|
+ <el-icon @click="setActiveItem(item.imageList.length - 1)">
|
|
|
|
|
+ <DArrowRight />
|
|
|
|
|
+ </el-icon>
|
|
|
|
|
+ <el-icon @click="actions('zoomOut')"><ZoomOut /></el-icon>
|
|
|
|
|
+ <el-icon @click="actions('zoomIn', { enableTransition: false, zoomRate: 2 })"><ZoomIn /></el-icon>
|
|
|
|
|
+ <el-icon @click="actions('clockwise', { rotateDeg: 180, enableTransition: false })"><RefreshRight /></el-icon>
|
|
|
|
|
+ <el-icon @click="actions('anticlockwise')"><RefreshLeft /></el-icon>
|
|
|
|
|
+ <el-icon @click="reset"><Refresh /></el-icon>
|
|
|
|
|
+ <el-icon @click="download(activeIndex)"><Download /></el-icon>
|
|
|
|
|
+ </template>
|
|
|
|
|
+ </el-image>
|
|
|
|
|
+ </div>
|
|
|
|
|
+ </div>
|
|
|
|
|
+ <!-- AI生成图片对话框 -->
|
|
|
|
|
+ <div class="ai-message" v-if="item.type !== 'user'">
|
|
|
|
|
+ {{ item.content }}
|
|
|
|
|
+ <span v-if="item.loading" class="loading-dots">
|
|
|
|
|
+ <span class="dot"></span>
|
|
|
|
|
+ <span class="dot"></span>
|
|
|
|
|
+ <span class="dot"></span>
|
|
|
|
|
+ </span>
|
|
|
|
|
+ <div class="image-list" v-if="item.imageList">
|
|
|
|
|
+ <el-image
|
|
|
|
|
+ v-for="(image, index) in item.imageList"
|
|
|
|
|
+ :key="index"
|
|
|
|
|
+ style=" width: fit-content; height: 220px; margin: 10px;"
|
|
|
|
|
+ :src="image"
|
|
|
|
|
+ :preview-src-list="item.imageList"
|
|
|
|
|
+ fit="cover"
|
|
|
|
|
+ show-progress
|
|
|
|
|
+ >
|
|
|
|
|
+ <template
|
|
|
|
|
+ #toolbar="{ actions, reset, activeIndex}"
|
|
|
|
|
+ >
|
|
|
|
|
+ <el-icon @click="actions('zoomOut')"><ZoomOut /></el-icon>
|
|
|
|
|
+ <el-icon
|
|
|
|
|
+ @click="actions('zoomIn', { enableTransition: false, zoomRate: 2 })">
|
|
|
|
|
+ <ZoomIn />
|
|
|
|
|
+ </el-icon>
|
|
|
|
|
+ <el-icon
|
|
|
|
|
+ @click="actions('clockwise', { rotateDeg: 180, enableTransition: false })">
|
|
|
|
|
+ <RefreshRight />
|
|
|
|
|
+ </el-icon>
|
|
|
|
|
+ <el-icon @click="actions('anticlockwise')"><RefreshLeft /></el-icon>
|
|
|
|
|
+ <el-icon @click="reset"><Refresh /></el-icon>
|
|
|
|
|
+ <el-icon @click="download(activeIndex)"><Download /></el-icon>
|
|
|
|
|
+ </template>
|
|
|
|
|
+ </el-image>
|
|
|
|
|
+ </div>
|
|
|
|
|
+ </div>
|
|
|
|
|
+ </div>
|
|
|
|
|
+ </div>
|
|
|
|
|
+ </div>
|
|
|
|
|
+
|
|
|
|
|
+ <!-- 发送按钮 -->
|
|
|
|
|
+ <div class="input-section">
|
|
|
|
|
+ <!-- 参考图 -->
|
|
|
|
|
+ <ImageUpload v-model="uploadedImage" ref="imageUploadRef"/>
|
|
|
|
|
+ <!-- 终止按钮 -->
|
|
|
|
|
+ <div
|
|
|
|
|
+ v-if="conversationInProgress"
|
|
|
|
|
+ @click="stopStream"
|
|
|
|
|
+ class="stop-btn"
|
|
|
|
|
+ title="终止问答"
|
|
|
|
|
+ >
|
|
|
|
|
+ <img :src="stopicon" alt="停止" />
|
|
|
|
|
+ </div>
|
|
|
|
|
+ <button v-if="!conversationInProgress"
|
|
|
|
|
+ @click="sendMessage">发送</button>
|
|
|
|
|
+ </div>
|
|
|
|
|
+ </div>
|
|
|
|
|
+ </div>
|
|
|
|
|
+ </div>
|
|
|
|
|
+</template>
|
|
|
|
|
+
|
|
|
|
|
+<script setup>
|
|
|
|
|
+import { ref, onMounted,onUnmounted} from 'vue'
|
|
|
|
|
+import {AiImageStatusEnum, CreatePainting, PaintingGetMys} from '@/api/questions.js'
|
|
|
|
|
+import { useRouter, useRoute } from 'vue-router'
|
|
|
|
|
+import {
|
|
|
|
|
+ Document,
|
|
|
|
|
+ Menu as IconMenu,
|
|
|
|
|
+ Location,
|
|
|
|
|
+ Setting,
|
|
|
|
|
+ ArrowLeftBold,
|
|
|
|
|
+ Fold,
|
|
|
|
|
+ Expand,
|
|
|
|
|
+ ChatLineRound,
|
|
|
|
|
+ Picture,
|
|
|
|
|
+ MagicStick,
|
|
|
|
|
+ Tickets,
|
|
|
|
|
+ User
|
|
|
|
|
+} from '@element-plus/icons-vue'
|
|
|
|
|
+
|
|
|
|
|
+import { saveRecord } from '@/api/personalized/index.js'
|
|
|
|
|
+
|
|
|
|
|
+// 导入全局状态
|
|
|
|
|
+import { globalState } from '@/utils/globalState.js'
|
|
|
|
|
+// 终止按钮
|
|
|
|
|
+import stopicon from "@/assets/icon/stopicon.png";
|
|
|
|
|
+// 消息组件
|
|
|
|
|
+import {Message} from "@/utils/message/Message.js";
|
|
|
|
|
+
|
|
|
|
|
+// 上传参考图
|
|
|
|
|
+import ImageUpload from '@/components/ImageUpload/index.vue';
|
|
|
|
|
+
|
|
|
|
|
+// 导入接口
|
|
|
|
|
+import { getModelIdByType } from '@/api/teachers.js'
|
|
|
|
|
+import { ModelTypeEnum } from '@/api/teachers.js'
|
|
|
|
|
+
|
|
|
|
|
+// 存储上传的图片
|
|
|
|
|
+const uploadedImage = ref('');
|
|
|
|
|
+
|
|
|
|
|
+const imageUploadRef = ref(null);
|
|
|
|
|
+
|
|
|
|
|
+
|
|
|
|
|
+// 对话状态变量
|
|
|
|
|
+const conversationInProgress = ref(false); // 对话是否正在进行中
|
|
|
|
|
+const conversationInAbortController = ref(); // 对话进行中 abort 控制器
|
|
|
|
|
+
|
|
|
|
|
+// tts 语音
|
|
|
|
|
+import { useAudioPlayer } from '@/api/tts/useAudioPlayer';
|
|
|
|
|
+
|
|
|
|
|
+// 添加抽屉显示状态
|
|
|
|
|
+const drawerVisible = ref(true)
|
|
|
|
|
+
|
|
|
|
|
+ // 年级ID相关
|
|
|
|
|
+const gradeId = ref('')
|
|
|
|
|
+// 添加消息计数器变量
|
|
|
|
|
+const messageCount = ref(0)
|
|
|
|
|
+// modelId响应式变量
|
|
|
|
|
+const modelId = ref(0)
|
|
|
|
|
+// 保存记录
|
|
|
|
|
+onMounted(async () => {
|
|
|
|
|
+ // 从全局状态初始化年级ID
|
|
|
|
|
+ gradeId.value = globalState.initGradeId()
|
|
|
|
|
+ try{
|
|
|
|
|
+ const res = await saveRecord({
|
|
|
|
|
+ brpNjId: gradeId.value,
|
|
|
|
|
+ brpType: "aiCount",
|
|
|
|
|
+ brpProgress: 1
|
|
|
|
|
+ });
|
|
|
|
|
+ // 获取modelId
|
|
|
|
|
+ const modelRes = await getModelIdByType({ type: ModelTypeEnum.IMAGE_TO_IMAGE, platform: "DouBao" })
|
|
|
|
|
+ modelId.value = modelRes.data
|
|
|
|
|
+ }catch(error){
|
|
|
|
|
+ console.error('保存记录失败:', error);
|
|
|
|
|
+ }
|
|
|
|
|
+});
|
|
|
|
|
+
|
|
|
|
|
+// 停止操作函数
|
|
|
|
|
+const stopStream = async () => {
|
|
|
|
|
+ // tip:如果 stream 进行中的 message,就需要调用 controller 结束
|
|
|
|
|
+ if (conversationInAbortController.value) {
|
|
|
|
|
+ conversationInAbortController.value.abort();
|
|
|
|
|
+ }
|
|
|
|
|
+ // 设置为 false
|
|
|
|
|
+ conversationInProgress.value = false;
|
|
|
|
|
+};
|
|
|
|
|
+
|
|
|
|
|
+// 发送消息函数,图片数据
|
|
|
|
|
+const sendMessage = async() => {
|
|
|
|
|
+ if (uploadedImage.value) {
|
|
|
|
|
+ // 创建 AbortController 实例,以便中止请求
|
|
|
|
|
+ conversationInAbortController.value = new AbortController();
|
|
|
|
|
+ // 标记对话进行中
|
|
|
|
|
+ conversationInProgress.value = true;
|
|
|
|
|
+
|
|
|
|
|
+ // 创建用户消息对象,包含图片
|
|
|
|
|
+ const userMessage = {
|
|
|
|
|
+ type: 'user',
|
|
|
|
|
+ content: '', // 删除了inputMessage内容
|
|
|
|
|
+ };
|
|
|
|
|
+
|
|
|
|
|
+ // 添加上传的图片到用户消息中
|
|
|
|
|
+ userMessage.imageUrl = uploadedImage.value;
|
|
|
|
|
+
|
|
|
|
|
+ imageAllList.value.push(userMessage);
|
|
|
|
|
+ imageAllList.value.push({
|
|
|
|
|
+ type: 'ai',
|
|
|
|
|
+ content: "正在为您生成图片,请稍等",
|
|
|
|
|
+ loading: true
|
|
|
|
|
+ })
|
|
|
|
|
+
|
|
|
|
|
+ // 递增消息计数器
|
|
|
|
|
+ messageCount.value++
|
|
|
|
|
+ // 发送saveRecord请求 保存消息次数
|
|
|
|
|
+ try{
|
|
|
|
|
+ await saveRecord({
|
|
|
|
|
+ brpNjId: gradeId.value,
|
|
|
|
|
+ brpType: "aiCount",
|
|
|
|
|
+ brpProgress: messageCount.value
|
|
|
|
|
+ });
|
|
|
|
|
+ console.log('保存记录成功,消息次数:', messageCount.value);
|
|
|
|
|
+ }catch(error){
|
|
|
|
|
+ console.error('保存记录失败:', error);
|
|
|
|
|
+ conversationInProgress.value = false;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ try {
|
|
|
|
|
+ CreatePainting({
|
|
|
|
|
+ "modelId": modelId.value,
|
|
|
|
|
+ "prompt":'',
|
|
|
|
|
+ "width":1024,
|
|
|
|
|
+ "height":1024,
|
|
|
|
|
+ "promptImage":uploadedImage.value
|
|
|
|
|
+ }).then(res=>{
|
|
|
|
|
+ console.log("生成图片",res)
|
|
|
|
|
+ //目前写死调用已生成的图片,全部通了后再改
|
|
|
|
|
+ inProgressImageMap.value[res.data] = {id:res.data,status:AiImageStatusEnum.IN_PROGRESS}
|
|
|
|
|
+ // inProgressImageMap.value[260] = {id:260,status:AiImageStatusEnum.IN_PROGRESS}
|
|
|
|
|
+ }).finally(() => {
|
|
|
|
|
+ // 图片生成请求完成后更新状态
|
|
|
|
|
+ conversationInProgress.value = false;
|
|
|
|
|
+ });
|
|
|
|
|
+ } catch (error) {
|
|
|
|
|
+ console.error('生成图片失败:', error);
|
|
|
|
|
+ conversationInProgress.value = false;
|
|
|
|
|
+ }
|
|
|
|
|
+ } else {
|
|
|
|
|
+ // 如果没有上传图片,显示提示信息
|
|
|
|
|
+ Message().error('请先上传参考图!', true);
|
|
|
|
|
+ }
|
|
|
|
|
+ // 调用子组件的方法清除预览图
|
|
|
|
|
+ imageUploadRef.value?.clearPreview();
|
|
|
|
|
+};
|
|
|
|
|
+
|
|
|
|
|
+
|
|
|
|
|
+// 生成图片
|
|
|
|
|
+import { ElIcon } from 'element-plus'
|
|
|
|
|
+import {
|
|
|
|
|
+ Back,
|
|
|
|
|
+ DArrowRight,
|
|
|
|
|
+ Download,
|
|
|
|
|
+ Refresh,
|
|
|
|
|
+ RefreshLeft,
|
|
|
|
|
+ RefreshRight,
|
|
|
|
|
+ Right,
|
|
|
|
|
+ ZoomIn,
|
|
|
|
|
+ ZoomOut,
|
|
|
|
|
+} from '@element-plus/icons-vue'
|
|
|
|
|
+
|
|
|
|
|
+
|
|
|
|
|
+const imageAllList = ref([]) // 对话的消息列表
|
|
|
|
|
+// 图片轮询相关的参数(正在生成中的)
|
|
|
|
|
+const inProgressImageMap = ref({}) // 监听的 image 映射,一般是生成中(需要轮询),key 为 image 编号,value 为 image
|
|
|
|
|
+const inProgressTimer = ref() // 生成中的 image 定时器,轮询生成进展
|
|
|
|
|
+
|
|
|
|
|
+
|
|
|
|
|
+/** 轮询生成中的 image 列表 */
|
|
|
|
|
+const refreshWatchImages = async () => {
|
|
|
|
|
+ const imageIds = Object.keys(inProgressImageMap.value).map(Number)
|
|
|
|
|
+ if (imageIds.length === 0) {
|
|
|
|
|
+ return
|
|
|
|
|
+ }
|
|
|
|
|
+ const list = await PaintingGetMys(imageIds)
|
|
|
|
|
+ const newWatchImages = {}
|
|
|
|
|
+ list.data.forEach((image) => {
|
|
|
|
|
+
|
|
|
|
|
+ if (image.status === AiImageStatusEnum.IN_PROGRESS) {
|
|
|
|
|
+ newWatchImages[image.id] = image
|
|
|
|
|
+ } else {
|
|
|
|
|
+ imageAllList.value.pop();
|
|
|
|
|
+ console.log('AI生成的图片地址:', image.picUrl);
|
|
|
|
|
+ imageAllList.value.push({
|
|
|
|
|
+ type: 'ai',
|
|
|
|
|
+ content: "已为您生成图片:",
|
|
|
|
|
+ imageList: [image.picUrl],
|
|
|
|
|
+ })
|
|
|
|
|
+ }
|
|
|
|
|
+ })
|
|
|
|
|
+ inProgressImageMap.value = newWatchImages
|
|
|
|
|
+ if (newWatchImages.size === 0) {
|
|
|
|
|
+ inProgressTimerFun()
|
|
|
|
|
+ }
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+
|
|
|
|
|
+/** 组件挂在的时候 */
|
|
|
|
|
+onMounted(async () => {
|
|
|
|
|
+ refreshWatchImagesFun()
|
|
|
|
|
+})
|
|
|
|
|
+
|
|
|
|
|
+/** 组件取消挂在的时候 */
|
|
|
|
|
+onUnmounted(async () => {
|
|
|
|
|
+ inProgressTimerFun()
|
|
|
|
|
+})
|
|
|
|
|
+
|
|
|
|
|
+// 自动刷新 image 列表
|
|
|
|
|
+const refreshWatchImagesFun = () => {
|
|
|
|
|
+ inProgressTimer.value = setInterval(async () => {
|
|
|
|
|
+ await refreshWatchImages()
|
|
|
|
|
+ }, 1000 * 3)
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+// 停止刷新image列表
|
|
|
|
|
+const inProgressTimerFun = () => {
|
|
|
|
|
+ if (inProgressTimer.value) {
|
|
|
|
|
+ clearInterval(inProgressTimer.value)
|
|
|
|
|
+ }
|
|
|
|
|
+}
|
|
|
|
|
+</script>
|
|
|
|
|
+
|
|
|
|
|
+<style scoped lang="scss">
|
|
|
|
|
+@use 'sass:math';
|
|
|
|
|
+// 定义rpx转换函数
|
|
|
|
|
+@function rpx($px) {
|
|
|
|
|
+ @return math.div($px, 750) * 100vw;
|
|
|
|
|
+}
|
|
|
|
|
+// 用户图片列表样式
|
|
|
|
|
+.user-image-list {
|
|
|
|
|
+ display: flex;
|
|
|
|
|
+ flex-wrap: wrap;
|
|
|
|
|
+ margin-top: rpx(5);
|
|
|
|
|
+}
|
|
|
|
|
+.number-people {
|
|
|
|
|
+ flex: 1;
|
|
|
|
|
+ height: 100%;
|
|
|
|
|
+ display: flex;
|
|
|
|
|
+ background-color: #ece9fd;
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+.content-box {
|
|
|
|
|
+ flex: 1;
|
|
|
|
|
+ // margin-top: rpx(10);
|
|
|
|
|
+ // margin-bottom: rpx(10);
|
|
|
|
|
+ margin: rpx(7);
|
|
|
|
|
+ border-radius: rpx(15);
|
|
|
|
|
+ background: rgba($color: #ffffff, $alpha: 0.5);
|
|
|
|
|
+ overflow-y: auto;
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+// 对话框
|
|
|
|
|
+.chat-dialog {
|
|
|
|
|
+ display: flex;
|
|
|
|
|
+ flex-direction: column;
|
|
|
|
|
+ height: 100%;
|
|
|
|
|
+}
|
|
|
|
|
+.message-list {
|
|
|
|
|
+ flex: 1;
|
|
|
|
|
+ overflow-y: auto;
|
|
|
|
|
+ padding: rpx(15);
|
|
|
|
|
+}
|
|
|
|
|
+/* 自定义滚动条样式 */
|
|
|
|
|
+.message-list::-webkit-scrollbar {
|
|
|
|
|
+ width: rpx(2); /* 滚动条宽度 */
|
|
|
|
|
+}
|
|
|
|
|
+.message-list::-webkit-scrollbar-track {
|
|
|
|
|
+ background: #f1effd; /* 滚动条轨道背景色 */
|
|
|
|
|
+ border-radius: rpx(4);
|
|
|
|
|
+}
|
|
|
|
|
+.message-list::-webkit-scrollbar-thumb {
|
|
|
|
|
+ background: #e2ddfc; /* 滚动条滑块颜色 */
|
|
|
|
|
+ border-radius: rpx(4);
|
|
|
|
|
+}
|
|
|
|
|
+.message-list::-webkit-scrollbar-thumb:hover {
|
|
|
|
|
+ background: #e2ddfc; /* 滚动条滑块 hover 状态颜色 */
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+.message-list .user-message {
|
|
|
|
|
+ background-color: #ffffff;
|
|
|
|
|
+ margin-left: auto; // 消息靠右显示
|
|
|
|
|
+ margin-right: 0; // 重置右边距
|
|
|
|
|
+ max-width: rpx(400);
|
|
|
|
|
+ font-size: rpx(8);
|
|
|
|
|
+ width: fit-content; // 宽度随文字内容变化
|
|
|
|
|
+ border-radius: rpx(5);
|
|
|
|
|
+ padding: rpx(5);
|
|
|
|
|
+ text-align: left; // 文字左对齐
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+.message-list .ai-message {
|
|
|
|
|
+ background-color: #ffdd55;
|
|
|
|
|
+ margin-left: 0; // 消息靠左显示
|
|
|
|
|
+ margin-right: auto; // 重置右边距
|
|
|
|
|
+ margin-bottom: rpx(10);
|
|
|
|
|
+ width: fit-content;
|
|
|
|
|
+ max-width: rpx(400);
|
|
|
|
|
+ padding: rpx(5);
|
|
|
|
|
+ font-size: rpx(8);
|
|
|
|
|
+ border-radius: rpx(5);
|
|
|
|
|
+ text-align: left; // 文字左对齐
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+// 加载动画效果
|
|
|
|
|
+.loading-dots {
|
|
|
|
|
+ display: inline-block;
|
|
|
|
|
+ margin-left: rpx(5);
|
|
|
|
|
+}
|
|
|
|
|
+.loading-dots .dot {
|
|
|
|
|
+ display: inline-block;
|
|
|
|
|
+ width: rpx(3);
|
|
|
|
|
+ height: rpx(3);
|
|
|
|
|
+ border-radius: 50%;
|
|
|
|
|
+ background-color: #333;
|
|
|
|
|
+ margin: 0 rpx(1);
|
|
|
|
|
+ animation: loading-dot 1.4s infinite ease-in-out both;
|
|
|
|
|
+}
|
|
|
|
|
+.loading-dots .dot:nth-child(1) {
|
|
|
|
|
+ animation-delay: -0.32s;
|
|
|
|
|
+}
|
|
|
|
|
+.loading-dots .dot:nth-child(2) {
|
|
|
|
|
+ animation-delay: -0.16s;
|
|
|
|
|
+}
|
|
|
|
|
+@keyframes loading-dot {
|
|
|
|
|
+ 0%, 80%, 100% {
|
|
|
|
|
+ transform: scale(0);
|
|
|
|
|
+ }
|
|
|
|
|
+ 40% {
|
|
|
|
|
+ transform: scale(1);
|
|
|
|
|
+ }
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+.image-list {
|
|
|
|
|
+ display: flex;
|
|
|
|
|
+ flex-wrap: wrap;
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+
|
|
|
|
|
+.content-demo {
|
|
|
|
|
+ background-color: #f4f2fa;
|
|
|
|
|
+ border-radius: 15px;
|
|
|
|
|
+ padding: 30px 10px;
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+.input-section {
|
|
|
|
|
+ display: flex;
|
|
|
|
|
+ justify-content: space-between;
|
|
|
|
|
+ align-items: center;
|
|
|
|
|
+ padding: rpx(10);
|
|
|
|
|
+ gap: rpx(5);
|
|
|
|
|
+
|
|
|
|
|
+ .left-section {
|
|
|
|
|
+ flex: 1;
|
|
|
|
|
+ display: flex;
|
|
|
|
|
+ justify-content: flex-start;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ .right-section {
|
|
|
|
|
+ display: flex;
|
|
|
|
|
+ align-items: center;
|
|
|
|
|
+ gap: rpx(10);
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ // 终止按钮样式
|
|
|
|
|
+ .stop-btn {
|
|
|
|
|
+ cursor: pointer;
|
|
|
|
|
+ display: flex;
|
|
|
|
|
+ align-items: center;
|
|
|
|
|
+ img {
|
|
|
|
|
+ width: rpx(20);
|
|
|
|
|
+ height: rpx(20);
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+}
|
|
|
|
|
+.input-section button {
|
|
|
|
|
+ padding: rpx(5) rpx(15);
|
|
|
|
|
+ background: linear-gradient(
|
|
|
|
|
+ to bottom,
|
|
|
|
|
+ #fee78a,
|
|
|
|
|
+ #ffce1b
|
|
|
|
|
+ ); /* 设置悬停、聚焦、点击状态下的背景色 */
|
|
|
|
|
+ color: black;
|
|
|
|
|
+ border: none;
|
|
|
|
|
+ font-size: rpx(7);
|
|
|
|
|
+ border-radius: rpx(5);
|
|
|
|
|
+ cursor: pointer;
|
|
|
|
|
+ box-shadow: 0 0px 2px rgba(0, 0, 0, 0.3);
|
|
|
|
|
+
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+.image-upload-section {
|
|
|
|
|
+ padding: rpx(10);
|
|
|
|
|
+ display: flex;
|
|
|
|
|
+ justify-content: center;
|
|
|
|
|
+ align-items: center;
|
|
|
|
|
+}
|
|
|
|
|
+</style>
|