|
|
@@ -128,8 +128,8 @@
|
|
|
>
|
|
|
<img :src="stopicon" alt="停止" />
|
|
|
</div>
|
|
|
- <button v-if="!conversationInProgress"
|
|
|
- @click="sendMessage">发送</button>
|
|
|
+ <button v-if="!conversationInProgress" class="generate-btn" data-point-cost="需消耗 ✦100积分"
|
|
|
+ aria-label="生成图片,本次需消耗100积分" @click="sendMessage">生成</button>
|
|
|
</div>
|
|
|
</div>
|
|
|
</div>
|
|
|
@@ -138,7 +138,8 @@
|
|
|
|
|
|
<script setup>
|
|
|
import {ref, onMounted, onUnmounted, defineEmits, computed} from 'vue'
|
|
|
-import {AiImageStatusEnum, CreatePainting, PaintingGetMys} from '@/api/questions.js'
|
|
|
+import {AiImageStatusEnum, CreatePainting, PaintingGetMys, getMyAiPointBalance} from '@/api/questions.js'
|
|
|
+import {Message} from '@/utils/message/Message.js'
|
|
|
import demo1 from '@/assets/images/ai-demo/ai-image-demo1.png'
|
|
|
import demo2 from '@/assets/images/ai-demo/ai-image-demo2.png'
|
|
|
import demo3 from '@/assets/images/ai-demo/ai-image-demo3.png'
|
|
|
@@ -280,8 +281,20 @@ const stopStream = async () => {
|
|
|
};
|
|
|
|
|
|
// 发送消息函数
|
|
|
+const ensureAiPoint = async (cost) => {
|
|
|
+ try {
|
|
|
+ const res = await getMyAiPointBalance()
|
|
|
+ if (res.code === 0 && Number(res.data?.balance ?? 0) >= cost) return true
|
|
|
+ Message().error(`当前租户 AI 积分不足,生成图片需要 ${cost} 积分`)
|
|
|
+ } catch (error) {
|
|
|
+ Message().error('暂时无法查询 AI 积分,请稍后重试')
|
|
|
+ }
|
|
|
+ return false
|
|
|
+}
|
|
|
+
|
|
|
const sendMessage = async() => {
|
|
|
if (inputMessage.value.trim()) {
|
|
|
+ if (!await ensureAiPoint(100)) return
|
|
|
// 创建 AbortController 实例,以便中止请求
|
|
|
conversationInAbortController.value = new AbortController();
|
|
|
// 标记对话进行中
|
|
|
@@ -638,4 +651,44 @@ const download = (activeIndex) => {
|
|
|
box-shadow: 0 0px 2px rgba(0, 0, 0, 0.3);
|
|
|
|
|
|
}
|
|
|
-</style>
|
|
|
+
|
|
|
+.input-section .generate-btn {
|
|
|
+ position: relative;
|
|
|
+
|
|
|
+ &::after {
|
|
|
+ position: absolute;
|
|
|
+ z-index: 5;
|
|
|
+ bottom: calc(100% + rpx(5));
|
|
|
+ left: 50%;
|
|
|
+ transform: translateX(-50%) translateY(rpx(2));
|
|
|
+ content: attr(data-point-cost);
|
|
|
+ padding: rpx(4) rpx(6);
|
|
|
+ border-radius: rpx(4);
|
|
|
+ background: rgba(49, 37, 12, 0.92);
|
|
|
+ color: #fff7d8;
|
|
|
+ font-size: rpx(5.5);
|
|
|
+ font-weight: 400;
|
|
|
+ line-height: 1;
|
|
|
+ white-space: nowrap;
|
|
|
+ opacity: 0;
|
|
|
+ pointer-events: none;
|
|
|
+ transition: opacity 0.16s ease, transform 0.16s ease;
|
|
|
+ }
|
|
|
+
|
|
|
+ &::before {
|
|
|
+ position: absolute;
|
|
|
+ z-index: 5;
|
|
|
+ bottom: calc(100% + rpx(1));
|
|
|
+ left: 50%;
|
|
|
+ transform: translateX(-50%);
|
|
|
+ content: '';
|
|
|
+ border: rpx(3) solid transparent;
|
|
|
+ border-top-color: rgba(49, 37, 12, 0.92);
|
|
|
+ opacity: 0;
|
|
|
+ transition: opacity 0.16s ease;
|
|
|
+ }
|
|
|
+
|
|
|
+ &:hover::after, &:focus-visible::after { opacity: 1; transform: translateX(-50%) translateY(0); }
|
|
|
+ &:hover::before, &:focus-visible::before { opacity: 1; }
|
|
|
+}
|
|
|
+</style>
|