9
头图

The last article uniapp cloud function tutorial ①: Login article , we have implemented simple login and registration logic. In this article, let's implement a small project of adding, deleting, modifying and verifying a product list. See the end of the text for the source code.

Scan code experience

.png or browser access

1. Database design

We need 2 tables: commodity classification table ( mall_type ) and commodity table ( mall_shop ). The commodity table is associated with the commodity classification table key

1.1 Product classification table ( mall_type )

image.png

{
  "bsonType": "object",
  "required": [],
  "permission": {
    "read": false,
    "create": false,
    "update": false,
    "delete": false
  },
  "properties": {
    "_id": {
      "description": "ID,系统自动生成"
    },
    "name": {
      "description": "商品一级分类"
    }
  }
}

1.2 Product list ( mall_shop )

image.png

{
  "bsonType": "object",
  "required": [],
  "permission": {
    "read": false,
    "create": false,
    "update": false,
    "delete": false
  },
  "properties": {
    "_id": {
      "description": "ID,系统自动生成"
    },
    "name": {
      "description": "商品名称"
    },
    "key": {
      "description": "对应的一级分类Id"
    },
    "icon": {
      "description": "商品图片"
    },
    "price": {
      "description": "价格"
    }
  }
}

only the key code is shown, the specific code can be viewed in the source code

2. Product list interface development

Here directly use the code of uviewui vertical classification
image.png

3. Development of commodity warehousing interface

3.1 Commodity classification function development

image.png

3.1.1 Product classification added function

Create a new cloud function addType , upload deployment and upload operation, add PATH /http/addtype

'use strict';
exports.main = async (event, context) => {
    const db = uniCloud.database(); //代码块为cdb
    const dbCmd = db.command
    const collection = db.collection('mall_type');

    let queryStringParameters = event.queryStringParameters
    let name = queryStringParameters['name']
    let callback = {}
    let isHasRes = await collection.where({
            name: dbCmd.eq(name)
        })
        .get()
    //简单做一下重复校验
    if (isHasRes.data.length) {
        callback = {
            mesg: '商品分类重复',
            code: 500
        }
    } else {
        let res = await collection.add({
            name: queryStringParameters['name']
        })
        callback = {
            mesg: '添加成功',
            code: 200,
            id: res.id
        }
    }

    return callback
};

Add form and interface

<u-form :model="form" ref="uForm">
    <u-form-item label="商品分类" prop="name" label-width='150'>
        <u-input v-model="form.name" placeholder="衣服、酒水等等" />
    </u-form-item>
</u-form>
<u-button @click="submit" type="primary" >提交</u-button>
addType() {
    uni.showLoading({
        title: '添加中'
    });
    uni.request({
        url: 'https://**.com/http/addtype',
        data: {
            name: this.form.name
        },
        success: (res) => {
            if (res.data.code == 200) {
                uni.showToast({
                    icon: 'success',
                    title: '添加成功'
                });
                this.$refs.uForm.resetFields()
            } else {
                uni.showToast({
                    icon: 'error',
                    title: res.data.mesg || '添加失败'
                });
            }
        },
        complete: () => {
            uni.hideLoading();
            this.getType()
        }
    })
},
3.1.2 Product classification query function

Create a new cloud function getType , upload deployment and upload operation, add PATH /http/gettype

exports.main = async (event, context) => {
    const db = uniCloud.database(); //代码块为cdb
    const res = await db.collection('mall_type').get()
    return res
};

Add to show how many classification interfaces there are currently, here in tag , it is also convenient to delete

<u-tag :text="item.name" v-for="(item,index) in typeList" :key="index" />
getType() {
    uni.showLoading({
        title: '获取分类中'
    });
    uni.request({
        url: 'https://**.com/http/gettype',
        success: (res) => {
            this.typeList = res.data.data || []
            uni.hideLoading()
        }
    })
}
3.1.2 Commodity category deletion function

Create a new cloud function delType , upload deployment and upload operation, add PATH /http/deltype

'use strict';
exports.main = async (event, context) => {
    const db = uniCloud.database(); 
    const dbCmd = db.command

    let id = event.queryStringParameters['id']
    const collection = db.collection('mall_type');
    let res = await collection.where({
        _id: dbCmd.eq(id)
    }).remove()
    
    return res
};

Add tag , and delete the secondary pop-up window

<u-tag :text="item.name" v-for="(item,index) in typeList" :key="index" closeable @close="tagClick(item,index)" />
<u-modal v-model="show" content="是否删除商品类型?" @confirm='confirm' show-cancel-button></u-modal>
tagClick(item, index) {
    this.show = true;
    this.selectItem = item
},
confirm() {
    uni.request({
        url: 'https://**.com/http/deltype',
        data: {
            id: this.selectItem._id
        },
        success: (res) => {
            uni.showToast({
                icon: 'success',
                title: '删除成功'
            });
            this.getType()
        }
    })
}

3.2 Product function development

image.png

3.2.1 Product addition function

Create a new cloud function addShop , upload deployment and upload operation, add PATH /http/addshop

'use strict';
exports.main = async (event, context) => {
    const db = uniCloud.database(); //代码块为cdb
    const dbCmd = db.command
    const collection = db.collection('mall_shop');
    //因为数据有base64图片,所以改为body获取
    let body = JSON.parse(event.body)
    let name = body['name']
    let key = body['key']
    let icon = body['icon']
    let price = body['price']
    let callback = {}
    let isHasRes = await collection.where({
            name: dbCmd.eq(name)
        })
        .get()

    if (isHasRes.data.length) {
        callback = {
            mesg: '商品重复',
            code: 500
        }
    } else {
        let res = await collection.add({
            name: name,
            key: key,
            icon: icon,
            price: price,
        })
        callback = {
            mesg: '添加成功',
            code: 200,
            id: res.id
        }
    }

    //返回数据给客户端
    return callback
};

The picture here is directly saved base64
Add form and interface

<u-form :model="form" ref="uForm" label-width='150'>
    <u-form-item label="商品名称" prop="name">
        <u-input v-model="form.name" placeholder="请输入商品名称" />
    </u-form-item>
    <u-form-item label="商品价格" prop="price">
        <u-input v-model="form.price" placeholder="请输入商品价格" type='number' />
    </u-form-item>
    <u-form-item label="商品类型" label-width="150" prop="keyLabel">
        <u-input type="select" :select-open="selectShow" v-model="form.keyLabel" placeholder="请选择商品类型"
            @click="selectShow = true"></u-input>
    </u-form-item>
    <u-form-item label="商品图片(<1MB)" prop="icon" label-width="150">
        <u-upload :max-size="1 * 1024 * 1024" ref="uUpload" width="160" height="160" @on-choose-complete='changeImg' :auto-upload="false" max-count="1"></u-upload>
    </u-form-item>
</u-form>
<u-button @click="submit" type="primary">提交</u-button>
<u-select mode="single-column" :list="typeList" v-model="selectShow" @confirm="selectConfirm"></u-select>

The picture upload is changed to upload by base64

changeImg(){
    let file = this.$refs.uUpload.lists[0]
    var fr = new FileReader();
    fr.onloadend = function(e) {
        this.form.icon = e.target.result;
    }.bind(this);
    fr.readAsDataURL(file.file);
},
addShop() {
    uni.showLoading({
        title: '添加中'
    });
    uni.request({
        url: 'https://f**.com/http/addshop',
        method: 'POST',
        data: {
            key: this.form.key,
            price: this.form.price,
            name: this.form.name,
            icon: this.form.icon,
        },
        success: (res) => {
            if (res.data.code == 200) {
                uni.showToast({
                    icon: 'success',
                    title: '添加成功'
                });
            //    this.$refs.uForm.resetFields()
            } else {
                uni.showToast({
                    icon: 'error',
                    title: res.data.mesg || '添加失败'
                });
            }
        },
        complete: () => {
            uni.hideLoading();
        }
    })
},
3.2.2 Product query function

Create a new cloud function getShop , upload deployment and upload operation, add PATH /http/getshop
The data format here can be uview according to the data format of the 0616fcc935dba0 product template

[
  {
    name: "xxx",
    foods: [
      {
        name: "xx",
        key: "xx",
        icon: "xx",
        price: "xx"
      }
    ]
  }
];
'use strict';
exports.main = async (event, context) => {
    const db = uniCloud.database(); //代码块为cdb
    const dbCmd = db.command
    //查询商品分类
    const typeRes = await db.collection('mall_type').get()
    const collection = db.collection('mall_shop');
    let shopList = []
    let typeList = typeRes.data || []
    for (var i = 0; i < typeList.length; i++) {
        //查询商品分类下的所属商品
        let list = await collection.where({
                key: dbCmd.eq(typeList[i]._id)
            })
            .get()
        let obj = {
            name: typeList[i].name,
            foods: list.data || []
        }
        shopList.push(obj)
    }

    return {
        data: shopList
    }
};

Go back to the mall template page just now, add the code to get the product, and tabbar the simulated data of 0616fcc935dbf7 with real data

getShop(){
    uni.showLoading({
        title: '获取商品中'
    });
    uni.request({
        url: 'https://f**.com/http/getShop',
        success: (res) => {
            this.tabbar = res.data.data || []
            uni.hideLoading()
        }
    })
},
3.2.3 Commodity deletion function

Create a new cloud function delShop , upload deployment and upload operation, add PATH /http/delshop

'use strict';
exports.main = async (event, context) => {
    const db = uniCloud.database(); //代码块为cdb
    const dbCmd = db.command


    let id = event.queryStringParameters['id']
    const collection = db.collection('mall_shop');
    let res = await collection.where({
        _id: dbCmd.eq(id)
    }).remove()
    //返回数据给客户端
    return res
};

In the mall list, we add a long press ( longpress ) delete function for the product, which is about line 24 of mallMenu.vue And add a second confirmation popup

<view class="thumb-box" v-for="(item1, index1) in item.foods" :key="index1"  @longpress='del(item1)'>
<image class="item-menu-image" :src="item1.icon" mode=""></image>
<view class="item-menu-name">{{item1.name}}</view>
</view>
、、、
、、、
<u-modal v-model="show" content="是否删除商品?" @confirm='confirm' show-cancel-button></u-modal>
del(item){
    this.delItem = item
    this.show = true
},
confirm(){
    uni.request({
        url: 'https://**.com/http/delshop',
        data: {
            id: this.delItem._id
        },
        success: (res) => {
            uni.showToast({
                icon: 'success',
                title: '删除成功'
            });
            this.getShop()
        }
    })
}

At this point, the product storage, viewing, and deletion functions have been developed

end

product picture material package download
source download
source download gitee
WX20210922-091703.png


雾岛听风
12.1k 声望8.6k 粉丝

丰富自己,胜过取悦别人。