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.

634 lines
13 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
  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" class="header-icon-image"></image>
  8. </view>
  9. <view class="title">{{headerTitle}}</view>
  10. <view class="notification-icon">
  11. <image src="/static/customer-service-platform/message.png" class="header-icon-image"></image>
  12. </view>
  13. </view>
  14. <!-- 内容区域 - 使用滚动视图 -->
  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. <view class="suggest-header">
  30. <text class="suggest-title">猜你想问</text>
  31. <view class="swap" @click="shuffleQuestions">
  32. <image class="swap-icon" src="/static/customer-service-platform/refresh-icon.png"></image>
  33. <text class="swap-title">换一换</text>
  34. </view>
  35. </view>
  36. <view class="card-line"></view>
  37. <view class="suggest-list">
  38. <view class="suggest-item" v-for="(q, idx) in showQuestions" :key="idx"
  39. @click="onQuestionClick(q)">
  40. <view class="left">
  41. <view :class="['num', 'num-' + ((idx % 5) + 1)]">{{ idx + 1 }}</view>
  42. <text class="q-text">{{ q }}</text>
  43. </view>
  44. <view class="right">
  45. <text class="arrow"></text>
  46. </view>
  47. </view>
  48. </view>
  49. </view>
  50. <!--反馈卡片部分-->
  51. <text class="feedback-card-title">反馈中心</text>
  52. <view class="card">
  53. <view class="suggest-header">
  54. <text class="feedback-title">填写反馈内容</text>
  55. </view>
  56. <view class="card-line"></view>
  57. <textarea class="feedback-input" placeholder="请描述您想反馈的内容 最多可输入200字" maxlength="200"
  58. v-model="feedbackText" />
  59. <view class="meta-row">
  60. <text class="char-count">{{ feedbackText.length }}/200</text>
  61. </view>
  62. <view class="suggest-header">
  63. <text class="upload-img-tip">上传图片</text>
  64. </view>
  65. <view class="upload-row">
  66. <view class="img-slot" v-for="(img, index) in images" :key="index">
  67. <image :src="img" mode="scaleToFill" class="slot-img" />
  68. <button v-if="img" class="remove" @click="removeImage(index)">×</button>
  69. </view>
  70. <view class="img-slot" v-if="images.length < 3">
  71. <view class="slot-empty" @click="chooseImage()">
  72. <image src="/static/customer-service-platform/camera.png" class="camera-icon" />
  73. </view>
  74. </view>
  75. <text class="tip-text" v-if="images.length === 0">最多添加3张图片</text>
  76. </view>
  77. <button class="feedback-btn" @click="onSumbitFeedback()">提交</button>
  78. <feedback-modal ref="feedback" @confirm="onConfirm" />
  79. </view>
  80. <!--历史反馈卡片部分-->
  81. <view class="card">
  82. <text class="feedback-title">历史反馈内容</text>
  83. <view class="card-line"></view>
  84. <button class="feedback-btn" @click="viewHistory">查看</button>
  85. </view>
  86. </scroll-view>
  87. </view>
  88. </template>
  89. <script>
  90. import { getQuestion} from "../../api/customerServicePlatform/customerServicePlatform";
  91. import FeedbackModal from '@/components/FeedbackModal.vue'
  92. export default {
  93. components: { FeedbackModal },
  94. data() {
  95. return {
  96. headerTitle: '智能客服中台',
  97. iSMT: 0,
  98. questions: [
  99. "DeepChart 有免费功能和付费功能的区分吗?具体有哪些?",
  100. "如何参与平台的用户反馈活动?反馈的问题会被采纳吗?",
  101. "我的自选股最多能添加多少只?能否按市场分类管理?",
  102. "注册时必须提供手机号 / 邮箱吗?能否匿名使用?",
  103. "忘记登录密码了,如何找回?",
  104. '如何注册账号?',
  105. '为什么无法注册账户?'
  106. ],
  107. showQuestions: [],
  108. feedbackText: '',
  109. images: [],
  110. }
  111. },
  112. mounted() {
  113. // 状态栏高度
  114. this.iSMT = uni.getSystemInfoSync().statusBarHeight;
  115. },
  116. created() {
  117. this.shuffleQuestions();
  118. },
  119. methods: {
  120. onSumbitFeedback(){
  121. this.onSuccess();
  122. },
  123. onSuccess() {
  124. this.$refs.feedback.show({
  125. status: 'success',
  126. title: '提交成功',
  127. subtitle: '— 感谢您的反馈 —',
  128. buttonText: '确定',
  129. width:'80%',
  130. });
  131. },
  132. onFail() {
  133. this.$refs.feedback.show({
  134. status: 'fail',
  135. title: '提交失败',
  136. subtitle: '— 请重新提交 —',
  137. buttonText: '确定',
  138. width:'80%',
  139. });
  140. },
  141. onBack() {
  142. if (typeof uni !== 'undefined') uni.navigateBack();
  143. },
  144. async getQuestionList(){
  145. const res = await getQuestion()
  146. if(res.code == 200){
  147. this.showQuestions =res.data
  148. }
  149. },
  150. shuffleQuestions() {
  151. // 随机取前4条或展示5条
  152. const arr = this.questions.slice();
  153. for (let i = arr.length - 1; i > 0; i--) {
  154. const j = Math.floor(Math.random() * (i + 1));
  155. [arr[i], arr[j]] = [arr[j], arr[i]];
  156. }
  157. this.showQuestions = arr.slice(0, 5);
  158. },
  159. onQuestionClick(q) {
  160. // 可跳转到问答页或直接填入反馈
  161. this.feedbackText = q;
  162. },
  163. chooseImage() {
  164. const that = this;
  165. if (typeof uni === 'undefined' || !uni.chooseImage) return;
  166. const remain = 3 - (that.images ? that.images.length : 0);
  167. if (remain <= 0) {
  168. if (typeof uni !== 'undefined') uni.showToast({
  169. title: '最多只能上传3张',
  170. icon: 'none'
  171. });
  172. return;
  173. }
  174. uni.chooseImage({
  175. count: remain, // 最多选取剩余可上传数量
  176. sizeType: ['original', 'compressed'],
  177. sourceType: ['album', 'camera'],
  178. success(res) {
  179. // res.tempFilePaths 是数组(小程序/APP)
  180. const paths = res.tempFilePaths || (res.tempFiles && res.tempFiles.map(f => f.path)) || [];
  181. // 追加到 images(Vue2 下 push 是响应式的)
  182. for (let p of paths) {
  183. if (that.images.length < 3) {
  184. that.images.push(p);
  185. }
  186. }
  187. // 可选:若要立即上传到服务器,可在这里调用 uni.uploadFile
  188. },
  189. fail(err) {
  190. // 处理取消或失败(不需要提示太多)
  191. // console.log('chooseImage fail', err)
  192. }
  193. });
  194. },
  195. removeImage(index) {
  196. // 删除并保持响应
  197. this.images.splice(index, 1);
  198. },
  199. submit() {
  200. if (!this.feedbackText.trim()) {
  201. if (typeof uni !== 'undefined') uni.showToast({
  202. title: '请填写反馈内容',
  203. icon: 'none'
  204. });
  205. return;
  206. }
  207. // 模拟上传
  208. if (typeof uni !== 'undefined') uni.showLoading({
  209. title: '提交中...'
  210. });
  211. setTimeout(() => {
  212. if (typeof uni !== 'undefined') {
  213. uni.hideLoading();
  214. uni.showToast({
  215. title: '提交成功',
  216. icon: 'success'
  217. });
  218. } else {
  219. console.log('提交数据', {
  220. text: this.feedbackText,
  221. images: this.images
  222. });
  223. }
  224. // 清空
  225. this.feedbackText = '';
  226. this.images = [null, null];
  227. }, 1000);
  228. },
  229. viewHistory() {
  230. // 跳转到历史页
  231. if (typeof uni !== 'undefined') uni.navigateTo({
  232. url: '/pages/customerServicePlatform/questionDetail'
  233. });
  234. }
  235. }
  236. }
  237. </script>
  238. <style scoped>
  239. .main {
  240. display: flex;
  241. flex-direction: column;
  242. height: 100vh;
  243. background-color: #ffffff;
  244. }
  245. .header {
  246. display: flex;
  247. justify-content: space-between;
  248. align-items: center;
  249. padding: 20rpx 30rpx;
  250. background-color: #ffffff;
  251. }
  252. .title {
  253. color: #000000;
  254. text-align: center;
  255. font-size: 32rpx;
  256. font-style: normal;
  257. font-weight: 400;
  258. }
  259. .back-icon,
  260. .notification-icon {
  261. width: 40rpx;
  262. display: flex;
  263. align-items: center;
  264. justify-content: center;
  265. }
  266. .header-icon-image {
  267. width: 40rpx;
  268. height: 40rpx;
  269. object-fit: contain;
  270. }
  271. .content-container {
  272. padding: 20rpx;
  273. width: 100%;
  274. box-sizing: border-box;
  275. overflow-x: hidden;
  276. }
  277. .content-header {
  278. display: flex;
  279. align-items: center;
  280. justify-content: center;
  281. gap: 24rpx;
  282. padding: 0 60rpx;
  283. width: 100%;
  284. box-sizing: border-box;
  285. height: 188rpx;
  286. }
  287. .content-header-area {
  288. display: flex;
  289. gap: 20rpx;
  290. }
  291. .logo {
  292. width: 120rpx;
  293. height: 120rpx;
  294. display: flex;
  295. align-items: center;
  296. justify-content: center;
  297. flex: 0 0 112rpx;
  298. }
  299. .greeting {
  300. display: flex;
  301. flex-direction: column;
  302. justify-content: center;
  303. flex: 1 1 auto;
  304. }
  305. .greet-title {
  306. color: #000;
  307. font-size: 40rpx;
  308. font-style: normal;
  309. font-weight: 500;
  310. line-height: normal;
  311. margin: 0;
  312. overflow: hidden;
  313. text-overflow: ellipsis;
  314. white-space: nowrap;
  315. }
  316. .greet-sub {
  317. color: #838383;
  318. font-size: 28rpx;
  319. font-style: normal;
  320. font-weight: 400;
  321. line-height: normal;
  322. margin-top: 12rpx;
  323. overflow: hidden;
  324. text-overflow: ellipsis;
  325. white-space: nowrap;
  326. }
  327. .card {
  328. width: 90%;
  329. margin: 0 auto;
  330. border-radius: 16rpx;
  331. padding: 20rpx 40rpx;
  332. box-sizing: border-box;
  333. border-radius: 12rpx;
  334. border: 4rpx solid #FCC8D4;
  335. background: linear-gradient(180deg, #FCC8D3 0%, #FEF0F3 30%, #FFF 100%);
  336. margin-bottom: 20rpx;
  337. }
  338. .suggest-header {
  339. width: 100%;
  340. display: flex;
  341. align-items: center;
  342. justify-content: space-between;
  343. }
  344. .suggest-title {
  345. color: #000000;
  346. font-size: 32rpx;
  347. font-style: normal;
  348. font-weight: 400;
  349. line-height: normal;
  350. }
  351. .swap {
  352. display: flex;
  353. align-items: center;
  354. transition: transform 0.1s ease, background-color 0.1s ease;
  355. }
  356. .swap:active {
  357. transform: scale(0.95);
  358. }
  359. .swap-icon {
  360. width: 30rpx;
  361. height: 30rpx;
  362. }
  363. .swap-title {
  364. padding-left: 8rpx;
  365. color: #000000;
  366. font-size: 24rpx;
  367. font-style: normal;
  368. font-weight: 400;
  369. line-height: normal;
  370. }
  371. .suggest-list {
  372. margin-top: 20rpx;
  373. }
  374. .card-line {
  375. margin-top: 20rpx;
  376. width: 100%;
  377. height: 2rpx;
  378. border-radius: 2rpx;
  379. background: #FFF;
  380. }
  381. .suggest-item {
  382. display: flex;
  383. justify-content: space-between;
  384. align-items: center;
  385. padding-top: 10rpx;
  386. border-radius: 12rpx;
  387. margin-bottom: 20rpx;
  388. width: 100%;
  389. box-sizing: border-box;
  390. }
  391. .left {
  392. width: 90%;
  393. display: flex;
  394. align-items: center;
  395. }
  396. .num {
  397. font-size: 40rpx;
  398. font-style: normal;
  399. font-weight: 700;
  400. line-height: normal;
  401. }
  402. .num-1 {
  403. color: #df5662;
  404. }
  405. .num-2 {
  406. color: #ec6d4f;
  407. }
  408. .num-3 {
  409. color: #f3ba40;
  410. }
  411. .num-4 {
  412. color: #9296a0;
  413. }
  414. .num-5 {
  415. color: #9296a0;
  416. }
  417. .q-text {
  418. padding-left: 14rpx;
  419. display: block;
  420. color: #333;
  421. font-size: 28rpx;
  422. white-space: nowrap;
  423. overflow: hidden;
  424. text-overflow: ellipsis;
  425. }
  426. .right {
  427. width: 48rpx;
  428. display: flex;
  429. align-items: center;
  430. justify-content: flex-end;
  431. }
  432. .arrow {
  433. color: #cfcfcf;
  434. font-size: 36rpx;
  435. }
  436. .suggest-item:active {
  437. background: rgba(255, 77, 128, 0.06);
  438. }
  439. .feedback-card-title {
  440. display: flex;
  441. justify-content: center;
  442. color: #000000;
  443. font-size: 32rpx;
  444. font-weight: 700;
  445. line-height: 40rpx;
  446. width: 100%;
  447. margin-bottom: 20rpx;
  448. }
  449. .feedback-title {
  450. color: #000000;
  451. font-size: 32rpx;
  452. font-style: normal;
  453. font-weight: 400;
  454. line-height: normal;
  455. }
  456. .feedback-input {
  457. width: 100%;
  458. display: flex;
  459. padding: 20rpx;
  460. flex-direction: column;
  461. box-sizing: border-box;
  462. align-items: flex-start;
  463. gap: 12rpx;
  464. align-self: stretch;
  465. border-radius: 12rpx;
  466. border: 2rpx solid #F0F1F1;
  467. margin-top: 20rpx;
  468. display: flex;
  469. background: #FFF;
  470. color: #8a8a8a;
  471. font-size: 24rpx;
  472. font-weight: 700;
  473. line-height: normal;
  474. }
  475. .meta-row {
  476. display: flex;
  477. justify-content: flex-end;
  478. margin-top: 12rpx;
  479. }
  480. .char-count {
  481. color: #999
  482. }
  483. .upload-img-tip {
  484. color: #000000;
  485. font-size: 24rpx;
  486. font-style: normal;
  487. font-weight: 400;
  488. line-height: normal;
  489. }
  490. .upload-row {
  491. display: flex;
  492. justify-content: flex-start;
  493. align-items: flex-start;
  494. align-content: flex-start;
  495. flex-wrap: wrap;
  496. gap: 20rpx;
  497. margin-top: 20rpx;
  498. width: 100%;
  499. }
  500. .img-slot {
  501. width: calc((100% - 2 * 30rpx) / 3);
  502. aspect-ratio: 1 / 1;
  503. border-radius: 6px;
  504. border: 1px solid #F0F1F1;
  505. background: #FFF;
  506. position: relative;
  507. display: flex;
  508. align-items: center;
  509. justify-content: center;
  510. overflow: hidden;
  511. transition: transform 0.2s ease;
  512. }
  513. .slot-empty {
  514. width: 100%;
  515. height: 100%;
  516. display: flex;
  517. align-items: center;
  518. justify-content: center;
  519. }
  520. .camera-icon {
  521. width: 34rpx;
  522. height: 34rpx;
  523. }
  524. .slot-img {
  525. width: 100%;
  526. height: 100%;
  527. border-radius: 16rpx;
  528. }
  529. .remove {
  530. position: absolute;
  531. right: 6rpx;
  532. top: 6rpx;
  533. border-radius: 50%;
  534. background: #fd5c58;
  535. padding: 0;
  536. color: #fff;
  537. width: 36rpx;
  538. height: 36rpx;
  539. font-size: 28rpx;
  540. line-height: 36rpx;
  541. text-align: center;
  542. border: none;
  543. outline: none;
  544. cursor: pointer;
  545. }
  546. .remove:active {
  547. background: rgba(0, 0, 0, 0.75);
  548. }
  549. .image-upload-tip {
  550. display: flex;
  551. align-items: center;
  552. }
  553. .tip-text {
  554. color: #999999;
  555. font-size: 24rpx;
  556. font-style: normal;
  557. font-weight: 400;
  558. line-height: 40rpx;
  559. padding-top: 64rpx;
  560. }
  561. .feedback-btn {
  562. margin-top: 24rpx;
  563. width: 180rpx;
  564. height: 60rpx;
  565. aspect-ratio: 89/30;
  566. border-radius: 30rpx;
  567. background: #090A08;
  568. color: #ffffff;
  569. display: flex;
  570. justify-content: center;
  571. align-items: center;
  572. font-size: 32rpx;
  573. font-style: normal;
  574. font-weight: 700;
  575. line-height: normal;
  576. }
  577. </style>