《数据库原理与安全》实验报告分享

南京航空航天大学《数据库原理与安全》实验报告

前言

本篇报告主要分享《数据库原理与安全》的大报告,其中部分图片有缺失,需要完整版和源码的请私信博主哦~

实验一:安装SQL Server及相应工具

1.SQL Server的下载与安装

首先,到官方网站下载相应版本

https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads

按照官网步骤安装即可,具体的安装步骤参考以下链接:

https://blog.csdn.net/m0_51126511/article/details/126971149

实验二:启动SQL Server 和建数据库、表

1.启动SQL Server Management Studio

在home栏找到SQL Server Management Studio,点击打开。

打开后,显示需要连接到服务器,这里为方便演示,选择Windows身份验证。

点击连接后进入主界面。

2.建数据库、表

选中数据库,右键点击新建数据库,输入数据库名称为GOODS,点击确定。

在该GOODS数据库中需要建立三张表:categories(商品类别表)、products(商品名称表)、ratings(商品评论表),三张表的具体信息如下:

  • categories(商品类别表):
列名数据类型允许Null值信息
catIdintno商品类别id
categoryvarchar(50)no商品类别名称
  • products(商品名称表):
列名数据类型允许Null值信息
productIdintno商品名称id
namevarchar(MAX)no商品名称
catIdsintno商品所属类别id
  • ratings(商品评论表):
列名数据类型允许Null值信息
userIdintno用户Id
productIdintno商品id
ratingvarchar(50)yes用户评分
timestampvarchar(50)no时间戳
titlevarchar(50)yes评论标题
commentvarchar(50)yes评论内容

代码如下:

--创建categories表
DROP TABLE IF EXIT 'categories';
CREATE TABLE categories (
  catId int primary key not null,
  category varchar(50) not null
);

--创建products表
DROP TABLE IF EXIT 'products';
CREATE TABLE products(
  productId int primary key not null,
  name varchar(MAX) not null,
  catIds int not null
);

--创建ratings表
DROP TABLE IF EXIT 'ratings';
CREATE TABLE ratings(
    userId int not null;
    productId int not null;
    rating vatchar(50) null;
    timestamp varchar(50) not null;
    title varchar(50) null;
    comment varchar(50) null;
);

实验三:SQL语言的DDL

  • 本次实验了解DDL语言的CREATE、DROP、ALTER对表、索引、视图的操作,学会MySQL中用

    DDL语言进行对表、索引、视图的增加、删除和改动。

  • 创建表:详见实验二。

  • 创建索引:在表的数据量较大的时候,索引能够有效加快查询速度。数据库提供多种索引模式,在

    数据库系统内部实现。下面演示在categories表和products中建立索引:

CREATE UNIQUE INDEX idx_catId ON categories(catId ASC);
CREATE UNIQUE INDEX idx_productId ON products(productId ASC);
  • 删除索引:
DROP INDEX idx_catId;
DROP INDEX idx_productId;
  • 创建视图:可以使用以下 SQL 语句来创建一个视图,以统计每个分类下的商品总数
CREATE VIEW category_product_count AS
SELECT c.category_id, c.category_name, COUNT(p.product_id) AS product_count
FROM categories c
LEFT JOIN products p ON c.category_id = p.category_id
GROUP BY c.category_id, c.category_name;

​ 在上述 SQL 语句中,我们使用了 LEFT JOIN 来保证即便某个分类下没有商品,也能在视图中显示 0 个商品总数。对于每个分类,我们使用了 COUNT 函数来计算其下所有商品的总数,并将该结果命名为 product_count。最后通过 GROUP BY 对结果进行分组,以便将各个分类的商品数量统计结果合并。

创建完成后,我们可以通过下面的语句查询视图中的数据:

SELECT * FROM category_product_count;

实验四:SQL语言的DML初步

  • DML包括数据查询和数据更新两种数据操作语句。其中,数据查询指对数据库中的数据查询、统计、分组、排序等操作;数据更新指数据的插入、删除和修改等数据维护操作。

  • 向表中插入数据(数据来源于github上关于近期amazon商品开源评论集,以下将展示插入部分数据到products表和ratings表中):

    -- ----------------------------
    	-- Records of products
    -- ----------------------------
      INSERT INTO `products` VALUES (0, 'CSSMs Biology: Control in Cells and in Organisms Unit 5', 832);
      INSERT INTO `products` VALUES (1, 'Treasure Island', 832);
      INSERT INTO `products` VALUES (2, 'Collins Primary Dictionaries – Collins Junior Illustrated Dictionary', 832);
      INSERT INTO `products` VALUES (3, 'Partners in Crime', 832);
      INSERT INTO `products` VALUES (4, 'The Hobbit', 832);
      INSERT INTO `products` VALUES (5, 'Caps for Sale Book and CD', 832);
      INSERT INTO `products` VALUES (6, 'The Gulag Archipelago Volume 3: An Experiment in Literary Investigation', 832);
      INSERT INTO `products` VALUES (7, '150 Best Bathroom Ideas', 832);
      INSERT INTO `products` VALUES (8, 'The Forgotten Warrior', 832);
      INSERT INTO `products` VALUES (9, 'Free Fall', 832);
      INSERT INTO `products` VALUES (10, 'What\s So Bad About Gasoline?', 832);
      INSERT INTO `products` VALUES (11, 'Barbarians at the Gate: The Fall of RJR Nabisco', 832);
      INSERT INTO `products` VALUES (12, 'The Secret Circle: The Initiation and The Captive Part I', 832);
      INSERT INTO `products` VALUES (13, 'Alex & Me: How a Scientist and a Parrot Discovered a Hidden World of Animal Intelligence--And Formed a Deep Bond in the Process', 832);
      INSERT INTO `products` VALUES (14, 'Knocking on Heaven\'s Door: How Physics and Scientific Thinking Illuminate the Universe and the Modern World', 832);
      INSERT INTO `products` VALUES (15, 'The Boy Who Harnessed the Wind: Creating Currents of Electricity and Hope', 832);
      INSERT INTO `products` VALUES (16, 'My Booky Wook: A Memoir of Sex, Drugs, and Stand-Up', 832);
      INSERT INTO `products` VALUES (17, 'Alex & Me: How a Scientist and a Parrot Discovered a Hidden World of Animal Intelligence--And Formed a Deep Bond in the Process', 832);
      INSERT INTO `products` VALUES (18, 'Power: Why Some People Have It-and Others Don\'t', 832);
      INSERT INTO `products` VALUES (19, 'If You Have to Cry, Go Outside: and Other Things Your Mother Never Told You', 832);
      INSERT INTO `products` VALUES (20, 'The Concise Roget\'s International Thesaurus, Revised and Updated, 7th Edition', 832);
      ......
      
    -- ----------------------------
    -- Records of ratings
    -- ----------------------------
    INSERT INTO `ratings` VALUES (0, 0, 5, '1332172800', '不错的复习资料', '简洁、明了、没有废话');
    INSERT INTO `ratings` VALUES (0, 1650, 5, '1263139200', 'DSC', NULL);
    INSERT INTO `ratings` VALUES (0, 34489, 5, '1379001600', '还不错', '不错  我还没看  书很好  很新');
    INSERT INTO `ratings` VALUES (0, 36709, 1, '1380729600', '电视机质量差不能换', '我想打0分的 可惜不行  电视机用1个月黑屏自动关机又不能换,修的人也不知道电视机哪里坏了,让我们电视机用的彻底坏了再去修,质量实在太差,这电视机我现在开都不想开,有时候10分钟,有时候1小时自动关机,浪费');
    INSERT INTO `ratings` VALUES (0, 38334, 5, '1390233600', '好!', NULL);
    INSERT INTO `ratings` VALUES (0, 50679, 5, '1311350400', '好', NULL);
    INSERT INTO `ratings` VALUES (0, 51702, 4, '1365091200', '不错', NULL);
    INSERT INTO `ratings` VALUES (0, 59268, 5, '1321286400', '不错', NULL);
    INSERT INTO `ratings` VALUES (0, 75687, 5, '1255968000', 'DSC', NULL);
    INSERT INTO `ratings` VALUES (0, 102883, 4, '1302105600', '内容详细,准确性较高', NULL);
    INSERT INTO `ratings` VALUES (0, 131713, 5, '1268496000', 'DSC', NULL);
    INSERT INTO `ratings` VALUES (0, 142899, 2, '1375113600', '字好小  看着压抑', NULL);
    INSERT INTO `ratings` VALUES (0, 152355, 4, '1376841600', '个人感觉不错', NULL);
    INSERT INTO `ratings` VALUES (0, 155731, 5, '1365523200', '经典,很好', '经典,睡不着就看看的');
    INSERT INTO `ratings` VALUES (0, 180511, 3, '1302796800', '有点贵', NULL);
    INSERT INTO `ratings` VALUES (0, 180619, 5, '1375718400', '货真价实', '很不错,质量有保证!');
    INSERT INTO `ratings` VALUES (0, 185916, 5, '1371484800', 'jklhjlhjlhjk', NULL);
    INSERT INTO `ratings` VALUES (0, 196282, 5, '1365523200', '经典,很好', '经典,睡不着就看看的');
    INSERT INTO `ratings` VALUES (0, 214139, 5, '1388332800', '不错', NULL);
    INSERT INTO `ratings` VALUES (0, 277735, 5, '1376236800', '实用', '这本书不错,丰富的分离方法,比较详细的参考书。');
    INSERT INTO `ratings` VALUES (0, 286203, 5, '1252598400', 'DSC-2009第三季信息港评选十组代表艺人', NULL);
    INSERT INTO `ratings` VALUES (0, 300752, 5, '1318176000', '书的内容非常好!', '书的内容非常好!是“爱的教育”好素材!想象力更是出人意料!很值得珍藏的一本书,我是和孩子都看完后才买的。我经常推荐给别的孩子,也让孩子推荐给她的同学,“一只蜘蛛怎样救一头猪呢”,没有人能想象出更好的答案!');
    INSERT INTO `ratings` VALUES (0, 360192, 5, '1378396800', '挺好的', NULL);
    INSERT INTO `ratings` VALUES (0, 364433, 5, '1367942400', '强烈推荐', '物美价廉,质量上乘。');
    

    导入所有数据后,每个表显示为:

    • categories(商品类别表)

    • products(商品名称表)

    • ratings(商品评论表)

实验五:DML的数据查询

  • DML的数据查询指对数据库中的数据查询、统计、分组、排序等操作。查询语句可以分为简单查询、连接查询、嵌套查询和组合查询。

  • 简单查询

SELECT * FROM categories WHERE category = '图书音像'
  • 连接查询
SELECT categories.catId,categories.category,products.name FROM categories FULL JOIN products ON categories.catId = products.catIds;
  • 嵌套查询
SELECT products.productId,products.name,catIds FROM products
WHERE catIds IN
(SELECT categories.catId FROM categories WHERE category = '图书音像');

实验六:SQL语言的DCL

  • SQL的数据控制通过DCL(数据控制语言) 实现。DCL通过对数据库用户的授权和收权命令来实现有关数据的存取控制,以保证数据库的安全性。

  • 实验步骤:

    1. 使用最高权限的账号登录数据库,在安全性→登录名(鼠标右击)→新建登录名

    2. 在弹出新建登录名窗口的“常规”中,输入登录名test1和密码。

    3. 点击左边选择页中的“服务器角色”,来给新建用户授予权限。

    4. 点击左边选择页中的“用户映射”,选择用户可以登录的数据库、选择用户拥有的登录数据库的权限。

    5. 最后点击“状态”,授予连接到数据库引擎,登录名启用,最后点击确定就可以了。

实验七:商品评论平台小程序的设计与实现

1.实验背景

  • 随着电商平台的盛行,越来越多的消费者在网上购物,而商品评论是消费者决定购买的重要参考。
  • 然而,现有的商品评论往往存在着一些问题,如评论不真实、评论存在一定的偏差等。面对这些问题,很多电商平台开始采用匿名评论的方式,以便消费者可以更加自由地、真实地表达自己的观点。
  • 因此,为了提高消费者的购物体验,我开发了一款商品评论平台小程序。该小程序可以让消费者查看自己想要购买的商品评分、大众评价并对已有的商品上传使用感受,从而方便消费者提前了解商品的大致情况,以做出更准确的判断。

2.实验开发环境

  • 操作系统:win11/Ubuntu(64-bit)
  • 开发工具:微信开发者工具等
  • 服务器:云服务器ESC(1核(vCPU) 2 GiB)
  • 数据库工具:SQLServer19.0.2、Navicat Preminum绿色版

3.实验主要技术

  • 小程序框架:小程序原生框架可以快速实现视图层、逻辑层和数据层的分离和交互。

  • 组件库:小程序提供了大量的原生组件,如按钮、文本输入框、图片、音视频等组件,还有其他第三方组件库,如weUI、vant等。

  • API和SDK:小程序提供了一系列API和SDK,便于调用微信提供的底层能力,如获取用户信息、请求网络等功能。

  • 云开发:小程序提供了云开发服务,包括云函数、云数据库、云存储、云托管等功能,可以方便地进行后端开发和管理。

  • ES6及以上版本:小程序支持ES6及以上版本的JavaScript语法,包括箭头函数、let和const、模板字符串等。

  • CSS:小程序支持CSS3及以上的语法,例如flex、border-radius等, 方便开发者进行页面布局和美化。

    简要流程:

  • 用户在微信小程序中点击按钮,触发前端事件。微信小程序前端将触发事件和需要传递的数据发送给后端服务器,后端服务器接收到请求。后端服务器根据接收到的请求,在数据库中进行相关数据的查询或修改,将结果返回给小程序前端。微信小程序前端解析后端返回的数据,根据数据更新小程序视图的显示内容,用户看到更新后的小程序页面。

  • 在整个流程中,前端主要负责小程序的视图渲染和与用户的交互,后端负责对数据库进行操作,服务器则负责连接前后端并进行数据的传递。

4.核心功能

  • 用户验证

    采用微信官方认证方式,微信小程序需要接入微信开放平台的认证功能,通过微信开放平台给小程序授权,获取用户身份信息。这种方式可以从微信的后台验证用户身份,并获取微信开放平台提供的session_key和openid等信息,以确保用户的安全和隐私。

  • 查询模块

  • 添加模块

5.系统设计

(1)数据库设计
  • 创建数据库categories、products、ratings,具体内容见实验二。
  • 该数据库的E-R图如下:
(2)登录设计
import { HttpRequest } from '../../utils/requests/index'
import type { LoginResult } from '../../utils/requests/typing'

Component({
    /**
     * 组件的属性列表
     */
    properties: {
        show: {
            type: Boolean,
            value: false
        },
        title: {
            type: String,
            value: "登录"
        },
        buttons: {
            type: Array,
            value: [
                { "text": "取消" },
                { "text": "确认" }
            ]
        }
    },
    /**
     * 组件的初始数据
     */
    data: {
        login_code: '',
        encrypted_data: '',
        iv: ''
    },
    /**
     * 组件的方法列表
     */
    methods: {
        /**
         * 获取用户信息
         */
        getUserProfile() {
            return new Promise((resolve: any, reject: any) => {
                wx.getUserProfile({
                    desc: '展示用户信息',
                    success: (res) => {
                        this.setData({
                            encrypted_data: res.encryptedData,
                            iv: res.iv
                        });
                        resolve();
                    },
                    fail: reject
                })
            })
        },

        // 获取登陆的code
        getLoginCode() {
            return new Promise((resolve: any, reject: any) => {
                wx.login({
                    success: (res) => {
                        this.setData({
                            "login_code": res.code,
                        })
                        resolve();
                    },
                    fail: reject
                })
            })
        },

        /**
         * 展示轻提示
         */
        showToast(message: string, icon: any = "success", duration: number = 15000) {
            wx.hideToast()
            wx.showToast({
                title: message,
                icon: icon,
                duration: duration,
                mask: true
            })
        },

        /**
         * 登录
         */
        login() {
            // 判断是否获取到了登录code和用户信息
            Promise.all([this.getLoginCode(), this.getUserProfile()]).then(async () => {
                // 展示登陆中
                this.showToast("登陆中...", "loading", 60000)
                // 获取请求对象单例
                let requests = HttpRequest.getInstance()
                // 获取登录code
                let login_code = this.data.login_code
                // 获取用户信息密文
                let encrypted_data = this.data.encrypted_data
                // 获取盐
                let iv = this.data.iv
                // 发起请求
                let result = await requests.login(login_code, encrypted_data, iv)
                // 判断登录是否成功
                if (result) {
                    result as unknown as LoginResult
                    // 将token取出
                    const { token } = result.data.data
                    // 将token存储
                    wx.setStorageSync("token", token)
                    // 提示登录成功
                    this.showToast("登陆成功", "success", 15000)
                    // 收起登录框
                    this.setData({show:false})
                    // 跳转回上个页面
                    wx.navigateBack()
                } else {
                    // 提示登录失败
                    this.showToast("登录失败", "error", 15000)
                    // 收起登录框
                    this.setData({show:false})
                }
            }).catch((e) => {
                this.showToast("用户拒绝授权", "error", 1500)
                this.setData({ show: false })
                console.log(e);
            })
        },

        /**
         * 点击了按钮
         */
        onClicked(e: any) {
            // 判断点击的是哪个按钮
            // 点击取消
            if (e.detail.index === 0) {
                this.setData({
                    show: false
                })
                return
            }
            // 点击了确认,登录
            this.login()
        }
    }
})
(3)查询设计
import { HttpRequest } from '../../utils/requests/index'
import type { SearchCategoriesResult, SearchProductsResult, SearchProductsListRequestConfig, SearchProductsListResult } from '../../utils/requests/typing'

Component({
    // 数据监听器
    observers: {
        /**
         * 当商品列表发生变化时触发
         * @param value 新的数据
         */
        'products_list': function (value: Array<SearchProductsListResult>) {
            this.triggerEvent('productsListChange', value)
        }
    },

    /**
     * 组件生命周期
     */
    lifetimes: {
        /**
         * 在组件实例进入页面节点树时执行
         */
        attached: function () {
            this.setData({
                search: this.onSearch.bind(this),
                search_result: []
            })
        },
    },

    /**
     * 组件的属性列表
     */
    properties: {
        // 当前商品列表的页码
        page_num: {
            type: Number,
            value: 0
        },
        // 当前商品列表每页显示数量
        page_amount: {
            type: Number,
            value: 10
        },
        // 当前商品名称id列表
        c_id: {
            type: Number,
            value: undefined
        },
        // 当前商品种类id
        p_id: {
            type: Array,
            value: []
        },
        // 是否最新一页
        last_page: {
            type: Boolean,
            value: false
        },
        // 商品列表
        products_list: {
            type: Array,
            value: [{ productId: null, name: null, catId: null, category: null }]
        }
    },

    /**
     * 组件的初始数据
     */
    data: {
        // 当前搜索框内容
        search_inp_value: '',
        // 搜索框的提示内容
        placeholder: '请输入要搜索的商品类别',
        // 搜索方法
        search: (_value: string): void => { },
        // 是否展示搜索结果
        showResult: false,
        // 搜索结果
        search_result: [{}],
        // 是否展示搜索项菜单
        show_action_sheet: false,
        // 当前搜索项下标
        currIndex: 0,
        // 当前类别
        currCategories: { value: null, text: null },
        // 搜索项
        action_sheet_groups: [
            { text: '商品类别', value: 1 },
            { text: '商品名称', value: 2 },
            { text: '清空类别', value: 3 }
        ],
    },

    /**
     * 组件的方法列表
     */
    methods: {
        /**
         * 当用户点击搜索框触发
         */
        onSearchFocus() {
            this.setData({
                showResult: true
            })
        },
        /**
         * 当用户点击搜索框以外触发
         */
        onSearchBlur() {
            this.setData({
                showResult: false
            })
        },
        /**
         * 当用户点击搜索框清空触发
         */
        onSearchClear() {
            this.setData({
                showResult: false,
                search_result: []
            })
        },
        /**
         * 展示搜索项
         */
        showActionsheet() {
            this.setData({ show_action_sheet: true })
        },
        /**
         * 当用户点击遮罩层关闭搜索项
         */
        onClose() {
            this.setData({ show_action_sheet: false })
        },
        /**
         * 当用户点击搜索项的时候触发
         * @param e 
         */
        onActiontap(e: any) {
            let placeholder;
            let currIndex = 0;
            switch (e.detail.value) {
                case 1:
                    currIndex = 0
                    break
                case 2:
                    currIndex = 1
                    break
                case 3:
                    currIndex = this.data.currIndex
                    this.setData({ currCategories: { text: null, value: null } })
            }
            placeholder = `请输入要搜索的${this.data.action_sheet_groups[currIndex].text}`
            this.setData({ show_action_sheet: false, placeholder: placeholder, currIndex: currIndex })
        },

        /**
         * 搜索商品类别
         * @param keyword 关键字
         */
        searchCategories(keyword: string): Promise<Array<object>> {
            return new Promise<Array<object>>(async () => {
                // 获取请求对象单例
                let requests = HttpRequest.getInstance()
                // 发送请求
                let result = await requests.searchCategories(keyword)
                // 判断结果是否有效
                if (result) {
                    // 处理结果
                    let items = result.data.data.map((item: SearchCategoriesResult) => {
                        return { text: item.category, value: item.catId }
                    })
                    // 将结果处理
                    this.setData({
                        search_result: items
                    })
                } else {
                    this.setData({
                        search_result: []
                    })
                }
            })
        },
        /**
         * 搜索商品名字
         * @param _keyword 
         */
        searchProducts(keyword: string): Promise<Array<object>> {
            return new Promise<Array<object>>(async () => {
                // 获取请求对象单例
                let requests = HttpRequest.getInstance()
                // 发送请求
                let result = await requests.SearchProducts(keyword)
                // 判断结果是否有效
                if (result) {
                    // 将结果处理
                    let items = result.data.data.map((item: SearchProductsResult) => {
                        return { text: item.name, value: item.productId, catId: item.catIds }
                    })
                    // 获取当前的商品类别
                    let currCategories = this.data.currCategories
                    // 判断是否选择了商品类别
                    if (currCategories.value !== null) {
                        // 将符合当前类别的选项挑出来
                        items = items.filter((item) => {
                            return item.catId === currCategories.value
                        })
                    }
                    // 将结果展示
                    this.setData({
                        search_result: items
                    })
                } else {
                    this.setData({
                        search_result: []
                    })
                }
            })
        },

        /**
         * 当用户搜索输入时触发
         */
        onSearch(value: string): Promise<null> {
            // 判断用户搜索的是商品还是
            if (this.data.currIndex === 0) {
                this.searchCategories(value)
            } else {
                this.searchProducts(value)
            }
            return new Promise(() => { })
        },

        /**
         * 下一页
         */
        nextPage() {
            if (this.data.last_page){
                // 展示轻提示
                this.showToast("已经是最新一页", "none", 1500)
                return;
            } 
            this.setData({
                page_num: this.data.page_num + 1
            })
            this.getProductsList()
        },

        /**
         * 展示轻提示
         */
        showToast(message: string, icon: any = "success", duration: number = 15000) {
            wx.hideToast()
            wx.showToast({
                title: message,
                icon: icon,
                duration: duration,
                mask: true
            })
        },

        /**
         * 请求商品列表
         */
        getProductsList() {
            const option: SearchProductsListRequestConfig = {
                page_num: this.data.page_num,
                amount: this.data.page_amount
            }
            // 如果选择了分类
            if (this.data.c_id) option['category_id'] = this.data.c_id;
            // 如果有商品id数组
            if (this.data.p_id.length > 0) option['id_list'] = this.data.p_id;
            // 展示轻提示
            this.showToast("加载中...", "loading", 60000)
            new Promise(async () => {
                // 获取请求实例
                let requests = HttpRequest.getInstance()
                // 发起请求
                let result = await requests.SearchProductsList(option)
                // 判断结果是否有效
                if (result) {
                    let data = result.data.data
                    let is_last = false
                    if (data.length === 0) {
                        is_last = true
                    }
                    // 将结果保存
                    this.setData({
                        products_list: this.data.products_list.concat(result.data.data),
                        last_page: is_last
                    })
                    // 展示轻提示
                    this.showToast("加载完成", "success", 1500)
                } else {
                    this.setData({
                        search_result: []
                    })
                    // 展示轻提示
                    this.showToast("加载失败", "error", 1500)
                }
            })
        },

        /**
         * 当用户点击了搜索结果项之后触发
         * @param 事件对象
         */
        onSelectresult(e: any) {
            // 提取点击的结果项
            let dataset = e.currentTarget.dataset
            // 判断点击的是什么
            if (this.data.currIndex === 0) {
                // 设置当前的搜索参数
                this.setData({
                    // 要搜索的商品种类id
                    c_id: dataset.value,
                    // 要搜索的商品id列表
                    p_id: [],
                    // 要搜索的商品的页码
                    page_num: 1,
                    // 要搜索的商品的每页数量
                    page_amound: 10,
                    // 当前商品列表
                    products_list: [],
                    // 保存当前选择的类别
                    currCategories: dataset,
                    // 清空搜索结果
                    search_result: [],
                    // 保存当前选择类别的名字
                    search_inp_value: dataset.text
                })
            } else {
                // 点击的是商品名字
                // 设置当前的搜索参数
                this.setData({
                    // 要搜索的商品id列表
                    p_id: [dataset.value],
                    // 要搜索的商品的页码
                    page_num: 1,
                    // 要搜索的商品的每页数量
                    page_amound: 10,
                    // 当前商品列表
                    products_list: [],
                    // 清空搜索结果
                    search_result: [],
                    // 保存当前选择类别的名字
                    search_inp_value: dataset.text
                })
            }
            // 发送请求
            this.getProductsList();
        }
    }
})
(4)添加分类
import { HttpRequest } from '../../utils/requests/index'

const backend_app = getApp<IAppOption>();

Page({

    /**
     * 页面的初始数据
     */
    data: {
        category_input: '',
        categories: [{ catId: -1, category: "无" }],
        select_categories: { catId: -1, category: "无" },
        product_input: '',
        product_image: '',
        domain: ''
    },

    /**
     * 生命周期函数--监听页面加载
     */
    onLoad() {
        this.setData({
            domain: backend_app.globalData.domain
        })
        // 获取所有的商品分类
        new Promise(async () => {
            const request = HttpRequest.getInstance()
            const result = await request.GetCategory()
            if (result) {
                this.setData({
                    categories: result.data.data
                })
            }
        })
    },

    /**
     * 生命周期函数--监听页面初次渲染完成
     */
    onReady() {

    },

    /**
     * 生命周期函数--监听页面显示
     */
    onShow() {

    },

    /**
     * 生命周期函数--监听页面隐藏
     */
    onHide() {

    },

    /**
     * 生命周期函数--监听页面卸载
     */
    onUnload() {

    },

    /**
     * 页面相关事件处理函数--监听用户下拉动作
     */
    onPullDownRefresh() {

    },

    /**
     * 页面上拉触底事件的处理函数
     */
    onReachBottom() {

    },

    /**
     * 用户点击右上角分享
     */
    onShareAppMessage() {

    },

    /**
     * 展示轻提示
     */
    showToast(message: string, icon: any = "success", duration: number = 15000) {
        wx.hideToast()
        wx.showToast({
            title: message,
            icon: icon,
            duration: duration,
            mask: true
        })
    },

    /**
     * 当添加商品分类输入
     */
    onCategoryInput(e: any) {
        this.setData({
            category_input: e.detail.value
        })
    },

    /**
     * 添加分类按钮
     */
    onAddCategory() {
        if (!this.data.category_input.trim()) {
            this.showToast("请输入分类名称", "none", 1000)
            return
        }
        this.showToast("发起请求", "loding", 60000)
        new Promise(async () => {
            const request = HttpRequest.getInstance()
            const result = await request.AddCategory({
                category_name: this.data.category_input
            })
            if (result?.data.code === 0) {
                this.showToast("添加成功", "success", 1000)
            } else {
                this.showToast("添加失败", "error", 1000)
            }
        })
    },

    /**
     * 选择了商品分类
     * @param e
     */
    onCategoryChange(e: any) {
        this.setData({
            select_categories: this.data.categories[e.detail.value]
        })
    },

    /**
     * 输入了商品名称
     * @param e 
     */
    onProductInput(e: any) {
        this.setData({
            product_input: e.detail.value
        })
    },

    /**
     * 选择图片
     */
    onChooseImage() {
        const self = this;

        wx.chooseMedia({
            count: 1,
            sizeType: ['compressed'],
            sourceType: ['album', 'camera'],
            success(res) {
                wx.uploadFile({
                    url: `${backend_app.globalData.domain}/goods/upload_image`,
                    filePath: res.tempFiles[0].tempFilePath,
                    name: 'image',
                    header: {token:wx.getStorageSync("token")},
                    success: (res:any) => {
                        let data = JSON.parse(res.data)                        
                        if (data.code === 0) {
                            self.setData({
                                product_image: data.data.file_name
                            })
                        }
                    },
                    fail: () => {
                        self.showToast("上传图片失败", "error", 1000)
                    }
                  });
            },
            fail() {
                self.showToast("选择图片失败", "error", 1000)
            }
        });
    },

    /**
     * 添加商品
     */
    onAddProduct() {
        if (this.data.select_categories.catId === -1) {
            this.showToast("请选择商品分类", "none", 1000)
            return
        }
        if (this.data.product_input === '') {
            this.showToast("请填写商品名称", "none", 1000)
            return
        }
        if (this.data.product_image === '') {
            this.showToast("请选择商品图片", "none", 1000)
            return
        }
        this.showToast("添加中...", "loding", 60000)
        new Promise(async () => {
            const request = HttpRequest.getInstance()
            const result = await request.AddProduct({
                image:this.data.product_image,
                name: this.data.product_input, 
                category_id: this.data.select_categories.catId
            })
            if (result) {
                this.showToast("添加成功", "success", 1000)
            }else {
                this.showToast("添加失败", "error", 1000)
            }
        })
    }
})
(5)添加评论
import { HttpRequest } from '../../utils/requests/index'

const comment_app = getApp<IAppOption>()

Page({

    /**
     * 页面的初始数据
     */
    data: {
        // 商品id
        productId: 0,
        // 当前查询结果
        ratings_list: [{}],
        // 每个评论的展开状态
        show_list: [],
        // 评论总数量
        count: 0,
        // 当前页码
        page_num: 1,
        // 每页显示多少
        page_amount: 10,
        // 是否最新页
        is_last: false,
        // 展示评论列表的高度
        list_view_height: ['height: calc(100vh - 200rpx);', 'height: calc(100vh - 100rpx - 100rpx - 0px);'],
        // 评论操作台的展开状态
        console_show: false,
        // 键盘高度
        keyboard_height: 0,
        // 输入的评论内容
        input_value: { title: '', comment: '', rating: 5 },
        // 域名
        domain:''
    },

    /**
     * 生命周期函数--监听页面加载
     */
    onLoad(option: any) {
        // 监听键盘高度变化事件
        wx.onKeyboardHeightChange((res) => {
            let list_height = this.data.list_view_height
            list_height[1] = `height: calc(100vh - 100rpx - 100rpx - ${res.height}px);`

            this.setData({
                keyboard_height: res.height,
                list_view_height: list_height
            });
        });
        // 保存当前商品id
        this.setData({
            productId: option.productId,
            domain:comment_app.globalData.domain
        })
        this.requestRatings()
    },

    /**
     * 生命周期函数--监听页面初次渲染完成
     */
    onReady() {

    },

    /**
     * 生命周期函数--监听页面显示
     */
    onShow() {

    },

    /**
     * 生命周期函数--监听页面隐藏
     */
    onHide() {

    },

    /**
     * 生命周期函数--监听页面卸载
     */
    onUnload() {

    },

    /**
     * 页面相关事件处理函数--监听用户下拉动作
     */
    onPullDownRefresh() {

    },

    /**
     * 页面上拉触底事件的处理函数
     */
    onReachBottom() {

    },

    /**
     * 用户点击右上角分享
     */
    onShareAppMessage() {

    },

    /**
     * 下一页
     */
    nextPage() {
        if (this.data.is_last) {
            // 展示轻提示
            this.showToast("已经是最新一页", "none", 1500)
            return;
        }
        this.setData({
            page_num: this.data.page_num + 1
        })
        this.requestRatings()
    },
    /**
     * 请求商品评论
     */
    requestRatings() {
        this.showToast("加载中...", "loding", 1000)
        // 请求商品id
        new Promise(async () => {
            // 获取请求实例
            const request = HttpRequest.getInstance()
            // 发起请求
            let result = await request.GetRatingList({
                product_id: this.data.productId,
                page_num: this.data.page_num,
                amount: this.data.page_amount
            })
            // 判断是否可以用
            if (result) {
                this.showToast("加载完成", "success", 1000)
                // 将其保存
                this.setData({
                    ratings_list: this.data.ratings_list.concat(result.data.data.list),
                    count: result.data.data.count
                })
                if (result.data.data.list.length === 0) {
                    this.setData({
                        is_last: true
                    })
                }
            } else {
                this.showToast("加载失败", "error", 1000)
            }
        })
    },

    /**
     * 评论视图滑到底
     */
    onScrolltolower() {
        this.nextPage()
    },

    /**
     * 展示轻提示
     */
    showToast(message: string, icon: any = "success", duration: number = 15000) {
        wx.hideToast()
        wx.showToast({
            title: message,
            icon: icon,
            duration: duration,
            mask: true
        })
    },

    /**
     * 评论输入框获得焦点触发
     */
    onInputFocus() {
        this.setData({
            console_show: true
        })
    },

    /**
     * 评论输入框失去焦点触发
     */
    onInputBlur(e: any) {
        const input_value = this.data.input_value
        switch (e.currentTarget.dataset.type) {
            case 'title':
                input_value.title = e.detail.value
                break
            case 'comment':
                input_value.comment = e.detail.value
                break
            case 'rating':
                let num = parseFloat(e.detail.value); // 将输入框的值转换为数字
                if (isNaN(num)) { // 如果转换失败就将其设置为5
                    num = 5;
                } else if (num < 0) { // 如果小于0就将其设置为0
                    num = 0;
                } else if (num > 5) { // 如果大于5就将其设置为5
                    num = 5;
                }
                input_value.rating = num
        }
        // 当输入框失去焦点时,保存输入的值
        this.setData({
            console_show: false,
            input_value: input_value,
        })
    },

    // 发送评论
    sendComment: function () {
        const { input_value } = this.data;
        if (!input_value.title.trim()) {
            wx.showToast({
                title: '请输入评论标题',
                icon: 'none',
                duration: 2000,
            });
            return;
        } else if (!input_value.comment.trim()) {
            wx.showToast({
                title: '请输入评论内容',
                icon: 'none',
                duration: 2000,
            });
            return;
        }
        this.showToast('提交中...', 'loding', 60000)
        // 在这里处理发送评论的逻辑,例如调用后端接口发送评论
        new Promise(async () => {
            const request = HttpRequest.getInstance()
            const result = await request.AddRating({
                product_id: this.data.productId,
                title: this.data.input_value.title,
                comment: this.data.input_value.comment,
                rating: this.data.input_value.rating
            })
            if (result?.data.code === 0) {
                this.showToast('成功', 'success', 1000)
                this.setData({
                    ratings_list: this.data.ratings_list.concat([{
                        title: this.data.input_value.title,
                        comment: this.data.input_value.comment,
                        user_avatar_url: result.data.data.avatar_url,
                        user_name: result.data.data.nickName,
                        timestamp: result.data.data.timestamp,
                        rating: this.data.input_value.rating
                    }])
                })
            } else {
                this.showToast('失败', 'error', 1000)
            }
        })
    },
})
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值