Browse Source

智能客服中台页面搭建

zhaowenkang/feature-20251028181547-行情页面
maziyang 4 weeks ago
parent
commit
9d9d8a906b
  1. 3
      .hbuilderx/launch.json
  2. 2
      components/footerBar.vue
  3. 19
      pages.json
  4. 627
      pages/customerServicePlatform/csPlatformIndex.vue
  5. 342
      pages/customerServicePlatform/historyRecord.vue
  6. 8
      pages/home/home.vue
  7. BIN
      static/customer-service-platform/a1.png
  8. BIN
      static/customer-service-platform/a2.jpg
  9. BIN
      static/customer-service-platform/camera.png
  10. BIN
      static/customer-service-platform/cs-platform-back.png
  11. BIN
      static/customer-service-platform/ellipse-dc-img.png
  12. BIN
      static/customer-service-platform/empty-content.png
  13. BIN
      static/customer-service-platform/message.png
  14. BIN
      static/customer-service-platform/refresh-icon.png
  15. BIN
      static/customer-service-platform/smile-icon.png

3
.hbuilderx/launch.json

@ -2,7 +2,8 @@
"version" : "1.0",
"configurations" : [
{
"playground" : "custom",
"customPlaygroundType" : "device",
"playground" : "standard",
"type" : "uni-app:app-android"
}
]

2
components/footerBar.vue

@ -85,7 +85,7 @@ const tabChange = (value) => {
} else if (value == 5) { //
if (props.type == 'member') return;
uni.redirectTo({
url: '/pages/home/member',
url: '/pages/customerServicePlatform/csPlatformIndex',
animationType: 'fade-in'
})
}

19
pages.json

@ -69,7 +69,26 @@
"titleNView": false,
"bounce": false
}
},
{
"path": "pages/customerServicePlatform/csPlatformIndex",
"style": {
"navigationStyle": "custom",
"disableSwipeBack": true,
"titleNView": false,
"bounce": false
}
},
{
"path": "pages/customerServicePlatform/historyRecord",
"style": {
"navigationStyle": "custom",
"disableSwipeBack": true,
"titleNView": false,
"bounce": false
}
}
],
"globalStyle": {
"navigationBarTextStyle": "black",

627
pages/customerServicePlatform/csPlatformIndex.vue

@ -0,0 +1,627 @@
<template>
<view class="main">
<view class="top" :style="{height:iSMT+'px'}"></view>
<!-- 头部导航 -->
<view class="header">
<view class="back-icon">
<image src="/static/customer-service-platform/cs-platform-back.png" class="header-icon-image"></image>
</view>
<view class="title">{{headerTitle}}</view>
<view class="notification-icon">
<image src="/static/customer-service-platform/message.png" class="header-icon-image"></image>
</view>
</view>
<!-- 内容区域 - 使用滚动视图 -->
<scroll-view scroll-y class="content-container">
<view class="content-header">
<view class="logo">
<image mode="aspectFit" src="/static/customer-service-platform/ellipse-dc-img.png"></image>
</view>
<view class="greeting">
<text class="greet-title">我能为你做点什么</text>
<text class="greet-sub">DeepChart随时为您提供服务</text>
</view>
</view>
<!--猜你想问卡片部分-->
<view class="card">
<view class="suggest-header">
<text class="suggest-title">猜你想问</text>
<view class="swap" @click="shuffleQuestions">
<image class="swap-icon" src="/static/customer-service-platform/refresh-icon.png"></image>
<text class="swap-title">换一换</text>
</view>
</view>
<view class="card-line"></view>
<view class="suggest-list">
<view class="suggest-item" v-for="(q, idx) in showQuestions" :key="q.id"
@click="onQuestionClick(q)">
<view class="left">
<view :class="['num', 'num-' + ((idx % 5) + 1)]">{{ idx + 1 }}</view>
</view>
<view class="mid">
<text class="q-text">{{ q.text }}</text>
</view>
<view class="right">
<text class="arrow"></text>
</view>
</view>
</view>
</view>
<!--反馈卡片部分-->
<text class="feedback-card-title">反馈中心</text>
<view class="card">
<view class="suggest-header">
<text class="feedback-title">填写反馈内容</text>
</view>
<view class="card-line"></view>
<textarea class="feedback-input" placeholder="请描述您想反馈的内容 最多可输入200字" maxlength="200"
v-model="feedbackText" />
<view class="meta-row">
<text class="char-count">{{ feedbackText.length }}/200</text>
</view>
<view class="suggest-header">
<text class="upload-img-tip">上传图片</text>
</view>
<view class="upload-row">
<view class="img-slot" v-for="(img, index) in images" :key="index">
<image :src="img" mode="scaleToFill" class="slot-img" />
<button v-if="img" class="remove" @click="removeImage(index)">×</button>
</view>
<view class="img-slot" v-if="images.length < 9">
<view class="slot-empty" @click="chooseImage()">
<image src="/static/customer-service-platform/camera.png" class="camera-icon" />
</view>
</view>
<text class="tip-text" v-if="images.length === 0">最多添加9张图片</text>
</view>
<button class="feedback-btn" @click="submit">提交</button>
</view>
<!--历史反馈卡片部分-->
<view class="card">
<text class="feedback-title">历史反馈内容</text>
<view class="card-line"></view>
<button class="feedback-btn" @click="viewHistory">查看</button>
</view>
</scroll-view>
</view>
</template>
<script>
export default {
data() {
return {
headerTitle: '智能客服中台',
iSMT: 0,
questions: [{
id: 1,
text: '如何注册账号?'
},
{
id: 2,
text: '为什么无法注册账户?'
},
{
id: 3,
text: 'DeepChart的主要功能有哪些?'
},
{
id: 4,
text: '什么是机构行为?'
},
{
id: 5,
text: '为什么机构行为很重要?'
},
{
id: 6,
text: '如何绑定银行卡?'
},
{
id: 7,
text: '忘记密码怎么办?'
}
],
showQuestions: [],
feedbackText: '',
images: [],
capacity: 2
}
},
mounted() {
//
this.iSMT = uni.getSystemInfoSync().statusBarHeight;
},
created() {
this.shuffleQuestions();
},
methods: {
onBack() {
// uni.navigateBack
if (typeof uni !== 'undefined') uni.navigateBack();
},
shuffleQuestions() {
// 45
const arr = this.questions.slice();
for (let i = arr.length - 1; i > 0; i--) {
const j = Math.floor(Math.random() * (i + 1));
[arr[i], arr[j]] = [arr[j], arr[i]];
}
this.showQuestions = arr.slice(0, 5);
},
onQuestionClick(q) {
//
this.feedbackText = q.text;
},
chooseImage() {
const that = this;
if (typeof uni === 'undefined' || !uni.chooseImage) return;
const remain = 9 - (that.images ? that.images.length : 0);
if (remain <= 0) {
if (typeof uni !== 'undefined') uni.showToast({
title: '最多只能上传9张',
icon: 'none'
});
return;
}
uni.chooseImage({
count: remain, //
sizeType: ['original', 'compressed'],
sourceType: ['album', 'camera'],
success(res) {
// res.tempFilePaths /APP
const paths = res.tempFilePaths || (res.tempFiles && res.tempFiles.map(f => f.path)) || [];
// imagesVue2 push
for (let p of paths) {
if (that.images.length < 9) {
that.images.push(p);
}
}
// uni.uploadFile
},
fail(err) {
//
// console.log('chooseImage fail', err)
}
});
},
removeImage(index) {
//
this.images.splice(index, 1);
},
submit() {
if (!this.feedbackText.trim()) {
if (typeof uni !== 'undefined') uni.showToast({
title: '请填写反馈内容',
icon: 'none'
});
return;
}
//
if (typeof uni !== 'undefined') uni.showLoading({
title: '提交中...'
});
setTimeout(() => {
if (typeof uni !== 'undefined') {
uni.hideLoading();
uni.showToast({
title: '提交成功',
icon: 'success'
});
} else {
console.log('提交数据', {
text: this.feedbackText,
images: this.images
});
}
//
this.feedbackText = '';
this.images = [null, null];
}, 1000);
},
viewHistory() {
//
if (typeof uni !== 'undefined') uni.navigateTo({
url: '/pages/customerServicePlatform/historyRecord'
});
}
}
}
</script>
<style scoped>
.main {
display: flex;
flex-direction: column;
height: 100vh;
background-color: #ffffff;
}
.header {
display: flex;
justify-content: space-between;
align-items: center;
padding: 20rpx 30rpx;
background-color: #ffffff;
}
.title {
color: #000000;
text-align: center;
font-size: 32rpx;
font-style: normal;
font-weight: 400;
}
.back-icon,
.notification-icon {
width: 40rpx;
display: flex;
align-items: center;
justify-content: center;
}
.header-icon-image {
width: 40rpx;
height: 40rpx;
object-fit: contain;
}
.content-container {
padding: 20rpx;
width: 100%;
box-sizing: border-box;
overflow-x: hidden;
}
.content-header {
display: flex;
align-items: center;
gap: 24rpx;
padding: 0 60rpx;
width: 100%;
box-sizing: border-box;
height: 188rpx;
}
.logo {
width: 120rpx;
height: 120rpx;
display: flex;
align-items: center;
justify-content: center;
flex: 0 0 112rpx;
}
.greeting {
display: flex;
flex-direction: column;
justify-content: center;
flex: 1 1 auto;
}
.greet-title {
color: #000;
font-size: 40rpx;
font-style: normal;
font-weight: 500;
line-height: normal;
margin: 0;
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
}
.greet-sub {
color: #838383;
font-size: 28rpx;
font-style: normal;
font-weight: 400;
line-height: normal;
margin-top: 12rpx;
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
}
.card {
width: 90%;
margin: 0 auto;
border-radius: 16rpx;
padding: 20rpx 40rpx;
box-sizing: border-box;
border-radius: 12rpx;
border: 4rpx solid #FCC8D4;
background: linear-gradient(180deg, #FCC8D3 0%, #FEF0F3 30%, #FFF 100%);
margin-bottom: 20rpx;
}
.suggest-header {
width: 100%;
display: flex;
align-items: center;
justify-content: space-between;
}
.suggest-title {
color: #000000;
font-size: 32rpx;
font-style: normal;
font-weight: 400;
line-height: normal;
}
.swap {
display: flex;
align-items: center;
transition: transform 0.1s ease, background-color 0.1s ease;
}
.swap:active {
transform: scale(0.95);
}
.swap-icon {
width: 30rpx;
height: 30rpx;
}
.swap-title {
padding-left: 8rpx;
color: #000000;
font-size: 24rpx;
font-style: normal;
font-weight: 400;
line-height: normal;
}
.suggest-list {
margin-top: 20rpx;
}
.card-line {
margin-top: 20rpx;
width: 100%;
height: 2rpx;
border-radius: 2rpx;
background: #FFF;
}
.suggest-item {
display: flex;
justify-content: space-between;
align-items: center;
padding-top: 10rpx;
border-radius: 12rpx;
margin-bottom: 20rpx;
width: 100%;
box-sizing: border-box;
}
.left {
width: 72rpx;
display: flex;
justify-content: center;
align-items: center;
padding-right: 12rpx;
}
.num {
font-size: 40rpx;
font-style: normal;
font-weight: 700;
line-height: normal;
}
.num-1 {
color: #df5662;
}
.num-2 {
color: #ec6d4f;
}
.num-3 {
color: #f3ba40;
}
.num-4 {
color: #9296a0;
}
.num-5 {
color: #9296a0;
}
.mid {
flex: 1 1 auto;
min-width: 0;
}
.q-text {
display: block;
color: #333;
font-size: 28rpx;
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
}
.right {
width: 48rpx;
display: flex;
align-items: center;
justify-content: flex-end;
}
.arrow {
color: #cfcfcf;
font-size: 36rpx;
}
.suggest-item:active {
background: rgba(255, 77, 128, 0.06);
}
.feedback-card-title {
display: flex;
justify-content: center;
color: #000000;
font-size: 32rpx;
font-weight: 700;
line-height: 40rpx;
width: 100%;
margin-bottom: 20rpx;
}
.feedback-title {
color: #000000;
font-size: 32rpx;
font-style: normal;
font-weight: 400;
line-height: normal;
}
.feedback-input {
width: 100%;
display: flex;
padding: 20rpx;
flex-direction: column;
box-sizing: border-box;
align-items: flex-start;
gap: 12rpx;
align-self: stretch;
border-radius: 12rpx;
border: 2rpx solid #F0F1F1;
margin-top: 20rpx;
display: flex;
background: #FFF;
color: #8a8a8a;
font-size: 24rpx;
font-weight: 700;
line-height: normal;
}
.meta-row {
display: flex;
justify-content: flex-end;
margin-top: 12rpx;
}
.char-count {
color: #999
}
.upload-img-tip {
color: #000000;
font-size: 24rpx;
font-style: normal;
font-weight: 400;
line-height: normal;
}
.upload-row {
display: flex;
justify-content: flex-start;
align-items: flex-start;
align-content: flex-start;
flex-wrap: wrap;
gap: 20rpx;
margin-top: 20rpx;
width: 100%;
}
.img-slot {
width: calc((100% - 2 * 30rpx) / 3);
aspect-ratio: 1 / 1;
border-radius: 6px;
border: 1px solid #F0F1F1;
background: #FFF;
position: relative;
display: flex;
align-items: center;
justify-content: center;
overflow: hidden;
box-shadow: 0 2rpx 6rpx rgba(0, 0, 0, 0.08);
transition: transform 0.2s ease;
}
.slot-empty {
width: 100%;
height: 100%;
display: flex;
align-items: center;
justify-content: center;
}
.camera-icon {
width: 34rpx;
height: 34rpx;
}
.slot-img {
width: 100%;
height: 100%;
border-radius: 16rpx;
}
.remove {
position: absolute;
right: 6rpx;
top: 6rpx;
border-radius: 50%;
background: #fd5c58;
padding: 0;
color: #fff;
width: 36rpx;
height: 36rpx;
font-size: 28rpx;
line-height: 36rpx;
text-align: center;
border: none;
outline: none;
cursor: pointer;
}
.remove:active {
background: rgba(0, 0, 0, 0.75);
}
.image-upload-tip {
display: flex;
align-items: center;
}
.tip-text {
color: #999999;
font-size: 24rpx;
font-style: normal;
font-weight: 400;
line-height: 40rpx;
padding-top: 64rpx;
}
.feedback-btn {
margin-top: 24rpx;
width: 180rpx;
height: 60rpx;
aspect-ratio: 89/30;
border-radius: 30rpx;
background: #090A08;
color: #ffffff;
display: flex;
justify-content: center;
align-items: center;
font-size: 16px;
font-style: normal;
font-weight: 700;
line-height: normal;
}
</style>

342
pages/customerServicePlatform/historyRecord.vue

@ -0,0 +1,342 @@
<template>
<view class="main">
<view class="top" :style="{height:iSMT+'px'}"></view>
<!-- 头部导航 -->
<view class="header">
<view class="back-icon">
<image @click="goBack()" src="/static/customer-service-platform/cs-platform-back.png"
class="header-icon-image"></image>
</view>
<view class="title">智能客服中台</view>
<view class="notification-icon">
<image src="/static/customer-service-platform/message.png" class="header-icon-image"></image>
</view>
</view>
<!-- 内容区域 - 使用滚动视图 -->
<scroll-view scroll-y class="content-container">
<view class="list-wrapper" v-if="historyList.length > 0">
<view class="content-header">
<text class="content-title">历史反馈内容</text>
</view>
<view class="card-line"></view>
<view v-for="(item, idx) in historyList" :key="item.id" class="history-item card">
<view class="item-head">
<view class="dot-outer">
<view class="dot-inner"></view>
</view>
<text class="feedback-time">{{ item.time }}</text>
<text class="feedback-status">
{{ item.statusText }}
<image class="smile-icon" src="/static/customer-service-platform/smile-icon.png"></image>
</text>
</view>
<view class="content-box">
<text class="content-text">{{ item.content }}</text>
<text class="count">{{ item.content.length }}/200</text>
</view>
<view v-if="item.images && item.images.length" class="thumb-row">
<view v-for="(img, i) in item.images" :key="i" class="thumb-slot"
@click="previewImage(item.images, i)">
<image :src="img" mode="scaleToFill" class="thumb-img" />
</view>
</view>
</view>
</view>
<!-- 如果没有历史显示空态 -->
<view v-if="historyList.length === 0" class="empty">
<image mode="aspectFit" class="empty-img" src="/static/customer-service-platform/empty-content.png">
</image>
<text class="empty-tip">暂无内容~</text>
</view>
</scroll-view>
</view>
</template>
<script>
export default {
data() {
return {
iSMT: 0,
// historyList: [],
historyList: [{
id: 1,
time: '2025/10/16 11:46',
status: '成功', // //
statusText: '反馈成功',
content: '你是不是总是看着股票回调时心里发慌,不知道什么时候进场才是最安全的?追高买错被套牢,亏得眼泪直流aaa,回调时又不敢进,错过了反弹的机会?今天,我将带你掌握一套精准确认底部的三步法——通过超卖信号、关键K线和强势启动点,帮助你轻松识别市场底部,稳健进场,避开高位追涨,赚取大波利润!我们今天会结合特斯拉(TSLA)和阿里巴巴(BABA)的经aaa典案例,帮助你更好地理解这些技巧,赶快拿起纸笔,开始学',
images: [
'/static/customer-service-platform/a2.jpg',
'/static/customer-service-platform/a1.png',
'/static/customer-service-platform/a2.jpg',
'/static/customer-service-platform/a1.png',
'/static/customer-service-platform/a2.jpg',
]
},
{
id: 2,
time: '2025/10/16 11:46',
status: '成功',
statusText: '反馈成功',
content: '请描述您想反馈的内容\n第二条示例文本,长度可以不一样,测试多行显示和字数统计功能。这里补充一些文字以便测试外观和换行效果。',
images: []
}
]
};
},
mounted() {
this.iSMT = uni.getSystemInfoSync().statusBarHeight;
},
methods: {
goBack() {
if (typeof uni !== 'undefined' && uni.navigateBack) {
uni.navigateBack();
} else {
window.history.back();
}
},
previewImage(list, index) {
if (typeof uni !== 'undefined' && uni.previewImage) {
uni.previewImage({
current: list[index],
urls: list
});
} else {
// H5 fallback
window.open(list[index], '_blank');
}
}
}
};
</script>
<style scoped>
.main {
display: flex;
flex-direction: column;
height: 100vh;
background-color: #ffffff;
}
.header {
display: flex;
justify-content: space-between;
align-items: center;
padding: 20rpx 30rpx;
background-color: #ffffff;
}
.title {
color: #000000;
text-align: center;
font-size: 32rpx;
font-style: normal;
font-weight: 400;
}
.back-icon,
.notification-icon {
width: 40rpx;
display: flex;
align-items: center;
justify-content: center;
}
.header-icon-image {
width: 40rpx;
height: 40rpx;
object-fit: contain;
}
.content-container {
padding: 20rpx;
padding-top: 0;
width: 100%;
box-sizing: border-box;
overflow-x: hidden;
}
/* 列表包装器,居中卡片 */
.list-wrapper {
width: 90%;
margin: 0 auto;
padding: 20rpx 40rpx;
flex-direction: column;
align-items: center;
gap: 20rpx;
box-sizing: border-box;
border-radius: 12rpx;
border: 4rpx solid #FCC8D4;
background: linear-gradient(180deg, #FCC8D3 0%, #FEF0F3 30%, #FFF 100%);
}
.content-header {
width: 100%;
display: flex;
align-items: center;
justify-content: space-between;
}
.content-title {
color: #000000;
font-size: 32rpx;
font-style: normal;
font-weight: 400;
line-height: normal;
}
.card-line {
margin-top: 20rpx;
width: 100%;
height: 2rpx;
border-radius: 2rpx;
background: #FFF;
}
/* 每一条历史卡片 */
.history-item {
border-radius: 10rpx;
padding: 20rpx;
margin-bottom: 20rpx;
box-sizing: border-box;
box-shadow: 0 4rpx 12rpx rgba(255, 77, 128, 0.06);
}
.item-head {
display: flex;
align-items: center;
gap: 12rpx;
margin-bottom: 12rpx;
}
.dot-outer {
width: 24rpx;
height: 24rpx;
border-radius: 50%;
background: rgba(255, 214, 230, 0.5);
/*粉色外圈*/
display: flex;
align-items: center;
justify-content: center;
box-shadow: 0 0 0 4rpx #ffffff;
/* 最外层白色 */
}
.dot-inner {
width: 14rpx;
height: 14rpx;
border-radius: 50%;
background: #ff4150;
/* 中心红色 */
}
.feedback-time {
color: #000000;
flex: 1;
font-size: 22rpx;
font-style: normal;
font-weight: 400;
line-height: normal;
padding-left: 26rpx;
}
.feedback-status {
color: #ff4150;
font-size: 12rpx;
font-style: normal;
font-weight: 400;
line-height: normal;
display: flex;
align-items: center;
}
.smile-icon {
width: 32rpx;
height: 32rpx;
}
/* 内容框 */
.content-box {
border: 2rpx solid #f0e6ea;
background: #fff;
border-radius: 8rpx;
padding: 18rpx;
position: relative;
box-sizing: border-box;
min-height: 160rpx;
}
.content-text {
display: block;
white-space: pre-wrap;
word-break: break-word;
color: #8a8a8a;
font-size: 24rpx;
font-style: normal;
font-weight: 700;
line-height: normal;
padding-bottom: 26rpx;
}
.count {
position: absolute;
right: 14rpx;
bottom: 10rpx;
color: #000000;
font-size: 24rpx;
font-style: normal;
font-weight: 400;
line-height: normal;
}
.thumb-row {
display: flex;
flex-wrap: wrap;
justify-content: flex-start;
align-items: flex-start;
align-content: flex-start;
width: 100%;
box-sizing: border-box;
gap: 20rpx;
margin-top: 14rpx;
background: #F9FAFE;
padding: 20rpx;
}
.thumb-slot {
width: calc((100% - 2 * 25rpx) / 3);
aspect-ratio: 1 / 1;
border-radius: 7rpx;
border: 1.2rpx solid #F0F1F1;
display: flex;
align-items: center;
justify-content: center;
overflow: hidden;
}
.thumb-img {
width: 100%;
height: 100%;
}
.empty {
padding: 50rpx 0;
text-align: center;
color: #afafaf;
font-size: 32rpx;
font-style: normal;
font-weight: 500;
line-height: 48rpx;
}
.empty-img {
width: 100%;
}
</style>

8
pages/home/home.vue

@ -264,14 +264,12 @@ export default {
object-fit: contain;
}
.content-container {
flex: 1;
padding: 10px;
.content-container {
padding: 20rpx;
width: 100%;
box-sizing: border-box;
overflow-x: hidden;
}
}
.section {
margin-bottom: 15px;
/* background-color: #f5f5f5; */

BIN
static/customer-service-platform/a1.png

After

Width: 1920  |  Height: 1040  |  Size: 521 KiB

BIN
static/customer-service-platform/a2.jpg

After

Width: 522  |  Height: 928  |  Size: 166 KiB

BIN
static/customer-service-platform/camera.png

After

Width: 18  |  Height: 16  |  Size: 428 B

BIN
static/customer-service-platform/cs-platform-back.png

After

Width: 20  |  Height: 20  |  Size: 247 B

BIN
static/customer-service-platform/ellipse-dc-img.png

After

Width: 60  |  Height: 60  |  Size: 2.1 KiB

BIN
static/customer-service-platform/empty-content.png

After

Width: 213  |  Height: 228  |  Size: 18 KiB

BIN
static/customer-service-platform/message.png

After

Width: 18  |  Height: 18  |  Size: 523 B

BIN
static/customer-service-platform/refresh-icon.png

After

Width: 15  |  Height: 15  |  Size: 339 B

BIN
static/customer-service-platform/smile-icon.png

After

Width: 16  |  Height: 16  |  Size: 440 B

Loading…
Cancel
Save