Merge branch 'dev' of http://47.94.45.65:3000/angelo/web-zk-h5 into test
This commit is contained in:
commit
9d00ba690b
|
@ -15,18 +15,20 @@
|
|||
treeData.extend,
|
||||
}"
|
||||
>
|
||||
<view :class="{ node: true }">
|
||||
<view class="node">
|
||||
<view
|
||||
class="person"
|
||||
:class="Array.isArray(treeData.class) ? treeData.class : []"
|
||||
>
|
||||
<view class="frame-text">
|
||||
<view style="font-weight: bold">{{
|
||||
<!-- <view style="font-weight: bold">{{
|
||||
treeData.nodeCode === '0-root' ? '' : treeData.nodeCode
|
||||
}}</view>
|
||||
}}</view> -->
|
||||
<view v-if="treeData.memberCode && treeData.memberName">
|
||||
<view> {{ treeData.memberCode }}</view>
|
||||
<view>{{ treeData.memberName }}</view>
|
||||
<view>{{ stageName }}</view>
|
||||
<!-- <view>{{ treeData.memberName }}</view> -->
|
||||
<view>{{ treeData.creationTime }}</view>
|
||||
</view>
|
||||
<view v-else> 空点位 </view>
|
||||
</view>
|
||||
|
@ -54,6 +56,7 @@
|
|||
:top="0"
|
||||
@click-node="clickNode"
|
||||
@click-top="clickTop"
|
||||
:stageName="stageName"
|
||||
/>
|
||||
</view>
|
||||
</view>
|
||||
|
@ -63,7 +66,7 @@
|
|||
<script>
|
||||
export default {
|
||||
name: 'TreeChart',
|
||||
props: ['json', 'size'],
|
||||
props: ['json', 'size', 'stageName'],
|
||||
data() {
|
||||
return {
|
||||
treeData: {},
|
||||
|
@ -291,6 +294,7 @@ export default {
|
|||
border: 2rpx solid #e9ecef;
|
||||
transition: all 0.3s ease;
|
||||
cursor: pointer;
|
||||
min-width: 120rpx;
|
||||
}
|
||||
|
||||
.node .person:hover {
|
||||
|
|
|
@ -42,7 +42,7 @@
|
|||
<!-- 基本信息 -->
|
||||
<view class="item-header">
|
||||
<view class="member-info">
|
||||
<text class="member-code">{{
|
||||
<text class="member-code" @click="handleMemberCodeClick(item)">{{
|
||||
`${currentUser.memberCode}-${item.childNode}`
|
||||
}}</text>
|
||||
</view>
|
||||
|
@ -192,6 +192,52 @@
|
|||
</view>
|
||||
</u-popup>
|
||||
|
||||
<!-- 树形图弹窗 -->
|
||||
<u-popup
|
||||
:show="showTreePopup"
|
||||
mode="center"
|
||||
@close="showTreePopup = false"
|
||||
:closeOnClickOverlay="true"
|
||||
borderRadius="20"
|
||||
width="96"
|
||||
height="80%"
|
||||
>
|
||||
<view class="tree-popup">
|
||||
<view class="tree-popup-header">
|
||||
<text class="popup-title">点位详情</text>
|
||||
<u-icon
|
||||
name="close"
|
||||
@click="showTreePopup = false"
|
||||
size="32rpx"
|
||||
></u-icon>
|
||||
</view>
|
||||
<view class="tree-popup-content">
|
||||
<view v-if="treeLoading" class="loading-tree">
|
||||
<u-loading-icon mode="spinner"></u-loading-icon>
|
||||
<text>加载中...</text>
|
||||
</view>
|
||||
<view v-else class="tree-container">
|
||||
<view
|
||||
class="tree-scroll-main"
|
||||
ref="treeScrollMain"
|
||||
@touchstart.prevent="handleTreeTouchStart"
|
||||
@touchmove.prevent="handleTreeTouchMove"
|
||||
@touchend="handleTreeTouchEnd"
|
||||
@dblclick="handleTreeDoubleClick"
|
||||
:style="treeContainerStyle"
|
||||
>
|
||||
<TreeChart
|
||||
:size="treeSize"
|
||||
:json="treeData"
|
||||
@click-node="clickTreeNode"
|
||||
:stageName="stageName"
|
||||
/>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</u-popup>
|
||||
|
||||
<!-- 选择器 -->
|
||||
<u-picker
|
||||
:show="stageListVisible"
|
||||
|
@ -213,8 +259,12 @@
|
|||
|
||||
<script>
|
||||
import * as arc from '@/config/architecture.js'
|
||||
import TreeChart from '@/components/architectures/resettleSO.vue'
|
||||
|
||||
export default {
|
||||
components: {
|
||||
TreeChart,
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
// 列表数据
|
||||
|
@ -266,6 +316,28 @@ export default {
|
|||
pointDetail: {},
|
||||
pointDetailLoading: false,
|
||||
currentUser: {},
|
||||
|
||||
// 树形图弹窗相关
|
||||
showTreePopup: false,
|
||||
treeData: {},
|
||||
treeLoading: false,
|
||||
selectedTreeItem: {},
|
||||
|
||||
// 树形图缩放和拖拽相关
|
||||
treeSize: 0.8,
|
||||
treeIsZooming: false,
|
||||
treeIsDragging: false,
|
||||
treeTouchStartPosition1: { x: 0, y: 0 },
|
||||
treeTouchStartPosition2: { x: 0, y: 0 },
|
||||
treeInitialDistance: 0,
|
||||
treeInitialSize: 0.5,
|
||||
treeMinSize: 0.2,
|
||||
treeMaxSize: 3.0,
|
||||
treeDragStartPosition: { x: 0, y: 0 },
|
||||
treeContainerTransform: { x: 0, y: 0 },
|
||||
treeLastTouchTime: 0,
|
||||
treeVelocity: { x: 0, y: 0 },
|
||||
treeMaxTransform: { x: 1000, y: 1000 },
|
||||
}
|
||||
},
|
||||
|
||||
|
@ -285,12 +357,25 @@ export default {
|
|||
this.loadMore()
|
||||
},
|
||||
|
||||
computed: {
|
||||
treeContainerStyle() {
|
||||
return {
|
||||
transform: `translate(${this.treeContainerTransform.x}rpx, ${this.treeContainerTransform.y}px) scale(${this.treeSize})`,
|
||||
transformOrigin: 'center center',
|
||||
transition:
|
||||
this.treeIsDragging || this.treeIsZooming
|
||||
? 'none'
|
||||
: 'transform 0.1s ease-out',
|
||||
}
|
||||
},
|
||||
},
|
||||
|
||||
methods: {
|
||||
init() {
|
||||
this.stageName = this.stageOptions[0][0].label
|
||||
this.queryParams.stage = this.stageOptions[0][0].value
|
||||
// 设置默认状态为"未完成"
|
||||
const statusIndex = 1
|
||||
const statusIndex = 2
|
||||
this.selectedStatusValue = this.statusOptions[0][statusIndex].value
|
||||
this.statusName = this.statusOptions[0][statusIndex].label
|
||||
this.queryParams.stageStatus = this.selectedStatusValue
|
||||
|
@ -495,6 +580,211 @@ export default {
|
|||
const date = new Date(dateStr)
|
||||
return `${date.getFullYear()}-${String(date.getMonth() + 1).padStart(2, '0')}-${String(date.getDate()).padStart(2, '0')}`
|
||||
},
|
||||
|
||||
// 处理会员编号点击事件
|
||||
handleMemberCodeClick(item) {
|
||||
this.selectedTreeItem = item
|
||||
this.showTreePopup = true
|
||||
this.loadTreeData(item)
|
||||
},
|
||||
|
||||
// 加载树形图数据
|
||||
async loadTreeData(item) {
|
||||
try {
|
||||
this.treeLoading = true
|
||||
this.treeData = {}
|
||||
|
||||
const params = {
|
||||
stage: this.queryParams.stage,
|
||||
childNode: item.childNode,
|
||||
}
|
||||
|
||||
const res = await arc.getAzFramework(params)
|
||||
|
||||
if (res.code === 200 && res.data && res.data.length > 0) {
|
||||
this.treeData = res.data[0]
|
||||
} else {
|
||||
uni.showToast({
|
||||
title: res.msg || '获取树形图数据失败',
|
||||
icon: 'none',
|
||||
})
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('加载树形图数据失败:', error)
|
||||
uni.showToast({
|
||||
title: '网络异常,请稍后重试',
|
||||
icon: 'none',
|
||||
})
|
||||
} finally {
|
||||
this.treeLoading = false
|
||||
}
|
||||
},
|
||||
|
||||
// 树形图节点点击事件
|
||||
clickTreeNode(e) {
|
||||
// 可以在这里处理树节点的点击事件
|
||||
console.log('树节点点击:', e)
|
||||
},
|
||||
|
||||
// 树形图触摸开始
|
||||
handleTreeTouchStart(event) {
|
||||
const touch1 = event.touches[0]
|
||||
const touch2 = event.touches[1]
|
||||
const currentTime = Date.now()
|
||||
|
||||
if (touch2) {
|
||||
// 双指触摸 - 缩放模式
|
||||
this.treeIsZooming = true
|
||||
this.treeIsDragging = false
|
||||
this.treeInitialSize = this.treeSize
|
||||
|
||||
this.treeTouchStartPosition1 = {
|
||||
x: touch1.clientX,
|
||||
y: touch1.clientY,
|
||||
}
|
||||
this.treeTouchStartPosition2 = {
|
||||
x: touch2.clientX,
|
||||
y: touch2.clientY,
|
||||
}
|
||||
this.treeInitialDistance = Math.hypot(
|
||||
touch2.clientX - touch1.clientX,
|
||||
touch2.clientY - touch1.clientY
|
||||
)
|
||||
} else {
|
||||
// 单指触摸 - 拖动模式
|
||||
this.treeIsZooming = false
|
||||
this.treeIsDragging = true
|
||||
this.treeDragStartPosition = {
|
||||
x: touch1.clientX,
|
||||
y: touch1.clientY,
|
||||
}
|
||||
this.treeLastTouchTime = currentTime
|
||||
}
|
||||
},
|
||||
|
||||
// 树形图触摸移动
|
||||
handleTreeTouchMove(event) {
|
||||
const touch1 = event.touches[0]
|
||||
const touch2 = event.touches[1]
|
||||
|
||||
if (touch2 && this.treeIsZooming && this.treeInitialDistance > 0) {
|
||||
// 双指缩放处理
|
||||
const currentDistance = Math.hypot(
|
||||
touch2.clientX - touch1.clientX,
|
||||
touch2.clientY - touch1.clientY
|
||||
)
|
||||
|
||||
const scale = currentDistance / this.treeInitialDistance
|
||||
let newSize = this.treeInitialSize * scale
|
||||
|
||||
// 应用边界限制
|
||||
newSize = Math.max(
|
||||
this.treeMinSize,
|
||||
Math.min(this.treeMaxSize, newSize)
|
||||
)
|
||||
|
||||
// 平滑缩放
|
||||
const sizeDiff = newSize - this.treeSize
|
||||
this.treeSize = this.treeSize + sizeDiff * 0.3
|
||||
} else if (!touch2 && this.treeIsDragging) {
|
||||
// 单指拖动处理
|
||||
const deltaX = touch1.clientX - this.treeDragStartPosition.x
|
||||
const deltaY = touch1.clientY - this.treeDragStartPosition.y
|
||||
|
||||
// 计算拖动速度
|
||||
this.treeVelocity.x = deltaX * 0.1
|
||||
this.treeVelocity.y = deltaY * 0.1
|
||||
|
||||
// 更新容器变换位置(添加阻尼效果)
|
||||
let newX = this.treeContainerTransform.x + deltaX * 0.8
|
||||
let newY = this.treeContainerTransform.y + deltaY * 0.8
|
||||
|
||||
// 应用边界限制(根据缩放调整边界)
|
||||
const scaledMaxX = this.treeMaxTransform.x * this.treeSize
|
||||
const scaledMaxY = this.treeMaxTransform.y * this.treeSize
|
||||
|
||||
newX = Math.max(-scaledMaxX, Math.min(scaledMaxX, newX))
|
||||
newY = Math.max(-scaledMaxY, Math.min(scaledMaxY, newY))
|
||||
|
||||
this.treeContainerTransform.x = newX
|
||||
this.treeContainerTransform.y = newY
|
||||
|
||||
// 更新拖动起始位置
|
||||
this.treeDragStartPosition.x = touch1.clientX
|
||||
this.treeDragStartPosition.y = touch1.clientY
|
||||
}
|
||||
},
|
||||
|
||||
// 树形图触摸结束
|
||||
handleTreeTouchEnd(event) {
|
||||
const currentTime = Date.now()
|
||||
const touchDuration = currentTime - this.treeLastTouchTime
|
||||
|
||||
// 如果是拖动结束,启动惯性滚动
|
||||
if (
|
||||
this.treeIsDragging &&
|
||||
(Math.abs(this.treeVelocity.x) > 1 || Math.abs(this.treeVelocity.y) > 1)
|
||||
) {
|
||||
this.startTreeInertiaScroll()
|
||||
}
|
||||
|
||||
// 重置触摸状态
|
||||
this.treeIsZooming = false
|
||||
this.treeIsDragging = false
|
||||
this.treeTouchStartPosition1 = { x: 0, y: 0 }
|
||||
this.treeTouchStartPosition2 = { x: 0, y: 0 }
|
||||
this.treeInitialDistance = 0
|
||||
this.treeInitialSize = this.treeSize
|
||||
this.treeDragStartPosition = { x: 0, y: 0 }
|
||||
},
|
||||
|
||||
// 树形图惯性滚动
|
||||
startTreeInertiaScroll() {
|
||||
const friction = 0.95 // 摩擦系数
|
||||
const minVelocity = 0.1 // 最小速度阈值
|
||||
|
||||
const animateInertia = () => {
|
||||
// 应用速度到位置
|
||||
let newX = this.treeContainerTransform.x + this.treeVelocity.x
|
||||
let newY = this.treeContainerTransform.y + this.treeVelocity.y
|
||||
|
||||
// 应用边界限制
|
||||
const scaledMaxX = this.treeMaxTransform.x * this.treeSize
|
||||
const scaledMaxY = this.treeMaxTransform.y * this.treeSize
|
||||
|
||||
newX = Math.max(-scaledMaxX, Math.min(scaledMaxX, newX))
|
||||
newY = Math.max(-scaledMaxY, Math.min(scaledMaxY, newY))
|
||||
|
||||
this.treeContainerTransform.x = newX
|
||||
this.treeContainerTransform.y = newY
|
||||
|
||||
// 减少速度
|
||||
this.treeVelocity.x *= friction
|
||||
this.treeVelocity.y *= friction
|
||||
|
||||
// 继续动画或停止
|
||||
if (
|
||||
Math.abs(this.treeVelocity.x) > minVelocity ||
|
||||
Math.abs(this.treeVelocity.y) > minVelocity
|
||||
) {
|
||||
requestAnimationFrame(animateInertia)
|
||||
}
|
||||
}
|
||||
|
||||
requestAnimationFrame(animateInertia)
|
||||
},
|
||||
|
||||
// 重置树形图缩放和位置
|
||||
resetTreeZoom() {
|
||||
this.treeSize = 0.5
|
||||
this.treeInitialSize = 0.5
|
||||
this.treeContainerTransform = { x: 0, y: 0 }
|
||||
},
|
||||
|
||||
// 双击重置树形图缩放和位置
|
||||
handleTreeDoubleClick() {
|
||||
this.resetTreeZoom()
|
||||
},
|
||||
},
|
||||
}
|
||||
</script>
|
||||
|
@ -639,9 +929,15 @@ export default {
|
|||
.member-code {
|
||||
font-size: 24rpx;
|
||||
font-weight: bold;
|
||||
color: #333;
|
||||
color: #005bac;
|
||||
flex-shrink: 0;
|
||||
margin-right: 30rpx;
|
||||
cursor: pointer;
|
||||
text-decoration: underline;
|
||||
|
||||
&:active {
|
||||
color: #003d7a;
|
||||
}
|
||||
}
|
||||
|
||||
.status-badge {
|
||||
|
@ -890,4 +1186,72 @@ export default {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* 树形图弹窗样式 */
|
||||
.tree-popup {
|
||||
width: 95vw;
|
||||
height: 80vh;
|
||||
background: #fff;
|
||||
border-radius: 20rpx;
|
||||
overflow: hidden;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
|
||||
.tree-popup-header {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
padding: 30rpx;
|
||||
background: #f5f6f8;
|
||||
border-bottom: 2rpx solid #eee;
|
||||
flex-shrink: 0;
|
||||
|
||||
.popup-title {
|
||||
font-size: 32rpx;
|
||||
font-weight: bold;
|
||||
color: #333;
|
||||
}
|
||||
}
|
||||
|
||||
.tree-popup-content {
|
||||
flex: 1;
|
||||
position: relative;
|
||||
overflow: hidden;
|
||||
|
||||
.loading-tree {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
height: 100%;
|
||||
font-size: 26rpx;
|
||||
color: #999;
|
||||
|
||||
text {
|
||||
margin-left: 12rpx;
|
||||
}
|
||||
}
|
||||
|
||||
.tree-container {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
position: relative;
|
||||
overflow: hidden;
|
||||
background: #fff;
|
||||
|
||||
.tree-scroll-main {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
transform-origin: center center;
|
||||
cursor: grab;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
|
||||
&:active {
|
||||
cursor: grabbing;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
|
|
@ -15,8 +15,8 @@
|
|||
<text class="value">{{ item.settleGradeVal }}</text>
|
||||
</view>
|
||||
<view class="item-row">
|
||||
<text class="label">会员昵称</text>
|
||||
<text class="value">{{ item.nickName }}</text>
|
||||
<text class="label">会员姓名</text>
|
||||
<text class="value">{{ item.memberName }}</text>
|
||||
</view>
|
||||
<view class="item-row">
|
||||
<text class="label">创建时间</text>
|
||||
|
|
|
@ -305,7 +305,7 @@ export default {
|
|||
},
|
||||
{
|
||||
url: '/pages/mine/directPush/index',
|
||||
name: '直推列表',
|
||||
name: '服务列表',
|
||||
imgurl: '../../static/images/mark5.png',
|
||||
menuKey: 'directPush',
|
||||
ifshow: false,
|
||||
|
|
Loading…
Reference in New Issue