uniapp-商城-61-后台 新增商品(添加商品到数据库)

完成商品的布局,完成商品的属性添加,最后的目的还是要完成数据添加,将我们前台的数据添加后台的数据库。

1、界面

2、点击提交完成商品添加

点击下方的提交按钮,将数据添加到数据库。

onSubmit  使用该函数---见3

            <view class="btnView">
                <button type="primary" @click="onSubmit">确认提交</button>
            </view>

3、提交按钮的处理逻辑

3.1 onSubmit接口

            //点击提交表单
            onSubmit() {
                this.$refs.goodsForm.validate().then(res => {
                    this.toDataBase();   //调用toDataBase   ---见 3.2

                }).catch(err => {
                    console.log(err);
                })
            },

这里看出,先找到了 goodsForm的表单名,进行验证,通过验证就执行 toDataBase

表单 goodsForm 在代码的开始部分已经定义了

验证采用的规则也在前面讲过了

3.2 toDataBase 接口到数据库保存

            //上传到云数据库
            async toDataBase() {
                //这里缺少一个更新的按钮,需要在list中去实现

                // console.log(this.goodsFormData.thumb);   //这里的数据太多了,需要处理一下
                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)

            }

3.2.1 处理图片  this.goodsFormData.thumb

前面商家信息 也遇到这个问题,商家信息也要处理 ,主要默认上传的图片的数据太多了,需要清理一下,截取我们需要的数据。

                //这里缺少一个更新的按钮,需要在list中去实现
                // console.log(this.goodsFormData.thumb);   //这里的数据太多了,需要处理一下
                this.goodsFormData.thumb = this.goodsFormData.thumb.map(item => {
                    return {
                        url: item.url,
                        name: item.name,
                        extname: item.extname
                    }
                })

 3.2.2 云对象上传商品数据

3.2.2.1、 创建云对象 green-mall-goods

   

代码:

const db = uniCloud.database();

async add(params){
        params.price = Number(params.price).toFixed(2)*100
        params.before_price = params.before_price ? Number(params.before_price).toFixed(2)*100 : null
        return await db.collection("green-mall-goods").add(params);        
    },

3.2.2.2 页面逻辑引入

在页面引入:

    const goodsCloudObj = uniCloud.importObject("green-mall-goods", {
        "customUI": true
    })

4、整体代码

<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中去实现// console.log(this.goodsFormData.thumb);   //这里的数据太多了,需要处理一下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>

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

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

相关文章

A级、B级弱电机房数据中心建设运营汇报方案

该方案围绕A 级、B 级弱电机房数据中心建设与运营展开,依据《数据中心设计规范》等标准,施工范围涵盖 10 类机房及配套设施,采用专业化施工团队与物资调配体系,强调标签规范、线缆隐藏等细节管理。运营阶段建立三方协同运维模式,针对三级故障制定30 分钟至 1 小时响应机制…

RAG数据处理:PDF/HTML

RAG而言用户输入的数据通常是各种各样文档&#xff0c;本文主要采用langchain实现PDF/HTML文档的处理方法 PDF文档解析 PDF文档很常见格式&#xff0c;但内部结构常常较复杂&#xff1a; 复杂的版式布局多样的元素&#xff08;段落、表格、公式、图片等&#xff09;文本流无…

时源芯微| KY键盘接口静电浪涌防护方案

KY键盘接口静电浪涌防护方案通过集成ESD保护元件、电阻和连接键&#xff0c;形成了一道有效的防护屏障。当键盘接口受到静电放电或其他浪涌冲击时&#xff0c;该方案能够迅速将过电压和过电流引导至地&#xff0c;从而保护后续电路免受损害。 ESD保护元件是方案中的核心部分&a…

Java 原生网络编程(BIO | NIO | Reactor 模式)

1、基本常识 Socket 是应用层与 TCP/IP 协议族通信的中间软件抽象层&#xff0c;是一组接口&#xff0c;使用了门面模式对应用层隐藏了传输层以下的实现细节。TCP 用主机的 IP 地址加上主机端口号作为 TCP 连接的端点&#xff0c;该端点叫做套接字 Socket。 比如三次握手&…

OpenCV透视变换

概念 OpenCV 透视变换是将图像从一个视平面投影到另一个视平面的过程&#xff0c;也叫投影映射 &#xff0c;属于空间立体三维变换。它基于透视原理&#xff0c;通过 33 的变换矩阵作用于图像像素坐标来实现映射转换 &#xff0c;能模拟人眼或相机镜头观看三维空间物体时的透视…

STM32F103定时器1每毫秒中断一次

定时器溢出中断&#xff0c;在程序设计中经常用到。在使用TIM1和TIM8溢出中断时&#xff0c;需要注意“TIM_TimeBaseStructure.TIM_RepetitionCounter0;”&#xff0c;它表示溢出一次&#xff0c;并可以设置中断标志位。 TIM1_Interrupt_Initializtion(1000,72); //当arr1…

数据库——SQL约束窗口函数介绍

4.SQL约束介绍 &#xff08;1&#xff09;主键约束 A、基本内容 基本内容 p r i m a r y primary primary k e y key key约束唯一表示数据库中的每条记录主键必须包含唯一的值&#xff08;UNIQUE&#xff09;主键不能包含NULL值&#xff08;NOT NULL&#xff09;每个表都应…

【typenum】 8 常量文件(consts.rs)

一、源码 这段代码通过类型级编程&#xff08;type-level programming&#xff09;在编译期实现数值计算。以下是常量定义部分&#xff1a; // THIS IS GENERATED CODE #![allow(missing_docs)] use crate::int::{NInt, PInt}; /** Type aliases for many constants.This fil…

第8讲、Multi-Head Attention 的核心机制与实现细节

&#x1f914; 为什么要有 Multi-Head Attention&#xff1f; 单个 Attention 机制虽然可以捕捉句子中不同词之间的关系&#xff0c;但它只能关注一种角度或模式。 Multi-Head 的作用是&#xff1a; 多个头 多个视角同时观察序列的不同关系。 例如&#xff1a; 一个头可能专…

百度智能云千帆携手联想,共创MCP生态宇宙

5月7日&#xff0c;2025联想创新科技大会&#xff08;Tech World&#xff09;在上海世博中心举行&#xff0c;本届大会以“让AI成为创新生产力”为主题。会上&#xff0c;联想集团董事长兼CEO杨元庆展示了包括覆盖全场景的超级智能体矩阵&#xff0c;包括个人超级智能体、企业超…

【OpenCV】帧差法、级联分类器、透视变换

一、帧差法&#xff08;移动目标识别&#xff09;&#xff1a; 好处&#xff1a;开销小&#xff0c;不怎么消耗CPU的算力&#xff0c;对硬件要求不高&#xff0c;但只适合固定摄像头 1、优点 计算效率高&#xff0c;硬件要求 响应速度快&#xff0c;实时性强 直接利用连续帧…

数据库迁移的艺术:团队协作中的冲突预防与解决之道

title: 数据库迁移的艺术:团队协作中的冲突预防与解决之道 date: 2025/05/17 00:13:50 updated: 2025/05/17 00:13:50 author: cmdragon excerpt: 在团队协作中,数据库迁移脚本冲突是常见问题。通过Alembic工具,可以有效地管理和解决这些冲突。冲突预防的四原则包括功能分…

Linux常用命令43——bunzip2解压缩bz2文件

在使用Linux或macOS日常开发中&#xff0c;熟悉一些基本的命令有助于提高工作效率&#xff0c;bunzip2可解压缩.bz2格式的压缩文件。bunzip2实际上是bzip2的符号连接&#xff0c;执行bunzip2与bzip2 -d的效果相同。本篇学习记录bunzip2命令的基本使用。 首先查看帮助文档&#…

盲盒:拆开未知的惊喜,收藏生活的仪式感

一、什么是盲盒&#xff1f;—— 一场关于“未知”的浪漫冒险 盲盒&#xff0c;是一种充满神秘感的消费体验&#xff1a; &#x1f381; 盒中藏惊喜——每个盲盒外观相同&#xff0c;但内含随机商品&#xff0c;可能是普通款、稀有款&#xff0c;甚至是“隐藏款”&#xff1b;…

Android 中使用通知(Kotlin 版)

1. 前置条件 Android Studio&#xff1a;确保使用最新版本&#xff08;2023.3.1&#xff09;目标 API&#xff1a;最低 API 21&#xff0c;兼容 Android 8.0&#xff08;渠道&#xff09;和 13&#xff08;权限&#xff09;依赖库&#xff1a;使用 WorkManager 和 Notificatio…

使用大模型预测急性结石性疾病技术方案

目录 1. 数据预处理与特征工程伪代码 - 数据清洗与特征处理数据预处理流程图2. 大模型构建与训练伪代码 - 模型训练模型训练流程图3. 术前预测系统伪代码 - 术前风险评估术前预测流程图4. 术中实时调整系统伪代码 - 术中风险预警术中调整流程图5. 术后护理系统伪代码 - 并发症预…

每日Prompt:生成自拍照

提示词 帮我生成一张图片&#xff1a;图片风格为「人像摄影」&#xff0c;请你画一张及其平凡无奇的iPhone对镜自拍照&#xff0c;主角是穿着JK风格cos服的可爱女孩&#xff0c;在自己精心布置的可按风格的房间内的落地镜前用后置摄像头随手一拍的快照。照片开启了闪光灯&…

动态规划-64.最小路径和-力扣(LetCode)

一、题目解析 从左上角到右下角使得数字总和最小且只能向下或向右移动 二、算法原理 1.状态表示 我们需要求到达[i,j]位置时数字总和的最小值&#xff0c;所以dp[i][j]表示&#xff1a;到达[i,j]位置时&#xff0c;路径数字总和的最小值。 2.状态转移方程 到达[i,j]之前要先…

LeetCode LCR 010 和为 K 的子数组 (Java)

两种解法详解&#xff1a;暴力枚举与前缀和哈希表寻找和为k的子数组 在解决数组中和为k的连续子数组个数的问题时&#xff0c;我们可以采用不同的方法。本文将详细解析两种常见的解法&#xff1a;暴力枚举法和前缀和结合哈希表的方法&#xff0c;分析它们的思路、优缺点及适用…

OpenVLA (2) 机器人环境和环境数据

文章目录 [TOC](文章目录) 前言1 BridgeData V21.1 概述1.2 硬件环境 2 数据集2.1 场景与结构2.2 数据结构2.2.1 images02.2.2 obs_dict.pkl2.2.3 policy_out.pkl 3 close question3.1 英伟达环境3.2 LIBERO 环境更适合仿真3.3 4090 运行问题 前言 按照笔者之前的行业经验, 数…