mirror of
https://gitee.com/krxd/shuyuan.git
synced 2026-04-08 05:15:54 +08:00
feat(erp): 增加食材分类筛选功能
- 在产品列表页面添加食材分类筛选功能 - 实现食材分类树形结构展示和选择 - 修改产品查询接口,支持按分类筛选 - 优化产品选择页面布局和样式
This commit is contained in:
9
bash.exe.stackdump
Normal file
9
bash.exe.stackdump
Normal file
@@ -0,0 +1,9 @@
|
||||
Stack trace:
|
||||
Frame Function Args
|
||||
000FFFFA2B0 00210062B0E (00210292088, 00210270E3E, 000FFFFA2B0, 000FFFF91B0)
|
||||
000FFFFA2B0 0021004846A (00000000000, 00000000000, 00000000000, 00000000000)
|
||||
000FFFFA2B0 002100484A2 (00210292139, 000FFFFA168, 000FFFFA2B0, 00000000000)
|
||||
000FFFFA2B0 002100CEE4E (00000000000, 00000000000, 00000000000, 00000000000)
|
||||
000FFFFA2B0 002100CEF75 (000FFFFA2C0, 00000000000, 00000000000, 00000000000)
|
||||
000FFFFA580 002100D0535 (000FFFFA2C0, 00000000000, 00000000000, 00000000000)
|
||||
End of stack trace
|
||||
@@ -191,4 +191,12 @@ export function deleteProduct(id : number) {
|
||||
showErrorMessage: true,
|
||||
showSuccessMessage: true,
|
||||
});
|
||||
}
|
||||
}
|
||||
/**
|
||||
* 获取食材分类tree
|
||||
* @param params
|
||||
* @returns
|
||||
*/
|
||||
export function getProductClassifyTreeList(params : Record<string, any>) {
|
||||
return request.get(`erp/product/tree`, params);
|
||||
}
|
||||
|
||||
Binary file not shown.
@@ -408,7 +408,7 @@
|
||||
return redirect({
|
||||
url: '/addon/erp/pages/product/product/product-select',
|
||||
param: {
|
||||
type: 'all'
|
||||
warehouse_id: formData.value.warehouse_id
|
||||
},
|
||||
})
|
||||
}
|
||||
|
||||
@@ -443,7 +443,7 @@
|
||||
return redirect({
|
||||
url: '/addon/erp/pages/product/product/product-select',
|
||||
param: {
|
||||
type: 'all'
|
||||
warehouse_id: formData.value.warehouse_id
|
||||
},
|
||||
})
|
||||
}
|
||||
|
||||
@@ -490,7 +490,7 @@
|
||||
return data;
|
||||
});
|
||||
|
||||
// 保存
|
||||
// 保存
|
||||
const handSave = async() => {
|
||||
if (loading.value) return
|
||||
if (!formData.value.customer_id) {
|
||||
|
||||
@@ -1,8 +1,16 @@
|
||||
<template>
|
||||
<view class="bg-[var(--page-bg-color)] min-h-[100vh]" :style="themeColor()">
|
||||
|
||||
<mescroll-body ref="mescrollRef" @init="mescrollInit" :down="{ use: false }" height="auto" @up="getListFn"
|
||||
:top="mescrollTop">
|
||||
<view class="classify-box">
|
||||
<u-form labelPosition="left" :model="productQuery" errorType='toast' ref="formRef" labelWidth="140rpx">
|
||||
<u-form-item label="食材分类" prop="type_name" required @click="showPicker">
|
||||
<u-input fontSize="28rpx" v-model.trim="productQuery.type_name" readonly clearable
|
||||
placeholderStyle="color: #888" placeholder="请选择分类" suffixIcon="arrow-down-fill"
|
||||
suffixIconStyle="font-size: 22rpx;color: #c0c4cc" />
|
||||
</u-form-item>
|
||||
</u-form>
|
||||
</view>
|
||||
<mescroll-body ref="mescrollRef" @init="mescrollInit" :down="{ use: false,auto:false }" :up="{ auto:false }"
|
||||
height="auto" @up="getListFn" :top="mescrollTop">
|
||||
<view class="sidebar-margin body-bottom" v-if="productList.length">
|
||||
<view class="mb-[15rpx]" v-for="(item,index) in productList" :key="item.id">
|
||||
|
||||
@@ -46,8 +54,9 @@
|
||||
<view><up-button :text="t('info')" size="mini"
|
||||
@click="redirect({ url: '/addon/erp/pages/product/product/detail',param:{id: item.id} })"></up-button>
|
||||
</view>
|
||||
<view v-if="hasPermission('erp_product_add')"><up-button type="error" @click="hanldeDelete(item.id)" :text="t('delete')"
|
||||
size="mini"></up-button></view>
|
||||
<view v-if="hasPermission('erp_product_add')"><up-button type="error"
|
||||
@click="hanldeDelete(item.id)" :text="t('delete')" size="mini"></up-button>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
@@ -66,7 +75,8 @@
|
||||
<u-icon size="30" color="#fff" name="plus-circle-fill"></u-icon>
|
||||
</up-button>
|
||||
</view>
|
||||
|
||||
<ba-tree-picker ref="treePicker" :multiple='false' @select-change="selectChange" title="选择食材分类"
|
||||
:localdata="productClassifyTreeList" valueKey="id" textKey="name" childrenKey="children" />
|
||||
</view>
|
||||
</template>
|
||||
|
||||
@@ -75,10 +85,11 @@
|
||||
import { topTabar } from '@/utils/topTabbar';
|
||||
import { t } from '@/locale';
|
||||
import { redirect, pxToRpx } from '@/utils/common';
|
||||
import baTreePicker from "@/components/ba-tree-picker/ba-tree-picker.vue"
|
||||
import MescrollBody from '@/components/mescroll/mescroll-body/mescroll-body.vue';
|
||||
import MescrollEmpty from '@/components/mescroll/mescroll-empty/mescroll-empty.vue';
|
||||
import useMescroll from '@/components/mescroll/hooks/useMescroll.js';
|
||||
import { getProductList, deleteProduct } from '@/addon/erp/api/product';
|
||||
import { getProductList, deleteProduct, getProductClassifyTreeList } from '@/addon/erp/api/product';
|
||||
import { onShow, onPageScroll, onReachBottom } from '@dcloudio/uni-app';
|
||||
import usePermission from '@/utils/usePermission'
|
||||
const { hasPermission } = usePermission()
|
||||
@@ -97,10 +108,15 @@
|
||||
const mescrollTop = "20rpx"
|
||||
|
||||
const productList = ref<Array<any>>([]),
|
||||
loading = ref<boolean>(true),
|
||||
listLoading = ref<boolean>(true),
|
||||
loading = ref<boolean>(false),
|
||||
listLoading = ref<boolean>(false),
|
||||
mescrollRef = ref(null);
|
||||
|
||||
const productClassifyTreeList = ref([])
|
||||
const treePicker = ref<any>(null)
|
||||
const productQuery = ref<any>({
|
||||
type_name: '',
|
||||
type_id: '',
|
||||
})
|
||||
interface mescrollStructure {
|
||||
num : number,
|
||||
size : number,
|
||||
@@ -112,7 +128,8 @@
|
||||
listLoading.value = true;
|
||||
let data : Object = {
|
||||
page: mescroll.num,
|
||||
limit: mescroll.size
|
||||
limit: mescroll.size,
|
||||
product_type_id: productQuery.value.type_id
|
||||
};
|
||||
getProductList(data).then((res : any) => {
|
||||
let newArr = res.data.data;
|
||||
@@ -134,7 +151,27 @@
|
||||
mescroll.endErr(); // 请求失败, 结束加载
|
||||
})
|
||||
}
|
||||
|
||||
// 获取食材分类
|
||||
const getProductClassifyTree = () => {
|
||||
getProductClassifyTreeList({}).then((res : any) => {
|
||||
productClassifyTreeList.value = res.data
|
||||
}).catch(err => {
|
||||
// 如果是4001,没有绑定企业账号,强制跳转绑定
|
||||
if (err.code == 4001) {
|
||||
redirect({ url: '/addon/erp/pages/member/bind' })
|
||||
}
|
||||
})
|
||||
}
|
||||
// 显示选择器
|
||||
const showPicker = () => {
|
||||
treePicker.value._show();
|
||||
}
|
||||
//监听选择(ids为数组)
|
||||
const selectChange = (ids : any, names : any) => {
|
||||
productQuery.value.type_id = ids.length > 0 ? ids[0] : ''
|
||||
productQuery.value.type_name = names
|
||||
getMescroll().resetUpScroll()
|
||||
}
|
||||
// 删除
|
||||
const del_id = ref<number>(0);
|
||||
const hanldeDelete = (id : number) => {
|
||||
@@ -155,7 +192,13 @@
|
||||
show.value = false;
|
||||
}).catch(() => { });
|
||||
}
|
||||
getProductClassifyTree()
|
||||
</script>
|
||||
|
||||
<style>
|
||||
<style scoped>
|
||||
.classify-box {
|
||||
padding: 20rpx 40rpx;
|
||||
box-sizing: border-box;
|
||||
background: #fff;
|
||||
}
|
||||
</style>
|
||||
@@ -1,56 +1,65 @@
|
||||
<template>
|
||||
<view class="min-h-[100vh]" :style="themeColor()">
|
||||
|
||||
<mescroll-body ref="mescrollRef" @init="mescrollInit" :down="{ use: false }" height="auto" @up="getListFn"
|
||||
:top="mescrollTop">
|
||||
<view class="classify-box">
|
||||
<u-form labelPosition="left" :model="productQuery" errorType='toast' ref="formRef"
|
||||
labelWidth="140rpx">
|
||||
<u-form-item label="食材分类" prop="type_name" required @click="showPicker">
|
||||
<u-input fontSize="28rpx" v-model.trim="productQuery.type_name" readonly clearable
|
||||
placeholderStyle="color: #888" placeholder="请选择分类" suffixIcon="arrow-down-fill"
|
||||
suffixIconStyle="font-size: 22rpx;color: #c0c4cc" />
|
||||
</u-form-item>
|
||||
</u-form>
|
||||
</view>
|
||||
<mescroll-body ref="mescrollRef" @init="mescrollInit" :down="{ use: false,auto:false }" :up="{ auto:false }"
|
||||
height="auto" @up="getListFn" :top="mescrollTop">
|
||||
<view class="sidebar-margin body-bottom" v-if="productList.length">
|
||||
<u-checkbox-group class="w-full" v-model="checkProductList" placement="column">
|
||||
<view class="mb-[15rpx]" v-for="(item,index) in productList" :key="index">
|
||||
<up-collapse class="bg-[#ffffff] rounded-10rpx">
|
||||
<up-collapse-item>
|
||||
<template #title>
|
||||
<view class="flex" style="display: flex;align-items: center;">
|
||||
<u-checkbox :name="item"></u-checkbox>
|
||||
<view>{{item.product?.name}}</view>
|
||||
<up-collapse class="bg-[#ffffff] rounded-10rpx">
|
||||
<up-collapse-item>
|
||||
<template #title>
|
||||
<view class="flex" style="display: flex;align-items: center;">
|
||||
<u-checkbox :name="item"></u-checkbox>
|
||||
<view>{{item.product?.name}}</view>
|
||||
</view>
|
||||
</template>
|
||||
<view class="body">
|
||||
<view class="flex justify-start flex-col p-[20rpx]">
|
||||
<view class="flex justify-start mb-[18rpx] text-[12px] text-[#6a6a6a]">
|
||||
食材编号:<text
|
||||
class="ml-[20rpx] text-[var(--primary-color)]">{{item.product?.code}}</text>
|
||||
</view>
|
||||
</template>
|
||||
<view class="body">
|
||||
<view class="flex justify-start flex-col p-[20rpx]">
|
||||
<view class="flex justify-start mb-[18rpx] text-[12px] text-[#6a6a6a]">
|
||||
食材编号:<text
|
||||
class="ml-[20rpx] text-[var(--primary-color)]">{{item.product?.code}}</text>
|
||||
</view>
|
||||
<view class="flex justify-start mb-[18rpx] text-[12px] text-[#6a6a6a]">
|
||||
食材类型:<text
|
||||
class="ml-[20rpx] text-[var(--primary-color)]">{{item.product?.productType?.name}}</text>
|
||||
</view>
|
||||
<view class="flex justify-start mb-[18rpx] text-[12px] text-[#6a6a6a]">
|
||||
食材规格:<text
|
||||
class="ml-[20rpx] text-[var(--primary-color)]">{{item.product?.spec}}</text>
|
||||
</view>
|
||||
<view class="flex justify-start mb-[18rpx] text-[12px] text-[#6a6a6a]">
|
||||
批次号:<text
|
||||
class="ml-[20rpx] text-[var(--primary-color)]">{{item.batch_number}}</text>
|
||||
</view>
|
||||
<view class="flex justify-start mb-[18rpx] text-[12px] text-[#6a6a6a]">
|
||||
库存数量:<text
|
||||
class="ml-[20rpx] text-[var(--primary-color)]">{{item.inventory}}</text>
|
||||
</view>
|
||||
<view class="flex justify-start mb-[18rpx] text-[12px] text-[#6a6a6a]">
|
||||
食材单位:<text
|
||||
class="ml-[20rpx] text-[var(--primary-color)]">{{item.product?.productUnit?.name}}</text>
|
||||
</view>
|
||||
<view class="flex justify-start mb-[18rpx] text-[12px] text-[#6a6a6a]">
|
||||
供应商:<text
|
||||
class="ml-[20rpx] text-[var(--primary-color)]">{{item.supplier?.name}}</text>
|
||||
</view>
|
||||
<view class="flex justify-start mb-[18rpx] text-[12px] text-[#6a6a6a]">
|
||||
创建时间:<text
|
||||
class="ml-[20rpx] text-[var(--primary-color)]">{{item.create_time}}</text>
|
||||
</view>
|
||||
<view class="flex justify-start mb-[18rpx] text-[12px] text-[#6a6a6a]">
|
||||
食材类型:<text
|
||||
class="ml-[20rpx] text-[var(--primary-color)]">{{item.product?.productType?.name}}</text>
|
||||
</view>
|
||||
<view class="flex justify-start mb-[18rpx] text-[12px] text-[#6a6a6a]">
|
||||
食材规格:<text
|
||||
class="ml-[20rpx] text-[var(--primary-color)]">{{item.product?.spec}}</text>
|
||||
</view>
|
||||
<view class="flex justify-start mb-[18rpx] text-[12px] text-[#6a6a6a]">
|
||||
批次号:<text
|
||||
class="ml-[20rpx] text-[var(--primary-color)]">{{item.batch_number}}</text>
|
||||
</view>
|
||||
<view class="flex justify-start mb-[18rpx] text-[12px] text-[#6a6a6a]">
|
||||
库存数量:<text
|
||||
class="ml-[20rpx] text-[var(--primary-color)]">{{item.inventory}}</text>
|
||||
</view>
|
||||
<view class="flex justify-start mb-[18rpx] text-[12px] text-[#6a6a6a]">
|
||||
食材单位:<text
|
||||
class="ml-[20rpx] text-[var(--primary-color)]">{{item.product?.productUnit?.name}}</text>
|
||||
</view>
|
||||
<view class="flex justify-start mb-[18rpx] text-[12px] text-[#6a6a6a]">
|
||||
供应商:<text
|
||||
class="ml-[20rpx] text-[var(--primary-color)]">{{item.supplier?.name}}</text>
|
||||
</view>
|
||||
<view class="flex justify-start mb-[18rpx] text-[12px] text-[#6a6a6a]">
|
||||
创建时间:<text
|
||||
class="ml-[20rpx] text-[var(--primary-color)]">{{item.create_time}}</text>
|
||||
</view>
|
||||
</view>
|
||||
</up-collapse-item>
|
||||
</view>
|
||||
</up-collapse-item>
|
||||
</up-collapse>
|
||||
</view>
|
||||
</u-checkbox-group>
|
||||
@@ -62,7 +71,8 @@
|
||||
<view class="sidebar-margin mt-[20rpx] body-bottom">
|
||||
<u-button @click="onConfirm" type="primary" shape="circle" text="确认选择"></u-button>
|
||||
</view>
|
||||
|
||||
<ba-tree-picker ref="treePicker" :multiple='false' @select-change="selectChange" title="选择食材分类"
|
||||
:localdata="productClassifyTreeList" valueKey="id" textKey="name" childrenKey="children" />
|
||||
</view>
|
||||
</template>
|
||||
|
||||
@@ -71,22 +81,26 @@
|
||||
import { topTabar } from '@/utils/topTabbar';
|
||||
import { t } from '@/locale';
|
||||
import { redirect, pxToRpx } from '@/utils/common';
|
||||
import baTreePicker from "@/components/ba-tree-picker/ba-tree-picker.vue"
|
||||
import MescrollBody from '@/components/mescroll/mescroll-body/mescroll-body.vue';
|
||||
import MescrollEmpty from '@/components/mescroll/mescroll-empty/mescroll-empty.vue';
|
||||
import useMescroll from '@/components/mescroll/hooks/useMescroll.js';
|
||||
import { getProductList,getProductListByWarehouseNew} from '@/addon/erp/api/product';
|
||||
import { getProductListByWarehouseNew, getProductClassifyTreeList } from '@/addon/erp/api/product';
|
||||
import { onLoad, onPageScroll, onReachBottom } from '@dcloudio/uni-app';
|
||||
|
||||
const { downCallback, mescrollInit, getMescroll } = useMescroll(onPageScroll, onReachBottom);
|
||||
|
||||
const productClassifyTreeList = ref([])
|
||||
|
||||
const checkProductList = ref<any[]>([]);
|
||||
const queryType = ref<any>('all'); // 查询方式 all 获取全部食材, warehouse 根据仓库ID ,获取对应的食材
|
||||
const warehouse_id = ref<any>(undefined); // 仓库Id
|
||||
const supplier_id= ref<any>(undefined); // 供应商Id
|
||||
const supplier_id = ref<any>(undefined); // 供应商Id
|
||||
const treePicker = ref<any>(null)
|
||||
const productQuery = ref<any>({
|
||||
type_name:'',
|
||||
type_id:'',
|
||||
})
|
||||
// 页面加载
|
||||
onLoad((option : any) => {
|
||||
queryType.value = option.type ? option.type : '';
|
||||
warehouse_id.value = option.warehouse_id ? option.warehouse_id : undefined
|
||||
supplier_id.value = option.supplier_id ? option.supplier_id : undefined
|
||||
})
|
||||
@@ -95,8 +109,8 @@
|
||||
const mescrollTop = "20rpx"
|
||||
|
||||
const productList = ref<Array<any>>([]),
|
||||
loading = ref<boolean>(true),
|
||||
listLoading = ref<boolean>(true),
|
||||
loading = ref<boolean>(false),
|
||||
listLoading = ref<boolean>(false),
|
||||
mescrollRef = ref(null);
|
||||
|
||||
interface mescrollStructure {
|
||||
@@ -106,18 +120,28 @@
|
||||
[propName : string] : any
|
||||
}
|
||||
|
||||
// 获取食材分类
|
||||
const getProductClassifyTree = () => {
|
||||
getProductClassifyTreeList({}).then((res : any) => {
|
||||
productClassifyTreeList.value = res.data
|
||||
}).catch(err => {
|
||||
// 如果是4001,没有绑定企业账号,强制跳转绑定
|
||||
if (err.code == 4001) {
|
||||
redirect({ url: '/addon/erp/pages/member/bind' })
|
||||
}
|
||||
})
|
||||
}
|
||||
const getListFn = (mescroll : mescrollStructure) => {
|
||||
listLoading.value = true;
|
||||
loading.value = true;
|
||||
let data : Object = {
|
||||
page: mescroll.num,
|
||||
limit: mescroll.size,
|
||||
warehouse_id: warehouse_id.value,
|
||||
supplier_id: supplier_id.value
|
||||
supplier_id: supplier_id.value,
|
||||
product_type_id: productQuery.value.type_id
|
||||
};
|
||||
let getDataApi =
|
||||
queryType.value == "all" ? getProductList : getProductListByWarehouseNew;
|
||||
|
||||
getDataApi(data).then((res : any) => {
|
||||
getProductListByWarehouseNew(data).then((res : any) => {
|
||||
let newArr = res.data.data;
|
||||
mescroll.endSuccess(newArr.length);
|
||||
//设置列表数据
|
||||
@@ -137,7 +161,16 @@
|
||||
mescroll.endErr(); // 请求失败, 结束加载
|
||||
})
|
||||
}
|
||||
|
||||
// 显示选择器
|
||||
const showPicker = () => {
|
||||
treePicker.value._show();
|
||||
}
|
||||
//监听选择(ids为数组)
|
||||
const selectChange = (ids : any, names : any) => {
|
||||
productQuery.value.type_id = ids.length > 0 ? ids[0] : ''
|
||||
productQuery.value.type_name = names
|
||||
getMescroll().resetUpScroll()
|
||||
}
|
||||
// 确认选择
|
||||
const onConfirm = () => {
|
||||
uni.$emit('choose_product-out', checkProductList.value);
|
||||
@@ -146,7 +179,12 @@
|
||||
delta: 1
|
||||
});
|
||||
}
|
||||
getProductClassifyTree()
|
||||
</script>
|
||||
|
||||
<style>
|
||||
<style scoped>
|
||||
.classify-box {
|
||||
padding: 20rpx 40rpx;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
</style>
|
||||
@@ -1,48 +1,58 @@
|
||||
<template>
|
||||
<view class="min-h-[100vh]" :style="themeColor()">
|
||||
<mescroll-body ref="mescrollRef" @init="mescrollInit" :down="{ use: false }" height="auto" @up="getListFn"
|
||||
:top="mescrollTop">
|
||||
<view class="classify-box">
|
||||
<u-form labelPosition="left" :model="productQuery" errorType='toast' ref="formRef"
|
||||
labelWidth="140rpx">
|
||||
<u-form-item label="食材分类" prop="type_name" required @click="showPicker">
|
||||
<u-input fontSize="28rpx" v-model.trim="productQuery.type_name" readonly clearable
|
||||
placeholderStyle="color: #888" placeholder="请选择分类" suffixIcon="arrow-down-fill"
|
||||
suffixIconStyle="font-size: 22rpx;color: #c0c4cc" />
|
||||
</u-form-item>
|
||||
</u-form>
|
||||
</view>
|
||||
<mescroll-body ref="mescrollRef" @init="mescrollInit" :down="{ use: false,auto:false }" :up="{ auto:false }"
|
||||
height="auto" @up="getListFn" :top="mescrollTop">
|
||||
<view class="sidebar-margin body-bottom" v-if="productList.length">
|
||||
<u-checkbox-group class="w-full" v-model="checkProductList" placement="column">
|
||||
<view class="mb-[15rpx]" v-for="(item,index) in productList" :key="index">
|
||||
<up-collapse class="bg-[#ffffff] rounded-10rpx">
|
||||
<up-collapse-item>
|
||||
<template #title>
|
||||
<view class="flex" style="display: flex;align-items: center;">
|
||||
<u-checkbox :name="item"></u-checkbox>
|
||||
<view>{{item.name}}</view>
|
||||
</view>
|
||||
</template>
|
||||
<view class="body">
|
||||
<view class="flex justify-start flex-col p-[20rpx]">
|
||||
<view class="flex justify-start mb-[18rpx] text-[12px] text-[#6a6a6a]">
|
||||
{{ t('code') }}:<text
|
||||
class="ml-[20rpx] text-[var(--primary-color)]">{{item.code}}</text>
|
||||
</view>
|
||||
<view class="flex justify-start mb-[18rpx] text-[12px] text-[#6a6a6a]">
|
||||
{{ t('productTypeId') }}:<text
|
||||
class="ml-[20rpx] text-[var(--primary-color)]">{{item.productType?.name}}</text>
|
||||
</view>
|
||||
<view class="flex justify-start mb-[18rpx] text-[12px] text-[#6a6a6a]">
|
||||
{{ t('spec') }}:<text
|
||||
class="ml-[20rpx] text-[var(--primary-color)]">{{item.spec}}</text>
|
||||
</view>
|
||||
<view class="flex justify-start mb-[18rpx] text-[12px] text-[#6a6a6a]">
|
||||
{{ t('inventory') }}:<text
|
||||
class="ml-[20rpx] text-[var(--primary-color)]">{{item.inventory}}</text>
|
||||
</view>
|
||||
<view class="flex justify-start mb-[18rpx] text-[12px] text-[#6a6a6a]">
|
||||
{{ t('productUnitId') }}:<text
|
||||
class="ml-[20rpx] text-[var(--primary-color)]">{{item.productUnit?.name}}</text>
|
||||
</view>
|
||||
<view class="flex justify-start mb-[18rpx] text-[12px] text-[#6a6a6a]">
|
||||
{{ t('createTime') }}:<text
|
||||
class="ml-[20rpx] text-[var(--primary-color)]">{{item.create_time}}</text>
|
||||
</view>
|
||||
|
||||
</view>
|
||||
<up-collapse class="bg-[#ffffff] rounded-10rpx">
|
||||
<up-collapse-item>
|
||||
<template #title>
|
||||
<view class="flex" style="display: flex;align-items: center;">
|
||||
<u-checkbox :name="item"></u-checkbox>
|
||||
<view>{{item.name}}</view>
|
||||
</view>
|
||||
</up-collapse-item>
|
||||
</template>
|
||||
<view class="body">
|
||||
<view class="flex justify-start flex-col p-[20rpx]">
|
||||
<view class="flex justify-start mb-[18rpx] text-[12px] text-[#6a6a6a]">
|
||||
{{ t('code') }}:<text
|
||||
class="ml-[20rpx] text-[var(--primary-color)]">{{item.code}}</text>
|
||||
</view>
|
||||
<view class="flex justify-start mb-[18rpx] text-[12px] text-[#6a6a6a]">
|
||||
{{ t('productTypeId') }}:<text
|
||||
class="ml-[20rpx] text-[var(--primary-color)]">{{item.productType?.name}}</text>
|
||||
</view>
|
||||
<view class="flex justify-start mb-[18rpx] text-[12px] text-[#6a6a6a]">
|
||||
{{ t('spec') }}:<text
|
||||
class="ml-[20rpx] text-[var(--primary-color)]">{{item.spec}}</text>
|
||||
</view>
|
||||
<view class="flex justify-start mb-[18rpx] text-[12px] text-[#6a6a6a]">
|
||||
{{ t('inventory') }}:<text
|
||||
class="ml-[20rpx] text-[var(--primary-color)]">{{item.inventory}}</text>
|
||||
</view>
|
||||
<view class="flex justify-start mb-[18rpx] text-[12px] text-[#6a6a6a]">
|
||||
{{ t('productUnitId') }}:<text
|
||||
class="ml-[20rpx] text-[var(--primary-color)]">{{item.productUnit?.name}}</text>
|
||||
</view>
|
||||
<view class="flex justify-start mb-[18rpx] text-[12px] text-[#6a6a6a]">
|
||||
{{ t('createTime') }}:<text
|
||||
class="ml-[20rpx] text-[var(--primary-color)]">{{item.create_time}}</text>
|
||||
</view>
|
||||
|
||||
</view>
|
||||
</view>
|
||||
</up-collapse-item>
|
||||
</up-collapse>
|
||||
</view>
|
||||
</u-checkbox-group>
|
||||
@@ -54,7 +64,8 @@
|
||||
<view class="sidebar-margin mt-[20rpx] body-bottom">
|
||||
<u-button @click="onConfirm" type="primary" shape="circle" :text="t('confirmChoose')"></u-button>
|
||||
</view>
|
||||
|
||||
<ba-tree-picker ref="treePicker" :multiple='false' @select-change="selectChange" title="选择食材分类"
|
||||
:localdata="productClassifyTreeList" valueKey="id" textKey="name" childrenKey="children" />
|
||||
</view>
|
||||
</template>
|
||||
|
||||
@@ -63,18 +74,24 @@
|
||||
import { topTabar } from '@/utils/topTabbar';
|
||||
import { t } from '@/locale';
|
||||
import { redirect, pxToRpx } from '@/utils/common';
|
||||
import baTreePicker from "@/components/ba-tree-picker/ba-tree-picker.vue"
|
||||
import MescrollBody from '@/components/mescroll/mescroll-body/mescroll-body.vue';
|
||||
import MescrollEmpty from '@/components/mescroll/mescroll-empty/mescroll-empty.vue';
|
||||
import useMescroll from '@/components/mescroll/hooks/useMescroll.js';
|
||||
import { getProductList, getProductListByWarehouse,getProductListByWarehouseNew} from '@/addon/erp/api/product';
|
||||
import { getProductListByWarehouse, getProductClassifyTreeList } from '@/addon/erp/api/product';
|
||||
import { onLoad, onPageScroll, onReachBottom } from '@dcloudio/uni-app';
|
||||
|
||||
const { downCallback, mescrollInit, getMescroll } = useMescroll(onPageScroll, onReachBottom);
|
||||
|
||||
|
||||
const productClassifyTreeList = ref<any[]>([]);
|
||||
const checkProductList = ref<any[]>([]);
|
||||
const queryType = ref<any>('all'); // 查询方式 all 获取全部食材, warehouse 根据仓库ID ,获取对应的食材
|
||||
const warehouse_id = ref<any>(undefined); // 仓库Id
|
||||
const treePicker = ref<any>(null)
|
||||
const productQuery = ref<any>({
|
||||
type_name:'',
|
||||
type_id:'',
|
||||
})
|
||||
// 页面加载
|
||||
onLoad((option : any) => {
|
||||
queryType.value = option.type ? option.type : '';
|
||||
@@ -83,8 +100,8 @@
|
||||
const mescrollTop = "20rpx"
|
||||
|
||||
const productList = ref<Array<any>>([]),
|
||||
loading = ref<boolean>(true),
|
||||
listLoading = ref<boolean>(true),
|
||||
loading = ref<boolean>(false),
|
||||
listLoading = ref<boolean>(false),
|
||||
mescrollRef = ref(null);
|
||||
|
||||
interface mescrollStructure {
|
||||
@@ -94,17 +111,28 @@
|
||||
[propName : string] : any
|
||||
}
|
||||
|
||||
// 获取食材分类
|
||||
const getProductClassifyTree = () => {
|
||||
getProductClassifyTreeList({}).then((res : any) => {
|
||||
productClassifyTreeList.value = res.data
|
||||
}).catch(err => {
|
||||
// 如果是4001,没有绑定企业账号,强制跳转绑定
|
||||
if (err.code == 4001) {
|
||||
redirect({ url: '/addon/erp/pages/member/bind' })
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
const getListFn = (mescroll : mescrollStructure) => {
|
||||
listLoading.value = true;
|
||||
loading.value = true;
|
||||
let data : Object = {
|
||||
page: mescroll.num,
|
||||
limit: mescroll.size,
|
||||
warehouse_id: warehouse_id.value
|
||||
warehouse_id: warehouse_id.value,
|
||||
product_type_id: productQuery.value.type_id
|
||||
};
|
||||
let getDataApi =
|
||||
queryType.value == "all" ? getProductList :queryType.value == "new" ?getProductListByWarehouseNew: getProductListByWarehouse;
|
||||
|
||||
getDataApi(data).then((res : any) => {
|
||||
getProductListByWarehouse(data).then((res : any) => {
|
||||
let newArr = res.data.data;
|
||||
mescroll.endSuccess(newArr.length);
|
||||
//设置列表数据
|
||||
@@ -124,7 +152,16 @@
|
||||
mescroll.endErr(); // 请求失败, 结束加载
|
||||
})
|
||||
}
|
||||
|
||||
// 显示选择器
|
||||
const showPicker = () => {
|
||||
treePicker.value._show();
|
||||
}
|
||||
//监听选择(ids为数组)
|
||||
const selectChange = (ids : any, names : any) => {
|
||||
productQuery.value.type_id = ids.length > 0 ? ids[0] : ''
|
||||
productQuery.value.type_name = names
|
||||
getMescroll().resetUpScroll()
|
||||
}
|
||||
// 确认选择
|
||||
const onConfirm = () => {
|
||||
uni.$emit('choose_product', checkProductList.value);
|
||||
@@ -133,7 +170,12 @@
|
||||
delta: 1
|
||||
});
|
||||
}
|
||||
getProductClassifyTree()
|
||||
</script>
|
||||
|
||||
<style>
|
||||
<style scoped>
|
||||
.classify-box {
|
||||
padding: 20rpx 40rpx;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
</style>
|
||||
@@ -328,7 +328,6 @@
|
||||
return redirect({
|
||||
url: '/addon/erp/pages/product/product/out-product-select',
|
||||
param: {
|
||||
type: 'warehouse',
|
||||
warehouse_id: formData.value.warehouse_id,
|
||||
supplier_id: formData.value.supplier_id,
|
||||
},
|
||||
|
||||
124
src/components/ba-tree-picker/README.md
Normal file
124
src/components/ba-tree-picker/README.md
Normal file
@@ -0,0 +1,124 @@
|
||||
## 树形层级选择器
|
||||
### 简介
|
||||
为统一样式而生,树形层级选择器,picker弹窗形式的,样式和比例参照uniapp的picker和uni-data-picker组件
|
||||
* 支持单选、多选、父级选择,当然也支持单层选择
|
||||
* 支持Object对象属性自定义映射
|
||||
* 支持显示全部选中、部分选中、未选中三种状态
|
||||
* 支持快速自定义简单样式(分割线、按钮、标题、对齐等),深入样式可复写css
|
||||
|
||||
### 使用方法
|
||||
在 `script` 中引入组件
|
||||
``` javascript
|
||||
import baTreePicker from "@/components/ba-tree-picker/ba-tree-picker.vue"
|
||||
export default {
|
||||
components: {
|
||||
baTreePicker
|
||||
}
|
||||
```
|
||||
在 `template` 中使用组件
|
||||
``` javascript
|
||||
<ba-tree-picker ref="treePicker" :multiple='false' @select-change="selectChange" title="选择城市"
|
||||
:localdata="listData" valueKey="value" textKey="label" childrenKey="children" />
|
||||
```
|
||||
在 `script` 中定义打开方法,和选择监听
|
||||
``` javascript
|
||||
methods: {
|
||||
// 显示选择器
|
||||
showPicker() {
|
||||
this.$refs.treePicker._show();
|
||||
},
|
||||
//监听选择(ids为数组)
|
||||
selectChange(ids, names) {
|
||||
console.log(ids, names)
|
||||
}
|
||||
}
|
||||
```
|
||||
在 `template` 中调用打开
|
||||
``` javascript
|
||||
<view @click="showPicker">调用选择器</view>
|
||||
```
|
||||
|
||||
### 属性
|
||||
|属性名|类型|默认值|说明|
|
||||
|:-|:-:|:--:|-:|
|
||||
|localdata|Array|[]|源数据,目前支持tree结构,后续会考虑支持扁平化结构|
|
||||
|valueKey|String|id|指定 Object 中 key 的值作为节点数据id|
|
||||
|textKey|String|name|指定 Object 中 key 的值作为节点显示内容|
|
||||
|childrenKey|String|children|指定 Object 中 key 的值作为节点子集|
|
||||
|multiple|Boolean|false|是否多选,默认单选|
|
||||
|selectParent|Boolean|true|是否可以选父级,默认可以|
|
||||
|title|String| |标题|
|
||||
|titleColor|String||标题颜色|
|
||||
|confirmColor|String|#0055ff|确定按钮颜色|
|
||||
|cancelColor|String|#757575|取消按钮颜色|
|
||||
|switchColor|String|#666|节点切换图标颜色|
|
||||
|border|Boolean|false|是否有分割线,默认无|
|
||||
|
||||
|
||||
|
||||
### 数据格式
|
||||
|
||||
注意:必须有id、name(id可通过valueKey来配置为其它键值,如value)字段,且唯一
|
||||
|
||||
``` json
|
||||
[
|
||||
{
|
||||
id: 1,
|
||||
name: '公司1',
|
||||
children: [{
|
||||
id: 11,
|
||||
name: '研发部',
|
||||
children: [{
|
||||
id: 111,
|
||||
name: '张三',
|
||||
|
||||
},{
|
||||
id: 112,
|
||||
name: '李四',
|
||||
|
||||
}]
|
||||
},{
|
||||
id: 12,
|
||||
name: '综合部',
|
||||
|
||||
} ]
|
||||
},
|
||||
{
|
||||
id: 2,
|
||||
name: '公司2',
|
||||
children: [{
|
||||
id: 21,
|
||||
name: '研发部',
|
||||
|
||||
},{
|
||||
id: 22,
|
||||
name: '综合部',
|
||||
|
||||
},{
|
||||
id: 23,
|
||||
name: '财务部',
|
||||
|
||||
}, ]
|
||||
},
|
||||
{
|
||||
id: 3,
|
||||
name: '公司3'
|
||||
},
|
||||
{
|
||||
id: 4,
|
||||
name: '公司4',
|
||||
children: [{
|
||||
id: 41,
|
||||
name: '研发部',
|
||||
|
||||
}]
|
||||
}
|
||||
]
|
||||
```
|
||||
</details>
|
||||
|
||||
### 方法
|
||||
|方法名|参数|默认值|说明|
|
||||
|:-|:-:|:--:|-:|
|
||||
|_show()| | |显示选择器|
|
||||
|_hide()| | |隐藏选择器|
|
||||
624
src/components/ba-tree-picker/ba-tree-picker.vue
Normal file
624
src/components/ba-tree-picker/ba-tree-picker.vue
Normal file
@@ -0,0 +1,624 @@
|
||||
<!-- 树形层级选择器-->
|
||||
<!-- 1、支持单选、多选 -->
|
||||
<template>
|
||||
<view>
|
||||
<view class="tree-cover" :class="{'show':showDialog}" @tap="_cancel"></view>
|
||||
<view class="tree-dialog" :class="{'show':showDialog}">
|
||||
<view class="tree-bar">
|
||||
<view class="tree-bar-cancel" :style="{'color':cancelColor}" hover-class="hover-c" @tap="_cancel">取消
|
||||
</view>
|
||||
<view class="tree-bar-title" :style="{'color':titleColor}">{{title}}</view>
|
||||
<view class="tree-bar-confirm" :style="{'color':confirmColor}" hover-class="hover-c" @tap="_confirm">
|
||||
{{multiple?'确定':''}}
|
||||
</view>
|
||||
</view>
|
||||
<view class="tree-view">
|
||||
<scroll-view class="tree-list" :scroll-y="true">
|
||||
<block v-for="(item, index) in treeList" :key="index">
|
||||
<view class="tree-item" :style="[{
|
||||
paddingLeft: item.level*30 + 'rpx'
|
||||
}]" :class="{
|
||||
itemBorder: border === true,
|
||||
show: item.isShow
|
||||
}">
|
||||
<view class="item-label">
|
||||
<view class="item-icon uni-inline-item" @tap.stop="_onItemSwitch(item, index)">
|
||||
<view v-if="!item.isLastLevel&&item.isShowChild" class="switch-on"
|
||||
:style="{'border-left-color':switchColor}">
|
||||
</view>
|
||||
<view v-else-if="!item.isLastLevel&&!item.isShowChild" class="switch-off"
|
||||
:style="{'border-top-color':switchColor}">
|
||||
</view>
|
||||
<view v-else class="item-last-dot" :style="{'border-top-color':switchColor}">
|
||||
</view>
|
||||
</view>
|
||||
<view class="uni-flex-item uni-inline-item" @tap.stop="_onItemSelect(item, index)">
|
||||
<view class="item-name"> {{item.name+(item.childCount?"("+item.childCount+")":'')}}
|
||||
</view>
|
||||
<view class="item-check" v-if="selectParent?true:item.isLastLevel">
|
||||
<view class="item-check-yes" v-if="item.checkStatus==1"
|
||||
:class="{'radio':!multiple}" :style="{'border-color':confirmColor}">
|
||||
<view class="item-check-yes-part"
|
||||
:style="{'background-color':confirmColor}">
|
||||
</view>
|
||||
</view>
|
||||
<view class="item-check-yes" v-else-if="item.checkStatus==2"
|
||||
:class="{'radio':!multiple}" :style="{'border-color':confirmColor}">
|
||||
<view class="item-check-yes-all" :style="{'background-color':confirmColor}">
|
||||
</view>
|
||||
</view>
|
||||
<view class="item-check-no" v-else :class="{'radio':!multiple}"
|
||||
:style="{'border-color':confirmColor}"></view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
</view>
|
||||
</block>
|
||||
</scroll-view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
emits: ['select-change'],
|
||||
name: "ba-tree-picker",
|
||||
props: {
|
||||
valueKey: {
|
||||
type: String,
|
||||
default: 'id'
|
||||
},
|
||||
textKey: {
|
||||
type: String,
|
||||
default: 'name'
|
||||
},
|
||||
childrenKey: {
|
||||
type: String,
|
||||
default: 'children'
|
||||
},
|
||||
localdata: {
|
||||
type: Array,
|
||||
default: function() {
|
||||
return []
|
||||
}
|
||||
},
|
||||
localTreeList: { //在已经格式化好的数据
|
||||
type: Array,
|
||||
default: function() {
|
||||
return []
|
||||
}
|
||||
},
|
||||
selectedData: {
|
||||
type: Array,
|
||||
default: function() {
|
||||
return []
|
||||
}
|
||||
},
|
||||
title: {
|
||||
type: String,
|
||||
default: ''
|
||||
},
|
||||
multiple: { // 是否可以多选
|
||||
type: Boolean,
|
||||
default: true
|
||||
},
|
||||
selectParent: { //是否可以选父级
|
||||
type: Boolean,
|
||||
default: true
|
||||
},
|
||||
confirmColor: { // 确定按钮颜色
|
||||
type: String,
|
||||
default: '' // #0055ff
|
||||
},
|
||||
cancelColor: { // 取消按钮颜色
|
||||
type: String,
|
||||
default: '' // #757575
|
||||
},
|
||||
titleColor: { // 标题颜色
|
||||
type: String,
|
||||
default: '' //
|
||||
},
|
||||
switchColor: { // 节点切换图标颜色
|
||||
type: String,
|
||||
default: '' // #666
|
||||
},
|
||||
border: { // 是否有分割线
|
||||
type: Boolean,
|
||||
default: false
|
||||
},
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
showDialog: false,
|
||||
treeList: []
|
||||
}
|
||||
},
|
||||
computed: {},
|
||||
methods: {
|
||||
_show() {
|
||||
this.showDialog = true
|
||||
},
|
||||
_hide() {
|
||||
this.showDialog = false
|
||||
},
|
||||
_cancel() {
|
||||
this._hide()
|
||||
this.$emit("cancel", '');
|
||||
},
|
||||
_confirm() { //多选
|
||||
let selectedList = []; //如果子集全部选中,只返回父级 id
|
||||
let selectedNames;
|
||||
let currentLevel = -1;
|
||||
this.treeList.forEach((item, index) => {
|
||||
if (currentLevel >= 0 && item.level > currentLevel) {
|
||||
|
||||
} else {
|
||||
if (item.checkStatus === 2) {
|
||||
currentLevel = item.level;
|
||||
selectedList.push(item.id);
|
||||
selectedNames = selectedNames ? selectedNames + ' / ' + item.name : item.name;
|
||||
} else {
|
||||
currentLevel = -1;
|
||||
}
|
||||
}
|
||||
})
|
||||
//console.log('_confirm', selectedList);
|
||||
this._hide()
|
||||
this.$emit("select-change", selectedList, selectedNames);
|
||||
},
|
||||
//格式化原数据(原数据为tree结构)
|
||||
_formatTreeData(list = [], level = 0, parentItem, isShowChild = true) {
|
||||
let nextIndex = 0;
|
||||
let parentId = -1;
|
||||
let initCheckStatus = 0;
|
||||
if (parentItem) {
|
||||
nextIndex = this.treeList.findIndex(item => item.id === parentItem.id) + 1;
|
||||
parentId = parentItem.id;
|
||||
if (!this.multiple) { //单选
|
||||
initCheckStatus = 0;
|
||||
} else
|
||||
initCheckStatus = parentItem.checkStatus == 2 ? 2 : 0;
|
||||
}
|
||||
list.forEach(item => {
|
||||
let isLastLevel = true;
|
||||
if (item && item[this.childrenKey]) {
|
||||
let children = item[this.childrenKey];
|
||||
if (Array.isArray(children) && children.length > 0) {
|
||||
isLastLevel = false;
|
||||
}
|
||||
}
|
||||
|
||||
let itemT = {
|
||||
id: item[this.valueKey],
|
||||
name: item[this.textKey],
|
||||
level,
|
||||
isLastLevel,
|
||||
isShow: isShowChild,
|
||||
isShowChild: false,
|
||||
checkStatus: initCheckStatus,
|
||||
orCheckStatus: 0,
|
||||
parentId,
|
||||
children: item[this.childrenKey],
|
||||
childCount: item[this.childrenKey] ? item[this.childrenKey].length : 0,
|
||||
childCheckCount: 0,
|
||||
childCheckPCount: 0
|
||||
};
|
||||
|
||||
if (this.selectedData.indexOf(itemT.id) >= 0) {
|
||||
itemT.checkStatus = 2;
|
||||
itemT.orCheckStatus = 2;
|
||||
itemT.childCheckCount = itemT.children ? itemT.children.length : 0;
|
||||
this._onItemParentSelect(itemT, nextIndex);
|
||||
}
|
||||
|
||||
this.treeList.splice(nextIndex, 0, itemT);
|
||||
nextIndex++;
|
||||
})
|
||||
//console.log(this.treeList);
|
||||
},
|
||||
// 节点打开、关闭切换
|
||||
_onItemSwitch(item, index) {
|
||||
// console.log(item)
|
||||
//console.log('_itemSwitch')
|
||||
if (item.isLastLevel === true) {
|
||||
return;
|
||||
}
|
||||
item.isShowChild = !item.isShowChild;
|
||||
if (item.children) {
|
||||
this._formatTreeData(item.children, item.level + 1, item);
|
||||
item.children = undefined;
|
||||
} else {
|
||||
this._onItemChildSwitch(item, index);
|
||||
}
|
||||
},
|
||||
_onItemChildSwitch(item, index) {
|
||||
//console.log('_onItemChildSwitch')
|
||||
const firstChildIndex = index + 1;
|
||||
if (firstChildIndex > 0)
|
||||
for (var i = firstChildIndex; i < this.treeList.length; i++) {
|
||||
let itemChild = this.treeList[i];
|
||||
if (itemChild.level > item.level) {
|
||||
if (item.isShowChild) {
|
||||
if (itemChild.parentId === item.id) {
|
||||
itemChild.isShow = item.isShowChild;
|
||||
if (!itemChild.isShow) {
|
||||
itemChild.isShowChild = false;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
itemChild.isShow = item.isShowChild;
|
||||
itemChild.isShowChild = false;
|
||||
}
|
||||
} else {
|
||||
return;
|
||||
}
|
||||
}
|
||||
},
|
||||
// 节点选中、取消选中
|
||||
_onItemSelect(item, index) {
|
||||
//console.log('_onItemSelect')
|
||||
//console.log(item)
|
||||
if (!this.multiple) { //单选
|
||||
item.checkStatus = item.checkStatus == 0 ? 2 : 0;
|
||||
|
||||
this.treeList.forEach((v, i) => {
|
||||
if (i != index) {
|
||||
this.treeList[i].checkStatus = 0
|
||||
} else {
|
||||
this.treeList[i].checkStatus = 2
|
||||
}
|
||||
})
|
||||
|
||||
let selectedList = [];
|
||||
let selectedNames;
|
||||
selectedList.push(item.id);
|
||||
selectedNames = item.name;
|
||||
this._hide()
|
||||
this.$emit("select-change", selectedList, selectedNames);
|
||||
return
|
||||
}
|
||||
|
||||
let oldCheckStatus = item.checkStatus;
|
||||
switch (oldCheckStatus) {
|
||||
case 0:
|
||||
item.checkStatus = 2;
|
||||
item.childCheckCount = item.childCount;
|
||||
item.childCheckPCount = 0;
|
||||
break;
|
||||
case 1:
|
||||
case 2:
|
||||
item.checkStatus = 0;
|
||||
item.childCheckCount = 0;
|
||||
item.childCheckPCount = 0;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
//子节点 全部选中
|
||||
this._onItemChildSelect(item, index);
|
||||
//父节点 选中状态变化
|
||||
this._onItemParentSelect(item, index, oldCheckStatus);
|
||||
},
|
||||
_onItemChildSelect(item, index) {
|
||||
//console.log('_onItemChildSelect')
|
||||
let allChildCount = 0;
|
||||
if (item.childCount && item.childCount > 0) {
|
||||
index++;
|
||||
while (index < this.treeList.length && this.treeList[index].level > item.level) {
|
||||
let itemChild = this.treeList[index];
|
||||
itemChild.checkStatus = item.checkStatus;
|
||||
if (itemChild.checkStatus == 2) {
|
||||
itemChild.childCheckCount = itemChild.childCount;
|
||||
itemChild.childCheckPCount = 0;
|
||||
} else if (itemChild.checkStatus == 0) {
|
||||
itemChild.childCheckCount = 0;
|
||||
itemChild.childCheckPCount = 0;
|
||||
}
|
||||
// console.log('>>>>index:', index, 'item:', itemChild.name, ' status:', itemChild
|
||||
// .checkStatus)
|
||||
index++;
|
||||
}
|
||||
}
|
||||
},
|
||||
_onItemParentSelect(item, index, oldCheckStatus) {
|
||||
//console.log('_onItemParentSelect')
|
||||
//console.log(item)
|
||||
const parentIndex = this.treeList.findIndex(itemP => itemP.id == item.parentId);
|
||||
//console.log('parentIndex:' + parentIndex)
|
||||
if (parentIndex >= 0) {
|
||||
let itemParent = this.treeList[parentIndex];
|
||||
let count = itemParent.childCheckCount;
|
||||
let oldCheckStatusParent = itemParent.checkStatus;
|
||||
|
||||
if (oldCheckStatus == 1) {
|
||||
itemParent.childCheckPCount -= 1;
|
||||
} else if (oldCheckStatus == 2) {
|
||||
itemParent.childCheckCount -= 1;
|
||||
}
|
||||
if (item.checkStatus == 1) {
|
||||
itemParent.childCheckPCount += 1;
|
||||
} else if (item.checkStatus == 2) {
|
||||
itemParent.childCheckCount += 1;
|
||||
}
|
||||
|
||||
if (itemParent.childCheckCount <= 0 && itemParent.childCheckPCount <= 0) {
|
||||
itemParent.childCheckCount = 0;
|
||||
itemParent.childCheckPCount = 0;
|
||||
itemParent.checkStatus = 0;
|
||||
} else if (itemParent.childCheckCount >= itemParent.childCount) {
|
||||
itemParent.childCheckCount = itemParent.childCount;
|
||||
itemParent.childCheckPCount = 0;
|
||||
itemParent.checkStatus = 2;
|
||||
} else {
|
||||
itemParent.checkStatus = 1;
|
||||
}
|
||||
//console.log('itemParent:', itemParent)
|
||||
this._onItemParentSelect(itemParent, parentIndex, oldCheckStatusParent);
|
||||
}
|
||||
},
|
||||
// 重置数据
|
||||
_reTreeList() {
|
||||
this.treeList.forEach((v, i) => {
|
||||
this.treeList[i].checkStatus = v.orCheckStatus
|
||||
})
|
||||
},
|
||||
_initTree() {
|
||||
this.treeList = [];
|
||||
this._formatTreeData(this.localdata);
|
||||
}
|
||||
},
|
||||
watch: {
|
||||
localdata() {
|
||||
this._initTree();
|
||||
},
|
||||
localTreeList() {
|
||||
this.treeList = this.localTreeList;
|
||||
}
|
||||
},
|
||||
mounted() {
|
||||
this._initTree();
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
.tree-cover {
|
||||
position: fixed;
|
||||
top: 0rpx;
|
||||
right: 0rpx;
|
||||
bottom: 0rpx;
|
||||
left: 0rpx;
|
||||
z-index: 100;
|
||||
background-color: rgba(0, 0, 0, .4);
|
||||
opacity: 0;
|
||||
transition: all 0.3s ease;
|
||||
visibility: hidden;
|
||||
}
|
||||
|
||||
.tree-cover.show {
|
||||
visibility: visible;
|
||||
opacity: 1;
|
||||
}
|
||||
|
||||
.tree-dialog {
|
||||
position: fixed;
|
||||
top: 0rpx;
|
||||
right: 0rpx;
|
||||
bottom: 0rpx;
|
||||
left: 0rpx;
|
||||
background-color: #fff;
|
||||
border-top-left-radius: 10px;
|
||||
border-top-right-radius: 10px;
|
||||
/* #ifndef APP-NVUE */
|
||||
display: flex;
|
||||
/* #endif */
|
||||
flex-direction: column;
|
||||
z-index: 102;
|
||||
top: 20%;
|
||||
transition: all 0.3s ease;
|
||||
transform: translateY(100%);
|
||||
}
|
||||
|
||||
.tree-dialog.show {
|
||||
transform: translateY(0);
|
||||
}
|
||||
|
||||
.tree-bar {
|
||||
/* background-color: #fff; */
|
||||
height: 90rpx;
|
||||
padding-left: 25rpx;
|
||||
padding-right: 25rpx;
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
box-sizing: border-box;
|
||||
border-bottom-width: 1rpx !important;
|
||||
border-bottom-style: solid;
|
||||
border-bottom-color: #f5f5f5;
|
||||
font-size: 32rpx;
|
||||
color: #757575;
|
||||
line-height: 1;
|
||||
}
|
||||
|
||||
.tree-bar-confirm {
|
||||
color: #0055ff;
|
||||
padding: 15rpx;
|
||||
}
|
||||
|
||||
.tree-bar-title {}
|
||||
|
||||
.tree-bar-cancel {
|
||||
color: #757575;
|
||||
padding: 15rpx;
|
||||
}
|
||||
|
||||
.tree-view {
|
||||
flex: 1;
|
||||
padding: 20rpx;
|
||||
/* #ifndef APP-NVUE */
|
||||
display: flex;
|
||||
/* #endif */
|
||||
flex-direction: column;
|
||||
overflow: hidden;
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
.tree-list {
|
||||
flex: 1;
|
||||
height: 100%;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.tree-item {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
line-height: 1;
|
||||
height: 0;
|
||||
opacity: 0;
|
||||
transition: 0.2s;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.tree-item.show {
|
||||
height: 90rpx;
|
||||
opacity: 1;
|
||||
}
|
||||
|
||||
.tree-item.showchild:before {
|
||||
transform: rotate(90deg);
|
||||
}
|
||||
|
||||
.tree-item.last:before {
|
||||
opacity: 0;
|
||||
}
|
||||
|
||||
.switch-on {
|
||||
width: 0;
|
||||
height: 0;
|
||||
border-left: 10rpx solid transparent;
|
||||
border-right: 10rpx solid transparent;
|
||||
border-top: 15rpx solid #666;
|
||||
}
|
||||
|
||||
.switch-off {
|
||||
width: 0;
|
||||
height: 0;
|
||||
border-bottom: 10rpx solid transparent;
|
||||
border-top: 10rpx solid transparent;
|
||||
border-left: 15rpx solid #666;
|
||||
}
|
||||
|
||||
.item-last-dot {
|
||||
position: absolute;
|
||||
width: 10rpx;
|
||||
height: 10rpx;
|
||||
border-radius: 100%;
|
||||
background: #666;
|
||||
}
|
||||
|
||||
.item-icon {
|
||||
width: 26rpx;
|
||||
height: 26rpx;
|
||||
margin-right: 8rpx;
|
||||
padding-right: 20rpx;
|
||||
padding-left: 20rpx;
|
||||
}
|
||||
|
||||
.item-label {
|
||||
flex: 1;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
height: 100%;
|
||||
line-height: 1.2;
|
||||
}
|
||||
.uni-flex-item{
|
||||
width: 100%;
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
}
|
||||
.item-name {
|
||||
flex: 1;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
white-space: nowrap;
|
||||
width: 450rpx;
|
||||
}
|
||||
|
||||
.item-check {
|
||||
width: 40px;
|
||||
height: 40px;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.item-check-yes,
|
||||
.item-check-no {
|
||||
width: 20px;
|
||||
height: 20px;
|
||||
border-top-left-radius: 20%;
|
||||
border-top-right-radius: 20%;
|
||||
border-bottom-right-radius: 20%;
|
||||
border-bottom-left-radius: 20%;
|
||||
border-top-width: 1rpx;
|
||||
border-left-width: 1rpx;
|
||||
border-bottom-width: 1rpx;
|
||||
border-right-width: 1rpx;
|
||||
border-style: solid;
|
||||
border-color: #0055ff;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
.item-check-yes-part {
|
||||
width: 12px;
|
||||
height: 12px;
|
||||
border-top-left-radius: 20%;
|
||||
border-top-right-radius: 20%;
|
||||
border-bottom-right-radius: 20%;
|
||||
border-bottom-left-radius: 20%;
|
||||
background-color: #0055ff;
|
||||
}
|
||||
|
||||
.item-check-yes-all {
|
||||
margin-bottom: 5px;
|
||||
border: 2px solid #007aff;
|
||||
border-left: 0;
|
||||
border-top: 0;
|
||||
height: 12px;
|
||||
width: 6px;
|
||||
transform-origin: center;
|
||||
/* #ifndef APP-NVUE */
|
||||
transition: all 0.3s;
|
||||
/* #endif */
|
||||
transform: rotate(45deg);
|
||||
}
|
||||
|
||||
.item-check .radio {
|
||||
border-top-left-radius: 50%;
|
||||
border-top-right-radius: 50%;
|
||||
border-bottom-right-radius: 50%;
|
||||
border-bottom-left-radius: 50%;
|
||||
}
|
||||
|
||||
.item-check .radio .item-check-yes-b {
|
||||
border-top-left-radius: 50%;
|
||||
border-top-right-radius: 50%;
|
||||
border-bottom-right-radius: 50%;
|
||||
border-bottom-left-radius: 50%;
|
||||
}
|
||||
|
||||
.hover-c {
|
||||
opacity: 0.6;
|
||||
}
|
||||
|
||||
.itemBorder {
|
||||
border-bottom: 1px solid #e5e5e5;
|
||||
}
|
||||
</style>
|
||||
Reference in New Issue
Block a user