You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
897 lines
28 KiB
897 lines
28 KiB
<template>
|
|
<view class="container">
|
|
<uni-nav-bar :fontSizes="17" dark left-icon="left" @clickLeft="back" :fixed="true" :border="false"
|
|
background-color="#3E73F5" status-bar title="智能安全检查" />
|
|
<!-- <image class="bg-img" src="https://mp-df79fe8b-b924-41b0-bcb1-960be6b4a619.cdn.bspapp.com/images/ask/content-bg@2x.png" /> -->
|
|
<image class="bg-img" src="https://i.postimg.cc/PxcQrX3C/content-bg-2x.png" />
|
|
<scroll-view class="main-scroll" scroll-y scroll-with-animation lower-threshold="150" ref="chatArea"
|
|
@scroll="handleScroll" @scrolltolower="lower">
|
|
<!-- 猜你想问 -->
|
|
<view class="guess-section">
|
|
<view class="guess-title">常见问题</view>
|
|
<view class="guess-item" v-for="(item, index) in guessList" :key="index" @click="handleGuessClick(item)">
|
|
<text class="question">{{ item.question }}</text>
|
|
<!-- <uni-icons type="right" size="18" color="#999"></uni-icons> -->
|
|
</view>
|
|
</view>
|
|
<!-- 聊天内容区 -->
|
|
<view class="chat-area">
|
|
<view v-for="(msg, idx) in messages" :key="idx">
|
|
<view :class="[msg.role + 's']">
|
|
<view :class="['msg', msg.role]" v-if="msg.role === 'user'">{{ msg.content }}</view>
|
|
<view :class="['msg', msg.role]" v-else v-html="parseMarkdown(msg.content)"></view>
|
|
<!-- 添加按钮,仅对 AI 回答显示 -->
|
|
<view v-if="msg.role === 'assistant'&&userType == 1||msg.role === 'assistant'&&userType == 2" class="add-btn-box">
|
|
<button v-if="!streaming" class="add-btn" @click="toggleAnswer(msg.content, idx)"
|
|
:class="{ 'added': selectedAnswerIds.has(idx) }">
|
|
<!-- <span class="iconfont" :class="selectedAnswerIds.has(index) ? 'icon-jian' : 'icon-jia'"></span> -->
|
|
<uni-icons :type="selectedAnswerIds.has(idx) ? 'trash' : 'plusempty'" size="22"
|
|
color="#fff"></uni-icons>
|
|
</button>
|
|
</view>
|
|
</view>
|
|
<view v-if="streaming && idx == messages.length - 1 && msg.role == 'assistant'" class="dots">
|
|
<view class="dotss"></view>
|
|
<view class="dotss"></view>
|
|
<view class="dotss"></view>
|
|
</view>
|
|
</view>
|
|
<!-- <view v-if="streaming" class="msg assistant">
|
|
<view v-html="parseMarkdown(streamingContent)"></view>
|
|
</view> -->
|
|
</view>
|
|
<view ref="scrollIntoViewId" :id="scrollIntoViewId" style="height: 1px;"></view>
|
|
|
|
</scroll-view>
|
|
<view v-if="selectedAnswers.length > 0" class="save-bar">
|
|
<!-- <div class="save-bar"> -->
|
|
<button class="save-btn" @click="saveAnswers">保存所选回答</button>
|
|
</view>
|
|
|
|
<!-- 底部输入框 -->
|
|
<view class="input-area">
|
|
<input class="chat-input" type="text" v-model="inputValue" :disabled="streaming"
|
|
:placeholder="activeTab === 'suggest' ? '请输入检查内容..' : '请输入你的问题或需求...'" @confirm="sendMessage" />
|
|
<button class="send-btn" @click="sendMessage" :disabled="!inputValue || streaming">
|
|
<!-- <image src="https://mp-df79fe8b-b924-41b0-bcb1-960be6b4a619.cdn.bspapp.com/images/ask/btn@2x.png" /> -->
|
|
<image src="https://i.postimg.cc/RqxF0KQW/btn-2x.png" />
|
|
</button>
|
|
</view>
|
|
</view>
|
|
</template>
|
|
|
|
<script>
|
|
import { marked } from 'marked';
|
|
import * as Api from '@/api/index/index'
|
|
import * as TextEncoding from "text-encoding-shim";
|
|
import store from '@/store'
|
|
let buffer = ''; //定义在页面的最外面。
|
|
let encoder = new TextEncoding.TextDecoder("utf-8");//定义在页面的最外面。
|
|
|
|
export default {
|
|
data() {
|
|
return {
|
|
activeTab: 'suggest',
|
|
random: '',
|
|
questId: 0,
|
|
messages: [],
|
|
inputValue: '',
|
|
selectedAnswers: [],
|
|
selectedAnswerIds: new Set(), // 使用 Set 存储已选答案的 id
|
|
streaming: false,
|
|
streamingContent: '',
|
|
scrollIntoViewId: '',
|
|
autoScroll: true,
|
|
userType: this.$store.state.user.userType,
|
|
tools: [
|
|
{ label: '客流分析', value: 'suggest', icon: '/static/icon_passenger-flow.svg', text: '景区舒适度实时知晓' },
|
|
{ label: '智能助手', value: 'assistant', icon: '/static/icon_assistant.svg', text: '行程规划与导览' },
|
|
],
|
|
guessList: [
|
|
{
|
|
type: 'suggest',
|
|
id: 0,
|
|
question: '游客休息区附近的灭火器随意摆放在地面,多个灭火器铭牌面朝墙壁,其中1具灭火器顶部高于1.6米。'
|
|
}, {
|
|
type: 'suggest',
|
|
id: 1,
|
|
question: '电脑桌下插座超负荷使用,存在多个插排串联现象,电缆未做穿管保护,线路裸露。'
|
|
}, {
|
|
type: 'suggest',
|
|
id: 2,
|
|
question: '安全出口被杂物堵塞,部分疏散指示灯不亮,房间内无疏散图,未张贴疏散方向指示。'
|
|
}, {
|
|
type: 'suggest',
|
|
id: 3,
|
|
question: '场馆未设置专职消防安全管理人员,无消防巡查记录,消火栓箱内设备锈蚀,疏散通道部分设有铁门限制通行。'
|
|
}
|
|
]
|
|
};
|
|
},
|
|
mounted() {
|
|
this.random = Array.from({ length: 12 }, () =>
|
|
'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789'.charAt(
|
|
Math.floor(Math.random() * 62)
|
|
)
|
|
).join('');
|
|
|
|
//获取常见问题
|
|
this.getNoticeList()
|
|
},
|
|
|
|
methods: {
|
|
//常见问题
|
|
getNoticeList() {
|
|
Api.getNoticeList().then(res => {
|
|
const arr = res.data.map(item => {
|
|
return item.status == 0
|
|
}).splice(0, 5)
|
|
console.log(res);
|
|
if (arr.length > 0) {
|
|
this.guessList = arr
|
|
}
|
|
}).catch(err => {
|
|
console.log(err);
|
|
})
|
|
}
|
|
,
|
|
back() {
|
|
uni.navigateBack()
|
|
},
|
|
parseMarkdown(content) {
|
|
return marked.parse(content || '');
|
|
},
|
|
handleScroll(e) {
|
|
const { scrollTop, scrollHeight, clientHeight } = e.detail;
|
|
this.autoScroll = false;
|
|
console.log(this.autoScroll, 'this.autoScroll')
|
|
},
|
|
lower: function (e) {
|
|
console.log(e)
|
|
},
|
|
scrollToBottom() {
|
|
let this_ = this;
|
|
// this.scrollIntoViewId = ''
|
|
if (!this.autoScroll) return;
|
|
this.scrollIntoViewId = 'bottom-anchor-' + Date.now();
|
|
// console.log(this.scrollIntoViewId, 'this.scrollIntoViewId', this.$refs.scrollIntoViewId)
|
|
this.$nextTick(() => {
|
|
uni.pageScrollTo({
|
|
selector: '#' + this.scrollIntoViewId,
|
|
duration: 10,
|
|
complete: () => {
|
|
console.log(this.autoScroll, 'this.autoScroll')
|
|
|
|
}
|
|
})
|
|
})
|
|
// setTimeout(() => {
|
|
// uni.pageScrollTo({
|
|
// selector: '#' + this.scrollIntoViewId,
|
|
// duration: 1000,
|
|
// })
|
|
// }, 1000)
|
|
},
|
|
switchTab(tab) {
|
|
this.activeTab = tab;
|
|
this.messages = [];
|
|
this.inputValue = '';
|
|
this.streaming = false;
|
|
this.streamingContent = '';
|
|
this.scrollToBottom()
|
|
// this.$nextTick(this.scrollToBottom);
|
|
},
|
|
sendMessage() {
|
|
this.autoScroll = true;
|
|
const question = this.inputValue.trim();
|
|
if (!question || this.streaming) return;
|
|
this.messages.push({ role: 'user', content: question });
|
|
this.inputValue = '';
|
|
this.scrollToBottom()
|
|
// this.$nextTick(this.scrollToBottom);
|
|
this.streamAnswer(question);
|
|
},
|
|
parseSSEEvent(rawData) {
|
|
const lines = rawData.split('\n');
|
|
let event = { data: '' };
|
|
|
|
lines.forEach(line => {
|
|
const colonIndex = line.indexOf(':');
|
|
if (colonIndex > 0) {
|
|
const field = line.slice(0, colonIndex).trim();
|
|
const value = line.slice(colonIndex + 1).trim();
|
|
if (field === 'data') {
|
|
event.data += value + '\n';
|
|
} else if (field === 'event') {
|
|
event.type = value;
|
|
} else if (field === 'id') {
|
|
event.id = value;
|
|
} else if (field === 'retry') {
|
|
event.retry = parseInt(value, 10);
|
|
}
|
|
}
|
|
});
|
|
|
|
event.data = event.data.trimEnd(); // 移除末尾换行
|
|
return event.data ? event : null;
|
|
},
|
|
extractAllMarkdownContents(visData) {
|
|
const markdownContents = [];
|
|
try {
|
|
// 使用正则表达式匹配所有 agent-messages 块
|
|
const agentMessagesRegex = /```agent-messages\n\[(.*?)\]\n```/gs;
|
|
let match;
|
|
|
|
while ((match = agentMessagesRegex.exec(visData)) !== null) {
|
|
try {
|
|
// 解析匹配到的 JSON 字符串
|
|
const messageJson = match[1].replace(/\\"/g, '"');
|
|
const messageData = JSON.parse(messageJson);
|
|
|
|
// 只提取 markdown 字段,并在前面加上【隐患描述】标题
|
|
if (messageData.markdown) {
|
|
// 在原始内容前添加【隐患描述】标题
|
|
// const contentWithTitle = `【隐患描述】\n\n${messageData.markdown}`;
|
|
markdownContents.push(messageData.markdown);
|
|
}
|
|
} catch (e) {
|
|
console.log('解析单个 agent-message 失败:', e);
|
|
}
|
|
}
|
|
} catch (e) {
|
|
console.log('解析 agent-messages 失败:', e);
|
|
}
|
|
return markdownContents;
|
|
},
|
|
async streamAnswer(question) {
|
|
this.streaming = true;
|
|
// this.streamingContent = '正在思考中...';
|
|
const msg = { role: 'assistant', content: '正在思考中...' };
|
|
this.messages.push(msg);
|
|
this.scrollToBottom();
|
|
let result = '';
|
|
// 缓存池(半截事件用)
|
|
this.sseBuffer = "";
|
|
|
|
const url = 'http://192.168.130.155:5679/api/v3/user_share_chat_completions'
|
|
+ '?api_key=cjy-778af2cdb2f645ff99493cee58919e9d'
|
|
+ '&app_code=c8360e1c-6d21-11f0-8f29-00e04f309c26'
|
|
+ '&random=' + this.random + '&user_input=' + encodeURIComponent(question);
|
|
|
|
const requestTask = wx.request({
|
|
|
|
url: url,
|
|
|
|
method: "GET",
|
|
|
|
header: {
|
|
|
|
Accept: "text/event-stream",
|
|
|
|
},
|
|
|
|
responseType: "arraybuffer",
|
|
|
|
enableChunked: true,
|
|
|
|
success(res) {
|
|
|
|
console.log("连接成功")
|
|
|
|
},
|
|
|
|
fail(err) {
|
|
|
|
console.error("请求失败:", err)
|
|
|
|
},
|
|
|
|
})
|
|
|
|
requestTask.onChunkReceived(async (res) => {
|
|
try {
|
|
// 将ArrayBuffer转为字符串并追加到缓冲区
|
|
|
|
let arrayBuffer = new Uint8Array(res.data)
|
|
let chunkStr = encoder.decode(arrayBuffer);
|
|
buffer += chunkStr;
|
|
|
|
// 分割完整事件(以\n\n分隔)
|
|
let eventEndIndex;
|
|
while ((eventEndIndex = buffer.indexOf('\n\n')) >= 0) {
|
|
const eventData = buffer.slice(0, eventEndIndex);
|
|
buffer = buffer.slice(eventEndIndex + 2);
|
|
|
|
// 解析SSE事件内容
|
|
const message = this.parseSSEEvent(eventData);
|
|
if (message) {
|
|
console.log('收到事件:', message);
|
|
// 触发自定义事件或更新数据
|
|
//数据拿到后,做自己的业务处理
|
|
const data = message.data.trim(); // 去掉 'data:' 前缀
|
|
|
|
// 检查是否为结束标记
|
|
if (data === '[DONE]') {
|
|
continue;
|
|
}
|
|
|
|
try {
|
|
const jsonData = JSON.parse(data);
|
|
// 提取 vis 字段内容
|
|
if (jsonData.vis && jsonData.vis !== '[DONE]') {
|
|
// 提取 agent-messages 中的 markdown 内容
|
|
const markdownContents = this.extractAllMarkdownContents(jsonData.vis);
|
|
if (markdownContents.length > 0) {
|
|
markdownContents[0] = `【隐患描述】\n\n ${markdownContents[0]} `;
|
|
console.log('markdownContents:', markdownContents);
|
|
|
|
result = markdownContents.join('\n\n'); // 合并所有markdown内容
|
|
msg.content = result;
|
|
this.scrollToBottom();
|
|
}
|
|
} else {
|
|
this.streaming = false;
|
|
}
|
|
} catch (e) {
|
|
console.log('解析JSON失败:', e);
|
|
} finally {
|
|
// this.streaming = false;
|
|
}
|
|
}
|
|
}
|
|
} catch (e) {
|
|
console.error('数据处理异常:', e);
|
|
} finally {
|
|
// this.streaming = false;
|
|
}
|
|
})
|
|
|
|
|
|
|
|
|
|
|
|
},
|
|
reBack(questId) {
|
|
console.log(questId, 'questId')
|
|
switch (questId) {
|
|
case 0:
|
|
return `
|
|
|
|
|
|
**【隐患描述】**:
|
|
游客休息区附近的灭火器随意摆放在地面,多个灭火器铭牌面朝墙壁,其中1具灭火器顶部高于1.6米。
|
|
|
|
**风险判定**:
|
|
存在中度消防安全隐患。
|
|
|
|
**【整改依据】**:
|
|
|
|
1. 《建筑灭火器配置设计规范》GB50140-2005 第5.1.3条:
|
|
> 灭火器的摆放应稳固,其铭牌应朝外。手提式灭火器宜设置在灭火器箱内或挂钩、托架上,其顶部离地面高度不应大于1.50m;底部离地面高度不宜小于0.08m。灭火器箱不得上锁。
|
|
|
|
2. 《中华人民共和国消防法》(2021年修订)第二十八条:
|
|
> 任何单位、个人不得损坏、挪用或者擅自拆除、停用消防设施、器材;不得埋压、圈占、遮挡消火栓或者占用防火间距;不得占用、堵塞、封闭疏散通道、安全出口、消防车通道。
|
|
|
|
**【整改建议】**:
|
|
|
|
- 所有灭火器应重新安装在灭火器箱或墙壁挂钩/托架上;
|
|
- 调整高度符合规范要求(顶部不高于1.50m);
|
|
- 保证铭牌朝外,方便检查与识别。
|
|
|
|
**【隐患等级】**:
|
|
中度风险。
|
|
|
|
`;
|
|
case 1:
|
|
return `
|
|
|
|
|
|
**问题描述**:
|
|
电脑桌下插座超负荷使用,存在多个插排串联现象,电缆未做穿管保护,线路裸露。
|
|
|
|
**风险判定**:
|
|
重大用电安全隐患。
|
|
|
|
**整改依据**:
|
|
|
|
1. 《用电安全导则》GB/T 13869-2017 第5.1.1条:
|
|
> 应禁止电气设备使用中串接插座(插排)进行多台设备连接,防止过载引发火灾。
|
|
|
|
2. 《建筑电气工程施工质量验收规范》GB50303-2015 第5.1.1:
|
|
> 导线敷设应平整,无扭结、无机械损伤,穿越楼板、墙体等处应加套管保护。
|
|
|
|
3. 《中华人民共和国安全生产法》第三十五条:
|
|
> 生产经营单位应当在有较大危险因素的生产经营场所和有关设施、设备上,设置明显的安全警示标志。
|
|
|
|
**整改建议**:
|
|
|
|
- 拆除串联插排,使用定制排插或分路供电;
|
|
- 所有电缆线路穿线管加装防护,避免裸露;
|
|
- 在高风险位置张贴电气警示标志。
|
|
|
|
**风险评级**:
|
|
重大风险。
|
|
|
|
`;
|
|
case 2:
|
|
return `
|
|
|
|
|
|
**问题描述**:
|
|
安全出口被杂物堵塞,部分疏散指示灯不亮,房间内无疏散图,未张贴疏散方向指示。
|
|
|
|
**风险判定**:
|
|
重大人员疏散安全隐患。
|
|
|
|
**整改依据**:
|
|
|
|
1. 《消防应急照明和疏散指示系统技术标准》GB51309-2018 第4.5.10条:
|
|
> 疏散指示标志应设置在通道明显位置,指明疏散方向,应能在火灾断电时自动点亮。
|
|
|
|
2. 《人员密集场所消防安全管理》GB/T 40248-2021 第7.5.2.j条:
|
|
> 宾馆、商场、医院、公共娱乐场所等场所各楼层的明显位置应设置安全疏散指示图,标明疏散路线、安全出口、人员所在位置等。
|
|
|
|
3. 《中华人民共和国消防法》(2021年修订)第二十八条:
|
|
> 不得占用、堵塞、封闭疏散通道、安全出口。
|
|
|
|
**整改建议**:
|
|
|
|
- 清除安全出口周边杂物,保持通畅;
|
|
- 检查疏散照明电源,维修损坏灯具,确保断电可自动亮起;
|
|
- 制作疏散图并张贴在包间门背面及走道显著位置。
|
|
|
|
**风险评级**:
|
|
重大风险。
|
|
|
|
`;
|
|
case 3:
|
|
return `
|
|
|
|
|
|
**问题描述**:
|
|
场馆未设置专职消防安全管理人员,无消防巡查记录,消火栓箱内设备锈蚀,疏散通道部分设有铁门限制通行。
|
|
|
|
**风险判定**:
|
|
制度缺失 + 消防设施老化 + 疏散障碍,构成重大管理风险。
|
|
|
|
**整改依据**:
|
|
|
|
1. 《中华人民共和国消防法》第十六条第二款:
|
|
> 机关、团体、企业、事业等单位应当按照国家标准、行业标准配置消防设施、器材,设置消防安全标志,并定期组织检验、维修,确保完好有效。
|
|
|
|
2. 《河北省安全生产风险管控与隐患治理规定》(省政府2号令)第十五条:
|
|
> 在有较大及以上等级风险的生产经营场所显著位置、关键部位和有关设施设备上应当设置明显警示标志、标识。
|
|
|
|
3. 《消防设施的维护管理》GB25201-2010 第5.2条:
|
|
> 消防设施应每月检查1次,每季度维护保养1次,发现损坏应及时修复。
|
|
|
|
4. 《建筑设计防火规范》GB50016-2014 第6.4.1条:
|
|
> 建筑的疏散通道、安全出口不得设置影响人员疏散的障碍物。
|
|
|
|
**整改建议**:
|
|
|
|
- 指定专人负责消防巡查,建立消防巡检制度并执行记录;
|
|
- 更换损坏消防器材,清理锈蚀水带;
|
|
- 疏散通道去除铁门等障碍物,保持畅通;
|
|
- 在关键部位张贴明显警示标志。
|
|
|
|
**风险评级**:
|
|
重大风险。
|
|
|
|
`;
|
|
default:
|
|
return '';
|
|
}
|
|
},
|
|
mockStreamAnswer(question) {
|
|
this.streaming = true;
|
|
this.streamingContent = '';
|
|
const answer = this.activeTab === 'suggest'
|
|
?
|
|
this.reBack(this.questId)
|
|
: '这是针对“游玩助手”的流式回复内容,模拟逐字输出效果。';
|
|
let i = 0;
|
|
const stream = () => {
|
|
if (i < answer.length) {
|
|
this.streamingContent += answer[i++];
|
|
// this.scrollToBottom()
|
|
this.$nextTick(this.scrollToBottom());
|
|
setTimeout(stream, 10);
|
|
} else {
|
|
this.messages.push({ role: 'assistant', content: this.streamingContent });
|
|
this.streaming = false;
|
|
this.streamingContent = '';
|
|
// this.scrollToBottom()
|
|
this.$nextTick(this.scrollToBottom());
|
|
}
|
|
};
|
|
stream();
|
|
},
|
|
handleGuessClick(question) {
|
|
this.activeTab = question.type;
|
|
this.questId = question.id;
|
|
if (this.streaming) return;
|
|
this.inputValue = '';
|
|
this.messages.push({ role: 'user', content: question.question });
|
|
this.scrollToBottom()
|
|
// this.$nextTick(this.scrollToBottom);
|
|
// this.mockStreamAnswer(question.question);
|
|
this.streamAnswer(question.question);
|
|
},
|
|
|
|
toggleAnswer(content, index) {
|
|
console.log('selectedAnswers:', this.selectedAnswers);
|
|
if (this.selectedAnswerIds.has(index)) {
|
|
// 如果已添加,则移除
|
|
this.selectedAnswerIds.delete(index);
|
|
const removeIndex = this.selectedAnswers.indexOf(content);
|
|
if (removeIndex > -1) {
|
|
this.selectedAnswers.splice(removeIndex, 1);
|
|
}
|
|
} else {
|
|
// 如果未添加,则添加
|
|
this.selectedAnswerIds.add(index);
|
|
// if (!this.selectedAnswers.includes(content)) {
|
|
this.selectedAnswers.push(content);
|
|
// }
|
|
}
|
|
},
|
|
saveAnswers() {
|
|
const data = this.selectedAnswers;
|
|
// const data = ['222', '111'] ;
|
|
// debugger;
|
|
const jsonData = JSON.stringify(data);
|
|
uni.navigateTo({
|
|
url: '/pageIndex/addSafeCheck/addSafeCheck?data=' + encodeURIComponent(jsonData),
|
|
})
|
|
this.selectedAnswers = [];
|
|
this.selectedAnswerIds = new Set();
|
|
|
|
},
|
|
}
|
|
}
|
|
</script>
|
|
<style lang="scss">
|
|
page {
|
|
background-color: #F5F6FB;
|
|
}
|
|
|
|
.container {
|
|
display: flex;
|
|
flex-direction: column;
|
|
width: 100%;
|
|
background: #F5F6FB;
|
|
|
|
.bg-img {
|
|
width: 100%;
|
|
height: 700rpx;
|
|
position: fixed;
|
|
top: 0;
|
|
left: 0;
|
|
}
|
|
|
|
}
|
|
|
|
.main-scroll {
|
|
width: 100%;
|
|
// height: calc(100vh - var(--window-top) - 200rpx);
|
|
flex: 1;
|
|
overflow-y: auto;
|
|
position: relative;
|
|
// z-index: 999;
|
|
margin-bottom: 100rpx;
|
|
}
|
|
|
|
/* 顶部渐变区 */
|
|
.header {
|
|
text-align: center;
|
|
// background: linear-gradient(to bottom, #d8f1ff, #ffffff);
|
|
padding: 60rpx 40rpx 40rpx;
|
|
display: flex;
|
|
flex-direction: column;
|
|
}
|
|
|
|
.avatar {
|
|
width: 100rpx;
|
|
height: 100rpx;
|
|
margin: 0 auto 20rpx;
|
|
border-radius: 50%;
|
|
background: #a0d8ff;
|
|
|
|
image {
|
|
width: 100%;
|
|
height: 100%;
|
|
border-radius: 50%;
|
|
margin-top: 5px;
|
|
}
|
|
}
|
|
|
|
.title {
|
|
font-size: 32rpx;
|
|
font-weight: bold;
|
|
color: #333;
|
|
}
|
|
|
|
.subtitle {
|
|
font-size: 24rpx;
|
|
color: #999;
|
|
margin-top: 10rpx;
|
|
}
|
|
|
|
|
|
.content {
|
|
display: flex;
|
|
flex-direction: column;
|
|
align-items: baseline;
|
|
}
|
|
|
|
.tool-label {
|
|
font-weight: 500;
|
|
font-size: 28rpx;
|
|
color: #1B1B1B;
|
|
}
|
|
|
|
.tool-label-s {
|
|
font-weight: 400;
|
|
font-size: 22rpx;
|
|
color: #9DA9C2;
|
|
}
|
|
|
|
/* 猜你想问 */
|
|
.guess-section {
|
|
background: #fff;
|
|
border-radius: 20rpx;
|
|
margin: 20rpx;
|
|
padding: 0 20rpx 20rpx;
|
|
}
|
|
|
|
.guess-title {
|
|
font-size: 32rpx;
|
|
color: #007aff;
|
|
width: 200rpx;
|
|
height: 68rpx;
|
|
display: flex;
|
|
align-items: center;
|
|
justify-content: start;
|
|
padding-left: 5rpx;
|
|
// background: url('/static/gues.png');
|
|
background-position: center;
|
|
background-size: contain;
|
|
background-repeat: no-repeat;
|
|
padding-top: 20rpx;
|
|
}
|
|
|
|
.guess-item {
|
|
display: flex;
|
|
justify-content: space-between;
|
|
align-items: center;
|
|
padding: 16rpx 0;
|
|
font-size: 28rpx;
|
|
color: #333;
|
|
// padding-left: 40rpx;
|
|
position: relative;
|
|
border-bottom: 1rpx solid #eee;
|
|
margin-top: 10rpx;
|
|
|
|
.question {
|
|
width: 100%;
|
|
overflow: hidden;
|
|
white-space: nowrap;
|
|
text-overflow: ellipsis;
|
|
}
|
|
}
|
|
|
|
.guess-item::before {
|
|
content: '';
|
|
width: 24rpx;
|
|
height: 24rpx;
|
|
// background-color: #eee;
|
|
position: absolute;
|
|
left: 10rpx;
|
|
top: 50%;
|
|
transform: translateY(-50%);
|
|
// background-image: url('/static/start@2x.png');
|
|
background-repeat: no-repeat;
|
|
background-position: center;
|
|
background-size: contain;
|
|
}
|
|
|
|
.guess-item:last-child {
|
|
border-bottom: none;
|
|
}
|
|
|
|
.arrow {
|
|
color: #ccc;
|
|
font-size: 28rpx;
|
|
}
|
|
|
|
/* 聊天气泡 */
|
|
.chat-area {
|
|
flex: 1;
|
|
padding: 20rpx;
|
|
overflow-y: auto;
|
|
// background: #f7f7f7;
|
|
width: unset !important;
|
|
}
|
|
|
|
.msg {
|
|
max-width: 70%;
|
|
padding: 20rpx;
|
|
border-radius: 20rpx;
|
|
margin-bottom: 20rpx;
|
|
font-size: 28rpx;
|
|
word-break: break-word;
|
|
}
|
|
|
|
.msg.user {
|
|
align-self: flex-end;
|
|
background: #007aff;
|
|
color: white;
|
|
}
|
|
|
|
.users {
|
|
display: flex;
|
|
flex-direction: row-reverse;
|
|
}
|
|
|
|
.msg.assistant {
|
|
align-self: flex-start;
|
|
background: #ffffff;
|
|
color: #333;
|
|
box-shadow: 0 2rpx 6rpx rgba(0, 0, 0, 0.1);
|
|
|
|
}
|
|
|
|
.assistants {
|
|
display: flex;
|
|
align-items: flex-start;
|
|
|
|
|
|
}
|
|
|
|
.add-btn-box {
|
|
margin-top: 6px;
|
|
margin-left: 6px;
|
|
}
|
|
|
|
.add-btn {
|
|
background-color: #3e73f5;
|
|
color: #fff;
|
|
border: none;
|
|
padding: 4px 4px;
|
|
border-radius: 6px;
|
|
font-size: 14px;
|
|
display: flex;
|
|
width: 50rpx;
|
|
height: 50rpx;
|
|
align-items: center;
|
|
justify-content: center;
|
|
}
|
|
|
|
.add-btn.added {
|
|
background-color: #ff4d4f;
|
|
}
|
|
|
|
.save-bar {
|
|
position: sticky;
|
|
padding: 8px;
|
|
text-align: center;
|
|
z-index: 10;
|
|
bottom: 100rpx;
|
|
width: 50%;
|
|
margin: 0 auto;
|
|
}
|
|
|
|
.save-btn {
|
|
background-color: #00c092;
|
|
color: #fff;
|
|
border: none;
|
|
padding: 6rpx 16rpx;
|
|
border-radius: 20rpx;
|
|
font-size: 28rpx;
|
|
font-weight: bold;
|
|
}
|
|
|
|
/* 底部输入栏 */
|
|
.input-area {
|
|
display: flex;
|
|
align-items: center;
|
|
padding: 0 5%;
|
|
margin-bottom: 11px;
|
|
position: fixed;
|
|
bottom: 10px;
|
|
z-index: 999;
|
|
width: -webkit-fill-available;
|
|
}
|
|
|
|
.chat-input {
|
|
flex: 1;
|
|
height: 40px;
|
|
border: 1px solid #B0B6C2;
|
|
border-radius: 20px;
|
|
padding: 0 20rpx;
|
|
font-size: 28rpx;
|
|
background: #fafafa;
|
|
}
|
|
|
|
.send-btn {
|
|
width: 56rpx;
|
|
height: 56rpx;
|
|
flex: none;
|
|
margin-left: 16rpx;
|
|
padding: 4rpx;
|
|
line-height: 40px;
|
|
// background: #007aff;
|
|
color: #fff;
|
|
border: none;
|
|
border-radius: 20rpx;
|
|
font-size: 28rpx;
|
|
// background-image: url('/static/icon_AI_bg.svg');
|
|
background-repeat: no-repeat;
|
|
background-position: center;
|
|
background-size: contain;
|
|
display: flex;
|
|
align-items: center;
|
|
justify-content: space-evenly;
|
|
padding-top: 10rpx;
|
|
background-image: linear-gradient(to bottom, #a06bd1, #9779d9, #8f85df, #8990e4, #869be6, #7aa8ee, #70b4f4, #69bff8, #52cffe, #41dfff, #46eefa, #5ffbf1);
|
|
|
|
image {
|
|
width: 32rpx;
|
|
height: 32rpx;
|
|
|
|
}
|
|
|
|
&::after {
|
|
border: none !important;
|
|
}
|
|
}
|
|
|
|
.send-btn:disabled {
|
|
// background-image: url(/static/btn-bg@2x.png);
|
|
// background-repeat: no-repeat;
|
|
// background-position: center;
|
|
// background-size: contain;
|
|
opacity: 0.5;
|
|
}
|
|
|
|
::v-deep .chat-area {
|
|
display: flex;
|
|
flex-direction: column;
|
|
}
|
|
|
|
.dots {
|
|
width: 3.5em;
|
|
display: flex;
|
|
flex-flow: row nowrap;
|
|
align-items: center;
|
|
justify-content: space-between;
|
|
margin: 0.5em 1em;
|
|
}
|
|
|
|
.dots .dotss {
|
|
width: 0.8em;
|
|
height: 0.8em;
|
|
border-radius: 50%;
|
|
background-color: #007aff50;
|
|
animation: fade 0.8s ease-in-out alternate infinite;
|
|
}
|
|
|
|
.dots .dotss:nth-child(2) {
|
|
animation-delay: 0.2s;
|
|
}
|
|
|
|
.dots .dotss:nth-child(3) {
|
|
animation-delay: 0.4s;
|
|
}
|
|
|
|
@keyframes fade {
|
|
from {
|
|
opacity: 1;
|
|
}
|
|
|
|
to {
|
|
opacity: 0;
|
|
}
|
|
}
|
|
</style>
|
|
|