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.

373 lines
7.7 KiB

4 weeks ago
4 weeks ago
4 weeks ago
4 weeks ago
4 weeks ago
4 weeks ago
4 weeks ago
4 weeks ago
4 weeks ago
4 weeks ago
4 weeks ago
4 weeks ago
4 weeks ago
4 weeks ago
4 weeks ago
4 weeks ago
4 weeks ago
4 weeks ago
4 weeks ago
4 weeks ago
4 weeks ago
  1. <template>
  2. <view class="main">
  3. <view class="top" :style="{ height: iSMT + 'px' }"></view>
  4. <!-- 头部导航 -->
  5. <view class="header">
  6. <view class="back-icon">
  7. <image @click="onBack" src="/static/customer-service-platform/cs-platform-back.png"
  8. class="header-icon-image"></image>
  9. </view>
  10. <view class="title">{{ headerTitle }}</view>
  11. <view class="notification-icon">
  12. <image src="/static/customer-service-platform/message.png" class="header-icon-image"></image>
  13. </view>
  14. </view>
  15. <scroll-view scroll-y class="content-container">
  16. <view class="content-header">
  17. <view class="content-header-area">
  18. <view class="logo">
  19. <image mode="aspectFit" src="/static/customer-service-platform/ellipse-dc-img.png"></image>
  20. </view>
  21. <view class="greeting">
  22. <text class="greet-title">我能为你做点什么</text>
  23. <text class="greet-sub">DeepChart随时为您提供服务</text>
  24. </view>
  25. </view>
  26. </view>
  27. <!-- 卡片部分 -->
  28. <view class="card">
  29. <!-- 问题头部-->
  30. <view class="question-header">
  31. <view class="question-row">
  32. <image class="question-avatar" src="/static/customer-service-platform/robot-head.png"
  33. mode="aspectFill"></image>
  34. <view class="question-title">{{ questionTitle }}</view>
  35. </view>
  36. </view>
  37. <!-- 卡片内容区-->
  38. <view class="card-body">
  39. <image class="card-logo" src="/static/customer-service-platform/ellipse-dc-img.png"
  40. mode="aspectFit"></image>
  41. <view class="card-text">
  42. <rich-text :nodes="renderMarkdown(answerContent)"></rich-text>
  43. <!-- <text class="card-paragraph">
  44. {{answerContent}}
  45. </text> -->
  46. </view>
  47. </view>
  48. </view>
  49. <view class="login-row" v-if="showLoginRegister">
  50. <button class="login-btn" @click="toLogin">登录</button>
  51. <button class="register-btn" @click="toRegistration">注册</button>
  52. </view>
  53. </scroll-view>
  54. </view>
  55. </template>
  56. <script>
  57. import {
  58. getAnswerApi
  59. } from "../../api/customerServicePlatform/customerServicePlatform";
  60. import marked from "marked"; // 引入 marked 库
  61. export default {
  62. data() {
  63. return {
  64. headerTitle: '智能客服中台',
  65. iSMT: 0,
  66. questionTitle: '',
  67. answerContent: '正在思考...',
  68. showLoginRegister: false,
  69. };
  70. },
  71. mounted() {
  72. this.iSMT = uni.getSystemInfoSync().statusBarHeight || 0;
  73. this.getAnswerContent()
  74. },
  75. onLoad(options) {
  76. if (options.question) {
  77. this.questionTitle = decodeURIComponent(options.question);
  78. if (this.questionTitle.includes("如何注册")) {
  79. this.showLoginRegister = true
  80. } else {
  81. this.showLoginRegister = false
  82. }
  83. }
  84. },
  85. methods: {
  86. renderMarkdown(content) {
  87. const renderer = new marked.Renderer();
  88. // renderer.heading = function (text, level) {
  89. // return `<p>${text}</p>`;
  90. // };
  91. // 设置 marked 选项
  92. marked.setOptions({
  93. renderer: renderer,
  94. highlight: null, // 如果需要代码高亮,可以设置适当的函数
  95. langPrefix: "language-",
  96. pedantic: false,
  97. gfm: true,
  98. breaks: false,
  99. sanitize: false,
  100. smartLists: true,
  101. smartypants: false,
  102. xhtml: false,
  103. });
  104. if (!content) return "";
  105. let renderedContent = marked.parse(content);
  106. renderedContent = renderedContent.replace(/\*/g, '');
  107. return renderedContent;
  108. },
  109. async getAnswerContent() {
  110. let conversationId = '';
  111. try {
  112. const cache = uni.getStorageSync('conversationId');
  113. if (cache) conversationId = cache;
  114. } catch (e) {
  115. conversationId = '';
  116. }
  117. try {
  118. const res = await getAnswerApi({
  119. question: this.questionTitle,
  120. conversationId: conversationId,
  121. })
  122. console.log(res)
  123. if (res.code == 200) {
  124. uni.setStorageSync('conversationId', res.data.conversationId);
  125. const answer = res.data.answer
  126. // 流式输出逻辑
  127. let currentIndex = 0;
  128. const answerLength = answer.length;
  129. // 每隔一定时间显示一部分内容
  130. this.interval = setInterval(() => {
  131. this.answerContent = answer.slice(0, currentIndex);
  132. currentIndex++;
  133. if (currentIndex > answerLength) {
  134. clearInterval(this.interval);
  135. }
  136. }, Math.floor(Math.random() * (150 - 30 + 1)) + 30);
  137. } else {
  138. this.answerContent = '获取回答失败,请重试';
  139. }
  140. } catch {
  141. this.answerContent = '获取回答失败,请重试';
  142. }
  143. },
  144. sleepTime() {
  145. const ms = Math.floor(Math.random() * (300 - 30 + 1)) + 30;
  146. return ms;
  147. },
  148. toRegistration() {
  149. uni.redirectTo({
  150. url: "/pages/start/Registration/Registration",
  151. });
  152. },
  153. toLogin() {
  154. uni.redirectTo({
  155. url: "/pages/start/login/login",
  156. });
  157. },
  158. onBack() {
  159. if (typeof uni !== 'undefined') uni.navigateBack();
  160. }
  161. }
  162. };
  163. </script>
  164. <style scoped>
  165. .main {
  166. display: flex;
  167. flex-direction: column;
  168. height: 100vh;
  169. background-color: #ffffff;
  170. }
  171. .header {
  172. display: flex;
  173. justify-content: space-between;
  174. align-items: center;
  175. padding: 20rpx 30rpx;
  176. background-color: #ffffff;
  177. }
  178. .title {
  179. color: #000000;
  180. text-align: center;
  181. font-size: 32rpx;
  182. font-weight: 400;
  183. }
  184. .back-icon,
  185. .notification-icon {
  186. width: 40rpx;
  187. display: flex;
  188. align-items: center;
  189. justify-content: center;
  190. }
  191. .header-icon-image {
  192. width: 40rpx;
  193. height: 40rpx;
  194. object-fit: contain;
  195. }
  196. .content-container {
  197. padding: 20rpx;
  198. width: 100%;
  199. box-sizing: border-box;
  200. overflow-x: hidden;
  201. }
  202. .content-header {
  203. display: flex;
  204. align-items: center;
  205. justify-content: center;
  206. gap: 24rpx;
  207. padding: 0 60rpx;
  208. width: 100%;
  209. box-sizing: border-box;
  210. height: 188rpx;
  211. }
  212. .content-header-area {
  213. display: flex;
  214. gap: 20rpx;
  215. }
  216. .logo {
  217. width: 120rpx;
  218. height: 120rpx;
  219. display: flex;
  220. align-items: center;
  221. justify-content: center;
  222. flex: 0 0 112rpx;
  223. }
  224. .greeting {
  225. display: flex;
  226. flex-direction: column;
  227. justify-content: center;
  228. flex: 1 1 auto;
  229. }
  230. .greet-title {
  231. color: #000;
  232. font-size: 40rpx;
  233. font-style: normal;
  234. font-weight: 500;
  235. line-height: normal;
  236. margin: 0;
  237. overflow: hidden;
  238. text-overflow: ellipsis;
  239. white-space: nowrap;
  240. }
  241. .greet-sub {
  242. color: #838383;
  243. font-size: 28rpx;
  244. font-style: normal;
  245. font-weight: 400;
  246. line-height: normal;
  247. margin-top: 12rpx;
  248. overflow: hidden;
  249. text-overflow: ellipsis;
  250. white-space: nowrap;
  251. }
  252. .card {
  253. width: 90%;
  254. margin: 0 auto 20rpx;
  255. padding: 28rpx;
  256. box-sizing: border-box;
  257. border-radius: 16rpx;
  258. border: 4rpx solid #FF7C99;
  259. background: #fff;
  260. }
  261. /* 问题头部 */
  262. .question-header {
  263. width: 100%;
  264. margin-bottom: 48rpx;
  265. }
  266. .question-row {
  267. display: flex;
  268. align-items: center;
  269. }
  270. .question-avatar {
  271. width: 52rpx;
  272. height: 52rpx;
  273. border-radius: 999rpx;
  274. margin-right: 20rpx;
  275. flex-shrink: 0;
  276. }
  277. .question-title {
  278. color: #000000;
  279. font-size: 34rpx;
  280. }
  281. /* 卡片内部布局 */
  282. .card-body {
  283. display: flex;
  284. gap: 20rpx;
  285. align-items: flex-start;
  286. }
  287. .card-logo {
  288. width: 52rpx;
  289. height: 52rpx;
  290. flex: 0 0 52rpx;
  291. border-radius: 8rpx;
  292. }
  293. .card-text {
  294. flex: 1 1 auto;
  295. }
  296. .card-paragraph {
  297. display: block;
  298. color: #000000;
  299. font-size: 28rpx;
  300. margin-bottom: 14rpx;
  301. font-style: normal;
  302. font-weight: 500;
  303. }
  304. .login-row {
  305. display: flex;
  306. justify-content: center;
  307. align-items: center;
  308. width: 100%;
  309. margin-top: 100rpx;
  310. }
  311. .login-btn {
  312. width: 260rpx;
  313. height: 100rpx;
  314. border-radius: 50rpx;
  315. background: #F3F3F3;
  316. color: #000000;
  317. display: flex;
  318. justify-content: center;
  319. align-items: center;
  320. font-size: 28rpx;
  321. margin-right: 20rpx;
  322. }
  323. .register-btn {
  324. width: 260rpx;
  325. height: 100rpx;
  326. border-radius: 60rpx;
  327. background: #000;
  328. color: #ffffff;
  329. display: flex;
  330. justify-content: center;
  331. align-items: center;
  332. font-size: 28rpx;
  333. }
  334. </style>