|
@@ -1,8 +1,66 @@
|
|
|
<template>
|
|
|
<div class="list-wrap">
|
|
|
<div class="list-content">
|
|
|
- <div class="list-item" v-for="(ele, idx) in defalutList" :key="idx">
|
|
|
- <div class="item-flex">
|
|
|
+ <el-collapse v-model="activeNames" expand-icon-position="left">
|
|
|
+ <el-collapse-item
|
|
|
+ title="Consistency"
|
|
|
+ v-for="(group, groupIndex) in groupList"
|
|
|
+ :key="groupIndex"
|
|
|
+ :name="groupIndex"
|
|
|
+ >
|
|
|
+ <template #title="{ isActive }">
|
|
|
+ <div :class="['title-wrapper', { 'is-active': isActive }]">
|
|
|
+ <div class="title-l">
|
|
|
+ <el-icon class="arrow-icon"><CaretBottom /></el-icon>
|
|
|
+ {{ group.name }}
|
|
|
+ <span class="group-length">({{ group.list.length }})</span>
|
|
|
+ </div>
|
|
|
+ <div class="title-r" @click.stop="handleRightClick">
|
|
|
+ <span class="title-manage">管理</span>
|
|
|
+ <el-checkbox
|
|
|
+ v-show="toSelectClient"
|
|
|
+ v-model="groupCheckStates[groupIndex].checkAll"
|
|
|
+ :indeterminate="groupCheckStates[groupIndex].isIndeterminate"
|
|
|
+ @change="(val) => handleCheckAllChange(val, groupIndex)"
|
|
|
+ >
|
|
|
+ 全选
|
|
|
+ </el-checkbox>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ </template>
|
|
|
+ <template #icon> </template>
|
|
|
+ <!-- 遍历当前分组中的每一项 -->
|
|
|
+ <el-checkbox-group v-model="checkedCities" @change="handleCheckedCitiesChange">
|
|
|
+ <div v-for="(ele, index) in group.list" :key="index" class="list-item">
|
|
|
+ <el-checkbox v-show="toSelectClient" label="" :value="ele.tel"> </el-checkbox>
|
|
|
+ <div class="item-flex">
|
|
|
+ <img
|
|
|
+ class="photo"
|
|
|
+ :src="
|
|
|
+ ele.icon || 'https://birdseye-img.sysuimars.com/dinggou-mini/defalut-icon.png'
|
|
|
+ "
|
|
|
+ alt=""
|
|
|
+ />
|
|
|
+ <div class="item-text">
|
|
|
+ <div class="name">
|
|
|
+ <span>{{ ele.name }}</span>
|
|
|
+ <el-icon
|
|
|
+ class="icon"
|
|
|
+ @click.stop="handlePerson('edit', ele)"
|
|
|
+ color="#2199F8"
|
|
|
+ size="16"
|
|
|
+ ><Edit
|
|
|
+ /></el-icon>
|
|
|
+ </div>
|
|
|
+ <div><span class="item-title">电话:</span>{{ ele.tel }}</div>
|
|
|
+ <div><span class="item-title">地址:</span>{{ ele.address || "--" }}</div>
|
|
|
+ </div>
|
|
|
+ <!-- <div class="blue-btn" @click="toCustomOneTree(ele)">去分配</div> -->
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ </el-checkbox-group>
|
|
|
+ </el-collapse-item>
|
|
|
+ <!-- <div class="item-flex">
|
|
|
<img class="photo" :src="ele.icon || 'https://birdseye-img.sysuimars.com/dinggou-mini/defalut-icon.png'" alt="" />
|
|
|
<div class="item-text">
|
|
|
<div class="name">
|
|
@@ -14,51 +72,173 @@
|
|
|
<div><span class="item-title">地址:</span>{{ ele.address || "--" }}</div>
|
|
|
</div>
|
|
|
<div class="blue-btn" @click="toCustomOneTree(ele)">去分配</div>
|
|
|
- </div>
|
|
|
- </div>
|
|
|
+ </div> -->
|
|
|
+ </el-collapse>
|
|
|
</div>
|
|
|
-
|
|
|
+
|
|
|
<!-- 渐变主色按钮 -->
|
|
|
- <div class="center-btn" @click="toCustomPage">一键分配</div>
|
|
|
+ <div class="center-btn" v-show="!toSelectClient" @click="toCustomPage">一键分配</div>
|
|
|
+ <div class="global-wrap" v-show="toSelectClient">
|
|
|
+ <div class="global-btn" @click="handleGlobalCheckAllChange">全选</div>
|
|
|
+ </div>
|
|
|
</div>
|
|
|
<!-- 新增客户、编辑客户 -->
|
|
|
<edit-client-popup ref="editClientRef"></edit-client-popup>
|
|
|
</template>
|
|
|
|
|
|
<script setup>
|
|
|
-import { ref, reactive, onMounted } from "vue";
|
|
|
+import { ref, reactive, onMounted, watch } from "vue";
|
|
|
import { Collapse, CollapseItem, Checkbox, Popup } from "vant";
|
|
|
-import { deepClone } from "@/common/commonFun";
|
|
|
import EditClientPopup from "@/components/editClientPopup.vue";
|
|
|
import { useRouter } from "vue-router";
|
|
|
const router = useRouter();
|
|
|
+const props = defineProps({
|
|
|
+ // 是否显示选择客户
|
|
|
+ checkDistributeShow: {
|
|
|
+ type: Boolean,
|
|
|
+ default: false,
|
|
|
+ },
|
|
|
+ // 是否开始重新加载列表
|
|
|
+ startReloadList: {
|
|
|
+ type: Boolean,
|
|
|
+ default: false,
|
|
|
+ },
|
|
|
+});
|
|
|
|
|
|
// const curIndex = ref(0)
|
|
|
const handlePerson = (type, data) => {
|
|
|
- editClientRef.value.openClientPopup(type, data)
|
|
|
+ editClientRef.value.openClientPopup(type, data);
|
|
|
};
|
|
|
|
|
|
const editClientRef = ref(null);
|
|
|
|
|
|
-const defalutList = ref([]);
|
|
|
+const activeNames = ref([0]);
|
|
|
+const groupList = ref([]);
|
|
|
|
|
|
+const toSelectClient = ref(false);
|
|
|
function toCustomPage() {
|
|
|
- router.push("/layout/customTree");
|
|
|
+ toSelectClient.value = true;
|
|
|
+ // toSelectClient.value = !toSelectClient.value;
|
|
|
+ // eventBus.emit("startBoxSelect", toSelectClient.value);
|
|
|
+ emit("update:checkDistributeShow", toSelectClient.value);
|
|
|
+ // router.push("/layout/customTree");
|
|
|
}
|
|
|
|
|
|
+const handleGlobalCheckAllChange = (val) => {
|
|
|
+ if (val) {
|
|
|
+ // 全选所有项目
|
|
|
+ checkedCities.value = groupList.value.flatMap((group) => group.list.map((item) => item.tel));
|
|
|
+ } else {
|
|
|
+ // 清空所有选择
|
|
|
+ checkedCities.value = [];
|
|
|
+ }
|
|
|
+
|
|
|
+ // 更新所有分组的状态
|
|
|
+ groupList.value.forEach((_, index) => {
|
|
|
+ updateGroupCheckStatus(index);
|
|
|
+ });
|
|
|
+};
|
|
|
+
|
|
|
function toCustomOneTree(data) {
|
|
|
router.push("/layout/customTree?type=single&data=" + JSON.stringify(data));
|
|
|
}
|
|
|
|
|
|
onMounted(() => {
|
|
|
- getUserList()
|
|
|
-})
|
|
|
+ getUserList();
|
|
|
+});
|
|
|
|
|
|
function getUserList() {
|
|
|
- VE_API.manage_interface.offlineTakeList({farmId: 766}).then(({data}) => {
|
|
|
- defalutList.value = data
|
|
|
- })
|
|
|
+ VE_API.manage_interface.fetchGroupList({ farmId: 766 }).then(({ data }) => {
|
|
|
+ // defalutList.value = data
|
|
|
+ groupList.value = Object.keys(data).map((key) => {
|
|
|
+ return {
|
|
|
+ name: key,
|
|
|
+ list: data[key],
|
|
|
+ };
|
|
|
+ });
|
|
|
+ initGroupCheckStates(); // 初始化分组选择状态
|
|
|
+ });
|
|
|
}
|
|
|
+
|
|
|
+const checkedCities = ref([]);
|
|
|
+
|
|
|
+// 使用一个对象来存储每个分组的全选状态
|
|
|
+const groupCheckStates = ref({});
|
|
|
+
|
|
|
+// 初始化分组选择状态
|
|
|
+const initGroupCheckStates = () => {
|
|
|
+ groupList.value.forEach((group, index) => {
|
|
|
+ groupCheckStates.value[index] = {
|
|
|
+ checkAll: false,
|
|
|
+ isIndeterminate: false,
|
|
|
+ };
|
|
|
+ });
|
|
|
+};
|
|
|
+
|
|
|
+// 修改后的全选处理方法
|
|
|
+const handleCheckAllChange = (val, groupIndex) => {
|
|
|
+ const currentGroup = groupList.value[groupIndex];
|
|
|
+ if (val) {
|
|
|
+ // 添加当前分组的所有项到选中列表
|
|
|
+ currentGroup.list.forEach((item) => {
|
|
|
+ if (!checkedCities.value.includes(item.tel)) {
|
|
|
+ checkedCities.value.push(item.tel);
|
|
|
+ }
|
|
|
+ });
|
|
|
+ } else {
|
|
|
+ // 移除当前分组的所有项
|
|
|
+ checkedCities.value = checkedCities.value.filter(
|
|
|
+ (name) => !currentGroup.list.some((item) => item.tel === name)
|
|
|
+ );
|
|
|
+ }
|
|
|
+ updateGroupCheckStatus(groupIndex);
|
|
|
+};
|
|
|
+// 更新分组的选择状态
|
|
|
+const updateGroupCheckStatus = (groupIndex) => {
|
|
|
+ const currentGroup = groupList.value[groupIndex];
|
|
|
+ const checkedCount = currentGroup.list.filter((item) => checkedCities.value.includes(item.tel)).length;
|
|
|
+
|
|
|
+ groupCheckStates.value[groupIndex].checkAll = checkedCount === currentGroup.list.length;
|
|
|
+ groupCheckStates.value[groupIndex].isIndeterminate = checkedCount > 0 && checkedCount < currentGroup.list.length;
|
|
|
+ console.log('groupList.value', checkedCities.value);
|
|
|
+
|
|
|
+ emit("update:checkData", checkedCities.value);
|
|
|
+};
|
|
|
+
|
|
|
+// 修改 handleCheckedCitiesChange 方法
|
|
|
+const handleCheckedCitiesChange = (value) => {
|
|
|
+ // 遍历所有分组,更新每个分组的选中状态
|
|
|
+ groupList.value.forEach((group, groupIndex) => {
|
|
|
+ updateGroupCheckStatus(groupIndex);
|
|
|
+ });
|
|
|
+};
|
|
|
+
|
|
|
+function handleRightClick() {
|
|
|
+ // 点击事件处理
|
|
|
+}
|
|
|
+
|
|
|
+watch(
|
|
|
+ () => props.checkDistributeShow,
|
|
|
+ (newVal) => {
|
|
|
+ if (newVal === false) {
|
|
|
+ toSelectClient.value = false; // 如果显示选择客户,则切换到选择客户模式
|
|
|
+ // 清空所有选择
|
|
|
+ checkedCities.value = [];
|
|
|
+ initGroupCheckStates(); // 初始化分组选择状态
|
|
|
+ }
|
|
|
+ }
|
|
|
+);
|
|
|
+
|
|
|
+watch(
|
|
|
+ () => props.startReloadList,
|
|
|
+ (newVal) => {
|
|
|
+ if (newVal) {
|
|
|
+ getUserList(); // 重新加载用户列表
|
|
|
+ }
|
|
|
+ }
|
|
|
+);
|
|
|
+
|
|
|
+const emit = defineEmits(["update:checkDistributeShow", "update:checkData"]);
|
|
|
</script>
|
|
|
|
|
|
<style lang="scss" scoped>
|
|
@@ -106,8 +286,10 @@ function getUserList() {
|
|
|
}
|
|
|
.list-content {
|
|
|
width: 100%;
|
|
|
- height: 100%;
|
|
|
+ height: calc(100% - 56px);
|
|
|
overflow: auto;
|
|
|
+ padding: 0 8px;
|
|
|
+ box-sizing: border-box;
|
|
|
&.max-height {
|
|
|
height: calc(100% - 50px - 55px);
|
|
|
}
|
|
@@ -116,6 +298,17 @@ function getUserList() {
|
|
|
cursor: pointer;
|
|
|
}
|
|
|
::v-deep {
|
|
|
+ .el-collapse-item__arrow {
|
|
|
+ display: none;
|
|
|
+ }
|
|
|
+ .el-collapse-item__header .is-active {
|
|
|
+ .arrow-icon {
|
|
|
+ transform: rotate(90deg);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ .el-collapse {
|
|
|
+ border-color: transparent;
|
|
|
+ }
|
|
|
.van-cell:after,
|
|
|
.van-collapse-item--border:after,
|
|
|
.van-hairline--top-bottom:after {
|
|
@@ -164,6 +357,38 @@ function getUserList() {
|
|
|
color: #000;
|
|
|
}
|
|
|
}
|
|
|
+ .title-wrapper {
|
|
|
+ width: 100%;
|
|
|
+ display: flex;
|
|
|
+ align-items: center;
|
|
|
+ justify-content: space-between;
|
|
|
+ .arrow-icon {
|
|
|
+ transition: transform 0.3s ease;
|
|
|
+ }
|
|
|
+ &.is-active {
|
|
|
+ .arrow-icon {
|
|
|
+ transform: rotate(90deg);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ .title-r {
|
|
|
+ color: #2199f8;
|
|
|
+ font-size: 14px;
|
|
|
+ display: flex;
|
|
|
+ align-items: center;
|
|
|
+ .title-manage {
|
|
|
+ margin-right: 10px;
|
|
|
+ }
|
|
|
+ ::v-deep {
|
|
|
+ .el-checkbox {
|
|
|
+ color: #2199f8;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ .group-length {
|
|
|
+ color: rgba(0, 0, 0, 0.4);
|
|
|
+ font-size: 12px;
|
|
|
+ }
|
|
|
.list-item {
|
|
|
border-radius: 6px;
|
|
|
position: relative;
|
|
@@ -185,12 +410,12 @@ function getUserList() {
|
|
|
justify-content: space-between;
|
|
|
width: 100%;
|
|
|
.blue-btn {
|
|
|
- cursor: pointer;
|
|
|
- color: #FFFFFF;
|
|
|
- font-size: 12px;
|
|
|
- padding: 5px 15px;
|
|
|
- border-radius: 20px;
|
|
|
- background: #2199F8;
|
|
|
+ cursor: pointer;
|
|
|
+ color: #ffffff;
|
|
|
+ font-size: 12px;
|
|
|
+ padding: 5px 15px;
|
|
|
+ border-radius: 20px;
|
|
|
+ background: #2199f8;
|
|
|
}
|
|
|
}
|
|
|
.photo {
|
|
@@ -218,7 +443,7 @@ function getUserList() {
|
|
|
}
|
|
|
}
|
|
|
.item-title {
|
|
|
- color: #666666;
|
|
|
+ color: #666666;
|
|
|
}
|
|
|
}
|
|
|
}
|
|
@@ -226,23 +451,46 @@ function getUserList() {
|
|
|
margin-top: 12px;
|
|
|
}
|
|
|
}
|
|
|
-
|
|
|
+
|
|
|
.center-btn {
|
|
|
position: absolute;
|
|
|
- bottom: 64px;
|
|
|
+ bottom: 9px;
|
|
|
left: 50%;
|
|
|
transform: translateX(-50%);
|
|
|
- color: #FFFFFF;
|
|
|
+ color: #ffffff;
|
|
|
border-radius: 20px;
|
|
|
font-size: 14px;
|
|
|
padding: 7px 10px;
|
|
|
cursor: pointer;
|
|
|
border: 1px solid #fff;
|
|
|
- background: linear-gradient(180deg, #84C9FF, #2199F8);
|
|
|
+ background: linear-gradient(180deg, #84c9ff, #2199f8);
|
|
|
width: 194px;
|
|
|
box-sizing: border-box;
|
|
|
text-align: center;
|
|
|
}
|
|
|
+ .global-wrap {
|
|
|
+ width: 100%;
|
|
|
+ padding-top: 17px;
|
|
|
+ box-shadow: 4px 0 4px rgba(0, 0, 0, 0.2);
|
|
|
+ padding-top: 12px;
|
|
|
+ box-shadow: 4px 0 4px rgba(0, 0, 0, 0.2);
|
|
|
+ text-align: center;
|
|
|
+ margin: 0 auto;
|
|
|
+ padding-bottom: 11px;
|
|
|
+ display: flex;
|
|
|
+ align-items: center;
|
|
|
+ justify-content: center;
|
|
|
+ .global-btn {
|
|
|
+ height: 38px;
|
|
|
+ width: 168px;
|
|
|
+ display: flex;
|
|
|
+ align-items: center;
|
|
|
+ justify-content: center;
|
|
|
+ background: #2199f8;
|
|
|
+ color: #fff;
|
|
|
+ border-radius: 4px;
|
|
|
+ }
|
|
|
+ }
|
|
|
.list-footer {
|
|
|
position: absolute;
|
|
|
bottom: 0;
|