vue3 实现多层级列表

news2024/9/22 15:41:36

文章目录

  • 需求背景
  • 解决效果
  • index.vue
  • 视频效果

需求背景

需要在统一个列表下,实现商品和规格得管理和联动

解决效果

在这里插入图片描述

index.vue

<!--/**
 * @author: liuk
 * @date: 2023/7/7
 * @describe: 商品列表
*/-->
<template>
  <div class="container">
    <h1>商品列表</h1>
    <div class="creatbtn" style="margin-bottom: 15px">
      <div class="creatbtn1">
        <el-button class="btn" @click="editShop('')">+&nbsp;新增商品</el-button>
      </div>
    </div>
    <el-row justify="space-between" style="margin-bottom: 15px">
      <el-col :span="12">
        <el-radio-group v-model="fromData.putShelf" @change="getList" size="large">
          <el-radio-button label="">全部</el-radio-button>
          <el-radio-button label="1">已发布</el-radio-button>
          <el-radio-button label="0">未发布</el-radio-button>
        </el-radio-group>
      </el-col>
      <el-col :span="12">
        <el-form-item label="名称">
          <el-input v-model="fromData.productName" style="width: 400px;marginRight:30px " placeholder="请输入内容"
                    @keyup.enter="getList">
            <template #append>
              <el-icon @click="getList">
                <Search/>
              </el-icon>
            </template>
          </el-input>
          <el-button type="danger" @click="resetBtn">重置</el-button>
        </el-form-item>
      </el-col>
    </el-row>

    <el-table v-if="shopTableList.length" v-loading="loading" :data="shopTableList" class="cemetery-table" border
              width="1200px"
              @expand-change="expandChange" :row-key="(row) => row.id" :expand-row-keys="expands">
      <el-table-column min-width="50" type="expand">
        <template #default="props">
          <div>
            <el-table :data="props.row.bMallGoodsSpecifications" border>
              <el-table-column width="80" type="index" label="序号" align="center"/>
              <el-table-column label="图片" align="center" prop="image">
                <template #default="scope">
                  <image-upload class="img-specif-box" v-model="scope.row.image" :limit="1"
                                :disabled="!scope.row.specificationEdit"
                  ></image-upload>
                </template>
              </el-table-column>
              <el-table-column label="规格描述" align="center" prop="specificationDescription">
                <template #default="scope">
                  <el-input v-model="scope.row.specificationDescription"
                            :disabled="!scope.row.specificationEdit"
                            style="width: 60px"/>
                </template>
              </el-table-column>
              <el-table-column label="规格" align="center" prop="specifications">
                <template #default="scope">
                  <el-input v-model="scope.row.specifications"
                            :disabled="!scope.row.specificationEdit"
                            style="width: 60px"/>
                </template>
              </el-table-column>
              <el-table-column label="价格" align="center" prop="price">
                <template #header>
                  <span class="red">*</span>
                  <el-icon>
                    <Edit/>
                  </el-icon>
                  价格
                </template>
                <template #default="scope">
                  <el-input v-model="scope.row.price"
                            :disabled="!scope.row.specificationEdit"
                            style="width: 60px"/>
                </template>
              </el-table-column>
              <el-table-column label="单位" align="center" prop="unitName">
                <template #default="scope">
                  <el-select v-model="scope.row.unitId" :disabled="!scope.row.specificationEdit">
                    <el-option v-for="(item,i) in units" :key="i" :label="item.label" :value="item.value"/>
                  </el-select>
                </template>
              </el-table-column>
              <el-table-column label="划线价" align="center" prop="crossedPrice">
                <template #header>
                  <el-icon>
                    <Edit/>
                  </el-icon>
                  划线价
                </template>
                <template #default="scope">
                  <el-input v-model="scope.row.crossedPrice"
                            :disabled="!scope.row.specificationEdit"
                            style="width: 60px"/>
                </template>
              </el-table-column>
              <el-table-column label="库存" align="center" prop="stock">
                <template #default="scope">
                  <el-input v-model="scope.row.stock"
                            :disabled="!scope.row.specificationEdit"
                            style="width: 60px"/>
                </template>
              </el-table-column>
              <el-table-column label="可否调价" align="center" prop="adjustThePrice">
                <template #default="scope">
                  <el-switch v-model="scope.row.adjustThePrice" :active-value="1" :inactive-value="0"
                             :disabled="!scope.row.specificationEdit"
                             style="--el-switch-on-color: rgb(19, 206, 102); --el-switch-off-color: rgb(255, 73, 73)"/>
                </template>
              </el-table-column>
              <el-table-column fixed="right" label="操作" align="center" class-name="small-padding fixed-width"
                               min-width="210">
                <template #default="scope">
                  <el-button v-show="!scope.row.specificationEdit" type="success"
                             @click="editSpecifications(scope.row,props)">编辑
                  </el-button>
                  <el-button v-show="scope.row.specificationEdit" type="success"
                             @click="updateSpecification(scope.row)">
                    保存
                  </el-button>
                  <el-button v-show="scope.row.specificationEdit"
                             @click="scope.row.specificationEdit = false">取消
                  </el-button>
                  <el-button v-show="!scope.row.specificationEdit" type="danger"
                             @click="delSpecifica(scope.row,props)">删除
                  </el-button>
                </template>
              </el-table-column>
            </el-table>
          </div>
        </template>
      </el-table-column>
      <el-table-column min-width="80" type="index" align="center" label="序号"/>
      <el-table-column min-width="100" label="商品名称" align="center" prop="productName" sortable>
        <template #header>
          商品名称
          <el-icon>
            <QuestionFilled/>
          </el-icon>
        </template>
      </el-table-column>
      <el-table-column min-width="150" label="图片" align="center" prop="productImage">
        <template #default="scope">
          <el-image style="width: 40px; height: 40px"
                    :src="scope.row.productImage"
                    :zoom-rate="1.2"
                    :preview-src-list="[scope.row.productImage]"
                    :initial-index="4"
                    preview-teleported
                    fit="cover"/>
        </template>
      </el-table-column>
      <el-table-column min-width="100" label="库存策略" align="center" prop="inventoryStrategy">
        <template #default="scope">
          {{ formatInventoryStrategy(scope.row.inventoryStrategy) }}
        </template>
      </el-table-column>
      <el-table-column min-width="100" label="顺序" prop="sort" align="center" sortable>
        <template #header>
          顺序
          <el-icon>
            <QuestionFilled/>
          </el-icon>
        </template>
      </el-table-column>
      <el-table-column min-width="100" label="是否已发布" align="center" prop="putShelf">
        <template #default="scope">
          <el-switch
              v-model="scope.row.putShelf" :active-value="1" :inactive-value="0"
              style="--el-switch-on-color: rgb(19, 206, 102); --el-switch-off-color: rgb(255, 73, 73)"/>
        </template>
      </el-table-column>
      <el-table-column min-width="100" label="是否静态" align="center" prop="staticState">
        <template #default="scope">
          <el-switch v-model="scope.row.staticState" :active-value="1" :inactive-value="0"
                     :before-change="staticStateChange.bind(null, scope.row)"
                     :disabled="scope.row.staticState == 1"
                     style="--el-switch-on-color: rgb(19, 206, 102); --el-switch-off-color: rgb(255, 73, 73)"/>
        </template>
      </el-table-column>
      <el-table-column min-width="100" label="SKU数量" align="center" prop="productNum">
        <template #default="scope">
          <span :class="{red:scope.row.productNum == 0}">{{ scope.row.productNum }}</span>
        </template>
      </el-table-column>
      <el-table-column min-width="100" label="价格" align="center" prop="productPrice"/>
      <el-table-column label="操作" fixed="right" min-width="250" align="center" class-name="small-padding fixed-width">
        <template #default="scope">
          <el-button @click="addSpecif(scope.row,scope)">增加规格</el-button>
          <el-button type="primary" @click="editShop(scope.row.id)">编辑</el-button>
          <el-button type="danger" @click="delShop(scope.row)">删除</el-button>
        </template>
      </el-table-column>
    </el-table>
    <el-empty description="暂无商品" v-else/>
    <pagination
        v-show="pages.total>0"
        :total="pages.total"
        v-model:page="pages.pageNum"
        v-model:limit="pages.pageSize"
        @pagination="getList"
    />
  </div>
</template>

<script setup>
import {listGoods, delGoods, previewGoods} from "@/api/retailmall/goods";
import {updateSpecifications, addSpecifications, delSpecifications} from "@/api/retailmall/specifications";
import {listUnits,} from "@/api/mall/units";
import {useRoute, useRouter} from "vue-router";
import {onMounted} from "vue";


// Emit
const emit = defineEmits(['editShopOpen'])
// route
const route = useRoute()
// store
import useMallStore from '@/store/modules/mall'

const mallStore = useMallStore()
const router = useRouter()
const {proxy} = getCurrentInstance();

const model = reactive({
  fromData: {},
  pages: {
    pageNum: 1,
    pageSize: 10,
    total: 0
  },
  expands: [],//表格展开行
  shopTableList: [],//商品列表
  loading: true,
  units: [],//单位列表
});
const {fromData, expands, pages, shopTableList, loading, units} = toRefs(model);

// 编辑商品
const editShop = (id) => {
  emit('editShopOpen')
  mallStore.setCurGoodId(id)
}

// 增加规格
const addSpecif = (row, props) => {
  let params = {
    commodityId: row.id,
    crossedPrice: 0,
    stock: 0,
    price: 0,
    specifications: 0,
    specificationDescription: ""
  }
  addSpecifications(params).then(res => {
    if (+res.code === 200) {
      previewGoods(props.row.id).then((res) => {
        if (+res.code === 200) {
          model.expands = [] // 展开行
          model.expands.push(row.id)
          props.row.bMallGoodsSpecifications = res.data.bMallGoodsSpecifications
          proxy.$message.success("新增成功")
        }
      })
    }
  })
}

// 修改规格
const updateSpecification = (row) => {
  updateSpecifications(row).then((res) => {
    if (+res.code === 200) {
      row.specificationEdit = false
      proxy.$message.success("编辑成功")
    }
  })
}
// 表格展开变化  -- 只能展开一行
const expandChange = (row, expandedRows) => {
  if (expandedRows.length) {
    model.expands = []
    if (row) {
      model.expands.push(row.id)
    }
  } else {
    model.expands = []
  }
}

// 删除商品
const delShop = (row) => {
  proxy.$modal.confirm(`确定要删除${row.productName}`).then(function () {
    return delGoods(row.id)
  }).then(() => {
    getList();
    proxy.$modal.msgSuccess("删除成功");
  })
}

// 是否静态开关变化
const staticStateChange = (item) => {
  return new Promise((resolve, reject) => {
    proxy.$modal.confirm('一旦商品开启静态,该商品不可进行任何操作(删除编辑发布隐藏),是否确定要 修改 商品 ?').then(() => {
      resolve(true)
    })
  })
}

// 编辑规格
const editSpecifications = (row) => {
  row.specificationEdit = true
}

// 删除规格
const delSpecifica = (row, props) => {
  proxy.$modal.confirm(`确定要删除${row.productName}`).then(function () {
    return delSpecifications(row.id)
  }).then(() => {
    previewGoods(props.row.id).then((res) => {
      props.row.bMallGoodsSpecifications = res.data.bMallGoodsSpecifications
    })
    proxy.$modal.msgSuccess("删除成功");
  })
}

// 获取商品列表
function getList() {
  let params = {
    ...model.fromData,
    ...model.pages,
    shopIds: [route.query.id],
    total: undefined
  }
  model.loading = true;
  listGoods(params).then(response => {
    model.expands = [] // 不展开行
    model.shopTableList = response.rows || {bMallGoodsSpecifications: []};
    model.pages.total = response.total;
    model.loading = false;
  })
}

// 表单重置
function reset() {
  form.value = {};
}

// 获取全部单位
const getlistUnits = () => {
  let params = {
    pageNum: 1,
    pageSize: 999
  }
  listUnits(params).then(res => {
    model.units = res.rows.map((item) => {
      return {
        label: item.name,
        value: item.id
      }
    })
  })
}
// 重置
const resetBtn = () => {
  fromData.value = {}
  getList()
}

onMounted(() => {
  getList();
  getlistUnits()
})

const formatInventoryStrategy = (val) => {
  let str = ''
  switch (val) {
    case 0:
      str = '无需库存'
      break
    case 1:
      str = '下单后减少'
      break
    case 2:
      str = '支付后减少'
      break
    case 3:
      str = '使用后减少'
      break
  }
  return str
}
</script>

视频效果

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/728690.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

textarea自适应高度二——(设置隐藏div获取高度和仿element-ui组件)

文章目录 前言一、通过隐藏div的方式来设置文本域自适应高度1. 新增一个文本域样式一个的dom&#xff0c;但是里面的textarea改为div2. 隐藏div的class3.设置文本域高度的方法 二、仿element-ui组件设置textarea自适应高度1.element-ui中自适应效果2. 看源码&#xff0c;盘逻辑…

病毒专题丨 plugx病毒

一、病毒简述 之前分析了一下&#xff0c;分析的较为简单&#xff0c;这次又详细分析了一下。 文件名称 00fbfaf36114d3ff9e2c43885341f1c02fade82b49d1cf451bc756d992c84b06 文件格式 RAR 文件类型(Magic) RAR archive data, v5 文件大小 157.74KB SHA256 00fbfaf36114d3ff9e…

【编程中的数学】:冰雹猜想

今天和大家分享一个令人着迷的数学谜题——冰雹猜想。这个谜题曾在1976年引起轰动&#xff0c;当时《华盛顿邮报》以头版头条刊登了一篇关于它的报道。让我们一起探索这个数学游戏的奥秘。 70年代中期&#xff0c;美国一所名牌大学的校园内兴起了一种数学游戏&#xff0c;这个游…

微信小程序使用vant时间选择器二次封装成自定义区间时间选择

目录 1.引入vant组件库 2.wxml页面 3.js页面 1.引入vant组件库 1.安装vant # 通过 npm 安装 npm i vant/weapp -S --production # 通过 yarn 安装 yarn add vant/weapp --production # 安装 0.x 版本 npm i vant-weapp -S --production 2.将 app.json 中的 "style&quo…

2-需求

目录 1.需求的定义 1.1.用户需求 1.2.软件需求 PS&#xff1a;软件需求规格说明书 2.为什么有需求&#xff1f; PS&#xff1a;为什么需求对软件测试人员如此重要&#xff1f; 3.测试人员眼里的需求 4.如何深入了解需求&#xff1f; 4.1.参加需求评审会议 4.2.查阅文…

数据结构初阶--二叉树OJ1

目录 二叉树的最大深度思路分析代码实现 相同的树思路分析代码实现 单值二叉树思路分析代码实现 二叉树的前序遍历思路分析代码实现 翻转二叉树思路分析代码实现 对称二叉树思路分析代码实现 另一棵树的子树思路分析代码实现 二叉树的最大深度 先来看题目描述 思路分析 题目…

QT学习—串口LED小项目

前言——博主刚开始接触QT&#xff0c;本文参考博主嵌入式大杂烩的一篇博文易懂 | 手把手教你编写你的第一个上位机&#xff0c;初步学习一下QT开发。 文章目录 一、QT安装二、新建工程三、创建上位机界面3.1 修改控件名3.2 添加槽函数 四、上位机程序打包五、上位机测试六、总…

不要用 in + 子查询

前两天我的 VIP 用户向我抛出了一个 SQL 问题&#xff0c;他的 MySQL 是 8.x版本&#xff1a; 大概意思如下 sql &#xff1a; select * from A where id in (select max(id) as id from A where task_id in(1,2,3) group by task_id );这个 A 表中是有 task_id 这个索引的。 …

【转换】编码转换工具笔记

应用场景 应用场景是程序整合第三方库多平台运行&#xff0c;第三方库window平台编译&#xff0c;代码移植到linux出现bom问题 思考解决 windows使用utf-8编码&#xff0c;linux使用utf-8无bom编码 工具主要针对utf-8编码文件&#xff0c;能够批量添加删除BOM&#xff0c;无…

SpringBoot获取项目日志

目的 对于布署在远端的服务&#xff0c;我们想快速的获取到日志。对于使用了日志服务&#xff0c;也可能因为上报间隔太长&#xff0c;日志不够实时。 所以想通过一些方式&#xff0c;可以不用进入到容器内也可以简单快速获取到日志&#xff0c;而且是实时的日志。目标就是获…

c语言进阶-动态内存管理

重点学习内容 动态内存管理四大函数 Malloc 内存申请函数 返回值是无类型的指针&#xff0c;指向分配的内存的首地址。申请失败会返回空指针。 malloc返回值是void*类型&#xff0c;使用时需要强制转换成所需类型。 malloc和free匹配使用&#xff0c;但是如果不free释放内存&…

解析3D视觉系统在引导金属件上下料中的应用

原创 | 文 BFT机器人 引言 Introduction 机器视觉技术作为一种高科技的智能化技术&#xff0c;正在工业生产领域发挥着越来越重要的作用。它利用计算机视觉技术&#xff0c;通过获取、处理和分析图像&#xff0c;实现对产品和工艺过程的监测、检测和控制。 随着人工智能技术的…

[SUCTF2019]hardcpp

前言 又遇到ollvm了 解混淆 可以直接用angr运行脚本去除除控制流平坦化&#xff0c;最好在ancoda等管理环境里面安装angr不然问题很多 https://github.com/Pure-T/deflat 去除前 去除后&#xff0c;它将多余的直接nop了 分析 主要加密区域位于匿名函数这一块&#xff0c…

前端学习——Web API(Day1)

Web API基本认知 Web API 基本认知 作用和分类 DOM DOM树 DOM对象 获取DOM对象 根据CSS选择器来获取DOM元素 <!DOCTYPE html> <html lang"zh-CN"> <head><meta charset"UTF-8"><meta http-equiv"X-UA-Compatible" …

【教学类-36-08】转学“纪念册“留念(生肖用midjounery-niji)

作品样式 背景需求&#xff1a; 即将离开班级&#xff0c;我想收集一份28个孩子的绘画册做——留念转学纪念册. 材料准备&#xff1a; 幼儿照片 ——3月初到中6班拍摄的幼儿手持学号名字纸的照片&#xff08;为了背诵幼儿信息而拍摄的照片&#xff0c;统一竖版&#xff09; 生…

jmeter 连接数据库常见报错

1. 不允许主机连接到MySQL 报错信息&#xff1a; Response message:java.sql.SQLException: Cannot create PoolableConnectionFactory (null, message from server: "Host 192.168.1.6 is not allowed to connect to this MySQL server") 说明&#xff1a;本机的地…

代码随想录day10

232. 用栈实现队列 思路&#xff1a;用两个list去模拟栈的操作&#xff0c;一个入栈list&#xff0c;一个出栈list. 并且了解栈的操作&#xff0c;pop,peek,push. 代码&#xff1a; def __init__(self):self.stack1 [] #入栈self.stack2[] #出栈def push(self, x: int) ->…

【Linux】常用网络命令:ping\netstat\mount\ifconfig

ping命令用于检测主机&#xff0c;执行ping命令指令会使用ICMP传输协议&#xff0c;发出请求回应的信息&#xff0c;若远程主机的网络功能没有问题&#xff0c;就会回应该信息。   netstat命令用于显示网络状态&#xff0c;利用netstat 指令可让你得知linux系统的网络情况。…

图像 跟踪 - MOTR: End-to-End Multiple-Object Tracking with Transformer (ECCV 2022)

MOTR: End-to-End Multiple-Object Tracking with Transformer - 使用Transformer进行端到端多目标跟踪&#xff08;ECCV 2022&#xff09; 摘要1. 引言2. 相关工作3. 方法3.1 目标检测中的查询3.2 检测查询和跟踪查询3.3 Tracklet-Aware标签分配3.4 MOTR架构3.5 查询交互模块3…

git-创建文件夹方式管理分支

文章目录 前言一、效果图二、git命令总结 前言 下面介绍一个git创建文件夹的方式管理分支的方法&#xff0c;在sourcetree上显示目录样式&#xff0c;好对每个版本做管理&#xff0c;可以更方便追踪历史版本代码。 一、效果图 1、git文件夹方式管理分支 二、git命令 1、在本…