十七、商品添加

article/2025/9/18 10:22:00

(1)通过编程式导航跳转到商品添加页面

1. 在List.vue页面。点击添加商品,实现页面跳转

2. 创建商品添加组件Add.vue

3. 为Add组件添加路由

               

(2) 渲染添加页面的基本UI结构

使用到Alter警告和Steps 步骤条组件

1. 引入组件

2. add组件的基本UI结构

(3)美化步骤条组件

1. 增加进度,并修改文字

2. css样式

(4)渲染tab栏区域

(5)实现步骤条和tab栏的数据联动效果

通过让进度条和tab标签共用activeIndex的值,实现联动效果:

1. 当选择商品参数时,v-model绑定该选项对应的name值1,

2. 从而修改activeIndex的值为1

3. 进而使进度条当前所在的进度转到下标为1的项:商品参数

注意:  v-model 绑定的是当前选中项的name值;

             active 绑定的是当前进度的下标值

                

(6)绘制“基本信息”面板的UI结构

补充:在el-form标签中,添加下面属性,使输入框标题和输入框分行显示

(7)获取商品分类的数据

(8)绘制商品分类的级联选择器

1. 创建级联选择器

2. 相关的数据

3. 方法

         

(9)只允许选中三级分类

(10)阻止页签切换

1. 首先为tabs标签页添加属性before-leave,其值为一个事件函数。

  1.1 该函数有两个参数(activeName将要跳转的标签项name,oldActiveName现在的标签项name)。

  1.2 若该事件函数的返回值为false,则阻止跳转到下一个标签项

2. 在事件函数中,

如果当前页的name为0(在“基本信息”标签项)并且 选中项id的数组长度不等于3,则禁止跳转,返回fals

目的:实现只有选中三级分类后,才可跳转

(11)获取动态参数列表数据(当点击商品参数页签时)

1. 为tabs页签添加点击事件,选择页签时触发该方法

2. 在该方法中,判断当前所在的页签是不是商品参数。

3. 如果是,则进行数据请求,获取动态参数列表

4. 为了便于获取当前选中分类的id,定义计算属性cateId

点击商品参数时,获取到的数据为:

(12)绘制商品参数面板中的复选框组

1. 引入复选框组件

2. 首先在获取动态参数列表的方法中,先将每个参数所对应的标签字符串attr_vals 转化为 数组

3. 通过第一个for循环,依次显示每一个参数名

4. 再通过嵌套的第二个for循环,以复选框的形式,依次显示当前参数对应的所有标签

补充:优化复选框的样式,使复选框开头对齐

(13)获取静态属性列表数据

(14)渲染商品属性面板的UI结构

(15)初步使用upload上传组件

1. 实现以下功能:

1.1 点击上传,选择本地图片进行上传

                         

1.2 上传成功后,显示:(也可以点击右上角的x,进行移除)

1.3 点击上传的图片,进行预览

2. 用到upload上传组件,引入该组件 

3. 使用upload上传组件

效果图:

(16)手动为upload绑定headers请求头

问题:在Network中显示是无效的ttoken。

         说明上传图片时没有使用axios发送请求,而是使用其内部的封装的一套ajax。其内部封装的ajax没有Authorization字段。

解决:通过headers为其指定Authorization字段

(17)监听upload组件的on-success事件(上传成功事件)

1. API文档中相关的信息

2. 为upload组件添加on-success(上传成功时,触发该方法)

3. 上传成功后,返回的数据中有图片的临时路径。将该路径保存到pics数组中

上传成功后返回的数据:

上传图片临时路径的pics数组:

(18)监听upload上传组件的on-remove事件(删除图片)

删除图片时,会返回数据:

(19)实现图片的预览效果

1. 监听图片的预览事件on-preview

2. 点击图片时,触发预览事件,该事件会传入数据。

3. 将数据中url(图片地址)赋值给变量previewPath,并且显示对话框(对话框中存放图片)

4. 使用对话框组件,显示图片预览。内容部分放当前点击的图片

(20)安装并配置vue-quill-editor(富文本编辑器)

1. 安装插件vue-quill-editor

2. 导入该插件(富文本编辑器),并全局注册

// 导入富文本编辑器对应的样式
import 'quill/dist/quill.core.css'
import 'quill/dist/quill.snow.css'
import 'quill/dist/quill.bubble.css'// 3.将富文本编辑器注册为全局可用的组件
Vue.use(VueQuillEditor)

3. 使用富文本编辑器

在全局css文件中

4. 添加商品按钮,查看addForm中的商品介绍是否与富文本编辑器输入的内容双向绑定

5. 效果图

  

(21)实现表单数据的预验证

1. 点击添加按钮,通过add方法,对提交的表单数据进行验证

(22)把选中分类的id数组(goods_cat)转化为字符串

          

1. 安装运行依赖lodash,调用方法cloneDeep(要拷贝的对象),实现深拷贝(对赋值的addForm操作,避免与级联选择器中绑定的goods_cat发生冲突)

2. 导入lodash

3. 使用其方法cloneDeep(要拷贝的对象)进行深拷贝,并将拷贝对象中的goods_cat数组转化为字符串

将上图中修改为打印form

(23)在add方法中处理attrs数组(商品的参数(包括动态参数和静态属性)

addForm. attrs:表示商品的参数(包括动态参数和静态属性)

1. 首先添加为addForm添加attrs属性

2. 在add方法中,获取动态参数和静态属性的attr_id和attr_value,存到addForm. attrs中

              

(24)完成添加商品的操作

Add.vue

<template><div><!-- 面包屑 导航区 --><el-breadcrumb separator="/"><el-breadcrumb-item :to="{ path: '/home' }">首页</el-breadcrumb-item><el-breadcrumb-item>商品管理</el-breadcrumb-item><el-breadcrumb-item>商品列表</el-breadcrumb-item></el-breadcrumb><!-- 卡片视图区 --><el-card><!-- alert警告 --><el-alerttitle="添加商品信息"type="info"centershow-icon></el-alert><!-- 进度条 --><el-steps :space="200" :active="activeIndex-0" finish-status="success" align-center><el-step title="基本信息"></el-step><el-step title="商品参数"></el-step><el-step title="商品属性"></el-step><el-step title="商品图片"></el-step><el-step title="商品内容"></el-step><el-step title="完成"></el-step></el-steps><!-- tabs标签页区域. 在外面添加表单便于数据的显示注意:tabs和tabs-pane标签之间不能有其它标签,所以将form放在最外面--><el-form :model="addForm" :rules="addFormRules" ref="addFormRef" label-width="100px" label-position="top"><el-tabs v-model="activeIndex" :tab-position="'left'" :before-leave="beforeTagLeave" @tab-click="tabClicked"><el-tab-pane label="基本信息" name="0"><el-form-item label="商品名称" prop="goods_name"><el-input v-model="addForm.goods_name"></el-input></el-form-item><el-form-item label="商品价格" prop="goods_price"><el-input v-model="addForm.goods_price" type="number"></el-input></el-form-item><el-form-item label="商品重量" prop="goods_weight"><el-input v-model="addForm.goods_weight" type="number"></el-input></el-form-item><el-form-item label="商品数量" prop="goods_number"><el-input v-model="addForm.goods_number" type="number"></el-input></el-form-item><el-form-item label="商品分类" prop="goods_cat"><el-cascaderexpand-trigger="hover":options="catelist":props="cateProp"v-model="addForm.goods_cat"@change="handleChange"></el-cascader></el-form-item></el-tab-pane><el-tab-pane label="商品参数" name="1"><!-- 通过for循环,显示当前选中分类下的每个参数名item.attr_name --><el-form-item :label="item.attr_name" v-for="item in manyTableData" :key="item.attr_id"><!-- 通过for循环,显示当前参数下所对应的所有取值attr_vals --><el-checkbox-group v-model="item.attr_vals"><el-checkbox :label="cb" v-for="(cb,i) in item.attr_vals" :key="i" border></el-checkbox></el-checkbox-group></el-form-item></el-tab-pane><el-tab-pane label="商品属性" name="2"><el-form-item :label="item.attr_name" v-for="item in onlyTableData" :key="item.attr_id"><el-input v-model="item.attr_vals"></el-input></el-form-item></el-tab-pane><el-tab-pane label="商品图片" name="3"><!-- 1. action:图片要上传到的后台API地址2. on-preview 预览图片操作3. on-remove 移除图片操作4. list-type="picture" 以图片的形式显示--><el-upload:action="uploadUrl":on-preview="handlePreview":on-remove="handleRemove"list-type="picture":headers="headerObj":on-success="handleSuccess"><el-button size="small" type="primary">点击上传</el-button></el-upload></el-tab-pane><el-tab-pane label="商品内容" name="4"><!-- 富文本编辑器组件 --><quill-editor v-model="addForm.goods_introduce"></quill-editor><!-- 添加商品按钮 --><el-button type="primary" class="btnAdd" @click="add">添加商品</el-button></el-tab-pane></el-tabs></el-form></el-card><!-- 图片预览框 --><el-dialogtitle="图片预览":visible.sync="previewVisible"width="50%"><img :src="previewPath" class="previewImg"></el-dialog></div>
</template>
<script>
// 导入lodash,将其命名为_。以进行深拷贝
import _ from 'lodash'
export default {data () {return {// 默认选中进度条第一项(第一项对应0),也是选中tab标签中的name值activeIndex: '0',// 添加商品的数据对象addForm: {goods_name: '',goods_price: 0,goods_weight: 0,goods_number: 0,goods_cat: [], // 添加商品所属的分类数组(存放选中的分类id)pics: [], // 图片临时地址的对象数组goods_introduce: '', // 商品的详情描述attrs: [] // 商品参数(包括动态参数和静态属性的attr_id和attr_value)},// 表单的验证规则addFormRules: {goods_name: [{ required: true, message: '请输入商品名称', trigger: 'blur' }],goods_price: [{ required: true, message: '请输入商品价格', trigger: 'blur' }],goods_weight: [{ required: true, message: '请输入商品重量', trigger: 'blur' }],goods_number: [{ required: true, message: '请输入商品数量', trigger: 'blur' }],goods_cat: [{ required: true, message: '请选中商品分类', trigger: 'blur' }]},// 商品分类列表catelist: [],// 级联选择框的属性配置cateProp: {value: 'cat_id', // 选中的是什么label: 'cat_name', // 看到的是什么children: 'children' // 具有父子关系的数组},// 动态参数列表数据manyTableData: [],// 静态属性列表数据onlyTableData: [],// 图片要上传到的后台API地址(/upload前面的地址为根路径)uploadUrl: 'http://127.0.0.1:8888/api/private/v1/upload',// 图片上传组件的headers请求头对象headerObj: {Authorization: window.sessionStorage.getItem('token')},// 被点击图片的url地址previewPath: '',// 控制图片预览框的显示与隐藏previewVisible: false}},created () {this.getCateList()},methods: {// 1. 获取商品分类数据(以在商品选择中显示)async getCateList() {const { data: res } = await this.$http.get('categories')if (res.meta.status !== 200) {return this.$message.error('获取商品分类数据失败!')}this.catelist = res.dataconsole.log(res.data)},// 2.级联选择器选中项发生变化时,会触发这个函数handleChange() {console.log(this.addForm.goods_cat)// 没有选中三级分类。将存放选中id的数组置空if (this.addForm.goods_cat.length !== 3) {this.addForm.goods_cat = []}},// 3.控制标签页的跳转(只有选中第一个标签页的三级分类后,才可跳转)beforeTagLeave(activeName, oldActiveName) {// 当前在第一个标签页,但是没有选中三级分类if (oldActiveName === '0' && this.addForm.goods_cat.length !== 3) {this.$message.error('请选择商品分类!')return false}},// 4. 点击页签时触发该方法async tabClicked() {// 4.1 选中商品参数页签, 获取动态参数列表数据if (this.activeIndex === '1') {// 发送数据请求const { data: res } = await this.$http.get(`categories/${this.cateId}/attributes`,{ params: { sel: 'many' } })if (res.meta.status !== 200) {return this.$message.error('获取参数列表失败')}// 先将获取的参数列表中每一个参数所对应的标签字符串,转化为 标签数组res.data.forEach(item => {item.attr_vals = item.attr_vals.length === 0 ? [] : item.attr_vals.split(' ')})// 将获取的动态参数列表保存this.manyTableData = res.dataconsole.log(res.data)} else if (this.activeIndex === '2') { // 4.2 选中商品属性页签,获取静态属性列表数据// 发送数据请求const { data: res } = await this.$http.get(`categories/${this.cateId}/attributes`,{ params: { sel: 'only' } })if (res.meta.status !== 200) {return this.$message.error('获取属性列表失败')}// 将获取的属性列表保存this.onlyTableData = res.dataconsole.log(res.data)}},// 5. 处理预览图片效果handlePreview(file) {// 1.获取点击图片的url地址this.previewPath = file.response.data.url// 2.使对话框(图片预览)可见this.previewVisible = true},// 6. 处理移除图片的操作handleRemove(file) {// 6.1 获取将要删除的图片的临时路径const filePath = file.response.data.tmp_path// 6.2 从pics 数组中,找到这个图片对应的索引值(使用foreach依次遍历pics数组,寻找filePath所对应的索引值)const i = this.addForm.pics.forEach(item =>item.pic === filePath)// 6.3 调用数组的splice方法,把图片信息对象,从pics数组中移除this.addForm.pics.splice(i, 1)console.log(this.addForm.pics)},// 7. 监听图片上传成功的事件(response:上传成功后返回的数据,包括图片的临时路径)handleSuccess(response) {// 1.拼接得到一个图片信息对象(图片临时路径)const pinInfo = { pic: response.data.tmp_path }// 2.将获取到的图片对象 加入到 pics数组this.addForm.pics.push(pinInfo)console.log(this.addForm.pics)},// 8.点击添加商品按钮,触发add() {this.$refs.addFormRef.validate(async valid => {// 8.1 预验证未通过if (!valid) {return this.$message.error('请填写必要的表单项')}// 8.2 预验证通过。执行添加的业务逻辑// 8.2.1 首先将选中的分类id数组( goods_cat),转化为字符串// 为了避免与级联选择器中绑定的 goods_cat 产生冲突,对原始的addForm进行深拷贝const form = _.cloneDeep(this.addForm)// 将选中分类id数组,转化为字符串form.goods_cat = form.goods_cat.join(',')// 8.3 获取动态参数数组中每个参数的attr_id和 attr_valuethis.manyTableData.forEach(item => {const newInfo = {attr_id: item.attr_id,attr_value: item.attr_vals.join(' ') // 对应参数的标签是用空格连起来的字符串}this.addForm.attrs.push(newInfo)})// 8.4 获取静态属性数组中每个属性的attr_id和 attr_valuethis.onlyTableData.forEach(item => {const newInfo = {attr_id: item.attr_id,attr_value: item.attr_vals}this.addForm.attrs.push(newInfo)})// 8.5 将获取的addForm的attrs赋值给form的attrsform.attrs = this.addForm.attrsconsole.log(form)// 8.6 发送添加商品请求(注意:商品名称是唯一的)const {data : res} = await this.$http.post('goods',form)if (res.meta.status !== 201) {return this.$message.error('添加商品失败!')}// 8.7 添加商品成功,回到商品列表页面this.$message.success('添加商品成功')this.$router.push('/goods')})}},computed: {// 1.获取当前选中分类的idcateId() {// 选中三级分类,返回三级分类的idif (this.addForm.goods_cat.length === 3) {return this.addForm.goods_cat[2]}// 没有选中return null}}
}
</script>
<style lang="less" scoped>.el-checkbox {margin: 0 10px 0 0 !important;}.previewImg {width: 100%;}/* 为添加商品按钮添加外边距*/.btnAdd {margin-top: 15px;}
</style>

 


http://chatgpt.dhexx.cn/article/TJZwTTZL.shtml

相关文章

(三十)商品管理-添加商品(上传图片)

&#xff08;三十&#xff09;商品管理-添加商品(上传图片) 添加商品(上传图片)1.修改页面上添加连接/store/adminProduct?methodaddUI2.在addUI请求转发到 添加页面3.在表单页面上修改action : /store/addProductServlet提交方式: method"post"添加enctype属性: e…

【VUE项目实战】56、商品添加功能(六)-提交添加的商品

接上篇《55、商品添加功能&#xff08;五&#xff09;-商品内容模块》 上一篇我们完成了商品内容编辑模块的开发&#xff0c;也即是完成了商品所有的信息编辑&#xff0c;本篇我们就来开发提交商品所有信息到后台的功能。 一、要实现的效果 我们要实现点击“添加商品”的按钮…

淘淘商城第30讲——实现商品添加功能

经过上文的学习&#xff0c;我相信大家都应该知道了富文本编辑器的使用方法&#xff0c;我们能走到这步&#xff0c;实属不易&#xff0c;本文终于可以来实现商品添加这个功能了。 在item-add.jsp页面当中&#xff0c;当点击提交按钮后&#xff0c;会触发submitForm方法&#…

密码登录

利用idea实现密码的输入 首先我们要先新建一个页面用于输入账号密码 req.setCharacterEncoding("UTF-8");String LoginNamereq.getParameter("LoginName");String LoginPwdreq.getParameter("LoginPwd");String msg"请输入密码";priva…

SQL Server安全:登录和用户

SQL Server安全&#xff1a;登录和用户 前言 建议配合sql server登录名、服务器角色、数据库用户、数据库角色、架构区别联系一起看。 授予 Principal &#xff08;安全主体&#xff09;操作 Securable&#xff08;安全对象&#xff09; 的 Permission&#xff08;权限&…

springboot-security安全登录

一个简单的security安全登录示例 配置环境 添加pom依赖坐标 <parent><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-parent</artifactId><version>2.1.6.RELEASE</version></parent><depe…

如何设计一个安全的登录接口?

Java技术栈 www.javastack.cn 关注阅读更多优质文章 作者&#xff1a;哒哒哒哒打代码链接&#xff1a;juejin.im/post/6859214952704999438 前言 大家学写程序时&#xff0c;第一行代码都是hello world。 但是当你开始学习WEB后台技术时&#xff0c;很多人的第一个功能就是写的…

[OS-Linux] CentOS 7.x 安全登录策略设置

简介 之前用用户名和密码登陆服务器 这样不安全 &#xff0c;用SSH公钥(public key)验证 这个办法能很好的解决 登陆服务器 和安全登陆服务器的特点&#xff1a; 方法 / 步骤 &#x1f510; 一: 证书生成 命令行页面生成 (推荐) 查看执行结果&#xff0c;这时候连续回车即可…

开启QQ登录保护仍被盗号——QQ安全机制全面分析

1、前言 周围总是有些同学QQ被盗号&#xff0c;攻击者盗取账号后会继续去欺骗列表里的好友&#xff0c;形成链式反应。危害比较大。 腾讯QQ安全中心提供了登录保护机制&#xff0c;如图&#xff1a; 这是腾讯为QQ添加第二层保护&#xff0c;在开启登录保护后&#xff0c;盗号者…

使用 PHP 和 MySQL 的安全登录系统

Secure Login System with PHP and MySQL 在本教程中&#xff0c;我将教您如何创建自己的安全 PHP 登录系统。登录表单是您网站的访问者可以用来登录您的网站以访问受限内容&#xff08;例如个人资料页面&#xff09;的表单。我们将利用 MySQL 从数据库中检索帐户数据。 高级…

使用腾讯企业邮箱为什么强烈建议启用安全登录?怎么启用?

腾讯企业邮箱开启安全登录&#xff0c;简单来说就是把企业邮箱账号和微信绑定。启用安全登录和关闭安全登录&#xff0c;主要是登录方式发生了变化。 登录方式&#xff1a; 登录启用前启用后网页端邮箱帐号密码登录/微信扫码登录仅支持微信扫码登录客户端邮箱帐号密码登录仅…

登录安全----双重MD5加密实现安全登录

个人简介&#xff1a; &#x1f4e6;个人主页&#xff1a;肇事司机赵四 &#x1f3c6;学习方向&#xff1a;JAVA后端开发 &#x1f4e3;种一棵树最好的时间是十年前&#xff0c;其次是现在&#xff01; &#x1f9e1;喜欢的话麻烦点点关注喔&#xff0c;你们的支持是我的最大动…

http登录模块加密登录安全登录方法

http请求很容易被截获&#xff0c;在写登录模块时&#xff0c;直接使用明文密码请求&#xff0c;很容易明文密码泄露&#xff1b;若在js页面对密码进行一次加密后在传输&#xff0c;虽不是明文密码&#xff0c;但也完全可以截获加密后的暗文&#xff0c;伪造http请求进行登录。…

安全登录认证

用户登录是任何一个应用系统的基本功能&#xff0c;特别是对于网上银行系统来说&#xff0c;用户登录的安全性尤为重要。如何设计一个网站的安全登录认证程序&#xff0c;是本文主要讨论的问题。 静态密码存在着比较多的安全隐患&#xff0c;攻击者有很多手段获得静态密码&…

Web登录如何确保安全

1、一个普通简单的HTML例子&#xff0c;用户登录信息是不安全的 <form action "http://localhost:8080/Application/login" method "POST"> 用户名&#xff1a;<input id"username" name"username" type"te…

实现安全登录的两种方法

登录安全——拦截器和过滤器或权限框架的使用 本次我们将采用两种方法实现登录的安全性&#xff0c;首先介绍拦截器和过滤器。 一、 过滤器和拦截器&#xff1a; 过滤器产生的时间/开始工作的时间&#xff1a; 进入Tomcat之后&#xff0c;但是在进servlet之前。Interceptor进入…

推荐几款优秀的搜素引擎

秘迹搜索 网址&#xff1a;https://mijisou.com/ 秘迹搜索是一款守护用户搜索信息的聚合搜索引擎&#xff0c;Ta不会根据搜索关键词追踪用户&#xff0c;也不会通过历史搜索内容做广告推荐。秘迹搜索通过聚合中文搜索服务比如Bing、百度、360、搜狗等搜索结果提供私密搜索服务…

12.推荐几款好用的搜索引擎

1.goobe https://goobe.io/ 专为程序员设计的搜索引擎&#xff08;搜索非技术相关的东西也很6&#xff09;&#xff0c;界面是这样事儿的 而且可以通过快照访问stackoverflow和github&#xff0c;非常好用 无广告&#xff0c;不跟踪 2.萌搜 https://mengso.com/ 号称小众的…

《搜索和推荐中的深度匹配》——1.1搜索和推荐

重磅推荐专栏&#xff1a; 《Transformers自然语言处理系列教程》 手把手带你深入实践Transformers&#xff0c;轻松构建属于自己的NLP智能应用&#xff01; 随着Internet的快速发展&#xff0c;当今信息科学的基本问题之一变得更加重要&#xff0c;即如何从通常庞大的信息库中…

基于Elasticsearch实现搜索推荐

在基于Elasticsearch实现搜索建议一文中我们曾经介绍过如何基于Elasticsearch来实现搜索建议&#xff0c;而本文是在此基于上进一步优化搜索体验&#xff0c;在当搜索无结果或结果过少时提供推荐搜索词给用户。 背景介绍 在根据用户输入和筛选条件进行搜索后&#xff0c;有时…