当前位置: 首页 > news >正文

uniapp-商城-60-后台 新增商品(属性的选中和页面显示)

        前面添加了属性,添加属性的子级项目。也分析了如何回显,但是在添加新的商品的时,我们也同样需要进行选择,还要能正常的显示在界面上。下面对页面的显示进行分析。

1、界面情况回顾

属性显示其实是个一嵌套的数据显示。

2、选中的界面

3、页面显示

使用了函数方法skuChildName,

还使用了点击就弹窗在两个地方都用了。clickSelect

对于默认显示:还用到了skuTitle 计算接口,

当然这个接口也可以用方法来做,但这里值都可以取得,所以就用这方法。

前一个章节讲了显示,需要添加一个view 进行显示:

4、相应显示的需要的方法 skuChildName

方法很简单,就是将读取的数据,arr数组,找出数组中的name ,然后对name进行/ 拼接

注意使用的方法   map

对数组中的值 使用  / 进行拼接。

注意这里只是计算了 子级 项的name  

            //属性返回子元素的名称
            skuChildName(arr) {
                let nsArr = arr.map(item => {
                    return item.name
                })
                return nsArr.join("/")
            },

5、计算页面的显示,如果没有值,那么就显示点击添加属性

是一个计算值的接口,默认是显示点击添加属性

如果this.goodsFormData.sku_select.length 不为0 ,就显示属性值中的name,用到的用 jion   /  链接

注意不是 children,这里只是计算了父级 属性

在页面上显示 也是直接用了该函数名字

        computed: {
            skuTitle() {
                if (this.goodsFormData.sku_select.length) {
                    let arr = this.goodsFormData.sku_select.map(item => {
                        return item.skuName
                    })
                    return arr.join("/")
                } else {
                    return "点击添加属性"
                }
            }
        },

            <uni-forms-item label="商品属性" >
                <u-cell :title="skuTitle" isLink :border="false" @click="clickSelect"></u-cell>
                <view class="skuList">
                    <view class="item" v-for="item in goodsFormData.sku_select" @click="clickSelect">
                        <view class="left">{{item.skuName}}:</view>
                        <view class="right">{{skuChildName(item.children)}}</view>
                    </view>
                </view>
            </uni-forms-item>

6 整体的代码(除开商品,属性这一栏 界面的  全都有了)

<template><view class="goodsView"><!-- 添加商品 --><uni-forms ref="goodsForm" :model="goodsFormData" :rules="goodsRules" :label-width="100" label-align="right"><uni-forms-item label="商品图片" required="true"><uni-file-picker v-model="goodsFormData.thumb" fileMediatype="image" mode="grid" ></uni-file-picker></uni-forms-item><uni-forms-item label="商品名称" required name="name" ><!-- trim 去空格 --><uni-easyinput v-model="goodsFormData.name" placeholder="请输入商品名称" trim="both"></uni-easyinput></uni-forms-item><uni-forms-item label="产品分类" required name="category_id"><!-- 云端数据  下拉框获取  field 就是获取的内容  一定要写成 value text 这是官方定义的  value选中的值,text显示的文本,也就是value后台用,text前台用 --><!-- 利用这个组件就实现了后端数据库的读取 --><uni-data-select collection="green-mall-categories" field="_id as value, name as text"v-model="goodsFormData.category_id"></uni-data-select></uni-forms-item><uni-forms-item label="商品价格" required name="price"><!-- trim 去空格 --><uni-easyinput type="number" v-model="goodsFormData.price" placeholder="请输入商品价格"trim="both"></uni-easyinput></uni-forms-item><uni-forms-item label="商品原价"><!-- trim 去空格 --><uni-easyinput type="number" v-model="goodsFormData.before_price" placeholder="请输入原价"trim="both"></uni-easyinput></uni-forms-item><uni-forms-item label="商品属性" ><u-cell :title="skuTitle" isLink :border="false" @click="clickSelect"></u-cell><view class="skuList"><view class="item" v-for="item in goodsFormData.sku_select" @click="clickSelect"><view class="left">{{item.skuName}}:</view><view class="right">{{skuChildName(item.children)}}</view></view></view></uni-forms-item><uni-forms-item label="商品描述"><!-- type 是类型  textarea 就是大框 --><uni-easyinput type="textarea" placeholder="请输入详细的描述信息"v-model="goodsFormData.description"></uni-easyinput></uni-forms-item><view class="btnView"><button type="primary" @click="onSubmit">确认提交</button></view></uni-forms><uni-popup ref="attrWrapPop" type="bottom"><!-- 底部弹出 type ref 是一个名字属性,便于被调用 给 clickSelect 在 clickSelect 函数中调用了该接口--><view class="attrWrapper"><!-- 分三部分  就是上中下 头身体和尾部 --><view class="head"><view class="title">商品属性</view><!-- clickAddAttr函数  添加属性的--><view class="addAttr" @click="clickAddAttr()">+ 添加属性</view></view><view class="body"><!-- 读取 skuArr 循环显示 分两部分显示 top 和 btngroup--><view class="item" v-for="(item,index) in skuArr"><view class="top"><checkbox :checked="item.checked" @click="changeCheckbox(index)"></checkbox><!-- changeCheckbox  选中就做这个操作 --><!-- checked 是否被选中的属性标识 --><view class="font">{{item.skuName}}</view></view><view class="btnGroup" v-if="item.checked"><!-- 需要判断checked 是不是true  是不是选中,选中了就展示--><view class="btn" :class="child.checked?'active':''" v-for="(child,cIdx) in item.children"@click="clickChlidBtn(index,cIdx)">{{child.name}}</view><!-- btn 读取skuArr ,循环显示选中就加class 为active  点击 就执行 clickChlidBtn函数--><view class="btn" @click="clickAddAttr(index)"><!-- btn 该盒子就是一个 + 号,用来添加该属性下的选项 clickAddAttr 点就执行uicon就一个 + 号图标  --><u-icon name="plus"></u-icon></view></view></view></view><view class="foot"><button type="primary" @click="clickConfirmSelect">确认选择</button><!-- 按钮 ,蓝色提交按钮type 就是颜色格式点击就是确认该商品的属性clickConfirmSelect--></view></view><view class="safe-area-bottom"></view><!--防止被苹果虚拟home键 挡住 --><!-- 这里就是直接调用的app.vue的全局样式。什么是全局样式:就是样式那里没有scoped 的,所以在以前老是要写一个表示局部样式,就怕vue 中class名字一样了如果你不些scoped ,就要把全局的view 的class 写在最前面。不知道懂不懂,慢慢悟吧--></uni-popup><!-- 这里是点击的添加属性的弹窗 --><!-- 你可能懵逼了那个添加属性的弹窗?两个弹窗都要用一个是第一个弹窗中的右上角的添加属性  class名字 addAttr一个是属性规格下的选项中的 + class的名字就是btn--><uni-popup ref="addAttrPop"><uni-popup-dialog mode="input" title="新增" placeholder="请输入新增的内容"@confirm="dialogConfirm"></uni-popup-dialog><!-- dialogConfirm 是一个确认后处理逻辑 --></uni-popup></view>
</template><script>const skuCloudObj = uniCloud.importObject("green-mall-sku", {"customUI": true});const goodsCloudObj = uniCloud.importObject("green-mall-goods", {"customUI": true})export default {data() {return {goodsFormData: {thumb: [],name: "",category_id: null,price: null,before_price: null,description: "",sku_select: []},addAttrType: "parent", //parent代表父,child代表子goodsRules: {name: {rules: [{required: true,errorMessage: "请输入产品名称"}]},price: {rules: [{required: true,errorMessage: "请输入产品价格"}]},category_id: {rules: [{required: true,errorMessage: "请输入产品分类"}]}},/*skuArr: [{_id:1,skuName:"颜色",checked:false,children:[{name:"红",checked:false},{name:"蓝",checked:false}]},{_id:2,skuName:"规格",checked:false,children:[{name:"M",checked:false},{name:"S",checked:false}]}],*/// 上面是一个数据结构例子,后台数据就应该着这样存// 实际是下面的[]skuArr: [],};},onLoad() {},computed: {skuTitle() {if (this.goodsFormData.sku_select.length) {let arr = this.goodsFormData.sku_select.map(item => {return item.skuName})console.log(arr);return arr.join("/")} else {return "点击添加属性"}}},methods: {//属性返回子元素的名称skuChildName(arr) {let nsArr = arr.map(item => {return item.name})return nsArr.join("/")},//点击确认选择 是在弹出框上选//some 数组至少有一个满足 没有就是false   every就是每一个都要满足,不满足就是false// 这里filter 选出父级属性 checked =true 被选中的 且子级属性有一个被选中的数组对象;// 然后再对选中的对象,逐一进行map运算//运算就是filter 过滤出来选中的子级元素//返回一个 数组 arr 且元素为一个对象,对象展开了item ,然后将children的值放到里面,覆盖item中的childrenclickConfirmSelect() {let arr = this.skuArr.filter(item => {let state = item.children.some(child => child.checked)  return item.checked && state}).map(item => {let children = item.children.filter(child => {return child.checked})// console.log(item,11111111);// console.log(children,2222222);return {...item,// children   //覆盖了item中children}})this.goodsFormData.sku_select = arr   //赋值后,页面在使用这个数组来显示  立即回显this.$refs.attrWrapPop.close();   //关闭掉弹窗},//获取sku列表async getSkuData() {let res = await skuCloudObj.get();this.skuArr = res.data// console.log(res);},//点击添加属性 index 存在就是嵌套下 父类属性的子类选项 ,不存在就是添加父类属性clickAddAttr(index = null) {if (index == null) {this.addAttrType = "parent"this.attrIndex = null} else {this.addAttrType = "child"this.attrIndex = index}this.$refs.addAttrPop.open();},//添加属性弹窗的确认按钮async dialogConfirm(e) {if (!e) return;if (this.addAttrType == "parent") {let obj = {skuName: e,checked: true,children: []}let res = await skuCloudObj.add(obj)obj._id = res.id;this.skuArr.push(obj)//向数组中添加一个元素,就弹窗的确认按钮} else if (this.addAttrType == "child") {let obj = {name: e,checked: true}let id = this.skuArr[this.attrIndex]._id;let res = await skuCloudObj.updateChild(id, obj)this.skuArr[this.attrIndex].children.push(obj)}},//点击属性的复选框	改变了值,也相应改变了显示 后面也把值存到了数据库changeCheckbox(index) {this.skuArr[index].checked = !this.skuArr[index].checked},//点击属性值的子元素  改变了值,也相应改变了显示 后面也把值存到了数据库clickChlidBtn(index, cIdx) {this.skuArr[index].children[cIdx].checked = !this.skuArr[index].children[cIdx].checked},//点击选择属性clickSelect() {this.$refs.attrWrapPop.open(); //使用open方法弹出来if (this.skuArr.length) return;this.getSkuData();},//点击提交表单onSubmit() {this.$refs.goodsForm.validate().then(res => {this.toDataBase();}).catch(err => {console.log(err);})},//上传到云数据库async toDataBase() {//这里缺少一个更新的按钮,需要在list中去实现this.goodsFormData.thumb = this.goodsFormData.thumb.map(item => {return {url: item.url,name: item.name,extname: item.extname}})let res = await goodsCloudObj.add(this.goodsFormData)uni.showToast({title: "新增商品成功"})setTimeout(() => {uni.navigateBack()}, 1500)}}}
</script><style lang="scss" scoped>.goodsView {padding: 30rpx;.skuList {.item {padding: 30rpx;background: $page-bg-color;margin: 15rpx 0;@include flex-box-set(start);}}}.attrWrapper {padding: 30rpx;background: #fff;border-radius: 20rpx 20rpx 0 0;.head {@include flex-box();font-size: 34rpx;margin-bottom: 30rpx;.title {font-weight: bold;}.addAttr {color: $brand-theme-color-aux;}}.body {.item {border-top: 1px solid $border-color-light;&:last-child {border-bottom: 1px solid $border-color-light;}.top {padding: 30rpx 0;@include flex-box-set(start);.font {padding-left: 10rpx;font-weight: bold;}}.btnGroup {padding: 10rpx 0 30rpx;@include flex-box-set(start);flex-wrap: wrap;.btn {padding: 0rpx 25rpx;height: 60rpx;border: 1rpx solid $border-color-light;margin-right: 20rpx;border-radius: 10rpx;color: $text-font-color-2;margin-bottom: 20rpx;@include flex-box-set();&.active {border-color: $brand-theme-color;color: $brand-theme-color;background: rgba(236, 87, 79, 0.1);}}}}}.foot {padding: 50rpx 200rpx;}}
</style>

相关文章:

  • 架构选择、区别
  • 学习51单片机02
  • 麒麟服务器操作系统安装 MySQL 8 实战指南
  • 掌握 Kotlin Android 单元测试:MockK 框架深度实践指南
  • 【AI】用Dify实现一个模拟面试的功能
  • require/exports 或 import/export的联系和区别,各自的使用场景
  • skywalking使用教程
  • 基于51单片机和8X8点阵屏、矩阵按键的匹对消除类小游戏
  • Flask 是否使用类似 Spring Boot 的核心注解机制
  • MyBatis—动态 SQL
  • Mysql存储过程(附案例)
  • Gitee DevOps:中国企业数字化转型的加速引擎
  • Gitee DevOps:中国企业数字化转型的“本土化加速器“
  • 【Pandas】pandas DataFrame kurt
  • 深度剖析:Dify+Sanic+Vue+ECharts 搭建 Text2SQL 项目 sanic-web 的 Debug 实战
  • 【Unity】用事件广播的方式实现游戏暂停,简单且实用!
  • 单元化架构
  • <PLC><视觉><机器人>基于海康威视视觉检测和UR机械臂,如何实现N点标定?
  • IEEE 列表会议第五届机器人、自动化与智能控制国际会议
  • 软件架构风格系列(4):事件驱动架构
  • 高瓴、景林旗下公司美股持仓揭晓:双双增持中概股
  • 下周或迎外贸“抢出口”高峰,跨境电商敏感货物如何便利化“登机”?
  • 李成钢出席中国与《数字经济伙伴关系协定》成员部级会议
  • 马上评|清理“滥竽充数者”,为医者正名
  • 杨文庄当选中国人口学会会长,曾任国家卫健委人口家庭司司长
  • 马上评|这种“维权”已经不算薅羊毛,涉嫌犯罪了