| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340 |
- <template>
- <block v-if="!isBom">
- <view class="search-box">
- <up-search placeholder="搜索关键词" v-model="keyword" height="35" @blur="onSearch" :clearabled="false"
- :showAction="false" />
- <view v-if="content.where.condition" class="clear" @click.stop="onSearch('')">
- <up-icon name="close-circle-fill" size="20" />
- </view>
- </view>
- <view style="height: 20rpx;" />
- </block>
- <My_listbox v-if="!isBom" ref="listBox" :empty="!list.length" :pullDown="!isBom" @getlist="getList">
- <showList :result="resultIds" :list='list' @onClick="onSelect" />
- <view style="height: 200rpx;" />
- </My_listbox>
- <view v-else-if="bomList.length" class="bom">
- <view class="left">
- <view class="class1" :class="active.class1 == index ? 'class1active' : ''" @click="changeClass1(index)"
- v-for="(item, index) in bomList" :key="item.plm_bomid" hover-class="navigator-hover">
- {{ item.bomname }}
- </view>
- </view>
- <view class="right">
- <My_listbox ref="listBox" :pullDown="false">
- <up-collapse :value="collapse1" @change="changeCollapse1($event)">
- <up-collapse-item :ref="el => {
- if (el) {
- collapseRefs['collapse' + item.plm_bomid] = el
- }
- }" :cellCustomStyle="{
- backgroundColor: '#fff',
- }" v-for="item in bomList[active.class1].subdep" :key="item.plm_bomid" :title="item.bomname"
- :name="item.plm_bomid">
- <up-collapse @change="changeCollapse($event, item.plm_bomid)" v-if="item.subdep.length"
- :name="item.plm_bomid">
- <up-collapse-item :cellCustomStyle="{
- backgroundColor: '#fff',
- }" :ref="el => {
- if (el) {
- collapseRefs['collapse' + item.plm_bomid] = el
- }
- }" v-for="item1 in item.subdep" :key="item1.plm_bomid" :title="item1.bomname"
- :name="item1.plm_bomid">
- <showList v-if="item1.items.length" size="small" :result="resultIds" :list='item1.items'
- @onClick="onSelect" />
- </up-collapse-item>
- </up-collapse>
- <showList v-if="item.items.length" size="small" :result="resultIds" :list='item.items'
- @onClick="onSelect" />
- </up-collapse-item>
- </up-collapse>
- <view style="height: 200rpx;" />
- </My_listbox>
- </view>
- </view>
- <My_listbox v-else ref="listBox" :empty="true" @getlist="getBomList" />
- <view class="footer">
- <My-button :text="`确定添加(${resultIds.length})`" @onClick="onAdd" />
- </view>
- </template>
- <script setup>
- import { ref, reactive, getCurrentInstance, nextTick } from 'vue';
- import { onLoad } from '@dcloudio/uni-app';
- import showList from "./accessoriesList.vue"
- const { $Http } = getCurrentInstance().proxy;
- const listBox = ref(null);
- const isBom = ref(false);
- let result = reactive([]);
- const resultIds = ref([]);
- const content = reactive({
- loading: false,
- "pageNumber": 1,
- "pageSize": 20,
- "where": {
- "condition": ""
- }
- })
- function onAdd() {
- $Http.selectAcc(result)
- }
- function onSelect(e) {
- if (result.some(item => item.itemid == e.itemid)) {
- result = result.filter(item => item.itemid != e.itemid);
- } else {
- result.push(e);
- }
- resultIds.value = result.map(item => item.itemid);
- }
- const list = ref([]);
- onLoad((options) => {
- console.log("options", options)
- console.log("$Http", $Http)
- result = result.concat(JSON.parse(options.list || '[]'));
- resultIds.value = result.map(item => item.itemid);
- console.log("初始选中", result, resultIds.value)
- let content1 = $Http.content1;
- content.sys_enterpriseid = content1.sys_enterpriseid;
- content.sa_workorderid = content1.sa_workorderid;
- if (content1.sku) $Http.basic({
- "id": 2025080610424703,
- "content": content1
- }).then(res => {
- console.log("查询产品是否存在BOM", res)
- if (res.data == 0) {
- // 不存在BOM
- getList(true);
- } else {
- // 存在BOM
- isBom.value = true;
- getBomList();
- }
- })
- })
- const bomList = ref([]);
- let active = reactive({
- class1: 0
- });
- function changeClass1(index) {
- active.class1 = index;
- }
- // 折叠面板
- const collapseRefs = ref({})
- const collapse1 = ref([])
- function changeCollapse1(e) {
- collapse1.value = e.filter(v => v.status == 'open').map(v => v.name)
- }
- function changeCollapse(e, id) {
- nextTick(() => {
- collapseRefs.value['collapse' + id].init()
- });
- setTimeout(() => {
- nextTick(() => {
- collapseRefs.value['collapse' + id].init()
- });
- }, 330);
- }
- // 有bom
- function getBomList() {
- $Http.basic({
- "id": "2025080610425503",
- content: {
- "sa_aftersalesbomid": content.sa_workorderid,
- "sys_enterpriseid": content.sys_enterpriseid,
- }
- }).then(res => {
- console.log("获取bom配件列表", res)
- listBox.value.refreshToComplete();
- listBox.value.setHeight();
- if (res.code == 1) {
- bomList.value = processBomData(res.data)
- console.log("bomList", bomList.value);
- } else {
- if (res.msg) uni.showToast({
- title: res.msg,
- icon: 'none'
- });
- }
- })
- }
- function processBomData(originalData) {
- // 1. 提取所有一级分类节点
- const topLevelNodes = [];
- // 遍历原始数据
- originalData.forEach(dataSet => {
- dataSet.bom?.forEach(rootNode => {
- // 提取根节点下的一级分类
- if (rootNode.subdep && rootNode.subdep.length > 0) {
- topLevelNodes.push(...rootNode.subdep);
- }
- });
- });
- // 2. 递归处理节点
- const processNode = (node) => {
- node.items = node.items || [];
- node.subdep = node.subdep || [];
- // 如果当前节点没有items和subdep,直接返回null
- if (node.items.length === 0 && node.subdep.length === 0) return null;
- try {
- if (node.items.length) node.items = node.items.map(item => {
- item.imageUrl = item.attinfos.length ? $Http.getSpecifiedImage(item.attinfos[0]) : ''
- return item;
- });
- } catch (error) {
- }
- // 创建新节点副本
- const newNode = { ...node };
- // 处理子节点
- if (node.subdep.length) newNode.subdep = node.subdep.map(subNode => processNode(subNode)).filter(subNode => subNode !== null);
- return newNode;
- };
- // 3. 处理所有一级分类节点
- return topLevelNodes.map(node => processNode(node)).filter(node => node && (node.subdep.length || node.items.length));
- }
- // 无BOM
- const keyword = ref('');
- function onSearch(e) {
- if (content.where.condition == e) return;
- content.where.condition = e;
- keyword.value = e;
- getList(true);
- }
- function getList(init = false) {
- if (isBom.value) return;
- if (content.loading) return;
- if (init) content.pageNumber = 1;
- content.loading = true;
- $Http.basic({
- "id": "2025080610425103",
- content
- }).then(res => {
- console.log("获取配件列表", res)
- content.loading = false;
- listBox.value.refreshToComplete();
- listBox.value.setHeight();
- res.data = res.data.map(item => {
- item.imageUrl = item.attinfos.length ? $Http.getSpecifiedImage(item.attinfos[0]) : ''
- return item;
- });
- if (res.code == 1) {
- list.value = reactive(res.firstPage ? res.data : list.value.concat(res.data));
- content.pageTotal = res.pageTotal;
- content.pageNumber = res.pageNumber;
- } else {
- if (res.msg) uni.showToast({
- title: res.msg,
- icon: 'none'
- });
- }
- })
- }
- </script>
- <style lang="scss" scoped>
- .bom {
- width: 100vw;
- display: flex;
- min-height: 100vh;
- .left {
- width: 250rpx;
- background: #fff;
- flex-shrink: 0;
- .class1 {
- padding: 30rpx 30rpx;
- width: 250rpx;
- box-sizing: border-box;
- background: #FFFFFF;
- border-radius: 0rpx 8rpx 0rpx 0rpx;
- font-family: PingFang SC, PingFang SC;
- font-size: 28rpx;
- color: #999999;
- }
- .class1active {
- position: relative;
- background: #F7F7FF;
- color: #3774F6;
- }
- .class1active::after {
- content: '';
- position: absolute;
- left: 0;
- top: 0;
- width: 8rpx;
- height: 100%;
- background: #3774F6;
- }
- }
- .right {
- flex: 1;
- }
- }
- .search-box {
- position: relative;
- padding: 20rpx;
- background: #fff;
- .clear {
- position: absolute;
- display: flex;
- align-items: center;
- right: 0;
- top: 50%;
- transform: translateY(-50%);
- width: 80rpx;
- padding-left: 10rpx;
- height: 70rpx;
- z-index: 2;
- }
- }
- .footer {
- position: fixed;
- bottom: 0;
- left: 0;
- width: 100%;
- height: 120rpx;
- padding: 10rpx 20rpx;
- background: #fff;
- box-sizing: border-box;
- }
- </style>
|