• 【易售小程序项目】修改“我的”界面前端实现;查看、重新编辑、下架自己发布的商品【后端基于若依管理系统开发】


    “我的”界面修改

    效果

    在这里插入图片描述

    界面实现

    界面的实现使用了一张png图片,图片直接使用PS制作一张即可,资源下载可以查看易售小程序我的界面上方背景

    在这里插入图片描述

    将图片放到项目的静态资源文件夹下面

    在这里插入图片描述

    使用下方的代码来设置页面的背景图片

    .background {
    	background-image: url("@/static/uniappMineBackground.png");
    	background-repeat: no-repeat;
    	background-size: 100%;
    	width: 100%;
    	padding-top: 20px;
    	margin-bottom: 25rpx;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8

    要想实现元素悬浮在背景图片上面的感觉,只需要修改一下元素的透明度即可,如下面的代码

    .top {
    	background: rgba(255, 255, 255, 0.5);
    	border-radius: 15px;
    	box-shadow: 5rpx 10rpx 20rpx rgba(0, 0, 0, 0.2);
    	margin: 0px 20rpx;
    	height: 350rpx;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7

    界面整体代码

    <template>
    	<view class="container">
    		<view class="background">
    			<view class="top">
    				
    				<view class="userDisplay">
    					<view class="avatar" @click="this.avatarChangeShow=true">
    						<u--image :src="userInfo.avatar" width="120rpx" height="120rpx" shape="circle"
    							:lazy-load="true">
    							<view slot="error" style="font-size: 24rpx;">加载失败view>
    						u--image>
    					view>
    					<view class="nameView">
    						<view>
    							<view style="font-weight: bold;font-size: 36rpx;color: #000000;">{{userInfo.nickName}}
    							view>
    							<view style="font-size: 30rpx;display: flex;margin-top: 10rpx;color: #6f6d71;">
    								
    								<text class="selfIntroductionText">简介:{{userInfo.selfIntroduction}}text>
    							view>
    						view>
    					view>
    				view>
    				<view class="buttonView">
    					<view class="buttonItem" @click="goToMyPublish">
    						<text class="iconfont" style="margin-right: 15rpx;font-size: 50rpx;">text>
    						我发布的
    					view>
    					
    					<view style="border-right: #2b92ff solid 1px;height: 40rpx;">
    					view>
    					<view class="buttonItem">
    						<text class="iconfont" style="margin-right: 15rpx;font-size: 50rpx;">text>
    						我的足迹
    					view>
    				view>
    			view>
    
    		view>
    
    		<view class="userMessage">
    	
    			<u-cell-group>
    				<u-cell name="userName" :value="userInfo.userName" :isLink="true"
    					@click="editMessage('userName',userInfo.userName,'用户名')">
    					<view slot="title" class="u-slot-title">
    						<text class="iconfont" style="margin-right: 10rpx;">text>
    						<text class="u-cell-text">用户名text>
    					view>
    				u-cell>
    				<u-cell name="nickName" :value="userInfo.nickName" :isLink="true"
    					@click="editMessage('nickName',userInfo.nickName,'昵称')">
    					<view slot="title" class="u-slot-title">
    						<text class="iconfont" style="margin-right: 10rpx;">text>
    						<text class="u-cell-text">昵称text>
    					view>
    				u-cell>
    				<u-cell name="avatar" :isLink="true" @click="editMessage('avatar',userInfo.avatar,'头像')">
    					<view slot="title" class="u-slot-title">
    						<text class="iconfont" style="margin-right: 10rpx;">text>
    						<text class="u-cell-text">头像text>
    					view>
    				u-cell>
    				<u-cell name="schoolName" :value="userInfo.schoolName" :isLink="true"
    					@click="editMessage('schoolId',userInfo.schoolName,'大学',userInfo.schoolId)">
    					<view slot="title" class="u-slot-title">
    						<text class="iconfont" style="margin-right: 10rpx;">text>
    						<text class="u-cell-text">大学text>
    					view>
    				u-cell>
    				<u-cell name="campusName" :value="userInfo.campusName" :isLink="true"
    					@click="editMessage('campusId',userInfo.campusName,'校区',userInfo.campusId,userInfo.schoolId)">
    					<view slot="title" class="u-slot-title">
    						<text class="iconfont" style="margin-right: 10rpx;">text>
    						<text class="u-cell-text">校区text>
    					view>
    				u-cell>
    				<u-cell name="sex" :value="sexName" :isLink="true" @click="editMessage('sex',userInfo.sex,'性别')">
    					<view slot="title" class="u-slot-title">
    						<text class="iconfont" style="margin-right: 10rpx;">text>
    						<text class="u-cell-text">性别text>
    					view>
    				u-cell>
    				<u-cell name="email" :value="userInfo.email" :isLink="true"
    					@click="editMessage('email',userInfo.email,'邮箱')">
    					<view slot="title" class="u-slot-title">
    						<text class="iconfont" style="margin-right: 10rpx;">text>
    						<text class="u-cell-text">邮箱text>
    					view>
    				u-cell>
    				<u-cell name="contactInformation" :isLink="true"
    					@click="editMessage('contactInformation',userInfo.contactInformation,'联系方式')">
    					<view slot="title" class="u-slot-title">
    						<text class="iconfont" style="margin-right: 10rpx;">text>
    						<text class="u-cell-text">联系方式text>
    					view>
    				u-cell>
    				<u-cell name="selfIntroduction" :isLink="true"
    					@click="editMessage('selfIntroduction',userInfo.selfIntroduction,'自我介绍')">
    					<view slot="title" class="u-slot-title">
    						<text class="iconfont" style="margin-right: 10rpx;">text>
    						<text class="u-cell-text">自我介绍text>
    					view>
    				u-cell>
    				<u-cell name="password" :isLink="true" @click="editMessage('password','-1','修改密码')">
    					<view slot="title" class="u-slot-title">
    						<text class="iconfont" style="margin-right: 10rpx;">text>
    						<text class="u-cell-text">修改密码text>
    					view>
    				u-cell>
    				<u-cell :isLink="true" @click="logout()">
    					<view slot="title" class="u-slot-title">
    						<text class="iconfont" style="margin-right: 10rpx;">text>
    						<text class="u-cell-text">退出账号text>
    					view>
    				u-cell>
    			u-cell-group>
    		view>
    	view>
    template>
    
    <script>
    	import {
    		logout
    	} from "@/api/login";
    	import {
    		getUserProfileVo
    	} from "@/api/user";
    
    	export default {
    
    		data() {
    			return {
    				userInfo: {
    					avatar: '',
    					nickName: "你好呀",
    					userName: "admin",
    					schoolName: "XX大学",
    					campusName: "XX学院",
    					sex: 0,
    					selfIntroduction: "自我介绍,打撒活动啊速宏达搜好滴傻大搜到阿斯顿撒旦好骚",
    					contactInformation: "联系方式",
    					email: "32136712361@qq.com"
    				},
    				sexName: '其他',
    			}
    		},
    		created() {
    			// this.getUserProfile();
    		},
    		onShow: function() {
    			console.log("查询个人信息")
    			this.getUserProfile();
    		},
    
    		methods: {
    			editMessage(editKey, currentValue, editName, valueId = undefined, schoolId = undefined) {
    				uni.navigateTo({
    					url: "/pages/my/profileEdit?editKey=" + editKey + "¤tValue=" + currentValue +
    						"&editName=" + editName + "&valueId=" + valueId + "&schoolId=" + schoolId
    				})
    			},
    			/**
    			 * 登出账号
    			 */
    			logout() {
    				// console.log("退出账号:")
    				logout().then(res => {
    					// console.log("退出账号:" + JSON.stringify(res));
    					// 清除所有缓存
    					uni.clearStorageSync();
    					// 跳转到登录页
    					uni.redirectTo({
    						url: "/pages/login/login"
    					})
    				})
    			},
    			/**
    			 * 获取用户信息
    			 */
    			getUserProfile() {
    				getUserProfileVo().then(res => {
    					// console.log("getUserProfile:" + JSON.stringify(res));
    					this.userInfo = res.data;
    					this.sexName = this.getSexName(this.userInfo.sex);
    					console.log("头像:" + this.userInfo.avatar);
    					// console.log("this.userInfo.sex:" + this.userInfo.sex + ",this.sexName:" + this.sexName);
    					// console.log("this.userInfo:" + JSON.stringify(this.userInfo));
    				})
    			},
    			getSexName(type) {
    				if (type == 0) {
    					return "男";
    				} else if (type == 1) {
    					return "女";
    				} else if (type == 2) {
    					return "其他";
    				}
    			},
    			/**
    			 * 查看我的发布
    			 */
    			goToMyPublish(){
    				uni.navigateTo({
    					url:"/pages/myPublish/myPublish"
    				})
    			}
    		}
    	}
    script>
    
    <style lang="scss">
    	.container {
    		background: #F4F5F7;
    		min-height: 100vh;
    		font-family: sans-serif;
    
    		.background {
    			background-image: url("@/static/uniappMineBackground.png");
    			background-repeat: no-repeat;
    			background-size: 100%;
    			width: 100%;
    			// height: 150px;
    			padding-top: 20px;
    			margin-bottom: 25rpx;
    
    			.top {
    				background: rgba(255, 255, 255, 0.5);
    				border-radius: 15px;
    				box-shadow: 5rpx 10rpx 20rpx rgba(0, 0, 0, 0.2);
    				margin: 0px 20rpx;
    				height: 350rpx;
    
    				.userDisplay {
    					display: flex;
    					padding: 25rpx;
    
    					.avatar {
    						display: flex;
    						justify-content: center;
    						align-items: center;
    						margin-right: 20rpx;
    						background: #ffffff;
    						border-radius: 50%;
    						padding: 3px;
    					}
    
    					.nameView {
    						display: flex;
    						justify-content: center;
    						align-items: center;
    
    						.selfIntroductionText {
    							overflow: hidden;
    							text-overflow: ellipsis;
    							display: -webkit-box;
    							/* 显示1行 */
    							-webkit-line-clamp: 1;
    							-webkit-box-orient: vertical;
    						}
    					}
    				}
    
    				.buttonView {
    					display: flex;
    					height: 180rpx;
    					align-items: center;
    
    					.buttonItem {
    						flex: 1;
    						display: flex;
    						align-items: center;
    						justify-content: center;
    						font-size: 32rpx;
    					}
    				}
    			}
    
    		}
    
    		.userMessage {
    			margin: 0rpx 20rpx;
    			background: #F4F5F7;
    			border-radius: 20rpx;
    		}
    	}
    style>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74
    • 75
    • 76
    • 77
    • 78
    • 79
    • 80
    • 81
    • 82
    • 83
    • 84
    • 85
    • 86
    • 87
    • 88
    • 89
    • 90
    • 91
    • 92
    • 93
    • 94
    • 95
    • 96
    • 97
    • 98
    • 99
    • 100
    • 101
    • 102
    • 103
    • 104
    • 105
    • 106
    • 107
    • 108
    • 109
    • 110
    • 111
    • 112
    • 113
    • 114
    • 115
    • 116
    • 117
    • 118
    • 119
    • 120
    • 121
    • 122
    • 123
    • 124
    • 125
    • 126
    • 127
    • 128
    • 129
    • 130
    • 131
    • 132
    • 133
    • 134
    • 135
    • 136
    • 137
    • 138
    • 139
    • 140
    • 141
    • 142
    • 143
    • 144
    • 145
    • 146
    • 147
    • 148
    • 149
    • 150
    • 151
    • 152
    • 153
    • 154
    • 155
    • 156
    • 157
    • 158
    • 159
    • 160
    • 161
    • 162
    • 163
    • 164
    • 165
    • 166
    • 167
    • 168
    • 169
    • 170
    • 171
    • 172
    • 173
    • 174
    • 175
    • 176
    • 177
    • 178
    • 179
    • 180
    • 181
    • 182
    • 183
    • 184
    • 185
    • 186
    • 187
    • 188
    • 189
    • 190
    • 191
    • 192
    • 193
    • 194
    • 195
    • 196
    • 197
    • 198
    • 199
    • 200
    • 201
    • 202
    • 203
    • 204
    • 205
    • 206
    • 207
    • 208
    • 209
    • 210
    • 211
    • 212
    • 213
    • 214
    • 215
    • 216
    • 217
    • 218
    • 219
    • 220
    • 221
    • 222
    • 223
    • 224
    • 225
    • 226
    • 227
    • 228
    • 229
    • 230
    • 231
    • 232
    • 233
    • 234
    • 235
    • 236
    • 237
    • 238
    • 239
    • 240
    • 241
    • 242
    • 243
    • 244
    • 245
    • 246
    • 247
    • 248
    • 249
    • 250
    • 251
    • 252
    • 253
    • 254
    • 255
    • 256
    • 257
    • 258
    • 259
    • 260
    • 261
    • 262
    • 263
    • 264
    • 265
    • 266
    • 267
    • 268
    • 269
    • 270
    • 271
    • 272
    • 273
    • 274
    • 275
    • 276
    • 277
    • 278
    • 279
    • 280
    • 281
    • 282
    • 283
    • 284
    • 285
    • 286
    • 287
    • 288
    • 289

    查看已发布商品

    界面效果

    在这里插入图片描述

    商品数据表

    在这里插入图片描述

    因为使用了status字段来表示了商品的状态,直接设置不同的status就可以分别查询出在售草稿或者已下架的商品

    后端

    上架、下架商品

    实现产品状态的切换非常简单,直接设置状态并发送请求即可。要注意的是,后台要判断执行修改的用户是不是当前登录的用户,防止用户直接绕过前端发请求随意修改其他用户的商品

    Controller
    /**
     * 修改商品
     */
    @PreAuthorize("@ss.hasPermi('market:product:edit')")
    @Log(title = "商品", businessType = BusinessType.UPDATE)
    @PutMapping
    public AjaxResult edit(@RequestBody Product product) {
        // 设置当前登录用户的用户id
        product.setUserId(getLoginUser().getUserId());
        if (product.getStatus() == 0) {
            // 如果想要将商品改成发布状态,需要对数据库的商品进行校验
            Product productInDatabase = productService.getById(product.getId());
            ProductValidate.validate(productInDatabase);
        }
        return toAjax(productService.updateProduct(product));
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    Mapper

    通过添加and user_id = #{userId},确保修改人为商品主人才能修改商品信息

    <update id="updateProduct" parameterType="Product">
        update product
        <trim prefix="SET" suffixOverrides=",">
            <if test="createTime != null">create_time = #{createTime},if>
            <if test="updateTime != null">update_time = #{updateTime},if>
            <if test="isDeleted != null">is_deleted = #{isDeleted},if>
            <if test="name != null and name != ''">name = #{name},if>
            <if test="description != null">description = #{description},if>
            <if test="originalPrice != null">original_price = #{originalPrice},if>
            <if test="price != null">price = #{price},if>
            <if test="productCategoryId != null">product_category_id = #{productCategoryId},if>
            <if test="userId != null">user_id = #{userId},if>
            <if test="reviewerId != null">reviewer_id = #{reviewerId},if>
            <if test="fineness != null">fineness = #{fineness},if>
            <if test="number != null and number != ''">number = #{number},if>
            <if test="unit != null and unit != ''">unit = #{unit},if>
            <if test="status != null">status = #{status},if>
            <if test="isContribute != null">is_contribute = #{isContribute},if>
            <if test="functionalStatus != null">functional_status = #{functionalStatus},if>
            <if test="brandId != null">brand_id = #{brandId},if>
        trim>
        where id = #{id} and user_id = #{userId}
    update>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23

    界面整体代码

    <template>
    	<view class="outside">
    		<u-toast ref="uToast">u-toast>
    		<u-tabs :list="tabNameList" @click="tabClick">u-tabs>
    		<view class="container">
    			<u-empty mode="data" icon="http://cdn.uviewui.com/uview/empty/data.png" v-if="productVoList.length==0"
    				:text="emptyText">
    			u-empty>
    
    			<view v-for="(productVo,index) in productVoList" class="item">
    				<view class="productItem">
    					<u--image v-if="productVo.picList!=null&&productVo.picList.length>0" :showLoading="true"
    						:src="productVo.picList[0].address" width="200rpx" height="200rpx" radius="10" mode="aspectFill"
    						:fade="true" duration="450" @click="seeProductDetail(productVo)">
    						<view slot="error" style="font-size: 24rpx;">加载失败view>
    					u--image>
    					<view style="margin: 10rpx;">view>
    					<view class="productMessage" style="width: 100%;">
    						<view @click="seeProductDetail(productVo)">
    							<view class="productTitle">{{productVo.name}}view>
    							<view class="price">¥<text class="number">{{productVo.price}}text>view>
    						view>
    						<view style="display: flex; justify-content: space-between;align-items: center;width: 100%;">
    							<view style="font-size: 28rpx;color: #B6B6B6;">
    								{{formatDateToString(productVo.createTime)}}
    							view>
    							<view style="display: flex;align-items: center;">
    								<view class="buttonView" @click="editProduct(productVo)"
    									style="border: #00BFFF solid 1px;color: #00BFFF;">编 辑view>
    								<view style="width: 15rpx;">view>
    								<view class="buttonView" @click="offShelf(productVo.id)"
    									style="border: #FF5A5F  solid 1px;color: #FF5A5F;" v-if="productStatus==0">下 架
    								view>
    								<view class="buttonView" @click="onShelf(productVo.id)"
    									style="border: #76D7C4  solid 1px;color: #76D7C4;" v-if="productStatus==3">上 架
    								view>
    								<view class="buttonView" @click="onShelf(productVo.id)" v-if="productStatus==2"
    									style="border: #76D7C4  solid 1px;color: #76D7C4;">重新上架view>
    							view>
    						view>
    					view>
    				view>
    
    
    			view>
    		view>
    
    	view>
    template>
    
    <script>
    	import {
    		listProductVo,
    		updateProduct
    	} from "@/api/market/product.js";
    
    	export default {
    		data() {
    			return {
    				tabNameList: [{
    					name: '在售',
    				}, {
    					name: '草稿',
    				}, {
    					name: '已下架'
    				}],
    				page: {
    					pageNum: 1,
    					pageSize: 10
    				},
    				productVoList: [],
    				emptyText: '您还没有商品处于出售状态哟',
    				// 商品状态 0:在售 1:售出 2:下架 3:草稿
    				productStatus: 0,
    			}
    		},
    		created() {
    			this.listProductVo();
    		},
    		methods: {
    			tabClick(item) {
    				// console.log('item', item);
    				if (item.name == "在售") {
    					this.emptyText = "您还没有商品处于出售状态哟";
    					this.productStatus = 0;
    				} else if (item.name == "草稿") {
    					this.emptyText = "您的草稿箱是空的";
    					this.productStatus = 3;
    				} else if (item.name == "已下架") {
    					this.emptyText = "您还没有下架过商品哟";
    					this.productStatus = 2;
    				}
    				this.listProductVo();
    			},
    			/**
    			 * 获取商品
    			 */
    			listProductVo() {
    				listProductVo({
    					userId: uni.getStorageSync("curUser").userId,
    					status: this.productStatus
    				}, this.page).then(res => {
    					console.log("listProductVo:" + JSON.stringify(res))
    					this.productVoList = res.data.pageMes.rows;
    				})
    			},
    			/**
    			 * 查看商品的详情
    			 */
    			seeProductDetail(productVo) {
    				uni.navigateTo({
    					url: "/pages/product/detail?productVo=" + encodeURIComponent(JSON.stringify(productVo))
    				})
    			},
    			/**
    			 * 格式化日期
    			 * @param {Object} date
    			 */
    			formatDateToString(dateStr) {
    				let date = new Date(dateStr);
    				// 今天的日期
    				let curDate = new Date();
    				if (date.getFullYear() == curDate.getFullYear() && date.getMonth() == curDate.getMonth() && date
    					.getDate() == curDate.getDate()) {
    					// 如果和今天的年月日都一样,那就只显示时间
    					return this.toDoubleNum(date.getHours()) + ":" + this.toDoubleNum(date.getMinutes());
    				} else {
    					// 如果年份一样,就只显示月日
    					return (curDate.getFullYear() == date.getFullYear() ? "" : (date.getFullYear() + "-")) + this
    						.toDoubleNum((
    							date
    							.getMonth() + 1)) +
    						"-" +
    						this.toDoubleNum(date.getDate());
    				}
    			},
    			/**
    			 * 如果传入的数字是两位数,直接返回;
    			 * 否则前面拼接一个0
    			
    			 * @param {Object} num
    			 */
    			toDoubleNum(num) {
    				if (num >= 10) {
    					return num;
    				} else {
    					return "0" + num;
    				}
    			},
    			/**
    			 * 编辑商品
    			 */
    			editProduct(productVo) {
    				uni.navigateTo({
    					url: "/pages/sellMyProduct/sellMyProduct?productVo=" + encodeURIComponent(JSON.stringify(
    						productVo))
    				})
    			},
    			/**
    			 * 下架商品
    
    			 * @param {Object} productId
    			 */
    			offShelf(productId) {
    				let product = {
    					id: productId,
    					status: 2
    				};
    				updateProduct(product).then(res => {
    					this.$refs.uToast.show({
    						type: 'success',
    						message: "下架成功",
    						duration: 500
    					});
    					this.listProductVo();
    				})
    			},
    			/**
    			 * 上架商品
    
    			 * @param {Object} productId
    			 */
    			onShelf(productId) {
    				let product = {
    					id: productId,
    					status: 0
    				};
    				updateProduct(product).then(res => {
    					this.$refs.uToast.show({
    						type: 'success',
    						message: "上架成功",
    						duration: 500
    					});
    					this.listProductVo();
    				})
    			},
    			/**
    			 * 跳转回来所执行的方法
    			 */
    			back() {
    				// 重新获取一遍数据
    				this.listProductVo();
    			}
    		}
    	}
    script>
    
    <style lang="scss">
    	.outside {
    		// background-color: #0093E9;
    		// background-image: linear-gradient(160deg, #0093E9 0%, #80D0C7 100%);
    
    		font-family: sans-serif;
    	}
    
    	.container {
    		padding: 25rpx;
    
    		.item {
    			background: rgba(255, 255, 255, 1.0);
    			border-radius: 5px;
    			box-shadow: 10rpx 10rpx 20rpx rgba(234, 235, 236, 1.0),
    				inset 1rpx 1rpx 1rpx rgba(234, 235, 236, 0.7);
    			padding: 30rpx;
    			margin-bottom: 30rpx;
    
    			.productItem {
    				display: flex;
    
    				.productMessage {
    					display: flex;
    					flex-direction: column;
    					justify-content: space-between;
    
    					.productTitle {
    						font-weight: 500;
    						margin-bottom: 10rpx;
    						// color: #ffffff;
    					}
    
    					.price {
    						color: #F84442;
    						// font-weight: bold;
    
    						.number {
    							font-size: 20px;
    						}
    					}
    				}
    
    			}
    
    			.buttonView {
    				padding: 10rpx 20rpx;
    				color: #B6B6B6;
    				border-radius: 10px;
    				// border: #B6B6B6 solid 1px;
    				font-size: 24rpx;
    				font-weight: bold;
    			}
    		}
    
    	}
    style>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74
    • 75
    • 76
    • 77
    • 78
    • 79
    • 80
    • 81
    • 82
    • 83
    • 84
    • 85
    • 86
    • 87
    • 88
    • 89
    • 90
    • 91
    • 92
    • 93
    • 94
    • 95
    • 96
    • 97
    • 98
    • 99
    • 100
    • 101
    • 102
    • 103
    • 104
    • 105
    • 106
    • 107
    • 108
    • 109
    • 110
    • 111
    • 112
    • 113
    • 114
    • 115
    • 116
    • 117
    • 118
    • 119
    • 120
    • 121
    • 122
    • 123
    • 124
    • 125
    • 126
    • 127
    • 128
    • 129
    • 130
    • 131
    • 132
    • 133
    • 134
    • 135
    • 136
    • 137
    • 138
    • 139
    • 140
    • 141
    • 142
    • 143
    • 144
    • 145
    • 146
    • 147
    • 148
    • 149
    • 150
    • 151
    • 152
    • 153
    • 154
    • 155
    • 156
    • 157
    • 158
    • 159
    • 160
    • 161
    • 162
    • 163
    • 164
    • 165
    • 166
    • 167
    • 168
    • 169
    • 170
    • 171
    • 172
    • 173
    • 174
    • 175
    • 176
    • 177
    • 178
    • 179
    • 180
    • 181
    • 182
    • 183
    • 184
    • 185
    • 186
    • 187
    • 188
    • 189
    • 190
    • 191
    • 192
    • 193
    • 194
    • 195
    • 196
    • 197
    • 198
    • 199
    • 200
    • 201
    • 202
    • 203
    • 204
    • 205
    • 206
    • 207
    • 208
    • 209
    • 210
    • 211
    • 212
    • 213
    • 214
    • 215
    • 216
    • 217
    • 218
    • 219
    • 220
    • 221
    • 222
    • 223
    • 224
    • 225
    • 226
    • 227
    • 228
    • 229
    • 230
    • 231
    • 232
    • 233
    • 234
    • 235
    • 236
    • 237
    • 238
    • 239
    • 240
    • 241
    • 242
    • 243
    • 244
    • 245
    • 246
    • 247
    • 248
    • 249
    • 250
    • 251
    • 252
    • 253
    • 254
    • 255
    • 256
    • 257
    • 258
    • 259
    • 260
    • 261
    • 262
    • 263
    • 264

    back方法

    这里写了一个back方法,但是这个页面却没有调用过该方法,写这个方法是何用意呢?其实,这个方法是给其他页面调用的。当用户修改商品时,会跳转到商品编辑发布的页面(即sellMyProduct页面),当商品信息修改结束之后,执行uni.navigateBack();返回到上一个页面,这时可以先执行相应页面的back方法再进行跳转。这样开发的优点是:跳转到sellMyProduct页面的前置页面不只有一个,如果指定跳转页面的话,需要写一些判断逻辑来判断要跳转到哪个页面,同时还需要传参来告诉所跳转到的页面要执行什么样的逻辑。而如果使用了back方法,可以将方法的实现交给页面本身,如果页面不需要执行逻辑,则直接将方法留空,调用者不需要管back如何实现,只需要调用即可,这样更加方便代码的维护和拓展。调用者的具体代码如下:

    // 获取上一页
    let pages = getCurrentPages();
    let prevPage = pages[pages.length - 2];
    // 调用上一页的返回方法
    prevPage.$vm.back();
    uni.navigateBack();
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    编辑商品、商品发布、保存草稿

    后端

    后端没有什么特殊的地方,只需要区分一下商品发布和草稿保存的校验过程即可

    商品校验方法

    package com.shm.dataValidate;
    
    import com.ruoyi.common.core.domain.entity.Product;
    import com.ruoyi.common.enums.ErrorCode;
    import com.ruoyi.common.exception.ServiceException;
    import com.ruoyi.common.utils.StringUtils;
    
    import java.math.BigDecimal;
    
    /**
     * @Author dam
     * @create 2023/9/2 17:14
     */
    public class ProductValidate {
        public static void validate(Product product) {
            if (StringUtils.isEmpty(product.getName())) {
                throw new ServiceException("请填写商品名称", ErrorCode.OPERATION_ERROR.getCode());
            } else if (StringUtils.isEmpty(product.getDescription())) {
                throw new ServiceException("请填写商品描述", ErrorCode.OPERATION_ERROR.getCode());
            } else if (product.getOriginalPrice() == null) {
                throw new ServiceException("请填写商品原价", ErrorCode.OPERATION_ERROR.getCode());
            } else if (product.getPrice() == null) {
                throw new ServiceException("请填写商品现价", ErrorCode.OPERATION_ERROR.getCode());
            } else if (product.getProductCategoryId() == null) {
                throw new ServiceException("请选择商品分类", ErrorCode.OPERATION_ERROR.getCode());
            } else if (product.getFineness() == null) {
                throw new ServiceException("请选择商品成色", ErrorCode.OPERATION_ERROR.getCode());
            } else if (product.getNumber() == null) {
                throw new ServiceException("请填写商品数量", ErrorCode.OPERATION_ERROR.getCode());
            } else if (StringUtils.isEmpty(product.getUnit())) {
                throw new ServiceException("请填写商品单位", ErrorCode.OPERATION_ERROR.getCode());
            } else if (product.getFunctionalStatus() == null) {
                throw new ServiceException("请选择商品功能状态", ErrorCode.OPERATION_ERROR.getCode());
            }
    
            if (product.getPrice().compareTo(product.getOriginalPrice()) == 1) {
                throw new ServiceException("商品的销售价格比原价高,请重新填写", ErrorCode.OPERATION_ERROR.getCode());
            }
            if (!validateNumber(product.getPrice())) {
                throw new ServiceException("商品出售价格输入有误,需要是正数且只有两位小数", ErrorCode.OPERATION_ERROR.getCode());
            }
            if (!validateNumber(product.getOriginalPrice())) {
                throw new ServiceException("商品原价输入有误,需要是正数且只有两位小数", ErrorCode.OPERATION_ERROR.getCode());
            }
        }
    
        /**
         * 校验价格是否符合要求
         * 正数
         * 小数点后面最多只有两位小数
         * @param number
         * @return
         */
        private static boolean validateNumber(BigDecimal number) {
            // 判断是否为正数
            if (number.compareTo(BigDecimal.ZERO) <= 0) {
                return false;
            }
    
            // 判断小数位数是否超过两位
            BigDecimal fractionalPart = number.remainder(BigDecimal.ONE);
            if (fractionalPart.scale() > 2) {
                return false;
            }
    
            return true;
        }
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69

    Controller

    /**
     * 上传商品
     */
    @PreAuthorize("@ss.hasPermi('market:product:add')")
    @Log(title = "商品", businessType = BusinessType.INSERT)
    @PostMapping("/uploadSellProduct")
    // 因为操作了多个数据表,添加事务注解,要么都成功,要么都失败
    @Transactional
    public AjaxResult uploadSellProduct(@RequestBody ProductVo productVo) {
        /// 存储商品
        Product product = new Product();
        BeanUtils.copyProperties(productVo, product);
    
        if (product.getStatus() == 0) {
            //--if-- 如果是要发布商品,要先进行数据校验,确保商品的数据都是合法的
            ProductValidate.validate(product);
            if (product.getId() == null) {
                // 设置商品主人
                product.setUserId(getLoginUser().getUserId());
                productService.insertProduct(product);
            } else {
                // 更新商品信息
                productService.updateProduct(product);
            }
    
            if (productVo.getPicList() == null || productVo.getPicList().size() == 0) {
                throw new ServiceException("商品没有上传对应的图片", ErrorCode.OPERATION_ERROR.getCode());
            }
        } else if (product.getStatus() == 3) {
            if (StringUtils.isEmpty(product.getName())) {
                throw new ServiceException("保存草稿时,商品名称不能为空", ErrorCode.OPERATION_ERROR.getCode());
            }
    
            //--if-- 如果只是保存草稿,不需要进行数据校验
            if (product.getId() == null) {
                // 设置商品主人
                product.setUserId(getLoginUser().getUserId());
                productService.insertProduct(product);
            } else {
                // 更新商品信息
                productService.updateProduct(product);
            }
        }
    
        /// 存储图片
        if (product.getId() != null) {
            // 先将商品绑定的图片删除
            pictureService.deletePicturesByItem(product.getId(), 0);
        }
        for (Picture picture : productVo.getPicList()) {
            picture.setItemId(product.getId());
            picture.setType(0);
        }
        if (productVo.getPicList().size() > 0) {
            pictureService.insertPictures(productVo.getPicList());
        }
    
        return AjaxResult.success();
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59

    页面整体代码

    该页面已经在【UniApp开发小程序】悬浮按钮+出售闲置商品+商品分类选择【后端基于若依管理系统开发】文章中进行了介绍,这里主要做一些微小的调整

    <template>
    	<view class="container">
    		<u-toast ref="uToast">u-toast>
    		<view class="content">
    			<view class="item">
    				<view class="labelName">商品名称view>
    				<u--input placeholder="请输入商品名称" border="surround" v-model="product.name">u--input>
    			view>
    			<u-divider text="商品描述和外观">u-divider>
    			
    			<u--textarea v-model="product.description" placeholder="请输入商品描述" height="150">u--textarea>
    			
    			<view>
    				<imageUpload v-model="picList" maxCount="9">imageUpload>
    			view>
    
    			<u-divider text="分类选择/自定义标签">u-divider>
    			
    			<view class="item">
    				<view class="labelName">分类view>
    				<view class="selectTextClass" @click="selectCategory">
    					{{product.productCategoryName?product.productCategoryName:"请选择分类"}}
    				view>
    			view>
    			
    			<view class="item">
    				<view class="labelName">成色view>
    				<view class="columnClass">
    					<view :class="product.fineness==index?'selectTextClass':'textClass'"
    						v-for="(finessName,index) in finenessList" :key="index" @click="changeFineness(index)">
    						{{finessName}}
    					view>
    				view>
    			view>
    			<view class="item">
    				<view class="labelName">功能状态view>
    				<view class="columnClass">
    					<view :class="product.functionalStatus==index?'selectTextClass':'textClass'"
    						v-for="(functionName,index) in functionList" :key="index"
    						@click="changeFunctionalStatus(index)">{{functionName}}
    					view>
    				view>
    			view>
    			<u-row customStyle="margin-bottom: 10px">
    				<u-col span="5">
    					<view class="item">
    						<view class="labelName">数量view>
    						<u--input placeholder="请输入商品数量" border="surround" v-model="product.number">u--input>
    					view>
    				u-col>
    				<u-col span="7">
    					<view class="item">
    						<view class="labelName">计量单位view>
    						<u--input placeholder="请输入计量单位" border="surround" v-model="product.unit">u--input>
    					view>
    				u-col>
    			u-row>
    
    			
    			<u-divider text="价格">u-divider>
    			<u-row customStyle="margin-bottom: 10px">
    				<u-col span="6">
    					<view class="item">
    						<view class="labelName">原价view>
    						<u-input placeholder="请输入原价" border="surround" v-model="product.originalPrice" color="#ff0000"
    							@blur="originalPriceChange">
    							<u--text text="¥" slot="prefix" margin="0 3px 0 0" type="error">u--text>
    						u-input>
    					view>
    				u-col>
    				<u-col span="6">
    					<view class="item">
    						<view class="labelName">出售价格view>
    						<u-input placeholder="请输入出售价格" border="surround" v-model="product.price" color="#ff0000"
    							@blur="priceChange">
    							<u--text text="¥" slot="prefix" margin="0 3px 0 0" type="error">u--text>
    						u-input>
    					view>
    				u-col>
    			u-row>
    
    			<view style="display: flex;margin: 0rpx 60rpx;">
    				<view style="background:#A9A9A9 ;" class="buttonView" @click="saveDraft">存 草 稿view>
    				<view style="width: 40rpx;">view>
    				<view style="background:#3C9CFF ;" class="buttonView" @click="uploadSellProduct">发 布view>
    			view>
    
    		view>
    	view>
    template>
    
    <script>
    	import imageUpload from "@/components/ImageUpload/ImageUpload.vue";
    	import {
    		uploadSellProduct
    	} from "@/api/market/product.js"
    	export default {
    		components: {
    			imageUpload
    		},
    		onShow: function() {
    			let categoryNameList = uni.getStorageSync("categoryNameList");
    			if (categoryNameList) {
    				this.categoryNameList = categoryNameList;
    				this.product.productCategoryId = uni.getStorageSync("productCategoryId");
    				this.product.productCategoryName = categoryNameList[categoryNameList.length - 1];
    				uni.removeStorageSync("categoryNameList");
    				uni.removeStorageSync("productCategoryId");
    			}
    		},
    		data() {
    			return {
    				product: {
    					id: undefined,
    					name: '',
    					descripption: '',
    					picList: [],
    					productCategoryId: undefined,
    					productCategoryName: undefined,
    					number: 1,
    					unit: '个',
    					isContribute: 0,
    					originalPrice: 0.00,
    					price: 0.00,
    					// 成色
    					fineness: 0,
    					// 功能状态
    					functionalStatus: 0,
    					brandId: 0
    				},
    				value: 'dasdas',
    				categoryNameList: ["选择分类"],
    				finenessList: ["全新", "几乎全新", "轻微使用痕迹", "明显使用痕迹", "外观破损"],
    				functionList: ["功能完好无维修", "维修过,可正常使用", "有小问题,不影响使用", "无法正常使用"],
    				picList: [],
    			}
    		},
    		onLoad(e) {
    			if (e.productVo) {
    				// 路由中携带了产品信息,说明是要修改产品信息
    				this.product = JSON.parse(decodeURIComponent(e.productVo));
    				for (var i = 0; i < this.product.picList.length; i++) {
    					this.picList.push(this.product.picList[i].address);
    				}
    				console.log("this.product:" + JSON.stringify(this.product));
    				console.log("this.picList:" + JSON.stringify(this.picList));
    			}
    		},
    		methods: {
    			getCategoryLayerName() {
    				let str = '';
    				// for (let i = 0; i < this.categoryNameList.length - 1; i++) {
    				// 	str += this.categoryNameList[i] + '/';
    				// }
    				return str + this.categoryNameList[this.categoryNameList.length - 1];
    			},
    			/**
    			 * 价格校验
    			 * @param {Object} price 价格
    			 */
    			priceVerify(price) {
    				if (isNaN(price)) {
    					this.$refs.uToast.show({
    						type: 'error',
    						message: "输入的价格不是数字,请重新输入"
    					})
    					return false;
    				}
    				if (price < 0) {
    
    					this.$refs.uToast.show({
    						type: 'error',
    						message: "输入的价格不能为负数,请重新输入"
    					})
    					return false;
    				}
    				if (price.toString().indexOf('.') !== -1 && price.toString().split('.')[1].length > 2) {
    					this.$refs.uToast.show({
    						type: 'error',
    						message: "输入的价格小数点后最多只有两位数字,请重新输入"
    					})
    					return false;
    				}
    				return true;
    			},
    			originalPriceChange() {
    				let haha = this.priceVerify(this.product.originalPrice);
    				if (haha === false) {
    					console.log("haha:" + haha);
    					this.product.originalPrice = 0.00;
    					console.log("this.product" + JSON.stringify(this.product));
    				}
    			},
    			priceChange() {
    				if (this.priceVerify(this.product.price) === false) {
    					this.product.price = 0.00;
    				}
    			},
    			/**
    			 * 修改成色
    			 * @param {Object} index
    			 */
    			changeFineness(index) {
    				this.product.fineness = index;
    			},
    			/**
    			 * 修改功能状态
    			 * @param {Object} index
    			 */
    			changeFunctionalStatus(index) {
    				this.product.functionalStatus = index;
    			},
    			/**
    			 * 上传闲置商品
    			 */
    			uploadSellProduct() {
    				// console.log("上传闲置商品picList:" + JSON.stringify(this.picList));
    				if (this.product.productCategoryId) {
    					if (this.picList.length == 0) {
    						this.$refs.uToast.show({
    							type: 'error',
    							message: "商品图片没有上传成功"
    						})
    					} else {
    						this.setPicAspectRatio().then(() => {
    							// console.log("即将上传的商品:" + JSON.stringify(this.product));
    							this.product.status = 0;
    							uploadSellProduct(this.product).then(res => {
    								if (!this.product.id) {
    									this.$refs.uToast.show({
    										type: 'success',
    										message: "您的商品已经发布到平台"
    									})
    								} else {
    									this.$refs.uToast.show({
    										type: 'success',
    										message: "您的商品修改并发布成功"
    									})
    								}
    								setTimeout(() => {
    									// 获取上一页
    									let pages = getCurrentPages();
    									let prevPage = pages[pages.length - 2];
    									// 调用上一页的返回方法
    									prevPage.$vm.back();
    									uni.navigateBack();
    								}, 500)
    							}).catch(error => {
    								console.log("error:" + JSON.stringify(error));
    								this.$refs.uToast.show({
    									type: 'error',
    									message: "商品发布失败"
    								})
    							});
    						});
    
    					}
    				} else {
    					this.$refs.uToast.show({
    						type: 'error',
    						message: "请选择分类"
    					})
    				}
    			},
    			/**
    			 * 保存商品草稿
    			 */
    			saveDraft() {
    				this.setPicAspectRatio().then(() => {
    					// console.log("即将上传的商品:" + JSON.stringify(this.product));
    					this.product.status = 3;
    					uploadSellProduct(this.product).then(res => {
    						this.$refs.uToast.show({
    							type: 'success',
    							message: "您的草稿保存成功"
    						})
    						setTimeout(() => {
    							// 获取上一页
    							let pages = getCurrentPages();
    							let prevPage = pages[pages.length - 2];
    							// 调用上一页的返回方法
    							prevPage.$vm.back();
    							uni.navigateBack();
    						}, 500)
    					}).catch(error => {
    						// console.log("error:" + JSON.stringify(error));
    						this.$refs.uToast.show({
    							type: 'error',
    							message: "草稿保存失败"
    						})
    					});
    				});
    
    			},
    
    			/**
    			 * 设置图片的宽高比
    			 */
    			setPicAspectRatio() {
    				return new Promise((resolve, reject) => {
    					this.product.picList = [];
    					let promises = [];
    					for (let i = 0; i < this.picList.length; i++) {
    						let picUrl = this.picList[i];
    						promises.push(this.getAspectRatio(picUrl).then((res) => {
    							let pic = {
    								address: picUrl,
    								aspectRatio: res
    							}
    							this.product.picList.push(pic);
    							console.log("当前图片高宽比设置完成");
    						}))
    					}
    					Promise.all(promises).then(() => {
    						console.log("所有图片高宽比设置完成,this.product.picList:" + JSON.stringify(this.product
    							.picList));
    						resolve();
    					})
    				})
    			},
    			/**
    			 * 获取单个图片的高宽比
    
    			 * @param {Object} url
    			 */
    			getAspectRatio(url) {
    				return new Promise((resolve, reject) => {
    					uni.getImageInfo({
    						src: url,
    						success: function(res) {
    							let aspectRatio = res.height / res.width;
    							resolve(aspectRatio);
    						}
    					});
    				})
    			},
    
    			/**
    			 * 选择分类
    			 */
    			selectCategory() {
    				uni.navigateTo({
    					url: "/pages/sellMyProduct/selectCategory"
    				})
    			}
    		}
    	}
    script>
    
    <style lang="scss">
    	.container {
    		background: #F6F6F6;
    		min-height: 100vh;
    		padding: 20rpx;
    		font-family: sans-serif;
    
    		.content {
    			background: #ffffff;
    			padding: 20rpx;
    
    
    			.item {
    				display: flex;
    				align-items: center;
    				height: 50px;
    				margin-bottom: 5px;
    
    				.labelName {
    					width: 70px;
    					margin-right: 10px;
    				}
    
    				.textClass {
    					display: inline;
    					background: #F7F7F7;
    					padding: 15rpx;
    					margin-right: 15px;
    					border-radius: 5px;
    				}
    
    				.selectTextClass {
    					display: inline;
    					background: #2B92FF;
    					padding: 15rpx;
    					margin-right: 15px;
    					border-radius: 5px;
    					color: #ffffff;
    					// font-weight: bold;
    				}
    
    				.columnClass {
    					// height: 50px;
    					display: flex;
    					align-items: center;
    
    					width: calc(100% - 70px);
    					overflow-x: auto;
    					// // 让内容只有一行
    					white-space: nowrap;
    				}
    
    				.columnClass::-webkit-scrollbar {
    					background-color: transparent;
    					/* 设置滚动条背景颜色 */
    					// width: 0px;
    					height: 0px;
    				}
    
    			}
    
    			.buttonView {
    				padding: 20rpx;
    				flex: 1;
    				text-align: center;
    				border-radius: 10rpx;
    				color: #ffffff;
    				font-weight: bold;
    			}
    
    		}
    	}
    style>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74
    • 75
    • 76
    • 77
    • 78
    • 79
    • 80
    • 81
    • 82
    • 83
    • 84
    • 85
    • 86
    • 87
    • 88
    • 89
    • 90
    • 91
    • 92
    • 93
    • 94
    • 95
    • 96
    • 97
    • 98
    • 99
    • 100
    • 101
    • 102
    • 103
    • 104
    • 105
    • 106
    • 107
    • 108
    • 109
    • 110
    • 111
    • 112
    • 113
    • 114
    • 115
    • 116
    • 117
    • 118
    • 119
    • 120
    • 121
    • 122
    • 123
    • 124
    • 125
    • 126
    • 127
    • 128
    • 129
    • 130
    • 131
    • 132
    • 133
    • 134
    • 135
    • 136
    • 137
    • 138
    • 139
    • 140
    • 141
    • 142
    • 143
    • 144
    • 145
    • 146
    • 147
    • 148
    • 149
    • 150
    • 151
    • 152
    • 153
    • 154
    • 155
    • 156
    • 157
    • 158
    • 159
    • 160
    • 161
    • 162
    • 163
    • 164
    • 165
    • 166
    • 167
    • 168
    • 169
    • 170
    • 171
    • 172
    • 173
    • 174
    • 175
    • 176
    • 177
    • 178
    • 179
    • 180
    • 181
    • 182
    • 183
    • 184
    • 185
    • 186
    • 187
    • 188
    • 189
    • 190
    • 191
    • 192
    • 193
    • 194
    • 195
    • 196
    • 197
    • 198
    • 199
    • 200
    • 201
    • 202
    • 203
    • 204
    • 205
    • 206
    • 207
    • 208
    • 209
    • 210
    • 211
    • 212
    • 213
    • 214
    • 215
    • 216
    • 217
    • 218
    • 219
    • 220
    • 221
    • 222
    • 223
    • 224
    • 225
    • 226
    • 227
    • 228
    • 229
    • 230
    • 231
    • 232
    • 233
    • 234
    • 235
    • 236
    • 237
    • 238
    • 239
    • 240
    • 241
    • 242
    • 243
    • 244
    • 245
    • 246
    • 247
    • 248
    • 249
    • 250
    • 251
    • 252
    • 253
    • 254
    • 255
    • 256
    • 257
    • 258
    • 259
    • 260
    • 261
    • 262
    • 263
    • 264
    • 265
    • 266
    • 267
    • 268
    • 269
    • 270
    • 271
    • 272
    • 273
    • 274
    • 275
    • 276
    • 277
    • 278
    • 279
    • 280
    • 281
    • 282
    • 283
    • 284
    • 285
    • 286
    • 287
    • 288
    • 289
    • 290
    • 291
    • 292
    • 293
    • 294
    • 295
    • 296
    • 297
    • 298
    • 299
    • 300
    • 301
    • 302
    • 303
    • 304
    • 305
    • 306
    • 307
    • 308
    • 309
    • 310
    • 311
    • 312
    • 313
    • 314
    • 315
    • 316
    • 317
    • 318
    • 319
    • 320
    • 321
    • 322
    • 323
    • 324
    • 325
    • 326
    • 327
    • 328
    • 329
    • 330
    • 331
    • 332
    • 333
    • 334
    • 335
    • 336
    • 337
    • 338
    • 339
    • 340
    • 341
    • 342
    • 343
    • 344
    • 345
    • 346
    • 347
    • 348
    • 349
    • 350
    • 351
    • 352
    • 353
    • 354
    • 355
    • 356
    • 357
    • 358
    • 359
    • 360
    • 361
    • 362
    • 363
    • 364
    • 365
    • 366
    • 367
    • 368
    • 369
    • 370
    • 371
    • 372
    • 373
    • 374
    • 375
    • 376
    • 377
    • 378
    • 379
    • 380
    • 381
    • 382
    • 383
    • 384
    • 385
    • 386
    • 387
    • 388
    • 389
    • 390
    • 391
    • 392
    • 393
    • 394
    • 395
    • 396
    • 397
    • 398
    • 399
    • 400
    • 401
    • 402
    • 403
    • 404
    • 405
    • 406
    • 407
    • 408
    • 409
    • 410
    • 411
    • 412
    • 413
    • 414
    • 415
    • 416
    • 417
    • 418
    • 419
    • 420
    • 421
    • 422

    同项目其他文章

    该项目的其他文章请查看【易售小程序项目】项目介绍、小程序页面展示与系列文章集合

  • 相关阅读:
    第三章:人工智能深度学习教程-人工智能与机器学习与深度学习之间的区别
    C语言实验十五 文件
    GPT-4并非世界模型,LeCun双手赞同!ACL力证LLM无法模拟真实世界
    工程可以编译通过,但是Vscode依然有波浪线提示
    独自一人开发一整套 ERP 系统是什么水平?
    Web服务器
    MySQL备份与恢复
    【数据结构】二叉树的前中后序遍历
    LEETCODE力扣详解:7.整数反转;9.回文数
    windows下使用pytorch进行单机多卡分布式训练
  • 原文地址:https://blog.csdn.net/laodanqiu/article/details/132638934