陪练和客户页面的产品化
This commit is contained in:
@@ -17,51 +17,26 @@
|
||||
|
||||
<view class="content">
|
||||
<!-- 标签页 -->
|
||||
<scroll-view class="tabs-scroll" scroll-x="true" show-scrollbar="false">
|
||||
<view class="tabs">
|
||||
<view
|
||||
class="tab-item"
|
||||
:class="{ active: activeTab === 'survey' }"
|
||||
@click="switchTab('survey')">
|
||||
<text>摸底</text>
|
||||
</view>
|
||||
<view
|
||||
class="tab-item"
|
||||
:class="{ active: activeTab === 'practice' }"
|
||||
@click="switchTab('practice')">
|
||||
<text>陪练</text>
|
||||
</view>
|
||||
<view
|
||||
class="tab-item"
|
||||
:class="{ active: activeTab === 'battle' }"
|
||||
@click="switchTab('battle')">
|
||||
<text>实战</text>
|
||||
</view>
|
||||
<view
|
||||
class="tab-item"
|
||||
:class="{ active: activeTab === 'quality' }"
|
||||
@click="switchTab('quality')">
|
||||
<text>质检</text>
|
||||
</view>
|
||||
<view
|
||||
class="tab-item"
|
||||
:class="{ active: activeTab === 'material' }"
|
||||
@click="switchTab('material')">
|
||||
<text>素材</text>
|
||||
</view>
|
||||
<view class="tabs">
|
||||
<view
|
||||
class="tab-item"
|
||||
:class="{ active: activeTab === 'practice' }"
|
||||
@click="switchTab('practice')">
|
||||
<text>陪练</text>
|
||||
</view>
|
||||
</scroll-view>
|
||||
|
||||
<!-- 摸底内容 -->
|
||||
<scroll-view
|
||||
class="tab-content"
|
||||
scroll-y
|
||||
v-if="activeTab === 'survey'">
|
||||
<view class="champion-card">
|
||||
<text class="champion-title">摸底</text>
|
||||
<text class="champion-desc">这里是摸底相关的内容展示区域</text>
|
||||
<view
|
||||
class="tab-item"
|
||||
:class="{ active: activeTab === 'quality' }"
|
||||
@click="switchTab('quality')">
|
||||
<text>质检</text>
|
||||
</view>
|
||||
</scroll-view>
|
||||
<view
|
||||
class="tab-item"
|
||||
:class="{ active: activeTab === 'material' }"
|
||||
@click="switchTab('material')">
|
||||
<text>素材</text>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<!-- 陪练内容 -->
|
||||
<scroll-view
|
||||
@@ -108,7 +83,7 @@
|
||||
</view>
|
||||
<text class="staff-name">{{ item.title || '未命名知识' }}</text>
|
||||
</view>
|
||||
<view class="card-menu-trigger" @tap.stop="showPracticeContextMenu(item, index, $event)">
|
||||
<view class="card-menu-trigger" @tap.stop="onPracticeActionBtnClick(item)">
|
||||
<uni-icons type="more-filled" size="20" color="#999"></uni-icons>
|
||||
</view>
|
||||
</view>
|
||||
@@ -126,16 +101,16 @@
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<!-- 上下文菜单 -->
|
||||
<!-- 操作菜单 -->
|
||||
<view
|
||||
class="context-menu"
|
||||
v-if="practiceContextMenuVisible && practiceContextMenuIndex === index"
|
||||
:style="{ top: practiceContextMenuTop + 'px', left: practiceContextMenuLeft + 'px' }"
|
||||
class="practice-action-menu"
|
||||
v-if="selectedPracticeItem && selectedPracticeItem.id === item.id && showPracticeActionMenu"
|
||||
@tap.stop>
|
||||
<view class="context-menu-item" @tap.stop="handleEditPractice(item)">
|
||||
<view class="practice-action-menu-item" @tap.stop="handleEditPractice(item)">
|
||||
<text>编辑</text>
|
||||
</view>
|
||||
<view class="context-menu-item context-menu-item--danger" @tap.stop="handleDeletePractice(item)">
|
||||
<view class="practice-action-menu-divider"></view>
|
||||
<view class="practice-action-menu-item practice-action-menu-item--danger" @tap.stop="handleDeletePractice(item)">
|
||||
<text>删除</text>
|
||||
</view>
|
||||
</view>
|
||||
@@ -304,17 +279,6 @@
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<!-- 实战内容 -->
|
||||
<scroll-view
|
||||
class="tab-content"
|
||||
scroll-y
|
||||
v-if="activeTab === 'battle'">
|
||||
<view class="champion-card">
|
||||
<text class="champion-title">实战</text>
|
||||
<text class="champion-desc">这里是实战相关的内容展示区域</text>
|
||||
</view>
|
||||
</scroll-view>
|
||||
|
||||
<!-- 质检内容 -->
|
||||
<scroll-view
|
||||
class="tab-content"
|
||||
@@ -562,6 +526,13 @@
|
||||
<!-- 上下文菜单遮罩层 -->
|
||||
<view class="context-menu-mask" v-if="contextMenuVisible" @tap="closeContextMenu"></view>
|
||||
|
||||
<!-- 陪练操作菜单遮罩层 -->
|
||||
<view
|
||||
class="practice-action-menu-mask"
|
||||
v-if="showPracticeActionMenu"
|
||||
@tap="closePracticeActionMenu">
|
||||
</view>
|
||||
|
||||
<!-- 内容详情弹出框 -->
|
||||
<view class="content-popup-mask" v-if="showContentPopup" @click="closeContentPopup">
|
||||
</view>
|
||||
@@ -604,7 +575,7 @@
|
||||
// #endif
|
||||
data() {
|
||||
return {
|
||||
activeTab: 'survey',
|
||||
activeTab: 'practice',
|
||||
// 素材相关数据
|
||||
materialList: [],
|
||||
materialLoading: false,
|
||||
@@ -676,11 +647,9 @@
|
||||
content: '',
|
||||
remark: ''
|
||||
},
|
||||
// 陪练上下文菜单
|
||||
practiceContextMenuVisible: false,
|
||||
practiceContextMenuIndex: -1,
|
||||
practiceContextMenuTop: 0,
|
||||
practiceContextMenuLeft: 0,
|
||||
// 陪练操作菜单
|
||||
selectedPracticeItem: null,
|
||||
showPracticeActionMenu: false,
|
||||
// 内容详情弹出框
|
||||
showContentPopup: false,
|
||||
contentPopupTitle: '',
|
||||
@@ -1301,53 +1270,23 @@
|
||||
this.practiceLoading = false;
|
||||
}
|
||||
},
|
||||
showPracticeContextMenu(item, index, event) {
|
||||
// 阻止事件冒泡
|
||||
if (event && event.stopPropagation) {
|
||||
event.stopPropagation();
|
||||
}
|
||||
// 获取系统信息以计算位置
|
||||
const systemInfo = uni.getSystemInfoSync();
|
||||
// 获取点击位置 - 优先使用触摸事件坐标
|
||||
let top = 100;
|
||||
let left = systemInfo.windowWidth - 180;
|
||||
|
||||
if (event) {
|
||||
if (event.touches && event.touches.length > 0) {
|
||||
// 触摸事件
|
||||
top = event.touches[0].clientY;
|
||||
left = event.touches[0].clientX - 80;
|
||||
} else if (event.detail && typeof event.detail.x === 'number') {
|
||||
// tap事件坐标(单位:px,需要转换)
|
||||
top = event.detail.y;
|
||||
left = event.detail.x - 80;
|
||||
} else if (event.clientY !== undefined) {
|
||||
// 鼠标事件
|
||||
top = event.clientY;
|
||||
left = event.clientX - 80;
|
||||
}
|
||||
onPracticeActionBtnClick(item) {
|
||||
// 如果已经选中当前项,则关闭菜单
|
||||
if (this.selectedPracticeItem && this.selectedPracticeItem.id === item.id && this.showPracticeActionMenu) {
|
||||
this.closePracticeActionMenu();
|
||||
return;
|
||||
}
|
||||
|
||||
// 确保菜单不超出屏幕
|
||||
if (left + 160 > systemInfo.windowWidth) {
|
||||
left = systemInfo.windowWidth - 180;
|
||||
}
|
||||
if (left < 0) {
|
||||
left = 10;
|
||||
}
|
||||
|
||||
this.practiceContextMenuTop = top;
|
||||
this.practiceContextMenuLeft = left;
|
||||
// 显示菜单
|
||||
this.practiceContextMenuIndex = index;
|
||||
this.practiceContextMenuVisible = true;
|
||||
this.selectedPracticeItem = item;
|
||||
this.showPracticeActionMenu = true;
|
||||
},
|
||||
closePracticeContextMenu() {
|
||||
this.practiceContextMenuVisible = false;
|
||||
this.practiceContextMenuIndex = -1;
|
||||
closePracticeActionMenu() {
|
||||
this.showPracticeActionMenu = false;
|
||||
this.selectedPracticeItem = null;
|
||||
},
|
||||
handleEditPractice(item) {
|
||||
this.closePracticeContextMenu();
|
||||
this.closePracticeActionMenu();
|
||||
// 填充编辑表单
|
||||
this.editPracticeForm = {
|
||||
id: item.id,
|
||||
@@ -1433,7 +1372,7 @@
|
||||
}
|
||||
},
|
||||
handleDeletePractice(item) {
|
||||
this.closePracticeContextMenu();
|
||||
this.closePracticeActionMenu();
|
||||
uni.showModal({
|
||||
title: '提示',
|
||||
content: '确认删除该陪练吗?',
|
||||
@@ -1658,26 +1597,17 @@
|
||||
}
|
||||
|
||||
/* 标签页 */
|
||||
.tabs-scroll {
|
||||
position: fixed;
|
||||
.tabs {
|
||||
display: flex;
|
||||
background-color: #FFFFFF;
|
||||
border-bottom: 1px solid #E0E0E0;
|
||||
padding: 0 16rpx;
|
||||
margin-top: 0;
|
||||
position: absolute;
|
||||
top: 88rpx; /* 导航栏高度 */
|
||||
left: 0;
|
||||
right: 0;
|
||||
width: 100%;
|
||||
background-color: #FFFFFF;
|
||||
border-bottom: 1px solid #E0E0E0;
|
||||
white-space: nowrap;
|
||||
margin-top: 0;
|
||||
z-index: 999;
|
||||
height: 72rpx; /* 设置固定高度,确保tabs可见 */
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
.tabs {
|
||||
display: inline-flex;
|
||||
padding: 0 16rpx;
|
||||
height: 100%; /* 确保tabs占满scroll-view的高度 */
|
||||
align-items: center; /* 垂直居中 */
|
||||
z-index: 1;
|
||||
}
|
||||
|
||||
.tab-item {
|
||||
@@ -1728,6 +1658,10 @@
|
||||
left: 0;
|
||||
right: 0;
|
||||
bottom: 96rpx; /* 底部导航栏高度 */
|
||||
background-color: #F5F5F5;
|
||||
padding: 24rpx 16rpx 0 16rpx; /* 顶部24rpx间距(与列表项间距一致),底部0 */
|
||||
box-sizing: border-box;
|
||||
overflow-y: auto;
|
||||
}
|
||||
|
||||
.champion-card {
|
||||
@@ -1761,13 +1695,15 @@
|
||||
display: flex;
|
||||
flex-wrap: nowrap;
|
||||
align-items: center;
|
||||
gap: 2rpx;
|
||||
padding: 4rpx 4rpx;
|
||||
margin-bottom: 4rpx;
|
||||
gap: 8rpx; /* 增加间距,避免元素被挤压 */
|
||||
padding: 12rpx 8rpx; /* 增加内边距,给搜索框更多空间 */
|
||||
margin-bottom: 24rpx; /* 与列表项间距保持一致(24rpx) */
|
||||
background-color: #F8F8FA;
|
||||
border-radius: 8rpx;
|
||||
border: 1px solid #EFEFF2;
|
||||
overflow-x: auto;
|
||||
min-height: 64rpx; /* 设置最小高度,确保搜索区域不被挤压 */
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
.toolbar-total {
|
||||
@@ -1775,21 +1711,24 @@
|
||||
color: #666;
|
||||
white-space: nowrap;
|
||||
flex-shrink: 0;
|
||||
margin-right: 2rpx;
|
||||
margin-right: 8rpx; /* 增加右边距,与搜索框保持距离 */
|
||||
line-height: 1.2;
|
||||
padding: 0 4rpx; /* 增加左右内边距 */
|
||||
}
|
||||
|
||||
.toolbar-input {
|
||||
flex: 1;
|
||||
min-width: 100rpx;
|
||||
height: 48rpx;
|
||||
line-height: 48rpx;
|
||||
min-width: 120rpx; /* 增加最小宽度,避免被挤压变形 */
|
||||
max-width: 200rpx; /* 设置最大宽度,保持合理比例 */
|
||||
height: 56rpx; /* 稍微增加高度,提升可用性 */
|
||||
line-height: 56rpx;
|
||||
background-color: #F5F6FA;
|
||||
border-radius: 8rpx;
|
||||
padding: 0 8rpx;
|
||||
padding: 0 12rpx; /* 增加左右内边距 */
|
||||
font-size: 24rpx;
|
||||
border: 1px solid transparent;
|
||||
box-sizing: border-box;
|
||||
flex-shrink: 1; /* 允许适当收缩,但保持最小宽度 */
|
||||
}
|
||||
|
||||
.toolbar-actions {
|
||||
@@ -1797,21 +1736,26 @@
|
||||
align-items: center;
|
||||
margin-left: auto;
|
||||
flex-shrink: 0;
|
||||
gap: 2rpx;
|
||||
gap: 8rpx; /* 增加按钮之间的间距 */
|
||||
}
|
||||
|
||||
.toolbar-btn {
|
||||
padding: 0 6rpx;
|
||||
height: 48rpx;
|
||||
min-width: 48rpx;
|
||||
padding: 0 12rpx; /* 增加左右内边距 */
|
||||
height: 56rpx; /* 与输入框高度保持一致 */
|
||||
min-width: 56rpx;
|
||||
color: #2A68FF;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
gap: 2rpx;
|
||||
gap: 4rpx; /* 增加图标和文字之间的间距 */
|
||||
font-size: 24rpx;
|
||||
font-weight: 400;
|
||||
line-height: 1;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
.toolbar-btn text {
|
||||
color: #2A68FF;
|
||||
}
|
||||
|
||||
.service-card {
|
||||
@@ -1845,13 +1789,24 @@
|
||||
}
|
||||
|
||||
.card-menu-trigger {
|
||||
width: 48rpx;
|
||||
height: 48rpx;
|
||||
width: 60rpx;
|
||||
height: 60rpx;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
cursor: pointer;
|
||||
flex-shrink: 0;
|
||||
margin-left: auto;
|
||||
margin-right: 0;
|
||||
margin-top: 0;
|
||||
margin-bottom: 0;
|
||||
flex-grow: 0;
|
||||
position: relative;
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
.card-menu-trigger:active {
|
||||
opacity: 0.7;
|
||||
}
|
||||
|
||||
.context-menu {
|
||||
@@ -1865,6 +1820,56 @@
|
||||
max-width: 200rpx;
|
||||
}
|
||||
|
||||
/* 陪练操作菜单样式 */
|
||||
.practice-card-item {
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.practice-action-menu {
|
||||
position: absolute;
|
||||
top: 60rpx;
|
||||
right: 32rpx;
|
||||
width: 160rpx;
|
||||
background-color: #FFFFFF;
|
||||
border-radius: 12rpx;
|
||||
box-shadow: 0 4rpx 12rpx rgba(0, 0, 0, 0.15);
|
||||
z-index: 100;
|
||||
overflow: hidden;
|
||||
margin-right: 0;
|
||||
}
|
||||
|
||||
.practice-action-menu-item {
|
||||
padding: 24rpx 32rpx;
|
||||
font-size: 28rpx;
|
||||
color: #333;
|
||||
text-align: center;
|
||||
background-color: #FFFFFF;
|
||||
}
|
||||
|
||||
.practice-action-menu-item:active {
|
||||
background-color: #F5F5F5;
|
||||
}
|
||||
|
||||
.practice-action-menu-item--danger {
|
||||
color: #FF5722;
|
||||
}
|
||||
|
||||
.practice-action-menu-divider {
|
||||
height: 1rpx;
|
||||
background-color: #E0E0E0;
|
||||
margin: 0 16rpx;
|
||||
}
|
||||
|
||||
.practice-action-menu-mask {
|
||||
position: fixed;
|
||||
top: 0;
|
||||
left: 0;
|
||||
right: 0;
|
||||
bottom: 0;
|
||||
background-color: transparent;
|
||||
z-index: 99;
|
||||
}
|
||||
|
||||
.context-menu-item {
|
||||
padding: 24rpx 32rpx;
|
||||
font-size: 28rpx;
|
||||
|
||||
@@ -1632,33 +1632,36 @@
|
||||
// 加载服务记录列表
|
||||
async loadServiceList(params = {}) {
|
||||
try {
|
||||
// 构建查询参数对象(后端使用 @RequestParam,参数需要作为 URL 查询参数传递)
|
||||
const queryParams = {
|
||||
current: this.serviceListPage.current,
|
||||
size: this.serviceListPage.size
|
||||
};
|
||||
|
||||
// 添加查询参数:所属销售姓名和客户姓名
|
||||
if (params.salesName) {
|
||||
queryParams.salesName = params.salesName;
|
||||
const trimmedSalesName = params.salesName?.trim();
|
||||
const trimmedCustomerName = params.customerName?.trim();
|
||||
if (trimmedSalesName) {
|
||||
queryParams.salesName = trimmedSalesName;
|
||||
}
|
||||
if (params.customerName) {
|
||||
queryParams.customerName = params.customerName;
|
||||
if (trimmedCustomerName) {
|
||||
queryParams.customerName = trimmedCustomerName;
|
||||
}
|
||||
|
||||
// 构建请求体(过滤空值),后端改为 POST
|
||||
const requestData = Object.keys(queryParams)
|
||||
// 将参数转换为 URL 查询字符串(因为后端使用 @RequestParam)
|
||||
const queryString = Object.keys(queryParams)
|
||||
.filter(key => queryParams[key] !== null && queryParams[key] !== undefined && queryParams[key] !== '')
|
||||
.reduce((acc, key) => {
|
||||
acc[key] = queryParams[key];
|
||||
return acc;
|
||||
}, {});
|
||||
.map(key => `${encodeURIComponent(key)}=${encodeURIComponent(queryParams[key])}`)
|
||||
.join('&');
|
||||
|
||||
const url = getApiUrl('/api/audioManagement/list');
|
||||
// 后端使用 @RequestParam,参数需要作为 URL 查询参数传递
|
||||
const baseUrl = getApiUrl('/api/audioManagement/list');
|
||||
const url = queryString ? `${baseUrl}?${queryString}` : baseUrl;
|
||||
|
||||
const res = await uni.request({
|
||||
url: url,
|
||||
url,
|
||||
method: 'POST',
|
||||
data: requestData,
|
||||
data: {}, // POST 请求体为空,参数都在 URL 查询字符串中
|
||||
header: {
|
||||
'Content-Type': 'application/json'
|
||||
},
|
||||
|
||||
Reference in New Issue
Block a user